[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