[Integration,5/6] RISC-V/zfh: Add half-precision floating-point v0.1 instructions.

Message ID 1617097017-16776-6-git-send-email-nelson.chu@sifive.com
State Superseded
Headers show
Series
  • RISC-V: The prototype of the integration and working branches for binutils.
Related show

Commit Message

Nelson Chu March 30, 2021, 9:36 a.m.
This patch is porting from the following riscv github,
https://github.com/riscv/riscv-binutils-gdb/commits/rvv-1.0.x-zfh

And here is the draft zfh spec,
https://github.com/riscv/riscv-isa-manual/tree/zfh

bfd/
    * elfxx-riscv.c (riscv_std_draft_ext_strtab): Added zfh.
gas/
    * config/tc-riscv.c (extended_ext_version_table): Added default
    version of zfh to v0.1.
    (riscv_extended_subset_supports): Handle INSN_CLASS*_ZFH.
    (extended_macro): Handle M_FLH and M_FSH.
    * testsuite/gas/riscv/extended/extended.exp: Updated.
    * testsuite/gas/riscv/extended/fp-zfh-insns.d: New testcase.
    * testsuite/gas/riscv/extended/fp-zfh-insns.s: Likewise.
include/
    * opcode/riscv-opc-extended.h: Added zfh encoding macros
    and DECLARE_INSN.
    * opcode/riscv.h (enum riscv_extended_insn_class): Added INSN_CLASS*_ZFH.
    (enum M_FLH, M_FSH): Added.
opcodes/
    * riscv-opc.c (riscv_draft_opcodes): Added zfh instructions.
---
 bfd/elfxx-riscv.c                               |   2 +-
 gas/config/tc-riscv.c                           |  23 +++++
 gas/testsuite/gas/riscv/extended/extended.exp   |   1 +
 gas/testsuite/gas/riscv/extended/fp-zfh-insns.d |  71 +++++++++++++++
 gas/testsuite/gas/riscv/extended/fp-zfh-insns.s |  68 +++++++++++++++
 include/opcode/riscv-opc-extended.h             | 111 ++++++++++++++++++++++++
 include/opcode/riscv.h                          |   5 ++
 opcodes/riscv-opc.c                             |  65 ++++++++++++++
 8 files changed, 345 insertions(+), 1 deletion(-)
 create mode 100644 gas/testsuite/gas/riscv/extended/fp-zfh-insns.d
 create mode 100644 gas/testsuite/gas/riscv/extended/fp-zfh-insns.s

-- 
2.7.4

Comments

Jim Wilson March 30, 2021, 11:09 p.m. | #1
On Tue, Mar 30, 2021 at 2:37 AM Nelson Chu <nelson.chu@sifive.com> wrote:

> +#define MATCH_FCVT_Q_H         0x46300053

> +#define MASK_FCVT_Q_H          0xfff0007f

> +#define MATCH_FCVT_H_Q         0x44200053

> +#define MASK_FCVT_H_Q          0xfff0007f

>


This looks wrong.  I think fcvt.q.h should be 0x462 and fcvt.h.q should be
0x443.  SiFive doesn't have Q support, so this wouldn't have turned up in
internal testing.

diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
> index 10e60fd..5a4f7bb 100644

> --- a/include/opcode/riscv.h

> +++ b/include/opcode/riscv.h

> @@ -492,6 +492,9 @@ enum riscv_extended_insn_class

>    INSN_CLASS_V_AND_F,

>    INSN_CLASS_V_OR_ZVAMO,

>    INSN_CLASS_V_OR_ZVLSSEG,

> +  INSN_CLASS_F_AND_ZFH,

>

This F and ZFH class looks redundant.  Zfh implies f just like d does.  We
don't need a F_AND_D class, so we don't need a F_AND_ZFH class.  It does no
harm though.

There is also a zfhmin extension in the docs I'm looking at.  That would
require another insn class.  But we can always add this later.

Jim
Nelson Chu April 6, 2021, 2:01 a.m. | #2
On Wed, Mar 31, 2021 at 7:10 AM Jim Wilson <jimw@sifive.com> wrote:
>

> On Tue, Mar 30, 2021 at 2:37 AM Nelson Chu <nelson.chu@sifive.com> wrote:

>>

>> +#define MATCH_FCVT_Q_H         0x46300053

>> +#define MASK_FCVT_Q_H          0xfff0007f

>> +#define MATCH_FCVT_H_Q         0x44200053

>> +#define MASK_FCVT_H_Q          0xfff0007f

>

>

> This looks wrong.  I think fcvt.q.h should be 0x462 and fcvt.h.q should be 0x443.  SiFive doesn't have Q support, so this wouldn't have turned up in internal testing.


Yes, they are wrong.  Thanks.

>> diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h

>> index 10e60fd..5a4f7bb 100644

>> --- a/include/opcode/riscv.h

>> +++ b/include/opcode/riscv.h

>> @@ -492,6 +492,9 @@ enum riscv_extended_insn_class

>>    INSN_CLASS_V_AND_F,

>>    INSN_CLASS_V_OR_ZVAMO,

>>    INSN_CLASS_V_OR_ZVLSSEG,

>> +  INSN_CLASS_F_AND_ZFH,

>

> This F and ZFH class looks redundant.  Zfh implies f just like d does.  We don't need a F_AND_D class, so we don't need a F_AND_ZFH class.  It does no harm though.


I didn't handle the implicit extension of zfh, the suggestion looks good.

> There is also a zfhmin extension in the docs I'm looking at.  That would require another insn class.  But we can always add this later.


OK, we can add this when the integration branch has been created.

Nelson

Patch

diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index 1d55755..91c57b8 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -1622,7 +1622,7 @@  static const char * const riscv_std_h_ext_strtab[] =
 
 static const char * const riscv_std_draft_ext_strtab[] =
 {
-  "zvamo", "zvlsseg", NULL
+  "zfh", "zvamo", "zvlsseg", NULL
 };
 
 static const char * const riscv_sifive_ext_strtab[] =
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index 1b08e9b..71b60f1 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -169,6 +169,7 @@  static const struct riscv_ext_version extended_ext_version_table[] =
   {"v",       ISA_SPEC_CLASS_DRAFT, 0, 10},
   {"zvamo",   ISA_SPEC_CLASS_DRAFT, 0, 10},
   {"zvlsseg", ISA_SPEC_CLASS_DRAFT, 0, 10},
+  {"zfh",     ISA_SPEC_CLASS_DRAFT, 0, 1},
 
   {"xsifivecdiscarddlone", ISA_SPEC_CLASS_DRAFT, 0, 1},
   {"xsifivecflushdlone",   ISA_SPEC_CLASS_DRAFT, 0, 1},
@@ -358,12 +359,21 @@  riscv_extended_subset_supports (int insn_class)
     case INSN_CLASS_V_OR_ZVLSSEG:
       return (riscv_subset_supports ("v")
 	      || riscv_subset_supports ("zvlsseg"));
+
+    case INSN_CLASS_F_AND_ZFH:
+      return riscv_subset_supports ("f") && riscv_subset_supports ("zfh");
+    case INSN_CLASS_D_AND_ZFH:
+      return riscv_subset_supports ("d") && riscv_subset_supports ("zfh");
+    case INSN_CLASS_Q_AND_ZFH:
+      return riscv_subset_supports ("q") && riscv_subset_supports ("zfh");
+
     case INSN_CLASS_XSIFIVE_CDISCARDDLONE:
       return riscv_subset_supports ("xsifivecdiscarddlone");
     case INSN_CLASS_XSIFIVE_CFLUSHDLONE:
       return riscv_subset_supports ("xsifivecflushdlone");
     case INSN_CLASS_XSIFIVE_CFLUSHILONE:
       return riscv_subset_supports ("xsifivecflushilone");
+
     default:
       as_fatal ("internal: unknown INSN_CLASS (0x%x)", insn_class);
       return FALSE;
@@ -1913,6 +1923,10 @@  extended_macro (struct riscv_cl_insn *ip,
 		expressionS *imm_expr ATTRIBUTE_UNUSED,
 		bfd_reloc_code_real_type *imm_reloc ATTRIBUTE_UNUSED)
 {
+  int rd = (ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD;
+  int rs1 = (ip->insn_opcode >> OP_SH_RS1) & OP_MASK_RS1;
+  int rs2 = (ip->insn_opcode >> OP_SH_RS2) & OP_MASK_RS2;
+
   switch (mask)
     {
     case M_VMSGE:
@@ -1920,6 +1934,15 @@  extended_macro (struct riscv_cl_insn *ip,
       vector_macro (ip);
       break;
 
+    case M_FLH:
+      pcrel_load (rd, rs1, imm_expr, "flh",
+		  BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);
+      break;
+    case M_FSH:
+      pcrel_store (rs2, rs1, imm_expr, "fsh",
+		   BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_S);
+      break;
+
     default:
       return FALSE;
     }
diff --git a/gas/testsuite/gas/riscv/extended/extended.exp b/gas/testsuite/gas/riscv/extended/extended.exp
index 3ba21bb..c9111cb 100644
--- a/gas/testsuite/gas/riscv/extended/extended.exp
+++ b/gas/testsuite/gas/riscv/extended/extended.exp
@@ -31,6 +31,7 @@  if [istarget riscv*-*-*] {
     run_dump_tests "vector-insns-fail-mask"
     run_dump_tests "vector-insns-fail-permutation"
     run_dump_tests "vector-insns-fail-zvamo"
+    run_dump_tests "fp-zfh-insns"
 
     run_dump_tests "sifive-insns"
 
diff --git a/gas/testsuite/gas/riscv/extended/fp-zfh-insns.d b/gas/testsuite/gas/riscv/extended/fp-zfh-insns.d
new file mode 100644
index 0000000..e6c0ac5
--- /dev/null
+++ b/gas/testsuite/gas/riscv/extended/fp-zfh-insns.d
@@ -0,0 +1,71 @@ 
+#as: -march=rv64ifdq_zfh
+#source: fp-zfh-insns.s
+#objdump: -dr
+
+.*:[ 	]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <.text>:
+[ 	]+[0-9a-f]+:[ 	]+00059507[ 	]+flh[ 	]+fa0,0\(a1\)
+[ 	]+[0-9a-f]+:[ 	]+00a59027[ 	]+fsh[ 	]+fa0,0\(a1\)
+[ 	]+[0-9a-f]+:[ 	]+24b58553[ 	]+fmv.h[ 	]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+24b59553[ 	]+fneg.h[ 	]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+24b5a553[ 	]+fabs.h[ 	]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+24c58553[ 	]+fsgnj.h[ 	]+fa0,fa1,fa2
+[ 	]+[0-9a-f]+:[ 	]+24c59553[ 	]+fsgnjn.h[ 	]+fa0,fa1,fa2
+[ 	]+[0-9a-f]+:[ 	]+24c5a553[ 	]+fsgnjx.h[ 	]+fa0,fa1,fa2
+[ 	]+[0-9a-f]+:[ 	]+04c5f553[ 	]+fadd.h[ 	]+fa0,fa1,fa2
+[ 	]+[0-9a-f]+:[ 	]+04c58553[ 	]+fadd.h[ 	]+fa0,fa1,fa2,rne
+[ 	]+[0-9a-f]+:[ 	]+0cc5f553[ 	]+fsub.h[ 	]+fa0,fa1,fa2
+[ 	]+[0-9a-f]+:[ 	]+0cc58553[ 	]+fsub.h[ 	]+fa0,fa1,fa2,rne
+[ 	]+[0-9a-f]+:[ 	]+14c5f553[ 	]+fmul.h[ 	]+fa0,fa1,fa2
+[ 	]+[0-9a-f]+:[ 	]+14c58553[ 	]+fmul.h[ 	]+fa0,fa1,fa2,rne
+[ 	]+[0-9a-f]+:[ 	]+1cc5f553[ 	]+fdiv.h[ 	]+fa0,fa1,fa2
+[ 	]+[0-9a-f]+:[ 	]+1cc58553[ 	]+fdiv.h[ 	]+fa0,fa1,fa2,rne
+[ 	]+[0-9a-f]+:[ 	]+5c05f553[ 	]+fsqrt.h[ 	]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+5c058553[ 	]+fsqrt.h[ 	]+fa0,fa1,rne
+[ 	]+[0-9a-f]+:[ 	]+2cc58553[ 	]+fmin.h[ 	]+fa0,fa1,fa2
+[ 	]+[0-9a-f]+:[ 	]+2cc59553[ 	]+fmax.h[ 	]+fa0,fa1,fa2
+[ 	]+[0-9a-f]+:[ 	]+6cc5f543[ 	]+fmadd.h[ 	]+fa0,fa1,fa2,fa3
+[ 	]+[0-9a-f]+:[ 	]+6cc58543[ 	]+fmadd.h[ 	]+fa0,fa1,fa2,fa3,rne
+[ 	]+[0-9a-f]+:[ 	]+6cc5f54f[ 	]+fnmadd.h[ 	]+fa0,fa1,fa2,fa3
+[ 	]+[0-9a-f]+:[ 	]+6cc5854f[ 	]+fnmadd.h[ 	]+fa0,fa1,fa2,fa3,rne
+[ 	]+[0-9a-f]+:[ 	]+6cc5f547[ 	]+fmsub.h[ 	]+fa0,fa1,fa2,fa3
+[ 	]+[0-9a-f]+:[ 	]+6cc58547[ 	]+fmsub.h[ 	]+fa0,fa1,fa2,fa3,rne
+[ 	]+[0-9a-f]+:[ 	]+6cc5f54b[ 	]+fnmsub.h[ 	]+fa0,fa1,fa2,fa3
+[ 	]+[0-9a-f]+:[ 	]+6cc5854b[ 	]+fnmsub.h[ 	]+fa0,fa1,fa2,fa3,rne
+[ 	]+[0-9a-f]+:[ 	]+c405f553[ 	]+fcvt.w.h[ 	]+a0,fa1
+[ 	]+[0-9a-f]+:[ 	]+c4058553[ 	]+fcvt.w.h[ 	]+a0,fa1,rne
+[ 	]+[0-9a-f]+:[ 	]+c415f553[ 	]+fcvt.wu.h[ 	]+a0,fa1
+[ 	]+[0-9a-f]+:[ 	]+c4158553[ 	]+fcvt.wu.h[ 	]+a0,fa1,rne
+[ 	]+[0-9a-f]+:[ 	]+d405f553[ 	]+fcvt.h.w[ 	]+fa0,a1
+[ 	]+[0-9a-f]+:[ 	]+d4058553[ 	]+fcvt.h.w[ 	]+fa0,a1,rne
+[ 	]+[0-9a-f]+:[ 	]+d415f553[ 	]+fcvt.h.wu[ 	]+fa0,a1
+[ 	]+[0-9a-f]+:[ 	]+d4158553[ 	]+fcvt.h.wu[ 	]+fa0,a1,rne
+[ 	]+[0-9a-f]+:[ 	]+c425f553[ 	]+fcvt.l.h[ 	]+a0,fa1
+[ 	]+[0-9a-f]+:[ 	]+c4258553[ 	]+fcvt.l.h[ 	]+a0,fa1,rne
+[ 	]+[0-9a-f]+:[ 	]+c435f553[ 	]+fcvt.lu.h[ 	]+a0,fa1
+[ 	]+[0-9a-f]+:[ 	]+c4358553[ 	]+fcvt.lu.h[ 	]+a0,fa1,rne
+[ 	]+[0-9a-f]+:[ 	]+d425f553[ 	]+fcvt.h.l[ 	]+fa0,a1
+[ 	]+[0-9a-f]+:[ 	]+d4258553[ 	]+fcvt.h.l[ 	]+fa0,a1,rne
+[ 	]+[0-9a-f]+:[ 	]+d435f553[ 	]+fcvt.h.lu[ 	]+fa0,a1
+[ 	]+[0-9a-f]+:[ 	]+d4358553[ 	]+fcvt.h.lu[ 	]+fa0,a1,rne
+[ 	]+[0-9a-f]+:[ 	]+e4058553[ 	]+fmv.x.h[ 	]+a0,fa1
+[ 	]+[0-9a-f]+:[ 	]+f4058553[ 	]+fmv.h.x[ 	]+fa0,a1
+[ 	]+[0-9a-f]+:[ 	]+40258553[ 	]+fcvt.s.h[ 	]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+42258553[ 	]+fcvt.d.h[ 	]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+46358553[ 	]+fcvt.q.h[ 	]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+4405f553[ 	]+fcvt.h.s[ 	]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+44058553[ 	]+fcvt.h.s[ 	]+fa0,fa1,rne
+[ 	]+[0-9a-f]+:[ 	]+4415f553[ 	]+fcvt.h.d[ 	]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+44158553[ 	]+fcvt.h.d[ 	]+fa0,fa1,rne
+[ 	]+[0-9a-f]+:[ 	]+4425f553[ 	]+fcvt.h.q[ 	]+fa0,fa1
+[ 	]+[0-9a-f]+:[ 	]+44258553[ 	]+fcvt.h.q[ 	]+fa0,fa1,rne
+[ 	]+[0-9a-f]+:[ 	]+e4059553[ 	]+fclass.h[ 	]+a0,fa1
+[ 	]+[0-9a-f]+:[ 	]+a4c5a553[ 	]+feq.h[ 	]+a0,fa1,fa2
+[ 	]+[0-9a-f]+:[ 	]+a4c59553[ 	]+flt.h[ 	]+a0,fa1,fa2
+[ 	]+[0-9a-f]+:[ 	]+a4c58553[ 	]+fle.h[ 	]+a0,fa1,fa2
+[ 	]+[0-9a-f]+:[ 	]+a4c59553[ 	]+flt.h[ 	]+a0,fa1,fa2
+[ 	]+[0-9a-f]+:[ 	]+a4c58553[ 	]+fle.h[ 	]+a0,fa1,fa2
diff --git a/gas/testsuite/gas/riscv/extended/fp-zfh-insns.s b/gas/testsuite/gas/riscv/extended/fp-zfh-insns.s
new file mode 100644
index 0000000..1a04cc6
--- /dev/null
+++ b/gas/testsuite/gas/riscv/extended/fp-zfh-insns.s
@@ -0,0 +1,68 @@ 
+	flh		fa0, 0(a1)
+	fsh		fa0, 0(a1)
+
+	fmv.h		fa0, fa1
+	fneg.h		fa0, fa1
+	fabs.h		fa0, fa1
+	fsgnj.h		fa0, fa1, fa2
+	fsgnjn.h	fa0, fa1, fa2
+	fsgnjx.h	fa0, fa1, fa2
+
+	fadd.h		fa0, fa1, fa2
+	fadd.h		fa0, fa1, fa2, rne
+	fsub.h		fa0, fa1, fa2
+	fsub.h		fa0, fa1, fa2, rne
+	fmul.h		fa0, fa1, fa2
+	fmul.h		fa0, fa1, fa2, rne
+	fdiv.h		fa0, fa1, fa2
+	fdiv.h		fa0, fa1, fa2, rne
+	fsqrt.h		fa0, fa1
+	fsqrt.h		fa0, fa1, rne
+	fmin.h		fa0, fa1, fa2
+	fmax.h		fa0, fa1, fa2
+
+	fmadd.h		fa0, fa1, fa2, fa3
+	fmadd.h		fa0, fa1, fa2, fa3, rne
+	fnmadd.h	fa0, fa1, fa2, fa3
+	fnmadd.h	fa0, fa1, fa2, fa3, rne
+	fmsub.h		fa0, fa1, fa2, fa3
+	fmsub.h		fa0, fa1, fa2, fa3, rne
+	fnmsub.h	fa0, fa1, fa2, fa3
+	fnmsub.h	fa0, fa1, fa2, fa3, rne
+
+	fcvt.w.h	a0, fa1
+	fcvt.w.h	a0, fa1, rne
+	fcvt.wu.h	a0, fa1
+	fcvt.wu.h	a0, fa1, rne
+	fcvt.h.w	fa0, a1
+	fcvt.h.w	fa0, a1, rne
+	fcvt.h.wu	fa0, a1
+	fcvt.h.wu	fa0, a1, rne
+	fcvt.l.h	a0, fa1
+	fcvt.l.h	a0, fa1, rne
+	fcvt.lu.h	a0, fa1
+	fcvt.lu.h	a0, fa1, rne
+	fcvt.h.l	fa0, a1
+	fcvt.h.l	fa0, a1, rne
+	fcvt.h.lu	fa0, a1
+	fcvt.h.lu	fa0, a1, rne
+
+	fmv.x.h		a0, fa1
+	fmv.h.x		fa0, a1
+
+	fcvt.s.h	fa0, fa1
+	fcvt.d.h	fa0, fa1
+	fcvt.q.h	fa0, fa1
+	fcvt.h.s	fa0, fa1
+	fcvt.h.s	fa0, fa1, rne
+	fcvt.h.d	fa0, fa1
+	fcvt.h.d	fa0, fa1, rne
+	fcvt.h.q	fa0, fa1
+	fcvt.h.q	fa0, fa1, rne
+	fclass.h	a0, fa1
+
+	feq.h		a0, fa1, fa2
+	flt.h		a0, fa1, fa2
+	fle.h		a0, fa1, fa2
+	fgt.h		a0, fa2, fa1
+	fge.h		a0, fa2, fa1
diff --git a/include/opcode/riscv-opc-extended.h b/include/opcode/riscv-opc-extended.h
index abe7662..cbd4f7b 100644
--- a/include/opcode/riscv-opc-extended.h
+++ b/include/opcode/riscv-opc-extended.h
@@ -20,6 +20,79 @@ 
 
 #ifndef RISCV_EXTENDED_ENCODING_H
 #define RISCV_EXTENDED_ENCODING_H
+/* ZFH instruction.  */
+#define MATCH_FLH		0x1007
+#define MASK_FLH		0x707f
+#define MATCH_FSH		0x1027
+#define MASK_FSH		0x707f
+#define MATCH_FADD_H		0x4000053
+#define MASK_FADD_H		0xfe00007f
+#define MATCH_FSUB_H		0xc000053
+#define MASK_FSUB_H		0xfe00007f
+#define MATCH_FMUL_H		0x14000053
+#define MASK_FMUL_H		0xfe00007f
+#define MATCH_FDIV_H		0x1c000053
+#define MASK_FDIV_H		0xfe00007f
+#define MATCH_FSGNJ_H		0x24000053
+#define MASK_FSGNJ_H		0xfe00707f
+#define MATCH_FSGNJN_H		0x24001053
+#define MASK_FSGNJN_H		0xfe00707f
+#define MATCH_FSGNJX_H		0x24002053
+#define MASK_FSGNJX_H		0xfe00707f
+#define MATCH_FMIN_H		0x2c000053
+#define MASK_FMIN_H 		0xfe00707f
+#define MATCH_FMAX_H		0x2c001053
+#define MASK_FMAX_H		0xfe00707f
+#define MATCH_FCVT_S_H		0x40200053
+#define MASK_FCVT_S_H		0xfff0007f
+#define MATCH_FCVT_H_S		0x44000053
+#define MASK_FCVT_H_S		0xfff0007f
+#define MATCH_FCVT_D_H		0x42200053
+#define MASK_FCVT_D_H		0xfff0007f
+#define MATCH_FCVT_H_D		0x44100053
+#define MASK_FCVT_H_D		0xfff0007f
+#define MATCH_FCVT_Q_H		0x46300053
+#define MASK_FCVT_Q_H		0xfff0007f
+#define MATCH_FCVT_H_Q		0x44200053
+#define MASK_FCVT_H_Q		0xfff0007f
+#define MATCH_FSQRT_H		0x5c000053
+#define MASK_FSQRT_H		0xfff0007f
+#define MATCH_FLE_H		0xa4000053
+#define MASK_FLE_H		0xfe00707f
+#define MATCH_FLT_H		0xa4001053
+#define MASK_FLT_H		0xfe00707f
+#define MATCH_FEQ_H		0xa4002053
+#define MASK_FEQ_H		0xfe00707f
+#define MATCH_FCVT_W_H		0xc4000053
+#define MASK_FCVT_W_H		0xfff0007f
+#define MATCH_FCVT_WU_H		0xc4100053
+#define MASK_FCVT_WU_H		0xfff0007f
+#define MATCH_FCVT_L_H		0xc4200053
+#define MASK_FCVT_L_H		0xfff0007f
+#define MATCH_FCVT_LU_H		0xc4300053
+#define MASK_FCVT_LU_H		0xfff0007f
+#define MATCH_FMV_X_H		0xe4000053
+#define MASK_FMV_X_H		0xfff0707f
+#define MATCH_FCLASS_H		0xe4001053
+#define MASK_FCLASS_H		0xfff0707f
+#define MATCH_FCVT_H_W		0xd4000053
+#define MASK_FCVT_H_W		0xfff0007f
+#define MATCH_FCVT_H_WU		0xd4100053
+#define MASK_FCVT_H_WU		0xfff0007f
+#define MATCH_FCVT_H_L		0xd4200053
+#define MASK_FCVT_H_L		0xfff0007f
+#define MATCH_FCVT_H_LU		0xd4300053
+#define MASK_FCVT_H_LU		0xfff0007f
+#define MATCH_FMV_H_X		0xf4000053
+#define MASK_FMV_H_X		0xfff0707f
+#define MATCH_FMADD_H		0x4000043
+#define MASK_FMADD_H		0x600007f
+#define MATCH_FMSUB_H		0x4000047
+#define MASK_FMSUB_H		0x600007f
+#define MATCH_FNMSUB_H		0x400004b
+#define MASK_FNMSUB_H		0x600007f
+#define MATCH_FNMADD_H		0x400004f
+#define MASK_FNMADD_H		0x600007f
 /* RVV instruction.  */
 #define MATCH_VSETVL		0x80007057
 #define MASK_VSETVL		0xfe00707f
@@ -1383,6 +1456,44 @@ 
 #define MATCH_CFLUSH_I_L1	0xfc100073
 #define MASK_CFLUSH_I_L1	0xffffffff
 #endif /* RISCV_EXTENDED_ENCODING_H */
+#ifdef DECLARE_INSN
+DECLARE_INSN(fadd_h, MATCH_FADD_H, MASK_FADD_H)
+DECLARE_INSN(fsub_h, MATCH_FSUB_D, MASK_FSUB_H)
+DECLARE_INSN(fmul_h, MATCH_FMUL_D, MASK_FMUL_H)
+DECLARE_INSN(fdiv_h, MATCH_FDIV_D, MASK_FDIV_H)
+DECLARE_INSN(fsgnj_h, MATCH_FSGNJ_D, MASK_FSGNJ_H)
+DECLARE_INSN(fsgnjn_h, MATCH_FSGNJN_D, MASK_FSGNJN_H)
+DECLARE_INSN(fsgnjx_h, MATCH_FSGNJX_D, MASK_FSGNJX_H)
+DECLARE_INSN(fmin_h, MATCH_FMIN_D, MASK_FMIN_H)
+DECLARE_INSN(fmax_h, MATCH_FMAX_D, MASK_FMAX_H)
+DECLARE_INSN(fcvt_s_h, MATCH_FCVT_S_D, MASK_FCVT_S_H)
+DECLARE_INSN(fcvt_h_s, MATCH_FCVT_H_S, MASK_FCVT_H_S)
+DECLARE_INSN(fcvt_d_h, MATCH_FCVT_D_H, MASK_FCVT_D_H)
+DECLARE_INSN(fcvt_h_d, MATCH_FCVT_H_D, MASK_FCVT_H_D)
+DECLARE_INSN(fcvt_q_h, MATCH_FCVT_Q_H, MASK_FCVT_Q_H)
+DECLARE_INSN(fcvt_h_q, MATCH_FCVT_H_Q, MASK_FCVT_H_Q)
+DECLARE_INSN(fsqrt_h, MATCH_FSQRT_H, MASK_FSQRT_H)
+DECLARE_INSN(fle_h, MATCH_FLE_H, MASK_FLE_H)
+DECLARE_INSN(flt_h, MATCH_FLT_H, MASK_FLT_H)
+DECLARE_INSN(feq_h, MATCH_FEQ_H, MASK_FEQ_H)
+DECLARE_INSN(fcvt_w_h, MATCH_FCVT_W_H, MASK_FCVT_W_H)
+DECLARE_INSN(fcvt_wu_h, MATCH_FCVT_WU_H, MASK_FCVT_WU_H)
+DECLARE_INSN(fcvt_l_h, MATCH_FCVT_L_H, MASK_FCVT_L_H)
+DECLARE_INSN(fcvt_lu_h, MATCH_FCVT_LU_H, MASK_FCVT_LU_H)
+DECLARE_INSN(fmv_x_h, MATCH_FMV_X_H, MASK_FMV_X_H)
+DECLARE_INSN(fclass_h, MATCH_FCLASS_H, MASK_FCLASS_H)
+DECLARE_INSN(fcvt_h_w, MATCH_FCVT_H_W, MASK_FCVT_H_W)
+DECLARE_INSN(fcvt_h_wu, MATCH_FCVT_H_WU, MASK_FCVT_H_WU)
+DECLARE_INSN(fcvt_h_l, MATCH_FCVT_H_L, MASK_FCVT_H_L)
+DECLARE_INSN(fcvt_h_lu, MATCH_FCVT_H_LU, MASK_FCVT_H_LU)
+DECLARE_INSN(fmv_h_x, MATCH_FMV_H_X, MASK_FMV_H_X)
+DECLARE_INSN(flh, MATCH_FLH, MASK_FLH)
+DECLARE_INSN(fsh, MATCH_FSH, MASK_FSH)
+DECLARE_INSN(fmadd_h, MATCH_FMADD_H, MASK_FMADD_H)
+DECLARE_INSN(fmsub_h, MATCH_FMSUB_H, MASK_FMSUB_H)
+DECLARE_INSN(fnmsub_h, MATCH_FNMSUB_H, MASK_FNMSUB_H)
+DECLARE_INSN(fnmadd_h, MATCH_FNMADD_H, MASK_FNMADD_H)
+#endif /* DECLARE_INSN */
 #ifdef DECLARE_CSR
 /* Unprivileged extended CSR addresses.  */
 #define CSR_VSTART 0x008
diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
index 10e60fd..5a4f7bb 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -492,6 +492,9 @@  enum riscv_extended_insn_class
   INSN_CLASS_V_AND_F,
   INSN_CLASS_V_OR_ZVAMO,
   INSN_CLASS_V_OR_ZVLSSEG,
+  INSN_CLASS_F_AND_ZFH,
+  INSN_CLASS_D_AND_ZFH,
+  INSN_CLASS_Q_AND_ZFH,
 
   /* Sifive */
   INSN_CLASS_XSIFIVE_CFLUSHDLONE,
@@ -505,6 +508,8 @@  enum
 {
   M_VMSGE = M_EXTENDED,
   M_VMSGEU,
+  M_FLH,
+  M_FSH,
 };
 
 /* RVV */
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index e1063d7..b28be54 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -1346,6 +1346,71 @@  match_vmv_nf_rv (const struct riscv_opcode *op,
 const struct riscv_opcode riscv_draft_opcodes[] =
 {
 /* name, xlen, isa, operands, match, mask, match_func, pinfo.  */
+/* Half-precision floating-point instruction subset.  */
+{"flh",        0, INSN_CLASS_F_AND_ZFH,  "D,o(s)",    MATCH_FLH, MASK_FLH, match_opcode, INSN_DREF|INSN_2_BYTE },
+{"flh",        0, INSN_CLASS_F_AND_ZFH,  "D,A,s",     0, (int) M_FLH, match_never, INSN_MACRO },
+{"fsh",        0, INSN_CLASS_F_AND_ZFH,  "T,q(s)",    MATCH_FSH, MASK_FSH, match_opcode, INSN_DREF|INSN_2_BYTE },
+{"fsh",        0, INSN_CLASS_F_AND_ZFH,  "T,A,s",     0, (int) M_FSH, match_never, INSN_MACRO },
+{"fmv.h",      0, INSN_CLASS_F_AND_ZFH,  "D,U",       MATCH_FSGNJ_H, MASK_FSGNJ_H, match_rs1_eq_rs2, INSN_ALIAS },
+{"fneg.h",     0, INSN_CLASS_F_AND_ZFH,  "D,U",       MATCH_FSGNJN_H, MASK_FSGNJN_H, match_rs1_eq_rs2, INSN_ALIAS },
+{"fabs.h",     0, INSN_CLASS_F_AND_ZFH,  "D,U",       MATCH_FSGNJX_H, MASK_FSGNJX_H, match_rs1_eq_rs2, INSN_ALIAS },
+{"fsgnj.h",    0, INSN_CLASS_F_AND_ZFH,  "D,S,T",     MATCH_FSGNJ_H, MASK_FSGNJ_H, match_opcode, 0 },
+{"fsgnjn.h",   0, INSN_CLASS_F_AND_ZFH,  "D,S,T",     MATCH_FSGNJN_H, MASK_FSGNJN_H, match_opcode, 0 },
+{"fsgnjx.h",   0, INSN_CLASS_F_AND_ZFH,  "D,S,T",     MATCH_FSGNJX_H, MASK_FSGNJX_H, match_opcode, 0 },
+{"fadd.h",     0, INSN_CLASS_F_AND_ZFH,  "D,S,T",     MATCH_FADD_H|MASK_RM, MASK_FADD_H|MASK_RM, match_opcode, 0 },
+{"fadd.h",     0, INSN_CLASS_F_AND_ZFH,  "D,S,T,m",   MATCH_FADD_H, MASK_FADD_H, match_opcode, 0 },
+{"fsub.h",     0, INSN_CLASS_F_AND_ZFH,  "D,S,T",     MATCH_FSUB_H|MASK_RM, MASK_FSUB_H|MASK_RM, match_opcode, 0 },
+{"fsub.h",     0, INSN_CLASS_F_AND_ZFH,  "D,S,T,m",   MATCH_FSUB_H, MASK_FSUB_H, match_opcode, 0 },
+{"fmul.h",     0, INSN_CLASS_F_AND_ZFH,  "D,S,T",     MATCH_FMUL_H|MASK_RM, MASK_FMUL_H|MASK_RM, match_opcode, 0 },
+{"fmul.h",     0, INSN_CLASS_F_AND_ZFH,  "D,S,T,m",   MATCH_FMUL_H, MASK_FMUL_H, match_opcode, 0 },
+{"fdiv.h",     0, INSN_CLASS_F_AND_ZFH,  "D,S,T",     MATCH_FDIV_H|MASK_RM, MASK_FDIV_H|MASK_RM, match_opcode, 0 },
+{"fdiv.h",     0, INSN_CLASS_F_AND_ZFH,  "D,S,T,m",   MATCH_FDIV_H, MASK_FDIV_H, match_opcode, 0 },
+{"fsqrt.h",    0, INSN_CLASS_F_AND_ZFH,  "D,S",       MATCH_FSQRT_H|MASK_RM, MASK_FSQRT_H|MASK_RM, match_opcode, 0 },
+{"fsqrt.h",    0, INSN_CLASS_F_AND_ZFH,  "D,S,m",     MATCH_FSQRT_H, MASK_FSQRT_H, match_opcode, 0 },
+{"fmin.h",     0, INSN_CLASS_F_AND_ZFH,  "D,S,T",     MATCH_FMIN_H, MASK_FMIN_H, match_opcode, 0 },
+{"fmax.h",     0, INSN_CLASS_F_AND_ZFH,  "D,S,T",     MATCH_FMAX_H, MASK_FMAX_H, match_opcode, 0 },
+{"fmadd.h",    0, INSN_CLASS_F_AND_ZFH,  "D,S,T,R",   MATCH_FMADD_H|MASK_RM, MASK_FMADD_H|MASK_RM, match_opcode, 0 },
+{"fmadd.h",    0, INSN_CLASS_F_AND_ZFH,  "D,S,T,R,m", MATCH_FMADD_H, MASK_FMADD_H, match_opcode, 0 },
+{"fnmadd.h",   0, INSN_CLASS_F_AND_ZFH,  "D,S,T,R",   MATCH_FNMADD_H|MASK_RM, MASK_FNMADD_H|MASK_RM, match_opcode, 0 },
+{"fnmadd.h",   0, INSN_CLASS_F_AND_ZFH,  "D,S,T,R,m", MATCH_FNMADD_H, MASK_FNMADD_H, match_opcode, 0 },
+{"fmsub.h",    0, INSN_CLASS_F_AND_ZFH,  "D,S,T,R",   MATCH_FMSUB_H|MASK_RM, MASK_FMSUB_H|MASK_RM, match_opcode, 0 },
+{"fmsub.h",    0, INSN_CLASS_F_AND_ZFH,  "D,S,T,R,m", MATCH_FMSUB_H, MASK_FMSUB_H, match_opcode, 0 },
+{"fnmsub.h",   0, INSN_CLASS_F_AND_ZFH,  "D,S,T,R",   MATCH_FNMSUB_H|MASK_RM, MASK_FNMSUB_H|MASK_RM, match_opcode, 0 },
+{"fnmsub.h",   0, INSN_CLASS_F_AND_ZFH,  "D,S,T,R,m", MATCH_FNMSUB_H, MASK_FNMSUB_H, match_opcode, 0 },
+{"fcvt.w.h",   0, INSN_CLASS_F_AND_ZFH,  "d,S",       MATCH_FCVT_W_H|MASK_RM, MASK_FCVT_W_H|MASK_RM, match_opcode, 0 },
+{"fcvt.w.h",   0, INSN_CLASS_F_AND_ZFH,  "d,S,m",     MATCH_FCVT_W_H, MASK_FCVT_W_H, match_opcode, 0 },
+{"fcvt.wu.h",  0, INSN_CLASS_F_AND_ZFH,  "d,S",       MATCH_FCVT_WU_H|MASK_RM, MASK_FCVT_WU_H|MASK_RM, match_opcode, 0 },
+{"fcvt.wu.h",  0, INSN_CLASS_F_AND_ZFH,  "d,S,m",     MATCH_FCVT_WU_H, MASK_FCVT_WU_H, match_opcode, 0 },
+{"fcvt.h.w",   0, INSN_CLASS_F_AND_ZFH,  "D,s",       MATCH_FCVT_H_W|MASK_RM, MASK_FCVT_H_W|MASK_RM, match_opcode, 0 },
+{"fcvt.h.w",   0, INSN_CLASS_F_AND_ZFH,  "D,s,m",     MATCH_FCVT_H_W, MASK_FCVT_H_W, match_opcode, 0 },
+{"fcvt.h.wu",  0, INSN_CLASS_F_AND_ZFH,  "D,s",       MATCH_FCVT_H_WU|MASK_RM, MASK_FCVT_H_WU|MASK_RM, match_opcode, 0 },
+{"fcvt.h.wu",  0, INSN_CLASS_F_AND_ZFH,  "D,s,m",     MATCH_FCVT_H_WU, MASK_FCVT_H_WU, match_opcode, 0 },
+{"fcvt.s.h",   0, INSN_CLASS_F_AND_ZFH,  "D,S",       MATCH_FCVT_S_H, MASK_FCVT_S_H|MASK_RM, match_opcode, 0 },
+{"fcvt.d.h",   0, INSN_CLASS_D_AND_ZFH,  "D,S",       MATCH_FCVT_D_H, MASK_FCVT_D_H|MASK_RM, match_opcode, 0 },
+{"fcvt.q.h",   0, INSN_CLASS_Q_AND_ZFH,  "D,S",       MATCH_FCVT_Q_H, MASK_FCVT_Q_H|MASK_RM, match_opcode, 0 },
+{"fcvt.h.s",   0, INSN_CLASS_F_AND_ZFH,  "D,S",       MATCH_FCVT_H_S|MASK_RM, MASK_FCVT_H_S|MASK_RM, match_opcode, 0 },
+{"fcvt.h.s",   0, INSN_CLASS_F_AND_ZFH,  "D,S,m",     MATCH_FCVT_H_S, MASK_FCVT_H_S, match_opcode, 0 },
+{"fcvt.h.d",   0, INSN_CLASS_D_AND_ZFH,  "D,S",       MATCH_FCVT_H_D|MASK_RM, MASK_FCVT_H_D|MASK_RM, match_opcode, 0 },
+{"fcvt.h.d",   0, INSN_CLASS_D_AND_ZFH,  "D,S,m",     MATCH_FCVT_H_D, MASK_FCVT_H_D, match_opcode, 0 },
+{"fcvt.h.q",   0, INSN_CLASS_Q_AND_ZFH,  "D,S",       MATCH_FCVT_H_Q|MASK_RM, MASK_FCVT_H_Q|MASK_RM, match_opcode, 0 },
+{"fcvt.h.q",   0, INSN_CLASS_Q_AND_ZFH,  "D,S,m",     MATCH_FCVT_H_Q, MASK_FCVT_H_Q, match_opcode, 0 },
+{"fclass.h",   0, INSN_CLASS_F_AND_ZFH,  "d,S",       MATCH_FCLASS_H, MASK_FCLASS_H, match_opcode, 0 },
+{"feq.h",      0, INSN_CLASS_F_AND_ZFH,  "d,S,T",     MATCH_FEQ_H, MASK_FEQ_H, match_opcode, 0 },
+{"flt.h",      0, INSN_CLASS_F_AND_ZFH,  "d,S,T",     MATCH_FLT_H, MASK_FLT_H, match_opcode, 0 },
+{"fle.h",      0, INSN_CLASS_F_AND_ZFH,  "d,S,T",     MATCH_FLE_H, MASK_FLE_H, match_opcode, 0 },
+{"fgt.h",      0, INSN_CLASS_F_AND_ZFH,  "d,T,S",     MATCH_FLT_H, MASK_FLT_H, match_opcode, 0 },
+{"fge.h",      0, INSN_CLASS_F_AND_ZFH,  "d,T,S",     MATCH_FLE_H, MASK_FLE_H, match_opcode, 0 },
+{"fmv.x.h",    0, INSN_CLASS_F_AND_ZFH,  "d,S",       MATCH_FMV_X_H, MASK_FMV_X_H, match_opcode, 0 },
+{"fmv.h.x",    0, INSN_CLASS_F_AND_ZFH,  "D,s",       MATCH_FMV_H_X, MASK_FMV_H_X, match_opcode, 0 },
+{"fcvt.l.h",  64, INSN_CLASS_F_AND_ZFH,  "d,S",       MATCH_FCVT_L_H|MASK_RM, MASK_FCVT_L_H|MASK_RM, match_opcode, 0 },
+{"fcvt.l.h",  64, INSN_CLASS_F_AND_ZFH,  "d,S,m",     MATCH_FCVT_L_H, MASK_FCVT_L_H, match_opcode, 0 },
+{"fcvt.lu.h", 64, INSN_CLASS_F_AND_ZFH,  "d,S",       MATCH_FCVT_LU_H|MASK_RM, MASK_FCVT_LU_H|MASK_RM, match_opcode, 0 },
+{"fcvt.lu.h", 64, INSN_CLASS_F_AND_ZFH,  "d,S,m",     MATCH_FCVT_LU_H, MASK_FCVT_LU_H, match_opcode, 0 },
+{"fcvt.h.l",  64, INSN_CLASS_F_AND_ZFH,  "D,s",       MATCH_FCVT_H_L|MASK_RM, MASK_FCVT_H_L|MASK_RM, match_opcode, 0 },
+{"fcvt.h.l",  64, INSN_CLASS_F_AND_ZFH,  "D,s,m",     MATCH_FCVT_H_L, MASK_FCVT_H_L, match_opcode, 0 },
+{"fcvt.h.lu", 64, INSN_CLASS_F_AND_ZFH,  "D,s",       MATCH_FCVT_H_LU|MASK_RM, MASK_FCVT_H_L|MASK_RM, match_opcode, 0 },
+{"fcvt.h.lu", 64, INSN_CLASS_F_AND_ZFH,  "D,s,m",     MATCH_FCVT_H_LU, MASK_FCVT_H_LU, match_opcode, 0 },
+
 /* RVV */
 {"vsetvl",     0, INSN_CLASS_V,  "d,s,t",  MATCH_VSETVL, MASK_VSETVL, match_opcode, 0},
 {"vsetvli",    0, INSN_CLASS_V,  "d,s,Vc", MATCH_VSETVLI, MASK_VSETVLI, match_opcode, 0},