32x: drc: one manual page worth of opcodes implemented (x86 and arm)
[picodrive.git] / cpu / sh2 / compiler.c
CommitLineData
e898de13 1/*
2 * vim:shiftwidth=2:expandtab
3 */
679af8a3 4#include <stdio.h>
5#include <stdlib.h>
6#include <assert.h>
41397701 7
f4bb5d6b 8#include "../../pico/pico_int.h"
679af8a3 9#include "sh2.h"
10#include "compiler.h"
11#include "../drc/cmn.h"
12
e898de13 13#ifndef DRC_DEBUG
14#define DRC_DEBUG 0
15#endif
16
553c3eaa 17#if DRC_DEBUG
f4bb5d6b 18#define dbg(l,...) { \
19 if ((l) & DRC_DEBUG) \
20 elprintf(EL_STATUS, ##__VA_ARGS__); \
21}
22
e898de13 23#include "mame/sh2dasm.h"
24#include <platform/linux/host_dasm.h>
25static int insns_compiled, hash_collisions, host_insn_count;
553c3eaa 26#define COUNT_OP \
27 host_insn_count++
28#else // !DRC_DEBUG
29#define COUNT_OP
30#define dbg(...)
e898de13 31#endif
553c3eaa 32
e898de13 33#if (DRC_DEBUG & 2)
f4bb5d6b 34static u8 *tcache_dsm_ptrs[3];
e898de13 35static char sh2dasm_buff[64];
f4bb5d6b 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)
e898de13 41#endif
42
679af8a3 43#define BLOCK_CYCLE_LIMIT 100
f4bb5d6b 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
49static 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};
679af8a3 54
f4bb5d6b 55static u8 *tcache_bases[3];
56static u8 *tcache_ptrs[3];
57
58// ptr for code emiters
59static u8 *tcache_ptr;
e898de13 60
c18edb34 61// host register tracking
62enum {
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
70typedef struct {
71 u8 reg;
72 u8 type;
73 u16 stamp; // kind of a timestamp
74 u32 val;
75} temp_reg_t;
76
80599a42 77// note: reg_temp[] must have at least the amount of
3863edbd 78// registers used by handlers in worst case (currently 4)
65c75cb0 79#ifdef ARM
80#include "../drc/emit_arm.c"
81
82static const int reg_map_g2h[] = {
c18edb34 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
91static temp_reg_t reg_temp[] = {
92 { 0, },
93 { 1, },
94 { 12, },
95 { 14, },
96 { 2, },
97 { 3, },
65c75cb0 98};
99
100#else
e898de13 101#include "../drc/emit_x86.c"
102
65c75cb0 103static const int reg_map_g2h[] = {
c18edb34 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
3863edbd 112// ax, cx, dx are usually temporaries by convention
c18edb34 113static temp_reg_t reg_temp[] = {
114 { xAX, },
3863edbd 115 { xBX, },
c18edb34 116 { xCX, },
117 { xDX, },
65c75cb0 118};
119
120#endif
121
80599a42 122#define T 0x00000001
123#define S 0x00000002
124#define I 0x000000f0
125#define Q 0x00000100
126#define M 0x00000200
127
679af8a3 128typedef 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
134typedef struct block_desc_ {
135 u32 addr; // SH2 PC address
f4bb5d6b 136 u32 end_addr; // TODO rm?
679af8a3 137 void *tcache_ptr; // translated block for above PC
f4bb5d6b 138 struct block_desc_ *next; // next block with the same PC hash
139#if (DRC_DEBUG & 1)
140 int refcount;
141#endif
679af8a3 142} block_desc;
143
f4bb5d6b 144static const int block_max_counts[3] = {
145 4*1024,
146 256,
147 256,
148};
149static block_desc *block_tables[3];
150static int block_counts[3];
679af8a3 151
f4bb5d6b 152// ROM hash table
679af8a3 153#define MAX_HASH_ENTRIES 1024
154#define HASH_MASK (MAX_HASH_ENTRIES - 1)
f4bb5d6b 155static void **hash_table;
679af8a3 156
679af8a3 157extern void sh2_drc_entry(SH2 *sh2, void *block);
158extern void sh2_drc_exit(void);
159
160// tmp
553c3eaa 161extern void REGPARM(2) sh2_do_op(SH2 *sh2, int opcode);
162static void REGPARM(1) sh2_test_irq(SH2 *sh2);
679af8a3 163
f4bb5d6b 164static void flush_tcache(int tcid)
165{
553c3eaa 166 dbg(1, "tcache #%d flush! (%d/%d, bds %d/%d)", tcid,
f4bb5d6b 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
679af8a3 183static 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
f4bb5d6b 196static block_desc *dr_add_block(u32 addr, int tcache_id, int *blk_id)
679af8a3 197{
f4bb5d6b 198 int *bcount = &block_counts[tcache_id];
679af8a3 199 block_desc *bd;
200
f4bb5d6b 201 if (*bcount >= block_max_counts[tcache_id])
202 return NULL;
679af8a3 203
f4bb5d6b 204 bd = &block_tables[tcache_id][*bcount];
679af8a3 205 bd->addr = addr;
206 bd->tcache_ptr = tcache_ptr;
f4bb5d6b 207 *blk_id = *bcount;
208 (*bcount)++;
679af8a3 209
210 return bd;
211}
212
213#define HASH_FUNC(hash_tab, addr) \
214 ((block_desc **)(hash_tab))[(addr) & HASH_MASK]
215
216// ---------------------------------------------------------------
217
c18edb34 218// register chache
219static u16 rcache_counter;
220
221static temp_reg_t *rcache_evict(void)
41397701 222{
c18edb34 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) {
80599a42 236 printf("no registers to evict, aborting\n");
c18edb34 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];
679af8a3 247}
248
c18edb34 249typedef enum {
250 RC_GR_READ,
251 RC_GR_WRITE,
252 RC_GR_RMW,
253} rc_gr_mode;
254
80599a42 255// note: must not be called when doing conditional code
c18edb34 256static int rcache_get_reg(sh2_reg_e r, rc_gr_mode mode)
679af8a3 257{
c18edb34 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;
679af8a3 265
c18edb34 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 }
679af8a3 278 }
279
c18edb34 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
290do_alloc:
291 if (mode != RC_GR_WRITE)
292 emith_ctx_read(tr->reg, r * 4);
679af8a3 293
c18edb34 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;
679af8a3 298}
299
c18edb34 300static int rcache_get_tmp(void)
679af8a3 301{
c18edb34 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
313do_alloc:
314 tr->type = HR_TEMP;
315 return tr->reg;
316}
317
80599a42 318static 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
345static 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.
354static 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
380do_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
c18edb34 390static 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
80599a42 397 if (i == ARRAY_SIZE(reg_temp) || reg_temp[i].type != HR_TEMP) {
c18edb34 398 printf("rcache_free_tmp fail: #%i hr %d, type %d\n", i, hr, reg_temp[i].type);
80599a42 399 return;
400 }
401
402 reg_temp[i].type = HR_FREE;
c18edb34 403}
404
80599a42 405static void rcache_clean(void)
c18edb34 406{
407 int i;
80599a42 408 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
c18edb34 409 if (reg_temp[i].type == HR_CACHED_DIRTY) {
410 // writeback
411 emith_ctx_write(reg_temp[i].reg, reg_temp[i].val * 4);
80599a42 412 reg_temp[i].type = HR_CACHED;
c18edb34 413 }
80599a42 414}
415
416static void rcache_invalidate(void)
417{
418 int i;
419 for (i = 0; i < ARRAY_SIZE(reg_temp); i++)
c18edb34 420 reg_temp[i].type = HR_FREE;
c18edb34 421 rcache_counter = 0;
422}
423
80599a42 424static void rcache_flush(void)
425{
426 rcache_clean();
427 rcache_invalidate();
428}
429
c18edb34 430// ---------------------------------------------------------------
431
432static 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
438static 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);
679af8a3 444}
445
80599a42 446// arguments must be ready
447// reg cache must be clean before call
448static int emit_memhandler_read(int size)
679af8a3 449{
80599a42 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);
679af8a3 462 break;
463 }
80599a42 464 rcache_invalidate();
465 // assuming arg0 and retval reg matches
466 return rcache_get_tmp_arg(0);
467}
679af8a3 468
80599a42 469static 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();
679af8a3 486}
80599a42 487
488/*
489MOV #imm,Rn 1110nnnniiiiiiii
490MOV.W @(disp,PC),Rn 1001nnnndddddddd
491MOV.L @(disp,PC),Rn 1101nnnndddddddd
492MOV Rm,Rn 0110nnnnmmmm0011
493MOV.B @Rm,Rn 0110nnnnmmmm0000
494MOV.W @Rm,Rn 0110nnnnmmmm0001
495MOV.L @Rm,Rn 0110nnnnmmmm0010
496MOV.B @Rm+,Rn 0110nnnnmmmm0100
497MOV.W @Rm+,Rn 0110nnnnmmmm0101
498MOV.L @Rm+,Rn 0110nnnnmmmm0110
499MOV.B R0,@(disp,Rn) 10000000nnnndddd
500MOV.W R0,@(disp,Rn) 10000001nnnndddd
501MOV.B @(disp,Rm),R0 10000100mmmmdddd
502MOV.W @(disp,Rm),R0 10000101mmmmdddd
503MOV.L @(disp,Rm),Rn 0101nnnnmmmmdddd
504MOV.B R0,@(disp,GBR) 11000000dddddddd
505MOV.W R0,@(disp,GBR) 11000001dddddddd
506MOV.L R0,@(disp,GBR) 11000010dddddddd
507MOV.B @(disp,GBR),R0 11000100dddddddd
508MOV.W @(disp,GBR),R0 11000101dddddddd
509MOV.L @(disp,GBR),R0 11000110dddddddd
510MOVA @(disp,PC),R0 11000111dddddddd
511SWAP.B Rm,Rn 0110nnnnmmmm1000
512SWAP.W Rm,Rn 0110nnnnmmmm1001
80599a42 513ADD #imm,Rn 0111nnnniiiiiiii
80599a42 514CMP/EQ #imm,R0 10001000iiiiiiii
80599a42 515CMP/PZ Rn 0100nnnn00010001
516CMP/PL Rn 0100nnnn00010101
80599a42 517EXTS.B Rm,Rn 0110nnnnmmmm1110
518EXTS.W Rm,Rn 0110nnnnmmmm1111
519EXTU.B Rm,Rn 0110nnnnmmmm1100
520EXTU.W Rm,Rn 0110nnnnmmmm1101
521MAC @Rm+,@Rn+ 0100nnnnmmmm1111
80599a42 522NEG Rm,Rn 0110nnnnmmmm1011
523NEGC Rm,Rn 0110nnnnmmmm1010
80599a42 524AND #imm,R0 11001001iiiiiiii
525AND.B #imm,@(R0,GBR) 11001101iiiiiiii
526NOT Rm,Rn 0110nnnnmmmm0111
80599a42 527OR #imm,R0 11001011iiiiiiii
528OR.B #imm,@(R0,GBR) 11001111iiiiiiii
529TAS.B @Rn 0100nnnn00011011
80599a42 530TST #imm,R0 11001000iiiiiiii
531TST.B #imm,@(R0,GBR) 11001100iiiiiiii
80599a42 532XOR #imm,R0 11001010iiiiiiii
533XOR.B #imm,@(R0,GBR) 11001110iiiiiiii
534ROTL Rn 0100nnnn00000100
535ROTR Rn 0100nnnn00000101
536ROTCL Rn 0100nnnn00100100
537ROTCR Rn 0100nnnn00100101
80599a42 538SHAR Rn 0100nnnn00100001
80599a42 539SHLR Rn 0100nnnn00000001
540SHLL2 Rn 0100nnnn00001000
541SHLR2 Rn 0100nnnn00001001
542SHLL8 Rn 0100nnnn00011000
543SHLR8 Rn 0100nnnn00011001
544SHLL16 Rn 0100nnnn00101000
545SHLR16 Rn 0100nnnn00101001
546LDC Rm,GBR 0100mmmm00011110
547LDC Rm,VBR 0100mmmm00101110
548LDC.L @Rm+,GBR 0100mmmm00010111
549LDC.L @Rm+,VBR 0100mmmm00100111
550LDS Rm,MACH 0100mmmm00001010
551LDS Rm,MACL 0100mmmm00011010
552LDS Rm,PR 0100mmmm00101010
553LDS.L @Rm+,MACH 0100mmmm00000110
554LDS.L @Rm+,MACL 0100mmmm00010110
555LDS.L @Rm+,PR 0100mmmm00100110
556STC.L SR,@–Rn 0100nnnn00000011
557STC.L GBR,@–Rn 0100nnnn00010011
558STC.L VBR,@–Rn 0100nnnn00100011
559STS.L MACH,@–Rn 0100nnnn00000010
560STS.L MACL,@–Rn 0100nnnn00010010
561STS.L PR,@–Rn 0100nnnn00100010
562TRAPA #imm 11000011iiiiiiii
679af8a3 563*/
564
e898de13 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
80599a42 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
679af8a3 585static void *sh2_translate(SH2 *sh2, block_desc *other_block)
586{
f4bb5d6b 587 void *block_entry;
679af8a3 588 block_desc *this_block;
41397701 589 unsigned int pc = sh2->pc;
e898de13 590 int op, delayed_op = 0, test_irq = 0;
f4bb5d6b 591 int tcache_id = 0, blkid = 0;
679af8a3 592 int cycles = 0;
3863edbd 593 u32 tmp, tmp2, tmp3, tmp4;
679af8a3 594
f4bb5d6b 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 }
e898de13 618
f4bb5d6b 619 this_block->next = other_block;
620 if ((sh2->pc & 0xc6000000) == 0x02000000) // ROM
621 HASH_FUNC(hash_table, pc) = this_block;
679af8a3 622
f4bb5d6b 623 block_entry = tcache_ptr;
e898de13 624#if (DRC_DEBUG & 1)
f4bb5d6b 625 printf("== %csh2 block #%d,%d %08x -> %p\n", sh2->is_slave ? 's' : 'm',
626 tcache_id, block_counts[tcache_id], pc, block_entry);
e898de13 627 if (other_block != NULL) {
628 printf(" hash collision with %08x\n", other_block->addr);
629 hash_collisions++;
630 }
679af8a3 631#endif
632
e898de13 633 while (cycles < BLOCK_CYCLE_LIMIT || delayed_op)
679af8a3 634 {
e898de13 635 if (delayed_op > 0)
636 delayed_op--;
637
2b2b46b0 638 op = p32x_sh2_read16(pc, sh2);
e898de13 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
679af8a3 646#endif
679af8a3 647
648 pc += 2;
649 cycles++;
650
651 switch ((op >> 12) & 0x0f)
652 {
3863edbd 653 /////////////////////////////////////////////
679af8a3 654 case 0x00:
80599a42 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;
e898de13 676 case 0x03:
677 CHECK_UNHANDLED_BITS(0xd0);
678 // BRAF Rm 0000mmmm00100011
679 // BSRF Rm 0000mmmm00000011
679af8a3 680 DELAYED_OP;
e898de13 681 if (!(op & 0x20))
682 emit_move_r_imm32(SHR_PR, pc + 2);
c18edb34 683 tmp = rcache_get_reg(SHR_PPC, RC_GR_WRITE);
80599a42 684 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
c18edb34 685 emith_move_r_r(tmp, tmp2);
686 emith_add_r_imm(tmp, pc + 2);
679af8a3 687 cycles++;
e898de13 688 goto end_op;
80599a42 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;
e898de13 729 case 0x09:
80599a42 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);
e898de13 766 goto end_op;
767 case 0x0b:
80599a42 768 CHECK_UNHANDLED_BITS(0xf00);
769 switch (GET_Fx())
770 {
771 case 0: // RTS 0000000000001011
772 DELAYED_OP;
e898de13 773 emit_move_r_r(SHR_PPC, SHR_PR);
774 cycles++;
80599a42 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
e898de13 784 //emit_move_r_r(SHR_PC, SHR_PR);
785 emit_move_r_imm32(SHR_PC, pc - 2);
c18edb34 786 rcache_flush();
f4bb5d6b 787 emith_pass_arg_r(0, CONTEXT_REG);
788 emith_pass_arg_imm(1, op);
e898de13 789 emith_call(sh2_do_op);
790 emit_move_r_r(SHR_PPC, SHR_PC);
791 test_irq = 1;
792 cycles += 3;
80599a42 793 break;
794 default:
795 goto default_;
e898de13 796 }
797 goto end_op;
80599a42 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
3863edbd 819 /////////////////////////////////////////////
80599a42 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;
3863edbd 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;
679af8a3 943 }
944 goto default_;
945
3863edbd 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 /////////////////////////////////////////////
679af8a3 1056 case 0x04:
3863edbd 1057 switch (op & 0x0f)
1058 {
c18edb34 1059 case 0x00:
3863edbd 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);
80599a42 1084 goto end_op;
1085 }
3863edbd 1086 goto default_;
e898de13 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
679af8a3 1098 DELAYED_OP;
e898de13 1099 if (!(op & 0x20))
1100 emit_move_r_imm32(SHR_PR, pc + 2);
1101 emit_move_r_r(SHR_PPC, (op >> 8) & 0x0f);
679af8a3 1102 cycles++;
e898de13 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_;
679af8a3 1110 }
1111 goto default_;
1112
3863edbd 1113 /////////////////////////////////////////////
e898de13 1114 case 0x08:
679af8a3 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--;
679af8a3 1122 // fallthrough
1123 // BT label 10001001dddddddd
1124 case 0x0900:
1125 // BF label 10001011dddddddd
80599a42 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);
e898de13 1142 cycles += 2;
1143 if (!delayed_op)
1144 goto end_block;
1145 goto end_op;
80599a42 1146 }}
679af8a3 1147 goto default_;
679af8a3 1148
3863edbd 1149 /////////////////////////////////////////////
679af8a3 1150 case 0x0a:
1151 // BRA label 1010dddddddddddd
1152 DELAYED_OP;
1153 do_bra:
1154 tmp = ((signed int)(op << 20) >> 19);
e898de13 1155 emit_move_r_imm32(SHR_PPC, pc + tmp + 2);
679af8a3 1156 cycles++;
e898de13 1157 break;
679af8a3 1158
3863edbd 1159 /////////////////////////////////////////////
679af8a3 1160 case 0x0b:
1161 // BSR label 1011dddddddddddd
1162 DELAYED_OP;
e898de13 1163 emit_move_r_imm32(SHR_PR, pc + 2);
679af8a3 1164 goto do_bra;
1165
1166 default:
1167 default_:
1168 emit_move_r_imm32(SHR_PC, pc - 2);
c18edb34 1169 rcache_flush();
f4bb5d6b 1170 emith_pass_arg_r(0, CONTEXT_REG);
1171 emith_pass_arg_imm(1, op);
679af8a3 1172 emith_call(sh2_do_op);
1173 break;
1174 }
1175
e898de13 1176end_op:
6add7875 1177 if (delayed_op == 1)
e898de13 1178 emit_move_r_r(SHR_PC, SHR_PPC);
6add7875 1179
e898de13 1180 if (test_irq && delayed_op != 2) {
c18edb34 1181 rcache_flush();
f4bb5d6b 1182 emith_pass_arg_r(0, CONTEXT_REG);
e898de13 1183 emith_call(sh2_test_irq);
1184 break;
1185 }
6add7875 1186 if (delayed_op == 1)
1187 break;
e898de13 1188
f4bb5d6b 1189 do_host_disasm(tcache_id);
679af8a3 1190 }
1191
1192end_block:
f4bb5d6b 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 }
679af8a3 1217 }
1218
c18edb34 1219 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
1220 emith_sub_r_imm(tmp, cycles << 12);
1221 rcache_flush();
679af8a3 1222 emith_jump(sh2_drc_exit);
f4bb5d6b 1223 tcache_ptrs[tcache_id] = tcache_ptr;
1224
553c3eaa 1225#ifdef ARM
1226 cache_flush_d_inval_i(block_entry, tcache_ptr);
1227#endif
1228
f4bb5d6b 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]);
553c3eaa 1236#if (DRC_DEBUG & 2)
1237 fflush(stdout);
1238#endif
1239
679af8a3 1240 return block_entry;
f4bb5d6b 1241/*
679af8a3 1242unimplemented:
1243 // last op
f4bb5d6b 1244 do_host_disasm(tcache_id);
679af8a3 1245 exit(1);
f4bb5d6b 1246*/
679af8a3 1247}
1248
1249void __attribute__((noinline)) sh2_drc_dispatcher(SH2 *sh2)
1250{
1251 while (((signed int)sh2->sr >> 12) > 0)
1252 {
679af8a3 1253 void *block = NULL;
f4bb5d6b 1254 block_desc *bd = NULL;
6add7875 1255
1256 // FIXME: must avoid doing it so often..
1257 sh2_test_irq(sh2);
1258
f4bb5d6b 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];
679af8a3 1273 block = bd->tcache_ptr;
f4bb5d6b 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 }
679af8a3 1286 }
1287
1288 if (block == NULL)
1289 block = sh2_translate(sh2, bd);
1290
f4bb5d6b 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++;
679af8a3 1296#endif
1297 sh2_drc_entry(sh2, block);
1298 }
1299}
1300
f4bb5d6b 1301static 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
1325void 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
1334void 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
679af8a3 1343void 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
553c3eaa 1356static void REGPARM(1) sh2_test_irq(SH2 *sh2)
679af8a3 1357{
6add7875 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 }
679af8a3 1368}
1369
f4bb5d6b 1370#if (DRC_DEBUG & 1)
1371static 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 }
553c3eaa 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;
f4bb5d6b 1402}
553c3eaa 1403#else
1404#define block_stats()
f4bb5d6b 1405#endif
1406
553c3eaa 1407void sh2_drc_flush_all(void)
1408{
1409 block_stats();
1410 flush_tcache(0);
1411 flush_tcache(1);
1412 flush_tcache(2);
1413}
1414
679af8a3 1415int sh2_drc_init(SH2 *sh2)
1416{
f4bb5d6b 1417 if (block_tables[0] == NULL) {
1418 int i, cnt;
7f5a3fc1 1419
1420 drc_cmn_init();
1421
f4bb5d6b 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)
e898de13 1425 return -1;
1426
f4bb5d6b 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
553c3eaa 1435 // tmp
1436 PicoOpt |= POPT_DIS_VDP_FIFO;
1437
f4bb5d6b 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
e898de13 1442#if (DRC_DEBUG & 1)
1443 hash_collisions = 0;
1444#endif
679af8a3 1445 }
1446
f4bb5d6b 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 }
41397701 1452
679af8a3 1453 return 0;
41397701 1454}
1455
e898de13 1456void sh2_drc_finish(SH2 *sh2)
1457{
f4bb5d6b 1458 if (block_tables[0] != NULL) {
f4bb5d6b 1459 block_stats();
f4bb5d6b 1460 free(block_tables[0]);
1461 memset(block_tables, 0, sizeof(block_tables));
7f5a3fc1 1462
1463 drc_cmn_cleanup();
e898de13 1464 }
1465
f4bb5d6b 1466 if (hash_table != NULL) {
1467 free(hash_table);
1468 hash_table = NULL;
1469 }
e898de13 1470}