diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index c070394a366..76636d3267f 100644 --- a/bfd/elfxx-riscv.c +++ b/bfd/elfxx-riscv.c @@ -1064,11 +1064,25 @@ riscv_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED, return bfd_reloc_ok; } +/* Record all implicit information for the subsets. */ + +typedef struct riscv_implicit_subset +{ + const char *subset_name; + const char *implicit_name; + /* A function to determine if we need to add the implicit subset. */ + bool (*check_func) (riscv_parse_subset_t *, + const struct riscv_implicit_subset *, + const riscv_subset_t *); +} riscv_implicit_subset_t; + /* Always add the IMPLICIT for the SUBSET. */ static bool -check_implicit_always (const char *implicit ATTRIBUTE_UNUSED, - riscv_subset_t *subset ATTRIBUTE_UNUSED) +check_implicit_always (riscv_parse_subset_t *rps ATTRIBUTE_UNUSED, + const riscv_implicit_subset_t *implicit + ATTRIBUTE_UNUSED, + const riscv_subset_t *subset ATTRIBUTE_UNUSED) { return true; } @@ -1076,23 +1090,31 @@ check_implicit_always (const char *implicit ATTRIBUTE_UNUSED, /* Add the IMPLICIT only when the version of SUBSET less than 2.1. */ static bool -check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED, - riscv_subset_t *subset) +check_implicit_for_i (riscv_parse_subset_t *rps ATTRIBUTE_UNUSED, + const riscv_implicit_subset_t *implicit ATTRIBUTE_UNUSED, + const riscv_subset_t *subset) { return (subset->major_version < 2 || (subset->major_version == 2 && subset->minor_version < 1)); } -/* Record all implicit information for the subsets. */ -struct riscv_implicit_subset +/* Add the IMPLICIT only when the 'Zce' extension is also available + and XLEN is 32. */ + +static bool +check_implicit_for_f_zce (riscv_parse_subset_t *rps, + const riscv_implicit_subset_t *implicit + ATTRIBUTE_UNUSED, + const riscv_subset_t *subset ATTRIBUTE_UNUSED) { - const char *subset_name; - const char *implicit_name; - /* A function to determine if we need to add the implicit subset. */ - bool (*check_func) (const char *, riscv_subset_t *); -}; -static struct riscv_implicit_subset riscv_implicit_subsets[] = + return *rps->xlen == 32 + && riscv_subset_supports (rps, "zce"); +} + +/* All extension implications. */ + +static riscv_implicit_subset_t riscv_implicit_subsets[] = { {"e", "i", check_implicit_always}, {"i", "zicsr", check_implicit_for_i}, @@ -1179,6 +1201,10 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] = {"zvksg", "zvkg", check_implicit_always}, {"zvksc", "zvks", check_implicit_always}, {"zvksc", "zvbc", check_implicit_always}, + {"zce", "zca", check_implicit_always}, + {"zce", "zcb", check_implicit_always}, + {"zce", "zcmp", check_implicit_always}, + {"zce", "zcmt", check_implicit_always}, {"zcf", "zca", check_implicit_always}, {"zcd", "zca", check_implicit_always}, {"zcb", "zca", check_implicit_always}, @@ -1191,6 +1217,9 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] = {"ssstateen", "zicsr", check_implicit_always}, {"sstc", "zicsr", check_implicit_always}, {"svadu", "zicsr", check_implicit_always}, + /* Complex implications (that should be checked after others). */ + {"f", "zcf", check_implicit_for_f_zce}, + /* Tail of the list. */ {NULL, NULL, NULL} }; @@ -1324,6 +1353,9 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] = {"zcb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, {"zcf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, {"zcd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, + {"zce", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, + {"zcmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, + {"zcmt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, {NULL, 0, 0, 0, 0} }; @@ -1909,7 +1941,7 @@ riscv_parse_extensions (riscv_parse_subset_t *rps, static void riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps) { - struct riscv_implicit_subset *t = riscv_implicit_subsets; + riscv_implicit_subset_t *t = riscv_implicit_subsets; bool finished = false; while (!finished) { @@ -1921,7 +1953,7 @@ riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps) if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset) && !riscv_lookup_subset (rps->subset_list, t->implicit_name, &implicit_subset) - && t->check_func (t->implicit_name, subset)) + && t->check_func (rps, t, subset)) { riscv_parse_add_subset (rps, t->implicit_name, RISCV_UNKNOWN_VERSION, diff --git a/gas/testsuite/gas/riscv/march-imply-zce-f-32.d b/gas/testsuite/gas/riscv/march-imply-zce-f-32.d new file mode 100644 index 00000000000..e0cca82e0a0 --- /dev/null +++ b/gas/testsuite/gas/riscv/march-imply-zce-f-32.d @@ -0,0 +1,6 @@ +#as: -march=rv32if_zce -march-attr -misa-spec=20191213 +#readelf: -A +#source: empty.s +Attribute Section: riscv +File Attributes + Tag_RISCV_arch: "rv32i2p1_f2p2_zicsr2p0_zca1p0_zcb1p0_zce1p0_zcf1p0_zcmp1p0_zcmt1p0" diff --git a/gas/testsuite/gas/riscv/march-imply-zce-f-64.d b/gas/testsuite/gas/riscv/march-imply-zce-f-64.d new file mode 100644 index 00000000000..f0ccd7a3fce --- /dev/null +++ b/gas/testsuite/gas/riscv/march-imply-zce-f-64.d @@ -0,0 +1,6 @@ +#as: -march=rv64if_zce -march-attr -misa-spec=20191213 +#readelf: -A +#source: empty.s +Attribute Section: riscv +File Attributes + Tag_RISCV_arch: "rv64i2p1_f2p2_zicsr2p0_zca1p0_zcb1p0_zce1p0_zcmp1p0_zcmt1p0" diff --git a/gas/testsuite/gas/riscv/march-imply-zce.d b/gas/testsuite/gas/riscv/march-imply-zce.d new file mode 100644 index 00000000000..2a4ab4e1b63 --- /dev/null +++ b/gas/testsuite/gas/riscv/march-imply-zce.d @@ -0,0 +1,6 @@ +#as: -march=rv32i_zce -march-attr -misa-spec=20191213 +#readelf: -A +#source: empty.s +Attribute Section: riscv +File Attributes + Tag_RISCV_arch: "rv32i2p1_zca1p0_zcb1p0_zce1p0_zcmp1p0_zcmt1p0"