Commit 32f70d76 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20170320' into staging



target-arm queue:
 * fix MSR/MRS decoding for M profile CPUs

# gpg: Signature made Mon 20 Mar 2017 12:53:26 GMT
# gpg:                using RSA key 0x3C2525ED14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>"
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20170320:
  arm: Fix APSR writes via M profile MSR
  arm: Enforce should-be-1 bits in MRS decoding
  arm: Don't decode MRS(banked) or MSR(banked) for M profile
  arm: HVC and SMC encodings don't exist for M profile

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 00e7c07b b28b3377
Loading
Loading
Loading
Loading
+22 −4
Original line number Diff line number Diff line
@@ -8548,8 +8548,18 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
    }
}

void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
{
    /* We're passed bits [11..0] of the instruction; extract
     * SYSm and the mask bits.
     * Invalid combinations of SYSm and mask are UNPREDICTABLE;
     * we choose to treat them as if the mask bits were valid.
     * NB that the pseudocode 'mask' variable is bits [11..10],
     * whereas ours is [11..8].
     */
    uint32_t mask = extract32(maskreg, 8, 4);
    uint32_t reg = extract32(maskreg, 0, 8);

    if (arm_current_el(env) == 0 && reg > 7) {
        /* only xPSR sub-fields may be written by unprivileged */
        return;
@@ -8558,8 +8568,16 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
    switch (reg) {
    case 0 ... 7: /* xPSR sub-fields */
        /* only APSR is actually writable */
        if (reg & 4) {
            xpsr_write(env, val, 0xf8000000); /* APSR */
        if (!(reg & 4)) {
            uint32_t apsrmask = 0;

            if (mask & 8) {
                apsrmask |= 0xf8000000; /* APSR NZCVQ */
            }
            if ((mask & 4) && arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
                apsrmask |= 0x000f0000; /* APSR GE[3:0] */
            }
            xpsr_write(env, val, apsrmask);
        }
        break;
    case 8: /* MSP */
+23 −3
Original line number Diff line number Diff line
@@ -10377,6 +10377,9 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                    goto illegal_op;

                if (insn & (1 << 26)) {
                    if (arm_dc_feature(s, ARM_FEATURE_M)) {
                        goto illegal_op;
                    }
                    if (!(insn & (1 << 20))) {
                        /* Hypervisor call (v7) */
                        int imm16 = extract32(insn, 16, 4) << 12
@@ -10400,7 +10403,8 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                    case 0: /* msr cpsr.  */
                        if (arm_dc_feature(s, ARM_FEATURE_M)) {
                            tmp = load_reg(s, rn);
                            addr = tcg_const_i32(insn & 0xff);
                            /* the constant is the mask and SYSm fields */
                            addr = tcg_const_i32(insn & 0xfff);
                            gen_helper_v7m_msr(cpu_env, addr, tmp);
                            tcg_temp_free_i32(addr);
                            tcg_temp_free_i32(tmp);
@@ -10497,7 +10501,8 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                        gen_exception_return(s, tmp);
                        break;
                    case 6: /* MRS */
                        if (extract32(insn, 5, 1)) {
                        if (extract32(insn, 5, 1) &&
                            !arm_dc_feature(s, ARM_FEATURE_M)) {
                            /* MRS (banked) */
                            int sysm = extract32(insn, 16, 4) |
                                (extract32(insn, 4, 1) << 4);
@@ -10506,6 +10511,14 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                            break;
                        }

                        if (extract32(insn, 16, 4) != 0xf) {
                            goto illegal_op;
                        }
                        if (!arm_dc_feature(s, ARM_FEATURE_M) &&
                            extract32(insn, 0, 8) != 0) {
                            goto illegal_op;
                        }

                        /* mrs cpsr */
                        tmp = tcg_temp_new_i32();
                        if (arm_dc_feature(s, ARM_FEATURE_M)) {
@@ -10518,7 +10531,8 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                        store_reg(s, rd, tmp);
                        break;
                    case 7: /* MRS */
                        if (extract32(insn, 5, 1)) {
                        if (extract32(insn, 5, 1) &&
                            !arm_dc_feature(s, ARM_FEATURE_M)) {
                            /* MRS (banked) */
                            int sysm = extract32(insn, 16, 4) |
                                (extract32(insn, 4, 1) << 4);
@@ -10532,6 +10546,12 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                        if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
                            goto illegal_op;
                        }

                        if (extract32(insn, 16, 4) != 0xf ||
                            extract32(insn, 0, 8) != 0) {
                            goto illegal_op;
                        }

                        tmp = load_cpu_field(spsr);
                        store_reg(s, rd, tmp);
                        break;