svp compiler direct calls
[picodrive.git] / Pico / carthw / svp / compiler.c
... / ...
CommitLineData
1// 187 blocks, 12072 bytes
2// 14 IRAM blocks
3
4#include "../../PicoInt.h"
5#include "compiler.h"
6
7static unsigned int *block_table[0x5090/2];
8static unsigned int *block_table_iram[15][0x800/2];
9static unsigned int *tcache_ptr = NULL;
10
11static int had_jump = 0;
12static int nblocks = 0;
13static 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
32static 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)
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
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)
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
132 if (cond) SET_PC(imm);
133 }
134 while (0);
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
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
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];
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
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
530static 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
618int 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
630void ssp1601_dyn_reset(ssp1601_t *ssp)
631{
632 ssp1601_reset_local(ssp);
633}
634
635void 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