achieveartificialintelligence updated this revision to Diff 314349.
achieveartificialintelligence marked 2 inline comments as done.
achieveartificialintelligence added a comment.

Including Zfinx, zdinx. Zfhinx.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D93298/new/

https://reviews.llvm.org/D93298

Files:
  llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
  llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
  llvm/lib/Target/RISCV/RISCV.td
  llvm/lib/Target/RISCV/RISCVInstrInfo.td
  llvm/lib/Target/RISCV/RISCVInstrInfoZfinx.td
  llvm/lib/Target/RISCV/RISCVRegisterInfo.td
  llvm/lib/Target/RISCV/RISCVSubtarget.cpp
  llvm/lib/Target/RISCV/RISCVSubtarget.h
  llvm/test/MC/RISCV/rv32i-invalid.s
  llvm/test/MC/RISCV/rv32zdinx-invalid.s
  llvm/test/MC/RISCV/rv32zdinx-valid.s
  llvm/test/MC/RISCV/rv32zfhinx-invalid.s
  llvm/test/MC/RISCV/rv32zfhinx-valid.s
  llvm/test/MC/RISCV/rv32zfinx-invalid.s
  llvm/test/MC/RISCV/rv32zfinx-valid.s
  llvm/test/MC/RISCV/rv64zdinx-invalid.s
  llvm/test/MC/RISCV/rv64zdinx-valid.s
  llvm/test/MC/RISCV/rv64zfhinx-invalid.s
  llvm/test/MC/RISCV/rv64zfhinx-valid.s
  llvm/test/MC/RISCV/rv64zfinx-invalid.s
  llvm/test/MC/RISCV/rv64zfinx-valid.s
  llvm/test/MC/RISCV/rvzdinx-aliases-valid.s
  llvm/test/MC/RISCV/rvzfhinx-aliases-valid.s
  llvm/test/MC/RISCV/rvzfinx-aliases-valid.s

Index: llvm/test/MC/RISCV/rvzfinx-aliases-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rvzfinx-aliases-valid.s
@@ -0,0 +1,82 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zfinx -riscv-no-aliases \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zfinx \
+# RUN:     | FileCheck -check-prefix=CHECK-ALIAS %s
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zfinx -riscv-no-aliases \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zfinx \
+# RUN:     | FileCheck -check-prefix=CHECK-ALIAS %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-zfinx < %s \
+# RUN:     | llvm-objdump -d --mattr=+experimental-zfinx -M no-aliases - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-zfinx < %s \
+# RUN:     | llvm-objdump -d --mattr=+experimental-zfinx - \
+# RUN:     | FileCheck -check-prefix=CHECK-ALIAS %s
+# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+experimental-zfinx < %s \
+# RUN:     | llvm-objdump -d --mattr=+experimental-zfinx -M no-aliases - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+experimental-zfinx < %s \
+# RUN:     | llvm-objdump -d --mattr=+experimental-zfinx - \
+# RUN:     | FileCheck -check-prefix=CHECK-ALIAS %s
+
+##===----------------------------------------------------------------------===##
+## Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
+##===----------------------------------------------------------------------===##
+
+# CHECK-INST: fsgnjx.s s1, s2, s2
+# CHECK-ALIAS: fabs.s s1, s2
+fabs.s s1, s2
+# CHECK-INST: fsgnjn.s s2, s3, s3
+# CHECK-ALIAS: fneg.s s2, s3
+fneg.s s2, s3
+
+# CHECK-INST: flt.s tp, s6, s5
+# CHECK-ALIAS: flt.s tp, s6, s5
+fgt.s x4, s5, s6
+# CHECK-INST: fle.s t2, s1, s0
+# CHECK-ALIAS: fle.s t2, s1, s0
+fge.s x7, x8, x9
+
+##===----------------------------------------------------------------------===##
+## Aliases which omit the rounding mode.
+##===----------------------------------------------------------------------===##
+
+# CHECK-INST: fmadd.s a0, a1, a2, a3, dyn
+# CHECK-ALIAS: fmadd.s a0, a1, a2, a3{{[[:space:]]}}
+fmadd.s x10, x11, x12, x13
+# CHECK-INST: fmsub.s a4, a5, a6, a7, dyn
+# CHECK-ALIAS: fmsub.s a4, a5, a6, a7{{[[:space:]]}}
+fmsub.s x14, x15, x16, x17
+# CHECK-INST: fnmsub.s s2, s3, s4, s5, dyn
+# CHECK-ALIAS: fnmsub.s s2, s3, s4, s5{{[[:space:]]}}
+fnmsub.s x18, x19, x20, x21
+# CHECK-INST: fnmadd.s s6, s7, s8, s9, dyn
+# CHECK-ALIAS: fnmadd.s s6, s7, s8, s9{{[[:space:]]}}
+fnmadd.s x22, x23, x24, x25
+# CHECK-INST: fadd.s s10, s11, t3, dyn
+# CHECK-ALIAS: fadd.s s10, s11, t3{{[[:space:]]}}
+fadd.s x26, x27, x28
+# CHECK-INST: fsub.s t4, t5, t6, dyn
+# CHECK-ALIAS: fsub.s t4, t5, t6{{[[:space:]]}}
+fsub.s x29, x30, x31
+# CHECK-INST: fmul.s s0, s1, s2, dyn
+# CHECK-ALIAS: fmul.s s0, s1, s2{{[[:space:]]}}
+fmul.s s0, s1, s2
+# CHECK-INST: fdiv.s s3, s4, s5, dyn
+# CHECK-ALIAS: fdiv.s s3, s4, s5{{[[:space:]]}}
+fdiv.s s3, s4, s5
+# CHECK-INST: sqrt.s s6, s7, dyn
+# CHECK-ALIAS: sqrt.s s6, s7{{[[:space:]]}}
+fsqrt.s s6, s7
+# CHECK-INST: fcvt.w.s a0, s5, dyn
+# CHECK-ALIAS: fcvt.w.s a0, s5{{[[:space:]]}}
+fcvt.w.s a0, s5
+# CHECK-INST: fcvt.wu.s a1, s6, dyn
+# CHECK-ALIAS: fcvt.wu.s a1, s6{{[[:space:]]}}
+fcvt.wu.s a1, s6
+# CHECK-INST: fcvt.s.w t6, a4, dyn
+# CHECK-ALIAS: fcvt.s.w t6, a4{{[[:space:]]}}
+fcvt.s.w t6, a4
+# CHECK-INST: fcvt.s.wu s0, a5, dyn
+# CHECK-ALIAS: fcvt.s.wu s0, a5{{[[:space:]]}}
+fcvt.s.wu s0, a5
Index: llvm/test/MC/RISCV/rvzfhinx-aliases-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rvzfhinx-aliases-valid.s
@@ -0,0 +1,83 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zfhinx -riscv-no-aliases \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zfhinx \
+# RUN:     | FileCheck -check-prefix=CHECK-ALIAS %s
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zfhinx -riscv-no-aliases \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zfhinx \
+# RUN:     | FileCheck -check-prefix=CHECK-ALIAS %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-zfhinx < %s \
+# RUN:     | llvm-objdump -d --mattr=+experimental-zfhinx -M no-aliases - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-zfhinx < %s \
+# RUN:     | llvm-objdump -d --mattr=+experimental-zfhinx - \
+# RUN:     | FileCheck -check-prefix=CHECK-ALIAS %s
+# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+experimental-zfhinx < %s \
+# RUN:     | llvm-objdump -d --mattr=+experimental-zfhinx -M no-aliases - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+experimental-zfhinx < %s \
+# RUN:     | llvm-objdump -d --mattr=+experimental-zfhinx - \
+# RUN:     | FileCheck -check-prefix=CHECK-ALIAS %s
+
+##===----------------------------------------------------------------------===##
+## Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
+##===----------------------------------------------------------------------===##
+
+# CHECK-INST: fsgnjx.h s1, s2, s2
+# CHECK-ALIAS: fabs.h s1, s2
+fabs.h s1, s2
+# CHECK-INST: fsgnjn.h s2, s3, s3
+# CHECK-ALIAS: fneg.h s2, s3
+fneg.h s2, s3
+
+# CHECK-INST: flt.h tp, s6, s5
+# CHECK-ALIAS: flt.h tp, s6, s5
+fgt.h x4, s5, s6
+# CHECK-INST: fle.h t2, s1, s0
+# CHECK-ALIAS: fle.h t2, s1, s0
+fge.h x7, x8, x9
+
+
+##===----------------------------------------------------------------------===##
+## Aliases which omit the rounding mode.
+##===----------------------------------------------------------------------===##
+
+# CHECK-INST: fmadd.h a0, a1, a2, a3, dyn
+# CHECK-ALIAS: fmadd.h a0, a1, a2, a3{{[[:space:]]}}
+fmadd.h x10, x11, x12, x13
+# CHECK-INST: fmsub.h a4, a5, a6, a7, dyn
+# CHECK-ALIAS: fmsub.h a4, a5, a6, a7{{[[:space:]]}}
+fmsub.h x14, x15, x16, x17
+# CHECK-INST: fnmsub.h s2, s3, s4, s5, dyn
+# CHECK-ALIAS: fnmsub.h s2, s3, s4, s5{{[[:space:]]}}
+fnmsub.h x18, x19, x20, x21
+# CHECK-INST: fnmadd.h s6, s7, s8, s9, dyn
+# CHECK-ALIAS: fnmadd.h s6, s7, s8, s9{{[[:space:]]}}
+fnmadd.h x22, x23, x24, x25
+# CHECK-INST: fadd.h s10, s11, t3, dyn
+# CHECK-ALIAS: fadd.h s10, s11, t3{{[[:space:]]}}
+fadd.h x26, x27, x28
+# CHECK-INST: fsub.h t4, t5, t6, dyn
+# CHECK-ALIAS: fsub.h t4, t5, t6{{[[:space:]]}}
+fsub.h x29, x30, x31
+# CHECK-INST: fmul.h s0, s1, s2, dyn
+# CHECK-ALIAS: fmul.h s0, s1, s2{{[[:space:]]}}
+fmul.h s0, s1, s2
+# CHECK-INST: fdiv.h s3, s4, s5, dyn
+# CHECK-ALIAS: fdiv.h s3, s4, s5{{[[:space:]]}}
+fdiv.h s3, s4, s5
+# CHECK-INST: fsqrt.h s6, s7, dyn
+# CHECK-ALIAS: fsqrt.h s6, s7{{[[:space:]]}}
+fsqrt.h s6, s7
+# CHECK-INST: fcvt.w.h a0, s5, dyn
+# CHECK-ALIAS: fcvt.w.h a0, s5{{[[:space:]]}}
+fcvt.w.h a0, s5
+# CHECK-INST: fcvt.wu.h a1, s6, dyn
+# CHECK-ALIAS: fcvt.wu.h a1, s6{{[[:space:]]}}
+fcvt.wu.h a1, s6
+# CHECK-INST: fcvt.h.w t6, a4, dyn
+# CHECK-ALIAS: fcvt.h.w t6, a4{{[[:space:]]}}
+fcvt.h.w t6, a4
+# CHECK-INST: fcvt.h.wu s0, a5, dyn
+# CHECK-ALIAS: fcvt.h.wu s0, a5{{[[:space:]]}}
+fcvt.h.wu s0, a5
Index: llvm/test/MC/RISCV/rvzdinx-aliases-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rvzdinx-aliases-valid.s
@@ -0,0 +1,27 @@
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zdinx -riscv-no-aliases \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zdinx \
+# RUN:     | FileCheck -check-prefix=CHECK-ALIAS %s
+# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+experimental-zdinx < %s \
+# RUN:     | llvm-objdump -d --mattr=+experimental-zdinx -M no-aliases - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+experimental-zdinx < %s \
+# RUN:     | llvm-objdump -d --mattr=+experimental-zdinx - \
+# RUN:     | FileCheck -check-prefix=CHECK-ALIAS %s
+
+##===----------------------------------------------------------------------===##
+## Aliases which omit the rounding mode.
+##===----------------------------------------------------------------------===##
+
+# CHECK-INST: fcvt.l.d a0, t0, dyn
+# CHECK-ALIAS: fcvt.l.d a0, t0{{[[:space:]]}}
+fcvt.l.d a0, t0
+# CHECK-INST: fcvt.lu.d a1, t1, dyn
+# CHECK-ALIAS: fcvt.lu.d a1, t1{{[[:space:]]}}
+fcvt.lu.d a1, t1
+# CHECK-INST: fcvt.d.l t3, a3, dyn
+# CHECK-ALIAS: fcvt.d.l t3, a3{{[[:space:]]}}
+fcvt.d.l t3, a3
+# CHECK-INST: fcvt.d.lu t4, a4, dyn
+# CHECK-ALIAS: fcvt.d.lu t4, a4{{[[:space:]]}}
+fcvt.d.lu t4, a4
Index: llvm/test/MC/RISCV/rv64zfinx-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv64zfinx-valid.s
@@ -0,0 +1,43 @@
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zfinx -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zfinx < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-zfinx -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+#
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-zfinx < %s 2>&1 \
+# RUN:     | FileCheck -check-prefix=CHECK-RV32 %s
+
+# CHECK-ASM-AND-OBJ: fcvt.l.s a0, t0, dyn
+# CHECK-ASM: encoding: [0x53,0xf5,0x22,0xc0]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
+fcvt.l.s a0, t0, dyn
+# CHECK-ASM-AND-OBJ: fcvt.lu.s a1, t1, dyn
+# CHECK-ASM: encoding: [0xd3,0x75,0x33,0xc0]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
+fcvt.lu.s a1, t1, dyn
+# CHECK-ASM-AND-OBJ: fcvt.s.l t2, a2, dyn
+# CHECK-ASM: encoding: [0xd3,0x73,0x26,0xd0]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
+fcvt.s.l t2, a2, dyn
+# CHECK-ASM-AND-OBJ: fcvt.s.lu t3, a3, dyn
+# CHECK-ASM: encoding: [0x53,0xfe,0x36,0xd0]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
+fcvt.s.lu t3, a3, dyn
+
+# Rounding modes
+# CHECK-ASM-AND-OBJ: fcvt.l.s a4, t4, rne
+# CHECK-ASM: encoding: [0x53,0x87,0x2e,0xc0]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
+fcvt.l.s a4, t4, rne
+# CHECK-ASM-AND-OBJ: fcvt.lu.s a5, t5, rtz
+# CHECK-ASM: encoding: [0xd3,0x17,0x3f,0xc0]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
+fcvt.lu.s a5, t5, rtz
+# CHECK-ASM-AND-OBJ: fcvt.s.l t6, a6, rdn
+# CHECK-ASM: encoding: [0xd3,0x2f,0x28,0xd0]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
+fcvt.s.l t6, a6, rdn
+# CHECK-ASM-AND-OBJ: fcvt.s.lu s7, a7, rup
+# CHECK-ASM: encoding: [0xd3,0xbb,0x38,0xd0]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
+fcvt.s.lu s7, a7, rup
Index: llvm/test/MC/RISCV/rv64zfinx-invalid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv64zfinx-invalid.s
@@ -0,0 +1,9 @@
+# RUN: not llvm-mc -triple riscv64 -mattr=+experimental-zfinx < %s 2>&1 | FileCheck %s
+
+# Integer registers where FP regs are expected
+fcvt.l.s t0, fa0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'F' (Single-Precision Floating-Point)
+fcvt.lu.s t1, fa1 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'F' (Single-Precision Floating-Point)
+
+# FP registers where integer regs are expected
+fcvt.s.l fa2, t2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'F' (Single-Precision Floating-Point)
+fcvt.s.lu fa3, t3 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'F' (Single-Precision Floating-Point)
Index: llvm/test/MC/RISCV/rv64zfhinx-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv64zfhinx-valid.s
@@ -0,0 +1,43 @@
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zfhinx -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zfhinx < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-zfhinx -M no-aliases -d -r - \
+# RUN:     | FileCheck -check-prefixes=CHECK-OBJ,CHECK-ASM-AND-OBJ %s
+#
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-zfhinx < %s 2>&1 \
+# RUN:     | FileCheck -check-prefix=CHECK-RV32 %s
+
+# CHECK-ASM-AND-OBJ: fcvt.l.h a0, t0, dyn
+# CHECK-ASM: encoding: [0x53,0xf5,0x22,0xc4]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
+fcvt.l.h a0, t0, dyn
+# CHECK-ASM-AND-OBJ: fcvt.lu.h a1, t1, dyn
+# CHECK-ASM: encoding: [0xd3,0x75,0x33,0xc4]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
+fcvt.lu.h a1, t1, dyn
+# CHECK-ASM-AND-OBJ: fcvt.h.l t2, a2, dyn
+# CHECK-ASM: encoding: [0xd3,0x73,0x26,0xd4]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
+fcvt.h.l t2, a2, dyn
+# CHECK-ASM-AND-OBJ: fcvt.h.lu t3, a3, dyn
+# CHECK-ASM: encoding: [0x53,0xfe,0x36,0xd4]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
+fcvt.h.lu t3, a3, dyn
+
+# Rounding modes
+# CHECK-ASM-AND-OBJ: fcvt.l.h a4, t4, rne
+# CHECK-ASM: encoding: [0x53,0x87,0x2e,0xc4]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
+fcvt.l.h a4, t4, rne
+# CHECK-ASM-AND-OBJ: fcvt.lu.h a5, t5, rtz
+# CHECK-ASM: encoding: [0xd3,0x17,0x3f,0xc4]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
+fcvt.lu.h a5, t5, rtz
+# CHECK-ASM-AND-OBJ: fcvt.h.l t6, a6, rdn
+# CHECK-ASM: encoding: [0xd3,0x2f,0x28,0xd4]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
+fcvt.h.l t6, a6, rdn
+# CHECK-ASM-AND-OBJ: fcvt.h.lu s7, a7, rup
+# CHECK-ASM: encoding: [0xd3,0xbb,0x38,0xd4]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
+fcvt.h.lu s7, a7, rup
Index: llvm/test/MC/RISCV/rv64zfhinx-invalid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv64zfhinx-invalid.s
@@ -0,0 +1,10 @@
+# RUN: not llvm-mc -triple riscv64 -mattr=+experimental-zfhinx < %s 2>&1 | \
+# RUN:   FileCheck %s
+
+# FP regs where Integer regs are expected
+fcvt.l.h t0, fa0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point)
+fcvt.lu.h t1, fa1 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point)
+
+# Integer registers where FP regs are expected
+fcvt.h.l fa2, t2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point)
+fcvt.h.lu fa3, t3 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point)
Index: llvm/test/MC/RISCV/rv64zdinx-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv64zdinx-valid.s
@@ -0,0 +1,51 @@
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zdinx -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zdinx < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-zdinx -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+#
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-zdinx < %s 2>&1 \
+# RUN:     | FileCheck -check-prefix=CHECK-RV32 %s
+
+# CHECK-ASM-AND-OBJ: fcvt.l.d a0, t0, dyn
+# CHECK-ASM: encoding: [0x53,0xf5,0x22,0xc2]
+# CHECK-RV32: :[[@LINE+1]]:14: error: invalid operand for instruction
+fcvt.l.d a0, t0, dyn
+# CHECK-ASM-AND-OBJ: fcvt.lu.d a1, t1, dyn
+# CHECK-ASM: encoding: [0xd3,0x75,0x33,0xc2]
+# CHECK-RV32: :[[@LINE+1]]:15: error: invalid operand for instruction
+fcvt.lu.d a1, t1, dyn
+# CHECK-ASM-AND-OBJ: fmv.x.d a2, t2
+# CHECK-ASM: encoding: [0x53,0x86,0x03,0xe2]
+# CHECK-RV32: :[[@LINE+1]]:13: error: invalid operand for instruction
+fmv.x.d a2, t2
+# CHECK-ASM-AND-OBJ: fcvt.d.l t3, a3, dyn
+# CHECK-ASM: encoding: [0x53,0xfe,0x26,0xd2]
+# CHECK-RV32: :[[@LINE+1]]:10: error: invalid operand for instruction
+fcvt.d.l t3, a3, dyn
+# CHECK-ASM-AND-OBJ: fcvt.d.lu t4, a4, dyn
+# CHECK-ASM: encoding: [0xd3,0x7e,0x37,0xd2]
+# CHECK-RV32: :[[@LINE+1]]:11: error: invalid operand for instruction
+fcvt.d.lu t4, a4, dyn
+# CHECK-ASM-AND-OBJ: fmv.d.x t5, a5
+# CHECK-ASM: encoding: [0x53,0x8f,0x07,0xf2]
+# CHECK-RV32: :[[@LINE+1]]:9: error: invalid operand for instruction
+fmv.d.x t5, a5
+
+# Rounding modes
+# CHECK-ASM-AND-OBJ: fcvt.d.l t3, a3, rne
+# CHECK-ASM: encoding: [0x53,0x8e,0x26,0xd2]
+# CHECK-RV32: :[[@LINE+1]]:10: error: invalid operand for instruction
+fcvt.d.l t3, a3, rne
+# CHECK-ASM-AND-OBJ: fcvt.d.lu t4, a4, rtz
+# CHECK-ASM: encoding: [0xd3,0x1e,0x37,0xd2]
+# CHECK-RV32: :[[@LINE+1]]:11: error: invalid operand for instruction
+fcvt.d.lu t4, a4, rtz
+# CHECK-ASM-AND-OBJ: fcvt.l.d a0, t0, rdn
+# CHECK-ASM: encoding: [0x53,0xa5,0x22,0xc2]
+# CHECK-RV32: :[[@LINE+1]]:14: error: invalid operand for instruction
+fcvt.l.d a0, t0, rdn
+# CHECK-ASM-AND-OBJ: fcvt.lu.d a1, t1, rup
+# CHECK-ASM: encoding: [0xd3,0x35,0x33,0xc2]
+# CHECK-RV32: :[[@LINE+1]]:15: error: invalid operand for instruction
+fcvt.lu.d a1, t1, rup
Index: llvm/test/MC/RISCV/rv64zdinx-invalid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv64zdinx-invalid.s
@@ -0,0 +1,11 @@
+# RUN: not llvm-mc -triple riscv64 -mattr=+experimental-zdinx < %s 2>&1 | FileCheck %s
+
+# Integer registers where FP regs are expected
+fcvt.l.d t0, fa0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'D' (Double-Precision Floating-Point)
+fcvt.lu.d t1, fa1 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'D' (Double-Precision Floating-Point)
+fmv.x.d t2, fa2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'D' (Double-Precision Floating-Point)
+
+# FP registers where integer regs are expected
+fcvt.d.l fa3, t3 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'D' (Double-Precision Floating-Point)
+fcvt.d.lu fa4, t4 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'D' (Double-Precision Floating-Point)
+fmv.d.x fa5, t5 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'D' (Double-Precision Floating-Point)
Index: llvm/test/MC/RISCV/rv32zfinx-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv32zfinx-valid.s
@@ -0,0 +1,166 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zfinx -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zfinx -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+experimental-zfinx < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-zfinx -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zfinx < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-zfinx -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: lw s0, 12(a0)
+# CHECK-ASM: encoding: [0x03,0x24,0xc5,0x00]
+lw s0, 12(a0)
+# CHECK-ASM-AND-OBJ: lw s1, 4(ra)
+# CHECK-ASM: encoding: [0x83,0xa4,0x40,0x00]
+lw s1, +4(ra)
+# CHECK-ASM-AND-OBJ: lw s2, -2048(a3)
+# CHECK-ASM: encoding: [0x03,0xa9,0x06,0x80]
+lw s2, -2048(x13)
+# CHECK-ASM-AND-OBJ: lw s3, -2048(s1)
+# CHECK-ASM: encoding: [0x83,0xa9,0x04,0x80]
+lw s3, %lo(2048)(s1)
+# CHECK-ASM-AND-OBJ: lw s4, 2047(s2)
+# CHECK-ASM: encoding: [0x03,0x2a,0xf9,0x7f]
+lw s4, 2047(s2)
+# CHECK-ASM-AND-OBJ: lw s5, 0(s3)
+# CHECK-ASM: encoding: [0x83,0xaa,0x09,0x00]
+lw s5, 0(s3)
+
+# CHECK-ASM-AND-OBJ: sw s6, 2047(s4)
+# CHECK-ASM: encoding: [0xa3,0x2f,0x6a,0x7f]
+sw s6, 2047(s4)
+# CHECK-ASM-AND-OBJ: sw s7, -2048(s5)
+# CHECK-ASM: encoding: [0x23,0xa0,0x7a,0x81]
+sw s7, -2048(s5)
+# CHECK-ASM-AND-OBJ: sw s8, -2048(s6)
+# CHECK-ASM: encoding: [0x23,0x20,0x8b,0x81]
+sw s8, %lo(2048)(s6)
+# CHECK-ASM-AND-OBJ: sw s9, 999(s7)
+# CHECK-ASM: encoding: [0xa3,0xa3,0x9b,0x3f]
+sw s9, 999(s7)
+
+# CHECK-ASM-AND-OBJ: fmadd.s a0, a1, a2, a3, dyn
+# CHECK-ASM: encoding: [0x43,0xf5,0xc5,0x68]
+fmadd.s x10, x11, x12, x13, dyn
+# CHECK-ASM-AND-OBJ: fmsub.s a4, a5, a6, a7, dyn
+# CHECK-ASM: encoding: [0x47,0xf7,0x07,0x89]
+fmsub.s x14, x15, x16, x17, dyn
+# CHECK-ASM-AND-OBJ: fnmsub.s s2, s3, s4, s5, dyn
+# CHECK-ASM: encoding: [0x4b,0xf9,0x49,0xa9]
+fnmsub.s x18, x19, x20, x21, dyn
+# CHECK-ASM-AND-OBJ: fnmadd.s s6, s7, s8, s9, dyn
+# CHECK-ASM: encoding: [0x4f,0xfb,0x8b,0xc9]
+fnmadd.s x22, x23, x24, x25, dyn
+
+# CHECK-ASM-AND-OBJ: fadd.s s10, s11, t3, dyn
+# CHECK-ASM: encoding: [0x53,0xfd,0xcd,0x01]
+fadd.s x26, x27, x28, dyn
+# CHECK-ASM-AND-OBJ: fsub.s t4, t5, t6, dyn
+# CHECK-ASM: encoding: [0xd3,0x7e,0xff,0x09]
+fsub.s x29, x30, x31, dyn
+# CHECK-ASM-AND-OBJ: fmul.s s0, s1, s2, dyn
+# CHECK-ASM: encoding: [0x53,0xf4,0x24,0x11]
+fmul.s s0, s1, s2, dyn
+# CHECK-ASM-AND-OBJ: fdiv.s s3, s4, s5, dyn
+# CHECK-ASM: encoding: [0xd3,0x79,0x5a,0x19]
+fdiv.s s3, s4, s5, dyn
+# CHECK-ASM-AND-OBJ: fsqrt.s t1, t2, dyn
+# CHECK-ASM: encoding: [0x53,0xf3,0x03,0x58]
+fsqrt.s t1, t2, dyn
+# CHECK-ASM-AND-OBJ: fsgnj.s s1, a0, a1
+# CHECK-ASM: encoding: [0xd3,0x04,0xb5,0x20]
+fsgnj.s s1, a0, a1
+# CHECK-ASM-AND-OBJ: fsgnjn.s a1, a3, a4
+# CHECK-ASM: encoding: [0xd3,0x95,0xe6,0x20]
+fsgnjn.s a1, a3, a4
+# CHECK-ASM-AND-OBJ: fsgnjx.s a4, a3, a2
+# CHECK-ASM: encoding: [0x53,0xa7,0xc6,0x20]
+fsgnjx.s a4, a3, a2
+# CHECK-ASM-AND-OBJ: fmin.s a5, a6, a7
+# CHECK-ASM: encoding: [0xd3,0x07,0x18,0x29]
+fmin.s a5, a6, a7
+# CHECK-ASM-AND-OBJ: fmax.s s2, s3, s4
+# CHECK-ASM: encoding: [0x53,0x99,0x49,0x29]
+fmax.s s2, s3, s4
+# CHECK-ASM-AND-OBJ: fcvt.w.s a0, s5, dyn
+# CHECK-ASM: encoding: [0x53,0xf5,0x0a,0xc0]
+fcvt.w.s a0, s5, dyn
+# CHECK-ASM-AND-OBJ: fcvt.wu.s a1, s6, dyn
+# CHECK-ASM: encoding: [0xd3,0x75,0x1b,0xc0]
+fcvt.wu.s a1, s6, dyn
+# CHECK-ASM-AND-OBJ: fmv.x.w a2, s7
+# CHECK-ASM: encoding: [0x53,0x86,0x0b,0xe0]
+fmv.x.w a2, s7
+# CHECK-ASM-AND-OBJ: feq.s a1, s8, s9
+# CHECK-ASM: encoding: [0xd3,0x25,0x9c,0xa1]
+feq.s a1, s8, s9
+# CHECK-ASM-AND-OBJ: flt.s a2, s10, s11
+# CHECK-ASM: encoding: [0x53,0x16,0xbd,0xa1]
+flt.s a2, s10, s11
+# CHECK-ASM-AND-OBJ: fle.s a3, t3, t4
+# CHECK-ASM: encoding: [0xd3,0x06,0xde,0xa1]
+fle.s a3, t3, t4
+# CHECK-ASM-AND-OBJ: fclass.s a3, t5
+# CHECK-ASM: encoding: [0xd3,0x16,0x0f,0xe0]
+fclass.s a3, t5
+# CHECK-ASM-AND-OBJ: fcvt.s.w t6, a4, dyn
+# CHECK-ASM: encoding: [0xd3,0x7f,0x07,0xd0]
+fcvt.s.w t6, a4, dyn
+# CHECK-ASM-AND-OBJ: fcvt.s.wu s0, a5, dyn
+# CHECK-ASM: encoding: [0x53,0xf4,0x17,0xd0]
+fcvt.s.wu s0, a5, dyn
+# CHECK-ASM-AND-OBJ: fmv.w.x ra, a6
+# CHECK-ASM: encoding: [0xd3,0x00,0x08,0xf0]
+fmv.w.x ra, a6
+
+# Rounding modes
+
+# CHECK-ASM-AND-OBJ: fmadd.s a0, a1, a2, a3, rne
+# CHECK-ASM: encoding: [0x43,0x85,0xc5,0x68]
+fmadd.s x10, x11, x12, x13, rne
+# CHECK-ASM-AND-OBJ: fmsub.s a4, a5, a6, a7, rtz
+# CHECK-ASM: encoding: [0x47,0x97,0x07,0x89]
+fmsub.s x14, x15, x16, x17, rtz
+# CHECK-ASM-AND-OBJ: fnmsub.s s2, s3, s4, s5, rdn
+# CHECK-ASM: encoding: [0x4b,0xa9,0x49,0xa9]
+fnmsub.s x18, x19, x20, x21, rdn
+# CHECK-ASM-AND-OBJ: fnmadd.s s6, s7, s8, s9, rup
+# CHECK-ASM: encoding: [0x4f,0xbb,0x8b,0xc9]
+fnmadd.s x22, x23, x24, x25, rup
+# CHECK-ASM-AND-OBJ: fmadd.s a0, a1, a2, a3, rmm
+# CHECK-ASM: encoding: [0x43,0xc5,0xc5,0x68]
+fmadd.s x10, x11, x12, x13, rmm
+# CHECK-ASM-AND-OBJ: fmsub.s a4, a5, a6, a7
+# CHECK-ASM: encoding: [0x47,0xf7,0x07,0x89]
+fmsub.s x14, x15, x16, x17, dyn
+
+# CHECK-ASM-AND-OBJ: fadd.s s10, s11, t3, rne
+# CHECK-ASM: encoding: [0x53,0x8d,0xcd,0x01]
+fadd.s x26, x27, x28, rne
+# CHECK-ASM-AND-OBJ: fsub.s t4, t5, t6, rtz
+# CHECK-ASM: encoding: [0xd3,0x1e,0xff,0x09]
+fsub.s x29, x30, x31, rtz
+# CHECK-ASM-AND-OBJ: fmul.s s0, s1, s2, rdn
+# CHECK-ASM: encoding: [0x53,0xa4,0x24,0x11]
+fmul.s s0, s1, s2, rdn
+# CHECK-ASM-AND-OBJ: fdiv.s s3, s4, s5, rup
+# CHECK-ASM: encoding: [0xd3,0x39,0x5a,0x19]
+fdiv.s s3, s4, s5, rup
+
+# CHECK-ASM-AND-OBJ: fsqrt.s t1, t2, rmm
+# CHECK-ASM: encoding: [0x53,0xc3,0x03,0x58]
+fsqrt.s t1, t2, rmm
+# CHECK-ASM-AND-OBJ: fcvt.w.s a0, s5, rup
+# CHECK-ASM: encoding: [0x53,0xb5,0x0a,0xc0]
+fcvt.w.s a0, s5, rup
+# CHECK-ASM-AND-OBJ: fcvt.wu.s a1, s6, rdn
+# CHECK-ASM: encoding: [0xd3,0x25,0x1b,0xc0]
+fcvt.wu.s a1, s6, rdn
+# CHECK-ASM-AND-OBJ: fcvt.s.w t6, a4, rtz
+# CHECK-ASM: encoding: [0xd3,0x1f,0x07,0xd0]
+fcvt.s.w t6, a4, rtz
+# CHECK-ASM-AND-OBJ: fcvt.s.wu s0, a5, rne
+# CHECK-ASM: encoding: [0x53,0x84,0x17,0xd0]
+fcvt.s.wu s0, a5, rne
Index: llvm/test/MC/RISCV/rv32zfinx-invalid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv32zfinx-invalid.s
@@ -0,0 +1,34 @@
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-zfinx < %s 2>&1 | FileCheck %s
+
+# Out of range immediates
+## simm12
+lw t1, -2049(a0) # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
+sw t2, 2048(a1) # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
+
+# Memory operand not formatted correctly
+lw t1, fa0, -200 # CHECK: :[[@LINE]]:13: error: invalid operand for instruction
+sw t2, fa1, 100 # CHECK: :[[@LINE]]:13: error: invalid operand for instruction
+
+# Invalid register names
+lw x15, 100(fa0) # CHECK: :[[@LINE]]:13: error: invalid operand for instruction
+lw t1, 100(fa10) # CHECK: :[[@LINE]]:12: error: expected register
+fsgnjn.s a100, a2, a3 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
+
+# Integer registers where FP regs are expected
+fmv.x.w s7, fa2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'F' (Single-Precision Floating-Point)
+
+# FP registers where integer regs are expected
+fmv.w.x fa8, t2 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
+
+# Rounding mode when a register is expected
+fmadd.s x10, x11, x12, ree # CHECK: :[[@LINE]]:24: error: invalid operand for instruction
+
+# Invalid rounding modes
+fmadd.s x10, x11, x12, x13, ree # CHECK: :[[@LINE]]:29: error: operand must be a valid floating point rounding mode mnemonic
+fmsub.s x14, x15, x16, x17, 0 # CHECK: :[[@LINE]]:29: error: operand must be a valid floating point rounding mode mnemonic
+fnmsub.s x18, x19, x20, x21, 0b111 # CHECK: :[[@LINE]]:30: error: operand must be a valid floating point rounding mode mnemonic
+
+# Using 'D' instructions for an 'F'-only target
+fadd.d t1, t3, t5 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zdinx' (Double in Integer)
+
+# Using RV64F instructions for RV32 is tested in rv64f-valid.s
Index: llvm/test/MC/RISCV/rv32zfhinx-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv32zfhinx-valid.s
@@ -0,0 +1,166 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zfhinx -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zfhinx -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+experimental-zfhinx < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-zfhinx -M no-aliases -d -r - \
+# RUN:     | FileCheck -check-prefixes=CHECK-OBJ,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zfhinx < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-zfhinx -M no-aliases -d -r - \
+# RUN:     | FileCheck -check-prefixes=CHECK-OBJ,CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: lh s0, 12(a0)
+# CHECK-ASM: encoding: [0x03,0x14,0xc5,0x00]
+lh s0, 12(a0)
+# CHECK-ASM-AND-OBJ: lh s1, 4(ra)
+# CHECK-ASM: encoding: [0x83,0x94,0x40,0x00]
+lh s1, +4(ra)
+# CHECK-ASM-AND-OBJ: lh s2, -2048(a3)
+# CHECK-ASM: encoding: [0x03,0x99,0x06,0x80]
+lh s2, -2048(x13)
+# CHECK-ASM-AND-OBJ: lh s3, -2048(s1)
+# CHECK-ASM: encoding: [0x83,0x99,0x04,0x80]
+lh s3, %lo(2048)(s1)
+# CHECK-ASM-AND-OBJ: lh s4, 2047(s2)
+# CHECK-ASM: encoding: [0x03,0x1a,0xf9,0x7f]
+lh s4, 2047(s2)
+# CHECK-ASM-AND-OBJ: lh s5, 0(s3)
+# CHECK-ASM: encoding: [0x83,0x9a,0x09,0x00]
+lh s5, 0(s3)
+
+# CHECK-ASM-AND-OBJ: sh s6, 2047(s4)
+# CHECK-ASM: encoding: [0xa3,0x1f,0x6a,0x7f]
+sh s6, 2047(s4)
+# CHECK-ASM-AND-OBJ: sh s7, -2048(s5)
+# CHECK-ASM: encoding: [0x23,0x90,0x7a,0x81]
+sh s7, -2048(s5)
+# CHECK-ASM-AND-OBJ: sh s0, -2048(s6)
+# CHECK-ASM: encoding: [0x23,0x10,0x8b,0x80]
+sh x8, %lo(2048)(s6)
+# CHECK-ASM-AND-OBJ: sh s1, 999(s7)
+# CHECK-ASM: encoding: [0xa3,0x93,0x9b,0x3e]
+sh x9, 999(s7)
+
+# CHECK-ASM-AND-OBJ: fmadd.h a0, a1, a2, a3, dyn
+# CHECK-ASM: encoding: [0x43,0xf5,0xc5,0x6c]
+fmadd.h x10, x11, x12, x13, dyn
+# CHECK-ASM-AND-OBJ: fmsub.h a4, a5, a6, a7, dyn
+# CHECK-ASM: encoding: [0x47,0xf7,0x07,0x8d]
+fmsub.h x14, x15, x16, x17, dyn
+# CHECK-ASM-AND-OBJ: fnmsub.h s2, s3, s4, s5, dyn
+# CHECK-ASM: encoding: [0x4b,0xf9,0x49,0xad]
+fnmsub.h x18, x19, x20, x21, dyn
+# CHECK-ASM-AND-OBJ: fnmadd.h s6, s7, s8, s9, dyn
+# CHECK-ASM: encoding: [0x4f,0xfb,0x8b,0xcd]
+fnmadd.h x22, x23, x24, x25, dyn
+
+# CHECK-ASM-AND-OBJ: fadd.h s10, s11, t3, dyn
+# CHECK-ASM: encoding: [0x53,0xfd,0xcd,0x05]
+fadd.h x26, x27, x28, dyn
+# CHECK-ASM-AND-OBJ: fsub.h t4, t5, t6, dyn
+# CHECK-ASM: encoding: [0xd3,0x7e,0xff,0x0d]
+fsub.h x29, x30, x31, dyn
+# CHECK-ASM-AND-OBJ: fmul.h s0, s1, s2, dyn
+# CHECK-ASM: encoding: [0x53,0xf4,0x24,0x15]
+fmul.h s0, s1, s2, dyn
+# CHECK-ASM-AND-OBJ: fdiv.h s3, s4, s5, dyn
+# CHECK-ASM: encoding: [0xd3,0x79,0x5a,0x1d]
+fdiv.h s3, s4, s5, dyn
+# CHECK-ASM-AND-OBJ: fsqrt.h s6, s7, dyn
+# CHECK-ASM: encoding: [0x53,0xfb,0x0b,0x5c]
+fsqrt.h s6, s7, dyn
+# CHECK-ASM-AND-OBJ: fsgnj.h s1, a0, a1
+# CHECK-ASM: encoding: [0xd3,0x04,0xb5,0x24]
+fsgnj.h x9, x10, x11
+# CHECK-ASM-AND-OBJ: fsgnjn.h a1, a3, a4
+# CHECK-ASM: encoding: [0xd3,0x95,0xe6,0x24]
+fsgnjn.h x11, x13, x14
+# CHECK-ASM-AND-OBJ: fsgnjx.h a4, a3, a2
+# CHECK-ASM: encoding: [0x53,0xa7,0xc6,0x24]
+fsgnjx.h x14, x13, x12
+# CHECK-ASM-AND-OBJ: fmin.h a5, a6, a7
+# CHECK-ASM: encoding: [0xd3,0x07,0x18,0x2d]
+fmin.h x15, x16, x17
+# CHECK-ASM-AND-OBJ: fmax.h s2, s3, s4
+# CHECK-ASM: encoding: [0x53,0x99,0x49,0x2d]
+fmax.h x18, x19, x20
+# CHECK-ASM-AND-OBJ: fcvt.w.h a0, s5, dyn
+# CHECK-ASM: encoding: [0x53,0xf5,0x0a,0xc4]
+fcvt.w.h x10, x21, dyn
+# CHECK-ASM-AND-OBJ: fcvt.wu.h a1, s6, dyn
+# CHECK-ASM: encoding: [0xd3,0x75,0x1b,0xc4]
+fcvt.wu.h x11, x22, dyn
+# CHECK-ASM-AND-OBJ: fmv.x.h a2, s7
+# CHECK-ASM: encoding: [0x53,0x86,0x0b,0xe4]
+fmv.x.h x12, x23
+# CHECK-ASM-AND-OBJ: feq.h a1, s8, s9
+# CHECK-ASM: encoding: [0xd3,0x25,0x9c,0xa5]
+feq.h x11, x24, x25
+# CHECK-ASM-AND-OBJ: flt.h a2, s10, s11
+# CHECK-ASM: encoding: [0x53,0x16,0xbd,0xa5]
+flt.h x12, x26, x27
+# CHECK-ASM-AND-OBJ: fle.h a3, t3, t4
+# CHECK-ASM: encoding: [0xd3,0x06,0xde,0xa5]
+fle.h x13, x28, x29
+# CHECK-ASM-AND-OBJ: fclass.h a3, t5
+# CHECK-ASM: encoding: [0xd3,0x16,0x0f,0xe4]
+fclass.h x13, x30
+# CHECK-ASM-AND-OBJ: fcvt.h.w t6, a4, dyn
+# CHECK-ASM: encoding: [0xd3,0x7f,0x07,0xd4]
+fcvt.h.w x31, x14, dyn
+# CHECK-ASM-AND-OBJ: fcvt.h.wu s0, a5, dyn
+# CHECK-ASM: encoding: [0x53,0xf4,0x17,0xd4]
+fcvt.h.wu s0, x15, dyn
+# CHECK-ASM-AND-OBJ: fmv.h.x s1, a6
+# CHECK-ASM: encoding: [0xd3,0x04,0x08,0xf4]
+fmv.h.x s1, x16
+
+# Rounding modes
+
+# CHECK-ASM-AND-OBJ: fmadd.h a0, a1, a2, a3, rne
+# CHECK-ASM: encoding: [0x43,0x85,0xc5,0x6c]
+fmadd.h x10, x11, x12, x13, rne
+# CHECK-ASM-AND-OBJ: fmsub.h a4, a5, a6, a7, rtz
+# CHECK-ASM: encoding: [0x47,0x97,0x07,0x8d]
+fmsub.h x14, x15, x16, x17, rtz
+# CHECK-ASM-AND-OBJ: fnmsub.h s2, s3, s4, s5, rdn
+# CHECK-ASM: encoding: [0x4b,0xa9,0x49,0xad]
+fnmsub.h x18, x19, x20, x21, rdn
+# CHECK-ASM-AND-OBJ: fnmadd.h s6, s7, s8, s9, rup
+# CHECK-ASM: encoding: [0x4f,0xbb,0x8b,0xcd]
+fnmadd.h x22, x23, x24, x25, rup
+# CHECK-ASM-AND-OBJ: fmadd.h a0, a1, a2, a3, rmm
+# CHECK-ASM: encoding: [0x43,0xc5,0xc5,0x6c]
+fmadd.h x10, x11, x12, x13, rmm
+# CHECK-ASM-AND-OBJ: fmsub.h a4, a5, a6, a7
+# CHECK-ASM: encoding: [0x47,0xf7,0x07,0x8d]
+fmsub.h x14, x15, x16, x17, dyn
+
+# CHECK-ASM-AND-OBJ: fadd.h s10, s11, t3, rne
+# CHECK-ASM: encoding: [0x53,0x8d,0xcd,0x05]
+fadd.h x26, x27, x28, rne
+# CHECK-ASM-AND-OBJ: fsub.h t4, t5, t6, rtz
+# CHECK-ASM: encoding: [0xd3,0x1e,0xff,0x0d]
+fsub.h x29, x30, x31, rtz
+# CHECK-ASM-AND-OBJ: fmul.h s0, s1, s2, rdn
+# CHECK-ASM: encoding: [0x53,0xa4,0x24,0x15]
+fmul.h s0, s1, s2, rdn
+# CHECK-ASM-AND-OBJ: fdiv.h s3, s4, s5, rup
+# CHECK-ASM: encoding: [0xd3,0x39,0x5a,0x1d]
+fdiv.h s3, s4, s5, rup
+
+# CHECK-ASM-AND-OBJ: fsqrt.h s6, s7, rmm
+# CHECK-ASM: encoding: [0x53,0xcb,0x0b,0x5c]
+fsqrt.h s6, s7, rmm
+# CHECK-ASM-AND-OBJ: fcvt.w.h a0, s5, rup
+# CHECK-ASM: encoding: [0x53,0xb5,0x0a,0xc4]
+fcvt.w.h x10, x21, rup
+# CHECK-ASM-AND-OBJ: fcvt.wu.h a1, s6, rdn
+# CHECK-ASM: encoding: [0xd3,0x25,0x1b,0xc4]
+fcvt.wu.h x11, x22, rdn
+# CHECK-ASM-AND-OBJ: fcvt.h.w t6, a4, rtz
+# CHECK-ASM: encoding: [0xd3,0x1f,0x07,0xd4]
+fcvt.h.w x31, x14, rtz
+# CHECK-ASM-AND-OBJ: fcvt.h.wu s0, a5, rne
+# CHECK-ASM: encoding: [0x53,0x84,0x17,0xd4]
+fcvt.h.wu s0, a5, rne
Index: llvm/test/MC/RISCV/rv32zfhinx-invalid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv32zfhinx-invalid.s
@@ -0,0 +1,36 @@
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-zfhinx < %s 2>&1 | \
+# RUN:   FileCheck %s
+
+# Out of range immediates
+## simm12
+lh t1, -2049(a0) # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
+sh t2, 2048(a1) # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
+
+# Memory operand not formatted correctly
+lh t1, a0, -200 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction
+sw t2, a1, 100 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction
+
+# Invalid register names
+flh ft15, 100(a0) # CHECK: :[[@LINE]]:5: error: invalid operand for instruction
+flh ft1, 100(a10) # CHECK: :[[@LINE]]:14: error: expected register
+fsgnjn.h a100, a2, a3 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
+
+# Integer registers where FP regs are expected
+fmv.h.x a8, ft2 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
+
+# FP registers where integer regs are expected
+fmv.x.h fs7, a2 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
+
+# Rounding mode when a register is expected
+fmadd.h x10, x11, x12, ree # CHECK: :[[@LINE]]:24: error: invalid operand for instruction
+
+# Invalid rounding modes
+fmadd.h x10, x11, x12, x13, ree # CHECK: :[[@LINE]]:29: error: operand must be a valid floating point rounding mode mnemonic
+fmsub.h x14, x15, x16, x17, 0 # CHECK: :[[@LINE]]:29: error: operand must be a valid floating point rounding mode mnemonic
+fnmsub.h x18, x19, x20, x21, 0b111 # CHECK: :[[@LINE]]:30: error: operand must be a valid floating point rounding mode mnemonic
+
+# Integer registers where FP regs are expected
+fadd.h fa2, fa1, fa0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point)
+
+# FP registers where integer regs are expected
+fcvt.wu.h t2, fa1 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point)
Index: llvm/test/MC/RISCV/rv32zdinx-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv32zdinx-valid.s
@@ -0,0 +1,156 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zdinx -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+experimental-zdinx < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-zdinx -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zdinx -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zdinx < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-zdinx -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: lw s0, 12(a0)
+# CHECK-ASM: encoding: [0x03,0x24,0xc5,0x00]
+lw s0, 12(a0)
+# CHECK-ASM-AND-OBJ: lw s1, 4(ra)
+# CHECK-ASM: encoding: [0x83,0xa4,0x40,0x00]
+lw s1, +4(ra)
+# CHECK-ASM-AND-OBJ: lw s2, -2048(a3)
+# CHECK-ASM: encoding: [0x03,0xa9,0x06,0x80]
+lw s2, -2048(x13)
+# CHECK-ASM-AND-OBJ: lw s3, -2048(s1)
+# CHECK-ASM: encoding: [0x83,0xa9,0x04,0x80]
+lw s3, %lo(2048)(s1)
+# CHECK-ASM-AND-OBJ: lw s4, 2047(s2)
+# CHECK-ASM: encoding: [0x03,0x2a,0xf9,0x7f]
+lw s4, 2047(s2)
+# CHECK-ASM-AND-OBJ: lw s5, 0(s3)
+# CHECK-ASM: encoding: [0x83,0xaa,0x09,0x00]
+lw s5, 0(s3)
+
+# CHECK-ASM-AND-OBJ: sw s6, 2047(s4)
+# CHECK-ASM: encoding: [0xa3,0x2f,0x6a,0x7f]
+sw s6, 2047(s4)
+# CHECK-ASM-AND-OBJ: sw s7, -2048(s5)
+# CHECK-ASM: encoding: [0x23,0xa0,0x7a,0x81]
+sw s7, -2048(s5)
+# CHECK-ASM-AND-OBJ: sw s8, -2048(s6)
+# CHECK-ASM: encoding: [0x23,0x20,0x8b,0x81]
+sw s8, %lo(2048)(s6)
+# CHECK-ASM-AND-OBJ: sw s9, 999(s7)
+# CHECK-ASM: encoding: [0xa3,0xa3,0x9b,0x3f]
+sw s9, 999(s7)
+
+# CHECK-ASM-AND-OBJ: fmadd.d a0, a2, a4, a6, dyn
+# CHECK-ASM: encoding: [0x43,0x75,0xe6,0x82]
+fmadd.d x10, x12, x14, x16, dyn
+# CHECK-ASM-AND-OBJ: fmsub.d a0, a2, a4, a6, dyn
+# CHECK-ASM: encoding: [0x47,0x75,0xe6,0x82]
+fmsub.d x10, x12, x14, x16, dyn
+# CHECK-ASM-AND-OBJ: fnmsub.d a0, a2, a4, a6, dyn
+# CHECK-ASM: encoding: [0x4b,0x75,0xe6,0x82]
+fnmsub.d x10, x12, x14, x16, dyn
+# CHECK-ASM-AND-OBJ: fnmadd.d a0, a2, a4, a6, dyn
+# CHECK-ASM: encoding: [0x4f,0x75,0xe6,0x82]
+fnmadd.d x10, x12, x14, x16, dyn
+
+# CHECK-ASM-AND-OBJ: fadd.d s10, t3, t5, dyn
+# CHECK-ASM: encoding: [0x53,0x7d,0xee,0x03]
+fadd.d x26, x28, x30, dyn
+# CHECK-ASM-AND-OBJ: fsub.d s10, t3, t5, dyn
+# CHECK-ASM: encoding: [0x53,0x7d,0xee,0x0b]
+fsub.d x26, x28, x30, dyn
+# CHECK-ASM-AND-OBJ: fmul.d s10, t3, t5, dyn
+# CHECK-ASM: encoding: [0x53,0x7d,0xee,0x13]
+fmul.d x26, x28, x30, dyn
+# CHECK-ASM-AND-OBJ: fdiv.d s10, t3, t5, dyn
+# CHECK-ASM: encoding: [0x53,0x7d,0xee,0x1b]
+fdiv.d x26, x28, x30, dyn
+# CHECK-ASM-AND-OBJ: fsqrt.d s4, s6, dyn
+# CHECK-ASM: encoding: [0x53,0x7a,0x0b,0x5a]
+fsqrt.d x20, x22, dyn
+# CHECK-ASM-AND-OBJ: fsgnj.d s10, t3, t5
+# CHECK-ASM: encoding: [0x53,0x0d,0xee,0x23]
+fsgnj.d x26, x28, x30
+# CHECK-ASM-AND-OBJ: fsgnjn.d s10, t3, t5
+# CHECK-ASM: encoding: [0x53,0x1d,0xee,0x23]
+fsgnjn.d x26, x28, x30
+# CHECK-ASM-AND-OBJ: fsgnjx.d s10, t3, t5
+# CHECK-ASM: encoding: [0x53,0x2d,0xee,0x23]
+fsgnjx.d x26, x28, x30
+# CHECK-ASM-AND-OBJ: fmin.d s10, t3, t5
+# CHECK-ASM: encoding: [0x53,0x0d,0xee,0x2b]
+fmin.d x26, x28, x30
+# CHECK-ASM-AND-OBJ: fmax.d s10, t3, t5
+# CHECK-ASM: encoding: [0x53,0x1d,0xee,0x2b]
+fmax.d x26, x28, x30
+
+# CHECK-ASM-AND-OBJ: fcvt.s.d s10, t3, dyn
+# CHECK-ASM: encoding: [0x53,0x7d,0x1e,0x40]
+fcvt.s.d x26, x28, dyn
+# CHECK-ASM-AND-OBJ: fcvt.d.s s10, t3
+# CHECK-ASM: encoding: [0x53,0x0d,0x0e,0x42]
+fcvt.d.s x26, x28
+# CHECK-ASM-AND-OBJ: feq.d s10, t3, t5
+# CHECK-ASM: encoding: [0x53,0x2d,0xee,0xa3]
+feq.d x26, x28, x30
+# CHECK-ASM-AND-OBJ: flt.d s10, t3, t5
+# CHECK-ASM: encoding: [0x53,0x1d,0xee,0xa3]
+flt.d x26, x28, x30
+# CHECK-ASM-AND-OBJ: fle.d s10, t3, t5
+# CHECK-ASM: encoding: [0x53,0x0d,0xee,0xa3]
+fle.d x26, x28, x30
+# CHECK-ASM-AND-OBJ: fclass.d s10, t3
+# CHECK-ASM: encoding: [0x53,0x1d,0x0e,0xe2]
+fclass.d x26, x28
+
+# CHECK-ASM-AND-OBJ: fcvt.w.d s4, s6, dyn
+# CHECK-ASM: encoding: [0x53,0x7a,0x0b,0xc2]
+fcvt.w.d x20, x22, dyn
+# CHECK-ASM-AND-OBJ: fcvt.d.w s10, t3
+# CHECK-ASM: encoding: [0x53,0x0d,0x0e,0xd2]
+fcvt.d.w x26, x28
+# CHECK-ASM-AND-OBJ: fcvt.d.wu s10, t3
+# CHECK-ASM: encoding: [0x53,0x0d,0x1e,0xd2]
+fcvt.d.wu x26, x28
+
+# Rounding modes
+
+# CHECK-ASM-AND-OBJ: fmadd.d a0, a2, a4, a6, rne
+# CHECK-ASM: encoding: [0x43,0x05,0xe6,0x82]
+fmadd.d x10, x12, x14, x16, rne
+# CHECK-ASM-AND-OBJ: fmsub.d a0, a2, a4, a6, rtz
+# CHECK-ASM: encoding: [0x47,0x15,0xe6,0x82]
+fmsub.d x10, x12, x14, x16, rtz
+# CHECK-ASM-AND-OBJ: fnmsub.d a0, a2, a4, a6, rdn
+# CHECK-ASM: encoding: [0x4b,0x25,0xe6,0x82]
+fnmsub.d x10, x12, x14, x16, rdn
+# CHECK-ASM-AND-OBJ: fnmadd.d a0, a2, a4, a6, rup
+# CHECK-ASM: encoding: [0x4f,0x35,0xe6,0x82]
+fnmadd.d x10, x12, x14, x16, rup
+
+# CHECK-ASM-AND-OBJ: fadd.d s10, t3, t5, rmm
+# CHECK-ASM: encoding: [0x53,0x4d,0xee,0x03]
+fadd.d x26, x28, x30, rmm
+# CHECK-ASM-AND-OBJ: fsub.d s10, t3, t5, dyn
+# CHECK-ASM: encoding: [0x53,0x7d,0xee,0x0b]
+fsub.d x26, x28, x30, dyn
+# CHECK-ASM-AND-OBJ: fmul.d s10, t3, t5, rne
+# CHECK-ASM: encoding: [0x53,0x0d,0xee,0x13]
+fmul.d x26, x28, x30, rne
+# CHECK-ASM-AND-OBJ: fdiv.d s10, t3, t5, rtz
+# CHECK-ASM: encoding: [0x53,0x1d,0xee,0x1b]
+fdiv.d x26, x28, x30, rtz
+
+# CHECK-ASM-AND-OBJ: fsqrt.d s4, s6, rdn
+# CHECK-ASM: encoding: [0x53,0x2a,0x0b,0x5a]
+fsqrt.d x20, x22, rdn
+# CHECK-ASM-AND-OBJ: fcvt.s.d s4, s6, rup
+# CHECK-ASM: encoding: [0x53,0x3a,0x1b,0x40]
+fcvt.s.d x20, x22, rup
+# CHECK-ASM-AND-OBJ: fcvt.w.d s4, s6, rmm
+# CHECK-ASM: encoding: [0x53,0x4a,0x0b,0xc2]
+fcvt.w.d x20, x22, rmm
+# CHECK-ASM-AND-OBJ: fcvt.wu.d s4, s6, dyn
+# CHECK-ASM: encoding: [0x53,0x7a,0x1b,0xc2]
+fcvt.wu.d x20, x22, dyn
Index: llvm/test/MC/RISCV/rv32zdinx-invalid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv32zdinx-invalid.s
@@ -0,0 +1,12 @@
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-zdinx < %s 2>&1 | FileCheck %s
+
+# Invalid register names
+fsgnjn.d a100, a2, a3 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
+
+# Integer registers where FP regs are expected
+fadd.d a2, a2, fa0 # CHECK: :[[@LINE]]:16: error: invalid operand for instruction
+
+# Access the odd register when the even register is needed
+fmadd.d x1, x2, x4, x6 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
+fadd.d a2, a1, a2 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction
+fsgnjn.d a1, a2, a3 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
Index: llvm/test/MC/RISCV/rv32i-invalid.s
===================================================================
--- llvm/test/MC/RISCV/rv32i-invalid.s
+++ llvm/test/MC/RISCV/rv32i-invalid.s
@@ -117,7 +117,7 @@
 jal gp, %pcrel_lo(4) # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574]
 jal gp, %pcrel_lo(d) # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574]
 
-# Bare symbol names when an operand modifier is required and unsupported 
+# Bare symbol names when an operand modifier is required and unsupported
 # operand modifiers.
 
 lui a0, foo # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi/%tprel_hi modifier or an integer in the range [0, 1048575]
@@ -173,6 +173,9 @@
 amomaxu.w s5, s4, (s3) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'A' (Atomic Instructions)
 fadd.s ft0, ft1, ft2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'F' (Single-Precision Floating-Point)
 fadd.h ft0, ft1, ft2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point)
+fadd.h a0, a1, a2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zfhinx' (Half float in Integer)
+fadd.s a0, a1, a2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zfinx' (Float in Integer)
+fadd.d a0, a0, a2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zdinx' (Double in Integer)
 
 # Using floating point registers when integer registers are expected
 addi a2, ft0, 24 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
Index: llvm/lib/Target/RISCV/RISCVSubtarget.h
===================================================================
--- llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -54,6 +54,9 @@
   bool HasStdExtZvlsseg = false;
   bool HasStdExtZvamo = false;
   bool HasStdExtZfh = false;
+  bool HasStdExtZfinx = false;
+  bool HasStdExtZdinx = false;
+  bool HasStdExtZfhinx = false;
   bool HasRV64 = false;
   bool IsRV32E = false;
   bool EnableLinkerRelax = false;
@@ -61,6 +64,7 @@
   bool EnableSaveRestore = false;
   unsigned XLen = 32;
   MVT XLenVT = MVT::i32;
+  MVT ZfinxLenVT = MVT::i32;
   RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown;
   BitVector UserReservedRegister;
   RISCVFrameLowering FrameLowering;
@@ -90,9 +94,7 @@
     return &FrameLowering;
   }
   const RISCVInstrInfo *getInstrInfo() const override { return &InstrInfo; }
-  const RISCVRegisterInfo *getRegisterInfo() const override {
-    return &RegInfo;
-  }
+  const RISCVRegisterInfo *getRegisterInfo() const override { return &RegInfo; }
   const RISCVTargetLowering *getTargetLowering() const override {
     return &TLInfo;
   }
@@ -120,6 +122,9 @@
   bool hasStdExtZvlsseg() const { return HasStdExtZvlsseg; }
   bool hasStdExtZvamo() const { return HasStdExtZvamo; }
   bool hasStdExtZfh() const { return HasStdExtZfh; }
+  bool hasStdExtZfinx() const { return HasStdExtZfinx; }
+  bool hasStdExtZdinx() const { return HasStdExtZdinx; }
+  bool hasStdExtZfhinx() const { return HasStdExtZfhinx; }
   bool is64Bit() const { return HasRV64; }
   bool isRV32E() const { return IsRV32E; }
   bool enableLinkerRelax() const { return EnableLinkerRelax; }
@@ -146,6 +151,6 @@
   const LegalizerInfo *getLegalizerInfo() const override;
   const RegisterBankInfo *getRegBankInfo() const override;
 };
-} // End llvm namespace
+} // namespace llvm
 
 #endif
Index: llvm/lib/Target/RISCV/RISCVSubtarget.cpp
===================================================================
--- llvm/lib/Target/RISCV/RISCVSubtarget.cpp
+++ llvm/lib/Target/RISCV/RISCVSubtarget.cpp
@@ -42,6 +42,7 @@
   ParseSubtargetFeatures(CPUName, TuneCPUName, FS);
   if (Is64Bit) {
     XLenVT = MVT::i64;
+    ZfinxLenVT = MVT::f64;
     XLen = 64;
   }
 
Index: llvm/lib/Target/RISCV/RISCVRegisterInfo.td
===================================================================
--- llvm/lib/Target/RISCV/RISCVRegisterInfo.td
+++ llvm/lib/Target/RISCV/RISCVRegisterInfo.td
@@ -57,6 +57,8 @@
 def sub_vrm4_hi : SubRegIndex<128, -1>;
 def sub_vrm8    : SubRegIndex<256, -1>;
 def sub_vrm8_hi : SubRegIndex<256, -1>;
+
+def sub_32_hi : SubRegIndex<32, 32>;
 } // Namespace = "RISCV"
 
 // Integer registers
@@ -108,6 +110,8 @@
 
 def XLenVT : ValueTypeByHwMode<[RV32, RV64],
                                [i32,  i64]>;
+def ZfinxLenVT : ValueTypeByHwMode<[RV32, RV64],
+                                   [f32, f64]>;
 
 // The order of registers represents the preferred allocation sequence.
 // Registers are listed in the order caller-save, callee-save, specials.
@@ -452,3 +456,47 @@
 def VMV0 : RegisterClass<"RISCV", VMaskVTs, 64, (add V0)> {
   let Size = 64;
 }
+
+let RegAltNameIndices = [ABIRegAltName] in {
+  foreach Index = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22,
+                   24, 26, 28, 30] in {
+    defvar Reg = !cast<Register>("X"#Index);
+    def X#Index#_PD : RISCVRegWithSubRegs<Index, Reg.AsmName,
+                       [!cast<Register>("X"#Index),
+                        !cast<Register>("X"#!add(Index, 1))],
+                       Reg.AltNames> {
+      let SubRegIndices = [sub_32, sub_32_hi];
+    }
+  }  
+}
+
+def GPRH : RegisterClass<"RISCV", [f16], 16, (add
+    (sequence "X%u", 10, 17),
+    (sequence "X%u", 5, 7),
+    (sequence "X%u", 28, 31),
+    (sequence "X%u", 8, 9),
+    (sequence "X%u", 18, 27),
+    (sequence "X%u", 0, 4)
+)>;
+
+def GPRF : RegisterClass<"RISCV", [f32], 32, (add
+    (sequence "X%u", 10, 17),
+    (sequence "X%u", 5, 7),
+    (sequence "X%u", 28, 31),
+    (sequence "X%u", 8, 9),
+    (sequence "X%u", 18, 27),
+    (sequence "X%u", 0, 4)
+)>;
+
+def GPRD : RegisterClass<"RISCV", [f64], 64, (add
+    (sequence "X%u", 10, 17),
+    (sequence "X%u", 5, 7),
+    (sequence "X%u", 28, 31),
+    (sequence "X%u", 8, 9),
+    (sequence "X%u", 18, 27),
+    (sequence "X%u", 0, 4)
+)>;
+
+def GPRPD : RegisterClass<"RISCV", [f64], 64, (add
+    X0_PD, X2_PD, X4_PD, X6_PD, X8_PD, X10_PD, X12_PD, X14_PD, X16_PD, 
+    X18_PD, X20_PD, X22_PD, X24_PD, X26_PD, X28_PD, X30_PD)>;
\ No newline at end of file
Index: llvm/lib/Target/RISCV/RISCVInstrInfoZfinx.td
===================================================================
--- /dev/null
+++ llvm/lib/Target/RISCV/RISCVInstrInfoZfinx.td
@@ -0,0 +1,653 @@
+//=== RISCVInstrInfoZfinx.td - RISC-V 'Zfinx' instructions -*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the RISC-V instructions from the standard 'Zfinx'
+// float in integer.
+// This version is still experimental as the 'Zfinx' extension hasn't been
+// ratified yet.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Instruction class templates
+//===----------------------------------------------------------------------===//
+
+def GPRasFPR : AsmOperandClass {
+  let Name = "GPRasFPR";
+  let ParserMethod = "parseGPRasFPR";
+}
+
+def GPRPDasFPR : AsmOperandClass {
+  let Name = "GPRPDasFPR";
+  let ParserMethod = "parseGPRasFPR";
+}
+
+def GPRDasFPR : AsmOperandClass {
+  let Name = "GPRDasFPR";
+  let ParserMethod = "parseGPRasFPR";
+}
+
+def GPRHOp : RegisterOperand<GPRH> {
+  let ParserMatchClass = GPRasFPR;
+}
+
+def GPRFOp : RegisterOperand<GPRF> {
+  let ParserMatchClass = GPRasFPR;
+}
+
+def GPRDOp : RegisterOperand<GPRD> {
+  let ParserMatchClass = GPRDasFPR;
+}
+
+def GPRPDOp : RegisterOperand<GPRPD> {
+  let ParserMatchClass = GPRPDasFPR;
+}
+
+def GPROp : RegisterOperand<GPR> {
+  let ParserMatchClass = GPRasFPR;
+}
+
+let DecoderNamespace = "RVZfinx" in {
+// For all floating extension
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPUnaryOpINX_r<bits<7> funct7, bits<3> funct3, RegisterOperand rdty,
+                RegisterOperand rs1ty, string opcodestr>
+    : RVInstR<funct7, funct3, OPC_OP_FP, (outs rdty:$rd), (ins rs1ty:$rs1),
+              opcodestr, "$rd, $rs1">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPUnaryOpINX_r_frm<bits<7> funct7, RegisterOperand rdty, RegisterOperand rs1ty,
+                      string opcodestr>
+    : RVInstRFrm<funct7, OPC_OP_FP, (outs rdty:$rd),
+                 (ins rs1ty:$rs1, frmarg:$funct3), opcodestr,
+                  "$rd, $rs1, $funct3">;
+
+// RV32/64 and zfh extension
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPFMAHINX_rrr_frm<RISCVOpcode opcode, string opcodestr>
+    : RVInstR4<0b10, opcode, (outs GPRHOp:$rd),
+               (ins GPRHOp:$rs1, GPRHOp:$rs2, GPRHOp:$rs3, frmarg:$funct3),
+                opcodestr, "$rd, $rs1, $rs2, $rs3, $funct3">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPALUHINX_rr<bits<7> funct7, bits<3> funct3, string opcodestr>
+    : RVInstR<funct7, funct3, OPC_OP_FP, (outs GPRHOp:$rd),
+              (ins GPRHOp:$rs1, GPRHOp:$rs2), opcodestr, "$rd, $rs1, $rs2">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPALUHINX_rr_frm<bits<7> funct7, string opcodestr>
+    : RVInstRFrm<funct7, OPC_OP_FP, (outs GPRHOp:$rd),
+                 (ins GPRHOp:$rs1, GPRHOp:$rs2, frmarg:$funct3), opcodestr,
+                  "$rd, $rs1, $rs2, $funct3">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPCmpHINX_rr<bits<3> funct3, string opcodestr>
+    : RVInstR<0b1010010, funct3, OPC_OP_FP, (outs GPROp:$rd),
+              (ins GPRHOp:$rs1, GPRHOp:$rs2), opcodestr, "$rd, $rs1, $rs2">,
+      Sched<[]>;
+
+// RV32/64 and F extension
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPFMASINX_rrr_frm<RISCVOpcode opcode, string opcodestr>
+    : RVInstR4<0b00, opcode, (outs GPRFOp:$rd),
+               (ins GPRFOp:$rs1, GPRFOp:$rs2, GPRFOp:$rs3, frmarg:$funct3),
+                opcodestr, "$rd, $rs1, $rs2, $rs3, $funct3">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPALUSINX_rr<bits<7> funct7, bits<3> funct3, string opcodestr>
+    : RVInstR<funct7, funct3, OPC_OP_FP, (outs GPRFOp:$rd),
+              (ins GPRFOp:$rs1, GPRFOp:$rs2), opcodestr, "$rd, $rs1, $rs2">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPALUSINX_rr_frm<bits<7> funct7, string opcodestr>
+    : RVInstRFrm<funct7, OPC_OP_FP, (outs GPRFOp:$rd),
+                 (ins GPRFOp:$rs1, GPRFOp:$rs2, frmarg:$funct3), opcodestr,
+                  "$rd, $rs1, $rs2, $funct3">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPCmpSINX_rr<bits<3> funct3, string opcodestr>
+    : RVInstR<0b1010000, funct3, OPC_OP_FP, (outs GPROp:$rd),
+              (ins GPRFOp:$rs1, GPRFOp:$rs2), opcodestr, "$rd, $rs1, $rs2">,
+      Sched<[WriteFCmp32, ReadFCmp32, ReadFCmp32]>;
+
+// RV64 D extension
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPFMADINX_rrr_frm<RISCVOpcode opcode, string opcodestr, RegisterOperand freg>
+    : RVInstR4<0b01, opcode, (outs freg:$rd),
+               (ins freg:$rs1, freg:$rs2, freg:$rs3, frmarg:$funct3),
+                opcodestr, "$rd, $rs1, $rs2, $rs3, $funct3">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPALUDINX_rr<bits<7> funct7, bits<3> funct3, string opcodestr, RegisterOperand freg>
+    : RVInstR<funct7, funct3, OPC_OP_FP, (outs freg:$rd),
+              (ins freg:$rs1, freg:$rs2), opcodestr, "$rd, $rs1, $rs2">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPALUDINX_rr_frm<bits<7> funct7, string opcodestr, RegisterOperand freg>
+    : RVInstRFrm<funct7, OPC_OP_FP, (outs freg:$rd),
+                (ins freg:$rs1, freg:$rs2, frmarg:$funct3), opcodestr,
+                 "$rd, $rs1, $rs2, $funct3">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPCmpDINX_rr<bits<3> funct3, string opcodestr, RegisterOperand freg>
+    : RVInstR<0b1010001, funct3, OPC_OP_FP, (outs GPROp:$rd),
+              (ins freg:$rs1, freg:$rs2), opcodestr, "$rd, $rs1, $rs2">,
+      Sched<[WriteFCmp64, ReadFCmp64, ReadFCmp64]>;
+} // DecoderNamespace = "RVZfinx"
+
+class FPUnaryOpINXDynFrmAlias<FPUnaryOpINX_r_frm Inst, string OpcodeStr,
+                           RegisterOperand rdty, RegisterOperand rs1ty>
+    : InstAlias<OpcodeStr#" $rd, $rs1",
+                (Inst rdty:$rd, rs1ty:$rs1, 0b111)>;
+
+class FPFMAHINXDynFrmAlias<FPFMAHINX_rrr_frm Inst, string OpcodeStr>
+    : InstAlias<OpcodeStr#" $rd, $rs1, $rs2, $rs3",
+                (Inst GPRHOp:$rd, GPRHOp:$rs1, GPRHOp:$rs2, GPRHOp:$rs3, 0b111)>;
+
+class FPALUHINXDynFrmAlias<FPALUHINX_rr_frm Inst, string OpcodeStr>
+    : InstAlias<OpcodeStr#" $rd, $rs1, $rs2",
+                (Inst GPRHOp:$rd, GPRHOp:$rs1, GPRHOp:$rs2, 0b111)>;
+
+class FPFMASINXDynFrmAlias<FPFMASINX_rrr_frm Inst, string OpcodeStr>
+    : InstAlias<OpcodeStr#" $rd, $rs1, $rs2, $rs3",
+                (Inst GPRFOp:$rd, GPRFOp:$rs1, GPRFOp:$rs2, GPRFOp:$rs3, 0b111)>;
+
+class FPALUSINXDynFrmAlias<FPALUSINX_rr_frm Inst, string OpcodeStr>
+    : InstAlias<OpcodeStr#" $rd, $rs1, $rs2",
+                (Inst GPRFOp:$rd, GPRFOp:$rs1, GPRFOp:$rs2, 0b111)>;
+
+class FPFMADINXDynFrmAlias<FPFMADINX_rrr_frm Inst, string OpcodeStr, RegisterOperand freg>
+    : InstAlias<OpcodeStr#" $rd, $rs1, $rs2, $rs3",
+                (Inst freg:$rd, freg:$rs1, freg:$rs2, freg:$rs3, 0b111)>;
+
+class FPALUDINXDynFrmAlias<FPALUDINX_rr_frm Inst, string OpcodeStr, RegisterOperand freg>
+    : InstAlias<OpcodeStr#" $rd, $rs1, $rs2",
+                (Inst freg:$rd, freg:$rs1, freg:$rs2, 0b111)>;
+
+//===----------------------------------------------------------------------===//
+// Instructions
+//===----------------------------------------------------------------------===//
+
+// instructions in zfh extension
+let Predicates = [HasStdExtZfhinx] in {
+def FMADD_H_INX  : FPFMAHINX_rrr_frm<OPC_MADD, "fmadd.h">, Sched<[]>;
+def           : FPFMAHINXDynFrmAlias<FMADD_H_INX, "fmadd.h">;
+def FMSUB_H_INX  : FPFMAHINX_rrr_frm<OPC_MSUB, "fmsub.h">, Sched<[]>;
+def           : FPFMAHINXDynFrmAlias<FMSUB_H_INX, "fmsub.h">;
+def FNMSUB_H_INX : FPFMAHINX_rrr_frm<OPC_NMSUB, "fnmsub.h">, Sched<[]>;
+def           : FPFMAHINXDynFrmAlias<FNMSUB_H_INX, "fnmsub.h">;
+def FNMADD_H_INX : FPFMAHINX_rrr_frm<OPC_NMADD, "fnmadd.h">, Sched<[]>;
+def           : FPFMAHINXDynFrmAlias<FNMADD_H_INX, "fnmadd.h">;
+
+def FADD_H_INX   : FPALUHINX_rr_frm<0b0000010, "fadd.h">, Sched<[]>;
+def           : FPALUHINXDynFrmAlias<FADD_H_INX, "fadd.h">;
+def FSUB_H_INX   : FPALUHINX_rr_frm<0b0000110, "fsub.h">, Sched<[]>;
+def           : FPALUHINXDynFrmAlias<FSUB_H_INX, "fsub.h">;
+def FMUL_H_INX   : FPALUHINX_rr_frm<0b0001010, "fmul.h">, Sched<[]>;
+def           : FPALUHINXDynFrmAlias<FMUL_H_INX, "fmul.h">;
+def FDIV_H_INX   : FPALUHINX_rr_frm<0b0001110, "fdiv.h">, Sched<[]>;
+def           : FPALUHINXDynFrmAlias<FDIV_H_INX, "fdiv.h">;
+
+def FSQRT_H_INX  : FPUnaryOpINX_r_frm<0b0101110, GPRHOp, GPRHOp, "fsqrt.h">,
+                Sched<[]> {
+  let rs2 = 0b00000;
+}
+def           : FPUnaryOpINXDynFrmAlias<FSQRT_H_INX, "fsqrt.h", GPRHOp, GPRHOp>;
+
+def FSGNJ_H_INX  : FPALUHINX_rr<0b0010010, 0b000, "fsgnj.h">, Sched<[]>;
+def FSGNJN_H_INX : FPALUHINX_rr<0b0010010, 0b001, "fsgnjn.h">, Sched<[]>;
+def FSGNJX_H_INX : FPALUHINX_rr<0b0010010, 0b010, "fsgnjx.h">, Sched<[]>;
+def FMIN_H_INX   : FPALUHINX_rr<0b0010110, 0b000, "fmin.h">, Sched<[]>;
+def FMAX_H_INX   : FPALUHINX_rr<0b0010110, 0b001, "fmax.h">, Sched<[]>;
+
+def FCVT_W_H_INX : FPUnaryOpINX_r_frm<0b1100010, GPROp, GPRHOp, "fcvt.w.h">,
+                Sched<[]> {
+  let rs2 = 0b00000;
+}
+def          : FPUnaryOpINXDynFrmAlias<FCVT_W_H_INX, "fcvt.w.h", GPROp, GPRHOp>;
+
+def FCVT_WU_H_INX : FPUnaryOpINX_r_frm<0b1100010, GPROp, GPRHOp, "fcvt.wu.h">,
+                Sched<[]> {
+  let rs2 = 0b00001;
+}
+def           : FPUnaryOpINXDynFrmAlias<FCVT_WU_H_INX, "fcvt.wu.h", GPROp, GPRHOp>;
+
+def FCVT_H_W_INX : FPUnaryOpINX_r_frm<0b1101010, GPRHOp, GPROp, "fcvt.h.w">,
+               Sched<[]> {
+  let rs2 = 0b00000;
+}
+def          : FPUnaryOpINXDynFrmAlias<FCVT_H_W_INX, "fcvt.h.w", GPRHOp, GPROp>;
+
+def FCVT_H_W_INXU : FPUnaryOpINX_r_frm<0b1101010, GPRHOp, GPROp, "fcvt.h.wu">,
+                Sched<[]> {
+  let rs2 = 0b00001;
+}
+def           : FPUnaryOpINXDynFrmAlias<FCVT_H_W_INXU, "fcvt.h.wu", GPRHOp, GPROp>;
+
+def FCVT_H_S_INX : FPUnaryOpINX_r_frm<0b0100010, GPRHOp, GPRFOp, "fcvt.h.s">,
+               Sched<[]> {
+  let rs2 = 0b00000;
+}
+def          : FPUnaryOpINXDynFrmAlias<FCVT_H_S_INX, "fcvt.h.s", GPRHOp, GPRFOp>;
+
+def FCVT_S_H_INX : FPUnaryOpINX_r<0b0100000, 0b000, GPRFOp, GPRHOp, "fcvt.s.h">,
+               Sched<[]> {
+  let rs2 = 0b00010;
+}
+
+def FMV_X_H_INX : FPUnaryOpINX_r<0b1110010, 0b000, GPROp, GPRHOp, "fmv.x.h">,
+              Sched<[]> {
+  let rs2 = 0b00000;
+}
+
+def FMV_H_X_INX : FPUnaryOpINX_r<0b1111010, 0b000, GPRHOp, GPROp, "fmv.h.x">,
+              Sched<[]> {
+  let rs2 = 0b00000;
+}
+
+def FEQ_H_INX    : FPCmpHINX_rr<0b010, "feq.h">;
+def FLT_H_INX    : FPCmpHINX_rr<0b001, "flt.h">;
+def FLE_H_INX    : FPCmpHINX_rr<0b000, "fle.h">;
+
+def FCLASS_H_INX : FPUnaryOpINX_r<0b1110010, 0b001, GPRHOp, GPRHOp, "fclass.h">,
+                Sched<[]> {
+  let rs2 = 0b00000;
+}
+
+def : InstAlias<"fmv.h $rd, $rs",  (FSGNJ_H_INX  GPRHOp:$rd, GPRHOp:$rs, GPRHOp:$rs)>;
+def : InstAlias<"fabs.h $rd, $rs", (FSGNJX_H_INX GPRHOp:$rd, GPRHOp:$rs, GPRHOp:$rs)>;
+def : InstAlias<"fneg.h $rd, $rs", (FSGNJN_H_INX GPRHOp:$rd, GPRHOp:$rs, GPRHOp:$rs)>;
+
+// fgt.h/fge.h are recognised by the GNU assembler but the canonical
+// flt.h/fle.h forms will always be printed. Therefore, set a zero weight.
+def : InstAlias<"fgt.h $rd, $rs, $rt",
+                (FLT_H_INX GPROp:$rd, GPRHOp:$rt, GPRHOp:$rs), 0>;
+def : InstAlias<"fge.h $rd, $rs, $rt",
+                (FLE_H_INX GPROp:$rd, GPRHOp:$rt, GPRHOp:$rs), 0>;
+} // Predicates = [HasStdExtZfhinx]
+
+// instructions in F extension and rv64
+let Predicates = [HasStdExtZfhinx, IsRV64] in {
+def FCVT_L_H_INX  : FPUnaryOpINX_r_frm<0b1100010, GPROp, GPRHOp, "fcvt.l.h">,
+                Sched<[]> {
+  let rs2 = 0b00010;
+}
+def           : FPUnaryOpINXDynFrmAlias<FCVT_L_H_INX, "fcvt.l.h", GPROp, GPRHOp>;
+
+def FCVT_LU_H_INX  : FPUnaryOpINX_r_frm<0b1100010, GPROp, GPRHOp, "fcvt.lu.h">,
+                 Sched<[]> {
+  let rs2 = 0b00011;
+}
+def            : FPUnaryOpINXDynFrmAlias<FCVT_LU_H_INX, "fcvt.lu.h", GPROp, GPRHOp>;
+
+def FCVT_H_L_INX : FPUnaryOpINX_r_frm<0b1101010, GPRHOp, GPROp, "fcvt.h.l">,
+               Sched<[]> {
+  let rs2 = 0b00010;
+}
+def          : FPUnaryOpINXDynFrmAlias<FCVT_H_L_INX, "fcvt.h.l", GPRHOp, GPROp>;
+
+def ZFCVT_H_LU_INX : FPUnaryOpINX_r_frm<0b1101010, GPRHOp, GPROp, "fcvt.h.lu">,
+                Sched<[]> {
+  let rs2 = 0b00011;
+}
+def           : FPUnaryOpINXDynFrmAlias<ZFCVT_H_LU_INX, "fcvt.h.lu", GPRHOp, GPROp>;
+} // Predicates = [HasStdExtZfhinx, IsRV64]
+
+// instructions that in F extention and D extention
+let Predicates = [HasStdExtZfhinx, HasStdExtZdinx] in {
+def FCVT_H_D_INX : FPUnaryOpINX_r_frm<0b0100010, GPRHOp, GPRDOp, "fcvt.h.d">,
+               Sched<[]> {
+  let rs2 = 0b00001;
+}
+def          : FPUnaryOpINXDynFrmAlias<FCVT_H_D_INX, "fcvt.h.d", GPRHOp, GPRDOp>;
+
+def FCVT_D_H_INX : FPUnaryOpINX_r<0b0100001, 0b000, GPRDOp, GPRHOp, "fcvt.d.h">,
+               Sched<[]> {
+  let rs2 = 0b00010;
+}
+} // Predicates = [HasStdExtZfhinx, HasStdExtZdinx]
+
+// instructions in F extension, no matter rv32 or rv64
+let Predicates = [HasStdExtZfinx] in {
+def FMADD_S_INX  : FPFMASINX_rrr_frm<OPC_MADD, "fmadd.s">,
+        Sched<[WriteFMulAdd32, ReadFMulAdd32, ReadFMulAdd32, ReadFMulAdd32]>;
+def           : FPFMASINXDynFrmAlias<FMADD_S_INX, "fmadd.s">;
+def FMSUB_S_INX  : FPFMASINX_rrr_frm<OPC_MSUB, "fmsub.s">,
+        Sched<[WriteFMulSub32, ReadFMulSub32, ReadFMulSub32, ReadFMulSub32]>;
+def           : FPFMASINXDynFrmAlias<FMSUB_S_INX, "fmsub.s">;
+def FNMSUB_S_INX : FPFMASINX_rrr_frm<OPC_NMSUB, "fnmsub.s">,
+        Sched<[WriteFMulSub32, ReadFMulSub32, ReadFMulSub32, ReadFMulSub32]>;
+def           : FPFMASINXDynFrmAlias<FNMSUB_S_INX, "fnmsub.s">;
+def FNMADD_S_INX : FPFMASINX_rrr_frm<OPC_NMADD, "fnmadd.s">,
+        Sched<[WriteFMulAdd32, ReadFMulAdd32, ReadFMulAdd32, ReadFMulAdd32]>;
+def           : FPFMASINXDynFrmAlias<FNMADD_S_INX, "fnmadd.s">;
+
+def FADD_S_INX   : FPALUSINX_rr_frm<0b0000000, "fadd.s">,
+                Sched<[WriteFALU32, ReadFALU32, ReadFALU32]>;
+def           : FPALUSINXDynFrmAlias<FADD_S_INX, "fadd.s">;
+def FSUB_S_INX   : FPALUSINX_rr_frm<0b0000100, "fsub.s">,
+                Sched<[WriteFALU32, ReadFALU32, ReadFALU32]>;
+def           : FPALUSINXDynFrmAlias<FSUB_S_INX, "fsub.s">;
+def FMUL_S_INX   : FPALUSINX_rr_frm<0b0001000, "fmul.s">,
+                Sched<[WriteFMul32, ReadFMul32, ReadFMul32]>;
+def           : FPALUSINXDynFrmAlias<FMUL_S_INX, "fmul.s">;
+def FDIV_S_INX   : FPALUSINX_rr_frm<0b0001100, "fdiv.s">,
+                Sched<[WriteFDiv32, ReadFDiv32, ReadFDiv32]>;
+def           : FPALUSINXDynFrmAlias<FDIV_S_INX, "fdiv.s">;
+
+def FSQRT_S_INX  : FPUnaryOpINX_r_frm<0b0101100, GPRFOp, GPRFOp, "fsqrt.s">,
+                Sched<[]> {
+  let rs2 = 0b00000;
+}
+def           : FPUnaryOpINXDynFrmAlias<FSQRT_S_INX, "fsqrt.s", GPRFOp, GPRFOp>;
+
+def FSGNJ_S_INX  : FPALUSINX_rr<0b0010000, 0b000, "fsgnj.s">,
+                Sched<[WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32]>;
+def FSGNJN_S_INX : FPALUSINX_rr<0b0010000, 0b001, "fsgnjn.s">,
+                Sched<[WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32]>;
+def FSGNJX_S_INX : FPALUSINX_rr<0b0010000, 0b010, "fsgnjx.s">,
+                Sched<[WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32]>;
+def FMIN_S_INX   : FPALUSINX_rr<0b0010100, 0b000, "fmin.s">,
+                Sched<[WriteFMinMax32, ReadFMinMax32, ReadFMinMax32]>;
+def FMAX_S_INX   : FPALUSINX_rr<0b0010100, 0b001, "fmax.s">,
+                Sched<[WriteFMinMax32, ReadFMinMax32, ReadFMinMax32]>;
+
+def FCVT_W_S_INX : FPUnaryOpINX_r_frm<0b1100000, GPROp, GPRFOp, "fcvt.w.s">,
+               Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]> {
+  let rs2 = 0b00000;
+}
+def        : FPUnaryOpINXDynFrmAlias<FCVT_W_S_INX, "fcvt.w.s", GPROp, GPRFOp>;
+
+def FCVT_WU_S_INX : FPUnaryOpINX_r_frm<0b1100000, GPROp, GPRFOp, "fcvt.wu.s">,
+                Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]> {
+  let rs2 = 0b00001;
+}
+def        : FPUnaryOpINXDynFrmAlias<FCVT_WU_S_INX, "fcvt.wu.s", GPROp, GPRFOp>;
+
+def FMV_X_W_INX : FPUnaryOpINX_r<0b1110000, 0b000, GPROp, GPRFOp, "fmv.x.w">,
+              Sched<[WriteFMovF32ToI32, ReadFMovF32ToI32]> {
+  let rs2 = 0b00000;
+}
+
+def FEQ_S_INX    : FPCmpSINX_rr<0b010, "feq.s">;
+def FLT_S_INX    : FPCmpSINX_rr<0b001, "flt.s">;
+def FLE_S_INX    : FPCmpSINX_rr<0b000, "fle.s">;
+
+def FCLASS_S_INX : FPUnaryOpINX_r<0b1110000, 0b001, GPRFOp, GPRFOp, "fclass.s">,
+                Sched<[WriteFClass32, ReadFClass32]> {
+  let rs2 = 0b00000;
+}
+
+def FCVT_S_W_INX : FPUnaryOpINX_r_frm<0b1101000, GPRFOp, GPROp, "fcvt.s.w">,
+               Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]> {
+  let rs2 = 0b00000;
+}
+def          : FPUnaryOpINXDynFrmAlias<FCVT_S_W_INX, "fcvt.s.w", GPRFOp, GPROp>;
+
+def ZFCVT_S_WU_INX : FPUnaryOpINX_r_frm<0b1101000, GPRFOp, GPROp, "fcvt.s.wu">,
+                Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]> {
+  let rs2 = 0b00001;
+}
+def           : FPUnaryOpINXDynFrmAlias<ZFCVT_S_WU_INX, "fcvt.s.wu", GPRFOp, GPROp>;
+
+def FMV_W_X_INX : FPUnaryOpINX_r<0b1111000, 0b000, GPRFOp, GPROp, "fmv.w.x">,
+              Sched<[WriteFMovI32ToF32, ReadFMovI32ToF32]> {
+  let rs2 = 0b00000;
+}
+
+def : InstAlias<"fabs.s $rd, $rs", (FSGNJX_S_INX GPRFOp:$rd, GPRFOp:$rs, GPRFOp:$rs)>;
+def : InstAlias<"fneg.s $rd, $rs", (FSGNJN_S_INX GPRFOp:$rd, GPRFOp:$rs, GPRFOp:$rs)>;
+
+// fgt.s/fge.s are recognised by the GNU assembler but the canonical
+// flt.s/fle.s forms will always be printed. Therefore, set a zero weight.
+def : InstAlias<"fgt.s $rd, $rs, $rt",
+                (FLT_S_INX GPROp:$rd, GPRFOp:$rt, GPRFOp:$rs), 0>;
+def : InstAlias<"fge.s $rd, $rs, $rt",
+                (FLE_S_INX GPROp:$rd, GPRFOp:$rt, GPRFOp:$rs), 0>;
+} // Predicates = [HasStdExtZfinx]
+
+// instructions that in F extention and rv64
+let Predicates = [HasStdExtZfinx, IsRV64] in {
+def FCVT_L_S_INX  : FPUnaryOpINX_r_frm<0b1100000, GPROp, GPRFOp, "fcvt.l.s">,
+                Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]> {
+  let rs2 = 0b00010;
+}
+def           : FPUnaryOpINXDynFrmAlias<FCVT_L_S_INX, "fcvt.l.s", GPROp, GPRFOp>;
+
+def FCVT_LU_S_INX  : FPUnaryOpINX_r_frm<0b1100000, GPROp, GPRFOp, "fcvt.lu.s">,
+                 Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]> {
+  let rs2 = 0b00011;
+}
+def          : FPUnaryOpINXDynFrmAlias<FCVT_LU_S_INX, "fcvt.lu.s", GPROp, GPRFOp>;
+
+def FCVT_S_L_INX : FPUnaryOpINX_r_frm<0b1101000, GPRFOp, GPROp, "fcvt.s.l">,
+               Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]> {
+  let rs2 = 0b00010;
+}
+def          : FPUnaryOpINXDynFrmAlias<FCVT_S_L_INX, "fcvt.s.l", GPRFOp, GPROp>;
+
+def ZFCVT_S_LU_INX : FPUnaryOpINX_r_frm<0b1101000, GPRFOp, GPROp, "fcvt.s.lu">,
+                Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]> {
+  let rs2 = 0b00011;
+}
+def           : FPUnaryOpINXDynFrmAlias<ZFCVT_S_LU_INX, "fcvt.s.lu", GPRFOp, GPROp>;
+} // Predicates = [HasStdExtZfinx, IsRV64]
+
+// instructions that in D extention and rv64
+let Predicates = [HasStdExtZdinx, IsRV64] in {
+def FMADD_D_INX  : FPFMADINX_rrr_frm<OPC_MADD, "fmadd.d", GPRDOp>,
+                Sched<[WriteFMulAdd64, ReadFMulAdd64, ReadFMulAdd64, ReadFMulAdd64]>;
+def           : FPFMADINXDynFrmAlias<FMADD_D_INX, "fmadd.d", GPRDOp>;
+def FMSUB_D_INX  : FPFMADINX_rrr_frm<OPC_MSUB, "fmsub.d", GPRDOp>,
+                Sched<[WriteFMulSub64, ReadFMulSub64, ReadFMulSub64, ReadFMulSub64]>;
+def           : FPFMADINXDynFrmAlias<FMSUB_D_INX, "fmsub.d", GPRDOp>;
+def FNMSUB_D_INX : FPFMADINX_rrr_frm<OPC_NMSUB, "fnmsub.d", GPRDOp>,
+                Sched<[WriteFMulSub64, ReadFMulSub64, ReadFMulSub64, ReadFMulSub64]>;
+def           : FPFMADINXDynFrmAlias<FNMSUB_D_INX, "fnmsub.d", GPRDOp>;
+def FNMADD_D_INX : FPFMADINX_rrr_frm<OPC_NMADD, "fnmadd.d", GPRDOp>,
+                Sched<[WriteFMulAdd64, ReadFMulAdd64, ReadFMulAdd64, ReadFMulAdd64]>;
+def           : FPFMADINXDynFrmAlias<FNMADD_D_INX, "fnmadd.d", GPRDOp>;
+
+def FADD_D_INX : FPALUDINX_rr_frm<0b0000001, "fadd.d", GPRDOp>,
+             Sched<[WriteFALU64, ReadFALU64, ReadFALU64]>;
+def        : FPALUDINXDynFrmAlias<FADD_D_INX, "fadd.d", GPRDOp>;
+def FSUB_D_INX : FPALUDINX_rr_frm<0b0000101, "fsub.d", GPRDOp>,
+             Sched<[WriteFALU64, ReadFALU64, ReadFALU64]>;
+def        : FPALUDINXDynFrmAlias<FSUB_D_INX, "fsub.d", GPRDOp>;
+def FMUL_D_INX : FPALUDINX_rr_frm<0b0001001, "fmul.d", GPRDOp>,
+             Sched<[WriteFMul64, ReadFMul64, ReadFMul64]>;
+def        : FPALUDINXDynFrmAlias<FMUL_D_INX, "fmul.d", GPRDOp>;
+def FDIV_D_INX : FPALUDINX_rr_frm<0b0001101, "fdiv.d", GPRDOp>,
+             Sched<[WriteFDiv64, ReadFDiv64, ReadFDiv64]>;
+def        : FPALUDINXDynFrmAlias<FDIV_D_INX, "fdiv.d", GPRDOp>;
+
+def FSQRT_D_INX : FPUnaryOpINX_r_frm<0b0101101, GPRDOp, GPRDOp, "fsqrt.d">,
+              Sched<[WriteFSqrt64, ReadFSqrt64]> {
+  let rs2 = 0b00000;
+}
+def         : FPUnaryOpINXDynFrmAlias<FSQRT_D_INX, "fsqrt.d", GPRDOp, GPRDOp>;
+
+def FSGNJ_D_INX  : FPALUDINX_rr<0b0010001, 0b000, "fsgnj.d", GPRDOp>,
+               Sched<[WriteFSGNJ64, ReadFSGNJ64, ReadFSGNJ64]>;
+def FSGNJN_D_INX : FPALUDINX_rr<0b0010001, 0b001, "fsgnjn.d", GPRDOp>,
+               Sched<[WriteFSGNJ64, ReadFSGNJ64, ReadFSGNJ64]>;
+def FSGNJX_D_INX : FPALUDINX_rr<0b0010001, 0b010, "fsgnjx.d", GPRDOp>,
+               Sched<[WriteFSGNJ64, ReadFSGNJ64, ReadFSGNJ64]>;
+def FMIN_D_INX   : FPALUDINX_rr<0b0010101, 0b000, "fmin.d", GPRDOp>,
+               Sched<[WriteFMinMax64, ReadFMinMax64, ReadFMinMax64]>;
+def FMAX_D_INX   : FPALUDINX_rr<0b0010101, 0b001, "fmax.d", GPRDOp>,
+               Sched<[WriteFMinMax64, ReadFMinMax64, ReadFMinMax64]>;
+
+def FCVT_S_D_INX : FPUnaryOpINX_r_frm<0b0100000, GPRFOp, GPRDOp, "fcvt.s.d">,
+               Sched<[WriteFCvtF64ToF32, ReadFCvtF64ToF32]> {
+  let rs2 = 0b00001;
+}
+def          : FPUnaryOpINXDynFrmAlias<FCVT_S_D_INX, "fcvt.s.d", GPRFOp, GPRDOp>;
+
+def FCVT_D_S_INX : FPUnaryOpINX_r<0b0100001, 0b000, GPRDOp, GPRFOp, "fcvt.d.s">,
+               Sched<[WriteFCvtF32ToF64, ReadFCvtF32ToF64]> {
+  let rs2 = 0b00000;
+}
+
+def FEQ_D_INX : FPCmpDINX_rr<0b010, "feq.d", GPRDOp>;
+def FLT_D_INX : FPCmpDINX_rr<0b001, "flt.d", GPRDOp>;
+def FLE_D_INX : FPCmpDINX_rr<0b000, "fle.d", GPRDOp>;
+
+def FCLASS_D_INX : FPUnaryOpINX_r<0b1110001, 0b001, GPROp, GPRDOp, "fclass.d">,
+               Sched<[WriteFClass64, ReadFClass64]> {
+  let rs2 = 0b00000;
+}
+
+def FCVT_W_D_INX : FPUnaryOpINX_r_frm<0b1100001, GPROp, GPRDOp, "fcvt.w.d">,
+               Sched<[WriteFCvtF64ToI32, ReadFCvtF64ToI32]> {
+  let rs2 = 0b00000;
+}
+def          : FPUnaryOpINXDynFrmAlias<FCVT_W_D_INX, "fcvt.w.d", GPROp, GPRDOp>;
+
+def FCVT_WU_D_INX : FPUnaryOpINX_r_frm<0b1100001, GPROp, GPRDOp, "fcvt.wu.d">,
+                Sched<[WriteFCvtF64ToI32, ReadFCvtF64ToI32]> {
+  let rs2 = 0b00001;
+}
+def           : FPUnaryOpINXDynFrmAlias<FCVT_WU_D_INX, "fcvt.wu.d", GPROp, GPRDOp>;
+
+def FCVT_D_W_INX : FPUnaryOpINX_r<0b1101001, 0b000, GPRDOp, GPROp, "fcvt.d.w">,
+               Sched<[WriteFCvtI32ToF64, ReadFCvtI32ToF64]> {
+  let rs2 = 0b00000;
+}
+
+def ZFCVT_D_WU_INX : FPUnaryOpINX_r<0b1101001, 0b000, GPRDOp, GPROp, "fcvt.d.wu">,
+                Sched<[WriteFCvtI32ToF64, ReadFCvtI32ToF64]> {
+  let rs2 = 0b00001;
+}
+
+def FCVT_L_D_INX  : FPUnaryOpINX_r_frm<0b1100001, GPROp, GPRDOp, "fcvt.l.d">,
+               Sched<[WriteFCvtF64ToI64, ReadFCvtF64ToI64]> {
+  let rs2 = 0b00010;
+}
+def            : FPUnaryOpINXDynFrmAlias<FCVT_L_D_INX, "fcvt.l.d", GPROp, GPRDOp>;
+
+def FCVT_LU_D_INX : FPUnaryOpINX_r_frm<0b1100001, GPROp, GPRDOp, "fcvt.lu.d">,
+                Sched<[WriteFCvtF64ToI64, ReadFCvtF64ToI64]> {
+  let rs2 = 0b00011;
+}
+def            : FPUnaryOpINXDynFrmAlias<FCVT_LU_D_INX, "fcvt.lu.d", GPROp, GPRDOp>;
+
+def FMV_X_D_INX   : FPUnaryOpINX_r<0b1110001, 0b000, GPROp, GPRDOp, "fmv.x.d">,
+              Sched<[WriteFMovF64ToI64, ReadFMovF64ToI64]> {
+  let rs2 = 0b00000;
+}
+
+def FCVT_D_L_INX  : FPUnaryOpINX_r_frm<0b1101001, GPRDOp, GPROp, "fcvt.d.l">,
+               Sched<[WriteFCvtI64ToF64, ReadFCvtI64ToF64]> {
+  let rs2 = 0b00010;
+}
+def            : FPUnaryOpINXDynFrmAlias<FCVT_D_L_INX, "fcvt.d.l", GPRDOp, GPROp>;
+
+def FCVT_D_L_INXU : FPUnaryOpINX_r_frm<0b1101001, GPRDOp, GPROp, "fcvt.d.lu">,
+                Sched<[WriteFCvtI64ToF64, ReadFCvtI64ToF64]> {
+  let rs2 = 0b00011;
+}
+def            : FPUnaryOpINXDynFrmAlias<FCVT_D_L_INXU, "fcvt.d.lu", GPRDOp, GPROp>;
+
+def FMV_D_X_INX   : FPUnaryOpINX_r<0b1111001, 0b000, GPRDOp, GPROp, "fmv.d.x">,
+              Sched<[WriteFMovI64ToF64, ReadFMovI64ToF64]> {
+  let rs2 = 0b00000;
+}
+} // Predicates = [HasStdExtZdinx, IsRV64]
+
+// instruction that in D extension and rv32
+let Predicates = [HasStdExtZdinx, IsRV32] in {
+let DecoderNamespace = "RV32DZfinx" in {
+def ZFMADD_IN32X : FPFMADINX_rrr_frm<OPC_MADD, "fmadd.d", GPRPDOp>,
+               Sched<[WriteFMulAdd64, ReadFMulAdd64, ReadFMulAdd64, ReadFMulAdd64]>;
+def ZFMSUB_IN32X : FPFMADINX_rrr_frm<OPC_MSUB, "fmsub.d", GPRPDOp>,
+               Sched<[WriteFMulSub64, ReadFMulSub64, ReadFMulSub64, ReadFMulSub64]>;
+def ZFNMSUB_IN32X : FPFMADINX_rrr_frm<OPC_NMSUB, "fnmsub.d", GPRPDOp>,
+               Sched<[WriteFMulSub64, ReadFMulSub64, ReadFMulSub64, ReadFMulSub64]>;
+def ZFNMADD_IN32X : FPFMADINX_rrr_frm<OPC_NMADD, "fnmadd.d", GPRPDOp>,
+               Sched<[WriteFMulAdd64, ReadFMulAdd64, ReadFMulAdd64, ReadFMulAdd64]>;
+
+def ZFADD_IN32X : FPALUDINX_rr_frm<0b0000001, "fadd.d", GPRPDOp>,
+             Sched<[WriteFALU64, ReadFALU64, ReadFALU64]>;
+def ZFSUB_IN32X : FPALUDINX_rr_frm<0b0000101, "fsub.d", GPRPDOp>,
+             Sched<[WriteFALU64, ReadFALU64, ReadFALU64]>;
+def ZFMUL_IN32X : FPALUDINX_rr_frm<0b0001001, "fmul.d", GPRPDOp>,
+             Sched<[WriteFMul64, ReadFMul64, ReadFMul64]>;
+def ZFDIV_IN32X : FPALUDINX_rr_frm<0b0001101, "fdiv.d", GPRPDOp>,
+             Sched<[WriteFDiv64, ReadFDiv64, ReadFDiv64]>;
+
+def ZFSQRT_IN32X : FPUnaryOpINX_r_frm<0b0101101, GPRPDOp, GPRPDOp, "fsqrt.d">,
+              Sched<[WriteFSqrt64, ReadFSqrt64]> {
+  let rs2 = 0b00000;
+}
+
+def ZFSGNJ_IN32X  : FPALUDINX_rr<0b0010001, 0b000, "fsgnj.d", GPRPDOp>,
+               Sched<[WriteFSGNJ64, ReadFSGNJ64, ReadFSGNJ64]>;
+def ZFSGNJN_IN32X : FPALUDINX_rr<0b0010001, 0b001, "fsgnjn.d", GPRPDOp>,
+               Sched<[WriteFSGNJ64, ReadFSGNJ64, ReadFSGNJ64]>;
+def ZFSGNJX_IN32X : FPALUDINX_rr<0b0010001, 0b010, "fsgnjx.d", GPRPDOp>,
+               Sched<[WriteFSGNJ64, ReadFSGNJ64, ReadFSGNJ64]>;
+def ZFMIN_IN32X   : FPALUDINX_rr<0b0010101, 0b000, "fmin.d", GPRPDOp>,
+               Sched<[WriteFMinMax64, ReadFMinMax64, ReadFMinMax64]>;
+def ZFMAX_IN32X   : FPALUDINX_rr<0b0010101, 0b001, "fmax.d", GPRPDOp>,
+               Sched<[WriteFMinMax64, ReadFMinMax64, ReadFMinMax64]>;
+
+def ZFCVT_S_IN32X : FPUnaryOpINX_r_frm<0b0100000, GPRFOp, GPRPDOp, "fcvt.s.d">,
+               Sched<[WriteFCvtF64ToF32, ReadFCvtF64ToF32]> {
+  let rs2 = 0b00001;
+}
+
+def ZFCVT_D_S32 : FPUnaryOpINX_r<0b0100001, 0b000, GPRPDOp, GPRFOp, "fcvt.d.s">,
+               Sched<[WriteFCvtF32ToF64, ReadFCvtF32ToF64]> {
+  let rs2 = 0b00000;
+}
+
+def ZFEQ_IN32X : FPCmpDINX_rr<0b010, "feq.d", GPRPDOp>;
+def ZFLT_IN32X : FPCmpDINX_rr<0b001, "flt.d", GPRPDOp>;
+def ZFLE_IN32X : FPCmpDINX_rr<0b000, "fle.d", GPRPDOp>;
+
+def ZFCLASS_IN32X : FPUnaryOpINX_r<0b1110001, 0b001, GPROp, GPRPDOp, "fclass.d">,
+               Sched<[WriteFClass64, ReadFClass64]> {
+  let rs2 = 0b00000;
+}
+
+def ZFCVT_W_IN32X : FPUnaryOpINX_r_frm<0b1100001, GPROp, GPRPDOp, "fcvt.w.d">,
+               Sched<[WriteFCvtF64ToI32, ReadFCvtF64ToI32]> {
+  let rs2 = 0b00000;
+}
+
+def ZFCVT_WU_IN32X : FPUnaryOpINX_r_frm<0b1100001, GPROp, GPRPDOp, "fcvt.wu.d">,
+                Sched<[WriteFCvtF64ToI32, ReadFCvtF64ToI32]> {
+  let rs2 = 0b00001;
+}
+
+def ZFCVT_D_W32 : FPUnaryOpINX_r<0b1101001, 0b000, GPRPDOp, GPROp, "fcvt.d.w">,
+               Sched<[WriteFCvtI32ToF64, ReadFCvtI32ToF64]> {
+  let rs2 = 0b00000;
+}
+
+def ZFCVT_D_WU32 : FPUnaryOpINX_r<0b1101001, 0b000, GPRPDOp, GPROp, "fcvt.d.wu">,
+                Sched<[WriteFCvtI32ToF64, ReadFCvtI32ToF64]> {
+  let rs2 = 0b00001;
+}
+} // DecoderNamespace = "RV32DZfinx"
+def        : FPFMADINXDynFrmAlias<ZFMADD_IN32X, "fmadd.d", GPRPDOp>;
+def        : FPFMADINXDynFrmAlias<ZFMSUB_IN32X, "fmsub.d", GPRPDOp>;
+def        : FPFMADINXDynFrmAlias<ZFNMSUB_IN32X, "fnmsub.d", GPRPDOp>;
+def        : FPALUDINXDynFrmAlias<ZFADD_IN32X, "fadd.d", GPRPDOp>;
+def        : FPFMADINXDynFrmAlias<ZFNMADD_IN32X, "fnmadd.d", GPRPDOp>;
+def        : FPALUDINXDynFrmAlias<ZFSUB_IN32X, "fsub.d", GPRPDOp>;
+def        : FPALUDINXDynFrmAlias<ZFMUL_IN32X, "fmul.d", GPRPDOp>;
+def        : FPALUDINXDynFrmAlias<ZFDIV_IN32X, "fdiv.d", GPRPDOp>;
+def        : FPUnaryOpINXDynFrmAlias<ZFCVT_W_IN32X, "fcvt.w.d", GPROp, GPRPDOp>;
+def        : FPUnaryOpINXDynFrmAlias<ZFSQRT_IN32X, "fsqrt.d", GPRPDOp, GPRPDOp>;
+def        : FPUnaryOpINXDynFrmAlias<ZFCVT_S_IN32X, "fcvt.s.d", GPRFOp, GPRPDOp>;
+def        : FPUnaryOpINXDynFrmAlias<ZFCVT_WU_IN32X, "fcvt.wu.d", GPROp, GPRPDOp>;
+
+} // Predicates = [HasStdExtD, HasStdExtZfinx, IsRV32]
Index: llvm/lib/Target/RISCV/RISCVInstrInfo.td
===================================================================
--- llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -1224,3 +1224,4 @@
 include "RISCVInstrInfoB.td"
 include "RISCVInstrInfoV.td"
 include "RISCVInstrInfoZfh.td"
+include "RISCVInstrInfoZfinx.td"
Index: llvm/lib/Target/RISCV/RISCV.td
===================================================================
--- llvm/lib/Target/RISCV/RISCV.td
+++ llvm/lib/Target/RISCV/RISCV.td
@@ -49,6 +49,27 @@
                              AssemblerPredicate<(all_of FeatureExtZfh),
                              "'Zfh' (Half-Precision Floating-Point)">;
 
+def FeatureExtZfinx
+    : SubtargetFeature<"experimental-zfinx", "HasStdExtZfinx", "true",
+                       "'Zfinx' (Float in Integer)">;
+def HasStdExtZfinx : Predicate<"Subtarget->hasStdExtZfinx()">,
+                             AssemblerPredicate<(all_of FeatureExtZfinx),
+                             "'Zfinx' (Float in Integer)">;
+
+def FeatureExtZdinx
+    : SubtargetFeature<"experimental-zdinx", "HasStdExtZdinx", "true",
+                       "'Zdinx' (Double in Integer)">;
+def HasStdExtZdinx : Predicate<"Subtarget->hasStdExtZdinx()">,
+                             AssemblerPredicate<(all_of FeatureExtZdinx),
+                             "'Zdinx' (Double in Integer)">;
+
+def FeatureExtZfhinx
+    : SubtargetFeature<"experimental-zfhinx", "HasStdExtZfhinx", "true",
+                       "'Zfhinx' (Half float in Integer)">;
+def HasStdExtZfhinx : Predicate<"Subtarget->hasStdExtZfhinx()">,
+                             AssemblerPredicate<(all_of FeatureExtZfhinx),
+                             "'Zfhinx' (Half float in Integer)">;
+
 def FeatureStdExtC
     : SubtargetFeature<"c", "HasStdExtC", "true",
                        "'C' (Compressed Instructions)">;
Index: llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
===================================================================
--- llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -161,6 +161,36 @@
   return MCDisassembler::Success;
 }
 
+static DecodeStatus DecodeGPRHRegisterClass(MCInst &Inst, uint64_t RegNo,
+                                            uint64_t Address,
+                                            const void *Decoder) {
+  return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
+}
+
+static DecodeStatus DecodeGPRFRegisterClass(MCInst &Inst, uint64_t RegNo,
+                                            uint64_t Address,
+                                            const void *Decoder) {
+  return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
+}
+
+static DecodeStatus DecodeGPRDRegisterClass(MCInst &Inst, uint64_t RegNo,
+                                            uint64_t Address,
+                                            const void *Decoder) {
+  return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
+}
+
+static DecodeStatus DecodeGPRPDRegisterClass(MCInst &Inst, uint64_t RegNo,
+                                             uint64_t Address,
+                                             const void *Decoder) {
+  if (RegNo >= 32 || RegNo & 1) {
+    return MCDisassembler::Fail;
+  }
+
+  MCRegister Reg = RISCV::X0 + RegNo;
+  Inst.addOperand(MCOperand::createReg(Reg));
+  return MCDisassembler::Success;
+}
+
 static DecodeStatus DecodeVRRegisterClass(MCInst &Inst, uint64_t RegNo,
                                           uint64_t Address,
                                           const void *Decoder) {
@@ -367,6 +397,33 @@
       return MCDisassembler::Fail;
     }
     Insn = support::endian::read32le(Bytes.data());
+
+    if (STI.getFeatureBits()[RISCV::FeatureExtZdinx] &&
+        !STI.getFeatureBits()[RISCV::Feature64Bit]) {
+      LLVM_DEBUG(dbgs() << "Trying RV32DZfinx table (Double in Integer and"
+                                                                  "rv32)\n");
+      Result = decodeInstruction(DecoderTableRV32DZfinx32, MI, Insn, Address,
+                                   this, STI);
+      if (Result != MCDisassembler::Fail) {
+        Size = 4;
+        return Result;
+      }
+    }
+
+    if (STI.getFeatureBits()[RISCV::FeatureExtZfinx] ||
+        STI.getFeatureBits()[RISCV::FeatureExtZfhinx] ||
+        (STI.getFeatureBits()[RISCV::FeatureExtZdinx] &&
+         STI.getFeatureBits()[RISCV::Feature64Bit])) {
+      LLVM_DEBUG(dbgs() << "Trying RVZfinx table (Float in Integer):\n");
+      // Calling the auto-generated decoder function.
+      Result = decodeInstruction(DecoderTableRVZfinx32, MI, Insn, Address, this,
+                                 STI);
+      if (Result != MCDisassembler::Fail) {
+        Size = 4;
+        return Result;
+      }
+    }
+
     LLVM_DEBUG(dbgs() << "Trying RISCV32 table :\n");
     Result = decodeInstruction(DecoderTable32, MI, Insn, Address, this, STI);
     Size = 4;
Index: llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
===================================================================
--- llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -162,6 +162,7 @@
   OperandMatchResultTy parseJALOffset(OperandVector &Operands);
   OperandMatchResultTy parseVTypeI(OperandVector &Operands);
   OperandMatchResultTy parseMaskReg(OperandVector &Operands);
+  OperandMatchResultTy parseGPRasFPR(OperandVector &Operands);
 
   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
 
@@ -264,6 +265,8 @@
 
   bool IsRV64;
 
+  bool IsGPRasFPR;
+
   struct RegOp {
     MCRegister RegNum;
   };
@@ -335,6 +338,13 @@
            RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum);
   }
 
+  bool isGPRasFPR() const { return isGPR() && IsGPRasFPR; }
+
+  bool isGPRPDasFPR() const { return isGPR() && IsGPRasFPR && !IsRV64
+                                      &&!((Reg.RegNum - RISCV::X0) & 1);}
+
+  bool isGPRDasFPR() const { return isGPR() && IsGPRasFPR && IsRV64; }
+
   static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
                                   RISCVMCExpr::VariantKind &VK) {
     if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
@@ -777,12 +787,14 @@
   }
 
   static std::unique_ptr<RISCVOperand> createReg(unsigned RegNo, SMLoc S,
-                                                 SMLoc E, bool IsRV64) {
+                                                 SMLoc E, bool IsRV64,
+                                                 bool IsGPRasFPR = false) {
     auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
     Op->Reg.RegNum = RegNo;
     Op->StartLoc = S;
     Op->EndLoc = E;
     Op->IsRV64 = IsRV64;
+    Op->IsGPRasFPR = IsGPRasFPR;
     return Op;
   }
 
@@ -834,6 +846,21 @@
     Inst.addOperand(MCOperand::createReg(getReg()));
   }
 
+  void addGPRasFPROperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    Inst.addOperand(MCOperand::createReg(getReg()));
+  }
+
+  void addGPRPDasFPROperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands");
+    Inst.addOperand(MCOperand::createReg(getReg()));
+  }
+
+  void addGPRDasFPROperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands");
+    Inst.addOperand(MCOperand::createReg(getReg()));
+  }
+
   void addImmOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     addExpr(Inst, getImm());
@@ -912,6 +939,12 @@
   return Reg - RISCV::F0_D + RISCV::F0_F;
 }
 
+static MCRegister convertGPRToGPRPD(MCRegister Reg) {
+  assert(Reg >= RISCV::X0 && Reg <= RISCV::X31 && !((Reg - RISCV::X0) & 1) &&
+         "Invalid register");
+  return (Reg - RISCV::X0) / 2 + RISCV::X0_PD;
+}
+
 unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
                                                     unsigned Kind) {
   RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
@@ -923,6 +956,7 @@
       RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg);
   bool IsRegFPR64C =
       RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg);
+  bool IsRegGPR = RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg);
 
   // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
   // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.
@@ -937,6 +971,16 @@
     Op.Reg.RegNum = convertFPR64ToFPR16(Reg);
     return Match_Success;
   }
+
+  // As the parser couldn't differentiate an GPRH, GPRF, GPRD, GPRPD from an
+  // GPR, coerce the register from GPR to these if necessary.
+  if (IsRegGPR && Kind == MCK_GPRPD && !isRV64()) {
+    if ((Reg - RISCV::X0) & 1)
+      return Match_InvalidOperand;
+    Op.Reg.RegNum = convertGPRToGPRPD(Reg);
+    return Match_Success;
+  }
+
   return Match_InvalidOperand;
 }
 
@@ -1616,6 +1660,29 @@
   return MatchOperand_Success;
 }
 
+OperandMatchResultTy RISCVAsmParser::parseGPRasFPR(OperandVector &Operands) {
+  switch (getLexer().getKind()) {
+  default:
+    return MatchOperand_NoMatch;
+  case AsmToken::Identifier:
+    StringRef Name = getLexer().getTok().getIdentifier();
+    MCRegister RegNo;
+    matchRegisterNameHelper(isRV32E(), RegNo, Name);
+
+    if (RegNo == RISCV::NoRegister)
+      return MatchOperand_NoMatch;
+    SMLoc S = getLoc();
+    SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
+    getLexer().Lex();
+    Operands.push_back(RISCVOperand::createReg(
+        RegNo, S, E, isRV64(),
+        !getSTI().hasFeature(RISCV::FeatureStdExtF) &&
+            !getSTI().hasFeature(RISCV::FeatureStdExtD) &&
+            !getSTI().hasFeature(RISCV::FeatureExtZfh)));
+  }
+  return MatchOperand_Success;
+}
+
 OperandMatchResultTy
 RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
   if (getLexer().isNot(AsmToken::LParen)) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to