[PATCH v2 5/9] Implement dest-register compatibility checks for the MIPS Allegrex VFPU regs.
David Guillen Fandos
david@davidgf.net
Tue Jan 20 23:32:13 GMT 2026
Some VFPU instructions do not support certain overlaps between source and
destination registers. Return an error whenever the overlap is not acceptable
for a given instruction and register pair.
Add more VFPU vector instructions with prefix register overlap decorators.
Signed-off-by: David Guillen Fandos <david@davidgf.net>
---
gas/config/tc-mips.c | 80 ++++++++++++++++++-
gas/testsuite/gas/mips/allegrex-vfpu-errors.l | 38 +++++++++
gas/testsuite/gas/mips/allegrex-vfpu-errors.s | 39 +++++++++
gas/testsuite/gas/mips/allegrex-vfpu.d | 51 ++++++++++++
gas/testsuite/gas/mips/allegrex-vfpu.s | 52 ++++++++++++
include/opcode/mips.h | 19 ++++-
opcodes/mips-formats.h | 30 ++++---
opcodes/mips-opc.c | 63 ++++++++++++++-
8 files changed, 353 insertions(+), 19 deletions(-)
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 930edceb6ec..79afc9fc9b1 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -106,7 +106,7 @@ static char *mips_flags_frag;
#define FCSR 31
-#define ILLEGAL_REG (32)
+#define ILLEGAL_REG (~0U)
#define AT mips_opts.at
@@ -6819,6 +6819,52 @@ match_vu0_suffix_operand (struct mips_arg_info *arg,
return true;
}
+/* Returns whether a pair of dest/src registers are compatible. */
+static bfd_boolean
+vfpu_reg_is_compat (unsigned int dst_reg, unsigned int dst_rsize,
+ unsigned int src_reg, unsigned int src_rsize,
+ bool accept_partial)
+{
+ static const unsigned short vreg_usage[4][16] = {
+ { 0x0001, 0x0010, 0x0100, 0x1000,
+ 0x0002, 0x0020, 0x0200, 0x2000,
+ 0x0004, 0x0040, 0x0400, 0x4000,
+ 0x0008, 0x0080, 0x0800, 0x8000 },
+ { 0x0003, 0x0030, 0x0300, 0x3000,
+ 0x0011, 0x0022, 0x0044, 0x0088,
+ 0x000c, 0x00c0, 0x0c00, 0xc000,
+ 0x1100, 0x2200, 0x4400, 0x8800 },
+ { 0x0007, 0x0070, 0x0700, 0x7000,
+ 0x0111, 0x0222, 0x0444, 0x0888,
+ 0x000e, 0x00e0, 0x0e00, 0xe000,
+ 0x1110, 0x2220, 0x4440, 0x8880 },
+ { 0x000f, 0x00f0, 0x0f00, 0xf000,
+ 0x1111, 0x2222, 0x4444, 0x8888,
+ 0x000f, 0x00f0, 0x0f00, 0xf000,
+ 0x1111, 0x2222, 0x4444, 0x8888 },
+ };
+
+ unsigned int dmtx = (dst_reg >> 2) & 7;
+ unsigned int smtx = (src_reg >> 2) & 7;
+ if (dmtx == smtx)
+ {
+ unsigned int sidx = src_reg & 3;
+ unsigned int didx = dst_reg & 3;
+ unsigned int sfsl = (src_reg >> 5) & 3;
+ unsigned int dfsl = (dst_reg >> 5) & 3;
+ unsigned int dmap = vreg_usage[dst_rsize][(dfsl << 2) | didx];
+ unsigned int smap = vreg_usage[src_rsize][(sfsl << 2) | sidx];
+
+ if (dmap & smap) {
+ /* There's overlap, if partial is allowed, check for compatibility. */
+ return (accept_partial && dmap == smap
+ && ((src_reg & 0x32) == (dst_reg & 0x32)));
+ }
+ }
+ return true;
+}
+
+
/* Generates a VFPU prefix immediate for a given reg type and size. */
static bfd_boolean
calculate_vfpu_prefix_imm (struct mips_arg_info *arg,
@@ -6915,6 +6961,7 @@ match_vfpu_reg_operand (struct mips_arg_info *arg,
{
const struct mips_vfpu_reg_operand *regvfpuop;
enum mips_vfpu_reg_shape rshape;
+ enum mips_vfpu_reg_type rtype;
unsigned int uval = arg->token->u.reg_vfpu.regno;
/* Validate register type, to ensure we use the right register prefix */
@@ -6931,8 +6978,9 @@ match_vfpu_reg_operand (struct mips_arg_info *arg,
if (arg->token->type != OT_REG_VFPU || uval >= 128)
return false;
- rshape = arg->token->u.reg_vfpu.shape;
regvfpuop = (struct mips_vfpu_reg_operand*)operand;
+ rshape = arg->token->u.reg_vfpu.shape;
+ rtype = regvfpuop->regtype;
if (rshape != val_shap[regvfpuop->rsize].gen &&
rshape != val_shap[regvfpuop->rsize].spc)
@@ -6943,6 +6991,31 @@ match_vfpu_reg_operand (struct mips_arg_info *arg,
return false;
}
+ if (rtype == OP_VFPU_REG_D && regvfpuop->regcompat != OP_VFPU_REGCOMPAT_ALL)
+ {
+ arg->dest_regno = uval | (regvfpuop->rsize << 8);
+ if (regvfpuop->regcompat == OP_VFPU_REGCOMPAT_SAME)
+ arg->dest_regno |= 0x8000;
+ }
+
+ if ((rtype == OP_VFPU_REG_S || rtype == OP_VFPU_REG_T)
+ && (arg->dest_regno != ILLEGAL_REG))
+ {
+ /* The destination register could be incompatible with source regs. */
+ unsigned int dreg = arg->dest_regno & 0x7f;
+ unsigned int drsize = (arg->dest_regno >> 8) & 3;
+ bool canpartial = arg->dest_regno & 0x8000;
+
+ if (!vfpu_reg_is_compat (dreg, drsize, uval, regvfpuop->rsize, canpartial))
+ {
+ set_insn_error_ss(arg->argnum,
+ "Invalid dest and %s register overlap (%s is allowed)",
+ rtype == OP_VFPU_REG_S ? "source" : "target",
+ canpartial ? "identical overlap" : "no overlap");
+ return false;
+ }
+ }
+
insn_insert_operand (arg->insn, operand, uval);
++arg->token;
@@ -6954,7 +7027,6 @@ match_vfpu_reg_operand (struct mips_arg_info *arg,
struct mips_opcode *pop;
bfd_reloc_code_real_type unused_reloc[3]
= {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
- enum mips_vfpu_reg_type rtype = regvfpuop->regtype;
const char *pfxmemo = rtype == OP_VFPU_REG_S ? "vpfxs" :
rtype == OP_VFPU_REG_T ? "vpfxt" : "vpfxd";
@@ -6977,7 +7049,7 @@ match_vfpu_reg_operand (struct mips_arg_info *arg,
pop = (struct mips_opcode *) str_hash_find (op_hash, pfxmemo);
create_insn (&pfxinstr, pop);
- if (!calculate_vfpu_prefix_imm (arg, regvfpuop->regtype, regvfpuop->rsize,
+ if (!calculate_vfpu_prefix_imm (arg, rtype, regvfpuop->rsize,
pfx_lim, &imm24))
return false;
diff --git a/gas/testsuite/gas/mips/allegrex-vfpu-errors.l b/gas/testsuite/gas/mips/allegrex-vfpu-errors.l
index 497e7f8aed6..0c113567857 100644
--- a/gas/testsuite/gas/mips/allegrex-vfpu-errors.l
+++ b/gas/testsuite/gas/mips/allegrex-vfpu-errors.l
@@ -20,3 +20,41 @@
.*:22: Error: invalid source prefix \(only swizzle allowed\) `vabs.q R000,R000\[0,x,x,x\]'
.*:23: Error: invalid source prefix \(only swizzle allowed\) `vneg.q R000,R000\[0,x,x,x\]'
.*:24: Error: invalid source prefix \(only swizzle allowed\) `vt4444.q R000,R000\[-x,x,x,x\]'
+.*:25: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vsin.p C000,R000'
+.*:26: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vsin.t R000,R010'
+.*:27: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vsin.q C000,R000'
+.*:28: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vasin.p C100,R100'
+.*:29: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vasin.t R100,R110'
+.*:30: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vasin.q C100,R100'
+.*:31: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vnsin.p C200,R200'
+.*:32: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vnsin.t R200,R210'
+.*:33: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vnsin.q C200,R200'
+.*:34: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vcos.p C700,R700'
+.*:35: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vcos.t R700,R710'
+.*:36: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vcos.q C700,R700'
+.*:37: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vrcp.p C600,R600'
+.*:38: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vrcp.t R600,R610'
+.*:39: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vrcp.q C600,R600'
+.*:40: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vrsq.p C000,R000'
+.*:41: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vrsq.t R000,R010'
+.*:42: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vrsq.q C000,R000'
+.*:43: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vnrcp.p C000,R000'
+.*:44: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vnrcp.t R000,R010'
+.*:45: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vnrcp.q C000,R000'
+.*:46: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vexp2.p C000,R000'
+.*:47: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vexp2.t R000,R010'
+.*:48: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vexp2.q C000,R000'
+.*:49: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vrexp2.p C000,R000'
+.*:50: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vrexp2.t R000,R010'
+.*:51: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vrexp2.q C000,R000'
+.*:52: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vlog2.p C000,R000'
+.*:53: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vlog2.t R000,R010'
+.*:54: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vlog2.q C000,R000'
+.*:55: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vsqrt.p C000,R000'
+.*:56: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vsqrt.t R000,R010'
+.*:57: Error: Invalid dest and source register overlap \(identical overlap is allowed\) `vsqrt.q C000,R000'
+.*:58: Error: Invalid dest and target register overlap \(identical overlap is allowed\) `vdiv.p C000,C000,R000'
+.*:59: Error: Invalid dest and target register overlap \(identical overlap is allowed\) `vdiv.t C000,C000,R000'
+.*:60: Error: Invalid dest and target register overlap \(identical overlap is allowed\) `vdiv.q C000,C000,R000'
+.*:61: Error: Invalid dest and source register overlap \(no overlap is allowed\) `vcrsp.t R000,R000,R100'
+.*:62: Error: Invalid dest and source register overlap \(no overlap is allowed\) `vqmul.q R000,R000,R100'
diff --git a/gas/testsuite/gas/mips/allegrex-vfpu-errors.s b/gas/testsuite/gas/mips/allegrex-vfpu-errors.s
index 67024c61348..25193f0ac4a 100644
--- a/gas/testsuite/gas/mips/allegrex-vfpu-errors.s
+++ b/gas/testsuite/gas/mips/allegrex-vfpu-errors.s
@@ -22,6 +22,45 @@
vabs.q R000, R000[0,x,x,x]
vneg.q R000, R000[0,x,x,x]
vt4444.q R000, R000[-x,x,x,x]
+ vsin.p C000, R000
+ vsin.t R000, R010
+ vsin.q C000, R000
+ vasin.p C100, R100
+ vasin.t R100, R110
+ vasin.q C100, R100
+ vnsin.p C200, R200
+ vnsin.t R200, R210
+ vnsin.q C200, R200
+ vcos.p C700, R700
+ vcos.t R700, R710
+ vcos.q C700, R700
+ vrcp.p C600, R600
+ vrcp.t R600, R610
+ vrcp.q C600, R600
+ vrsq.p C000, R000
+ vrsq.t R000, R010
+ vrsq.q C000, R000
+ vnrcp.p C000, R000
+ vnrcp.t R000, R010
+ vnrcp.q C000, R000
+ vexp2.p C000, R000
+ vexp2.t R000, R010
+ vexp2.q C000, R000
+ vrexp2.p C000, R000
+ vrexp2.t R000, R010
+ vrexp2.q C000, R000
+ vlog2.p C000, R000
+ vlog2.t R000, R010
+ vlog2.q C000, R000
+ vsqrt.p C000, R000
+ vsqrt.t R000, R010
+ vsqrt.q C000, R000
+ vdiv.p C000, C000, R000
+ vdiv.t C000, C000, R000
+ vdiv.q C000, C000, R000
+ vcrsp.t R000, R000, R100
+ vqmul.q R000, R000, R100
+
# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
.align 4, 0
diff --git a/gas/testsuite/gas/mips/allegrex-vfpu.d b/gas/testsuite/gas/mips/allegrex-vfpu.d
index ce91768e006..277b65707f7 100644
--- a/gas/testsuite/gas/mips/allegrex-vfpu.d
+++ b/gas/testsuite/gas/mips/allegrex-vfpu.d
@@ -128,4 +128,55 @@ Disassembly of section .text:
0x000001dc de000100 vpfxd m,,,
0x000001e0 dc000050 vpfxs x,x,y,y
0x000001e4 d03ea0a0 vi2us.q R000.p,R000.q
+0x000001e8 d0171717 vasin.s S530.s,S530.s
+0x000001ec d01764e4 vasin.p R120.p,R120.p
+0x000001f0 d017e464 vasin.t R110.t,R110.t
+0x000001f4 d017a4a4 vasin.q R100.q,R100.q
+0x000001f8 d0131717 vcos.s S530.s,S530.s
+0x000001fc d01364e4 vcos.p R120.p,R120.p
+0x00000200 d013e464 vcos.t R110.t,R110.t
+0x00000204 d013a4a4 vcos.q R100.q,R100.q
+0x00000208 f2e6e564 vcrsp.t R110.t,R111.t,R112.t
+0x0000020c 6684a404 vcrs.t C100.t,R100.t,C100.t
+0x00000210 63971717 vdiv.s S530.s,S530.s,S530.s
+0x00000214 63e464e4 vdiv.p R120.p,R120.p,R120.p
+0x00000218 63e4e464 vdiv.t R110.t,R110.t,R110.t
+0x0000021c 63a4a4a4 vdiv.q R100.q,R100.q,R100.q
+0x00000220 d0141717 vexp2.s S530.s,S530.s
+0x00000224 d01464e4 vexp2.p R120.p,R120.p
+0x00000228 d014e464 vexp2.t R110.t,R110.t
+0x0000022c d014a4a4 vexp2.q R100.q,R100.q
+0x00000230 d0151717 vlog2.s S530.s,S530.s
+0x00000234 d01564e4 vlog2.p R120.p,R120.p
+0x00000238 d015e464 vlog2.t R110.t,R110.t
+0x0000023c d015a4a4 vlog2.q R100.q,R100.q
+0x00000240 d0181717 vnrcp.s S530.s,S530.s
+0x00000244 d01864e4 vnrcp.p R120.p,R120.p
+0x00000248 d018e464 vnrcp.t R110.t,R110.t
+0x0000024c d018a4a4 vnrcp.q R100.q,R100.q
+0x00000250 d01a1717 vnsin.s S530.s,S530.s
+0x00000254 d01a64e4 vnsin.p R120.p,R120.p
+0x00000258 d01ae464 vnsin.t R110.t,R110.t
+0x0000025c d01aa4a4 vnsin.q R100.q,R100.q
+0x00000260 f2a8a0a4 vqmul.q R100.q,R000.q,R200.q
+0x00000264 d0101717 vrcp.s S530.s,S530.s
+0x00000268 d01064e4 vrcp.p R120.p,R120.p
+0x0000026c d010e464 vrcp.t R110.t,R110.t
+0x00000270 d010a4a4 vrcp.q R100.q,R100.q
+0x00000274 d01c1717 vrexp2.s S530.s,S530.s
+0x00000278 d01c64e4 vrexp2.p R120.p,R120.p
+0x0000027c d01ce464 vrexp2.t R110.t,R110.t
+0x00000280 d01ca4a4 vrexp2.q R100.q,R100.q
+0x00000284 d0111717 vrsq.s S530.s,S530.s
+0x00000288 d01164e4 vrsq.p R120.p,R120.p
+0x0000028c d011e464 vrsq.t R110.t,R110.t
+0x00000290 d011a4a4 vrsq.q R100.q,R100.q
+0x00000294 d0121717 vsin.s S530.s,S530.s
+0x00000298 d01264e4 vsin.p R120.p,R120.p
+0x0000029c d012e464 vsin.t R110.t,R110.t
+0x000002a0 d012a4a4 vsin.q R100.q,R100.q
+0x000002a4 d0161717 vsqrt.s S530.s,S530.s
+0x000002a8 d01664e4 vsqrt.p R120.p,R120.p
+0x000002ac d016e464 vsqrt.t R110.t,R110.t
+0x000002b0 d016a4a4 vsqrt.q R100.q,R100.q
\.\.\.
diff --git a/gas/testsuite/gas/mips/allegrex-vfpu.s b/gas/testsuite/gas/mips/allegrex-vfpu.s
index c40acb84ca9..1bba03ca974 100644
--- a/gas/testsuite/gas/mips/allegrex-vfpu.s
+++ b/gas/testsuite/gas/mips/allegrex-vfpu.s
@@ -114,6 +114,58 @@
vt5650.q R000, R000[w,z,y,x]
vi2us.q R000[m,], R000[x,x,y,y]
+ vasin.s S530, S530
+ vasin.p R120, R120
+ vasin.t R110, R110
+ vasin.q R100, R100
+ vcos.s S530, S530
+ vcos.p R120, R120
+ vcos.t R110, R110
+ vcos.q R100, R100
+ vcrsp.t R110, R111, R112
+ vcrs.t C100, R100, C100
+ vdiv.s S530, S530, S530
+ vdiv.p R120, R120, R120
+ vdiv.t R110, R110, R110
+ vdiv.q R100, R100, R100
+ vexp2.s S530, S530
+ vexp2.p R120, R120
+ vexp2.t R110, R110
+ vexp2.q R100, R100
+ vlog2.s S530, S530
+ vlog2.p R120, R120
+ vlog2.t R110, R110
+ vlog2.q R100, R100
+ vnrcp.s S530, S530
+ vnrcp.p R120, R120
+ vnrcp.t R110, R110
+ vnrcp.q R100, R100
+ vnsin.s S530, S530
+ vnsin.p R120, R120
+ vnsin.t R110, R110
+ vnsin.q R100, R100
+ vqmul.q R100, R000, R200
+ vrcp.s S530, S530
+ vrcp.p R120, R120
+ vrcp.t R110, R110
+ vrcp.q R100, R100
+ vrexp2.s S530, S530
+ vrexp2.p R120, R120
+ vrexp2.t R110, R110
+ vrexp2.q R100, R100
+ vrsq.s S530, S530
+ vrsq.p R120, R120
+ vrsq.t R110, R110
+ vrsq.q R100, R100
+ vsin.s S530, S530
+ vsin.p R120, R120
+ vsin.t R110, R110
+ vsin.q R100, R100
+ vsqrt.s S530, S530
+ vsqrt.p R120, R120
+ vsqrt.t R110, R110
+ vsqrt.q R100, R100
+
# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
.align 4, 0
.space 16
diff --git a/include/opcode/mips.h b/include/opcode/mips.h
index 0a8f1fd0f1c..b90f8ea33f7 100644
--- a/include/opcode/mips.h
+++ b/include/opcode/mips.h
@@ -264,6 +264,18 @@ enum mips_vfpu_regpfx_compat {
OP_VFPU_PFXCOMPAT_LIMITED
};
+/* Enumerates the types of VFPU register-register compatibility. */
+enum mips_vfpu_regdst_compat {
+ /* All registers are allowed. */
+ OP_VFPU_REGCOMPAT_ALL,
+
+ /* Identical overlap is allowed. */
+ OP_VFPU_REGCOMPAT_SAME,
+
+ /* No overlap whatsover is allowed. */
+ OP_VFPU_REGCOMPAT_NONE
+};
+
/* Base class for all operands. */
struct mips_operand
@@ -408,11 +420,14 @@ struct mips_vfpu_reg_operand
/* Register (sub)type. */
enum mips_vfpu_reg_type regtype;
+ /* Register access size. */
+ unsigned int rsize;
+
/* Register-prefix compatibility. */
enum mips_vfpu_regpfx_compat pfxcompat;
- /* Register access size. */
- unsigned int rsize;
+ /* Register-register compatibility. */
+ enum mips_vfpu_regdst_compat regcompat;
};
/* Return true if the assembly syntax allows OPERAND to be omitted. */
diff --git a/opcodes/mips-formats.h b/opcodes/mips-formats.h
index 00e11de1fad..9d91d83b730 100644
--- a/opcodes/mips-formats.h
+++ b/opcodes/mips-formats.h
@@ -112,34 +112,44 @@
return &op.root; \
}
-#define VFPU_REGEXP(OP, SIZE, LSB, RTYPE, RSIZE, PFXCOMPAT) \
+#define VFPU_REGEXP(OP, SIZE, LSB, RTYPE, RSIZE, PFX_COMPAT, REG_COMPAT) \
{ \
static const struct mips_vfpu_reg_operand op[] = { \
- { { OP_VFPU_##OP, SIZE, LSB }, OP_VFPU_REG_##RTYPE, PFXCOMPAT, 0 }, \
- { { OP_VFPU_##OP, SIZE, LSB }, OP_VFPU_REG_##RTYPE, PFXCOMPAT, 1 }, \
- { { OP_VFPU_##OP, SIZE, LSB }, OP_VFPU_REG_##RTYPE, PFXCOMPAT, 2 }, \
- { { OP_VFPU_##OP, SIZE, LSB }, OP_VFPU_REG_##RTYPE, PFXCOMPAT, 3 }, \
+ { { OP_VFPU_##OP, SIZE, LSB }, OP_VFPU_REG_##RTYPE, 0, \
+ OP_VFPU_PFXCOMPAT_##PFX_COMPAT, OP_VFPU_REGCOMPAT_##REG_COMPAT}, \
+ { { OP_VFPU_##OP, SIZE, LSB }, OP_VFPU_REG_##RTYPE, 1, \
+ OP_VFPU_PFXCOMPAT_##PFX_COMPAT, OP_VFPU_REGCOMPAT_##REG_COMPAT}, \
+ { { OP_VFPU_##OP, SIZE, LSB }, OP_VFPU_REG_##RTYPE, 2, \
+ OP_VFPU_PFXCOMPAT_##PFX_COMPAT, OP_VFPU_REGCOMPAT_##REG_COMPAT}, \
+ { { OP_VFPU_##OP, SIZE, LSB }, OP_VFPU_REG_##RTYPE, 3, \
+ OP_VFPU_PFXCOMPAT_##PFX_COMPAT, OP_VFPU_REGCOMPAT_##REG_COMPAT}, \
}; \
return &op[RSIZE].root; \
}
-#define VFPU_REG(SIZE, LSB, RTYPE, RSIZE, PFX_COMPAT) \
+#define VFPU_REG(SIZE, LSB, RTYPE, RSIZE, PFX_COMPAT, REG_COMPAT) \
{ \
switch (PFX_COMPAT) \
{ \
case 'a': \
- VFPU_REGEXP(REG, SIZE, LSB, RTYPE, RSIZE, OP_VFPU_PFXCOMPAT_ALL) \
+ VFPU_REGEXP(REG, SIZE, LSB, RTYPE, RSIZE, ALL, REG_COMPAT) \
case 'n': \
- VFPU_REGEXP(REG, SIZE, LSB, RTYPE, RSIZE, OP_VFPU_PFXCOMPAT_NONE) \
+ VFPU_REGEXP(REG, SIZE, LSB, RTYPE, RSIZE, NONE, REG_COMPAT) \
case 'l': \
- VFPU_REGEXP(REG, SIZE, LSB, RTYPE, RSIZE, OP_VFPU_PFXCOMPAT_LIMITED) \
+ VFPU_REGEXP(REG, SIZE, LSB, RTYPE, RSIZE, LIMITED, REG_COMPAT) \
default: \
abort(); \
} \
}
+#define VFPU_SREG(SIZE, LSB, RTYPE, RSIZE, PFX_COMPAT) \
+ VFPU_REG(SIZE, LSB, RTYPE, RSIZE, PFX_COMPAT, ALL)
+
+#define VFPU_DREG(SIZE, LSB, RTYPE, RSIZE, PFX_COMPAT, REG_COMPAT) \
+ VFPU_REG(SIZE, LSB, RTYPE, RSIZE, PFX_COMPAT, REG_COMPAT)
+
#define VFPU_PFX(SIZE, LSB, RTYPE, RSIZE) \
- VFPU_REGEXP(PFX, SIZE, LSB, RTYPE, RSIZE, OP_VFPU_PFXCOMPAT_ALL)
+ VFPU_REGEXP(PFX, SIZE, LSB, RTYPE, RSIZE, ALL, ALL)
#define PCREL(SIZE, LSB, IS_SIGNED, SHIFT, ALIGN_LOG2, INCLUDE_ISA_BIT, \
FLIP_ISA_BIT) \
diff --git a/opcodes/mips-opc.c b/opcodes/mips-opc.c
index b5dd46f9cf4..847ad0f30e5 100644
--- a/opcodes/mips-opc.c
+++ b/opcodes/mips-opc.c
@@ -145,16 +145,22 @@ decode_mips_operand (const char *p)
case '?':
switch (p[1])
{
- case 'd': VFPU_REG(7, 0, D, p[2] - '0', p[3]);
- case 's': VFPU_REG(7, 8, S, p[2] - '0', p[3]);
- case 't': VFPU_REG(7, 16, T, p[2] - '0', p[3]);
+ case 's': VFPU_SREG(7, 8, S, p[2] - '0', p[3]);
+ case 't': VFPU_SREG(7, 16, T, p[2] - '0', p[3]);
+ case 'd': VFPU_DREG(7, 0, D, p[2] - '0', p[3], ALL);
+ case 'D': VFPU_DREG(7, 0, D, p[2] - '0', p[3], SAME);
+ case 'i': VFPU_DREG(7, 0, D, p[2] - '0', p[3], NONE);
case 'p':
switch (p[2])
{
case 'd': VFPU_PFX(24, 0, D, 3);
case 's': VFPU_PFX(24, 0, S, 3);
case 't': VFPU_PFX(24, 0, T, 3);
+ default:
+ abort();
}
+ default:
+ abort();
}
break;
@@ -695,12 +701,30 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"vadd.q", "?d3a,?s3a,?t3a", 0x60008080, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vadd.s", "?d0a,?s0a,?t0a", 0x60000000, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vadd.t", "?d2a,?s2a,?t2a", 0x60008000, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vasin.p", "?D1n,?s1n", 0xd0170080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vasin.q", "?D3n,?s3n", 0xd0178080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vasin.s", "?D0n,?s0n", 0xd0170000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vasin.t", "?D2n,?s2n", 0xd0178000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vavg.p", "?d0a,?s1a", 0xd0470080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vavg.q", "?d0a,?s3a", 0xd0478080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vavg.t", "?d0a,?s2a", 0xd0478000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vcos.p", "?D1n,?s1n", 0xd0130080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vcos.q", "?D3n,?s3n", 0xd0138080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vcos.s", "?D0n,?s0n", 0xd0130000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vcos.t", "?D2n,?s2n", 0xd0138000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vcrsp.t", "?i2n,?s2n,?t2n", 0xf2808000, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vcrs.t", "?d2a,?s2n,?t2n", 0x66808000, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vdiv.p", "?D1n,?s1n,?t1n", 0x63800080, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vdiv.q", "?D3n,?s3n,?t3n", 0x63808080, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vdiv.s", "?D0n,?s0n,?t0n", 0x63800000, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vdiv.t", "?D2n,?s2n,?t2n", 0x63808000, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vdot.p", "?d0a,?s1a,?t1a", 0x64800080, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vdot.q", "?d0a,?s3a,?t3a", 0x64808080, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vdot.t", "?d0a,?s2a,?t2a", 0x64808000, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vexp2.p", "?D1n,?s1n", 0xd0140080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vexp2.q", "?D3n,?s3n", 0xd0148080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vexp2.s", "?D0n,?s0n", 0xd0140000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vexp2.t", "?D2n,?s2n", 0xd0148000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vfad.p", "?d0a,?s1a", 0xd0460080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vfad.q", "?d0a,?s3a", 0xd0468080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vfad.t", "?d0a,?s2a", 0xd0468000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
@@ -709,6 +733,10 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"vi2us.q", "?d1l,?s3l", 0xd03e8080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vidt.p", "?d1a", 0xd0030080, 0xffffff80, WR_C2, 0, ALX, 0, 0 },
{"vidt.q", "?d3a", 0xd0038080, 0xffffff80, WR_C2, 0, ALX, 0, 0 },
+{"vlog2.p", "?D1n,?s1n", 0xd0150080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vlog2.q", "?D3n,?s3n", 0xd0158080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vlog2.s", "?D0n,?s0n", 0xd0150000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vlog2.t", "?D2n,?s2n", 0xd0158000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vmax.p", "?d1a,?s1a,?t1a", 0x6d800080, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vmax.q", "?d3a,?s3a,?t3a", 0x6d808080, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vmax.s", "?d0a,?s0a,?t0a", 0x6d800000, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
@@ -729,6 +757,14 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"vneg.q", "?d3a,?s3l", 0xd0028080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vneg.s", "?d0a,?s0l", 0xd0020000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vneg.t", "?d2a,?s2l", 0xd0028000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vnrcp.p", "?D1n,?s1n", 0xd0180080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vnrcp.q", "?D3n,?s3n", 0xd0188080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vnrcp.s", "?D0n,?s0n", 0xd0180000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vnrcp.t", "?D2n,?s2n", 0xd0188000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vnsin.p", "?D1n,?s1n", 0xd01a0080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vnsin.q", "?D3n,?s3n", 0xd01a8080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vnsin.s", "?D0n,?s0n", 0xd01a0000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vnsin.t", "?D2n,?s2n", 0xd01a8000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vocp.p", "?d1a,?s1n", 0xd0440080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vocp.q", "?d3a,?s3n", 0xd0448080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vocp.s", "?d0a,?s0n", 0xd0440000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
@@ -740,6 +776,19 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"vpfxd", "?pd.", 0xde000000, 0xff000000, CP, ALXPFX, ALX, 0, 0 },
{"vpfxs", "?ps.", 0xdc000000, 0xff000000, CP, ALXPFX, ALX, 0, 0 },
{"vpfxt", "?pt.", 0xdd000000, 0xff000000, CP, ALXPFX, ALX, 0, 0 },
+{"vqmul.q", "?i3n,?s3n,?t3n", 0xf2808080, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vrcp.p", "?D1n,?s1n", 0xd0100080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vrcp.q", "?D3n,?s3n", 0xd0108080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vrcp.s", "?D0n,?s0n", 0xd0100000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vrcp.t", "?D2n,?s2n", 0xd0108000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vrexp2.p", "?D1n,?s1n", 0xd01c0080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vrexp2.q", "?D3n,?s3n", 0xd01c8080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vrexp2.s", "?D0n,?s0n", 0xd01c0000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vrexp2.t", "?D2n,?s2n", 0xd01c8000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vrsq.p", "?D1n,?s1n", 0xd0110080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vrsq.q", "?D3n,?s3n", 0xd0118080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vrsq.s", "?D0n,?s0n", 0xd0110000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vrsq.t", "?D2n,?s2n", 0xd0118000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vsat0.p", "?d1n,?s1a", 0xd0040080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vsat0.q", "?d3n,?s3a", 0xd0048080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vsat0.s", "?d0n,?s0a", 0xd0040000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
@@ -763,10 +812,18 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"vsgn.q", "?d3a,?s3a", 0xd04a8080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vsgn.s", "?d0a,?s0a", 0xd04a0000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vsgn.t", "?d2a,?s2a", 0xd04a8000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vsin.p", "?D1n,?s1n", 0xd0120080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vsin.q", "?D3n,?s3n", 0xd0128080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vsin.s", "?D0n,?s0n", 0xd0120000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vsin.t", "?D2n,?s2n", 0xd0128000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vslt.p", "?d1a,?s1a,?t1a", 0x6f800080, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vslt.q", "?d3a,?s3a,?t3a", 0x6f808080, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vslt.s", "?d0a,?s0a,?t0a", 0x6f800000, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vslt.t", "?d2a,?s2a,?t2a", 0x6f808000, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vsqrt.p", "?D1n,?s1n", 0xd0160080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vsqrt.q", "?D3n,?s3n", 0xd0168080, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vsqrt.s", "?D0n,?s0n", 0xd0160000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
+{"vsqrt.t", "?D2n,?s2n", 0xd0168000, 0xffff8080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vsub.p", "?d1a,?s1a,?t1a", 0x60800080, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vsub.q", "?d3a,?s3a,?t3a", 0x60808080, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
{"vsub.s", "?d0a,?s0a,?t0a", 0x60800000, 0xff808080, RD_C2|WR_C2, 0, ALX, 0, 0 },
--
2.51.1
More information about the Gcc-patches
mailing list