svp: added few opcodes to translate_op()
[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:
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;
543         }
544
545         return -1;
546 }
547
548 static void *translate_block(int pc)
549 {
550         unsigned int op, op1, imm, ccount = 0;
551         unsigned int *block_start;
552         int ret;
553
554         // create .pool
555         //*tcache_ptr++ = (u32) in_funcs;                       // -1 func pool
556
557         printf("translate %04x -> %04x\n", pc<<1, (tcache_ptr-tcache)<<2);
558         block_start = tcache_ptr;
559
560         emit_block_prologue();
561
562         for (; ccount < 100;)
563         {
564                 //printf("  insn #%i\n", icount);
565                 op = PROGRAM(pc++);
566                 op1 = op >> 9;
567                 imm = (u32)-1;
568
569                 if ((op1 & 0xf) == 4 || (op1 & 0xf) == 6)
570                         imm = PROGRAM(pc++); // immediate
571
572                 ret = translate_op(op, &pc);
573                 if (ret <= 0)
574                 {
575                         emit_mov_const(0, op);
576
577                         // need immediate?
578                         if (imm != (u32)-1)
579                                 emit_mov_const(1, imm);
580
581                         // dump PC
582                         emit_pc_dump(pc);
583
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++;
591                 }
592                 else
593                         ccount += ret;
594
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         }
601
602         emit_block_epilogue(ccount + 1);
603         *tcache_ptr++ = 0xffffffff; // end of block
604         //printf("  %i inst\n", icount);
605
606         if (tcache_ptr - tcache > TCACHE_SIZE/4) {
607                 printf("tcache overflow!\n");
608                 fflush(stdout);
609                 exit(1);
610         }
611
612         // stats
613         nblocks++;
614         //if (pc >= 0x400)
615         printf("%i blocks, %i bytes\n", nblocks, (tcache_ptr - tcache)*4);
616         //printf("%p %p\n", tcache_ptr, emit_block_epilogue);
617
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
626
627         handle_caches();
628
629         return block_start;
630 }
631
632
633
634 // -----------------------------------------------------
635
636 int ssp1601_dyn_startup(void)
637 {
638         memset(tcache, 0, TCACHE_SIZE);
639         memset(block_table, 0, sizeof(block_table));
640         memset(block_table_iram, 0, sizeof(block_table_iram));
641         tcache_ptr = tcache;
642         *tcache_ptr++ = 0xffffffff;
643
644         return 0;
645 }
646
647
648 void ssp1601_dyn_reset(ssp1601_t *ssp)
649 {
650         ssp1601_reset_local(ssp);
651 }
652
653 void ssp1601_dyn_run(int cycles)
654 {
655         //rPC = 0x1272 >> 1;
656         while (cycles > 0)
657         {
658                 int (*trans_entry)(void);
659                 if (rPC < 0x800/2)
660                 {
661                         if (iram_dirty) {
662                                 iram_context = get_iram_context();
663                                 iram_dirty--;
664                         }
665                         if (block_table_iram[iram_context][rPC] == NULL)
666                                 block_table_iram[iram_context][rPC] = translate_block(rPC);
667                         trans_entry = (void *) block_table_iram[iram_context][rPC];
668                 }
669                 else
670                 {
671                         if (block_table[rPC] == NULL)
672                                 block_table[rPC] = translate_block(rPC);
673                         trans_entry = (void *) block_table[rPC];
674                 }
675
676                 had_jump = 0;
677
678                 //printf("enter %04x\n", rPC<<1);
679                 cycles -= trans_entry();
680                 //printf("leave %04x\n", rPC<<1);
681         }
682 //      debug_dump2file("tcache.bin", tcache, (tcache_ptr - tcache) << 1);
683 //      exit(1);
684 }
685