drc: minor adjustments
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / new_dynarec.c
index e0cff62..f81c985 100644 (file)
@@ -47,11 +47,19 @@ static int sceBlock;
 #ifndef min
 #define min(a, b) ((b) < (a) ? (b) : (a))
 #endif
+#ifndef max
+#define max(a, b) ((b) > (a) ? (b) : (a))
+#endif
 
 //#define DISASM
-//#define assem_debug printf
-//#define inv_debug printf
+//#define ASSEM_PRINT
+
+#ifdef ASSEM_PRINT
+#define assem_debug printf
+#else
 #define assem_debug(...)
+#endif
+//#define inv_debug printf
 #define inv_debug(...)
 
 #ifdef __i386__
@@ -222,6 +230,7 @@ struct link_entry
 
   int new_dynarec_hacks;
   int new_dynarec_hacks_pergame;
+  int new_dynarec_hacks_old;
   int new_dynarec_did_compile;
 
   #define HACK_ENABLED(x) ((new_dynarec_hacks | new_dynarec_hacks_pergame) & (x))
@@ -336,7 +345,7 @@ static void add_to_linker(void *addr, u_int target, int ext);
 static void *emit_fastpath_cmp_jump(int i,int addr,int *addr_reg_override);
 static void *get_direct_memhandler(void *table, u_int addr,
   enum stub_type type, uintptr_t *addr_host);
-static void cop2_call_stall_check(u_int op, int i, const struct regstat *i_regs, u_int reglist);
+static void cop2_do_stall_check(u_int op, int i, const struct regstat *i_regs, u_int reglist);
 static void pass_args(int a0, int a1);
 static void emit_far_jump(const void *f);
 static void emit_far_call(const void *f);
@@ -454,6 +463,7 @@ static void do_clear_cache(void)
 
 int cycle_multiplier; // 100 for 1.0
 int cycle_multiplier_override;
+int cycle_multiplier_old;
 
 static int CLOCK_ADJUST(int x)
 {
@@ -905,7 +915,7 @@ static void host_tempreg_acquire(void) {}
 static void host_tempreg_release(void) {}
 #endif
 
-#ifdef DRC_DBG
+#ifdef ASSEM_PRINT
 extern void gen_interupt();
 extern void do_insn_cmp();
 #define FUNCNAME(f) { f, " " #f }
@@ -929,7 +939,9 @@ static const struct {
   FUNCNAME(new_dyna_leave),
   FUNCNAME(pcsx_mtc0),
   FUNCNAME(pcsx_mtc0_ds),
+#ifdef DRC_DBG
   FUNCNAME(do_insn_cmp),
+#endif
 #ifdef __arm__
   FUNCNAME(verify_code),
 #endif
@@ -1083,12 +1095,14 @@ void remove_hash(int vaddr)
   }
 }
 
-void ll_remove_matching_addrs(struct ll_entry **head,uintptr_t addr,int shift)
+static void ll_remove_matching_addrs(struct ll_entry **head,
+  uintptr_t base_offs_s, int shift)
 {
   struct ll_entry *next;
   while(*head) {
-    if(((uintptr_t)((*head)->addr)>>shift)==(addr>>shift) ||
-       ((uintptr_t)((*head)->addr-MAX_OUTPUT_BLOCK_SIZE)>>shift)==(addr>>shift))
+    uintptr_t o1 = (u_char *)(*head)->addr - ndrc->translation_cache;
+    uintptr_t o2 = o1 - MAX_OUTPUT_BLOCK_SIZE;
+    if ((o1 >> shift) == base_offs_s || (o2 >> shift) == base_offs_s)
     {
       inv_debug("EXP: Remove pointer to %p (%x)\n",(*head)->addr,(*head)->vaddr);
       remove_hash((*head)->vaddr);
@@ -1119,13 +1133,15 @@ void ll_clear(struct ll_entry **head)
 }
 
 // Dereference the pointers and remove if it matches
-static void ll_kill_pointers(struct ll_entry *head,uintptr_t addr,int shift)
+static void ll_kill_pointers(struct ll_entry *head,
+  uintptr_t base_offs_s, int shift)
 {
   while(head) {
-    uintptr_t ptr = (uintptr_t)get_pointer(head->addr);
-    inv_debug("EXP: Lookup pointer to %lx at %p (%x)\n",(long)ptr,head->addr,head->vaddr);
-    if(((ptr>>shift)==(addr>>shift)) ||
-       (((ptr-MAX_OUTPUT_BLOCK_SIZE)>>shift)==(addr>>shift)))
+    u_char *ptr = get_pointer(head->addr);
+    uintptr_t o1 = ptr - ndrc->translation_cache;
+    uintptr_t o2 = o1 - MAX_OUTPUT_BLOCK_SIZE;
+    inv_debug("EXP: Lookup pointer to %p at %p (%x)\n",ptr,head->addr,head->vaddr);
+    if ((o1 >> shift) == base_offs_s || (o2 >> shift) == base_offs_s)
     {
       inv_debug("EXP: Kill pointer at %p (%x)\n",head->addr,head->vaddr);
       void *host_addr=find_extjump_insn(head->addr);
@@ -1156,7 +1172,7 @@ static void invalidate_page(u_int page)
     inv_debug("INVALIDATE: kill pointer to %x (%p)\n",head->vaddr,head->addr);
     void *host_addr=find_extjump_insn(head->addr);
     mark_clear_cache(host_addr);
-    set_jump_target(host_addr, head->addr);
+    set_jump_target(host_addr, head->addr); // point back to dyna_linker
     next=head->next;
     free(head);
     head=next;
@@ -1305,14 +1321,13 @@ static void do_invstub(int n)
 
 // Add an entry to jump_out after making a link
 // src should point to code by emit_extjump2()
-void add_link(u_int vaddr,void *src)
+void add_jump_out(u_int vaddr,void *src)
 {
   u_int page=get_page(vaddr);
-  inv_debug("add_link: %p -> %x (%d)\n",src,vaddr,page);
+  inv_debug("add_jump_out: %p -> %x (%d)\n",src,vaddr,page);
   check_extjump2(src);
   ll_add(jump_out+page,vaddr,src);
-  //void *ptr=get_pointer(src);
-  //inv_debug("add_link: Pointer is to %p\n",ptr);
+  //inv_debug("add_jump_out:  to %p\n",get_pointer(src));
 }
 
 // If a code block was found to be unmodified (bit was set in
@@ -1600,6 +1615,12 @@ static void alloc_reg_temp(struct regstat *cur,int i,signed char reg)
 
 static void mov_alloc(struct regstat *current,int i)
 {
+  if (rs1[i] == HIREG || rs1[i] == LOREG) {
+    // logically this is needed but just won't work, no idea why
+    //alloc_cc(current,i); // for stalls
+    //dirty_reg(current,CCREG);
+  }
+
   // Note: Don't need to actually alloc the source registers
   //alloc_reg(current,i,rs1[i]);
   alloc_reg(current,i,rt1[i]);
@@ -1863,6 +1884,7 @@ void multdiv_alloc(struct regstat *current,int i)
   //  case 0x1F: DDIVU
   clear_const(current,rs1[i]);
   clear_const(current,rs2[i]);
+  alloc_cc(current,i); // for stalls
   if(rs1[i]&&rs2[i])
   {
     if((opcode2[i]&4)==0) // 32-bit
@@ -3314,7 +3336,6 @@ static void log_gte_stall(int stall, u_int cycle)
 {
   if ((u_int)stall <= 44)
     printf("x    stall %2d %u\n", stall, cycle + last_count);
- if (cycle + last_count > 1215348544) exit(1);
 }
 
 static void emit_log_gte_stall(int i, int stall, u_int reglist)
@@ -3330,14 +3351,13 @@ static void emit_log_gte_stall(int i, int stall, u_int reglist)
 }
 #endif
 
-static void cop2_call_stall_check(u_int op, int i, const struct regstat *i_regs, u_int reglist)
+static void cop2_do_stall_check(u_int op, int i, const struct regstat *i_regs, u_int reglist)
 {
   int j = i, other_gte_op_cycles = -1, stall = -MAXBLOCK, cycles_passed;
   int rtmp = reglist_find_free(reglist);
 
-  if (HACK_ENABLED(NDHACK_GTE_NO_STALL))
+  if (HACK_ENABLED(NDHACK_NO_STALLS))
     return;
-  //assert(get_reg(i_regs->regmap, CCREG) == HOST_CCREG);
   if (get_reg(i_regs->regmap, CCREG) != HOST_CCREG) {
     // happens occasionally... cc evicted? Don't bother then
     //printf("no cc %08x\n", start + i*4);
@@ -3349,6 +3369,7 @@ static void cop2_call_stall_check(u_int op, int i, const struct regstat *i_regs,
       if (cop2_is_stalling_op(j, &other_gte_op_cycles) || bt[j])
         break;
     }
+    j = max(j, 0);
   }
   cycles_passed = CLOCK_ADJUST(ccadj[i] - ccadj[j]);
   if (other_gte_op_cycles >= 0)
@@ -3357,7 +3378,7 @@ static void cop2_call_stall_check(u_int op, int i, const struct regstat *i_regs,
     stall = 0; // can't stall
   if (stall == -MAXBLOCK && rtmp >= 0) {
     // unknown stall, do the expensive runtime check
-    assem_debug("; cop2_call_stall_check\n");
+    assem_debug("; cop2_do_stall_check\n");
 #if 0 // too slow
     save_regs(reglist);
     emit_movimm(gte_cycletab[op], 0);
@@ -3415,6 +3436,98 @@ static void cop2_call_stall_check(u_int op, int i, const struct regstat *i_regs,
   host_tempreg_release();
 }
 
+static int is_mflohi(int i)
+{
+  return (itype[i] == MOV && (rs1[i] == HIREG || rs1[i] == LOREG));
+}
+
+static int check_multdiv(int i, int *cycles)
+{
+  if (itype[i] != MULTDIV)
+    return 0;
+  if (opcode2[i] == 0x18 || opcode2[i] == 0x19) // MULT(U)
+    *cycles = 11; // approx from 7 11 14
+  else
+    *cycles = 37;
+  return 1;
+}
+
+static void multdiv_prepare_stall(int i, const struct regstat *i_regs)
+{
+  int j, found = 0, c = 0;
+  if (HACK_ENABLED(NDHACK_NO_STALLS))
+    return;
+  if (get_reg(i_regs->regmap, CCREG) != HOST_CCREG) {
+    // happens occasionally... cc evicted? Don't bother then
+    return;
+  }
+  for (j = i + 1; j < slen; j++) {
+    if (bt[j])
+      break;
+    if ((found = is_mflohi(j)))
+      break;
+    if (is_jump(j)) {
+      // check ds
+      if (j + 1 < slen && (found = is_mflohi(j + 1)))
+        j++;
+      break;
+    }
+  }
+  if (found)
+    // handle all in multdiv_do_stall()
+    return;
+  check_multdiv(i, &c);
+  assert(c > 0);
+  assem_debug("; muldiv prepare stall %d\n", c);
+  host_tempreg_acquire();
+  emit_addimm(HOST_CCREG, CLOCK_ADJUST(ccadj[i]) + c, HOST_TEMPREG);
+  emit_writeword(HOST_TEMPREG, &psxRegs.muldivBusyCycle);
+  host_tempreg_release();
+}
+
+static void multdiv_do_stall(int i, const struct regstat *i_regs)
+{
+  int j, known_cycles = 0;
+  u_int reglist = get_host_reglist(i_regs->regmap);
+  int rtmp = get_reg(i_regs->regmap, -1);
+  if (rtmp < 0)
+    rtmp = reglist_find_free(reglist);
+  if (HACK_ENABLED(NDHACK_NO_STALLS))
+    return;
+  if (get_reg(i_regs->regmap, CCREG) != HOST_CCREG || rtmp < 0) {
+    // happens occasionally... cc evicted? Don't bother then
+    //printf("no cc/rtmp %08x\n", start + i*4);
+    return;
+  }
+  if (!bt[i]) {
+    for (j = i - 1; j >= 0; j--) {
+      if (is_ds[j]) break;
+      if (check_multdiv(j, &known_cycles) || bt[j])
+        break;
+      if (is_mflohi(j))
+        // already handled by this op
+        return;
+    }
+    j = max(j, 0);
+  }
+  if (known_cycles > 0) {
+    known_cycles -= CLOCK_ADJUST(ccadj[i] - ccadj[j]);
+    assem_debug("; muldiv stall resolved %d\n", known_cycles);
+    if (known_cycles > 0)
+      emit_addimm(HOST_CCREG, known_cycles, HOST_CCREG);
+    return;
+  }
+  assem_debug("; muldiv stall unresolved\n");
+  host_tempreg_acquire();
+  emit_readword(&psxRegs.muldivBusyCycle, rtmp);
+  emit_addimm(rtmp, -CLOCK_ADJUST(ccadj[i]), rtmp);
+  emit_sub(rtmp, HOST_CCREG, HOST_TEMPREG);
+  emit_cmpimm(HOST_TEMPREG, 37);
+  emit_cmovb_reg(rtmp, HOST_CCREG);
+  //emit_log_gte_stall(i, 0, reglist);
+  host_tempreg_release();
+}
+
 static void cop2_get_dreg(u_int copr,signed char tl,signed char temp)
 {
   switch (copr) {
@@ -3532,8 +3645,9 @@ static void c2ls_assemble(int i, const struct regstat *i_regs)
   if (!offset&&!c&&s>=0) ar=s;
   assert(ar>=0);
 
+  cop2_do_stall_check(0, i, i_regs, reglist);
+
   if (opcode[i]==0x3a) { // SWC2
-    cop2_call_stall_check(0, i, i_regs, reglist_exclude(reglist, tl, -1));
     cop2_get_dreg(copr,tl,-1);
     type=STOREW_STUB;
   }
@@ -3600,12 +3714,13 @@ static void cop2_assemble(int i, const struct regstat *i_regs)
   u_int copr = (source[i]>>11) & 0x1f;
   signed char temp = get_reg(i_regs->regmap, -1);
 
-  if (opcode2[i] == 0 || opcode2[i] == 2) { // MFC2/CFC2
-    if (!HACK_ENABLED(NDHACK_GTE_NO_STALL)) {
+  if (!HACK_ENABLED(NDHACK_NO_STALLS)) {
+    u_int reglist = reglist_exclude(get_host_reglist(i_regs->regmap), temp, -1);
+    if (opcode2[i] == 0 || opcode2[i] == 2) { // MFC2/CFC2
       signed char tl = get_reg(i_regs->regmap, rt1[i]);
-      u_int reglist = reglist_exclude(get_host_reglist(i_regs->regmap), tl, temp);
-      cop2_call_stall_check(0, i, i_regs, reglist);
+      reglist = reglist_exclude(reglist, tl, -1);
     }
+    cop2_do_stall_check(0, i, i_regs, reglist);
   }
   if (opcode2[i]==0) { // MFC2
     signed char tl=get_reg(i_regs->regmap,rt1[i]);
@@ -3753,6 +3868,8 @@ static void mov_assemble(int i,struct regstat *i_regs)
       else emit_loadreg(rs1[i],tl);
     }
   }
+  if (rs1[i] == HIREG || rs1[i] == LOREG) // MFHI/MFLO
+    multdiv_do_stall(i, i_regs);
 }
 
 // call interpreter, exception handler, things that change pc/regs/cycles ...
@@ -3921,7 +4038,9 @@ static void ds_assemble(int i,struct regstat *i_regs)
     case C2OP:
       c2op_assemble(i,i_regs);break;
     case MULTDIV:
-      multdiv_assemble(i,i_regs);break;
+      multdiv_assemble(i,i_regs);
+      multdiv_prepare_stall(i,i_regs);
+      break;
     case MOV:
       mov_assemble(i,i_regs);break;
     case SYSCALL:
@@ -4577,7 +4696,9 @@ static void ds_assemble_entry(int i)
     case C2OP:
       c2op_assemble(t,&regs[t]);break;
     case MULTDIV:
-      multdiv_assemble(t,&regs[t]);break;
+      multdiv_assemble(t,&regs[t]);
+      multdiv_prepare_stall(i,&regs[t]);
+      break;
     case MOV:
       mov_assemble(t,&regs[t]);break;
     case SYSCALL:
@@ -5850,7 +5971,7 @@ static void pagespan_assemble(int i,struct regstat *i_regs)
   emit_extjump_ds(branch_addr, target_addr);
   if(compiled_target_addr) {
     set_jump_target(branch_addr, compiled_target_addr);
-    add_link(target_addr,stub);
+    add_jump_out(target_addr,stub);
   }
   else set_jump_target(branch_addr, stub);
   if(likely[i]) {
@@ -5865,7 +5986,7 @@ static void pagespan_assemble(int i,struct regstat *i_regs)
     emit_extjump_ds(branch_addr, target_addr);
     if(compiled_target_addr) {
       set_jump_target(branch_addr, compiled_target_addr);
-      add_link(target_addr,stub);
+      add_jump_out(target_addr,stub);
     }
     else set_jump_target(branch_addr, stub);
   }
@@ -5879,7 +6000,7 @@ static void pagespan_ds()
   u_int page=get_page(vaddr);
   u_int vpage=get_vpage(vaddr);
   ll_add(jump_dirty+vpage,vaddr,(void *)out);
-  do_dirty_stub_ds();
+  do_dirty_stub_ds(slen*4);
   ll_add(jump_in+page,vaddr,(void *)out);
   assert(regs[0].regmap_entry[HOST_CCREG]==CCREG);
   if(regs[0].regmap[HOST_CCREG]!=CCREG)
@@ -5921,7 +6042,9 @@ static void pagespan_ds()
     case C2OP:
       c2op_assemble(0,&regs[0]);break;
     case MULTDIV:
-      multdiv_assemble(0,&regs[0]);break;
+      multdiv_assemble(0,&regs[0]);
+      multdiv_prepare_stall(0,&regs[0]);
+      break;
     case MOV:
       mov_assemble(0,&regs[0]);break;
     case SYSCALL:
@@ -6731,6 +6854,9 @@ void new_dynarec_clear_full(void)
   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);
+
+  cycle_multiplier_old = cycle_multiplier;
+  new_dynarec_hacks_old = new_dynarec_hacks;
 }
 
 void new_dynarec_init(void)
@@ -8105,7 +8231,7 @@ int new_recompile_block(u_int addr)
       // this should really be removed since the real stalls have been implemented,
       // but doing so causes sizeable perf regression against the older version
       u_int gtec = gte_cycletab[source[i] & 0x3f];
-      cc += HACK_ENABLED(NDHACK_GTE_NO_STALL) ? gtec/2 : 2;
+      cc += HACK_ENABLED(NDHACK_NO_STALLS) ? gtec/2 : 2;
     }
     else if(i>1&&itype[i]==STORE&&itype[i-1]==STORE&&itype[i-2]==STORE&&!bt[i])
     {
@@ -8114,7 +8240,7 @@ int new_recompile_block(u_int addr)
     else if(itype[i]==C2LS)
     {
       // same as with C2OP
-      cc += HACK_ENABLED(NDHACK_GTE_NO_STALL) ? 4 : 2;
+      cc += HACK_ENABLED(NDHACK_NO_STALLS) ? 4 : 2;
     }
 #endif
     else
@@ -9094,7 +9220,9 @@ int new_recompile_block(u_int addr)
         case C2OP:
           c2op_assemble(i,&regs[i]);break;
         case MULTDIV:
-          multdiv_assemble(i,&regs[i]);break;
+          multdiv_assemble(i,&regs[i]);
+          multdiv_prepare_stall(i,&regs[i]);
+          break;
         case MOV:
           mov_assemble(i,&regs[i]);break;
         case SYSCALL:
@@ -9120,10 +9248,14 @@ int new_recompile_block(u_int addr)
         literal_pool_jumpover(256);
     }
   }
-  //assert(is_ujump(i-2));
+
+  assert(slen > 0);
+  if (itype[slen-1] == INTCALL) {
+    // no ending needed for this block since INTCALL never returns
+  }
   // If the block did not end with an unconditional branch,
   // add a jump to the next instruction.
-  if(i>1) {
+  else if (i > 1) {
     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);
@@ -9203,7 +9335,7 @@ int new_recompile_block(u_int addr)
       emit_extjump(link_addr[i].addr, link_addr[i].target);
       if (addr) {
         set_jump_target(link_addr[i].addr, addr);
-        add_link(link_addr[i].target,stub);
+        add_jump_out(link_addr[i].target,stub);
       }
       else
         set_jump_target(link_addr[i].addr, stub);
@@ -9221,8 +9353,17 @@ int new_recompile_block(u_int addr)
       //#endif
     }
   }
+
+  u_int source_len = slen*4;
+  if (itype[slen-1] == INTCALL && source_len > 4)
+    // no need to treat the last instruction as compiled
+    // as interpreter fully handles it
+    source_len -= 4;
+
+  if ((u_char *)copy + source_len > (u_char *)shadow + sizeof(shadow))
+    copy = shadow;
+
   // External Branch Targets (jump_in)
-  if(copy+slen*4>(void *)shadow+sizeof(shadow)) copy=shadow;
   for(i=0;i<slen;i++)
   {
     if(bt[i]||i==0)
@@ -9237,7 +9378,7 @@ int new_recompile_block(u_int addr)
           assem_debug("%p (%d) <- %8x\n",instr_addr[i],i,start+i*4);
           assem_debug("jump_in: %x\n",start+i*4);
           ll_add(jump_dirty+vpage,vaddr,out);
-          void *entry_point = do_dirty_stub(i);
+          void *entry_point = do_dirty_stub(i, source_len);
           ll_add_flags(jump_in+page,vaddr,state_rflags,entry_point);
           // If there was an existing entry in the hash table,
           // replace it with the new address.
@@ -9260,8 +9401,8 @@ int new_recompile_block(u_int addr)
   #endif
   assert(out - (u_char *)beginning < MAX_OUTPUT_BLOCK_SIZE);
   //printf("shadow buffer: %p-%p\n",copy,(u_char *)copy+slen*4);
-  memcpy(copy,source,slen*4);
-  copy+=slen*4;
+  memcpy(copy, source, source_len);
+  copy += source_len;
 
   end_block(beginning);
 
@@ -9289,34 +9430,37 @@ int new_recompile_block(u_int addr)
   while(expirep!=end)
   {
     int shift=TARGET_SIZE_2-3; // Divide into 8 blocks
-    uintptr_t base=(uintptr_t)ndrc->translation_cache+((expirep>>13)<<shift); // Base address of this block
+    uintptr_t base_offs = ((uintptr_t)(expirep >> 13) << shift); // Base offset of this block
+    uintptr_t base_offs_s = base_offs >> shift;
     inv_debug("EXP: Phase %d\n",expirep);
     switch((expirep>>11)&3)
     {
       case 0:
         // Clear jump_in and jump_dirty
-        ll_remove_matching_addrs(jump_in+(expirep&2047),base,shift);
-        ll_remove_matching_addrs(jump_dirty+(expirep&2047),base,shift);
-        ll_remove_matching_addrs(jump_in+2048+(expirep&2047),base,shift);
-        ll_remove_matching_addrs(jump_dirty+2048+(expirep&2047),base,shift);
+        ll_remove_matching_addrs(jump_in+(expirep&2047),base_offs_s,shift);
+        ll_remove_matching_addrs(jump_dirty+(expirep&2047),base_offs_s,shift);
+        ll_remove_matching_addrs(jump_in+2048+(expirep&2047),base_offs_s,shift);
+        ll_remove_matching_addrs(jump_dirty+2048+(expirep&2047),base_offs_s,shift);
         break;
       case 1:
         // Clear pointers
-        ll_kill_pointers(jump_out[expirep&2047],base,shift);
-        ll_kill_pointers(jump_out[(expirep&2047)+2048],base,shift);
+        ll_kill_pointers(jump_out[expirep&2047],base_offs_s,shift);
+        ll_kill_pointers(jump_out[(expirep&2047)+2048],base_offs_s,shift);
         break;
       case 2:
         // Clear hash table
         for(i=0;i<32;i++) {
           struct ht_entry *ht_bin = &hash_table[((expirep&2047)<<5)+i];
-          if (((uintptr_t)ht_bin->tcaddr[1]>>shift) == (base>>shift) ||
-             (((uintptr_t)ht_bin->tcaddr[1]-MAX_OUTPUT_BLOCK_SIZE)>>shift)==(base>>shift)) {
+          uintptr_t o1 = (u_char *)ht_bin->tcaddr[1] - ndrc->translation_cache;
+          uintptr_t o2 = o1 - MAX_OUTPUT_BLOCK_SIZE;
+          if ((o1 >> shift) == base_offs_s || (o2 >> shift) == base_offs_s) {
             inv_debug("EXP: Remove hash %x -> %p\n",ht_bin->vaddr[1],ht_bin->tcaddr[1]);
             ht_bin->vaddr[1] = -1;
             ht_bin->tcaddr[1] = NULL;
           }
-          if (((uintptr_t)ht_bin->tcaddr[0]>>shift) == (base>>shift) ||
-             (((uintptr_t)ht_bin->tcaddr[0]-MAX_OUTPUT_BLOCK_SIZE)>>shift)==(base>>shift)) {
+          o1 = (u_char *)ht_bin->tcaddr[0] - ndrc->translation_cache;
+          o2 = o1 - MAX_OUTPUT_BLOCK_SIZE;
+          if ((o1 >> shift) == base_offs_s || (o2 >> shift) == base_offs_s) {
             inv_debug("EXP: Remove hash %x -> %p\n",ht_bin->vaddr[0],ht_bin->tcaddr[0]);
             ht_bin->vaddr[0] = ht_bin->vaddr[1];
             ht_bin->tcaddr[0] = ht_bin->tcaddr[1];
@@ -9329,8 +9473,8 @@ int new_recompile_block(u_int addr)
         // Clear jump_out
         if((expirep&2047)==0)
           do_clear_cache();
-        ll_remove_matching_addrs(jump_out+(expirep&2047),base,shift);
-        ll_remove_matching_addrs(jump_out+2048+(expirep&2047),base,shift);
+        ll_remove_matching_addrs(jump_out+(expirep&2047),base_offs_s,shift);
+        ll_remove_matching_addrs(jump_out+2048+(expirep&2047),base_offs_s,shift);
         break;
     }
     expirep=(expirep+1)&65535;