diff options
author | balrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-07-19 10:12:22 +0000 |
---|---|---|
committer | balrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-07-19 10:12:22 +0000 |
commit | 22478e79f2793aa1bc7a5019ae2e48303573e0d5 (patch) | |
tree | a736478a7d1cb9670b44dfc9f6015127dc0bbfe4 /target-arm/translate.c | |
parent | f617a9a6bb3b66e93d30f57e966f425e58cef8bc (diff) | |
download | hqemu-22478e79f2793aa1bc7a5019ae2e48303573e0d5.zip hqemu-22478e79f2793aa1bc7a5019ae2e48303573e0d5.tar.gz |
Fix smlald, smlsld, pkhtp, pkhbt, ssat, usat, umul, smul... (Laurent Desnogues).
helper.c
- copy reference c0_c2 to runtime c0_c2 and not c0_c1
op_helper.c
- remove old code (PARAM1, probably some left over from old dyngen)
that broke do_[us]sat
translate.c
- gen_smul_dual should sign-extend from 16 bit to 32 bit and not from
8 to 32
- disas_arm_insn:
* smlalxy: that was completely wrong; now the addition is
performed as for smlald
* pkhtb: optional ASR not taken into account (similar
* to [us]sat)
* pkhtb/pkhbt: tmp2 is dead
* smlald, smlsld, smuad, smusd, smlad, smlsd: rd
* and rn swapped
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4898 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-arm/translate.c')
-rw-r--r-- | target-arm/translate.c | 31 |
1 files changed, 18 insertions, 13 deletions
diff --git a/target-arm/translate.c b/target-arm/translate.c index 3183ef8..8e3e169 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -250,8 +250,8 @@ static void gen_smul_dual(TCGv a, TCGv b) { TCGv tmp1 = new_tmp(); TCGv tmp2 = new_tmp(); - tcg_gen_ext8s_i32(tmp1, a); - tcg_gen_ext8s_i32(tmp2, b); + tcg_gen_ext16s_i32(tmp1, a); + tcg_gen_ext16s_i32(tmp2, b); tcg_gen_mul_i32(tmp1, tmp1, tmp2); dead_tmp(tmp2); tcg_gen_sari_i32(a, a, 16); @@ -5998,10 +5998,11 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) gen_mulxy(tmp, tmp2, sh & 2, sh & 4); dead_tmp(tmp2); if (op1 == 2) { - tmp = tcg_temp_new(TCG_TYPE_I64); - tcg_gen_ext_i32_i64(tmp, cpu_T[0]); - gen_addq(s, tmp, rn, rd); - gen_storeq_reg(s, rn, rd, tmp); + tmp2 = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_ext_i32_i64(tmp2, tmp); + dead_tmp(tmp); + gen_addq(s, tmp2, rn, rd); + gen_storeq_reg(s, rn, rd, tmp2); } else { if (op1 == 0) { tmp2 = load_reg(s, rn); @@ -6372,18 +6373,22 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) tmp = load_reg(s, rn); tmp2 = load_reg(s, rm); shift = (insn >> 7) & 0x1f; - if (shift) - tcg_gen_shli_i32(tmp2, tmp2, shift); if (insn & (1 << 6)) { /* pkhtb */ + if (shift == 0) + shift = 31; + tcg_gen_sari_i32(tmp2, tmp2, shift); tcg_gen_andi_i32(tmp, tmp, 0xffff0000); tcg_gen_ext16u_i32(tmp2, tmp2); } else { /* pkhbt */ + if (shift) + tcg_gen_shli_i32(tmp2, tmp2, shift); tcg_gen_ext16u_i32(tmp, tmp); tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000); } tcg_gen_or_i32(tmp, tmp, tmp2); + dead_tmp(tmp2); store_reg(s, rd, tmp); } else if ((insn & 0x00200020) == 0x00200000) { /* [us]sat */ @@ -6510,17 +6515,17 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) tmp2 = tcg_temp_new(TCG_TYPE_I64); tcg_gen_ext_i32_i64(tmp2, tmp); dead_tmp(tmp); - gen_addq(s, tmp2, rn, rd); - gen_storeq_reg(s, rn, rd, tmp2); + gen_addq(s, tmp2, rd, rn); + gen_storeq_reg(s, rd, rn, tmp2); } else { /* smuad, smusd, smlad, smlsd */ - if (rn != 15) + if (rd != 15) { - tmp2 = load_reg(s, rn); + tmp2 = load_reg(s, rd); gen_helper_add_setq(tmp, tmp, tmp2); dead_tmp(tmp2); } - store_reg(s, rd, tmp); + store_reg(s, rn, tmp); } } break; |