some drc debug patches
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / new_dynarec.c
index b0bfb23..6d7069d 100644 (file)
 #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
@@ -265,11 +273,20 @@ static int tracedebug=0;
 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
 }
 
@@ -287,8 +304,9 @@ static void end_tcache_write(void *start, void *end)
   #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
@@ -3423,12 +3441,17 @@ void syscall_assemble(int i,struct regstat *i_regs)
 
 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);
 }
@@ -4240,6 +4263,28 @@ int match_bt(signed char i_regmap[],uint64_t i_is32,uint64_t i_dirty,int addr)
   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)
 {
@@ -4247,6 +4292,7 @@ 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&&regs[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]);
@@ -7023,19 +7069,43 @@ void new_dynarec_clear_full()
 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_PRIVATE | MAP_ANONYMOUS,
-            -1, 0) != out) {
+            -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
@@ -7054,9 +7124,15 @@ void new_dynarec_init()
 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);
@@ -9980,6 +10056,8 @@ int new_recompile_block(int addr)
       // 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&&regs[i].regmap[HOST_CCREG]!=CCREG)
         wb_register(CCREG,regs[i].regmap_entry,regs[i].wasdirty,regs[i].was32);