|
|
1.1 root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.