diff options
Diffstat (limited to 'libpcsxcore')
-rw-r--r-- | libpcsxcore/new_dynarec/assem_arm.c | 12 | ||||
-rw-r--r-- | libpcsxcore/new_dynarec/emu_if.c | 1 | ||||
-rw-r--r-- | libpcsxcore/new_dynarec/emu_if.h | 2 | ||||
-rw-r--r-- | libpcsxcore/new_dynarec/pcsxmem_inline.c | 127 |
4 files changed, 141 insertions, 1 deletions
diff --git a/libpcsxcore/new_dynarec/assem_arm.c b/libpcsxcore/new_dynarec/assem_arm.c index 8432884..eed584e 100644 --- a/libpcsxcore/new_dynarec/assem_arm.c +++ b/libpcsxcore/new_dynarec/assem_arm.c @@ -2602,6 +2602,10 @@ emit_extjump_ds(int addr, int target) emit_extjump2(addr, target, (int)dyna_linker_ds); } +#ifdef PCSX +#include "pcsxmem_inline.c" +#endif + do_readstub(int n) { assem_debug("do_readstub %x\n",start+stubs[n][3]*4); @@ -2721,6 +2725,10 @@ inline_readstub(int type, int i, u_int addr, signed char regmap[], int target, i ftable=(int)readmemd; #endif assert(ftable!=0); +#ifdef PCSX + if(pcsx_direct_read(type,addr,target?rs:-1,rt)) + return; +#endif if(target==0) emit_movimm(addr,rs); emit_writeword(rs,(int)&address); @@ -2879,6 +2887,10 @@ inline_writestub(int type, int i, u_int addr, signed char regmap[], int target, int rt=get_reg(regmap,target); assert(rs>=0); assert(rt>=0); +#ifdef PCSX + if(pcsx_direct_write(type,addr,rs,rt,regmap)) + return; +#endif int ftable=0; if(type==STOREB_STUB) ftable=(int)writememb; diff --git a/libpcsxcore/new_dynarec/emu_if.c b/libpcsxcore/new_dynarec/emu_if.c index 3bfec4e..b44feb3 100644 --- a/libpcsxcore/new_dynarec/emu_if.c +++ b/libpcsxcore/new_dynarec/emu_if.c @@ -155,7 +155,6 @@ static int ari64_init() { extern void (*psxCP2[64])(); extern void psxNULL(); - extern void *psxH_ptr; size_t i; new_dynarec_init(); diff --git a/libpcsxcore/new_dynarec/emu_if.h b/libpcsxcore/new_dynarec/emu_if.h index 9e7f710..a561255 100644 --- a/libpcsxcore/new_dynarec/emu_if.h +++ b/libpcsxcore/new_dynarec/emu_if.h @@ -45,6 +45,8 @@ extern unsigned int word; /* write */ extern unsigned short hword; extern unsigned char byte; +extern void *psxH_ptr; + /* cycles/irqs */ extern unsigned int next_interupt; extern int pending_exception; diff --git a/libpcsxcore/new_dynarec/pcsxmem_inline.c b/libpcsxcore/new_dynarec/pcsxmem_inline.c new file mode 100644 index 0000000..90dafa0 --- /dev/null +++ b/libpcsxcore/new_dynarec/pcsxmem_inline.c @@ -0,0 +1,127 @@ +/* + * (C) GraÅžvydas "notaz" Ignotas, 2011 + * + * This work is licensed under the terms of GNU GPL version 2 or later. + * See the COPYING file in the top-level directory. + */ + +static int emit_ldr_type(int type, int offs, int rs, int rt) +{ + switch(type) { + case LOADB_STUB: + emit_movsbl_indexed(offs,rs,rt); + break; + case LOADBU_STUB: + emit_movzbl_indexed(offs,rs,rt); + break; + case LOADH_STUB: + emit_movswl_indexed(offs,rs,rt); + break; + case LOADHU_STUB: + emit_movzwl_indexed(offs,rs,rt); + break; + case LOADW_STUB: + emit_readword_indexed(offs,rs,rt); + break; + default: + assert(0); + } +} + +static int emit_str_type(int type, int offs, int rs, int rt) +{ + switch(type) { + case STOREB_STUB: + emit_writebyte_indexed(rt,offs,rs); + break; + case STOREH_STUB: + emit_writehword_indexed(rt,offs,rs); + break; + case STOREW_STUB: + emit_writeword_indexed(rt,offs,rs); + break; + default: + assert(0); + } +} + +static void convert_ram_addr(u_int a_rs, u_int a_rt, int rs, int rt) +{ + if(rs<0) + emit_movimm(a_rt,rt); + else if((a_rs&~0x60000000)==a_rt) + emit_andimm(rs,~0x60000000,rt); + else if((a_rs&~0x00600000)==a_rt) + emit_andimm(rs,~0x00600000,rt); + else + emit_movimm(a_rt,rt); +} + +static int pcsx_direct_read(int type, u_int addr, int rs, int rt) +{ + if((addr & 0x1f800000) == 0) { + assem_debug("pcsx_direct_read %08x ram\n",addr); + if(rt<0) + return 1; + u_int a=(addr&~0x60600000)|0x80000000; + convert_ram_addr(addr,a,rs,rt); + emit_ldr_type(type,0,rt,rt); + return 1; + } + if((addr & 0x1ff80000) == 0x1fc00000) { + assem_debug("pcsx_direct_read %08x bios\n",addr); + if(rt<0) + return 1; + emit_movimm((u_int)&psxR[addr&0x7ffff],rt); + emit_ldr_type(type,0,rt,rt); + return 1; + } + if((addr & 0xfffff000) == 0x1f800000) { + assem_debug("pcsx_direct_read %08x scratchpad\n",addr); + if(rt<0) + return 1; + if(type==LOADW_STUB||type==LOADBU_STUB||(addr&0xf00)==0) { + emit_readword((int)&psxH_ptr,rt); + emit_ldr_type(type,addr&0xfff,rt,rt); + } else { + emit_movimm((u_int)&psxH[addr&0xfff],rt); + emit_ldr_type(type,0,rt,rt); + } + return 1; + } + + assem_debug("pcsx_direct_read %08x miss\n",addr); + return 0; +} + +static int pcsx_direct_write(int type, u_int addr, int rs, int rt, signed char *regmap) +{ + if((addr & 0x1f800000) == 0) { + assem_debug("pcsx_direct_write %08x ram\n",addr); + u_int a=(addr&~0x60600000)|0x80000000; + convert_ram_addr(addr,a,rs,HOST_TEMPREG); + emit_str_type(type,0,HOST_TEMPREG,rt); + + int ir=get_reg(regmap,INVCP); + assert(ir>=0); + emit_cmpmem_indexedsr12_reg(ir,rs,1); + emit_callne(invalidate_addr_reg[rs]); + return 1; + } + if((addr & 0xfffff000) == 0x1f800000) { + assem_debug("pcsx_direct_write %08x scratchpad\n",addr); + if(type==STOREW_STUB||type==STOREB_STUB||(addr&0xf00)==0) { + emit_readword((int)&psxH_ptr,HOST_TEMPREG); + emit_str_type(type,addr&0xfff,HOST_TEMPREG,rt); + } else { + emit_movimm((u_int)&psxH[addr&0xfff],HOST_TEMPREG); + emit_str_type(type,0,HOST_TEMPREG,rt); + } + return 1; + } + + assem_debug("pcsx_direct_write %08x miss\n",addr); + return 0; +} + +// vim:shiftwidth=2:expandtab |