Skip to content

Commit

Permalink
RISC-V: Add 'Zicntr' and 'Zihpm' support with compatibility measures
Browse files Browse the repository at this point in the history
This commit adds support for 'Zicntr' and 'Zihpm' extensions (version 2.0).

However, because GNU Binutils handled those as a part of 'I' and there was
a time when a ratified specification did split counters from the 'I'
extension without separate extension names, we need to take care of
possible compatibility issues.

So, if a 'Zicntr' pseudoinstruction is used without that extension,
it generates not an error but a warning.

bfd/ChangeLog:

	* elfxx-riscv.c (riscv_implicit_subsets): Add implications related
	to counter extensions.
	(riscv_supported_std_z_ext): Add 'Zicntr' and 'Zihpm' extensions.
	Define default versions of 'Zicsr' and 'Zifencei' on the draft ISA
	because they might be used on the 'E' extension handling.
	(riscv_is_subset_of_i_2p0): New function.
	(riscv_parse_add_subset): If a subset of the 'I' extension version
	2.0 is being added, check the version of 'I' and allow its version
	unknown when the 'I' extension version is less than 2.1.
	(riscv_multi_subset_supports, riscv_multi_subset_supports_ext):
	Add support for the 'Zicntr' extension with compatibility measure.

gas/ChangeLog:

	* config/tc-riscv.c (enum riscv_csr_class): Add new CSR classes
	corresponding 'Zicntr' and 'Zihpm' extensions.
	(riscv_csr_address): Add handling for new CSR classes.
	(riscv_ip): Raise a warning if a 'Zicntr' pseudoinstruction is
	used without that extension.
	* testsuite/gas/riscv/csr-insns-pseudo.s: Rename section names
	to indicate that the extension 'Zicntr' is needed.
	* testsuite/gas/riscv/csr-insns-pseudo.d: Add "zicntr" to arch.
	* testsuite/gas/riscv/csr-insns-pseudo-noalias.d: Likewise.
	* testsuite/gas/riscv/csr-insns-pseudo-zfinx.d: Likewise.
	* testsuite/gas/riscv/csr-insns-read-only.d: Likewise.
	* testsuite/gas/riscv/csr-version-1p9p1.d: Specify versions.
	* testsuite/gas/riscv/csr-version-1p10.d: Likewise.
	* testsuite/gas/riscv/csr-version-1p11.d: Likewise.
	* testsuite/gas/riscv/csr-version-1p12.d: Likewise.
	* testsuite/gas/riscv/csr-version-1p9p1.l: Add warnings regarding
	'Zicntr' and 'Zihpm' extension recategorization.
	* testsuite/gas/riscv/csr-version-1p10.l: Likewise.
	* testsuite/gas/riscv/csr-version-1p11.l: Likewise.
	* testsuite/gas/riscv/csr-version-1p12.l: Likewise.
	* testsuite/gas/riscv/march-imply-i2p0-01.d: 'I' version 2.0
	effectively imples 'Zicsr' and 'Zifencei' but should not be
	reflected to the expanded architectural string.
	* testsuite/gas/riscv/march-ok-reorder.d: Use 'I' version 2.1 and
	use other extensions to test proper ordering.
	* testsuite/gas/riscv/csr-insns-pseudo-nozicntr.d: New test to
	see warnings are generated when the 'Zicntr' extension is not
	specified.
	* testsuite/gas/riscv/csr-insns-pseudo-nozicntr.l: Likewise.

include/ChangeLog:

	* opcode/riscv-opc.h: Recategorize user counter CSRs.
	* opcode/riscv.h (enum riscv_insn_class): Add INSN_CLASS_ZICNTR
	for 'Zicntr' pseudoinstructions.

opcodes/ChangeLog:

	* riscv-opc.c (riscv_opcodes): Recategorize counter
	pseudoinstructions to the 'Zicntr' extension.
  • Loading branch information
a4lg committed Oct 21, 2023
1 parent 0e17d3f commit a155952
Show file tree
Hide file tree
Showing 22 changed files with 1,224 additions and 87 deletions.
52 changes: 47 additions & 5 deletions bfd/elfxx-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,8 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
{"e", "i", check_implicit_always},
{"i", "zicsr", check_implicit_for_i},
{"i", "zifencei", check_implicit_for_i},
{"i", "zicntr", check_implicit_for_i},
{"i", "zihpm", check_implicit_for_i},
{"g", "i", check_implicit_always},
{"g", "m", check_implicit_always},
{"g", "a", check_implicit_always},
Expand Down Expand Up @@ -1148,6 +1150,8 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
{"zhinx", "zhinxmin", check_implicit_always},
{"zhinxmin", "zfinx", check_implicit_always},
{"zfinx", "zicsr", check_implicit_always},
{"zicntr", "zicsr", check_implicit_always},
{"zihpm", "zicsr", check_implicit_always},
{"zk", "zkn", check_implicit_always},
{"zk", "zkr", check_implicit_always},
{"zk", "zkt", check_implicit_always},
Expand Down Expand Up @@ -1251,13 +1255,17 @@ 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_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 },
{"zicsr", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
{"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
{"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
{"zifencei", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
{"zihintntl", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
{"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 @@ -1649,6 +1657,18 @@ riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
}
}

/* Check if the subset is one of the extensions split from
the 'I' extension version 2.0. */

static bool
riscv_is_subset_of_i_2p0 (const char *subset)
{
return (strcmp (subset, "zicsr") == 0
|| strcmp (subset, "zifencei") == 0
|| strcmp (subset, "zicntr") == 0
|| strcmp (subset, "zihpm") == 0);
}

/* Find the default versions for the extension before adding them to
the subset list, if their versions are RISCV_UNKNOWN_VERSION.
Afterwards, report errors if we can not find their default versions. */
Expand All @@ -1662,9 +1682,26 @@ riscv_parse_add_subset (riscv_parse_subset_t *rps,
{
int major_version = major;
int minor_version = minor;
bool handle_subset_of_i_2p0 = false;

/* If a subset of the 'I' extension version 2.0 is being added,
check the version of 'I' and allow its version unknown when the
'I' extension version is less than 2.1.
Draft 'E' is arbitrarily handled since it's a draft but the default
handling is the same as 'I' >= 2.1 because non-draft 'E' extension
does not have 'I' version 2.0 subsets. */
if (riscv_is_subset_of_i_2p0 (subset))
{
riscv_subset_t *ext_i;
if (riscv_lookup_subset (rps->subset_list, "i", &ext_i)
&& (ext_i->major_version < 2
|| (ext_i->major_version == 2 && ext_i->minor_version < 1)))
handle_subset_of_i_2p0 = true;
}

if (major_version == RISCV_UNKNOWN_VERSION
|| minor_version == RISCV_UNKNOWN_VERSION)
if (!handle_subset_of_i_2p0
&& (major_version == RISCV_UNKNOWN_VERSION
|| minor_version == RISCV_UNKNOWN_VERSION))
riscv_get_default_ext_version (rps->isa_spec, subset,
&major_version, &minor_version);

Expand All @@ -1677,9 +1714,9 @@ 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. */
else if (strcmp (subset, "zicsr") != 0
&& strcmp (subset, "zifencei") != 0)
/* Allow old ISA spec (version 2.2) can recognize extensions
effectively split from the base 'I' extension version 2.0. */
else if (!riscv_is_subset_of_i_2p0 (subset))
rps->error_handler
(_("cannot find default versions of the ISA extension `%s'"),
subset);
Expand Down Expand Up @@ -2389,6 +2426,9 @@ 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:
/* Instead of 'Zicntr', query for 'I' for compatibility. */
return riscv_subset_supports (rps, "i");
case INSN_CLASS_ZICOND:
return riscv_subset_supports (rps, "zicond");
case INSN_CLASS_ZICSR:
Expand Down Expand Up @@ -2592,6 +2632,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
25 changes: 25 additions & 0 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 Down Expand Up @@ -1033,6 +1037,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 Down Expand Up @@ -2611,6 +2627,15 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
insn_with_csr = false;
}

/* Check if we are using a 'Zicntr' pseudoinstruction
without the 'Zicntr' extension. */
if (insn->insn_class == INSN_CLASS_ZICNTR
&& !riscv_subset_supports (&riscv_rps_as, "zicntr"))
{
as_warn (_("`%s' needs `zicntr' extension"),
insn->name);
}

/* The (segmant) load and store with EEW 64 cannot be used
when zve32x is enabled. */
if (ip->insn_mo->pinfo & INSN_V_EEW64
Expand Down
2 changes: 1 addition & 1 deletion gas/testsuite/gas/riscv/csr-insns-pseudo-noalias.d
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#source: csr-insns-pseudo.s
#as: -march=rv32if
#as: -march=rv32if_zicntr
#objdump: -dr -Mno-aliases

.*:[ ]+file format .*
Expand Down
37 changes: 37 additions & 0 deletions gas/testsuite/gas/riscv/csr-insns-pseudo-nozicntr.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#source: csr-insns-pseudo.s
#as: -march=rv32i2p1_f2p2
#warning_output: csr-insns-pseudo-nozicntr.l
#objdump: -dr

.*:[ ]+file format .*


Disassembly of section .text:

0+000 <pseudo_csr_insn>:
[ ]+[0-9a-f]+:[ ]+000022f3[ ]+csrr[ ]+t0,ustatus
[ ]+[0-9a-f]+:[ ]+00029073[ ]+csrw[ ]+ustatus,t0
[ ]+[0-9a-f]+:[ ]+0002a073[ ]+csrs[ ]+ustatus,t0
[ ]+[0-9a-f]+:[ ]+0002b073[ ]+csrc[ ]+ustatus,t0
[ ]+[0-9a-f]+:[ ]+000fd073[ ]+csrwi[ ]+ustatus,31
[ ]+[0-9a-f]+:[ ]+000fe073[ ]+csrsi[ ]+ustatus,31
[ ]+[0-9a-f]+:[ ]+000ff073[ ]+csrci[ ]+ustatus,31
[ ]+[0-9a-f]+:[ ]+c00022f3[ ]+rdcycle[ ]+t0
[ ]+[0-9a-f]+:[ ]+c01022f3[ ]+rdtime[ ]+t0
[ ]+[0-9a-f]+:[ ]+c02022f3[ ]+rdinstret[ ]+t0
[ ]+[0-9a-f]+:[ ]+c80022f3[ ]+rdcycleh[ ]+t0
[ ]+[0-9a-f]+:[ ]+c81022f3[ ]+rdtimeh[ ]+t0
[ ]+[0-9a-f]+:[ ]+c82022f3[ ]+rdinstreth[ ]+t0
[ ]+[0-9a-f]+:[ ]+003022f3[ ]+frcsr[ ]+t0
[ ]+[0-9a-f]+:[ ]+003392f3[ ]+fscsr[ ]+t0,t2
[ ]+[0-9a-f]+:[ ]+00339073[ ]+fscsr[ ]+t2
[ ]+[0-9a-f]+:[ ]+002022f3[ ]+frrm[ ]+t0
[ ]+[0-9a-f]+:[ ]+002312f3[ ]+fsrm[ ]+t0,t1
[ ]+[0-9a-f]+:[ ]+00231073[ ]+fsrm[ ]+t1
[ ]+[0-9a-f]+:[ ]+002fd2f3[ ]+fsrmi[ ]+t0,31
[ ]+[0-9a-f]+:[ ]+002fd073[ ]+fsrmi[ ]+zero,31
[ ]+[0-9a-f]+:[ ]+001022f3[ ]+frflags[ ]+t0
[ ]+[0-9a-f]+:[ ]+001312f3[ ]+fsflags[ ]+t0,t1
[ ]+[0-9a-f]+:[ ]+00131073[ ]+fsflags[ ]+t1
[ ]+[0-9a-f]+:[ ]+001fd2f3[ ]+fsflagsi[ ]+t0,31
[ ]+[0-9a-f]+:[ ]+001fd073[ ]+fsflagsi[ ]+zero,31
7 changes: 7 additions & 0 deletions gas/testsuite/gas/riscv/csr-insns-pseudo-nozicntr.l
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.*Assembler messages:
.*Warning: `rdcycle' needs `zicntr' extension
.*Warning: `rdtime' needs `zicntr' extension
.*Warning: `rdinstret' needs `zicntr' extension
.*Warning: `rdcycleh' needs `zicntr' extension
.*Warning: `rdtimeh' needs `zicntr' extension
.*Warning: `rdinstreth' needs `zicntr' extension
2 changes: 1 addition & 1 deletion gas/testsuite/gas/riscv/csr-insns-pseudo-zfinx.d
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#source: csr-insns-pseudo.s
#as: -march=rv32i_zfinx
#as: -march=rv32i_zicntr_zfinx
#objdump: -dr

.*:[ ]+file format .*
Expand Down
2 changes: 1 addition & 1 deletion gas/testsuite/gas/riscv/csr-insns-pseudo.d
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#source: csr-insns-pseudo.s
#as: -march=rv32if
#as: -march=rv32if_zicntr
#objdump: -dr

.*:[ ]+file format .*
Expand Down
3 changes: 2 additions & 1 deletion gas/testsuite/gas/riscv/csr-insns-pseudo.s
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ pseudo_csr_insn:
csrsi 0x0, 31
csrci 0x0, 31

# Zicntr
rdcycle t0
rdtime t0
rdinstret t0

# rv32i-ext
# Zicntr (RV32)
rdcycleh t0
rdtimeh t0
rdinstreth t0
Expand Down
2 changes: 1 addition & 1 deletion gas/testsuite/gas/riscv/csr-insns-read-only.d
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#as: -march=rv32if -mcsr-check -mpriv-spec=1.11
#as: -march=rv32if_zicntr -mcsr-check -mpriv-spec=1.11
#source: csr-insns-read-only.s
#warning_output: csr-insns-read-only.l
2 changes: 1 addition & 1 deletion gas/testsuite/gas/riscv/csr-version-1p10.d
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#as: -march=rv64i_zicsr -mcsr-check -mpriv-spec=1.10
#as: -march=rv64i2p1_zicsr2p0 -mcsr-check -mpriv-spec=1.10
#source: csr.s
#warning_output: csr-version-1p10.l
#objdump: -dr -Mpriv-spec=1.10
Expand Down
Loading

0 comments on commit a155952

Please sign in to comment.