diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2013-12-01 10:58:41 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2013-12-01 14:33:36 +0000 |
commit | 2a5f4f44de31e012f031218cc922a4d846a062d9 (patch) | |
tree | 9470cbd7ac73d57c53d013dfbbb79a0be89cb64f | |
parent | b92eba378c182b3b31bc0a106d28bc0a22022f1e (diff) |
BUGFIX add_sub_ext_reg
handle_add_sub_ext_reg is also broken (most notably it can't
correctly handle a simple "sub sp, x1, x0"). Replace with an
implementation that just does a TCG subtract for a nonflags
subtract, etc.
-rw-r--r-- | target-arm/translate-a64.c | 35 |
1 files changed, 18 insertions, 17 deletions
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 07bfc85254..eeca877c2f 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -2353,7 +2353,7 @@ static void handle_add_sub_ext_reg(DisasContext *s, uint32_t insn) TCGv_i64 tcg_rm_ext = tcg_temp_new_i64(); TCGv_i64 tcg_rd; TCGv_i64 tcg_rn; - TCGv_i64 carry_in; + TCGv_i64 tcg_result; /* non-flag setting ops may use SP */ if (!setflags) { @@ -2367,30 +2367,31 @@ static void handle_add_sub_ext_reg(DisasContext *s, uint32_t insn) ext_and_shift_reg(tcg_rm_ext, tcg_rm, option, imm3); - if (!sf) { - tcg_gen_ext32s_i64(tcg_rm_ext, tcg_rm_ext); // superflous? - tcg_gen_ext32s_i64(tcg_rn, tcg_rn); - } + tcg_result = tcg_temp_new_i64(); - if (sub_op) { - tcg_gen_not_i64(tcg_rm, tcg_rm); - carry_in = tcg_const_i64(1); + if (!setflags) { + if (sub_op) { + tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm_ext); + } else { + tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm_ext); + } } else { - carry_in = tcg_const_i64(0); - } - - tcg_gen_add_i64(tcg_rd, tcg_rn, tcg_rm_ext); - if (setflags) { - gen_arith_CC(sf, tcg_rd, tcg_rn, tcg_rm, carry_in); + if (sub_op) { + gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm_ext); + } else { + gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm_ext); + } } - if (!sf) { - tcg_gen_ext32u_i64(tcg_rd, tcg_rd); + if (sf) { + tcg_gen_mov_i64(tcg_rd, tcg_result); + } else { + tcg_gen_ext32u_i64(tcg_rd, tcg_result); } + tcg_temp_free_i64(tcg_result); tcg_temp_free_i64(tcg_rm_ext); tcg_temp_free_i64(tcg_rn); - tcg_temp_free_i64(carry_in); } /* C3.5.2 Add/subtract (shifted register) |