added 12-in-1 mapper to carthw
[picodrive.git] / Pico / carthw / svp / compiler.c
CommitLineData
726bbb3e 1// 187 blocks, 12072 bytes
2// 14 IRAM blocks
3
4#include "../../PicoInt.h"
e807ac75 5#include "compiler.h"
726bbb3e 6
892b1dd2 7static unsigned int *block_table[0x5090/2];
8static unsigned int *block_table_iram[15][0x800/2];
892b1dd2 9static unsigned int *tcache_ptr = NULL;
726bbb3e 10
726bbb3e 11static int nblocks = 0;
df143b36 12static int iram_context = 0;
726bbb3e 13
5d817c91 14#ifndef ARM
bad5731d 15#define DUMP_BLOCK 0x29a0
5d817c91 16unsigned int tcache[512*1024];
17void regfile_load(void){}
18void regfile_store(void){}
19#endif
20
726bbb3e 21#define EMBED_INTERPRETER
22#define ssp1601_reset ssp1601_reset_local
23#define ssp1601_run ssp1601_run_local
24
5c129565 25#define GET_PC() rPC
26#define GET_PPC_OFFS() (GET_PC()*2 - 2)
d274c33b 27#define SET_PC(d) { rPC = d; } /* must return to dispatcher after this */
726bbb3e 28//#define GET_PC() (PC - (unsigned short *)svp->iram_rom)
29//#define GET_PPC_OFFS() ((unsigned int)PC - (unsigned int)svp->iram_rom - 2)
30//#define SET_PC(d) PC = (unsigned short *)svp->iram_rom + d
31
32#include "ssp16.c"
5c129565 33#include "gen_arm.c"
726bbb3e 34
35// -----------------------------------------------------
36
892b1dd2 37// ld d, s
38static void op00(unsigned int op, unsigned int imm)
39{
40 unsigned int tmpv;
259ed0ea 41 PC = ((unsigned short *)(void *)&op) + 1; /* FIXME: needed for interpreter */
892b1dd2 42 if (op == 0) return; // nop
43 if (op == ((SSP_A<<4)|SSP_P)) { // A <- P
44 // not sure. MAME claims that only hi word is transfered.
45 read_P(); // update P
46 rA32 = rP.v;
47 }
48 else
49 {
50 tmpv = REG_READ(op & 0x0f);
51 REG_WRITE((op & 0xf0) >> 4, tmpv);
52 }
53}
54
55// ld d, (ri)
56static void op01(unsigned int op, unsigned int imm)
57{
58 unsigned int tmpv;
59 tmpv = ptr1_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv);
60}
61
62// ld (ri), s
63static void op02(unsigned int op, unsigned int imm)
64{
65 unsigned int tmpv;
66 tmpv = REG_READ((op & 0xf0) >> 4); ptr1_write(op, tmpv);
67}
68
69// ldi d, imm
70static void op04(unsigned int op, unsigned int imm)
71{
72 REG_WRITE((op & 0xf0) >> 4, imm);
73}
74
75// ld d, ((ri))
76static void op05(unsigned int op, unsigned int imm)
77{
78 unsigned int tmpv;
79 tmpv = ptr2_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv);
80}
81
82// ldi (ri), imm
83static void op06(unsigned int op, unsigned int imm)
84{
85 ptr1_write(op, imm);
86}
87
88// ld adr, a
89static void op07(unsigned int op, unsigned int imm)
90{
91 ssp->RAM[op & 0x1ff] = rA;
92}
93
94// ld d, ri
95static void op09(unsigned int op, unsigned int imm)
96{
97 unsigned int tmpv;
98 tmpv = rIJ[(op&3)|((op>>6)&4)]; REG_WRITE((op & 0xf0) >> 4, tmpv);
99}
100
101// ld ri, s
102static void op0a(unsigned int op, unsigned int imm)
103{
104 rIJ[(op&3)|((op>>6)&4)] = REG_READ((op & 0xf0) >> 4);
105}
106
107// ldi ri, simm (also op0d op0e op0f)
108static void op0c(unsigned int op, unsigned int imm)
109{
110 rIJ[(op>>8)&7] = op;
111}
112
113// call cond, addr
114static void op24(unsigned int op, unsigned int imm)
115{
116 int cond = 0;
117 do {
118 COND_CHECK
259ed0ea 119 if (cond) { int new_PC = imm; write_STACK(GET_PC()); SET_PC(new_PC); }
892b1dd2 120 }
121 while (0);
122}
123
124// ld d, (a)
125static void op25(unsigned int op, unsigned int imm)
126{
127 unsigned int tmpv;
128 tmpv = ((unsigned short *)svp->iram_rom)[rA]; REG_WRITE((op & 0xf0) >> 4, tmpv);
129}
130
131// bra cond, addr
132static void op26(unsigned int op, unsigned int imm)
133{
134 do
135 {
136 int cond = 0;
137 COND_CHECK
259ed0ea 138 if (cond) SET_PC(imm);
892b1dd2 139 }
259ed0ea 140 while (0);
892b1dd2 141}
142
143// mod cond, op
144static void op48(unsigned int op, unsigned int imm)
145{
146 do
147 {
148 int cond = 0;
149 COND_CHECK
150 if (cond) {
151 switch (op & 7) {
152 case 2: rA32 = (signed int)rA32 >> 1; break; // shr (arithmetic)
153 case 3: rA32 <<= 1; break; // shl
154 case 6: rA32 = -(signed int)rA32; break; // neg
155 case 7: if ((int)rA32 < 0) rA32 = -(signed int)rA32; break; // abs
156 default: elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: unhandled mod %i @ %04x",
157 op&7, GET_PPC_OFFS());
158 }
159 UPD_ACC_ZN // ?
160 }
161 }
162 while(0);
163}
164
165// mpys?
166static void op1b(unsigned int op, unsigned int imm)
167{
168 read_P(); // update P
169 rA32 -= rP.v; // maybe only upper word?
170 UPD_ACC_ZN // there checking flags after this
171 rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
172 rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
173}
174
175// mpya (rj), (ri), b
176static void op4b(unsigned int op, unsigned int imm)
177{
178 read_P(); // update P
179 rA32 += rP.v; // confirmed to be 32bit
180 UPD_ACC_ZN // ?
181 rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
182 rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
183}
184
185// mld (rj), (ri), b
186static void op5b(unsigned int op, unsigned int imm)
187{
188 rA32 = 0;
189 rST &= 0x0fff; // ?
190 rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
191 rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
192}
193
194// OP a, s
195static void op10(unsigned int op, unsigned int imm)
196{
197 do
198 {
199 unsigned int tmpv;
200 OP_CHECK32(OP_SUBA32); tmpv = REG_READ(op & 0x0f); OP_SUBA(tmpv);
201 }
202 while(0);
203}
204
205static void op30(unsigned int op, unsigned int imm)
206{
207 do
208 {
209 unsigned int tmpv;
210 OP_CHECK32(OP_CMPA32); tmpv = REG_READ(op & 0x0f); OP_CMPA(tmpv);
211 }
212 while(0);
213}
214
215static void op40(unsigned int op, unsigned int imm)
216{
217 do
218 {
219 unsigned int tmpv;
220 OP_CHECK32(OP_ADDA32); tmpv = REG_READ(op & 0x0f); OP_ADDA(tmpv);
221 }
222 while(0);
223}
224
225static void op50(unsigned int op, unsigned int imm)
226{
227 do
228 {
229 unsigned int tmpv;
230 OP_CHECK32(OP_ANDA32); tmpv = REG_READ(op & 0x0f); OP_ANDA(tmpv);
231 }
232 while(0);
233}
234
235static void op60(unsigned int op, unsigned int imm)
236{
237 do
238 {
239 unsigned int tmpv;
240 OP_CHECK32(OP_ORA32 ); tmpv = REG_READ(op & 0x0f); OP_ORA (tmpv);
241 }
242 while(0);
243}
244
245static void op70(unsigned int op, unsigned int imm)
246{
247 do
248 {
249 unsigned int tmpv;
250 OP_CHECK32(OP_EORA32); tmpv = REG_READ(op & 0x0f); OP_EORA(tmpv);
251 }
252 while(0);
253}
254
255// OP a, (ri)
256static void op11(unsigned int op, unsigned int imm)
257{
258 unsigned int tmpv;
259 tmpv = ptr1_read(op); OP_SUBA(tmpv);
260}
261
262static void op31(unsigned int op, unsigned int imm)
263{
264 unsigned int tmpv;
265 tmpv = ptr1_read(op); OP_CMPA(tmpv);
266}
267
268static void op41(unsigned int op, unsigned int imm)
269{
270 unsigned int tmpv;
271 tmpv = ptr1_read(op); OP_ADDA(tmpv);
272}
273
274static void op51(unsigned int op, unsigned int imm)
275{
276 unsigned int tmpv;
277 tmpv = ptr1_read(op); OP_ANDA(tmpv);
278}
279
280static void op61(unsigned int op, unsigned int imm)
281{
282 unsigned int tmpv;
283 tmpv = ptr1_read(op); OP_ORA (tmpv);
284}
285
286static void op71(unsigned int op, unsigned int imm)
287{
288 unsigned int tmpv;
289 tmpv = ptr1_read(op); OP_EORA(tmpv);
290}
291
292// OP a, adr
293static void op03(unsigned int op, unsigned int imm)
294{
295 unsigned int tmpv;
296 tmpv = ssp->RAM[op & 0x1ff]; OP_LDA (tmpv);
297}
298
299static void op13(unsigned int op, unsigned int imm)
300{
301 unsigned int tmpv;
302 tmpv = ssp->RAM[op & 0x1ff]; OP_SUBA(tmpv);
303}
304
305static void op33(unsigned int op, unsigned int imm)
306{
307 unsigned int tmpv;
308 tmpv = ssp->RAM[op & 0x1ff]; OP_CMPA(tmpv);
309}
310
311static void op43(unsigned int op, unsigned int imm)
312{
313 unsigned int tmpv;
314 tmpv = ssp->RAM[op & 0x1ff]; OP_ADDA(tmpv);
315}
316
317static void op53(unsigned int op, unsigned int imm)
318{
319 unsigned int tmpv;
320 tmpv = ssp->RAM[op & 0x1ff]; OP_ANDA(tmpv);
321}
322
323static void op63(unsigned int op, unsigned int imm)
324{
325 unsigned int tmpv;
326 tmpv = ssp->RAM[op & 0x1ff]; OP_ORA (tmpv);
327}
328
329static void op73(unsigned int op, unsigned int imm)
330{
331 unsigned int tmpv;
332 tmpv = ssp->RAM[op & 0x1ff]; OP_EORA(tmpv);
333}
334
335// OP a, imm
336static void op14(unsigned int op, unsigned int imm)
337{
338 OP_SUBA(imm);
339}
340
341static void op34(unsigned int op, unsigned int imm)
342{
343 OP_CMPA(imm);
344}
345
346static void op44(unsigned int op, unsigned int imm)
347{
348 OP_ADDA(imm);
349}
350
351static void op54(unsigned int op, unsigned int imm)
352{
353 OP_ANDA(imm);
354}
355
356static void op64(unsigned int op, unsigned int imm)
357{
358 OP_ORA (imm);
359}
360
361static void op74(unsigned int op, unsigned int imm)
362{
363 OP_EORA(imm);
364}
365
366// OP a, ((ri))
367static void op15(unsigned int op, unsigned int imm)
368{
369 unsigned int tmpv;
370 tmpv = ptr2_read(op); OP_SUBA(tmpv);
371}
372
373static void op35(unsigned int op, unsigned int imm)
374{
375 unsigned int tmpv;
376 tmpv = ptr2_read(op); OP_CMPA(tmpv);
377}
378
379static void op45(unsigned int op, unsigned int imm)
380{
381 unsigned int tmpv;
382 tmpv = ptr2_read(op); OP_ADDA(tmpv);
383}
384
385static void op55(unsigned int op, unsigned int imm)
386{
387 unsigned int tmpv;
388 tmpv = ptr2_read(op); OP_ANDA(tmpv);
389}
390
391static void op65(unsigned int op, unsigned int imm)
392{
393 unsigned int tmpv;
394 tmpv = ptr2_read(op); OP_ORA (tmpv);
395}
396
397static void op75(unsigned int op, unsigned int imm)
398{
399 unsigned int tmpv;
400 tmpv = ptr2_read(op); OP_EORA(tmpv);
401}
402
403// OP a, ri
404static void op19(unsigned int op, unsigned int imm)
405{
406 unsigned int tmpv;
407 tmpv = rIJ[IJind]; OP_SUBA(tmpv);
408}
409
410static void op39(unsigned int op, unsigned int imm)
411{
412 unsigned int tmpv;
413 tmpv = rIJ[IJind]; OP_CMPA(tmpv);
414}
415
416static void op49(unsigned int op, unsigned int imm)
417{
418 unsigned int tmpv;
419 tmpv = rIJ[IJind]; OP_ADDA(tmpv);
420}
421
422static void op59(unsigned int op, unsigned int imm)
423{
424 unsigned int tmpv;
425 tmpv = rIJ[IJind]; OP_ANDA(tmpv);
426}
427
428static void op69(unsigned int op, unsigned int imm)
429{
430 unsigned int tmpv;
431 tmpv = rIJ[IJind]; OP_ORA (tmpv);
432}
433
434static void op79(unsigned int op, unsigned int imm)
435{
436 unsigned int tmpv;
437 tmpv = rIJ[IJind]; OP_EORA(tmpv);
438}
439
440// OP simm
441static void op1c(unsigned int op, unsigned int imm)
442{
443 OP_SUBA(op & 0xff);
444}
445
446static void op3c(unsigned int op, unsigned int imm)
447{
448 OP_CMPA(op & 0xff);
449}
450
451static void op4c(unsigned int op, unsigned int imm)
452{
453 OP_ADDA(op & 0xff);
454}
455
456static void op5c(unsigned int op, unsigned int imm)
457{
458 OP_ANDA(op & 0xff);
459}
460
461static void op6c(unsigned int op, unsigned int imm)
462{
463 OP_ORA (op & 0xff);
464}
465
466static void op7c(unsigned int op, unsigned int imm)
467{
468 OP_EORA(op & 0xff);
469}
470
471typedef void (in_func)(unsigned int op, unsigned int imm);
472
473static in_func *in_funcs[0x80] =
474{
475 op00, op01, op02, op03, op04, op05, op06, op07,
476 NULL, op09, op0a, NULL, op0c, op0c, op0c, op0c,
477 op10, op11, NULL, op13, op14, op15, NULL, NULL,
478 NULL, op19, NULL, op1b, op1c, NULL, NULL, NULL,
479 NULL, NULL, NULL, NULL, op24, op25, op26, NULL,
480 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
481 op30, op31, NULL, op33, op34, op35, NULL, NULL,
482 NULL, op39, NULL, NULL, op3c, NULL, NULL, NULL,
483 op40, op41, NULL, op43, op44, op45, NULL, NULL,
484 op48, op49, NULL, op4b, op4c, NULL, NULL, NULL,
485 op50, op51, NULL, op53, op54, op55, NULL, NULL,
486 NULL, op59, NULL, op5b, op5c, NULL, NULL, NULL,
487 op60, op61, NULL, op63, op64, op65, NULL, NULL,
488 NULL, op69, NULL, NULL, op6c, NULL, NULL, NULL,
489 op70, op71, NULL, op73, op74, op75, NULL, NULL,
490 NULL, op79, NULL, NULL, op7c, NULL, NULL, NULL,
491};
492
493// -----------------------------------------------------
494
df143b36 495static unsigned char iram_context_map[] =
496{
497 0, 0, 0, 0, 1, 0, 0, 0, // 04
498 0, 0, 0, 0, 0, 0, 2, 0, // 0e
499 0, 0, 0, 0, 0, 3, 0, 4, // 15 17
500 5, 0, 0, 6, 0, 7, 0, 0, // 18 1b 1d
501 8, 9, 0, 0, 0,10, 0, 0, // 20 21 25
502 0, 0, 0, 0, 0, 0, 0, 0,
503 0, 0,11, 0, 0,12, 0, 0, // 32 35
504 13,14, 0, 0, 0, 0, 0, 0 // 38 39
505};
506
df143b36 507static int get_iram_context(void)
508{
509 unsigned char *ir = (unsigned char *)svp->iram_rom;
510 int val1, val = ir[0x083^1] + ir[0x4FA^1] + ir[0x5F7^1] + ir[0x47B^1];
df143b36 511 val1 = iram_context_map[(val>>1)&0x3f];
512
5c129565 513 if (val1 == 0) {
df143b36 514 printf("val: %02x PC=%04x\n", (val>>1)&0x3f, rPC);
df143b36 515 //debug_dump2file(name, svp->iram_rom, 0x800);
516 exit(1);
517 }
5c129565 518// elprintf(EL_ANOMALY, "iram_context: %02i", val1);
df143b36 519 return val1;
520}
521
5d817c91 522// -----------------------------------------------------
523/*
524enum {
525 SSP_GR0, SSP_X, SSP_Y, SSP_A,
526 SSP_ST, SSP_STACK, SSP_PC, SSP_P,
527 SSP_PM0, SSP_PM1, SSP_PM2, SSP_XST,
528 SSP_PM4, SSP_gr13, SSP_PMC, SSP_AL
529};
530*/
531/* regs with known values */
532static struct
533{
534 ssp_reg_t gr[8];
535 unsigned char r[8];
bad5731d 536} known_regs;
537
538#define KRREG_X (1 << SSP_X)
539#define KRREG_Y (1 << SSP_Y)
540#define KRREG_A (1 << SSP_A) /* AH only */
541#define KRREG_ST (1 << SSP_ST)
542#define KRREG_STACK (1 << SSP_STACK)
543#define KRREG_PC (1 << SSP_PC)
544#define KRREG_P (1 << SSP_P)
545#define KRREG_PR0 (1 << 8)
546#define KRREG_PR4 (1 << 12)
547#define KRREG_AL (1 << 16)
548
549/* bitfield of known register values */
550static u32 known_regb = 0;
551
552/* known vals, which need to be flushed
553 * (only ST, P, r0-r7)
554 * ST means flags are being held in ARM PSR
555 */
556static u32 dirty_regb = 0;
5d817c91 557
558/* known values of host regs.
d274c33b 559 * -1 - unknown
560 * 000000-00ffff - 16bit value
561 * 100000-10ffff - base reg (r7) + 16bit val
562 * 0r0000 - means reg (low) eq gr[r].h
5d817c91 563 */
564static int hostreg_r[4];
565
566static void hostreg_clear(void)
567{
568 int i;
569 for (i = 0; i < 4; i++)
570 hostreg_r[i] = -1;
571}
572
bad5731d 573// TODO
5d817c91 574/*static*/ void hostreg_ah_changed(void)
575{
576 int i;
577 for (i = 0; i < 4; i++)
d274c33b 578 if (hostreg_r[i] == (SSP_A<<16)) hostreg_r[i] = -1;
5d817c91 579}
580
726bbb3e 581
5c129565 582#define PROGRAM(x) ((unsigned short *)svp->iram_rom)[x]
726bbb3e 583
d274c33b 584/* update P, if needed. Trashes r1 */
585static void tr_flush_dirty_P(void)
586{
587 // TODO: const regs
bad5731d 588 if (!(dirty_regb & KRREG_P)) return;
d274c33b 589 EOP_MOV_REG_ASR(10, 4, 16); // mov r10, r4, asr #16
590 EOP_MOV_REG_LSL( 1, 4, 16); // mov r1, r4, lsl #16
591 EOP_MOV_REG_ASR( 1, 1, 15); // mov r1, r1, asr #15
592 EOP_MUL(10, 1, 10); // mul r10, r1, r10
bad5731d 593 dirty_regb &= ~KRREG_P;
d274c33b 594}
595
5d817c91 596/* write dirty r0-r7 to host regs. Nothing is trashed */
d274c33b 597static void tr_flush_dirty_pr(void)
5d817c91 598{
599 int i, ror = 0, reg;
bad5731d 600 int dirty = dirty_regb >> 8;
5d817c91 601 /* r0-r7 */
bad5731d 602 for (i = 0; dirty && i < 8; i++, dirty >>= 1)
5d817c91 603 {
bad5731d 604 if (!(dirty&1)) continue;
5d817c91 605 switch (i&3) {
606 case 0: ror = 0; break;
607 case 1: ror = 24/2; break;
608 case 2: ror = 16/2; break;
609 }
610 reg = (i < 4) ? 8 : 9;
611 EOP_BIC_IMM(reg,reg,ror,0xff);
bad5731d 612 if (known_regs.r[i] != 0)
613 EOP_ORR_IMM(reg,reg,ror,known_regs.r[i]);
5d817c91 614 }
bad5731d 615 dirty_regb &= ~0xff00;
616}
617
618/* fush ARM PSR to r6. Trashes r0 */
619static void tr_flush_dirty_ST(void)
620{
621 if (!(dirty_regb & KRREG_ST)) return;
622 EOP_BIC_IMM(6,6,0,0x0f);
623 EOP_MRS(0);
624 EOP_ORR_REG_LSR(6,6,0,28);
625 dirty_regb &= ~KRREG_ST;
626 hostreg_r[0] = -1;
627}
628
629/* load 16bit val into host reg r0-r3. Nothing is trashed */
630static void tr_mov16(int r, int val)
631{
632 if (hostreg_r[r] != val) {
633 emit_mov_const(A_COND_AL, r, val);
634 hostreg_r[r] = val;
635 }
636}
637
638static void tr_mov16_cond(int cond, int r, int val)
639{
640 emit_mov_const(cond, r, val);
5d817c91 641}
642
bad5731d 643/* read bank word to r0. Thrashes r1. */
5d817c91 644static void tr_bank_read(int addr) /* word addr 0-0x1ff */
645{
bad5731d 646 int breg = 7;
647 if (addr > 0x7f) {
648 if (hostreg_r[1] != (0x100000|((addr&0x180)<<1))) {
649 EOP_ADD_IMM(1,7,30/2,(addr&0x180)>>1); // add r1, r7, ((op&0x180)<<1)
650 hostreg_r[1] = 0x100000|((addr&0x180)<<1);
5d817c91 651 }
bad5731d 652 breg = 1;
5d817c91 653 }
bad5731d 654 EOP_LDRH_IMM(0,breg,(addr&0x7f)<<1); // ldrh r0, [r1, (op&0x7f)<<1]
5d817c91 655 hostreg_r[0] = -1;
656}
657
658/* write r0 to bank. Trashes r1. */
659static void tr_bank_write(int addr)
660{
661 int breg = 7;
662 if (addr > 0x7f) {
d274c33b 663 if (hostreg_r[1] != (0x100000|((addr&0x180)<<1))) {
5d817c91 664 EOP_ADD_IMM(1,7,30/2,(addr&0x180)>>1); // add r1, r7, ((op&0x180)<<1)
d274c33b 665 hostreg_r[1] = 0x100000|((addr&0x180)<<1);
5d817c91 666 }
667 breg = 1;
668 }
b9c1d012 669 EOP_STRH_IMM(0,breg,(addr&0x7f)<<1); // strh r0, [r1, (op&0x7f)<<1]
5d817c91 670}
671
672/* handle RAM bank pointer modifiers. Nothing is trashed. */
673static void tr_ptrr_mod(int r, int mod, int need_modulo)
674{
675 int modulo = -1, modulo_shift = -1; /* unknown */
676
677 if (mod == 0) return;
678
679 if (!need_modulo || mod == 1) // +!
680 modulo_shift = 8;
bad5731d 681 else if (need_modulo && (known_regb & KRREG_ST)) {
682 modulo_shift = known_regs.gr[SSP_ST].h & 7;
5d817c91 683 if (modulo_shift == 0) modulo_shift = 8;
684 }
685
686 if (mod > 1 && modulo_shift == -1) { printf("need var modulo\n"); exit(1); }
687 modulo = (1 << modulo_shift) - 1;
688
bad5731d 689 if (known_regb & (1 << (r + 8))) {
5d817c91 690 if (mod == 2)
bad5731d 691 known_regs.r[r] = (known_regs.r[r] & ~modulo) | ((known_regs.r[r] - 1) & modulo);
692 else known_regs.r[r] = (known_regs.r[r] & ~modulo) | ((known_regs.r[r] + 1) & modulo);
5d817c91 693 } else {
694 int reg = (r < 4) ? 8 : 9;
695 int ror = ((r&3) + 1)*8 - (8 - modulo_shift);
696 EOP_MOV_REG_ROR(reg,reg,ror);
697 // {add|sub} reg, reg, #1<<shift
698 EOP_C_DOP_IMM(A_COND_AL,(mod==2)?A_OP_SUB:A_OP_ADD,0,reg,reg, 8/2, 1<<(8 - modulo_shift));
699 EOP_MOV_REG_ROR(reg,reg,32-ror);
700 }
701}
702
bad5731d 703/* handle writes r0 to (rX). Trashes r1.
704 * fortunately we can ignore modulo increment modes for writes. */
705static void tr_rX_write1(int op)
706{
707 if ((op&3) == 3)
708 {
709 int mod = (op>>2) & 3; // direct addressing
710 tr_bank_write((op & 0x100) + mod);
711 }
712 else
713 {
714 int r = (op&3) | ((op>>6)&4);
715 if (known_regb & (1 << (r + 8))) {
716 tr_bank_write((op&0x100) | known_regs.r[r]);
717 } else {
718 int reg = (r < 4) ? 8 : 9;
719 int ror = ((4 - (r&3))*8) & 0x1f;
720 EOP_AND_IMM(1,reg,ror/2,0xff); // and r1, r{7,8}, <mask>
721 if (r >= 4)
722 EOP_ORR_IMM(1,1,((ror-8)&0x1f)/2,1); // orr r1, r1, 1<<shift
723 if (r&3) EOP_ADD_REG_LSR(1,7,1, (r&3)*8-1); // add r1, r7, r1, lsr #lsr
724 else EOP_ADD_REG_LSL(1,7,1,1);
725 EOP_STRH_SIMPLE(0,1); // strh r0, [r1]
726 hostreg_r[1] = -1;
727 }
728 tr_ptrr_mod(r, (op>>2) & 3, 0);
729 }
730}
731
732/* get ARM cond which would mean that SSP cond is satisfied. No trash. */
733static int tr_cond_check(int op)
734{
735 int f = op & 0x100;
736 switch (op&0xf0) {
737 case 0x00: return A_COND_AL; /* always true */
738 case 0x50: /* Z matches f(?) bit */
739 if (dirty_regb & KRREG_ST) return f ? A_COND_EQ : A_COND_NE;
740 EOP_TST_IMM(6, 0, 4);
741 return f ? A_COND_NE : A_COND_EQ;
742 case 0x70: /* N matches f(?) bit */
743 if (dirty_regb & KRREG_ST) return f ? A_COND_MI : A_COND_PL;
744 EOP_TST_IMM(6, 0, 8);
745 return f ? A_COND_NE : A_COND_EQ;
746 default:
747 printf("unimplemented cond?\n");
748 exit(1);
749 return 0;
750 }
751}
752
753static int tr_neg_cond(int cond)
754{
755 switch (cond) {
756 case A_COND_AL: printf("neg for AL?\n"); exit(1);
757 case A_COND_EQ: return A_COND_NE;
758 case A_COND_NE: return A_COND_EQ;
759 case A_COND_MI: return A_COND_PL;
760 case A_COND_PL: return A_COND_MI;
761 default: printf("bad cond for neg\n"); exit(1);
762 }
763 return 0;
764}
765
b9c1d012 766// SSP_GR0, SSP_X, SSP_Y, SSP_A,
767// SSP_ST, SSP_STACK, SSP_PC, SSP_P,
768//@ r4: XXYY
769//@ r5: A
770//@ r6: STACK and emu flags
771//@ r7: SSP context
772//@ r10: P
773
bad5731d 774// read general reg to r0. Trashes r1
d274c33b 775static void tr_GR0_to_r0(void)
776{
777 tr_mov16(0, 0xffff);
778}
779
780static void tr_X_to_r0(void)
781{
782 if (hostreg_r[0] != (SSP_X<<16)) {
783 EOP_MOV_REG_LSR(0, 4, 16); // mov r0, r4, lsr #16
784 hostreg_r[0] = SSP_X<<16;
785 }
786}
787
788static void tr_Y_to_r0(void)
789{
790 // TODO..
791 if (hostreg_r[0] != (SSP_Y<<16)) {
792 EOP_MOV_REG_SIMPLE(0, 4); // mov r0, r4
793 hostreg_r[0] = SSP_Y<<16;
794 }
795}
796
797static void tr_A_to_r0(void)
798{
799 if (hostreg_r[0] != (SSP_A<<16)) {
800 EOP_MOV_REG_LSR(0, 5, 16); // mov r0, r5, lsr #16 @ AH
801 hostreg_r[0] = SSP_A<<16;
802 }
803}
804
805static void tr_ST_to_r0(void)
806{
807 // VR doesn't need much accuracy here..
808 EOP_MOV_REG_LSR(0, 6, 4); // mov r0, r6, lsr #4
809 EOP_AND_IMM(0, 0, 0, 0x67); // and r0, r0, #0x67
810 hostreg_r[0] = -1;
811}
812
813static void tr_STACK_to_r0(void)
814{
815 // 448
816 EOP_SUB_IMM(6, 6, 8/2, 0x20); // sub r6, r6, #1<<29
817 EOP_ADD_IMM(1, 7, 24/2, 0x04); // add r1, r7, 0x400
818 EOP_ADD_IMM(1, 1, 0, 0x48); // add r1, r1, 0x048
819 EOP_ADD_REG_LSR(1, 1, 6, 28); // add r1, r1, r6, lsr #28
820 EOP_LDRH_SIMPLE(0, 1); // ldrh r0, [r1]
821 hostreg_r[0] = hostreg_r[1] = -1;
822}
823
824static void tr_PC_to_r0(void)
825{
bad5731d 826 tr_mov16(0, known_regs.gr[SSP_PC].h);
d274c33b 827}
828
829static void tr_P_to_r0(void)
830{
831 tr_flush_dirty_P();
832 EOP_MOV_REG_LSR(0, 10, 16); // mov r0, r10, lsr #16
833 hostreg_r[0] = -1;
834}
835
836typedef void (tr_read_func)(void);
837
838static tr_read_func *tr_read_funcs[8] =
839{
840 tr_GR0_to_r0,
841 tr_X_to_r0,
842 tr_Y_to_r0,
843 tr_A_to_r0,
844 tr_ST_to_r0,
845 tr_STACK_to_r0,
846 tr_PC_to_r0,
847 tr_P_to_r0
848};
849
850
b9c1d012 851// write r0 to general reg handlers. Trashes r1
d274c33b 852static void tr_unhandled(void)
b9c1d012 853{
bad5731d 854 printf("unhandled @ %04x\n", known_regs.gr[SSP_PC].h<<1);
b9c1d012 855 exit(1);
856}
857
858static void tr_r0_to_GR0(void)
859{
860 // do nothing
861}
862
863static void tr_r0_to_X(void)
864{
865 EOP_MOV_REG_LSL(4, 4, 16); // mov r4, r4, lsl #16
866 EOP_MOV_REG_LSR(4, 4, 16); // mov r4, r4, lsr #16
867 EOP_ORR_REG_LSL(4, 4, 0, 16); // orr r4, r4, r0, lsl #16
bad5731d 868 dirty_regb |= KRREG_P; // touching X or Y makes P dirty.
869 hostreg_r[0] = SSP_X<<16;
b9c1d012 870}
871
872static void tr_r0_to_Y(void)
873{
874 EOP_MOV_REG_LSR(4, 4, 16); // mov r4, r4, lsr #16
875 EOP_ORR_REG_LSL(4, 4, 0, 16); // orr r4, r4, r0, lsl #16
876 EOP_MOV_REG_ROR(4, 4, 16); // mov r4, r4, ror #16
bad5731d 877 dirty_regb |= KRREG_P;
878 hostreg_r[0] = SSP_Y<<16;
b9c1d012 879}
880
881static void tr_r0_to_A(void)
882{
883 EOP_MOV_REG_LSL(5, 5, 16); // mov r5, r5, lsl #16
d274c33b 884 EOP_MOV_REG_LSR(5, 5, 16); // mov r5, r5, lsr #16 @ AL
b9c1d012 885 EOP_ORR_REG_LSL(5, 5, 0, 16); // orr r5, r5, r0, lsl #16
bad5731d 886 hostreg_r[0] = SSP_A<<16;
b9c1d012 887}
888
889static void tr_r0_to_ST(void)
890{
891 // VR doesn't need much accuracy here..
892 EOP_AND_IMM(1, 0, 0, 0x67); // and r1, r0, #0x67
893 EOP_AND_IMM(6, 6, 8/2, 0xe0); // and r6, r6, #7<<29 @ preserve STACK
894 EOP_ORR_REG_LSL(6, 6, 1, 4); // orr r6, r6, r1, lsl #4
895 hostreg_r[1] = -1;
896}
897
898static void tr_r0_to_STACK(void)
899{
900 // 448
901 EOP_ADD_IMM(1, 7, 24/2, 0x04); // add r1, r7, 0x400
902 EOP_ADD_IMM(1, 1, 0, 0x48); // add r1, r1, 0x048
d274c33b 903 EOP_ADD_REG_LSR(1, 1, 6, 28); // add r1, r1, r6, lsr #28
b9c1d012 904 EOP_STRH_SIMPLE(0, 1); // strh r0, [r1]
d274c33b 905 EOP_ADD_IMM(6, 6, 8/2, 0x20); // add r6, r6, #1<<29
b9c1d012 906 hostreg_r[1] = -1;
907}
908
909static void tr_r0_to_PC(void)
910{
911 EOP_MOV_REG_LSL(1, 0, 16); // mov r1, r0, lsl #16
d274c33b 912 EOP_STR_IMM(1,7,0x400+6*4); // str r1, [r7, #(0x400+6*8)]
b9c1d012 913 hostreg_r[1] = -1;
914}
915
916typedef void (tr_write_func)(void);
917
918static tr_write_func *tr_write_funcs[8] =
919{
920 tr_r0_to_GR0,
921 tr_r0_to_X,
922 tr_r0_to_Y,
923 tr_r0_to_A,
924 tr_r0_to_ST,
925 tr_r0_to_STACK,
926 tr_r0_to_PC,
d274c33b 927 tr_unhandled
b9c1d012 928};
929
5d817c91 930
931static int translate_op(unsigned int op, int *pc, int imm)
932{
d274c33b 933 u32 tmpv, tmpv2;
5d817c91 934 int ret = 0;
bad5731d 935 known_regs.gr[SSP_PC].h = *pc;
5d817c91 936
e807ac75 937 switch (op >> 9)
938 {
939 // ld d, s
f48f5e3b 940 case 0x00:
5d817c91 941 if (op == 0) { ret++; break; } // nop
d274c33b 942 tmpv = op & 0xf; // src
943 tmpv2 = (op >> 4) & 0xf; // dst
944 if (tmpv >= 8 || tmpv2 >= 8) return -1; // TODO
945 if (tmpv2 == SSP_A && tmpv == SSP_P) { // ld A, P
946 tr_flush_dirty_P();
947 EOP_MOV_REG_SIMPLE(5, 10);
bad5731d 948 known_regb &= ~(KRREG_A|KRREG_AL);
d274c33b 949 ret++; break;
950 }
951 tr_read_funcs[tmpv]();
952 tr_write_funcs[tmpv2]();
bad5731d 953 if (known_regb & (1 << tmpv)) {
954 known_regs.gr[tmpv2].h = known_regs.gr[tmpv].h;
955 known_regb |= 1 << tmpv2;
d274c33b 956 } else
bad5731d 957 known_regb &= ~(1 << tmpv2);
958 ret++; break;
959
960 // ld d, (ri)
961 //case 0x01: tmpv = ptr1_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv); break;
962
963 // ld (ri), s
964 case 0x02:
965 tmpv = (op >> 4) & 0xf; // src
966 if (tmpv >= 8) return -1; // TODO
967 tr_read_funcs[tmpv]();
968 tr_rX_write1(op);
d274c33b 969 ret++; break;
f48f5e3b 970
971 // ld a, adr
972 case 0x03:
5d817c91 973 tr_bank_read(op&0x1ff);
b9c1d012 974 tr_r0_to_A();
bad5731d 975 known_regb &= ~KRREG_A;
d274c33b 976 hostreg_r[0] = SSP_A<<16;
5d817c91 977 ret++; break;
978
b9c1d012 979 // ldi d, imm
980 case 0x04:
981 tmpv = (op & 0xf0) >> 4;
982 if (tmpv < 8)
983 {
984 tr_mov16(0, imm);
985 tr_write_funcs[tmpv]();
bad5731d 986 known_regs.gr[tmpv].h = imm;
987 known_regb |= 1 << tmpv;
b9c1d012 988 ret++; break;
989 }
990 else if (tmpv == 0xe && (PROGRAM(*pc) >> 9) == 4)
991 {
992 // programming PMC..
993 (*pc)++;
994 tmpv = imm | (PROGRAM((*pc)++) << 16);
bad5731d 995 emit_mov_const(A_COND_AL, 0, tmpv);
b9c1d012 996 EOP_LDR_IMM(1,7,0x484); // ldr r0, [r7, #0x484] // emu_status
997 EOP_STR_IMM(0,7,0x400+14*4); // PMC
d274c33b 998 // reads on fe06, fe08; next op is ld -,
999 if ((tmpv == 0x187f03 || tmpv == 0x187f04) && (PROGRAM(*pc) & 0xfff0) == 0)
1000 {
bad5731d 1001 int flag = (tmpv == 0x187f03) ? SSP_WAIT_30FE06 : SSP_WAIT_30FE08;
1002 tr_flush_dirty_ST();
b9c1d012 1003 EOP_LDR_IMM(0,7,0x490); // dram_ptr
1004 EOP_ADD_IMM(0,0,24/2,0xfe); // add r0, r0, #0xfe00
1005 EOP_LDRH_IMM(0,0,8); // ldrh r0, [r0, #8]
1006 EOP_TST_REG_SIMPLE(0,0);
d274c33b 1007 EOP_C_DOP_IMM(A_COND_EQ,A_OP_ADD,0,11,11,22/2,1); // add r11, r11, #1024
1008 EOP_C_DOP_IMM(A_COND_EQ,A_OP_ORR,0, 1, 1,24/2,flag>>8); // orr r1, r1, #SSP_WAIT_30FE08
b9c1d012 1009 }
1010 EOP_ORR_IMM(1,1,0,SSP_PMC_SET); // orr r1, r1, #SSP_PMC_SET
1011 EOP_STR_IMM(1,7,0x484); // str r1, [r7, #0x484] // emu_status
1012 hostreg_r[0] = hostreg_r[1] = -1;
1013 ret += 2; break;
1014 }
1015 else
1016 return -1; /* TODO.. */
1017
bad5731d 1018 // ld d, ((ri))
1019 case 0x05: {
1020 int r;
1021 r = (op&3) | ((op>>6)&4); // src
1022 tmpv2 = (op >> 4) & 0xf; // dst
1023 if (tmpv2 >= 8) return -1; // TODO
1024
1025 if ((r&3) == 3) {
1026 tr_bank_read((op&0x100) | ((op>>2)&3));
1027 } else if (known_regb & (1 << (r+8))) {
1028 tr_bank_read((op&0x100) | known_regs.r[r]);
1029 } else {
1030 int reg = (r < 4) ? 8 : 9;
1031 int ror = ((4 - (r&3))*8) & 0x1f;
1032 EOP_AND_IMM(1,reg,ror/2,0xff); // and r1, r{7,8}, <mask>
1033 if (r >= 4)
1034 EOP_ORR_IMM(1,1,((ror-8)&0x1f)/2,1); // orr r1, r1, 1<<shift
1035 if (r&3) EOP_ADD_REG_LSR(1,7,1, (r&3)*8-1); // add r1, r7, r1, lsr #lsr
1036 else EOP_ADD_REG_LSL(1,7,1,1);
1037 EOP_LDRH_SIMPLE(0,1); // ldrh r0, [r1]
1038 }
1039 EOP_LDR_IMM(2,7,0x48c); // ptr_iram_rom
1040 EOP_ADD_REG_LSL(2,2,0,1); // add r2, r2, r0, lsl #1
1041 EOP_ADD_IMM(0,0,0,1); // add r0, r0, #1
1042 if ((r&3) == 3) {
1043 tr_bank_write((op&0x100) | ((op>>2)&3));
1044 } else if (known_regb & (1 << (r+8))) {
1045 tr_bank_write((op&0x100) | known_regs.r[r]);
1046 } else {
1047 EOP_STRH_SIMPLE(0,1); // strh r0, [r1]
1048 hostreg_r[1] = -1;
1049 }
1050 EOP_LDRH_SIMPLE(0,2); // ldrh r0, [r0]
1051 hostreg_r[0] = hostreg_r[2] = -1;
1052 tr_write_funcs[tmpv2]();
1053 ret += 2; break; /* should certainly take > 1 */
1054 }
b9c1d012 1055
5d817c91 1056 // ldi (ri), imm
1057 case 0x06:
5d817c91 1058 tr_mov16(0, imm);
bad5731d 1059 tr_rX_write1(op);
5d817c91 1060 ret++; break;
f48f5e3b 1061
1062 // ld adr, a
1063 case 0x07:
d274c33b 1064 if (hostreg_r[0] != (SSP_A<<16)) {
5d817c91 1065 EOP_MOV_REG_LSR(0, 5, 16); // mov r0, r5, lsr #16 @ A
d274c33b 1066 hostreg_r[0] = SSP_A<<16;
5d817c91 1067 }
1068 tr_bank_write(op&0x1ff);
1069 ret++; break;
1070
d274c33b 1071 // ld d, ri
1072 case 0x09: {
bad5731d 1073 int r;
d274c33b 1074 r = (op&3) | ((op>>6)&4); // src
bad5731d 1075 tmpv2 = (op >> 4) & 0xf; // dst
d274c33b 1076 if (tmpv2 >= 8) tr_unhandled();
bad5731d 1077 if ((r&3) == 3) tr_unhandled();
d274c33b 1078
bad5731d 1079 if (known_regb & (1 << (r+8))) {
1080 tr_mov16(0, known_regs.r[r]);
1081 known_regs.gr[tmpv2].h = known_regs.r[r];
1082 known_regb |= 1 << tmpv2;
d274c33b 1083 } else {
bad5731d 1084 int reg = (r < 4) ? 8 : 9;
d274c33b 1085 if (r&3) EOP_MOV_REG_LSR(0, reg, (r&3)*8); // mov r0, r{7,8}, lsr #lsr
1086 EOP_AND_IMM(0, (r&3)?0:reg, 0, 0xff); // and r0, r{7,8}, <mask>
1087 hostreg_r[0] = -1;
bad5731d 1088 known_regb &= ~(1 << tmpv2);
d274c33b 1089 }
1090 tr_write_funcs[tmpv2]();
1091 ret++; break;
1092 }
1093
bad5731d 1094 // ld ri, s
1095 case 0x0a: {
1096 int r;
1097 r = (op&3) | ((op>>6)&4); // dst
1098 tmpv = (op >> 4) & 0xf; // src
1099 if (tmpv >= 8) tr_unhandled();
1100 if ((r&3) == 3) tr_unhandled();
1101
1102 if (known_regb & (1 << tmpv)) {
1103 known_regs.r[r] = known_regs.gr[tmpv].h;
1104 known_regb |= 1 << (r + 8);
1105 dirty_regb |= 1 << (r + 8);
1106 } else {
1107 int reg = (r < 4) ? 8 : 9;
1108 int ror = ((4 - (r&3))*8) & 0x1f;
1109 tr_read_funcs[tmpv]();
1110 EOP_BIC_IMM(reg, reg, ror/2, 0xff); // bic r{7,8}, r{7,8}, <mask>
1111 EOP_AND_IMM(0, 0, 0, 0xff); // and r0, r0, 0xff
1112 EOP_ORR_REG_LSL(reg, reg, 0, (r&3)*8); // orr r{7,8}, r{7,8}, r0, lsl #lsl
1113 hostreg_r[0] = -1;
1114 known_regb &= ~(1 << (r+8));
1115 dirty_regb &= ~(1 << (r+8));
1116 }
1117 ret++; break;
1118 }
1119
5d817c91 1120 // ldi ri, simm
1121 case 0x0c ... 0x0f:
1122 tmpv = (op>>8)&7;
bad5731d 1123 known_regs.r[tmpv] = op;
1124 known_regb |= 1 << (tmpv + 8);
5d817c91 1125 dirty_regb |= 1 << (tmpv + 8);
1126 ret++; break;
bad5731d 1127
1128 // ld d, (a)
1129 case 0x25:
1130 // tmpv = ((unsigned short *)svp->iram_rom)[rA]; REG_WRITE((op & 0xf0) >> 4, tmpv); break;
1131 tmpv2 = (op >> 4) & 0xf; // dst
1132 if (tmpv2 >= 8) return -1; // TODO
1133
1134 tr_read_funcs[SSP_A]();
1135 EOP_LDR_IMM(1,7,0x48c); // ptr_iram_rom
1136 EOP_ADD_REG_LSL(0,1,0,1); // add r0, r1, r0, lsl #1
1137 EOP_LDRH_SIMPLE(0,0); // ldrh r0, [r0]
1138 hostreg_r[0] = hostreg_r[1] = -1;
1139 tr_write_funcs[tmpv2]();
1140 ret += 2; break; /* should certainly take > 1 */
1141
1142 // bra cond, addr
1143 case 0x26: {
1144 tmpv = tr_cond_check(op);
1145 tr_mov16_cond(tmpv, 0, imm);
1146 if (tmpv != A_COND_AL) {
1147 EOP_C_DOP_IMM(tmpv, A_OP_ADD, 0, 11, 11, 0, 1); // add 1 to cycles if we jump
1148 tr_mov16_cond(tr_neg_cond(tmpv), 0, *pc);
1149 }
1150 else
1151 ret++; // always jump */
1152 tr_write_funcs[SSP_PC]();
1153 ret++; break;
1154 }
1155
1156
1157/*
1158 // mpys?
1159 case 0x1b:
1160 read_P(); // update P
1161 rA32 -= rP.v; // maybe only upper word?
1162 UPD_ACC_ZN // there checking flags after this
1163 rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
1164 rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
1165 break;
1166
1167 // mpya (rj), (ri), b
1168 case 0x4b:
1169 read_P(); // update P
1170 rA32 += rP.v; // confirmed to be 32bit
1171 UPD_ACC_ZN // ?
1172 rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
1173 rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
1174 break;
1175
1176 // mld (rj), (ri), b
1177 case 0x5b:
1178 EOP_MOV_IMM(5, 0, 0); // mov r5, #0
1179 known_regs.r[SSP_A].v = 0;
1180 known_regb |= (KRREG_A|KRREG_AL);
1181 EOP_BIC_IMM(6, 6, 0, 0x0f); // bic r6, r6, 0xf // flags
1182 // TODO
1183 ret++; break;
1184*/
e807ac75 1185 }
1186
5d817c91 1187 return ret;
e807ac75 1188}
1189
df143b36 1190static void *translate_block(int pc)
726bbb3e 1191{
e807ac75 1192 unsigned int op, op1, imm, ccount = 0;
5c129565 1193 unsigned int *block_start;
d274c33b 1194 int ret, ret_prev = -1;
5c129565 1195
1196 // create .pool
e807ac75 1197 //*tcache_ptr++ = (u32) in_funcs; // -1 func pool
726bbb3e 1198
259ed0ea 1199 printf("translate %04x -> %04x\n", pc<<1, (tcache_ptr-tcache)<<2);
5c129565 1200 block_start = tcache_ptr;
bad5731d 1201 known_regb = 0;
1202 dirty_regb = KRREG_P;
5d817c91 1203 hostreg_clear();
5c129565 1204
1205 emit_block_prologue();
726bbb3e 1206
e807ac75 1207 for (; ccount < 100;)
726bbb3e 1208 {
259ed0ea 1209 //printf(" insn #%i\n", icount);
726bbb3e 1210 op = PROGRAM(pc++);
1211 op1 = op >> 9;
e807ac75 1212 imm = (u32)-1;
5c129565 1213
e807ac75 1214 if ((op1 & 0xf) == 4 || (op1 & 0xf) == 6)
1215 imm = PROGRAM(pc++); // immediate
5c129565 1216
5d817c91 1217 ret = translate_op(op, &pc, imm);
e807ac75 1218 if (ret <= 0)
1219 {
d274c33b 1220 tr_flush_dirty_pr();
5d817c91 1221
bad5731d 1222 emit_mov_const(A_COND_AL, 0, op);
5c129565 1223
e807ac75 1224 // need immediate?
1225 if (imm != (u32)-1)
bad5731d 1226 emit_mov_const(A_COND_AL, 1, imm);
5c129565 1227
e807ac75 1228 // dump PC
1229 emit_pc_dump(pc);
5c129565 1230
d274c33b 1231 if (ret_prev > 0) emit_call(regfile_store);
1232 emit_call(in_funcs[op1]);
1233 emit_call(regfile_load);
e807ac75 1234
1235 if (in_funcs[op1] == NULL) {
1236 printf("NULL func! op=%08x (%02x)\n", op, op1);
1237 exit(1);
1238 }
1239 ccount++;
5d817c91 1240 hostreg_clear();
bad5731d 1241 dirty_regb |= KRREG_P;
1242 known_regb = 0;
892b1dd2 1243 }
e807ac75 1244 else
1245 ccount += ret;
1246
726bbb3e 1247 if (op1 == 0x24 || op1 == 0x26 || // call, bra
1248 ((op1 == 0 || op1 == 1 || op1 == 4 || op1 == 5 || op1 == 9 || op1 == 0x25) &&
1249 (op & 0xf0) == 0x60)) { // ld PC
1250 break;
1251 }
d274c33b 1252 ret_prev = ret;
726bbb3e 1253 }
5c129565 1254
d274c33b 1255 tr_flush_dirty_pr();
e807ac75 1256 emit_block_epilogue(ccount + 1);
5c129565 1257 *tcache_ptr++ = 0xffffffff; // end of block
726bbb3e 1258 //printf(" %i inst\n", icount);
1259
892b1dd2 1260 if (tcache_ptr - tcache > TCACHE_SIZE/4) {
726bbb3e 1261 printf("tcache overflow!\n");
1262 fflush(stdout);
1263 exit(1);
1264 }
1265
1266 // stats
1267 nblocks++;
df143b36 1268 //if (pc >= 0x400)
892b1dd2 1269 printf("%i blocks, %i bytes\n", nblocks, (tcache_ptr - tcache)*4);
259ed0ea 1270 //printf("%p %p\n", tcache_ptr, emit_block_epilogue);
df143b36 1271
5d817c91 1272#ifdef DUMP_BLOCK
5c129565 1273 {
1274 FILE *f = fopen("tcache.bin", "wb");
1275 fwrite(tcache, 1, (tcache_ptr - tcache)*4, f);
1276 fclose(f);
1277 }
1278 exit(0);
1279#endif
259ed0ea 1280
1281 handle_caches();
1282
5c129565 1283 return block_start;
726bbb3e 1284}
1285
1286
1287
1288// -----------------------------------------------------
1289
e807ac75 1290int ssp1601_dyn_startup(void)
726bbb3e 1291{
e807ac75 1292 memset(tcache, 0, TCACHE_SIZE);
726bbb3e 1293 memset(block_table, 0, sizeof(block_table));
df143b36 1294 memset(block_table_iram, 0, sizeof(block_table_iram));
e807ac75 1295 tcache_ptr = tcache;
5c129565 1296 *tcache_ptr++ = 0xffffffff;
726bbb3e 1297
1298 return 0;
1299}
1300
1301
1302void ssp1601_dyn_reset(ssp1601_t *ssp)
1303{
1304 ssp1601_reset_local(ssp);
bad5731d 1305 ssp->ptr_rom = (unsigned int) Pico.rom;
1306 ssp->ptr_iram_rom = (unsigned int) svp->iram_rom;
d274c33b 1307 ssp->ptr_dram = (unsigned int) svp->dram;
726bbb3e 1308}
1309
726bbb3e 1310void ssp1601_dyn_run(int cycles)
1311{
b9c1d012 1312 if (ssp->emu_status & SSP_WAIT_MASK) return;
1313 //{ printf("%i wait\n", Pico.m.frame_count); return; }
1314 //printf("%i %04x\n", Pico.m.frame_count, rPC<<1);
1315
5d817c91 1316#ifdef DUMP_BLOCK
1317 rPC = DUMP_BLOCK >> 1;
1318#endif
726bbb3e 1319 while (cycles > 0)
1320 {
e807ac75 1321 int (*trans_entry)(void);
df143b36 1322 if (rPC < 0x800/2)
1323 {
1324 if (iram_dirty) {
1325 iram_context = get_iram_context();
892b1dd2 1326 iram_dirty--;
df143b36 1327 }
1328 if (block_table_iram[iram_context][rPC] == NULL)
1329 block_table_iram[iram_context][rPC] = translate_block(rPC);
5c129565 1330 trans_entry = (void *) block_table_iram[iram_context][rPC];
df143b36 1331 }
1332 else
1333 {
1334 if (block_table[rPC] == NULL)
1335 block_table[rPC] = translate_block(rPC);
5c129565 1336 trans_entry = (void *) block_table[rPC];
df143b36 1337 }
726bbb3e 1338
e807ac75 1339 //printf("enter %04x\n", rPC<<1);
1340 cycles -= trans_entry();
1341 //printf("leave %04x\n", rPC<<1);
726bbb3e 1342 }
1343// debug_dump2file("tcache.bin", tcache, (tcache_ptr - tcache) << 1);
1344// exit(1);
1345}
1346