target/arm: Implement CLRM instruction

In v8.1M the new CLRM instruction allows zeroing an arbitrary set of
the general-purpose registers and APSR. Implement this.

The encoding is a subset of the LDMIA T2 encoding, using what would
be Rn=0b1111 (which UNDEFs for LDMIA).

Backports 6e21a013fbdf54960a079dccc90772bb622e28e8
This commit is contained in:
Peter Maydell 2021-03-03 18:00:25 -05:00 committed by Lioncash
parent 43d8441881
commit 2e3bd010a8
2 changed files with 44 additions and 1 deletions

View file

@ -609,7 +609,11 @@ UXTAB 1111 1010 0101 .... 1111 .... 10.. .... @rrr_rot
STM_t32 1110 1000 10.0 .... ................ @ldstm i=1 b=0
STM_t32 1110 1001 00.0 .... ................ @ldstm i=0 b=1
LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
{
# Rn=15 UNDEFs for LDM; M-profile CLRM uses that encoding
CLRM 1110 1000 1001 1111 list:16
LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
}
LDM_t32 1110 1001 00.1 .... ................ @ldstm i=0 b=1
&rfe !extern rn w pu

View file

@ -8220,6 +8220,45 @@ static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
return do_ldm(s, a, 1);
}
static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
int i;
TCGv_i32 zero;
if (!dc_isar_feature(aa32_m_sec_state, s)) {
return false;
}
if (extract32(a->list, 13, 1)) {
return false;
}
if (!a->list) {
/* UNPREDICTABLE; we choose to UNDEF */
return false;
}
zero = tcg_const_i32(tcg_ctx, 0);
for (i = 0; i < 15; i++) {
if (extract32(a->list, i, 1)) {
/* Clear R[i] */
tcg_gen_mov_i32(tcg_ctx, tcg_ctx->cpu_R[i], zero);
}
}
if (extract32(a->list, 15, 1)) {
/*
* Clear APSR (by calling the MSR helper with the same argument
* as for "MSR APSR_nzcvqg, Rn": mask = 0b1100, SYSM=0)
*/
TCGv_i32 maskreg = tcg_const_i32(tcg_ctx, 0xc << 8);
gen_helper_v7m_msr(tcg_ctx, tcg_ctx->cpu_env, maskreg, zero);
tcg_temp_free_i32(tcg_ctx, maskreg);
}
tcg_temp_free_i32(tcg_ctx, zero);
return true;
}
/*
* Branch, branch with link
*/