diff mbox series

[07/55] target/arm: Implement MVE WLSTP insn

Message ID 20210607165821.9892-8-peter.maydell@linaro.org
State Superseded
Headers show
Series target/arm: First slice of MVE implementation | expand

Commit Message

Peter Maydell June 7, 2021, 4:57 p.m. UTC
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>

---
 target/arm/t32.decode  |  8 ++++++--
 target/arm/translate.c | 36 +++++++++++++++++++++++++++++++++++-
 2 files changed, 41 insertions(+), 3 deletions(-)

-- 
2.20.1

Comments

Richard Henderson June 8, 2021, 1:42 a.m. UTC | #1
On 6/7/21 9:57 AM, Peter Maydell wrote:
> +    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

> +    }


I guess it doesn't matter, but I'd swap these two, as LE is the more specific 
encoding.

> @@ -8148,10 +8152,40 @@ 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);

> +        }


Surely return true here...

> +    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);


... otherwise this assert will trigger.


r~
r~
diff mbox series

Patch

diff --git a/target/arm/t32.decode b/target/arm/t32.decode
index 087e514e0ac..4f0c686a3c3 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
+    {
+      # 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
   ]
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 2f6c012f672..79ec185dd83 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -8135,7 +8135,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) {
@@ -8148,10 +8152,40 @@  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);
+        }
+    }
+
     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);