#ifdef __MACH__
#include <libkern/OSCacheControl.h>
#endif
+#ifdef _3DS
+#include <3ds_utils.h>
+#endif
+#ifdef VITA
+#include <psp2/kernel/sysmem.h>
+static int sceBlock;
+#endif
#include "new_dynarec_config.h"
+#include "../psxhle.h" //emulator interface
#include "emu_if.h" //emulator interface
//#define DISASM
static void mprotect_w_x(void *start, void *end, int is_x)
{
#ifdef NO_WRITE_EXEC
+ #if defined(VITA)
+ // *Open* enables write on all memory that was
+ // allocated by sceKernelAllocMemBlockForVM()?
+ if (is_x)
+ sceKernelCloseVMDomain();
+ else
+ sceKernelOpenVMDomain();
+ #else
u_long mstart = (u_long)start & ~4095ul;
u_long mend = (u_long)end;
if (mprotect((void *)mstart, mend - mstart,
PROT_READ | (is_x ? PROT_EXEC : PROT_WRITE)) != 0)
SysPrintf("mprotect(%c) failed: %s\n", is_x ? 'x' : 'w', strerror(errno));
+ #endif
#endif
}
#elif defined(__MACH__)
sys_cache_control(kCacheFunctionPrepareForExecution, start, len);
#elif defined(VITA)
- int block = sceKernelFindMemBlockByAddr(start, len);
- sceKernelSyncVMDomain(block, start, len);
+ sceKernelSyncVMDomain(sceBlock, start, len);
+ #elif defined(_3DS)
+ ctr_flush_invalidate_cache();
#else
__clear_cache(start, end);
#endif
void hlecall_assemble(int i,struct regstat *i_regs)
{
+ extern void psxNULL();
signed char ccreg=get_reg(i_regs->regmap,CCREG);
assert(ccreg==HOST_CCREG);
assert(!is_delayslot);
(void)ccreg;
emit_movimm(start+i*4+4,0); // Get PC
- emit_movimm((int)psxHLEt[source[i]&7],1);
+ uint32_t hleCode = source[i] & 0x03ffffff;
+ if (hleCode >= (sizeof(psxHLEt) / sizeof(psxHLEt[0])))
+ emit_movimm((int)psxNULL,1);
+ else
+ emit_movimm((int)psxHLEt[hleCode],1);
emit_addimm(HOST_CCREG,CLOCK_ADJUST(ccadj[i]),HOST_CCREG); // XXX
emit_jmp((int)jump_hlecall);
}
return 1;
}
+#ifdef DRC_DBG
+static void drc_dbg_emit_do_cmp(int i)
+{
+ extern void do_insn_cmp();
+ extern int cycle;
+ u_int hr,reglist=0;
+
+ for(hr=0;hr<HOST_REGS;hr++)
+ if(regs[i].regmap[hr]>=0) reglist|=1<<hr;
+ save_regs(reglist);
+ emit_movimm(start+i*4,0);
+ emit_writeword(0,(int)&pcaddr);
+ emit_call((int)do_insn_cmp);
+ //emit_readword((int)&cycle,0);
+ //emit_addimm(0,2,0);
+ //emit_writeword(0,(int)&cycle);
+ restore_regs(reglist);
+}
+#else
+#define drc_dbg_emit_do_cmp(x)
+#endif
+
// Used when a branch jumps into the delay slot of another branch
void ds_assemble_entry(int i)
{
if(!instr_addr[t]) instr_addr[t]=(u_int)out;
assem_debug("Assemble delay slot at %x\n",ba[i]);
assem_debug("<->\n");
+ drc_dbg_emit_do_cmp(t);
if(regs[t].regmap_entry[HOST_CCREG]==CCREG&®s[t].regmap[HOST_CCREG]!=CCREG)
wb_register(CCREG,regs[t].regmap_entry,regs[t].wasdirty,regs[t].was32);
load_regs(regs[t].regmap_entry,regs[t].regmap,regs[t].was32,rs1[t],rs2[t]);
void new_dynarec_init()
{
SysPrintf("Init new dynarec\n");
- out=(u_char *)BASE_ADDR;
-#if BASE_ADDR_FIXED
- if (mmap (out, 1<<TARGET_SIZE_2,
+
+ // allocate/prepare a buffer for translation cache
+ // see assem_arm.h for some explanation
+#if defined(BASE_ADDR_FIXED)
+ if (mmap (translation_cache, 1 << TARGET_SIZE_2,
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
- -1, 0) <= 0) {
+ MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0) != translation_cache) {
SysPrintf("mmap() failed: %s\n", strerror(errno));
+ SysPrintf("disable BASE_ADDR_FIXED and recompile\n");
+ abort();
+ }
+#elif defined(BASE_ADDR_DYNAMIC)
+ #ifdef VITA
+ sceBlock = sceKernelAllocMemBlockForVM("code", 1 << TARGET_SIZE_2);
+ if (sceBlock < 0)
+ SysPrintf("sceKernelAllocMemBlockForVM failed\n");
+ int ret = sceKernelGetMemBlockBase(sceBlock, (void **)&translation_cache);
+ if (ret < 0)
+ SysPrintf("sceKernelGetMemBlockBase failed\n");
+ #else
+ translation_cache = mmap (NULL, 1 << TARGET_SIZE_2,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (translation_cache == MAP_FAILED) {
+ SysPrintf("mmap() failed: %s\n", strerror(errno));
+ abort();
}
-#elif !defined(NO_WRITE_EXEC)
+ #endif
+#else
+ #ifndef NO_WRITE_EXEC
// not all systems allow execute in data segment by default
- if (mprotect(out, 1<<TARGET_SIZE_2, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
+ if (mprotect((void *)BASE_ADDR, 1<<TARGET_SIZE_2, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
SysPrintf("mprotect() failed: %s\n", strerror(errno));
+ #endif
#endif
+ out=(u_char *)BASE_ADDR;
cycle_multiplier=200;
new_dynarec_clear_full();
#ifdef HOST_IMM8
void new_dynarec_cleanup()
{
int n;
- #if BASE_ADDR_FIXED
- if (munmap ((void *)BASE_ADDR, 1<<TARGET_SIZE_2) < 0) {SysPrintf("munmap() failed\n");}
+#if defined(BASE_ADDR_FIXED) || defined(BASE_ADDR_DYNAMIC)
+ #ifdef VITA
+ sceKernelFreeMemBlock(sceBlock);
+ sceBlock = -1;
+ #else
+ if (munmap ((void *)BASE_ADDR, 1<<TARGET_SIZE_2) < 0)
+ SysPrintf("munmap() failed\n");
#endif
+#endif
for(n=0;n<4096;n++) ll_clear(jump_in+n);
for(n=0;n<4096;n++) ll_clear(jump_out+n);
for(n=0;n<4096;n++) ll_clear(jump_dirty+n);
// branch target entry point
instr_addr[i]=(u_int)out;
assem_debug("<->\n");
+ drc_dbg_emit_do_cmp(i);
+
// load regs
if(regs[i].regmap_entry[HOST_CCREG]==CCREG&®s[i].regmap[HOST_CCREG]!=CCREG)
wb_register(CCREG,regs[i].regmap_entry,regs[i].wasdirty,regs[i].was32);