RISC-V: Add support for the Zfa extension

This patch adds support for the RISC-V Zfa extension,
which introduces additional floating-point instructions:
* fli (load-immediate) with pre-defined immediates
* fminm/fmaxm (like fmin/fmax but with different NaN behaviour)
* fround/froundmx (round to integer)
* fcvtmod.w.d (Modular Convert-to-Integer)
* fmv* to access high bits of FP registers in case XLEN < FLEN
* fleq/fltq (quiet comparison instructions)

Zfa defines its instructions in combination with the following
extensions:
* single-precision floating-point (F)
* double-precision floating-point (D)
* quad-precision floating-point (Q)
* half-precision floating-point (Zfh)

This patch is based on an earlier version from Tsukasa OI:
  https://sourceware.org/pipermail/binutils/2022-September/122939.html
Most significant change to that commit is the switch from the rs1-field
value to the actual floating-point value in the last operand of the fli*
instructions. Everything that strtof() can parse is accepted and
the '%a' printf specifier is used to output hex floating-point literals
in the disassembly.

The Zfa specification is frozen (and has passed public review).  It is
available as a chapter in "The RISC-V Instruction Set Manual: Volume 1":
  https://github.com/riscv/riscv-isa-manual/releases

bfd/ChangeLog:

	* elfxx-riscv.c (riscv_multi_subset_supports): Add instruction
	class support for 'Zfa' extension.
	(riscv_multi_subset_supports_ext): Likewise.
	(riscv_implicit_subsets): Add 'Zfa' -> 'F' dependency.

gas/ChangeLog:

	* config/tc-riscv.c (flt_lookup): New helper to lookup a float value
	in an array.
	(validate_riscv_insn): Add 'Wfv' as new format string directive.
	(riscv_ip): Likewise.
	* doc/c-riscv.texi: Add floating-point chapter and describe
	limiations of the Zfa FP literal parsing.
	* testsuite/gas/riscv/zfa-32.d: New test.
	* testsuite/gas/riscv/zfa-32.s: New test.
	* testsuite/gas/riscv/zfa-64.d: New test.
	* testsuite/gas/riscv/zfa-64.s: New test.
	* testsuite/gas/riscv/zfa-fail.d: New test.
	* testsuite/gas/riscv/zfa-fail.l: New test.
	* testsuite/gas/riscv/zfa-fail.s: New test.
	* testsuite/gas/riscv/zfa.d: New test.
	* testsuite/gas/riscv/zfa.s: New test.
	* testsuite/gas/riscv/zfa.s: New test.

	* opcode/riscv-opc.h (MATCH_FLI_H): New.
	(MASK_FLI_H): New.
	(MATCH_FMINM_H): New.
	(MASK_FMINM_H): New.
	(MATCH_FMAXM_H): New.
	(MASK_FMAXM_H): New.
	(MATCH_FROUND_H): New.
	(MASK_FROUND_H): New.
	(MATCH_FROUNDNX_H): New.
	(MASK_FROUNDNX_H): New.
	(MATCH_FLTQ_H): New.
	(MASK_FLTQ_H): New.
	(MATCH_FLEQ_H): New.
	(MASK_FLEQ_H): New.
	(MATCH_FLI_S): New.
	(MASK_FLI_S): New.
	(MATCH_FMINM_S): New.
	(MASK_FMINM_S): New.
	(MATCH_FMAXM_S): New.
	(MASK_FMAXM_S): New.
	(MATCH_FROUND_S): New.
	(MASK_FROUND_S): New.
	(MATCH_FROUNDNX_S): New.
	(MASK_FROUNDNX_S): New.
	(MATCH_FLTQ_S): New.
	(MASK_FLTQ_S): New.
	(MATCH_FLEQ_S): New.
	(MASK_FLEQ_S): New.
	(MATCH_FLI_D): New.
	(MASK_FLI_D): New.
	(MATCH_FMINM_D): New.
	(MASK_FMINM_D): New.
	(MATCH_FMAXM_D): New.
	(MASK_FMAXM_D): New.
	(MATCH_FROUND_D): New.
	(MASK_FROUND_D): New.
	(MATCH_FROUNDNX_D): New.
	(MASK_FROUNDNX_D): New.
	(MATCH_FLTQ_D): New.
	(MASK_FLTQ_D): New.
	(MATCH_FLEQ_D): New.
	(MASK_FLEQ_D): New.
	(MATCH_FLI_Q): New.
	(MASK_FLI_Q): New.
	(MATCH_FMINM_Q): New.
	(MASK_FMINM_Q): New.
	(MATCH_FMAXM_Q): New.
	(MASK_FMAXM_Q): New.
	(MATCH_FROUND_Q): New.
	(MASK_FROUND_Q): New.
	(MATCH_FROUNDNX_Q): New.
	(MASK_FROUNDNX_Q): New.
	(MATCH_FLTQ_Q): New.
	(MASK_FLTQ_Q): New.
	(MATCH_FLEQ_Q): New.
	(MASK_FLEQ_Q): New.
	(MATCH_FCVTMOD_W_D): New.
	(MASK_FCVTMOD_W_D): New.
	(MATCH_FMVH_X_D): New.
	(MASK_FMVH_X_D): New.
	(MATCH_FMVH_X_Q): New.
	(MASK_FMVH_X_Q): New.
	(MATCH_FMVP_D_X): New.
	(MASK_FMVP_D_X): New.
	(MATCH_FMVP_Q_X): New.
	(MASK_FMVP_Q_X): New.
	(DECLARE_INSN): New.
	* opcode/riscv.h (enum riscv_insn_class): Add instruction
	classes for the Zfa extension.

opcodes/ChangeLog:

	* riscv-dis.c (print_insn_args): Add support for
	new format string directive 'Wfv'.
	* riscv-opc.c: Add Zfa instructions.

Co-Developed-by: Tsukasa OI <research_trasio@irq.a4lg.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
Co-Developed-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
Christoph Müllner
2023-03-27 09:27:31 +02:00
committed by Philipp Tomsich
parent 3713e829be
commit 1f3fc45bdd
16 changed files with 550 additions and 0 deletions

View File

@ -419,6 +419,72 @@
#define MASK_FCVT_Q_L 0xfff0007f
#define MATCH_FCVT_Q_LU 0xd6300053
#define MASK_FCVT_Q_LU 0xfff0007f
#define MATCH_FLI_H 0xf4100053
#define MASK_FLI_H 0xfff0707f
#define MATCH_FMINM_H 0x2c002053
#define MASK_FMINM_H 0xfe00707f
#define MATCH_FMAXM_H 0x2c003053
#define MASK_FMAXM_H 0xfe00707f
#define MATCH_FROUND_H 0x44400053
#define MASK_FROUND_H 0xfff0007f
#define MATCH_FROUNDNX_H 0x44500053
#define MASK_FROUNDNX_H 0xfff0007f
#define MATCH_FLTQ_H 0xa4005053
#define MASK_FLTQ_H 0xfe00707f
#define MATCH_FLEQ_H 0xa4004053
#define MASK_FLEQ_H 0xfe00707f
#define MATCH_FLI_S 0xf0100053
#define MASK_FLI_S 0xfff0707f
#define MATCH_FMINM_S 0x28002053
#define MASK_FMINM_S 0xfe00707f
#define MATCH_FMAXM_S 0x28003053
#define MASK_FMAXM_S 0xfe00707f
#define MATCH_FROUND_S 0x40400053
#define MASK_FROUND_S 0xfff0007f
#define MATCH_FROUNDNX_S 0x40500053
#define MASK_FROUNDNX_S 0xfff0007f
#define MATCH_FLTQ_S 0xa0005053
#define MASK_FLTQ_S 0xfe00707f
#define MATCH_FLEQ_S 0xa0004053
#define MASK_FLEQ_S 0xfe00707f
#define MATCH_FLI_D 0xf2100053
#define MASK_FLI_D 0xfff0707f
#define MATCH_FMINM_D 0x2a002053
#define MASK_FMINM_D 0xfe00707f
#define MATCH_FMAXM_D 0x2a003053
#define MASK_FMAXM_D 0xfe00707f
#define MATCH_FROUND_D 0x42400053
#define MASK_FROUND_D 0xfff0007f
#define MATCH_FROUNDNX_D 0x42500053
#define MASK_FROUNDNX_D 0xfff0007f
#define MATCH_FLTQ_D 0xa2005053
#define MASK_FLTQ_D 0xfe00707f
#define MATCH_FLEQ_D 0xa2004053
#define MASK_FLEQ_D 0xfe00707f
#define MATCH_FLI_Q 0xf6100053
#define MASK_FLI_Q 0xfff0707f
#define MATCH_FMINM_Q 0x2e002053
#define MASK_FMINM_Q 0xfe00707f
#define MATCH_FMAXM_Q 0x2e003053
#define MASK_FMAXM_Q 0xfe00707f
#define MATCH_FROUND_Q 0x46400053
#define MASK_FROUND_Q 0xfff0007f
#define MATCH_FROUNDNX_Q 0x46500053
#define MASK_FROUNDNX_Q 0xfff0007f
#define MATCH_FLTQ_Q 0xa6005053
#define MASK_FLTQ_Q 0xfe00707f
#define MATCH_FLEQ_Q 0xa6004053
#define MASK_FLEQ_Q 0xfe00707f
#define MATCH_FCVTMOD_W_D 0xc2801053
#define MASK_FCVTMOD_W_D 0xfff0707f
#define MATCH_FMVH_X_D 0xe2100053
#define MASK_FMVH_X_D 0xfff0707f
#define MATCH_FMVH_X_Q 0xe6100053
#define MASK_FMVH_X_Q 0xfff0707f
#define MATCH_FMVP_D_X 0xb2000053
#define MASK_FMVP_D_X 0xfe00707f
#define MATCH_FMVP_Q_X 0xb6000053
#define MASK_FMVP_Q_X 0xfe00707f
#define MATCH_CLZ 0x60001013
#define MASK_CLZ 0xfff0707f
#define MATCH_CTZ 0x60101013
@ -2991,6 +3057,39 @@ DECLARE_INSN(fcvt_q_w, MATCH_FCVT_Q_W, MASK_FCVT_Q_W)
DECLARE_INSN(fcvt_q_wu, MATCH_FCVT_Q_WU, MASK_FCVT_Q_WU)
DECLARE_INSN(fcvt_q_l, MATCH_FCVT_Q_L, MASK_FCVT_Q_L)
DECLARE_INSN(fcvt_q_lu, MATCH_FCVT_Q_LU, MASK_FCVT_Q_LU)
DECLARE_INSN(fli_h, MATCH_FLI_H, MASK_FLI_H)
DECLARE_INSN(fminm_h, MATCH_FMINM_H, MASK_FMINM_H)
DECLARE_INSN(fmaxm_h, MATCH_FMAXM_H, MASK_FMAXM_H)
DECLARE_INSN(fround_h, MATCH_FROUND_H, MASK_FROUND_H)
DECLARE_INSN(fround_nx_h, MATCH_FROUNDNX_H, MASK_FROUNDNX_H)
DECLARE_INSN(fltq_h, MATCH_FLTQ_H, MASK_FLTQ_H)
DECLARE_INSN(fleq_h, MATCH_FLEQ_H, MASK_FLEQ_H)
DECLARE_INSN(fli_s, MATCH_FLI_S, MASK_FLI_S)
DECLARE_INSN(fminm_s, MATCH_FMINM_S, MASK_FMINM_S)
DECLARE_INSN(fmaxm_s, MATCH_FMAXM_S, MASK_FMAXM_S)
DECLARE_INSN(fround_s, MATCH_FROUND_S, MASK_FROUND_S)
DECLARE_INSN(fround_nx_s, MATCH_FROUNDNX_S, MASK_FROUNDNX_S)
DECLARE_INSN(fltq_s, MATCH_FLTQ_S, MASK_FLTQ_S)
DECLARE_INSN(fleq_s, MATCH_FLEQ_S, MASK_FLEQ_S)
DECLARE_INSN(fli_d, MATCH_FLI_D, MASK_FLI_D)
DECLARE_INSN(fminm_d, MATCH_FMINM_D, MASK_FMINM_D)
DECLARE_INSN(fmaxm_d, MATCH_FMAXM_D, MASK_FMAXM_D)
DECLARE_INSN(fround_d, MATCH_FROUND_D, MASK_FROUND_D)
DECLARE_INSN(fround_nx_d, MATCH_FROUNDNX_D, MASK_FROUNDNX_D)
DECLARE_INSN(fltq_d, MATCH_FLTQ_D, MASK_FLTQ_D)
DECLARE_INSN(fleq_d, MATCH_FLEQ_D, MASK_FLEQ_D)
DECLARE_INSN(fli_q, MATCH_FLI_Q, MASK_FLI_Q)
DECLARE_INSN(fminm_q, MATCH_FMINM_Q, MASK_FMINM_Q)
DECLARE_INSN(fmaxm_q, MATCH_FMAXM_Q, MASK_FMAXM_Q)
DECLARE_INSN(fround_q, MATCH_FROUND_Q, MASK_FROUND_Q)
DECLARE_INSN(fround_nx_q, MATCH_FROUNDNX_Q, MASK_FROUNDNX_Q)
DECLARE_INSN(fltq_q, MATCH_FLTQ_Q, MASK_FLTQ_Q)
DECLARE_INSN(fleq_q, MATCH_FLEQ_Q, MASK_FLEQ_Q)
DECLARE_INSN(fcvtmod_w_d, MATCH_FCVTMOD_W_D, MASK_FCVTMOD_W_D)
DECLARE_INSN(fmvh_x_d, MATCH_FMVH_X_D, MASK_FMVH_X_D)
DECLARE_INSN(fmvh_x_q, MATCH_FMVH_X_Q, MASK_FMVH_X_Q)
DECLARE_INSN(fmvp_d_x, MATCH_FMVP_D_X, MASK_FMVP_D_X)
DECLARE_INSN(fmvp_q_x, MATCH_FMVP_Q_X, MASK_FMVP_Q_X)
DECLARE_INSN(clz, MATCH_CLZ, MASK_CLZ)
DECLARE_INSN(ctz, MATCH_CTZ, MASK_CTZ)
DECLARE_INSN(cpop, MATCH_CPOP, MASK_CPOP)

View File

@ -389,6 +389,10 @@ enum riscv_insn_class
INSN_CLASS_ZFHMIN_INX,
INSN_CLASS_ZFHMIN_AND_D_INX,
INSN_CLASS_ZFHMIN_AND_Q_INX,
INSN_CLASS_ZFA,
INSN_CLASS_D_AND_ZFA,
INSN_CLASS_Q_AND_ZFA,
INSN_CLASS_ZFH_AND_ZFA,
INSN_CLASS_ZBA,
INSN_CLASS_ZBB,
INSN_CLASS_ZBC,
@ -557,6 +561,8 @@ extern const char * const riscv_vsew[8];
extern const char * const riscv_vlmul[8];
extern const char * const riscv_vta[2];
extern const char * const riscv_vma[2];
extern const char * const riscv_fli_symval[32];
extern const float riscv_fli_numval[32];
extern const struct riscv_opcode riscv_opcodes[];
extern const struct riscv_opcode riscv_insn_types[];