[v2,02/67] target/arm: Introduce translate-a64.h

Message ID 20180217182323.25885-3-richard.henderson@linaro.org
State Superseded
Headers show
Series
  • target/arm: Scalable Vector Extension
Related show

Commit Message

Richard Henderson Feb. 17, 2018, 6:22 p.m.
Move some stuff that will be common to both translate-a64.c
and translate-sve.c.

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

---
 target/arm/translate-a64.h | 110 +++++++++++++++++++++++++++++++++++++++++++++
 target/arm/translate-a64.c | 101 ++++++-----------------------------------
 2 files changed, 123 insertions(+), 88 deletions(-)
 create mode 100644 target/arm/translate-a64.h

-- 
2.14.3

Comments

Peter Maydell Feb. 22, 2018, 5:30 p.m. | #1
On 17 February 2018 at 18:22, Richard Henderson
<richard.henderson@linaro.org> wrote:
> Move some stuff that will be common to both translate-a64.c

> and translate-sve.c.

>

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

> ---


Reviewed-by: Peter Maydell <peter.maydell@linaro.org>


thanks
-- PMM
Alex Bennée April 3, 2018, 9:01 a.m. | #2
Richard Henderson <richard.henderson@linaro.org> writes:

> Move some stuff that will be common to both translate-a64.c

> and translate-sve.c.

>

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


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


> ---

>  target/arm/translate-a64.h | 110 +++++++++++++++++++++++++++++++++++++++++++++

>  target/arm/translate-a64.c | 101 ++++++-----------------------------------

>  2 files changed, 123 insertions(+), 88 deletions(-)

>  create mode 100644 target/arm/translate-a64.h

>

> diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h

> new file mode 100644

> index 0000000000..e519aee314

> --- /dev/null

> +++ b/target/arm/translate-a64.h

> @@ -0,0 +1,110 @@

> +/*

> + *  AArch64 translation, common definitions.

> + *

> + * This library is free software; you can redistribute it and/or

> + * modify it under the terms of the GNU Lesser General Public

> + * License as published by the Free Software Foundation; either

> + * version 2 of the License, or (at your option) any later version.

> + *

> + * This library is distributed in the hope that it will be useful,

> + * but WITHOUT ANY WARRANTY; without even the implied warranty of

> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU

> + * Lesser General Public License for more details.

> + *

> + * You should have received a copy of the GNU Lesser General Public

> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.

> + */

> +

> +#ifndef TARGET_ARM_TRANSLATE_A64_H

> +#define TARGET_ARM_TRANSLATE_A64_H

> +

> +void unallocated_encoding(DisasContext *s);

> +

> +#define unsupported_encoding(s, insn)                                    \

> +    do {                                                                 \

> +        qemu_log_mask(LOG_UNIMP,                                         \

> +                      "%s:%d: unsupported instruction encoding 0x%08x "  \

> +                      "at pc=%016" PRIx64 "\n",                          \

> +                      __FILE__, __LINE__, insn, s->pc - 4);              \

> +        unallocated_encoding(s);                                         \

> +    } while (0)

> +

> +TCGv_i64 new_tmp_a64(DisasContext *s);

> +TCGv_i64 new_tmp_a64_zero(DisasContext *s);

> +TCGv_i64 cpu_reg(DisasContext *s, int reg);

> +TCGv_i64 cpu_reg_sp(DisasContext *s, int reg);

> +TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf);

> +TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf);

> +void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v);

> +TCGv_ptr get_fpstatus_ptr(bool);

> +bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,

> +                            unsigned int imms, unsigned int immr);

> +uint64_t vfp_expand_imm(int size, uint8_t imm8);

> +

> +/* We should have at some point before trying to access an FP register

> + * done the necessary access check, so assert that

> + * (a) we did the check and

> + * (b) we didn't then just plough ahead anyway if it failed.

> + * Print the instruction pattern in the abort message so we can figure

> + * out what we need to fix if a user encounters this problem in the wild.

> + */

> +static inline void assert_fp_access_checked(DisasContext *s)

> +{

> +#ifdef CONFIG_DEBUG_TCG

> +    if (unlikely(!s->fp_access_checked || s->fp_excp_el)) {

> +        fprintf(stderr, "target-arm: FP access check missing for "

> +                "instruction 0x%08x\n", s->insn);

> +        abort();

> +    }

> +#endif

> +}

> +

> +/* Return the offset into CPUARMState of an element of specified

> + * size, 'element' places in from the least significant end of

> + * the FP/vector register Qn.

> + */

> +static inline int vec_reg_offset(DisasContext *s, int regno,

> +                                 int element, TCGMemOp size)

> +{

> +    int offs = 0;

> +#ifdef HOST_WORDS_BIGENDIAN

> +    /* 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.

> +     */

> +    offs += (16 - ((element + 1) * (1 << size)));

> +    offs ^= 8;

> +#else

> +    offs += element * (1 << size);

> +#endif

> +    offs += offsetof(CPUARMState, vfp.zregs[regno]);

> +    assert_fp_access_checked(s);

> +    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.zregs[regno]);

> +}

> +

> +/* Return a newly allocated pointer to the vector register.  */

> +static inline 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 byte size of the "whole" vector register, VL / 8.  */

> +static inline int vec_full_reg_size(DisasContext *s)

> +{

> +    return s->sve_len;

> +}

> +

> +bool disas_sve(DisasContext *, uint32_t);

> +

> +#endif /* TARGET_ARM_TRANSLATE_A64_H */

> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c

> index 032cbfa17d..e0e7ebf68c 100644

> --- a/target/arm/translate-a64.c

> +++ b/target/arm/translate-a64.c

> @@ -36,13 +36,13 @@

>  #include "exec/log.h"

>

>  #include "trace-tcg.h"

> +#include "translate-a64.h"

>

>  static TCGv_i64 cpu_X[32];

>  static TCGv_i64 cpu_pc;

>

>  /* Load/store exclusive handling */

>  static TCGv_i64 cpu_exclusive_high;

> -static TCGv_i64 cpu_reg(DisasContext *s, int reg);

>

>  static const char *regnames[] = {

>      "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",

> @@ -392,22 +392,13 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)

>      }

>  }

>

> -static void unallocated_encoding(DisasContext *s)

> +void unallocated_encoding(DisasContext *s)

>  {

>      /* Unallocated and reserved encodings are uncategorized */

>      gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),

>                         default_exception_el(s));

>  }

>

> -#define unsupported_encoding(s, insn)                                    \

> -    do {                                                                 \

> -        qemu_log_mask(LOG_UNIMP,                                         \

> -                      "%s:%d: unsupported instruction encoding 0x%08x "  \

> -                      "at pc=%016" PRIx64 "\n",                          \

> -                      __FILE__, __LINE__, insn, s->pc - 4);              \

> -        unallocated_encoding(s);                                         \

> -    } while (0)

> -

>  static void init_tmp_a64_array(DisasContext *s)

>  {

>  #ifdef CONFIG_DEBUG_TCG

> @@ -425,13 +416,13 @@ static void free_tmp_a64(DisasContext *s)

>      init_tmp_a64_array(s);

>  }

>

> -static TCGv_i64 new_tmp_a64(DisasContext *s)

> +TCGv_i64 new_tmp_a64(DisasContext *s)

>  {

>      assert(s->tmp_a64_count < TMP_A64_MAX);

>      return s->tmp_a64[s->tmp_a64_count++] = tcg_temp_new_i64();

>  }

>

> -static TCGv_i64 new_tmp_a64_zero(DisasContext *s)

> +TCGv_i64 new_tmp_a64_zero(DisasContext *s)

>  {

>      TCGv_i64 t = new_tmp_a64(s);

>      tcg_gen_movi_i64(t, 0);

> @@ -453,7 +444,7 @@ static TCGv_i64 new_tmp_a64_zero(DisasContext *s)

>   * to cpu_X[31] and ZR accesses to a temporary which can be discarded.

>   * This is the point of the _sp forms.

>   */

> -static TCGv_i64 cpu_reg(DisasContext *s, int reg)

> +TCGv_i64 cpu_reg(DisasContext *s, int reg)

>  {

>      if (reg == 31) {

>          return new_tmp_a64_zero(s);

> @@ -463,7 +454,7 @@ static TCGv_i64 cpu_reg(DisasContext *s, int reg)

>  }

>

>  /* register access for when 31 == SP */

> -static TCGv_i64 cpu_reg_sp(DisasContext *s, int reg)

> +TCGv_i64 cpu_reg_sp(DisasContext *s, int reg)

>  {

>      return cpu_X[reg];

>  }

> @@ -472,7 +463,7 @@ static TCGv_i64 cpu_reg_sp(DisasContext *s, int reg)

>   * representing the register contents. This TCGv is an auto-freed

>   * temporary so it need not be explicitly freed, and may be modified.

>   */

> -static TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)

> +TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)

>  {

>      TCGv_i64 v = new_tmp_a64(s);

>      if (reg != 31) {

> @@ -487,7 +478,7 @@ static TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)

>      return v;

>  }

>

> -static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)

> +TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)

>  {

>      TCGv_i64 v = new_tmp_a64(s);

>      if (sf) {

> @@ -498,72 +489,6 @@ static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)

>      return v;

>  }

>

> -/* We should have at some point before trying to access an FP register

> - * done the necessary access check, so assert that

> - * (a) we did the check and

> - * (b) we didn't then just plough ahead anyway if it failed.

> - * Print the instruction pattern in the abort message so we can figure

> - * out what we need to fix if a user encounters this problem in the wild.

> - */

> -static inline void assert_fp_access_checked(DisasContext *s)

> -{

> -#ifdef CONFIG_DEBUG_TCG

> -    if (unlikely(!s->fp_access_checked || s->fp_excp_el)) {

> -        fprintf(stderr, "target-arm: FP access check missing for "

> -                "instruction 0x%08x\n", s->insn);

> -        abort();

> -    }

> -#endif

> -}

> -

> -/* Return the offset into CPUARMState of an element of specified

> - * size, 'element' places in from the least significant end of

> - * the FP/vector register Qn.

> - */

> -static inline int vec_reg_offset(DisasContext *s, int regno,

> -                                 int element, TCGMemOp size)

> -{

> -    int offs = 0;

> -#ifdef HOST_WORDS_BIGENDIAN

> -    /* 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.

> -     */

> -    offs += (16 - ((element + 1) * (1 << size)));

> -    offs ^= 8;

> -#else

> -    offs += element * (1 << size);

> -#endif

> -    offs += offsetof(CPUARMState, vfp.zregs[regno]);

> -    assert_fp_access_checked(s);

> -    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.zregs[regno]);

> -}

> -

> -/* 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 byte size of the "whole" vector register, VL / 8.  */

> -static inline int vec_full_reg_size(DisasContext *s)

> -{

> -    /* FIXME SVE: We should put the composite ZCR_EL* value into tb->flags.

> -       In the meantime this is just the AdvSIMD length of 128.  */

> -    return 128 / 8;

> -}

> -

>  /* Return the offset into CPUARMState of a slice (from

>   * the least significant end) of FP register Qn (ie

>   * Dn, Sn, Hn or Bn).

> @@ -620,7 +545,7 @@ static void clear_vec_high(DisasContext *s, bool is_q, int rd)

>      }

>  }

>

> -static void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)

> +void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)

>  {

>      unsigned ofs = fp_reg_offset(s, reg, MO_64);

>

> @@ -637,7 +562,7 @@ static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v)

>      tcg_temp_free_i64(tmp);

>  }

>

> -static TCGv_ptr get_fpstatus_ptr(bool is_f16)

> +TCGv_ptr get_fpstatus_ptr(bool is_f16)

>  {

>      TCGv_ptr statusptr = tcg_temp_new_ptr();

>      int offset;

> @@ -3130,8 +3055,8 @@ static inline uint64_t bitmask64(unsigned int length)

>   * value (ie should cause a guest UNDEF exception), and true if they are

>   * valid, in which case the decoded bit pattern is written to result.

>   */

> -static bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,

> -                                   unsigned int imms, unsigned int immr)

> +bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,

> +                            unsigned int imms, unsigned int immr)

>  {

>      uint64_t mask;

>      unsigned e, levels, s, r;

> @@ -5164,7 +5089,7 @@ static void disas_fp_3src(DisasContext *s, uint32_t insn)

>   * the range 01....1xx to 10....0xx, and the most significant 4 bits of

>   * the mantissa; see VFPExpandImm() in the v8 ARM ARM.

>   */

> -static uint64_t vfp_expand_imm(int size, uint8_t imm8)

> +uint64_t vfp_expand_imm(int size, uint8_t imm8)

>  {

>      uint64_t imm;



--
Alex Bennée

Patch

diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
new file mode 100644
index 0000000000..e519aee314
--- /dev/null
+++ b/target/arm/translate-a64.h
@@ -0,0 +1,110 @@ 
+/*
+ *  AArch64 translation, common definitions.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TARGET_ARM_TRANSLATE_A64_H
+#define TARGET_ARM_TRANSLATE_A64_H
+
+void unallocated_encoding(DisasContext *s);
+
+#define unsupported_encoding(s, insn)                                    \
+    do {                                                                 \
+        qemu_log_mask(LOG_UNIMP,                                         \
+                      "%s:%d: unsupported instruction encoding 0x%08x "  \
+                      "at pc=%016" PRIx64 "\n",                          \
+                      __FILE__, __LINE__, insn, s->pc - 4);              \
+        unallocated_encoding(s);                                         \
+    } while (0)
+
+TCGv_i64 new_tmp_a64(DisasContext *s);
+TCGv_i64 new_tmp_a64_zero(DisasContext *s);
+TCGv_i64 cpu_reg(DisasContext *s, int reg);
+TCGv_i64 cpu_reg_sp(DisasContext *s, int reg);
+TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf);
+TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf);
+void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v);
+TCGv_ptr get_fpstatus_ptr(bool);
+bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
+                            unsigned int imms, unsigned int immr);
+uint64_t vfp_expand_imm(int size, uint8_t imm8);
+
+/* We should have at some point before trying to access an FP register
+ * done the necessary access check, so assert that
+ * (a) we did the check and
+ * (b) we didn't then just plough ahead anyway if it failed.
+ * Print the instruction pattern in the abort message so we can figure
+ * out what we need to fix if a user encounters this problem in the wild.
+ */
+static inline void assert_fp_access_checked(DisasContext *s)
+{
+#ifdef CONFIG_DEBUG_TCG
+    if (unlikely(!s->fp_access_checked || s->fp_excp_el)) {
+        fprintf(stderr, "target-arm: FP access check missing for "
+                "instruction 0x%08x\n", s->insn);
+        abort();
+    }
+#endif
+}
+
+/* Return the offset into CPUARMState of an element of specified
+ * size, 'element' places in from the least significant end of
+ * the FP/vector register Qn.
+ */
+static inline int vec_reg_offset(DisasContext *s, int regno,
+                                 int element, TCGMemOp size)
+{
+    int offs = 0;
+#ifdef HOST_WORDS_BIGENDIAN
+    /* 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.
+     */
+    offs += (16 - ((element + 1) * (1 << size)));
+    offs ^= 8;
+#else
+    offs += element * (1 << size);
+#endif
+    offs += offsetof(CPUARMState, vfp.zregs[regno]);
+    assert_fp_access_checked(s);
+    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.zregs[regno]);
+}
+
+/* Return a newly allocated pointer to the vector register.  */
+static inline 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 byte size of the "whole" vector register, VL / 8.  */
+static inline int vec_full_reg_size(DisasContext *s)
+{
+    return s->sve_len;
+}
+
+bool disas_sve(DisasContext *, uint32_t);
+
+#endif /* TARGET_ARM_TRANSLATE_A64_H */
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 032cbfa17d..e0e7ebf68c 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -36,13 +36,13 @@ 
 #include "exec/log.h"
 
 #include "trace-tcg.h"
+#include "translate-a64.h"
 
 static TCGv_i64 cpu_X[32];
 static TCGv_i64 cpu_pc;
 
 /* Load/store exclusive handling */
 static TCGv_i64 cpu_exclusive_high;
-static TCGv_i64 cpu_reg(DisasContext *s, int reg);
 
 static const char *regnames[] = {
     "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
@@ -392,22 +392,13 @@  static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
     }
 }
 
-static void unallocated_encoding(DisasContext *s)
+void unallocated_encoding(DisasContext *s)
 {
     /* Unallocated and reserved encodings are uncategorized */
     gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
                        default_exception_el(s));
 }
 
-#define unsupported_encoding(s, insn)                                    \
-    do {                                                                 \
-        qemu_log_mask(LOG_UNIMP,                                         \
-                      "%s:%d: unsupported instruction encoding 0x%08x "  \
-                      "at pc=%016" PRIx64 "\n",                          \
-                      __FILE__, __LINE__, insn, s->pc - 4);              \
-        unallocated_encoding(s);                                         \
-    } while (0)
-
 static void init_tmp_a64_array(DisasContext *s)
 {
 #ifdef CONFIG_DEBUG_TCG
@@ -425,13 +416,13 @@  static void free_tmp_a64(DisasContext *s)
     init_tmp_a64_array(s);
 }
 
-static TCGv_i64 new_tmp_a64(DisasContext *s)
+TCGv_i64 new_tmp_a64(DisasContext *s)
 {
     assert(s->tmp_a64_count < TMP_A64_MAX);
     return s->tmp_a64[s->tmp_a64_count++] = tcg_temp_new_i64();
 }
 
-static TCGv_i64 new_tmp_a64_zero(DisasContext *s)
+TCGv_i64 new_tmp_a64_zero(DisasContext *s)
 {
     TCGv_i64 t = new_tmp_a64(s);
     tcg_gen_movi_i64(t, 0);
@@ -453,7 +444,7 @@  static TCGv_i64 new_tmp_a64_zero(DisasContext *s)
  * to cpu_X[31] and ZR accesses to a temporary which can be discarded.
  * This is the point of the _sp forms.
  */
-static TCGv_i64 cpu_reg(DisasContext *s, int reg)
+TCGv_i64 cpu_reg(DisasContext *s, int reg)
 {
     if (reg == 31) {
         return new_tmp_a64_zero(s);
@@ -463,7 +454,7 @@  static TCGv_i64 cpu_reg(DisasContext *s, int reg)
 }
 
 /* register access for when 31 == SP */
-static TCGv_i64 cpu_reg_sp(DisasContext *s, int reg)
+TCGv_i64 cpu_reg_sp(DisasContext *s, int reg)
 {
     return cpu_X[reg];
 }
@@ -472,7 +463,7 @@  static TCGv_i64 cpu_reg_sp(DisasContext *s, int reg)
  * representing the register contents. This TCGv is an auto-freed
  * temporary so it need not be explicitly freed, and may be modified.
  */
-static TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)
+TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)
 {
     TCGv_i64 v = new_tmp_a64(s);
     if (reg != 31) {
@@ -487,7 +478,7 @@  static TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)
     return v;
 }
 
-static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
+TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
 {
     TCGv_i64 v = new_tmp_a64(s);
     if (sf) {
@@ -498,72 +489,6 @@  static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
     return v;
 }
 
-/* We should have at some point before trying to access an FP register
- * done the necessary access check, so assert that
- * (a) we did the check and
- * (b) we didn't then just plough ahead anyway if it failed.
- * Print the instruction pattern in the abort message so we can figure
- * out what we need to fix if a user encounters this problem in the wild.
- */
-static inline void assert_fp_access_checked(DisasContext *s)
-{
-#ifdef CONFIG_DEBUG_TCG
-    if (unlikely(!s->fp_access_checked || s->fp_excp_el)) {
-        fprintf(stderr, "target-arm: FP access check missing for "
-                "instruction 0x%08x\n", s->insn);
-        abort();
-    }
-#endif
-}
-
-/* Return the offset into CPUARMState of an element of specified
- * size, 'element' places in from the least significant end of
- * the FP/vector register Qn.
- */
-static inline int vec_reg_offset(DisasContext *s, int regno,
-                                 int element, TCGMemOp size)
-{
-    int offs = 0;
-#ifdef HOST_WORDS_BIGENDIAN
-    /* 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.
-     */
-    offs += (16 - ((element + 1) * (1 << size)));
-    offs ^= 8;
-#else
-    offs += element * (1 << size);
-#endif
-    offs += offsetof(CPUARMState, vfp.zregs[regno]);
-    assert_fp_access_checked(s);
-    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.zregs[regno]);
-}
-
-/* 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 byte size of the "whole" vector register, VL / 8.  */
-static inline int vec_full_reg_size(DisasContext *s)
-{
-    /* FIXME SVE: We should put the composite ZCR_EL* value into tb->flags.
-       In the meantime this is just the AdvSIMD length of 128.  */
-    return 128 / 8;
-}
-
 /* Return the offset into CPUARMState of a slice (from
  * the least significant end) of FP register Qn (ie
  * Dn, Sn, Hn or Bn).
@@ -620,7 +545,7 @@  static void clear_vec_high(DisasContext *s, bool is_q, int rd)
     }
 }
 
-static void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)
+void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)
 {
     unsigned ofs = fp_reg_offset(s, reg, MO_64);
 
@@ -637,7 +562,7 @@  static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v)
     tcg_temp_free_i64(tmp);
 }
 
-static TCGv_ptr get_fpstatus_ptr(bool is_f16)
+TCGv_ptr get_fpstatus_ptr(bool is_f16)
 {
     TCGv_ptr statusptr = tcg_temp_new_ptr();
     int offset;
@@ -3130,8 +3055,8 @@  static inline uint64_t bitmask64(unsigned int length)
  * value (ie should cause a guest UNDEF exception), and true if they are
  * valid, in which case the decoded bit pattern is written to result.
  */
-static bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
-                                   unsigned int imms, unsigned int immr)
+bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
+                            unsigned int imms, unsigned int immr)
 {
     uint64_t mask;
     unsigned e, levels, s, r;
@@ -5164,7 +5089,7 @@  static void disas_fp_3src(DisasContext *s, uint32_t insn)
  * the range 01....1xx to 10....0xx, and the most significant 4 bits of
  * the mantissa; see VFPExpandImm() in the v8 ARM ARM.
  */
-static uint64_t vfp_expand_imm(int size, uint8_t imm8)
+uint64_t vfp_expand_imm(int size, uint8_t imm8)
 {
     uint64_t imm;