PCI SCSI HBA emulation.
[qemu] / target-sh4 / op.c
1 /*
2  *  SH4 emulation
3  * 
4  *  Copyright (c) 2005 Samuel Tardieu
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include "exec.h"
21
22 static inline void set_flag(uint32_t flag)
23 {
24     env->flags |= flag;
25 }
26
27 static inline void clr_flag(uint32_t flag)
28 {
29     env->flags &= ~flag;
30 }
31
32 static inline void set_t(void)
33 {
34     env->sr |= SR_T;
35 }
36
37 static inline void clr_t(void)
38 {
39     env->sr &= ~SR_T;
40 }
41
42 static inline void cond_t(int cond)
43 {
44     if (cond)
45         set_t();
46     else
47         clr_t();
48 }
49
50 void OPPROTO op_movl_imm_T0(void)
51 {
52     T0 = (uint32_t) PARAM1;
53     RETURN();
54 }
55
56 void OPPROTO op_movl_imm_T1(void)
57 {
58     T0 = (uint32_t) PARAM1;
59     RETURN();
60 }
61
62 void OPPROTO op_movl_imm_T2(void)
63 {
64     T0 = (uint32_t) PARAM1;
65     RETURN();
66 }
67
68 void OPPROTO op_cmp_eq_imm_T0(void)
69 {
70     cond_t((int32_t) T0 == (int32_t) PARAM1);
71     RETURN();
72 }
73
74 void OPPROTO op_cmd_eq_T0_T1(void)
75 {
76     cond_t(T0 == T1);
77     RETURN();
78 }
79
80 void OPPROTO op_cmd_hs_T0_T1(void)
81 {
82     cond_t((uint32_t) T0 <= (uint32_t) T1);
83     RETURN();
84 }
85
86 void OPPROTO op_cmd_ge_T0_T1(void)
87 {
88     cond_t((int32_t) T0 <= (int32_t) T1);
89     RETURN();
90 }
91
92 void OPPROTO op_cmd_hi_T0_T1(void)
93 {
94     cond_t((uint32_t) T0 < (uint32_t) T1);
95     RETURN();
96 }
97
98 void OPPROTO op_cmd_gt_T0_T1(void)
99 {
100     cond_t((int32_t) T0 < (int32_t) T1);
101     RETURN();
102 }
103
104 void OPPROTO op_not_T0(void)
105 {
106     T0 = ~T0;
107     RETURN();
108 }
109
110 void OPPROTO op_bf_s(void)
111 {
112     T2 = ~env->sr;
113     env->delayed_pc = PARAM1;
114     set_flag(DELAY_SLOT_CONDITIONAL);
115     RETURN();
116 }
117
118 void OPPROTO op_bt_s(void)
119 {
120     T2 = env->sr;
121     env->delayed_pc = PARAM1;
122     set_flag(DELAY_SLOT_CONDITIONAL);
123     RETURN();
124 }
125
126 void OPPROTO op_bra(void)
127 {
128     env->delayed_pc = PARAM1;
129     set_flag(DELAY_SLOT);
130     RETURN();
131 }
132
133 void OPPROTO op_braf_T0(void)
134 {
135     env->delayed_pc = PARAM1 + T0;
136     set_flag(DELAY_SLOT);
137     RETURN();
138 }
139
140 void OPPROTO op_bsr(void)
141 {
142     env->pr = PARAM1;
143     env->delayed_pc = PARAM2;
144     set_flag(DELAY_SLOT);
145     RETURN();
146 }
147
148 void OPPROTO op_bsrf_T0(void)
149 {
150     env->pr = PARAM1;
151     env->delayed_pc = PARAM1 + T0;
152     set_flag(DELAY_SLOT);
153     RETURN();
154 }
155
156 void OPPROTO op_jsr_T0(void)
157 {
158     env->pr = PARAM1;
159     env->delayed_pc = T0;
160     set_flag(DELAY_SLOT);
161     RETURN();
162 }
163
164 void OPPROTO op_rts(void)
165 {
166     env->delayed_pc = env->pr;
167     set_flag(DELAY_SLOT);
168     RETURN();
169 }
170
171 void OPPROTO op_clr_delay_slot(void)
172 {
173     clr_flag(DELAY_SLOT);
174     RETURN();
175 }
176
177 void OPPROTO op_clr_delay_slot_conditional(void)
178 {
179     clr_flag(DELAY_SLOT_CONDITIONAL);
180     RETURN();
181 }
182
183 void OPPROTO op_exit_tb(void)
184 {
185     EXIT_TB();
186     RETURN();
187 }
188
189 void OPPROTO op_addl_imm_T0(void)
190 {
191     T0 += PARAM1;
192     RETURN();
193 }
194
195 void OPPROTO op_addl_imm_T1(void)
196 {
197     T1 += PARAM1;
198     RETURN();
199 }
200
201 void OPPROTO op_clrmac(void)
202 {
203     env->mach = env->macl = 0;
204     RETURN();
205 }
206
207 void OPPROTO op_clrs(void)
208 {
209     env->sr &= ~SR_S;
210     RETURN();
211 }
212
213 void OPPROTO op_clrt(void)
214 {
215     env->sr &= ~SR_T;
216     RETURN();
217 }
218
219 void OPPROTO op_sets(void)
220 {
221     env->sr |= SR_S;
222     RETURN();
223 }
224
225 void OPPROTO op_sett(void)
226 {
227     env->sr |= SR_T;
228     RETURN();
229 }
230
231 void OPPROTO op_rte(void)
232 {
233     env->sr = env->ssr;
234     env->delayed_pc = env->spc;
235     set_flag(DELAY_SLOT);
236     RETURN();
237 }
238
239 void OPPROTO op_swapb_T0(void)
240 {
241     T0 = (T0 & 0xffff0000) | ((T0 & 0xff) << 8) | ((T0 >> 8) & 0xff);
242     RETURN();
243 }
244
245 void OPPROTO op_swapw_T0(void)
246 {
247     T0 = ((T0 & 0xffff) << 16) | ((T0 >> 16) & 0xffff);
248     RETURN();
249 }
250
251 void OPPROTO op_xtrct_T0_T1(void)
252 {
253     T1 = ((T0 & 0xffff) << 16) | ((T1 >> 16) & 0xffff);
254     RETURN();
255 }
256
257 void OPPROTO op_addc_T0_T1(void)
258 {
259     helper_addc_T0_T1();
260     RETURN();
261 }
262
263 void OPPROTO op_addv_T0_T1(void)
264 {
265     helper_addv_T0_T1();
266     RETURN();
267 }
268
269 void OPPROTO op_cmp_eq_T0_T1(void)
270 {
271     cond_t(T1 == T0);
272     RETURN();
273 }
274
275 void OPPROTO op_cmp_ge_T0_T1(void)
276 {
277     cond_t((int32_t) T1 >= (int32_t) T0);
278     RETURN();
279 }
280
281 void OPPROTO op_cmp_gt_T0_T1(void)
282 {
283     cond_t((int32_t) T1 > (int32_t) T0);
284     RETURN();
285 }
286
287 void OPPROTO op_cmp_hi_T0_T1(void)
288 {
289     cond_t((uint32_t) T1 > (uint32_t) T0);
290     RETURN();
291 }
292
293 void OPPROTO op_cmp_hs_T0_T1(void)
294 {
295     cond_t((uint32_t) T1 >= (uint32_t) T0);
296     RETURN();
297 }
298
299 void OPPROTO op_cmp_str_T0_T1(void)
300 {
301     cond_t((T0 & 0x000000ff) == (T1 & 0x000000ff) ||
302            (T0 & 0x0000ff00) == (T1 & 0x0000ff00) ||
303            (T0 & 0x00ff0000) == (T1 & 0x00ff0000) ||
304            (T0 & 0xff000000) == (T1 & 0xff000000));
305     RETURN();
306 }
307
308 void OPPROTO op_tst_T0_T1(void)
309 {
310     cond_t((T1 & T0) == 0);
311     RETURN();
312 }
313
314 void OPPROTO op_div0s_T0_T1(void)
315 {
316     if (T1 & 0x80000000)
317         env->sr |= SR_Q;
318     else
319         env->sr &= ~SR_Q;
320     if (T0 & 0x80000000)
321         env->sr |= SR_M;
322     else
323         env->sr &= ~SR_M;
324     cond_t((T1 ^ T0) & 0x80000000);
325     RETURN();
326 }
327
328 void OPPROTO op_div0u(void)
329 {
330     env->sr &= ~(SR_M | SR_Q | SR_T);
331     RETURN();
332 }
333
334 void OPPROTO op_div1_T0_T1(void)
335 {
336     helper_div1_T0_T1();
337     RETURN();
338 }
339
340 void OPPROTO op_dmulsl_T0_T1(void)
341 {
342     helper_dmulsl_T0_T1();
343     RETURN();
344 }
345
346 void OPPROTO op_dmulul_T0_T1(void)
347 {
348     helper_dmulul_T0_T1();
349     RETURN();
350 }
351
352 void OPPROTO op_macl_T0_T1(void)
353 {
354     helper_macl_T0_T1();
355     RETURN();
356 }
357
358 void OPPROTO op_macw_T0_T1(void)
359 {
360     helper_macw_T0_T1();
361     RETURN();
362 }
363
364 void OPPROTO op_mull_T0_T1(void)
365 {
366     env->macl = (T0 * T1) & 0xffffffff;
367     RETURN();
368 }
369
370 void OPPROTO op_mulsw_T0_T1(void)
371 {
372     env->macl = (int32_t) T0 *(int32_t) T1;
373     RETURN();
374 }
375
376 void OPPROTO op_muluw_T0_T1(void)
377 {
378     env->macl = (uint32_t) T0 *(uint32_t) T1;
379     RETURN();
380 }
381
382 void OPPROTO op_neg_T0(void)
383 {
384     T0 = -T0;
385     RETURN();
386 }
387
388 void OPPROTO op_negc_T0(void)
389 {
390     helper_negc_T0();
391     RETURN();
392 }
393
394 void OPPROTO op_shad_T0_T1(void)
395 {
396     if ((T0 & 0x80000000) == 0)
397         T1 <<= (T0 & 0x1f);
398     else if ((T0 & 0x1f) == 0)
399         T1 = 0;
400     else
401         T1 = ((int32_t) T1) >> ((~T0 & 0x1f) + 1);
402     RETURN();
403 }
404
405 void OPPROTO op_shld_T0_T1(void)
406 {
407     if ((T0 & 0x80000000) == 0)
408         T1 <<= (T0 & 0x1f);
409     else if ((T0 & 0x1f) == 0)
410         T1 = 0;
411     else
412         T1 = ((uint32_t) T1) >> ((~T0 & 0x1f) + 1);
413     RETURN();
414 }
415
416 void OPPROTO op_subc_T0_T1(void)
417 {
418     helper_subc_T0_T1();
419     RETURN();
420 }
421
422 void OPPROTO op_subv_T0_T1(void)
423 {
424     helper_subv_T0_T1();
425     RETURN();
426 }
427
428 void OPPROTO op_trapa(void)
429 {
430     env->tra = PARAM1 * 2;
431     env->exception_index = 0x160;
432     do_raise_exception();
433     RETURN();
434 }
435
436 void OPPROTO op_cmp_pl_T0(void)
437 {
438     cond_t((int32_t) T0 > 0);
439     RETURN();
440 }
441
442 void OPPROTO op_cmp_pz_T0(void)
443 {
444     cond_t((int32_t) T0 >= 0);
445     RETURN();
446 }
447
448 void OPPROTO op_jmp_T0(void)
449 {
450     env->delayed_pc = T0;
451     set_flag(DELAY_SLOT);
452     RETURN();
453 }
454
455 void OPPROTO op_movl_rN_rN(void)
456 {
457     env->gregs[PARAM2] = env->gregs[PARAM1];
458     RETURN();
459 }
460
461 void OPPROTO op_ldcl_rMplus_rN_bank(void)
462 {
463     env->gregs[PARAM2] = env->gregs[PARAM1];
464     env->gregs[PARAM1] += 4;
465     RETURN();
466 }
467
468 #define LDSTOPS(target,load,store) \
469 void OPPROTO op_##load##_T0_##target (void) \
470 { env ->target = T0;   RETURN(); \
471 } \
472 void OPPROTO op_##store##_##target##_T0 (void) \
473 { T0 = env->target;   RETURN(); \
474 } \
475
476 LDSTOPS(sr, ldc, stc)
477     LDSTOPS(gbr, ldc, stc)
478     LDSTOPS(vbr, ldc, stc)
479     LDSTOPS(ssr, ldc, stc)
480     LDSTOPS(spc, ldc, stc)
481     LDSTOPS(sgr, ldc, stc)
482     LDSTOPS(dbr, ldc, stc)
483     LDSTOPS(mach, lds, sts)
484     LDSTOPS(macl, lds, sts)
485     LDSTOPS(pr, lds, sts)
486
487 void OPPROTO op_movt_rN(void)
488 {
489     env->gregs[PARAM1] = env->sr & SR_T;
490     RETURN();
491 }
492
493 void OPPROTO op_rotcl_Rn(void)
494 {
495     helper_rotcl(&env->gregs[PARAM1]);
496     RETURN();
497 }
498
499 void OPPROTO op_rotcr_Rn(void)
500 {
501     helper_rotcr(&env->gregs[PARAM1]);
502     RETURN();
503 }
504
505 void OPPROTO op_rotl_Rn(void)
506 {
507     cond_t(env->gregs[PARAM1] & 0x80000000);
508     env->gregs[PARAM1] = (env->gregs[PARAM1] << 1) | (env->sr & SR_T);
509     RETURN();
510 }
511
512 void OPPROTO op_rotr_Rn(void)
513 {
514     cond_t(env->gregs[PARAM1] & 1);
515     env->gregs[PARAM1] = (env->gregs[PARAM1] >> 1) |
516         ((env->sr & SR_T) ? 0x80000000 : 0);
517     RETURN();
518 }
519
520 void OPPROTO op_shal_Rn(void)
521 {
522     cond_t(env->gregs[PARAM1] & 0x80000000);
523     env->gregs[PARAM1] <<= 1;
524     RETURN();
525 }
526
527 void OPPROTO op_shar_Rn(void)
528 {
529     cond_t(env->gregs[PARAM1] & 1);
530     *(int32_t *) & env->gregs[PARAM1] >>= 1;
531     RETURN();
532 }
533
534 void OPPROTO op_shlr_Rn(void)
535 {
536     cond_t(env->gregs[PARAM1] & 1);
537     *(uint32_t *) & env->gregs[PARAM1] >>= 1;
538     RETURN();
539 }
540
541 void OPPROTO op_shll2_Rn(void)
542 {
543     env->gregs[PARAM1] <<= 2;
544     RETURN();
545 }
546
547 void OPPROTO op_shll8_Rn(void)
548 {
549     env->gregs[PARAM1] <<= 8;
550     RETURN();
551 }
552
553 void OPPROTO op_shll16_Rn(void)
554 {
555     env->gregs[PARAM1] <<= 16;
556     RETURN();
557 }
558
559 void OPPROTO op_shlr2_Rn(void)
560 {
561     *(uint32_t *) & env->gregs[PARAM1] >>= 2;
562     RETURN();
563 }
564
565 void OPPROTO op_shlr8_Rn(void)
566 {
567     *(uint32_t *) & env->gregs[PARAM1] >>= 8;
568     RETURN();
569 }
570
571 void OPPROTO op_shlr16_Rn(void)
572 {
573     *(uint32_t *) & env->gregs[PARAM1] >>= 16;
574     RETURN();
575 }
576
577 void OPPROTO op_tasb_rN(void)
578 {
579     cond_t(*(int8_t *) env->gregs[PARAM1] == 0);
580     *(int8_t *) env->gregs[PARAM1] |= 0x80;
581     RETURN();
582 }
583
584 void OPPROTO op_movl_T0_rN(void)
585 {
586     env->gregs[PARAM1] = T0;
587     RETURN();
588 }
589
590 void OPPROTO op_movl_T1_rN(void)
591 {
592     env->gregs[PARAM1] = T1;
593     RETURN();
594 }
595
596 void OPPROTO op_movb_rN_T0(void)
597 {
598     T0 = (int32_t) (int8_t) (env->gregs[PARAM1] & 0xff);
599     RETURN();
600 }
601
602 void OPPROTO op_movub_rN_T0(void)
603 {
604     T0 = env->gregs[PARAM1] & 0xff;
605     RETURN();
606 }
607
608 void OPPROTO op_movw_rN_T0(void)
609 {
610     T0 = (int32_t) (int16_t) (env->gregs[PARAM1] & 0xffff);
611     RETURN();
612 }
613
614 void OPPROTO op_movuw_rN_T0(void)
615 {
616     T0 = env->gregs[PARAM1] & 0xffff;
617     RETURN();
618 }
619
620 void OPPROTO op_movl_rN_T0(void)
621 {
622     T0 = env->gregs[PARAM1];
623     RETURN();
624 }
625
626 void OPPROTO op_movb_rN_T1(void)
627 {
628     T1 = (int32_t) (int8_t) (env->gregs[PARAM1] & 0xff);
629     RETURN();
630 }
631
632 void OPPROTO op_movub_rN_T1(void)
633 {
634     T1 = env->gregs[PARAM1] & 0xff;
635     RETURN();
636 }
637
638 void OPPROTO op_movw_rN_T1(void)
639 {
640     T1 = (int32_t) (int16_t) (env->gregs[PARAM1] & 0xffff);
641     RETURN();
642 }
643
644 void OPPROTO op_movuw_rN_T1(void)
645 {
646     T1 = env->gregs[PARAM1] & 0xffff;
647     RETURN();
648 }
649
650 void OPPROTO op_movl_rN_T1(void)
651 {
652     T1 = env->gregs[PARAM1];
653     RETURN();
654 }
655
656 void OPPROTO op_movl_imm_rN(void)
657 {
658     env->gregs[PARAM2] = PARAM1;
659     RETURN();
660 }
661
662 void OPPROTO op_dec1_rN(void)
663 {
664     env->gregs[PARAM1] -= 1;
665     RETURN();
666 }
667
668 void OPPROTO op_dec2_rN(void)
669 {
670     env->gregs[PARAM1] -= 2;
671     RETURN();
672 }
673
674 void OPPROTO op_dec4_rN(void)
675 {
676     env->gregs[PARAM1] -= 4;
677     RETURN();
678 }
679
680 void OPPROTO op_inc1_rN(void)
681 {
682     env->gregs[PARAM1] += 1;
683     RETURN();
684 }
685
686 void OPPROTO op_inc2_rN(void)
687 {
688     env->gregs[PARAM1] += 2;
689     RETURN();
690 }
691
692 void OPPROTO op_inc4_rN(void)
693 {
694     env->gregs[PARAM1] += 4;
695     RETURN();
696 }
697
698 void OPPROTO op_add_T0_rN(void)
699 {
700     env->gregs[PARAM1] += T0;
701     RETURN();
702 }
703
704 void OPPROTO op_sub_T0_rN(void)
705 {
706     env->gregs[PARAM1] -= T0;
707     RETURN();
708 }
709
710 void OPPROTO op_and_T0_rN(void)
711 {
712     env->gregs[PARAM1] &= T0;
713     RETURN();
714 }
715
716 void OPPROTO op_or_T0_rN(void)
717 {
718     env->gregs[PARAM1] |= T0;
719     RETURN();
720 }
721
722 void OPPROTO op_xor_T0_rN(void)
723 {
724     env->gregs[PARAM1] ^= T0;
725     RETURN();
726 }
727
728 void OPPROTO op_add_rN_T0(void)
729 {
730     T0 += env->gregs[PARAM1];
731     RETURN();
732 }
733
734 void OPPROTO op_add_rN_T1(void)
735 {
736     T1 += env->gregs[PARAM1];
737     RETURN();
738 }
739
740 void OPPROTO op_add_imm_rN(void)
741 {
742     env->gregs[PARAM2] += PARAM1;
743     RETURN();
744 }
745
746 void OPPROTO op_and_imm_rN(void)
747 {
748     env->gregs[PARAM2] &= PARAM1;
749     RETURN();
750 }
751
752 void OPPROTO op_or_imm_rN(void)
753 {
754     env->gregs[PARAM2] |= PARAM1;
755     RETURN();
756 }
757
758 void OPPROTO op_xor_imm_rN(void)
759 {
760     env->gregs[PARAM2] ^= PARAM1;
761     RETURN();
762 }
763
764 void OPPROTO op_dt_rN(void)
765 {
766     cond_t((--env->gregs[PARAM1]) == 0);
767     RETURN();
768 }
769
770 void OPPROTO op_tst_imm_rN(void)
771 {
772     cond_t((env->gregs[PARAM2] & PARAM1) == 0);
773     RETURN();
774 }
775
776 void OPPROTO op_movl_T0_T1(void)
777 {
778     T1 = T0;
779     RETURN();
780 }
781
782 void OPPROTO op_goto_tb0(void)
783 {
784     GOTO_TB(op_goto_tb0, PARAM1, 0);
785     RETURN();
786 }
787
788 void OPPROTO op_goto_tb1(void)
789 {
790     GOTO_TB(op_goto_tb1, PARAM1, 1);
791     RETURN();
792 }
793
794 void OPPROTO op_movl_imm_PC(void)
795 {
796     env->pc = PARAM1;
797     RETURN();
798 }
799
800 void OPPROTO op_jT(void)
801 {
802     if (env->sr & SR_T)
803         GOTO_LABEL_PARAM(1);
804     RETURN();
805 }
806
807 void OPPROTO op_jTT2(void)
808 {
809     if (T2 & SR_T)
810         GOTO_LABEL_PARAM(1);
811     RETURN();
812 }
813
814 void OPPROTO op_movl_delayed_pc_PC(void)
815 {
816     env->pc = env->delayed_pc;
817     RETURN();
818 }
819
820 void OPPROTO op_addl_GBR_T0(void)
821 {
822     T0 += env->gbr;
823     RETURN();
824 }
825
826 void OPPROTO op_and_imm_T0(void)
827 {
828     T0 &= PARAM1;
829     RETURN();
830 }
831
832 void OPPROTO op_or_imm_T0(void)
833 {
834     T0 |= PARAM1;
835     RETURN();
836 }
837
838 void OPPROTO op_xor_imm_T0(void)
839 {
840     T0 ^= PARAM1;
841     RETURN();
842 }
843
844 void OPPROTO op_tst_imm_T0(void)
845 {
846     cond_t((T0 & PARAM1) == 0);
847     RETURN();
848 }
849
850 void OPPROTO op_raise_illegal_instruction(void)
851 {
852     env->exception_index = 0x180;
853     do_raise_exception();
854     RETURN();
855 }
856
857 void OPPROTO op_raise_slot_illegal_instruction(void)
858 {
859     env->exception_index = 0x1a0;
860     do_raise_exception();
861     RETURN();
862 }
863
864 void OPPROTO op_debug(void)
865 {
866     env->exception_index = EXCP_DEBUG;
867     cpu_loop_exit();
868 }
869
870 /* Load and store */
871 #define MEMSUFFIX _raw
872 #include "op_mem.c"
873 #undef MEMSUFFIX
874 #if !defined(CONFIG_USER_ONLY)
875 #define MEMSUFFIX _user
876 #include "op_mem.c"
877 #undef MEMSUFFIX
878
879 #define MEMSUFFIX _kernel
880 #include "op_mem.c"
881 #undef MEMSUFFIX
882 #endif