1 // 187 blocks, 12072 bytes
4 #include "../../PicoInt.h"
6 #define TCACHE_SIZE (256*1024)
7 static unsigned int *block_table[0x5090/2];
8 static unsigned int *block_table_iram[15][0x800/2];
9 static unsigned int *tcache = NULL;
10 static unsigned int *tcache_ptr = NULL;
12 static int had_jump = 0;
13 static int nblocks = 0;
14 static int iram_context = 0;
16 #define EMBED_INTERPRETER
17 #define ssp1601_reset ssp1601_reset_local
18 #define ssp1601_run ssp1601_run_local
20 static unsigned int interp_get_pc(void);
22 #define GET_PC interp_get_pc
23 #define GET_PPC_OFFS() (interp_get_pc()*2 - 2)
24 #define SET_PC(d) { had_jump = 1; rPC = d; } /* must return to dispatcher after this */
25 //#define GET_PC() (PC - (unsigned short *)svp->iram_rom)
26 //#define GET_PPC_OFFS() ((unsigned int)PC - (unsigned int)svp->iram_rom - 2)
27 //#define SET_PC(d) PC = (unsigned short *)svp->iram_rom + d
31 // -----------------------------------------------------
34 static void op00(unsigned int op, unsigned int imm)
37 if (op == 0) return; // nop
38 if (op == ((SSP_A<<4)|SSP_P)) { // A <- P
39 // not sure. MAME claims that only hi word is transfered.
45 tmpv = REG_READ(op & 0x0f);
46 REG_WRITE((op & 0xf0) >> 4, tmpv);
51 static void op01(unsigned int op, unsigned int imm)
54 tmpv = ptr1_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv);
58 static void op02(unsigned int op, unsigned int imm)
61 tmpv = REG_READ((op & 0xf0) >> 4); ptr1_write(op, tmpv);
65 static void op04(unsigned int op, unsigned int imm)
67 REG_WRITE((op & 0xf0) >> 4, imm);
71 static void op05(unsigned int op, unsigned int imm)
74 tmpv = ptr2_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv);
78 static void op06(unsigned int op, unsigned int imm)
84 static void op07(unsigned int op, unsigned int imm)
86 ssp->RAM[op & 0x1ff] = rA;
90 static void op09(unsigned int op, unsigned int imm)
93 tmpv = rIJ[(op&3)|((op>>6)&4)]; REG_WRITE((op & 0xf0) >> 4, tmpv);
97 static void op0a(unsigned int op, unsigned int imm)
99 rIJ[(op&3)|((op>>6)&4)] = REG_READ((op & 0xf0) >> 4);
102 // ldi ri, simm (also op0d op0e op0f)
103 static void op0c(unsigned int op, unsigned int imm)
109 static void op24(unsigned int op, unsigned int imm)
114 if (cond) { int new_PC = imm; write_STACK(GET_PC()); write_PC(new_PC); }
120 static void op25(unsigned int op, unsigned int imm)
123 tmpv = ((unsigned short *)svp->iram_rom)[rA]; REG_WRITE((op & 0xf0) >> 4, tmpv);
127 static void op26(unsigned int op, unsigned int imm)
133 if (cond) write_PC(imm);
139 static void op48(unsigned int op, unsigned int imm)
147 case 2: rA32 = (signed int)rA32 >> 1; break; // shr (arithmetic)
148 case 3: rA32 <<= 1; break; // shl
149 case 6: rA32 = -(signed int)rA32; break; // neg
150 case 7: if ((int)rA32 < 0) rA32 = -(signed int)rA32; break; // abs
151 default: elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: unhandled mod %i @ %04x",
152 op&7, GET_PPC_OFFS());
161 static void op1b(unsigned int op, unsigned int imm)
163 read_P(); // update P
164 rA32 -= rP.v; // maybe only upper word?
165 UPD_ACC_ZN // there checking flags after this
166 rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
167 rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
170 // mpya (rj), (ri), b
171 static void op4b(unsigned int op, unsigned int imm)
173 read_P(); // update P
174 rA32 += rP.v; // confirmed to be 32bit
176 rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
177 rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
181 static void op5b(unsigned int op, unsigned int imm)
185 rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
186 rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
190 static void op10(unsigned int op, unsigned int imm)
195 OP_CHECK32(OP_SUBA32); tmpv = REG_READ(op & 0x0f); OP_SUBA(tmpv);
200 static void op30(unsigned int op, unsigned int imm)
205 OP_CHECK32(OP_CMPA32); tmpv = REG_READ(op & 0x0f); OP_CMPA(tmpv);
210 static void op40(unsigned int op, unsigned int imm)
215 OP_CHECK32(OP_ADDA32); tmpv = REG_READ(op & 0x0f); OP_ADDA(tmpv);
220 static void op50(unsigned int op, unsigned int imm)
225 OP_CHECK32(OP_ANDA32); tmpv = REG_READ(op & 0x0f); OP_ANDA(tmpv);
230 static void op60(unsigned int op, unsigned int imm)
235 OP_CHECK32(OP_ORA32 ); tmpv = REG_READ(op & 0x0f); OP_ORA (tmpv);
240 static void op70(unsigned int op, unsigned int imm)
245 OP_CHECK32(OP_EORA32); tmpv = REG_READ(op & 0x0f); OP_EORA(tmpv);
251 static void op11(unsigned int op, unsigned int imm)
254 tmpv = ptr1_read(op); OP_SUBA(tmpv);
257 static void op31(unsigned int op, unsigned int imm)
260 tmpv = ptr1_read(op); OP_CMPA(tmpv);
263 static void op41(unsigned int op, unsigned int imm)
266 tmpv = ptr1_read(op); OP_ADDA(tmpv);
269 static void op51(unsigned int op, unsigned int imm)
272 tmpv = ptr1_read(op); OP_ANDA(tmpv);
275 static void op61(unsigned int op, unsigned int imm)
278 tmpv = ptr1_read(op); OP_ORA (tmpv);
281 static void op71(unsigned int op, unsigned int imm)
284 tmpv = ptr1_read(op); OP_EORA(tmpv);
288 static void op03(unsigned int op, unsigned int imm)
291 tmpv = ssp->RAM[op & 0x1ff]; OP_LDA (tmpv);
294 static void op13(unsigned int op, unsigned int imm)
297 tmpv = ssp->RAM[op & 0x1ff]; OP_SUBA(tmpv);
300 static void op33(unsigned int op, unsigned int imm)
303 tmpv = ssp->RAM[op & 0x1ff]; OP_CMPA(tmpv);
306 static void op43(unsigned int op, unsigned int imm)
309 tmpv = ssp->RAM[op & 0x1ff]; OP_ADDA(tmpv);
312 static void op53(unsigned int op, unsigned int imm)
315 tmpv = ssp->RAM[op & 0x1ff]; OP_ANDA(tmpv);
318 static void op63(unsigned int op, unsigned int imm)
321 tmpv = ssp->RAM[op & 0x1ff]; OP_ORA (tmpv);
324 static void op73(unsigned int op, unsigned int imm)
327 tmpv = ssp->RAM[op & 0x1ff]; OP_EORA(tmpv);
331 static void op14(unsigned int op, unsigned int imm)
336 static void op34(unsigned int op, unsigned int imm)
341 static void op44(unsigned int op, unsigned int imm)
346 static void op54(unsigned int op, unsigned int imm)
351 static void op64(unsigned int op, unsigned int imm)
356 static void op74(unsigned int op, unsigned int imm)
362 static void op15(unsigned int op, unsigned int imm)
365 tmpv = ptr2_read(op); OP_SUBA(tmpv);
368 static void op35(unsigned int op, unsigned int imm)
371 tmpv = ptr2_read(op); OP_CMPA(tmpv);
374 static void op45(unsigned int op, unsigned int imm)
377 tmpv = ptr2_read(op); OP_ADDA(tmpv);
380 static void op55(unsigned int op, unsigned int imm)
383 tmpv = ptr2_read(op); OP_ANDA(tmpv);
386 static void op65(unsigned int op, unsigned int imm)
389 tmpv = ptr2_read(op); OP_ORA (tmpv);
392 static void op75(unsigned int op, unsigned int imm)
395 tmpv = ptr2_read(op); OP_EORA(tmpv);
399 static void op19(unsigned int op, unsigned int imm)
402 tmpv = rIJ[IJind]; OP_SUBA(tmpv);
405 static void op39(unsigned int op, unsigned int imm)
408 tmpv = rIJ[IJind]; OP_CMPA(tmpv);
411 static void op49(unsigned int op, unsigned int imm)
414 tmpv = rIJ[IJind]; OP_ADDA(tmpv);
417 static void op59(unsigned int op, unsigned int imm)
420 tmpv = rIJ[IJind]; OP_ANDA(tmpv);
423 static void op69(unsigned int op, unsigned int imm)
426 tmpv = rIJ[IJind]; OP_ORA (tmpv);
429 static void op79(unsigned int op, unsigned int imm)
432 tmpv = rIJ[IJind]; OP_EORA(tmpv);
436 static void op1c(unsigned int op, unsigned int imm)
441 static void op3c(unsigned int op, unsigned int imm)
446 static void op4c(unsigned int op, unsigned int imm)
451 static void op5c(unsigned int op, unsigned int imm)
456 static void op6c(unsigned int op, unsigned int imm)
461 static void op7c(unsigned int op, unsigned int imm)
466 typedef void (in_func)(unsigned int op, unsigned int imm);
468 static in_func *in_funcs[0x80] =
470 op00, op01, op02, op03, op04, op05, op06, op07,
471 NULL, op09, op0a, NULL, op0c, op0c, op0c, op0c,
472 op10, op11, NULL, op13, op14, op15, NULL, NULL,
473 NULL, op19, NULL, op1b, op1c, NULL, NULL, NULL,
474 NULL, NULL, NULL, NULL, op24, op25, op26, NULL,
475 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
476 op30, op31, NULL, op33, op34, op35, NULL, NULL,
477 NULL, op39, NULL, NULL, op3c, NULL, NULL, NULL,
478 op40, op41, NULL, op43, op44, op45, NULL, NULL,
479 op48, op49, NULL, op4b, op4c, NULL, NULL, NULL,
480 op50, op51, NULL, op53, op54, op55, NULL, NULL,
481 NULL, op59, NULL, op5b, op5c, NULL, NULL, NULL,
482 op60, op61, NULL, op63, op64, op65, NULL, NULL,
483 NULL, op69, NULL, NULL, op6c, NULL, NULL, NULL,
484 op70, op71, NULL, op73, op74, op75, NULL, NULL,
485 NULL, op79, NULL, NULL, op7c, NULL, NULL, NULL,
488 // -----------------------------------------------------
490 static unsigned int crctable[256] =
492 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
493 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
494 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
495 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
496 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL,
497 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
498 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
499 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
500 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L,
501 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,
502 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L,
503 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
504 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L,
505 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,
506 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,
507 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
508 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,
509 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
510 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,
511 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
512 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,
513 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
514 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,
515 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
516 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,
517 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL,
518 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,
519 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
520 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L,
521 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,
522 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L,
523 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
524 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL,
525 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,
526 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,
527 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
528 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
529 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
530 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,
531 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
532 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,
533 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
534 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,
535 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
536 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,
537 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
538 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
539 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
540 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL,
541 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,
542 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L,
543 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
544 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL,
545 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,
546 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL,
547 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
548 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,
549 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,
550 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L,
551 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
552 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L,
553 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
554 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,
555 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
558 static u32 chksum_crc32 (unsigned char *block, unsigned int length)
564 for (i = 0; i < length; i++)
566 crc = ((crc >> 8) & 0x00FFFFFF) ^ crctable[(crc ^ *block++) & 0xFF];
568 return (crc ^ 0xFFFFFFFF);
571 //static int iram_crcs[32] = { 0, };
573 // -----------------------------------------------------
575 static unsigned char iram_context_map[] =
577 0, 0, 0, 0, 1, 0, 0, 0, // 04
578 0, 0, 0, 0, 0, 0, 2, 0, // 0e
579 0, 0, 0, 0, 0, 3, 0, 4, // 15 17
580 5, 0, 0, 6, 0, 7, 0, 0, // 18 1b 1d
581 8, 9, 0, 0, 0,10, 0, 0, // 20 21 25
582 0, 0, 0, 0, 0, 0, 0, 0,
583 0, 0,11, 0, 0,12, 0, 0, // 32 35
584 13,14, 0, 0, 0, 0, 0, 0 // 38 39
587 static unsigned int checksums[] =
607 static int get_iram_context(void)
609 unsigned char *ir = (unsigned char *)svp->iram_rom;
610 int val1, val = ir[0x083^1] + ir[0x4FA^1] + ir[0x5F7^1] + ir[0x47B^1];
611 int crc = chksum_crc32(svp->iram_rom, 0x800);
612 val1 = iram_context_map[(val>>1)&0x3f];
614 if (crc != checksums[val1] || val1 == 0) {
615 printf("val: %02x PC=%04x\n", (val>>1)&0x3f, rPC);
616 elprintf(EL_ANOMALY, "bad crc: %08x vs %08x", crc, checksums[val1]);
617 //debug_dump2file(name, svp->iram_rom, 0x800);
620 elprintf(EL_ANOMALY, "iram_context: %02i", val1);
624 #define PROGRAM(x) ((unsigned short *)svp->iram_rom)[x]
626 static u32 interp_get_pc(void)
629 unsigned short *pc1 = PC;
632 while (pc1[-1] != 0xfe01) pc1--; // goto current block start
636 for (i = 0; i < 0x5090/2; i++)
637 if (block_table[i] == pc1) break;
638 if (i == 0x5090/2) goto fail;
642 for (i = 0; i < 0x800/2; i++)
643 if (block_table_iram[iram_context][i] == pc1) break;
644 if (i == 0x800/2) goto fail;
647 return i + (PC - pc1);
649 printf("block not found!\n");
656 static void *translate_block(int pc)
658 unsigned int op, op1, icount = 0;
663 //printf("translate %04x -> %04x\n", pc<<1, (tcache_ptr-tcache)<<1);
670 if ((op1 & 0xf) == 4 || (op1 & 0xf) == 6) {
671 op |= PROGRAM(pc++) << 16; // immediate
674 *tcache_ptr = (unsigned int) in_funcs[op1];
675 if (*tcache_ptr == 0) {
676 printf("NULL func! op=%08x (%02x)\n", op, op1);
680 if (op1 == 0x24 || op1 == 0x26 || // call, bra
681 ((op1 == 0 || op1 == 1 || op1 == 4 || op1 == 5 || op1 == 9 || op1 == 0x25) &&
682 (op & 0xf0) == 0x60)) { // ld PC
686 *tcache_ptr++ = 0xfe01;
687 *tcache_ptr++ = 0xfe01; // end of block
688 //printf(" %i inst\n", icount);
690 if (tcache_ptr - tcache > TCACHE_SIZE/4) {
691 printf("tcache overflow!\n");
699 printf("%i blocks, %i bytes\n", nblocks, (tcache_ptr - tcache)*4);
706 // -----------------------------------------------------
708 int ssp1601_dyn_init(void)
710 tcache = tcache_ptr = malloc(TCACHE_SIZE);
711 memset(tcache, 0, sizeof(TCACHE_SIZE));
712 memset(block_table, 0, sizeof(block_table));
713 memset(block_table_iram, 0, sizeof(block_table_iram));
714 *tcache_ptr++ = 0xfe01;
715 *tcache_ptr++ = 0xfe01;
721 void ssp1601_dyn_reset(ssp1601_t *ssp)
723 ssp1601_reset_local(ssp);
727 static void ssp1601_run2(unsigned int *iPC)
730 unsigned int op, op1, imm;
731 while (*iPC != 0xfe01)
737 if ((op1 & 0xf) == 4 || (op1 & 0xf) == 6) rPC++;
738 PC = ((unsigned short *)&op) + 1; /* needed for interpreter */
740 func = (in_func *) *iPC++;
747 void ssp1601_dyn_run(int cycles)
756 iram_context = get_iram_context();
759 if (block_table_iram[iram_context][rPC] == NULL)
760 block_table_iram[iram_context][rPC] = translate_block(rPC);
761 iPC = block_table_iram[iram_context][rPC];
765 if (block_table[rPC] == NULL)
766 block_table[rPC] = translate_block(rPC);
767 iPC = block_table[rPC];
772 //printf("enter @ %04x, PC=%04x\n", (PC - tcache)<<1, rPC<<1);
779 if (pc_old < 0x800/2)
780 rPC += (PC - block_table_iram[iram_context][pc_old]) - 1;
782 rPC += (PC - block_table[pc_old]) - 1;
785 //printf("end @ %04x, PC=%04x\n", (PC - tcache)<<1, rPC<<1);
787 if (pc_old < 0x400) {
789 tcache_ptr = block_table[pc_old];
790 block_table[pc_old] = NULL;
793 if (pc_old >= 0x400 && rPC < 0x400)
795 int i, crc = chksum_crc32(svp->iram_rom, 0x800);
796 for (i = 0; i < 32; i++)
797 if (iram_crcs[i] == crc) break;
800 for (i = 0; i < 32 && iram_crcs[i]; i++);
802 printf("%i IRAMs\n", i+1);
803 sprintf(name, "ir%08x.bin", crc);
804 debug_dump2file(name, svp->iram_rom, 0x800);
806 printf("CRC %08x %08x\n", crc, iram_id);
810 // debug_dump2file("tcache.bin", tcache, (tcache_ptr - tcache) << 1);