svp compiler: some pointer reg handling
[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
5d817c91 15#ifndef ARM
16#define DUMP_BLOCK 0x40b0
17unsigned int tcache[512*1024];
18void regfile_load(void){}
19void regfile_store(void){}
20#endif
21
726bbb3e 22#define EMBED_INTERPRETER
23#define ssp1601_reset ssp1601_reset_local
24#define ssp1601_run ssp1601_run_local
25
5c129565 26#define GET_PC() rPC
27#define GET_PPC_OFFS() (GET_PC()*2 - 2)
726bbb3e 28#define SET_PC(d) { had_jump = 1; rPC = d; } /* must return to dispatcher after this */
29//#define GET_PC() (PC - (unsigned short *)svp->iram_rom)
30//#define GET_PPC_OFFS() ((unsigned int)PC - (unsigned int)svp->iram_rom - 2)
31//#define SET_PC(d) PC = (unsigned short *)svp->iram_rom + d
32
33#include "ssp16.c"
5c129565 34#include "gen_arm.c"
726bbb3e 35
36// -----------------------------------------------------
37
892b1dd2 38// ld d, s
39static void op00(unsigned int op, unsigned int imm)
40{
41 unsigned int tmpv;
259ed0ea 42 PC = ((unsigned short *)(void *)&op) + 1; /* FIXME: needed for interpreter */
892b1dd2 43 if (op == 0) return; // nop
44 if (op == ((SSP_A<<4)|SSP_P)) { // A <- P
45 // not sure. MAME claims that only hi word is transfered.
46 read_P(); // update P
47 rA32 = rP.v;
48 }
49 else
50 {
51 tmpv = REG_READ(op & 0x0f);
52 REG_WRITE((op & 0xf0) >> 4, tmpv);
53 }
54}
55
56// ld d, (ri)
57static void op01(unsigned int op, unsigned int imm)
58{
59 unsigned int tmpv;
60 tmpv = ptr1_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv);
61}
62
63// ld (ri), s
64static void op02(unsigned int op, unsigned int imm)
65{
66 unsigned int tmpv;
67 tmpv = REG_READ((op & 0xf0) >> 4); ptr1_write(op, tmpv);
68}
69
70// ldi d, imm
71static void op04(unsigned int op, unsigned int imm)
72{
73 REG_WRITE((op & 0xf0) >> 4, imm);
74}
75
76// ld d, ((ri))
77static void op05(unsigned int op, unsigned int imm)
78{
79 unsigned int tmpv;
80 tmpv = ptr2_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv);
81}
82
83// ldi (ri), imm
84static void op06(unsigned int op, unsigned int imm)
85{
86 ptr1_write(op, imm);
87}
88
89// ld adr, a
90static void op07(unsigned int op, unsigned int imm)
91{
92 ssp->RAM[op & 0x1ff] = rA;
93}
94
95// ld d, ri
96static void op09(unsigned int op, unsigned int imm)
97{
98 unsigned int tmpv;
99 tmpv = rIJ[(op&3)|((op>>6)&4)]; REG_WRITE((op & 0xf0) >> 4, tmpv);
100}
101
102// ld ri, s
103static void op0a(unsigned int op, unsigned int imm)
104{
105 rIJ[(op&3)|((op>>6)&4)] = REG_READ((op & 0xf0) >> 4);
106}
107
108// ldi ri, simm (also op0d op0e op0f)
109static void op0c(unsigned int op, unsigned int imm)
110{
111 rIJ[(op>>8)&7] = op;
112}
113
114// call cond, addr
115static void op24(unsigned int op, unsigned int imm)
116{
117 int cond = 0;
118 do {
119 COND_CHECK
259ed0ea 120 if (cond) { int new_PC = imm; write_STACK(GET_PC()); SET_PC(new_PC); }
892b1dd2 121 }
122 while (0);
123}
124
125// ld d, (a)
126static void op25(unsigned int op, unsigned int imm)
127{
128 unsigned int tmpv;
129 tmpv = ((unsigned short *)svp->iram_rom)[rA]; REG_WRITE((op & 0xf0) >> 4, tmpv);
130}
131
132// bra cond, addr
133static void op26(unsigned int op, unsigned int imm)
134{
135 do
136 {
137 int cond = 0;
138 COND_CHECK
259ed0ea 139 if (cond) SET_PC(imm);
892b1dd2 140 }
259ed0ea 141 while (0);
892b1dd2 142}
143
144// mod cond, op
145static void op48(unsigned int op, unsigned int imm)
146{
147 do
148 {
149 int cond = 0;
150 COND_CHECK
151 if (cond) {
152 switch (op & 7) {
153 case 2: rA32 = (signed int)rA32 >> 1; break; // shr (arithmetic)
154 case 3: rA32 <<= 1; break; // shl
155 case 6: rA32 = -(signed int)rA32; break; // neg
156 case 7: if ((int)rA32 < 0) rA32 = -(signed int)rA32; break; // abs
157 default: elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: unhandled mod %i @ %04x",
158 op&7, GET_PPC_OFFS());
159 }
160 UPD_ACC_ZN // ?
161 }
162 }
163 while(0);
164}
165
166// mpys?
167static void op1b(unsigned int op, unsigned int imm)
168{
169 read_P(); // update P
170 rA32 -= rP.v; // maybe only upper word?
171 UPD_ACC_ZN // there checking flags after this
172 rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
173 rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
174}
175
176// mpya (rj), (ri), b
177static void op4b(unsigned int op, unsigned int imm)
178{
179 read_P(); // update P
180 rA32 += rP.v; // confirmed to be 32bit
181 UPD_ACC_ZN // ?
182 rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
183 rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
184}
185
186// mld (rj), (ri), b
187static void op5b(unsigned int op, unsigned int imm)
188{
189 rA32 = 0;
190 rST &= 0x0fff; // ?
191 rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
192 rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
193}
194
195// OP a, s
196static void op10(unsigned int op, unsigned int imm)
197{
198 do
199 {
200 unsigned int tmpv;
201 OP_CHECK32(OP_SUBA32); tmpv = REG_READ(op & 0x0f); OP_SUBA(tmpv);
202 }
203 while(0);
204}
205
206static void op30(unsigned int op, unsigned int imm)
207{
208 do
209 {
210 unsigned int tmpv;
211 OP_CHECK32(OP_CMPA32); tmpv = REG_READ(op & 0x0f); OP_CMPA(tmpv);
212 }
213 while(0);
214}
215
216static void op40(unsigned int op, unsigned int imm)
217{
218 do
219 {
220 unsigned int tmpv;
221 OP_CHECK32(OP_ADDA32); tmpv = REG_READ(op & 0x0f); OP_ADDA(tmpv);
222 }
223 while(0);
224}
225
226static void op50(unsigned int op, unsigned int imm)
227{
228 do
229 {
230 unsigned int tmpv;
231 OP_CHECK32(OP_ANDA32); tmpv = REG_READ(op & 0x0f); OP_ANDA(tmpv);
232 }
233 while(0);
234}
235
236static void op60(unsigned int op, unsigned int imm)
237{
238 do
239 {
240 unsigned int tmpv;
241 OP_CHECK32(OP_ORA32 ); tmpv = REG_READ(op & 0x0f); OP_ORA (tmpv);
242 }
243 while(0);
244}
245
246static void op70(unsigned int op, unsigned int imm)
247{
248 do
249 {
250 unsigned int tmpv;
251 OP_CHECK32(OP_EORA32); tmpv = REG_READ(op & 0x0f); OP_EORA(tmpv);
252 }
253 while(0);
254}
255
256// OP a, (ri)
257static void op11(unsigned int op, unsigned int imm)
258{
259 unsigned int tmpv;
260 tmpv = ptr1_read(op); OP_SUBA(tmpv);
261}
262
263static void op31(unsigned int op, unsigned int imm)
264{
265 unsigned int tmpv;
266 tmpv = ptr1_read(op); OP_CMPA(tmpv);
267}
268
269static void op41(unsigned int op, unsigned int imm)
270{
271 unsigned int tmpv;
272 tmpv = ptr1_read(op); OP_ADDA(tmpv);
273}
274
275static void op51(unsigned int op, unsigned int imm)
276{
277 unsigned int tmpv;
278 tmpv = ptr1_read(op); OP_ANDA(tmpv);
279}
280
281static void op61(unsigned int op, unsigned int imm)
282{
283 unsigned int tmpv;
284 tmpv = ptr1_read(op); OP_ORA (tmpv);
285}
286
287static void op71(unsigned int op, unsigned int imm)
288{
289 unsigned int tmpv;
290 tmpv = ptr1_read(op); OP_EORA(tmpv);
291}
292
293// OP a, adr
294static void op03(unsigned int op, unsigned int imm)
295{
296 unsigned int tmpv;
297 tmpv = ssp->RAM[op & 0x1ff]; OP_LDA (tmpv);
298}
299
300static void op13(unsigned int op, unsigned int imm)
301{
302 unsigned int tmpv;
303 tmpv = ssp->RAM[op & 0x1ff]; OP_SUBA(tmpv);
304}
305
306static void op33(unsigned int op, unsigned int imm)
307{
308 unsigned int tmpv;
309 tmpv = ssp->RAM[op & 0x1ff]; OP_CMPA(tmpv);
310}
311
312static void op43(unsigned int op, unsigned int imm)
313{
314 unsigned int tmpv;
315 tmpv = ssp->RAM[op & 0x1ff]; OP_ADDA(tmpv);
316}
317
318static void op53(unsigned int op, unsigned int imm)
319{
320 unsigned int tmpv;
321 tmpv = ssp->RAM[op & 0x1ff]; OP_ANDA(tmpv);
322}
323
324static void op63(unsigned int op, unsigned int imm)
325{
326 unsigned int tmpv;
327 tmpv = ssp->RAM[op & 0x1ff]; OP_ORA (tmpv);
328}
329
330static void op73(unsigned int op, unsigned int imm)
331{
332 unsigned int tmpv;
333 tmpv = ssp->RAM[op & 0x1ff]; OP_EORA(tmpv);
334}
335
336// OP a, imm
337static void op14(unsigned int op, unsigned int imm)
338{
339 OP_SUBA(imm);
340}
341
342static void op34(unsigned int op, unsigned int imm)
343{
344 OP_CMPA(imm);
345}
346
347static void op44(unsigned int op, unsigned int imm)
348{
349 OP_ADDA(imm);
350}
351
352static void op54(unsigned int op, unsigned int imm)
353{
354 OP_ANDA(imm);
355}
356
357static void op64(unsigned int op, unsigned int imm)
358{
359 OP_ORA (imm);
360}
361
362static void op74(unsigned int op, unsigned int imm)
363{
364 OP_EORA(imm);
365}
366
367// OP a, ((ri))
368static void op15(unsigned int op, unsigned int imm)
369{
370 unsigned int tmpv;
371 tmpv = ptr2_read(op); OP_SUBA(tmpv);
372}
373
374static void op35(unsigned int op, unsigned int imm)
375{
376 unsigned int tmpv;
377 tmpv = ptr2_read(op); OP_CMPA(tmpv);
378}
379
380static void op45(unsigned int op, unsigned int imm)
381{
382 unsigned int tmpv;
383 tmpv = ptr2_read(op); OP_ADDA(tmpv);
384}
385
386static void op55(unsigned int op, unsigned int imm)
387{
388 unsigned int tmpv;
389 tmpv = ptr2_read(op); OP_ANDA(tmpv);
390}
391
392static void op65(unsigned int op, unsigned int imm)
393{
394 unsigned int tmpv;
395 tmpv = ptr2_read(op); OP_ORA (tmpv);
396}
397
398static void op75(unsigned int op, unsigned int imm)
399{
400 unsigned int tmpv;
401 tmpv = ptr2_read(op); OP_EORA(tmpv);
402}
403
404// OP a, ri
405static void op19(unsigned int op, unsigned int imm)
406{
407 unsigned int tmpv;
408 tmpv = rIJ[IJind]; OP_SUBA(tmpv);
409}
410
411static void op39(unsigned int op, unsigned int imm)
412{
413 unsigned int tmpv;
414 tmpv = rIJ[IJind]; OP_CMPA(tmpv);
415}
416
417static void op49(unsigned int op, unsigned int imm)
418{
419 unsigned int tmpv;
420 tmpv = rIJ[IJind]; OP_ADDA(tmpv);
421}
422
423static void op59(unsigned int op, unsigned int imm)
424{
425 unsigned int tmpv;
426 tmpv = rIJ[IJind]; OP_ANDA(tmpv);
427}
428
429static void op69(unsigned int op, unsigned int imm)
430{
431 unsigned int tmpv;
432 tmpv = rIJ[IJind]; OP_ORA (tmpv);
433}
434
435static void op79(unsigned int op, unsigned int imm)
436{
437 unsigned int tmpv;
438 tmpv = rIJ[IJind]; OP_EORA(tmpv);
439}
440
441// OP simm
442static void op1c(unsigned int op, unsigned int imm)
443{
444 OP_SUBA(op & 0xff);
445}
446
447static void op3c(unsigned int op, unsigned int imm)
448{
449 OP_CMPA(op & 0xff);
450}
451
452static void op4c(unsigned int op, unsigned int imm)
453{
454 OP_ADDA(op & 0xff);
455}
456
457static void op5c(unsigned int op, unsigned int imm)
458{
459 OP_ANDA(op & 0xff);
460}
461
462static void op6c(unsigned int op, unsigned int imm)
463{
464 OP_ORA (op & 0xff);
465}
466
467static void op7c(unsigned int op, unsigned int imm)
468{
469 OP_EORA(op & 0xff);
470}
471
472typedef void (in_func)(unsigned int op, unsigned int imm);
473
474static in_func *in_funcs[0x80] =
475{
476 op00, op01, op02, op03, op04, op05, op06, op07,
477 NULL, op09, op0a, NULL, op0c, op0c, op0c, op0c,
478 op10, op11, NULL, op13, op14, op15, NULL, NULL,
479 NULL, op19, NULL, op1b, op1c, NULL, NULL, NULL,
480 NULL, NULL, NULL, NULL, op24, op25, op26, NULL,
481 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
482 op30, op31, NULL, op33, op34, op35, NULL, NULL,
483 NULL, op39, NULL, NULL, op3c, NULL, NULL, NULL,
484 op40, op41, NULL, op43, op44, op45, NULL, NULL,
485 op48, op49, NULL, op4b, op4c, NULL, NULL, NULL,
486 op50, op51, NULL, op53, op54, op55, NULL, NULL,
487 NULL, op59, NULL, op5b, op5c, NULL, NULL, NULL,
488 op60, op61, NULL, op63, op64, op65, NULL, NULL,
489 NULL, op69, NULL, NULL, op6c, NULL, NULL, NULL,
490 op70, op71, NULL, op73, op74, op75, NULL, NULL,
491 NULL, op79, NULL, NULL, op7c, NULL, NULL, NULL,
492};
493
494// -----------------------------------------------------
495
df143b36 496static unsigned char iram_context_map[] =
497{
498 0, 0, 0, 0, 1, 0, 0, 0, // 04
499 0, 0, 0, 0, 0, 0, 2, 0, // 0e
500 0, 0, 0, 0, 0, 3, 0, 4, // 15 17
501 5, 0, 0, 6, 0, 7, 0, 0, // 18 1b 1d
502 8, 9, 0, 0, 0,10, 0, 0, // 20 21 25
503 0, 0, 0, 0, 0, 0, 0, 0,
504 0, 0,11, 0, 0,12, 0, 0, // 32 35
505 13,14, 0, 0, 0, 0, 0, 0 // 38 39
506};
507
df143b36 508static int get_iram_context(void)
509{
510 unsigned char *ir = (unsigned char *)svp->iram_rom;
511 int val1, val = ir[0x083^1] + ir[0x4FA^1] + ir[0x5F7^1] + ir[0x47B^1];
df143b36 512 val1 = iram_context_map[(val>>1)&0x3f];
513
5c129565 514 if (val1 == 0) {
df143b36 515 printf("val: %02x PC=%04x\n", (val>>1)&0x3f, rPC);
df143b36 516 //debug_dump2file(name, svp->iram_rom, 0x800);
517 exit(1);
518 }
5c129565 519// elprintf(EL_ANOMALY, "iram_context: %02i", val1);
df143b36 520 return val1;
521}
522
5d817c91 523// -----------------------------------------------------
524/*
525enum {
526 SSP_GR0, SSP_X, SSP_Y, SSP_A,
527 SSP_ST, SSP_STACK, SSP_PC, SSP_P,
528 SSP_PM0, SSP_PM1, SSP_PM2, SSP_XST,
529 SSP_PM4, SSP_gr13, SSP_PMC, SSP_AL
530};
531*/
532/* regs with known values */
533static struct
534{
535 ssp_reg_t gr[8];
536 unsigned char r[8];
537} const_regs;
538
539#define CRREG_X (1 << SSP_X)
540#define CRREG_Y (1 << SSP_Y)
541#define CRREG_A (1 << SSP_A) /* AH only */
542#define CRREG_ST (1 << SSP_ST)
543#define CRREG_STACK (1 << SSP_STACK)
544#define CRREG_PC (1 << SSP_PC)
545#define CRREG_P (1 << SSP_P)
546#define CRREG_PR0 (1 << 8)
547#define CRREG_PR4 (1 << 12)
548#define CRREG_AL (1 << 16)
549
550static u32 const_regb = 0; /* bitfield of known register values */
551static u32 dirty_regb = 0; /* known vals, which need to be flushed (only r0-r7) */
552
553/* known values of host regs.
554 * -1 - unknown
555 * 00000-0ffff - 16bit value
556 * 10000-1ffff - base reg (r7) + 16bit val
557 * 20000 - means reg (low) eq AH
558 */
559static int hostreg_r[4];
560
561static void hostreg_clear(void)
562{
563 int i;
564 for (i = 0; i < 4; i++)
565 hostreg_r[i] = -1;
566}
567
568/*static*/ void hostreg_ah_changed(void)
569{
570 int i;
571 for (i = 0; i < 4; i++)
572 if (hostreg_r[i] == 0x20000) hostreg_r[i] = -1;
573}
574
726bbb3e 575
5c129565 576#define PROGRAM(x) ((unsigned short *)svp->iram_rom)[x]
726bbb3e 577
5d817c91 578/* load 16bit val into host reg r0-r3. Nothing is trashed */
579static void tr_mov16(int r, int val)
e807ac75 580{
5d817c91 581 if (hostreg_r[r] != val) {
582 emit_mov_const(r, val);
583 hostreg_r[r] = val;
584 }
585}
586
587/* write dirty r0-r7 to host regs. Nothing is trashed */
588static void tr_flush_dirty(void)
589{
590 int i, ror = 0, reg;
591 dirty_regb >>= 8;
592 /* r0-r7 */
593 for (i = 0; dirty_regb && i < 8; i++, dirty_regb >>= 1)
594 {
595 if (!(dirty_regb&1)) continue;
596 switch (i&3) {
597 case 0: ror = 0; break;
598 case 1: ror = 24/2; break;
599 case 2: ror = 16/2; break;
600 }
601 reg = (i < 4) ? 8 : 9;
602 EOP_BIC_IMM(reg,reg,ror,0xff);
603 if (const_regs.r[i] != 0)
604 EOP_ORR_IMM(reg,reg,ror,const_regs.r[i]);
605 }
606}
607
608/* read bank word to r0 (MSW may contain trash). Thrashes r1. */
609static void tr_bank_read(int addr) /* word addr 0-0x1ff */
610{
611 if (addr&1) {
612 int breg = 7;
613 if (addr > 0x7f) {
614 if (hostreg_r[1] != (0x10000|((addr&0x180)<<1))) {
615 EOP_ADD_IMM(1,7,30/2,(addr&0x180)>>1); // add r1, r7, ((op&0x180)<<1)
616 hostreg_r[1] = 0x10000|((addr&0x180)<<1);
617 }
618 breg = 1;
619 }
620 EOP_LDRH_IMM(0,breg,(addr&0x7f)<<1); // ldrh r0, [r1, (op&0x7f)<<1]
621 } else {
622 EOP_LDR_IMM(0,7,(addr&0x1ff)<<1); // ldr r0, [r1, (op&0x1ff)<<1]
623 }
624 hostreg_r[0] = -1;
625}
626
627/* write r0 to bank. Trashes r1. */
628static void tr_bank_write(int addr)
629{
630 int breg = 7;
631 if (addr > 0x7f) {
632 if (hostreg_r[1] != (0x10000|((addr&0x180)<<1))) {
633 EOP_ADD_IMM(1,7,30/2,(addr&0x180)>>1); // add r1, r7, ((op&0x180)<<1)
634 hostreg_r[1] = 0x10000|((addr&0x180)<<1);
635 }
636 breg = 1;
637 }
638 EOP_STRH_IMM(0,breg,(addr&0x7f)<<1); // str r0, [r1, (op&0x7f)<<1]
639}
640
641/* handle RAM bank pointer modifiers. Nothing is trashed. */
642static void tr_ptrr_mod(int r, int mod, int need_modulo)
643{
644 int modulo = -1, modulo_shift = -1; /* unknown */
645
646 if (mod == 0) return;
647
648 if (!need_modulo || mod == 1) // +!
649 modulo_shift = 8;
650 else if (need_modulo && (const_regb & CRREG_ST)) {
651 modulo_shift = const_regs.gr[SSP_ST].h & 7;
652 if (modulo_shift == 0) modulo_shift = 8;
653 }
654
655 if (mod > 1 && modulo_shift == -1) { printf("need var modulo\n"); exit(1); }
656 modulo = (1 << modulo_shift) - 1;
657
658 if (const_regb & (1 << (r + 8))) {
659 if (mod == 2)
660 const_regs.r[r] = (const_regs.r[r] & ~modulo) | ((const_regs.r[r] - 1) & modulo);
661 else const_regs.r[r] = (const_regs.r[r] & ~modulo) | ((const_regs.r[r] + 1) & modulo);
662 } else {
663 int reg = (r < 4) ? 8 : 9;
664 int ror = ((r&3) + 1)*8 - (8 - modulo_shift);
665 EOP_MOV_REG_ROR(reg,reg,ror);
666 // {add|sub} reg, reg, #1<<shift
667 EOP_C_DOP_IMM(A_COND_AL,(mod==2)?A_OP_SUB:A_OP_ADD,0,reg,reg, 8/2, 1<<(8 - modulo_shift));
668 EOP_MOV_REG_ROR(reg,reg,32-ror);
669 }
670}
671
672
673static int translate_op(unsigned int op, int *pc, int imm)
674{
675 u32 tmpv;
676 int ret = 0;
677
e807ac75 678 switch (op >> 9)
679 {
680 // ld d, s
f48f5e3b 681 case 0x00:
5d817c91 682 if (op == 0) { ret++; break; } // nop
f48f5e3b 683 break;
684
685 // ld a, adr
686 case 0x03:
5d817c91 687 tr_bank_read(op&0x1ff);
688 EOP_MOV_REG_LSL(5, 5, 16); // mov r5, r5, lsl #16
689 EOP_MOV_REG_LSR(5, 5, 16); // mov r5, r5, lsl #16 @ AL
690 EOP_ORR_REG_LSL(5, 5, 0, 16); // orr r5, r5, r0, lsl #16
691 const_regb &= ~CRREG_A;
692 hostreg_r[0] = 0x20000;
693 ret++; break;
694
695 // ldi (ri), imm
696 case 0x06:
697 //tmpv = *PC++; ptr1_write(op, tmpv); break;
698 // int t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18);
699 tr_mov16(0, imm);
700 if ((op&3) == 3)
701 {
702 tmpv = (op>>2) & 3; // direct addressing
703 if (op & 0x100) {
704 if (hostreg_r[1] != 0x10200) {
705 EOP_ADD_IMM(1,7,30/2,0x200>>2); // add r1, r7, 0x200
706 hostreg_r[1] = 0x10200;
707 }
708 EOP_STRH_IMM(0,1,tmpv<<1); // str r0, [r1, {0,2,4,6}]
709 } else {
710 EOP_STRH_IMM(0,7,tmpv<<1); // str r0, [r7, {0,2,4,6}]
711 }
712 }
713 else
714 {
715 int r = (op&3) | ((op>>6)&4);
716 if (const_regb & (1 << (r + 8))) {
717 tr_bank_write(const_regs.r[r] | ((r < 4) ? 0 : 0x100));
718 } else {
719 int reg = (r < 4) ? 8 : 9;
720 int ror = ((4 - (r&3))*8) & 0x1f;
721 EOP_AND_IMM(1,reg,ror/2,0xff); // and r1, r{7,8}, <mask>
722 if (r >= 4)
723 EOP_ORR_IMM(1,1,((ror-8)&0x1f)/2,1); // orr r1, r1, 1<<shift
724 if (r&3) EOP_ADD_REG_LSR(1,7,1, (r&3)*8-1); // add r1, r7, r1, lsr #lsr
725 else EOP_ADD_REG_LSL(1,7,1,1);
726 EOP_STRH_SIMPLE(0,1); // strh r0, [r1]
727 hostreg_r[1] = -1;
728 }
729 tr_ptrr_mod(r, (op>>2) & 3, 0);
730 }
731 ret++; break;
f48f5e3b 732
733 // ld adr, a
734 case 0x07:
5d817c91 735 if (hostreg_r[0] != 0x20000) {
736 EOP_MOV_REG_LSR(0, 5, 16); // mov r0, r5, lsr #16 @ A
737 hostreg_r[0] = 0x20000;
738 }
739 tr_bank_write(op&0x1ff);
740 ret++; break;
741
742 // ldi ri, simm
743 case 0x0c ... 0x0f:
744 tmpv = (op>>8)&7;
745 const_regs.r[tmpv] = op;
746 const_regb |= 1 << (tmpv + 8);
747 dirty_regb |= 1 << (tmpv + 8);
748 ret++; break;
e807ac75 749 }
750
5d817c91 751 return ret;
e807ac75 752}
753
df143b36 754static void *translate_block(int pc)
726bbb3e 755{
e807ac75 756 unsigned int op, op1, imm, ccount = 0;
5c129565 757 unsigned int *block_start;
e807ac75 758 int ret;
5c129565 759
760 // create .pool
e807ac75 761 //*tcache_ptr++ = (u32) in_funcs; // -1 func pool
726bbb3e 762
259ed0ea 763 printf("translate %04x -> %04x\n", pc<<1, (tcache_ptr-tcache)<<2);
5c129565 764 block_start = tcache_ptr;
5d817c91 765 const_regb = dirty_regb = 0;
766 hostreg_clear();
5c129565 767
768 emit_block_prologue();
726bbb3e 769
e807ac75 770 for (; ccount < 100;)
726bbb3e 771 {
259ed0ea 772 //printf(" insn #%i\n", icount);
726bbb3e 773 op = PROGRAM(pc++);
774 op1 = op >> 9;
e807ac75 775 imm = (u32)-1;
5c129565 776
e807ac75 777 if ((op1 & 0xf) == 4 || (op1 & 0xf) == 6)
778 imm = PROGRAM(pc++); // immediate
5c129565 779
5d817c91 780 ret = translate_op(op, &pc, imm);
e807ac75 781 if (ret <= 0)
782 {
5d817c91 783 tr_flush_dirty();
784
e807ac75 785 emit_mov_const(0, op);
5c129565 786
e807ac75 787 // need immediate?
788 if (imm != (u32)-1)
789 emit_mov_const(1, imm);
5c129565 790
e807ac75 791 // dump PC
792 emit_pc_dump(pc);
5c129565 793
e807ac75 794 emit_interpreter_call(in_funcs[op1]);
795
796 if (in_funcs[op1] == NULL) {
797 printf("NULL func! op=%08x (%02x)\n", op, op1);
798 exit(1);
799 }
800 ccount++;
5d817c91 801 hostreg_clear();
892b1dd2 802 }
e807ac75 803 else
804 ccount += ret;
805
726bbb3e 806 if (op1 == 0x24 || op1 == 0x26 || // call, bra
807 ((op1 == 0 || op1 == 1 || op1 == 4 || op1 == 5 || op1 == 9 || op1 == 0x25) &&
808 (op & 0xf0) == 0x60)) { // ld PC
809 break;
810 }
811 }
5c129565 812
5d817c91 813 tr_flush_dirty();
e807ac75 814 emit_block_epilogue(ccount + 1);
5c129565 815 *tcache_ptr++ = 0xffffffff; // end of block
726bbb3e 816 //printf(" %i inst\n", icount);
817
892b1dd2 818 if (tcache_ptr - tcache > TCACHE_SIZE/4) {
726bbb3e 819 printf("tcache overflow!\n");
820 fflush(stdout);
821 exit(1);
822 }
823
824 // stats
825 nblocks++;
df143b36 826 //if (pc >= 0x400)
892b1dd2 827 printf("%i blocks, %i bytes\n", nblocks, (tcache_ptr - tcache)*4);
259ed0ea 828 //printf("%p %p\n", tcache_ptr, emit_block_epilogue);
df143b36 829
5d817c91 830#ifdef DUMP_BLOCK
5c129565 831 {
832 FILE *f = fopen("tcache.bin", "wb");
833 fwrite(tcache, 1, (tcache_ptr - tcache)*4, f);
834 fclose(f);
835 }
836 exit(0);
837#endif
259ed0ea 838
839 handle_caches();
840
5c129565 841 return block_start;
726bbb3e 842}
843
844
845
846// -----------------------------------------------------
847
e807ac75 848int ssp1601_dyn_startup(void)
726bbb3e 849{
e807ac75 850 memset(tcache, 0, TCACHE_SIZE);
726bbb3e 851 memset(block_table, 0, sizeof(block_table));
df143b36 852 memset(block_table_iram, 0, sizeof(block_table_iram));
e807ac75 853 tcache_ptr = tcache;
5c129565 854 *tcache_ptr++ = 0xffffffff;
726bbb3e 855
856 return 0;
857}
858
859
860void ssp1601_dyn_reset(ssp1601_t *ssp)
861{
862 ssp1601_reset_local(ssp);
863}
864
726bbb3e 865void ssp1601_dyn_run(int cycles)
866{
5d817c91 867#ifdef DUMP_BLOCK
868 rPC = DUMP_BLOCK >> 1;
869#endif
726bbb3e 870 while (cycles > 0)
871 {
e807ac75 872 int (*trans_entry)(void);
df143b36 873 if (rPC < 0x800/2)
874 {
875 if (iram_dirty) {
876 iram_context = get_iram_context();
892b1dd2 877 iram_dirty--;
df143b36 878 }
879 if (block_table_iram[iram_context][rPC] == NULL)
880 block_table_iram[iram_context][rPC] = translate_block(rPC);
5c129565 881 trans_entry = (void *) block_table_iram[iram_context][rPC];
df143b36 882 }
883 else
884 {
885 if (block_table[rPC] == NULL)
886 block_table[rPC] = translate_block(rPC);
5c129565 887 trans_entry = (void *) block_table[rPC];
df143b36 888 }
726bbb3e 889
726bbb3e 890 had_jump = 0;
891
e807ac75 892 //printf("enter %04x\n", rPC<<1);
893 cycles -= trans_entry();
894 //printf("leave %04x\n", rPC<<1);
726bbb3e 895 }
896// debug_dump2file("tcache.bin", tcache, (tcache_ptr - tcache) << 1);
897// exit(1);
898}
899