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" };
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();
}
}

View file

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

View file

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

View file

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

View file

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

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 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 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)
{
// stack LR
EOP_STMFD_ST(A_R14M); // stmfd r13!, {r14}
// 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_block_epilogue(unsigned int *block_start, int icount)
static void emit_block_epilogue(int icount)
{
int back = (tcache_ptr - block_start) + 2;
back += 3; // g_cycles
check_offset_12(back<<2);
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}
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
}
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);
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()

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 int g_cycles;

View file

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

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 "compiler.h"
#ifdef __GP2X__
#include <sys/mman.h>
#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;
}

View file

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