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