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_R15 = 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 int hr = rcache_get_reg(dst, RC_GR_WRITE);
435 emith_move_r_imm(hr, imm);
438 static void emit_move_r_r(sh2_reg_e dst, sh2_reg_e src)
440 int hr_d = rcache_get_reg(dst, RC_GR_WRITE);
441 int hr_s = rcache_get_reg(src, RC_GR_READ);
443 emith_move_r_r(hr_d, hr_s);
446 // arguments must be ready
447 // reg cache must be clean before call
448 static int emit_memhandler_read(int size)
451 host_arg2reg(ctxr, 1);
452 emith_move_r_r(ctxr, CONTEXT_REG);
455 emith_call(p32x_sh2_read8);
458 emith_call(p32x_sh2_read16);
461 emith_call(p32x_sh2_read32);
465 // assuming arg0 and retval reg matches
466 return rcache_get_tmp_arg(0);
469 static void emit_memhandler_write(int size)
472 host_arg2reg(ctxr, 2);
473 emith_move_r_r(ctxr, CONTEXT_REG);
476 emith_call(p32x_sh2_write8);
479 emith_call(p32x_sh2_write16);
482 emith_call(p32x_sh2_write32);
489 MOV #imm,Rn 1110nnnniiiiiiii
490 MOV.W @(disp,PC),Rn 1001nnnndddddddd
491 MOV.L @(disp,PC),Rn 1101nnnndddddddd
492 MOV Rm,Rn 0110nnnnmmmm0011
493 MOV.B @Rm,Rn 0110nnnnmmmm0000
494 MOV.W @Rm,Rn 0110nnnnmmmm0001
495 MOV.L @Rm,Rn 0110nnnnmmmm0010
496 MOV.B @Rm+,Rn 0110nnnnmmmm0100
497 MOV.W @Rm+,Rn 0110nnnnmmmm0101
498 MOV.L @Rm+,Rn 0110nnnnmmmm0110
499 MOV.B R0,@(disp,Rn) 10000000nnnndddd
500 MOV.W R0,@(disp,Rn) 10000001nnnndddd
501 MOV.B @(disp,Rm),R0 10000100mmmmdddd
502 MOV.W @(disp,Rm),R0 10000101mmmmdddd
503 MOV.L @(disp,Rm),Rn 0101nnnnmmmmdddd
504 MOV.B R0,@(disp,GBR) 11000000dddddddd
505 MOV.W R0,@(disp,GBR) 11000001dddddddd
506 MOV.L R0,@(disp,GBR) 11000010dddddddd
507 MOV.B @(disp,GBR),R0 11000100dddddddd
508 MOV.W @(disp,GBR),R0 11000101dddddddd
509 MOV.L @(disp,GBR),R0 11000110dddddddd
510 MOVA @(disp,PC),R0 11000111dddddddd
511 SWAP.B Rm,Rn 0110nnnnmmmm1000
512 SWAP.W Rm,Rn 0110nnnnmmmm1001
513 ADD #imm,Rn 0111nnnniiiiiiii
514 CMP/EQ #imm,R0 10001000iiiiiiii
515 CMP/PZ Rn 0100nnnn00010001
516 CMP/PL Rn 0100nnnn00010101
517 EXTS.B Rm,Rn 0110nnnnmmmm1110
518 EXTS.W Rm,Rn 0110nnnnmmmm1111
519 EXTU.B Rm,Rn 0110nnnnmmmm1100
520 EXTU.W Rm,Rn 0110nnnnmmmm1101
521 MAC @Rm+,@Rn+ 0100nnnnmmmm1111
522 NEG Rm,Rn 0110nnnnmmmm1011
523 NEGC Rm,Rn 0110nnnnmmmm1010
524 AND #imm,R0 11001001iiiiiiii
525 AND.B #imm,@(R0,GBR) 11001101iiiiiiii
526 NOT Rm,Rn 0110nnnnmmmm0111
527 OR #imm,R0 11001011iiiiiiii
528 OR.B #imm,@(R0,GBR) 11001111iiiiiiii
529 TAS.B @Rn 0100nnnn00011011
530 TST #imm,R0 11001000iiiiiiii
531 TST.B #imm,@(R0,GBR) 11001100iiiiiiii
532 XOR #imm,R0 11001010iiiiiiii
533 XOR.B #imm,@(R0,GBR) 11001110iiiiiiii
534 ROTL Rn 0100nnnn00000100
535 ROTR Rn 0100nnnn00000101
536 ROTCL Rn 0100nnnn00100100
537 ROTCR Rn 0100nnnn00100101
538 SHAR Rn 0100nnnn00100001
539 SHLR Rn 0100nnnn00000001
540 SHLL2 Rn 0100nnnn00001000
541 SHLR2 Rn 0100nnnn00001001
542 SHLL8 Rn 0100nnnn00011000
543 SHLR8 Rn 0100nnnn00011001
544 SHLL16 Rn 0100nnnn00101000
545 SHLR16 Rn 0100nnnn00101001
546 LDC Rm,GBR 0100mmmm00011110
547 LDC Rm,VBR 0100mmmm00101110
548 LDC.L @Rm+,GBR 0100mmmm00010111
549 LDC.L @Rm+,VBR 0100mmmm00100111
550 LDS Rm,MACH 0100mmmm00001010
551 LDS Rm,MACL 0100mmmm00011010
552 LDS Rm,PR 0100mmmm00101010
553 LDS.L @Rm+,MACH 0100mmmm00000110
554 LDS.L @Rm+,MACL 0100mmmm00010110
555 LDS.L @Rm+,PR 0100mmmm00100110
556 STC.L SR,@–Rn 0100nnnn00000011
557 STC.L GBR,@–Rn 0100nnnn00010011
558 STC.L VBR,@–Rn 0100nnnn00100011
559 STS.L MACH,@–Rn 0100nnnn00000010
560 STS.L MACL,@–Rn 0100nnnn00010010
561 STS.L PR,@–Rn 0100nnnn00100010
562 TRAPA #imm 11000011iiiiiiii
568 #define CHECK_UNHANDLED_BITS(mask) { \
569 if ((op & (mask)) != 0) \
576 #define GET_Rm GET_Fx
581 #define CHECK_FX_GT_3() \
585 static void *sh2_translate(SH2 *sh2, block_desc *other_block)
588 block_desc *this_block;
589 unsigned int pc = sh2->pc;
590 int op, delayed_op = 0, test_irq = 0;
591 int tcache_id = 0, blkid = 0;
593 u32 tmp, tmp2, tmp3, tmp4;
597 if ((tmp != 0 && tmp != 1 && tmp != 6) || sh2->pc == 0) {
598 printf("invalid PC, aborting: %08x\n", sh2->pc);
599 // FIXME: be less destructive
603 if ((sh2->pc & 0xe0000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
604 // data_array, BIOS have separate tcache (shared)
605 tcache_id = 1 + sh2->is_slave;
608 tcache_ptr = tcache_ptrs[tcache_id];
609 this_block = dr_add_block(pc, tcache_id, &blkid);
611 tmp = tcache_ptr - tcache_bases[tcache_id];
612 if (tmp > tcache_sizes[tcache_id] - MAX_BLOCK_SIZE || this_block == NULL) {
613 flush_tcache(tcache_id);
614 tcache_ptr = tcache_ptrs[tcache_id];
615 other_block = NULL; // also gone too due to flush
616 this_block = dr_add_block(pc, tcache_id, &blkid);
619 this_block->next = other_block;
620 if ((sh2->pc & 0xc6000000) == 0x02000000) // ROM
621 HASH_FUNC(hash_table, pc) = this_block;
623 block_entry = tcache_ptr;
625 printf("== %csh2 block #%d,%d %08x -> %p\n", sh2->is_slave ? 's' : 'm',
626 tcache_id, block_counts[tcache_id], pc, block_entry);
627 if (other_block != NULL) {
628 printf(" hash collision with %08x\n", other_block->addr);
633 while (cycles < BLOCK_CYCLE_LIMIT || delayed_op)
638 op = p32x_sh2_read16(pc, sh2);
643 DasmSH2(sh2dasm_buff, pc, op);
644 printf("%08x %04x %s\n", pc, op, sh2dasm_buff);
651 switch ((op >> 12) & 0x0f)
653 /////////////////////////////////////////////
658 tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
661 case 0: // STC SR,Rn 0000nnnn00000010
664 case 1: // STC GBR,Rn 0000nnnn00010010
667 case 2: // STC VBR,Rn 0000nnnn00100010
673 tmp2 = rcache_get_reg(tmp2, RC_GR_READ);
674 emith_move_r_r(tmp, tmp2);
677 CHECK_UNHANDLED_BITS(0xd0);
678 // BRAF Rm 0000mmmm00100011
679 // BSRF Rm 0000mmmm00000011
682 emit_move_r_imm32(SHR_PR, pc + 2);
683 tmp = rcache_get_reg(SHR_PPC, RC_GR_WRITE);
684 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
685 emith_move_r_r(tmp, tmp2);
686 emith_add_r_imm(tmp, pc + 2);
689 case 0x04: // MOV.B Rm,@(R0,Rn) 0000nnnnmmmm0100
690 case 0x05: // MOV.W Rm,@(R0,Rn) 0000nnnnmmmm0101
691 case 0x06: // MOV.L Rm,@(R0,Rn) 0000nnnnmmmm0110
693 tmp = rcache_get_reg_arg(0, SHR_R0);
694 tmp2 = rcache_get_reg_arg(1, GET_Rm());
695 tmp3 = rcache_get_reg(GET_Rn(), RC_GR_READ);
696 emith_add_r_r(tmp, tmp3);
697 emit_memhandler_write(op & 3);
700 // MUL.L Rm,Rn 0000nnnnmmmm0111
701 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
702 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
703 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
704 emith_mul(tmp3, tmp2, tmp);
708 CHECK_UNHANDLED_BITS(0xf00);
711 case 0: // CLRT 0000000000001000
712 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
713 emith_bic_r_imm(tmp, T);
715 case 1: // SETT 0000000000011000
716 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
717 emith_or_r_imm(tmp, T);
719 case 2: // CLRMAC 0000000000101000
720 tmp = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
721 emith_move_r_imm(tmp, 0);
722 tmp = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
723 emith_move_r_imm(tmp, 0);
732 case 0: // NOP 0000000000001001
733 CHECK_UNHANDLED_BITS(0xf00);
735 case 1: // DIV0U 0000000000011001
736 CHECK_UNHANDLED_BITS(0xf00);
737 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
738 emith_bic_r_imm(tmp, M|Q|T);
740 case 2: // MOVT Rn 0000nnnn00101001
741 tmp = rcache_get_reg(SHR_SR, RC_GR_READ);
742 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
743 emith_clear_msb(tmp2, tmp, 31);
750 tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
753 case 0: // STS MACH,Rn 0000nnnn00001010
754 tmp2 = rcache_get_reg(SHR_MACH, RC_GR_READ);
756 case 1: // STS MACL,Rn 0000nnnn00011010
757 tmp2 = rcache_get_reg(SHR_MACL, RC_GR_READ);
759 case 2: // STS PR,Rn 0000nnnn00101010
760 tmp2 = rcache_get_reg(SHR_PR, RC_GR_READ);
765 emith_move_r_r(tmp, tmp2);
768 CHECK_UNHANDLED_BITS(0xf00);
771 case 0: // RTS 0000000000001011
773 emit_move_r_r(SHR_PPC, SHR_PR);
776 case 1: // SLEEP 0000000000011011
777 emit_move_r_imm32(SHR_PC, pc - 2);
778 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
779 emith_clear_msb(tmp, tmp, 20); // clear cycles
783 case 2: // RTE 0000000000101011
784 //emit_move_r_r(SHR_PC, SHR_PR);
785 emit_move_r_imm32(SHR_PC, pc - 2);
787 emith_pass_arg_r(0, CONTEXT_REG);
788 emith_pass_arg_imm(1, op);
789 emith_call(sh2_do_op);
790 emit_move_r_r(SHR_PPC, SHR_PC);
798 case 0x0c: // MOV.B @(R0,Rm),Rn 0000nnnnmmmm1100
799 case 0x0d: // MOV.W @(R0,Rm),Rn 0000nnnnmmmm1101
800 case 0x0e: // MOV.L @(R0,Rm),Rn 0000nnnnmmmm1110
802 tmp = rcache_get_reg_arg(0, SHR_R0);
803 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
804 emith_add_r_r(tmp, tmp2);
805 tmp = emit_memhandler_read(op & 3);
806 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
807 rcache_free_tmp(tmp);
809 emith_sext(tmp2, tmp, (op & 1) ? 16 : 8);
811 emith_move_r_r(tmp2, tmp);
813 case 0x0f: // MAC.L @Rm+,@Rn+ 0000nnnnmmmm1111
819 /////////////////////////////////////////////
821 // MOV.L Rm,@(disp,Rn) 0001nnnnmmmmdddd
823 tmp = rcache_get_reg_arg(0, GET_Rn());
824 tmp2 = rcache_get_reg_arg(1, GET_Rm());
825 emith_add_r_imm(tmp, (op & 0x0f) * 4);
826 emit_memhandler_write(2);
832 case 0x00: // MOV.B Rm,@Rn 0010nnnnmmmm0000
833 case 0x01: // MOV.W Rm,@Rn 0010nnnnmmmm0001
834 case 0x02: // MOV.L Rm,@Rn 0010nnnnmmmm0010
836 rcache_get_reg_arg(0, GET_Rn());
837 rcache_get_reg_arg(1, GET_Rm());
838 emit_memhandler_write(op & 3);
840 case 0x04: // MOV.B Rm,@–Rn 0010nnnnmmmm0100
841 case 0x05: // MOV.W Rm,@–Rn 0010nnnnmmmm0101
842 case 0x06: // MOV.L Rm,@–Rn 0010nnnnmmmm0110
843 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
844 emith_sub_r_imm(tmp, (1 << (op & 3)));
846 rcache_get_reg_arg(0, GET_Rn());
847 rcache_get_reg_arg(1, GET_Rm());
848 emit_memhandler_write(op & 3);
850 case 0x07: // DIV0S Rm,Rn 0010nnnnmmmm0111
851 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
852 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
853 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
854 emith_bic_r_imm(tmp, M|Q|T);
855 emith_tst_r_imm(tmp2, (1<<31));
856 EMITH_SJMP_START(DCOND_EQ);
857 emith_or_r_imm_c(DCOND_NE, tmp, Q);
858 EMITH_SJMP_END(DCOND_EQ);
859 emith_tst_r_imm(tmp3, (1<<31));
860 EMITH_SJMP_START(DCOND_EQ);
861 emith_or_r_imm_c(DCOND_NE, tmp, M);
862 EMITH_SJMP_END(DCOND_EQ);
863 emith_teq_r_r(tmp2, tmp3);
864 EMITH_SJMP_START(DCOND_PL);
865 emith_or_r_imm_c(DCOND_MI, tmp, T);
866 EMITH_SJMP_END(DCOND_PL);
868 case 0x08: // TST Rm,Rn 0010nnnnmmmm1000
869 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
870 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
871 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
872 emith_bic_r_imm(tmp, T);
873 emith_tst_r_r(tmp2, tmp3);
874 EMITH_SJMP_START(DCOND_NE);
875 emith_or_r_imm_c(DCOND_EQ, tmp, T);
876 EMITH_SJMP_END(DCOND_NE);
878 case 0x09: // AND Rm,Rn 0010nnnnmmmm1001
879 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
880 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
881 emith_and_r_r(tmp, tmp2);
883 case 0x0a: // XOR Rm,Rn 0010nnnnmmmm1010
884 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
885 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
886 emith_eor_r_r(tmp, tmp2);
888 case 0x0b: // OR Rm,Rn 0010nnnnmmmm1011
889 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
890 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
891 emith_or_r_r(tmp, tmp2);
893 case 0x0c: // CMP/STR Rm,Rn 0010nnnnmmmm1100
894 tmp = rcache_get_tmp();
895 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
896 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
897 emith_eor_r_r_r(tmp, tmp2, tmp3);
898 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
899 emith_bic_r_imm(tmp2, T);
900 emith_tst_r_imm(tmp, 0x000000ff);
901 EMITH_SJMP_START(DCOND_NE);
902 emith_or_r_imm_c(DCOND_EQ, tmp2, T);
903 EMITH_SJMP_END(DCOND_NE);
904 emith_tst_r_imm(tmp, 0x0000ff00);
905 EMITH_SJMP_START(DCOND_NE);
906 emith_or_r_imm_c(DCOND_EQ, tmp2, T);
907 EMITH_SJMP_END(DCOND_NE);
908 emith_tst_r_imm(tmp, 0x00ff0000);
909 EMITH_SJMP_START(DCOND_NE);
910 emith_or_r_imm_c(DCOND_EQ, tmp2, T);
911 EMITH_SJMP_END(DCOND_NE);
912 emith_tst_r_imm(tmp, 0xff000000);
913 EMITH_SJMP_START(DCOND_NE);
914 emith_or_r_imm_c(DCOND_EQ, tmp2, T);
915 EMITH_SJMP_END(DCOND_NE);
916 rcache_free_tmp(tmp);
918 case 0x0d: // XTRCT Rm,Rn 0010nnnnmmmm1101
919 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
920 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
921 emith_lsr(tmp, tmp, 16);
922 emith_or_r_r_r_lsl(tmp, tmp, tmp2, 16);
924 case 0x0e: // MULU.W Rm,Rn 0010nnnnmmmm1110
925 case 0x0f: // MULS.W Rm,Rn 0010nnnnmmmm1111
926 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
927 tmp = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
929 emith_sext(tmp, tmp2, 16);
931 emith_clear_msb(tmp, tmp2, 16);
932 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
933 tmp2 = rcache_get_tmp();
935 emith_sext(tmp2, tmp3, 16);
937 emith_clear_msb(tmp2, tmp3, 16);
938 emith_mul(tmp, tmp, tmp2);
939 rcache_free_tmp(tmp2);
940 // FIXME: causes timing issues in Doom?
946 /////////////////////////////////////////////
950 case 0x00: // CMP/EQ Rm,Rn 0011nnnnmmmm0000
951 case 0x02: // CMP/HS Rm,Rn 0011nnnnmmmm0010
952 case 0x03: // CMP/GE Rm,Rn 0011nnnnmmmm0011
953 case 0x06: // CMP/HI Rm,Rn 0011nnnnmmmm0110
954 case 0x07: // CMP/GT Rm,Rn 0011nnnnmmmm0111
955 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
956 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
957 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
958 emith_bic_r_imm(tmp, T);
959 emith_cmp_r_r(tmp2, tmp3);
963 EMITH_SJMP_START(DCOND_NE);
964 emith_or_r_imm_c(DCOND_EQ, tmp, T);
965 EMITH_SJMP_END(DCOND_NE);
968 EMITH_SJMP_START(DCOND_LO);
969 emith_or_r_imm_c(DCOND_HS, tmp, T);
970 EMITH_SJMP_END(DCOND_LO);
973 EMITH_SJMP_START(DCOND_LT);
974 emith_or_r_imm_c(DCOND_GE, tmp, T);
975 EMITH_SJMP_END(DCOND_LT);
978 EMITH_SJMP_START(DCOND_LS);
979 emith_or_r_imm_c(DCOND_HI, tmp, T);
980 EMITH_SJMP_END(DCOND_LS);
983 EMITH_SJMP_START(DCOND_LE);
984 emith_or_r_imm_c(DCOND_GT, tmp, T);
985 EMITH_SJMP_END(DCOND_LE);
989 case 0x04: // DIV1 Rm,Rn 0011nnnnmmmm0100
992 case 0x05: // DMULU.L Rm,Rn 0011nnnnmmmm0101
993 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
994 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
995 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
996 tmp4 = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
997 emith_mul_u64(tmp3, tmp4, tmp, tmp2);
999 case 0x08: // SUB Rm,Rn 0011nnnnmmmm1000
1000 case 0x0c: // ADD Rm,Rn 0011nnnnmmmm1100
1001 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1002 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1004 emith_add_r_r(tmp, tmp2);
1006 emith_sub_r_r(tmp, tmp2);
1008 case 0x0a: // SUBC Rm,Rn 0011nnnnmmmm1010
1009 case 0x0e: // ADDC Rm,Rn 0011nnnnmmmm1110
1010 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1011 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1012 tmp3 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1013 if (op & 4) { // adc
1014 emith_set_carry(tmp3);
1015 emith_adcf_r_r(tmp, tmp2);
1016 tmp = DCOND_CS; // set condition
1017 tmp2 = DCOND_CC; // clear condition
1019 emith_set_carry_sub(tmp3);
1020 emith_sbcf_r_r(tmp, tmp2);
1021 tmp = DCOND_LO; // using LO/HS instead of CS/CC
1022 tmp2 = DCOND_HS; // due to ARM target..
1024 EMITH_SJMP_START(tmp);
1025 emith_bic_r_imm_c(tmp2, tmp3, T);
1026 EMITH_SJMP_END(tmp);
1027 EMITH_SJMP_START(tmp2);
1028 emith_or_r_imm_c(tmp, tmp3, T);
1029 EMITH_SJMP_END(tmp2);
1031 case 0x0b: // SUBV Rm,Rn 0011nnnnmmmm1011
1032 case 0x0f: // ADDV Rm,Rn 0011nnnnmmmm1111
1033 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1034 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1035 tmp3 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1036 emith_bic_r_imm(tmp3, T);
1038 emith_addf_r_r(tmp, tmp2);
1040 emith_subf_r_r(tmp, tmp2);
1041 EMITH_SJMP_START(DCOND_VC);
1042 emith_or_r_imm_c(DCOND_VS, tmp3, T);
1043 EMITH_SJMP_END(DCOND_VC);
1045 case 0x0d: // DMULS.L Rm,Rn 0011nnnnmmmm1101
1046 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
1047 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1048 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
1049 tmp4 = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
1050 emith_mul_s64(tmp3, tmp4, tmp, tmp2);
1055 /////////////////////////////////////////////
1062 case 0: // SHLL Rn 0100nnnn00000000
1063 case 2: // SHAL Rn 0100nnnn00100000
1064 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1065 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1066 emith_bic_r_imm(tmp2, T);
1067 emith_lslf(tmp, tmp, 1);
1068 EMITH_SJMP_START(DCOND_CC);
1069 emith_or_r_imm_c(DCOND_CS, tmp2, T);
1070 EMITH_SJMP_END(DCOND_CC);
1072 case 1: // DT Rn 0100nnnn00010000
1073 if (p32x_sh2_read16(pc, sh2) == 0x8bfd) { // BF #-2
1074 emith_sh2_dtbf_loop();
1077 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1078 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1079 emith_bic_r_imm(tmp2, T);
1080 emith_subf_r_imm(tmp, 1);
1081 EMITH_SJMP_START(DCOND_NE);
1082 emith_or_r_imm_c(DCOND_EQ, tmp2, T);
1083 EMITH_SJMP_END(DCOND_NE);
1088 if ((op & 0xf0) != 0)
1090 // LDC.L @Rm+,SR 0100mmmm00000111
1094 if ((op & 0xd0) != 0)
1096 // JMP @Rm 0100mmmm00101011
1097 // JSR @Rm 0100mmmm00001011
1100 emit_move_r_imm32(SHR_PR, pc + 2);
1101 emit_move_r_r(SHR_PPC, (op >> 8) & 0x0f);
1105 if ((op & 0xf0) != 0)
1107 // LDC Rm,SR 0100mmmm00001110
1113 /////////////////////////////////////////////
1115 switch (op & 0x0f00) {
1116 // BT/S label 10001101dddddddd
1118 // BF/S label 10001111dddddddd
1123 // BT label 10001001dddddddd
1125 // BF label 10001011dddddddd
1127 // jmp_cond ~ cond when guest doesn't jump
1128 int jmp_cond = (op & 0x0200) ? DCOND_NE : DCOND_EQ;
1129 int insn_cond = (op & 0x0200) ? DCOND_EQ : DCOND_NE;
1130 signed int offs = ((signed int)(op << 24) >> 23);
1131 tmp = rcache_get_reg(delayed_op ? SHR_PPC : SHR_PC, RC_GR_WRITE);
1132 emith_move_r_imm(tmp, pc + (delayed_op ? 2 : 0));
1134 EMITH_SJMP_START(jmp_cond);
1138 emith_sub_r_imm_c(insn_cond, tmp, -offs);
1140 emith_add_r_imm_c(insn_cond, tmp, offs);
1141 EMITH_SJMP_END(jmp_cond);
1149 /////////////////////////////////////////////
1151 // BRA label 1010dddddddddddd
1154 tmp = ((signed int)(op << 20) >> 19);
1155 emit_move_r_imm32(SHR_PPC, pc + tmp + 2);
1159 /////////////////////////////////////////////
1161 // BSR label 1011dddddddddddd
1163 emit_move_r_imm32(SHR_PR, pc + 2);
1168 emit_move_r_imm32(SHR_PC, pc - 2);
1170 emith_pass_arg_r(0, CONTEXT_REG);
1171 emith_pass_arg_imm(1, op);
1172 emith_call(sh2_do_op);
1177 if (delayed_op == 1)
1178 emit_move_r_r(SHR_PC, SHR_PPC);
1180 if (test_irq && delayed_op != 2) {
1182 emith_pass_arg_r(0, CONTEXT_REG);
1183 emith_call(sh2_test_irq);
1186 if (delayed_op == 1)
1189 do_host_disasm(tcache_id);
1193 this_block->end_addr = pc;
1195 // mark memory blocks as containing compiled code
1196 if ((sh2->pc & 0xe0000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
1198 u16 *drcblk = Pico32xMem->drcblk_da[sh2->is_slave];
1199 tmp = (this_block->addr & 0xfff) >> SH2_DRCBLK_DA_SHIFT;
1200 tmp2 = (this_block->end_addr & 0xfff) >> SH2_DRCBLK_DA_SHIFT;
1201 Pico32xMem->drcblk_da[sh2->is_slave][tmp] = (blkid << 1) | 1;
1202 for (++tmp; tmp < tmp2; tmp++) {
1204 break; // dont overwrite overlay block
1205 drcblk[tmp] = blkid << 1;
1208 else if ((this_block->addr & 0xc7fc0000) == 0x06000000) { // DRAM
1209 tmp = (this_block->addr & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT;
1210 tmp2 = (this_block->end_addr & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT;
1211 Pico32xMem->drcblk_ram[tmp] = (blkid << 1) | 1;
1212 for (++tmp; tmp < tmp2; tmp++) {
1213 if (Pico32xMem->drcblk_ram[tmp])
1215 Pico32xMem->drcblk_ram[tmp] = blkid << 1;
1219 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
1220 emith_sub_r_imm(tmp, cycles << 12);
1222 emith_jump(sh2_drc_exit);
1223 tcache_ptrs[tcache_id] = tcache_ptr;
1226 cache_flush_d_inval_i(block_entry, tcache_ptr);
1229 do_host_disasm(tcache_id);
1230 dbg(1, " block #%d,%d tcache %d/%d, insns %d -> %d %.3f",
1231 tcache_id, block_counts[tcache_id],
1232 tcache_ptr - tcache_bases[tcache_id], tcache_sizes[tcache_id],
1233 insns_compiled, host_insn_count, (double)host_insn_count / insns_compiled);
1234 if ((sh2->pc & 0xc6000000) == 0x02000000) // ROM
1235 dbg(1, " hash collisions %d/%d", hash_collisions, block_counts[tcache_id]);
1244 do_host_disasm(tcache_id);
1249 void __attribute__((noinline)) sh2_drc_dispatcher(SH2 *sh2)
1251 while (((signed int)sh2->sr >> 12) > 0)
1254 block_desc *bd = NULL;
1256 // FIXME: must avoid doing it so often..
1259 // we have full block id tables for data_array and RAM
1260 // BIOS goes to data_array table too
1261 if ((sh2->pc & 0xff000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
1262 int blkid = Pico32xMem->drcblk_da[sh2->is_slave][(sh2->pc & 0xfff) >> SH2_DRCBLK_DA_SHIFT];
1264 bd = &block_tables[1 + sh2->is_slave][blkid >> 1];
1265 block = bd->tcache_ptr;
1269 else if ((sh2->pc & 0xc6000000) == 0x06000000) {
1270 int blkid = Pico32xMem->drcblk_ram[(sh2->pc & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT];
1272 bd = &block_tables[0][blkid >> 1];
1273 block = bd->tcache_ptr;
1277 else if ((sh2->pc & 0xc6000000) == 0x02000000) {
1278 bd = HASH_FUNC(hash_table, sh2->pc);
1281 if (bd->addr == sh2->pc)
1282 block = bd->tcache_ptr;
1284 block = dr_find_block(bd, sh2->pc);
1289 block = sh2_translate(sh2, bd);
1291 dbg(4, "= %csh2 enter %08x %p, c=%d", sh2->is_slave ? 's' : 'm',
1292 sh2->pc, block, (signed int)sh2->sr >> 12);
1297 sh2_drc_entry(sh2, block);
1301 static void sh2_smc_rm_block(u16 *drcblk, u16 *p, block_desc *btab, u32 a)
1304 block_desc *bd = btab + id;
1306 dbg(1, " killing block %08x", bd->addr);
1307 bd->addr = bd->end_addr = 0;
1309 while (p > drcblk && (p[-1] >> 1) == id)
1312 // check for possible overlay block
1313 if (p > 0 && p[-1] != 0) {
1314 bd = btab + (p[-1] >> 1);
1315 if (bd->addr <= a && a < bd->end_addr)
1316 sh2_smc_rm_block(drcblk, p - 1, btab, a);
1322 while ((*p >> 1) == id);
1325 void sh2_drc_wcheck_ram(unsigned int a, int val, int cpuid)
1327 u16 *drcblk = Pico32xMem->drcblk_ram;
1328 u16 *p = drcblk + ((a & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT);
1330 dbg(1, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a);
1331 sh2_smc_rm_block(drcblk, p, block_tables[0], a);
1334 void sh2_drc_wcheck_da(unsigned int a, int val, int cpuid)
1336 u16 *drcblk = Pico32xMem->drcblk_da[cpuid];
1337 u16 *p = drcblk + ((a & 0xfff) >> SH2_DRCBLK_DA_SHIFT);
1339 dbg(1, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a);
1340 sh2_smc_rm_block(drcblk, p, block_tables[1 + cpuid], a);
1343 void sh2_execute(SH2 *sh2, int cycles)
1345 sh2->cycles_aim += cycles;
1346 cycles = sh2->cycles_aim - sh2->cycles_done;
1348 // cycles are kept in SHR_SR unused bits (upper 20)
1350 sh2->sr |= cycles << 12;
1351 sh2_drc_dispatcher(sh2);
1353 sh2->cycles_done += cycles - ((signed int)sh2->sr >> 12);
1356 static void REGPARM(1) sh2_test_irq(SH2 *sh2)
1358 if (sh2->pending_level > ((sh2->sr >> 4) & 0x0f))
1360 if (sh2->pending_irl > sh2->pending_int_irq)
1361 sh2_do_irq(sh2, sh2->pending_irl, 64 + sh2->pending_irl/2);
1363 sh2_do_irq(sh2, sh2->pending_int_irq, sh2->pending_int_vector);
1364 sh2->pending_int_irq = 0; // auto-clear
1365 sh2->pending_level = sh2->pending_irl;
1371 static void block_stats(void)
1373 int c, b, i, total = 0;
1375 for (b = 0; b < ARRAY_SIZE(block_tables); b++)
1376 for (i = 0; i < block_counts[b]; i++)
1377 if (block_tables[b][i].addr != 0)
1378 total += block_tables[b][i].refcount;
1380 for (c = 0; c < 10; c++) {
1381 block_desc *blk, *maxb = NULL;
1383 for (b = 0; b < ARRAY_SIZE(block_tables); b++) {
1384 for (i = 0; i < block_counts[b]; i++) {
1385 blk = &block_tables[b][i];
1386 if (blk->addr != 0 && blk->refcount > max) {
1387 max = blk->refcount;
1394 printf("%08x %9d %2.3f%%\n", maxb->addr, maxb->refcount,
1395 (double)maxb->refcount / total * 100.0);
1399 for (b = 0; b < ARRAY_SIZE(block_tables); b++)
1400 for (i = 0; i < block_counts[b]; i++)
1401 block_tables[b][i].refcount = 0;
1404 #define block_stats()
1407 void sh2_drc_flush_all(void)
1415 int sh2_drc_init(SH2 *sh2)
1417 if (block_tables[0] == NULL) {
1422 cnt = block_max_counts[0] + block_max_counts[1] + block_max_counts[2];
1423 block_tables[0] = calloc(cnt, sizeof(*block_tables[0]));
1424 if (block_tables[0] == NULL)
1427 memset(block_counts, 0, sizeof(block_counts));
1428 tcache_bases[0] = tcache_ptrs[0] = tcache;
1430 for (i = 1; i < ARRAY_SIZE(block_tables); i++) {
1431 block_tables[i] = block_tables[i - 1] + block_max_counts[i - 1];
1432 tcache_bases[i] = tcache_ptrs[i] = tcache_bases[i - 1] + tcache_sizes[i - 1];
1436 PicoOpt |= POPT_DIS_VDP_FIFO;
1439 for (i = 0; i < ARRAY_SIZE(block_tables); i++)
1440 tcache_dsm_ptrs[i] = tcache_bases[i];
1443 hash_collisions = 0;
1447 if (hash_table == NULL) {
1448 hash_table = calloc(sizeof(hash_table[0]), MAX_HASH_ENTRIES);
1449 if (hash_table == NULL)
1456 void sh2_drc_finish(SH2 *sh2)
1458 if (block_tables[0] != NULL) {
1460 free(block_tables[0]);
1461 memset(block_tables, 0, sizeof(block_tables));
1466 if (hash_table != NULL) {