summaryrefslogtreecommitdiff
path: root/target-arm
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2011-10-19 16:14:05 +0000
committerPeter Maydell <peter.maydell@linaro.org>2011-10-19 16:14:05 +0000
commit41e9564df650ddedbdab27283ebcb0173adf024f (patch)
treee8601b84e4c4ac508efaab6e2ba1cc3ed1e342ce /target-arm
parent26cc6abf61cc2bf68eaeb89b1497c12330e6b73c (diff)
target-arm: v6 media multiply space: UNDEF on unassigned encodings
Clean up the decoding of the v6 media multiply space so that we UNDEF on unassigned encodings rather than randomly interpreting them as some instruction in this space. Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target-arm')
-rw-r--r--target-arm/translate.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 75c0ad413a..e99fc183b4 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7569,11 +7569,16 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
}
break;
case 2: /* Multiplies (Type 3). */
- tmp = load_reg(s, rm);
- tmp2 = load_reg(s, rs);
- if (insn & (1 << 20)) {
+ switch ((insn >> 20) & 0x7) {
+ case 5:
+ if (((insn >> 6) ^ (insn >> 7)) & 1) {
+ /* op2 not 00x or 11x : UNDEF */
+ goto illegal_op;
+ }
/* Signed multiply most significant [accumulate].
(SMMUL, SMMLA, SMMLS) */
+ tmp = load_reg(s, rm);
+ tmp2 = load_reg(s, rs);
tmp64 = gen_muls_i64_i32(tmp, tmp2);
if (rd != 15) {
@@ -7592,7 +7597,15 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
tcg_gen_trunc_i64_i32(tmp, tmp64);
tcg_temp_free_i64(tmp64);
store_reg(s, rn, tmp);
- } else {
+ break;
+ case 0:
+ case 4:
+ /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
+ if (insn & (1 << 7)) {
+ goto illegal_op;
+ }
+ tmp = load_reg(s, rm);
+ tmp2 = load_reg(s, rs);
if (insn & (1 << 5))
gen_swap_half(tmp2);
gen_smul_dual(tmp, tmp2);
@@ -7625,6 +7638,9 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
}
store_reg(s, rn, tmp);
}
+ break;
+ default:
+ goto illegal_op;
}
break;
case 3: