Commit ef11bc3c authored by Richard Henderson's avatar Richard Henderson Committed by Peter Maydell
Browse files

target/arm: Convert ERET



Pass the T5 encoding of SUBS PC, LR, #IMM through the normal SUBS path
to make it clear exactly what's happening -- we hit ALUExceptionReturn
along that path.

Reviewed-by: default avatarPeter Maydell <peter.maydell@linaro.org>
Signed-off-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Message-id: 20190904193059.26202-18-richard.henderson@linaro.org
Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parent 4c97f5b2
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -211,3 +211,5 @@ BXJ .... 0001 0010 1111 1111 1111 0010 .... @rm
BLX_r            .... 0001 0010 1111 1111 1111 0011 ....      @rm

CLZ              .... 0001 0110 1111 .... 1111 0001 ....      @rdm

ERET             ---- 0001 0110 0000 0000 0000 0110 1110
+8 −0
Original line number Diff line number Diff line
@@ -218,4 +218,12 @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
    MSR_v7m      1111 0011 100 0   rn:4 1000 mask:2 00 sysm:8
  }
  BXJ            1111 0011 1100 rm:4 1000 1111 0000 0000      &r
  {
    # At v6T2, this is the T5 encoding of SUBS PC, LR, #IMM, and works as for
    # every other encoding of SUBS.  With v7VE, IMM=0 is redefined as ERET.
    # The distinction between the two only matters for Hyp mode.
    ERET         1111 0011 1101 1110 1000 1111 0000 0000
    SUB_rri      1111 0011 1101 1110 1000 1111 imm:8 \
                 &s_rri_rot rot=0 s=1 rd=15 rn=14
  }
}
+23 −39
Original line number Diff line number Diff line
@@ -8503,6 +8503,27 @@ static bool trans_CLZ(DisasContext *s, arg_CLZ *a)
    return true;
}

static bool trans_ERET(DisasContext *s, arg_ERET *a)
{
    TCGv_i32 tmp;

    if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
        return false;
    }
    if (IS_USER(s)) {
        unallocated_encoding(s);
        return true;
    }
    if (s->current_el == 2) {
        /* ERET from Hyp uses ELR_Hyp, not LR */
        tmp = load_cpu_field(elr_el[2]);
    } else {
        tmp = load_reg(s, 14);
    }
    gen_exception_return(s, tmp);
    return true;
}

/*
 * Legacy decoder.
 */
@@ -8797,29 +8818,10 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
        case 0x4: /* crc32 */
            /* All done in decodetree.  Illegal ops reach here.  */
            goto illegal_op;
        case 0x5:
            /* Saturating addition and subtraction.  */
            /* All done in decodetree.  Reach here for illegal ops.  */
            goto illegal_op;
        case 0x5: /* Saturating addition and subtraction.  */
        case 0x6: /* ERET */
            if (op1 != 3) {
                goto illegal_op;
            }
            if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
                goto illegal_op;
            }
            if ((insn & 0x000fff0f) != 0x0000000e) {
                /* UNPREDICTABLE; we choose to UNDEF */
            /* All done in decodetree.  Reach here for illegal ops.  */
            goto illegal_op;
            }

            if (s->current_el == 2) {
                tmp = load_cpu_field(elr_el[2]);
            } else {
                tmp = load_reg(s, 14);
            }
            gen_exception_return(s, tmp);
            break;
        case 7:
        {
            int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
@@ -10628,24 +10630,6 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
                    case 4: /* bxj, in decodetree */
                        goto illegal_op;
                    case 5: /* Exception return.  */
                        if (IS_USER(s)) {
                            goto illegal_op;
                        }
                        if (rn != 14 || rd != 15) {
                            goto illegal_op;
                        }
                        if (s->current_el == 2) {
                            /* ERET from Hyp uses ELR_Hyp, not LR */
                            if (insn & 0xff) {
                                goto illegal_op;
                            }
                            tmp = load_cpu_field(elr_el[2]);
                        } else {
                            tmp = load_reg(s, rn);
                            tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
                        }
                        gen_exception_return(s, tmp);
                        break;
                    case 6: /* MRS, in decodetree */
                    case 7: /* MSR, in decodetree */
                        goto illegal_op;