drc: add a timing hack for Internal Section
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / new_dynarec.c
index ef9bec7..4e09592 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];
@@ -440,11 +442,14 @@ static void do_clear_cache(void)
 #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;
 }
 
 static u_int get_page(u_int vaddr)
@@ -592,7 +597,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;
@@ -604,7 +609,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;
@@ -615,7 +620,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;
@@ -627,7 +632,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;
@@ -1717,7 +1723,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]);
 }
@@ -2157,10 +2163,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
@@ -4321,9 +4328,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);
@@ -4332,6 +4354,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)
@@ -4458,11 +4481,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);
@@ -6609,16 +6634,25 @@ void new_dynarec_cleanup(void)
 
 static u_int *get_source_start(u_int addr, u_int *limit)
 {
+  if (!(new_dynarec_hacks & 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 (!(new_dynarec_hacks & NDHACK_OVERRIDE_CYCLE_M))
+      cycle_multiplier_override = 200;
+
     *limit = (addr & 0xfff00000) | 0x80000;
     return (u_int *)((u_char *)psxR + (addr&0x7ffff));
   }
@@ -7696,7 +7730,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));
@@ -7717,7 +7751,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
@@ -7744,7 +7778,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
@@ -7769,7 +7803,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
@@ -7823,7 +7857,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
@@ -7920,7 +7954,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) {