This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Aw: Re: [PATCH] Support VU0 on MIPS R5900
- From: "JÃrgen Urban" <JuergenUrban at gmx dot de>
- To: "Richard Sandiford" <rdsandiford at googlemail dot com>
- Cc: binutils at sourceware dot org
- Date: Mon, 20 May 2013 22:00:04 +0200 (CEST)
- Subject: Aw: Re: [PATCH] Support VU0 on MIPS R5900
- References: <20130108234130 dot 27410 at gmx dot net>, <87a9rrso6l dot fsf at talisman dot default>
- Sensitivity: Normal
Hello Richard,
> I'm really sorry for the slow response. The patch mostly looks good,
> but I've got a few questions:
>
> > + /* RTYPE_VF registers have optional appended suffixes
> > + for R5900 VU instructions. */
> > + if (mips_opts.arch == CPU_R5900 && (types & RTYPE_VF))
> > + {
> > + while(!ISDIGIT(*(e-1)) && e != *s)
> > + --e;
> > + }
> > +
>
> Is there any need for this mips_opts.arch test? It looked on face
> value like the "types & RTYPE_VF" part was right on its own.
>
> > insn = (struct mips_opcode *) hash_find (hash, name);
> >
> > - if (insn != NULL || !mips_opts.micromips)
> > - break;
> > + if (insn != NULL
> > + || (!mips_opts.micromips && mips_opts.arch != CPU_R5900))
> > + break;
> > if (forced_insn_length)
> > - break;
> > + break;
> > + if (tried_suffix)
> > + {
> > + if(dot)
> > + *dot = '.';
> > + tried_suffix = 0;
> > + break;
> > + }
> > + /* Used for VU0 insn.xyz, insn.xyzw, or any other variation.
> > + The suffix is needed for comparing with operand suffixes. */
> > + if (mips_opts.arch == CPU_R5900)
> > + {
> > + dot = strrchr (name,'.');
> > + opend = dot != NULL ? dot - name : end;
> > + if (opend < 3)
> > + break;
> > + if (dot)
> > + {
> > + *dot = '\0';
> > + dot++;
> > + insn_suffix = alloca (strlen(dot)+1);
> > + strncpy(insn_suffix,dot,strlen(dot));
> > + insn_suffix[strlen(dot)] = '\0';
> > + dot--;
> > + }
> > + tried_suffix = 1;
> > + }
>
> "forced_insn_length" has no meaning for the standard encoding, so I
> think it should remain in the micromips-specific part. The VU-specific
> stuff should happen regardless of mips_opts.arch.
>
> Why "opend < 3"? It looked like that had been copied from the
> micromips code. I don't think the length of the bit before the "."
> really matters for VU0.
>
> The code allows any instruction to have a suffix (including those
> without "+j"), so it needs to check that insn_suffix has been consumed.
> That might need a few control-flow changes, since mips_ip has some
> early non-error exits.
>
> FWIW, I think the patch below might help to make the VU stuff easier to add.
>
> > @@ -11269,7 +11420,17 @@ mips_ip (char *str, struct mips_cl_insn
> > || (mips_opts.micromips
> > && args[1] == 'm'
> > && (args[2] == 'l' || args[2] == 'n'
> > - || args[2] == 's' || args[2] == 'a')));
> > + || args[2] == 's' || args[2] == 'a'))
> > + || (mips_opts.arch == CPU_R5900
> > + && args[1] == '+' && args[2] == '9')
> > + || (mips_opts.arch == CPU_R5900
> > + && args[1] == '+' && args[2] == '-'
> > + && args[3] == '+'
> > + && (args[4] == '0' || args[4] == '9'))
> > + || (mips_opts.arch == CPU_R5900
> > + && args[1] == '+'
> > + && (args[2] == '0' || args[2] == '9')
> > + && args[3] == '+' && args[4] == '+'));
> > if (*s == '\0' && args[1] == 'b')
> > return;
> > /* Fall through. */
>
> I don't think we should be checking "mips_opts.arch == CPU_R5900" here,
> especially since this is an assert about a static property of the table.
> We check elsewhere whether or not the instruction belongs to the
> current ISA.
>
> > + case 'f': /* 15 bit immediate in bit 6 for vcallms */
> > + my_getExpression (&imm_expr, s);
> > + check_absolute_expr (ip, &imm_expr);
> > + min_range = 0;
> > + max_range = 0xff8;
> > + if (imm_expr.X_add_number < min_range ||
> > + imm_expr.X_add_number > max_range)
> > + {
> > + as_bad (_("Micromem offset not in range 0x%lx..0x%lx (0x%lx)"),
> > + (long) min_range, (long) max_range,
> > + (long) imm_expr.X_add_number);
> > + }
> > + if (imm_expr.X_add_number & 0x7)
> > + as_bad (_("Micromem offset is not aligned 0x%lx"),
> > + (long)imm_expr.X_add_number);
> > + /* Not in specs, division is done for simplicity */
> > + INSERT_OPERAND (0, VCALLMS, *ip, (imm_expr.X_add_number >> 3));
> > + imm_expr.X_op = O_absent;
> > + s = expr_end;
> > + continue;
>
> I don't understand the comment, sorry.
>
> > + if (!file_mips_legacy_vu0)
> > + {
> > + if (strncmp(disreg_name,s,2)
> > + || (s[2] != '\0' && s[2] != ',' && !ISSPACE(s[2])))
> > + as_bad (_("Expected `%s' register"),disreg_name);
> > + }
> > + else
> > + {
> > + if (disreg_name[1] != s[0]
> > + || (s[1] != '\0' && s[1] != ',' && !ISSPACE(s[1])))
> > + as_bad (_("Expected `%c' register"),disreg_name[1]);
> > + }
> > + }
> > + while(*s != '\0' && *s != ',' && !ISSPACE(*s))
> > + s++;
>
> Would is_part_of_name work instead of these s[2] and s[1] tests?
> Instead of the while loop, it seems better for the "if" statements
> to skip over the name. E.g. something like:
>
> if (!file_mips_legacy_vu0)
> {
> if (strncmp (disreg_name, s, 2) == 0
> && !is_part_of_name (s[2]))
> s += 2;
> else
> as_bad (_("Expected `%s' register"), disreg_name);
> }
> else
> {
> if (disreg_name[1] == s[0]
> && !is_part_of_name (s[1]))
> s += 1;
> else
> as_bad (_("Expected `%c' register"), disreg_name[1]);
> }
>
> > + for (i = 0; i < strlen(insn_suffix); i++)
> > + if (insn_suffix[i] == valid[0])
> > + fields[0]++;
> > + else if (insn_suffix[i] == valid[1])
> > + fields[1]++;
> > + else if (insn_suffix[i] == valid[2])
> > + fields[2]++;
> > + else if (insn_suffix[i] == valid[3])
> > + fields[3]++;
> > + else
> > + as_bad (_("Invalid character in opcode suffix "
> > + "`%c'"), insn_suffix[i]);
>
> for (i = 0; insn_suffix[i]; i++)
>
> > + case 'k': /* Optional R5900 VU operand suffix */
> > + {
> > + unsigned int length = 0;
> > + s_reset = s;
> > + if (*s == '\0' || ISSPACE(*s) || *s == ',')
> > + continue;
> > + while (*s != '\0' && !ISSPACE(*s) && *s != ',')
> > + {
> > + length++;
> > + s++;
> > + }
> > + s = s_reset;
> > + if (insn_suffix)
> > + if (strncmp(s,insn_suffix,strlen(insn_suffix))
> > + || length != strlen(insn_suffix))
> > + insn_error ="Mismatched operand suffix";
> > + s += length;
> > + }
> > + continue;
>
> This seems to allow any suffix in the case where insn_suffix is null
> (which AIUI is equivalent to ".xyzw"). Is that intentional, or should
> we match "xyzw" in that case?
>
> All errors need to be wrapped in _(...) so that they get picked up for
> translation.
>
> > @@ -11922,7 +12353,34 @@ mips_ip (char *str, struct mips_cl_insn
> > cop0 = opcode == OP_OP_COP0;
> > }
> > types = RTYPE_NUM | (cop0 ? RTYPE_CP0 : RTYPE_GP);
> > - ok = reg_lookup (&s, types, ®no);
> > + if (!file_mips_legacy_vu0 || mips_opts.arch != CPU_R5900)
> > + ok = reg_lookup (&s, types, ®no);
> > + else
> > + {
> > + if (*s == '$')
> > + ++s;
> > + if (!strncmp(s,"vf",2))
> > + s+=2;
> > + else if (!strncmp(s,"vi",2))
> > + s+=2;
> > +
> > + if (ISDIGIT(*s))
> > + {
> > + regno = 0;
> > + do
> > + {
> > + regno *= 10;
> > + regno += *s - '0';
> > + ++s;
> > + }
> > + while (ISDIGIT (*s));
> > +
> > + if (regno > 31)
> > + ok = 0;
> > + else
> > + ok = 1;
> > + }
> > + }
> > if (mips_opts.micromips)
> > INSERT_OPERAND (1, RS, *ip, regno);
> > else
>
> Here too mips_opts.arch != CPU_R5900 seems the wrong thing to check.
> We should be checking a property of the instruction instead.
>
> Please factor out the file_mips_legacy_vu0 parsing into a separate function,
> since it appears three times.
>
> > @@ -12130,6 +12615,8 @@ mips_ip (char *str, struct mips_cl_insn
> > s_reset = s;
> > if (reg_lookup (&s, rtype, ®no))
> > {
> > + /* Jumped from extended (+ 5,6,7,8,9,0) args for R5900 */
> > + vu0:
> > if ((regno & 1) != 0
> > && HAVE_32BIT_FPRS
> > && !mips_oddfpreg_ok (ip->insn_mo, argnum))
>
> Please try to avoid the long goto. Which parts of:
>
> if ((regno & 1) != 0
> && HAVE_32BIT_FPRS
> && !mips_oddfpreg_ok (ip->insn_mo, argnum))
> as_warn (_("Float register should be even, was %d"),
> regno);
>
> c = *args;
> if (*s == ' ')
> ++s;
> if (args[1] != *s)
> {
> if (c == 'V' || c == 'W')
> {
> regno = lastregno;
> s = s_reset;
> ++args;
> }
> }
>
> apply in the VU0 case?
>
> > @@ -19556,7 +20053,8 @@ MIPS options:\n\
> > -msoft-float do not allow floating-point instructions\n\
> > -msingle-float only allow 32-bit floating-point operations\n\
> > -mdouble-float allow 32-bit and 64-bit floating-point operations\n\
> > ---[no-]construct-floats [dis]allow floating point values to be constructed\n"
> > +--[no-]construct-floats [dis]allow floating point values to be constructed\n\
> > +-mr5900-legacy-vu0 allow legacy VU0 register names\n"
> > ));
> > #ifdef OBJ_ELF
> > fprintf (stream, _("\
>
> This needs to be documented in doc/c-mips.texi.
>
> > + case 'd': /* FTF field for r5900 VU floating point register */
> > + case 'e': /* FSF field for r5900 VU floating point register */
> > + case 'l': /* BC field for r5900 VU instructions */
> > + {
> > + unsigned int field = 0;
> > +
> > + if (*d == 'd')
> > + field = GET_OP (l, VFTF);
> > + if (*d == 'e')
> > + field = GET_OP (l, VFSF);
> > + if (*d == 'l')
> > + field = GET_OP (l, VBC);
> > +
> > + if (field == 0)
> > + infprintf (is, "x");
> > + if (field == 1)
> > + infprintf (is, "y");
> > + if (field == 2)
> > + infprintf (is, "z");
> > + if (field == 3)
> > + infprintf (is, "w");
> > + }
> > + break;
> > +
>
> Please split the "field == ..." stuff out into a separate function,
> or simply use:
>
> infprintf (is, "%c", "xyzw"[GET_OP (l, ...)]);
>
> three times, one after each case statement.
>
> There are some places where the patch doesn't follow the coding conventions
> (usually spaces missing before "(" and ","), but I'm happy to fix those
> up before committing.
>
> Thanks,
> Richard
>
>
> gas/
> * config/tc-mips.c (micromips_strip_length): New function,
> split out from...
> (mips_ip): ...here.
>
> Index: gas/config/tc-mips.c
> ===================================================================
> --- gas/config/tc-mips.c 2013-01-26 16:42:59.000000000 +0000
> +++ gas/config/tc-mips.c 2013-01-29 19:58:34.644152580 +0000
> @@ -10768,6 +10768,33 @@ expr_const_in_range (expressionS *ep, of
> && ep->X_add_number < max << bit);
> }
>
> +/* Remove any micromips length suffix from instruction mnemonic NAME
> + (of length LENGTH) and store it in forced_insn_length. Return true
> + if something changed. */
> +
> +static bfd_boolean
> +micromips_strip_length (char *name, int length)
> +{
> + char *dot;
> + long opend;
> +
> + /* The length goes before any "." suffix. */
> + dot = strchr (name, '.');
> + opend = dot != NULL ? dot - name : length;
> + if (opend < 3)
> + return FALSE;
> +
> + if (name[opend - 2] == '1' && name[opend - 1] == '6')
> + forced_insn_length = 2;
> + else if (name[opend - 2] == '3' && name[opend - 1] == '2')
> + forced_insn_length = 4;
> + else
> + return FALSE;
> +
> + memcpy (name + opend - 2, name + opend, length - opend + 1);
> + return TRUE;
> +}
> +
> /* This routine assembles an instruction into its binary format. As a
> side effect, it sets one of the global variables imm_reloc or
> offset_reloc to the type of relocation to do if one of the operands
> @@ -10793,11 +10820,9 @@ mips_ip (char *str, struct mips_cl_insn
> unsigned int limlo, limhi;
> char *s_reset;
> offsetT min_range, max_range;
> - long opend;
> char *name;
> int argnum;
> unsigned int rtype;
> - char *dot;
> long end;
>
> insn_error = NULL;
> @@ -10824,35 +10849,16 @@ mips_ip (char *str, struct mips_cl_insn
> memcpy (name, str, end);
> name[end] = '\0';
>
> - for (;;)
> - {
> - insn = (struct mips_opcode *) hash_find (hash, name);
> -
> - if (insn != NULL || !mips_opts.micromips)
> - break;
> - if (forced_insn_length)
> - break;
> -
> - /* See if there's an instruction size override suffix,
> - either `16' or `32', at the end of the mnemonic proper,
> - that defines the operation, i.e. before the first `.'
> - character if any. Strip it and retry. */
> - dot = strchr (name, '.');
> - opend = dot != NULL ? dot - name : end;
> - if (opend < 3)
> - break;
> - if (name[opend - 2] == '1' && name[opend - 1] == '6')
> - forced_insn_length = 2;
> - else if (name[opend - 2] == '3' && name[opend - 1] == '2')
> - forced_insn_length = 4;
> - else
> - break;
> - memcpy (name + opend - 2, name + opend, end - opend + 1);
> - }
> - if (insn == NULL)
> + insn = (struct mips_opcode *) hash_find (hash, name);
> + if (!insn)
> {
> - insn_error = _("Unrecognized opcode");
> - return;
> + if (mips_opts.micromips && micromips_strip_length (name, end))
> + insn = (struct mips_opcode *) hash_find (hash, name);
> + if (!insn)
> + {
> + insn_error = _("Unrecognized opcode");
> + return;
> + }
> }
>
> /* For microMIPS instructions placed in a fixed-length branch delay slot
>
The attached patch shouldn't have the problems you listed, because it only contains the basic support for VU0 instructions. It doesn't include the complicated macromode instructions.
The patch adds support for the instructions:
bc2f, bc2fl, bc2t, bc2tl, cfc2, cfc2.i, cfc2.ni, ctc2, ctc2.i, ctc2.ni, qmfc2, qmfc2.i, qmfc2.ni, qmtc2, qmtc2.i and qmtc2.ni.
The patch for the macromode instructions will be submitted later when I get a repsonse from ragnarok2040.
Best regards
JÃrgen
diff -Nurp binutils-cvs-20130519/gas/config/tc-mips.c binutils-cvs-20130519-mips64r5900el-linux-patched/gas/config/tc-mips.c
--- binutils-cvs-20130519/gas/config/tc-mips.c 2013-05-10 03:08:48.000000000 +0200
+++ binutils-cvs-20130519-mips64r5900el-linux-patched/gas/config/tc-mips.c 2013-05-20 20:55:26.019181968 +0200
@@ -8201,6 +8201,13 @@ macro (struct mips_cl_insn *ip)
/* Itbl support may require additional care here. */
coproc = 1;
goto ld_st;
+ case M_LQC2_AB:
+ ab = 1;
+ s = "lqc2";
+ fmt = "E,o(b)";
+ /* Itbl support may require additional care here. */
+ coproc = 1;
+ goto ld_st;
case M_LDC3_AB:
ab = 1;
s = "ldc3";
@@ -8390,6 +8397,13 @@ macro (struct mips_cl_insn *ip)
/* Itbl support may require additional care here. */
coproc = 1;
goto ld_st;
+ case M_SQC2_AB:
+ ab = 1;
+ s = "sqc2";
+ fmt = "E,o(b)";
+ /* Itbl support may require additional care here. */
+ coproc = 1;
+ goto ld_st;
case M_SDC3_AB:
ab = 1;
gas_assert (!mips_opts.micromips);
diff -Nurp binutils-cvs-20130519/gas/testsuite/gas/mips/mips.exp binutils-cvs-20130519-mips64r5900el-linux-patched/gas/testsuite/gas/mips/mips.exp
--- binutils-cvs-20130519/gas/testsuite/gas/mips/mips.exp 2013-05-10 03:08:48.000000000 +0200
+++ binutils-cvs-20130519-mips64r5900el-linux-patched/gas/testsuite/gas/mips/mips.exp 2013-05-20 20:55:26.019181968 +0200
@@ -1173,6 +1173,7 @@ if { [istarget mips*-*-vxworks*] } {
run_dump_test "r5900"
run_dump_test "r5900-full"
if $elf { run_list_test "r5900-nollsc" "-mabi=o64 -march=r5900" }
+ run_dump_test "r5900-vu0"
run_list_test_arches "ext-ill" [mips_arch_list_matching mips64r2]
}
diff -Nurp binutils-cvs-20130519/gas/testsuite/gas/mips/r5900-vu0.d binutils-cvs-20130519-mips64r5900el-linux-patched/gas/testsuite/gas/mips/r5900-vu0.d
--- binutils-cvs-20130519/gas/testsuite/gas/mips/r5900-vu0.d 1970-01-01 01:00:00.000000000 +0100
+++ binutils-cvs-20130519-mips64r5900el-linux-patched/gas/testsuite/gas/mips/r5900-vu0.d 2013-05-20 21:09:08.471167872 +0200
@@ -0,0 +1,40 @@
+#objdump: -dr --prefix-addresses --show-raw-insn -M gpr-names=numeric -mmips:5900
+#name: MIPS R5900 VU0
+#as: -march=r5900
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> d8000000 lqc2 \$0,0\(\$0\)
+[0-9a-f]+ <[^>]*> d8217fff lqc2 \$1,32767\(\$1\)
+[0-9a-f]+ <[^>]*> d9088000 lqc2 \$8,-32768\(\$8\)
+[0-9a-f]+ <[^>]*> dbffffff lqc2 \$31,-1\(\$31\)
+[0-9a-f]+ <[^>]*> f8000000 sqc2 \$0,0\(\$0\)
+[0-9a-f]+ <[^>]*> f8217fff sqc2 \$1,32767\(\$1\)
+[0-9a-f]+ <[^>]*> f9088000 sqc2 \$8,-32768\(\$8\)
+[0-9a-f]+ <[^>]*> fbffffff sqc2 \$31,-1\(\$31\)
+[0-9a-f]+ <[^>]*> 48400000 cfc2 \$0,\$0
+[0-9a-f]+ <[^>]*> 4840f800 cfc2 \$0,\$31
+[0-9a-f]+ <[^>]*> 48400001 cfc2.i \$0,\$0
+[0-9a-f]+ <[^>]*> 4840f801 cfc2.i \$0,\$31
+[0-9a-f]+ <[^>]*> 48400000 cfc2 \$0,\$0
+[0-9a-f]+ <[^>]*> 4840f800 cfc2 \$0,\$31
+[0-9a-f]+ <[^>]*> 48c00000 ctc2 \$0,\$0
+[0-9a-f]+ <[^>]*> 48c0f800 ctc2 \$0,\$31
+[0-9a-f]+ <[^>]*> 48c00001 ctc2.i \$0,\$0
+[0-9a-f]+ <[^>]*> 48c0f801 ctc2.i \$0,\$31
+[0-9a-f]+ <[^>]*> 48c00000 ctc2 \$0,\$0
+[0-9a-f]+ <[^>]*> 48c0f800 ctc2 \$0,\$31
+[0-9a-f]+ <[^>]*> 48200000 qmfc2 \$0,\$0
+[0-9a-f]+ <[^>]*> 4820f800 qmfc2 \$0,\$31
+[0-9a-f]+ <[^>]*> 48200001 qmfc2.i \$0,\$0
+[0-9a-f]+ <[^>]*> 4820f801 qmfc2.i \$0,\$31
+[0-9a-f]+ <[^>]*> 48200000 qmfc2 \$0,\$0
+[0-9a-f]+ <[^>]*> 4820f800 qmfc2 \$0,\$31
+[0-9a-f]+ <[^>]*> 48a00000 qmtc2 \$0,\$0
+[0-9a-f]+ <[^>]*> 48a0f800 qmtc2 \$0,\$31
+[0-9a-f]+ <[^>]*> 48a00001 qmtc2.i \$0,\$0
+[0-9a-f]+ <[^>]*> 48a0f801 qmtc2.i \$0,\$31
+[0-9a-f]+ <[^>]*> 48a00000 qmtc2 \$0,\$0
+[0-9a-f]+ <[^>]*> 48a0f800 qmtc2 \$0,\$31
+ \.\.\.
diff -Nurp binutils-cvs-20130519/gas/testsuite/gas/mips/r5900-vu0.s binutils-cvs-20130519-mips64r5900el-linux-patched/gas/testsuite/gas/mips/r5900-vu0.s
--- binutils-cvs-20130519/gas/testsuite/gas/mips/r5900-vu0.s 1970-01-01 01:00:00.000000000 +0100
+++ binutils-cvs-20130519-mips64r5900el-linux-patched/gas/testsuite/gas/mips/r5900-vu0.s 2013-05-20 21:08:43.795168295 +0200
@@ -0,0 +1,52 @@
+ .set noreorder
+ .set noat
+
+ .globl text_label .text
+text_label:
+
+ # Floating point transfer to VU
+ lqc2 $0,0($0)
+ lqc2 $1, 0x7fff($1)
+ lqc2 $8, -0x8000($8)
+ lqc2 $31, -1($31)
+
+ # Floating point transfer from VU
+ sqc2 $0,0($0)
+ sqc2 $1, 0x7fff($1)
+ sqc2 $8, -0x8000($8)
+ sqc2 $31, -1($31)
+
+ # Integer transfer from VU
+ cfc2 $0,$0
+ cfc2 $0,$31
+ cfc2.i $0,$0
+ cfc2.i $0,$31
+ cfc2.ni $0,$0
+ cfc2.ni $0,$31
+
+ # Integer transfer to VU
+ ctc2 $0,$0
+ ctc2 $0,$31
+ ctc2.i $0,$0
+ ctc2.i $0,$31
+ ctc2.ni $0,$0
+ ctc2.ni $0,$31
+
+ # Floating point transfer from VU
+ qmfc2 $0,$0
+ qmfc2 $0,$31
+ qmfc2.i $0,$0
+ qmfc2.i $0,$31
+ qmfc2.ni $0,$0
+ qmfc2.ni $0,$31
+
+ # Floating point transfer to VU
+ qmtc2 $0,$0
+ qmtc2 $0,$31
+ qmtc2.i $0,$0
+ qmtc2.i $0,$31
+ qmtc2.ni $0,$0
+ qmtc2.ni $0,$31
+
+# Force at least 8 (non-delay-slot) zero bytes, to make 'objdump' print ...
+ .space 8
diff -Nurp binutils-cvs-20130519/include/opcode/mips.h binutils-cvs-20130519-mips64r5900el-linux-patched/include/opcode/mips.h
--- binutils-cvs-20130519/include/opcode/mips.h 2013-05-10 03:08:48.000000000 +0200
+++ binutils-cvs-20130519-mips64r5900el-linux-patched/include/opcode/mips.h 2013-05-20 20:55:26.019181968 +0200
@@ -1070,6 +1070,7 @@ enum
M_LDC1_AB,
M_LDC2_AB,
M_LDC2_OB,
+ M_LQC2_AB,
M_LDC3_AB,
M_LDL_AB,
M_LDL_OB,
@@ -1163,6 +1164,7 @@ enum
M_SDC1_AB,
M_SDC2_AB,
M_SDC2_OB,
+ M_SQC2_AB,
M_SDC3_AB,
M_SDL_AB,
M_SDL_OB,
diff -Nurp binutils-cvs-20130519/opcodes/mips-opc.c binutils-cvs-20130519-mips64r5900el-linux-patched/opcodes/mips-opc.c
--- binutils-cvs-20130519/opcodes/mips-opc.c 2013-05-10 03:08:48.000000000 +0200
+++ binutils-cvs-20130519-mips64r5900el-linux-patched/opcodes/mips-opc.c 2013-05-20 20:55:26.019181968 +0200
@@ -914,6 +914,8 @@ const struct mips_opcode mips_builtin_op
{"lld", "t,A(b)", 0, (int) M_LLD_AB, INSN_MACRO, 0, I3, EE },
{"lq", "t,o(b)", 0x78000000, 0xfc000000, WR_t|RD_b, 0, MMI },
{"lq", "t,A(b)", 0, (int) M_LQ_AB, INSN_MACRO, 0, MMI },
+{"lqc2", "E,o(b)", 0xd8000000, 0xfc000000, RD_b|WR_C2, 0, EE },
+{"lqc2", "E,A(b)", 0, (int) M_LQC2_AB, INSN_MACRO, 0, EE },
{"lui", "t,u", 0x3c000000, 0xffe00000, WR_t, 0, I1 },
{"luxc1", "D,t(b)", 0x4c000005, 0xfc00f83f, LDD|WR_D|RD_t|RD_b|FP_D, 0, I5_33|N55},
{"lw", "t,o(b)", 0x8c000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 },
@@ -1535,6 +1537,8 @@ const struct mips_opcode mips_builtin_op
{"snei", "t,r,+Q", 0x7000002f, 0xfc00003f, WR_t|RD_s, 0, IOCT },
{"sq", "t,o(b)", 0x7c000000, 0xfc000000, SM|RD_t|RD_b, 0, MMI },
{"sq", "t,A(b)", 0, (int) M_SQ_AB, INSN_MACRO, 0, MMI },
+{"sqc2", "E,o(b)", 0xf8000000, 0xfc000000, SM|RD_C2|RD_b, 0, EE },
+{"sqc2", "E,A(b)", 0, (int) M_SQC2_AB, INSN_MACRO, 0, EE },
{"sqrt.d", "D,S", 0x46200004, 0xffff003f, WR_D|RD_S|FP_D, 0, I2, SF },
{"sqrt.s", "D,S", 0x46000004, 0xffff003f, WR_D|RD_S|FP_S, 0, I2 },
{"sqrt.ps", "D,S", 0x46c00004, 0xffff003f, WR_D|RD_S|FP_D, 0, SB1 },
@@ -1781,16 +1785,20 @@ const struct mips_opcode mips_builtin_op
/* Coprocessor 2 move/branch operations overlap with VR5400 .ob format
instructions so they are here for the latters to take precedence. */
-{"bc2f", "p", 0x49000000, 0xffff0000, CBD|RD_CC, 0, I1, IOCT|IOCTP|IOCT2|EE },
+{"bc2f", "p", 0x49000000, 0xffff0000, CBD|RD_CC, 0, I1, IOCT|IOCTP|IOCT2 },
{"bc2f", "N,p", 0x49000000, 0xffe30000, CBD|RD_CC, 0, I32, IOCT|IOCTP|IOCT2 },
-{"bc2fl", "p", 0x49020000, 0xffff0000, CBL|RD_CC, 0, I2|T3, IOCT|IOCTP|IOCT2|EE },
+{"bc2fl", "p", 0x49020000, 0xffff0000, CBL|RD_CC, 0, I2|T3, IOCT|IOCTP|IOCT2 },
{"bc2fl", "N,p", 0x49020000, 0xffe30000, CBL|RD_CC, 0, I32, IOCT|IOCTP|IOCT2 },
-{"bc2t", "p", 0x49010000, 0xffff0000, CBD|RD_CC, 0, I1, IOCT|IOCTP|IOCT2|EE },
+{"bc2t", "p", 0x49010000, 0xffff0000, CBD|RD_CC, 0, I1, IOCT|IOCTP|IOCT2 },
{"bc2t", "N,p", 0x49010000, 0xffe30000, CBD|RD_CC, 0, I32, IOCT|IOCTP|IOCT2 },
-{"bc2tl", "p", 0x49030000, 0xffff0000, CBL|RD_CC, 0, I2|T3, IOCT|IOCTP|IOCT2|EE },
+{"bc2tl", "p", 0x49030000, 0xffff0000, CBL|RD_CC, 0, I2|T3, IOCT|IOCTP|IOCT2 },
{"bc2tl", "N,p", 0x49030000, 0xffe30000, CBL|RD_CC, 0, I32, IOCT|IOCTP|IOCT2 },
-{"cfc2", "t,G", 0x48400000, 0xffe007ff, LCD|WR_t|RD_C2, 0, I1, IOCT|IOCTP|IOCT2|EE },
-{"ctc2", "t,G", 0x48c00000, 0xffe007ff, COD|RD_t|WR_CC, 0, I1, IOCT|IOCTP|IOCT2|EE },
+{"cfc2", "t,G", 0x48400000, 0xffe007ff, LCD|WR_t|RD_C2, 0, I1, IOCT|IOCTP|IOCT2 },
+{"cfc2.i", "t,G", 0x48400001, 0xffe007ff, LCD|WR_t|RD_C2, 0, EE },
+{"cfc2.ni", "t,G", 0x48400000, 0xffe007ff, LCD|WR_t|RD_C2, 0, EE },
+{"ctc2", "t,G", 0x48c00000, 0xffe007ff, COD|RD_t|WR_CC, 0, I1, IOCT|IOCTP|IOCT2 },
+{"ctc2.i", "t,G", 0x48c00001, 0xffe007ff, COD|RD_t|WR_CC, 0, EE },
+{"ctc2.ni", "t,G", 0x48c00000, 0xffe007ff, COD|RD_t|WR_CC, 0, EE },
{"dmfc2", "t,i", 0x48200000, 0xffe00000, LCD|WR_t|RD_C2, 0, IOCT },
{"dmfc2", "t,G", 0x48200000, 0xffe007ff, LCD|WR_t|RD_C2, 0, I3, IOCT|IOCTP|IOCT2|EE },
{"dmfc2", "t,G,H", 0x48200000, 0xffe007f8, LCD|WR_t|RD_C2, 0, I64, IOCT|IOCTP|IOCT2 },
@@ -1807,7 +1815,12 @@ const struct mips_opcode mips_builtin_op
{"mthc2", "t,G", 0x48e00000, 0xffe007ff, COD|RD_t|WR_C2|WR_CC, 0, I33, IOCT|IOCTP|IOCT2 },
{"mthc2", "t,G,H", 0x48e00000, 0xffe007f8, COD|RD_t|WR_C2|WR_CC, 0, I33, IOCT|IOCTP|IOCT2 },
{"mthc2", "t,i", 0x48e00000, 0xffe00000, COD|RD_t|WR_C2|WR_CC, 0, I33, IOCT|IOCTP|IOCT2 },
-
+{"qmfc2", "t,G", 0x48200000, 0xffe007ff, WR_t|RD_C2, 0, EE },
+{"qmfc2.i", "t,G", 0x48200001, 0xffe007ff, WR_t|RD_C2, 0, EE },
+{"qmfc2.ni","t,G", 0x48200000, 0xffe007ff, WR_t|RD_C2, 0, EE },
+{"qmtc2", "t,G", 0x48a00000, 0xffe007ff, RD_t|WR_C2, 0, EE },
+{"qmtc2.i", "t,G", 0x48a00001, 0xffe007ff, RD_t|WR_C2, 0, EE },
+{"qmtc2.ni","t,G", 0x48a00000, 0xffe007ff, RD_t|WR_C2, 0, EE },
/* Coprocessor 3 move/branch operations overlap with MIPS IV COP1X
instructions, so they are here for the latters to take precedence. */
{"bc3f", "p", 0x4d000000, 0xffff0000, CBD|RD_CC, 0, I1, IOCT|IOCTP|IOCT2|EE },