[PATCH 10/19] RISC-V: check operands for Zdinx in RV32

Jiawei jiawei@iscas.ac.cn
Tue Apr 28 08:45:35 GMT 2026


> Like for Zilsd, register pair operands are required to be encoded with the
> low bit clear. Since match functions don't have XLEN available, introduce
> respective flags, to be used explicitly in assembler and disassembler.
> ---
> What about Zqinx? There's no formal spec for that extension afaics. For
> RV64, does that behave like Zdinx for RV32? For RV32, does it require
> register numbers to be divisible by 4? Or is it not a thing there in the
> first place?
>
> No similar checking is easily possible for scalar vector insns, as element
> width there isn't encoded in the insn. (Plus V and Zdinx can't be enabled
> together right now anyway.)
>
> We could further use RV32_EVEN_CHECK for Zilsd as well, then allowing to
> eliminate one or two match functions. (Hence RV32_EVEN_CHECK()'s scope is
> pretty wide.)
>
The RV32 Zdinx operand checking looks right to me. In RV32, double-precision
values in GPRs need to be represented as register pairs, so the 
corresponding
D/S/T/R operands must use even-numbered registers.

The new INSN_RV32_EVEN_* flags look like a good way to express this
requirement in the opcode table, and it is useful that both the 
assembler and
disassembler check the same property. The gating on xlen == 32 and
RCLASS_GPR also avoids affecting the normal FPR-based D extension case.

Regarding Zqinx, I found that the old binutils Zqinx register tests treated
RV64 Zqinx as using register pairs, and RV32 Zqinx as using register pairs
and quad-register groups.

https://sourceware.org/pipermail/binutils/2022-February/119683.html

So the natural rule would be that RV64 Zqinx needs
even-numbered registers for Q operands, while RV32 Zqinx needs registers
divisible by 4 for Q operands. However, the Zfinx specification also says
that Zqinx is not considered further in that document, so I agree it is 
better
not to infer or add Zqinx checking in this patch.

Best regards,

Jiawei

>
> --- a/gas/config/tc-riscv.c
> +++ b/gas/config/tc-riscv.c
> @@ -2908,6 +2908,12 @@ riscv_ip (char *str, struct riscv_cl_ins
>        *imm_reloc = BFD_RELOC_UNUSED;
>        p = percent_op_null;
>
> +#define RV32_EVEN_CHECK(form, rclass, regno)     \
> +  (!(ip->insn_mo->pinfo & INSN_RV32_EVEN_##form) \
> +   || xlen != 32                                 \
> +   || (rclass) != RCLASS_GPR                     \
> +   || !((regno) & 1))
> +
>        for (oparg = insn->args;; ++oparg)
>      {
>        opargStart = oparg;
> @@ -2915,6 +2921,8 @@ riscv_ip (char *str, struct riscv_cl_ins
>          ++asarg;
>        switch (*oparg)
>          {
> +          enum reg_class rclass;
> +
>          case '\0': /* End of args.  */
>            if (insn->match_func && !insn->match_func (insn, 
> ip->insn_opcode))
>          break;
> @@ -3554,32 +3562,40 @@ riscv_ip (char *str, struct riscv_cl_ins
>          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), &regno))
> +          rclass = riscv_subset_supports (&riscv_rps_as, "zfinx")
> +               ? RCLASS_GPR : RCLASS_FPR;
> +          if (reg_lookup (&asarg, rclass, &regno))
>          {
>            char c = *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;
>
> @@ -4282,6 +4298,8 @@ riscv_ip (char *str, struct riscv_cl_ins
>        insn_with_csr = false;
>      }
>
> +#undef RV32_EVEN_CHECK
> +
>   out:
>    /* Restore the character we might have clobbered above.  */
>    if (save_c)
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zdinx-rv32.d
> @@ -0,0 +1,52 @@
> +#as: -march=rv32i_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
> --- /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
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zdinx-rv32-fail.d
> @@ -0,0 +1,3 @@
> +#as: -march=rv32i_zdinx
> +#source: zdinx.s
> +#error_output: zdinx-rv32-fail.l
> --- /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 .*'
> --- a/include/opcode/riscv.h
> +++ b/include/opcode/riscv.h
> @@ -679,6 +679,18 @@ struct riscv_opcode
>  #define INSN_8_BYTE        0x00000040
>  #define INSN_16_BYTE        0x00000050
>
> +/* 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
> --- a/opcodes/riscv-dis.c
> +++ b/opcodes/riscv-dis.c
> @@ -1032,6 +1032,23 @@ riscv_disassemble_insn (bfd_vma memaddr,
>             if ((op->pinfo & INSN_V_EEW64)
>            && !riscv_subset_supports (&pd->riscv_rps_dis, "zve64x"))
>          continue;
> +
> +          if (pd->xlen == 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;
> +        }
>          }
>
>        /* It's a match.  */
> --- a/opcodes/riscv-opc.c
> +++ b/opcodes/riscv-opc.c
> @@ -931,10 +931,10 @@ const struct riscv_opcode riscv_opcodes[
>  {"fcvt.h.w",   0, INSN_CLASS_ZFH_INX,  "D,sm", MATCH_FCVT_H_W, 
> MASK_FCVT_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_FCVT_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_FCVT_H_S, match_opcode, 0 },
> -{"fcvt.h.d",   0, INSN_CLASS_ZFHMIN_AND_D_INX, "D,Sm", 
> MATCH_FCVT_H_D, MASK_FCVT_H_D, match_opcode, 0 },
> +{"fcvt.h.d",   0, INSN_CLASS_ZFHMIN_AND_D_INX, "D,Sm", 
> MATCH_FCVT_H_D, MASK_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, MASK_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 },
> @@ -1021,35 +1021,35 @@ const struct riscv_opcode riscv_opcodes[
>  {"fsd",        0, INSN_CLASS_ZCD, "CD,Cl(Cs)", MATCH_C_FSD, 
> MASK_C_FSD, match_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_rs1_nonzero, INSN_MACRO },
> -{"fmv.d",      0, INSN_CLASS_D_INX,   "D,U",  MATCH_FSGNJ_D, 
> MASK_FSGNJ_D, match_rs1_eq_rs2, INSN_ALIAS },
> -{"fneg.d",     0, INSN_CLASS_D_INX,   "D,U",  MATCH_FSGNJN_D, 
> MASK_FSGNJN_D, match_rs1_eq_rs2, INSN_ALIAS },
> -{"fabs.d",     0, INSN_CLASS_D_INX,   "D,U",  MATCH_FSGNJX_D, 
> MASK_FSGNJX_D, match_rs1_eq_rs2, INSN_ALIAS },
> -{"fsgnj.d",    0, INSN_CLASS_D_INX,   "D,S,T",  MATCH_FSGNJ_D, 
> MASK_FSGNJ_D, match_opcode, 0 },
> -{"fsgnjn.d",   0, INSN_CLASS_D_INX,   "D,S,T",  MATCH_FSGNJN_D, 
> MASK_FSGNJN_D, match_opcode, 0 },
> -{"fsgnjx.d",   0, INSN_CLASS_D_INX,   "D,S,T",  MATCH_FSGNJX_D, 
> MASK_FSGNJX_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_FSQRT_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_FMADD_D, match_opcode, 0 },
> -{"fnmadd.d",   0, INSN_CLASS_D_INX,   "D,S,T,Rm", MATCH_FNMADD_D, 
> MASK_FNMADD_D, match_opcode, 0 },
> -{"fmsub.d",    0, INSN_CLASS_D_INX,   "D,S,T,Rm", MATCH_FMSUB_D, 
> MASK_FMSUB_D, match_opcode, 0 },
> -{"fnmsub.d",   0, INSN_CLASS_D_INX,   "D,S,T,Rm", MATCH_FNMSUB_D, 
> MASK_FNMSUB_D, match_opcode, 0 },
> -{"fcvt.w.d",   0, INSN_CLASS_D_INX,   "d,Sm", MATCH_FCVT_W_D, 
> MASK_FCVT_W_D, match_opcode, 0 },
> -{"fcvt.wu.d",  0, INSN_CLASS_D_INX,   "d,Sm", MATCH_FCVT_WU_D, 
> MASK_FCVT_WU_D, match_opcode, 0 },
> -{"fcvt.d.w",   0, INSN_CLASS_D_INX,   "D,s",  MATCH_FCVT_D_W, 
> MASK_FCVT_D_W|MASK_RM, match_opcode, 0 },
> -{"fcvt.d.wu",  0, INSN_CLASS_D_INX,   "D,s",  MATCH_FCVT_D_WU, 
> MASK_FCVT_D_WU|MASK_RM, match_opcode, 0 },
> -{"fcvt.d.s",   0, INSN_CLASS_D_INX,   "D,S",  MATCH_FCVT_D_S, 
> MASK_FCVT_D_S|MASK_RM, match_opcode, 0 },
> -{"fcvt.s.d",   0, INSN_CLASS_D_INX,   "D,Sm", MATCH_FCVT_S_D, 
> MASK_FCVT_S_D, match_opcode, 0 },
> -{"fclass.d",   0, INSN_CLASS_D_INX,   "d,S",  MATCH_FCLASS_D, 
> MASK_FCLASS_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_FSGNJ_D, match_rs1_eq_rs2, INSN_ALIAS|INSN_RV32_EVEN_DU },
> +{"fneg.d",     0, INSN_CLASS_D_INX,   "D,U",  MATCH_FSGNJN_D, 
> MASK_FSGNJN_D, match_rs1_eq_rs2, INSN_ALIAS|INSN_RV32_EVEN_DU },
> +{"fabs.d",     0, INSN_CLASS_D_INX,   "D,U",  MATCH_FSGNJX_D, 
> MASK_FSGNJX_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_FSGNJ_D, match_opcode, INSN_RV32_EVEN_DST },
> +{"fsgnjn.d",   0, INSN_CLASS_D_INX,   "D,S,T",  MATCH_FSGNJN_D, 
> MASK_FSGNJN_D, match_opcode, INSN_RV32_EVEN_DST },
> +{"fsgnjx.d",   0, INSN_CLASS_D_INX,   "D,S,T",  MATCH_FSGNJX_D, 
> MASK_FSGNJX_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_FSQRT_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_FMADD_D, match_opcode, INSN_RV32_EVEN_DSTR },
> +{"fnmadd.d",   0, INSN_CLASS_D_INX,   "D,S,T,Rm", MATCH_FNMADD_D, 
> MASK_FNMADD_D, match_opcode, INSN_RV32_EVEN_DSTR },
> +{"fmsub.d",    0, INSN_CLASS_D_INX,   "D,S,T,Rm", MATCH_FMSUB_D, 
> MASK_FMSUB_D, match_opcode, INSN_RV32_EVEN_DSTR },
> +{"fnmsub.d",   0, INSN_CLASS_D_INX,   "D,S,T,Rm", MATCH_FNMSUB_D, 
> MASK_FNMSUB_D, match_opcode, INSN_RV32_EVEN_DSTR },
> +{"fcvt.w.d",   0, INSN_CLASS_D_INX,   "d,Sm", MATCH_FCVT_W_D, 
> MASK_FCVT_W_D, match_opcode, INSN_RV32_EVEN_S },
> +{"fcvt.wu.d",  0, INSN_CLASS_D_INX,   "d,Sm", MATCH_FCVT_WU_D, 
> MASK_FCVT_WU_D, match_opcode, INSN_RV32_EVEN_S },
> +{"fcvt.d.w",   0, INSN_CLASS_D_INX,   "D,s",  MATCH_FCVT_D_W, 
> MASK_FCVT_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_FCVT_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_FCVT_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_FCVT_S_D, match_opcode, INSN_RV32_EVEN_S },
> +{"fclass.d",   0, INSN_CLASS_D_INX,   "d,S",  MATCH_FCLASS_D, 
> MASK_FCLASS_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_FCVT_L_D, match_opcode, 0 },
>



More information about the Binutils mailing list