[PATCH] RISC-V: Add zilsd & zclsd support

Kito Cheng kito.cheng@gmail.com
Fri May 9 08:23:16 GMT 2025


Ooops, sorry, this version is missing one extra testcase. plz just see v2

On Fri, May 9, 2025 at 4:15 PM Kito Cheng <kito.cheng@sifive.com> wrote:
>
> From: dysun <sundongya@nucleisys.com>
>
> Ref: https://github.com/riscv/riscv-zilsd/blob/main/zilsd.adoc
>
> Signed-off-by: dysun <sundongya@nucleisys.com>
>
> Co-developed-by: LIU Xu <liuxu@nucleisys.com>
> Co-developed-by: ZHAO Fujin <zhaofujin@nucleisys.com>
> ---
>  bfd/elfxx-riscv.c                          | 20 ++++++++
>  gas/testsuite/gas/riscv/march-help.l       |  2 +
>  gas/testsuite/gas/riscv/zilsd-zclsd-fail.d |  3 ++
>  gas/testsuite/gas/riscv/zilsd-zclsd-fail.l | 15 ++++++
>  gas/testsuite/gas/riscv/zilsd-zclsd-fail.s | 15 ++++++
>  gas/testsuite/gas/riscv/zilsd-zclsd.d      | 29 ++++++++++++
>  gas/testsuite/gas/riscv/zilsd-zclsd.s      | 20 ++++++++
>  include/opcode/riscv.h                     |  2 +
>  opcodes/riscv-opc.c                        | 54 ++++++++++++++++++++++
>  9 files changed, 160 insertions(+)
>  create mode 100644 gas/testsuite/gas/riscv/zilsd-zclsd-fail.d
>  create mode 100644 gas/testsuite/gas/riscv/zilsd-zclsd-fail.l
>  create mode 100644 gas/testsuite/gas/riscv/zilsd-zclsd-fail.s
>  create mode 100644 gas/testsuite/gas/riscv/zilsd-zclsd.d
>  create mode 100644 gas/testsuite/gas/riscv/zilsd-zclsd.s
>
> diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
> index 83e237c2a03..7b4d108db52 100644
> --- a/bfd/elfxx-riscv.c
> +++ b/bfd/elfxx-riscv.c
> @@ -1222,6 +1222,7 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
>
>    {"zicfilp", "+zicsr", check_implicit_always},
>    {"zicfiss", "+zimop,+zicsr", check_implicit_always},
> +  {"zclsd", "+zca,+zilsd", check_implicit_always},
>
>    {"sha", "+h,+ssstateen,+shcounterenw,+shvstvala,+shtvala,+shvstvecd,+shvsatpa,+shgatpa", check_implicit_always},
>
> @@ -1365,6 +1366,7 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] =
>    {"zimop",            ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
>    {"zicfiss",          ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
>    {"zicfilp",          ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
> +  {"zilsd",             ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
>    {"zmmul",            ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
>    {"za64rs",           ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
>    {"za128rs",          ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
> @@ -1444,6 +1446,7 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] =
>    {"zcmop",            ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
>    {"zcmp",             ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
>    {"zcmt",             ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
> +  {"zclsd",             ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
>    {NULL, 0, 0, 0, 0}
>  };
>
> @@ -2140,6 +2143,15 @@ riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
>         (_("`xtheadvector' is conflict with the `v' extension"));
>        no_conflict = false;
>      }
> +  if (riscv_lookup_subset (rps->subset_list, "zclsd", &subset)
> +      && ((riscv_lookup_subset (rps->subset_list, "c", &subset)
> +          && riscv_lookup_subset (rps->subset_list, "f", &subset))
> +         || riscv_lookup_subset (rps->subset_list, "zcf", &subset)))
> +    {
> +      rps->error_handler
> +       (_("`zclsd' is conflict with the `c+f'/ `zcf' extension"));
> +      no_conflict = false;
> +    }
>    if (riscv_lookup_subset (rps->subset_list, "ssnpm", &subset) && xlen != 64)
>      {
>        rps->error_handler (_ ("rv%d does not support the `ssnpm' extension"),
> @@ -2808,6 +2820,10 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
>      case INSN_CLASS_SMCTR_OR_SSCTR:
>        return (riscv_subset_supports (rps, "smctr")
>               || riscv_subset_supports (rps, "ssctr"));
> +    case INSN_CLASS_ZILSD:
> +      return riscv_subset_supports (rps, "zilsd");
> +    case INSN_CLASS_ZCLSD:
> +      return riscv_subset_supports (rps, "zclsd");
>      case INSN_CLASS_SMRNMI:
>        return riscv_subset_supports (rps, "smrnmi");
>      case INSN_CLASS_SVINVAL:
> @@ -3125,6 +3141,10 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
>        return "zcmt";
>      case INSN_CLASS_SMCTR_OR_SSCTR:
>        return _("smctr' or `ssctr");
> +    case INSN_CLASS_ZILSD:
> +     return "zilsd";
> +    case INSN_CLASS_ZCLSD:
> +      return "zclsd";
>      case INSN_CLASS_SMRNMI:
>        return "smrnmi";
>      case INSN_CLASS_SVINVAL:
> diff --git a/gas/testsuite/gas/riscv/march-help.l b/gas/testsuite/gas/riscv/march-help.l
> index bcc3a8f1fbd..caf897b22b8 100644
> --- a/gas/testsuite/gas/riscv/march-help.l
> +++ b/gas/testsuite/gas/riscv/march-help.l
> @@ -28,6 +28,7 @@ All available -march extensions for RISC-V:
>         zimop                                   1.0
>         zicfiss                                 1.0
>         zicfilp                                 1.0
> +       zilsd                                   1.0
>         zmmul                                   1.0
>         za64rs                                  1.0
>         za128rs                                 1.0
> @@ -107,6 +108,7 @@ All available -march extensions for RISC-V:
>         zcmop                                   1.0
>         zcmp                                    1.0
>         zcmt                                    1.0
> +       zclsd                                   1.0
>         sha                                     1.0
>         shcounterenw                            1.0
>         shgatpa                                 1.0
> diff --git a/gas/testsuite/gas/riscv/zilsd-zclsd-fail.d b/gas/testsuite/gas/riscv/zilsd-zclsd-fail.d
> new file mode 100644
> index 00000000000..da73c2dd78e
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zilsd-zclsd-fail.d
> @@ -0,0 +1,3 @@
> +#as: -march=rv32ima_zilsd_zclsd
> +#source: zilsd-zclsd-fail.s
> +#error_output: zilsd-zclsd-fail.l
> diff --git a/gas/testsuite/gas/riscv/zilsd-zclsd-fail.l b/gas/testsuite/gas/riscv/zilsd-zclsd-fail.l
> new file mode 100644
> index 00000000000..18e29039c6d
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zilsd-zclsd-fail.l
> @@ -0,0 +1,15 @@
> +.*: Assembler messages:
> +.*: Error: illegal operands `ld x7,\(x5\)'
> +.*: Error: illegal operands `ld x9,8\(x11\)'
> +.*: Error: illegal operands `ld x13,16\(x16\)'
> +.*: Error: illegal operands `sd x7,\(x5\)'
> +.*: Error: illegal operands `sd x9,8\(x11\)'
> +.*: Error: illegal operands `sd x13,16\(x16\)'
> +.*: Error: illegal operands `c.ld x11,\(x9\)'
> +.*: Error: illegal operands `c.ld x13,\(x16\)'
> +.*: Error: illegal operands `c.ldsp x0,\(x2\)'
> +.*: Error: illegal operands `c.ldsp x11,\(x2\)'
> +.*: Error: illegal operands `c.sd x11,\(x9\)'
> +.*: Error: illegal operands `c.sd x13,\(x16\)'
> +.*: Error: illegal operands `c.sdsp x11,\(x2\)'
> +.*: Error: illegal operands `c.sdsp x13,8\(x2\)'
> diff --git a/gas/testsuite/gas/riscv/zilsd-zclsd-fail.s b/gas/testsuite/gas/riscv/zilsd-zclsd-fail.s
> new file mode 100644
> index 00000000000..925cd483592
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zilsd-zclsd-fail.s
> @@ -0,0 +1,15 @@
> +target:
> +    ld x7, (x5)
> +    ld x9, 8(x11)
> +    ld x13, 16(x16)
> +    sd x7, (x5)
> +    sd x9, 8(x11)
> +    sd x13, 16(x16)
> +    c.ld x11, (x9)
> +    c.ld x13, (x16)
> +    c.ldsp x0, (x2)
> +    c.ldsp x11, (x2)
> +    c.sd x11, (x9)
> +    c.sd x13, (x16)
> +    c.sdsp x11, (x2)
> +    c.sdsp x13, 8(x2)
> diff --git a/gas/testsuite/gas/riscv/zilsd-zclsd.d b/gas/testsuite/gas/riscv/zilsd-zclsd.d
> new file mode 100644
> index 00000000000..816371c52ec
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zilsd-zclsd.d
> @@ -0,0 +1,29 @@
> +#as: -march=rv32ima_zilsd_zclsd
> +#source: zilsd-zclsd.s
> +#objdump: -d -Mno-aliases
> +
> +.*:[   ]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+000 <target>:
> +[      ]+0:[   ]+0007b303[     ]+ld[   ]+t1,0\(a5\)
> +[      ]+4:[   ]+00883903[     ]+ld[   ]+s2,8\(a6\)
> +[      ]+8:[   ]+0105ba03[     ]+ld[   ]+s4,16\(a1\)
> +[      ]+c:[   ]+0067b023[     ]+sd[   ]+t1,0\(a5\)
> +[      ]+10:[  ]+01283423[     ]+sd[   ]+s2,8\(a6\)
> +[      ]+14:[  ]+0145b823[     ]+sd[   ]+s4,16\(a1\)
> +[      ]+18:[  ]+6380[         ]+c.ld[         ]+s0,0\(a5\)
> +[      ]+1a:[  ]+6408[         ]+c.ld[         ]+a0,8\(s0\)
> +[      ]+1c:[  ]+6a90[         ]+c.ld[         ]+a2,16\(a3\)
> +[      ]+1e:[  ]+e380[         ]+c.sd[         ]+s0,0\(a5\)
> +[      ]+20:[  ]+e408[         ]+c.sd[         ]+a0,8\(s0\)
> +[      ]+22:[  ]+ea90[         ]+c.sd[         ]+a2,16\(a3\)
> +[      ]+24:[  ]+6122[         ]+c.ldsp[       ]+sp,8\(sp\)
> +[      ]+26:[  ]+652a[         ]+c.ldsp[       ]+a0,136\(sp\)
> +[      ]+28:[  ]+7f7e[         ]+c.ldsp[       ]+t5,504\(sp\)
> +[      ]+2a:[  ]+e002[         ]+c.sdsp[       ]+zero,0\(sp\)
> +[      ]+2c:[  ]+e40a[         ]+c.sdsp[       ]+sp,8\(sp\)
> +[      ]+2e:[  ]+e52a[         ]+c.sdsp[       ]+a0,136\(sp\)
> +[      ]+30:[  ]+fffa[         ]+c.sdsp[       ]+t5,504\(sp\)
> diff --git a/gas/testsuite/gas/riscv/zilsd-zclsd.s b/gas/testsuite/gas/riscv/zilsd-zclsd.s
> new file mode 100644
> index 00000000000..28d83ed860d
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zilsd-zclsd.s
> @@ -0,0 +1,20 @@
> +target:
> +    ld x6, (x15)
> +    ld x18, 8(x16)
> +    ld x20, 16(x11)
> +    sd x6, (x15)
> +    sd x18, 8(x16)
> +    sd x20, 16(x11)
> +    c.ld x8, (x15)
> +    c.ld x10, 8(x8)
> +    c.ld x12, 16(x13)
> +    c.sd x8, (x15)
> +    c.sd x10, 8(x8)
> +    c.sd x12, 16(x13)
> +    c.ldsp x2, 8(sp)
> +    c.ldsp x10, 136(sp)
> +    c.ldsp x30, 504(sp)
> +    c.sdsp x0, (sp)
> +    c.sdsp x2, 8(sp)
> +    c.sdsp x10, 136(sp)
> +    c.sdsp x30, 504(sp)
> diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
> index c5dd546aac5..7fca806b643 100644
> --- a/include/opcode/riscv.h
> +++ b/include/opcode/riscv.h
> @@ -562,6 +562,8 @@ enum riscv_insn_class
>    INSN_CLASS_ZCMP,
>    INSN_CLASS_ZCMT,
>    INSN_CLASS_SMCTR_OR_SSCTR,
> +  INSN_CLASS_ZILSD,
> +  INSN_CLASS_ZCLSD,
>    INSN_CLASS_SMRNMI,
>    INSN_CLASS_SVINVAL,
>    INSN_CLASS_ZICBOM,
> diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
> index 340d1255e18..78ff561dfb6 100644
> --- a/opcodes/riscv-opc.c
> +++ b/opcodes/riscv-opc.c
> @@ -161,6 +161,7 @@ riscv_get_sp_base (insn_t opcode, unsigned int xlen)
>  #define MASK_RS2 (OP_MASK_RS2 << OP_SH_RS2)
>  #define MASK_RD (OP_MASK_RD << OP_SH_RD)
>  #define MASK_CRS2 (OP_MASK_CRS2 << OP_SH_CRS2)
> +#define MASK_CRS2S (OP_MASK_CRS2S << OP_SH_CRS2S)
>  #define MASK_IMM ENCODE_ITYPE_IMM (-1U)
>  #define MASK_RVC_IMM ENCODE_CITYPE_IMM (-1U)
>  #define MASK_UIMM ENCODE_UTYPE_IMM (-1U)
> @@ -205,6 +206,20 @@ match_rs2_rd_even (const struct riscv_opcode *op, insn_t insn)
>    return ((rs2 & 1) == 0) && ((rd & 1) == 0) && match_opcode (op, insn);
>  }
>
> +static int
> +match_rd_even (const struct riscv_opcode *op, insn_t insn)
> +{
> +  int rd = (insn & MASK_RD) >> OP_SH_RD;
> +  return ((rd & 1) == 0) && match_opcode (op, insn);
> +}
> +
> +static int
> +match_rs2_even (const struct riscv_opcode *op, insn_t insn)
> +{
> +  int rs2 = (insn & MASK_RS2) >> OP_SH_RS2;
> +  return ((rs2 & 1) == 0) && match_opcode (op, insn);
> +}
> +
>  static int
>  match_rd_nonzero (const struct riscv_opcode *op, insn_t insn)
>  {
> @@ -212,12 +227,38 @@ match_rd_nonzero (const struct riscv_opcode *op, insn_t insn)
>          && ((insn & MASK_RD) != 0);
>  }
>
> +static int
> +match_rd_even_nonzero (const struct riscv_opcode *op, insn_t insn)
> +{
> +  return match_rd_nonzero (op, insn) && match_rd_even (op, insn);
> +}
> +
>  static int
>  match_rs1_nonzero (const struct riscv_opcode *op ATTRIBUTE_UNUSED, insn_t insn)
>  {
>    return (insn & MASK_RS1) != 0;
>  }
>
> +static int
> +match_rs1_nonzero_rs2_even (const struct riscv_opcode *op ATTRIBUTE_UNUSED, insn_t insn)
> +{
> +  return match_rs1_nonzero (op, insn) && match_rs2_even (op, insn);
> +}
> +
> +static int
> +match_crs2s_even (const struct riscv_opcode *op, insn_t insn)
> +{
> +  int crs2s = (insn & MASK_CRS2S) >> OP_SH_CRS2S;
> +  return ((crs2s & 1) == 0) && match_opcode (op, insn);
> +}
> +
> +static int
> +match_crs2_even (const struct riscv_opcode *op, insn_t insn)
> +{
> +  int crs2 = (insn & MASK_CRS2) >> OP_SH_CRS2;
> +  return ((crs2 & 1) == 0) && match_opcode (op, insn);
> +}
> +
>  static int
>  match_c_add (const struct riscv_opcode *op, insn_t insn)
>  {
> @@ -625,10 +666,18 @@ const struct riscv_opcode riscv_opcodes[] =
>  {"ld",         64, INSN_CLASS_C, "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
>  {"ld",         64, INSN_CLASS_I, "d,o(s)",    MATCH_LD, MASK_LD, match_opcode, INSN_DREF|INSN_8_BYTE },
>  {"ld",         64, INSN_CLASS_I, "d,A",       0, (int) M_Lx, match_rd_nonzero, INSN_MACRO },
> +{"ld",         32, INSN_CLASS_ZCLSD, "d,Cn(Cc)",  MATCH_C_LDSP, MASK_C_LDSP, match_rd_even_nonzero, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
> +{"ld",         32, INSN_CLASS_ZCLSD, "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_crs2s_even, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
> +{"ld",         32, INSN_CLASS_ZILSD, "d,o(s)",    MATCH_LD, MASK_LD, match_rd_even, INSN_DREF|INSN_8_BYTE },
> +{"ld",         32, INSN_CLASS_ZILSD, "d,A",       0, (int) M_Lx, match_rd_even_nonzero, INSN_MACRO },
>  {"sd",         64, INSN_CLASS_C, "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
>  {"sd",         64, INSN_CLASS_C, "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
>  {"sd",         64, INSN_CLASS_I, "t,q(s)",    MATCH_SD, MASK_SD, match_opcode, INSN_DREF|INSN_8_BYTE },
>  {"sd",         64, INSN_CLASS_I, "t,A,s",     0, (int) M_Sx_FSx, match_rs1_nonzero, INSN_MACRO },
> +{"sd",         32, INSN_CLASS_ZCLSD, "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_crs2_even, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
> +{"sd",         32, INSN_CLASS_ZCLSD, "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_crs2s_even, INSN_ALIAS|INSN_DREF|INSN_8_BYTE },
> +{"sd",         32, INSN_CLASS_ZILSD, "t,q(s)",    MATCH_SD, MASK_SD, match_rs2_even, INSN_DREF|INSN_8_BYTE },
> +{"sd",         32, INSN_CLASS_ZILSD, "t,A,s",     0, (int) M_Sx_FSx, match_rs1_nonzero_rs2_even, INSN_MACRO },
>  {"sext.w",     64, INSN_CLASS_C, "d,CU",      MATCH_C_ADDIW, MASK_C_ADDIW|MASK_RVC_IMM, match_rd_nonzero, INSN_ALIAS },
>  {"sext.w",     64, INSN_CLASS_I, "d,s",       MATCH_ADDIW, MASK_ADDIW|MASK_IMM, match_opcode, INSN_ALIAS },
>  {"addiw",      64, INSN_CLASS_C, "d,CU,Co",   MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, INSN_ALIAS },
> @@ -1160,9 +1209,14 @@ const struct riscv_opcode riscv_opcodes[] =
>  {"c.addiw",   64, INSN_CLASS_C,   "d,Co",      MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, 0 },
>  {"c.addw",    64, INSN_CLASS_C,   "Cs,Ct",     MATCH_C_ADDW, MASK_C_ADDW, match_opcode, 0 },
>  {"c.subw",    64, INSN_CLASS_C,   "Cs,Ct",     MATCH_C_SUBW, MASK_C_SUBW, match_opcode, 0 },
> +/*zclsd  */
> +{"c.ldsp",    32, INSN_CLASS_ZCLSD, "d,Cn(Cc)",  MATCH_C_LDSP, MASK_C_LDSP, match_rd_even_nonzero, INSN_DREF|INSN_8_BYTE },
>  {"c.ldsp",    64, INSN_CLASS_C,   "d,Cn(Cc)",  MATCH_C_LDSP, MASK_C_LDSP, match_rd_nonzero, INSN_DREF|INSN_8_BYTE },
> +{"c.ld",      32, INSN_CLASS_ZCLSD, "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_crs2s_even, INSN_DREF|INSN_8_BYTE },
>  {"c.ld",      64, INSN_CLASS_C,   "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_opcode, INSN_DREF|INSN_8_BYTE },
> +{"c.sdsp",    32, INSN_CLASS_ZCLSD, "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_crs2_even, INSN_DREF|INSN_8_BYTE },
>  {"c.sdsp",    64, INSN_CLASS_C,   "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_opcode, INSN_DREF|INSN_8_BYTE },
> +{"c.sd",      32, INSN_CLASS_ZCLSD, "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_crs2s_even, INSN_DREF|INSN_8_BYTE },
>  {"c.sd",      64, INSN_CLASS_C,   "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_opcode, INSN_DREF|INSN_8_BYTE },
>  {"c.fldsp",    0, INSN_CLASS_D_AND_C, "D,Cn(Cc)",  MATCH_C_FLDSP, MASK_C_FLDSP, match_opcode, INSN_DREF|INSN_8_BYTE },
>  {"c.fld",      0, INSN_CLASS_D_AND_C, "CD,Cl(Cs)", MATCH_C_FLD, MASK_C_FLD, match_opcode, INSN_DREF|INSN_8_BYTE },
> --
> 2.34.1
>


More information about the Binutils mailing list