use mem mapping for idle loop det
[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 515EXTS.B Rm,Rn 0110nnnnmmmm1110
516EXTS.W Rm,Rn 0110nnnnmmmm1111
517EXTU.B Rm,Rn 0110nnnnmmmm1100
518EXTU.W Rm,Rn 0110nnnnmmmm1101
519MAC @Rm+,@Rn+ 0100nnnnmmmm1111
80599a42 520NEG Rm,Rn 0110nnnnmmmm1011
521NEGC Rm,Rn 0110nnnnmmmm1010
80599a42 522AND #imm,R0 11001001iiiiiiii
523AND.B #imm,@(R0,GBR) 11001101iiiiiiii
524NOT Rm,Rn 0110nnnnmmmm0111
80599a42 525OR #imm,R0 11001011iiiiiiii
526OR.B #imm,@(R0,GBR) 11001111iiiiiiii
527TAS.B @Rn 0100nnnn00011011
80599a42 528TST #imm,R0 11001000iiiiiiii
529TST.B #imm,@(R0,GBR) 11001100iiiiiiii
80599a42 530XOR #imm,R0 11001010iiiiiiii
531XOR.B #imm,@(R0,GBR) 11001110iiiiiiii
80599a42 532SHLL2 Rn 0100nnnn00001000
533SHLR2 Rn 0100nnnn00001001
534SHLL8 Rn 0100nnnn00011000
535SHLR8 Rn 0100nnnn00011001
536SHLL16 Rn 0100nnnn00101000
537SHLR16 Rn 0100nnnn00101001
538LDC Rm,GBR 0100mmmm00011110
539LDC Rm,VBR 0100mmmm00101110
80599a42 540LDS Rm,MACH 0100mmmm00001010
541LDS Rm,MACL 0100mmmm00011010
542LDS Rm,PR 0100mmmm00101010
80599a42 543TRAPA #imm 11000011iiiiiiii
679af8a3 544*/
545
e898de13 546#define DELAYED_OP \
547 delayed_op = 2
548
549#define CHECK_UNHANDLED_BITS(mask) { \
550 if ((op & (mask)) != 0) \
551 goto default_; \
552}
553
80599a42 554#define GET_Fx() \
555 ((op >> 4) & 0x0f)
556
557#define GET_Rm GET_Fx
558
559#define GET_Rn() \
560 ((op >> 8) & 0x0f)
561
ed8cf79b 562#define CHECK_FX_LT(n) \
563 if (GET_Fx() < n) \
80599a42 564 goto default_
565
679af8a3 566static void *sh2_translate(SH2 *sh2, block_desc *other_block)
567{
f4bb5d6b 568 void *block_entry;
679af8a3 569 block_desc *this_block;
41397701 570 unsigned int pc = sh2->pc;
e898de13 571 int op, delayed_op = 0, test_irq = 0;
f4bb5d6b 572 int tcache_id = 0, blkid = 0;
679af8a3 573 int cycles = 0;
3863edbd 574 u32 tmp, tmp2, tmp3, tmp4;
679af8a3 575
f4bb5d6b 576 // validate PC
577 tmp = sh2->pc >> 29;
578 if ((tmp != 0 && tmp != 1 && tmp != 6) || sh2->pc == 0) {
579 printf("invalid PC, aborting: %08x\n", sh2->pc);
580 // FIXME: be less destructive
581 exit(1);
582 }
583
584 if ((sh2->pc & 0xe0000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
585 // data_array, BIOS have separate tcache (shared)
586 tcache_id = 1 + sh2->is_slave;
587 }
588
589 tcache_ptr = tcache_ptrs[tcache_id];
590 this_block = dr_add_block(pc, tcache_id, &blkid);
591
592 tmp = tcache_ptr - tcache_bases[tcache_id];
593 if (tmp > tcache_sizes[tcache_id] - MAX_BLOCK_SIZE || this_block == NULL) {
594 flush_tcache(tcache_id);
595 tcache_ptr = tcache_ptrs[tcache_id];
596 other_block = NULL; // also gone too due to flush
597 this_block = dr_add_block(pc, tcache_id, &blkid);
598 }
e898de13 599
f4bb5d6b 600 this_block->next = other_block;
601 if ((sh2->pc & 0xc6000000) == 0x02000000) // ROM
602 HASH_FUNC(hash_table, pc) = this_block;
679af8a3 603
f4bb5d6b 604 block_entry = tcache_ptr;
e898de13 605#if (DRC_DEBUG & 1)
f4bb5d6b 606 printf("== %csh2 block #%d,%d %08x -> %p\n", sh2->is_slave ? 's' : 'm',
607 tcache_id, block_counts[tcache_id], pc, block_entry);
e898de13 608 if (other_block != NULL) {
609 printf(" hash collision with %08x\n", other_block->addr);
610 hash_collisions++;
611 }
679af8a3 612#endif
613
e898de13 614 while (cycles < BLOCK_CYCLE_LIMIT || delayed_op)
679af8a3 615 {
e898de13 616 if (delayed_op > 0)
617 delayed_op--;
618
2b2b46b0 619 op = p32x_sh2_read16(pc, sh2);
e898de13 620
621#if (DRC_DEBUG & 3)
622 insns_compiled++;
623#if (DRC_DEBUG & 2)
624 DasmSH2(sh2dasm_buff, pc, op);
625 printf("%08x %04x %s\n", pc, op, sh2dasm_buff);
626#endif
679af8a3 627#endif
679af8a3 628
629 pc += 2;
630 cycles++;
631
632 switch ((op >> 12) & 0x0f)
633 {
3863edbd 634 /////////////////////////////////////////////
679af8a3 635 case 0x00:
80599a42 636 switch (op & 0x0f)
637 {
638 case 0x02:
639 tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
640 switch (GET_Fx())
641 {
642 case 0: // STC SR,Rn 0000nnnn00000010
643 tmp2 = SHR_SR;
644 break;
645 case 1: // STC GBR,Rn 0000nnnn00010010
646 tmp2 = SHR_GBR;
647 break;
648 case 2: // STC VBR,Rn 0000nnnn00100010
649 tmp2 = SHR_VBR;
650 break;
651 default:
652 goto default_;
653 }
ed8cf79b 654 tmp3 = rcache_get_reg(tmp2, RC_GR_READ);
655 emith_move_r_r(tmp, tmp3);
656 if (tmp2 == SHR_SR)
657 emith_clear_msb(tmp, tmp, 20); // reserved bits defined by ISA as 0
80599a42 658 goto end_op;
e898de13 659 case 0x03:
660 CHECK_UNHANDLED_BITS(0xd0);
661 // BRAF Rm 0000mmmm00100011
662 // BSRF Rm 0000mmmm00000011
679af8a3 663 DELAYED_OP;
e898de13 664 if (!(op & 0x20))
665 emit_move_r_imm32(SHR_PR, pc + 2);
c18edb34 666 tmp = rcache_get_reg(SHR_PPC, RC_GR_WRITE);
80599a42 667 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
c18edb34 668 emith_move_r_r(tmp, tmp2);
669 emith_add_r_imm(tmp, pc + 2);
679af8a3 670 cycles++;
e898de13 671 goto end_op;
80599a42 672 case 0x04: // MOV.B Rm,@(R0,Rn) 0000nnnnmmmm0100
673 case 0x05: // MOV.W Rm,@(R0,Rn) 0000nnnnmmmm0101
674 case 0x06: // MOV.L Rm,@(R0,Rn) 0000nnnnmmmm0110
675 rcache_clean();
676 tmp = rcache_get_reg_arg(0, SHR_R0);
677 tmp2 = rcache_get_reg_arg(1, GET_Rm());
678 tmp3 = rcache_get_reg(GET_Rn(), RC_GR_READ);
679 emith_add_r_r(tmp, tmp3);
680 emit_memhandler_write(op & 3);
681 goto end_op;
682 case 0x07:
683 // MUL.L Rm,Rn 0000nnnnmmmm0111
684 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
685 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
686 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
687 emith_mul(tmp3, tmp2, tmp);
688 cycles++;
689 goto end_op;
690 case 0x08:
691 CHECK_UNHANDLED_BITS(0xf00);
692 switch (GET_Fx())
693 {
694 case 0: // CLRT 0000000000001000
695 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
696 emith_bic_r_imm(tmp, T);
697 break;
698 case 1: // SETT 0000000000011000
699 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
700 emith_or_r_imm(tmp, T);
701 break;
702 case 2: // CLRMAC 0000000000101000
703 tmp = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
704 emith_move_r_imm(tmp, 0);
705 tmp = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
706 emith_move_r_imm(tmp, 0);
707 break;
708 default:
709 goto default_;
710 }
711 goto end_op;
e898de13 712 case 0x09:
80599a42 713 switch (GET_Fx())
714 {
715 case 0: // NOP 0000000000001001
716 CHECK_UNHANDLED_BITS(0xf00);
717 break;
718 case 1: // DIV0U 0000000000011001
719 CHECK_UNHANDLED_BITS(0xf00);
720 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
721 emith_bic_r_imm(tmp, M|Q|T);
722 break;
723 case 2: // MOVT Rn 0000nnnn00101001
724 tmp = rcache_get_reg(SHR_SR, RC_GR_READ);
725 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
726 emith_clear_msb(tmp2, tmp, 31);
727 break;
728 default:
729 goto default_;
730 }
731 goto end_op;
732 case 0x0a:
733 tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
734 switch (GET_Fx())
735 {
736 case 0: // STS MACH,Rn 0000nnnn00001010
ed8cf79b 737 tmp2 = SHR_MACH;
80599a42 738 break;
739 case 1: // STS MACL,Rn 0000nnnn00011010
ed8cf79b 740 tmp2 = SHR_MACL;
80599a42 741 break;
742 case 2: // STS PR,Rn 0000nnnn00101010
ed8cf79b 743 tmp2 = SHR_PR;
80599a42 744 break;
745 default:
746 goto default_;
747 }
ed8cf79b 748 tmp2 = rcache_get_reg(tmp2, RC_GR_READ);
80599a42 749 emith_move_r_r(tmp, tmp2);
e898de13 750 goto end_op;
751 case 0x0b:
80599a42 752 CHECK_UNHANDLED_BITS(0xf00);
753 switch (GET_Fx())
754 {
755 case 0: // RTS 0000000000001011
756 DELAYED_OP;
e898de13 757 emit_move_r_r(SHR_PPC, SHR_PR);
758 cycles++;
80599a42 759 break;
760 case 1: // SLEEP 0000000000011011
761 emit_move_r_imm32(SHR_PC, pc - 2);
762 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
763 emith_clear_msb(tmp, tmp, 20); // clear cycles
764 test_irq = 1;
765 cycles = 1;
766 break;
767 case 2: // RTE 0000000000101011
e898de13 768 //emit_move_r_r(SHR_PC, SHR_PR);
769 emit_move_r_imm32(SHR_PC, pc - 2);
c18edb34 770 rcache_flush();
f4bb5d6b 771 emith_pass_arg_r(0, CONTEXT_REG);
772 emith_pass_arg_imm(1, op);
e898de13 773 emith_call(sh2_do_op);
774 emit_move_r_r(SHR_PPC, SHR_PC);
775 test_irq = 1;
776 cycles += 3;
80599a42 777 break;
778 default:
779 goto default_;
e898de13 780 }
781 goto end_op;
80599a42 782 case 0x0c: // MOV.B @(R0,Rm),Rn 0000nnnnmmmm1100
783 case 0x0d: // MOV.W @(R0,Rm),Rn 0000nnnnmmmm1101
784 case 0x0e: // MOV.L @(R0,Rm),Rn 0000nnnnmmmm1110
785 rcache_clean();
786 tmp = rcache_get_reg_arg(0, SHR_R0);
787 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
788 emith_add_r_r(tmp, tmp2);
789 tmp = emit_memhandler_read(op & 3);
790 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
791 rcache_free_tmp(tmp);
792 if ((op & 3) != 2) {
793 emith_sext(tmp2, tmp, (op & 1) ? 16 : 8);
794 } else
795 emith_move_r_r(tmp2, tmp);
796 goto end_op;
797 case 0x0f: // MAC.L @Rm+,@Rn+ 0000nnnnmmmm1111
798 // TODO
799 break;
800 }
801 goto default_;
802
3863edbd 803 /////////////////////////////////////////////
80599a42 804 case 0x01:
805 // MOV.L Rm,@(disp,Rn) 0001nnnnmmmmdddd
806 rcache_clean();
807 tmp = rcache_get_reg_arg(0, GET_Rn());
808 tmp2 = rcache_get_reg_arg(1, GET_Rm());
809 emith_add_r_imm(tmp, (op & 0x0f) * 4);
810 emit_memhandler_write(2);
811 goto end_op;
812
813 case 0x02:
814 switch (op & 0x0f)
815 {
816 case 0x00: // MOV.B Rm,@Rn 0010nnnnmmmm0000
817 case 0x01: // MOV.W Rm,@Rn 0010nnnnmmmm0001
818 case 0x02: // MOV.L Rm,@Rn 0010nnnnmmmm0010
819 rcache_clean();
820 rcache_get_reg_arg(0, GET_Rn());
821 rcache_get_reg_arg(1, GET_Rm());
822 emit_memhandler_write(op & 3);
823 goto end_op;
824 case 0x04: // MOV.B Rm,@–Rn 0010nnnnmmmm0100
825 case 0x05: // MOV.W Rm,@–Rn 0010nnnnmmmm0101
826 case 0x06: // MOV.L Rm,@–Rn 0010nnnnmmmm0110
827 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
828 emith_sub_r_imm(tmp, (1 << (op & 3)));
829 rcache_clean();
830 rcache_get_reg_arg(0, GET_Rn());
831 rcache_get_reg_arg(1, GET_Rm());
832 emit_memhandler_write(op & 3);
833 goto end_op;
834 case 0x07: // DIV0S Rm,Rn 0010nnnnmmmm0111
835 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
836 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
837 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
838 emith_bic_r_imm(tmp, M|Q|T);
839 emith_tst_r_imm(tmp2, (1<<31));
840 EMITH_SJMP_START(DCOND_EQ);
841 emith_or_r_imm_c(DCOND_NE, tmp, Q);
842 EMITH_SJMP_END(DCOND_EQ);
843 emith_tst_r_imm(tmp3, (1<<31));
844 EMITH_SJMP_START(DCOND_EQ);
845 emith_or_r_imm_c(DCOND_NE, tmp, M);
846 EMITH_SJMP_END(DCOND_EQ);
847 emith_teq_r_r(tmp2, tmp3);
848 EMITH_SJMP_START(DCOND_PL);
849 emith_or_r_imm_c(DCOND_MI, tmp, T);
850 EMITH_SJMP_END(DCOND_PL);
851 goto end_op;
3863edbd 852 case 0x08: // TST Rm,Rn 0010nnnnmmmm1000
853 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
854 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
855 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
856 emith_bic_r_imm(tmp, T);
857 emith_tst_r_r(tmp2, tmp3);
858 EMITH_SJMP_START(DCOND_NE);
859 emith_or_r_imm_c(DCOND_EQ, tmp, T);
860 EMITH_SJMP_END(DCOND_NE);
861 goto end_op;
862 case 0x09: // AND Rm,Rn 0010nnnnmmmm1001
863 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
864 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
865 emith_and_r_r(tmp, tmp2);
866 goto end_op;
867 case 0x0a: // XOR Rm,Rn 0010nnnnmmmm1010
868 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
869 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
870 emith_eor_r_r(tmp, tmp2);
871 goto end_op;
872 case 0x0b: // OR Rm,Rn 0010nnnnmmmm1011
873 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
874 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
875 emith_or_r_r(tmp, tmp2);
876 goto end_op;
877 case 0x0c: // CMP/STR Rm,Rn 0010nnnnmmmm1100
878 tmp = rcache_get_tmp();
879 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
880 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
881 emith_eor_r_r_r(tmp, tmp2, tmp3);
882 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
883 emith_bic_r_imm(tmp2, T);
884 emith_tst_r_imm(tmp, 0x000000ff);
885 EMITH_SJMP_START(DCOND_NE);
886 emith_or_r_imm_c(DCOND_EQ, tmp2, T);
887 EMITH_SJMP_END(DCOND_NE);
888 emith_tst_r_imm(tmp, 0x0000ff00);
889 EMITH_SJMP_START(DCOND_NE);
890 emith_or_r_imm_c(DCOND_EQ, tmp2, T);
891 EMITH_SJMP_END(DCOND_NE);
892 emith_tst_r_imm(tmp, 0x00ff0000);
893 EMITH_SJMP_START(DCOND_NE);
894 emith_or_r_imm_c(DCOND_EQ, tmp2, T);
895 EMITH_SJMP_END(DCOND_NE);
896 emith_tst_r_imm(tmp, 0xff000000);
897 EMITH_SJMP_START(DCOND_NE);
898 emith_or_r_imm_c(DCOND_EQ, tmp2, T);
899 EMITH_SJMP_END(DCOND_NE);
900 rcache_free_tmp(tmp);
901 goto end_op;
902 case 0x0d: // XTRCT Rm,Rn 0010nnnnmmmm1101
903 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
904 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
905 emith_lsr(tmp, tmp, 16);
906 emith_or_r_r_r_lsl(tmp, tmp, tmp2, 16);
907 goto end_op;
908 case 0x0e: // MULU.W Rm,Rn 0010nnnnmmmm1110
909 case 0x0f: // MULS.W Rm,Rn 0010nnnnmmmm1111
910 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
911 tmp = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
912 if (op & 1) {
913 emith_sext(tmp, tmp2, 16);
914 } else
915 emith_clear_msb(tmp, tmp2, 16);
916 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
917 tmp2 = rcache_get_tmp();
918 if (op & 1) {
919 emith_sext(tmp2, tmp3, 16);
920 } else
921 emith_clear_msb(tmp2, tmp3, 16);
922 emith_mul(tmp, tmp, tmp2);
923 rcache_free_tmp(tmp2);
924// FIXME: causes timing issues in Doom?
925// cycles++;
926 goto end_op;
679af8a3 927 }
928 goto default_;
929
3863edbd 930 /////////////////////////////////////////////
931 case 0x03:
932 switch (op & 0x0f)
933 {
934 case 0x00: // CMP/EQ Rm,Rn 0011nnnnmmmm0000
935 case 0x02: // CMP/HS Rm,Rn 0011nnnnmmmm0010
936 case 0x03: // CMP/GE Rm,Rn 0011nnnnmmmm0011
937 case 0x06: // CMP/HI Rm,Rn 0011nnnnmmmm0110
938 case 0x07: // CMP/GT Rm,Rn 0011nnnnmmmm0111
939 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
940 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
941 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
942 emith_bic_r_imm(tmp, T);
943 emith_cmp_r_r(tmp2, tmp3);
944 switch (op & 0x07)
945 {
946 case 0x00: // CMP/EQ
947 EMITH_SJMP_START(DCOND_NE);
948 emith_or_r_imm_c(DCOND_EQ, tmp, T);
949 EMITH_SJMP_END(DCOND_NE);
950 break;
951 case 0x02: // CMP/HS
952 EMITH_SJMP_START(DCOND_LO);
953 emith_or_r_imm_c(DCOND_HS, tmp, T);
954 EMITH_SJMP_END(DCOND_LO);
955 break;
956 case 0x03: // CMP/GE
957 EMITH_SJMP_START(DCOND_LT);
958 emith_or_r_imm_c(DCOND_GE, tmp, T);
959 EMITH_SJMP_END(DCOND_LT);
960 break;
961 case 0x06: // CMP/HI
962 EMITH_SJMP_START(DCOND_LS);
963 emith_or_r_imm_c(DCOND_HI, tmp, T);
964 EMITH_SJMP_END(DCOND_LS);
965 break;
966 case 0x07: // CMP/GT
967 EMITH_SJMP_START(DCOND_LE);
968 emith_or_r_imm_c(DCOND_GT, tmp, T);
969 EMITH_SJMP_END(DCOND_LE);
970 break;
971 }
972 goto end_op;
973 case 0x04: // DIV1 Rm,Rn 0011nnnnmmmm0100
974 // TODO
975 break;
976 case 0x05: // DMULU.L Rm,Rn 0011nnnnmmmm0101
977 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
978 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
979 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
980 tmp4 = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
981 emith_mul_u64(tmp3, tmp4, tmp, tmp2);
982 goto end_op;
983 case 0x08: // SUB Rm,Rn 0011nnnnmmmm1000
984 case 0x0c: // ADD Rm,Rn 0011nnnnmmmm1100
985 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
986 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
987 if (op & 4) {
988 emith_add_r_r(tmp, tmp2);
989 } else
990 emith_sub_r_r(tmp, tmp2);
991 goto end_op;
992 case 0x0a: // SUBC Rm,Rn 0011nnnnmmmm1010
993 case 0x0e: // ADDC Rm,Rn 0011nnnnmmmm1110
994 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
995 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
996 tmp3 = rcache_get_reg(SHR_SR, RC_GR_RMW);
997 if (op & 4) { // adc
998 emith_set_carry(tmp3);
999 emith_adcf_r_r(tmp, tmp2);
ed8cf79b 1000 emith_carry_to_t(tmp3, 0);
3863edbd 1001 } else {
1002 emith_set_carry_sub(tmp3);
1003 emith_sbcf_r_r(tmp, tmp2);
ed8cf79b 1004 emith_carry_to_t(tmp3, 1);
3863edbd 1005 }
3863edbd 1006 goto end_op;
1007 case 0x0b: // SUBV Rm,Rn 0011nnnnmmmm1011
1008 case 0x0f: // ADDV Rm,Rn 0011nnnnmmmm1111
1009 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1010 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1011 tmp3 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1012 emith_bic_r_imm(tmp3, T);
1013 if (op & 4) {
1014 emith_addf_r_r(tmp, tmp2);
1015 } else
1016 emith_subf_r_r(tmp, tmp2);
1017 EMITH_SJMP_START(DCOND_VC);
1018 emith_or_r_imm_c(DCOND_VS, tmp3, T);
1019 EMITH_SJMP_END(DCOND_VC);
1020 goto end_op;
1021 case 0x0d: // DMULS.L Rm,Rn 0011nnnnmmmm1101
1022 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
1023 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
1024 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
1025 tmp4 = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
1026 emith_mul_s64(tmp3, tmp4, tmp, tmp2);
1027 goto end_op;
1028 }
1029 goto default_;
1030
1031 /////////////////////////////////////////////
679af8a3 1032 case 0x04:
3863edbd 1033 switch (op & 0x0f)
1034 {
c18edb34 1035 case 0x00:
3863edbd 1036 switch (GET_Fx())
1037 {
1038 case 0: // SHLL Rn 0100nnnn00000000
1039 case 2: // SHAL Rn 0100nnnn00100000
1040 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1041 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
3863edbd 1042 emith_lslf(tmp, tmp, 1);
ed8cf79b 1043 emith_carry_to_t(tmp2, 0);
3863edbd 1044 goto end_op;
1045 case 1: // DT Rn 0100nnnn00010000
1046 if (p32x_sh2_read16(pc, sh2) == 0x8bfd) { // BF #-2
1047 emith_sh2_dtbf_loop();
1048 goto end_op;
1049 }
1050 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1051 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1052 emith_bic_r_imm(tmp2, T);
1053 emith_subf_r_imm(tmp, 1);
1054 EMITH_SJMP_START(DCOND_NE);
1055 emith_or_r_imm_c(DCOND_EQ, tmp2, T);
1056 EMITH_SJMP_END(DCOND_NE);
80599a42 1057 goto end_op;
1058 }
3863edbd 1059 goto default_;
ed8cf79b 1060 case 0x01:
1061 switch (GET_Fx())
1062 {
1063 case 0: // SHLR Rn 0100nnnn00000001
1064 case 2: // SHAR Rn 0100nnnn00100001
1065 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1066 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1067 if (op & 0x20) {
1068 emith_asrf(tmp, tmp, 1);
1069 } else
1070 emith_lsrf(tmp, tmp, 1);
1071 emith_carry_to_t(tmp2, 0);
1072 goto end_op;
1073 case 1: // CMP/PZ Rn 0100nnnn00010001
1074 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1075 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1076 emith_bic_r_imm(tmp2, T);
1077 emith_cmp_r_imm(tmp, 0);
1078 EMITH_SJMP_START(DCOND_LT);
1079 emith_or_r_imm_c(DCOND_GE, tmp2, T);
1080 EMITH_SJMP_END(DCOND_LT);
1081 goto end_op;
1082 }
1083 goto default_;
1084 case 0x02:
1085 case 0x03:
1086 switch (op & 0x3f)
1087 {
1088 case 0x02: // STS.L MACH,@–Rn 0100nnnn00000010
1089 tmp = SHR_MACH;
1090 break;
1091 case 0x12: // STS.L MACL,@–Rn 0100nnnn00010010
1092 tmp = SHR_MACL;
1093 break;
1094 case 0x22: // STS.L PR,@–Rn 0100nnnn00100010
1095 tmp = SHR_PR;
1096 break;
1097 case 0x03: // STC.L SR,@–Rn 0100nnnn00000011
1098 tmp = SHR_SR;
1099 break;
1100 case 0x13: // STC.L GBR,@–Rn 0100nnnn00010011
1101 tmp = SHR_GBR;
1102 break;
1103 case 0x23: // STC.L VBR,@–Rn 0100nnnn00100011
1104 tmp = SHR_VBR;
1105 break;
1106 default:
e898de13 1107 goto default_;
ed8cf79b 1108 }
1109 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1110 emith_sub_r_imm(tmp2, 4);
1111 rcache_clean();
1112 rcache_get_reg_arg(0, GET_Rn());
1113 tmp3 = rcache_get_reg_arg(1, tmp);
1114 if (tmp == SHR_SR)
1115 emith_clear_msb(tmp3, tmp3, 20); // reserved bits defined by ISA as 0
1116 emit_memhandler_write(2);
1117 goto end_op;
1118 case 0x04:
1119 case 0x05:
1120 switch (op & 0x3f)
1121 {
1122 case 0x04: // ROTL Rn 0100nnnn00000100
1123 case 0x05: // ROTR Rn 0100nnnn00000101
1124 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1125 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1126 if (op & 1) {
1127 emith_rorf(tmp, tmp, 1);
1128 } else
1129 emith_rolf(tmp, tmp, 1);
1130 emith_carry_to_t(tmp2, 0);
1131 goto end_op;
1132 case 0x24: // ROTCL Rn 0100nnnn00100100
1133 case 0x25: // ROTCR Rn 0100nnnn00100101
1134 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1135 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1136 emith_set_carry(tmp2);
1137 if (op & 1) {
1138 emith_rorcf(tmp);
1139 } else
1140 emith_rolcf(tmp);
1141 emith_carry_to_t(tmp2, 0);
1142 goto end_op;
1143 case 0x15: // CMP/PL Rn 0100nnnn00010101
1144 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1145 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1146 emith_bic_r_imm(tmp2, T);
1147 emith_cmp_r_imm(tmp, 0);
1148 EMITH_SJMP_START(DCOND_LE);
1149 emith_or_r_imm_c(DCOND_GT, tmp2, T);
1150 EMITH_SJMP_END(DCOND_LE);
1151 goto end_op;
1152 }
e898de13 1153 goto default_;
ed8cf79b 1154 case 0x06:
1155 case 0x07:
1156 switch (op & 0x3f)
1157 {
1158 case 0x06: // LDS.L @Rm+,MACH 0100mmmm00000110
1159 tmp = SHR_MACH;
1160 break;
1161 case 0x16: // LDS.L @Rm+,MACL 0100mmmm00010110
1162 tmp = SHR_MACL;
1163 break;
1164 case 0x26: // LDS.L @Rm+,PR 0100mmmm00100110
1165 tmp = SHR_PR;
1166 break;
1167 case 0x07: // LDC.L @Rm+,SR 0100mmmm00000111
1168 tmp = SHR_SR;
1169 break;
1170 case 0x17: // LDC.L @Rm+,GBR 0100mmmm00010111
1171 tmp = SHR_GBR;
1172 break;
1173 case 0x27: // LDC.L @Rm+,VBR 0100mmmm00100111
1174 tmp = SHR_VBR;
1175 break;
1176 default:
1177 goto default_;
1178 }
1179 rcache_clean();
1180 rcache_get_reg_arg(0, GET_Rn());
1181 tmp2 = emit_memhandler_read(2);
1182 if (tmp == SHR_SR) {
1183 emith_write_sr(tmp2);
1184 test_irq = 1;
1185 } else {
1186 tmp = rcache_get_reg(tmp, RC_GR_WRITE);
1187 emith_move_r_r(tmp, tmp2);
1188 }
1189 rcache_free_tmp(tmp2);
1190 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1191 emith_add_r_imm(tmp, 4);
1192 goto end_op;
e898de13 1193 case 0x0b:
1194 if ((op & 0xd0) != 0)
1195 goto default_;
1196 // JMP @Rm 0100mmmm00101011
1197 // JSR @Rm 0100mmmm00001011
679af8a3 1198 DELAYED_OP;
e898de13 1199 if (!(op & 0x20))
1200 emit_move_r_imm32(SHR_PR, pc + 2);
1201 emit_move_r_r(SHR_PPC, (op >> 8) & 0x0f);
679af8a3 1202 cycles++;
e898de13 1203 goto end_op;
1204 case 0x0e:
1205 if ((op & 0xf0) != 0)
1206 goto default_;
1207 // LDC Rm,SR 0100mmmm00001110
1208 test_irq = 1;
1209 goto default_;
679af8a3 1210 }
1211 goto default_;
1212
3863edbd 1213 /////////////////////////////////////////////
e898de13 1214 case 0x08:
679af8a3 1215 switch (op & 0x0f00) {
1216 // BT/S label 10001101dddddddd
1217 case 0x0d00:
1218 // BF/S label 10001111dddddddd
1219 case 0x0f00:
1220 DELAYED_OP;
1221 cycles--;
679af8a3 1222 // fallthrough
1223 // BT label 10001001dddddddd
1224 case 0x0900:
1225 // BF label 10001011dddddddd
80599a42 1226 case 0x0b00: {
1227 // jmp_cond ~ cond when guest doesn't jump
1228 int jmp_cond = (op & 0x0200) ? DCOND_NE : DCOND_EQ;
1229 int insn_cond = (op & 0x0200) ? DCOND_EQ : DCOND_NE;
1230 signed int offs = ((signed int)(op << 24) >> 23);
1231 tmp = rcache_get_reg(delayed_op ? SHR_PPC : SHR_PC, RC_GR_WRITE);
1232 emith_move_r_imm(tmp, pc + (delayed_op ? 2 : 0));
1233 emith_sh2_test_t();
1234 EMITH_SJMP_START(jmp_cond);
1235 if (!delayed_op)
1236 offs += 2;
1237 if (offs < 0) {
1238 emith_sub_r_imm_c(insn_cond, tmp, -offs);
1239 } else
1240 emith_add_r_imm_c(insn_cond, tmp, offs);
1241 EMITH_SJMP_END(jmp_cond);
e898de13 1242 cycles += 2;
1243 if (!delayed_op)
1244 goto end_block;
1245 goto end_op;
80599a42 1246 }}
679af8a3 1247 goto default_;
679af8a3 1248
3863edbd 1249 /////////////////////////////////////////////
679af8a3 1250 case 0x0a:
1251 // BRA label 1010dddddddddddd
1252 DELAYED_OP;
1253 do_bra:
1254 tmp = ((signed int)(op << 20) >> 19);
e898de13 1255 emit_move_r_imm32(SHR_PPC, pc + tmp + 2);
679af8a3 1256 cycles++;
e898de13 1257 break;
679af8a3 1258
3863edbd 1259 /////////////////////////////////////////////
679af8a3 1260 case 0x0b:
1261 // BSR label 1011dddddddddddd
1262 DELAYED_OP;
e898de13 1263 emit_move_r_imm32(SHR_PR, pc + 2);
679af8a3 1264 goto do_bra;
1265
1266 default:
1267 default_:
1268 emit_move_r_imm32(SHR_PC, pc - 2);
c18edb34 1269 rcache_flush();
f4bb5d6b 1270 emith_pass_arg_r(0, CONTEXT_REG);
1271 emith_pass_arg_imm(1, op);
679af8a3 1272 emith_call(sh2_do_op);
1273 break;
1274 }
1275
e898de13 1276end_op:
6add7875 1277 if (delayed_op == 1)
e898de13 1278 emit_move_r_r(SHR_PC, SHR_PPC);
6add7875 1279
e898de13 1280 if (test_irq && delayed_op != 2) {
c18edb34 1281 rcache_flush();
f4bb5d6b 1282 emith_pass_arg_r(0, CONTEXT_REG);
e898de13 1283 emith_call(sh2_test_irq);
1284 break;
1285 }
6add7875 1286 if (delayed_op == 1)
1287 break;
e898de13 1288
f4bb5d6b 1289 do_host_disasm(tcache_id);
679af8a3 1290 }
1291
1292end_block:
f4bb5d6b 1293 this_block->end_addr = pc;
1294
1295 // mark memory blocks as containing compiled code
1296 if ((sh2->pc & 0xe0000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
1297 // data array, BIOS
1298 u16 *drcblk = Pico32xMem->drcblk_da[sh2->is_slave];
1299 tmp = (this_block->addr & 0xfff) >> SH2_DRCBLK_DA_SHIFT;
1300 tmp2 = (this_block->end_addr & 0xfff) >> SH2_DRCBLK_DA_SHIFT;
1301 Pico32xMem->drcblk_da[sh2->is_slave][tmp] = (blkid << 1) | 1;
1302 for (++tmp; tmp < tmp2; tmp++) {
1303 if (drcblk[tmp])
1304 break; // dont overwrite overlay block
1305 drcblk[tmp] = blkid << 1;
1306 }
1307 }
1308 else if ((this_block->addr & 0xc7fc0000) == 0x06000000) { // DRAM
1309 tmp = (this_block->addr & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT;
1310 tmp2 = (this_block->end_addr & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT;
1311 Pico32xMem->drcblk_ram[tmp] = (blkid << 1) | 1;
1312 for (++tmp; tmp < tmp2; tmp++) {
1313 if (Pico32xMem->drcblk_ram[tmp])
1314 break;
1315 Pico32xMem->drcblk_ram[tmp] = blkid << 1;
1316 }
679af8a3 1317 }
1318
c18edb34 1319 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
1320 emith_sub_r_imm(tmp, cycles << 12);
1321 rcache_flush();
679af8a3 1322 emith_jump(sh2_drc_exit);
f4bb5d6b 1323 tcache_ptrs[tcache_id] = tcache_ptr;
1324
553c3eaa 1325#ifdef ARM
1326 cache_flush_d_inval_i(block_entry, tcache_ptr);
1327#endif
1328
f4bb5d6b 1329 do_host_disasm(tcache_id);
1330 dbg(1, " block #%d,%d tcache %d/%d, insns %d -> %d %.3f",
1331 tcache_id, block_counts[tcache_id],
1332 tcache_ptr - tcache_bases[tcache_id], tcache_sizes[tcache_id],
1333 insns_compiled, host_insn_count, (double)host_insn_count / insns_compiled);
1334 if ((sh2->pc & 0xc6000000) == 0x02000000) // ROM
1335 dbg(1, " hash collisions %d/%d", hash_collisions, block_counts[tcache_id]);
553c3eaa 1336#if (DRC_DEBUG & 2)
1337 fflush(stdout);
1338#endif
1339
679af8a3 1340 return block_entry;
f4bb5d6b 1341/*
679af8a3 1342unimplemented:
1343 // last op
f4bb5d6b 1344 do_host_disasm(tcache_id);
679af8a3 1345 exit(1);
f4bb5d6b 1346*/
679af8a3 1347}
1348
1349void __attribute__((noinline)) sh2_drc_dispatcher(SH2 *sh2)
1350{
1351 while (((signed int)sh2->sr >> 12) > 0)
1352 {
679af8a3 1353 void *block = NULL;
f4bb5d6b 1354 block_desc *bd = NULL;
6add7875 1355
1356 // FIXME: must avoid doing it so often..
1357 sh2_test_irq(sh2);
1358
f4bb5d6b 1359 // we have full block id tables for data_array and RAM
1360 // BIOS goes to data_array table too
1361 if ((sh2->pc & 0xff000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
1362 int blkid = Pico32xMem->drcblk_da[sh2->is_slave][(sh2->pc & 0xfff) >> SH2_DRCBLK_DA_SHIFT];
1363 if (blkid & 1) {
1364 bd = &block_tables[1 + sh2->is_slave][blkid >> 1];
1365 block = bd->tcache_ptr;
1366 }
1367 }
1368 // RAM
1369 else if ((sh2->pc & 0xc6000000) == 0x06000000) {
1370 int blkid = Pico32xMem->drcblk_ram[(sh2->pc & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT];
1371 if (blkid & 1) {
1372 bd = &block_tables[0][blkid >> 1];
679af8a3 1373 block = bd->tcache_ptr;
f4bb5d6b 1374 }
1375 }
1376 // ROM
1377 else if ((sh2->pc & 0xc6000000) == 0x02000000) {
1378 bd = HASH_FUNC(hash_table, sh2->pc);
1379
1380 if (bd != NULL) {
1381 if (bd->addr == sh2->pc)
1382 block = bd->tcache_ptr;
1383 else
1384 block = dr_find_block(bd, sh2->pc);
1385 }
679af8a3 1386 }
1387
1388 if (block == NULL)
1389 block = sh2_translate(sh2, bd);
1390
f4bb5d6b 1391 dbg(4, "= %csh2 enter %08x %p, c=%d", sh2->is_slave ? 's' : 'm',
1392 sh2->pc, block, (signed int)sh2->sr >> 12);
1393#if (DRC_DEBUG & 1)
1394 if (bd != NULL)
1395 bd->refcount++;
679af8a3 1396#endif
1397 sh2_drc_entry(sh2, block);
1398 }
1399}
1400
f4bb5d6b 1401static void sh2_smc_rm_block(u16 *drcblk, u16 *p, block_desc *btab, u32 a)
1402{
1403 u16 id = *p >> 1;
1404 block_desc *bd = btab + id;
1405
1406 dbg(1, " killing block %08x", bd->addr);
1407 bd->addr = bd->end_addr = 0;
1408
1409 while (p > drcblk && (p[-1] >> 1) == id)
1410 p--;
1411
1412 // check for possible overlay block
1413 if (p > 0 && p[-1] != 0) {
1414 bd = btab + (p[-1] >> 1);
1415 if (bd->addr <= a && a < bd->end_addr)
1416 sh2_smc_rm_block(drcblk, p - 1, btab, a);
1417 }
1418
1419 do {
1420 *p++ = 0;
1421 }
1422 while ((*p >> 1) == id);
1423}
1424
1425void sh2_drc_wcheck_ram(unsigned int a, int val, int cpuid)
1426{
1427 u16 *drcblk = Pico32xMem->drcblk_ram;
1428 u16 *p = drcblk + ((a & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT);
1429
1430 dbg(1, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a);
1431 sh2_smc_rm_block(drcblk, p, block_tables[0], a);
1432}
1433
1434void sh2_drc_wcheck_da(unsigned int a, int val, int cpuid)
1435{
1436 u16 *drcblk = Pico32xMem->drcblk_da[cpuid];
1437 u16 *p = drcblk + ((a & 0xfff) >> SH2_DRCBLK_DA_SHIFT);
1438
1439 dbg(1, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a);
1440 sh2_smc_rm_block(drcblk, p, block_tables[1 + cpuid], a);
1441}
1442
679af8a3 1443void sh2_execute(SH2 *sh2, int cycles)
1444{
1445 sh2->cycles_aim += cycles;
1446 cycles = sh2->cycles_aim - sh2->cycles_done;
1447
1448 // cycles are kept in SHR_SR unused bits (upper 20)
1449 sh2->sr &= 0x3f3;
1450 sh2->sr |= cycles << 12;
1451 sh2_drc_dispatcher(sh2);
1452
1453 sh2->cycles_done += cycles - ((signed int)sh2->sr >> 12);
1454}
1455
553c3eaa 1456static void REGPARM(1) sh2_test_irq(SH2 *sh2)
679af8a3 1457{
6add7875 1458 if (sh2->pending_level > ((sh2->sr >> 4) & 0x0f))
1459 {
1460 if (sh2->pending_irl > sh2->pending_int_irq)
1461 sh2_do_irq(sh2, sh2->pending_irl, 64 + sh2->pending_irl/2);
1462 else {
1463 sh2_do_irq(sh2, sh2->pending_int_irq, sh2->pending_int_vector);
1464 sh2->pending_int_irq = 0; // auto-clear
1465 sh2->pending_level = sh2->pending_irl;
1466 }
1467 }
679af8a3 1468}
1469
f4bb5d6b 1470#if (DRC_DEBUG & 1)
1471static void block_stats(void)
1472{
1473 int c, b, i, total = 0;
1474
1475 for (b = 0; b < ARRAY_SIZE(block_tables); b++)
1476 for (i = 0; i < block_counts[b]; i++)
1477 if (block_tables[b][i].addr != 0)
1478 total += block_tables[b][i].refcount;
1479
1480 for (c = 0; c < 10; c++) {
1481 block_desc *blk, *maxb = NULL;
1482 int max = 0;
1483 for (b = 0; b < ARRAY_SIZE(block_tables); b++) {
1484 for (i = 0; i < block_counts[b]; i++) {
1485 blk = &block_tables[b][i];
1486 if (blk->addr != 0 && blk->refcount > max) {
1487 max = blk->refcount;
1488 maxb = blk;
1489 }
1490 }
1491 }
1492 if (maxb == NULL)
1493 break;
1494 printf("%08x %9d %2.3f%%\n", maxb->addr, maxb->refcount,
1495 (double)maxb->refcount / total * 100.0);
1496 maxb->refcount = 0;
1497 }
553c3eaa 1498
1499 for (b = 0; b < ARRAY_SIZE(block_tables); b++)
1500 for (i = 0; i < block_counts[b]; i++)
1501 block_tables[b][i].refcount = 0;
f4bb5d6b 1502}
553c3eaa 1503#else
1504#define block_stats()
f4bb5d6b 1505#endif
1506
553c3eaa 1507void sh2_drc_flush_all(void)
1508{
1509 block_stats();
1510 flush_tcache(0);
1511 flush_tcache(1);
1512 flush_tcache(2);
1513}
1514
679af8a3 1515int sh2_drc_init(SH2 *sh2)
1516{
f4bb5d6b 1517 if (block_tables[0] == NULL) {
1518 int i, cnt;
7f5a3fc1 1519
1520 drc_cmn_init();
1521
f4bb5d6b 1522 cnt = block_max_counts[0] + block_max_counts[1] + block_max_counts[2];
1523 block_tables[0] = calloc(cnt, sizeof(*block_tables[0]));
1524 if (block_tables[0] == NULL)
e898de13 1525 return -1;
1526
f4bb5d6b 1527 memset(block_counts, 0, sizeof(block_counts));
1528 tcache_bases[0] = tcache_ptrs[0] = tcache;
1529
1530 for (i = 1; i < ARRAY_SIZE(block_tables); i++) {
1531 block_tables[i] = block_tables[i - 1] + block_max_counts[i - 1];
1532 tcache_bases[i] = tcache_ptrs[i] = tcache_bases[i - 1] + tcache_sizes[i - 1];
1533 }
1534
553c3eaa 1535 // tmp
1536 PicoOpt |= POPT_DIS_VDP_FIFO;
1537
f4bb5d6b 1538#if (DRC_DEBUG & 2)
1539 for (i = 0; i < ARRAY_SIZE(block_tables); i++)
1540 tcache_dsm_ptrs[i] = tcache_bases[i];
1541#endif
e898de13 1542#if (DRC_DEBUG & 1)
1543 hash_collisions = 0;
1544#endif
679af8a3 1545 }
1546
f4bb5d6b 1547 if (hash_table == NULL) {
1548 hash_table = calloc(sizeof(hash_table[0]), MAX_HASH_ENTRIES);
1549 if (hash_table == NULL)
1550 return -1;
1551 }
41397701 1552
679af8a3 1553 return 0;
41397701 1554}
1555
e898de13 1556void sh2_drc_finish(SH2 *sh2)
1557{
f4bb5d6b 1558 if (block_tables[0] != NULL) {
f4bb5d6b 1559 block_stats();
f4bb5d6b 1560 free(block_tables[0]);
1561 memset(block_tables, 0, sizeof(block_tables));
7f5a3fc1 1562
1563 drc_cmn_cleanup();
e898de13 1564 }
1565
f4bb5d6b 1566 if (hash_table != NULL) {
1567 free(hash_table);
1568 hash_table = NULL;
1569 }
e898de13 1570}