2 * vim:shiftwidth=2:expandtab
5 * - tcache, block descriptor, link buffer overflows result in sh2_translate()
6 * failure, followed by full tcache invalidation for that region
7 * - jumps between blocks are tracked for SMC handling (in block_links[]),
8 * except jumps between different tcaches
11 * - static register allocation
12 * - remaining register caching and tracking in temporaries
13 * - block-local branch linking
14 * - block linking (except between tcaches)
15 * - some constant propagation
18 * - proper SMC handling
19 * - better constant propagation
28 #include "../../pico/pico_int.h"
31 #include "../drc/cmn.h"
34 #define PROPAGATE_CONSTANTS 1
35 #define LINK_BRANCHES 1
37 // max literal offset from the block end
38 #define MAX_LITERAL_OFFSET 32*2
46 #define dbg(l,...) { \
47 if ((l) & DRC_DEBUG) \
48 elprintf(EL_STATUS, ##__VA_ARGS__); \
51 #include "mame/sh2dasm.h"
52 #include <platform/linux/host_dasm.h>
53 static int insns_compiled, hash_collisions, host_insn_count;
62 static u8 *tcache_dsm_ptrs[3];
63 static char sh2dasm_buff[64];
64 #define do_host_disasm(tcid) \
65 host_dasm(tcache_dsm_ptrs[tcid], tcache_ptr - tcache_dsm_ptrs[tcid]); \
66 tcache_dsm_ptrs[tcid] = tcache_ptr
68 #define do_host_disasm(x)
72 static void REGPARM(3) *sh2_drc_announce_entry(void *block, SH2 *sh2, u32 sr)
75 dbg(4, "= %csh2 enter %08x %p, c=%d", sh2->is_slave ? 's' : 'm',
76 sh2->pc, block, (signed int)sr >> 12);
82 #define BLOCK_CYCLE_LIMIT 100
83 #define MAX_BLOCK_SIZE (BLOCK_CYCLE_LIMIT * 6 * 6)
84 #define TCACHE_BUFFERS 3
86 // we have 3 translation cache buffers, split from one drc/cmn buffer.
87 // BIOS shares tcache with data array because it's only used for init
88 // and can be discarded early
89 // XXX: need to tune sizes
90 static const int tcache_sizes[TCACHE_BUFFERS] = {
91 DRC_TCACHE_SIZE * 6 / 8, // ROM, DRAM
92 DRC_TCACHE_SIZE / 8, // BIOS, data array in master sh2
93 DRC_TCACHE_SIZE / 8, // ... slave
96 static u8 *tcache_bases[TCACHE_BUFFERS];
97 static u8 *tcache_ptrs[TCACHE_BUFFERS];
99 // ptr for code emiters
100 static u8 *tcache_ptr;
102 typedef struct block_desc_ {
103 u32 addr; // SH2 PC address
104 u32 end_addr; // TODO rm?
105 void *tcache_ptr; // translated block for above PC
106 struct block_desc_ *next; // next block with the same PC hash
112 typedef struct block_link_ {
115 // struct block_link_ *next;
118 static const int block_max_counts[TCACHE_BUFFERS] = {
123 static block_desc *block_tables[TCACHE_BUFFERS];
124 static block_link *block_links[TCACHE_BUFFERS];
125 static int block_counts[TCACHE_BUFFERS];
126 static int block_link_counts[TCACHE_BUFFERS];
128 // host register tracking
131 HR_CACHED, // 'val' has sh2_reg_e
132 // HR_CONST, // 'val' has a constant
133 HR_TEMP, // reg used for temp storage
137 HRF_DIRTY = 1 << 0, // reg has "dirty" value to be written to ctx
138 HRF_LOCKED = 1 << 1, // HR_CACHED can't be evicted
142 u32 hreg:5; // "host" reg
143 u32 greg:5; // "guest" reg
146 u32 stamp:16; // kind of a timestamp
149 // note: reg_temp[] must have at least the amount of
150 // registers used by handlers in worst case (currently 4)
152 #include "../drc/emit_arm.c"
154 static const int reg_map_g2h[] = {
163 static temp_reg_t reg_temp[] = {
172 #elif defined(__i386__)
173 #include "../drc/emit_x86.c"
175 static const int reg_map_g2h[] = {
184 // ax, cx, dx are usually temporaries by convention
185 static temp_reg_t reg_temp[] = {
193 #error unsupported arch
201 #define T_save 0x00000800
208 #define MAX_HASH_ENTRIES 1024
209 #define HASH_MASK (MAX_HASH_ENTRIES - 1)
210 static void **hash_table;
212 #define HASH_FUNC(hash_tab, addr) \
213 ((block_desc **)(hash_tab))[(addr) & HASH_MASK]
215 static void REGPARM(1) (*sh2_drc_entry)(SH2 *sh2);
216 static void (*sh2_drc_dispatcher)(void);
217 static void (*sh2_drc_exit)(void);
218 static void (*sh2_drc_test_irq)(void);
219 static void REGPARM(2) (*sh2_drc_write8)(u32 a, u32 d);
220 static void REGPARM(2) (*sh2_drc_write8_slot)(u32 a, u32 d);
221 static void REGPARM(2) (*sh2_drc_write16)(u32 a, u32 d);
222 static void REGPARM(2) (*sh2_drc_write16_slot)(u32 a, u32 d);
224 extern void REGPARM(2) sh2_do_op(SH2 *sh2, int opcode);
226 static void flush_tcache(int tcid)
228 dbg(1, "tcache #%d flush! (%d/%d, bds %d/%d)", tcid,
229 tcache_ptrs[tcid] - tcache_bases[tcid], tcache_sizes[tcid],
230 block_counts[tcid], block_max_counts[tcid]);
232 block_counts[tcid] = 0;
233 tcache_ptrs[tcid] = tcache_bases[tcid];
234 if (tcid == 0) { // ROM, RAM
235 memset(hash_table, 0, sizeof(hash_table[0]) * MAX_HASH_ENTRIES);
236 memset(Pico32xMem->drcblk_ram, 0, sizeof(Pico32xMem->drcblk_ram));
239 memset(Pico32xMem->drcblk_da[tcid - 1], 0, sizeof(Pico32xMem->drcblk_da[0]));
241 tcache_dsm_ptrs[tcid] = tcache_bases[tcid];
245 // add block links (tracked branches)
246 static int dr_add_block_link(u32 target_pc, void *jump, int tcache_id)
248 block_link *bl = block_links[tcache_id];
249 int cnt = block_link_counts[tcache_id];
251 if (cnt >= block_max_counts[tcache_id] * 2) {
252 printf("bl overflow for tcache %d\n", tcache_id);
256 bl[cnt].target_pc = target_pc;
258 block_link_counts[tcache_id]++;
263 static void *dr_find_block(block_desc *tab, u32 addr)
265 for (tab = tab->next; tab != NULL; tab = tab->next)
266 if (tab->addr == addr)
270 return tab->tcache_ptr;
272 printf("block miss for %08x\n", addr);
276 static block_desc *dr_add_block(u32 addr, int tcache_id, int *blk_id)
278 int *bcount = &block_counts[tcache_id];
281 if (*bcount >= block_max_counts[tcache_id]) {
282 printf("bd overflow for tcache %d\n", tcache_id);
286 bd = &block_tables[tcache_id][*bcount];
288 bd->tcache_ptr = tcache_ptr;
292 if ((addr & 0xc6000000) == 0x02000000) { // ROM
293 bd->next = HASH_FUNC(hash_table, addr);
294 HASH_FUNC(hash_table, addr) = bd;
296 if (bd->next != NULL) {
297 printf(" hash collision with %08x\n", bd->next->addr);
306 #define ADD_TO_ARRAY(array, count, item, failcode) \
307 array[count++] = item; \
308 if (count >= ARRAY_SIZE(array)) { \
309 printf("warning: " #array " overflow\n"); \
313 int find_in_array(u32 *array, size_t size, u32 what)
316 for (i = 0; i < size; i++)
317 if (what == array[i])
323 // ---------------------------------------------------------------
331 static int rcache_get_reg_(sh2_reg_e r, rc_gr_mode mode, int do_locking);
333 // guest regs with constants
334 static u32 dr_gcregs[24];
335 // a mask of constant/dirty regs
336 static u32 dr_gcregs_mask;
337 static u32 dr_gcregs_dirty;
339 static void gconst_new(sh2_reg_e r, u32 val)
341 #if PROPAGATE_CONSTANTS
344 dr_gcregs_mask |= 1 << r;
345 dr_gcregs_dirty |= 1 << r;
348 // throw away old r that we might have cached
349 for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
350 if ((reg_temp[i].type == HR_CACHED) &&
351 reg_temp[i].greg == r) {
352 reg_temp[i].type = HR_FREE;
353 reg_temp[i].flags = 0;
359 static int gconst_get(sh2_reg_e r, u32 *val)
361 if (dr_gcregs_mask & (1 << r)) {
368 static int gconst_check(sh2_reg_e r)
370 if ((dr_gcregs_mask | dr_gcregs_dirty) & (1 << r))
375 // update hr if dirty, else do nothing
376 static int gconst_try_read(int hr, sh2_reg_e r)
378 if (dr_gcregs_dirty & (1 << r)) {
379 emith_move_r_imm(hr, dr_gcregs[r]);
380 dr_gcregs_dirty &= ~(1 << r);
386 static void gconst_check_evict(sh2_reg_e r)
388 if (dr_gcregs_mask & (1 << r))
389 // no longer cached in reg, make dirty again
390 dr_gcregs_dirty |= 1 << r;
393 static void gconst_kill(sh2_reg_e r)
395 dr_gcregs_mask &= ~(1 << r);
396 dr_gcregs_dirty &= ~(1 << r);
399 static void gconst_clean(void)
403 for (i = 0; i < ARRAY_SIZE(dr_gcregs); i++)
404 if (dr_gcregs_dirty & (1 << i)) {
405 // using RC_GR_READ here: it will call gconst_try_read,
406 // cache the reg and mark it dirty.
407 rcache_get_reg_(i, RC_GR_READ, 0);
411 static void gconst_invalidate(void)
413 dr_gcregs_mask = dr_gcregs_dirty = 0;
417 static u16 rcache_counter;
419 static temp_reg_t *rcache_evict(void)
421 // evict reg with oldest stamp
423 u16 min_stamp = (u16)-1;
425 for (i = 0; i < ARRAY_SIZE(reg_temp); i++) {
426 if (reg_temp[i].type == HR_CACHED && !(reg_temp[i].flags & HRF_LOCKED) &&
427 reg_temp[i].stamp <= min_stamp) {
428 min_stamp = reg_temp[i].stamp;
434 printf("no registers to evict, aborting\n");
439 if (reg_temp[i].type == HR_CACHED) {
440 if (reg_temp[i].flags & HRF_DIRTY)
442 emith_ctx_write(reg_temp[i].hreg, reg_temp[i].greg * 4);
443 gconst_check_evict(reg_temp[i].greg);
446 reg_temp[i].type = HR_FREE;
447 reg_temp[i].flags = 0;
451 static int get_reg_static(sh2_reg_e r, rc_gr_mode mode)
453 int i = reg_map_g2h[r];
455 if (mode != RC_GR_WRITE)
456 gconst_try_read(i, r);
461 // note: must not be called when doing conditional code
462 static int rcache_get_reg_(sh2_reg_e r, rc_gr_mode mode, int do_locking)
467 // maybe statically mapped?
468 ret = get_reg_static(r, mode);
474 // maybe already cached?
475 // if so, prefer against gconst (they must be in sync)
476 for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
477 if (reg_temp[i].type == HR_CACHED && reg_temp[i].greg == r) {
478 reg_temp[i].stamp = rcache_counter;
479 if (mode != RC_GR_READ)
480 reg_temp[i].flags |= HRF_DIRTY;
481 ret = reg_temp[i].hreg;
487 for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
488 if (reg_temp[i].type == HR_FREE) {
497 tr->type = HR_CACHED;
499 tr->flags |= HRF_LOCKED;
500 if (mode != RC_GR_READ)
501 tr->flags |= HRF_DIRTY;
503 tr->stamp = rcache_counter;
506 if (mode != RC_GR_WRITE) {
507 if (gconst_check(r)) {
508 if (gconst_try_read(ret, r))
509 tr->flags |= HRF_DIRTY;
512 emith_ctx_read(tr->hreg, r * 4);
516 if (mode != RC_GR_READ)
522 static int rcache_get_reg(sh2_reg_e r, rc_gr_mode mode)
524 return rcache_get_reg_(r, mode, 1);
527 static int rcache_get_tmp(void)
532 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
533 if (reg_temp[i].type == HR_FREE) {
545 static int rcache_get_arg_id(int arg)
548 host_arg2reg(r, arg);
550 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
551 if (reg_temp[i].hreg == r)
554 if (i == ARRAY_SIZE(reg_temp))
555 // let's just say it's untracked arg reg
558 if (reg_temp[i].type == HR_CACHED) {
560 if (reg_temp[i].flags & HRF_DIRTY)
561 emith_ctx_write(reg_temp[i].hreg, reg_temp[i].greg * 4);
562 gconst_check_evict(reg_temp[i].greg);
564 else if (reg_temp[i].type == HR_TEMP) {
565 printf("arg %d reg %d already used, aborting\n", arg, r);
569 reg_temp[i].type = HR_FREE;
570 reg_temp[i].flags = 0;
575 // get a reg to be used as function arg
576 static int rcache_get_tmp_arg(int arg)
578 int id = rcache_get_arg_id(arg);
579 reg_temp[id].type = HR_TEMP;
581 return reg_temp[id].hreg;
584 // same but caches a reg. RC_GR_READ only.
585 static int rcache_get_reg_arg(int arg, sh2_reg_e r)
587 int i, srcr, dstr, dstid;
590 dstid = rcache_get_arg_id(arg);
591 dstr = reg_temp[dstid].hreg;
593 // maybe already statically mapped?
594 srcr = get_reg_static(r, RC_GR_READ);
598 // maybe already cached?
599 for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
600 if ((reg_temp[i].type == HR_CACHED) &&
601 reg_temp[i].greg == r)
603 srcr = reg_temp[i].hreg;
610 if (gconst_check(r)) {
611 if (gconst_try_read(srcr, r))
615 emith_ctx_read(srcr, r * 4);
619 emith_move_r_r(dstr, srcr);
621 reg_temp[dstid].stamp = ++rcache_counter;
622 reg_temp[dstid].type = HR_CACHED;
623 reg_temp[dstid].greg = r;
624 reg_temp[dstid].flags |= HRF_LOCKED;
626 reg_temp[dstid].flags |= HRF_DIRTY;
630 static void rcache_free_tmp(int hr)
633 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
634 if (reg_temp[i].hreg == hr)
637 if (i == ARRAY_SIZE(reg_temp) || reg_temp[i].type != HR_TEMP) {
638 printf("rcache_free_tmp fail: #%i hr %d, type %d\n", i, hr, reg_temp[i].type);
642 reg_temp[i].type = HR_FREE;
643 reg_temp[i].flags = 0;
646 static void rcache_unlock(int hr)
649 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
650 if (reg_temp[i].type == HR_CACHED && reg_temp[i].hreg == hr)
651 reg_temp[i].flags &= ~HRF_LOCKED;
654 static void rcache_unlock_all(void)
657 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
658 reg_temp[i].flags &= ~HRF_LOCKED;
661 static void rcache_clean(void)
666 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
667 if (reg_temp[i].type == HR_CACHED && (reg_temp[i].flags & HRF_DIRTY)) {
669 emith_ctx_write(reg_temp[i].hreg, reg_temp[i].greg * 4);
670 reg_temp[i].flags &= ~HRF_DIRTY;
674 static void rcache_invalidate(void)
677 for (i = 0; i < ARRAY_SIZE(reg_temp); i++) {
678 reg_temp[i].type = HR_FREE;
679 reg_temp[i].flags = 0;
686 static void rcache_flush(void)
692 // ---------------------------------------------------------------
694 // address space stuff
695 static void *dr_get_pc_base(u32 pc, int is_slave)
700 if ((pc & ~0x7ff) == 0) {
702 ret = is_slave ? Pico32xMem->sh2_rom_s : Pico32xMem->sh2_rom_m;
705 else if ((pc & 0xfffff000) == 0xc0000000) {
707 ret = Pico32xMem->data_array[is_slave];
710 else if ((pc & 0xc6000000) == 0x06000000) {
712 ret = Pico32xMem->sdram;
715 else if ((pc & 0xc6000000) == 0x02000000) {
722 return (void *)-1; // NULL is valid value
724 return (char *)ret - (pc & ~mask);
727 static int emit_get_rbase_and_offs(u32 a, u32 *offs)
733 if ((a & ~0x7ff) == 0) {
735 poffs = offsetof(SH2, p_bios);
738 else if ((a & 0xfffff000) == 0xc0000000) {
740 poffs = offsetof(SH2, p_da);
743 else if ((a & 0xc6000000) == 0x06000000) {
745 poffs = offsetof(SH2, p_sdram);
748 else if ((a & 0xc6000000) == 0x02000000) {
750 poffs = offsetof(SH2, p_rom);
757 // XXX: could use related reg
758 hr = rcache_get_tmp();
759 emith_ctx_read(hr, poffs);
760 emith_add_r_imm(hr, a & mask & ~0xff);
761 *offs = a & 0xff; // XXX: ARM oriented..
765 static void REGPARM(3) *lookup_block(u32 pc, int is_slave, int *tcache_id)
767 block_desc *bd = NULL;
771 // we have full block id tables for data_array and RAM
772 // BIOS goes to data_array table too
773 if ((pc & 0xe0000000) == 0xc0000000 || (pc & ~0xfff) == 0) {
774 int blkid = Pico32xMem->drcblk_da[is_slave][(pc & 0xfff) >> SH2_DRCBLK_DA_SHIFT];
775 *tcache_id = 1 + is_slave;
777 bd = &block_tables[*tcache_id][blkid >> 1];
778 block = bd->tcache_ptr;
782 else if ((pc & 0xc6000000) == 0x06000000) {
783 int blkid = Pico32xMem->drcblk_ram[(pc & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT];
785 bd = &block_tables[0][blkid >> 1];
786 block = bd->tcache_ptr;
790 else if ((pc & 0xc6000000) == 0x02000000) {
791 bd = HASH_FUNC(hash_table, pc);
795 block = bd->tcache_ptr;
797 block = dr_find_block(bd, pc);
808 static void emit_move_r_imm32(sh2_reg_e dst, u32 imm)
810 #if PROPAGATE_CONSTANTS
811 gconst_new(dst, imm);
813 int hr = rcache_get_reg(dst, RC_GR_WRITE);
814 emith_move_r_imm(hr, imm);
818 static void emit_move_r_r(sh2_reg_e dst, sh2_reg_e src)
820 int hr_d = rcache_get_reg(dst, RC_GR_WRITE);
821 int hr_s = rcache_get_reg(src, RC_GR_READ);
823 emith_move_r_r(hr_d, hr_s);
826 // T must be clear, and comparison done just before this
827 static void emit_or_t_if_eq(int srr)
829 EMITH_SJMP_START(DCOND_NE);
830 emith_or_r_imm_c(DCOND_EQ, srr, T);
831 EMITH_SJMP_END(DCOND_NE);
834 // arguments must be ready
835 // reg cache must be clean before call
836 static int emit_memhandler_read_(int size, int ram_check)
839 host_arg2reg(arg0, 0);
843 // must writeback cycles for poll detection stuff
845 if (reg_map_g2h[SHR_SR] != -1)
846 emith_ctx_write(reg_map_g2h[SHR_SR], SHR_SR * 4);
848 arg1 = rcache_get_tmp_arg(1);
849 emith_move_r_r(arg1, CONTEXT_REG);
852 if (ram_check && Pico.rom == (void *)0x02000000 && Pico32xMem->sdram == (void *)0x06000000) {
853 int tmp = rcache_get_tmp();
854 emith_and_r_r_imm(tmp, arg0, 0xfb000000);
855 emith_cmp_r_imm(tmp, 0x02000000);
858 EMITH_SJMP3_START(DCOND_NE);
859 emith_eor_r_imm_c(DCOND_EQ, arg0, 1);
860 emith_read8_r_r_offs_c(DCOND_EQ, arg0, arg0, 0);
861 EMITH_SJMP3_MID(DCOND_NE);
862 emith_call_cond(DCOND_NE, p32x_sh2_read8);
866 EMITH_SJMP3_START(DCOND_NE);
867 emith_read16_r_r_offs_c(DCOND_EQ, arg0, arg0, 0);
868 EMITH_SJMP3_MID(DCOND_NE);
869 emith_call_cond(DCOND_NE, p32x_sh2_read16);
873 EMITH_SJMP3_START(DCOND_NE);
874 emith_read_r_r_offs_c(DCOND_EQ, arg0, arg0, 0);
875 emith_ror_c(DCOND_EQ, arg0, arg0, 16);
876 EMITH_SJMP3_MID(DCOND_NE);
877 emith_call_cond(DCOND_NE, p32x_sh2_read32);
887 emith_call(p32x_sh2_read8);
890 emith_call(p32x_sh2_read16);
893 emith_call(p32x_sh2_read32);
898 // assuming arg0 and retval reg matches
899 return rcache_get_tmp_arg(0);
902 static int emit_memhandler_read(int size)
904 return emit_memhandler_read_(size, 1);
907 static int emit_memhandler_read_rr(sh2_reg_e rd, sh2_reg_e rs, u32 offs, int size)
909 int hr, hr2, ram_check = 1;
912 if (gconst_get(rs, &val)) {
913 hr = emit_get_rbase_and_offs(val + offs, &offs2);
915 hr2 = rcache_get_reg(rd, RC_GR_WRITE);
918 emith_read8_r_r_offs(hr2, hr, offs2 ^ 1);
919 emith_sext(hr2, hr2, 8);
922 emith_read16_r_r_offs(hr2, hr, offs2);
923 emith_sext(hr2, hr2, 16);
926 emith_read_r_r_offs(hr2, hr, offs2);
927 emith_ror(hr2, hr2, 16);
937 hr = rcache_get_reg_arg(0, rs);
939 emith_add_r_imm(hr, offs);
940 hr = emit_memhandler_read_(size, ram_check);
941 hr2 = rcache_get_reg(rd, RC_GR_WRITE);
943 emith_sext(hr2, hr, (size == 1) ? 16 : 8);
945 emith_move_r_r(hr2, hr);
951 static void emit_memhandler_write(int size, u32 pc, int delay)
954 host_arg2reg(ctxr, 2);
957 // XXX: consider inlining sh2_drc_write8
959 emith_call(sh2_drc_write8_slot);
961 emit_move_r_imm32(SHR_PC, pc);
963 emith_call(sh2_drc_write8);
968 emith_call(sh2_drc_write16_slot);
970 emit_move_r_imm32(SHR_PC, pc);
972 emith_call(sh2_drc_write16);
976 emith_move_r_r(ctxr, CONTEXT_REG);
977 emith_call(p32x_sh2_write32);
984 static int emit_indirect_indexed_read(int rx, int ry, int size)
987 a0 = rcache_get_reg_arg(0, rx);
988 t = rcache_get_reg(ry, RC_GR_READ);
989 emith_add_r_r(a0, t);
990 return emit_memhandler_read(size);
994 static void emit_indirect_read_double(u32 *rnr, u32 *rmr, int rn, int rm, int size)
998 rcache_get_reg_arg(0, rn);
999 tmp = emit_memhandler_read(size);
1000 emith_ctx_write(tmp, offsetof(SH2, drc_tmp));
1001 rcache_free_tmp(tmp);
1002 tmp = rcache_get_reg(rn, RC_GR_RMW);
1003 emith_add_r_imm(tmp, 1 << size);
1006 rcache_get_reg_arg(0, rm);
1007 *rmr = emit_memhandler_read(size);
1008 *rnr = rcache_get_tmp();
1009 emith_ctx_read(*rnr, offsetof(SH2, drc_tmp));
1010 tmp = rcache_get_reg(rm, RC_GR_RMW);
1011 emith_add_r_imm(tmp, 1 << size);
1015 static void emit_do_static_regs(int is_write, int tmpr)
1019 for (i = 0; i < ARRAY_SIZE(reg_map_g2h); i++) {
1024 for (count = 1; i < ARRAY_SIZE(reg_map_g2h) - 1; i++, r++) {
1025 if (reg_map_g2h[i + 1] != r + 1)
1031 // i, r point to last item
1033 emith_ctx_write_multiple(r - count + 1, (i - count + 1) * 4, count, tmpr);
1035 emith_ctx_read_multiple(r - count + 1, (i - count + 1) * 4, count, tmpr);
1038 emith_ctx_write(r, i * 4);
1040 emith_ctx_read(r, i * 4);
1045 static void emit_block_entry(void)
1047 int arg0, arg1, arg2;
1049 host_arg2reg(arg0, 0);
1050 host_arg2reg(arg1, 1);
1051 host_arg2reg(arg2, 2);
1054 emith_move_r_r(arg1, CONTEXT_REG);
1055 emith_move_r_r(arg2, rcache_get_reg(SHR_SR, RC_GR_READ));
1056 emith_call(sh2_drc_announce_entry);
1057 rcache_invalidate();
1059 emith_tst_r_r(arg0, arg0);
1060 EMITH_SJMP_START(DCOND_EQ);
1061 emith_jump_reg_c(DCOND_NE, arg0);
1062 EMITH_SJMP_END(DCOND_EQ);
1065 void dr_link_blocks(void *target, u32 pc, int tcache_id)
1068 block_link *bl = block_links[tcache_id];
1069 int cnt = block_link_counts[tcache_id];
1072 for (i = 0; i < cnt; i++) {
1073 if (bl[i].target_pc == pc) {
1074 dbg(1, "- link from %p", bl[i].jump);
1075 emith_jump_patch(bl[i].jump, target);
1076 // XXX: sync ARM caches (old jump should be fine)?
1082 void *dr_prepare_ext_branch(u32 pc, SH2 *sh2, int tcache_id)
1085 int target_tcache_id;
1089 target = lookup_block(pc, sh2->is_slave, &target_tcache_id);
1090 if (target_tcache_id == tcache_id) {
1091 // allow linking blocks only from local cache
1092 ret = dr_add_block_link(pc, tcache_ptr, tcache_id);
1096 if (target == NULL || target_tcache_id != tcache_id)
1097 target = sh2_drc_dispatcher;
1101 return sh2_drc_dispatcher;
1105 #define DELAYED_OP \
1108 #define DELAY_SAVE_T(sr) { \
1109 emith_bic_r_imm(sr, T_save); \
1110 emith_tst_r_imm(sr, T); \
1111 EMITH_SJMP_START(DCOND_EQ); \
1112 emith_or_r_imm_c(DCOND_NE, sr, T_save); \
1113 EMITH_SJMP_END(DCOND_EQ); \
1114 drcf.use_saved_t = 1; \
1117 #define FLUSH_CYCLES(sr) \
1119 emith_sub_r_imm(sr, cycles << 12); \
1123 #define CHECK_UNHANDLED_BITS(mask) { \
1124 if ((op & (mask)) != 0) \
1128 #define FETCH_OP(pc) \
1129 dr_pc_base[(pc) / 2]
1131 #define FETCH32(a) \
1132 ((dr_pc_base[(a) / 2] << 16) | dr_pc_base[(a) / 2 + 1])
1137 #define GET_Rm GET_Fx
1142 #define CHECK_FX_LT(n) \
1143 if (GET_Fx() >= n) \
1146 #define MAX_LOCAL_BRANCHES 32
1148 // op_flags: data from 1st pass
1149 #define OP_FLAGS(pc) op_flags[((pc) - base_pc) / 2]
1150 #define OF_DELAY_OP (1 << 0)
1152 static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
1154 // XXX: maybe use structs instead?
1155 void *branch_target_ptr[MAX_LOCAL_BRANCHES];
1156 u32 branch_target_pc[MAX_LOCAL_BRANCHES];
1157 int branch_target_count = 0;
1158 void *branch_patch_ptr[MAX_LOCAL_BRANCHES];
1159 u32 branch_patch_pc[MAX_LOCAL_BRANCHES];
1160 int branch_patch_count = 0;
1161 int pending_branch_cond = -1;
1162 int pending_branch_pc = 0;
1163 u8 op_flags[BLOCK_CYCLE_LIMIT + 1];
1167 u32 use_saved_t:1; // delayed op modifies T
1170 // PC of current, first, last, last_target_blk SH2 insn
1171 u32 pc, base_pc, end_pc, out_pc;
1172 u32 last_inlined_literal = 0;
1174 block_desc *this_block;
1185 // get base/validate PC
1186 dr_pc_base = dr_get_pc_base(base_pc, sh2->is_slave);
1187 if (dr_pc_base == (void *)-1) {
1188 printf("invalid PC, aborting: %08x\n", base_pc);
1189 // FIXME: be less destructive
1193 tcache_ptr = tcache_ptrs[tcache_id];
1194 this_block = dr_add_block(base_pc, tcache_id, &blkid_main);
1195 if (this_block == NULL)
1198 // predict tcache overflow
1199 tmp = tcache_ptr - tcache_bases[tcache_id];
1200 if (tmp > tcache_sizes[tcache_id] - MAX_BLOCK_SIZE) {
1201 printf("tcache %d overflow\n", tcache_id);
1205 block_entry = tcache_ptr;
1206 dbg(1, "== %csh2 block #%d,%d %08x -> %p", sh2->is_slave ? 's' : 'm',
1207 tcache_id, blkid_main, base_pc, block_entry);
1209 dr_link_blocks(tcache_ptr, base_pc, tcache_id);
1211 // 1st pass: scan forward for local branches
1212 memset(op_flags, 0, sizeof(op_flags));
1213 for (cycles = 0, pc = base_pc; cycles < BLOCK_CYCLE_LIMIT; cycles++, pc += 2) {
1215 if ((op & 0xf000) == 0xa000 || (op & 0xf000) == 0xb000) { // BRA, BSR
1216 signed int offs = ((signed int)(op << 20) >> 19);
1218 OP_FLAGS(pc) |= OF_DELAY_OP;
1219 ADD_TO_ARRAY(branch_target_pc, branch_target_count, pc + offs + 2,);
1222 if ((op & 0xf000) == 0) {
1224 if (op == 0x1b) // SLEEP
1226 if (op == 0x23 || op == 0x03 || op == 0x0b || op == 0x2b) { // BRAF, BSRF, RTS, RTE
1228 OP_FLAGS(pc) |= OF_DELAY_OP;
1233 if ((op & 0xf0df) == 0x400b) { // JMP, JSR
1235 OP_FLAGS(pc) |= OF_DELAY_OP;
1238 if ((op & 0xf900) == 0x8900) { // BT(S), BF(S)
1239 signed int offs = ((signed int)(op << 24) >> 23);
1241 OP_FLAGS(pc + 2) |= OF_DELAY_OP;
1242 ADD_TO_ARRAY(branch_target_pc, branch_target_count, pc + offs + 4, break);
1244 if ((op & 0xff00) == 0xc300) // TRAPA
1250 // clean branch_targets that are not really local,
1251 // and that land on delay slots
1252 for (i = 0, tmp = 0; i < branch_target_count; i++) {
1253 pc = branch_target_pc[i];
1254 if (base_pc <= pc && pc <= end_pc && !(OP_FLAGS(pc) & OF_DELAY_OP))
1255 branch_target_pc[tmp++] = branch_target_pc[i];
1257 branch_target_count = tmp;
1258 memset(branch_target_ptr, 0, sizeof(branch_target_ptr[0]) * branch_target_count);
1261 branch_target_count = 0;
1264 // -------------------------------------------------
1265 // 2nd pass: actual compilation
1268 for (cycles = 0; pc <= end_pc || drcf.delayed_op; )
1272 if (drcf.delayed_op > 0)
1277 i = find_in_array(branch_target_pc, branch_target_count, pc);
1282 /* make "subblock" - just a mid-block entry */
1283 block_desc *subblock;
1287 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1289 // decide if to flush rcache
1290 if ((op & 0xf0ff) == 0x4010 && FETCH_OP(pc + 2) == 0x8bfd) // DT; BF #-2
1294 do_host_disasm(tcache_id);
1296 subblock = dr_add_block(pc, tcache_id, &blkid);
1297 if (subblock == NULL)
1299 subblock->end_addr = pc;
1301 if (tcache_id != 0) { // data array, BIOS
1302 drcblk = Pico32xMem->drcblk_da[sh2->is_slave];
1303 drcblk += (pc & 0x00fff) >> SH2_DRCBLK_DA_SHIFT;
1304 *drcblk = (blkid << 1) | 1;
1305 } else if ((this_block->addr & 0xc7fc0000) == 0x06000000) { // DRAM
1306 drcblk = Pico32xMem->drcblk_ram;
1307 drcblk += (pc & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT;
1308 *drcblk = (blkid << 1) | 1;
1311 dbg(1, "-- %csh2 subblock #%d,%d %08x -> %p", sh2->is_slave ? 's' : 'm',
1312 tcache_id, blkid, pc, tcache_ptr);
1314 // since we made a block entry, link any other blocks that jump to current pc
1315 dr_link_blocks(tcache_ptr, pc, tcache_id);
1317 branch_target_ptr[i] = tcache_ptr;
1320 emit_move_r_imm32(SHR_PC, pc);
1324 sr = rcache_get_reg(SHR_SR, RC_GR_READ);
1325 emith_cmp_r_imm(sr, 0);
1326 emith_jump_cond(DCOND_LE, sh2_drc_exit);
1327 do_host_disasm(tcache_id);
1333 DasmSH2(sh2dasm_buff, pc, op);
1334 printf("%08x %04x %s\n", pc, op, sh2dasm_buff);
1346 switch ((op >> 12) & 0x0f)
1348 /////////////////////////////////////////////
1353 tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
1356 case 0: // STC SR,Rn 0000nnnn00000010
1359 case 1: // STC GBR,Rn 0000nnnn00010010
1362 case 2: // STC VBR,Rn 0000nnnn00100010
1368 tmp3 = rcache_get_reg(tmp2, RC_GR_READ);
1369 emith_move_r_r(tmp, tmp3);
1371 emith_clear_msb(tmp, tmp, 22); // reserved bits defined by ISA as 0
1374 CHECK_UNHANDLED_BITS(0xd0);
1375 // BRAF Rm 0000mmmm00100011
1376 // BSRF Rm 0000mmmm00000011
1378 tmp = rcache_get_reg(SHR_PC, RC_GR_WRITE);
1379 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
1380 emith_move_r_r(tmp, tmp2);
1382 emith_add_r_imm(tmp, pc + 2);
1384 tmp3 = rcache_get_reg(SHR_PR, RC_GR_WRITE);
1385 emith_move_r_imm(tmp3, pc + 2);
1386 emith_add_r_r(tmp, tmp3);
1391 case 0x04: // MOV.B Rm,@(R0,Rn) 0000nnnnmmmm0100
1392 case 0x05: // MOV.W Rm,@(R0,Rn) 0000nnnnmmmm0101
1393 case 0x06: // MOV.L Rm,@(R0,Rn) 0000nnnnmmmm0110
1395 tmp = rcache_get_reg_arg(1, GET_Rm());
1396 tmp2 = rcache_get_reg_arg(0, SHR_R0);
1397 tmp3 = rcache_get_reg(GET_Rn(), RC_GR_READ);
1398 emith_add_r_r(tmp2, tmp3);
1399 emit_memhandler_write(op & 3, pc, drcf.delayed_op);
1402 // MUL.L Rm,Rn 0000nnnnmmmm0111
1403 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
1404 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1405 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
1406 emith_mul(tmp3, tmp2, tmp);
1410 CHECK_UNHANDLED_BITS(0xf00);
1413 case 0: // CLRT 0000000000001000
1414 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1415 if (drcf.delayed_op)
1417 emith_bic_r_imm(sr, T);
1419 case 1: // SETT 0000000000011000
1420 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1421 if (drcf.delayed_op)
1423 emith_or_r_imm(sr, T);
1425 case 2: // CLRMAC 0000000000101000
1426 emit_move_r_imm32(SHR_MACL, 0);
1427 emit_move_r_imm32(SHR_MACH, 0);
1436 case 0: // NOP 0000000000001001
1437 CHECK_UNHANDLED_BITS(0xf00);
1439 case 1: // DIV0U 0000000000011001
1440 CHECK_UNHANDLED_BITS(0xf00);
1441 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1442 if (drcf.delayed_op)
1444 emith_bic_r_imm(sr, M|Q|T);
1446 case 2: // MOVT Rn 0000nnnn00101001
1447 sr = rcache_get_reg(SHR_SR, RC_GR_READ);
1448 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
1449 emith_clear_msb(tmp2, sr, 31);
1456 tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
1459 case 0: // STS MACH,Rn 0000nnnn00001010
1462 case 1: // STS MACL,Rn 0000nnnn00011010
1465 case 2: // STS PR,Rn 0000nnnn00101010
1471 tmp2 = rcache_get_reg(tmp2, RC_GR_READ);
1472 emith_move_r_r(tmp, tmp2);
1475 CHECK_UNHANDLED_BITS(0xf00);
1478 case 0: // RTS 0000000000001011
1480 emit_move_r_r(SHR_PC, SHR_PR);
1484 case 1: // SLEEP 0000000000011011
1485 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
1486 emith_clear_msb(tmp, tmp, 20); // clear cycles
1487 out_pc = out_pc - 2;
1490 case 2: // RTE 0000000000101011
1493 emit_memhandler_read_rr(SHR_PC, SHR_SP, 0, 2);
1495 tmp = rcache_get_reg_arg(0, SHR_SP);
1496 emith_add_r_imm(tmp, 4);
1497 tmp = emit_memhandler_read(2);
1498 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1499 emith_write_sr(sr, tmp);
1500 rcache_free_tmp(tmp);
1501 tmp = rcache_get_reg(SHR_SP, RC_GR_RMW);
1502 emith_add_r_imm(tmp, 4*2);
1511 case 0x0c: // MOV.B @(R0,Rm),Rn 0000nnnnmmmm1100
1512 case 0x0d: // MOV.W @(R0,Rm),Rn 0000nnnnmmmm1101
1513 case 0x0e: // MOV.L @(R0,Rm),Rn 0000nnnnmmmm1110
1514 tmp = emit_indirect_indexed_read(SHR_R0, GET_Rm(), op & 3);
1515 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
1516 if ((op & 3) != 2) {
1517 emith_sext(tmp2, tmp, (op & 1) ? 16 : 8);
1519 emith_move_r_r(tmp2, tmp);
1520 rcache_free_tmp(tmp);
1522 case 0x0f: // MAC.L @Rm+,@Rn+ 0000nnnnmmmm1111
1523 emit_indirect_read_double(&tmp, &tmp2, GET_Rn(), GET_Rm(), 2);
1524 tmp4 = rcache_get_reg(SHR_MACH, RC_GR_RMW);
1525 /* MS 16 MAC bits unused if saturated */
1526 sr = rcache_get_reg(SHR_SR, RC_GR_READ);
1527 emith_tst_r_imm(sr, S);
1528 EMITH_SJMP_START(DCOND_EQ);
1529 emith_clear_msb_c(DCOND_NE, tmp4, tmp4, 16);
1530 EMITH_SJMP_END(DCOND_EQ);
1532 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_RMW); // might evict SR
1533 emith_mula_s64(tmp3, tmp4, tmp, tmp2);
1534 rcache_free_tmp(tmp2);
1535 sr = rcache_get_reg(SHR_SR, RC_GR_READ); // reget just in case
1536 emith_tst_r_imm(sr, S);
1538 EMITH_JMP_START(DCOND_EQ);
1539 emith_asr(tmp, tmp4, 15);
1540 emith_cmp_r_imm(tmp, -1); // negative overflow (0x80000000..0xffff7fff)
1541 EMITH_SJMP_START(DCOND_GE);
1542 emith_move_r_imm_c(DCOND_LT, tmp4, 0x8000);
1543 emith_move_r_imm_c(DCOND_LT, tmp3, 0x0000);
1544 EMITH_SJMP_END(DCOND_GE);
1545 emith_cmp_r_imm(tmp, 0); // positive overflow (0x00008000..0x7fffffff)
1546 EMITH_SJMP_START(DCOND_LE);
1547 emith_move_r_imm_c(DCOND_GT, tmp4, 0x00007fff);
1548 emith_move_r_imm_c(DCOND_GT, tmp3, 0xffffffff);
1549 EMITH_SJMP_END(DCOND_LE);
1550 EMITH_JMP_END(DCOND_EQ);
1552 rcache_free_tmp(tmp);
1558 /////////////////////////////////////////////
1560 // MOV.L Rm,@(disp,Rn) 0001nnnnmmmmdddd
1562 tmp = rcache_get_reg_arg(0, GET_Rn());
1563 tmp2 = rcache_get_reg_arg(1, GET_Rm());
1565 emith_add_r_imm(tmp, (op & 0x0f) * 4);
1566 emit_memhandler_write(2, pc, drcf.delayed_op);
1572 case 0x00: // MOV.B Rm,@Rn 0010nnnnmmmm0000
1573 case 0x01: // MOV.W Rm,@Rn 0010nnnnmmmm0001
1574 case 0x02: // MOV.L Rm,@Rn 0010nnnnmmmm0010
1576 rcache_get_reg_arg(0, GET_Rn());
1577 rcache_get_reg_arg(1, GET_Rm());
1578 emit_memhandler_write(op & 3, pc, drcf.delayed_op);
1580 case 0x04: // MOV.B Rm,@–Rn 0010nnnnmmmm0100
1581 case 0x05: // MOV.W Rm,@–Rn 0010nnnnmmmm0101
1582 case 0x06: // MOV.L Rm,@–Rn 0010nnnnmmmm0110
1583 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1584 emith_sub_r_imm(tmp, (1 << (op & 3)));
1586 rcache_get_reg_arg(0, GET_Rn());
1587 rcache_get_reg_arg(1, GET_Rm());
1588 emit_memhandler_write(op & 3, pc, drcf.delayed_op);
1590 case 0x07: // DIV0S Rm,Rn 0010nnnnmmmm0111
1591 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1592 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
1593 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1594 if (drcf.delayed_op)
1596 emith_bic_r_imm(sr, M|Q|T);
1597 emith_tst_r_imm(tmp2, (1<<31));
1598 EMITH_SJMP_START(DCOND_EQ);
1599 emith_or_r_imm_c(DCOND_NE, sr, Q);
1600 EMITH_SJMP_END(DCOND_EQ);
1601 emith_tst_r_imm(tmp3, (1<<31));
1602 EMITH_SJMP_START(DCOND_EQ);
1603 emith_or_r_imm_c(DCOND_NE, sr, M);
1604 EMITH_SJMP_END(DCOND_EQ);
1605 emith_teq_r_r(tmp2, tmp3);
1606 EMITH_SJMP_START(DCOND_PL);
1607 emith_or_r_imm_c(DCOND_MI, sr, T);
1608 EMITH_SJMP_END(DCOND_PL);
1610 case 0x08: // TST Rm,Rn 0010nnnnmmmm1000
1611 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1612 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
1613 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1614 if (drcf.delayed_op)
1616 emith_bic_r_imm(sr, T);
1617 emith_tst_r_r(tmp2, tmp3);
1618 emit_or_t_if_eq(sr);
1620 case 0x09: // AND Rm,Rn 0010nnnnmmmm1001
1621 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1622 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1623 emith_and_r_r(tmp, tmp2);
1625 case 0x0a: // XOR Rm,Rn 0010nnnnmmmm1010
1626 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1627 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1628 emith_eor_r_r(tmp, tmp2);
1630 case 0x0b: // OR Rm,Rn 0010nnnnmmmm1011
1631 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1632 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1633 emith_or_r_r(tmp, tmp2);
1635 case 0x0c: // CMP/STR Rm,Rn 0010nnnnmmmm1100
1636 tmp = rcache_get_tmp();
1637 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
1638 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1639 emith_eor_r_r_r(tmp, tmp2, tmp3);
1640 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1641 if (drcf.delayed_op)
1643 emith_bic_r_imm(sr, T);
1644 emith_tst_r_imm(tmp, 0x000000ff);
1645 emit_or_t_if_eq(tmp);
1646 emith_tst_r_imm(tmp, 0x0000ff00);
1647 emit_or_t_if_eq(tmp);
1648 emith_tst_r_imm(tmp, 0x00ff0000);
1649 emit_or_t_if_eq(tmp);
1650 emith_tst_r_imm(tmp, 0xff000000);
1651 emit_or_t_if_eq(tmp);
1652 rcache_free_tmp(tmp);
1654 case 0x0d: // XTRCT Rm,Rn 0010nnnnmmmm1101
1655 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1656 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1657 emith_lsr(tmp, tmp, 16);
1658 emith_or_r_r_lsl(tmp, tmp2, 16);
1660 case 0x0e: // MULU.W Rm,Rn 0010nnnnmmmm1110
1661 case 0x0f: // MULS.W Rm,Rn 0010nnnnmmmm1111
1662 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
1663 tmp = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
1665 emith_sext(tmp, tmp2, 16);
1667 emith_clear_msb(tmp, tmp2, 16);
1668 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1669 tmp2 = rcache_get_tmp();
1671 emith_sext(tmp2, tmp3, 16);
1673 emith_clear_msb(tmp2, tmp3, 16);
1674 emith_mul(tmp, tmp, tmp2);
1675 rcache_free_tmp(tmp2);
1676 // FIXME: causes timing issues in Doom?
1682 /////////////////////////////////////////////
1686 case 0x00: // CMP/EQ Rm,Rn 0011nnnnmmmm0000
1687 case 0x02: // CMP/HS Rm,Rn 0011nnnnmmmm0010
1688 case 0x03: // CMP/GE Rm,Rn 0011nnnnmmmm0011
1689 case 0x06: // CMP/HI Rm,Rn 0011nnnnmmmm0110
1690 case 0x07: // CMP/GT Rm,Rn 0011nnnnmmmm0111
1691 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1692 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
1693 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1694 if (drcf.delayed_op)
1696 emith_bic_r_imm(sr, T);
1697 emith_cmp_r_r(tmp2, tmp3);
1700 case 0x00: // CMP/EQ
1701 emit_or_t_if_eq(sr);
1703 case 0x02: // CMP/HS
1704 EMITH_SJMP_START(DCOND_LO);
1705 emith_or_r_imm_c(DCOND_HS, sr, T);
1706 EMITH_SJMP_END(DCOND_LO);
1708 case 0x03: // CMP/GE
1709 EMITH_SJMP_START(DCOND_LT);
1710 emith_or_r_imm_c(DCOND_GE, sr, T);
1711 EMITH_SJMP_END(DCOND_LT);
1713 case 0x06: // CMP/HI
1714 EMITH_SJMP_START(DCOND_LS);
1715 emith_or_r_imm_c(DCOND_HI, sr, T);
1716 EMITH_SJMP_END(DCOND_LS);
1718 case 0x07: // CMP/GT
1719 EMITH_SJMP_START(DCOND_LE);
1720 emith_or_r_imm_c(DCOND_GT, sr, T);
1721 EMITH_SJMP_END(DCOND_LE);
1725 case 0x04: // DIV1 Rm,Rn 0011nnnnmmmm0100
1726 // Q1 = carry(Rn = (Rn << 1) | T)
1728 // Q2 = carry(Rn += Rm)
1730 // Q2 = carry(Rn -= Rm)
1732 // T = (Q == M) = !(Q ^ M) = !(Q1 ^ Q2)
1733 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1734 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1735 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1736 if (drcf.delayed_op)
1738 emith_tpop_carry(sr, 0);
1739 emith_adcf_r_r(tmp2, tmp2);
1740 emith_tpush_carry(sr, 0); // keep Q1 in T for now
1741 tmp4 = rcache_get_tmp();
1742 emith_and_r_r_imm(tmp4, sr, M);
1743 emith_eor_r_r_lsr(sr, tmp4, M_SHIFT - Q_SHIFT); // Q ^= M
1744 rcache_free_tmp(tmp4);
1745 // add or sub, invert T if carry to get Q1 ^ Q2
1746 // in: (Q ^ M) passed in Q, Q1 in T
1747 emith_sh2_div1_step(tmp2, tmp3, sr);
1748 emith_bic_r_imm(sr, Q);
1749 emith_tst_r_imm(sr, M);
1750 EMITH_SJMP_START(DCOND_EQ);
1751 emith_or_r_imm_c(DCOND_NE, sr, Q); // Q = M
1752 EMITH_SJMP_END(DCOND_EQ);
1753 emith_tst_r_imm(sr, T);
1754 EMITH_SJMP_START(DCOND_EQ);
1755 emith_eor_r_imm_c(DCOND_NE, sr, Q); // Q = M ^ Q1 ^ Q2
1756 EMITH_SJMP_END(DCOND_EQ);
1757 emith_eor_r_imm(sr, T); // T = !(Q1 ^ Q2)
1759 case 0x05: // DMULU.L Rm,Rn 0011nnnnmmmm0101
1760 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
1761 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1762 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
1763 tmp4 = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
1764 emith_mul_u64(tmp3, tmp4, tmp, tmp2);
1766 case 0x08: // SUB Rm,Rn 0011nnnnmmmm1000
1767 case 0x0c: // ADD Rm,Rn 0011nnnnmmmm1100
1768 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1769 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1771 emith_add_r_r(tmp, tmp2);
1773 emith_sub_r_r(tmp, tmp2);
1775 case 0x0a: // SUBC Rm,Rn 0011nnnnmmmm1010
1776 case 0x0e: // ADDC Rm,Rn 0011nnnnmmmm1110
1777 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1778 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1779 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1780 if (drcf.delayed_op)
1782 if (op & 4) { // adc
1783 emith_tpop_carry(sr, 0);
1784 emith_adcf_r_r(tmp, tmp2);
1785 emith_tpush_carry(sr, 0);
1787 emith_tpop_carry(sr, 1);
1788 emith_sbcf_r_r(tmp, tmp2);
1789 emith_tpush_carry(sr, 1);
1792 case 0x0b: // SUBV Rm,Rn 0011nnnnmmmm1011
1793 case 0x0f: // ADDV Rm,Rn 0011nnnnmmmm1111
1794 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1795 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1796 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1797 if (drcf.delayed_op)
1799 emith_bic_r_imm(sr, T);
1801 emith_addf_r_r(tmp, tmp2);
1803 emith_subf_r_r(tmp, tmp2);
1804 EMITH_SJMP_START(DCOND_VC);
1805 emith_or_r_imm_c(DCOND_VS, sr, T);
1806 EMITH_SJMP_END(DCOND_VC);
1808 case 0x0d: // DMULS.L Rm,Rn 0011nnnnmmmm1101
1809 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
1810 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1811 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
1812 tmp4 = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
1813 emith_mul_s64(tmp3, tmp4, tmp, tmp2);
1818 /////////////////////////////////////////////
1825 case 0: // SHLL Rn 0100nnnn00000000
1826 case 2: // SHAL Rn 0100nnnn00100000
1827 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1828 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1829 if (drcf.delayed_op)
1831 emith_tpop_carry(sr, 0); // dummy
1832 emith_lslf(tmp, tmp, 1);
1833 emith_tpush_carry(sr, 0);
1835 case 1: // DT Rn 0100nnnn00010000
1836 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1837 if (drcf.delayed_op)
1839 if (FETCH_OP(pc) == 0x8bfd) { // BF #-2
1840 if (gconst_get(GET_Rn(), &tmp)) {
1841 // XXX: limit burned cycles
1842 emit_move_r_imm32(GET_Rn(), 0);
1843 emith_or_r_imm(sr, T);
1848 emith_sh2_dtbf_loop();
1851 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1852 emith_bic_r_imm(sr, T);
1853 emith_subf_r_imm(tmp, 1);
1854 emit_or_t_if_eq(sr);
1861 case 0: // SHLR Rn 0100nnnn00000001
1862 case 2: // SHAR Rn 0100nnnn00100001
1863 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1864 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1865 if (drcf.delayed_op)
1867 emith_tpop_carry(sr, 0); // dummy
1869 emith_asrf(tmp, tmp, 1);
1871 emith_lsrf(tmp, tmp, 1);
1872 emith_tpush_carry(sr, 0);
1874 case 1: // CMP/PZ Rn 0100nnnn00010001
1875 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1876 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1877 if (drcf.delayed_op)
1879 emith_bic_r_imm(sr, T);
1880 emith_cmp_r_imm(tmp, 0);
1881 EMITH_SJMP_START(DCOND_LT);
1882 emith_or_r_imm_c(DCOND_GE, sr, T);
1883 EMITH_SJMP_END(DCOND_LT);
1891 case 0x02: // STS.L MACH,@–Rn 0100nnnn00000010
1894 case 0x12: // STS.L MACL,@–Rn 0100nnnn00010010
1897 case 0x22: // STS.L PR,@–Rn 0100nnnn00100010
1900 case 0x03: // STC.L SR,@–Rn 0100nnnn00000011
1903 case 0x13: // STC.L GBR,@–Rn 0100nnnn00010011
1906 case 0x23: // STC.L VBR,@–Rn 0100nnnn00100011
1912 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1913 emith_sub_r_imm(tmp2, 4);
1915 rcache_get_reg_arg(0, GET_Rn());
1916 tmp3 = rcache_get_reg_arg(1, tmp);
1918 emith_clear_msb(tmp3, tmp3, 22); // reserved bits defined by ISA as 0
1919 emit_memhandler_write(2, pc, drcf.delayed_op);
1925 case 0x04: // ROTL Rn 0100nnnn00000100
1926 case 0x05: // ROTR Rn 0100nnnn00000101
1927 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1928 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1929 if (drcf.delayed_op)
1931 emith_tpop_carry(sr, 0); // dummy
1933 emith_rorf(tmp, tmp, 1);
1935 emith_rolf(tmp, tmp, 1);
1936 emith_tpush_carry(sr, 0);
1938 case 0x24: // ROTCL Rn 0100nnnn00100100
1939 case 0x25: // ROTCR Rn 0100nnnn00100101
1940 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1941 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1942 if (drcf.delayed_op)
1944 emith_tpop_carry(sr, 0);
1949 emith_tpush_carry(sr, 0);
1951 case 0x15: // CMP/PL Rn 0100nnnn00010101
1952 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1953 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1954 if (drcf.delayed_op)
1956 emith_bic_r_imm(sr, T);
1957 emith_cmp_r_imm(tmp, 0);
1958 EMITH_SJMP_START(DCOND_LE);
1959 emith_or_r_imm_c(DCOND_GT, sr, T);
1960 EMITH_SJMP_END(DCOND_LE);
1968 case 0x06: // LDS.L @Rm+,MACH 0100mmmm00000110
1971 case 0x16: // LDS.L @Rm+,MACL 0100mmmm00010110
1974 case 0x26: // LDS.L @Rm+,PR 0100mmmm00100110
1977 case 0x07: // LDC.L @Rm+,SR 0100mmmm00000111
1980 case 0x17: // LDC.L @Rm+,GBR 0100mmmm00010111
1983 case 0x27: // LDC.L @Rm+,VBR 0100mmmm00100111
1989 rcache_get_reg_arg(0, GET_Rn());
1990 tmp2 = emit_memhandler_read(2);
1991 if (tmp == SHR_SR) {
1992 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1993 if (drcf.delayed_op)
1995 emith_write_sr(sr, tmp2);
1998 tmp = rcache_get_reg(tmp, RC_GR_WRITE);
1999 emith_move_r_r(tmp, tmp2);
2001 rcache_free_tmp(tmp2);
2002 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
2003 emith_add_r_imm(tmp, 4);
2010 // SHLL2 Rn 0100nnnn00001000
2011 // SHLR2 Rn 0100nnnn00001001
2015 // SHLL8 Rn 0100nnnn00011000
2016 // SHLR8 Rn 0100nnnn00011001
2020 // SHLL16 Rn 0100nnnn00101000
2021 // SHLR16 Rn 0100nnnn00101001
2027 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_RMW);
2029 emith_lsr(tmp2, tmp2, tmp);
2031 emith_lsl(tmp2, tmp2, tmp);
2036 case 0: // LDS Rm,MACH 0100mmmm00001010
2039 case 1: // LDS Rm,MACL 0100mmmm00011010
2042 case 2: // LDS Rm,PR 0100mmmm00101010
2048 emit_move_r_r(tmp2, GET_Rn());
2053 case 0: // JSR @Rm 0100mmmm00001011
2054 case 2: // JMP @Rm 0100mmmm00101011
2057 emit_move_r_imm32(SHR_PR, pc + 2);
2058 emit_move_r_r(SHR_PC, (op >> 8) & 0x0f);
2062 case 1: // TAS.B @Rn 0100nnnn00011011
2063 // XXX: is TAS working on 32X?
2064 rcache_get_reg_arg(0, GET_Rn());
2065 tmp = emit_memhandler_read(0);
2066 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2067 if (drcf.delayed_op)
2069 emith_bic_r_imm(sr, T);
2070 emith_cmp_r_imm(tmp, 0);
2071 emit_or_t_if_eq(sr);
2073 emith_or_r_imm(tmp, 0x80);
2074 tmp2 = rcache_get_tmp_arg(1); // assuming it differs to tmp
2075 emith_move_r_r(tmp2, tmp);
2076 rcache_free_tmp(tmp);
2077 rcache_get_reg_arg(0, GET_Rn());
2078 emit_memhandler_write(0, pc, drcf.delayed_op);
2086 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
2089 case 0: // LDC Rm,SR 0100mmmm00001110
2092 case 1: // LDC Rm,GBR 0100mmmm00011110
2095 case 2: // LDC Rm,VBR 0100mmmm00101110
2101 if (tmp2 == SHR_SR) {
2102 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2103 if (drcf.delayed_op)
2105 emith_write_sr(sr, tmp);
2108 tmp2 = rcache_get_reg(tmp2, RC_GR_WRITE);
2109 emith_move_r_r(tmp2, tmp);
2113 // MAC.W @Rm+,@Rn+ 0100nnnnmmmm1111
2114 emit_indirect_read_double(&tmp, &tmp2, GET_Rn(), GET_Rm(), 1);
2115 emith_sext(tmp, tmp, 16);
2116 emith_sext(tmp2, tmp2, 16);
2117 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_RMW);
2118 tmp4 = rcache_get_reg(SHR_MACH, RC_GR_RMW);
2119 emith_mula_s64(tmp3, tmp4, tmp, tmp2);
2120 rcache_free_tmp(tmp2);
2121 // XXX: MACH should be untouched when S is set?
2122 sr = rcache_get_reg(SHR_SR, RC_GR_READ);
2123 emith_tst_r_imm(sr, S);
2124 EMITH_JMP_START(DCOND_EQ);
2126 emith_asr(tmp, tmp3, 31);
2127 emith_eorf_r_r(tmp, tmp4); // tmp = ((signed)macl >> 31) ^ mach
2128 EMITH_JMP_START(DCOND_EQ);
2129 emith_move_r_imm(tmp3, 0x80000000);
2130 emith_tst_r_r(tmp4, tmp4);
2131 EMITH_SJMP_START(DCOND_MI);
2132 emith_sub_r_imm_c(DCOND_PL, tmp3, 1); // positive
2133 EMITH_SJMP_END(DCOND_MI);
2134 EMITH_JMP_END(DCOND_EQ);
2136 EMITH_JMP_END(DCOND_EQ);
2137 rcache_free_tmp(tmp);
2143 /////////////////////////////////////////////
2145 // MOV.L @(disp,Rm),Rn 0101nnnnmmmmdddd
2146 emit_memhandler_read_rr(GET_Rn(), GET_Rm(), (op & 0x0f) * 4, 2);
2149 /////////////////////////////////////////////
2153 case 0x00: // MOV.B @Rm,Rn 0110nnnnmmmm0000
2154 case 0x01: // MOV.W @Rm,Rn 0110nnnnmmmm0001
2155 case 0x02: // MOV.L @Rm,Rn 0110nnnnmmmm0010
2156 case 0x04: // MOV.B @Rm+,Rn 0110nnnnmmmm0100
2157 case 0x05: // MOV.W @Rm+,Rn 0110nnnnmmmm0101
2158 case 0x06: // MOV.L @Rm+,Rn 0110nnnnmmmm0110
2159 emit_memhandler_read_rr(GET_Rn(), GET_Rm(), 0, op & 3);
2160 if ((op & 7) >= 4 && GET_Rn() != GET_Rm()) {
2161 tmp = rcache_get_reg(GET_Rm(), RC_GR_RMW);
2162 emith_add_r_imm(tmp, (1 << (op & 3)));
2167 tmp = rcache_get_reg(GET_Rm(), RC_GR_READ);
2168 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
2171 case 0x03: // MOV Rm,Rn 0110nnnnmmmm0011
2172 emith_move_r_r(tmp2, tmp);
2174 case 0x07: // NOT Rm,Rn 0110nnnnmmmm0111
2175 emith_mvn_r_r(tmp2, tmp);
2177 case 0x08: // SWAP.B Rm,Rn 0110nnnnmmmm1000
2180 tmp3 = rcache_get_tmp();
2181 tmp4 = rcache_get_tmp();
2182 emith_lsr(tmp3, tmp, 16);
2183 emith_or_r_r_lsl(tmp3, tmp, 24);
2184 emith_and_r_r_imm(tmp4, tmp, 0xff00);
2185 emith_or_r_r_lsl(tmp3, tmp4, 8);
2186 emith_rol(tmp2, tmp3, 16);
2187 rcache_free_tmp(tmp4);
2189 rcache_free_tmp(tmp3);
2191 case 0x09: // SWAP.W Rm,Rn 0110nnnnmmmm1001
2192 emith_rol(tmp2, tmp, 16);
2194 case 0x0a: // NEGC Rm,Rn 0110nnnnmmmm1010
2195 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2196 if (drcf.delayed_op)
2198 emith_tpop_carry(sr, 1);
2199 emith_negcf_r_r(tmp2, tmp);
2200 emith_tpush_carry(sr, 1);
2202 case 0x0b: // NEG Rm,Rn 0110nnnnmmmm1011
2203 emith_neg_r_r(tmp2, tmp);
2205 case 0x0c: // EXTU.B Rm,Rn 0110nnnnmmmm1100
2206 emith_clear_msb(tmp2, tmp, 24);
2208 case 0x0d: // EXTU.W Rm,Rn 0110nnnnmmmm1101
2209 emith_clear_msb(tmp2, tmp, 16);
2211 case 0x0e: // EXTS.B Rm,Rn 0110nnnnmmmm1110
2212 emith_sext(tmp2, tmp, 8);
2214 case 0x0f: // EXTS.W Rm,Rn 0110nnnnmmmm1111
2215 emith_sext(tmp2, tmp, 16);
2222 /////////////////////////////////////////////
2224 // ADD #imm,Rn 0111nnnniiiiiiii
2225 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
2226 if (op & 0x80) { // adding negative
2227 emith_sub_r_imm(tmp, -op & 0xff);
2229 emith_add_r_imm(tmp, op & 0xff);
2232 /////////////////////////////////////////////
2234 switch (op & 0x0f00)
2236 case 0x0000: // MOV.B R0,@(disp,Rn) 10000000nnnndddd
2237 case 0x0100: // MOV.W R0,@(disp,Rn) 10000001nnnndddd
2239 tmp = rcache_get_reg_arg(0, GET_Rm());
2240 tmp2 = rcache_get_reg_arg(1, SHR_R0);
2241 tmp3 = (op & 0x100) >> 8;
2243 emith_add_r_imm(tmp, (op & 0x0f) << tmp3);
2244 emit_memhandler_write(tmp3, pc, drcf.delayed_op);
2246 case 0x0400: // MOV.B @(disp,Rm),R0 10000100mmmmdddd
2247 case 0x0500: // MOV.W @(disp,Rm),R0 10000101mmmmdddd
2248 tmp = (op & 0x100) >> 8;
2249 emit_memhandler_read_rr(SHR_R0, GET_Rm(), (op & 0x0f) << tmp, tmp);
2251 case 0x0800: // CMP/EQ #imm,R0 10001000iiiiiiii
2252 // XXX: could use cmn
2253 tmp = rcache_get_tmp();
2254 tmp2 = rcache_get_reg(0, RC_GR_READ);
2255 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2256 if (drcf.delayed_op)
2258 emith_move_r_imm_s8(tmp, op & 0xff);
2259 emith_bic_r_imm(sr, T);
2260 emith_cmp_r_r(tmp2, tmp);
2261 emit_or_t_if_eq(sr);
2262 rcache_free_tmp(tmp);
2264 case 0x0d00: // BT/S label 10001101dddddddd
2265 case 0x0f00: // BF/S label 10001111dddddddd
2269 case 0x0900: // BT label 10001001dddddddd
2270 case 0x0b00: // BF label 10001011dddddddd
2271 // will handle conditional branches later
2272 pending_branch_cond = (op & 0x0200) ? DCOND_EQ : DCOND_NE;
2273 i = ((signed int)(op << 24) >> 23);
2274 pending_branch_pc = pc + i + 2;
2280 /////////////////////////////////////////////
2282 // MOV.W @(disp,PC),Rn 1001nnnndddddddd
2283 tmp = pc + (op & 0xff) * 2 + 2;
2284 #if PROPAGATE_CONSTANTS
2285 if (tmp < end_pc + MAX_LITERAL_OFFSET) {
2286 gconst_new(GET_Rn(), (u32)(int)(signed short)FETCH_OP(tmp));
2287 if (last_inlined_literal < tmp)
2288 last_inlined_literal = tmp;
2293 tmp2 = rcache_get_tmp_arg(0);
2294 emith_move_r_imm(tmp2, tmp);
2295 tmp2 = emit_memhandler_read(1);
2296 tmp3 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
2297 emith_sext(tmp3, tmp2, 16);
2298 rcache_free_tmp(tmp2);
2302 /////////////////////////////////////////////
2304 // BRA label 1010dddddddddddd
2306 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2307 tmp = ((signed int)(op << 20) >> 19);
2308 out_pc = pc + tmp + 2;
2310 emith_clear_msb(sr, sr, 20); // burn cycles
2314 /////////////////////////////////////////////
2316 // BSR label 1011dddddddddddd
2318 emit_move_r_imm32(SHR_PR, pc + 2);
2319 tmp = ((signed int)(op << 20) >> 19);
2320 out_pc = pc + tmp + 2;
2324 /////////////////////////////////////////////
2326 switch (op & 0x0f00)
2328 case 0x0000: // MOV.B R0,@(disp,GBR) 11000000dddddddd
2329 case 0x0100: // MOV.W R0,@(disp,GBR) 11000001dddddddd
2330 case 0x0200: // MOV.L R0,@(disp,GBR) 11000010dddddddd
2332 tmp = rcache_get_reg_arg(0, SHR_GBR);
2333 tmp2 = rcache_get_reg_arg(1, SHR_R0);
2334 tmp3 = (op & 0x300) >> 8;
2335 emith_add_r_imm(tmp, (op & 0xff) << tmp3);
2336 emit_memhandler_write(tmp3, pc, drcf.delayed_op);
2338 case 0x0400: // MOV.B @(disp,GBR),R0 11000100dddddddd
2339 case 0x0500: // MOV.W @(disp,GBR),R0 11000101dddddddd
2340 case 0x0600: // MOV.L @(disp,GBR),R0 11000110dddddddd
2341 tmp = (op & 0x300) >> 8;
2342 emit_memhandler_read_rr(SHR_R0, SHR_GBR, (op & 0xff) << tmp, tmp);
2344 case 0x0300: // TRAPA #imm 11000011iiiiiiii
2345 tmp = rcache_get_reg(SHR_SP, RC_GR_RMW);
2346 emith_sub_r_imm(tmp, 4*2);
2348 tmp = rcache_get_reg_arg(0, SHR_SP);
2349 emith_add_r_imm(tmp, 4);
2350 tmp = rcache_get_reg_arg(1, SHR_SR);
2351 emith_clear_msb(tmp, tmp, 22);
2352 emit_memhandler_write(2, pc, drcf.delayed_op);
2354 rcache_get_reg_arg(0, SHR_SP);
2355 tmp = rcache_get_tmp_arg(1);
2356 emith_move_r_imm(tmp, pc);
2357 emit_memhandler_write(2, pc, drcf.delayed_op);
2359 emit_memhandler_read_rr(SHR_PC, SHR_VBR, (op & 0xff) * 4, 2);
2363 case 0x0700: // MOVA @(disp,PC),R0 11000111dddddddd
2364 emit_move_r_imm32(SHR_R0, (pc + (op & 0xff) * 4 + 2) & ~3);
2366 case 0x0800: // TST #imm,R0 11001000iiiiiiii
2367 tmp = rcache_get_reg(SHR_R0, RC_GR_READ);
2368 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2369 if (drcf.delayed_op)
2371 emith_bic_r_imm(sr, T);
2372 emith_tst_r_imm(tmp, op & 0xff);
2373 emit_or_t_if_eq(sr);
2375 case 0x0900: // AND #imm,R0 11001001iiiiiiii
2376 tmp = rcache_get_reg(SHR_R0, RC_GR_RMW);
2377 emith_and_r_imm(tmp, op & 0xff);
2379 case 0x0a00: // XOR #imm,R0 11001010iiiiiiii
2380 tmp = rcache_get_reg(SHR_R0, RC_GR_RMW);
2381 emith_eor_r_imm(tmp, op & 0xff);
2383 case 0x0b00: // OR #imm,R0 11001011iiiiiiii
2384 tmp = rcache_get_reg(SHR_R0, RC_GR_RMW);
2385 emith_or_r_imm(tmp, op & 0xff);
2387 case 0x0c00: // TST.B #imm,@(R0,GBR) 11001100iiiiiiii
2388 tmp = emit_indirect_indexed_read(SHR_R0, SHR_GBR, 0);
2389 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2390 if (drcf.delayed_op)
2392 emith_bic_r_imm(sr, T);
2393 emith_tst_r_imm(tmp, op & 0xff);
2394 emit_or_t_if_eq(sr);
2395 rcache_free_tmp(tmp);
2398 case 0x0d00: // AND.B #imm,@(R0,GBR) 11001101iiiiiiii
2399 tmp = emit_indirect_indexed_read(SHR_R0, SHR_GBR, 0);
2400 emith_and_r_imm(tmp, op & 0xff);
2402 case 0x0e00: // XOR.B #imm,@(R0,GBR) 11001110iiiiiiii
2403 tmp = emit_indirect_indexed_read(SHR_R0, SHR_GBR, 0);
2404 emith_eor_r_imm(tmp, op & 0xff);
2406 case 0x0f00: // OR.B #imm,@(R0,GBR) 11001111iiiiiiii
2407 tmp = emit_indirect_indexed_read(SHR_R0, SHR_GBR, 0);
2408 emith_or_r_imm(tmp, op & 0xff);
2410 tmp2 = rcache_get_tmp_arg(1);
2411 emith_move_r_r(tmp2, tmp);
2412 rcache_free_tmp(tmp);
2413 tmp3 = rcache_get_reg_arg(0, SHR_GBR);
2414 tmp4 = rcache_get_reg(SHR_R0, RC_GR_READ);
2415 emith_add_r_r(tmp3, tmp4);
2416 emit_memhandler_write(0, pc, drcf.delayed_op);
2422 /////////////////////////////////////////////
2424 // MOV.L @(disp,PC),Rn 1101nnnndddddddd
2425 tmp = (pc + (op & 0xff) * 4 + 2) & ~3;
2426 #if PROPAGATE_CONSTANTS
2427 if (tmp < end_pc + MAX_LITERAL_OFFSET) {
2428 gconst_new(GET_Rn(), FETCH32(tmp));
2429 if (last_inlined_literal < tmp)
2430 last_inlined_literal = tmp;
2435 tmp2 = rcache_get_tmp_arg(0);
2436 emith_move_r_imm(tmp2, tmp);
2437 tmp2 = emit_memhandler_read(2);
2438 tmp3 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
2439 emith_move_r_r(tmp3, tmp2);
2440 rcache_free_tmp(tmp2);
2444 /////////////////////////////////////////////
2446 // MOV #imm,Rn 1110nnnniiiiiiii
2447 emit_move_r_imm32(GET_Rn(), (u32)(signed int)(signed char)op);
2452 elprintf(EL_ANOMALY, "%csh2 drc: unhandled op %04x @ %08x",
2453 sh2->is_slave ? 's' : 'm', op, pc - 2);
2454 #ifdef DRC_DEBUG_INTERP
2455 emit_move_r_imm32(SHR_PC, pc - 2);
2457 emith_pass_arg_r(0, CONTEXT_REG);
2458 emith_pass_arg_imm(1, op);
2459 emith_call(sh2_do_op);
2465 rcache_unlock_all();
2467 // conditional branch handling (with/without delay)
2468 if (pending_branch_cond != -1 && drcf.delayed_op != 2)
2470 u32 target_pc = pending_branch_pc;
2473 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2477 if (drcf.use_saved_t)
2478 emith_tst_r_imm(sr, T_save);
2480 emith_tst_r_imm(sr, T);
2482 if (find_in_array(branch_target_pc, branch_target_count, target_pc) >= 0) {
2484 // XXX: jumps back can be linked already
2485 branch_patch_pc[branch_patch_count] = target_pc;
2486 branch_patch_ptr[branch_patch_count] = tcache_ptr;
2487 emith_jump_cond_patchable(pending_branch_cond, tcache_ptr);
2489 branch_patch_count++;
2490 if (branch_patch_count == MAX_LOCAL_BRANCHES) {
2491 printf("warning: too many local branches\n");
2496 // can't resolve branch locally, make a block exit
2497 emit_move_r_imm32(SHR_PC, target_pc);
2500 target = dr_prepare_ext_branch(target_pc, sh2, tcache_id);
2503 emith_jump_cond_patchable(pending_branch_cond, target);
2506 drcf.use_saved_t = 0;
2507 pending_branch_cond = -1;
2511 // XXX: delay slots..
2512 if (drcf.test_irq && drcf.delayed_op != 2) {
2513 if (!drcf.delayed_op)
2514 emit_move_r_imm32(SHR_PC, pc);
2515 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2518 emith_call(sh2_drc_test_irq);
2522 do_host_disasm(tcache_id);
2524 if (out_pc != 0 && drcf.delayed_op != 2)
2528 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
2532 if (out_pc == (u32)-1) {
2533 // indirect jump -> back to dispatcher
2534 emith_jump(sh2_drc_dispatcher);
2539 emit_move_r_imm32(SHR_PC, out_pc);
2542 target = dr_prepare_ext_branch(out_pc, sh2, tcache_id);
2545 emith_jump_patchable(target);
2548 // link local branches
2549 for (i = 0; i < branch_patch_count; i++) {
2552 t = find_in_array(branch_target_pc, branch_target_count, branch_patch_pc[i]);
2553 target = branch_target_ptr[t];
2554 if (target == NULL) {
2555 // flush pc and go back to dispatcher (should no longer happen)
2556 printf("stray branch to %08x %p\n", branch_patch_pc[i], tcache_ptr);
2557 target = tcache_ptr;
2558 emit_move_r_imm32(SHR_PC, branch_patch_pc[i]);
2560 emith_jump(sh2_drc_dispatcher);
2562 emith_jump_patch(branch_patch_ptr[i], target);
2565 this_block->end_addr = pc;
2566 if (last_inlined_literal > pc)
2567 this_block->end_addr = last_inlined_literal + 4;
2569 // mark memory blocks as containing compiled code
2570 if (tcache_id != 0) {
2572 u16 *drcblk = Pico32xMem->drcblk_da[sh2->is_slave];
2573 tmp = (this_block->addr & 0xfff) >> SH2_DRCBLK_DA_SHIFT;
2574 tmp2 = (this_block->end_addr & 0xfff) >> SH2_DRCBLK_DA_SHIFT;
2575 drcblk[tmp] = (blkid_main << 1) | 1;
2576 for (++tmp; tmp < tmp2; tmp++) {
2578 continue; // dont overwrite overlay block(s)
2579 drcblk[tmp] = blkid_main << 1;
2582 else if ((this_block->addr & 0xc7fc0000) == 0x06000000) { // DRAM
2583 tmp = (this_block->addr & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT;
2584 tmp2 = (this_block->end_addr & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT;
2585 Pico32xMem->drcblk_ram[tmp] = (blkid_main << 1) | 1;
2586 for (++tmp; tmp < tmp2; tmp++) {
2587 if (Pico32xMem->drcblk_ram[tmp])
2589 Pico32xMem->drcblk_ram[tmp] = blkid_main << 1;
2593 tcache_ptrs[tcache_id] = tcache_ptr;
2596 cache_flush_d_inval_i(block_entry, tcache_ptr);
2599 do_host_disasm(tcache_id);
2600 dbg(1, " block #%d,%d tcache %d/%d, insns %d -> %d %.3f",
2601 tcache_id, block_counts[tcache_id],
2602 tcache_ptr - tcache_bases[tcache_id], tcache_sizes[tcache_id],
2603 insns_compiled, host_insn_count, (double)host_insn_count / insns_compiled);
2604 if ((sh2->pc & 0xc6000000) == 0x02000000) // ROM
2605 dbg(1, " hash collisions %d/%d", hash_collisions, block_counts[tcache_id]);
2608 tcache_dsm_ptrs[tcache_id] = block_entry;
2609 do_host_disasm(tcache_id);
2620 static void sh2_generate_utils(void)
2622 int arg0, arg1, arg2, sr, tmp;
2623 void *sh2_drc_write_end, *sh2_drc_write_slot_end;
2625 host_arg2reg(arg0, 0);
2626 host_arg2reg(arg1, 1);
2627 host_arg2reg(arg2, 2);
2628 emith_move_r_r(arg0, arg0); // nop
2630 // sh2_drc_exit(void)
2631 sh2_drc_exit = (void *)tcache_ptr;
2632 emit_do_static_regs(1, arg2);
2633 emith_sh2_drc_exit();
2635 // sh2_drc_dispatcher(void)
2636 sh2_drc_dispatcher = (void *)tcache_ptr;
2637 sr = rcache_get_reg(SHR_SR, RC_GR_READ);
2638 emith_cmp_r_imm(sr, 0);
2639 emith_jump_cond(DCOND_LT, sh2_drc_exit);
2640 rcache_invalidate();
2641 emith_ctx_read(arg0, SHR_PC * 4);
2642 emith_ctx_read(arg1, offsetof(SH2, is_slave));
2643 emith_add_r_r_imm(arg2, CONTEXT_REG, offsetof(SH2, drc_tmp));
2644 emith_call(lookup_block);
2646 // lookup failed, call sh2_translate()
2647 emith_move_r_r(arg0, CONTEXT_REG);
2648 emith_ctx_read(arg1, offsetof(SH2, drc_tmp)); // tcache_id
2649 emith_call(sh2_translate);
2651 // sh2_translate() failed, flush cache and retry
2652 emith_ctx_read(arg0, offsetof(SH2, drc_tmp));
2653 emith_call(flush_tcache);
2654 emith_move_r_r(arg0, CONTEXT_REG);
2655 emith_ctx_read(arg1, offsetof(SH2, drc_tmp));
2656 emith_call(sh2_translate);
2658 // XXX: can't translate, fail
2661 // sh2_drc_test_irq(void)
2662 // assumes it's called from main function (may jump to dispatcher)
2663 sh2_drc_test_irq = (void *)tcache_ptr;
2664 emith_ctx_read(arg1, offsetof(SH2, pending_level));
2665 sr = rcache_get_reg(SHR_SR, RC_GR_READ);
2666 emith_lsr(arg0, sr, I_SHIFT);
2667 emith_and_r_imm(arg0, 0x0f);
2668 emith_cmp_r_r(arg1, arg0); // pending_level > ((sr >> 4) & 0x0f)?
2669 EMITH_SJMP_START(DCOND_GT);
2670 emith_ret_c(DCOND_LE); // nope, return
2671 EMITH_SJMP_END(DCOND_GT);
2673 tmp = rcache_get_reg(SHR_SP, RC_GR_RMW);
2674 emith_sub_r_imm(tmp, 4*2);
2677 tmp = rcache_get_reg_arg(0, SHR_SP);
2678 emith_add_r_imm(tmp, 4);
2679 tmp = rcache_get_reg_arg(1, SHR_SR);
2680 emith_clear_msb(tmp, tmp, 22);
2681 emith_move_r_r(arg2, CONTEXT_REG);
2682 emith_call(p32x_sh2_write32);
2683 rcache_invalidate();
2685 rcache_get_reg_arg(0, SHR_SP);
2686 emith_ctx_read(arg1, SHR_PC * 4);
2687 emith_move_r_r(arg2, CONTEXT_REG);
2688 emith_call(p32x_sh2_write32);
2689 rcache_invalidate();
2690 // update I, cycles, do callback
2691 emith_ctx_read(arg1, offsetof(SH2, pending_level));
2692 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2693 emith_bic_r_imm(sr, I);
2694 emith_or_r_r_lsl(sr, arg1, I_SHIFT);
2695 emith_sub_r_imm(sr, 13 << 12); // at least 13 cycles
2697 emith_move_r_r(arg0, CONTEXT_REG);
2698 emith_call_ctx(offsetof(SH2, irq_callback)); // vector = sh2->irq_callback(sh2, level);
2700 emith_lsl(arg0, arg0, 2);
2701 emith_ctx_read(arg1, SHR_VBR * 4);
2702 emith_add_r_r(arg0, arg1);
2703 emit_memhandler_read(2);
2704 emith_ctx_write(arg0, SHR_PC * 4);
2706 emith_add_r_imm(xSP, 4); // fix stack
2708 emith_jump(sh2_drc_dispatcher);
2709 rcache_invalidate();
2711 // sh2_drc_entry(SH2 *sh2)
2712 sh2_drc_entry = (void *)tcache_ptr;
2713 emith_sh2_drc_entry();
2714 emith_move_r_r(CONTEXT_REG, arg0); // move ctx, arg0
2715 emit_do_static_regs(0, arg2);
2716 emith_call(sh2_drc_test_irq);
2717 emith_jump(sh2_drc_dispatcher);
2719 // write-caused irq detection
2720 sh2_drc_write_end = tcache_ptr;
2721 emith_tst_r_r(arg0, arg0);
2722 EMITH_SJMP_START(DCOND_NE);
2723 emith_jump_ctx_c(DCOND_EQ, offsetof(SH2, drc_tmp)); // return
2724 EMITH_SJMP_END(DCOND_NE);
2725 // since PC is up to date, jump to it's block instead of returning
2726 emith_call(sh2_drc_test_irq);
2727 emith_jump_ctx(offsetof(SH2, drc_tmp));
2729 // write-caused irq detection for writes in delay slot
2730 sh2_drc_write_slot_end = tcache_ptr;
2731 emith_tst_r_r(arg0, arg0);
2732 EMITH_SJMP_START(DCOND_NE);
2733 emith_jump_ctx_c(DCOND_EQ, offsetof(SH2, drc_tmp));
2734 EMITH_SJMP_END(DCOND_NE);
2735 // just burn cycles to get back to dispatcher after branch is handled
2736 sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2737 emith_ctx_write(sr, offsetof(SH2, irq_cycles));
2738 emith_clear_msb(sr, sr, 20); // clear cycles
2740 emith_jump_ctx(offsetof(SH2, drc_tmp));
2742 // sh2_drc_write8(u32 a, u32 d)
2743 sh2_drc_write8 = (void *)tcache_ptr;
2744 emith_ret_to_ctx(offsetof(SH2, drc_tmp));
2745 emith_ctx_read(arg2, offsetof(SH2, write8_tab));
2746 emith_sh2_wcall(arg0, arg2, sh2_drc_write_end);
2748 // sh2_drc_write16(u32 a, u32 d)
2749 sh2_drc_write16 = (void *)tcache_ptr;
2750 emith_ret_to_ctx(offsetof(SH2, drc_tmp));
2751 emith_ctx_read(arg2, offsetof(SH2, write16_tab));
2752 emith_sh2_wcall(arg0, arg2, sh2_drc_write_end);
2754 // sh2_drc_write8_slot(u32 a, u32 d)
2755 sh2_drc_write8_slot = (void *)tcache_ptr;
2756 emith_ret_to_ctx(offsetof(SH2, drc_tmp));
2757 emith_ctx_read(arg2, offsetof(SH2, write8_tab));
2758 emith_sh2_wcall(arg0, arg2, sh2_drc_write_slot_end);
2760 // sh2_drc_write16_slot(u32 a, u32 d)
2761 sh2_drc_write16_slot = (void *)tcache_ptr;
2762 emith_ret_to_ctx(offsetof(SH2, drc_tmp));
2763 emith_ctx_read(arg2, offsetof(SH2, write16_tab));
2764 emith_sh2_wcall(arg0, arg2, sh2_drc_write_slot_end);
2766 rcache_invalidate();
2768 host_dasm_new_symbol(sh2_drc_entry);
2769 host_dasm_new_symbol(sh2_drc_dispatcher);
2770 host_dasm_new_symbol(sh2_drc_exit);
2771 host_dasm_new_symbol(sh2_drc_test_irq);
2772 host_dasm_new_symbol(sh2_drc_write_end);
2773 host_dasm_new_symbol(sh2_drc_write_slot_end);
2774 host_dasm_new_symbol(sh2_drc_write8);
2775 host_dasm_new_symbol(sh2_drc_write8_slot);
2776 host_dasm_new_symbol(sh2_drc_write16);
2777 host_dasm_new_symbol(sh2_drc_write16_slot);
2781 static void sh2_smc_rm_block(u16 *drcblk, u16 *p, block_desc *btab, u32 a)
2784 block_desc *bd = btab + id;
2786 // FIXME: skip subblocks; do both directions
2787 // FIXME: collect all branches
2788 dbg(1, " killing block %08x", bd->addr);
2789 bd->addr = bd->end_addr = 0;
2791 while (p > drcblk && (p[-1] >> 1) == id)
2794 // check for possible overlay block
2795 if (p > 0 && p[-1] != 0) {
2796 bd = btab + (p[-1] >> 1);
2797 if (bd->addr <= a && a < bd->end_addr)
2798 sh2_smc_rm_block(drcblk, p - 1, btab, a);
2804 while ((*p >> 1) == id);
2807 void sh2_drc_wcheck_ram(unsigned int a, int val, int cpuid)
2809 u16 *drcblk = Pico32xMem->drcblk_ram;
2810 u16 *p = drcblk + ((a & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT);
2812 dbg(1, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a);
2813 sh2_smc_rm_block(drcblk, p, block_tables[0], a);
2816 void sh2_drc_wcheck_da(unsigned int a, int val, int cpuid)
2818 u16 *drcblk = Pico32xMem->drcblk_da[cpuid];
2819 u16 *p = drcblk + ((a & 0xfff) >> SH2_DRCBLK_DA_SHIFT);
2821 dbg(1, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a);
2822 sh2_smc_rm_block(drcblk, p, block_tables[1 + cpuid], a);
2825 void sh2_execute(SH2 *sh2c, int cycles)
2830 sh2c->cycles_aim += cycles;
2831 cycles = sh2c->cycles_aim - sh2c->cycles_done;
2833 // cycles are kept in SHR_SR unused bits (upper 20)
2834 // bit19 contains T saved for delay slot
2835 // others are usual SH2 flags
2837 sh2c->sr |= cycles << 12;
2838 sh2_drc_entry(sh2c);
2841 ret_cycles = (signed int)sh2c->sr >> 12;
2843 printf("warning: drc returned with cycles: %d\n", ret_cycles);
2845 sh2c->cycles_done += cycles - ret_cycles;
2849 void block_stats(void)
2851 int c, b, i, total = 0;
2853 printf("block stats:\n");
2854 for (b = 0; b < ARRAY_SIZE(block_tables); b++)
2855 for (i = 0; i < block_counts[b]; i++)
2856 if (block_tables[b][i].addr != 0)
2857 total += block_tables[b][i].refcount;
2859 for (c = 0; c < 10; c++) {
2860 block_desc *blk, *maxb = NULL;
2862 for (b = 0; b < ARRAY_SIZE(block_tables); b++) {
2863 for (i = 0; i < block_counts[b]; i++) {
2864 blk = &block_tables[b][i];
2865 if (blk->addr != 0 && blk->refcount > max) {
2866 max = blk->refcount;
2873 printf("%08x %9d %2.3f%%\n", maxb->addr, maxb->refcount,
2874 (double)maxb->refcount / total * 100.0);
2878 for (b = 0; b < ARRAY_SIZE(block_tables); b++)
2879 for (i = 0; i < block_counts[b]; i++)
2880 block_tables[b][i].refcount = 0;
2883 #define block_stats()
2886 void sh2_drc_flush_all(void)
2894 void sh2_drc_mem_setup(SH2 *sh2)
2896 // fill the convenience pointers
2897 sh2->p_bios = sh2->is_slave ? Pico32xMem->sh2_rom_s : Pico32xMem->sh2_rom_m;
2898 sh2->p_da = Pico32xMem->data_array[sh2->is_slave];
2899 sh2->p_sdram = Pico32xMem->sdram;
2900 sh2->p_rom = Pico.rom;
2903 int sh2_drc_init(SH2 *sh2)
2907 if (block_tables[0] == NULL)
2909 for (i = 0; i < TCACHE_BUFFERS; i++) {
2910 block_tables[i] = calloc(block_max_counts[i], sizeof(*block_tables[0]));
2911 if (block_tables[i] == NULL)
2913 // max 2 block links (exits) per block
2914 block_links[i] = calloc(block_max_counts[i] * 2, sizeof(*block_links[0]));
2915 if (block_links[i] == NULL)
2918 memset(block_counts, 0, sizeof(block_counts));
2919 memset(block_link_counts, 0, sizeof(block_link_counts));
2922 tcache_ptr = tcache;
2923 sh2_generate_utils();
2925 cache_flush_d_inval_i(tcache, tcache_ptr);
2928 tcache_bases[0] = tcache_ptrs[0] = tcache_ptr;
2929 for (i = 1; i < ARRAY_SIZE(tcache_bases); i++)
2930 tcache_bases[i] = tcache_ptrs[i] = tcache_bases[i - 1] + tcache_sizes[i - 1];
2933 PicoOpt |= POPT_DIS_VDP_FIFO;
2936 for (i = 0; i < ARRAY_SIZE(block_tables); i++)
2937 tcache_dsm_ptrs[i] = tcache_bases[i];
2939 tcache_dsm_ptrs[0] = tcache;
2943 hash_collisions = 0;
2947 if (hash_table == NULL) {
2948 hash_table = calloc(sizeof(hash_table[0]), MAX_HASH_ENTRIES);
2949 if (hash_table == NULL)
2956 sh2_drc_finish(sh2);
2960 void sh2_drc_finish(SH2 *sh2)
2964 if (block_tables[0] != NULL) {
2967 for (i = 0; i < TCACHE_BUFFERS; i++) {
2969 printf("~~~ tcache %d\n", i);
2970 tcache_dsm_ptrs[i] = tcache_bases[i];
2971 tcache_ptr = tcache_ptrs[i];
2975 if (block_tables[i] != NULL)
2976 free(block_tables[i]);
2977 block_tables[i] = NULL;
2978 if (block_links[i] == NULL)
2979 free(block_links[i]);
2980 block_links[i] = NULL;
2986 if (hash_table != NULL) {