32x: don't log purge area access
[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 {
52d759c3 129 SHR_R0 = 0, SHR_SP = 15,
679af8a3 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{
52d759c3 434 // TODO: propagate this constant
c18edb34 435 int hr = rcache_get_reg(dst, RC_GR_WRITE);
436 emith_move_r_imm(hr, imm);
437}
438
439static void emit_move_r_r(sh2_reg_e dst, sh2_reg_e src)
440{
441 int hr_d = rcache_get_reg(dst, RC_GR_WRITE);
442 int hr_s = rcache_get_reg(src, RC_GR_READ);
443
444 emith_move_r_r(hr_d, hr_s);
679af8a3 445}
446
52d759c3 447// T must be clear, and comparison done just before this
448static void emit_or_t_if_eq(int srr)
449{
450 EMITH_SJMP_START(DCOND_NE);
451 emith_or_r_imm_c(DCOND_EQ, srr, T);
452 EMITH_SJMP_END(DCOND_NE);
453}
454
80599a42 455// arguments must be ready
456// reg cache must be clean before call
457static int emit_memhandler_read(int size)
679af8a3 458{
80599a42 459 int ctxr;
460 host_arg2reg(ctxr, 1);
461 emith_move_r_r(ctxr, CONTEXT_REG);
462 switch (size) {
463 case 0: // 8
464 emith_call(p32x_sh2_read8);
465 break;
466 case 1: // 16
467 emith_call(p32x_sh2_read16);
468 break;
469 case 2: // 32
470 emith_call(p32x_sh2_read32);
679af8a3 471 break;
472 }
80599a42 473 rcache_invalidate();
474 // assuming arg0 and retval reg matches
475 return rcache_get_tmp_arg(0);
476}
679af8a3 477
80599a42 478static void emit_memhandler_write(int size)
479{
480 int ctxr;
481 host_arg2reg(ctxr, 2);
482 emith_move_r_r(ctxr, CONTEXT_REG);
483 switch (size) {
484 case 0: // 8
485 emith_call(p32x_sh2_write8);
486 break;
487 case 1: // 16
488 emith_call(p32x_sh2_write16);
489 break;
490 case 2: // 32
491 emith_call(p32x_sh2_write32);
492 break;
493 }
494 rcache_invalidate();
679af8a3 495}
80599a42 496
52d759c3 497// @(Rx,Ry)
498static int emit_indirect_indexed_read(int rx, int ry, int size)
499{
500 int a0, t;
501 rcache_clean();
502 a0 = rcache_get_reg_arg(0, rx);
503 t = rcache_get_reg(ry, RC_GR_READ);
504 emith_add_r_r(a0, t);
505 return emit_memhandler_read(size);
506}
507
508// Rwr -> @(Rx,Ry)
509static void emit_indirect_indexed_write(int rx, int ry, int wr, int size)
510{
511 int a0, t;
512 rcache_clean();
513 rcache_get_reg_arg(1, wr);
514 a0 = rcache_get_reg_arg(0, rx);
515 t = rcache_get_reg(ry, RC_GR_READ);
516 emith_add_r_r(a0, t);
517 emit_memhandler_write(size);
518}
519
679af8a3 520
e898de13 521#define DELAYED_OP \
522 delayed_op = 2
523
524#define CHECK_UNHANDLED_BITS(mask) { \
525 if ((op & (mask)) != 0) \
526 goto default_; \
527}
528
80599a42 529#define GET_Fx() \
530 ((op >> 4) & 0x0f)
531
532#define GET_Rm GET_Fx
533
534#define GET_Rn() \
535 ((op >> 8) & 0x0f)
536
ed8cf79b 537#define CHECK_FX_LT(n) \
52d759c3 538 if (GET_Fx() >= n) \
80599a42 539 goto default_
540
679af8a3 541static void *sh2_translate(SH2 *sh2, block_desc *other_block)
542{
f4bb5d6b 543 void *block_entry;
679af8a3 544 block_desc *this_block;
41397701 545 unsigned int pc = sh2->pc;
e898de13 546 int op, delayed_op = 0, test_irq = 0;
f4bb5d6b 547 int tcache_id = 0, blkid = 0;
679af8a3 548 int cycles = 0;
3863edbd 549 u32 tmp, tmp2, tmp3, tmp4;
679af8a3 550
f4bb5d6b 551 // validate PC
552 tmp = sh2->pc >> 29;
553 if ((tmp != 0 && tmp != 1 && tmp != 6) || sh2->pc == 0) {
554 printf("invalid PC, aborting: %08x\n", sh2->pc);
555 // FIXME: be less destructive
556 exit(1);
557 }
558
559 if ((sh2->pc & 0xe0000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
560 // data_array, BIOS have separate tcache (shared)
561 tcache_id = 1 + sh2->is_slave;
562 }
563
564 tcache_ptr = tcache_ptrs[tcache_id];
565 this_block = dr_add_block(pc, tcache_id, &blkid);
566
567 tmp = tcache_ptr - tcache_bases[tcache_id];
568 if (tmp > tcache_sizes[tcache_id] - MAX_BLOCK_SIZE || this_block == NULL) {
569 flush_tcache(tcache_id);
570 tcache_ptr = tcache_ptrs[tcache_id];
571 other_block = NULL; // also gone too due to flush
572 this_block = dr_add_block(pc, tcache_id, &blkid);
573 }
e898de13 574
f4bb5d6b 575 this_block->next = other_block;
576 if ((sh2->pc & 0xc6000000) == 0x02000000) // ROM
577 HASH_FUNC(hash_table, pc) = this_block;
679af8a3 578
f4bb5d6b 579 block_entry = tcache_ptr;
e898de13 580#if (DRC_DEBUG & 1)
f4bb5d6b 581 printf("== %csh2 block #%d,%d %08x -> %p\n", sh2->is_slave ? 's' : 'm',
582 tcache_id, block_counts[tcache_id], pc, block_entry);
e898de13 583 if (other_block != NULL) {
584 printf(" hash collision with %08x\n", other_block->addr);
585 hash_collisions++;
586 }
679af8a3 587#endif
588
e898de13 589 while (cycles < BLOCK_CYCLE_LIMIT || delayed_op)
679af8a3 590 {
e898de13 591 if (delayed_op > 0)
592 delayed_op--;
593
2b2b46b0 594 op = p32x_sh2_read16(pc, sh2);
e898de13 595
596#if (DRC_DEBUG & 3)
597 insns_compiled++;
598#if (DRC_DEBUG & 2)
599 DasmSH2(sh2dasm_buff, pc, op);
600 printf("%08x %04x %s\n", pc, op, sh2dasm_buff);
601#endif
679af8a3 602#endif
679af8a3 603
604 pc += 2;
605 cycles++;
606
607 switch ((op >> 12) & 0x0f)
608 {
3863edbd 609 /////////////////////////////////////////////
679af8a3 610 case 0x00:
80599a42 611 switch (op & 0x0f)
612 {
613 case 0x02:
614 tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
615 switch (GET_Fx())
616 {
617 case 0: // STC SR,Rn 0000nnnn00000010
618 tmp2 = SHR_SR;
619 break;
620 case 1: // STC GBR,Rn 0000nnnn00010010
621 tmp2 = SHR_GBR;
622 break;
623 case 2: // STC VBR,Rn 0000nnnn00100010
624 tmp2 = SHR_VBR;
625 break;
626 default:
627 goto default_;
628 }
ed8cf79b 629 tmp3 = rcache_get_reg(tmp2, RC_GR_READ);
630 emith_move_r_r(tmp, tmp3);
631 if (tmp2 == SHR_SR)
632 emith_clear_msb(tmp, tmp, 20); // reserved bits defined by ISA as 0
80599a42 633 goto end_op;
e898de13 634 case 0x03:
635 CHECK_UNHANDLED_BITS(0xd0);
636 // BRAF Rm 0000mmmm00100011
637 // BSRF Rm 0000mmmm00000011
679af8a3 638 DELAYED_OP;
e898de13 639 if (!(op & 0x20))
640 emit_move_r_imm32(SHR_PR, pc + 2);
c18edb34 641 tmp = rcache_get_reg(SHR_PPC, RC_GR_WRITE);
80599a42 642 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
c18edb34 643 emith_move_r_r(tmp, tmp2);
644 emith_add_r_imm(tmp, pc + 2);
679af8a3 645 cycles++;
e898de13 646 goto end_op;
80599a42 647 case 0x04: // MOV.B Rm,@(R0,Rn) 0000nnnnmmmm0100
648 case 0x05: // MOV.W Rm,@(R0,Rn) 0000nnnnmmmm0101
649 case 0x06: // MOV.L Rm,@(R0,Rn) 0000nnnnmmmm0110
52d759c3 650 emit_indirect_indexed_write(SHR_R0, GET_Rn(), GET_Rm(), op & 3);
80599a42 651 goto end_op;
652 case 0x07:
653 // MUL.L Rm,Rn 0000nnnnmmmm0111
654 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
655 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
656 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
657 emith_mul(tmp3, tmp2, tmp);
658 cycles++;
659 goto end_op;
660 case 0x08:
661 CHECK_UNHANDLED_BITS(0xf00);
662 switch (GET_Fx())
663 {
664 case 0: // CLRT 0000000000001000
665 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
666 emith_bic_r_imm(tmp, T);
667 break;
668 case 1: // SETT 0000000000011000
669 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
670 emith_or_r_imm(tmp, T);
671 break;
672 case 2: // CLRMAC 0000000000101000
673 tmp = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
674 emith_move_r_imm(tmp, 0);
675 tmp = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
676 emith_move_r_imm(tmp, 0);
677 break;
678 default:
679 goto default_;
680 }
681 goto end_op;
e898de13 682 case 0x09:
80599a42 683 switch (GET_Fx())
684 {
685 case 0: // NOP 0000000000001001
686 CHECK_UNHANDLED_BITS(0xf00);
687 break;
688 case 1: // DIV0U 0000000000011001
689 CHECK_UNHANDLED_BITS(0xf00);
690 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
691 emith_bic_r_imm(tmp, M|Q|T);
692 break;
693 case 2: // MOVT Rn 0000nnnn00101001
694 tmp = rcache_get_reg(SHR_SR, RC_GR_READ);
695 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
696 emith_clear_msb(tmp2, tmp, 31);
697 break;
698 default:
699 goto default_;
700 }
701 goto end_op;
702 case 0x0a:
703 tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
704 switch (GET_Fx())
705 {
706 case 0: // STS MACH,Rn 0000nnnn00001010
ed8cf79b 707 tmp2 = SHR_MACH;
80599a42 708 break;
709 case 1: // STS MACL,Rn 0000nnnn00011010
ed8cf79b 710 tmp2 = SHR_MACL;
80599a42 711 break;
712 case 2: // STS PR,Rn 0000nnnn00101010
ed8cf79b 713 tmp2 = SHR_PR;
80599a42 714 break;
715 default:
716 goto default_;
717 }
ed8cf79b 718 tmp2 = rcache_get_reg(tmp2, RC_GR_READ);
80599a42 719 emith_move_r_r(tmp, tmp2);
e898de13 720 goto end_op;
721 case 0x0b:
80599a42 722 CHECK_UNHANDLED_BITS(0xf00);
723 switch (GET_Fx())
724 {
725 case 0: // RTS 0000000000001011
726 DELAYED_OP;
e898de13 727 emit_move_r_r(SHR_PPC, SHR_PR);
728 cycles++;
80599a42 729 break;
730 case 1: // SLEEP 0000000000011011
731 emit_move_r_imm32(SHR_PC, pc - 2);
732 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
733 emith_clear_msb(tmp, tmp, 20); // clear cycles
734 test_irq = 1;
735 cycles = 1;
736 break;
737 case 2: // RTE 0000000000101011
52d759c3 738 DELAYED_OP;
739 rcache_clean();
740 // pop PC
741 rcache_get_reg_arg(0, SHR_SP);
742 tmp = emit_memhandler_read(2);
743 tmp2 = rcache_get_reg(SHR_PPC, RC_GR_WRITE);
744 emith_move_r_r(tmp2, tmp);
745 rcache_free_tmp(tmp);
746 rcache_clean();
747 // pop SR
748 tmp = rcache_get_reg_arg(0, SHR_SP);
749 emith_add_r_imm(tmp, 4);
750 tmp = emit_memhandler_read(2);
751 emith_write_sr(tmp);
752 rcache_free_tmp(tmp);
753 tmp = rcache_get_reg(SHR_SP, RC_GR_RMW);
754 emith_add_r_imm(tmp, 4*2);
e898de13 755 test_irq = 1;
756 cycles += 3;
80599a42 757 break;
758 default:
759 goto default_;
e898de13 760 }
761 goto end_op;
80599a42 762 case 0x0c: // MOV.B @(R0,Rm),Rn 0000nnnnmmmm1100
763 case 0x0d: // MOV.W @(R0,Rm),Rn 0000nnnnmmmm1101
764 case 0x0e: // MOV.L @(R0,Rm),Rn 0000nnnnmmmm1110
52d759c3 765 tmp = emit_indirect_indexed_read(SHR_R0, GET_Rm(), op & 3);
80599a42 766 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
80599a42 767 if ((op & 3) != 2) {
768 emith_sext(tmp2, tmp, (op & 1) ? 16 : 8);
769 } else
770 emith_move_r_r(tmp2, tmp);
52d759c3 771 rcache_free_tmp(tmp);
80599a42 772 goto end_op;
773 case 0x0f: // MAC.L @Rm+,@Rn+ 0000nnnnmmmm1111
774 // TODO
775 break;
776 }
777 goto default_;
778
3863edbd 779 /////////////////////////////////////////////
80599a42 780 case 0x01:
781 // MOV.L Rm,@(disp,Rn) 0001nnnnmmmmdddd
782 rcache_clean();
783 tmp = rcache_get_reg_arg(0, GET_Rn());
784 tmp2 = rcache_get_reg_arg(1, GET_Rm());
785 emith_add_r_imm(tmp, (op & 0x0f) * 4);
786 emit_memhandler_write(2);
787 goto end_op;
788
789 case 0x02:
790 switch (op & 0x0f)
791 {
792 case 0x00: // MOV.B Rm,@Rn 0010nnnnmmmm0000
793 case 0x01: // MOV.W Rm,@Rn 0010nnnnmmmm0001
794 case 0x02: // MOV.L Rm,@Rn 0010nnnnmmmm0010
795 rcache_clean();
796 rcache_get_reg_arg(0, GET_Rn());
797 rcache_get_reg_arg(1, GET_Rm());
798 emit_memhandler_write(op & 3);
799 goto end_op;
800 case 0x04: // MOV.B Rm,@–Rn 0010nnnnmmmm0100
801 case 0x05: // MOV.W Rm,@–Rn 0010nnnnmmmm0101
802 case 0x06: // MOV.L Rm,@–Rn 0010nnnnmmmm0110
803 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
804 emith_sub_r_imm(tmp, (1 << (op & 3)));
805 rcache_clean();
806 rcache_get_reg_arg(0, GET_Rn());
807 rcache_get_reg_arg(1, GET_Rm());
808 emit_memhandler_write(op & 3);
809 goto end_op;
810 case 0x07: // DIV0S Rm,Rn 0010nnnnmmmm0111
811 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
812 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
813 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
814 emith_bic_r_imm(tmp, M|Q|T);
815 emith_tst_r_imm(tmp2, (1<<31));
816 EMITH_SJMP_START(DCOND_EQ);
817 emith_or_r_imm_c(DCOND_NE, tmp, Q);
818 EMITH_SJMP_END(DCOND_EQ);
819 emith_tst_r_imm(tmp3, (1<<31));
820 EMITH_SJMP_START(DCOND_EQ);
821 emith_or_r_imm_c(DCOND_NE, tmp, M);
822 EMITH_SJMP_END(DCOND_EQ);
823 emith_teq_r_r(tmp2, tmp3);
824 EMITH_SJMP_START(DCOND_PL);
825 emith_or_r_imm_c(DCOND_MI, tmp, T);
826 EMITH_SJMP_END(DCOND_PL);
827 goto end_op;
3863edbd 828 case 0x08: // TST Rm,Rn 0010nnnnmmmm1000
829 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
830 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
831 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
832 emith_bic_r_imm(tmp, T);
833 emith_tst_r_r(tmp2, tmp3);
52d759c3 834 emit_or_t_if_eq(tmp);
3863edbd 835 goto end_op;
836 case 0x09: // AND Rm,Rn 0010nnnnmmmm1001
837 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
838 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
839 emith_and_r_r(tmp, tmp2);
840 goto end_op;
841 case 0x0a: // XOR Rm,Rn 0010nnnnmmmm1010
842 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
843 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
844 emith_eor_r_r(tmp, tmp2);
845 goto end_op;
846 case 0x0b: // OR Rm,Rn 0010nnnnmmmm1011
847 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
848 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
849 emith_or_r_r(tmp, tmp2);
850 goto end_op;
851 case 0x0c: // CMP/STR Rm,Rn 0010nnnnmmmm1100
852 tmp = rcache_get_tmp();
853 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
854 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
855 emith_eor_r_r_r(tmp, tmp2, tmp3);
856 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
857 emith_bic_r_imm(tmp2, T);
858 emith_tst_r_imm(tmp, 0x000000ff);
52d759c3 859 emit_or_t_if_eq(tmp);
3863edbd 860 emith_tst_r_imm(tmp, 0x0000ff00);
52d759c3 861 emit_or_t_if_eq(tmp);
3863edbd 862 emith_tst_r_imm(tmp, 0x00ff0000);
52d759c3 863 emit_or_t_if_eq(tmp);
3863edbd 864 emith_tst_r_imm(tmp, 0xff000000);
52d759c3 865 emit_or_t_if_eq(tmp);
3863edbd 866 rcache_free_tmp(tmp);
867 goto end_op;
868 case 0x0d: // XTRCT Rm,Rn 0010nnnnmmmm1101
869 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
870 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
871 emith_lsr(tmp, tmp, 16);
872 emith_or_r_r_r_lsl(tmp, tmp, tmp2, 16);
873 goto end_op;
874 case 0x0e: // MULU.W Rm,Rn 0010nnnnmmmm1110
875 case 0x0f: // MULS.W Rm,Rn 0010nnnnmmmm1111
876 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
877 tmp = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
878 if (op & 1) {
879 emith_sext(tmp, tmp2, 16);
880 } else
881 emith_clear_msb(tmp, tmp2, 16);
882 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
883 tmp2 = rcache_get_tmp();
884 if (op & 1) {
885 emith_sext(tmp2, tmp3, 16);
886 } else
887 emith_clear_msb(tmp2, tmp3, 16);
888 emith_mul(tmp, tmp, tmp2);
889 rcache_free_tmp(tmp2);
890// FIXME: causes timing issues in Doom?
891// cycles++;
892 goto end_op;
679af8a3 893 }
894 goto default_;
895
3863edbd 896 /////////////////////////////////////////////
897 case 0x03:
898 switch (op & 0x0f)
899 {
900 case 0x00: // CMP/EQ Rm,Rn 0011nnnnmmmm0000
901 case 0x02: // CMP/HS Rm,Rn 0011nnnnmmmm0010
902 case 0x03: // CMP/GE Rm,Rn 0011nnnnmmmm0011
903 case 0x06: // CMP/HI Rm,Rn 0011nnnnmmmm0110
904 case 0x07: // CMP/GT Rm,Rn 0011nnnnmmmm0111
905 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
906 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
907 tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
908 emith_bic_r_imm(tmp, T);
909 emith_cmp_r_r(tmp2, tmp3);
910 switch (op & 0x07)
911 {
912 case 0x00: // CMP/EQ
52d759c3 913 emit_or_t_if_eq(tmp);
3863edbd 914 break;
915 case 0x02: // CMP/HS
916 EMITH_SJMP_START(DCOND_LO);
917 emith_or_r_imm_c(DCOND_HS, tmp, T);
918 EMITH_SJMP_END(DCOND_LO);
919 break;
920 case 0x03: // CMP/GE
921 EMITH_SJMP_START(DCOND_LT);
922 emith_or_r_imm_c(DCOND_GE, tmp, T);
923 EMITH_SJMP_END(DCOND_LT);
924 break;
925 case 0x06: // CMP/HI
926 EMITH_SJMP_START(DCOND_LS);
927 emith_or_r_imm_c(DCOND_HI, tmp, T);
928 EMITH_SJMP_END(DCOND_LS);
929 break;
930 case 0x07: // CMP/GT
931 EMITH_SJMP_START(DCOND_LE);
932 emith_or_r_imm_c(DCOND_GT, tmp, T);
933 EMITH_SJMP_END(DCOND_LE);
934 break;
935 }
936 goto end_op;
937 case 0x04: // DIV1 Rm,Rn 0011nnnnmmmm0100
938 // TODO
939 break;
940 case 0x05: // DMULU.L Rm,Rn 0011nnnnmmmm0101
941 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
942 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
943 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
944 tmp4 = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
945 emith_mul_u64(tmp3, tmp4, tmp, tmp2);
946 goto end_op;
947 case 0x08: // SUB Rm,Rn 0011nnnnmmmm1000
948 case 0x0c: // ADD Rm,Rn 0011nnnnmmmm1100
949 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
950 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
951 if (op & 4) {
952 emith_add_r_r(tmp, tmp2);
953 } else
954 emith_sub_r_r(tmp, tmp2);
955 goto end_op;
956 case 0x0a: // SUBC Rm,Rn 0011nnnnmmmm1010
957 case 0x0e: // ADDC Rm,Rn 0011nnnnmmmm1110
958 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
959 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
960 tmp3 = rcache_get_reg(SHR_SR, RC_GR_RMW);
961 if (op & 4) { // adc
962 emith_set_carry(tmp3);
963 emith_adcf_r_r(tmp, tmp2);
ed8cf79b 964 emith_carry_to_t(tmp3, 0);
3863edbd 965 } else {
966 emith_set_carry_sub(tmp3);
967 emith_sbcf_r_r(tmp, tmp2);
ed8cf79b 968 emith_carry_to_t(tmp3, 1);
3863edbd 969 }
3863edbd 970 goto end_op;
971 case 0x0b: // SUBV Rm,Rn 0011nnnnmmmm1011
972 case 0x0f: // ADDV Rm,Rn 0011nnnnmmmm1111
973 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
974 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
975 tmp3 = rcache_get_reg(SHR_SR, RC_GR_RMW);
976 emith_bic_r_imm(tmp3, T);
977 if (op & 4) {
978 emith_addf_r_r(tmp, tmp2);
979 } else
980 emith_subf_r_r(tmp, tmp2);
981 EMITH_SJMP_START(DCOND_VC);
982 emith_or_r_imm_c(DCOND_VS, tmp3, T);
983 EMITH_SJMP_END(DCOND_VC);
984 goto end_op;
985 case 0x0d: // DMULS.L Rm,Rn 0011nnnnmmmm1101
986 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
987 tmp2 = rcache_get_reg(GET_Rm(), RC_GR_READ);
988 tmp3 = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
989 tmp4 = rcache_get_reg(SHR_MACH, RC_GR_WRITE);
990 emith_mul_s64(tmp3, tmp4, tmp, tmp2);
991 goto end_op;
992 }
993 goto default_;
994
995 /////////////////////////////////////////////
679af8a3 996 case 0x04:
3863edbd 997 switch (op & 0x0f)
998 {
c18edb34 999 case 0x00:
3863edbd 1000 switch (GET_Fx())
1001 {
1002 case 0: // SHLL Rn 0100nnnn00000000
1003 case 2: // SHAL Rn 0100nnnn00100000
1004 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1005 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
3863edbd 1006 emith_lslf(tmp, tmp, 1);
ed8cf79b 1007 emith_carry_to_t(tmp2, 0);
3863edbd 1008 goto end_op;
1009 case 1: // DT Rn 0100nnnn00010000
1010 if (p32x_sh2_read16(pc, sh2) == 0x8bfd) { // BF #-2
1011 emith_sh2_dtbf_loop();
1012 goto end_op;
1013 }
1014 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1015 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1016 emith_bic_r_imm(tmp2, T);
1017 emith_subf_r_imm(tmp, 1);
52d759c3 1018 emit_or_t_if_eq(tmp2);
80599a42 1019 goto end_op;
1020 }
3863edbd 1021 goto default_;
ed8cf79b 1022 case 0x01:
1023 switch (GET_Fx())
1024 {
1025 case 0: // SHLR Rn 0100nnnn00000001
1026 case 2: // SHAR Rn 0100nnnn00100001
1027 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1028 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1029 if (op & 0x20) {
1030 emith_asrf(tmp, tmp, 1);
1031 } else
1032 emith_lsrf(tmp, tmp, 1);
1033 emith_carry_to_t(tmp2, 0);
1034 goto end_op;
1035 case 1: // CMP/PZ Rn 0100nnnn00010001
1036 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1037 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1038 emith_bic_r_imm(tmp2, T);
1039 emith_cmp_r_imm(tmp, 0);
1040 EMITH_SJMP_START(DCOND_LT);
1041 emith_or_r_imm_c(DCOND_GE, tmp2, T);
1042 EMITH_SJMP_END(DCOND_LT);
1043 goto end_op;
1044 }
1045 goto default_;
1046 case 0x02:
1047 case 0x03:
1048 switch (op & 0x3f)
1049 {
1050 case 0x02: // STS.L MACH,@–Rn 0100nnnn00000010
1051 tmp = SHR_MACH;
1052 break;
1053 case 0x12: // STS.L MACL,@–Rn 0100nnnn00010010
1054 tmp = SHR_MACL;
1055 break;
1056 case 0x22: // STS.L PR,@–Rn 0100nnnn00100010
1057 tmp = SHR_PR;
1058 break;
1059 case 0x03: // STC.L SR,@–Rn 0100nnnn00000011
1060 tmp = SHR_SR;
1061 break;
1062 case 0x13: // STC.L GBR,@–Rn 0100nnnn00010011
1063 tmp = SHR_GBR;
1064 break;
1065 case 0x23: // STC.L VBR,@–Rn 0100nnnn00100011
1066 tmp = SHR_VBR;
1067 break;
1068 default:
e898de13 1069 goto default_;
ed8cf79b 1070 }
1071 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1072 emith_sub_r_imm(tmp2, 4);
1073 rcache_clean();
1074 rcache_get_reg_arg(0, GET_Rn());
1075 tmp3 = rcache_get_reg_arg(1, tmp);
1076 if (tmp == SHR_SR)
1077 emith_clear_msb(tmp3, tmp3, 20); // reserved bits defined by ISA as 0
1078 emit_memhandler_write(2);
1079 goto end_op;
1080 case 0x04:
1081 case 0x05:
1082 switch (op & 0x3f)
1083 {
1084 case 0x04: // ROTL Rn 0100nnnn00000100
1085 case 0x05: // ROTR Rn 0100nnnn00000101
1086 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1087 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1088 if (op & 1) {
1089 emith_rorf(tmp, tmp, 1);
1090 } else
1091 emith_rolf(tmp, tmp, 1);
1092 emith_carry_to_t(tmp2, 0);
1093 goto end_op;
1094 case 0x24: // ROTCL Rn 0100nnnn00100100
1095 case 0x25: // ROTCR Rn 0100nnnn00100101
1096 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1097 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1098 emith_set_carry(tmp2);
1099 if (op & 1) {
1100 emith_rorcf(tmp);
1101 } else
1102 emith_rolcf(tmp);
1103 emith_carry_to_t(tmp2, 0);
1104 goto end_op;
1105 case 0x15: // CMP/PL Rn 0100nnnn00010101
1106 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1107 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1108 emith_bic_r_imm(tmp2, T);
1109 emith_cmp_r_imm(tmp, 0);
1110 EMITH_SJMP_START(DCOND_LE);
1111 emith_or_r_imm_c(DCOND_GT, tmp2, T);
1112 EMITH_SJMP_END(DCOND_LE);
1113 goto end_op;
1114 }
e898de13 1115 goto default_;
ed8cf79b 1116 case 0x06:
1117 case 0x07:
1118 switch (op & 0x3f)
1119 {
1120 case 0x06: // LDS.L @Rm+,MACH 0100mmmm00000110
1121 tmp = SHR_MACH;
1122 break;
1123 case 0x16: // LDS.L @Rm+,MACL 0100mmmm00010110
1124 tmp = SHR_MACL;
1125 break;
1126 case 0x26: // LDS.L @Rm+,PR 0100mmmm00100110
1127 tmp = SHR_PR;
1128 break;
1129 case 0x07: // LDC.L @Rm+,SR 0100mmmm00000111
1130 tmp = SHR_SR;
1131 break;
1132 case 0x17: // LDC.L @Rm+,GBR 0100mmmm00010111
1133 tmp = SHR_GBR;
1134 break;
1135 case 0x27: // LDC.L @Rm+,VBR 0100mmmm00100111
1136 tmp = SHR_VBR;
1137 break;
1138 default:
1139 goto default_;
1140 }
1141 rcache_clean();
1142 rcache_get_reg_arg(0, GET_Rn());
1143 tmp2 = emit_memhandler_read(2);
1144 if (tmp == SHR_SR) {
1145 emith_write_sr(tmp2);
1146 test_irq = 1;
1147 } else {
1148 tmp = rcache_get_reg(tmp, RC_GR_WRITE);
1149 emith_move_r_r(tmp, tmp2);
1150 }
1151 rcache_free_tmp(tmp2);
1152 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1153 emith_add_r_imm(tmp, 4);
1154 goto end_op;
52d759c3 1155 case 0x08:
1156 case 0x09:
1157 switch (GET_Fx())
1158 {
1159 case 0:
1160 // SHLL2 Rn 0100nnnn00001000
1161 // SHLR2 Rn 0100nnnn00001001
1162 tmp = 2;
1163 break;
1164 case 1:
1165 // SHLL8 Rn 0100nnnn00011000
1166 // SHLR8 Rn 0100nnnn00011001
1167 tmp = 8;
1168 break;
1169 case 2:
1170 // SHLL16 Rn 0100nnnn00101000
1171 // SHLR16 Rn 0100nnnn00101001
1172 tmp = 16;
1173 break;
1174 default:
1175 goto default_;
1176 }
1177 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1178 if (op & 1) {
1179 emith_lsr(tmp2, tmp2, tmp);
1180 } else
1181 emith_lsl(tmp2, tmp2, tmp);
1182 goto end_op;
1183 case 0x0a:
1184 switch (GET_Fx())
1185 {
1186 case 0: // LDS Rm,MACH 0100mmmm00001010
1187 tmp2 = SHR_MACH;
1188 break;
1189 case 1: // LDS Rm,MACL 0100mmmm00011010
1190 tmp2 = SHR_MACL;
1191 break;
1192 case 2: // LDS Rm,PR 0100mmmm00101010
1193 tmp2 = SHR_PR;
1194 break;
1195 default:
1196 goto default_;
1197 }
1198 emit_move_r_r(tmp2, GET_Rn());
1199 goto end_op;
e898de13 1200 case 0x0b:
52d759c3 1201 switch (GET_Fx())
1202 {
1203 case 0: // JSR @Rm 0100mmmm00001011
1204 case 2: // JMP @Rm 0100mmmm00101011
1205 DELAYED_OP;
1206 if (!(op & 0x20))
1207 emit_move_r_imm32(SHR_PR, pc + 2);
1208 emit_move_r_r(SHR_PPC, (op >> 8) & 0x0f);
1209 cycles++;
1210 break;
1211 case 1: // TAS.B @Rn 0100nnnn00011011
1212 // XXX: is TAS working on 32X?
1213 rcache_clean();
1214 rcache_get_reg_arg(0, GET_Rn());
1215 tmp = emit_memhandler_read(0);
1216 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1217 emith_bic_r_imm(tmp2, T);
1218 emith_cmp_r_imm(tmp, 0);
1219 emit_or_t_if_eq(tmp2);
1220 rcache_clean();
1221 emith_or_r_imm(tmp, 0x80);
1222 tmp2 = rcache_get_tmp_arg(1); // assuming it differs to tmp
1223 emith_move_r_r(tmp2, tmp);
1224 rcache_free_tmp(tmp);
1225 rcache_get_reg_arg(0, GET_Rn());
1226 emit_memhandler_write(0);
1227 cycles += 3;
1228 break;
1229 default:
e898de13 1230 goto default_;
52d759c3 1231 }
e898de13 1232 goto end_op;
1233 case 0x0e:
52d759c3 1234 tmp = rcache_get_reg(GET_Rn(), RC_GR_READ);
1235 switch (GET_Fx())
1236 {
1237 case 0: // LDC Rm,SR 0100mmmm00001110
1238 tmp2 = SHR_SR;
1239 break;
1240 case 1: // LDC Rm,GBR 0100mmmm00011110
1241 tmp2 = SHR_GBR;
1242 break;
1243 case 2: // LDC Rm,VBR 0100mmmm00101110
1244 tmp2 = SHR_VBR;
1245 break;
1246 default:
e898de13 1247 goto default_;
52d759c3 1248 }
1249 if (tmp2 == SHR_SR) {
1250 emith_write_sr(tmp);
1251 emit_move_r_imm32(SHR_PC, pc);
1252 test_irq = 1;
1253 } else {
1254 tmp2 = rcache_get_reg(tmp2, RC_GR_WRITE);
1255 emith_move_r_r(tmp2, tmp);
1256 }
1257 goto end_op;
1258 case 0x0f:
1259 // MAC @Rm+,@Rn+ 0100nnnnmmmm1111
1260 break; // TODO
679af8a3 1261 }
1262 goto default_;
1263
52d759c3 1264 /////////////////////////////////////////////
1265 case 0x05:
1266 // MOV.L @(disp,Rm),Rn 0101nnnnmmmmdddd
1267 rcache_clean();
1268 tmp = rcache_get_reg_arg(0, GET_Rm());
1269 emith_add_r_imm(tmp, (op & 0x0f) * 4);
1270 tmp = emit_memhandler_read(2);
1271 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
1272 emith_move_r_r(tmp2, tmp);
1273 rcache_free_tmp(tmp);
1274 goto end_op;
1275
1276 /////////////////////////////////////////////
1277 case 0x06:
1278 switch (op & 0x0f)
1279 {
1280 case 0x00: // MOV.B @Rm,Rn 0110nnnnmmmm0000
1281 case 0x01: // MOV.W @Rm,Rn 0110nnnnmmmm0001
1282 case 0x02: // MOV.L @Rm,Rn 0110nnnnmmmm0010
1283 case 0x04: // MOV.B @Rm+,Rn 0110nnnnmmmm0100
1284 case 0x05: // MOV.W @Rm+,Rn 0110nnnnmmmm0101
1285 case 0x06: // MOV.L @Rm+,Rn 0110nnnnmmmm0110
1286 rcache_clean();
1287 rcache_get_reg_arg(0, GET_Rm());
1288 tmp = emit_memhandler_read(op & 3);
1289 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
1290 if ((op & 3) != 2) {
1291 emith_sext(tmp2, tmp, (op & 1) ? 16 : 8);
1292 } else
1293 emith_move_r_r(tmp2, tmp);
1294 rcache_free_tmp(tmp);
1295 if ((op & 7) >= 4 && GET_Rn() != GET_Rm()) {
1296 tmp = rcache_get_reg(GET_Rm(), RC_GR_RMW);
1297 emith_add_r_imm(tmp, (1 << (op & 3)));
1298 }
1299 goto end_op;
1300 case 0x03:
1301 case 0x07 ... 0x0f:
1302 tmp = rcache_get_reg(GET_Rm(), RC_GR_READ);
1303 tmp2 = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
1304 switch (op & 0x0f)
1305 {
1306 case 0x03: // MOV Rm,Rn 0110nnnnmmmm0011
1307 emith_move_r_r(tmp2, tmp);
1308 break;
1309 case 0x07: // NOT Rm,Rn 0110nnnnmmmm0111
1310 emith_mvn_r_r(tmp2, tmp);
1311 break;
1312 case 0x08: // SWAP.B Rm,Rn 0110nnnnmmmm1000
1313 tmp3 = tmp2;
1314 if (tmp == tmp2)
1315 tmp3 = rcache_get_tmp();
1316 tmp4 = rcache_get_tmp();
1317 emith_lsr(tmp3, tmp, 16);
1318 emith_or_r_r_r_lsl(tmp3, tmp3, tmp, 24);
1319 emith_and_r_r_imm(tmp4, tmp, 0xff00);
1320 emith_or_r_r_r_lsl(tmp3, tmp3, tmp4, 8);
1321 emith_rol(tmp2, tmp3, 16);
1322 rcache_free_tmp(tmp4);
1323 if (tmp == tmp2)
1324 rcache_free_tmp(tmp3);
1325 break;
1326 case 0x09: // SWAP.W Rm,Rn 0110nnnnmmmm1001
1327 emith_rol(tmp2, tmp, 16);
1328 break;
1329 case 0x0a: // NEGC Rm,Rn 0110nnnnmmmm1010
1330 tmp3 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1331 emith_set_carry_sub(tmp3);
1332 emith_negcf_r_r(tmp2, tmp);
1333 emith_carry_to_t(tmp3, 1);
1334 break;
1335 case 0x0b: // NEG Rm,Rn 0110nnnnmmmm1011
1336 emith_neg_r_r(tmp2, tmp);
1337 break;
1338 case 0x0c: // EXTU.B Rm,Rn 0110nnnnmmmm1100
1339 emith_clear_msb(tmp2, tmp, 24);
1340 break;
1341 case 0x0d: // EXTU.W Rm,Rn 0110nnnnmmmm1101
1342 emith_clear_msb(tmp2, tmp, 16);
1343 break;
1344 case 0x0e: // EXTS.B Rm,Rn 0110nnnnmmmm1110
1345 emith_sext(tmp2, tmp, 8);
1346 break;
1347 case 0x0f: // EXTS.W Rm,Rn 0110nnnnmmmm1111
1348 emith_sext(tmp2, tmp, 16);
1349 break;
1350 }
1351 goto end_op;
1352 }
1353 goto default_;
1354
1355 /////////////////////////////////////////////
1356 case 0x07:
1357 // ADD #imm,Rn 0111nnnniiiiiiii
1358 tmp = rcache_get_reg(GET_Rn(), RC_GR_RMW);
1359 if (op & 0x80) { // adding negative
1360 emith_sub_r_imm(tmp, -op & 0xff);
1361 } else
1362 emith_add_r_imm(tmp, op & 0xff);
1363 goto end_op;
1364
3863edbd 1365 /////////////////////////////////////////////
e898de13 1366 case 0x08:
52d759c3 1367 switch (op & 0x0f00)
1368 {
1369 case 0x0000: // MOV.B R0,@(disp,Rn) 10000000nnnndddd
1370 case 0x0100: // MOV.W R0,@(disp,Rn) 10000001nnnndddd
1371 rcache_clean();
1372 tmp = rcache_get_reg_arg(0, GET_Rm());
1373 tmp2 = rcache_get_reg_arg(1, SHR_R0);
1374 tmp3 = (op & 0x100) >> 8;
1375 emith_add_r_imm(tmp, (op & 0x0f) << tmp3);
1376 emit_memhandler_write(tmp3);
1377 goto end_op;
1378 case 0x0400: // MOV.B @(disp,Rm),R0 10000100mmmmdddd
1379 case 0x0500: // MOV.W @(disp,Rm),R0 10000101mmmmdddd
1380 rcache_clean();
1381 tmp = rcache_get_reg_arg(0, GET_Rm());
1382 tmp3 = (op & 0x100) >> 8;
1383 emith_add_r_imm(tmp, (op & 0x0f) << tmp3);
1384 tmp = emit_memhandler_read(tmp3);
1385 tmp2 = rcache_get_reg(0, RC_GR_WRITE);
1386 emith_sext(tmp2, tmp, 8 << tmp3);
1387 rcache_free_tmp(tmp);
1388 goto end_op;
1389 case 0x0800: // CMP/EQ #imm,R0 10001000iiiiiiii
1390 // XXX: could use cmn
1391 tmp = rcache_get_tmp();
1392 tmp2 = rcache_get_reg(0, RC_GR_READ);
1393 tmp3 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1394 emith_move_r_imm_s8(tmp, op & 0xff);
1395 emith_bic_r_imm(tmp3, T);
1396 emith_cmp_r_r(tmp2, tmp);
1397 emit_or_t_if_eq(tmp3);
1398 rcache_free_tmp(tmp);
1399 goto end_op;
1400 case 0x0d00: // BT/S label 10001101dddddddd
1401 case 0x0f00: // BF/S label 10001111dddddddd
679af8a3 1402 DELAYED_OP;
1403 cycles--;
679af8a3 1404 // fallthrough
52d759c3 1405 case 0x0900: // BT label 10001001dddddddd
1406 case 0x0b00: { // BF label 10001011dddddddd
80599a42 1407 // jmp_cond ~ cond when guest doesn't jump
1408 int jmp_cond = (op & 0x0200) ? DCOND_NE : DCOND_EQ;
1409 int insn_cond = (op & 0x0200) ? DCOND_EQ : DCOND_NE;
1410 signed int offs = ((signed int)(op << 24) >> 23);
1411 tmp = rcache_get_reg(delayed_op ? SHR_PPC : SHR_PC, RC_GR_WRITE);
1412 emith_move_r_imm(tmp, pc + (delayed_op ? 2 : 0));
1413 emith_sh2_test_t();
1414 EMITH_SJMP_START(jmp_cond);
1415 if (!delayed_op)
1416 offs += 2;
1417 if (offs < 0) {
1418 emith_sub_r_imm_c(insn_cond, tmp, -offs);
1419 } else
1420 emith_add_r_imm_c(insn_cond, tmp, offs);
1421 EMITH_SJMP_END(jmp_cond);
e898de13 1422 cycles += 2;
1423 if (!delayed_op)
52d759c3 1424 goto end_block_btf;
e898de13 1425 goto end_op;
80599a42 1426 }}
679af8a3 1427 goto default_;
679af8a3 1428
52d759c3 1429 /////////////////////////////////////////////
1430 case 0x09:
1431 // MOV.W @(disp,PC),Rn 1001nnnndddddddd
1432 // TODO
1433 goto default_;
1434
3863edbd 1435 /////////////////////////////////////////////
679af8a3 1436 case 0x0a:
1437 // BRA label 1010dddddddddddd
1438 DELAYED_OP;
1439 do_bra:
1440 tmp = ((signed int)(op << 20) >> 19);
e898de13 1441 emit_move_r_imm32(SHR_PPC, pc + tmp + 2);
679af8a3 1442 cycles++;
e898de13 1443 break;
679af8a3 1444
3863edbd 1445 /////////////////////////////////////////////
679af8a3 1446 case 0x0b:
1447 // BSR label 1011dddddddddddd
1448 DELAYED_OP;
e898de13 1449 emit_move_r_imm32(SHR_PR, pc + 2);
679af8a3 1450 goto do_bra;
1451
52d759c3 1452 /////////////////////////////////////////////
1453 case 0x0c:
1454 switch (op & 0x0f00)
1455 {
1456 case 0x0000: // MOV.B R0,@(disp,GBR) 11000000dddddddd
1457 case 0x0100: // MOV.W R0,@(disp,GBR) 11000001dddddddd
1458 case 0x0200: // MOV.L R0,@(disp,GBR) 11000010dddddddd
1459 rcache_clean();
1460 tmp = rcache_get_reg_arg(0, SHR_GBR);
1461 tmp2 = rcache_get_reg_arg(1, SHR_R0);
1462 tmp3 = (op & 0x300) >> 8;
1463 emith_add_r_imm(tmp, (op & 0xff) << tmp3);
1464 emit_memhandler_write(tmp3);
1465 goto end_op;
1466 case 0x0400: // MOV.B @(disp,GBR),R0 11000100dddddddd
1467 case 0x0500: // MOV.W @(disp,GBR),R0 11000101dddddddd
1468 case 0x0600: // MOV.L @(disp,GBR),R0 11000110dddddddd
1469 rcache_clean();
1470 tmp = rcache_get_reg_arg(0, SHR_GBR);
1471 tmp3 = (op & 0x300) >> 8;
1472 emith_add_r_imm(tmp, (op & 0xff) << tmp3);
1473 tmp = emit_memhandler_read(tmp3);
1474 tmp2 = rcache_get_reg(0, RC_GR_WRITE);
1475 if (tmp3 != 2) {
1476 emith_sext(tmp2, tmp, 8 << tmp3);
1477 } else
1478 emith_move_r_r(tmp2, tmp);
1479 rcache_free_tmp(tmp);
1480 goto end_op;
1481 case 0x0300: // TRAPA #imm 11000011iiiiiiii
1482 tmp = rcache_get_reg(SHR_SP, RC_GR_RMW);
1483 emith_sub_r_imm(tmp, 4*2);
1484 rcache_clean();
1485 // push SR
1486 tmp = rcache_get_reg_arg(0, SHR_SP);
1487 emith_add_r_imm(tmp, 4);
1488 tmp = rcache_get_reg_arg(1, SHR_SR);
1489 emith_clear_msb(tmp, tmp, 20);
1490 emit_memhandler_write(2);
1491 // push PC
1492 rcache_get_reg_arg(0, SHR_SP);
1493 tmp = rcache_get_tmp_arg(1);
1494 emith_move_r_imm(tmp, pc);
1495 emit_memhandler_write(2);
1496 // obtain new PC
1497 tmp = rcache_get_reg_arg(0, SHR_VBR);
1498 emith_add_r_imm(tmp, (op & 0xff) * 4);
1499 tmp = emit_memhandler_read(2);
1500 tmp2 = rcache_get_reg(SHR_PC, RC_GR_WRITE);
1501 emith_move_r_r(tmp2, tmp);
1502 rcache_free_tmp(tmp);
1503 cycles += 7;
1504 goto end_block_btf;
1505 case 0x0700: // MOVA @(disp,PC),R0 11000111dddddddd
1506 emit_move_r_imm32(SHR_R0, (pc + (op & 0xff) * 4 + 2) & ~3);
1507 goto end_op;
1508 case 0x0800: // TST #imm,R0 11001000iiiiiiii
1509 tmp = rcache_get_reg(SHR_R0, RC_GR_READ);
1510 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1511 emith_bic_r_imm(tmp2, T);
1512 emith_tst_r_imm(tmp, op & 0xff);
1513 emit_or_t_if_eq(tmp2);
1514 goto end_op;
1515 case 0x0900: // AND #imm,R0 11001001iiiiiiii
1516 tmp = rcache_get_reg(SHR_R0, RC_GR_RMW);
1517 emith_and_r_imm(tmp, op & 0xff);
1518 goto end_op;
1519 case 0x0a00: // XOR #imm,R0 11001010iiiiiiii
1520 tmp = rcache_get_reg(SHR_R0, RC_GR_RMW);
1521 emith_eor_r_imm(tmp, op & 0xff);
1522 goto end_op;
1523 case 0x0b00: // OR #imm,R0 11001011iiiiiiii
1524 tmp = rcache_get_reg(SHR_R0, RC_GR_RMW);
1525 emith_or_r_imm(tmp, op & 0xff);
1526 goto end_op;
1527 case 0x0c00: // TST.B #imm,@(R0,GBR) 11001100iiiiiiii
1528 tmp = emit_indirect_indexed_read(SHR_R0, SHR_GBR, 0);
1529 tmp2 = rcache_get_reg(SHR_SR, RC_GR_RMW);
1530 emith_bic_r_imm(tmp2, T);
1531 emith_tst_r_imm(tmp, op & 0xff);
1532 emit_or_t_if_eq(tmp2);
1533 rcache_free_tmp(tmp);
1534 cycles += 2;
1535 goto end_op;
1536 case 0x0d00: // AND.B #imm,@(R0,GBR) 11001101iiiiiiii
1537 tmp = emit_indirect_indexed_read(SHR_R0, SHR_GBR, 0);
1538 emith_and_r_imm(tmp, op & 0xff);
1539 emit_indirect_indexed_write(SHR_R0, SHR_GBR, tmp, 0);
1540 cycles += 2;
1541 goto end_op;
1542 case 0x0e00: // XOR.B #imm,@(R0,GBR) 11001110iiiiiiii
1543 tmp = emit_indirect_indexed_read(SHR_R0, SHR_GBR, 0);
1544 emith_eor_r_imm(tmp, op & 0xff);
1545 emit_indirect_indexed_write(SHR_R0, SHR_GBR, tmp, 0);
1546 cycles += 2;
1547 goto end_op;
1548 case 0x0f00: // OR.B #imm,@(R0,GBR) 11001111iiiiiiii
1549 tmp = emit_indirect_indexed_read(SHR_R0, SHR_GBR, 0);
1550 emith_or_r_imm(tmp, op & 0xff);
1551 emit_indirect_indexed_write(SHR_R0, SHR_GBR, tmp, 0);
1552 cycles += 2;
1553 goto end_op;
1554 }
1555 goto default_;
1556
1557 /////////////////////////////////////////////
1558 case 0x0d:
1559 // MOV.L @(disp,PC),Rn 1101nnnndddddddd
1560 // TODO
1561 goto default_;
1562
1563 /////////////////////////////////////////////
1564 case 0x0e:
1565 // MOV #imm,Rn 1110nnnniiiiiiii
1566 tmp = rcache_get_reg(GET_Rn(), RC_GR_WRITE);
1567 emith_move_r_imm_s8(tmp, op & 0xff);
1568 goto end_op;
1569
679af8a3 1570 default:
1571 default_:
1572 emit_move_r_imm32(SHR_PC, pc - 2);
c18edb34 1573 rcache_flush();
f4bb5d6b 1574 emith_pass_arg_r(0, CONTEXT_REG);
1575 emith_pass_arg_imm(1, op);
679af8a3 1576 emith_call(sh2_do_op);
1577 break;
1578 }
1579
e898de13 1580end_op:
6add7875 1581 if (delayed_op == 1)
e898de13 1582 emit_move_r_r(SHR_PC, SHR_PPC);
6add7875 1583
e898de13 1584 if (test_irq && delayed_op != 2) {
c18edb34 1585 rcache_flush();
f4bb5d6b 1586 emith_pass_arg_r(0, CONTEXT_REG);
e898de13 1587 emith_call(sh2_test_irq);
1588 break;
1589 }
6add7875 1590 if (delayed_op == 1)
1591 break;
e898de13 1592
f4bb5d6b 1593 do_host_disasm(tcache_id);
679af8a3 1594 }
1595
52d759c3 1596 // delayed_op means some kind of branch - PC already handled
1597 if (!delayed_op)
1598 emit_move_r_imm32(SHR_PC, pc);
1599
1600end_block_btf:
f4bb5d6b 1601 this_block->end_addr = pc;
1602
1603 // mark memory blocks as containing compiled code
1604 if ((sh2->pc & 0xe0000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
1605 // data array, BIOS
1606 u16 *drcblk = Pico32xMem->drcblk_da[sh2->is_slave];
1607 tmp = (this_block->addr & 0xfff) >> SH2_DRCBLK_DA_SHIFT;
1608 tmp2 = (this_block->end_addr & 0xfff) >> SH2_DRCBLK_DA_SHIFT;
1609 Pico32xMem->drcblk_da[sh2->is_slave][tmp] = (blkid << 1) | 1;
1610 for (++tmp; tmp < tmp2; tmp++) {
1611 if (drcblk[tmp])
1612 break; // dont overwrite overlay block
1613 drcblk[tmp] = blkid << 1;
1614 }
1615 }
1616 else if ((this_block->addr & 0xc7fc0000) == 0x06000000) { // DRAM
1617 tmp = (this_block->addr & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT;
1618 tmp2 = (this_block->end_addr & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT;
1619 Pico32xMem->drcblk_ram[tmp] = (blkid << 1) | 1;
1620 for (++tmp; tmp < tmp2; tmp++) {
1621 if (Pico32xMem->drcblk_ram[tmp])
1622 break;
1623 Pico32xMem->drcblk_ram[tmp] = blkid << 1;
1624 }
679af8a3 1625 }
1626
c18edb34 1627 tmp = rcache_get_reg(SHR_SR, RC_GR_RMW);
1628 emith_sub_r_imm(tmp, cycles << 12);
1629 rcache_flush();
679af8a3 1630 emith_jump(sh2_drc_exit);
f4bb5d6b 1631 tcache_ptrs[tcache_id] = tcache_ptr;
1632
553c3eaa 1633#ifdef ARM
1634 cache_flush_d_inval_i(block_entry, tcache_ptr);
1635#endif
1636
f4bb5d6b 1637 do_host_disasm(tcache_id);
1638 dbg(1, " block #%d,%d tcache %d/%d, insns %d -> %d %.3f",
1639 tcache_id, block_counts[tcache_id],
1640 tcache_ptr - tcache_bases[tcache_id], tcache_sizes[tcache_id],
1641 insns_compiled, host_insn_count, (double)host_insn_count / insns_compiled);
1642 if ((sh2->pc & 0xc6000000) == 0x02000000) // ROM
1643 dbg(1, " hash collisions %d/%d", hash_collisions, block_counts[tcache_id]);
553c3eaa 1644#if (DRC_DEBUG & 2)
1645 fflush(stdout);
1646#endif
1647
679af8a3 1648 return block_entry;
f4bb5d6b 1649/*
679af8a3 1650unimplemented:
1651 // last op
f4bb5d6b 1652 do_host_disasm(tcache_id);
679af8a3 1653 exit(1);
f4bb5d6b 1654*/
679af8a3 1655}
1656
1657void __attribute__((noinline)) sh2_drc_dispatcher(SH2 *sh2)
1658{
52d759c3 1659 // TODO: need to handle self-caused interrupts
1660 sh2_test_irq(sh2);
1661
679af8a3 1662 while (((signed int)sh2->sr >> 12) > 0)
1663 {
679af8a3 1664 void *block = NULL;
f4bb5d6b 1665 block_desc *bd = NULL;
6add7875 1666
1667 // FIXME: must avoid doing it so often..
52d759c3 1668 //sh2_test_irq(sh2);
6add7875 1669
f4bb5d6b 1670 // we have full block id tables for data_array and RAM
1671 // BIOS goes to data_array table too
1672 if ((sh2->pc & 0xff000000) == 0xc0000000 || (sh2->pc & ~0xfff) == 0) {
1673 int blkid = Pico32xMem->drcblk_da[sh2->is_slave][(sh2->pc & 0xfff) >> SH2_DRCBLK_DA_SHIFT];
1674 if (blkid & 1) {
1675 bd = &block_tables[1 + sh2->is_slave][blkid >> 1];
1676 block = bd->tcache_ptr;
1677 }
1678 }
1679 // RAM
1680 else if ((sh2->pc & 0xc6000000) == 0x06000000) {
1681 int blkid = Pico32xMem->drcblk_ram[(sh2->pc & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT];
1682 if (blkid & 1) {
1683 bd = &block_tables[0][blkid >> 1];
679af8a3 1684 block = bd->tcache_ptr;
f4bb5d6b 1685 }
1686 }
1687 // ROM
1688 else if ((sh2->pc & 0xc6000000) == 0x02000000) {
1689 bd = HASH_FUNC(hash_table, sh2->pc);
1690
1691 if (bd != NULL) {
1692 if (bd->addr == sh2->pc)
1693 block = bd->tcache_ptr;
1694 else
1695 block = dr_find_block(bd, sh2->pc);
1696 }
679af8a3 1697 }
1698
1699 if (block == NULL)
1700 block = sh2_translate(sh2, bd);
1701
f4bb5d6b 1702 dbg(4, "= %csh2 enter %08x %p, c=%d", sh2->is_slave ? 's' : 'm',
1703 sh2->pc, block, (signed int)sh2->sr >> 12);
1704#if (DRC_DEBUG & 1)
1705 if (bd != NULL)
1706 bd->refcount++;
679af8a3 1707#endif
1708 sh2_drc_entry(sh2, block);
1709 }
1710}
1711
f4bb5d6b 1712static void sh2_smc_rm_block(u16 *drcblk, u16 *p, block_desc *btab, u32 a)
1713{
1714 u16 id = *p >> 1;
1715 block_desc *bd = btab + id;
1716
1717 dbg(1, " killing block %08x", bd->addr);
1718 bd->addr = bd->end_addr = 0;
1719
1720 while (p > drcblk && (p[-1] >> 1) == id)
1721 p--;
1722
1723 // check for possible overlay block
1724 if (p > 0 && p[-1] != 0) {
1725 bd = btab + (p[-1] >> 1);
1726 if (bd->addr <= a && a < bd->end_addr)
1727 sh2_smc_rm_block(drcblk, p - 1, btab, a);
1728 }
1729
1730 do {
1731 *p++ = 0;
1732 }
1733 while ((*p >> 1) == id);
1734}
1735
1736void sh2_drc_wcheck_ram(unsigned int a, int val, int cpuid)
1737{
1738 u16 *drcblk = Pico32xMem->drcblk_ram;
1739 u16 *p = drcblk + ((a & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT);
1740
1741 dbg(1, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a);
1742 sh2_smc_rm_block(drcblk, p, block_tables[0], a);
1743}
1744
1745void sh2_drc_wcheck_da(unsigned int a, int val, int cpuid)
1746{
1747 u16 *drcblk = Pico32xMem->drcblk_da[cpuid];
1748 u16 *p = drcblk + ((a & 0xfff) >> SH2_DRCBLK_DA_SHIFT);
1749
1750 dbg(1, "%csh2 smc check @%08x", cpuid ? 's' : 'm', a);
1751 sh2_smc_rm_block(drcblk, p, block_tables[1 + cpuid], a);
1752}
1753
52d759c3 1754void sh2_execute(SH2 *sh2c, int cycles)
679af8a3 1755{
52d759c3 1756 sh2 = sh2c; // XXX
1757
1758 sh2c->cycles_aim += cycles;
1759 cycles = sh2c->cycles_aim - sh2c->cycles_done;
679af8a3 1760
1761 // cycles are kept in SHR_SR unused bits (upper 20)
52d759c3 1762 sh2c->sr &= 0x3f3;
1763 sh2c->sr |= cycles << 12;
1764 sh2_drc_dispatcher(sh2c);
679af8a3 1765
52d759c3 1766 sh2c->cycles_done += cycles - ((signed int)sh2c->sr >> 12);
679af8a3 1767}
1768
553c3eaa 1769static void REGPARM(1) sh2_test_irq(SH2 *sh2)
679af8a3 1770{
6add7875 1771 if (sh2->pending_level > ((sh2->sr >> 4) & 0x0f))
1772 {
1773 if (sh2->pending_irl > sh2->pending_int_irq)
1774 sh2_do_irq(sh2, sh2->pending_irl, 64 + sh2->pending_irl/2);
1775 else {
1776 sh2_do_irq(sh2, sh2->pending_int_irq, sh2->pending_int_vector);
1777 sh2->pending_int_irq = 0; // auto-clear
1778 sh2->pending_level = sh2->pending_irl;
1779 }
1780 }
679af8a3 1781}
1782
f4bb5d6b 1783#if (DRC_DEBUG & 1)
1784static void block_stats(void)
1785{
1786 int c, b, i, total = 0;
1787
1788 for (b = 0; b < ARRAY_SIZE(block_tables); b++)
1789 for (i = 0; i < block_counts[b]; i++)
1790 if (block_tables[b][i].addr != 0)
1791 total += block_tables[b][i].refcount;
1792
1793 for (c = 0; c < 10; c++) {
1794 block_desc *blk, *maxb = NULL;
1795 int max = 0;
1796 for (b = 0; b < ARRAY_SIZE(block_tables); b++) {
1797 for (i = 0; i < block_counts[b]; i++) {
1798 blk = &block_tables[b][i];
1799 if (blk->addr != 0 && blk->refcount > max) {
1800 max = blk->refcount;
1801 maxb = blk;
1802 }
1803 }
1804 }
1805 if (maxb == NULL)
1806 break;
1807 printf("%08x %9d %2.3f%%\n", maxb->addr, maxb->refcount,
1808 (double)maxb->refcount / total * 100.0);
1809 maxb->refcount = 0;
1810 }
553c3eaa 1811
1812 for (b = 0; b < ARRAY_SIZE(block_tables); b++)
1813 for (i = 0; i < block_counts[b]; i++)
1814 block_tables[b][i].refcount = 0;
f4bb5d6b 1815}
553c3eaa 1816#else
1817#define block_stats()
f4bb5d6b 1818#endif
1819
553c3eaa 1820void sh2_drc_flush_all(void)
1821{
1822 block_stats();
1823 flush_tcache(0);
1824 flush_tcache(1);
1825 flush_tcache(2);
1826}
1827
679af8a3 1828int sh2_drc_init(SH2 *sh2)
1829{
f4bb5d6b 1830 if (block_tables[0] == NULL) {
1831 int i, cnt;
7f5a3fc1 1832
1833 drc_cmn_init();
1834
f4bb5d6b 1835 cnt = block_max_counts[0] + block_max_counts[1] + block_max_counts[2];
1836 block_tables[0] = calloc(cnt, sizeof(*block_tables[0]));
1837 if (block_tables[0] == NULL)
e898de13 1838 return -1;
1839
f4bb5d6b 1840 memset(block_counts, 0, sizeof(block_counts));
1841 tcache_bases[0] = tcache_ptrs[0] = tcache;
1842
1843 for (i = 1; i < ARRAY_SIZE(block_tables); i++) {
1844 block_tables[i] = block_tables[i - 1] + block_max_counts[i - 1];
1845 tcache_bases[i] = tcache_ptrs[i] = tcache_bases[i - 1] + tcache_sizes[i - 1];
1846 }
1847
553c3eaa 1848 // tmp
1849 PicoOpt |= POPT_DIS_VDP_FIFO;
1850
f4bb5d6b 1851#if (DRC_DEBUG & 2)
1852 for (i = 0; i < ARRAY_SIZE(block_tables); i++)
1853 tcache_dsm_ptrs[i] = tcache_bases[i];
1854#endif
e898de13 1855#if (DRC_DEBUG & 1)
1856 hash_collisions = 0;
1857#endif
679af8a3 1858 }
1859
f4bb5d6b 1860 if (hash_table == NULL) {
1861 hash_table = calloc(sizeof(hash_table[0]), MAX_HASH_ENTRIES);
1862 if (hash_table == NULL)
1863 return -1;
1864 }
41397701 1865
679af8a3 1866 return 0;
41397701 1867}
1868
e898de13 1869void sh2_drc_finish(SH2 *sh2)
1870{
f4bb5d6b 1871 if (block_tables[0] != NULL) {
f4bb5d6b 1872 block_stats();
f4bb5d6b 1873 free(block_tables[0]);
1874 memset(block_tables, 0, sizeof(block_tables));
7f5a3fc1 1875
1876 drc_cmn_cleanup();
e898de13 1877 }
1878
f4bb5d6b 1879 if (hash_table != NULL) {
1880 free(hash_table);
1881 hash_table = NULL;
1882 }
e898de13 1883}