diff options
Diffstat (limited to 'target-arm/translate.c')
-rw-r--r-- | target-arm/translate.c | 18 |
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 */ |