Skip to contentSkip to conversation

Fix modulus result from MIPS DDIV & avoid overflowing division

PATCH New Richard Sandiford 1 participant 1 message May 25, 2008

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Fix modulus result from MIPS DDIV & avoid overflowing division

The MIPS DDIV code assigns the division result to cpu_T[0] before the remainder code has read the dividend. Fixed by using the same sort of construct as DDIVU, which doesn't have this problem.

Also, the code checks for overflowing division cases, but it doesn't avoid doing the division itself; it only avoids doing the remainder. We don't really need to do anything, because the dividend is also the quotient.

Richard

target-mips/translate.c +15 -10
Index: qemu/target-mips/translate.c
===================================================================
@@ -2047,20 +2047,25 @@ static void gen_muldiv (DisasContext *ct
             tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_T[1], 0, l1);
             {
                 int l2 = gen_new_label();
-                int l3 = gen_new_label();
 
                 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[0], 1ULL << 63, l2);
                 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_T[1], -1ULL, l2);
-                tcg_gen_div_i64(cpu_T[0], cpu_T[0], cpu_T[1]);
-                tcg_gen_movi_tl(cpu_T[1], 0);
-                tcg_gen_br(l3);
+                {
+                    tcg_gen_movi_tl(cpu_T[1], 0);
+                    gen_store_LO(cpu_T[0], 0);
+                    gen_store_HI(cpu_T[1], 0);
+                    tcg_gen_br(l1);
+                }
                 gen_set_label(l2);
-                tcg_gen_div_i64(cpu_T[0], cpu_T[0], cpu_T[1]);
-                tcg_gen_rem_i64(cpu_T[1], cpu_T[0], cpu_T[1]);
-                gen_set_label(l3);
-
-                gen_store_LO(cpu_T[0], 0);
-                gen_store_HI(cpu_T[1], 0);
+                {
+                    TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
+                    TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
+
+                    tcg_gen_div_i64(r_tmp1, cpu_T[0], cpu_T[1]);
+                    tcg_gen_rem_i64(r_tmp2, cpu_T[0], cpu_T[1]);
+                    gen_store_LO(r_tmp1, 0);
+                    gen_store_HI(r_tmp2, 0);
+                }
             }
             gen_set_label(l1);
         }