[integration] RISC-V/SiFive: Added SiFive custom cache control instructions.

Nelson Chu nelson.chu@sifive.com
Mon Oct 25 02:23:16 GMT 2021


Hi Guys,

Ping.  If there are no other concerns, I will commit this patch into
the riscv integration branch recently.

Thanks
Nelson

On Mon, Sep 27, 2021 at 4:30 PM Nelson Chu <nelson.chu@sifive.com> wrote:
>
> According to the chapter 10 of the following U74-MC manual,
> https://sifive.cdn.prismic.io/sifive/6d9a2510-2632-44f3-adb9-d0430f139372_sifive_coreip_U74MC_AXI4_rtl_v19_08p2p0_release_manual.pdf
>
> and the implementations of freedom-metal,
> https://github.com/sifive/freedom-metal/blob/v201908-branch/src/cache.c
>
> * Encodings,
> 31-25   24-20 19-15 14-12  11-7  6-0
> FUNCT7  RS2   RS1   FUNCT3 RD    OPCODE
> 1111110 00000 xxxxx 000    00000 1110011 CFLUSH.D.L1
> 1111110 00010 xxxxx 000    00000 1110011 CDISCARD.D.L1
> 1111110 00001 00000 000    00000 1110011 CFLUSH.I.L1
>
> * Extension names,
> xsfcflushdlone:   CFLUSH.D.L1.
> xsfcdiscarddlone: CDISCARD.D.L1.
> xsfcflushilone:   CFLUSH.I.L1.
>
> * Vendor target triples,
> For assembler, the target vendor is defined as TARGET_VENDOR in the
> gas/config.h, but I don't see any related settings in bfd/config.h
> and opcode/config.  Since we may have vendor relocations in the future,
> and these relocation numbers may repeat, I add a new RISCV_TARGET_VENDOR
> in the bfd/config.h for riscv.  The vendor name will be stored in the
> bfd/cpu-riscv.c, so that all tools (gas, bfd, opcode, ...) can get
> the vendor name from the configure setting.
>
> If the --with-arch configure option, -march gas option and elf architecture
> attributes are not set, then we will generate the default ISA string
> according to the chosen target vendor.  For example, if you build the
> binutils with the configure option, --target=riscv64-sifive-elf, then
> the assembler will find the whole supported extension tables in the
> bfd/elfxx-riscv.c, and generate the suitable ISA string.
>
> bfd/
>         * configure.ac (RISCV_TARGET_VENDOR): Defined to store target_vendor,
>         only when the target is riscv*.
>         * config.in: Regenerated.
>         * configure: Regenerated.
>         * cpu-riscv.c (riscv_vendor_name): Defined to RISCV_TARGET_VENDOR.
>         * cpu-riscv.h (enum riscv_spec_class): Added VENDOR_SPEC_CLASS_SIFIVE.
>         * elfxx-riscv. (EXT_SIFIVE): Defined to choose the default extensions
>         for sifive.
>         (riscv_supported_vendor_sifive_ext): Added extensions for sifive cache
>         control instructions.
>         (riscv_supported_std_ext, riscv_all_supported_ext): Updated.
>         (riscv_get_default_ext_version): Updated.
>         (riscv_set_default_arch): Updated.
> gas/
>         * config/tc-riscv.c (VENDOR_SIFIVE_EXT): Added.
>         (riscv_extended_subset_supports): Handle INSN_CLASS_XSF*.
>         (op_vendor_sifive_hash): Added to store sifive opcodes.
>         (md_begin): Init the op_vendor_sifive_hash.
>         (riscv_find_extended_opcode_hash): Find the opcodes from
>         op_vendor_sifive_hash.
>         * testsuite/gas/riscv/extended/sifive-insns.d: New testcase.
>         * testsuite/gas/riscv/extended/sifive-insns.s: Likewise.
> include/
>         * opcode/riscv-opc-extended.h: Added opcodes for sifive cache
>         instructions.
>         * opcode/riscv.h (enum riscv_extended_insn_class): Added INSN_CLASS_XSF*.
> opcodes/
>         * riscv-opc.c (riscv_vendor_sifive_opcodes): Added.
>         (riscv_extended_opcodes): Updated.
> ---
>  bfd/config.in                                 |  3 ++
>  bfd/configure                                 | 10 +++++++
>  bfd/configure.ac                              |  6 ++++
>  bfd/cpu-riscv.c                               |  2 ++
>  bfd/cpu-riscv.h                               |  5 ++++
>  bfd/elfxx-riscv.c                             | 28 ++++++++++++++++---
>  gas/config/tc-riscv.c                         | 18 +++++++++++-
>  .../gas/riscv/extended/sifive-insns.d         | 12 ++++++++
>  .../gas/riscv/extended/sifive-insns.s         |  4 +++
>  include/opcode/riscv-opc-extended.h           | 11 ++++++++
>  include/opcode/riscv.h                        |  5 ++++
>  opcodes/riscv-opc.c                           | 14 ++++++++++
>  12 files changed, 113 insertions(+), 5 deletions(-)
>  create mode 100644 gas/testsuite/gas/riscv/extended/sifive-insns.d
>  create mode 100644 gas/testsuite/gas/riscv/extended/sifive-insns.s
>
> diff --git a/bfd/config.in b/bfd/config.in
> index f54a3cacbea..abd1385a185 100644
> --- a/bfd/config.in
> +++ b/bfd/config.in
> @@ -257,6 +257,9 @@
>  /* Define to the version of this package. */
>  #undef PACKAGE_VERSION
>
> +/* RISCV target vendor. */
> +#undef RISCV_TARGET_VENDOR
> +
>  /* The size of `int', as computed by sizeof. */
>  #undef SIZEOF_INT
>
> diff --git a/bfd/configure b/bfd/configure
> index cae69d413d4..5670a62b095 100755
> --- a/bfd/configure
> +++ b/bfd/configure
> @@ -13655,6 +13655,16 @@ test -n "${selarchs}" && tdefaults="${tdefaults} -DSELECT_ARCHITECTURES='${selar
>
>
>
> +case "${target_cpu}" in
> +  riscv*)
> +
> +cat >>confdefs.h <<_ACEOF
> +#define RISCV_TARGET_VENDOR "${target_vendor}"
> +_ACEOF
> +
> +    ;;
> +esac
> +
>  # If we are configured native, pick a core file support file.
>  COREFILE=
>  COREFLAG=
> diff --git a/bfd/configure.ac b/bfd/configure.ac
> index 9ff303ab6e1..ace0b65a631 100644
> --- a/bfd/configure.ac
> +++ b/bfd/configure.ac
> @@ -820,6 +820,12 @@ AC_SUBST(bfd_default_target_size)
>  AC_SUBST(tdefaults)
>  AC_SUBST(havevecs)
>
> +case "${target_cpu}" in
> +  riscv*)
> +    AC_DEFINE_UNQUOTED(RISCV_TARGET_VENDOR, "${target_vendor}", [RISCV target vendor.])
> +    ;;
> +esac
> +
>  # If we are configured native, pick a core file support file.
>  COREFILE=
>  COREFLAG=
> diff --git a/bfd/cpu-riscv.c b/bfd/cpu-riscv.c
> index 813f2c3df8d..981f8d72e5c 100644
> --- a/bfd/cpu-riscv.c
> +++ b/bfd/cpu-riscv.c
> @@ -25,6 +25,8 @@
>  #include "libbfd.h"
>  #include "cpu-riscv.h"
>
> +const char *riscv_vendor_name = RISCV_TARGET_VENDOR;
> +
>  static const bfd_arch_info_type *
>  riscv_compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b)
>  {
> diff --git a/bfd/cpu-riscv.h b/bfd/cpu-riscv.h
> index c43a4ceae58..4657c0e3e90 100644
> --- a/bfd/cpu-riscv.h
> +++ b/bfd/cpu-riscv.h
> @@ -18,6 +18,8 @@
>     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
>     MA 02110-1301, USA.  */
>
> +extern const char *riscv_vendor_name;
> +
>  enum riscv_spec_class
>  {
>    /* ISA spec.  */
> @@ -36,6 +38,9 @@ enum riscv_spec_class
>
>    /* Vendor spec for T_HEAD XuanTie.  */
>    VENDOR_SPEC_CLASS_THEAD,
> +
> +  /* Vendor spec for SiFive.  */
> +  VENDOR_SPEC_CLASS_SIFIVE,
>  };
>
>  struct riscv_spec
> diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
> index e61319cf395..bb77a5f67b1 100644
> --- a/bfd/elfxx-riscv.c
> +++ b/bfd/elfxx-riscv.c
> @@ -1083,7 +1083,8 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
>  /* For default_enable field, decide if the extension should
>     be enbaled by default.  */
>
> -#define EXT_DEFAULT   0x1
> +#define EXT_DEFAULT    0x1
> +#define EXT_SIFIVE     (0x1 << 2)
>
>  /* List all extensions that binutils should know about.  */
>
> @@ -1108,7 +1109,7 @@ static struct riscv_supported_ext riscv_supported_std_ext[] =
>    {"i",                ISA_SPEC_CLASS_2P2,             2, 0, 0 },
>    /* The g is a special case which we don't want to output it,
>       but still need it when adding implicit extensions.  */
> -  {"g",                ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
> +  {"g",                ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT|EXT_SIFIVE },
>    {"m",                ISA_SPEC_CLASS_20191213,        2, 0, 0 },
>    {"m",                ISA_SPEC_CLASS_20190608,        2, 0, 0 },
>    {"m",                ISA_SPEC_CLASS_2P2,             2, 0, 0 },
> @@ -1179,6 +1180,14 @@ static struct riscv_supported_ext riscv_supported_vendor_thead_ext[] =
>    {NULL, 0, 0, 0, 0}
>  };
>
> +static struct riscv_supported_ext riscv_supported_vendor_sifive_ext[] =
> +{
> +  {"xsfcdiscarddlone", VENDOR_SPEC_CLASS_SIFIVE,       0, 1, EXT_SIFIVE},
> +  {"xsfcflushdlone",   VENDOR_SPEC_CLASS_SIFIVE,       0, 1, EXT_SIFIVE},
> +  {"xsfcflushilone",   VENDOR_SPEC_CLASS_SIFIVE,       0, 1, EXT_SIFIVE},
> +  {NULL, 0, 0, 0, 0}
> +};
> +
>  const struct riscv_supported_ext *riscv_all_supported_ext[] =
>  {
>    riscv_supported_std_ext,
> @@ -1187,6 +1196,7 @@ const struct riscv_supported_ext *riscv_all_supported_ext[] =
>    riscv_supported_std_h_ext,
>    riscv_supported_std_zxm_ext,
>    riscv_supported_vendor_thead_ext,
> +  riscv_supported_vendor_sifive_ext,
>    NULL
>  };
>
> @@ -1451,7 +1461,10 @@ riscv_get_default_ext_version (enum riscv_spec_class default_isa_spec,
>      case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
>      case RV_ISA_CLASS_H: table = riscv_supported_std_h_ext; break;
>      case RV_ISA_CLASS_X:
> -      table = riscv_supported_vendor_thead_ext;
> +      if (strncmp (name, "xsf", 3) == 0)
> +       table = riscv_supported_vendor_sifive_ext;
> +      else
> +       table = riscv_supported_vendor_thead_ext;
>        break;
>      default:
>        table = riscv_supported_std_ext;
> @@ -1463,6 +1476,7 @@ riscv_get_default_ext_version (enum riscv_spec_class default_isa_spec,
>        if (strcmp (table[i].name, name) == 0
>           && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
>               || table[i].isa_spec_class == VENDOR_SPEC_CLASS_THEAD
> +             || table[i].isa_spec_class == VENDOR_SPEC_CLASS_SIFIVE
>               || table[i].isa_spec_class == default_isa_spec))
>         {
>           *major_version = table[i].major_version;
> @@ -1849,8 +1863,14 @@ riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
>  static void
>  riscv_set_default_arch (riscv_parse_subset_t *rps)
>  {
> -  unsigned long enable = EXT_DEFAULT;
> +  unsigned long enable;
>    int i, j;
> +
> +  if (strcmp (riscv_vendor_name, "sifive") == 0)
> +    enable = EXT_SIFIVE;
> +  else
> +    enable = EXT_DEFAULT;
> +
>    for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
>      {
>        const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
> diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
> index d4cf99e002b..c1b3c84b5b9 100644
> --- a/gas/config/tc-riscv.c
> +++ b/gas/config/tc-riscv.c
> @@ -40,6 +40,7 @@ enum
>  {
>    DRAFT_EXT = 0,
>    VENDOR_THEAD_EXT,
> +  VENDOR_SIFIVE_EXT,
>    EXTENDED_EXT_NUM
>  };
>
> @@ -309,6 +310,13 @@ riscv_extended_subset_supports (int insn_class)
>      case INSN_CLASS_THEADSE:
>        return riscv_subset_supports ("xtheadse");
>
> +    case INSN_CLASS_XSF_CDISCARDDLONE:
> +      return riscv_subset_supports ("xsfcdiscarddlone");
> +    case INSN_CLASS_XSF_CFLUSHDLONE:
> +      return riscv_subset_supports ("xsfcflushdlone");
> +    case INSN_CLASS_XSF_CFLUSHILONE:
> +      return riscv_subset_supports ("xsfcflushilone");
> +
>      default:
>        as_fatal ("internal: unknown INSN_CLASS (0x%x)", insn_class);
>        return false;
> @@ -457,6 +465,9 @@ static htab_t op_draft_hash = NULL;
>  /* Handle of the T-HEAD OPCODE hash table.  */
>  static htab_t op_vendor_thead_hash = NULL;
>
> +/* Handle of the sifive OPCODE hash table.  */
> +static htab_t op_vendor_sifive_hash = NULL;
> +
>  /* Handle of the type of .insn hash table.  */
>  static htab_t insn_type_hash = NULL;
>
> @@ -1478,7 +1489,10 @@ md_begin (void)
>    hash_reg_names (RCLASS_VECR, riscv_vecr_names_numeric, NVECR);
>    hash_reg_names (RCLASS_VECM, riscv_vecm_names_numeric, NVECM);
>    op_draft_hash = init_opcode_hash (riscv_extended_opcodes[DRAFT_EXT], false);
> -  op_vendor_thead_hash = init_opcode_hash (riscv_extended_opcodes[VENDOR_THEAD_EXT], false);
> +  op_vendor_thead_hash =
> +       init_opcode_hash (riscv_extended_opcodes[VENDOR_THEAD_EXT], false);
> +  op_vendor_sifive_hash =
> +       init_opcode_hash (riscv_extended_opcodes[VENDOR_SIFIVE_EXT], false);
>  }
>
>  static insn_t
> @@ -1590,6 +1604,8 @@ riscv_find_extended_opcode_hash (char *str ATTRIBUTE_UNUSED)
>         case VENDOR_THEAD_EXT:
>           insn = (struct riscv_opcode *) str_hash_find (op_vendor_thead_hash, str);
>           break;
> +       case VENDOR_SIFIVE_EXT:
> +         insn = (struct riscv_opcode *) str_hash_find (op_vendor_sifive_hash, str);
>         default:
>           break;
>         }
> diff --git a/gas/testsuite/gas/riscv/extended/sifive-insns.d b/gas/testsuite/gas/riscv/extended/sifive-insns.d
> new file mode 100644
> index 00000000000..ea6377ad756
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/extended/sifive-insns.d
> @@ -0,0 +1,12 @@
> +#as: -march=rv32i_xsfcdiscarddlone_xsfcflushdlone_xsfcflushilone
> +#objdump: -dr
> +
> +.*:[   ]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+000 <target>:
> +[      ]+0:[   ]+fc050073[     ]+cflush.d.l1[  ]+a0
> +[      ]+4:[   ]+fc250073[     ]+cdiscard.d.l1[        ]+a0
> +[      ]+8:[   ]+fc100073[     ]+cflush.i.l1
> diff --git a/gas/testsuite/gas/riscv/extended/sifive-insns.s b/gas/testsuite/gas/riscv/extended/sifive-insns.s
> new file mode 100644
> index 00000000000..b44dad08bd2
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/extended/sifive-insns.s
> @@ -0,0 +1,4 @@
> +target:
> +       cflush.d.l1     x10
> +       cdiscard.d.l1   x10
> +       cflush.i.l1
> diff --git a/include/opcode/riscv-opc-extended.h b/include/opcode/riscv-opc-extended.h
> index 3de8809b4c2..f0f7490537c 100644
> --- a/include/opcode/riscv-opc-extended.h
> +++ b/include/opcode/riscv-opc-extended.h
> @@ -2078,3 +2078,14 @@ DECLARE_CSR(shpmcounter29, CSR_SHPMCOUNTER29, CSR_CLASS_VENDOR_THEAD, PRIV_SPEC_
>  DECLARE_CSR(shpmcounter30, CSR_SHPMCOUNTER30, CSR_CLASS_VENDOR_THEAD, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE)
>  DECLARE_CSR(shpmcounter31, CSR_SHPMCOUNTER31, CSR_CLASS_VENDOR_THEAD, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE)
>  #endif /* DECLARE_CSR */
> +
> +#ifndef __RISCV_OPC_SIFIVE_THEAD__
> +#define __RISCV_OPC_SIFIVE_THEAD__
> +/* SiFive cache control instructions.  */
> +#define MATCH_CFLUSH_D_L1      0xfc000073
> +#define MASK_CFLUSH_D_L1       0xfff07fff
> +#define MATCH_CDISCARD_D_L1    0xfc200073
> +#define MASK_CDISCARD_D_L1     0xfff07fff
> +#define MATCH_CFLUSH_I_L1      0xfc100073
> +#define MASK_CFLUSH_I_L1       0xffffffff
> +#endif /* __RISCV_OPC_SIFIVE_THEAD__ */
> diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
> index 1603fcfc495..7f97bb2cf3a 100644
> --- a/include/opcode/riscv.h
> +++ b/include/opcode/riscv.h
> @@ -527,6 +527,11 @@ enum riscv_extended_insn_class
>    INSN_CLASS_THEADC_OR_THEADE_OR_THEADSE,
>    INSN_CLASS_THEADE,
>    INSN_CLASS_THEADSE,
> +
> +  /* SiFive.  */
> +  INSN_CLASS_XSF_CDISCARDDLONE,
> +  INSN_CLASS_XSF_CFLUSHDLONE,
> +  INSN_CLASS_XSF_CFLUSHILONE,
>  };
>
>  /* This is a list of macro expanded instructions for extended
> diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
> index 05f94704774..9b2a482c3e6 100644
> --- a/opcodes/riscv-opc.c
> +++ b/opcodes/riscv-opc.c
> @@ -2378,10 +2378,24 @@ struct riscv_opcode riscv_vendor_thead_opcodes[] =
>
>  };
>
> +/* Vendor SiFive extensions.  */
> +const struct riscv_opcode riscv_vendor_sifive_opcodes[] =
> +{
> +/* name, xlen, isa, operands, match, mask, match_func, pinfo.  */
> +/* Half-precision floating-point instruction subset.  */
> +{"cflush.d.l1",                0, INSN_CLASS_XSF_CFLUSHDLONE,   "s", MATCH_CFLUSH_D_L1, MASK_CFLUSH_D_L1, match_opcode, 0 },
> +{"cdiscard.d.l1",      0, INSN_CLASS_XSF_CDISCARDDLONE, "s", MATCH_CDISCARD_D_L1, MASK_CDISCARD_D_L1, match_opcode, 0 },
> +{"cflush.i.l1",                0, INSN_CLASS_XSF_CFLUSHILONE,   "",  MATCH_CFLUSH_I_L1, MASK_CFLUSH_I_L1, match_opcode, 0 },
> +
> +/* Terminate the list.  */
> +{0, 0, INSN_CLASS_NONE, 0, 0, 0, 0, 0 },
> +};
> +
>  /* The supported extended extensions.  */
>  const struct riscv_opcode *riscv_extended_opcodes[] =
>  {
>    riscv_draft_opcodes,
>    riscv_vendor_thead_opcodes,
> +  riscv_vendor_sifive_opcodes,
>    NULL
>  };
> --
> 2.30.2
>


More information about the Binutils mailing list