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