Re: [PATCH v4 07/12] RISC-V: check operands for Zqinx

Nelson Chu <[email protected]> Mon, 27 Jul 2026 11:15:06 +0800
Newsgroups gmane.comp.gnu.binutils
Message-ID <CAHT-pJydDYqBS4S4ecj9Kma6nW2wq++ewjUKM9dRNgZORoS9WQ@mail.gmail.com>
On Fri, Jul 24, 2026 at 6:04 PM Jan Beulich <[email protected]> wrote:
>
> By analogy to Zdinx on RV32, register pair operands are presumably (there
> not being any formal spec afaict) required to be encoded with the low bit
> clear in RV64; in RV32 the low two bits need to be clear. Since match
> functions don't have XLEN available, introduce respective flags, to be
> used explicitly in assembler and disassembler.

Okay, same reason as the previous patch.

> ---
> Does Zqinx actually make much sense in RV32? Function argument passing,
> for example, ends up odd: a0..a3 aren't suitable to hold an argument.
> Hence only a single argument can be passed in registers (a2..a5).

Jiawei,

You should know the best for these finx changes, do you think zqinx
should be allowed under rv32?

Thanks
Nelson

> No similar checking is easily possible for scalar vector insns, as element
> width there isn't encoded in the insn. (Plus V and Zqinx can't be enabled
> together right now anyway.)
> ---
> v3: Fix typo in comment.
> v2: New.
>
> --- a/gas/config/tc-riscv.c
> +++ b/gas/config/tc-riscv.c
> @@ -3010,6 +3010,12 @@ riscv_ip (char *str, struct riscv_cl_ins
>     || (rclass) != RCLASS_GPR                     \
>     || !((regno) & 1))
>
> +#define RV64_EVEN_CHECK(form, rclass, regno)     \
> +  (!(ip->insn_mo->pinfo & INSN_RV64_EVEN_##form) \
> +   || xlen > 64                                  \
> +   || (rclass) != RCLASS_GPR                     \
> +   || !((regno) & (xlen == 32 ? 3 : 1)))
> +
>        for (oparg = insn->args;; ++oparg)
>         {
>           opargStart = oparg;
> @@ -3689,12 +3695,14 @@ riscv_ip (char *str, struct riscv_cl_ins
>                   switch (c)
>                     {
>                     case 'D':
> -                     if (!RV32_EVEN_CHECK (D, rclass, regno))
> +                     if (!RV32_EVEN_CHECK (D, rclass, regno)
> +                         || !RV64_EVEN_CHECK (D, rclass, regno))
>                         break;
>                       INSERT_OPERAND (RD, *ip, regno);
>                       continue;
>                     case 'S':
> -                     if (!RV32_EVEN_CHECK (S, rclass, regno))
> +                     if (!RV32_EVEN_CHECK (S, rclass, regno)
> +                         || !RV64_EVEN_CHECK (S, rclass, regno))
>                         break;
>                       INSERT_OPERAND (RS1, *ip, regno);
>                       continue;
> @@ -3702,12 +3710,14 @@ riscv_ip (char *str, struct riscv_cl_ins
>                       INSERT_OPERAND (RS1, *ip, regno);
>                       /* Fall through.  */
>                     case 'T':
> -                     if (!RV32_EVEN_CHECK (T, rclass, regno))
> +                     if (!RV32_EVEN_CHECK (T, rclass, regno)
> +                         || !RV64_EVEN_CHECK (T, rclass, regno))
>                         break;
>                       INSERT_OPERAND (RS2, *ip, regno);
>                       continue;
>                     case 'R':
> -                     if (!RV32_EVEN_CHECK (R, rclass, regno))
> +                     if (!RV32_EVEN_CHECK (R, rclass, regno)
> +                         || !RV64_EVEN_CHECK (R, rclass, regno))
>                         break;
>                       INSERT_OPERAND (RS3, *ip, regno);
>                       continue;
> @@ -4547,6 +4557,7 @@ riscv_ip (char *str, struct riscv_cl_ins
>      }
>
>  #undef RV32_EVEN_CHECK
> +#undef RV64_EVEN_CHECK
>
>   out:
>    /* Restore the character we might have clobbered above.  */
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zqinx-rv32.d
> @@ -0,0 +1,52 @@
> +#as: -march=rv32i_zqinx
> +#objdump: -dwr
> +
> +.*:[   ]+file format .*
> +
> +Disassembly of section .text:
> +
> +0+000 <target>:
> +[      ]+[0-9a-f]+:[   ]+078a7453[     ]+fadd\.q[      ]+s0,s4,s8
> +[      ]+[0-9a-f]+:[   ]+078a0453[     ]+fadd\.q[      ]+s0,s4,s8,rne
> +[      ]+[0-9a-f]+:[   ]+0f8a7453[     ]+fsub\.q[      ]+s0,s4,s8
> +[      ]+[0-9a-f]+:[   ]+0f8a0453[     ]+fsub\.q[      ]+s0,s4,s8,rne
> +[      ]+[0-9a-f]+:[   ]+178a7453[     ]+fmul\.q[      ]+s0,s4,s8
> +[      ]+[0-9a-f]+:[   ]+178a0453[     ]+fmul\.q[      ]+s0,s4,s8,rne
> +[      ]+[0-9a-f]+:[   ]+1f8a7453[     ]+fdiv\.q[      ]+s0,s4,s8
> +[      ]+[0-9a-f]+:[   ]+1f8a0453[     ]+fdiv\.q[      ]+s0,s4,s8,rne
> +[      ]+[0-9a-f]+:[   ]+5e0a7453[     ]+fsqrt\.q[     ]+s0,s4
> +[      ]+[0-9a-f]+:[   ]+5e0a0453[     ]+fsqrt\.q[     ]+s0,s4,rne
> +[      ]+[0-9a-f]+:[   ]+2f8a0453[     ]+fmin\.q[      ]+s0,s4,s8
> +[      ]+[0-9a-f]+:[   ]+2f8a1453[     ]+fmax\.q[      ]+s0,s4,s8
> +[      ]+[0-9a-f]+:[   ]+678a7443[     ]+fmadd\.q[     ]+s0,s4,s8,a2
> +[      ]+[0-9a-f]+:[   ]+678a0443[     ]+fmadd\.q[     ]+s0,s4,s8,a2,rne
> +[      ]+[0-9a-f]+:[   ]+678a744f[     ]+fnmadd\.q[    ]+s0,s4,s8,a2
> +[      ]+[0-9a-f]+:[   ]+678a044f[     ]+fnmadd\.q[    ]+s0,s4,s8,a2,rne
> +[      ]+[0-9a-f]+:[   ]+678a7447[     ]+fmsub\.q[     ]+s0,s4,s8,a2
> +[      ]+[0-9a-f]+:[   ]+678a0447[     ]+fmsub\.q[     ]+s0,s4,s8,a2,rne
> +[      ]+[0-9a-f]+:[   ]+678a744b[     ]+fnmsub\.q[    ]+s0,s4,s8,a2
> +[      ]+[0-9a-f]+:[   ]+678a044b[     ]+fnmsub\.q[    ]+s0,s4,s8,a2,rne
> +[      ]+[0-9a-f]+:[   ]+c60a75d3[     ]+fcvt\.w\.q[   ]+a1,s4
> +[      ]+[0-9a-f]+:[   ]+c60a05d3[     ]+fcvt\.w\.q[   ]+a1,s4,rne
> +[      ]+[0-9a-f]+:[   ]+c61a75d3[     ]+fcvt\.wu\.q[  ]+a1,s4
> +[      ]+[0-9a-f]+:[   ]+c61a05d3[     ]+fcvt\.wu\.q[  ]+a1,s4,rne
> +[      ]+[0-9a-f]+:[   ]+d6058453[     ]+fcvt\.q\.w[   ]+s0,a1
> +[      ]+[0-9a-f]+:[   ]+d6158453[     ]+fcvt\.q\.wu[  ]+s0,a1
> +[      ]+[0-9a-f]+:[   ]+46058453[     ]+fcvt\.q\.s[   ]+s0,a1
> +[      ]+[0-9a-f]+:[   ]+403a75d3[     ]+fcvt\.s\.q[   ]+a1,s4
> +[      ]+[0-9a-f]+:[   ]+403a05d3[     ]+fcvt\.s\.q[   ]+a1,s4,rne
> +[      ]+[0-9a-f]+:[   ]+46150453[     ]+fcvt\.q\.d[   ]+s0,a0
> +[      ]+[0-9a-f]+:[   ]+423a7553[     ]+fcvt\.d\.q[   ]+a0,s4
> +[      ]+[0-9a-f]+:[   ]+423a0553[     ]+fcvt\.d\.q[   ]+a0,s4,rne
> +[      ]+[0-9a-f]+:[   ]+46258453[     ]+fcvt\.q\.h[   ]+s0,a1
> +[      ]+[0-9a-f]+:[   ]+443a75d3[     ]+fcvt\.h\.q[   ]+a1,s4
> +[      ]+[0-9a-f]+:[   ]+443a05d3[     ]+fcvt\.h\.q[   ]+a1,s4,rne
> +[      ]+[0-9a-f]+:[   ]+278a0453[     ]+fsgnj\.q[     ]+s0,s4,s8
> +[      ]+[0-9a-f]+:[   ]+278a1453[     ]+fsgnjn\.q[    ]+s0,s4,s8
> +[      ]+[0-9a-f]+:[   ]+278a2453[     ]+fsgnjx\.q[    ]+s0,s4,s8
> +[      ]+[0-9a-f]+:[   ]+a78a25d3[     ]+feq\.q[       ]+a1,s4,s8
> +[      ]+[0-9a-f]+:[   ]+a78a15d3[     ]+flt\.q[       ]+a1,s4,s8
> +[      ]+[0-9a-f]+:[   ]+a78a05d3[     ]+fle\.q[       ]+a1,s4,s8
> +[      ]+[0-9a-f]+:[   ]+a74c15d3[     ]+flt\.q[       ]+a1,s8,s4
> +[      ]+[0-9a-f]+:[   ]+a74c05d3[     ]+fle\.q[       ]+a1,s8,s4
> +[      ]+[0-9a-f]+:[   ]+274a0453[     ]+fmv\.q[       ]+s0,s4
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zqinx-rv32.s
> @@ -0,0 +1,54 @@
> +target:
> +       fadd.q          s0, s4, s8
> +       fadd.q          s0, s4, s8, rne
> +       fsub.q          s0, s4, s8
> +       fsub.q          s0, s4, s8, rne
> +       fmul.q          s0, s4, s8
> +       fmul.q          s0, s4, s8, rne
> +       fdiv.q          s0, s4, s8
> +       fdiv.q          s0, s4, s8, rne
> +       fsqrt.q         s0, s4
> +       fsqrt.q         s0, s4, rne
> +       fmin.q          s0, s4, s8
> +       fmax.q          s0, s4, s8
> +       fmadd.q         s0, s4, s8, a2
> +       fmadd.q         s0, s4, s8, a2, rne
> +       fnmadd.q        s0, s4, s8, a2
> +       fnmadd.q        s0, s4, s8, a2, rne
> +       fmsub.q         s0, s4, s8, a2
> +       fmsub.q         s0, s4, s8, a2, rne
> +       fnmsub.q        s0, s4, s8, a2
> +       fnmsub.q        s0, s4, s8, a2, rne
> +
> +       fcvt.w.q        a1, s4
> +       fcvt.w.q        a1, s4, rne
> +       fcvt.wu.q       a1, s4
> +       fcvt.wu.q       a1, s4, rne
> +       fcvt.q.w        s0, a1
> +       fcvt.q.wu       s0, a1
> +
> +       fcvt.q.s        s0, a1
> +       fcvt.s.q        a1, s4
> +       fcvt.s.q        a1, s4, rne
> +
> +       fcvt.q.d        s0, a0
> +       fcvt.d.q        a0, s4
> +       fcvt.d.q        a0, s4, rne
> +
> +       .option push
> +       .option arch, +zhinxmin
> +       fcvt.q.h        s0, a1
> +       fcvt.h.q        a1, s4
> +       fcvt.h.q        a1, s4, rne
> +       .option pop
> +
> +       fsgnj.q         s0, s4, s8
> +       fsgnjn.q        s0, s4, s8
> +       fsgnjx.q        s0, s4, s8
> +       feq.q           a1, s4, s8
> +       flt.q           a1, s4, s8
> +       fle.q           a1, s4, s8
> +       fgt.q           a1, s4, s8
> +       fge.q           a1, s4, s8
> +
> +       fmv.q           s0, s4
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zqinx-rv32-fail.d
> @@ -0,0 +1,3 @@
> +#as: -march=rv32i_zqinx
> +#source: zqinx.s
> +#error_output: zqinx-rv32-fail.l
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zqinx-rv32-fail.l
> @@ -0,0 +1,42 @@
> +.*: Assembler messages:
> +.*: Error: illegal operands `fadd\.q .*'
> +.*: Error: illegal operands `fadd\.q .*'
> +.*: Error: illegal operands `fsub\.q .*'
> +.*: Error: illegal operands `fsub\.q .*'
> +.*: Error: illegal operands `fmul\.q .*'
> +.*: Error: illegal operands `fmul\.q .*'
> +.*: Error: illegal operands `fdiv\.q .*'
> +.*: Error: illegal operands `fdiv\.q .*'
> +.*: Error: illegal operands `fsqrt\.q .*'
> +.*: Error: illegal operands `fsqrt\.q .*'
> +.*: Error: illegal operands `fmin\.q .*'
> +.*: Error: illegal operands `fmax\.q .*'
> +.*: Error: illegal operands `fmadd\.q .*'
> +.*: Error: illegal operands `fmadd\.q .*'
> +.*: Error: illegal operands `fnmadd\.q .*'
> +.*: Error: illegal operands `fnmadd\.q .*'
> +.*: Error: illegal operands `fmsub\.q .*'
> +.*: Error: illegal operands `fmsub\.q .*'
> +.*: Error: illegal operands `fnmsub\.q .*'
> +.*: Error: illegal operands `fnmsub\.q .*'
> +.*: Error: unrecognized opcode `fcvt\.l\.q .*'
> +.*: Error: unrecognized opcode `fcvt\.l\.q .*'
> +.*: Error: unrecognized opcode `fcvt\.lu\.q .*'
> +.*: Error: unrecognized opcode `fcvt\.lu\.q .*'
> +.*: Error: illegal operands `fcvt\.q\.w .*'
> +.*: Error: illegal operands `fcvt\.q\.wu .*'
> +.*: Error: unrecognized opcode `fcvt\.q\.l .*'
> +.*: Error: unrecognized opcode `fcvt\.q\.lu .*'
> +.*: Error: illegal operands `fcvt\.q\.s .*'
> +.*: Error: illegal operands `fcvt\.q\.d .*'
> +.*: Error: illegal operands `fsgnj\.q .*'
> +.*: Error: illegal operands `fsgnjn\.q .*'
> +.*: Error: illegal operands `fsgnjx\.q .*'
> +.*: Error: illegal operands `feq\.q .*'
> +.*: Error: illegal operands `flt\.q .*'
> +.*: Error: illegal operands `fle\.q .*'
> +.*: Error: illegal operands `fgt\.q .*'
> +.*: Error: illegal operands `fge\.q .*'
> +.*: Error: illegal operands `fmv\.q .*'
> +.*: Error: illegal operands `fneg\.q .*'
> +.*: Error: illegal operands `fabs\.q .*'
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zqinx-rv64-fail.d
> @@ -0,0 +1,2 @@
> +#as: -march=rv64i_zqinx
> +#error_output: zqinx-rv64-fail.l
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zqinx-rv64-fail.l
> @@ -0,0 +1,62 @@
> +.*: Assembler messages:
> +.*: Error: illegal operands `fadd\.q .*'
> +.*: Error: illegal operands `fadd\.q .*'
> +.*: Error: illegal operands `fadd\.q .*'
> +.*: Error: illegal operands `fsub\.q .*'
> +.*: Error: illegal operands `fsub\.q .*'
> +.*: Error: illegal operands `fsub\.q .*'
> +.*: Error: illegal operands `fmul\.q .*'
> +.*: Error: illegal operands `fmul\.q .*'
> +.*: Error: illegal operands `fmul\.q .*'
> +.*: Error: illegal operands `fdiv\.q .*'
> +.*: Error: illegal operands `fdiv\.q .*'
> +.*: Error: illegal operands `fdiv\.q .*'
> +.*: Error: illegal operands `fsqrt\.q .*'
> +.*: Error: illegal operands `fsqrt\.q .*'
> +.*: Error: illegal operands `fmin\.q .*'
> +.*: Error: illegal operands `fmin\.q .*'
> +.*: Error: illegal operands `fmin\.q .*'
> +.*: Error: illegal operands `fmax\.q .*'
> +.*: Error: illegal operands `fmax\.q .*'
> +.*: Error: illegal operands `fmax\.q .*'
> +.*: Error: illegal operands `fmadd\.q .*'
> +.*: Error: illegal operands `fmadd\.q .*'
> +.*: Error: illegal operands `fmadd\.q .*'
> +.*: Error: illegal operands `fmadd\.q .*'
> +.*: Error: illegal operands `fnmadd\.q .*'
> +.*: Error: illegal operands `fnmadd\.q .*'
> +.*: Error: illegal operands `fnmadd\.q .*'
> +.*: Error: illegal operands `fnmadd\.q .*'
> +.*: Error: illegal operands `fmsub\.q .*'
> +.*: Error: illegal operands `fmsub\.q .*'
> +.*: Error: illegal operands `fmsub\.q .*'
> +.*: Error: illegal operands `fmsub\.q .*'
> +.*: Error: illegal operands `fnmsub\.q .*'
> +.*: Error: illegal operands `fnmsub\.q .*'
> +.*: Error: illegal operands `fnmsub\.q .*'
> +.*: Error: illegal operands `fnmsub\.q .*'
> +.*: Error: illegal operands `fcvt\.w\.q .*'
> +.*: Error: illegal operands `fcvt\.wu\.q .*'
> +.*: Error: illegal operands `fcvt\.q\.w .*'
> +.*: Error: illegal operands `fcvt\.q\.wu .*'
> +.*: Error: illegal operands `fcvt\.q\.s .*'
> +.*: Error: illegal operands `fcvt\.s\.q .*'
> +.*: Error: illegal operands `fcvt\.q\.d .*'
> +.*: Error: illegal operands `fcvt\.d\.q .*'
> +.*: Error: illegal operands `fcvt\.q\.h .*'
> +.*: Error: illegal operands `fcvt\.h\.q .*'
> +.*: Error: illegal operands `fsgnj\.q .*'
> +.*: Error: illegal operands `fsgnjn\.q .*'
> +.*: Error: illegal operands `fsgnjx\.q .*'
> +.*: Error: illegal operands `feq\.q .*'
> +.*: Error: illegal operands `flt\.q .*'
> +.*: Error: illegal operands `fle\.q .*'
> +.*: Error: illegal operands `fgt\.q .*'
> +.*: Error: illegal operands `fge\.q .*'
> +.*: Error: illegal operands `fmv\.q .*'
> +.*: Error: illegal operands `fmv\.q .*'
> +.*: Error: illegal operands `fneg\.q .*'
> +.*: Error: illegal operands `fneg\.q .*'
> +.*: Error: illegal operands `fabs\.q .*'
> +.*: Error: illegal operands `fabs\.q .*'
> +.*: Error: illegal operands `fclass\.q .*'
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zqinx-rv64-fail.s
> @@ -0,0 +1,70 @@
> +target:
> +       fadd.q          s1, s4, s8
> +       fadd.q          s0, s5, s8
> +       fadd.q          s0, s4, s9
> +       fsub.q          s1, s4, s8
> +       fsub.q          s0, s5, s8
> +       fsub.q          s0, s4, s9
> +       fmul.q          s1, s4, s8
> +       fmul.q          s0, s5, s8
> +       fmul.q          s0, s4, s9
> +       fdiv.q          s1, s4, s8
> +       fdiv.q          s0, s5, s8
> +       fdiv.q          s0, s4, s9
> +       fsqrt.q         s1, s4
> +       fsqrt.q         s0, s5
> +       fmin.q          s1, s4, s8
> +       fmin.q          s0, s5, s8
> +       fmin.q          s0, s4, s9
> +       fmax.q          s1, s4, s8
> +       fmax.q          s0, s5, s8
> +       fmax.q          s0, s4, s9
> +       fmadd.q         s1, s4, s8, a2
> +       fmadd.q         s0, s5, s8, a2
> +       fmadd.q         s0, s4, s9, a2
> +       fmadd.q         s0, s4, s8, a3
> +       fnmadd.q        s1, s4, s8, a2
> +       fnmadd.q        s0, s5, s8, a2
> +       fnmadd.q        s0, s4, s9, a2
> +       fnmadd.q        s0, s4, s8, a3
> +       fmsub.q         s1, s4, s8, a2
> +       fmsub.q         s0, s5, s8, a2
> +       fmsub.q         s0, s4, s9, a2
> +       fmsub.q         s0, s4, s8, a3
> +       fnmsub.q        s1, s4, s8, a2
> +       fnmsub.q        s0, s5, s8, a2
> +       fnmsub.q        s0, s4, s9, a2
> +       fnmsub.q        s0, s4, s8, a3
> +
> +       fcvt.w.q        a0, s5
> +       fcvt.wu.q       a0, s5
> +       fcvt.q.w        s1, a0
> +       fcvt.q.wu       s1, a0
> +
> +       fcvt.q.s        s1, a0
> +       fcvt.s.q        a0, s5
> +
> +       fcvt.q.d        s1, a0
> +       fcvt.d.q        a0, s5
> +
> +       .option push
> +       .option arch, +zhinxmin
> +       fcvt.q.h        s1, a0
> +       fcvt.h.q        a0, s5
> +       .option pop
> +
> +       fsgnj.q         s1, s4, s8
> +       fsgnjn.q        s0, s5, s8
> +       fsgnjx.q        s0, s4, s9
> +       feq.q           a0, s5, s8
> +       flt.q           a0, s4, s9
> +       fle.q           a0, s5, s8
> +       fgt.q           a0, s4, s9
> +       fge.q           a0, s5, s8
> +       fmv.q           s1, s4
> +       fmv.q           s0, s5
> +       fneg.q          s1, s4
> +       fneg.q          s0, s5
> +       fabs.q          s1, s4
> +       fabs.q          s0, s5
> +       fclass.q        a0, s5
> --- a/include/opcode/riscv.h
> +++ b/include/opcode/riscv.h
> @@ -721,6 +721,19 @@ struct riscv_opcode
>  #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)
>
> +/* Operands required to be an even-numbered register (pair) in RV64, and one
> +   divisible by 4 on RV32.  */
> +#define INSN_RV64_EVEN_D       0x00001000
> +#define INSN_RV64_EVEN_S       0x00002000
> +#define INSN_RV64_EVEN_T       0x00004000 /* Also covering U.  */
> +#define INSN_RV64_EVEN_R       0x00008000
> +/* Shorthands for combinations of the above.  */
> +#define INSN_RV64_EVEN_DS      (INSN_RV64_EVEN_D   | INSN_RV64_EVEN_S)
> +#define INSN_RV64_EVEN_DST     (INSN_RV64_EVEN_DS  | INSN_RV64_EVEN_T)
> +#define INSN_RV64_EVEN_DSTR    (INSN_RV64_EVEN_DST | INSN_RV64_EVEN_R)
> +#define INSN_RV64_EVEN_DU      (INSN_RV64_EVEN_D   | INSN_RV64_EVEN_T)
> +#define INSN_RV64_EVEN_ST      (INSN_RV64_EVEN_S   | INSN_RV64_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
> @@ -1155,6 +1155,25 @@ riscv_disassemble_insn (bfd_vma memaddr,
>                       && (word & (1u << OP_SH_RS3)))
>                     continue;
>                 }
> +
> +             if (pd->xlen <= 64
> +                 && riscv_subset_supports (&pd->riscv_rps_dis, "zqinx"))
> +               {
> +                 unsigned int mask = pd->xlen == 32 ? 3 : 1;
> +
> +                 if ((op->pinfo & INSN_RV64_EVEN_D)
> +                     && (word & (mask << OP_SH_RD)))
> +                   continue;
> +                 if ((op->pinfo & INSN_RV64_EVEN_S)
> +                     && (word & (mask << OP_SH_RS1)))
> +                   continue;
> +                 if ((op->pinfo & INSN_RV64_EVEN_T)
> +                     && (word & (mask << OP_SH_RS2)))
> +                   continue;
> +                 if ((op->pinfo & INSN_RV64_EVEN_R)
> +                     && (word & (mask << OP_SH_RS3)))
> +                   continue;
> +               }
>             }
>
>           /* It's a match.  */
> --- a/opcodes/riscv-opc.c
> +++ b/opcodes/riscv-opc.c
> @@ -956,10 +956,10 @@ const struct riscv_opcode riscv_opcodes[
>  {"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, 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.q.h",   0, INSN_CLASS_ZFHMIN_AND_Q_INX, "D,S", MATCH_FCVT_Q_H, MASK_FCVT_Q_H|MASK_RM, match_opcode, INSN_RV64_EVEN_D },
>  {"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, 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 },
> +{"fcvt.h.q",   0, INSN_CLASS_ZFHMIN_AND_Q_INX, "D,Sm", MATCH_FCVT_H_Q, MASK_FCVT_H_Q, match_opcode, INSN_RV64_EVEN_S },
>  {"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 },
>  {"flt.h",      0, INSN_CLASS_ZFH_INX,   "d,S,T",     MATCH_FLT_H, MASK_FLT_H, match_opcode, 0 },
> @@ -1086,41 +1086,41 @@ const struct riscv_opcode riscv_opcodes[
>  {"flq",        0, INSN_CLASS_Q,   "D,A,s",     0, (int) M_FLx, match_rs1_nonzero, INSN_MACRO },
>  {"fsq",        0, INSN_CLASS_Q,   "T,q(s)",    MATCH_FSQ, MASK_FSQ, match_opcode, INSN_DREF|INSN_16_BYTE },
>  {"fsq",        0, INSN_CLASS_Q,   "T,A,s",     0, (int) M_Sx_FSx, match_rs1_nonzero, INSN_MACRO },
> -{"fmv.q",      0, INSN_CLASS_Q_INX,   "D,U",       MATCH_FSGNJ_Q, MASK_FSGNJ_Q, match_rs1_eq_rs2, INSN_ALIAS },
> -{"fneg.q",     0, INSN_CLASS_Q_INX,   "D,U",       MATCH_FSGNJN_Q, MASK_FSGNJN_Q, match_rs1_eq_rs2, INSN_ALIAS },
> -{"fabs.q",     0, INSN_CLASS_Q_INX,   "D,U",       MATCH_FSGNJX_Q, MASK_FSGNJX_Q, match_rs1_eq_rs2, INSN_ALIAS },
> -{"fsgnj.q",    0, INSN_CLASS_Q_INX,   "D,S,T",     MATCH_FSGNJ_Q, MASK_FSGNJ_Q, match_opcode, 0 },
> -{"fsgnjn.q",   0, INSN_CLASS_Q_INX,   "D,S,T",     MATCH_FSGNJN_Q, MASK_FSGNJN_Q, match_opcode, 0 },
> -{"fsgnjx.q",   0, INSN_CLASS_Q_INX,   "D,S,T",     MATCH_FSGNJX_Q, MASK_FSGNJX_Q, match_opcode, 0 },
> -{"fadd.q",     0, INSN_CLASS_Q_INX,   "D,S,Tm",    MATCH_FADD_Q, MASK_FADD_Q, match_opcode, 0 },
> -{"fsub.q",     0, INSN_CLASS_Q_INX,   "D,S,Tm",    MATCH_FSUB_Q, MASK_FSUB_Q, match_opcode, 0 },
> -{"fmul.q",     0, INSN_CLASS_Q_INX,   "D,S,Tm",    MATCH_FMUL_Q, MASK_FMUL_Q, match_opcode, 0 },
> -{"fdiv.q",     0, INSN_CLASS_Q_INX,   "D,S,Tm",    MATCH_FDIV_Q, MASK_FDIV_Q, match_opcode, 0 },
> -{"fsqrt.q",    0, INSN_CLASS_Q_INX,   "D,Sm",      MATCH_FSQRT_Q, MASK_FSQRT_Q, match_opcode, 0 },
> -{"fmin.q",     0, INSN_CLASS_Q_INX,   "D,S,T",     MATCH_FMIN_Q, MASK_FMIN_Q, match_opcode, 0 },
> -{"fmax.q",     0, INSN_CLASS_Q_INX,   "D,S,T",     MATCH_FMAX_Q, MASK_FMAX_Q, match_opcode, 0 },
> -{"fmadd.q",    0, INSN_CLASS_Q_INX,   "D,S,T,Rm",  MATCH_FMADD_Q, MASK_FMADD_Q, match_opcode, 0 },
> -{"fnmadd.q",   0, INSN_CLASS_Q_INX,   "D,S,T,Rm",  MATCH_FNMADD_Q, MASK_FNMADD_Q, match_opcode, 0 },
> -{"fmsub.q",    0, INSN_CLASS_Q_INX,   "D,S,T,Rm",  MATCH_FMSUB_Q, MASK_FMSUB_Q, match_opcode, 0 },
> -{"fnmsub.q",   0, INSN_CLASS_Q_INX,   "D,S,T,Rm",  MATCH_FNMSUB_Q, MASK_FNMSUB_Q, match_opcode, 0 },
> -{"fcvt.w.q",   0, INSN_CLASS_Q_INX,   "d,Sm",      MATCH_FCVT_W_Q, MASK_FCVT_W_Q, match_opcode, 0 },
> -{"fcvt.wu.q",  0, INSN_CLASS_Q_INX,   "d,Sm",      MATCH_FCVT_WU_Q, MASK_FCVT_WU_Q, match_opcode, 0 },
> -{"fcvt.q.w",   0, INSN_CLASS_Q_INX,   "D,s",       MATCH_FCVT_Q_W, MASK_FCVT_Q_W|MASK_RM, match_opcode, 0 },
> -{"fcvt.q.wu",  0, INSN_CLASS_Q_INX,   "D,s",       MATCH_FCVT_Q_WU, MASK_FCVT_Q_WU|MASK_RM, match_opcode, 0 },
> -{"fcvt.q.s",   0, INSN_CLASS_Q_INX,   "D,S",       MATCH_FCVT_Q_S, MASK_FCVT_Q_S|MASK_RM, match_opcode, 0 },
> -{"fcvt.q.d",   0, INSN_CLASS_Q_INX,   "D,S",       MATCH_FCVT_Q_D, MASK_FCVT_Q_D|MASK_RM, match_opcode, 0 },
> -{"fcvt.s.q",   0, INSN_CLASS_Q_INX,   "D,Sm",      MATCH_FCVT_S_Q, MASK_FCVT_S_Q, match_opcode, 0 },
> -{"fcvt.d.q",   0, INSN_CLASS_Q_INX,   "D,Sm",      MATCH_FCVT_D_Q, MASK_FCVT_D_Q, match_opcode, 0 },
> -{"fclass.q",   0, INSN_CLASS_Q_INX,   "d,S",       MATCH_FCLASS_Q, MASK_FCLASS_Q, match_opcode, 0 },
> -{"feq.q",      0, INSN_CLASS_Q_INX,   "d,S,T",     MATCH_FEQ_Q, MASK_FEQ_Q, match_opcode, 0 },
> -{"flt.q",      0, INSN_CLASS_Q_INX,   "d,S,T",     MATCH_FLT_Q, MASK_FLT_Q, match_opcode, 0 },
> -{"fle.q",      0, INSN_CLASS_Q_INX,   "d,S,T",     MATCH_FLE_Q, MASK_FLE_Q, match_opcode, 0 },
> -{"fgt.q",      0, INSN_CLASS_Q_INX,   "d,T,S",     MATCH_FLT_Q, MASK_FLT_Q, match_opcode, INSN_ALIAS },
> -{"fge.q",      0, INSN_CLASS_Q_INX,   "d,T,S",     MATCH_FLE_Q, MASK_FLE_Q, match_opcode, INSN_ALIAS },
> -{"fcvt.l.q",  64, INSN_CLASS_Q_INX,   "d,Sm",      MATCH_FCVT_L_Q, MASK_FCVT_L_Q, match_opcode, 0 },
> -{"fcvt.lu.q", 64, INSN_CLASS_Q_INX,   "d,Sm",      MATCH_FCVT_LU_Q, MASK_FCVT_LU_Q, match_opcode, 0 },
> -{"fcvt.q.l",  64, INSN_CLASS_Q_INX,   "D,s",       MATCH_FCVT_Q_L, MASK_FCVT_Q_L|MASK_RM, match_opcode, 0 },
> -{"fcvt.q.lu", 64, INSN_CLASS_Q_INX,   "D,s",       MATCH_FCVT_Q_LU, MASK_FCVT_Q_LU|MASK_RM, match_opcode, 0 },
> +{"fmv.q",      0, INSN_CLASS_Q_INX,   "D,U",       MATCH_FSGNJ_Q, MASK_FSGNJ_Q, match_rs1_eq_rs2, INSN_ALIAS|INSN_RV64_EVEN_DU },
> +{"fneg.q",     0, INSN_CLASS_Q_INX,   "D,U",       MATCH_FSGNJN_Q, MASK_FSGNJN_Q, match_rs1_eq_rs2, INSN_ALIAS|INSN_RV64_EVEN_DU },
> +{"fabs.q",     0, INSN_CLASS_Q_INX,   "D,U",       MATCH_FSGNJX_Q, MASK_FSGNJX_Q, match_rs1_eq_rs2, INSN_ALIAS|INSN_RV64_EVEN_DU },
> +{"fsgnj.q",    0, INSN_CLASS_Q_INX,   "D,S,T",     MATCH_FSGNJ_Q, MASK_FSGNJ_Q, match_opcode, INSN_RV64_EVEN_DST },
> +{"fsgnjn.q",   0, INSN_CLASS_Q_INX,   "D,S,T",     MATCH_FSGNJN_Q, MASK_FSGNJN_Q, match_opcode, INSN_RV64_EVEN_DST },
> +{"fsgnjx.q",   0, INSN_CLASS_Q_INX,   "D,S,T",     MATCH_FSGNJX_Q, MASK_FSGNJX_Q, match_opcode, INSN_RV64_EVEN_DST },
> +{"fadd.q",     0, INSN_CLASS_Q_INX,   "D,S,Tm",    MATCH_FADD_Q, MASK_FADD_Q, match_opcode, INSN_RV64_EVEN_DST },
> +{"fsub.q",     0, INSN_CLASS_Q_INX,   "D,S,Tm",    MATCH_FSUB_Q, MASK_FSUB_Q, match_opcode, INSN_RV64_EVEN_DST },
> +{"fmul.q",     0, INSN_CLASS_Q_INX,   "D,S,Tm",    MATCH_FMUL_Q, MASK_FMUL_Q, match_opcode, INSN_RV64_EVEN_DST },
> +{"fdiv.q",     0, INSN_CLASS_Q_INX,   "D,S,Tm",    MATCH_FDIV_Q, MASK_FDIV_Q, match_opcode, INSN_RV64_EVEN_DST },
> +{"fsqrt.q",    0, INSN_CLASS_Q_INX,   "D,Sm",      MATCH_FSQRT_Q, MASK_FSQRT_Q, match_opcode, INSN_RV64_EVEN_DS },
> +{"fmin.q",     0, INSN_CLASS_Q_INX,   "D,S,T",     MATCH_FMIN_Q, MASK_FMIN_Q, match_opcode, INSN_RV64_EVEN_DST },
> +{"fmax.q",     0, INSN_CLASS_Q_INX,   "D,S,T",     MATCH_FMAX_Q, MASK_FMAX_Q, match_opcode, INSN_RV64_EVEN_DST },
> +{"fmadd.q",    0, INSN_CLASS_Q_INX,   "D,S,T,Rm",  MATCH_FMADD_Q, MASK_FMADD_Q, match_opcode, INSN_RV64_EVEN_DSTR },
> +{"fnmadd.q",   0, INSN_CLASS_Q_INX,   "D,S,T,Rm",  MATCH_FNMADD_Q, MASK_FNMADD_Q, match_opcode, INSN_RV64_EVEN_DSTR },
> +{"fmsub.q",    0, INSN_CLASS_Q_INX,   "D,S,T,Rm",  MATCH_FMSUB_Q, MASK_FMSUB_Q, match_opcode, INSN_RV64_EVEN_DSTR },
> +{"fnmsub.q",   0, INSN_CLASS_Q_INX,   "D,S,T,Rm",  MATCH_FNMSUB_Q, MASK_FNMSUB_Q, match_opcode, INSN_RV64_EVEN_DSTR },
> +{"fcvt.w.q",   0, INSN_CLASS_Q_INX,   "d,Sm",      MATCH_FCVT_W_Q, MASK_FCVT_W_Q, match_opcode, INSN_RV64_EVEN_S },
> +{"fcvt.wu.q",  0, INSN_CLASS_Q_INX,   "d,Sm",      MATCH_FCVT_WU_Q, MASK_FCVT_WU_Q, match_opcode, INSN_RV64_EVEN_S },
> +{"fcvt.q.w",   0, INSN_CLASS_Q_INX,   "D,s",       MATCH_FCVT_Q_W, MASK_FCVT_Q_W|MASK_RM, match_opcode, INSN_RV64_EVEN_D },
> +{"fcvt.q.wu",  0, INSN_CLASS_Q_INX,   "D,s",       MATCH_FCVT_Q_WU, MASK_FCVT_Q_WU|MASK_RM, match_opcode, INSN_RV64_EVEN_D },
> +{"fcvt.q.s",   0, INSN_CLASS_Q_INX,   "D,S",       MATCH_FCVT_Q_S, MASK_FCVT_Q_S|MASK_RM, match_opcode, INSN_RV64_EVEN_D },
> +{"fcvt.q.d",   0, INSN_CLASS_Q_INX,   "D,S",       MATCH_FCVT_Q_D, MASK_FCVT_Q_D|MASK_RM, match_opcode, INSN_RV64_EVEN_D|INSN_RV32_EVEN_S },
> +{"fcvt.s.q",   0, INSN_CLASS_Q_INX,   "D,Sm",      MATCH_FCVT_S_Q, MASK_FCVT_S_Q, match_opcode, INSN_RV64_EVEN_S },
> +{"fcvt.d.q",   0, INSN_CLASS_Q_INX,   "D,Sm",      MATCH_FCVT_D_Q, MASK_FCVT_D_Q, match_opcode, INSN_RV32_EVEN_D|INSN_RV64_EVEN_S },
> +{"fclass.q",   0, INSN_CLASS_Q_INX,   "d,S",       MATCH_FCLASS_Q, MASK_FCLASS_Q, match_opcode, INSN_RV64_EVEN_S },
> +{"feq.q",      0, INSN_CLASS_Q_INX,   "d,S,T",     MATCH_FEQ_Q, MASK_FEQ_Q, match_opcode, INSN_RV64_EVEN_ST },
> +{"flt.q",      0, INSN_CLASS_Q_INX,   "d,S,T",     MATCH_FLT_Q, MASK_FLT_Q, match_opcode, INSN_RV64_EVEN_ST },
> +{"fle.q",      0, INSN_CLASS_Q_INX,   "d,S,T",     MATCH_FLE_Q, MASK_FLE_Q, match_opcode, INSN_RV64_EVEN_ST },
> +{"fgt.q",      0, INSN_CLASS_Q_INX,   "d,T,S",     MATCH_FLT_Q, MASK_FLT_Q, match_opcode, INSN_ALIAS|INSN_RV64_EVEN_ST },
> +{"fge.q",      0, INSN_CLASS_Q_INX,   "d,T,S",     MATCH_FLE_Q, MASK_FLE_Q, match_opcode, INSN_ALIAS|INSN_RV64_EVEN_ST },
> +{"fcvt.l.q",  64, INSN_CLASS_Q_INX,   "d,Sm",      MATCH_FCVT_L_Q, MASK_FCVT_L_Q, match_opcode, INSN_RV64_EVEN_S },
> +{"fcvt.lu.q", 64, INSN_CLASS_Q_INX,   "d,Sm",      MATCH_FCVT_LU_Q, MASK_FCVT_LU_Q, match_opcode, INSN_RV64_EVEN_S },
> +{"fcvt.q.l",  64, INSN_CLASS_Q_INX,   "D,s",       MATCH_FCVT_Q_L, MASK_FCVT_Q_L|MASK_RM, match_opcode, INSN_RV64_EVEN_D },
> +{"fcvt.q.lu", 64, INSN_CLASS_Q_INX,   "D,s",       MATCH_FCVT_Q_LU, MASK_FCVT_Q_LU|MASK_RM, match_opcode, INSN_RV64_EVEN_D },
>
>  /* Compressed instructions.  */
>  {"c.unimp",    0, INSN_CLASS_ZCA,   "",          0, 0xffffU,  match_opcode, 0 },
>