mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-07-07 13:50:36 +00:00
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. Backports cc73bbded0dfb5612b0e416f7eda13a66950542a
This commit is contained in:
parent
2dae268fcb
commit
666fe17025
|
@ -90,6 +90,9 @@ SBC_rrri 1110101 1011 . .... 0 ... .... .... .... @s_rrr_shi
|
||||||
}
|
}
|
||||||
RSB_rrri 1110101 1110 . .... 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)
|
# Data-processing (register-shifted register)
|
||||||
|
|
||||||
MOV_rxrr 1111 1010 0 shty:2 s:1 rm:4 1111 rd:4 0000 rs:4 \
|
MOV_rxrr 1111 1010 0 shty:2 s:1 rm:4 1111 rd:4 0000 rs:4 \
|
||||||
|
|
|
@ -8511,6 +8511,67 @@ static bool trans_IT(DisasContext *s, arg_IT *a)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* v8.1M CSEL/CSINC/CSNEG/CSINV */
|
||||||
|
static bool trans_CSEL(DisasContext *s, arg_CSEL *a)
|
||||||
|
{
|
||||||
|
TCGv_i32 rn, rm, zero;
|
||||||
|
DisasCompare c;
|
||||||
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
|
|
||||||
|
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(tcg_ctx, 0);
|
||||||
|
} else {
|
||||||
|
rn = load_reg(s, a->rn);
|
||||||
|
}
|
||||||
|
if (a->rm == 15) {
|
||||||
|
rm = tcg_const_i32(tcg_ctx, 0);
|
||||||
|
} else {
|
||||||
|
rm = load_reg(s, a->rm);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (a->op) {
|
||||||
|
case 0: /* CSEL */
|
||||||
|
break;
|
||||||
|
case 1: /* CSINC */
|
||||||
|
tcg_gen_addi_i32(tcg_ctx, rm, rm, 1);
|
||||||
|
break;
|
||||||
|
case 2: /* CSINV */
|
||||||
|
tcg_gen_not_i32(tcg_ctx, rm, rm);
|
||||||
|
break;
|
||||||
|
case 3: /* CSNEG */
|
||||||
|
tcg_gen_neg_i32(tcg_ctx, rm, rm);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
arm_test_cc(s, &c, a->fcond);
|
||||||
|
zero = tcg_const_i32(tcg_ctx, 0);
|
||||||
|
tcg_gen_movcond_i32(tcg_ctx, c.cond, rn, c.value, zero, rn, rm);
|
||||||
|
arm_free_cc(s, &c);
|
||||||
|
tcg_temp_free_i32(tcg_ctx, zero);
|
||||||
|
|
||||||
|
store_reg(s, a->rd, rn);
|
||||||
|
tcg_temp_free_i32(tcg_ctx, rm);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Legacy decoder.
|
* Legacy decoder.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue