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 0x1d7c
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 CRREG_X (1 << SSP_X)
539 #define CRREG_Y (1 << SSP_Y)
540 #define CRREG_A (1 << SSP_A) /* AH only */
541 #define CRREG_ST (1 << SSP_ST)
542 #define CRREG_STACK (1 << SSP_STACK)
543 #define CRREG_PC (1 << SSP_PC)
544 #define CRREG_P (1 << SSP_P)
545 #define CRREG_PR0 (1 << 8)
546 #define CRREG_PR4 (1 << 12)
547 #define CRREG_AL (1 << 16)
549 static u32 const_regb = 0; /* bitfield of known register values */
550 static u32 dirty_regb = 0; /* known vals, which need to be flushed (only P, r0-r7) */
552 /* known values of host regs.
554 * 000000-00ffff - 16bit value
555 * 100000-10ffff - base reg (r7) + 16bit val
556 * 0r0000 - means reg (low) eq gr[r].h
558 static int hostreg_r[4];
560 static void hostreg_clear(void)
563 for (i = 0; i < 4; i++)
567 /*static*/ void hostreg_ah_changed(void)
570 for (i = 0; i < 4; i++)
571 if (hostreg_r[i] == (SSP_A<<16)) hostreg_r[i] = -1;
575 #define PROGRAM(x) ((unsigned short *)svp->iram_rom)[x]
577 /* load 16bit val into host reg r0-r3. Nothing is trashed */
578 static void tr_mov16(int r, int val)
580 if (hostreg_r[r] != val) {
581 emit_mov_const(r, val);
586 /* update P, if needed. Trashes r1 */
587 static void tr_flush_dirty_P(void)
590 if (!(dirty_regb & CRREG_P)) return;
591 EOP_MOV_REG_ASR(10, 4, 16); // mov r10, r4, asr #16
592 EOP_MOV_REG_LSL( 1, 4, 16); // mov r1, r4, lsl #16
593 EOP_MOV_REG_ASR( 1, 1, 15); // mov r1, r1, asr #15
594 EOP_MUL(10, 1, 10); // mul r10, r1, r10
595 dirty_regb &= ~CRREG_P;
598 /* write dirty r0-r7 to host regs. Nothing is trashed */
599 static void tr_flush_dirty_pr(void)
604 for (i = 0; dirty_regb && i < 8; i++, dirty_regb >>= 1)
606 if (!(dirty_regb&1)) continue;
608 case 0: ror = 0; break;
609 case 1: ror = 24/2; break;
610 case 2: ror = 16/2; break;
612 reg = (i < 4) ? 8 : 9;
613 EOP_BIC_IMM(reg,reg,ror,0xff);
614 if (const_regs.r[i] != 0)
615 EOP_ORR_IMM(reg,reg,ror,const_regs.r[i]);
619 /* read bank word to r0 (MSW may contain trash). Thrashes r1. */
620 static void tr_bank_read(int addr) /* word addr 0-0x1ff */
625 if (hostreg_r[1] != (0x100000|((addr&0x180)<<1))) {
626 EOP_ADD_IMM(1,7,30/2,(addr&0x180)>>1); // add r1, r7, ((op&0x180)<<1)
627 hostreg_r[1] = 0x100000|((addr&0x180)<<1);
631 EOP_LDRH_IMM(0,breg,(addr&0x7f)<<1); // ldrh r0, [r1, (op&0x7f)<<1]
633 EOP_LDR_IMM(0,7,(addr&0x1ff)<<1); // ldr r0, [r1, (op&0x1ff)<<1]
638 /* write r0 to bank. Trashes r1. */
639 static void tr_bank_write(int addr)
643 if (hostreg_r[1] != (0x100000|((addr&0x180)<<1))) {
644 EOP_ADD_IMM(1,7,30/2,(addr&0x180)>>1); // add r1, r7, ((op&0x180)<<1)
645 hostreg_r[1] = 0x100000|((addr&0x180)<<1);
649 EOP_STRH_IMM(0,breg,(addr&0x7f)<<1); // strh r0, [r1, (op&0x7f)<<1]
652 /* handle RAM bank pointer modifiers. Nothing is trashed. */
653 static void tr_ptrr_mod(int r, int mod, int need_modulo)
655 int modulo = -1, modulo_shift = -1; /* unknown */
657 if (mod == 0) return;
659 if (!need_modulo || mod == 1) // +!
661 else if (need_modulo && (const_regb & CRREG_ST)) {
662 modulo_shift = const_regs.gr[SSP_ST].h & 7;
663 if (modulo_shift == 0) modulo_shift = 8;
666 if (mod > 1 && modulo_shift == -1) { printf("need var modulo\n"); exit(1); }
667 modulo = (1 << modulo_shift) - 1;
669 if (const_regb & (1 << (r + 8))) {
671 const_regs.r[r] = (const_regs.r[r] & ~modulo) | ((const_regs.r[r] - 1) & modulo);
672 else const_regs.r[r] = (const_regs.r[r] & ~modulo) | ((const_regs.r[r] + 1) & modulo);
674 int reg = (r < 4) ? 8 : 9;
675 int ror = ((r&3) + 1)*8 - (8 - modulo_shift);
676 EOP_MOV_REG_ROR(reg,reg,ror);
677 // {add|sub} reg, reg, #1<<shift
678 EOP_C_DOP_IMM(A_COND_AL,(mod==2)?A_OP_SUB:A_OP_ADD,0,reg,reg, 8/2, 1<<(8 - modulo_shift));
679 EOP_MOV_REG_ROR(reg,reg,32-ror);
683 // SSP_GR0, SSP_X, SSP_Y, SSP_A,
684 // SSP_ST, SSP_STACK, SSP_PC, SSP_P,
687 //@ r6: STACK and emu flags
691 static void tr_GR0_to_r0(void)
696 static void tr_X_to_r0(void)
698 if (hostreg_r[0] != (SSP_X<<16)) {
699 EOP_MOV_REG_LSR(0, 4, 16); // mov r0, r4, lsr #16
700 hostreg_r[0] = SSP_X<<16;
704 static void tr_Y_to_r0(void)
707 if (hostreg_r[0] != (SSP_Y<<16)) {
708 EOP_MOV_REG_SIMPLE(0, 4); // mov r0, r4
709 hostreg_r[0] = SSP_Y<<16;
713 static void tr_A_to_r0(void)
715 if (hostreg_r[0] != (SSP_A<<16)) {
716 EOP_MOV_REG_LSR(0, 5, 16); // mov r0, r5, lsr #16 @ AH
717 hostreg_r[0] = SSP_A<<16;
721 static void tr_ST_to_r0(void)
723 // VR doesn't need much accuracy here..
724 EOP_MOV_REG_LSR(0, 6, 4); // mov r0, r6, lsr #4
725 EOP_AND_IMM(0, 0, 0, 0x67); // and r0, r0, #0x67
729 static void tr_STACK_to_r0(void)
732 EOP_SUB_IMM(6, 6, 8/2, 0x20); // sub r6, r6, #1<<29
733 EOP_ADD_IMM(1, 7, 24/2, 0x04); // add r1, r7, 0x400
734 EOP_ADD_IMM(1, 1, 0, 0x48); // add r1, r1, 0x048
735 EOP_ADD_REG_LSR(1, 1, 6, 28); // add r1, r1, r6, lsr #28
736 EOP_LDRH_SIMPLE(0, 1); // ldrh r0, [r1]
737 hostreg_r[0] = hostreg_r[1] = -1;
740 static void tr_PC_to_r0(void)
742 tr_mov16(0, const_regs.gr[SSP_PC].h);
745 static void tr_P_to_r0(void)
748 EOP_MOV_REG_LSR(0, 10, 16); // mov r0, r10, lsr #16
752 typedef void (tr_read_func)(void);
754 static tr_read_func *tr_read_funcs[8] =
767 // write r0 to general reg handlers. Trashes r1
768 static void tr_unhandled(void)
770 printf("unhandled @ %04x\n", const_regs.gr[SSP_PC].h<<1);
774 static void tr_r0_to_GR0(void)
779 static void tr_r0_to_X(void)
781 EOP_MOV_REG_LSL(4, 4, 16); // mov r4, r4, lsl #16
782 EOP_MOV_REG_LSR(4, 4, 16); // mov r4, r4, lsr #16
783 EOP_ORR_REG_LSL(4, 4, 0, 16); // orr r4, r4, r0, lsl #16
784 dirty_regb |= CRREG_P; // touching X or Y makes P dirty.
787 static void tr_r0_to_Y(void)
789 EOP_MOV_REG_LSR(4, 4, 16); // mov r4, r4, lsr #16
790 EOP_ORR_REG_LSL(4, 4, 0, 16); // orr r4, r4, r0, lsl #16
791 EOP_MOV_REG_ROR(4, 4, 16); // mov r4, r4, ror #16
792 dirty_regb |= CRREG_P;
795 static void tr_r0_to_A(void)
797 EOP_MOV_REG_LSL(5, 5, 16); // mov r5, r5, lsl #16
798 EOP_MOV_REG_LSR(5, 5, 16); // mov r5, r5, lsr #16 @ AL
799 EOP_ORR_REG_LSL(5, 5, 0, 16); // orr r5, r5, r0, lsl #16
802 static void tr_r0_to_ST(void)
804 // VR doesn't need much accuracy here..
805 EOP_AND_IMM(1, 0, 0, 0x67); // and r1, r0, #0x67
806 EOP_AND_IMM(6, 6, 8/2, 0xe0); // and r6, r6, #7<<29 @ preserve STACK
807 EOP_ORR_REG_LSL(6, 6, 1, 4); // orr r6, r6, r1, lsl #4
811 static void tr_r0_to_STACK(void)
814 EOP_ADD_IMM(1, 7, 24/2, 0x04); // add r1, r7, 0x400
815 EOP_ADD_IMM(1, 1, 0, 0x48); // add r1, r1, 0x048
816 EOP_ADD_REG_LSR(1, 1, 6, 28); // add r1, r1, r6, lsr #28
817 EOP_STRH_SIMPLE(0, 1); // strh r0, [r1]
818 EOP_ADD_IMM(6, 6, 8/2, 0x20); // add r6, r6, #1<<29
822 static void tr_r0_to_PC(void)
824 EOP_MOV_REG_LSL(1, 0, 16); // mov r1, r0, lsl #16
825 EOP_STR_IMM(1,7,0x400+6*4); // str r1, [r7, #(0x400+6*8)]
829 typedef void (tr_write_func)(void);
831 static tr_write_func *tr_write_funcs[8] =
844 static int translate_op(unsigned int op, int *pc, int imm)
848 const_regs.gr[SSP_PC].h = *pc;
854 if (op == 0) { ret++; break; } // nop
855 tmpv = op & 0xf; // src
856 tmpv2 = (op >> 4) & 0xf; // dst
857 if (tmpv >= 8 || tmpv2 >= 8) return -1; // TODO
858 if (tmpv2 == SSP_A && tmpv == SSP_P) { // ld A, P
860 EOP_MOV_REG_SIMPLE(5, 10);
861 const_regb &= ~(CRREG_A|CRREG_AL);
864 tr_read_funcs[tmpv]();
865 tr_write_funcs[tmpv2]();
866 if (const_regb & (1 << tmpv)) {
867 const_regs.gr[tmpv2].h = const_regs.gr[tmpv].h;
868 const_regb |= 1 << tmpv2;
870 const_regb &= ~(1 << tmpv2);
875 tr_bank_read(op&0x1ff);
877 const_regb &= ~CRREG_A;
878 hostreg_r[0] = SSP_A<<16;
883 tmpv = (op & 0xf0) >> 4;
887 tr_write_funcs[tmpv]();
888 const_regs.gr[tmpv].h = imm;
889 const_regb |= 1 << tmpv;
892 else if (tmpv == 0xe && (PROGRAM(*pc) >> 9) == 4)
896 tmpv = imm | (PROGRAM((*pc)++) << 16);
897 emit_mov_const(0, tmpv);
898 EOP_LDR_IMM(1,7,0x484); // ldr r0, [r7, #0x484] // emu_status
899 EOP_STR_IMM(0,7,0x400+14*4); // PMC
900 // reads on fe06, fe08; next op is ld -,
901 if ((tmpv == 0x187f03 || tmpv == 0x187f04) && (PROGRAM(*pc) & 0xfff0) == 0)
903 int flag = (tmpv == 0x187f03) ? (SSP_WAIT_30FE06) : (SSP_WAIT_30FE08);
904 EOP_LDR_IMM(0,7,0x490); // dram_ptr
905 EOP_ADD_IMM(0,0,24/2,0xfe); // add r0, r0, #0xfe00
906 EOP_LDRH_IMM(0,0,8); // ldrh r0, [r0, #8]
907 EOP_TST_REG_SIMPLE(0,0);
908 EOP_C_DOP_IMM(A_COND_EQ,A_OP_ADD,0,11,11,22/2,1); // add r11, r11, #1024
909 EOP_C_DOP_IMM(A_COND_EQ,A_OP_ORR,0, 1, 1,24/2,flag>>8); // orr r1, r1, #SSP_WAIT_30FE08
911 EOP_ORR_IMM(1,1,0,SSP_PMC_SET); // orr r1, r1, #SSP_PMC_SET
912 EOP_STR_IMM(1,7,0x484); // str r1, [r7, #0x484] // emu_status
913 hostreg_r[0] = hostreg_r[1] = -1;
917 return -1; /* TODO.. */
922 // int t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18);
926 tmpv = (op>>2) & 3; // direct addressing
928 if (hostreg_r[1] != 0x100200) {
929 EOP_ADD_IMM(1,7,30/2,0x200>>2); // add r1, r7, 0x200
930 hostreg_r[1] = 0x100200;
932 EOP_STRH_IMM(0,1,tmpv<<1); // str r0, [r1, {0,2,4,6}]
934 EOP_STRH_IMM(0,7,tmpv<<1); // str r0, [r7, {0,2,4,6}]
939 int r = (op&3) | ((op>>6)&4);
940 if (const_regb & (1 << (r + 8))) {
941 tr_bank_write(const_regs.r[r] | ((r < 4) ? 0 : 0x100));
943 int reg = (r < 4) ? 8 : 9;
944 int ror = ((4 - (r&3))*8) & 0x1f;
945 EOP_AND_IMM(1,reg,ror/2,0xff); // and r1, r{7,8}, <mask>
947 EOP_ORR_IMM(1,1,((ror-8)&0x1f)/2,1); // orr r1, r1, 1<<shift
948 if (r&3) EOP_ADD_REG_LSR(1,7,1, (r&3)*8-1); // add r1, r7, r1, lsr #lsr
949 else EOP_ADD_REG_LSL(1,7,1,1);
950 EOP_STRH_SIMPLE(0,1); // strh r0, [r1]
953 tr_ptrr_mod(r, (op>>2) & 3, 0);
959 if (hostreg_r[0] != (SSP_A<<16)) {
960 EOP_MOV_REG_LSR(0, 5, 16); // mov r0, r5, lsr #16 @ A
961 hostreg_r[0] = SSP_A<<16;
963 tr_bank_write(op&0x1ff);
969 r = (op&3) | ((op>>6)&4); // src
970 tmpv2 = (op >> 4) & 0xf; // dst
971 if (tmpv2 >= 8) tr_unhandled();
973 if (const_regb & (1 << (r+8))) {
974 tr_mov16(0, const_regs.r[r]);
975 const_regs.gr[tmpv2].h = const_regs.r[r];
976 const_regb |= 1 << tmpv2;
978 reg = (r < 4) ? 8 : 9;
979 if (r&3) EOP_MOV_REG_LSR(0, reg, (r&3)*8); // mov r0, r{7,8}, lsr #lsr
980 EOP_AND_IMM(0, (r&3)?0:reg, 0, 0xff); // and r0, r{7,8}, <mask>
982 const_regb &= ~(1 << tmpv2);
984 tr_write_funcs[tmpv2]();
991 const_regs.r[tmpv] = op;
992 const_regb |= 1 << (tmpv + 8);
993 dirty_regb |= 1 << (tmpv + 8);
1000 static void *translate_block(int pc)
1002 unsigned int op, op1, imm, ccount = 0;
1003 unsigned int *block_start;
1004 int ret, ret_prev = -1;
1007 //*tcache_ptr++ = (u32) in_funcs; // -1 func pool
1009 printf("translate %04x -> %04x\n", pc<<1, (tcache_ptr-tcache)<<2);
1010 block_start = tcache_ptr;
1012 dirty_regb = CRREG_P;
1015 emit_block_prologue();
1017 for (; ccount < 100;)
1019 //printf(" insn #%i\n", icount);
1024 if ((op1 & 0xf) == 4 || (op1 & 0xf) == 6)
1025 imm = PROGRAM(pc++); // immediate
1027 ret = translate_op(op, &pc, imm);
1030 tr_flush_dirty_pr();
1032 emit_mov_const(0, op);
1036 emit_mov_const(1, imm);
1041 if (ret_prev > 0) emit_call(regfile_store);
1042 emit_call(in_funcs[op1]);
1043 emit_call(regfile_load);
1045 if (in_funcs[op1] == NULL) {
1046 printf("NULL func! op=%08x (%02x)\n", op, op1);
1051 dirty_regb |= CRREG_P;
1056 if (op1 == 0x24 || op1 == 0x26 || // call, bra
1057 ((op1 == 0 || op1 == 1 || op1 == 4 || op1 == 5 || op1 == 9 || op1 == 0x25) &&
1058 (op & 0xf0) == 0x60)) { // ld PC
1064 tr_flush_dirty_pr();
1065 emit_block_epilogue(ccount + 1);
1066 *tcache_ptr++ = 0xffffffff; // end of block
1067 //printf(" %i inst\n", icount);
1069 if (tcache_ptr - tcache > TCACHE_SIZE/4) {
1070 printf("tcache overflow!\n");
1078 printf("%i blocks, %i bytes\n", nblocks, (tcache_ptr - tcache)*4);
1079 //printf("%p %p\n", tcache_ptr, emit_block_epilogue);
1083 FILE *f = fopen("tcache.bin", "wb");
1084 fwrite(tcache, 1, (tcache_ptr - tcache)*4, f);
1097 // -----------------------------------------------------
1099 int ssp1601_dyn_startup(void)
1101 memset(tcache, 0, TCACHE_SIZE);
1102 memset(block_table, 0, sizeof(block_table));
1103 memset(block_table_iram, 0, sizeof(block_table_iram));
1104 tcache_ptr = tcache;
1105 *tcache_ptr++ = 0xffffffff;
1111 void ssp1601_dyn_reset(ssp1601_t *ssp)
1113 ssp1601_reset_local(ssp);
1114 ssp->ptr_rom = (unsigned int) Pico.rom;
1115 ssp->ptr_iram = (unsigned int) svp->iram_rom;
1116 ssp->ptr_dram = (unsigned int) svp->dram;
1119 void ssp1601_dyn_run(int cycles)
1121 if (ssp->emu_status & SSP_WAIT_MASK) return;
1122 //{ printf("%i wait\n", Pico.m.frame_count); return; }
1123 //printf("%i %04x\n", Pico.m.frame_count, rPC<<1);
1126 rPC = DUMP_BLOCK >> 1;
1130 int (*trans_entry)(void);
1134 iram_context = get_iram_context();
1137 if (block_table_iram[iram_context][rPC] == NULL)
1138 block_table_iram[iram_context][rPC] = translate_block(rPC);
1139 trans_entry = (void *) block_table_iram[iram_context][rPC];
1143 if (block_table[rPC] == NULL)
1144 block_table[rPC] = translate_block(rPC);
1145 trans_entry = (void *) block_table[rPC];
1148 //printf("enter %04x\n", rPC<<1);
1149 cycles -= trans_entry();
1150 //printf("leave %04x\n", rPC<<1);
1152 // debug_dump2file("tcache.bin", tcache, (tcache_ptr - tcache) << 1);