All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Alex Bennée" <alex.bennee@linaro.org>
To: Richard Henderson <richard.henderson@linaro.org>
Cc: qemu-devel@nongnu.org, peter.maydell@linaro.org
Subject: Re: [Qemu-devel] [PATCH v11 09/20] tcg: Add generic vector helpers with a scalar operand
Date: Tue, 06 Feb 2018 11:04:05 +0000	[thread overview]
Message-ID: <87po5iwfa2.fsf@linaro.org> (raw)
In-Reply-To: <20180126045742.5487-10-richard.henderson@linaro.org>


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

> Use dup to convert a non-constant scalar to a third vector.
>
> Add addition, multiplication, and logical operations with an immediate.
> Add addition, subtraction, multiplication, and logical operations with
> a non-constant scalar.  Allow for the front-end to build operations in
> which the scalar operand comes first.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

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

> ---
>  accel/tcg/tcg-runtime.h      |  19 +++
>  tcg/tcg-op-gvec.h            |  59 ++++++-
>  accel/tcg/tcg-runtime-gvec.c | 180 +++++++++++++++++++++
>  tcg/tcg-op-gvec.c            | 361 ++++++++++++++++++++++++++++++++++++++++++-
>  4 files changed, 617 insertions(+), 2 deletions(-)
>
> diff --git a/accel/tcg/tcg-runtime.h b/accel/tcg/tcg-runtime.h
> index f224a975e8..2536959a18 100644
> --- a/accel/tcg/tcg-runtime.h
> +++ b/accel/tcg/tcg-runtime.h
> @@ -147,16 +147,31 @@ DEF_HELPER_FLAGS_4(gvec_add16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
>  DEF_HELPER_FLAGS_4(gvec_add32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
>  DEF_HELPER_FLAGS_4(gvec_add64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
>
> +DEF_HELPER_FLAGS_4(gvec_adds8, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
> +DEF_HELPER_FLAGS_4(gvec_adds16, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
> +DEF_HELPER_FLAGS_4(gvec_adds32, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
> +DEF_HELPER_FLAGS_4(gvec_adds64, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
> +
>  DEF_HELPER_FLAGS_4(gvec_sub8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
>  DEF_HELPER_FLAGS_4(gvec_sub16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
>  DEF_HELPER_FLAGS_4(gvec_sub32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
>  DEF_HELPER_FLAGS_4(gvec_sub64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
>
> +DEF_HELPER_FLAGS_4(gvec_subs8, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
> +DEF_HELPER_FLAGS_4(gvec_subs16, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
> +DEF_HELPER_FLAGS_4(gvec_subs32, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
> +DEF_HELPER_FLAGS_4(gvec_subs64, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
> +
>  DEF_HELPER_FLAGS_4(gvec_mul8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
>  DEF_HELPER_FLAGS_4(gvec_mul16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
>  DEF_HELPER_FLAGS_4(gvec_mul32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
>  DEF_HELPER_FLAGS_4(gvec_mul64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
>
> +DEF_HELPER_FLAGS_4(gvec_muls8, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
> +DEF_HELPER_FLAGS_4(gvec_muls16, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
> +DEF_HELPER_FLAGS_4(gvec_muls32, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
> +DEF_HELPER_FLAGS_4(gvec_muls64, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
> +
>  DEF_HELPER_FLAGS_4(gvec_ssadd8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
>  DEF_HELPER_FLAGS_4(gvec_ssadd16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
>  DEF_HELPER_FLAGS_4(gvec_ssadd32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
> @@ -189,6 +204,10 @@ DEF_HELPER_FLAGS_4(gvec_xor, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
>  DEF_HELPER_FLAGS_4(gvec_andc, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
>  DEF_HELPER_FLAGS_4(gvec_orc, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
>
> +DEF_HELPER_FLAGS_4(gvec_ands, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
> +DEF_HELPER_FLAGS_4(gvec_xors, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
> +DEF_HELPER_FLAGS_4(gvec_ors, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
> +
>  DEF_HELPER_FLAGS_3(gvec_shl8i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
>  DEF_HELPER_FLAGS_3(gvec_shl16i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
>  DEF_HELPER_FLAGS_3(gvec_shl32i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
> diff --git a/tcg/tcg-op-gvec.h b/tcg/tcg-op-gvec.h
> index 03ced440c2..ff43a29a0b 100644
> --- a/tcg/tcg-op-gvec.h
> +++ b/tcg/tcg-op-gvec.h
> @@ -35,6 +35,12 @@ void tcg_gen_gvec_2_ool(uint32_t dofs, uint32_t aofs,
>                          uint32_t oprsz, uint32_t maxsz, int32_t data,
>                          gen_helper_gvec_2 *fn);
>
> +/* Similarly, passing an extra data value.  */
> +typedef void gen_helper_gvec_2i(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv_i32);
> +void tcg_gen_gvec_2i_ool(uint32_t dofs, uint32_t aofs, TCGv_i64 c,
> +                         uint32_t oprsz, uint32_t maxsz, int32_t data,
> +                         gen_helper_gvec_2i *fn);
> +
>  /* Similarly, passing an extra pointer (e.g. env or float_status).  */
>  typedef void gen_helper_gvec_2_ptr(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
>  void tcg_gen_gvec_2_ptr(uint32_t dofs, uint32_t aofs,
> @@ -102,8 +108,10 @@ typedef struct {
>      void (*fni4)(TCGv_i32, TCGv_i32, int32_t);
>      /* Expand inline with a host vector type.  */
>      void (*fniv)(unsigned, TCGv_vec, TCGv_vec, int64_t);
> -    /* Expand out-of-line helper w/descriptor.  */
> +    /* Expand out-of-line helper w/descriptor, data in descriptor.  */
>      gen_helper_gvec_2 *fno;
> +    /* Expand out-of-line helper w/descriptor, data as argument.  */
> +    gen_helper_gvec_2i *fnoi;
>      /* The opcode, if any, to which this corresponds.  */
>      TCGOpcode opc;
>      /* The vector element size, if applicable.  */
> @@ -114,6 +122,27 @@ typedef struct {
>      bool load_dest;
>  } GVecGen2i;
>
> +typedef struct {
> +    /* Expand inline as a 64-bit or 32-bit integer.
> +       Only one of these will be non-NULL.  */
> +    void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64);
> +    void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32);
> +    /* Expand inline with a host vector type.  */
> +    void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec);
> +    /* Expand out-of-line helper w/descriptor.  */
> +    gen_helper_gvec_2i *fno;
> +    /* The opcode, if any, to which this corresponds.  */
> +    TCGOpcode opc;
> +    /* The data argument to the out-of-line helper.  */
> +    uint32_t data;
> +    /* The vector element size, if applicable.  */
> +    uint8_t vece;
> +    /* Prefer i64 to v64.  */
> +    bool prefer_i64;
> +    /* Load scalar as 1st source operand.  */
> +    bool scalar_first;
> +} GVecGen2s;
> +
>  typedef struct {
>      /* Expand inline as a 64-bit or 32-bit integer.
>         Only one of these will be non-NULL.  */
> @@ -158,6 +187,8 @@ void tcg_gen_gvec_2(uint32_t dofs, uint32_t aofs,
>                      uint32_t oprsz, uint32_t maxsz, const GVecGen2 *);
>  void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
>                       uint32_t maxsz, int64_t c, const GVecGen2i *);
> +void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
> +                     uint32_t maxsz, TCGv_i64 c, const GVecGen2s *);
>  void tcg_gen_gvec_3(uint32_t dofs, uint32_t aofs, uint32_t bofs,
>                      uint32_t oprsz, uint32_t maxsz, const GVecGen3 *);
>  void tcg_gen_gvec_4(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t cofs,
> @@ -179,6 +210,18 @@ void tcg_gen_gvec_sub(unsigned vece, uint32_t dofs, uint32_t aofs,
>  void tcg_gen_gvec_mul(unsigned vece, uint32_t dofs, uint32_t aofs,
>                        uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
>
> +void tcg_gen_gvec_addi(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       int64_t c, uint32_t oprsz, uint32_t maxsz);
> +void tcg_gen_gvec_muli(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       int64_t c, uint32_t oprsz, uint32_t maxsz);
> +
> +void tcg_gen_gvec_adds(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
> +void tcg_gen_gvec_subs(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
> +void tcg_gen_gvec_muls(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
> +
>  /* Saturated arithmetic.  */
>  void tcg_gen_gvec_ssadd(unsigned vece, uint32_t dofs, uint32_t aofs,
>                          uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
> @@ -200,6 +243,20 @@ void tcg_gen_gvec_andc(unsigned vece, uint32_t dofs, uint32_t aofs,
>  void tcg_gen_gvec_orc(unsigned vece, uint32_t dofs, uint32_t aofs,
>                        uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
>
> +void tcg_gen_gvec_andi(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       int64_t c, uint32_t oprsz, uint32_t maxsz);
> +void tcg_gen_gvec_xori(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       int64_t c, uint32_t oprsz, uint32_t maxsz);
> +void tcg_gen_gvec_ori(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                      int64_t c, uint32_t oprsz, uint32_t maxsz);
> +
> +void tcg_gen_gvec_ands(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
> +void tcg_gen_gvec_xors(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
> +void tcg_gen_gvec_ors(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                      TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
> +
>  void tcg_gen_gvec_dup_mem(unsigned vece, uint32_t dofs, uint32_t aofs,
>                            uint32_t s, uint32_t m);
>  void tcg_gen_gvec_dup_i32(unsigned vece, uint32_t dofs, uint32_t s,
> diff --git a/accel/tcg/tcg-runtime-gvec.c b/accel/tcg/tcg-runtime-gvec.c
> index e6f99babcd..8bf8d63912 100644
> --- a/accel/tcg/tcg-runtime-gvec.c
> +++ b/accel/tcg/tcg-runtime-gvec.c
> @@ -122,6 +122,54 @@ void HELPER(gvec_add64)(void *d, void *a, void *b, uint32_t desc)
>      clear_high(d, oprsz, desc);
>  }
>
> +void HELPER(gvec_adds8)(void *d, void *a, uint64_t b, uint32_t desc)
> +{
> +    intptr_t oprsz = simd_oprsz(desc);
> +    vec8 vecb = (vec8)DUP16(b);
> +    intptr_t i;
> +
> +    for (i = 0; i < oprsz; i += sizeof(vec8)) {
> +        *(vec8 *)(d + i) = *(vec8 *)(a + i) + vecb;
> +    }
> +    clear_high(d, oprsz, desc);
> +}
> +
> +void HELPER(gvec_adds16)(void *d, void *a, uint64_t b, uint32_t desc)
> +{
> +    intptr_t oprsz = simd_oprsz(desc);
> +    vec16 vecb = (vec16)DUP8(b);
> +    intptr_t i;
> +
> +    for (i = 0; i < oprsz; i += sizeof(vec16)) {
> +        *(vec16 *)(d + i) = *(vec16 *)(a + i) + vecb;
> +    }
> +    clear_high(d, oprsz, desc);
> +}
> +
> +void HELPER(gvec_adds32)(void *d, void *a, uint64_t b, uint32_t desc)
> +{
> +    intptr_t oprsz = simd_oprsz(desc);
> +    vec32 vecb = (vec32)DUP4(b);
> +    intptr_t i;
> +
> +    for (i = 0; i < oprsz; i += sizeof(vec32)) {
> +        *(vec32 *)(d + i) = *(vec32 *)(a + i) + vecb;
> +    }
> +    clear_high(d, oprsz, desc);
> +}
> +
> +void HELPER(gvec_adds64)(void *d, void *a, uint64_t b, uint32_t desc)
> +{
> +    intptr_t oprsz = simd_oprsz(desc);
> +    vec64 vecb = (vec64)DUP2(b);
> +    intptr_t i;
> +
> +    for (i = 0; i < oprsz; i += sizeof(vec64)) {
> +        *(vec64 *)(d + i) = *(vec64 *)(a + i) + vecb;
> +    }
> +    clear_high(d, oprsz, desc);
> +}
> +
>  void HELPER(gvec_sub8)(void *d, void *a, void *b, uint32_t desc)
>  {
>      intptr_t oprsz = simd_oprsz(desc);
> @@ -166,6 +214,54 @@ void HELPER(gvec_sub64)(void *d, void *a, void *b, uint32_t desc)
>      clear_high(d, oprsz, desc);
>  }
>
> +void HELPER(gvec_subs8)(void *d, void *a, uint64_t b, uint32_t desc)
> +{
> +    intptr_t oprsz = simd_oprsz(desc);
> +    vec8 vecb = (vec8)DUP16(b);
> +    intptr_t i;
> +
> +    for (i = 0; i < oprsz; i += sizeof(vec8)) {
> +        *(vec8 *)(d + i) = *(vec8 *)(a + i) - vecb;
> +    }
> +    clear_high(d, oprsz, desc);
> +}
> +
> +void HELPER(gvec_subs16)(void *d, void *a, uint64_t b, uint32_t desc)
> +{
> +    intptr_t oprsz = simd_oprsz(desc);
> +    vec16 vecb = (vec16)DUP8(b);
> +    intptr_t i;
> +
> +    for (i = 0; i < oprsz; i += sizeof(vec16)) {
> +        *(vec16 *)(d + i) = *(vec16 *)(a + i) - vecb;
> +    }
> +    clear_high(d, oprsz, desc);
> +}
> +
> +void HELPER(gvec_subs32)(void *d, void *a, uint64_t b, uint32_t desc)
> +{
> +    intptr_t oprsz = simd_oprsz(desc);
> +    vec32 vecb = (vec32)DUP4(b);
> +    intptr_t i;
> +
> +    for (i = 0; i < oprsz; i += sizeof(vec32)) {
> +        *(vec32 *)(d + i) = *(vec32 *)(a + i) - vecb;
> +    }
> +    clear_high(d, oprsz, desc);
> +}
> +
> +void HELPER(gvec_subs64)(void *d, void *a, uint64_t b, uint32_t desc)
> +{
> +    intptr_t oprsz = simd_oprsz(desc);
> +    vec64 vecb = (vec64)DUP2(b);
> +    intptr_t i;
> +
> +    for (i = 0; i < oprsz; i += sizeof(vec64)) {
> +        *(vec64 *)(d + i) = *(vec64 *)(a + i) - vecb;
> +    }
> +    clear_high(d, oprsz, desc);
> +}
> +
>  void HELPER(gvec_mul8)(void *d, void *a, void *b, uint32_t desc)
>  {
>      intptr_t oprsz = simd_oprsz(desc);
> @@ -210,6 +306,54 @@ void HELPER(gvec_mul64)(void *d, void *a, void *b, uint32_t desc)
>      clear_high(d, oprsz, desc);
>  }
>
> +void HELPER(gvec_muls8)(void *d, void *a, uint64_t b, uint32_t desc)
> +{
> +    intptr_t oprsz = simd_oprsz(desc);
> +    vec8 vecb = (vec8)DUP16(b);
> +    intptr_t i;
> +
> +    for (i = 0; i < oprsz; i += sizeof(vec8)) {
> +        *(vec8 *)(d + i) = *(vec8 *)(a + i) * vecb;
> +    }
> +    clear_high(d, oprsz, desc);
> +}
> +
> +void HELPER(gvec_muls16)(void *d, void *a, uint64_t b, uint32_t desc)
> +{
> +    intptr_t oprsz = simd_oprsz(desc);
> +    vec16 vecb = (vec16)DUP8(b);
> +    intptr_t i;
> +
> +    for (i = 0; i < oprsz; i += sizeof(vec16)) {
> +        *(vec16 *)(d + i) = *(vec16 *)(a + i) * vecb;
> +    }
> +    clear_high(d, oprsz, desc);
> +}
> +
> +void HELPER(gvec_muls32)(void *d, void *a, uint64_t b, uint32_t desc)
> +{
> +    intptr_t oprsz = simd_oprsz(desc);
> +    vec32 vecb = (vec32)DUP4(b);
> +    intptr_t i;
> +
> +    for (i = 0; i < oprsz; i += sizeof(vec32)) {
> +        *(vec32 *)(d + i) = *(vec32 *)(a + i) * vecb;
> +    }
> +    clear_high(d, oprsz, desc);
> +}
> +
> +void HELPER(gvec_muls64)(void *d, void *a, uint64_t b, uint32_t desc)
> +{
> +    intptr_t oprsz = simd_oprsz(desc);
> +    vec64 vecb = (vec64)DUP2(b);
> +    intptr_t i;
> +
> +    for (i = 0; i < oprsz; i += sizeof(vec64)) {
> +        *(vec64 *)(d + i) = *(vec64 *)(a + i) * vecb;
> +    }
> +    clear_high(d, oprsz, desc);
> +}
> +
>  void HELPER(gvec_neg8)(void *d, void *a, uint32_t desc)
>  {
>      intptr_t oprsz = simd_oprsz(desc);
> @@ -368,6 +512,42 @@ void HELPER(gvec_orc)(void *d, void *a, void *b, uint32_t desc)
>      clear_high(d, oprsz, desc);
>  }
>
> +void HELPER(gvec_ands)(void *d, void *a, uint64_t b, uint32_t desc)
> +{
> +    intptr_t oprsz = simd_oprsz(desc);
> +    vec64 vecb = (vec64)DUP2(b);
> +    intptr_t i;
> +
> +    for (i = 0; i < oprsz; i += sizeof(vec64)) {
> +        *(vec64 *)(d + i) = *(vec64 *)(a + i) & vecb;
> +    }
> +    clear_high(d, oprsz, desc);
> +}
> +
> +void HELPER(gvec_xors)(void *d, void *a, uint64_t b, uint32_t desc)
> +{
> +    intptr_t oprsz = simd_oprsz(desc);
> +    vec64 vecb = (vec64)DUP2(b);
> +    intptr_t i;
> +
> +    for (i = 0; i < oprsz; i += sizeof(vec64)) {
> +        *(vec64 *)(d + i) = *(vec64 *)(a + i) ^ vecb;
> +    }
> +    clear_high(d, oprsz, desc);
> +}
> +
> +void HELPER(gvec_ors)(void *d, void *a, uint64_t b, uint32_t desc)
> +{
> +    intptr_t oprsz = simd_oprsz(desc);
> +    vec64 vecb = (vec64)DUP2(b);
> +    intptr_t i;
> +
> +    for (i = 0; i < oprsz; i += sizeof(vec64)) {
> +        *(vec64 *)(d + i) = *(vec64 *)(a + i) | vecb;
> +    }
> +    clear_high(d, oprsz, desc);
> +}
> +
>  void HELPER(gvec_shl8i)(void *d, void *a, uint32_t desc)
>  {
>      intptr_t oprsz = simd_oprsz(desc);
> diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c
> index f621422646..082698f87f 100644
> --- a/tcg/tcg-op-gvec.c
> +++ b/tcg/tcg-op-gvec.c
> @@ -103,6 +103,28 @@ void tcg_gen_gvec_2_ool(uint32_t dofs, uint32_t aofs,
>      tcg_temp_free_i32(desc);
>  }
>
> +/* Generate a call to a gvec-style helper with two vector operands
> +   and one scalar operand.  */
> +void tcg_gen_gvec_2i_ool(uint32_t dofs, uint32_t aofs, TCGv_i64 c,
> +                         uint32_t oprsz, uint32_t maxsz, int32_t data,
> +                         gen_helper_gvec_2i *fn)
> +{
> +    TCGv_ptr a0, a1;
> +    TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
> +
> +    a0 = tcg_temp_new_ptr();
> +    a1 = tcg_temp_new_ptr();
> +
> +    tcg_gen_addi_ptr(a0, cpu_env, dofs);
> +    tcg_gen_addi_ptr(a1, cpu_env, aofs);
> +
> +    fn(a0, a1, c, desc);
> +
> +    tcg_temp_free_ptr(a0);
> +    tcg_temp_free_ptr(a1);
> +    tcg_temp_free_i32(desc);
> +}
> +
>  /* Generate a call to a gvec-style helper with three vector operands.  */
>  void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs,
>                          uint32_t oprsz, uint32_t maxsz, int32_t data,
> @@ -554,6 +576,27 @@ static void expand_2i_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
>      tcg_temp_free_i32(t1);
>  }
>
> +static void expand_2s_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
> +                          TCGv_i32 c, bool scalar_first,
> +                          void (*fni)(TCGv_i32, TCGv_i32, TCGv_i32))
> +{
> +    TCGv_i32 t0 = tcg_temp_new_i32();
> +    TCGv_i32 t1 = tcg_temp_new_i32();
> +    uint32_t i;
> +
> +    for (i = 0; i < oprsz; i += 4) {
> +        tcg_gen_ld_i32(t0, cpu_env, aofs + i);
> +        if (scalar_first) {
> +            fni(t1, c, t0);
> +        } else {
> +            fni(t1, t0, c);
> +        }
> +        tcg_gen_st_i32(t1, cpu_env, dofs + i);
> +    }
> +    tcg_temp_free_i32(t0);
> +    tcg_temp_free_i32(t1);
> +}
> +
>  /* Expand OPSZ bytes worth of three-operand operations using i32 elements.  */
>  static void expand_3_i32(uint32_t dofs, uint32_t aofs,
>                           uint32_t bofs, uint32_t oprsz, bool load_dest,
> @@ -637,6 +680,27 @@ static void expand_2i_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
>      tcg_temp_free_i64(t1);
>  }
>
> +static void expand_2s_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
> +                          TCGv_i64 c, bool scalar_first,
> +                          void (*fni)(TCGv_i64, TCGv_i64, TCGv_i64))
> +{
> +    TCGv_i64 t0 = tcg_temp_new_i64();
> +    TCGv_i64 t1 = tcg_temp_new_i64();
> +    uint32_t i;
> +
> +    for (i = 0; i < oprsz; i += 8) {
> +        tcg_gen_ld_i64(t0, cpu_env, aofs + i);
> +        if (scalar_first) {
> +            fni(t1, c, t0);
> +        } else {
> +            fni(t1, t0, c);
> +        }
> +        tcg_gen_st_i64(t1, cpu_env, dofs + i);
> +    }
> +    tcg_temp_free_i64(t0);
> +    tcg_temp_free_i64(t1);
> +}
> +
>  /* Expand OPSZ bytes worth of three-operand operations using i64 elements.  */
>  static void expand_3_i64(uint32_t dofs, uint32_t aofs,
>                           uint32_t bofs, uint32_t oprsz, bool load_dest,
> @@ -724,6 +788,28 @@ static void expand_2i_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
>      tcg_temp_free_vec(t1);
>  }
>
> +static void expand_2s_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                          uint32_t oprsz, uint32_t tysz, TCGType type,
> +                          TCGv_vec c, bool scalar_first,
> +                          void (*fni)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec))
> +{
> +    TCGv_vec t0 = tcg_temp_new_vec(type);
> +    TCGv_vec t1 = tcg_temp_new_vec(type);
> +    uint32_t i;
> +
> +    for (i = 0; i < oprsz; i += tysz) {
> +        tcg_gen_ld_vec(t0, cpu_env, aofs + i);
> +        if (scalar_first) {
> +            fni(vece, t1, c, t0);
> +        } else {
> +            fni(vece, t1, t0, c);
> +        }
> +        tcg_gen_st_vec(t1, cpu_env, dofs + i);
> +    }
> +    tcg_temp_free_vec(t0);
> +    tcg_temp_free_vec(t1);
> +}
> +
>  /* Expand OPSZ bytes worth of three-operand operations using host vectors.  */
>  static void expand_3_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
>                           uint32_t bofs, uint32_t oprsz,
> @@ -827,6 +913,7 @@ void tcg_gen_gvec_2(uint32_t dofs, uint32_t aofs,
>      }
>  }
>
> +/* Expand a vector operation with two vectors and an immediate.  */
>  void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
>                       uint32_t maxsz, int64_t c, const GVecGen2i *g)
>  {
> @@ -866,7 +953,13 @@ void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
>      } else if (g->fni4 && check_size_impl(oprsz, 4)) {
>          expand_2i_i32(dofs, aofs, oprsz, c, g->load_dest, g->fni4);
>      } else {
> -        tcg_gen_gvec_2_ool(dofs, aofs, oprsz, maxsz, c, g->fno);
> +        if (g->fno) {
> +            tcg_gen_gvec_2_ool(dofs, aofs, oprsz, maxsz, c, g->fno);
> +        } else {
> +            TCGv_i64 tcg_c = tcg_const_i64(c);
> +            tcg_gen_gvec_2i_ool(dofs, aofs, tcg_c, oprsz, maxsz, c, g->fnoi);
> +            tcg_temp_free_i64(tcg_c);
> +        }
>          return;
>      }
>
> @@ -876,6 +969,87 @@ void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
>      }
>  }
>
> +/* Expand a vector operation with two vectors and a scalar.  */
> +void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
> +                     uint32_t maxsz, TCGv_i64 c, const GVecGen2s *g)
> +{
> +    TCGType type;
> +
> +    check_size_align(oprsz, maxsz, dofs | aofs);
> +    check_overlap_2(dofs, aofs, maxsz);
> +
> +    type = 0;
> +    if (g->fniv) {
> +        if (TCG_TARGET_HAS_v256 && check_size_impl(oprsz, 32)) {
> +            type = TCG_TYPE_V256;
> +        } else if (TCG_TARGET_HAS_v128 && check_size_impl(oprsz, 16)) {
> +            type = TCG_TYPE_V128;
> +        } else if (TCG_TARGET_HAS_v64 && !g->prefer_i64
> +               && check_size_impl(oprsz, 8)) {
> +            type = TCG_TYPE_V64;
> +        }
> +    }
> +    if (type != 0) {
> +        TCGv_vec t_vec = tcg_temp_new_vec(type);
> +
> +        tcg_gen_dup_i64_vec(g->vece, t_vec, c);
> +
> +        /* Recall that ARM SVE allows vector sizes that are not a power of 2.
> +           Expand with successively smaller host vector sizes.  The intent is
> +           that e.g. oprsz == 80 would be expanded with 2x32 + 1x16.  */
> +        switch (type) {
> +        case TCG_TYPE_V256:
> +            {
> +                uint32_t some = QEMU_ALIGN_DOWN(oprsz, 32);
> +                expand_2s_vec(g->vece, dofs, aofs, some, 32, TCG_TYPE_V256,
> +                              t_vec, g->scalar_first, g->fniv);
> +                if (some == oprsz) {
> +                    break;
> +                }
> +                dofs += some;
> +                aofs += some;
> +                oprsz -= some;
> +                maxsz -= some;
> +            }
> +            /* fallthru */
> +
> +        case TCG_TYPE_V128:
> +            expand_2s_vec(g->vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128,
> +                          t_vec, g->scalar_first, g->fniv);
> +            break;
> +
> +        case TCG_TYPE_V64:
> +            expand_2s_vec(g->vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64,
> +                          t_vec, g->scalar_first, g->fniv);
> +            break;
> +
> +        default:
> +            g_assert_not_reached();
> +        }
> +        tcg_temp_free_vec(t_vec);
> +    } else if (g->fni8 && check_size_impl(oprsz, 8)) {
> +        TCGv_i64 t64 = tcg_temp_new_i64();
> +
> +        gen_dup_i64(g->vece, t64, c);
> +        expand_2s_i64(dofs, aofs, oprsz, t64, g->scalar_first, g->fni8);
> +        tcg_temp_free_i64(t64);
> +    } else if (g->fni4 && check_size_impl(oprsz, 4)) {
> +        TCGv_i32 t32 = tcg_temp_new_i32();
> +
> +        tcg_gen_extrl_i64_i32(t32, c);
> +        gen_dup_i32(g->vece, t32, t32);
> +        expand_2s_i32(dofs, aofs, oprsz, t32, g->scalar_first, g->fni4);
> +        tcg_temp_free_i32(t32);
> +    } else {
> +        tcg_gen_gvec_2i_ool(dofs, aofs, c, oprsz, maxsz, 0, g->fno);
> +        return;
> +    }
> +
> +    if (oprsz < maxsz) {
> +        expand_clr(dofs + oprsz, maxsz - oprsz);
> +    }
> +}
> +
>  /* Expand a vector three-operand operation.  */
>  void tcg_gen_gvec_3(uint32_t dofs, uint32_t aofs, uint32_t bofs,
>                      uint32_t oprsz, uint32_t maxsz, const GVecGen3 *g)
> @@ -1200,6 +1374,76 @@ void tcg_gen_gvec_add(unsigned vece, uint32_t dofs, uint32_t aofs,
>      tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
>  }
>
> +void tcg_gen_gvec_adds(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
> +{
> +    static const GVecGen2s g[4] = {
> +        { .fni8 = tcg_gen_vec_add8_i64,
> +          .fniv = tcg_gen_add_vec,
> +          .fno = gen_helper_gvec_adds8,
> +          .opc = INDEX_op_add_vec,
> +          .vece = MO_8 },
> +        { .fni8 = tcg_gen_vec_add16_i64,
> +          .fniv = tcg_gen_add_vec,
> +          .fno = gen_helper_gvec_adds16,
> +          .opc = INDEX_op_add_vec,
> +          .vece = MO_16 },
> +        { .fni4 = tcg_gen_add_i32,
> +          .fniv = tcg_gen_add_vec,
> +          .fno = gen_helper_gvec_adds32,
> +          .opc = INDEX_op_add_vec,
> +          .vece = MO_32 },
> +        { .fni8 = tcg_gen_add_i64,
> +          .fniv = tcg_gen_add_vec,
> +          .fno = gen_helper_gvec_adds64,
> +          .opc = INDEX_op_add_vec,
> +          .prefer_i64 = TCG_TARGET_REG_BITS == 64,
> +          .vece = MO_64 },
> +    };
> +
> +    tcg_debug_assert(vece <= MO_64);
> +    tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, c, &g[vece]);
> +}
> +
> +void tcg_gen_gvec_addi(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       int64_t c, uint32_t oprsz, uint32_t maxsz)
> +{
> +    TCGv_i64 tmp = tcg_const_i64(c);
> +    tcg_gen_gvec_adds(vece, dofs, aofs, tmp, oprsz, maxsz);
> +    tcg_temp_free_i64(tmp);
> +}
> +
> +void tcg_gen_gvec_subs(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
> +{
> +    static const GVecGen2s g[4] = {
> +        { .fni8 = tcg_gen_vec_sub8_i64,
> +          .fniv = tcg_gen_sub_vec,
> +          .fno = gen_helper_gvec_subs8,
> +          .opc = INDEX_op_sub_vec,
> +          .vece = MO_8 },
> +        { .fni8 = tcg_gen_vec_sub16_i64,
> +          .fniv = tcg_gen_sub_vec,
> +          .fno = gen_helper_gvec_subs16,
> +          .opc = INDEX_op_sub_vec,
> +          .vece = MO_16 },
> +        { .fni4 = tcg_gen_sub_i32,
> +          .fniv = tcg_gen_sub_vec,
> +          .fno = gen_helper_gvec_subs32,
> +          .opc = INDEX_op_sub_vec,
> +          .vece = MO_32 },
> +        { .fni8 = tcg_gen_sub_i64,
> +          .fniv = tcg_gen_sub_vec,
> +          .fno = gen_helper_gvec_subs64,
> +          .opc = INDEX_op_sub_vec,
> +          .prefer_i64 = TCG_TARGET_REG_BITS == 64,
> +          .vece = MO_64 },
> +    };
> +
> +    tcg_debug_assert(vece <= MO_64);
> +    tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, c, &g[vece]);
> +}
> +
>  /* Perform a vector subtraction using normal subtraction and a mask.
>     Compare gen_addv_mask above.  */
>  static void gen_subv_mask(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b, TCGv_i64 m)
> @@ -1308,6 +1552,43 @@ void tcg_gen_gvec_mul(unsigned vece, uint32_t dofs, uint32_t aofs,
>      tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
>  }
>
> +void tcg_gen_gvec_muls(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
> +{
> +    static const GVecGen2s g[4] = {
> +        { .fniv = tcg_gen_mul_vec,
> +          .fno = gen_helper_gvec_muls8,
> +          .opc = INDEX_op_mul_vec,
> +          .vece = MO_8 },
> +        { .fniv = tcg_gen_mul_vec,
> +          .fno = gen_helper_gvec_muls16,
> +          .opc = INDEX_op_mul_vec,
> +          .vece = MO_16 },
> +        { .fni4 = tcg_gen_mul_i32,
> +          .fniv = tcg_gen_mul_vec,
> +          .fno = gen_helper_gvec_muls32,
> +          .opc = INDEX_op_mul_vec,
> +          .vece = MO_32 },
> +        { .fni8 = tcg_gen_mul_i64,
> +          .fniv = tcg_gen_mul_vec,
> +          .fno = gen_helper_gvec_muls64,
> +          .opc = INDEX_op_mul_vec,
> +          .prefer_i64 = TCG_TARGET_REG_BITS == 64,
> +          .vece = MO_64 },
> +    };
> +
> +    tcg_debug_assert(vece <= MO_64);
> +    tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, c, &g[vece]);
> +}
> +
> +void tcg_gen_gvec_muli(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       int64_t c, uint32_t oprsz, uint32_t maxsz)
> +{
> +    TCGv_i64 tmp = tcg_const_i64(c);
> +    tcg_gen_gvec_muls(vece, dofs, aofs, tmp, oprsz, maxsz);
> +    tcg_temp_free_i64(tmp);
> +}
> +
>  void tcg_gen_gvec_ssadd(unsigned vece, uint32_t dofs, uint32_t aofs,
>                          uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
>  {
> @@ -1540,6 +1821,84 @@ void tcg_gen_gvec_orc(unsigned vece, uint32_t dofs, uint32_t aofs,
>      tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g);
>  }
>
> +static const GVecGen2s gop_ands = {
> +    .fni8 = tcg_gen_and_i64,
> +    .fniv = tcg_gen_and_vec,
> +    .fno = gen_helper_gvec_ands,
> +    .opc = INDEX_op_and_vec,
> +    .prefer_i64 = TCG_TARGET_REG_BITS == 64,
> +    .vece = MO_64
> +};
> +
> +void tcg_gen_gvec_ands(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
> +{
> +    TCGv_i64 tmp = tcg_temp_new_i64();
> +    gen_dup_i64(vece, tmp, c);
> +    tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ands);
> +    tcg_temp_free_i64(tmp);
> +}
> +
> +void tcg_gen_gvec_andi(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       int64_t c, uint32_t oprsz, uint32_t maxsz)
> +{
> +    TCGv_i64 tmp = tcg_const_i64(dup_const(vece, c));
> +    tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ands);
> +    tcg_temp_free_i64(tmp);
> +}
> +
> +static const GVecGen2s gop_xors = {
> +    .fni8 = tcg_gen_xor_i64,
> +    .fniv = tcg_gen_xor_vec,
> +    .fno = gen_helper_gvec_xors,
> +    .opc = INDEX_op_xor_vec,
> +    .prefer_i64 = TCG_TARGET_REG_BITS == 64,
> +    .vece = MO_64
> +};
> +
> +void tcg_gen_gvec_xors(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
> +{
> +    TCGv_i64 tmp = tcg_temp_new_i64();
> +    gen_dup_i64(vece, tmp, c);
> +    tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_xors);
> +    tcg_temp_free_i64(tmp);
> +}
> +
> +void tcg_gen_gvec_xori(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                       int64_t c, uint32_t oprsz, uint32_t maxsz)
> +{
> +    TCGv_i64 tmp = tcg_const_i64(dup_const(vece, c));
> +    tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_xors);
> +    tcg_temp_free_i64(tmp);
> +}
> +
> +static const GVecGen2s gop_ors = {
> +    .fni8 = tcg_gen_or_i64,
> +    .fniv = tcg_gen_or_vec,
> +    .fno = gen_helper_gvec_ors,
> +    .opc = INDEX_op_or_vec,
> +    .prefer_i64 = TCG_TARGET_REG_BITS == 64,
> +    .vece = MO_64
> +};
> +
> +void tcg_gen_gvec_ors(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                      TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
> +{
> +    TCGv_i64 tmp = tcg_temp_new_i64();
> +    gen_dup_i64(vece, tmp, c);
> +    tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ors);
> +    tcg_temp_free_i64(tmp);
> +}
> +
> +void tcg_gen_gvec_ori(unsigned vece, uint32_t dofs, uint32_t aofs,
> +                      int64_t c, uint32_t oprsz, uint32_t maxsz)
> +{
> +    TCGv_i64 tmp = tcg_const_i64(dup_const(vece, c));
> +    tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ors);
> +    tcg_temp_free_i64(tmp);
> +}
> +
>  void tcg_gen_vec_shl8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c)
>  {
>      uint64_t mask = dup_const(MO_8, 0xff << c);


--
Alex Bennée

  reply	other threads:[~2018-02-06 11:04 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-01-26  4:57 [Qemu-devel] [PATCH v11 00/20] tcg: generic vector operations Richard Henderson
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 01/20] tcg: Allow multiple word entries into the constant pool Richard Henderson
2018-02-06  8:51   ` Alex Bennée
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 02/20] tcg: Add types and basic operations for host vectors Richard Henderson
2018-02-06  8:53   ` Alex Bennée
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 03/20] tcg: Standardize integral arguments to expanders Richard Henderson
2018-02-06  8:57   ` Alex Bennée
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 04/20] tcg: Add generic vector expanders Richard Henderson
2018-02-06 10:59   ` Alex Bennée
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 05/20] tcg: Add generic vector ops for constant shifts Richard Henderson
2018-02-06 11:00   ` Alex Bennée
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 06/20] tcg: Add generic vector ops for comparisons Richard Henderson
2018-02-06 11:01   ` Alex Bennée
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 07/20] tcg: Add generic vector ops for multiplication Richard Henderson
2018-02-06 11:02   ` Alex Bennée
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 08/20] tcg: Add generic helpers for saturating arithmetic Richard Henderson
2018-02-06 11:03   ` Alex Bennée
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 09/20] tcg: Add generic vector helpers with a scalar operand Richard Henderson
2018-02-06 11:04   ` Alex Bennée [this message]
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 10/20] tcg/optimize: Handle vector opcodes during optimize Richard Henderson
2018-02-06 11:07   ` Alex Bennée
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 11/20] target/arm: Align vector registers Richard Henderson
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 12/20] target/arm: Use vector infrastructure for aa64 add/sub/logic Richard Henderson
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 13/20] target/arm: Use vector infrastructure for aa64 mov/not/neg Richard Henderson
2018-02-06 11:08   ` Alex Bennée
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 14/20] target/arm: Use vector infrastructure for aa64 dup/movi Richard Henderson
2018-02-06 11:09   ` Alex Bennée
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 15/20] target/arm: Use vector infrastructure for aa64 constant shifts Richard Henderson
2018-02-05 11:14   ` Peter Maydell
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 16/20] target/arm: Use vector infrastructure for aa64 compares Richard Henderson
2018-02-06 11:10   ` Alex Bennée
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 17/20] target/arm: Use vector infrastructure for aa64 multiplies Richard Henderson
2018-02-06 11:11   ` Alex Bennée
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 18/20] target/arm: Use vector infrastructure for aa64 orr/bic immediate Richard Henderson
2018-02-06 11:13   ` Alex Bennée
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 19/20] tcg/i386: Add vector operations Richard Henderson
2018-01-26  4:57 ` [Qemu-devel] [PATCH v11 20/20] tcg/aarch64: " Richard Henderson
2018-02-06 11:15   ` Alex Bennée
2018-01-26 17:25 ` [Qemu-devel] [PATCH v11 00/20] tcg: generic " no-reply
2018-02-06 11:24 ` Alex Bennée
2018-02-06 12:07   ` Philippe Mathieu-Daudé
2018-02-06 12:36     ` Alex Bennée
2018-02-06 16:24 ` Alex Bennée
2018-02-06 20:57   ` Alex Bennée

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87po5iwfa2.fsf@linaro.org \
    --to=alex.bennee@linaro.org \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.