Skip to content

Commit 872554c

Browse files
committed
RISC-V: Add 'Zicntr' and 'Zihpm' support with compatibility measures
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 'Zicntr' pseudoinstructions are 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.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/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.
1 parent 4a6daab commit 872554c

16 files changed

+1217
-80
lines changed

bfd/elfxx-riscv.c

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,6 +1097,8 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
10971097
{"e", "i", check_implicit_always},
10981098
{"i", "zicsr", check_implicit_for_i},
10991099
{"i", "zifencei", check_implicit_for_i},
1100+
{"i", "zicntr", check_implicit_for_i},
1101+
{"i", "zihpm", check_implicit_for_i},
11001102
{"g", "i", check_implicit_always},
11011103
{"g", "m", check_implicit_always},
11021104
{"g", "a", check_implicit_always},
@@ -1148,6 +1150,8 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
11481150
{"zhinx", "zhinxmin", check_implicit_always},
11491151
{"zhinxmin", "zfinx", check_implicit_always},
11501152
{"zfinx", "zicsr", check_implicit_always},
1153+
{"zicntr", "zicsr", check_implicit_always},
1154+
{"zihpm", "zicsr", check_implicit_always},
11511155
{"zk", "zkn", check_implicit_always},
11521156
{"zk", "zkr", check_implicit_always},
11531157
{"zk", "zkt", check_implicit_always},
@@ -1251,13 +1255,17 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] =
12511255
{"zicbom", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
12521256
{"zicbop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
12531257
{"zicboz", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1258+
{"zicntr", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
12541259
{"zicond", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
12551260
{"zicsr", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
12561261
{"zicsr", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1262+
{"zicsr", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
12571263
{"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
12581264
{"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
1265+
{"zifencei", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
12591266
{"zihintntl", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
12601267
{"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
1268+
{"zihpm", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
12611269
{"zmmul", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
12621270
{"zawrs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
12631271
{"zfa", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
@@ -1649,6 +1657,18 @@ riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec,
16491657
}
16501658
}
16511659

1660+
/* Check if the subset is one of the extensions split from
1661+
the 'I' extension version 2.0. */
1662+
1663+
static bool
1664+
riscv_is_subset_of_i_2p0 (const char *subset)
1665+
{
1666+
return (strcmp (subset, "zicsr") == 0
1667+
|| strcmp (subset, "zifencei") == 0
1668+
|| strcmp (subset, "zicntr") == 0
1669+
|| strcmp (subset, "zihpm") == 0);
1670+
}
1671+
16521672
/* Find the default versions for the extension before adding them to
16531673
the subset list, if their versions are RISCV_UNKNOWN_VERSION.
16541674
Afterwards, report errors if we can not find their default versions. */
@@ -1662,9 +1682,26 @@ riscv_parse_add_subset (riscv_parse_subset_t *rps,
16621682
{
16631683
int major_version = major;
16641684
int minor_version = minor;
1685+
bool handle_subset_of_i_2p0 = false;
1686+
1687+
/* If a subset of the 'I' extension version 2.0 is being added,
1688+
check the version of 'I' and allow its version unknown when the
1689+
'I' extension version is less than 2.1.
1690+
Draft 'E' is arbitrarily handled since it's a draft but the default
1691+
handling is the same as 'I' >= 2.1 because non-draft 'E' extension
1692+
does not have 'I' version 2.0 subsets. */
1693+
if (riscv_is_subset_of_i_2p0 (subset))
1694+
{
1695+
riscv_subset_t *ext_i;
1696+
if (riscv_lookup_subset (rps->subset_list, "i", &ext_i)
1697+
&& (ext_i->major_version < 2
1698+
|| (ext_i->major_version == 2 && ext_i->minor_version < 1)))
1699+
handle_subset_of_i_2p0 = true;
1700+
}
16651701

1666-
if (major_version == RISCV_UNKNOWN_VERSION
1667-
|| minor_version == RISCV_UNKNOWN_VERSION)
1702+
if (!handle_subset_of_i_2p0
1703+
&& (major_version == RISCV_UNKNOWN_VERSION
1704+
|| minor_version == RISCV_UNKNOWN_VERSION))
16681705
riscv_get_default_ext_version (rps->isa_spec, subset,
16691706
&major_version, &minor_version);
16701707

@@ -1677,9 +1714,9 @@ riscv_parse_add_subset (riscv_parse_subset_t *rps,
16771714
rps->error_handler
16781715
(_("x ISA extension `%s' must be set with the versions"),
16791716
subset);
1680-
/* Allow old ISA spec can recognize zicsr and zifencei. */
1681-
else if (strcmp (subset, "zicsr") != 0
1682-
&& strcmp (subset, "zifencei") != 0)
1717+
/* Allow old ISA spec (version 2.2) can recognize extensions
1718+
effectively split from the base 'I' extension version 2.0. */
1719+
else if (!riscv_is_subset_of_i_2p0 (subset))
16831720
rps->error_handler
16841721
(_("cannot find default versions of the ISA extension `%s'"),
16851722
subset);
@@ -2389,6 +2426,9 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
23892426
return riscv_subset_supports (rps, "zicbop");
23902427
case INSN_CLASS_ZICBOZ:
23912428
return riscv_subset_supports (rps, "zicboz");
2429+
case INSN_CLASS_ZICNTR:
2430+
/* Instead of 'Zicntr', query for 'I' for compatibility. */
2431+
return riscv_subset_supports (rps, "i");
23922432
case INSN_CLASS_ZICOND:
23932433
return riscv_subset_supports (rps, "zicond");
23942434
case INSN_CLASS_ZICSR:
@@ -2592,6 +2632,8 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
25922632
return "zicbop";
25932633
case INSN_CLASS_ZICBOZ:
25942634
return "zicboz";
2635+
case INSN_CLASS_ZICNTR:
2636+
return "zicntr";
25952637
case INSN_CLASS_ZICOND:
25962638
return "zicond";
25972639
case INSN_CLASS_ZICSR:

gas/config/tc-riscv.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ enum riscv_csr_class
6666

6767
CSR_CLASS_I,
6868
CSR_CLASS_I_32, /* rv32 only */
69+
CSR_CLASS_ZICNTR, /* basic hardware perf counter */
70+
CSR_CLASS_ZICNTR_32, /* basic hardware perf counter, rv32 only */
71+
CSR_CLASS_ZIHPM, /* additional hardware perf counter */
72+
CSR_CLASS_ZIHPM_32, /* additional hardware perf counter, rv32 only */
6973
CSR_CLASS_F, /* f-ext only */
7074
CSR_CLASS_ZKR, /* zkr only */
7175
CSR_CLASS_V, /* rvv only */
@@ -1033,6 +1037,18 @@ riscv_csr_address (const char *csr_name,
10331037
need_check_version = true;
10341038
extension = "i";
10351039
break;
1040+
case CSR_CLASS_ZICNTR_32:
1041+
is_rv32_only = true;
1042+
/* Fall through. */
1043+
case CSR_CLASS_ZICNTR:
1044+
extension = "zicntr";
1045+
break;
1046+
case CSR_CLASS_ZIHPM_32:
1047+
is_rv32_only = true;
1048+
/* Fall through. */
1049+
case CSR_CLASS_ZIHPM:
1050+
extension = "zihpm";
1051+
break;
10361052
case CSR_CLASS_H_32:
10371053
is_rv32_only = true;
10381054
/* Fall through. */
@@ -2611,6 +2627,15 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
26112627
insn_with_csr = false;
26122628
}
26132629

2630+
/* Check if we are using a 'Zicntr' pseudoinstruction
2631+
without the 'Zicntr' extension. */
2632+
if (insn->insn_class == INSN_CLASS_ZICNTR
2633+
&& !riscv_subset_supports (&riscv_rps_as, "zicntr"))
2634+
{
2635+
as_warn (_("`%s' needs `zicntr' extension"),
2636+
insn->name);
2637+
}
2638+
26142639
/* The (segmant) load and store with EEW 64 cannot be used
26152640
when zve32x is enabled. */
26162641
if (ip->insn_mo->pinfo & INSN_V_EEW64

gas/testsuite/gas/riscv/csr-insns-pseudo-noalias.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#source: csr-insns-pseudo.s
2-
#as: -march=rv32if
2+
#as: -march=rv32if_zicntr
33
#objdump: -dr -Mno-aliases
44

55
.*:[ ]+file format .*
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#source: csr-insns-pseudo.s
2+
#as: -march=rv32if
3+
#warning_output: csr-insns-pseudo-nozicntr.l
4+
#objdump: -dr
5+
6+
.*:[ ]+file format .*
7+
8+
9+
Disassembly of section .text:
10+
11+
0+000 <pseudo_csr_insn>:
12+
[ ]+[0-9a-f]+:[ ]+000022f3[ ]+csrr[ ]+t0,ustatus
13+
[ ]+[0-9a-f]+:[ ]+00029073[ ]+csrw[ ]+ustatus,t0
14+
[ ]+[0-9a-f]+:[ ]+0002a073[ ]+csrs[ ]+ustatus,t0
15+
[ ]+[0-9a-f]+:[ ]+0002b073[ ]+csrc[ ]+ustatus,t0
16+
[ ]+[0-9a-f]+:[ ]+000fd073[ ]+csrwi[ ]+ustatus,31
17+
[ ]+[0-9a-f]+:[ ]+000fe073[ ]+csrsi[ ]+ustatus,31
18+
[ ]+[0-9a-f]+:[ ]+000ff073[ ]+csrci[ ]+ustatus,31
19+
[ ]+[0-9a-f]+:[ ]+c00022f3[ ]+rdcycle[ ]+t0
20+
[ ]+[0-9a-f]+:[ ]+c01022f3[ ]+rdtime[ ]+t0
21+
[ ]+[0-9a-f]+:[ ]+c02022f3[ ]+rdinstret[ ]+t0
22+
[ ]+[0-9a-f]+:[ ]+c80022f3[ ]+rdcycleh[ ]+t0
23+
[ ]+[0-9a-f]+:[ ]+c81022f3[ ]+rdtimeh[ ]+t0
24+
[ ]+[0-9a-f]+:[ ]+c82022f3[ ]+rdinstreth[ ]+t0
25+
[ ]+[0-9a-f]+:[ ]+003022f3[ ]+frcsr[ ]+t0
26+
[ ]+[0-9a-f]+:[ ]+003392f3[ ]+fscsr[ ]+t0,t2
27+
[ ]+[0-9a-f]+:[ ]+00339073[ ]+fscsr[ ]+t2
28+
[ ]+[0-9a-f]+:[ ]+002022f3[ ]+frrm[ ]+t0
29+
[ ]+[0-9a-f]+:[ ]+002312f3[ ]+fsrm[ ]+t0,t1
30+
[ ]+[0-9a-f]+:[ ]+00231073[ ]+fsrm[ ]+t1
31+
[ ]+[0-9a-f]+:[ ]+002fd2f3[ ]+fsrmi[ ]+t0,31
32+
[ ]+[0-9a-f]+:[ ]+002fd073[ ]+fsrmi[ ]+zero,31
33+
[ ]+[0-9a-f]+:[ ]+001022f3[ ]+frflags[ ]+t0
34+
[ ]+[0-9a-f]+:[ ]+001312f3[ ]+fsflags[ ]+t0,t1
35+
[ ]+[0-9a-f]+:[ ]+00131073[ ]+fsflags[ ]+t1
36+
[ ]+[0-9a-f]+:[ ]+001fd2f3[ ]+fsflagsi[ ]+t0,31
37+
[ ]+[0-9a-f]+:[ ]+001fd073[ ]+fsflagsi[ ]+zero,31
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.*Assembler messages:
2+
.*Warning: `rdcycle' needs `zicntr' extension
3+
.*Warning: `rdtime' needs `zicntr' extension
4+
.*Warning: `rdinstret' needs `zicntr' extension
5+
.*Warning: `rdcycleh' needs `zicntr' extension
6+
.*Warning: `rdtimeh' needs `zicntr' extension
7+
.*Warning: `rdinstreth' needs `zicntr' extension

gas/testsuite/gas/riscv/csr-insns-pseudo-zfinx.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#source: csr-insns-pseudo.s
2-
#as: -march=rv32i_zfinx
2+
#as: -march=rv32i_zicntr_zfinx
33
#objdump: -dr
44

55
.*:[ ]+file format .*

gas/testsuite/gas/riscv/csr-insns-pseudo.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#source: csr-insns-pseudo.s
2-
#as: -march=rv32if
2+
#as: -march=rv32if_zicntr
33
#objdump: -dr
44

55
.*:[ ]+file format .*

gas/testsuite/gas/riscv/csr-insns-pseudo.s

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ pseudo_csr_insn:
88
csrsi 0x0, 31
99
csrci 0x0, 31
1010

11+
# Zicntr
1112
rdcycle t0
1213
rdtime t0
1314
rdinstret t0
1415

15-
# rv32i-ext
16+
# Zicntr (RV32)
1617
rdcycleh t0
1718
rdtimeh t0
1819
rdinstreth t0
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
#as: -march=rv32if -mcsr-check -mpriv-spec=1.11
1+
#as: -march=rv32if_zicntr -mcsr-check -mpriv-spec=1.11
22
#source: csr-insns-read-only.s
33
#warning_output: csr-insns-read-only.l

0 commit comments

Comments
 (0)