public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [RFC PATCH v2 0/2] RISC-V: Add support for the Zfa extension
@ 2023-03-27  8:01 Christoph Muellner
  2023-03-27  8:01 ` [RFC PATCH v2 1/2] RISC-V: Allocate "various" operand type Christoph Muellner
  2023-03-27  8:01 ` [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension Christoph Muellner
  0 siblings, 2 replies; 15+ messages in thread
From: Christoph Muellner @ 2023-03-27  8:01 UTC (permalink / raw)
  To: binutils, Nelson Chu, Andrew Waterman, Palmer Dabbelt,
	Jim Wilson, Philipp Tomsich, Jeff Law, Tsukasa OI
  Cc: Christoph Müllner

From: Christoph Müllner <christoph.muellner@vrull.eu>

This series adds support for the RISC-V Zfa extension.
It consists of two patches:
1) A clean-up patch from Tsukasa that improves the way we structure
   format string directives.
2) A patch that introduces support for the Zfa extension.

The first patch does not have any dependencies and is suggested to get
merged as early as possible.

The second patch can land once the Zfa specification gets frozen.

Some additional bits to get the full context:
* Tsukasa wrote a first version, which can be found here:
  https://sourceware.org/pipermail/binutils/2022-September/122939.html
* I took over the patch as agreed here:
  https://sourceware.org/pipermail/binutils/2023-March/126753.html

There is also a discussion how to represent the constants in the
assembly notation. I've decided to use C-like constants, as I consider
this as the most user-friedly form for assembly programmers (for
examples see gas/testsuite/gas/riscv/zfa.s).
I prefer to not support the RS1-constants or the hex-encoded register
values that will land in the floating-point registers, as I want to
avoid misinterpretation because of multiple allowed notations.
If another notation is preferred, then please let me know.

Christoph Müllner (1):
  RISC-V: Add support for the Zfa extension

Tsukasa OI (1):
  RISC-V: Allocate "various" operand type

 bfd/elfxx-riscv.c                  | 39 ++++++++++++
 gas/config/tc-riscv.c              | 89 ++++++++++++++++++++++-----
 gas/testsuite/gas/riscv/zfa-32.d   | 10 +++
 gas/testsuite/gas/riscv/zfa-32.s   |  3 +
 gas/testsuite/gas/riscv/zfa-64.d   | 10 +++
 gas/testsuite/gas/riscv/zfa-64.s   |  3 +
 gas/testsuite/gas/riscv/zfa-fail.d |  2 +
 gas/testsuite/gas/riscv/zfa-fail.l | 33 ++++++++++
 gas/testsuite/gas/riscv/zfa-fail.s | 26 ++++++++
 gas/testsuite/gas/riscv/zfa.d      | 89 +++++++++++++++++++++++++++
 gas/testsuite/gas/riscv/zfa.s      | 87 ++++++++++++++++++++++++++
 include/opcode/riscv-opc.h         | 99 ++++++++++++++++++++++++++++++
 include/opcode/riscv.h             |  5 ++
 opcodes/riscv-dis.c                | 38 ++++++++++--
 opcodes/riscv-opc.c                | 59 +++++++++++++++++-
 15 files changed, 567 insertions(+), 25 deletions(-)
 create mode 100644 gas/testsuite/gas/riscv/zfa-32.d
 create mode 100644 gas/testsuite/gas/riscv/zfa-32.s
 create mode 100644 gas/testsuite/gas/riscv/zfa-64.d
 create mode 100644 gas/testsuite/gas/riscv/zfa-64.s
 create mode 100644 gas/testsuite/gas/riscv/zfa-fail.d
 create mode 100644 gas/testsuite/gas/riscv/zfa-fail.l
 create mode 100644 gas/testsuite/gas/riscv/zfa-fail.s
 create mode 100644 gas/testsuite/gas/riscv/zfa.d
 create mode 100644 gas/testsuite/gas/riscv/zfa.s

-- 
2.39.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [RFC PATCH v2 1/2] RISC-V: Allocate "various" operand type
  2023-03-27  8:01 [RFC PATCH v2 0/2] RISC-V: Add support for the Zfa extension Christoph Muellner
@ 2023-03-27  8:01 ` Christoph Muellner
  2023-03-27  8:01 ` [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension Christoph Muellner
  1 sibling, 0 replies; 15+ messages in thread
From: Christoph Muellner @ 2023-03-27  8:01 UTC (permalink / raw)
  To: binutils, Nelson Chu, Andrew Waterman, Palmer Dabbelt,
	Jim Wilson, Philipp Tomsich, Jeff Law, Tsukasa OI

From: Tsukasa OI <research_trasio@irq.a4lg.com>

This commit intends to move operands that require very special handling or
operand types that are so minor (e.g. only useful on a few instructions)
under "W".  I also intend this "W" to be "temporary" operand storage until
we can find good two character (or less) operand type.

In this commit, prefetch offset operand "f" for 'Zicbop' extension is moved
to "Wif" because of its special handling (and allocating single character
"f" for this operand type seemed too much).

Current expected allocation guideline is as follows:

1.  'W'
2.  The most closely related single-letter extension in lowercase
    (strongly recommended but not mandatory)
3.  Identify operand type

The author currently plans to allocate following three-character operand
types (for operands including instructions from unratified extensions).

1.  "Wif" ('Zicbop': fetch offset)
2.  "Wfv" (unratified 'Zfa': value operand from FLI.[HSDQ] instructions)
3.  "Wfm" / "WfM"
    'Zfh', 'F', 'D', 'Q': rounding modes "m" with special handling
                          solely for widening conversion instructions.

gas/ChangeLog:

	* config/tc-riscv.c (validate_riscv_insn, riscv_ip): Move from
	"f" to "Wif".

opcodes/ChangeLog:

	* riscv-dis.c (print_insn_args): Move from "f" to "Wif".
	* riscv-opc.c (riscv_opcodes): Reflect new operand type.
---
 gas/config/tc-riscv.c | 64 +++++++++++++++++++++++++++++++------------
 opcodes/riscv-dis.c   | 26 ++++++++++++++----
 opcodes/riscv-opc.c   |  6 ++--
 3 files changed, 71 insertions(+), 25 deletions(-)

diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index 40550ba8d74..4eff07a6d4a 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -1362,7 +1362,6 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
 	case 'j': used_bits |= ENCODE_ITYPE_IMM (-1U); break;
 	case 'a': used_bits |= ENCODE_JTYPE_IMM (-1U); break;
 	case 'p': used_bits |= ENCODE_BTYPE_IMM (-1U); break;
-	case 'f': /* Fall through.  */
 	case 'q': used_bits |= ENCODE_STYPE_IMM (-1U); break;
 	case 'u': used_bits |= ENCODE_UTYPE_IMM (-1U); break;
 	case 'z': break; /* Zero immediate.  */
@@ -1389,6 +1388,21 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
 		goto unknown_validate_operand;
 	    }
 	  break;
+	case 'W': /* Various operands.  */
+	  switch (*++oparg)
+	    {
+	    case 'i':
+	      switch (*++oparg)
+		{
+		case 'f': used_bits |= ENCODE_STYPE_IMM (-1U); break;
+		default:
+		  goto unknown_validate_operand;
+		}
+	      break;
+	    default:
+	      goto unknown_validate_operand;
+	    }
+	  break;
 	case 'X': /* Integer immediate.  */
 	  {
 	    size_t n;
@@ -3420,22 +3434,37 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
 	      imm_expr->X_op = O_absent;
 	      continue;
 
-	    case 'f': /* Prefetch offset, pseudo S-type but lower 5-bits zero.  */
-	      if (riscv_handle_implicit_zero_offset (imm_expr, asarg))
-		continue;
-	      my_getExpression (imm_expr, asarg);
-	      check_absolute_expr (ip, imm_expr, false);
-	      if (((unsigned) (imm_expr->X_add_number) & 0x1fU)
-		  || imm_expr->X_add_number >= (signed) RISCV_IMM_REACH / 2
-		  || imm_expr->X_add_number < -(signed) RISCV_IMM_REACH / 2)
-		as_bad (_("improper prefetch offset (%ld)"),
-			(long) imm_expr->X_add_number);
-	      ip->insn_opcode |=
-		ENCODE_STYPE_IMM ((unsigned) (imm_expr->X_add_number) &
-				  ~ 0x1fU);
-	      imm_expr->X_op = O_absent;
-	      asarg = expr_parse_end;
-	      continue;
+	    case 'W': /* Various operands.  */
+	      switch (*++oparg)
+		{
+		case 'i':
+		  switch (*++oparg)
+		    {
+		    case 'f':
+		      /* Prefetch offset for 'Zicbop' extension.
+			 pseudo S-type but lower 5-bits zero.  */
+		      if (riscv_handle_implicit_zero_offset (imm_expr, asarg))
+			continue;
+		      my_getExpression (imm_expr, asarg);
+		      check_absolute_expr (ip, imm_expr, false);
+		      if (((unsigned) (imm_expr->X_add_number) & 0x1fU)
+			  || imm_expr->X_add_number >= RISCV_IMM_REACH / 2
+			  || imm_expr->X_add_number < -RISCV_IMM_REACH / 2)
+			as_bad (_ ("improper prefetch offset (%ld)"),
+				(long) imm_expr->X_add_number);
+		      ip->insn_opcode |= ENCODE_STYPE_IMM (
+			  (unsigned) (imm_expr->X_add_number) & ~0x1fU);
+		      imm_expr->X_op = O_absent;
+		      asarg = expr_parse_end;
+		      continue;
+		    default:
+		      goto unknown_riscv_ip_operand;
+		    }
+		  break;
+		default:
+		  goto unknown_riscv_ip_operand;
+		}
+	      break;
 
 	    case 'X': /* Integer immediate.  */
 	      {
@@ -3488,6 +3517,7 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
 		  }
 	      }
 	      break;
+
 	    default:
 	    unknown_riscv_ip_operand:
 	      as_fatal (_("internal: unknown argument type `%s'"),
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index 7baba054daa..77a18b08599 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -473,11 +473,6 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 		 (int)EXTRACT_STYPE_IMM (l));
 	  break;
 
-	case 'f':
-	  print (info->stream, dis_style_address_offset, "%d",
-		 (int)EXTRACT_STYPE_IMM (l));
-	  break;
-
 	case 'a':
 	  info->target = EXTRACT_JTYPE_IMM (l) + pc;
 	  (*info->print_address_func) (info->target, info);
@@ -582,6 +577,27 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 	  print (info->stream, dis_style_immediate, "%d", rs1);
 	  break;
 
+	case 'W': /* Various operands.  */
+	  {
+	    switch (*++oparg)
+	      {
+	      case 'i':
+		switch (*++oparg)
+		  {
+		  case 'f':
+		    print (info->stream, dis_style_address_offset, "%d",
+			   (int) EXTRACT_STYPE_IMM (l));
+		    break;
+		  default:
+		    goto undefined_modifier;
+		  }
+		  break;
+	      default:
+		goto undefined_modifier;
+	      }
+	  }
+	  break;
+
 	case 'X': /* Integer immediate.  */
 	  {
 	    size_t n;
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index f67375f10a9..d9d69cda548 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -313,9 +313,9 @@ const struct riscv_opcode riscv_opcodes[] =
 /* name, xlen, isa, operands, match, mask, match_func, pinfo.  */
 
 /* Standard hints.  */
-{"prefetch.i",  0, INSN_CLASS_ZICBOP, "f(s)", MATCH_PREFETCH_I, MASK_PREFETCH_I, match_opcode, 0 },
-{"prefetch.r",  0, INSN_CLASS_ZICBOP, "f(s)", MATCH_PREFETCH_R, MASK_PREFETCH_R, match_opcode, 0 },
-{"prefetch.w",  0, INSN_CLASS_ZICBOP, "f(s)", MATCH_PREFETCH_W, MASK_PREFETCH_W, match_opcode, 0 },
+{"prefetch.i",  0, INSN_CLASS_ZICBOP, "Wif(s)", MATCH_PREFETCH_I, MASK_PREFETCH_I, match_opcode, 0 },
+{"prefetch.r",  0, INSN_CLASS_ZICBOP, "Wif(s)", MATCH_PREFETCH_R, MASK_PREFETCH_R, match_opcode, 0 },
+{"prefetch.w",  0, INSN_CLASS_ZICBOP, "Wif(s)", MATCH_PREFETCH_W, MASK_PREFETCH_W, match_opcode, 0 },
 {"pause",       0, INSN_CLASS_ZIHINTPAUSE, "", MATCH_PAUSE, MASK_PAUSE, match_opcode, 0 },
 
 /* Basic RVI instructions and aliases.  */
-- 
2.39.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension
  2023-03-27  8:01 [RFC PATCH v2 0/2] RISC-V: Add support for the Zfa extension Christoph Muellner
  2023-03-27  8:01 ` [RFC PATCH v2 1/2] RISC-V: Allocate "various" operand type Christoph Muellner
@ 2023-03-27  8:01 ` Christoph Muellner
  2023-03-27  8:09   ` Kito Cheng
  2023-03-27  8:38   ` Jan Beulich
  1 sibling, 2 replies; 15+ messages in thread
From: Christoph Muellner @ 2023-03-27  8:01 UTC (permalink / raw)
  To: binutils, Nelson Chu, Andrew Waterman, Palmer Dabbelt,
	Jim Wilson, Philipp Tomsich, Jeff Law, Tsukasa OI
  Cc: Christoph Müllner

From: Christoph Müllner <christoph.muellner@vrull.eu>

This patch introduces the RISC-V Zfa extension, which introduces
additional floating-point extensions:
* 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 float register bigger than XLEN
* Quiet comparison instructions (fleq/fltq)

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 assembly mnemonic.

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 (validate_riscv_insn): Add support for
	new format string directive 'Wfv'.
	(riscv_ip): Likewise.
	* 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>
---
 bfd/elfxx-riscv.c                  | 39 ++++++++++++
 gas/config/tc-riscv.c              | 25 ++++++++
 gas/testsuite/gas/riscv/zfa-32.d   | 10 +++
 gas/testsuite/gas/riscv/zfa-32.s   |  3 +
 gas/testsuite/gas/riscv/zfa-64.d   | 10 +++
 gas/testsuite/gas/riscv/zfa-64.s   |  3 +
 gas/testsuite/gas/riscv/zfa-fail.d |  2 +
 gas/testsuite/gas/riscv/zfa-fail.l | 33 ++++++++++
 gas/testsuite/gas/riscv/zfa-fail.s | 26 ++++++++
 gas/testsuite/gas/riscv/zfa.d      | 89 +++++++++++++++++++++++++++
 gas/testsuite/gas/riscv/zfa.s      | 87 ++++++++++++++++++++++++++
 include/opcode/riscv-opc.h         | 99 ++++++++++++++++++++++++++++++
 include/opcode/riscv.h             |  5 ++
 opcodes/riscv-dis.c                | 12 ++++
 opcodes/riscv-opc.c                | 53 ++++++++++++++++
 15 files changed, 496 insertions(+)
 create mode 100644 gas/testsuite/gas/riscv/zfa-32.d
 create mode 100644 gas/testsuite/gas/riscv/zfa-32.s
 create mode 100644 gas/testsuite/gas/riscv/zfa-64.d
 create mode 100644 gas/testsuite/gas/riscv/zfa-64.s
 create mode 100644 gas/testsuite/gas/riscv/zfa-fail.d
 create mode 100644 gas/testsuite/gas/riscv/zfa-fail.l
 create mode 100644 gas/testsuite/gas/riscv/zfa-fail.s
 create mode 100644 gas/testsuite/gas/riscv/zfa.d
 create mode 100644 gas/testsuite/gas/riscv/zfa.s

diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index 19391d94e30..d57fe2400fd 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -1078,6 +1078,7 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
   {"zvl256b", "zvl128b",	check_implicit_always},
   {"zvl128b", "zvl64b",		check_implicit_always},
   {"zvl64b", "zvl32b",		check_implicit_always},
+  {"zfa", "f",		check_implicit_always},
   {"d", "f",		check_implicit_always},
   {"zfh", "zfhmin",	check_implicit_always},
   {"zfhmin", "f",	check_implicit_always},
@@ -1175,6 +1176,7 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] =
   {"zihintpause",	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 },
   {"zfh",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
   {"zfhmin",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
   {"zfinx",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
@@ -2313,6 +2315,17 @@ 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_ZFA:
+      return riscv_subset_supports (rps, "zfa");
+    case INSN_CLASS_D_AND_ZFA:
+      return riscv_subset_supports (rps, "d")
+	     && riscv_subset_supports (rps, "zfa");
+    case INSN_CLASS_Q_AND_ZFA:
+      return riscv_subset_supports (rps, "q")
+	     && riscv_subset_supports (rps, "zfa");
+    case INSN_CLASS_ZFH_AND_ZFA:
+      return riscv_subset_supports (rps, "zfh")
+	     && riscv_subset_supports (rps, "zfa");
     case INSN_CLASS_ZBA:
       return riscv_subset_supports (rps, "zba");
     case INSN_CLASS_ZBB:
@@ -2479,6 +2492,32 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
 	return "zhinxmin";
       else
 	return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
+    case INSN_CLASS_ZFA:
+      return "zfa";
+    case INSN_CLASS_D_AND_ZFA:
+      if (!riscv_subset_supports (rps, "d")
+	  && !riscv_subset_supports (rps, "zfa"))
+	return _("d' and `zfa");
+      else if (!riscv_subset_supports (rps, "d"))
+	return "d";
+      else
+	return "zfa";
+    case INSN_CLASS_Q_AND_ZFA:
+      if (!riscv_subset_supports (rps, "q")
+	  && !riscv_subset_supports (rps, "zfa"))
+	return _("q' and `zfa");
+      else if (!riscv_subset_supports (rps, "q"))
+	return "q";
+      else
+	return "zfa";
+    case INSN_CLASS_ZFH_AND_ZFA:
+      if (!riscv_subset_supports (rps, "zfh")
+	  && !riscv_subset_supports (rps, "zfa"))
+	return _("zfh' and `zfa");
+      else if (!riscv_subset_supports (rps, "zfh"))
+	return "zfh";
+      else
+	return "zfa";
     case INSN_CLASS_ZBA:
       return "zba";
     case INSN_CLASS_ZBB:
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index 4eff07a6d4a..1e301568080 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -1399,6 +1399,14 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
 		  goto unknown_validate_operand;
 		}
 	      break;
+	    case 'f':
+	      switch (*++oparg)
+		{
+		case 'v': USE_BITS (OP_MASK_RS1, OP_SH_RS1); break;
+		default:
+		  goto unknown_validate_operand;
+		}
+	      break;
 	    default:
 	      goto unknown_validate_operand;
 	    }
@@ -3461,6 +3469,23 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
 		      goto unknown_riscv_ip_operand;
 		    }
 		  break;
+		case 'f':
+		  switch (*++oparg)
+		    {
+		    case 'v':
+		      /* FLI.[HSDQ] value field for 'Zfa' extension.  */
+		      if (!arg_lookup (&asarg, riscv_fli_value,
+				       ARRAY_SIZE (riscv_fli_value), &regno))
+			{
+			  as_bad (_("improper fli value operand"));
+			  break;
+			}
+		      INSERT_OPERAND (RS1, *ip, regno);
+		      continue;
+		    default:
+		      goto unknown_riscv_ip_operand;
+		    }
+		  break;
 		default:
 		  goto unknown_riscv_ip_operand;
 		}
diff --git a/gas/testsuite/gas/riscv/zfa-32.d b/gas/testsuite/gas/riscv/zfa-32.d
new file mode 100644
index 00000000000..48e20bf4675
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zfa-32.d
@@ -0,0 +1,10 @@
+#as: -march=rv32id_zfa
+#objdump: -d
+
+.*:[ 	]+file format .*
+
+Disassembly of section .text:
+
+0+000 <target>:
+[ 	]+[0-9a-f]+:[ 	]+e2108553[ 	]+fmvh\.x\.d[ 	]+a0,ft1
+[ 	]+[0-9a-f]+:[ 	]+b2b500d3[ 	]+fmvp\.d\.x[ 	]+ft1,a0,a1
diff --git a/gas/testsuite/gas/riscv/zfa-32.s b/gas/testsuite/gas/riscv/zfa-32.s
new file mode 100644
index 00000000000..da95441cdc7
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zfa-32.s
@@ -0,0 +1,3 @@
+target:
+	fmvh.x.d	a0, ft1
+	fmvp.d.x	ft1, a0, a1
diff --git a/gas/testsuite/gas/riscv/zfa-64.d b/gas/testsuite/gas/riscv/zfa-64.d
new file mode 100644
index 00000000000..48b6d74ed9b
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zfa-64.d
@@ -0,0 +1,10 @@
+#as: -march=rv64iq_zfa
+#objdump: -d
+
+.*:[ 	]+file format .*
+
+Disassembly of section .text:
+
+0+000 <target>:
+[ 	]+[0-9a-f]+:[ 	]+e6108553[ 	]+fmvh\.x\.q[ 	]+a0,ft1
+[ 	]+[0-9a-f]+:[ 	]+b6b500d3[ 	]+fmvp\.q\.x[ 	]+ft1,a0,a1
diff --git a/gas/testsuite/gas/riscv/zfa-64.s b/gas/testsuite/gas/riscv/zfa-64.s
new file mode 100644
index 00000000000..dc8129dae3e
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zfa-64.s
@@ -0,0 +1,3 @@
+target:
+	fmvh.x.q	a0, ft1
+	fmvp.q.x	ft1, a0, a1
diff --git a/gas/testsuite/gas/riscv/zfa-fail.d b/gas/testsuite/gas/riscv/zfa-fail.d
new file mode 100644
index 00000000000..d9d4a36c65c
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zfa-fail.d
@@ -0,0 +1,2 @@
+#as: -march=rv64iq_zfa_zfh
+#error_output: zfa-fail.l
diff --git a/gas/testsuite/gas/riscv/zfa-fail.l b/gas/testsuite/gas/riscv/zfa-fail.l
new file mode 100644
index 00000000000..19b6ff4967d
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zfa-fail.l
@@ -0,0 +1,33 @@
+.*: Assembler messages:
+.*: Error: improper fli value operand
+.*: Error: illegal operands `fli\.s ft1,1'
+.*: Error: improper fli value operand
+.*: Error: illegal operands `fli\.d ft1,-1'
+.*: Error: improper fli value operand
+.*: Error: illegal operands `fli\.q ft1,1.250'
+.*: Error: improper fli value operand
+.*: Error: illegal operands `fli\.h ft1,8'
+.*: Error: improper fli value operand
+.*: Error: illegal operands `fli\.s ft1,infinity'
+.*: Error: improper fli value operand
+.*: Error: illegal operands `fli\.d ft1,invalid'
+.*: Error: improper fli value operand
+.*: Error: illegal operands `fli\.q ft1,30'
+.*: Error: improper fli value operand
+.*: Error: illegal operands `fli\.h ft1,31'
+.*: Error: improper fli value operand
+.*: Error: illegal operands `fli\.s ft1,32'
+.*: Error: improper fli value operand
+.*: Error: illegal operands `fli\.d ft1,0'
+.*: Error: improper fli value operand
+.*: Error: illegal operands `fli\.q ft1,0.0'
+.*: Error: improper fli value operand
+.*: Error: illegal operands `fli\.h ft1,-0.0'
+.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1'
+.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,rne'
+.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,rdn'
+.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,rup'
+.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,rmm'
+.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,dyn'
+.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,invalid'
+
diff --git a/gas/testsuite/gas/riscv/zfa-fail.s b/gas/testsuite/gas/riscv/zfa-fail.s
new file mode 100644
index 00000000000..e6c6bdc909a
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zfa-fail.s
@@ -0,0 +1,26 @@
+target:
+	# fli.[sdqh]: Invalid value field
+	fli.s	ft1, 1
+	fli.d	ft1, -1
+	fli.q	ft1, 1.250
+	fli.h	ft1, 8
+	fli.s	ft1, infinity
+	fli.d	ft1, invalid
+	fli.q	ft1, 30
+	fli.h	ft1, 31
+	fli.s	ft1, 32
+	fli.d	ft1, 0
+	fli.q	ft1, 0.0
+	fli.h	ft1, -0.0
+
+	# fcvtmod.w.d: Requires explicit rounding mode.
+	fcvtmod.w.d	a0, ft1
+
+	# fcvtmod.w.d: Rounding mode other than rtz are reserved.
+	fcvtmod.w.d	a0, ft1, rne
+	fcvtmod.w.d	a0, ft1, rdn
+	fcvtmod.w.d	a0, ft1, rup
+	fcvtmod.w.d	a0, ft1, rmm
+	fcvtmod.w.d	a0, ft1, dyn
+	# fcvtmod.w.d: Invalid rounding mode is invalid.
+	fcvtmod.w.d	a0, ft1, invalid
diff --git a/gas/testsuite/gas/riscv/zfa.d b/gas/testsuite/gas/riscv/zfa.d
new file mode 100644
index 00000000000..a6f1f81db29
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zfa.d
@@ -0,0 +1,89 @@
+#as: -march=rv32iq_zfa_zfh
+#objdump: -d
+
+.*:[ 	]+file format .*
+
+Disassembly of section .text:
+
+0+000 <target>:
+[ 	]+[0-9a-f]+:[ 	]+f01000d3[ 	]+fli\.s[ 		]+ft1,-1.0
+[ 	]+[0-9a-f]+:[ 	]+f01080d3[ 	]+fli\.s[ 		]+ft1,min
+[ 	]+[0-9a-f]+:[ 	]+f01100d3[ 	]+fli\.s[ 		]+ft1,0.0000152587890625
+[ 	]+[0-9a-f]+:[ 	]+f01180d3[ 	]+fli\.s[ 		]+ft1,0.000030517578125
+[ 	]+[0-9a-f]+:[ 	]+f01200d3[ 	]+fli\.s[ 		]+ft1,0.00390625
+[ 	]+[0-9a-f]+:[ 	]+f01280d3[ 	]+fli\.s[ 		]+ft1,0.0078125
+[ 	]+[0-9a-f]+:[ 	]+f01300d3[ 	]+fli\.s[ 		]+ft1,0.0625
+[ 	]+[0-9a-f]+:[ 	]+f01380d3[ 	]+fli\.s[ 		]+ft1,0.125
+[ 	]+[0-9a-f]+:[ 	]+f21400d3[ 	]+fli\.d[ 		]+ft1,0.25
+[ 	]+[0-9a-f]+:[ 	]+f21480d3[ 	]+fli\.d[ 		]+ft1,0.3125
+[ 	]+[0-9a-f]+:[ 	]+f21500d3[ 	]+fli\.d[ 		]+ft1,0.375
+[ 	]+[0-9a-f]+:[ 	]+f21580d3[ 	]+fli\.d[ 		]+ft1,0.4375
+[ 	]+[0-9a-f]+:[ 	]+f21600d3[ 	]+fli\.d[ 		]+ft1,0.5
+[ 	]+[0-9a-f]+:[ 	]+f21680d3[ 	]+fli\.d[ 		]+ft1,0.625
+[ 	]+[0-9a-f]+:[ 	]+f21700d3[ 	]+fli\.d[ 		]+ft1,0.75
+[ 	]+[0-9a-f]+:[ 	]+f21780d3[ 	]+fli\.d[ 		]+ft1,0.875
+[ 	]+[0-9a-f]+:[ 	]+f61800d3[ 	]+fli\.q[ 		]+ft1,1.0
+[ 	]+[0-9a-f]+:[ 	]+f61880d3[ 	]+fli\.q[ 		]+ft1,1.25
+[ 	]+[0-9a-f]+:[ 	]+f61900d3[ 	]+fli\.q[ 		]+ft1,1.5
+[ 	]+[0-9a-f]+:[ 	]+f61980d3[ 	]+fli\.q[ 		]+ft1,1.75
+[ 	]+[0-9a-f]+:[ 	]+f61a00d3[ 	]+fli\.q[ 		]+ft1,2.0
+[ 	]+[0-9a-f]+:[ 	]+f61a80d3[ 	]+fli\.q[ 		]+ft1,2.5
+[ 	]+[0-9a-f]+:[ 	]+f61b00d3[ 	]+fli\.q[ 		]+ft1,3.0
+[ 	]+[0-9a-f]+:[ 	]+f61b80d3[ 	]+fli\.q[ 		]+ft1,4.0
+[ 	]+[0-9a-f]+:[ 	]+f41c00d3[ 	]+fli\.h[ 		]+ft1,8.0
+[ 	]+[0-9a-f]+:[ 	]+f41c80d3[ 	]+fli\.h[ 		]+ft1,16.0
+[ 	]+[0-9a-f]+:[ 	]+f41d00d3[ 	]+fli\.h[ 		]+ft1,128.0
+[ 	]+[0-9a-f]+:[ 	]+f41d80d3[ 	]+fli\.h[ 		]+ft1,256.0
+[ 	]+[0-9a-f]+:[ 	]+f41e00d3[ 	]+fli\.h[ 		]+ft1,32768.0
+[ 	]+[0-9a-f]+:[ 	]+f41e80d3[ 	]+fli\.h[ 		]+ft1,65536.0
+[ 	]+[0-9a-f]+:[ 	]+f41f00d3[ 	]+fli\.h[ 		]+ft1,inf
+[ 	]+[0-9a-f]+:[ 	]+f41f80d3[ 	]+fli\.h[ 		]+ft1,nan
+[ 	]+[0-9a-f]+:[ 	]+2c3100d3[ 	]+fmin\.h[ 		]+ft1,ft2,ft3
+[ 	]+[0-9a-f]+:[ 	]+2c3120d3[ 	]+fminm\.h[ 		]+ft1,ft2,ft3
+[ 	]+[0-9a-f]+:[ 	]+283100d3[ 	]+fmin\.s[ 		]+ft1,ft2,ft3
+[ 	]+[0-9a-f]+:[ 	]+283120d3[ 	]+fminm\.s[ 		]+ft1,ft2,ft3
+[ 	]+[0-9a-f]+:[ 	]+2a3100d3[ 	]+fmin\.d[ 		]+ft1,ft2,ft3
+[ 	]+[0-9a-f]+:[ 	]+2a3120d3[ 	]+fminm\.d[ 		]+ft1,ft2,ft3
+[ 	]+[0-9a-f]+:[ 	]+2e3100d3[ 	]+fmin\.q[ 		]+ft1,ft2,ft3
+[ 	]+[0-9a-f]+:[ 	]+2e3120d3[ 	]+fminm\.q[ 		]+ft1,ft2,ft3
+[ 	]+[0-9a-f]+:[ 	]+2c3110d3[ 	]+fmax\.h[ 		]+ft1,ft2,ft3
+[ 	]+[0-9a-f]+:[ 	]+2c3130d3[ 	]+fmaxm\.h[ 		]+ft1,ft2,ft3
+[ 	]+[0-9a-f]+:[ 	]+283110d3[ 	]+fmax\.s[ 		]+ft1,ft2,ft3
+[ 	]+[0-9a-f]+:[ 	]+283130d3[ 	]+fmaxm\.s[ 		]+ft1,ft2,ft3
+[ 	]+[0-9a-f]+:[ 	]+2a3110d3[ 	]+fmax\.d[ 		]+ft1,ft2,ft3
+[ 	]+[0-9a-f]+:[ 	]+2a3130d3[ 	]+fmaxm\.d[ 		]+ft1,ft2,ft3
+[ 	]+[0-9a-f]+:[ 	]+2e3110d3[ 	]+fmax\.q[ 		]+ft1,ft2,ft3
+[ 	]+[0-9a-f]+:[ 	]+2e3130d3[ 	]+fmaxm\.q[ 		]+ft1,ft2,ft3
+[ 	]+[0-9a-f]+:[ 	]+4445f553[ 	]+fround\.h[ 		]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+44459553[ 	]+fround\.h[ 		]+fa0,fa1,rtz
+[ 	]+[0-9a-f]+:[ 	]+4045f553[ 	]+fround\.s[ 		]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+40459553[ 	]+fround\.s[ 		]+fa0,fa1,rtz
+[ 	]+[0-9a-f]+:[ 	]+4245f553[ 	]+fround\.d[ 		]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+42459553[ 	]+fround\.d[ 		]+fa0,fa1,rtz
+[ 	]+[0-9a-f]+:[ 	]+4645f553[ 	]+fround\.q[ 		]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+46459553[ 	]+fround\.q[ 		]+fa0,fa1,rtz
+[ 	]+[0-9a-f]+:[ 	]+4455f553[ 	]+froundnx\.h[ 		]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+44559553[ 	]+froundnx\.h[ 		]+fa0,fa1,rtz
+[ 	]+[0-9a-f]+:[ 	]+4055f553[ 	]+froundnx\.s[ 		]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+40559553[ 	]+froundnx\.s[ 		]+fa0,fa1,rtz
+[ 	]+[0-9a-f]+:[ 	]+4255f553[ 	]+froundnx\.d[ 		]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+42559553[ 	]+froundnx\.d[ 		]+fa0,fa1,rtz
+[ 	]+[0-9a-f]+:[ 	]+4655f553[ 	]+froundnx\.q[ 		]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+46559553[ 	]+froundnx\.q[ 		]+fa0,fa1,rtz
+[ 	]+[0-9a-f]+:[ 	]+c2809553[ 	]+fcvtmod\.w\.d[ 	]+a0,ft1,rtz
+[ 	]+[0-9a-f]+:[ 	]+a4209553[ 	]+flt\.h[ 		]+a0,ft1,ft2
+[ 	]+[0-9a-f]+:[ 	]+a420d553[ 	]+fltq\.h[ 		]+a0,ft1,ft2
+[ 	]+[0-9a-f]+:[ 	]+a0209553[ 	]+flt\.s[ 		]+a0,ft1,ft2
+[ 	]+[0-9a-f]+:[ 	]+a020d553[ 	]+fltq\.s[ 		]+a0,ft1,ft2
+[ 	]+[0-9a-f]+:[ 	]+a2209553[ 	]+flt\.d[ 		]+a0,ft1,ft2
+[ 	]+[0-9a-f]+:[ 	]+a220d553[ 	]+fltq\.d[ 		]+a0,ft1,ft2
+[ 	]+[0-9a-f]+:[ 	]+a6209553[ 	]+flt\.q[ 		]+a0,ft1,ft2
+[ 	]+[0-9a-f]+:[ 	]+a620d553[ 	]+fltq\.q[ 		]+a0,ft1,ft2
+[ 	]+[0-9a-f]+:[ 	]+a4208553[ 	]+fle\.h[ 		]+a0,ft1,ft2
+[ 	]+[0-9a-f]+:[ 	]+a420c553[ 	]+fleq\.h[ 		]+a0,ft1,ft2
+[ 	]+[0-9a-f]+:[ 	]+a0208553[ 	]+fle\.s[ 		]+a0,ft1,ft2
+[ 	]+[0-9a-f]+:[ 	]+a020c553[ 	]+fleq\.s[ 		]+a0,ft1,ft2
+[ 	]+[0-9a-f]+:[ 	]+a2208553[ 	]+fle\.d[ 		]+a0,ft1,ft2
+[ 	]+[0-9a-f]+:[ 	]+a220c553[ 	]+fleq\.d[ 		]+a0,ft1,ft2
+[ 	]+[0-9a-f]+:[ 	]+a6208553[ 	]+fle\.q[ 		]+a0,ft1,ft2
+[ 	]+[0-9a-f]+:[ 	]+a620c553[ 	]+fleq\.q[ 		]+a0,ft1,ft2
diff --git a/gas/testsuite/gas/riscv/zfa.s b/gas/testsuite/gas/riscv/zfa.s
new file mode 100644
index 00000000000..906e8a4a56d
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zfa.s
@@ -0,0 +1,87 @@
+target:
+	# fli
+	fli.s		ft1, -1.0
+	fli.s		ft1, min
+	fli.s		ft1, 0.0000152587890625
+	fli.s		ft1, 0.000030517578125
+	fli.s		ft1, 0.00390625
+	fli.s		ft1, 0.0078125
+	fli.s		ft1, 0.0625
+	fli.s		ft1, 0.125
+	fli.d		ft1, 0.25
+	fli.d		ft1, 0.3125
+	fli.d		ft1, 0.375
+	fli.d		ft1, 0.4375
+	fli.d		ft1, 0.5
+	fli.d		ft1, 0.625
+	fli.d		ft1, 0.75
+	fli.d		ft1, 0.875
+	fli.q		ft1, 1.0
+	fli.q		ft1, 1.25
+	fli.q		ft1, 1.5
+	fli.q		ft1, 1.75
+	fli.q		ft1, 2.0
+	fli.q		ft1, 2.5
+	fli.q		ft1, 3.0
+	fli.q		ft1, 4.0
+	fli.h		ft1, 8.0
+	fli.h		ft1, 16.0
+	fli.h		ft1, 128.0
+	fli.h		ft1, 256.0
+	fli.h		ft1, 32768.0
+	fli.h		ft1, 65536.0
+	fli.h		ft1, inf
+	fli.h		ft1, nan
+	# fminm/fmaxm
+	fmin.h		ft1, ft2, ft3
+	fminm.h		ft1, ft2, ft3
+	fmin.s		ft1, ft2, ft3
+	fminm.s		ft1, ft2, ft3
+	fmin.d		ft1, ft2, ft3
+	fminm.d		ft1, ft2, ft3
+	fmin.q		ft1, ft2, ft3
+	fminm.q		ft1, ft2, ft3
+	fmax.h		ft1, ft2, ft3
+	fmaxm.h		ft1, ft2, ft3
+	fmax.s		ft1, ft2, ft3
+	fmaxm.s		ft1, ft2, ft3
+	fmax.d		ft1, ft2, ft3
+	fmaxm.d		ft1, ft2, ft3
+	fmax.q		ft1, ft2, ft3
+	fmaxm.q		ft1, ft2, ft3
+	# fround/froundnx
+	fround.h	fa0, fa1
+	fround.h	fa0, fa1, rtz
+	fround.s	fa0, fa1
+	fround.s	fa0, fa1, rtz
+	fround.d	fa0, fa1
+	fround.d	fa0, fa1, rtz
+	fround.q	fa0, fa1
+	fround.q	fa0, fa1, rtz
+	froundnx.h	fa0, fa1
+	froundnx.h	fa0, fa1, rtz
+	froundnx.s	fa0, fa1
+	froundnx.s	fa0, fa1, rtz
+	froundnx.d	fa0, fa1
+	froundnx.d	fa0, fa1, rtz
+	froundnx.q	fa0, fa1
+	froundnx.q	fa0, fa1, rtz
+	# fcvtmod.w.d
+	fcvtmod.w.d	a0, ft1, rtz
+	# fltq/fleq
+	flt.h		a0, ft1, ft2
+	fltq.h		a0, ft1, ft2
+	flt.s		a0, ft1, ft2
+	fltq.s		a0, ft1, ft2
+	flt.d		a0, ft1, ft2
+	fltq.d		a0, ft1, ft2
+	flt.q		a0, ft1, ft2
+	fltq.q		a0, ft1, ft2
+	fle.h		a0, ft1, ft2
+	fleq.h		a0, ft1, ft2
+	fle.s		a0, ft1, ft2
+	fleq.s		a0, ft1, ft2
+	fle.d		a0, ft1, ft2
+	fleq.d		a0, ft1, ft2
+	fle.q		a0, ft1, ft2
+	fleq.q		a0, ft1, ft2
diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h
index 85d35c1efc9..e141c377bde 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
@@ -2981,6 +3047,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 b4ae55249bb..1ca698c95ee 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -388,6 +388,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,
@@ -554,6 +558,7 @@ 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_value[32];
 
 extern const struct riscv_opcode riscv_opcodes[];
 extern const struct riscv_opcode riscv_insn_types[];
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index 77a18b08599..edb599e1741 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -592,6 +592,17 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 		    goto undefined_modifier;
 		  }
 		  break;
+	      case 'f':
+		switch (*++oparg)
+		  {
+		  case 'v':
+		    print (info->stream, dis_style_text, "%s",
+			   riscv_fli_value[rs1]);
+		    break;
+		  default:
+		    goto undefined_modifier;
+		  }
+		break;
 	      default:
 		goto undefined_modifier;
 	      }
@@ -640,6 +651,7 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 	      }
 	  }
 	  break;
+
 	default:
 	undefined_modifier:
 	  /* xgettext:c-format */
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index d9d69cda548..424969fbe57 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -110,6 +110,16 @@ const char * const riscv_vma[2] =
   "mu", "ma"
 };
 
+/* The FLI.[HSDQ] value constants.  */
+const char * const riscv_fli_value[32] =
+{
+  "-1.0", "min", "0.0000152587890625", "0.000030517578125",
+  "0.00390625", "0.0078125", "0.0625", "0.125",
+  "0.25", "0.3125", "0.375", "0.4375", "0.5", "0.625", "0.75", "0.875",
+  "1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "4.0",
+  "8.0", "16.0", "128.0", "256.0", "32768.0", "65536.0",  "inf", "nan",
+};
+
 /* The order of overloaded instructions matters.  Label arguments and
    register arguments look the same. Instructions that can have either
    for arguments must apear in the correct order in this table for the
@@ -939,6 +949,49 @@ const struct riscv_opcode riscv_opcodes[] =
 {"wrs.nto",    0, INSN_CLASS_ZAWRS, "", MATCH_WRS_NTO, MASK_WRS_NTO, match_opcode, 0 },
 {"wrs.sto",    0, INSN_CLASS_ZAWRS, "", MATCH_WRS_STO, MASK_WRS_STO, match_opcode, 0 },
 
+/* Zfa instructions.  */
+{"fli.s",       0, INSN_CLASS_ZFA,         "D,Wfv", MATCH_FLI_S, MASK_FLI_S, match_opcode, 0 },
+{"fli.d",       0, INSN_CLASS_D_AND_ZFA,   "D,Wfv", MATCH_FLI_D, MASK_FLI_D, match_opcode, 0 },
+{"fli.q",       0, INSN_CLASS_Q_AND_ZFA,   "D,Wfv", MATCH_FLI_Q, MASK_FLI_Q, match_opcode, 0 },
+{"fli.h",       0, INSN_CLASS_ZFH_AND_ZFA, "D,Wfv", MATCH_FLI_H, MASK_FLI_H, match_opcode, 0 },
+{"fminm.s",     0, INSN_CLASS_ZFA,         "D,S,T", MATCH_FMINM_S, MASK_FMINM_S, match_opcode, 0 },
+{"fmaxm.s",     0, INSN_CLASS_ZFA,         "D,S,T", MATCH_FMAXM_S, MASK_FMAXM_S, match_opcode, 0 },
+{"fminm.d",     0, INSN_CLASS_D_AND_ZFA,   "D,S,T", MATCH_FMINM_D, MASK_FMINM_D, match_opcode, 0 },
+{"fmaxm.d",     0, INSN_CLASS_D_AND_ZFA,   "D,S,T", MATCH_FMAXM_D, MASK_FMAXM_D, match_opcode, 0 },
+{"fminm.q",     0, INSN_CLASS_Q_AND_ZFA,   "D,S,T", MATCH_FMINM_Q, MASK_FMINM_Q, match_opcode, 0 },
+{"fmaxm.q",     0, INSN_CLASS_Q_AND_ZFA,   "D,S,T", MATCH_FMAXM_Q, MASK_FMAXM_Q, match_opcode, 0 },
+{"fminm.h",     0, INSN_CLASS_ZFH_AND_ZFA, "D,S,T", MATCH_FMINM_H, MASK_FMINM_H, match_opcode, 0 },
+{"fmaxm.h",     0, INSN_CLASS_ZFH_AND_ZFA, "D,S,T", MATCH_FMAXM_H, MASK_FMAXM_H, match_opcode, 0 },
+{"fround.s",    0, INSN_CLASS_ZFA,         "D,S",   MATCH_FROUND_S|MASK_RM, MASK_FROUND_S|MASK_RM, match_opcode, 0 },
+{"fround.s",    0, INSN_CLASS_ZFA,         "D,S,m", MATCH_FROUND_S, MASK_FROUND_S, match_opcode, 0 },
+{"froundnx.s",  0, INSN_CLASS_ZFA,         "D,S",   MATCH_FROUNDNX_S|MASK_RM, MASK_FROUNDNX_S|MASK_RM, match_opcode, 0 },
+{"froundnx.s",  0, INSN_CLASS_ZFA,         "D,S,m", MATCH_FROUNDNX_S, MASK_FROUNDNX_S, match_opcode, 0 },
+{"fround.d",    0, INSN_CLASS_D_AND_ZFA,   "D,S",   MATCH_FROUND_D|MASK_RM, MASK_FROUND_D|MASK_RM, match_opcode, 0 },
+{"fround.d",    0, INSN_CLASS_D_AND_ZFA,   "D,S,m", MATCH_FROUND_D, MASK_FROUND_D, match_opcode, 0 },
+{"froundnx.d",  0, INSN_CLASS_D_AND_ZFA,   "D,S",   MATCH_FROUNDNX_D|MASK_RM, MASK_FROUNDNX_D|MASK_RM, match_opcode, 0 },
+{"froundnx.d",  0, INSN_CLASS_D_AND_ZFA,   "D,S,m", MATCH_FROUNDNX_D, MASK_FROUNDNX_D, match_opcode, 0 },
+{"fround.q",    0, INSN_CLASS_Q_AND_ZFA,   "D,S",   MATCH_FROUND_Q|MASK_RM, MASK_FROUND_Q|MASK_RM, match_opcode, 0 },
+{"fround.q",    0, INSN_CLASS_Q_AND_ZFA,   "D,S,m", MATCH_FROUND_Q, MASK_FROUND_Q, match_opcode, 0 },
+{"froundnx.q",  0, INSN_CLASS_Q_AND_ZFA,   "D,S",   MATCH_FROUNDNX_Q|MASK_RM, MASK_FROUNDNX_Q|MASK_RM, match_opcode, 0 },
+{"froundnx.q",  0, INSN_CLASS_Q_AND_ZFA,   "D,S,m", MATCH_FROUNDNX_Q, MASK_FROUNDNX_Q, match_opcode, 0 },
+{"fround.h",    0, INSN_CLASS_ZFH_AND_ZFA, "D,S",   MATCH_FROUND_H|MASK_RM, MASK_FROUND_H|MASK_RM, match_opcode, 0 },
+{"fround.h",    0, INSN_CLASS_ZFH_AND_ZFA, "D,S,m", MATCH_FROUND_H, MASK_FROUND_H, match_opcode, 0 },
+{"froundnx.h",  0, INSN_CLASS_ZFH_AND_ZFA, "D,S",   MATCH_FROUNDNX_H|MASK_RM, MASK_FROUNDNX_H|MASK_RM, match_opcode, 0 },
+{"froundnx.h",  0, INSN_CLASS_ZFH_AND_ZFA, "D,S,m", MATCH_FROUNDNX_H, MASK_FROUNDNX_H, match_opcode, 0 },
+{"fcvtmod.w.d", 0, INSN_CLASS_D_AND_ZFA,   "d,S,m", MATCH_FCVTMOD_W_D, MASK_FCVTMOD_W_D, match_opcode, 0 },
+{"fmvh.x.d",   32, INSN_CLASS_D_AND_ZFA,   "d,S",   MATCH_FMVH_X_D, MASK_FMVH_X_D, match_opcode, 0 },
+{"fmvp.d.x",   32, INSN_CLASS_D_AND_ZFA,   "D,s,t", MATCH_FMVP_D_X, MASK_FMVP_D_X, match_opcode, 0 },
+{"fmvh.x.q",   64, INSN_CLASS_Q_AND_ZFA,   "d,S",   MATCH_FMVH_X_Q, MASK_FMVH_X_Q, match_opcode, 0 },
+{"fmvp.q.x",   64, INSN_CLASS_Q_AND_ZFA,   "D,s,t", MATCH_FMVP_Q_X, MASK_FMVP_Q_X, match_opcode, 0 },
+{"fltq.s",      0, INSN_CLASS_ZFA,         "d,S,T", MATCH_FLTQ_S, MASK_FLTQ_S, match_opcode, 0 },
+{"fleq.s",      0, INSN_CLASS_ZFA,         "d,S,T", MATCH_FLEQ_S, MASK_FLEQ_S, match_opcode, 0 },
+{"fltq.d",      0, INSN_CLASS_D_AND_ZFA,   "d,S,T", MATCH_FLTQ_D, MASK_FLTQ_D, match_opcode, 0 },
+{"fleq.d",      0, INSN_CLASS_D_AND_ZFA,   "d,S,T", MATCH_FLEQ_D, MASK_FLEQ_D, match_opcode, 0 },
+{"fltq.q",      0, INSN_CLASS_Q_AND_ZFA,   "d,S,T", MATCH_FLTQ_Q, MASK_FLTQ_Q, match_opcode, 0 },
+{"fleq.q",      0, INSN_CLASS_Q_AND_ZFA,   "d,S,T", MATCH_FLEQ_Q, MASK_FLEQ_Q, match_opcode, 0 },
+{"fltq.h",      0, INSN_CLASS_ZFH_AND_ZFA, "d,S,T", MATCH_FLTQ_H, MASK_FLTQ_H, match_opcode, 0 },
+{"fleq.h",      0, INSN_CLASS_ZFH_AND_ZFA, "d,S,T", MATCH_FLEQ_H, MASK_FLEQ_H, match_opcode, 0 },
+
 /* Zbb or zbkb instructions.  */
 {"clz",        0, INSN_CLASS_ZBB,  "d,s",   MATCH_CLZ, MASK_CLZ, match_opcode, 0 },
 {"ctz",        0, INSN_CLASS_ZBB,  "d,s",   MATCH_CTZ, MASK_CTZ, match_opcode, 0 },
-- 
2.39.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension
  2023-03-27  8:01 ` [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension Christoph Muellner
@ 2023-03-27  8:09   ` Kito Cheng
  2023-03-27  8:26     ` Christoph Müllner
  2023-03-27  8:38   ` Jan Beulich
  1 sibling, 1 reply; 15+ messages in thread
From: Kito Cheng @ 2023-03-27  8:09 UTC (permalink / raw)
  To: Christoph Muellner
  Cc: binutils, Nelson Chu, Andrew Waterman, Palmer Dabbelt,
	Jim Wilson, Philipp Tomsich, Jeff Law, Tsukasa OI

Could you add support for hex floating point value as operand input of
fli instruction?

On Mon, Mar 27, 2023 at 4:03 PM Christoph Muellner
<christoph.muellner@vrull.eu> wrote:
>
> From: Christoph Müllner <christoph.muellner@vrull.eu>
>
> This patch introduces the RISC-V Zfa extension, which introduces
> additional floating-point extensions:
> * 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 float register bigger than XLEN
> * Quiet comparison instructions (fleq/fltq)
>
> 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 assembly mnemonic.
>
> 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 (validate_riscv_insn): Add support for
>         new format string directive 'Wfv'.
>         (riscv_ip): Likewise.
>         * 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>
> ---
>  bfd/elfxx-riscv.c                  | 39 ++++++++++++
>  gas/config/tc-riscv.c              | 25 ++++++++
>  gas/testsuite/gas/riscv/zfa-32.d   | 10 +++
>  gas/testsuite/gas/riscv/zfa-32.s   |  3 +
>  gas/testsuite/gas/riscv/zfa-64.d   | 10 +++
>  gas/testsuite/gas/riscv/zfa-64.s   |  3 +
>  gas/testsuite/gas/riscv/zfa-fail.d |  2 +
>  gas/testsuite/gas/riscv/zfa-fail.l | 33 ++++++++++
>  gas/testsuite/gas/riscv/zfa-fail.s | 26 ++++++++
>  gas/testsuite/gas/riscv/zfa.d      | 89 +++++++++++++++++++++++++++
>  gas/testsuite/gas/riscv/zfa.s      | 87 ++++++++++++++++++++++++++
>  include/opcode/riscv-opc.h         | 99 ++++++++++++++++++++++++++++++
>  include/opcode/riscv.h             |  5 ++
>  opcodes/riscv-dis.c                | 12 ++++
>  opcodes/riscv-opc.c                | 53 ++++++++++++++++
>  15 files changed, 496 insertions(+)
>  create mode 100644 gas/testsuite/gas/riscv/zfa-32.d
>  create mode 100644 gas/testsuite/gas/riscv/zfa-32.s
>  create mode 100644 gas/testsuite/gas/riscv/zfa-64.d
>  create mode 100644 gas/testsuite/gas/riscv/zfa-64.s
>  create mode 100644 gas/testsuite/gas/riscv/zfa-fail.d
>  create mode 100644 gas/testsuite/gas/riscv/zfa-fail.l
>  create mode 100644 gas/testsuite/gas/riscv/zfa-fail.s
>  create mode 100644 gas/testsuite/gas/riscv/zfa.d
>  create mode 100644 gas/testsuite/gas/riscv/zfa.s
>
> diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
> index 19391d94e30..d57fe2400fd 100644
> --- a/bfd/elfxx-riscv.c
> +++ b/bfd/elfxx-riscv.c
> @@ -1078,6 +1078,7 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
>    {"zvl256b", "zvl128b",       check_implicit_always},
>    {"zvl128b", "zvl64b",                check_implicit_always},
>    {"zvl64b", "zvl32b",         check_implicit_always},
> +  {"zfa", "f",         check_implicit_always},
>    {"d", "f",           check_implicit_always},
>    {"zfh", "zfhmin",    check_implicit_always},
>    {"zfhmin", "f",      check_implicit_always},
> @@ -1175,6 +1176,7 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] =
>    {"zihintpause",      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 },
>    {"zfh",              ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
>    {"zfhmin",           ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
>    {"zfinx",            ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
> @@ -2313,6 +2315,17 @@ 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_ZFA:
> +      return riscv_subset_supports (rps, "zfa");
> +    case INSN_CLASS_D_AND_ZFA:
> +      return riscv_subset_supports (rps, "d")
> +            && riscv_subset_supports (rps, "zfa");
> +    case INSN_CLASS_Q_AND_ZFA:
> +      return riscv_subset_supports (rps, "q")
> +            && riscv_subset_supports (rps, "zfa");
> +    case INSN_CLASS_ZFH_AND_ZFA:
> +      return riscv_subset_supports (rps, "zfh")
> +            && riscv_subset_supports (rps, "zfa");
>      case INSN_CLASS_ZBA:
>        return riscv_subset_supports (rps, "zba");
>      case INSN_CLASS_ZBB:
> @@ -2479,6 +2492,32 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
>         return "zhinxmin";
>        else
>         return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
> +    case INSN_CLASS_ZFA:
> +      return "zfa";
> +    case INSN_CLASS_D_AND_ZFA:
> +      if (!riscv_subset_supports (rps, "d")
> +         && !riscv_subset_supports (rps, "zfa"))
> +       return _("d' and `zfa");
> +      else if (!riscv_subset_supports (rps, "d"))
> +       return "d";
> +      else
> +       return "zfa";
> +    case INSN_CLASS_Q_AND_ZFA:
> +      if (!riscv_subset_supports (rps, "q")
> +         && !riscv_subset_supports (rps, "zfa"))
> +       return _("q' and `zfa");
> +      else if (!riscv_subset_supports (rps, "q"))
> +       return "q";
> +      else
> +       return "zfa";
> +    case INSN_CLASS_ZFH_AND_ZFA:
> +      if (!riscv_subset_supports (rps, "zfh")
> +         && !riscv_subset_supports (rps, "zfa"))
> +       return _("zfh' and `zfa");
> +      else if (!riscv_subset_supports (rps, "zfh"))
> +       return "zfh";
> +      else
> +       return "zfa";
>      case INSN_CLASS_ZBA:
>        return "zba";
>      case INSN_CLASS_ZBB:
> diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
> index 4eff07a6d4a..1e301568080 100644
> --- a/gas/config/tc-riscv.c
> +++ b/gas/config/tc-riscv.c
> @@ -1399,6 +1399,14 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
>                   goto unknown_validate_operand;
>                 }
>               break;
> +           case 'f':
> +             switch (*++oparg)
> +               {
> +               case 'v': USE_BITS (OP_MASK_RS1, OP_SH_RS1); break;
> +               default:
> +                 goto unknown_validate_operand;
> +               }
> +             break;
>             default:
>               goto unknown_validate_operand;
>             }
> @@ -3461,6 +3469,23 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
>                       goto unknown_riscv_ip_operand;
>                     }
>                   break;
> +               case 'f':
> +                 switch (*++oparg)
> +                   {
> +                   case 'v':
> +                     /* FLI.[HSDQ] value field for 'Zfa' extension.  */
> +                     if (!arg_lookup (&asarg, riscv_fli_value,
> +                                      ARRAY_SIZE (riscv_fli_value), &regno))
> +                       {
> +                         as_bad (_("improper fli value operand"));
> +                         break;
> +                       }
> +                     INSERT_OPERAND (RS1, *ip, regno);
> +                     continue;
> +                   default:
> +                     goto unknown_riscv_ip_operand;
> +                   }
> +                 break;
>                 default:
>                   goto unknown_riscv_ip_operand;
>                 }
> diff --git a/gas/testsuite/gas/riscv/zfa-32.d b/gas/testsuite/gas/riscv/zfa-32.d
> new file mode 100644
> index 00000000000..48e20bf4675
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zfa-32.d
> @@ -0,0 +1,10 @@
> +#as: -march=rv32id_zfa
> +#objdump: -d
> +
> +.*:[   ]+file format .*
> +
> +Disassembly of section .text:
> +
> +0+000 <target>:
> +[      ]+[0-9a-f]+:[   ]+e2108553[     ]+fmvh\.x\.d[   ]+a0,ft1
> +[      ]+[0-9a-f]+:[   ]+b2b500d3[     ]+fmvp\.d\.x[   ]+ft1,a0,a1
> diff --git a/gas/testsuite/gas/riscv/zfa-32.s b/gas/testsuite/gas/riscv/zfa-32.s
> new file mode 100644
> index 00000000000..da95441cdc7
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zfa-32.s
> @@ -0,0 +1,3 @@
> +target:
> +       fmvh.x.d        a0, ft1
> +       fmvp.d.x        ft1, a0, a1
> diff --git a/gas/testsuite/gas/riscv/zfa-64.d b/gas/testsuite/gas/riscv/zfa-64.d
> new file mode 100644
> index 00000000000..48b6d74ed9b
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zfa-64.d
> @@ -0,0 +1,10 @@
> +#as: -march=rv64iq_zfa
> +#objdump: -d
> +
> +.*:[   ]+file format .*
> +
> +Disassembly of section .text:
> +
> +0+000 <target>:
> +[      ]+[0-9a-f]+:[   ]+e6108553[     ]+fmvh\.x\.q[   ]+a0,ft1
> +[      ]+[0-9a-f]+:[   ]+b6b500d3[     ]+fmvp\.q\.x[   ]+ft1,a0,a1
> diff --git a/gas/testsuite/gas/riscv/zfa-64.s b/gas/testsuite/gas/riscv/zfa-64.s
> new file mode 100644
> index 00000000000..dc8129dae3e
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zfa-64.s
> @@ -0,0 +1,3 @@
> +target:
> +       fmvh.x.q        a0, ft1
> +       fmvp.q.x        ft1, a0, a1
> diff --git a/gas/testsuite/gas/riscv/zfa-fail.d b/gas/testsuite/gas/riscv/zfa-fail.d
> new file mode 100644
> index 00000000000..d9d4a36c65c
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zfa-fail.d
> @@ -0,0 +1,2 @@
> +#as: -march=rv64iq_zfa_zfh
> +#error_output: zfa-fail.l
> diff --git a/gas/testsuite/gas/riscv/zfa-fail.l b/gas/testsuite/gas/riscv/zfa-fail.l
> new file mode 100644
> index 00000000000..19b6ff4967d
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zfa-fail.l
> @@ -0,0 +1,33 @@
> +.*: Assembler messages:
> +.*: Error: improper fli value operand
> +.*: Error: illegal operands `fli\.s ft1,1'
> +.*: Error: improper fli value operand
> +.*: Error: illegal operands `fli\.d ft1,-1'
> +.*: Error: improper fli value operand
> +.*: Error: illegal operands `fli\.q ft1,1.250'
> +.*: Error: improper fli value operand
> +.*: Error: illegal operands `fli\.h ft1,8'
> +.*: Error: improper fli value operand
> +.*: Error: illegal operands `fli\.s ft1,infinity'
> +.*: Error: improper fli value operand
> +.*: Error: illegal operands `fli\.d ft1,invalid'
> +.*: Error: improper fli value operand
> +.*: Error: illegal operands `fli\.q ft1,30'
> +.*: Error: improper fli value operand
> +.*: Error: illegal operands `fli\.h ft1,31'
> +.*: Error: improper fli value operand
> +.*: Error: illegal operands `fli\.s ft1,32'
> +.*: Error: improper fli value operand
> +.*: Error: illegal operands `fli\.d ft1,0'
> +.*: Error: improper fli value operand
> +.*: Error: illegal operands `fli\.q ft1,0.0'
> +.*: Error: improper fli value operand
> +.*: Error: illegal operands `fli\.h ft1,-0.0'
> +.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1'
> +.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,rne'
> +.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,rdn'
> +.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,rup'
> +.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,rmm'
> +.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,dyn'
> +.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,invalid'
> +
> diff --git a/gas/testsuite/gas/riscv/zfa-fail.s b/gas/testsuite/gas/riscv/zfa-fail.s
> new file mode 100644
> index 00000000000..e6c6bdc909a
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zfa-fail.s
> @@ -0,0 +1,26 @@
> +target:
> +       # fli.[sdqh]: Invalid value field
> +       fli.s   ft1, 1
> +       fli.d   ft1, -1
> +       fli.q   ft1, 1.250
> +       fli.h   ft1, 8
> +       fli.s   ft1, infinity
> +       fli.d   ft1, invalid
> +       fli.q   ft1, 30
> +       fli.h   ft1, 31
> +       fli.s   ft1, 32
> +       fli.d   ft1, 0
> +       fli.q   ft1, 0.0
> +       fli.h   ft1, -0.0
> +
> +       # fcvtmod.w.d: Requires explicit rounding mode.
> +       fcvtmod.w.d     a0, ft1
> +
> +       # fcvtmod.w.d: Rounding mode other than rtz are reserved.
> +       fcvtmod.w.d     a0, ft1, rne
> +       fcvtmod.w.d     a0, ft1, rdn
> +       fcvtmod.w.d     a0, ft1, rup
> +       fcvtmod.w.d     a0, ft1, rmm
> +       fcvtmod.w.d     a0, ft1, dyn
> +       # fcvtmod.w.d: Invalid rounding mode is invalid.
> +       fcvtmod.w.d     a0, ft1, invalid
> diff --git a/gas/testsuite/gas/riscv/zfa.d b/gas/testsuite/gas/riscv/zfa.d
> new file mode 100644
> index 00000000000..a6f1f81db29
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zfa.d
> @@ -0,0 +1,89 @@
> +#as: -march=rv32iq_zfa_zfh
> +#objdump: -d
> +
> +.*:[   ]+file format .*
> +
> +Disassembly of section .text:
> +
> +0+000 <target>:
> +[      ]+[0-9a-f]+:[   ]+f01000d3[     ]+fli\.s[               ]+ft1,-1.0
> +[      ]+[0-9a-f]+:[   ]+f01080d3[     ]+fli\.s[               ]+ft1,min
> +[      ]+[0-9a-f]+:[   ]+f01100d3[     ]+fli\.s[               ]+ft1,0.0000152587890625
> +[      ]+[0-9a-f]+:[   ]+f01180d3[     ]+fli\.s[               ]+ft1,0.000030517578125
> +[      ]+[0-9a-f]+:[   ]+f01200d3[     ]+fli\.s[               ]+ft1,0.00390625
> +[      ]+[0-9a-f]+:[   ]+f01280d3[     ]+fli\.s[               ]+ft1,0.0078125
> +[      ]+[0-9a-f]+:[   ]+f01300d3[     ]+fli\.s[               ]+ft1,0.0625
> +[      ]+[0-9a-f]+:[   ]+f01380d3[     ]+fli\.s[               ]+ft1,0.125
> +[      ]+[0-9a-f]+:[   ]+f21400d3[     ]+fli\.d[               ]+ft1,0.25
> +[      ]+[0-9a-f]+:[   ]+f21480d3[     ]+fli\.d[               ]+ft1,0.3125
> +[      ]+[0-9a-f]+:[   ]+f21500d3[     ]+fli\.d[               ]+ft1,0.375
> +[      ]+[0-9a-f]+:[   ]+f21580d3[     ]+fli\.d[               ]+ft1,0.4375
> +[      ]+[0-9a-f]+:[   ]+f21600d3[     ]+fli\.d[               ]+ft1,0.5
> +[      ]+[0-9a-f]+:[   ]+f21680d3[     ]+fli\.d[               ]+ft1,0.625
> +[      ]+[0-9a-f]+:[   ]+f21700d3[     ]+fli\.d[               ]+ft1,0.75
> +[      ]+[0-9a-f]+:[   ]+f21780d3[     ]+fli\.d[               ]+ft1,0.875
> +[      ]+[0-9a-f]+:[   ]+f61800d3[     ]+fli\.q[               ]+ft1,1.0
> +[      ]+[0-9a-f]+:[   ]+f61880d3[     ]+fli\.q[               ]+ft1,1.25
> +[      ]+[0-9a-f]+:[   ]+f61900d3[     ]+fli\.q[               ]+ft1,1.5
> +[      ]+[0-9a-f]+:[   ]+f61980d3[     ]+fli\.q[               ]+ft1,1.75
> +[      ]+[0-9a-f]+:[   ]+f61a00d3[     ]+fli\.q[               ]+ft1,2.0
> +[      ]+[0-9a-f]+:[   ]+f61a80d3[     ]+fli\.q[               ]+ft1,2.5
> +[      ]+[0-9a-f]+:[   ]+f61b00d3[     ]+fli\.q[               ]+ft1,3.0
> +[      ]+[0-9a-f]+:[   ]+f61b80d3[     ]+fli\.q[               ]+ft1,4.0
> +[      ]+[0-9a-f]+:[   ]+f41c00d3[     ]+fli\.h[               ]+ft1,8.0
> +[      ]+[0-9a-f]+:[   ]+f41c80d3[     ]+fli\.h[               ]+ft1,16.0
> +[      ]+[0-9a-f]+:[   ]+f41d00d3[     ]+fli\.h[               ]+ft1,128.0
> +[      ]+[0-9a-f]+:[   ]+f41d80d3[     ]+fli\.h[               ]+ft1,256.0
> +[      ]+[0-9a-f]+:[   ]+f41e00d3[     ]+fli\.h[               ]+ft1,32768.0
> +[      ]+[0-9a-f]+:[   ]+f41e80d3[     ]+fli\.h[               ]+ft1,65536.0
> +[      ]+[0-9a-f]+:[   ]+f41f00d3[     ]+fli\.h[               ]+ft1,inf
> +[      ]+[0-9a-f]+:[   ]+f41f80d3[     ]+fli\.h[               ]+ft1,nan
> +[      ]+[0-9a-f]+:[   ]+2c3100d3[     ]+fmin\.h[              ]+ft1,ft2,ft3
> +[      ]+[0-9a-f]+:[   ]+2c3120d3[     ]+fminm\.h[             ]+ft1,ft2,ft3
> +[      ]+[0-9a-f]+:[   ]+283100d3[     ]+fmin\.s[              ]+ft1,ft2,ft3
> +[      ]+[0-9a-f]+:[   ]+283120d3[     ]+fminm\.s[             ]+ft1,ft2,ft3
> +[      ]+[0-9a-f]+:[   ]+2a3100d3[     ]+fmin\.d[              ]+ft1,ft2,ft3
> +[      ]+[0-9a-f]+:[   ]+2a3120d3[     ]+fminm\.d[             ]+ft1,ft2,ft3
> +[      ]+[0-9a-f]+:[   ]+2e3100d3[     ]+fmin\.q[              ]+ft1,ft2,ft3
> +[      ]+[0-9a-f]+:[   ]+2e3120d3[     ]+fminm\.q[             ]+ft1,ft2,ft3
> +[      ]+[0-9a-f]+:[   ]+2c3110d3[     ]+fmax\.h[              ]+ft1,ft2,ft3
> +[      ]+[0-9a-f]+:[   ]+2c3130d3[     ]+fmaxm\.h[             ]+ft1,ft2,ft3
> +[      ]+[0-9a-f]+:[   ]+283110d3[     ]+fmax\.s[              ]+ft1,ft2,ft3
> +[      ]+[0-9a-f]+:[   ]+283130d3[     ]+fmaxm\.s[             ]+ft1,ft2,ft3
> +[      ]+[0-9a-f]+:[   ]+2a3110d3[     ]+fmax\.d[              ]+ft1,ft2,ft3
> +[      ]+[0-9a-f]+:[   ]+2a3130d3[     ]+fmaxm\.d[             ]+ft1,ft2,ft3
> +[      ]+[0-9a-f]+:[   ]+2e3110d3[     ]+fmax\.q[              ]+ft1,ft2,ft3
> +[      ]+[0-9a-f]+:[   ]+2e3130d3[     ]+fmaxm\.q[             ]+ft1,ft2,ft3
> +[      ]+[0-9a-f]+:[   ]+4445f553[     ]+fround\.h[            ]+fa0,fa1
> +[      ]+[0-9a-f]+:[   ]+44459553[     ]+fround\.h[            ]+fa0,fa1,rtz
> +[      ]+[0-9a-f]+:[   ]+4045f553[     ]+fround\.s[            ]+fa0,fa1
> +[      ]+[0-9a-f]+:[   ]+40459553[     ]+fround\.s[            ]+fa0,fa1,rtz
> +[      ]+[0-9a-f]+:[   ]+4245f553[     ]+fround\.d[            ]+fa0,fa1
> +[      ]+[0-9a-f]+:[   ]+42459553[     ]+fround\.d[            ]+fa0,fa1,rtz
> +[      ]+[0-9a-f]+:[   ]+4645f553[     ]+fround\.q[            ]+fa0,fa1
> +[      ]+[0-9a-f]+:[   ]+46459553[     ]+fround\.q[            ]+fa0,fa1,rtz
> +[      ]+[0-9a-f]+:[   ]+4455f553[     ]+froundnx\.h[          ]+fa0,fa1
> +[      ]+[0-9a-f]+:[   ]+44559553[     ]+froundnx\.h[          ]+fa0,fa1,rtz
> +[      ]+[0-9a-f]+:[   ]+4055f553[     ]+froundnx\.s[          ]+fa0,fa1
> +[      ]+[0-9a-f]+:[   ]+40559553[     ]+froundnx\.s[          ]+fa0,fa1,rtz
> +[      ]+[0-9a-f]+:[   ]+4255f553[     ]+froundnx\.d[          ]+fa0,fa1
> +[      ]+[0-9a-f]+:[   ]+42559553[     ]+froundnx\.d[          ]+fa0,fa1,rtz
> +[      ]+[0-9a-f]+:[   ]+4655f553[     ]+froundnx\.q[          ]+fa0,fa1
> +[      ]+[0-9a-f]+:[   ]+46559553[     ]+froundnx\.q[          ]+fa0,fa1,rtz
> +[      ]+[0-9a-f]+:[   ]+c2809553[     ]+fcvtmod\.w\.d[        ]+a0,ft1,rtz
> +[      ]+[0-9a-f]+:[   ]+a4209553[     ]+flt\.h[               ]+a0,ft1,ft2
> +[      ]+[0-9a-f]+:[   ]+a420d553[     ]+fltq\.h[              ]+a0,ft1,ft2
> +[      ]+[0-9a-f]+:[   ]+a0209553[     ]+flt\.s[               ]+a0,ft1,ft2
> +[      ]+[0-9a-f]+:[   ]+a020d553[     ]+fltq\.s[              ]+a0,ft1,ft2
> +[      ]+[0-9a-f]+:[   ]+a2209553[     ]+flt\.d[               ]+a0,ft1,ft2
> +[      ]+[0-9a-f]+:[   ]+a220d553[     ]+fltq\.d[              ]+a0,ft1,ft2
> +[      ]+[0-9a-f]+:[   ]+a6209553[     ]+flt\.q[               ]+a0,ft1,ft2
> +[      ]+[0-9a-f]+:[   ]+a620d553[     ]+fltq\.q[              ]+a0,ft1,ft2
> +[      ]+[0-9a-f]+:[   ]+a4208553[     ]+fle\.h[               ]+a0,ft1,ft2
> +[      ]+[0-9a-f]+:[   ]+a420c553[     ]+fleq\.h[              ]+a0,ft1,ft2
> +[      ]+[0-9a-f]+:[   ]+a0208553[     ]+fle\.s[               ]+a0,ft1,ft2
> +[      ]+[0-9a-f]+:[   ]+a020c553[     ]+fleq\.s[              ]+a0,ft1,ft2
> +[      ]+[0-9a-f]+:[   ]+a2208553[     ]+fle\.d[               ]+a0,ft1,ft2
> +[      ]+[0-9a-f]+:[   ]+a220c553[     ]+fleq\.d[              ]+a0,ft1,ft2
> +[      ]+[0-9a-f]+:[   ]+a6208553[     ]+fle\.q[               ]+a0,ft1,ft2
> +[      ]+[0-9a-f]+:[   ]+a620c553[     ]+fleq\.q[              ]+a0,ft1,ft2
> diff --git a/gas/testsuite/gas/riscv/zfa.s b/gas/testsuite/gas/riscv/zfa.s
> new file mode 100644
> index 00000000000..906e8a4a56d
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zfa.s
> @@ -0,0 +1,87 @@
> +target:
> +       # fli
> +       fli.s           ft1, -1.0
> +       fli.s           ft1, min
> +       fli.s           ft1, 0.0000152587890625
> +       fli.s           ft1, 0.000030517578125
> +       fli.s           ft1, 0.00390625
> +       fli.s           ft1, 0.0078125
> +       fli.s           ft1, 0.0625
> +       fli.s           ft1, 0.125
> +       fli.d           ft1, 0.25
> +       fli.d           ft1, 0.3125
> +       fli.d           ft1, 0.375
> +       fli.d           ft1, 0.4375
> +       fli.d           ft1, 0.5
> +       fli.d           ft1, 0.625
> +       fli.d           ft1, 0.75
> +       fli.d           ft1, 0.875
> +       fli.q           ft1, 1.0
> +       fli.q           ft1, 1.25
> +       fli.q           ft1, 1.5
> +       fli.q           ft1, 1.75
> +       fli.q           ft1, 2.0
> +       fli.q           ft1, 2.5
> +       fli.q           ft1, 3.0
> +       fli.q           ft1, 4.0
> +       fli.h           ft1, 8.0
> +       fli.h           ft1, 16.0
> +       fli.h           ft1, 128.0
> +       fli.h           ft1, 256.0
> +       fli.h           ft1, 32768.0
> +       fli.h           ft1, 65536.0
> +       fli.h           ft1, inf
> +       fli.h           ft1, nan
> +       # fminm/fmaxm
> +       fmin.h          ft1, ft2, ft3
> +       fminm.h         ft1, ft2, ft3
> +       fmin.s          ft1, ft2, ft3
> +       fminm.s         ft1, ft2, ft3
> +       fmin.d          ft1, ft2, ft3
> +       fminm.d         ft1, ft2, ft3
> +       fmin.q          ft1, ft2, ft3
> +       fminm.q         ft1, ft2, ft3
> +       fmax.h          ft1, ft2, ft3
> +       fmaxm.h         ft1, ft2, ft3
> +       fmax.s          ft1, ft2, ft3
> +       fmaxm.s         ft1, ft2, ft3
> +       fmax.d          ft1, ft2, ft3
> +       fmaxm.d         ft1, ft2, ft3
> +       fmax.q          ft1, ft2, ft3
> +       fmaxm.q         ft1, ft2, ft3
> +       # fround/froundnx
> +       fround.h        fa0, fa1
> +       fround.h        fa0, fa1, rtz
> +       fround.s        fa0, fa1
> +       fround.s        fa0, fa1, rtz
> +       fround.d        fa0, fa1
> +       fround.d        fa0, fa1, rtz
> +       fround.q        fa0, fa1
> +       fround.q        fa0, fa1, rtz
> +       froundnx.h      fa0, fa1
> +       froundnx.h      fa0, fa1, rtz
> +       froundnx.s      fa0, fa1
> +       froundnx.s      fa0, fa1, rtz
> +       froundnx.d      fa0, fa1
> +       froundnx.d      fa0, fa1, rtz
> +       froundnx.q      fa0, fa1
> +       froundnx.q      fa0, fa1, rtz
> +       # fcvtmod.w.d
> +       fcvtmod.w.d     a0, ft1, rtz
> +       # fltq/fleq
> +       flt.h           a0, ft1, ft2
> +       fltq.h          a0, ft1, ft2
> +       flt.s           a0, ft1, ft2
> +       fltq.s          a0, ft1, ft2
> +       flt.d           a0, ft1, ft2
> +       fltq.d          a0, ft1, ft2
> +       flt.q           a0, ft1, ft2
> +       fltq.q          a0, ft1, ft2
> +       fle.h           a0, ft1, ft2
> +       fleq.h          a0, ft1, ft2
> +       fle.s           a0, ft1, ft2
> +       fleq.s          a0, ft1, ft2
> +       fle.d           a0, ft1, ft2
> +       fleq.d          a0, ft1, ft2
> +       fle.q           a0, ft1, ft2
> +       fleq.q          a0, ft1, ft2
> diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h
> index 85d35c1efc9..e141c377bde 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
> @@ -2981,6 +3047,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 b4ae55249bb..1ca698c95ee 100644
> --- a/include/opcode/riscv.h
> +++ b/include/opcode/riscv.h
> @@ -388,6 +388,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,
> @@ -554,6 +558,7 @@ 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_value[32];
>
>  extern const struct riscv_opcode riscv_opcodes[];
>  extern const struct riscv_opcode riscv_insn_types[];
> diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
> index 77a18b08599..edb599e1741 100644
> --- a/opcodes/riscv-dis.c
> +++ b/opcodes/riscv-dis.c
> @@ -592,6 +592,17 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
>                     goto undefined_modifier;
>                   }
>                   break;
> +             case 'f':
> +               switch (*++oparg)
> +                 {
> +                 case 'v':
> +                   print (info->stream, dis_style_text, "%s",
> +                          riscv_fli_value[rs1]);
> +                   break;
> +                 default:
> +                   goto undefined_modifier;
> +                 }
> +               break;
>               default:
>                 goto undefined_modifier;
>               }
> @@ -640,6 +651,7 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
>               }
>           }
>           break;
> +
>         default:
>         undefined_modifier:
>           /* xgettext:c-format */
> diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
> index d9d69cda548..424969fbe57 100644
> --- a/opcodes/riscv-opc.c
> +++ b/opcodes/riscv-opc.c
> @@ -110,6 +110,16 @@ const char * const riscv_vma[2] =
>    "mu", "ma"
>  };
>
> +/* The FLI.[HSDQ] value constants.  */
> +const char * const riscv_fli_value[32] =
> +{
> +  "-1.0", "min", "0.0000152587890625", "0.000030517578125",
> +  "0.00390625", "0.0078125", "0.0625", "0.125",
> +  "0.25", "0.3125", "0.375", "0.4375", "0.5", "0.625", "0.75", "0.875",
> +  "1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "4.0",
> +  "8.0", "16.0", "128.0", "256.0", "32768.0", "65536.0",  "inf", "nan",
> +};
> +
>  /* The order of overloaded instructions matters.  Label arguments and
>     register arguments look the same. Instructions that can have either
>     for arguments must apear in the correct order in this table for the
> @@ -939,6 +949,49 @@ const struct riscv_opcode riscv_opcodes[] =
>  {"wrs.nto",    0, INSN_CLASS_ZAWRS, "", MATCH_WRS_NTO, MASK_WRS_NTO, match_opcode, 0 },
>  {"wrs.sto",    0, INSN_CLASS_ZAWRS, "", MATCH_WRS_STO, MASK_WRS_STO, match_opcode, 0 },
>
> +/* Zfa instructions.  */
> +{"fli.s",       0, INSN_CLASS_ZFA,         "D,Wfv", MATCH_FLI_S, MASK_FLI_S, match_opcode, 0 },
> +{"fli.d",       0, INSN_CLASS_D_AND_ZFA,   "D,Wfv", MATCH_FLI_D, MASK_FLI_D, match_opcode, 0 },
> +{"fli.q",       0, INSN_CLASS_Q_AND_ZFA,   "D,Wfv", MATCH_FLI_Q, MASK_FLI_Q, match_opcode, 0 },
> +{"fli.h",       0, INSN_CLASS_ZFH_AND_ZFA, "D,Wfv", MATCH_FLI_H, MASK_FLI_H, match_opcode, 0 },
> +{"fminm.s",     0, INSN_CLASS_ZFA,         "D,S,T", MATCH_FMINM_S, MASK_FMINM_S, match_opcode, 0 },
> +{"fmaxm.s",     0, INSN_CLASS_ZFA,         "D,S,T", MATCH_FMAXM_S, MASK_FMAXM_S, match_opcode, 0 },
> +{"fminm.d",     0, INSN_CLASS_D_AND_ZFA,   "D,S,T", MATCH_FMINM_D, MASK_FMINM_D, match_opcode, 0 },
> +{"fmaxm.d",     0, INSN_CLASS_D_AND_ZFA,   "D,S,T", MATCH_FMAXM_D, MASK_FMAXM_D, match_opcode, 0 },
> +{"fminm.q",     0, INSN_CLASS_Q_AND_ZFA,   "D,S,T", MATCH_FMINM_Q, MASK_FMINM_Q, match_opcode, 0 },
> +{"fmaxm.q",     0, INSN_CLASS_Q_AND_ZFA,   "D,S,T", MATCH_FMAXM_Q, MASK_FMAXM_Q, match_opcode, 0 },
> +{"fminm.h",     0, INSN_CLASS_ZFH_AND_ZFA, "D,S,T", MATCH_FMINM_H, MASK_FMINM_H, match_opcode, 0 },
> +{"fmaxm.h",     0, INSN_CLASS_ZFH_AND_ZFA, "D,S,T", MATCH_FMAXM_H, MASK_FMAXM_H, match_opcode, 0 },
> +{"fround.s",    0, INSN_CLASS_ZFA,         "D,S",   MATCH_FROUND_S|MASK_RM, MASK_FROUND_S|MASK_RM, match_opcode, 0 },
> +{"fround.s",    0, INSN_CLASS_ZFA,         "D,S,m", MATCH_FROUND_S, MASK_FROUND_S, match_opcode, 0 },
> +{"froundnx.s",  0, INSN_CLASS_ZFA,         "D,S",   MATCH_FROUNDNX_S|MASK_RM, MASK_FROUNDNX_S|MASK_RM, match_opcode, 0 },
> +{"froundnx.s",  0, INSN_CLASS_ZFA,         "D,S,m", MATCH_FROUNDNX_S, MASK_FROUNDNX_S, match_opcode, 0 },
> +{"fround.d",    0, INSN_CLASS_D_AND_ZFA,   "D,S",   MATCH_FROUND_D|MASK_RM, MASK_FROUND_D|MASK_RM, match_opcode, 0 },
> +{"fround.d",    0, INSN_CLASS_D_AND_ZFA,   "D,S,m", MATCH_FROUND_D, MASK_FROUND_D, match_opcode, 0 },
> +{"froundnx.d",  0, INSN_CLASS_D_AND_ZFA,   "D,S",   MATCH_FROUNDNX_D|MASK_RM, MASK_FROUNDNX_D|MASK_RM, match_opcode, 0 },
> +{"froundnx.d",  0, INSN_CLASS_D_AND_ZFA,   "D,S,m", MATCH_FROUNDNX_D, MASK_FROUNDNX_D, match_opcode, 0 },
> +{"fround.q",    0, INSN_CLASS_Q_AND_ZFA,   "D,S",   MATCH_FROUND_Q|MASK_RM, MASK_FROUND_Q|MASK_RM, match_opcode, 0 },
> +{"fround.q",    0, INSN_CLASS_Q_AND_ZFA,   "D,S,m", MATCH_FROUND_Q, MASK_FROUND_Q, match_opcode, 0 },
> +{"froundnx.q",  0, INSN_CLASS_Q_AND_ZFA,   "D,S",   MATCH_FROUNDNX_Q|MASK_RM, MASK_FROUNDNX_Q|MASK_RM, match_opcode, 0 },
> +{"froundnx.q",  0, INSN_CLASS_Q_AND_ZFA,   "D,S,m", MATCH_FROUNDNX_Q, MASK_FROUNDNX_Q, match_opcode, 0 },
> +{"fround.h",    0, INSN_CLASS_ZFH_AND_ZFA, "D,S",   MATCH_FROUND_H|MASK_RM, MASK_FROUND_H|MASK_RM, match_opcode, 0 },
> +{"fround.h",    0, INSN_CLASS_ZFH_AND_ZFA, "D,S,m", MATCH_FROUND_H, MASK_FROUND_H, match_opcode, 0 },
> +{"froundnx.h",  0, INSN_CLASS_ZFH_AND_ZFA, "D,S",   MATCH_FROUNDNX_H|MASK_RM, MASK_FROUNDNX_H|MASK_RM, match_opcode, 0 },
> +{"froundnx.h",  0, INSN_CLASS_ZFH_AND_ZFA, "D,S,m", MATCH_FROUNDNX_H, MASK_FROUNDNX_H, match_opcode, 0 },
> +{"fcvtmod.w.d", 0, INSN_CLASS_D_AND_ZFA,   "d,S,m", MATCH_FCVTMOD_W_D, MASK_FCVTMOD_W_D, match_opcode, 0 },
> +{"fmvh.x.d",   32, INSN_CLASS_D_AND_ZFA,   "d,S",   MATCH_FMVH_X_D, MASK_FMVH_X_D, match_opcode, 0 },
> +{"fmvp.d.x",   32, INSN_CLASS_D_AND_ZFA,   "D,s,t", MATCH_FMVP_D_X, MASK_FMVP_D_X, match_opcode, 0 },
> +{"fmvh.x.q",   64, INSN_CLASS_Q_AND_ZFA,   "d,S",   MATCH_FMVH_X_Q, MASK_FMVH_X_Q, match_opcode, 0 },
> +{"fmvp.q.x",   64, INSN_CLASS_Q_AND_ZFA,   "D,s,t", MATCH_FMVP_Q_X, MASK_FMVP_Q_X, match_opcode, 0 },
> +{"fltq.s",      0, INSN_CLASS_ZFA,         "d,S,T", MATCH_FLTQ_S, MASK_FLTQ_S, match_opcode, 0 },
> +{"fleq.s",      0, INSN_CLASS_ZFA,         "d,S,T", MATCH_FLEQ_S, MASK_FLEQ_S, match_opcode, 0 },
> +{"fltq.d",      0, INSN_CLASS_D_AND_ZFA,   "d,S,T", MATCH_FLTQ_D, MASK_FLTQ_D, match_opcode, 0 },
> +{"fleq.d",      0, INSN_CLASS_D_AND_ZFA,   "d,S,T", MATCH_FLEQ_D, MASK_FLEQ_D, match_opcode, 0 },
> +{"fltq.q",      0, INSN_CLASS_Q_AND_ZFA,   "d,S,T", MATCH_FLTQ_Q, MASK_FLTQ_Q, match_opcode, 0 },
> +{"fleq.q",      0, INSN_CLASS_Q_AND_ZFA,   "d,S,T", MATCH_FLEQ_Q, MASK_FLEQ_Q, match_opcode, 0 },
> +{"fltq.h",      0, INSN_CLASS_ZFH_AND_ZFA, "d,S,T", MATCH_FLTQ_H, MASK_FLTQ_H, match_opcode, 0 },
> +{"fleq.h",      0, INSN_CLASS_ZFH_AND_ZFA, "d,S,T", MATCH_FLEQ_H, MASK_FLEQ_H, match_opcode, 0 },
> +
>  /* Zbb or zbkb instructions.  */
>  {"clz",        0, INSN_CLASS_ZBB,  "d,s",   MATCH_CLZ, MASK_CLZ, match_opcode, 0 },
>  {"ctz",        0, INSN_CLASS_ZBB,  "d,s",   MATCH_CTZ, MASK_CTZ, match_opcode, 0 },
> --
> 2.39.2
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension
  2023-03-27  8:09   ` Kito Cheng
@ 2023-03-27  8:26     ` Christoph Müllner
  0 siblings, 0 replies; 15+ messages in thread
From: Christoph Müllner @ 2023-03-27  8:26 UTC (permalink / raw)
  To: Kito Cheng
  Cc: binutils, Nelson Chu, Andrew Waterman, Palmer Dabbelt,
	Jim Wilson, Philipp Tomsich, Jeff Law, Tsukasa OI

On Mon, Mar 27, 2023 at 10:09 AM Kito Cheng <kito.cheng@gmail.com> wrote:
>
> Could you add support for hex floating point value as operand input of
> fli instruction?

Ok, will do.

So additional support of the following notation will be added:
* fli.d fs1, 0xbff0000000000000 # -1.0
* fli.s fs1, 0xbf800000 # -1.0
* fli.h fs1, 0xbc00 # -1.0
* ...

Note that the floating-point values differ among the different
extensions (F, D, Zfh).




>
> On Mon, Mar 27, 2023 at 4:03 PM Christoph Muellner
> <christoph.muellner@vrull.eu> wrote:
> >
> > From: Christoph Müllner <christoph.muellner@vrull.eu>
> >
> > This patch introduces the RISC-V Zfa extension, which introduces
> > additional floating-point extensions:
> > * 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 float register bigger than XLEN
> > * Quiet comparison instructions (fleq/fltq)
> >
> > 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 assembly mnemonic.
> >
> > 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 (validate_riscv_insn): Add support for
> >         new format string directive 'Wfv'.
> >         (riscv_ip): Likewise.
> >         * 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>
> > ---
> >  bfd/elfxx-riscv.c                  | 39 ++++++++++++
> >  gas/config/tc-riscv.c              | 25 ++++++++
> >  gas/testsuite/gas/riscv/zfa-32.d   | 10 +++
> >  gas/testsuite/gas/riscv/zfa-32.s   |  3 +
> >  gas/testsuite/gas/riscv/zfa-64.d   | 10 +++
> >  gas/testsuite/gas/riscv/zfa-64.s   |  3 +
> >  gas/testsuite/gas/riscv/zfa-fail.d |  2 +
> >  gas/testsuite/gas/riscv/zfa-fail.l | 33 ++++++++++
> >  gas/testsuite/gas/riscv/zfa-fail.s | 26 ++++++++
> >  gas/testsuite/gas/riscv/zfa.d      | 89 +++++++++++++++++++++++++++
> >  gas/testsuite/gas/riscv/zfa.s      | 87 ++++++++++++++++++++++++++
> >  include/opcode/riscv-opc.h         | 99 ++++++++++++++++++++++++++++++
> >  include/opcode/riscv.h             |  5 ++
> >  opcodes/riscv-dis.c                | 12 ++++
> >  opcodes/riscv-opc.c                | 53 ++++++++++++++++
> >  15 files changed, 496 insertions(+)
> >  create mode 100644 gas/testsuite/gas/riscv/zfa-32.d
> >  create mode 100644 gas/testsuite/gas/riscv/zfa-32.s
> >  create mode 100644 gas/testsuite/gas/riscv/zfa-64.d
> >  create mode 100644 gas/testsuite/gas/riscv/zfa-64.s
> >  create mode 100644 gas/testsuite/gas/riscv/zfa-fail.d
> >  create mode 100644 gas/testsuite/gas/riscv/zfa-fail.l
> >  create mode 100644 gas/testsuite/gas/riscv/zfa-fail.s
> >  create mode 100644 gas/testsuite/gas/riscv/zfa.d
> >  create mode 100644 gas/testsuite/gas/riscv/zfa.s
> >
> > diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
> > index 19391d94e30..d57fe2400fd 100644
> > --- a/bfd/elfxx-riscv.c
> > +++ b/bfd/elfxx-riscv.c
> > @@ -1078,6 +1078,7 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
> >    {"zvl256b", "zvl128b",       check_implicit_always},
> >    {"zvl128b", "zvl64b",                check_implicit_always},
> >    {"zvl64b", "zvl32b",         check_implicit_always},
> > +  {"zfa", "f",         check_implicit_always},
> >    {"d", "f",           check_implicit_always},
> >    {"zfh", "zfhmin",    check_implicit_always},
> >    {"zfhmin", "f",      check_implicit_always},
> > @@ -1175,6 +1176,7 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] =
> >    {"zihintpause",      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 },
> >    {"zfh",              ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
> >    {"zfhmin",           ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
> >    {"zfinx",            ISA_SPEC_CLASS_DRAFT,           1, 0,  0 },
> > @@ -2313,6 +2315,17 @@ 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_ZFA:
> > +      return riscv_subset_supports (rps, "zfa");
> > +    case INSN_CLASS_D_AND_ZFA:
> > +      return riscv_subset_supports (rps, "d")
> > +            && riscv_subset_supports (rps, "zfa");
> > +    case INSN_CLASS_Q_AND_ZFA:
> > +      return riscv_subset_supports (rps, "q")
> > +            && riscv_subset_supports (rps, "zfa");
> > +    case INSN_CLASS_ZFH_AND_ZFA:
> > +      return riscv_subset_supports (rps, "zfh")
> > +            && riscv_subset_supports (rps, "zfa");
> >      case INSN_CLASS_ZBA:
> >        return riscv_subset_supports (rps, "zba");
> >      case INSN_CLASS_ZBB:
> > @@ -2479,6 +2492,32 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
> >         return "zhinxmin";
> >        else
> >         return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
> > +    case INSN_CLASS_ZFA:
> > +      return "zfa";
> > +    case INSN_CLASS_D_AND_ZFA:
> > +      if (!riscv_subset_supports (rps, "d")
> > +         && !riscv_subset_supports (rps, "zfa"))
> > +       return _("d' and `zfa");
> > +      else if (!riscv_subset_supports (rps, "d"))
> > +       return "d";
> > +      else
> > +       return "zfa";
> > +    case INSN_CLASS_Q_AND_ZFA:
> > +      if (!riscv_subset_supports (rps, "q")
> > +         && !riscv_subset_supports (rps, "zfa"))
> > +       return _("q' and `zfa");
> > +      else if (!riscv_subset_supports (rps, "q"))
> > +       return "q";
> > +      else
> > +       return "zfa";
> > +    case INSN_CLASS_ZFH_AND_ZFA:
> > +      if (!riscv_subset_supports (rps, "zfh")
> > +         && !riscv_subset_supports (rps, "zfa"))
> > +       return _("zfh' and `zfa");
> > +      else if (!riscv_subset_supports (rps, "zfh"))
> > +       return "zfh";
> > +      else
> > +       return "zfa";
> >      case INSN_CLASS_ZBA:
> >        return "zba";
> >      case INSN_CLASS_ZBB:
> > diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
> > index 4eff07a6d4a..1e301568080 100644
> > --- a/gas/config/tc-riscv.c
> > +++ b/gas/config/tc-riscv.c
> > @@ -1399,6 +1399,14 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
> >                   goto unknown_validate_operand;
> >                 }
> >               break;
> > +           case 'f':
> > +             switch (*++oparg)
> > +               {
> > +               case 'v': USE_BITS (OP_MASK_RS1, OP_SH_RS1); break;
> > +               default:
> > +                 goto unknown_validate_operand;
> > +               }
> > +             break;
> >             default:
> >               goto unknown_validate_operand;
> >             }
> > @@ -3461,6 +3469,23 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
> >                       goto unknown_riscv_ip_operand;
> >                     }
> >                   break;
> > +               case 'f':
> > +                 switch (*++oparg)
> > +                   {
> > +                   case 'v':
> > +                     /* FLI.[HSDQ] value field for 'Zfa' extension.  */
> > +                     if (!arg_lookup (&asarg, riscv_fli_value,
> > +                                      ARRAY_SIZE (riscv_fli_value), &regno))
> > +                       {
> > +                         as_bad (_("improper fli value operand"));
> > +                         break;
> > +                       }
> > +                     INSERT_OPERAND (RS1, *ip, regno);
> > +                     continue;
> > +                   default:
> > +                     goto unknown_riscv_ip_operand;
> > +                   }
> > +                 break;
> >                 default:
> >                   goto unknown_riscv_ip_operand;
> >                 }
> > diff --git a/gas/testsuite/gas/riscv/zfa-32.d b/gas/testsuite/gas/riscv/zfa-32.d
> > new file mode 100644
> > index 00000000000..48e20bf4675
> > --- /dev/null
> > +++ b/gas/testsuite/gas/riscv/zfa-32.d
> > @@ -0,0 +1,10 @@
> > +#as: -march=rv32id_zfa
> > +#objdump: -d
> > +
> > +.*:[   ]+file format .*
> > +
> > +Disassembly of section .text:
> > +
> > +0+000 <target>:
> > +[      ]+[0-9a-f]+:[   ]+e2108553[     ]+fmvh\.x\.d[   ]+a0,ft1
> > +[      ]+[0-9a-f]+:[   ]+b2b500d3[     ]+fmvp\.d\.x[   ]+ft1,a0,a1
> > diff --git a/gas/testsuite/gas/riscv/zfa-32.s b/gas/testsuite/gas/riscv/zfa-32.s
> > new file mode 100644
> > index 00000000000..da95441cdc7
> > --- /dev/null
> > +++ b/gas/testsuite/gas/riscv/zfa-32.s
> > @@ -0,0 +1,3 @@
> > +target:
> > +       fmvh.x.d        a0, ft1
> > +       fmvp.d.x        ft1, a0, a1
> > diff --git a/gas/testsuite/gas/riscv/zfa-64.d b/gas/testsuite/gas/riscv/zfa-64.d
> > new file mode 100644
> > index 00000000000..48b6d74ed9b
> > --- /dev/null
> > +++ b/gas/testsuite/gas/riscv/zfa-64.d
> > @@ -0,0 +1,10 @@
> > +#as: -march=rv64iq_zfa
> > +#objdump: -d
> > +
> > +.*:[   ]+file format .*
> > +
> > +Disassembly of section .text:
> > +
> > +0+000 <target>:
> > +[      ]+[0-9a-f]+:[   ]+e6108553[     ]+fmvh\.x\.q[   ]+a0,ft1
> > +[      ]+[0-9a-f]+:[   ]+b6b500d3[     ]+fmvp\.q\.x[   ]+ft1,a0,a1
> > diff --git a/gas/testsuite/gas/riscv/zfa-64.s b/gas/testsuite/gas/riscv/zfa-64.s
> > new file mode 100644
> > index 00000000000..dc8129dae3e
> > --- /dev/null
> > +++ b/gas/testsuite/gas/riscv/zfa-64.s
> > @@ -0,0 +1,3 @@
> > +target:
> > +       fmvh.x.q        a0, ft1
> > +       fmvp.q.x        ft1, a0, a1
> > diff --git a/gas/testsuite/gas/riscv/zfa-fail.d b/gas/testsuite/gas/riscv/zfa-fail.d
> > new file mode 100644
> > index 00000000000..d9d4a36c65c
> > --- /dev/null
> > +++ b/gas/testsuite/gas/riscv/zfa-fail.d
> > @@ -0,0 +1,2 @@
> > +#as: -march=rv64iq_zfa_zfh
> > +#error_output: zfa-fail.l
> > diff --git a/gas/testsuite/gas/riscv/zfa-fail.l b/gas/testsuite/gas/riscv/zfa-fail.l
> > new file mode 100644
> > index 00000000000..19b6ff4967d
> > --- /dev/null
> > +++ b/gas/testsuite/gas/riscv/zfa-fail.l
> > @@ -0,0 +1,33 @@
> > +.*: Assembler messages:
> > +.*: Error: improper fli value operand
> > +.*: Error: illegal operands `fli\.s ft1,1'
> > +.*: Error: improper fli value operand
> > +.*: Error: illegal operands `fli\.d ft1,-1'
> > +.*: Error: improper fli value operand
> > +.*: Error: illegal operands `fli\.q ft1,1.250'
> > +.*: Error: improper fli value operand
> > +.*: Error: illegal operands `fli\.h ft1,8'
> > +.*: Error: improper fli value operand
> > +.*: Error: illegal operands `fli\.s ft1,infinity'
> > +.*: Error: improper fli value operand
> > +.*: Error: illegal operands `fli\.d ft1,invalid'
> > +.*: Error: improper fli value operand
> > +.*: Error: illegal operands `fli\.q ft1,30'
> > +.*: Error: improper fli value operand
> > +.*: Error: illegal operands `fli\.h ft1,31'
> > +.*: Error: improper fli value operand
> > +.*: Error: illegal operands `fli\.s ft1,32'
> > +.*: Error: improper fli value operand
> > +.*: Error: illegal operands `fli\.d ft1,0'
> > +.*: Error: improper fli value operand
> > +.*: Error: illegal operands `fli\.q ft1,0.0'
> > +.*: Error: improper fli value operand
> > +.*: Error: illegal operands `fli\.h ft1,-0.0'
> > +.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1'
> > +.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,rne'
> > +.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,rdn'
> > +.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,rup'
> > +.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,rmm'
> > +.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,dyn'
> > +.*: Error: illegal operands `fcvtmod\.w\.d a0,ft1,invalid'
> > +
> > diff --git a/gas/testsuite/gas/riscv/zfa-fail.s b/gas/testsuite/gas/riscv/zfa-fail.s
> > new file mode 100644
> > index 00000000000..e6c6bdc909a
> > --- /dev/null
> > +++ b/gas/testsuite/gas/riscv/zfa-fail.s
> > @@ -0,0 +1,26 @@
> > +target:
> > +       # fli.[sdqh]: Invalid value field
> > +       fli.s   ft1, 1
> > +       fli.d   ft1, -1
> > +       fli.q   ft1, 1.250
> > +       fli.h   ft1, 8
> > +       fli.s   ft1, infinity
> > +       fli.d   ft1, invalid
> > +       fli.q   ft1, 30
> > +       fli.h   ft1, 31
> > +       fli.s   ft1, 32
> > +       fli.d   ft1, 0
> > +       fli.q   ft1, 0.0
> > +       fli.h   ft1, -0.0
> > +
> > +       # fcvtmod.w.d: Requires explicit rounding mode.
> > +       fcvtmod.w.d     a0, ft1
> > +
> > +       # fcvtmod.w.d: Rounding mode other than rtz are reserved.
> > +       fcvtmod.w.d     a0, ft1, rne
> > +       fcvtmod.w.d     a0, ft1, rdn
> > +       fcvtmod.w.d     a0, ft1, rup
> > +       fcvtmod.w.d     a0, ft1, rmm
> > +       fcvtmod.w.d     a0, ft1, dyn
> > +       # fcvtmod.w.d: Invalid rounding mode is invalid.
> > +       fcvtmod.w.d     a0, ft1, invalid
> > diff --git a/gas/testsuite/gas/riscv/zfa.d b/gas/testsuite/gas/riscv/zfa.d
> > new file mode 100644
> > index 00000000000..a6f1f81db29
> > --- /dev/null
> > +++ b/gas/testsuite/gas/riscv/zfa.d
> > @@ -0,0 +1,89 @@
> > +#as: -march=rv32iq_zfa_zfh
> > +#objdump: -d
> > +
> > +.*:[   ]+file format .*
> > +
> > +Disassembly of section .text:
> > +
> > +0+000 <target>:
> > +[      ]+[0-9a-f]+:[   ]+f01000d3[     ]+fli\.s[               ]+ft1,-1.0
> > +[      ]+[0-9a-f]+:[   ]+f01080d3[     ]+fli\.s[               ]+ft1,min
> > +[      ]+[0-9a-f]+:[   ]+f01100d3[     ]+fli\.s[               ]+ft1,0.0000152587890625
> > +[      ]+[0-9a-f]+:[   ]+f01180d3[     ]+fli\.s[               ]+ft1,0.000030517578125
> > +[      ]+[0-9a-f]+:[   ]+f01200d3[     ]+fli\.s[               ]+ft1,0.00390625
> > +[      ]+[0-9a-f]+:[   ]+f01280d3[     ]+fli\.s[               ]+ft1,0.0078125
> > +[      ]+[0-9a-f]+:[   ]+f01300d3[     ]+fli\.s[               ]+ft1,0.0625
> > +[      ]+[0-9a-f]+:[   ]+f01380d3[     ]+fli\.s[               ]+ft1,0.125
> > +[      ]+[0-9a-f]+:[   ]+f21400d3[     ]+fli\.d[               ]+ft1,0.25
> > +[      ]+[0-9a-f]+:[   ]+f21480d3[     ]+fli\.d[               ]+ft1,0.3125
> > +[      ]+[0-9a-f]+:[   ]+f21500d3[     ]+fli\.d[               ]+ft1,0.375
> > +[      ]+[0-9a-f]+:[   ]+f21580d3[     ]+fli\.d[               ]+ft1,0.4375
> > +[      ]+[0-9a-f]+:[   ]+f21600d3[     ]+fli\.d[               ]+ft1,0.5
> > +[      ]+[0-9a-f]+:[   ]+f21680d3[     ]+fli\.d[               ]+ft1,0.625
> > +[      ]+[0-9a-f]+:[   ]+f21700d3[     ]+fli\.d[               ]+ft1,0.75
> > +[      ]+[0-9a-f]+:[   ]+f21780d3[     ]+fli\.d[               ]+ft1,0.875
> > +[      ]+[0-9a-f]+:[   ]+f61800d3[     ]+fli\.q[               ]+ft1,1.0
> > +[      ]+[0-9a-f]+:[   ]+f61880d3[     ]+fli\.q[               ]+ft1,1.25
> > +[      ]+[0-9a-f]+:[   ]+f61900d3[     ]+fli\.q[               ]+ft1,1.5
> > +[      ]+[0-9a-f]+:[   ]+f61980d3[     ]+fli\.q[               ]+ft1,1.75
> > +[      ]+[0-9a-f]+:[   ]+f61a00d3[     ]+fli\.q[               ]+ft1,2.0
> > +[      ]+[0-9a-f]+:[   ]+f61a80d3[     ]+fli\.q[               ]+ft1,2.5
> > +[      ]+[0-9a-f]+:[   ]+f61b00d3[     ]+fli\.q[               ]+ft1,3.0
> > +[      ]+[0-9a-f]+:[   ]+f61b80d3[     ]+fli\.q[               ]+ft1,4.0
> > +[      ]+[0-9a-f]+:[   ]+f41c00d3[     ]+fli\.h[               ]+ft1,8.0
> > +[      ]+[0-9a-f]+:[   ]+f41c80d3[     ]+fli\.h[               ]+ft1,16.0
> > +[      ]+[0-9a-f]+:[   ]+f41d00d3[     ]+fli\.h[               ]+ft1,128.0
> > +[      ]+[0-9a-f]+:[   ]+f41d80d3[     ]+fli\.h[               ]+ft1,256.0
> > +[      ]+[0-9a-f]+:[   ]+f41e00d3[     ]+fli\.h[               ]+ft1,32768.0
> > +[      ]+[0-9a-f]+:[   ]+f41e80d3[     ]+fli\.h[               ]+ft1,65536.0
> > +[      ]+[0-9a-f]+:[   ]+f41f00d3[     ]+fli\.h[               ]+ft1,inf
> > +[      ]+[0-9a-f]+:[   ]+f41f80d3[     ]+fli\.h[               ]+ft1,nan
> > +[      ]+[0-9a-f]+:[   ]+2c3100d3[     ]+fmin\.h[              ]+ft1,ft2,ft3
> > +[      ]+[0-9a-f]+:[   ]+2c3120d3[     ]+fminm\.h[             ]+ft1,ft2,ft3
> > +[      ]+[0-9a-f]+:[   ]+283100d3[     ]+fmin\.s[              ]+ft1,ft2,ft3
> > +[      ]+[0-9a-f]+:[   ]+283120d3[     ]+fminm\.s[             ]+ft1,ft2,ft3
> > +[      ]+[0-9a-f]+:[   ]+2a3100d3[     ]+fmin\.d[              ]+ft1,ft2,ft3
> > +[      ]+[0-9a-f]+:[   ]+2a3120d3[     ]+fminm\.d[             ]+ft1,ft2,ft3
> > +[      ]+[0-9a-f]+:[   ]+2e3100d3[     ]+fmin\.q[              ]+ft1,ft2,ft3
> > +[      ]+[0-9a-f]+:[   ]+2e3120d3[     ]+fminm\.q[             ]+ft1,ft2,ft3
> > +[      ]+[0-9a-f]+:[   ]+2c3110d3[     ]+fmax\.h[              ]+ft1,ft2,ft3
> > +[      ]+[0-9a-f]+:[   ]+2c3130d3[     ]+fmaxm\.h[             ]+ft1,ft2,ft3
> > +[      ]+[0-9a-f]+:[   ]+283110d3[     ]+fmax\.s[              ]+ft1,ft2,ft3
> > +[      ]+[0-9a-f]+:[   ]+283130d3[     ]+fmaxm\.s[             ]+ft1,ft2,ft3
> > +[      ]+[0-9a-f]+:[   ]+2a3110d3[     ]+fmax\.d[              ]+ft1,ft2,ft3
> > +[      ]+[0-9a-f]+:[   ]+2a3130d3[     ]+fmaxm\.d[             ]+ft1,ft2,ft3
> > +[      ]+[0-9a-f]+:[   ]+2e3110d3[     ]+fmax\.q[              ]+ft1,ft2,ft3
> > +[      ]+[0-9a-f]+:[   ]+2e3130d3[     ]+fmaxm\.q[             ]+ft1,ft2,ft3
> > +[      ]+[0-9a-f]+:[   ]+4445f553[     ]+fround\.h[            ]+fa0,fa1
> > +[      ]+[0-9a-f]+:[   ]+44459553[     ]+fround\.h[            ]+fa0,fa1,rtz
> > +[      ]+[0-9a-f]+:[   ]+4045f553[     ]+fround\.s[            ]+fa0,fa1
> > +[      ]+[0-9a-f]+:[   ]+40459553[     ]+fround\.s[            ]+fa0,fa1,rtz
> > +[      ]+[0-9a-f]+:[   ]+4245f553[     ]+fround\.d[            ]+fa0,fa1
> > +[      ]+[0-9a-f]+:[   ]+42459553[     ]+fround\.d[            ]+fa0,fa1,rtz
> > +[      ]+[0-9a-f]+:[   ]+4645f553[     ]+fround\.q[            ]+fa0,fa1
> > +[      ]+[0-9a-f]+:[   ]+46459553[     ]+fround\.q[            ]+fa0,fa1,rtz
> > +[      ]+[0-9a-f]+:[   ]+4455f553[     ]+froundnx\.h[          ]+fa0,fa1
> > +[      ]+[0-9a-f]+:[   ]+44559553[     ]+froundnx\.h[          ]+fa0,fa1,rtz
> > +[      ]+[0-9a-f]+:[   ]+4055f553[     ]+froundnx\.s[          ]+fa0,fa1
> > +[      ]+[0-9a-f]+:[   ]+40559553[     ]+froundnx\.s[          ]+fa0,fa1,rtz
> > +[      ]+[0-9a-f]+:[   ]+4255f553[     ]+froundnx\.d[          ]+fa0,fa1
> > +[      ]+[0-9a-f]+:[   ]+42559553[     ]+froundnx\.d[          ]+fa0,fa1,rtz
> > +[      ]+[0-9a-f]+:[   ]+4655f553[     ]+froundnx\.q[          ]+fa0,fa1
> > +[      ]+[0-9a-f]+:[   ]+46559553[     ]+froundnx\.q[          ]+fa0,fa1,rtz
> > +[      ]+[0-9a-f]+:[   ]+c2809553[     ]+fcvtmod\.w\.d[        ]+a0,ft1,rtz
> > +[      ]+[0-9a-f]+:[   ]+a4209553[     ]+flt\.h[               ]+a0,ft1,ft2
> > +[      ]+[0-9a-f]+:[   ]+a420d553[     ]+fltq\.h[              ]+a0,ft1,ft2
> > +[      ]+[0-9a-f]+:[   ]+a0209553[     ]+flt\.s[               ]+a0,ft1,ft2
> > +[      ]+[0-9a-f]+:[   ]+a020d553[     ]+fltq\.s[              ]+a0,ft1,ft2
> > +[      ]+[0-9a-f]+:[   ]+a2209553[     ]+flt\.d[               ]+a0,ft1,ft2
> > +[      ]+[0-9a-f]+:[   ]+a220d553[     ]+fltq\.d[              ]+a0,ft1,ft2
> > +[      ]+[0-9a-f]+:[   ]+a6209553[     ]+flt\.q[               ]+a0,ft1,ft2
> > +[      ]+[0-9a-f]+:[   ]+a620d553[     ]+fltq\.q[              ]+a0,ft1,ft2
> > +[      ]+[0-9a-f]+:[   ]+a4208553[     ]+fle\.h[               ]+a0,ft1,ft2
> > +[      ]+[0-9a-f]+:[   ]+a420c553[     ]+fleq\.h[              ]+a0,ft1,ft2
> > +[      ]+[0-9a-f]+:[   ]+a0208553[     ]+fle\.s[               ]+a0,ft1,ft2
> > +[      ]+[0-9a-f]+:[   ]+a020c553[     ]+fleq\.s[              ]+a0,ft1,ft2
> > +[      ]+[0-9a-f]+:[   ]+a2208553[     ]+fle\.d[               ]+a0,ft1,ft2
> > +[      ]+[0-9a-f]+:[   ]+a220c553[     ]+fleq\.d[              ]+a0,ft1,ft2
> > +[      ]+[0-9a-f]+:[   ]+a6208553[     ]+fle\.q[               ]+a0,ft1,ft2
> > +[      ]+[0-9a-f]+:[   ]+a620c553[     ]+fleq\.q[              ]+a0,ft1,ft2
> > diff --git a/gas/testsuite/gas/riscv/zfa.s b/gas/testsuite/gas/riscv/zfa.s
> > new file mode 100644
> > index 00000000000..906e8a4a56d
> > --- /dev/null
> > +++ b/gas/testsuite/gas/riscv/zfa.s
> > @@ -0,0 +1,87 @@
> > +target:
> > +       # fli
> > +       fli.s           ft1, -1.0
> > +       fli.s           ft1, min
> > +       fli.s           ft1, 0.0000152587890625
> > +       fli.s           ft1, 0.000030517578125
> > +       fli.s           ft1, 0.00390625
> > +       fli.s           ft1, 0.0078125
> > +       fli.s           ft1, 0.0625
> > +       fli.s           ft1, 0.125
> > +       fli.d           ft1, 0.25
> > +       fli.d           ft1, 0.3125
> > +       fli.d           ft1, 0.375
> > +       fli.d           ft1, 0.4375
> > +       fli.d           ft1, 0.5
> > +       fli.d           ft1, 0.625
> > +       fli.d           ft1, 0.75
> > +       fli.d           ft1, 0.875
> > +       fli.q           ft1, 1.0
> > +       fli.q           ft1, 1.25
> > +       fli.q           ft1, 1.5
> > +       fli.q           ft1, 1.75
> > +       fli.q           ft1, 2.0
> > +       fli.q           ft1, 2.5
> > +       fli.q           ft1, 3.0
> > +       fli.q           ft1, 4.0
> > +       fli.h           ft1, 8.0
> > +       fli.h           ft1, 16.0
> > +       fli.h           ft1, 128.0
> > +       fli.h           ft1, 256.0
> > +       fli.h           ft1, 32768.0
> > +       fli.h           ft1, 65536.0
> > +       fli.h           ft1, inf
> > +       fli.h           ft1, nan
> > +       # fminm/fmaxm
> > +       fmin.h          ft1, ft2, ft3
> > +       fminm.h         ft1, ft2, ft3
> > +       fmin.s          ft1, ft2, ft3
> > +       fminm.s         ft1, ft2, ft3
> > +       fmin.d          ft1, ft2, ft3
> > +       fminm.d         ft1, ft2, ft3
> > +       fmin.q          ft1, ft2, ft3
> > +       fminm.q         ft1, ft2, ft3
> > +       fmax.h          ft1, ft2, ft3
> > +       fmaxm.h         ft1, ft2, ft3
> > +       fmax.s          ft1, ft2, ft3
> > +       fmaxm.s         ft1, ft2, ft3
> > +       fmax.d          ft1, ft2, ft3
> > +       fmaxm.d         ft1, ft2, ft3
> > +       fmax.q          ft1, ft2, ft3
> > +       fmaxm.q         ft1, ft2, ft3
> > +       # fround/froundnx
> > +       fround.h        fa0, fa1
> > +       fround.h        fa0, fa1, rtz
> > +       fround.s        fa0, fa1
> > +       fround.s        fa0, fa1, rtz
> > +       fround.d        fa0, fa1
> > +       fround.d        fa0, fa1, rtz
> > +       fround.q        fa0, fa1
> > +       fround.q        fa0, fa1, rtz
> > +       froundnx.h      fa0, fa1
> > +       froundnx.h      fa0, fa1, rtz
> > +       froundnx.s      fa0, fa1
> > +       froundnx.s      fa0, fa1, rtz
> > +       froundnx.d      fa0, fa1
> > +       froundnx.d      fa0, fa1, rtz
> > +       froundnx.q      fa0, fa1
> > +       froundnx.q      fa0, fa1, rtz
> > +       # fcvtmod.w.d
> > +       fcvtmod.w.d     a0, ft1, rtz
> > +       # fltq/fleq
> > +       flt.h           a0, ft1, ft2
> > +       fltq.h          a0, ft1, ft2
> > +       flt.s           a0, ft1, ft2
> > +       fltq.s          a0, ft1, ft2
> > +       flt.d           a0, ft1, ft2
> > +       fltq.d          a0, ft1, ft2
> > +       flt.q           a0, ft1, ft2
> > +       fltq.q          a0, ft1, ft2
> > +       fle.h           a0, ft1, ft2
> > +       fleq.h          a0, ft1, ft2
> > +       fle.s           a0, ft1, ft2
> > +       fleq.s          a0, ft1, ft2
> > +       fle.d           a0, ft1, ft2
> > +       fleq.d          a0, ft1, ft2
> > +       fle.q           a0, ft1, ft2
> > +       fleq.q          a0, ft1, ft2
> > diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h
> > index 85d35c1efc9..e141c377bde 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
> > @@ -2981,6 +3047,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 b4ae55249bb..1ca698c95ee 100644
> > --- a/include/opcode/riscv.h
> > +++ b/include/opcode/riscv.h
> > @@ -388,6 +388,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,
> > @@ -554,6 +558,7 @@ 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_value[32];
> >
> >  extern const struct riscv_opcode riscv_opcodes[];
> >  extern const struct riscv_opcode riscv_insn_types[];
> > diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
> > index 77a18b08599..edb599e1741 100644
> > --- a/opcodes/riscv-dis.c
> > +++ b/opcodes/riscv-dis.c
> > @@ -592,6 +592,17 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
> >                     goto undefined_modifier;
> >                   }
> >                   break;
> > +             case 'f':
> > +               switch (*++oparg)
> > +                 {
> > +                 case 'v':
> > +                   print (info->stream, dis_style_text, "%s",
> > +                          riscv_fli_value[rs1]);
> > +                   break;
> > +                 default:
> > +                   goto undefined_modifier;
> > +                 }
> > +               break;
> >               default:
> >                 goto undefined_modifier;
> >               }
> > @@ -640,6 +651,7 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
> >               }
> >           }
> >           break;
> > +
> >         default:
> >         undefined_modifier:
> >           /* xgettext:c-format */
> > diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
> > index d9d69cda548..424969fbe57 100644
> > --- a/opcodes/riscv-opc.c
> > +++ b/opcodes/riscv-opc.c
> > @@ -110,6 +110,16 @@ const char * const riscv_vma[2] =
> >    "mu", "ma"
> >  };
> >
> > +/* The FLI.[HSDQ] value constants.  */
> > +const char * const riscv_fli_value[32] =
> > +{
> > +  "-1.0", "min", "0.0000152587890625", "0.000030517578125",
> > +  "0.00390625", "0.0078125", "0.0625", "0.125",
> > +  "0.25", "0.3125", "0.375", "0.4375", "0.5", "0.625", "0.75", "0.875",
> > +  "1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "4.0",
> > +  "8.0", "16.0", "128.0", "256.0", "32768.0", "65536.0",  "inf", "nan",
> > +};
> > +
> >  /* The order of overloaded instructions matters.  Label arguments and
> >     register arguments look the same. Instructions that can have either
> >     for arguments must apear in the correct order in this table for the
> > @@ -939,6 +949,49 @@ const struct riscv_opcode riscv_opcodes[] =
> >  {"wrs.nto",    0, INSN_CLASS_ZAWRS, "", MATCH_WRS_NTO, MASK_WRS_NTO, match_opcode, 0 },
> >  {"wrs.sto",    0, INSN_CLASS_ZAWRS, "", MATCH_WRS_STO, MASK_WRS_STO, match_opcode, 0 },
> >
> > +/* Zfa instructions.  */
> > +{"fli.s",       0, INSN_CLASS_ZFA,         "D,Wfv", MATCH_FLI_S, MASK_FLI_S, match_opcode, 0 },
> > +{"fli.d",       0, INSN_CLASS_D_AND_ZFA,   "D,Wfv", MATCH_FLI_D, MASK_FLI_D, match_opcode, 0 },
> > +{"fli.q",       0, INSN_CLASS_Q_AND_ZFA,   "D,Wfv", MATCH_FLI_Q, MASK_FLI_Q, match_opcode, 0 },
> > +{"fli.h",       0, INSN_CLASS_ZFH_AND_ZFA, "D,Wfv", MATCH_FLI_H, MASK_FLI_H, match_opcode, 0 },
> > +{"fminm.s",     0, INSN_CLASS_ZFA,         "D,S,T", MATCH_FMINM_S, MASK_FMINM_S, match_opcode, 0 },
> > +{"fmaxm.s",     0, INSN_CLASS_ZFA,         "D,S,T", MATCH_FMAXM_S, MASK_FMAXM_S, match_opcode, 0 },
> > +{"fminm.d",     0, INSN_CLASS_D_AND_ZFA,   "D,S,T", MATCH_FMINM_D, MASK_FMINM_D, match_opcode, 0 },
> > +{"fmaxm.d",     0, INSN_CLASS_D_AND_ZFA,   "D,S,T", MATCH_FMAXM_D, MASK_FMAXM_D, match_opcode, 0 },
> > +{"fminm.q",     0, INSN_CLASS_Q_AND_ZFA,   "D,S,T", MATCH_FMINM_Q, MASK_FMINM_Q, match_opcode, 0 },
> > +{"fmaxm.q",     0, INSN_CLASS_Q_AND_ZFA,   "D,S,T", MATCH_FMAXM_Q, MASK_FMAXM_Q, match_opcode, 0 },
> > +{"fminm.h",     0, INSN_CLASS_ZFH_AND_ZFA, "D,S,T", MATCH_FMINM_H, MASK_FMINM_H, match_opcode, 0 },
> > +{"fmaxm.h",     0, INSN_CLASS_ZFH_AND_ZFA, "D,S,T", MATCH_FMAXM_H, MASK_FMAXM_H, match_opcode, 0 },
> > +{"fround.s",    0, INSN_CLASS_ZFA,         "D,S",   MATCH_FROUND_S|MASK_RM, MASK_FROUND_S|MASK_RM, match_opcode, 0 },
> > +{"fround.s",    0, INSN_CLASS_ZFA,         "D,S,m", MATCH_FROUND_S, MASK_FROUND_S, match_opcode, 0 },
> > +{"froundnx.s",  0, INSN_CLASS_ZFA,         "D,S",   MATCH_FROUNDNX_S|MASK_RM, MASK_FROUNDNX_S|MASK_RM, match_opcode, 0 },
> > +{"froundnx.s",  0, INSN_CLASS_ZFA,         "D,S,m", MATCH_FROUNDNX_S, MASK_FROUNDNX_S, match_opcode, 0 },
> > +{"fround.d",    0, INSN_CLASS_D_AND_ZFA,   "D,S",   MATCH_FROUND_D|MASK_RM, MASK_FROUND_D|MASK_RM, match_opcode, 0 },
> > +{"fround.d",    0, INSN_CLASS_D_AND_ZFA,   "D,S,m", MATCH_FROUND_D, MASK_FROUND_D, match_opcode, 0 },
> > +{"froundnx.d",  0, INSN_CLASS_D_AND_ZFA,   "D,S",   MATCH_FROUNDNX_D|MASK_RM, MASK_FROUNDNX_D|MASK_RM, match_opcode, 0 },
> > +{"froundnx.d",  0, INSN_CLASS_D_AND_ZFA,   "D,S,m", MATCH_FROUNDNX_D, MASK_FROUNDNX_D, match_opcode, 0 },
> > +{"fround.q",    0, INSN_CLASS_Q_AND_ZFA,   "D,S",   MATCH_FROUND_Q|MASK_RM, MASK_FROUND_Q|MASK_RM, match_opcode, 0 },
> > +{"fround.q",    0, INSN_CLASS_Q_AND_ZFA,   "D,S,m", MATCH_FROUND_Q, MASK_FROUND_Q, match_opcode, 0 },
> > +{"froundnx.q",  0, INSN_CLASS_Q_AND_ZFA,   "D,S",   MATCH_FROUNDNX_Q|MASK_RM, MASK_FROUNDNX_Q|MASK_RM, match_opcode, 0 },
> > +{"froundnx.q",  0, INSN_CLASS_Q_AND_ZFA,   "D,S,m", MATCH_FROUNDNX_Q, MASK_FROUNDNX_Q, match_opcode, 0 },
> > +{"fround.h",    0, INSN_CLASS_ZFH_AND_ZFA, "D,S",   MATCH_FROUND_H|MASK_RM, MASK_FROUND_H|MASK_RM, match_opcode, 0 },
> > +{"fround.h",    0, INSN_CLASS_ZFH_AND_ZFA, "D,S,m", MATCH_FROUND_H, MASK_FROUND_H, match_opcode, 0 },
> > +{"froundnx.h",  0, INSN_CLASS_ZFH_AND_ZFA, "D,S",   MATCH_FROUNDNX_H|MASK_RM, MASK_FROUNDNX_H|MASK_RM, match_opcode, 0 },
> > +{"froundnx.h",  0, INSN_CLASS_ZFH_AND_ZFA, "D,S,m", MATCH_FROUNDNX_H, MASK_FROUNDNX_H, match_opcode, 0 },
> > +{"fcvtmod.w.d", 0, INSN_CLASS_D_AND_ZFA,   "d,S,m", MATCH_FCVTMOD_W_D, MASK_FCVTMOD_W_D, match_opcode, 0 },
> > +{"fmvh.x.d",   32, INSN_CLASS_D_AND_ZFA,   "d,S",   MATCH_FMVH_X_D, MASK_FMVH_X_D, match_opcode, 0 },
> > +{"fmvp.d.x",   32, INSN_CLASS_D_AND_ZFA,   "D,s,t", MATCH_FMVP_D_X, MASK_FMVP_D_X, match_opcode, 0 },
> > +{"fmvh.x.q",   64, INSN_CLASS_Q_AND_ZFA,   "d,S",   MATCH_FMVH_X_Q, MASK_FMVH_X_Q, match_opcode, 0 },
> > +{"fmvp.q.x",   64, INSN_CLASS_Q_AND_ZFA,   "D,s,t", MATCH_FMVP_Q_X, MASK_FMVP_Q_X, match_opcode, 0 },
> > +{"fltq.s",      0, INSN_CLASS_ZFA,         "d,S,T", MATCH_FLTQ_S, MASK_FLTQ_S, match_opcode, 0 },
> > +{"fleq.s",      0, INSN_CLASS_ZFA,         "d,S,T", MATCH_FLEQ_S, MASK_FLEQ_S, match_opcode, 0 },
> > +{"fltq.d",      0, INSN_CLASS_D_AND_ZFA,   "d,S,T", MATCH_FLTQ_D, MASK_FLTQ_D, match_opcode, 0 },
> > +{"fleq.d",      0, INSN_CLASS_D_AND_ZFA,   "d,S,T", MATCH_FLEQ_D, MASK_FLEQ_D, match_opcode, 0 },
> > +{"fltq.q",      0, INSN_CLASS_Q_AND_ZFA,   "d,S,T", MATCH_FLTQ_Q, MASK_FLTQ_Q, match_opcode, 0 },
> > +{"fleq.q",      0, INSN_CLASS_Q_AND_ZFA,   "d,S,T", MATCH_FLEQ_Q, MASK_FLEQ_Q, match_opcode, 0 },
> > +{"fltq.h",      0, INSN_CLASS_ZFH_AND_ZFA, "d,S,T", MATCH_FLTQ_H, MASK_FLTQ_H, match_opcode, 0 },
> > +{"fleq.h",      0, INSN_CLASS_ZFH_AND_ZFA, "d,S,T", MATCH_FLEQ_H, MASK_FLEQ_H, match_opcode, 0 },
> > +
> >  /* Zbb or zbkb instructions.  */
> >  {"clz",        0, INSN_CLASS_ZBB,  "d,s",   MATCH_CLZ, MASK_CLZ, match_opcode, 0 },
> >  {"ctz",        0, INSN_CLASS_ZBB,  "d,s",   MATCH_CTZ, MASK_CTZ, match_opcode, 0 },
> > --
> > 2.39.2
> >

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension
  2023-03-27  8:01 ` [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension Christoph Muellner
  2023-03-27  8:09   ` Kito Cheng
@ 2023-03-27  8:38   ` Jan Beulich
  2023-03-27  8:53     ` Kito Cheng
  1 sibling, 1 reply; 15+ messages in thread
From: Jan Beulich @ 2023-03-27  8:38 UTC (permalink / raw)
  To: Christoph Muellner
  Cc: binutils, Nelson Chu, Andrew Waterman, Palmer Dabbelt,
	Jim Wilson, Philipp Tomsich, Jeff Law, Tsukasa OI

On 27.03.2023 10:01, Christoph Muellner wrote:
> --- a/opcodes/riscv-opc.c
> +++ b/opcodes/riscv-opc.c
> @@ -110,6 +110,16 @@ const char * const riscv_vma[2] =
>    "mu", "ma"
>  };
>  
> +/* The FLI.[HSDQ] value constants.  */
> +const char * const riscv_fli_value[32] =
> +{
> +  "-1.0", "min", "0.0000152587890625", "0.000030517578125",
> +  "0.00390625", "0.0078125", "0.0625", "0.125",
> +  "0.25", "0.3125", "0.375", "0.4375", "0.5", "0.625", "0.75", "0.875",
> +  "1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "4.0",
> +  "8.0", "16.0", "128.0", "256.0", "32768.0", "65536.0",  "inf", "nan",
> +};

Especially for values like 1.0x2^^-n (entries 2 and onwards) I question
the spelled out numbers to be the most suitable ones usability wise. At
least some alternative spelling (e.g. 2.e-16) ought to be recognized as
well. But since there are meany reasonable spellings (leading 0 omitted
in 0.<fraction> or trailing zero omitted in <num>.0), I guess I'd prefer
if values were actually parsed as a floating point number (e.g. via
ieee_md_atof()), and then matched against values stored in the table.
One might further consider to also permit the 2nd form accepted
elsewhere, see read.c:parse_one_float().

Jan

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension
  2023-03-27  8:38   ` Jan Beulich
@ 2023-03-27  8:53     ` Kito Cheng
  2023-03-27  9:08       ` Christoph Müllner
  2023-03-27  9:54       ` Jan Beulich
  0 siblings, 2 replies; 15+ messages in thread
From: Kito Cheng @ 2023-03-27  8:53 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Christoph Muellner, binutils, Nelson Chu, Andrew Waterman,
	Palmer Dabbelt, Jim Wilson, Philipp Tomsich, Jeff Law,
	Tsukasa OI

Wait, I mean the hex floating point format defined in C99/C++17, not
the raw hex value.
so something like 0x1p-16 (0.0000152587890625), 0x1p-2 (0.25) 0x1p+0,
-0x1p+0 could be used for fli.* instruction.

You could use printf with %a to get those values.

https://gcc.gnu.org/onlinedocs/gcc/Hex-Floats.html
https://developer.arm.com/documentation/dui0375/latest/Compiler-Coding-Practices/Hexadecimal-floating-point-numbers-in-C99


On Mon, Mar 27, 2023 at 4:39 PM Jan Beulich via Binutils
<binutils@sourceware.org> wrote:
>
> On 27.03.2023 10:01, Christoph Muellner wrote:
> > --- a/opcodes/riscv-opc.c
> > +++ b/opcodes/riscv-opc.c
> > @@ -110,6 +110,16 @@ const char * const riscv_vma[2] =
> >    "mu", "ma"
> >  };
> >
> > +/* The FLI.[HSDQ] value constants.  */
> > +const char * const riscv_fli_value[32] =
> > +{
> > +  "-1.0", "min", "0.0000152587890625", "0.000030517578125",
> > +  "0.00390625", "0.0078125", "0.0625", "0.125",
> > +  "0.25", "0.3125", "0.375", "0.4375", "0.5", "0.625", "0.75", "0.875",
> > +  "1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "4.0",
> > +  "8.0", "16.0", "128.0", "256.0", "32768.0", "65536.0",  "inf", "nan",
> > +};
>
> Especially for values like 1.0x2^^-n (entries 2 and onwards) I question
> the spelled out numbers to be the most suitable ones usability wise. At
> least some alternative spelling (e.g. 2.e-16) ought to be recognized as
> well. But since there are meany reasonable spellings (leading 0 omitted
> in 0.<fraction> or trailing zero omitted in <num>.0), I guess I'd prefer
> if values were actually parsed as a floating point number (e.g. via
> ieee_md_atof()), and then matched against values stored in the table.
> One might further consider to also permit the 2nd form accepted
> elsewhere, see read.c:parse_one_float().
>
> Jan

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension
  2023-03-27  8:53     ` Kito Cheng
@ 2023-03-27  9:08       ` Christoph Müllner
  2023-03-27  9:54       ` Jan Beulich
  1 sibling, 0 replies; 15+ messages in thread
From: Christoph Müllner @ 2023-03-27  9:08 UTC (permalink / raw)
  To: Kito Cheng
  Cc: Jan Beulich, binutils, Nelson Chu, Andrew Waterman,
	Palmer Dabbelt, Jim Wilson, Philipp Tomsich, Jeff Law,
	Tsukasa OI

On Mon, Mar 27, 2023 at 10:53 AM Kito Cheng <kito.cheng@gmail.com> wrote:
>
> Wait, I mean the hex floating point format defined in C99/C++17, not
> the raw hex value.
> so something like 0x1p-16 (0.0000152587890625), 0x1p-2 (0.25) 0x1p+0,
> -0x1p+0 could be used for fli.* instruction.
>
> You could use printf with %a to get those values.
>
> https://gcc.gnu.org/onlinedocs/gcc/Hex-Floats.html
> https://developer.arm.com/documentation/dui0375/latest/Compiler-Coding-Practices/Hexadecimal-floating-point-numbers-in-C99

Ok, got it.
Thanks!

>
>
> On Mon, Mar 27, 2023 at 4:39 PM Jan Beulich via Binutils
> <binutils@sourceware.org> wrote:
> >
> > On 27.03.2023 10:01, Christoph Muellner wrote:
> > > --- a/opcodes/riscv-opc.c
> > > +++ b/opcodes/riscv-opc.c
> > > @@ -110,6 +110,16 @@ const char * const riscv_vma[2] =
> > >    "mu", "ma"
> > >  };
> > >
> > > +/* The FLI.[HSDQ] value constants.  */
> > > +const char * const riscv_fli_value[32] =
> > > +{
> > > +  "-1.0", "min", "0.0000152587890625", "0.000030517578125",
> > > +  "0.00390625", "0.0078125", "0.0625", "0.125",
> > > +  "0.25", "0.3125", "0.375", "0.4375", "0.5", "0.625", "0.75", "0.875",
> > > +  "1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "4.0",
> > > +  "8.0", "16.0", "128.0", "256.0", "32768.0", "65536.0",  "inf", "nan",
> > > +};
> >
> > Especially for values like 1.0x2^^-n (entries 2 and onwards) I question
> > the spelled out numbers to be the most suitable ones usability wise. At
> > least some alternative spelling (e.g. 2.e-16) ought to be recognized as
> > well. But since there are meany reasonable spellings (leading 0 omitted
> > in 0.<fraction> or trailing zero omitted in <num>.0), I guess I'd prefer
> > if values were actually parsed as a floating point number (e.g. via
> > ieee_md_atof()), and then matched against values stored in the table.
> > One might further consider to also permit the 2nd form accepted
> > elsewhere, see read.c:parse_one_float().
> >
> > Jan

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension
  2023-03-27  8:53     ` Kito Cheng
  2023-03-27  9:08       ` Christoph Müllner
@ 2023-03-27  9:54       ` Jan Beulich
  2023-03-30 10:30         ` Christoph Müllner
  1 sibling, 1 reply; 15+ messages in thread
From: Jan Beulich @ 2023-03-27  9:54 UTC (permalink / raw)
  To: Kito Cheng
  Cc: Christoph Muellner, binutils, Nelson Chu, Andrew Waterman,
	Palmer Dabbelt, Jim Wilson, Philipp Tomsich, Jeff Law,
	Tsukasa OI

On 27.03.2023 10:53, Kito Cheng wrote:
> Wait, I mean the hex floating point format defined in C99/C++17, not
> the raw hex value.
> so something like 0x1p-16 (0.0000152587890625), 0x1p-2 (0.25) 0x1p+0,
> -0x1p+0 could be used for fli.* instruction.
> 
> You could use printf with %a to get those values.
> 
> https://gcc.gnu.org/onlinedocs/gcc/Hex-Floats.html
> https://developer.arm.com/documentation/dui0375/latest/Compiler-Coding-Practices/Hexadecimal-floating-point-numbers-in-C99

Sure, my (secondary) suggestion ...

> On Mon, Mar 27, 2023 at 4:39 PM Jan Beulich via Binutils
> <binutils@sourceware.org> wrote:
>>
>> On 27.03.2023 10:01, Christoph Muellner wrote:
>>> --- a/opcodes/riscv-opc.c
>>> +++ b/opcodes/riscv-opc.c
>>> @@ -110,6 +110,16 @@ const char * const riscv_vma[2] =
>>>    "mu", "ma"
>>>  };
>>>
>>> +/* The FLI.[HSDQ] value constants.  */
>>> +const char * const riscv_fli_value[32] =
>>> +{
>>> +  "-1.0", "min", "0.0000152587890625", "0.000030517578125",
>>> +  "0.00390625", "0.0078125", "0.0625", "0.125",
>>> +  "0.25", "0.3125", "0.375", "0.4375", "0.5", "0.625", "0.75", "0.875",
>>> +  "1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "4.0",
>>> +  "8.0", "16.0", "128.0", "256.0", "32768.0", "65536.0",  "inf", "nan",
>>> +};
>>
>> Especially for values like 1.0x2^^-n (entries 2 and onwards) I question
>> the spelled out numbers to be the most suitable ones usability wise. At
>> least some alternative spelling (e.g. 2.e-16) ought to be recognized as
>> well. But since there are meany reasonable spellings (leading 0 omitted
>> in 0.<fraction> or trailing zero omitted in <num>.0), I guess I'd prefer
>> if values were actually parsed as a floating point number (e.g. via
>> ieee_md_atof()), and then matched against values stored in the table.
>> One might further consider to also permit the 2nd form accepted
>> elsewhere, see read.c:parse_one_float().

... here wasn't meant to collide with yours. What you're asking for is
covered by my primary suggestion (to actually parse the values), extended
by the need to actually recognize C99 hex float in the parser then (leaving
aside for now whether that's feasible in the first place).

Jan

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension
  2023-03-27  9:54       ` Jan Beulich
@ 2023-03-30 10:30         ` Christoph Müllner
  2023-03-30 10:54           ` Jan Beulich
  0 siblings, 1 reply; 15+ messages in thread
From: Christoph Müllner @ 2023-03-30 10:30 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Kito Cheng, binutils, Nelson Chu, Andrew Waterman,
	Palmer Dabbelt, Jim Wilson, Philipp Tomsich, Jeff Law,
	Tsukasa OI

On Mon, Mar 27, 2023 at 11:54 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 27.03.2023 10:53, Kito Cheng wrote:
> > Wait, I mean the hex floating point format defined in C99/C++17, not
> > the raw hex value.
> > so something like 0x1p-16 (0.0000152587890625), 0x1p-2 (0.25) 0x1p+0,
> > -0x1p+0 could be used for fli.* instruction.
> >
> > You could use printf with %a to get those values.
> >
> > https://gcc.gnu.org/onlinedocs/gcc/Hex-Floats.html
> > https://developer.arm.com/documentation/dui0375/latest/Compiler-Coding-Practices/Hexadecimal-floating-point-numbers-in-C99
>
> Sure, my (secondary) suggestion ...
>
> > On Mon, Mar 27, 2023 at 4:39 PM Jan Beulich via Binutils
> > <binutils@sourceware.org> wrote:
> >>
> >> On 27.03.2023 10:01, Christoph Muellner wrote:
> >>> --- a/opcodes/riscv-opc.c
> >>> +++ b/opcodes/riscv-opc.c
> >>> @@ -110,6 +110,16 @@ const char * const riscv_vma[2] =
> >>>    "mu", "ma"
> >>>  };
> >>>
> >>> +/* The FLI.[HSDQ] value constants.  */
> >>> +const char * const riscv_fli_value[32] =
> >>> +{
> >>> +  "-1.0", "min", "0.0000152587890625", "0.000030517578125",
> >>> +  "0.00390625", "0.0078125", "0.0625", "0.125",
> >>> +  "0.25", "0.3125", "0.375", "0.4375", "0.5", "0.625", "0.75", "0.875",
> >>> +  "1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "4.0",
> >>> +  "8.0", "16.0", "128.0", "256.0", "32768.0", "65536.0",  "inf", "nan",
> >>> +};
> >>
> >> Especially for values like 1.0x2^^-n (entries 2 and onwards) I question
> >> the spelled out numbers to be the most suitable ones usability wise. At
> >> least some alternative spelling (e.g. 2.e-16) ought to be recognized as
> >> well. But since there are meany reasonable spellings (leading 0 omitted
> >> in 0.<fraction> or trailing zero omitted in <num>.0), I guess I'd prefer
> >> if values were actually parsed as a floating point number (e.g. via
> >> ieee_md_atof()), and then matched against values stored in the table.
> >> One might further consider to also permit the 2nd form accepted
> >> elsewhere, see read.c:parse_one_float().
>
> ... here wasn't meant to collide with yours. What you're asking for is
> covered by my primary suggestion (to actually parse the values), extended
> by the need to actually recognize C99 hex float in the parser then (leaving
> aside for now whether that's feasible in the first place).

Thanks for all the suggestions!

I worked my way through this and I believe that the following would be
a reasonable solution:
* constants min, inf and nan must be symbols (as stated in the specification)
* other constants are parsed by scanf("%f") as floats and compared
(float compare in C) against the numeric constants in the table
* output in the disassembly uses symbols for min/inf/nan and %a (hex
FP literals) for other constants

So we support every format that '%f' accepts including hex FP literals
(e.g. -0x1p0, 0x1p+0, ...) and normal FP constants (e.g.
0.0000152587890625, 25E-4).

Patch is ready and will be sent in a few minutes.

BR
Christoph

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension
  2023-03-30 10:30         ` Christoph Müllner
@ 2023-03-30 10:54           ` Jan Beulich
  2023-03-30 12:18             ` Jan Beulich
  0 siblings, 1 reply; 15+ messages in thread
From: Jan Beulich @ 2023-03-30 10:54 UTC (permalink / raw)
  To: Christoph Müllner
  Cc: Kito Cheng, binutils, Nelson Chu, Andrew Waterman,
	Palmer Dabbelt, Jim Wilson, Philipp Tomsich, Jeff Law,
	Tsukasa OI

On 30.03.2023 12:30, Christoph Müllner wrote:
> On Mon, Mar 27, 2023 at 11:54 AM Jan Beulich <jbeulich@suse.com> wrote:
>>
>> On 27.03.2023 10:53, Kito Cheng wrote:
>>> Wait, I mean the hex floating point format defined in C99/C++17, not
>>> the raw hex value.
>>> so something like 0x1p-16 (0.0000152587890625), 0x1p-2 (0.25) 0x1p+0,
>>> -0x1p+0 could be used for fli.* instruction.
>>>
>>> You could use printf with %a to get those values.
>>>
>>> https://gcc.gnu.org/onlinedocs/gcc/Hex-Floats.html
>>> https://developer.arm.com/documentation/dui0375/latest/Compiler-Coding-Practices/Hexadecimal-floating-point-numbers-in-C99
>>
>> Sure, my (secondary) suggestion ...
>>
>>> On Mon, Mar 27, 2023 at 4:39 PM Jan Beulich via Binutils
>>> <binutils@sourceware.org> wrote:
>>>>
>>>> On 27.03.2023 10:01, Christoph Muellner wrote:
>>>>> --- a/opcodes/riscv-opc.c
>>>>> +++ b/opcodes/riscv-opc.c
>>>>> @@ -110,6 +110,16 @@ const char * const riscv_vma[2] =
>>>>>    "mu", "ma"
>>>>>  };
>>>>>
>>>>> +/* The FLI.[HSDQ] value constants.  */
>>>>> +const char * const riscv_fli_value[32] =
>>>>> +{
>>>>> +  "-1.0", "min", "0.0000152587890625", "0.000030517578125",
>>>>> +  "0.00390625", "0.0078125", "0.0625", "0.125",
>>>>> +  "0.25", "0.3125", "0.375", "0.4375", "0.5", "0.625", "0.75", "0.875",
>>>>> +  "1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "4.0",
>>>>> +  "8.0", "16.0", "128.0", "256.0", "32768.0", "65536.0",  "inf", "nan",
>>>>> +};
>>>>
>>>> Especially for values like 1.0x2^^-n (entries 2 and onwards) I question
>>>> the spelled out numbers to be the most suitable ones usability wise. At
>>>> least some alternative spelling (e.g. 2.e-16) ought to be recognized as
>>>> well. But since there are meany reasonable spellings (leading 0 omitted
>>>> in 0.<fraction> or trailing zero omitted in <num>.0), I guess I'd prefer
>>>> if values were actually parsed as a floating point number (e.g. via
>>>> ieee_md_atof()), and then matched against values stored in the table.
>>>> One might further consider to also permit the 2nd form accepted
>>>> elsewhere, see read.c:parse_one_float().
>>
>> ... here wasn't meant to collide with yours. What you're asking for is
>> covered by my primary suggestion (to actually parse the values), extended
>> by the need to actually recognize C99 hex float in the parser then (leaving
>> aside for now whether that's feasible in the first place).
> 
> Thanks for all the suggestions!
> 
> I worked my way through this and I believe that the following would be
> a reasonable solution:
> * constants min, inf and nan must be symbols (as stated in the specification)
> * other constants are parsed by scanf("%f") as floats and compared
> (float compare in C) against the numeric constants in the table
> * output in the disassembly uses symbols for min/inf/nan and %a (hex
> FP literals) for other constants
> 
> So we support every format that '%f' accepts including hex FP literals
> (e.g. -0x1p0, 0x1p+0, ...) and normal FP constants (e.g.
> 0.0000152587890625, 25E-4).

How's this going to work with a cross-assembler run on an architecture
supporting a floating point format other than IEEE 754's? Hence why I
suggested using ieee_md_atof() instead.

Jan

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension
  2023-03-30 10:54           ` Jan Beulich
@ 2023-03-30 12:18             ` Jan Beulich
  2023-03-30 15:36               ` Christoph Müllner
  0 siblings, 1 reply; 15+ messages in thread
From: Jan Beulich @ 2023-03-30 12:18 UTC (permalink / raw)
  To: Christoph Müllner
  Cc: Kito Cheng, binutils, Nelson Chu, Andrew Waterman,
	Palmer Dabbelt, Jim Wilson, Philipp Tomsich, Jeff Law,
	Tsukasa OI

On 30.03.2023 12:54, Jan Beulich via Binutils wrote:
> On 30.03.2023 12:30, Christoph Müllner wrote:
>> On Mon, Mar 27, 2023 at 11:54 AM Jan Beulich <jbeulich@suse.com> wrote:
>>>
>>> On 27.03.2023 10:53, Kito Cheng wrote:
>>>> Wait, I mean the hex floating point format defined in C99/C++17, not
>>>> the raw hex value.
>>>> so something like 0x1p-16 (0.0000152587890625), 0x1p-2 (0.25) 0x1p+0,
>>>> -0x1p+0 could be used for fli.* instruction.
>>>>
>>>> You could use printf with %a to get those values.
>>>>
>>>> https://gcc.gnu.org/onlinedocs/gcc/Hex-Floats.html
>>>> https://developer.arm.com/documentation/dui0375/latest/Compiler-Coding-Practices/Hexadecimal-floating-point-numbers-in-C99
>>>
>>> Sure, my (secondary) suggestion ...
>>>
>>>> On Mon, Mar 27, 2023 at 4:39 PM Jan Beulich via Binutils
>>>> <binutils@sourceware.org> wrote:
>>>>>
>>>>> On 27.03.2023 10:01, Christoph Muellner wrote:
>>>>>> --- a/opcodes/riscv-opc.c
>>>>>> +++ b/opcodes/riscv-opc.c
>>>>>> @@ -110,6 +110,16 @@ const char * const riscv_vma[2] =
>>>>>>    "mu", "ma"
>>>>>>  };
>>>>>>
>>>>>> +/* The FLI.[HSDQ] value constants.  */
>>>>>> +const char * const riscv_fli_value[32] =
>>>>>> +{
>>>>>> +  "-1.0", "min", "0.0000152587890625", "0.000030517578125",
>>>>>> +  "0.00390625", "0.0078125", "0.0625", "0.125",
>>>>>> +  "0.25", "0.3125", "0.375", "0.4375", "0.5", "0.625", "0.75", "0.875",
>>>>>> +  "1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "4.0",
>>>>>> +  "8.0", "16.0", "128.0", "256.0", "32768.0", "65536.0",  "inf", "nan",
>>>>>> +};
>>>>>
>>>>> Especially for values like 1.0x2^^-n (entries 2 and onwards) I question
>>>>> the spelled out numbers to be the most suitable ones usability wise. At
>>>>> least some alternative spelling (e.g. 2.e-16) ought to be recognized as
>>>>> well. But since there are meany reasonable spellings (leading 0 omitted
>>>>> in 0.<fraction> or trailing zero omitted in <num>.0), I guess I'd prefer
>>>>> if values were actually parsed as a floating point number (e.g. via
>>>>> ieee_md_atof()), and then matched against values stored in the table.
>>>>> One might further consider to also permit the 2nd form accepted
>>>>> elsewhere, see read.c:parse_one_float().
>>>
>>> ... here wasn't meant to collide with yours. What you're asking for is
>>> covered by my primary suggestion (to actually parse the values), extended
>>> by the need to actually recognize C99 hex float in the parser then (leaving
>>> aside for now whether that's feasible in the first place).
>>
>> Thanks for all the suggestions!
>>
>> I worked my way through this and I believe that the following would be
>> a reasonable solution:
>> * constants min, inf and nan must be symbols (as stated in the specification)
>> * other constants are parsed by scanf("%f") as floats and compared
>> (float compare in C) against the numeric constants in the table
>> * output in the disassembly uses symbols for min/inf/nan and %a (hex
>> FP literals) for other constants
>>
>> So we support every format that '%f' accepts including hex FP literals
>> (e.g. -0x1p0, 0x1p+0, ...) and normal FP constants (e.g.
>> 0.0000152587890625, 25E-4).
> 
> How's this going to work with a cross-assembler run on an architecture
> supporting a floating point format other than IEEE 754's? Hence why I
> suggested using ieee_md_atof() instead.

Hmm, I see riscv_fli_numval[] has "float" as the base type (which I
didn't really expect), so this ought to work as long as the initializers
used can be represented exactly in whatever arch's floating point format.

Jan

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension
  2023-03-30 12:18             ` Jan Beulich
@ 2023-03-30 15:36               ` Christoph Müllner
  2023-03-30 16:13                 ` Jan Beulich
  0 siblings, 1 reply; 15+ messages in thread
From: Christoph Müllner @ 2023-03-30 15:36 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Kito Cheng, binutils, Nelson Chu, Andrew Waterman,
	Palmer Dabbelt, Jim Wilson, Philipp Tomsich, Jeff Law,
	Tsukasa OI

On Thu, Mar 30, 2023 at 2:18 PM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 30.03.2023 12:54, Jan Beulich via Binutils wrote:
> > On 30.03.2023 12:30, Christoph Müllner wrote:
> >> On Mon, Mar 27, 2023 at 11:54 AM Jan Beulich <jbeulich@suse.com> wrote:
> >>>
> >>> On 27.03.2023 10:53, Kito Cheng wrote:
> >>>> Wait, I mean the hex floating point format defined in C99/C++17, not
> >>>> the raw hex value.
> >>>> so something like 0x1p-16 (0.0000152587890625), 0x1p-2 (0.25) 0x1p+0,
> >>>> -0x1p+0 could be used for fli.* instruction.
> >>>>
> >>>> You could use printf with %a to get those values.
> >>>>
> >>>> https://gcc.gnu.org/onlinedocs/gcc/Hex-Floats.html
> >>>> https://developer.arm.com/documentation/dui0375/latest/Compiler-Coding-Practices/Hexadecimal-floating-point-numbers-in-C99
> >>>
> >>> Sure, my (secondary) suggestion ...
> >>>
> >>>> On Mon, Mar 27, 2023 at 4:39 PM Jan Beulich via Binutils
> >>>> <binutils@sourceware.org> wrote:
> >>>>>
> >>>>> On 27.03.2023 10:01, Christoph Muellner wrote:
> >>>>>> --- a/opcodes/riscv-opc.c
> >>>>>> +++ b/opcodes/riscv-opc.c
> >>>>>> @@ -110,6 +110,16 @@ const char * const riscv_vma[2] =
> >>>>>>    "mu", "ma"
> >>>>>>  };
> >>>>>>
> >>>>>> +/* The FLI.[HSDQ] value constants.  */
> >>>>>> +const char * const riscv_fli_value[32] =
> >>>>>> +{
> >>>>>> +  "-1.0", "min", "0.0000152587890625", "0.000030517578125",
> >>>>>> +  "0.00390625", "0.0078125", "0.0625", "0.125",
> >>>>>> +  "0.25", "0.3125", "0.375", "0.4375", "0.5", "0.625", "0.75", "0.875",
> >>>>>> +  "1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "4.0",
> >>>>>> +  "8.0", "16.0", "128.0", "256.0", "32768.0", "65536.0",  "inf", "nan",
> >>>>>> +};
> >>>>>
> >>>>> Especially for values like 1.0x2^^-n (entries 2 and onwards) I question
> >>>>> the spelled out numbers to be the most suitable ones usability wise. At
> >>>>> least some alternative spelling (e.g. 2.e-16) ought to be recognized as
> >>>>> well. But since there are meany reasonable spellings (leading 0 omitted
> >>>>> in 0.<fraction> or trailing zero omitted in <num>.0), I guess I'd prefer
> >>>>> if values were actually parsed as a floating point number (e.g. via
> >>>>> ieee_md_atof()), and then matched against values stored in the table.
> >>>>> One might further consider to also permit the 2nd form accepted
> >>>>> elsewhere, see read.c:parse_one_float().
> >>>
> >>> ... here wasn't meant to collide with yours. What you're asking for is
> >>> covered by my primary suggestion (to actually parse the values), extended
> >>> by the need to actually recognize C99 hex float in the parser then (leaving
> >>> aside for now whether that's feasible in the first place).
> >>
> >> Thanks for all the suggestions!
> >>
> >> I worked my way through this and I believe that the following would be
> >> a reasonable solution:
> >> * constants min, inf and nan must be symbols (as stated in the specification)
> >> * other constants are parsed by scanf("%f") as floats and compared
> >> (float compare in C) against the numeric constants in the table
> >> * output in the disassembly uses symbols for min/inf/nan and %a (hex
> >> FP literals) for other constants
> >>
> >> So we support every format that '%f' accepts including hex FP literals
> >> (e.g. -0x1p0, 0x1p+0, ...) and normal FP constants (e.g.
> >> 0.0000152587890625, 25E-4).
> >
> > How's this going to work with a cross-assembler run on an architecture
> > supporting a floating point format other than IEEE 754's? Hence why I
> > suggested using ieee_md_atof() instead.
>
> Hmm, I see riscv_fli_numval[] has "float" as the base type (which I
> didn't really expect), so this ought to work as long as the initializers
> used can be represented exactly in whatever arch's floating point format.

The idea to compare parsed FP numbers was yours (thanks for that!).
To do that the use of floats seemed obvious as I did not see why using the
atof-ieee machinery was necessary (I did not consider non IEEE 754 machines).

Since we only parse and compare, at least the hex FP literals should
work on all machines (otherwise these machines would have more serious issues).
As I don't have access to non IEEE 754 machines I can not test other
representations.

I now had a look at the atof-ieee framework and found the following issues:
* ieee_md_atof() does not reveal the number of parsed bytes
  Workaround: use atof_ieee() directly instead (access to F_PRECISION would
  be nice to not have to compare the whole LITTLENUM_TYPE values).
* Parsing hex FP literals does not work
  Input: 0x1p-15
  Error: Could not parse input: x1p-15
* Parsing two strings will always be slower than parsing only one of them.
* Parsers in the atof-ieee framework don't care about pointer-to-const,
  but the constant tables are of type "const char * const".

I now understand that the solution in this patch is not perfect.
But given the alternative is not perfect either, I would prefer to
keep the approach
of this patch unless we identify that it is really broken on an
existing machine that
does not use IEEE 754 FP (we can add more test cases to spot that
during testing).

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension
  2023-03-30 15:36               ` Christoph Müllner
@ 2023-03-30 16:13                 ` Jan Beulich
  2023-03-30 16:59                   ` Christoph Müllner
  0 siblings, 1 reply; 15+ messages in thread
From: Jan Beulich @ 2023-03-30 16:13 UTC (permalink / raw)
  To: Christoph Müllner
  Cc: Kito Cheng, binutils, Nelson Chu, Andrew Waterman,
	Palmer Dabbelt, Jim Wilson, Philipp Tomsich, Jeff Law,
	Tsukasa OI

On 30.03.2023 17:36, Christoph Müllner wrote:
> On Thu, Mar 30, 2023 at 2:18 PM Jan Beulich <jbeulich@suse.com> wrote:
>>
>> On 30.03.2023 12:54, Jan Beulich via Binutils wrote:
>>> On 30.03.2023 12:30, Christoph Müllner wrote:
>>>> On Mon, Mar 27, 2023 at 11:54 AM Jan Beulich <jbeulich@suse.com> wrote:
>>>>>
>>>>> On 27.03.2023 10:53, Kito Cheng wrote:
>>>>>> Wait, I mean the hex floating point format defined in C99/C++17, not
>>>>>> the raw hex value.
>>>>>> so something like 0x1p-16 (0.0000152587890625), 0x1p-2 (0.25) 0x1p+0,
>>>>>> -0x1p+0 could be used for fli.* instruction.
>>>>>>
>>>>>> You could use printf with %a to get those values.
>>>>>>
>>>>>> https://gcc.gnu.org/onlinedocs/gcc/Hex-Floats.html
>>>>>> https://developer.arm.com/documentation/dui0375/latest/Compiler-Coding-Practices/Hexadecimal-floating-point-numbers-in-C99
>>>>>
>>>>> Sure, my (secondary) suggestion ...
>>>>>
>>>>>> On Mon, Mar 27, 2023 at 4:39 PM Jan Beulich via Binutils
>>>>>> <binutils@sourceware.org> wrote:
>>>>>>>
>>>>>>> On 27.03.2023 10:01, Christoph Muellner wrote:
>>>>>>>> --- a/opcodes/riscv-opc.c
>>>>>>>> +++ b/opcodes/riscv-opc.c
>>>>>>>> @@ -110,6 +110,16 @@ const char * const riscv_vma[2] =
>>>>>>>>    "mu", "ma"
>>>>>>>>  };
>>>>>>>>
>>>>>>>> +/* The FLI.[HSDQ] value constants.  */
>>>>>>>> +const char * const riscv_fli_value[32] =
>>>>>>>> +{
>>>>>>>> +  "-1.0", "min", "0.0000152587890625", "0.000030517578125",
>>>>>>>> +  "0.00390625", "0.0078125", "0.0625", "0.125",
>>>>>>>> +  "0.25", "0.3125", "0.375", "0.4375", "0.5", "0.625", "0.75", "0.875",
>>>>>>>> +  "1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "4.0",
>>>>>>>> +  "8.0", "16.0", "128.0", "256.0", "32768.0", "65536.0",  "inf", "nan",
>>>>>>>> +};
>>>>>>>
>>>>>>> Especially for values like 1.0x2^^-n (entries 2 and onwards) I question
>>>>>>> the spelled out numbers to be the most suitable ones usability wise. At
>>>>>>> least some alternative spelling (e.g. 2.e-16) ought to be recognized as
>>>>>>> well. But since there are meany reasonable spellings (leading 0 omitted
>>>>>>> in 0.<fraction> or trailing zero omitted in <num>.0), I guess I'd prefer
>>>>>>> if values were actually parsed as a floating point number (e.g. via
>>>>>>> ieee_md_atof()), and then matched against values stored in the table.
>>>>>>> One might further consider to also permit the 2nd form accepted
>>>>>>> elsewhere, see read.c:parse_one_float().
>>>>>
>>>>> ... here wasn't meant to collide with yours. What you're asking for is
>>>>> covered by my primary suggestion (to actually parse the values), extended
>>>>> by the need to actually recognize C99 hex float in the parser then (leaving
>>>>> aside for now whether that's feasible in the first place).
>>>>
>>>> Thanks for all the suggestions!
>>>>
>>>> I worked my way through this and I believe that the following would be
>>>> a reasonable solution:
>>>> * constants min, inf and nan must be symbols (as stated in the specification)
>>>> * other constants are parsed by scanf("%f") as floats and compared
>>>> (float compare in C) against the numeric constants in the table
>>>> * output in the disassembly uses symbols for min/inf/nan and %a (hex
>>>> FP literals) for other constants
>>>>
>>>> So we support every format that '%f' accepts including hex FP literals
>>>> (e.g. -0x1p0, 0x1p+0, ...) and normal FP constants (e.g.
>>>> 0.0000152587890625, 25E-4).
>>>
>>> How's this going to work with a cross-assembler run on an architecture
>>> supporting a floating point format other than IEEE 754's? Hence why I
>>> suggested using ieee_md_atof() instead.
>>
>> Hmm, I see riscv_fli_numval[] has "float" as the base type (which I
>> didn't really expect), so this ought to work as long as the initializers
>> used can be represented exactly in whatever arch's floating point format.
> 
> The idea to compare parsed FP numbers was yours (thanks for that!).
> To do that the use of floats seemed obvious as I did not see why using the
> atof-ieee machinery was necessary (I did not consider non IEEE 754 machines).
> 
> Since we only parse and compare, at least the hex FP literals should
> work on all machines (otherwise these machines would have more serious issues).
> As I don't have access to non IEEE 754 machines I can not test other
> representations.
> 
> I now had a look at the atof-ieee framework and found the following issues:
> * ieee_md_atof() does not reveal the number of parsed bytes
>   Workaround: use atof_ieee() directly instead (access to F_PRECISION would
>   be nice to not have to compare the whole LITTLENUM_TYPE values).
> * Parsing hex FP literals does not work
>   Input: 0x1p-15
>   Error: Could not parse input: x1p-15
> * Parsing two strings will always be slower than parsing only one of them.

Why parsing two strings? The table values could all be pre-computed.

> * Parsers in the atof-ieee framework don't care about pointer-to-const,
>   but the constant tables are of type "const char * const".
> 
> I now understand that the solution in this patch is not perfect.
> But given the alternative is not perfect either, I would prefer to
> keep the approach
> of this patch unless we identify that it is really broken on an
> existing machine that
> does not use IEEE 754 FP (we can add more test cases to spot that
> during testing).

Fair enough I guess as long as it's properly spelled out somewhere,
so that people running into issues don't need to dig through half
the assembler.

Jan

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension
  2023-03-30 16:13                 ` Jan Beulich
@ 2023-03-30 16:59                   ` Christoph Müllner
  0 siblings, 0 replies; 15+ messages in thread
From: Christoph Müllner @ 2023-03-30 16:59 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Kito Cheng, binutils, Nelson Chu, Andrew Waterman,
	Palmer Dabbelt, Jim Wilson, Philipp Tomsich, Jeff Law,
	Tsukasa OI

On Thu, Mar 30, 2023 at 6:13 PM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 30.03.2023 17:36, Christoph Müllner wrote:
> > On Thu, Mar 30, 2023 at 2:18 PM Jan Beulich <jbeulich@suse.com> wrote:
> >>
> >> On 30.03.2023 12:54, Jan Beulich via Binutils wrote:
> >>> On 30.03.2023 12:30, Christoph Müllner wrote:
> >>>> On Mon, Mar 27, 2023 at 11:54 AM Jan Beulich <jbeulich@suse.com> wrote:
> >>>>>
> >>>>> On 27.03.2023 10:53, Kito Cheng wrote:
> >>>>>> Wait, I mean the hex floating point format defined in C99/C++17, not
> >>>>>> the raw hex value.
> >>>>>> so something like 0x1p-16 (0.0000152587890625), 0x1p-2 (0.25) 0x1p+0,
> >>>>>> -0x1p+0 could be used for fli.* instruction.
> >>>>>>
> >>>>>> You could use printf with %a to get those values.
> >>>>>>
> >>>>>> https://gcc.gnu.org/onlinedocs/gcc/Hex-Floats.html
> >>>>>> https://developer.arm.com/documentation/dui0375/latest/Compiler-Coding-Practices/Hexadecimal-floating-point-numbers-in-C99
> >>>>>
> >>>>> Sure, my (secondary) suggestion ...
> >>>>>
> >>>>>> On Mon, Mar 27, 2023 at 4:39 PM Jan Beulich via Binutils
> >>>>>> <binutils@sourceware.org> wrote:
> >>>>>>>
> >>>>>>> On 27.03.2023 10:01, Christoph Muellner wrote:
> >>>>>>>> --- a/opcodes/riscv-opc.c
> >>>>>>>> +++ b/opcodes/riscv-opc.c
> >>>>>>>> @@ -110,6 +110,16 @@ const char * const riscv_vma[2] =
> >>>>>>>>    "mu", "ma"
> >>>>>>>>  };
> >>>>>>>>
> >>>>>>>> +/* The FLI.[HSDQ] value constants.  */
> >>>>>>>> +const char * const riscv_fli_value[32] =
> >>>>>>>> +{
> >>>>>>>> +  "-1.0", "min", "0.0000152587890625", "0.000030517578125",
> >>>>>>>> +  "0.00390625", "0.0078125", "0.0625", "0.125",
> >>>>>>>> +  "0.25", "0.3125", "0.375", "0.4375", "0.5", "0.625", "0.75", "0.875",
> >>>>>>>> +  "1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "4.0",
> >>>>>>>> +  "8.0", "16.0", "128.0", "256.0", "32768.0", "65536.0",  "inf", "nan",
> >>>>>>>> +};
> >>>>>>>
> >>>>>>> Especially for values like 1.0x2^^-n (entries 2 and onwards) I question
> >>>>>>> the spelled out numbers to be the most suitable ones usability wise. At
> >>>>>>> least some alternative spelling (e.g. 2.e-16) ought to be recognized as
> >>>>>>> well. But since there are meany reasonable spellings (leading 0 omitted
> >>>>>>> in 0.<fraction> or trailing zero omitted in <num>.0), I guess I'd prefer
> >>>>>>> if values were actually parsed as a floating point number (e.g. via
> >>>>>>> ieee_md_atof()), and then matched against values stored in the table.
> >>>>>>> One might further consider to also permit the 2nd form accepted
> >>>>>>> elsewhere, see read.c:parse_one_float().
> >>>>>
> >>>>> ... here wasn't meant to collide with yours. What you're asking for is
> >>>>> covered by my primary suggestion (to actually parse the values), extended
> >>>>> by the need to actually recognize C99 hex float in the parser then (leaving
> >>>>> aside for now whether that's feasible in the first place).
> >>>>
> >>>> Thanks for all the suggestions!
> >>>>
> >>>> I worked my way through this and I believe that the following would be
> >>>> a reasonable solution:
> >>>> * constants min, inf and nan must be symbols (as stated in the specification)
> >>>> * other constants are parsed by scanf("%f") as floats and compared
> >>>> (float compare in C) against the numeric constants in the table
> >>>> * output in the disassembly uses symbols for min/inf/nan and %a (hex
> >>>> FP literals) for other constants
> >>>>
> >>>> So we support every format that '%f' accepts including hex FP literals
> >>>> (e.g. -0x1p0, 0x1p+0, ...) and normal FP constants (e.g.
> >>>> 0.0000152587890625, 25E-4).
> >>>
> >>> How's this going to work with a cross-assembler run on an architecture
> >>> supporting a floating point format other than IEEE 754's? Hence why I
> >>> suggested using ieee_md_atof() instead.
> >>
> >> Hmm, I see riscv_fli_numval[] has "float" as the base type (which I
> >> didn't really expect), so this ought to work as long as the initializers
> >> used can be represented exactly in whatever arch's floating point format.
> >
> > The idea to compare parsed FP numbers was yours (thanks for that!).
> > To do that the use of floats seemed obvious as I did not see why using the
> > atof-ieee machinery was necessary (I did not consider non IEEE 754 machines).
> >
> > Since we only parse and compare, at least the hex FP literals should
> > work on all machines (otherwise these machines would have more serious issues).
> > As I don't have access to non IEEE 754 machines I can not test other
> > representations.
> >
> > I now had a look at the atof-ieee framework and found the following issues:
> > * ieee_md_atof() does not reveal the number of parsed bytes
> >   Workaround: use atof_ieee() directly instead (access to F_PRECISION would
> >   be nice to not have to compare the whole LITTLENUM_TYPE values).
> > * Parsing hex FP literals does not work
> >   Input: 0x1p-15
> >   Error: Could not parse input: x1p-15
> > * Parsing two strings will always be slower than parsing only one of them.
>
> Why parsing two strings? The table values could all be pre-computed.

Agree.

>
> > * Parsers in the atof-ieee framework don't care about pointer-to-const,
> >   but the constant tables are of type "const char * const".
> >
> > I now understand that the solution in this patch is not perfect.
> > But given the alternative is not perfect either, I would prefer to
> > keep the approach
> > of this patch unless we identify that it is really broken on an
> > existing machine that
> > does not use IEEE 754 FP (we can add more test cases to spot that
> > during testing).
>
> Fair enough I guess as long as it's properly spelled out somewhere,
> so that people running into issues don't need to dig through half
> the assembler.

I just noticed that gas/doc/c-riscv.texi is missing a RISC-V
Floating-point section.
A new revision of this patch will include the information in there
(including the error
message that is expected on such a machine).

Besides that I will also replace scanf() by strtof() in the new revision.

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2023-03-30 16:59 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-27  8:01 [RFC PATCH v2 0/2] RISC-V: Add support for the Zfa extension Christoph Muellner
2023-03-27  8:01 ` [RFC PATCH v2 1/2] RISC-V: Allocate "various" operand type Christoph Muellner
2023-03-27  8:01 ` [RFC PATCH v2 2/2] RISC-V: Add support for the Zfa extension Christoph Muellner
2023-03-27  8:09   ` Kito Cheng
2023-03-27  8:26     ` Christoph Müllner
2023-03-27  8:38   ` Jan Beulich
2023-03-27  8:53     ` Kito Cheng
2023-03-27  9:08       ` Christoph Müllner
2023-03-27  9:54       ` Jan Beulich
2023-03-30 10:30         ` Christoph Müllner
2023-03-30 10:54           ` Jan Beulich
2023-03-30 12:18             ` Jan Beulich
2023-03-30 15:36               ` Christoph Müllner
2023-03-30 16:13                 ` Jan Beulich
2023-03-30 16:59                   ` Christoph Müllner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).