target-arm: Decode SETEND correctly in Thumb
authorPeter Maydell <peter.maydell@linaro.org>
Wed, 14 Mar 2012 12:26:11 +0000 (12:26 +0000)
committerPeter Maydell <peter.maydell@linaro.org>
Thu, 15 Mar 2012 17:00:55 +0000 (17:00 +0000)
Decode the SETEND instruction correctly in Thumb mode,
rather than accidentally treating it like CPS. We don't
support BE8 mode, but this change brings the Thumb mode
in to line with behaviour in ARM mode: 'SETEND BE' is
not supported and will provoke an UNDEF exception, but
'SETEND LE' is correctly handled as a no-op.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reported-by: Daniel Forsgren <daniel.forsgren@enea.com>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
target-arm/translate.c

index 2709010f4a650b57b46edba725eefbc944547db7..81725d1687ecc979ca4c8d4f4517bd6406bdd171 100644 (file)
@@ -9704,32 +9704,49 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
             store_reg(s, rd, tmp);
             break;
 
-        case 6: /* cps */
-            ARCH(6);
-            if (IS_USER(s))
+        case 6:
+            switch ((insn >> 5) & 7) {
+            case 2:
+                /* setend */
+                ARCH(6);
+                if (insn & (1 << 3)) {
+                    /* BE8 mode not implemented.  */
+                    goto illegal_op;
+                }
                 break;
-            if (IS_M(env)) {
-                tmp = tcg_const_i32((insn & (1 << 4)) != 0);
-                /* FAULTMASK */
-                if (insn & 1) {
-                    addr = tcg_const_i32(19);
-                    gen_helper_v7m_msr(cpu_env, addr, tmp);
-                    tcg_temp_free_i32(addr);
+            case 3:
+                /* cps */
+                ARCH(6);
+                if (IS_USER(s)) {
+                    break;
                 }
-                /* PRIMASK */
-                if (insn & 2) {
-                    addr = tcg_const_i32(16);
-                    gen_helper_v7m_msr(cpu_env, addr, tmp);
-                    tcg_temp_free_i32(addr);
+                if (IS_M(env)) {
+                    tmp = tcg_const_i32((insn & (1 << 4)) != 0);
+                    /* FAULTMASK */
+                    if (insn & 1) {
+                        addr = tcg_const_i32(19);
+                        gen_helper_v7m_msr(cpu_env, addr, tmp);
+                        tcg_temp_free_i32(addr);
+                    }
+                    /* PRIMASK */
+                    if (insn & 2) {
+                        addr = tcg_const_i32(16);
+                        gen_helper_v7m_msr(cpu_env, addr, tmp);
+                        tcg_temp_free_i32(addr);
+                    }
+                    tcg_temp_free_i32(tmp);
+                    gen_lookup_tb(s);
+                } else {
+                    if (insn & (1 << 4)) {
+                        shift = CPSR_A | CPSR_I | CPSR_F;
+                    } else {
+                        shift = 0;
+                    }
+                    gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
                 }
-                tcg_temp_free_i32(tmp);
-                gen_lookup_tb(s);
-            } else {
-                if (insn & (1 << 4))
-                    shift = CPSR_A | CPSR_I | CPSR_F;
-                else
-                    shift = 0;
-                gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
+                break;
+            default:
+                goto undef;
             }
             break;