LGTM.
At 2026/6/5 17:30, Jan Beulich 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.
> ---
> 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.)
> ---
> v2: New.
There may be some niche use cases in embedded systems, but I do not have
strong evidence that Zqinx is widely used.
Given the lack of a formal specification, I agree that we should be
conservative here. If binutils continues to recognize Zqinx, then the
operand checks should at least be consistent with the natural register
grouping rules. Otherwise, treating Zqinx support as incomplete and avoiding
further assumptions also sounds reasonable to me.
One small typo nit in riscv.h comment:
divisble -> divisible
Best regard,
Jiawei
>
> --- a/gas/config/tc-riscv.c
> +++ b/gas/config/tc-riscv.c
> @@ -2934,6 +2934,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;
> @@ -3593,12 +3599,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;
> @@ -3606,12 +3614,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;
> @@ -4312,6 +4322,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
> @@ -691,6 +691,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
> + divisble 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
> @@ -1049,6 +1049,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
> @@ -932,10 +932,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 },
> @@ -1062,41 +1062,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 },
@@ -2934,6 +2934,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;
@@ -3593,12 +3599,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;
@@ -3606,12 +3614,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;
@@ -4312,6 +4322,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
@@ -691,6 +691,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
+ divisble 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
@@ -1049,6 +1049,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. */
@@ -932,10 +932,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 },
@@ -1062,41 +1062,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 },