drc: update some logging and patches
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / new_dynarec.c
index d369b81..b160a4a 100644 (file)
@@ -179,7 +179,8 @@ struct block_info
   u_int tc_offs;
   //u_int tc_len;
   u_int reg_sv_flags;
-  u_short is_dirty;
+  u_char is_dirty;
+  u_char inv_near_misses;
   u_short jump_in_cnt;
   struct {
     u_int vaddr;
@@ -602,9 +603,9 @@ static void hash_table_remove(int vaddr)
 
 static void mark_invalid_code(u_int vaddr, u_int len, char invalid)
 {
+  u_int vaddr_m = vaddr & 0x1fffffff;
   u_int i, j;
-  vaddr &= 0x1fffffff;
-  for (i = vaddr & ~0xfff; i < vaddr + len; i += 0x1000) {
+  for (i = vaddr_m & ~0xfff; i < vaddr_m + len; i += 0x1000) {
     // ram mirrors, but should not hurt bios
     for (j = 0; j < 0x800000; j += 0x200000) {
       invalid_code[(i|j) >> 12] =
@@ -645,7 +646,7 @@ static void *try_restore_block(u_int vaddr, u_int start_page, u_int end_page)
       if (memcmp(block->source, block->copy, block->len))
         continue;
 
-      block->is_dirty = 0;
+      block->is_dirty = block->inv_near_misses = 0;
       found_clean = block->jump_in[i].addr;
       hash_table_add(vaddr, found_clean);
       mark_invalid_code(block->start, block->len, 0);
@@ -1347,10 +1348,11 @@ static void invalidate_block(struct block_info *block)
 static int invalidate_range(u_int start, u_int end,
   u32 *inv_start_ret, u32 *inv_end_ret)
 {
+  struct block_info *last_block = NULL;
   u_int start_page = get_page_prev(start);
   u_int end_page = get_page(end - 1);
   u_int start_m = pmmask(start);
-  u_int end_m = pmmask(end);
+  u_int end_m = pmmask(end - 1);
   u_int inv_start, inv_end;
   u_int blk_start_m, blk_end_m;
   u_int page;
@@ -1366,6 +1368,7 @@ static int invalidate_range(u_int start, u_int end,
     for (block = blocks[page]; block != NULL; block = block->next) {
       if (block->is_dirty)
         continue;
+      last_block = block;
       blk_end_m = pmmask(block->start + block->len);
       if (blk_end_m <= start_m) {
         inv_start = max(inv_start, blk_end_m);
@@ -1385,12 +1388,22 @@ static int invalidate_range(u_int start, u_int end,
     }
   }
 
+  if (!hit && last_block && last_block->source) {
+    // could be some leftover unused block, uselessly trapping writes
+    last_block->inv_near_misses++;
+    if (last_block->inv_near_misses > 128) {
+      invalidate_block(last_block);
+      stat_inc(stat_inv_hits);
+      hit++;
+    }
+  }
   if (hit) {
     do_clear_cache();
 #ifdef USE_MINI_HT
     memset(mini_ht, -1, sizeof(mini_ht));
 #endif
   }
+
   if (inv_start <= (start_m & ~0xfff) && inv_end >= (start_m | 0xfff))
     // the whole page is empty now
     mark_invalid_code(start, 1, 1);
@@ -2061,7 +2074,7 @@ static void cop0_alloc(struct regstat *current,int i)
   }
   else
   {
-    // TLBR/TLBWI/TLBWR/TLBP/ERET
+    // RFE
     assert(dops[i].opcode2==0x10);
     alloc_all(current,i);
   }
@@ -5311,7 +5324,7 @@ static void rjump_assemble(int i, const struct regstat *i_regs)
   //assert(adj==0);
   emit_addimm_and_set_flags(ccadj[i] + CLOCK_ADJUST(2), HOST_CCREG);
   add_stub(CC_STUB,out,NULL,0,i,-1,TAKEN,rs);
-  if(dops[i+1].itype==COP0&&(source[i+1]&0x3f)==0x10)
+  if(dops[i+1].itype==COP0 && dops[i+1].opcode2==0x10)
     // special case for RFE
     emit_jmp(0);
   else
@@ -7013,9 +7026,9 @@ static noinline void pass2_unneeded_regs(int istart,int iend,int r)
       // SYSCALL instruction (software interrupt)
       u=1;
     }
-    else if(dops[i].itype==COP0 && (source[i]&0x3f)==0x18)
+    else if(dops[i].itype==COP0 && dops[i].opcode2==0x10)
     {
-      // ERET instruction (return from interrupt)
+      // RFE
       u=1;
     }
     //u=1; // DEBUG
@@ -8758,7 +8771,7 @@ static noinline void pass10_expire_blocks(void)
     u_int phase = (expirep >> (base_shift - 1)) & 1u;
     if (!(expirep & (MAX_OUTPUT_BLOCK_SIZE / 2 - 1))) {
       inv_debug("EXP: base_offs %x/%x phase %u\n", base_offs,
-        out - ndrc->translation_cache phase);
+        out - ndrc->translation_cache, phase);
     }
 
     if (!phase) {
@@ -8793,6 +8806,7 @@ static struct block_info *new_block_info(u_int start, u_int len,
   block->tc_offs = beginning - ndrc->translation_cache;
   //block->tc_len = out - beginning;
   block->is_dirty = 0;
+  block->inv_near_misses = 0;
   block->jump_in_cnt = jump_in_count;
 
   // insert sorted by start mirror-unmasked vaddr