From e807ac752b4653487ec5bdf516205e24a1c657eb Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 20 Feb 2008 21:35:19 +0000 Subject: [PATCH] svp compiler direct calls git-svn-id: file:///home/notaz/opt/svn/PicoDrive@360 be3aeb3a-fb24-0410-a615-afba39da0efa --- Pico/Cart.c | 9 ++- Pico/Pico.c | 1 + Pico/PicoInt.h | 1 + Pico/carthw/carthw.h | 1 + Pico/carthw/svp/compiler.c | 113 +++++++++++++++---------------------- Pico/carthw/svp/compiler.h | 11 ++++ Pico/carthw/svp/gen_arm.c | 70 ++++++++++++++--------- Pico/carthw/svp/ssp16.c | 5 +- Pico/carthw/svp/ssp16.h | 4 -- Pico/carthw/svp/stub_arm.S | 81 ++++++++++++++++++++++++++ Pico/carthw/svp/stub_arm.s | 23 -------- Pico/carthw/svp/svp.c | 36 +++++++++++- platform/gp2x/Makefile | 3 + 13 files changed, 235 insertions(+), 123 deletions(-) create mode 100644 Pico/carthw/svp/compiler.h create mode 100644 Pico/carthw/svp/stub_arm.S delete mode 100644 Pico/carthw/svp/stub_arm.s diff --git a/Pico/Cart.c b/Pico/Cart.c index e616622a..5e01e9ac 100644 --- a/Pico/Cart.c +++ b/Pico/Cart.c @@ -15,6 +15,8 @@ static char *rom_exts[] = { "bin", "gen", "smd", "iso" }; +void (*PicoCartUnloadHook)(void) = NULL; + void (*PicoCartLoadProgressCB)(int percent) = NULL; void (*PicoCDLoadProgressCB)(int percent) = NULL; // handled in Pico/cd/cd_file.c @@ -493,6 +495,11 @@ int PicoCartInsert(unsigned char *rom,unsigned int romsize) Pico.rom=rom; Pico.romsize=romsize; + if (PicoCartUnloadHook != NULL) { + PicoCartUnloadHook(); + PicoCartUnloadHook = NULL; + } + PicoMemResetHooks(); PicoDmaHook = NULL; PicoResetHook = NULL; @@ -646,7 +653,7 @@ void PicoCartDetect(void) if (name_cmp("Virtua Racing") == 0 || name_cmp("VIRTUA RACING") == 0) { - PicoSVPInit(); + PicoSVPStartup(); } } diff --git a/Pico/Pico.c b/Pico/Pico.c index 0e9ee6c2..b07af08d 100644 --- a/Pico/Pico.c +++ b/Pico/Pico.c @@ -38,6 +38,7 @@ int PicoInit(void) z80_init(); // init even if we aren't going to use it PicoInitMCD(); + PicoSVPInit(); SRam.data=0; diff --git a/Pico/PicoInt.h b/Pico/PicoInt.h index b503330d..f29c20ba 100644 --- a/Pico/PicoInt.h +++ b/Pico/PicoInt.h @@ -377,6 +377,7 @@ extern carthw_state_chunk *carthw_chunks; // Cart.c PICO_INTERNAL void PicoCartDetect(void); +extern void (*PicoCartUnloadHook)(void); // Debug.c int CM_compareRun(int cyc, int is_sub); diff --git a/Pico/carthw/carthw.h b/Pico/carthw/carthw.h index 397dc283..e940d580 100644 --- a/Pico/carthw/carthw.h +++ b/Pico/carthw/carthw.h @@ -11,6 +11,7 @@ typedef struct { 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); diff --git a/Pico/carthw/svp/compiler.c b/Pico/carthw/svp/compiler.c index dac52851..7f10a5bd 100644 --- a/Pico/carthw/svp/compiler.c +++ b/Pico/carthw/svp/compiler.c @@ -2,11 +2,10 @@ // 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; @@ -517,44 +516,64 @@ static int get_iram_context(void) #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 @@ -562,7 +581,7 @@ static void *translate_block(int pc) } } - emit_block_epilogue(block_start, icount + 1); + emit_block_epilogue(ccount + 1); *tcache_ptr++ = 0xffffffff; // end of block //printf(" %i inst\n", icount); @@ -596,16 +615,12 @@ static void *translate_block(int pc) // ----------------------------------------------------- -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; @@ -621,7 +636,7 @@ void ssp1601_dyn_run(int cycles) { while (cycles > 0) { - void (*trans_entry)(void); + int (*trans_entry)(void); if (rPC < 0x800/2) { if (iram_dirty) { @@ -641,45 +656,9 @@ void ssp1601_dyn_run(int cycles) 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); diff --git a/Pico/carthw/svp/compiler.h b/Pico/carthw/svp/compiler.h new file mode 100644 index 00000000..1d8dc6cd --- /dev/null +++ b/Pico/carthw/svp/compiler.h @@ -0,0 +1,11 @@ +#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); + diff --git a/Pico/carthw/svp/gen_arm.c b/Pico/carthw/svp/gen_arm.c index 30364136..6e661726 100644 --- a/Pico/carthw/svp/gen_arm.c +++ b/Pico/carthw/svp/gen_arm.c @@ -1,5 +1,13 @@ #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 @@ -37,6 +45,7 @@ #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 */ @@ -52,6 +61,12 @@ #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) { @@ -72,53 +87,56 @@ 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() diff --git a/Pico/carthw/svp/ssp16.c b/Pico/carthw/svp/ssp16.c index b2de4596..ea0529f1 100644 --- a/Pico/carthw/svp/ssp16.c +++ b/Pico/carthw/svp/ssp16.c @@ -332,7 +332,10 @@ } -static ssp1601_t *ssp = NULL; +#ifndef EMBED_INTERPRETER +static +#endif +ssp1601_t *ssp = NULL; static unsigned short *PC; static int g_cycles; diff --git a/Pico/carthw/svp/ssp16.h b/Pico/carthw/svp/ssp16.h index c7db4de9..3d8a764d 100644 --- a/Pico/carthw/svp/ssp16.h +++ b/Pico/carthw/svp/ssp16.h @@ -58,7 +58,3 @@ typedef struct 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); - diff --git a/Pico/carthw/svp/stub_arm.S b/Pico/carthw/svp/stub_arm.S new file mode 100644 index 00000000..d87d4415 --- /dev/null +++ b/Pico/carthw/svp/stub_arm.S @@ -0,0 +1,81 @@ +@ 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 + + + diff --git a/Pico/carthw/svp/stub_arm.s b/Pico/carthw/svp/stub_arm.s deleted file mode 100644 index 18a202c3..00000000 --- a/Pico/carthw/svp/stub_arm.s +++ /dev/null @@ -1,23 +0,0 @@ -@ 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 - - diff --git a/Pico/carthw/svp/svp.c b/Pico/carthw/svp/svp.c index 3dbc269c..e76c7ce8 100644 --- a/Pico/carthw/svp/svp.c +++ b/Pico/carthw/svp/svp.c @@ -7,6 +7,10 @@ #include "../../PicoInt.h" +#include "compiler.h" +#ifdef __GP2X__ +#include +#endif svp_t *svp = NULL; int PicoSVPCycles = 1000; // cycles/line @@ -40,6 +44,10 @@ static void PicoSVPReset(void) 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); @@ -77,6 +85,25 @@ static int PicoSVPDma(unsigned int source, int len, unsigned short **srcp, unsig 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; @@ -93,9 +120,14 @@ void PicoSVPInit(void) 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.. @@ -105,6 +137,7 @@ void PicoSVPInit(void) PicoDmaHook = PicoSVPDma; PicoResetHook = PicoSVPReset; PicoLineHook = PicoSVPLine; + PicoCartUnloadHook = PicoSVPShutdown; // save state stuff svp_states[0].ptr = svp->iram_rom; @@ -113,3 +146,4 @@ void PicoSVPInit(void) carthw_chunks = svp_states; } + diff --git a/platform/gp2x/Makefile b/platform/gp2x/Makefile index 1bb9204b..8145ecd0 100644 --- a/platform/gp2x/Makefile +++ b/platform/gp2x/Makefile @@ -159,6 +159,9 @@ up: PicoDrive.gpe .s.o: @echo ">>>" $< $(GCC) $(COPT) $(DEFINC) -c $< -o $@ +.S.o: + @echo ">>>" $< + $(GCC) $(COPT) $(DEFINC) -c $< -o $@ ../../Pico/carthw/svp/compiler.o : ../../Pico/carthw/svp/ssp16.o ../../Pico/carthw/svp/gen_arm.c -- 2.39.5