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 3?)
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
113 static temp_reg_t reg_temp[] = {
128 SHR_R0 = 0, SHR_R15 = 15,
129 SHR_PC, SHR_PPC, SHR_PR, SHR_SR,
130 SHR_GBR, SHR_VBR, SHR_MACH, SHR_MACL,
133 typedef struct block_desc_ {
134 u32 addr; // SH2 PC address
135 u32 end_addr; // TODO rm?
136 void *tcache_ptr; // translated block for above PC
137 struct block_desc_ *next; // next block with the same PC hash
143 static const int block_max_counts[3] = {
148 static block_desc *block_tables[3];
149 static int block_counts[3];
152 #define MAX_HASH_ENTRIES 1024
153 #define HASH_MASK (MAX_HASH_ENTRIES - 1)
154 static void **hash_table;
156 extern void sh2_drc_entry(SH2 *sh2, void *block);
157 extern void sh2_drc_exit(void);
160 extern void REGPARM(2) sh2_do_op(SH2 *sh2, int opcode);
161 static void REGPARM(1) sh2_test_irq(SH2 *sh2);
163 static void flush_tcache(int tcid)
165 dbg(1, "tcache #%d flush! (%d/%d, bds %d/%d)", tcid,
166 tcache_ptrs[tcid] - tcache_bases[tcid], tcache_sizes[tcid],
167 block_counts[tcid], block_max_counts[tcid]);
169 block_counts[tcid] = 0;
170 tcache_ptrs[tcid] = tcache_bases[tcid];
171 if (tcid == 0) { // ROM, RAM
172 memset(hash_table, 0, sizeof(hash_table[0]) * MAX_HASH_ENTRIES);
173 memset(Pico32xMem->drcblk_ram, 0, sizeof(Pico32xMem->drcblk_ram));
176 memset(Pico32xMem->drcblk_da[tcid - 1], 0, sizeof(Pico32xMem->drcblk_da[0]));
178 tcache_dsm_ptrs[tcid] = tcache_bases[tcid];
182 static void *dr_find_block(block_desc *tab, u32 addr)
184 for (tab = tab->next; tab != NULL; tab = tab->next)
185 if (tab->addr == addr)
189 return tab->tcache_ptr;
191 printf("block miss for %08x\n", addr);
195 static block_desc *dr_add_block(u32 addr, int tcache_id, int *blk_id)
197 int *bcount = &block_counts[tcache_id];
200 if (*bcount >= block_max_counts[tcache_id])
203 bd = &block_tables[tcache_id][*bcount];
205 bd->tcache_ptr = tcache_ptr;
212 #define HASH_FUNC(hash_tab, addr) \
213 ((block_desc **)(hash_tab))[(addr) & HASH_MASK]
215 // ---------------------------------------------------------------
218 static u16 rcache_counter;
220 static temp_reg_t *rcache_evict(void)
222 // evict reg with oldest stamp
224 u16 min_stamp = (u16)-1;
226 for (i = 0; i < ARRAY_SIZE(reg_temp); i++) {
227 if (reg_temp[i].type == HR_CACHED || reg_temp[i].type == HR_CACHED_DIRTY)
228 if (reg_temp[i].stamp <= min_stamp) {
229 min_stamp = reg_temp[i].stamp;
235 printf("no registers to evict, aborting\n");
240 if (reg_temp[i].type == HR_CACHED_DIRTY) {
242 emith_ctx_write(reg_temp[i].reg, reg_temp[i].val * 4);
254 // note: must not be called when doing conditional code
255 static int rcache_get_reg(sh2_reg_e r, rc_gr_mode mode)
260 // maybe already statically mapped?
267 // maybe already cached?
268 for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
269 if ((reg_temp[i].type == HR_CACHED || reg_temp[i].type == HR_CACHED_DIRTY) &&
270 reg_temp[i].val == r)
272 reg_temp[i].stamp = rcache_counter;
273 if (mode != RC_GR_READ)
274 reg_temp[i].type = HR_CACHED_DIRTY;
275 return reg_temp[i].reg;
280 for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
281 if (reg_temp[i].type == HR_FREE || reg_temp[i].type == HR_CONST) {
290 if (mode != RC_GR_WRITE)
291 emith_ctx_read(tr->reg, r * 4);
293 tr->type = mode != RC_GR_READ ? HR_CACHED_DIRTY : HR_CACHED;
295 tr->stamp = rcache_counter;
299 static int rcache_get_tmp(void)
304 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
305 if (reg_temp[i].type == HR_FREE || reg_temp[i].type == HR_CONST) {
317 static int rcache_get_arg_id(int arg)
320 host_arg2reg(r, arg);
322 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
323 if (reg_temp[i].reg == r)
326 if (i == ARRAY_SIZE(reg_temp))
327 // let's just say it's untracked arg reg
330 if (reg_temp[i].type == HR_CACHED_DIRTY) {
332 emith_ctx_write(reg_temp[i].reg, reg_temp[i].val * 4);
334 else if (reg_temp[i].type == HR_TEMP) {
335 printf("arg %d reg %d already used, aborting\n", arg, r);
342 // get a reg to be used as function arg
343 // it's assumed that regs are cleaned before call
344 static int rcache_get_tmp_arg(int arg)
346 int id = rcache_get_arg_id(arg);
347 reg_temp[id].type = HR_TEMP;
349 return reg_temp[id].reg;
352 // same but caches reg. RC_GR_READ only.
353 static int rcache_get_reg_arg(int arg, sh2_reg_e r)
355 int i, srcr, dstr, dstid;
357 dstid = rcache_get_arg_id(arg);
358 dstr = reg_temp[dstid].reg;
360 // maybe already statically mapped?
361 srcr = reg_map_g2h[r];
365 // maybe already cached?
366 for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
367 if ((reg_temp[i].type == HR_CACHED || reg_temp[i].type == HR_CACHED_DIRTY) &&
368 reg_temp[i].val == r)
370 srcr = reg_temp[i].reg;
377 emith_ctx_read(srcr, r * 4);
381 emith_move_r_r(dstr, srcr);
383 reg_temp[dstid].stamp = ++rcache_counter;
384 reg_temp[dstid].type = HR_CACHED;
385 reg_temp[dstid].val = r;
389 static void rcache_free_tmp(int hr)
392 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
393 if (reg_temp[i].reg == hr)
396 if (i == ARRAY_SIZE(reg_temp) || reg_temp[i].type != HR_TEMP) {
397 printf("rcache_free_tmp fail: #%i hr %d, type %d\n", i, hr, reg_temp[i].type);
401 reg_temp[i].type = HR_FREE;
404 static void rcache_clean(void)
407 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
408 if (reg_temp[i].type == HR_CACHED_DIRTY) {
410 emith_ctx_write(reg_temp[i].reg, reg_temp[i].val * 4);
411 reg_temp[i].type = HR_CACHED;
415 static void rcache_invalidate(void)
418 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
419 reg_temp[i].type = HR_FREE;
423 static void rcache_flush(void)
429 // ---------------------------------------------------------------
431 static void emit_move_r_imm32(sh2_reg_e dst, u32 imm)
433 int hr = rcache_get_reg(dst, RC_GR_WRITE);
434 emith_move_r_imm(hr, imm);
437 static void emit_move_r_r(sh2_reg_e dst, sh2_reg_e src)
439 int hr_d = rcache_get_reg(dst, RC_GR_WRITE);
440 int hr_s = rcache_get_reg(src, RC_GR_READ);
442 emith_move_r_r(hr_d, hr_s);
445 // arguments must be ready
446 // reg cache must be clean before call
447 static int emit_memhandler_read(int size)
450 host_arg2reg(ctxr, 1);
451 emith_move_r_r(ctxr, CONTEXT_REG);
454 emith_call(p32x_sh2_read8);
457 emith_call(p32x_sh2_read16);
460 emith_call(p32x_sh2_read32);
464 // assuming arg0 and retval reg matches
465 return rcache_get_tmp_arg(0);
468 static void emit_memhandler_write(int size)
471 host_arg2reg(ctxr, 2);
472 emith_move_r_r(ctxr, CONTEXT_REG);
475 emith_call(p32x_sh2_write8);
478 emith_call(p32x_sh2_write16);
481 emith_call(p32x_sh2_write32);
488 MOV #imm,Rn 1110nnnniiiiiiii
489 MOV.W @(disp,PC),Rn 1001nnnndddddddd
490 MOV.L @(disp,PC),Rn 1101nnnndddddddd
491 MOV Rm,Rn 0110nnnnmmmm0011
492 MOV.B @Rm,Rn 0110nnnnmmmm0000
493 MOV.W @Rm,Rn 0110nnnnmmmm0001
494 MOV.L @Rm,Rn 0110nnnnmmmm0010
495 MOV.B @Rm+,Rn 0110nnnnmmmm0100
496 MOV.W @Rm+,Rn 0110nnnnmmmm0101
497 MOV.L @Rm+,Rn 0110nnnnmmmm0110
498 MOV.B R0,@(disp,Rn) 10000000nnnndddd
499 MOV.W R0,@(disp,Rn) 10000001nnnndddd
500 MOV.B @(disp,Rm),R0 10000100mmmmdddd
501 MOV.W @(disp,Rm),R0 10000101mmmmdddd
502 MOV.L @(disp,Rm),Rn 0101nnnnmmmmdddd
503 MOV.B R0,@(disp,GBR) 11000000dddddddd
504 MOV.W R0,@(disp,GBR) 11000001dddddddd
505 MOV.L R0,@(disp,GBR) 11000010dddddddd
506 MOV.B @(disp,GBR),R0 11000100dddddddd
507 MOV.W @(disp,GBR),R0 11000101dddddddd
508 MOV.L @(disp,GBR),R0 11000110dddddddd
509 MOVA @(disp,PC),R0 11000111dddddddd
510 SWAP.B Rm,Rn 0110nnnnmmmm1000
511 SWAP.W Rm,Rn 0110nnnnmmmm1001
512 XTRCT Rm,Rn 0010nnnnmmmm1101
513 ADD Rm,Rn 0011nnnnmmmm1100
514 ADD #imm,Rn 0111nnnniiiiiiii
515 ADDC Rm,Rn 0011nnnnmmmm1110
516 ADDV Rm,Rn 0011nnnnmmmm1111
517 CMP/EQ #imm,R0 10001000iiiiiiii
518 CMP/EQ Rm,Rn 0011nnnnmmmm0000
519 CMP/HS Rm,Rn 0011nnnnmmmm0010
520 CMP/GE Rm,Rn 0011nnnnmmmm0011
521 CMP/HI Rm,Rn 0011nnnnmmmm0110
522 CMP/GT Rm,Rn 0011nnnnmmmm0111
523 CMP/PZ Rn 0100nnnn00010001
524 CMP/PL Rn 0100nnnn00010101
525 CMP/ST Rm,Rn 0010nnnnmmmm1100
526 DIV1 Rm,Rn 0011nnnnmmmm0100
527 DMULS. Rm,Rn 0011nnnnmmmm1101
528 DMULU.L Rm,Rn 0011nnnnmmmm0101
529 EXTS.B Rm,Rn 0110nnnnmmmm1110
530 EXTS.W Rm,Rn 0110nnnnmmmm1111
531 EXTU.B Rm,Rn 0110nnnnmmmm1100
532 EXTU.W Rm,Rn 0110nnnnmmmm1101
533 MAC @Rm+,@Rn+ 0100nnnnmmmm1111
534 MULS.W Rm,Rn 0010nnnnmmmm1111
535 MULU.W Rm,Rn 0010nnnnmmmm1110
536 NEG Rm,Rn 0110nnnnmmmm1011
537 NEGC Rm,Rn 0110nnnnmmmm1010
538 SUB Rm,Rn 0011nnnnmmmm1000
539 SUBC Rm,Rn 0011nnnnmmmm1010
540 SUBV Rm,Rn 0011nnnnmmmm1011
541 AND Rm,Rn 0010nnnnmmmm1001
542 AND #imm,R0 11001001iiiiiiii
543 AND.B #imm,@(R0,GBR) 11001101iiiiiiii
544 NOT Rm,Rn 0110nnnnmmmm0111
545 OR Rm,Rn 0010nnnnmmmm1011
546 OR #imm,R0 11001011iiiiiiii
547 OR.B #imm,@(R0,GBR) 11001111iiiiiiii
548 TAS.B @Rn 0100nnnn00011011
549 TST Rm,Rn 0010nnnnmmmm1000
550 TST #imm,R0 11001000iiiiiiii
551 TST.B #imm,@(R0,GBR) 11001100iiiiiiii
552 XOR Rm,Rn 0010nnnnmmmm1010
553 XOR #imm,R0 11001010iiiiiiii
554 XOR.B #imm,@(R0,GBR) 11001110iiiiiiii
555 ROTL Rn 0100nnnn00000100
556 ROTR Rn 0100nnnn00000101
557 ROTCL Rn 0100nnnn00100100
558 ROTCR Rn 0100nnnn00100101
559 SHAL Rn 0100nnnn00100000
560 SHAR Rn 0100nnnn00100001
561 SHLL Rn 0100nnnn00000000
562 SHLR Rn 0100nnnn00000001
563 SHLL2 Rn 0100nnnn00001000
564 SHLR2 Rn 0100nnnn00001001
565 SHLL8 Rn 0100nnnn00011000
566 SHLR8 Rn 0100nnnn00011001
567 SHLL16 Rn 0100nnnn00101000
568 SHLR16 Rn 0100nnnn00101001
569 LDC Rm,GBR 0100mmmm00011110
570 LDC Rm,VBR 0100mmmm00101110
571 LDC.L @Rm+,GBR 0100mmmm00010111
572 LDC.L @Rm+,VBR 0100mmmm00100111
573 LDS Rm,MACH 0100mmmm00001010
574 LDS Rm,MACL 0100mmmm00011010
575 LDS Rm,PR 0100mmmm00101010
576 LDS.L @Rm+,MACH 0100mmmm00000110
577 LDS.L @Rm+,MACL 0100mmmm00010110
578 LDS.L @Rm+,PR 0100mmmm00100110
579 STC.L SR,@–Rn 0100nnnn00000011
580 STC.L GBR,@–Rn 0100nnnn00010011
581 STC.L VBR,@–Rn 0100nnnn00100011
582 STS.L MACH,@–Rn 0100nnnn00000010
583 STS.L MACL,@–Rn 0100nnnn00010010
584 STS.L PR,@–Rn 0100nnnn00100010
585 TRAPA #imm 11000011iiiiiiii
591 #define CHECK_UNHANDLED_BITS(mask) { \
592 if ((op & (mask)) != 0) \
599 #define GET_Rm GET_Fx
604 #define CHECK_FX_GT_3() \
608 static void *sh2_translate(SH2 *sh2, block_desc *other_block)
611 block_desc *this_block;
612 unsigned int pc = sh2->pc;
613 int op, delayed_op = 0, test_irq = 0;
614 int tcache_id = 0, blkid = 0;
620 if ((tmp != 0 && tmp != 1 && tmp != 6) || sh2->pc == 0) {
621 printf("invalid PC, aborting: %08x\n", sh2->pc);
622 // FIXME: be less destructive
626 if ((sh2->pc & 0xe0000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
627 // data_array, BIOS have separate tcache (shared)
628 tcache_id = 1 + sh2->is_slave;
631 tcache_ptr = tcache_ptrs[tcache_id];
632 this_block = dr_add_block(pc, tcache_id, &blkid);
634 tmp = tcache_ptr - tcache_bases[tcache_id];
635 if (tmp > tcache_sizes[tcache_id] - MAX_BLOCK_SIZE || this_block == NULL) {
636 flush_tcache(tcache_id);
637 tcache_ptr = tcache_ptrs[tcache_id];
638 other_block = NULL; // also gone too due to flush
639 this_block = dr_add_block(pc, tcache_id, &blkid);
642 this_block->next = other_block;
643 if ((sh2->pc & 0xc6000000) == 0x02000000) // ROM
644 HASH_FUNC(hash_table, pc) = this_block;
646 block_entry = tcache_ptr;
648 printf("== %csh2 block #%d,%d %08x -> %p\n", sh2->is_slave ? 's' : 'm',
649 tcache_id, block_counts[tcache_id], pc, block_entry);
650 if (other_block != NULL) {
651 printf(" hash collision with %08x\n", other_block->addr);
656 while (cycles < BLOCK_CYCLE_LIMIT || delayed_op)
661 op = p32x_sh2_read16(pc, sh2);
666 DasmSH2(sh2dasm_buff, pc, op);
667 printf("%08x %04x %s\n", pc, op, sh2dasm_buff);
674 switch ((op >> 12) & 0x0f)
680 tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
683 case 0: // STC SR,Rn 0000nnnn00000010
686 case 1: // STC GBR,Rn 0000nnnn00010010
689 case 2: // STC VBR,Rn 0000nnnn00100010
695 tmp2 = rcache_get_reg(tmp2, RC_GR_READ);
696 emith_move_r_r(tmp, tmp2);
699 CHECK_UNHANDLED_BITS(0xd0);
700 // BRAF Rm 0000mmmm00100011
701 // BSRF Rm 0000mmmm00000011
704 emit_move_r_imm32(SHR_PR, pc + 2);
705 tmp = rcache_get_reg(SHR_PPC, RC_GR_WRITE);
706 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
707 emith_move_r_r(tmp, tmp2);
708 emith_add_r_imm(tmp, pc + 2);
711 case 0x04: // MOV.B Rm,@(R0,Rn) 0000nnnnmmmm0100
712 case 0x05: // MOV.W Rm,@(R0,Rn) 0000nnnnmmmm0101
713 case 0x06: // MOV.L Rm,@(R0,Rn) 0000nnnnmmmm0110
715 tmp = rcache_get_reg_arg(0, SHR_R0);
716 tmp2 = rcache_get_reg_arg(1, GET_Rm());
717 tmp3 = rcache_get_reg(GET_Rn(), RC_GR_READ);
718 emith_add_r_r(tmp, tmp3);
719 emit_memhandler_write(op & 3);
722 // MUL.L Rm,Rn 0000nnnnmmmm0111
723 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
724 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
725 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
726 emith_mul(tmp3, tmp2, tmp);
730 CHECK_UNHANDLED_BITS(0xf00);
733 case 0: // CLRT 0000000000001000
734 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
735 emith_bic_r_imm(tmp, T);
737 case 1: // SETT 0000000000011000
738 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
739 emith_or_r_imm(tmp, T);
741 case 2: // CLRMAC 0000000000101000
742 tmp = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
743 emith_move_r_imm(tmp, 0);
744 tmp = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
745 emith_move_r_imm(tmp, 0);
754 case 0: // NOP 0000000000001001
755 CHECK_UNHANDLED_BITS(0xf00);
757 case 1: // DIV0U 0000000000011001
758 CHECK_UNHANDLED_BITS(0xf00);
759 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
760 emith_bic_r_imm(tmp, M|Q|T);
762 case 2: // MOVT Rn 0000nnnn00101001
763 tmp = rcache_get_reg(SHR_SR, RC_GR_READ);
764 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
765 emith_clear_msb(tmp2, tmp, 31);
772 tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
775 case 0: // STS MACH,Rn 0000nnnn00001010
776 tmp2 = rcache_get_reg(SHR_MACH, RC_GR_READ);
778 case 1: // STS MACL,Rn 0000nnnn00011010
779 tmp2 = rcache_get_reg(SHR_MACL, RC_GR_READ);
781 case 2: // STS PR,Rn 0000nnnn00101010
782 tmp2 = rcache_get_reg(SHR_PR, RC_GR_READ);
787 emith_move_r_r(tmp, tmp2);
790 CHECK_UNHANDLED_BITS(0xf00);
793 case 0: // RTS 0000000000001011
795 emit_move_r_r(SHR_PPC, SHR_PR);
798 case 1: // SLEEP 0000000000011011
799 emit_move_r_imm32(SHR_PC, pc - 2);
800 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
801 emith_clear_msb(tmp, tmp, 20); // clear cycles
805 case 2: // RTE 0000000000101011
806 //emit_move_r_r(SHR_PC, SHR_PR);
807 emit_move_r_imm32(SHR_PC, pc - 2);
809 emith_pass_arg_r(0, CONTEXT_REG);
810 emith_pass_arg_imm(1, op);
811 emith_call(sh2_do_op);
812 emit_move_r_r(SHR_PPC, SHR_PC);
820 case 0x0c: // MOV.B @(R0,Rm),Rn 0000nnnnmmmm1100
821 case 0x0d: // MOV.W @(R0,Rm),Rn 0000nnnnmmmm1101
822 case 0x0e: // MOV.L @(R0,Rm),Rn 0000nnnnmmmm1110
824 tmp = rcache_get_reg_arg(0, SHR_R0);
825 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
826 emith_add_r_r(tmp, tmp2);
827 tmp = emit_memhandler_read(op & 3);
828 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
829 rcache_free_tmp(tmp);
831 emith_sext(tmp2, tmp, (op & 1) ? 16 : 8);
833 emith_move_r_r(tmp2, tmp);
835 case 0x0f: // MAC.L @Rm+,@Rn+ 0000nnnnmmmm1111
842 // MOV.L Rm,@(disp,Rn) 0001nnnnmmmmdddd
844 tmp = rcache_get_reg_arg(0, GET_Rn());
845 tmp2 = rcache_get_reg_arg(1, GET_Rm());
846 emith_add_r_imm(tmp, (op & 0x0f) * 4);
847 emit_memhandler_write(2);
853 case 0x00: // MOV.B Rm,@Rn 0010nnnnmmmm0000
854 case 0x01: // MOV.W Rm,@Rn 0010nnnnmmmm0001
855 case 0x02: // MOV.L Rm,@Rn 0010nnnnmmmm0010
857 rcache_get_reg_arg(0, GET_Rn());
858 rcache_get_reg_arg(1, GET_Rm());
859 emit_memhandler_write(op & 3);
861 case 0x04: // MOV.B Rm,@–Rn 0010nnnnmmmm0100
862 case 0x05: // MOV.W Rm,@–Rn 0010nnnnmmmm0101
863 case 0x06: // MOV.L Rm,@–Rn 0010nnnnmmmm0110
864 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
865 emith_sub_r_imm(tmp, (1 << (op & 3)));
867 rcache_get_reg_arg(0, GET_Rn());
868 rcache_get_reg_arg(1, GET_Rm());
869 emit_memhandler_write(op & 3);
871 case 0x07: // DIV0S Rm,Rn 0010nnnnmmmm0111
872 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
873 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
874 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
875 emith_bic_r_imm(tmp, M|Q|T);
876 emith_tst_r_imm(tmp2, (1<<31));
877 EMITH_SJMP_START(DCOND_EQ);
878 emith_or_r_imm_c(DCOND_NE, tmp, Q);
879 EMITH_SJMP_END(DCOND_EQ);
880 emith_tst_r_imm(tmp3, (1<<31));
881 EMITH_SJMP_START(DCOND_EQ);
882 emith_or_r_imm_c(DCOND_NE, tmp, M);
883 EMITH_SJMP_END(DCOND_EQ);
884 emith_teq_r_r(tmp2, tmp3);
885 EMITH_SJMP_START(DCOND_PL);
886 emith_or_r_imm_c(DCOND_MI, tmp, T);
887 EMITH_SJMP_END(DCOND_PL);
895 if ((op & 0xf0) != 0x10)
897 // DT Rn 0100nnnn00010000
898 if (p32x_sh2_read16(pc, sh2) == 0x8bfd) { // BF #-2
899 emith_sh2_dtbf_loop();
902 tmp = rcache_get_reg((op >> 8) & 0x0f, RC_GR_RMW);
903 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
904 emith_bic_r_imm(tmp2, T);
905 emith_subf_r_imm(tmp, 1);
906 EMITH_SJMP_START(DCOND_NE);
907 emith_or_r_imm_c(DCOND_EQ, tmp2, T);
908 EMITH_SJMP_END(DCOND_NE);
911 if ((op & 0xf0) != 0)
913 // LDC.L @Rm+,SR 0100mmmm00000111
917 if ((op & 0xd0) != 0)
919 // JMP @Rm 0100mmmm00101011
920 // JSR @Rm 0100mmmm00001011
923 emit_move_r_imm32(SHR_PR, pc + 2);
924 emit_move_r_r(SHR_PPC, (op >> 8) & 0x0f);
928 if ((op & 0xf0) != 0)
930 // LDC Rm,SR 0100mmmm00001110
937 switch (op & 0x0f00) {
938 // BT/S label 10001101dddddddd
940 // BF/S label 10001111dddddddd
945 // BT label 10001001dddddddd
947 // BF label 10001011dddddddd
949 // jmp_cond ~ cond when guest doesn't jump
950 int jmp_cond = (op & 0x0200) ? DCOND_NE : DCOND_EQ;
951 int insn_cond = (op & 0x0200) ? DCOND_EQ : DCOND_NE;
952 signed int offs = ((signed int)(op << 24) >> 23);
953 tmp = rcache_get_reg(delayed_op ? SHR_PPC : SHR_PC, RC_GR_WRITE);
954 emith_move_r_imm(tmp, pc + (delayed_op ? 2 : 0));
956 EMITH_SJMP_START(jmp_cond);
960 emith_sub_r_imm_c(insn_cond, tmp, -offs);
962 emith_add_r_imm_c(insn_cond, tmp, offs);
963 EMITH_SJMP_END(jmp_cond);
972 // BRA label 1010dddddddddddd
975 tmp = ((signed int)(op << 20) >> 19);
976 emit_move_r_imm32(SHR_PPC, pc + tmp + 2);
981 // BSR label 1011dddddddddddd
983 emit_move_r_imm32(SHR_PR, pc + 2);
988 emit_move_r_imm32(SHR_PC, pc - 2);
990 emith_pass_arg_r(0, CONTEXT_REG);
991 emith_pass_arg_imm(1, op);
992 emith_call(sh2_do_op);
998 emit_move_r_r(SHR_PC, SHR_PPC);
1000 if (test_irq && delayed_op != 2) {
1002 emith_pass_arg_r(0, CONTEXT_REG);
1003 emith_call(sh2_test_irq);
1006 if (delayed_op == 1)
1009 do_host_disasm(tcache_id);
1013 this_block->end_addr = pc;
1015 // mark memory blocks as containing compiled code
1016 if ((sh2->pc & 0xe0000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
1018 u16 *drcblk = Pico32xMem->drcblk_da[sh2->is_slave];
1019 tmp = (this_block->addr & 0xfff) >> SH2_DRCBLK_DA_SHIFT;
1020 tmp2 = (this_block->end_addr & 0xfff) >> SH2_DRCBLK_DA_SHIFT;
1021 Pico32xMem->drcblk_da[sh2->is_slave][tmp] = (blkid << 1) | 1;
1022 for (++tmp; tmp < tmp2; tmp++) {
1024 break; // dont overwrite overlay block
1025 drcblk[tmp] = blkid << 1;
1028 else if ((this_block->addr & 0xc7fc0000) == 0x06000000) { // DRAM
1029 tmp = (this_block->addr & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT;
1030 tmp2 = (this_block->end_addr & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT;
1031 Pico32xMem->drcblk_ram[tmp] = (blkid << 1) | 1;
1032 for (++tmp; tmp < tmp2; tmp++) {
1033 if (Pico32xMem->drcblk_ram[tmp])
1035 Pico32xMem->drcblk_ram[tmp] = blkid << 1;
1039 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
1040 emith_sub_r_imm(tmp, cycles << 12);
1042 emith_jump(sh2_drc_exit);
1043 tcache_ptrs[tcache_id] = tcache_ptr;
1046 cache_flush_d_inval_i(block_entry, tcache_ptr);
1049 do_host_disasm(tcache_id);
1050 dbg(1, " block #%d,%d tcache %d/%d, insns %d -> %d %.3f",
1051 tcache_id, block_counts[tcache_id],
1052 tcache_ptr - tcache_bases[tcache_id], tcache_sizes[tcache_id],
1053 insns_compiled, host_insn_count, (double)host_insn_count / insns_compiled);
1054 if ((sh2->pc & 0xc6000000) == 0x02000000) // ROM
1055 dbg(1, " hash collisions %d/%d", hash_collisions, block_counts[tcache_id]);
1064 do_host_disasm(tcache_id);
1069 void __attribute__((noinline)) sh2_drc_dispatcher(SH2 *sh2)
1071 while (((signed int)sh2->sr >> 12) > 0)
1074 block_desc *bd = NULL;
1076 // FIXME: must avoid doing it so often..
1079 // we have full block id tables for data_array and RAM
1080 // BIOS goes to data_array table too
1081 if ((sh2->pc & 0xff000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
1082 int blkid = Pico32xMem->drcblk_da[sh2->is_slave][(sh2->pc & 0xfff) >> SH2_DRCBLK_DA_SHIFT];
1084 bd = &block_tables[1 + sh2->is_slave][blkid >> 1];
1085 block = bd->tcache_ptr;
1089 else if ((sh2->pc & 0xc6000000) == 0x06000000) {
1090 int blkid = Pico32xMem->drcblk_ram[(sh2->pc & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT];
1092 bd = &block_tables[0][blkid >> 1];
1093 block = bd->tcache_ptr;
1097 else if ((sh2->pc & 0xc6000000) == 0x02000000) {
1098 bd = HASH_FUNC(hash_table, sh2->pc);
1101 if (bd->addr == sh2->pc)
1102 block = bd->tcache_ptr;
1104 block = dr_find_block(bd, sh2->pc);
1109 block = sh2_translate(sh2, bd);
1111 dbg(4, "= %csh2 enter %08x %p, c=%d", sh2->is_slave ? 's' : 'm',
1112 sh2->pc, block, (signed int)sh2->sr >> 12);
1117 sh2_drc_entry(sh2, block);
1121 static void sh2_smc_rm_block(u16 *drcblk, u16 *p, block_desc *btab, u32 a)
1124 block_desc *bd = btab + id;
1126 dbg(1, " killing block %08x", bd->addr);
1127 bd->addr = bd->end_addr = 0;
1129 while (p > drcblk && (p[-1] >> 1) == id)
1132 // check for possible overlay block
1133 if (p > 0 && p[-1] != 0) {
1134 bd = btab + (p[-1] >> 1);
1135 if (bd->addr <= a && a < bd->end_addr)
1136 sh2_smc_rm_block(drcblk, p - 1, btab, a);
1142 while ((*p >> 1) == id);
1145 void sh2_drc_wcheck_ram(unsigned int a, int val, int cpuid)
1147 u16 *drcblk = Pico32xMem->drcblk_ram;
1148 u16 *p = drcblk + ((a & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT);
1150 dbg(1, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a);
1151 sh2_smc_rm_block(drcblk, p, block_tables[0], a);
1154 void sh2_drc_wcheck_da(unsigned int a, int val, int cpuid)
1156 u16 *drcblk = Pico32xMem->drcblk_da[cpuid];
1157 u16 *p = drcblk + ((a & 0xfff) >> SH2_DRCBLK_DA_SHIFT);
1159 dbg(1, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a);
1160 sh2_smc_rm_block(drcblk, p, block_tables[1 + cpuid], a);
1163 void sh2_execute(SH2 *sh2, int cycles)
1165 sh2->cycles_aim += cycles;
1166 cycles = sh2->cycles_aim - sh2->cycles_done;
1168 // cycles are kept in SHR_SR unused bits (upper 20)
1170 sh2->sr |= cycles << 12;
1171 sh2_drc_dispatcher(sh2);
1173 sh2->cycles_done += cycles - ((signed int)sh2->sr >> 12);
1176 static void REGPARM(1) sh2_test_irq(SH2 *sh2)
1178 if (sh2->pending_level > ((sh2->sr >> 4) & 0x0f))
1180 if (sh2->pending_irl > sh2->pending_int_irq)
1181 sh2_do_irq(sh2, sh2->pending_irl, 64 + sh2->pending_irl/2);
1183 sh2_do_irq(sh2, sh2->pending_int_irq, sh2->pending_int_vector);
1184 sh2->pending_int_irq = 0; // auto-clear
1185 sh2->pending_level = sh2->pending_irl;
1191 static void block_stats(void)
1193 int c, b, i, total = 0;
1195 for (b = 0; b < ARRAY_SIZE(block_tables); b++)
1196 for (i = 0; i < block_counts[b]; i++)
1197 if (block_tables[b][i].addr != 0)
1198 total += block_tables[b][i].refcount;
1200 for (c = 0; c < 10; c++) {
1201 block_desc *blk, *maxb = NULL;
1203 for (b = 0; b < ARRAY_SIZE(block_tables); b++) {
1204 for (i = 0; i < block_counts[b]; i++) {
1205 blk = &block_tables[b][i];
1206 if (blk->addr != 0 && blk->refcount > max) {
1207 max = blk->refcount;
1214 printf("%08x %9d %2.3f%%\n", maxb->addr, maxb->refcount,
1215 (double)maxb->refcount / total * 100.0);
1219 for (b = 0; b < ARRAY_SIZE(block_tables); b++)
1220 for (i = 0; i < block_counts[b]; i++)
1221 block_tables[b][i].refcount = 0;
1224 #define block_stats()
1227 void sh2_drc_flush_all(void)
1235 int sh2_drc_init(SH2 *sh2)
1237 if (block_tables[0] == NULL) {
1242 cnt = block_max_counts[0] + block_max_counts[1] + block_max_counts[2];
1243 block_tables[0] = calloc(cnt, sizeof(*block_tables[0]));
1244 if (block_tables[0] == NULL)
1247 memset(block_counts, 0, sizeof(block_counts));
1248 tcache_bases[0] = tcache_ptrs[0] = tcache;
1250 for (i = 1; i < ARRAY_SIZE(block_tables); i++) {
1251 block_tables[i] = block_tables[i - 1] + block_max_counts[i - 1];
1252 tcache_bases[i] = tcache_ptrs[i] = tcache_bases[i - 1] + tcache_sizes[i - 1];
1256 PicoOpt |= POPT_DIS_VDP_FIFO;
1259 for (i = 0; i < ARRAY_SIZE(block_tables); i++)
1260 tcache_dsm_ptrs[i] = tcache_bases[i];
1263 hash_collisions = 0;
1267 if (hash_table == NULL) {
1268 hash_table = calloc(sizeof(hash_table[0]), MAX_HASH_ENTRIES);
1269 if (hash_table == NULL)
1276 void sh2_drc_finish(SH2 *sh2)
1278 if (block_tables[0] != NULL) {
1280 free(block_tables[0]);
1281 memset(block_tables, 0, sizeof(block_tables));
1286 if (hash_table != NULL) {