some drc debug patches
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / new_dynarec.c
index 6501d26..6d7069d 100644 (file)
 #include <assert.h>
 #include <errno.h>
 #include <sys/mman.h>
+#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
 #include "assem_arm.h"
 #endif
 
-#ifdef __BLACKBERRY_QNX__
-#undef __clear_cache
-#define __clear_cache(start,end) msync(start, (size_t)((void*)end - (void*)start), MS_SYNC | MS_CACHE_ONLY | MS_INVALIDATE_ICACHE);
-#elif defined(__MACH__)
-#include <libkern/OSCacheControl.h>
-#define __clear_cache mach_clear_cache
-static void __clear_cache(void *start, void *end) {
-  size_t len = (char *)end - (char *)start;
-  sys_dcache_flush(start, len);
-  sys_icache_invalidate(start, len);
-}
-#endif
-
 #define MAXBLOCK 4096
 #define MAX_OUTPUT_BLOCK_SIZE 262144
 
@@ -271,6 +270,66 @@ static void add_to_linker(int addr,int target,int ext);
 
 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
+}
+
+static void start_tcache_write(void *start, void *end)
+{
+  mprotect_w_x(start, end, 0);
+}
+
+static void end_tcache_write(void *start, void *end)
+{
+#ifdef __arm__
+  size_t len = (char *)end - (char *)start;
+  #if   defined(__BLACKBERRY_QNX__)
+  msync(start, len, MS_SYNC | MS_CACHE_ONLY | MS_INVALIDATE_ICACHE);
+  #elif defined(__MACH__)
+  sys_cache_control(kCacheFunctionPrepareForExecution, start, len);
+  #elif defined(VITA)
+  sceKernelSyncVMDomain(sceBlock, start, len);
+  #elif defined(_3DS)
+  ctr_flush_invalidate_cache();
+  #else
+  __clear_cache(start, end);
+  #endif
+  (void)len;
+#endif
+
+  mprotect_w_x(start, end, 1);
+}
+
+static void *start_block(void)
+{
+  u_char *end = out + MAX_OUTPUT_BLOCK_SIZE;
+  if (end > (u_char *)BASE_ADDR + (1<<TARGET_SIZE_2))
+    end = (u_char *)BASE_ADDR + (1<<TARGET_SIZE_2);
+  start_tcache_write(out, end);
+  return out;
+}
+
+static void end_block(void *start)
+{
+  end_tcache_write(start, out);
+}
+
 //#define DEBUG_CYCLE_COUNT 1
 
 #define NO_CYCLE_PENALTY_THR 12
@@ -311,10 +370,10 @@ void *get_addr(u_int vaddr)
   while(head!=NULL) {
     if(head->vaddr==vaddr) {
   //printf("TRACE: count=%d next=%d (get_addr match %x: %x)\n",Count,next_interupt,vaddr,(int)head->addr);
-      int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
+      u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
       ht_bin[3]=ht_bin[1];
       ht_bin[2]=ht_bin[0];
-      ht_bin[1]=(int)head->addr;
+      ht_bin[1]=(u_int)head->addr;
       ht_bin[0]=vaddr;
       return head->addr;
     }
@@ -334,9 +393,9 @@ void *get_addr(u_int vaddr)
           restore_candidate[vpage>>3]|=1<<(vpage&7);
         }
         else restore_candidate[page>>3]|=1<<(page&7);
-        int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
+        u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
         if(ht_bin[0]==vaddr) {
-          ht_bin[1]=(int)head->addr; // Replace existing entry
+          ht_bin[1]=(u_int)head->addr; // Replace existing entry
         }
         else
         {
@@ -366,7 +425,7 @@ void *get_addr(u_int vaddr)
 void *get_addr_ht(u_int vaddr)
 {
   //printf("TRACE: count=%d next=%d (get_addr_ht %x)\n",Count,next_interupt,vaddr);
-  int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
+  u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
   if(ht_bin[0]==vaddr) return (void *)ht_bin[1];
   if(ht_bin[2]==vaddr) return (void *)ht_bin[3];
   return get_addr(vaddr);
@@ -634,6 +693,7 @@ int needed_again(int r, int i)
     }
   }*/
   if(rn<10) return 1;
+  (void)b;
   return 0;
 }
 
@@ -781,7 +841,7 @@ void *check_addr(u_int vaddr)
 void remove_hash(int vaddr)
 {
   //printf("remove hash: %x\n",vaddr);
-  int *ht_bin=hash_table[(((vaddr)>>16)^vaddr)&0xFFFF];
+  u_int *ht_bin=hash_table[(((vaddr)>>16)^vaddr)&0xFFFF];
   if(ht_bin[2]==vaddr) {
     ht_bin[2]=ht_bin[3]=-1;
   }
@@ -817,7 +877,7 @@ void ll_clear(struct ll_entry **head)
 {
   struct ll_entry *cur;
   struct ll_entry *next;
-  if(cur=*head) {
+  if((cur=*head)) {
     *head=0;
     while(cur) {
       next=cur->next;
@@ -828,7 +888,7 @@ void ll_clear(struct ll_entry **head)
 }
 
 // Dereference the pointers and remove if it matches
-void ll_kill_pointers(struct ll_entry *head,int addr,int shift)
+static void ll_kill_pointers(struct ll_entry *head,int addr,int shift)
 {
   while(head) {
     int ptr=get_pointer(head->addr);
@@ -837,10 +897,11 @@ void ll_kill_pointers(struct ll_entry *head,int addr,int shift)
        (((ptr-MAX_OUTPUT_BLOCK_SIZE)>>shift)==(addr>>shift)))
     {
       inv_debug("EXP: Kill pointer at %x (%x)\n",(int)head->addr,head->vaddr);
-      u_int host_addr=(u_int)kill_pointer(head->addr);
+      void *host_addr=find_extjump_insn(head->addr);
       #ifdef __arm__
-        needs_clear_cache[(host_addr-(u_int)BASE_ADDR)>>17]|=1<<(((host_addr-(u_int)BASE_ADDR)>>12)&31);
+        mark_clear_cache(host_addr);
       #endif
+      set_jump_target((int)host_addr,(int)head->addr);
     }
     head=head->next;
   }
@@ -864,10 +925,11 @@ void invalidate_page(u_int page)
   jump_out[page]=0;
   while(head!=NULL) {
     inv_debug("INVALIDATE: kill pointer to %x (%x)\n",head->vaddr,(int)head->addr);
-    u_int host_addr=(u_int)kill_pointer(head->addr);
+    void *host_addr=find_extjump_insn(head->addr);
     #ifdef __arm__
-      needs_clear_cache[(host_addr-(u_int)BASE_ADDR)>>17]|=1<<(((host_addr-(u_int)BASE_ADDR)>>12)&31);
+      mark_clear_cache(host_addr);
     #endif
+    set_jump_target((int)host_addr,(int)head->addr);
     next=head->next;
     free(head);
     head=next;
@@ -991,7 +1053,7 @@ void invalidate_addr(u_int addr)
 // Anything could have changed, so invalidate everything.
 void invalidate_all_pages()
 {
-  u_int page,n;
+  u_int page;
   for(page=0;page<4096;page++)
     invalidate_page(page);
   for(page=0;page<1048576;page++)
@@ -999,9 +1061,6 @@ void invalidate_all_pages()
       restore_candidate[(page&2047)>>3]|=1<<(page&7);
       restore_candidate[((page&2047)>>3)+256]|=1<<(page&7);
     }
-  #ifdef __arm__
-  __clear_cache((void *)BASE_ADDR,(void *)BASE_ADDR+(1<<TARGET_SIZE_2));
-  #endif
   #ifdef USE_MINI_HT
   memset(mini_ht,-1,sizeof(mini_ht));
   #endif
@@ -1014,6 +1073,7 @@ void add_link(u_int vaddr,void *src)
   inv_debug("add_link: %x -> %x (%d)\n",(int)src,vaddr,page);
   int *ptr=(int *)(src+4);
   assert((*ptr&0x0fff0000)==0x059f0000);
+  (void)ptr;
   ll_add(jump_out+page,vaddr,src);
   //int ptr=get_pointer(src);
   //inv_debug("add_link: Pointer is to %x\n",(int)ptr);
@@ -1033,7 +1093,7 @@ void clean_blocks(u_int page)
       // Don't restore blocks which are about to expire from the cache
       if((((u_int)head->addr-(u_int)out)<<(32-TARGET_SIZE_2))>0x60000000+(MAX_OUTPUT_BLOCK_SIZE<<(32-TARGET_SIZE_2))) {
         u_int start,end;
-        if(verify_dirty((int)head->addr)) {
+        if(verify_dirty(head->addr)) {
           //printf("Possibly Restore %x (%x)\n",head->vaddr, (int)head->addr);
           u_int i;
           u_int inv=0;
@@ -1054,12 +1114,12 @@ void clean_blocks(u_int page)
               //printf("page=%x, addr=%x\n",page,head->vaddr);
               //assert(head->vaddr>>12==(page|0x80000));
               ll_add_flags(jump_in+ppage,head->vaddr,head->reg_sv_flags,clean_addr);
-              int *ht_bin=hash_table[((head->vaddr>>16)^head->vaddr)&0xFFFF];
+              u_int *ht_bin=hash_table[((head->vaddr>>16)^head->vaddr)&0xFFFF];
               if(ht_bin[0]==head->vaddr) {
-                ht_bin[1]=(int)clean_addr; // Replace existing entry
+                ht_bin[1]=(u_int)clean_addr; // Replace existing entry
               }
               if(ht_bin[2]==head->vaddr) {
-                ht_bin[3]=(int)clean_addr; // Replace existing entry
+                ht_bin[3]=(u_int)clean_addr; // Replace existing entry
               }
             }
           }
@@ -2333,23 +2393,25 @@ void imm16_assemble(int i,struct regstat *i_regs)
                 emit_mov(sh,th);
               }
             }
-            if(opcode[i]==0x0d) //ORI
-            if(sl<0) {
-              emit_orimm(tl,imm[i],tl);
-            }else{
-              if(!((i_regs->wasconst>>sl)&1))
-                emit_orimm(sl,imm[i],tl);
-              else
-                emit_movimm(constmap[i][sl]|imm[i],tl);
+            if(opcode[i]==0x0d) { // ORI
+              if(sl<0) {
+                emit_orimm(tl,imm[i],tl);
+              }else{
+                if(!((i_regs->wasconst>>sl)&1))
+                  emit_orimm(sl,imm[i],tl);
+                else
+                  emit_movimm(constmap[i][sl]|imm[i],tl);
+              }
             }
-            if(opcode[i]==0x0e) //XORI
-            if(sl<0) {
-              emit_xorimm(tl,imm[i],tl);
-            }else{
-              if(!((i_regs->wasconst>>sl)&1))
-                emit_xorimm(sl,imm[i],tl);
-              else
-                emit_movimm(constmap[i][sl]^imm[i],tl);
+            if(opcode[i]==0x0e) { // XORI
+              if(sl<0) {
+                emit_xorimm(tl,imm[i],tl);
+              }else{
+                if(!((i_regs->wasconst>>sl)&1))
+                  emit_xorimm(sl,imm[i],tl);
+                else
+                  emit_movimm(constmap[i][sl]^imm[i],tl);
+              }
             }
           }
           else {
@@ -2533,7 +2595,7 @@ void load_assemble(int i,struct regstat *i_regs)
   //printf("load_assemble: c=%d\n",c);
   //if(c) printf("load_assemble: const=%x\n",(int)constmap[i][s]+offset);
   // FIXME: Even if the load is a NOP, we should check for pagefaults...
-  if(tl<0&&(!c||(((u_int)constmap[i][s]+offset)>>16)==0x1f80)
+  if((tl<0&&(!c||(((u_int)constmap[i][s]+offset)>>16)==0x1f80))
     ||rt1[i]==0) {
       // could be FIFO, must perform the read
       // ||dummy read
@@ -2790,7 +2852,7 @@ void load_assemble(int i,struct regstat *i_regs)
     emit_call((int)memdebug);
     //emit_popa();
     restore_regs(0x100f);
-  }/**/
+  }*/
 }
 
 #ifndef loadlr_assemble
@@ -2806,7 +2868,7 @@ void store_assemble(int i,struct regstat *i_regs)
   int s,th,tl,map=-1;
   int addr,temp;
   int offset;
-  int jaddr=0,jaddr2,type;
+  int jaddr=0,type;
   int memtarget=0,c=0;
   int agr=AGEN1+(i&1);
   int faststore_reg_override=0;
@@ -2925,7 +2987,7 @@ void store_assemble(int i,struct regstat *i_regs)
       #if defined(HAVE_CONDITIONAL_CALL) && !defined(DESTRUCTIVE_SHIFT)
       emit_callne(invalidate_addr_reg[addr]);
       #else
-      jaddr2=(int)out;
+      int jaddr2=(int)out;
       emit_jne(0);
       add_stub(INVCODE_STUB,jaddr2,(int)out,reglist|(1<<HOST_CCREG),addr,0,0,0);
       #endif
@@ -2986,16 +3048,16 @@ void store_assemble(int i,struct regstat *i_regs)
     #ifdef __arm__
     restore_regs(0x100f);
     #endif
-  }/**/
+  }*/
 }
 
 void storelr_assemble(int i,struct regstat *i_regs)
 {
   int s,th,tl;
   int temp;
-  int temp2;
+  int temp2=-1;
   int offset;
-  int jaddr=0,jaddr2;
+  int jaddr=0;
   int case1,case2,case3;
   int done0,done1,done2;
   int memtarget=0,c=0;
@@ -3198,7 +3260,7 @@ void storelr_assemble(int i,struct regstat *i_regs)
     #if defined(HAVE_CONDITIONAL_CALL) && !defined(DESTRUCTIVE_SHIFT)
     emit_callne(invalidate_addr_reg[temp]);
     #else
-    jaddr2=(int)out;
+    int jaddr2=(int)out;
     emit_jne(0);
     add_stub(INVCODE_STUB,jaddr2,(int)out,reglist|(1<<HOST_CCREG),temp,0,0,0);
     #endif
@@ -3215,7 +3277,7 @@ void storelr_assemble(int i,struct regstat *i_regs)
     emit_call((int)memdebug);
     emit_popa();
     //restore_regs(0x100f);
-  /**/
+  */
 }
 
 void c1ls_assemble(int i,struct regstat *i_regs)
@@ -3229,7 +3291,7 @@ void c2ls_assemble(int i,struct regstat *i_regs)
   int ar;
   int offset;
   int memtarget=0,c=0;
-  int jaddr2=0,jaddr3,type;
+  int jaddr2=0,type;
   int agr=AGEN1+(i&1);
   int fastio_reg_override=0;
   u_int hr,reglist=0;
@@ -3310,7 +3372,7 @@ void c2ls_assemble(int i,struct regstat *i_regs)
     #if defined(HAVE_CONDITIONAL_CALL) && !defined(DESTRUCTIVE_SHIFT)
     emit_callne(invalidate_addr_reg[ar]);
     #else
-    jaddr3=(int)out;
+    int jaddr3=(int)out;
     emit_jne(0);
     add_stub(INVCODE_STUB,jaddr3,(int)out,reglist|(1<<HOST_CCREG),ar,0,0,0);
     #endif
@@ -3371,6 +3433,7 @@ void syscall_assemble(int i,struct regstat *i_regs)
   signed char ccreg=get_reg(i_regs->regmap,CCREG);
   assert(ccreg==HOST_CCREG);
   assert(!is_delayslot);
+  (void)ccreg;
   emit_movimm(start+i*4,EAX); // Get PC
   emit_addimm(HOST_CCREG,CLOCK_ADJUST(ccadj[i]),HOST_CCREG); // CHECK: is this right?  There should probably be an extra cycle...
   emit_jmp((int)jump_syscall_hle); // XXX
@@ -3378,11 +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);
 }
@@ -3392,6 +3461,7 @@ void intcall_assemble(int i,struct regstat *i_regs)
   signed char ccreg=get_reg(i_regs->regmap,CCREG);
   assert(ccreg==HOST_CCREG);
   assert(!is_delayslot);
+  (void)ccreg;
   emit_movimm(start+i*4,0); // Get PC
   emit_addimm(HOST_CCREG,CLOCK_ADJUST(ccadj[i]),HOST_CCREG);
   emit_jmp((int)jump_intcall);
@@ -4193,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)
 {
@@ -4200,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]);
@@ -4636,7 +4729,6 @@ static void ujump_assemble_write_ra(int i)
 
 void ujump_assemble(int i,struct regstat *i_regs)
 {
-  signed char *i_regmap=i_regs->regmap;
   int ra_done=0;
   if(i==(ba[i]-start)>>2) assem_debug("idle loop\n");
   address_generation(i+1,i_regs,regs[i].regmap_entry);
@@ -4644,6 +4736,7 @@ void ujump_assemble(int i,struct regstat *i_regs)
   int temp=get_reg(branch_regs[i].regmap,PTEMP);
   if(rt1[i]==31&&temp>=0)
   {
+    signed char *i_regmap=i_regs->regmap;
     int return_address=start+i*4+8;
     if(get_reg(branch_regs[i].regmap,31)>0)
     if(i_regmap[temp]==PTEMP) emit_movimm((int)hash_table[((return_address>>16)^return_address)&0xFFFF],temp);
@@ -4709,9 +4802,8 @@ static void rjump_assemble_write_ra(int i)
 
 void rjump_assemble(int i,struct regstat *i_regs)
 {
-  signed char *i_regmap=i_regs->regmap;
   int temp;
-  int rs,cc,adj;
+  int rs,cc;
   int ra_done=0;
   rs=get_reg(branch_regs[i].regmap,rs1[i]);
   assert(rs>=0);
@@ -4728,6 +4820,7 @@ void rjump_assemble(int i,struct regstat *i_regs)
   if(rt1[i]==31)
   {
     if((temp=get_reg(branch_regs[i].regmap,PTEMP))>=0) {
+      signed char *i_regmap=i_regs->regmap;
       int return_address=start+i*4+8;
       if(i_regmap[temp]==PTEMP) emit_movimm((int)hash_table[((return_address>>16)^return_address)&0xFFFF],temp);
     }
@@ -4756,6 +4849,7 @@ void rjump_assemble(int i,struct regstat *i_regs)
     rjump_assemble_write_ra(i);
   cc=get_reg(branch_regs[i].regmap,CCREG);
   assert(cc==HOST_CCREG);
+  (void)cc;
   #ifdef USE_MINI_HT
   int rh=get_reg(branch_regs[i].regmap,RHASH);
   int ht=get_reg(branch_regs[i].regmap,RHTBL);
@@ -5761,7 +5855,6 @@ static void pagespan_assemble(int i,struct regstat *i_regs)
   int s1h=get_reg(i_regs->regmap,rs1[i]|64);
   int s2l=get_reg(i_regs->regmap,rs2[i]);
   int s2h=get_reg(i_regs->regmap,rs2[i]|64);
-  void *nt_branch=NULL;
   int taken=0;
   int nottaken=0;
   int unconditional=0;
@@ -5778,7 +5871,7 @@ static void pagespan_assemble(int i,struct regstat *i_regs)
     s1h=s2h=-1;
   }
   int hr=0;
-  int addr,alt,ntaddr;
+  int addr=-1,alt=-1,ntaddr=-1;
   if(i_regs->regmap[HOST_BTREG]<0) {addr=HOST_BTREG;}
   else {
     while(hr<HOST_REGS)
@@ -6771,7 +6864,7 @@ void clean_registers(int istart,int iend,int wr)
               if(r!=EXCLUDE_REG) {
                 if(regs[i].regmap[r]==regmap_pre[i+2][r]) {
                   regs[i+2].wasdirty&=wont_dirty_i|~(1<<r);
-                }else {/*printf("i: %x (%d) mismatch(+2): %d\n",start+i*4,i,r);/*assert(!((wont_dirty_i>>r)&1));*/}
+                }else {/*printf("i: %x (%d) mismatch(+2): %d\n",start+i*4,i,r);assert(!((wont_dirty_i>>r)&1));*/}
               }
             }
           }
@@ -6783,7 +6876,7 @@ void clean_registers(int istart,int iend,int wr)
               if(r!=EXCLUDE_REG) {
                 if(regs[i].regmap[r]==regmap_pre[i+1][r]) {
                   regs[i+1].wasdirty&=wont_dirty_i|~(1<<r);
-                }else {/*printf("i: %x (%d) mismatch(+1): %d\n",start+i*4,i,r);/*assert(!((wont_dirty_i>>r)&1));*/}
+                }else {/*printf("i: %x (%d) mismatch(+1): %d\n",start+i*4,i,r);assert(!((wont_dirty_i>>r)&1));*/}
               }
             }
           }
@@ -6826,7 +6919,7 @@ void clean_registers(int istart,int iend,int wr)
             wont_dirty_i|=((unneeded_reg[i]>>(regmap_pre[i][r]&63))&1)<<r;
           } else {
             wont_dirty_i|=1<<r;
-            /*printf("i: %x (%d) mismatch: %d\n",start+i*4,i,r);/*assert(!((will_dirty>>r)&1));*/
+            /*printf("i: %x (%d) mismatch: %d\n",start+i*4,i,r);assert(!((will_dirty>>r)&1));*/
           }
         }
       }
@@ -6932,13 +7025,14 @@ static void disassemble_inst(int i) {}
 static int new_dynarec_test(void)
 {
   int (*testfunc)(void) = (void *)out;
+  void *beginning;
   int ret;
+
+  beginning = start_block();
   emit_movimm(DRC_TEST_VAL,0); // test
   emit_jmpreg(14);
   literal_pool(0);
-#ifdef __arm__
-  __clear_cache((void *)testfunc, out);
-#endif
+  end_block(beginning);
   SysPrintf("testing if we can run recompiled code..\n");
   ret = testfunc();
   if (ret == DRC_TEST_VAL)
@@ -6975,20 +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_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();
   }
+  #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
-  int n;
+  out=(u_char *)BASE_ADDR;
   cycle_multiplier=200;
   new_dynarec_clear_full();
 #ifdef HOST_IMM8
@@ -7007,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);
@@ -7037,6 +7160,7 @@ static u_int *get_source_start(u_int addr, u_int *limit)
     *limit = (addr & 0x80600000) + 0x00200000;
     return (u_int *)((u_int)rdram + (addr&0x1fffff));
   }
+  return NULL;
 }
 
 static u_int scan_for_ret(u_int addr)
@@ -7054,6 +7178,7 @@ static u_int scan_for_ret(u_int addr)
     if (*mem == 0x03e00008) // jr $ra
       return addr + 8;
   }
+  return addr;
 }
 
 struct savestate_block {
@@ -7167,16 +7292,15 @@ int new_recompile_block(int addr)
   if (Config.HLE && start == 0x80001000) // hlecall
   {
     // XXX: is this enough? Maybe check hleSoftCall?
-    u_int beginning=(u_int)out;
+    void *beginning=start_block();
     u_int page=get_page(start);
+
     invalid_code[start>>12]=0;
     emit_movimm(start,0);
     emit_writeword(0,(int)&pcaddr);
     emit_jmp((int)new_dyna_leave);
     literal_pool(0);
-#ifdef __arm__
-    __clear_cache((void *)beginning,out);
-#endif
+    end_block(beginning);
     ll_add_flags(jump_in+page,start,state_rflags,(void *)beginning);
     return 0;
   }
@@ -8359,7 +8483,7 @@ int new_recompile_block(int addr)
       // Create entry (branch target) regmap
       for(hr=0;hr<HOST_REGS;hr++)
       {
-        int r,or,er;
+        int r,or;
         r=current.regmap[hr];
         if(r>=0) {
           if(r!=regmap_pre[i][hr]) {
@@ -9878,7 +10002,7 @@ int new_recompile_block(int addr)
   cop1_usable=0;
   uint64_t is32_pre=0;
   u_int dirty_pre=0;
-  u_int beginning=(u_int)out;
+  void *beginning=start_block();
   if((u_int)addr&1) {
     ds=1;
     pagespan_ds();
@@ -9932,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);
@@ -10151,7 +10277,7 @@ int new_recompile_block(int addr)
           // replace it with the new address.
           // Don't add new entries.  We'll insert the
           // ones that actually get used in check_addr().
-          int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
+          u_int *ht_bin=hash_table[((vaddr>>16)^vaddr)&0xFFFF];
           if(ht_bin[0]==vaddr) {
             ht_bin[1]=entry_point;
           }
@@ -10168,14 +10294,12 @@ int new_recompile_block(int addr)
   // Align code
   if(((u_int)out)&7) emit_addnop(13);
   #endif
-  assert((u_int)out-beginning<MAX_OUTPUT_BLOCK_SIZE);
+  assert((u_int)out-(u_int)beginning<MAX_OUTPUT_BLOCK_SIZE);
   //printf("shadow buffer: %x-%x\n",(int)copy,(int)copy+slen*4);
   memcpy(copy,source,slen*4);
   copy+=slen*4;
 
-  #ifdef __arm__
-  __clear_cache((void *)beginning,out);
-  #endif
+  end_block(beginning);
 
   // If we're within 256K of the end of the buffer,
   // start over from the beginning. (Is 256K enough?)
@@ -10219,7 +10343,7 @@ int new_recompile_block(int addr)
       case 2:
         // Clear hash table
         for(i=0;i<32;i++) {
-          int *ht_bin=hash_table[((expirep&2047)<<5)+i];
+          u_int *ht_bin=hash_table[((expirep&2047)<<5)+i];
           if((ht_bin[3]>>shift)==(base>>shift) ||
              ((ht_bin[3]-MAX_OUTPUT_BLOCK_SIZE)>>shift)==(base>>shift)) {
             inv_debug("EXP: Remove hash %x -> %x\n",ht_bin[2],ht_bin[3]);