qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] Fix modulus result from MIPS DDIV & avoid overflowi


From: Richard Sandiford
Subject: [Qemu-devel] [PATCH] Fix modulus result from MIPS DDIV & avoid overflowing division
Date: Sun, 25 May 2008 11:00:10 +0100
User-agent: Gnus/5.110006 (No Gnus v0.6) Emacs/22.1 (gnu/linux)

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


Index: qemu/target-mips/translate.c
===================================================================
--- qemu.orig/target-mips/translate.c   2008-05-25 09:57:00.000000000 +0100
+++ qemu/target-mips/translate.c        2008-05-25 09:57:08.000000000 +0100
@@ -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);
         }





reply via email to

[Prev in Thread] Current Thread [Next in Thread]