2 * vim:shiftwidth=2:expandtab
8 #include "../../pico/pico_int.h"
11 #include "../drc/cmn.h"
18 #define dbg(l,...) { \
19 if ((l) & DRC_DEBUG) \
20 elprintf(EL_STATUS, ##__VA_ARGS__); \
23 #include "mame/sh2dasm.h"
24 #include <platform/linux/host_dasm.h>
25 static int insns_compiled, hash_collisions, host_insn_count;
34 static u8 *tcache_dsm_ptrs[3];
35 static char sh2dasm_buff[64];
36 #define do_host_disasm(tcid) \
37 host_dasm(tcache_dsm_ptrs[tcid], tcache_ptr - tcache_dsm_ptrs[tcid]); \
38 tcache_dsm_ptrs[tcid] = tcache_ptr
40 #define do_host_disasm(x)
43 #define BLOCK_CYCLE_LIMIT 100
44 #define MAX_BLOCK_SIZE (BLOCK_CYCLE_LIMIT * 6 * 6)
46 // we have 3 translation cache buffers, split from one drc/cmn buffer.
47 // BIOS shares tcache with data array because it's only used for init
48 // and can be discarded early
49 static const int tcache_sizes[3] = {
50 DRC_TCACHE_SIZE * 6 / 8, // ROM, DRAM
51 DRC_TCACHE_SIZE / 8, // BIOS, data array in master sh2
52 DRC_TCACHE_SIZE / 8, // ... slave
55 static u8 *tcache_bases[3];
56 static u8 *tcache_ptrs[3];
58 // ptr for code emiters
59 static u8 *tcache_ptr;
61 // host register tracking
64 HR_CACHED, // 'val' has sh2_reg_e
66 HR_CONST, // 'val' has constant
67 HR_TEMP, // reg used for temp storage
73 u16 stamp; // kind of a timestamp
77 // note: reg_temp[] must have at least the amount of
78 // registers used by handlers in worst case (currently 4)
80 #include "../drc/emit_arm.c"
82 static const int reg_map_g2h[] = {
91 static temp_reg_t reg_temp[] = {
101 #include "../drc/emit_x86.c"
103 static const int reg_map_g2h[] = {
112 // ax, cx, dx are usually temporaries by convention
113 static temp_reg_t reg_temp[] = {
129 SHR_R0 = 0, SHR_SP = 15,
130 SHR_PC, SHR_PPC, SHR_PR, SHR_SR,
131 SHR_GBR, SHR_VBR, SHR_MACH, SHR_MACL,
134 typedef struct block_desc_ {
135 u32 addr; // SH2 PC address
136 u32 end_addr; // TODO rm?
137 void *tcache_ptr; // translated block for above PC
138 struct block_desc_ *next; // next block with the same PC hash
144 static const int block_max_counts[3] = {
149 static block_desc *block_tables[3];
150 static int block_counts[3];
153 #define MAX_HASH_ENTRIES 1024
154 #define HASH_MASK (MAX_HASH_ENTRIES - 1)
155 static void **hash_table;
157 extern void sh2_drc_entry(SH2 *sh2, void *block);
158 extern void sh2_drc_exit(void);
161 extern void REGPARM(2) sh2_do_op(SH2 *sh2, int opcode);
162 static void REGPARM(1) sh2_test_irq(SH2 *sh2);
164 static void flush_tcache(int tcid)
166 dbg(1, "tcache #%d flush! (%d/%d, bds %d/%d)", tcid,
167 tcache_ptrs[tcid] - tcache_bases[tcid], tcache_sizes[tcid],
168 block_counts[tcid], block_max_counts[tcid]);
170 block_counts[tcid] = 0;
171 tcache_ptrs[tcid] = tcache_bases[tcid];
172 if (tcid == 0) { // ROM, RAM
173 memset(hash_table, 0, sizeof(hash_table[0]) * MAX_HASH_ENTRIES);
174 memset(Pico32xMem->drcblk_ram, 0, sizeof(Pico32xMem->drcblk_ram));
177 memset(Pico32xMem->drcblk_da[tcid - 1], 0, sizeof(Pico32xMem->drcblk_da[0]));
179 tcache_dsm_ptrs[tcid] = tcache_bases[tcid];
183 static void *dr_find_block(block_desc *tab, u32 addr)
185 for (tab = tab->next; tab != NULL; tab = tab->next)
186 if (tab->addr == addr)
190 return tab->tcache_ptr;
192 printf("block miss for %08x\n", addr);
196 static block_desc *dr_add_block(u32 addr, int tcache_id, int *blk_id)
198 int *bcount = &block_counts[tcache_id];
201 if (*bcount >= block_max_counts[tcache_id])
204 bd = &block_tables[tcache_id][*bcount];
206 bd->tcache_ptr = tcache_ptr;
213 #define HASH_FUNC(hash_tab, addr) \
214 ((block_desc **)(hash_tab))[(addr) & HASH_MASK]
216 // ---------------------------------------------------------------
219 static u16 rcache_counter;
221 static temp_reg_t *rcache_evict(void)
223 // evict reg with oldest stamp
225 u16 min_stamp = (u16)-1;
227 for (i = 0; i < ARRAY_SIZE(reg_temp); i++) {
228 if (reg_temp[i].type == HR_CACHED || reg_temp[i].type == HR_CACHED_DIRTY)
229 if (reg_temp[i].stamp <= min_stamp) {
230 min_stamp = reg_temp[i].stamp;
236 printf("no registers to evict, aborting\n");
241 if (reg_temp[i].type == HR_CACHED_DIRTY) {
243 emith_ctx_write(reg_temp[i].reg, reg_temp[i].val * 4);
255 // note: must not be called when doing conditional code
256 static int rcache_get_reg(sh2_reg_e r, rc_gr_mode mode)
261 // maybe already statically mapped?
268 // maybe already cached?
269 for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
270 if ((reg_temp[i].type == HR_CACHED || reg_temp[i].type == HR_CACHED_DIRTY) &&
271 reg_temp[i].val == r)
273 reg_temp[i].stamp = rcache_counter;
274 if (mode != RC_GR_READ)
275 reg_temp[i].type = HR_CACHED_DIRTY;
276 return reg_temp[i].reg;
281 for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
282 if (reg_temp[i].type == HR_FREE || reg_temp[i].type == HR_CONST) {
291 if (mode != RC_GR_WRITE)
292 emith_ctx_read(tr->reg, r * 4);
294 tr->type = mode != RC_GR_READ ? HR_CACHED_DIRTY : HR_CACHED;
296 tr->stamp = rcache_counter;
300 static int rcache_get_tmp(void)
305 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
306 if (reg_temp[i].type == HR_FREE || reg_temp[i].type == HR_CONST) {
318 static int rcache_get_arg_id(int arg)
321 host_arg2reg(r, arg);
323 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
324 if (reg_temp[i].reg == r)
327 if (i == ARRAY_SIZE(reg_temp))
328 // let's just say it's untracked arg reg
331 if (reg_temp[i].type == HR_CACHED_DIRTY) {
333 emith_ctx_write(reg_temp[i].reg, reg_temp[i].val * 4);
335 else if (reg_temp[i].type == HR_TEMP) {
336 printf("arg %d reg %d already used, aborting\n", arg, r);
343 // get a reg to be used as function arg
344 // it's assumed that regs are cleaned before call
345 static int rcache_get_tmp_arg(int arg)
347 int id = rcache_get_arg_id(arg);
348 reg_temp[id].type = HR_TEMP;
350 return reg_temp[id].reg;
353 // same but caches reg. RC_GR_READ only.
354 static int rcache_get_reg_arg(int arg, sh2_reg_e r)
356 int i, srcr, dstr, dstid;
358 dstid = rcache_get_arg_id(arg);
359 dstr = reg_temp[dstid].reg;
361 // maybe already statically mapped?
362 srcr = reg_map_g2h[r];
366 // maybe already cached?
367 for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
368 if ((reg_temp[i].type == HR_CACHED || reg_temp[i].type == HR_CACHED_DIRTY) &&
369 reg_temp[i].val == r)
371 srcr = reg_temp[i].reg;
378 emith_ctx_read(srcr, r * 4);
382 emith_move_r_r(dstr, srcr);
384 reg_temp[dstid].stamp = ++rcache_counter;
385 reg_temp[dstid].type = HR_CACHED;
386 reg_temp[dstid].val = r;
390 static void rcache_free_tmp(int hr)
393 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
394 if (reg_temp[i].reg == hr)
397 if (i == ARRAY_SIZE(reg_temp) || reg_temp[i].type != HR_TEMP) {
398 printf("rcache_free_tmp fail: #%i hr %d, type %d\n", i, hr, reg_temp[i].type);
402 reg_temp[i].type = HR_FREE;
405 static void rcache_clean(void)
408 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
409 if (reg_temp[i].type == HR_CACHED_DIRTY) {
411 emith_ctx_write(reg_temp[i].reg, reg_temp[i].val * 4);
412 reg_temp[i].type = HR_CACHED;
416 static void rcache_invalidate(void)
419 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
420 reg_temp[i].type = HR_FREE;
424 static void rcache_flush(void)
430 // ---------------------------------------------------------------
432 static void emit_move_r_imm32(sh2_reg_e dst, u32 imm)
434 // TODO: propagate this constant
435 int hr = rcache_get_reg(dst, RC_GR_WRITE);
436 emith_move_r_imm(hr, imm);
439 static void emit_move_r_r(sh2_reg_e dst, sh2_reg_e src)
441 int hr_d = rcache_get_reg(dst, RC_GR_WRITE);
442 int hr_s = rcache_get_reg(src, RC_GR_READ);
444 emith_move_r_r(hr_d, hr_s);
447 // T must be clear, and comparison done just before this
448 static void emit_or_t_if_eq(int srr)
450 EMITH_SJMP_START(DCOND_NE);
451 emith_or_r_imm_c(DCOND_EQ, srr, T);
452 EMITH_SJMP_END(DCOND_NE);
455 // arguments must be ready
456 // reg cache must be clean before call
457 static int emit_memhandler_read(int size)
460 host_arg2reg(ctxr, 1);
461 emith_move_r_r(ctxr, CONTEXT_REG);
464 emith_call(p32x_sh2_read8);
467 emith_call(p32x_sh2_read16);
470 emith_call(p32x_sh2_read32);
474 // assuming arg0 and retval reg matches
475 return rcache_get_tmp_arg(0);
478 static void emit_memhandler_write(int size)
481 host_arg2reg(ctxr, 2);
482 emith_move_r_r(ctxr, CONTEXT_REG);
485 emith_call(p32x_sh2_write8);
488 emith_call(p32x_sh2_write16);
491 emith_call(p32x_sh2_write32);
498 static int emit_indirect_indexed_read(int rx, int ry, int size)
502 a0 = rcache_get_reg_arg(0, rx);
503 t = rcache_get_reg(ry, RC_GR_READ);
504 emith_add_r_r(a0, t);
505 return emit_memhandler_read(size);
509 static void emit_indirect_indexed_write(int rx, int ry, int wr, int size)
513 rcache_get_reg_arg(1, wr);
514 a0 = rcache_get_reg_arg(0, rx);
515 t = rcache_get_reg(ry, RC_GR_READ);
516 emith_add_r_r(a0, t);
517 emit_memhandler_write(size);
524 #define CHECK_UNHANDLED_BITS(mask) { \
525 if ((op & (mask)) != 0) \
532 #define GET_Rm GET_Fx
537 #define CHECK_FX_LT(n) \
541 static void *sh2_translate(SH2 *sh2, block_desc *other_block)
544 block_desc *this_block;
545 unsigned int pc = sh2->pc;
546 int op, delayed_op = 0, test_irq = 0;
547 int tcache_id = 0, blkid = 0;
549 u32 tmp, tmp2, tmp3, tmp4;
553 if ((tmp != 0 && tmp != 1 && tmp != 6) || sh2->pc == 0) {
554 printf("invalid PC, aborting: %08x\n", sh2->pc);
555 // FIXME: be less destructive
559 if ((sh2->pc & 0xe0000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
560 // data_array, BIOS have separate tcache (shared)
561 tcache_id = 1 + sh2->is_slave;
564 tcache_ptr = tcache_ptrs[tcache_id];
565 this_block = dr_add_block(pc, tcache_id, &blkid);
567 tmp = tcache_ptr - tcache_bases[tcache_id];
568 if (tmp > tcache_sizes[tcache_id] - MAX_BLOCK_SIZE || this_block == NULL) {
569 flush_tcache(tcache_id);
570 tcache_ptr = tcache_ptrs[tcache_id];
571 other_block = NULL; // also gone too due to flush
572 this_block = dr_add_block(pc, tcache_id, &blkid);
575 this_block->next = other_block;
576 if ((sh2->pc & 0xc6000000) == 0x02000000) // ROM
577 HASH_FUNC(hash_table, pc) = this_block;
579 block_entry = tcache_ptr;
581 printf("== %csh2 block #%d,%d %08x -> %p\n", sh2->is_slave ? 's' : 'm',
582 tcache_id, block_counts[tcache_id], pc, block_entry);
583 if (other_block != NULL) {
584 printf(" hash collision with %08x\n", other_block->addr);
589 while (cycles < BLOCK_CYCLE_LIMIT || delayed_op)
594 op = p32x_sh2_read16(pc, sh2);
599 DasmSH2(sh2dasm_buff, pc, op);
600 printf("%08x %04x %s\n", pc, op, sh2dasm_buff);
607 switch ((op >> 12) & 0x0f)
609 /////////////////////////////////////////////
614 tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
617 case 0: // STC SR,Rn 0000nnnn00000010
620 case 1: // STC GBR,Rn 0000nnnn00010010
623 case 2: // STC VBR,Rn 0000nnnn00100010
629 tmp3 = rcache_get_reg(tmp2, RC_GR_READ);
630 emith_move_r_r(tmp, tmp3);
632 emith_clear_msb(tmp, tmp, 20); // reserved bits defined by ISA as 0
635 CHECK_UNHANDLED_BITS(0xd0);
636 // BRAF Rm 0000mmmm00100011
637 // BSRF Rm 0000mmmm00000011
640 emit_move_r_imm32(SHR_PR, pc + 2);
641 tmp = rcache_get_reg(SHR_PPC, RC_GR_WRITE);
642 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
643 emith_move_r_r(tmp, tmp2);
644 emith_add_r_imm(tmp, pc + 2);
647 case 0x04: // MOV.B Rm,@(R0,Rn) 0000nnnnmmmm0100
648 case 0x05: // MOV.W Rm,@(R0,Rn) 0000nnnnmmmm0101
649 case 0x06: // MOV.L Rm,@(R0,Rn) 0000nnnnmmmm0110
650 emit_indirect_indexed_write(SHR_R0, GET_Rn(), GET_Rm(), op & 3);
653 // MUL.L Rm,Rn 0000nnnnmmmm0111
654 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
655 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
656 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
657 emith_mul(tmp3, tmp2, tmp);
661 CHECK_UNHANDLED_BITS(0xf00);
664 case 0: // CLRT 0000000000001000
665 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
666 emith_bic_r_imm(tmp, T);
668 case 1: // SETT 0000000000011000
669 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
670 emith_or_r_imm(tmp, T);
672 case 2: // CLRMAC 0000000000101000
673 tmp = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
674 emith_move_r_imm(tmp, 0);
675 tmp = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
676 emith_move_r_imm(tmp, 0);
685 case 0: // NOP 0000000000001001
686 CHECK_UNHANDLED_BITS(0xf00);
688 case 1: // DIV0U 0000000000011001
689 CHECK_UNHANDLED_BITS(0xf00);
690 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
691 emith_bic_r_imm(tmp, M|Q|T);
693 case 2: // MOVT Rn 0000nnnn00101001
694 tmp = rcache_get_reg(SHR_SR, RC_GR_READ);
695 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
696 emith_clear_msb(tmp2, tmp, 31);
703 tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
706 case 0: // STS MACH,Rn 0000nnnn00001010
709 case 1: // STS MACL,Rn 0000nnnn00011010
712 case 2: // STS PR,Rn 0000nnnn00101010
718 tmp2 = rcache_get_reg(tmp2, RC_GR_READ);
719 emith_move_r_r(tmp, tmp2);
722 CHECK_UNHANDLED_BITS(0xf00);
725 case 0: // RTS 0000000000001011
727 emit_move_r_r(SHR_PPC, SHR_PR);
730 case 1: // SLEEP 0000000000011011
731 emit_move_r_imm32(SHR_PC, pc - 2);
732 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
733 emith_clear_msb(tmp, tmp, 20); // clear cycles
737 case 2: // RTE 0000000000101011
741 rcache_get_reg_arg(0, SHR_SP);
742 tmp = emit_memhandler_read(2);
743 tmp2 = rcache_get_reg(SHR_PPC, RC_GR_WRITE);
744 emith_move_r_r(tmp2, tmp);
745 rcache_free_tmp(tmp);
748 tmp = rcache_get_reg_arg(0, SHR_SP);
749 emith_add_r_imm(tmp, 4);
750 tmp = emit_memhandler_read(2);
752 rcache_free_tmp(tmp);
753 tmp = rcache_get_reg(SHR_SP, RC_GR_RMW);
754 emith_add_r_imm(tmp, 4*2);
762 case 0x0c: // MOV.B @(R0,Rm),Rn 0000nnnnmmmm1100
763 case 0x0d: // MOV.W @(R0,Rm),Rn 0000nnnnmmmm1101
764 case 0x0e: // MOV.L @(R0,Rm),Rn 0000nnnnmmmm1110
765 tmp = emit_indirect_indexed_read(SHR_R0, GET_Rm(), op & 3);
766 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
768 emith_sext(tmp2, tmp, (op & 1) ? 16 : 8);
770 emith_move_r_r(tmp2, tmp);
771 rcache_free_tmp(tmp);
773 case 0x0f: // MAC.L @Rm+,@Rn+ 0000nnnnmmmm1111
779 /////////////////////////////////////////////
781 // MOV.L Rm,@(disp,Rn) 0001nnnnmmmmdddd
783 tmp = rcache_get_reg_arg(0, GET_Rn());
784 tmp2 = rcache_get_reg_arg(1, GET_Rm());
785 emith_add_r_imm(tmp, (op & 0x0f) * 4);
786 emit_memhandler_write(2);
792 case 0x00: // MOV.B Rm,@Rn 0010nnnnmmmm0000
793 case 0x01: // MOV.W Rm,@Rn 0010nnnnmmmm0001
794 case 0x02: // MOV.L Rm,@Rn 0010nnnnmmmm0010
796 rcache_get_reg_arg(0, GET_Rn());
797 rcache_get_reg_arg(1, GET_Rm());
798 emit_memhandler_write(op & 3);
800 case 0x04: // MOV.B Rm,@–Rn 0010nnnnmmmm0100
801 case 0x05: // MOV.W Rm,@–Rn 0010nnnnmmmm0101
802 case 0x06: // MOV.L Rm,@–Rn 0010nnnnmmmm0110
803 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
804 emith_sub_r_imm(tmp, (1 << (op & 3)));
806 rcache_get_reg_arg(0, GET_Rn());
807 rcache_get_reg_arg(1, GET_Rm());
808 emit_memhandler_write(op & 3);
810 case 0x07: // DIV0S Rm,Rn 0010nnnnmmmm0111
811 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
812 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
813 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
814 emith_bic_r_imm(tmp, M|Q|T);
815 emith_tst_r_imm(tmp2, (1<<31));
816 EMITH_SJMP_START(DCOND_EQ);
817 emith_or_r_imm_c(DCOND_NE, tmp, Q);
818 EMITH_SJMP_END(DCOND_EQ);
819 emith_tst_r_imm(tmp3, (1<<31));
820 EMITH_SJMP_START(DCOND_EQ);
821 emith_or_r_imm_c(DCOND_NE, tmp, M);
822 EMITH_SJMP_END(DCOND_EQ);
823 emith_teq_r_r(tmp2, tmp3);
824 EMITH_SJMP_START(DCOND_PL);
825 emith_or_r_imm_c(DCOND_MI, tmp, T);
826 EMITH_SJMP_END(DCOND_PL);
828 case 0x08: // TST Rm,Rn 0010nnnnmmmm1000
829 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
830 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
831 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
832 emith_bic_r_imm(tmp, T);
833 emith_tst_r_r(tmp2, tmp3);
834 emit_or_t_if_eq(tmp);
836 case 0x09: // AND Rm,Rn 0010nnnnmmmm1001
837 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
838 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
839 emith_and_r_r(tmp, tmp2);
841 case 0x0a: // XOR Rm,Rn 0010nnnnmmmm1010
842 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
843 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
844 emith_eor_r_r(tmp, tmp2);
846 case 0x0b: // OR Rm,Rn 0010nnnnmmmm1011
847 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
848 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
849 emith_or_r_r(tmp, tmp2);
851 case 0x0c: // CMP/STR Rm,Rn 0010nnnnmmmm1100
852 tmp = rcache_get_tmp();
853 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
854 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
855 emith_eor_r_r_r(tmp, tmp2, tmp3);
856 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
857 emith_bic_r_imm(tmp2, T);
858 emith_tst_r_imm(tmp, 0x000000ff);
859 emit_or_t_if_eq(tmp);
860 emith_tst_r_imm(tmp, 0x0000ff00);
861 emit_or_t_if_eq(tmp);
862 emith_tst_r_imm(tmp, 0x00ff0000);
863 emit_or_t_if_eq(tmp);
864 emith_tst_r_imm(tmp, 0xff000000);
865 emit_or_t_if_eq(tmp);
866 rcache_free_tmp(tmp);
868 case 0x0d: // XTRCT Rm,Rn 0010nnnnmmmm1101
869 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
870 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
871 emith_lsr(tmp, tmp, 16);
872 emith_or_r_r_r_lsl(tmp, tmp, tmp2, 16);
874 case 0x0e: // MULU.W Rm,Rn 0010nnnnmmmm1110
875 case 0x0f: // MULS.W Rm,Rn 0010nnnnmmmm1111
876 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
877 tmp = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
879 emith_sext(tmp, tmp2, 16);
881 emith_clear_msb(tmp, tmp2, 16);
882 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
883 tmp2 = rcache_get_tmp();
885 emith_sext(tmp2, tmp3, 16);
887 emith_clear_msb(tmp2, tmp3, 16);
888 emith_mul(tmp, tmp, tmp2);
889 rcache_free_tmp(tmp2);
890 // FIXME: causes timing issues in Doom?
896 /////////////////////////////////////////////
900 case 0x00: // CMP/EQ Rm,Rn 0011nnnnmmmm0000
901 case 0x02: // CMP/HS Rm,Rn 0011nnnnmmmm0010
902 case 0x03: // CMP/GE Rm,Rn 0011nnnnmmmm0011
903 case 0x06: // CMP/HI Rm,Rn 0011nnnnmmmm0110
904 case 0x07: // CMP/GT Rm,Rn 0011nnnnmmmm0111
905 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
906 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
907 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
908 emith_bic_r_imm(tmp, T);
909 emith_cmp_r_r(tmp2, tmp3);
913 emit_or_t_if_eq(tmp);
916 EMITH_SJMP_START(DCOND_LO);
917 emith_or_r_imm_c(DCOND_HS, tmp, T);
918 EMITH_SJMP_END(DCOND_LO);
921 EMITH_SJMP_START(DCOND_LT);
922 emith_or_r_imm_c(DCOND_GE, tmp, T);
923 EMITH_SJMP_END(DCOND_LT);
926 EMITH_SJMP_START(DCOND_LS);
927 emith_or_r_imm_c(DCOND_HI, tmp, T);
928 EMITH_SJMP_END(DCOND_LS);
931 EMITH_SJMP_START(DCOND_LE);
932 emith_or_r_imm_c(DCOND_GT, tmp, T);
933 EMITH_SJMP_END(DCOND_LE);
937 case 0x04: // DIV1 Rm,Rn 0011nnnnmmmm0100
940 case 0x05: // DMULU.L Rm,Rn 0011nnnnmmmm0101
941 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
942 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
943 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
944 tmp4 = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
945 emith_mul_u64(tmp3, tmp4, tmp, tmp2);
947 case 0x08: // SUB Rm,Rn 0011nnnnmmmm1000
948 case 0x0c: // ADD Rm,Rn 0011nnnnmmmm1100
949 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
950 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
952 emith_add_r_r(tmp, tmp2);
954 emith_sub_r_r(tmp, tmp2);
956 case 0x0a: // SUBC Rm,Rn 0011nnnnmmmm1010
957 case 0x0e: // ADDC Rm,Rn 0011nnnnmmmm1110
958 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
959 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
960 tmp3 = rcache_get_reg(SHR_SR, RC_GR_RMW);
962 emith_set_carry(tmp3);
963 emith_adcf_r_r(tmp, tmp2);
964 emith_carry_to_t(tmp3, 0);
966 emith_set_carry_sub(tmp3);
967 emith_sbcf_r_r(tmp, tmp2);
968 emith_carry_to_t(tmp3, 1);
971 case 0x0b: // SUBV Rm,Rn 0011nnnnmmmm1011
972 case 0x0f: // ADDV Rm,Rn 0011nnnnmmmm1111
973 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
974 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
975 tmp3 = rcache_get_reg(SHR_SR, RC_GR_RMW);
976 emith_bic_r_imm(tmp3, T);
978 emith_addf_r_r(tmp, tmp2);
980 emith_subf_r_r(tmp, tmp2);
981 EMITH_SJMP_START(DCOND_VC);
982 emith_or_r_imm_c(DCOND_VS, tmp3, T);
983 EMITH_SJMP_END(DCOND_VC);
985 case 0x0d: // DMULS.L Rm,Rn 0011nnnnmmmm1101
986 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
987 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
988 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
989 tmp4 = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
990 emith_mul_s64(tmp3, tmp4, tmp, tmp2);
995 /////////////////////////////////////////////
1002 case 0: // SHLL Rn 0100nnnn00000000
1003 case 2: // SHAL Rn 0100nnnn00100000
1004 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1005 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1006 emith_lslf(tmp, tmp, 1);
1007 emith_carry_to_t(tmp2, 0);
1009 case 1: // DT Rn 0100nnnn00010000
1010 if (p32x_sh2_read16(pc, sh2) == 0x8bfd) { // BF #-2
1011 emith_sh2_dtbf_loop();
1014 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1015 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1016 emith_bic_r_imm(tmp2, T);
1017 emith_subf_r_imm(tmp, 1);
1018 emit_or_t_if_eq(tmp2);
1025 case 0: // SHLR Rn 0100nnnn00000001
1026 case 2: // SHAR Rn 0100nnnn00100001
1027 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1028 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1030 emith_asrf(tmp, tmp, 1);
1032 emith_lsrf(tmp, tmp, 1);
1033 emith_carry_to_t(tmp2, 0);
1035 case 1: // CMP/PZ Rn 0100nnnn00010001
1036 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1037 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1038 emith_bic_r_imm(tmp2, T);
1039 emith_cmp_r_imm(tmp, 0);
1040 EMITH_SJMP_START(DCOND_LT);
1041 emith_or_r_imm_c(DCOND_GE, tmp2, T);
1042 EMITH_SJMP_END(DCOND_LT);
1050 case 0x02: // STS.L MACH,@–Rn 0100nnnn00000010
1053 case 0x12: // STS.L MACL,@–Rn 0100nnnn00010010
1056 case 0x22: // STS.L PR,@–Rn 0100nnnn00100010
1059 case 0x03: // STC.L SR,@–Rn 0100nnnn00000011
1062 case 0x13: // STC.L GBR,@–Rn 0100nnnn00010011
1065 case 0x23: // STC.L VBR,@–Rn 0100nnnn00100011
1071 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1072 emith_sub_r_imm(tmp2, 4);
1074 rcache_get_reg_arg(0, GET_Rn());
1075 tmp3 = rcache_get_reg_arg(1, tmp);
1077 emith_clear_msb(tmp3, tmp3, 20); // reserved bits defined by ISA as 0
1078 emit_memhandler_write(2);
1084 case 0x04: // ROTL Rn 0100nnnn00000100
1085 case 0x05: // ROTR Rn 0100nnnn00000101
1086 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1087 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1089 emith_rorf(tmp, tmp, 1);
1091 emith_rolf(tmp, tmp, 1);
1092 emith_carry_to_t(tmp2, 0);
1094 case 0x24: // ROTCL Rn 0100nnnn00100100
1095 case 0x25: // ROTCR Rn 0100nnnn00100101
1096 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1097 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1098 emith_set_carry(tmp2);
1103 emith_carry_to_t(tmp2, 0);
1105 case 0x15: // CMP/PL Rn 0100nnnn00010101
1106 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1107 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1108 emith_bic_r_imm(tmp2, T);
1109 emith_cmp_r_imm(tmp, 0);
1110 EMITH_SJMP_START(DCOND_LE);
1111 emith_or_r_imm_c(DCOND_GT, tmp2, T);
1112 EMITH_SJMP_END(DCOND_LE);
1120 case 0x06: // LDS.L @Rm+,MACH 0100mmmm00000110
1123 case 0x16: // LDS.L @Rm+,MACL 0100mmmm00010110
1126 case 0x26: // LDS.L @Rm+,PR 0100mmmm00100110
1129 case 0x07: // LDC.L @Rm+,SR 0100mmmm00000111
1132 case 0x17: // LDC.L @Rm+,GBR 0100mmmm00010111
1135 case 0x27: // LDC.L @Rm+,VBR 0100mmmm00100111
1142 rcache_get_reg_arg(0, GET_Rn());
1143 tmp2 = emit_memhandler_read(2);
1144 if (tmp == SHR_SR) {
1145 emith_write_sr(tmp2);
1148 tmp = rcache_get_reg(tmp, RC_GR_WRITE);
1149 emith_move_r_r(tmp, tmp2);
1151 rcache_free_tmp(tmp2);
1152 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1153 emith_add_r_imm(tmp, 4);
1160 // SHLL2 Rn 0100nnnn00001000
1161 // SHLR2 Rn 0100nnnn00001001
1165 // SHLL8 Rn 0100nnnn00011000
1166 // SHLR8 Rn 0100nnnn00011001
1170 // SHLL16 Rn 0100nnnn00101000
1171 // SHLR16 Rn 0100nnnn00101001
1177 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1179 emith_lsr(tmp2, tmp2, tmp);
1181 emith_lsl(tmp2, tmp2, tmp);
1186 case 0: // LDS Rm,MACH 0100mmmm00001010
1189 case 1: // LDS Rm,MACL 0100mmmm00011010
1192 case 2: // LDS Rm,PR 0100mmmm00101010
1198 emit_move_r_r(tmp2, GET_Rn());
1203 case 0: // JSR @Rm 0100mmmm00001011
1204 case 2: // JMP @Rm 0100mmmm00101011
1207 emit_move_r_imm32(SHR_PR, pc + 2);
1208 emit_move_r_r(SHR_PPC, (op >> 8) & 0x0f);
1211 case 1: // TAS.B @Rn 0100nnnn00011011
1212 // XXX: is TAS working on 32X?
1214 rcache_get_reg_arg(0, GET_Rn());
1215 tmp = emit_memhandler_read(0);
1216 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1217 emith_bic_r_imm(tmp2, T);
1218 emith_cmp_r_imm(tmp, 0);
1219 emit_or_t_if_eq(tmp2);
1221 emith_or_r_imm(tmp, 0x80);
1222 tmp2 = rcache_get_tmp_arg(1); // assuming it differs to tmp
1223 emith_move_r_r(tmp2, tmp);
1224 rcache_free_tmp(tmp);
1225 rcache_get_reg_arg(0, GET_Rn());
1226 emit_memhandler_write(0);
1234 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
1237 case 0: // LDC Rm,SR 0100mmmm00001110
1240 case 1: // LDC Rm,GBR 0100mmmm00011110
1243 case 2: // LDC Rm,VBR 0100mmmm00101110
1249 if (tmp2 == SHR_SR) {
1250 emith_write_sr(tmp);
1251 emit_move_r_imm32(SHR_PC, pc);
1254 tmp2 = rcache_get_reg(tmp2, RC_GR_WRITE);
1255 emith_move_r_r(tmp2, tmp);
1259 // MAC @Rm+,@Rn+ 0100nnnnmmmm1111
1264 /////////////////////////////////////////////
1266 // MOV.L @(disp,Rm),Rn 0101nnnnmmmmdddd
1268 tmp = rcache_get_reg_arg(0, GET_Rm());
1269 emith_add_r_imm(tmp, (op & 0x0f) * 4);
1270 tmp = emit_memhandler_read(2);
1271 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
1272 emith_move_r_r(tmp2, tmp);
1273 rcache_free_tmp(tmp);
1276 /////////////////////////////////////////////
1280 case 0x00: // MOV.B @Rm,Rn 0110nnnnmmmm0000
1281 case 0x01: // MOV.W @Rm,Rn 0110nnnnmmmm0001
1282 case 0x02: // MOV.L @Rm,Rn 0110nnnnmmmm0010
1283 case 0x04: // MOV.B @Rm+,Rn 0110nnnnmmmm0100
1284 case 0x05: // MOV.W @Rm+,Rn 0110nnnnmmmm0101
1285 case 0x06: // MOV.L @Rm+,Rn 0110nnnnmmmm0110
1287 rcache_get_reg_arg(0, GET_Rm());
1288 tmp = emit_memhandler_read(op & 3);
1289 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
1290 if ((op & 3) != 2) {
1291 emith_sext(tmp2, tmp, (op & 1) ? 16 : 8);
1293 emith_move_r_r(tmp2, tmp);
1294 rcache_free_tmp(tmp);
1295 if ((op & 7) >= 4 && GET_Rn() != GET_Rm()) {
1296 tmp = rcache_get_reg(GET_Rm(), RC_GR_RMW);
1297 emith_add_r_imm(tmp, (1 << (op & 3)));
1302 tmp = rcache_get_reg(GET_Rm(), RC_GR_READ);
1303 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
1306 case 0x03: // MOV Rm,Rn 0110nnnnmmmm0011
1307 emith_move_r_r(tmp2, tmp);
1309 case 0x07: // NOT Rm,Rn 0110nnnnmmmm0111
1310 emith_mvn_r_r(tmp2, tmp);
1312 case 0x08: // SWAP.B Rm,Rn 0110nnnnmmmm1000
1315 tmp3 = rcache_get_tmp();
1316 tmp4 = rcache_get_tmp();
1317 emith_lsr(tmp3, tmp, 16);
1318 emith_or_r_r_r_lsl(tmp3, tmp3, tmp, 24);
1319 emith_and_r_r_imm(tmp4, tmp, 0xff00);
1320 emith_or_r_r_r_lsl(tmp3, tmp3, tmp4, 8);
1321 emith_rol(tmp2, tmp3, 16);
1322 rcache_free_tmp(tmp4);
1324 rcache_free_tmp(tmp3);
1326 case 0x09: // SWAP.W Rm,Rn 0110nnnnmmmm1001
1327 emith_rol(tmp2, tmp, 16);
1329 case 0x0a: // NEGC Rm,Rn 0110nnnnmmmm1010
1330 tmp3 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1331 emith_set_carry_sub(tmp3);
1332 emith_negcf_r_r(tmp2, tmp);
1333 emith_carry_to_t(tmp3, 1);
1335 case 0x0b: // NEG Rm,Rn 0110nnnnmmmm1011
1336 emith_neg_r_r(tmp2, tmp);
1338 case 0x0c: // EXTU.B Rm,Rn 0110nnnnmmmm1100
1339 emith_clear_msb(tmp2, tmp, 24);
1341 case 0x0d: // EXTU.W Rm,Rn 0110nnnnmmmm1101
1342 emith_clear_msb(tmp2, tmp, 16);
1344 case 0x0e: // EXTS.B Rm,Rn 0110nnnnmmmm1110
1345 emith_sext(tmp2, tmp, 8);
1347 case 0x0f: // EXTS.W Rm,Rn 0110nnnnmmmm1111
1348 emith_sext(tmp2, tmp, 16);
1355 /////////////////////////////////////////////
1357 // ADD #imm,Rn 0111nnnniiiiiiii
1358 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1359 if (op & 0x80) { // adding negative
1360 emith_sub_r_imm(tmp, -op & 0xff);
1362 emith_add_r_imm(tmp, op & 0xff);
1365 /////////////////////////////////////////////
1367 switch (op & 0x0f00)
1369 case 0x0000: // MOV.B R0,@(disp,Rn) 10000000nnnndddd
1370 case 0x0100: // MOV.W R0,@(disp,Rn) 10000001nnnndddd
1372 tmp = rcache_get_reg_arg(0, GET_Rm());
1373 tmp2 = rcache_get_reg_arg(1, SHR_R0);
1374 tmp3 = (op & 0x100) >> 8;
1375 emith_add_r_imm(tmp, (op & 0x0f) << tmp3);
1376 emit_memhandler_write(tmp3);
1378 case 0x0400: // MOV.B @(disp,Rm),R0 10000100mmmmdddd
1379 case 0x0500: // MOV.W @(disp,Rm),R0 10000101mmmmdddd
1381 tmp = rcache_get_reg_arg(0, GET_Rm());
1382 tmp3 = (op & 0x100) >> 8;
1383 emith_add_r_imm(tmp, (op & 0x0f) << tmp3);
1384 tmp = emit_memhandler_read(tmp3);
1385 tmp2 = rcache_get_reg(0, RC_GR_WRITE);
1386 emith_sext(tmp2, tmp, 8 << tmp3);
1387 rcache_free_tmp(tmp);
1389 case 0x0800: // CMP/EQ #imm,R0 10001000iiiiiiii
1390 // XXX: could use cmn
1391 tmp = rcache_get_tmp();
1392 tmp2 = rcache_get_reg(0, RC_GR_READ);
1393 tmp3 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1394 emith_move_r_imm_s8(tmp, op & 0xff);
1395 emith_bic_r_imm(tmp3, T);
1396 emith_cmp_r_r(tmp2, tmp);
1397 emit_or_t_if_eq(tmp3);
1398 rcache_free_tmp(tmp);
1400 case 0x0d00: // BT/S label 10001101dddddddd
1401 case 0x0f00: // BF/S label 10001111dddddddd
1405 case 0x0900: // BT label 10001001dddddddd
1406 case 0x0b00: { // BF label 10001011dddddddd
1407 // jmp_cond ~ cond when guest doesn't jump
1408 int jmp_cond = (op & 0x0200) ? DCOND_NE : DCOND_EQ;
1409 int insn_cond = (op & 0x0200) ? DCOND_EQ : DCOND_NE;
1410 signed int offs = ((signed int)(op << 24) >> 23);
1411 tmp = rcache_get_reg(delayed_op ? SHR_PPC : SHR_PC, RC_GR_WRITE);
1412 emith_move_r_imm(tmp, pc + (delayed_op ? 2 : 0));
1414 EMITH_SJMP_START(jmp_cond);
1418 emith_sub_r_imm_c(insn_cond, tmp, -offs);
1420 emith_add_r_imm_c(insn_cond, tmp, offs);
1421 EMITH_SJMP_END(jmp_cond);
1429 /////////////////////////////////////////////
1431 // MOV.W @(disp,PC),Rn 1001nnnndddddddd
1435 /////////////////////////////////////////////
1437 // BRA label 1010dddddddddddd
1440 tmp = ((signed int)(op << 20) >> 19);
1441 emit_move_r_imm32(SHR_PPC, pc + tmp + 2);
1445 /////////////////////////////////////////////
1447 // BSR label 1011dddddddddddd
1449 emit_move_r_imm32(SHR_PR, pc + 2);
1452 /////////////////////////////////////////////
1454 switch (op & 0x0f00)
1456 case 0x0000: // MOV.B R0,@(disp,GBR) 11000000dddddddd
1457 case 0x0100: // MOV.W R0,@(disp,GBR) 11000001dddddddd
1458 case 0x0200: // MOV.L R0,@(disp,GBR) 11000010dddddddd
1460 tmp = rcache_get_reg_arg(0, SHR_GBR);
1461 tmp2 = rcache_get_reg_arg(1, SHR_R0);
1462 tmp3 = (op & 0x300) >> 8;
1463 emith_add_r_imm(tmp, (op & 0xff) << tmp3);
1464 emit_memhandler_write(tmp3);
1466 case 0x0400: // MOV.B @(disp,GBR),R0 11000100dddddddd
1467 case 0x0500: // MOV.W @(disp,GBR),R0 11000101dddddddd
1468 case 0x0600: // MOV.L @(disp,GBR),R0 11000110dddddddd
1470 tmp = rcache_get_reg_arg(0, SHR_GBR);
1471 tmp3 = (op & 0x300) >> 8;
1472 emith_add_r_imm(tmp, (op & 0xff) << tmp3);
1473 tmp = emit_memhandler_read(tmp3);
1474 tmp2 = rcache_get_reg(0, RC_GR_WRITE);
1476 emith_sext(tmp2, tmp, 8 << tmp3);
1478 emith_move_r_r(tmp2, tmp);
1479 rcache_free_tmp(tmp);
1481 case 0x0300: // TRAPA #imm 11000011iiiiiiii
1482 tmp = rcache_get_reg(SHR_SP, RC_GR_RMW);
1483 emith_sub_r_imm(tmp, 4*2);
1486 tmp = rcache_get_reg_arg(0, SHR_SP);
1487 emith_add_r_imm(tmp, 4);
1488 tmp = rcache_get_reg_arg(1, SHR_SR);
1489 emith_clear_msb(tmp, tmp, 20);
1490 emit_memhandler_write(2);
1492 rcache_get_reg_arg(0, SHR_SP);
1493 tmp = rcache_get_tmp_arg(1);
1494 emith_move_r_imm(tmp, pc);
1495 emit_memhandler_write(2);
1497 tmp = rcache_get_reg_arg(0, SHR_VBR);
1498 emith_add_r_imm(tmp, (op & 0xff) * 4);
1499 tmp = emit_memhandler_read(2);
1500 tmp2 = rcache_get_reg(SHR_PC, RC_GR_WRITE);
1501 emith_move_r_r(tmp2, tmp);
1502 rcache_free_tmp(tmp);
1505 case 0x0700: // MOVA @(disp,PC),R0 11000111dddddddd
1506 emit_move_r_imm32(SHR_R0, (pc + (op & 0xff) * 4 + 2) & ~3);
1508 case 0x0800: // TST #imm,R0 11001000iiiiiiii
1509 tmp = rcache_get_reg(SHR_R0, RC_GR_READ);
1510 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1511 emith_bic_r_imm(tmp2, T);
1512 emith_tst_r_imm(tmp, op & 0xff);
1513 emit_or_t_if_eq(tmp2);
1515 case 0x0900: // AND #imm,R0 11001001iiiiiiii
1516 tmp = rcache_get_reg(SHR_R0, RC_GR_RMW);
1517 emith_and_r_imm(tmp, op & 0xff);
1519 case 0x0a00: // XOR #imm,R0 11001010iiiiiiii
1520 tmp = rcache_get_reg(SHR_R0, RC_GR_RMW);
1521 emith_eor_r_imm(tmp, op & 0xff);
1523 case 0x0b00: // OR #imm,R0 11001011iiiiiiii
1524 tmp = rcache_get_reg(SHR_R0, RC_GR_RMW);
1525 emith_or_r_imm(tmp, op & 0xff);
1527 case 0x0c00: // TST.B #imm,@(R0,GBR) 11001100iiiiiiii
1528 tmp = emit_indirect_indexed_read(SHR_R0, SHR_GBR, 0);
1529 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1530 emith_bic_r_imm(tmp2, T);
1531 emith_tst_r_imm(tmp, op & 0xff);
1532 emit_or_t_if_eq(tmp2);
1533 rcache_free_tmp(tmp);
1536 case 0x0d00: // AND.B #imm,@(R0,GBR) 11001101iiiiiiii
1537 tmp = emit_indirect_indexed_read(SHR_R0, SHR_GBR, 0);
1538 emith_and_r_imm(tmp, op & 0xff);
1539 emit_indirect_indexed_write(SHR_R0, SHR_GBR, tmp, 0);
1542 case 0x0e00: // XOR.B #imm,@(R0,GBR) 11001110iiiiiiii
1543 tmp = emit_indirect_indexed_read(SHR_R0, SHR_GBR, 0);
1544 emith_eor_r_imm(tmp, op & 0xff);
1545 emit_indirect_indexed_write(SHR_R0, SHR_GBR, tmp, 0);
1548 case 0x0f00: // OR.B #imm,@(R0,GBR) 11001111iiiiiiii
1549 tmp = emit_indirect_indexed_read(SHR_R0, SHR_GBR, 0);
1550 emith_or_r_imm(tmp, op & 0xff);
1551 emit_indirect_indexed_write(SHR_R0, SHR_GBR, tmp, 0);
1557 /////////////////////////////////////////////
1559 // MOV.L @(disp,PC),Rn 1101nnnndddddddd
1563 /////////////////////////////////////////////
1565 // MOV #imm,Rn 1110nnnniiiiiiii
1566 tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
1567 emith_move_r_imm_s8(tmp, op & 0xff);
1572 emit_move_r_imm32(SHR_PC, pc - 2);
1574 emith_pass_arg_r(0, CONTEXT_REG);
1575 emith_pass_arg_imm(1, op);
1576 emith_call(sh2_do_op);
1581 if (delayed_op == 1)
1582 emit_move_r_r(SHR_PC, SHR_PPC);
1584 if (test_irq && delayed_op != 2) {
1586 emith_pass_arg_r(0, CONTEXT_REG);
1587 emith_call(sh2_test_irq);
1590 if (delayed_op == 1)
1593 do_host_disasm(tcache_id);
1596 // delayed_op means some kind of branch - PC already handled
1598 emit_move_r_imm32(SHR_PC, pc);
1601 this_block->end_addr = pc;
1603 // mark memory blocks as containing compiled code
1604 if ((sh2->pc & 0xe0000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
1606 u16 *drcblk = Pico32xMem->drcblk_da[sh2->is_slave];
1607 tmp = (this_block->addr & 0xfff) >> SH2_DRCBLK_DA_SHIFT;
1608 tmp2 = (this_block->end_addr & 0xfff) >> SH2_DRCBLK_DA_SHIFT;
1609 Pico32xMem->drcblk_da[sh2->is_slave][tmp] = (blkid << 1) | 1;
1610 for (++tmp; tmp < tmp2; tmp++) {
1612 break; // dont overwrite overlay block
1613 drcblk[tmp] = blkid << 1;
1616 else if ((this_block->addr & 0xc7fc0000) == 0x06000000) { // DRAM
1617 tmp = (this_block->addr & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT;
1618 tmp2 = (this_block->end_addr & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT;
1619 Pico32xMem->drcblk_ram[tmp] = (blkid << 1) | 1;
1620 for (++tmp; tmp < tmp2; tmp++) {
1621 if (Pico32xMem->drcblk_ram[tmp])
1623 Pico32xMem->drcblk_ram[tmp] = blkid << 1;
1627 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
1628 emith_sub_r_imm(tmp, cycles << 12);
1630 emith_jump(sh2_drc_exit);
1631 tcache_ptrs[tcache_id] = tcache_ptr;
1634 cache_flush_d_inval_i(block_entry, tcache_ptr);
1637 do_host_disasm(tcache_id);
1638 dbg(1, " block #%d,%d tcache %d/%d, insns %d -> %d %.3f",
1639 tcache_id, block_counts[tcache_id],
1640 tcache_ptr - tcache_bases[tcache_id], tcache_sizes[tcache_id],
1641 insns_compiled, host_insn_count, (double)host_insn_count / insns_compiled);
1642 if ((sh2->pc & 0xc6000000) == 0x02000000) // ROM
1643 dbg(1, " hash collisions %d/%d", hash_collisions, block_counts[tcache_id]);
1652 do_host_disasm(tcache_id);
1657 void __attribute__((noinline)) sh2_drc_dispatcher(SH2 *sh2)
1659 // TODO: need to handle self-caused interrupts
1662 while (((signed int)sh2->sr >> 12) > 0)
1665 block_desc *bd = NULL;
1667 // FIXME: must avoid doing it so often..
1668 //sh2_test_irq(sh2);
1670 // we have full block id tables for data_array and RAM
1671 // BIOS goes to data_array table too
1672 if ((sh2->pc & 0xff000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
1673 int blkid = Pico32xMem->drcblk_da[sh2->is_slave][(sh2->pc & 0xfff) >> SH2_DRCBLK_DA_SHIFT];
1675 bd = &block_tables[1 + sh2->is_slave][blkid >> 1];
1676 block = bd->tcache_ptr;
1680 else if ((sh2->pc & 0xc6000000) == 0x06000000) {
1681 int blkid = Pico32xMem->drcblk_ram[(sh2->pc & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT];
1683 bd = &block_tables[0][blkid >> 1];
1684 block = bd->tcache_ptr;
1688 else if ((sh2->pc & 0xc6000000) == 0x02000000) {
1689 bd = HASH_FUNC(hash_table, sh2->pc);
1692 if (bd->addr == sh2->pc)
1693 block = bd->tcache_ptr;
1695 block = dr_find_block(bd, sh2->pc);
1700 block = sh2_translate(sh2, bd);
1702 dbg(4, "= %csh2 enter %08x %p, c=%d", sh2->is_slave ? 's' : 'm',
1703 sh2->pc, block, (signed int)sh2->sr >> 12);
1708 sh2_drc_entry(sh2, block);
1712 static void sh2_smc_rm_block(u16 *drcblk, u16 *p, block_desc *btab, u32 a)
1715 block_desc *bd = btab + id;
1717 dbg(1, " killing block %08x", bd->addr);
1718 bd->addr = bd->end_addr = 0;
1720 while (p > drcblk && (p[-1] >> 1) == id)
1723 // check for possible overlay block
1724 if (p > 0 && p[-1] != 0) {
1725 bd = btab + (p[-1] >> 1);
1726 if (bd->addr <= a && a < bd->end_addr)
1727 sh2_smc_rm_block(drcblk, p - 1, btab, a);
1733 while ((*p >> 1) == id);
1736 void sh2_drc_wcheck_ram(unsigned int a, int val, int cpuid)
1738 u16 *drcblk = Pico32xMem->drcblk_ram;
1739 u16 *p = drcblk + ((a & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT);
1741 dbg(1, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a);
1742 sh2_smc_rm_block(drcblk, p, block_tables[0], a);
1745 void sh2_drc_wcheck_da(unsigned int a, int val, int cpuid)
1747 u16 *drcblk = Pico32xMem->drcblk_da[cpuid];
1748 u16 *p = drcblk + ((a & 0xfff) >> SH2_DRCBLK_DA_SHIFT);
1750 dbg(1, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a);
1751 sh2_smc_rm_block(drcblk, p, block_tables[1 + cpuid], a);
1754 void sh2_execute(SH2 *sh2c, int cycles)
1758 sh2c->cycles_aim += cycles;
1759 cycles = sh2c->cycles_aim - sh2c->cycles_done;
1761 // cycles are kept in SHR_SR unused bits (upper 20)
1763 sh2c->sr |= cycles << 12;
1764 sh2_drc_dispatcher(sh2c);
1766 sh2c->cycles_done += cycles - ((signed int)sh2c->sr >> 12);
1769 static void REGPARM(1) sh2_test_irq(SH2 *sh2)
1771 if (sh2->pending_level > ((sh2->sr >> 4) & 0x0f))
1773 if (sh2->pending_irl > sh2->pending_int_irq)
1774 sh2_do_irq(sh2, sh2->pending_irl, 64 + sh2->pending_irl/2);
1776 sh2_do_irq(sh2, sh2->pending_int_irq, sh2->pending_int_vector);
1777 sh2->pending_int_irq = 0; // auto-clear
1778 sh2->pending_level = sh2->pending_irl;
1784 static void block_stats(void)
1786 int c, b, i, total = 0;
1788 for (b = 0; b < ARRAY_SIZE(block_tables); b++)
1789 for (i = 0; i < block_counts[b]; i++)
1790 if (block_tables[b][i].addr != 0)
1791 total += block_tables[b][i].refcount;
1793 for (c = 0; c < 10; c++) {
1794 block_desc *blk, *maxb = NULL;
1796 for (b = 0; b < ARRAY_SIZE(block_tables); b++) {
1797 for (i = 0; i < block_counts[b]; i++) {
1798 blk = &block_tables[b][i];
1799 if (blk->addr != 0 && blk->refcount > max) {
1800 max = blk->refcount;
1807 printf("%08x %9d %2.3f%%\n", maxb->addr, maxb->refcount,
1808 (double)maxb->refcount / total * 100.0);
1812 for (b = 0; b < ARRAY_SIZE(block_tables); b++)
1813 for (i = 0; i < block_counts[b]; i++)
1814 block_tables[b][i].refcount = 0;
1817 #define block_stats()
1820 void sh2_drc_flush_all(void)
1828 int sh2_drc_init(SH2 *sh2)
1830 if (block_tables[0] == NULL) {
1835 cnt = block_max_counts[0] + block_max_counts[1] + block_max_counts[2];
1836 block_tables[0] = calloc(cnt, sizeof(*block_tables[0]));
1837 if (block_tables[0] == NULL)
1840 memset(block_counts, 0, sizeof(block_counts));
1841 tcache_bases[0] = tcache_ptrs[0] = tcache;
1843 for (i = 1; i < ARRAY_SIZE(block_tables); i++) {
1844 block_tables[i] = block_tables[i - 1] + block_max_counts[i - 1];
1845 tcache_bases[i] = tcache_ptrs[i] = tcache_bases[i - 1] + tcache_sizes[i - 1];
1849 PicoOpt |= POPT_DIS_VDP_FIFO;
1852 for (i = 0; i < ARRAY_SIZE(block_tables); i++)
1853 tcache_dsm_ptrs[i] = tcache_bases[i];
1856 hash_collisions = 0;
1860 if (hash_table == NULL) {
1861 hash_table = calloc(sizeof(hash_table[0]), MAX_HASH_ENTRIES);
1862 if (hash_table == NULL)
1869 void sh2_drc_finish(SH2 *sh2)
1871 if (block_tables[0] != NULL) {
1873 free(block_tables[0]);
1874 memset(block_tables, 0, sizeof(block_tables));
1879 if (hash_table != NULL) {