All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE
@ 2018-01-19  4:54 Richard Henderson
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 01/16] target/arm: Mark disas_set_insn_syndrome inline Richard Henderson
                   ` (18 more replies)
  0 siblings, 19 replies; 46+ messages in thread
From: Richard Henderson @ 2018-01-19  4:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

I believe that this addresses all of the comments Peter had with
respect to v1.  I did go ahead and add the system registers, so that
I could figure out how they're supposed to work.

This has been rebased to master so that it has no dependencies.


r~


Richard Henderson (16):
  target/arm: Mark disas_set_insn_syndrome inline
  target/arm: Use pointers in crypto helpers
  target/arm: Use pointers in neon zip/uzp helpers
  target/arm: Use pointers in neon tbl helper
  target/arm: Change the type of vfp.regs
  target/arm: Add aa{32,64}_vfp_{dreg,qreg} helpers
  vmstate: Add VMSTATE_UINT64_SUB_ARRAY
  target/arm: Expand vector registers for SVE
  target/arm: Add predicate registers for SVE
  target/arm: Add ARM_FEATURE_SVE
  target/arm: Add SVE to migration state
  target/arm: Add ZCR_ELx
  target/arm: Move cpu_get_tb_cpu_state out of line
  target/arm: Hoist store to flags output in cpu_get_tb_cpu_state
  target/arm: Simplify fp_exception_el for user-only
  target/arm: Add SVE state to TB->FLAGS

 include/migration/vmstate.h |   9 +-
 target/arm/cpu.h            | 227 +++++++++++++++-----------------------
 target/arm/helper.h         |  46 ++++----
 target/arm/translate.h      |   2 +-
 linux-user/signal.c         |  22 ++--
 target/arm/arch_dump.c      |   8 +-
 target/arm/crypto_helper.c  | 184 ++++++++++++-------------------
 target/arm/helper-a64.c     |   5 +-
 target/arm/helper.c         | 263 ++++++++++++++++++++++++++++++++++++++++++--
 target/arm/kvm32.c          |   4 +-
 target/arm/kvm64.c          |  31 ++----
 target/arm/machine.c        |  88 ++++++++++++++-
 target/arm/neon_helper.c    | 162 ++++++++++++++-------------
 target/arm/op_helper.c      |  17 ++-
 target/arm/translate-a64.c  | 106 +++++++++---------
 target/arm/translate.c      | 139 ++++++++++++-----------
 16 files changed, 781 insertions(+), 532 deletions(-)

-- 
2.14.3

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v2 01/16] target/arm: Mark disas_set_insn_syndrome inline
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
@ 2018-01-19  4:54 ` Richard Henderson
  2018-01-19 13:54   ` Alex Bennée
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 02/16] target/arm: Use pointers in crypto helpers Richard Henderson
                   ` (17 subsequent siblings)
  18 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2018-01-19  4:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

If it isn't used when translate.h is included,
we'll get a compiler Werror.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/translate.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/arm/translate.h b/target/arm/translate.h
index cd7313ace7..3f4df91e5e 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -108,7 +108,7 @@ static inline int default_exception_el(DisasContext *s)
             ? 3 : MAX(1, s->current_el);
 }
 
-static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
+static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
 {
     /* We don't need to save all of the syndrome so we mask and shift
      * out unneeded bits to help the sleb128 encoder do a better job.
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v2 02/16] target/arm: Use pointers in crypto helpers
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 01/16] target/arm: Mark disas_set_insn_syndrome inline Richard Henderson
@ 2018-01-19  4:54 ` Richard Henderson
  2018-01-22 10:09   ` Alex Bennée
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 03/16] target/arm: Use pointers in neon zip/uzp helpers Richard Henderson
                   ` (16 subsequent siblings)
  18 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2018-01-19  4:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Rather than passing regnos to the helpers, pass pointers to the
vector registers directly.  This eliminates the need to pass in
the environment pointer and reduces the number of places that
directly access env->vfp.regs[].

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/helper.h        |  18 ++---
 target/arm/crypto_helper.c | 184 +++++++++++++++++----------------------------
 target/arm/translate-a64.c |  75 ++++++++++--------
 target/arm/translate.c     |  68 +++++++++--------
 4 files changed, 161 insertions(+), 184 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index 066729e8ad..688380af6b 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -522,17 +522,17 @@ DEF_HELPER_3(neon_qzip8, void, env, i32, i32)
 DEF_HELPER_3(neon_qzip16, void, env, i32, i32)
 DEF_HELPER_3(neon_qzip32, void, env, i32, i32)
 
-DEF_HELPER_4(crypto_aese, void, env, i32, i32, i32)
-DEF_HELPER_4(crypto_aesmc, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_3(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
 
-DEF_HELPER_5(crypto_sha1_3reg, void, env, i32, i32, i32, i32)
-DEF_HELPER_3(crypto_sha1h, void, env, i32, i32)
-DEF_HELPER_3(crypto_sha1su1, void, env, i32, i32)
+DEF_HELPER_FLAGS_4(crypto_sha1_3reg, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_2(crypto_sha1h, TCG_CALL_NO_RWG, void, ptr, ptr)
+DEF_HELPER_FLAGS_2(crypto_sha1su1, TCG_CALL_NO_RWG, void, ptr, ptr)
 
-DEF_HELPER_4(crypto_sha256h, void, env, i32, i32, i32)
-DEF_HELPER_4(crypto_sha256h2, void, env, i32, i32, i32)
-DEF_HELPER_3(crypto_sha256su0, void, env, i32, i32)
-DEF_HELPER_4(crypto_sha256su1, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_3(crypto_sha256h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
+DEF_HELPER_FLAGS_3(crypto_sha256h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
+DEF_HELPER_FLAGS_2(crypto_sha256su0, TCG_CALL_NO_RWG, void, ptr, ptr)
+DEF_HELPER_FLAGS_3(crypto_sha256su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
 
 DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
 DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
index 3b6df3f41a..9ca0bdead7 100644
--- a/target/arm/crypto_helper.c
+++ b/target/arm/crypto_helper.c
@@ -30,20 +30,14 @@ union CRYPTO_STATE {
 #define CR_ST_WORD(state, i)   (state.words[i])
 #endif
 
-void HELPER(crypto_aese)(CPUARMState *env, uint32_t rd, uint32_t rm,
-                         uint32_t decrypt)
+void HELPER(crypto_aese)(void *vd, void *vm, uint32_t decrypt)
 {
     static uint8_t const * const sbox[2] = { AES_sbox, AES_isbox };
     static uint8_t const * const shift[2] = { AES_shifts, AES_ishifts };
-
-    union CRYPTO_STATE rk = { .l = {
-        float64_val(env->vfp.regs[rm]),
-        float64_val(env->vfp.regs[rm + 1])
-    } };
-    union CRYPTO_STATE st = { .l = {
-        float64_val(env->vfp.regs[rd]),
-        float64_val(env->vfp.regs[rd + 1])
-    } };
+    uint64_t *rd = vd;
+    uint64_t *rm = vm;
+    union CRYPTO_STATE rk = { .l = { rm[0], rm[1] } };
+    union CRYPTO_STATE st = { .l = { rd[0], rd[1] } };
     int i;
 
     assert(decrypt < 2);
@@ -57,12 +51,11 @@ void HELPER(crypto_aese)(CPUARMState *env, uint32_t rd, uint32_t rm,
         CR_ST_BYTE(st, i) = sbox[decrypt][CR_ST_BYTE(rk, shift[decrypt][i])];
     }
 
-    env->vfp.regs[rd] = make_float64(st.l[0]);
-    env->vfp.regs[rd + 1] = make_float64(st.l[1]);
+    rd[0] = st.l[0];
+    rd[1] = st.l[1];
 }
 
-void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm,
-                          uint32_t decrypt)
+void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t decrypt)
 {
     static uint32_t const mc[][256] = { {
         /* MixColumns lookup table */
@@ -197,10 +190,10 @@ void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm,
         0x92b479a7, 0x99b970a9, 0x84ae6bbb, 0x8fa362b5,
         0xbe805d9f, 0xb58d5491, 0xa89a4f83, 0xa397468d,
     } };
-    union CRYPTO_STATE st = { .l = {
-        float64_val(env->vfp.regs[rm]),
-        float64_val(env->vfp.regs[rm + 1])
-    } };
+
+    uint64_t *rd = vd;
+    uint64_t *rm = vm;
+    union CRYPTO_STATE st = { .l = { rm[0], rm[1] } };
     int i;
 
     assert(decrypt < 2);
@@ -213,8 +206,8 @@ void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm,
             rol32(mc[decrypt][CR_ST_BYTE(st, i + 3)], 24);
     }
 
-    env->vfp.regs[rd] = make_float64(st.l[0]);
-    env->vfp.regs[rd + 1] = make_float64(st.l[1]);
+    rd[0] = st.l[0];
+    rd[1] = st.l[1];
 }
 
 /*
@@ -236,21 +229,14 @@ static uint32_t maj(uint32_t x, uint32_t y, uint32_t z)
     return (x & y) | ((x | y) & z);
 }
 
-void HELPER(crypto_sha1_3reg)(CPUARMState *env, uint32_t rd, uint32_t rn,
-                              uint32_t rm, uint32_t op)
+void HELPER(crypto_sha1_3reg)(void *vd, void *vn, void *vm, uint32_t op)
 {
-    union CRYPTO_STATE d = { .l = {
-        float64_val(env->vfp.regs[rd]),
-        float64_val(env->vfp.regs[rd + 1])
-    } };
-    union CRYPTO_STATE n = { .l = {
-        float64_val(env->vfp.regs[rn]),
-        float64_val(env->vfp.regs[rn + 1])
-    } };
-    union CRYPTO_STATE m = { .l = {
-        float64_val(env->vfp.regs[rm]),
-        float64_val(env->vfp.regs[rm + 1])
-    } };
+    uint64_t *rd = vd;
+    uint64_t *rn = vn;
+    uint64_t *rm = vm;
+    union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
+    union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
+    union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
 
     if (op == 3) { /* sha1su0 */
         d.l[0] ^= d.l[1] ^ m.l[0];
@@ -284,42 +270,37 @@ void HELPER(crypto_sha1_3reg)(CPUARMState *env, uint32_t rd, uint32_t rn,
             CR_ST_WORD(d, 0) = t;
         }
     }
-    env->vfp.regs[rd] = make_float64(d.l[0]);
-    env->vfp.regs[rd + 1] = make_float64(d.l[1]);
+    rd[0] = d.l[0];
+    rd[1] = d.l[1];
 }
 
-void HELPER(crypto_sha1h)(CPUARMState *env, uint32_t rd, uint32_t rm)
+void HELPER(crypto_sha1h)(void *vd, void *vm)
 {
-    union CRYPTO_STATE m = { .l = {
-        float64_val(env->vfp.regs[rm]),
-        float64_val(env->vfp.regs[rm + 1])
-    } };
+    uint64_t *rd = vd;
+    uint64_t *rm = vm;
+    union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
 
     CR_ST_WORD(m, 0) = ror32(CR_ST_WORD(m, 0), 2);
     CR_ST_WORD(m, 1) = CR_ST_WORD(m, 2) = CR_ST_WORD(m, 3) = 0;
 
-    env->vfp.regs[rd] = make_float64(m.l[0]);
-    env->vfp.regs[rd + 1] = make_float64(m.l[1]);
+    rd[0] = m.l[0];
+    rd[1] = m.l[1];
 }
 
-void HELPER(crypto_sha1su1)(CPUARMState *env, uint32_t rd, uint32_t rm)
+void HELPER(crypto_sha1su1)(void *vd, void *vm)
 {
-    union CRYPTO_STATE d = { .l = {
-        float64_val(env->vfp.regs[rd]),
-        float64_val(env->vfp.regs[rd + 1])
-    } };
-    union CRYPTO_STATE m = { .l = {
-        float64_val(env->vfp.regs[rm]),
-        float64_val(env->vfp.regs[rm + 1])
-    } };
+    uint64_t *rd = vd;
+    uint64_t *rm = vm;
+    union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
+    union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
 
     CR_ST_WORD(d, 0) = rol32(CR_ST_WORD(d, 0) ^ CR_ST_WORD(m, 1), 1);
     CR_ST_WORD(d, 1) = rol32(CR_ST_WORD(d, 1) ^ CR_ST_WORD(m, 2), 1);
     CR_ST_WORD(d, 2) = rol32(CR_ST_WORD(d, 2) ^ CR_ST_WORD(m, 3), 1);
     CR_ST_WORD(d, 3) = rol32(CR_ST_WORD(d, 3) ^ CR_ST_WORD(d, 0), 1);
 
-    env->vfp.regs[rd] = make_float64(d.l[0]);
-    env->vfp.regs[rd + 1] = make_float64(d.l[1]);
+    rd[0] = d.l[0];
+    rd[1] = d.l[1];
 }
 
 /*
@@ -347,21 +328,14 @@ static uint32_t s1(uint32_t x)
     return ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10);
 }
 
-void HELPER(crypto_sha256h)(CPUARMState *env, uint32_t rd, uint32_t rn,
-                            uint32_t rm)
+void HELPER(crypto_sha256h)(void *vd, void *vn, void *vm)
 {
-    union CRYPTO_STATE d = { .l = {
-        float64_val(env->vfp.regs[rd]),
-        float64_val(env->vfp.regs[rd + 1])
-    } };
-    union CRYPTO_STATE n = { .l = {
-        float64_val(env->vfp.regs[rn]),
-        float64_val(env->vfp.regs[rn + 1])
-    } };
-    union CRYPTO_STATE m = { .l = {
-        float64_val(env->vfp.regs[rm]),
-        float64_val(env->vfp.regs[rm + 1])
-    } };
+    uint64_t *rd = vd;
+    uint64_t *rn = vn;
+    uint64_t *rm = vm;
+    union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
+    union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
+    union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
     int i;
 
     for (i = 0; i < 4; i++) {
@@ -383,25 +357,18 @@ void HELPER(crypto_sha256h)(CPUARMState *env, uint32_t rd, uint32_t rn,
         CR_ST_WORD(d, 0) = t;
     }
 
-    env->vfp.regs[rd] = make_float64(d.l[0]);
-    env->vfp.regs[rd + 1] = make_float64(d.l[1]);
+    rd[0] = d.l[0];
+    rd[1] = d.l[1];
 }
 
-void HELPER(crypto_sha256h2)(CPUARMState *env, uint32_t rd, uint32_t rn,
-                             uint32_t rm)
+void HELPER(crypto_sha256h2)(void *vd, void *vn, void *vm)
 {
-    union CRYPTO_STATE d = { .l = {
-        float64_val(env->vfp.regs[rd]),
-        float64_val(env->vfp.regs[rd + 1])
-    } };
-    union CRYPTO_STATE n = { .l = {
-        float64_val(env->vfp.regs[rn]),
-        float64_val(env->vfp.regs[rn + 1])
-    } };
-    union CRYPTO_STATE m = { .l = {
-        float64_val(env->vfp.regs[rm]),
-        float64_val(env->vfp.regs[rm + 1])
-    } };
+    uint64_t *rd = vd;
+    uint64_t *rn = vn;
+    uint64_t *rm = vm;
+    union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
+    union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
+    union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
     int i;
 
     for (i = 0; i < 4; i++) {
@@ -415,51 +382,40 @@ void HELPER(crypto_sha256h2)(CPUARMState *env, uint32_t rd, uint32_t rn,
         CR_ST_WORD(d, 0) = CR_ST_WORD(n, 3 - i) + t;
     }
 
-    env->vfp.regs[rd] = make_float64(d.l[0]);
-    env->vfp.regs[rd + 1] = make_float64(d.l[1]);
+    rd[0] = d.l[0];
+    rd[1] = d.l[1];
 }
 
-void HELPER(crypto_sha256su0)(CPUARMState *env, uint32_t rd, uint32_t rm)
+void HELPER(crypto_sha256su0)(void *vd, void *vm)
 {
-    union CRYPTO_STATE d = { .l = {
-        float64_val(env->vfp.regs[rd]),
-        float64_val(env->vfp.regs[rd + 1])
-    } };
-    union CRYPTO_STATE m = { .l = {
-        float64_val(env->vfp.regs[rm]),
-        float64_val(env->vfp.regs[rm + 1])
-    } };
+    uint64_t *rd = vd;
+    uint64_t *rm = vm;
+    union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
+    union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
 
     CR_ST_WORD(d, 0) += s0(CR_ST_WORD(d, 1));
     CR_ST_WORD(d, 1) += s0(CR_ST_WORD(d, 2));
     CR_ST_WORD(d, 2) += s0(CR_ST_WORD(d, 3));
     CR_ST_WORD(d, 3) += s0(CR_ST_WORD(m, 0));
 
-    env->vfp.regs[rd] = make_float64(d.l[0]);
-    env->vfp.regs[rd + 1] = make_float64(d.l[1]);
+    rd[0] = d.l[0];
+    rd[1] = d.l[1];
 }
 
-void HELPER(crypto_sha256su1)(CPUARMState *env, uint32_t rd, uint32_t rn,
-                              uint32_t rm)
+void HELPER(crypto_sha256su1)(void *vd, void *vn, void *vm)
 {
-    union CRYPTO_STATE d = { .l = {
-        float64_val(env->vfp.regs[rd]),
-        float64_val(env->vfp.regs[rd + 1])
-    } };
-    union CRYPTO_STATE n = { .l = {
-        float64_val(env->vfp.regs[rn]),
-        float64_val(env->vfp.regs[rn + 1])
-    } };
-    union CRYPTO_STATE m = { .l = {
-        float64_val(env->vfp.regs[rm]),
-        float64_val(env->vfp.regs[rm + 1])
-    } };
+    uint64_t *rd = vd;
+    uint64_t *rn = vn;
+    uint64_t *rm = vm;
+    union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
+    union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
+    union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
 
     CR_ST_WORD(d, 0) += s1(CR_ST_WORD(m, 2)) + CR_ST_WORD(n, 1);
     CR_ST_WORD(d, 1) += s1(CR_ST_WORD(m, 3)) + CR_ST_WORD(n, 2);
     CR_ST_WORD(d, 2) += s1(CR_ST_WORD(d, 0)) + CR_ST_WORD(n, 3);
     CR_ST_WORD(d, 3) += s1(CR_ST_WORD(d, 1)) + CR_ST_WORD(m, 0);
 
-    env->vfp.regs[rd] = make_float64(d.l[0]);
-    env->vfp.regs[rd + 1] = make_float64(d.l[1]);
+    rd[0] = d.l[0];
+    rd[1] = d.l[1];
 }
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 70c1e08a36..6d9b3af64c 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -80,8 +80,9 @@ typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
 typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
 typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
 typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64);
-typedef void CryptoTwoOpEnvFn(TCGv_ptr, TCGv_i32, TCGv_i32);
-typedef void CryptoThreeOpEnvFn(TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32);
+typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr);
+typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
+typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
 
 /* initialize TCG globals.  */
 void a64_translate_init(void)
@@ -535,6 +536,21 @@ static inline int vec_reg_offset(DisasContext *s, int regno,
     return offs;
 }
 
+/* Return the offset info CPUARMState of the "whole" vector register Qn.  */
+static inline int vec_full_reg_offset(DisasContext *s, int regno)
+{
+    assert_fp_access_checked(s);
+    return offsetof(CPUARMState, vfp.regs[regno * 2]);
+}
+
+/* Return a newly allocated pointer to the vector register.  */
+static TCGv_ptr vec_full_reg_ptr(DisasContext *s, int regno)
+{
+    TCGv_ptr ret = tcg_temp_new_ptr();
+    tcg_gen_addi_ptr(ret, cpu_env, vec_full_reg_offset(s, regno));
+    return ret;
+}
+
 /* Return the offset into CPUARMState of a slice (from
  * the least significant end) of FP register Qn (ie
  * Dn, Sn, Hn or Bn).
@@ -10949,8 +10965,9 @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
     int rn = extract32(insn, 5, 5);
     int rd = extract32(insn, 0, 5);
     int decrypt;
-    TCGv_i32 tcg_rd_regno, tcg_rn_regno, tcg_decrypt;
-    CryptoThreeOpEnvFn *genfn;
+    TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
+    TCGv_i32 tcg_decrypt;
+    CryptoThreeOpIntFn *genfn;
 
     if (!arm_dc_feature(s, ARM_FEATURE_V8_AES)
         || size != 0) {
@@ -10984,18 +11001,14 @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
         return;
     }
 
-    /* Note that we convert the Vx register indexes into the
-     * index within the vfp.regs[] array, so we can share the
-     * helper with the AArch32 instructions.
-     */
-    tcg_rd_regno = tcg_const_i32(rd << 1);
-    tcg_rn_regno = tcg_const_i32(rn << 1);
+    tcg_rd_ptr = vec_full_reg_ptr(s, rd);
+    tcg_rn_ptr = vec_full_reg_ptr(s, rn);
     tcg_decrypt = tcg_const_i32(decrypt);
 
-    genfn(cpu_env, tcg_rd_regno, tcg_rn_regno, tcg_decrypt);
+    genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_decrypt);
 
-    tcg_temp_free_i32(tcg_rd_regno);
-    tcg_temp_free_i32(tcg_rn_regno);
+    tcg_temp_free_ptr(tcg_rd_ptr);
+    tcg_temp_free_ptr(tcg_rn_ptr);
     tcg_temp_free_i32(tcg_decrypt);
 }
 
@@ -11012,8 +11025,8 @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
     int rm = extract32(insn, 16, 5);
     int rn = extract32(insn, 5, 5);
     int rd = extract32(insn, 0, 5);
-    CryptoThreeOpEnvFn *genfn;
-    TCGv_i32 tcg_rd_regno, tcg_rn_regno, tcg_rm_regno;
+    CryptoThreeOpFn *genfn;
+    TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
     int feature = ARM_FEATURE_V8_SHA256;
 
     if (size != 0) {
@@ -11052,23 +11065,23 @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
         return;
     }
 
-    tcg_rd_regno = tcg_const_i32(rd << 1);
-    tcg_rn_regno = tcg_const_i32(rn << 1);
-    tcg_rm_regno = tcg_const_i32(rm << 1);
+    tcg_rd_ptr = vec_full_reg_ptr(s, rd);
+    tcg_rn_ptr = vec_full_reg_ptr(s, rn);
+    tcg_rm_ptr = vec_full_reg_ptr(s, rm);
 
     if (genfn) {
-        genfn(cpu_env, tcg_rd_regno, tcg_rn_regno, tcg_rm_regno);
+        genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
     } else {
         TCGv_i32 tcg_opcode = tcg_const_i32(opcode);
 
-        gen_helper_crypto_sha1_3reg(cpu_env, tcg_rd_regno,
-                                    tcg_rn_regno, tcg_rm_regno, tcg_opcode);
+        gen_helper_crypto_sha1_3reg(tcg_rd_ptr, tcg_rn_ptr,
+                                    tcg_rm_ptr, tcg_opcode);
         tcg_temp_free_i32(tcg_opcode);
     }
 
-    tcg_temp_free_i32(tcg_rd_regno);
-    tcg_temp_free_i32(tcg_rn_regno);
-    tcg_temp_free_i32(tcg_rm_regno);
+    tcg_temp_free_ptr(tcg_rd_ptr);
+    tcg_temp_free_ptr(tcg_rn_ptr);
+    tcg_temp_free_ptr(tcg_rm_ptr);
 }
 
 /* Crypto two-reg SHA
@@ -11083,9 +11096,9 @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
     int opcode = extract32(insn, 12, 5);
     int rn = extract32(insn, 5, 5);
     int rd = extract32(insn, 0, 5);
-    CryptoTwoOpEnvFn *genfn;
+    CryptoTwoOpFn *genfn;
     int feature;
-    TCGv_i32 tcg_rd_regno, tcg_rn_regno;
+    TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
 
     if (size != 0) {
         unallocated_encoding(s);
@@ -11119,13 +11132,13 @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
         return;
     }
 
-    tcg_rd_regno = tcg_const_i32(rd << 1);
-    tcg_rn_regno = tcg_const_i32(rn << 1);
+    tcg_rd_ptr = vec_full_reg_ptr(s, rd);
+    tcg_rn_ptr = vec_full_reg_ptr(s, rn);
 
-    genfn(cpu_env, tcg_rd_regno, tcg_rn_regno);
+    genfn(tcg_rd_ptr, tcg_rn_ptr);
 
-    tcg_temp_free_i32(tcg_rd_regno);
-    tcg_temp_free_i32(tcg_rn_regno);
+    tcg_temp_free_ptr(tcg_rd_ptr);
+    tcg_temp_free_ptr(tcg_rn_ptr);
 }
 
 /* C3.6 Data processing - SIMD, inc Crypto
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 781be1e219..7b5db15861 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1559,6 +1559,13 @@ static inline void neon_store_reg64(TCGv_i64 var, int reg)
     tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
 }
 
+static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
+{
+    TCGv_ptr ret = tcg_temp_new_ptr();
+    tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
+    return ret;
+}
+
 #define tcg_gen_ld_f32 tcg_gen_ld_i32
 #define tcg_gen_ld_f64 tcg_gen_ld_i64
 #define tcg_gen_st_f32 tcg_gen_st_i32
@@ -5597,6 +5604,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
     int u;
     uint32_t imm, mask;
     TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
+    TCGv_ptr ptr1, ptr2, ptr3;
     TCGv_i64 tmp64;
 
     /* FIXME: this access check should not take precedence over UNDEF
@@ -5643,34 +5651,34 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
                 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) {
                     return 1;
                 }
-                tmp = tcg_const_i32(rd);
-                tmp2 = tcg_const_i32(rn);
-                tmp3 = tcg_const_i32(rm);
+                ptr1 = vfp_reg_ptr(true, rd);
+                ptr2 = vfp_reg_ptr(true, rn);
+                ptr3 = vfp_reg_ptr(true, rm);
                 tmp4 = tcg_const_i32(size);
-                gen_helper_crypto_sha1_3reg(cpu_env, tmp, tmp2, tmp3, tmp4);
+                gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4);
                 tcg_temp_free_i32(tmp4);
             } else { /* SHA-256 */
                 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA256) || size == 3) {
                     return 1;
                 }
-                tmp = tcg_const_i32(rd);
-                tmp2 = tcg_const_i32(rn);
-                tmp3 = tcg_const_i32(rm);
+                ptr1 = vfp_reg_ptr(true, rd);
+                ptr2 = vfp_reg_ptr(true, rn);
+                ptr3 = vfp_reg_ptr(true, rm);
                 switch (size) {
                 case 0:
-                    gen_helper_crypto_sha256h(cpu_env, tmp, tmp2, tmp3);
+                    gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
                     break;
                 case 1:
-                    gen_helper_crypto_sha256h2(cpu_env, tmp, tmp2, tmp3);
+                    gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
                     break;
                 case 2:
-                    gen_helper_crypto_sha256su1(cpu_env, tmp, tmp2, tmp3);
+                    gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
                     break;
                 }
             }
-            tcg_temp_free_i32(tmp);
-            tcg_temp_free_i32(tmp2);
-            tcg_temp_free_i32(tmp3);
+            tcg_temp_free_ptr(ptr1);
+            tcg_temp_free_ptr(ptr2);
+            tcg_temp_free_ptr(ptr3);
             return 0;
         }
         if (size == 3 && op != NEON_3R_LOGIC) {
@@ -7159,8 +7167,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
                         || ((rm | rd) & 1)) {
                         return 1;
                     }
-                    tmp = tcg_const_i32(rd);
-                    tmp2 = tcg_const_i32(rm);
+                    ptr1 = vfp_reg_ptr(true, rd);
+                    ptr2 = vfp_reg_ptr(true, rm);
 
                      /* Bit 6 is the lowest opcode bit; it distinguishes between
                       * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
@@ -7168,12 +7176,12 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
                     tmp3 = tcg_const_i32(extract32(insn, 6, 1));
 
                     if (op == NEON_2RM_AESE) {
-                        gen_helper_crypto_aese(cpu_env, tmp, tmp2, tmp3);
+                        gen_helper_crypto_aese(ptr1, ptr2, tmp3);
                     } else {
-                        gen_helper_crypto_aesmc(cpu_env, tmp, tmp2, tmp3);
+                        gen_helper_crypto_aesmc(ptr1, ptr2, tmp3);
                     }
-                    tcg_temp_free_i32(tmp);
-                    tcg_temp_free_i32(tmp2);
+                    tcg_temp_free_ptr(ptr1);
+                    tcg_temp_free_ptr(ptr2);
                     tcg_temp_free_i32(tmp3);
                     break;
                 case NEON_2RM_SHA1H:
@@ -7181,13 +7189,13 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
                         || ((rm | rd) & 1)) {
                         return 1;
                     }
-                    tmp = tcg_const_i32(rd);
-                    tmp2 = tcg_const_i32(rm);
+                    ptr1 = vfp_reg_ptr(true, rd);
+                    ptr2 = vfp_reg_ptr(true, rm);
 
-                    gen_helper_crypto_sha1h(cpu_env, tmp, tmp2);
+                    gen_helper_crypto_sha1h(ptr1, ptr2);
 
-                    tcg_temp_free_i32(tmp);
-                    tcg_temp_free_i32(tmp2);
+                    tcg_temp_free_ptr(ptr1);
+                    tcg_temp_free_ptr(ptr2);
                     break;
                 case NEON_2RM_SHA1SU1:
                     if ((rm | rd) & 1) {
@@ -7201,15 +7209,15 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
                     } else if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) {
                         return 1;
                     }
-                    tmp = tcg_const_i32(rd);
-                    tmp2 = tcg_const_i32(rm);
+                    ptr1 = vfp_reg_ptr(true, rd);
+                    ptr2 = vfp_reg_ptr(true, rm);
                     if (q) {
-                        gen_helper_crypto_sha256su0(cpu_env, tmp, tmp2);
+                        gen_helper_crypto_sha256su0(ptr1, ptr2);
                     } else {
-                        gen_helper_crypto_sha1su1(cpu_env, tmp, tmp2);
+                        gen_helper_crypto_sha1su1(ptr1, ptr2);
                     }
-                    tcg_temp_free_i32(tmp);
-                    tcg_temp_free_i32(tmp2);
+                    tcg_temp_free_ptr(ptr1);
+                    tcg_temp_free_ptr(ptr2);
                     break;
                 default:
                 elementwise:
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v2 03/16] target/arm: Use pointers in neon zip/uzp helpers
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 01/16] target/arm: Mark disas_set_insn_syndrome inline Richard Henderson
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 02/16] target/arm: Use pointers in crypto helpers Richard Henderson
@ 2018-01-19  4:54 ` Richard Henderson
  2018-01-22 10:44   ` Alex Bennée
  2018-01-22 10:44   ` Alex Bennée
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 04/16] target/arm: Use pointers in neon tbl helper Richard Henderson
                   ` (15 subsequent siblings)
  18 siblings, 2 replies; 46+ messages in thread
From: Richard Henderson @ 2018-01-19  4:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Rather than passing regnos to the helpers, pass pointers to the
vector registers directly.  This eliminates the need to pass in
the environment pointer and reduces the number of places that
directly access env->vfp.regs[].

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/helper.h      |  20 +++---
 target/arm/neon_helper.c | 162 +++++++++++++++++++++++++----------------------
 target/arm/translate.c   |  42 ++++++------
 3 files changed, 120 insertions(+), 104 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index 688380af6b..dbdc38fcb7 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -511,16 +511,16 @@ DEF_HELPER_3(iwmmxt_muladdsl, i64, i64, i32, i32)
 DEF_HELPER_3(iwmmxt_muladdsw, i64, i64, i32, i32)
 DEF_HELPER_3(iwmmxt_muladdswl, i64, i64, i32, i32)
 
-DEF_HELPER_3(neon_unzip8, void, env, i32, i32)
-DEF_HELPER_3(neon_unzip16, void, env, i32, i32)
-DEF_HELPER_3(neon_qunzip8, void, env, i32, i32)
-DEF_HELPER_3(neon_qunzip16, void, env, i32, i32)
-DEF_HELPER_3(neon_qunzip32, void, env, i32, i32)
-DEF_HELPER_3(neon_zip8, void, env, i32, i32)
-DEF_HELPER_3(neon_zip16, void, env, i32, i32)
-DEF_HELPER_3(neon_qzip8, void, env, i32, i32)
-DEF_HELPER_3(neon_qzip16, void, env, i32, i32)
-DEF_HELPER_3(neon_qzip32, void, env, i32, i32)
+DEF_HELPER_FLAGS_2(neon_unzip8, TCG_CALL_NO_RWG, void, ptr, ptr)
+DEF_HELPER_FLAGS_2(neon_unzip16, TCG_CALL_NO_RWG, void, ptr, ptr)
+DEF_HELPER_FLAGS_2(neon_qunzip8, TCG_CALL_NO_RWG, void, ptr, ptr)
+DEF_HELPER_FLAGS_2(neon_qunzip16, TCG_CALL_NO_RWG, void, ptr, ptr)
+DEF_HELPER_FLAGS_2(neon_qunzip32, TCG_CALL_NO_RWG, void, ptr, ptr)
+DEF_HELPER_FLAGS_2(neon_zip8, TCG_CALL_NO_RWG, void, ptr, ptr)
+DEF_HELPER_FLAGS_2(neon_zip16, TCG_CALL_NO_RWG, void, ptr, ptr)
+DEF_HELPER_FLAGS_2(neon_qzip8, TCG_CALL_NO_RWG, void, ptr, ptr)
+DEF_HELPER_FLAGS_2(neon_qzip16, TCG_CALL_NO_RWG, void, ptr, ptr)
+DEF_HELPER_FLAGS_2(neon_qzip32, TCG_CALL_NO_RWG, void, ptr, ptr)
 
 DEF_HELPER_FLAGS_3(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
 DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c
index ebdf7c9b10..689491cad3 100644
--- a/target/arm/neon_helper.c
+++ b/target/arm/neon_helper.c
@@ -2027,12 +2027,12 @@ uint64_t HELPER(neon_acgt_f64)(uint64_t a, uint64_t b, void *fpstp)
 
 #define ELEM(V, N, SIZE) (((V) >> ((N) * (SIZE))) & ((1ull << (SIZE)) - 1))
 
-void HELPER(neon_qunzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qunzip8)(void *vd, void *vm)
 {
-    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
-    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
-    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
-    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
+    uint64_t *rd = vd, *rm = vm;
+    uint64_t zd0 = rd[0], zd1 = rd[1];
+    uint64_t zm0 = rm[0], zm1 = rm[1];
+
     uint64_t d0 = ELEM(zd0, 0, 8) | (ELEM(zd0, 2, 8) << 8)
         | (ELEM(zd0, 4, 8) << 16) | (ELEM(zd0, 6, 8) << 24)
         | (ELEM(zd1, 0, 8) << 32) | (ELEM(zd1, 2, 8) << 40)
@@ -2049,18 +2049,19 @@ void HELPER(neon_qunzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
         | (ELEM(zm0, 5, 8) << 16) | (ELEM(zm0, 7, 8) << 24)
         | (ELEM(zm1, 1, 8) << 32) | (ELEM(zm1, 3, 8) << 40)
         | (ELEM(zm1, 5, 8) << 48) | (ELEM(zm1, 7, 8) << 56);
-    env->vfp.regs[rm] = make_float64(m0);
-    env->vfp.regs[rm + 1] = make_float64(m1);
-    env->vfp.regs[rd] = make_float64(d0);
-    env->vfp.regs[rd + 1] = make_float64(d1);
+
+    rm[0] = m0;
+    rm[1] = m1;
+    rd[0] = d0;
+    rd[1] = d1;
 }
 
-void HELPER(neon_qunzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qunzip16)(void *vd, void *vm)
 {
-    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
-    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
-    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
-    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
+    uint64_t *rd = vd, *rm = vm;
+    uint64_t zd0 = rd[0], zd1 = rd[1];
+    uint64_t zm0 = rm[0], zm1 = rm[1];
+
     uint64_t d0 = ELEM(zd0, 0, 16) | (ELEM(zd0, 2, 16) << 16)
         | (ELEM(zd1, 0, 16) << 32) | (ELEM(zd1, 2, 16) << 48);
     uint64_t d1 = ELEM(zm0, 0, 16) | (ELEM(zm0, 2, 16) << 16)
@@ -2069,32 +2070,35 @@ void HELPER(neon_qunzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
         | (ELEM(zd1, 1, 16) << 32) | (ELEM(zd1, 3, 16) << 48);
     uint64_t m1 = ELEM(zm0, 1, 16) | (ELEM(zm0, 3, 16) << 16)
         | (ELEM(zm1, 1, 16) << 32) | (ELEM(zm1, 3, 16) << 48);
-    env->vfp.regs[rm] = make_float64(m0);
-    env->vfp.regs[rm + 1] = make_float64(m1);
-    env->vfp.regs[rd] = make_float64(d0);
-    env->vfp.regs[rd + 1] = make_float64(d1);
+
+    rm[0] = m0;
+    rm[1] = m1;
+    rd[0] = d0;
+    rd[1] = d1;
 }
 
-void HELPER(neon_qunzip32)(CPUARMState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qunzip32)(void *vd, void *vm)
 {
-    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
-    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
-    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
-    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
+    uint64_t *rd = vd, *rm = vm;
+    uint64_t zd0 = rd[0], zd1 = rd[1];
+    uint64_t zm0 = rm[0], zm1 = rm[1];
+
     uint64_t d0 = ELEM(zd0, 0, 32) | (ELEM(zd1, 0, 32) << 32);
     uint64_t d1 = ELEM(zm0, 0, 32) | (ELEM(zm1, 0, 32) << 32);
     uint64_t m0 = ELEM(zd0, 1, 32) | (ELEM(zd1, 1, 32) << 32);
     uint64_t m1 = ELEM(zm0, 1, 32) | (ELEM(zm1, 1, 32) << 32);
-    env->vfp.regs[rm] = make_float64(m0);
-    env->vfp.regs[rm + 1] = make_float64(m1);
-    env->vfp.regs[rd] = make_float64(d0);
-    env->vfp.regs[rd + 1] = make_float64(d1);
+
+    rm[0] = m0;
+    rm[1] = m1;
+    rd[0] = d0;
+    rd[1] = d1;
 }
 
-void HELPER(neon_unzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_unzip8)(void *vd, void *vm)
 {
-    uint64_t zm = float64_val(env->vfp.regs[rm]);
-    uint64_t zd = float64_val(env->vfp.regs[rd]);
+    uint64_t *rd = vd, *rm = vm;
+    uint64_t zd = rd[0], zm = rm[0];
+
     uint64_t d0 = ELEM(zd, 0, 8) | (ELEM(zd, 2, 8) << 8)
         | (ELEM(zd, 4, 8) << 16) | (ELEM(zd, 6, 8) << 24)
         | (ELEM(zm, 0, 8) << 32) | (ELEM(zm, 2, 8) << 40)
@@ -2103,28 +2107,31 @@ void HELPER(neon_unzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
         | (ELEM(zd, 5, 8) << 16) | (ELEM(zd, 7, 8) << 24)
         | (ELEM(zm, 1, 8) << 32) | (ELEM(zm, 3, 8) << 40)
         | (ELEM(zm, 5, 8) << 48) | (ELEM(zm, 7, 8) << 56);
-    env->vfp.regs[rm] = make_float64(m0);
-    env->vfp.regs[rd] = make_float64(d0);
+
+    rm[0] = m0;
+    rd[0] = d0;
 }
 
-void HELPER(neon_unzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_unzip16)(void *vd, void *vm)
 {
-    uint64_t zm = float64_val(env->vfp.regs[rm]);
-    uint64_t zd = float64_val(env->vfp.regs[rd]);
+    uint64_t *rd = vd, *rm = vm;
+    uint64_t zd = rd[0], zm = rm[0];
+
     uint64_t d0 = ELEM(zd, 0, 16) | (ELEM(zd, 2, 16) << 16)
         | (ELEM(zm, 0, 16) << 32) | (ELEM(zm, 2, 16) << 48);
     uint64_t m0 = ELEM(zd, 1, 16) | (ELEM(zd, 3, 16) << 16)
         | (ELEM(zm, 1, 16) << 32) | (ELEM(zm, 3, 16) << 48);
-    env->vfp.regs[rm] = make_float64(m0);
-    env->vfp.regs[rd] = make_float64(d0);
+
+    rm[0] = m0;
+    rd[0] = d0;
 }
 
-void HELPER(neon_qzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qzip8)(void *vd, void *vm)
 {
-    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
-    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
-    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
-    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
+    uint64_t *rd = vd, *rm = vm;
+    uint64_t zd0 = rd[0], zd1 = rd[1];
+    uint64_t zm0 = rm[0], zm1 = rm[1];
+
     uint64_t d0 = ELEM(zd0, 0, 8) | (ELEM(zm0, 0, 8) << 8)
         | (ELEM(zd0, 1, 8) << 16) | (ELEM(zm0, 1, 8) << 24)
         | (ELEM(zd0, 2, 8) << 32) | (ELEM(zm0, 2, 8) << 40)
@@ -2141,18 +2148,19 @@ void HELPER(neon_qzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
         | (ELEM(zd1, 5, 8) << 16) | (ELEM(zm1, 5, 8) << 24)
         | (ELEM(zd1, 6, 8) << 32) | (ELEM(zm1, 6, 8) << 40)
         | (ELEM(zd1, 7, 8) << 48) | (ELEM(zm1, 7, 8) << 56);
-    env->vfp.regs[rm] = make_float64(m0);
-    env->vfp.regs[rm + 1] = make_float64(m1);
-    env->vfp.regs[rd] = make_float64(d0);
-    env->vfp.regs[rd + 1] = make_float64(d1);
+
+    rm[0] = m0;
+    rm[1] = m1;
+    rd[0] = d0;
+    rd[1] = d1;
 }
 
-void HELPER(neon_qzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qzip16)(void *vd, void *vm)
 {
-    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
-    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
-    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
-    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
+    uint64_t *rd = vd, *rm = vm;
+    uint64_t zd0 = rd[0], zd1 = rd[1];
+    uint64_t zm0 = rm[0], zm1 = rm[1];
+
     uint64_t d0 = ELEM(zd0, 0, 16) | (ELEM(zm0, 0, 16) << 16)
         | (ELEM(zd0, 1, 16) << 32) | (ELEM(zm0, 1, 16) << 48);
     uint64_t d1 = ELEM(zd0, 2, 16) | (ELEM(zm0, 2, 16) << 16)
@@ -2161,32 +2169,35 @@ void HELPER(neon_qzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
         | (ELEM(zd1, 1, 16) << 32) | (ELEM(zm1, 1, 16) << 48);
     uint64_t m1 = ELEM(zd1, 2, 16) | (ELEM(zm1, 2, 16) << 16)
         | (ELEM(zd1, 3, 16) << 32) | (ELEM(zm1, 3, 16) << 48);
-    env->vfp.regs[rm] = make_float64(m0);
-    env->vfp.regs[rm + 1] = make_float64(m1);
-    env->vfp.regs[rd] = make_float64(d0);
-    env->vfp.regs[rd + 1] = make_float64(d1);
+
+    rm[0] = m0;
+    rm[1] = m1;
+    rd[0] = d0;
+    rd[1] = d1;
 }
 
-void HELPER(neon_qzip32)(CPUARMState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qzip32)(void *vd, void *vm)
 {
-    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
-    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
-    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
-    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
+    uint64_t *rd = vd, *rm = vm;
+    uint64_t zd0 = rd[0], zd1 = rd[1];
+    uint64_t zm0 = rm[0], zm1 = rm[1];
+
     uint64_t d0 = ELEM(zd0, 0, 32) | (ELEM(zm0, 0, 32) << 32);
     uint64_t d1 = ELEM(zd0, 1, 32) | (ELEM(zm0, 1, 32) << 32);
     uint64_t m0 = ELEM(zd1, 0, 32) | (ELEM(zm1, 0, 32) << 32);
     uint64_t m1 = ELEM(zd1, 1, 32) | (ELEM(zm1, 1, 32) << 32);
-    env->vfp.regs[rm] = make_float64(m0);
-    env->vfp.regs[rm + 1] = make_float64(m1);
-    env->vfp.regs[rd] = make_float64(d0);
-    env->vfp.regs[rd + 1] = make_float64(d1);
+
+    rm[0] = m0;
+    rm[1] = m1;
+    rd[0] = d0;
+    rd[1] = d1;
 }
 
-void HELPER(neon_zip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_zip8)(void *vd, void *vm)
 {
-    uint64_t zm = float64_val(env->vfp.regs[rm]);
-    uint64_t zd = float64_val(env->vfp.regs[rd]);
+    uint64_t *rd = vd, *rm = vm;
+    uint64_t zd = rd[0], zm = rm[0];
+
     uint64_t d0 = ELEM(zd, 0, 8) | (ELEM(zm, 0, 8) << 8)
         | (ELEM(zd, 1, 8) << 16) | (ELEM(zm, 1, 8) << 24)
         | (ELEM(zd, 2, 8) << 32) | (ELEM(zm, 2, 8) << 40)
@@ -2195,20 +2206,23 @@ void HELPER(neon_zip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
         | (ELEM(zd, 5, 8) << 16) | (ELEM(zm, 5, 8) << 24)
         | (ELEM(zd, 6, 8) << 32) | (ELEM(zm, 6, 8) << 40)
         | (ELEM(zd, 7, 8) << 48) | (ELEM(zm, 7, 8) << 56);
-    env->vfp.regs[rm] = make_float64(m0);
-    env->vfp.regs[rd] = make_float64(d0);
+
+    rm[0] = m0;
+    rd[0] = d0;
 }
 
-void HELPER(neon_zip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_zip16)(void *vd, void *vm)
 {
-    uint64_t zm = float64_val(env->vfp.regs[rm]);
-    uint64_t zd = float64_val(env->vfp.regs[rd]);
+    uint64_t *rd = vd, *rm = vm;
+    uint64_t zd = rd[0], zm = rm[0];
+
     uint64_t d0 = ELEM(zd, 0, 16) | (ELEM(zm, 0, 16) << 16)
         | (ELEM(zd, 1, 16) << 32) | (ELEM(zm, 1, 16) << 48);
     uint64_t m0 = ELEM(zd, 2, 16) | (ELEM(zm, 2, 16) << 16)
         | (ELEM(zd, 3, 16) << 32) | (ELEM(zm, 3, 16) << 48);
-    env->vfp.regs[rm] = make_float64(m0);
-    env->vfp.regs[rd] = make_float64(d0);
+
+    rm[0] = m0;
+    rd[0] = d0;
 }
 
 /* Helper function for 64 bit polynomial multiply case:
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 7b5db15861..6f02c56abb 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -4687,22 +4687,23 @@ static inline TCGv_i32 neon_get_scalar(int size, int reg)
 
 static int gen_neon_unzip(int rd, int rm, int size, int q)
 {
-    TCGv_i32 tmp, tmp2;
+    TCGv_ptr pd, pm;
+    
     if (!q && size == 2) {
         return 1;
     }
-    tmp = tcg_const_i32(rd);
-    tmp2 = tcg_const_i32(rm);
+    pd = vfp_reg_ptr(true, rd);
+    pm = vfp_reg_ptr(true, rm);
     if (q) {
         switch (size) {
         case 0:
-            gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
+            gen_helper_neon_qunzip8(pd, pm);
             break;
         case 1:
-            gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
+            gen_helper_neon_qunzip16(pd, pm);
             break;
         case 2:
-            gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
+            gen_helper_neon_qunzip32(pd, pm);
             break;
         default:
             abort();
@@ -4710,38 +4711,39 @@ static int gen_neon_unzip(int rd, int rm, int size, int q)
     } else {
         switch (size) {
         case 0:
-            gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
+            gen_helper_neon_unzip8(pd, pm);
             break;
         case 1:
-            gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
+            gen_helper_neon_unzip16(pd, pm);
             break;
         default:
             abort();
         }
     }
-    tcg_temp_free_i32(tmp);
-    tcg_temp_free_i32(tmp2);
+    tcg_temp_free_ptr(pd);
+    tcg_temp_free_ptr(pm);
     return 0;
 }
 
 static int gen_neon_zip(int rd, int rm, int size, int q)
 {
-    TCGv_i32 tmp, tmp2;
+    TCGv_ptr pd, pm;
+
     if (!q && size == 2) {
         return 1;
     }
-    tmp = tcg_const_i32(rd);
-    tmp2 = tcg_const_i32(rm);
+    pd = vfp_reg_ptr(true, rd);
+    pm = vfp_reg_ptr(true, rm);
     if (q) {
         switch (size) {
         case 0:
-            gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
+            gen_helper_neon_qzip8(pd, pm);
             break;
         case 1:
-            gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
+            gen_helper_neon_qzip16(pd, pm);
             break;
         case 2:
-            gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
+            gen_helper_neon_qzip32(pd, pm);
             break;
         default:
             abort();
@@ -4749,17 +4751,17 @@ static int gen_neon_zip(int rd, int rm, int size, int q)
     } else {
         switch (size) {
         case 0:
-            gen_helper_neon_zip8(cpu_env, tmp, tmp2);
+            gen_helper_neon_zip8(pd, pm);
             break;
         case 1:
-            gen_helper_neon_zip16(cpu_env, tmp, tmp2);
+            gen_helper_neon_zip16(pd, pm);
             break;
         default:
             abort();
         }
     }
-    tcg_temp_free_i32(tmp);
-    tcg_temp_free_i32(tmp2);
+    tcg_temp_free_ptr(pd);
+    tcg_temp_free_ptr(pm);
     return 0;
 }
 
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v2 04/16] target/arm: Use pointers in neon tbl helper
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
                   ` (2 preceding siblings ...)
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 03/16] target/arm: Use pointers in neon zip/uzp helpers Richard Henderson
@ 2018-01-19  4:54 ` Richard Henderson
  2018-01-22 10:52   ` Alex Bennée
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 05/16] target/arm: Change the type of vfp.regs Richard Henderson
                   ` (14 subsequent siblings)
  18 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2018-01-19  4:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Rather than passing a regno to the helper, pass pointers to the
vector register directly.  This eliminates the need to pass in
the environment pointer and reduces the number of places that
directly access env->vfp.regs[].

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/helper.h    |  2 +-
 target/arm/op_helper.c | 17 +++++++----------
 target/arm/translate.c |  8 ++++----
 3 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index dbdc38fcb7..5dec2e6262 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -188,7 +188,7 @@ DEF_HELPER_FLAGS_2(rsqrte_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
 DEF_HELPER_FLAGS_2(rsqrte_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
 DEF_HELPER_2(recpe_u32, i32, i32, ptr)
 DEF_HELPER_FLAGS_2(rsqrte_u32, TCG_CALL_NO_RWG, i32, i32, ptr)
-DEF_HELPER_5(neon_tbl, i32, env, i32, i32, i32, i32)
+DEF_HELPER_FLAGS_4(neon_tbl, TCG_CALL_NO_RWG, i32, i32, i32, ptr, i32)
 
 DEF_HELPER_3(shl_cc, i32, env, i32, i32)
 DEF_HELPER_3(shr_cc, i32, env, i32, i32)
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 712c5c55b6..a937e76710 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -54,20 +54,17 @@ static int exception_target_el(CPUARMState *env)
     return target_el;
 }
 
-uint32_t HELPER(neon_tbl)(CPUARMState *env, uint32_t ireg, uint32_t def,
-                          uint32_t rn, uint32_t maxindex)
+uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def, void *vn,
+                          uint32_t maxindex)
 {
-    uint32_t val;
-    uint32_t tmp;
-    int index;
-    int shift;
-    uint64_t *table;
-    table = (uint64_t *)&env->vfp.regs[rn];
+    uint32_t val, shift;
+    uint64_t *table = vn;
+
     val = 0;
     for (shift = 0; shift < 32; shift += 8) {
-        index = (ireg >> shift) & 0xff;
+        uint32_t index = (ireg >> shift) & 0xff;
         if (index < maxindex) {
-            tmp = (table[index >> 3] >> ((index & 7) << 3)) & 0xff;
+            uint32_t tmp = (table[index >> 3] >> ((index & 7) << 3)) & 0xff;
             val |= tmp << shift;
         } else {
             val |= def & (0xff << shift);
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 6f02c56abb..852d2a75b1 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -7544,9 +7544,9 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
                     tcg_gen_movi_i32(tmp, 0);
                 }
                 tmp2 = neon_load_reg(rm, 0);
-                tmp4 = tcg_const_i32(rn);
+                ptr1 = vfp_reg_ptr(true, rn);
                 tmp5 = tcg_const_i32(n);
-                gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5);
+                gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5);
                 tcg_temp_free_i32(tmp);
                 if (insn & (1 << 6)) {
                     tmp = neon_load_reg(rd, 1);
@@ -7555,9 +7555,9 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
                     tcg_gen_movi_i32(tmp, 0);
                 }
                 tmp3 = neon_load_reg(rm, 1);
-                gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5);
+                gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5);
                 tcg_temp_free_i32(tmp5);
-                tcg_temp_free_i32(tmp4);
+                tcg_temp_free_ptr(ptr1);
                 neon_store_reg(rd, 0, tmp2);
                 neon_store_reg(rd, 1, tmp3);
                 tcg_temp_free_i32(tmp);
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v2 05/16] target/arm: Change the type of vfp.regs
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
                   ` (3 preceding siblings ...)
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 04/16] target/arm: Use pointers in neon tbl helper Richard Henderson
@ 2018-01-19  4:54 ` Richard Henderson
  2018-01-22 10:56   ` Alex Bennée
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 06/16] target/arm: Add aa{32, 64}_vfp_{dreg, qreg} helpers Richard Henderson
                   ` (13 subsequent siblings)
  18 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2018-01-19  4:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

All direct users of this field want an integral value.  Drop all
of the extra casting between uint64_t and float64.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h           |  2 +-
 target/arm/arch_dump.c     |  4 ++--
 target/arm/helper.c        | 20 ++++++++++----------
 target/arm/machine.c       |  2 +-
 target/arm/translate-a64.c |  8 ++++----
 target/arm/translate.c     |  2 +-
 6 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 96316700dd..76ab7953a6 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -492,7 +492,7 @@ typedef struct CPUARMState {
          * the two execution states, and means we do not need to explicitly
          * map these registers when changing states.
          */
-        float64 regs[64];
+        uint64_t regs[64];
 
         uint32_t xregs[16];
         /* We store these fpcsr fields separately for convenience.  */
diff --git a/target/arm/arch_dump.c b/target/arm/arch_dump.c
index 9e5b2fb31c..0c43e0eef8 100644
--- a/target/arm/arch_dump.c
+++ b/target/arm/arch_dump.c
@@ -100,7 +100,7 @@ static int aarch64_write_elf64_prfpreg(WriteCoreDumpFunction f,
     aarch64_note_init(&note, s, "CORE", 5, NT_PRFPREG, sizeof(note.vfp));
 
     for (i = 0; i < 64; ++i) {
-        note.vfp.vregs[i] = cpu_to_dump64(s, float64_val(env->vfp.regs[i]));
+        note.vfp.vregs[i] = cpu_to_dump64(s, env->vfp.regs[i]);
     }
 
     if (s->dump_info.d_endian == ELFDATA2MSB) {
@@ -229,7 +229,7 @@ static int arm_write_elf32_vfp(WriteCoreDumpFunction f, CPUARMState *env,
     arm_note_init(&note, s, "LINUX", 6, NT_ARM_VFP, sizeof(note.vfp));
 
     for (i = 0; i < 32; ++i) {
-        note.vfp.vregs[i] = cpu_to_dump64(s, float64_val(env->vfp.regs[i]));
+        note.vfp.vregs[i] = cpu_to_dump64(s, env->vfp.regs[i]);
     }
 
     note.vfp.fpscr = cpu_to_dump32(s, vfp_get_fpscr(env));
diff --git a/target/arm/helper.c b/target/arm/helper.c
index c83c901a86..8fda797582 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -64,15 +64,15 @@ static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
     /* VFP data registers are always little-endian.  */
     nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
     if (reg < nregs) {
-        stfq_le_p(buf, env->vfp.regs[reg]);
+        stq_le_p(buf, env->vfp.regs[reg]);
         return 8;
     }
     if (arm_feature(env, ARM_FEATURE_NEON)) {
         /* Aliases for Q regs.  */
         nregs += 16;
         if (reg < nregs) {
-            stfq_le_p(buf, env->vfp.regs[(reg - 32) * 2]);
-            stfq_le_p(buf + 8, env->vfp.regs[(reg - 32) * 2 + 1]);
+            stq_le_p(buf, env->vfp.regs[(reg - 32) * 2]);
+            stq_le_p(buf + 8, env->vfp.regs[(reg - 32) * 2 + 1]);
             return 16;
         }
     }
@@ -90,14 +90,14 @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
 
     nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
     if (reg < nregs) {
-        env->vfp.regs[reg] = ldfq_le_p(buf);
+        env->vfp.regs[reg] = ldq_le_p(buf);
         return 8;
     }
     if (arm_feature(env, ARM_FEATURE_NEON)) {
         nregs += 16;
         if (reg < nregs) {
-            env->vfp.regs[(reg - 32) * 2] = ldfq_le_p(buf);
-            env->vfp.regs[(reg - 32) * 2 + 1] = ldfq_le_p(buf + 8);
+            env->vfp.regs[(reg - 32) * 2] = ldq_le_p(buf);
+            env->vfp.regs[(reg - 32) * 2 + 1] = ldq_le_p(buf + 8);
             return 16;
         }
     }
@@ -114,8 +114,8 @@ static int aarch64_fpu_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
     switch (reg) {
     case 0 ... 31:
         /* 128 bit FP register */
-        stfq_le_p(buf, env->vfp.regs[reg * 2]);
-        stfq_le_p(buf + 8, env->vfp.regs[reg * 2 + 1]);
+        stq_le_p(buf, env->vfp.regs[reg * 2]);
+        stq_le_p(buf + 8, env->vfp.regs[reg * 2 + 1]);
         return 16;
     case 32:
         /* FPSR */
@@ -135,8 +135,8 @@ static int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
     switch (reg) {
     case 0 ... 31:
         /* 128 bit FP register */
-        env->vfp.regs[reg * 2] = ldfq_le_p(buf);
-        env->vfp.regs[reg * 2 + 1] = ldfq_le_p(buf + 8);
+        env->vfp.regs[reg * 2] = ldq_le_p(buf);
+        env->vfp.regs[reg * 2 + 1] = ldq_le_p(buf + 8);
         return 16;
     case 32:
         /* FPSR */
diff --git a/target/arm/machine.c b/target/arm/machine.c
index 176274629c..a85c2430d3 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -50,7 +50,7 @@ static const VMStateDescription vmstate_vfp = {
     .minimum_version_id = 3,
     .needed = vfp_needed,
     .fields = (VMStateField[]) {
-        VMSTATE_FLOAT64_ARRAY(env.vfp.regs, ARMCPU, 64),
+        VMSTATE_UINT64_ARRAY(env.vfp.regs, ARMCPU, 64),
         /* The xregs array is a little awkward because element 1 (FPSCR)
          * requires a specific accessor, so we have to split it up in
          * the vmstate:
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 6d9b3af64c..c14fb4185c 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -165,12 +165,12 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
     if (flags & CPU_DUMP_FPU) {
         int numvfpregs = 32;
         for (i = 0; i < numvfpregs; i += 2) {
-            uint64_t vlo = float64_val(env->vfp.regs[i * 2]);
-            uint64_t vhi = float64_val(env->vfp.regs[(i * 2) + 1]);
+            uint64_t vlo = env->vfp.regs[i * 2];
+            uint64_t vhi = env->vfp.regs[(i * 2) + 1];
             cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 " ",
                         i, vhi, vlo);
-            vlo = float64_val(env->vfp.regs[(i + 1) * 2]);
-            vhi = float64_val(env->vfp.regs[((i + 1) * 2) + 1]);
+            vlo = env->vfp.regs[(i + 1) * 2];
+            vhi = env->vfp.regs[((i + 1) * 2) + 1];
             cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "\n",
                         i + 1, vhi, vlo);
         }
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 852d2a75b1..cfe49bf579 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -12572,7 +12572,7 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
             numvfpregs += 16;
         }
         for (i = 0; i < numvfpregs; i++) {
-            uint64_t v = float64_val(env->vfp.regs[i]);
+            uint64_t v = env->vfp.regs[i];
             cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
                         i * 2, (uint32_t)v,
                         i * 2 + 1, (uint32_t)(v >> 32),
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v2 06/16] target/arm: Add aa{32, 64}_vfp_{dreg, qreg} helpers
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
                   ` (4 preceding siblings ...)
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 05/16] target/arm: Change the type of vfp.regs Richard Henderson
@ 2018-01-19  4:54 ` Richard Henderson
  2018-01-22 11:02   ` Alex Bennée
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 07/16] vmstate: Add VMSTATE_UINT64_SUB_ARRAY Richard Henderson
                   ` (12 subsequent siblings)
  18 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2018-01-19  4:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Helpers that return a pointer into env->vfp.regs so that we isolate
the logic of how to index the regs array for different cpu modes.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h           | 27 +++++++++++++++++++++++++++
 linux-user/signal.c        | 22 ++++++++++++----------
 target/arm/arch_dump.c     |  8 +++++---
 target/arm/helper-a64.c    |  5 +++--
 target/arm/helper.c        | 32 ++++++++++++++++++++------------
 target/arm/kvm32.c         |  4 ++--
 target/arm/kvm64.c         | 31 ++++++++++---------------------
 target/arm/translate-a64.c | 25 ++++++++-----------------
 target/arm/translate.c     | 16 +++++++++-------
 9 files changed, 96 insertions(+), 74 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 76ab7953a6..7d396606f3 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2885,4 +2885,31 @@ static inline void *arm_get_el_change_hook_opaque(ARMCPU *cpu)
     return cpu->el_change_hook_opaque;
 }
 
+/**
+ * aa32_vfp_dreg:
+ * Return a pointer to the Dn register within env in 32-bit mode.
+ */
+static inline uint64_t *aa32_vfp_dreg(CPUARMState *env, unsigned regno)
+{
+    return &env->vfp.regs[regno];
+}
+
+/**
+ * aa32_vfp_qreg:
+ * Return a pointer to the Qn register within env in 32-bit mode.
+ */
+static inline uint64_t *aa32_vfp_qreg(CPUARMState *env, unsigned regno)
+{
+    return &env->vfp.regs[2 * regno];
+}
+
+/**
+ * aa64_vfp_qreg:
+ * Return a pointer to the Qn register within env in 64-bit mode.
+ */
+static inline uint64_t *aa64_vfp_qreg(CPUARMState *env, unsigned regno)
+{
+    return &env->vfp.regs[2 * regno];
+}
+
 #endif
diff --git a/linux-user/signal.c b/linux-user/signal.c
index f85f0dd780..5321f9e795 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1487,12 +1487,13 @@ static int target_setup_sigframe(struct target_rt_sigframe *sf,
     }
 
     for (i = 0; i < 32; i++) {
+        uint64_t *q = aa64_vfp_qreg(env, i);
 #ifdef TARGET_WORDS_BIGENDIAN
-        __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
-        __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
+        __put_user(q[0], &aux->fpsimd.vregs[i * 2 + 1]);
+        __put_user(q[1], &aux->fpsimd.vregs[i * 2]);
 #else
-        __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
-        __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
+        __put_user(q[0], &aux->fpsimd.vregs[i * 2]);
+        __put_user(q[1], &aux->fpsimd.vregs[i * 2 + 1]);
 #endif
     }
     __put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr);
@@ -1539,12 +1540,13 @@ static int target_restore_sigframe(CPUARMState *env,
     }
 
     for (i = 0; i < 32; i++) {
+        uint64_t *q = aa64_vfp_qreg(env, i);
 #ifdef TARGET_WORDS_BIGENDIAN
-        __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
-        __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
+        __get_user(q[0], &aux->fpsimd.vregs[i * 2 + 1]);
+        __get_user(q[1], &aux->fpsimd.vregs[i * 2]);
 #else
-        __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
-        __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
+        __get_user(q[0], &aux->fpsimd.vregs[i * 2]);
+        __get_user(q[1], &aux->fpsimd.vregs[i * 2 + 1]);
 #endif
     }
     __get_user(fpsr, &aux->fpsimd.fpsr);
@@ -1903,7 +1905,7 @@ static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
     __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
     __put_user(sizeof(*vfpframe), &vfpframe->size);
     for (i = 0; i < 32; i++) {
-        __put_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
+        __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
     }
     __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
     __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
@@ -2210,7 +2212,7 @@ static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
         return 0;
     }
     for (i = 0; i < 32; i++) {
-        __get_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
+        __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
     }
     __get_user(fpscr, &vfpframe->ufp.fpscr);
     vfp_set_fpscr(env, fpscr);
diff --git a/target/arm/arch_dump.c b/target/arm/arch_dump.c
index 0c43e0eef8..26a2c09868 100644
--- a/target/arm/arch_dump.c
+++ b/target/arm/arch_dump.c
@@ -99,8 +99,10 @@ static int aarch64_write_elf64_prfpreg(WriteCoreDumpFunction f,
 
     aarch64_note_init(&note, s, "CORE", 5, NT_PRFPREG, sizeof(note.vfp));
 
-    for (i = 0; i < 64; ++i) {
-        note.vfp.vregs[i] = cpu_to_dump64(s, env->vfp.regs[i]);
+    for (i = 0; i < 32; ++i) {
+        uint64_t *q = aa64_vfp_qreg(env, i);
+        note.vfp.vregs[2*i + 0] = cpu_to_dump64(s, q[0]);
+        note.vfp.vregs[2*i + 1] = cpu_to_dump64(s, q[1]);
     }
 
     if (s->dump_info.d_endian == ELFDATA2MSB) {
@@ -229,7 +231,7 @@ static int arm_write_elf32_vfp(WriteCoreDumpFunction f, CPUARMState *env,
     arm_note_init(&note, s, "LINUX", 6, NT_ARM_VFP, sizeof(note.vfp));
 
     for (i = 0; i < 32; ++i) {
-        note.vfp.vregs[i] = cpu_to_dump64(s, env->vfp.regs[i]);
+        note.vfp.vregs[i] = cpu_to_dump64(s, *aa32_vfp_dreg(env, i));
     }
 
     note.vfp.fpscr = cpu_to_dump32(s, vfp_get_fpscr(env));
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index 3e00a9ead1..06fd321fae 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -153,13 +153,14 @@ uint64_t HELPER(simd_tbl)(CPUARMState *env, uint64_t result, uint64_t indices,
         if (index < 16 * numregs) {
             /* Convert index (a byte offset into the virtual table
              * which is a series of 128-bit vectors concatenated)
-             * into the correct vfp.regs[] element plus a bit offset
+             * into the correct register element plus a bit offset
              * into that element, bearing in mind that the table
              * can wrap around from V31 to V0.
              */
             int elt = (rn * 2 + (index >> 3)) % 64;
             int bitidx = (index & 7) * 8;
-            uint64_t val = extract64(env->vfp.regs[elt], bitidx, 8);
+            uint64_t *q = aa64_vfp_qreg(env, elt >> 1);
+            uint64_t val = extract64(q[elt & 1], bitidx, 8);
 
             result = deposit64(result, shift, 8, val);
         }
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 8fda797582..6705903301 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -64,15 +64,16 @@ static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
     /* VFP data registers are always little-endian.  */
     nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
     if (reg < nregs) {
-        stq_le_p(buf, env->vfp.regs[reg]);
+        stq_le_p(buf, *aa32_vfp_dreg(env, reg));
         return 8;
     }
     if (arm_feature(env, ARM_FEATURE_NEON)) {
         /* Aliases for Q regs.  */
         nregs += 16;
         if (reg < nregs) {
-            stq_le_p(buf, env->vfp.regs[(reg - 32) * 2]);
-            stq_le_p(buf + 8, env->vfp.regs[(reg - 32) * 2 + 1]);
+            uint64_t *q = aa32_vfp_qreg(env, reg - 32);
+            stq_le_p(buf, q[0]);
+            stq_le_p(buf + 8, q[1]);
             return 16;
         }
     }
@@ -90,14 +91,15 @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
 
     nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
     if (reg < nregs) {
-        env->vfp.regs[reg] = ldq_le_p(buf);
+        *aa32_vfp_dreg(env, reg) = ldq_le_p(buf);
         return 8;
     }
     if (arm_feature(env, ARM_FEATURE_NEON)) {
         nregs += 16;
         if (reg < nregs) {
-            env->vfp.regs[(reg - 32) * 2] = ldq_le_p(buf);
-            env->vfp.regs[(reg - 32) * 2 + 1] = ldq_le_p(buf + 8);
+            uint64_t *q = aa32_vfp_qreg(env, reg - 32);
+            q[0] = ldq_le_p(buf);
+            q[1] = ldq_le_p(buf + 8);
             return 16;
         }
     }
@@ -114,9 +116,12 @@ static int aarch64_fpu_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
     switch (reg) {
     case 0 ... 31:
         /* 128 bit FP register */
-        stq_le_p(buf, env->vfp.regs[reg * 2]);
-        stq_le_p(buf + 8, env->vfp.regs[reg * 2 + 1]);
-        return 16;
+        {
+            uint64_t *q = aa64_vfp_qreg(env, reg);
+            stq_le_p(buf, q[0]);
+            stq_le_p(buf + 8, q[1]);
+            return 16;
+        }
     case 32:
         /* FPSR */
         stl_p(buf, vfp_get_fpsr(env));
@@ -135,9 +140,12 @@ static int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
     switch (reg) {
     case 0 ... 31:
         /* 128 bit FP register */
-        env->vfp.regs[reg * 2] = ldq_le_p(buf);
-        env->vfp.regs[reg * 2 + 1] = ldq_le_p(buf + 8);
-        return 16;
+        {
+            uint64_t *q = aa64_vfp_qreg(env, reg);
+            q[0] = ldq_le_p(buf);
+            q[1] = ldq_le_p(buf + 8);
+            return 16;
+        }
     case 32:
         /* FPSR */
         vfp_set_fpsr(env, ldl_p(buf));
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
index f925a21481..f77c9c494b 100644
--- a/target/arm/kvm32.c
+++ b/target/arm/kvm32.c
@@ -358,7 +358,7 @@ int kvm_arch_put_registers(CPUState *cs, int level)
     /* VFP registers */
     r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
     for (i = 0; i < 32; i++) {
-        r.addr = (uintptr_t)(&env->vfp.regs[i]);
+        r.addr = (uintptr_t)aa32_vfp_dreg(env, i);
         ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
         if (ret) {
             return ret;
@@ -445,7 +445,7 @@ int kvm_arch_get_registers(CPUState *cs)
     /* VFP registers */
     r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
     for (i = 0; i < 32; i++) {
-        r.addr = (uintptr_t)(&env->vfp.regs[i]);
+        r.addr = (uintptr_t)aa32_vfp_dreg(env, i);
         ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
         if (ret) {
             return ret;
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index 6554c30007..ac728494a4 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -696,21 +696,16 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         }
     }
 
-    /* Advanced SIMD and FP registers
-     * We map Qn = regs[2n+1]:regs[2n]
-     */
+    /* Advanced SIMD and FP registers. */
     for (i = 0; i < 32; i++) {
-        int rd = i << 1;
-        uint64_t fp_val[2];
+        uint64_t *q = aa64_vfp_qreg(env, i);
 #ifdef HOST_WORDS_BIGENDIAN
-        fp_val[0] = env->vfp.regs[rd + 1];
-        fp_val[1] = env->vfp.regs[rd];
+        uint64_t fp_val[2] = { q[1], q[0] };
+        reg.addr = (uintptr_t)fp_val;
 #else
-        fp_val[1] = env->vfp.regs[rd + 1];
-        fp_val[0] = env->vfp.regs[rd];
+        reg.addr = (uintptr_t)q;
 #endif
         reg.id = AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]);
-        reg.addr = (uintptr_t)(&fp_val);
         ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
         if (ret) {
             return ret;
@@ -837,24 +832,18 @@ int kvm_arch_get_registers(CPUState *cs)
         env->spsr = env->banked_spsr[i];
     }
 
-    /* Advanced SIMD and FP registers
-     * We map Qn = regs[2n+1]:regs[2n]
-     */
+    /* Advanced SIMD and FP registers */
     for (i = 0; i < 32; i++) {
-        uint64_t fp_val[2];
+        uint64_t *q = aa64_vfp_qreg(env, i);
         reg.id = AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]);
-        reg.addr = (uintptr_t)(&fp_val);
+        reg.addr = (uintptr_t)q;
         ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
         if (ret) {
             return ret;
         } else {
-            int rd = i << 1;
 #ifdef HOST_WORDS_BIGENDIAN
-            env->vfp.regs[rd + 1] = fp_val[0];
-            env->vfp.regs[rd] = fp_val[1];
-#else
-            env->vfp.regs[rd + 1] = fp_val[1];
-            env->vfp.regs[rd] = fp_val[0];
+            uint64_t t;
+            t = q[0], q[0] = q[1], q[1] = t;
 #endif
         }
     }
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index c14fb4185c..eed64c73e5 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -164,15 +164,12 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
 
     if (flags & CPU_DUMP_FPU) {
         int numvfpregs = 32;
-        for (i = 0; i < numvfpregs; i += 2) {
-            uint64_t vlo = env->vfp.regs[i * 2];
-            uint64_t vhi = env->vfp.regs[(i * 2) + 1];
-            cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 " ",
-                        i, vhi, vlo);
-            vlo = env->vfp.regs[(i + 1) * 2];
-            vhi = env->vfp.regs[((i + 1) * 2) + 1];
-            cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "\n",
-                        i + 1, vhi, vlo);
+        for (i = 0; i < numvfpregs; i++) {
+            uint64_t *q = aa64_vfp_qreg(env, i);
+            uint64_t vlo = q[0];
+            uint64_t vhi = q[1];
+            cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "%c",
+                        i, vhi, vlo, (i & 1 ? '\n' : ' '));
         }
         cpu_fprintf(f, "FPCR: %08x  FPSR: %08x\n",
                     vfp_get_fpcr(env), vfp_get_fpsr(env));
@@ -558,19 +555,13 @@ static TCGv_ptr vec_full_reg_ptr(DisasContext *s, int regno)
  */
 static inline int fp_reg_offset(DisasContext *s, int regno, TCGMemOp size)
 {
-    int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
-#ifdef HOST_WORDS_BIGENDIAN
-    offs += (8 - (1 << size));
-#endif
-    assert_fp_access_checked(s);
-    return offs;
+    return vec_reg_offset(s, regno, 0, size);
 }
 
 /* Offset of the high half of the 128 bit vector Qn */
 static inline int fp_reg_hi_offset(DisasContext *s, int regno)
 {
-    assert_fp_access_checked(s);
-    return offsetof(CPUARMState, vfp.regs[regno * 2 + 1]);
+    return vec_reg_offset(s, regno, 1, MO_64);
 }
 
 /* Convenience accessors for reading and writing single and double
diff --git a/target/arm/translate.c b/target/arm/translate.c
index cfe49bf579..55826b7e5a 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1515,14 +1515,16 @@ static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
 static inline long
 vfp_reg_offset (int dp, int reg)
 {
-    if (dp)
+    if (dp) {
         return offsetof(CPUARMState, vfp.regs[reg]);
-    else if (reg & 1) {
-        return offsetof(CPUARMState, vfp.regs[reg >> 1])
-          + offsetof(CPU_DoubleU, l.upper);
     } else {
-        return offsetof(CPUARMState, vfp.regs[reg >> 1])
-          + offsetof(CPU_DoubleU, l.lower);
+        long ofs = offsetof(CPUARMState, vfp.regs[reg >> 1]);
+        if (reg & 1) {
+            ofs += offsetof(CPU_DoubleU, l.upper);
+        } else {
+            ofs += offsetof(CPU_DoubleU, l.lower);
+        }
+        return ofs;
     }
 }
 
@@ -12572,7 +12574,7 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
             numvfpregs += 16;
         }
         for (i = 0; i < numvfpregs; i++) {
-            uint64_t v = env->vfp.regs[i];
+            uint64_t v = *aa32_vfp_dreg(env, i);
             cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
                         i * 2, (uint32_t)v,
                         i * 2 + 1, (uint32_t)(v >> 32),
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v2 07/16] vmstate: Add VMSTATE_UINT64_SUB_ARRAY
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
                   ` (5 preceding siblings ...)
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 06/16] target/arm: Add aa{32, 64}_vfp_{dreg, qreg} helpers Richard Henderson
@ 2018-01-19  4:54 ` Richard Henderson
  2018-01-22 11:02   ` Alex Bennée
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 08/16] target/arm: Expand vector registers for SVE Richard Henderson
                   ` (11 subsequent siblings)
  18 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2018-01-19  4:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

At the same time, move VMSTATE_UINT32_SUB_ARRAY
beside the other UINT32 definitions.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/migration/vmstate.h | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 88b55df5ae..8c3889433c 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -905,6 +905,9 @@ extern const VMStateInfo vmstate_info_qtailq;
 #define VMSTATE_UINT32_ARRAY(_f, _s, _n)                              \
     VMSTATE_UINT32_ARRAY_V(_f, _s, _n, 0)
 
+#define VMSTATE_UINT32_SUB_ARRAY(_f, _s, _start, _num)                \
+    VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint32, uint32_t)
+
 #define VMSTATE_UINT32_2DARRAY(_f, _s, _n1, _n2)                      \
     VMSTATE_UINT32_2DARRAY_V(_f, _s, _n1, _n2, 0)
 
@@ -914,6 +917,9 @@ extern const VMStateInfo vmstate_info_qtailq;
 #define VMSTATE_UINT64_ARRAY(_f, _s, _n)                              \
     VMSTATE_UINT64_ARRAY_V(_f, _s, _n, 0)
 
+#define VMSTATE_UINT64_SUB_ARRAY(_f, _s, _start, _num)                \
+    VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint64, uint64_t)
+
 #define VMSTATE_UINT64_2DARRAY(_f, _s, _n1, _n2)                      \
     VMSTATE_UINT64_2DARRAY_V(_f, _s, _n1, _n2, 0)
 
@@ -932,9 +938,6 @@ extern const VMStateInfo vmstate_info_qtailq;
 #define VMSTATE_INT32_ARRAY(_f, _s, _n)                               \
     VMSTATE_INT32_ARRAY_V(_f, _s, _n, 0)
 
-#define VMSTATE_UINT32_SUB_ARRAY(_f, _s, _start, _num)                \
-    VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint32, uint32_t)
-
 #define VMSTATE_INT64_ARRAY_V(_f, _s, _n, _v)                         \
     VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_int64, int64_t)
 
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v2 08/16] target/arm: Expand vector registers for SVE
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
                   ` (6 preceding siblings ...)
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 07/16] vmstate: Add VMSTATE_UINT64_SUB_ARRAY Richard Henderson
@ 2018-01-19  4:54 ` Richard Henderson
  2018-01-22 11:08   ` Alex Bennée
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 09/16] target/arm: Add predicate " Richard Henderson
                   ` (10 subsequent siblings)
  18 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2018-01-19  4:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Change vfp.regs as a uint64_t to vfp.zregs as an ARMVectorReg.
The previous patches have made the change in representation
relatively painless.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h           | 57 ++++++++++++++++++++++++++++++----------------
 target/arm/machine.c       | 35 +++++++++++++++++++++++++++-
 target/arm/translate-a64.c |  8 +++----
 target/arm/translate.c     |  7 +++---
 4 files changed, 79 insertions(+), 28 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 7d396606f3..57d805b5d8 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -153,6 +153,40 @@ typedef struct {
     uint32_t base_mask;
 } TCR;
 
+/* Define a maximum sized vector register.
+ * For 32-bit, this is a 128-bit NEON/AdvSIMD register.
+ * For 64-bit, this is a 2048-bit SVE register.
+ *
+ * Note that the mapping between S, D, and Q views of the register bank
+ * differs between AArch64 and AArch32.
+ * In AArch32:
+ *  Qn = regs[n].d[1]:regs[n].d[0]
+ *  Dn = regs[n / 2].d[n & 1]
+ *  Sn = regs[n / 4].d[n % 4 / 2],
+ *       bits 31..0 for even n, and bits 63..32 for odd n
+ *       (and regs[16] to regs[31] are inaccessible)
+ * In AArch64:
+ *  Zn = regs[n].d[*]
+ *  Qn = regs[n].d[1]:regs[n].d[0]
+ *  Dn = regs[n].d[0]
+ *  Sn = regs[n].d[0] bits 31..0
+ *
+ * This corresponds to the architecturally defined mapping between
+ * the two execution states, and means we do not need to explicitly
+ * map these registers when changing states.
+ */
+
+#ifdef TARGET_AARCH64
+# define ARM_MAX_VQ    16
+#else
+# define ARM_MAX_VQ    1
+#endif
+
+typedef struct ARMVectorReg {
+    uint64_t d[2 * ARM_MAX_VQ] QEMU_ALIGNED(16);
+} ARMVectorReg;
+
+
 typedef struct CPUARMState {
     /* Regs for current mode.  */
     uint32_t regs[16];
@@ -477,22 +511,7 @@ typedef struct CPUARMState {
 
     /* VFP coprocessor state.  */
     struct {
-        /* VFP/Neon register state. Note that the mapping between S, D and Q
-         * views of the register bank differs between AArch64 and AArch32:
-         * In AArch32:
-         *  Qn = regs[2n+1]:regs[2n]
-         *  Dn = regs[n]
-         *  Sn = regs[n/2] bits 31..0 for even n, and bits 63..32 for odd n
-         * (and regs[32] to regs[63] are inaccessible)
-         * In AArch64:
-         *  Qn = regs[2n+1]:regs[2n]
-         *  Dn = regs[2n]
-         *  Sn = regs[2n] bits 31..0
-         * This corresponds to the architecturally defined mapping between
-         * the two execution states, and means we do not need to explicitly
-         * map these registers when changing states.
-         */
-        uint64_t regs[64];
+        ARMVectorReg zregs[32];
 
         uint32_t xregs[16];
         /* We store these fpcsr fields separately for convenience.  */
@@ -2891,7 +2910,7 @@ static inline void *arm_get_el_change_hook_opaque(ARMCPU *cpu)
  */
 static inline uint64_t *aa32_vfp_dreg(CPUARMState *env, unsigned regno)
 {
-    return &env->vfp.regs[regno];
+    return &env->vfp.zregs[regno >> 1].d[regno & 1];
 }
 
 /**
@@ -2900,7 +2919,7 @@ static inline uint64_t *aa32_vfp_dreg(CPUARMState *env, unsigned regno)
  */
 static inline uint64_t *aa32_vfp_qreg(CPUARMState *env, unsigned regno)
 {
-    return &env->vfp.regs[2 * regno];
+    return &env->vfp.zregs[regno].d[0];
 }
 
 /**
@@ -2909,7 +2928,7 @@ static inline uint64_t *aa32_vfp_qreg(CPUARMState *env, unsigned regno)
  */
 static inline uint64_t *aa64_vfp_qreg(CPUARMState *env, unsigned regno)
 {
-    return &env->vfp.regs[2 * regno];
+    return &env->vfp.zregs[regno].d[0];
 }
 
 #endif
diff --git a/target/arm/machine.c b/target/arm/machine.c
index a85c2430d3..cb0e1c92bb 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -50,7 +50,40 @@ static const VMStateDescription vmstate_vfp = {
     .minimum_version_id = 3,
     .needed = vfp_needed,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT64_ARRAY(env.vfp.regs, ARMCPU, 64),
+        /* For compatibility, store Qn out of Zn here.  */
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[0].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[1].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[2].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[3].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[4].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[5].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[6].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[7].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[8].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[9].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[10].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[11].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[12].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[13].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[14].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[15].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[16].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[17].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[18].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[19].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[20].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[21].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[22].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[23].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[24].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[25].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[26].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[27].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[28].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[29].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[30].d, ARMCPU, 0, 2),
+        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[31].d, ARMCPU, 0, 2),
+
         /* The xregs array is a little awkward because element 1 (FPSCR)
          * requires a specific accessor, so we have to split it up in
          * the vmstate:
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index eed64c73e5..10eef870fe 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -517,8 +517,8 @@ static inline int vec_reg_offset(DisasContext *s, int regno,
 {
     int offs = 0;
 #ifdef HOST_WORDS_BIGENDIAN
-    /* This is complicated slightly because vfp.regs[2n] is
-     * still the low half and  vfp.regs[2n+1] the high half
+    /* This is complicated slightly because vfp.zregs[n].d[0] is
+     * still the low half and vfp.zregs[n].d[1] the high half
      * of the 128 bit vector, even on big endian systems.
      * Calculate the offset assuming a fully bigendian 128 bits,
      * then XOR to account for the order of the two 64 bit halves.
@@ -528,7 +528,7 @@ static inline int vec_reg_offset(DisasContext *s, int regno,
 #else
     offs += element * (1 << size);
 #endif
-    offs += offsetof(CPUARMState, vfp.regs[regno * 2]);
+    offs += offsetof(CPUARMState, vfp.zregs[regno]);
     assert_fp_access_checked(s);
     return offs;
 }
@@ -537,7 +537,7 @@ static inline int vec_reg_offset(DisasContext *s, int regno,
 static inline int vec_full_reg_offset(DisasContext *s, int regno)
 {
     assert_fp_access_checked(s);
-    return offsetof(CPUARMState, vfp.regs[regno * 2]);
+    return offsetof(CPUARMState, vfp.zregs[regno]);
 }
 
 /* Return a newly allocated pointer to the vector register.  */
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 55826b7e5a..a8c13d3758 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1512,13 +1512,12 @@ static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
     }
 }
 
-static inline long
-vfp_reg_offset (int dp, int reg)
+static inline long vfp_reg_offset(bool dp, unsigned reg)
 {
     if (dp) {
-        return offsetof(CPUARMState, vfp.regs[reg]);
+        return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
     } else {
-        long ofs = offsetof(CPUARMState, vfp.regs[reg >> 1]);
+        long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]);
         if (reg & 1) {
             ofs += offsetof(CPU_DoubleU, l.upper);
         } else {
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v2 09/16] target/arm: Add predicate registers for SVE
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
                   ` (7 preceding siblings ...)
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 08/16] target/arm: Expand vector registers for SVE Richard Henderson
@ 2018-01-19  4:54 ` Richard Henderson
  2018-01-22 12:04   ` Alex Bennée
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 10/16] target/arm: Add ARM_FEATURE_SVE Richard Henderson
                   ` (9 subsequent siblings)
  18 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2018-01-19  4:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 57d805b5d8..132da359b5 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -186,6 +186,15 @@ typedef struct ARMVectorReg {
     uint64_t d[2 * ARM_MAX_VQ] QEMU_ALIGNED(16);
 } ARMVectorReg;
 
+/* In AArch32 mode, predicate registers do not exist at all.  */
+typedef struct ARMPredicateReg {
+#ifdef TARGET_AARCH64
+    uint64_t p[2 * ARM_MAX_VQ / 8] QEMU_ALIGNED(16);
+#else
+    uint64_t p[0];
+#endif
+} ARMPredicateReg;
+
 
 typedef struct CPUARMState {
     /* Regs for current mode.  */
@@ -513,6 +522,9 @@ typedef struct CPUARMState {
     struct {
         ARMVectorReg zregs[32];
 
+        /* Store FFR as pregs[16] to make it easier to treat as any other.  */
+        ARMPredicateReg pregs[17];
+
         uint32_t xregs[16];
         /* We store these fpcsr fields separately for convenience.  */
         int vec_len;
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v2 10/16] target/arm: Add ARM_FEATURE_SVE
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
                   ` (8 preceding siblings ...)
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 09/16] target/arm: Add predicate " Richard Henderson
@ 2018-01-19  4:54 ` Richard Henderson
  2018-01-22 12:05   ` Alex Bennée
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 11/16] target/arm: Add SVE to migration state Richard Henderson
                   ` (8 subsequent siblings)
  18 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2018-01-19  4:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Not enabled anywhere so far.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 132da359b5..0a923e42d8 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1371,6 +1371,7 @@ enum arm_features {
     ARM_FEATURE_VBAR, /* has cp15 VBAR */
     ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
     ARM_FEATURE_JAZELLE, /* has (trivial) Jazelle implementation */
+    ARM_FEATURE_SVE, /* has Scalable Vector Extension */
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v2 11/16] target/arm: Add SVE to migration state
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
                   ` (9 preceding siblings ...)
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 10/16] target/arm: Add ARM_FEATURE_SVE Richard Henderson
@ 2018-01-19  4:54 ` Richard Henderson
  2018-01-22 13:40   ` Alex Bennée
  2018-01-22 14:16   ` Peter Maydell
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 12/16] target/arm: Add ZCR_ELx Richard Henderson
                   ` (7 subsequent siblings)
  18 siblings, 2 replies; 46+ messages in thread
From: Richard Henderson @ 2018-01-19  4:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Save the high parts of the Zregs and all of the Pregs.
The ZCR_ELx registers are migrated via the CP mechanism.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/machine.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/target/arm/machine.c b/target/arm/machine.c
index cb0e1c92bb..2c8b43062f 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -122,6 +122,56 @@ static const VMStateDescription vmstate_iwmmxt = {
     }
 };
 
+#ifdef TARGET_AARCH64
+/* The expression ARM_MAX_VQ - 2 is 0 for pure AArch32 build,
+ * and ARMPredicateReg is actively empty.  This triggers errors
+ * in the expansion of the VMSTATE macros.
+ */
+
+static bool sve_needed(void *opaque)
+{
+    ARMCPU *cpu = opaque;
+    CPUARMState *env = &cpu->env;
+
+    return arm_feature(env, ARM_FEATURE_SVE);
+}
+
+/* The first two words of each Zreg is stored in VFP state.  */
+static const VMStateDescription vmstate_zreg_hi_reg = {
+    .name = "cpu/sve/zreg_hi",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64_SUB_ARRAY(d, ARMVectorReg, 2, ARM_MAX_VQ - 2),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_preg_reg = {
+    .name = "cpu/sve/preg",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64_ARRAY(p, ARMPredicateReg, 2 * ARM_MAX_VQ / 8),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_sve = {
+    .name = "cpu/sve",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = sve_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT_ARRAY(env.vfp.zregs, ARMCPU, 32, 0,
+                             vmstate_zreg_hi_reg, ARMVectorReg),
+        VMSTATE_STRUCT_ARRAY(env.vfp.pregs, ARMCPU, 17, 0,
+                             vmstate_preg_reg, ARMPredicateReg),
+        VMSTATE_END_OF_LIST()
+    }
+};
+#endif /* AARCH64 */
+
 static bool m_needed(void *opaque)
 {
     ARMCPU *cpu = opaque;
@@ -586,6 +636,9 @@ const VMStateDescription vmstate_arm_cpu = {
         &vmstate_pmsav7,
         &vmstate_pmsav8,
         &vmstate_m_security,
+#ifdef TARGET_AARCH64
+        &vmstate_sve,
+#endif
         NULL
     }
 };
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v2 12/16] target/arm: Add ZCR_ELx
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
                   ` (10 preceding siblings ...)
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 11/16] target/arm: Add SVE to migration state Richard Henderson
@ 2018-01-19  4:54 ` Richard Henderson
  2018-01-22 14:38   ` Peter Maydell
  2018-01-22 15:00   ` Alex Bennée
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 13/16] target/arm: Move cpu_get_tb_cpu_state out of line Richard Henderson
                   ` (6 subsequent siblings)
  18 siblings, 2 replies; 46+ messages in thread
From: Richard Henderson @ 2018-01-19  4:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Define ZCR_EL[1-3].

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h    |  5 ++++
 target/arm/helper.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 0a923e42d8..c8e8155b6e 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -547,6 +547,9 @@ typedef struct CPUARMState {
          */
         float_status fp_status;
         float_status standard_fp_status;
+
+        /* ZCR_EL[1-3] */
+        uint64_t zcr_el[4];
     } vfp;
     uint64_t exclusive_addr;
     uint64_t exclusive_val;
@@ -921,6 +924,8 @@ void pmccntr_sync(CPUARMState *env);
 #define CPTR_TCPAC    (1U << 31)
 #define CPTR_TTA      (1U << 20)
 #define CPTR_TFP      (1U << 10)
+#define CPTR_TZ       (1U << 8)   /* CPTR_EL2 */
+#define CPTR_EZ       (1U << 8)   /* CPTR_EL3 */
 
 #define MDCR_EPMAD    (1U << 21)
 #define MDCR_EDAD     (1U << 20)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 6705903301..984a4b1306 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -4266,6 +4266,82 @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
     REGINFO_SENTINEL
 };
 
+/* Return the exception level to which SVE-disabled exceptions should
+ * be taken, or 0 if SVE is enabled.
+ */
+static int sve_exception_el(CPUARMState *env)
+{
+#ifndef CONFIG_USER_ONLY
+    int highest_el = arm_highest_el(env);
+    int current_el = arm_current_el(env);
+    int i;
+
+    for (i = highest_el; i >= MAX(1, current_el); --i) {
+        switch (i) {
+        case 3:
+            if ((env->cp15.cptr_el[3] & CPTR_EZ) == 0) {
+                return 3;
+            }
+            break;
+        case 2:
+            if (env->cp15.cptr_el[2] & CPTR_TZ) {
+                return 2;
+            }
+            break;
+        case 1:
+            switch (extract32(env->cp15.cpacr_el1, 16, 2)) {
+            case 1:
+                return current_el == 0 ? 1 : 0;
+            case 3:
+                return 0;
+            default:
+                return 1;
+            }
+        }
+    }
+#endif
+    return 0;
+}
+
+static CPAccessResult zcr_access(CPUARMState *env, const ARMCPRegInfo *ri,
+                                 bool isread)
+{
+    switch (sve_exception_el(env)) {
+    case 3:
+        return CP_ACCESS_TRAP_EL3;
+    case 2:
+        return CP_ACCESS_TRAP_EL2;
+    case 1:
+        return CP_ACCESS_TRAP;
+    }
+    return CP_ACCESS_OK;
+}
+
+static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                      uint64_t value)
+{
+    /* Bits other than [3:0] are RAZ/WI.  */
+    raw_write(env, ri, value & 0xf);
+}
+
+static const ARMCPRegInfo sve_cp_reginfo[] = {
+    { .name = "ZCR_EL1", .state = ARM_CP_STATE_AA64,
+      .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 0,
+      .access = PL1_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
+      .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[1]),
+      .writefn = zcr_write, .raw_writefn = raw_write, },
+    { .name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
+      .opc0 = 2, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
+      .access = PL2_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
+      .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[2]),
+      .writefn = zcr_write, .raw_writefn = raw_write, },
+    { .name = "ZCR_EL3", .state = ARM_CP_STATE_AA64,
+      .opc0 = 2, .opc1 = 6, .crn = 1, .crm = 2, .opc2 = 0,
+      .access = PL1_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
+      .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[3]),
+      .writefn = zcr_write, .raw_writefn = raw_write, },
+};
+
 void hw_watchpoint_update(ARMCPU *cpu, int n)
 {
     CPUARMState *env = &cpu->env;
@@ -5332,6 +5408,10 @@ void register_cp_regs_for_features(ARMCPU *cpu)
         }
         define_one_arm_cp_reg(cpu, &sctlr);
     }
+
+    if (arm_feature(env, ARM_FEATURE_SVE)) {
+        define_arm_cp_regs(cpu, sve_cp_reginfo);
+    }
 }
 
 void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v2 13/16] target/arm: Move cpu_get_tb_cpu_state out of line
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
                   ` (11 preceding siblings ...)
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 12/16] target/arm: Add ZCR_ELx Richard Henderson
@ 2018-01-19  4:54 ` Richard Henderson
  2018-01-22 15:07   ` Alex Bennée
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 14/16] target/arm: Hoist store to flags output in cpu_get_tb_cpu_state Richard Henderson
                   ` (5 subsequent siblings)
  18 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2018-01-19  4:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h    | 127 +---------------------------------------------------
 target/arm/helper.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 128 insertions(+), 125 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index c8e8155b6e..2de1afb53a 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2703,71 +2703,6 @@ static inline bool bswap_code(bool sctlr_b)
 #endif
 }
 
-/* Return the exception level to which FP-disabled exceptions should
- * be taken, or 0 if FP is enabled.
- */
-static inline int fp_exception_el(CPUARMState *env)
-{
-    int fpen;
-    int cur_el = arm_current_el(env);
-
-    /* CPACR and the CPTR registers don't exist before v6, so FP is
-     * always accessible
-     */
-    if (!arm_feature(env, ARM_FEATURE_V6)) {
-        return 0;
-    }
-
-    /* The CPACR controls traps to EL1, or PL1 if we're 32 bit:
-     * 0, 2 : trap EL0 and EL1/PL1 accesses
-     * 1    : trap only EL0 accesses
-     * 3    : trap no accesses
-     */
-    fpen = extract32(env->cp15.cpacr_el1, 20, 2);
-    switch (fpen) {
-    case 0:
-    case 2:
-        if (cur_el == 0 || cur_el == 1) {
-            /* Trap to PL1, which might be EL1 or EL3 */
-            if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
-                return 3;
-            }
-            return 1;
-        }
-        if (cur_el == 3 && !is_a64(env)) {
-            /* Secure PL1 running at EL3 */
-            return 3;
-        }
-        break;
-    case 1:
-        if (cur_el == 0) {
-            return 1;
-        }
-        break;
-    case 3:
-        break;
-    }
-
-    /* For the CPTR registers we don't need to guard with an ARM_FEATURE
-     * check because zero bits in the registers mean "don't trap".
-     */
-
-    /* CPTR_EL2 : present in v7VE or v8 */
-    if (cur_el <= 2 && extract32(env->cp15.cptr_el[2], 10, 1)
-        && !arm_is_secure_below_el3(env)) {
-        /* Trap FP ops at EL2, NS-EL1 or NS-EL0 to EL2 */
-        return 2;
-    }
-
-    /* CPTR_EL3 : present in v8 */
-    if (extract32(env->cp15.cptr_el[3], 10, 1)) {
-        /* Trap all FP ops to EL3 */
-        return 3;
-    }
-
-    return 0;
-}
-
 #ifdef CONFIG_USER_ONLY
 static inline bool arm_cpu_bswap_data(CPUARMState *env)
 {
@@ -2814,66 +2749,8 @@ static inline uint32_t arm_regime_tbi1(CPUARMState *env, ARMMMUIdx mmu_idx)
 }
 #endif
 
-static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
-                                        target_ulong *cs_base, uint32_t *flags)
-{
-    ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
-    if (is_a64(env)) {
-        *pc = env->pc;
-        *flags = ARM_TBFLAG_AARCH64_STATE_MASK;
-        /* Get control bits for tagged addresses */
-        *flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
-        *flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
-    } else {
-        *pc = env->regs[15];
-        *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
-            | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
-            | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
-            | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
-            | (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT);
-        if (!(access_secure_reg(env))) {
-            *flags |= ARM_TBFLAG_NS_MASK;
-        }
-        if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
-            || arm_el_is_aa64(env, 1)) {
-            *flags |= ARM_TBFLAG_VFPEN_MASK;
-        }
-        *flags |= (extract32(env->cp15.c15_cpar, 0, 2)
-                   << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
-    }
-
-    *flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT);
-
-    /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
-     * states defined in the ARM ARM for software singlestep:
-     *  SS_ACTIVE   PSTATE.SS   State
-     *     0            x       Inactive (the TB flag for SS is always 0)
-     *     1            0       Active-pending
-     *     1            1       Active-not-pending
-     */
-    if (arm_singlestep_active(env)) {
-        *flags |= ARM_TBFLAG_SS_ACTIVE_MASK;
-        if (is_a64(env)) {
-            if (env->pstate & PSTATE_SS) {
-                *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
-            }
-        } else {
-            if (env->uncached_cpsr & PSTATE_SS) {
-                *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
-            }
-        }
-    }
-    if (arm_cpu_data_is_big_endian(env)) {
-        *flags |= ARM_TBFLAG_BE_DATA_MASK;
-    }
-    *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
-
-    if (arm_v7m_is_handler_mode(env)) {
-        *flags |= ARM_TBFLAG_HANDLER_MASK;
-    }
-
-    *cs_base = 0;
-}
+void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
+                          target_ulong *cs_base, uint32_t *flags);
 
 enum {
     QEMU_PSCI_CONDUIT_DISABLED = 0,
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 984a4b1306..9e673bb672 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11701,3 +11701,129 @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
     /* Linux crc32c converts the output to one's complement.  */
     return crc32c(acc, buf, bytes) ^ 0xffffffff;
 }
+
+/* Return the exception level to which FP-disabled exceptions should
+ * be taken, or 0 if FP is enabled.
+ */
+static inline int fp_exception_el(CPUARMState *env)
+{
+    int fpen;
+    int cur_el = arm_current_el(env);
+
+    /* CPACR and the CPTR registers don't exist before v6, so FP is
+     * always accessible
+     */
+    if (!arm_feature(env, ARM_FEATURE_V6)) {
+        return 0;
+    }
+
+    /* The CPACR controls traps to EL1, or PL1 if we're 32 bit:
+     * 0, 2 : trap EL0 and EL1/PL1 accesses
+     * 1    : trap only EL0 accesses
+     * 3    : trap no accesses
+     */
+    fpen = extract32(env->cp15.cpacr_el1, 20, 2);
+    switch (fpen) {
+    case 0:
+    case 2:
+        if (cur_el == 0 || cur_el == 1) {
+            /* Trap to PL1, which might be EL1 or EL3 */
+            if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
+                return 3;
+            }
+            return 1;
+        }
+        if (cur_el == 3 && !is_a64(env)) {
+            /* Secure PL1 running at EL3 */
+            return 3;
+        }
+        break;
+    case 1:
+        if (cur_el == 0) {
+            return 1;
+        }
+        break;
+    case 3:
+        break;
+    }
+
+    /* For the CPTR registers we don't need to guard with an ARM_FEATURE
+     * check because zero bits in the registers mean "don't trap".
+     */
+
+    /* CPTR_EL2 : present in v7VE or v8 */
+    if (cur_el <= 2 && extract32(env->cp15.cptr_el[2], 10, 1)
+        && !arm_is_secure_below_el3(env)) {
+        /* Trap FP ops at EL2, NS-EL1 or NS-EL0 to EL2 */
+        return 2;
+    }
+
+    /* CPTR_EL3 : present in v8 */
+    if (extract32(env->cp15.cptr_el[3], 10, 1)) {
+        /* Trap all FP ops to EL3 */
+        return 3;
+    }
+
+    return 0;
+}
+
+void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
+                          target_ulong *cs_base, uint32_t *flags)
+{
+    ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
+    if (is_a64(env)) {
+        *pc = env->pc;
+        *flags = ARM_TBFLAG_AARCH64_STATE_MASK;
+        /* Get control bits for tagged addresses */
+        *flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
+        *flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
+    } else {
+        *pc = env->regs[15];
+        *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
+            | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
+            | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
+            | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
+            | (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT);
+        if (!(access_secure_reg(env))) {
+            *flags |= ARM_TBFLAG_NS_MASK;
+        }
+        if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
+            || arm_el_is_aa64(env, 1)) {
+            *flags |= ARM_TBFLAG_VFPEN_MASK;
+        }
+        *flags |= (extract32(env->cp15.c15_cpar, 0, 2)
+                   << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
+    }
+
+    *flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT);
+
+    /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
+     * states defined in the ARM ARM for software singlestep:
+     *  SS_ACTIVE   PSTATE.SS   State
+     *     0            x       Inactive (the TB flag for SS is always 0)
+     *     1            0       Active-pending
+     *     1            1       Active-not-pending
+     */
+    if (arm_singlestep_active(env)) {
+        *flags |= ARM_TBFLAG_SS_ACTIVE_MASK;
+        if (is_a64(env)) {
+            if (env->pstate & PSTATE_SS) {
+                *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
+            }
+        } else {
+            if (env->uncached_cpsr & PSTATE_SS) {
+                *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
+            }
+        }
+    }
+    if (arm_cpu_data_is_big_endian(env)) {
+        *flags |= ARM_TBFLAG_BE_DATA_MASK;
+    }
+    *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
+
+    if (arm_v7m_is_handler_mode(env)) {
+        *flags |= ARM_TBFLAG_HANDLER_MASK;
+    }
+
+    *cs_base = 0;
+}
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v2 14/16] target/arm: Hoist store to flags output in cpu_get_tb_cpu_state
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
                   ` (12 preceding siblings ...)
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 13/16] target/arm: Move cpu_get_tb_cpu_state out of line Richard Henderson
@ 2018-01-19  4:54 ` Richard Henderson
  2018-01-22 15:09   ` Alex Bennée
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 15/16] target/arm: Simplify fp_exception_el for user-only Richard Henderson
                   ` (4 subsequent siblings)
  18 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2018-01-19  4:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/helper.c | 35 +++++++++++++++++++----------------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 9e673bb672..c0e5f321c5 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11768,34 +11768,36 @@ static inline int fp_exception_el(CPUARMState *env)
 }
 
 void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
-                          target_ulong *cs_base, uint32_t *flags)
+                          target_ulong *cs_base, uint32_t *pflags)
 {
     ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
+    uint32_t flags;
+
     if (is_a64(env)) {
         *pc = env->pc;
-        *flags = ARM_TBFLAG_AARCH64_STATE_MASK;
+        flags = ARM_TBFLAG_AARCH64_STATE_MASK;
         /* Get control bits for tagged addresses */
-        *flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
-        *flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
+        flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
+        flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
     } else {
         *pc = env->regs[15];
-        *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
+        flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
             | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
             | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
             | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
             | (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT);
         if (!(access_secure_reg(env))) {
-            *flags |= ARM_TBFLAG_NS_MASK;
+            flags |= ARM_TBFLAG_NS_MASK;
         }
         if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
             || arm_el_is_aa64(env, 1)) {
-            *flags |= ARM_TBFLAG_VFPEN_MASK;
+            flags |= ARM_TBFLAG_VFPEN_MASK;
         }
-        *flags |= (extract32(env->cp15.c15_cpar, 0, 2)
-                   << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
+        flags |= (extract32(env->cp15.c15_cpar, 0, 2)
+                  << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
     }
 
-    *flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT);
+    flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT);
 
     /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
      * states defined in the ARM ARM for software singlestep:
@@ -11805,25 +11807,26 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
      *     1            1       Active-not-pending
      */
     if (arm_singlestep_active(env)) {
-        *flags |= ARM_TBFLAG_SS_ACTIVE_MASK;
+        flags |= ARM_TBFLAG_SS_ACTIVE_MASK;
         if (is_a64(env)) {
             if (env->pstate & PSTATE_SS) {
-                *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
+                flags |= ARM_TBFLAG_PSTATE_SS_MASK;
             }
         } else {
             if (env->uncached_cpsr & PSTATE_SS) {
-                *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
+                flags |= ARM_TBFLAG_PSTATE_SS_MASK;
             }
         }
     }
     if (arm_cpu_data_is_big_endian(env)) {
-        *flags |= ARM_TBFLAG_BE_DATA_MASK;
+        flags |= ARM_TBFLAG_BE_DATA_MASK;
     }
-    *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
+    flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
 
     if (arm_v7m_is_handler_mode(env)) {
-        *flags |= ARM_TBFLAG_HANDLER_MASK;
+        flags |= ARM_TBFLAG_HANDLER_MASK;
     }
 
+    *pflags = flags;
     *cs_base = 0;
 }
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v2 15/16] target/arm: Simplify fp_exception_el for user-only
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
                   ` (13 preceding siblings ...)
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 14/16] target/arm: Hoist store to flags output in cpu_get_tb_cpu_state Richard Henderson
@ 2018-01-19  4:54 ` Richard Henderson
  2018-01-22 15:10   ` Alex Bennée
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 16/16] target/arm: Add SVE state to TB->FLAGS Richard Henderson
                   ` (3 subsequent siblings)
  18 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2018-01-19  4:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/helper.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index c0e5f321c5..44814af99b 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11707,6 +11707,7 @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
  */
 static inline int fp_exception_el(CPUARMState *env)
 {
+#ifndef CONFIG_USER_ONLY
     int fpen;
     int cur_el = arm_current_el(env);
 
@@ -11763,7 +11764,7 @@ static inline int fp_exception_el(CPUARMState *env)
         /* Trap all FP ops to EL3 */
         return 3;
     }
-
+#endif
     return 0;
 }
 
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v2 16/16] target/arm: Add SVE state to TB->FLAGS
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
                   ` (14 preceding siblings ...)
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 15/16] target/arm: Simplify fp_exception_el for user-only Richard Henderson
@ 2018-01-19  4:54 ` Richard Henderson
  2018-01-22 14:40   ` Peter Maydell
  2018-01-19  5:29 ` [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE no-reply
                   ` (2 subsequent siblings)
  18 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2018-01-19  4:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Add both SVE exception state and vector length.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h    |  4 ++++
 target/arm/helper.c | 23 ++++++++++++++++++++++-
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 2de1afb53a..d7208d56df 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2646,6 +2646,10 @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
 #define ARM_TBFLAG_TBI0_MASK (0x1ull << ARM_TBFLAG_TBI0_SHIFT)
 #define ARM_TBFLAG_TBI1_SHIFT 1        /* TBI1 for EL0/1  */
 #define ARM_TBFLAG_TBI1_MASK (0x1ull << ARM_TBFLAG_TBI1_SHIFT)
+#define ARM_TBFLAG_SVEEXC_EL_SHIFT  2
+#define ARM_TBFLAG_SVEEXC_EL_MASK   (0x3 << ARM_TBFLAG_SVEEXC_EL_SHIFT)
+#define ARM_TBFLAG_ZCR_LEN_SHIFT    4
+#define ARM_TBFLAG_ZCR_LEN_MASK     (0xf << ARM_TBFLAG_ZCR_LEN_SHIFT)
 
 /* some convenience accessor macros */
 #define ARM_TBFLAG_AARCH64_STATE(F) \
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 44814af99b..6072634ca8 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11772,14 +11772,35 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
                           target_ulong *cs_base, uint32_t *pflags)
 {
     ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
+    int fp_el = fp_exception_el(env);
     uint32_t flags;
 
     if (is_a64(env)) {
+        int sve_el = sve_exception_el(env);
+        uint32_t zcr_len;
+
         *pc = env->pc;
         flags = ARM_TBFLAG_AARCH64_STATE_MASK;
         /* Get control bits for tagged addresses */
         flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
         flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
+        flags |= sve_el << ARM_TBFLAG_SVEEXC_EL_SHIFT;
+
+        /* If SVE is disabled, but FP is enabled,
+           then the effective len is 0.  */
+        if (sve_el != 0 && fp_el == 0) {
+            zcr_len = 0;
+        } else {
+            int highest_el = arm_highest_el(env);
+            int current_el = arm_current_el(env);
+            int i;
+
+            zcr_len = 0xf & (uint32_t)env->vfp.zcr_el[highest_el];
+            for (i = highest_el - 1; i >= MAX(1, current_el); --i) {
+                zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[i]);
+            }
+        }
+        flags |= zcr_len << ARM_TBFLAG_ZCR_LEN_SHIFT;
     } else {
         *pc = env->regs[15];
         flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
@@ -11822,7 +11843,7 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
     if (arm_cpu_data_is_big_endian(env)) {
         flags |= ARM_TBFLAG_BE_DATA_MASK;
     }
-    flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
+    flags |= fp_el << ARM_TBFLAG_FPEXC_EL_SHIFT;
 
     if (arm_v7m_is_handler_mode(env)) {
         flags |= ARM_TBFLAG_HANDLER_MASK;
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
                   ` (15 preceding siblings ...)
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 16/16] target/arm: Add SVE state to TB->FLAGS Richard Henderson
@ 2018-01-19  5:29 ` no-reply
  2018-01-22 14:12 ` Peter Maydell
  2018-01-22 15:12 ` Alex Bennée
  18 siblings, 0 replies; 46+ messages in thread
From: no-reply @ 2018-01-19  5:29 UTC (permalink / raw)
  To: richard.henderson; +Cc: famz, qemu-devel, peter.maydell

Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20180119045438.28582-1-richard.henderson@linaro.org
Subject: [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
    echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
    if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
        failed=1
        echo
    fi
    n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]               patchew/20180119045438.28582-1-richard.henderson@linaro.org -> patchew/20180119045438.28582-1-richard.henderson@linaro.org
 * [new tag]               patchew/20180119050005.29392-1-sjitindarsingh@gmail.com -> patchew/20180119050005.29392-1-sjitindarsingh@gmail.com
Switched to a new branch 'test'
6308b3eb42 target/arm: Add SVE state to TB->FLAGS
bc0bf3ebae target/arm: Simplify fp_exception_el for user-only
9cdaf60c2f target/arm: Hoist store to flags output in cpu_get_tb_cpu_state
1547b70c1e target/arm: Move cpu_get_tb_cpu_state out of line
b01bb5ca6b target/arm: Add ZCR_ELx
a42658d26a target/arm: Add SVE to migration state
03a80b68c0 target/arm: Add ARM_FEATURE_SVE
a396b26009 target/arm: Add predicate registers for SVE
0ccce9b3c9 target/arm: Expand vector registers for SVE
aea9739609 vmstate: Add VMSTATE_UINT64_SUB_ARRAY
119ea30dc0 target/arm: Add aa{32, 64}_vfp_{dreg, qreg} helpers
2acd7c7cec target/arm: Change the type of vfp.regs
ae2da084a4 target/arm: Use pointers in neon tbl helper
af4b1905c4 target/arm: Use pointers in neon zip/uzp helpers
9228c6c201 target/arm: Use pointers in crypto helpers
164bf2cd53 target/arm: Mark disas_set_insn_syndrome inline

=== OUTPUT BEGIN ===
Checking PATCH 1/16: target/arm: Mark disas_set_insn_syndrome inline...
Checking PATCH 2/16: target/arm: Use pointers in crypto helpers...
Checking PATCH 3/16: target/arm: Use pointers in neon zip/uzp helpers...
ERROR: trailing whitespace
#315: FILE: target/arm/translate.c:4691:
+    $

total: 1 errors, 0 warnings, 373 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 4/16: target/arm: Use pointers in neon tbl helper...
Checking PATCH 5/16: target/arm: Change the type of vfp.regs...
Checking PATCH 6/16: target/arm: Add aa{32, 64}_vfp_{dreg, qreg} helpers...
ERROR: spaces required around that '*' (ctx:VxV)
#82: FILE: target/arm/arch_dump.c:104:
+        note.vfp.vregs[2*i + 0] = cpu_to_dump64(s, q[0]);
                         ^

ERROR: spaces required around that '*' (ctx:VxV)
#83: FILE: target/arm/arch_dump.c:105:
+        note.vfp.vregs[2*i + 1] = cpu_to_dump64(s, q[1]);
                         ^

total: 2 errors, 0 warnings, 327 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 7/16: vmstate: Add VMSTATE_UINT64_SUB_ARRAY...
Checking PATCH 8/16: target/arm: Expand vector registers for SVE...
Checking PATCH 9/16: target/arm: Add predicate registers for SVE...
Checking PATCH 10/16: target/arm: Add ARM_FEATURE_SVE...
Checking PATCH 11/16: target/arm: Add SVE to migration state...
Checking PATCH 12/16: target/arm: Add ZCR_ELx...
Checking PATCH 13/16: target/arm: Move cpu_get_tb_cpu_state out of line...
Checking PATCH 14/16: target/arm: Hoist store to flags output in cpu_get_tb_cpu_state...
Checking PATCH 15/16: target/arm: Simplify fp_exception_el for user-only...
Checking PATCH 16/16: target/arm: Add SVE state to TB->FLAGS...
=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 01/16] target/arm: Mark disas_set_insn_syndrome inline
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 01/16] target/arm: Mark disas_set_insn_syndrome inline Richard Henderson
@ 2018-01-19 13:54   ` Alex Bennée
  0 siblings, 0 replies; 46+ messages in thread
From: Alex Bennée @ 2018-01-19 13:54 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> If it isn't used when translate.h is included,
> we'll get a compiler Werror.
>
> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target/arm/translate.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target/arm/translate.h b/target/arm/translate.h
> index cd7313ace7..3f4df91e5e 100644
> --- a/target/arm/translate.h
> +++ b/target/arm/translate.h
> @@ -108,7 +108,7 @@ static inline int default_exception_el(DisasContext *s)
>              ? 3 : MAX(1, s->current_el);
>  }
>
> -static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
> +static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
>  {
>      /* We don't need to save all of the syndrome so we mask and shift
>       * out unneeded bits to help the sleb128 encoder do a better job.


--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 02/16] target/arm: Use pointers in crypto helpers
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 02/16] target/arm: Use pointers in crypto helpers Richard Henderson
@ 2018-01-22 10:09   ` Alex Bennée
  0 siblings, 0 replies; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 10:09 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> Rather than passing regnos to the helpers, pass pointers to the
> vector registers directly.  This eliminates the need to pass in
> the environment pointer and reduces the number of places that
> directly access env->vfp.regs[].
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target/arm/helper.h        |  18 ++---
>  target/arm/crypto_helper.c | 184 +++++++++++++++++----------------------------
>  target/arm/translate-a64.c |  75 ++++++++++--------
>  target/arm/translate.c     |  68 +++++++++--------
>  4 files changed, 161 insertions(+), 184 deletions(-)
>
> diff --git a/target/arm/helper.h b/target/arm/helper.h
> index 066729e8ad..688380af6b 100644
> --- a/target/arm/helper.h
> +++ b/target/arm/helper.h
> @@ -522,17 +522,17 @@ DEF_HELPER_3(neon_qzip8, void, env, i32, i32)
>  DEF_HELPER_3(neon_qzip16, void, env, i32, i32)
>  DEF_HELPER_3(neon_qzip32, void, env, i32, i32)
>
> -DEF_HELPER_4(crypto_aese, void, env, i32, i32, i32)
> -DEF_HELPER_4(crypto_aesmc, void, env, i32, i32, i32)
> +DEF_HELPER_FLAGS_3(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
> +DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
>
> -DEF_HELPER_5(crypto_sha1_3reg, void, env, i32, i32, i32, i32)
> -DEF_HELPER_3(crypto_sha1h, void, env, i32, i32)
> -DEF_HELPER_3(crypto_sha1su1, void, env, i32, i32)
> +DEF_HELPER_FLAGS_4(crypto_sha1_3reg, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
> +DEF_HELPER_FLAGS_2(crypto_sha1h, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(crypto_sha1su1, TCG_CALL_NO_RWG, void, ptr, ptr)
>
> -DEF_HELPER_4(crypto_sha256h, void, env, i32, i32, i32)
> -DEF_HELPER_4(crypto_sha256h2, void, env, i32, i32, i32)
> -DEF_HELPER_3(crypto_sha256su0, void, env, i32, i32)
> -DEF_HELPER_4(crypto_sha256su1, void, env, i32, i32, i32)
> +DEF_HELPER_FLAGS_3(crypto_sha256h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
> +DEF_HELPER_FLAGS_3(crypto_sha256h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
> +DEF_HELPER_FLAGS_2(crypto_sha256su0, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_3(crypto_sha256su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
>
>  DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
>  DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
> diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
> index 3b6df3f41a..9ca0bdead7 100644
> --- a/target/arm/crypto_helper.c
> +++ b/target/arm/crypto_helper.c
> @@ -30,20 +30,14 @@ union CRYPTO_STATE {
>  #define CR_ST_WORD(state, i)   (state.words[i])
>  #endif
>
> -void HELPER(crypto_aese)(CPUARMState *env, uint32_t rd, uint32_t rm,
> -                         uint32_t decrypt)
> +void HELPER(crypto_aese)(void *vd, void *vm, uint32_t decrypt)
>  {
>      static uint8_t const * const sbox[2] = { AES_sbox, AES_isbox };
>      static uint8_t const * const shift[2] = { AES_shifts, AES_ishifts };
> -
> -    union CRYPTO_STATE rk = { .l = {
> -        float64_val(env->vfp.regs[rm]),
> -        float64_val(env->vfp.regs[rm + 1])
> -    } };
> -    union CRYPTO_STATE st = { .l = {
> -        float64_val(env->vfp.regs[rd]),
> -        float64_val(env->vfp.regs[rd + 1])
> -    } };
> +    uint64_t *rd = vd;
> +    uint64_t *rm = vm;
> +    union CRYPTO_STATE rk = { .l = { rm[0], rm[1] } };
> +    union CRYPTO_STATE st = { .l = { rd[0], rd[1] } };
>      int i;
>
>      assert(decrypt < 2);
> @@ -57,12 +51,11 @@ void HELPER(crypto_aese)(CPUARMState *env, uint32_t rd, uint32_t rm,
>          CR_ST_BYTE(st, i) = sbox[decrypt][CR_ST_BYTE(rk, shift[decrypt][i])];
>      }
>
> -    env->vfp.regs[rd] = make_float64(st.l[0]);
> -    env->vfp.regs[rd + 1] = make_float64(st.l[1]);
> +    rd[0] = st.l[0];
> +    rd[1] = st.l[1];
>  }
>
> -void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm,
> -                          uint32_t decrypt)
> +void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t decrypt)
>  {
>      static uint32_t const mc[][256] = { {
>          /* MixColumns lookup table */
> @@ -197,10 +190,10 @@ void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm,
>          0x92b479a7, 0x99b970a9, 0x84ae6bbb, 0x8fa362b5,
>          0xbe805d9f, 0xb58d5491, 0xa89a4f83, 0xa397468d,
>      } };
> -    union CRYPTO_STATE st = { .l = {
> -        float64_val(env->vfp.regs[rm]),
> -        float64_val(env->vfp.regs[rm + 1])
> -    } };
> +
> +    uint64_t *rd = vd;
> +    uint64_t *rm = vm;
> +    union CRYPTO_STATE st = { .l = { rm[0], rm[1] } };
>      int i;
>
>      assert(decrypt < 2);
> @@ -213,8 +206,8 @@ void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm,
>              rol32(mc[decrypt][CR_ST_BYTE(st, i + 3)], 24);
>      }
>
> -    env->vfp.regs[rd] = make_float64(st.l[0]);
> -    env->vfp.regs[rd + 1] = make_float64(st.l[1]);
> +    rd[0] = st.l[0];
> +    rd[1] = st.l[1];
>  }
>
>  /*
> @@ -236,21 +229,14 @@ static uint32_t maj(uint32_t x, uint32_t y, uint32_t z)
>      return (x & y) | ((x | y) & z);
>  }
>
> -void HELPER(crypto_sha1_3reg)(CPUARMState *env, uint32_t rd, uint32_t rn,
> -                              uint32_t rm, uint32_t op)
> +void HELPER(crypto_sha1_3reg)(void *vd, void *vn, void *vm, uint32_t op)
>  {
> -    union CRYPTO_STATE d = { .l = {
> -        float64_val(env->vfp.regs[rd]),
> -        float64_val(env->vfp.regs[rd + 1])
> -    } };
> -    union CRYPTO_STATE n = { .l = {
> -        float64_val(env->vfp.regs[rn]),
> -        float64_val(env->vfp.regs[rn + 1])
> -    } };
> -    union CRYPTO_STATE m = { .l = {
> -        float64_val(env->vfp.regs[rm]),
> -        float64_val(env->vfp.regs[rm + 1])
> -    } };
> +    uint64_t *rd = vd;
> +    uint64_t *rn = vn;
> +    uint64_t *rm = vm;
> +    union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
> +    union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
> +    union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
>
>      if (op == 3) { /* sha1su0 */
>          d.l[0] ^= d.l[1] ^ m.l[0];
> @@ -284,42 +270,37 @@ void HELPER(crypto_sha1_3reg)(CPUARMState *env, uint32_t rd, uint32_t rn,
>              CR_ST_WORD(d, 0) = t;
>          }
>      }
> -    env->vfp.regs[rd] = make_float64(d.l[0]);
> -    env->vfp.regs[rd + 1] = make_float64(d.l[1]);
> +    rd[0] = d.l[0];
> +    rd[1] = d.l[1];
>  }
>
> -void HELPER(crypto_sha1h)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(crypto_sha1h)(void *vd, void *vm)
>  {
> -    union CRYPTO_STATE m = { .l = {
> -        float64_val(env->vfp.regs[rm]),
> -        float64_val(env->vfp.regs[rm + 1])
> -    } };
> +    uint64_t *rd = vd;
> +    uint64_t *rm = vm;
> +    union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
>
>      CR_ST_WORD(m, 0) = ror32(CR_ST_WORD(m, 0), 2);
>      CR_ST_WORD(m, 1) = CR_ST_WORD(m, 2) = CR_ST_WORD(m, 3) = 0;
>
> -    env->vfp.regs[rd] = make_float64(m.l[0]);
> -    env->vfp.regs[rd + 1] = make_float64(m.l[1]);
> +    rd[0] = m.l[0];
> +    rd[1] = m.l[1];
>  }
>
> -void HELPER(crypto_sha1su1)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(crypto_sha1su1)(void *vd, void *vm)
>  {
> -    union CRYPTO_STATE d = { .l = {
> -        float64_val(env->vfp.regs[rd]),
> -        float64_val(env->vfp.regs[rd + 1])
> -    } };
> -    union CRYPTO_STATE m = { .l = {
> -        float64_val(env->vfp.regs[rm]),
> -        float64_val(env->vfp.regs[rm + 1])
> -    } };
> +    uint64_t *rd = vd;
> +    uint64_t *rm = vm;
> +    union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
> +    union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
>
>      CR_ST_WORD(d, 0) = rol32(CR_ST_WORD(d, 0) ^ CR_ST_WORD(m, 1), 1);
>      CR_ST_WORD(d, 1) = rol32(CR_ST_WORD(d, 1) ^ CR_ST_WORD(m, 2), 1);
>      CR_ST_WORD(d, 2) = rol32(CR_ST_WORD(d, 2) ^ CR_ST_WORD(m, 3), 1);
>      CR_ST_WORD(d, 3) = rol32(CR_ST_WORD(d, 3) ^ CR_ST_WORD(d, 0), 1);
>
> -    env->vfp.regs[rd] = make_float64(d.l[0]);
> -    env->vfp.regs[rd + 1] = make_float64(d.l[1]);
> +    rd[0] = d.l[0];
> +    rd[1] = d.l[1];
>  }
>
>  /*
> @@ -347,21 +328,14 @@ static uint32_t s1(uint32_t x)
>      return ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10);
>  }
>
> -void HELPER(crypto_sha256h)(CPUARMState *env, uint32_t rd, uint32_t rn,
> -                            uint32_t rm)
> +void HELPER(crypto_sha256h)(void *vd, void *vn, void *vm)
>  {
> -    union CRYPTO_STATE d = { .l = {
> -        float64_val(env->vfp.regs[rd]),
> -        float64_val(env->vfp.regs[rd + 1])
> -    } };
> -    union CRYPTO_STATE n = { .l = {
> -        float64_val(env->vfp.regs[rn]),
> -        float64_val(env->vfp.regs[rn + 1])
> -    } };
> -    union CRYPTO_STATE m = { .l = {
> -        float64_val(env->vfp.regs[rm]),
> -        float64_val(env->vfp.regs[rm + 1])
> -    } };
> +    uint64_t *rd = vd;
> +    uint64_t *rn = vn;
> +    uint64_t *rm = vm;
> +    union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
> +    union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
> +    union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
>      int i;
>
>      for (i = 0; i < 4; i++) {
> @@ -383,25 +357,18 @@ void HELPER(crypto_sha256h)(CPUARMState *env, uint32_t rd, uint32_t rn,
>          CR_ST_WORD(d, 0) = t;
>      }
>
> -    env->vfp.regs[rd] = make_float64(d.l[0]);
> -    env->vfp.regs[rd + 1] = make_float64(d.l[1]);
> +    rd[0] = d.l[0];
> +    rd[1] = d.l[1];
>  }
>
> -void HELPER(crypto_sha256h2)(CPUARMState *env, uint32_t rd, uint32_t rn,
> -                             uint32_t rm)
> +void HELPER(crypto_sha256h2)(void *vd, void *vn, void *vm)
>  {
> -    union CRYPTO_STATE d = { .l = {
> -        float64_val(env->vfp.regs[rd]),
> -        float64_val(env->vfp.regs[rd + 1])
> -    } };
> -    union CRYPTO_STATE n = { .l = {
> -        float64_val(env->vfp.regs[rn]),
> -        float64_val(env->vfp.regs[rn + 1])
> -    } };
> -    union CRYPTO_STATE m = { .l = {
> -        float64_val(env->vfp.regs[rm]),
> -        float64_val(env->vfp.regs[rm + 1])
> -    } };
> +    uint64_t *rd = vd;
> +    uint64_t *rn = vn;
> +    uint64_t *rm = vm;
> +    union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
> +    union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
> +    union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
>      int i;
>
>      for (i = 0; i < 4; i++) {
> @@ -415,51 +382,40 @@ void HELPER(crypto_sha256h2)(CPUARMState *env, uint32_t rd, uint32_t rn,
>          CR_ST_WORD(d, 0) = CR_ST_WORD(n, 3 - i) + t;
>      }
>
> -    env->vfp.regs[rd] = make_float64(d.l[0]);
> -    env->vfp.regs[rd + 1] = make_float64(d.l[1]);
> +    rd[0] = d.l[0];
> +    rd[1] = d.l[1];
>  }
>
> -void HELPER(crypto_sha256su0)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(crypto_sha256su0)(void *vd, void *vm)
>  {
> -    union CRYPTO_STATE d = { .l = {
> -        float64_val(env->vfp.regs[rd]),
> -        float64_val(env->vfp.regs[rd + 1])
> -    } };
> -    union CRYPTO_STATE m = { .l = {
> -        float64_val(env->vfp.regs[rm]),
> -        float64_val(env->vfp.regs[rm + 1])
> -    } };
> +    uint64_t *rd = vd;
> +    uint64_t *rm = vm;
> +    union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
> +    union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
>
>      CR_ST_WORD(d, 0) += s0(CR_ST_WORD(d, 1));
>      CR_ST_WORD(d, 1) += s0(CR_ST_WORD(d, 2));
>      CR_ST_WORD(d, 2) += s0(CR_ST_WORD(d, 3));
>      CR_ST_WORD(d, 3) += s0(CR_ST_WORD(m, 0));
>
> -    env->vfp.regs[rd] = make_float64(d.l[0]);
> -    env->vfp.regs[rd + 1] = make_float64(d.l[1]);
> +    rd[0] = d.l[0];
> +    rd[1] = d.l[1];
>  }
>
> -void HELPER(crypto_sha256su1)(CPUARMState *env, uint32_t rd, uint32_t rn,
> -                              uint32_t rm)
> +void HELPER(crypto_sha256su1)(void *vd, void *vn, void *vm)
>  {
> -    union CRYPTO_STATE d = { .l = {
> -        float64_val(env->vfp.regs[rd]),
> -        float64_val(env->vfp.regs[rd + 1])
> -    } };
> -    union CRYPTO_STATE n = { .l = {
> -        float64_val(env->vfp.regs[rn]),
> -        float64_val(env->vfp.regs[rn + 1])
> -    } };
> -    union CRYPTO_STATE m = { .l = {
> -        float64_val(env->vfp.regs[rm]),
> -        float64_val(env->vfp.regs[rm + 1])
> -    } };
> +    uint64_t *rd = vd;
> +    uint64_t *rn = vn;
> +    uint64_t *rm = vm;
> +    union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
> +    union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
> +    union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
>
>      CR_ST_WORD(d, 0) += s1(CR_ST_WORD(m, 2)) + CR_ST_WORD(n, 1);
>      CR_ST_WORD(d, 1) += s1(CR_ST_WORD(m, 3)) + CR_ST_WORD(n, 2);
>      CR_ST_WORD(d, 2) += s1(CR_ST_WORD(d, 0)) + CR_ST_WORD(n, 3);
>      CR_ST_WORD(d, 3) += s1(CR_ST_WORD(d, 1)) + CR_ST_WORD(m, 0);
>
> -    env->vfp.regs[rd] = make_float64(d.l[0]);
> -    env->vfp.regs[rd + 1] = make_float64(d.l[1]);
> +    rd[0] = d.l[0];
> +    rd[1] = d.l[1];
>  }
> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
> index 70c1e08a36..6d9b3af64c 100644
> --- a/target/arm/translate-a64.c
> +++ b/target/arm/translate-a64.c
> @@ -80,8 +80,9 @@ typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
>  typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
>  typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
>  typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64);
> -typedef void CryptoTwoOpEnvFn(TCGv_ptr, TCGv_i32, TCGv_i32);
> -typedef void CryptoThreeOpEnvFn(TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32);
> +typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr);
> +typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
> +typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
>
>  /* initialize TCG globals.  */
>  void a64_translate_init(void)
> @@ -535,6 +536,21 @@ static inline int vec_reg_offset(DisasContext *s, int regno,
>      return offs;
>  }
>
> +/* Return the offset info CPUARMState of the "whole" vector register Qn.  */
> +static inline int vec_full_reg_offset(DisasContext *s, int regno)
> +{
> +    assert_fp_access_checked(s);
> +    return offsetof(CPUARMState, vfp.regs[regno * 2]);
> +}
> +
> +/* Return a newly allocated pointer to the vector register.  */
> +static TCGv_ptr vec_full_reg_ptr(DisasContext *s, int regno)
> +{
> +    TCGv_ptr ret = tcg_temp_new_ptr();
> +    tcg_gen_addi_ptr(ret, cpu_env, vec_full_reg_offset(s, regno));
> +    return ret;
> +}
> +
>  /* Return the offset into CPUARMState of a slice (from
>   * the least significant end) of FP register Qn (ie
>   * Dn, Sn, Hn or Bn).
> @@ -10949,8 +10965,9 @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
>      int rn = extract32(insn, 5, 5);
>      int rd = extract32(insn, 0, 5);
>      int decrypt;
> -    TCGv_i32 tcg_rd_regno, tcg_rn_regno, tcg_decrypt;
> -    CryptoThreeOpEnvFn *genfn;
> +    TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
> +    TCGv_i32 tcg_decrypt;
> +    CryptoThreeOpIntFn *genfn;
>
>      if (!arm_dc_feature(s, ARM_FEATURE_V8_AES)
>          || size != 0) {
> @@ -10984,18 +11001,14 @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
>          return;
>      }
>
> -    /* Note that we convert the Vx register indexes into the
> -     * index within the vfp.regs[] array, so we can share the
> -     * helper with the AArch32 instructions.
> -     */
> -    tcg_rd_regno = tcg_const_i32(rd << 1);
> -    tcg_rn_regno = tcg_const_i32(rn << 1);
> +    tcg_rd_ptr = vec_full_reg_ptr(s, rd);
> +    tcg_rn_ptr = vec_full_reg_ptr(s, rn);
>      tcg_decrypt = tcg_const_i32(decrypt);
>
> -    genfn(cpu_env, tcg_rd_regno, tcg_rn_regno, tcg_decrypt);
> +    genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_decrypt);
>
> -    tcg_temp_free_i32(tcg_rd_regno);
> -    tcg_temp_free_i32(tcg_rn_regno);
> +    tcg_temp_free_ptr(tcg_rd_ptr);
> +    tcg_temp_free_ptr(tcg_rn_ptr);
>      tcg_temp_free_i32(tcg_decrypt);
>  }
>
> @@ -11012,8 +11025,8 @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
>      int rm = extract32(insn, 16, 5);
>      int rn = extract32(insn, 5, 5);
>      int rd = extract32(insn, 0, 5);
> -    CryptoThreeOpEnvFn *genfn;
> -    TCGv_i32 tcg_rd_regno, tcg_rn_regno, tcg_rm_regno;
> +    CryptoThreeOpFn *genfn;
> +    TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
>      int feature = ARM_FEATURE_V8_SHA256;
>
>      if (size != 0) {
> @@ -11052,23 +11065,23 @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
>          return;
>      }
>
> -    tcg_rd_regno = tcg_const_i32(rd << 1);
> -    tcg_rn_regno = tcg_const_i32(rn << 1);
> -    tcg_rm_regno = tcg_const_i32(rm << 1);
> +    tcg_rd_ptr = vec_full_reg_ptr(s, rd);
> +    tcg_rn_ptr = vec_full_reg_ptr(s, rn);
> +    tcg_rm_ptr = vec_full_reg_ptr(s, rm);
>
>      if (genfn) {
> -        genfn(cpu_env, tcg_rd_regno, tcg_rn_regno, tcg_rm_regno);
> +        genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
>      } else {
>          TCGv_i32 tcg_opcode = tcg_const_i32(opcode);
>
> -        gen_helper_crypto_sha1_3reg(cpu_env, tcg_rd_regno,
> -                                    tcg_rn_regno, tcg_rm_regno, tcg_opcode);
> +        gen_helper_crypto_sha1_3reg(tcg_rd_ptr, tcg_rn_ptr,
> +                                    tcg_rm_ptr, tcg_opcode);
>          tcg_temp_free_i32(tcg_opcode);
>      }
>
> -    tcg_temp_free_i32(tcg_rd_regno);
> -    tcg_temp_free_i32(tcg_rn_regno);
> -    tcg_temp_free_i32(tcg_rm_regno);
> +    tcg_temp_free_ptr(tcg_rd_ptr);
> +    tcg_temp_free_ptr(tcg_rn_ptr);
> +    tcg_temp_free_ptr(tcg_rm_ptr);
>  }
>
>  /* Crypto two-reg SHA
> @@ -11083,9 +11096,9 @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
>      int opcode = extract32(insn, 12, 5);
>      int rn = extract32(insn, 5, 5);
>      int rd = extract32(insn, 0, 5);
> -    CryptoTwoOpEnvFn *genfn;
> +    CryptoTwoOpFn *genfn;
>      int feature;
> -    TCGv_i32 tcg_rd_regno, tcg_rn_regno;
> +    TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
>
>      if (size != 0) {
>          unallocated_encoding(s);
> @@ -11119,13 +11132,13 @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
>          return;
>      }
>
> -    tcg_rd_regno = tcg_const_i32(rd << 1);
> -    tcg_rn_regno = tcg_const_i32(rn << 1);
> +    tcg_rd_ptr = vec_full_reg_ptr(s, rd);
> +    tcg_rn_ptr = vec_full_reg_ptr(s, rn);
>
> -    genfn(cpu_env, tcg_rd_regno, tcg_rn_regno);
> +    genfn(tcg_rd_ptr, tcg_rn_ptr);
>
> -    tcg_temp_free_i32(tcg_rd_regno);
> -    tcg_temp_free_i32(tcg_rn_regno);
> +    tcg_temp_free_ptr(tcg_rd_ptr);
> +    tcg_temp_free_ptr(tcg_rn_ptr);
>  }
>
>  /* C3.6 Data processing - SIMD, inc Crypto
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index 781be1e219..7b5db15861 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -1559,6 +1559,13 @@ static inline void neon_store_reg64(TCGv_i64 var, int reg)
>      tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
>  }
>
> +static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
> +{
> +    TCGv_ptr ret = tcg_temp_new_ptr();
> +    tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
> +    return ret;
> +}
> +
>  #define tcg_gen_ld_f32 tcg_gen_ld_i32
>  #define tcg_gen_ld_f64 tcg_gen_ld_i64
>  #define tcg_gen_st_f32 tcg_gen_st_i32
> @@ -5597,6 +5604,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
>      int u;
>      uint32_t imm, mask;
>      TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
> +    TCGv_ptr ptr1, ptr2, ptr3;
>      TCGv_i64 tmp64;
>
>      /* FIXME: this access check should not take precedence over UNDEF
> @@ -5643,34 +5651,34 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
>                  if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) {
>                      return 1;
>                  }
> -                tmp = tcg_const_i32(rd);
> -                tmp2 = tcg_const_i32(rn);
> -                tmp3 = tcg_const_i32(rm);
> +                ptr1 = vfp_reg_ptr(true, rd);
> +                ptr2 = vfp_reg_ptr(true, rn);
> +                ptr3 = vfp_reg_ptr(true, rm);
>                  tmp4 = tcg_const_i32(size);
> -                gen_helper_crypto_sha1_3reg(cpu_env, tmp, tmp2, tmp3, tmp4);
> +                gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4);
>                  tcg_temp_free_i32(tmp4);
>              } else { /* SHA-256 */
>                  if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA256) || size == 3) {
>                      return 1;
>                  }
> -                tmp = tcg_const_i32(rd);
> -                tmp2 = tcg_const_i32(rn);
> -                tmp3 = tcg_const_i32(rm);
> +                ptr1 = vfp_reg_ptr(true, rd);
> +                ptr2 = vfp_reg_ptr(true, rn);
> +                ptr3 = vfp_reg_ptr(true, rm);
>                  switch (size) {
>                  case 0:
> -                    gen_helper_crypto_sha256h(cpu_env, tmp, tmp2, tmp3);
> +                    gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
>                      break;
>                  case 1:
> -                    gen_helper_crypto_sha256h2(cpu_env, tmp, tmp2, tmp3);
> +                    gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
>                      break;
>                  case 2:
> -                    gen_helper_crypto_sha256su1(cpu_env, tmp, tmp2, tmp3);
> +                    gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
>                      break;
>                  }
>              }
> -            tcg_temp_free_i32(tmp);
> -            tcg_temp_free_i32(tmp2);
> -            tcg_temp_free_i32(tmp3);
> +            tcg_temp_free_ptr(ptr1);
> +            tcg_temp_free_ptr(ptr2);
> +            tcg_temp_free_ptr(ptr3);
>              return 0;
>          }
>          if (size == 3 && op != NEON_3R_LOGIC) {
> @@ -7159,8 +7167,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
>                          || ((rm | rd) & 1)) {
>                          return 1;
>                      }
> -                    tmp = tcg_const_i32(rd);
> -                    tmp2 = tcg_const_i32(rm);
> +                    ptr1 = vfp_reg_ptr(true, rd);
> +                    ptr2 = vfp_reg_ptr(true, rm);
>
>                       /* Bit 6 is the lowest opcode bit; it distinguishes between
>                        * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
> @@ -7168,12 +7176,12 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
>                      tmp3 = tcg_const_i32(extract32(insn, 6, 1));
>
>                      if (op == NEON_2RM_AESE) {
> -                        gen_helper_crypto_aese(cpu_env, tmp, tmp2, tmp3);
> +                        gen_helper_crypto_aese(ptr1, ptr2, tmp3);
>                      } else {
> -                        gen_helper_crypto_aesmc(cpu_env, tmp, tmp2, tmp3);
> +                        gen_helper_crypto_aesmc(ptr1, ptr2, tmp3);
>                      }
> -                    tcg_temp_free_i32(tmp);
> -                    tcg_temp_free_i32(tmp2);
> +                    tcg_temp_free_ptr(ptr1);
> +                    tcg_temp_free_ptr(ptr2);
>                      tcg_temp_free_i32(tmp3);
>                      break;
>                  case NEON_2RM_SHA1H:
> @@ -7181,13 +7189,13 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
>                          || ((rm | rd) & 1)) {
>                          return 1;
>                      }
> -                    tmp = tcg_const_i32(rd);
> -                    tmp2 = tcg_const_i32(rm);
> +                    ptr1 = vfp_reg_ptr(true, rd);
> +                    ptr2 = vfp_reg_ptr(true, rm);
>
> -                    gen_helper_crypto_sha1h(cpu_env, tmp, tmp2);
> +                    gen_helper_crypto_sha1h(ptr1, ptr2);
>
> -                    tcg_temp_free_i32(tmp);
> -                    tcg_temp_free_i32(tmp2);
> +                    tcg_temp_free_ptr(ptr1);
> +                    tcg_temp_free_ptr(ptr2);
>                      break;
>                  case NEON_2RM_SHA1SU1:
>                      if ((rm | rd) & 1) {
> @@ -7201,15 +7209,15 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
>                      } else if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) {
>                          return 1;
>                      }
> -                    tmp = tcg_const_i32(rd);
> -                    tmp2 = tcg_const_i32(rm);
> +                    ptr1 = vfp_reg_ptr(true, rd);
> +                    ptr2 = vfp_reg_ptr(true, rm);
>                      if (q) {
> -                        gen_helper_crypto_sha256su0(cpu_env, tmp, tmp2);
> +                        gen_helper_crypto_sha256su0(ptr1, ptr2);
>                      } else {
> -                        gen_helper_crypto_sha1su1(cpu_env, tmp, tmp2);
> +                        gen_helper_crypto_sha1su1(ptr1, ptr2);
>                      }
> -                    tcg_temp_free_i32(tmp);
> -                    tcg_temp_free_i32(tmp2);
> +                    tcg_temp_free_ptr(ptr1);
> +                    tcg_temp_free_ptr(ptr2);
>                      break;
>                  default:
>                  elementwise:


--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 03/16] target/arm: Use pointers in neon zip/uzp helpers
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 03/16] target/arm: Use pointers in neon zip/uzp helpers Richard Henderson
@ 2018-01-22 10:44   ` Alex Bennée
  2018-01-22 10:44   ` Alex Bennée
  1 sibling, 0 replies; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 10:44 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> Rather than passing regnos to the helpers, pass pointers to the
> vector registers directly.  This eliminates the need to pass in
> the environment pointer and reduces the number of places that
> directly access env->vfp.regs[].
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target/arm/helper.h      |  20 +++---
>  target/arm/neon_helper.c | 162 +++++++++++++++++++++++++----------------------
>  target/arm/translate.c   |  42 ++++++------
>  3 files changed, 120 insertions(+), 104 deletions(-)
>
> diff --git a/target/arm/helper.h b/target/arm/helper.h
> index 688380af6b..dbdc38fcb7 100644
> --- a/target/arm/helper.h
> +++ b/target/arm/helper.h
> @@ -511,16 +511,16 @@ DEF_HELPER_3(iwmmxt_muladdsl, i64, i64, i32, i32)
>  DEF_HELPER_3(iwmmxt_muladdsw, i64, i64, i32, i32)
>  DEF_HELPER_3(iwmmxt_muladdswl, i64, i64, i32, i32)
>
> -DEF_HELPER_3(neon_unzip8, void, env, i32, i32)
> -DEF_HELPER_3(neon_unzip16, void, env, i32, i32)
> -DEF_HELPER_3(neon_qunzip8, void, env, i32, i32)
> -DEF_HELPER_3(neon_qunzip16, void, env, i32, i32)
> -DEF_HELPER_3(neon_qunzip32, void, env, i32, i32)
> -DEF_HELPER_3(neon_zip8, void, env, i32, i32)
> -DEF_HELPER_3(neon_zip16, void, env, i32, i32)
> -DEF_HELPER_3(neon_qzip8, void, env, i32, i32)
> -DEF_HELPER_3(neon_qzip16, void, env, i32, i32)
> -DEF_HELPER_3(neon_qzip32, void, env, i32, i32)
> +DEF_HELPER_FLAGS_2(neon_unzip8, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_unzip16, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_qunzip8, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_qunzip16, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_qunzip32, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_zip8, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_zip16, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_qzip8, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_qzip16, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_qzip32, TCG_CALL_NO_RWG, void, ptr, ptr)
>
>  DEF_HELPER_FLAGS_3(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
>  DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
> diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c
> index ebdf7c9b10..689491cad3 100644
> --- a/target/arm/neon_helper.c
> +++ b/target/arm/neon_helper.c
> @@ -2027,12 +2027,12 @@ uint64_t HELPER(neon_acgt_f64)(uint64_t a, uint64_t b, void *fpstp)
>
>  #define ELEM(V, N, SIZE) (((V) >> ((N) * (SIZE))) & ((1ull << (SIZE)) - 1))
>
> -void HELPER(neon_qunzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_qunzip8)(void *vd, void *vm)
>  {
> -    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
> -    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
> -    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
> -    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd0 = rd[0], zd1 = rd[1];
> +    uint64_t zm0 = rm[0], zm1 = rm[1];
> +
>      uint64_t d0 = ELEM(zd0, 0, 8) | (ELEM(zd0, 2, 8) << 8)
>          | (ELEM(zd0, 4, 8) << 16) | (ELEM(zd0, 6, 8) << 24)
>          | (ELEM(zd1, 0, 8) << 32) | (ELEM(zd1, 2, 8) << 40)
> @@ -2049,18 +2049,19 @@ void HELPER(neon_qunzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
>          | (ELEM(zm0, 5, 8) << 16) | (ELEM(zm0, 7, 8) << 24)
>          | (ELEM(zm1, 1, 8) << 32) | (ELEM(zm1, 3, 8) << 40)
>          | (ELEM(zm1, 5, 8) << 48) | (ELEM(zm1, 7, 8) << 56);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rm + 1] = make_float64(m1);
> -    env->vfp.regs[rd] = make_float64(d0);
> -    env->vfp.regs[rd + 1] = make_float64(d1);
> +
> +    rm[0] = m0;
> +    rm[1] = m1;
> +    rd[0] = d0;
> +    rd[1] = d1;
>  }
>
> -void HELPER(neon_qunzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_qunzip16)(void *vd, void *vm)
>  {
> -    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
> -    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
> -    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
> -    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd0 = rd[0], zd1 = rd[1];
> +    uint64_t zm0 = rm[0], zm1 = rm[1];
> +
>      uint64_t d0 = ELEM(zd0, 0, 16) | (ELEM(zd0, 2, 16) << 16)
>          | (ELEM(zd1, 0, 16) << 32) | (ELEM(zd1, 2, 16) << 48);
>      uint64_t d1 = ELEM(zm0, 0, 16) | (ELEM(zm0, 2, 16) << 16)
> @@ -2069,32 +2070,35 @@ void HELPER(neon_qunzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
>          | (ELEM(zd1, 1, 16) << 32) | (ELEM(zd1, 3, 16) << 48);
>      uint64_t m1 = ELEM(zm0, 1, 16) | (ELEM(zm0, 3, 16) << 16)
>          | (ELEM(zm1, 1, 16) << 32) | (ELEM(zm1, 3, 16) << 48);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rm + 1] = make_float64(m1);
> -    env->vfp.regs[rd] = make_float64(d0);
> -    env->vfp.regs[rd + 1] = make_float64(d1);
> +
> +    rm[0] = m0;
> +    rm[1] = m1;
> +    rd[0] = d0;
> +    rd[1] = d1;
>  }
>
> -void HELPER(neon_qunzip32)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_qunzip32)(void *vd, void *vm)
>  {
> -    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
> -    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
> -    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
> -    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd0 = rd[0], zd1 = rd[1];
> +    uint64_t zm0 = rm[0], zm1 = rm[1];
> +
>      uint64_t d0 = ELEM(zd0, 0, 32) | (ELEM(zd1, 0, 32) << 32);
>      uint64_t d1 = ELEM(zm0, 0, 32) | (ELEM(zm1, 0, 32) << 32);
>      uint64_t m0 = ELEM(zd0, 1, 32) | (ELEM(zd1, 1, 32) << 32);
>      uint64_t m1 = ELEM(zm0, 1, 32) | (ELEM(zm1, 1, 32) << 32);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rm + 1] = make_float64(m1);
> -    env->vfp.regs[rd] = make_float64(d0);
> -    env->vfp.regs[rd + 1] = make_float64(d1);
> +
> +    rm[0] = m0;
> +    rm[1] = m1;
> +    rd[0] = d0;
> +    rd[1] = d1;
>  }
>
> -void HELPER(neon_unzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_unzip8)(void *vd, void *vm)
>  {
> -    uint64_t zm = float64_val(env->vfp.regs[rm]);
> -    uint64_t zd = float64_val(env->vfp.regs[rd]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd = rd[0], zm = rm[0];
> +
>      uint64_t d0 = ELEM(zd, 0, 8) | (ELEM(zd, 2, 8) << 8)
>          | (ELEM(zd, 4, 8) << 16) | (ELEM(zd, 6, 8) << 24)
>          | (ELEM(zm, 0, 8) << 32) | (ELEM(zm, 2, 8) << 40)
> @@ -2103,28 +2107,31 @@ void HELPER(neon_unzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
>          | (ELEM(zd, 5, 8) << 16) | (ELEM(zd, 7, 8) << 24)
>          | (ELEM(zm, 1, 8) << 32) | (ELEM(zm, 3, 8) << 40)
>          | (ELEM(zm, 5, 8) << 48) | (ELEM(zm, 7, 8) << 56);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rd] = make_float64(d0);
> +
> +    rm[0] = m0;
> +    rd[0] = d0;
>  }
>
> -void HELPER(neon_unzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_unzip16)(void *vd, void *vm)
>  {
> -    uint64_t zm = float64_val(env->vfp.regs[rm]);
> -    uint64_t zd = float64_val(env->vfp.regs[rd]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd = rd[0], zm = rm[0];
> +
>      uint64_t d0 = ELEM(zd, 0, 16) | (ELEM(zd, 2, 16) << 16)
>          | (ELEM(zm, 0, 16) << 32) | (ELEM(zm, 2, 16) << 48);
>      uint64_t m0 = ELEM(zd, 1, 16) | (ELEM(zd, 3, 16) << 16)
>          | (ELEM(zm, 1, 16) << 32) | (ELEM(zm, 3, 16) << 48);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rd] = make_float64(d0);
> +
> +    rm[0] = m0;
> +    rd[0] = d0;
>  }
>
> -void HELPER(neon_qzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_qzip8)(void *vd, void *vm)
>  {
> -    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
> -    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
> -    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
> -    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd0 = rd[0], zd1 = rd[1];
> +    uint64_t zm0 = rm[0], zm1 = rm[1];
> +
>      uint64_t d0 = ELEM(zd0, 0, 8) | (ELEM(zm0, 0, 8) << 8)
>          | (ELEM(zd0, 1, 8) << 16) | (ELEM(zm0, 1, 8) << 24)
>          | (ELEM(zd0, 2, 8) << 32) | (ELEM(zm0, 2, 8) << 40)
> @@ -2141,18 +2148,19 @@ void HELPER(neon_qzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
>          | (ELEM(zd1, 5, 8) << 16) | (ELEM(zm1, 5, 8) << 24)
>          | (ELEM(zd1, 6, 8) << 32) | (ELEM(zm1, 6, 8) << 40)
>          | (ELEM(zd1, 7, 8) << 48) | (ELEM(zm1, 7, 8) << 56);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rm + 1] = make_float64(m1);
> -    env->vfp.regs[rd] = make_float64(d0);
> -    env->vfp.regs[rd + 1] = make_float64(d1);
> +
> +    rm[0] = m0;
> +    rm[1] = m1;
> +    rd[0] = d0;
> +    rd[1] = d1;
>  }
>
> -void HELPER(neon_qzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_qzip16)(void *vd, void *vm)
>  {
> -    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
> -    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
> -    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
> -    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd0 = rd[0], zd1 = rd[1];
> +    uint64_t zm0 = rm[0], zm1 = rm[1];
> +
>      uint64_t d0 = ELEM(zd0, 0, 16) | (ELEM(zm0, 0, 16) << 16)
>          | (ELEM(zd0, 1, 16) << 32) | (ELEM(zm0, 1, 16) << 48);
>      uint64_t d1 = ELEM(zd0, 2, 16) | (ELEM(zm0, 2, 16) << 16)
> @@ -2161,32 +2169,35 @@ void HELPER(neon_qzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
>          | (ELEM(zd1, 1, 16) << 32) | (ELEM(zm1, 1, 16) << 48);
>      uint64_t m1 = ELEM(zd1, 2, 16) | (ELEM(zm1, 2, 16) << 16)
>          | (ELEM(zd1, 3, 16) << 32) | (ELEM(zm1, 3, 16) << 48);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rm + 1] = make_float64(m1);
> -    env->vfp.regs[rd] = make_float64(d0);
> -    env->vfp.regs[rd + 1] = make_float64(d1);
> +
> +    rm[0] = m0;
> +    rm[1] = m1;
> +    rd[0] = d0;
> +    rd[1] = d1;
>  }
>
> -void HELPER(neon_qzip32)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_qzip32)(void *vd, void *vm)
>  {
> -    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
> -    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
> -    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
> -    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd0 = rd[0], zd1 = rd[1];
> +    uint64_t zm0 = rm[0], zm1 = rm[1];
> +
>      uint64_t d0 = ELEM(zd0, 0, 32) | (ELEM(zm0, 0, 32) << 32);
>      uint64_t d1 = ELEM(zd0, 1, 32) | (ELEM(zm0, 1, 32) << 32);
>      uint64_t m0 = ELEM(zd1, 0, 32) | (ELEM(zm1, 0, 32) << 32);
>      uint64_t m1 = ELEM(zd1, 1, 32) | (ELEM(zm1, 1, 32) << 32);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rm + 1] = make_float64(m1);
> -    env->vfp.regs[rd] = make_float64(d0);
> -    env->vfp.regs[rd + 1] = make_float64(d1);
> +
> +    rm[0] = m0;
> +    rm[1] = m1;
> +    rd[0] = d0;
> +    rd[1] = d1;
>  }
>
> -void HELPER(neon_zip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_zip8)(void *vd, void *vm)
>  {
> -    uint64_t zm = float64_val(env->vfp.regs[rm]);
> -    uint64_t zd = float64_val(env->vfp.regs[rd]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd = rd[0], zm = rm[0];
> +
>      uint64_t d0 = ELEM(zd, 0, 8) | (ELEM(zm, 0, 8) << 8)
>          | (ELEM(zd, 1, 8) << 16) | (ELEM(zm, 1, 8) << 24)
>          | (ELEM(zd, 2, 8) << 32) | (ELEM(zm, 2, 8) << 40)
> @@ -2195,20 +2206,23 @@ void HELPER(neon_zip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
>          | (ELEM(zd, 5, 8) << 16) | (ELEM(zm, 5, 8) << 24)
>          | (ELEM(zd, 6, 8) << 32) | (ELEM(zm, 6, 8) << 40)
>          | (ELEM(zd, 7, 8) << 48) | (ELEM(zm, 7, 8) << 56);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rd] = make_float64(d0);
> +
> +    rm[0] = m0;
> +    rd[0] = d0;
>  }
>
> -void HELPER(neon_zip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_zip16)(void *vd, void *vm)
>  {
> -    uint64_t zm = float64_val(env->vfp.regs[rm]);
> -    uint64_t zd = float64_val(env->vfp.regs[rd]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd = rd[0], zm = rm[0];
> +
>      uint64_t d0 = ELEM(zd, 0, 16) | (ELEM(zm, 0, 16) << 16)
>          | (ELEM(zd, 1, 16) << 32) | (ELEM(zm, 1, 16) << 48);
>      uint64_t m0 = ELEM(zd, 2, 16) | (ELEM(zm, 2, 16) << 16)
>          | (ELEM(zd, 3, 16) << 32) | (ELEM(zm, 3, 16) << 48);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rd] = make_float64(d0);
> +
> +    rm[0] = m0;
> +    rd[0] = d0;
>  }
>
>  /* Helper function for 64 bit polynomial multiply case:
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index 7b5db15861..6f02c56abb 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -4687,22 +4687,23 @@ static inline TCGv_i32 neon_get_scalar(int size, int reg)
>
>  static int gen_neon_unzip(int rd, int rm, int size, int q)
>  {
> -    TCGv_i32 tmp, tmp2;
> +    TCGv_ptr pd, pm;
> +
>      if (!q && size == 2) {
>          return 1;
>      }
> -    tmp = tcg_const_i32(rd);
> -    tmp2 = tcg_const_i32(rm);
> +    pd = vfp_reg_ptr(true, rd);
> +    pm = vfp_reg_ptr(true, rm);
>      if (q) {
>          switch (size) {
>          case 0:
> -            gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
> +            gen_helper_neon_qunzip8(pd, pm);
>              break;
>          case 1:
> -            gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
> +            gen_helper_neon_qunzip16(pd, pm);
>              break;
>          case 2:
> -            gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
> +            gen_helper_neon_qunzip32(pd, pm);
>              break;
>          default:
>              abort();
> @@ -4710,38 +4711,39 @@ static int gen_neon_unzip(int rd, int rm, int size, int q)
>      } else {
>          switch (size) {
>          case 0:
> -            gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
> +            gen_helper_neon_unzip8(pd, pm);
>              break;
>          case 1:
> -            gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
> +            gen_helper_neon_unzip16(pd, pm);
>              break;
>          default:
>              abort();
>          }
>      }
> -    tcg_temp_free_i32(tmp);
> -    tcg_temp_free_i32(tmp2);
> +    tcg_temp_free_ptr(pd);
> +    tcg_temp_free_ptr(pm);
>      return 0;
>  }
>
>  static int gen_neon_zip(int rd, int rm, int size, int q)
>  {
> -    TCGv_i32 tmp, tmp2;
> +    TCGv_ptr pd, pm;
> +
>      if (!q && size == 2) {
>          return 1;
>      }
> -    tmp = tcg_const_i32(rd);
> -    tmp2 = tcg_const_i32(rm);
> +    pd = vfp_reg_ptr(true, rd);
> +    pm = vfp_reg_ptr(true, rm);
>      if (q) {
>          switch (size) {
>          case 0:
> -            gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
> +            gen_helper_neon_qzip8(pd, pm);
>              break;
>          case 1:
> -            gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
> +            gen_helper_neon_qzip16(pd, pm);
>              break;
>          case 2:
> -            gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
> +            gen_helper_neon_qzip32(pd, pm);
>              break;
>          default:
>              abort();
> @@ -4749,17 +4751,17 @@ static int gen_neon_zip(int rd, int rm, int size, int q)
>      } else {
>          switch (size) {
>          case 0:
> -            gen_helper_neon_zip8(cpu_env, tmp, tmp2);
> +            gen_helper_neon_zip8(pd, pm);
>              break;
>          case 1:
> -            gen_helper_neon_zip16(cpu_env, tmp, tmp2);
> +            gen_helper_neon_zip16(pd, pm);
>              break;
>          default:
>              abort();
>          }
>      }
> -    tcg_temp_free_i32(tmp);
> -    tcg_temp_free_i32(tmp2);
> +    tcg_temp_free_ptr(pd);
> +    tcg_temp_free_ptr(pm);
>      return 0;
>  }


--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 03/16] target/arm: Use pointers in neon zip/uzp helpers
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 03/16] target/arm: Use pointers in neon zip/uzp helpers Richard Henderson
  2018-01-22 10:44   ` Alex Bennée
@ 2018-01-22 10:44   ` Alex Bennée
  1 sibling, 0 replies; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 10:44 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> Rather than passing regnos to the helpers, pass pointers to the
> vector registers directly.  This eliminates the need to pass in
> the environment pointer and reduces the number of places that
> directly access env->vfp.regs[].
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target/arm/helper.h      |  20 +++---
>  target/arm/neon_helper.c | 162 +++++++++++++++++++++++++----------------------
>  target/arm/translate.c   |  42 ++++++------
>  3 files changed, 120 insertions(+), 104 deletions(-)
>
> diff --git a/target/arm/helper.h b/target/arm/helper.h
> index 688380af6b..dbdc38fcb7 100644
> --- a/target/arm/helper.h
> +++ b/target/arm/helper.h
> @@ -511,16 +511,16 @@ DEF_HELPER_3(iwmmxt_muladdsl, i64, i64, i32, i32)
>  DEF_HELPER_3(iwmmxt_muladdsw, i64, i64, i32, i32)
>  DEF_HELPER_3(iwmmxt_muladdswl, i64, i64, i32, i32)
>
> -DEF_HELPER_3(neon_unzip8, void, env, i32, i32)
> -DEF_HELPER_3(neon_unzip16, void, env, i32, i32)
> -DEF_HELPER_3(neon_qunzip8, void, env, i32, i32)
> -DEF_HELPER_3(neon_qunzip16, void, env, i32, i32)
> -DEF_HELPER_3(neon_qunzip32, void, env, i32, i32)
> -DEF_HELPER_3(neon_zip8, void, env, i32, i32)
> -DEF_HELPER_3(neon_zip16, void, env, i32, i32)
> -DEF_HELPER_3(neon_qzip8, void, env, i32, i32)
> -DEF_HELPER_3(neon_qzip16, void, env, i32, i32)
> -DEF_HELPER_3(neon_qzip32, void, env, i32, i32)
> +DEF_HELPER_FLAGS_2(neon_unzip8, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_unzip16, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_qunzip8, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_qunzip16, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_qunzip32, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_zip8, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_zip16, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_qzip8, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_qzip16, TCG_CALL_NO_RWG, void, ptr, ptr)
> +DEF_HELPER_FLAGS_2(neon_qzip32, TCG_CALL_NO_RWG, void, ptr, ptr)
>
>  DEF_HELPER_FLAGS_3(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
>  DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
> diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c
> index ebdf7c9b10..689491cad3 100644
> --- a/target/arm/neon_helper.c
> +++ b/target/arm/neon_helper.c
> @@ -2027,12 +2027,12 @@ uint64_t HELPER(neon_acgt_f64)(uint64_t a, uint64_t b, void *fpstp)
>
>  #define ELEM(V, N, SIZE) (((V) >> ((N) * (SIZE))) & ((1ull << (SIZE)) - 1))
>
> -void HELPER(neon_qunzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_qunzip8)(void *vd, void *vm)
>  {
> -    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
> -    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
> -    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
> -    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd0 = rd[0], zd1 = rd[1];
> +    uint64_t zm0 = rm[0], zm1 = rm[1];
> +
>      uint64_t d0 = ELEM(zd0, 0, 8) | (ELEM(zd0, 2, 8) << 8)
>          | (ELEM(zd0, 4, 8) << 16) | (ELEM(zd0, 6, 8) << 24)
>          | (ELEM(zd1, 0, 8) << 32) | (ELEM(zd1, 2, 8) << 40)
> @@ -2049,18 +2049,19 @@ void HELPER(neon_qunzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
>          | (ELEM(zm0, 5, 8) << 16) | (ELEM(zm0, 7, 8) << 24)
>          | (ELEM(zm1, 1, 8) << 32) | (ELEM(zm1, 3, 8) << 40)
>          | (ELEM(zm1, 5, 8) << 48) | (ELEM(zm1, 7, 8) << 56);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rm + 1] = make_float64(m1);
> -    env->vfp.regs[rd] = make_float64(d0);
> -    env->vfp.regs[rd + 1] = make_float64(d1);
> +
> +    rm[0] = m0;
> +    rm[1] = m1;
> +    rd[0] = d0;
> +    rd[1] = d1;
>  }
>
> -void HELPER(neon_qunzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_qunzip16)(void *vd, void *vm)
>  {
> -    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
> -    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
> -    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
> -    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd0 = rd[0], zd1 = rd[1];
> +    uint64_t zm0 = rm[0], zm1 = rm[1];
> +
>      uint64_t d0 = ELEM(zd0, 0, 16) | (ELEM(zd0, 2, 16) << 16)
>          | (ELEM(zd1, 0, 16) << 32) | (ELEM(zd1, 2, 16) << 48);
>      uint64_t d1 = ELEM(zm0, 0, 16) | (ELEM(zm0, 2, 16) << 16)
> @@ -2069,32 +2070,35 @@ void HELPER(neon_qunzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
>          | (ELEM(zd1, 1, 16) << 32) | (ELEM(zd1, 3, 16) << 48);
>      uint64_t m1 = ELEM(zm0, 1, 16) | (ELEM(zm0, 3, 16) << 16)
>          | (ELEM(zm1, 1, 16) << 32) | (ELEM(zm1, 3, 16) << 48);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rm + 1] = make_float64(m1);
> -    env->vfp.regs[rd] = make_float64(d0);
> -    env->vfp.regs[rd + 1] = make_float64(d1);
> +
> +    rm[0] = m0;
> +    rm[1] = m1;
> +    rd[0] = d0;
> +    rd[1] = d1;
>  }
>
> -void HELPER(neon_qunzip32)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_qunzip32)(void *vd, void *vm)
>  {
> -    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
> -    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
> -    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
> -    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd0 = rd[0], zd1 = rd[1];
> +    uint64_t zm0 = rm[0], zm1 = rm[1];
> +
>      uint64_t d0 = ELEM(zd0, 0, 32) | (ELEM(zd1, 0, 32) << 32);
>      uint64_t d1 = ELEM(zm0, 0, 32) | (ELEM(zm1, 0, 32) << 32);
>      uint64_t m0 = ELEM(zd0, 1, 32) | (ELEM(zd1, 1, 32) << 32);
>      uint64_t m1 = ELEM(zm0, 1, 32) | (ELEM(zm1, 1, 32) << 32);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rm + 1] = make_float64(m1);
> -    env->vfp.regs[rd] = make_float64(d0);
> -    env->vfp.regs[rd + 1] = make_float64(d1);
> +
> +    rm[0] = m0;
> +    rm[1] = m1;
> +    rd[0] = d0;
> +    rd[1] = d1;
>  }
>
> -void HELPER(neon_unzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_unzip8)(void *vd, void *vm)
>  {
> -    uint64_t zm = float64_val(env->vfp.regs[rm]);
> -    uint64_t zd = float64_val(env->vfp.regs[rd]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd = rd[0], zm = rm[0];
> +
>      uint64_t d0 = ELEM(zd, 0, 8) | (ELEM(zd, 2, 8) << 8)
>          | (ELEM(zd, 4, 8) << 16) | (ELEM(zd, 6, 8) << 24)
>          | (ELEM(zm, 0, 8) << 32) | (ELEM(zm, 2, 8) << 40)
> @@ -2103,28 +2107,31 @@ void HELPER(neon_unzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
>          | (ELEM(zd, 5, 8) << 16) | (ELEM(zd, 7, 8) << 24)
>          | (ELEM(zm, 1, 8) << 32) | (ELEM(zm, 3, 8) << 40)
>          | (ELEM(zm, 5, 8) << 48) | (ELEM(zm, 7, 8) << 56);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rd] = make_float64(d0);
> +
> +    rm[0] = m0;
> +    rd[0] = d0;
>  }
>
> -void HELPER(neon_unzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_unzip16)(void *vd, void *vm)
>  {
> -    uint64_t zm = float64_val(env->vfp.regs[rm]);
> -    uint64_t zd = float64_val(env->vfp.regs[rd]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd = rd[0], zm = rm[0];
> +
>      uint64_t d0 = ELEM(zd, 0, 16) | (ELEM(zd, 2, 16) << 16)
>          | (ELEM(zm, 0, 16) << 32) | (ELEM(zm, 2, 16) << 48);
>      uint64_t m0 = ELEM(zd, 1, 16) | (ELEM(zd, 3, 16) << 16)
>          | (ELEM(zm, 1, 16) << 32) | (ELEM(zm, 3, 16) << 48);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rd] = make_float64(d0);
> +
> +    rm[0] = m0;
> +    rd[0] = d0;
>  }
>
> -void HELPER(neon_qzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_qzip8)(void *vd, void *vm)
>  {
> -    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
> -    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
> -    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
> -    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd0 = rd[0], zd1 = rd[1];
> +    uint64_t zm0 = rm[0], zm1 = rm[1];
> +
>      uint64_t d0 = ELEM(zd0, 0, 8) | (ELEM(zm0, 0, 8) << 8)
>          | (ELEM(zd0, 1, 8) << 16) | (ELEM(zm0, 1, 8) << 24)
>          | (ELEM(zd0, 2, 8) << 32) | (ELEM(zm0, 2, 8) << 40)
> @@ -2141,18 +2148,19 @@ void HELPER(neon_qzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
>          | (ELEM(zd1, 5, 8) << 16) | (ELEM(zm1, 5, 8) << 24)
>          | (ELEM(zd1, 6, 8) << 32) | (ELEM(zm1, 6, 8) << 40)
>          | (ELEM(zd1, 7, 8) << 48) | (ELEM(zm1, 7, 8) << 56);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rm + 1] = make_float64(m1);
> -    env->vfp.regs[rd] = make_float64(d0);
> -    env->vfp.regs[rd + 1] = make_float64(d1);
> +
> +    rm[0] = m0;
> +    rm[1] = m1;
> +    rd[0] = d0;
> +    rd[1] = d1;
>  }
>
> -void HELPER(neon_qzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_qzip16)(void *vd, void *vm)
>  {
> -    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
> -    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
> -    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
> -    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd0 = rd[0], zd1 = rd[1];
> +    uint64_t zm0 = rm[0], zm1 = rm[1];
> +
>      uint64_t d0 = ELEM(zd0, 0, 16) | (ELEM(zm0, 0, 16) << 16)
>          | (ELEM(zd0, 1, 16) << 32) | (ELEM(zm0, 1, 16) << 48);
>      uint64_t d1 = ELEM(zd0, 2, 16) | (ELEM(zm0, 2, 16) << 16)
> @@ -2161,32 +2169,35 @@ void HELPER(neon_qzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
>          | (ELEM(zd1, 1, 16) << 32) | (ELEM(zm1, 1, 16) << 48);
>      uint64_t m1 = ELEM(zd1, 2, 16) | (ELEM(zm1, 2, 16) << 16)
>          | (ELEM(zd1, 3, 16) << 32) | (ELEM(zm1, 3, 16) << 48);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rm + 1] = make_float64(m1);
> -    env->vfp.regs[rd] = make_float64(d0);
> -    env->vfp.regs[rd + 1] = make_float64(d1);
> +
> +    rm[0] = m0;
> +    rm[1] = m1;
> +    rd[0] = d0;
> +    rd[1] = d1;
>  }
>
> -void HELPER(neon_qzip32)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_qzip32)(void *vd, void *vm)
>  {
> -    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
> -    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
> -    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
> -    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd0 = rd[0], zd1 = rd[1];
> +    uint64_t zm0 = rm[0], zm1 = rm[1];
> +
>      uint64_t d0 = ELEM(zd0, 0, 32) | (ELEM(zm0, 0, 32) << 32);
>      uint64_t d1 = ELEM(zd0, 1, 32) | (ELEM(zm0, 1, 32) << 32);
>      uint64_t m0 = ELEM(zd1, 0, 32) | (ELEM(zm1, 0, 32) << 32);
>      uint64_t m1 = ELEM(zd1, 1, 32) | (ELEM(zm1, 1, 32) << 32);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rm + 1] = make_float64(m1);
> -    env->vfp.regs[rd] = make_float64(d0);
> -    env->vfp.regs[rd + 1] = make_float64(d1);
> +
> +    rm[0] = m0;
> +    rm[1] = m1;
> +    rd[0] = d0;
> +    rd[1] = d1;
>  }
>
> -void HELPER(neon_zip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_zip8)(void *vd, void *vm)
>  {
> -    uint64_t zm = float64_val(env->vfp.regs[rm]);
> -    uint64_t zd = float64_val(env->vfp.regs[rd]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd = rd[0], zm = rm[0];
> +
>      uint64_t d0 = ELEM(zd, 0, 8) | (ELEM(zm, 0, 8) << 8)
>          | (ELEM(zd, 1, 8) << 16) | (ELEM(zm, 1, 8) << 24)
>          | (ELEM(zd, 2, 8) << 32) | (ELEM(zm, 2, 8) << 40)
> @@ -2195,20 +2206,23 @@ void HELPER(neon_zip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
>          | (ELEM(zd, 5, 8) << 16) | (ELEM(zm, 5, 8) << 24)
>          | (ELEM(zd, 6, 8) << 32) | (ELEM(zm, 6, 8) << 40)
>          | (ELEM(zd, 7, 8) << 48) | (ELEM(zm, 7, 8) << 56);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rd] = make_float64(d0);
> +
> +    rm[0] = m0;
> +    rd[0] = d0;
>  }
>
> -void HELPER(neon_zip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
> +void HELPER(neon_zip16)(void *vd, void *vm)
>  {
> -    uint64_t zm = float64_val(env->vfp.regs[rm]);
> -    uint64_t zd = float64_val(env->vfp.regs[rd]);
> +    uint64_t *rd = vd, *rm = vm;
> +    uint64_t zd = rd[0], zm = rm[0];
> +
>      uint64_t d0 = ELEM(zd, 0, 16) | (ELEM(zm, 0, 16) << 16)
>          | (ELEM(zd, 1, 16) << 32) | (ELEM(zm, 1, 16) << 48);
>      uint64_t m0 = ELEM(zd, 2, 16) | (ELEM(zm, 2, 16) << 16)
>          | (ELEM(zd, 3, 16) << 32) | (ELEM(zm, 3, 16) << 48);
> -    env->vfp.regs[rm] = make_float64(m0);
> -    env->vfp.regs[rd] = make_float64(d0);
> +
> +    rm[0] = m0;
> +    rd[0] = d0;
>  }
>
>  /* Helper function for 64 bit polynomial multiply case:
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index 7b5db15861..6f02c56abb 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -4687,22 +4687,23 @@ static inline TCGv_i32 neon_get_scalar(int size, int reg)
>
>  static int gen_neon_unzip(int rd, int rm, int size, int q)
>  {
> -    TCGv_i32 tmp, tmp2;
> +    TCGv_ptr pd, pm;
> +
>      if (!q && size == 2) {
>          return 1;
>      }
> -    tmp = tcg_const_i32(rd);
> -    tmp2 = tcg_const_i32(rm);
> +    pd = vfp_reg_ptr(true, rd);
> +    pm = vfp_reg_ptr(true, rm);
>      if (q) {
>          switch (size) {
>          case 0:
> -            gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
> +            gen_helper_neon_qunzip8(pd, pm);
>              break;
>          case 1:
> -            gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
> +            gen_helper_neon_qunzip16(pd, pm);
>              break;
>          case 2:
> -            gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
> +            gen_helper_neon_qunzip32(pd, pm);
>              break;
>          default:
>              abort();
> @@ -4710,38 +4711,39 @@ static int gen_neon_unzip(int rd, int rm, int size, int q)
>      } else {
>          switch (size) {
>          case 0:
> -            gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
> +            gen_helper_neon_unzip8(pd, pm);
>              break;
>          case 1:
> -            gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
> +            gen_helper_neon_unzip16(pd, pm);
>              break;
>          default:
>              abort();
>          }
>      }
> -    tcg_temp_free_i32(tmp);
> -    tcg_temp_free_i32(tmp2);
> +    tcg_temp_free_ptr(pd);
> +    tcg_temp_free_ptr(pm);
>      return 0;
>  }
>
>  static int gen_neon_zip(int rd, int rm, int size, int q)
>  {
> -    TCGv_i32 tmp, tmp2;
> +    TCGv_ptr pd, pm;
> +
>      if (!q && size == 2) {
>          return 1;
>      }
> -    tmp = tcg_const_i32(rd);
> -    tmp2 = tcg_const_i32(rm);
> +    pd = vfp_reg_ptr(true, rd);
> +    pm = vfp_reg_ptr(true, rm);
>      if (q) {
>          switch (size) {
>          case 0:
> -            gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
> +            gen_helper_neon_qzip8(pd, pm);
>              break;
>          case 1:
> -            gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
> +            gen_helper_neon_qzip16(pd, pm);
>              break;
>          case 2:
> -            gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
> +            gen_helper_neon_qzip32(pd, pm);
>              break;
>          default:
>              abort();
> @@ -4749,17 +4751,17 @@ static int gen_neon_zip(int rd, int rm, int size, int q)
>      } else {
>          switch (size) {
>          case 0:
> -            gen_helper_neon_zip8(cpu_env, tmp, tmp2);
> +            gen_helper_neon_zip8(pd, pm);
>              break;
>          case 1:
> -            gen_helper_neon_zip16(cpu_env, tmp, tmp2);
> +            gen_helper_neon_zip16(pd, pm);
>              break;
>          default:
>              abort();
>          }
>      }
> -    tcg_temp_free_i32(tmp);
> -    tcg_temp_free_i32(tmp2);
> +    tcg_temp_free_ptr(pd);
> +    tcg_temp_free_ptr(pm);
>      return 0;
>  }


--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 04/16] target/arm: Use pointers in neon tbl helper
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 04/16] target/arm: Use pointers in neon tbl helper Richard Henderson
@ 2018-01-22 10:52   ` Alex Bennée
  0 siblings, 0 replies; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 10:52 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> Rather than passing a regno to the helper, pass pointers to the
> vector register directly.  This eliminates the need to pass in
> the environment pointer and reduces the number of places that
> directly access env->vfp.regs[].
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/helper.h    |  2 +-
>  target/arm/op_helper.c | 17 +++++++----------
>  target/arm/translate.c |  8 ++++----
>  3 files changed, 12 insertions(+), 15 deletions(-)
>
> diff --git a/target/arm/helper.h b/target/arm/helper.h
> index dbdc38fcb7..5dec2e6262 100644
> --- a/target/arm/helper.h
> +++ b/target/arm/helper.h
> @@ -188,7 +188,7 @@ DEF_HELPER_FLAGS_2(rsqrte_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
>  DEF_HELPER_FLAGS_2(rsqrte_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
>  DEF_HELPER_2(recpe_u32, i32, i32, ptr)
>  DEF_HELPER_FLAGS_2(rsqrte_u32, TCG_CALL_NO_RWG, i32, i32, ptr)
> -DEF_HELPER_5(neon_tbl, i32, env, i32, i32, i32, i32)
> +DEF_HELPER_FLAGS_4(neon_tbl, TCG_CALL_NO_RWG, i32, i32, i32, ptr, i32)
>
>  DEF_HELPER_3(shl_cc, i32, env, i32, i32)
>  DEF_HELPER_3(shr_cc, i32, env, i32, i32)
> diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
> index 712c5c55b6..a937e76710 100644
> --- a/target/arm/op_helper.c
> +++ b/target/arm/op_helper.c
> @@ -54,20 +54,17 @@ static int exception_target_el(CPUARMState *env)
>      return target_el;
>  }
>
> -uint32_t HELPER(neon_tbl)(CPUARMState *env, uint32_t ireg, uint32_t def,
> -                          uint32_t rn, uint32_t maxindex)
> +uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def, void *vn,
> +                          uint32_t maxindex)
>  {
> -    uint32_t val;
> -    uint32_t tmp;
> -    int index;
> -    int shift;
> -    uint64_t *table;
> -    table = (uint64_t *)&env->vfp.regs[rn];
> +    uint32_t val, shift;

Any particular reason to promote shift to a uint32_t here?

> +    uint64_t *table = vn;
> +
>      val = 0;
>      for (shift = 0; shift < 32; shift += 8) {
> -        index = (ireg >> shift) & 0xff;
> +        uint32_t index = (ireg >> shift) & 0xff;
>          if (index < maxindex) {
> -            tmp = (table[index >> 3] >> ((index & 7) << 3)) & 0xff;
> +            uint32_t tmp = (table[index >> 3] >> ((index & 7) << 3)) & 0xff;
>              val |= tmp << shift;
>          } else {
>              val |= def & (0xff << shift);
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index 6f02c56abb..852d2a75b1 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -7544,9 +7544,9 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
>                      tcg_gen_movi_i32(tmp, 0);
>                  }
>                  tmp2 = neon_load_reg(rm, 0);
> -                tmp4 = tcg_const_i32(rn);
> +                ptr1 = vfp_reg_ptr(true, rn);
>                  tmp5 = tcg_const_i32(n);
> -                gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5);
> +                gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5);
>                  tcg_temp_free_i32(tmp);
>                  if (insn & (1 << 6)) {
>                      tmp = neon_load_reg(rd, 1);
> @@ -7555,9 +7555,9 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
>                      tcg_gen_movi_i32(tmp, 0);
>                  }
>                  tmp3 = neon_load_reg(rm, 1);
> -                gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5);
> +                gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5);
>                  tcg_temp_free_i32(tmp5);
> -                tcg_temp_free_i32(tmp4);
> +                tcg_temp_free_ptr(ptr1);
>                  neon_store_reg(rd, 0, tmp2);
>                  neon_store_reg(rd, 1, tmp3);
>                  tcg_temp_free_i32(tmp);

I was wondering why tmp4 wasn't dropped from the declarations until I
was reminded how massively overloaded this function is.

Anyway baring the minor nit:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>



--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 05/16] target/arm: Change the type of vfp.regs
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 05/16] target/arm: Change the type of vfp.regs Richard Henderson
@ 2018-01-22 10:56   ` Alex Bennée
  2018-01-22 16:03     ` Richard Henderson
  0 siblings, 1 reply; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 10:56 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> All direct users of this field want an integral value.  Drop all
> of the extra casting between uint64_t and float64.

Did the extra casting ever generate superfluous code?

Anyway:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/cpu.h           |  2 +-
>  target/arm/arch_dump.c     |  4 ++--
>  target/arm/helper.c        | 20 ++++++++++----------
>  target/arm/machine.c       |  2 +-
>  target/arm/translate-a64.c |  8 ++++----
>  target/arm/translate.c     |  2 +-
>  6 files changed, 19 insertions(+), 19 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 96316700dd..76ab7953a6 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -492,7 +492,7 @@ typedef struct CPUARMState {
>           * the two execution states, and means we do not need to explicitly
>           * map these registers when changing states.
>           */
> -        float64 regs[64];
> +        uint64_t regs[64];
>
>          uint32_t xregs[16];
>          /* We store these fpcsr fields separately for convenience.  */
> diff --git a/target/arm/arch_dump.c b/target/arm/arch_dump.c
> index 9e5b2fb31c..0c43e0eef8 100644
> --- a/target/arm/arch_dump.c
> +++ b/target/arm/arch_dump.c
> @@ -100,7 +100,7 @@ static int aarch64_write_elf64_prfpreg(WriteCoreDumpFunction f,
>      aarch64_note_init(&note, s, "CORE", 5, NT_PRFPREG, sizeof(note.vfp));
>
>      for (i = 0; i < 64; ++i) {
> -        note.vfp.vregs[i] = cpu_to_dump64(s, float64_val(env->vfp.regs[i]));
> +        note.vfp.vregs[i] = cpu_to_dump64(s, env->vfp.regs[i]);
>      }
>
>      if (s->dump_info.d_endian == ELFDATA2MSB) {
> @@ -229,7 +229,7 @@ static int arm_write_elf32_vfp(WriteCoreDumpFunction f, CPUARMState *env,
>      arm_note_init(&note, s, "LINUX", 6, NT_ARM_VFP, sizeof(note.vfp));
>
>      for (i = 0; i < 32; ++i) {
> -        note.vfp.vregs[i] = cpu_to_dump64(s, float64_val(env->vfp.regs[i]));
> +        note.vfp.vregs[i] = cpu_to_dump64(s, env->vfp.regs[i]);
>      }
>
>      note.vfp.fpscr = cpu_to_dump32(s, vfp_get_fpscr(env));
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index c83c901a86..8fda797582 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -64,15 +64,15 @@ static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
>      /* VFP data registers are always little-endian.  */
>      nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
>      if (reg < nregs) {
> -        stfq_le_p(buf, env->vfp.regs[reg]);
> +        stq_le_p(buf, env->vfp.regs[reg]);
>          return 8;
>      }
>      if (arm_feature(env, ARM_FEATURE_NEON)) {
>          /* Aliases for Q regs.  */
>          nregs += 16;
>          if (reg < nregs) {
> -            stfq_le_p(buf, env->vfp.regs[(reg - 32) * 2]);
> -            stfq_le_p(buf + 8, env->vfp.regs[(reg - 32) * 2 + 1]);
> +            stq_le_p(buf, env->vfp.regs[(reg - 32) * 2]);
> +            stq_le_p(buf + 8, env->vfp.regs[(reg - 32) * 2 + 1]);
>              return 16;
>          }
>      }
> @@ -90,14 +90,14 @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
>
>      nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
>      if (reg < nregs) {
> -        env->vfp.regs[reg] = ldfq_le_p(buf);
> +        env->vfp.regs[reg] = ldq_le_p(buf);
>          return 8;
>      }
>      if (arm_feature(env, ARM_FEATURE_NEON)) {
>          nregs += 16;
>          if (reg < nregs) {
> -            env->vfp.regs[(reg - 32) * 2] = ldfq_le_p(buf);
> -            env->vfp.regs[(reg - 32) * 2 + 1] = ldfq_le_p(buf + 8);
> +            env->vfp.regs[(reg - 32) * 2] = ldq_le_p(buf);
> +            env->vfp.regs[(reg - 32) * 2 + 1] = ldq_le_p(buf + 8);
>              return 16;
>          }
>      }
> @@ -114,8 +114,8 @@ static int aarch64_fpu_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
>      switch (reg) {
>      case 0 ... 31:
>          /* 128 bit FP register */
> -        stfq_le_p(buf, env->vfp.regs[reg * 2]);
> -        stfq_le_p(buf + 8, env->vfp.regs[reg * 2 + 1]);
> +        stq_le_p(buf, env->vfp.regs[reg * 2]);
> +        stq_le_p(buf + 8, env->vfp.regs[reg * 2 + 1]);
>          return 16;
>      case 32:
>          /* FPSR */
> @@ -135,8 +135,8 @@ static int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
>      switch (reg) {
>      case 0 ... 31:
>          /* 128 bit FP register */
> -        env->vfp.regs[reg * 2] = ldfq_le_p(buf);
> -        env->vfp.regs[reg * 2 + 1] = ldfq_le_p(buf + 8);
> +        env->vfp.regs[reg * 2] = ldq_le_p(buf);
> +        env->vfp.regs[reg * 2 + 1] = ldq_le_p(buf + 8);
>          return 16;
>      case 32:
>          /* FPSR */
> diff --git a/target/arm/machine.c b/target/arm/machine.c
> index 176274629c..a85c2430d3 100644
> --- a/target/arm/machine.c
> +++ b/target/arm/machine.c
> @@ -50,7 +50,7 @@ static const VMStateDescription vmstate_vfp = {
>      .minimum_version_id = 3,
>      .needed = vfp_needed,
>      .fields = (VMStateField[]) {
> -        VMSTATE_FLOAT64_ARRAY(env.vfp.regs, ARMCPU, 64),
> +        VMSTATE_UINT64_ARRAY(env.vfp.regs, ARMCPU, 64),
>          /* The xregs array is a little awkward because element 1 (FPSCR)
>           * requires a specific accessor, so we have to split it up in
>           * the vmstate:
> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
> index 6d9b3af64c..c14fb4185c 100644
> --- a/target/arm/translate-a64.c
> +++ b/target/arm/translate-a64.c
> @@ -165,12 +165,12 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
>      if (flags & CPU_DUMP_FPU) {
>          int numvfpregs = 32;
>          for (i = 0; i < numvfpregs; i += 2) {
> -            uint64_t vlo = float64_val(env->vfp.regs[i * 2]);
> -            uint64_t vhi = float64_val(env->vfp.regs[(i * 2) + 1]);
> +            uint64_t vlo = env->vfp.regs[i * 2];
> +            uint64_t vhi = env->vfp.regs[(i * 2) + 1];
>              cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 " ",
>                          i, vhi, vlo);
> -            vlo = float64_val(env->vfp.regs[(i + 1) * 2]);
> -            vhi = float64_val(env->vfp.regs[((i + 1) * 2) + 1]);
> +            vlo = env->vfp.regs[(i + 1) * 2];
> +            vhi = env->vfp.regs[((i + 1) * 2) + 1];
>              cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "\n",
>                          i + 1, vhi, vlo);
>          }
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index 852d2a75b1..cfe49bf579 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -12572,7 +12572,7 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
>              numvfpregs += 16;
>          }
>          for (i = 0; i < numvfpregs; i++) {
> -            uint64_t v = float64_val(env->vfp.regs[i]);
> +            uint64_t v = env->vfp.regs[i];
>              cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
>                          i * 2, (uint32_t)v,
>                          i * 2 + 1, (uint32_t)(v >> 32),


--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 06/16] target/arm: Add aa{32, 64}_vfp_{dreg, qreg} helpers
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 06/16] target/arm: Add aa{32, 64}_vfp_{dreg, qreg} helpers Richard Henderson
@ 2018-01-22 11:02   ` Alex Bennée
  0 siblings, 0 replies; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 11:02 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> Helpers that return a pointer into env->vfp.regs so that we isolate
> the logic of how to index the regs array for different cpu modes.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target/arm/cpu.h           | 27 +++++++++++++++++++++++++++
>  linux-user/signal.c        | 22 ++++++++++++----------
>  target/arm/arch_dump.c     |  8 +++++---
>  target/arm/helper-a64.c    |  5 +++--
>  target/arm/helper.c        | 32 ++++++++++++++++++++------------
>  target/arm/kvm32.c         |  4 ++--
>  target/arm/kvm64.c         | 31 ++++++++++---------------------
>  target/arm/translate-a64.c | 25 ++++++++-----------------
>  target/arm/translate.c     | 16 +++++++++-------
>  9 files changed, 96 insertions(+), 74 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 76ab7953a6..7d396606f3 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -2885,4 +2885,31 @@ static inline void *arm_get_el_change_hook_opaque(ARMCPU *cpu)
>      return cpu->el_change_hook_opaque;
>  }
>
> +/**
> + * aa32_vfp_dreg:
> + * Return a pointer to the Dn register within env in 32-bit mode.
> + */
> +static inline uint64_t *aa32_vfp_dreg(CPUARMState *env, unsigned regno)
> +{
> +    return &env->vfp.regs[regno];
> +}
> +
> +/**
> + * aa32_vfp_qreg:
> + * Return a pointer to the Qn register within env in 32-bit mode.
> + */
> +static inline uint64_t *aa32_vfp_qreg(CPUARMState *env, unsigned regno)
> +{
> +    return &env->vfp.regs[2 * regno];
> +}
> +
> +/**
> + * aa64_vfp_qreg:
> + * Return a pointer to the Qn register within env in 64-bit mode.
> + */
> +static inline uint64_t *aa64_vfp_qreg(CPUARMState *env, unsigned regno)
> +{
> +    return &env->vfp.regs[2 * regno];
> +}
> +
>  #endif
> diff --git a/linux-user/signal.c b/linux-user/signal.c
> index f85f0dd780..5321f9e795 100644
> --- a/linux-user/signal.c
> +++ b/linux-user/signal.c
> @@ -1487,12 +1487,13 @@ static int target_setup_sigframe(struct target_rt_sigframe *sf,
>      }
>
>      for (i = 0; i < 32; i++) {
> +        uint64_t *q = aa64_vfp_qreg(env, i);
>  #ifdef TARGET_WORDS_BIGENDIAN
> -        __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
> -        __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
> +        __put_user(q[0], &aux->fpsimd.vregs[i * 2 + 1]);
> +        __put_user(q[1], &aux->fpsimd.vregs[i * 2]);
>  #else
> -        __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
> -        __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
> +        __put_user(q[0], &aux->fpsimd.vregs[i * 2]);
> +        __put_user(q[1], &aux->fpsimd.vregs[i * 2 + 1]);
>  #endif
>      }
>      __put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr);
> @@ -1539,12 +1540,13 @@ static int target_restore_sigframe(CPUARMState *env,
>      }
>
>      for (i = 0; i < 32; i++) {
> +        uint64_t *q = aa64_vfp_qreg(env, i);
>  #ifdef TARGET_WORDS_BIGENDIAN
> -        __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
> -        __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
> +        __get_user(q[0], &aux->fpsimd.vregs[i * 2 + 1]);
> +        __get_user(q[1], &aux->fpsimd.vregs[i * 2]);
>  #else
> -        __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
> -        __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
> +        __get_user(q[0], &aux->fpsimd.vregs[i * 2]);
> +        __get_user(q[1], &aux->fpsimd.vregs[i * 2 + 1]);
>  #endif
>      }
>      __get_user(fpsr, &aux->fpsimd.fpsr);
> @@ -1903,7 +1905,7 @@ static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
>      __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
>      __put_user(sizeof(*vfpframe), &vfpframe->size);
>      for (i = 0; i < 32; i++) {
> -        __put_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
> +        __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
>      }
>      __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
>      __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
> @@ -2210,7 +2212,7 @@ static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
>          return 0;
>      }
>      for (i = 0; i < 32; i++) {
> -        __get_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
> +        __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
>      }
>      __get_user(fpscr, &vfpframe->ufp.fpscr);
>      vfp_set_fpscr(env, fpscr);
> diff --git a/target/arm/arch_dump.c b/target/arm/arch_dump.c
> index 0c43e0eef8..26a2c09868 100644
> --- a/target/arm/arch_dump.c
> +++ b/target/arm/arch_dump.c
> @@ -99,8 +99,10 @@ static int aarch64_write_elf64_prfpreg(WriteCoreDumpFunction f,
>
>      aarch64_note_init(&note, s, "CORE", 5, NT_PRFPREG, sizeof(note.vfp));
>
> -    for (i = 0; i < 64; ++i) {
> -        note.vfp.vregs[i] = cpu_to_dump64(s, env->vfp.regs[i]);
> +    for (i = 0; i < 32; ++i) {
> +        uint64_t *q = aa64_vfp_qreg(env, i);
> +        note.vfp.vregs[2*i + 0] = cpu_to_dump64(s, q[0]);
> +        note.vfp.vregs[2*i + 1] = cpu_to_dump64(s, q[1]);
>      }
>
>      if (s->dump_info.d_endian == ELFDATA2MSB) {
> @@ -229,7 +231,7 @@ static int arm_write_elf32_vfp(WriteCoreDumpFunction f, CPUARMState *env,
>      arm_note_init(&note, s, "LINUX", 6, NT_ARM_VFP, sizeof(note.vfp));
>
>      for (i = 0; i < 32; ++i) {
> -        note.vfp.vregs[i] = cpu_to_dump64(s, env->vfp.regs[i]);
> +        note.vfp.vregs[i] = cpu_to_dump64(s, *aa32_vfp_dreg(env, i));
>      }
>
>      note.vfp.fpscr = cpu_to_dump32(s, vfp_get_fpscr(env));
> diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
> index 3e00a9ead1..06fd321fae 100644
> --- a/target/arm/helper-a64.c
> +++ b/target/arm/helper-a64.c
> @@ -153,13 +153,14 @@ uint64_t HELPER(simd_tbl)(CPUARMState *env, uint64_t result, uint64_t indices,
>          if (index < 16 * numregs) {
>              /* Convert index (a byte offset into the virtual table
>               * which is a series of 128-bit vectors concatenated)
> -             * into the correct vfp.regs[] element plus a bit offset
> +             * into the correct register element plus a bit offset
>               * into that element, bearing in mind that the table
>               * can wrap around from V31 to V0.
>               */
>              int elt = (rn * 2 + (index >> 3)) % 64;
>              int bitidx = (index & 7) * 8;
> -            uint64_t val = extract64(env->vfp.regs[elt], bitidx, 8);
> +            uint64_t *q = aa64_vfp_qreg(env, elt >> 1);
> +            uint64_t val = extract64(q[elt & 1], bitidx, 8);
>
>              result = deposit64(result, shift, 8, val);
>          }
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 8fda797582..6705903301 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -64,15 +64,16 @@ static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
>      /* VFP data registers are always little-endian.  */
>      nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
>      if (reg < nregs) {
> -        stq_le_p(buf, env->vfp.regs[reg]);
> +        stq_le_p(buf, *aa32_vfp_dreg(env, reg));
>          return 8;
>      }
>      if (arm_feature(env, ARM_FEATURE_NEON)) {
>          /* Aliases for Q regs.  */
>          nregs += 16;
>          if (reg < nregs) {
> -            stq_le_p(buf, env->vfp.regs[(reg - 32) * 2]);
> -            stq_le_p(buf + 8, env->vfp.regs[(reg - 32) * 2 + 1]);
> +            uint64_t *q = aa32_vfp_qreg(env, reg - 32);
> +            stq_le_p(buf, q[0]);
> +            stq_le_p(buf + 8, q[1]);
>              return 16;
>          }
>      }
> @@ -90,14 +91,15 @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
>
>      nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
>      if (reg < nregs) {
> -        env->vfp.regs[reg] = ldq_le_p(buf);
> +        *aa32_vfp_dreg(env, reg) = ldq_le_p(buf);
>          return 8;
>      }
>      if (arm_feature(env, ARM_FEATURE_NEON)) {
>          nregs += 16;
>          if (reg < nregs) {
> -            env->vfp.regs[(reg - 32) * 2] = ldq_le_p(buf);
> -            env->vfp.regs[(reg - 32) * 2 + 1] = ldq_le_p(buf + 8);
> +            uint64_t *q = aa32_vfp_qreg(env, reg - 32);
> +            q[0] = ldq_le_p(buf);
> +            q[1] = ldq_le_p(buf + 8);
>              return 16;
>          }
>      }
> @@ -114,9 +116,12 @@ static int aarch64_fpu_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
>      switch (reg) {
>      case 0 ... 31:
>          /* 128 bit FP register */
> -        stq_le_p(buf, env->vfp.regs[reg * 2]);
> -        stq_le_p(buf + 8, env->vfp.regs[reg * 2 + 1]);
> -        return 16;
> +        {
> +            uint64_t *q = aa64_vfp_qreg(env, reg);
> +            stq_le_p(buf, q[0]);
> +            stq_le_p(buf + 8, q[1]);
> +            return 16;
> +        }
>      case 32:
>          /* FPSR */
>          stl_p(buf, vfp_get_fpsr(env));
> @@ -135,9 +140,12 @@ static int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
>      switch (reg) {
>      case 0 ... 31:
>          /* 128 bit FP register */
> -        env->vfp.regs[reg * 2] = ldq_le_p(buf);
> -        env->vfp.regs[reg * 2 + 1] = ldq_le_p(buf + 8);
> -        return 16;
> +        {
> +            uint64_t *q = aa64_vfp_qreg(env, reg);
> +            q[0] = ldq_le_p(buf);
> +            q[1] = ldq_le_p(buf + 8);
> +            return 16;
> +        }
>      case 32:
>          /* FPSR */
>          vfp_set_fpsr(env, ldl_p(buf));
> diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
> index f925a21481..f77c9c494b 100644
> --- a/target/arm/kvm32.c
> +++ b/target/arm/kvm32.c
> @@ -358,7 +358,7 @@ int kvm_arch_put_registers(CPUState *cs, int level)
>      /* VFP registers */
>      r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
>      for (i = 0; i < 32; i++) {
> -        r.addr = (uintptr_t)(&env->vfp.regs[i]);
> +        r.addr = (uintptr_t)aa32_vfp_dreg(env, i);
>          ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
>          if (ret) {
>              return ret;
> @@ -445,7 +445,7 @@ int kvm_arch_get_registers(CPUState *cs)
>      /* VFP registers */
>      r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
>      for (i = 0; i < 32; i++) {
> -        r.addr = (uintptr_t)(&env->vfp.regs[i]);
> +        r.addr = (uintptr_t)aa32_vfp_dreg(env, i);
>          ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
>          if (ret) {
>              return ret;
> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
> index 6554c30007..ac728494a4 100644
> --- a/target/arm/kvm64.c
> +++ b/target/arm/kvm64.c
> @@ -696,21 +696,16 @@ int kvm_arch_put_registers(CPUState *cs, int level)
>          }
>      }
>
> -    /* Advanced SIMD and FP registers
> -     * We map Qn = regs[2n+1]:regs[2n]
> -     */
> +    /* Advanced SIMD and FP registers. */
>      for (i = 0; i < 32; i++) {
> -        int rd = i << 1;
> -        uint64_t fp_val[2];
> +        uint64_t *q = aa64_vfp_qreg(env, i);
>  #ifdef HOST_WORDS_BIGENDIAN
> -        fp_val[0] = env->vfp.regs[rd + 1];
> -        fp_val[1] = env->vfp.regs[rd];
> +        uint64_t fp_val[2] = { q[1], q[0] };
> +        reg.addr = (uintptr_t)fp_val;
>  #else
> -        fp_val[1] = env->vfp.regs[rd + 1];
> -        fp_val[0] = env->vfp.regs[rd];
> +        reg.addr = (uintptr_t)q;
>  #endif
>          reg.id = AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]);
> -        reg.addr = (uintptr_t)(&fp_val);
>          ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
>          if (ret) {
>              return ret;
> @@ -837,24 +832,18 @@ int kvm_arch_get_registers(CPUState *cs)
>          env->spsr = env->banked_spsr[i];
>      }
>
> -    /* Advanced SIMD and FP registers
> -     * We map Qn = regs[2n+1]:regs[2n]
> -     */
> +    /* Advanced SIMD and FP registers */
>      for (i = 0; i < 32; i++) {
> -        uint64_t fp_val[2];
> +        uint64_t *q = aa64_vfp_qreg(env, i);
>          reg.id = AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]);
> -        reg.addr = (uintptr_t)(&fp_val);
> +        reg.addr = (uintptr_t)q;
>          ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
>          if (ret) {
>              return ret;
>          } else {
> -            int rd = i << 1;
>  #ifdef HOST_WORDS_BIGENDIAN
> -            env->vfp.regs[rd + 1] = fp_val[0];
> -            env->vfp.regs[rd] = fp_val[1];
> -#else
> -            env->vfp.regs[rd + 1] = fp_val[1];
> -            env->vfp.regs[rd] = fp_val[0];
> +            uint64_t t;
> +            t = q[0], q[0] = q[1], q[1] = t;
>  #endif
>          }
>      }
> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
> index c14fb4185c..eed64c73e5 100644
> --- a/target/arm/translate-a64.c
> +++ b/target/arm/translate-a64.c
> @@ -164,15 +164,12 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
>
>      if (flags & CPU_DUMP_FPU) {
>          int numvfpregs = 32;
> -        for (i = 0; i < numvfpregs; i += 2) {
> -            uint64_t vlo = env->vfp.regs[i * 2];
> -            uint64_t vhi = env->vfp.regs[(i * 2) + 1];
> -            cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 " ",
> -                        i, vhi, vlo);
> -            vlo = env->vfp.regs[(i + 1) * 2];
> -            vhi = env->vfp.regs[((i + 1) * 2) + 1];
> -            cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "\n",
> -                        i + 1, vhi, vlo);
> +        for (i = 0; i < numvfpregs; i++) {
> +            uint64_t *q = aa64_vfp_qreg(env, i);
> +            uint64_t vlo = q[0];
> +            uint64_t vhi = q[1];
> +            cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "%c",
> +                        i, vhi, vlo, (i & 1 ? '\n' : ' '));
>          }
>          cpu_fprintf(f, "FPCR: %08x  FPSR: %08x\n",
>                      vfp_get_fpcr(env), vfp_get_fpsr(env));
> @@ -558,19 +555,13 @@ static TCGv_ptr vec_full_reg_ptr(DisasContext *s, int regno)
>   */
>  static inline int fp_reg_offset(DisasContext *s, int regno, TCGMemOp size)
>  {
> -    int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
> -#ifdef HOST_WORDS_BIGENDIAN
> -    offs += (8 - (1 << size));
> -#endif
> -    assert_fp_access_checked(s);
> -    return offs;
> +    return vec_reg_offset(s, regno, 0, size);
>  }
>
>  /* Offset of the high half of the 128 bit vector Qn */
>  static inline int fp_reg_hi_offset(DisasContext *s, int regno)
>  {
> -    assert_fp_access_checked(s);
> -    return offsetof(CPUARMState, vfp.regs[regno * 2 + 1]);
> +    return vec_reg_offset(s, regno, 1, MO_64);
>  }
>
>  /* Convenience accessors for reading and writing single and double
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index cfe49bf579..55826b7e5a 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -1515,14 +1515,16 @@ static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
>  static inline long
>  vfp_reg_offset (int dp, int reg)
>  {
> -    if (dp)
> +    if (dp) {
>          return offsetof(CPUARMState, vfp.regs[reg]);
> -    else if (reg & 1) {
> -        return offsetof(CPUARMState, vfp.regs[reg >> 1])
> -          + offsetof(CPU_DoubleU, l.upper);
>      } else {
> -        return offsetof(CPUARMState, vfp.regs[reg >> 1])
> -          + offsetof(CPU_DoubleU, l.lower);
> +        long ofs = offsetof(CPUARMState, vfp.regs[reg >> 1]);
> +        if (reg & 1) {
> +            ofs += offsetof(CPU_DoubleU, l.upper);
> +        } else {
> +            ofs += offsetof(CPU_DoubleU, l.lower);
> +        }
> +        return ofs;
>      }
>  }
>
> @@ -12572,7 +12574,7 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
>              numvfpregs += 16;
>          }
>          for (i = 0; i < numvfpregs; i++) {
> -            uint64_t v = env->vfp.regs[i];
> +            uint64_t v = *aa32_vfp_dreg(env, i);
>              cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
>                          i * 2, (uint32_t)v,
>                          i * 2 + 1, (uint32_t)(v >> 32),


--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 07/16] vmstate: Add VMSTATE_UINT64_SUB_ARRAY
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 07/16] vmstate: Add VMSTATE_UINT64_SUB_ARRAY Richard Henderson
@ 2018-01-22 11:02   ` Alex Bennée
  0 siblings, 0 replies; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 11:02 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> At the same time, move VMSTATE_UINT32_SUB_ARRAY
> beside the other UINT32 definitions.
>
> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  include/migration/vmstate.h | 9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
> index 88b55df5ae..8c3889433c 100644
> --- a/include/migration/vmstate.h
> +++ b/include/migration/vmstate.h
> @@ -905,6 +905,9 @@ extern const VMStateInfo vmstate_info_qtailq;
>  #define VMSTATE_UINT32_ARRAY(_f, _s, _n)                              \
>      VMSTATE_UINT32_ARRAY_V(_f, _s, _n, 0)
>
> +#define VMSTATE_UINT32_SUB_ARRAY(_f, _s, _start, _num)                \
> +    VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint32, uint32_t)
> +
>  #define VMSTATE_UINT32_2DARRAY(_f, _s, _n1, _n2)                      \
>      VMSTATE_UINT32_2DARRAY_V(_f, _s, _n1, _n2, 0)
>
> @@ -914,6 +917,9 @@ extern const VMStateInfo vmstate_info_qtailq;
>  #define VMSTATE_UINT64_ARRAY(_f, _s, _n)                              \
>      VMSTATE_UINT64_ARRAY_V(_f, _s, _n, 0)
>
> +#define VMSTATE_UINT64_SUB_ARRAY(_f, _s, _start, _num)                \
> +    VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint64, uint64_t)
> +
>  #define VMSTATE_UINT64_2DARRAY(_f, _s, _n1, _n2)                      \
>      VMSTATE_UINT64_2DARRAY_V(_f, _s, _n1, _n2, 0)
>
> @@ -932,9 +938,6 @@ extern const VMStateInfo vmstate_info_qtailq;
>  #define VMSTATE_INT32_ARRAY(_f, _s, _n)                               \
>      VMSTATE_INT32_ARRAY_V(_f, _s, _n, 0)
>
> -#define VMSTATE_UINT32_SUB_ARRAY(_f, _s, _start, _num)                \
> -    VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint32, uint32_t)
> -
>  #define VMSTATE_INT64_ARRAY_V(_f, _s, _n, _v)                         \
>      VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_int64, int64_t)


--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 08/16] target/arm: Expand vector registers for SVE
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 08/16] target/arm: Expand vector registers for SVE Richard Henderson
@ 2018-01-22 11:08   ` Alex Bennée
  0 siblings, 0 replies; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 11:08 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> Change vfp.regs as a uint64_t to vfp.zregs as an ARMVectorReg.
> The previous patches have made the change in representation
> relatively painless.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/cpu.h           | 57 ++++++++++++++++++++++++++++++----------------
>  target/arm/machine.c       | 35 +++++++++++++++++++++++++++-
>  target/arm/translate-a64.c |  8 +++----
>  target/arm/translate.c     |  7 +++---
>  4 files changed, 79 insertions(+), 28 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 7d396606f3..57d805b5d8 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -153,6 +153,40 @@ typedef struct {
>      uint32_t base_mask;
>  } TCR;
>
> +/* Define a maximum sized vector register.
> + * For 32-bit, this is a 128-bit NEON/AdvSIMD register.
> + * For 64-bit, this is a 2048-bit SVE register.
> + *
> + * Note that the mapping between S, D, and Q views of the register bank
> + * differs between AArch64 and AArch32.
> + * In AArch32:
> + *  Qn = regs[n].d[1]:regs[n].d[0]
> + *  Dn = regs[n / 2].d[n & 1]
> + *  Sn = regs[n / 4].d[n % 4 / 2],
> + *       bits 31..0 for even n, and bits 63..32 for odd n
> + *       (and regs[16] to regs[31] are inaccessible)
> + * In AArch64:
> + *  Zn = regs[n].d[*]
> + *  Qn = regs[n].d[1]:regs[n].d[0]
> + *  Dn = regs[n].d[0]
> + *  Sn = regs[n].d[0] bits 31..0
> + *
> + * This corresponds to the architecturally defined mapping between
> + * the two execution states, and means we do not need to explicitly
> + * map these registers when changing states.

It might be worth prompting to use the helper functions to get the right
offsets here.

> + */
> +
> +#ifdef TARGET_AARCH64
> +# define ARM_MAX_VQ    16
> +#else
> +# define ARM_MAX_VQ    1
> +#endif
> +
> +typedef struct ARMVectorReg {
> +    uint64_t d[2 * ARM_MAX_VQ] QEMU_ALIGNED(16);
> +} ARMVectorReg;
> +

The QEMU_ALIGNED also deserves a comment either here or in the comment
block above.

> +
>  typedef struct CPUARMState {
>      /* Regs for current mode.  */
>      uint32_t regs[16];
> @@ -477,22 +511,7 @@ typedef struct CPUARMState {
>
>      /* VFP coprocessor state.  */
>      struct {
> -        /* VFP/Neon register state. Note that the mapping between S, D and Q
> -         * views of the register bank differs between AArch64 and AArch32:
> -         * In AArch32:
> -         *  Qn = regs[2n+1]:regs[2n]
> -         *  Dn = regs[n]
> -         *  Sn = regs[n/2] bits 31..0 for even n, and bits 63..32 for odd n
> -         * (and regs[32] to regs[63] are inaccessible)
> -         * In AArch64:
> -         *  Qn = regs[2n+1]:regs[2n]
> -         *  Dn = regs[2n]
> -         *  Sn = regs[2n] bits 31..0
> -         * This corresponds to the architecturally defined mapping between
> -         * the two execution states, and means we do not need to explicitly
> -         * map these registers when changing states.
> -         */
> -        uint64_t regs[64];
> +        ARMVectorReg zregs[32];
>
>          uint32_t xregs[16];
>          /* We store these fpcsr fields separately for convenience.  */
> @@ -2891,7 +2910,7 @@ static inline void *arm_get_el_change_hook_opaque(ARMCPU *cpu)
>   */
>  static inline uint64_t *aa32_vfp_dreg(CPUARMState *env, unsigned regno)
>  {
> -    return &env->vfp.regs[regno];
> +    return &env->vfp.zregs[regno >> 1].d[regno & 1];
>  }
>
>  /**
> @@ -2900,7 +2919,7 @@ static inline uint64_t *aa32_vfp_dreg(CPUARMState *env, unsigned regno)
>   */
>  static inline uint64_t *aa32_vfp_qreg(CPUARMState *env, unsigned regno)
>  {
> -    return &env->vfp.regs[2 * regno];
> +    return &env->vfp.zregs[regno].d[0];
>  }
>
>  /**
> @@ -2909,7 +2928,7 @@ static inline uint64_t *aa32_vfp_qreg(CPUARMState *env, unsigned regno)
>   */
>  static inline uint64_t *aa64_vfp_qreg(CPUARMState *env, unsigned regno)
>  {
> -    return &env->vfp.regs[2 * regno];
> +    return &env->vfp.zregs[regno].d[0];
>  }
>
>  #endif
> diff --git a/target/arm/machine.c b/target/arm/machine.c
> index a85c2430d3..cb0e1c92bb 100644
> --- a/target/arm/machine.c
> +++ b/target/arm/machine.c
> @@ -50,7 +50,40 @@ static const VMStateDescription vmstate_vfp = {
>      .minimum_version_id = 3,
>      .needed = vfp_needed,
>      .fields = (VMStateField[]) {
> -        VMSTATE_UINT64_ARRAY(env.vfp.regs, ARMCPU, 64),
> +        /* For compatibility, store Qn out of Zn here.  */
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[0].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[1].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[2].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[3].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[4].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[5].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[6].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[7].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[8].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[9].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[10].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[11].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[12].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[13].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[14].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[15].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[16].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[17].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[18].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[19].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[20].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[21].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[22].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[23].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[24].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[25].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[26].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[27].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[28].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[29].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[30].d, ARMCPU, 0, 2),
> +        VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[31].d, ARMCPU, 0, 2),
> +
>          /* The xregs array is a little awkward because element 1 (FPSCR)
>           * requires a specific accessor, so we have to split it up in
>           * the vmstate:
> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
> index eed64c73e5..10eef870fe 100644
> --- a/target/arm/translate-a64.c
> +++ b/target/arm/translate-a64.c
> @@ -517,8 +517,8 @@ static inline int vec_reg_offset(DisasContext *s, int regno,
>  {
>      int offs = 0;
>  #ifdef HOST_WORDS_BIGENDIAN
> -    /* This is complicated slightly because vfp.regs[2n] is
> -     * still the low half and  vfp.regs[2n+1] the high half
> +    /* This is complicated slightly because vfp.zregs[n].d[0] is
> +     * still the low half and vfp.zregs[n].d[1] the high half
>       * of the 128 bit vector, even on big endian systems.
>       * Calculate the offset assuming a fully bigendian 128 bits,
>       * then XOR to account for the order of the two 64 bit halves.
> @@ -528,7 +528,7 @@ static inline int vec_reg_offset(DisasContext *s, int regno,
>  #else
>      offs += element * (1 << size);
>  #endif
> -    offs += offsetof(CPUARMState, vfp.regs[regno * 2]);
> +    offs += offsetof(CPUARMState, vfp.zregs[regno]);
>      assert_fp_access_checked(s);
>      return offs;
>  }
> @@ -537,7 +537,7 @@ static inline int vec_reg_offset(DisasContext *s, int regno,
>  static inline int vec_full_reg_offset(DisasContext *s, int regno)
>  {
>      assert_fp_access_checked(s);
> -    return offsetof(CPUARMState, vfp.regs[regno * 2]);
> +    return offsetof(CPUARMState, vfp.zregs[regno]);
>  }
>
>  /* Return a newly allocated pointer to the vector register.  */
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index 55826b7e5a..a8c13d3758 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -1512,13 +1512,12 @@ static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
>      }
>  }
>
> -static inline long
> -vfp_reg_offset (int dp, int reg)
> +static inline long vfp_reg_offset(bool dp, unsigned reg)
>  {
>      if (dp) {
> -        return offsetof(CPUARMState, vfp.regs[reg]);
> +        return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
>      } else {
> -        long ofs = offsetof(CPUARMState, vfp.regs[reg >> 1]);
> +        long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]);
>          if (reg & 1) {
>              ofs += offsetof(CPU_DoubleU, l.upper);
>          } else {

Other than the minor comment notes it looks good:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 09/16] target/arm: Add predicate registers for SVE
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 09/16] target/arm: Add predicate " Richard Henderson
@ 2018-01-22 12:04   ` Alex Bennée
  2018-01-22 16:07     ` Richard Henderson
  0 siblings, 1 reply; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 12:04 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/cpu.h | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 57d805b5d8..132da359b5 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -186,6 +186,15 @@ typedef struct ARMVectorReg {
>      uint64_t d[2 * ARM_MAX_VQ] QEMU_ALIGNED(16);
>  } ARMVectorReg;
>
> +/* In AArch32 mode, predicate registers do not exist at all.  */
> +typedef struct ARMPredicateReg {
> +#ifdef TARGET_AARCH64
> +    uint64_t p[2 * ARM_MAX_VQ / 8] QEMU_ALIGNED(16);
> +#else
> +    uint64_t p[0];
> +#endif
> +} ARMPredicateReg;
> +
>
>  typedef struct CPUARMState {
>      /* Regs for current mode.  */
> @@ -513,6 +522,9 @@ typedef struct CPUARMState {
>      struct {
>          ARMVectorReg zregs[32];
>
> +        /* Store FFR as pregs[16] to make it easier to treat as any other.  */
> +        ARMPredicateReg pregs[17];
> +

What happens if code tries to accidentally access this on the 32 bit build?

>          uint32_t xregs[16];
>          /* We store these fpcsr fields separately for convenience.  */
>          int vec_len;


--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 10/16] target/arm: Add ARM_FEATURE_SVE
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 10/16] target/arm: Add ARM_FEATURE_SVE Richard Henderson
@ 2018-01-22 12:05   ` Alex Bennée
  0 siblings, 0 replies; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 12:05 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> Not enabled anywhere so far.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target/arm/cpu.h | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 132da359b5..0a923e42d8 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -1371,6 +1371,7 @@ enum arm_features {
>      ARM_FEATURE_VBAR, /* has cp15 VBAR */
>      ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
>      ARM_FEATURE_JAZELLE, /* has (trivial) Jazelle implementation */
> +    ARM_FEATURE_SVE, /* has Scalable Vector Extension */
>  };
>
>  static inline int arm_feature(CPUARMState *env, int feature)


--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 11/16] target/arm: Add SVE to migration state
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 11/16] target/arm: Add SVE to migration state Richard Henderson
@ 2018-01-22 13:40   ` Alex Bennée
  2018-01-22 16:11     ` Richard Henderson
  2018-01-22 14:16   ` Peter Maydell
  1 sibling, 1 reply; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 13:40 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> Save the high parts of the Zregs and all of the Pregs.
> The ZCR_ELx registers are migrated via the CP mechanism.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/machine.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 53 insertions(+)
>
> diff --git a/target/arm/machine.c b/target/arm/machine.c
> index cb0e1c92bb..2c8b43062f 100644
> --- a/target/arm/machine.c
> +++ b/target/arm/machine.c
> @@ -122,6 +122,56 @@ static const VMStateDescription vmstate_iwmmxt = {
>      }
>  };
>
> +#ifdef TARGET_AARCH64
> +/* The expression ARM_MAX_VQ - 2 is 0 for pure AArch32 build,
> + * and ARMPredicateReg is actively empty.  This triggers errors
> + * in the expansion of the VMSTATE macros.
> + */

This makes me think that #ifdef-ing out the pregs might be better for
the 32 bit target build.

> +
> +static bool sve_needed(void *opaque)
> +{
> +    ARMCPU *cpu = opaque;
> +    CPUARMState *env = &cpu->env;
> +
> +    return arm_feature(env, ARM_FEATURE_SVE);
> +}
> +
> +/* The first two words of each Zreg is stored in VFP state.  */
> +static const VMStateDescription vmstate_zreg_hi_reg = {
> +    .name = "cpu/sve/zreg_hi",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT64_SUB_ARRAY(d, ARMVectorReg, 2, ARM_MAX_VQ - 2),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static const VMStateDescription vmstate_preg_reg = {
> +    .name = "cpu/sve/preg",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT64_ARRAY(p, ARMPredicateReg, 2 * ARM_MAX_VQ / 8),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static const VMStateDescription vmstate_sve = {
> +    .name = "cpu/sve",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .needed = sve_needed,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_STRUCT_ARRAY(env.vfp.zregs, ARMCPU, 32, 0,
> +                             vmstate_zreg_hi_reg, ARMVectorReg),
> +        VMSTATE_STRUCT_ARRAY(env.vfp.pregs, ARMCPU, 17, 0,
> +                             vmstate_preg_reg, ARMPredicateReg),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +#endif /* AARCH64 */
> +
>  static bool m_needed(void *opaque)
>  {
>      ARMCPU *cpu = opaque;
> @@ -586,6 +636,9 @@ const VMStateDescription vmstate_arm_cpu = {
>          &vmstate_pmsav7,
>          &vmstate_pmsav8,
>          &vmstate_m_security,
> +#ifdef TARGET_AARCH64
> +        &vmstate_sve,
> +#endif
>          NULL
>      }
>  };


--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
                   ` (16 preceding siblings ...)
  2018-01-19  5:29 ` [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE no-reply
@ 2018-01-22 14:12 ` Peter Maydell
  2018-01-22 15:12   ` Alex Bennée
  2018-01-22 15:12 ` Alex Bennée
  18 siblings, 1 reply; 46+ messages in thread
From: Peter Maydell @ 2018-01-22 14:12 UTC (permalink / raw)
  To: Richard Henderson; +Cc: QEMU Developers

On 19 January 2018 at 04:54, Richard Henderson
<richard.henderson@linaro.org> wrote:
> I believe that this addresses all of the comments Peter had with
> respect to v1.  I did go ahead and add the system registers, so that
> I could figure out how they're supposed to work.
>
> This has been rebased to master so that it has no dependencies.
>
>
> r~
>
>
> Richard Henderson (16):
> 1  target/arm: Mark disas_set_insn_syndrome inline
> 2  target/arm: Use pointers in crypto helpers
> 3  target/arm: Use pointers in neon zip/uzp helpers
> 4  target/arm: Use pointers in neon tbl helper
> 5  target/arm: Change the type of vfp.regs
> 6  target/arm: Add aa{32,64}_vfp_{dreg,qreg} helpers
> 7  vmstate: Add VMSTATE_UINT64_SUB_ARRAY
> 8  target/arm: Expand vector registers for SVE
> 9  target/arm: Add predicate registers for SVE
> 10 target/arm: Add ARM_FEATURE_SVE
> 11 target/arm: Add SVE to migration state
> 12 target/arm: Add ZCR_ELx
> 13 target/arm: Move cpu_get_tb_cpu_state out of line
> 14 target/arm: Hoist store to flags output in cpu_get_tb_cpu_state
> 15 target/arm: Simplify fp_exception_el for user-only
> 16 target/arm: Add SVE state to TB->FLAGS

In the interests of reducing the size of this patch set, I'm going to
take patches 1..7, 10, 13..15 into target-arm.next. (Alex, I know
you had a nit about changing the type of a variable in patch 4 but
I think I'd rather just take the patchset rather than do another
round with it for that.)

The target-arm.next branch (which rebases!) with those patches is at:

https://git.linaro.org/people/peter.maydell/qemu-arm.git target-arm.next

I expect I'll make a pullreq either tomorrow or more likely Thursday.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 11/16] target/arm: Add SVE to migration state
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 11/16] target/arm: Add SVE to migration state Richard Henderson
  2018-01-22 13:40   ` Alex Bennée
@ 2018-01-22 14:16   ` Peter Maydell
  2018-01-22 16:10     ` Richard Henderson
  1 sibling, 1 reply; 46+ messages in thread
From: Peter Maydell @ 2018-01-22 14:16 UTC (permalink / raw)
  To: Richard Henderson; +Cc: QEMU Developers

On 19 January 2018 at 04:54, Richard Henderson
<richard.henderson@linaro.org> wrote:
> Save the high parts of the Zregs and all of the Pregs.
> The ZCR_ELx registers are migrated via the CP mechanism.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/machine.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 53 insertions(+)
>
> diff --git a/target/arm/machine.c b/target/arm/machine.c
> index cb0e1c92bb..2c8b43062f 100644
> --- a/target/arm/machine.c
> +++ b/target/arm/machine.c
> @@ -122,6 +122,56 @@ static const VMStateDescription vmstate_iwmmxt = {
>      }
>  };
>
> +#ifdef TARGET_AARCH64
> +/* The expression ARM_MAX_VQ - 2 is 0 for pure AArch32 build,
> + * and ARMPredicateReg is actively empty.  This triggers errors
> + * in the expansion of the VMSTATE macros.
> + */
> +
> +static bool sve_needed(void *opaque)
> +{
> +    ARMCPU *cpu = opaque;
> +    CPUARMState *env = &cpu->env;
> +
> +    return arm_feature(env, ARM_FEATURE_SVE);
> +}
> +
> +/* The first two words of each Zreg is stored in VFP state.  */
> +static const VMStateDescription vmstate_zreg_hi_reg = {
> +    .name = "cpu/sve/zreg_hi",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT64_SUB_ARRAY(d, ARMVectorReg, 2, ARM_MAX_VQ - 2),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static const VMStateDescription vmstate_preg_reg = {
> +    .name = "cpu/sve/preg",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT64_ARRAY(p, ARMPredicateReg, 2 * ARM_MAX_VQ / 8),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static const VMStateDescription vmstate_sve = {
> +    .name = "cpu/sve",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .needed = sve_needed,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_STRUCT_ARRAY(env.vfp.zregs, ARMCPU, 32, 0,
> +                             vmstate_zreg_hi_reg, ARMVectorReg),
> +        VMSTATE_STRUCT_ARRAY(env.vfp.pregs, ARMCPU, 17, 0,
> +                             vmstate_preg_reg, ARMPredicateReg),

Is it the QEMU_ALIGNED attribute that means we need to do the pregs
via a STRUCT_ARRAY rather than being able to use a UINT64_2DARRAY ?

> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +#endif /* AARCH64 */

thanks
-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 12/16] target/arm: Add ZCR_ELx
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 12/16] target/arm: Add ZCR_ELx Richard Henderson
@ 2018-01-22 14:38   ` Peter Maydell
  2018-01-22 15:00   ` Alex Bennée
  1 sibling, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2018-01-22 14:38 UTC (permalink / raw)
  To: Richard Henderson; +Cc: QEMU Developers

On 19 January 2018 at 04:54, Richard Henderson
<richard.henderson@linaro.org> wrote:
> Define ZCR_EL[1-3].
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/cpu.h    |  5 ++++
>  target/arm/helper.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 85 insertions(+)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 0a923e42d8..c8e8155b6e 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -547,6 +547,9 @@ typedef struct CPUARMState {
>           */
>          float_status fp_status;
>          float_status standard_fp_status;
> +
> +        /* ZCR_EL[1-3] */
> +        uint64_t zcr_el[4];
>      } vfp;
>      uint64_t exclusive_addr;
>      uint64_t exclusive_val;
> @@ -921,6 +924,8 @@ void pmccntr_sync(CPUARMState *env);
>  #define CPTR_TCPAC    (1U << 31)
>  #define CPTR_TTA      (1U << 20)
>  #define CPTR_TFP      (1U << 10)
> +#define CPTR_TZ       (1U << 8)   /* CPTR_EL2 */
> +#define CPTR_EZ       (1U << 8)   /* CPTR_EL3 */
>
>  #define MDCR_EPMAD    (1U << 21)
>  #define MDCR_EDAD     (1U << 20)
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 6705903301..984a4b1306 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -4266,6 +4266,82 @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
>      REGINFO_SENTINEL
>  };
>
> +/* Return the exception level to which SVE-disabled exceptions should
> + * be taken, or 0 if SVE is enabled.
> + */
> +static int sve_exception_el(CPUARMState *env)
> +{
> +#ifndef CONFIG_USER_ONLY
> +    int highest_el = arm_highest_el(env);
> +    int current_el = arm_current_el(env);
> +    int i;
> +
> +    for (i = highest_el; i >= MAX(1, current_el); --i) {

This structure is a bit odd, because it doesn't account for the
possibility that EL3 could be implemented but EL2 not. Usually
these access checks are written as a series of if()s (see eg
access_tda(), access_tpm()). Where the register bit defaults to
the right thing for an unimplemented EL we can get away without
the arm_feature(env, ARM_FEATURE_ELx) test.

It also doesn't get the prioritization right if more than one
trap bit is set. This is defined by "Synchronous exception
prioritization for exceptions taken to AArch64" in the v8A Arm ARM,
which says that exceptions taken to EL2 because of CPTR_EL2
bits take precedence over taking an exception to EL3 because
of CPTR_EL3 bits (items 10 and 15 in the list), and taking
the exception to EL1 because of CPACR_EL1 takes precedence
over both (item 8).

> +        switch (i) {
> +        case 3:
> +            if ((env->cp15.cptr_el[3] & CPTR_EZ) == 0) {
> +                return 3;
> +            }
> +            break;
> +        case 2:
> +            if (env->cp15.cptr_el[2] & CPTR_TZ) {
> +                return 2;
> +            }

You need to check that we're in NonSecure before honouring
this trap bit, otherwise Secure EL1/EL0 would trap to EL2.

> +            break;
> +        case 1:
> +            switch (extract32(env->cp15.cpacr_el1, 16, 2)) {
> +            case 1:
> +                return current_el == 0 ? 1 : 0;
> +            case 3:
> +                return 0;
> +            default:
> +                return 1;
> +            }
> +        }
> +    }
> +#endif
> +    return 0;
> +}
> +
> +static CPAccessResult zcr_access(CPUARMState *env, const ARMCPRegInfo *ri,
> +                                 bool isread)
> +{
> +    switch (sve_exception_el(env)) {
> +    case 3:
> +        return CP_ACCESS_TRAP_EL3;
> +    case 2:
> +        return CP_ACCESS_TRAP_EL2;
> +    case 1:
> +        return CP_ACCESS_TRAP;
> +    }
> +    return CP_ACCESS_OK;
> +}
> +
> +static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> +                      uint64_t value)
> +{
> +    /* Bits other than [3:0] are RAZ/WI.  */
> +    raw_write(env, ri, value & 0xf);
> +}
> +
> +static const ARMCPRegInfo sve_cp_reginfo[] = {
> +    { .name = "ZCR_EL1", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 0,

Are you sure the encodings are right here? My docs say opc0 == 3
for all of these.

> +      .access = PL1_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
> +      .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[1]),
> +      .writefn = zcr_write, .raw_writefn = raw_write, },
> +    { .name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 2, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
> +      .access = PL2_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
> +      .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[2]),
> +      .writefn = zcr_write, .raw_writefn = raw_write, },
> +    { .name = "ZCR_EL3", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 2, .opc1 = 6, .crn = 1, .crm = 2, .opc2 = 0,
> +      .access = PL1_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,

Shouldn't this be PL3_RW ? At any rate you need something to
stop NS EL1 and EL2 from being able to access it.

> +      .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[3]),
> +      .writefn = zcr_write, .raw_writefn = raw_write, },
> +};
> +
>  void hw_watchpoint_update(ARMCPU *cpu, int n)
>  {
>      CPUARMState *env = &cpu->env;
> @@ -5332,6 +5408,10 @@ void register_cp_regs_for_features(ARMCPU *cpu)
>          }
>          define_one_arm_cp_reg(cpu, &sctlr);
>      }
> +
> +    if (arm_feature(env, ARM_FEATURE_SVE)) {
> +        define_arm_cp_regs(cpu, sve_cp_reginfo);
> +    }
>  }
>
>  void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
> --
> 2.14.3

thanks
-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 16/16] target/arm: Add SVE state to TB->FLAGS
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 16/16] target/arm: Add SVE state to TB->FLAGS Richard Henderson
@ 2018-01-22 14:40   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2018-01-22 14:40 UTC (permalink / raw)
  To: Richard Henderson; +Cc: QEMU Developers

On 19 January 2018 at 04:54, Richard Henderson
<richard.henderson@linaro.org> wrote:
> Add both SVE exception state and vector length.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

> @@ -11772,14 +11772,35 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
>                            target_ulong *cs_base, uint32_t *pflags)
>  {
>      ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
> +    int fp_el = fp_exception_el(env);
>      uint32_t flags;
>
>      if (is_a64(env)) {
> +        int sve_el = sve_exception_el(env);
> +        uint32_t zcr_len;
> +
>          *pc = env->pc;
>          flags = ARM_TBFLAG_AARCH64_STATE_MASK;
>          /* Get control bits for tagged addresses */
>          flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
>          flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
> +        flags |= sve_el << ARM_TBFLAG_SVEEXC_EL_SHIFT;
> +
> +        /* If SVE is disabled, but FP is enabled,
> +           then the effective len is 0.  */
> +        if (sve_el != 0 && fp_el == 0) {
> +            zcr_len = 0;
> +        } else {
> +            int highest_el = arm_highest_el(env);
> +            int current_el = arm_current_el(env);
> +            int i;
> +
> +            zcr_len = 0xf & (uint32_t)env->vfp.zcr_el[highest_el];
> +            for (i = highest_el - 1; i >= MAX(1, current_el); --i) {
> +                zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[i]);
> +            }

This loop also doesn't consider the case of EL3 implemented but
EL2 not, I think.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 12/16] target/arm: Add ZCR_ELx
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 12/16] target/arm: Add ZCR_ELx Richard Henderson
  2018-01-22 14:38   ` Peter Maydell
@ 2018-01-22 15:00   ` Alex Bennée
  1 sibling, 0 replies; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 15:00 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> Define ZCR_EL[1-3].
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/cpu.h    |  5 ++++
>  target/arm/helper.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 85 insertions(+)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 0a923e42d8..c8e8155b6e 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -547,6 +547,9 @@ typedef struct CPUARMState {
>           */
>          float_status fp_status;
>          float_status standard_fp_status;
> +
> +        /* ZCR_EL[1-3] */
> +        uint64_t zcr_el[4];
>      } vfp;
>      uint64_t exclusive_addr;
>      uint64_t exclusive_val;
> @@ -921,6 +924,8 @@ void pmccntr_sync(CPUARMState *env);
>  #define CPTR_TCPAC    (1U << 31)
>  #define CPTR_TTA      (1U << 20)
>  #define CPTR_TFP      (1U << 10)
> +#define CPTR_TZ       (1U << 8)   /* CPTR_EL2 */
> +#define CPTR_EZ       (1U << 8)   /* CPTR_EL3 */
>
>  #define MDCR_EPMAD    (1U << 21)
>  #define MDCR_EDAD     (1U << 20)
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 6705903301..984a4b1306 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -4266,6 +4266,82 @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
>      REGINFO_SENTINEL
>  };
>
> +/* Return the exception level to which SVE-disabled exceptions should
> + * be taken, or 0 if SVE is enabled.
> + */
> +static int sve_exception_el(CPUARMState *env)
> +{
> +#ifndef CONFIG_USER_ONLY
> +    int highest_el = arm_highest_el(env);
> +    int current_el = arm_current_el(env);
> +    int i;
> +
> +    for (i = highest_el; i >= MAX(1, current_el); --i) {
> +        switch (i) {
> +        case 3:
> +            if ((env->cp15.cptr_el[3] & CPTR_EZ) == 0) {
> +                return 3;
> +            }
> +            break;
> +        case 2:
> +            if (env->cp15.cptr_el[2] & CPTR_TZ) {
> +                return 2;
> +            }
> +            break;
> +        case 1:

Might be worth a comment /* ZEN bits */

> +            switch (extract32(env->cp15.cpacr_el1, 16, 2)) {
> +            case 1:
> +                return current_el == 0 ? 1 : 0;
> +            case 3:
> +                return 0;
> +            default:
> +                return 1;

Am I missing something here?

"Traps SVE instructions and instructions that access SVE System registers at EL0 and EL1 to EL1,
or to EL2 when SCR_EL3.NS and HCR_EL2.TGE are both 1. Defined values
are:"


> +            }
> +        }
> +    }
> +#endif
> +    return 0;
> +}
> +
> +static CPAccessResult zcr_access(CPUARMState *env, const ARMCPRegInfo *ri,
> +                                 bool isread)
> +{
> +    switch (sve_exception_el(env)) {
> +    case 3:
> +        return CP_ACCESS_TRAP_EL3;
> +    case 2:
> +        return CP_ACCESS_TRAP_EL2;
> +    case 1:
> +        return CP_ACCESS_TRAP;
> +    }
> +    return CP_ACCESS_OK;
> +}
> +
> +static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> +                      uint64_t value)
> +{
> +    /* Bits other than [3:0] are RAZ/WI.  */
> +    raw_write(env, ri, value & 0xf);
> +}
> +
> +static const ARMCPRegInfo sve_cp_reginfo[] = {
> +    { .name = "ZCR_EL1", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 0,
> +      .access = PL1_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
> +      .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[1]),
> +      .writefn = zcr_write, .raw_writefn = raw_write, },
> +    { .name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 2, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
> +      .access = PL2_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
> +      .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[2]),
> +      .writefn = zcr_write, .raw_writefn = raw_write, },
> +    { .name = "ZCR_EL3", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 2, .opc1 = 6, .crn = 1, .crm = 2, .opc2 = 0,
> +      .access = PL1_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
> +      .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[3]),
> +      .writefn = zcr_write, .raw_writefn = raw_write, },
> +};
> +
>  void hw_watchpoint_update(ARMCPU *cpu, int n)
>  {
>      CPUARMState *env = &cpu->env;
> @@ -5332,6 +5408,10 @@ void register_cp_regs_for_features(ARMCPU *cpu)
>          }
>          define_one_arm_cp_reg(cpu, &sctlr);
>      }
> +
> +    if (arm_feature(env, ARM_FEATURE_SVE)) {
> +        define_arm_cp_regs(cpu, sve_cp_reginfo);
> +    }
>  }
>
>  void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)


--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 13/16] target/arm: Move cpu_get_tb_cpu_state out of line
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 13/16] target/arm: Move cpu_get_tb_cpu_state out of line Richard Henderson
@ 2018-01-22 15:07   ` Alex Bennée
  2018-01-22 16:18     ` Richard Henderson
  0 siblings, 1 reply; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 15:07 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/cpu.h    | 127 +---------------------------------------------------
>  target/arm/helper.c | 126
> +++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 128 insertions(+), 125 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index c8e8155b6e..2de1afb53a 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -2703,71 +2703,6 @@ static inline bool bswap_code(bool sctlr_b)
>  #endif
>  }
>
> -/* Return the exception level to which FP-disabled exceptions should
> - * be taken, or 0 if FP is enabled.
> - */
> -static inline int fp_exception_el(CPUARMState *env)
> -{
> -    int fpen;
> -    int cur_el = arm_current_el(env);
> -
> -    /* CPACR and the CPTR registers don't exist before v6, so FP is
> -     * always accessible
> -     */
> -    if (!arm_feature(env, ARM_FEATURE_V6)) {
> -        return 0;
> -    }
> -
> -    /* The CPACR controls traps to EL1, or PL1 if we're 32 bit:
> -     * 0, 2 : trap EL0 and EL1/PL1 accesses
> -     * 1    : trap only EL0 accesses
> -     * 3    : trap no accesses
> -     */
> -    fpen = extract32(env->cp15.cpacr_el1, 20, 2);
> -    switch (fpen) {
> -    case 0:
> -    case 2:
> -        if (cur_el == 0 || cur_el == 1) {
> -            /* Trap to PL1, which might be EL1 or EL3 */
> -            if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
> -                return 3;
> -            }
> -            return 1;
> -        }
> -        if (cur_el == 3 && !is_a64(env)) {
> -            /* Secure PL1 running at EL3 */
> -            return 3;
> -        }
> -        break;
> -    case 1:
> -        if (cur_el == 0) {
> -            return 1;
> -        }
> -        break;
> -    case 3:
> -        break;
> -    }
> -
> -    /* For the CPTR registers we don't need to guard with an ARM_FEATURE
> -     * check because zero bits in the registers mean "don't trap".
> -     */
> -
> -    /* CPTR_EL2 : present in v7VE or v8 */
> -    if (cur_el <= 2 && extract32(env->cp15.cptr_el[2], 10, 1)
> -        && !arm_is_secure_below_el3(env)) {
> -        /* Trap FP ops at EL2, NS-EL1 or NS-EL0 to EL2 */
> -        return 2;
> -    }
> -
> -    /* CPTR_EL3 : present in v8 */
> -    if (extract32(env->cp15.cptr_el[3], 10, 1)) {
> -        /* Trap all FP ops to EL3 */
> -        return 3;
> -    }
> -
> -    return 0;
> -}
> -
>  #ifdef CONFIG_USER_ONLY
>  static inline bool arm_cpu_bswap_data(CPUARMState *env)
>  {
> @@ -2814,66 +2749,8 @@ static inline uint32_t arm_regime_tbi1(CPUARMState *env, ARMMMUIdx mmu_idx)
>  }
>  #endif
>
> -static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
> -                                        target_ulong *cs_base, uint32_t *flags)
> -{
> -    ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
> -    if (is_a64(env)) {
> -        *pc = env->pc;
> -        *flags = ARM_TBFLAG_AARCH64_STATE_MASK;
> -        /* Get control bits for tagged addresses */
> -        *flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
> -        *flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
> -    } else {
> -        *pc = env->regs[15];
> -        *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
> -            | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
> -            | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
> -            | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
> -            | (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT);
> -        if (!(access_secure_reg(env))) {
> -            *flags |= ARM_TBFLAG_NS_MASK;
> -        }
> -        if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
> -            || arm_el_is_aa64(env, 1)) {
> -            *flags |= ARM_TBFLAG_VFPEN_MASK;
> -        }
> -        *flags |= (extract32(env->cp15.c15_cpar, 0, 2)
> -                   << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
> -    }
> -
> -    *flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT);
> -
> -    /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
> -     * states defined in the ARM ARM for software singlestep:
> -     *  SS_ACTIVE   PSTATE.SS   State
> -     *     0            x       Inactive (the TB flag for SS is always 0)
> -     *     1            0       Active-pending
> -     *     1            1       Active-not-pending
> -     */
> -    if (arm_singlestep_active(env)) {
> -        *flags |= ARM_TBFLAG_SS_ACTIVE_MASK;
> -        if (is_a64(env)) {
> -            if (env->pstate & PSTATE_SS) {
> -                *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
> -            }
> -        } else {
> -            if (env->uncached_cpsr & PSTATE_SS) {
> -                *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
> -            }
> -        }
> -    }
> -    if (arm_cpu_data_is_big_endian(env)) {
> -        *flags |= ARM_TBFLAG_BE_DATA_MASK;
> -    }
> -    *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
> -
> -    if (arm_v7m_is_handler_mode(env)) {
> -        *flags |= ARM_TBFLAG_HANDLER_MASK;
> -    }
> -
> -    *cs_base = 0;
> -}
> +void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
> +                          target_ulong *cs_base, uint32_t *flags);
>
>  enum {
>      QEMU_PSCI_CONDUIT_DISABLED = 0,
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 984a4b1306..9e673bb672 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -11701,3 +11701,129 @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
>      /* Linux crc32c converts the output to one's complement.  */
>      return crc32c(acc, buf, bytes) ^ 0xffffffff;
>  }
> +
> +/* Return the exception level to which FP-disabled exceptions should
> + * be taken, or 0 if FP is enabled.
> + */
> +static inline int fp_exception_el(CPUARMState *env)

You can drop the inline here. The compiler knows what to do and we are
no longer in a header.

> +{
> +    int fpen;
> +    int cur_el = arm_current_el(env);
> +
> +    /* CPACR and the CPTR registers don't exist before v6, so FP is
> +     * always accessible
> +     */
> +    if (!arm_feature(env, ARM_FEATURE_V6)) {
> +        return 0;
> +    }
> +
> +    /* The CPACR controls traps to EL1, or PL1 if we're 32 bit:
> +     * 0, 2 : trap EL0 and EL1/PL1 accesses
> +     * 1    : trap only EL0 accesses
> +     * 3    : trap no accesses
> +     */
> +    fpen = extract32(env->cp15.cpacr_el1, 20, 2);
> +    switch (fpen) {
> +    case 0:
> +    case 2:
> +        if (cur_el == 0 || cur_el == 1) {
> +            /* Trap to PL1, which might be EL1 or EL3 */
> +            if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
> +                return 3;
> +            }
> +            return 1;
> +        }
> +        if (cur_el == 3 && !is_a64(env)) {
> +            /* Secure PL1 running at EL3 */
> +            return 3;
> +        }
> +        break;
> +    case 1:
> +        if (cur_el == 0) {
> +            return 1;
> +        }
> +        break;
> +    case 3:
> +        break;
> +    }
> +
> +    /* For the CPTR registers we don't need to guard with an ARM_FEATURE
> +     * check because zero bits in the registers mean "don't trap".
> +     */
> +
> +    /* CPTR_EL2 : present in v7VE or v8 */
> +    if (cur_el <= 2 && extract32(env->cp15.cptr_el[2], 10, 1)
> +        && !arm_is_secure_below_el3(env)) {
> +        /* Trap FP ops at EL2, NS-EL1 or NS-EL0 to EL2 */
> +        return 2;
> +    }
> +
> +    /* CPTR_EL3 : present in v8 */
> +    if (extract32(env->cp15.cptr_el[3], 10, 1)) {
> +        /* Trap all FP ops to EL3 */
> +        return 3;
> +    }
> +
> +    return 0;
> +}

I'm not sure helper.c is the best place for this. Maybe cpu.c?

> +
> +void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
> +                          target_ulong *cs_base, uint32_t *flags)
> +{
> +    ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
> +    if (is_a64(env)) {
> +        *pc = env->pc;
> +        *flags = ARM_TBFLAG_AARCH64_STATE_MASK;
> +        /* Get control bits for tagged addresses */
> +        *flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
> +        *flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
> +    } else {
> +        *pc = env->regs[15];
> +        *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
> +            | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
> +            | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
> +            | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
> +            | (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT);
> +        if (!(access_secure_reg(env))) {
> +            *flags |= ARM_TBFLAG_NS_MASK;
> +        }
> +        if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
> +            || arm_el_is_aa64(env, 1)) {
> +            *flags |= ARM_TBFLAG_VFPEN_MASK;
> +        }
> +        *flags |= (extract32(env->cp15.c15_cpar, 0, 2)
> +                   << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
> +    }
> +
> +    *flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT);
> +
> +    /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
> +     * states defined in the ARM ARM for software singlestep:
> +     *  SS_ACTIVE   PSTATE.SS   State
> +     *     0            x       Inactive (the TB flag for SS is always 0)
> +     *     1            0       Active-pending
> +     *     1            1       Active-not-pending
> +     */
> +    if (arm_singlestep_active(env)) {
> +        *flags |= ARM_TBFLAG_SS_ACTIVE_MASK;
> +        if (is_a64(env)) {
> +            if (env->pstate & PSTATE_SS) {
> +                *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
> +            }
> +        } else {
> +            if (env->uncached_cpsr & PSTATE_SS) {
> +                *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
> +            }
> +        }
> +    }
> +    if (arm_cpu_data_is_big_endian(env)) {
> +        *flags |= ARM_TBFLAG_BE_DATA_MASK;
> +    }
> +    *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
> +
> +    if (arm_v7m_is_handler_mode(env)) {
> +        *flags |= ARM_TBFLAG_HANDLER_MASK;
> +    }
> +
> +    *cs_base = 0;
> +}


--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 14/16] target/arm: Hoist store to flags output in cpu_get_tb_cpu_state
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 14/16] target/arm: Hoist store to flags output in cpu_get_tb_cpu_state Richard Henderson
@ 2018-01-22 15:09   ` Alex Bennée
  0 siblings, 0 replies; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 15:09 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

But it would be nice to resurrect Paolo's tb state caching series as
this is an expensive function to re-compute everytime.

> ---
>  target/arm/helper.c | 35 +++++++++++++++++++----------------
>  1 file changed, 19 insertions(+), 16 deletions(-)
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 9e673bb672..c0e5f321c5 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -11768,34 +11768,36 @@ static inline int fp_exception_el(CPUARMState *env)
>  }
>
>  void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
> -                          target_ulong *cs_base, uint32_t *flags)
> +                          target_ulong *cs_base, uint32_t *pflags)
>  {
>      ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
> +    uint32_t flags;
> +
>      if (is_a64(env)) {
>          *pc = env->pc;
> -        *flags = ARM_TBFLAG_AARCH64_STATE_MASK;
> +        flags = ARM_TBFLAG_AARCH64_STATE_MASK;
>          /* Get control bits for tagged addresses */
> -        *flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
> -        *flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
> +        flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
> +        flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
>      } else {
>          *pc = env->regs[15];
> -        *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
> +        flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
>              | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
>              | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
>              | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
>              | (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT);
>          if (!(access_secure_reg(env))) {
> -            *flags |= ARM_TBFLAG_NS_MASK;
> +            flags |= ARM_TBFLAG_NS_MASK;
>          }
>          if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
>              || arm_el_is_aa64(env, 1)) {
> -            *flags |= ARM_TBFLAG_VFPEN_MASK;
> +            flags |= ARM_TBFLAG_VFPEN_MASK;
>          }
> -        *flags |= (extract32(env->cp15.c15_cpar, 0, 2)
> -                   << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
> +        flags |= (extract32(env->cp15.c15_cpar, 0, 2)
> +                  << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
>      }
>
> -    *flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT);
> +    flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT);
>
>      /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
>       * states defined in the ARM ARM for software singlestep:
> @@ -11805,25 +11807,26 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
>       *     1            1       Active-not-pending
>       */
>      if (arm_singlestep_active(env)) {
> -        *flags |= ARM_TBFLAG_SS_ACTIVE_MASK;
> +        flags |= ARM_TBFLAG_SS_ACTIVE_MASK;
>          if (is_a64(env)) {
>              if (env->pstate & PSTATE_SS) {
> -                *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
> +                flags |= ARM_TBFLAG_PSTATE_SS_MASK;
>              }
>          } else {
>              if (env->uncached_cpsr & PSTATE_SS) {
> -                *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
> +                flags |= ARM_TBFLAG_PSTATE_SS_MASK;
>              }
>          }
>      }
>      if (arm_cpu_data_is_big_endian(env)) {
> -        *flags |= ARM_TBFLAG_BE_DATA_MASK;
> +        flags |= ARM_TBFLAG_BE_DATA_MASK;
>      }
> -    *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
> +    flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
>
>      if (arm_v7m_is_handler_mode(env)) {
> -        *flags |= ARM_TBFLAG_HANDLER_MASK;
> +        flags |= ARM_TBFLAG_HANDLER_MASK;
>      }
>
> +    *pflags = flags;
>      *cs_base = 0;
>  }


--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 15/16] target/arm: Simplify fp_exception_el for user-only
  2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 15/16] target/arm: Simplify fp_exception_el for user-only Richard Henderson
@ 2018-01-22 15:10   ` Alex Bennée
  0 siblings, 0 replies; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 15:10 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target/arm/helper.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index c0e5f321c5..44814af99b 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -11707,6 +11707,7 @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
>   */
>  static inline int fp_exception_el(CPUARMState *env)
>  {
> +#ifndef CONFIG_USER_ONLY
>      int fpen;
>      int cur_el = arm_current_el(env);
>
> @@ -11763,7 +11764,7 @@ static inline int fp_exception_el(CPUARMState *env)
>          /* Trap all FP ops to EL3 */
>          return 3;
>      }
> -
> +#endif
>      return 0;
>  }


--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE
  2018-01-22 14:12 ` Peter Maydell
@ 2018-01-22 15:12   ` Alex Bennée
  0 siblings, 0 replies; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 15:12 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Richard Henderson, QEMU Developers


Peter Maydell <peter.maydell@linaro.org> writes:

> On 19 January 2018 at 04:54, Richard Henderson
> <richard.henderson@linaro.org> wrote:
>> I believe that this addresses all of the comments Peter had with
>> respect to v1.  I did go ahead and add the system registers, so that
>> I could figure out how they're supposed to work.
>>
>> This has been rebased to master so that it has no dependencies.
>>
>>
>> r~
>>
>>
>> Richard Henderson (16):
>> 1  target/arm: Mark disas_set_insn_syndrome inline
>> 2  target/arm: Use pointers in crypto helpers
>> 3  target/arm: Use pointers in neon zip/uzp helpers
>> 4  target/arm: Use pointers in neon tbl helper
>> 5  target/arm: Change the type of vfp.regs
>> 6  target/arm: Add aa{32,64}_vfp_{dreg,qreg} helpers
>> 7  vmstate: Add VMSTATE_UINT64_SUB_ARRAY
>> 8  target/arm: Expand vector registers for SVE
>> 9  target/arm: Add predicate registers for SVE
>> 10 target/arm: Add ARM_FEATURE_SVE
>> 11 target/arm: Add SVE to migration state
>> 12 target/arm: Add ZCR_ELx
>> 13 target/arm: Move cpu_get_tb_cpu_state out of line
>> 14 target/arm: Hoist store to flags output in cpu_get_tb_cpu_state
>> 15 target/arm: Simplify fp_exception_el for user-only
>> 16 target/arm: Add SVE state to TB->FLAGS
>
> In the interests of reducing the size of this patch set, I'm going to
> take patches 1..7, 10, 13..15 into target-arm.next. (Alex, I know
> you had a nit about changing the type of a variable in patch 4 but
> I think I'd rather just take the patchset rather than do another
> round with it for that.)

Sure - it was only a nit ;-)

>
> The target-arm.next branch (which rebases!) with those patches is at:
>
> https://git.linaro.org/people/peter.maydell/qemu-arm.git target-arm.next
>
> I expect I'll make a pullreq either tomorrow or more likely Thursday.
>
> thanks
> -- PMM


--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE
  2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
                   ` (17 preceding siblings ...)
  2018-01-22 14:12 ` Peter Maydell
@ 2018-01-22 15:12 ` Alex Bennée
  18 siblings, 0 replies; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 15:12 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> I believe that this addresses all of the comments Peter had with
> respect to v1.  I did go ahead and add the system registers, so that
> I could figure out how they're supposed to work.
>
> This has been rebased to master so that it has no dependencies.

I've completed my review pass for this series now, looking pretty good.

--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 05/16] target/arm: Change the type of vfp.regs
  2018-01-22 10:56   ` Alex Bennée
@ 2018-01-22 16:03     ` Richard Henderson
  0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2018-01-22 16:03 UTC (permalink / raw)
  To: Alex Bennée; +Cc: qemu-devel, peter.maydell

On 01/22/2018 02:56 AM, Alex Bennée wrote:
> 
> Richard Henderson <richard.henderson@linaro.org> writes:
> 
>> All direct users of this field want an integral value.  Drop all
>> of the extra casting between uint64_t and float64.
> 
> Did the extra casting ever generate superfluous code?

No, it's just ugly.


r~

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 09/16] target/arm: Add predicate registers for SVE
  2018-01-22 12:04   ` Alex Bennée
@ 2018-01-22 16:07     ` Richard Henderson
  2018-01-22 18:35       ` Alex Bennée
  0 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2018-01-22 16:07 UTC (permalink / raw)
  To: Alex Bennée; +Cc: qemu-devel, peter.maydell

On 01/22/2018 04:04 AM, Alex Bennée wrote:
> 
> Richard Henderson <richard.henderson@linaro.org> writes:
> 
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>  target/arm/cpu.h | 12 ++++++++++++
>>  1 file changed, 12 insertions(+)
>>
>> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
>> index 57d805b5d8..132da359b5 100644
>> --- a/target/arm/cpu.h
>> +++ b/target/arm/cpu.h
>> @@ -186,6 +186,15 @@ typedef struct ARMVectorReg {
>>      uint64_t d[2 * ARM_MAX_VQ] QEMU_ALIGNED(16);
>>  } ARMVectorReg;
>>
>> +/* In AArch32 mode, predicate registers do not exist at all.  */
>> +typedef struct ARMPredicateReg {
>> +#ifdef TARGET_AARCH64
>> +    uint64_t p[2 * ARM_MAX_VQ / 8] QEMU_ALIGNED(16);
>> +#else
>> +    uint64_t p[0];
>> +#endif
>> +} ARMPredicateReg;
>> +
>>
>>  typedef struct CPUARMState {
>>      /* Regs for current mode.  */
>> @@ -513,6 +522,9 @@ typedef struct CPUARMState {
>>      struct {
>>          ARMVectorReg zregs[32];
>>
>> +        /* Store FFR as pregs[16] to make it easier to treat as any other.  */
>> +        ARMPredicateReg pregs[17];
>> +
> 
> What happens if code tries to accidentally access this on the 32 bit build?

*shrug* About what you'd expect.  What do you suggest?  Ifdeffery?


r~

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 11/16] target/arm: Add SVE to migration state
  2018-01-22 14:16   ` Peter Maydell
@ 2018-01-22 16:10     ` Richard Henderson
  0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2018-01-22 16:10 UTC (permalink / raw)
  To: Peter Maydell; +Cc: QEMU Developers

On 01/22/2018 06:16 AM, Peter Maydell wrote:
>> +/* The first two words of each Zreg is stored in VFP state.  */
>> +static const VMStateDescription vmstate_zreg_hi_reg = {
>> +    .name = "cpu/sve/zreg_hi",
>> +    .version_id = 1,
>> +    .minimum_version_id = 1,
>> +    .fields = (VMStateField[]) {
>> +        VMSTATE_UINT64_SUB_ARRAY(d, ARMVectorReg, 2, ARM_MAX_VQ - 2),
>> +        VMSTATE_END_OF_LIST()
>> +    }
>> +};
>> +
>> +static const VMStateDescription vmstate_preg_reg = {
>> +    .name = "cpu/sve/preg",
>> +    .version_id = 1,
>> +    .minimum_version_id = 1,
>> +    .fields = (VMStateField[]) {
>> +        VMSTATE_UINT64_ARRAY(p, ARMPredicateReg, 2 * ARM_MAX_VQ / 8),
>> +        VMSTATE_END_OF_LIST()
>> +    }
>> +};
>> +
>> +static const VMStateDescription vmstate_sve = {
>> +    .name = "cpu/sve",
>> +    .version_id = 1,
>> +    .minimum_version_id = 1,
>> +    .needed = sve_needed,
>> +    .fields = (VMStateField[]) {
>> +        VMSTATE_STRUCT_ARRAY(env.vfp.zregs, ARMCPU, 32, 0,
>> +                             vmstate_zreg_hi_reg, ARMVectorReg),
>> +        VMSTATE_STRUCT_ARRAY(env.vfp.pregs, ARMCPU, 17, 0,
>> +                             vmstate_preg_reg, ARMPredicateReg),
> 
> Is it the QEMU_ALIGNED attribute that means we need to do the pregs
> via a STRUCT_ARRAY rather than being able to use a UINT64_2DARRAY ?

I didn't try; I was copying from the x86 code.


r~

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 11/16] target/arm: Add SVE to migration state
  2018-01-22 13:40   ` Alex Bennée
@ 2018-01-22 16:11     ` Richard Henderson
  0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2018-01-22 16:11 UTC (permalink / raw)
  To: Alex Bennée; +Cc: qemu-devel, peter.maydell

On 01/22/2018 05:40 AM, Alex Bennée wrote:
>> +#ifdef TARGET_AARCH64
>> +/* The expression ARM_MAX_VQ - 2 is 0 for pure AArch32 build,
>> + * and ARMPredicateReg is actively empty.  This triggers errors
>> + * in the expansion of the VMSTATE macros.
>> + */
> 
> This makes me think that #ifdef-ing out the pregs might be better for
> the 32 bit target build.

Fair.


r~

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 13/16] target/arm: Move cpu_get_tb_cpu_state out of line
  2018-01-22 15:07   ` Alex Bennée
@ 2018-01-22 16:18     ` Richard Henderson
  0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2018-01-22 16:18 UTC (permalink / raw)
  To: Alex Bennée; +Cc: qemu-devel, peter.maydell

On 01/22/2018 07:07 AM, Alex Bennée wrote:
> 
> Richard Henderson <richard.henderson@linaro.org> writes:
> 
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>  target/arm/cpu.h    | 127 +---------------------------------------------------
>>  target/arm/helper.c | 126
>> +++++++++++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 128 insertions(+), 125 deletions(-)
>>
>> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
>> index c8e8155b6e..2de1afb53a 100644
>> --- a/target/arm/cpu.h
>> +++ b/target/arm/cpu.h
>> @@ -2703,71 +2703,6 @@ static inline bool bswap_code(bool sctlr_b)
>>  #endif
>>  }
>>
>> -/* Return the exception level to which FP-disabled exceptions should
>> - * be taken, or 0 if FP is enabled.
>> - */
>> -static inline int fp_exception_el(CPUARMState *env)
>> -{
>> -    int fpen;
>> -    int cur_el = arm_current_el(env);
>> -
>> -    /* CPACR and the CPTR registers don't exist before v6, so FP is
>> -     * always accessible
>> -     */
>> -    if (!arm_feature(env, ARM_FEATURE_V6)) {
>> -        return 0;
>> -    }
>> -
>> -    /* The CPACR controls traps to EL1, or PL1 if we're 32 bit:
>> -     * 0, 2 : trap EL0 and EL1/PL1 accesses
>> -     * 1    : trap only EL0 accesses
>> -     * 3    : trap no accesses
>> -     */
>> -    fpen = extract32(env->cp15.cpacr_el1, 20, 2);
>> -    switch (fpen) {
>> -    case 0:
>> -    case 2:
>> -        if (cur_el == 0 || cur_el == 1) {
>> -            /* Trap to PL1, which might be EL1 or EL3 */
>> -            if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
>> -                return 3;
>> -            }
>> -            return 1;
>> -        }
>> -        if (cur_el == 3 && !is_a64(env)) {
>> -            /* Secure PL1 running at EL3 */
>> -            return 3;
>> -        }
>> -        break;
>> -    case 1:
>> -        if (cur_el == 0) {
>> -            return 1;
>> -        }
>> -        break;
>> -    case 3:
>> -        break;
>> -    }
>> -
>> -    /* For the CPTR registers we don't need to guard with an ARM_FEATURE
>> -     * check because zero bits in the registers mean "don't trap".
>> -     */
>> -
>> -    /* CPTR_EL2 : present in v7VE or v8 */
>> -    if (cur_el <= 2 && extract32(env->cp15.cptr_el[2], 10, 1)
>> -        && !arm_is_secure_below_el3(env)) {
>> -        /* Trap FP ops at EL2, NS-EL1 or NS-EL0 to EL2 */
>> -        return 2;
>> -    }
>> -
>> -    /* CPTR_EL3 : present in v8 */
>> -    if (extract32(env->cp15.cptr_el[3], 10, 1)) {
>> -        /* Trap all FP ops to EL3 */
>> -        return 3;
>> -    }
>> -
>> -    return 0;
>> -}
>> -
>>  #ifdef CONFIG_USER_ONLY
>>  static inline bool arm_cpu_bswap_data(CPUARMState *env)
>>  {
>> @@ -2814,66 +2749,8 @@ static inline uint32_t arm_regime_tbi1(CPUARMState *env, ARMMMUIdx mmu_idx)
>>  }
>>  #endif
>>
>> -static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
>> -                                        target_ulong *cs_base, uint32_t *flags)
>> -{
>> -    ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
>> -    if (is_a64(env)) {
>> -        *pc = env->pc;
>> -        *flags = ARM_TBFLAG_AARCH64_STATE_MASK;
>> -        /* Get control bits for tagged addresses */
>> -        *flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
>> -        *flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
>> -    } else {
>> -        *pc = env->regs[15];
>> -        *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
>> -            | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
>> -            | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
>> -            | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
>> -            | (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT);
>> -        if (!(access_secure_reg(env))) {
>> -            *flags |= ARM_TBFLAG_NS_MASK;
>> -        }
>> -        if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
>> -            || arm_el_is_aa64(env, 1)) {
>> -            *flags |= ARM_TBFLAG_VFPEN_MASK;
>> -        }
>> -        *flags |= (extract32(env->cp15.c15_cpar, 0, 2)
>> -                   << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
>> -    }
>> -
>> -    *flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT);
>> -
>> -    /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
>> -     * states defined in the ARM ARM for software singlestep:
>> -     *  SS_ACTIVE   PSTATE.SS   State
>> -     *     0            x       Inactive (the TB flag for SS is always 0)
>> -     *     1            0       Active-pending
>> -     *     1            1       Active-not-pending
>> -     */
>> -    if (arm_singlestep_active(env)) {
>> -        *flags |= ARM_TBFLAG_SS_ACTIVE_MASK;
>> -        if (is_a64(env)) {
>> -            if (env->pstate & PSTATE_SS) {
>> -                *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
>> -            }
>> -        } else {
>> -            if (env->uncached_cpsr & PSTATE_SS) {
>> -                *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
>> -            }
>> -        }
>> -    }
>> -    if (arm_cpu_data_is_big_endian(env)) {
>> -        *flags |= ARM_TBFLAG_BE_DATA_MASK;
>> -    }
>> -    *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
>> -
>> -    if (arm_v7m_is_handler_mode(env)) {
>> -        *flags |= ARM_TBFLAG_HANDLER_MASK;
>> -    }
>> -
>> -    *cs_base = 0;
>> -}
>> +void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
>> +                          target_ulong *cs_base, uint32_t *flags);
>>
>>  enum {
>>      QEMU_PSCI_CONDUIT_DISABLED = 0,
>> diff --git a/target/arm/helper.c b/target/arm/helper.c
>> index 984a4b1306..9e673bb672 100644
>> --- a/target/arm/helper.c
>> +++ b/target/arm/helper.c
>> @@ -11701,3 +11701,129 @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
>>      /* Linux crc32c converts the output to one's complement.  */
>>      return crc32c(acc, buf, bytes) ^ 0xffffffff;
>>  }
>> +
>> +/* Return the exception level to which FP-disabled exceptions should
>> + * be taken, or 0 if FP is enabled.
>> + */
>> +static inline int fp_exception_el(CPUARMState *env)
> 
> You can drop the inline here. The compiler knows what to do and we are
> no longer in a header.
> 
>> +{
>> +    int fpen;
>> +    int cur_el = arm_current_el(env);
>> +
>> +    /* CPACR and the CPTR registers don't exist before v6, so FP is
>> +     * always accessible
>> +     */
>> +    if (!arm_feature(env, ARM_FEATURE_V6)) {
>> +        return 0;
>> +    }
>> +
>> +    /* The CPACR controls traps to EL1, or PL1 if we're 32 bit:
>> +     * 0, 2 : trap EL0 and EL1/PL1 accesses
>> +     * 1    : trap only EL0 accesses
>> +     * 3    : trap no accesses
>> +     */
>> +    fpen = extract32(env->cp15.cpacr_el1, 20, 2);
>> +    switch (fpen) {
>> +    case 0:
>> +    case 2:
>> +        if (cur_el == 0 || cur_el == 1) {
>> +            /* Trap to PL1, which might be EL1 or EL3 */
>> +            if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
>> +                return 3;
>> +            }
>> +            return 1;
>> +        }
>> +        if (cur_el == 3 && !is_a64(env)) {
>> +            /* Secure PL1 running at EL3 */
>> +            return 3;
>> +        }
>> +        break;
>> +    case 1:
>> +        if (cur_el == 0) {
>> +            return 1;
>> +        }
>> +        break;
>> +    case 3:
>> +        break;
>> +    }
>> +
>> +    /* For the CPTR registers we don't need to guard with an ARM_FEATURE
>> +     * check because zero bits in the registers mean "don't trap".
>> +     */
>> +
>> +    /* CPTR_EL2 : present in v7VE or v8 */
>> +    if (cur_el <= 2 && extract32(env->cp15.cptr_el[2], 10, 1)
>> +        && !arm_is_secure_below_el3(env)) {
>> +        /* Trap FP ops at EL2, NS-EL1 or NS-EL0 to EL2 */
>> +        return 2;
>> +    }
>> +
>> +    /* CPTR_EL3 : present in v8 */
>> +    if (extract32(env->cp15.cptr_el[3], 10, 1)) {
>> +        /* Trap all FP ops to EL3 */
>> +        return 3;
>> +    }
>> +
>> +    return 0;
>> +}
> 
> I'm not sure helper.c is the best place for this. Maybe cpu.c?

Because sve_exception_el will also be used for protecting access to the SVE
system registers, all of which are defined here in helper.c.


r~

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v2 09/16] target/arm: Add predicate registers for SVE
  2018-01-22 16:07     ` Richard Henderson
@ 2018-01-22 18:35       ` Alex Bennée
  0 siblings, 0 replies; 46+ messages in thread
From: Alex Bennée @ 2018-01-22 18:35 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> On 01/22/2018 04:04 AM, Alex Bennée wrote:
>>
>> Richard Henderson <richard.henderson@linaro.org> writes:
>>
>>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>>> ---
>>>  target/arm/cpu.h | 12 ++++++++++++
>>>  1 file changed, 12 insertions(+)
>>>
>>> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
>>> index 57d805b5d8..132da359b5 100644
>>> --- a/target/arm/cpu.h
>>> +++ b/target/arm/cpu.h
>>> @@ -186,6 +186,15 @@ typedef struct ARMVectorReg {
>>>      uint64_t d[2 * ARM_MAX_VQ] QEMU_ALIGNED(16);
>>>  } ARMVectorReg;
>>>
>>> +/* In AArch32 mode, predicate registers do not exist at all.  */
>>> +typedef struct ARMPredicateReg {
>>> +#ifdef TARGET_AARCH64
>>> +    uint64_t p[2 * ARM_MAX_VQ / 8] QEMU_ALIGNED(16);
>>> +#else
>>> +    uint64_t p[0];
>>> +#endif
>>> +} ARMPredicateReg;
>>> +
>>>
>>>  typedef struct CPUARMState {
>>>      /* Regs for current mode.  */
>>> @@ -513,6 +522,9 @@ typedef struct CPUARMState {
>>>      struct {
>>>          ARMVectorReg zregs[32];
>>>
>>> +        /* Store FFR as pregs[16] to make it easier to treat as any other.  */
>>> +        ARMPredicateReg pregs[17];
>>> +
>>
>> What happens if code tries to accidentally access this on the 32 bit build?
>
> *shrug* About what you'd expect.  What do you suggest?  Ifdeffery?

I think so. I'd prefer a straight compile failure to some subtle
run-time corruption. That is of course assuming the #ifdef magic doesn't
make the aarch32 support for aarch64-softmmu harder. I wouldn't say it
is a hill I want to die on ;-)

--
Alex Bennée

^ permalink raw reply	[flat|nested] 46+ messages in thread

end of thread, other threads:[~2018-01-22 18:36 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-19  4:54 [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE Richard Henderson
2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 01/16] target/arm: Mark disas_set_insn_syndrome inline Richard Henderson
2018-01-19 13:54   ` Alex Bennée
2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 02/16] target/arm: Use pointers in crypto helpers Richard Henderson
2018-01-22 10:09   ` Alex Bennée
2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 03/16] target/arm: Use pointers in neon zip/uzp helpers Richard Henderson
2018-01-22 10:44   ` Alex Bennée
2018-01-22 10:44   ` Alex Bennée
2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 04/16] target/arm: Use pointers in neon tbl helper Richard Henderson
2018-01-22 10:52   ` Alex Bennée
2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 05/16] target/arm: Change the type of vfp.regs Richard Henderson
2018-01-22 10:56   ` Alex Bennée
2018-01-22 16:03     ` Richard Henderson
2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 06/16] target/arm: Add aa{32, 64}_vfp_{dreg, qreg} helpers Richard Henderson
2018-01-22 11:02   ` Alex Bennée
2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 07/16] vmstate: Add VMSTATE_UINT64_SUB_ARRAY Richard Henderson
2018-01-22 11:02   ` Alex Bennée
2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 08/16] target/arm: Expand vector registers for SVE Richard Henderson
2018-01-22 11:08   ` Alex Bennée
2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 09/16] target/arm: Add predicate " Richard Henderson
2018-01-22 12:04   ` Alex Bennée
2018-01-22 16:07     ` Richard Henderson
2018-01-22 18:35       ` Alex Bennée
2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 10/16] target/arm: Add ARM_FEATURE_SVE Richard Henderson
2018-01-22 12:05   ` Alex Bennée
2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 11/16] target/arm: Add SVE to migration state Richard Henderson
2018-01-22 13:40   ` Alex Bennée
2018-01-22 16:11     ` Richard Henderson
2018-01-22 14:16   ` Peter Maydell
2018-01-22 16:10     ` Richard Henderson
2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 12/16] target/arm: Add ZCR_ELx Richard Henderson
2018-01-22 14:38   ` Peter Maydell
2018-01-22 15:00   ` Alex Bennée
2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 13/16] target/arm: Move cpu_get_tb_cpu_state out of line Richard Henderson
2018-01-22 15:07   ` Alex Bennée
2018-01-22 16:18     ` Richard Henderson
2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 14/16] target/arm: Hoist store to flags output in cpu_get_tb_cpu_state Richard Henderson
2018-01-22 15:09   ` Alex Bennée
2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 15/16] target/arm: Simplify fp_exception_el for user-only Richard Henderson
2018-01-22 15:10   ` Alex Bennée
2018-01-19  4:54 ` [Qemu-devel] [PATCH v2 16/16] target/arm: Add SVE state to TB->FLAGS Richard Henderson
2018-01-22 14:40   ` Peter Maydell
2018-01-19  5:29 ` [Qemu-devel] [PATCH v2 00/16] target/arm: Prepatory work for SVE no-reply
2018-01-22 14:12 ` Peter Maydell
2018-01-22 15:12   ` Alex Bennée
2018-01-22 15:12 ` Alex Bennée

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.