Skip to content

Commit

Permalink
RISC-V: Validate Zdinx/Zqinx register pairs
Browse files Browse the repository at this point in the history
This commit adds floating point register number validation on
Zdinx/Zqinx extensions by separating handling on D/Q and Zdinx/Zqinx
extensions (per-xlen on Zdinx/Zqinx).

bfd/ChangeLog:

	* elfxx-riscv.c (riscv_multi_subset_supports): Reflect new
	instruction classes. (riscv_multi_subset_supports_ext): Reflect
	new instruction classes.

gas/ChangeLog:

	* config/tc-riscv.c (riscv_ip): Add handling for new instruction
	flag INSN_F_OR_X.

include/ChangeLog:

	* opcode/riscv.h (enum riscv_insn_class): Add INSN_CLASS_ZDINX
	and INSN_CLASS_ZQINX narrow instruction classes.
	(INSN_F_OR_X): New pinfo flag for better error handling.

opcodes/ChangeLog:

	* riscv-opc.c (MASK_RS3): New mask macro for RS3 field.
	(match_opcode_zdinx_rtype_g2, match_opcode_zdinx_rtype_g4,
	match_rs1_eq_rs2_zdinx_rtype_g2,
	match_rs1_eq_rs2_zdinx_rtype_g4,
	match_opcode_zdinx_r4type_g2, match_opcode_zdinx_r4type_g4,
	match_opcode_zdinx_itype_g1_2, match_opcode_zdinx_itype_g1_4,
	match_opcode_zdinx_itype_g2_1, match_opcode_zdinx_itype_g2_2,
	match_opcode_zdinx_itype_g2_4, match_opcode_zdinx_itype_g4_1,
	match_opcode_zdinx_itype_g4_2, match_opcode_zdinx_itype_g4_4,
	match_opcode_zdinx_cmp_g2, match_opcode_zdinx_cmp_g4): New
	instruction matching functions with register pair /
	quad-register group validation.
	(riscv_opcodes): Use new instruction classes, matching functions
	and the pinfo flag.
  • Loading branch information
a4lg committed Aug 9, 2022
1 parent f399f3b commit 8bf4fcd
Show file tree
Hide file tree
Showing 4 changed files with 470 additions and 108 deletions.
8 changes: 8 additions & 0 deletions bfd/elfxx-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -2356,6 +2356,10 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
&& riscv_subset_supports (rps, "q"))
|| (riscv_subset_supports (rps, "zhinxmin")
&& riscv_subset_supports (rps, "zqinx")));
case INSN_CLASS_ZDINX:
return riscv_subset_supports (rps, "zdinx");
case INSN_CLASS_ZQINX:
return riscv_subset_supports (rps, "zqinx");
case INSN_CLASS_ZBA:
return riscv_subset_supports (rps, "zba");
case INSN_CLASS_ZBB:
Expand Down Expand Up @@ -2489,6 +2493,10 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
return "zhinxmin";
else
return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
case INSN_CLASS_ZDINX:
return "zdinx";
case INSN_CLASS_ZQINX:
return "zqinx";
case INSN_CLASS_ZBA:
return "zba";
case INSN_CLASS_ZBB:
Expand Down
21 changes: 19 additions & 2 deletions gas/config/tc-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -2306,6 +2306,7 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
int argnum;
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 @@ -2332,8 +2333,24 @@ 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_F_OR_X)
switch (insn_class)
{
case INSN_CLASS_D:
case INSN_CLASS_ZDINX:
insn_class = INSN_CLASS_D_OR_ZDINX;
break;
case INSN_CLASS_Q:
case INSN_CLASS_ZQINX:
insn_class = INSN_CLASS_Q_OR_ZQINX;
break;
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
10 changes: 8 additions & 2 deletions include/opcode/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -368,8 +368,10 @@ enum riscv_insn_class
INSN_CLASS_ZIFENCEI,
INSN_CLASS_ZIHINTPAUSE,
INSN_CLASS_F_OR_ZFINX,
INSN_CLASS_D_OR_ZDINX,
INSN_CLASS_Q_OR_ZQINX,
INSN_CLASS_D_OR_ZDINX, /* Diagnostics only. */
INSN_CLASS_Q_OR_ZQINX, /* Diagnostics only. */
INSN_CLASS_ZDINX,
INSN_CLASS_ZQINX,
INSN_CLASS_ZFH_OR_ZHINX,
INSN_CLASS_ZFHMIN,
INSN_CLASS_ZFHMIN_OR_ZHINXMIN,
Expand Down Expand Up @@ -467,6 +469,10 @@ struct riscv_opcode
#define INSN_8_BYTE 0x00000040
#define INSN_16_BYTE 0x00000050

/* Instruction has different entry that shares the name but differs
in register operands (FPR or GPR) used. */
#define INSN_F_OR_X 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
Loading

0 comments on commit 8bf4fcd

Please sign in to comment.