svp compiler direct calls
[picodrive.git] / Pico / carthw / svp / compiler.c
CommitLineData
726bbb3e 1// 187 blocks, 12072 bytes
2// 14 IRAM blocks
3
4#include "../../PicoInt.h"
e807ac75 5#include "compiler.h"
726bbb3e 6
892b1dd2 7static unsigned int *block_table[0x5090/2];
8static unsigned int *block_table_iram[15][0x800/2];
892b1dd2 9static unsigned int *tcache_ptr = NULL;
726bbb3e 10
11static int had_jump = 0;
12static int nblocks = 0;
df143b36 13static int iram_context = 0;
726bbb3e 14
15#define EMBED_INTERPRETER
16#define ssp1601_reset ssp1601_reset_local
17#define ssp1601_run ssp1601_run_local
18
5c129565 19#define GET_PC() rPC
20#define GET_PPC_OFFS() (GET_PC()*2 - 2)
726bbb3e 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"
5c129565 27#include "gen_arm.c"
726bbb3e 28
29// -----------------------------------------------------
30
892b1dd2 31// ld d, s
32static void op00(unsigned int op, unsigned int imm)
33{
34 unsigned int tmpv;
259ed0ea 35 PC = ((unsigned short *)(void *)&op) + 1; /* FIXME: needed for interpreter */
892b1dd2 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)
50static 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
57static 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
64static void op04(unsigned int op, unsigned int imm)
65{
66 REG_WRITE((op & 0xf0) >> 4, imm);
67}
68
69// ld d, ((ri))
70static 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
77static void op06(unsigned int op, unsigned int imm)
78{
79 ptr1_write(op, imm);
80}
81
82// ld adr, a
83static void op07(unsigned int op, unsigned int imm)
84{
85 ssp->RAM[op & 0x1ff] = rA;
86}
87
88// ld d, ri
89static 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
96static 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)
102static void op0c(unsigned int op, unsigned int imm)
103{
104 rIJ[(op>>8)&7] = op;
105}
106
107// call cond, addr
108static void op24(unsigned int op, unsigned int imm)
109{
110 int cond = 0;
111 do {
112 COND_CHECK
259ed0ea 113 if (cond) { int new_PC = imm; write_STACK(GET_PC()); SET_PC(new_PC); }
892b1dd2 114 }
115 while (0);
116}
117
118// ld d, (a)
119static 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
126static void op26(unsigned int op, unsigned int imm)
127{
128 do
129 {
130 int cond = 0;
131 COND_CHECK
259ed0ea 132 if (cond) SET_PC(imm);
892b1dd2 133 }
259ed0ea 134 while (0);
892b1dd2 135}
136
137// mod cond, op
138static 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?
160static 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
170static 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
180static 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
189static 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
199static 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
209static 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
219static 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
229static 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
239static 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)
250static void op11(unsigned int op, unsigned int imm)
251{
252 unsigned int tmpv;
253 tmpv = ptr1_read(op); OP_SUBA(tmpv);
254}
255
256static void op31(unsigned int op, unsigned int imm)
257{
258 unsigned int tmpv;
259 tmpv = ptr1_read(op); OP_CMPA(tmpv);
260}
261
262static void op41(unsigned int op, unsigned int imm)
263{
264 unsigned int tmpv;
265 tmpv = ptr1_read(op); OP_ADDA(tmpv);
266}
267
268static void op51(unsigned int op, unsigned int imm)
269{
270 unsigned int tmpv;
271 tmpv = ptr1_read(op); OP_ANDA(tmpv);
272}
273
274static void op61(unsigned int op, unsigned int imm)
275{
276 unsigned int tmpv;
277 tmpv = ptr1_read(op); OP_ORA (tmpv);
278}
279
280static 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
287static void op03(unsigned int op, unsigned int imm)
288{
289 unsigned int tmpv;
290 tmpv = ssp->RAM[op & 0x1ff]; OP_LDA (tmpv);
291}
292
293static void op13(unsigned int op, unsigned int imm)
294{
295 unsigned int tmpv;
296 tmpv = ssp->RAM[op & 0x1ff]; OP_SUBA(tmpv);
297}
298
299static void op33(unsigned int op, unsigned int imm)
300{
301 unsigned int tmpv;
302 tmpv = ssp->RAM[op & 0x1ff]; OP_CMPA(tmpv);
303}
304
305static void op43(unsigned int op, unsigned int imm)
306{
307 unsigned int tmpv;
308 tmpv = ssp->RAM[op & 0x1ff]; OP_ADDA(tmpv);
309}
310
311static void op53(unsigned int op, unsigned int imm)
312{
313 unsigned int tmpv;
314 tmpv = ssp->RAM[op & 0x1ff]; OP_ANDA(tmpv);
315}
316
317static void op63(unsigned int op, unsigned int imm)
318{
319 unsigned int tmpv;
320 tmpv = ssp->RAM[op & 0x1ff]; OP_ORA (tmpv);
321}
322
323static 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
330static void op14(unsigned int op, unsigned int imm)
331{
332 OP_SUBA(imm);
333}
334
335static void op34(unsigned int op, unsigned int imm)
336{
337 OP_CMPA(imm);
338}
339
340static void op44(unsigned int op, unsigned int imm)
341{
342 OP_ADDA(imm);
343}
344
345static void op54(unsigned int op, unsigned int imm)
346{
347 OP_ANDA(imm);
348}
349
350static void op64(unsigned int op, unsigned int imm)
351{
352 OP_ORA (imm);
353}
354
355static void op74(unsigned int op, unsigned int imm)
356{
357 OP_EORA(imm);
358}
359
360// OP a, ((ri))
361static void op15(unsigned int op, unsigned int imm)
362{
363 unsigned int tmpv;
364 tmpv = ptr2_read(op); OP_SUBA(tmpv);
365}
366
367static void op35(unsigned int op, unsigned int imm)
368{
369 unsigned int tmpv;
370 tmpv = ptr2_read(op); OP_CMPA(tmpv);
371}
372
373static void op45(unsigned int op, unsigned int imm)
374{
375 unsigned int tmpv;
376 tmpv = ptr2_read(op); OP_ADDA(tmpv);
377}
378
379static void op55(unsigned int op, unsigned int imm)
380{
381 unsigned int tmpv;
382 tmpv = ptr2_read(op); OP_ANDA(tmpv);
383}
384
385static void op65(unsigned int op, unsigned int imm)
386{
387 unsigned int tmpv;
388 tmpv = ptr2_read(op); OP_ORA (tmpv);
389}
390
391static 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
398static void op19(unsigned int op, unsigned int imm)
399{
400 unsigned int tmpv;
401 tmpv = rIJ[IJind]; OP_SUBA(tmpv);
402}
403
404static void op39(unsigned int op, unsigned int imm)
405{
406 unsigned int tmpv;
407 tmpv = rIJ[IJind]; OP_CMPA(tmpv);
408}
409
410static void op49(unsigned int op, unsigned int imm)
411{
412 unsigned int tmpv;
413 tmpv = rIJ[IJind]; OP_ADDA(tmpv);
414}
415
416static void op59(unsigned int op, unsigned int imm)
417{
418 unsigned int tmpv;
419 tmpv = rIJ[IJind]; OP_ANDA(tmpv);
420}
421
422static void op69(unsigned int op, unsigned int imm)
423{
424 unsigned int tmpv;
425 tmpv = rIJ[IJind]; OP_ORA (tmpv);
426}
427
428static 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
435static void op1c(unsigned int op, unsigned int imm)
436{
437 OP_SUBA(op & 0xff);
438}
439
440static void op3c(unsigned int op, unsigned int imm)
441{
442 OP_CMPA(op & 0xff);
443}
444
445static void op4c(unsigned int op, unsigned int imm)
446{
447 OP_ADDA(op & 0xff);
448}
449
450static void op5c(unsigned int op, unsigned int imm)
451{
452 OP_ANDA(op & 0xff);
453}
454
455static void op6c(unsigned int op, unsigned int imm)
456{
457 OP_ORA (op & 0xff);
458}
459
460static void op7c(unsigned int op, unsigned int imm)
461{
462 OP_EORA(op & 0xff);
463}
464
465typedef void (in_func)(unsigned int op, unsigned int imm);
466
467static 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
df143b36 489static 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
df143b36 501static 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];
df143b36 505 val1 = iram_context_map[(val>>1)&0x3f];
506
5c129565 507 if (val1 == 0) {
df143b36 508 printf("val: %02x PC=%04x\n", (val>>1)&0x3f, rPC);
df143b36 509 //debug_dump2file(name, svp->iram_rom, 0x800);
510 exit(1);
511 }
5c129565 512// elprintf(EL_ANOMALY, "iram_context: %02i", val1);
df143b36 513 return val1;
514}
515
726bbb3e 516
5c129565 517#define PROGRAM(x) ((unsigned short *)svp->iram_rom)[x]
726bbb3e 518
e807ac75 519static 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
df143b36 530static void *translate_block(int pc)
726bbb3e 531{
e807ac75 532 unsigned int op, op1, imm, ccount = 0;
5c129565 533 unsigned int *block_start;
e807ac75 534 int ret;
5c129565 535
536 // create .pool
e807ac75 537 //*tcache_ptr++ = (u32) in_funcs; // -1 func pool
726bbb3e 538
259ed0ea 539 printf("translate %04x -> %04x\n", pc<<1, (tcache_ptr-tcache)<<2);
5c129565 540 block_start = tcache_ptr;
541
542 emit_block_prologue();
726bbb3e 543
e807ac75 544 for (; ccount < 100;)
726bbb3e 545 {
259ed0ea 546 //printf(" insn #%i\n", icount);
726bbb3e 547 op = PROGRAM(pc++);
548 op1 = op >> 9;
e807ac75 549 imm = (u32)-1;
5c129565 550
e807ac75 551 if ((op1 & 0xf) == 4 || (op1 & 0xf) == 6)
552 imm = PROGRAM(pc++); // immediate
5c129565 553
e807ac75 554 ret = translate_op(op, &pc);
555 if (ret <= 0)
556 {
557 emit_mov_const(0, op);
5c129565 558
e807ac75 559 // need immediate?
560 if (imm != (u32)-1)
561 emit_mov_const(1, imm);
5c129565 562
e807ac75 563 // dump PC
564 emit_pc_dump(pc);
5c129565 565
e807ac75 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++;
892b1dd2 573 }
e807ac75 574 else
575 ccount += ret;
576
726bbb3e 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 }
5c129565 583
e807ac75 584 emit_block_epilogue(ccount + 1);
5c129565 585 *tcache_ptr++ = 0xffffffff; // end of block
726bbb3e 586 //printf(" %i inst\n", icount);
587
892b1dd2 588 if (tcache_ptr - tcache > TCACHE_SIZE/4) {
726bbb3e 589 printf("tcache overflow!\n");
590 fflush(stdout);
591 exit(1);
592 }
593
594 // stats
595 nblocks++;
df143b36 596 //if (pc >= 0x400)
892b1dd2 597 printf("%i blocks, %i bytes\n", nblocks, (tcache_ptr - tcache)*4);
259ed0ea 598 //printf("%p %p\n", tcache_ptr, emit_block_epilogue);
df143b36 599
5c129565 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
259ed0ea 608
609 handle_caches();
610
5c129565 611 return block_start;
726bbb3e 612}
613
614
615
616// -----------------------------------------------------
617
e807ac75 618int ssp1601_dyn_startup(void)
726bbb3e 619{
e807ac75 620 memset(tcache, 0, TCACHE_SIZE);
726bbb3e 621 memset(block_table, 0, sizeof(block_table));
df143b36 622 memset(block_table_iram, 0, sizeof(block_table_iram));
e807ac75 623 tcache_ptr = tcache;
5c129565 624 *tcache_ptr++ = 0xffffffff;
726bbb3e 625
626 return 0;
627}
628
629
630void ssp1601_dyn_reset(ssp1601_t *ssp)
631{
632 ssp1601_reset_local(ssp);
633}
634
726bbb3e 635void ssp1601_dyn_run(int cycles)
636{
637 while (cycles > 0)
638 {
e807ac75 639 int (*trans_entry)(void);
df143b36 640 if (rPC < 0x800/2)
641 {
642 if (iram_dirty) {
643 iram_context = get_iram_context();
892b1dd2 644 iram_dirty--;
df143b36 645 }
646 if (block_table_iram[iram_context][rPC] == NULL)
647 block_table_iram[iram_context][rPC] = translate_block(rPC);
5c129565 648 trans_entry = (void *) block_table_iram[iram_context][rPC];
df143b36 649 }
650 else
651 {
652 if (block_table[rPC] == NULL)
653 block_table[rPC] = translate_block(rPC);
5c129565 654 trans_entry = (void *) block_table[rPC];
df143b36 655 }
726bbb3e 656
726bbb3e 657 had_jump = 0;
658
e807ac75 659 //printf("enter %04x\n", rPC<<1);
660 cycles -= trans_entry();
661 //printf("leave %04x\n", rPC<<1);
726bbb3e 662 }
663// debug_dump2file("tcache.bin", tcache, (tcache_ptr - tcache) << 1);
664// exit(1);
665}
666