drc: use helpers for jump checks
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / new_dynarec.c
index cfeddc2..964c07b 100644 (file)
@@ -185,8 +185,10 @@ struct link_entry
   static uint64_t unneeded_reg[MAXBLOCK];
   static uint64_t branch_unneeded_reg[MAXBLOCK];
   static signed char regmap_pre[MAXBLOCK][HOST_REGS]; // pre-instruction i?
-  static uint64_t current_constmap[HOST_REGS];
-  static uint64_t constmap[MAXBLOCK][HOST_REGS];
+  // contains 'real' consts at [i] insn, but may differ from what's actually
+  // loaded in host reg as 'final' value is always loaded, see get_final_value()
+  static uint32_t current_constmap[HOST_REGS];
+  static uint32_t constmap[MAXBLOCK][HOST_REGS];
   static struct regstat regs[MAXBLOCK];
   static struct regstat branch_regs[MAXBLOCK];
   static signed char minimum_free_regs[MAXBLOCK];
@@ -214,8 +216,11 @@ struct link_entry
 #endif
 
   int new_dynarec_hacks;
+  int new_dynarec_hacks_pergame;
   int new_dynarec_did_compile;
 
+  #define HACK_ENABLED(x) ((new_dynarec_hacks | new_dynarec_hacks_pergame) & (x))
+
   extern int cycle_count; // ... until end of the timeslice, counts -N -> 0
   extern int last_count;  // last absolute target, often = next_interupt
   extern int pcaddr;
@@ -355,7 +360,7 @@ static void start_tcache_write(void *start, void *end)
 
 static void end_tcache_write(void *start, void *end)
 {
-#ifdef __arm__
+#if defined(__arm__) || defined(__aarch64__)
   size_t len = (char *)end - (char *)start;
   #if   defined(__BLACKBERRY_QNX__)
   msync(start, len, MS_SYNC | MS_CACHE_ONLY | MS_INVALIDATE_ICACHE);
@@ -365,12 +370,14 @@ static void end_tcache_write(void *start, void *end)
   sceKernelSyncVMDomain(sceBlock, start, len);
   #elif defined(_3DS)
   ctr_flush_invalidate_cache();
+  #elif defined(__aarch64__)
+  // as of 2021, __clear_cache() is still broken on arm64
+  // so here is a custom one :(
+  clear_cache_arm64(start, end);
   #else
   __clear_cache(start, end);
   #endif
   (void)len;
-#else
-  __clear_cache(start, end);
 #endif
 
   mprotect_w_x(start, end, 1);
@@ -390,16 +397,74 @@ static void end_block(void *start)
   end_tcache_write(start, out);
 }
 
+// also takes care of w^x mappings when patching code
+static u_int needs_clear_cache[1<<(TARGET_SIZE_2-17)];
+
+static void mark_clear_cache(void *target)
+{
+  uintptr_t offset = (u_char *)target - ndrc->translation_cache;
+  u_int mask = 1u << ((offset >> 12) & 31);
+  if (!(needs_clear_cache[offset >> 17] & mask)) {
+    char *start = (char *)((uintptr_t)target & ~4095l);
+    start_tcache_write(start, start + 4095);
+    needs_clear_cache[offset >> 17] |= mask;
+  }
+}
+
+// Clearing the cache is rather slow on ARM Linux, so mark the areas
+// that need to be cleared, and then only clear these areas once.
+static void do_clear_cache(void)
+{
+  int i, j;
+  for (i = 0; i < (1<<(TARGET_SIZE_2-17)); i++)
+  {
+    u_int bitmap = needs_clear_cache[i];
+    if (!bitmap)
+      continue;
+    for (j = 0; j < 32; j++)
+    {
+      u_char *start, *end;
+      if (!(bitmap & (1<<j)))
+        continue;
+
+      start = ndrc->translation_cache + i*131072 + j*4096;
+      end = start + 4095;
+      for (j++; j < 32; j++) {
+        if (!(bitmap & (1<<j)))
+          break;
+        end += 4096;
+      }
+      end_tcache_write(start, end);
+    }
+    needs_clear_cache[i] = 0;
+  }
+}
+
 //#define DEBUG_CYCLE_COUNT 1
 
 #define NO_CYCLE_PENALTY_THR 12
 
 int cycle_multiplier; // 100 for 1.0
+int cycle_multiplier_override;
 
 static int CLOCK_ADJUST(int x)
 {
+  int m = cycle_multiplier_override
+        ? cycle_multiplier_override : cycle_multiplier;
   int s=(x>>31)|1;
-  return (x * cycle_multiplier + s * 50) / 100;
+  return (x * m + s * 50) / 100;
+}
+
+// is the op an unconditional jump?
+static int is_ujump(int i)
+{
+  return itype[i] == UJUMP || itype[i] == RJUMP
+    || (source[i] >> 16) == 0x1000; // beq r0, r0, offset // b offset
+}
+
+static int is_jump(int i)
+{
+  return itype[i] == RJUMP || itype[i] == UJUMP || itype[i] == CJUMP || itype[i] == SJUMP;
 }
 
 static u_int get_page(u_int vaddr)
@@ -547,7 +612,7 @@ void dirty_reg(struct regstat *cur,signed char reg)
   }
 }
 
-void set_const(struct regstat *cur,signed char reg,uint64_t value)
+static void set_const(struct regstat *cur, signed char reg, uint32_t value)
 {
   int hr;
   if(!reg) return;
@@ -559,7 +624,7 @@ void set_const(struct regstat *cur,signed char reg,uint64_t value)
   }
 }
 
-void clear_const(struct regstat *cur,signed char reg)
+static void clear_const(struct regstat *cur, signed char reg)
 {
   int hr;
   if(!reg) return;
@@ -570,7 +635,7 @@ void clear_const(struct regstat *cur,signed char reg)
   }
 }
 
-int is_const(struct regstat *cur,signed char reg)
+static int is_const(struct regstat *cur, signed char reg)
 {
   int hr;
   if(reg<0) return 0;
@@ -582,7 +647,8 @@ int is_const(struct regstat *cur,signed char reg)
   }
   return 0;
 }
-uint64_t get_const(struct regstat *cur,signed char reg)
+
+static uint32_t get_const(struct regstat *cur, signed char reg)
 {
   int hr;
   if(!reg) return 0;
@@ -608,7 +674,7 @@ void lsn(u_char hsn[], int i, int *preferred_reg)
       j=slen-i-1;
       break;
     }
-    if(itype[i+j]==UJUMP||itype[i+j]==RJUMP||(source[i+j]>>16)==0x1000)
+    if (is_ujump(i+j))
     {
       // Don't go past an unconditonal jump
       j++;
@@ -656,7 +722,7 @@ void lsn(u_char hsn[], int i, int *preferred_reg)
     // TODO: preferred register based on backward branch
   }
   // Delay slot should preferably not overwrite branch conditions or cycle count
-  if(i>0&&(itype[i-1]==RJUMP||itype[i-1]==UJUMP||itype[i-1]==CJUMP||itype[i-1]==SJUMP)) {
+  if (i > 0 && is_jump(i-1)) {
     if(rs1[i-1]) if(hsn[rs1[i-1]]>1) hsn[rs1[i-1]]=1;
     if(rs2[i-1]) if(hsn[rs2[i-1]]>1) hsn[rs2[i-1]]=1;
     hsn[CCREG]=1;
@@ -691,7 +757,7 @@ int needed_again(int r, int i)
   int b=-1;
   int rn=10;
 
-  if(i>0&&(itype[i-1]==UJUMP||itype[i-1]==RJUMP||(source[i-1]>>16)==0x1000))
+  if (i > 0 && is_ujump(i-1))
   {
     if(ba[i-1]<start || ba[i-1]>start+slen*4-4)
       return 0; // Don't need any registers if exiting the block
@@ -702,7 +768,7 @@ int needed_again(int r, int i)
       j=slen-i-1;
       break;
     }
-    if(itype[i+j]==UJUMP||itype[i+j]==RJUMP||(source[i+j]>>16)==0x1000)
+    if (is_ujump(i+j))
     {
       // Don't go past an unconditonal jump
       j++;
@@ -758,7 +824,7 @@ int loop_reg(int i, int r, int hr)
       j=slen-i-1;
       break;
     }
-    if(itype[i+j]==UJUMP||itype[i+j]==RJUMP||(source[i+j]>>16)==0x1000)
+    if (is_ujump(i+j))
     {
       // Don't go past an unconditonal jump
       j++;
@@ -1054,9 +1120,7 @@ static void ll_kill_pointers(struct ll_entry *head,uintptr_t addr,int shift)
     {
       inv_debug("EXP: Kill pointer at %p (%x)\n",head->addr,head->vaddr);
       void *host_addr=find_extjump_insn(head->addr);
-      #if defined(__arm__) || defined(__aarch64__)
-        mark_clear_cache(host_addr);
-      #endif
+      mark_clear_cache(host_addr);
       set_jump_target(host_addr, head->addr);
     }
     head=head->next;
@@ -1082,9 +1146,7 @@ static void invalidate_page(u_int page)
   while(head!=NULL) {
     inv_debug("INVALIDATE: kill pointer to %x (%p)\n",head->vaddr,head->addr);
     void *host_addr=find_extjump_insn(head->addr);
-    #if defined(__arm__) || defined(__aarch64__)
-      mark_clear_cache(host_addr);
-    #endif
+    mark_clear_cache(host_addr);
     set_jump_target(host_addr, head->addr);
     next=head->next;
     free(head);
@@ -1107,9 +1169,7 @@ static void invalidate_block_range(u_int block, u_int first, u_int last)
   for(first=page+1;first<last;first++) {
     invalidate_page(first);
   }
-  #if defined(__arm__) || defined(__aarch64__)
-    do_clear_cache();
-  #endif
+  do_clear_cache();
 
   // Don't trap writes
   invalid_code[block]=1;
@@ -1206,7 +1266,7 @@ void invalidate_addr(u_int addr)
 
 // This is called when loading a save state.
 // Anything could have changed, so invalidate everything.
-void invalidate_all_pages()
+void invalidate_all_pages(void)
 {
   u_int page;
   for(page=0;page<4096;page++)
@@ -1219,6 +1279,7 @@ void invalidate_all_pages()
   #ifdef USE_MINI_HT
   memset(mini_ht,-1,sizeof(mini_ht));
   #endif
+  do_clear_cache();
 }
 
 static void do_invstub(int n)
@@ -1677,7 +1738,7 @@ static void imm16_alloc(struct regstat *current,int i)
     else clear_const(current,rt1[i]);
   }
   else {
-    set_const(current,rt1[i],((long long)((short)imm[i]))<<16); // LUI
+    set_const(current,rt1[i],imm[i]<<16); // LUI
   }
   dirty_reg(current,rt1[i]);
 }
@@ -2117,10 +2178,11 @@ static void alu_assemble(int i,struct regstat *i_regs)
           s2l=get_reg(i_regs->regmap,rs2[i]);
           if(rs2[i]==0) // rx<r0
           {
-            assert(s1l>=0);
-            if(opcode2[i]==0x2a) // SLT
+            if(opcode2[i]==0x2a&&rs1[i]!=0) { // SLT
+              assert(s1l>=0);
               emit_shrimm(s1l,31,t);
-            else // SLTU (unsigned can not be less than zero)
+            }
+            else // SLTU (unsigned can not be less than zero, 0<0)
               emit_zeroreg(t);
           }
           else if(rs1[i]==0) // r0<rx
@@ -2885,7 +2947,7 @@ void store_assemble(int i,struct regstat *i_regs)
     add_stub_r(type,jaddr,out,i,addr,i_regs,ccadj[i],reglist);
     jaddr=0;
   }
-  if(!(i_regs->waswritten&(1<<rs1[i]))&&!(new_dynarec_hacks&NDHACK_NO_SMC_CHECK)) {
+  if(!(i_regs->waswritten&(1<<rs1[i])) && !HACK_ENABLED(NDHACK_NO_SMC_CHECK)) {
     if(!c||memtarget) {
       #ifdef DESTRUCTIVE_SHIFT
       // The x86 shift operation is 'destructive'; it overwrites the
@@ -3050,7 +3112,7 @@ static void storelr_assemble(int i,struct regstat *i_regs)
   set_jump_target(done2, out);
   if(!c||!memtarget)
     add_stub_r(STORELR_STUB,jaddr,out,i,temp,i_regs,ccadj[i],reglist);
-  if(!(i_regs->waswritten&(1<<rs1[i]))&&!(new_dynarec_hacks&NDHACK_NO_SMC_CHECK)) {
+  if(!(i_regs->waswritten&(1<<rs1[i])) && !HACK_ENABLED(NDHACK_NO_SMC_CHECK)) {
     emit_addimm_no_flags(-ram_offset,temp);
     #if defined(HOST_IMM8)
     int ir=get_reg(i_regs->regmap,INVCP);
@@ -3360,7 +3422,7 @@ static void c2ls_assemble(int i,struct regstat *i_regs)
   if(jaddr2)
     add_stub_r(type,jaddr2,out,i,ar,i_regs,ccadj[i],reglist);
   if(opcode[i]==0x3a) // SWC2
-  if(!(i_regs->waswritten&(1<<rs1[i]))&&!(new_dynarec_hacks&NDHACK_NO_SMC_CHECK)) {
+  if(!(i_regs->waswritten&(1<<rs1[i])) && !HACK_ENABLED(NDHACK_NO_SMC_CHECK)) {
 #if defined(HOST_IMM8)
     int ir=get_reg(i_regs->regmap,INVCP);
     assert(ir>=0);
@@ -4281,9 +4343,24 @@ static void drc_dbg_emit_do_cmp(int i)
   //extern int cycle;
   u_int hr,reglist=0;
 
-  for(hr=0;hr<HOST_REGS;hr++)
+  assem_debug("//do_insn_cmp %08x\n", start+i*4);
+  for (hr = 0; hr < HOST_REGS; hr++)
     if(regs[i].regmap[hr]>=0) reglist|=1<<hr;
   save_regs(reglist);
+  // write out changed consts to match the interpreter
+  if (i > 0 && !bt[i]) {
+    for (hr = 0; hr < HOST_REGS; hr++) {
+      int reg = regs[i-1].regmap[hr];
+      if (hr == EXCLUDE_REG || reg < 0)
+        continue;
+      if (!((regs[i-1].isconst >> hr) & 1))
+        continue;
+      if (i > 1 && reg == regs[i-2].regmap[hr] && constmap[i-1][hr] == constmap[i-2][hr])
+        continue;
+      emit_movimm(constmap[i-1][hr],0);
+      emit_storereg(reg, 0);
+    }
+  }
   emit_movimm(start+i*4,0);
   emit_writeword(0,&pcaddr);
   emit_far_call(do_insn_cmp);
@@ -4292,6 +4369,7 @@ static void drc_dbg_emit_do_cmp(int i)
   //emit_writeword(0,&cycle);
   (void)get_reg2;
   restore_regs(reglist);
+  assem_debug("\\\\do_insn_cmp\n");
 }
 #else
 #define drc_dbg_emit_do_cmp(x)
@@ -4418,11 +4496,13 @@ void do_cc(int i,signed char i_regmap[],int *adj,int addr,int taken,int invert)
   else if(*adj==0||invert) {
     int cycles=CLOCK_ADJUST(count+2);
     // faster loop HACK
+#if 0
     if (t&&*adj) {
       int rel=t-i;
       if(-NO_CYCLE_PENALTY_THR<rel&&rel<0)
         cycles=CLOCK_ADJUST(*adj)+count+2-*adj;
     }
+#endif
     emit_addimm_and_set_flags(cycles,HOST_CCREG);
     jaddr=out;
     emit_jns(0);
@@ -5729,7 +5809,7 @@ void unneeded_registers(int istart,int iend,int r)
   uint64_t u,gte_u,b,gte_b;
   uint64_t temp_u,temp_gte_u=0;
   uint64_t gte_u_unknown=0;
-  if(new_dynarec_hacks&NDHACK_GTE_UNNEEDED)
+  if (HACK_ENABLED(NDHACK_GTE_UNNEEDED))
     gte_u_unknown=~0ll;
   if(iend==slen-1) {
     u=1;
@@ -5780,7 +5860,7 @@ void unneeded_registers(int istart,int iend,int r)
         bt[(ba[i]-start)>>2]=1;
         if(ba[i]<=start+i*4) {
           // Backward branch
-          if(itype[i]==RJUMP||itype[i]==UJUMP||(source[i]>>16)==0x1000)
+          if(is_ujump(i))
           {
             // Unconditional branch
             temp_u=1;
@@ -5825,7 +5905,7 @@ void unneeded_registers(int istart,int iend,int r)
             gte_unneeded[(ba[i]-start)>>2]=gte_u_unknown;
           }
         } /*else*/ if(1) {
-          if(itype[i]==RJUMP||itype[i]==UJUMP||(source[i]>>16)==0x1000)
+          if (is_ujump(i))
           {
             // Unconditional branch
             u=unneeded_reg[(ba[i]-start)>>2];
@@ -5935,7 +6015,7 @@ void clean_registers(int istart,int iend,int wr)
       if(ba[i]<start || ba[i]>=(start+slen*4))
       {
         // Branch out of this block, flush all regs
-        if(itype[i]==RJUMP||itype[i]==UJUMP||(source[i]>>16)==0x1000)
+        if (is_ujump(i))
         {
           // Unconditional branch
           will_dirty_i=0;
@@ -6015,7 +6095,7 @@ void clean_registers(int istart,int iend,int wr)
         // Internal branch
         if(ba[i]<=start+i*4) {
           // Backward branch
-          if(itype[i]==RJUMP||itype[i]==UJUMP||(source[i]>>16)==0x1000)
+          if (is_ujump(i))
           {
             // Unconditional branch
             temp_will_dirty=0;
@@ -6112,7 +6192,7 @@ void clean_registers(int istart,int iend,int wr)
         }
         /*else*/ if(1)
         {
-          if(itype[i]==RJUMP||itype[i]==UJUMP||(source[i]>>16)==0x1000)
+          if (is_ujump(i))
           {
             // Unconditional branch
             will_dirty_i=0;
@@ -6279,7 +6359,7 @@ void clean_registers(int istart,int iend,int wr)
         regs[i].dirty&=wont_dirty_i;
         if(itype[i]==RJUMP||itype[i]==UJUMP||itype[i]==CJUMP||itype[i]==SJUMP)
         {
-          if(i<iend-1&&itype[i]!=RJUMP&&itype[i]!=UJUMP&&(source[i]>>16)!=0x1000) {
+          if (i < iend-1 && !is_ujump(i)) {
             for(r=0;r<HOST_REGS;r++) {
               if(r!=EXCLUDE_REG) {
                 if(regs[i].regmap[r]==regmap_pre[i+2][r]) {
@@ -6476,7 +6556,7 @@ static void new_dynarec_test(void)
 
 // clear the state completely, instead of just marking
 // things invalid like invalidate_all_pages() does
-void new_dynarec_clear_full()
+void new_dynarec_clear_full(void)
 {
   int n;
   out = ndrc->translation_cache;
@@ -6497,7 +6577,7 @@ void new_dynarec_clear_full()
   for(n=0;n<4096;n++) ll_clear(jump_dirty+n);
 }
 
-void new_dynarec_init()
+void new_dynarec_init(void)
 {
   SysPrintf("Init new dynarec\n");
 
@@ -6547,7 +6627,7 @@ void new_dynarec_init()
     SysPrintf("warning: RAM is not directly mapped, performance will suffer\n");
 }
 
-void new_dynarec_cleanup()
+void new_dynarec_cleanup(void)
 {
   int n;
 #ifdef BASE_ADDR_DYNAMIC
@@ -6569,16 +6649,25 @@ void new_dynarec_cleanup()
 
 static u_int *get_source_start(u_int addr, u_int *limit)
 {
+  if (!HACK_ENABLED(NDHACK_OVERRIDE_CYCLE_M))
+    cycle_multiplier_override = 0;
+
   if (addr < 0x00200000 ||
-    (0xa0000000 <= addr && addr < 0xa0200000)) {
+    (0xa0000000 <= addr && addr < 0xa0200000))
+  {
     // used for BIOS calls mostly?
     *limit = (addr&0xa0000000)|0x00200000;
     return (u_int *)(rdram + (addr&0x1fffff));
   }
   else if (!Config.HLE && (
     /* (0x9fc00000 <= addr && addr < 0x9fc80000) ||*/
-    (0xbfc00000 <= addr && addr < 0xbfc80000))) {
-    // BIOS
+    (0xbfc00000 <= addr && addr < 0xbfc80000)))
+  {
+    // BIOS. The multiplier should be much higher as it's uncached 8bit mem,
+    // but timings in PCSX are too tied to the interpreter's BIAS
+    if (!HACK_ENABLED(NDHACK_OVERRIDE_CYCLE_M))
+      cycle_multiplier_override = 200;
+
     *limit = (addr & 0xfff00000) | 0x80000;
     return (u_int *)((u_char *)psxR + (addr&0x7ffff));
   }
@@ -7161,7 +7250,7 @@ int new_recompile_block(u_int addr)
     else if(type==CJUMP||type==SJUMP)
       ba[i]=start+i*4+4+((signed int)((unsigned int)source[i]<<16)>>14);
     else ba[i]=-1;
-    if(i>0&&(itype[i-1]==RJUMP||itype[i-1]==UJUMP||itype[i-1]==CJUMP||itype[i-1]==SJUMP)) {
+    if (i > 0 && is_jump(i-1)) {
       int do_in_intrp=0;
       // branch in delay slot?
       if(type==RJUMP||type==UJUMP||type==CJUMP||type==SJUMP) {
@@ -7179,7 +7268,7 @@ int new_recompile_block(u_int addr)
           bt[t+1]=1; // expected return from interpreter
         }
         else if(i>=2&&rt1[i-2]==2&&rt1[i]==2&&rs1[i]!=2&&rs2[i]!=2&&rs1[i-1]!=2&&rs2[i-1]!=2&&
-              !(i>=3&&(itype[i-3]==RJUMP||itype[i-3]==UJUMP||itype[i-3]==CJUMP||itype[i-3]==SJUMP))) {
+              !(i>=3&&is_jump(i-3))) {
           // v0 overwrite like this is a sign of trouble, bail out
           SysPrintf("v0 overwrite @%08x (%08x)\n", addr + i*4, addr);
           do_in_intrp=1;
@@ -7195,7 +7284,7 @@ int new_recompile_block(u_int addr)
       }
     }
     /* Is this the end of the block? */
-    if(i>0&&(itype[i-1]==UJUMP||itype[i-1]==RJUMP||(source[i-1]>>16)==0x1000)) {
+    if (i > 0 && is_ujump(i-1)) {
       if(rt1[i-1]==0) { // Continue past subroutine call (JAL)
         done=2;
       }
@@ -7656,7 +7745,7 @@ int new_recompile_block(u_int addr)
             dirty_reg(&branch_regs[i-1],31);
           }
           memcpy(&branch_regs[i-1].regmap_entry,&branch_regs[i-1].regmap,sizeof(current.regmap));
-          memcpy(constmap[i],constmap[i-1],sizeof(current_constmap));
+          memcpy(constmap[i],constmap[i-1],sizeof(constmap[i]));
           break;
         case RJUMP:
           memcpy(&branch_regs[i-1],&current,sizeof(current));
@@ -7677,7 +7766,7 @@ int new_recompile_block(u_int addr)
           }
           #endif
           memcpy(&branch_regs[i-1].regmap_entry,&branch_regs[i-1].regmap,sizeof(current.regmap));
-          memcpy(constmap[i],constmap[i-1],sizeof(current_constmap));
+          memcpy(constmap[i],constmap[i-1],sizeof(constmap[i]));
           break;
         case CJUMP:
           if((opcode[i-1]&0x3E)==4) // BEQ/BNE
@@ -7704,7 +7793,7 @@ int new_recompile_block(u_int addr)
             branch_regs[i-1].isconst=0;
             branch_regs[i-1].wasconst=0;
             memcpy(&branch_regs[i-1].regmap_entry,&current.regmap,sizeof(current.regmap));
-            memcpy(constmap[i],constmap[i-1],sizeof(current_constmap));
+            memcpy(constmap[i],constmap[i-1],sizeof(constmap[i]));
           }
           else
           if((opcode[i-1]&0x3E)==6) // BLEZ/BGTZ
@@ -7729,7 +7818,7 @@ int new_recompile_block(u_int addr)
             branch_regs[i-1].isconst=0;
             branch_regs[i-1].wasconst=0;
             memcpy(&branch_regs[i-1].regmap_entry,&current.regmap,sizeof(current.regmap));
-            memcpy(constmap[i],constmap[i-1],sizeof(current_constmap));
+            memcpy(constmap[i],constmap[i-1],sizeof(constmap[i]));
           }
           else
           // Alloc the delay slot in case the branch is taken
@@ -7783,7 +7872,7 @@ int new_recompile_block(u_int addr)
             branch_regs[i-1].isconst=0;
             branch_regs[i-1].wasconst=0;
             memcpy(&branch_regs[i-1].regmap_entry,&current.regmap,sizeof(current.regmap));
-            memcpy(constmap[i],constmap[i-1],sizeof(current_constmap));
+            memcpy(constmap[i],constmap[i-1],sizeof(constmap[i]));
           }
           else
           // Alloc the delay slot in case the branch is taken
@@ -7807,7 +7896,7 @@ int new_recompile_block(u_int addr)
           break;
       }
 
-      if(itype[i-1]==UJUMP||itype[i-1]==RJUMP||(source[i-1]>>16)==0x1000)
+      if (is_ujump(i-1))
       {
         if(rt1[i-1]==31) // JAL/JALR
         {
@@ -7880,7 +7969,7 @@ int new_recompile_block(u_int addr)
     if(!is_ds[i]) {
       regs[i].dirty=current.dirty;
       regs[i].isconst=current.isconst;
-      memcpy(constmap[i],current_constmap,sizeof(current_constmap));
+      memcpy(constmap[i],current_constmap,sizeof(constmap[i]));
     }
     for(hr=0;hr<HOST_REGS;hr++) {
       if(hr!=EXCLUDE_REG&&regs[i].regmap[hr]>=0) {
@@ -7921,7 +8010,7 @@ int new_recompile_block(u_int addr)
         }
       }
       // Conditional branch may need registers for following instructions
-      if(itype[i]!=RJUMP&&itype[i]!=UJUMP&&(source[i]>>16)!=0x1000)
+      if (!is_ujump(i))
       {
         if(i<slen-2) {
           nr|=needed_reg[i+2];
@@ -8022,7 +8111,7 @@ int new_recompile_block(u_int addr)
            (regs[i].regmap[hr]&63)!=rt1[i] && (regs[i].regmap[hr]&63)!=rt2[i] &&
            (regs[i].regmap[hr]&63)!=PTEMP && (regs[i].regmap[hr]&63)!=CCREG)
         {
-          if(itype[i]!=RJUMP&&itype[i]!=UJUMP&&(source[i]>>16)!=0x1000)
+          if (!is_ujump(i))
           {
             if(likely[i]) {
               regs[i].regmap[hr]=-1;
@@ -8066,7 +8155,7 @@ int new_recompile_block(u_int addr)
             {
               branch_regs[i].regmap[hr]=-1;
               branch_regs[i].regmap_entry[hr]=-1;
-              if(itype[i]!=RJUMP&&itype[i]!=UJUMP&&(source[i]>>16)!=0x1000)
+              if (!is_ujump(i))
               {
                 if(!likely[i]&&i<slen-2) {
                   regmap_pre[i+2][hr]=-1;
@@ -8257,7 +8346,7 @@ int new_recompile_block(u_int addr)
                       branch_regs[i].dirty|=(1<<hr)&regs[i].dirty;
                       branch_regs[i].wasconst&=~(1<<hr);
                       branch_regs[i].isconst&=~(1<<hr);
-                      if(itype[i]!=RJUMP&&itype[i]!=UJUMP&&(source[i]>>16)!=0x1000) {
+                      if (!is_ujump(i)) {
                         regmap_pre[i+2][hr]=f_regmap[hr];
                         regs[i+2].wasdirty&=~(1<<hr);
                         regs[i+2].wasdirty|=(1<<hr)&regs[i].dirty;
@@ -8278,7 +8367,7 @@ int new_recompile_block(u_int addr)
                       branch_regs[k].dirty&=~(1<<hr);
                       branch_regs[k].wasconst&=~(1<<hr);
                       branch_regs[k].isconst&=~(1<<hr);
-                      if(itype[k]!=RJUMP&&itype[k]!=UJUMP&&(source[k]>>16)!=0x1000) {
+                      if (!is_ujump(k)) {
                         regmap_pre[k+2][hr]=f_regmap[hr];
                         regs[k+2].wasdirty&=~(1<<hr);
                       }
@@ -8300,7 +8389,7 @@ int new_recompile_block(u_int addr)
                   //printf("no-match due to different register\n");
                   break;
                 }
-                if(itype[j]==UJUMP||itype[j]==RJUMP||(source[j]>>16)==0x1000)
+                if (is_ujump(j))
                 {
                   // Stop on unconditional branch
                   break;
@@ -8766,7 +8855,7 @@ int new_recompile_block(u_int addr)
     } else {
       speculate_register_values(i);
       #ifndef DESTRUCTIVE_WRITEBACK
-      if(i<2||(itype[i-2]!=UJUMP&&itype[i-2]!=RJUMP&&(source[i-2]>>16)!=0x1000))
+      if (i < 2 || !is_ujump(i-2))
       {
         wb_valid(regmap_pre[i],regs[i].regmap_entry,dirty_pre,regs[i].wasdirty,unneeded_reg[i]);
       }
@@ -8777,7 +8866,7 @@ int new_recompile_block(u_int addr)
       }
       #endif
       // write back
-      if(i<2||(itype[i-2]!=UJUMP&&itype[i-2]!=RJUMP&&(source[i-2]>>16)!=0x1000))
+      if (i < 2 || !is_ujump(i-2))
       {
         wb_invalidate(regmap_pre[i],regs[i].regmap_entry,regs[i].wasdirty,unneeded_reg[i]);
         loop_preload(regmap_pre[i],regs[i].regmap_entry);
@@ -8869,17 +8958,17 @@ int new_recompile_block(u_int addr)
         case SPAN:
           pagespan_assemble(i,&regs[i]);break;
       }
-      if(itype[i]==UJUMP||itype[i]==RJUMP||(source[i]>>16)==0x1000)
+      if (is_ujump(i))
         literal_pool(1024);
       else
         literal_pool_jumpover(256);
     }
   }
-  //assert(itype[i-2]==UJUMP||itype[i-2]==RJUMP||(source[i-2]>>16)==0x1000);
+  //assert(is_ujump(i-2));
   // If the block did not end with an unconditional branch,
   // add a jump to the next instruction.
   if(i>1) {
-    if(itype[i-2]!=UJUMP&&itype[i-2]!=RJUMP&&(source[i-2]>>16)!=0x1000&&itype[i-1]!=SPAN) {
+    if(!is_ujump(i-2)&&itype[i-1]!=SPAN) {
       assert(itype[i-1]!=UJUMP&&itype[i-1]!=CJUMP&&itype[i-1]!=SJUMP&&itype[i-1]!=RJUMP);
       assert(i==slen);
       if(itype[i-2]!=CJUMP&&itype[i-2]!=SJUMP) {
@@ -9082,10 +9171,8 @@ int new_recompile_block(u_int addr)
         break;
       case 3:
         // Clear jump_out
-        #if defined(__arm__) || defined(__aarch64__)
         if((expirep&2047)==0)
           do_clear_cache();
-        #endif
         ll_remove_matching_addrs(jump_out+(expirep&2047),base,shift);
         ll_remove_matching_addrs(jump_out+2048+(expirep&2047),base,shift);
         break;