Fix modulus result from MIPS DDIV & avoid overflowing division
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
@@ -2047,20 +2047,25 @@ static void gen_muldiv (DisasContext *cttcg_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); }