diff options
author | Igor V. Kovalenko <igor.v.kovalenko@gmail.com> | 2010-06-02 00:12:58 +0400 |
---|---|---|
committer | Blue Swirl <blauwirbel@gmail.com> | 2010-06-02 20:08:44 +0000 |
commit | fb170183e7387ade9aef2bddd59a8a62fceedac6 (patch) | |
tree | c199733945d474ebb16bb29718bc9a74e7a2f011 | |
parent | 09487205bb03548d260300d32595ba17ab597337 (diff) |
sparc64: fix umul and smul insns
- truncate and sign or zero extend operands before multiplication
- factor out common code to gen_op_multiply() with parameter to sign/zero extend
- call gen_op_multiply from gen_op_umul and gen_op_smul
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
-rw-r--r-- | target-sparc/translate.c | 55 |
1 files changed, 29 insertions, 26 deletions
diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 0bc1a82706..23f95191ad 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -662,50 +662,53 @@ static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2) tcg_gen_mov_tl(dst, cpu_cc_dst); } -static inline void gen_op_umul(TCGv dst, TCGv src1, TCGv src2) +static inline void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext) { + TCGv_i32 r_src1, r_src2; TCGv_i64 r_temp, r_temp2; + r_src1 = tcg_temp_new_i32(); + r_src2 = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(r_src1, src1); + tcg_gen_trunc_tl_i32(r_src2, src2); + r_temp = tcg_temp_new_i64(); r_temp2 = tcg_temp_new_i64(); - tcg_gen_extu_tl_i64(r_temp, src2); - tcg_gen_extu_tl_i64(r_temp2, src1); + if (sign_ext) { + tcg_gen_ext_i32_i64(r_temp, r_src2); + tcg_gen_ext_i32_i64(r_temp2, r_src1); + } else { + tcg_gen_extu_i32_i64(r_temp, r_src2); + tcg_gen_extu_i32_i64(r_temp2, r_src1); + } + tcg_gen_mul_i64(r_temp2, r_temp, r_temp2); tcg_gen_shri_i64(r_temp, r_temp2, 32); tcg_gen_trunc_i64_tl(cpu_tmp0, r_temp); tcg_temp_free_i64(r_temp); tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff); -#ifdef TARGET_SPARC64 - tcg_gen_mov_i64(dst, r_temp2); -#else + tcg_gen_trunc_i64_tl(dst, r_temp2); -#endif + tcg_temp_free_i64(r_temp2); + + tcg_temp_free_i32(r_src1); + tcg_temp_free_i32(r_src2); } -static inline void gen_op_smul(TCGv dst, TCGv src1, TCGv src2) +static inline void gen_op_umul(TCGv dst, TCGv src1, TCGv src2) { - TCGv_i64 r_temp, r_temp2; - - r_temp = tcg_temp_new_i64(); - r_temp2 = tcg_temp_new_i64(); - - tcg_gen_ext_tl_i64(r_temp, src2); - tcg_gen_ext_tl_i64(r_temp2, src1); - tcg_gen_mul_i64(r_temp2, r_temp, r_temp2); + /* zero-extend truncated operands before multiplication */ + gen_op_multiply(dst, src1, src2, 0); +} - tcg_gen_shri_i64(r_temp, r_temp2, 32); - tcg_gen_trunc_i64_tl(cpu_tmp0, r_temp); - tcg_temp_free_i64(r_temp); - tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff); -#ifdef TARGET_SPARC64 - tcg_gen_mov_i64(dst, r_temp2); -#else - tcg_gen_trunc_i64_tl(dst, r_temp2); -#endif - tcg_temp_free_i64(r_temp2); +static inline void gen_op_smul(TCGv dst, TCGv src1, TCGv src2) +{ + /* sign-extend truncated operands before multiplication */ + gen_op_multiply(dst, src1, src2, 1); } #ifdef TARGET_SPARC64 |