Skip to content

Commit a155952

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 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.
1 parent 0e17d3f commit a155952

22 files changed

+1224
-87
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=rv32i2p1_f2p2
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

gas/testsuite/gas/riscv/csr-version-1p10.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#as: -march=rv64i_zicsr -mcsr-check -mpriv-spec=1.10
1+
#as: -march=rv64i2p1_zicsr2p0 -mcsr-check -mpriv-spec=1.10
22
#source: csr.s
33
#warning_output: csr-version-1p10.l
44
#objdump: -dr -Mpriv-spec=1.10

0 commit comments

Comments
 (0)