svp compiler direct calls
authornotaz <notasas@gmail.com>
Wed, 20 Feb 2008 21:35:19 +0000 (21:35 +0000)
committernotaz <notasas@gmail.com>
Wed, 20 Feb 2008 21:35:19 +0000 (21:35 +0000)
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@360 be3aeb3a-fb24-0410-a615-afba39da0efa

13 files changed:
Pico/Cart.c
Pico/Pico.c
Pico/PicoInt.h
Pico/carthw/carthw.h
Pico/carthw/svp/compiler.c
Pico/carthw/svp/compiler.h [new file with mode: 0644]
Pico/carthw/svp/gen_arm.c
Pico/carthw/svp/ssp16.c
Pico/carthw/svp/ssp16.h
Pico/carthw/svp/stub_arm.S [new file with mode: 0644]
Pico/carthw/svp/stub_arm.s [deleted file]
Pico/carthw/svp/svp.c
platform/gp2x/Makefile

index e616622..5e01e9a 100644 (file)
@@ -15,6 +15,8 @@
 \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
@@ -493,6 +495,11 @@ int PicoCartInsert(unsigned char *rom,unsigned int romsize)
   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
@@ -646,7 +653,7 @@ void PicoCartDetect(void)
   if (name_cmp("Virtua Racing") == 0 ||\r
       name_cmp("VIRTUA RACING") == 0)\r
   {\r
-    PicoSVPInit();\r
+    PicoSVPStartup();\r
   }\r
 }\r
 \r
index 0e9ee6c..b07af08 100644 (file)
@@ -38,6 +38,7 @@ int PicoInit(void)
   z80_init(); // init even if we aren't going to use it\r
 \r
   PicoInitMCD();\r
+  PicoSVPInit();\r
 \r
   SRam.data=0;\r
 \r
index b503330..f29c20b 100644 (file)
@@ -377,6 +377,7 @@ extern carthw_state_chunk *carthw_chunks;
 \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
index 397dc28..e940d58 100644 (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);
index dac5285..7f10a5b 100644 (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);
 
-               // 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 (file)
index 0000000..1d8dc6c
--- /dev/null
@@ -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);
+
index 3036413..6e66172 100644 (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 */
 
 #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()
index b2de459..ea0529f 100644 (file)
 }
 
 
-static ssp1601_t *ssp = NULL;
+#ifndef EMBED_INTERPRETER
+static
+#endif
+ssp1601_t *ssp = NULL;
 static unsigned short *PC;
 static int g_cycles;
 
index c7db4de..3d8a764 100644 (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);
-
diff --git a/Pico/carthw/svp/stub_arm.S b/Pico/carthw/svp/stub_arm.S
new file mode 100644 (file)
index 0000000..d87d441
--- /dev/null
@@ -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 (file)
index 18a202c..0000000
+++ /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
-
-
index 3dbc269..e76c7ce 100644 (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;
 }
 
+
index 1bb9204..8145ecd 100644 (file)
@@ -159,6 +159,9 @@ up: PicoDrive.gpe
 .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