svp: added few opcodes to translate_op()
[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
f48f5e3b 524 case 0x00:
525 if (op == 0) return 1; // nop
526 break;
527
528 // ld a, adr
529 case 0x03:
530 EOP_ADD_IMM(0,7,1,30/2,(op&0x180)>>1); // add r1, r7, ((op&0x180)<<1)
531 EOP_LDRH_IMM(0,1,(op&0x7f)<<1); // ldr r0, [r1, (op&0x7f)<<1]
532 EOP_MOV_REG_LSL(5, 5, 16); // mov r5, r5, lsl #16 @ A
533 EOP_ORR_REG_SIMPLE(5, 0); // orr r5, r5, r0
534 EOP_MOV_REG_ROR(5,5,16); // mov r5, r5, ror #16
535 return 1;
536
537 // ld adr, a
538 case 0x07:
539 EOP_ADD_IMM(0,7,1,30/2,(op&0x180)>>1); // add r1, r7, ((op&0x180)<<1)
540 EOP_MOV_REG_LSR(0, 5, 16); // mov r0, r5, lsr #16 @ A
541 EOP_STRH_IMM(0,1,(op&0x7f)<<1); // str r0, [r1, (op&0x7f)<<1]
542 return 1;
e807ac75 543 }
544
545 return -1;
546}
547
df143b36 548static void *translate_block(int pc)
726bbb3e 549{
e807ac75 550 unsigned int op, op1, imm, ccount = 0;
5c129565 551 unsigned int *block_start;
e807ac75 552 int ret;
5c129565 553
554 // create .pool
e807ac75 555 //*tcache_ptr++ = (u32) in_funcs; // -1 func pool
726bbb3e 556
259ed0ea 557 printf("translate %04x -> %04x\n", pc<<1, (tcache_ptr-tcache)<<2);
5c129565 558 block_start = tcache_ptr;
559
560 emit_block_prologue();
726bbb3e 561
e807ac75 562 for (; ccount < 100;)
726bbb3e 563 {
259ed0ea 564 //printf(" insn #%i\n", icount);
726bbb3e 565 op = PROGRAM(pc++);
566 op1 = op >> 9;
e807ac75 567 imm = (u32)-1;
5c129565 568
e807ac75 569 if ((op1 & 0xf) == 4 || (op1 & 0xf) == 6)
570 imm = PROGRAM(pc++); // immediate
5c129565 571
e807ac75 572 ret = translate_op(op, &pc);
573 if (ret <= 0)
574 {
575 emit_mov_const(0, op);
5c129565 576
e807ac75 577 // need immediate?
578 if (imm != (u32)-1)
579 emit_mov_const(1, imm);
5c129565 580
e807ac75 581 // dump PC
582 emit_pc_dump(pc);
5c129565 583
e807ac75 584 emit_interpreter_call(in_funcs[op1]);
585
586 if (in_funcs[op1] == NULL) {
587 printf("NULL func! op=%08x (%02x)\n", op, op1);
588 exit(1);
589 }
590 ccount++;
892b1dd2 591 }
e807ac75 592 else
593 ccount += ret;
594
726bbb3e 595 if (op1 == 0x24 || op1 == 0x26 || // call, bra
596 ((op1 == 0 || op1 == 1 || op1 == 4 || op1 == 5 || op1 == 9 || op1 == 0x25) &&
597 (op & 0xf0) == 0x60)) { // ld PC
598 break;
599 }
600 }
5c129565 601
e807ac75 602 emit_block_epilogue(ccount + 1);
5c129565 603 *tcache_ptr++ = 0xffffffff; // end of block
726bbb3e 604 //printf(" %i inst\n", icount);
605
892b1dd2 606 if (tcache_ptr - tcache > TCACHE_SIZE/4) {
726bbb3e 607 printf("tcache overflow!\n");
608 fflush(stdout);
609 exit(1);
610 }
611
612 // stats
613 nblocks++;
df143b36 614 //if (pc >= 0x400)
892b1dd2 615 printf("%i blocks, %i bytes\n", nblocks, (tcache_ptr - tcache)*4);
259ed0ea 616 //printf("%p %p\n", tcache_ptr, emit_block_epilogue);
df143b36 617
5c129565 618#if 0
619 {
620 FILE *f = fopen("tcache.bin", "wb");
621 fwrite(tcache, 1, (tcache_ptr - tcache)*4, f);
622 fclose(f);
623 }
624 exit(0);
625#endif
259ed0ea 626
627 handle_caches();
628
5c129565 629 return block_start;
726bbb3e 630}
631
632
633
634// -----------------------------------------------------
635
e807ac75 636int ssp1601_dyn_startup(void)
726bbb3e 637{
e807ac75 638 memset(tcache, 0, TCACHE_SIZE);
726bbb3e 639 memset(block_table, 0, sizeof(block_table));
df143b36 640 memset(block_table_iram, 0, sizeof(block_table_iram));
e807ac75 641 tcache_ptr = tcache;
5c129565 642 *tcache_ptr++ = 0xffffffff;
726bbb3e 643
644 return 0;
645}
646
647
648void ssp1601_dyn_reset(ssp1601_t *ssp)
649{
650 ssp1601_reset_local(ssp);
651}
652
726bbb3e 653void ssp1601_dyn_run(int cycles)
654{
f48f5e3b 655 //rPC = 0x1272 >> 1;
726bbb3e 656 while (cycles > 0)
657 {
e807ac75 658 int (*trans_entry)(void);
df143b36 659 if (rPC < 0x800/2)
660 {
661 if (iram_dirty) {
662 iram_context = get_iram_context();
892b1dd2 663 iram_dirty--;
df143b36 664 }
665 if (block_table_iram[iram_context][rPC] == NULL)
666 block_table_iram[iram_context][rPC] = translate_block(rPC);
5c129565 667 trans_entry = (void *) block_table_iram[iram_context][rPC];
df143b36 668 }
669 else
670 {
671 if (block_table[rPC] == NULL)
672 block_table[rPC] = translate_block(rPC);
5c129565 673 trans_entry = (void *) block_table[rPC];
df143b36 674 }
726bbb3e 675
726bbb3e 676 had_jump = 0;
677
e807ac75 678 //printf("enter %04x\n", rPC<<1);
679 cycles -= trans_entry();
680 //printf("leave %04x\n", rPC<<1);
726bbb3e 681 }
682// debug_dump2file("tcache.bin", tcache, (tcache_ptr - tcache) << 1);
683// exit(1);
684}
685