32x: drc: more bugfixing
[picodrive.git] / cpu / sh2 / compiler.c
1 /*
2  * vim:shiftwidth=2:expandtab
3  *
4  * notes:
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
9  * - non-main block entries are called subblocks, as they have same tracking
10  *   structures that main blocks have.
11  *
12  * implemented:
13  * - static register allocation
14  * - remaining register caching and tracking in temporaries
15  * - block-local branch linking
16  * - block linking (except between tcaches)
17  * - some constant propagation
18  *
19  * TODO:
20  * - proper SMC handling
21  * - better constant propagation
22  * - stack caching?
23  * - bug fixing
24  */
25 #include <stddef.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <assert.h>
29
30 #include "../../pico/pico_int.h"
31 #include "sh2.h"
32 #include "compiler.h"
33 #include "../drc/cmn.h"
34 #include "../debug.h"
35
36 // features
37 #define PROPAGATE_CONSTANTS     1
38 #define LINK_BRANCHES           1
39
40 // limits (per block)
41 #define BLOCK_CYCLE_LIMIT       100
42 #define MAX_BLOCK_SIZE          (BLOCK_CYCLE_LIMIT * 6 * 6)
43
44 // max literal offset from the block end
45 #define MAX_LITERAL_OFFSET      32*2
46 #define MAX_LITERALS            (BLOCK_CYCLE_LIMIT / 4)
47 #define MAX_LOCAL_BRANCHES      32
48
49 // debug stuff {
50 #ifndef DRC_DEBUG
51 #define DRC_DEBUG 0
52 #endif
53
54 #if DRC_DEBUG
55 #define dbg(l,...) { \
56   if ((l) & DRC_DEBUG) \
57     elprintf(EL_STATUS, ##__VA_ARGS__); \
58 }
59
60 #include "mame/sh2dasm.h"
61 #include <platform/linux/host_dasm.h>
62 static int insns_compiled, hash_collisions, host_insn_count;
63 #define COUNT_OP \
64         host_insn_count++
65 #else // !DRC_DEBUG
66 #define COUNT_OP
67 #define dbg(...)
68 #endif
69
70 #if (DRC_DEBUG & 2)
71 static u8 *tcache_dsm_ptrs[3];
72 static char sh2dasm_buff[64];
73 #define do_host_disasm(tcid) \
74   host_dasm(tcache_dsm_ptrs[tcid], tcache_ptr - tcache_dsm_ptrs[tcid]); \
75   tcache_dsm_ptrs[tcid] = tcache_ptr
76 #else
77 #define do_host_disasm(x)
78 #endif
79
80 #if (DRC_DEBUG & 4) || defined(PDB)
81 static void REGPARM(3) *sh2_drc_log_entry(void *block, SH2 *sh2, u32 sr)
82 {
83   if (block != NULL) {
84     dbg(4, "= %csh2 enter %08x %p, c=%d", sh2->is_slave ? 's' : 'm',
85       sh2->pc, block, (signed int)sr >> 12);
86     pdb_step(sh2, sh2->pc);
87   }
88   return block;
89 }
90 #endif
91 // } debug
92
93 #define TCACHE_BUFFERS 3
94
95 // we have 3 translation cache buffers, split from one drc/cmn buffer.
96 // BIOS shares tcache with data array because it's only used for init
97 // and can be discarded early
98 // XXX: need to tune sizes
99 static const int tcache_sizes[TCACHE_BUFFERS] = {
100   DRC_TCACHE_SIZE * 6 / 8, // ROM, DRAM
101   DRC_TCACHE_SIZE / 8, // BIOS, data array in master sh2
102   DRC_TCACHE_SIZE / 8, // ... slave
103 };
104
105 static u8 *tcache_bases[TCACHE_BUFFERS];
106 static u8 *tcache_ptrs[TCACHE_BUFFERS];
107
108 // ptr for code emiters
109 static u8 *tcache_ptr;
110
111 typedef struct block_desc_ {
112   u32 addr;                  // SH2 PC address
113   void *tcache_ptr;          // translated block for above PC
114   struct block_desc_ *next;  // next block with the same PC hash
115 #if (DRC_DEBUG & 1)
116   int refcount;
117 #endif
118 } block_desc;
119
120 typedef struct block_link_ {
121   u32 target_pc;
122   void *jump;     // insn address
123 //  struct block_link_ *next;
124 } block_link;
125
126 static const int block_max_counts[TCACHE_BUFFERS] = {
127   4*1024,
128   256,
129   256,
130 };
131 static block_desc *block_tables[TCACHE_BUFFERS];
132 static block_link *block_links[TCACHE_BUFFERS]; 
133 static int block_counts[TCACHE_BUFFERS];
134 static int block_link_counts[TCACHE_BUFFERS];
135
136 // host register tracking
137 enum {
138   HR_FREE,
139   HR_CACHED, // 'val' has sh2_reg_e
140 //  HR_CONST,  // 'val' has a constant
141   HR_TEMP,   // reg used for temp storage
142 };
143
144 enum {
145   HRF_DIRTY  = 1 << 0, // reg has "dirty" value to be written to ctx
146   HRF_LOCKED = 1 << 1, // HR_CACHED can't be evicted
147 };
148
149 typedef struct {
150   u32 hreg:5;   // "host" reg
151   u32 greg:5;   // "guest" reg
152   u32 type:3;
153   u32 flags:3;
154   u32 stamp:16; // kind of a timestamp
155 } temp_reg_t;
156
157 // note: reg_temp[] must have at least the amount of
158 // registers used by handlers in worst case (currently 4)
159 #ifdef ARM
160 #include "../drc/emit_arm.c"
161
162 static const int reg_map_g2h[] = {
163    4,  5,  6,  7,
164    8, -1, -1, -1,
165   -1, -1, -1, -1,
166   -1, -1, -1,  9,
167   -1, -1, -1, 10,
168   -1, -1, -1, -1,
169 };
170
171 static temp_reg_t reg_temp[] = {
172   {  0, },
173   {  1, },
174   { 12, },
175   { 14, },
176   {  2, },
177   {  3, },
178 };
179
180 #elif defined(__i386__)
181 #include "../drc/emit_x86.c"
182
183 static const int reg_map_g2h[] = {
184   xSI,-1, -1, -1,
185   -1, -1, -1, -1,
186   -1, -1, -1, -1,
187   -1, -1, -1, -1,
188   -1, -1, -1, xDI,
189   -1, -1, -1, -1,
190 };
191
192 // ax, cx, dx are usually temporaries by convention
193 static temp_reg_t reg_temp[] = {
194   { xAX, },
195   { xBX, },
196   { xCX, },
197   { xDX, },
198 };
199
200 #else
201 #error unsupported arch
202 #endif
203
204 #define T       0x00000001
205 #define S       0x00000002
206 #define I       0x000000f0
207 #define Q       0x00000100
208 #define M       0x00000200
209 #define T_save  0x00000800
210
211 #define I_SHIFT 4
212 #define Q_SHIFT 8
213 #define M_SHIFT 9
214
215 // ROM hash table
216 #define MAX_HASH_ENTRIES 1024
217 #define HASH_MASK (MAX_HASH_ENTRIES - 1)
218 static void **hash_table;
219
220 #define HASH_FUNC(hash_tab, addr) \
221   ((block_desc **)(hash_tab))[(addr) & HASH_MASK]
222
223 static void REGPARM(1) (*sh2_drc_entry)(SH2 *sh2);
224 static void            (*sh2_drc_dispatcher)(void);
225 static void            (*sh2_drc_exit)(void);
226 static void            (*sh2_drc_test_irq)(void);
227
228 static u32  REGPARM(2) (*sh2_drc_read8)(u32 a, SH2 *sh2);
229 static u32  REGPARM(2) (*sh2_drc_read16)(u32 a, SH2 *sh2);
230 static u32  REGPARM(2) (*sh2_drc_read32)(u32 a, SH2 *sh2);
231 static void REGPARM(2) (*sh2_drc_write8)(u32 a, u32 d);
232 static void REGPARM(2) (*sh2_drc_write8_slot)(u32 a, u32 d);
233 static void REGPARM(2) (*sh2_drc_write16)(u32 a, u32 d);
234 static void REGPARM(2) (*sh2_drc_write16_slot)(u32 a, u32 d);
235 static int  REGPARM(3) (*sh2_drc_write32)(u32 a, u32 d, SH2 *sh2);
236
237 extern void REGPARM(2) sh2_do_op(SH2 *sh2, int opcode);
238
239 // address space stuff
240 static void *dr_get_pc_base(u32 pc, int is_slave)
241 {
242   void *ret = NULL;
243   u32 mask = 0;
244
245   if ((pc & ~0x7ff) == 0) {
246     // BIOS
247     ret = is_slave ? Pico32xMem->sh2_rom_s : Pico32xMem->sh2_rom_m;
248     mask = 0x7ff;
249   }
250   else if ((pc & 0xfffff000) == 0xc0000000) {
251     // data array
252     ret = Pico32xMem->data_array[is_slave];
253     mask = 0xfff;
254   }
255   else if ((pc & 0xc6000000) == 0x06000000) {
256     // SDRAM
257     ret = Pico32xMem->sdram;
258     mask = 0x03ffff;
259   }
260   else if ((pc & 0xc6000000) == 0x02000000) {
261     // ROM
262     ret = Pico.rom;
263     mask = 0x3fffff;
264   }
265
266   if (ret == NULL)
267     return (void *)-1; // NULL is valid value
268
269   return (char *)ret - (pc & ~mask);
270 }
271
272 static int dr_ctx_get_mem_ptr(u32 a, u32 *mask)
273 {
274   int poffs = -1;
275
276   if ((a & ~0x7ff) == 0) {
277     // BIOS
278     poffs = offsetof(SH2, p_bios);
279     *mask = 0x7ff;
280   }
281   else if ((a & 0xfffff000) == 0xc0000000) {
282     // data array
283     poffs = offsetof(SH2, p_da);
284     *mask = 0xfff;
285   }
286   else if ((a & 0xc6000000) == 0x06000000) {
287     // SDRAM
288     poffs = offsetof(SH2, p_sdram);
289     *mask = 0x03ffff;
290   }
291   else if ((a & 0xc6000000) == 0x02000000) {
292     // ROM
293     poffs = offsetof(SH2, p_rom);
294     *mask = 0x3fffff;
295   }
296
297   return poffs;
298 }
299
300 static block_desc *dr_get_bd(u32 pc, int is_slave, int *tcache_id)
301 {
302   *tcache_id = 0;
303
304   // we have full block id tables for data_array and RAM
305   // BIOS goes to data_array table too
306   if ((pc & 0xe0000000) == 0xc0000000 || (pc & ~0xfff) == 0) {
307     int blkid = Pico32xMem->drcblk_da[is_slave][(pc & 0xfff) >> SH2_DRCBLK_DA_SHIFT];
308     *tcache_id = 1 + is_slave;
309     if (blkid & 1)
310       return &block_tables[*tcache_id][blkid >> 1];
311   }
312   // RAM
313   else if ((pc & 0xc6000000) == 0x06000000) {
314     int blkid = Pico32xMem->drcblk_ram[(pc & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT];
315     if (blkid & 1)
316       return &block_tables[0][blkid >> 1];
317   }
318   // ROM
319   else if ((pc & 0xc6000000) == 0x02000000) {
320     block_desc *bd = HASH_FUNC(hash_table, pc);
321
322     for (; bd != NULL; bd = bd->next)
323       if (bd->addr == pc)
324         return bd;
325   }
326
327   return NULL;
328 }
329
330 // ---------------------------------------------------------------
331
332 // block management
333 static void REGPARM(1) flush_tcache(int tcid)
334 {
335   dbg(1, "tcache #%d flush! (%d/%d, bds %d/%d)", tcid,
336     tcache_ptrs[tcid] - tcache_bases[tcid], tcache_sizes[tcid],
337     block_counts[tcid], block_max_counts[tcid]);
338
339   block_counts[tcid] = 0;
340   block_link_counts[tcid] = 0;
341   tcache_ptrs[tcid] = tcache_bases[tcid];
342   if (tcid == 0) { // ROM, RAM
343     memset(hash_table, 0, sizeof(hash_table[0]) * MAX_HASH_ENTRIES);
344     memset(Pico32xMem->drcblk_ram, 0, sizeof(Pico32xMem->drcblk_ram));
345   }
346   else
347     memset(Pico32xMem->drcblk_da[tcid - 1], 0, sizeof(Pico32xMem->drcblk_da[0]));
348 #if (DRC_DEBUG & 2)
349   tcache_dsm_ptrs[tcid] = tcache_bases[tcid];
350 #endif
351 }
352
353 #if LINK_BRANCHES
354 // add block links (tracked branches)
355 static int dr_add_block_link(u32 target_pc, void *jump, int tcache_id)
356 {
357   block_link *bl = block_links[tcache_id];
358   int cnt = block_link_counts[tcache_id];
359
360   if (cnt >= block_max_counts[tcache_id] * 2) {
361     printf("bl overflow for tcache %d\n", tcache_id);
362     return -1;
363   }
364
365   bl[cnt].target_pc = target_pc;
366   bl[cnt].jump = jump;
367   block_link_counts[tcache_id]++;
368
369   return 0;
370 }
371 #endif
372
373 static block_desc *dr_add_block(u32 addr, int is_slave, int *blk_id)
374 {
375   block_desc *bd;
376   int tcache_id;
377   int *bcount;
378
379   bd = dr_get_bd(addr, is_slave, &tcache_id);
380   if (bd != NULL) {
381     dbg(1, "block override for %08x", addr);
382     bd->tcache_ptr = tcache_ptr;
383     *blk_id = bd - block_tables[tcache_id];
384     return bd;
385   }
386
387   bcount = &block_counts[tcache_id];
388   if (*bcount >= block_max_counts[tcache_id]) {
389     printf("bd overflow for tcache %d\n", tcache_id);
390     return NULL;
391   }
392   if (*bcount == 0)
393     (*bcount)++; // not using descriptor 0
394
395   bd = &block_tables[tcache_id][*bcount];
396   bd->addr = addr;
397   bd->tcache_ptr = tcache_ptr;
398   *blk_id = *bcount;
399   (*bcount)++;
400
401   if ((addr & 0xc6000000) == 0x02000000) { // ROM
402     bd->next = HASH_FUNC(hash_table, addr);
403     HASH_FUNC(hash_table, addr) = bd;
404 #if (DRC_DEBUG & 1)
405     if (bd->next != NULL) {
406       printf(" hash collision with %08x\n", bd->next->addr);
407       hash_collisions++;
408     }
409 #endif
410   }
411
412   return bd;
413 }
414
415 static void REGPARM(3) *dr_lookup_block(u32 pc, int is_slave, int *tcache_id)
416 {
417   block_desc *bd = NULL;
418   void *block = NULL;
419
420   bd = dr_get_bd(pc, is_slave, tcache_id);
421   if (bd != NULL)
422     block = bd->tcache_ptr;
423
424 #if (DRC_DEBUG & 1)
425   if (bd != NULL)
426     bd->refcount++;
427 #endif
428   return block;
429 }
430
431 static void *dr_prepare_ext_branch(u32 pc, SH2 *sh2, int tcache_id)
432 {
433 #if LINK_BRANCHES
434   int target_tcache_id;
435   void *target;
436   int ret;
437
438   target = dr_lookup_block(pc, sh2->is_slave, &target_tcache_id);
439   if (target_tcache_id == tcache_id) {
440     // allow linking blocks only from local cache
441     ret = dr_add_block_link(pc, tcache_ptr, tcache_id);
442     if (ret < 0)
443       return NULL;
444   }
445   if (target == NULL || target_tcache_id != tcache_id)
446     target = sh2_drc_dispatcher;
447
448   return target;
449 #else
450   return sh2_drc_dispatcher;
451 #endif
452 }
453
454 static void dr_link_blocks(void *target, u32 pc, int tcache_id)
455 {
456 #if LINK_BRANCHES
457   block_link *bl = block_links[tcache_id];
458   int cnt = block_link_counts[tcache_id];
459   int i;
460
461   for (i = 0; i < cnt; i++) {
462     if (bl[i].target_pc == pc) {
463       dbg(1, "- link from %p", bl[i].jump);
464       emith_jump_patch(bl[i].jump, target);
465       // XXX: sync ARM caches (old jump should be fine)?
466     }
467   }
468 #endif
469 }
470
471 #define ADD_TO_ARRAY(array, count, item, failcode) \
472   array[count++] = item; \
473   if (count >= ARRAY_SIZE(array)) { \
474     printf("warning: " #array " overflow\n"); \
475     failcode; \
476   }
477
478 static int find_in_array(u32 *array, size_t size, u32 what)
479 {
480   size_t i;
481   for (i = 0; i < size; i++)
482     if (what == array[i])
483       return i;
484
485   return -1;
486 }
487
488 // ---------------------------------------------------------------
489
490 // register cache / constant propagation stuff
491 typedef enum {
492   RC_GR_READ,
493   RC_GR_WRITE,
494   RC_GR_RMW,
495 } rc_gr_mode;
496
497 static int rcache_get_reg_(sh2_reg_e r, rc_gr_mode mode, int do_locking);
498
499 // guest regs with constants
500 static u32 dr_gcregs[24];
501 // a mask of constant/dirty regs
502 static u32 dr_gcregs_mask;
503 static u32 dr_gcregs_dirty;
504
505 #if PROPAGATE_CONSTANTS
506 static void gconst_new(sh2_reg_e r, u32 val)
507 {
508   int i;
509
510   dr_gcregs_mask  |= 1 << r;
511   dr_gcregs_dirty |= 1 << r;
512   dr_gcregs[r] = val;
513
514   // throw away old r that we might have cached
515   for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
516     if ((reg_temp[i].type == HR_CACHED) &&
517          reg_temp[i].greg == r) {
518       reg_temp[i].type = HR_FREE;
519       reg_temp[i].flags = 0;
520     }
521   }
522 }
523 #endif
524
525 static int gconst_get(sh2_reg_e r, u32 *val)
526 {
527   if (dr_gcregs_mask & (1 << r)) {
528     *val = dr_gcregs[r];
529     return 1;
530   }
531   return 0;
532 }
533
534 static int gconst_check(sh2_reg_e r)
535 {
536   if ((dr_gcregs_mask | dr_gcregs_dirty) & (1 << r))
537     return 1;
538   return 0;
539 }
540
541 // update hr if dirty, else do nothing
542 static int gconst_try_read(int hr, sh2_reg_e r)
543 {
544   if (dr_gcregs_dirty & (1 << r)) {
545     emith_move_r_imm(hr, dr_gcregs[r]);
546     dr_gcregs_dirty &= ~(1 << r);
547     return 1;
548   }
549   return 0;
550 }
551
552 static void gconst_check_evict(sh2_reg_e r)
553 {
554   if (dr_gcregs_mask & (1 << r))
555     // no longer cached in reg, make dirty again
556     dr_gcregs_dirty |= 1 << r;
557 }
558
559 static void gconst_kill(sh2_reg_e r)
560 {
561   dr_gcregs_mask &= ~(1 << r);
562   dr_gcregs_dirty &= ~(1 << r);
563 }
564
565 static void gconst_clean(void)
566 {
567   int i;
568
569   for (i = 0; i < ARRAY_SIZE(dr_gcregs); i++)
570     if (dr_gcregs_dirty & (1 << i)) {
571       // using RC_GR_READ here: it will call gconst_try_read,
572       // cache the reg and mark it dirty.
573       rcache_get_reg_(i, RC_GR_READ, 0);
574     }
575 }
576
577 static void gconst_invalidate(void)
578 {
579   dr_gcregs_mask = dr_gcregs_dirty = 0;
580 }
581
582 static u16 rcache_counter;
583
584 static temp_reg_t *rcache_evict(void)
585 {
586   // evict reg with oldest stamp
587   int i, oldest = -1;
588   u16 min_stamp = (u16)-1;
589
590   for (i = 0; i < ARRAY_SIZE(reg_temp); i++) {
591     if (reg_temp[i].type == HR_CACHED && !(reg_temp[i].flags & HRF_LOCKED) &&
592         reg_temp[i].stamp <= min_stamp) {
593       min_stamp = reg_temp[i].stamp;
594       oldest = i;
595     }
596   }
597
598   if (oldest == -1) {
599     printf("no registers to evict, aborting\n");
600     exit(1);
601   }
602
603   i = oldest;
604   if (reg_temp[i].type == HR_CACHED) {
605     if (reg_temp[i].flags & HRF_DIRTY)
606       // writeback
607       emith_ctx_write(reg_temp[i].hreg, reg_temp[i].greg * 4);
608     gconst_check_evict(reg_temp[i].greg);
609   }
610
611   reg_temp[i].type = HR_FREE;
612   reg_temp[i].flags = 0;
613   return &reg_temp[i];
614 }
615
616 static int get_reg_static(sh2_reg_e r, rc_gr_mode mode)
617 {
618   int i = reg_map_g2h[r];
619   if (i != -1) {
620     if (mode != RC_GR_WRITE)
621       gconst_try_read(i, r);
622   }
623   return i;
624 }
625
626 // note: must not be called when doing conditional code
627 static int rcache_get_reg_(sh2_reg_e r, rc_gr_mode mode, int do_locking)
628 {
629   temp_reg_t *tr;
630   int i, ret;
631
632   // maybe statically mapped?
633   ret = get_reg_static(r, mode);
634   if (ret != -1)
635     goto end;
636
637   rcache_counter++;
638
639   // maybe already cached?
640   // if so, prefer against gconst (they must be in sync)
641   for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
642     if (reg_temp[i].type == HR_CACHED && reg_temp[i].greg == r) {
643       reg_temp[i].stamp = rcache_counter;
644       if (mode != RC_GR_READ)
645         reg_temp[i].flags |= HRF_DIRTY;
646       ret = reg_temp[i].hreg;
647       goto end;
648     }
649   }
650
651   // use any free reg
652   for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
653     if (reg_temp[i].type == HR_FREE) {
654       tr = &reg_temp[i];
655       goto do_alloc;
656     }
657   }
658
659   tr = rcache_evict();
660
661 do_alloc:
662   tr->type = HR_CACHED;
663   if (do_locking)
664     tr->flags |= HRF_LOCKED;
665   if (mode != RC_GR_READ)
666     tr->flags |= HRF_DIRTY;
667   tr->greg = r;
668   tr->stamp = rcache_counter;
669   ret = tr->hreg;
670
671   if (mode != RC_GR_WRITE) {
672     if (gconst_check(r)) {
673       if (gconst_try_read(ret, r))
674         tr->flags |= HRF_DIRTY;
675     }
676     else
677       emith_ctx_read(tr->hreg, r * 4);
678   }
679
680 end:
681   if (mode != RC_GR_READ)
682     gconst_kill(r);
683
684   return ret;
685 }
686
687 static int rcache_get_reg(sh2_reg_e r, rc_gr_mode mode)
688 {
689   return rcache_get_reg_(r, mode, 1);
690 }
691
692 static int rcache_get_tmp(void)
693 {
694   temp_reg_t *tr;
695   int i;
696
697   for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
698     if (reg_temp[i].type == HR_FREE) {
699       tr = &reg_temp[i];
700       goto do_alloc;
701     }
702
703   tr = rcache_evict();
704
705 do_alloc:
706   tr->type = HR_TEMP;
707   return tr->hreg;
708 }
709
710 static int rcache_get_arg_id(int arg)
711 {
712   int i, r = 0;
713   host_arg2reg(r, arg);
714
715   for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
716     if (reg_temp[i].hreg == r)
717       break;
718
719   if (i == ARRAY_SIZE(reg_temp)) // can't happen
720     exit(1);
721
722   if (reg_temp[i].type == HR_CACHED) {
723     // writeback
724     if (reg_temp[i].flags & HRF_DIRTY)
725       emith_ctx_write(reg_temp[i].hreg, reg_temp[i].greg * 4);
726     gconst_check_evict(reg_temp[i].greg);
727   }
728   else if (reg_temp[i].type == HR_TEMP) {
729     printf("arg %d reg %d already used, aborting\n", arg, r);
730     exit(1);
731   }
732
733   reg_temp[i].type = HR_FREE;
734   reg_temp[i].flags = 0;
735
736   return i;
737 }
738
739 // get a reg to be used as function arg
740 static int rcache_get_tmp_arg(int arg)
741 {
742   int id = rcache_get_arg_id(arg);
743   reg_temp[id].type = HR_TEMP;
744
745   return reg_temp[id].hreg;
746 }
747
748 // same but caches a reg. RC_GR_READ only.
749 static int rcache_get_reg_arg(int arg, sh2_reg_e r)
750 {
751   int i, srcr, dstr, dstid;
752   int dirty = 0, src_dirty = 0;
753
754   dstid = rcache_get_arg_id(arg);
755   dstr = reg_temp[dstid].hreg;
756
757   // maybe already statically mapped?
758   srcr = get_reg_static(r, RC_GR_READ);
759   if (srcr != -1)
760     goto do_cache;
761
762   // maybe already cached?
763   for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
764     if ((reg_temp[i].type == HR_CACHED) &&
765          reg_temp[i].greg == r)
766     {
767       srcr = reg_temp[i].hreg;
768       if (reg_temp[i].flags & HRF_DIRTY)
769         src_dirty = 1;
770       goto do_cache;
771     }
772   }
773
774   // must read
775   srcr = dstr;
776   if (gconst_check(r)) {
777     if (gconst_try_read(srcr, r))
778       dirty = 1;
779   }
780   else
781     emith_ctx_read(srcr, r * 4);
782
783 do_cache:
784   if (dstr != srcr)
785     emith_move_r_r(dstr, srcr);
786 #if 1
787   else
788     dirty |= src_dirty;
789
790   if (dirty)
791     // must clean, callers might want to modify the arg before call
792     emith_ctx_write(dstr, r * 4);
793 #else
794   if (dirty)
795     reg_temp[dstid].flags |= HRF_DIRTY;
796 #endif
797
798   reg_temp[dstid].stamp = ++rcache_counter;
799   reg_temp[dstid].type = HR_CACHED;
800   reg_temp[dstid].greg = r;
801   reg_temp[dstid].flags |= HRF_LOCKED;
802   return dstr;
803 }
804
805 static void rcache_free_tmp(int hr)
806 {
807   int i;
808   for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
809     if (reg_temp[i].hreg == hr)
810       break;
811
812   if (i == ARRAY_SIZE(reg_temp) || reg_temp[i].type != HR_TEMP) {
813     printf("rcache_free_tmp fail: #%i hr %d, type %d\n", i, hr, reg_temp[i].type);
814     return;
815   }
816
817   reg_temp[i].type = HR_FREE;
818   reg_temp[i].flags = 0;
819 }
820
821 static void rcache_unlock(int hr)
822 {
823   int i;
824   for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
825     if (reg_temp[i].type == HR_CACHED && reg_temp[i].hreg == hr)
826       reg_temp[i].flags &= ~HRF_LOCKED;
827 }
828
829 static void rcache_unlock_all(void)
830 {
831   int i;
832   for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
833     reg_temp[i].flags &= ~HRF_LOCKED;
834 }
835
836 static void rcache_clean(void)
837 {
838   int i;
839   gconst_clean();
840
841   for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
842     if (reg_temp[i].type == HR_CACHED && (reg_temp[i].flags & HRF_DIRTY)) {
843       // writeback
844       emith_ctx_write(reg_temp[i].hreg, reg_temp[i].greg * 4);
845       reg_temp[i].flags &= ~HRF_DIRTY;
846     }
847 }
848
849 static void rcache_invalidate(void)
850 {
851   int i;
852   for (i = 0; i < ARRAY_SIZE(reg_temp); i++) {
853     reg_temp[i].type = HR_FREE;
854     reg_temp[i].flags = 0;
855   }
856   rcache_counter = 0;
857
858   gconst_invalidate();
859 }
860
861 static void rcache_flush(void)
862 {
863   rcache_clean();
864   rcache_invalidate();
865 }
866
867 // ---------------------------------------------------------------
868
869 static int emit_get_rbase_and_offs(u32 a, u32 *offs)
870 {
871   u32 mask = 0;
872   int poffs;
873   int hr;
874
875   poffs = dr_ctx_get_mem_ptr(a, &mask);
876   if (poffs == -1)
877     return -1;
878
879   // XXX: could use some related reg
880   hr = rcache_get_tmp();
881   emith_ctx_read(hr, poffs);
882   emith_add_r_imm(hr, a & mask & ~0xff);
883   *offs = a & 0xff; // XXX: ARM oriented..
884   return hr;
885 }
886
887 static void emit_move_r_imm32(sh2_reg_e dst, u32 imm)
888 {
889 #if PROPAGATE_CONSTANTS
890   gconst_new(dst, imm);
891 #else
892   int hr = rcache_get_reg(dst, RC_GR_WRITE);
893   emith_move_r_imm(hr, imm);
894 #endif
895 }
896
897 static void emit_move_r_r(sh2_reg_e dst, sh2_reg_e src)
898 {
899   int hr_d = rcache_get_reg(dst, RC_GR_WRITE);
900   int hr_s = rcache_get_reg(src, RC_GR_READ);
901
902   emith_move_r_r(hr_d, hr_s);
903 }
904
905 // T must be clear, and comparison done just before this
906 static void emit_or_t_if_eq(int srr)
907 {
908   EMITH_SJMP_START(DCOND_NE);
909   emith_or_r_imm_c(DCOND_EQ, srr, T);
910   EMITH_SJMP_END(DCOND_NE);
911 }
912
913 // arguments must be ready
914 // reg cache must be clean before call
915 static int emit_memhandler_read_(int size, int ram_check)
916 {
917   int arg0, arg1;
918   host_arg2reg(arg0, 0);
919
920   rcache_clean();
921
922   // must writeback cycles for poll detection stuff
923   // FIXME: rm
924   if (reg_map_g2h[SHR_SR] != -1)
925     emith_ctx_write(reg_map_g2h[SHR_SR], SHR_SR * 4);
926
927   arg1 = rcache_get_tmp_arg(1);
928   emith_move_r_r(arg1, CONTEXT_REG);
929
930 #ifndef PDB_NET
931   if (ram_check && Pico.rom == (void *)0x02000000 && Pico32xMem->sdram == (void *)0x06000000) {
932     int tmp = rcache_get_tmp();
933     emith_and_r_r_imm(tmp, arg0, 0xfb000000);
934     emith_cmp_r_imm(tmp, 0x02000000);
935     switch (size) {
936     case 0: // 8
937       EMITH_SJMP3_START(DCOND_NE);
938       emith_eor_r_imm_c(DCOND_EQ, arg0, 1);
939       emith_read8_r_r_offs_c(DCOND_EQ, arg0, arg0, 0);
940       EMITH_SJMP3_MID(DCOND_NE);
941       emith_call_cond(DCOND_NE, sh2_drc_read8);
942       EMITH_SJMP3_END();
943       break;
944     case 1: // 16
945       EMITH_SJMP3_START(DCOND_NE);
946       emith_read16_r_r_offs_c(DCOND_EQ, arg0, arg0, 0);
947       EMITH_SJMP3_MID(DCOND_NE);
948       emith_call_cond(DCOND_NE, sh2_drc_read16);
949       EMITH_SJMP3_END();
950       break;
951     case 2: // 32
952       EMITH_SJMP3_START(DCOND_NE);
953       emith_read_r_r_offs_c(DCOND_EQ, arg0, arg0, 0);
954       emith_ror_c(DCOND_EQ, arg0, arg0, 16);
955       EMITH_SJMP3_MID(DCOND_NE);
956       emith_call_cond(DCOND_NE, sh2_drc_read32);
957       EMITH_SJMP3_END();
958       break;
959     }
960   }
961   else
962 #endif
963   {
964     switch (size) {
965     case 0: // 8
966       emith_call(sh2_drc_read8);
967       break;
968     case 1: // 16
969       emith_call(sh2_drc_read16);
970       break;
971     case 2: // 32
972       emith_call(sh2_drc_read32);
973       break;
974     }
975   }
976   rcache_invalidate();
977   // assuming arg0 and retval reg matches
978   return rcache_get_tmp_arg(0);
979 }
980
981 static int emit_memhandler_read(int size)
982 {
983   return emit_memhandler_read_(size, 1);
984 }
985
986 static int emit_memhandler_read_rr(sh2_reg_e rd, sh2_reg_e rs, u32 offs, int size)
987 {
988   int hr, hr2, ram_check = 1;
989   u32 val, offs2;
990
991   if (gconst_get(rs, &val)) {
992     hr = emit_get_rbase_and_offs(val + offs, &offs2);
993     if (hr != -1) {
994       hr2 = rcache_get_reg(rd, RC_GR_WRITE);
995       switch (size) {
996       case 0: // 8
997         emith_read8_r_r_offs(hr2, hr, offs2 ^ 1);
998         emith_sext(hr2, hr2, 8);
999         break;
1000       case 1: // 16
1001         emith_read16_r_r_offs(hr2, hr, offs2);
1002         emith_sext(hr2, hr2, 16);
1003         break;
1004       case 2: // 32
1005         emith_read_r_r_offs(hr2, hr, offs2);
1006         emith_ror(hr2, hr2, 16);
1007         break;
1008       }
1009       rcache_free_tmp(hr);
1010       return hr2;
1011     }
1012
1013     ram_check = 0;
1014   }
1015
1016   hr = rcache_get_reg_arg(0, rs);
1017   if (offs != 0)
1018     emith_add_r_imm(hr, offs);
1019   hr  = emit_memhandler_read_(size, ram_check);
1020   hr2 = rcache_get_reg(rd, RC_GR_WRITE);
1021   if (size != 2) {
1022     emith_sext(hr2, hr, (size == 1) ? 16 : 8);
1023   } else
1024     emith_move_r_r(hr2, hr);
1025   rcache_free_tmp(hr);
1026
1027   return hr2;
1028 }
1029
1030 static void emit_memhandler_write(int size, u32 pc, int delay)
1031 {
1032   int ctxr;
1033   host_arg2reg(ctxr, 2);
1034   switch (size) {
1035   case 0: // 8
1036     // XXX: consider inlining sh2_drc_write8
1037     if (delay) {
1038       emith_call(sh2_drc_write8_slot);
1039     } else {
1040       emit_move_r_imm32(SHR_PC, pc);
1041       rcache_clean();
1042       emith_call(sh2_drc_write8);
1043     }
1044     break;
1045   case 1: // 16
1046     if (delay) {
1047       emith_call(sh2_drc_write16_slot);
1048     } else {
1049       emit_move_r_imm32(SHR_PC, pc);
1050       rcache_clean();
1051       emith_call(sh2_drc_write16);
1052     }
1053     break;
1054   case 2: // 32
1055     emith_move_r_r(ctxr, CONTEXT_REG);
1056     emith_call(sh2_drc_write32);
1057     break;
1058   }
1059   rcache_invalidate();
1060 }
1061
1062 // @(Rx,Ry)
1063 static int emit_indirect_indexed_read(int rx, int ry, int size)
1064 {
1065   int a0, t;
1066   a0 = rcache_get_reg_arg(0, rx);
1067   t  = rcache_get_reg(ry, RC_GR_READ);
1068   emith_add_r_r(a0, t);
1069   return emit_memhandler_read(size);
1070 }
1071
1072 // read @Rn, @rm
1073 static void emit_indirect_read_double(u32 *rnr, u32 *rmr, int rn, int rm, int size)
1074 {
1075   int tmp;
1076
1077   rcache_get_reg_arg(0, rn);
1078   tmp = emit_memhandler_read(size);
1079   emith_ctx_write(tmp, offsetof(SH2, drc_tmp));
1080   rcache_free_tmp(tmp);
1081   tmp = rcache_get_reg(rn, RC_GR_RMW);
1082   emith_add_r_imm(tmp, 1 << size);
1083   rcache_unlock(tmp);
1084
1085   rcache_get_reg_arg(0, rm);
1086   *rmr = emit_memhandler_read(size);
1087   *rnr = rcache_get_tmp();
1088   emith_ctx_read(*rnr, offsetof(SH2, drc_tmp));
1089   tmp = rcache_get_reg(rm, RC_GR_RMW);
1090   emith_add_r_imm(tmp, 1 << size);
1091   rcache_unlock(tmp);
1092 }
1093  
1094 static void emit_do_static_regs(int is_write, int tmpr)
1095 {
1096   int i, r, count;
1097
1098   for (i = 0; i < ARRAY_SIZE(reg_map_g2h); i++) {
1099     r = reg_map_g2h[i];
1100     if (r == -1)
1101       continue;
1102
1103     for (count = 1; i < ARRAY_SIZE(reg_map_g2h) - 1; i++, r++) {
1104       if (reg_map_g2h[i + 1] != r + 1)
1105         break;
1106       count++;
1107     }
1108
1109     if (count > 1) {
1110       // i, r point to last item
1111       if (is_write)
1112         emith_ctx_write_multiple(r - count + 1, (i - count + 1) * 4, count, tmpr);
1113       else
1114         emith_ctx_read_multiple(r - count + 1, (i - count + 1) * 4, count, tmpr);
1115     } else {
1116       if (is_write)
1117         emith_ctx_write(r, i * 4);
1118       else
1119         emith_ctx_read(r, i * 4);
1120     }
1121   }
1122 }
1123
1124 static void emit_block_entry(void)
1125 {
1126   int arg0, arg1, arg2;
1127
1128   host_arg2reg(arg0, 0);
1129   host_arg2reg(arg1, 1);
1130   host_arg2reg(arg2, 2);
1131
1132 #if (DRC_DEBUG & 4) || defined(PDB)
1133   emit_do_static_regs(1, arg2);
1134   emith_move_r_r(arg1, CONTEXT_REG);
1135   emith_move_r_r(arg2, rcache_get_reg(SHR_SR, RC_GR_READ));
1136   emith_call(sh2_drc_log_entry);
1137   rcache_invalidate();
1138 #endif
1139   emith_tst_r_r(arg0, arg0);
1140   EMITH_SJMP_START(DCOND_EQ);
1141   emith_jump_reg_c(DCOND_NE, arg0);
1142   EMITH_SJMP_END(DCOND_EQ);
1143 }
1144
1145 #define DELAYED_OP \
1146   drcf.delayed_op = 2
1147
1148 #define DELAY_SAVE_T(sr) { \
1149   emith_bic_r_imm(sr, T_save); \
1150   emith_tst_r_imm(sr, T);      \
1151   EMITH_SJMP_START(DCOND_EQ);  \
1152   emith_or_r_imm_c(DCOND_NE, sr, T_save); \
1153   EMITH_SJMP_END(DCOND_EQ);    \
1154   drcf.use_saved_t = 1;        \
1155 }
1156
1157 #define FLUSH_CYCLES(sr) \
1158   if (cycles > 0) { \
1159     emith_sub_r_imm(sr, cycles << 12); \
1160     cycles = 0; \
1161   }
1162
1163 #define CHECK_UNHANDLED_BITS(mask) { \
1164   if ((op & (mask)) != 0) \
1165     goto default_; \
1166 }
1167
1168 #define FETCH_OP(pc) \
1169   dr_pc_base[(pc) / 2]
1170
1171 #define FETCH32(a) \
1172   ((dr_pc_base[(a) / 2] << 16) | dr_pc_base[(a) / 2 + 1])
1173
1174 #define GET_Fx() \
1175   ((op >> 4) & 0x0f)
1176
1177 #define GET_Rm GET_Fx
1178
1179 #define GET_Rn() \
1180   ((op >> 8) & 0x0f)
1181
1182 #define CHECK_FX_LT(n) \
1183   if (GET_Fx() >= n) \
1184     goto default_
1185
1186 // op_flags: data from 1st pass
1187 #define OP_FLAGS(pc) op_flags[((pc) - base_pc) / 2]
1188 #define OF_DELAY_OP (1 << 0)
1189
1190 static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
1191 {
1192   // XXX: maybe use structs instead?
1193   u32 branch_target_pc[MAX_LOCAL_BRANCHES];
1194   void *branch_target_ptr[MAX_LOCAL_BRANCHES];
1195   int branch_target_blkid[MAX_LOCAL_BRANCHES];
1196   int branch_target_count = 0;
1197   void *branch_patch_ptr[MAX_LOCAL_BRANCHES];
1198   u32 branch_patch_pc[MAX_LOCAL_BRANCHES];
1199   int branch_patch_count = 0;
1200   u32 literal_addr[MAX_LITERALS];
1201   int literal_addr_count = 0;
1202   int pending_branch_cond = -1;
1203   int pending_branch_pc = 0;
1204   u8 op_flags[BLOCK_CYCLE_LIMIT + 1];
1205   struct {
1206     u32 delayed_op:2;
1207     u32 test_irq:1;
1208     u32 use_saved_t:1; // delayed op modifies T
1209   } drcf = { 0, };
1210
1211   // PC of current, first, last, last_target_blk SH2 insn
1212   u32 pc, base_pc, end_pc, out_pc;
1213   void *block_entry;
1214   block_desc *this_block;
1215   u16 *dr_pc_base;
1216   int blkid_main = 0;
1217   int skip_op = 0;
1218   u32 tmp, tmp2;
1219   int cycles;
1220   int op;
1221   int i;
1222
1223   base_pc = sh2->pc;
1224
1225   // get base/validate PC
1226   dr_pc_base = dr_get_pc_base(base_pc, sh2->is_slave);
1227   if (dr_pc_base == (void *)-1) {
1228     printf("invalid PC, aborting: %08x\n", base_pc);
1229     // FIXME: be less destructive
1230     exit(1);
1231   }
1232
1233   tcache_ptr = tcache_ptrs[tcache_id];
1234   this_block = dr_add_block(base_pc, sh2->is_slave, &blkid_main);
1235   if (this_block == NULL)
1236     return NULL;
1237
1238   // predict tcache overflow
1239   tmp = tcache_ptr - tcache_bases[tcache_id];
1240   if (tmp > tcache_sizes[tcache_id] - MAX_BLOCK_SIZE) {
1241     printf("tcache %d overflow\n", tcache_id);
1242     return NULL;
1243   }
1244
1245   block_entry = tcache_ptr;
1246   dbg(1, "== %csh2 block #%d,%d %08x -> %p", sh2->is_slave ? 's' : 'm',
1247     tcache_id, blkid_main, base_pc, block_entry);
1248
1249   dr_link_blocks(tcache_ptr, base_pc, tcache_id);
1250
1251   // 1st pass: scan forward for local branches
1252   memset(op_flags, 0, sizeof(op_flags));
1253   for (cycles = 0, pc = base_pc; cycles < BLOCK_CYCLE_LIMIT; cycles++, pc += 2) {
1254     op = FETCH_OP(pc);
1255     if ((op & 0xf000) == 0xa000 || (op & 0xf000) == 0xb000) { // BRA, BSR
1256       signed int offs = ((signed int)(op << 20) >> 19);
1257       pc += 2;
1258       OP_FLAGS(pc) |= OF_DELAY_OP;
1259       ADD_TO_ARRAY(branch_target_pc, branch_target_count, pc + offs + 2,);
1260       break;
1261     }
1262     if ((op & 0xf000) == 0) {
1263       op &= 0xff;
1264       if (op == 0x1b) // SLEEP
1265         break;
1266       if (op == 0x23 || op == 0x03 || op == 0x0b || op == 0x2b) { // BRAF, BSRF, RTS, RTE
1267         pc += 2;
1268         OP_FLAGS(pc) |= OF_DELAY_OP;
1269         break;
1270       }
1271       continue;
1272     }
1273     if ((op & 0xf0df) == 0x400b) { // JMP, JSR
1274       pc += 2;
1275       OP_FLAGS(pc) |= OF_DELAY_OP;
1276       break;
1277     }
1278     if ((op & 0xf900) == 0x8900) { // BT(S), BF(S)
1279       signed int offs = ((signed int)(op << 24) >> 23);
1280       if (op & 0x0400)
1281         OP_FLAGS(pc + 2) |= OF_DELAY_OP;
1282       ADD_TO_ARRAY(branch_target_pc, branch_target_count, pc + offs + 4, break);
1283     }
1284     if ((op & 0xff00) == 0xc300) // TRAPA
1285       break;
1286   }
1287
1288   end_pc = pc;
1289
1290   // clean branch_targets that are not really local,
1291   // and that land on delay slots
1292   for (i = 0, tmp = 0; i < branch_target_count; i++) {
1293     pc = branch_target_pc[i];
1294     if (base_pc <= pc && pc <= end_pc && !(OP_FLAGS(pc) & OF_DELAY_OP))
1295       branch_target_pc[tmp++] = branch_target_pc[i];
1296   }
1297   branch_target_count = tmp;
1298   memset(branch_target_ptr, 0, sizeof(branch_target_ptr[0]) * branch_target_count);
1299   memset(branch_target_blkid, 0, sizeof(branch_target_blkid[0]) * branch_target_count);
1300
1301   // -------------------------------------------------
1302   // 2nd pass: actual compilation
1303   out_pc = 0;
1304   pc = base_pc;
1305   for (cycles = 0; pc <= end_pc || drcf.delayed_op; )
1306   {
1307     u32 tmp3, tmp4, sr;
1308
1309     if (drcf.delayed_op > 0)
1310       drcf.delayed_op--;
1311
1312     op = FETCH_OP(pc);
1313
1314     i = find_in_array(branch_target_pc, branch_target_count, pc);
1315     if (i >= 0 || pc == base_pc)
1316     {
1317       if (pc != base_pc)
1318       {
1319         /* make "subblock" - just a mid-block entry */
1320         block_desc *subblock;
1321
1322         sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1323         FLUSH_CYCLES(sr);
1324         // decide if to flush rcache
1325         if ((op & 0xf0ff) == 0x4010 && FETCH_OP(pc + 2) == 0x8bfd) // DT; BF #-2
1326           rcache_clean();
1327         else
1328           rcache_flush();
1329         do_host_disasm(tcache_id);
1330
1331         dbg(1, "-- %csh2 subblock #%d,%d %08x -> %p", sh2->is_slave ? 's' : 'm',
1332           tcache_id, branch_target_blkid[i], pc, tcache_ptr);
1333
1334         subblock = dr_add_block(pc, sh2->is_slave, &branch_target_blkid[i]);
1335         if (subblock == NULL)
1336           return NULL;
1337
1338         // since we made a block entry, link any other blocks that jump to current pc
1339         dr_link_blocks(tcache_ptr, pc, tcache_id);
1340       }
1341       if (i >= 0)
1342         branch_target_ptr[i] = tcache_ptr;
1343
1344       // must update PC
1345       emit_move_r_imm32(SHR_PC, pc);
1346       rcache_clean();
1347
1348       // check cycles
1349       sr = rcache_get_reg(SHR_SR, RC_GR_READ);
1350       emith_cmp_r_imm(sr, 0);
1351       emith_jump_cond(DCOND_LE, sh2_drc_exit);
1352       do_host_disasm(tcache_id);
1353       rcache_unlock_all();
1354     }
1355
1356 #if (DRC_DEBUG & 3)
1357     insns_compiled++;
1358 #if (DRC_DEBUG & 2)
1359     DasmSH2(sh2dasm_buff, pc, op);
1360     printf("%08x %04x %s\n", pc, op, sh2dasm_buff);
1361 #endif
1362 #endif
1363
1364     pc += 2;
1365     cycles++;
1366
1367     if (skip_op > 0) {
1368       skip_op--;
1369       continue;
1370     }
1371
1372     switch ((op >> 12) & 0x0f)
1373     {
1374     /////////////////////////////////////////////
1375     case 0x00:
1376       switch (op & 0x0f)
1377       {
1378       case 0x02:
1379         tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
1380         switch (GET_Fx())
1381         {
1382         case 0: // STC SR,Rn  0000nnnn00000010
1383           tmp2 = SHR_SR;
1384           break;
1385         case 1: // STC GBR,Rn 0000nnnn00010010
1386           tmp2 = SHR_GBR;
1387           break;
1388         case 2: // STC VBR,Rn 0000nnnn00100010
1389           tmp2 = SHR_VBR;
1390           break;
1391         default:
1392           goto default_;
1393         }
1394         tmp3 = rcache_get_reg(tmp2, RC_GR_READ);
1395         emith_move_r_r(tmp, tmp3);
1396         if (tmp2 == SHR_SR)
1397           emith_clear_msb(tmp, tmp, 22); // reserved bits defined by ISA as 0
1398         goto end_op;
1399       case 0x03:
1400         CHECK_UNHANDLED_BITS(0xd0);
1401         // BRAF Rm    0000mmmm00100011
1402         // BSRF Rm    0000mmmm00000011
1403         DELAYED_OP;
1404         tmp  = rcache_get_reg(SHR_PC, RC_GR_WRITE);
1405         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
1406         emith_move_r_r(tmp, tmp2);
1407         if (op & 0x20)
1408           emith_add_r_imm(tmp, pc + 2);
1409         else { // BSRF
1410           tmp3 = rcache_get_reg(SHR_PR, RC_GR_WRITE);
1411           emith_move_r_imm(tmp3, pc + 2);
1412           emith_add_r_r(tmp, tmp3);
1413         }
1414         out_pc = (u32)-1;
1415         cycles++;
1416         goto end_op;
1417       case 0x04: // MOV.B Rm,@(R0,Rn)   0000nnnnmmmm0100
1418       case 0x05: // MOV.W Rm,@(R0,Rn)   0000nnnnmmmm0101
1419       case 0x06: // MOV.L Rm,@(R0,Rn)   0000nnnnmmmm0110
1420         rcache_clean();
1421         tmp  = rcache_get_reg_arg(1, GET_Rm());
1422         tmp2 = rcache_get_reg_arg(0, SHR_R0);
1423         tmp3 = rcache_get_reg(GET_Rn(), RC_GR_READ);
1424         emith_add_r_r(tmp2, tmp3);
1425         emit_memhandler_write(op & 3, pc, drcf.delayed_op);
1426         goto end_op;
1427       case 0x07:
1428         // MUL.L     Rm,Rn      0000nnnnmmmm0111
1429         tmp  = rcache_get_reg(GET_Rn(), RC_GR_READ);
1430         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1431         tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
1432         emith_mul(tmp3, tmp2, tmp);
1433         cycles++;
1434         goto end_op;
1435       case 0x08:
1436         CHECK_UNHANDLED_BITS(0xf00);
1437         switch (GET_Fx())
1438         {
1439         case 0: // CLRT               0000000000001000
1440           sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1441           if (drcf.delayed_op)
1442             DELAY_SAVE_T(sr);
1443           emith_bic_r_imm(sr, T);
1444           break;
1445         case 1: // SETT               0000000000011000
1446           sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1447           if (drcf.delayed_op)
1448             DELAY_SAVE_T(sr);
1449           emith_or_r_imm(sr, T);
1450           break;
1451         case 2: // CLRMAC             0000000000101000
1452           emit_move_r_imm32(SHR_MACL, 0);
1453           emit_move_r_imm32(SHR_MACH, 0);
1454           break;
1455         default:
1456           goto default_;
1457         }
1458         goto end_op;
1459       case 0x09:
1460         switch (GET_Fx())
1461         {
1462         case 0: // NOP        0000000000001001
1463           CHECK_UNHANDLED_BITS(0xf00);
1464           break;
1465         case 1: // DIV0U      0000000000011001
1466           CHECK_UNHANDLED_BITS(0xf00);
1467           sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1468           if (drcf.delayed_op)
1469             DELAY_SAVE_T(sr);
1470           emith_bic_r_imm(sr, M|Q|T);
1471           break;
1472         case 2: // MOVT Rn    0000nnnn00101001
1473           sr   = rcache_get_reg(SHR_SR, RC_GR_READ);
1474           tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
1475           emith_clear_msb(tmp2, sr, 31);
1476           break;
1477         default:
1478           goto default_;
1479         }
1480         goto end_op;
1481       case 0x0a:
1482         tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
1483         switch (GET_Fx())
1484         {
1485         case 0: // STS      MACH,Rn   0000nnnn00001010
1486           tmp2 = SHR_MACH;
1487           break;
1488         case 1: // STS      MACL,Rn   0000nnnn00011010
1489           tmp2 = SHR_MACL;
1490           break;
1491         case 2: // STS      PR,Rn     0000nnnn00101010
1492           tmp2 = SHR_PR;
1493           break;
1494         default:
1495           goto default_;
1496         }
1497         tmp2 = rcache_get_reg(tmp2, RC_GR_READ);
1498         emith_move_r_r(tmp, tmp2);
1499         goto end_op;
1500       case 0x0b:
1501         CHECK_UNHANDLED_BITS(0xf00);
1502         switch (GET_Fx())
1503         {
1504         case 0: // RTS        0000000000001011
1505           DELAYED_OP;
1506           emit_move_r_r(SHR_PC, SHR_PR);
1507           out_pc = (u32)-1;
1508           cycles++;
1509           break;
1510         case 1: // SLEEP      0000000000011011
1511           tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
1512           emith_clear_msb(tmp, tmp, 20); // clear cycles
1513           out_pc = out_pc - 2;
1514           cycles = 1;
1515           goto end_op;
1516         case 2: // RTE        0000000000101011
1517           DELAYED_OP;
1518           // pop PC
1519           emit_memhandler_read_rr(SHR_PC, SHR_SP, 0, 2);
1520           // pop SR
1521           tmp = rcache_get_reg_arg(0, SHR_SP);
1522           emith_add_r_imm(tmp, 4);
1523           tmp = emit_memhandler_read(2);
1524           sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
1525           emith_write_sr(sr, tmp);
1526           rcache_free_tmp(tmp);
1527           tmp = rcache_get_reg(SHR_SP, RC_GR_RMW);
1528           emith_add_r_imm(tmp, 4*2);
1529           drcf.test_irq = 1;
1530           out_pc = (u32)-1;
1531           cycles += 3;
1532           break;
1533         default:
1534           goto default_;
1535         }
1536         goto end_op;
1537       case 0x0c: // MOV.B    @(R0,Rm),Rn      0000nnnnmmmm1100
1538       case 0x0d: // MOV.W    @(R0,Rm),Rn      0000nnnnmmmm1101
1539       case 0x0e: // MOV.L    @(R0,Rm),Rn      0000nnnnmmmm1110
1540         tmp = emit_indirect_indexed_read(SHR_R0, GET_Rm(), op & 3);
1541         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
1542         if ((op & 3) != 2) {
1543           emith_sext(tmp2, tmp, (op & 1) ? 16 : 8);
1544         } else
1545           emith_move_r_r(tmp2, tmp);
1546         rcache_free_tmp(tmp);
1547         goto end_op;
1548       case 0x0f: // MAC.L   @Rm+,@Rn+  0000nnnnmmmm1111
1549         emit_indirect_read_double(&tmp, &tmp2, GET_Rn(), GET_Rm(), 2);
1550         tmp4 = rcache_get_reg(SHR_MACH, RC_GR_RMW);
1551         /* MS 16 MAC bits unused if saturated */
1552         sr = rcache_get_reg(SHR_SR, RC_GR_READ);
1553         emith_tst_r_imm(sr, S);
1554         EMITH_SJMP_START(DCOND_EQ);
1555         emith_clear_msb_c(DCOND_NE, tmp4, tmp4, 16);
1556         EMITH_SJMP_END(DCOND_EQ);
1557         rcache_unlock(sr);
1558         tmp3 = rcache_get_reg(SHR_MACL, RC_GR_RMW); // might evict SR
1559         emith_mula_s64(tmp3, tmp4, tmp, tmp2);
1560         rcache_free_tmp(tmp2);
1561         sr = rcache_get_reg(SHR_SR, RC_GR_READ); // reget just in case
1562         emith_tst_r_imm(sr, S);
1563
1564         EMITH_JMP_START(DCOND_EQ);
1565         emith_asr(tmp, tmp4, 15);
1566         emith_cmp_r_imm(tmp, -1); // negative overflow (0x80000000..0xffff7fff)
1567         EMITH_SJMP_START(DCOND_GE);
1568         emith_move_r_imm_c(DCOND_LT, tmp4, 0x8000);
1569         emith_move_r_imm_c(DCOND_LT, tmp3, 0x0000);
1570         EMITH_SJMP_END(DCOND_GE);
1571         emith_cmp_r_imm(tmp, 0); // positive overflow (0x00008000..0x7fffffff)
1572         EMITH_SJMP_START(DCOND_LE);
1573         emith_move_r_imm_c(DCOND_GT, tmp4, 0x00007fff);
1574         emith_move_r_imm_c(DCOND_GT, tmp3, 0xffffffff);
1575         EMITH_SJMP_END(DCOND_LE);
1576         EMITH_JMP_END(DCOND_EQ);
1577
1578         rcache_free_tmp(tmp);
1579         cycles += 3;
1580         goto end_op;
1581       }
1582       goto default_;
1583
1584     /////////////////////////////////////////////
1585     case 0x01:
1586       // MOV.L Rm,@(disp,Rn) 0001nnnnmmmmdddd
1587       rcache_clean();
1588       tmp  = rcache_get_reg_arg(0, GET_Rn());
1589       tmp2 = rcache_get_reg_arg(1, GET_Rm());
1590       if (op & 0x0f)
1591         emith_add_r_imm(tmp, (op & 0x0f) * 4);
1592       emit_memhandler_write(2, pc, drcf.delayed_op);
1593       goto end_op;
1594
1595     case 0x02:
1596       switch (op & 0x0f)
1597       {
1598       case 0x00: // MOV.B Rm,@Rn        0010nnnnmmmm0000
1599       case 0x01: // MOV.W Rm,@Rn        0010nnnnmmmm0001
1600       case 0x02: // MOV.L Rm,@Rn        0010nnnnmmmm0010
1601         rcache_clean();
1602         rcache_get_reg_arg(0, GET_Rn());
1603         rcache_get_reg_arg(1, GET_Rm());
1604         emit_memhandler_write(op & 3, pc, drcf.delayed_op);
1605         goto end_op;
1606       case 0x04: // MOV.B Rm,@–Rn       0010nnnnmmmm0100
1607       case 0x05: // MOV.W Rm,@–Rn       0010nnnnmmmm0101
1608       case 0x06: // MOV.L Rm,@–Rn       0010nnnnmmmm0110
1609         tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1610         emith_sub_r_imm(tmp, (1 << (op & 3)));
1611         rcache_clean();
1612         rcache_get_reg_arg(0, GET_Rn());
1613         rcache_get_reg_arg(1, GET_Rm());
1614         emit_memhandler_write(op & 3, pc, drcf.delayed_op);
1615         goto end_op;
1616       case 0x07: // DIV0S Rm,Rn         0010nnnnmmmm0111
1617         sr   = rcache_get_reg(SHR_SR, RC_GR_RMW);
1618         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
1619         tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1620         if (drcf.delayed_op)
1621           DELAY_SAVE_T(sr);
1622         emith_bic_r_imm(sr, M|Q|T);
1623         emith_tst_r_imm(tmp2, (1<<31));
1624         EMITH_SJMP_START(DCOND_EQ);
1625         emith_or_r_imm_c(DCOND_NE, sr, Q);
1626         EMITH_SJMP_END(DCOND_EQ);
1627         emith_tst_r_imm(tmp3, (1<<31));
1628         EMITH_SJMP_START(DCOND_EQ);
1629         emith_or_r_imm_c(DCOND_NE, sr, M);
1630         EMITH_SJMP_END(DCOND_EQ);
1631         emith_teq_r_r(tmp2, tmp3);
1632         EMITH_SJMP_START(DCOND_PL);
1633         emith_or_r_imm_c(DCOND_MI, sr, T);
1634         EMITH_SJMP_END(DCOND_PL);
1635         goto end_op;
1636       case 0x08: // TST Rm,Rn           0010nnnnmmmm1000
1637         sr  = rcache_get_reg(SHR_SR, RC_GR_RMW);
1638         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
1639         tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1640         if (drcf.delayed_op)
1641           DELAY_SAVE_T(sr);
1642         emith_bic_r_imm(sr, T);
1643         emith_tst_r_r(tmp2, tmp3);
1644         emit_or_t_if_eq(sr);
1645         goto end_op;
1646       case 0x09: // AND Rm,Rn           0010nnnnmmmm1001
1647         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1648         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1649         emith_and_r_r(tmp, tmp2);
1650         goto end_op;
1651       case 0x0a: // XOR Rm,Rn           0010nnnnmmmm1010
1652         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1653         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1654         emith_eor_r_r(tmp, tmp2);
1655         goto end_op;
1656       case 0x0b: // OR  Rm,Rn           0010nnnnmmmm1011
1657         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1658         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1659         emith_or_r_r(tmp, tmp2);
1660         goto end_op;
1661       case 0x0c: // CMP/STR Rm,Rn       0010nnnnmmmm1100
1662         tmp  = rcache_get_tmp();
1663         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
1664         tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1665         emith_eor_r_r_r(tmp, tmp2, tmp3);
1666         sr   = rcache_get_reg(SHR_SR, RC_GR_RMW);
1667         if (drcf.delayed_op)
1668           DELAY_SAVE_T(sr);
1669         emith_bic_r_imm(sr, T);
1670         emith_tst_r_imm(tmp, 0x000000ff);
1671         emit_or_t_if_eq(tmp);
1672         emith_tst_r_imm(tmp, 0x0000ff00);
1673         emit_or_t_if_eq(tmp);
1674         emith_tst_r_imm(tmp, 0x00ff0000);
1675         emit_or_t_if_eq(tmp);
1676         emith_tst_r_imm(tmp, 0xff000000);
1677         emit_or_t_if_eq(tmp);
1678         rcache_free_tmp(tmp);
1679         goto end_op;
1680       case 0x0d: // XTRCT  Rm,Rn        0010nnnnmmmm1101
1681         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1682         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1683         emith_lsr(tmp, tmp, 16);
1684         emith_or_r_r_lsl(tmp, tmp2, 16);
1685         goto end_op;
1686       case 0x0e: // MULU.W Rm,Rn        0010nnnnmmmm1110
1687       case 0x0f: // MULS.W Rm,Rn        0010nnnnmmmm1111
1688         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
1689         tmp  = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
1690         if (op & 1) {
1691           emith_sext(tmp, tmp2, 16);
1692         } else
1693           emith_clear_msb(tmp, tmp2, 16);
1694         tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1695         tmp2 = rcache_get_tmp();
1696         if (op & 1) {
1697           emith_sext(tmp2, tmp3, 16);
1698         } else
1699           emith_clear_msb(tmp2, tmp3, 16);
1700         emith_mul(tmp, tmp, tmp2);
1701         rcache_free_tmp(tmp2);
1702 //      FIXME: causes timing issues in Doom?
1703 //        cycles++;
1704         goto end_op;
1705       }
1706       goto default_;
1707
1708     /////////////////////////////////////////////
1709     case 0x03:
1710       switch (op & 0x0f)
1711       {
1712       case 0x00: // CMP/EQ Rm,Rn        0011nnnnmmmm0000
1713       case 0x02: // CMP/HS Rm,Rn        0011nnnnmmmm0010
1714       case 0x03: // CMP/GE Rm,Rn        0011nnnnmmmm0011
1715       case 0x06: // CMP/HI Rm,Rn        0011nnnnmmmm0110
1716       case 0x07: // CMP/GT Rm,Rn        0011nnnnmmmm0111
1717         sr   = rcache_get_reg(SHR_SR, RC_GR_RMW);
1718         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
1719         tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1720         if (drcf.delayed_op)
1721           DELAY_SAVE_T(sr);
1722         emith_bic_r_imm(sr, T);
1723         emith_cmp_r_r(tmp2, tmp3);
1724         switch (op & 0x07)
1725         {
1726         case 0x00: // CMP/EQ
1727           emit_or_t_if_eq(sr);
1728           break;
1729         case 0x02: // CMP/HS
1730           EMITH_SJMP_START(DCOND_LO);
1731           emith_or_r_imm_c(DCOND_HS, sr, T);
1732           EMITH_SJMP_END(DCOND_LO);
1733           break;
1734         case 0x03: // CMP/GE
1735           EMITH_SJMP_START(DCOND_LT);
1736           emith_or_r_imm_c(DCOND_GE, sr, T);
1737           EMITH_SJMP_END(DCOND_LT);
1738           break;
1739         case 0x06: // CMP/HI
1740           EMITH_SJMP_START(DCOND_LS);
1741           emith_or_r_imm_c(DCOND_HI, sr, T);
1742           EMITH_SJMP_END(DCOND_LS);
1743           break;
1744         case 0x07: // CMP/GT
1745           EMITH_SJMP_START(DCOND_LE);
1746           emith_or_r_imm_c(DCOND_GT, sr, T);
1747           EMITH_SJMP_END(DCOND_LE);
1748           break;
1749         }
1750         goto end_op;
1751       case 0x04: // DIV1    Rm,Rn       0011nnnnmmmm0100
1752         // Q1 = carry(Rn = (Rn << 1) | T)
1753         // if Q ^ M
1754         //   Q2 = carry(Rn += Rm)
1755         // else
1756         //   Q2 = carry(Rn -= Rm)
1757         // Q = M ^ Q1 ^ Q2
1758         // T = (Q == M) = !(Q ^ M) = !(Q1 ^ Q2)
1759         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1760         tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1761         sr   = rcache_get_reg(SHR_SR, RC_GR_RMW);
1762         if (drcf.delayed_op)
1763           DELAY_SAVE_T(sr);
1764         emith_tpop_carry(sr, 0);
1765         emith_adcf_r_r(tmp2, tmp2);
1766         emith_tpush_carry(sr, 0);            // keep Q1 in T for now
1767         tmp4 = rcache_get_tmp();
1768         emith_and_r_r_imm(tmp4, sr, M);
1769         emith_eor_r_r_lsr(sr, tmp4, M_SHIFT - Q_SHIFT); // Q ^= M
1770         rcache_free_tmp(tmp4);
1771         // add or sub, invert T if carry to get Q1 ^ Q2
1772         // in: (Q ^ M) passed in Q, Q1 in T
1773         emith_sh2_div1_step(tmp2, tmp3, sr);
1774         emith_bic_r_imm(sr, Q);
1775         emith_tst_r_imm(sr, M);
1776         EMITH_SJMP_START(DCOND_EQ);
1777         emith_or_r_imm_c(DCOND_NE, sr, Q);  // Q = M
1778         EMITH_SJMP_END(DCOND_EQ);
1779         emith_tst_r_imm(sr, T);
1780         EMITH_SJMP_START(DCOND_EQ);
1781         emith_eor_r_imm_c(DCOND_NE, sr, Q); // Q = M ^ Q1 ^ Q2
1782         EMITH_SJMP_END(DCOND_EQ);
1783         emith_eor_r_imm(sr, T);             // T = !(Q1 ^ Q2)
1784         goto end_op;
1785       case 0x05: // DMULU.L Rm,Rn       0011nnnnmmmm0101
1786         tmp  = rcache_get_reg(GET_Rn(), RC_GR_READ);
1787         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1788         tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
1789         tmp4 = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
1790         emith_mul_u64(tmp3, tmp4, tmp, tmp2);
1791         goto end_op;
1792       case 0x08: // SUB     Rm,Rn       0011nnnnmmmm1000
1793       case 0x0c: // ADD     Rm,Rn       0011nnnnmmmm1100
1794         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1795         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1796         if (op & 4) {
1797           emith_add_r_r(tmp, tmp2);
1798         } else
1799           emith_sub_r_r(tmp, tmp2);
1800         goto end_op;
1801       case 0x0a: // SUBC    Rm,Rn       0011nnnnmmmm1010
1802       case 0x0e: // ADDC    Rm,Rn       0011nnnnmmmm1110
1803         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1804         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1805         sr   = rcache_get_reg(SHR_SR, RC_GR_RMW);
1806         if (drcf.delayed_op)
1807           DELAY_SAVE_T(sr);
1808         if (op & 4) { // adc
1809           emith_tpop_carry(sr, 0);
1810           emith_adcf_r_r(tmp, tmp2);
1811           emith_tpush_carry(sr, 0);
1812         } else {
1813           emith_tpop_carry(sr, 1);
1814           emith_sbcf_r_r(tmp, tmp2);
1815           emith_tpush_carry(sr, 1);
1816         }
1817         goto end_op;
1818       case 0x0b: // SUBV    Rm,Rn       0011nnnnmmmm1011
1819       case 0x0f: // ADDV    Rm,Rn       0011nnnnmmmm1111
1820         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1821         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1822         sr   = rcache_get_reg(SHR_SR, RC_GR_RMW);
1823         if (drcf.delayed_op)
1824           DELAY_SAVE_T(sr);
1825         emith_bic_r_imm(sr, T);
1826         if (op & 4) {
1827           emith_addf_r_r(tmp, tmp2);
1828         } else
1829           emith_subf_r_r(tmp, tmp2);
1830         EMITH_SJMP_START(DCOND_VC);
1831         emith_or_r_imm_c(DCOND_VS, sr, T);
1832         EMITH_SJMP_END(DCOND_VC);
1833         goto end_op;
1834       case 0x0d: // DMULS.L Rm,Rn       0011nnnnmmmm1101
1835         tmp  = rcache_get_reg(GET_Rn(), RC_GR_READ);
1836         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1837         tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
1838         tmp4 = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
1839         emith_mul_s64(tmp3, tmp4, tmp, tmp2);
1840         goto end_op;
1841       }
1842       goto default_;
1843
1844     /////////////////////////////////////////////
1845     case 0x04:
1846       switch (op & 0x0f)
1847       {
1848       case 0x00:
1849         switch (GET_Fx())
1850         {
1851         case 0: // SHLL Rn    0100nnnn00000000
1852         case 2: // SHAL Rn    0100nnnn00100000
1853           tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1854           sr  = rcache_get_reg(SHR_SR, RC_GR_RMW);
1855           if (drcf.delayed_op)
1856             DELAY_SAVE_T(sr);
1857           emith_tpop_carry(sr, 0); // dummy
1858           emith_lslf(tmp, tmp, 1);
1859           emith_tpush_carry(sr, 0);
1860           goto end_op;
1861         case 1: // DT Rn      0100nnnn00010000
1862           sr  = rcache_get_reg(SHR_SR, RC_GR_RMW);
1863           if (drcf.delayed_op)
1864             DELAY_SAVE_T(sr);
1865           if (FETCH_OP(pc) == 0x8bfd) { // BF #-2
1866             if (gconst_get(GET_Rn(), &tmp)) {
1867               // XXX: limit burned cycles
1868               emit_move_r_imm32(GET_Rn(), 0);
1869               emith_or_r_imm(sr, T);
1870               cycles += tmp * 4 + 1; // +1 syncs with noconst version, not sure why
1871               skip_op = 1;
1872             }
1873             else
1874               emith_sh2_dtbf_loop();
1875             goto end_op;
1876           }
1877           tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1878           emith_bic_r_imm(sr, T);
1879           emith_subf_r_imm(tmp, 1);
1880           emit_or_t_if_eq(sr);
1881           goto end_op;
1882         }
1883         goto default_;
1884       case 0x01:
1885         switch (GET_Fx())
1886         {
1887         case 0: // SHLR Rn    0100nnnn00000001
1888         case 2: // SHAR Rn    0100nnnn00100001
1889           tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1890           sr  = rcache_get_reg(SHR_SR, RC_GR_RMW);
1891           if (drcf.delayed_op)
1892             DELAY_SAVE_T(sr);
1893           emith_tpop_carry(sr, 0); // dummy
1894           if (op & 0x20) {
1895             emith_asrf(tmp, tmp, 1);
1896           } else
1897             emith_lsrf(tmp, tmp, 1);
1898           emith_tpush_carry(sr, 0);
1899           goto end_op;
1900         case 1: // CMP/PZ Rn  0100nnnn00010001
1901           tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1902           sr  = rcache_get_reg(SHR_SR, RC_GR_RMW);
1903           if (drcf.delayed_op)
1904             DELAY_SAVE_T(sr);
1905           emith_bic_r_imm(sr, T);
1906           emith_cmp_r_imm(tmp, 0);
1907           EMITH_SJMP_START(DCOND_LT);
1908           emith_or_r_imm_c(DCOND_GE, sr, T);
1909           EMITH_SJMP_END(DCOND_LT);
1910           goto end_op;
1911         }
1912         goto default_;
1913       case 0x02:
1914       case 0x03:
1915         switch (op & 0x3f)
1916         {
1917         case 0x02: // STS.L    MACH,@–Rn 0100nnnn00000010
1918           tmp = SHR_MACH;
1919           break;
1920         case 0x12: // STS.L    MACL,@–Rn 0100nnnn00010010
1921           tmp = SHR_MACL;
1922           break;
1923         case 0x22: // STS.L    PR,@–Rn   0100nnnn00100010
1924           tmp = SHR_PR;
1925           break;
1926         case 0x03: // STC.L    SR,@–Rn   0100nnnn00000011
1927           tmp = SHR_SR;
1928           break;
1929         case 0x13: // STC.L    GBR,@–Rn  0100nnnn00010011
1930           tmp = SHR_GBR;
1931           break;
1932         case 0x23: // STC.L    VBR,@–Rn  0100nnnn00100011
1933           tmp = SHR_VBR;
1934           break;
1935         default:
1936           goto default_;
1937         }
1938         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1939         emith_sub_r_imm(tmp2, 4);
1940         rcache_clean();
1941         rcache_get_reg_arg(0, GET_Rn());
1942         tmp3 = rcache_get_reg_arg(1, tmp);
1943         if (tmp == SHR_SR)
1944           emith_clear_msb(tmp3, tmp3, 22); // reserved bits defined by ISA as 0
1945         emit_memhandler_write(2, pc, drcf.delayed_op);
1946         goto end_op;
1947       case 0x04:
1948       case 0x05:
1949         switch (op & 0x3f)
1950         {
1951         case 0x04: // ROTL   Rn          0100nnnn00000100
1952         case 0x05: // ROTR   Rn          0100nnnn00000101
1953           tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1954           sr  = rcache_get_reg(SHR_SR, RC_GR_RMW);
1955           if (drcf.delayed_op)
1956             DELAY_SAVE_T(sr);
1957           emith_tpop_carry(sr, 0); // dummy
1958           if (op & 1) {
1959             emith_rorf(tmp, tmp, 1);
1960           } else
1961             emith_rolf(tmp, tmp, 1);
1962           emith_tpush_carry(sr, 0);
1963           goto end_op;
1964         case 0x24: // ROTCL  Rn          0100nnnn00100100
1965         case 0x25: // ROTCR  Rn          0100nnnn00100101
1966           tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1967           sr  = rcache_get_reg(SHR_SR, RC_GR_RMW);
1968           if (drcf.delayed_op)
1969             DELAY_SAVE_T(sr);
1970           emith_tpop_carry(sr, 0);
1971           if (op & 1) {
1972             emith_rorcf(tmp);
1973           } else
1974             emith_rolcf(tmp);
1975           emith_tpush_carry(sr, 0);
1976           goto end_op;
1977         case 0x15: // CMP/PL Rn          0100nnnn00010101
1978           tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1979           sr  = rcache_get_reg(SHR_SR, RC_GR_RMW);
1980           if (drcf.delayed_op)
1981             DELAY_SAVE_T(sr);
1982           emith_bic_r_imm(sr, T);
1983           emith_cmp_r_imm(tmp, 0);
1984           EMITH_SJMP_START(DCOND_LE);
1985           emith_or_r_imm_c(DCOND_GT, sr, T);
1986           EMITH_SJMP_END(DCOND_LE);
1987           goto end_op;
1988         }
1989         goto default_;
1990       case 0x06:
1991       case 0x07:
1992         switch (op & 0x3f)
1993         {
1994         case 0x06: // LDS.L @Rm+,MACH 0100mmmm00000110
1995           tmp = SHR_MACH;
1996           break;
1997         case 0x16: // LDS.L @Rm+,MACL 0100mmmm00010110
1998           tmp = SHR_MACL;
1999           break;
2000         case 0x26: // LDS.L @Rm+,PR   0100mmmm00100110
2001           tmp = SHR_PR;
2002           break;
2003         case 0x07: // LDC.L @Rm+,SR   0100mmmm00000111
2004           tmp = SHR_SR;
2005           break;
2006         case 0x17: // LDC.L @Rm+,GBR  0100mmmm00010111
2007           tmp = SHR_GBR;
2008           break;
2009         case 0x27: // LDC.L @Rm+,VBR  0100mmmm00100111
2010           tmp = SHR_VBR;
2011           break;
2012         default:
2013           goto default_;
2014         }
2015         rcache_get_reg_arg(0, GET_Rn());
2016         tmp2 = emit_memhandler_read(2);
2017         if (tmp == SHR_SR) {
2018           sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2019           if (drcf.delayed_op)
2020             DELAY_SAVE_T(sr);
2021           emith_write_sr(sr, tmp2);
2022           drcf.test_irq = 1;
2023         } else {
2024           tmp = rcache_get_reg(tmp, RC_GR_WRITE);
2025           emith_move_r_r(tmp, tmp2);
2026         }
2027         rcache_free_tmp(tmp2);
2028         tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
2029         emith_add_r_imm(tmp, 4);
2030         goto end_op;
2031       case 0x08:
2032       case 0x09:
2033         switch (GET_Fx())
2034         {
2035         case 0:
2036           // SHLL2 Rn        0100nnnn00001000
2037           // SHLR2 Rn        0100nnnn00001001
2038           tmp = 2;
2039           break;
2040         case 1:
2041           // SHLL8 Rn        0100nnnn00011000
2042           // SHLR8 Rn        0100nnnn00011001
2043           tmp = 8;
2044           break;
2045         case 2:
2046           // SHLL16 Rn       0100nnnn00101000
2047           // SHLR16 Rn       0100nnnn00101001
2048           tmp = 16;
2049           break;
2050         default:
2051           goto default_;
2052         }
2053         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_RMW);
2054         if (op & 1) {
2055           emith_lsr(tmp2, tmp2, tmp);
2056         } else
2057           emith_lsl(tmp2, tmp2, tmp);
2058         goto end_op;
2059       case 0x0a:
2060         switch (GET_Fx())
2061         {
2062         case 0: // LDS      Rm,MACH   0100mmmm00001010
2063           tmp2 = SHR_MACH;
2064           break;
2065         case 1: // LDS      Rm,MACL   0100mmmm00011010
2066           tmp2 = SHR_MACL;
2067           break;
2068         case 2: // LDS      Rm,PR     0100mmmm00101010
2069           tmp2 = SHR_PR;
2070           break;
2071         default:
2072           goto default_;
2073         }
2074         emit_move_r_r(tmp2, GET_Rn());
2075         goto end_op;
2076       case 0x0b:
2077         switch (GET_Fx())
2078         {
2079         case 0: // JSR  @Rm   0100mmmm00001011
2080         case 2: // JMP  @Rm   0100mmmm00101011
2081           DELAYED_OP;
2082           if (!(op & 0x20))
2083             emit_move_r_imm32(SHR_PR, pc + 2);
2084           emit_move_r_r(SHR_PC, (op >> 8) & 0x0f);
2085           out_pc = (u32)-1;
2086           cycles++;
2087           break;
2088         case 1: // TAS.B @Rn  0100nnnn00011011
2089           // XXX: is TAS working on 32X?
2090           rcache_get_reg_arg(0, GET_Rn());
2091           tmp = emit_memhandler_read(0);
2092           sr  = rcache_get_reg(SHR_SR, RC_GR_RMW);
2093           if (drcf.delayed_op)
2094             DELAY_SAVE_T(sr);
2095           emith_bic_r_imm(sr, T);
2096           emith_cmp_r_imm(tmp, 0);
2097           emit_or_t_if_eq(sr);
2098           rcache_clean();
2099           emith_or_r_imm(tmp, 0x80);
2100           tmp2 = rcache_get_tmp_arg(1); // assuming it differs to tmp
2101           emith_move_r_r(tmp2, tmp);
2102           rcache_free_tmp(tmp);
2103           rcache_get_reg_arg(0, GET_Rn());
2104           emit_memhandler_write(0, pc, drcf.delayed_op);
2105           cycles += 3;
2106           break;
2107         default:
2108           goto default_;
2109         }
2110         goto end_op;
2111       case 0x0e:
2112         tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
2113         switch (GET_Fx())
2114         {
2115         case 0: // LDC Rm,SR   0100mmmm00001110
2116           tmp2 = SHR_SR;
2117           break;
2118         case 1: // LDC Rm,GBR  0100mmmm00011110
2119           tmp2 = SHR_GBR;
2120           break;
2121         case 2: // LDC Rm,VBR  0100mmmm00101110
2122           tmp2 = SHR_VBR;
2123           break;
2124         default:
2125           goto default_;
2126         }
2127         if (tmp2 == SHR_SR) {
2128           sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2129           if (drcf.delayed_op)
2130             DELAY_SAVE_T(sr);
2131           emith_write_sr(sr, tmp);
2132           drcf.test_irq = 1;
2133         } else {
2134           tmp2 = rcache_get_reg(tmp2, RC_GR_WRITE);
2135           emith_move_r_r(tmp2, tmp);
2136         }
2137         goto end_op;
2138       case 0x0f:
2139         // MAC.W @Rm+,@Rn+  0100nnnnmmmm1111
2140         emit_indirect_read_double(&tmp, &tmp2, GET_Rn(), GET_Rm(), 1);
2141         emith_sext(tmp, tmp, 16);
2142         emith_sext(tmp2, tmp2, 16);
2143         tmp3 = rcache_get_reg(SHR_MACL, RC_GR_RMW);
2144         tmp4 = rcache_get_reg(SHR_MACH, RC_GR_RMW);
2145         emith_mula_s64(tmp3, tmp4, tmp, tmp2);
2146         rcache_free_tmp(tmp2);
2147         // XXX: MACH should be untouched when S is set?
2148         sr = rcache_get_reg(SHR_SR, RC_GR_READ);
2149         emith_tst_r_imm(sr, S);
2150         EMITH_JMP_START(DCOND_EQ);
2151
2152         emith_asr(tmp, tmp3, 31);
2153         emith_eorf_r_r(tmp, tmp4); // tmp = ((signed)macl >> 31) ^ mach
2154         EMITH_JMP_START(DCOND_EQ);
2155         emith_move_r_imm(tmp3, 0x80000000);
2156         emith_tst_r_r(tmp4, tmp4);
2157         EMITH_SJMP_START(DCOND_MI);
2158         emith_sub_r_imm_c(DCOND_PL, tmp3, 1); // positive
2159         EMITH_SJMP_END(DCOND_MI);
2160         EMITH_JMP_END(DCOND_EQ);
2161
2162         EMITH_JMP_END(DCOND_EQ);
2163         rcache_free_tmp(tmp);
2164         cycles += 2;
2165         goto end_op;
2166       }
2167       goto default_;
2168
2169     /////////////////////////////////////////////
2170     case 0x05:
2171       // MOV.L @(disp,Rm),Rn 0101nnnnmmmmdddd
2172       emit_memhandler_read_rr(GET_Rn(), GET_Rm(), (op & 0x0f) * 4, 2);
2173       goto end_op;
2174
2175     /////////////////////////////////////////////
2176     case 0x06:
2177       switch (op & 0x0f)
2178       {
2179       case 0x00: // MOV.B @Rm,Rn        0110nnnnmmmm0000
2180       case 0x01: // MOV.W @Rm,Rn        0110nnnnmmmm0001
2181       case 0x02: // MOV.L @Rm,Rn        0110nnnnmmmm0010
2182       case 0x04: // MOV.B @Rm+,Rn       0110nnnnmmmm0100
2183       case 0x05: // MOV.W @Rm+,Rn       0110nnnnmmmm0101
2184       case 0x06: // MOV.L @Rm+,Rn       0110nnnnmmmm0110
2185         emit_memhandler_read_rr(GET_Rn(), GET_Rm(), 0, op & 3);
2186         if ((op & 7) >= 4 && GET_Rn() != GET_Rm()) {
2187           tmp = rcache_get_reg(GET_Rm(), RC_GR_RMW);
2188           emith_add_r_imm(tmp, (1 << (op & 3)));
2189         }
2190         goto end_op;
2191       case 0x03:
2192       case 0x07 ... 0x0f:
2193         tmp  = rcache_get_reg(GET_Rm(), RC_GR_READ);
2194         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
2195         switch (op & 0x0f)
2196         {
2197         case 0x03: // MOV    Rm,Rn        0110nnnnmmmm0011
2198           emith_move_r_r(tmp2, tmp);
2199           break;
2200         case 0x07: // NOT    Rm,Rn        0110nnnnmmmm0111
2201           emith_mvn_r_r(tmp2, tmp);
2202           break;
2203         case 0x08: // SWAP.B Rm,Rn        0110nnnnmmmm1000
2204           tmp3 = tmp2;
2205           if (tmp == tmp2)
2206             tmp3 = rcache_get_tmp();
2207           tmp4 = rcache_get_tmp();
2208           emith_lsr(tmp3, tmp, 16);
2209           emith_or_r_r_lsl(tmp3, tmp, 24);
2210           emith_and_r_r_imm(tmp4, tmp, 0xff00);
2211           emith_or_r_r_lsl(tmp3, tmp4, 8);
2212           emith_rol(tmp2, tmp3, 16);
2213           rcache_free_tmp(tmp4);
2214           if (tmp == tmp2)
2215             rcache_free_tmp(tmp3);
2216           break;
2217         case 0x09: // SWAP.W Rm,Rn        0110nnnnmmmm1001
2218           emith_rol(tmp2, tmp, 16);
2219           break;
2220         case 0x0a: // NEGC   Rm,Rn        0110nnnnmmmm1010
2221           sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2222           if (drcf.delayed_op)
2223             DELAY_SAVE_T(sr);
2224           emith_tpop_carry(sr, 1);
2225           emith_negcf_r_r(tmp2, tmp);
2226           emith_tpush_carry(sr, 1);
2227           break;
2228         case 0x0b: // NEG    Rm,Rn        0110nnnnmmmm1011
2229           emith_neg_r_r(tmp2, tmp);
2230           break;
2231         case 0x0c: // EXTU.B Rm,Rn        0110nnnnmmmm1100
2232           emith_clear_msb(tmp2, tmp, 24);
2233           break;
2234         case 0x0d: // EXTU.W Rm,Rn        0110nnnnmmmm1101
2235           emith_clear_msb(tmp2, tmp, 16);
2236           break;
2237         case 0x0e: // EXTS.B Rm,Rn        0110nnnnmmmm1110
2238           emith_sext(tmp2, tmp, 8);
2239           break;
2240         case 0x0f: // EXTS.W Rm,Rn        0110nnnnmmmm1111
2241           emith_sext(tmp2, tmp, 16);
2242           break;
2243         }
2244         goto end_op;
2245       }
2246       goto default_;
2247
2248     /////////////////////////////////////////////
2249     case 0x07:
2250       // ADD #imm,Rn  0111nnnniiiiiiii
2251       tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
2252       if (op & 0x80) { // adding negative
2253         emith_sub_r_imm(tmp, -op & 0xff);
2254       } else
2255         emith_add_r_imm(tmp, op & 0xff);
2256       goto end_op;
2257
2258     /////////////////////////////////////////////
2259     case 0x08:
2260       switch (op & 0x0f00)
2261       {
2262       case 0x0000: // MOV.B R0,@(disp,Rn)  10000000nnnndddd
2263       case 0x0100: // MOV.W R0,@(disp,Rn)  10000001nnnndddd
2264         rcache_clean();
2265         tmp  = rcache_get_reg_arg(0, GET_Rm());
2266         tmp2 = rcache_get_reg_arg(1, SHR_R0);
2267         tmp3 = (op & 0x100) >> 8;
2268         if (op & 0x0f)
2269           emith_add_r_imm(tmp, (op & 0x0f) << tmp3);
2270         emit_memhandler_write(tmp3, pc, drcf.delayed_op);
2271         goto end_op;
2272       case 0x0400: // MOV.B @(disp,Rm),R0  10000100mmmmdddd
2273       case 0x0500: // MOV.W @(disp,Rm),R0  10000101mmmmdddd
2274         tmp = (op & 0x100) >> 8;
2275         emit_memhandler_read_rr(SHR_R0, GET_Rm(), (op & 0x0f) << tmp, tmp);
2276         goto end_op;
2277       case 0x0800: // CMP/EQ #imm,R0       10001000iiiiiiii
2278         // XXX: could use cmn
2279         tmp  = rcache_get_tmp();
2280         tmp2 = rcache_get_reg(0, RC_GR_READ);
2281         sr   = rcache_get_reg(SHR_SR, RC_GR_RMW);
2282         if (drcf.delayed_op)
2283           DELAY_SAVE_T(sr);
2284         emith_move_r_imm_s8(tmp, op & 0xff);
2285         emith_bic_r_imm(sr, T);
2286         emith_cmp_r_r(tmp2, tmp);
2287         emit_or_t_if_eq(sr);
2288         rcache_free_tmp(tmp);
2289         goto end_op;
2290       case 0x0d00: // BT/S label 10001101dddddddd
2291       case 0x0f00: // BF/S label 10001111dddddddd
2292         DELAYED_OP;
2293         cycles--;
2294         // fallthrough
2295       case 0x0900: // BT   label 10001001dddddddd
2296       case 0x0b00: // BF   label 10001011dddddddd
2297         // will handle conditional branches later
2298         pending_branch_cond = (op & 0x0200) ? DCOND_EQ : DCOND_NE;
2299         i = ((signed int)(op << 24) >> 23);
2300         pending_branch_pc = pc + i + 2;
2301         cycles += 2;
2302         goto end_op;
2303       }
2304       goto default_;
2305
2306     /////////////////////////////////////////////
2307     case 0x09:
2308       // MOV.W @(disp,PC),Rn  1001nnnndddddddd
2309       tmp = pc + (op & 0xff) * 2 + 2;
2310 #if PROPAGATE_CONSTANTS
2311       if (tmp < end_pc + MAX_LITERAL_OFFSET && literal_addr_count < MAX_LITERALS) {
2312         ADD_TO_ARRAY(literal_addr, literal_addr_count, tmp,);
2313         gconst_new(GET_Rn(), (u32)(int)(signed short)FETCH_OP(tmp));
2314       }
2315       else
2316 #endif
2317       {
2318         tmp2 = rcache_get_tmp_arg(0);
2319         emith_move_r_imm(tmp2, tmp);
2320         tmp2 = emit_memhandler_read(1);
2321         tmp3 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
2322         emith_sext(tmp3, tmp2, 16);
2323         rcache_free_tmp(tmp2);
2324       }
2325       goto end_op;
2326
2327     /////////////////////////////////////////////
2328     case 0x0a:
2329       // BRA  label 1010dddddddddddd
2330       DELAYED_OP;
2331       sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2332       tmp = ((signed int)(op << 20) >> 19);
2333       out_pc = pc + tmp + 2;
2334       if (tmp == (u32)-4)
2335         emith_clear_msb(sr, sr, 20); // burn cycles
2336       cycles++;
2337       break;
2338
2339     /////////////////////////////////////////////
2340     case 0x0b:
2341       // BSR  label 1011dddddddddddd
2342       DELAYED_OP;
2343       emit_move_r_imm32(SHR_PR, pc + 2);
2344       tmp = ((signed int)(op << 20) >> 19);
2345       out_pc = pc + tmp + 2;
2346       cycles++;
2347       break;
2348
2349     /////////////////////////////////////////////
2350     case 0x0c:
2351       switch (op & 0x0f00)
2352       {
2353       case 0x0000: // MOV.B R0,@(disp,GBR)   11000000dddddddd
2354       case 0x0100: // MOV.W R0,@(disp,GBR)   11000001dddddddd
2355       case 0x0200: // MOV.L R0,@(disp,GBR)   11000010dddddddd
2356         rcache_clean();
2357         tmp  = rcache_get_reg_arg(0, SHR_GBR);
2358         tmp2 = rcache_get_reg_arg(1, SHR_R0);
2359         tmp3 = (op & 0x300) >> 8;
2360         emith_add_r_imm(tmp, (op & 0xff) << tmp3);
2361         emit_memhandler_write(tmp3, pc, drcf.delayed_op);
2362         goto end_op;
2363       case 0x0400: // MOV.B @(disp,GBR),R0   11000100dddddddd
2364       case 0x0500: // MOV.W @(disp,GBR),R0   11000101dddddddd
2365       case 0x0600: // MOV.L @(disp,GBR),R0   11000110dddddddd
2366         tmp = (op & 0x300) >> 8;
2367         emit_memhandler_read_rr(SHR_R0, SHR_GBR, (op & 0xff) << tmp, tmp);
2368         goto end_op;
2369       case 0x0300: // TRAPA #imm      11000011iiiiiiii
2370         tmp = rcache_get_reg(SHR_SP, RC_GR_RMW);
2371         emith_sub_r_imm(tmp, 4*2);
2372         // push SR
2373         tmp = rcache_get_reg_arg(0, SHR_SP);
2374         emith_add_r_imm(tmp, 4);
2375         tmp = rcache_get_reg_arg(1, SHR_SR);
2376         emith_clear_msb(tmp, tmp, 22);
2377         emit_memhandler_write(2, pc, drcf.delayed_op);
2378         // push PC
2379         rcache_get_reg_arg(0, SHR_SP);
2380         tmp = rcache_get_tmp_arg(1);
2381         emith_move_r_imm(tmp, pc);
2382         emit_memhandler_write(2, pc, drcf.delayed_op);
2383         // obtain new PC
2384         emit_memhandler_read_rr(SHR_PC, SHR_VBR, (op & 0xff) * 4, 2);
2385         out_pc = (u32)-1;
2386         cycles += 7;
2387         goto end_op;
2388       case 0x0700: // MOVA @(disp,PC),R0    11000111dddddddd
2389         emit_move_r_imm32(SHR_R0, (pc + (op & 0xff) * 4 + 2) & ~3);
2390         goto end_op;
2391       case 0x0800: // TST #imm,R0           11001000iiiiiiii
2392         tmp = rcache_get_reg(SHR_R0, RC_GR_READ);
2393         sr  = rcache_get_reg(SHR_SR, RC_GR_RMW);
2394         if (drcf.delayed_op)
2395           DELAY_SAVE_T(sr);
2396         emith_bic_r_imm(sr, T);
2397         emith_tst_r_imm(tmp, op & 0xff);
2398         emit_or_t_if_eq(sr);
2399         goto end_op;
2400       case 0x0900: // AND #imm,R0           11001001iiiiiiii
2401         tmp = rcache_get_reg(SHR_R0, RC_GR_RMW);
2402         emith_and_r_imm(tmp, op & 0xff);
2403         goto end_op;
2404       case 0x0a00: // XOR #imm,R0           11001010iiiiiiii
2405         tmp = rcache_get_reg(SHR_R0, RC_GR_RMW);
2406         emith_eor_r_imm(tmp, op & 0xff);
2407         goto end_op;
2408       case 0x0b00: // OR  #imm,R0           11001011iiiiiiii
2409         tmp = rcache_get_reg(SHR_R0, RC_GR_RMW);
2410         emith_or_r_imm(tmp, op & 0xff);
2411         goto end_op;
2412       case 0x0c00: // TST.B #imm,@(R0,GBR)  11001100iiiiiiii
2413         tmp = emit_indirect_indexed_read(SHR_R0, SHR_GBR, 0);
2414         sr  = rcache_get_reg(SHR_SR, RC_GR_RMW);
2415         if (drcf.delayed_op)
2416           DELAY_SAVE_T(sr);
2417         emith_bic_r_imm(sr, T);
2418         emith_tst_r_imm(tmp, op & 0xff);
2419         emit_or_t_if_eq(sr);
2420         rcache_free_tmp(tmp);
2421         cycles += 2;
2422         goto end_op;
2423       case 0x0d00: // AND.B #imm,@(R0,GBR)  11001101iiiiiiii
2424         tmp = emit_indirect_indexed_read(SHR_R0, SHR_GBR, 0);
2425         emith_and_r_imm(tmp, op & 0xff);
2426         goto end_rmw_op;
2427       case 0x0e00: // XOR.B #imm,@(R0,GBR)  11001110iiiiiiii
2428         tmp = emit_indirect_indexed_read(SHR_R0, SHR_GBR, 0);
2429         emith_eor_r_imm(tmp, op & 0xff);
2430         goto end_rmw_op;
2431       case 0x0f00: // OR.B  #imm,@(R0,GBR)  11001111iiiiiiii
2432         tmp = emit_indirect_indexed_read(SHR_R0, SHR_GBR, 0);
2433         emith_or_r_imm(tmp, op & 0xff);
2434       end_rmw_op:
2435         tmp2 = rcache_get_tmp_arg(1);
2436         emith_move_r_r(tmp2, tmp);
2437         rcache_free_tmp(tmp);
2438         tmp3 = rcache_get_reg_arg(0, SHR_GBR);
2439         tmp4 = rcache_get_reg(SHR_R0, RC_GR_READ);
2440         emith_add_r_r(tmp3, tmp4);
2441         emit_memhandler_write(0, pc, drcf.delayed_op);
2442         cycles += 2;
2443         goto end_op;
2444       }
2445       goto default_;
2446
2447     /////////////////////////////////////////////
2448     case 0x0d:
2449       // MOV.L @(disp,PC),Rn  1101nnnndddddddd
2450       tmp = (pc + (op & 0xff) * 4 + 2) & ~3;
2451 #if PROPAGATE_CONSTANTS
2452       if (tmp < end_pc + MAX_LITERAL_OFFSET && literal_addr_count < MAX_LITERALS) {
2453         ADD_TO_ARRAY(literal_addr, literal_addr_count, tmp,);
2454         gconst_new(GET_Rn(), FETCH32(tmp));
2455       }
2456       else
2457 #endif
2458       {
2459         tmp2 = rcache_get_tmp_arg(0);
2460         emith_move_r_imm(tmp2, tmp);
2461         tmp2 = emit_memhandler_read(2);
2462         tmp3 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
2463         emith_move_r_r(tmp3, tmp2);
2464         rcache_free_tmp(tmp2);
2465       }
2466       goto end_op;
2467
2468     /////////////////////////////////////////////
2469     case 0x0e:
2470       // MOV #imm,Rn   1110nnnniiiiiiii
2471       emit_move_r_imm32(GET_Rn(), (u32)(signed int)(signed char)op);
2472       goto end_op;
2473
2474     default:
2475     default_:
2476       elprintf(EL_ANOMALY, "%csh2 drc: unhandled op %04x @ %08x",
2477         sh2->is_slave ? 's' : 'm', op, pc - 2);
2478 #ifdef DRC_DEBUG_INTERP
2479       emit_move_r_imm32(SHR_PC, pc - 2);
2480       rcache_flush();
2481       emith_pass_arg_r(0, CONTEXT_REG);
2482       emith_pass_arg_imm(1, op);
2483       emith_call(sh2_do_op);
2484 #endif
2485       break;
2486     }
2487
2488 end_op:
2489     rcache_unlock_all();
2490
2491     // conditional branch handling (with/without delay)
2492     if (pending_branch_cond != -1 && drcf.delayed_op != 2)
2493     {
2494       u32 target_pc = pending_branch_pc;
2495       void *target;
2496
2497       sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2498       // handle cycles
2499       FLUSH_CYCLES(sr);
2500       rcache_clean();
2501       if (drcf.use_saved_t)
2502         emith_tst_r_imm(sr, T_save);
2503       else
2504         emith_tst_r_imm(sr, T);
2505
2506 #if LINK_BRANCHES
2507       if (find_in_array(branch_target_pc, branch_target_count, target_pc) >= 0) {
2508         // local branch
2509         // XXX: jumps back can be linked already
2510         branch_patch_pc[branch_patch_count] = target_pc;
2511         branch_patch_ptr[branch_patch_count] = tcache_ptr;
2512         emith_jump_cond_patchable(pending_branch_cond, tcache_ptr);
2513
2514         branch_patch_count++;
2515         if (branch_patch_count == MAX_LOCAL_BRANCHES) {
2516           printf("warning: too many local branches\n");
2517           break;
2518         }
2519       }
2520       else
2521 #endif
2522       {
2523         // can't resolve branch locally, make a block exit
2524         emit_move_r_imm32(SHR_PC, target_pc);
2525         rcache_clean();
2526
2527         target = dr_prepare_ext_branch(target_pc, sh2, tcache_id);
2528         if (target == NULL)
2529           return NULL;
2530         emith_jump_cond_patchable(pending_branch_cond, target);
2531       }
2532
2533       drcf.use_saved_t = 0;
2534       pending_branch_cond = -1;
2535     }
2536
2537     // test irq?
2538     // XXX: delay slots..
2539     if (drcf.test_irq && drcf.delayed_op != 2) {
2540       if (!drcf.delayed_op)
2541         emit_move_r_imm32(SHR_PC, pc);
2542       sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2543       FLUSH_CYCLES(sr);
2544       rcache_flush();
2545       emith_call(sh2_drc_test_irq);
2546       drcf.test_irq = 0;
2547     }
2548
2549     do_host_disasm(tcache_id);
2550
2551     if (out_pc != 0 && drcf.delayed_op != 2)
2552       break;
2553   }
2554
2555   tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
2556   FLUSH_CYCLES(tmp);
2557   rcache_flush();
2558
2559   if (out_pc == (u32)-1) {
2560     // indirect jump -> back to dispatcher
2561     emith_jump(sh2_drc_dispatcher);
2562   } else {
2563     void *target;
2564     if (out_pc == 0)
2565       out_pc = pc;
2566     emit_move_r_imm32(SHR_PC, out_pc);
2567     rcache_flush();
2568
2569     target = dr_prepare_ext_branch(out_pc, sh2, tcache_id);
2570     if (target == NULL)
2571       return NULL;
2572     emith_jump_patchable(target);
2573   }
2574
2575   // link local branches
2576   for (i = 0; i < branch_patch_count; i++) {
2577     void *target;
2578     int t;
2579     t = find_in_array(branch_target_pc, branch_target_count, branch_patch_pc[i]);
2580     target = branch_target_ptr[t];
2581     if (target == NULL) {
2582       // flush pc and go back to dispatcher (should no longer happen)
2583       printf("stray branch to %08x %p\n", branch_patch_pc[i], tcache_ptr);
2584       target = tcache_ptr;
2585       emit_move_r_imm32(SHR_PC, branch_patch_pc[i]);
2586       rcache_flush();
2587       emith_jump(sh2_drc_dispatcher);
2588     }
2589     emith_jump_patch(branch_patch_ptr[i], target);
2590   }
2591
2592   end_pc = pc;
2593
2594   // mark memory blocks as containing compiled code
2595   // override any overlay blocks as they become unreachable anyway
2596   if (tcache_id != 0 || (this_block->addr & 0xc7fc0000) == 0x06000000)
2597   {
2598     u16 *drc_ram_blk = NULL;
2599     u32 mask = 0, shift = 0;
2600
2601     if (tcache_id != 0) {
2602       // data array, BIOS
2603       drc_ram_blk = Pico32xMem->drcblk_da[sh2->is_slave];
2604       shift = SH2_DRCBLK_DA_SHIFT;
2605       mask = 0xfff;
2606     }
2607     else if ((this_block->addr & 0xc7fc0000) == 0x06000000) {
2608       // SDRAM
2609       drc_ram_blk = Pico32xMem->drcblk_ram;
2610       shift = SH2_DRCBLK_RAM_SHIFT;
2611       mask = 0x3ffff;
2612     }
2613
2614     drc_ram_blk[(base_pc >> shift) & mask] = (blkid_main << 1) | 1;
2615     for (pc = base_pc + 2; pc < end_pc; pc += 2)
2616       drc_ram_blk[(pc >> shift) & mask] = blkid_main << 1;
2617
2618     // mark subblocks
2619     for (i = 0; i < branch_target_count; i++)
2620       if (branch_target_blkid[i] != 0)
2621         drc_ram_blk[(branch_target_pc[i] >> shift) & mask] =
2622           (branch_target_blkid[i] << 1) | 1;
2623
2624     // mark literals
2625     for (i = 0; i < literal_addr_count; i++) {
2626       tmp = literal_addr[i];
2627       //printf("marking literal %08x\n", tmp);
2628       drc_ram_blk[(tmp >> shift) & mask] = blkid_main << 1;
2629       if (!(tmp & 3)) // assume long
2630         drc_ram_blk[((tmp + 2) >> shift) & mask] = blkid_main << 1;
2631     }
2632   }
2633
2634   tcache_ptrs[tcache_id] = tcache_ptr;
2635
2636   host_instructions_updated(block_entry, tcache_ptr);
2637
2638   do_host_disasm(tcache_id);
2639   dbg(1, " block #%d,%d tcache %d/%d, insns %d -> %d %.3f",
2640     tcache_id, block_counts[tcache_id],
2641     tcache_ptr - tcache_bases[tcache_id], tcache_sizes[tcache_id],
2642     insns_compiled, host_insn_count, (double)host_insn_count / insns_compiled);
2643   if ((sh2->pc & 0xc6000000) == 0x02000000) // ROM
2644     dbg(1, "  hash collisions %d/%d", hash_collisions, block_counts[tcache_id]);
2645 /*
2646  printf("~~~\n");
2647  tcache_dsm_ptrs[tcache_id] = block_entry;
2648  do_host_disasm(tcache_id);
2649  printf("~~~\n");
2650 */
2651
2652 #if (DRC_DEBUG & 2)
2653   fflush(stdout);
2654 #endif
2655
2656   return block_entry;
2657 }
2658
2659 static void sh2_generate_utils(void)
2660 {
2661   int arg0, arg1, arg2, sr, tmp;
2662   void *sh2_drc_write_end, *sh2_drc_write_slot_end;
2663
2664   sh2_drc_write32 = p32x_sh2_write32;
2665   sh2_drc_read8  = p32x_sh2_read8;
2666   sh2_drc_read16 = p32x_sh2_read16;
2667   sh2_drc_read32 = p32x_sh2_read32;
2668
2669   host_arg2reg(arg0, 0);
2670   host_arg2reg(arg1, 1);
2671   host_arg2reg(arg2, 2);
2672   emith_move_r_r(arg0, arg0); // nop
2673
2674   // sh2_drc_exit(void)
2675   sh2_drc_exit = (void *)tcache_ptr;
2676   emit_do_static_regs(1, arg2);
2677   emith_sh2_drc_exit();
2678
2679   // sh2_drc_dispatcher(void)
2680   sh2_drc_dispatcher = (void *)tcache_ptr;
2681   sr = rcache_get_reg(SHR_SR, RC_GR_READ);
2682   emith_cmp_r_imm(sr, 0);
2683   emith_jump_cond(DCOND_LT, sh2_drc_exit);
2684   rcache_invalidate();
2685   emith_ctx_read(arg0, SHR_PC * 4);
2686   emith_ctx_read(arg1, offsetof(SH2, is_slave));
2687   emith_add_r_r_imm(arg2, CONTEXT_REG, offsetof(SH2, drc_tmp));
2688   emith_call(dr_lookup_block);
2689   emit_block_entry();
2690   // lookup failed, call sh2_translate()
2691   emith_move_r_r(arg0, CONTEXT_REG);
2692   emith_ctx_read(arg1, offsetof(SH2, drc_tmp)); // tcache_id
2693   emith_call(sh2_translate);
2694   emit_block_entry();
2695   // sh2_translate() failed, flush cache and retry
2696   emith_ctx_read(arg0, offsetof(SH2, drc_tmp));
2697   emith_call(flush_tcache);
2698   emith_move_r_r(arg0, CONTEXT_REG);
2699   emith_ctx_read(arg1, offsetof(SH2, drc_tmp));
2700   emith_call(sh2_translate);
2701   emit_block_entry();
2702   // XXX: can't translate, fail
2703   emith_call(exit);
2704
2705   // sh2_drc_test_irq(void)
2706   // assumes it's called from main function (may jump to dispatcher)
2707   sh2_drc_test_irq = (void *)tcache_ptr;
2708   emith_ctx_read(arg1, offsetof(SH2, pending_level));
2709   sr = rcache_get_reg(SHR_SR, RC_GR_READ);
2710   emith_lsr(arg0, sr, I_SHIFT);
2711   emith_and_r_imm(arg0, 0x0f);
2712   emith_cmp_r_r(arg1, arg0); // pending_level > ((sr >> 4) & 0x0f)?
2713   EMITH_SJMP_START(DCOND_GT);
2714   emith_ret_c(DCOND_LE);     // nope, return
2715   EMITH_SJMP_END(DCOND_GT);
2716   // adjust SP
2717   tmp = rcache_get_reg(SHR_SP, RC_GR_RMW);
2718   emith_sub_r_imm(tmp, 4*2);
2719   rcache_clean();
2720   // push SR
2721   tmp = rcache_get_reg_arg(0, SHR_SP);
2722   emith_add_r_imm(tmp, 4);
2723   tmp = rcache_get_reg_arg(1, SHR_SR);
2724   emith_clear_msb(tmp, tmp, 22);
2725   emith_move_r_r(arg2, CONTEXT_REG);
2726   emith_call(p32x_sh2_write32); // XXX: use sh2_drc_write32?
2727   rcache_invalidate();
2728   // push PC
2729   rcache_get_reg_arg(0, SHR_SP);
2730   emith_ctx_read(arg1, SHR_PC * 4);
2731   emith_move_r_r(arg2, CONTEXT_REG);
2732   emith_call(p32x_sh2_write32);
2733   rcache_invalidate();
2734   // update I, cycles, do callback
2735   emith_ctx_read(arg1, offsetof(SH2, pending_level));
2736   sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2737   emith_bic_r_imm(sr, I);
2738   emith_or_r_r_lsl(sr, arg1, I_SHIFT);
2739   emith_sub_r_imm(sr, 13 << 12); // at least 13 cycles
2740   rcache_flush();
2741   emith_move_r_r(arg0, CONTEXT_REG);
2742   emith_call_ctx(offsetof(SH2, irq_callback)); // vector = sh2->irq_callback(sh2, level);
2743   // obtain new PC
2744   emith_lsl(arg0, arg0, 2);
2745   emith_ctx_read(arg1, SHR_VBR * 4);
2746   emith_add_r_r(arg0, arg1);
2747   emit_memhandler_read(2);
2748   emith_ctx_write(arg0, SHR_PC * 4);
2749 #ifdef __i386__
2750   emith_add_r_imm(xSP, 4); // fix stack
2751 #endif
2752   emith_jump(sh2_drc_dispatcher);
2753   rcache_invalidate();
2754
2755   // sh2_drc_entry(SH2 *sh2)
2756   sh2_drc_entry = (void *)tcache_ptr;
2757   emith_sh2_drc_entry();
2758   emith_move_r_r(CONTEXT_REG, arg0); // move ctx, arg0
2759   emit_do_static_regs(0, arg2);
2760   emith_call(sh2_drc_test_irq);
2761   emith_jump(sh2_drc_dispatcher);
2762
2763   // write-caused irq detection
2764   sh2_drc_write_end = tcache_ptr;
2765   emith_tst_r_r(arg0, arg0);
2766   EMITH_SJMP_START(DCOND_NE);
2767   emith_jump_ctx_c(DCOND_EQ, offsetof(SH2, drc_tmp)); // return
2768   EMITH_SJMP_END(DCOND_NE);
2769   emith_call(sh2_drc_test_irq);
2770   emith_jump_ctx(offsetof(SH2, drc_tmp));
2771
2772   // write-caused irq detection for writes in delay slot
2773   sh2_drc_write_slot_end = tcache_ptr;
2774   emith_tst_r_r(arg0, arg0);
2775   EMITH_SJMP_START(DCOND_NE);
2776   emith_jump_ctx_c(DCOND_EQ, offsetof(SH2, drc_tmp));
2777   EMITH_SJMP_END(DCOND_NE);
2778   // just burn cycles to get back to dispatcher after branch is handled
2779   sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
2780   emith_ctx_write(sr, offsetof(SH2, irq_cycles));
2781   emith_clear_msb(sr, sr, 20); // clear cycles
2782   rcache_flush();
2783   emith_jump_ctx(offsetof(SH2, drc_tmp));
2784
2785   // sh2_drc_write8(u32 a, u32 d)
2786   sh2_drc_write8 = (void *)tcache_ptr;
2787   emith_ret_to_ctx(offsetof(SH2, drc_tmp));
2788   emith_ctx_read(arg2, offsetof(SH2, write8_tab));
2789   emith_sh2_wcall(arg0, arg2, sh2_drc_write_end);
2790
2791   // sh2_drc_write16(u32 a, u32 d)
2792   sh2_drc_write16 = (void *)tcache_ptr;
2793   emith_ret_to_ctx(offsetof(SH2, drc_tmp));
2794   emith_ctx_read(arg2, offsetof(SH2, write16_tab));
2795   emith_sh2_wcall(arg0, arg2, sh2_drc_write_end);
2796
2797   // sh2_drc_write8_slot(u32 a, u32 d)
2798   sh2_drc_write8_slot = (void *)tcache_ptr;
2799   emith_ret_to_ctx(offsetof(SH2, drc_tmp));
2800   emith_ctx_read(arg2, offsetof(SH2, write8_tab));
2801   emith_sh2_wcall(arg0, arg2, sh2_drc_write_slot_end);
2802
2803   // sh2_drc_write16_slot(u32 a, u32 d)
2804   sh2_drc_write16_slot = (void *)tcache_ptr;
2805   emith_ret_to_ctx(offsetof(SH2, drc_tmp));
2806   emith_ctx_read(arg2, offsetof(SH2, write16_tab));
2807   emith_sh2_wcall(arg0, arg2, sh2_drc_write_slot_end);
2808
2809 #ifdef PDB_NET
2810   // debug
2811   #define MAKE_READ_WRAPPER(func) { \
2812     void *tmp = (void *)tcache_ptr; \
2813     emith_push_ret(); \
2814     emith_call(func); \
2815     emith_ctx_read(arg2, offsetof(SH2, pdb_io_csum[0]));  \
2816     emith_addf_r_r(arg2, arg0);                           \
2817     emith_ctx_write(arg2, offsetof(SH2, pdb_io_csum[0])); \
2818     emith_ctx_read(arg2, offsetof(SH2, pdb_io_csum[1]));  \
2819     emith_adc_r_imm(arg2, 0x01000000);                    \
2820     emith_ctx_write(arg2, offsetof(SH2, pdb_io_csum[1])); \
2821     emith_pop_and_ret(); \
2822     func = tmp; \
2823   }
2824   #define MAKE_WRITE_WRAPPER(func) { \
2825     void *tmp = (void *)tcache_ptr; \
2826     emith_ctx_read(arg2, offsetof(SH2, pdb_io_csum[0]));  \
2827     emith_addf_r_r(arg2, arg1);                           \
2828     emith_ctx_write(arg2, offsetof(SH2, pdb_io_csum[0])); \
2829     emith_ctx_read(arg2, offsetof(SH2, pdb_io_csum[1]));  \
2830     emith_adc_r_imm(arg2, 0x01000000);                    \
2831     emith_ctx_write(arg2, offsetof(SH2, pdb_io_csum[1])); \
2832     emith_move_r_r(arg2, CONTEXT_REG);                    \
2833     emith_jump(func); \
2834     func = tmp; \
2835   }
2836
2837   MAKE_READ_WRAPPER(sh2_drc_read8);
2838   MAKE_READ_WRAPPER(sh2_drc_read16);
2839   MAKE_READ_WRAPPER(sh2_drc_read32);
2840   MAKE_WRITE_WRAPPER(sh2_drc_write8);
2841   MAKE_WRITE_WRAPPER(sh2_drc_write8_slot);
2842   MAKE_WRITE_WRAPPER(sh2_drc_write16);
2843   MAKE_WRITE_WRAPPER(sh2_drc_write16_slot);
2844   MAKE_WRITE_WRAPPER(sh2_drc_write32);
2845 #if (DRC_DEBUG & 2)
2846   host_dasm_new_symbol(sh2_drc_read8);
2847   host_dasm_new_symbol(sh2_drc_read16);
2848   host_dasm_new_symbol(sh2_drc_read32);
2849   host_dasm_new_symbol(sh2_drc_write32);
2850 #endif
2851 #endif
2852
2853   rcache_invalidate();
2854 #if (DRC_DEBUG & 2)
2855   host_dasm_new_symbol(sh2_drc_entry);
2856   host_dasm_new_symbol(sh2_drc_dispatcher);
2857   host_dasm_new_symbol(sh2_drc_exit);
2858   host_dasm_new_symbol(sh2_drc_test_irq);
2859   host_dasm_new_symbol(sh2_drc_write_end);
2860   host_dasm_new_symbol(sh2_drc_write_slot_end);
2861   host_dasm_new_symbol(sh2_drc_write8);
2862   host_dasm_new_symbol(sh2_drc_write8_slot);
2863   host_dasm_new_symbol(sh2_drc_write16);
2864   host_dasm_new_symbol(sh2_drc_write16_slot);
2865 #endif
2866 }
2867
2868 static void *sh2_smc_rm_block_entry(block_desc *bd, int tcache_id)
2869 {
2870   void *tmp;
2871
2872   // XXX: kill links somehow?
2873   dbg(1, "  killing entry %08x, blkid %d", bd->addr, bd - block_tables[tcache_id]);
2874   if (bd->addr == 0 || bd->tcache_ptr == NULL) {
2875     printf("  killing dead block!? %08x\n", bd->addr);
2876     return bd->tcache_ptr;
2877   }
2878
2879   // since we never reuse space of dead blocks,
2880   // insert jump to dispatcher for blocks that are linked to this point
2881   //emith_jump_at(bd->tcache_ptr, sh2_drc_dispatcher);
2882
2883   // attempt to handle self-modifying blocks by exiting at nearest known PC
2884   tmp = tcache_ptr;
2885   tcache_ptr = bd->tcache_ptr;
2886   emit_move_r_imm32(SHR_PC, bd->addr);
2887   rcache_flush();
2888   emith_jump(sh2_drc_dispatcher);
2889   tcache_ptr = tmp;
2890
2891   bd->addr = 0;
2892   return bd->tcache_ptr;
2893 }
2894
2895 static void sh2_smc_rm_block(u32 a, u16 *drc_ram_blk, int tcache_id, u32 shift, u32 mask)
2896 {
2897   //block_link *bl = block_links[tcache_id];
2898   //int bl_count = block_link_counts[tcache_id];
2899   block_desc *btab = block_tables[tcache_id];
2900   u16 *p = drc_ram_blk + ((a & mask) >> shift);
2901   u16 *pmax = drc_ram_blk + (mask >> shift);
2902   void *tcache_min, *tcache_max;
2903   int zeros;
2904   u16 *pt;
2905
2906   // Figure out what the main block is, as subblocks also have the flag set.
2907   // This relies on sub having single entry. It's possible that innocent
2908   // block might be hit, but that's not such a big deal.
2909   if ((p[0] >> 1) != (p[1] >> 1)) {
2910     for (; p > drc_ram_blk; p--)
2911       if (p[-1] == 0 || (p[-1] >> 1) == (*p >> 1))
2912         break;
2913   }
2914   pt = p;
2915
2916   for (; p > drc_ram_blk; p--)
2917     if ((*p & 1))
2918       break;
2919
2920   if (!(*p & 1)) {
2921     printf("smc rm: missing block start for %08x?\n", a);
2922     p = pt;
2923   }
2924
2925   if (*p == 0)
2926     return;
2927
2928   tcache_min = tcache_max = sh2_smc_rm_block_entry(&btab[*p >> 1], tcache_id);
2929   *p = 0;
2930
2931   for (p++, zeros = 0; p < pmax && zeros < MAX_LITERAL_OFFSET / 2; p++) {
2932     int id = *p >> 1;
2933     if (id == 0) {
2934       // there can be holes because games sometimes keep variables
2935       // directly in literal pool and we don't inline them to avoid recompile
2936       // (Star Wars Arcade)
2937       zeros++;
2938       continue;
2939     }
2940     if (*p & 1) {
2941       if (id == (p[1] >> 1))
2942         // hit other block
2943         break;
2944       tcache_max = sh2_smc_rm_block_entry(&btab[id], tcache_id);
2945     }
2946     *p = 0;
2947   }
2948
2949   host_instructions_updated(tcache_min, (void *)((char *)tcache_max + 4*4 + 4));
2950 }
2951
2952 void sh2_drc_wcheck_ram(unsigned int a, int val, int cpuid)
2953 {
2954   dbg(1, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a);
2955   sh2_smc_rm_block(a, Pico32xMem->drcblk_ram, 0, SH2_DRCBLK_RAM_SHIFT, 0x3ffff);
2956 }
2957
2958 void sh2_drc_wcheck_da(unsigned int a, int val, int cpuid)
2959 {
2960   dbg(1, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a);
2961   sh2_smc_rm_block(a, Pico32xMem->drcblk_da[cpuid],
2962     1 + cpuid, SH2_DRCBLK_DA_SHIFT, 0xfff);
2963 }
2964
2965 void sh2_execute(SH2 *sh2c, int cycles)
2966 {
2967   int ret_cycles;
2968   sh2 = sh2c; // XXX
2969
2970   sh2c->cycles_aim += cycles;
2971   cycles = sh2c->cycles_aim - sh2c->cycles_done;
2972
2973   // cycles are kept in SHR_SR unused bits (upper 20)
2974   // bit19 contains T saved for delay slot
2975   // others are usual SH2 flags
2976   sh2c->sr &= 0x3f3;
2977   sh2c->sr |= cycles << 12;
2978   sh2_drc_entry(sh2c);
2979
2980   // TODO: irq cycles
2981   ret_cycles = (signed int)sh2c->sr >> 12;
2982   if (ret_cycles > 0)
2983     printf("warning: drc returned with cycles: %d\n", ret_cycles);
2984
2985   sh2c->cycles_done += cycles - ret_cycles;
2986 }
2987
2988 #if (DRC_DEBUG & 1)
2989 void block_stats(void)
2990 {
2991   int c, b, i, total = 0;
2992
2993   printf("block stats:\n");
2994   for (b = 0; b < ARRAY_SIZE(block_tables); b++)
2995     for (i = 0; i < block_counts[b]; i++)
2996       if (block_tables[b][i].addr != 0)
2997         total += block_tables[b][i].refcount;
2998
2999   for (c = 0; c < 10; c++) {
3000     block_desc *blk, *maxb = NULL;
3001     int max = 0;
3002     for (b = 0; b < ARRAY_SIZE(block_tables); b++) {
3003       for (i = 0; i < block_counts[b]; i++) {
3004         blk = &block_tables[b][i];
3005         if (blk->addr != 0 && blk->refcount > max) {
3006           max = blk->refcount;
3007           maxb = blk;
3008         }
3009       }
3010     }
3011     if (maxb == NULL)
3012       break;
3013     printf("%08x %9d %2.3f%%\n", maxb->addr, maxb->refcount,
3014       (double)maxb->refcount / total * 100.0);
3015     maxb->refcount = 0;
3016   }
3017
3018   for (b = 0; b < ARRAY_SIZE(block_tables); b++)
3019     for (i = 0; i < block_counts[b]; i++)
3020       block_tables[b][i].refcount = 0;
3021 }
3022 #else
3023 #define block_stats()
3024 #endif
3025
3026 void sh2_drc_flush_all(void)
3027 {
3028   block_stats();
3029   flush_tcache(0);
3030   flush_tcache(1);
3031   flush_tcache(2);
3032 }
3033
3034 void sh2_drc_mem_setup(SH2 *sh2)
3035 {
3036   // fill the convenience pointers
3037   sh2->p_bios = sh2->is_slave ? Pico32xMem->sh2_rom_s : Pico32xMem->sh2_rom_m;
3038   sh2->p_da = Pico32xMem->data_array[sh2->is_slave];
3039   sh2->p_sdram = Pico32xMem->sdram;
3040   sh2->p_rom = Pico.rom;
3041 }
3042
3043 int sh2_drc_init(SH2 *sh2)
3044 {
3045   int i;
3046
3047   if (block_tables[0] == NULL)
3048   {
3049     for (i = 0; i < TCACHE_BUFFERS; i++) {
3050       block_tables[i] = calloc(block_max_counts[i], sizeof(*block_tables[0]));
3051       if (block_tables[i] == NULL)
3052         goto fail;
3053       // max 2 block links (exits) per block
3054       block_links[i] = calloc(block_max_counts[i] * 2, sizeof(*block_links[0]));
3055       if (block_links[i] == NULL)
3056         goto fail;
3057     }
3058     memset(block_counts, 0, sizeof(block_counts));
3059     memset(block_link_counts, 0, sizeof(block_link_counts));
3060
3061     drc_cmn_init();
3062     tcache_ptr = tcache;
3063     sh2_generate_utils();
3064     host_instructions_updated(tcache, tcache_ptr);
3065
3066     tcache_bases[0] = tcache_ptrs[0] = tcache_ptr;
3067     for (i = 1; i < ARRAY_SIZE(tcache_bases); i++)
3068       tcache_bases[i] = tcache_ptrs[i] = tcache_bases[i - 1] + tcache_sizes[i - 1];
3069
3070     // tmp
3071     PicoOpt |= POPT_DIS_VDP_FIFO;
3072
3073 #if (DRC_DEBUG & 2)
3074     for (i = 0; i < ARRAY_SIZE(block_tables); i++)
3075       tcache_dsm_ptrs[i] = tcache_bases[i];
3076     // disasm the utils
3077     tcache_dsm_ptrs[0] = tcache;
3078     do_host_disasm(0);
3079 #endif
3080 #if (DRC_DEBUG & 1)
3081     hash_collisions = 0;
3082 #endif
3083   }
3084
3085   if (hash_table == NULL) {
3086     hash_table = calloc(sizeof(hash_table[0]), MAX_HASH_ENTRIES);
3087     if (hash_table == NULL)
3088       goto fail;
3089   }
3090
3091   return 0;
3092
3093 fail:
3094   sh2_drc_finish(sh2);
3095   return -1;
3096 }
3097
3098 void sh2_drc_finish(SH2 *sh2)
3099 {
3100   int i;
3101
3102   if (block_tables[0] != NULL) {
3103     block_stats();
3104
3105     for (i = 0; i < TCACHE_BUFFERS; i++) {
3106 #if (DRC_DEBUG & 2)
3107       printf("~~~ tcache %d\n", i);
3108       tcache_dsm_ptrs[i] = tcache_bases[i];
3109       tcache_ptr = tcache_ptrs[i];
3110       do_host_disasm(i);
3111 #endif
3112
3113       if (block_tables[i] != NULL)
3114         free(block_tables[i]);
3115       block_tables[i] = NULL;
3116       if (block_links[i] == NULL)
3117         free(block_links[i]);
3118       block_links[i] = NULL;
3119     }
3120
3121     drc_cmn_cleanup();
3122   }
3123
3124   if (hash_table != NULL) {
3125     free(hash_table);
3126     hash_table = NULL;
3127   }
3128 }