svp: some ARM code translation, as calls, broken
[picodrive.git] / Pico / carthw / svp / compiler.c
CommitLineData
726bbb3e 1// 187 blocks, 12072 bytes
2// 14 IRAM blocks
3
4#include "../../PicoInt.h"
5
6#define TCACHE_SIZE (256*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;
5c129565 36 PC = ((unsigned short *)&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
114 if (cond) { int new_PC = imm; write_STACK(GET_PC()); write_PC(new_PC); }
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
133 if (cond) write_PC(imm);
134 }
135 while(0);
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
5c129565 530 block_start = tcache_ptr;
531
532 emit_block_prologue();
726bbb3e 533
534 //printf("translate %04x -> %04x\n", pc<<1, (tcache_ptr-tcache)<<1);
535 for (;;)
536 {
892b1dd2 537 icount++;
726bbb3e 538 op = PROGRAM(pc++);
539 op1 = op >> 9;
5c129565 540
541 emit_mov_const16(0, op);
542
726bbb3e 543 // need immediate?
544 if ((op1 & 0xf) == 4 || (op1 & 0xf) == 6) {
5c129565 545 emit_mov_const16(1, PROGRAM(pc++)); // immediate
726bbb3e 546 }
5c129565 547
548 // dump PC
549 emit_pc_inc(block_start, pc);
550
551 emit_call(block_start, op1);
552
553 if (in_funcs[op1] == NULL) {
892b1dd2 554 printf("NULL func! op=%08x (%02x)\n", op, op1);
555 exit(1);
556 }
726bbb3e 557 if (op1 == 0x24 || op1 == 0x26 || // call, bra
558 ((op1 == 0 || op1 == 1 || op1 == 4 || op1 == 5 || op1 == 9 || op1 == 0x25) &&
559 (op & 0xf0) == 0x60)) { // ld PC
560 break;
561 }
562 }
5c129565 563
564 emit_block_epilogue(block_start, icount + 1);
565 *tcache_ptr++ = 0xffffffff; // end of block
726bbb3e 566 //printf(" %i inst\n", icount);
567
892b1dd2 568 if (tcache_ptr - tcache > TCACHE_SIZE/4) {
726bbb3e 569 printf("tcache overflow!\n");
570 fflush(stdout);
571 exit(1);
572 }
573
574 // stats
575 nblocks++;
df143b36 576 //if (pc >= 0x400)
892b1dd2 577 printf("%i blocks, %i bytes\n", nblocks, (tcache_ptr - tcache)*4);
df143b36 578
5c129565 579#if 0
580 {
581 FILE *f = fopen("tcache.bin", "wb");
582 fwrite(tcache, 1, (tcache_ptr - tcache)*4, f);
583 fclose(f);
584 }
585 exit(0);
586#endif
587 return block_start;
726bbb3e 588}
589
590
591
592// -----------------------------------------------------
593
594int ssp1601_dyn_init(void)
595{
596 tcache = tcache_ptr = malloc(TCACHE_SIZE);
5c129565 597 if (tcache == NULL) {
598 printf("oom\n");
599 exit(1);
600 }
726bbb3e 601 memset(tcache, 0, sizeof(TCACHE_SIZE));
602 memset(block_table, 0, sizeof(block_table));
df143b36 603 memset(block_table_iram, 0, sizeof(block_table_iram));
5c129565 604 *tcache_ptr++ = 0xffffffff;
726bbb3e 605
606 return 0;
607}
608
609
610void ssp1601_dyn_reset(ssp1601_t *ssp)
611{
612 ssp1601_reset_local(ssp);
613}
614
5c129565 615static void handle_caches()
892b1dd2 616{
5c129565 617#ifdef ARM
618 extern void flush_inval_dcache(const void *start_addr, const void *end_addr);
619 extern void flush_inval_icache(const void *start_addr, const void *end_addr);
620 flush_inval_dcache(tcache, tcache_ptr);
621 flush_inval_icache(tcache, tcache_ptr);
622#else
623#error wth
624#endif
892b1dd2 625}
626
726bbb3e 627void ssp1601_dyn_run(int cycles)
628{
629 while (cycles > 0)
630 {
5c129565 631 void (*trans_entry)(void);
df143b36 632 if (rPC < 0x800/2)
633 {
634 if (iram_dirty) {
635 iram_context = get_iram_context();
892b1dd2 636 iram_dirty--;
df143b36 637 }
638 if (block_table_iram[iram_context][rPC] == NULL)
639 block_table_iram[iram_context][rPC] = translate_block(rPC);
5c129565 640 trans_entry = (void *) block_table_iram[iram_context][rPC];
df143b36 641 }
642 else
643 {
644 if (block_table[rPC] == NULL)
645 block_table[rPC] = translate_block(rPC);
5c129565 646 trans_entry = (void *) block_table[rPC];
df143b36 647 }
726bbb3e 648
726bbb3e 649 had_jump = 0;
650
651 //printf("enter @ %04x, PC=%04x\n", (PC - tcache)<<1, rPC<<1);
892b1dd2 652 g_cycles = 0;
5c129565 653 handle_caches();
654 trans_entry();
655 cycles -= g_cycles;
892b1dd2 656/*
726bbb3e 657 if (!had_jump) {
658 // no jumps
df143b36 659 if (pc_old < 0x800/2)
660 rPC += (PC - block_table_iram[iram_context][pc_old]) - 1;
661 else
662 rPC += (PC - block_table[pc_old]) - 1;
726bbb3e 663 }
892b1dd2 664*/
726bbb3e 665 //printf("end @ %04x, PC=%04x\n", (PC - tcache)<<1, rPC<<1);
df143b36 666/*
726bbb3e 667 if (pc_old < 0x400) {
668 // flush IRAM cache
669 tcache_ptr = block_table[pc_old];
670 block_table[pc_old] = NULL;
671 nblocks--;
672 }
673 if (pc_old >= 0x400 && rPC < 0x400)
674 {
675 int i, crc = chksum_crc32(svp->iram_rom, 0x800);
676 for (i = 0; i < 32; i++)
677 if (iram_crcs[i] == crc) break;
678 if (i == 32) {
df143b36 679 char name[32];
726bbb3e 680 for (i = 0; i < 32 && iram_crcs[i]; i++);
681 iram_crcs[i] = crc;
682 printf("%i IRAMs\n", i+1);
df143b36 683 sprintf(name, "ir%08x.bin", crc);
684 debug_dump2file(name, svp->iram_rom, 0x800);
726bbb3e 685 }
12f0f94d 686 printf("CRC %08x %08x\n", crc, iram_id);
726bbb3e 687 }
df143b36 688*/
726bbb3e 689 }
690// debug_dump2file("tcache.bin", tcache, (tcache_ptr - tcache) << 1);
691// exit(1);
692}
693