]> git.proxmox.com Git - mirror_qemu.git/commitdiff
target-arm: v6 media multiply space: UNDEF on unassigned encodings
authorPeter Maydell <peter.maydell@linaro.org>
Wed, 19 Oct 2011 16:14:05 +0000 (16:14 +0000)
committerPeter Maydell <peter.maydell@linaro.org>
Wed, 19 Oct 2011 16:14:05 +0000 (16:14 +0000)
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>
target-arm/translate.c

index 75c0ad413a4b909f67ad7b2c9c8f6abe92fdd49d..e99fc183b43a461848110c1b3b67ea5952908a4c 100644 (file)
@@ -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: