From b081408f66662068a3d274f696bdabba5186b68e Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 2 Jan 2010 21:03:04 +0000 Subject: [PATCH] 32x: drc: mmap dram+rom for direct dereference git-svn-id: file:///home/notaz/opt/svn/PicoDrive@851 be3aeb3a-fb24-0410-a615-afba39da0efa --- cpu/drc/emit_arm.c | 39 ++++++++++++++--- cpu/drc/emit_x86.c | 98 ++++++++++++++++++++++++++++++++----------- cpu/sh2/compiler.c | 72 +++++++++++++++++++++++-------- pico/32x/32x.c | 2 +- pico/32x/memory.c | 2 +- pico/cart.c | 34 +++++++-------- pico/pico.h | 7 +++- platform/linux/plat.c | 19 +++++++++ 8 files changed, 201 insertions(+), 72 deletions(-) diff --git a/cpu/drc/emit_arm.c b/cpu/drc/emit_arm.c index 6a115e3..b1e3ded 100644 --- a/cpu/drc/emit_arm.c +++ b/cpu/drc/emit_arm.c @@ -169,7 +169,8 @@ #define EOP_C_AM3_REG(cond,u,l,rn,rd,s,h,rm) EOP_C_AM3(cond,u,0,l,rn,rd,s,h,rm) /* ldr and str */ -#define EOP_LDR_IMM2(cond,rd,rn,offset_12) EOP_C_AM2_IMM(cond,1,0,1,rn,rd,offset_12) +#define EOP_LDR_IMM2(cond,rd,rn,offset_12) EOP_C_AM2_IMM(cond,1,0,1,rn,rd,offset_12) +#define EOP_LDRB_IMM2(cond,rd,rn,offset_12) EOP_C_AM2_IMM(cond,1,1,1,rn,rd,offset_12) #define EOP_LDR_IMM( rd,rn,offset_12) EOP_C_AM2_IMM(A_COND_AL,1,0,1,rn,rd,offset_12) #define EOP_LDR_NEGIMM(rd,rn,offset_12) EOP_C_AM2_IMM(A_COND_AL,0,0,1,rn,rd,offset_12) @@ -179,6 +180,8 @@ #define EOP_LDR_REG_LSL(cond,rd,rn,rm,shift_imm) EOP_C_AM2_REG(cond,1,0,1,rn,rd,shift_imm,A_AM1_LSL,rm) +#define EOP_LDRH_IMM2(cond,rd,rn,offset_8) EOP_C_AM3_IMM(cond,1,1,rn,rd,0,1,offset_8) + #define EOP_LDRH_IMM( rd,rn,offset_8) EOP_C_AM3_IMM(A_COND_AL,1,1,rn,rd,0,1,offset_8) #define EOP_LDRH_SIMPLE(rd,rn) EOP_C_AM3_IMM(A_COND_AL,1,1,rn,rd,0,1,0) #define EOP_LDRH_REG( rd,rn,rm) EOP_C_AM3_REG(A_COND_AL,1,1,rn,rd,0,1,rm) @@ -327,11 +330,14 @@ static int emith_xbranch(int cond, void *target, int is_call) } // fake "simple" or "short" jump - using cond insns instead -#define EMITH_SJMP_START(cond) \ +#define EMITH_NOTHING1(cond) \ (void)(cond) -#define EMITH_SJMP_END(cond) \ - (void)(cond) +#define EMITH_SJMP_START(cond) EMITH_NOTHING1(cond) +#define EMITH_SJMP_END(cond) EMITH_NOTHING1(cond) +#define EMITH_SJMP3_START(cond) EMITH_NOTHING1(cond) +#define EMITH_SJMP3_MID(cond) EMITH_NOTHING1(cond) +#define EMITH_SJMP3_END() #define emith_move_r_r(d, s) \ EOP_MOV_REG_SIMPLE(d, s) @@ -485,8 +491,11 @@ static int emith_xbranch(int cond, void *target, int is_call) #define emith_asr(d, s, cnt) \ EOP_MOV_REG(A_COND_AL,0,d,s,A_AM1_ASR,cnt) +#define emith_ror_c(cond, d, s, cnt) \ + EOP_MOV_REG(cond,0,d,s,A_AM1_ROR,cnt) + #define emith_ror(d, s, cnt) \ - EOP_MOV_REG(A_COND_AL,0,d,s,A_AM1_ROR,cnt) + emith_ror_c(A_COND_AL, d, s, cnt) #define emith_rol(d, s, cnt) \ EOP_MOV_REG(A_COND_AL,0,d,s,A_AM1_ROR,32-(cnt)); \ @@ -536,8 +545,26 @@ static int emith_xbranch(int cond, void *target, int is_call) EOP_C_SMLAL(A_COND_AL,0,dhi,dlo,s1,s2) // misc +#define emith_read_r_r_offs_c(cond, r, rs, offs) \ + EOP_LDR_IMM2(cond, r, rs, offs) + +#define emith_read8_r_r_offs_c(cond, r, rs, offs) \ + EOP_LDRB_IMM2(cond, r, rs, offs) + +#define emith_read16_r_r_offs_c(cond, r, rs, offs) \ + EOP_LDRH_IMM2(cond, r, rs, offs) + +#define emith_read_r_r_offs(r, rs, offs) \ + emith_read_r_r_offs_c(A_COND_AL, r, rs, offs) + +#define emith_read8_r_r_offs(r, rs, offs) \ + emith_read8_r_r_offs_c(A_COND_AL, r, rs, offs) + +#define emith_read16_r_r_offs(r, rs, offs) \ + emith_read16_r_r_offs_c(A_COND_AL, r, rs, offs) + #define emith_ctx_read(r, offs) \ - EOP_LDR_IMM(r, CONTEXT_REG, offs) + emith_read_r_r_offs(r, CONTEXT_REG, offs) #define emith_ctx_write(r, offs) \ EOP_STR_IMM(r, CONTEXT_REG, offs) diff --git a/cpu/drc/emit_x86.c b/cpu/drc/emit_x86.c index 02ad79c..1c29eea 100644 --- a/cpu/drc/emit_x86.c +++ b/cpu/drc/emit_x86.c @@ -219,29 +219,38 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; emith_add_r_imm(r, imm); \ } -#define emith_or_r_imm_c(cond, r, imm) { \ - (void)(cond); \ - emith_or_r_imm(r, imm); \ -} - -#define emith_eor_r_imm_c(cond, r, imm) { \ - (void)(cond); \ - emith_eor_r_imm(r, imm); \ -} - #define emith_sub_r_imm_c(cond, r, imm) { \ (void)(cond); \ emith_sub_r_imm(r, imm); \ } -#define emith_bic_r_imm_c(cond, r, imm) { \ - (void)(cond); \ - emith_bic_r_imm(r, imm); \ -} - -#define emith_jump_reg_c(cond, r) emith_jump_reg(r) -#define emith_jump_ctx_c(cond, offs) emith_jump_ctx(offs) -#define emith_ret_c(cond) emith_ret() +#define emith_or_r_imm_c(cond, r, imm) \ + emith_or_r_imm(r, imm) +#define emith_eor_r_imm_c(cond, r, imm) \ + emith_eor_r_imm(r, imm) +#define emith_bic_r_imm_c(cond, r, imm) \ + emith_bic_r_imm(r, imm) +#define emith_ror_c(cond, d, s, cnt) \ + emith_ror(d, s, cnt) + +#define emith_read_r_r_offs_c(cond, r, rs, offs) \ + emith_read_r_r_offs(r, rs, offs) +#define emith_write_r_r_offs_c(cond, r, rs, offs) \ + emith_write_r_r_offs(r, rs, offs) +#define emith_read8_r_r_offs_c(cond, r, rs, offs) \ + emith_read8_r_r_offs(r, rs, offs) +#define emith_write8_r_r_offs_c(cond, r, rs, offs) \ + emith_write8_r_r_offs(r, rs, offs) +#define emith_read16_r_r_offs_c(cond, r, rs, offs) \ + emith_read16_r_r_offs(r, rs, offs) +#define emith_write16_r_r_offs_c(cond, r, rs, offs) \ + emith_write16_r_r_offs(r, rs, offs) +#define emith_jump_reg_c(cond, r) \ + emith_jump_reg(r) +#define emith_jump_ctx_c(cond, offs) \ + emith_jump_ctx(offs) +#define emith_ret_c(cond) \ + emith_ret() // _r_r_imm #define emith_add_r_r_imm(d, s, imm) { \ @@ -391,22 +400,44 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; #define emith_rolcf emith_rolc #define emith_rorcf emith_rorc -#define emith_ctx_op(op, r, offs) do { \ +#define emith_deref_op(op, r, rs, offs) do { \ /* mov r <-> [ebp+#offs] */ \ if ((offs) >= 0x80) { \ - EMIT_OP_MODRM(op, 2, r, xBP); \ + EMIT_OP_MODRM(op, 2, r, rs); \ EMIT(offs, u32); \ } else { \ - EMIT_OP_MODRM(op, 1, r, xBP); \ + EMIT_OP_MODRM(op, 1, r, rs); \ EMIT(offs, u8); \ } \ } while (0) +#define emith_read_r_r_offs(r, rs, offs) \ + emith_deref_op(0x8b, r, rs, offs) + +#define emith_write_r_r_offs(r, rs, offs) \ + emith_deref_op(0x89, r, rs, offs) + +#define emith_read8_r_r_offs(r, rs, offs) \ + emith_deref_op(0x8a, r, rs, offs) + +#define emith_write8_r_r_offs(r, rs, offs) \ + emith_deref_op(0x88, r, rs, offs) + +#define emith_read16_r_r_offs(r, rs, offs) { \ + EMIT(0x66, u8); /* operand override */ \ + emith_read_r_r_offs(r, rs, offs); \ +} + +#define emith_write16_r_r_offs(r, rs, offs) { \ + EMIT(0x66, u8); \ + emith_write16_r_r_offs(r, rs, offs) \ +} + #define emith_ctx_read(r, offs) \ - emith_ctx_op(0x8b, r, offs) + emith_read_r_r_offs(r, CONTEXT_REG, offs) #define emith_ctx_write(r, offs) \ - emith_ctx_op(0x89, r, offs) + emith_write_r_r_offs(r, CONTEXT_REG, offs) #define emith_ctx_read_multiple(r, offs, cnt, tmpr) do { \ int r_ = r, offs_ = offs, cnt_ = cnt; \ @@ -460,7 +491,7 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; EMIT_OP_MODRM(0xff, 3, 2, r) #define emith_call_ctx(offs) { \ - EMIT_OP_MODRM(0xff, 2, 2, xBP); \ + EMIT_OP_MODRM(0xff, 2, 2, CONTEXT_REG); \ EMIT(offs, u32); \ } @@ -471,7 +502,7 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; EMIT_OP_MODRM(0xff, 3, 4, r) #define emith_jump_ctx(offs) { \ - EMIT_OP_MODRM(0xff, 2, 4, xBP); \ + EMIT_OP_MODRM(0xff, 2, 4, CONTEXT_REG); \ EMIT(offs, u32); \ } @@ -483,10 +514,27 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; JMP8_EMIT(cond, cond_ptr); \ } +#define EMITH_JMP3_START(cond) { \ + u8 *cond_ptr, *else_ptr; \ + JMP8_POS(cond_ptr) + +#define EMITH_JMP3_MID(cond) \ + JMP8_POS(else_ptr); \ + JMP8_EMIT(cond, cond_ptr); + +#define EMITH_JMP3_END() \ + JMP8_EMIT_NC(else_ptr); \ +} + // "simple" jump (no more then a few insns) +// ARM will use conditional instructions here #define EMITH_SJMP_START EMITH_JMP_START #define EMITH_SJMP_END EMITH_JMP_END +#define EMITH_SJMP3_START EMITH_JMP3_START +#define EMITH_SJMP3_MID EMITH_JMP3_MID +#define EMITH_SJMP3_END EMITH_JMP3_END + #define host_arg2reg(rd, arg) \ switch (arg) { \ case 0: rd = xAX; break; \ diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index ee84364..25529cd 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -496,24 +496,60 @@ static void emit_or_t_if_eq(int srr) // reg cache must be clean before call static int emit_memhandler_read(int size) { - int ctxr; - host_arg2reg(ctxr, 1); - emith_move_r_r(ctxr, CONTEXT_REG); - switch (size) { - case 0: // 8 - // must writeback cycles for poll detection stuff - if (reg_map_g2h[SHR_SR] != -1) - emith_ctx_write(reg_map_g2h[SHR_SR], SHR_SR * 4); - emith_call(p32x_sh2_read8); - break; - case 1: // 16 - if (reg_map_g2h[SHR_SR] != -1) - emith_ctx_write(reg_map_g2h[SHR_SR], SHR_SR * 4); - emith_call(p32x_sh2_read16); - break; - case 2: // 32 - emith_call(p32x_sh2_read32); - break; + int arg0, arg1; + host_arg2reg(arg0, 0); + + // must writeback cycles for poll detection stuff + if (reg_map_g2h[SHR_SR] != -1) + emith_ctx_write(reg_map_g2h[SHR_SR], SHR_SR * 4); + arg1 = rcache_get_tmp_arg(1); + emith_move_r_r(arg1, CONTEXT_REG); + +#if 1 + if (Pico.rom == (void *)0x02000000 && Pico32xMem->sdram == (void *)0x06000000) { + int tmp = rcache_get_tmp(); + emith_and_r_r_imm(tmp, arg0, 0xfb000000); + emith_cmp_r_imm(tmp, 0x02000000); + switch (size) { + case 0: // 8 + EMITH_SJMP3_START(DCOND_NE); + emith_eor_r_imm_c(DCOND_EQ, arg0, 1); + emith_read8_r_r_offs_c(DCOND_EQ, arg0, arg0, 0); + EMITH_SJMP3_MID(DCOND_NE); + emith_call_cond(DCOND_NE, p32x_sh2_read8); + EMITH_SJMP3_END(); + break; + case 1: // 16 + EMITH_SJMP3_START(DCOND_NE); + emith_read16_r_r_offs_c(DCOND_EQ, arg0, arg0, 0); + EMITH_SJMP3_MID(DCOND_NE); + emith_call_cond(DCOND_NE, p32x_sh2_read16); + EMITH_SJMP3_END(); + break; + case 2: // 32 + EMITH_SJMP3_START(DCOND_NE); + emith_read_r_r_offs_c(DCOND_EQ, arg0, arg0, 0); + emith_ror_c(DCOND_EQ, arg0, arg0, 16); + EMITH_SJMP3_MID(DCOND_NE); + emith_call_cond(DCOND_NE, p32x_sh2_read32); + EMITH_SJMP3_END(); + break; + } + } + else +#endif + { + switch (size) { + case 0: // 8 + emith_call(p32x_sh2_read8); + break; + case 1: // 16 + emith_call(p32x_sh2_read16); + break; + case 2: // 32 + emith_call(p32x_sh2_read32); + break; + } } rcache_invalidate(); // assuming arg0 and retval reg matches diff --git a/pico/32x/32x.c b/pico/32x/32x.c index e945c8e..94e696b 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -129,7 +129,7 @@ void PicoPower32x(void) void PicoUnload32x(void) { if (Pico32xMem != NULL) - free(Pico32xMem); + plat_munmap(Pico32xMem, sizeof(*Pico32xMem)); Pico32xMem = NULL; sh2_finish(&msh2); sh2_finish(&ssh2); diff --git a/pico/32x/memory.c b/pico/32x/memory.c index 7104cef..999a060 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -1419,7 +1419,7 @@ void PicoMemSetup32x(void) unsigned int rs; int i; - Pico32xMem = calloc(1, sizeof(*Pico32xMem)); + Pico32xMem = plat_mmap(0x06000000, sizeof(*Pico32xMem)); if (Pico32xMem == NULL) { elprintf(EL_STATUS, "OOM"); return; diff --git a/pico/cart.c b/pico/cart.c index 45f3866..8d30a93 100644 --- a/pico/cart.c +++ b/pico/cart.c @@ -13,6 +13,7 @@ #include "../unzip/unzip_stream.h" +static int rom_alloc_size; static const char *rom_exts[] = { "bin", "gen", "smd", "iso", "sms", "gg", "sg" }; void (*PicoCartUnloadHook)(void); @@ -425,22 +426,10 @@ static int DecodeSmd(unsigned char *data,int len) return 0; } -static unsigned char *cd_realloc(void *old, int filesize) -{ - unsigned char *rom; - rom=realloc(old, sizeof(mcd_state)); - if (rom) memset(rom+0x20000, 0, sizeof(mcd_state)-0x20000); - return rom; -} - static unsigned char *PicoCartAlloc(int filesize, int is_sms) { - int alloc_size; unsigned char *rom; - if (PicoAHW & PAHW_MCD) - return cd_realloc(NULL, filesize); - if (is_sms) { // make size power of 2 for easier banking handling int s = 0, tmp = filesize; @@ -448,18 +437,24 @@ static unsigned char *PicoCartAlloc(int filesize, int is_sms) s++; if (filesize > (1 << s)) s++; - alloc_size = 1 << s; + rom_alloc_size = 1 << s; } else { + // make alloc size at least sizeof(mcd_state), + // in case we want to switch to CD mode + if (filesize < sizeof(mcd_state)) + filesize = sizeof(mcd_state); + // align to 512K for memhandlers - alloc_size = (filesize + 0x7ffff) & ~0x7ffff; + rom_alloc_size = (filesize + 0x7ffff) & ~0x7ffff; } - if (alloc_size - filesize < 4) - alloc_size += 4; // padding for out-of-bound exec protection + if (rom_alloc_size - filesize < 4) + rom_alloc_size += 4; // padding for out-of-bound exec protection // Allocate space for the rom plus padding - rom = calloc(alloc_size, 1); + // use special address for 32x dynarec + rom = plat_mmap(0x02000000, rom_alloc_size); return rom; } @@ -513,7 +508,6 @@ int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms) if (!(PicoAHW & PAHW_MCD) && size == 0x20000 && (!strncmp((char *)rom+0x124, "BOOT", 4) || !strncmp((char *)rom+0x128, "BOOT", 4))) { PicoAHW |= PAHW_MCD; - rom = cd_realloc(rom, size); } // Check for SMD: @@ -608,8 +602,8 @@ void PicoCartUnload(void) if (Pico.rom != NULL) { SekFinishIdleDet(); - free(Pico.rom); - Pico.rom=NULL; + plat_munmap(Pico.rom, rom_alloc_size); + Pico.rom = NULL; } } diff --git a/pico/pico.h b/pico/pico.h index c274b80..033ed6f 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -28,9 +28,14 @@ extern void mp3_update(int *buffer, int length, int stereo); // this function should write-back d-cache and invalidate i-cache // on a mem region [start_addr, end_addr) -// used by SVP dynarec +// used by dynarecs extern void cache_flush_d_inval_i(const void *start_addr, const void *end_addr); +// attempt to alloc mem at specified address. +// alloc anywhere else if that fails (callers should handle that) +extern void *plat_mmap(unsigned long addr, size_t size); +extern void plat_munmap(void *ptr, size_t size); + // this one should handle display mode changes extern void emu_video_mode_change(int start_line, int line_count, int is_32cols); diff --git a/platform/linux/plat.c b/platform/linux/plat.c index d777f23..492007c 100644 --- a/platform/linux/plat.c +++ b/platform/linux/plat.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "../common/plat.h" @@ -108,3 +109,21 @@ int plat_wait_event(int *fds_hnds, int count, int timeout_ms) return ret; } +void *plat_mmap(unsigned long addr, size_t size) +{ + void *req, *ret; + req = (void *)addr; + ret = mmap(req, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); + if (ret == MAP_FAILED) + return NULL; + if (ret != req) + printf("warning: mmaped to %p, requested %p\n", ret, req); + + return ret; +} + +void plat_munmap(void *ptr, size_t size) +{ + munmap(ptr, size); +} + -- 2.39.2