Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 98 additions & 16 deletions bfd/elfxx-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1064,39 +1064,76 @@ 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;
}

/* 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
/* Compatibility measure for counters (Zicntr and Zihpm):
Do or do not add the IMPLICIT only when the ISA version is
less than the border. */

static bool
check_implicit_compat_counter_from_i (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[] =
/* When rps->isa_spec is NULL, we don't need to care about implicit
extensions because the caller is the linker. */
return rps->isa_spec && *rps->isa_spec <= ISA_SPEC_CLASS_20191213;
}

static bool
check_implicit_compat_counter_to_zicsr (riscv_parse_subset_t *rps,
const riscv_implicit_subset_t
*implicit,
const riscv_subset_t *subset)
{
return (rps->isa_spec
&& !check_implicit_compat_counter_from_i (rps, implicit, subset));
}

/* All extension implications. */

static riscv_implicit_subset_t riscv_implicit_subsets[] =
{
{"e", "i", check_implicit_always},
{"i", "zicsr", check_implicit_for_i},
{"i", "zifencei", check_implicit_for_i},
{"i", "zicntr", check_implicit_compat_counter_from_i},
{"i", "zihpm", check_implicit_compat_counter_from_i},
{"g", "i", check_implicit_always},
{"g", "m", check_implicit_always},
{"g", "a", check_implicit_always},
Expand Down Expand Up @@ -1182,12 +1219,20 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
{"zcf", "zca", check_implicit_always},
{"zcd", "zca", check_implicit_always},
{"zcb", "zca", check_implicit_always},
{"zicntr", "zicsr", check_implicit_compat_counter_to_zicsr},
{"zihpm", "zicsr", check_implicit_compat_counter_to_zicsr},
{"smaia", "ssaia", check_implicit_always},
{"smcdeleg", "zicsr", check_implicit_always}, /* Compat. */
{"smcdeleg", "sscsrind", check_implicit_always},
{"smcntrpmf", "zicsr", check_implicit_always},
{"smcsrind", "zicsr", check_implicit_always},
{"smstateen", "ssstateen", check_implicit_always},
{"smepmp", "zicsr", check_implicit_always},
{"ssaia", "zicsr", check_implicit_always},
{"ssccfg", "zicsr", check_implicit_always}, /* Compat. */
{"ssccfg", "sscsrind", check_implicit_always},
{"sscofpmf", "zicsr", check_implicit_always},
{"sscsrind", "zicsr", check_implicit_always},
{"ssstateen", "zicsr", check_implicit_always},
{"sstc", "zicsr", check_implicit_always},
{"svadu", "zicsr", check_implicit_always},
Expand Down Expand Up @@ -1251,13 +1296,21 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] =
{"zicbom", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zicbop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zicboz", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zicntr", ISA_SPEC_CLASS_2P2, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 }, /* Compat. */
{"zicntr", ISA_SPEC_CLASS_20190608, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 }, /* Compat. */
{"zicntr", ISA_SPEC_CLASS_20191213, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 }, /* Compat. */
{"zicntr", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
{"zicond", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zicsr", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
{"zicsr", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
{"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
{"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
{"zihintntl", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
{"zihpm", ISA_SPEC_CLASS_2P2, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 }, /* Compat. */
{"zihpm", ISA_SPEC_CLASS_20190608, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 }, /* Compat. */
{"zihpm", ISA_SPEC_CLASS_20191213, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 }, /* Compat. */
{"zihpm", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
{"zmmul", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zawrs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zfa", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
Expand Down Expand Up @@ -1330,11 +1383,15 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] =
static struct riscv_supported_ext riscv_supported_std_s_ext[] =
{
{"smaia", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"smcdeleg", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
{"smcntrpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"smcsrind", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"smepmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"smstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"ssaia", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"ssccfg", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
{"sscofpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"sscsrind", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"ssstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"sstc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"svadu", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
Expand Down Expand Up @@ -1677,9 +1734,12 @@ riscv_parse_add_subset (riscv_parse_subset_t *rps,
rps->error_handler
(_("x ISA extension `%s' must be set with the versions"),
subset);
/* Allow old ISA spec can recognize zicsr and zifencei. */
/* Allow old ISA spec (version 2.2) can recognize extensions
effectively split from the base 'I' extension version 2.0. */
else if (strcmp (subset, "zicsr") != 0
&& strcmp (subset, "zifencei") != 0)
&& strcmp (subset, "zifencei") != 0
&& strcmp (subset, "zicntr") != 0
&& strcmp (subset, "zihpm") != 0)
rps->error_handler
(_("cannot find default versions of the ISA extension `%s'"),
subset);
Expand Down Expand Up @@ -1909,7 +1969,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)
{
Expand All @@ -1921,7 +1981,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,
Expand Down Expand Up @@ -1975,6 +2035,24 @@ riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
no_conflict = false;
}

bool support_counters = (riscv_subset_supports (rps, "zicntr")
|| riscv_subset_supports (rps, "zihpm"));
if (!support_counters)
{
if (riscv_subset_supports(rps, "smcdeleg"))
{
rps->error_handler
(_("`smcdeleg' requires either `zicntr' or `zihpm' extension"));
no_conflict = false;
}
if (riscv_subset_supports(rps, "ssccfg"))
{
rps->error_handler
(_("`ssccfg' requires either `zicntr' or `zihpm' extension"));
no_conflict = false;
}
}

bool support_zve = false;
bool support_zvl = false;
riscv_subset_t *s = rps->subset_list->head;
Expand Down Expand Up @@ -2389,6 +2467,8 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
return riscv_subset_supports (rps, "zicbop");
case INSN_CLASS_ZICBOZ:
return riscv_subset_supports (rps, "zicboz");
case INSN_CLASS_ZICNTR:
return riscv_subset_supports (rps, "zicntr");
case INSN_CLASS_ZICOND:
return riscv_subset_supports (rps, "zicond");
case INSN_CLASS_ZICSR:
Expand Down Expand Up @@ -2592,6 +2672,8 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
return "zicbop";
case INSN_CLASS_ZICBOZ:
return "zicboz";
case INSN_CLASS_ZICNTR:
return "zicntr";
case INSN_CLASS_ZICOND:
return "zicond";
case INSN_CLASS_ZICSR:
Expand Down
54 changes: 52 additions & 2 deletions gas/config/tc-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ enum riscv_csr_class

CSR_CLASS_I,
CSR_CLASS_I_32, /* rv32 only */
CSR_CLASS_ZICNTR, /* basic hardware perf counter */
CSR_CLASS_ZICNTR_32, /* basic hardware perf counter, rv32 only */
CSR_CLASS_ZIHPM, /* additional hardware perf counter */
CSR_CLASS_ZIHPM_32, /* additional hardware perf counter, rv32 only */
CSR_CLASS_F, /* f-ext only */
CSR_CLASS_ZKR, /* zkr only */
CSR_CLASS_V, /* rvv only */
Expand All @@ -74,14 +78,20 @@ enum riscv_csr_class
CSR_CLASS_H_32, /* hypervisor, rv32 only */
CSR_CLASS_SMAIA, /* Smaia */
CSR_CLASS_SMAIA_32, /* Smaia, rv32 only */
CSR_CLASS_SMAIA_OR_SMCSRIND, /* Smaia or Smcsrind */
CSR_CLASS_SMCNTRPMF, /* Smcntrpmf */
CSR_CLASS_SMCNTRPMF_32, /* Smcntrpmf, rv32 only */
CSR_CLASS_SMCSRIND, /* Smcsrind */
CSR_CLASS_SMSTATEEN, /* Smstateen only */
CSR_CLASS_SMSTATEEN_32, /* Smstateen RV32 only */
CSR_CLASS_SSAIA, /* Ssaia */
CSR_CLASS_SSAIA_AND_H, /* Ssaia with H */
CSR_CLASS_SSAIA_32, /* Ssaia, rv32 only */
CSR_CLASS_SSAIA_AND_H_32, /* Ssaia with H, rv32 only */
CSR_CLASS_SSAIA_OR_SSCSRIND, /* Ssaia or Sscsrind */
CSR_CLASS_SSAIA_OR_SSCSRIND_AND_H, /* Ssaia or Sscsrind (with H) */
CSR_CLASS_SSCSRIND, /* Sscsrind */
CSR_CLASS_SSCSRIND_AND_H, /* Sscsrind (with H) */
CSR_CLASS_SSSTATEEN, /* S[ms]stateen only */
CSR_CLASS_SSSTATEEN_AND_H, /* S[ms]stateen only (with H) */
CSR_CLASS_SSSTATEEN_AND_H_32, /* S[ms]stateen RV32 only (with H) */
Expand Down Expand Up @@ -1022,6 +1032,8 @@ riscv_csr_address (const char *csr_name,
bool need_check_version = false;
bool is_rv32_only = false;
bool is_h_required = false;
bool is_csr_req_complex = false;
bool csr_ok = false;
const char* extension = NULL;

switch (csr_class)
Expand All @@ -1033,6 +1045,18 @@ riscv_csr_address (const char *csr_name,
need_check_version = true;
extension = "i";
break;
case CSR_CLASS_ZICNTR_32:
is_rv32_only = true;
/* Fall through. */
case CSR_CLASS_ZICNTR:
extension = "zicntr";
break;
case CSR_CLASS_ZIHPM_32:
is_rv32_only = true;
/* Fall through. */
case CSR_CLASS_ZIHPM:
extension = "zihpm";
break;
case CSR_CLASS_H_32:
is_rv32_only = true;
/* Fall through. */
Expand All @@ -1054,13 +1078,22 @@ riscv_csr_address (const char *csr_name,
case CSR_CLASS_SMAIA:
extension = "smaia";
break;
case CSR_CLASS_SMAIA_OR_SMCSRIND:
is_csr_req_complex = true;
extension = _ ("smaia' or `smcsrind");
csr_ok = (riscv_subset_supports (&riscv_rps_as, "smaia")
|| riscv_subset_supports (&riscv_rps_as, "smcsrind"));
break;
case CSR_CLASS_SMCNTRPMF_32:
is_rv32_only = true;
/* Fall through. */
case CSR_CLASS_SMCNTRPMF:
need_check_version = true;
extension = "smcntrpmf";
break;
case CSR_CLASS_SMCSRIND:
extension = "smcsrind";
break;
case CSR_CLASS_SMSTATEEN_32:
is_rv32_only = true;
/* Fall through. */
Expand Down Expand Up @@ -1092,6 +1125,21 @@ riscv_csr_address (const char *csr_name,
case CSR_CLASS_SSCOFPMF:
extension = "sscofpmf";
break;
case CSR_CLASS_SSAIA_OR_SSCSRIND_AND_H:
is_h_required = true;
/* Fall through. */
case CSR_CLASS_SSAIA_OR_SSCSRIND:
is_csr_req_complex = true;
extension = _ ("ssaia' or `sscsrind");
csr_ok = (riscv_subset_supports (&riscv_rps_as, "ssaia")
|| riscv_subset_supports (&riscv_rps_as, "sscsrind"));
break;
case CSR_CLASS_SSCSRIND_AND_H:
is_h_required = true;
/* Fall through. */
case CSR_CLASS_SSCSRIND:
extension = "sscsrind";
break;
case CSR_CLASS_SSTC:
case CSR_CLASS_SSTC_AND_H:
case CSR_CLASS_SSTC_32:
Expand All @@ -1115,8 +1163,10 @@ riscv_csr_address (const char *csr_name,
if (is_h_required && !riscv_subset_supports (&riscv_rps_as, "h"))
as_warn (_("invalid CSR `%s', needs `h' extension"), csr_name);

if (extension != NULL
&& !riscv_subset_supports (&riscv_rps_as, extension))
if (is_csr_req_complex
? !csr_ok
: (extension != NULL
&& !riscv_subset_supports (&riscv_rps_as, extension)))
as_warn (_("invalid CSR `%s', needs `%s' extension"),
csr_name, extension);
}
Expand Down
15 changes: 15 additions & 0 deletions gas/testsuite/gas/riscv/csr-dw-regnums.d
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,11 @@ Contents of the .* section:
DW_CFA_offset_extended_sf: r4898 \(minstretcfg\) at cfa\+3208
DW_CFA_offset_extended_sf: r5921 \(mcyclecfgh\) at cfa\+7300
DW_CFA_offset_extended_sf: r5922 \(minstretcfgh\) at cfa\+7304
DW_CFA_offset_extended_sf: r4946 \(mireg2\) at cfa\+3400
DW_CFA_offset_extended_sf: r4947 \(mireg3\) at cfa\+3404
DW_CFA_offset_extended_sf: r4949 \(mireg4\) at cfa\+3412
DW_CFA_offset_extended_sf: r4950 \(mireg5\) at cfa\+3416
DW_CFA_offset_extended_sf: r4951 \(mireg6\) at cfa\+3420
DW_CFA_offset_extended_sf: r4876 \(mstateen0\) at cfa\+3120
DW_CFA_offset_extended_sf: r4877 \(mstateen1\) at cfa\+3124
DW_CFA_offset_extended_sf: r4878 \(mstateen2\) at cfa\+3128
Expand Down Expand Up @@ -399,6 +404,16 @@ Contents of the .* section:
DW_CFA_offset_extended_sf: r5949 \(mhpmevent29h\) at cfa\+7412
DW_CFA_offset_extended_sf: r5950 \(mhpmevent30h\) at cfa\+7416
DW_CFA_offset_extended_sf: r5951 \(mhpmevent31h\) at cfa\+7420
DW_CFA_offset_extended_sf: r4434 \(sireg2\) at cfa\+1352
DW_CFA_offset_extended_sf: r4435 \(sireg3\) at cfa\+1356
DW_CFA_offset_extended_sf: r4437 \(sireg4\) at cfa\+1364
DW_CFA_offset_extended_sf: r4438 \(sireg5\) at cfa\+1368
DW_CFA_offset_extended_sf: r4439 \(sireg6\) at cfa\+1372
DW_CFA_offset_extended_sf: r4690 \(vsireg2\) at cfa\+2376
DW_CFA_offset_extended_sf: r4691 \(vsireg3\) at cfa\+2380
DW_CFA_offset_extended_sf: r4693 \(vsireg4\) at cfa\+2388
DW_CFA_offset_extended_sf: r4694 \(vsireg5\) at cfa\+2392
DW_CFA_offset_extended_sf: r4695 \(vsireg6\) at cfa\+2396
DW_CFA_offset_extended_sf: r4429 \(stimecmp\) at cfa\+1332
DW_CFA_offset_extended_sf: r4445 \(stimecmph\) at cfa\+1396
DW_CFA_offset_extended_sf: r4685 \(vstimecmp\) at cfa\+2356
Expand Down
Loading