e925638f777dd3ad0f8887cae178fd627cfe0415
[picodrive.git] / cpu / sh2 / compiler.c
1 /*
2  * SH2 recompiler
3  * (C) notaz, 2009,2010,2013
4  * (C) irixxxx, 2018-2024
5  *
6  * This work is licensed under the terms of MAME license.
7  * See COPYING file in the top-level directory.
8  *
9  * notes:
10  * - tcache, block descriptor, block entry buffer overflows result in oldest
11  *   blocks being deleted until enough space is available
12  * - link and list element buffer overflows result in failure and exit
13  * - jumps between blocks are tracked for SMC handling (in block_entry->links),
14  *   except jumps from global to CPU-local tcaches
15  *
16  * implemented:
17  * - static register allocation
18  * - remaining register caching and tracking in temporaries
19  * - block-local branch linking
20  * - block linking
21  * - some constant propagation
22  * - call stack caching for host block entry address
23  * - delay, poll, and idle loop detection and handling
24  * - some T/M flag optimizations where the value is known or isn't used
25  *
26  * TODO:
27  * - better constant propagation
28  * - bug fixing
29  */
30 #include <stddef.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <assert.h>
34
35 #include <pico/pico_int.h>
36 #include <pico/arm_features.h>
37 #include "sh2.h"
38 #include "compiler.h"
39 #include "../drc/cmn.h"
40 #include "../debug.h"
41
42 // features
43 #define PROPAGATE_CONSTANTS     1
44 #define LINK_BRANCHES           1
45 #define BRANCH_CACHE            1
46 #define CALL_STACK              1
47 #define ALIAS_REGISTERS         1
48 #define REMAP_REGISTER          1
49 #define LOOP_DETECTION          1
50 #define LOOP_OPTIMIZER          1
51 #define T_OPTIMIZER             1
52 #define DIV_OPTIMIZER           1
53
54 #define MAX_LITERAL_OFFSET      0x200   // max. MOVA, MOV @(PC) offset
55 #define MAX_LOCAL_TARGETS       (BLOCK_INSN_LIMIT / 4)
56 #define MAX_LOCAL_BRANCHES      (BLOCK_INSN_LIMIT / 2)
57
58 // debug stuff
59 // 01 - warnings/errors
60 // 02 - block info/smc
61 // 04 - asm
62 // 08 - runtime block entry log
63 // 10 - smc self-check
64 // 20 - runtime block entry counter
65 // 40 - rcache checking
66 // 80 - branch cache statistics
67 // 100 - write trace
68 // 200 - compare trace
69 // 400 - block entry backtrace on exit
70 // 800 - state dump on exit
71 #ifndef DRC_DEBUG
72 #define DRC_DEBUG 0//x847
73 #endif
74
75 #if DRC_DEBUG
76 #define dbg(l,...) { \
77   if ((l) & DRC_DEBUG) \
78     elprintf(EL_STATUS, ##__VA_ARGS__); \
79 }
80 #include "mame/sh2dasm.h"
81 #include <platform/libpicofe/linux/host_dasm.h>
82 static int insns_compiled, hash_collisions, host_insn_count;
83 #define COUNT_OP \
84         host_insn_count++
85 #else // !DRC_DEBUG
86 #define COUNT_OP
87 #define dbg(...)
88 #endif
89
90
91 ///
92 #define FETCH_OP(pc) \
93   dr_pc_base[(pc) / 2]
94
95 #define FETCH32(a) \
96   ((dr_pc_base[(a) / 2] << 16) | dr_pc_base[(a) / 2 + 1])
97
98 #define CHECK_UNHANDLED_BITS(mask, label) { \
99   if ((op & (mask)) != 0) \
100     goto label; \
101 }
102
103 #define GET_Fx() \
104   ((op >> 4) & 0x0f)
105
106 #define GET_Rm GET_Fx
107
108 #define GET_Rn() \
109   ((op >> 8) & 0x0f)
110
111 #define T       0x00000001
112 #define S       0x00000002
113 #define I       0x000000f0
114 #define Q       0x00000100
115 #define M       0x00000200
116 #define T_save  0x00000800
117
118 #define I_SHIFT 4
119 #define Q_SHIFT 8
120 #define M_SHIFT 9
121 #define T_SHIFT 11
122
123 static struct op_data {
124   u8 op;
125   u8 cycles;
126   u8 size;     // 0, 1, 2 - byte, word, long
127   s8 rm;       // branch or load/store data reg
128   u32 source;  // bitmask of src regs
129   u32 dest;    // bitmask of dest regs
130   u32 imm;     // immediate/io address/branch target
131                // (for literal - address, not value)
132 } ops[BLOCK_INSN_LIMIT];
133
134 enum op_types {
135   OP_UNHANDLED = 0,
136   OP_BRANCH,
137   OP_BRANCH_N,  // conditional known not to be taken
138   OP_BRANCH_CT, // conditional, branch if T set
139   OP_BRANCH_CF, // conditional, branch if T clear
140   OP_BRANCH_R,  // indirect
141   OP_BRANCH_RF, // indirect far (PC + Rm)
142   OP_SETCLRT,   // T flag set/clear
143   OP_MOVE,      // register move
144   OP_LOAD_CONST,// load const to register
145   OP_LOAD_POOL, // literal pool load, imm is address
146   OP_MOVA,      // MOVA instruction
147   OP_SLEEP,     // SLEEP instruction
148   OP_RTE,       // RTE instruction
149   OP_TRAPA,     // TRAPA instruction
150   OP_LDC,       // LDC instruction
151   OP_DIV0,      // DIV0[US] instruction
152   OP_UNDEFINED,
153 };
154
155 struct div {
156   u32 state:1;          // 0: expect DIV1/ROTCL, 1: expect DIV1
157   u32 rn:5, rm:5, ro:5; // rn and rm for DIV1, ro for ROTCL
158   u32 div1:8, rotcl:8;  // DIV1 count, ROTCL count
159 };
160 union _div { u32 imm; struct div div; };  // XXX tut-tut type punning...
161 #define div(opd)        ((union _div *)&((opd)->imm))->div
162
163 // XXX consider trap insns: OP_TRAPA, OP_UNDEFINED?
164 #define OP_ISBRANCH(op) ((BITRANGE(OP_BRANCH, OP_BRANCH_RF)| BITMASK1(OP_RTE)) \
165                                 & BITMASK1(op))
166 #define OP_ISBRAUC(op) (BITMASK4(OP_BRANCH, OP_BRANCH_R, OP_BRANCH_RF, OP_RTE) \
167                                 & BITMASK1(op))
168 #define OP_ISBRACND(op) (BITMASK2(OP_BRANCH_CT, OP_BRANCH_CF) \
169                                 & BITMASK1(op))
170 #define OP_ISBRAIMM(op) (BITMASK3(OP_BRANCH, OP_BRANCH_CT, OP_BRANCH_CF) \
171                                 & BITMASK1(op))
172 #define OP_ISBRAIND(op) (BITMASK3(OP_BRANCH_R, OP_BRANCH_RF, OP_RTE) \
173                                 & BITMASK1(op))
174
175 #ifdef DRC_SH2
176
177 #if (DRC_DEBUG & 4)
178 static u8 *tcache_dsm_ptrs[3];
179 static char sh2dasm_buff[64];
180 #define do_host_disasm(tcid) \
181   host_dasm(tcache_dsm_ptrs[tcid], emith_insn_ptr() - tcache_dsm_ptrs[tcid]); \
182   tcache_dsm_ptrs[tcid] = emith_insn_ptr()
183 #else
184 #define do_host_disasm(x)
185 #endif
186
187 #define SH2_DUMP(sh2, reason) { \
188         char ms = (sh2)->is_slave ? 's' : 'm'; \
189         printf("%csh2 %s %08lx\n", ms, reason, (ulong)(sh2)->pc); \
190         printf("%csh2 r0-7  %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", ms, \
191                 (ulong)(sh2)->r[0], (ulong)(sh2)->r[1], (ulong)(sh2)->r[2], (ulong)(sh2)->r[3], \
192                 (ulong)(sh2)->r[4], (ulong)(sh2)->r[5], (ulong)(sh2)->r[6], (ulong)(sh2)->r[7]); \
193         printf("%csh2 r8-15 %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", ms, \
194                 (ulong)(sh2)->r[8], (ulong)(sh2)->r[9], (ulong)(sh2)->r[10], (ulong)(sh2)->r[11], \
195                 (ulong)(sh2)->r[12], (ulong)(sh2)->r[13], (ulong)(sh2)->r[14], (ulong)(sh2)->r[15]); \
196         printf("%csh2 pc-ml %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", ms, \
197                 (ulong)(sh2)->pc, (ulong)(sh2)->ppc, (ulong)(sh2)->pr, (ulong)(sh2)->sr, \
198                 (ulong)(sh2)->gbr, (ulong)(sh2)->vbr, (ulong)(sh2)->mach, (ulong)(sh2)->macl); \
199         printf("%csh2 tmp-p  %08x %08x %08x %08x %08x %08lx %08x %08x\n", ms, \
200                 (sh2)->drc_tmp, (sh2)->irq_cycles, \
201                 (sh2)->pdb_io_csum[0], (sh2)->pdb_io_csum[1], (sh2)->state, \
202                 (ulong)(sh2)->poll_addr, (sh2)->poll_cycles, (sh2)->poll_cnt); \
203 }
204
205 #if (DRC_DEBUG & (256|512|1024))
206 static SH2 csh2[2][8];
207 static FILE *trace[2];
208 static int topen[2];
209 #endif
210 #if (DRC_DEBUG & 8)
211 static u32 lastpc, lastcnt;
212 static void *lastblock;
213 #endif
214 #if (DRC_DEBUG & (8|256|512|1024)) || defined(PDB)
215 static void REGPARM(3) *sh2_drc_log_entry(void *block, SH2 *sh2, u32 sr)
216 {
217   if (block != NULL) {
218 #if defined PDB
219     dbg(8, "= %csh2 enter %08x %p, c=%d", sh2->is_slave?'s':'m',
220       sh2->pc, block, ((signed int)sr >> 12)+1);
221     pdb_step(sh2, sh2->pc);
222 #elif (DRC_DEBUG & 8)
223     if (lastpc != sh2->pc) {
224       if (lastcnt)
225         dbg(8, "= %csh2 enter %08x %p (%d times), c=%d", sh2->is_slave?'s':'m',
226           lastpc, lastblock, lastcnt, (signed int)sr >> 12);
227       dbg(8, "= %csh2 enter %08x %p, c=%d", sh2->is_slave?'s':'m',
228         sh2->pc, block, (signed int)sr >> 12);
229       lastpc = sh2->pc;
230       lastblock = block;
231       lastcnt = 0;
232     } else
233       lastcnt++;
234 #elif (DRC_DEBUG & 256)
235   {
236     static SH2 fsh2;
237     int idx = sh2->is_slave;
238     if (!trace[0] && !topen[0]++) {
239       trace[0] = fopen("pico.trace0", "wb");
240       trace[1] = fopen("pico.trace1", "wb");
241     }
242     if (trace[idx] && csh2[idx][0].pc != sh2->pc) {
243       fwrite(sh2, offsetof(SH2, read8_map), 1, trace[idx]);
244       fwrite(&sh2->pdb_io_csum, sizeof(sh2->pdb_io_csum), 1, trace[idx]);
245       memcpy(&csh2[idx][0], sh2, offsetof(SH2, poll_cnt)+4);
246       csh2[idx][0].is_slave = idx;
247     }
248   }
249 #elif (DRC_DEBUG & 512)
250   {
251     static SH2 fsh2;
252     int idx = sh2->is_slave;
253     if (!trace[0] && !topen[0]++) {
254       trace[0] = fopen("pico.trace0", "rb");
255       trace[1] = fopen("pico.trace1", "rb");
256     }
257     if (trace[idx] && csh2[idx][0].pc != sh2->pc) {
258       if (!fread(&fsh2, offsetof(SH2, read8_map), 1, trace[idx]) ||
259           !fread(&fsh2.pdb_io_csum, sizeof(sh2->pdb_io_csum), 1, trace[idx])) {
260         printf("trace eof at %08lx\n",ftell(trace[idx]));
261         exit(1);
262       }
263       fsh2.sr = (fsh2.sr & 0x3ff) | (sh2->sr & ~0x3ff);
264       fsh2.is_slave = idx;
265       if (memcmp(&fsh2, sh2, offsetof(SH2, read8_map)) ||
266           0)//memcmp(&fsh2.pdb_io_csum, &sh2->pdb_io_csum, sizeof(sh2->pdb_io_csum)))
267       {
268         printf("difference at %08lx!\n",ftell(trace[idx]));
269         SH2_DUMP(&fsh2, "file");
270         SH2_DUMP(sh2, "current");
271         SH2_DUMP(&csh2[idx][0], "previous");
272         SH2_DUMP(&csh2[idx][1], "previous");
273         char *ps = (char *)sh2, *pf = (char *)&fsh2;
274         for (idx = 0; idx < offsetof(SH2, read8_map); idx += sizeof(u32))
275                 if (*(u32 *)(ps+idx) != *(u32 *)(pf+idx))
276                         printf("diff reg %ld\n",(long)idx/sizeof(u32));
277         exit(1);
278       }
279       memcpy(&csh2[idx][1], &csh2[idx][0], offsetof(SH2, poll_cnt)+4);
280       csh2[idx][0] = fsh2;
281     }
282   }
283 #elif (DRC_DEBUG & 1024)
284   {
285     int x = sh2->is_slave, i;
286     for (i = 0; i < ARRAY_SIZE(csh2[x])-1; i++)
287       memcpy(&csh2[x][i], &csh2[x][i+1], offsetof(SH2, poll_cnt)+4);
288     memcpy(&csh2[x][ARRAY_SIZE(csh2[x])-1], sh2, offsetof(SH2, poll_cnt)+4);
289     csh2[x][0].is_slave = x;
290   }
291 #endif
292   }
293   return block;
294 }
295 #endif
296
297
298 // we have 3 translation cache buffers, split from one drc/cmn buffer.
299 // BIOS shares tcache with data array because it's only used for init
300 // and can be discarded early
301 #define TCACHE_BUFFERS 3
302
303
304 struct ring_buffer {
305   u8 *base;                  // ring buffer memory
306   unsigned item_sz;          // size of one buffer item
307   unsigned size;             // number of itmes in ring
308   int first, next;           // read and write pointers
309   int used;                  // number of used items in ring
310 };
311
312 enum { BL_JMP=1, BL_LDJMP, BL_JCCBLX };
313 struct block_link {
314   short tcache_id;
315   short type;                // BL_JMP et al
316   u32 target_pc;
317   void *jump;                // insn address
318   void *blx;                 // block link/exit  area if any
319   u8 jdisp[12];              // jump backup buffer
320   struct block_link *next;   // either in block_entry->links or unresolved
321   struct block_link *o_next; //     ...in block_entry->o_links
322   struct block_link *prev;
323   struct block_link *o_prev;
324   struct block_entry *target;// target block this is linked in (be->links)
325 };
326
327 struct block_entry {
328   u32 pc;
329   u8 *tcache_ptr;            // translated block for above PC
330   struct block_entry *next;  // chain in hash_table with same pc hash
331   struct block_entry *prev;
332   struct block_link *links;  // incoming links to this entry
333   struct block_link *o_links;// outgoing links from this entry
334 #if (DRC_DEBUG & 2)
335   struct block_desc *block;
336 #endif
337 #if (DRC_DEBUG & 32)
338   int entry_count;
339 #endif
340 };
341
342 struct block_desc {
343   u32 addr;                  // block start SH2 PC address
344   u32 addr_lit;              // block start SH2 literal pool addr
345   int size;                  // ..of recompiled insns
346   int size_lit;              // ..of (insns+)literal pool
347   u8 *tcache_ptr;            // start address of block in cache
348   u16 crc;                   // crc of insns and literals
349   u16 active;                // actively used or deactivated?
350   struct block_list *list;
351 #if (DRC_DEBUG & 2)
352   int refcount;
353 #endif
354   int entry_count;
355   struct block_entry *entryp;
356 };
357
358 struct block_list {
359   struct block_desc *block;  // block reference
360   struct block_list *next;   // pointers for doubly linked list
361   struct block_list *prev;
362   struct block_list **head;  // list head (for removing from list)
363   struct block_list *l_next;
364 };
365
366 static u8 *tcache_ptr;       // ptr for code emitters
367
368 // XXX: need to tune sizes
369
370 static struct ring_buffer tcache_ring[TCACHE_BUFFERS];
371 static const int tcache_sizes[TCACHE_BUFFERS] = {
372   DRC_TCACHE_SIZE * 30 / 32, // ROM (rarely used), DRAM
373   DRC_TCACHE_SIZE / 32, // BIOS, data array in master sh2
374   DRC_TCACHE_SIZE / 32, // ... slave
375 };
376
377 #define BLOCK_MAX_COUNT(tcid)           ((tcid) ? 256 : 32*256)
378 static struct ring_buffer block_ring[TCACHE_BUFFERS];
379 static struct block_desc *block_tables[TCACHE_BUFFERS];
380
381 #define ENTRY_MAX_COUNT(tcid)           ((tcid) ? 8*512 : 256*512)
382 static struct ring_buffer entry_ring[TCACHE_BUFFERS];
383 static struct block_entry *entry_tables[TCACHE_BUFFERS];
384
385 // we have block_link_pool to avoid using mallocs
386 #define BLOCK_LINK_MAX_COUNT(tcid)      ((tcid) ? 512 : 32*512)
387 static struct block_link *block_link_pool[TCACHE_BUFFERS]; 
388 static int block_link_pool_counts[TCACHE_BUFFERS];
389 static struct block_link **unresolved_links[TCACHE_BUFFERS];
390 static struct block_link *blink_free[TCACHE_BUFFERS];
391
392 // used for invalidation
393 #define RAM_SIZE(tcid)                  ((tcid) ? 0x1000 : 0x40000)
394 #define INVAL_PAGE_SIZE 0x100
395
396 static struct block_list *inactive_blocks[TCACHE_BUFFERS];
397
398 // array of pointers to block_lists for RAM and 2 data arrays
399 // each array has len: sizeof(mem) / INVAL_PAGE_SIZE 
400 static struct block_list **inval_lookup[TCACHE_BUFFERS];
401
402 #define HASH_TABLE_SIZE(tcid)           ((tcid) ? 512 : 32*512)
403 static struct block_entry **hash_tables[TCACHE_BUFFERS];
404
405 #define HASH_FUNC(hash_tab, addr, mask) \
406   (hash_tab)[((addr) >> 1) & (mask)]
407
408 #define BLOCK_LIST_MAX_COUNT            (64*1024)
409 static struct block_list *block_list_pool; 
410 static int block_list_pool_count;
411 static struct block_list *blist_free;
412
413 #if (DRC_DEBUG & 128)
414 #if BRANCH_CACHE
415 int bchit, bcmiss;
416 #endif
417 #if CALL_STACK
418 int rchit, rcmiss;
419 #endif
420 #endif
421
422 // host register tracking
423 enum cache_reg_htype {
424   HRT_TEMP   = 1, // is for temps and args
425   HRT_REG    = 2, // is for sh2 regs
426 };
427
428 enum cache_reg_flags {
429   HRF_DIRTY  = 1 << 0, // has "dirty" value to be written to ctx
430   HRF_PINNED = 1 << 1, // has a pinned mapping
431   HRF_S16    = 1 << 2, // has a sign extended 16 bit value
432   HRF_U16    = 1 << 3, // has a zero extended 16 bit value
433 };
434
435 enum cache_reg_type {
436   HR_FREE,
437   HR_CACHED, // vreg has sh2_reg_e
438   HR_TEMP,   // reg used for temp storage
439 };
440
441 typedef struct {
442   u8 hreg:6;    // "host" reg
443   u8 htype:2;   // TEMP or REG?
444   u8 flags:4;   // DIRTY, PINNED?
445   u8 type:2;    // CACHED or TEMP?
446   u8 locked:2;  // LOCKED reference counter
447   u16 stamp;    // kind of a timestamp
448   u32 gregs;    // "guest" reg mask
449 } cache_reg_t;
450
451 // guest register tracking
452 enum guest_reg_flags {
453   GRF_DIRTY  = 1 << 0, // reg has "dirty" value to be written to ctx
454   GRF_CONST  = 1 << 1, // reg has a constant
455   GRF_CDIRTY = 1 << 2, // constant not yet written to ctx
456   GRF_STATIC = 1 << 3, // reg has static mapping to vreg
457   GRF_PINNED = 1 << 4, // reg has pinned mapping to vreg
458 };
459
460 typedef struct {
461   u8 flags;     // guest flags: is constant, is dirty?
462   s8 sreg;      // cache reg for static mapping
463   s8 vreg;      // cache_reg this is currently mapped to, -1 if not mapped
464   s8 cnst;      // const index if this is constant
465 } guest_reg_t;
466
467
468 // possibly needed in code emitter
469 static int rcache_get_tmp(void);
470 static void rcache_free_tmp(int hr);
471
472 // Note: Register assignment goes by ABI convention. Caller save registers are
473 // TEMPORARY, callee save registers are PRESERVED. Unusable regs are omitted.
474 // there must be at least the free (not context or statically mapped) amount of
475 // PRESERVED/TEMPORARY registers used by handlers in worst case (currently 4). 
476 // there must be at least 3 PARAM, and PARAM+TEMPORARY must be at least 4.
477 // SR must and R0 should by all means be statically mapped.
478 // XXX the static definition of SR MUST match that in compiler.h
479
480 #if defined(__arm__) || defined(_M_ARM)
481 #include "../drc/emit_arm.c"
482 #elif defined(__aarch64__) || defined(_M_ARM64)
483 #include "../drc/emit_arm64.c"
484 #elif defined(__mips__)
485 #include "../drc/emit_mips.c"
486 #elif defined(__riscv__) || defined(__riscv)
487 #include "../drc/emit_riscv.c"
488 #elif defined(__powerpc__) || defined(__PPC__) || defined(__ppc__) || defined(_M_PPC)
489 #include "../drc/emit_ppc.c"
490 #elif defined(__i386__) || defined(_M_X86)
491 #include "../drc/emit_x86.c"
492 #elif defined(__x86_64__) || defined(_M_X64)
493 #include "../drc/emit_x86.c"
494 #else
495 #error unsupported arch
496 #endif
497
498 static const signed char hregs_param[] = PARAM_REGS;
499 static const signed char hregs_temp [] = TEMPORARY_REGS;
500 static const signed char hregs_saved[] = PRESERVED_REGS;
501 static const signed char regs_static[] = STATIC_SH2_REGS;
502
503 #define CACHE_REGS \
504     (ARRAY_SIZE(hregs_param)+ARRAY_SIZE(hregs_temp)+ARRAY_SIZE(hregs_saved)-1)
505 static cache_reg_t cache_regs[CACHE_REGS];
506
507 static signed char reg_map_host[HOST_REGS];
508
509 static guest_reg_t guest_regs[SH2_REGS];
510
511 // generated functions called from C, to be called only through host_call()
512 static void REGPARM(1) (*sh2_drc_entry)(SH2 *sh2);
513 #ifdef DRC_SR_REG
514 void REGPARM(1) (*sh2_drc_save_sr)(SH2 *sh2);
515 void REGPARM(1) (*sh2_drc_restore_sr)(SH2 *sh2);
516 #endif
517
518 // generated DRC helper functions, only called from generated code via emith_call*()
519 static void REGPARM(1) (*sh2_drc_dispatcher)(u32 pc);
520 #if CALL_STACK
521 static u32  REGPARM(2) (*sh2_drc_dispatcher_call)(u32 pc);
522 static void REGPARM(1) (*sh2_drc_dispatcher_return)(u32 pc);
523 #endif
524 static void REGPARM(1) (*sh2_drc_exit)(u32 pc);
525 static void            (*sh2_drc_test_irq)(void);
526
527 static u32  REGPARM(1) (*sh2_drc_read8)(u32 a);
528 static u32  REGPARM(1) (*sh2_drc_read16)(u32 a);
529 static u32  REGPARM(1) (*sh2_drc_read32)(u32 a);
530 static u32  REGPARM(1) (*sh2_drc_read8_poll)(u32 a);
531 static u32  REGPARM(1) (*sh2_drc_read16_poll)(u32 a);
532 static u32  REGPARM(1) (*sh2_drc_read32_poll)(u32 a);
533 static void REGPARM(2) (*sh2_drc_write8)(u32 a, u32 d);
534 static void REGPARM(2) (*sh2_drc_write16)(u32 a, u32 d);
535 static void REGPARM(2) (*sh2_drc_write32)(u32 a, u32 d);
536
537 // flags for memory access
538 #define MF_SIZEMASK 0x03        // size of access
539 #define MF_POSTINCR 0x10        // post increment (for read_rr)
540 #define MF_PREDECR  MF_POSTINCR // pre decrement (for write_rr)
541 #define MF_POLLING  0x20        // include polling check in read
542
543 // address space stuff
544 static int dr_ctx_get_mem_ptr(SH2 *sh2, u32 a, u32 *mask)
545 {
546   void *memptr;
547   int poffs = -1;
548
549   // check if region is mapped memory
550   memptr = p32x_sh2_get_mem_ptr(a, mask, sh2);
551   if (memptr == NULL)
552     return poffs;
553
554   if (memptr == sh2->p_bios)        // BIOS
555     poffs = offsetof(SH2, p_bios);
556   else if (memptr == sh2->p_da)     // data array
557     poffs = offsetof(SH2, p_da);
558   else if (memptr == sh2->p_sdram)  // SDRAM
559     poffs = offsetof(SH2, p_sdram);
560   else if (memptr == sh2->p_rom)    // ROM
561     poffs = offsetof(SH2, p_rom);
562
563   return poffs;
564 }
565
566 static int dr_get_tcache_id(u32 pc, int is_slave)
567 {
568   u32 tcid = 0;
569  
570   if ((pc & 0xe0000000) == 0xc0000000)
571     tcid = 1 + is_slave; // data array
572   if ((pc & ~0xfff) == 0)
573     tcid = 1 + is_slave; // BIOS
574   return tcid;
575 }
576
577 static struct block_entry *dr_get_entry(u32 pc, int is_slave, int *tcache_id)
578 {
579   struct block_entry *be;
580  
581   *tcache_id = dr_get_tcache_id(pc, is_slave);
582
583   be = HASH_FUNC(hash_tables[*tcache_id], pc, HASH_TABLE_SIZE(*tcache_id) - 1);
584   if (be != NULL) // don't ask... gcc code generation hint
585   for (; be != NULL; be = be->next)
586     if (be->pc == pc)
587       return be;
588
589   return NULL;
590 }
591
592 // ---------------------------------------------------------------
593
594 // ring buffer management
595 #define RING_INIT(r,m,n)    *(r) = (struct ring_buffer) { .base = (u8 *)m, \
596                                         .item_sz = sizeof(*(m)), .size = n };
597
598 static void *ring_alloc(struct ring_buffer *rb, int count)
599 {
600   // allocate space in ring buffer
601   void *p;
602
603   p = rb->base + rb->next * rb->item_sz;
604   if (rb->next+count > rb->size) {
605     rb->used += rb->size - rb->next;
606     p = rb->base; // wrap if overflow at end
607     rb->next = count;
608   } else {
609     rb->next += count;
610     if (rb->next == rb->size) rb->next = 0;
611   }
612
613   rb->used += count;
614   return p;
615 }
616
617 static void ring_wrap(struct ring_buffer *rb)
618 {
619   // insufficient space at end of buffer memory, wrap around
620   rb->used += rb->size - rb->next;
621   rb->next = 0;
622 }
623
624 static void ring_free(struct ring_buffer *rb, int count)
625 {
626   // free oldest space in ring buffer
627   rb->first += count;
628   if (rb->first >= rb->size) rb->first -= rb->size;
629
630   rb->used -= count;
631 }
632
633 static void ring_free_p(struct ring_buffer *rb, void *p)
634 {
635   // free ring buffer space upto given pointer
636   rb->first = ((u8 *)p - rb->base) / rb->item_sz;
637
638   rb->used = rb->next - rb->first;
639   if (rb->used < 0) rb->used += rb->size;
640 }
641
642 static void *ring_reset(struct ring_buffer *rb)
643 {
644   // reset to initial state
645   rb->first = rb->next = rb->used = 0;
646   return rb->base + rb->next * rb->item_sz;
647 }
648
649 static void *ring_first(struct ring_buffer *rb)
650 {
651   return rb->base + rb->first * rb->item_sz;
652 }
653
654 static void *ring_next(struct ring_buffer *rb)
655 {
656   return rb->base + rb->next * rb->item_sz;
657 }
658
659
660 // block management
661 static void add_to_block_list(struct block_list **blist, struct block_desc *block)
662 {
663   struct block_list *added;
664
665   if (blist_free) {
666     added = blist_free;
667     blist_free = added->next;
668   } else if (block_list_pool_count >= BLOCK_LIST_MAX_COUNT) {
669     printf( "block list overflow\n");
670     exit(1);
671   } else {
672     added = block_list_pool + block_list_pool_count;
673     block_list_pool_count ++;
674   }
675
676   added->block = block;
677   added->l_next = block->list;
678   block->list = added;
679   added->head = blist;
680
681   added->prev = NULL;
682   if (*blist)
683     (*blist)->prev = added;
684   added->next = *blist;
685   *blist = added;
686 }
687
688 static void rm_from_block_lists(struct block_desc *block)
689 {
690   struct block_list *entry;
691
692   entry = block->list;
693   while (entry != NULL) {
694     if (entry->prev != NULL)
695       entry->prev->next = entry->next;
696     else
697       *(entry->head) = entry->next;
698     if (entry->next != NULL)
699       entry->next->prev = entry->prev;
700
701     entry->next = blist_free;
702     blist_free = entry;
703
704     entry = entry->l_next;
705   }
706   block->list = NULL;
707 }
708
709 static void discard_block_list(struct block_list **blist)
710 {
711   struct block_list *next, *current = *blist;
712   while (current != NULL) {
713     next = current->next;
714     current->next = blist_free;
715     blist_free = current;
716     current = next;
717   }
718   *blist = NULL;
719 }
720
721 static void add_to_hashlist(struct block_entry *be, int tcache_id)
722 {
723   u32 tcmask = HASH_TABLE_SIZE(tcache_id) - 1;
724   struct block_entry **head = &HASH_FUNC(hash_tables[tcache_id], be->pc, tcmask);
725
726   be->prev = NULL;
727   if (*head)
728     (*head)->prev = be;
729   be->next = *head;
730   *head = be;
731
732 #if (DRC_DEBUG & 2)
733   if (be->next != NULL) {
734     printf(" %08lx@%p: entry hash collision with %08lx@%p\n",
735       (ulong)be->pc, be->tcache_ptr, (ulong)be->next->pc, be->next->tcache_ptr);
736     hash_collisions++;
737   }
738 #endif
739 }
740
741 static void rm_from_hashlist(struct block_entry *be, int tcache_id)
742 {
743   u32 tcmask = HASH_TABLE_SIZE(tcache_id) - 1;
744   struct block_entry **head = &HASH_FUNC(hash_tables[tcache_id], be->pc, tcmask);
745
746 #if DRC_DEBUG & 1
747   struct block_entry *current = be;
748   while (current->prev != NULL)
749     current = current->prev;
750   if (current != *head)
751     dbg(1, "rm_from_hashlist @%p: be %p %08x missing?", head, be, be->pc);
752 #endif
753
754   if (be->prev != NULL)
755     be->prev->next = be->next;
756   else
757     *head = be->next;
758   if (be->next != NULL)
759     be->next->prev = be->prev;
760 }
761
762
763 #if LINK_BRANCHES
764 static void add_to_hashlist_unresolved(struct block_link *bl, int tcache_id)
765 {
766   u32 tcmask = HASH_TABLE_SIZE(tcache_id) - 1;
767   struct block_link **head = &HASH_FUNC(unresolved_links[tcache_id], bl->target_pc, tcmask);
768
769 #if DRC_DEBUG & 1
770   struct block_link *current = *head;
771   while (current != NULL && current != bl)
772     current = current->next;
773   if (current == bl)
774     dbg(1, "add_to_hashlist_unresolved @%p: bl %p %p %08x already in?", head, bl, bl->target, bl->target_pc);
775 #endif
776
777   bl->target = NULL; // marker for not resolved
778   bl->prev = NULL;
779   if (*head)
780     (*head)->prev = bl;
781   bl->next = *head;
782   *head = bl;
783 }
784
785 static void rm_from_hashlist_unresolved(struct block_link *bl, int tcache_id)
786 {
787   u32 tcmask = HASH_TABLE_SIZE(tcache_id) - 1;
788   struct block_link **head = &HASH_FUNC(unresolved_links[tcache_id], bl->target_pc, tcmask);
789
790 #if DRC_DEBUG & 1
791   struct block_link *current = bl;
792   while (current->prev != NULL)
793     current = current->prev;
794   if (current != *head)
795     dbg(1, "rm_from_hashlist_unresolved @%p: bl %p %p %08x missing?", head, bl, bl->target, bl->target_pc);
796 #endif
797
798   if (bl->prev != NULL)
799     bl->prev->next = bl->next;
800   else
801     *head = bl->next;
802   if (bl->next != NULL)
803     bl->next->prev = bl->prev;
804 }
805
806 static void dr_block_link(struct block_entry *be, struct block_link *bl, int emit_jump)
807 {
808   dbg(2, "- %slink from %p to pc %08x entry %p", emit_jump ? "":"early ",
809     bl->jump, bl->target_pc, be->tcache_ptr);
810
811   if (emit_jump) {
812     u8 *jump = bl->jump;
813     int jsz = emith_jump_patch_size();
814     if (bl->type == BL_JMP) { // patch: jump @entry
815       // inlined: @jump far jump to target
816       emith_jump_patch(jump, be->tcache_ptr, &jump);
817     } else if (bl->type == BL_LDJMP) { // write: jump @entry
818       // inlined: @jump far jump to target
819       emith_jump_at(jump, be->tcache_ptr);
820       jsz = emith_jump_at_size();
821     } else if (bl->type == BL_JCCBLX) { // patch: jump cond -> jump @entry
822       if (emith_jump_patch_inrange(bl->jump, be->tcache_ptr)) {
823         // inlined: @jump near jumpcc to target
824         emith_jump_patch(jump, be->tcache_ptr, &jump);
825       } else { // dispatcher cond immediate
826         // via blx: @jump near jumpcc to blx; @blx far jump
827         emith_jump_patch(jump, bl->blx, &jump);
828         emith_jump_at(bl->blx, be->tcache_ptr);
829         host_instructions_updated(bl->blx, (char *)bl->blx + emith_jump_at_size(),
830             ((uintptr_t)bl->blx & 0x1f) + emith_jump_at_size()-1 > 0x1f);
831       }
832     } else {
833       printf("unknown BL type %d\n", bl->type);
834       exit(1);
835     }
836     host_instructions_updated(jump, jump + jsz, ((uintptr_t)jump & 0x1f) + jsz-1 > 0x1f);
837   }
838
839   // move bl to block_entry
840   bl->target = be;
841   bl->prev = NULL;
842   if (be->links)
843     be->links->prev = bl;
844   bl->next = be->links;
845   be->links = bl;
846 }
847
848 static void dr_block_unlink(struct block_link *bl, int emit_jump)
849 {
850   dbg(2,"- unlink from %p to pc %08x", bl->jump, bl->target_pc);
851
852   if (bl->target) {
853     if (emit_jump) {
854       u8 *jump = bl->jump;
855       int jsz = emith_jump_patch_size();
856       if (bl->type == BL_JMP) { // jump_patch @dispatcher
857         // inlined: @jump far jump to dispatcher
858         emith_jump_patch(jump, sh2_drc_dispatcher, &jump);
859       } else if (bl->type == BL_LDJMP) { // restore: load pc, jump @dispatcher
860         // inlined: @jump load target_pc, far jump to dispatcher
861         memcpy(jump, bl->jdisp, emith_jump_at_size());
862         jsz = emith_jump_at_size();
863       } else if (bl->type == BL_JCCBLX) { // jump cond @blx; @blx: load pc, jump
864         // via blx: @jump near jumpcc to blx; @blx load target_pc, far jump
865         emith_jump_patch(bl->jump, bl->blx, &jump);
866         memcpy(bl->blx, bl->jdisp, emith_jump_at_size());
867         host_instructions_updated(bl->blx, (char *)bl->blx + emith_jump_at_size(), 1);
868       } else {
869         printf("unknown BL type %d\n", bl->type);
870         exit(1);
871       }
872       // update cpu caches since the previous jump target doesn't exist anymore
873       host_instructions_updated(jump, jump + jsz, 1);
874     }
875
876     if (bl->prev)
877       bl->prev->next = bl->next;
878     else
879       bl->target->links = bl->next;
880     if (bl->next)
881       bl->next->prev = bl->prev;
882     bl->target = NULL;
883   }
884 }
885 #endif
886
887 static struct block_link *dr_prepare_ext_branch(struct block_entry *owner, u32 pc, int is_slave, int tcache_id)
888 {
889 #if LINK_BRANCHES
890   struct block_link *bl = block_link_pool[tcache_id];
891   int cnt = block_link_pool_counts[tcache_id];
892   int target_tcache_id;
893
894   // get the target block entry
895   target_tcache_id = dr_get_tcache_id(pc, is_slave);
896   if (target_tcache_id && target_tcache_id != tcache_id)
897     return NULL;
898
899   // get a block link
900   if (blink_free[tcache_id] != NULL) {
901     bl = blink_free[tcache_id];
902     blink_free[tcache_id] = bl->next;
903   } else if (cnt >= BLOCK_LINK_MAX_COUNT(tcache_id)) {
904     dbg(1, "bl overflow for tcache %d", tcache_id);
905     return NULL;
906   } else {
907     bl += cnt;
908     block_link_pool_counts[tcache_id] = cnt+1;
909   }
910
911   // prepare link and add to outgoing list of owner
912   bl->tcache_id = tcache_id;
913   bl->target_pc = pc;
914   bl->jump = tcache_ptr;
915   bl->blx = NULL;
916   bl->o_next = owner->o_links;
917   owner->o_links = bl;
918
919   add_to_hashlist_unresolved(bl, tcache_id);
920   return bl;
921 #else
922   return NULL;
923 #endif
924 }
925
926 static void dr_mark_memory(int mark, struct block_desc *block, int tcache_id, u32 nolit)
927 {
928   u8 *drc_ram_blk = NULL, *lit_ram_blk = NULL;
929   u32 addr, end, mask = 0, shift = 0, idx;
930
931   // mark memory blocks as containing compiled code
932   if ((block->addr & 0xc7fc0000) == 0x06000000
933       || (block->addr & 0xfffff000) == 0xc0000000)
934   {
935     if (tcache_id != 0) {
936       // data array
937       drc_ram_blk = Pico32xMem->drcblk_da[tcache_id-1];
938       lit_ram_blk = Pico32xMem->drclit_da[tcache_id-1];
939       shift = SH2_DRCBLK_DA_SHIFT;
940     }
941     else {
942       // SDRAM
943       drc_ram_blk = Pico32xMem->drcblk_ram;
944       lit_ram_blk = Pico32xMem->drclit_ram;
945       shift = SH2_DRCBLK_RAM_SHIFT;
946     }
947     mask = RAM_SIZE(tcache_id) - 1;
948
949     // mark recompiled insns
950     addr = block->addr & ~((1 << shift) - 1);
951     end = block->addr + block->size;
952     for (idx = (addr & mask) >> shift; addr < end; addr += (1 << shift))
953       drc_ram_blk[idx++] += mark;
954
955     // mark literal pool
956     if (addr < (block->addr_lit & ~((1 << shift) - 1)))
957       addr = block->addr_lit & ~((1 << shift) - 1);
958     end = block->addr_lit + block->size_lit;
959     for (idx = (addr & mask) >> shift; addr < end; addr += (1 << shift))
960       drc_ram_blk[idx++] += mark;
961
962     // mark for literals disabled
963     if (nolit) {
964       addr = nolit & ~((1 << shift) - 1);
965       end = block->addr_lit + block->size_lit;
966       for (idx = (addr & mask) >> shift; addr < end; addr += (1 << shift))
967         lit_ram_blk[idx++] = 1;
968     }
969
970     if (mark < 0)
971       rm_from_block_lists(block);
972     else {
973       // add to invalidation lookup lists
974       addr = block->addr & ~(INVAL_PAGE_SIZE - 1);
975       end = block->addr + block->size;
976       for (idx = (addr & mask) / INVAL_PAGE_SIZE; addr < end; addr += INVAL_PAGE_SIZE)
977         add_to_block_list(&inval_lookup[tcache_id][idx++], block);
978
979       if (addr < (block->addr_lit & ~(INVAL_PAGE_SIZE - 1)))
980         addr = block->addr_lit & ~(INVAL_PAGE_SIZE - 1);
981       end = block->addr_lit + block->size_lit;
982       for (idx = (addr & mask) / INVAL_PAGE_SIZE; addr < end; addr += INVAL_PAGE_SIZE)
983         add_to_block_list(&inval_lookup[tcache_id][idx++], block);
984     }
985   }
986 }
987
988 static u32 dr_check_nolit(u32 start, u32 end, int tcache_id)
989 {
990   u8 *lit_ram_blk = NULL;
991   u32 mask = 0, shift = 0, addr, idx;
992
993   if ((start & 0xc7fc0000) == 0x06000000
994       || (start & 0xfffff000) == 0xc0000000)
995   {
996     if (tcache_id != 0) {
997       // data array
998       lit_ram_blk = Pico32xMem->drclit_da[tcache_id-1];
999       shift = SH2_DRCBLK_DA_SHIFT;
1000     }
1001     else {
1002       // SDRAM
1003       lit_ram_blk = Pico32xMem->drclit_ram;
1004       shift = SH2_DRCBLK_RAM_SHIFT;
1005     }
1006     mask = RAM_SIZE(tcache_id) - 1;
1007
1008     addr = start & ~((1 << shift) - 1);
1009     for (idx = (addr & mask) >> shift; addr < end; addr += (1 << shift))
1010       if (lit_ram_blk[idx++])
1011         break;
1012
1013     return (addr < start ? start : addr > end ? end : addr);
1014   }
1015
1016   return end;
1017 }
1018
1019 static void dr_rm_block_entry(struct block_desc *bd, int tcache_id, u32 nolit, int free)
1020 {
1021   struct block_link *bl;
1022   u32 i;
1023
1024   free = free || nolit; // block is invalid if literals are overwritten
1025   dbg(2,"  %sing block %08x-%08x,%08x-%08x, blkid %d,%d", free?"delet":"disabl",
1026     bd->addr, bd->addr + bd->size, bd->addr_lit, bd->addr_lit + bd->size_lit,
1027     tcache_id, bd - block_tables[tcache_id]);
1028   if (bd->addr == 0 || bd->entry_count == 0) {
1029     dbg(1, "  killing dead block!? %08x", bd->addr);
1030     return;
1031   }
1032
1033   // remove from hash table, make incoming links unresolved
1034   if (bd->active) {
1035     for (i = 0; i < bd->entry_count; i++) {
1036       rm_from_hashlist(&bd->entryp[i], tcache_id);
1037
1038 #if LINK_BRANCHES
1039       while ((bl = bd->entryp[i].links) != NULL) {
1040         dr_block_unlink(bl, 1);
1041         add_to_hashlist_unresolved(bl, tcache_id);
1042       }
1043 #endif
1044     }
1045
1046     dr_mark_memory(-1, bd, tcache_id, nolit);
1047     add_to_block_list(&inactive_blocks[tcache_id], bd);
1048   }
1049   bd->active = 0;
1050
1051   if (free) {
1052 #if LINK_BRANCHES
1053     // revoke outgoing links
1054     for (bl = bd->entryp[0].o_links; bl != NULL; bl = bl->o_next) {
1055       if (bl->target)
1056         dr_block_unlink(bl, 0);
1057       else
1058         rm_from_hashlist_unresolved(bl, tcache_id);
1059       bl->jump = NULL;
1060       bl->next = blink_free[bl->tcache_id];
1061       blink_free[bl->tcache_id] = bl;
1062     }
1063     bd->entryp[0].o_links = NULL;
1064 #endif
1065     // invalidate block
1066     rm_from_block_lists(bd);
1067     bd->addr = bd->size = bd->addr_lit = bd->size_lit = 0;
1068     bd->entry_count = 0;
1069   }
1070   emith_update_cache();
1071 }
1072
1073 static struct block_desc *dr_find_inactive_block(int tcache_id, u16 crc,
1074   u32 addr, int size, u32 addr_lit, int size_lit)
1075 {
1076   struct block_list **head = &inactive_blocks[tcache_id];
1077   struct block_list *current;
1078
1079   for (current = *head; current != NULL; current = current->next) {
1080     struct block_desc *block = current->block;
1081     if (block->crc == crc && block->addr == addr && block->size == size &&
1082         block->addr_lit == addr_lit && block->size_lit == size_lit)
1083     {
1084       rm_from_block_lists(block);
1085       return block;
1086     }
1087   }
1088   return NULL;
1089 }
1090
1091 static struct block_desc *dr_add_block(int entries, u32 addr, int size,
1092   u32 addr_lit, int size_lit, u16 crc, int is_slave, int *blk_id)
1093 {
1094   struct block_entry *be;
1095   struct block_desc *bd;
1096   int tcache_id;
1097
1098   // do a lookup to get tcache_id and override check
1099   be = dr_get_entry(addr, is_slave, &tcache_id);
1100   if (be != NULL)
1101     dbg(1, "block override for %08x", addr);
1102
1103   if (block_ring[tcache_id].used + 1 > block_ring[tcache_id].size ||
1104       entry_ring[tcache_id].used + entries > entry_ring[tcache_id].size) {
1105     dbg(1, "bd overflow for tcache %d", tcache_id);
1106     return NULL;
1107   }
1108
1109   *blk_id = block_ring[tcache_id].next;
1110   bd = ring_alloc(&block_ring[tcache_id], 1);
1111   bd->entryp = ring_alloc(&entry_ring[tcache_id], entries);
1112
1113   bd->addr = addr;
1114   bd->size = size;
1115   bd->addr_lit = addr_lit;
1116   bd->size_lit = size_lit;
1117   bd->tcache_ptr = tcache_ptr;
1118   bd->crc = crc;
1119   bd->active = 0;
1120   bd->list = NULL;
1121   bd->entry_count = 0;
1122 #if (DRC_DEBUG & 2)
1123   bd->refcount = 0;
1124 #endif
1125
1126   return bd;
1127 }
1128
1129 static void dr_link_blocks(struct block_entry *be, int tcache_id)
1130 {
1131 #if LINK_BRANCHES
1132   u32 tcmask = HASH_TABLE_SIZE(tcache_id) - 1;
1133   u32 pc = be->pc;
1134   struct block_link **head = &HASH_FUNC(unresolved_links[tcache_id], pc, tcmask);
1135   struct block_link *bl = *head, *next;
1136
1137   while (bl != NULL) {
1138     next = bl->next;
1139     if (bl->target_pc == pc && (!bl->tcache_id || bl->tcache_id == tcache_id)) {
1140       rm_from_hashlist_unresolved(bl, bl->tcache_id);
1141       dr_block_link(be, bl, 1);
1142     }
1143     bl = next;
1144   }
1145 #endif
1146 }
1147
1148 static void dr_link_outgoing(struct block_entry *be, int tcache_id, int is_slave)
1149 {
1150 #if LINK_BRANCHES
1151   struct block_link *bl;
1152   int target_tcache_id;
1153
1154   for (bl = be->o_links; bl; bl = bl->o_next) {
1155     if (bl->target == NULL) {
1156       be = dr_get_entry(bl->target_pc, is_slave, &target_tcache_id);
1157       if (be != NULL && (!target_tcache_id || target_tcache_id == tcache_id)) {
1158         // remove bl from unresolved_links (must've been since target was NULL)
1159         rm_from_hashlist_unresolved(bl, bl->tcache_id);
1160         dr_block_link(be, bl, 1);
1161       }
1162     }
1163   }
1164 #endif
1165 }
1166
1167 static void dr_activate_block(struct block_desc *bd, int tcache_id, int is_slave)
1168 {
1169   int i;
1170
1171   // connect branches
1172   for (i = 0; i < bd->entry_count; i++) {
1173     struct block_entry *entry = &bd->entryp[i];
1174     add_to_hashlist(entry, tcache_id);
1175     // incoming branches
1176     dr_link_blocks(entry, tcache_id);
1177     if (!tcache_id)
1178       dr_link_blocks(entry, is_slave?2:1);
1179     // outgoing branches
1180     dr_link_outgoing(entry, tcache_id, is_slave);
1181   }
1182
1183   // mark memory for overwrite detection
1184   dr_mark_memory(1, bd, tcache_id, 0);
1185   bd->active = 1;
1186 }
1187
1188 static void REGPARM(3) *dr_lookup_block(u32 pc, SH2 *sh2, int *tcache_id)
1189 {
1190   struct block_entry *be = NULL;
1191   void *block = NULL;
1192
1193   be = dr_get_entry(pc, sh2->is_slave, tcache_id);
1194   if (be != NULL)
1195     block = be->tcache_ptr;
1196
1197 #if (DRC_DEBUG & 2)
1198   if (be != NULL)
1199     be->block->refcount++;
1200 #endif
1201   return block;
1202 }
1203
1204 static void dr_free_oldest_block(int tcache_id)
1205 {
1206   struct block_desc *bf;
1207
1208   bf = ring_first(&block_ring[tcache_id]);
1209   if (bf->addr && bf->entry_count)
1210     dr_rm_block_entry(bf, tcache_id, 0, 1);
1211   ring_free(&block_ring[tcache_id], 1);
1212
1213   if (block_ring[tcache_id].used) {
1214     bf = ring_first(&block_ring[tcache_id]);
1215     ring_free_p(&entry_ring[tcache_id], bf->entryp);
1216     ring_free_p(&tcache_ring[tcache_id], bf->tcache_ptr);
1217   } else {
1218     // reset since size of code block isn't known if no successor block exists
1219     ring_reset(&block_ring[tcache_id]);
1220     ring_reset(&entry_ring[tcache_id]);
1221     ring_reset(&tcache_ring[tcache_id]);
1222   }
1223 }
1224
1225 static inline void dr_reserve_cache(int tcache_id, struct ring_buffer *rb, int count)
1226 {
1227   // while not enough space available
1228   if (rb->next + count >= rb->size){
1229     // not enough space in rest of buffer -> wrap around
1230     while (rb->first >= rb->next && rb->used)
1231       dr_free_oldest_block(tcache_id);
1232     if (rb->first == 0 && rb->used)
1233       dr_free_oldest_block(tcache_id);
1234     ring_wrap(rb);
1235   }
1236   while (rb->first >= rb->next && rb->next + count > rb->first && rb->used)
1237     dr_free_oldest_block(tcache_id);
1238 }
1239
1240 static u8 *dr_prepare_cache(int tcache_id, int insn_count, int entry_count)
1241 {
1242   int bf = block_ring[tcache_id].first;
1243
1244   // reserve one block desc
1245   if (block_ring[tcache_id].used >= block_ring[tcache_id].size)
1246     dr_free_oldest_block(tcache_id);
1247   // reserve block entries
1248   dr_reserve_cache(tcache_id, &entry_ring[tcache_id], entry_count);
1249   // reserve cache space
1250   dr_reserve_cache(tcache_id, &tcache_ring[tcache_id], insn_count*128);
1251
1252   if (bf != block_ring[tcache_id].first) {
1253     // deleted some block(s), clear branch cache and return stack
1254 #if BRANCH_CACHE
1255     if (tcache_id)
1256       memset32(sh2s[tcache_id-1].branch_cache, -1, sizeof(sh2s[0].branch_cache)/4);
1257     else {
1258       memset32(sh2s[0].branch_cache, -1, sizeof(sh2s[0].branch_cache)/4);
1259       memset32(sh2s[1].branch_cache, -1, sizeof(sh2s[1].branch_cache)/4);
1260     }
1261 #endif
1262 #if CALL_STACK
1263     if (tcache_id) {
1264       memset32(sh2s[tcache_id-1].rts_cache, -1, sizeof(sh2s[0].rts_cache)/4);
1265       sh2s[tcache_id-1].rts_cache_idx = 0;
1266     } else {
1267       memset32(sh2s[0].rts_cache, -1, sizeof(sh2s[0].rts_cache)/4);
1268       memset32(sh2s[1].rts_cache, -1, sizeof(sh2s[1].rts_cache)/4);
1269       sh2s[0].rts_cache_idx = sh2s[1].rts_cache_idx = 0;
1270     }
1271 #endif
1272   }
1273
1274   return ring_next(&tcache_ring[tcache_id]);
1275 }
1276
1277 static void dr_flush_tcache(int tcid)
1278 {
1279   int i;
1280 #if (DRC_DEBUG & 1)
1281   elprintf(EL_STATUS, "tcache #%d flush! (%d/%d, bds %d/%d bes %d/%d)", tcid,
1282     tcache_ring[tcid].used, tcache_ring[tcid].size, block_ring[tcid].used,
1283     block_ring[tcid].size, entry_ring[tcid].used, entry_ring[tcid].size);
1284 #endif
1285
1286   ring_reset(&tcache_ring[tcid]);
1287   ring_reset(&block_ring[tcid]);
1288   ring_reset(&entry_ring[tcid]);
1289
1290   block_link_pool_counts[tcid] = 0;
1291   blink_free[tcid] = NULL;
1292   memset(unresolved_links[tcid], 0, sizeof(*unresolved_links[0]) * HASH_TABLE_SIZE(tcid));
1293   memset(hash_tables[tcid], 0, sizeof(*hash_tables[0]) * HASH_TABLE_SIZE(tcid));
1294
1295   if (tcid == 0) { // ROM, RAM
1296     memset(Pico32xMem->drcblk_ram, 0, sizeof(Pico32xMem->drcblk_ram));
1297     memset(Pico32xMem->drclit_ram, 0, sizeof(Pico32xMem->drclit_ram));
1298     memset(sh2s[0].branch_cache, -1, sizeof(sh2s[0].branch_cache));
1299     memset(sh2s[1].branch_cache, -1, sizeof(sh2s[1].branch_cache));
1300     memset(sh2s[0].rts_cache, -1, sizeof(sh2s[0].rts_cache));
1301     memset(sh2s[1].rts_cache, -1, sizeof(sh2s[1].rts_cache));
1302     sh2s[0].rts_cache_idx = sh2s[1].rts_cache_idx = 0;
1303   } else {
1304     memset(Pico32xMem->drcblk_ram, 0, sizeof(Pico32xMem->drcblk_ram));
1305     memset(Pico32xMem->drclit_ram, 0, sizeof(Pico32xMem->drclit_ram));
1306     memset(Pico32xMem->drcblk_da[tcid - 1], 0, sizeof(Pico32xMem->drcblk_da[tcid - 1]));
1307     memset(Pico32xMem->drclit_da[tcid - 1], 0, sizeof(Pico32xMem->drclit_da[tcid - 1]));
1308     memset(sh2s[tcid - 1].branch_cache, -1, sizeof(sh2s[0].branch_cache));
1309     memset(sh2s[tcid - 1].rts_cache, -1, sizeof(sh2s[0].rts_cache));
1310     sh2s[tcid - 1].rts_cache_idx = 0;
1311   }
1312 #if (DRC_DEBUG & 4)
1313   tcache_dsm_ptrs[tcid] = tcache_ring[tcid].base;
1314 #endif
1315
1316   for (i = 0; i < RAM_SIZE(tcid) / INVAL_PAGE_SIZE; i++)
1317     discard_block_list(&inval_lookup[tcid][i]);
1318   discard_block_list(&inactive_blocks[tcid]);
1319 }
1320
1321 static void *dr_failure(void)
1322 {
1323   printf("recompilation failed\n");
1324   exit(1);
1325 }
1326
1327 // ---------------------------------------------------------------
1328
1329 // NB rcache allocation dependencies:
1330 // - get_reg_arg/get_tmp_arg first (might evict other regs just allocated)
1331 // - get_reg(..., NULL) before get_reg(..., &hr) if it might get the same reg
1332 // - get_reg(..., RC_GR_READ/RMW, ...) before WRITE (might evict needed reg)
1333
1334 // register cache / constant propagation stuff
1335 typedef enum {
1336   RC_GR_READ,
1337   RC_GR_WRITE,
1338   RC_GR_RMW,
1339 } rc_gr_mode;
1340
1341 typedef struct {
1342   u32 gregs;
1343   u32 val;
1344 } gconst_t;
1345
1346 gconst_t gconsts[ARRAY_SIZE(guest_regs)];
1347
1348 static int rcache_get_reg_(sh2_reg_e r, rc_gr_mode mode, int do_locking, int *hr);
1349 static inline int rcache_is_cached(sh2_reg_e r);
1350 static void rcache_add_vreg_alias(int x, sh2_reg_e r);
1351 static void rcache_remove_vreg_alias(int x, sh2_reg_e r);
1352 static void rcache_evict_vreg(int x);
1353 static void rcache_remap_vreg(int x);
1354 static int rcache_get_reg(sh2_reg_e r, rc_gr_mode mode, int *hr);
1355
1356 static void rcache_set_x16(int hr, int s16_, int u16_)
1357 {
1358   int x = reg_map_host[hr];
1359   if (x >= 0) {
1360     cache_regs[x].flags &= ~(HRF_S16|HRF_U16);
1361     if (s16_) cache_regs[x].flags |= HRF_S16;
1362     if (u16_) cache_regs[x].flags |= HRF_U16;
1363   }
1364 }
1365
1366 static void rcache_copy_x16(int hr, int hr2)
1367 {
1368   int x = reg_map_host[hr], y = reg_map_host[hr2];
1369   if (x >= 0 && y >= 0) {
1370     cache_regs[x].flags = (cache_regs[x].flags & ~(HRF_S16|HRF_U16)) |
1371                           (cache_regs[y].flags &  (HRF_S16|HRF_U16));
1372   }
1373 }
1374
1375 static int rcache_is_s16(int hr)
1376 {
1377   int x = reg_map_host[hr];
1378   return (x >= 0 ? cache_regs[x].flags & HRF_S16 : 0);
1379 }
1380
1381 static int rcache_is_u16(int hr)
1382 {
1383   int x = reg_map_host[hr];
1384   return (x >= 0 ? cache_regs[x].flags & HRF_U16 : 0);
1385 }
1386
1387 #define RCACHE_DUMP(msg) { \
1388   cache_reg_t *cp; \
1389   guest_reg_t *gp; \
1390   int i; \
1391   printf("cache dump %s:\n",msg); \
1392   printf(" cache_regs:\n"); \
1393   for (i = 0; i < ARRAY_SIZE(cache_regs); i++) { \
1394     cp = &cache_regs[i]; \
1395     if (cp->type != HR_FREE || cp->gregs || cp->locked || cp->flags) \
1396       printf("  %d: hr=%d t=%d f=%x c=%d m=%lx\n", i, cp->hreg, cp->type, cp->flags, cp->locked, (ulong)cp->gregs); \
1397   } \
1398   printf(" guest_regs:\n"); \
1399   for (i = 0; i < ARRAY_SIZE(guest_regs); i++) { \
1400     gp = &guest_regs[i]; \
1401     if (gp->vreg != -1 || gp->sreg >= 0 || gp->flags) \
1402       printf("  %d: v=%d f=%x s=%d c=%d\n", i, gp->vreg, gp->flags, gp->sreg, gp->cnst); \
1403   } \
1404   printf(" gconsts:\n"); \
1405   for (i = 0; i < ARRAY_SIZE(gconsts); i++) { \
1406     if (gconsts[i].gregs) \
1407       printf("  %d: m=%lx v=%lx\n", i, (ulong)gconsts[i].gregs, (ulong)gconsts[i].val); \
1408   } \
1409 }
1410
1411 #define RCACHE_CHECK(msg) { \
1412   cache_reg_t *cp; \
1413   guest_reg_t *gp; \
1414   int i, x, m = 0, d = 0; \
1415   for (i = 0; i < ARRAY_SIZE(cache_regs); i++) { \
1416     cp = &cache_regs[i]; \
1417     if (cp->flags & HRF_PINNED) m |= (1 << i); \
1418     if (cp->type == HR_FREE || cp->type == HR_TEMP) continue; \
1419     /* check connectivity greg->vreg */ \
1420     FOR_ALL_BITS_SET_DO(cp->gregs, x, \
1421       if (guest_regs[x].vreg != i) \
1422         { d = 1; printf("cache check v=%d r=%d not connected?\n",i,x); } \
1423     ) \
1424   } \
1425   for (i = 0; i < ARRAY_SIZE(guest_regs); i++) { \
1426     gp = &guest_regs[i]; \
1427     if (gp->vreg != -1 && !(cache_regs[gp->vreg].gregs & (1 << i))) \
1428       { d = 1; printf("cache check r=%d v=%d not connected?\n", i, gp->vreg); }\
1429     if (gp->vreg != -1 && cache_regs[gp->vreg].type != HR_CACHED) \
1430       { d = 1; printf("cache check r=%d v=%d wrong type?\n", i, gp->vreg); }\
1431     if ((gp->flags & GRF_CONST) && !(gconsts[gp->cnst].gregs & (1 << i))) \
1432       { d = 1; printf("cache check r=%d c=%d not connected?\n", i, gp->cnst); }\
1433     if ((gp->flags & GRF_CDIRTY) && (gp->vreg != -1 || !(gp->flags & GRF_CONST)))\
1434       { d = 1; printf("cache check r=%d CDIRTY?\n", i); } \
1435     if (gp->flags & (GRF_STATIC|GRF_PINNED)) { \
1436       if (gp->sreg == -1 || !(cache_regs[gp->sreg].flags & HRF_PINNED))\
1437         { d = 1; printf("cache check r=%d v=%d not pinned?\n", i, gp->vreg); } \
1438       else m &= ~(1 << gp->sreg); \
1439     } \
1440   } \
1441   for (i = 0; i < ARRAY_SIZE(gconsts); i++) { \
1442     FOR_ALL_BITS_SET_DO(gconsts[i].gregs, x, \
1443       if (guest_regs[x].cnst != i || !(guest_regs[x].flags & GRF_CONST)) \
1444         { d = 1; printf("cache check c=%d v=%d not connected?\n",i,x); } \
1445     ) \
1446   } \
1447   if (m) \
1448     { d = 1; printf("cache check m=%x pinning wrong?\n",m); } \
1449   if (d) RCACHE_DUMP(msg) \
1450 /*  else { \
1451     printf("locked regs %s:\n",msg); \
1452     for (i = 0; i < ARRAY_SIZE(cache_regs); i++) { \
1453       cp = &cache_regs[i]; \
1454       if (cp->locked) \
1455         printf("  %d: hr=%d t=%d f=%x c=%d m=%x\n", i, cp->hreg, cp->type, cp->flags, cp->locked, cp->gregs); \
1456     } \
1457   } */ \
1458 }
1459
1460 static inline int gconst_alloc(sh2_reg_e r)
1461 {
1462   int i, n = -1;
1463
1464   for (i = 0; i < ARRAY_SIZE(gconsts); i++) {
1465     gconsts[i].gregs &= ~(1 << r);
1466     if (gconsts[i].gregs == 0 && n < 0)
1467       n = i;
1468   }
1469   if (n >= 0)
1470     gconsts[n].gregs = (1 << r);
1471   else {
1472     printf("all gconst buffers in use, aborting\n");
1473     exit(1); // cannot happen - more constants than guest regs?
1474   }
1475   return n;
1476 }
1477
1478 static void gconst_set(sh2_reg_e r, u32 val)
1479 {
1480   int i = gconst_alloc(r);
1481
1482   guest_regs[r].flags |= GRF_CONST;
1483   guest_regs[r].cnst = i;
1484   gconsts[i].val = val;
1485 }
1486
1487 static void gconst_new(sh2_reg_e r, u32 val)
1488 {
1489   gconst_set(r, val);
1490   guest_regs[r].flags |= GRF_CDIRTY;
1491
1492   // throw away old r that we might have cached
1493   if (guest_regs[r].vreg >= 0)
1494     rcache_remove_vreg_alias(guest_regs[r].vreg, r);
1495 }
1496
1497 static int gconst_get(sh2_reg_e r, u32 *val)
1498 {
1499   if (guest_regs[r].flags & GRF_CONST) {
1500     *val = gconsts[guest_regs[r].cnst].val;
1501     return 1;
1502   }
1503   *val = 0;
1504   return 0;
1505 }
1506
1507 static int gconst_check(sh2_reg_e r)
1508 {
1509   if (guest_regs[r].flags & (GRF_CONST|GRF_CDIRTY))
1510     return 1;
1511   return 0;
1512 }
1513
1514 // update hr if dirty, else do nothing
1515 static int gconst_try_read(int vreg, sh2_reg_e r)
1516 {
1517   int i, x;
1518   u32 v;
1519
1520   if (guest_regs[r].flags & GRF_CDIRTY) {
1521     x = guest_regs[r].cnst;
1522     v = gconsts[x].val;
1523     emith_move_r_imm(cache_regs[vreg].hreg, v);
1524     rcache_set_x16(cache_regs[vreg].hreg, v == (s16)v, v == (u16)v);
1525     FOR_ALL_BITS_SET_DO(gconsts[x].gregs, i,
1526       {
1527         if (guest_regs[i].vreg >= 0 && guest_regs[i].vreg != vreg)
1528           rcache_remove_vreg_alias(guest_regs[i].vreg, i);
1529         if (guest_regs[i].vreg < 0)
1530           rcache_add_vreg_alias(vreg, i);
1531         guest_regs[i].flags &= ~GRF_CDIRTY;
1532         guest_regs[i].flags |= GRF_DIRTY;
1533       });
1534     cache_regs[vreg].type = HR_CACHED;
1535     cache_regs[vreg].flags |= HRF_DIRTY;
1536     return 1;
1537   }
1538   return 0;
1539 }
1540
1541 static u32 gconst_dirty_mask(void)
1542 {
1543   u32 mask = 0;
1544   int i;
1545
1546   for (i = 0; i < ARRAY_SIZE(guest_regs); i++)
1547     if (guest_regs[i].flags & GRF_CDIRTY)
1548       mask |= (1 << i);
1549   return mask;
1550 }
1551
1552 static void gconst_kill(sh2_reg_e r)
1553 {
1554   if (guest_regs[r].flags & (GRF_CONST|GRF_CDIRTY))
1555     gconsts[guest_regs[r].cnst].gregs &= ~(1 << r);
1556   guest_regs[r].flags &= ~(GRF_CONST|GRF_CDIRTY);
1557 }
1558
1559 static void gconst_copy(sh2_reg_e rd, sh2_reg_e rs)
1560 {
1561   gconst_kill(rd);
1562   if (guest_regs[rs].flags & GRF_CONST) {
1563     guest_regs[rd].flags |= GRF_CONST;
1564     if (guest_regs[rd].vreg < 0)
1565       guest_regs[rd].flags |= GRF_CDIRTY;
1566     guest_regs[rd].cnst = guest_regs[rs].cnst;
1567     gconsts[guest_regs[rd].cnst].gregs |= (1 << rd);
1568   }
1569 }
1570
1571 static void gconst_clean(void)
1572 {
1573   int i;
1574
1575   for (i = 0; i < ARRAY_SIZE(guest_regs); i++)
1576     if (guest_regs[i].flags & GRF_CDIRTY) {
1577       // using RC_GR_READ here: it will call gconst_try_read,
1578       // cache the reg and mark it dirty.
1579       rcache_get_reg_(i, RC_GR_READ, 0, NULL);
1580     }
1581 }
1582
1583 static void gconst_invalidate(void)
1584 {
1585   int i;
1586
1587   for (i = 0; i < ARRAY_SIZE(guest_regs); i++) {
1588     if (guest_regs[i].flags & (GRF_CONST|GRF_CDIRTY))
1589       gconsts[guest_regs[i].cnst].gregs &= ~(1 << i);
1590     guest_regs[i].flags &= ~(GRF_CONST|GRF_CDIRTY);
1591   }
1592 }
1593
1594
1595 static u16 rcache_counter;
1596 // SH2 register usage bitmasks
1597 static u32 rcache_vregs_reg;     // regs of type HRT_REG (for pinning)
1598 static u32 rcache_regs_static;   // statically allocated regs
1599 static u32 rcache_regs_pinned;   // pinned regs
1600 static u32 rcache_regs_now;      // regs used in current insn
1601 static u32 rcache_regs_soon;     // regs used in the next few insns
1602 static u32 rcache_regs_late;     // regs used in later insns
1603 static u32 rcache_regs_discard;  // regs overwritten without being used
1604 static u32 rcache_regs_clean;    // regs needing cleaning
1605
1606 static void rcache_lock_vreg(int x)
1607 {
1608   if (x >= 0) {
1609     cache_regs[x].locked ++;
1610 #if DRC_DEBUG & 64
1611     if (cache_regs[x].type == HR_FREE) {
1612       printf("locking free vreg %x, aborting\n", x);
1613       exit(1);
1614     }
1615     if (!cache_regs[x].locked) {
1616       printf("locking overflow vreg %x, aborting\n", x);
1617       exit(1);
1618     }
1619 #endif
1620   }
1621 }
1622
1623 static void rcache_unlock_vreg(int x)
1624 {
1625   if (x >= 0) {
1626 #if DRC_DEBUG & 64
1627     if (cache_regs[x].type == HR_FREE) {
1628       printf("unlocking free vreg %x, aborting\n", x);
1629       exit(1);
1630     }
1631 #endif
1632     if (cache_regs[x].locked)
1633       cache_regs[x].locked --;
1634   }
1635 }
1636
1637 static void rcache_free_vreg(int x)
1638 {
1639   cache_regs[x].type = cache_regs[x].locked ? HR_TEMP : HR_FREE;
1640   cache_regs[x].flags &= HRF_PINNED;
1641   cache_regs[x].gregs = 0;
1642 }
1643
1644 static void rcache_unmap_vreg(int x)
1645 {
1646   int i;
1647
1648   FOR_ALL_BITS_SET_DO(cache_regs[x].gregs, i,
1649       if (guest_regs[i].flags & GRF_DIRTY) {
1650         // if a dirty reg is unmapped save its value to context
1651         if ((~rcache_regs_discard | rcache_regs_now) & (1 << i))
1652           emith_ctx_write(cache_regs[x].hreg, i * 4);
1653         guest_regs[i].flags &= ~GRF_DIRTY;
1654       }
1655       guest_regs[i].vreg = -1);
1656   rcache_free_vreg(x);
1657 }
1658
1659 static void rcache_move_vreg(int d, int x)
1660 {
1661   int i;
1662
1663   cache_regs[d].type = HR_CACHED;
1664   cache_regs[d].gregs = cache_regs[x].gregs;
1665   cache_regs[d].flags &= HRF_PINNED;
1666   cache_regs[d].flags |= cache_regs[x].flags & ~HRF_PINNED;
1667   cache_regs[d].locked = 0;
1668   cache_regs[d].stamp = cache_regs[x].stamp;
1669   emith_move_r_r(cache_regs[d].hreg, cache_regs[x].hreg);
1670   for (i = 0; i < ARRAY_SIZE(guest_regs); i++)
1671     if (guest_regs[i].vreg == x)
1672       guest_regs[i].vreg = d;
1673   rcache_free_vreg(x);
1674 }
1675
1676 static void rcache_clean_vreg(int x)
1677 {
1678   u32 rns = rcache_regs_now | rcache_regs_soon;
1679   int r;
1680
1681   if (cache_regs[x].flags & HRF_DIRTY) { // writeback
1682     cache_regs[x].flags &= ~HRF_DIRTY;
1683     rcache_lock_vreg(x);
1684     FOR_ALL_BITS_SET_DO(cache_regs[x].gregs, r,
1685         if (guest_regs[r].flags & GRF_DIRTY) {
1686           if (guest_regs[r].flags & (GRF_STATIC|GRF_PINNED)) {
1687             if (guest_regs[r].vreg != guest_regs[r].sreg &&
1688                 !cache_regs[guest_regs[r].sreg].locked &&
1689                 ((~rcache_regs_discard | rcache_regs_now) & (1 << r)) &&
1690                 !(rns & cache_regs[guest_regs[r].sreg].gregs)) {
1691               // statically mapped reg not in its sreg. move back to sreg
1692               rcache_evict_vreg(guest_regs[r].sreg);
1693               emith_move_r_r(cache_regs[guest_regs[r].sreg].hreg,
1694                              cache_regs[guest_regs[r].vreg].hreg);
1695               rcache_copy_x16(cache_regs[guest_regs[r].sreg].hreg,
1696                              cache_regs[guest_regs[r].vreg].hreg);
1697               rcache_remove_vreg_alias(x, r);
1698               rcache_add_vreg_alias(guest_regs[r].sreg, r);
1699               cache_regs[guest_regs[r].sreg].flags |= HRF_DIRTY;
1700             } else
1701               // cannot remap. keep dirty for writeback in unmap
1702               cache_regs[x].flags |= HRF_DIRTY;
1703           } else {
1704             if ((~rcache_regs_discard | rcache_regs_now) & (1 << r))
1705               emith_ctx_write(cache_regs[x].hreg, r * 4);
1706             guest_regs[r].flags &= ~GRF_DIRTY;
1707           }
1708           rcache_regs_clean &= ~(1 << r);
1709         })
1710     rcache_unlock_vreg(x);
1711   }
1712
1713 #if DRC_DEBUG & 64
1714   RCACHE_CHECK("after clean");
1715 #endif
1716 }
1717
1718 static void rcache_add_vreg_alias(int x, sh2_reg_e r)
1719 {
1720   cache_regs[x].gregs |= (1 << r);
1721   guest_regs[r].vreg = x;
1722   cache_regs[x].type = HR_CACHED;
1723 }
1724
1725 static void rcache_remove_vreg_alias(int x, sh2_reg_e r)
1726 {
1727   cache_regs[x].gregs &= ~(1 << r);
1728   if (!cache_regs[x].gregs) {
1729     // no reg mapped -> free vreg
1730     if (cache_regs[x].locked)
1731       cache_regs[x].type = HR_TEMP;
1732     else
1733       rcache_free_vreg(x);
1734   }
1735   guest_regs[r].vreg = -1;
1736 }
1737
1738 static void rcache_evict_vreg(int x)
1739 {
1740   rcache_remap_vreg(x);
1741   rcache_unmap_vreg(x);
1742 }
1743
1744 static void rcache_evict_vreg_aliases(int x, sh2_reg_e r)
1745 {
1746   rcache_remove_vreg_alias(x, r);
1747   rcache_evict_vreg(x);
1748   rcache_add_vreg_alias(x, r);
1749 }
1750
1751 static int rcache_allocate(int what, int minprio)
1752 {
1753   // evict reg with oldest stamp (only for HRT_REG, no temps)
1754   int i, i_prio, oldest = -1, prio = 0;
1755   u16 min_stamp = (u16)-1;
1756
1757   for (i = ARRAY_SIZE(cache_regs)-1; i >= 0; i--) {
1758     // consider only non-static, unpinned, unlocked REG or TEMP
1759     if ((cache_regs[i].flags & HRF_PINNED) || cache_regs[i].locked)
1760       continue;
1761     if ((what > 0 && !(cache_regs[i].htype & HRT_REG)) ||   // get a REG
1762         (what == 0 && (cache_regs[i].htype & HRT_TEMP)) ||  // get a non-TEMP
1763         (what < 0 && !(cache_regs[i].htype & HRT_TEMP)))    // get a TEMP
1764       continue;
1765     if (cache_regs[i].type == HR_FREE || cache_regs[i].type == HR_TEMP) {
1766       // REG is free
1767       prio = 10;
1768       oldest = i;
1769       break;
1770     }
1771     if (cache_regs[i].type == HR_CACHED) {
1772       if (rcache_regs_now & cache_regs[i].gregs)
1773         // REGs needed for the current insn
1774         i_prio = 0;
1775       else if (rcache_regs_soon & cache_regs[i].gregs)
1776         // REGs needed in the next insns
1777         i_prio = 2;
1778       else if (rcache_regs_late & cache_regs[i].gregs)
1779         // REGs needed in some future insn
1780         i_prio = 4;
1781       else if (~rcache_regs_discard & cache_regs[i].gregs)
1782         // REGs not needed in the foreseeable future
1783         i_prio = 6;
1784       else
1785         // REGs soon overwritten anyway
1786         i_prio = 8;
1787       if (!(cache_regs[i].flags & HRF_DIRTY)) i_prio ++;
1788
1789       if (prio < i_prio || (prio == i_prio && cache_regs[i].stamp < min_stamp)) {
1790         min_stamp = cache_regs[i].stamp;
1791         oldest = i;
1792         prio = i_prio;
1793       }
1794     }
1795   }
1796
1797
1798   if (prio < minprio || oldest == -1)
1799     return -1;
1800
1801   if (cache_regs[oldest].type == HR_CACHED)
1802     rcache_evict_vreg(oldest);
1803   else
1804     rcache_free_vreg(oldest);
1805
1806   return oldest;
1807 }
1808
1809 static int rcache_allocate_vreg(int needed)
1810 {
1811   int x;
1812   
1813   x = rcache_allocate(1, needed ? 0 : 4);
1814   if (x < 0)
1815     x = rcache_allocate(-1, 0);
1816   return x;
1817 }
1818
1819 static int rcache_allocate_nontemp(void)
1820 {
1821   int x = rcache_allocate(0, 4);
1822   return x;
1823 }
1824
1825 static int rcache_allocate_temp(void)
1826 {
1827   int x = rcache_allocate(-1, 0);
1828   if (x < 0)
1829     x = rcache_allocate(0, 0);
1830   return x;
1831 }
1832
1833 // maps a host register to a REG
1834 static int rcache_map_reg(sh2_reg_e r, int hr)
1835 {
1836 #if REMAP_REGISTER
1837   int i;
1838
1839   gconst_kill(r);
1840
1841   // lookup the TEMP hr maps to
1842   i = reg_map_host[hr];
1843   if (i < 0) {
1844     // must not happen
1845     printf("invalid host register %d\n", hr);
1846     exit(1);
1847   }
1848
1849   // remove old mappings of r and i if one exists
1850   if (guest_regs[r].vreg >= 0)
1851     rcache_remove_vreg_alias(guest_regs[r].vreg, r);
1852   if (cache_regs[i].type == HR_CACHED)
1853     rcache_evict_vreg(i);
1854   // set new mappping
1855   cache_regs[i].type = HR_CACHED;
1856   cache_regs[i].gregs = 1 << r;
1857   cache_regs[i].locked = 0;
1858   cache_regs[i].stamp = ++rcache_counter;
1859   cache_regs[i].flags |= HRF_DIRTY;
1860   rcache_lock_vreg(i);
1861   guest_regs[r].flags |= GRF_DIRTY;
1862   guest_regs[r].vreg = i;
1863 #if DRC_DEBUG & 64
1864   RCACHE_CHECK("after map");
1865 #endif
1866   return cache_regs[i].hreg;
1867 #else
1868   return rcache_get_reg(r, RC_GR_WRITE, NULL);
1869 #endif
1870 }
1871
1872 // remap vreg from a TEMP to a REG if it will be used (upcoming TEMP invalidation)
1873 static void rcache_remap_vreg(int x)
1874 {
1875 #if REMAP_REGISTER
1876   u32 rsl_d = rcache_regs_soon | rcache_regs_late;
1877   int d;
1878
1879   // x must be a cached vreg
1880   if (cache_regs[x].type != HR_CACHED || cache_regs[x].locked)
1881     return;
1882   // don't do it if x isn't used
1883   if (!(rsl_d & cache_regs[x].gregs)) {
1884     // clean here to avoid data loss on invalidation
1885     rcache_clean_vreg(x);
1886     return;
1887   }
1888
1889   FOR_ALL_BITS_SET_DO(cache_regs[x].gregs, d,
1890     if ((guest_regs[d].flags & (GRF_STATIC|GRF_PINNED)) &&
1891         !cache_regs[guest_regs[d].sreg].locked &&
1892         !((rsl_d|rcache_regs_now) & cache_regs[guest_regs[d].sreg].gregs)) {
1893       // STATIC not in its sreg and sreg is available
1894       rcache_evict_vreg(guest_regs[d].sreg);
1895       rcache_move_vreg(guest_regs[d].sreg, x);
1896       return;
1897     }
1898   )
1899
1900   // allocate a non-TEMP vreg
1901   rcache_lock_vreg(x); // lock to avoid evicting x
1902   d = rcache_allocate_nontemp();
1903   rcache_unlock_vreg(x);
1904   if (d < 0) {
1905     rcache_clean_vreg(x);
1906     return;
1907   }
1908
1909   // move vreg to new location
1910   rcache_move_vreg(d, x);
1911 #if DRC_DEBUG & 64
1912   RCACHE_CHECK("after remap");
1913 #endif
1914 #else
1915   rcache_clean_vreg(x);
1916 #endif
1917 }
1918
1919 static void rcache_alias_vreg(sh2_reg_e rd, sh2_reg_e rs)
1920 {
1921 #if ALIAS_REGISTERS
1922   int x;
1923
1924   // if s isn't constant, it must be in cache for aliasing
1925   if (!gconst_check(rs))
1926     rcache_get_reg_(rs, RC_GR_READ, 0, NULL);
1927
1928   // if d and s are not already aliased
1929   x = guest_regs[rs].vreg;
1930   if (guest_regs[rd].vreg != x) {
1931     // remove possible old mapping of dst
1932     if (guest_regs[rd].vreg >= 0)
1933       rcache_remove_vreg_alias(guest_regs[rd].vreg, rd);
1934     // make dst an alias of src
1935     if (x >= 0)
1936       rcache_add_vreg_alias(x, rd);
1937     // if d is now in cache, it must be dirty
1938     if (guest_regs[rd].vreg >= 0) {
1939       x = guest_regs[rd].vreg;
1940       cache_regs[x].flags |= HRF_DIRTY;
1941       guest_regs[rd].flags |= GRF_DIRTY;
1942     }
1943   }
1944
1945   gconst_copy(rd, rs);
1946 #if DRC_DEBUG & 64
1947   RCACHE_CHECK("after alias");
1948 #endif
1949 #else
1950   int hr_s = rcache_get_reg(rs, RC_GR_READ, NULL);
1951   int hr_d = rcache_get_reg(rd, RC_GR_WRITE, NULL);
1952
1953   emith_move_r_r(hr_d, hr_s);
1954   gconst_copy(rd, rs);
1955 #endif
1956 }
1957
1958 // note: must not be called when doing conditional code
1959 static int rcache_get_reg_(sh2_reg_e r, rc_gr_mode mode, int do_locking, int *hr)
1960 {
1961   int src, dst, ali;
1962   cache_reg_t *tr;
1963   u32 rsp_d = (rcache_regs_soon | rcache_regs_static | rcache_regs_pinned) &
1964                ~rcache_regs_discard;
1965
1966   dst = src = guest_regs[r].vreg;
1967
1968   rcache_lock_vreg(src); // lock to avoid evicting src
1969   // good opportunity to relocate a remapped STATIC?
1970   if ((guest_regs[r].flags & (GRF_STATIC|GRF_PINNED)) &&
1971       src != guest_regs[r].sreg && (src < 0 || mode != RC_GR_READ) &&
1972       !cache_regs[guest_regs[r].sreg].locked &&
1973       !((rsp_d|rcache_regs_now) & cache_regs[guest_regs[r].sreg].gregs)) {
1974     dst = guest_regs[r].sreg;
1975     rcache_evict_vreg(dst);
1976   } else if (dst < 0) {
1977     // allocate a cache register
1978     if ((dst = rcache_allocate_vreg(rsp_d & (1 << r))) < 0) {
1979       printf("no registers to evict, aborting\n");
1980       exit(1);
1981     }
1982   }
1983   tr = &cache_regs[dst];
1984   tr->stamp = rcache_counter;
1985   // remove r from src
1986   if (src >= 0 && src != dst)
1987     rcache_remove_vreg_alias(src, r);
1988   rcache_unlock_vreg(src);
1989
1990   // if r has a constant it may have aliases
1991   if (mode != RC_GR_WRITE && gconst_try_read(dst, r))
1992     src = dst;
1993
1994   // if r will be modified, check for aliases being needed rsn
1995   ali = tr->gregs & ~(1 << r);
1996   if (mode != RC_GR_READ && src == dst && ali) {
1997     int x = -1;
1998     if ((rsp_d|rcache_regs_now) & ali) {
1999       if ((guest_regs[r].flags & (GRF_STATIC|GRF_PINNED)) &&
2000           guest_regs[r].sreg == dst && !tr->locked) {
2001         // split aliases if r is STATIC in sreg and dst isn't already locked
2002         int t;
2003         FOR_ALL_BITS_SET_DO(ali, t,
2004           if ((guest_regs[t].flags & (GRF_STATIC|GRF_PINNED)) &&
2005               !(ali & ~(1 << t)) &&
2006               !cache_regs[guest_regs[t].sreg].locked &&
2007               !((rsp_d|rcache_regs_now) & cache_regs[guest_regs[t].sreg].gregs)) {
2008             // alias is a single STATIC and its sreg is available
2009             x = guest_regs[t].sreg;
2010             rcache_evict_vreg(x);
2011           } else {
2012             rcache_lock_vreg(dst); // lock to avoid evicting dst
2013             x = rcache_allocate_vreg(rsp_d & ali);
2014             rcache_unlock_vreg(dst);
2015           }
2016           break;
2017         )
2018         if (x >= 0) {
2019           rcache_remove_vreg_alias(src, r);
2020           src = dst;
2021           rcache_move_vreg(x, dst);
2022         }
2023       } else {
2024         // split r
2025         rcache_lock_vreg(src); // lock to avoid evicting src
2026         x = rcache_allocate_vreg(rsp_d & (1 << r));
2027         rcache_unlock_vreg(src);
2028         if (x >= 0) {
2029           rcache_remove_vreg_alias(src, r);
2030           dst = x;
2031           tr = &cache_regs[dst];
2032           tr->stamp = rcache_counter;
2033         }
2034       }
2035     }
2036     if (x < 0)
2037       // aliases not needed or no vreg available, remove them
2038       rcache_evict_vreg_aliases(dst, r);
2039   }
2040
2041   // assign r to dst
2042   rcache_add_vreg_alias(dst, r);
2043
2044   // handle dst register transfer
2045   if (src < 0 && mode != RC_GR_WRITE)
2046     emith_ctx_read(tr->hreg, r * 4);
2047   if (hr) {
2048     *hr = (src >= 0 ? cache_regs[src].hreg : tr->hreg);
2049     rcache_lock_vreg(src >= 0 ? src : dst);
2050   } else if (src >= 0 && mode != RC_GR_WRITE && cache_regs[src].hreg != tr->hreg)
2051     emith_move_r_r(tr->hreg, cache_regs[src].hreg);
2052
2053   // housekeeping
2054   if (do_locking)
2055     rcache_lock_vreg(dst);
2056   if (mode != RC_GR_READ) {
2057     tr->flags |= HRF_DIRTY;
2058     guest_regs[r].flags |= GRF_DIRTY;
2059     gconst_kill(r);
2060     rcache_set_x16(tr->hreg, 0, 0);
2061   } else if (src >= 0 && cache_regs[src].hreg != tr->hreg)
2062     rcache_copy_x16(tr->hreg, cache_regs[src].hreg);
2063 #if DRC_DEBUG & 64
2064   RCACHE_CHECK("after getreg");
2065 #endif
2066   return tr->hreg;
2067 }
2068
2069 static int rcache_get_reg(sh2_reg_e r, rc_gr_mode mode, int *hr)
2070 {
2071   return rcache_get_reg_(r, mode, 1, hr);
2072 }
2073
2074 static void rcache_pin_reg(sh2_reg_e r)
2075 {
2076   int hr, x;
2077
2078   // don't pin if static or already pinned
2079   if (guest_regs[r].flags & (GRF_STATIC|GRF_PINNED))
2080     return;
2081
2082   rcache_regs_soon |= (1 << r); // kludge to prevent allocation of a temp
2083   hr = rcache_get_reg_(r, RC_GR_RMW, 0, NULL);
2084   x = reg_map_host[hr];
2085
2086   // can only pin non-TEMPs
2087   if (!(cache_regs[x].htype & HRT_TEMP)) {
2088     guest_regs[r].flags |= GRF_PINNED;
2089     cache_regs[x].flags |= HRF_PINNED;
2090     guest_regs[r].sreg = x;
2091     rcache_regs_pinned |= (1 << r);
2092   }
2093 #if DRC_DEBUG & 64
2094   RCACHE_CHECK("after pin");
2095 #endif
2096 }
2097
2098 static int rcache_get_tmp(void)
2099 {
2100   int i;
2101
2102   i = rcache_allocate_temp();
2103   if (i < 0) {
2104     printf("cannot allocate temp\n");
2105     exit(1);
2106   }
2107
2108   cache_regs[i].type = HR_TEMP;
2109   rcache_lock_vreg(i);
2110
2111   return cache_regs[i].hreg;
2112 }
2113
2114 static int rcache_get_vreg_hr(int hr)
2115 {
2116   int i;
2117
2118   i = reg_map_host[hr];
2119   if (i < 0 || cache_regs[i].locked) {
2120     printf("host register %d is locked\n", hr);
2121     exit(1);
2122   }
2123
2124   if (cache_regs[i].type == HR_CACHED)
2125     rcache_evict_vreg(i);
2126   else if (cache_regs[i].type == HR_TEMP && cache_regs[i].locked) {
2127     printf("host reg %d already used, aborting\n", hr);
2128     exit(1);
2129   }
2130
2131   return i;
2132 }
2133
2134 static int rcache_get_vreg_arg(int arg)
2135 {
2136   int hr = 0;
2137
2138   host_arg2reg(hr, arg);
2139   return rcache_get_vreg_hr(hr);
2140 }
2141
2142 // get a reg to be used as function arg
2143 static int rcache_get_tmp_arg(int arg)
2144 {
2145   int x = rcache_get_vreg_arg(arg);
2146   cache_regs[x].type = HR_TEMP;
2147   rcache_lock_vreg(x);
2148
2149   return cache_regs[x].hreg;
2150 }
2151
2152 // ... as return value after a call
2153 static int rcache_get_tmp_ret(void)
2154 {
2155   int x = rcache_get_vreg_hr(RET_REG);
2156   cache_regs[x].type = HR_TEMP;
2157   rcache_lock_vreg(x);
2158
2159   return cache_regs[x].hreg;
2160 }
2161
2162 // same but caches a reg if access is readonly (announced by hr being NULL)
2163 static int rcache_get_reg_arg(int arg, sh2_reg_e r, int *hr)
2164 {
2165   int i, srcr, dstr, dstid, keep;
2166   u32 val;
2167   host_arg2reg(dstr, arg);
2168
2169   i = guest_regs[r].vreg;
2170   if (i >= 0 && cache_regs[i].type == HR_CACHED && cache_regs[i].hreg == dstr)
2171     // r is already in arg, avoid evicting
2172     dstid = i;
2173   else
2174     dstid = rcache_get_vreg_arg(arg);
2175   dstr = cache_regs[dstid].hreg;
2176
2177   if (rcache_is_cached(r)) {
2178     // r is needed later on anyway
2179     srcr = rcache_get_reg_(r, RC_GR_READ, 0, NULL);
2180     keep = 1;
2181   } else if ((guest_regs[r].flags & GRF_CDIRTY) && gconst_get(r, &val)) {
2182     // r has an uncomitted const - load into arg, but keep constant uncomitted
2183     srcr = dstr;
2184     emith_move_r_imm(srcr, val);
2185     keep = 0;
2186   } else {
2187     // must read from ctx
2188     srcr = dstr;
2189     emith_ctx_read(srcr, r * 4);
2190     keep = 1;
2191   }
2192
2193   if (cache_regs[dstid].type == HR_CACHED)
2194     rcache_evict_vreg(dstid);
2195
2196   cache_regs[dstid].type = HR_TEMP;
2197   if (hr == NULL) {
2198     if (dstr != srcr)
2199       // arg is a copy of cached r
2200       emith_move_r_r(dstr, srcr);
2201     else if (keep && guest_regs[r].vreg < 0)
2202       // keep arg as vreg for r
2203       rcache_add_vreg_alias(dstid, r);
2204   } else {
2205     *hr = srcr;
2206     if (dstr != srcr) // must lock srcr if not copied here
2207       rcache_lock_vreg(reg_map_host[srcr]);
2208   }
2209
2210   cache_regs[dstid].stamp = ++rcache_counter;
2211   rcache_lock_vreg(dstid);
2212 #if DRC_DEBUG & 64
2213   RCACHE_CHECK("after getarg");
2214 #endif
2215   return dstr;
2216 }
2217
2218 static void rcache_free_tmp(int hr)
2219 {
2220   int i = reg_map_host[hr];
2221
2222   if (i < 0 || cache_regs[i].type != HR_TEMP) {
2223     printf("rcache_free_tmp fail: #%i hr %d, type %d\n", i, hr, cache_regs[i].type);
2224     exit(1);
2225   }
2226
2227   rcache_unlock_vreg(i);
2228 }
2229
2230 // saves temporary result either in REG or in drctmp
2231 static int rcache_save_tmp(int hr)
2232 {
2233   int i;
2234
2235   // find REG, either free or unlocked temp or oldest non-hinted cached
2236   i = rcache_allocate_nontemp();
2237   if (i < 0) {
2238     // if none is available, store in drctmp
2239     emith_ctx_write(hr, offsetof(SH2, drc_tmp));
2240     rcache_free_tmp(hr);
2241     return -1;
2242   }
2243
2244   cache_regs[i].type = HR_CACHED;
2245   cache_regs[i].gregs = 0; // not storing any guest register
2246   cache_regs[i].flags &= HRF_PINNED;
2247   cache_regs[i].locked = 0;
2248   cache_regs[i].stamp = ++rcache_counter;
2249   rcache_lock_vreg(i);
2250   emith_move_r_r(cache_regs[i].hreg, hr);
2251   rcache_free_tmp(hr);
2252   return i;
2253 }
2254
2255 static int rcache_restore_tmp(int x)
2256 {
2257   int hr;
2258
2259   // find REG with tmp store: cached but with no gregs
2260   if (x >= 0) {
2261     if (cache_regs[x].type != HR_CACHED || cache_regs[x].gregs) {
2262       printf("invalid tmp storage %d\n", x);
2263       exit(1);
2264     }
2265     // found, transform to a TEMP
2266     cache_regs[x].type = HR_TEMP;
2267     return cache_regs[x].hreg;
2268   }
2269  
2270   // if not available, create a TEMP store and fetch from drctmp
2271   hr = rcache_get_tmp();
2272   emith_ctx_read(hr, offsetof(SH2, drc_tmp));
2273
2274   return hr;
2275 }
2276
2277 static void rcache_free(int hr)
2278 {
2279   int x = reg_map_host[hr];
2280   rcache_unlock_vreg(x);
2281 }
2282
2283 static void rcache_unlock(int x)
2284 {
2285   if (x >= 0)
2286     cache_regs[x].locked = 0;
2287 }
2288
2289 static void rcache_unlock_all(void)
2290 {
2291   int i;
2292   for (i = 0; i < ARRAY_SIZE(cache_regs); i++)
2293     cache_regs[i].locked = 0;
2294 }
2295
2296 static void rcache_unpin_all(void)
2297 {
2298   int i;
2299
2300   for (i = 0; i < ARRAY_SIZE(guest_regs); i++) {
2301     if (guest_regs[i].flags & GRF_PINNED) {
2302       guest_regs[i].flags &= ~GRF_PINNED;
2303       cache_regs[guest_regs[i].sreg].flags &= ~HRF_PINNED;
2304       guest_regs[i].sreg = -1;
2305       rcache_regs_pinned &= ~(1 << i);
2306     }
2307   }
2308 #if DRC_DEBUG & 64
2309   RCACHE_CHECK("after unpin");
2310 #endif
2311 }
2312
2313 static void rcache_save_pinned(void)
2314 {
2315   int i;
2316
2317   // save pinned regs to context
2318   for (i = 0; i < ARRAY_SIZE(guest_regs); i++)
2319     if ((guest_regs[i].flags & GRF_PINNED) && guest_regs[i].vreg >= 0)
2320       emith_ctx_write(cache_regs[guest_regs[i].vreg].hreg, i * 4);
2321 }
2322
2323 static inline void rcache_set_usage_now(u32 mask)
2324 {
2325   rcache_regs_now = mask;
2326 }
2327
2328 static inline void rcache_set_usage_soon(u32 mask)
2329 {
2330   rcache_regs_soon = mask;
2331 }
2332
2333 static inline void rcache_set_usage_late(u32 mask)
2334 {
2335   rcache_regs_late = mask;
2336 }
2337
2338 static inline void rcache_set_usage_discard(u32 mask)
2339 {
2340   rcache_regs_discard = mask;
2341 }
2342
2343 static inline int rcache_is_cached(sh2_reg_e r)
2344 {
2345   // is r in cache or needed RSN?
2346   u32 rsc = rcache_regs_soon | rcache_regs_clean;
2347   return (guest_regs[r].vreg >= 0 || (rsc & (1 << r)));
2348 }
2349
2350 static inline int rcache_is_hreg_used(int hr)
2351 {
2352   int x = reg_map_host[hr];
2353   // is hr in use?
2354   return cache_regs[x].type != HR_FREE &&
2355         (cache_regs[x].type != HR_TEMP || cache_regs[x].locked);
2356 }
2357
2358 static inline u32 rcache_used_hregs_mask(void)
2359 {
2360   u32 mask = 0;
2361   int i;
2362
2363   for (i = 0; i < ARRAY_SIZE(cache_regs); i++)
2364     if ((cache_regs[i].htype & HRT_TEMP) && cache_regs[i].type != HR_FREE &&
2365         (cache_regs[i].type != HR_TEMP || cache_regs[i].locked))
2366       mask |= 1 << cache_regs[i].hreg;
2367
2368   return mask;
2369 }
2370
2371 static inline u32 rcache_dirty_mask(void)
2372 {
2373   u32 mask = 0;
2374   int i;
2375
2376   for (i = 0; i < ARRAY_SIZE(guest_regs); i++)
2377     if (guest_regs[i].flags & GRF_DIRTY)
2378       mask |= 1 << i;
2379   mask |= gconst_dirty_mask();
2380
2381   return mask;
2382 }
2383
2384 static inline u32 rcache_cached_mask(void)
2385 {
2386   u32 mask = 0;
2387   int i;
2388
2389   for (i = 0; i < ARRAY_SIZE(cache_regs); i++)
2390     if (cache_regs[i].type == HR_CACHED)
2391       mask |= cache_regs[i].gregs;
2392
2393   return mask;
2394 }
2395
2396 static void rcache_clean_tmp(void)
2397 {
2398   int i;
2399
2400   rcache_regs_clean = (1 << ARRAY_SIZE(guest_regs)) - 1;
2401   for (i = 0; i < ARRAY_SIZE(cache_regs); i++)
2402     if (cache_regs[i].type == HR_CACHED && (cache_regs[i].htype & HRT_TEMP)) {
2403       rcache_unlock(i);
2404       rcache_remap_vreg(i);
2405     }
2406   rcache_regs_clean = 0;
2407 }
2408
2409 static void rcache_clean_masked(u32 mask)
2410 {
2411   int i, r, hr;
2412   u32 m;
2413
2414   rcache_regs_clean |= mask;
2415   mask = rcache_regs_clean;
2416
2417   // clean constants where all aliases are covered by the mask, exempt statics
2418   // to avoid flushing them to context if sreg isn't available
2419   m = mask & ~(rcache_regs_static | rcache_regs_pinned);
2420   for (i = 0; i < ARRAY_SIZE(gconsts); i++)
2421     if ((gconsts[i].gregs & m) && !(gconsts[i].gregs & ~mask)) {
2422       FOR_ALL_BITS_SET_DO(gconsts[i].gregs, r,
2423           if (guest_regs[r].flags & GRF_CDIRTY) {
2424             hr = rcache_get_reg_(r, RC_GR_READ, 0, NULL);
2425             rcache_clean_vreg(reg_map_host[hr]);
2426             break;
2427           });
2428     }
2429   // clean vregs where all aliases are covered by the mask
2430   for (i = 0; i < ARRAY_SIZE(cache_regs); i++)
2431     if (cache_regs[i].type == HR_CACHED &&
2432         (cache_regs[i].gregs & mask) && !(cache_regs[i].gregs & ~mask))
2433       rcache_clean_vreg(i);
2434 }
2435
2436 static void rcache_clean(void)
2437 {
2438   int i;
2439   gconst_clean();
2440
2441   rcache_regs_clean = (1 << ARRAY_SIZE(guest_regs)) - 1;
2442   for (i = ARRAY_SIZE(cache_regs)-1; i >= 0; i--)
2443     if (cache_regs[i].type == HR_CACHED)
2444       rcache_clean_vreg(i);
2445
2446   // relocate statics to their sregs (necessary before conditional jumps)
2447   for (i = 0; i < ARRAY_SIZE(guest_regs); i++) {
2448     if ((guest_regs[i].flags & (GRF_STATIC|GRF_PINNED)) &&
2449           guest_regs[i].vreg != guest_regs[i].sreg) {
2450       rcache_lock_vreg(guest_regs[i].vreg);
2451       rcache_evict_vreg(guest_regs[i].sreg);
2452       rcache_unlock_vreg(guest_regs[i].vreg);
2453       if (guest_regs[i].vreg < 0)
2454         emith_ctx_read(cache_regs[guest_regs[i].sreg].hreg, i*4);
2455       else {
2456         emith_move_r_r(cache_regs[guest_regs[i].sreg].hreg,
2457                         cache_regs[guest_regs[i].vreg].hreg);
2458         rcache_copy_x16(cache_regs[guest_regs[i].sreg].hreg,
2459                         cache_regs[guest_regs[i].vreg].hreg);
2460         rcache_remove_vreg_alias(guest_regs[i].vreg, i);
2461       }
2462       cache_regs[guest_regs[i].sreg].gregs = 1 << i;
2463       cache_regs[guest_regs[i].sreg].type = HR_CACHED;
2464       cache_regs[guest_regs[i].sreg].flags |= HRF_DIRTY|HRF_PINNED;
2465       guest_regs[i].flags |= GRF_DIRTY;
2466       guest_regs[i].vreg = guest_regs[i].sreg;
2467     }
2468   }
2469   rcache_regs_clean = 0;
2470 }
2471
2472 static void rcache_invalidate_tmp(void)
2473 {
2474   int i;
2475
2476   for (i = 0; i < ARRAY_SIZE(cache_regs); i++) {
2477     if (cache_regs[i].htype & HRT_TEMP) {
2478       rcache_unlock(i);
2479       if (cache_regs[i].type == HR_CACHED)
2480         rcache_evict_vreg(i);
2481       else
2482         rcache_free_vreg(i);
2483     }
2484   }
2485 }
2486
2487 static void rcache_invalidate(void)
2488 {
2489   int i;
2490   gconst_invalidate();
2491   rcache_unlock_all();
2492
2493   for (i = 0; i < ARRAY_SIZE(cache_regs); i++)
2494     rcache_free_vreg(i);
2495
2496   for (i = 0; i < ARRAY_SIZE(guest_regs); i++) {
2497     guest_regs[i].flags &= GRF_STATIC;
2498     if (!(guest_regs[i].flags & GRF_STATIC))
2499       guest_regs[i].vreg = -1;
2500     else {
2501       cache_regs[guest_regs[i].sreg].gregs = 1 << i;
2502       cache_regs[guest_regs[i].sreg].type = HR_CACHED;
2503       cache_regs[guest_regs[i].sreg].flags |= HRF_DIRTY|HRF_PINNED;
2504       guest_regs[i].flags |= GRF_DIRTY;
2505       guest_regs[i].vreg = guest_regs[i].sreg;
2506     }
2507   }
2508
2509   rcache_counter = 0;
2510   rcache_regs_now = rcache_regs_soon = rcache_regs_late = 0;
2511   rcache_regs_discard = rcache_regs_clean = 0;
2512 }
2513
2514 static void rcache_flush(void)
2515 {
2516   rcache_clean();
2517   rcache_invalidate();
2518 }
2519
2520 static void rcache_create(void)
2521 {
2522   int x = 0, i;
2523
2524   // create cache_regs as host register representation
2525   // RET_REG/params should be first TEMPs to avoid allocation conflicts in calls
2526   cache_regs[x++] = (cache_reg_t) {.hreg = RET_REG, .htype = HRT_TEMP};
2527   for (i = 0; i < ARRAY_SIZE(hregs_param); i++)
2528     if (hregs_param[i] != RET_REG)
2529       cache_regs[x++] = (cache_reg_t){.hreg = hregs_param[i],.htype = HRT_TEMP};
2530
2531   for (i = 0; i < ARRAY_SIZE(hregs_temp); i++)
2532     if (hregs_temp[i] != RET_REG)
2533       cache_regs[x++] = (cache_reg_t){.hreg = hregs_temp[i], .htype = HRT_TEMP};
2534
2535   for (i = ARRAY_SIZE(hregs_saved)-1; i >= 0; i--)
2536     if (hregs_saved[i] != CONTEXT_REG)
2537       cache_regs[x++] = (cache_reg_t){.hreg = hregs_saved[i], .htype = HRT_REG};
2538
2539   if (x != ARRAY_SIZE(cache_regs)) {
2540     printf("rcache_create failed (conflicting register count)\n");
2541     exit(1);
2542   }
2543
2544   // mapping from host_register to cache regs index
2545   memset(reg_map_host, -1, sizeof(reg_map_host));
2546   for (i = 0; i < ARRAY_SIZE(cache_regs); i++) {
2547     if (cache_regs[i].htype)
2548       reg_map_host[cache_regs[i].hreg] = i;
2549     if (cache_regs[i].htype == HRT_REG)
2550       rcache_vregs_reg |= (1 << i);
2551   }
2552
2553   // create static host register mapping for SH2 regs
2554   for (i = 0; i < ARRAY_SIZE(guest_regs); i++) {
2555     guest_regs[i] = (guest_reg_t){.sreg = -1};
2556   }
2557   for (i = 0; i < ARRAY_SIZE(regs_static); i += 2) {
2558     for (x = ARRAY_SIZE(cache_regs)-1; x >= 0; x--)
2559       if (cache_regs[x].hreg == regs_static[i+1])       break;
2560     if (x >= 0) {
2561       guest_regs[regs_static[i]] = (guest_reg_t){.flags = GRF_STATIC,.sreg = x};
2562       rcache_regs_static |= (1 << regs_static[i]);
2563       rcache_vregs_reg &= ~(1 << x);
2564     }
2565   }
2566
2567   printf("DRC registers created, %ld host regs (%d REG, %d STATIC, 1 CTX)\n",
2568     CACHE_REGS+1L, count_bits(rcache_vregs_reg),count_bits(rcache_regs_static));
2569 }
2570
2571 static void rcache_init(void)
2572 {
2573   // create DRC data structures
2574   rcache_create();
2575
2576   rcache_invalidate();
2577 #if DRC_DEBUG & 64
2578   RCACHE_CHECK("after init");
2579 #endif
2580 }
2581
2582 // ---------------------------------------------------------------
2583
2584 // swap 32 bit value read from mem in generated code (same as CPU_BE2)
2585 static void emit_le_swap(int cond, int r)
2586 {
2587 #if CPU_IS_LE
2588   if (cond == -1)
2589     emith_ror(r, r, 16);
2590   else
2591     emith_ror_c(cond, r, r, 16);
2592 #endif
2593 }
2594
2595 // fix memory byte ptr in generated code (same as MEM_BE2)
2596 static void emit_le_ptr8(int cond, int r)
2597 {
2598 #if CPU_IS_LE
2599   if (cond == -1)
2600     emith_eor_r_imm_ptr(r, 1);
2601   else
2602     emith_eor_r_imm_ptr_c(cond, r, 1);
2603 #endif
2604 }
2605
2606 // split address by mask, in base part (upper) and offset (lower, signed!)
2607 static uptr split_address(uptr la, uptr mask, s32 *offs)
2608 {
2609   uptr sign = (mask>>1) + 1; // sign bit in offset
2610   *offs = (la & mask) | (la & sign ? ~mask : 0); // offset part, sign extended
2611   la = (la & ~mask) + ((la & sign) << 1); // base part, corrected for offs sign
2612 #ifdef __arm__
2613   // arm32 offset has an add/sub flag and an unsigned 8 bit value, which only
2614   // allows values of [-255...255]. the value -256 thus can't be used.
2615   if (*offs < 0) {  // TODO not working at all with negative offsets on ARM?
2616   //if (*offs == -sign) {
2617     la -= sign;
2618     *offs += sign;
2619   }
2620 #endif
2621   return la;
2622 }
2623
2624 // NB may return either REG or TEMP
2625 static int emit_get_rbase_and_offs(SH2 *sh2, sh2_reg_e r, int rmode, s32 *offs)
2626 {
2627   uptr omask = emith_rw_offs_max(); // offset mask
2628   u32 mask = 0;
2629   u32 a;
2630   int poffs;
2631   int hr, hr2;
2632   uptr la;
2633
2634   // is r constant and points to a memory region?
2635   if (! gconst_get(r, &a))
2636     return -1;
2637   poffs = dr_ctx_get_mem_ptr(sh2, a + *offs, &mask);
2638   if (poffs == -1)
2639     return -1;
2640
2641   if (mask < 0x20000) {
2642     // data array, BIOS, DRAM, can't safely access directly since host addr may
2643     // change (BIOS,da code may run on either core, DRAM may be switched)
2644     hr = rcache_get_tmp();
2645     a = (a + *offs) & mask;
2646     if (poffs == offsetof(SH2, p_da)) {
2647       // access sh2->data_array directly
2648       a = split_address(a + offsetof(SH2, data_array), omask, offs);
2649       emith_add_r_r_ptr_imm(hr, CONTEXT_REG, a);
2650     } else {
2651       a = split_address(a, omask, offs);
2652       emith_ctx_read_ptr(hr, poffs);
2653       if (a)
2654         emith_add_r_r_ptr_imm(hr, hr, a);
2655     }
2656     return hr;
2657   }
2658
2659   // ROM, SDRAM. Host address should be mmapped to be equal to SH2 address.
2660   la = (uptr)*(void **)((char *)sh2 + poffs);
2661
2662   // if r is in rcache or needed soon anyway, and offs is relative to region,
2663   // and address translation fits in add_ptr_imm (s32), then use rcached const 
2664   if (la == (s32)la && !(((a & mask) + *offs) & ~mask) && rcache_is_cached(r)) {
2665 #if CPU_IS_LE // need to fix odd address for correct byte addressing
2666     if (a & 1) *offs += (*offs&1) ? 2 : -2;
2667 #endif
2668     la -= (s32)((a & ~mask) - *offs); // diff between reg and memory
2669     hr = hr2 = rcache_get_reg(r, rmode, NULL);
2670     if ((s32)a < 0) emith_uext_ptr(hr2);
2671     la = split_address(la, omask, offs);
2672     if (la) {
2673       hr = rcache_get_tmp();
2674       emith_add_r_r_ptr_imm(hr, hr2, la);
2675       rcache_free(hr2);
2676     }
2677   } else {
2678     // known fixed host address
2679     la = split_address(la + ((a + *offs) & mask), omask, offs);
2680     if (la == 0) {
2681       // offset only. optimize for hosts having short indexed addressing
2682       la = *offs & ~0x7f;  // keep the lower bits for endianess handling
2683       *offs &= 0x7f;
2684     }
2685     hr = rcache_get_tmp();
2686     emith_move_r_ptr_imm(hr, la);
2687   }
2688   return hr;
2689 }
2690
2691 // read const data from const ROM address
2692 static int emit_get_rom_data(SH2 *sh2, sh2_reg_e r, s32 offs, int size, u32 *val)
2693 {
2694   u32 a, mask;
2695
2696   *val = 0;
2697   if (gconst_get(r, &a)) {
2698     a += offs;
2699     // check if rom is memory mapped (not bank switched), and address is in rom
2700     if (p32x_sh2_mem_is_rom(a, sh2) && p32x_sh2_get_mem_ptr(a, &mask, sh2) == sh2->p_rom) {
2701       switch (size & MF_SIZEMASK) {
2702       case 0:   *val = (s8)p32x_sh2_read8(a, sh2s);   break;  // 8
2703       case 1:   *val = (s16)p32x_sh2_read16(a, sh2s); break;  // 16
2704       case 2:   *val = p32x_sh2_read32(a, sh2s);      break;  // 32
2705       }
2706       return 1;
2707     }
2708   }
2709   return 0;
2710 }
2711
2712 static void emit_move_r_imm32(sh2_reg_e dst, u32 imm)
2713 {
2714 #if PROPAGATE_CONSTANTS
2715   gconst_new(dst, imm);
2716 #else
2717   int hr = rcache_get_reg(dst, RC_GR_WRITE, NULL);
2718   emith_move_r_imm(hr, imm);
2719 #endif
2720 }
2721
2722 static void emit_move_r_r(sh2_reg_e dst, sh2_reg_e src)
2723 {
2724   if (gconst_check(src) || rcache_is_cached(src))
2725     rcache_alias_vreg(dst, src);
2726   else {
2727     int hr_d = rcache_get_reg(dst, RC_GR_WRITE, NULL);
2728     emith_ctx_read(hr_d, src * 4);
2729   }
2730 }
2731
2732 static void emit_add_r_imm(sh2_reg_e r, u32 imm)
2733 {
2734   u32 val;
2735   int isgc = gconst_get(r, &val);
2736   int hr, hr2;
2737
2738   if (!isgc || rcache_is_cached(r)) {
2739     // not constant, or r is already in cache
2740     hr = rcache_get_reg(r, RC_GR_RMW, &hr2);
2741     emith_add_r_r_imm(hr, hr2, imm);
2742     rcache_free(hr2);
2743     if (isgc)
2744       gconst_set(r, val + imm);
2745   } else
2746     gconst_new(r, val + imm);
2747 }
2748
2749 static void emit_sub_r_imm(sh2_reg_e r, u32 imm)
2750 {
2751   u32 val;
2752   int isgc = gconst_get(r, &val);
2753   int hr, hr2;
2754
2755   if (!isgc || rcache_is_cached(r)) {
2756     // not constant, or r is already in cache
2757     hr = rcache_get_reg(r, RC_GR_RMW, &hr2);
2758     emith_sub_r_r_imm(hr, hr2, imm);
2759     rcache_free(hr2);
2760     if (isgc)
2761       gconst_set(r, val - imm);
2762   } else
2763     gconst_new(r, val - imm);
2764 }
2765
2766 static void emit_sync_t_to_sr(void)
2767 {
2768   // avoid reloading SR from context if there's nothing to do
2769   if (emith_get_t_cond() >= 0) {
2770     int sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
2771     emith_sync_t(sr);
2772   }
2773 }
2774
2775 // rd = @(arg0)
2776 static int emit_memhandler_read(int size)
2777 {
2778   int hr;
2779
2780   emit_sync_t_to_sr();
2781   rcache_clean_tmp();
2782 #ifndef DRC_SR_REG
2783   // must writeback cycles for poll detection stuff
2784   if (guest_regs[SHR_SR].vreg != -1)
2785     rcache_unmap_vreg(guest_regs[SHR_SR].vreg);
2786 #endif
2787   rcache_invalidate_tmp();
2788
2789   if (size & MF_POLLING)
2790     switch (size & MF_SIZEMASK) {
2791     case 0:   emith_call(sh2_drc_read8_poll);   break; // 8
2792     case 1:   emith_call(sh2_drc_read16_poll);  break; // 16
2793     case 2:   emith_call(sh2_drc_read32_poll);  break; // 32
2794     }
2795   else
2796     switch (size & MF_SIZEMASK) {
2797     case 0:   emith_call(sh2_drc_read8);        break; // 8
2798     case 1:   emith_call(sh2_drc_read16);       break; // 16
2799     case 2:   emith_call(sh2_drc_read32);       break; // 32
2800     }
2801
2802   hr = rcache_get_tmp_ret();
2803   rcache_set_x16(hr, (size & MF_SIZEMASK) < 2, 0);
2804   return hr;
2805 }
2806
2807 // @(arg0) = arg1
2808 static void emit_memhandler_write(int size)
2809 {
2810   emit_sync_t_to_sr();
2811   rcache_clean_tmp();
2812 #ifndef DRC_SR_REG
2813   if (guest_regs[SHR_SR].vreg != -1)
2814     rcache_unmap_vreg(guest_regs[SHR_SR].vreg);
2815 #endif
2816   rcache_invalidate_tmp();
2817
2818   switch (size & MF_SIZEMASK) {
2819   case 0:   emith_call(sh2_drc_write8);     break;  // 8
2820   case 1:   emith_call(sh2_drc_write16);    break;  // 16
2821   case 2:   emith_call(sh2_drc_write32);    break;  // 32
2822   }
2823 }
2824
2825 // rd = @(Rs,#offs); rd < 0 -> return a temp
2826 static int emit_memhandler_read_rr(SH2 *sh2, sh2_reg_e rd, sh2_reg_e rs, s32 offs, int size)
2827 {
2828   int hr, hr2;
2829   u32 val;
2830
2831 #if PROPAGATE_CONSTANTS
2832   if (emit_get_rom_data(sh2, rs, offs, size, &val)) {
2833     if (rd == SHR_TMP) {
2834       hr2 = rcache_get_tmp();
2835       emith_move_r_imm(hr2, val);
2836     } else {
2837       emit_move_r_imm32(rd, val);
2838       hr2 = rcache_get_reg(rd, RC_GR_RMW, NULL);
2839     }
2840     rcache_set_x16(hr2, val == (s16)val, val == (u16)val);
2841     if (size & MF_POSTINCR)
2842       emit_add_r_imm(rs, 1 << (size & MF_SIZEMASK));
2843     return hr2;
2844   }
2845
2846   val = size & MF_POSTINCR;
2847   hr = emit_get_rbase_and_offs(sh2, rs, val ? RC_GR_RMW : RC_GR_READ, &offs);
2848   if (hr != -1) {
2849     if (rd == SHR_TMP)
2850       hr2 = rcache_get_tmp();
2851     else
2852       hr2 = rcache_get_reg(rd, RC_GR_WRITE, NULL);
2853     switch (size & MF_SIZEMASK) {
2854     case 0: emith_read8s_r_r_offs(hr2, hr, MEM_BE2(offs));  break; // 8
2855     case 1: emith_read16s_r_r_offs(hr2, hr, offs);          break; // 16
2856     case 2: emith_read_r_r_offs(hr2, hr, offs); emit_le_swap(-1, hr2); break;
2857     }
2858     rcache_free(hr);
2859     if (size & MF_POSTINCR)
2860       emit_add_r_imm(rs, 1 << (size & MF_SIZEMASK));
2861     return hr2;
2862   }
2863 #endif
2864
2865   if (gconst_get(rs, &val) && !rcache_is_cached(rs)) {
2866     hr = rcache_get_tmp_arg(0);
2867     emith_move_r_imm(hr, val + offs);
2868     if (size & MF_POSTINCR)
2869       gconst_new(rs, val + (1 << (size & MF_SIZEMASK)));
2870   } else if (size & MF_POSTINCR) {
2871     hr = rcache_get_tmp_arg(0);
2872     hr2 = rcache_get_reg(rs, RC_GR_RMW, NULL);
2873     emith_add_r_r_imm(hr, hr2, offs);
2874     emith_add_r_imm(hr2, 1 << (size & MF_SIZEMASK));
2875     if (gconst_get(rs, &val))
2876       gconst_set(rs, val + (1 << (size & MF_SIZEMASK)));
2877   } else {
2878     hr = rcache_get_reg_arg(0, rs, &hr2);
2879     if (offs || hr != hr2)
2880       emith_add_r_r_imm(hr, hr2, offs);
2881   }
2882   hr = emit_memhandler_read(size);
2883
2884   if (rd == SHR_TMP)
2885     hr2 = hr;
2886   else
2887     hr2 = rcache_map_reg(rd, hr);
2888
2889   if (hr != hr2) {
2890     emith_move_r_r(hr2, hr);
2891     rcache_free_tmp(hr);
2892   }
2893   return hr2;
2894 }
2895
2896 // @(Rs,#offs) = rd; rd < 0 -> write arg1
2897 static void emit_memhandler_write_rr(SH2 *sh2, sh2_reg_e rd, sh2_reg_e rs, s32 offs, int size)
2898 {
2899   int hr, hr2;
2900   u32 val;
2901
2902   if (rd == SHR_TMP) {
2903     host_arg2reg(hr2, 1); // already locked and prepared by caller
2904   } else if ((size & MF_PREDECR) && rd == rs) { // must avoid caching rd in arg1
2905     hr2 = rcache_get_reg_arg(1, rd, &hr);
2906     if (hr != hr2) {
2907       emith_move_r_r(hr2, hr);
2908       rcache_free(hr2);
2909     }
2910   } else
2911     hr2 = rcache_get_reg_arg(1, rd, NULL);
2912   if (rd != SHR_TMP)
2913     rcache_unlock(guest_regs[rd].vreg); // unlock in case rd is in arg0
2914
2915   if (gconst_get(rs, &val) && !rcache_is_cached(rs)) {
2916     hr = rcache_get_tmp_arg(0);
2917     if (size & MF_PREDECR) {
2918       val -= 1 << (size & MF_SIZEMASK);
2919       gconst_new(rs, val);
2920     }
2921     emith_move_r_imm(hr, val + offs);
2922   } else if (offs || (size & MF_PREDECR)) {
2923     if (size & MF_PREDECR)
2924       emit_sub_r_imm(rs, 1 << (size & MF_SIZEMASK));
2925     rcache_unlock(guest_regs[rs].vreg); // unlock in case rs is in arg0
2926     hr = rcache_get_reg_arg(0, rs, &hr2);
2927     if (offs || hr != hr2)
2928       emith_add_r_r_imm(hr, hr2, offs);
2929   } else
2930     hr = rcache_get_reg_arg(0, rs, NULL);
2931
2932   emit_memhandler_write(size);
2933 }
2934
2935 // rd = @(Rx,Ry); rd < 0 -> return a temp
2936 static int emit_indirect_indexed_read(SH2 *sh2, sh2_reg_e rd, sh2_reg_e rx, sh2_reg_e ry, int size)
2937 {
2938   int hr, hr2;
2939   int tx, ty;
2940 #if PROPAGATE_CONSTANTS
2941   u32 offs;
2942
2943   // if offs is larger than 0x01000000, it's most probably the base address part
2944   if (gconst_get(ry, &offs) && offs < 0x01000000)
2945     return emit_memhandler_read_rr(sh2, rd, rx, offs, size);
2946   if (gconst_get(rx, &offs) && offs < 0x01000000)
2947     return emit_memhandler_read_rr(sh2, rd, ry, offs, size);
2948 #endif
2949   hr = rcache_get_reg_arg(0, rx, &tx);
2950   ty = rcache_get_reg(ry, RC_GR_READ, NULL);
2951   emith_add_r_r_r(hr, tx, ty);
2952   hr = emit_memhandler_read(size);
2953
2954   if (rd == SHR_TMP)
2955     hr2 = hr;
2956   else
2957     hr2 = rcache_map_reg(rd, hr);
2958
2959   if (hr != hr2) {
2960     emith_move_r_r(hr2, hr);
2961     rcache_free_tmp(hr);
2962   }
2963   return hr2;
2964 }
2965
2966 // @(Rx,Ry) = rd; rd < 0 -> write arg1
2967 static void emit_indirect_indexed_write(SH2 *sh2, sh2_reg_e rd, sh2_reg_e rx, sh2_reg_e ry, int size)
2968 {
2969   int hr, tx, ty;
2970 #if PROPAGATE_CONSTANTS
2971   u32 offs;
2972
2973   // if offs is larger than 0x01000000, it's most probably the base address part
2974   if (gconst_get(ry, &offs) && offs < 0x01000000)
2975     return emit_memhandler_write_rr(sh2, rd, rx, offs, size);
2976   if (gconst_get(rx, &offs) && offs < 0x01000000)
2977     return emit_memhandler_write_rr(sh2, rd, ry, offs, size);
2978 #endif
2979   if (rd != SHR_TMP)
2980     rcache_get_reg_arg(1, rd, NULL);
2981   hr = rcache_get_reg_arg(0, rx, &tx);
2982   ty = rcache_get_reg(ry, RC_GR_READ, NULL);
2983   emith_add_r_r_r(hr, tx, ty);
2984   emit_memhandler_write(size);
2985 }
2986
2987 // @Rn+,@Rm+
2988 static void emit_indirect_read_double(SH2 *sh2, int *rnr, int *rmr, sh2_reg_e rn, sh2_reg_e rm, int size)
2989 {
2990   int tmp;
2991
2992   // unlock rn, rm here to avoid REG shortage in MAC operation
2993   tmp = emit_memhandler_read_rr(sh2, SHR_TMP, rn, 0, size | MF_POSTINCR);
2994   rcache_unlock(guest_regs[rn].vreg);
2995   tmp = rcache_save_tmp(tmp);
2996   *rmr = emit_memhandler_read_rr(sh2, SHR_TMP, rm, 0, size | MF_POSTINCR);
2997   rcache_unlock(guest_regs[rm].vreg);
2998   *rnr = rcache_restore_tmp(tmp);
2999 }
3000  
3001 static void emit_do_static_regs(int is_write, int tmpr)
3002 {
3003   int i, r, count;
3004
3005   for (i = 0; i < ARRAY_SIZE(guest_regs); i++) {
3006     if (guest_regs[i].flags & (GRF_STATIC|GRF_PINNED))
3007       r = cache_regs[guest_regs[i].vreg].hreg;
3008     else
3009       continue;
3010
3011     for (count = 1; i < ARRAY_SIZE(guest_regs) - 1; i++, r++) {
3012       if ((guest_regs[i + 1].flags & (GRF_STATIC|GRF_PINNED)) &&
3013           cache_regs[guest_regs[i + 1].vreg].hreg == r + 1)
3014         count++;
3015       else
3016         break;
3017     }
3018
3019     if (count > 1) {
3020       // i, r point to last item
3021       if (is_write)
3022         emith_ctx_write_multiple(r - count + 1, (i - count + 1) * 4, count, tmpr);
3023       else
3024         emith_ctx_read_multiple(r - count + 1, (i - count + 1) * 4, count, tmpr);
3025     } else {
3026       if (is_write)
3027         emith_ctx_write(r, i * 4);
3028       else
3029         emith_ctx_read(r, i * 4);
3030     }
3031   }
3032 }
3033
3034 #if DIV_OPTIMIZER
3035 // divide operation replacement functions, called by compiled code. Only the
3036 // 32:16 cases and the 64:32 cases described in the SH2 prog man are replaced.
3037
3038 // This is surprisingly difficult since the SH2 division operation is generating
3039 // the result in the dividend during the operation, leaving some remainder-like
3040 // stuff in the bits unused for the result, and leaving the T and Q status bits
3041 // in a state depending on the operands and the result. Q always reflects the
3042 // last result bit generated (i.e. bit 0 of the result). For T:
3043 //      32:16   T = top bit of the 16 bit remainder-like
3044 //      64:32   T = resulting T of the DIV0U/S operation
3045 // The remainder-like depends on outcome of the last generated result bit.
3046
3047 static uint32_t REGPARM(3) sh2_drc_divu32(uint32_t dv, uint32_t *dt, uint32_t ds)
3048 {
3049   if (likely(ds > dv && (uint16_t)ds == 0)) {
3050     // good case: no overflow, divisor not 0, lower 16 bits 0
3051     uint32_t quot = dv / (ds>>16), rem = dv - (quot * (ds>>16));
3052     if (~quot&1) rem -= ds>>16;
3053     *dt = (rem>>15) & 1;
3054     return (uint16_t)quot | ((2*rem + (quot>>31)) << 16);
3055   } else {
3056     // bad case: use the sh2 algo to get the right result
3057     int q = 0, t = 0, s = 16;
3058     while (s--) {
3059       uint32_t v = dv>>31;
3060       dv = (dv<<1) | t;
3061       t = v;
3062       v = dv;
3063       if (q)  dv += ds, q = dv < v;
3064       else    dv -= ds, q = dv > v;
3065       q ^= t, t = !q;
3066     }
3067     *dt = dv>>31;
3068     return (dv<<1) | t;
3069   }
3070 }
3071
3072 static uint32_t REGPARM(3) sh2_drc_divu64(uint32_t dh, uint32_t *dl, uint32_t ds)
3073 {
3074   uint64_t dv = *dl | ((uint64_t)dh << 32);
3075   if (likely(ds > dh)) {
3076     // good case: no overflow, divisor not 0
3077     uint32_t quot = dv / ds, rem = dv - ((uint64_t)quot * ds);
3078     if (~quot&1) rem -= ds;
3079     *dl = quot;
3080     return rem;
3081   } else {
3082     // bad case: use the sh2 algo to get the right result
3083     int q = 0, t = 0, s = 32;
3084     while (s--) {
3085       uint64_t v = dv>>63;
3086       dv = (dv<<1) | t;
3087       t = v;
3088       v = dv;
3089       if (q)  dv += ((uint64_t)ds << 32), q = dv < v;
3090       else    dv -= ((uint64_t)ds << 32), q = dv > v;
3091       q ^= t, t = !q;
3092     }
3093     *dl = (dv<<1) | t;
3094     return (dv>>32);
3095   }
3096 }
3097
3098 static uint32_t REGPARM(3) sh2_drc_divs32(int32_t dv, uint32_t *dt, int32_t ds)
3099 {
3100   uint32_t adv = abs(dv), ads = abs(ds)>>16;
3101   if (likely(ads > adv>>16 && ds != 0x80000000 && (int16_t)ds == 0)) {
3102     // good case: no overflow, divisor not 0 and not MIN_INT, lower 16 bits 0
3103     uint32_t quot = adv / ads, rem = adv - (quot * ads);
3104     int m1 = (rem ? dv^ds : ds) < 0;
3105     if (rem && dv < 0)  rem = (quot&1 ? -rem : +ads-rem);
3106     else                rem = (quot&1 ? +rem : -ads+rem);
3107     quot = ((dv^ds)<0 ? -quot : +quot) - m1;
3108     *dt = (rem>>15) & 1;
3109     return (uint16_t)quot | ((2*rem + (quot>>31)) << 16);
3110   } else {
3111     // bad case: use the sh2 algo to get the right result
3112     int m = (uint32_t)ds>>31, q = (uint32_t)dv>>31, t = m^q, s = 16;
3113     while (s--) {
3114       uint32_t v = (uint32_t)dv>>31;
3115       dv = (dv<<1) | t;
3116       t = v;
3117       v = dv;
3118       if (m^q)  dv += ds, q = (uint32_t)dv < v;
3119       else      dv -= ds, q = (uint32_t)dv > v;
3120       q ^= m^t, t = !(m^q);
3121     }
3122     *dt = (uint32_t)dv>>31;
3123     return (dv<<1) | t;
3124   }
3125 }
3126
3127 static uint32_t REGPARM(3) sh2_drc_divs64(int32_t dh, uint32_t *dl, int32_t ds)
3128 {
3129   int64_t _dv = *dl | ((int64_t)dh << 32);
3130   uint32_t ads = abs(ds);
3131   if (likely(_dv >= 0 && ads > _dv>>32 && ds != 0x80000000) ||
3132       likely(_dv < 0 && ads > -_dv>>32 && ds != 0x80000000)) {
3133     uint64_t adv = (_dv < 0 ? -_dv : _dv); // no llabs in older toolchains
3134     // good case: no overflow, divisor not 0 and not MIN_INT
3135     uint32_t quot = adv / ads, rem = adv - ((uint64_t)quot * ads);
3136     int m1 = (rem ? dh^ds : ds) < 0;
3137     if (rem && dh < 0) rem = (quot&1 ? -rem : +ads-rem);
3138     else               rem = (quot&1 ? +rem : -ads+rem);
3139     quot = ((dh^ds)<0 ? -quot : +quot) - m1;
3140     *dl = quot;
3141     return rem;
3142   } else {
3143     // bad case: use the sh2 algo to get the right result
3144     uint64_t dv = (uint64_t)_dv;
3145     int m = (uint32_t)ds>>31, q = (uint64_t)dv>>63, t = m^q, s = 32;
3146     while (s--) {
3147       uint64_t v = (uint64_t)dv>>63;
3148       dv = (dv<<1) | t;
3149       t = v;
3150       v = dv;
3151       if (m^q)  dv += ((uint64_t)ds << 32), q = dv < v;
3152       else      dv -= ((uint64_t)ds << 32), q = dv > v;
3153       q ^= m^t, t = !(m^q);
3154     }
3155     *dl = (dv<<1) | t;
3156     return (dv>>32);
3157   }
3158 }
3159 #endif
3160
3161 // block local link stuff
3162 struct linkage {
3163   u32 pc;
3164   void *ptr;
3165   struct block_link *bl;
3166   u32 mask;
3167 };
3168
3169 static inline int find_in_linkage(const struct linkage *array, int size, u32 pc)
3170 {
3171   size_t i;
3172   for (i = 0; i < size; i++)
3173     if (pc == array[i].pc)
3174       return i;
3175
3176   return -1;
3177 }
3178
3179 static int find_in_sorted_linkage(const struct linkage *array, int size, u32 pc)
3180 {
3181   // binary search in sorted array
3182   int left = 0, right = size-1;
3183   while (left <= right)
3184   {
3185     int middle = (left + right) / 2;
3186     if (array[middle].pc == pc)
3187       return middle;
3188     else if (array[middle].pc < pc)
3189       left = middle + 1;
3190     else
3191       right = middle - 1;
3192   }
3193   return -1;
3194 }
3195
3196 static void emit_branch_linkage_code(SH2 *sh2, struct block_desc *block, int tcache_id,
3197                                 const struct linkage *targets, int target_count,
3198                                 const struct linkage *links, int link_count)
3199 {
3200   struct block_link *bl;
3201   int u, v, tmp;
3202
3203   emith_flush();
3204   for (u = 0; u < link_count; u++) {
3205     emith_pool_check();
3206     // look up local branch targets
3207     if (links[u].mask & 0x2) {
3208       v = find_in_sorted_linkage(targets, target_count, links[u].pc);
3209       if (v < 0 || ! targets[v].ptr) {
3210         // forward branch not yet resolved, prepare external linking
3211         emith_jump_patch(links[u].ptr, tcache_ptr, NULL);
3212         bl = dr_prepare_ext_branch(block->entryp, links[u].pc, sh2->is_slave, tcache_id);
3213         if (bl)
3214           bl->type = BL_LDJMP;
3215         tmp = rcache_get_tmp_arg(0);
3216         emith_move_r_imm(tmp, links[u].pc);
3217         rcache_free_tmp(tmp);
3218         emith_jump_patchable(sh2_drc_dispatcher);
3219       } else if (emith_jump_patch_inrange(links[u].ptr, targets[v].ptr)) {
3220         // inrange local branch
3221         emith_jump_patch(links[u].ptr, targets[v].ptr, NULL);
3222       } else {
3223         // far local branch
3224         emith_jump_patch(links[u].ptr, tcache_ptr, NULL);
3225         emith_jump(targets[v].ptr);
3226       }
3227     } else {
3228       // external or exit, emit blx area entry
3229       void *target = (links[u].mask & 0x1 ? sh2_drc_exit : sh2_drc_dispatcher);
3230       if (links[u].bl)
3231         links[u].bl->blx = tcache_ptr;
3232       emith_jump_patch(links[u].ptr, tcache_ptr, NULL);
3233       tmp = rcache_get_tmp_arg(0);
3234       emith_move_r_imm(tmp, links[u].pc & ~1);
3235       rcache_free_tmp(tmp);
3236       emith_jump(target);
3237     }
3238   }
3239 }
3240
3241 #define DELAY_SAVE_T(sr) { \
3242   int t_ = rcache_get_tmp(); \
3243   emith_bic_r_imm(sr, T_save); \
3244   emith_and_r_r_imm(t_, sr, 1); \
3245   emith_or_r_r_lsl(sr, t_, T_SHIFT); \
3246   rcache_free_tmp(t_); \
3247 }
3248
3249 #define FLUSH_CYCLES(sr) \
3250   if (cycles > 0) \
3251     emith_sub_r_imm(sr, cycles << 12); \
3252   else if (cycles < 0) /* may happen after a branch not taken */ \
3253     emith_add_r_imm(sr, -cycles << 12); \
3254   cycles = 0; \
3255
3256 static void *dr_get_pc_base(u32 pc, SH2 *sh2);
3257 static void sh2_smc_rm_blocks(u32 a, int len, int tcache_id, int free);
3258
3259 static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
3260 {
3261   // branch targets in current block
3262   static struct linkage branch_targets[MAX_LOCAL_TARGETS];
3263   int branch_target_count = 0;
3264   // unresolved local or external targets with block link/exit area if needed
3265   static struct linkage blx_targets[MAX_LOCAL_BRANCHES];
3266   int blx_target_count = 0;
3267
3268   static u8 op_flags[BLOCK_INSN_LIMIT];
3269
3270   enum flg_states { FLG_UNKNOWN, FLG_UNUSED, FLG_0, FLG_1 };
3271   struct drcf {
3272     int delay_reg:8;
3273     u32 loop_type:8;
3274     u32 polling:8;
3275     u32 pinning:1;
3276     u32 test_irq:1;
3277     u32 pending_branch_direct:1;
3278     u32 pending_branch_indirect:1;
3279     u32 Tflag:2, Mflag:2;
3280   } drcf = { 0, };
3281
3282 #if LOOP_OPTIMIZER
3283   // loops with pinned registers for optimzation
3284   // pinned regs are like statics and don't need saving/restoring inside a loop
3285   static struct linkage pinned_loops[MAX_LOCAL_TARGETS/16];
3286   int pinned_loop_count = 0;
3287 #endif
3288
3289   // PC of current, first, last SH2 insn
3290   u32 pc, base_pc, end_pc;
3291   u32 base_literals, end_literals;
3292   u8 *block_entry_ptr;
3293   struct block_desc *block;
3294   struct block_entry *entry;
3295   struct block_link *bl;
3296   u16 *dr_pc_base;
3297   struct op_data *opd;
3298   int blkid_main = 0;
3299   int skip_op = 0;
3300   int tmp, tmp2;
3301   int cycles;
3302   int i, v;
3303   u32 u, m1, m2, m3, m4;
3304   int op;
3305   u16 crc;
3306
3307   base_pc = sh2->pc;
3308
3309   // get base/validate PC
3310   dr_pc_base = dr_get_pc_base(base_pc, sh2);
3311   if (dr_pc_base == (void *)-1) {
3312     printf("invalid PC, aborting: %08lx\n", (long)base_pc);
3313     // FIXME: be less destructive
3314     exit(1);
3315   }
3316
3317   // initial passes to disassemble and analyze the block
3318   crc = scan_block(base_pc, sh2->is_slave, op_flags, &end_pc, &base_literals, &end_literals);
3319   end_literals = dr_check_nolit(base_literals, end_literals, tcache_id);
3320   if (base_literals == end_literals) // map empty lit section to end of code
3321     base_literals = end_literals = end_pc;
3322
3323   // if there is already a translated but inactive block, reuse it
3324   block = dr_find_inactive_block(tcache_id, crc, base_pc, end_pc - base_pc,
3325     base_literals, end_literals - base_literals);
3326
3327 #if (DRC_DEBUG & (256|512))
3328   // remove any (partial) old blocks which might get in the way, to make sure
3329   // the same branch targets are used in the recording/playback code. Not needed
3330   // normally since the SH2 code wasn't overwritten and should be the same.
3331   sh2_smc_rm_blocks(base_pc, end_pc - base_pc, tcache_id, 0);
3332 #endif
3333
3334   if (block) {
3335     dbg(2, "== %csh2 reuse block %08x-%08x,%08x-%08x -> %p", sh2->is_slave ? 's' : 'm',
3336       base_pc, end_pc, base_literals, end_literals, block->entryp->tcache_ptr);
3337     dr_activate_block(block, tcache_id, sh2->is_slave);
3338     emith_update_cache();
3339     return block->entryp[0].tcache_ptr;
3340   }
3341
3342   // collect branch_targets that don't land on delay slots
3343   m1 = m2 = m3 = m4 = v = op = 0;
3344   for (pc = base_pc, i = 0; pc < end_pc; i++, pc += 2) {
3345     if (op_flags[i] & OF_DELAY_OP)
3346       op_flags[i] &= ~OF_BTARGET;
3347     if (op_flags[i] & OF_BTARGET) {
3348       if (branch_target_count < ARRAY_SIZE(branch_targets))
3349         branch_targets[branch_target_count++] = (struct linkage) { .pc = pc };
3350       else {
3351         printf("warning: linkage overflow\n");
3352         end_pc = pc;
3353         break;
3354       }
3355     }
3356     if (ops[i].op == OP_LDC && (ops[i].dest & BITMASK1(SHR_SR)) && pc+2 < end_pc)
3357       op_flags[i+1] |= OF_BTARGET; // RTE entrypoint in case of SR.IMASK change
3358     // unify T and SR since rcache doesn't know about "virtual" guest regs
3359     if (ops[i].source & BITMASK1(SHR_T))  ops[i].source |= BITMASK1(SHR_SR);
3360     if (ops[i].dest   & BITMASK1(SHR_T))  ops[i].source |= BITMASK1(SHR_SR);
3361     if (ops[i].dest   & BITMASK1(SHR_T))  ops[i].dest   |= BITMASK1(SHR_SR);
3362 #if LOOP_DETECTION
3363     // loop types detected:
3364     // 1. target: ... BRA target -> idle loop
3365     // 2. target: ... delay insn ... BF target -> delay loop
3366     // 3. target: ... poll  insn ... BF/BT target -> poll loop
3367     // 4. target: ... poll  insn ... BF/BT exit ... BRA target, exit: -> poll
3368     // conditions:
3369     // a. no further branch targets between target and back jump.
3370     // b. no unconditional branch insn inside the loop.
3371     // c. exactly one poll or delay insn is allowed inside a delay/poll loop
3372     // (scan_block marks loops only if they meet conditions a through c)
3373     // d. idle loops do not modify anything but PC,SR and contain no branches
3374     // e. delay/poll loops do not modify anything but the concerned reg,PC,SR
3375     // f. loading constants into registers inside the loop is allowed
3376     // g. a delay/poll loop must have a conditional branch somewhere
3377     // h. an idle loop must not have a conditional branch
3378     if (op_flags[i] & OF_BTARGET) {
3379       // possible loop entry point
3380       drcf.loop_type = op_flags[i] & OF_LOOP;
3381       drcf.pending_branch_direct = drcf.pending_branch_indirect = 0;
3382       op = OF_IDLE_LOOP; // loop type
3383       v = i;
3384       m1 = m2 = m3 = m4 = 0;
3385       if (!drcf.loop_type)   // reset basic loop it it isn't recognized as loop
3386         op_flags[i] &= ~OF_BASIC_LOOP;
3387     }
3388     if (drcf.loop_type) {
3389       // calculate reg masks for loop pinning
3390       m4 |= ops[i].source & ~m3;
3391       m3 |= ops[i].dest;
3392       // detect loop type, and store poll/delay register
3393       if (op_flags[i] & OF_POLL_INSN) {
3394         op = OF_POLL_LOOP;
3395         m1 |= ops[i].dest;   // loop poll/delay regs
3396       } else if (op_flags[i] & OF_DELAY_INSN) {
3397         op = OF_DELAY_LOOP;
3398         m1 |= ops[i].dest;
3399       } else if (ops[i].op != OP_LOAD_POOL && ops[i].op != OP_LOAD_CONST
3400               && (ops[i].op != OP_MOVE || op != OF_POLL_LOOP)) {
3401         // not (MOV @(PC) or MOV # or (MOV reg and poll)),   condition f
3402         m2 |= ops[i].dest;   // regs modified by other insns
3403       }
3404       // branch detector
3405       if (OP_ISBRAIMM(ops[i].op)) {
3406         if (ops[i].imm == base_pc + 2*v)
3407           drcf.pending_branch_direct = 1;       // backward branch detected
3408         else
3409           op_flags[v] &= ~OF_BASIC_LOOP;        // no basic loop
3410       }
3411       if (OP_ISBRACND(ops[i].op))
3412         drcf.pending_branch_indirect = 1;       // conditions g,h - cond.branch
3413       // poll/idle loops terminate with their backwards branch to the loop start
3414       if (drcf.pending_branch_direct && !(op_flags[i+1] & OF_DELAY_OP)) {
3415         m2 &= ~(m1 | BITMASK3(SHR_PC, SHR_SR, SHR_T)); // conditions d,e + g,h
3416         if (m2 || ((op == OF_IDLE_LOOP) == (drcf.pending_branch_indirect)))
3417           op = 0;                               // conditions not met
3418         op_flags[v] = (op_flags[v] & ~OF_LOOP) | op; // set loop type
3419         drcf.loop_type = 0;
3420 #if LOOP_OPTIMIZER
3421         if (op_flags[v] & OF_BASIC_LOOP) {
3422           m3 &= ~rcache_regs_static & ~BITMASK5(SHR_PC, SHR_PR, SHR_SR, SHR_T, SHR_MEM);
3423           if (m3 && count_bits(m3) < count_bits(rcache_vregs_reg) &&
3424               pinned_loop_count < ARRAY_SIZE(pinned_loops)-1) {
3425             pinned_loops[pinned_loop_count++] =
3426                 (struct linkage) { .pc = base_pc + 2*v, .mask = m3 };
3427           } else
3428             op_flags[v] &= ~OF_BASIC_LOOP;
3429         }
3430 #endif
3431       }
3432     }
3433 #endif
3434   }
3435
3436   tcache_ptr = dr_prepare_cache(tcache_id, (end_pc - base_pc) / 2, branch_target_count);
3437 #if (DRC_DEBUG & 4)
3438   tcache_dsm_ptrs[tcache_id] = tcache_ptr;
3439 #endif
3440
3441   block = dr_add_block(branch_target_count, base_pc, end_pc - base_pc,
3442     base_literals, end_literals-base_literals, crc, sh2->is_slave, &blkid_main);
3443   if (block == NULL)
3444     return NULL;
3445
3446   block_entry_ptr = tcache_ptr;
3447   dbg(2, "== %csh2 block #%d,%d %08x-%08x,%08x-%08x -> %p", sh2->is_slave ? 's' : 'm',
3448     tcache_id, blkid_main, base_pc, end_pc, base_literals, end_literals, block_entry_ptr);
3449
3450
3451   // clear stale state after compile errors
3452   rcache_invalidate();
3453   emith_invalidate_t();
3454   drcf = (struct drcf) { 0 };
3455 #if LOOP_OPTIMIZER
3456   pinned_loops[pinned_loop_count].pc = -1;
3457   pinned_loop_count = 0;
3458 #endif
3459
3460   // -------------------------------------------------
3461   // 3rd pass: actual compilation
3462   pc = base_pc;
3463   cycles = 0;
3464   for (i = 0; pc < end_pc; i++)
3465   {
3466     u32 delay_dep_fw = 0, delay_dep_bk = 0;
3467     int tmp3, tmp4;
3468     int sr;
3469
3470     if (op_flags[i] & OF_BTARGET)
3471     {
3472       if (pc != base_pc)
3473       {
3474         sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
3475         FLUSH_CYCLES(sr);
3476         emith_sync_t(sr);
3477         drcf.Mflag = FLG_UNKNOWN;
3478         rcache_flush();
3479         emith_flush();
3480       }
3481
3482       // make block entry
3483       v = block->entry_count;
3484       entry = &block->entryp[v];
3485       if (v < branch_target_count)
3486       {
3487         entry = &block->entryp[v];
3488         entry->pc = pc;
3489         entry->tcache_ptr = tcache_ptr;
3490         entry->links = entry->o_links = NULL;
3491 #if (DRC_DEBUG & 2)
3492         entry->block = block;
3493 #endif
3494         block->entry_count++;
3495
3496         dbg(2, "-- %csh2 block #%d,%d entry %08x -> %p",
3497           sh2->is_slave ? 's' : 'm', tcache_id, blkid_main,
3498           pc, tcache_ptr);
3499       }
3500       else {
3501         dbg(1, "too many entryp for block #%d,%d pc=%08x",
3502           tcache_id, blkid_main, pc);
3503         break;
3504       }
3505
3506       v = find_in_sorted_linkage(branch_targets, branch_target_count, pc);
3507       if (v >= 0)
3508         branch_targets[v].ptr = tcache_ptr;
3509 #if LOOP_DETECTION
3510       drcf.loop_type = op_flags[i] & OF_LOOP;
3511       drcf.delay_reg = -1;
3512       drcf.polling = (drcf.loop_type == OF_POLL_LOOP ? MF_POLLING : 0);
3513 #endif
3514
3515       rcache_clean();
3516
3517 #if (DRC_DEBUG & 0x10)
3518       tmp = rcache_get_tmp_arg(0);
3519       emith_move_r_imm(tmp, pc);
3520       tmp = emit_memhandler_read(1);
3521       tmp2 = rcache_get_tmp();
3522       tmp3 = rcache_get_tmp();
3523       emith_move_r_imm(tmp2, (s16)FETCH_OP(pc));
3524       emith_move_r_imm(tmp3, 0);
3525       emith_cmp_r_r(tmp, tmp2);
3526       EMITH_SJMP_START(DCOND_EQ);
3527       emith_read_r_r_offs_c(DCOND_NE, tmp3, tmp3, 0); // crash
3528       EMITH_SJMP_END(DCOND_EQ);
3529       rcache_free_tmp(tmp);
3530       rcache_free_tmp(tmp2);
3531       rcache_free_tmp(tmp3);
3532 #endif
3533
3534       // check cycles
3535       sr = rcache_get_reg(SHR_SR, RC_GR_READ, NULL);
3536
3537 #if LOOP_OPTIMIZER
3538       if (op_flags[i] & OF_BASIC_LOOP) {
3539         if (pinned_loops[pinned_loop_count].pc == pc) {
3540           // pin needed regs on loop entry 
3541           FOR_ALL_BITS_SET_DO(pinned_loops[pinned_loop_count].mask, v, rcache_pin_reg(v));
3542           emith_flush();
3543           // store current PC as loop target
3544           pinned_loops[pinned_loop_count].ptr = tcache_ptr;
3545           drcf.pinning = 1;
3546         } else
3547           op_flags[i] &= ~OF_BASIC_LOOP;
3548       }
3549
3550       if (op_flags[i] & OF_BASIC_LOOP) {
3551         // if exiting a pinned loop pinned regs must be written back to ctx
3552         // since they are reloaded in the loop entry code
3553         emith_cmp_r_imm(sr, 0);
3554         EMITH_JMP_START(DCOND_GE);
3555         rcache_save_pinned();
3556
3557         if (blx_target_count < ARRAY_SIZE(blx_targets)) {
3558           // exit via stub in blx table (saves some 1-3 insns in the main flow)
3559           blx_targets[blx_target_count++] =
3560               (struct linkage) { .pc = pc, .ptr = tcache_ptr, .mask = 0x1 };
3561           emith_jump_patchable(tcache_ptr);
3562         } else {
3563           // blx table full, must inline exit code
3564           tmp = rcache_get_tmp_arg(0);
3565           emith_move_r_imm(tmp, pc);
3566           emith_jump(sh2_drc_exit);
3567           rcache_free_tmp(tmp);
3568         }
3569         EMITH_JMP_END(DCOND_GE);
3570       } else
3571 #endif
3572       {
3573         if (blx_target_count < ARRAY_SIZE(blx_targets)) {
3574           // exit via stub in blx table (saves some 1-3 insns in the main flow)
3575           emith_cmp_r_imm(sr, 0);
3576           blx_targets[blx_target_count++] =
3577               (struct linkage) { .pc = pc, .ptr = tcache_ptr, .mask = 0x1 };
3578           emith_jump_cond_patchable(DCOND_LT, tcache_ptr);
3579         } else {
3580           // blx table full, must inline exit code
3581           tmp = rcache_get_tmp_arg(0);
3582           emith_cmp_r_imm(sr, 0);
3583           EMITH_SJMP_START(DCOND_GE);
3584           emith_move_r_imm_c(DCOND_LT, tmp, pc);
3585           emith_jump_cond(DCOND_LT, sh2_drc_exit);
3586           EMITH_SJMP_END(DCOND_GE);
3587           rcache_free_tmp(tmp);
3588         }
3589       }
3590
3591 #if (DRC_DEBUG & 32)
3592       // block hit counter
3593       tmp  = rcache_get_tmp_arg(0);
3594       tmp2 = rcache_get_tmp_arg(1);
3595       emith_move_r_ptr_imm(tmp, (uptr)entry);
3596       emith_read_r_r_offs(tmp2, tmp, offsetof(struct block_entry, entry_count));
3597       emith_add_r_imm(tmp2, 1);
3598       emith_write_r_r_offs(tmp2, tmp, offsetof(struct block_entry, entry_count));
3599       rcache_free_tmp(tmp);
3600       rcache_free_tmp(tmp2);
3601 #endif
3602
3603 #if (DRC_DEBUG & (8|256|512|1024))
3604       sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
3605       emith_sync_t(sr);
3606       rcache_clean();
3607       tmp = rcache_used_hregs_mask();
3608       emith_save_caller_regs(tmp);
3609       emit_do_static_regs(1, 0);
3610       rcache_get_reg_arg(2, SHR_SR, NULL);
3611       tmp2 = rcache_get_tmp_arg(0);
3612       tmp3 = rcache_get_tmp_arg(1);
3613       tmp4 = rcache_get_tmp();
3614       emith_move_r_ptr_imm(tmp2, tcache_ptr);
3615       emith_move_r_r_ptr(tmp3, CONTEXT_REG);
3616       emith_move_r_imm(tmp4, pc);
3617       emith_ctx_write(tmp4, SHR_PC * 4);
3618       rcache_invalidate_tmp();
3619       emith_abicall(sh2_drc_log_entry);
3620       emith_restore_caller_regs(tmp);
3621 #endif
3622
3623       do_host_disasm(tcache_id);
3624       rcache_unlock_all();
3625     }
3626
3627 #ifdef DRC_CMP
3628     if (!(op_flags[i] & OF_DELAY_OP)) {
3629       sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
3630       FLUSH_CYCLES(sr);
3631       emith_sync_t(sr);
3632       emit_move_r_imm32(SHR_PC, pc);
3633       rcache_clean();
3634
3635       tmp = rcache_used_hregs_mask();
3636       emith_save_caller_regs(tmp);
3637       emit_do_static_regs(1, 0);
3638       emith_pass_arg_r(0, CONTEXT_REG);
3639       emith_abicall(do_sh2_cmp);
3640       emith_restore_caller_regs(tmp);
3641     }
3642 #endif
3643
3644     // emit blx area if limits are approached
3645     if (blx_target_count && (blx_target_count > ARRAY_SIZE(blx_targets)-4 || 
3646         !emith_jump_patch_inrange(blx_targets[0].ptr, tcache_ptr+0x100))) {
3647       u8 *jp;
3648       rcache_invalidate_tmp();
3649       jp = tcache_ptr;
3650       emith_jump_patchable(tcache_ptr);
3651       emit_branch_linkage_code(sh2, block, tcache_id, branch_targets,
3652                           branch_target_count, blx_targets, blx_target_count);
3653       blx_target_count = 0;
3654       do_host_disasm(tcache_id);
3655       emith_jump_patch(jp, tcache_ptr, NULL);
3656     }
3657
3658     emith_pool_check();
3659
3660     opd = &ops[i];
3661     op = FETCH_OP(pc);
3662 #if (DRC_DEBUG & 4)
3663     DasmSH2(sh2dasm_buff, pc, op);
3664     if (op_flags[i] & OF_BTARGET) {
3665       if ((op_flags[i] & OF_LOOP) == OF_DELAY_LOOP)     tmp3 = '+';
3666       else if ((op_flags[i] & OF_LOOP) == OF_POLL_LOOP) tmp3 = '=';
3667       else if ((op_flags[i] & OF_LOOP) == OF_IDLE_LOOP) tmp3 = '~';
3668       else                                              tmp3 = '*';
3669     } else if (drcf.loop_type)                          tmp3 = '.';
3670     else                                                tmp3 = ' ';
3671     printf("%c%08lx %04x %s\n", tmp3, (ulong)pc, op, sh2dasm_buff);
3672 #endif
3673
3674     pc += 2;
3675 #if (DRC_DEBUG & 2)
3676     insns_compiled++;
3677 #endif
3678     if (skip_op > 0) {
3679       skip_op--;
3680       continue;
3681     }
3682
3683     if (op_flags[i] & OF_DELAY_OP)
3684     {
3685       // handle delay slot dependencies
3686       delay_dep_fw = opd->dest & ops[i-1].source;
3687       delay_dep_bk = opd->source & ops[i-1].dest;
3688       if (delay_dep_fw & BITMASK1(SHR_T)) {
3689         sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
3690         emith_sync_t(sr);
3691         DELAY_SAVE_T(sr);
3692       }
3693       if (delay_dep_bk & BITMASK1(SHR_PC)) {
3694         if (opd->op != OP_LOAD_POOL && opd->op != OP_MOVA) {
3695           // can only be those 2 really..
3696           elprintf_sh2(sh2, EL_ANOMALY,
3697             "drc: illegal slot insn %04x @ %08x?", op, pc - 2);
3698         }
3699         // store PC for MOVA/MOV @PC address calculation
3700         if (opd->imm != 0)
3701           ; // case OP_BRANCH - addr already resolved in scan_block
3702         else {
3703           switch (ops[i-1].op) {
3704           case OP_BRANCH:
3705             emit_move_r_imm32(SHR_PC, ops[i-1].imm);
3706             break;
3707           case OP_BRANCH_CT:
3708           case OP_BRANCH_CF:
3709             sr = rcache_get_reg(SHR_SR, RC_GR_READ, NULL);
3710             tmp = rcache_get_reg(SHR_PC, RC_GR_WRITE, NULL);
3711             emith_move_r_imm(tmp, pc);
3712             tmp2 = emith_tst_t(sr, (ops[i-1].op == OP_BRANCH_CT));
3713             tmp3 = emith_invert_cond(tmp2);
3714             EMITH_SJMP_START(tmp3);
3715             emith_move_r_imm_c(tmp2, tmp, ops[i-1].imm);
3716             EMITH_SJMP_END(tmp3);
3717             break;
3718           case OP_BRANCH_N: // BT/BF known not to be taken
3719             // XXX could modify opd->imm instead?
3720             emit_move_r_imm32(SHR_PC, pc);
3721             break;
3722           // case OP_BRANCH_R OP_BRANCH_RF - PC already loaded
3723           }
3724         }
3725       }
3726       //if (delay_dep_fw & ~BITMASK1(SHR_T))
3727       //  dbg(1, "unhandled delay_dep_fw: %x", delay_dep_fw & ~BITMASK1(SHR_T));
3728       if (delay_dep_bk & ~BITMASK2(SHR_PC, SHR_PR))
3729         dbg(1, "unhandled delay_dep_bk: %x", delay_dep_bk);
3730     }
3731
3732     // inform cache about future register usage
3733     u32 late = 0;             // regs read by future ops
3734     u32 write = 0;            // regs written to (to detect write before read)
3735     u32 soon = 0;             // regs read soon
3736     for (v = 1; v <= 9; v++) {
3737       // no sense in looking any further than the next rcache flush
3738       tmp = ((op_flags[i+v] & OF_BTARGET) || (op_flags[i+v-1] & OF_DELAY_OP) ||
3739                 (OP_ISBRACND(opd[v-1].op) && !(op_flags[i+v] & OF_DELAY_OP)));
3740       // XXX looking behind cond branch to avoid evicting regs used later?
3741       if (pc + 2*v <= end_pc && !tmp) { // (pc already incremented above)
3742         late |= opd[v].source & ~write;
3743         // ignore source regs after they have been written to
3744         write |= opd[v].dest;
3745         // regs needed in the next few instructions
3746         if (v <= 4)
3747           soon = late;
3748       } else
3749         break;
3750     }
3751     rcache_set_usage_now(opd[0].source);   // current insn
3752     rcache_set_usage_soon(soon);           // insns 1-4
3753     rcache_set_usage_late(late & ~soon);   // insns 5-9
3754     rcache_set_usage_discard(write & ~(late|soon));
3755     if (v <= 9)
3756       // upcoming rcache_flush, start writing back unused dirty stuff
3757       rcache_clean_masked(rcache_dirty_mask() & ~(write|opd[0].dest));
3758
3759     switch (opd->op)
3760     {
3761     case OP_BRANCH_N:
3762       // never taken, just use up cycles
3763       goto end_op;
3764     case OP_BRANCH:
3765     case OP_BRANCH_CT:
3766     case OP_BRANCH_CF:
3767       if (opd->dest & BITMASK1(SHR_PR))
3768         emit_move_r_imm32(SHR_PR, pc + 2);
3769       drcf.pending_branch_direct = 1;
3770       goto end_op;
3771
3772     case OP_BRANCH_R:
3773       if (opd->dest & BITMASK1(SHR_PR))
3774         emit_move_r_imm32(SHR_PR, pc + 2);
3775       emit_move_r_r(SHR_PC, opd->rm);
3776       drcf.pending_branch_indirect = 1;
3777       goto end_op;
3778
3779     case OP_BRANCH_RF:
3780       tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ, NULL);
3781       tmp  = rcache_get_reg(SHR_PC, RC_GR_WRITE, NULL);
3782       emith_move_r_imm(tmp, pc + 2);
3783       if (opd->dest & BITMASK1(SHR_PR)) {
3784         tmp3 = rcache_get_reg(SHR_PR, RC_GR_WRITE, NULL);
3785         emith_move_r_r(tmp3, tmp);
3786       }
3787       emith_add_r_r(tmp, tmp2);
3788       if (gconst_get(GET_Rn(), &u))
3789         gconst_set(SHR_PC, pc + 2 + u);
3790       drcf.pending_branch_indirect = 1;
3791       goto end_op;
3792
3793     case OP_SLEEP: // SLEEP      0000000000011011
3794       printf("TODO sleep\n");
3795       goto end_op;
3796
3797     case OP_RTE: // RTE        0000000000101011
3798       emith_invalidate_t();
3799       // pop PC
3800       tmp = emit_memhandler_read_rr(sh2, SHR_PC, SHR_SP, 0, 2 | MF_POSTINCR);
3801       rcache_free(tmp);
3802       // pop SR
3803       tmp = emit_memhandler_read_rr(sh2, SHR_TMP, SHR_SP, 0, 2 | MF_POSTINCR);
3804       sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
3805       emith_write_sr(sr, tmp);
3806       rcache_free_tmp(tmp);
3807       drcf.test_irq = 1;
3808       drcf.pending_branch_indirect = 1;
3809       goto end_op;
3810
3811     case OP_UNDEFINED:
3812       elprintf_sh2(sh2, EL_ANOMALY, "drc: unhandled op %04x @ %08x", op, pc-2);
3813       opd->imm = (op_flags[i] & OF_B_IN_DS) ? 6 : 4;
3814       // fallthrough
3815     case OP_TRAPA: // TRAPA #imm      11000011iiiiiiii
3816       // push SR
3817       tmp  = rcache_get_reg_arg(1, SHR_SR, &tmp2);
3818       emith_sync_t(tmp2);
3819       emith_clear_msb(tmp, tmp2, 22);
3820       emit_memhandler_write_rr(sh2, SHR_TMP, SHR_SP, 0, 2 | MF_PREDECR);
3821       // push PC
3822       if (opd->op == OP_TRAPA) {
3823         tmp = rcache_get_tmp_arg(1);
3824         emith_move_r_imm(tmp, pc);
3825       } else if (drcf.pending_branch_indirect) {
3826         tmp = rcache_get_reg_arg(1, SHR_PC, NULL);
3827       } else {
3828         tmp = rcache_get_tmp_arg(1);
3829         emith_move_r_imm(tmp, pc - 2);
3830       }
3831       emit_memhandler_write_rr(sh2, SHR_TMP, SHR_SP, 0, 2 | MF_PREDECR);
3832       // obtain new PC
3833       emit_memhandler_read_rr(sh2, SHR_PC, SHR_VBR, opd->imm * 4, 2);
3834       // indirect jump -> back to dispatcher
3835       drcf.pending_branch_indirect = 1;
3836       goto end_op;
3837
3838     case OP_LOAD_POOL:
3839 #if PROPAGATE_CONSTANTS
3840       if ((opd->imm && opd->imm >= base_pc && opd->imm < end_literals) ||
3841           p32x_sh2_mem_is_rom(opd->imm, sh2))
3842       {
3843         if (opd->size == 2)
3844           u = FETCH32(opd->imm);
3845         else
3846           u = (s16)FETCH_OP(opd->imm);
3847         gconst_new(GET_Rn(), u);
3848       }
3849       else
3850 #endif
3851       {
3852         if (opd->imm != 0) {
3853           tmp = rcache_get_tmp_arg(0);
3854           emith_move_r_imm(tmp, opd->imm);
3855         } else {
3856           // have to calculate read addr from PC for delay slot
3857           tmp = rcache_get_reg_arg(0, SHR_PC, &tmp2);
3858           if (opd->size == 2) {
3859             emith_add_r_r_imm(tmp, tmp2, 2 + (op & 0xff) * 4);
3860             emith_bic_r_imm(tmp, 3);
3861           }
3862           else
3863             emith_add_r_r_imm(tmp, tmp2, 2 + (op & 0xff) * 2);
3864         }
3865         tmp2 = emit_memhandler_read(opd->size);
3866         tmp3 = rcache_map_reg(GET_Rn(), tmp2);
3867         if (tmp3 != tmp2) {
3868           emith_move_r_r(tmp3, tmp2);
3869           rcache_free_tmp(tmp2);
3870         }
3871       }
3872       goto end_op;
3873
3874     case OP_MOVA: // MOVA @(disp,PC),R0    11000111dddddddd
3875       if (opd->imm != 0)
3876         emit_move_r_imm32(SHR_R0, opd->imm);
3877       else {
3878         // have to calculate addr from PC for delay slot
3879         tmp2 = rcache_get_reg(SHR_PC, RC_GR_READ, NULL);
3880         tmp = rcache_get_reg(SHR_R0, RC_GR_WRITE, NULL);
3881         emith_add_r_r_imm(tmp, tmp2, 2 + (op & 0xff) * 4);
3882         emith_bic_r_imm(tmp, 3);
3883       }
3884       goto end_op;
3885     }
3886
3887     switch ((op >> 12) & 0x0f)
3888     {
3889     /////////////////////////////////////////////
3890     case 0x00:
3891       switch (op & 0x0f)
3892       {
3893       case 0x02:
3894         switch (GET_Fx())
3895         {
3896         case 0: // STC SR,Rn  0000nnnn00000010
3897           tmp2 = SHR_SR;
3898           break;
3899         case 1: // STC GBR,Rn 0000nnnn00010010
3900           tmp2 = SHR_GBR;
3901           break;
3902         case 2: // STC VBR,Rn 0000nnnn00100010
3903           tmp2 = SHR_VBR;
3904           break;
3905         default:
3906           goto default_;
3907         }
3908         if (tmp2 == SHR_SR) {
3909           sr = rcache_get_reg(SHR_SR, RC_GR_READ, NULL);
3910           emith_sync_t(sr);
3911           tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE, NULL);
3912           emith_clear_msb(tmp, sr, 22); // reserved bits defined by ISA as 0
3913         } else
3914           emit_move_r_r(GET_Rn(), tmp2);
3915         goto end_op;
3916       case 0x04: // MOV.B Rm,@(R0,Rn)   0000nnnnmmmm0100
3917       case 0x05: // MOV.W Rm,@(R0,Rn)   0000nnnnmmmm0101
3918       case 0x06: // MOV.L Rm,@(R0,Rn)   0000nnnnmmmm0110
3919         sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
3920         FLUSH_CYCLES(sr);
3921         emit_indirect_indexed_write(sh2, GET_Rm(), SHR_R0, GET_Rn(), op & 3);
3922         goto end_op;
3923       case 0x07: // MUL.L     Rm,Rn      0000nnnnmmmm0111
3924         tmp  = rcache_get_reg(GET_Rn(), RC_GR_READ, NULL);
3925         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
3926         tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE, NULL);
3927         emith_mul(tmp3, tmp2, tmp);
3928         goto end_op;
3929       case 0x08:
3930         switch (GET_Fx())
3931         {
3932         case 0: // CLRT               0000000000001000
3933           sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
3934 #if T_OPTIMIZER
3935           if (~rcache_regs_discard & BITMASK1(SHR_T))
3936 #endif
3937             emith_set_t(sr, 0);
3938           break;
3939         case 1: // SETT               0000000000011000
3940           sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
3941 #if T_OPTIMIZER
3942           if (~rcache_regs_discard & BITMASK1(SHR_T))
3943 #endif
3944             emith_set_t(sr, 1);
3945           break;
3946         case 2: // CLRMAC             0000000000101000
3947           emit_move_r_imm32(SHR_MACL, 0);
3948           emit_move_r_imm32(SHR_MACH, 0);
3949           break;
3950         default:
3951           goto default_;
3952         }
3953         goto end_op;
3954       case 0x09:
3955         switch (GET_Fx())
3956         {
3957         case 0: // NOP        0000000000001001
3958           break;
3959         case 1: // DIV0U      0000000000011001
3960           sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
3961           emith_invalidate_t();
3962           emith_bic_r_imm(sr, M|Q|T);
3963           drcf.Mflag = FLG_0;
3964 #if DIV_OPTIMIZER
3965           if (div(opd).div1 == 16 && div(opd).ro == div(opd).rn) {
3966             // divide 32/16
3967             rcache_get_reg_arg(0, div(opd).rn, NULL);
3968             rcache_get_reg_arg(2, div(opd).rm, NULL);
3969             tmp = rcache_get_tmp_arg(1);
3970             emith_add_r_r_ptr_imm(tmp, CONTEXT_REG, offsetof(SH2, drc_tmp));
3971             rcache_invalidate_tmp();
3972             emith_abicall(sh2_drc_divu32);
3973             tmp = rcache_get_tmp_ret();
3974             tmp2 = rcache_map_reg(div(opd).rn, tmp);
3975             if (tmp != tmp2)
3976               emith_move_r_r(tmp2, tmp);
3977
3978             tmp3  = rcache_get_tmp();
3979             emith_and_r_r_imm(tmp3, tmp2, 1);     // Q = !Rn[0]
3980             emith_eor_r_r_imm(tmp3, tmp3, 1);
3981             emith_or_r_r_lsl(sr, tmp3, Q_SHIFT);
3982             emith_ctx_read(tmp3, offsetof(SH2, drc_tmp));
3983             emith_or_r_r_r(sr, sr, tmp3);         // T
3984             rcache_free_tmp(tmp3);
3985             skip_op = div(opd).div1 + div(opd).rotcl;
3986             cycles += skip_op;
3987           }
3988           else if (div(opd).div1 == 32 && div(opd).ro != div(opd).rn) {
3989             // divide 64/32
3990             tmp4 = rcache_get_reg(div(opd).ro, RC_GR_READ, NULL);
3991             emith_ctx_write(tmp4, offsetof(SH2, drc_tmp));
3992             rcache_free(tmp4);
3993             rcache_get_reg_arg(0, div(opd).rn, NULL);
3994             rcache_get_reg_arg(2, div(opd).rm, NULL);
3995             tmp = rcache_get_tmp_arg(1);
3996             emith_add_r_r_ptr_imm(tmp, CONTEXT_REG, offsetof(SH2, drc_tmp));
3997             rcache_invalidate_tmp();
3998             emith_abicall(sh2_drc_divu64);
3999             tmp = rcache_get_tmp_ret();
4000             tmp2 = rcache_map_reg(div(opd).rn, tmp);
4001             tmp4 = rcache_get_reg(div(opd).ro, RC_GR_WRITE, NULL);
4002             if (tmp != tmp2)
4003               emith_move_r_r(tmp2, tmp);
4004             emith_ctx_read(tmp4, offsetof(SH2, drc_tmp));
4005
4006             tmp3  = rcache_get_tmp();
4007             emith_and_r_r_imm(tmp3, tmp4, 1);     // Q = !Ro[0]
4008             emith_eor_r_r_imm(tmp3, tmp3, 1);
4009             emith_or_r_r_lsl(sr, tmp3, Q_SHIFT);
4010             rcache_free_tmp(tmp3);
4011             skip_op = div(opd).div1 + div(opd).rotcl;
4012             cycles += skip_op;
4013           }
4014 #endif
4015           break;
4016         case 2: // MOVT Rn    0000nnnn00101001
4017           sr   = rcache_get_reg(SHR_SR, RC_GR_READ, NULL);
4018           emith_sync_t(sr);
4019           tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE, NULL);
4020           emith_clear_msb(tmp2, sr, 31);
4021           break;
4022         default:
4023           goto default_;
4024         }
4025         goto end_op;
4026       case 0x0a:
4027         switch (GET_Fx())
4028         {
4029         case 0: // STS      MACH,Rn   0000nnnn00001010
4030           tmp2 = SHR_MACH;
4031           break;
4032         case 1: // STS      MACL,Rn   0000nnnn00011010
4033           tmp2 = SHR_MACL;
4034           break;
4035         case 2: // STS      PR,Rn     0000nnnn00101010
4036           tmp2 = SHR_PR;
4037           break;
4038         default:
4039           goto default_;
4040         }
4041         emit_move_r_r(GET_Rn(), tmp2);
4042         goto end_op;
4043       case 0x0c: // MOV.B    @(R0,Rm),Rn      0000nnnnmmmm1100
4044       case 0x0d: // MOV.W    @(R0,Rm),Rn      0000nnnnmmmm1101
4045       case 0x0e: // MOV.L    @(R0,Rm),Rn      0000nnnnmmmm1110
4046         sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4047         FLUSH_CYCLES(sr);
4048         emit_indirect_indexed_read(sh2, GET_Rn(), SHR_R0, GET_Rm(), (op & 3) | drcf.polling);
4049         goto end_op;
4050       case 0x0f: // MAC.L   @Rm+,@Rn+  0000nnnnmmmm1111
4051         emit_indirect_read_double(sh2, &tmp, &tmp2, GET_Rn(), GET_Rm(), 2);
4052         sr = rcache_get_reg(SHR_SR, RC_GR_READ, NULL);
4053         tmp3 = rcache_get_reg(SHR_MACL, RC_GR_RMW, NULL);
4054         tmp4 = rcache_get_reg(SHR_MACH, RC_GR_RMW, NULL);
4055         emith_sh2_macl(tmp3, tmp4, tmp, tmp2, sr);
4056         rcache_free_tmp(tmp2);
4057         rcache_free_tmp(tmp);
4058         goto end_op;
4059       }
4060       goto default_;
4061
4062     /////////////////////////////////////////////
4063     case 0x01: // MOV.L Rm,@(disp,Rn) 0001nnnnmmmmdddd
4064       sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4065       FLUSH_CYCLES(sr);
4066       emit_memhandler_write_rr(sh2, GET_Rm(), GET_Rn(), (op & 0x0f) * 4, 2);
4067       goto end_op;
4068
4069     case 0x02:
4070       switch (op & 0x0f)
4071       {
4072       case 0x00: // MOV.B Rm,@Rn        0010nnnnmmmm0000
4073       case 0x01: // MOV.W Rm,@Rn        0010nnnnmmmm0001
4074       case 0x02: // MOV.L Rm,@Rn        0010nnnnmmmm0010
4075         sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4076         FLUSH_CYCLES(sr);
4077         emit_memhandler_write_rr(sh2, GET_Rm(), GET_Rn(), 0, op & 3);
4078         goto end_op;
4079       case 0x04: // MOV.B Rm,@-Rn       0010nnnnmmmm0100
4080       case 0x05: // MOV.W Rm,@-Rn       0010nnnnmmmm0101
4081       case 0x06: // MOV.L Rm,@-Rn       0010nnnnmmmm0110
4082         sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4083         FLUSH_CYCLES(sr);
4084         emit_memhandler_write_rr(sh2, GET_Rm(), GET_Rn(), 0, (op & 3) | MF_PREDECR);
4085         goto end_op;
4086       case 0x07: // DIV0S Rm,Rn         0010nnnnmmmm0111
4087         sr   = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4088         emith_invalidate_t();
4089         emith_bic_r_imm(sr, M|Q|T);
4090         drcf.Mflag = FLG_UNKNOWN;
4091 #if DIV_OPTIMIZER
4092         if (div(opd).div1 == 16 && div(opd).ro == div(opd).rn) {
4093           // divide 32/16
4094           tmp = rcache_get_reg_arg(0, div(opd).rn, NULL);
4095           tmp2 = rcache_get_reg_arg(2, div(opd).rm, NULL);
4096           tmp3 = rcache_get_tmp_arg(1);
4097           emith_lsr(tmp3, tmp2, 31);
4098           emith_or_r_r_lsl(sr, tmp3, M_SHIFT);        // M = Rm[31]
4099           emith_add_r_r_ptr_imm(tmp3, CONTEXT_REG, offsetof(SH2, drc_tmp));
4100           rcache_invalidate_tmp();
4101           emith_abicall(sh2_drc_divs32);
4102           tmp = rcache_get_tmp_ret();
4103           tmp2 = rcache_map_reg(div(opd).rn, tmp);
4104           if (tmp != tmp2)
4105             emith_move_r_r(tmp2, tmp);
4106           tmp3  = rcache_get_tmp();
4107
4108           emith_eor_r_r_r_lsr(tmp3, tmp2, sr, M_SHIFT);
4109           emith_and_r_r_imm(tmp3, tmp3, 1);
4110           emith_eor_r_r_imm(tmp3, tmp3, 1);
4111           emith_or_r_r_lsl(sr, tmp3, Q_SHIFT);        // Q = !Rn[0]^M
4112           emith_ctx_read(tmp3, offsetof(SH2, drc_tmp));
4113           emith_or_r_r_r(sr, sr, tmp3);               // T
4114           rcache_free_tmp(tmp3);
4115           skip_op = div(opd).div1 + div(opd).rotcl;
4116           cycles += skip_op;
4117         }
4118         else if (div(opd).div1 == 32 && div(opd).ro != div(opd).rn) {
4119           // divide 64/32
4120           tmp4 = rcache_get_reg(div(opd).ro, RC_GR_READ, NULL);
4121           emith_ctx_write(tmp4, offsetof(SH2, drc_tmp));
4122           rcache_free(tmp4);
4123           tmp  = rcache_get_reg_arg(0, div(opd).rn, NULL);
4124           tmp2 = rcache_get_reg_arg(2, div(opd).rm, NULL);
4125           tmp3 = rcache_get_tmp_arg(1);
4126           emith_lsr(tmp3, tmp2, 31);
4127           emith_or_r_r_lsl(sr, tmp3, M_SHIFT);        // M = Rm[31]
4128           emith_eor_r_r_lsr(tmp3, tmp, 31);
4129           emith_or_r_r(sr, tmp3);                     // T = Rn[31]^M
4130           emith_add_r_r_ptr_imm(tmp3, CONTEXT_REG, offsetof(SH2, drc_tmp));
4131           rcache_invalidate_tmp();
4132           emith_abicall(sh2_drc_divs64);
4133           tmp = rcache_get_tmp_ret();
4134           tmp2 = rcache_map_reg(div(opd).rn, tmp);
4135           tmp4 = rcache_get_reg(div(opd).ro, RC_GR_WRITE, NULL);
4136           if (tmp != tmp2)
4137             emith_move_r_r(tmp2, tmp);
4138           emith_ctx_read(tmp4, offsetof(SH2, drc_tmp));
4139
4140           tmp3  = rcache_get_tmp();
4141           emith_eor_r_r_r_lsr(tmp3, tmp4, sr, M_SHIFT);
4142           emith_and_r_r_imm(tmp3, tmp3, 1);
4143           emith_eor_r_r_imm(tmp3, tmp3, 1);
4144           emith_or_r_r_lsl(sr, tmp3, Q_SHIFT);        // Q = !Ro[0]^M
4145           rcache_free_tmp(tmp3);
4146           skip_op = div(opd).div1 + div(opd).rotcl;
4147           cycles += skip_op;
4148         } else
4149 #endif
4150         {
4151           tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ, NULL);
4152           tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
4153           tmp  = rcache_get_tmp();
4154           emith_lsr(tmp, tmp2, 31);       // Q = Nn
4155           emith_or_r_r_lsl(sr, tmp, Q_SHIFT);
4156           emith_lsr(tmp, tmp3, 31);       // M = Nm
4157           emith_or_r_r_lsl(sr, tmp, M_SHIFT);
4158           emith_eor_r_r_lsr(tmp, tmp2, 31);
4159           emith_or_r_r(sr, tmp);          // T = Q^M
4160           rcache_free(tmp);
4161         }
4162         goto end_op;
4163       case 0x08: // TST Rm,Rn           0010nnnnmmmm1000
4164         sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4165         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ, NULL);
4166         tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
4167         emith_clr_t_cond(sr);
4168         emith_tst_r_r(tmp2, tmp3);
4169         emith_set_t_cond(sr, DCOND_EQ);
4170         goto end_op;
4171       case 0x09: // AND Rm,Rn           0010nnnnmmmm1001
4172         if (GET_Rm() != GET_Rn()) {
4173           tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
4174           tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW, &tmp3);
4175           emith_and_r_r_r(tmp, tmp3, tmp2);
4176         }
4177         goto end_op;
4178       case 0x0a: // XOR Rm,Rn           0010nnnnmmmm1010
4179 #if PROPAGATE_CONSTANTS
4180         if (GET_Rn() == GET_Rm()) {
4181           gconst_new(GET_Rn(), 0);
4182           goto end_op;
4183         }
4184 #endif
4185         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
4186         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW, &tmp3);
4187         emith_eor_r_r_r(tmp, tmp3, tmp2);
4188         goto end_op;
4189       case 0x0b: // OR  Rm,Rn           0010nnnnmmmm1011
4190         if (GET_Rm() != GET_Rn()) {
4191           tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
4192           tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW, &tmp3);
4193           emith_or_r_r_r(tmp, tmp3, tmp2);
4194         }
4195         goto end_op;
4196       case 0x0c: // CMP/STR Rm,Rn       0010nnnnmmmm1100
4197         tmp  = rcache_get_tmp();
4198         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ, NULL);
4199         tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
4200         emith_eor_r_r_r(tmp, tmp2, tmp3);
4201         sr   = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4202         emith_clr_t_cond(sr);
4203         emith_tst_r_imm(tmp, 0x000000ff);
4204         EMITH_SJMP_START(DCOND_EQ);
4205         emith_tst_r_imm_c(DCOND_NE, tmp, 0x0000ff00);
4206         EMITH_SJMP_START(DCOND_EQ);
4207         emith_tst_r_imm_c(DCOND_NE, tmp, 0x00ff0000);
4208         EMITH_SJMP_START(DCOND_EQ);
4209         emith_tst_r_imm_c(DCOND_NE, tmp, 0xff000000);
4210         EMITH_SJMP_END(DCOND_EQ);
4211         EMITH_SJMP_END(DCOND_EQ);
4212         EMITH_SJMP_END(DCOND_EQ);
4213         emith_set_t_cond(sr, DCOND_EQ);
4214         rcache_free_tmp(tmp);
4215         goto end_op;
4216       case 0x0d: // XTRCT  Rm,Rn        0010nnnnmmmm1101
4217         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
4218         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW, &tmp3);
4219         emith_lsr(tmp, tmp3, 16);
4220         emith_or_r_r_lsl(tmp, tmp2, 16);
4221         goto end_op;
4222       case 0x0e: // MULU.W Rm,Rn        0010nnnnmmmm1110
4223       case 0x0f: // MULS.W Rm,Rn        0010nnnnmmmm1111
4224         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ, NULL);
4225         tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
4226         tmp  = rcache_get_reg(SHR_MACL, RC_GR_WRITE, NULL);
4227         tmp4 = tmp3;
4228         if (op & 1) {
4229           if (! rcache_is_s16(tmp2)) {
4230             emith_sext(tmp, tmp2, 16);
4231             tmp2 = tmp;
4232           }
4233           if (! rcache_is_s16(tmp3)) {
4234             tmp4 = rcache_get_tmp();
4235             emith_sext(tmp4, tmp3, 16);
4236           }
4237         } else {
4238           if (! rcache_is_u16(tmp2)) {
4239             emith_clear_msb(tmp, tmp2, 16);
4240             tmp2 = tmp;
4241           }
4242           if (! rcache_is_u16(tmp3)) {
4243             tmp4 = rcache_get_tmp();
4244             emith_clear_msb(tmp4, tmp3, 16);
4245           }
4246         }
4247         emith_mul(tmp, tmp2, tmp4);
4248         if (tmp4 != tmp3)
4249           rcache_free_tmp(tmp4);
4250         goto end_op;
4251       }
4252       goto default_;
4253
4254     /////////////////////////////////////////////
4255     case 0x03:
4256       switch (op & 0x0f)
4257       {
4258       case 0x00: // CMP/EQ Rm,Rn        0011nnnnmmmm0000
4259       case 0x02: // CMP/HS Rm,Rn        0011nnnnmmmm0010
4260       case 0x03: // CMP/GE Rm,Rn        0011nnnnmmmm0011
4261       case 0x06: // CMP/HI Rm,Rn        0011nnnnmmmm0110
4262       case 0x07: // CMP/GT Rm,Rn        0011nnnnmmmm0111
4263         sr   = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4264         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ, NULL);
4265         tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
4266         switch (op & 0x07)
4267         {
4268         case 0x00: // CMP/EQ
4269           tmp = DCOND_EQ;
4270           break;
4271         case 0x02: // CMP/HS
4272           tmp = DCOND_HS;
4273           break;
4274         case 0x03: // CMP/GE
4275           tmp = DCOND_GE;
4276           break;
4277         case 0x06: // CMP/HI
4278           tmp = DCOND_HI;
4279           break;
4280         case 0x07: // CMP/GT
4281           tmp = DCOND_GT;
4282           break;
4283         }
4284         emith_clr_t_cond(sr);
4285         emith_cmp_r_r(tmp2, tmp3);
4286         emith_set_t_cond(sr, tmp);
4287         goto end_op;
4288       case 0x04: // DIV1    Rm,Rn       0011nnnnmmmm0100
4289         // Q1 = carry(Rn = (Rn << 1) | T)
4290         // if Q ^ M
4291         //   Q2 = carry(Rn += Rm)
4292         // else
4293         //   Q2 = carry(Rn -= Rm)
4294         // Q = M ^ Q1 ^ Q2
4295         // T = (Q == M) = !(Q ^ M) = !(Q1 ^ Q2)
4296         tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
4297         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_RMW, NULL);
4298         sr   = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4299         emith_sync_t(sr);
4300         tmp = rcache_get_tmp();
4301         if (drcf.Mflag != FLG_0) {
4302           emith_and_r_r_imm(tmp, sr, M);
4303           emith_eor_r_r_lsr(sr, tmp, M_SHIFT - Q_SHIFT); // Q ^= M
4304         }
4305         rcache_free_tmp(tmp);
4306         // shift Rn, add T, add or sub Rm, set T = !(Q1 ^ Q2)
4307         // in: (Q ^ M) passed in Q
4308         emith_sh2_div1_step(tmp2, tmp3, sr);
4309         tmp = rcache_get_tmp();
4310         emith_or_r_imm(sr, Q);              // Q = !T
4311         emith_and_r_r_imm(tmp, sr, T);
4312         emith_eor_r_r_lsl(sr, tmp, Q_SHIFT);
4313         if (drcf.Mflag != FLG_0) {          // Q = M ^ !T = M ^ Q1 ^ Q2
4314           emith_and_r_r_imm(tmp, sr, M);
4315           emith_eor_r_r_lsr(sr, tmp, M_SHIFT - Q_SHIFT);
4316         }
4317         rcache_free_tmp(tmp);
4318         goto end_op;
4319       case 0x05: // DMULU.L Rm,Rn       0011nnnnmmmm0101
4320         tmp  = rcache_get_reg(GET_Rn(), RC_GR_READ, NULL);
4321         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
4322         tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE, NULL);
4323         tmp4 = rcache_get_reg(SHR_MACH, RC_GR_WRITE, NULL);
4324         emith_mul_u64(tmp3, tmp4, tmp, tmp2);
4325         goto end_op;
4326       case 0x08: // SUB     Rm,Rn       0011nnnnmmmm1000
4327 #if PROPAGATE_CONSTANTS
4328         if (GET_Rn() == GET_Rm()) {
4329           gconst_new(GET_Rn(), 0);
4330           goto end_op;
4331         }
4332 #endif
4333       case 0x0c: // ADD     Rm,Rn       0011nnnnmmmm1100
4334         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
4335         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW, &tmp3);
4336         if (op & 4) {
4337           emith_add_r_r_r(tmp, tmp3, tmp2);
4338         } else
4339           emith_sub_r_r_r(tmp, tmp3, tmp2);
4340         goto end_op;
4341       case 0x0a: // SUBC    Rm,Rn       0011nnnnmmmm1010
4342       case 0x0e: // ADDC    Rm,Rn       0011nnnnmmmm1110
4343         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
4344         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW, &tmp3);
4345         sr   = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4346         emith_sync_t(sr);
4347 #if T_OPTIMIZER
4348         if (rcache_regs_discard & BITMASK1(SHR_T)) {
4349           if (op & 4) {
4350             emith_t_to_carry(sr, 0);
4351             emith_adc_r_r_r(tmp, tmp3, tmp2);
4352           } else {
4353             emith_t_to_carry(sr, 1);
4354             emith_sbc_r_r_r(tmp, tmp3, tmp2);
4355           }
4356         } else
4357 #endif
4358         {
4359           EMITH_HINT_COND(DCOND_CS);
4360           if (op & 4) { // adc
4361             emith_tpop_carry(sr, 0);
4362             emith_adcf_r_r_r(tmp, tmp3, tmp2);
4363             emith_tpush_carry(sr, 0);
4364           } else {
4365             emith_tpop_carry(sr, 1);
4366             emith_sbcf_r_r_r(tmp, tmp3, tmp2);
4367             emith_tpush_carry(sr, 1);
4368           }
4369         }
4370         goto end_op;
4371       case 0x0b: // SUBV    Rm,Rn       0011nnnnmmmm1011
4372       case 0x0f: // ADDV    Rm,Rn       0011nnnnmmmm1111
4373         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
4374         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW, &tmp3);
4375         sr   = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4376 #if T_OPTIMIZER
4377         if (rcache_regs_discard & BITMASK1(SHR_T)) {
4378           if (op & 4)
4379             emith_add_r_r_r(tmp,tmp3,tmp2);
4380           else
4381             emith_sub_r_r_r(tmp,tmp3,tmp2);
4382         } else
4383 #endif
4384         {
4385           emith_clr_t_cond(sr);
4386           EMITH_HINT_COND(DCOND_VS);
4387           if (op & 4)
4388             emith_addf_r_r_r(tmp, tmp3, tmp2);
4389           else
4390             emith_subf_r_r_r(tmp, tmp3, tmp2);
4391           emith_set_t_cond(sr, DCOND_VS);
4392         }
4393         goto end_op;
4394       case 0x0d: // DMULS.L Rm,Rn       0011nnnnmmmm1101
4395         tmp  = rcache_get_reg(GET_Rn(), RC_GR_READ, NULL);
4396         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
4397         tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE, NULL);
4398         tmp4 = rcache_get_reg(SHR_MACH, RC_GR_WRITE, NULL);
4399         emith_mul_s64(tmp3, tmp4, tmp, tmp2);
4400         goto end_op;
4401       }
4402       goto default_;
4403
4404     /////////////////////////////////////////////
4405     case 0x04:
4406       switch (op & 0x0f)
4407       {
4408       case 0x00:
4409         switch (GET_Fx())
4410         {
4411         case 0: // SHLL Rn    0100nnnn00000000
4412         case 2: // SHAL Rn    0100nnnn00100000
4413           tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW, &tmp2);
4414           sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4415 #if T_OPTIMIZER
4416           if (rcache_regs_discard & BITMASK1(SHR_T))
4417             emith_lsl(tmp, tmp2, 1);
4418           else
4419 #endif
4420           {
4421             emith_invalidate_t();
4422             emith_lslf(tmp, tmp2, 1);
4423             emith_carry_to_t(sr, 0);
4424           }
4425           goto end_op;
4426         case 1: // DT Rn      0100nnnn00010000
4427           sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4428 #if LOOP_DETECTION
4429           if (drcf.loop_type == OF_DELAY_LOOP) {
4430             if (drcf.delay_reg == -1)
4431               drcf.delay_reg = GET_Rn();
4432             else
4433               drcf.polling = drcf.loop_type = 0;
4434           }
4435 #endif
4436           tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW, &tmp2);
4437           emith_clr_t_cond(sr);
4438           EMITH_HINT_COND(DCOND_EQ);
4439           emith_subf_r_r_imm(tmp, tmp2, 1);
4440           emith_set_t_cond(sr, DCOND_EQ);
4441           emith_or_r_imm(sr, SH2_NO_POLLING);
4442           goto end_op;
4443         }
4444         goto default_;
4445       case 0x01:
4446         switch (GET_Fx())
4447         {
4448         case 0: // SHLR Rn    0100nnnn00000001
4449         case 2: // SHAR Rn    0100nnnn00100001
4450           tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW, &tmp2);
4451           sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4452 #if T_OPTIMIZER
4453           if (rcache_regs_discard & BITMASK1(SHR_T)) {
4454             if (op & 0x20)
4455               emith_asr(tmp,tmp2,1);
4456             else
4457               emith_lsr(tmp,tmp2,1);
4458           } else
4459 #endif
4460           {
4461             emith_invalidate_t();
4462             if (op & 0x20) {
4463               emith_asrf(tmp, tmp2, 1);
4464             } else
4465               emith_lsrf(tmp, tmp2, 1);
4466             emith_carry_to_t(sr, 0);
4467           }
4468           goto end_op;
4469         case 1: // CMP/PZ Rn  0100nnnn00010001
4470           tmp = rcache_get_reg(GET_Rn(), RC_GR_READ, NULL);
4471           sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4472           emith_clr_t_cond(sr);
4473           emith_cmp_r_imm(tmp, 0);
4474           emith_set_t_cond(sr, DCOND_GE);
4475           goto end_op;
4476         }
4477         goto default_;
4478       case 0x02:
4479       case 0x03:
4480         switch (op & 0x3f)
4481         {
4482         case 0x02: // STS.L    MACH,@-Rn 0100nnnn00000010
4483           tmp = SHR_MACH;
4484           break;
4485         case 0x12: // STS.L    MACL,@-Rn 0100nnnn00010010
4486           tmp = SHR_MACL;
4487           break;
4488         case 0x22: // STS.L    PR,@-Rn   0100nnnn00100010
4489           tmp = SHR_PR;
4490           break;
4491         case 0x03: // STC.L    SR,@-Rn   0100nnnn00000011
4492           tmp = SHR_SR;
4493           break;
4494         case 0x13: // STC.L    GBR,@-Rn  0100nnnn00010011
4495           tmp = SHR_GBR;
4496           break;
4497         case 0x23: // STC.L    VBR,@-Rn  0100nnnn00100011
4498           tmp = SHR_VBR;
4499           break;
4500         default:
4501           goto default_;
4502         }
4503         if (tmp == SHR_SR) {
4504           tmp3 = rcache_get_reg_arg(1, tmp, &tmp4);
4505           emith_sync_t(tmp4);
4506           emith_clear_msb(tmp3, tmp4, 22); // reserved bits defined by ISA as 0
4507         } else
4508           tmp3 = rcache_get_reg_arg(1, tmp, NULL);
4509         emit_memhandler_write_rr(sh2, SHR_TMP, GET_Rn(), 0, 2 | MF_PREDECR);
4510         goto end_op;
4511       case 0x04:
4512       case 0x05:
4513         switch (op & 0x3f)
4514         {
4515         case 0x04: // ROTL   Rn          0100nnnn00000100
4516         case 0x05: // ROTR   Rn          0100nnnn00000101
4517           tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW, &tmp2);
4518           sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4519 #if T_OPTIMIZER
4520           if (rcache_regs_discard & BITMASK1(SHR_T)) {
4521             if (op & 1)
4522               emith_ror(tmp, tmp2, 1);
4523             else
4524               emith_rol(tmp, tmp2, 1);
4525           } else
4526 #endif
4527           {
4528             emith_invalidate_t();
4529             if (op & 1)
4530               emith_rorf(tmp, tmp2, 1);
4531             else
4532               emith_rolf(tmp, tmp2, 1);
4533             emith_carry_to_t(sr, 0);
4534           }
4535           goto end_op;
4536         case 0x24: // ROTCL  Rn          0100nnnn00100100
4537         case 0x25: // ROTCR  Rn          0100nnnn00100101
4538           tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW, NULL);
4539           sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4540           emith_sync_t(sr);
4541 #if T_OPTIMIZER
4542           if (rcache_regs_discard & BITMASK1(SHR_T)) {
4543             emith_t_to_carry(sr, 0);
4544             if (op & 1)
4545               emith_rorc(tmp);
4546             else
4547               emith_rolc(tmp);
4548           } else
4549 #endif
4550           {
4551             emith_tpop_carry(sr, 0);
4552             if (op & 1)
4553               emith_rorcf(tmp);
4554             else
4555               emith_rolcf(tmp);
4556             emith_tpush_carry(sr, 0);
4557           }
4558           goto end_op;
4559         case 0x15: // CMP/PL Rn          0100nnnn00010101
4560           tmp = rcache_get_reg(GET_Rn(), RC_GR_READ, NULL);
4561           sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4562           emith_clr_t_cond(sr);
4563           emith_cmp_r_imm(tmp, 0);
4564           emith_set_t_cond(sr, DCOND_GT);
4565           goto end_op;
4566         }
4567         goto default_;
4568       case 0x06:
4569       case 0x07:
4570         switch (op & 0x3f)
4571         {
4572         case 0x06: // LDS.L @Rm+,MACH 0100mmmm00000110
4573           tmp = SHR_MACH;
4574           break;
4575         case 0x16: // LDS.L @Rm+,MACL 0100mmmm00010110
4576           tmp = SHR_MACL;
4577           break;
4578         case 0x26: // LDS.L @Rm+,PR   0100mmmm00100110
4579           tmp = SHR_PR;
4580           break;
4581         case 0x07: // LDC.L @Rm+,SR   0100mmmm00000111
4582           tmp = SHR_SR;
4583           break;
4584         case 0x17: // LDC.L @Rm+,GBR  0100mmmm00010111
4585           tmp = SHR_GBR;
4586           break;
4587         case 0x27: // LDC.L @Rm+,VBR  0100mmmm00100111
4588           tmp = SHR_VBR;
4589           break;
4590         default:
4591           goto default_;
4592         }
4593         if (tmp == SHR_SR) {
4594           emith_invalidate_t();
4595           tmp2 = emit_memhandler_read_rr(sh2, SHR_TMP, GET_Rn(), 0, 2 | MF_POSTINCR);
4596           sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4597           emith_write_sr(sr, tmp2);
4598           rcache_free_tmp(tmp2);
4599           drcf.test_irq = 1;
4600         } else
4601           emit_memhandler_read_rr(sh2, tmp, GET_Rn(), 0, 2 | MF_POSTINCR);
4602         goto end_op;
4603       case 0x08:
4604       case 0x09:
4605         switch (GET_Fx())
4606         {
4607         case 0: // SHLL2 Rn        0100nnnn00001000
4608                 // SHLR2 Rn        0100nnnn00001001
4609           tmp = 2;
4610           break;
4611         case 1: // SHLL8 Rn        0100nnnn00011000
4612                 // SHLR8 Rn        0100nnnn00011001
4613           tmp = 8;
4614           break;
4615         case 2: // SHLL16 Rn       0100nnnn00101000
4616                 // SHLR16 Rn       0100nnnn00101001
4617           tmp = 16;
4618           break;
4619         default:
4620           goto default_;
4621         }
4622         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_RMW, &tmp3);
4623         if (op & 1) {
4624           emith_lsr(tmp2, tmp3, tmp);
4625         } else
4626           emith_lsl(tmp2, tmp3, tmp);
4627         goto end_op;
4628       case 0x0a:
4629         switch (GET_Fx())
4630         {
4631         case 0: // LDS      Rm,MACH   0100mmmm00001010
4632           tmp2 = SHR_MACH;
4633           break;
4634         case 1: // LDS      Rm,MACL   0100mmmm00011010
4635           tmp2 = SHR_MACL;
4636           break;
4637         case 2: // LDS      Rm,PR     0100mmmm00101010
4638           tmp2 = SHR_PR;
4639           break;
4640         default:
4641           goto default_;
4642         }
4643         emit_move_r_r(tmp2, GET_Rn());
4644         goto end_op;
4645       case 0x0b:
4646         switch (GET_Fx())
4647         {
4648         case 1: // TAS.B @Rn  0100nnnn00011011
4649           // XXX: is TAS working on 32X?
4650           sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4651           FLUSH_CYCLES(sr);
4652           rcache_get_reg_arg(0, GET_Rn(), NULL);
4653           tmp = emit_memhandler_read(0);
4654           sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4655           emith_clr_t_cond(sr);
4656           emith_cmp_r_imm(tmp, 0);
4657           emith_set_t_cond(sr, DCOND_EQ);
4658           emith_or_r_imm(tmp, 0x80);
4659           tmp2 = rcache_get_tmp_arg(1); // assuming it differs to tmp
4660           emith_move_r_r(tmp2, tmp);
4661           rcache_free_tmp(tmp);
4662           rcache_get_reg_arg(0, GET_Rn(), NULL);
4663           emit_memhandler_write(0);
4664           break;
4665         default:
4666           goto default_;
4667         }
4668         goto end_op;
4669       case 0x0e:
4670         switch (GET_Fx())
4671         {
4672         case 0: // LDC Rm,SR   0100mmmm00001110
4673           tmp2 = SHR_SR;
4674           break;
4675         case 1: // LDC Rm,GBR  0100mmmm00011110
4676           tmp2 = SHR_GBR;
4677           break;
4678         case 2: // LDC Rm,VBR  0100mmmm00101110
4679           tmp2 = SHR_VBR;
4680           break;
4681         default:
4682           goto default_;
4683         }
4684         if (tmp2 == SHR_SR) {
4685           emith_invalidate_t();
4686           sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4687           tmp = rcache_get_reg(GET_Rn(), RC_GR_READ, NULL);
4688           emith_write_sr(sr, tmp);
4689           drcf.test_irq = 1;
4690         } else
4691           emit_move_r_r(tmp2, GET_Rn());
4692         goto end_op;
4693       case 0x0f: // MAC.W @Rm+,@Rn+  0100nnnnmmmm1111
4694         emit_indirect_read_double(sh2, &tmp, &tmp2, GET_Rn(), GET_Rm(), 1);
4695         sr = rcache_get_reg(SHR_SR, RC_GR_READ, NULL);
4696         tmp3 = rcache_get_reg(SHR_MACL, RC_GR_RMW, NULL);
4697         tmp4 = rcache_get_reg(SHR_MACH, RC_GR_RMW, NULL);
4698         emith_sh2_macw(tmp3, tmp4, tmp, tmp2, sr);
4699         rcache_free_tmp(tmp2);
4700         rcache_free_tmp(tmp);
4701         goto end_op;
4702       }
4703       goto default_;
4704
4705     /////////////////////////////////////////////
4706     case 0x05: // MOV.L @(disp,Rm),Rn 0101nnnnmmmmdddd
4707       sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4708       FLUSH_CYCLES(sr);
4709       emit_memhandler_read_rr(sh2, GET_Rn(), GET_Rm(), (op & 0x0f) * 4, 2 | drcf.polling);
4710       goto end_op;
4711
4712     /////////////////////////////////////////////
4713     case 0x06:
4714       switch (op & 0x0f)
4715       {
4716       case 0x00: // MOV.B @Rm,Rn        0110nnnnmmmm0000
4717       case 0x01: // MOV.W @Rm,Rn        0110nnnnmmmm0001
4718       case 0x02: // MOV.L @Rm,Rn        0110nnnnmmmm0010
4719       case 0x04: // MOV.B @Rm+,Rn       0110nnnnmmmm0100
4720       case 0x05: // MOV.W @Rm+,Rn       0110nnnnmmmm0101
4721       case 0x06: // MOV.L @Rm+,Rn       0110nnnnmmmm0110
4722         sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4723         FLUSH_CYCLES(sr);
4724         tmp = ((op & 7) >= 4 && GET_Rn() != GET_Rm()) ? MF_POSTINCR : drcf.polling;
4725         emit_memhandler_read_rr(sh2, GET_Rn(), GET_Rm(), 0, (op & 3) | tmp);
4726         goto end_op;
4727       case 0x03: // MOV    Rm,Rn        0110nnnnmmmm0011
4728         emit_move_r_r(GET_Rn(), GET_Rm());
4729         goto end_op;
4730       default: // 0x07 ... 0x0f
4731         tmp  = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
4732         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE, NULL);
4733         switch (op & 0x0f)
4734         {
4735         case 0x07: // NOT    Rm,Rn        0110nnnnmmmm0111
4736           emith_mvn_r_r(tmp2, tmp);
4737           break;
4738         case 0x08: // SWAP.B Rm,Rn        0110nnnnmmmm1000
4739           tmp3 = tmp2;
4740           if (tmp == tmp2)
4741             tmp3 = rcache_get_tmp();
4742           tmp4 = rcache_get_tmp();
4743           emith_lsr(tmp3, tmp, 16);
4744           emith_or_r_r_lsl(tmp3, tmp, 24);
4745           emith_and_r_r_imm(tmp4, tmp, 0xff00);
4746           emith_or_r_r_lsl(tmp3, tmp4, 8);
4747           emith_rol(tmp2, tmp3, 16);
4748           rcache_free_tmp(tmp4);
4749           if (tmp == tmp2)
4750             rcache_free_tmp(tmp3);
4751           break;
4752         case 0x09: // SWAP.W Rm,Rn        0110nnnnmmmm1001
4753           emith_rol(tmp2, tmp, 16);
4754           break;
4755         case 0x0a: // NEGC   Rm,Rn        0110nnnnmmmm1010
4756           sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4757           emith_sync_t(sr);
4758 #if T_OPTIMIZER
4759           if (rcache_regs_discard & BITMASK1(SHR_T)) {
4760             emith_t_to_carry(sr, 1);
4761             emith_negc_r_r(tmp2, tmp);
4762           } else
4763 #endif
4764           {
4765             EMITH_HINT_COND(DCOND_CS);
4766             emith_tpop_carry(sr, 1);
4767             emith_negcf_r_r(tmp2, tmp);
4768             emith_tpush_carry(sr, 1);
4769           }
4770           break;
4771         case 0x0b: // NEG    Rm,Rn        0110nnnnmmmm1011
4772           emith_neg_r_r(tmp2, tmp);
4773           break;
4774         case 0x0c: // EXTU.B Rm,Rn        0110nnnnmmmm1100
4775           emith_clear_msb(tmp2, tmp, 24);
4776           rcache_set_x16(tmp2, 1, 1);
4777           break;
4778         case 0x0d: // EXTU.W Rm,Rn        0110nnnnmmmm1101
4779           emith_clear_msb(tmp2, tmp, 16);
4780           rcache_set_x16(tmp2, 0, 1);
4781           break;
4782         case 0x0e: // EXTS.B Rm,Rn        0110nnnnmmmm1110
4783           emith_sext(tmp2, tmp, 8);
4784           rcache_set_x16(tmp2, 1, 0);
4785           break;
4786         case 0x0f: // EXTS.W Rm,Rn        0110nnnnmmmm1111
4787           emith_sext(tmp2, tmp, 16);
4788           rcache_set_x16(tmp2, 1, 0);
4789           break;
4790         }
4791         goto end_op;
4792       }
4793       goto default_;
4794
4795     /////////////////////////////////////////////
4796     case 0x07: // ADD #imm,Rn  0111nnnniiiiiiii
4797       if (op & 0x80) // adding negative
4798         emit_sub_r_imm(GET_Rn(), (u8)-op);
4799       else
4800         emit_add_r_imm(GET_Rn(), (u8)op);
4801       goto end_op;
4802
4803     /////////////////////////////////////////////
4804     case 0x08:
4805       switch (op & 0x0f00)
4806       {
4807       case 0x0000: // MOV.B R0,@(disp,Rn)  10000000nnnndddd
4808       case 0x0100: // MOV.W R0,@(disp,Rn)  10000001nnnndddd
4809         sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4810         FLUSH_CYCLES(sr);
4811         tmp = (op & 0x100) >> 8;
4812         emit_memhandler_write_rr(sh2, SHR_R0, GET_Rm(), (op & 0x0f) << tmp, tmp);
4813         goto end_op;
4814       case 0x0400: // MOV.B @(disp,Rm),R0  10000100mmmmdddd
4815       case 0x0500: // MOV.W @(disp,Rm),R0  10000101mmmmdddd
4816         sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4817         FLUSH_CYCLES(sr);
4818         tmp = (op & 0x100) >> 8;
4819         emit_memhandler_read_rr(sh2, SHR_R0, GET_Rm(), (op & 0x0f) << tmp, tmp | drcf.polling);
4820         goto end_op;
4821       case 0x0800: // CMP/EQ #imm,R0       10001000iiiiiiii
4822         tmp2 = rcache_get_reg(SHR_R0, RC_GR_READ, NULL);
4823         sr   = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4824         emith_clr_t_cond(sr);
4825         emith_cmp_r_imm(tmp2, (s8)(op & 0xff));
4826         emith_set_t_cond(sr, DCOND_EQ);
4827         goto end_op;
4828       }
4829       goto default_;
4830
4831     /////////////////////////////////////////////
4832     case 0x0c:
4833       switch (op & 0x0f00)
4834       {
4835       case 0x0000: // MOV.B R0,@(disp,GBR)   11000000dddddddd
4836       case 0x0100: // MOV.W R0,@(disp,GBR)   11000001dddddddd
4837       case 0x0200: // MOV.L R0,@(disp,GBR)   11000010dddddddd
4838         sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4839         FLUSH_CYCLES(sr);
4840         tmp = (op & 0x300) >> 8;
4841         emit_memhandler_write_rr(sh2, SHR_R0, SHR_GBR, (op & 0xff) << tmp, tmp);
4842         goto end_op;
4843       case 0x0400: // MOV.B @(disp,GBR),R0   11000100dddddddd
4844       case 0x0500: // MOV.W @(disp,GBR),R0   11000101dddddddd
4845       case 0x0600: // MOV.L @(disp,GBR),R0   11000110dddddddd
4846         sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4847         FLUSH_CYCLES(sr);
4848         tmp = (op & 0x300) >> 8;
4849         emit_memhandler_read_rr(sh2, SHR_R0, SHR_GBR, (op & 0xff) << tmp, tmp | drcf.polling);
4850         goto end_op;
4851       case 0x0800: // TST #imm,R0           11001000iiiiiiii
4852         tmp = rcache_get_reg(SHR_R0, RC_GR_READ, NULL);
4853         sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4854         emith_clr_t_cond(sr);
4855         emith_tst_r_imm(tmp, op & 0xff);
4856         emith_set_t_cond(sr, DCOND_EQ);
4857         goto end_op;
4858       case 0x0900: // AND #imm,R0           11001001iiiiiiii
4859         tmp = rcache_get_reg(SHR_R0, RC_GR_RMW, &tmp2);
4860         emith_and_r_r_imm(tmp, tmp2, (op & 0xff));
4861         goto end_op;
4862       case 0x0a00: // XOR #imm,R0           11001010iiiiiiii
4863         if (op & 0xff) {
4864           tmp = rcache_get_reg(SHR_R0, RC_GR_RMW, &tmp2);
4865           emith_eor_r_r_imm(tmp, tmp2, (op & 0xff));
4866         }
4867         goto end_op;
4868       case 0x0b00: // OR  #imm,R0           11001011iiiiiiii
4869         if (op & 0xff) {
4870           tmp = rcache_get_reg(SHR_R0, RC_GR_RMW, &tmp2);
4871           emith_or_r_r_imm(tmp, tmp2, (op & 0xff));
4872         }
4873         goto end_op;
4874       case 0x0c00: // TST.B #imm,@(R0,GBR)  11001100iiiiiiii
4875         sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4876         FLUSH_CYCLES(sr);
4877         tmp = emit_indirect_indexed_read(sh2, SHR_TMP, SHR_R0, SHR_GBR, 0 | drcf.polling);
4878         sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4879         emith_clr_t_cond(sr);
4880         emith_tst_r_imm(tmp, op & 0xff);
4881         emith_set_t_cond(sr, DCOND_EQ);
4882         rcache_free_tmp(tmp);
4883         goto end_op;
4884       case 0x0d00: // AND.B #imm,@(R0,GBR)  11001101iiiiiiii
4885         sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4886         FLUSH_CYCLES(sr);
4887         tmp = emit_indirect_indexed_read(sh2, SHR_TMP, SHR_R0, SHR_GBR, 0);
4888         tmp2 = rcache_get_tmp_arg(1);
4889         emith_and_r_r_imm(tmp2, tmp, (op & 0xff));
4890         goto end_rmw_op;
4891       case 0x0e00: // XOR.B #imm,@(R0,GBR)  11001110iiiiiiii
4892         sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4893         FLUSH_CYCLES(sr);
4894         tmp = emit_indirect_indexed_read(sh2, SHR_TMP, SHR_R0, SHR_GBR, 0);
4895         tmp2 = rcache_get_tmp_arg(1);
4896         emith_eor_r_r_imm(tmp2, tmp, (op & 0xff));
4897         goto end_rmw_op;
4898       case 0x0f00: // OR.B  #imm,@(R0,GBR)  11001111iiiiiiii
4899         sr  = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4900         FLUSH_CYCLES(sr);
4901         tmp = emit_indirect_indexed_read(sh2, SHR_TMP, SHR_R0, SHR_GBR, 0);
4902         tmp2 = rcache_get_tmp_arg(1);
4903         emith_or_r_r_imm(tmp2, tmp, (op & 0xff));
4904       end_rmw_op:
4905         rcache_free_tmp(tmp);
4906         emit_indirect_indexed_write(sh2, SHR_TMP, SHR_R0, SHR_GBR, 0);
4907         goto end_op;
4908       }
4909       goto default_;
4910
4911     /////////////////////////////////////////////
4912     case 0x0e: // MOV #imm,Rn   1110nnnniiiiiiii
4913       emit_move_r_imm32(GET_Rn(), (s8)op);
4914       goto end_op;
4915
4916     default:
4917     default_:
4918       if (!(op_flags[i] & OF_B_IN_DS)) {
4919         elprintf_sh2(sh2, EL_ANOMALY,
4920           "drc: illegal op %04x @ %08x", op, pc - 2);
4921         exit(1);
4922       }
4923     }
4924
4925 end_op:
4926     rcache_unlock_all();
4927     rcache_set_usage_now(0);
4928 #if DRC_DEBUG & 64
4929     RCACHE_CHECK("after insn");
4930 #endif
4931
4932     cycles += opd->cycles;
4933
4934     if (op_flags[i+1] & OF_DELAY_OP) {
4935       do_host_disasm(tcache_id);
4936       continue;
4937     }
4938
4939     // test irq?
4940     if (drcf.test_irq && !drcf.pending_branch_direct) {
4941       sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4942       FLUSH_CYCLES(sr);
4943       emith_sync_t(sr);
4944       if (!drcf.pending_branch_indirect)
4945         emit_move_r_imm32(SHR_PC, pc);
4946       rcache_flush();
4947       emith_call(sh2_drc_test_irq);
4948       drcf.test_irq = 0;
4949     }
4950
4951     // branch handling
4952     if (drcf.pending_branch_direct)
4953     {
4954       struct op_data *opd_b = (op_flags[i] & OF_DELAY_OP) ? opd-1 : opd;
4955       u32 target_pc = opd_b->imm;
4956       int cond = -1;
4957       int ctaken = 0;
4958       void *target = NULL;
4959
4960       if (OP_ISBRACND(opd_b->op))
4961         ctaken = (op_flags[i] & OF_DELAY_OP) ? 1 : 2;
4962       cycles += ctaken; // assume branch taken
4963
4964 #if LOOP_OPTIMIZER
4965       if ((drcf.loop_type == OF_IDLE_LOOP ||
4966           (drcf.loop_type == OF_DELAY_LOOP && drcf.delay_reg >= 0)))
4967       {
4968         // idle or delay loop
4969         emit_sync_t_to_sr();
4970         emith_sh2_delay_loop(cycles, drcf.delay_reg);
4971         rcache_unlock_all(); // may lock delay_reg
4972         drcf.polling = drcf.loop_type = drcf.pinning = 0;
4973       }
4974 #endif
4975
4976 #if CALL_STACK
4977       void *rtsadd = NULL, *rtsret = NULL;
4978       if ((opd_b->dest & BITMASK1(SHR_PR)) && pc+2 < end_pc) {
4979         // BSR - save rts data
4980         tmp = rcache_get_tmp_arg(1);
4981         rtsadd = tcache_ptr;
4982         emith_move_r_imm_s8_patchable(tmp, 0);
4983         rcache_clean_tmp();
4984         rcache_invalidate_tmp();
4985         emith_call(sh2_drc_dispatcher_call);
4986         rtsret = tcache_ptr;
4987       }
4988 #endif
4989
4990       // XXX move below cond test if not changing host cond (MIPS delay slot)?
4991       sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
4992       FLUSH_CYCLES(sr);
4993       rcache_clean();
4994
4995       if (OP_ISBRACND(opd_b->op)) {
4996         // BT[S], BF[S] - emit condition test
4997         cond = (opd_b->op == OP_BRANCH_CF) ? DCOND_EQ : DCOND_NE;
4998         if (delay_dep_fw & BITMASK1(SHR_T)) {
4999           emith_sync_t(sr);
5000           emith_tst_r_imm(sr, T_save);
5001         } else {
5002           cond = emith_tst_t(sr, (opd_b->op == OP_BRANCH_CT));
5003           if (emith_get_t_cond() >= 0) {
5004             if (opd_b->op == OP_BRANCH_CT)
5005               emith_or_r_imm_c(cond, sr, T);
5006             else
5007               emith_bic_r_imm_c(cond, sr, T);
5008           }
5009         }
5010       } else
5011         emith_sync_t(sr);
5012       // no modification of host status/flags between here and branching!
5013
5014       v = find_in_sorted_linkage(branch_targets, branch_target_count, target_pc);
5015       if (v >= 0)
5016       {
5017         // local branch
5018         if (branch_targets[v].ptr) {
5019           // local backward jump, link here now since host PC is already known
5020           target = branch_targets[v].ptr;
5021 #if LOOP_OPTIMIZER
5022           if (pinned_loops[pinned_loop_count].pc == target_pc) {
5023             // backward jump at end of optimized loop
5024             rcache_unpin_all();
5025             target = pinned_loops[pinned_loop_count].ptr;
5026             pinned_loop_count ++;
5027           }
5028 #endif
5029           if (cond != -1) {
5030             if (emith_jump_patch_inrange(tcache_ptr, target)) {
5031               emith_jump_cond(cond, target);
5032             } else {
5033               // not reachable directly, must use far branch
5034               EMITH_JMP_START(emith_invert_cond(cond));
5035               emith_jump(target);
5036               EMITH_JMP_END(emith_invert_cond(cond));
5037             }
5038           } else {
5039             emith_jump(target);
5040             rcache_invalidate();
5041           }
5042         } else if (blx_target_count < MAX_LOCAL_BRANCHES) {
5043           // local forward jump
5044           target = tcache_ptr;
5045           blx_targets[blx_target_count++] =
5046               (struct linkage) { .pc = target_pc, .ptr = target, .mask = 0x2 };
5047           if (cond != -1)
5048             emith_jump_cond_patchable(cond, target);
5049           else {
5050             emith_jump_patchable(target);
5051             rcache_invalidate();
5052           }
5053         } else
5054           // no space for resolving forward branch, handle it as external
5055           dbg(1, "warning: too many unresolved branches");
5056       }
5057
5058       if (target == NULL)
5059       {
5060         // can't resolve branch locally, make a block exit
5061         bl = dr_prepare_ext_branch(block->entryp, target_pc, sh2->is_slave, tcache_id);
5062         if (cond != -1) {
5063 #ifndef __arm__
5064           if (bl && blx_target_count < ARRAY_SIZE(blx_targets)) {
5065             // conditional jumps get a blx stub for the far jump
5066             bl->type = BL_JCCBLX;
5067             target = tcache_ptr;
5068             blx_targets[blx_target_count++] =
5069                 (struct linkage) { .pc = target_pc, .ptr = target, .bl = bl };
5070             emith_jump_cond_patchable(cond, target);
5071           } else {
5072             // not linkable, or blx table full; inline jump @dispatcher
5073             EMITH_JMP_START(emith_invert_cond(cond));
5074             if (bl) {
5075               bl->jump = tcache_ptr;
5076               emith_flush(); // flush to inhibit insn swapping
5077               bl->type = BL_LDJMP;
5078             }
5079             tmp = rcache_get_tmp_arg(0);
5080             emith_move_r_imm(tmp, target_pc);
5081             rcache_free_tmp(tmp);
5082             target = sh2_drc_dispatcher;
5083
5084             emith_jump_patchable(target);
5085             EMITH_JMP_END(emith_invert_cond(cond));
5086           }
5087 #else
5088           // jump @dispatcher - ARM 32bit version with conditional execution
5089           EMITH_SJMP_START(emith_invert_cond(cond));
5090           tmp = rcache_get_tmp_arg(0);
5091           emith_move_r_imm_c(cond, tmp, target_pc);
5092           rcache_free_tmp(tmp);
5093           target = sh2_drc_dispatcher;
5094
5095           if (bl) {
5096             bl->jump = tcache_ptr;
5097             bl->type = BL_JMP;
5098           }
5099           emith_jump_cond_patchable(cond, target);
5100           EMITH_SJMP_END(emith_invert_cond(cond));
5101 #endif
5102         } else {
5103           // unconditional, has the far jump inlined
5104           if (bl) {
5105             emith_flush(); // flush to inhibit insn swapping
5106             bl->type = BL_LDJMP;
5107           }
5108
5109           tmp = rcache_get_tmp_arg(0);
5110           emith_move_r_imm(tmp, target_pc);
5111           rcache_free_tmp(tmp);
5112           target = sh2_drc_dispatcher;
5113
5114           emith_jump_patchable(target);
5115           rcache_invalidate();
5116         }
5117       }
5118
5119 #if CALL_STACK
5120       if (rtsadd)
5121         emith_move_r_imm_s8_patch(rtsadd, tcache_ptr - (u8 *)rtsret);
5122 #endif
5123
5124       // branch not taken, correct cycle count (now, cycles < 0)
5125       if (ctaken)
5126         cycles -= ctaken;
5127       // set T bit to reflect branch not taken for OP_BRANCH_CT/CF
5128       if (emith_get_t_cond() >= 0) // T is synced for all other cases
5129         emith_set_t(sr, opd_b->op == OP_BRANCH_CF);
5130
5131       drcf.pending_branch_direct = 0;
5132       if (target_pc >= base_pc && target_pc < pc)
5133         drcf.polling = drcf.loop_type = 0;
5134     }
5135     else if (drcf.pending_branch_indirect) {
5136       u32 target_pc;
5137
5138       tmp = rcache_get_reg_arg(0, SHR_PC, NULL);
5139
5140 #if CALL_STACK
5141       struct op_data *opd_b = (op_flags[i] & OF_DELAY_OP) ? opd-1 : opd;
5142       void *rtsadd = NULL, *rtsret = NULL;
5143
5144       if ((opd_b->dest & BITMASK1(SHR_PR)) && pc+2 < end_pc) {
5145         // JSR, BSRF - save rts data
5146         tmp = rcache_get_tmp_arg(1);
5147         rtsadd = tcache_ptr;
5148         emith_move_r_imm_s8_patchable(tmp, 0);
5149         rcache_clean_tmp();
5150         rcache_invalidate_tmp();
5151         emith_call(sh2_drc_dispatcher_call);
5152         rtsret = tcache_ptr;
5153       }
5154 #endif
5155
5156       sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
5157       FLUSH_CYCLES(sr);
5158       emith_sync_t(sr);
5159       rcache_clean();
5160
5161 #if CALL_STACK
5162       if (opd_b->rm == SHR_PR) {
5163         // RTS - restore rts data, else jump to dispatcher
5164         emith_jump(sh2_drc_dispatcher_return);
5165       } else
5166 #endif
5167       if (gconst_get(SHR_PC, &target_pc)) {
5168         // JMP, JSR, BRAF, BSRF const - treat like unconditional direct branch
5169         bl = dr_prepare_ext_branch(block->entryp, target_pc, sh2->is_slave, tcache_id);
5170         if (bl) // pc already loaded somewhere else, can patch jump only
5171           bl->type = BL_JMP;
5172         emith_jump_patchable(sh2_drc_dispatcher);
5173       } else {
5174         // JMP, JSR, BRAF, BSRF not const
5175         emith_jump(sh2_drc_dispatcher);
5176       }
5177       rcache_invalidate();
5178
5179 #if CALL_STACK
5180       if (rtsadd)
5181         emith_move_r_imm_s8_patch(rtsadd, tcache_ptr - (u8 *)rtsret);
5182 #endif
5183
5184       drcf.pending_branch_indirect = 0;
5185       drcf.polling = drcf.loop_type = 0;
5186     }
5187     rcache_unlock_all();
5188
5189     do_host_disasm(tcache_id);
5190   }
5191
5192   // check the last op
5193   if (op_flags[i-1] & OF_DELAY_OP)
5194     opd = &ops[i-2];
5195   else
5196     opd = &ops[i-1];
5197
5198   if (! OP_ISBRAUC(opd->op) || (opd->dest & BITMASK1(SHR_PR)))
5199   {
5200     tmp = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
5201     FLUSH_CYCLES(tmp);
5202     emith_sync_t(tmp);
5203
5204     rcache_clean();
5205     bl = dr_prepare_ext_branch(block->entryp, pc, sh2->is_slave, tcache_id);
5206     if (bl) {
5207       emith_flush(); // flush to inhibit insn swapping
5208       bl->type = BL_LDJMP;
5209     }
5210     tmp = rcache_get_tmp_arg(0);
5211     emith_move_r_imm(tmp, pc);
5212     emith_jump_patchable(sh2_drc_dispatcher);
5213     rcache_invalidate();
5214   } else
5215     rcache_flush();
5216
5217   // link unresolved branches, emitting blx area entries as needed
5218   emit_branch_linkage_code(sh2, block, tcache_id, branch_targets,
5219                       branch_target_count, blx_targets, blx_target_count);
5220
5221   emith_flush();
5222   do_host_disasm(tcache_id);
5223
5224   emith_pool_commit(0);
5225
5226   // fill blx backup; do this last to backup final patched code
5227   for (i = 0; i < block->entry_count; i++)
5228     for (bl = block->entryp[i].o_links; bl; bl = bl->o_next)
5229       memcpy(bl->jdisp, bl->blx ? bl->blx : bl->jump, emith_jump_at_size());
5230
5231   ring_alloc(&tcache_ring[tcache_id], tcache_ptr - block_entry_ptr);
5232   host_instructions_updated(block_entry_ptr, tcache_ptr, 1);
5233
5234   dr_activate_block(block, tcache_id, sh2->is_slave);
5235   emith_update_cache();
5236
5237   do_host_disasm(tcache_id);
5238
5239   dbg(2, " block #%d,%d -> %p tcache %d/%d, insns %d -> %d %.3f",
5240     tcache_id, blkid_main, tcache_ptr,
5241     tcache_ring[tcache_id].used, tcache_ring[tcache_id].size,
5242     insns_compiled, host_insn_count, (float)host_insn_count / insns_compiled);
5243   if ((sh2->pc & 0xc6000000) == 0x02000000) { // ROM
5244     dbg(2, "  hash collisions %d/%d", hash_collisions, block_ring[tcache_id].used);
5245     Pico32x.emu_flags |= P32XF_DRC_ROM_C;
5246   }
5247 /*
5248  printf("~~~\n");
5249  tcache_dsm_ptrs[tcache_id] = block_entry_ptr;
5250  do_host_disasm(tcache_id);
5251  printf("~~~\n");
5252 */
5253
5254   return block_entry_ptr;
5255 }
5256
5257 static void sh2_generate_utils(void)
5258 {
5259   int arg0, arg1, arg2, arg3, sr, tmp, tmp2;
5260 #if DRC_DEBUG
5261   int hic = host_insn_count; // don't count utils for insn statistics
5262 #endif
5263
5264   host_arg2reg(arg0, 0);
5265   host_arg2reg(arg1, 1);
5266   host_arg2reg(arg2, 2);
5267   host_arg2reg(arg3, 3);
5268
5269   // sh2_drc_write8(u32 a, u32 d)
5270   sh2_drc_write8 = (void *)tcache_ptr;
5271   emith_ctx_read_ptr(arg2, offsetof(SH2, write8_tab));
5272   emith_sh2_wcall(arg0, arg1, arg2, arg3);
5273   emith_flush();
5274
5275   // sh2_drc_write16(u32 a, u32 d)
5276   sh2_drc_write16 = (void *)tcache_ptr;
5277   emith_ctx_read_ptr(arg2, offsetof(SH2, write16_tab));
5278   emith_sh2_wcall(arg0, arg1, arg2, arg3);
5279   emith_flush();
5280
5281   // sh2_drc_write32(u32 a, u32 d)
5282   sh2_drc_write32 = (void *)tcache_ptr;
5283   emith_ctx_read_ptr(arg2, offsetof(SH2, write32_tab));
5284   emith_sh2_wcall(arg0, arg1, arg2, arg3);
5285   emith_flush();
5286
5287   // d = sh2_drc_read8(u32 a)
5288   sh2_drc_read8 = (void *)tcache_ptr;
5289   emith_ctx_read_ptr(arg1, offsetof(SH2, read8_map));
5290   EMITH_HINT_COND(DCOND_CS);
5291   emith_sh2_rcall(arg0, arg1, arg2, arg3);
5292   EMITH_SJMP_START(DCOND_CS);
5293   emith_and_r_r_c(DCOND_CC, arg0, arg3);
5294   emit_le_ptr8(DCOND_CC, arg0);
5295   emith_read8s_r_r_r_c(DCOND_CC, RET_REG, arg2, arg0);
5296   emith_ret_c(DCOND_CC);
5297   EMITH_SJMP_END(DCOND_CS);
5298   emith_move_r_r_ptr(arg1, CONTEXT_REG);
5299   emith_abijump_reg(arg2);
5300   emith_flush();
5301
5302   // d = sh2_drc_read16(u32 a)
5303   sh2_drc_read16 = (void *)tcache_ptr;
5304   emith_ctx_read_ptr(arg1, offsetof(SH2, read16_map));
5305   EMITH_HINT_COND(DCOND_CS);
5306   emith_sh2_rcall(arg0, arg1, arg2, arg3);
5307   EMITH_SJMP_START(DCOND_CS);
5308   emith_and_r_r_c(DCOND_CC, arg0, arg3);
5309   emith_read16s_r_r_r_c(DCOND_CC, RET_REG, arg2, arg0);
5310   emith_ret_c(DCOND_CC);
5311   EMITH_SJMP_END(DCOND_CS);
5312   emith_move_r_r_ptr(arg1, CONTEXT_REG);
5313   emith_abijump_reg(arg2);
5314   emith_flush();
5315
5316   // d = sh2_drc_read32(u32 a)
5317   sh2_drc_read32 = (void *)tcache_ptr;
5318   emith_ctx_read_ptr(arg1, offsetof(SH2, read32_map));
5319   EMITH_HINT_COND(DCOND_CS);
5320   emith_sh2_rcall(arg0, arg1, arg2, arg3);
5321   EMITH_SJMP_START(DCOND_CS);
5322   emith_and_r_r_c(DCOND_CC, arg0, arg3);
5323   emith_read_r_r_r_c(DCOND_CC, RET_REG, arg2, arg0);
5324   emit_le_swap(DCOND_CC, RET_REG);
5325   emith_ret_c(DCOND_CC);
5326   EMITH_SJMP_END(DCOND_CS);
5327   emith_move_r_r_ptr(arg1, CONTEXT_REG);
5328   emith_abijump_reg(arg2);
5329   emith_flush();
5330
5331   // d = sh2_drc_read8_poll(u32 a)
5332   sh2_drc_read8_poll = (void *)tcache_ptr;
5333   emith_ctx_read_ptr(arg1, offsetof(SH2, read8_map));
5334   EMITH_HINT_COND(DCOND_CS);
5335   emith_sh2_rcall(arg0, arg1, arg2, arg3);
5336   EMITH_SJMP_START(DCOND_CC);
5337   emith_move_r_r_ptr_c(DCOND_CS, arg1, CONTEXT_REG);
5338   emith_abijump_reg_c(DCOND_CS, arg2);
5339   EMITH_SJMP_END(DCOND_CC);
5340   emith_and_r_r_r(arg1, arg0, arg3);
5341   emit_le_ptr8(-1, arg1);
5342   emith_read8s_r_r_r(arg1, arg2, arg1);
5343   emith_push_ret(arg1);
5344   emith_move_r_r_ptr(arg2, CONTEXT_REG);
5345   emith_abicall(p32x_sh2_poll_memory8);
5346   emith_pop_and_ret(arg1);
5347   emith_flush();
5348
5349   // d = sh2_drc_read16_poll(u32 a)
5350   sh2_drc_read16_poll = (void *)tcache_ptr;
5351   emith_ctx_read_ptr(arg1, offsetof(SH2, read16_map));
5352   EMITH_HINT_COND(DCOND_CS);
5353   emith_sh2_rcall(arg0, arg1, arg2, arg3);
5354   EMITH_SJMP_START(DCOND_CC);
5355   emith_move_r_r_ptr_c(DCOND_CS, arg1, CONTEXT_REG);
5356   emith_abijump_reg_c(DCOND_CS, arg2);
5357   EMITH_SJMP_END(DCOND_CC);
5358   emith_and_r_r_r(arg1, arg0, arg3);
5359   emith_read16s_r_r_r(arg1, arg2, arg1);
5360   emith_push_ret(arg1);
5361   emith_move_r_r_ptr(arg2, CONTEXT_REG);
5362   emith_abicall(p32x_sh2_poll_memory16);
5363   emith_pop_and_ret(arg1);
5364   emith_flush();
5365
5366   // d = sh2_drc_read32_poll(u32 a)
5367   sh2_drc_read32_poll = (void *)tcache_ptr;
5368   emith_ctx_read_ptr(arg1, offsetof(SH2, read32_map));
5369   EMITH_HINT_COND(DCOND_CS);
5370   emith_sh2_rcall(arg0, arg1, arg2, arg3);
5371   EMITH_SJMP_START(DCOND_CC);
5372   emith_move_r_r_ptr_c(DCOND_CS, arg1, CONTEXT_REG);
5373   emith_abijump_reg_c(DCOND_CS, arg2);
5374   EMITH_SJMP_END(DCOND_CC);
5375   emith_and_r_r_r(arg1, arg0, arg3);
5376   emith_read_r_r_r(arg1, arg2, arg1);
5377   emit_le_swap(-1, arg1);
5378   emith_push_ret(arg1);
5379   emith_move_r_r_ptr(arg2, CONTEXT_REG);
5380   emith_abicall(p32x_sh2_poll_memory32);
5381   emith_pop_and_ret(arg1);
5382   emith_flush();
5383
5384   // sh2_drc_exit(u32 pc)
5385   sh2_drc_exit = (void *)tcache_ptr;
5386   emith_ctx_write(arg0, SHR_PC * 4);
5387   emit_do_static_regs(1, arg2);
5388   emith_sh2_drc_exit();
5389   emith_flush();
5390
5391   // sh2_drc_dispatcher(u32 pc)
5392   sh2_drc_dispatcher = (void *)tcache_ptr;
5393   emith_ctx_write(arg0, SHR_PC * 4);
5394 #if BRANCH_CACHE
5395   // check if PC is in branch target cache
5396   emith_and_r_r_imm(arg1, arg0, (ARRAY_SIZE(sh2s->branch_cache)-1)*8);
5397   emith_add_r_r_r_lsl_ptr(arg1, CONTEXT_REG, arg1, sizeof(void *) == 8 ? 1 : 0);
5398   emith_read_r_r_offs(arg2, arg1, offsetof(SH2, branch_cache));
5399   emith_cmp_r_r(arg2, arg0);
5400   EMITH_SJMP_START(DCOND_NE);
5401 #if (DRC_DEBUG & 128)
5402   emith_move_r_ptr_imm(arg2, (uptr)&bchit);
5403   emith_read_r_r_offs_c(DCOND_EQ, arg3, arg2, 0);
5404   emith_add_r_imm_c(DCOND_EQ, arg3, 1);
5405   emith_write_r_r_offs_c(DCOND_EQ, arg3, arg2, 0);
5406 #endif
5407   emith_read_r_r_offs_ptr_c(DCOND_EQ, RET_REG, arg1, offsetof(SH2, branch_cache) + sizeof(void *));
5408   emith_jump_reg_c(DCOND_EQ, RET_REG);
5409   EMITH_SJMP_END(DCOND_NE);
5410 #endif
5411   emith_move_r_r_ptr(arg1, CONTEXT_REG);
5412   emith_add_r_r_ptr_imm(arg2, CONTEXT_REG, offsetof(SH2, drc_tmp));
5413   emith_abicall(dr_lookup_block);
5414   // store PC and block entry ptr (in arg0) in branch target cache
5415   emith_tst_r_r_ptr(RET_REG, RET_REG);
5416   EMITH_SJMP_START(DCOND_EQ);
5417 #if BRANCH_CACHE
5418 #if (DRC_DEBUG & 128)
5419   emith_move_r_ptr_imm(arg2, (uptr)&bcmiss);
5420   emith_read_r_r_offs_c(DCOND_NE, arg3, arg2, 0);
5421   emith_add_r_imm_c(DCOND_NE, arg3, 1);
5422   emith_write_r_r_offs_c(DCOND_NE, arg3, arg2, 0);
5423 #endif
5424   emith_ctx_read_c(DCOND_NE, arg2, SHR_PC * 4);
5425   emith_and_r_r_imm(arg1, arg2, (ARRAY_SIZE(sh2s->branch_cache)-1)*8);
5426   emith_add_r_r_r_lsl_ptr(arg1, CONTEXT_REG, arg1, sizeof(void *) == 8 ? 1 : 0);
5427   emith_write_r_r_offs_c(DCOND_NE, arg2, arg1, offsetof(SH2, branch_cache));
5428   emith_write_r_r_offs_ptr_c(DCOND_NE, RET_REG, arg1, offsetof(SH2, branch_cache) + sizeof(void *));
5429 #endif
5430   emith_jump_reg_c(DCOND_NE, RET_REG);
5431   EMITH_SJMP_END(DCOND_EQ);
5432   // lookup failed, call sh2_translate()
5433   emith_move_r_r_ptr(arg0, CONTEXT_REG);
5434   emith_ctx_read(arg1, offsetof(SH2, drc_tmp)); // tcache_id
5435   emith_abicall(sh2_translate);
5436   emith_tst_r_r_ptr(RET_REG, RET_REG);
5437   EMITH_SJMP_START(DCOND_EQ);
5438   emith_jump_reg_c(DCOND_NE, RET_REG);
5439   EMITH_SJMP_END(DCOND_EQ);
5440   // XXX: can't translate, fail
5441   emith_abicall(dr_failure);
5442   emith_flush();
5443
5444 #if CALL_STACK
5445   // pc = sh2_drc_dispatcher_call(u32 pc)
5446   sh2_drc_dispatcher_call = (void *)tcache_ptr;
5447   emith_ctx_read(arg2, offsetof(SH2, rts_cache_idx));
5448   emith_add_r_imm(arg2, (u32)(2*sizeof(void *)));
5449   emith_and_r_imm(arg2, (ARRAY_SIZE(sh2s->rts_cache)-1) * 2*sizeof(void *));
5450   emith_ctx_write(arg2, offsetof(SH2, rts_cache_idx));
5451   emith_add_r_r_r_lsl_ptr(arg3, CONTEXT_REG, arg2, 0);
5452   rcache_get_reg_arg(2, SHR_PR, NULL);
5453   emith_add_r_ret(arg1);
5454   emith_write_r_r_offs_ptr(arg1, arg3, offsetof(SH2, rts_cache)+sizeof(void *));
5455   emith_write_r_r_offs(arg2, arg3, offsetof(SH2, rts_cache));
5456   rcache_flush();
5457   emith_ret();
5458   emith_flush();
5459
5460   // sh2_drc_dispatcher_return(u32 pc)
5461   sh2_drc_dispatcher_return = (void *)tcache_ptr;
5462   emith_ctx_read(arg2, offsetof(SH2, rts_cache_idx));
5463   emith_add_r_r_r_lsl_ptr(arg1, CONTEXT_REG, arg2, 0);
5464   emith_read_r_r_offs(arg3, arg1, offsetof(SH2, rts_cache));
5465   emith_cmp_r_r(arg0, arg3);
5466 #if (DRC_DEBUG & 128)
5467   EMITH_SJMP_START(DCOND_EQ);
5468   emith_move_r_ptr_imm(arg3, (uptr)&rcmiss);
5469   emith_read_r_r_offs_c(DCOND_NE, arg1, arg3, 0);
5470   emith_add_r_imm_c(DCOND_NE, arg1, 1);
5471   emith_write_r_r_offs_c(DCOND_NE, arg1, arg3, 0);
5472   emith_jump_cond(DCOND_NE, sh2_drc_dispatcher);
5473   EMITH_SJMP_END(DCOND_EQ);
5474 #else
5475   emith_jump_cond(DCOND_NE, sh2_drc_dispatcher);
5476 #endif
5477   emith_read_r_r_offs_ptr(arg0, arg1, offsetof(SH2, rts_cache) + sizeof(void *));
5478   emith_sub_r_imm(arg2, (u32)(2*sizeof(void *)));
5479   emith_and_r_imm(arg2, (ARRAY_SIZE(sh2s->rts_cache)-1) * 2*sizeof(void *));
5480   emith_ctx_write(arg2, offsetof(SH2, rts_cache_idx));
5481 #if (DRC_DEBUG & 128)
5482   emith_move_r_ptr_imm(arg3, (uptr)&rchit);
5483   emith_read_r_r_offs(arg1, arg3, 0);
5484   emith_add_r_imm(arg1, 1);
5485   emith_write_r_r_offs(arg1, arg3, 0);
5486 #endif
5487   emith_jump_reg(arg0);
5488   emith_flush();
5489 #endif
5490
5491   // sh2_drc_test_irq(void)
5492   // assumes it's called from main function (may jump to dispatcher)
5493   sh2_drc_test_irq = (void *)tcache_ptr;
5494   emith_ctx_read(arg1, offsetof(SH2, pending_level));
5495   sr = rcache_get_reg(SHR_SR, RC_GR_READ, NULL);
5496   emith_lsr(arg0, sr, I_SHIFT);
5497   emith_and_r_imm(arg0, 0x0f);
5498   emith_cmp_r_r(arg1, arg0); // pending_level > ((sr >> 4) & 0x0f)?
5499   EMITH_SJMP_START(DCOND_GT);
5500   emith_ret_c(DCOND_LE);     // nope, return
5501   EMITH_SJMP_END(DCOND_GT);
5502   // adjust SP
5503   tmp = rcache_get_reg(SHR_SP, RC_GR_RMW, NULL);
5504   emith_sub_r_imm(tmp, 4*2);
5505   rcache_clean();
5506   // push SR
5507   tmp = rcache_get_reg_arg(0, SHR_SP, &tmp2);
5508   emith_add_r_r_imm(tmp, tmp2, 4);
5509   tmp = rcache_get_reg_arg(1, SHR_SR, NULL);
5510   emith_clear_msb(tmp, tmp, 22);
5511   emith_move_r_r_ptr(arg2, CONTEXT_REG);
5512   rcache_invalidate_tmp();
5513   emith_abicall(p32x_sh2_write32); // XXX: use sh2_drc_write32?
5514   // push PC
5515   rcache_get_reg_arg(0, SHR_SP, NULL);
5516   rcache_get_reg_arg(1, SHR_PC, NULL);
5517   emith_move_r_r_ptr(arg2, CONTEXT_REG);
5518   rcache_invalidate_tmp();
5519   emith_abicall(p32x_sh2_write32);
5520   // update I, cycles, do callback
5521   emith_ctx_read(arg1, offsetof(SH2, pending_level));
5522   sr = rcache_get_reg(SHR_SR, RC_GR_RMW, NULL);
5523   emith_bic_r_imm(sr, I);
5524   emith_or_r_r_lsl(sr, arg1, I_SHIFT);
5525   emith_sub_r_imm(sr, 13 << 12); // at least 13 cycles
5526   rcache_flush();
5527   emith_move_r_r_ptr(arg0, CONTEXT_REG);
5528   emith_abicall_ctx(offsetof(SH2, irq_callback)); // vector = sh2->irq_callback(sh2, level);
5529   // obtain new PC
5530   tmp = rcache_get_reg_arg(1, SHR_VBR, &tmp2);
5531   emith_add_r_r_r_lsl(arg0, tmp2, RET_REG, 2);
5532   emith_call(sh2_drc_read32);
5533   if (arg0 != RET_REG)
5534     emith_move_r_r(arg0, RET_REG);
5535   emith_call_cleanup();
5536   rcache_invalidate();
5537   emith_jump(sh2_drc_dispatcher);
5538   emith_flush();
5539
5540   // sh2_drc_entry(SH2 *sh2)
5541   sh2_drc_entry = (void *)tcache_ptr;
5542   emith_sh2_drc_entry();
5543   emith_move_r_r_ptr(CONTEXT_REG, arg0); // move ctx, arg0
5544   emit_do_static_regs(0, arg2);
5545   emith_call(sh2_drc_test_irq);
5546   emith_ctx_read(arg0, SHR_PC * 4);
5547   emith_jump(sh2_drc_dispatcher);
5548   emith_flush();
5549
5550 #ifdef DRC_SR_REG
5551   // sh2_drc_save_sr(SH2 *sh2)
5552   sh2_drc_save_sr = (void *)tcache_ptr;
5553   tmp = rcache_get_reg(SHR_SR, RC_GR_READ, NULL);
5554   emith_write_r_r_offs(tmp, arg0, SHR_SR * 4);
5555   rcache_invalidate();
5556   emith_ret();
5557   emith_flush();
5558
5559   // sh2_drc_restore_sr(SH2 *sh2)
5560   sh2_drc_restore_sr = (void *)tcache_ptr;
5561   tmp = rcache_get_reg(SHR_SR, RC_GR_WRITE, NULL);
5562   emith_read_r_r_offs(tmp, arg0, SHR_SR * 4);
5563   rcache_flush();
5564   emith_ret();
5565   emith_flush();
5566 #endif
5567
5568 #ifdef PDB_NET
5569   // debug
5570   #define MAKE_READ_WRAPPER(func) { \
5571     void *tmp = (void *)tcache_ptr; \
5572     emith_push_ret(); \
5573     emith_call(func); \
5574     emith_ctx_read(arg2, offsetof(SH2, pdb_io_csum[0]));  \
5575     emith_addf_r_r(arg2, arg0);                           \
5576     emith_ctx_write(arg2, offsetof(SH2, pdb_io_csum[0])); \
5577     emith_ctx_read(arg2, offsetof(SH2, pdb_io_csum[1]));  \
5578     emith_adc_r_imm(arg2, 0x01000000);                    \
5579     emith_ctx_write(arg2, offsetof(SH2, pdb_io_csum[1])); \
5580     emith_pop_and_ret(); \
5581     emith_flush(); \
5582     func = tmp; \
5583   }
5584   #define MAKE_WRITE_WRAPPER(func) { \
5585     void *tmp = (void *)tcache_ptr; \
5586     emith_ctx_read(arg2, offsetof(SH2, pdb_io_csum[0]));  \
5587     emith_addf_r_r(arg2, arg1);                           \
5588     emith_ctx_write(arg2, offsetof(SH2, pdb_io_csum[0])); \
5589     emith_ctx_read(arg2, offsetof(SH2, pdb_io_csum[1]));  \
5590     emith_adc_r_imm(arg2, 0x01000000);                    \
5591     emith_ctx_write(arg2, offsetof(SH2, pdb_io_csum[1])); \
5592     emith_move_r_r_ptr(arg2, CONTEXT_REG);                \
5593     emith_jump(func); \
5594     emith_flush(); \
5595     func = tmp; \
5596   }
5597
5598   MAKE_READ_WRAPPER(sh2_drc_read8);
5599   MAKE_READ_WRAPPER(sh2_drc_read16);
5600   MAKE_READ_WRAPPER(sh2_drc_read32);
5601   MAKE_WRITE_WRAPPER(sh2_drc_write8);
5602   MAKE_WRITE_WRAPPER(sh2_drc_write16);
5603   MAKE_WRITE_WRAPPER(sh2_drc_write32);
5604   MAKE_READ_WRAPPER(sh2_drc_read8_poll);
5605   MAKE_READ_WRAPPER(sh2_drc_read16_poll);
5606   MAKE_READ_WRAPPER(sh2_drc_read32_poll);
5607 #endif
5608
5609   emith_pool_commit(0);
5610   rcache_invalidate();
5611 #if (DRC_DEBUG & 4)
5612   host_dasm_new_symbol(sh2_drc_entry);
5613   host_dasm_new_symbol(sh2_drc_dispatcher);
5614 #if CALL_STACK
5615   host_dasm_new_symbol(sh2_drc_dispatcher_call);
5616   host_dasm_new_symbol(sh2_drc_dispatcher_return);
5617 #endif
5618   host_dasm_new_symbol(sh2_drc_exit);
5619   host_dasm_new_symbol(sh2_drc_test_irq);
5620   host_dasm_new_symbol(sh2_drc_write8);
5621   host_dasm_new_symbol(sh2_drc_write16);
5622   host_dasm_new_symbol(sh2_drc_write32);
5623   host_dasm_new_symbol(sh2_drc_read8);
5624   host_dasm_new_symbol(sh2_drc_read16);
5625   host_dasm_new_symbol(sh2_drc_read32);
5626   host_dasm_new_symbol(sh2_drc_read8_poll);
5627   host_dasm_new_symbol(sh2_drc_read16_poll);
5628   host_dasm_new_symbol(sh2_drc_read32_poll);
5629 #ifdef DRC_SR_REG
5630   host_dasm_new_symbol(sh2_drc_save_sr);
5631   host_dasm_new_symbol(sh2_drc_restore_sr);
5632 #endif
5633 #endif
5634
5635 #if DRC_DEBUG
5636   host_insn_count = hic;
5637 #endif
5638 }
5639
5640 static void sh2_smc_rm_blocks(u32 a, int len, int tcache_id, int free)
5641 {
5642   struct block_list **blist, *entry, *next;
5643   u32 mask = RAM_SIZE(tcache_id) - 1;
5644   u32 wtmask = ~0x20000000; // writethrough area mask
5645   u32 start_addr, end_addr;
5646   u32 start_lit, end_lit;
5647   struct block_desc *block;
5648   int removed = 0, rest;
5649
5650   // ignore cache-through
5651   a &= wtmask;
5652
5653   do {
5654     blist = &inval_lookup[tcache_id][(a & mask) / INVAL_PAGE_SIZE];
5655     entry = *blist;
5656     // go through the block list for this range
5657     while (entry != NULL) {
5658       next = entry->next;
5659       block = entry->block;
5660       start_addr = block->addr & wtmask;
5661       end_addr = start_addr + block->size;
5662       start_lit = block->addr_lit & wtmask;
5663       end_lit = start_lit + block->size_lit;
5664       // disable/delete block if it covers the modified address
5665       if ((start_addr < a+len && a < end_addr) ||
5666           (start_lit < a+len && a < end_lit))
5667       {
5668         dbg(2, "smc remove @%08x", a);
5669         end_addr = (start_lit < a+len && block->size_lit ? a : 0);
5670         dr_rm_block_entry(block, tcache_id, end_addr, free);
5671         removed = 1;
5672       }
5673       entry = next;
5674     }
5675     rest = INVAL_PAGE_SIZE - (a & (INVAL_PAGE_SIZE-1));
5676     a += rest, len -= rest;
5677   } while (len > 0);
5678
5679   if (!removed) {
5680     if (len <= 4)
5681       dbg(2, "rm_blocks called @%08x, no work?", a);
5682     return;
5683   }
5684
5685 #if BRANCH_CACHE
5686   if (tcache_id)
5687     memset32(sh2s[tcache_id-1].branch_cache, -1, sizeof(sh2s[0].branch_cache)/4);
5688   else {
5689     memset32(sh2s[0].branch_cache, -1, sizeof(sh2s[0].branch_cache)/4);
5690     memset32(sh2s[1].branch_cache, -1, sizeof(sh2s[1].branch_cache)/4);
5691   }
5692 #endif
5693 #if CALL_STACK
5694   if (tcache_id) {
5695     memset32(sh2s[tcache_id-1].rts_cache, -1, sizeof(sh2s[0].rts_cache)/4);
5696     sh2s[tcache_id-1].rts_cache_idx = 0;
5697   } else {
5698     memset32(sh2s[0].rts_cache, -1, sizeof(sh2s[0].rts_cache)/4);
5699     memset32(sh2s[1].rts_cache, -1, sizeof(sh2s[1].rts_cache)/4);
5700     sh2s[0].rts_cache_idx = sh2s[1].rts_cache_idx = 0;
5701   }
5702 #endif
5703 }
5704
5705 void sh2_drc_wcheck_ram(u32 a, unsigned len, SH2 *sh2)
5706 {
5707   sh2_smc_rm_blocks(a, len, 0, 0);
5708 }
5709
5710 void sh2_drc_wcheck_da(u32 a, unsigned len, SH2 *sh2)
5711 {
5712   sh2_smc_rm_blocks(a, len, 1 + sh2->is_slave, 0);
5713 }
5714
5715 int sh2_execute_drc(SH2 *sh2c, int cycles)
5716 {
5717   int ret_cycles;
5718
5719   // cycles are kept in SHR_SR unused bits (upper 20)
5720   // bit11 contains T saved for delay slot
5721   // others are usual SH2 flags
5722   sh2c->sr &= 0x3f3;
5723   sh2c->sr |= (cycles-1) << 12;
5724 #if (DRC_DEBUG & 8)
5725   lastpc = lastcnt = 0;
5726 #endif
5727
5728   sh2c->state |= SH2_IN_DRC;
5729   host_call(sh2_drc_entry, (SH2 *))(sh2c);
5730   sh2c->state &= ~SH2_IN_DRC;
5731
5732   // TODO: irq cycles
5733   ret_cycles = (int32_t)sh2c->sr >> 12;
5734   if (ret_cycles >= 0)
5735     dbg(1, "warning: drc returned with cycles: %d, pc %08x", ret_cycles, sh2c->pc);
5736 #if (DRC_DEBUG & 8)
5737   if (lastcnt)
5738     dbg(8, "= %csh2 enter %08x %p (%d times), c=%d", sh2c->is_slave?'s':'m',
5739       lastpc, lastblock, lastcnt, (signed int)sh2c->sr >> 12);
5740 #endif
5741
5742   sh2c->sr &= 0x3f3;
5743   return ret_cycles+1;
5744 }
5745
5746 static void block_stats(void)
5747 {
5748 #if (DRC_DEBUG & 2)
5749   int c, b, i;
5750   long total = 0;
5751
5752   printf("block stats:\n");
5753   for (b = 0; b < ARRAY_SIZE(block_tables); b++) {
5754     for (i = block_ring[b].first; i != block_ring[b].next; i = (i+1)%block_ring[b].size)
5755       if (block_tables[b][i].addr != 0)
5756         total += block_tables[b][i].refcount;
5757   }
5758   printf("total: %ld\n",total);
5759
5760   for (c = 0; c < 20; c++) {
5761     struct block_desc *blk, *maxb = NULL;
5762     int max = 0;
5763     for (b = 0; b < ARRAY_SIZE(block_tables); b++) {
5764       for (i = block_ring[b].first; i != block_ring[b].next; i = (i+1)%block_ring[b].size)
5765         if ((blk = &block_tables[b][i])->addr != 0 && blk->refcount > max) {
5766           max = blk->refcount;
5767           maxb = blk;
5768         }
5769     }
5770     if (maxb == NULL)
5771       break;
5772     printf("%08lx %p %9d %2.3f%%\n", (ulong)maxb->addr, maxb->tcache_ptr, maxb->refcount,
5773       (double)maxb->refcount / total * 100.0);
5774     maxb->refcount = 0;
5775   }
5776
5777   for (b = 0; b < ARRAY_SIZE(block_tables); b++) 
5778     for (i = block_ring[b].first; i != block_ring[b].next; i = (i+1)%block_ring[b].size)
5779       block_tables[b][i].refcount = 0;
5780 #endif
5781 }
5782
5783 void entry_stats(void)
5784 {
5785 #if (DRC_DEBUG & 32)
5786   int c, b, i, j;
5787   long total = 0;
5788
5789   printf("block entry stats:\n");
5790   for (b = 0; b < ARRAY_SIZE(block_tables); b++) {
5791     for (i = block_ring[b].first; i != block_ring[b].next; i = (i+1)%block_ring[b].size)
5792       for (j = 0; j < block_tables[b][i].entry_count; j++)
5793         total += block_tables[b][i].entryp[j].entry_count;
5794   }
5795   printf("total: %ld\n",total);
5796
5797   for (c = 0; c < 20; c++) {
5798     struct block_desc *blk;
5799     struct block_entry *maxb = NULL;
5800     int max = 0;
5801     for (b = 0; b < ARRAY_SIZE(block_tables); b++) {
5802       for (i = block_ring[b].first; i != block_ring[b].next; i = (i+1)%block_ring[b].size) {
5803         blk = &block_tables[b][i];
5804         for (j = 0; j < blk->entry_count; j++)
5805           if (blk->entryp[j].entry_count > max) {
5806             max = blk->entryp[j].entry_count;
5807             maxb = &blk->entryp[j];
5808           }
5809       }
5810     }
5811     if (maxb == NULL)
5812       break;
5813     printf("%08lx %p %9d %2.3f%%\n", (ulong)maxb->pc, maxb->tcache_ptr, maxb->entry_count,
5814       (double)100 * maxb->entry_count / total);
5815     maxb->entry_count = 0;
5816   }
5817
5818   for (b = 0; b < ARRAY_SIZE(block_tables); b++) {
5819     for (i = block_ring[b].first; i != block_ring[b].next; i = (i+1)%block_ring[b].size)
5820       for (j = 0; j < block_tables[b][i].entry_count; j++)
5821         block_tables[b][i].entryp[j].entry_count = 0;
5822   }
5823 #endif
5824 }
5825
5826 static void backtrace(void)
5827 {
5828 #if (DRC_DEBUG & 1024)
5829   int i;
5830   printf("backtrace master:\n");
5831   for (i = 0; i < ARRAY_SIZE(csh2[0]); i++)
5832     SH2_DUMP(&csh2[0][i], "bt msh2");
5833   printf("backtrace slave:\n");
5834   for (i = 0; i < ARRAY_SIZE(csh2[1]); i++)
5835     SH2_DUMP(&csh2[1][i], "bt ssh2");
5836 #endif
5837 }
5838
5839 static void state_dump(void)
5840 {
5841 #if (DRC_DEBUG & 2048)
5842   int i;
5843
5844   SH2_DUMP(&sh2s[0], "master");
5845   printf("VBR msh2: %lx\n", (ulong)sh2s[0].vbr);
5846   for (i = 0; i < 0x60; i++) {
5847     printf("%08lx ",(ulong)p32x_sh2_read32(sh2s[0].vbr + i*4, &sh2s[0]));
5848     if ((i+1) % 8 == 0) printf("\n");
5849   }
5850   printf("stack msh2: %lx\n", (ulong)sh2s[0].r[15]);
5851   for (i = -0x30; i < 0x30; i++) {
5852     printf("%08lx ",(ulong)p32x_sh2_read32(sh2s[0].r[15] + i*4, &sh2s[0]));
5853     if ((i+1) % 8 == 0) printf("\n");
5854   }
5855   SH2_DUMP(&sh2s[1], "slave");
5856   printf("VBR ssh2: %lx\n", (ulong)sh2s[1].vbr);
5857   for (i = 0; i < 0x60; i++) {
5858     printf("%08lx ",(ulong)p32x_sh2_read32(sh2s[1].vbr + i*4, &sh2s[1]));
5859     if ((i+1) % 8 == 0) printf("\n");
5860   }
5861   printf("stack ssh2: %lx\n", (ulong)sh2s[1].r[15]);
5862   for (i = -0x30; i < 0x30; i++) {
5863     printf("%08lx ",(ulong)p32x_sh2_read32(sh2s[1].r[15] + i*4, &sh2s[1]));
5864     if ((i+1) % 8 == 0) printf("\n");
5865   }
5866 #endif
5867 }
5868
5869 static void bcache_stats(void)
5870 {
5871 #if (DRC_DEBUG & 128)
5872   int i;
5873 #if CALL_STACK
5874   for (i = 1; i < ARRAY_SIZE(sh2s->rts_cache); i++)
5875     if (sh2s[0].rts_cache[i].pc == -1 && sh2s[1].rts_cache[i].pc == -1) break;
5876
5877   printf("return cache hits:%d misses:%d depth: %d index: %d/%d\n", rchit, rcmiss, i,sh2s[0].rts_cache_idx,sh2s[1].rts_cache_idx);
5878   for (i = 0; i < ARRAY_SIZE(sh2s[0].rts_cache); i++) {
5879     printf("%08lx ",(ulong)sh2s[0].rts_cache[i].pc);
5880     if ((i+1) % 8 == 0) printf("\n");
5881   }
5882   for (i = 0; i < ARRAY_SIZE(sh2s[1].rts_cache); i++) {
5883     printf("%08lx ",(ulong)sh2s[1].rts_cache[i].pc);
5884     if ((i+1) % 8 == 0) printf("\n");
5885   }
5886 #endif
5887 #if BRANCH_CACHE
5888   printf("branch cache hits:%d misses:%d\n", bchit, bcmiss);
5889   printf("branch cache master:\n");
5890   for (i = 0; i < ARRAY_SIZE(sh2s[0].branch_cache); i++) {
5891     printf("%08lx ",(ulong)sh2s[0].branch_cache[i].pc);
5892     if ((i+1) % 8 == 0) printf("\n");
5893   }
5894   printf("branch cache slave:\n");
5895   for (i = 0; i < ARRAY_SIZE(sh2s[1].branch_cache); i++) {
5896     printf("%08lx ",(ulong)sh2s[1].branch_cache[i].pc);
5897     if ((i+1) % 8 == 0) printf("\n");
5898   }
5899 #endif
5900 #endif
5901 }
5902
5903 void sh2_drc_flush_all(void)
5904 {
5905   if (block_tables[0] == NULL)
5906     return;
5907
5908   backtrace();
5909   state_dump();
5910   block_stats();
5911   entry_stats();
5912   bcache_stats();
5913   dr_flush_tcache(0);
5914   dr_flush_tcache(1);
5915   dr_flush_tcache(2);
5916   Pico32x.emu_flags &= ~P32XF_DRC_ROM_C;
5917 }
5918
5919 void sh2_drc_mem_setup(SH2 *sh2)
5920 {
5921   // fill the DRC-only convenience pointers
5922   sh2->p_drcblk_da = Pico32xMem->drcblk_da[!!sh2->is_slave];
5923   sh2->p_drcblk_ram = Pico32xMem->drcblk_ram;
5924 }
5925
5926 int sh2_drc_init(SH2 *sh2)
5927 {
5928   int i;
5929
5930   if (block_tables[0] == NULL)
5931   {
5932     for (i = 0; i < TCACHE_BUFFERS; i++) {
5933       block_tables[i] = calloc(BLOCK_MAX_COUNT(i), sizeof(*block_tables[0]));
5934       if (block_tables[i] == NULL)
5935         goto fail;
5936       entry_tables[i] = calloc(ENTRY_MAX_COUNT(i), sizeof(*entry_tables[0]));
5937       if (entry_tables[i] == NULL)
5938         goto fail;
5939       block_link_pool[i] = calloc(BLOCK_LINK_MAX_COUNT(i),
5940                           sizeof(*block_link_pool[0]));
5941       if (block_link_pool[i] == NULL)
5942         goto fail;
5943
5944       inval_lookup[i] = calloc(RAM_SIZE(i) / INVAL_PAGE_SIZE,
5945                                sizeof(inval_lookup[0]));
5946       if (inval_lookup[i] == NULL)
5947         goto fail;
5948
5949       hash_tables[i] = calloc(HASH_TABLE_SIZE(i), sizeof(*hash_tables[0]));
5950       if (hash_tables[i] == NULL)
5951         goto fail;
5952
5953       unresolved_links[i] = calloc(HASH_TABLE_SIZE(i), sizeof(*unresolved_links[0]));
5954       if (unresolved_links[i] == NULL)
5955         goto fail;
5956 //atexit(sh2_drc_finish);
5957
5958       RING_INIT(&block_ring[i], block_tables[i], BLOCK_MAX_COUNT(i));
5959       RING_INIT(&entry_ring[i], entry_tables[i], ENTRY_MAX_COUNT(i));
5960     }
5961
5962     block_list_pool = calloc(BLOCK_LIST_MAX_COUNT, sizeof(*block_list_pool));
5963     if (block_list_pool == NULL)
5964       goto fail;
5965     block_list_pool_count = 0;
5966     blist_free = NULL;
5967
5968     memset(block_link_pool_counts, 0, sizeof(block_link_pool_counts));
5969     memset(blink_free, 0, sizeof(blink_free));
5970
5971     drc_cmn_init();
5972     rcache_init();
5973
5974     tcache_ptr = tcache;
5975     sh2_generate_utils();
5976     host_instructions_updated(tcache, tcache_ptr, 1);
5977     emith_update_cache();
5978
5979     i = tcache_ptr - tcache;
5980     RING_INIT(&tcache_ring[0], tcache_ptr, tcache_sizes[0] - i);
5981     for (i = 1; i < ARRAY_SIZE(tcache_ring); i++) {
5982       RING_INIT(&tcache_ring[i], tcache_ring[i-1].base + tcache_ring[i-1].size,
5983                   tcache_sizes[i]);
5984     }
5985
5986 #if (DRC_DEBUG & 4)
5987     for (i = 0; i < ARRAY_SIZE(block_tables); i++)
5988       tcache_dsm_ptrs[i] = tcache_ring[i].base;
5989     // disasm the utils
5990     tcache_dsm_ptrs[0] = tcache;
5991     do_host_disasm(0);
5992 #endif
5993 #if (DRC_DEBUG & 1)
5994     hash_collisions = 0;
5995 #endif
5996   }
5997   memset(sh2->branch_cache, -1, sizeof(sh2->branch_cache));
5998   memset(sh2->rts_cache, -1, sizeof(sh2->rts_cache));
5999   sh2->rts_cache_idx = 0;
6000
6001   return 0;
6002
6003 fail:
6004   sh2_drc_finish(sh2);
6005   return -1;
6006 }
6007
6008 void sh2_drc_finish(SH2 *sh2)
6009 {
6010   int i;
6011
6012   if (block_tables[0] == NULL)
6013     return;
6014
6015 #if (DRC_DEBUG & (256|512))
6016    if (trace[0]) fclose(trace[0]);
6017    if (trace[1]) fclose(trace[1]);
6018    trace[0] = trace[1] = NULL;
6019 #endif
6020
6021 #if (DRC_DEBUG & 4)
6022   for (i = 0; i < TCACHE_BUFFERS; i++) {
6023     printf("~~~ tcache %d\n", i);
6024 #if 0
6025     if (tcache_ring[i].first < tcache_ring[i].next) {
6026       tcache_dsm_ptrs[i] = tcache_ring[i].first;
6027       tcache_ptr = tcache_ring[i].next;
6028       do_host_disasm(i);
6029     } else if (tcache_ring[i].used) {
6030       tcache_dsm_ptrs[i] = tcache_ring[i].first;
6031       tcache_ptr = tcache_ring[i].base + tcache_ring[i].size;
6032       do_host_disasm(i);
6033       tcache_dsm_ptrs[i] = tcache_ring[i].base;
6034       tcache_ptr = tcache_ring[i].next;
6035       do_host_disasm(i);
6036     }
6037 #endif
6038     printf("max links: %d\n", block_link_pool_counts[i]);
6039   }
6040   printf("max block list: %d\n", block_list_pool_count);
6041 #endif
6042
6043   sh2_drc_flush_all();
6044
6045   for (i = 0; i < TCACHE_BUFFERS; i++) {
6046     if (block_tables[i] != NULL)
6047       free(block_tables[i]);
6048     block_tables[i] = NULL;
6049     if (entry_tables[i] != NULL)
6050       free(entry_tables[i]);
6051     entry_tables[i] = NULL;
6052     if (block_link_pool[i] != NULL)
6053       free(block_link_pool[i]);
6054     block_link_pool[i] = NULL;
6055     blink_free[i] = NULL;
6056
6057     if (inval_lookup[i] != NULL)
6058       free(inval_lookup[i]);
6059     inval_lookup[i] = NULL;
6060
6061     if (hash_tables[i] != NULL) {
6062       free(hash_tables[i]);
6063       hash_tables[i] = NULL;
6064     }
6065
6066     if (unresolved_links[i] != NULL) {
6067       free(unresolved_links[i]);
6068       unresolved_links[i] = NULL;
6069     }
6070   }
6071
6072   if (block_list_pool != NULL)
6073     free(block_list_pool);
6074   block_list_pool = NULL;
6075   blist_free = NULL;
6076
6077   drc_cmn_cleanup();
6078 }
6079
6080 #endif /* DRC_SH2 */
6081
6082 static void *dr_get_pc_base(u32 pc, SH2 *sh2)
6083 {
6084   void *ret;
6085   u32 mask = 0;
6086
6087   ret = p32x_sh2_get_mem_ptr(pc, &mask, sh2);
6088   if (ret == (void *)-1)
6089     return ret;
6090
6091   return (char *)ret - (pc & ~mask);
6092 }
6093
6094 u16 scan_block(u32 base_pc, int is_slave, u8 *op_flags, u32 *end_pc_out,
6095   u32 *base_literals_out, u32 *end_literals_out)
6096 {
6097   u16 *dr_pc_base;
6098   u32 pc, op, tmp;
6099   u32 end_pc, end_literals = 0;
6100   u32 lowest_literal = 0;
6101   u32 lowest_mova = 0;
6102   struct op_data *opd;
6103   int next_is_delay = 0;
6104   int end_block = 0;
6105   int is_divop;
6106   int i, i_end, i_div = -1;
6107   u32 crc = 0;
6108   // 2nd pass stuff
6109   int last_btarget; // loop detector 
6110   enum { T_UNKNOWN, T_CLEAR, T_SET } t; // T propagation state
6111
6112   memset(op_flags, 0, sizeof(*op_flags) * BLOCK_INSN_LIMIT);
6113   op_flags[0] |= OF_BTARGET; // block start is always a target
6114
6115   dr_pc_base = dr_get_pc_base(base_pc, &sh2s[!!is_slave]);
6116
6117   // 1st pass: disassemble
6118   for (i = 0, pc = base_pc; ; i++, pc += 2) {
6119     // we need an ops[] entry after the last one initialized,
6120     // so do it before end_block checks
6121     opd = &ops[i];
6122     opd->op = OP_UNHANDLED;
6123     opd->rm = -1;
6124     opd->source = opd->dest = 0;
6125     opd->cycles = 1;
6126     opd->imm = 0;
6127
6128     if (next_is_delay) {
6129       op_flags[i] |= OF_DELAY_OP;
6130       next_is_delay = 0;
6131     }
6132     else if (end_block || i >= BLOCK_INSN_LIMIT - 2)
6133       break;
6134     else if ((lowest_mova && lowest_mova <= pc) ||
6135               (lowest_literal && lowest_literal <= pc))
6136       break; // text area collides with data area
6137
6138     is_divop = 0;
6139     op = FETCH_OP(pc);
6140     switch ((op & 0xf000) >> 12)
6141     {
6142     /////////////////////////////////////////////
6143     case 0x00:
6144       switch (op & 0x0f)
6145       {
6146       case 0x02:
6147         switch (GET_Fx())
6148         {
6149         case 0: // STC SR,Rn  0000nnnn00000010
6150           tmp = BITMASK2(SHR_SR, SHR_T);
6151           break;
6152         case 1: // STC GBR,Rn 0000nnnn00010010
6153           tmp = BITMASK1(SHR_GBR);
6154           break;
6155         case 2: // STC VBR,Rn 0000nnnn00100010
6156           tmp = BITMASK1(SHR_VBR);
6157           break;
6158         default:
6159           goto undefined;
6160         }
6161         opd->op = OP_MOVE;
6162         opd->source = tmp;
6163         opd->dest = BITMASK1(GET_Rn());
6164         break;
6165       case 0x03:
6166         CHECK_UNHANDLED_BITS(0xd0, undefined);
6167         // BRAF Rm    0000mmmm00100011
6168         // BSRF Rm    0000mmmm00000011
6169         opd->op = OP_BRANCH_RF;
6170         opd->rm = GET_Rn();
6171         opd->source = BITMASK2(SHR_PC, opd->rm);
6172         opd->dest = BITMASK1(SHR_PC);
6173         if (!(op & 0x20))
6174           opd->dest |= BITMASK1(SHR_PR);
6175         opd->cycles = 2;
6176         next_is_delay = 1;
6177         if (!(opd->dest & BITMASK1(SHR_PR)))
6178           end_block = !(op_flags[i+1+next_is_delay] & OF_BTARGET);
6179         else
6180           op_flags[i+1+next_is_delay] |= OF_BTARGET;
6181         break;
6182       case 0x04: // MOV.B Rm,@(R0,Rn)   0000nnnnmmmm0100
6183       case 0x05: // MOV.W Rm,@(R0,Rn)   0000nnnnmmmm0101
6184       case 0x06: // MOV.L Rm,@(R0,Rn)   0000nnnnmmmm0110
6185         opd->source = BITMASK3(GET_Rm(), SHR_R0, GET_Rn());
6186         opd->dest = BITMASK1(SHR_MEM);
6187         break;
6188       case 0x07:
6189         // MUL.L     Rm,Rn      0000nnnnmmmm0111
6190         opd->source = BITMASK2(GET_Rm(), GET_Rn());
6191         opd->dest = BITMASK1(SHR_MACL);
6192         opd->cycles = 2;
6193         break;
6194       case 0x08:
6195         CHECK_UNHANDLED_BITS(0xf00, undefined);
6196         switch (GET_Fx())
6197         {
6198         case 0: // CLRT               0000000000001000
6199           opd->op = OP_SETCLRT;
6200           opd->dest = BITMASK1(SHR_T);
6201           opd->imm = 0;
6202           break;
6203         case 1: // SETT               0000000000011000
6204           opd->op = OP_SETCLRT;
6205           opd->dest = BITMASK1(SHR_T);
6206           opd->imm = 1;
6207           break;
6208         case 2: // CLRMAC             0000000000101000
6209           opd->dest = BITMASK2(SHR_MACL, SHR_MACH);
6210           break;
6211         default:
6212           goto undefined;
6213         }
6214         break;
6215       case 0x09:
6216         switch (GET_Fx())
6217         {
6218         case 0: // NOP        0000000000001001
6219           CHECK_UNHANDLED_BITS(0xf00, undefined);
6220           break;
6221         case 1: // DIV0U      0000000000011001
6222           CHECK_UNHANDLED_BITS(0xf00, undefined);
6223           opd->op = OP_DIV0;
6224           opd->source = BITMASK1(SHR_SR);
6225           opd->dest = BITMASK2(SHR_SR, SHR_T);
6226           div(opd) = (struct div){ .rn=SHR_MEM, .rm=SHR_MEM, .ro=SHR_MEM };
6227           i_div = i;
6228           is_divop = 1;
6229           break;
6230         case 2: // MOVT Rn    0000nnnn00101001
6231           opd->source = BITMASK1(SHR_T);
6232           opd->dest = BITMASK1(GET_Rn());
6233           break;
6234         default:
6235           goto undefined;
6236         }
6237         break;
6238       case 0x0a:
6239         switch (GET_Fx())
6240         {
6241         case 0: // STS      MACH,Rn   0000nnnn00001010
6242           tmp = SHR_MACH;
6243           break;
6244         case 1: // STS      MACL,Rn   0000nnnn00011010
6245           tmp = SHR_MACL;
6246           break;
6247         case 2: // STS      PR,Rn     0000nnnn00101010
6248           tmp = SHR_PR;
6249           break;
6250         default:
6251           goto undefined;
6252         }
6253         opd->op = OP_MOVE;
6254         opd->source = BITMASK1(tmp);
6255         opd->dest = BITMASK1(GET_Rn());
6256         break;
6257       case 0x0b:
6258         CHECK_UNHANDLED_BITS(0xf00, undefined);
6259         switch (GET_Fx())
6260         {
6261         case 0: // RTS        0000000000001011
6262           opd->op = OP_BRANCH_R;
6263           opd->rm = SHR_PR;
6264           opd->source = BITMASK1(opd->rm);
6265           opd->dest = BITMASK1(SHR_PC);
6266           opd->cycles = 2;
6267           next_is_delay = 1;
6268           end_block = !(op_flags[i+1+next_is_delay] & OF_BTARGET);
6269           break;
6270         case 1: // SLEEP      0000000000011011
6271           opd->op = OP_SLEEP;
6272           opd->cycles = 3;
6273           end_block = 1;
6274           break;
6275         case 2: // RTE        0000000000101011
6276           opd->op = OP_RTE;
6277           opd->source = BITMASK1(SHR_SP);
6278           opd->dest = BITMASK4(SHR_SP, SHR_SR, SHR_T, SHR_PC);
6279           opd->cycles = 4;
6280           next_is_delay = 1;
6281           end_block = !(op_flags[i+1+next_is_delay] & OF_BTARGET);
6282           break;
6283         default:
6284           goto undefined;
6285         }
6286         break;
6287       case 0x0c: // MOV.B    @(R0,Rm),Rn      0000nnnnmmmm1100
6288       case 0x0d: // MOV.W    @(R0,Rm),Rn      0000nnnnmmmm1101
6289       case 0x0e: // MOV.L    @(R0,Rm),Rn      0000nnnnmmmm1110
6290         opd->source = BITMASK3(GET_Rm(), SHR_R0, SHR_MEM);
6291         opd->dest = BITMASK1(GET_Rn());
6292         op_flags[i] |= OF_POLL_INSN;
6293         break;
6294       case 0x0f: // MAC.L   @Rm+,@Rn+  0000nnnnmmmm1111
6295         opd->source = BITMASK6(GET_Rm(), GET_Rn(), SHR_SR, SHR_MACL, SHR_MACH, SHR_MEM);
6296         opd->dest = BITMASK4(GET_Rm(), GET_Rn(), SHR_MACL, SHR_MACH);
6297         opd->cycles = 3;
6298         break;
6299       default:
6300         goto undefined;
6301       }
6302       break;
6303
6304     /////////////////////////////////////////////
6305     case 0x01:
6306       // MOV.L Rm,@(disp,Rn) 0001nnnnmmmmdddd
6307       opd->source = BITMASK2(GET_Rm(), GET_Rn());
6308       opd->dest = BITMASK1(SHR_MEM);
6309       opd->imm = (op & 0x0f) * 4;
6310       break;
6311
6312     /////////////////////////////////////////////
6313     case 0x02:
6314       switch (op & 0x0f)
6315       {
6316       case 0x00: // MOV.B Rm,@Rn        0010nnnnmmmm0000
6317       case 0x01: // MOV.W Rm,@Rn        0010nnnnmmmm0001
6318       case 0x02: // MOV.L Rm,@Rn        0010nnnnmmmm0010
6319         opd->source = BITMASK2(GET_Rm(), GET_Rn());
6320         opd->dest = BITMASK1(SHR_MEM);
6321         break;
6322       case 0x04: // MOV.B Rm,@-Rn       0010nnnnmmmm0100
6323       case 0x05: // MOV.W Rm,@-Rn       0010nnnnmmmm0101
6324       case 0x06: // MOV.L Rm,@-Rn       0010nnnnmmmm0110
6325         opd->source = BITMASK2(GET_Rm(), GET_Rn());
6326         opd->dest = BITMASK2(GET_Rn(), SHR_MEM);
6327         break;
6328       case 0x07: // DIV0S Rm,Rn         0010nnnnmmmm0111
6329         opd->op = OP_DIV0;
6330         opd->source = BITMASK3(SHR_SR, GET_Rm(), GET_Rn());
6331         opd->dest = BITMASK2(SHR_SR, SHR_T);
6332         div(opd) = (struct div){ .rn=GET_Rn(), .rm=GET_Rm(), .ro=SHR_MEM };
6333         i_div = i;
6334         is_divop = 1;
6335         break;
6336       case 0x08: // TST Rm,Rn           0010nnnnmmmm1000
6337         opd->source = BITMASK2(GET_Rm(), GET_Rn());
6338         opd->dest = BITMASK1(SHR_T);
6339         break;
6340       case 0x09: // AND Rm,Rn           0010nnnnmmmm1001
6341       case 0x0a: // XOR Rm,Rn           0010nnnnmmmm1010
6342       case 0x0b: // OR  Rm,Rn           0010nnnnmmmm1011
6343         opd->source = BITMASK2(GET_Rm(), GET_Rn());
6344         opd->dest = BITMASK1(GET_Rn());
6345         break;
6346       case 0x0c: // CMP/STR Rm,Rn       0010nnnnmmmm1100
6347         opd->source = BITMASK2(GET_Rm(), GET_Rn());
6348         opd->dest = BITMASK1(SHR_T);
6349         break;
6350       case 0x0d: // XTRCT  Rm,Rn        0010nnnnmmmm1101
6351         opd->source = BITMASK2(GET_Rm(), GET_Rn());
6352         opd->dest = BITMASK1(GET_Rn());
6353         break;
6354       case 0x0e: // MULU.W Rm,Rn        0010nnnnmmmm1110
6355       case 0x0f: // MULS.W Rm,Rn        0010nnnnmmmm1111
6356         opd->source = BITMASK2(GET_Rm(), GET_Rn());
6357         opd->dest = BITMASK1(SHR_MACL);
6358         break;
6359       default:
6360         goto undefined;
6361       }
6362       break;
6363
6364     /////////////////////////////////////////////
6365     case 0x03:
6366       switch (op & 0x0f)
6367       {
6368       case 0x00: // CMP/EQ Rm,Rn        0011nnnnmmmm0000
6369       case 0x02: // CMP/HS Rm,Rn        0011nnnnmmmm0010
6370       case 0x03: // CMP/GE Rm,Rn        0011nnnnmmmm0011
6371       case 0x06: // CMP/HI Rm,Rn        0011nnnnmmmm0110
6372       case 0x07: // CMP/GT Rm,Rn        0011nnnnmmmm0111
6373         opd->source = BITMASK2(GET_Rm(), GET_Rn());
6374         opd->dest = BITMASK1(SHR_T);
6375         break;
6376       case 0x04: // DIV1    Rm,Rn       0011nnnnmmmm0100
6377         opd->source = BITMASK4(GET_Rm(), GET_Rn(), SHR_SR, SHR_T);
6378         opd->dest = BITMASK3(GET_Rn(), SHR_SR, SHR_T);
6379         if (i_div >= 0) {
6380           // divide operation: all DIV1 operations must use the same reg pair
6381           if (div(&ops[i_div]).rn == SHR_MEM)
6382             div(&ops[i_div]).rn=GET_Rn(), div(&ops[i_div]).rm=GET_Rm();
6383           if (div(&ops[i_div]).rn == GET_Rn() && div(&ops[i_div]).rm == GET_Rm()) {
6384             div(&ops[i_div]).div1 += 1;
6385             div(&ops[i_div]).state = 0;
6386             is_divop = 1;
6387           } else {
6388             ops[i_div].imm = 0;
6389             i_div = -1;
6390           }
6391         }
6392         break;
6393       case 0x05: // DMULU.L Rm,Rn       0011nnnnmmmm0101
6394       case 0x0d: // DMULS.L Rm,Rn       0011nnnnmmmm1101
6395         opd->source = BITMASK2(GET_Rm(), GET_Rn());
6396         opd->dest = BITMASK2(SHR_MACL, SHR_MACH);
6397         opd->cycles = 2;
6398         break;
6399       case 0x08: // SUB     Rm,Rn       0011nnnnmmmm1000
6400       case 0x0c: // ADD     Rm,Rn       0011nnnnmmmm1100
6401         opd->source = BITMASK2(GET_Rm(), GET_Rn());
6402         opd->dest = BITMASK1(GET_Rn());
6403         break;
6404       case 0x0a: // SUBC    Rm,Rn       0011nnnnmmmm1010
6405       case 0x0e: // ADDC    Rm,Rn       0011nnnnmmmm1110
6406         opd->source = BITMASK3(GET_Rm(), GET_Rn(), SHR_T);
6407         opd->dest = BITMASK2(GET_Rn(), SHR_T);
6408         break;
6409       case 0x0b: // SUBV    Rm,Rn       0011nnnnmmmm1011
6410       case 0x0f: // ADDV    Rm,Rn       0011nnnnmmmm1111
6411         opd->source = BITMASK2(GET_Rm(), GET_Rn());
6412         opd->dest = BITMASK2(GET_Rn(), SHR_T);
6413         break;
6414       default:
6415         goto undefined;
6416       }
6417       break;
6418
6419     /////////////////////////////////////////////
6420     case 0x04:
6421       switch (op & 0x0f)
6422       {
6423       case 0x00:
6424         switch (GET_Fx())
6425         {
6426         case 0: // SHLL Rn    0100nnnn00000000
6427         case 2: // SHAL Rn    0100nnnn00100000
6428           opd->source = BITMASK1(GET_Rn());
6429           opd->dest = BITMASK2(GET_Rn(), SHR_T);
6430           break;
6431         case 1: // DT Rn      0100nnnn00010000
6432           opd->source = BITMASK1(GET_Rn());
6433           opd->dest = BITMASK2(GET_Rn(), SHR_T);
6434           op_flags[i] |= OF_DELAY_INSN;
6435           break;
6436         default:
6437           goto undefined;
6438         }
6439         break;
6440       case 0x01:
6441         switch (GET_Fx())
6442         {
6443         case 0: // SHLR Rn    0100nnnn00000001
6444         case 2: // SHAR Rn    0100nnnn00100001
6445           opd->source = BITMASK1(GET_Rn());
6446           opd->dest = BITMASK2(GET_Rn(), SHR_T);
6447           break;
6448         case 1: // CMP/PZ Rn  0100nnnn00010001
6449           opd->source = BITMASK1(GET_Rn());
6450           opd->dest = BITMASK1(SHR_T);
6451           break;
6452         default:
6453           goto undefined;
6454         }
6455         break;
6456       case 0x02:
6457       case 0x03:
6458         switch (op & 0x3f)
6459         {
6460         case 0x02: // STS.L    MACH,@-Rn 0100nnnn00000010
6461           tmp = BITMASK1(SHR_MACH);
6462           break;
6463         case 0x12: // STS.L    MACL,@-Rn 0100nnnn00010010
6464           tmp = BITMASK1(SHR_MACL);
6465           break;
6466         case 0x22: // STS.L    PR,@-Rn   0100nnnn00100010
6467           tmp = BITMASK1(SHR_PR);
6468           break;
6469         case 0x03: // STC.L    SR,@-Rn   0100nnnn00000011
6470           tmp = BITMASK2(SHR_SR, SHR_T);
6471           opd->cycles = 2;
6472           break;
6473         case 0x13: // STC.L    GBR,@-Rn  0100nnnn00010011
6474           tmp = BITMASK1(SHR_GBR);
6475           opd->cycles = 2;
6476           break;
6477         case 0x23: // STC.L    VBR,@-Rn  0100nnnn00100011
6478           tmp = BITMASK1(SHR_VBR);
6479           opd->cycles = 2;
6480           break;
6481         default:
6482           goto undefined;
6483         }
6484         opd->source = BITMASK1(GET_Rn()) | tmp;
6485         opd->dest = BITMASK2(GET_Rn(), SHR_MEM);
6486         break;
6487       case 0x04:
6488       case 0x05:
6489         switch (op & 0x3f)
6490         {
6491         case 0x04: // ROTL   Rn          0100nnnn00000100
6492         case 0x05: // ROTR   Rn          0100nnnn00000101
6493           opd->source = BITMASK1(GET_Rn());
6494           opd->dest = BITMASK2(GET_Rn(), SHR_T);
6495           break;
6496         case 0x24: // ROTCL  Rn          0100nnnn00100100
6497           if (i_div >= 0) {
6498             // divide operation: all ROTCL operations must use the same register
6499             if (div(&ops[i_div]).ro == SHR_MEM)
6500               div(&ops[i_div]).ro = GET_Rn();
6501             if (div(&ops[i_div]).ro == GET_Rn() && !div(&ops[i_div]).state) {
6502               div(&ops[i_div]).rotcl += 1;
6503               div(&ops[i_div]).state = 1;
6504               is_divop = 1;
6505             } else {
6506               ops[i_div].imm = 0;
6507               i_div = -1;
6508             }
6509           }
6510         case 0x25: // ROTCR  Rn          0100nnnn00100101
6511           opd->source = BITMASK2(GET_Rn(), SHR_T);
6512           opd->dest = BITMASK2(GET_Rn(), SHR_T);
6513           break;
6514         case 0x15: // CMP/PL Rn          0100nnnn00010101
6515           opd->source = BITMASK1(GET_Rn());
6516           opd->dest = BITMASK1(SHR_T);
6517           break;
6518         default:
6519           goto undefined;
6520         }
6521         break;
6522       case 0x06:
6523       case 0x07:
6524         switch (op & 0x3f)
6525         {
6526         case 0x06: // LDS.L @Rm+,MACH 0100mmmm00000110
6527           tmp = BITMASK1(SHR_MACH);
6528           break;
6529         case 0x16: // LDS.L @Rm+,MACL 0100mmmm00010110
6530           tmp = BITMASK1(SHR_MACL);
6531           break;
6532         case 0x26: // LDS.L @Rm+,PR   0100mmmm00100110
6533           tmp = BITMASK1(SHR_PR);
6534           break;
6535         case 0x07: // LDC.L @Rm+,SR   0100mmmm00000111
6536           tmp = BITMASK2(SHR_SR, SHR_T);
6537           opd->op = OP_LDC;
6538           opd->cycles = 3;
6539           break;
6540         case 0x17: // LDC.L @Rm+,GBR  0100mmmm00010111
6541           tmp = BITMASK1(SHR_GBR);
6542           opd->op = OP_LDC;
6543           opd->cycles = 3;
6544           break;
6545         case 0x27: // LDC.L @Rm+,VBR  0100mmmm00100111
6546           tmp = BITMASK1(SHR_VBR);
6547           opd->op = OP_LDC;
6548           opd->cycles = 3;
6549           break;
6550         default:
6551           goto undefined;
6552         }
6553         opd->source = BITMASK2(GET_Rn(), SHR_MEM);
6554         opd->dest = BITMASK1(GET_Rn()) | tmp;
6555         break;
6556       case 0x08:
6557       case 0x09:
6558         switch (GET_Fx())
6559         {
6560         case 0:
6561           // SHLL2 Rn        0100nnnn00001000
6562           // SHLR2 Rn        0100nnnn00001001
6563           break;
6564         case 1:
6565           // SHLL8 Rn        0100nnnn00011000
6566           // SHLR8 Rn        0100nnnn00011001
6567           break;
6568         case 2:
6569           // SHLL16 Rn       0100nnnn00101000
6570           // SHLR16 Rn       0100nnnn00101001
6571           break;
6572         default:
6573           goto undefined;
6574         }
6575         opd->source = BITMASK1(GET_Rn());
6576         opd->dest = BITMASK1(GET_Rn());
6577         break;
6578       case 0x0a:
6579         switch (GET_Fx())
6580         {
6581         case 0: // LDS      Rm,MACH   0100mmmm00001010
6582           tmp = SHR_MACH;
6583           break;
6584         case 1: // LDS      Rm,MACL   0100mmmm00011010
6585           tmp = SHR_MACL;
6586           break;
6587         case 2: // LDS      Rm,PR     0100mmmm00101010
6588           tmp = SHR_PR;
6589           break;
6590         default:
6591           goto undefined;
6592         }
6593         opd->op = OP_MOVE;
6594         opd->source = BITMASK1(GET_Rn());
6595         opd->dest = BITMASK1(tmp);
6596         break;
6597       case 0x0b:
6598         switch (GET_Fx())
6599         {
6600         case 0: // JSR  @Rm   0100mmmm00001011
6601           opd->dest = BITMASK1(SHR_PR);
6602         case 2: // JMP  @Rm   0100mmmm00101011
6603           opd->op = OP_BRANCH_R;
6604           opd->rm = GET_Rn();
6605           opd->source = BITMASK1(opd->rm);
6606           opd->dest |= BITMASK1(SHR_PC);
6607           opd->cycles = 2;
6608           next_is_delay = 1;
6609           if (!(opd->dest & BITMASK1(SHR_PR)))
6610             end_block = !(op_flags[i+1+next_is_delay] & OF_BTARGET);
6611           else
6612             op_flags[i+1+next_is_delay] |= OF_BTARGET;
6613           break;
6614         case 1: // TAS.B @Rn  0100nnnn00011011
6615           opd->source = BITMASK2(GET_Rn(), SHR_MEM);
6616           opd->dest = BITMASK2(SHR_T, SHR_MEM);
6617           opd->cycles = 4;
6618           break;
6619         default:
6620           goto undefined;
6621         }
6622         break;
6623       case 0x0e:
6624         switch (GET_Fx())
6625         {
6626         case 0: // LDC Rm,SR   0100mmmm00001110
6627           tmp = BITMASK2(SHR_SR, SHR_T);
6628           break;
6629         case 1: // LDC Rm,GBR  0100mmmm00011110
6630           tmp = BITMASK1(SHR_GBR);
6631           break;
6632         case 2: // LDC Rm,VBR  0100mmmm00101110
6633           tmp = BITMASK1(SHR_VBR);
6634           break;
6635         default:
6636           goto undefined;
6637         }
6638         opd->op = OP_LDC;
6639         opd->source = BITMASK1(GET_Rn());
6640         opd->dest = tmp;
6641         break;
6642       case 0x0f:
6643         // MAC.W @Rm+,@Rn+  0100nnnnmmmm1111
6644         opd->source = BITMASK6(GET_Rm(), GET_Rn(), SHR_SR, SHR_MACL, SHR_MACH, SHR_MEM);
6645         opd->dest = BITMASK4(GET_Rm(), GET_Rn(), SHR_MACL, SHR_MACH);
6646         opd->cycles = 3;
6647         break;
6648       default:
6649         goto undefined;
6650       }
6651       break;
6652
6653     /////////////////////////////////////////////
6654     case 0x05:
6655       // MOV.L @(disp,Rm),Rn 0101nnnnmmmmdddd
6656       opd->source = BITMASK2(GET_Rm(), SHR_MEM);
6657       opd->dest = BITMASK1(GET_Rn());
6658       opd->imm = (op & 0x0f) * 4;
6659       op_flags[i] |= OF_POLL_INSN;
6660       break;
6661
6662     /////////////////////////////////////////////
6663     case 0x06:
6664       switch (op & 0x0f)
6665       {
6666       case 0x04: // MOV.B @Rm+,Rn       0110nnnnmmmm0100
6667       case 0x05: // MOV.W @Rm+,Rn       0110nnnnmmmm0101
6668       case 0x06: // MOV.L @Rm+,Rn       0110nnnnmmmm0110
6669         opd->dest = BITMASK2(GET_Rm(), GET_Rn());
6670         opd->source = BITMASK2(GET_Rm(), SHR_MEM);
6671         break;
6672       case 0x00: // MOV.B @Rm,Rn        0110nnnnmmmm0000
6673       case 0x01: // MOV.W @Rm,Rn        0110nnnnmmmm0001
6674       case 0x02: // MOV.L @Rm,Rn        0110nnnnmmmm0010
6675         opd->dest = BITMASK1(GET_Rn());
6676         opd->source = BITMASK2(GET_Rm(), SHR_MEM);
6677         op_flags[i] |= OF_POLL_INSN;
6678         break;
6679       case 0x0a: // NEGC   Rm,Rn        0110nnnnmmmm1010
6680         opd->source = BITMASK2(GET_Rm(), SHR_T);
6681         opd->dest = BITMASK2(GET_Rn(), SHR_T);
6682         break;
6683       case 0x03: // MOV    Rm,Rn        0110nnnnmmmm0011
6684         opd->op = OP_MOVE;
6685         goto arith_rmrn;
6686       case 0x07: // NOT    Rm,Rn        0110nnnnmmmm0111
6687       case 0x08: // SWAP.B Rm,Rn        0110nnnnmmmm1000
6688       case 0x09: // SWAP.W Rm,Rn        0110nnnnmmmm1001
6689       case 0x0b: // NEG    Rm,Rn        0110nnnnmmmm1011
6690       case 0x0c: // EXTU.B Rm,Rn        0110nnnnmmmm1100
6691       case 0x0d: // EXTU.W Rm,Rn        0110nnnnmmmm1101
6692       case 0x0e: // EXTS.B Rm,Rn        0110nnnnmmmm1110
6693       case 0x0f: // EXTS.W Rm,Rn        0110nnnnmmmm1111
6694       arith_rmrn:
6695         opd->source = BITMASK1(GET_Rm());
6696         opd->dest = BITMASK1(GET_Rn());
6697         break;
6698       }
6699       break;
6700
6701     /////////////////////////////////////////////
6702     case 0x07:
6703       // ADD #imm,Rn  0111nnnniiiiiiii
6704       opd->source = opd->dest = BITMASK1(GET_Rn());
6705       opd->imm = (s8)op;
6706       break;
6707
6708     /////////////////////////////////////////////
6709     case 0x08:
6710       switch (op & 0x0f00)
6711       {
6712       case 0x0000: // MOV.B R0,@(disp,Rn)  10000000nnnndddd
6713         opd->source = BITMASK2(GET_Rm(), SHR_R0);
6714         opd->dest = BITMASK1(SHR_MEM);
6715         opd->imm = (op & 0x0f);
6716         break;
6717       case 0x0100: // MOV.W R0,@(disp,Rn)  10000001nnnndddd
6718         opd->source = BITMASK2(GET_Rm(), SHR_R0);
6719         opd->dest = BITMASK1(SHR_MEM);
6720         opd->imm = (op & 0x0f) * 2;
6721         break;
6722       case 0x0400: // MOV.B @(disp,Rm),R0  10000100mmmmdddd
6723         opd->source = BITMASK2(GET_Rm(), SHR_MEM);
6724         opd->dest = BITMASK1(SHR_R0);
6725         opd->imm = (op & 0x0f);
6726         op_flags[i] |= OF_POLL_INSN;
6727         break;
6728       case 0x0500: // MOV.W @(disp,Rm),R0  10000101mmmmdddd
6729         opd->source = BITMASK2(GET_Rm(), SHR_MEM);
6730         opd->dest = BITMASK1(SHR_R0);
6731         opd->imm = (op & 0x0f) * 2;
6732         op_flags[i] |= OF_POLL_INSN;
6733         break;
6734       case 0x0800: // CMP/EQ #imm,R0       10001000iiiiiiii
6735         opd->source = BITMASK1(SHR_R0);
6736         opd->dest = BITMASK1(SHR_T);
6737         opd->imm = (s8)op;
6738         break;
6739       case 0x0d00: // BT/S label 10001101dddddddd
6740       case 0x0f00: // BF/S label 10001111dddddddd
6741         next_is_delay = 1;
6742         // fallthrough
6743       case 0x0900: // BT   label 10001001dddddddd
6744       case 0x0b00: // BF   label 10001011dddddddd
6745         opd->op = (op & 0x0200) ? OP_BRANCH_CF : OP_BRANCH_CT;
6746         opd->source = BITMASK2(SHR_PC, SHR_T);
6747         opd->dest = BITMASK1(SHR_PC);
6748         opd->imm = ((signed int)(op << 24) >> 23);
6749         opd->imm += pc + 4;
6750         if (base_pc <= opd->imm && opd->imm < base_pc + BLOCK_INSN_LIMIT * 2)
6751           op_flags[(opd->imm - base_pc) / 2] |= OF_BTARGET;
6752         break;
6753       default:
6754         goto undefined;
6755       }
6756       break;
6757
6758     /////////////////////////////////////////////
6759     case 0x09:
6760       // MOV.W @(disp,PC),Rn  1001nnnndddddddd
6761       opd->op = OP_LOAD_POOL;
6762       tmp = pc + 2;
6763       if (op_flags[i] & OF_DELAY_OP) {
6764         if (ops[i-1].op == OP_BRANCH)
6765           tmp = ops[i-1].imm;
6766         else if (ops[i-1].op != OP_BRANCH_N)
6767           tmp = 0;
6768       }
6769       opd->source = BITMASK2(SHR_PC, SHR_MEM);
6770       opd->dest = BITMASK1(GET_Rn());
6771       if (tmp) {
6772         opd->imm = tmp + 2 + (op & 0xff) * 2;
6773         if (lowest_literal == 0 || opd->imm < lowest_literal)
6774           lowest_literal = opd->imm;
6775       }
6776       opd->size = 1;
6777       break;
6778
6779     /////////////////////////////////////////////
6780     case 0x0b:
6781       // BSR  label 1011dddddddddddd
6782       opd->dest = BITMASK1(SHR_PR);
6783     case 0x0a:
6784       // BRA  label 1010dddddddddddd
6785       opd->op = OP_BRANCH;
6786       opd->source =  BITMASK1(SHR_PC);
6787       opd->dest |= BITMASK1(SHR_PC);
6788       opd->imm = ((signed int)(op << 20) >> 19);
6789       opd->imm += pc + 4;
6790       opd->cycles = 2;
6791       next_is_delay = 1;
6792       if (!(opd->dest & BITMASK1(SHR_PR))) {
6793         if (base_pc <= opd->imm && opd->imm < base_pc + BLOCK_INSN_LIMIT * 2) {
6794           op_flags[(opd->imm - base_pc) / 2] |= OF_BTARGET;
6795           if (opd->imm <= pc)
6796             end_block = !(op_flags[i+1+next_is_delay] & OF_BTARGET);
6797         } else
6798           end_block = !(op_flags[i+1+next_is_delay] & OF_BTARGET);
6799       } else
6800         op_flags[i+1+next_is_delay] |= OF_BTARGET;
6801       break;
6802
6803     /////////////////////////////////////////////
6804     case 0x0c:
6805       switch (op & 0x0f00)
6806       {
6807       case 0x0000: // MOV.B R0,@(disp,GBR)   11000000dddddddd
6808       case 0x0100: // MOV.W R0,@(disp,GBR)   11000001dddddddd
6809       case 0x0200: // MOV.L R0,@(disp,GBR)   11000010dddddddd
6810         opd->source = BITMASK2(SHR_GBR, SHR_R0);
6811         opd->dest = BITMASK1(SHR_MEM);
6812         opd->size = (op & 0x300) >> 8;
6813         opd->imm = (op & 0xff) << opd->size;
6814         break;
6815       case 0x0400: // MOV.B @(disp,GBR),R0   11000100dddddddd
6816       case 0x0500: // MOV.W @(disp,GBR),R0   11000101dddddddd
6817       case 0x0600: // MOV.L @(disp,GBR),R0   11000110dddddddd
6818         opd->source = BITMASK2(SHR_GBR, SHR_MEM);
6819         opd->dest = BITMASK1(SHR_R0);
6820         opd->size = (op & 0x300) >> 8;
6821         opd->imm = (op & 0xff) << opd->size;
6822         op_flags[i] |= OF_POLL_INSN;
6823         break;
6824       case 0x0300: // TRAPA #imm      11000011iiiiiiii
6825         opd->op = OP_TRAPA;
6826         opd->source = BITMASK4(SHR_SP, SHR_PC, SHR_SR, SHR_T);
6827         opd->dest = BITMASK2(SHR_SP, SHR_PC);
6828         opd->imm = (op & 0xff);
6829         opd->cycles = 8;
6830         op_flags[i+1] |= OF_BTARGET;
6831         break;
6832       case 0x0700: // MOVA @(disp,PC),R0    11000111dddddddd
6833         opd->op = OP_MOVA;
6834         tmp = pc + 2;
6835         if (op_flags[i] & OF_DELAY_OP) {
6836           if (ops[i-1].op == OP_BRANCH)
6837             tmp = ops[i-1].imm;
6838           else if (ops[i-1].op != OP_BRANCH_N)
6839             tmp = 0;
6840         }
6841         opd->dest = BITMASK1(SHR_R0);
6842         if (tmp) {
6843           opd->imm = (tmp + 2 + (op & 0xff) * 4) & ~3;
6844           if (opd->imm >= base_pc) {
6845             if (lowest_mova == 0 || opd->imm < lowest_mova)
6846               lowest_mova = opd->imm;
6847           }
6848         }
6849         break;
6850       case 0x0800: // TST #imm,R0           11001000iiiiiiii
6851         opd->source = BITMASK1(SHR_R0);
6852         opd->dest = BITMASK1(SHR_T);
6853         opd->imm = op & 0xff;
6854         break;
6855       case 0x0900: // AND #imm,R0           11001001iiiiiiii
6856         opd->source = opd->dest = BITMASK1(SHR_R0);
6857         opd->imm = op & 0xff;
6858         break;
6859       case 0x0a00: // XOR #imm,R0           11001010iiiiiiii
6860         opd->source = opd->dest = BITMASK1(SHR_R0);
6861         opd->imm = op & 0xff;
6862         break;
6863       case 0x0b00: // OR  #imm,R0           11001011iiiiiiii
6864         opd->source = opd->dest = BITMASK1(SHR_R0);
6865         opd->imm = op & 0xff;
6866         break;
6867       case 0x0c00: // TST.B #imm,@(R0,GBR)  11001100iiiiiiii
6868         opd->source = BITMASK3(SHR_GBR, SHR_R0, SHR_MEM);
6869         opd->dest = BITMASK1(SHR_T);
6870         opd->imm = op & 0xff;
6871         op_flags[i] |= OF_POLL_INSN;
6872         opd->cycles = 3;
6873         break;
6874       case 0x0d00: // AND.B #imm,@(R0,GBR)  11001101iiiiiiii
6875       case 0x0e00: // XOR.B #imm,@(R0,GBR)  11001110iiiiiiii
6876       case 0x0f00: // OR.B  #imm,@(R0,GBR)  11001111iiiiiiii
6877         opd->source = BITMASK3(SHR_GBR, SHR_R0, SHR_MEM);
6878         opd->dest = BITMASK1(SHR_MEM);
6879         opd->imm = op & 0xff;
6880         opd->cycles = 3;
6881         break;
6882       default:
6883         goto undefined;
6884       }
6885       break;
6886
6887     /////////////////////////////////////////////
6888     case 0x0d:
6889       // MOV.L @(disp,PC),Rn  1101nnnndddddddd
6890       opd->op = OP_LOAD_POOL;
6891       tmp = pc + 2;
6892       if (op_flags[i] & OF_DELAY_OP) {
6893         if (ops[i-1].op == OP_BRANCH)
6894           tmp = ops[i-1].imm;
6895         else if (ops[i-1].op != OP_BRANCH_N)
6896           tmp = 0;
6897       }
6898       opd->source = BITMASK2(SHR_PC, SHR_MEM);
6899       opd->dest = BITMASK1(GET_Rn());
6900       if (tmp) {
6901         opd->imm = (tmp + 2 + (op & 0xff) * 4) & ~3;
6902         if (lowest_literal == 0 || opd->imm < lowest_literal)
6903           lowest_literal = opd->imm;
6904       }
6905       opd->size = 2;
6906       break;
6907
6908     /////////////////////////////////////////////
6909     case 0x0e:
6910       // MOV #imm,Rn   1110nnnniiiiiiii
6911       opd->op = OP_LOAD_CONST;
6912       opd->dest = BITMASK1(GET_Rn());
6913       opd->imm = (s8)op;
6914       break;
6915
6916     default:
6917     undefined:
6918       opd->op = OP_UNDEFINED;
6919       // an unhandled instruction is probably not code if it's not the 1st insn
6920       if (!(op_flags[i] & OF_DELAY_OP) && pc != base_pc)
6921         goto end; 
6922       break;
6923     }
6924
6925     if (op_flags[i] & OF_DELAY_OP) {
6926       switch (opd->op) {
6927       case OP_BRANCH:
6928       case OP_BRANCH_N:
6929       case OP_BRANCH_CT:
6930       case OP_BRANCH_CF:
6931       case OP_BRANCH_R:
6932       case OP_BRANCH_RF:
6933         elprintf(EL_ANOMALY, "%csh2 drc: branch in DS @ %08x",
6934           is_slave ? 's' : 'm', pc);
6935         opd->op = OP_UNDEFINED;
6936         op_flags[i] |= OF_B_IN_DS;
6937         next_is_delay = 0;
6938         break;
6939       }
6940     } else if (!is_divop && i_div >= 0)
6941       i_div = -1;       // divide parser stop
6942   }
6943 end:
6944   i_end = i;
6945   end_pc = pc;
6946
6947   // 2nd pass: some analysis
6948   lowest_literal = end_literals = lowest_mova = 0;
6949   t = T_UNKNOWN; // T flag state
6950   last_btarget = 0;
6951   op = 0; // delay/poll insns counter
6952   is_divop = 0; // divide op insns counter
6953   i_div = -1; // index of current divide op
6954   for (i = 0, pc = base_pc; i < i_end; i++, pc += 2) {
6955     opd = &ops[i];
6956     crc += FETCH_OP(pc);
6957
6958     // propagate T (TODO: DIV0U)
6959     if (op_flags[i] & OF_BTARGET)
6960       t = T_UNKNOWN;
6961
6962     if ((opd->op == OP_BRANCH_CT && t == T_SET) ||
6963         (opd->op == OP_BRANCH_CF && t == T_CLEAR)) {
6964       opd->op = OP_BRANCH;
6965       opd->cycles = (op_flags[i + 1] & OF_DELAY_OP) ? 2 : 3;
6966     } else if ((opd->op == OP_BRANCH_CT && t == T_CLEAR) ||
6967                (opd->op == OP_BRANCH_CF && t == T_SET))
6968       opd->op = OP_BRANCH_N;
6969     else if (OP_ISBRACND(opd->op))
6970       t = (opd->op == OP_BRANCH_CF ? T_SET : T_CLEAR);
6971     else if (opd->op == OP_SETCLRT)
6972       t = (opd->imm ? T_SET : T_CLEAR);
6973     else if (opd->dest & BITMASK1(SHR_T))
6974       t = T_UNKNOWN;
6975
6976     // "overscan" detection: unreachable code after unconditional branch
6977     // this can happen if the insn after a forward branch isn't a local target
6978     if (OP_ISBRAUC(opd->op)) {
6979       if (op_flags[i + 1] & OF_DELAY_OP) {
6980         if (i_end > i + 2 && !(op_flags[i + 2] & OF_BTARGET))
6981           i_end = i + 2;
6982       } else {
6983         if (i_end > i + 1 && !(op_flags[i + 1] & OF_BTARGET))
6984           i_end = i + 1;
6985       }
6986     }
6987
6988     // divide operation verification:
6989     // 1. there must not be a branch target inside
6990     // 2. nothing is in a delay slot (could only be DIV0)
6991     // 2. DIV0/n*(ROTCL+DIV1)/ROTCL:
6992     //     div.div1 > 0 && div.rotcl == div.div1+1 && div.rn =! div.ro
6993     // 3. DIV0/n*DIV1/ROTCL:
6994     //     div.div1 > 0 && div.rotcl == 1 && div.ro == div.rn
6995     if (i_div >= 0) {
6996       if (op_flags[i] & OF_BTARGET) {   // condition 1
6997         ops[i_div].imm = 0;
6998         i_div = -1;
6999       } else if (--is_divop == 0)
7000         i_div = -1;
7001     } else if (opd->op == OP_DIV0) {
7002       struct div *div = &div(opd);
7003       is_divop = div->div1 + div->rotcl;
7004       if (op_flags[i] & OF_DELAY_OP)    // condition 2
7005         opd->imm = 0;
7006       else if (! div->div1 || ! ((div->ro == div->rn && div->rotcl == 1) ||
7007                (div->ro != div->rn && div->rotcl == div->div1+1)))
7008         opd->imm = 0;                   // condition 3+4
7009       else if (is_divop)
7010         i_div = i;
7011     }
7012
7013     // literal pool size detection
7014     if (opd->op == OP_MOVA && opd->imm >= base_pc)
7015       if (lowest_mova == 0 || opd->imm < lowest_mova)
7016         lowest_mova = opd->imm;
7017     if (opd->op == OP_LOAD_POOL) {
7018       if (opd->imm >= base_pc && opd->imm < end_pc + MAX_LITERAL_OFFSET) {
7019         if (end_literals < opd->imm + opd->size * 2)
7020           end_literals = opd->imm + opd->size * 2;
7021         if (lowest_literal == 0 || lowest_literal > opd->imm)
7022           lowest_literal = opd->imm;
7023         if (opd->size == 2) {
7024           // tweak for NFL: treat a 32bit literal as an address and check if it
7025           // points to the literal space. In that case handle it like MOVA. 
7026           tmp = FETCH32(opd->imm) & ~0x20000000; // MUST ignore wt bit here
7027           if (tmp >= end_pc && tmp < end_pc + MAX_LITERAL_OFFSET)
7028             if (lowest_mova == 0 || tmp < lowest_mova)
7029               lowest_mova = tmp;
7030         }
7031       }
7032     }
7033 #if LOOP_DETECTION
7034     // inner loop detection
7035     // 1. a loop always starts with a branch target (for the backwards jump)
7036     // 2. it doesn't contain more than one polling and/or delaying insn
7037     // 3. it doesn't contain unconditional jumps
7038     // 4. no overlapping of loops
7039     if (op_flags[i] & OF_BTARGET) {
7040       last_btarget = i;         // possible loop starting point
7041       op = 0;
7042     }
7043     // XXX let's hope nobody is putting a delay or poll insn in a delay slot :-/
7044     if (OP_ISBRAIMM(opd->op)) {
7045       // BSR, BRA, BT, BF with immediate target
7046       int i_tmp = (opd->imm - base_pc) / 2; // branch target, index in ops
7047       if (i_tmp == last_btarget) // candidate for basic loop optimizer
7048         op_flags[i_tmp] |= OF_BASIC_LOOP;
7049       if (i_tmp == last_btarget && op <= 1) {
7050         op_flags[i_tmp] |= OF_LOOP; // conditions met -> mark loop
7051         last_btarget = i+1;     // condition 4
7052       } else if (opd->op == OP_BRANCH)
7053         last_btarget = i+1;     // condition 3
7054     }
7055     else if (OP_ISBRAIND(opd->op))
7056       // BRAF, BSRF, JMP, JSR, register indirect. treat it as off-limits jump
7057       last_btarget = i+1;       // condition 3
7058     else if (op_flags[i] & (OF_POLL_INSN|OF_DELAY_INSN))
7059       op ++;                    // condition 2 
7060 #endif
7061   }
7062   end_pc = pc;
7063
7064   // end_literals is used to decide to inline a literal or not
7065   // XXX: need better detection if this actually is used in write
7066   if (lowest_literal >= base_pc) {
7067     if (lowest_literal < end_pc) {
7068       dbg(1, "warning: lowest_literal=%08x < end_pc=%08x", lowest_literal, end_pc);
7069       // TODO: does this always mean end_pc covers data?
7070     }
7071   }
7072   if (lowest_mova >= base_pc) {
7073     if (lowest_mova < end_literals) {
7074       dbg(1, "warning: mova=%08x < end_literals=%08x", lowest_mova, end_literals);
7075       end_literals = lowest_mova;
7076     }
7077     if (lowest_mova < end_pc) {
7078       dbg(1, "warning: mova=%08x < end_pc=%08x", lowest_mova, end_pc);
7079       end_literals = end_pc;
7080     }
7081   }
7082   if (lowest_literal >= end_literals)
7083     lowest_literal = end_literals;
7084
7085   if (lowest_literal && end_literals)
7086     for (pc = lowest_literal; pc < end_literals; pc += 2)
7087       crc += FETCH_OP(pc);
7088
7089   *end_pc_out = end_pc;
7090   if (base_literals_out != NULL)
7091     *base_literals_out = (lowest_literal ? lowest_literal : end_pc);
7092   if (end_literals_out != NULL)
7093     *end_literals_out = (end_literals ? end_literals : end_pc);
7094
7095   // crc overflow handling, twice to collect all overflows
7096   crc = (crc & 0xffff) + (crc >> 16);
7097   crc = (crc & 0xffff) + (crc >> 16);
7098   return crc;
7099 }
7100
7101 // vim:shiftwidth=2:ts=2:expandtab