[v4,07/12] RISC-V: check operands for Zqinx
Checks
| Context |
Check |
Description |
| linaro-tcwg-bot/tcwg_binutils_build--master-arm |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_binutils_check--master-arm |
success
|
Test passed
|
| linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 |
success
|
Test passed
|
Commit Message
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.
---
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).
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.
Comments
On Fri, Jul 24, 2026 at 6:04 PM Jan Beulich <jbeulich@suse.com> 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 },
>
On 27.07.2026 05:15, Nelson Chu wrote:
> On Fri, Jul 24, 2026 at 6:04 PM Jan Beulich <jbeulich@suse.com> wrote:
>> ---
>> 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?
May I put the question a little differently: Shouldn't there be at least
a semi-official spec for Zqinx, which would then address the question
above?
Jan
@@ -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. */
@@ -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
@@ -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
@@ -0,0 +1,3 @@
+#as: -march=rv32i_zqinx
+#source: zqinx.s
+#error_output: 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 .*'
@@ -0,0 +1,2 @@
+#as: -march=rv64i_zqinx
+#error_output: 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 .*'
@@ -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
@@ -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
@@ -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. */
@@ -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 },