Implement the MVE DLSTP insn; this is like the existing DLS insn, except that it must do an FPU access check and it sets LTPSIZE to the value specified in the insn.
Signed-off-by: Peter Maydell <peter.mayd...@linaro.org> --- target/arm/t32.decode | 9 ++++++--- target/arm/translate.c | 23 +++++++++++++++++++++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/target/arm/t32.decode b/target/arm/t32.decode index 4f0c686a3c3..8e1ca7d64a9 100644 --- a/target/arm/t32.decode +++ b/target/arm/t32.decode @@ -671,14 +671,17 @@ BL 1111 0. .......... 11.1 ............ @branch24 # LE and WLS immediate %lob_imm 1:10 11:1 !function=times_2 - DLS 1111 0 0000 100 rn:4 1110 0000 0000 0001 + DLS 1111 0 0000 100 rn:4 1110 0000 0000 0001 size=4 WLS 1111 0 0000 100 rn:4 1100 . .......... 1 imm=%lob_imm size=4 { # This is WLSTP WLS 1111 0 0000 0 size:2 rn:4 1100 . .......... 1 imm=%lob_imm LE 1111 0 0000 0 f:1 0 1111 1100 . .......... 1 imm=%lob_imm } - - LCTP 1111 0 0000 000 1111 1110 0000 0000 0001 + { + # This is DLSTP + DLS 1111 0 0000 0 size:2 rn:4 1110 0000 0000 0001 + LCTP 1111 0 0000 000 1111 1110 0000 0000 0001 + } ] } diff --git a/target/arm/translate.c b/target/arm/translate.c index 79ec185dd83..976c665be9c 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -8115,13 +8115,32 @@ static bool trans_DLS(DisasContext *s, arg_DLS *a) return false; } if (a->rn == 13 || a->rn == 15) { - /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */ + /* + * For DLSTP rn == 15 is a related encoding (LCTP); the + * other cases caught by this condition are all + * CONSTRAINED UNPREDICTABLE: we choose to UNDEF + */ return false; } - /* Not a while loop, no tail predication: just set LR to the count */ + if (a->size != 4) { + /* DLSTP */ + if (!dc_isar_feature(aa32_mve, s)) { + return false; + } + if (!vfp_access_check(s)) { + return true; + } + } + + /* Not a while loop: set LR to the count, and set LTPSIZE for DLSTP */ tmp = load_reg(s, a->rn); store_reg(s, 14, tmp); + if (a->size != 4) { + /* DLSTP: set FPSCR.LTPSIZE */ + tmp = tcg_const_i32(a->size); + store_cpu_field(tmp, v7m.ltpsize); + } return true; } -- 2.20.1