\r
static char *rom_exts[] = { "bin", "gen", "smd", "iso" };\r
\r
+void (*PicoCartUnloadHook)(void) = NULL;\r
+\r
void (*PicoCartLoadProgressCB)(int percent) = NULL;\r
void (*PicoCDLoadProgressCB)(int percent) = NULL; // handled in Pico/cd/cd_file.c\r
\r
Pico.rom=rom;\r
Pico.romsize=romsize;\r
\r
+ if (PicoCartUnloadHook != NULL) {\r
+ PicoCartUnloadHook();\r
+ PicoCartUnloadHook = NULL;\r
+ }\r
+\r
PicoMemResetHooks();\r
PicoDmaHook = NULL;\r
PicoResetHook = NULL;\r
if (name_cmp("Virtua Racing") == 0 ||\r
name_cmp("VIRTUA RACING") == 0)\r
{\r
- PicoSVPInit();\r
+ PicoSVPStartup();\r
}\r
}\r
\r
z80_init(); // init even if we aren't going to use it\r
\r
PicoInitMCD();\r
+ PicoSVPInit();\r
\r
SRam.data=0;\r
\r
\r
// Cart.c\r
PICO_INTERNAL void PicoCartDetect(void);\r
+extern void (*PicoCartUnloadHook)(void);\r
\r
// Debug.c\r
int CM_compareRun(int cyc, int is_sub);\r
extern svp_t *svp;
void PicoSVPInit(void);
+void PicoSVPStartup(void);
unsigned int PicoSVPRead16(unsigned int a, int realsize);
void PicoSVPWrite8 (unsigned int a, unsigned int d, int realsize);
// 14 IRAM blocks
#include "../../PicoInt.h"
+#include "compiler.h"
-#define TCACHE_SIZE (1024*1024)
static unsigned int *block_table[0x5090/2];
static unsigned int *block_table_iram[15][0x800/2];
-static unsigned int *tcache = NULL;
static unsigned int *tcache_ptr = NULL;
static int had_jump = 0;
#define PROGRAM(x) ((unsigned short *)svp->iram_rom)[x]
+static int translate_op(unsigned int op, int *pc)
+{
+ switch (op >> 9)
+ {
+ // ld d, s
+ case 0x00: break;
+ }
+
+ return -1;
+}
+
static void *translate_block(int pc)
{
- unsigned int op, op1, icount = 0;
+ unsigned int op, op1, imm, ccount = 0;
unsigned int *block_start;
+ int ret;
// create .pool
- *tcache_ptr++ = (u32) &g_cycles; // -3 g_cycles
- *tcache_ptr++ = (u32) &ssp->gr[SSP_PC].v; // -2 ptr to rPC
- *tcache_ptr++ = (u32) in_funcs; // -1 func pool
+ //*tcache_ptr++ = (u32) in_funcs; // -1 func pool
printf("translate %04x -> %04x\n", pc<<1, (tcache_ptr-tcache)<<2);
block_start = tcache_ptr;
emit_block_prologue();
- for (; icount < 100;)
+ for (; ccount < 100;)
{
- icount++;
//printf(" insn #%i\n", icount);
op = PROGRAM(pc++);
op1 = op >> 9;
+ imm = (u32)-1;
- emit_mov_const(0, op);
+ if ((op1 & 0xf) == 4 || (op1 & 0xf) == 6)
+ imm = PROGRAM(pc++); // immediate
- // need immediate?
- if ((op1 & 0xf) == 4 || (op1 & 0xf) == 6) {
- emit_mov_const(1, PROGRAM(pc++)); // immediate
- }
+ ret = translate_op(op, &pc);
+ if (ret <= 0)
+ {
+ emit_mov_const(0, op);
- // dump PC
- emit_pc_inc(block_start, pc);
+ // need immediate?
+ if (imm != (u32)-1)
+ emit_mov_const(1, imm);
- emit_call(block_start, op1);
+ // dump PC
+ emit_pc_dump(pc);
- if (in_funcs[op1] == NULL) {
- printf("NULL func! op=%08x (%02x)\n", op, op1);
- exit(1);
+ emit_interpreter_call(in_funcs[op1]);
+
+ if (in_funcs[op1] == NULL) {
+ printf("NULL func! op=%08x (%02x)\n", op, op1);
+ exit(1);
+ }
+ ccount++;
}
+ else
+ ccount += ret;
+
if (op1 == 0x24 || op1 == 0x26 || // call, bra
((op1 == 0 || op1 == 1 || op1 == 4 || op1 == 5 || op1 == 9 || op1 == 0x25) &&
(op & 0xf0) == 0x60)) { // ld PC
}
}
- emit_block_epilogue(block_start, icount + 1);
+ emit_block_epilogue(ccount + 1);
*tcache_ptr++ = 0xffffffff; // end of block
//printf(" %i inst\n", icount);
// -----------------------------------------------------
-int ssp1601_dyn_init(void)
+int ssp1601_dyn_startup(void)
{
- tcache = tcache_ptr = malloc(TCACHE_SIZE);
- if (tcache == NULL) {
- printf("oom\n");
- exit(1);
- }
- memset(tcache, 0, sizeof(TCACHE_SIZE));
+ memset(tcache, 0, TCACHE_SIZE);
memset(block_table, 0, sizeof(block_table));
memset(block_table_iram, 0, sizeof(block_table_iram));
+ tcache_ptr = tcache;
*tcache_ptr++ = 0xffffffff;
return 0;
{
while (cycles > 0)
{
- void (*trans_entry)(void);
+ int (*trans_entry)(void);
if (rPC < 0x800/2)
{
if (iram_dirty) {
had_jump = 0;
- //printf("enter @ %04x, PC=%04x\n", (PC - tcache)<<1, rPC<<1);
- g_cycles = 0;
- //printf("enter %04x\n", rPC);
- trans_entry();
- //printf("leave %04x\n", rPC);
- cycles -= g_cycles;
-/*
- if (!had_jump) {
- // no jumps
- if (pc_old < 0x800/2)
- rPC += (PC - block_table_iram[iram_context][pc_old]) - 1;
- else
- rPC += (PC - block_table[pc_old]) - 1;
- }
-*/
- //printf("end @ %04x, PC=%04x\n", (PC - tcache)<<1, rPC<<1);
-/*
- if (pc_old < 0x400) {
- // flush IRAM cache
- tcache_ptr = block_table[pc_old];
- block_table[pc_old] = NULL;
- nblocks--;
- }
- if (pc_old >= 0x400 && rPC < 0x400)
- {
- int i, crc = chksum_crc32(svp->iram_rom, 0x800);
- for (i = 0; i < 32; i++)
- if (iram_crcs[i] == crc) break;
- if (i == 32) {
- char name[32];
- for (i = 0; i < 32 && iram_crcs[i]; i++);
- iram_crcs[i] = crc;
- printf("%i IRAMs\n", i+1);
- sprintf(name, "ir%08x.bin", crc);
- debug_dump2file(name, svp->iram_rom, 0x800);
- }
- printf("CRC %08x %08x\n", crc, iram_id);
- }
-*/
+ //printf("enter %04x\n", rPC<<1);
+ cycles -= trans_entry();
+ //printf("leave %04x\n", rPC<<1);
}
// debug_dump2file("tcache.bin", tcache, (tcache_ptr - tcache) << 1);
// exit(1);
--- /dev/null
+#define TCACHE_SIZE (1024*1024)
+
+extern unsigned int tcache[];
+
+void regfile_load(void);
+void regfile_store(void);
+
+int ssp1601_dyn_startup(void);
+void ssp1601_dyn_reset(ssp1601_t *ssp);
+void ssp1601_dyn_run(int cycles);
+
#define EMIT(x) *tcache_ptr++ = x
+#define A_R4M (1 << 4)
+#define A_R5M (1 << 5)
+#define A_R6M (1 << 6)
+#define A_R7M (1 << 7)
+#define A_R8M (1 << 8)
+#define A_R9M (1 << 9)
+#define A_R10M (1 << 10)
+#define A_R11M (1 << 11)
#define A_R14M (1 << 14)
#define A_COND_AL 0xe
#define EOP_LDR_IMM( rd,rn,offset_12) EOP_C_XXR_IMM(A_COND_AL,1,0,1,rn,rd,offset_12)
#define EOP_LDR_NEGIMM(rd,rn,offset_12) EOP_C_XXR_IMM(A_COND_AL,0,0,1,rn,rd,offset_12)
#define EOP_LDR_SIMPLE(rd,rn) EOP_C_XXR_IMM(A_COND_AL,1,0,1,rn,rd,0)
+#define EOP_STR_IMM( rd,rn,offset_12) EOP_C_XXR_IMM(A_COND_AL,1,0,0,rn,rd,offset_12)
#define EOP_STR_SIMPLE(rd,rn) EOP_C_XXR_IMM(A_COND_AL,1,0,0,rn,rd,0)
/* ldm and stm */
#define EOP_BX(rm) EOP_C_BX(A_COND_AL,rm)
+#define EOP_C_B(cond,l,signed_immed_24) \
+ EMIT(((cond)<<28) | 0x0a000000 | ((l)<<24) | (signed_immed_24))
+
+#define EOP_B( signed_immed_24) EOP_C_B(A_COND_AL,0,signed_immed_24)
+#define EOP_BL(signed_immed_24) EOP_C_B(A_COND_AL,1,signed_immed_24)
+
static void emit_mov_const(int d, unsigned int val)
{
EOP_C_DOP_IMM(A_COND_AL,need_or ? A_OP_ORR : A_OP_MOV, 0, need_or ? d : 0, d, 0, val&0xff);
}
+/*
static void check_offset_12(unsigned int val)
{
if (!(val & ~0xfff)) return;
printf("offset_12 overflow %04x\n", val);
exit(1);
}
+*/
-static void emit_block_prologue(void)
+static void check_offset_24(int val)
{
- // stack LR
- EOP_STMFD_ST(A_R14M); // stmfd r13!, {r14}
+ if (val >= (int)0xff000000 && val <= 0x00ffffff) return;
+ printf("offset_24 overflow %08x\n", val);
+ exit(1);
}
-static void emit_block_epilogue(unsigned int *block_start, int icount)
+static void emit_call(void *target)
{
- int back = (tcache_ptr - block_start) + 2;
- back += 3; // g_cycles
- check_offset_12(back<<2);
+ int val = (unsigned int *)target - tcache_ptr - 2;
+ check_offset_24(val);
- EOP_LDR_NEGIMM(2,15,back<<2); // ldr r2,[pc,#back]
- emit_mov_const(3, icount);
- EOP_STR_SIMPLE(3,2); // str r3,[r2]
+ EOP_BL(val & 0xffffff); // bl target
+}
- EOP_LDMFD_ST(A_R14M); // ldmfd r13!, {r14}
- EOP_BX(14); // bx r14
+static void emit_block_prologue(void)
+{
+ // stack regs
+ EOP_STMFD_ST(A_R4M|A_R5M|A_R6M|A_R7M|A_R8M|A_R9M|A_R10M|A_R11M|A_R14M); // stmfd r13!, {r4-r11,lr}
+ emit_call(regfile_load);
}
-static void emit_pc_inc(unsigned int *block_start, int pc)
+static void emit_block_epilogue(int icount)
{
- int back = (tcache_ptr - block_start) + 2;
- back += 2; // rPC ptr
- check_offset_12(back<<2);
+ emit_call(regfile_store);
+ EOP_LDMFD_ST(A_R4M|A_R5M|A_R6M|A_R7M|A_R8M|A_R9M|A_R10M|A_R11M|A_R14M); // ldmfd r13!, {r4-r11,lr}
+ emit_mov_const(0, icount);
+ EOP_BX(14); // bx r14
+}
- EOP_LDR_NEGIMM(2,15,back<<2); // ldr r2,[pc,#back]
+static void emit_pc_dump(int pc)
+{
emit_mov_const(3, pc<<16);
- EOP_STR_SIMPLE(3,2); // str r3,[r2]
+ EOP_STR_IMM(3,7,0x400+6*4); // str r3, [r7, #(0x400+6*8)]
}
-static void emit_call(unsigned int *block_start, unsigned int op1)
+static void emit_interpreter_call(void *target)
{
- int back = (tcache_ptr - block_start) + 2;
- back += 1; // func table
- check_offset_12(back<<2);
-
- EOP_LDR_NEGIMM(2,15,back<<2); // ldr r2,[pc,#back]
- EOP_MOV_REG_SIMPLE(14,15); // mov lr,pc
- EOP_LDR_IMM(15,2,op1<<2); // ldr pc,[r2,#op1]
+ emit_call(regfile_store);
+ emit_call(target);
+ emit_call(regfile_load);
}
static void handle_caches()
}
-static ssp1601_t *ssp = NULL;
+#ifndef EMBED_INTERPRETER
+static
+#endif
+ssp1601_t *ssp = NULL;
static unsigned short *PC;
static int g_cycles;
void ssp1601_reset(ssp1601_t *ssp);
void ssp1601_run(int cycles);
-int ssp1601_dyn_init(void);
-void ssp1601_dyn_reset(ssp1601_t *ssp);
-void ssp1601_dyn_run(int cycles);
-
--- /dev/null
+@ vim:filetype=armasm
+
+.if 0
+#include "compiler.h"
+.endif
+
+.global tcache
+
+.global flush_inval_caches
+.global regfile_load
+.global regfile_store
+
+@ translation cache buffer
+.text
+.align 12 @ 4096
+.size tcache, TCACHE_SIZE
+tcache:
+ .space TCACHE_SIZE
+
+
+.text
+.align 2
+
+
+flush_inval_caches:
+ mov r2, #0x0 @ must be 0
+ swi 0x9f0002
+ bx lr
+
+
+@ SSP_GR0, SSP_X, SSP_Y, SSP_A,
+@ SSP_ST, SSP_STACK, SSP_PC, SSP_P,
+@ SSP_PM0, SSP_PM1, SSP_PM2, SSP_XST,
+@ SSP_PM4, SSP_gr13, SSP_PMC, SSP_AL
+
+@ register map:
+@ r4: XXYY
+@ r5: A
+@ r6: STACK and emu flags
+@ r7: SSP context
+@ r8: r0-r2
+@ r9: r4-r6
+@ r10: P
+@ r11: cycles
+
+@ trashes r2,r3
+
+regfile_load:
+ ldr r7, =ssp
+ ldr r7, [r7]
+ add r2, r7, #0x400
+ add r2, r2, #4
+ ldmia r2, {r3,r4,r5,r6,r8}
+ mov r3, r3, lsr #16
+ mov r3, r3, lsl #16
+ orr r4, r3, r4, lsr #16 @ XXYY
+ bic r6, r6, #0xff
+ orr r6, r6, r8, lsr #16 @ flags + STACK
+ ldr r8, [r7, #0x440] @ r0-r2
+ ldr r9, [r7, #0x444] @ r4-r6
+ ldr r10,[r7, #(0x400+7*4)] @ P
+ bx lr
+
+
+regfile_store:
+ str r10,[r7, #(0x400+7*4)] @ P
+ str r8, [r7, #0x440] @ r0-r2
+ str r9, [r7, #0x444] @ r4-r6
+ mov r9, r6, lsl #16
+ and r9, r9, #(7<<16) @ STACK
+ bic r6, r6, #0xff @ ST
+ mov r3, r4, lsl #16 @ Y
+ mov r2, r4, lsr #16
+ mov r2, r2, lsl #16 @ X
+ add r8, r7, #0x400
+ add r8, r8, #4
+ stmia r8, {r2,r3,r5,r6,r9}
+ bx lr
+
+
+
+++ /dev/null
-@ vim:filetype=armasm
-
-
-@ register map:
-@ r4: XXYY
-@ r5: A
-@ r6: STACK and emu flags
-@ r7: SSP context
-@ r8: r0-r2
-@ r9: r4-r6
-@ r10: P
-
-.global flush_inval_caches
-
-.text
-.align 4
-
-flush_inval_caches:
- mov r2, #0x0 @ must be 0
- swi 0x9f0002
- bx lr
-
-
#include "../../PicoInt.h"
+#include "compiler.h"
+#ifdef __GP2X__
+#include <sys/mman.h>
+#endif
svp_t *svp = NULL;
int PicoSVPCycles = 1000; // cycles/line
static void PicoSVPLine(int count)
{
+ static int inited = 0;
+ if (!(svp->ssp1601.gr[SSP_PM0].h & 2) && !inited) return;
+ inited = 1;
+
// ???
if (PicoOpt&0x20000)
ssp1601_run(PicoSVPCycles * count);
void PicoSVPInit(void)
+{
+#ifdef __GP2X__
+ int ret;
+ ret = munmap(tcache, TCACHE_SIZE);
+ printf("munmap tcache: %i\n", ret);
+#endif
+}
+
+
+static void PicoSVPShutdown(void)
+{
+#ifdef __GP2X__
+ // also unmap tcache
+ PicoSVPInit();
+#endif
+}
+
+
+void PicoSVPStartup(void)
{
void *tmp;
svp = (void *) ((char *)tmp + 0x200000);
memset(svp, 0, sizeof(*svp));
+#ifdef __GP2X__
+ tmp = mmap(tcache, TCACHE_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
+ printf("mmap tcache: %p, asked %p\n", tmp, tcache);
+#endif
+
// init SVP compiler
if (!(PicoOpt&0x20000)) {
- if (ssp1601_dyn_init()) return;
+ if (ssp1601_dyn_startup()) return;
}
// init ok, setup hooks..
PicoDmaHook = PicoSVPDma;
PicoResetHook = PicoSVPReset;
PicoLineHook = PicoSVPLine;
+ PicoCartUnloadHook = PicoSVPShutdown;
// save state stuff
svp_states[0].ptr = svp->iram_rom;
carthw_chunks = svp_states;
}
+
.s.o:\r
@echo ">>>" $<\r
$(GCC) $(COPT) $(DEFINC) -c $< -o $@\r
+.S.o:\r
+ @echo ">>>" $<\r
+ $(GCC) $(COPT) $(DEFINC) -c $< -o $@\r
\r
../../Pico/carthw/svp/compiler.o : ../../Pico/carthw/svp/ssp16.o ../../Pico/carthw/svp/gen_arm.c\r
\r