From 1f3fc45bddc7147a2e59346a59290094137ef1e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20M=C3=BCllner?= Date: Mon, 27 Mar 2023 09:27:31 +0200 Subject: RISC-V: Add support for the Zfa extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Christoph Müllner Co-Developed-by: Philipp Tomsich Acked-by: Palmer Dabbelt --- include/opcode/riscv-opc.h | 99 ++++++++++++++++++++++++++++++++++++++++++++++ include/opcode/riscv.h | 6 +++ 2 files changed, 105 insertions(+) (limited to 'include') diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h index ad91c5a..3d5f660 100644 --- a/include/opcode/riscv-opc.h +++ b/include/opcode/riscv-opc.h @@ -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) diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h index 4b108e4..e96b957 100644 --- a/include/opcode/riscv.h +++ b/include/opcode/riscv.h @@ -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[]; -- cgit v1.1