aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/config.in3
-rwxr-xr-xbfd/configure10
-rw-r--r--bfd/configure.ac6
-rw-r--r--bfd/cpu-riscv.c2
-rw-r--r--bfd/cpu-riscv.h5
-rw-r--r--bfd/elfxx-riscv.c28
-rw-r--r--gas/config/tc-riscv.c18
-rw-r--r--gas/testsuite/gas/riscv/extended/sifive-insns.d12
-rw-r--r--gas/testsuite/gas/riscv/extended/sifive-insns.s4
-rw-r--r--include/opcode/riscv-opc-extended.h11
-rw-r--r--include/opcode/riscv.h5
-rw-r--r--opcodes/riscv-opc.c14
12 files changed, 113 insertions, 5 deletions
diff --git a/bfd/config.in b/bfd/config.in
index f54a3ca..abd1385 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 58449ee..53263db 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -13658,6 +13658,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 50ba391..94885ba 100644
--- a/bfd/configure.ac
+++ b/bfd/configure.ac
@@ -822,6 +822,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 813f2c3..981f8d7 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 c43a4ce..4657c0e 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 34bcab6..10c05c3 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -1109,7 +1109,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. */
@@ -1134,7 +1135,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 },
@@ -1223,6 +1224,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,
@@ -1231,6 +1240,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
};
@@ -1495,7 +1505,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;
@@ -1507,6 +1520,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;
@@ -1917,8 +1931,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 99165f5..8e28adb7 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
};
@@ -310,6 +311,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;
@@ -461,6 +469,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;
@@ -1481,7 +1492,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
@@ -1593,6 +1607,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 0000000..ea6377a
--- /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 0000000..b44dad0
--- /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 de9741f..1010661 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 8cef449..568e33b 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -529,6 +529,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 22474f0..c55a264 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -2302,10 +2302,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
};