aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Lyon <christophe.lyon@st.com>2011-01-19 15:37:58 +0100
committerAurelien Jarno <aurelien@aurel32.net>2011-01-26 14:30:24 +0100
commitc6067f04c5bb40547f79b5c02b1cdef043b39c5f (patch)
tree3de4d03d3c2fc243a4dcb89a07cfb9e5b41b4dd3
parent40d3c433606530ee1bb46ce95a6ca1cf2ee9d9c7 (diff)
target-arm: Fix garbage collection of temporaries in Neon emulation.
Fix garbage collection of temporaries in Neon emulation. Signed-off-by: Christophe Lyon <christophe.lyon@st.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
-rw-r--r--target-arm/translate.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/target-arm/translate.c b/target-arm/translate.c
index f445c87110..41cbb96ab0 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4183,6 +4183,13 @@ static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
break;
default: abort();
}
+
+ /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
+ Don't forget to clean them now. */
+ if (size < 2) {
+ dead_tmp(a);
+ dead_tmp(b);
+ }
}
/* Translate a NEON data processing instruction. Return nonzero if the
@@ -4847,7 +4854,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
if (size == 3) {
tcg_temp_free_i64(tmp64);
} else {
- dead_tmp(tmp2);
+ tcg_temp_free_i32(tmp2);
}
} else if (op == 10) {
/* VSHLL */
@@ -5083,8 +5090,6 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
case 8: case 9: case 10: case 11: case 12: case 13:
/* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
- dead_tmp(tmp2);
- dead_tmp(tmp);
break;
case 14: /* Polynomial VMULL */
cpu_abort(env, "Polynomial VMULL not implemented");
@@ -5235,6 +5240,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
return 1;
tmp2 = neon_get_scalar(size, rm);
+ /* We need a copy of tmp2 because gen_neon_mull
+ * deletes it during pass 0. */
+ tmp4 = new_tmp();
+ tcg_gen_mov_i32(tmp4, tmp2);
tmp3 = neon_load_reg(rn, 1);
for (pass = 0; pass < 2; pass++) {
@@ -5242,9 +5251,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
tmp = neon_load_reg(rn, 0);
} else {
tmp = tmp3;
+ tmp2 = tmp4;
}
gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
- dead_tmp(tmp);
if (op == 6 || op == 7) {
gen_neon_negl(cpu_V0, size);
}
@@ -5271,7 +5280,6 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
neon_store_reg64(cpu_V0, rd + pass);
}
- dead_tmp(tmp2);
break;
default: /* 14 and 15 are RESERVED */