[PATCH] RISC-V: T-HEAD: Fix wrong instruction encoding for th.vsetvl

Nelson Chu nelson@rivosinc.com
Fri Dec 29 00:57:53 GMT 2023


On Mon, Dec 18, 2023 at 5:29 PM Jin Ma <jinma@linux.alibaba.com> wrote:

> Since the particularity of "vsetvl" was not taken into account in the
> initial support patches for XTheadVector, the program operation failed
> due to instruction coding errors. According to T-Head SPEC ([1]), the
> "vsetvl" in the XTheadVector extension consists of SEW, LMUL and EDIV,
> which is quite different from the "V" extension. Therefore, we cannot
> simply reuse the processing of vsetvl in V extension.
>
> We have set up tens of thousands of test cases to ensure that no
> further encoding issues are there, and and execute all compiled test
> files on real HW and make sure they don't trigger SIGILL.
>
> Ref:
> [1]
> https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.3.0/xthead-2023-11-10-2.3.0.pdf
>
> Co-developed-by: Lifang Xia <lifang_xia@linux.alibaba.com>
> Co-developed-by: Christoph Müllner <christoph.muellner@vrull.eu>
>
> gas/ChangeLog:
>
>         * config/tc-riscv.c (my_getVsetvliExpression): Add handling for
>         the XTheadVector extension.
>         * testsuite/gas/riscv/x-thead-vector.d: Change test.
>         * testsuite/gas/riscv/x-thead-vector.s: Likewise.
>
> include/ChangeLog:
>
>         * opcode/riscv.h (OP_MASK_XTHEADVLMUL): New macro.
>         (OP_SH_XTHEADVLMUL): Likewise.
>         (OP_MASK_XTHEADVSEW): Likewise.
>         (OP_SH_XTHEADVSEW): Likewise.
>         (OP_MASK_XTHEADVEDIV): Likewise.
>         (OP_SH_XTHEADVEDIV): Likewise.
>         (OP_MASK_XTHEADVTYPE_RES): Likewise.
>         (OP_SH_XTHEADVTYPE_RES): Likewise.
>
> opcodes/ChangeLog:
>
>         * riscv-dis.c (print_insn_args): Likewise.
>         * riscv-opc.c: Likewise.
> ---
>  gas/config/tc-riscv.c                    | 49 ++++++++++++++++++++++++
>  gas/testsuite/gas/riscv/x-thead-vector.d |  3 +-
>  gas/testsuite/gas/riscv/x-thead-vector.s |  1 +
>  include/opcode/riscv.h                   | 11 ++++++
>  opcodes/riscv-dis.c                      | 20 ++++++++++
>  opcodes/riscv-opc.c                      | 12 ++++++
>  6 files changed, 95 insertions(+), 1 deletion(-)
>
> diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
> index b902c6ba2c1..eb6e5260016 100644
> --- a/gas/config/tc-riscv.c
> +++ b/gas/config/tc-riscv.c
> @@ -2371,8 +2371,57 @@ my_getVsetvliExpression (expressionS *ep, char *str)
>  {
>    unsigned int vsew_value = 0, vlmul_value = 0;
>    unsigned int vta_value = 0, vma_value = 0;
> +  unsigned int vlen_value = 0, vediv_value = 0; /* XTheadVector.  */
>    bfd_boolean vsew_found = FALSE, vlmul_found = FALSE;
>    bfd_boolean vta_found = FALSE, vma_found = FALSE;
> +  bfd_boolean vlen_found = FALSE, vediv_found = FALSE; /* XTheadVector.
> */
> +
> +  /* Vsetvl has a different expression for XTheadVector.  */
> +  if (riscv_subset_supports (&riscv_rps_as, "xtheadvector"))
> +    {
> +      if (arg_lookup (&str, riscv_vsew, ARRAY_SIZE (riscv_vsew),
> +                     &vsew_value))
> +       {
> +         if (*str == ',')
> +           ++str;
> +         if (vsew_found)
> +           as_bad (_("multiple vsew constants"));
> +         vsew_found = TRUE;
> +       }
> +
> +      if (arg_lookup (&str, riscv_vlen, ARRAY_SIZE (riscv_vlen),
> +                     &vlen_value))
> +       {
> +         if (*str == ',')
> +           ++str;
> +         if (vlen_found)
> +           as_bad (_("multiple vlen constants"));
> +         vlen_found = TRUE;
> +       }
> +      if (arg_lookup (&str, riscv_vediv, ARRAY_SIZE (riscv_vediv),
> +                     &vediv_value))
> +       {
> +         if (*str == ',')
> +           ++str;
> +         if (vediv_found)
> +           as_bad (_("multiple vediv constants"));
> +         vediv_found = TRUE;
> +       }
> +
> +      if (vlen_found || vediv_found || vsew_found)
> +       {
> +         ep->X_op = O_constant;
> +         ep->X_add_number
> +           = (vediv_value << 5) | (vsew_value << 2) | (vlen_value);
> +         expr_parse_end = str;
> +       }
> +      else
> +       {
> +         my_getExpression (ep, str);
> +         str = expr_parse_end;
> +       }
> +      return;
> +    }
>

Maybe we should have new vendor operands to do this?


>    if (arg_lookup (&str, riscv_vsew, ARRAY_SIZE (riscv_vsew), &vsew_value))
>      {
> diff --git a/gas/testsuite/gas/riscv/x-thead-vector.d
> b/gas/testsuite/gas/riscv/x-thead-vector.d
> index 014c2fdb80d..17b30dd1064 100644
> --- a/gas/testsuite/gas/riscv/x-thead-vector.d
> +++ b/gas/testsuite/gas/riscv/x-thead-vector.d
> @@ -8,8 +8,9 @@ Disassembly of section .text:
>
>  0+000 <.text>:
>  [      ]+[0-9a-f]+:[   ]+80c5f557[     ]+th.vsetvl[    ]+a0,a1,a2
> -[      ]+[0-9a-f]+:[   ]+0005f557[     ]+th.vsetvli[   ]+a0,a1,e8,m1,tu,mu
> +[      ]+[0-9a-f]+:[   ]+0005f557[     ]+th.vsetvli[   ]+a0,a1,e8,m1,d1
>  [      ]+[0-9a-f]+:[   ]+7ff5f557[     ]+th.vsetvli[   ]+a0,a1,2047
> +[      ]+[0-9a-f]+:[   ]+0455f557[     ]+th.vsetvli[   ]+a0,a1,e16,m2,d4
>  [      ]+[0-9a-f]+:[   ]+12050207[     ]+th.vlb.v[     ]+v4,\(a0\)
>  [      ]+[0-9a-f]+:[   ]+12050207[     ]+th.vlb.v[     ]+v4,\(a0\)
>  [      ]+[0-9a-f]+:[   ]+10050207[     ]+th.vlb.v[     ]+v4,\(a0\),v0.t
> diff --git a/gas/testsuite/gas/riscv/x-thead-vector.s
> b/gas/testsuite/gas/riscv/x-thead-vector.s
> index 3a4dea38c8b..43c63a45735 100644
> --- a/gas/testsuite/gas/riscv/x-thead-vector.s
> +++ b/gas/testsuite/gas/riscv/x-thead-vector.s
> @@ -1,6 +1,7 @@
>         th.vsetvl a0, a1, a2
>         th.vsetvli a0, a1, 0
>         th.vsetvli a0, a1, 0x7ff
> +       th.vsetvli a0, a1, e16,m2,d4
>
>         th.vlb.v v4, (a0)
>         th.vlb.v v4, 0(a0)
> diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
> index 6687b434074..179d122a83c 100644
> --- a/include/opcode/riscv.h
> +++ b/include/opcode/riscv.h
> @@ -328,6 +328,15 @@ static inline unsigned int riscv_insn_length (insn_t
> insn)
>  #define OP_MASK_VWD            0x1
>  #define OP_SH_VWD              26
>
> +#define OP_MASK_XTHEADVLMUL    0x3
> +#define OP_SH_XTHEADVLMUL      0
> +#define OP_MASK_XTHEADVSEW     0x7
> +#define OP_SH_XTHEADVSEW       2
> +#define OP_MASK_XTHEADVEDIV    0x3
> +#define OP_SH_XTHEADVEDIV      5
> +#define OP_MASK_XTHEADVTYPE_RES        0xf
> +#define OP_SH_XTHEADVTYPE_RES  7
> +
>  #define NVECR 32
>  #define NVECM 1
>
> @@ -595,6 +604,8 @@ extern const char * const riscv_vsew[8];
>  extern const char * const riscv_vlmul[8];
>  extern const char * const riscv_vta[2];
>  extern const char * const riscv_vma[2];
> +extern const char * const riscv_vlen[4];
> +extern const char * const riscv_vediv[4];
>  extern const char * const riscv_fli_symval[32];
>  extern const float riscv_fli_numval[32];
>
> diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
> index 68674380797..ef01cb4af27 100644
> --- a/opcodes/riscv-dis.c
> +++ b/opcodes/riscv-dis.c
> @@ -367,6 +367,26 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma
> pc, disassemble_info *info
>               {
>                 int imm = (*oparg == 'b') ? EXTRACT_RVV_VB_IMM (l)
>                                           : EXTRACT_RVV_VC_IMM (l);
> +
> +               if (riscv_subset_supports (&riscv_rps_dis, "xtheadvector"))
> +                 {
> +                   unsigned int imm_vediv = EXTRACT_OPERAND (XTHEADVEDIV,
> imm);
> +                   unsigned int imm_vlmul = EXTRACT_OPERAND (XTHEADVLMUL,
> imm);
> +                   unsigned int imm_vsew = EXTRACT_OPERAND (XTHEADVSEW,
> imm);
> +                   unsigned int imm_vtype_res
> +                     = EXTRACT_OPERAND (XTHEADVTYPE_RES, imm);
> +                   if (imm_vsew < ARRAY_SIZE (riscv_vsew)
> +                       && imm_vlmul < ARRAY_SIZE (riscv_vlen)
> +                       && imm_vediv < ARRAY_SIZE (riscv_vediv)
> +                       && ! imm_vtype_res)
> +                     print (info->stream, dis_style_text, "%s,%s,%s",
> +                            riscv_vsew[imm_vsew], riscv_vlen[imm_vlmul],
> +                            riscv_vediv[imm_vediv]);
> +                   else
> +                     print (info->stream, dis_style_immediate, "%d", imm);
> +                   break;
> +                 }
> +
>                 unsigned int imm_vlmul = EXTRACT_OPERAND (VLMUL, imm);
>                 unsigned int imm_vsew = EXTRACT_OPERAND (VSEW, imm);
>                 unsigned int imm_vta = EXTRACT_OPERAND (VTA, imm);
> diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
> index bf388cdaa2f..d5619ddbc41 100644
> --- a/opcodes/riscv-opc.c
> +++ b/opcodes/riscv-opc.c
> @@ -110,6 +110,18 @@ const char * const riscv_vma[2] =
>    "mu", "ma"
>  };
>
> +/* XTheadVector, List of vsetvli vlmul constants.  */
> +const char * const riscv_vlen[4] =
> +{
> +    "m1", "m2", "m4", "m8"
> +};
> +
> +/* XTheadVector, List of vsetvli vediv constants.  */
> +const char * const riscv_vediv[4] =
> +{
> +    "d1", "d2", "d4", "d8"
> +};
> +
>  /* The FLI.[HSDQ] symbolic constants (NULL for numeric constant).  */
>  const char * const riscv_fli_symval[32] =
>  {
>
> base-commit: c4fb39bb31a53bbb2df3be3200d694f025c5b892
> --
> 2.17.1
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://sourceware.org/pipermail/binutils/attachments/20231229/e386b6d8/attachment-0001.htm>


More information about the Binutils mailing list