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
This commit is contained in:
parent
5d2555a1fe
commit
cc73bbded0
@ -90,6 +90,9 @@ SBC_rrri 1110101 1011 . .... 0 ... .... .... .... @s_rrr_shi
|
||||
}
|
||||
RSB_rrri 1110101 1110 . .... 0 ... .... .... .... @s_rrr_shi
|
||||
|
||||
# v8.1M CSEL and friends
|
||||
CSEL 1110101 0010 1 rn:4 10 op:2 rd:4 fcond:4 rm:4
|
||||
|
||||
# Data-processing (register-shifted register)
|
||||
|
||||
MOV_rxrr 1111 1010 0 shty:2 s:1 rm:4 1111 rd:4 0000 rs:4 \
|
||||
|
@ -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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user