drc: merge Ari64's patch: 14_dont_save_or_restore_temporary
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / assem_arm.c
index 4d4d700..2b0ef9c 100644 (file)
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus - assem_arm.c                                             *
- *   Copyright (C) 2009-2010 Ari64                                         *
+ *   Copyright (C) 2009-2011 Ari64                                         *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
@@ -845,7 +845,8 @@ u_int rd_rn_imm_shift(u_int rd, u_int rn, u_int imm, u_int shift)
 }
 u_int genimm(u_int imm,u_int *encoded)
 {
-  if(imm==0) {*encoded=0;return 1;}
+  *encoded=0;
+  if(imm==0) return 1;
   int i=32;
   while(i>0)
   {
@@ -1002,7 +1003,8 @@ void emit_loadreg(int r, int hr)
 #ifdef FORCE32
   if(r&64) {
     printf("64bit load in 32bit mode!\n");
-    exit(1);
+    assert(0);
+    return;
   }
 #endif
   if((r&63)==0)
@@ -1026,7 +1028,8 @@ void emit_storereg(int r, int hr)
 #ifdef FORCE32
   if(r&64) {
     printf("64bit store in 32bit mode!\n");
-    exit(1);
+    assert(0);
+    return;
   }
 #endif
   int addr=((int)reg)+((r&63)<<REG_SHIFT)+((r&64)>>4);
@@ -2736,6 +2739,18 @@ inline_readstub(int type, int i, u_int addr, signed char regmap[], int target, i
   emit_writeword(rs,(int)&address);
   //emit_pusha();
   save_regs(reglist);
+#ifndef PCSX
+  if((signed int)addr>=(signed int)0xC0000000) {
+    // Theoretically we can have a pagefault here, if the TLB has never
+    // been enabled and the address is outside the range 80000000..BFFFFFFF
+    // Write out the registers so the pagefault can be handled.  This is
+    // a very rare case and likely represents a bug.
+    int ds=regmap!=regs[i].regmap;
+    if(!ds) load_all_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty,i);
+    if(!ds) wb_dirtys(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty);
+    else wb_dirtys(branch_regs[i-1].regmap_entry,branch_regs[i-1].was32,branch_regs[i-1].wasdirty);
+  }
+#endif
   //emit_shrimm(rs,16,1);
   int cc=get_reg(regmap,CCREG);
   if(cc<0) {
@@ -2926,6 +2941,19 @@ inline_writestub(int type, int i, u_int addr, signed char regmap[], int target,
   }
   //emit_pusha();
   save_regs(reglist);
+#ifndef PCSX
+  // rearmed note: load_all_consts prevents BIOS boot, some bug?
+  if((signed int)addr>=(signed int)0xC0000000) {
+    // Theoretically we can have a pagefault here, if the TLB has never
+    // been enabled and the address is outside the range 80000000..BFFFFFFF
+    // Write out the registers so the pagefault can be handled.  This is
+    // a very rare case and likely represents a bug.
+    int ds=regmap!=regs[i].regmap;
+    if(!ds) load_all_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty,i);
+    if(!ds) wb_dirtys(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty);
+    else wb_dirtys(branch_regs[i-1].regmap_entry,branch_regs[i-1].was32,branch_regs[i-1].wasdirty);
+  }
+#endif
   //emit_shrimm(rs,16,1);
   int cc=get_reg(regmap,CCREG);
   if(cc<0) {
@@ -3385,6 +3413,7 @@ void loadlr_assemble_arm(int i,struct regstat *i_regs)
     }
     map=get_reg(i_regs->regmap,TLREG);
     assert(map>=0);
+    reglist&=~(1<<map);
     map=do_tlb_r(addr,temp2,map,0,a,c?-1:temp,c,constmap[i][s]+offset);
     if(c) {
       if (opcode[i]==0x22||opcode[i]==0x26) {