drc: handle division by 0 correctly
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / assem_arm.c
index af45ce3..0c668d3 100644 (file)
@@ -1057,7 +1057,7 @@ void emit_test(int rs, int rt)
 void emit_testimm(int rs,int imm)
 {
   u_int armval;
-  assem_debug("tst %s,$%d\n",regname[rs],imm);
+  assem_debug("tst %s,#%d\n",regname[rs],imm);
   genimm_checked(imm,&armval);
   output_w32(0xe3100000|rd_rn_rm(0,rs,0)|armval);
 }
@@ -1450,10 +1450,10 @@ void emit_cmpimm(int rs,int imm)
 {
   u_int armval;
   if(genimm(imm,&armval)) {
-    assem_debug("cmp %s,$%d\n",regname[rs],imm);
+    assem_debug("cmp %s,#%d\n",regname[rs],imm);
     output_w32(0xe3500000|rd_rn_rm(0,rs,0)|armval);
   }else if(genimm(-imm,&armval)) {
-    assem_debug("cmn %s,$%d\n",regname[rs],imm);
+    assem_debug("cmn %s,#%d\n",regname[rs],imm);
     output_w32(0xe3700000|rd_rn_rm(0,rs,0)|armval);
   }else if(imm>0) {
     assert(imm<65536);
@@ -4493,7 +4493,9 @@ void multdiv_assemble_arm(int i,struct regstat *i_regs)
         assert(quotient>=0);
         assert(remainder>=0);
         emit_movs(d1,remainder);
-        emit_negmi(remainder,remainder);
+        emit_movimm(0xffffffff,quotient);
+        emit_negmi(quotient,quotient); // .. quotient and ..
+        emit_negmi(remainder,remainder); // .. remainder for div0 case (will be negated back after jump)
         emit_movs(d2,HOST_TEMPREG);
         emit_jeq((int)out+52); // Division by zero
         emit_negmi(HOST_TEMPREG,HOST_TEMPREG);
@@ -4521,12 +4523,13 @@ void multdiv_assemble_arm(int i,struct regstat *i_regs)
         signed char remainder=get_reg(i_regs->regmap,HIREG);
         assert(quotient>=0);
         assert(remainder>=0);
+        emit_mov(d1,remainder);
+        emit_movimm(0xffffffff,quotient); // div0 case
         emit_test(d2,d2);
-        emit_jeq((int)out+44); // Division by zero
+        emit_jeq((int)out+40); // Division by zero
         emit_clz(d2,HOST_TEMPREG);
         emit_movimm(1<<31,quotient);
         emit_shl(d2,HOST_TEMPREG,d2);
-        emit_mov(d1,remainder);
         emit_shr(quotient,HOST_TEMPREG,quotient);
         emit_cmp(remainder,d2);
         emit_subcs(remainder,d2,remainder);