diff options
author | Peter Maydell | 2020-10-19 17:12:54 +0200 |
---|---|---|
committer | Peter Maydell | 2020-10-20 17:12:01 +0200 |
commit | cc73bbded0dfb5612b0e416f7eda13a66950542a (patch) | |
tree | defa551bafc8f47cdc338c3c31604a5a42f48b83 /target/arm/translate.c | |
parent | target/arm: Implement v8.1M NOCP handling (diff) | |
download | qemu-cc73bbded0dfb5612b0e416f7eda13a66950542a.tar.gz qemu-cc73bbded0dfb5612b0e416f7eda13a66950542a.tar.xz qemu-cc73bbded0dfb5612b0e416f7eda13a66950542a.zip |
target/arm: Implement v8.1M conditional-select insns
v8.1M brings four new insns to M-profile:
* CSEL : Rd = cond ? Rn : Rm
* CSINC : Rd = cond ? Rn : Rm+1
* CSINV : Rd = cond ? Rn : ~Rm
* CSNEG : Rd = cond ? Rn : -Rm
Implement these.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20201019151301.2046-4-peter.maydell@linaro.org
Diffstat (limited to 'target/arm/translate.c')
-rw-r--r-- | target/arm/translate.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/target/arm/translate.c b/target/arm/translate.c index d8729e42c4..9f2201ca57 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -8262,6 +8262,66 @@ static bool trans_IT(DisasContext *s, arg_IT *a) return true; } +/* v8.1M CSEL/CSINC/CSNEG/CSINV */ +static bool trans_CSEL(DisasContext *s, arg_CSEL *a) +{ + TCGv_i32 rn, rm, zero; + DisasCompare c; + + if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) { + return false; + } + + if (a->rm == 13) { + /* SEE "Related encodings" (MVE shifts) */ + return false; + } + + if (a->rd == 13 || a->rd == 15 || a->rn == 13 || a->fcond >= 14) { + /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */ + return false; + } + + /* In this insn input reg fields of 0b1111 mean "zero", not "PC" */ + if (a->rn == 15) { + rn = tcg_const_i32(0); + } else { + rn = load_reg(s, a->rn); + } + if (a->rm == 15) { + rm = tcg_const_i32(0); + } else { + rm = load_reg(s, a->rm); + } + + switch (a->op) { + case 0: /* CSEL */ + break; + case 1: /* CSINC */ + tcg_gen_addi_i32(rm, rm, 1); + break; + case 2: /* CSINV */ + tcg_gen_not_i32(rm, rm); + break; + case 3: /* CSNEG */ + tcg_gen_neg_i32(rm, rm); + break; + default: + g_assert_not_reached(); + } + + arm_test_cc(&c, a->fcond); + zero = tcg_const_i32(0); + tcg_gen_movcond_i32(c.cond, rn, c.value, zero, rn, rm); + arm_free_cc(&c); + tcg_temp_free_i32(zero); + + store_reg(s, a->rd, rn); + tcg_temp_free_i32(rm); + + return true; +} + /* * Legacy decoder. */ |