From b98e294936816f1470cb7a65d1a094c438edcbc7 Mon Sep 17 00:00:00 2001
From: Richard Sandiford <rdsandiford@googlemail.com>
Date: Sun, 4 Aug 2013 07:31:38 +0000
Subject: [PATCH] =?UTF-8?q?include/opcode/=202013-08-04=20=20J=C3=BCrgen?=
 =?UTF-8?q?=20Urban=20=20<JuergenUrban@gmx.de>=20=09=20=20=20=20Richard=20?=
 =?UTF-8?q?Sandiford=20=20<rdsandiford@googlemail.com>?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

	* mips.h: Document new VU0 operand characters.
	(OP_VU0_SUFFIX, OP_VU0_MATCH_SUFFIX): New mips_operand_types.
	(OP_REG_VF, OP_REG_VI, OP_REG_R5900_I, OP_REG_R5900_Q, OP_REG_R5900_R)
	(OP_REG_R5900_ACC): New mips_reg_operand_types.
	(INSN2_VU0_CHANNEL_SUFFIX): New macro.
	(mips_vu0_channel_mask): Declare.

opcodes/
2013-08-04  Jürgen Urban  <JuergenUrban@gmx.de>
	    Richard Sandiford  <rdsandiford@googlemail.com>

	* mips-dis.c (print_reg): Handle OP_REG_VI, OP_REG_VF, OP_REG_R5900_I,
	OP_REG_R5900_Q, OP_REG_R5900_R and OP_REG_R5900_ACC.
	(print_vu0_channel): New function.
	(print_insn_arg): Handle OP_VU0_SUFFIX and OP_VU0_MATCH_SUFFIX.
	(print_insn_args): Handle '#'.
	(print_insn_mips): Handle INSN2_VU0_CHANNEL_SUFFIX.
	* mips-opc.c (mips_vu0_channel_mask): New constant.
	(decode_mips_operand): Handle new VU0 operand types.
	(VU0, VU0CH): New macros.
	(mips_builtin_opcodes): Add VU0 opcodes.  Use "+7" rather than "E"
	for LQC2 and SQC2.  Use "+9" rather than "G" for EE CFC2 and CTC2.
	Use "+6" rather than "G" for QMFC2 and QMTC2.

gas/
2013-08-04  Jürgen Urban  <JuergenUrban@gmx.de>
	    Richard Sandiford  <rdsandiford@googlemail.com>

	* config/tc-mips.c (MAX_OPERANDS): Bump to 6.
	(RWARN): Bump to 0x8000000.
	(RTYPE_VI, RTYPE_VF, RTYPE_R5900_I, RTYPE_R5900_Q, RTYPE_R5900_R)
	(RTYPE_R5900_ACC): New register types.
	(RTYPE_MASK): Include them.
	(R5900_I_NAMES, R5900_Q_NAMES, R5900_R_NAMES, R5900_ACC_NAMES): New
	macros.
	(reg_names): Include them.
	(mips_parse_register_1): New function, split out from...
	(mips_parse_register): ...here.  Add a channels_ptr parameter.
	Look for VU0 channel suffixes when nonnull.
	(reg_lookup): Update the call to mips_parse_register.
	(mips_parse_vu0_channels): New function.
	(OT_CHANNELS, OT_DOUBLE_CHAR): New mips_operand_token_types.
	(mips_operand_token): Add a "channels" field to the union.
	Extend the comment above "ch" to OT_DOUBLE_CHAR.
	(mips_parse_base_start): Match -- and ++.  Handle channel suffixes.
	(mips_parse_argument_token): Handle channel suffixes here too.
	(validate_mips_insn): Handle INSN2_VU0_CHANNEL_SUFFIX.
	Ignore OP_VU0_MATCH_SUFFIX when calculating the used bits.
	Handle '#' formats.
	(md_begin): Register $vfN and $vfI registers.
	(operand_reg_mask): Handle OP_VU0_SUFFIX and OP_VU0_MATCH_SUFFIX.
	(convert_reg_type): Handle OP_REG_VI, OP_REG_VF, OP_REG_R5900_I,
	OP_REG_R5900_Q, OP_REG_R5900_R and OP_REG_R5900_ACC.
	(match_vu0_suffix_operand): New function.
	(match_operand): Handle OP_VU0_SUFFIX and OP_VU0_MATCH_SUFFIX.
	(macro): Use "+7" rather than "E" for LDQ2 and STQ2.
	(mips_lookup_insn): New function.
	(mips_ip): Use it.  Allow "+K" operands to be elided at the end
	of an instruction.  Handle '#' sequences.

gas/testsuite/
2013-08-04  Jürgen Urban  <JuergenUrban@gmx.de>

	* gas/mips/r5900-vu0.d: Expect $vfN and $viN instead of numeric
	coprocessor registers.
	* gas/mips/r5900-all-vu0.s, gas/mips/r5900-all-vu0.d,
	gas/mips/r5900-full-vu0.s, gas/mips/r5900-full-vu0.d,
	gas/mips/r5900-error-vu0.s, gas/mips/r5900-error-vu0.l: New tests.
	* gas/mips/mips.exp: Run them.
---
 include/opcode/ChangeLog | 10 ++++++++
 include/opcode/mips.h    | 55 +++++++++++++++++++++++++++++++++++-----
 2 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/include/opcode/ChangeLog b/include/opcode/ChangeLog
index 9952cf854..cdf578add 100644
--- a/include/opcode/ChangeLog
+++ b/include/opcode/ChangeLog
@@ -1,3 +1,13 @@
+2013-08-04  Jürgen Urban  <JuergenUrban@gmx.de>
+	    Richard Sandiford  <rdsandiford@googlemail.com>
+
+	* mips.h: Document new VU0 operand characters.
+	(OP_VU0_SUFFIX, OP_VU0_MATCH_SUFFIX): New mips_operand_types.
+	(OP_REG_VF, OP_REG_VI, OP_REG_R5900_I, OP_REG_R5900_Q, OP_REG_R5900_R)
+	(OP_REG_R5900_ACC): New mips_reg_operand_types.
+	(INSN2_VU0_CHANNEL_SUFFIX): New macro.
+	(mips_vu0_channel_mask): Declare.
+
 2013-08-03  Richard Sandiford  <rdsandiford@googlemail.com>
 
 	* mips.h (mips_pcrel_operand): Inherit from mips_int_operand.
diff --git a/include/opcode/mips.h b/include/opcode/mips.h
index e82e4c293..ae6983b1d 100644
--- a/include/opcode/mips.h
+++ b/include/opcode/mips.h
@@ -401,7 +401,15 @@ enum mips_operand_type {
   OP_REPEAT_PREV_REG,
 
   /* $pc, which has no encoding in the architectural instruction.  */
-  OP_PC
+  OP_PC,
+
+  /* A 4-bit XYZW channel mask or 2-bit XYZW index; the size determines
+     which.  */
+  OP_VU0_SUFFIX,
+
+  /* Like OP_VU0_SUFFIX, but used when the operand's value has already
+     been set.  Any suffix used here must match the previous value.  */
+  OP_VU0_MATCH_SUFFIX
 };
 
 /* Enumerates the types of MIPS register.  */
@@ -430,7 +438,19 @@ enum mips_reg_operand_type {
 
   /* Hardware registers $0-$31.  Mnemonic names like hwr_cpunum can
      also be used in some contexts.  */
-  OP_REG_HW
+  OP_REG_HW,
+
+  /* Floating-point registers $vf0-$vf31.  */
+  OP_REG_VF,
+
+  /* Integer registers $vi0-$vi31.  */
+  OP_REG_VI,
+
+  /* R5900 VU0 registers $I, $Q, $R and $ACC.  */
+  OP_REG_R5900_I,
+  OP_REG_R5900_Q,
+  OP_REG_R5900_R,
+  OP_REG_R5900_ACC
 };
 
 /* Base class for all operands.  */
@@ -781,6 +801,26 @@ struct mips_opcode
    "Y"	source register (OP_*_FS)
    "Z"	source register (OP_*_FT)
 
+   R5900 VU0 Macromode instructions:
+   "+5" 5 bit floating point register (FD)
+   "+6" 5 bit floating point register (FS)
+   "+7" 5 bit floating point register (FT)
+   "+8" 5 bit integer register (FD)
+   "+9" 5 bit integer register (FS)
+   "+0" 5 bit integer register (FT)
+   "+K" match an existing 4-bit channel mask starting at bit 21
+   "+L" 2-bit channel index starting at bit 21
+   "+M" 2-bit channel index starting at bit 23
+   "+N" match an existing 2-bit channel index starting at bit 0
+   "+f" 15 bit immediate for VCALLMS
+   "+g" 5 bit signed immediate for VIADDI
+   "+m" $ACC register (syntax only)
+   "+q" $Q register (syntax only)
+   "+r" $R register (syntax only)
+   "+y" $I register (syntax only)
+   "#+" "++" decorator in ($reg++) sequence
+   "#-" "--" decorator in (--$reg) sequence
+
    DSP ASE usage:
    "2" 2 bit unsigned immediate for byte align (OP_*_BP)
    "3" 3 bit unsigned immediate (OP_*_SA3)
@@ -846,15 +886,15 @@ struct mips_opcode
 
    Characters used so far, for quick reference when adding more:
    "1234567890"
-   "%[]<>(),+:'@!$*&\~"
+   "%[]<>(),+:'@!#$*&\~"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklopqrstuvwxz"
 
    Extension character sequences used so far ("+" followed by the
    following), for quick reference when adding more:
-   "1234"
-   "ABCEFGHIJPQSXZ"
-   "abcijpstxz"
+   "1234567890"
+   "ABCEFGHIJKLMNPQSXZ"
+   "abcfgijmpqrstxyz"
 */
 
 /* These are the bits which may be set in the pinfo field of an
@@ -960,6 +1000,8 @@ struct mips_opcode
 #define INSN2_COND_BRANCH	    0x00001000
 /* Reads from $16.  This is true of the MIPS16 0x6500 nop.  */
 #define INSN2_READ_GPR_16           0x00002000
+/* Has an "\.x?y?z?w?" suffix based on mips_vu0_channel_mask.  */
+#define INSN2_VU0_CHANNEL_SUFFIX    0x00004000
 
 /* Masks used to mark instructions to indicate which MIPS ISA level
    they were introduced in.  INSN_ISA_MASK masks an enumeration that
@@ -1490,6 +1532,7 @@ enum
    Many instructions are short hand for other instructions (i.e., The
    jal <register> instruction is short for jalr <register>).  */
 
+extern const struct mips_operand mips_vu0_channel_mask;
 extern const struct mips_operand *decode_mips_operand (const char *);
 extern const struct mips_opcode mips_builtin_opcodes[];
 extern const int bfd_mips_num_builtin_opcodes;