svp compiler direct calls

git-svn-id: file:///home/notaz/opt/svn/PicoDrive@360 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
notaz 2008-02-20 21:35:19 +00:00
parent 259ed0ea66
commit e807ac752b
13 changed files with 238 additions and 126 deletions

View file

@ -15,6 +15,8 @@
static char *rom_exts[] = { "bin", "gen", "smd", "iso" }; static char *rom_exts[] = { "bin", "gen", "smd", "iso" };
void (*PicoCartUnloadHook)(void) = NULL;
void (*PicoCartLoadProgressCB)(int percent) = NULL; void (*PicoCartLoadProgressCB)(int percent) = NULL;
void (*PicoCDLoadProgressCB)(int percent) = NULL; // handled in Pico/cd/cd_file.c 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.rom=rom;
Pico.romsize=romsize; Pico.romsize=romsize;
if (PicoCartUnloadHook != NULL) {
PicoCartUnloadHook();
PicoCartUnloadHook = NULL;
}
PicoMemResetHooks(); PicoMemResetHooks();
PicoDmaHook = NULL; PicoDmaHook = NULL;
PicoResetHook = NULL; PicoResetHook = NULL;
@ -646,7 +653,7 @@ void PicoCartDetect(void)
if (name_cmp("Virtua Racing") == 0 || if (name_cmp("Virtua Racing") == 0 ||
name_cmp("VIRTUA RACING") == 0) name_cmp("VIRTUA RACING") == 0)
{ {
PicoSVPInit(); PicoSVPStartup();
} }
} }

View file

@ -38,6 +38,7 @@ int PicoInit(void)
z80_init(); // init even if we aren't going to use it z80_init(); // init even if we aren't going to use it
PicoInitMCD(); PicoInitMCD();
PicoSVPInit();
SRam.data=0; SRam.data=0;

View file

@ -377,6 +377,7 @@ extern carthw_state_chunk *carthw_chunks;
// Cart.c // Cart.c
PICO_INTERNAL void PicoCartDetect(void); PICO_INTERNAL void PicoCartDetect(void);
extern void (*PicoCartUnloadHook)(void);
// Debug.c // Debug.c
int CM_compareRun(int cyc, int is_sub); int CM_compareRun(int cyc, int is_sub);

View file

@ -11,6 +11,7 @@ typedef struct {
extern svp_t *svp; extern svp_t *svp;
void PicoSVPInit(void); void PicoSVPInit(void);
void PicoSVPStartup(void);
unsigned int PicoSVPRead16(unsigned int a, int realsize); unsigned int PicoSVPRead16(unsigned int a, int realsize);
void PicoSVPWrite8 (unsigned int a, unsigned int d, int realsize); void PicoSVPWrite8 (unsigned int a, unsigned int d, int realsize);

View file

@ -2,11 +2,10 @@
// 14 IRAM blocks // 14 IRAM blocks
#include "../../PicoInt.h" #include "../../PicoInt.h"
#include "compiler.h"
#define TCACHE_SIZE (1024*1024)
static unsigned int *block_table[0x5090/2]; static unsigned int *block_table[0x5090/2];
static unsigned int *block_table_iram[15][0x800/2]; static unsigned int *block_table_iram[15][0x800/2];
static unsigned int *tcache = NULL;
static unsigned int *tcache_ptr = NULL; static unsigned int *tcache_ptr = NULL;
static int had_jump = 0; static int had_jump = 0;
@ -517,44 +516,64 @@ static int get_iram_context(void)
#define PROGRAM(x) ((unsigned short *)svp->iram_rom)[x] #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) static void *translate_block(int pc)
{ {
unsigned int op, op1, icount = 0; unsigned int op, op1, imm, ccount = 0;
unsigned int *block_start; unsigned int *block_start;
int ret;
// create .pool // create .pool
*tcache_ptr++ = (u32) &g_cycles; // -3 g_cycles //*tcache_ptr++ = (u32) in_funcs; // -1 func pool
*tcache_ptr++ = (u32) &ssp->gr[SSP_PC].v; // -2 ptr to rPC
*tcache_ptr++ = (u32) in_funcs; // -1 func pool
printf("translate %04x -> %04x\n", pc<<1, (tcache_ptr-tcache)<<2); printf("translate %04x -> %04x\n", pc<<1, (tcache_ptr-tcache)<<2);
block_start = tcache_ptr; block_start = tcache_ptr;
emit_block_prologue(); emit_block_prologue();
for (; icount < 100;) for (; ccount < 100;)
{ {
icount++;
//printf(" insn #%i\n", icount); //printf(" insn #%i\n", icount);
op = PROGRAM(pc++); op = PROGRAM(pc++);
op1 = op >> 9; op1 = op >> 9;
imm = (u32)-1;
emit_mov_const(0, op); if ((op1 & 0xf) == 4 || (op1 & 0xf) == 6)
imm = PROGRAM(pc++); // immediate
// need immediate? ret = translate_op(op, &pc);
if ((op1 & 0xf) == 4 || (op1 & 0xf) == 6) { if (ret <= 0)
emit_mov_const(1, PROGRAM(pc++)); // immediate {
emit_mov_const(0, op);
// need immediate?
if (imm != (u32)-1)
emit_mov_const(1, imm);
// dump PC
emit_pc_dump(pc);
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;
// dump PC
emit_pc_inc(block_start, pc);
emit_call(block_start, op1);
if (in_funcs[op1] == NULL) {
printf("NULL func! op=%08x (%02x)\n", op, op1);
exit(1);
}
if (op1 == 0x24 || op1 == 0x26 || // call, bra if (op1 == 0x24 || op1 == 0x26 || // call, bra
((op1 == 0 || op1 == 1 || op1 == 4 || op1 == 5 || op1 == 9 || op1 == 0x25) && ((op1 == 0 || op1 == 1 || op1 == 4 || op1 == 5 || op1 == 9 || op1 == 0x25) &&
(op & 0xf0) == 0x60)) { // ld PC (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 *tcache_ptr++ = 0xffffffff; // end of block
//printf(" %i inst\n", icount); //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); memset(tcache, 0, TCACHE_SIZE);
if (tcache == NULL) {
printf("oom\n");
exit(1);
}
memset(tcache, 0, sizeof(TCACHE_SIZE));
memset(block_table, 0, sizeof(block_table)); memset(block_table, 0, sizeof(block_table));
memset(block_table_iram, 0, sizeof(block_table_iram)); memset(block_table_iram, 0, sizeof(block_table_iram));
tcache_ptr = tcache;
*tcache_ptr++ = 0xffffffff; *tcache_ptr++ = 0xffffffff;
return 0; return 0;
@ -621,7 +636,7 @@ void ssp1601_dyn_run(int cycles)
{ {
while (cycles > 0) while (cycles > 0)
{ {
void (*trans_entry)(void); int (*trans_entry)(void);
if (rPC < 0x800/2) if (rPC < 0x800/2)
{ {
if (iram_dirty) { if (iram_dirty) {
@ -641,45 +656,9 @@ void ssp1601_dyn_run(int cycles)
had_jump = 0; had_jump = 0;
//printf("enter @ %04x, PC=%04x\n", (PC - tcache)<<1, rPC<<1); //printf("enter %04x\n", rPC<<1);
g_cycles = 0; cycles -= trans_entry();
//printf("enter %04x\n", rPC); //printf("leave %04x\n", rPC<<1);
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);
}
*/
} }
// debug_dump2file("tcache.bin", tcache, (tcache_ptr - tcache) << 1); // debug_dump2file("tcache.bin", tcache, (tcache_ptr - tcache) << 1);
// exit(1); // exit(1);

View file

@ -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);

View file

@ -1,5 +1,13 @@
#define EMIT(x) *tcache_ptr++ = x #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_R14M (1 << 14)
#define A_COND_AL 0xe #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_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_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_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) #define EOP_STR_SIMPLE(rd,rn) EOP_C_XXR_IMM(A_COND_AL,1,0,0,rn,rd,0)
/* ldm and stm */ /* ldm and stm */
@ -52,6 +61,12 @@
#define EOP_BX(rm) EOP_C_BX(A_COND_AL,rm) #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) 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); 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) static void check_offset_12(unsigned int val)
{ {
if (!(val & ~0xfff)) return; if (!(val & ~0xfff)) return;
printf("offset_12 overflow %04x\n", val); printf("offset_12 overflow %04x\n", val);
exit(1); exit(1);
} }
*/
static void check_offset_24(int val)
{
if (val >= (int)0xff000000 && val <= 0x00ffffff) return;
printf("offset_24 overflow %08x\n", val);
exit(1);
}
static void emit_call(void *target)
{
int val = (unsigned int *)target - tcache_ptr - 2;
check_offset_24(val);
EOP_BL(val & 0xffffff); // bl target
}
static void emit_block_prologue(void) static void emit_block_prologue(void)
{ {
// stack LR // stack regs
EOP_STMFD_ST(A_R14M); // stmfd r13!, {r14} 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_block_epilogue(unsigned int *block_start, int icount) static void emit_block_epilogue(int icount)
{ {
int back = (tcache_ptr - block_start) + 2; emit_call(regfile_store);
back += 3; // g_cycles 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}
check_offset_12(back<<2); emit_mov_const(0, icount);
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_LDMFD_ST(A_R14M); // ldmfd r13!, {r14}
EOP_BX(14); // bx r14 EOP_BX(14); // bx r14
} }
static void emit_pc_inc(unsigned int *block_start, int pc) static void emit_pc_dump(int pc)
{ {
int back = (tcache_ptr - block_start) + 2;
back += 2; // rPC ptr
check_offset_12(back<<2);
EOP_LDR_NEGIMM(2,15,back<<2); // ldr r2,[pc,#back]
emit_mov_const(3, pc<<16); 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; emit_call(regfile_store);
back += 1; // func table emit_call(target);
check_offset_12(back<<2); emit_call(regfile_load);
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]
} }
static void handle_caches() static void handle_caches()

View file

@ -332,7 +332,10 @@
} }
static ssp1601_t *ssp = NULL; #ifndef EMBED_INTERPRETER
static
#endif
ssp1601_t *ssp = NULL;
static unsigned short *PC; static unsigned short *PC;
static int g_cycles; static int g_cycles;

View file

@ -58,7 +58,3 @@ typedef struct
void ssp1601_reset(ssp1601_t *ssp); void ssp1601_reset(ssp1601_t *ssp);
void ssp1601_run(int cycles); void ssp1601_run(int cycles);
int ssp1601_dyn_init(void);
void ssp1601_dyn_reset(ssp1601_t *ssp);
void ssp1601_dyn_run(int cycles);

View file

@ -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

View file

@ -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

View file

@ -7,6 +7,10 @@
#include "../../PicoInt.h" #include "../../PicoInt.h"
#include "compiler.h"
#ifdef __GP2X__
#include <sys/mman.h>
#endif
svp_t *svp = NULL; svp_t *svp = NULL;
int PicoSVPCycles = 1000; // cycles/line int PicoSVPCycles = 1000; // cycles/line
@ -40,6 +44,10 @@ static void PicoSVPReset(void)
static void PicoSVPLine(int count) static void PicoSVPLine(int count)
{ {
static int inited = 0;
if (!(svp->ssp1601.gr[SSP_PM0].h & 2) && !inited) return;
inited = 1;
// ??? // ???
if (PicoOpt&0x20000) if (PicoOpt&0x20000)
ssp1601_run(PicoSVPCycles * count); ssp1601_run(PicoSVPCycles * count);
@ -77,6 +85,25 @@ static int PicoSVPDma(unsigned int source, int len, unsigned short **srcp, unsig
void PicoSVPInit(void) 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; void *tmp;
@ -93,9 +120,14 @@ void PicoSVPInit(void)
svp = (void *) ((char *)tmp + 0x200000); svp = (void *) ((char *)tmp + 0x200000);
memset(svp, 0, sizeof(*svp)); 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 // init SVP compiler
if (!(PicoOpt&0x20000)) { if (!(PicoOpt&0x20000)) {
if (ssp1601_dyn_init()) return; if (ssp1601_dyn_startup()) return;
} }
// init ok, setup hooks.. // init ok, setup hooks..
@ -105,6 +137,7 @@ void PicoSVPInit(void)
PicoDmaHook = PicoSVPDma; PicoDmaHook = PicoSVPDma;
PicoResetHook = PicoSVPReset; PicoResetHook = PicoSVPReset;
PicoLineHook = PicoSVPLine; PicoLineHook = PicoSVPLine;
PicoCartUnloadHook = PicoSVPShutdown;
// save state stuff // save state stuff
svp_states[0].ptr = svp->iram_rom; svp_states[0].ptr = svp->iram_rom;
@ -113,3 +146,4 @@ void PicoSVPInit(void)
carthw_chunks = svp_states; carthw_chunks = svp_states;
} }

View file

@ -159,6 +159,9 @@ up: PicoDrive.gpe
.s.o: .s.o:
@echo ">>>" $< @echo ">>>" $<
$(GCC) $(COPT) $(DEFINC) -c $< -o $@ $(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 ../../Pico/carthw/svp/compiler.o : ../../Pico/carthw/svp/ssp16.o ../../Pico/carthw/svp/gen_arm.c