rom_data -> rom_loaded
[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
726bbb3e 11static int nblocks = 0;
df143b36 12static int iram_context = 0;
726bbb3e 13
5d817c91 14#ifndef ARM
a6fb500b 15#define DUMP_BLOCK 0x240a
5d817c91 16unsigned int tcache[512*1024];
17void regfile_load(void){}
18void regfile_store(void){}
19#endif
20
726bbb3e 21#define EMBED_INTERPRETER
22#define ssp1601_reset ssp1601_reset_local
23#define ssp1601_run ssp1601_run_local
24
5c129565 25#define GET_PC() rPC
26#define GET_PPC_OFFS() (GET_PC()*2 - 2)
d274c33b 27#define SET_PC(d) { rPC = d; } /* must return to dispatcher after this */
726bbb3e 28//#define GET_PC() (PC - (unsigned short *)svp->iram_rom)
29//#define GET_PPC_OFFS() ((unsigned int)PC - (unsigned int)svp->iram_rom - 2)
30//#define SET_PC(d) PC = (unsigned short *)svp->iram_rom + d
31
32#include "ssp16.c"
5c129565 33#include "gen_arm.c"
726bbb3e 34
35// -----------------------------------------------------
36
892b1dd2 37// ld d, s
38static void op00(unsigned int op, unsigned int imm)
39{
40 unsigned int tmpv;
259ed0ea 41 PC = ((unsigned short *)(void *)&op) + 1; /* FIXME: needed for interpreter */
892b1dd2 42 if (op == 0) return; // nop
43 if (op == ((SSP_A<<4)|SSP_P)) { // A <- P
44 // not sure. MAME claims that only hi word is transfered.
45 read_P(); // update P
46 rA32 = rP.v;
47 }
48 else
49 {
50 tmpv = REG_READ(op & 0x0f);
51 REG_WRITE((op & 0xf0) >> 4, tmpv);
52 }
53}
54
55// ld d, (ri)
56static void op01(unsigned int op, unsigned int imm)
57{
58 unsigned int tmpv;
59 tmpv = ptr1_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv);
60}
61
62// ld (ri), s
63static void op02(unsigned int op, unsigned int imm)
64{
65 unsigned int tmpv;
66 tmpv = REG_READ((op & 0xf0) >> 4); ptr1_write(op, tmpv);
67}
68
69// ldi d, imm
70static void op04(unsigned int op, unsigned int imm)
71{
72 REG_WRITE((op & 0xf0) >> 4, imm);
73}
74
75// ld d, ((ri))
76static void op05(unsigned int op, unsigned int imm)
77{
78 unsigned int tmpv;
79 tmpv = ptr2_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv);
80}
81
82// ldi (ri), imm
83static void op06(unsigned int op, unsigned int imm)
84{
85 ptr1_write(op, imm);
86}
87
88// ld adr, a
89static void op07(unsigned int op, unsigned int imm)
90{
91 ssp->RAM[op & 0x1ff] = rA;
92}
93
94// ld d, ri
95static void op09(unsigned int op, unsigned int imm)
96{
97 unsigned int tmpv;
98 tmpv = rIJ[(op&3)|((op>>6)&4)]; REG_WRITE((op & 0xf0) >> 4, tmpv);
99}
100
101// ld ri, s
102static void op0a(unsigned int op, unsigned int imm)
103{
104 rIJ[(op&3)|((op>>6)&4)] = REG_READ((op & 0xf0) >> 4);
105}
106
107// ldi ri, simm (also op0d op0e op0f)
108static void op0c(unsigned int op, unsigned int imm)
109{
110 rIJ[(op>>8)&7] = op;
111}
112
113// call cond, addr
114static void op24(unsigned int op, unsigned int imm)
115{
116 int cond = 0;
117 do {
118 COND_CHECK
259ed0ea 119 if (cond) { int new_PC = imm; write_STACK(GET_PC()); SET_PC(new_PC); }
892b1dd2 120 }
121 while (0);
122}
123
124// ld d, (a)
125static void op25(unsigned int op, unsigned int imm)
126{
127 unsigned int tmpv;
128 tmpv = ((unsigned short *)svp->iram_rom)[rA]; REG_WRITE((op & 0xf0) >> 4, tmpv);
129}
130
131// bra cond, addr
132static void op26(unsigned int op, unsigned int imm)
133{
134 do
135 {
136 int cond = 0;
137 COND_CHECK
259ed0ea 138 if (cond) SET_PC(imm);
892b1dd2 139 }
259ed0ea 140 while (0);
892b1dd2 141}
142
143// mod cond, op
144static void op48(unsigned int op, unsigned int imm)
145{
146 do
147 {
148 int cond = 0;
149 COND_CHECK
150 if (cond) {
151 switch (op & 7) {
152 case 2: rA32 = (signed int)rA32 >> 1; break; // shr (arithmetic)
153 case 3: rA32 <<= 1; break; // shl
154 case 6: rA32 = -(signed int)rA32; break; // neg
155 case 7: if ((int)rA32 < 0) rA32 = -(signed int)rA32; break; // abs
156 default: elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: unhandled mod %i @ %04x",
157 op&7, GET_PPC_OFFS());
158 }
159 UPD_ACC_ZN // ?
160 }
161 }
162 while(0);
163}
164
165// mpys?
166static void op1b(unsigned int op, unsigned int imm)
167{
168 read_P(); // update P
169 rA32 -= rP.v; // maybe only upper word?
170 UPD_ACC_ZN // there checking flags after this
171 rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
172 rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
173}
174
175// mpya (rj), (ri), b
176static void op4b(unsigned int op, unsigned int imm)
177{
178 read_P(); // update P
179 rA32 += rP.v; // confirmed to be 32bit
180 UPD_ACC_ZN // ?
181 rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
182 rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
183}
184
185// mld (rj), (ri), b
186static void op5b(unsigned int op, unsigned int imm)
187{
188 rA32 = 0;
189 rST &= 0x0fff; // ?
190 rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
191 rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
192}
193
194// OP a, s
195static void op10(unsigned int op, unsigned int imm)
196{
197 do
198 {
199 unsigned int tmpv;
200 OP_CHECK32(OP_SUBA32); tmpv = REG_READ(op & 0x0f); OP_SUBA(tmpv);
201 }
202 while(0);
203}
204
205static void op30(unsigned int op, unsigned int imm)
206{
207 do
208 {
209 unsigned int tmpv;
210 OP_CHECK32(OP_CMPA32); tmpv = REG_READ(op & 0x0f); OP_CMPA(tmpv);
211 }
212 while(0);
213}
214
215static void op40(unsigned int op, unsigned int imm)
216{
217 do
218 {
219 unsigned int tmpv;
220 OP_CHECK32(OP_ADDA32); tmpv = REG_READ(op & 0x0f); OP_ADDA(tmpv);
221 }
222 while(0);
223}
224
225static void op50(unsigned int op, unsigned int imm)
226{
227 do
228 {
229 unsigned int tmpv;
230 OP_CHECK32(OP_ANDA32); tmpv = REG_READ(op & 0x0f); OP_ANDA(tmpv);
231 }
232 while(0);
233}
234
235static void op60(unsigned int op, unsigned int imm)
236{
237 do
238 {
239 unsigned int tmpv;
240 OP_CHECK32(OP_ORA32 ); tmpv = REG_READ(op & 0x0f); OP_ORA (tmpv);
241 }
242 while(0);
243}
244
245static void op70(unsigned int op, unsigned int imm)
246{
247 do
248 {
249 unsigned int tmpv;
250 OP_CHECK32(OP_EORA32); tmpv = REG_READ(op & 0x0f); OP_EORA(tmpv);
251 }
252 while(0);
253}
254
255// OP a, (ri)
256static void op11(unsigned int op, unsigned int imm)
257{
258 unsigned int tmpv;
259 tmpv = ptr1_read(op); OP_SUBA(tmpv);
260}
261
262static void op31(unsigned int op, unsigned int imm)
263{
264 unsigned int tmpv;
265 tmpv = ptr1_read(op); OP_CMPA(tmpv);
266}
267
268static void op41(unsigned int op, unsigned int imm)
269{
270 unsigned int tmpv;
271 tmpv = ptr1_read(op); OP_ADDA(tmpv);
272}
273
274static void op51(unsigned int op, unsigned int imm)
275{
276 unsigned int tmpv;
277 tmpv = ptr1_read(op); OP_ANDA(tmpv);
278}
279
280static void op61(unsigned int op, unsigned int imm)
281{
282 unsigned int tmpv;
283 tmpv = ptr1_read(op); OP_ORA (tmpv);
284}
285
286static void op71(unsigned int op, unsigned int imm)
287{
288 unsigned int tmpv;
289 tmpv = ptr1_read(op); OP_EORA(tmpv);
290}
291
292// OP a, adr
293static void op03(unsigned int op, unsigned int imm)
294{
295 unsigned int tmpv;
296 tmpv = ssp->RAM[op & 0x1ff]; OP_LDA (tmpv);
297}
298
299static void op13(unsigned int op, unsigned int imm)
300{
301 unsigned int tmpv;
302 tmpv = ssp->RAM[op & 0x1ff]; OP_SUBA(tmpv);
303}
304
305static void op33(unsigned int op, unsigned int imm)
306{
307 unsigned int tmpv;
308 tmpv = ssp->RAM[op & 0x1ff]; OP_CMPA(tmpv);
309}
310
311static void op43(unsigned int op, unsigned int imm)
312{
313 unsigned int tmpv;
314 tmpv = ssp->RAM[op & 0x1ff]; OP_ADDA(tmpv);
315}
316
317static void op53(unsigned int op, unsigned int imm)
318{
319 unsigned int tmpv;
320 tmpv = ssp->RAM[op & 0x1ff]; OP_ANDA(tmpv);
321}
322
323static void op63(unsigned int op, unsigned int imm)
324{
325 unsigned int tmpv;
326 tmpv = ssp->RAM[op & 0x1ff]; OP_ORA (tmpv);
327}
328
329static void op73(unsigned int op, unsigned int imm)
330{
331 unsigned int tmpv;
332 tmpv = ssp->RAM[op & 0x1ff]; OP_EORA(tmpv);
333}
334
335// OP a, imm
336static void op14(unsigned int op, unsigned int imm)
337{
338 OP_SUBA(imm);
339}
340
341static void op34(unsigned int op, unsigned int imm)
342{
343 OP_CMPA(imm);
344}
345
346static void op44(unsigned int op, unsigned int imm)
347{
348 OP_ADDA(imm);
349}
350
351static void op54(unsigned int op, unsigned int imm)
352{
353 OP_ANDA(imm);
354}
355
356static void op64(unsigned int op, unsigned int imm)
357{
358 OP_ORA (imm);
359}
360
361static void op74(unsigned int op, unsigned int imm)
362{
363 OP_EORA(imm);
364}
365
366// OP a, ((ri))
367static void op15(unsigned int op, unsigned int imm)
368{
369 unsigned int tmpv;
370 tmpv = ptr2_read(op); OP_SUBA(tmpv);
371}
372
373static void op35(unsigned int op, unsigned int imm)
374{
375 unsigned int tmpv;
376 tmpv = ptr2_read(op); OP_CMPA(tmpv);
377}
378
379static void op45(unsigned int op, unsigned int imm)
380{
381 unsigned int tmpv;
382 tmpv = ptr2_read(op); OP_ADDA(tmpv);
383}
384
385static void op55(unsigned int op, unsigned int imm)
386{
387 unsigned int tmpv;
388 tmpv = ptr2_read(op); OP_ANDA(tmpv);
389}
390
391static void op65(unsigned int op, unsigned int imm)
392{
393 unsigned int tmpv;
394 tmpv = ptr2_read(op); OP_ORA (tmpv);
395}
396
397static void op75(unsigned int op, unsigned int imm)
398{
399 unsigned int tmpv;
400 tmpv = ptr2_read(op); OP_EORA(tmpv);
401}
402
403// OP a, ri
404static void op19(unsigned int op, unsigned int imm)
405{
406 unsigned int tmpv;
407 tmpv = rIJ[IJind]; OP_SUBA(tmpv);
408}
409
410static void op39(unsigned int op, unsigned int imm)
411{
412 unsigned int tmpv;
413 tmpv = rIJ[IJind]; OP_CMPA(tmpv);
414}
415
416static void op49(unsigned int op, unsigned int imm)
417{
418 unsigned int tmpv;
419 tmpv = rIJ[IJind]; OP_ADDA(tmpv);
420}
421
422static void op59(unsigned int op, unsigned int imm)
423{
424 unsigned int tmpv;
425 tmpv = rIJ[IJind]; OP_ANDA(tmpv);
426}
427
428static void op69(unsigned int op, unsigned int imm)
429{
430 unsigned int tmpv;
431 tmpv = rIJ[IJind]; OP_ORA (tmpv);
432}
433
434static void op79(unsigned int op, unsigned int imm)
435{
436 unsigned int tmpv;
437 tmpv = rIJ[IJind]; OP_EORA(tmpv);
438}
439
440// OP simm
441static void op1c(unsigned int op, unsigned int imm)
442{
443 OP_SUBA(op & 0xff);
444}
445
446static void op3c(unsigned int op, unsigned int imm)
447{
448 OP_CMPA(op & 0xff);
449}
450
451static void op4c(unsigned int op, unsigned int imm)
452{
453 OP_ADDA(op & 0xff);
454}
455
456static void op5c(unsigned int op, unsigned int imm)
457{
458 OP_ANDA(op & 0xff);
459}
460
461static void op6c(unsigned int op, unsigned int imm)
462{
463 OP_ORA (op & 0xff);
464}
465
466static void op7c(unsigned int op, unsigned int imm)
467{
468 OP_EORA(op & 0xff);
469}
470
471typedef void (in_func)(unsigned int op, unsigned int imm);
472
473static in_func *in_funcs[0x80] =
474{
475 op00, op01, op02, op03, op04, op05, op06, op07,
476 NULL, op09, op0a, NULL, op0c, op0c, op0c, op0c,
477 op10, op11, NULL, op13, op14, op15, NULL, NULL,
478 NULL, op19, NULL, op1b, op1c, NULL, NULL, NULL,
479 NULL, NULL, NULL, NULL, op24, op25, op26, NULL,
480 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
481 op30, op31, NULL, op33, op34, op35, NULL, NULL,
482 NULL, op39, NULL, NULL, op3c, NULL, NULL, NULL,
483 op40, op41, NULL, op43, op44, op45, NULL, NULL,
484 op48, op49, NULL, op4b, op4c, NULL, NULL, NULL,
485 op50, op51, NULL, op53, op54, op55, NULL, NULL,
486 NULL, op59, NULL, op5b, op5c, NULL, NULL, NULL,
487 op60, op61, NULL, op63, op64, op65, NULL, NULL,
488 NULL, op69, NULL, NULL, op6c, NULL, NULL, NULL,
489 op70, op71, NULL, op73, op74, op75, NULL, NULL,
490 NULL, op79, NULL, NULL, op7c, NULL, NULL, NULL,
491};
492
493// -----------------------------------------------------
494
df143b36 495static unsigned char iram_context_map[] =
496{
497 0, 0, 0, 0, 1, 0, 0, 0, // 04
498 0, 0, 0, 0, 0, 0, 2, 0, // 0e
499 0, 0, 0, 0, 0, 3, 0, 4, // 15 17
500 5, 0, 0, 6, 0, 7, 0, 0, // 18 1b 1d
501 8, 9, 0, 0, 0,10, 0, 0, // 20 21 25
502 0, 0, 0, 0, 0, 0, 0, 0,
503 0, 0,11, 0, 0,12, 0, 0, // 32 35
504 13,14, 0, 0, 0, 0, 0, 0 // 38 39
505};
506
df143b36 507static int get_iram_context(void)
508{
509 unsigned char *ir = (unsigned char *)svp->iram_rom;
510 int val1, val = ir[0x083^1] + ir[0x4FA^1] + ir[0x5F7^1] + ir[0x47B^1];
df143b36 511 val1 = iram_context_map[(val>>1)&0x3f];
512
5c129565 513 if (val1 == 0) {
df143b36 514 printf("val: %02x PC=%04x\n", (val>>1)&0x3f, rPC);
df143b36 515 //debug_dump2file(name, svp->iram_rom, 0x800);
516 exit(1);
517 }
5c129565 518// elprintf(EL_ANOMALY, "iram_context: %02i", val1);
df143b36 519 return val1;
520}
521
5d817c91 522// -----------------------------------------------------
523/*
524enum {
525 SSP_GR0, SSP_X, SSP_Y, SSP_A,
526 SSP_ST, SSP_STACK, SSP_PC, SSP_P,
527 SSP_PM0, SSP_PM1, SSP_PM2, SSP_XST,
528 SSP_PM4, SSP_gr13, SSP_PMC, SSP_AL
529};
530*/
531/* regs with known values */
532static struct
533{
534 ssp_reg_t gr[8];
535 unsigned char r[8];
bad5731d 536} known_regs;
537
538#define KRREG_X (1 << SSP_X)
539#define KRREG_Y (1 << SSP_Y)
540#define KRREG_A (1 << SSP_A) /* AH only */
541#define KRREG_ST (1 << SSP_ST)
542#define KRREG_STACK (1 << SSP_STACK)
543#define KRREG_PC (1 << SSP_PC)
544#define KRREG_P (1 << SSP_P)
545#define KRREG_PR0 (1 << 8)
546#define KRREG_PR4 (1 << 12)
547#define KRREG_AL (1 << 16)
548
549/* bitfield of known register values */
550static u32 known_regb = 0;
551
552/* known vals, which need to be flushed
553 * (only ST, P, r0-r7)
554 * ST means flags are being held in ARM PSR
555 */
556static u32 dirty_regb = 0;
5d817c91 557
558/* known values of host regs.
d274c33b 559 * -1 - unknown
560 * 000000-00ffff - 16bit value
561 * 100000-10ffff - base reg (r7) + 16bit val
562 * 0r0000 - means reg (low) eq gr[r].h
5d817c91 563 */
564static int hostreg_r[4];
565
566static void hostreg_clear(void)
567{
568 int i;
569 for (i = 0; i < 4; i++)
570 hostreg_r[i] = -1;
571}
572
bad5731d 573// TODO
5d817c91 574/*static*/ void hostreg_ah_changed(void)
575{
576 int i;
577 for (i = 0; i < 4; i++)
d274c33b 578 if (hostreg_r[i] == (SSP_A<<16)) hostreg_r[i] = -1;
5d817c91 579}
580
726bbb3e 581
5c129565 582#define PROGRAM(x) ((unsigned short *)svp->iram_rom)[x]
726bbb3e 583
d274c33b 584/* update P, if needed. Trashes r1 */
585static void tr_flush_dirty_P(void)
586{
587 // TODO: const regs
bad5731d 588 if (!(dirty_regb & KRREG_P)) return;
d274c33b 589 EOP_MOV_REG_ASR(10, 4, 16); // mov r10, r4, asr #16
590 EOP_MOV_REG_LSL( 1, 4, 16); // mov r1, r4, lsl #16
591 EOP_MOV_REG_ASR( 1, 1, 15); // mov r1, r1, asr #15
592 EOP_MUL(10, 1, 10); // mul r10, r1, r10
bad5731d 593 dirty_regb &= ~KRREG_P;
d274c33b 594}
595
5d817c91 596/* write dirty r0-r7 to host regs. Nothing is trashed */
d274c33b 597static void tr_flush_dirty_pr(void)
5d817c91 598{
599 int i, ror = 0, reg;
bad5731d 600 int dirty = dirty_regb >> 8;
5d817c91 601 /* r0-r7 */
bad5731d 602 for (i = 0; dirty && i < 8; i++, dirty >>= 1)
5d817c91 603 {
bad5731d 604 if (!(dirty&1)) continue;
5d817c91 605 switch (i&3) {
606 case 0: ror = 0; break;
607 case 1: ror = 24/2; break;
608 case 2: ror = 16/2; break;
609 }
610 reg = (i < 4) ? 8 : 9;
611 EOP_BIC_IMM(reg,reg,ror,0xff);
bad5731d 612 if (known_regs.r[i] != 0)
613 EOP_ORR_IMM(reg,reg,ror,known_regs.r[i]);
5d817c91 614 }
bad5731d 615 dirty_regb &= ~0xff00;
616}
617
618/* fush ARM PSR to r6. Trashes r0 */
619static void tr_flush_dirty_ST(void)
620{
621 if (!(dirty_regb & KRREG_ST)) return;
622 EOP_BIC_IMM(6,6,0,0x0f);
623 EOP_MRS(0);
624 EOP_ORR_REG_LSR(6,6,0,28);
625 dirty_regb &= ~KRREG_ST;
626 hostreg_r[0] = -1;
627}
628
629/* load 16bit val into host reg r0-r3. Nothing is trashed */
630static void tr_mov16(int r, int val)
631{
632 if (hostreg_r[r] != val) {
633 emit_mov_const(A_COND_AL, r, val);
634 hostreg_r[r] = val;
635 }
636}
637
638static void tr_mov16_cond(int cond, int r, int val)
639{
640 emit_mov_const(cond, r, val);
a6fb500b 641 hostreg_r[r] = -1;
5d817c91 642}
643
bad5731d 644/* read bank word to r0. Thrashes r1. */
5d817c91 645static void tr_bank_read(int addr) /* word addr 0-0x1ff */
646{
bad5731d 647 int breg = 7;
648 if (addr > 0x7f) {
649 if (hostreg_r[1] != (0x100000|((addr&0x180)<<1))) {
650 EOP_ADD_IMM(1,7,30/2,(addr&0x180)>>1); // add r1, r7, ((op&0x180)<<1)
651 hostreg_r[1] = 0x100000|((addr&0x180)<<1);
5d817c91 652 }
bad5731d 653 breg = 1;
5d817c91 654 }
bad5731d 655 EOP_LDRH_IMM(0,breg,(addr&0x7f)<<1); // ldrh r0, [r1, (op&0x7f)<<1]
5d817c91 656 hostreg_r[0] = -1;
657}
658
659/* write r0 to bank. Trashes r1. */
660static void tr_bank_write(int addr)
661{
662 int breg = 7;
663 if (addr > 0x7f) {
d274c33b 664 if (hostreg_r[1] != (0x100000|((addr&0x180)<<1))) {
5d817c91 665 EOP_ADD_IMM(1,7,30/2,(addr&0x180)>>1); // add r1, r7, ((op&0x180)<<1)
d274c33b 666 hostreg_r[1] = 0x100000|((addr&0x180)<<1);
5d817c91 667 }
668 breg = 1;
669 }
b9c1d012 670 EOP_STRH_IMM(0,breg,(addr&0x7f)<<1); // strh r0, [r1, (op&0x7f)<<1]
5d817c91 671}
672
673/* handle RAM bank pointer modifiers. Nothing is trashed. */
674static void tr_ptrr_mod(int r, int mod, int need_modulo)
675{
a6fb500b 676 int modulo_shift = -1; /* unknown */
5d817c91 677
678 if (mod == 0) return;
679
680 if (!need_modulo || mod == 1) // +!
681 modulo_shift = 8;
bad5731d 682 else if (need_modulo && (known_regb & KRREG_ST)) {
683 modulo_shift = known_regs.gr[SSP_ST].h & 7;
5d817c91 684 if (modulo_shift == 0) modulo_shift = 8;
685 }
686
a6fb500b 687 if (mod > 1 && modulo_shift == -1) {
688/* TODO
689 int reg = (r < 4) ? 8 : 9;
690 int ror = ((r&3) + 1)*8 - (8 - modulo_shift);
691 EOP_MOV_REG_ROR(reg,reg,ror);
692 // {add|sub} reg, reg, #1<<shift
693 EOP_C_DOP_IMM(A_COND_AL,(mod==2)?A_OP_SUB:A_OP_ADD,0,reg,reg, 8/2, 1<<(8 - modulo_shift));
694 EOP_MOV_REG_ROR(reg,reg,32-ror);
695*/
5d817c91 696
a6fb500b 697 printf("need var modulo\n"); exit(1);
698 }
699 else if (known_regb & (1 << (r + 8)))
700 {
701 int modulo = (1 << modulo_shift) - 1;
5d817c91 702 if (mod == 2)
bad5731d 703 known_regs.r[r] = (known_regs.r[r] & ~modulo) | ((known_regs.r[r] - 1) & modulo);
704 else known_regs.r[r] = (known_regs.r[r] & ~modulo) | ((known_regs.r[r] + 1) & modulo);
a6fb500b 705 }
706 else
707 {
5d817c91 708 int reg = (r < 4) ? 8 : 9;
709 int ror = ((r&3) + 1)*8 - (8 - modulo_shift);
710 EOP_MOV_REG_ROR(reg,reg,ror);
711 // {add|sub} reg, reg, #1<<shift
712 EOP_C_DOP_IMM(A_COND_AL,(mod==2)?A_OP_SUB:A_OP_ADD,0,reg,reg, 8/2, 1<<(8 - modulo_shift));
713 EOP_MOV_REG_ROR(reg,reg,32-ror);
714 }
715}
716
bad5731d 717/* handle writes r0 to (rX). Trashes r1.
718 * fortunately we can ignore modulo increment modes for writes. */
719static void tr_rX_write1(int op)
720{
721 if ((op&3) == 3)
722 {
723 int mod = (op>>2) & 3; // direct addressing
724 tr_bank_write((op & 0x100) + mod);
725 }
726 else
727 {
728 int r = (op&3) | ((op>>6)&4);
729 if (known_regb & (1 << (r + 8))) {
730 tr_bank_write((op&0x100) | known_regs.r[r]);
731 } else {
732 int reg = (r < 4) ? 8 : 9;
733 int ror = ((4 - (r&3))*8) & 0x1f;
734 EOP_AND_IMM(1,reg,ror/2,0xff); // and r1, r{7,8}, <mask>
735 if (r >= 4)
736 EOP_ORR_IMM(1,1,((ror-8)&0x1f)/2,1); // orr r1, r1, 1<<shift
737 if (r&3) EOP_ADD_REG_LSR(1,7,1, (r&3)*8-1); // add r1, r7, r1, lsr #lsr
738 else EOP_ADD_REG_LSL(1,7,1,1);
739 EOP_STRH_SIMPLE(0,1); // strh r0, [r1]
740 hostreg_r[1] = -1;
741 }
742 tr_ptrr_mod(r, (op>>2) & 3, 0);
743 }
744}
745
746/* get ARM cond which would mean that SSP cond is satisfied. No trash. */
747static int tr_cond_check(int op)
748{
749 int f = op & 0x100;
750 switch (op&0xf0) {
751 case 0x00: return A_COND_AL; /* always true */
752 case 0x50: /* Z matches f(?) bit */
753 if (dirty_regb & KRREG_ST) return f ? A_COND_EQ : A_COND_NE;
754 EOP_TST_IMM(6, 0, 4);
755 return f ? A_COND_NE : A_COND_EQ;
756 case 0x70: /* N matches f(?) bit */
757 if (dirty_regb & KRREG_ST) return f ? A_COND_MI : A_COND_PL;
758 EOP_TST_IMM(6, 0, 8);
759 return f ? A_COND_NE : A_COND_EQ;
760 default:
761 printf("unimplemented cond?\n");
762 exit(1);
763 return 0;
764 }
765}
766
767static int tr_neg_cond(int cond)
768{
769 switch (cond) {
770 case A_COND_AL: printf("neg for AL?\n"); exit(1);
771 case A_COND_EQ: return A_COND_NE;
772 case A_COND_NE: return A_COND_EQ;
773 case A_COND_MI: return A_COND_PL;
774 case A_COND_PL: return A_COND_MI;
775 default: printf("bad cond for neg\n"); exit(1);
776 }
777 return 0;
778}
779
b9c1d012 780// SSP_GR0, SSP_X, SSP_Y, SSP_A,
781// SSP_ST, SSP_STACK, SSP_PC, SSP_P,
782//@ r4: XXYY
783//@ r5: A
784//@ r6: STACK and emu flags
785//@ r7: SSP context
786//@ r10: P
787
bad5731d 788// read general reg to r0. Trashes r1
d274c33b 789static void tr_GR0_to_r0(void)
790{
791 tr_mov16(0, 0xffff);
792}
793
794static void tr_X_to_r0(void)
795{
796 if (hostreg_r[0] != (SSP_X<<16)) {
797 EOP_MOV_REG_LSR(0, 4, 16); // mov r0, r4, lsr #16
798 hostreg_r[0] = SSP_X<<16;
799 }
800}
801
802static void tr_Y_to_r0(void)
803{
804 // TODO..
805 if (hostreg_r[0] != (SSP_Y<<16)) {
806 EOP_MOV_REG_SIMPLE(0, 4); // mov r0, r4
807 hostreg_r[0] = SSP_Y<<16;
808 }
809}
810
811static void tr_A_to_r0(void)
812{
813 if (hostreg_r[0] != (SSP_A<<16)) {
814 EOP_MOV_REG_LSR(0, 5, 16); // mov r0, r5, lsr #16 @ AH
815 hostreg_r[0] = SSP_A<<16;
816 }
817}
818
819static void tr_ST_to_r0(void)
820{
821 // VR doesn't need much accuracy here..
822 EOP_MOV_REG_LSR(0, 6, 4); // mov r0, r6, lsr #4
823 EOP_AND_IMM(0, 0, 0, 0x67); // and r0, r0, #0x67
824 hostreg_r[0] = -1;
825}
826
827static void tr_STACK_to_r0(void)
828{
829 // 448
830 EOP_SUB_IMM(6, 6, 8/2, 0x20); // sub r6, r6, #1<<29
831 EOP_ADD_IMM(1, 7, 24/2, 0x04); // add r1, r7, 0x400
832 EOP_ADD_IMM(1, 1, 0, 0x48); // add r1, r1, 0x048
833 EOP_ADD_REG_LSR(1, 1, 6, 28); // add r1, r1, r6, lsr #28
834 EOP_LDRH_SIMPLE(0, 1); // ldrh r0, [r1]
835 hostreg_r[0] = hostreg_r[1] = -1;
836}
837
838static void tr_PC_to_r0(void)
839{
bad5731d 840 tr_mov16(0, known_regs.gr[SSP_PC].h);
d274c33b 841}
842
843static void tr_P_to_r0(void)
844{
845 tr_flush_dirty_P();
846 EOP_MOV_REG_LSR(0, 10, 16); // mov r0, r10, lsr #16
847 hostreg_r[0] = -1;
848}
849
850typedef void (tr_read_func)(void);
851
852static tr_read_func *tr_read_funcs[8] =
853{
854 tr_GR0_to_r0,
855 tr_X_to_r0,
856 tr_Y_to_r0,
857 tr_A_to_r0,
858 tr_ST_to_r0,
859 tr_STACK_to_r0,
860 tr_PC_to_r0,
861 tr_P_to_r0
862};
863
864
b9c1d012 865// write r0 to general reg handlers. Trashes r1
d274c33b 866static void tr_unhandled(void)
b9c1d012 867{
bad5731d 868 printf("unhandled @ %04x\n", known_regs.gr[SSP_PC].h<<1);
b9c1d012 869 exit(1);
870}
871
872static void tr_r0_to_GR0(void)
873{
874 // do nothing
875}
876
877static void tr_r0_to_X(void)
878{
879 EOP_MOV_REG_LSL(4, 4, 16); // mov r4, r4, lsl #16
880 EOP_MOV_REG_LSR(4, 4, 16); // mov r4, r4, lsr #16
881 EOP_ORR_REG_LSL(4, 4, 0, 16); // orr r4, r4, r0, lsl #16
bad5731d 882 dirty_regb |= KRREG_P; // touching X or Y makes P dirty.
883 hostreg_r[0] = SSP_X<<16;
b9c1d012 884}
885
886static void tr_r0_to_Y(void)
887{
888 EOP_MOV_REG_LSR(4, 4, 16); // mov r4, r4, lsr #16
889 EOP_ORR_REG_LSL(4, 4, 0, 16); // orr r4, r4, r0, lsl #16
890 EOP_MOV_REG_ROR(4, 4, 16); // mov r4, r4, ror #16
bad5731d 891 dirty_regb |= KRREG_P;
892 hostreg_r[0] = SSP_Y<<16;
b9c1d012 893}
894
895static void tr_r0_to_A(void)
896{
897 EOP_MOV_REG_LSL(5, 5, 16); // mov r5, r5, lsl #16
d274c33b 898 EOP_MOV_REG_LSR(5, 5, 16); // mov r5, r5, lsr #16 @ AL
b9c1d012 899 EOP_ORR_REG_LSL(5, 5, 0, 16); // orr r5, r5, r0, lsl #16
bad5731d 900 hostreg_r[0] = SSP_A<<16;
b9c1d012 901}
902
903static void tr_r0_to_ST(void)
904{
905 // VR doesn't need much accuracy here..
906 EOP_AND_IMM(1, 0, 0, 0x67); // and r1, r0, #0x67
907 EOP_AND_IMM(6, 6, 8/2, 0xe0); // and r6, r6, #7<<29 @ preserve STACK
908 EOP_ORR_REG_LSL(6, 6, 1, 4); // orr r6, r6, r1, lsl #4
909 hostreg_r[1] = -1;
910}
911
912static void tr_r0_to_STACK(void)
913{
914 // 448
915 EOP_ADD_IMM(1, 7, 24/2, 0x04); // add r1, r7, 0x400
916 EOP_ADD_IMM(1, 1, 0, 0x48); // add r1, r1, 0x048
d274c33b 917 EOP_ADD_REG_LSR(1, 1, 6, 28); // add r1, r1, r6, lsr #28
b9c1d012 918 EOP_STRH_SIMPLE(0, 1); // strh r0, [r1]
d274c33b 919 EOP_ADD_IMM(6, 6, 8/2, 0x20); // add r6, r6, #1<<29
b9c1d012 920 hostreg_r[1] = -1;
921}
922
923static void tr_r0_to_PC(void)
924{
925 EOP_MOV_REG_LSL(1, 0, 16); // mov r1, r0, lsl #16
d274c33b 926 EOP_STR_IMM(1,7,0x400+6*4); // str r1, [r7, #(0x400+6*8)]
b9c1d012 927 hostreg_r[1] = -1;
928}
929
930typedef void (tr_write_func)(void);
931
932static tr_write_func *tr_write_funcs[8] =
933{
934 tr_r0_to_GR0,
935 tr_r0_to_X,
936 tr_r0_to_Y,
937 tr_r0_to_A,
938 tr_r0_to_ST,
939 tr_r0_to_STACK,
940 tr_r0_to_PC,
d274c33b 941 tr_unhandled
b9c1d012 942};
943
5d817c91 944
945static int translate_op(unsigned int op, int *pc, int imm)
946{
d274c33b 947 u32 tmpv, tmpv2;
5d817c91 948 int ret = 0;
bad5731d 949 known_regs.gr[SSP_PC].h = *pc;
5d817c91 950
e807ac75 951 switch (op >> 9)
952 {
953 // ld d, s
f48f5e3b 954 case 0x00:
5d817c91 955 if (op == 0) { ret++; break; } // nop
d274c33b 956 tmpv = op & 0xf; // src
957 tmpv2 = (op >> 4) & 0xf; // dst
958 if (tmpv >= 8 || tmpv2 >= 8) return -1; // TODO
959 if (tmpv2 == SSP_A && tmpv == SSP_P) { // ld A, P
960 tr_flush_dirty_P();
961 EOP_MOV_REG_SIMPLE(5, 10);
bad5731d 962 known_regb &= ~(KRREG_A|KRREG_AL);
d274c33b 963 ret++; break;
964 }
965 tr_read_funcs[tmpv]();
966 tr_write_funcs[tmpv2]();
bad5731d 967 if (known_regb & (1 << tmpv)) {
968 known_regs.gr[tmpv2].h = known_regs.gr[tmpv].h;
969 known_regb |= 1 << tmpv2;
d274c33b 970 } else
bad5731d 971 known_regb &= ~(1 << tmpv2);
972 ret++; break;
973
974 // ld d, (ri)
975 //case 0x01: tmpv = ptr1_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv); break;
976
977 // ld (ri), s
978 case 0x02:
979 tmpv = (op >> 4) & 0xf; // src
980 if (tmpv >= 8) return -1; // TODO
981 tr_read_funcs[tmpv]();
982 tr_rX_write1(op);
d274c33b 983 ret++; break;
f48f5e3b 984
985 // ld a, adr
986 case 0x03:
5d817c91 987 tr_bank_read(op&0x1ff);
b9c1d012 988 tr_r0_to_A();
bad5731d 989 known_regb &= ~KRREG_A;
d274c33b 990 hostreg_r[0] = SSP_A<<16;
5d817c91 991 ret++; break;
992
b9c1d012 993 // ldi d, imm
994 case 0x04:
995 tmpv = (op & 0xf0) >> 4;
996 if (tmpv < 8)
997 {
998 tr_mov16(0, imm);
999 tr_write_funcs[tmpv]();
bad5731d 1000 known_regs.gr[tmpv].h = imm;
1001 known_regb |= 1 << tmpv;
a6fb500b 1002 ret += 2; break;
b9c1d012 1003 }
1004 else if (tmpv == 0xe && (PROGRAM(*pc) >> 9) == 4)
1005 {
1006 // programming PMC..
1007 (*pc)++;
1008 tmpv = imm | (PROGRAM((*pc)++) << 16);
a6fb500b 1009 ret += 2;
bad5731d 1010 emit_mov_const(A_COND_AL, 0, tmpv);
b9c1d012 1011 EOP_LDR_IMM(1,7,0x484); // ldr r0, [r7, #0x484] // emu_status
1012 EOP_STR_IMM(0,7,0x400+14*4); // PMC
d274c33b 1013 // reads on fe06, fe08; next op is ld -,
1014 if ((tmpv == 0x187f03 || tmpv == 0x187f04) && (PROGRAM(*pc) & 0xfff0) == 0)
1015 {
bad5731d 1016 int flag = (tmpv == 0x187f03) ? SSP_WAIT_30FE06 : SSP_WAIT_30FE08;
1017 tr_flush_dirty_ST();
b9c1d012 1018 EOP_LDR_IMM(0,7,0x490); // dram_ptr
1019 EOP_ADD_IMM(0,0,24/2,0xfe); // add r0, r0, #0xfe00
1020 EOP_LDRH_IMM(0,0,8); // ldrh r0, [r0, #8]
1021 EOP_TST_REG_SIMPLE(0,0);
d274c33b 1022 EOP_C_DOP_IMM(A_COND_EQ,A_OP_ADD,0,11,11,22/2,1); // add r11, r11, #1024
1023 EOP_C_DOP_IMM(A_COND_EQ,A_OP_ORR,0, 1, 1,24/2,flag>>8); // orr r1, r1, #SSP_WAIT_30FE08
b9c1d012 1024 }
1025 EOP_ORR_IMM(1,1,0,SSP_PMC_SET); // orr r1, r1, #SSP_PMC_SET
1026 EOP_STR_IMM(1,7,0x484); // str r1, [r7, #0x484] // emu_status
1027 hostreg_r[0] = hostreg_r[1] = -1;
1028 ret += 2; break;
1029 }
1030 else
1031 return -1; /* TODO.. */
1032
bad5731d 1033 // ld d, ((ri))
1034 case 0x05: {
1035 int r;
1036 r = (op&3) | ((op>>6)&4); // src
1037 tmpv2 = (op >> 4) & 0xf; // dst
1038 if (tmpv2 >= 8) return -1; // TODO
1039
1040 if ((r&3) == 3) {
1041 tr_bank_read((op&0x100) | ((op>>2)&3));
1042 } else if (known_regb & (1 << (r+8))) {
1043 tr_bank_read((op&0x100) | known_regs.r[r]);
1044 } else {
1045 int reg = (r < 4) ? 8 : 9;
1046 int ror = ((4 - (r&3))*8) & 0x1f;
1047 EOP_AND_IMM(1,reg,ror/2,0xff); // and r1, r{7,8}, <mask>
1048 if (r >= 4)
1049 EOP_ORR_IMM(1,1,((ror-8)&0x1f)/2,1); // orr r1, r1, 1<<shift
1050 if (r&3) EOP_ADD_REG_LSR(1,7,1, (r&3)*8-1); // add r1, r7, r1, lsr #lsr
1051 else EOP_ADD_REG_LSL(1,7,1,1);
1052 EOP_LDRH_SIMPLE(0,1); // ldrh r0, [r1]
1053 }
1054 EOP_LDR_IMM(2,7,0x48c); // ptr_iram_rom
1055 EOP_ADD_REG_LSL(2,2,0,1); // add r2, r2, r0, lsl #1
1056 EOP_ADD_IMM(0,0,0,1); // add r0, r0, #1
1057 if ((r&3) == 3) {
1058 tr_bank_write((op&0x100) | ((op>>2)&3));
1059 } else if (known_regb & (1 << (r+8))) {
1060 tr_bank_write((op&0x100) | known_regs.r[r]);
1061 } else {
1062 EOP_STRH_SIMPLE(0,1); // strh r0, [r1]
1063 hostreg_r[1] = -1;
1064 }
1065 EOP_LDRH_SIMPLE(0,2); // ldrh r0, [r0]
1066 hostreg_r[0] = hostreg_r[2] = -1;
a6fb500b 1067 known_regb &= ~(1 << tmpv2);
bad5731d 1068 tr_write_funcs[tmpv2]();
a6fb500b 1069 ret += 3; break; /* should certainly take > 1 */
bad5731d 1070 }
b9c1d012 1071
5d817c91 1072 // ldi (ri), imm
1073 case 0x06:
5d817c91 1074 tr_mov16(0, imm);
bad5731d 1075 tr_rX_write1(op);
a6fb500b 1076 ret += 2; break;
f48f5e3b 1077
1078 // ld adr, a
1079 case 0x07:
d274c33b 1080 if (hostreg_r[0] != (SSP_A<<16)) {
5d817c91 1081 EOP_MOV_REG_LSR(0, 5, 16); // mov r0, r5, lsr #16 @ A
d274c33b 1082 hostreg_r[0] = SSP_A<<16;
5d817c91 1083 }
1084 tr_bank_write(op&0x1ff);
1085 ret++; break;
1086
d274c33b 1087 // ld d, ri
1088 case 0x09: {
bad5731d 1089 int r;
d274c33b 1090 r = (op&3) | ((op>>6)&4); // src
bad5731d 1091 tmpv2 = (op >> 4) & 0xf; // dst
d274c33b 1092 if (tmpv2 >= 8) tr_unhandled();
bad5731d 1093 if ((r&3) == 3) tr_unhandled();
d274c33b 1094
bad5731d 1095 if (known_regb & (1 << (r+8))) {
1096 tr_mov16(0, known_regs.r[r]);
1097 known_regs.gr[tmpv2].h = known_regs.r[r];
1098 known_regb |= 1 << tmpv2;
d274c33b 1099 } else {
bad5731d 1100 int reg = (r < 4) ? 8 : 9;
d274c33b 1101 if (r&3) EOP_MOV_REG_LSR(0, reg, (r&3)*8); // mov r0, r{7,8}, lsr #lsr
1102 EOP_AND_IMM(0, (r&3)?0:reg, 0, 0xff); // and r0, r{7,8}, <mask>
1103 hostreg_r[0] = -1;
bad5731d 1104 known_regb &= ~(1 << tmpv2);
d274c33b 1105 }
1106 tr_write_funcs[tmpv2]();
1107 ret++; break;
1108 }
1109
bad5731d 1110 // ld ri, s
1111 case 0x0a: {
1112 int r;
1113 r = (op&3) | ((op>>6)&4); // dst
1114 tmpv = (op >> 4) & 0xf; // src
1115 if (tmpv >= 8) tr_unhandled();
1116 if ((r&3) == 3) tr_unhandled();
1117
1118 if (known_regb & (1 << tmpv)) {
1119 known_regs.r[r] = known_regs.gr[tmpv].h;
1120 known_regb |= 1 << (r + 8);
1121 dirty_regb |= 1 << (r + 8);
1122 } else {
1123 int reg = (r < 4) ? 8 : 9;
1124 int ror = ((4 - (r&3))*8) & 0x1f;
1125 tr_read_funcs[tmpv]();
1126 EOP_BIC_IMM(reg, reg, ror/2, 0xff); // bic r{7,8}, r{7,8}, <mask>
1127 EOP_AND_IMM(0, 0, 0, 0xff); // and r0, r0, 0xff
1128 EOP_ORR_REG_LSL(reg, reg, 0, (r&3)*8); // orr r{7,8}, r{7,8}, r0, lsl #lsl
1129 hostreg_r[0] = -1;
1130 known_regb &= ~(1 << (r+8));
1131 dirty_regb &= ~(1 << (r+8));
1132 }
1133 ret++; break;
1134 }
1135
5d817c91 1136 // ldi ri, simm
1137 case 0x0c ... 0x0f:
1138 tmpv = (op>>8)&7;
bad5731d 1139 known_regs.r[tmpv] = op;
1140 known_regb |= 1 << (tmpv + 8);
5d817c91 1141 dirty_regb |= 1 << (tmpv + 8);
1142 ret++; break;
bad5731d 1143
a6fb500b 1144 // call cond, addr
1145 case 0x24:
1146 tr_mov16(0, *pc);
1147 tr_r0_to_STACK();
1148 tmpv = tr_cond_check(op);
1149 tr_mov16_cond(tmpv, 0, imm);
1150 if (tmpv != A_COND_AL) {
1151 tr_mov16_cond(tr_neg_cond(tmpv), 0, *pc);
1152 }
1153 tr_r0_to_PC();
1154 ret += 2; break;
1155
bad5731d 1156 // ld d, (a)
1157 case 0x25:
bad5731d 1158 tmpv2 = (op >> 4) & 0xf; // dst
1159 if (tmpv2 >= 8) return -1; // TODO
1160
a6fb500b 1161 tr_A_to_r0();
bad5731d 1162 EOP_LDR_IMM(1,7,0x48c); // ptr_iram_rom
1163 EOP_ADD_REG_LSL(0,1,0,1); // add r0, r1, r0, lsl #1
1164 EOP_LDRH_SIMPLE(0,0); // ldrh r0, [r0]
1165 hostreg_r[0] = hostreg_r[1] = -1;
a6fb500b 1166 known_regb &= ~(1 << tmpv2);
bad5731d 1167 tr_write_funcs[tmpv2]();
a6fb500b 1168 ret += 3; break;
bad5731d 1169
1170 // bra cond, addr
a6fb500b 1171 case 0x26:
bad5731d 1172 tmpv = tr_cond_check(op);
1173 tr_mov16_cond(tmpv, 0, imm);
1174 if (tmpv != A_COND_AL) {
bad5731d 1175 tr_mov16_cond(tr_neg_cond(tmpv), 0, *pc);
1176 }
a6fb500b 1177 tr_r0_to_PC();
1178 ret += 2; break;
bad5731d 1179
1180
1181/*
1182 // mpys?
1183 case 0x1b:
1184 read_P(); // update P
1185 rA32 -= rP.v; // maybe only upper word?
1186 UPD_ACC_ZN // there checking flags after this
1187 rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
1188 rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
1189 break;
1190
1191 // mpya (rj), (ri), b
1192 case 0x4b:
1193 read_P(); // update P
1194 rA32 += rP.v; // confirmed to be 32bit
1195 UPD_ACC_ZN // ?
1196 rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
1197 rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
1198 break;
1199
1200 // mld (rj), (ri), b
1201 case 0x5b:
1202 EOP_MOV_IMM(5, 0, 0); // mov r5, #0
1203 known_regs.r[SSP_A].v = 0;
1204 known_regb |= (KRREG_A|KRREG_AL);
1205 EOP_BIC_IMM(6, 6, 0, 0x0f); // bic r6, r6, 0xf // flags
a6fb500b 1206 EOP_BIC_IMM(6, 6, 0, 0x04); // bic r6, r6, 4 // set Z
bad5731d 1207 // TODO
1208 ret++; break;
1209*/
e807ac75 1210 }
1211
5d817c91 1212 return ret;
e807ac75 1213}
1214
df143b36 1215static void *translate_block(int pc)
726bbb3e 1216{
e807ac75 1217 unsigned int op, op1, imm, ccount = 0;
5c129565 1218 unsigned int *block_start;
d274c33b 1219 int ret, ret_prev = -1;
5c129565 1220
1221 // create .pool
e807ac75 1222 //*tcache_ptr++ = (u32) in_funcs; // -1 func pool
726bbb3e 1223
259ed0ea 1224 printf("translate %04x -> %04x\n", pc<<1, (tcache_ptr-tcache)<<2);
5c129565 1225 block_start = tcache_ptr;
bad5731d 1226 known_regb = 0;
1227 dirty_regb = KRREG_P;
5d817c91 1228 hostreg_clear();
5c129565 1229
1230 emit_block_prologue();
726bbb3e 1231
e807ac75 1232 for (; ccount < 100;)
726bbb3e 1233 {
259ed0ea 1234 //printf(" insn #%i\n", icount);
726bbb3e 1235 op = PROGRAM(pc++);
1236 op1 = op >> 9;
e807ac75 1237 imm = (u32)-1;
5c129565 1238
e807ac75 1239 if ((op1 & 0xf) == 4 || (op1 & 0xf) == 6)
1240 imm = PROGRAM(pc++); // immediate
5c129565 1241
5d817c91 1242 ret = translate_op(op, &pc, imm);
e807ac75 1243 if (ret <= 0)
1244 {
d274c33b 1245 tr_flush_dirty_pr();
5d817c91 1246
bad5731d 1247 emit_mov_const(A_COND_AL, 0, op);
5c129565 1248
e807ac75 1249 // need immediate?
1250 if (imm != (u32)-1)
bad5731d 1251 emit_mov_const(A_COND_AL, 1, imm);
5c129565 1252
e807ac75 1253 // dump PC
1254 emit_pc_dump(pc);
5c129565 1255
d274c33b 1256 if (ret_prev > 0) emit_call(regfile_store);
1257 emit_call(in_funcs[op1]);
1258 emit_call(regfile_load);
e807ac75 1259
1260 if (in_funcs[op1] == NULL) {
1261 printf("NULL func! op=%08x (%02x)\n", op, op1);
1262 exit(1);
1263 }
1264 ccount++;
5d817c91 1265 hostreg_clear();
bad5731d 1266 dirty_regb |= KRREG_P;
1267 known_regb = 0;
892b1dd2 1268 }
e807ac75 1269 else
1270 ccount += ret;
1271
726bbb3e 1272 if (op1 == 0x24 || op1 == 0x26 || // call, bra
1273 ((op1 == 0 || op1 == 1 || op1 == 4 || op1 == 5 || op1 == 9 || op1 == 0x25) &&
1274 (op & 0xf0) == 0x60)) { // ld PC
1275 break;
1276 }
d274c33b 1277 ret_prev = ret;
726bbb3e 1278 }
5c129565 1279
d274c33b 1280 tr_flush_dirty_pr();
e807ac75 1281 emit_block_epilogue(ccount + 1);
5c129565 1282 *tcache_ptr++ = 0xffffffff; // end of block
726bbb3e 1283 //printf(" %i inst\n", icount);
1284
892b1dd2 1285 if (tcache_ptr - tcache > TCACHE_SIZE/4) {
726bbb3e 1286 printf("tcache overflow!\n");
1287 fflush(stdout);
1288 exit(1);
1289 }
1290
1291 // stats
1292 nblocks++;
df143b36 1293 //if (pc >= 0x400)
892b1dd2 1294 printf("%i blocks, %i bytes\n", nblocks, (tcache_ptr - tcache)*4);
259ed0ea 1295 //printf("%p %p\n", tcache_ptr, emit_block_epilogue);
df143b36 1296
5d817c91 1297#ifdef DUMP_BLOCK
5c129565 1298 {
1299 FILE *f = fopen("tcache.bin", "wb");
1300 fwrite(tcache, 1, (tcache_ptr - tcache)*4, f);
1301 fclose(f);
1302 }
1303 exit(0);
1304#endif
259ed0ea 1305
1306 handle_caches();
1307
5c129565 1308 return block_start;
726bbb3e 1309}
1310
1311
1312
1313// -----------------------------------------------------
1314
e807ac75 1315int ssp1601_dyn_startup(void)
726bbb3e 1316{
e807ac75 1317 memset(tcache, 0, TCACHE_SIZE);
726bbb3e 1318 memset(block_table, 0, sizeof(block_table));
df143b36 1319 memset(block_table_iram, 0, sizeof(block_table_iram));
e807ac75 1320 tcache_ptr = tcache;
5c129565 1321 *tcache_ptr++ = 0xffffffff;
726bbb3e 1322
1323 return 0;
1324}
1325
1326
1327void ssp1601_dyn_reset(ssp1601_t *ssp)
1328{
1329 ssp1601_reset_local(ssp);
bad5731d 1330 ssp->ptr_rom = (unsigned int) Pico.rom;
1331 ssp->ptr_iram_rom = (unsigned int) svp->iram_rom;
d274c33b 1332 ssp->ptr_dram = (unsigned int) svp->dram;
726bbb3e 1333}
1334
726bbb3e 1335void ssp1601_dyn_run(int cycles)
1336{
b9c1d012 1337 if (ssp->emu_status & SSP_WAIT_MASK) return;
1338 //{ printf("%i wait\n", Pico.m.frame_count); return; }
1339 //printf("%i %04x\n", Pico.m.frame_count, rPC<<1);
1340
5d817c91 1341#ifdef DUMP_BLOCK
1342 rPC = DUMP_BLOCK >> 1;
1343#endif
726bbb3e 1344 while (cycles > 0)
1345 {
e807ac75 1346 int (*trans_entry)(void);
df143b36 1347 if (rPC < 0x800/2)
1348 {
1349 if (iram_dirty) {
1350 iram_context = get_iram_context();
892b1dd2 1351 iram_dirty--;
df143b36 1352 }
1353 if (block_table_iram[iram_context][rPC] == NULL)
1354 block_table_iram[iram_context][rPC] = translate_block(rPC);
5c129565 1355 trans_entry = (void *) block_table_iram[iram_context][rPC];
df143b36 1356 }
1357 else
1358 {
1359 if (block_table[rPC] == NULL)
1360 block_table[rPC] = translate_block(rPC);
5c129565 1361 trans_entry = (void *) block_table[rPC];
df143b36 1362 }
726bbb3e 1363
e807ac75 1364 //printf("enter %04x\n", rPC<<1);
1365 cycles -= trans_entry();
1366 //printf("leave %04x\n", rPC<<1);
726bbb3e 1367 }
1368// debug_dump2file("tcache.bin", tcache, (tcache_ptr - tcache) << 1);
1369// exit(1);
1370}
1371