[binutils-gdb] RISC-V: check operands for Zdinx in RV32
Jan Beulich via Binutils-cvs <[email protected]> Fri, 31 Jul 2026 09:54:10 +0000 (GMT)
| Newsgroups | gmane.comp.gnu.binutils.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D0aa268acc975= 28c98434c787ab479f89fef12c10 commit 0aa268acc97528c98434c787ab479f89fef12c10 Author: Jan Beulich <[email protected]> Date: Fri Jul 31 11:51:12 2026 +0200 RISC-V: check operands for Zdinx in RV32 =20 Like for Zilsd, register pair operands are required to be encoded with = the low bit clear. Since match functions don't have XLEN available, introdu= ce respective flags, to be used explicitly in assembler and disassembler. Diff: --- gas/config/tc-riscv.c | 34 ++++++++++++---- gas/testsuite/gas/riscv/zdinx-rv32-fail.d | 3 ++ gas/testsuite/gas/riscv/zdinx-rv32-fail.l | 47 +++++++++++++++++++++++ gas/testsuite/gas/riscv/zdinx-rv32.d | 52 +++++++++++++++++++++++++ gas/testsuite/gas/riscv/zdinx-rv32.s | 52 +++++++++++++++++++++++++ include/opcode/riscv.h | 12 ++++++ opcodes/riscv-dis.c | 17 ++++++++ opcodes/riscv-opc.c | 64 +++++++++++++++------------= ---- 8 files changed, 241 insertions(+), 40 deletions(-) diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index ec35444ccf9..1fa33da6ec3 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -3004,6 +3004,12 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expre= ssionS *imm_expr, *imm_reloc =3D BFD_RELOC_UNUSED; p =3D percent_op_null; =20 +#define RV32_EVEN_CHECK(form, rclass, regno) \ + (!(ip->insn_mo->pinfo & INSN_RV32_EVEN_##form) \ + || xlen !=3D 32 \ + || (rclass) !=3D RCLASS_GPR \ + || !((regno) & 1)) + for (oparg =3D insn->args;; ++oparg) { opargStart =3D oparg; @@ -3011,6 +3017,8 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expres= sionS *imm_expr, ++asarg; switch (*oparg) { + enum reg_class rclass; + case '\0': /* End of args. */ if (insn->match_func && !insn->match_func (insn, ip->insn_opcode)) break; @@ -3670,32 +3678,40 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expr= essionS *imm_expr, case 'T': /* Floating point RS2. */ case 'U': /* Floating point RS1 and RS2. */ case 'R': /* Floating point RS3. */ - if (reg_lookup (&asarg, - (riscv_subset_supports (&riscv_rps_as, "zfinx") - ? RCLASS_GPR : RCLASS_FPR), ®no)) + rclass =3D riscv_subset_supports (&riscv_rps_as, "zfinx") + ? RCLASS_GPR : RCLASS_FPR; + if (reg_lookup (&asarg, rclass, ®no)) { char c =3D *oparg; if (is_whitespace (*asarg)) ++asarg; + switch (c) { case 'D': + if (!RV32_EVEN_CHECK (D, rclass, regno)) + break; INSERT_OPERAND (RD, *ip, regno); - break; + continue; case 'S': + if (!RV32_EVEN_CHECK (S, rclass, regno)) + break; INSERT_OPERAND (RS1, *ip, regno); - break; + continue; case 'U': INSERT_OPERAND (RS1, *ip, regno); /* Fall through. */ case 'T': + if (!RV32_EVEN_CHECK (T, rclass, regno)) + break; INSERT_OPERAND (RS2, *ip, regno); - break; + continue; case 'R': + if (!RV32_EVEN_CHECK (R, rclass, regno)) + break; INSERT_OPERAND (RS3, *ip, regno); - break; + continue; } - continue; } break; =20 @@ -4530,6 +4546,8 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expres= sionS *imm_expr, insn_with_csr =3D false; } =20 +#undef RV32_EVEN_CHECK + out: /* Restore the character we might have clobbered above. */ if (save_c) diff --git a/gas/testsuite/gas/riscv/zdinx-rv32-fail.d b/gas/testsuite/gas/= riscv/zdinx-rv32-fail.d new file mode 100644 index 00000000000..7d7b8d80296 --- /dev/null +++ b/gas/testsuite/gas/riscv/zdinx-rv32-fail.d @@ -0,0 +1,3 @@ +#as: -march=3Drv32i_zdinx +#source: zdinx.s +#error_output: zdinx-rv32-fail.l diff --git a/gas/testsuite/gas/riscv/zdinx-rv32-fail.l b/gas/testsuite/gas/= riscv/zdinx-rv32-fail.l new file mode 100644 index 00000000000..e5c1592b89b --- /dev/null +++ b/gas/testsuite/gas/riscv/zdinx-rv32-fail.l @@ -0,0 +1,47 @@ +.*: Assembler messages: +.*: Error: illegal operands `fadd\.d .*' +.*: Error: illegal operands `fadd\.d .*' +.*: Error: illegal operands `fsub\.d .*' +.*: Error: illegal operands `fsub\.d .*' +.*: Error: illegal operands `fmul\.d .*' +.*: Error: illegal operands `fmul\.d .*' +.*: Error: illegal operands `fdiv\.d .*' +.*: Error: illegal operands `fdiv\.d .*' +.*: Error: illegal operands `fsqrt\.d .*' +.*: Error: illegal operands `fsqrt\.d .*' +.*: Error: illegal operands `fmin\.d .*' +.*: Error: illegal operands `fmax\.d .*' +.*: Error: illegal operands `fmadd\.d .*' +.*: Error: illegal operands `fmadd\.d .*' +.*: Error: illegal operands `fnmadd\.d .*' +.*: Error: illegal operands `fnmadd\.d .*' +.*: Error: illegal operands `fmsub\.d .*' +.*: Error: illegal operands `fmsub\.d .*' +.*: Error: illegal operands `fnmsub\.d .*' +.*: Error: illegal operands `fnmsub\.d .*' +.*: Error: illegal operands `fcvt\.w\.d .*' +.*: Error: illegal operands `fcvt\.w\.d .*' +.*: Error: illegal operands `fcvt\.wu\.d .*' +.*: Error: illegal operands `fcvt\.wu\.d .*' +.*: Error: unrecognized opcode `fcvt\.l\.d .*' +.*: Error: unrecognized opcode `fcvt\.l\.d .*' +.*: Error: unrecognized opcode `fcvt\.lu\.d .*' +.*: Error: unrecognized opcode `fcvt\.lu\.d .*' +.*: Error: unrecognized opcode `fcvt\.d\.l .*' +.*: Error: unrecognized opcode `fcvt\.d\.l .*' +.*: Error: unrecognized opcode `fcvt\.d\.lu .*' +.*: Error: unrecognized opcode `fcvt\.d\.lu .*' +.*: Error: illegal operands `fcvt\.s\.d .*' +.*: Error: illegal operands `fcvt\.s\.d .*' +.*: Error: illegal operands `fsgnj\.d .*' +.*: Error: illegal operands `fsgnjn\.d .*' +.*: Error: illegal operands `fsgnjx\.d .*' +.*: Error: illegal operands `feq\.d .*' +.*: Error: illegal operands `flt\.d .*' +.*: Error: illegal operands `fle\.d .*' +.*: Error: illegal operands `fgt\.d .*' +.*: Error: illegal operands `fge\.d .*' +.*: Error: illegal operands `fmv\.d .*' +.*: Error: illegal operands `fneg\.d .*' +.*: Error: illegal operands `fabs\.d .*' +.*: Error: illegal operands `fclass\.d .*' diff --git a/gas/testsuite/gas/riscv/zdinx-rv32.d b/gas/testsuite/gas/riscv= /zdinx-rv32.d new file mode 100644 index 00000000000..863f316645a --- /dev/null +++ b/gas/testsuite/gas/riscv/zdinx-rv32.d @@ -0,0 +1,52 @@ +#as: -march=3Drv32i_zdinx +#objdump: -dwr + +.*:[ ]+file format .* + +Disassembly of section .text: + +0+000 <target>: +[ ]+[0-9a-f]+:[ ]+02e67553[ ]+fadd\.d[ ]+a0,a2,a4 +[ ]+[0-9a-f]+:[ ]+02e60553[ ]+fadd\.d[ ]+a0,a2,a4,rne +[ ]+[0-9a-f]+:[ ]+0ae67553[ ]+fsub\.d[ ]+a0,a2,a4 +[ ]+[0-9a-f]+:[ ]+0ae60553[ ]+fsub\.d[ ]+a0,a2,a4,rne +[ ]+[0-9a-f]+:[ ]+12e67553[ ]+fmul\.d[ ]+a0,a2,a4 +[ ]+[0-9a-f]+:[ ]+12e60553[ ]+fmul\.d[ ]+a0,a2,a4,rne +[ ]+[0-9a-f]+:[ ]+1ae67553[ ]+fdiv\.d[ ]+a0,a2,a4 +[ ]+[0-9a-f]+:[ ]+1ae60553[ ]+fdiv\.d[ ]+a0,a2,a4,rne +[ ]+[0-9a-f]+:[ ]+5a067553[ ]+fsqrt\.d[ ]+a0,a2 +[ ]+[0-9a-f]+:[ ]+5a060553[ ]+fsqrt\.d[ ]+a0,a2,rne +[ ]+[0-9a-f]+:[ ]+2ae60553[ ]+fmin\.d[ ]+a0,a2,a4 +[ ]+[0-9a-f]+:[ ]+2ae61553[ ]+fmax\.d[ ]+a0,a2,a4 +[ ]+[0-9a-f]+:[ ]+82e67543[ ]+fmadd\.d[ ]+a0,a2,a4,a6 +[ ]+[0-9a-f]+:[ ]+82e60543[ ]+fmadd\.d[ ]+a0,a2,a4,a6,rne +[ ]+[0-9a-f]+:[ ]+82e6754f[ ]+fnmadd\.d[ ]+a0,a2,a4,a6 +[ ]+[0-9a-f]+:[ ]+82e6054f[ ]+fnmadd\.d[ ]+a0,a2,a4,a6,rne +[ ]+[0-9a-f]+:[ ]+82e67547[ ]+fmsub\.d[ ]+a0,a2,a4,a6 +[ ]+[0-9a-f]+:[ ]+82e60547[ ]+fmsub\.d[ ]+a0,a2,a4,a6,rne +[ ]+[0-9a-f]+:[ ]+82e6754b[ ]+fnmsub\.d[ ]+a0,a2,a4,a6 +[ ]+[0-9a-f]+:[ ]+82e6054b[ ]+fnmsub\.d[ ]+a0,a2,a4,a6,rne +[ ]+[0-9a-f]+:[ ]+c20675d3[ ]+fcvt\.w\.d[ ]+a1,a2 +[ ]+[0-9a-f]+:[ ]+c20605d3[ ]+fcvt\.w\.d[ ]+a1,a2,rne +[ ]+[0-9a-f]+:[ ]+c21675d3[ ]+fcvt\.wu\.d[ ]+a1,a2 +[ ]+[0-9a-f]+:[ ]+c21605d3[ ]+fcvt\.wu\.d[ ]+a1,a2,rne +[ ]+[0-9a-f]+:[ ]+d2058553[ ]+fcvt\.d\.w[ ]+a0,a1 +[ ]+[0-9a-f]+:[ ]+d2158553[ ]+fcvt\.d\.wu[ ]+a0,a1 +[ ]+[0-9a-f]+:[ ]+42058553[ ]+fcvt\.d\.s[ ]+a0,a1 +[ ]+[0-9a-f]+:[ ]+401675d3[ ]+fcvt\.s\.d[ ]+a1,a2 +[ ]+[0-9a-f]+:[ ]+401605d3[ ]+fcvt\.s\.d[ ]+a1,a2,rne +[ ]+[0-9a-f]+:[ ]+42258553[ ]+fcvt\.d\.h[ ]+a0,a1 +[ ]+[0-9a-f]+:[ ]+441675d3[ ]+fcvt\.h\.d[ ]+a1,a2 +[ ]+[0-9a-f]+:[ ]+441605d3[ ]+fcvt\.h\.d[ ]+a1,a2,rne +[ ]+[0-9a-f]+:[ ]+22e60553[ ]+fsgnj\.d[ ]+a0,a2,a4 +[ ]+[0-9a-f]+:[ ]+22e61553[ ]+fsgnjn\.d[ ]+a0,a2,a4 +[ ]+[0-9a-f]+:[ ]+22e62553[ ]+fsgnjx\.d[ ]+a0,a2,a4 +[ ]+[0-9a-f]+:[ ]+a2e625d3[ ]+feq\.d[ ]+a1,a2,a4 +[ ]+[0-9a-f]+:[ ]+a2e615d3[ ]+flt\.d[ ]+a1,a2,a4 +[ ]+[0-9a-f]+:[ ]+a2e605d3[ ]+fle\.d[ ]+a1,a2,a4 +[ ]+[0-9a-f]+:[ ]+a2c715d3[ ]+flt\.d[ ]+a1,a4,a2 +[ ]+[0-9a-f]+:[ ]+a2c705d3[ ]+fle\.d[ ]+a1,a4,a2 +[ ]+[0-9a-f]+:[ ]+22c60553[ ]+fmv\.d[ ]+a0,a2 +[ ]+[0-9a-f]+:[ ]+22c61553[ ]+fneg\.d[ ]+a0,a2 +[ ]+[0-9a-f]+:[ ]+22c62553[ ]+fabs\.d[ ]+a0,a2 +[ ]+[0-9a-f]+:[ ]+e20615d3[ ]+fclass\.d[ ]+a1,a2 diff --git a/gas/testsuite/gas/riscv/zdinx-rv32.s b/gas/testsuite/gas/riscv= /zdinx-rv32.s new file mode 100644 index 00000000000..d6684c0e8a5 --- /dev/null +++ b/gas/testsuite/gas/riscv/zdinx-rv32.s @@ -0,0 +1,52 @@ +target: + fadd.d a0, a2, a4 + fadd.d a0, a2, a4, rne + fsub.d a0, a2, a4 + fsub.d a0, a2, a4, rne + fmul.d a0, a2, a4 + fmul.d a0, a2, a4, rne + fdiv.d a0, a2, a4 + fdiv.d a0, a2, a4, rne + fsqrt.d a0, a2 + fsqrt.d a0, a2, rne + fmin.d a0, a2, a4 + fmax.d a0, a2, a4 + fmadd.d a0, a2, a4, a6 + fmadd.d a0, a2, a4, a6, rne + fnmadd.d a0, a2, a4, a6 + fnmadd.d a0, a2, a4, a6, rne + fmsub.d a0, a2, a4, a6 + fmsub.d a0, a2, a4, a6, rne + fnmsub.d a0, a2, a4, a6 + fnmsub.d a0, a2, a4, a6, rne + + fcvt.w.d a1, a2 + fcvt.w.d a1, a2, rne + fcvt.wu.d a1, a2 + fcvt.wu.d a1, a2, rne + fcvt.d.w a0, a1 + fcvt.d.wu a0, a1 + + fcvt.d.s a0, a1 + fcvt.s.d a1, a2 + fcvt.s.d a1, a2, rne + + .option push + .option arch, +zhinxmin + fcvt.d.h a0, a1 + fcvt.h.d a1, a2 + fcvt.h.d a1, a2, rne + .option pop + + fsgnj.d a0, a2, a4 + fsgnjn.d a0, a2, a4 + fsgnjx.d a0, a2, a4 + feq.d a1, a2, a4 + flt.d a1, a2, a4 + fle.d a1, a2, a4 + fgt.d a1, a2, a4 + fge.d a1, a2, a4 + fmv.d a0, a2 + fneg.d a0, a2 + fabs.d a0, a2 + fclass.d a1, a2 diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h index 132be423878..d142d3401fa 100644 --- a/include/opcode/riscv.h +++ b/include/opcode/riscv.h @@ -709,6 +709,18 @@ struct riscv_opcode #define INSN_8_BYTE 0x00000040 #define INSN_16_BYTE 0x00000050 =20 +/* Operands required to be an even-numbered register (pair) in RV32. */ +#define INSN_RV32_EVEN_D 0x00000100 +#define INSN_RV32_EVEN_S 0x00000200 +#define INSN_RV32_EVEN_T 0x00000400 /* Also covering U. */ +#define INSN_RV32_EVEN_R 0x00000800 +/* Shorthands for combinations of the above. */ +#define INSN_RV32_EVEN_DS (INSN_RV32_EVEN_D | INSN_RV32_EVEN_S) +#define INSN_RV32_EVEN_DST (INSN_RV32_EVEN_DS | INSN_RV32_EVEN_T) +#define INSN_RV32_EVEN_DSTR (INSN_RV32_EVEN_DST | INSN_RV32_EVEN_R) +#define INSN_RV32_EVEN_DU (INSN_RV32_EVEN_D | INSN_RV32_EVEN_T) +#define INSN_RV32_EVEN_ST (INSN_RV32_EVEN_S | INSN_RV32_EVEN_T) + /* Instruction is actually a macro. It should be ignored by the disassembler, and requires special treatment by the assembler. */ #define INSN_MACRO 0xffffffff diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c index e43c4e524ca..696f2d9777f 100644 --- a/opcodes/riscv-dis.c +++ b/opcodes/riscv-dis.c @@ -1138,6 +1138,23 @@ riscv_disassemble_insn (bfd_vma memaddr, if (!riscv_multi_subset_supports (&pd->riscv_rps_dis, op->insn_class)) continue; + + if (pd->xlen =3D=3D 32 + && riscv_subset_supports (&pd->riscv_rps_dis, "zdinx")) + { + if ((op->pinfo & INSN_RV32_EVEN_D) + && (word & (1u << OP_SH_RD))) + continue; + if ((op->pinfo & INSN_RV32_EVEN_S) + && (word & (1u << OP_SH_RS1))) + continue; + if ((op->pinfo & INSN_RV32_EVEN_T) + && (word & (1u << OP_SH_RS2))) + continue; + if ((op->pinfo & INSN_RV32_EVEN_R) + && (word & (1u << OP_SH_RS3))) + continue; + } } =20 /* It's a match. */ diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c index f9c5224c2b0..6b01851b757 100644 --- a/opcodes/riscv-opc.c +++ b/opcodes/riscv-opc.c @@ -955,10 +955,10 @@ const struct riscv_opcode riscv_opcodes[] =3D {"fcvt.h.w", 0, INSN_CLASS_ZFH_INX, "D,sm", MATCH_FCVT_H_W, MASK_F= CVT_H_W, match_opcode, 0 }, {"fcvt.h.wu", 0, INSN_CLASS_ZFH_INX, "D,sm", MATCH_FCVT_H_WU, MASK_= FCVT_H_WU, match_opcode, 0 }, {"fcvt.s.h", 0, INSN_CLASS_ZFHMIN_INX, "D,S", MATCH_FCVT_S_H, MASK_F= CVT_S_H|MASK_RM, match_opcode, 0 }, -{"fcvt.d.h", 0, INSN_CLASS_ZFHMIN_AND_D_INX, "D,S", MATCH_FCVT= _D_H, MASK_FCVT_D_H|MASK_RM, match_opcode, 0 }, -{"fcvt.q.h", 0, INSN_CLASS_ZFHMIN_AND_Q_INX, "D,S", MATCH_FCVT= _Q_H, MASK_FCVT_Q_H|MASK_RM, match_opcode, 0 }, +{"fcvt.d.h", 0, INSN_CLASS_ZFHMIN_AND_D_INX, "D,S", MATCH_FCVT_D_H, MASK= _FCVT_D_H|MASK_RM, match_opcode, INSN_RV32_EVEN_D }, +{"fcvt.q.h", 0, INSN_CLASS_ZFHMIN_AND_Q_INX, "D,S", MATCH_FCVT_Q_H, MASK= _FCVT_Q_H|MASK_RM, match_opcode, 0 }, {"fcvt.h.s", 0, INSN_CLASS_ZFHMIN_INX, "D,Sm", MATCH_FCVT_H_S, MASK_F= CVT_H_S, match_opcode, 0 }, -{"fcvt.h.d", 0, INSN_CLASS_ZFHMIN_AND_D_INX, "D,Sm", MATCH_FCVT_H_D, MAS= K_FCVT_H_D, match_opcode, 0 }, +{"fcvt.h.d", 0, INSN_CLASS_ZFHMIN_AND_D_INX, "D,Sm", MATCH_FCVT_H_D, MAS= K_FCVT_H_D, match_opcode, INSN_RV32_EVEN_S }, {"fcvt.h.q", 0, INSN_CLASS_ZFHMIN_AND_Q_INX, "D,Sm", MATCH_FCVT_H_Q, MAS= K_FCVT_H_Q, match_opcode, 0 }, {"fclass.h", 0, INSN_CLASS_ZFH_INX, "d,S", MATCH_FCLASS_H, MASK_= FCLASS_H, match_opcode, 0 }, {"feq.h", 0, INSN_CLASS_ZFH_INX, "d,S,T", MATCH_FEQ_H, MASK_FEQ= _H, match_opcode, 0 }, @@ -1045,35 +1045,35 @@ const struct riscv_opcode riscv_opcodes[] =3D {"fsd", 0, INSN_CLASS_ZCD, "CD,Cl(Cs)", MATCH_C_FSD, MASK_C_FSD, ma= tch_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE }, {"fsd", 0, INSN_CLASS_D, "T,q(s)", MATCH_FSD, MASK_FSD, match_= opcode, INSN_DREF|INSN_8_BYTE }, {"fsd", 0, INSN_CLASS_D, "T,A,s", 0, (int) M_Sx_FSx, match_rs= 1_nonzero, INSN_MACRO }, -{"fmv.d", 0, INSN_CLASS_D_INX, "D,U", MATCH_FSGNJ_D, MASK_FSG= NJ_D, match_rs1_eq_rs2, INSN_ALIAS }, -{"fneg.d", 0, INSN_CLASS_D_INX, "D,U", MATCH_FSGNJN_D, MASK_FS= GNJN_D, match_rs1_eq_rs2, INSN_ALIAS }, -{"fabs.d", 0, INSN_CLASS_D_INX, "D,U", MATCH_FSGNJX_D, MASK_FS= GNJX_D, match_rs1_eq_rs2, INSN_ALIAS }, -{"fsgnj.d", 0, INSN_CLASS_D_INX, "D,S,T", MATCH_FSGNJ_D, MASK_FSG= NJ_D, match_opcode, 0 }, -{"fsgnjn.d", 0, INSN_CLASS_D_INX, "D,S,T", MATCH_FSGNJN_D, MASK_FS= GNJN_D, match_opcode, 0 }, -{"fsgnjx.d", 0, INSN_CLASS_D_INX, "D,S,T", MATCH_FSGNJX_D, MASK_FS= GNJX_D, match_opcode, 0 }, -{"fadd.d", 0, INSN_CLASS_D_INX, "D,S,Tm", MATCH_FADD_D, MASK_FADD= _D, match_opcode, 0 }, -{"fsub.d", 0, INSN_CLASS_D_INX, "D,S,Tm", MATCH_FSUB_D, MASK_FSUB= _D, match_opcode, 0 }, -{"fmul.d", 0, INSN_CLASS_D_INX, "D,S,Tm", MATCH_FMUL_D, MASK_FMUL= _D, match_opcode, 0 }, -{"fdiv.d", 0, INSN_CLASS_D_INX, "D,S,Tm", MATCH_FDIV_D, MASK_FDIV= _D, match_opcode, 0 }, -{"fsqrt.d", 0, INSN_CLASS_D_INX, "D,Sm", MATCH_FSQRT_D, MASK_FSQ= RT_D, match_opcode, 0 }, -{"fmin.d", 0, INSN_CLASS_D_INX, "D,S,T", MATCH_FMIN_D, MASK_FMIN= _D, match_opcode, 0 }, -{"fmax.d", 0, INSN_CLASS_D_INX, "D,S,T", MATCH_FMAX_D, MASK_FMAX= _D, match_opcode, 0 }, -{"fmadd.d", 0, INSN_CLASS_D_INX, "D,S,T,Rm", MATCH_FMADD_D, MASK_FMA= DD_D, match_opcode, 0 }, -{"fnmadd.d", 0, INSN_CLASS_D_INX, "D,S,T,Rm", MATCH_FNMADD_D, MASK_FN= MADD_D, match_opcode, 0 }, -{"fmsub.d", 0, INSN_CLASS_D_INX, "D,S,T,Rm", MATCH_FMSUB_D, MASK_FMS= UB_D, match_opcode, 0 }, -{"fnmsub.d", 0, INSN_CLASS_D_INX, "D,S,T,Rm", MATCH_FNMSUB_D, MASK_FN= MSUB_D, match_opcode, 0 }, -{"fcvt.w.d", 0, INSN_CLASS_D_INX, "d,Sm", MATCH_FCVT_W_D, MASK_FC= VT_W_D, match_opcode, 0 }, -{"fcvt.wu.d", 0, INSN_CLASS_D_INX, "d,Sm", MATCH_FCVT_WU_D, MASK_F= CVT_WU_D, match_opcode, 0 }, -{"fcvt.d.w", 0, INSN_CLASS_D_INX, "D,s", MATCH_FCVT_D_W, MASK_FC= VT_D_W|MASK_RM, match_opcode, 0 }, -{"fcvt.d.wu", 0, INSN_CLASS_D_INX, "D,s", MATCH_FCVT_D_WU, MASK_F= CVT_D_WU|MASK_RM, match_opcode, 0 }, -{"fcvt.d.s", 0, INSN_CLASS_D_INX, "D,S", MATCH_FCVT_D_S, MASK_FC= VT_D_S|MASK_RM, match_opcode, 0 }, -{"fcvt.s.d", 0, INSN_CLASS_D_INX, "D,Sm", MATCH_FCVT_S_D, MASK_FC= VT_S_D, match_opcode, 0 }, -{"fclass.d", 0, INSN_CLASS_D_INX, "d,S", MATCH_FCLASS_D, MASK_FC= LASS_D, match_opcode, 0 }, -{"feq.d", 0, INSN_CLASS_D_INX, "d,S,T", MATCH_FEQ_D, MASK_FEQ_D= , match_opcode, 0 }, -{"flt.d", 0, INSN_CLASS_D_INX, "d,S,T", MATCH_FLT_D, MASK_FLT_D= , match_opcode, 0 }, -{"fle.d", 0, INSN_CLASS_D_INX, "d,S,T", MATCH_FLE_D, MASK_FLE_D= , match_opcode, 0 }, -{"fgt.d", 0, INSN_CLASS_D_INX, "d,T,S", MATCH_FLT_D, MASK_FLT_D= , match_opcode, INSN_ALIAS }, -{"fge.d", 0, INSN_CLASS_D_INX, "d,T,S", MATCH_FLE_D, MASK_FLE_D= , match_opcode, INSN_ALIAS }, +{"fmv.d", 0, INSN_CLASS_D_INX, "D,U", MATCH_FSGNJ_D, MASK_FSG= NJ_D, match_rs1_eq_rs2, INSN_ALIAS|INSN_RV32_EVEN_DU }, +{"fneg.d", 0, INSN_CLASS_D_INX, "D,U", MATCH_FSGNJN_D, MASK_FS= GNJN_D, match_rs1_eq_rs2, INSN_ALIAS|INSN_RV32_EVEN_DU }, +{"fabs.d", 0, INSN_CLASS_D_INX, "D,U", MATCH_FSGNJX_D, MASK_FS= GNJX_D, match_rs1_eq_rs2, INSN_ALIAS|INSN_RV32_EVEN_DU }, +{"fsgnj.d", 0, INSN_CLASS_D_INX, "D,S,T", MATCH_FSGNJ_D, MASK_FSG= NJ_D, match_opcode, INSN_RV32_EVEN_DST }, +{"fsgnjn.d", 0, INSN_CLASS_D_INX, "D,S,T", MATCH_FSGNJN_D, MASK_FS= GNJN_D, match_opcode, INSN_RV32_EVEN_DST }, +{"fsgnjx.d", 0, INSN_CLASS_D_INX, "D,S,T", MATCH_FSGNJX_D, MASK_FS= GNJX_D, match_opcode, INSN_RV32_EVEN_DST }, +{"fadd.d", 0, INSN_CLASS_D_INX, "D,S,Tm", MATCH_FADD_D, MASK_FADD= _D, match_opcode, INSN_RV32_EVEN_DST }, +{"fsub.d", 0, INSN_CLASS_D_INX, "D,S,Tm", MATCH_FSUB_D, MASK_FSUB= _D, match_opcode, INSN_RV32_EVEN_DST }, +{"fmul.d", 0, INSN_CLASS_D_INX, "D,S,Tm", MATCH_FMUL_D, MASK_FMUL= _D, match_opcode, INSN_RV32_EVEN_DST }, +{"fdiv.d", 0, INSN_CLASS_D_INX, "D,S,Tm", MATCH_FDIV_D, MASK_FDIV= _D, match_opcode, INSN_RV32_EVEN_DST }, +{"fsqrt.d", 0, INSN_CLASS_D_INX, "D,Sm", MATCH_FSQRT_D, MASK_FSQ= RT_D, match_opcode, INSN_RV32_EVEN_DS }, +{"fmin.d", 0, INSN_CLASS_D_INX, "D,S,T", MATCH_FMIN_D, MASK_FMIN= _D, match_opcode, INSN_RV32_EVEN_DST }, +{"fmax.d", 0, INSN_CLASS_D_INX, "D,S,T", MATCH_FMAX_D, MASK_FMAX= _D, match_opcode, INSN_RV32_EVEN_DST }, +{"fmadd.d", 0, INSN_CLASS_D_INX, "D,S,T,Rm", MATCH_FMADD_D, MASK_FMA= DD_D, match_opcode, INSN_RV32_EVEN_DSTR }, +{"fnmadd.d", 0, INSN_CLASS_D_INX, "D,S,T,Rm", MATCH_FNMADD_D, MASK_FN= MADD_D, match_opcode, INSN_RV32_EVEN_DSTR }, +{"fmsub.d", 0, INSN_CLASS_D_INX, "D,S,T,Rm", MATCH_FMSUB_D, MASK_FMS= UB_D, match_opcode, INSN_RV32_EVEN_DSTR }, +{"fnmsub.d", 0, INSN_CLASS_D_INX, "D,S,T,Rm", MATCH_FNMSUB_D, MASK_FN= MSUB_D, match_opcode, INSN_RV32_EVEN_DSTR }, +{"fcvt.w.d", 0, INSN_CLASS_D_INX, "d,Sm", MATCH_FCVT_W_D, MASK_FC= VT_W_D, match_opcode, INSN_RV32_EVEN_S }, +{"fcvt.wu.d", 0, INSN_CLASS_D_INX, "d,Sm", MATCH_FCVT_WU_D, MASK_F= CVT_WU_D, match_opcode, INSN_RV32_EVEN_S }, +{"fcvt.d.w", 0, INSN_CLASS_D_INX, "D,s", MATCH_FCVT_D_W, MASK_FC= VT_D_W|MASK_RM, match_opcode, INSN_RV32_EVEN_D }, +{"fcvt.d.wu", 0, INSN_CLASS_D_INX, "D,s", MATCH_FCVT_D_WU, MASK_F= CVT_D_WU|MASK_RM, match_opcode, INSN_RV32_EVEN_D }, +{"fcvt.d.s", 0, INSN_CLASS_D_INX, "D,S", MATCH_FCVT_D_S, MASK_FC= VT_D_S|MASK_RM, match_opcode, INSN_RV32_EVEN_D }, +{"fcvt.s.d", 0, INSN_CLASS_D_INX, "D,Sm", MATCH_FCVT_S_D, MASK_FC= VT_S_D, match_opcode, INSN_RV32_EVEN_S }, +{"fclass.d", 0, INSN_CLASS_D_INX, "d,S", MATCH_FCLASS_D, MASK_FC= LASS_D, match_opcode, INSN_RV32_EVEN_S }, +{"feq.d", 0, INSN_CLASS_D_INX, "d,S,T", MATCH_FEQ_D, MASK_FEQ_D= , match_opcode, INSN_RV32_EVEN_ST }, +{"flt.d", 0, INSN_CLASS_D_INX, "d,S,T", MATCH_FLT_D, MASK_FLT_D= , match_opcode, INSN_RV32_EVEN_ST }, +{"fle.d", 0, INSN_CLASS_D_INX, "d,S,T", MATCH_FLE_D, MASK_FLE_D= , match_opcode, INSN_RV32_EVEN_ST }, +{"fgt.d", 0, INSN_CLASS_D_INX, "d,T,S", MATCH_FLT_D, MASK_FLT_D= , match_opcode, INSN_ALIAS|INSN_RV32_EVEN_ST }, +{"fge.d", 0, INSN_CLASS_D_INX, "d,T,S", MATCH_FLE_D, MASK_FLE_D= , match_opcode, INSN_ALIAS|INSN_RV32_EVEN_ST }, {"fmv.x.d", 64, INSN_CLASS_D, "d,S", MATCH_FMV_X_D, MASK_FMV_X_D= , match_opcode, 0 }, {"fmv.d.x", 64, INSN_CLASS_D, "D,s", MATCH_FMV_D_X, MASK_FMV_D_X= , match_opcode, 0 }, {"fcvt.l.d", 64, INSN_CLASS_D_INX, "d,Sm", MATCH_FCVT_L_D, MASK_FC= VT_L_D, match_opcode, 0 },