svp compiler, early stage, works
[picodrive.git] / Pico / carthw / svp / compiler.c
CommitLineData
726bbb3e 1// 187 blocks, 12072 bytes
2// 14 IRAM blocks
3
4#include "../../PicoInt.h"
5
259ed0ea 6#define TCACHE_SIZE (1024*1024)
892b1dd2 7static unsigned int *block_table[0x5090/2];
8static unsigned int *block_table_iram[15][0x800/2];
9static unsigned int *tcache = NULL;
10static unsigned int *tcache_ptr = NULL;
726bbb3e 11
12static int had_jump = 0;
13static int nblocks = 0;
df143b36 14static int iram_context = 0;
726bbb3e 15
16#define EMBED_INTERPRETER
17#define ssp1601_reset ssp1601_reset_local
18#define ssp1601_run ssp1601_run_local
19
5c129565 20#define GET_PC() rPC
21#define GET_PPC_OFFS() (GET_PC()*2 - 2)
726bbb3e 22#define SET_PC(d) { had_jump = 1; rPC = d; } /* must return to dispatcher after this */
23//#define GET_PC() (PC - (unsigned short *)svp->iram_rom)
24//#define GET_PPC_OFFS() ((unsigned int)PC - (unsigned int)svp->iram_rom - 2)
25//#define SET_PC(d) PC = (unsigned short *)svp->iram_rom + d
26
27#include "ssp16.c"
5c129565 28#include "gen_arm.c"
726bbb3e 29
30// -----------------------------------------------------
31
892b1dd2 32// ld d, s
33static void op00(unsigned int op, unsigned int imm)
34{
35 unsigned int tmpv;
259ed0ea 36 PC = ((unsigned short *)(void *)&op) + 1; /* FIXME: needed for interpreter */
892b1dd2 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.
40 read_P(); // update P
41 rA32 = rP.v;
42 }
43 else
44 {
45 tmpv = REG_READ(op & 0x0f);
46 REG_WRITE((op & 0xf0) >> 4, tmpv);
47 }
48}
49
50// ld d, (ri)
51static void op01(unsigned int op, unsigned int imm)
52{
53 unsigned int tmpv;
54 tmpv = ptr1_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv);
55}
56
57// ld (ri), s
58static void op02(unsigned int op, unsigned int imm)
59{
60 unsigned int tmpv;
61 tmpv = REG_READ((op & 0xf0) >> 4); ptr1_write(op, tmpv);
62}
63
64// ldi d, imm
65static void op04(unsigned int op, unsigned int imm)
66{
67 REG_WRITE((op & 0xf0) >> 4, imm);
68}
69
70// ld d, ((ri))
71static void op05(unsigned int op, unsigned int imm)
72{
73 unsigned int tmpv;
74 tmpv = ptr2_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv);
75}
76
77// ldi (ri), imm
78static void op06(unsigned int op, unsigned int imm)
79{
80 ptr1_write(op, imm);
81}
82
83// ld adr, a
84static void op07(unsigned int op, unsigned int imm)
85{
86 ssp->RAM[op & 0x1ff] = rA;
87}
88
89// ld d, ri
90static void op09(unsigned int op, unsigned int imm)
91{
92 unsigned int tmpv;
93 tmpv = rIJ[(op&3)|((op>>6)&4)]; REG_WRITE((op & 0xf0) >> 4, tmpv);
94}
95
96// ld ri, s
97static void op0a(unsigned int op, unsigned int imm)
98{
99 rIJ[(op&3)|((op>>6)&4)] = REG_READ((op & 0xf0) >> 4);
100}
101
102// ldi ri, simm (also op0d op0e op0f)
103static void op0c(unsigned int op, unsigned int imm)
104{
105 rIJ[(op>>8)&7] = op;
106}
107
108// call cond, addr
109static void op24(unsigned int op, unsigned int imm)
110{
111 int cond = 0;
112 do {
113 COND_CHECK
259ed0ea 114 if (cond) { int new_PC = imm; write_STACK(GET_PC()); SET_PC(new_PC); }
892b1dd2 115 }
116 while (0);
117}
118
119// ld d, (a)
120static void op25(unsigned int op, unsigned int imm)
121{
122 unsigned int tmpv;
123 tmpv = ((unsigned short *)svp->iram_rom)[rA]; REG_WRITE((op & 0xf0) >> 4, tmpv);
124}
125
126// bra cond, addr
127static void op26(unsigned int op, unsigned int imm)
128{
129 do
130 {
131 int cond = 0;
132 COND_CHECK
259ed0ea 133 if (cond) SET_PC(imm);
892b1dd2 134 }
259ed0ea 135 while (0);
892b1dd2 136}
137
138// mod cond, op
139static void op48(unsigned int op, unsigned int imm)
140{
141 do
142 {
143 int cond = 0;
144 COND_CHECK
145 if (cond) {
146 switch (op & 7) {
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());
153 }
154 UPD_ACC_ZN // ?
155 }
156 }
157 while(0);
158}
159
160// mpys?
161static void op1b(unsigned int op, unsigned int imm)
162{
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
168}
169
170// mpya (rj), (ri), b
171static void op4b(unsigned int op, unsigned int imm)
172{
173 read_P(); // update P
174 rA32 += rP.v; // confirmed to be 32bit
175 UPD_ACC_ZN // ?
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
178}
179
180// mld (rj), (ri), b
181static void op5b(unsigned int op, unsigned int imm)
182{
183 rA32 = 0;
184 rST &= 0x0fff; // ?
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
187}
188
189// OP a, s
190static void op10(unsigned int op, unsigned int imm)
191{
192 do
193 {
194 unsigned int tmpv;
195 OP_CHECK32(OP_SUBA32); tmpv = REG_READ(op & 0x0f); OP_SUBA(tmpv);
196 }
197 while(0);
198}
199
200static void op30(unsigned int op, unsigned int imm)
201{
202 do
203 {
204 unsigned int tmpv;
205 OP_CHECK32(OP_CMPA32); tmpv = REG_READ(op & 0x0f); OP_CMPA(tmpv);
206 }
207 while(0);
208}
209
210static void op40(unsigned int op, unsigned int imm)
211{
212 do
213 {
214 unsigned int tmpv;
215 OP_CHECK32(OP_ADDA32); tmpv = REG_READ(op & 0x0f); OP_ADDA(tmpv);
216 }
217 while(0);
218}
219
220static void op50(unsigned int op, unsigned int imm)
221{
222 do
223 {
224 unsigned int tmpv;
225 OP_CHECK32(OP_ANDA32); tmpv = REG_READ(op & 0x0f); OP_ANDA(tmpv);
226 }
227 while(0);
228}
229
230static void op60(unsigned int op, unsigned int imm)
231{
232 do
233 {
234 unsigned int tmpv;
235 OP_CHECK32(OP_ORA32 ); tmpv = REG_READ(op & 0x0f); OP_ORA (tmpv);
236 }
237 while(0);
238}
239
240static void op70(unsigned int op, unsigned int imm)
241{
242 do
243 {
244 unsigned int tmpv;
245 OP_CHECK32(OP_EORA32); tmpv = REG_READ(op & 0x0f); OP_EORA(tmpv);
246 }
247 while(0);
248}
249
250// OP a, (ri)
251static void op11(unsigned int op, unsigned int imm)
252{
253 unsigned int tmpv;
254 tmpv = ptr1_read(op); OP_SUBA(tmpv);
255}
256
257static void op31(unsigned int op, unsigned int imm)
258{
259 unsigned int tmpv;
260 tmpv = ptr1_read(op); OP_CMPA(tmpv);
261}
262
263static void op41(unsigned int op, unsigned int imm)
264{
265 unsigned int tmpv;
266 tmpv = ptr1_read(op); OP_ADDA(tmpv);
267}
268
269static void op51(unsigned int op, unsigned int imm)
270{
271 unsigned int tmpv;
272 tmpv = ptr1_read(op); OP_ANDA(tmpv);
273}
274
275static void op61(unsigned int op, unsigned int imm)
276{
277 unsigned int tmpv;
278 tmpv = ptr1_read(op); OP_ORA (tmpv);
279}
280
281static void op71(unsigned int op, unsigned int imm)
282{
283 unsigned int tmpv;
284 tmpv = ptr1_read(op); OP_EORA(tmpv);
285}
286
287// OP a, adr
288static void op03(unsigned int op, unsigned int imm)
289{
290 unsigned int tmpv;
291 tmpv = ssp->RAM[op & 0x1ff]; OP_LDA (tmpv);
292}
293
294static void op13(unsigned int op, unsigned int imm)
295{
296 unsigned int tmpv;
297 tmpv = ssp->RAM[op & 0x1ff]; OP_SUBA(tmpv);
298}
299
300static void op33(unsigned int op, unsigned int imm)
301{
302 unsigned int tmpv;
303 tmpv = ssp->RAM[op & 0x1ff]; OP_CMPA(tmpv);
304}
305
306static void op43(unsigned int op, unsigned int imm)
307{
308 unsigned int tmpv;
309 tmpv = ssp->RAM[op & 0x1ff]; OP_ADDA(tmpv);
310}
311
312static void op53(unsigned int op, unsigned int imm)
313{
314 unsigned int tmpv;
315 tmpv = ssp->RAM[op & 0x1ff]; OP_ANDA(tmpv);
316}
317
318static void op63(unsigned int op, unsigned int imm)
319{
320 unsigned int tmpv;
321 tmpv = ssp->RAM[op & 0x1ff]; OP_ORA (tmpv);
322}
323
324static void op73(unsigned int op, unsigned int imm)
325{
326 unsigned int tmpv;
327 tmpv = ssp->RAM[op & 0x1ff]; OP_EORA(tmpv);
328}
329
330// OP a, imm
331static void op14(unsigned int op, unsigned int imm)
332{
333 OP_SUBA(imm);
334}
335
336static void op34(unsigned int op, unsigned int imm)
337{
338 OP_CMPA(imm);
339}
340
341static void op44(unsigned int op, unsigned int imm)
342{
343 OP_ADDA(imm);
344}
345
346static void op54(unsigned int op, unsigned int imm)
347{
348 OP_ANDA(imm);
349}
350
351static void op64(unsigned int op, unsigned int imm)
352{
353 OP_ORA (imm);
354}
355
356static void op74(unsigned int op, unsigned int imm)
357{
358 OP_EORA(imm);
359}
360
361// OP a, ((ri))
362static void op15(unsigned int op, unsigned int imm)
363{
364 unsigned int tmpv;
365 tmpv = ptr2_read(op); OP_SUBA(tmpv);
366}
367
368static void op35(unsigned int op, unsigned int imm)
369{
370 unsigned int tmpv;
371 tmpv = ptr2_read(op); OP_CMPA(tmpv);
372}
373
374static void op45(unsigned int op, unsigned int imm)
375{
376 unsigned int tmpv;
377 tmpv = ptr2_read(op); OP_ADDA(tmpv);
378}
379
380static void op55(unsigned int op, unsigned int imm)
381{
382 unsigned int tmpv;
383 tmpv = ptr2_read(op); OP_ANDA(tmpv);
384}
385
386static void op65(unsigned int op, unsigned int imm)
387{
388 unsigned int tmpv;
389 tmpv = ptr2_read(op); OP_ORA (tmpv);
390}
391
392static void op75(unsigned int op, unsigned int imm)
393{
394 unsigned int tmpv;
395 tmpv = ptr2_read(op); OP_EORA(tmpv);
396}
397
398// OP a, ri
399static void op19(unsigned int op, unsigned int imm)
400{
401 unsigned int tmpv;
402 tmpv = rIJ[IJind]; OP_SUBA(tmpv);
403}
404
405static void op39(unsigned int op, unsigned int imm)
406{
407 unsigned int tmpv;
408 tmpv = rIJ[IJind]; OP_CMPA(tmpv);
409}
410
411static void op49(unsigned int op, unsigned int imm)
412{
413 unsigned int tmpv;
414 tmpv = rIJ[IJind]; OP_ADDA(tmpv);
415}
416
417static void op59(unsigned int op, unsigned int imm)
418{
419 unsigned int tmpv;
420 tmpv = rIJ[IJind]; OP_ANDA(tmpv);
421}
422
423static void op69(unsigned int op, unsigned int imm)
424{
425 unsigned int tmpv;
426 tmpv = rIJ[IJind]; OP_ORA (tmpv);
427}
428
429static void op79(unsigned int op, unsigned int imm)
430{
431 unsigned int tmpv;
432 tmpv = rIJ[IJind]; OP_EORA(tmpv);
433}
434
435// OP simm
436static void op1c(unsigned int op, unsigned int imm)
437{
438 OP_SUBA(op & 0xff);
439}
440
441static void op3c(unsigned int op, unsigned int imm)
442{
443 OP_CMPA(op & 0xff);
444}
445
446static void op4c(unsigned int op, unsigned int imm)
447{
448 OP_ADDA(op & 0xff);
449}
450
451static void op5c(unsigned int op, unsigned int imm)
452{
453 OP_ANDA(op & 0xff);
454}
455
456static void op6c(unsigned int op, unsigned int imm)
457{
458 OP_ORA (op & 0xff);
459}
460
461static void op7c(unsigned int op, unsigned int imm)
462{
463 OP_EORA(op & 0xff);
464}
465
466typedef void (in_func)(unsigned int op, unsigned int imm);
467
468static in_func *in_funcs[0x80] =
469{
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,
486};
487
488// -----------------------------------------------------
489
df143b36 490static unsigned char iram_context_map[] =
491{
492 0, 0, 0, 0, 1, 0, 0, 0, // 04
493 0, 0, 0, 0, 0, 0, 2, 0, // 0e
494 0, 0, 0, 0, 0, 3, 0, 4, // 15 17
495 5, 0, 0, 6, 0, 7, 0, 0, // 18 1b 1d
496 8, 9, 0, 0, 0,10, 0, 0, // 20 21 25
497 0, 0, 0, 0, 0, 0, 0, 0,
498 0, 0,11, 0, 0,12, 0, 0, // 32 35
499 13,14, 0, 0, 0, 0, 0, 0 // 38 39
500};
501
df143b36 502static int get_iram_context(void)
503{
504 unsigned char *ir = (unsigned char *)svp->iram_rom;
505 int val1, val = ir[0x083^1] + ir[0x4FA^1] + ir[0x5F7^1] + ir[0x47B^1];
df143b36 506 val1 = iram_context_map[(val>>1)&0x3f];
507
5c129565 508 if (val1 == 0) {
df143b36 509 printf("val: %02x PC=%04x\n", (val>>1)&0x3f, rPC);
df143b36 510 //debug_dump2file(name, svp->iram_rom, 0x800);
511 exit(1);
512 }
5c129565 513// elprintf(EL_ANOMALY, "iram_context: %02i", val1);
df143b36 514 return val1;
515}
516
726bbb3e 517
5c129565 518#define PROGRAM(x) ((unsigned short *)svp->iram_rom)[x]
726bbb3e 519
df143b36 520static void *translate_block(int pc)
726bbb3e 521{
892b1dd2 522 unsigned int op, op1, icount = 0;
5c129565 523 unsigned int *block_start;
524
525 // create .pool
526 *tcache_ptr++ = (u32) &g_cycles; // -3 g_cycles
527 *tcache_ptr++ = (u32) &ssp->gr[SSP_PC].v; // -2 ptr to rPC
528 *tcache_ptr++ = (u32) in_funcs; // -1 func pool
726bbb3e 529
259ed0ea 530 printf("translate %04x -> %04x\n", pc<<1, (tcache_ptr-tcache)<<2);
5c129565 531 block_start = tcache_ptr;
532
533 emit_block_prologue();
726bbb3e 534
259ed0ea 535 for (; icount < 100;)
726bbb3e 536 {
892b1dd2 537 icount++;
259ed0ea 538 //printf(" insn #%i\n", icount);
726bbb3e 539 op = PROGRAM(pc++);
540 op1 = op >> 9;
5c129565 541
259ed0ea 542 emit_mov_const(0, op);
5c129565 543
726bbb3e 544 // need immediate?
545 if ((op1 & 0xf) == 4 || (op1 & 0xf) == 6) {
259ed0ea 546 emit_mov_const(1, PROGRAM(pc++)); // immediate
726bbb3e 547 }
5c129565 548
549 // dump PC
550 emit_pc_inc(block_start, pc);
551
552 emit_call(block_start, op1);
553
554 if (in_funcs[op1] == NULL) {
892b1dd2 555 printf("NULL func! op=%08x (%02x)\n", op, op1);
556 exit(1);
557 }
726bbb3e 558 if (op1 == 0x24 || op1 == 0x26 || // call, bra
559 ((op1 == 0 || op1 == 1 || op1 == 4 || op1 == 5 || op1 == 9 || op1 == 0x25) &&
560 (op & 0xf0) == 0x60)) { // ld PC
561 break;
562 }
563 }
5c129565 564
565 emit_block_epilogue(block_start, icount + 1);
566 *tcache_ptr++ = 0xffffffff; // end of block
726bbb3e 567 //printf(" %i inst\n", icount);
568
892b1dd2 569 if (tcache_ptr - tcache > TCACHE_SIZE/4) {
726bbb3e 570 printf("tcache overflow!\n");
571 fflush(stdout);
572 exit(1);
573 }
574
575 // stats
576 nblocks++;
df143b36 577 //if (pc >= 0x400)
892b1dd2 578 printf("%i blocks, %i bytes\n", nblocks, (tcache_ptr - tcache)*4);
259ed0ea 579 //printf("%p %p\n", tcache_ptr, emit_block_epilogue);
df143b36 580
5c129565 581#if 0
582 {
583 FILE *f = fopen("tcache.bin", "wb");
584 fwrite(tcache, 1, (tcache_ptr - tcache)*4, f);
585 fclose(f);
586 }
587 exit(0);
588#endif
259ed0ea 589
590 handle_caches();
591
5c129565 592 return block_start;
726bbb3e 593}
594
595
596
597// -----------------------------------------------------
598
599int ssp1601_dyn_init(void)
600{
601 tcache = tcache_ptr = malloc(TCACHE_SIZE);
5c129565 602 if (tcache == NULL) {
603 printf("oom\n");
604 exit(1);
605 }
726bbb3e 606 memset(tcache, 0, sizeof(TCACHE_SIZE));
607 memset(block_table, 0, sizeof(block_table));
df143b36 608 memset(block_table_iram, 0, sizeof(block_table_iram));
5c129565 609 *tcache_ptr++ = 0xffffffff;
726bbb3e 610
611 return 0;
612}
613
614
615void ssp1601_dyn_reset(ssp1601_t *ssp)
616{
617 ssp1601_reset_local(ssp);
618}
619
726bbb3e 620void ssp1601_dyn_run(int cycles)
621{
622 while (cycles > 0)
623 {
5c129565 624 void (*trans_entry)(void);
df143b36 625 if (rPC < 0x800/2)
626 {
627 if (iram_dirty) {
628 iram_context = get_iram_context();
892b1dd2 629 iram_dirty--;
df143b36 630 }
631 if (block_table_iram[iram_context][rPC] == NULL)
632 block_table_iram[iram_context][rPC] = translate_block(rPC);
5c129565 633 trans_entry = (void *) block_table_iram[iram_context][rPC];
df143b36 634 }
635 else
636 {
637 if (block_table[rPC] == NULL)
638 block_table[rPC] = translate_block(rPC);
5c129565 639 trans_entry = (void *) block_table[rPC];
df143b36 640 }
726bbb3e 641
726bbb3e 642 had_jump = 0;
643
644 //printf("enter @ %04x, PC=%04x\n", (PC - tcache)<<1, rPC<<1);
892b1dd2 645 g_cycles = 0;
259ed0ea 646 //printf("enter %04x\n", rPC);
5c129565 647 trans_entry();
259ed0ea 648 //printf("leave %04x\n", rPC);
5c129565 649 cycles -= g_cycles;
892b1dd2 650/*
726bbb3e 651 if (!had_jump) {
652 // no jumps
df143b36 653 if (pc_old < 0x800/2)
654 rPC += (PC - block_table_iram[iram_context][pc_old]) - 1;
655 else
656 rPC += (PC - block_table[pc_old]) - 1;
726bbb3e 657 }
892b1dd2 658*/
726bbb3e 659 //printf("end @ %04x, PC=%04x\n", (PC - tcache)<<1, rPC<<1);
df143b36 660/*
726bbb3e 661 if (pc_old < 0x400) {
662 // flush IRAM cache
663 tcache_ptr = block_table[pc_old];
664 block_table[pc_old] = NULL;
665 nblocks--;
666 }
667 if (pc_old >= 0x400 && rPC < 0x400)
668 {
669 int i, crc = chksum_crc32(svp->iram_rom, 0x800);
670 for (i = 0; i < 32; i++)
671 if (iram_crcs[i] == crc) break;
672 if (i == 32) {
df143b36 673 char name[32];
726bbb3e 674 for (i = 0; i < 32 && iram_crcs[i]; i++);
675 iram_crcs[i] = crc;
676 printf("%i IRAMs\n", i+1);
df143b36 677 sprintf(name, "ir%08x.bin", crc);
678 debug_dump2file(name, svp->iram_rom, 0x800);
726bbb3e 679 }
12f0f94d 680 printf("CRC %08x %08x\n", crc, iram_id);
726bbb3e 681 }
df143b36 682*/
726bbb3e 683 }
684// debug_dump2file("tcache.bin", tcache, (tcache_ptr - tcache) << 1);
685// exit(1);
686}
687