svp: some ARM code translation, as calls, broken
[picodrive.git] / Pico / carthw / svp / compiler.c
1 // 187 blocks, 12072 bytes
2 // 14 IRAM blocks
3
4 #include "../../PicoInt.h"
5
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;
11
12 static int had_jump = 0;
13 static int nblocks = 0;
14 static int iram_context = 0;
15
16 #define EMBED_INTERPRETER
17 #define ssp1601_reset ssp1601_reset_local
18 #define ssp1601_run ssp1601_run_local
19
20 #define GET_PC() rPC
21 #define GET_PPC_OFFS() (GET_PC()*2 - 2)
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"
28 #include "gen_arm.c"
29
30 // -----------------------------------------------------
31
32 // ld d, s
33 static void op00(unsigned int op, unsigned int imm)
34 {
35         unsigned int tmpv;
36         PC = ((unsigned short *)&op) + 1; /* FIXME: needed for interpreter */
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)
51 static 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
58 static 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
65 static void op04(unsigned int op, unsigned int imm)
66 {
67         REG_WRITE((op & 0xf0) >> 4, imm);
68 }
69
70 // ld d, ((ri))
71 static 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
78 static void op06(unsigned int op, unsigned int imm)
79 {
80         ptr1_write(op, imm);
81 }
82
83 // ld adr, a
84 static void op07(unsigned int op, unsigned int imm)
85 {
86         ssp->RAM[op & 0x1ff] = rA;
87 }
88
89 // ld d, ri
90 static 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
97 static 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)
103 static void op0c(unsigned int op, unsigned int imm)
104 {
105         rIJ[(op>>8)&7] = op;
106 }
107
108 // call cond, addr
109 static 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)
120 static 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
127 static 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
139 static 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?
161 static 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
171 static 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
181 static 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
190 static 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
200 static 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
210 static 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
220 static 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
230 static 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
240 static 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)
251 static void op11(unsigned int op, unsigned int imm)
252 {
253         unsigned int tmpv;
254         tmpv = ptr1_read(op); OP_SUBA(tmpv);
255 }
256
257 static void op31(unsigned int op, unsigned int imm)
258 {
259         unsigned int tmpv;
260         tmpv = ptr1_read(op); OP_CMPA(tmpv);
261 }
262
263 static void op41(unsigned int op, unsigned int imm)
264 {
265         unsigned int tmpv;
266         tmpv = ptr1_read(op); OP_ADDA(tmpv);
267 }
268
269 static void op51(unsigned int op, unsigned int imm)
270 {
271         unsigned int tmpv;
272         tmpv = ptr1_read(op); OP_ANDA(tmpv);
273 }
274
275 static void op61(unsigned int op, unsigned int imm)
276 {
277         unsigned int tmpv;
278         tmpv = ptr1_read(op); OP_ORA (tmpv);
279 }
280
281 static 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
288 static void op03(unsigned int op, unsigned int imm)
289 {
290         unsigned int tmpv;
291         tmpv = ssp->RAM[op & 0x1ff]; OP_LDA (tmpv);
292 }
293
294 static void op13(unsigned int op, unsigned int imm)
295 {
296         unsigned int tmpv;
297         tmpv = ssp->RAM[op & 0x1ff]; OP_SUBA(tmpv);
298 }
299
300 static void op33(unsigned int op, unsigned int imm)
301 {
302         unsigned int tmpv;
303         tmpv = ssp->RAM[op & 0x1ff]; OP_CMPA(tmpv);
304 }
305
306 static void op43(unsigned int op, unsigned int imm)
307 {
308         unsigned int tmpv;
309         tmpv = ssp->RAM[op & 0x1ff]; OP_ADDA(tmpv);
310 }
311
312 static void op53(unsigned int op, unsigned int imm)
313 {
314         unsigned int tmpv;
315         tmpv = ssp->RAM[op & 0x1ff]; OP_ANDA(tmpv);
316 }
317
318 static void op63(unsigned int op, unsigned int imm)
319 {
320         unsigned int tmpv;
321         tmpv = ssp->RAM[op & 0x1ff]; OP_ORA (tmpv);
322 }
323
324 static 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
331 static void op14(unsigned int op, unsigned int imm)
332 {
333         OP_SUBA(imm);
334 }
335
336 static void op34(unsigned int op, unsigned int imm)
337 {
338         OP_CMPA(imm);
339 }
340
341 static void op44(unsigned int op, unsigned int imm)
342 {
343         OP_ADDA(imm);
344 }
345
346 static void op54(unsigned int op, unsigned int imm)
347 {
348         OP_ANDA(imm);
349 }
350
351 static void op64(unsigned int op, unsigned int imm)
352 {
353         OP_ORA (imm);
354 }
355
356 static void op74(unsigned int op, unsigned int imm)
357 {
358         OP_EORA(imm);
359 }
360
361 // OP a, ((ri))
362 static void op15(unsigned int op, unsigned int imm)
363 {
364         unsigned int tmpv;
365         tmpv = ptr2_read(op); OP_SUBA(tmpv);
366 }
367
368 static void op35(unsigned int op, unsigned int imm)
369 {
370         unsigned int tmpv;
371         tmpv = ptr2_read(op); OP_CMPA(tmpv);
372 }
373
374 static void op45(unsigned int op, unsigned int imm)
375 {
376         unsigned int tmpv;
377         tmpv = ptr2_read(op); OP_ADDA(tmpv);
378 }
379
380 static void op55(unsigned int op, unsigned int imm)
381 {
382         unsigned int tmpv;
383         tmpv = ptr2_read(op); OP_ANDA(tmpv);
384 }
385
386 static void op65(unsigned int op, unsigned int imm)
387 {
388         unsigned int tmpv;
389         tmpv = ptr2_read(op); OP_ORA (tmpv);
390 }
391
392 static 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
399 static void op19(unsigned int op, unsigned int imm)
400 {
401         unsigned int tmpv;
402         tmpv = rIJ[IJind]; OP_SUBA(tmpv);
403 }
404
405 static void op39(unsigned int op, unsigned int imm)
406 {
407         unsigned int tmpv;
408         tmpv = rIJ[IJind]; OP_CMPA(tmpv);
409 }
410
411 static void op49(unsigned int op, unsigned int imm)
412 {
413         unsigned int tmpv;
414         tmpv = rIJ[IJind]; OP_ADDA(tmpv);
415 }
416
417 static void op59(unsigned int op, unsigned int imm)
418 {
419         unsigned int tmpv;
420         tmpv = rIJ[IJind]; OP_ANDA(tmpv);
421 }
422
423 static void op69(unsigned int op, unsigned int imm)
424 {
425         unsigned int tmpv;
426         tmpv = rIJ[IJind]; OP_ORA (tmpv);
427 }
428
429 static 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
436 static void op1c(unsigned int op, unsigned int imm)
437 {
438         OP_SUBA(op & 0xff);
439 }
440
441 static void op3c(unsigned int op, unsigned int imm)
442 {
443         OP_CMPA(op & 0xff);
444 }
445
446 static void op4c(unsigned int op, unsigned int imm)
447 {
448         OP_ADDA(op & 0xff);
449 }
450
451 static void op5c(unsigned int op, unsigned int imm)
452 {
453         OP_ANDA(op & 0xff);
454 }
455
456 static void op6c(unsigned int op, unsigned int imm)
457 {
458         OP_ORA (op & 0xff);
459 }
460
461 static void op7c(unsigned int op, unsigned int imm)
462 {
463         OP_EORA(op & 0xff);
464 }
465
466 typedef void (in_func)(unsigned int op, unsigned int imm);
467
468 static 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
490 static 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
502 static 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];
506         val1 = iram_context_map[(val>>1)&0x3f];
507
508         if (val1 == 0) {
509                 printf("val: %02x PC=%04x\n", (val>>1)&0x3f, rPC);
510                 //debug_dump2file(name, svp->iram_rom, 0x800);
511                 exit(1);
512         }
513 //      elprintf(EL_ANOMALY, "iram_context: %02i", val1);
514         return val1;
515 }
516
517
518 #define PROGRAM(x) ((unsigned short *)svp->iram_rom)[x]
519
520 static void *translate_block(int pc)
521 {
522         unsigned int op, op1, icount = 0;
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
529
530         block_start = tcache_ptr;
531
532         emit_block_prologue();
533
534         //printf("translate %04x -> %04x\n", pc<<1, (tcache_ptr-tcache)<<1);
535         for (;;)
536         {
537                 icount++;
538                 op = PROGRAM(pc++);
539                 op1 = op >> 9;
540
541                 emit_mov_const16(0, op);
542
543                 // need immediate?
544                 if ((op1 & 0xf) == 4 || (op1 & 0xf) == 6) {
545                         emit_mov_const16(1, PROGRAM(pc++)); // immediate
546                 }
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) {
554                         printf("NULL func! op=%08x (%02x)\n", op, op1);
555                         exit(1);
556                 }
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         }
563
564         emit_block_epilogue(block_start, icount + 1);
565         *tcache_ptr++ = 0xffffffff; // end of block
566         //printf("  %i inst\n", icount);
567
568         if (tcache_ptr - tcache > TCACHE_SIZE/4) {
569                 printf("tcache overflow!\n");
570                 fflush(stdout);
571                 exit(1);
572         }
573
574         // stats
575         nblocks++;
576         //if (pc >= 0x400)
577         printf("%i blocks, %i bytes\n", nblocks, (tcache_ptr - tcache)*4);
578
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;
588 }
589
590
591
592 // -----------------------------------------------------
593
594 int ssp1601_dyn_init(void)
595 {
596         tcache = tcache_ptr = malloc(TCACHE_SIZE);
597         if (tcache == NULL) {
598                 printf("oom\n");
599                 exit(1);
600         }
601         memset(tcache, 0, sizeof(TCACHE_SIZE));
602         memset(block_table, 0, sizeof(block_table));
603         memset(block_table_iram, 0, sizeof(block_table_iram));
604         *tcache_ptr++ = 0xffffffff;
605
606         return 0;
607 }
608
609
610 void ssp1601_dyn_reset(ssp1601_t *ssp)
611 {
612         ssp1601_reset_local(ssp);
613 }
614
615 static void handle_caches()
616 {
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
625 }
626
627 void ssp1601_dyn_run(int cycles)
628 {
629         while (cycles > 0)
630         {
631                 void (*trans_entry)(void);
632                 if (rPC < 0x800/2)
633                 {
634                         if (iram_dirty) {
635                                 iram_context = get_iram_context();
636                                 iram_dirty--;
637                         }
638                         if (block_table_iram[iram_context][rPC] == NULL)
639                                 block_table_iram[iram_context][rPC] = translate_block(rPC);
640                         trans_entry = (void *) block_table_iram[iram_context][rPC];
641                 }
642                 else
643                 {
644                         if (block_table[rPC] == NULL)
645                                 block_table[rPC] = translate_block(rPC);
646                         trans_entry = (void *) block_table[rPC];
647                 }
648
649                 had_jump = 0;
650
651                 //printf("enter @ %04x, PC=%04x\n", (PC - tcache)<<1, rPC<<1);
652                 g_cycles = 0;
653                 handle_caches();
654                 trans_entry();
655                 cycles -= g_cycles;
656 /*
657                 if (!had_jump) {
658                         // no jumps
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;
663                 }
664 */
665                 //printf("end   @ %04x, PC=%04x\n", (PC - tcache)<<1, rPC<<1);
666 /*
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) {
679                                 char name[32];
680                                 for (i = 0; i < 32 && iram_crcs[i]; i++);
681                                 iram_crcs[i] = crc;
682                                 printf("%i IRAMs\n", i+1);
683                                 sprintf(name, "ir%08x.bin", crc);
684                                 debug_dump2file(name, svp->iram_rom, 0x800);
685                         }
686                         printf("CRC %08x %08x\n", crc, iram_id);
687                 }
688 */
689         }
690 //      debug_dump2file("tcache.bin", tcache, (tcache_ptr - tcache) << 1);
691 //      exit(1);
692 }
693