32x: drc: one manual page worth of opcodes implemented (x86 and arm)
[picodrive.git] / cpu / sh2 / compiler.c
1 /*
2  * vim:shiftwidth=2:expandtab
3  */
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <assert.h>
7
8 #include "../../pico/pico_int.h"
9 #include "sh2.h"
10 #include "compiler.h"
11 #include "../drc/cmn.h"
12
13 #ifndef DRC_DEBUG
14 #define DRC_DEBUG 0
15 #endif
16
17 #if DRC_DEBUG
18 #define dbg(l,...) { \
19   if ((l) & DRC_DEBUG) \
20     elprintf(EL_STATUS, ##__VA_ARGS__); \
21 }
22
23 #include "mame/sh2dasm.h"
24 #include <platform/linux/host_dasm.h>
25 static int insns_compiled, hash_collisions, host_insn_count;
26 #define COUNT_OP \
27         host_insn_count++
28 #else // !DRC_DEBUG
29 #define COUNT_OP
30 #define dbg(...)
31 #endif
32
33 #if (DRC_DEBUG & 2)
34 static u8 *tcache_dsm_ptrs[3];
35 static char sh2dasm_buff[64];
36 #define do_host_disasm(tcid) \
37   host_dasm(tcache_dsm_ptrs[tcid], tcache_ptr - tcache_dsm_ptrs[tcid]); \
38   tcache_dsm_ptrs[tcid] = tcache_ptr
39 #else
40 #define do_host_disasm(x)
41 #endif
42
43 #define BLOCK_CYCLE_LIMIT 100
44 #define MAX_BLOCK_SIZE (BLOCK_CYCLE_LIMIT * 6 * 6)
45
46 // we have 3 translation cache buffers, split from one drc/cmn buffer.
47 // BIOS shares tcache with data array because it's only used for init
48 // and can be discarded early
49 static const int tcache_sizes[3] = {
50   DRC_TCACHE_SIZE * 6 / 8, // ROM, DRAM
51   DRC_TCACHE_SIZE / 8, // BIOS, data array in master sh2
52   DRC_TCACHE_SIZE / 8, // ... slave
53 };
54
55 static u8 *tcache_bases[3];
56 static u8 *tcache_ptrs[3];
57
58 // ptr for code emiters
59 static u8 *tcache_ptr;
60
61 // host register tracking
62 enum {
63   HR_FREE,
64   HR_CACHED, // 'val' has sh2_reg_e
65   HR_CACHED_DIRTY,
66   HR_CONST,  // 'val' has constant
67   HR_TEMP,   // reg used for temp storage
68 };
69
70 typedef struct {
71   u8 reg;
72   u8 type;
73   u16 stamp; // kind of a timestamp
74   u32 val;
75 } temp_reg_t;
76
77 // note: reg_temp[] must have at least the amount of
78 // registers used by handlers in worst case (currently 4)
79 #ifdef ARM
80 #include "../drc/emit_arm.c"
81
82 static const int reg_map_g2h[] = {
83   -1, -1, -1, -1,
84   -1, -1, -1, -1,
85   -1, -1, -1, -1,
86   -1, -1, -1, -1,
87   -1, -1, -1, -1,
88   -1, -1, -1, -1,
89 };
90
91 static temp_reg_t reg_temp[] = {
92   {  0, },
93   {  1, },
94   { 12, },
95   { 14, },
96   {  2, },
97   {  3, },
98 };
99
100 #else
101 #include "../drc/emit_x86.c"
102
103 static const int reg_map_g2h[] = {
104   -1, -1, -1, -1,
105   -1, -1, -1, -1,
106   -1, -1, -1, -1,
107   -1, -1, -1, -1,
108   -1, -1, -1, -1,
109   -1, -1, -1, -1,
110 };
111
112 // ax, cx, dx are usually temporaries by convention
113 static temp_reg_t reg_temp[] = {
114   { xAX, },
115   { xBX, },
116   { xCX, },
117   { xDX, },
118 };
119
120 #endif
121
122 #define T       0x00000001
123 #define S       0x00000002
124 #define I       0x000000f0
125 #define Q       0x00000100
126 #define M       0x00000200
127
128 typedef enum {
129   SHR_R0 = 0, SHR_R15 = 15,
130   SHR_PC,  SHR_PPC, SHR_PR,   SHR_SR,
131   SHR_GBR, SHR_VBR, SHR_MACH, SHR_MACL,
132 } sh2_reg_e;
133
134 typedef struct block_desc_ {
135   u32 addr;                     // SH2 PC address
136   u32 end_addr;                 // TODO rm?
137   void *tcache_ptr;             // translated block for above PC
138   struct block_desc_ *next;     // next block with the same PC hash
139 #if (DRC_DEBUG & 1)
140   int refcount;
141 #endif
142 } block_desc;
143
144 static const int block_max_counts[3] = {
145   4*1024,
146   256,
147   256,
148 };
149 static block_desc *block_tables[3];
150 static int block_counts[3];
151
152 // ROM hash table
153 #define MAX_HASH_ENTRIES 1024
154 #define HASH_MASK (MAX_HASH_ENTRIES - 1)
155 static void **hash_table;
156
157 extern void sh2_drc_entry(SH2 *sh2, void *block);
158 extern void sh2_drc_exit(void);
159
160 // tmp
161 extern void REGPARM(2) sh2_do_op(SH2 *sh2, int opcode);
162 static void REGPARM(1) sh2_test_irq(SH2 *sh2);
163
164 static void flush_tcache(int tcid)
165 {
166   dbg(1, "tcache #%d flush! (%d/%d, bds %d/%d)", tcid,
167     tcache_ptrs[tcid] - tcache_bases[tcid], tcache_sizes[tcid],
168     block_counts[tcid], block_max_counts[tcid]);
169
170   block_counts[tcid] = 0;
171   tcache_ptrs[tcid] = tcache_bases[tcid];
172   if (tcid == 0) { // ROM, RAM
173     memset(hash_table, 0, sizeof(hash_table[0]) * MAX_HASH_ENTRIES);
174     memset(Pico32xMem->drcblk_ram, 0, sizeof(Pico32xMem->drcblk_ram));
175   }
176   else
177     memset(Pico32xMem->drcblk_da[tcid - 1], 0, sizeof(Pico32xMem->drcblk_da[0]));
178 #if (DRC_DEBUG & 2)
179   tcache_dsm_ptrs[tcid] = tcache_bases[tcid];
180 #endif
181 }
182
183 static void *dr_find_block(block_desc *tab, u32 addr)
184 {
185   for (tab = tab->next; tab != NULL; tab = tab->next)
186     if (tab->addr == addr)
187       break;
188
189   if (tab != NULL)
190     return tab->tcache_ptr;
191
192   printf("block miss for %08x\n", addr);
193   return NULL;
194 }
195
196 static block_desc *dr_add_block(u32 addr, int tcache_id, int *blk_id)
197 {
198   int *bcount = &block_counts[tcache_id];
199   block_desc *bd;
200
201   if (*bcount >= block_max_counts[tcache_id])
202     return NULL;
203
204   bd = &block_tables[tcache_id][*bcount];
205   bd->addr = addr;
206   bd->tcache_ptr = tcache_ptr;
207   *blk_id = *bcount;
208   (*bcount)++;
209
210   return bd;
211 }
212
213 #define HASH_FUNC(hash_tab, addr) \
214   ((block_desc **)(hash_tab))[(addr) & HASH_MASK]
215
216 // ---------------------------------------------------------------
217
218 // register chache
219 static u16 rcache_counter;
220
221 static temp_reg_t *rcache_evict(void)
222 {
223   // evict reg with oldest stamp
224   int i, oldest = -1;
225   u16 min_stamp = (u16)-1;
226
227   for (i = 0; i < ARRAY_SIZE(reg_temp); i++) {
228     if (reg_temp[i].type == HR_CACHED || reg_temp[i].type == HR_CACHED_DIRTY)
229       if (reg_temp[i].stamp <= min_stamp) {
230         min_stamp = reg_temp[i].stamp;
231         oldest = i;
232       }
233   }
234
235   if (oldest == -1) {
236     printf("no registers to evict, aborting\n");
237     exit(1);
238   }
239
240   i = oldest;
241   if (reg_temp[i].type == HR_CACHED_DIRTY) {
242     // writeback
243     emith_ctx_write(reg_temp[i].reg, reg_temp[i].val * 4);
244   }
245
246   return &reg_temp[i];
247 }
248
249 typedef enum {
250   RC_GR_READ,
251   RC_GR_WRITE,
252   RC_GR_RMW,
253 } rc_gr_mode;
254
255 // note: must not be called when doing conditional code
256 static int rcache_get_reg(sh2_reg_e r, rc_gr_mode mode)
257 {
258   temp_reg_t *tr;
259   int i;
260
261   // maybe already statically mapped?
262   i = reg_map_g2h[r];
263   if (i != -1)
264     return i;
265
266   rcache_counter++;
267
268   // maybe already cached?
269   for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
270     if ((reg_temp[i].type == HR_CACHED || reg_temp[i].type == HR_CACHED_DIRTY) &&
271          reg_temp[i].val == r)
272     {
273       reg_temp[i].stamp = rcache_counter;
274       if (mode != RC_GR_READ)
275         reg_temp[i].type = HR_CACHED_DIRTY;
276       return reg_temp[i].reg;
277     }
278   }
279
280   // use any free reg
281   for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
282     if (reg_temp[i].type == HR_FREE || reg_temp[i].type == HR_CONST) {
283       tr = &reg_temp[i];
284       goto do_alloc;
285     }
286   }
287
288   tr = rcache_evict();
289
290 do_alloc:
291   if (mode != RC_GR_WRITE)
292     emith_ctx_read(tr->reg, r * 4);
293
294   tr->type = mode != RC_GR_READ ? HR_CACHED_DIRTY : HR_CACHED;
295   tr->val = r;
296   tr->stamp = rcache_counter;
297   return tr->reg;
298 }
299
300 static int rcache_get_tmp(void)
301 {
302   temp_reg_t *tr;
303   int i;
304
305   for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
306     if (reg_temp[i].type == HR_FREE || reg_temp[i].type == HR_CONST) {
307       tr = &reg_temp[i];
308       goto do_alloc;
309     }
310
311   tr = rcache_evict();
312
313 do_alloc:
314   tr->type = HR_TEMP;
315   return tr->reg;
316 }
317
318 static int rcache_get_arg_id(int arg)
319 {
320   int i, r = 0;
321   host_arg2reg(r, arg);
322
323   for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
324     if (reg_temp[i].reg == r)
325       break;
326
327   if (i == ARRAY_SIZE(reg_temp))
328     // let's just say it's untracked arg reg
329     return r;
330
331   if (reg_temp[i].type == HR_CACHED_DIRTY) {
332     // writeback
333     emith_ctx_write(reg_temp[i].reg, reg_temp[i].val * 4);
334   }
335   else if (reg_temp[i].type == HR_TEMP) {
336     printf("arg %d reg %d already used, aborting\n", arg, r);
337     exit(1);
338   }
339
340   return i;
341 }
342
343 // get a reg to be used as function arg
344 // it's assumed that regs are cleaned before call
345 static int rcache_get_tmp_arg(int arg)
346 {
347   int id = rcache_get_arg_id(arg);
348   reg_temp[id].type = HR_TEMP;
349
350   return reg_temp[id].reg;
351 }
352
353 // same but caches reg. RC_GR_READ only.
354 static int rcache_get_reg_arg(int arg, sh2_reg_e r)
355 {
356   int i, srcr, dstr, dstid;
357
358   dstid = rcache_get_arg_id(arg);
359   dstr = reg_temp[dstid].reg;
360
361   // maybe already statically mapped?
362   srcr = reg_map_g2h[r];
363   if (srcr != -1)
364     goto do_cache;
365
366   // maybe already cached?
367   for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
368     if ((reg_temp[i].type == HR_CACHED || reg_temp[i].type == HR_CACHED_DIRTY) &&
369          reg_temp[i].val == r)
370     {
371       srcr = reg_temp[i].reg;
372       goto do_cache;
373     }
374   }
375
376   // must read
377   srcr = dstr;
378   emith_ctx_read(srcr, r * 4);
379
380 do_cache:
381   if (srcr != dstr)
382     emith_move_r_r(dstr, srcr);
383
384   reg_temp[dstid].stamp = ++rcache_counter;
385   reg_temp[dstid].type = HR_CACHED;
386   reg_temp[dstid].val = r;
387   return dstr;
388 }
389
390 static void rcache_free_tmp(int hr)
391 {
392   int i;
393   for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
394     if (reg_temp[i].reg == hr)
395       break;
396
397   if (i == ARRAY_SIZE(reg_temp) || reg_temp[i].type != HR_TEMP) {
398     printf("rcache_free_tmp fail: #%i hr %d, type %d\n", i, hr, reg_temp[i].type);
399     return;
400   }
401
402   reg_temp[i].type = HR_FREE;
403 }
404
405 static void rcache_clean(void)
406 {
407   int i;
408   for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
409     if (reg_temp[i].type == HR_CACHED_DIRTY) {
410       // writeback
411       emith_ctx_write(reg_temp[i].reg, reg_temp[i].val * 4);
412       reg_temp[i].type = HR_CACHED;
413     }
414 }
415
416 static void rcache_invalidate(void)
417 {
418   int i;
419   for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
420     reg_temp[i].type = HR_FREE;
421   rcache_counter = 0;
422 }
423
424 static void rcache_flush(void)
425 {
426   rcache_clean();
427   rcache_invalidate();
428 }
429
430 // ---------------------------------------------------------------
431
432 static void emit_move_r_imm32(sh2_reg_e dst, u32 imm)
433 {
434   int hr = rcache_get_reg(dst, RC_GR_WRITE);
435   emith_move_r_imm(hr, imm);
436 }
437
438 static void emit_move_r_r(sh2_reg_e dst, sh2_reg_e src)
439 {
440   int hr_d = rcache_get_reg(dst, RC_GR_WRITE);
441   int hr_s = rcache_get_reg(src, RC_GR_READ);
442
443   emith_move_r_r(hr_d, hr_s);
444 }
445
446 // arguments must be ready
447 // reg cache must be clean before call
448 static int emit_memhandler_read(int size)
449 {
450   int ctxr;
451   host_arg2reg(ctxr, 1);
452   emith_move_r_r(ctxr, CONTEXT_REG);
453   switch (size) {
454   case 0: // 8
455     emith_call(p32x_sh2_read8);
456     break;
457   case 1: // 16
458     emith_call(p32x_sh2_read16);
459     break;
460   case 2: // 32
461     emith_call(p32x_sh2_read32);
462     break;
463   }
464   rcache_invalidate();
465   // assuming arg0 and retval reg matches
466   return rcache_get_tmp_arg(0);
467 }
468
469 static void emit_memhandler_write(int size)
470 {
471   int ctxr;
472   host_arg2reg(ctxr, 2);
473   emith_move_r_r(ctxr, CONTEXT_REG);
474   switch (size) {
475   case 0: // 8
476     emith_call(p32x_sh2_write8);
477     break;
478   case 1: // 16
479     emith_call(p32x_sh2_write16);
480     break;
481   case 2: // 32
482     emith_call(p32x_sh2_write32);
483     break;
484   }
485   rcache_invalidate();
486 }
487
488 /*
489 MOV   #imm,Rn       1110nnnniiiiiiii
490 MOV.W @(disp,PC),Rn 1001nnnndddddddd
491 MOV.L @(disp,PC),Rn 1101nnnndddddddd
492 MOV   Rm,Rn         0110nnnnmmmm0011
493 MOV.B @Rm,Rn        0110nnnnmmmm0000
494 MOV.W @Rm,Rn        0110nnnnmmmm0001
495 MOV.L @Rm,Rn        0110nnnnmmmm0010
496 MOV.B @Rm+,Rn       0110nnnnmmmm0100
497 MOV.W @Rm+,Rn       0110nnnnmmmm0101
498 MOV.L @Rm+,Rn       0110nnnnmmmm0110
499 MOV.B R0,@(disp,Rn) 10000000nnnndddd
500 MOV.W R0,@(disp,Rn) 10000001nnnndddd
501 MOV.B @(disp,Rm),R0 10000100mmmmdddd
502 MOV.W @(disp,Rm),R0 10000101mmmmdddd
503 MOV.L @(disp,Rm),Rn 0101nnnnmmmmdddd
504 MOV.B    R0,@(disp,GBR)   11000000dddddddd
505 MOV.W    R0,@(disp,GBR)   11000001dddddddd
506 MOV.L    R0,@(disp,GBR)   11000010dddddddd
507 MOV.B    @(disp,GBR),R0   11000100dddddddd
508 MOV.W    @(disp,GBR),R0   11000101dddddddd
509 MOV.L    @(disp,GBR),R0   11000110dddddddd
510 MOVA     @(disp,PC),R0    11000111dddddddd
511 SWAP.B Rm,Rn              0110nnnnmmmm1000
512 SWAP.W Rm,Rn              0110nnnnmmmm1001
513 ADD         #imm,Rn  0111nnnniiiiiiii
514 CMP/EQ      #imm,R0  10001000iiiiiiii
515 CMP/PZ      Rn       0100nnnn00010001
516 CMP/PL      Rn       0100nnnn00010101
517 EXTS.B Rm,Rn         0110nnnnmmmm1110
518 EXTS.W Rm,Rn         0110nnnnmmmm1111
519 EXTU.B Rm,Rn         0110nnnnmmmm1100
520 EXTU.W Rm,Rn         0110nnnnmmmm1101
521 MAC       @Rm+,@Rn+  0100nnnnmmmm1111
522 NEG       Rm,Rn      0110nnnnmmmm1011
523 NEGC      Rm,Rn      0110nnnnmmmm1010
524 AND      #imm,R0             11001001iiiiiiii
525 AND.B    #imm,@(R0,GBR)      11001101iiiiiiii
526 NOT      Rm,Rn               0110nnnnmmmm0111
527 OR       #imm,R0             11001011iiiiiiii
528 OR.B     #imm,@(R0,GBR)      11001111iiiiiiii
529 TAS.B    @Rn                 0100nnnn00011011
530 TST      #imm,R0             11001000iiiiiiii
531 TST.B    #imm,@(R0,GBR)      11001100iiiiiiii
532 XOR      #imm,R0             11001010iiiiiiii
533 XOR.B    #imm,@(R0,GBR)      11001110iiiiiiii
534 ROTL     Rn        0100nnnn00000100
535 ROTR     Rn        0100nnnn00000101
536 ROTCL    Rn        0100nnnn00100100
537 ROTCR    Rn        0100nnnn00100101
538 SHAR     Rn        0100nnnn00100001
539 SHLR     Rn        0100nnnn00000001
540 SHLL2    Rn        0100nnnn00001000
541 SHLR2    Rn        0100nnnn00001001
542 SHLL8    Rn        0100nnnn00011000
543 SHLR8    Rn        0100nnnn00011001
544 SHLL16 Rn          0100nnnn00101000
545 SHLR16 Rn          0100nnnn00101001
546 LDC      Rm,GBR    0100mmmm00011110
547 LDC      Rm,VBR    0100mmmm00101110
548 LDC.L    @Rm+,GBR  0100mmmm00010111
549 LDC.L    @Rm+,VBR  0100mmmm00100111
550 LDS      Rm,MACH   0100mmmm00001010
551 LDS      Rm,MACL   0100mmmm00011010
552 LDS      Rm,PR     0100mmmm00101010
553 LDS.L    @Rm+,MACH 0100mmmm00000110
554 LDS.L    @Rm+,MACL 0100mmmm00010110
555 LDS.L    @Rm+,PR   0100mmmm00100110
556 STC.L    SR,@–Rn   0100nnnn00000011
557 STC.L    GBR,@–Rn  0100nnnn00010011
558 STC.L    VBR,@–Rn  0100nnnn00100011
559 STS.L    MACH,@–Rn 0100nnnn00000010
560 STS.L    MACL,@–Rn 0100nnnn00010010
561 STS.L    PR,@–Rn   0100nnnn00100010
562 TRAPA    #imm      11000011iiiiiiii
563 */
564
565 #define DELAYED_OP \
566   delayed_op = 2
567
568 #define CHECK_UNHANDLED_BITS(mask) { \
569   if ((op & (mask)) != 0) \
570     goto default_; \
571 }
572
573 #define GET_Fx() \
574   ((op >> 4) & 0x0f)
575
576 #define GET_Rm GET_Fx
577
578 #define GET_Rn() \
579   ((op >> 8) & 0x0f)
580
581 #define CHECK_FX_GT_3() \
582   if (GET_Fx() > 3) \
583     goto default_
584
585 static void *sh2_translate(SH2 *sh2, block_desc *other_block)
586 {
587   void *block_entry;
588   block_desc *this_block;
589   unsigned int pc = sh2->pc;
590   int op, delayed_op = 0, test_irq = 0;
591   int tcache_id = 0, blkid = 0;
592   int cycles = 0;
593   u32 tmp, tmp2, tmp3, tmp4;
594
595   // validate PC
596   tmp = sh2->pc >> 29;
597   if ((tmp != 0 && tmp != 1 && tmp != 6) || sh2->pc == 0) {
598     printf("invalid PC, aborting: %08x\n", sh2->pc);
599     // FIXME: be less destructive
600     exit(1);
601   }
602
603   if ((sh2->pc & 0xe0000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
604     // data_array, BIOS have separate tcache (shared)
605     tcache_id = 1 + sh2->is_slave;
606   }
607
608   tcache_ptr = tcache_ptrs[tcache_id];
609   this_block = dr_add_block(pc, tcache_id, &blkid);
610
611   tmp = tcache_ptr - tcache_bases[tcache_id];
612   if (tmp > tcache_sizes[tcache_id] - MAX_BLOCK_SIZE || this_block == NULL) {
613     flush_tcache(tcache_id);
614     tcache_ptr = tcache_ptrs[tcache_id];
615     other_block = NULL; // also gone too due to flush
616     this_block = dr_add_block(pc, tcache_id, &blkid);
617   }
618
619   this_block->next = other_block;
620   if ((sh2->pc & 0xc6000000) == 0x02000000) // ROM
621     HASH_FUNC(hash_table, pc) = this_block;
622
623   block_entry = tcache_ptr;
624 #if (DRC_DEBUG & 1)
625   printf("== %csh2 block #%d,%d %08x -> %p\n", sh2->is_slave ? 's' : 'm',
626     tcache_id, block_counts[tcache_id], pc, block_entry);
627   if (other_block != NULL) {
628     printf(" hash collision with %08x\n", other_block->addr);
629     hash_collisions++;
630   }
631 #endif
632
633   while (cycles < BLOCK_CYCLE_LIMIT || delayed_op)
634   {
635     if (delayed_op > 0)
636       delayed_op--;
637
638     op = p32x_sh2_read16(pc, sh2);
639
640 #if (DRC_DEBUG & 3)
641     insns_compiled++;
642 #if (DRC_DEBUG & 2)
643     DasmSH2(sh2dasm_buff, pc, op);
644     printf("%08x %04x %s\n", pc, op, sh2dasm_buff);
645 #endif
646 #endif
647
648     pc += 2;
649     cycles++;
650
651     switch ((op >> 12) & 0x0f)
652     {
653     /////////////////////////////////////////////
654     case 0x00:
655       switch (op & 0x0f)
656       {
657       case 0x02:
658         tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
659         switch (GET_Fx())
660         {
661         case 0: // STC SR,Rn  0000nnnn00000010
662           tmp2 = SHR_SR;
663           break;
664         case 1: // STC GBR,Rn 0000nnnn00010010
665           tmp2 = SHR_GBR;
666           break;
667         case 2: // STC VBR,Rn 0000nnnn00100010
668           tmp2 = SHR_VBR;
669           break;
670         default:
671           goto default_;
672         }
673         tmp2 = rcache_get_reg(tmp2, RC_GR_READ);
674         emith_move_r_r(tmp, tmp2);
675         goto end_op;
676       case 0x03:
677         CHECK_UNHANDLED_BITS(0xd0);
678         // BRAF Rm    0000mmmm00100011
679         // BSRF Rm    0000mmmm00000011
680         DELAYED_OP;
681         if (!(op & 0x20))
682           emit_move_r_imm32(SHR_PR, pc + 2);
683         tmp = rcache_get_reg(SHR_PPC, RC_GR_WRITE);
684         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
685         emith_move_r_r(tmp, tmp2);
686         emith_add_r_imm(tmp, pc + 2);
687         cycles++;
688         goto end_op;
689       case 0x04: // MOV.B Rm,@(R0,Rn)   0000nnnnmmmm0100
690       case 0x05: // MOV.W Rm,@(R0,Rn)   0000nnnnmmmm0101
691       case 0x06: // MOV.L Rm,@(R0,Rn)   0000nnnnmmmm0110
692         rcache_clean();
693         tmp  = rcache_get_reg_arg(0, SHR_R0);
694         tmp2 = rcache_get_reg_arg(1, GET_Rm());
695         tmp3 = rcache_get_reg(GET_Rn(), RC_GR_READ);
696         emith_add_r_r(tmp, tmp3);
697         emit_memhandler_write(op & 3);
698         goto end_op;
699       case 0x07:
700         // MUL.L     Rm,Rn      0000nnnnmmmm0111
701         tmp  = rcache_get_reg(GET_Rn(), RC_GR_READ);
702         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
703         tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
704         emith_mul(tmp3, tmp2, tmp);
705         cycles++;
706         goto end_op;
707       case 0x08:
708         CHECK_UNHANDLED_BITS(0xf00);
709         switch (GET_Fx())
710         {
711         case 0: // CLRT               0000000000001000
712           tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
713           emith_bic_r_imm(tmp, T);
714           break;
715         case 1: // SETT               0000000000011000
716           tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
717           emith_or_r_imm(tmp, T);
718           break;
719         case 2: // CLRMAC             0000000000101000
720           tmp = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
721           emith_move_r_imm(tmp, 0);
722           tmp = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
723           emith_move_r_imm(tmp, 0);
724           break;
725         default:
726           goto default_;
727         }
728         goto end_op;
729       case 0x09:
730         switch (GET_Fx())
731         {
732         case 0: // NOP        0000000000001001
733           CHECK_UNHANDLED_BITS(0xf00);
734           break;
735         case 1: // DIV0U      0000000000011001
736           CHECK_UNHANDLED_BITS(0xf00);
737           tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
738           emith_bic_r_imm(tmp, M|Q|T);
739           break;
740         case 2: // MOVT Rn    0000nnnn00101001
741           tmp  = rcache_get_reg(SHR_SR, RC_GR_READ);
742           tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
743           emith_clear_msb(tmp2, tmp, 31);
744           break;
745         default:
746           goto default_;
747         }
748         goto end_op;
749       case 0x0a:
750         tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
751         switch (GET_Fx())
752         {
753         case 0: // STS      MACH,Rn   0000nnnn00001010
754           tmp2 = rcache_get_reg(SHR_MACH, RC_GR_READ);
755           break;
756         case 1: // STS      MACL,Rn   0000nnnn00011010
757           tmp2 = rcache_get_reg(SHR_MACL, RC_GR_READ);
758           break;
759         case 2: // STS      PR,Rn     0000nnnn00101010
760           tmp2 = rcache_get_reg(SHR_PR, RC_GR_READ);
761           break;
762         default:
763           goto default_;
764         }
765         emith_move_r_r(tmp, tmp2);
766         goto end_op;
767       case 0x0b:
768         CHECK_UNHANDLED_BITS(0xf00);
769         switch (GET_Fx())
770         {
771         case 0: // RTS        0000000000001011
772           DELAYED_OP;
773           emit_move_r_r(SHR_PPC, SHR_PR);
774           cycles++;
775           break;
776         case 1: // SLEEP      0000000000011011
777           emit_move_r_imm32(SHR_PC, pc - 2);
778           tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
779           emith_clear_msb(tmp, tmp, 20); // clear cycles
780           test_irq = 1;
781           cycles = 1;
782           break;
783         case 2: // RTE        0000000000101011
784           //emit_move_r_r(SHR_PC, SHR_PR);
785           emit_move_r_imm32(SHR_PC, pc - 2);
786           rcache_flush();
787           emith_pass_arg_r(0, CONTEXT_REG);
788           emith_pass_arg_imm(1, op);
789           emith_call(sh2_do_op);
790           emit_move_r_r(SHR_PPC, SHR_PC);
791           test_irq = 1;
792           cycles += 3;
793           break;
794         default:
795           goto default_;
796         }
797         goto end_op;
798       case 0x0c: // MOV.B    @(R0,Rm),Rn      0000nnnnmmmm1100
799       case 0x0d: // MOV.W    @(R0,Rm),Rn      0000nnnnmmmm1101
800       case 0x0e: // MOV.L    @(R0,Rm),Rn      0000nnnnmmmm1110
801         rcache_clean();
802         tmp  = rcache_get_reg_arg(0, SHR_R0);
803         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
804         emith_add_r_r(tmp, tmp2);
805         tmp  = emit_memhandler_read(op & 3);
806         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
807         rcache_free_tmp(tmp);
808         if ((op & 3) != 2) {
809           emith_sext(tmp2, tmp, (op & 1) ? 16 : 8);
810         } else
811           emith_move_r_r(tmp2, tmp);
812         goto end_op;
813       case 0x0f: // MAC.L   @Rm+,@Rn+  0000nnnnmmmm1111
814         // TODO
815         break;
816       }
817       goto default_;
818
819     /////////////////////////////////////////////
820     case 0x01:
821       // MOV.L Rm,@(disp,Rn) 0001nnnnmmmmdddd
822       rcache_clean();
823       tmp  = rcache_get_reg_arg(0, GET_Rn());
824       tmp2 = rcache_get_reg_arg(1, GET_Rm());
825       emith_add_r_imm(tmp, (op & 0x0f) * 4);
826       emit_memhandler_write(2);
827       goto end_op;
828
829     case 0x02:
830       switch (op & 0x0f)
831       {
832       case 0x00: // MOV.B Rm,@Rn        0010nnnnmmmm0000
833       case 0x01: // MOV.W Rm,@Rn        0010nnnnmmmm0001
834       case 0x02: // MOV.L Rm,@Rn        0010nnnnmmmm0010
835         rcache_clean();
836         rcache_get_reg_arg(0, GET_Rn());
837         rcache_get_reg_arg(1, GET_Rm());
838         emit_memhandler_write(op & 3);
839         goto end_op;
840       case 0x04: // MOV.B Rm,@–Rn       0010nnnnmmmm0100
841       case 0x05: // MOV.W Rm,@–Rn       0010nnnnmmmm0101
842       case 0x06: // MOV.L Rm,@–Rn       0010nnnnmmmm0110
843         tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
844         emith_sub_r_imm(tmp, (1 << (op & 3)));
845         rcache_clean();
846         rcache_get_reg_arg(0, GET_Rn());
847         rcache_get_reg_arg(1, GET_Rm());
848         emit_memhandler_write(op & 3);
849         goto end_op;
850       case 0x07: // DIV0S Rm,Rn         0010nnnnmmmm0111
851         tmp  = rcache_get_reg(SHR_SR, RC_GR_RMW);
852         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
853         tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
854         emith_bic_r_imm(tmp, M|Q|T);
855         emith_tst_r_imm(tmp2, (1<<31));
856         EMITH_SJMP_START(DCOND_EQ);
857         emith_or_r_imm_c(DCOND_NE, tmp, Q);
858         EMITH_SJMP_END(DCOND_EQ);
859         emith_tst_r_imm(tmp3, (1<<31));
860         EMITH_SJMP_START(DCOND_EQ);
861         emith_or_r_imm_c(DCOND_NE, tmp, M);
862         EMITH_SJMP_END(DCOND_EQ);
863         emith_teq_r_r(tmp2, tmp3);
864         EMITH_SJMP_START(DCOND_PL);
865         emith_or_r_imm_c(DCOND_MI, tmp, T);
866         EMITH_SJMP_END(DCOND_PL);
867         goto end_op;
868       case 0x08: // TST Rm,Rn           0010nnnnmmmm1000
869         tmp  = rcache_get_reg(SHR_SR, RC_GR_RMW);
870         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
871         tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
872         emith_bic_r_imm(tmp, T);
873         emith_tst_r_r(tmp2, tmp3);
874         EMITH_SJMP_START(DCOND_NE);
875         emith_or_r_imm_c(DCOND_EQ, tmp, T);
876         EMITH_SJMP_END(DCOND_NE);
877         goto end_op;
878       case 0x09: // AND Rm,Rn           0010nnnnmmmm1001
879         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW);
880         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
881         emith_and_r_r(tmp, tmp2);
882         goto end_op;
883       case 0x0a: // XOR Rm,Rn           0010nnnnmmmm1010
884         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW);
885         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
886         emith_eor_r_r(tmp, tmp2);
887         goto end_op;
888       case 0x0b: // OR  Rm,Rn           0010nnnnmmmm1011
889         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW);
890         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
891         emith_or_r_r(tmp, tmp2);
892         goto end_op;
893       case 0x0c: // CMP/STR Rm,Rn       0010nnnnmmmm1100
894         tmp  = rcache_get_tmp();
895         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
896         tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
897         emith_eor_r_r_r(tmp, tmp2, tmp3);
898         tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
899         emith_bic_r_imm(tmp2, T);
900         emith_tst_r_imm(tmp, 0x000000ff);
901         EMITH_SJMP_START(DCOND_NE);
902         emith_or_r_imm_c(DCOND_EQ, tmp2, T);
903         EMITH_SJMP_END(DCOND_NE);
904         emith_tst_r_imm(tmp, 0x0000ff00);
905         EMITH_SJMP_START(DCOND_NE);
906         emith_or_r_imm_c(DCOND_EQ, tmp2, T);
907         EMITH_SJMP_END(DCOND_NE);
908         emith_tst_r_imm(tmp, 0x00ff0000);
909         EMITH_SJMP_START(DCOND_NE);
910         emith_or_r_imm_c(DCOND_EQ, tmp2, T);
911         EMITH_SJMP_END(DCOND_NE);
912         emith_tst_r_imm(tmp, 0xff000000);
913         EMITH_SJMP_START(DCOND_NE);
914         emith_or_r_imm_c(DCOND_EQ, tmp2, T);
915         EMITH_SJMP_END(DCOND_NE);
916         rcache_free_tmp(tmp);
917         goto end_op;
918       case 0x0d: // XTRCT  Rm,Rn        0010nnnnmmmm1101
919         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW);
920         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
921         emith_lsr(tmp, tmp, 16);
922         emith_or_r_r_r_lsl(tmp, tmp, tmp2, 16);
923         goto end_op;
924       case 0x0e: // MULU.W Rm,Rn        0010nnnnmmmm1110
925       case 0x0f: // MULS.W Rm,Rn        0010nnnnmmmm1111
926         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
927         tmp  = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
928         if (op & 1) {
929           emith_sext(tmp, tmp2, 16);
930         } else
931           emith_clear_msb(tmp, tmp2, 16);
932         tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
933         tmp2 = rcache_get_tmp();
934         if (op & 1) {
935           emith_sext(tmp2, tmp3, 16);
936         } else
937           emith_clear_msb(tmp2, tmp3, 16);
938         emith_mul(tmp, tmp, tmp2);
939         rcache_free_tmp(tmp2);
940 //      FIXME: causes timing issues in Doom?
941 //        cycles++;
942         goto end_op;
943       }
944       goto default_;
945
946     /////////////////////////////////////////////
947     case 0x03:
948       switch (op & 0x0f)
949       {
950       case 0x00: // CMP/EQ Rm,Rn        0011nnnnmmmm0000
951       case 0x02: // CMP/HS Rm,Rn        0011nnnnmmmm0010
952       case 0x03: // CMP/GE Rm,Rn        0011nnnnmmmm0011
953       case 0x06: // CMP/HI Rm,Rn        0011nnnnmmmm0110
954       case 0x07: // CMP/GT Rm,Rn        0011nnnnmmmm0111
955         tmp  = rcache_get_reg(SHR_SR, RC_GR_RMW);
956         tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
957         tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
958         emith_bic_r_imm(tmp, T);
959         emith_cmp_r_r(tmp2, tmp3);
960         switch (op & 0x07)
961         {
962         case 0x00: // CMP/EQ
963           EMITH_SJMP_START(DCOND_NE);
964           emith_or_r_imm_c(DCOND_EQ, tmp, T);
965           EMITH_SJMP_END(DCOND_NE);
966           break;
967         case 0x02: // CMP/HS
968           EMITH_SJMP_START(DCOND_LO);
969           emith_or_r_imm_c(DCOND_HS, tmp, T);
970           EMITH_SJMP_END(DCOND_LO);
971           break;
972         case 0x03: // CMP/GE
973           EMITH_SJMP_START(DCOND_LT);
974           emith_or_r_imm_c(DCOND_GE, tmp, T);
975           EMITH_SJMP_END(DCOND_LT);
976           break;
977         case 0x06: // CMP/HI
978           EMITH_SJMP_START(DCOND_LS);
979           emith_or_r_imm_c(DCOND_HI, tmp, T);
980           EMITH_SJMP_END(DCOND_LS);
981           break;
982         case 0x07: // CMP/GT
983           EMITH_SJMP_START(DCOND_LE);
984           emith_or_r_imm_c(DCOND_GT, tmp, T);
985           EMITH_SJMP_END(DCOND_LE);
986           break;
987         }
988         goto end_op;
989       case 0x04: // DIV1    Rm,Rn       0011nnnnmmmm0100
990         // TODO
991         break;
992       case 0x05: // DMULU.L Rm,Rn       0011nnnnmmmm0101
993         tmp  = rcache_get_reg(GET_Rn(), RC_GR_READ);
994         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
995         tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
996         tmp4 = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
997         emith_mul_u64(tmp3, tmp4, tmp, tmp2);
998         goto end_op;
999       case 0x08: // SUB     Rm,Rn       0011nnnnmmmm1000
1000       case 0x0c: // ADD     Rm,Rn       0011nnnnmmmm1100
1001         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1002         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1003         if (op & 4) {
1004           emith_add_r_r(tmp, tmp2);
1005         } else
1006           emith_sub_r_r(tmp, tmp2);
1007         goto end_op;
1008       case 0x0a: // SUBC    Rm,Rn       0011nnnnmmmm1010
1009       case 0x0e: // ADDC    Rm,Rn       0011nnnnmmmm1110
1010         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1011         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1012         tmp3 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1013         if (op & 4) { // adc
1014           emith_set_carry(tmp3);
1015           emith_adcf_r_r(tmp, tmp2);
1016           tmp  = DCOND_CS; // set condition
1017           tmp2 = DCOND_CC; // clear condition
1018         } else {
1019           emith_set_carry_sub(tmp3);
1020           emith_sbcf_r_r(tmp, tmp2);
1021           tmp  = DCOND_LO; // using LO/HS instead of CS/CC
1022           tmp2 = DCOND_HS; // due to ARM target..
1023         }
1024         EMITH_SJMP_START(tmp);
1025         emith_bic_r_imm_c(tmp2, tmp3, T);
1026         EMITH_SJMP_END(tmp);
1027         EMITH_SJMP_START(tmp2);
1028         emith_or_r_imm_c(tmp, tmp3, T);
1029         EMITH_SJMP_END(tmp2);
1030         goto end_op;
1031       case 0x0b: // SUBV    Rm,Rn       0011nnnnmmmm1011
1032       case 0x0f: // ADDV    Rm,Rn       0011nnnnmmmm1111
1033         tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1034         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1035         tmp3 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1036         emith_bic_r_imm(tmp3, T);
1037         if (op & 4) {
1038           emith_addf_r_r(tmp, tmp2);
1039         } else
1040           emith_subf_r_r(tmp, tmp2);
1041         EMITH_SJMP_START(DCOND_VC);
1042         emith_or_r_imm_c(DCOND_VS, tmp3, T);
1043         EMITH_SJMP_END(DCOND_VC);
1044         goto end_op;
1045       case 0x0d: // DMULS.L Rm,Rn       0011nnnnmmmm1101
1046         tmp  = rcache_get_reg(GET_Rn(), RC_GR_READ);
1047         tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1048         tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
1049         tmp4 = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
1050         emith_mul_s64(tmp3, tmp4, tmp, tmp2);
1051         goto end_op;
1052       }
1053       goto default_;
1054
1055     /////////////////////////////////////////////
1056     case 0x04:
1057       switch (op & 0x0f)
1058       {
1059       case 0x00:
1060         switch (GET_Fx())
1061         {
1062         case 0: // SHLL Rn    0100nnnn00000000
1063         case 2: // SHAL Rn    0100nnnn00100000
1064           tmp  = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1065           tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1066           emith_bic_r_imm(tmp2, T);
1067           emith_lslf(tmp, tmp, 1);
1068           EMITH_SJMP_START(DCOND_CC);
1069           emith_or_r_imm_c(DCOND_CS, tmp2, T);
1070           EMITH_SJMP_END(DCOND_CC);
1071           goto end_op;
1072         case 1: // DT Rn      0100nnnn00010000
1073           if (p32x_sh2_read16(pc, sh2) == 0x8bfd) { // BF #-2
1074             emith_sh2_dtbf_loop();
1075             goto end_op;
1076           }
1077           tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1078           tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1079           emith_bic_r_imm(tmp2, T);
1080           emith_subf_r_imm(tmp, 1);
1081           EMITH_SJMP_START(DCOND_NE);
1082           emith_or_r_imm_c(DCOND_EQ, tmp2, T);
1083           EMITH_SJMP_END(DCOND_NE);
1084           goto end_op;
1085         }
1086         goto default_;
1087       case 0x07:
1088         if ((op & 0xf0) != 0)
1089           goto default_;
1090         // LDC.L @Rm+,SR  0100mmmm00000111
1091         test_irq = 1;
1092         goto default_;
1093       case 0x0b:
1094         if ((op & 0xd0) != 0)
1095           goto default_;
1096         // JMP  @Rm   0100mmmm00101011
1097         // JSR  @Rm   0100mmmm00001011
1098         DELAYED_OP;
1099         if (!(op & 0x20))
1100           emit_move_r_imm32(SHR_PR, pc + 2);
1101         emit_move_r_r(SHR_PPC, (op >> 8) & 0x0f);
1102         cycles++;
1103         goto end_op;
1104       case 0x0e:
1105         if ((op & 0xf0) != 0)
1106           goto default_;
1107         // LDC Rm,SR  0100mmmm00001110
1108         test_irq = 1;
1109         goto default_;
1110       }
1111       goto default_;
1112
1113     /////////////////////////////////////////////
1114     case 0x08:
1115       switch (op & 0x0f00) {
1116       // BT/S label 10001101dddddddd
1117       case 0x0d00:
1118       // BF/S label 10001111dddddddd
1119       case 0x0f00:
1120         DELAYED_OP;
1121         cycles--;
1122         // fallthrough
1123       // BT   label 10001001dddddddd
1124       case 0x0900:
1125       // BF   label 10001011dddddddd
1126       case 0x0b00: {
1127         // jmp_cond ~ cond when guest doesn't jump
1128         int jmp_cond  = (op & 0x0200) ? DCOND_NE : DCOND_EQ;
1129         int insn_cond = (op & 0x0200) ? DCOND_EQ : DCOND_NE;
1130         signed int offs = ((signed int)(op << 24) >> 23);
1131         tmp = rcache_get_reg(delayed_op ? SHR_PPC : SHR_PC, RC_GR_WRITE);
1132         emith_move_r_imm(tmp, pc + (delayed_op ? 2 : 0));
1133         emith_sh2_test_t();
1134         EMITH_SJMP_START(jmp_cond);
1135         if (!delayed_op)
1136           offs += 2;
1137         if (offs < 0) {
1138           emith_sub_r_imm_c(insn_cond, tmp, -offs);
1139         } else
1140           emith_add_r_imm_c(insn_cond, tmp, offs);
1141         EMITH_SJMP_END(jmp_cond);
1142         cycles += 2;
1143         if (!delayed_op)
1144           goto end_block;
1145         goto end_op;
1146       }}
1147       goto default_;
1148
1149     /////////////////////////////////////////////
1150     case 0x0a:
1151       // BRA  label 1010dddddddddddd
1152       DELAYED_OP;
1153     do_bra:
1154       tmp = ((signed int)(op << 20) >> 19);
1155       emit_move_r_imm32(SHR_PPC, pc + tmp + 2);
1156       cycles++;
1157       break;
1158
1159     /////////////////////////////////////////////
1160     case 0x0b:
1161       // BSR  label 1011dddddddddddd
1162       DELAYED_OP;
1163       emit_move_r_imm32(SHR_PR, pc + 2);
1164       goto do_bra;
1165
1166     default:
1167     default_:
1168       emit_move_r_imm32(SHR_PC, pc - 2);
1169       rcache_flush();
1170       emith_pass_arg_r(0, CONTEXT_REG);
1171       emith_pass_arg_imm(1, op);
1172       emith_call(sh2_do_op);
1173       break;
1174     }
1175
1176 end_op:
1177     if (delayed_op == 1)
1178       emit_move_r_r(SHR_PC, SHR_PPC);
1179
1180     if (test_irq && delayed_op != 2) {
1181       rcache_flush();
1182       emith_pass_arg_r(0, CONTEXT_REG);
1183       emith_call(sh2_test_irq);
1184       break;
1185     }
1186     if (delayed_op == 1)
1187       break;
1188
1189     do_host_disasm(tcache_id);
1190   }
1191
1192 end_block:
1193   this_block->end_addr = pc;
1194
1195   // mark memory blocks as containing compiled code
1196   if ((sh2->pc & 0xe0000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
1197     // data array, BIOS
1198     u16 *drcblk = Pico32xMem->drcblk_da[sh2->is_slave];
1199     tmp =  (this_block->addr & 0xfff) >> SH2_DRCBLK_DA_SHIFT;
1200     tmp2 = (this_block->end_addr & 0xfff) >> SH2_DRCBLK_DA_SHIFT;
1201     Pico32xMem->drcblk_da[sh2->is_slave][tmp] = (blkid << 1) | 1;
1202     for (++tmp; tmp < tmp2; tmp++) {
1203       if (drcblk[tmp])
1204         break; // dont overwrite overlay block
1205       drcblk[tmp] = blkid << 1;
1206     }
1207   }
1208   else if ((this_block->addr & 0xc7fc0000) == 0x06000000) { // DRAM
1209     tmp =  (this_block->addr & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT;
1210     tmp2 = (this_block->end_addr & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT;
1211     Pico32xMem->drcblk_ram[tmp] = (blkid << 1) | 1;
1212     for (++tmp; tmp < tmp2; tmp++) {
1213       if (Pico32xMem->drcblk_ram[tmp])
1214         break;
1215       Pico32xMem->drcblk_ram[tmp] = blkid << 1;
1216     }
1217   }
1218
1219   tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
1220   emith_sub_r_imm(tmp, cycles << 12);
1221   rcache_flush();
1222   emith_jump(sh2_drc_exit);
1223   tcache_ptrs[tcache_id] = tcache_ptr;
1224
1225 #ifdef ARM
1226   cache_flush_d_inval_i(block_entry, tcache_ptr);
1227 #endif
1228
1229   do_host_disasm(tcache_id);
1230   dbg(1, " block #%d,%d tcache %d/%d, insns %d -> %d %.3f",
1231     tcache_id, block_counts[tcache_id],
1232     tcache_ptr - tcache_bases[tcache_id], tcache_sizes[tcache_id],
1233     insns_compiled, host_insn_count, (double)host_insn_count / insns_compiled);
1234   if ((sh2->pc & 0xc6000000) == 0x02000000) // ROM
1235     dbg(1, "  hash collisions %d/%d", hash_collisions, block_counts[tcache_id]);
1236 #if (DRC_DEBUG & 2)
1237   fflush(stdout);
1238 #endif
1239
1240   return block_entry;
1241 /*
1242 unimplemented:
1243   // last op
1244   do_host_disasm(tcache_id);
1245   exit(1);
1246 */
1247 }
1248
1249 void __attribute__((noinline)) sh2_drc_dispatcher(SH2 *sh2)
1250 {
1251   while (((signed int)sh2->sr >> 12) > 0)
1252   {
1253     void *block = NULL;
1254     block_desc *bd = NULL;
1255
1256     // FIXME: must avoid doing it so often..
1257     sh2_test_irq(sh2);
1258
1259     // we have full block id tables for data_array and RAM
1260     // BIOS goes to data_array table too
1261     if ((sh2->pc & 0xff000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
1262       int blkid = Pico32xMem->drcblk_da[sh2->is_slave][(sh2->pc & 0xfff) >> SH2_DRCBLK_DA_SHIFT];
1263       if (blkid & 1) {
1264         bd = &block_tables[1 + sh2->is_slave][blkid >> 1];
1265         block = bd->tcache_ptr;
1266       }
1267     }
1268     // RAM
1269     else if ((sh2->pc & 0xc6000000) == 0x06000000) {
1270       int blkid = Pico32xMem->drcblk_ram[(sh2->pc & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT];
1271       if (blkid & 1) {
1272         bd = &block_tables[0][blkid >> 1];
1273         block = bd->tcache_ptr;
1274       }
1275     }
1276     // ROM
1277     else if ((sh2->pc & 0xc6000000) == 0x02000000) {
1278       bd = HASH_FUNC(hash_table, sh2->pc);
1279
1280       if (bd != NULL) {
1281         if (bd->addr == sh2->pc)
1282           block = bd->tcache_ptr;
1283         else
1284           block = dr_find_block(bd, sh2->pc);
1285       }
1286     }
1287
1288     if (block == NULL)
1289       block = sh2_translate(sh2, bd);
1290
1291     dbg(4, "= %csh2 enter %08x %p, c=%d", sh2->is_slave ? 's' : 'm',
1292       sh2->pc, block, (signed int)sh2->sr >> 12);
1293 #if (DRC_DEBUG & 1)
1294     if (bd != NULL)
1295       bd->refcount++;
1296 #endif
1297     sh2_drc_entry(sh2, block);
1298   }
1299 }
1300
1301 static void sh2_smc_rm_block(u16 *drcblk, u16 *p, block_desc *btab, u32 a)
1302 {
1303   u16 id = *p >> 1;
1304   block_desc *bd = btab + id;
1305
1306   dbg(1, "  killing block %08x", bd->addr);
1307   bd->addr = bd->end_addr = 0;
1308
1309   while (p > drcblk && (p[-1] >> 1) == id)
1310     p--;
1311
1312   // check for possible overlay block
1313   if (p > 0 && p[-1] != 0) {
1314     bd = btab + (p[-1] >> 1);
1315     if (bd->addr <= a && a < bd->end_addr)
1316       sh2_smc_rm_block(drcblk, p - 1, btab, a);
1317   }
1318
1319   do {
1320     *p++ = 0;
1321   }
1322   while ((*p >> 1) == id);
1323 }
1324
1325 void sh2_drc_wcheck_ram(unsigned int a, int val, int cpuid)
1326 {
1327   u16 *drcblk = Pico32xMem->drcblk_ram;
1328   u16 *p = drcblk + ((a & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT);
1329
1330   dbg(1, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a);
1331   sh2_smc_rm_block(drcblk, p, block_tables[0], a);
1332 }
1333
1334 void sh2_drc_wcheck_da(unsigned int a, int val, int cpuid)
1335 {
1336   u16 *drcblk = Pico32xMem->drcblk_da[cpuid];
1337   u16 *p = drcblk + ((a & 0xfff) >> SH2_DRCBLK_DA_SHIFT);
1338
1339   dbg(1, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a);
1340   sh2_smc_rm_block(drcblk, p, block_tables[1 + cpuid], a);
1341 }
1342
1343 void sh2_execute(SH2 *sh2, int cycles)
1344 {
1345   sh2->cycles_aim += cycles;
1346   cycles = sh2->cycles_aim - sh2->cycles_done;
1347
1348   // cycles are kept in SHR_SR unused bits (upper 20)
1349   sh2->sr &= 0x3f3;
1350   sh2->sr |= cycles << 12;
1351   sh2_drc_dispatcher(sh2);
1352
1353   sh2->cycles_done += cycles - ((signed int)sh2->sr >> 12);
1354 }
1355
1356 static void REGPARM(1) sh2_test_irq(SH2 *sh2)
1357 {
1358   if (sh2->pending_level > ((sh2->sr >> 4) & 0x0f))
1359   {
1360     if (sh2->pending_irl > sh2->pending_int_irq)
1361       sh2_do_irq(sh2, sh2->pending_irl, 64 + sh2->pending_irl/2);
1362     else {
1363       sh2_do_irq(sh2, sh2->pending_int_irq, sh2->pending_int_vector);
1364       sh2->pending_int_irq = 0; // auto-clear
1365       sh2->pending_level = sh2->pending_irl;
1366     }
1367   }
1368 }
1369
1370 #if (DRC_DEBUG & 1)
1371 static void block_stats(void)
1372 {
1373   int c, b, i, total = 0;
1374
1375   for (b = 0; b < ARRAY_SIZE(block_tables); b++)
1376     for (i = 0; i < block_counts[b]; i++)
1377       if (block_tables[b][i].addr != 0)
1378         total += block_tables[b][i].refcount;
1379
1380   for (c = 0; c < 10; c++) {
1381     block_desc *blk, *maxb = NULL;
1382     int max = 0;
1383     for (b = 0; b < ARRAY_SIZE(block_tables); b++) {
1384       for (i = 0; i < block_counts[b]; i++) {
1385         blk = &block_tables[b][i];
1386         if (blk->addr != 0 && blk->refcount > max) {
1387           max = blk->refcount;
1388           maxb = blk;
1389         }
1390       }
1391     }
1392     if (maxb == NULL)
1393       break;
1394     printf("%08x %9d %2.3f%%\n", maxb->addr, maxb->refcount,
1395       (double)maxb->refcount / total * 100.0);
1396     maxb->refcount = 0;
1397   }
1398
1399   for (b = 0; b < ARRAY_SIZE(block_tables); b++)
1400     for (i = 0; i < block_counts[b]; i++)
1401       block_tables[b][i].refcount = 0;
1402 }
1403 #else
1404 #define block_stats()
1405 #endif
1406
1407 void sh2_drc_flush_all(void)
1408 {
1409   block_stats();
1410   flush_tcache(0);
1411   flush_tcache(1);
1412   flush_tcache(2);
1413 }
1414
1415 int sh2_drc_init(SH2 *sh2)
1416 {
1417   if (block_tables[0] == NULL) {
1418     int i, cnt;
1419
1420     drc_cmn_init();
1421
1422     cnt = block_max_counts[0] + block_max_counts[1] + block_max_counts[2];
1423     block_tables[0] = calloc(cnt, sizeof(*block_tables[0]));
1424     if (block_tables[0] == NULL)
1425       return -1;
1426
1427     memset(block_counts, 0, sizeof(block_counts));
1428     tcache_bases[0] = tcache_ptrs[0] = tcache;
1429
1430     for (i = 1; i < ARRAY_SIZE(block_tables); i++) {
1431       block_tables[i] = block_tables[i - 1] + block_max_counts[i - 1];
1432       tcache_bases[i] = tcache_ptrs[i] = tcache_bases[i - 1] + tcache_sizes[i - 1];
1433     }
1434
1435     // tmp
1436     PicoOpt |= POPT_DIS_VDP_FIFO;
1437
1438 #if (DRC_DEBUG & 2)
1439     for (i = 0; i < ARRAY_SIZE(block_tables); i++)
1440       tcache_dsm_ptrs[i] = tcache_bases[i];
1441 #endif
1442 #if (DRC_DEBUG & 1)
1443     hash_collisions = 0;
1444 #endif
1445   }
1446
1447   if (hash_table == NULL) {
1448     hash_table = calloc(sizeof(hash_table[0]), MAX_HASH_ENTRIES);
1449     if (hash_table == NULL)
1450       return -1;
1451   }
1452
1453   return 0;
1454 }
1455
1456 void sh2_drc_finish(SH2 *sh2)
1457 {
1458   if (block_tables[0] != NULL) {
1459     block_stats();
1460     free(block_tables[0]);
1461     memset(block_tables, 0, sizeof(block_tables));
1462
1463     drc_cmn_cleanup();
1464   }
1465
1466   if (hash_table != NULL) {
1467     free(hash_table);
1468     hash_table = NULL;
1469   }
1470 }