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