1 // 187 blocks, 12072 bytes
4 #include "../../PicoInt.h"
7 static unsigned int *block_table[0x5090/2];
8 static unsigned int *block_table_iram[15][0x800/2];
9 static unsigned int *tcache_ptr = NULL;
11 static int nblocks = 0;
12 static int iram_context = 0;
15 #define DUMP_BLOCK 0x08aa
16 unsigned int tcache[512*1024];
17 void regfile_load(void){}
18 void regfile_store(void){}
21 #define EMBED_INTERPRETER
22 #define ssp1601_reset ssp1601_reset_local
23 #define ssp1601_run ssp1601_run_local
26 #define GET_PPC_OFFS() (GET_PC()*2 - 2)
27 #define SET_PC(d) { rPC = d; } /* must return to dispatcher after this */
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
35 // -----------------------------------------------------
38 static void op00(unsigned int op, unsigned int imm)
41 PC = ((unsigned short *)(void *)&op) + 1; /* FIXME: needed for interpreter */
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.
50 tmpv = REG_READ(op & 0x0f);
51 REG_WRITE((op & 0xf0) >> 4, tmpv);
56 static void op01(unsigned int op, unsigned int imm)
59 tmpv = ptr1_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv);
63 static void op02(unsigned int op, unsigned int imm)
66 tmpv = REG_READ((op & 0xf0) >> 4); ptr1_write(op, tmpv);
70 static void op04(unsigned int op, unsigned int imm)
72 REG_WRITE((op & 0xf0) >> 4, imm);
76 static void op05(unsigned int op, unsigned int imm)
79 tmpv = ptr2_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv);
83 static void op06(unsigned int op, unsigned int imm)
89 static void op07(unsigned int op, unsigned int imm)
91 ssp->RAM[op & 0x1ff] = rA;
95 static void op09(unsigned int op, unsigned int imm)
98 tmpv = rIJ[(op&3)|((op>>6)&4)]; REG_WRITE((op & 0xf0) >> 4, tmpv);
102 static void op0a(unsigned int op, unsigned int imm)
104 rIJ[(op&3)|((op>>6)&4)] = REG_READ((op & 0xf0) >> 4);
107 // ldi ri, simm (also op0d op0e op0f)
108 static void op0c(unsigned int op, unsigned int imm)
114 static void op24(unsigned int op, unsigned int imm)
119 if (cond) { int new_PC = imm; write_STACK(GET_PC()); SET_PC(new_PC); }
125 static void op25(unsigned int op, unsigned int imm)
128 tmpv = ((unsigned short *)svp->iram_rom)[rA]; REG_WRITE((op & 0xf0) >> 4, tmpv);
132 static void op26(unsigned int op, unsigned int imm)
138 if (cond) SET_PC(imm);
144 static void op48(unsigned int op, unsigned int imm)
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());
166 static void op1b(unsigned int op, unsigned int imm)
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
175 // mpya (rj), (ri), b
176 static void op4b(unsigned int op, unsigned int imm)
178 read_P(); // update P
179 rA32 += rP.v; // confirmed to be 32bit
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
186 static void op5b(unsigned int op, unsigned int imm)
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
195 static void op10(unsigned int op, unsigned int imm)
200 OP_CHECK32(OP_SUBA32); tmpv = REG_READ(op & 0x0f); OP_SUBA(tmpv);
205 static void op30(unsigned int op, unsigned int imm)
210 OP_CHECK32(OP_CMPA32); tmpv = REG_READ(op & 0x0f); OP_CMPA(tmpv);
215 static void op40(unsigned int op, unsigned int imm)
220 OP_CHECK32(OP_ADDA32); tmpv = REG_READ(op & 0x0f); OP_ADDA(tmpv);
225 static void op50(unsigned int op, unsigned int imm)
230 OP_CHECK32(OP_ANDA32); tmpv = REG_READ(op & 0x0f); OP_ANDA(tmpv);
235 static void op60(unsigned int op, unsigned int imm)
240 OP_CHECK32(OP_ORA32 ); tmpv = REG_READ(op & 0x0f); OP_ORA (tmpv);
245 static void op70(unsigned int op, unsigned int imm)
250 OP_CHECK32(OP_EORA32); tmpv = REG_READ(op & 0x0f); OP_EORA(tmpv);
256 static void op11(unsigned int op, unsigned int imm)
259 tmpv = ptr1_read(op); OP_SUBA(tmpv);
262 static void op31(unsigned int op, unsigned int imm)
265 tmpv = ptr1_read(op); OP_CMPA(tmpv);
268 static void op41(unsigned int op, unsigned int imm)
271 tmpv = ptr1_read(op); OP_ADDA(tmpv);
274 static void op51(unsigned int op, unsigned int imm)
277 tmpv = ptr1_read(op); OP_ANDA(tmpv);
280 static void op61(unsigned int op, unsigned int imm)
283 tmpv = ptr1_read(op); OP_ORA (tmpv);
286 static void op71(unsigned int op, unsigned int imm)
289 tmpv = ptr1_read(op); OP_EORA(tmpv);
293 static void op03(unsigned int op, unsigned int imm)
296 tmpv = ssp->RAM[op & 0x1ff]; OP_LDA (tmpv);
299 static void op13(unsigned int op, unsigned int imm)
302 tmpv = ssp->RAM[op & 0x1ff]; OP_SUBA(tmpv);
305 static void op33(unsigned int op, unsigned int imm)
308 tmpv = ssp->RAM[op & 0x1ff]; OP_CMPA(tmpv);
311 static void op43(unsigned int op, unsigned int imm)
314 tmpv = ssp->RAM[op & 0x1ff]; OP_ADDA(tmpv);
317 static void op53(unsigned int op, unsigned int imm)
320 tmpv = ssp->RAM[op & 0x1ff]; OP_ANDA(tmpv);
323 static void op63(unsigned int op, unsigned int imm)
326 tmpv = ssp->RAM[op & 0x1ff]; OP_ORA (tmpv);
329 static void op73(unsigned int op, unsigned int imm)
332 tmpv = ssp->RAM[op & 0x1ff]; OP_EORA(tmpv);
336 static void op14(unsigned int op, unsigned int imm)
341 static void op34(unsigned int op, unsigned int imm)
346 static void op44(unsigned int op, unsigned int imm)
351 static void op54(unsigned int op, unsigned int imm)
356 static void op64(unsigned int op, unsigned int imm)
361 static void op74(unsigned int op, unsigned int imm)
367 static void op15(unsigned int op, unsigned int imm)
370 tmpv = ptr2_read(op); OP_SUBA(tmpv);
373 static void op35(unsigned int op, unsigned int imm)
376 tmpv = ptr2_read(op); OP_CMPA(tmpv);
379 static void op45(unsigned int op, unsigned int imm)
382 tmpv = ptr2_read(op); OP_ADDA(tmpv);
385 static void op55(unsigned int op, unsigned int imm)
388 tmpv = ptr2_read(op); OP_ANDA(tmpv);
391 static void op65(unsigned int op, unsigned int imm)
394 tmpv = ptr2_read(op); OP_ORA (tmpv);
397 static void op75(unsigned int op, unsigned int imm)
400 tmpv = ptr2_read(op); OP_EORA(tmpv);
404 static void op19(unsigned int op, unsigned int imm)
407 tmpv = rIJ[IJind]; OP_SUBA(tmpv);
410 static void op39(unsigned int op, unsigned int imm)
413 tmpv = rIJ[IJind]; OP_CMPA(tmpv);
416 static void op49(unsigned int op, unsigned int imm)
419 tmpv = rIJ[IJind]; OP_ADDA(tmpv);
422 static void op59(unsigned int op, unsigned int imm)
425 tmpv = rIJ[IJind]; OP_ANDA(tmpv);
428 static void op69(unsigned int op, unsigned int imm)
431 tmpv = rIJ[IJind]; OP_ORA (tmpv);
434 static void op79(unsigned int op, unsigned int imm)
437 tmpv = rIJ[IJind]; OP_EORA(tmpv);
441 static void op1c(unsigned int op, unsigned int imm)
446 static void op3c(unsigned int op, unsigned int imm)
451 static void op4c(unsigned int op, unsigned int imm)
456 static void op5c(unsigned int op, unsigned int imm)
461 static void op6c(unsigned int op, unsigned int imm)
466 static void op7c(unsigned int op, unsigned int imm)
471 typedef void (in_func)(unsigned int op, unsigned int imm);
473 static in_func *in_funcs[0x80] =
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,
493 // -----------------------------------------------------
495 static unsigned char iram_context_map[] =
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
507 static int get_iram_context(void)
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];
511 val1 = iram_context_map[(val>>1)&0x3f];
514 printf("val: %02x PC=%04x\n", (val>>1)&0x3f, rPC);
515 //debug_dump2file(name, svp->iram_rom, 0x800);
518 // elprintf(EL_ANOMALY, "iram_context: %02i", val1);
522 // -----------------------------------------------------
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
531 /* regs with known values */
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)
549 /* bitfield of known register values */
550 static u32 known_regb = 0;
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 * P means that it needs to be recalculated
557 static u32 dirty_regb = 0;
559 /* known values of host regs.
561 * 000000-00ffff - 16bit value
562 * 100000-10ffff - base reg (r7) + 16bit val
563 * 0r0000 - means reg (low) eq gr[r].h, r != AL
565 static int hostreg_r[4];
567 static void hostreg_clear(void)
570 for (i = 0; i < 4; i++)
574 static void hostreg_sspreg_changed(int sspreg)
577 for (i = 0; i < 4; i++)
578 if (hostreg_r[i] == (sspreg<<16)) hostreg_r[i] = -1;
582 #define PROGRAM(x) ((unsigned short *)svp->iram_rom)[x]
584 static void tr_unhandled(void)
586 FILE *f = fopen("tcache.bin", "wb");
587 fwrite(tcache, 1, (tcache_ptr - tcache)*4, f);
589 printf("unhandled @ %04x\n", known_regs.gr[SSP_PC].h<<1);
593 /* update P, if needed. Trashes r0 */
594 static void tr_flush_dirty_P(void)
597 if (!(dirty_regb & KRREG_P)) return;
598 EOP_MOV_REG_ASR(10, 4, 16); // mov r10, r4, asr #16
599 EOP_MOV_REG_LSL( 0, 4, 16); // mov r0, r4, lsl #16
600 EOP_MOV_REG_ASR( 0, 0, 15); // mov r0, r0, asr #15
601 EOP_MUL(10, 0, 10); // mul r10, r0, r10
602 dirty_regb &= ~KRREG_P;
606 /* write dirty pr to host reg. Nothing is trashed */
607 static void tr_flush_dirty_pr(int r)
611 if (!(dirty_regb & (1 << (r+8)))) return;
614 case 0: ror = 0; break;
615 case 1: ror = 24/2; break;
616 case 2: ror = 16/2; break;
618 reg = (r < 4) ? 8 : 9;
619 EOP_BIC_IMM(reg,reg,ror,0xff);
620 if (known_regs.r[r] != 0)
621 EOP_ORR_IMM(reg,reg,ror,known_regs.r[r]);
622 dirty_regb &= ~(1 << (r+8));
625 /* write all dirty pr0-pr7 to host regs. Nothing is trashed */
626 static void tr_flush_dirty_prs(void)
629 int dirty = dirty_regb >> 8;
631 for (i = 0; dirty && i < 8; i++, dirty >>= 1)
633 if (!(dirty&1)) continue;
635 case 0: ror = 0; break;
636 case 1: ror = 24/2; break;
637 case 2: ror = 16/2; break;
639 reg = (i < 4) ? 8 : 9;
640 EOP_BIC_IMM(reg,reg,ror,0xff);
641 if (known_regs.r[i] != 0)
642 EOP_ORR_IMM(reg,reg,ror,known_regs.r[i]);
644 dirty_regb &= ~0xff00;
647 /* write dirty pr and "forget" it. Nothing is trashed. */
648 static void tr_release_pr(int r)
650 tr_flush_dirty_pr(r);
651 known_regb &= ~(1 << (r+8));
654 /* fush ARM PSR to r6. Trashes r1 */
655 static void tr_flush_dirty_ST(void)
657 if (!(dirty_regb & KRREG_ST)) return;
658 EOP_BIC_IMM(6,6,0,0x0f);
660 EOP_ORR_REG_LSR(6,6,1,28);
661 dirty_regb &= ~KRREG_ST;
665 /* inverse of above. Trashes r1 */
666 static void tr_make_dirty_ST(void)
668 if (dirty_regb & KRREG_ST) return;
669 if (known_regb & KRREG_ST) {
671 if (known_regs.gr[SSP_ST].h & SSP_FLAG_N) flags |= 8;
672 if (known_regs.gr[SSP_ST].h & SSP_FLAG_Z) flags |= 4;
673 EOP_MSR_IMM(4/2, flags);
675 EOP_MOV_REG_LSL(1, 6, 28);
679 dirty_regb |= KRREG_ST;
682 /* load 16bit val into host reg r0-r3. Nothing is trashed */
683 static void tr_mov16(int r, int val)
685 if (hostreg_r[r] != val) {
686 emit_mov_const(A_COND_AL, r, val);
691 static void tr_mov16_cond(int cond, int r, int val)
693 emit_mov_const(cond, r, val);
697 /* read bank word to r0 (upper bits zero). Thrashes r1. */
698 static void tr_bank_read(int addr) /* word addr 0-0x1ff */
702 if (hostreg_r[1] != (0x100000|((addr&0x180)<<1))) {
703 EOP_ADD_IMM(1,7,30/2,(addr&0x180)>>1); // add r1, r7, ((op&0x180)<<1)
704 hostreg_r[1] = 0x100000|((addr&0x180)<<1);
708 EOP_LDRH_IMM(0,breg,(addr&0x7f)<<1); // ldrh r0, [r1, (op&0x7f)<<1]
712 /* write r0 to bank. Trashes r1. */
713 static void tr_bank_write(int addr)
717 if (hostreg_r[1] != (0x100000|((addr&0x180)<<1))) {
718 EOP_ADD_IMM(1,7,30/2,(addr&0x180)>>1); // add r1, r7, ((op&0x180)<<1)
719 hostreg_r[1] = 0x100000|((addr&0x180)<<1);
723 EOP_STRH_IMM(0,breg,(addr&0x7f)<<1); // strh r0, [r1, (op&0x7f)<<1]
726 /* handle RAM bank pointer modifiers. if need_modulo, trash r1-r3, else nothing */
727 static void tr_ptrr_mod(int r, int mod, int need_modulo, int count)
729 int modulo_shift = -1; /* unknown */
731 if (mod == 0) return;
733 if (!need_modulo || mod == 1) // +!
735 else if (need_modulo && (known_regb & KRREG_ST)) {
736 modulo_shift = known_regs.gr[SSP_ST].h & 7;
737 if (modulo_shift == 0) modulo_shift = 8;
740 if (modulo_shift == -1)
742 int reg = (r < 4) ? 8 : 9;
744 if (dirty_regb & KRREG_ST) {
745 // avoid flushing ARM flags
746 EOP_AND_IMM(1, 6, 0, 0x70);
747 EOP_SUB_IMM(1, 1, 0, 0x10);
748 EOP_AND_IMM(1, 1, 0, 0x70);
749 EOP_ADD_IMM(1, 1, 0, 0x10);
751 EOP_C_DOP_IMM(A_COND_AL,A_OP_AND,1,6,1,0,0x70); // ands r1, r6, #0x70
752 EOP_C_DOP_IMM(A_COND_EQ,A_OP_MOV,0,0,1,0,0x80); // moveq r1, #0x80
754 EOP_MOV_REG_LSR(1, 1, 4); // mov r1, r1, lsr #4
755 EOP_RSB_IMM(2, 1, 0, 8); // rsb r1, r1, #8
756 EOP_MOV_IMM(3, 8/2, count); // mov r3, #0x01000000
758 EOP_ADD_IMM(1, 1, 0, (r&3)*8); // add r1, r1, #(r&3)*8
759 EOP_MOV_REG2_ROR(reg,reg,1); // mov reg, reg, ror r1
761 EOP_SUB_REG2_LSL(reg,reg,3,2); // sub reg, reg, #0x01000000 << r2
762 else EOP_ADD_REG2_LSL(reg,reg,3,2);
763 EOP_RSB_IMM(1, 1, 0, 32); // rsb r1, r1, #32
764 EOP_MOV_REG2_ROR(reg,reg,1); // mov reg, reg, ror r1
765 hostreg_r[1] = hostreg_r[2] = hostreg_r[3] = -1;
767 else if (known_regb & (1 << (r + 8)))
769 int modulo = (1 << modulo_shift) - 1;
771 known_regs.r[r] = (known_regs.r[r] & ~modulo) | ((known_regs.r[r] - count) & modulo);
772 else known_regs.r[r] = (known_regs.r[r] & ~modulo) | ((known_regs.r[r] + count) & modulo);
776 int reg = (r < 4) ? 8 : 9;
777 int ror = ((r&3) + 1)*8 - (8 - modulo_shift);
778 EOP_MOV_REG_ROR(reg,reg,ror);
779 // {add|sub} reg, reg, #1<<shift
780 EOP_C_DOP_IMM(A_COND_AL,(mod==2)?A_OP_SUB:A_OP_ADD,0,reg,reg, 8/2, count << (8 - modulo_shift));
781 EOP_MOV_REG_ROR(reg,reg,32-ror);
785 /* handle writes r0 to (rX). Trashes r1.
786 * fortunately we can ignore modulo increment modes for writes. */
787 static void tr_rX_write(int op)
791 int mod = (op>>2) & 3; // direct addressing
792 tr_bank_write((op & 0x100) + mod);
796 int r = (op&3) | ((op>>6)&4);
797 if (known_regb & (1 << (r + 8))) {
798 tr_bank_write((op&0x100) | known_regs.r[r]);
800 int reg = (r < 4) ? 8 : 9;
801 int ror = ((4 - (r&3))*8) & 0x1f;
802 EOP_AND_IMM(1,reg,ror/2,0xff); // and r1, r{7,8}, <mask>
804 EOP_ORR_IMM(1,1,((ror-8)&0x1f)/2,1); // orr r1, r1, 1<<shift
805 if (r&3) EOP_ADD_REG_LSR(1,7,1, (r&3)*8-1); // add r1, r7, r1, lsr #lsr
806 else EOP_ADD_REG_LSL(1,7,1,1);
807 EOP_STRH_SIMPLE(0,1); // strh r0, [r1]
810 tr_ptrr_mod(r, (op>>2) & 3, 0, 1);
814 /* read (rX) to r0. Trashes r1-r3. */
815 static void tr_rX_read(int r, int mod)
819 tr_bank_read(((r << 6) & 0x100) + mod); // direct addressing
823 if (known_regb & (1 << (r + 8))) {
824 tr_bank_read(((r << 6) & 0x100) | known_regs.r[r]);
826 int reg = (r < 4) ? 8 : 9;
827 int ror = ((4 - (r&3))*8) & 0x1f;
828 EOP_AND_IMM(1,reg,ror/2,0xff); // and r1, r{7,8}, <mask>
830 EOP_ORR_IMM(1,1,((ror-8)&0x1f)/2,1); // orr r1, r1, 1<<shift
831 if (r&3) EOP_ADD_REG_LSR(1,7,1, (r&3)*8-1); // add r1, r7, r1, lsr #lsr
832 else EOP_ADD_REG_LSL(1,7,1,1);
833 EOP_LDRH_SIMPLE(0,1); // ldrh r0, [r1]
834 hostreg_r[0] = hostreg_r[1] = -1;
836 tr_ptrr_mod(r, mod, 1, 1);
840 /* read ((rX)) to r0. Trashes r1,r2. */
841 static void tr_rX_read2(int op)
843 int r = (op&3) | ((op>>6)&4); // src
846 tr_bank_read((op&0x100) | ((op>>2)&3));
847 } else if (known_regb & (1 << (r+8))) {
848 tr_bank_read((op&0x100) | known_regs.r[r]);
850 int reg = (r < 4) ? 8 : 9;
851 int ror = ((4 - (r&3))*8) & 0x1f;
852 EOP_AND_IMM(1,reg,ror/2,0xff); // and r1, r{7,8}, <mask>
854 EOP_ORR_IMM(1,1,((ror-8)&0x1f)/2,1); // orr r1, r1, 1<<shift
855 if (r&3) EOP_ADD_REG_LSR(1,7,1, (r&3)*8-1); // add r1, r7, r1, lsr #lsr
856 else EOP_ADD_REG_LSL(1,7,1,1);
857 EOP_LDRH_SIMPLE(0,1); // ldrh r0, [r1]
859 EOP_LDR_IMM(2,7,0x48c); // ptr_iram_rom
860 EOP_ADD_REG_LSL(2,2,0,1); // add r2, r2, r0, lsl #1
861 EOP_ADD_IMM(0,0,0,1); // add r0, r0, #1
863 tr_bank_write((op&0x100) | ((op>>2)&3));
864 } else if (known_regb & (1 << (r+8))) {
865 tr_bank_write((op&0x100) | known_regs.r[r]);
867 EOP_STRH_SIMPLE(0,1); // strh r0, [r1]
870 EOP_LDRH_SIMPLE(0,2); // ldrh r0, [r2]
871 hostreg_r[0] = hostreg_r[2] = -1;
874 /* get ARM cond which would mean that SSP cond is satisfied. No trash. */
875 static int tr_cond_check(int op)
877 int f = (op & 0x100) >> 8;
879 case 0x00: return A_COND_AL; /* always true */
880 case 0x50: /* Z matches f(?) bit */
881 if (dirty_regb & KRREG_ST) return f ? A_COND_EQ : A_COND_NE;
882 EOP_TST_IMM(6, 0, 4);
883 return f ? A_COND_NE : A_COND_EQ;
884 case 0x70: /* N matches f(?) bit */
885 if (dirty_regb & KRREG_ST) return f ? A_COND_MI : A_COND_PL;
886 EOP_TST_IMM(6, 0, 8);
887 return f ? A_COND_NE : A_COND_EQ;
889 printf("unimplemented cond?\n");
895 static int tr_neg_cond(int cond)
898 case A_COND_AL: printf("neg for AL?\n"); exit(1);
899 case A_COND_EQ: return A_COND_NE;
900 case A_COND_NE: return A_COND_EQ;
901 case A_COND_MI: return A_COND_PL;
902 case A_COND_PL: return A_COND_MI;
903 default: printf("bad cond for neg\n"); exit(1);
908 // SSP_GR0, SSP_X, SSP_Y, SSP_A,
909 // SSP_ST, SSP_STACK, SSP_PC, SSP_P,
912 //@ r6: STACK and emu flags
916 // read general reg to r0. Trashes r1
917 static void tr_GR0_to_r0(void)
922 static void tr_X_to_r0(void)
924 if (hostreg_r[0] != (SSP_X<<16)) {
925 EOP_MOV_REG_LSR(0, 4, 16); // mov r0, r4, lsr #16
926 hostreg_r[0] = SSP_X<<16;
930 static void tr_Y_to_r0(void)
933 if (hostreg_r[0] != (SSP_Y<<16)) {
934 EOP_MOV_REG_SIMPLE(0, 4); // mov r0, r4
935 hostreg_r[0] = SSP_Y<<16;
939 static void tr_A_to_r0(void)
941 if (hostreg_r[0] != (SSP_A<<16)) {
942 EOP_MOV_REG_LSR(0, 5, 16); // mov r0, r5, lsr #16 @ AH
943 hostreg_r[0] = SSP_A<<16;
947 static void tr_ST_to_r0(void)
949 // VR doesn't need much accuracy here..
950 EOP_MOV_REG_LSR(0, 6, 4); // mov r0, r6, lsr #4
951 EOP_AND_IMM(0, 0, 0, 0x67); // and r0, r0, #0x67
955 static void tr_STACK_to_r0(void)
958 EOP_SUB_IMM(6, 6, 8/2, 0x20); // sub r6, r6, #1<<29
959 EOP_ADD_IMM(1, 7, 24/2, 0x04); // add r1, r7, 0x400
960 EOP_ADD_IMM(1, 1, 0, 0x48); // add r1, r1, 0x048
961 EOP_ADD_REG_LSR(1, 1, 6, 28); // add r1, r1, r6, lsr #28
962 EOP_LDRH_SIMPLE(0, 1); // ldrh r0, [r1]
963 hostreg_r[0] = hostreg_r[1] = -1;
966 static void tr_PC_to_r0(void)
968 tr_mov16(0, known_regs.gr[SSP_PC].h);
971 static void tr_P_to_r0(void)
974 EOP_MOV_REG_LSR(0, 10, 16); // mov r0, r10, lsr #16
978 typedef void (tr_read_func)(void);
980 static tr_read_func *tr_read_funcs[8] =
993 // write r0 to general reg handlers. Trashes r1
994 #define TR_WRITE_R0_TO_REG(reg) \
996 hostreg_sspreg_changed(reg); \
997 hostreg_r[0] = (reg)<<16; \
998 if (const_val != -1) { \
999 known_regs.gr[reg].h = const_val; \
1000 known_regb |= 1 << (reg); \
1002 known_regb &= ~(1 << (reg)); \
1006 static void tr_r0_to_GR0(int const_val)
1011 static void tr_r0_to_X(int const_val)
1013 EOP_MOV_REG_LSL(4, 4, 16); // mov r4, r4, lsl #16
1014 EOP_MOV_REG_LSR(4, 4, 16); // mov r4, r4, lsr #16
1015 EOP_ORR_REG_LSL(4, 4, 0, 16); // orr r4, r4, r0, lsl #16
1016 dirty_regb |= KRREG_P; // touching X or Y makes P dirty.
1017 TR_WRITE_R0_TO_REG(SSP_X);
1020 static void tr_r0_to_Y(int const_val)
1022 EOP_MOV_REG_LSR(4, 4, 16); // mov r4, r4, lsr #16
1023 EOP_ORR_REG_LSL(4, 4, 0, 16); // orr r4, r4, r0, lsl #16
1024 EOP_MOV_REG_ROR(4, 4, 16); // mov r4, r4, ror #16
1025 dirty_regb |= KRREG_P;
1026 TR_WRITE_R0_TO_REG(SSP_Y);
1029 static void tr_r0_to_A(int const_val)
1031 EOP_MOV_REG_LSL(5, 5, 16); // mov r5, r5, lsl #16
1032 EOP_MOV_REG_LSR(5, 5, 16); // mov r5, r5, lsr #16 @ AL
1033 EOP_ORR_REG_LSL(5, 5, 0, 16); // orr r5, r5, r0, lsl #16
1034 TR_WRITE_R0_TO_REG(SSP_A);
1037 static void tr_r0_to_ST(int const_val)
1039 // VR doesn't need much accuracy here..
1040 EOP_AND_IMM(1, 0, 0, 0x67); // and r1, r0, #0x67
1041 EOP_AND_IMM(6, 6, 8/2, 0xe0); // and r6, r6, #7<<29 @ preserve STACK
1042 EOP_ORR_REG_LSL(6, 6, 1, 4); // orr r6, r6, r1, lsl #4
1043 TR_WRITE_R0_TO_REG(SSP_ST);
1045 dirty_regb &= ~KRREG_ST;
1048 static void tr_r0_to_STACK(int const_val)
1051 EOP_ADD_IMM(1, 7, 24/2, 0x04); // add r1, r7, 0x400
1052 EOP_ADD_IMM(1, 1, 0, 0x48); // add r1, r1, 0x048
1053 EOP_ADD_REG_LSR(1, 1, 6, 28); // add r1, r1, r6, lsr #28
1054 EOP_STRH_SIMPLE(0, 1); // strh r0, [r1]
1055 EOP_ADD_IMM(6, 6, 8/2, 0x20); // add r6, r6, #1<<29
1059 static void tr_r0_to_PC(int const_val)
1061 EOP_MOV_REG_LSL(1, 0, 16); // mov r1, r0, lsl #16
1062 EOP_STR_IMM(1,7,0x400+6*4); // str r1, [r7, #(0x400+6*8)]
1066 typedef void (tr_write_func)(int const_val);
1068 static tr_write_func *tr_write_funcs[8] =
1077 (tr_write_func *)tr_unhandled
1080 static void tr_mac_load_XY(int op)
1082 tr_rX_read(op&3, (op>>2)&3); // X
1083 EOP_MOV_REG_LSL(4, 0, 16);
1084 tr_rX_read(((op>>4)&3)|4, (op>>6)&3); // Y
1085 EOP_ORR_REG_SIMPLE(4, 0);
1086 dirty_regb |= KRREG_P;
1087 hostreg_sspreg_changed(SSP_X);
1088 hostreg_sspreg_changed(SSP_Y);
1089 known_regb &= ~KRREG_X;
1090 known_regb &= ~KRREG_Y;
1093 static int tr_aop_ssp2arm(int op)
1096 case 1: return A_OP_SUB;
1097 case 3: return A_OP_CMP;
1098 case 4: return A_OP_ADD;
1099 case 5: return A_OP_AND;
1100 case 6: return A_OP_ORR;
1101 case 7: return A_OP_EOR;
1108 static int translate_op(unsigned int op, int *pc, int imm)
1110 u32 tmpv, tmpv2, tmpv3;
1112 known_regs.gr[SSP_PC].h = *pc;
1118 if (op == 0) { ret++; break; } // nop
1119 tmpv = op & 0xf; // src
1120 tmpv2 = (op >> 4) & 0xf; // dst
1121 if (tmpv >= 8 || tmpv2 >= 8) return -1; // TODO
1122 if (tmpv2 == SSP_A && tmpv == SSP_P) { // ld A, P
1124 EOP_MOV_REG_SIMPLE(5, 10);
1125 hostreg_sspreg_changed(SSP_A); \
1126 known_regb &= ~(KRREG_A|KRREG_AL);
1129 tr_read_funcs[tmpv]();
1130 tr_write_funcs[tmpv2]((known_regb & (1 << tmpv)) ? known_regs.gr[tmpv].h : -1);
1135 // tmpv = ptr1_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv); break;
1136 int r = (op&3) | ((op>>6)&4);
1137 int mod = (op>>2)&3;
1138 tmpv = (op >> 4) & 0xf; // dst
1139 if (tmpv >= 8) return -1; // TODO
1142 else tr_ptrr_mod(r, mod, 1, 1);
1143 tr_write_funcs[tmpv](-1);
1149 tmpv = (op >> 4) & 0xf; // src
1150 if (tmpv >= 8) return -1; // TODO
1151 tr_read_funcs[tmpv]();
1157 tr_bank_read(op&0x1ff);
1163 tmpv = (op & 0xf0) >> 4;
1167 tr_write_funcs[tmpv](imm);
1170 else if (tmpv == 0xe && (PROGRAM(*pc) >> 9) == 4)
1172 // programming PMC..
1174 tmpv = imm | (PROGRAM((*pc)++) << 16);
1176 emit_mov_const(A_COND_AL, 0, tmpv);
1177 EOP_LDR_IMM(1,7,0x484); // ldr r1, [r7, #0x484] // emu_status
1178 EOP_STR_IMM(0,7,0x400+14*4); // PMC
1179 // reads on fe06, fe08; next op is ld -,
1180 if ((tmpv == 0x187f03 || tmpv == 0x187f04) && (PROGRAM(*pc) & 0xfff0) == 0)
1182 int flag = (tmpv == 0x187f03) ? SSP_WAIT_30FE06 : SSP_WAIT_30FE08;
1183 tr_flush_dirty_ST();
1184 EOP_LDR_IMM(0,7,0x490); // dram_ptr
1185 EOP_ADD_IMM(0,0,24/2,0xfe); // add r0, r0, #0xfe00
1186 EOP_LDRH_IMM(0,0,(tmpv == 0x187f03) ? 6 : 8); // ldrh r0, [r0, #8]
1187 EOP_TST_REG_SIMPLE(0,0);
1188 EOP_C_DOP_IMM(A_COND_EQ,A_OP_ADD,0,11,11,22/2,1); // add r11, r11, #1024
1189 EOP_C_DOP_IMM(A_COND_EQ,A_OP_ORR,0, 1, 1,24/2,flag>>8); // orr r1, r1, #SSP_WAIT_30FE08
1191 EOP_ORR_IMM(1,1,0,SSP_PMC_SET); // orr r1, r1, #SSP_PMC_SET
1192 EOP_STR_IMM(1,7,0x484); // str r1, [r7, #0x484] // emu_status
1193 hostreg_r[0] = hostreg_r[1] = -1;
1197 return -1; /* TODO.. */
1201 tmpv2 = (op >> 4) & 0xf; // dst
1202 if (tmpv2 >= 8) return -1; // TODO
1204 tr_write_funcs[tmpv2](-1);
1216 tr_bank_write(op&0x1ff);
1222 r = (op&3) | ((op>>6)&4); // src
1223 tmpv2 = (op >> 4) & 0xf; // dst
1224 if (tmpv2 >= 8) tr_unhandled();
1225 if ((r&3) == 3) tr_unhandled();
1227 if (known_regb & (1 << (r+8))) {
1228 tr_mov16(0, known_regs.r[r]);
1229 tr_write_funcs[tmpv2](known_regs.r[r]);
1231 int reg = (r < 4) ? 8 : 9;
1232 if (r&3) EOP_MOV_REG_LSR(0, reg, (r&3)*8); // mov r0, r{7,8}, lsr #lsr
1233 EOP_AND_IMM(0, (r&3)?0:reg, 0, 0xff); // and r0, r{7,8}, <mask>
1235 tr_write_funcs[tmpv2](-1);
1243 r = (op&3) | ((op>>6)&4); // dst
1244 tmpv = (op >> 4) & 0xf; // src
1245 if (tmpv >= 8) tr_unhandled();
1246 if ((r&3) == 3) tr_unhandled();
1248 if (known_regb & (1 << tmpv)) {
1249 known_regs.r[r] = known_regs.gr[tmpv].h;
1250 known_regb |= 1 << (r + 8);
1251 dirty_regb |= 1 << (r + 8);
1253 int reg = (r < 4) ? 8 : 9;
1254 int ror = ((4 - (r&3))*8) & 0x1f;
1255 tr_read_funcs[tmpv]();
1256 EOP_BIC_IMM(reg, reg, ror/2, 0xff); // bic r{7,8}, r{7,8}, <mask>
1257 EOP_AND_IMM(0, 0, 0, 0xff); // and r0, r0, 0xff
1258 EOP_ORR_REG_LSL(reg, reg, 0, (r&3)*8); // orr r{7,8}, r{7,8}, r0, lsl #lsl
1260 known_regb &= ~(1 << (r+8));
1261 dirty_regb &= ~(1 << (r+8));
1269 known_regs.r[tmpv] = op;
1270 known_regb |= 1 << (tmpv + 8);
1271 dirty_regb |= 1 << (tmpv + 8);
1276 u32 *jump_op = NULL;
1277 tmpv = tr_cond_check(op);
1278 if (tmpv != A_COND_AL) {
1279 jump_op = tcache_ptr;
1280 EOP_MOV_IMM(0, 0, 0); // placeholder for branch
1283 tr_r0_to_STACK(*pc);
1284 if (tmpv != A_COND_AL) {
1285 u32 *real_ptr = tcache_ptr;
1286 tcache_ptr = jump_op;
1287 EOP_C_B(tr_neg_cond(tmpv),0,real_ptr - jump_op - 2);
1288 tcache_ptr = real_ptr;
1290 tr_mov16_cond(tmpv, 0, imm);
1291 if (tmpv != A_COND_AL) {
1292 tr_mov16_cond(tr_neg_cond(tmpv), 0, *pc);
1294 tr_r0_to_PC(tmpv == A_COND_AL ? imm : -1);
1300 tmpv2 = (op >> 4) & 0xf; // dst
1301 if (tmpv2 >= 8) return -1; // TODO
1304 EOP_LDR_IMM(1,7,0x48c); // ptr_iram_rom
1305 EOP_ADD_REG_LSL(0,1,0,1); // add r0, r1, r0, lsl #1
1306 EOP_LDRH_SIMPLE(0,0); // ldrh r0, [r0]
1307 hostreg_r[0] = hostreg_r[1] = -1;
1308 tr_write_funcs[tmpv2](-1);
1313 tmpv = tr_cond_check(op);
1314 tr_mov16_cond(tmpv, 0, imm);
1315 if (tmpv != A_COND_AL) {
1316 tr_mov16_cond(tr_neg_cond(tmpv), 0, *pc);
1318 tr_r0_to_PC(tmpv == A_COND_AL ? imm : -1);
1323 // check for repeats of this op
1325 while (PROGRAM(*pc) == op && (op & 7) != 6) {
1328 if ((op&0xf0) != 0) // !always
1331 tmpv2 = tr_cond_check(op);
1333 case 2: EOP_C_DOP_REG_XIMM(tmpv2,A_OP_MOV,1,0,5,tmpv,A_AM1_ASR,5); break; // shr (arithmetic)
1334 case 3: EOP_C_DOP_REG_XIMM(tmpv2,A_OP_MOV,1,0,5,tmpv,A_AM1_LSL,5); break; // shl
1335 case 6: EOP_C_DOP_IMM(tmpv2,A_OP_RSB,1,5,5,0,0); break; // neg
1336 case 7: EOP_C_DOP_REG_XIMM(tmpv2,A_OP_EOR,0,5,1,31,A_AM1_ASR,5); // eor r1, r5, r5, asr #31
1337 EOP_C_DOP_REG_XIMM(tmpv2,A_OP_ADD,1,1,5,31,A_AM1_LSR,5); // adds r5, r1, r5, lsr #31
1338 hostreg_r[1] = -1; break; // abs
1339 default: tr_unhandled();
1342 hostreg_sspreg_changed(SSP_A);
1343 dirty_regb |= KRREG_ST;
1344 known_regb &= ~KRREG_ST;
1345 known_regb &= ~(KRREG_A|KRREG_AL);
1354 EOP_C_DOP_REG_XIMM(A_COND_AL,A_OP_SUB,1,5,5,0,A_AM1_LSL,10); // subs r5, r5, r10
1355 hostreg_sspreg_changed(SSP_A);
1356 known_regb &= ~(KRREG_A|KRREG_AL);
1357 dirty_regb |= KRREG_ST;
1360 // mpya (rj), (ri), b
1365 EOP_C_DOP_REG_XIMM(A_COND_AL,A_OP_ADD,1,5,5,0,A_AM1_LSL,10); // adds r5, r5, r10
1366 hostreg_sspreg_changed(SSP_A);
1367 known_regb &= ~(KRREG_A|KRREG_AL);
1368 dirty_regb |= KRREG_ST;
1371 // mld (rj), (ri), b
1373 EOP_C_DOP_IMM(A_COND_AL,A_OP_MOV,1,0,5,0,0); // movs r5, #0
1374 hostreg_sspreg_changed(SSP_A);
1375 known_regs.gr[SSP_A].v = 0;
1376 known_regb |= (KRREG_A|KRREG_AL);
1377 dirty_regb |= KRREG_ST;
1388 tmpv = op & 0xf; // src
1389 tmpv2 = tr_aop_ssp2arm(op>>13); // op
1390 tmpv3 = (tmpv2 == A_OP_CMP) ? 0 : 5;
1391 if (tmpv >= 8) return -1; // TODO
1392 if (tmpv == SSP_P) {
1394 EOP_C_DOP_REG_XIMM(A_COND_AL,tmpv2,1,5,tmpv3, 0,A_AM1_LSL,10); // OPs r5, r5, r10
1395 } else if (tmpv == SSP_A) {
1396 EOP_C_DOP_REG_XIMM(A_COND_AL,tmpv2,1,5,tmpv3, 0,A_AM1_LSL, 5); // OPs r5, r5, r5
1398 tr_read_funcs[tmpv]();
1399 EOP_C_DOP_REG_XIMM(A_COND_AL,tmpv2,1,5,tmpv3,16,A_AM1_LSL, 0); // OPs r5, r5, r0, lsl #16
1401 hostreg_sspreg_changed(SSP_A);
1402 known_regb &= ~(KRREG_A|KRREG_AL|KRREG_ST);
1403 dirty_regb |= KRREG_ST;
1413 tmpv2 = tr_aop_ssp2arm(op>>13); // op
1414 tmpv3 = (tmpv2 == A_OP_CMP) ? 0 : 5;
1415 tr_rX_read((op&3)|((op>>6)&4), (op>>2)&3);
1416 EOP_C_DOP_REG_XIMM(A_COND_AL,tmpv2,1,5,tmpv3,16,A_AM1_LSL,0); // OPs r5, r5, r0, lsl #16
1417 hostreg_sspreg_changed(SSP_A);
1418 known_regb &= ~(KRREG_A|KRREG_AL|KRREG_ST);
1419 dirty_regb |= KRREG_ST;
1429 tmpv2 = tr_aop_ssp2arm(op>>13); // op
1430 tmpv3 = (tmpv2 == A_OP_CMP) ? 0 : 5;
1431 tr_bank_read(op&0x1ff);
1432 EOP_C_DOP_REG_XIMM(A_COND_AL,tmpv2,1,5,tmpv3,16,A_AM1_LSL,0); // OPs r5, r5, r0, lsl #16
1433 hostreg_sspreg_changed(SSP_A);
1434 known_regb &= ~(KRREG_A|KRREG_AL|KRREG_ST);
1435 dirty_regb |= KRREG_ST;
1445 tmpv = (op & 0xf0) >> 4;
1446 tmpv2 = tr_aop_ssp2arm(op>>13); // op
1447 tmpv3 = (tmpv2 == A_OP_CMP) ? 0 : 5;
1449 EOP_C_DOP_REG_XIMM(A_COND_AL,tmpv2,1,5,tmpv3,16,A_AM1_LSL,0); // OPs r5, r5, r0, lsl #16
1450 hostreg_sspreg_changed(SSP_A);
1451 known_regb &= ~(KRREG_A|KRREG_AL|KRREG_ST);
1452 dirty_regb |= KRREG_ST;
1462 tmpv2 = tr_aop_ssp2arm(op>>13); // op
1463 tmpv3 = (tmpv2 == A_OP_CMP) ? 0 : 5;
1465 EOP_C_DOP_REG_XIMM(A_COND_AL,tmpv2,1,5,tmpv3,16,A_AM1_LSL,0); // OPs r5, r5, r0, lsl #16
1466 hostreg_sspreg_changed(SSP_A);
1467 known_regb &= ~(KRREG_A|KRREG_AL|KRREG_ST);
1468 dirty_regb |= KRREG_ST;
1479 tmpv2 = tr_aop_ssp2arm(op>>13); // op
1480 tmpv3 = (tmpv2 == A_OP_CMP) ? 0 : 5;
1481 r = (op&3) | ((op>>6)&4); // src
1482 if ((r&3) == 3) tr_unhandled();
1484 if (known_regb & (1 << (r+8))) {
1485 EOP_C_DOP_IMM(A_COND_AL,tmpv2,1,5,tmpv3,16/2,known_regs.r[r]); // OPs r5, r5, #val<<16
1487 int reg = (r < 4) ? 8 : 9;
1488 if (r&3) EOP_MOV_REG_LSR(0, reg, (r&3)*8); // mov r0, r{7,8}, lsr #lsr
1489 EOP_AND_IMM(0, (r&3)?0:reg, 0, 0xff); // and r0, r{7,8}, <mask>
1490 EOP_C_DOP_REG_XIMM(A_COND_AL,tmpv2,1,5,tmpv3,16,A_AM1_LSL,0); // OPs r5, r5, r0, lsl #16
1493 hostreg_sspreg_changed(SSP_A);
1494 known_regb &= ~(KRREG_A|KRREG_AL|KRREG_ST);
1495 dirty_regb |= KRREG_ST;
1506 tmpv2 = tr_aop_ssp2arm(op>>13); // op
1507 tmpv3 = (tmpv2 == A_OP_CMP) ? 0 : 5;
1508 EOP_C_DOP_IMM(A_COND_AL,tmpv2,1,5,tmpv3,16/2,op & 0xff); // OPs r5, r5, #val<<16
1509 hostreg_sspreg_changed(SSP_A);
1510 known_regb &= ~(KRREG_A|KRREG_AL|KRREG_ST);
1511 dirty_regb |= KRREG_ST;
1518 static void *translate_block(int pc)
1520 unsigned int op, op1, imm, ccount = 0;
1521 unsigned int *block_start;
1522 int ret, ret_prev = -1;
1525 //*tcache_ptr++ = (u32) in_funcs; // -1 func pool
1527 printf("translate %04x -> %04x\n", pc<<1, (tcache_ptr-tcache)<<2);
1528 block_start = tcache_ptr;
1530 dirty_regb = KRREG_P;
1533 emit_block_prologue();
1535 for (; ccount < 100;)
1537 //printf(" insn #%i\n", icount);
1542 if ((op1 & 0xf) == 4 || (op1 & 0xf) == 6)
1543 imm = PROGRAM(pc++); // immediate
1545 ret = translate_op(op, &pc, imm);
1548 tr_flush_dirty_prs();
1549 tr_flush_dirty_ST();
1551 emit_mov_const(A_COND_AL, 0, op);
1555 emit_mov_const(A_COND_AL, 1, imm);
1560 if (ret_prev > 0) emit_call(regfile_store);
1561 emit_call(in_funcs[op1]);
1562 emit_call(regfile_load);
1564 if (in_funcs[op1] == NULL) {
1565 printf("NULL func! op=%08x (%02x)\n", op, op1);
1570 dirty_regb |= KRREG_P;
1576 if (op1 == 0x24 || op1 == 0x26 || // call, bra
1577 ((op1 == 0 || op1 == 1 || op1 == 4 || op1 == 5 || op1 == 9 || op1 == 0x25) &&
1578 (op & 0xf0) == 0x60)) { // ld PC
1584 tr_flush_dirty_prs();
1585 tr_flush_dirty_ST();
1586 emit_block_epilogue(ccount + 1);
1587 *tcache_ptr++ = 0xffffffff; // end of block
1588 //printf(" %i inst\n", icount);
1590 if (tcache_ptr - tcache > TCACHE_SIZE/4) {
1591 printf("tcache overflow!\n");
1599 printf("%i blocks, %i bytes\n", nblocks, (tcache_ptr - tcache)*4);
1600 //printf("%p %p\n", tcache_ptr, emit_block_epilogue);
1604 FILE *f = fopen("tcache.bin", "wb");
1605 fwrite(tcache, 1, (tcache_ptr - tcache)*4, f);
1618 // -----------------------------------------------------
1620 int ssp1601_dyn_startup(void)
1622 memset(tcache, 0, TCACHE_SIZE);
1623 memset(block_table, 0, sizeof(block_table));
1624 memset(block_table_iram, 0, sizeof(block_table_iram));
1625 tcache_ptr = tcache;
1626 *tcache_ptr++ = 0xffffffff;
1630 static unsigned short dummy = 0;
1637 void ssp1601_dyn_reset(ssp1601_t *ssp)
1639 ssp1601_reset_local(ssp);
1640 ssp->ptr_rom = (unsigned int) Pico.rom;
1641 ssp->ptr_iram_rom = (unsigned int) svp->iram_rom;
1642 ssp->ptr_dram = (unsigned int) svp->dram;
1645 void ssp1601_dyn_run(int cycles)
1647 if (ssp->emu_status & SSP_WAIT_MASK) return;
1648 //{ printf("%i wait\n", Pico.m.frame_count); return; }
1649 //printf("%i %04x\n", Pico.m.frame_count, rPC<<1);
1652 rPC = DUMP_BLOCK >> 1;
1656 int (*trans_entry)(void);
1660 iram_context = get_iram_context();
1663 if (block_table_iram[iram_context][rPC] == NULL)
1664 block_table_iram[iram_context][rPC] = translate_block(rPC);
1665 trans_entry = (void *) block_table_iram[iram_context][rPC];
1669 if (block_table[rPC] == NULL)
1670 block_table[rPC] = translate_block(rPC);
1671 trans_entry = (void *) block_table[rPC];
1674 //printf("enter %04x\n", rPC<<1);
1675 cycles -= trans_entry();
1676 //printf("leave %04x\n", rPC<<1);
1678 // debug_dump2file("tcache.bin", tcache, (tcache_ptr - tcache) << 1);