aboutsummaryrefslogtreecommitdiff
path: root/target/arm
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-06-14 16:09:17 +0100
committerPeter Maydell <peter.maydell@linaro.org>2021-06-16 14:33:52 +0100
commit6822abfdf8b382be4fc84066fa1087e5fef81360 (patch)
tree91b4e865a7ceeebd70f5175ed71064876a934063 /target/arm
parent76c32d721da1a69999eb2d3cd5f1d272ca26f98e (diff)
target/arm: Implement MVE WLSTP insn
Implement the MVE WLSTP insn; this is like the existing WLS insn, except that it specifies a size value which is used to set FPSCR.LTPSIZE. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210614151007.4545-8-peter.maydell@linaro.org
Diffstat (limited to 'target/arm')
-rw-r--r--target/arm/t32.decode8
-rw-r--r--target/arm/translate.c37
2 files changed, 42 insertions, 3 deletions
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
index 087e514e0a..6906829265 100644
--- a/target/arm/t32.decode
+++ b/target/arm/t32.decode
@@ -672,8 +672,12 @@ BL 1111 0. .......... 11.1 ............ @branch24
%lob_imm 1:10 11:1 !function=times_2
DLS 1111 0 0000 100 rn:4 1110 0000 0000 0001
- WLS 1111 0 0000 100 rn:4 1100 . .......... 1 imm=%lob_imm
- LE 1111 0 0000 0 f:1 0 1111 1100 . .......... 1 imm=%lob_imm
+ WLS 1111 0 0000 100 rn:4 1100 . .......... 1 imm=%lob_imm size=4
+ {
+ LE 1111 0 0000 0 f:1 0 1111 1100 . .......... 1 imm=%lob_imm
+ # This is WLSTP
+ WLS 1111 0 0000 0 size:2 rn:4 1100 . .......... 1 imm=%lob_imm
+ }
LCTP 1111 0 0000 000 1111 1110 0000 0000 0001
]
diff --git a/target/arm/translate.c b/target/arm/translate.c
index c49561590c..78878e9b19 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -8134,7 +8134,11 @@ static bool trans_WLS(DisasContext *s, arg_WLS *a)
return false;
}
if (a->rn == 13 || a->rn == 15) {
- /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
+ /*
+ * For WLSTP rn == 15 is a related encoding (LE); the
+ * other cases caught by this condition are all
+ * CONSTRAINED UNPREDICTABLE: we choose to UNDEF
+ */
return false;
}
if (s->condexec_mask) {
@@ -8147,10 +8151,41 @@ static bool trans_WLS(DisasContext *s, arg_WLS *a)
*/
return false;
}
+ if (a->size != 4) {
+ /* WLSTP */
+ if (!dc_isar_feature(aa32_mve, s)) {
+ return false;
+ }
+ /*
+ * We need to check that the FPU is enabled here, but mustn't
+ * call vfp_access_check() to do that because we don't want to
+ * do the lazy state preservation in the "loop count is zero" case.
+ * Do the check-and-raise-exception by hand.
+ */
+ if (s->fp_excp_el) {
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
+ syn_uncategorized(), s->fp_excp_el);
+ return true;
+ }
+ }
+
nextlabel = gen_new_label();
tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_R[a->rn], 0, nextlabel);
tmp = load_reg(s, a->rn);
store_reg(s, 14, tmp);
+ if (a->size != 4) {
+ /*
+ * WLSTP: set FPSCR.LTPSIZE. This requires that we do the
+ * lazy state preservation, new FP context creation, etc,
+ * that vfp_access_check() does. We know that the actual
+ * access check will succeed (ie it won't generate code that
+ * throws an exception) because we did that check by hand earlier.
+ */
+ bool ok = vfp_access_check(s);
+ assert(ok);
+ tmp = tcg_const_i32(a->size);
+ store_cpu_field(tmp, v7m.ltpsize);
+ }
gen_jmp_tb(s, s->base.pc_next, 1);
gen_set_label(nextlabel);