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.

To preserve maximum compatibility, this commit implements as follows:

*   For RISC-V ISA version 20191213 or less (all current non-draft ones),
    imply counter extensions from 'I' and DO NOT imply the 'Zicsr' extension
    from counter extensions.  We also suppress outputting the existence of
    counter extensions unless the version number is explicitly specified.
*   For future ratified ISAs, leave two options (each require minor edits):
    *   Continue previous behaviors or
    *   DO NOT imply counter extensions from 'I'.  DO imply the 'Zicsr'
        extension from counter extensions.  DO NOT suppress outputting the
        existence of such counter extensions by having a known
        version number (version 2.0 or [though unlikely] later).
        Make small changes to the disassembler to keep compatibility when
        disassembling old files.

bfd/ChangeLog:

	* elfxx-riscv.c (check_implicit_compat_counter_from_i): New function
	for counter compatibility from 'I' to counter extensions.
	(check_implicit_compat_counter_to_zicsr): New function for counter
	compatibility from counter extensions to the 'Zicsr' extension.
	(riscv_implicit_subsets): Add implications related to counter
	extensions with compatibility measures.
	(riscv_supported_std_z_ext): Add 'Zicntr' and 'Zihpm' extensions.
	But make version "unknown" to suppress outputting implicit
	dependencies on older ISAs.
	(riscv_parse_add_subset): Add "zicntr" and "zihpm" to exceptions
	to recognize on older ISAs if there's no version number.
	(riscv_multi_subset_supports): Add support for 'Zicntr'.
	(riscv_multi_subset_supports_ext): Likewise.

gas/ChangeLog:

	* config/tc-riscv.c (enum riscv_csr_class): Add CSR classes for
	'Zicntr' and 'Zihpm' extensions.
	(riscv_csr_address): Add handling for new CSR classes.
	* testsuite/gas/riscv/march-imply-i.s: Add 'Zicntr' instructions.

include/ChangeLog:

	* opcode/riscv-opc.h: Change CSR classes for 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 19, 2023
1 parent 36579cc commit 1ae2bb7
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 163 deletions.
49 changes: 47 additions & 2 deletions bfd/elfxx-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1099,13 +1099,41 @@ check_implicit_for_i (riscv_parse_subset_t *rps ATTRIBUTE_UNUSED,
&& subset->minor_version < 1));
}

/* 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)
{
/* 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 @@ -1191,6 +1219,8 @@ static riscv_implicit_subset_t 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},
{"smcntrpmf", "zicsr", check_implicit_always},
{"smstateen", "ssstateen", check_implicit_always},
Expand Down Expand Up @@ -1260,13 +1290,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 @@ -1686,9 +1724,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 @@ -2398,6 +2439,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 @@ -2601,6 +2644,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
16 changes: 16 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
8 changes: 8 additions & 0 deletions gas/testsuite/gas/riscv/march-imply-i.s
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,11 @@ target:

# zifencei
fence.i

# zicntr
rdcycle t0
rdtime t0
rdinstret t0
rdcycleh t0
rdtimeh t0
rdinstreth t0
Loading

0 comments on commit 1ae2bb7

Please sign in to comment.