Skip to content

Commit

Permalink
RISC-V: Implement extension variants
Browse files Browse the repository at this point in the history
If there is a instruction with multiple variants with different
requirements and the assembler fails to parse all variants, there is a case
that needs to refer ALL variants to generate proper diagnostics.

If an instruction with INSN_HAS_EXT_VARS fails, the assembler now has a
chance to modify the instruction class for proper diagnostics.  A typical
use of this feature is to select _wider_ instruction class when necessary.

gas/ChangeLog:

	* config/tc-riscv.c (riscv_ip): Add empty INSN_HAS_EXT_VARS
	handling.

include/ChangeLog:

	* opcode/riscv.h (INSN_HAS_EXT_VARS): New.
  • Loading branch information
a4lg committed Sep 30, 2022
1 parent 1588edc commit 9a5d8d7
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 2 deletions.
27 changes: 25 additions & 2 deletions gas/config/tc-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -2376,6 +2376,7 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
unsigned int regno;
const struct percent_op_match *p;
struct riscv_ip_error error;
enum riscv_insn_class insn_class;
error.msg = "unrecognized opcode";
error.statement = str;
error.missing_ext = NULL;
Expand All @@ -2402,8 +2403,30 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,

if (!riscv_multi_subset_supports (&riscv_rps_as, insn->insn_class))
{
error.missing_ext = riscv_multi_subset_supports_ext (&riscv_rps_as,
insn->insn_class);
insn_class = insn->insn_class;
if (insn->pinfo != INSN_MACRO && insn->pinfo & INSN_HAS_EXT_VARS)
{
/* If an instruction is not supported for example, there is a
case where some extensions (that is not related to the last
"same name" variants) should be printed for diagnostics.
For instance, if parsing "fmin.d" fails on both 'D' and
'Zdinx' variants, we have to require 'D' or 'Zdinx', not just
'Zdinx', the last "fmin.d" variant in riscv_opcodes.
For instructions with INSN_HAS_EXT_VARS, we should rewrite the
instruction class (from a specific one to a generic one)
to provide proper error output.
*/
switch (insn_class)
{
default:
break;
}
}
if (!riscv_multi_subset_supports (&riscv_rps_as, insn_class))
error.missing_ext = riscv_multi_subset_supports_ext (&riscv_rps_as,
insn_class);
continue;
}

Expand Down
5 changes: 5 additions & 0 deletions include/opcode/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,11 @@ struct riscv_opcode
#define INSN_8_BYTE 0x00000040
#define INSN_16_BYTE 0x00000050

/* Instruction has different entry that shares the name but differs
in extension requirements (extension variants). Those instructions must be
taken care if we should print an "extension required" error. */
#define INSN_HAS_EXT_VARS 0x00000080

/* Instruction is actually a macro. It should be ignored by the
disassembler, and requires special treatment by the assembler. */
#define INSN_MACRO 0xffffffff
Expand Down

0 comments on commit 9a5d8d7

Please sign in to comment.