public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Add support for MIPS64r6
@ 2014-04-29 19:17 Andrew Bennett
  2014-04-29 19:33 ` Andreas Schwab
  2014-05-07 17:52 ` Richard Sandiford
  0 siblings, 2 replies; 14+ messages in thread
From: Andrew Bennett @ 2014-04-29 19:17 UTC (permalink / raw)
  To: binutils; +Cc: Rich Fuhler, Matthew Fortune, rdsandiford, Saeed Ghazanfar

Hi,

This patch adds support for MIPS64r6.  MIPS64r6 includes most of MIPS64r5 
but there are some instructions that have been re-coded or removed in order 
to support the new MIPS64r6 instructions.  

For more information please refer to:
http://www.imgtec.com/mips/mips64-architecture.asp

Some notes on the changes:

A dense encoding has been used for several new instructions leading to the
introduction of new special operand types. Some special casing during
disassembly has also been necessary to handle these cases. While some checks
are redundant due to the ordering of the opcode table they are present for
safety in case of any future re-ordering of the table.

A new PLT template has been added for R6 as the explicit JR opcode has been
removed instead relying on JALR $0, <reg>.  Although JALR exists for <=r5
we are being cautious in case the use of JALR is interpreted as a call in
pre-existing MIPS implementations as part of hardware optimisations.

MicroMIPSr5 is not compatible with MIPSr6 and as such is disabled. The JALX
instruction has also been removed and the encoding re-used. If a new
compressed ISA is defined then the interlinking support will need updating.

ABI related changes for R6 are:
1) Introduction of new PC relative relocations
2) Definition of the new ISAs in e_flags.

We would like to get early feedback on the ABI so that work in other tools
can also be finalised.  The decision to define the new ISA in e_flags instead
of the newly proposed .MIPS.abiflags section is due to the need for preventing
linking of R<6 and R6 code.  While mixing ISAs within executables and DSOs is
not supported we do not intend to prevent mixing of executables and DSOs.  The
linux kernel will handle the emulation of instructions that do not exist.  

The current patch does not contain any test cases, as we would like your 
opinions on how to proceed with this.  There are three main issues.  Firstly,
disabling all tests that check instructions that have been removed in 
MIPSr6.  The problem here is that typically these tests contain valid, and
non-valid R6 instructions, so there needs to be a way to prevent the non-valid
instructions from being assembled if we are testing for R6.  One approach is to
break the testcases up into the valid and non-valid instructions, and then just
predicate the non-valid instruction tests in mips.exp for R6. What do you think
about doing this?
Secondly, updating tests that check for instructions that have been recoded in
R6.  Would you be happy if we used the micromips@ approach for the disassembly
files; we could use something like mipsr6@ ?
Finally, should we cover all new instructions in one file and all removed
instructions in another or break it down further?

The patch passes the gas testsuite apart from two tests: MIPS 16 reloc; and
MIPS16 reloc 2.  These tests fail because the order of the text section labels
in the symbol table is different to what these tests expect.  We are looking 
into the failures at the moment, and will include a fix in the updated patch 
which contains the R6 testcases.

The patch and ChangeLog entries are shown below.

Many thanks,


Andrew

Andrew Bennett
Software Design Engineer, MIPS Processor IP
Imagination Technologies Limited
t: +44 (0)113 2429814
www.imgtec.com


2014-04-24  Chao-ying Fu    <chao-ying.fu@imgtec.com>
	    Matthew Fortune <matthew.fortune@imgtec.com>
	    Andrew Bennett  <andrew.bennett@imgtec.com>
 
/
 	* config.sub: Add support for mips32r6 and mips64r6.
 	* configure.ac: Add mips*-img-elf* triple.
 	* configure: Regenerate.
 
bfd/
 	* aoutx.h (NAME (aout, machine_type)): Add mips32r6 and mips64r6.
 	* archures.c (bfd_architecture): Likewise.
 	* bfd-in2.h (bfd_architecture): Likewise.
 	* cpu-mips.c (arch_info_struct): Likewise.
 	(bfd_reloc_code_real): Add relocs BFD_RELOC_MIPS_21_PCREL_S2, 
 	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3 and
 	BFD_RELOC_MIPS_19_PCREL_S2.
	* config.bfd: Add mips*-img-elf* triple.
 	* elf32-mips.c: Define relocs R_MIPS_PC21_S2, R_MIPS_PC26_S2
 	R_MIPS_PC18_S3, R_MIPS_PC19_S2, R_MIPS_PCHI16 and R_MIPS_PCLO16.
 	(mips_reloc_map): Add entries for BFD_RELOC_MIPS_21_PCREL_S2, 
 	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
	BFD_RELOC_LO16_PCREL.
	* elf64-mips.c: Define partial inplace and non-partial 
	inplace relocs R_MIPS_PC21_S2, R_MIPS_PC26_S2, R_MIPS_PC18_S3, 
	R_MIPS_PC19_S2, R_MIPS_PCHI16 and R_MIPS_PCLO16.
	(mips_reloc_map): Add entries for BFD_RELOC_MIPS_21_PCREL_S2, 
	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
	BFD_RELOC_LO16_PCREL.
	* elfn32-mips.c: Define partial inplace and non-partial 
	inplace relocs R_MIPS_PC21_S2, R_MIPS_PC26_S2, R_MIPS_PC18_S3, 
	R_MIPS_PC19_S2, R_MIPS_PCHI16 and R_MIPS_PCLO16.
	(mips_reloc_map): Add entries for BFD_RELOC_MIPS_21_PCREL_S2, 
	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
	BFD_RELOC_LO16_PCREL.
	* elfxx-mips.c (MIPSR6_P): New define.
	(mipsr6_exec_plt_entry): New array.
	(aligned_pcrel_reloc_p): New function.
	(mips_elf_relocation_needs_la25_stub): Add support for relocs: 
	R_MIPS_PC21_S2 and R_MIPS_PC26_S2.
	(_bfd_mips_elf_check_relocs): Likewise.
	(mips_elf_calculate_relocation): Add support for relocs:
	R_MIPS_PC21_S2, R_MIPS_PC26_S2, R_MIPS_PC18_S3, R_MIPS_PC19_S2,
	R_MIPS_PCHI16 and R_MIPS_PCLO16. Also allow relocs R_MIPS_PC16 and
	R_MIPS_GNU_REL16_S2 to support partial inplace.
	(_bfd_elf_mips_mach): Add support for mips32r6 and mips64r6.
	(mips_set_isa_flags): Likewise.
	(_bfd_mips_elf_print_private_bfd_data): Likewise.
	(_bfd_mips_elf_relocate_section): Add a check for unaligned
	pc relative relocs.
	(_bfd_mips_elf_finish_dynamic_symbol): Add support for MIPS r6
	plt entry.
	(mips_32bit_flags_p): Add supprt for mips32r6.
	* libbfd.h (bfd_reloc_code_real_names): Add entries for
	BFD_RELOC_MIPS_21_PCREL_S2, BFD_RELOC_MIPS_26_PCREL_S2,
	BFD_RELOC_MIPS_18_PCREL_S3 and BFD_RELOC_MIPS_19_PCREL_S2.
	* reloc.c: Document relocs BFD_RELOC_MIPS_21_PCREL_S2, 
	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3 and 
	BFD_RELOC_MIPS_19_PCREL_S2.

binutils/
	* readelf.c (get_machine_flags): Add support for mips32r6 and 
	mips64r6.

binutils/testsuite
	* binutils-all/objcopy.exp: Add mips*-img-elf* triple.
	* binutils-all/readelf.exp: Likewise.

elfcpp/
	* mips.h (E_MIPS_ARCH_32R6, E_MIPS_ARCH_64R6): New enum constants.

gas/
	* config/tc-mips.c (ISA_IS_R6): New define.
	(ISA_HAS_64BIT_REGS): Add mips64r6.
	(ISA_HAS_DROR): Likewise.
	(ISA_HAS_64BIT_FPRS): Add mips32r6 and mips64r6.
	(ISA_HAS_ROR): Likewise.
	(ISA_HAS_ODD_SINGLE_FPR): Likewise.
	(ISA_HAS_MXHC1): Likewise.
	(hilo_interlocks): Likewise.
	(md_longopts): Likewise.
	(options): Add OPTION_MIPS32R6 and OPTION_MIPS64R6.
	(mips_ase): Add fields mips32_rem_rev, mips64_rem_rev,
	micromips32_rem_rev and micromips64_rem_rev.
	(mips_ases): Updated to add which ISA an ASE was removed in.
	(mips_isa_rev): Add support for mips32r6 and mips64r6.
	(mips_check_isa_supports_ase): Add support to check if an ASE
	has been removed in the specified MIPS ISA revision. 
	(validate_mips_insn): Skip '-' character.
	(macro_build): Likewise.
	(limited_pcrel_reloc_p): Add relocs: BFD_RELOC_MIPS_21_PCREL_S2,
	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3, 
	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
	BFD_RELOC_LO16_PCREL.
	(operand_reg_mask): Add support for OP_SAME_RS_RT, OP_GP_NOT_ZERO,
	OP_GP_NOT_ZERO_NOT_PREV, OP_GP_NOT_ZERO_LT_PREV, OP_GP_GT_PREV,
	OP_GP_LE_PREV and OP_GP_GE_PREV.
	(match_same_rs_rt_operand): New function.
	(match_gp_not_zero_operand): New function.
	(match_gp_not_zero_lt_prev_operand): New function.
	(match_gp_gt_prev_operand): New function.
	(match_gp_le_prev_operand): New function.
	(match_gp_ge_prev_operand): New function.
	(match_gp_not_zero_not_prev_operand): New function.
	(match_tied_reg_operand): Added type argument.
	(match_operand): Updated entries for OP_REPEAT_DEST_REG, 
	and OP_REPEAT_PREV_REG.  Added entries for: OP_SAME_RS_RT,
	OP_GP_NOT_ZERO, OP_GP_NOT_ZERO_LT_PREV, OP_GP_GT_PREV, OP_GP_LE_PREV,
	OP_GP_GE_PREV and OP_GP_NOT_ZERO_NOT_PREV. 
	(insns_between): Added case to deal with forbidden slots.
	(append_insn): Added support for relocs: BFD_RELOC_MIPS_21_PCREL_S2
	and BFD_RELOC_MIPS_26_PCREL_S2
	(match_insn): Add support for operands -A, -B, +' and +".  Also
	skip '-' character.
	(mips_percent_op): Add entries for %pcrel_hi and %pcrel_lo.
	(md_parse_option): Add support for mips32r6 and mips64r6.
	(mips_after_parse_args): Prevent 32 bit floating point registers
	for MIPS r6, and produce and error if a user tries to do this.
	Also produce an error if user tries to enable branch relaxation
	or micromips for MIPS r6.
	(md_pcrel_from): Add cases for relocs: BFD_RELOC_MIPS_21_PCREL_S2,
	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_32_PCREL:,
	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL,
	BFD_RELOC_LO16_PCREL and BFD_RELOC_MIPS_18_PCREL_S3.
	(mips_force_relocation): Prevent forced relaxation for MIPS r6.
	(md_apply_fix): Add support for relocs: BFD_RELOC_MIPS_21_PCREL_S2,
	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
	BFD_RELOC_LO16_PCREL.
	(s_mipsset): Add support for mips32r6 and mips64r6.  Also prevent 
	.set micromips for mips32r6 or mips64r6.
	(tc_gen_reloc): Add relocs: BFD_RELOC_MIPS_21_PCREL_S2,
	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
	BFD_RELOC_LO16_PCREL.
	(mips_cpu_info_table): Add entries for mips32r6 and mips64r6.
	* configure.in: Add support for mips32r6 and mips64r6.
	* configure: Regenerate.
	* configure.tgt: Add mips*-img-elf* target triple.
	* doc/c-mips.texi: Document the -mips32r6 and -mips64r6 command line
	options.

include/elf/
	* mips.h: Add relocs: R_MIPS_PC21_S2, R_MIPS_PC26_S2, R_MIPS_PC18_S3,
	R_MIPS_PC19_S2, R_MIPS_PCHI16 and R_MIPS_PCLO16.
	(E_MIPS_ARCH_32R6): New define.
	(E_MIPS_ARCH_64R6): New define.

include/opcode
	* mips.h (mips_operand_type): Add new entries: OP_SAME_RS_RT,
	OP_GP_NOT_ZERO, OP_GP_NOT_ZERO_LT_PREV, OP_GP_GT_PREV, OP_GP_LE_PREV,
	OP_GP_GE_PREV, OP_GP_NOT_ZERO_NOT_PREV.
	Add descriptions for the MIPS R6 instruction arguments: -a, -b, -d, -s,
	-t, -u, -v, -w, -x, -y, -A, -B, +I, +O, +R, +:, +\, +", +;
	(INSN2_FORBIDDEN_SLOT): New define.
	(INSN_ISA_MASK): Updated.
	(INSN_ISA32R6): New define.
	(INSN_ISA64R6): New define.
	(mips_isa_table): Add entries for mips32r6 and mips64r6.
	(ISA_MIPS32R6): New define.
	(ISA_MIPS64R6): New define.
	(CPU_MIPS32R6): New define.
	(CPU_MIPS64R6): New define.
	(cpu_is_member): Add cases for CPU_MIPS32R6, and CPU_MIPS64R6.

ld/
	* configure.tgt: Add img*-mips-elf* target triple. 
	* ldmain.c (get_emulation): Add support for -mips32r6 and -mips64r6.

ld/testsuite/
	* ld-mips-elf/mips-elf.exp: Add support for mips*-img-elf* target
	triple.

opcodes/
	* mips-dis.c (mips_arch_choices): Add entries for mips32r6 and
	mips64r6.
	(parse_mips_dis_option): Allow MSA and virtualization support for 
	mips64r6.
	(mips_print_arg_state): Add fields dest_regno and seen_dest.
	(mips_seen_register): New function.
	(print_insn_arg): Refactored code to use mips_seen_register
	function.  Also add support for OP_SAME_RS_RT, OP_GP_NOT_ZERO,  
	OP_GP_NOT_ZERO_LT_PREV, OP_GP_GT_PREV, OP_GP_LE_PREV, OP_GP_GE_PREV
	and OP_GP_NOT_ZERO_NOT_PREV.
	(print_insn_args): Add length argument.  Add code to correctly
	calculate the instruction address for pc relative instructions.
	(print_insn_mips): Add code to prevent new MIPS R6 instructions
	from being decoded as MIPS R2 instructions.  Also update the argument
	used in the call to print_insn_args.
	(print_insn_micromips): Update the arguments used in the call to 
	print_insn_args.
	* mips-opc.c (decode_mips_operand): Add support for -a, -b, -d, -s,
	-t, -u, -v, -w, -x, -y, -A, -B, +I, +O, +R, +:, +\, +", +;
	(RD_pc): New define.
	(FS): New define.
	(I34): New define.
	(I66): New define.
	(mips_builtin_opcodes): Add MIPS R6 instructions.  Exclude recoded 
	MIPS R6 instructions from MIPS R2 instructions. 


diff --git a/bfd/aoutx.h b/bfd/aoutx.h
index ad81a7a..2143dd3 100644
--- a/bfd/aoutx.h
+++ b/bfd/aoutx.h
@@ -791,9 +791,11 @@ NAME (aout, machine_type) (enum bfd_architecture arch,
 	case bfd_mach_mips16:
 	case bfd_mach_mipsisa32:
 	case bfd_mach_mipsisa32r2:
+	case bfd_mach_mipsisa32r6:
 	case bfd_mach_mips5:
 	case bfd_mach_mipsisa64:
 	case bfd_mach_mipsisa64r2:
+	case bfd_mach_mipsisa64r6:
 	case bfd_mach_mips_sb1:
 	case bfd_mach_mips_xlr:
 	  /* FIXME: These should be MIPS3, MIPS4, MIPS16, MIPS32, etc.  */
diff --git a/bfd/archures.c b/bfd/archures.c
index 4ab5f1d..92bf821 100644
--- a/bfd/archures.c
+++ b/bfd/archures.c
@@ -182,8 +182,10 @@ DESCRIPTION
 .#define bfd_mach_mips_xlr              887682   {* decimal 'XLR'  *}
 .#define bfd_mach_mipsisa32             32
 .#define bfd_mach_mipsisa32r2           33
+.#define bfd_mach_mipsisa32r6           34
 .#define bfd_mach_mipsisa64             64
 .#define bfd_mach_mipsisa64r2           65
+.#define bfd_mach_mipsisa64r6           66
 .#define bfd_mach_mips_micromips        96
 .  bfd_arch_i386,      {* Intel 386 *}
 .#define bfd_mach_i386_intel_syntax	(1 << 0)
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index e38441c..a1323b3 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1967,8 +1967,10 @@ enum bfd_architecture
 #define bfd_mach_mips_xlr              887682   /* decimal 'XLR'  */
 #define bfd_mach_mipsisa32             32
 #define bfd_mach_mipsisa32r2           33
+#define bfd_mach_mipsisa32r6           34
 #define bfd_mach_mipsisa64             64
 #define bfd_mach_mipsisa64r2           65
+#define bfd_mach_mipsisa64r6           66
 #define bfd_mach_mips_micromips        96
   bfd_arch_i386,      /* Intel 386 */
 #define bfd_mach_i386_intel_syntax     (1 << 0)
@@ -2933,6 +2935,12 @@ to compensate for the borrow when the low bits are added.  */
   BFD_RELOC_MICROMIPS_10_PCREL_S1,
   BFD_RELOC_MICROMIPS_16_PCREL_S1,
 
+/* MIPS PC-relative relocations.  */
+  BFD_RELOC_MIPS_21_PCREL_S2,
+  BFD_RELOC_MIPS_26_PCREL_S2,
+  BFD_RELOC_MIPS_18_PCREL_S3,
+  BFD_RELOC_MIPS_19_PCREL_S2,
+
 /* microMIPS versions of generic BFD relocs.  */
   BFD_RELOC_MICROMIPS_GPREL16,
   BFD_RELOC_MICROMIPS_HI16,
diff --git a/bfd/config.bfd b/bfd/config.bfd
index 9269c02..b4e5119 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -1030,7 +1030,7 @@ case "${targ}" in
     targ_defvec=bfd_elf32_tradlittlemips_vec
     targ_selvecs="bfd_elf32_tradbigmips_vec bfd_elf32_ntradbigmips_vec bfd_elf32_ntradlittlemips_vec bfd_elf64_tradbigmips_vec bfd_elf64_tradlittlemips_vec"
     ;;
-  mips*-sde-elf* | mips*-mti-elf*)
+  mips*-sde-elf* | mips*-mti-elf* | mips*-img-elf*)
     targ_defvec=bfd_elf32_tradbigmips_vec
     targ_selvecs="bfd_elf32_tradlittlemips_vec bfd_elf32_ntradbigmips_vec bfd_elf32_ntradlittlemips_vec bfd_elf64_tradbigmips_vec bfd_elf64_tradlittlemips_vec"
     ;;
diff --git a/bfd/cpu-mips.c b/bfd/cpu-mips.c
index 6e5a787..fcb579e 100644
--- a/bfd/cpu-mips.c
+++ b/bfd/cpu-mips.c
@@ -87,8 +87,10 @@ enum
   I_mips5,
   I_mipsisa32,
   I_mipsisa32r2,
+  I_mipsisa32r6,
   I_mipsisa64,
   I_mipsisa64r2,
+  I_mipsisa64r6,
   I_sb1,
   I_loongson_2e,
   I_loongson_2f,
@@ -131,8 +133,10 @@ static const bfd_arch_info_type arch_info_struct[] =
   N (64, 64, bfd_mach_mips5,    "mips:mips5",     FALSE, NN(I_mips5)),
   N (32, 32, bfd_mach_mipsisa32,  "mips:isa32",   FALSE, NN(I_mipsisa32)),
   N (32, 32, bfd_mach_mipsisa32r2,"mips:isa32r2", FALSE, NN(I_mipsisa32r2)),
+  N (32, 32, bfd_mach_mipsisa32r6,"mips:isa32r6", FALSE, NN(I_mipsisa32r6)),
   N (64, 64, bfd_mach_mipsisa64,  "mips:isa64",   FALSE, NN(I_mipsisa64)),
   N (64, 64, bfd_mach_mipsisa64r2,"mips:isa64r2", FALSE, NN(I_mipsisa64r2)),
+  N (64, 64, bfd_mach_mipsisa64r6,"mips:isa64r6", FALSE, NN(I_mipsisa64r6)),
   N (64, 64, bfd_mach_mips_sb1, "mips:sb1",       FALSE, NN(I_sb1)),
   N (64, 64, bfd_mach_mips_loongson_2e, "mips:loongson_2e",       FALSE, NN(I_loongson_2e)),
   N (64, 64, bfd_mach_mips_loongson_2f, "mips:loongson_2f",       FALSE, NN(I_loongson_2f)),
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c
index e0342e0..2174244 100644
--- a/bfd/elf32-mips.c
+++ b/bfd/elf32-mips.c
@@ -716,6 +716,100 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
 	 0x0,			/* src_mask */
 	 0xffffffff,		/* dst_mask */
 	 FALSE),		/* pcrel_offset */
+
+  EMPTY_HOWTO (52),
+  EMPTY_HOWTO (53),
+  EMPTY_HOWTO (54),
+  EMPTY_HOWTO (55),
+  EMPTY_HOWTO (56),
+  EMPTY_HOWTO (57),
+  EMPTY_HOWTO (58),
+  EMPTY_HOWTO (59),
+
+  HOWTO (R_MIPS_PC21_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MIPS_PC21_S2",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x001fffff,		/* src_mask */
+	 0x001fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PC26_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 26,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MIPS_PC26_S2",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x03ffffff,		/* src_mask */
+	 0x03ffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PC18_S3,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 18,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PC18_S3",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0003ffff,		/* src_mask */
+	 0x0003ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PC19_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PC19_S2",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0007ffff,		/* src_mask */
+	 0x0007ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PCHI16,		/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PCHI16",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PCLO16,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PCLO16",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
 };
 
 /* The reloc used for BFD_RELOC_CTOR when doing a 64 bit link.  This
@@ -1905,7 +1999,13 @@ static const struct elf_reloc_map mips_reloc_map[] =
   { BFD_RELOC_MIPS_TLS_TPREL32, R_MIPS_TLS_TPREL32 },
   { BFD_RELOC_MIPS_TLS_TPREL64, R_MIPS_TLS_TPREL64 },
   { BFD_RELOC_MIPS_TLS_TPREL_HI16, R_MIPS_TLS_TPREL_HI16 },
-  { BFD_RELOC_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_TPREL_LO16 }
+  { BFD_RELOC_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_TPREL_LO16 },
+  { BFD_RELOC_MIPS_21_PCREL_S2, R_MIPS_PC21_S2 },
+  { BFD_RELOC_MIPS_26_PCREL_S2, R_MIPS_PC26_S2 },
+  { BFD_RELOC_MIPS_18_PCREL_S3, R_MIPS_PC18_S3 },
+  { BFD_RELOC_MIPS_19_PCREL_S2, R_MIPS_PC19_S2 },
+  { BFD_RELOC_HI16_S_PCREL, R_MIPS_PCHI16 },
+  { BFD_RELOC_LO16_PCREL, R_MIPS_PCLO16 }
 };
 
 static const struct elf_reloc_map mips16_reloc_map[] =
diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c
index d1b52b1..4d10c02 100644
--- a/bfd/elf64-mips.c
+++ b/bfd/elf64-mips.c
@@ -805,6 +805,100 @@ static reloc_howto_type mips_elf64_howto_table_rel[] =
 	 0x0,			/* src_mask */
 	 0xffffffff,		/* dst_mask */
 	 FALSE),		/* pcrel_offset */
+
+  EMPTY_HOWTO (52),
+  EMPTY_HOWTO (53),
+  EMPTY_HOWTO (54),
+  EMPTY_HOWTO (55),
+  EMPTY_HOWTO (56),
+  EMPTY_HOWTO (57),
+  EMPTY_HOWTO (58),
+  EMPTY_HOWTO (59),
+
+  HOWTO (R_MIPS_PC21_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MIPS_PC21_S2",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x001fffff,		/* src_mask */
+	 0x001fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PC26_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 26,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MIPS_PC26_S2",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x03ffffff,		/* src_mask */
+	 0x03ffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PC18_S3,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 18,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PC18_S3",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0003ffff,		/* src_mask */
+	 0x0003ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PC19_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PC19_S2",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0007ffff,		/* src_mask */
+	 0x0007ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PCHI16,		/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PCHI16",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PCLO16,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PCLO16",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
 };
 
 /* The relocation table used for SHT_RELA sections.  */
@@ -1492,6 +1586,100 @@ static reloc_howto_type mips_elf64_howto_table_rela[] =
 	 0x0,			/* src_mask */
 	 0xffffffff,		/* dst_mask */
 	 FALSE),		/* pcrel_offset */
+
+  EMPTY_HOWTO (52),
+  EMPTY_HOWTO (53),
+  EMPTY_HOWTO (54),
+  EMPTY_HOWTO (55),
+  EMPTY_HOWTO (56),
+  EMPTY_HOWTO (57),
+  EMPTY_HOWTO (58),
+  EMPTY_HOWTO (59),
+
+  HOWTO (R_MIPS_PC21_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MIPS_PC21_S2",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x001fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PC26_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 26,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MIPS_PC26_S2",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x03ffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PC18_S3,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 18,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PC18_S3",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0003ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PC19_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PC19_S2",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0007ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PCHI16,		/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PCHI16",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PCLO16,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PCLO16",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
 };
 
 static reloc_howto_type mips16_elf64_howto_table_rel[] =
@@ -3202,7 +3390,13 @@ static const struct elf_reloc_map mips_reloc_map[] =
   { BFD_RELOC_MIPS_TLS_TPREL32, R_MIPS_TLS_TPREL32 },
   { BFD_RELOC_MIPS_TLS_TPREL64, R_MIPS_TLS_TPREL64 },
   { BFD_RELOC_MIPS_TLS_TPREL_HI16, R_MIPS_TLS_TPREL_HI16 },
-  { BFD_RELOC_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_TPREL_LO16 }
+  { BFD_RELOC_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_TPREL_LO16 },
+  { BFD_RELOC_MIPS_21_PCREL_S2, R_MIPS_PC21_S2 },
+  { BFD_RELOC_MIPS_26_PCREL_S2, R_MIPS_PC26_S2 },
+  { BFD_RELOC_MIPS_18_PCREL_S3, R_MIPS_PC18_S3 },
+  { BFD_RELOC_MIPS_19_PCREL_S2, R_MIPS_PC19_S2 },
+  { BFD_RELOC_HI16_S_PCREL, R_MIPS_PCHI16 },
+  { BFD_RELOC_LO16_PCREL, R_MIPS_PCLO16 }
 };
 
 static const struct elf_reloc_map mips16_reloc_map[] =
diff --git a/bfd/elfn32-mips.c b/bfd/elfn32-mips.c
index 0cbbb81..75391d2 100644
--- a/bfd/elfn32-mips.c
+++ b/bfd/elfn32-mips.c
@@ -770,6 +770,100 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
 	 0x0,			/* src_mask */
 	 0xffffffff,		/* dst_mask */
 	 FALSE),		/* pcrel_offset */
+
+  EMPTY_HOWTO (52),
+  EMPTY_HOWTO (53),
+  EMPTY_HOWTO (54),
+  EMPTY_HOWTO (55),
+  EMPTY_HOWTO (56),
+  EMPTY_HOWTO (57),
+  EMPTY_HOWTO (58),
+  EMPTY_HOWTO (59),
+
+  HOWTO (R_MIPS_PC21_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MIPS_PC21_S2",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x001fffff,		/* src_mask */
+	 0x001fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PC26_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 26,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MIPS_PC26_S2",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x03ffffff,		/* src_mask */
+	 0x03ffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PC18_S3,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 18,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PC18_S3",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0003ffff,		/* src_mask */
+	 0x0003ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PC19_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PC19_S2",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0007ffff,		/* src_mask */
+	 0x0007ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PCHI16,		/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PCHI16",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PCLO16,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PCLO16",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
 };
 
 /* The relocation table used for SHT_RELA sections.  */
@@ -1458,6 +1552,100 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
 	 0x0,			/* src_mask */
 	 0xffffffff,		/* dst_mask */
 	 FALSE),		/* pcrel_offset */
+
+  EMPTY_HOWTO (52),
+  EMPTY_HOWTO (53),
+  EMPTY_HOWTO (54),
+  EMPTY_HOWTO (55),
+  EMPTY_HOWTO (56),
+  EMPTY_HOWTO (57),
+  EMPTY_HOWTO (58),
+  EMPTY_HOWTO (59),
+
+  HOWTO (R_MIPS_PC21_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MIPS_PC21_S2",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x001fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PC26_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 26,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MIPS_PC26_S2",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x03ffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PC18_S3,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 18,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PC18_S3",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0003ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PC19_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PC19_S2",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0007ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PCHI16,		/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PCHI16",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_MIPS_PCLO16,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MIPS_PCLO16",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
 };
 
 static reloc_howto_type elf_mips16_howto_table_rel[] =
@@ -3018,7 +3206,13 @@ static const struct elf_reloc_map mips_reloc_map[] =
   { BFD_RELOC_MIPS_TLS_TPREL32, R_MIPS_TLS_TPREL32 },
   { BFD_RELOC_MIPS_TLS_TPREL64, R_MIPS_TLS_TPREL64 },
   { BFD_RELOC_MIPS_TLS_TPREL_HI16, R_MIPS_TLS_TPREL_HI16 },
-  { BFD_RELOC_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_TPREL_LO16 }
+  { BFD_RELOC_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_TPREL_LO16 },
+  { BFD_RELOC_MIPS_21_PCREL_S2, R_MIPS_PC21_S2 },
+  { BFD_RELOC_MIPS_26_PCREL_S2, R_MIPS_PC26_S2 },
+  { BFD_RELOC_MIPS_18_PCREL_S3, R_MIPS_PC18_S3 },
+  { BFD_RELOC_MIPS_19_PCREL_S2, R_MIPS_PC19_S2 },
+  { BFD_RELOC_HI16_S_PCREL, R_MIPS_PCHI16 },
+  { BFD_RELOC_LO16_PCREL, R_MIPS_PCLO16 }
 };
 
 static const struct elf_reloc_map mips16_reloc_map[] =
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index d939444..b1506a8 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -791,6 +791,11 @@ static bfd *reldyn_sorting_bfd;
 #define MICROMIPS_P(abfd) \
   ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH_ASE_MICROMIPS) != 0)
 
+/* Nonzero if ABFD is MIPS R6.  */
+#define MIPSR6_P(abfd) \
+  ((elf_elfheader (abfd)->e_flags \
+    & (E_MIPS_ARCH_32R6 | E_MIPS_ARCH_64R6)) != 0)
+
 /* The IRIX compatibility level we are striving for.  */
 #define IRIX_COMPAT(abfd) \
   (get_elf_backend_data (abfd)->elf_backend_mips_irix_compat (abfd))
@@ -1088,6 +1093,14 @@ static const bfd_vma mips_exec_plt_entry[] =
   0x03200008	/* jr $25					*/
 };
 
+static const bfd_vma mipsr6_exec_plt_entry[] =
+{
+  0x3c0f0000,	/* lui $15, %hi(.got.plt entry)			*/
+  0x01f90000,	/* l[wd] $25, %lo(.got.plt entry)($15)		*/
+  0x25f80000,	/* addiu $24, $15, %lo(.got.plt entry)		*/
+  0x03200009	/* jr $25					*/
+};
+
 /* The format of subsequent MIPS16 o32 PLT entries.  We use v0 ($2)
    and v1 ($3) as temporaries because t8 ($24) and t9 ($25) are not
    directly addressable.  */
@@ -2194,6 +2207,13 @@ jal_reloc_p (int r_type)
 }
 
 static inline bfd_boolean
+aligned_pcrel_reloc_p (int r_type)
+{
+  return (r_type == R_MIPS_PC18_S3
+	  || r_type == R_MIPS_PC19_S2);
+}
+
+static inline bfd_boolean
 micromips_branch_reloc_p (int r_type)
 {
   return (r_type == R_MICROMIPS_26_S1
@@ -5109,6 +5129,8 @@ mips_elf_relocation_needs_la25_stub (bfd *input_bfd, int r_type,
     {
     case R_MIPS_26:
     case R_MIPS_PC16:
+    case R_MIPS_PC21_S2:
+    case R_MIPS_PC26_S2:
     case R_MICROMIPS_26_S1:
     case R_MICROMIPS_PC7_S1:
     case R_MICROMIPS_PC10_S1:
@@ -5893,12 +5915,75 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
 
     case R_MIPS_PC16:
     case R_MIPS_GNU_REL16_S2:
-      value = symbol + _bfd_mips_elf_sign_extend (addend, 18) - p;
+      if (howto->partial_inplace)
+	addend = _bfd_mips_elf_sign_extend (addend, 18);
+      value = symbol + addend - p;
       overflowed_p = mips_elf_overflow_p (value, 18);
       value >>= howto->rightshift;
       value &= howto->dst_mask;
       break;
 
+    case R_MIPS_PC21_S2:
+      if (howto->partial_inplace)
+	addend = _bfd_mips_elf_sign_extend (addend, 23);
+      value = symbol + addend - p;
+      overflowed_p = mips_elf_overflow_p (value, 23);
+      value >>= howto->rightshift;
+      value &= howto->dst_mask;
+      break;
+
+    case R_MIPS_PC26_S2:
+      if (howto->partial_inplace)
+	addend = _bfd_mips_elf_sign_extend (addend, 28);
+      value = symbol + addend - p;
+      overflowed_p = mips_elf_overflow_p (value, 28);
+      value >>= howto->rightshift;
+      value &= howto->dst_mask;
+      break;
+
+    case R_MIPS_PC18_S3:
+      if (howto->partial_inplace)
+	addend = _bfd_mips_elf_sign_extend (addend, 21);
+
+      if ((symbol + addend) & 7)
+	return bfd_reloc_outofrange;
+
+      value = symbol + addend - ((p | 7) ^ 7);
+      overflowed_p = mips_elf_overflow_p (value, 21);
+      value >>= howto->rightshift;
+      value &= howto->dst_mask;
+      break;
+
+    case R_MIPS_PC19_S2:
+      if (howto->partial_inplace)
+	addend = _bfd_mips_elf_sign_extend (addend, 21);
+
+      if ((symbol + addend) & 3)
+	return bfd_reloc_outofrange;
+
+      value = symbol + addend - p;
+      overflowed_p = mips_elf_overflow_p (value, 21);
+      value >>= howto->rightshift;
+      value &= howto->dst_mask;
+      break;
+
+    case R_MIPS_PCHI16:
+      if (howto->partial_inplace)
+	addend = _bfd_mips_elf_sign_extend (addend, 16);
+      value = mips_elf_high (symbol + addend - p);
+      BFD_ASSERT (howto->rightshift == 16);
+      overflowed_p = mips_elf_overflow_p (value, 16);
+      value &= howto->dst_mask;
+      break;
+
+    case R_MIPS_PCLO16:
+      if (howto->partial_inplace)
+	addend = _bfd_mips_elf_sign_extend (addend, 16);
+      value = symbol + addend - p;
+      overflowed_p = mips_elf_overflow_p (value, 32);
+      value &= howto->dst_mask;
+      break;
+
     case R_MICROMIPS_PC7_S1:
       value = symbol + _bfd_mips_elf_sign_extend (addend, 8) - p;
       overflowed_p = mips_elf_overflow_p (value, 8);
@@ -6465,6 +6550,12 @@ _bfd_elf_mips_mach (flagword flags)
 
 	case E_MIPS_ARCH_64R2:
 	  return bfd_mach_mipsisa64r2;
+
+	case E_MIPS_ARCH_32R6:
+	  return bfd_mach_mipsisa32r6;
+
+	case E_MIPS_ARCH_64R6:
+	  return bfd_mach_mipsisa64r6;
 	}
     }
 
@@ -8129,6 +8220,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
 	case R_MIPS_26:
 	case R_MIPS_PC16:
+	case R_MIPS_PC21_S2:
+	case R_MIPS_PC26_S2:
 	case R_MIPS16_26:
 	case R_MICROMIPS_26_S1:
 	case R_MICROMIPS_PC7_S1:
@@ -10048,6 +10141,13 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		(info, msg, name, input_bfd, input_section, rel->r_offset);
 	      return FALSE;
 	    }
+	  if (aligned_pcrel_reloc_p (howto->type))
+	    {
+	      msg = _("pc relative load using unaligned address");
+	      info->callbacks->warning
+		(info, msg, name, input_bfd, input_section, rel->r_offset);
+	      return FALSE;
+	    }
 	  /* Fall through.  */
 
 	default:
@@ -10337,7 +10437,11 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
 	  load = MIPS_ELF_LOAD_WORD (output_bfd);
 
 	  /* Fill in the PLT entry itself.  */
-	  plt_entry = mips_exec_plt_entry;
+
+	  if (MIPSR6_P (output_bfd))
+	    plt_entry = mipsr6_exec_plt_entry;
+	  else
+	    plt_entry = mips_exec_plt_entry;
 	  bfd_put_32 (output_bfd, plt_entry[0] | got_address_high, loc);
 	  bfd_put_32 (output_bfd, plt_entry[1] | got_address_low | load,
 		      loc + 4);
@@ -11670,6 +11774,14 @@ mips_set_isa_flags (bfd *abfd)
     case bfd_mach_mipsisa64r2:
       val = E_MIPS_ARCH_64R2;
       break;
+
+    case bfd_mach_mipsisa32r6:
+      val = E_MIPS_ARCH_32R6;
+      break;
+
+    case bfd_mach_mipsisa64r6:
+      val = E_MIPS_ARCH_64R6;
+      break;
     }
   elf_elfheader (abfd)->e_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH);
   elf_elfheader (abfd)->e_flags |= val;
@@ -14323,7 +14435,8 @@ mips_32bit_flags_p (flagword flags)
 	  || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1
 	  || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2
 	  || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32
-	  || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R2);
+	  || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R2
+	  || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R6);
 }
 
 
@@ -14992,6 +15105,10 @@ _bfd_mips_elf_print_private_bfd_data (bfd *abfd, void *ptr)
     fprintf (file, " [mips32r2]");
   else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64R2)
     fprintf (file, " [mips64r2]");
+  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R6)
+    fprintf (file, " [mips32r6]");
+  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64R6)
+    fprintf (file, " [mips64r6]");
   else
     fprintf (file, _(" [unknown ISA]"));
 
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 09f307f..d6faaec 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1126,6 +1126,10 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_MICROMIPS_7_PCREL_S1",
   "BFD_RELOC_MICROMIPS_10_PCREL_S1",
   "BFD_RELOC_MICROMIPS_16_PCREL_S1",
+  "BFD_RELOC_MIPS_21_PCREL_S2",
+  "BFD_RELOC_MIPS_26_PCREL_S2",
+  "BFD_RELOC_MIPS_18_PCREL_S3",
+  "BFD_RELOC_MIPS_19_PCREL_S2",
   "BFD_RELOC_MICROMIPS_GPREL16",
   "BFD_RELOC_MICROMIPS_HI16",
   "BFD_RELOC_MICROMIPS_HI16_S",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 7f46c58..3aa2515 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2289,6 +2289,17 @@ ENUMDOC
   microMIPS PC-relative relocations.
 
 ENUM
+  BFD_RELOC_MIPS_21_PCREL_S2
+ENUMX
+  BFD_RELOC_MIPS_26_PCREL_S2
+ENUMX
+  BFD_RELOC_MIPS_18_PCREL_S3
+ENUMX
+  BFD_RELOC_MIPS_19_PCREL_S2
+ENUMDOC
+  MIPS PC-relative relocations.
+
+ENUM
   BFD_RELOC_MICROMIPS_GPREL16
 ENUMX
   BFD_RELOC_MICROMIPS_HI16
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 9cafd7c..54f66c2 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -2848,8 +2848,10 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
 	    case E_MIPS_ARCH_5: strcat (buf, ", mips5"); break;
 	    case E_MIPS_ARCH_32: strcat (buf, ", mips32"); break;
 	    case E_MIPS_ARCH_32R2: strcat (buf, ", mips32r2"); break;
+	    case E_MIPS_ARCH_32R6: strcat (buf, ", mips32r6"); break;
 	    case E_MIPS_ARCH_64: strcat (buf, ", mips64"); break;
 	    case E_MIPS_ARCH_64R2: strcat (buf, ", mips64r2"); break;
+	    case E_MIPS_ARCH_64R6: strcat (buf, ", mips64r6"); break;
 	    default: strcat (buf, _(", unknown ISA")); break;
 	    }
 	  break;
diff --git a/binutils/testsuite/binutils-all/objcopy.exp b/binutils/testsuite/binutils-all/objcopy.exp
index 6159b9d..9b22744 100644
--- a/binutils/testsuite/binutils-all/objcopy.exp
+++ b/binutils/testsuite/binutils-all/objcopy.exp
@@ -986,6 +986,7 @@ if [is_elf_format] {
     # targ_defvec=bfd_elf32_nlittlemips_vec in config.bfd.  When syncing,
     # don't forget that earlier case-matches trump later ones.
     if { ![istarget "mips*-sde-elf*"] && ![istarget "mips*-mti-elf*"]
+	 && ![istarget "mips*-img-elf*"]
          && ![istarget "mips64*-*-openbsd*"] } {
 	setup_xfail "mips*-*-irix5*" "mips*-*-irix6*" "mips*-*-elf*" \
 	    "mips*-*-rtems*" "mips*-*-windiss" "mips*-*-none" \
diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp
index 2a6bc6a..e45d6ea 100644
--- a/binutils/testsuite/binutils-all/readelf.exp
+++ b/binutils/testsuite/binutils-all/readelf.exp
@@ -103,6 +103,7 @@ proc readelf_test { options binary_file regexp_file xfails } {
 	if { [istarget "mips*-*-*linux*"]
 	     || [istarget "mips*-sde-elf*"]
 	     || [istarget "mips*-mti-elf*"]
+	     || [istarget "mips*-img-elf*"]
 	     || [istarget "mips*-*freebsd*"] } then {
 	    set target_machine tmips
 	} else {
diff --git a/config.sub b/config.sub
index 61cb4bc..4c5769a 100755
--- a/config.sub
+++ b/config.sub
@@ -283,8 +283,10 @@ case $basic_machine in
 	| mips64vr5900 | mips64vr5900el \
 	| mipsisa32 | mipsisa32el \
 	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa32r6 | mipsisa32r6el \
 	| mipsisa64 | mipsisa64el \
 	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64r6 | mipsisa64r6el \
 	| mipsisa64sb1 | mipsisa64sb1el \
 	| mipsisa64sr71k | mipsisa64sr71kel \
 	| mipsr5900 | mipsr5900el \
@@ -402,8 +404,10 @@ case $basic_machine in
 	| mips64vr5900-* | mips64vr5900el-* \
 	| mipsisa32-* | mipsisa32el-* \
 	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa32r6-* | mipsisa32r6el-* \
 	| mipsisa64-* | mipsisa64el-* \
 	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64r6-* | mipsisa64r6el-* \
 	| mipsisa64sb1-* | mipsisa64sb1el-* \
 	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
 	| mipsr5900-* | mipsr5900el-* \
diff --git a/configure b/configure
index 749a35e..98f8391 100755
--- a/configure
+++ b/configure
@@ -3776,7 +3776,7 @@ case "${target}" in
   microblaze*)
     noconfigdirs="$noconfigdirs gprof"
     ;;
-  mips*-sde-elf* | mips*-mti-elf*)
+  mips*-sde-elf* | mips*-mti-elf* | mips*-img-elf*)
     if test x$with_newlib = xyes; then
       noconfigdirs="$noconfigdirs gprof"
     fi
@@ -6981,7 +6981,7 @@ case "${target}" in
   spu-*-*)
     target_makefile_frag="config/mt-spu"
     ;;
-  mips*-sde-elf* | mips*-mti-elf*)
+  mips*-sde-elf* | mips*-mti-elf* | mips*-img-elf*)
     target_makefile_frag="config/mt-sde"
     ;;
   mipsisa*-*-elfoabi*)
diff --git a/configure.ac b/configure.ac
index b24b33d..df882fb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1106,7 +1106,7 @@ case "${target}" in
   microblaze*)
     noconfigdirs="$noconfigdirs gprof"
     ;;
-  mips*-sde-elf* | mips*-mti-elf*)
+  mips*-sde-elf* | mips*-mti-elf* | mips*-img-elf*)
     if test x$with_newlib = xyes; then
       noconfigdirs="$noconfigdirs gprof"
     fi
@@ -2361,7 +2361,7 @@ case "${target}" in
   spu-*-*)
     target_makefile_frag="config/mt-spu"
     ;;
-  mips*-sde-elf* | mips*-mti-elf*)
+  mips*-sde-elf* | mips*-mti-elf* | mips*-img-elf*)
     target_makefile_frag="config/mt-sde"
     ;;
   mipsisa*-*-elfoabi*)
diff --git a/elfcpp/mips.h b/elfcpp/mips.h
index 91f7270..7fb8256 100644
--- a/elfcpp/mips.h
+++ b/elfcpp/mips.h
@@ -250,6 +250,10 @@ enum
   E_MIPS_ARCH_32R2 = 0x70000000,
   // -mips64r2 code.
   E_MIPS_ARCH_64R2 = 0x80000000,
+  // -mips32r6 code.
+  E_MIPS_ARCH_32R6 = 0x90000000,
+  // -mips64r6 code.
+  E_MIPS_ARCH_64R6 = 0xa0000000,
 };
 
 enum
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 960169e..49771bc 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -345,13 +345,18 @@ static int mips_32bitmode = 0;
    || (ABI) == N64_ABI			\
    || (ABI) == O64_ABI)
 
+#define ISA_IS_R6(ISA)			\
+  ((ISA) == ISA_MIPS32R6		\
+   || (ISA) == ISA_MIPS64R6)
+
 /*  Return true if ISA supports 64 bit wide gp registers.  */
 #define ISA_HAS_64BIT_REGS(ISA)		\
   ((ISA) == ISA_MIPS3			\
    || (ISA) == ISA_MIPS4		\
    || (ISA) == ISA_MIPS5		\
    || (ISA) == ISA_MIPS64		\
-   || (ISA) == ISA_MIPS64R2)
+   || (ISA) == ISA_MIPS64R2		\
+   || (ISA) == ISA_MIPS64R6)
 
 /*  Return true if ISA supports 64 bit wide float registers.  */
 #define ISA_HAS_64BIT_FPRS(ISA)		\
@@ -359,13 +364,16 @@ static int mips_32bitmode = 0;
    || (ISA) == ISA_MIPS4		\
    || (ISA) == ISA_MIPS5		\
    || (ISA) == ISA_MIPS32R2		\
+   || (ISA) == ISA_MIPS32R6		\
    || (ISA) == ISA_MIPS64		\
-   || (ISA) == ISA_MIPS64R2)
+   || (ISA) == ISA_MIPS64R2		\
+   || (ISA) == ISA_MIPS64R6)
 
 /* Return true if ISA supports 64-bit right rotate (dror et al.)
    instructions.  */
 #define ISA_HAS_DROR(ISA)		\
   ((ISA) == ISA_MIPS64R2		\
+   || (ISA) == ISA_MIPS64R6		\
    || (mips_opts.micromips		\
        && ISA_HAS_64BIT_REGS (ISA))	\
    )
@@ -374,7 +382,9 @@ static int mips_32bitmode = 0;
    instructions.  */
 #define ISA_HAS_ROR(ISA)		\
   ((ISA) == ISA_MIPS32R2		\
+   || (ISA) == ISA_MIPS32R6		\
    || (ISA) == ISA_MIPS64R2		\
+   || (ISA) == ISA_MIPS64R6		\
    || (mips_opts.ase & ASE_SMARTMIPS)	\
    || mips_opts.micromips		\
    )
@@ -383,14 +393,18 @@ static int mips_32bitmode = 0;
 #define ISA_HAS_ODD_SINGLE_FPR(ISA)	\
   ((ISA) == ISA_MIPS32			\
    || (ISA) == ISA_MIPS32R2		\
+   || (ISA) == ISA_MIPS32R6		\
    || (ISA) == ISA_MIPS64		\
-   || (ISA) == ISA_MIPS64R2)
+   || (ISA) == ISA_MIPS64R2		\
+   || (ISA) == ISA_MIPS64R6)
 
 /* Return true if ISA supports move to/from high part of a 64-bit
    floating-point register. */
 #define ISA_HAS_MXHC1(ISA)		\
   ((ISA) == ISA_MIPS32R2		\
-   || (ISA) == ISA_MIPS64R2)
+   || (ISA) == ISA_MIPS32R6		\
+   || (ISA) == ISA_MIPS64R2		\
+   || (ISA) == ISA_MIPS64R6)
 
 #define HAVE_32BIT_GPRS		                   \
     (mips_opts.gp32 || !ISA_HAS_64BIT_REGS (mips_opts.isa))
@@ -473,8 +487,10 @@ static int mips_32bitmode = 0;
 #define hilo_interlocks \
   (mips_opts.isa == ISA_MIPS32                        \
    || mips_opts.isa == ISA_MIPS32R2                   \
+   || mips_opts.isa == ISA_MIPS32R6                   \
    || mips_opts.isa == ISA_MIPS64                     \
    || mips_opts.isa == ISA_MIPS64R2                   \
+   || mips_opts.isa == ISA_MIPS64R6                   \
    || mips_opts.arch == CPU_R4010                     \
    || mips_opts.arch == CPU_R5900                     \
    || mips_opts.arch == CPU_R10000                    \
@@ -1318,6 +1334,8 @@ enum options
     OPTION_MIPS64,
     OPTION_MIPS32R2,
     OPTION_MIPS64R2,
+    OPTION_MIPS32R6,
+    OPTION_MIPS64R6,
     OPTION_MIPS16,
     OPTION_NO_MIPS16,
     OPTION_MIPS3D,
@@ -1423,6 +1441,8 @@ struct option md_longopts[] =
   {"mips64", no_argument, NULL, OPTION_MIPS64},
   {"mips32r2", no_argument, NULL, OPTION_MIPS32R2},
   {"mips64r2", no_argument, NULL, OPTION_MIPS64R2},
+  {"mips32r6", no_argument, NULL, OPTION_MIPS32R6},
+  {"mips64r6", no_argument, NULL, OPTION_MIPS64R6},
 
   /* Options which specify Application Specific Extensions (ASEs).  */
   {"mips16", no_argument, NULL, OPTION_MIPS16},
@@ -1559,55 +1579,73 @@ struct mips_ase
   int mips64_rev;
   int micromips32_rev;
   int micromips64_rev;
+
+  /* The architecture revisions for MIPS32, MIPS64, microMIPS32 and microMIPS64
+     where the ASE was removed or -1 if the extension has not been removed.  */
+  int mips32_rem_rev;
+  int mips64_rem_rev;
+  int micromips32_rem_rev;
+  int micromips64_rem_rev;
 };
 
 /* A table of all supported ASEs.  */
 static const struct mips_ase mips_ases[] = {
   { "dsp", ASE_DSP, ASE_DSP64,
     OPTION_DSP, OPTION_NO_DSP,
-    2, 2, 2, 2 },
+    2, 2, 2, 2,
+    6, 6, 6, 6 },
 
   { "dspr2", ASE_DSP | ASE_DSPR2, 0,
     OPTION_DSPR2, OPTION_NO_DSPR2,
-    2, 2, 2, 2 },
+    2, 2, 2, 2,
+    6, 6, 6, 6 },
 
   { "eva", ASE_EVA, 0,
     OPTION_EVA, OPTION_NO_EVA,
-    2, 2, 2, 2 },
+     2,  2,  2,  2,
+    -1, -1, -1, -1 },
 
   { "mcu", ASE_MCU, 0,
     OPTION_MCU, OPTION_NO_MCU,
-    2, 2, 2, 2 },
+     2,  2,  2,  2,
+    -1, -1, -1, -1 },
 
   /* Deprecated in MIPS64r5, but we don't implement that yet.  */
   { "mdmx", ASE_MDMX, 0,
     OPTION_MDMX, OPTION_NO_MDMX,
-    -1, 1, -1, -1 },
+    -1, 1, -1, -1,
+    -1, 6, -1, -1 },
 
   /* Requires 64-bit FPRs, so the minimum MIPS32 revision is 2.  */
   { "mips3d", ASE_MIPS3D, 0,
     OPTION_MIPS3D, OPTION_NO_MIPS3D,
-    2, 1, -1, -1 },
+    2, 1, -1, -1,
+    6, 6, -1, -1 },
 
   { "mt", ASE_MT, 0,
     OPTION_MT, OPTION_NO_MT,
-    2, 2, -1, -1 },
+     2,  2, -1, -1,
+    -1, -1, -1, -1 },
 
   { "smartmips", ASE_SMARTMIPS, 0,
     OPTION_SMARTMIPS, OPTION_NO_SMARTMIPS,
-    1, -1, -1, -1 },
+    1, -1, -1, -1,
+    6, -1, -1, -1 },
 
   { "virt", ASE_VIRT, ASE_VIRT64,
     OPTION_VIRT, OPTION_NO_VIRT,
-    2, 2, 2, 2 },
+     2,  2,  2,  2,
+    -1, -1, -1, -1 },
 
   { "msa", ASE_MSA, ASE_MSA64,
     OPTION_MSA, OPTION_NO_MSA,
-    2, 2, 2, 2 },
+     2,  2,  2,  2,
+    -1, -1, -1, -1 },
 
   { "xpa", ASE_XPA, 0,
     OPTION_XPA, OPTION_NO_XPA,
-    2, 2, -1, -1 }
+     2,  2, -1, -1,
+    -1, -1, -1, -1 },
 };
 
 /* The set of ASEs that require -mfp64.  */
@@ -1858,6 +1896,9 @@ mips_target_format (void)
 static int
 mips_isa_rev (void)
 {
+  if (mips_opts.isa == ISA_MIPS32R6 || mips_opts.isa == ISA_MIPS64R6)
+    return 6;
+
   if (mips_opts.isa == ISA_MIPS32R2 || mips_opts.isa == ISA_MIPS64R2)
     return 2;
 
@@ -1891,14 +1932,22 @@ static void
 mips_check_isa_supports_ase (const struct mips_ase *ase)
 {
   const char *base;
-  int min_rev, size;
+  int size, min_rev, rem_rev;
   static unsigned int warned_isa;
   static unsigned int warned_fp32;
 
   if (ISA_HAS_64BIT_REGS (mips_opts.isa))
-    min_rev = mips_opts.micromips ? ase->micromips64_rev : ase->mips64_rev;
+    {
+      min_rev = mips_opts.micromips ? ase->micromips64_rev : ase->mips64_rev;
+      rem_rev = mips_opts.micromips ? ase->micromips64_rem_rev
+				    : ase->mips64_rem_rev;
+    }
   else
-    min_rev = mips_opts.micromips ? ase->micromips32_rev : ase->mips32_rev;
+    {
+      min_rev = mips_opts.micromips ? ase->micromips32_rev : ase->mips32_rev;
+      rem_rev = mips_opts.micromips ? ase->micromips32_rem_rev
+				    : ase->mips32_rem_rev;
+    }
   if ((min_rev < 0 || mips_isa_rev () < min_rev)
       && (warned_isa & ase->flags) != ase->flags)
     {
@@ -1912,6 +1961,16 @@ mips_check_isa_supports_ase (const struct mips_ase *ase)
 	as_warn (_("the `%s' extension requires %s%d revision %d or greater"),
 		 ase->name, base, size, min_rev);
     }
+  if ((rem_rev > 0 && mips_isa_rev () >= rem_rev)
+      && (warned_isa & ase->flags) != ase->flags)
+    {
+      warned_isa |= ase->flags;
+      base = mips_opts.micromips ? "microMIPS" : "MIPS";
+      size = ISA_HAS_64BIT_REGS (mips_opts.isa) ? 64 : 32;
+      as_warn (_("the `%s' extension was removed in %s%d revision %d"),
+	       ase->name, base, size, rem_rev);
+    }
+
   if ((ase->flags & FP64_ASES)
       && mips_opts.fp32
       && (warned_fp32 & ase->flags) != ase->flags)
@@ -3239,7 +3298,7 @@ validate_mips_insn (const struct mips_opcode *opcode,
 	      used_bits &= ~(mask & 0x700);
 	  }
 	/* Skip prefix characters.  */
-	if (decode_operand && (*s == '+' || *s == 'm'))
+	if (decode_operand && (*s == '+' || *s == 'm' || *s == '-'))
 	  ++s;
 	opno += 1;
 	break;
@@ -3761,9 +3820,15 @@ limited_pcrel_reloc_p (bfd_reloc_code_real_type reloc)
     case BFD_RELOC_MICROMIPS_7_PCREL_S1:
     case BFD_RELOC_MICROMIPS_10_PCREL_S1:
     case BFD_RELOC_MICROMIPS_16_PCREL_S1:
+    case BFD_RELOC_MIPS_21_PCREL_S2:
+    case BFD_RELOC_MIPS_26_PCREL_S2:
+    case BFD_RELOC_MIPS_18_PCREL_S3:
+    case BFD_RELOC_MIPS_19_PCREL_S2:
       return TRUE;
 
     case BFD_RELOC_32_PCREL:
+    case BFD_RELOC_HI16_S_PCREL:
+    case BFD_RELOC_LO16_PCREL:
       return HAVE_64BIT_ADDRESSES;
 
     default:
@@ -4066,6 +4131,24 @@ operand_reg_mask (const struct mips_cl_insn *insn,
       uval = insn_extract_operand (insn, operand);
       return (1 << (uval & 31)) | (1 << (uval >> 5));
 
+    case OP_SAME_RS_RT:
+      if (!(type_mask & (1 << OP_REG_GP)))
+	return 0;
+      uval = insn_extract_operand (insn, operand);
+      gas_assert ((uval & 31) == (uval >> 5));
+      return 1 << (uval & 31);
+
+    case OP_GP_NOT_ZERO:
+    case OP_GP_NOT_ZERO_NOT_PREV:
+    case OP_GP_NOT_ZERO_LT_PREV:
+    case OP_GP_GT_PREV:
+    case OP_GP_LE_PREV:
+    case OP_GP_GE_PREV:
+      if (!(type_mask & (1 << OP_REG_GP)))
+	return 0;
+      uval = insn_extract_operand (insn, operand);
+      return 1 << (uval & 31);
+
     case OP_LWM_SWM_LIST:
       abort ();
 
@@ -4848,6 +4931,161 @@ match_clo_clz_dest_operand (struct mips_arg_info *arg,
   return TRUE;
 }
 
+/* OP_SAME_RS_RT matcher.  */
+
+static bfd_boolean
+match_same_rs_rt_operand (struct mips_arg_info *arg,
+			  const struct mips_operand *operand)
+{
+  unsigned int regno;
+
+  if (!match_reg (arg, OP_REG_GP, &regno))
+    return FALSE;
+
+  if (regno == 0)
+    {
+      set_insn_error (arg->argnum, _("the source register must not be $0"));
+      return FALSE;
+    }
+
+  arg->last_regno = regno;
+
+  insn_insert_operand (arg->insn, operand, regno | (regno << 5));
+  return TRUE;
+}
+
+/* OP_GP_NOT_ZERO matcher.  */
+
+static bfd_boolean
+match_gp_not_zero_operand (struct mips_arg_info *arg,
+			   const struct mips_operand *operand)
+{
+  unsigned int regno;
+
+  if (!match_reg (arg, OP_REG_GP, &regno))
+    return FALSE;
+
+  if (regno == 0)
+    {
+      set_insn_error (arg->argnum, _("the source register must not be $0"));
+      return FALSE;
+    }
+
+  arg->last_regno = regno;
+
+  insn_insert_operand (arg->insn, operand, regno);
+  return TRUE;
+}
+
+/* OP_GP_NOT_ZERO_LT_PREV matcher.  */
+
+static bfd_boolean
+match_gp_not_zero_lt_prev_operand (struct mips_arg_info *arg,
+				   const struct mips_operand *operand)
+{
+  unsigned int regno;
+
+  if (!match_reg (arg, OP_REG_GP, &regno))
+    return FALSE;
+
+  if (regno == 0)
+    {
+      set_insn_error (arg->argnum, _("the source register must not be $0"));
+      return FALSE;
+    }
+
+  if (regno >= arg->last_regno)
+    return FALSE;
+
+  arg->last_regno = regno;
+
+  insn_insert_operand (arg->insn, operand, regno);
+  return TRUE;
+}
+
+/* OP_GP_GT_PREV matcher.  */
+
+static bfd_boolean
+match_gp_gt_prev_operand (struct mips_arg_info *arg,
+			  const struct mips_operand *operand)
+{
+  unsigned int regno;
+
+  if (!match_reg (arg, OP_REG_GP, &regno))
+    return FALSE;
+
+  if (regno <= arg->last_regno)
+    return FALSE;
+
+  arg->last_regno = regno;
+
+  insn_insert_operand (arg->insn, operand, regno);
+  return TRUE;
+}
+
+/* OP_GP_LE_PREV matcher.  */
+
+static bfd_boolean
+match_gp_le_prev_operand (struct mips_arg_info *arg,
+			  const struct mips_operand *operand)
+{
+  unsigned int regno;
+
+  if (!match_reg (arg, OP_REG_GP, &regno))
+    return FALSE;
+
+  if (regno > arg->last_regno)
+    return FALSE;
+
+  arg->last_regno = regno;
+
+  insn_insert_operand (arg->insn, operand, regno);
+  return TRUE;
+}
+
+/* OP_GP_GE_PREV matcher.  */
+
+static bfd_boolean
+match_gp_ge_prev_operand (struct mips_arg_info *arg,
+			  const struct mips_operand *operand)
+{
+  unsigned int regno;
+
+  if (!match_reg (arg, OP_REG_GP, &regno))
+    return FALSE;
+
+  if (regno < arg->last_regno)
+    return FALSE;
+
+  arg->last_regno = regno;
+
+  insn_insert_operand (arg->insn, operand, regno);
+  return TRUE;
+}
+
+/* OP_GP_NOT_ZERO_NOT_PREV matcher.  */
+
+static bfd_boolean
+match_gp_not_zero_not_prev_operand (struct mips_arg_info *arg,
+				    const struct mips_operand *operand)
+{
+  unsigned int regno;
+
+  if (!match_reg (arg, OP_REG_GP, &regno))
+    return FALSE;
+
+  if (regno == 0 || regno == arg->last_regno)
+    {
+      set_insn_error (arg->argnum, _("the source registers must not be $0 and different"));
+      return FALSE;
+    }
+
+  arg->last_regno = regno;
+
+  insn_insert_operand (arg->insn, operand, regno);
+  return TRUE;
+}
+
 /* OP_LWM_SWM_LIST matcher.  */
 
 static bfd_boolean
@@ -5245,11 +5483,13 @@ match_pc_operand (struct mips_arg_info *arg)
    register that we need to match.  */
 
 static bfd_boolean
-match_tied_reg_operand (struct mips_arg_info *arg, unsigned int other_regno)
+match_tied_reg_operand (struct mips_arg_info *arg,
+			enum mips_reg_operand_type type,
+			unsigned int other_regno)
 {
   unsigned int regno;
 
-  return match_reg (arg, OP_REG_GP, &regno) && regno == other_regno;
+  return match_reg (arg, type, &regno) && regno == other_regno;
 }
 
 /* Read a floating-point constant from S for LI.S or LI.D.  LENGTH is
@@ -5495,10 +5735,10 @@ match_operand (struct mips_arg_info *arg,
       return match_mdmx_imm_reg_operand (arg, operand);
 
     case OP_REPEAT_DEST_REG:
-      return match_tied_reg_operand (arg, arg->dest_regno);
+      return match_tied_reg_operand (arg, OP_REG_GP, arg->dest_regno);
 
     case OP_REPEAT_PREV_REG:
-      return match_tied_reg_operand (arg, arg->last_regno);
+      return match_tied_reg_operand (arg, OP_REG_GP, arg->last_regno);
 
     case OP_PC:
       return match_pc_operand (arg);
@@ -5514,6 +5754,28 @@ match_operand (struct mips_arg_info *arg,
 
     case OP_REG_INDEX:
       return match_reg_index_operand (arg, operand);
+
+    case OP_SAME_RS_RT:
+      return match_same_rs_rt_operand (arg, operand);
+
+    case OP_GP_NOT_ZERO:
+      return match_gp_not_zero_operand (arg, operand);
+
+    case OP_GP_NOT_ZERO_LT_PREV:
+      return match_gp_not_zero_lt_prev_operand (arg, operand);
+
+    case OP_GP_GT_PREV:
+      return match_gp_gt_prev_operand (arg, operand);
+
+    case OP_GP_LE_PREV:
+      return match_gp_le_prev_operand (arg, operand);
+
+    case OP_GP_GE_PREV:
+      return match_gp_ge_prev_operand (arg, operand);
+
+    case OP_GP_NOT_ZERO_NOT_PREV:
+      return match_gp_not_zero_not_prev_operand (arg, operand);
+
     }
   abort ();
 }
@@ -5714,6 +5976,11 @@ insns_between (const struct mips_cl_insn *insn1,
 	return 1;
     }
 
+  if (insn1->insn_mo->pinfo2 & INSN2_FORBIDDEN_SLOT
+      && (pinfo2 & INSN_NO_DELAY_SLOT
+	  || (insn2 && delayed_branch_p (insn2))))
+    return 1;
+
   return 0;
 }
 
@@ -6571,6 +6838,46 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
 	  }
 	  break;
 
+	case BFD_RELOC_MIPS_21_PCREL_S2:
+	  {
+	    int shift;
+
+	    shift = 2;
+	    if ((address_expr->X_add_number & ((1 << shift) - 1)) != 0)
+	      as_bad (_("branch to misaligned address (0x%lx)"),
+		      (unsigned long) address_expr->X_add_number);
+	    if (!mips_relax_branch)
+	      {
+		if ((address_expr->X_add_number + (1 << (shift + 20)))
+		    & ~((1 << (shift + 21)) - 1))
+		  as_bad (_("branch address range overflow (0x%lx)"),
+			  (unsigned long) address_expr->X_add_number);
+		ip->insn_opcode |= ((address_expr->X_add_number >> shift)
+				    & 0x1fffff);
+	      }
+	  }
+	  break;
+
+	case BFD_RELOC_MIPS_26_PCREL_S2:
+	  {
+	    int shift;
+
+	    shift = 2;
+	    if ((address_expr->X_add_number & ((1 << shift) - 1)) != 0)
+	      as_bad (_("branch to misaligned address (0x%lx)"),
+		      (unsigned long) address_expr->X_add_number);
+	    if (!mips_relax_branch)
+	      {
+		if ((address_expr->X_add_number + (1 << (shift + 25)))
+		    & ~((1 << (shift + 26)) - 1))
+		  as_bad (_("branch address range overflow (0x%lx)"),
+			  (unsigned long) address_expr->X_add_number);
+		ip->insn_opcode |= ((address_expr->X_add_number >> shift)
+				    & 0x3ffffff);
+	      }
+	  }
+	  break;
+
 	default:
 	  {
 	    offsetT value;
@@ -7235,12 +7542,32 @@ match_insn (struct mips_cl_insn *insn, const struct mips_opcode *opcode,
       arg.opnum += 1;
       switch (*args)
 	{
+	case '-':
+	  switch (args[1])
+	    {
+	    case 'A':
+	      *offset_reloc = BFD_RELOC_MIPS_19_PCREL_S2;
+	      break;
+	    case 'B':
+	      *offset_reloc = BFD_RELOC_MIPS_18_PCREL_S3;
+	      break;
+	    }
+	  break;
+
 	case '+':
 	  switch (args[1])
 	    {
 	    case 'i':
 	      *offset_reloc = BFD_RELOC_MIPS_JMP;
 	      break;
+
+	    case '\'':
+	      *offset_reloc = BFD_RELOC_MIPS_26_PCREL_S2;
+	      break;
+
+	    case '\"':
+	      *offset_reloc = BFD_RELOC_MIPS_21_PCREL_S2;
+	      break;
 	    }
 	  break;
 
@@ -7326,7 +7653,7 @@ match_insn (struct mips_cl_insn *insn, const struct mips_opcode *opcode,
 	abort ();
 
       /* Skip prefixes.  */
-      if (*args == '+' || *args == 'm')
+      if (*args == '+' || *args == 'm' || *args == '-')
 	args++;
 
       if (mips_optional_operand_p (operand)
@@ -7977,7 +8304,7 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...)
 	    uval |= (uval << 5);
 	  insn_insert_operand (&insn, operand, uval);
 
-	  if (*fmt == '+' || *fmt == 'm')
+	  if (*fmt == '+' || *fmt == 'm' || *fmt == '-')
 	    ++fmt;
 	  break;
 	}
@@ -13263,7 +13590,9 @@ static const struct percent_op_match mips_percent_op[] =
   {"%tprel_hi", BFD_RELOC_MIPS_TLS_TPREL_HI16},
   {"%tprel_lo", BFD_RELOC_MIPS_TLS_TPREL_LO16},
   {"%gottprel", BFD_RELOC_MIPS_TLS_GOTTPREL},
-  {"%hi", BFD_RELOC_HI16_S}
+  {"%hi", BFD_RELOC_HI16_S},
+  {"%pcrel_hi", BFD_RELOC_HI16_S_PCREL},
+  {"%pcrel_lo", BFD_RELOC_LO16_PCREL}
 };
 
 static const struct percent_op_match mips16_percent_op[] =
@@ -13533,10 +13862,18 @@ md_parse_option (int c, char *arg)
       file_mips_isa = ISA_MIPS32R2;
       break;
 
+    case OPTION_MIPS32R6:
+      file_mips_isa = ISA_MIPS32R6;
+      break;
+
     case OPTION_MIPS64R2:
       file_mips_isa = ISA_MIPS64R2;
       break;
 
+    case OPTION_MIPS64R6:
+      file_mips_isa = ISA_MIPS64R6;
+      break;
+
     case OPTION_MIPS64:
       file_mips_isa = ISA_MIPS64;
       break;
@@ -13978,6 +14315,9 @@ mips_after_parse_args (void)
 	       && ISA_HAS_64BIT_FPRS (mips_opts.isa))
 	/* -mips3d and -mdmx imply 64-bit float registers, if possible.  */
 	file_mips_fp32 = 0;
+      else if (ISA_IS_R6 (mips_opts.isa))
+	/* R6 implies 64-bit float registers.  */
+	file_mips_fp32 = 0;
       else
 	/* 32-bit float registers.  */
 	file_mips_fp32 = 1;
@@ -13995,6 +14335,8 @@ mips_after_parse_args (void)
     case 1:
       if (ABI_NEEDS_64BIT_REGS (mips_abi))
 	as_warn (_("-mfp32 used with a 64-bit ABI"));
+      else if (ISA_IS_R6 (mips_opts.isa))
+	as_bad (_("-mfp32 used with a MIPS R6 cpu"));
       break;
     }
 
@@ -14037,6 +14379,12 @@ mips_after_parse_args (void)
 
   if (mips_flag_mdebug < 0)
     mips_flag_mdebug = 0;
+
+  if (ISA_IS_R6 (mips_opts.isa) && mips_relax_branch)
+    as_bad (_("branch relaxation not supported in mips32r6 or mips64r6"));
+
+  if (ISA_IS_R6 (mips_opts.isa) && mips_opts.micromips == 1)
+    as_bad (_("micromips is not supported in mips32r6 or mips64r6"));
 }
 

 void
@@ -14061,10 +14409,19 @@ md_pcrel_from (fixS *fixP)
     case BFD_RELOC_MICROMIPS_16_PCREL_S1:
     case BFD_RELOC_MICROMIPS_JMP:
     case BFD_RELOC_16_PCREL_S2:
+    case BFD_RELOC_MIPS_21_PCREL_S2:
+    case BFD_RELOC_MIPS_26_PCREL_S2:
     case BFD_RELOC_MIPS_JMP:
       /* Return the address of the delay slot.  */
       return addr + 4;
 
+    case BFD_RELOC_32_PCREL:
+    case BFD_RELOC_MIPS_19_PCREL_S2:
+    case BFD_RELOC_HI16_S_PCREL:
+    case BFD_RELOC_LO16_PCREL:
+    case BFD_RELOC_MIPS_18_PCREL_S3:
+      return addr;
+
     default:
       return addr;
     }
@@ -14226,6 +14583,17 @@ mips_force_relocation (fixS *fixp)
       || fixp->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1)
     return 1;
 
+  /* We want all relocations to be kept for R6 relaxation */
+  if (ISA_IS_R6 (mips_opts.isa)
+      && (fixp->fx_r_type == BFD_RELOC_16_PCREL_S2
+	  || fixp->fx_r_type == BFD_RELOC_MIPS_21_PCREL_S2
+	  || fixp->fx_r_type == BFD_RELOC_MIPS_26_PCREL_S2
+	  || fixp->fx_r_type == BFD_RELOC_MIPS_18_PCREL_S3
+	  || fixp->fx_r_type == BFD_RELOC_MIPS_19_PCREL_S2
+	  || fixp->fx_r_type == BFD_RELOC_HI16_S_PCREL
+	  || fixp->fx_r_type == BFD_RELOC_LO16_PCREL))
+    return 1;
+
   return 0;
 }
 
@@ -14270,6 +14638,12 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
       case BFD_RELOC_MICROMIPS_10_PCREL_S1:
       case BFD_RELOC_MICROMIPS_16_PCREL_S1:
       case BFD_RELOC_32_PCREL:
+      case BFD_RELOC_MIPS_21_PCREL_S2:
+      case BFD_RELOC_MIPS_26_PCREL_S2:
+      case BFD_RELOC_MIPS_19_PCREL_S2:
+      case BFD_RELOC_HI16_S_PCREL:
+      case BFD_RELOC_LO16_PCREL:
+      case BFD_RELOC_MIPS_18_PCREL_S3:
 	break;
 
       case BFD_RELOC_32:
@@ -14462,6 +14836,81 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 	md_number_to_chars (buf, *valP, fixP->fx_size);
       break;
 
+    case BFD_RELOC_MIPS_21_PCREL_S2:
+      if ((*valP & 0x3) != 0)
+	as_bad_where (fixP->fx_file, fixP->fx_line,
+		      _("branch to misaligned address (%lx)"), (long) *valP);
+
+      /* We need to save the bits in the instruction since fixup_segment()
+	 might be deleting the relocation entry (i.e., a branch within
+	 the current segment).  */
+      if (! fixP->fx_done)
+	break;
+
+      /* Update old instruction data.  */
+      insn = read_insn (buf);
+
+      if (*valP + 0x400000 <= 0x7fffff)
+	{
+	  insn |= (*valP >> 2) & 0x1fffff;
+	  write_insn (buf, insn);
+	}
+      else
+	{
+	  /* CFU FIXME.  */
+	  gas_assert (0);
+	}
+      break;
+
+    case BFD_RELOC_MIPS_26_PCREL_S2:
+      if ((*valP & 0x3) != 0)
+	as_bad_where (fixP->fx_file, fixP->fx_line,
+		      _("branch to misaligned address (%lx)"), (long) *valP);
+
+      /* We need to save the bits in the instruction since fixup_segment()
+	 might be deleting the relocation entry (i.e., a branch within
+	 the current segment).  */
+      if (! fixP->fx_done)
+	break;
+
+      /* Update old instruction data.  */
+      insn = read_insn (buf);
+
+      if (*valP + 0x8000000 <= 0xfffffff)
+	{
+	  insn |= (*valP >> 2) & 0x3ffffff;
+	  write_insn (buf, insn);
+	}
+      else
+	{
+	  /* CFU FIXME.  */
+	  gas_assert (0);
+	}
+      break;
+
+    case BFD_RELOC_MIPS_18_PCREL_S3:
+      if ((*valP & 0x3) != 0)
+	as_bad_where (fixP->fx_file, fixP->fx_line,
+		      _("pc rel from misaligned address (%lx)"),
+		      (long) *valP);
+
+      gas_assert(!fixP->fx_done);
+      break;
+
+    case BFD_RELOC_MIPS_19_PCREL_S2:
+      if ((*valP & 0x3) != 0)
+	as_bad_where (fixP->fx_file, fixP->fx_line,
+		      _("pc rel from misaligned address (%lx)"),
+		      (long) *valP);
+
+      gas_assert(!fixP->fx_done);
+      break;
+
+    case BFD_RELOC_HI16_S_PCREL:
+    case BFD_RELOC_LO16_PCREL:
+      gas_assert(!fixP->fx_done);
+      break;
+
     case BFD_RELOC_16_PCREL_S2:
       if ((*valP & 0x3) != 0)
 	as_bad_where (fixP->fx_file, fixP->fx_line,
@@ -15030,6 +15479,9 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
     {
       if (mips_opts.mips16 == 1)
 	as_fatal (_("`micromips' cannot be used with `mips16'"));
+      else if (ISA_IS_R6 (mips_opts.isa))
+	as_fatal (_("`micromips' cannot be used with `mips32r6' or `mips64r6'"));
+
       mips_opts.micromips = 1;
     }
   else if (strcmp (name, "nomicromips") == 0)
@@ -15092,6 +15544,10 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
 	  mips_opts.gp32 = 1;
 	  mips_opts.fp32 = 1;
 	  break;
+	case ISA_MIPS32R6:
+	  mips_opts.gp32 = 1;
+	  mips_opts.fp32 = 0;
+	  break;
 	case ISA_MIPS3:
 	case ISA_MIPS4:
 	case ISA_MIPS5:
@@ -15107,6 +15563,10 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
 	  mips_opts.fp32 = 0;
 	    }
 	  break;
+	case ISA_MIPS64R6:
+	  mips_opts.gp32 = 0;
+	  mips_opts.fp32 = 0;
+	  break;
 	default:
 	  as_bad (_("unknown ISA level %s"), name + 4);
 	  break;
@@ -16538,7 +16998,13 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
 		  || fixp->fx_r_type == BFD_RELOC_MICROMIPS_7_PCREL_S1
 		  || fixp->fx_r_type == BFD_RELOC_MICROMIPS_10_PCREL_S1
 		  || fixp->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1
-		  || fixp->fx_r_type == BFD_RELOC_32_PCREL);
+		  || fixp->fx_r_type == BFD_RELOC_32_PCREL
+		  || fixp->fx_r_type == BFD_RELOC_MIPS_21_PCREL_S2
+		  || fixp->fx_r_type == BFD_RELOC_MIPS_26_PCREL_S2
+		  || fixp->fx_r_type == BFD_RELOC_MIPS_18_PCREL_S3
+		  || fixp->fx_r_type == BFD_RELOC_MIPS_19_PCREL_S2
+		  || fixp->fx_r_type == BFD_RELOC_HI16_S_PCREL
+		  || fixp->fx_r_type == BFD_RELOC_LO16_PCREL);
 
       /* At this point, fx_addnumber is "symbol offset - pcrel address".
 	 Relocations want only the symbol offset.  */
@@ -17806,8 +18272,10 @@ static const struct mips_cpu_info mips_cpu_info_table[] =
   { "mips5",          MIPS_CPU_IS_ISA, 0,	ISA_MIPS5,    CPU_MIPS5 },
   { "mips32",         MIPS_CPU_IS_ISA, 0,	ISA_MIPS32,   CPU_MIPS32 },
   { "mips32r2",       MIPS_CPU_IS_ISA, 0,	ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "mips32r6",       MIPS_CPU_IS_ISA, 0,	ISA_MIPS32R6, CPU_MIPS32R6 },
   { "mips64",         MIPS_CPU_IS_ISA, 0,	ISA_MIPS64,   CPU_MIPS64 },
   { "mips64r2",       MIPS_CPU_IS_ISA, 0,	ISA_MIPS64R2, CPU_MIPS64R2 },
+  { "mips64r6",       MIPS_CPU_IS_ISA, 0,	ISA_MIPS64R6, CPU_MIPS64R6 },
 
   /* MIPS I */
   { "r3000",          0, 0,			ISA_MIPS1,    CPU_R3000 },
@@ -18120,8 +18588,10 @@ MIPS options:\n\
 -mips5                  generate MIPS ISA V instructions\n\
 -mips32                 generate MIPS32 ISA instructions\n\
 -mips32r2               generate MIPS32 release 2 ISA instructions\n\
+-mips32r6               generate MIPS32 release 6 ISA instructions\n\
 -mips64                 generate MIPS64 ISA instructions\n\
 -mips64r2               generate MIPS64 release 2 ISA instructions\n\
+-mips64r6               generate MIPS64 release 6 ISA instructions\n\
 -march=CPU/-mtune=CPU	generate code/schedule for CPU, where CPU is one of:\n"));
 
   first = 1;
diff --git a/gas/configure b/gas/configure
index 27b9d1d..37d7bea 100755
--- a/gas/configure
+++ b/gas/configure
@@ -12036,12 +12036,18 @@ _ACEOF
 	  mipsisa32r2 | mipsisa32r2el)
 	    mips_cpu=mips32r2
 	    ;;
+	  mipsisa32r6 | mipsisa32r6el)
+	    mips_cpu=mips32r6
+	    ;;
 	  mipsisa64 | mipsisa64el)
 	    mips_cpu=mips64
 	    ;;
 	  mipsisa64r2 | mipsisa64r2el)
 	    mips_cpu=mips64r2
 	    ;;
+	  mipsisa64r6 | mipsisa64r6el)
+	    mips_cpu=mips64r6
+	    ;;
 	  mipstx39 | mipstx39el)
 	    mips_cpu=r3900
 	    ;;
@@ -12051,6 +12057,9 @@ _ACEOF
 	  mipsisa32r2* | mipsisa64r2*)
 	    mips_cpu=`echo $target_cpu | sed -e 's/[a-z]*..r2//' -e 's/el$//'`
 	    ;;
+	  mipsisa32r6* | mipsisa64r6*)
+	    mips_cpu=`echo $target_cpu | sed -e 's/[a-z]*..r6//' -e 's/el$//'`
+	    ;;
 	  mips64* | mipsisa64* | mipsisa32*)
 	    mips_cpu=`echo $target_cpu | sed -e 's/[a-z]*..//' -e 's/el$//'`
 	    ;;
diff --git a/gas/configure.in b/gas/configure.in
index 33cd50b..68fa5be 100644
--- a/gas/configure.in
+++ b/gas/configure.in
@@ -213,12 +213,18 @@ changequote([,])dnl
 	  mipsisa32r2 | mipsisa32r2el)
 	    mips_cpu=mips32r2
 	    ;;
+	  mipsisa32r6 | mipsisa32r6el)
+	    mips_cpu=mips32r6
+	    ;;
 	  mipsisa64 | mipsisa64el)
 	    mips_cpu=mips64
 	    ;;
 	  mipsisa64r2 | mipsisa64r2el)
 	    mips_cpu=mips64r2
 	    ;;
+	  mipsisa64r6 | mipsisa64r6el)
+	    mips_cpu=mips64r6
+	    ;;
 	  mipstx39 | mipstx39el)
 	    mips_cpu=r3900
 	    ;;
@@ -230,6 +236,11 @@ changequote(,)dnl
 	    mips_cpu=`echo $target_cpu | sed -e 's/[a-z]*..r2//' -e 's/el$//'`
 changequote([,])dnl
 	    ;;
+	  mipsisa32r6* | mipsisa64r6*)
+changequote(,)dnl
+	    mips_cpu=`echo $target_cpu | sed -e 's/[a-z]*..r6//' -e 's/el$//'`
+changequote([,])dnl
+	    ;;
 	  mips64* | mipsisa64* | mipsisa32*)
 changequote(,)dnl
 	    mips_cpu=`echo $target_cpu | sed -e 's/[a-z]*..//' -e 's/el$//'`
diff --git a/gas/configure.tgt b/gas/configure.tgt
index 7d5afa9..11f2688 100644
--- a/gas/configure.tgt
+++ b/gas/configure.tgt
@@ -326,7 +326,8 @@ case ${generic_target} in
   mips*-*-freebsd* | mips*-*-kfreebsd*-gnu)
 					fmt=elf em=freebsd ;;
   mips-*-sysv4*MP* | mips-*-gnu*)	fmt=elf em=tmips ;;
-  mips*-sde-elf* | mips*-mti-elf*)	fmt=elf em=tmips ;;
+  mips*-sde-elf* | mips*-mti-elf* | mips*-img-elf*)
+					fmt=elf em=tmips ;;
   mips-*-elf* | mips-*-rtems*)		fmt=elf ;;
   mips-*-netbsd*)			fmt=elf em=tmips ;;
   mips-*-openbsd*)			fmt=elf em=tmips ;;
diff --git a/gas/doc/c-mips.texi b/gas/doc/c-mips.texi
index 0c5e82d..ffcf27f 100644
--- a/gas/doc/c-mips.texi
+++ b/gas/doc/c-mips.texi
@@ -81,17 +81,20 @@ VxWorks-style position-independent macro expansions.
 @itemx -mips5
 @itemx -mips32
 @itemx -mips32r2
+@itemx -mips32r6
 @itemx -mips64
 @itemx -mips64r2
+@itemx -mips64r6
 Generate code for a particular MIPS Instruction Set Architecture level.
 @samp{-mips1} corresponds to the R2000 and R3000 processors,
 @samp{-mips2} to the R6000 processor, @samp{-mips3} to the
 R4000 processor, and @samp{-mips4} to the R8000 and R10000 processors.
-@samp{-mips5}, @samp{-mips32}, @samp{-mips32r2}, @samp{-mips64}, and
-@samp{-mips64r2} correspond to generic MIPS V, MIPS32, MIPS32 Release 2,
-MIPS64, and MIPS64 Release 2 ISA processors, respectively.  You can also
-switch instruction sets during the assembly; see @ref{MIPS ISA,
-Directives to override the ISA level}.
+@samp{-mips5}, @samp{-mips32}, @samp{-mips32r2}, @samp{-mips32r6},
+@samp{-mips64}, @samp{-mips64r2} and @samp{-mips64r6} correspond to
+generic MIPS V, MIPS32, MIPS32 Release 2, MIPS32 Release 6, MIPS64,
+MIPS64 Release 2, and MIPS64 Release 6 ISA processors, respectively.
+You can also switch instruction sets during the assembly; see
+@ref{MIPS ISA, Directives to override the ISA level}.
 
 @item -mgp32
 @itemx -mfp32
@@ -652,8 +655,8 @@ Small data is not supported for SVR4-style PIC.
 @kindex @code{.set mips@var{n}}
 @sc{gnu} @code{@value{AS}} supports an additional directive to change
 the MIPS Instruction Set Architecture level on the fly: @code{.set
-mips@var{n}}.  @var{n} should be a number from 0 to 5, or 32, 32r2, 64
-or 64r2.
+mips@var{n}}.  @var{n} should be a number from 0 to 5, or 32, 32r2,
+32r6, 64, 64r2 or 64r6.
 The values other than 0 make the assembler accept instructions
 for the corresponding ISA level, from that point on in the
 assembly.  @code{.set mips@var{n}} affects not only which instructions
diff --git a/include/elf/mips.h b/include/elf/mips.h
index 2949629..1d15ac2 100644
--- a/include/elf/mips.h
+++ b/include/elf/mips.h
@@ -87,7 +87,14 @@ START_RELOC_NUMBERS (elf_mips_reloc_type)
   RELOC_NUMBER (R_MIPS_TLS_TPREL_HI16, 49)
   RELOC_NUMBER (R_MIPS_TLS_TPREL_LO16, 50)
   RELOC_NUMBER (R_MIPS_GLOB_DAT, 51)
-  FAKE_RELOC (R_MIPS_max, 52)
+  /* Space to grow */
+  RELOC_NUMBER (R_MIPS_PC21_S2, 60)
+  RELOC_NUMBER (R_MIPS_PC26_S2, 61)
+  RELOC_NUMBER (R_MIPS_PC18_S3, 62)
+  RELOC_NUMBER (R_MIPS_PC19_S2, 63)
+  RELOC_NUMBER (R_MIPS_PCHI16, 64)
+  RELOC_NUMBER (R_MIPS_PCLO16, 65)
+  FAKE_RELOC (R_MIPS_max, 66)
   /* These relocs are used for the mips16.  */
   FAKE_RELOC (R_MIPS16_min, 100)
   RELOC_NUMBER (R_MIPS16_26, 100)
@@ -237,6 +244,12 @@ END_RELOC_NUMBERS (R_MIPS_maxext)
 /* -mips64r2 code.  */
 #define E_MIPS_ARCH_64R2        0x80000000
 
+/* -mips32r6 code.  */
+#define E_MIPS_ARCH_32R6        0x90000000
+
+/* -mips64r6 code.  */
+#define E_MIPS_ARCH_64R6        0xa0000000
+
 /* The ABI of the file.  Also see EF_MIPS_ABI2 above. */
 #define EF_MIPS_ABI		0x0000F000
 
diff --git a/include/opcode/mips.h b/include/opcode/mips.h
index a5d2935..d0d5c03 100644
--- a/include/opcode/mips.h
+++ b/include/opcode/mips.h
@@ -417,7 +417,34 @@ enum mips_operand_type {
   OP_IMM_INDEX,
 
   /* An index selected by a register, e.g. [$2].  */
-  OP_REG_INDEX
+  OP_REG_INDEX,
+
+  /* The operand spans two 5-bit register fields, both of which must be set to
+     the source register.  */
+  OP_SAME_RS_RT,
+
+  /* The operand is a GP register but not $0.  */
+  OP_GP_NOT_ZERO,
+
+  /* The operand is a GP register but the register number is less than the
+     previous operand's register number but not $0.  */
+  OP_GP_NOT_ZERO_LT_PREV,
+
+  /* The operand is a GP register but the register number is greater than the
+     previous operand's register number.  */
+  OP_GP_GT_PREV,
+
+  /* The operand is a GP register but the register number is less than or equal
+     to the previous operand's register number.  */
+  OP_GP_LE_PREV,
+
+  /* The operand is a GP register but the register number is greater than or
+     equal to the previous operand's register number.  */
+  OP_GP_GE_PREV,
+
+  /* The operand is a GP register but the register number is both not $0 and
+     not the same as the previous operand's register number.  */
+  OP_GP_NOT_ZERO_NOT_PREV
 };
 
 /* Enumerates the types of MIPS register.  */
@@ -927,6 +954,27 @@ struct mips_opcode
    "+*" 5-bit register vector element index at bit 16
    "+|" 8-bit mask at bit 16
 
+   MIPS R6:
+   "+:" 11-bit mask at bit 0
+   "+'" 26 bit PC relative branch target address
+   "+"" 21 bit PC relative branch target address
+   "+;" 5 bit same register in both OP_*_RS and OP_*_RT
+   "+I" 2bit unsigned bit position at bit 6
+   "+O" 3bit unsigned bit position at bit 6
+   "+R" must be program counter
+   "-a" (-262144 .. 262143) << 2 at bit 0
+   "-b" (-131072 .. 131071) << 3 at bit 0
+   "-d" Same as destination register GP
+   "-s" 5 bit source register specifier (OP_*_RS) not $0
+   "-t" 5 bit source register specifier (OP_*_RT) not $0
+   "-u" 5 bit source register specifier (OP_*_RT) greater than OP_*_RS
+   "-v" 5 bit source register specifier (OP_*_RT) not $0 not OP_*_RS
+   "-w" 5 bit source register specifier (OP_*_RT) less than OP_*_RS
+   "-x" 5 bit source register specifier (OP_*_RT) greater than OP_*_RS
+   "-y" 5 bit source register specifier (OP_*_RT) not $0 less than OP_*_RS
+   "-A" symbolic offset (-262144 .. 262143) << 2 at bit 0
+   "-B" symbolic offset (-131072 .. 131071) << 3 at bit 0
+
    Other:
    "()" parens surrounding optional value
    ","  separates operands
@@ -934,16 +982,21 @@ 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:
    "1234567890"
-   "~!@#$%^&*|"
-   "ABCEFGHJKLMNPQSTUVWXZ"
+   "~!@#$%^&*|:'";"
+   "ABCEFGHIJKLMNOPQRSTUVWXZ"
    "abcdefghijklmnopqrstuvwxyz"
+
+   Extension character sequences used so far ("-" followed by the
+   following), for quick reference when adding more:
+   "AB"
+   "abdstuvwxy"
 */
 
 /* These are the bits which may be set in the pinfo field of an
@@ -1051,6 +1104,8 @@ struct mips_opcode
 #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
+/* Instruction has a forbidden slot.  */
+#define INSN2_FORBIDDEN_SLOT        0x00008000
 
 /* Masks used to mark instructions to indicate which MIPS ISA level
    they were introduced in.  INSN_ISA_MASK masks an enumeration that
@@ -1058,7 +1113,7 @@ struct mips_opcode
    word constructed using these macros is a bitmask of the remaining
    INSN_* values below.  */
 
-#define INSN_ISA_MASK		  0x0000000ful
+#define INSN_ISA_MASK		  0x0000001ful
 
 /* We cannot start at zero due to ISA_UNKNOWN below.  */
 #define INSN_ISA1                 1
@@ -1079,9 +1134,11 @@ struct mips_opcode
 #define INSN_ISA4_32              12
 #define INSN_ISA4_32R2            13
 #define INSN_ISA5_32R2            14
+#define INSN_ISA32R6              15
+#define INSN_ISA64R6              16
 
 /* Given INSN_ISA* values X and Y, where X ranges over INSN_ISA1 through
-   INSN_ISA5_32R2 and Y ranges over INSN_ISA1 through INSN_ISA64R2,
+   INSN_ISA32R6 and Y ranges over INSN_ISA1 through INSN_ISA64R6,
    this table describes whether at least one of the ISAs described by X
    is/are implemented by ISA Y.  (Think of Y as the ISA level supported by
    a particular core and X as the ISA level(s) at which a certain instruction
@@ -1089,7 +1146,8 @@ struct mips_opcode
    (mips_isa_table[(Y & INSN_ISA_MASK) - 1] >> ((X & INSN_ISA_MASK) - 1)) & 1
    is non-zero.  */
 static const unsigned int mips_isa_table[] =
-  { 0x0001, 0x0003, 0x0607, 0x1e0f, 0x3e1f, 0x0a23, 0x3e63, 0x3ebf, 0x3fff };
+  { 0x0001, 0x0003, 0x0607, 0x1e0f, 0x3e1f, 0x0a23, 0x3e63, 0x3ebf, 0x3fff,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7e63, 0xffff };
 
 /* Masks used for Chip specific instructions.  */
 #define INSN_CHIP_MASK		  0xc3ff0f20
@@ -1173,6 +1231,8 @@ static const unsigned int mips_isa_table[] =
 #define       ISA_MIPS32R2    INSN_ISA32R2
 #define       ISA_MIPS64R2    INSN_ISA64R2
 
+#define       ISA_MIPS32R6    INSN_ISA32R6
+#define       ISA_MIPS64R6    INSN_ISA64R6
 
 /* CPU defines, use instead of hardcoding processor number. Keep this
    in sync with bfd/archures.c in order for machine selection to work.  */
@@ -1203,9 +1263,11 @@ static const unsigned int mips_isa_table[] =
 #define CPU_MIPS16	16
 #define CPU_MIPS32	32
 #define CPU_MIPS32R2	33
+#define CPU_MIPS32R6	34
 #define CPU_MIPS5       5
 #define CPU_MIPS64      64
 #define CPU_MIPS64R2	65
+#define CPU_MIPS64R6	66
 #define CPU_SB1         12310201        /* octal 'SB', 01.  */
 #define CPU_LOONGSON_2E 3001
 #define CPU_LOONGSON_2F 3002
@@ -1281,6 +1343,13 @@ cpu_is_member (int cpu, unsigned int mask)
     case CPU_XLR:
       return (mask & INSN_XLR) != 0;
 
+    case CPU_MIPS32R6:
+      return (mask & INSN_ISA_MASK) == INSN_ISA32R6;
+
+    case CPU_MIPS64R6:
+      return ((mask & INSN_ISA_MASK) == INSN_ISA32R6)
+	     || ((mask & INSN_ISA_MASK) == INSN_ISA64R6);
+
     default:
       return FALSE;
     }
@@ -2121,7 +2190,7 @@ extern const int bfd_mips16_num_opcodes;
 
    Characters used so far, for quick reference when adding more:
    "12345678 0"
-   "<>(),+.@\^|~"
+   "<>(),+-.@\^|~"
    "ABCDEFGHI KLMN   RST V    "
    "abcd f hijklmnopqrstuvw yz"
 
@@ -2138,6 +2207,12 @@ extern const int bfd_mips16_num_opcodes;
    ""
    " BCDEFGHIJ LMNOPQ   U WXYZ"
    " bcdefghij lmn pq st   xyz"
+
+   Extension character sequences used so far ("-" followed by the
+   following), for quick reference when adding more:
+   ""
+   ""
+   <none so far>
 */
 
 extern const struct mips_operand *decode_micromips_operand (const char *);
diff --git a/ld/configure.tgt b/ld/configure.tgt
index 2b11d44..81a6728 100644
--- a/ld/configure.tgt
+++ b/ld/configure.tgt
@@ -454,7 +454,7 @@ mips*vr5000el-*-elf*)	targ_emul=elf32l4300 ;;
 mips*vr5000-*-elf*)	targ_emul=elf32b4300 ;;
 mips*el-sde-elf*)	targ_emul=elf32ltsmip
 			targ_extra_emuls="elf32btsmip elf32ltsmipn32 elf64ltsmip elf32btsmipn32 elf64btsmip" ;;
-mips*-sde-elf* | mips*-mti-elf*)
+mips*-sde-elf* | mips*-mti-elf* | mips*-img-elf*)
 			targ_emul=elf32btsmip
 			targ_extra_emuls="elf32ltsmip elf32btsmipn32 elf64btsmip elf32ltsmipn32 elf64ltsmip" ;;
 mips64*el-ps2-elf*)	targ_emul=elf32lr5900n32
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 4c7ea68..592b0c4 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -611,8 +611,10 @@ get_emulation (int argc, char **argv)
 		   || strcmp (argv[i], "-mips5") == 0
 		   || strcmp (argv[i], "-mips32") == 0
 		   || strcmp (argv[i], "-mips32r2") == 0
+		   || strcmp (argv[i], "-mips32r6") == 0
 		   || strcmp (argv[i], "-mips64") == 0
-		   || strcmp (argv[i], "-mips64r2") == 0)
+		   || strcmp (argv[i], "-mips64r2") == 0
+		   || strcmp (argv[i], "-mips64r6") == 0)
 	    {
 	      /* FIXME: The arguments -mips1, -mips2, -mips3, etc. are
 		 passed to the linker by some MIPS compilers.  They
diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp
index a2632b2..2d3f052 100644
--- a/ld/testsuite/ld-mips-elf/mips-elf.exp
+++ b/ld/testsuite/ld-mips-elf/mips-elf.exp
@@ -55,7 +55,8 @@ if {![istarget mips*-*-*] || ![is_elf_format]} {
 set has_newabi [expr [istarget *-*-irix6*] \
 		     || [istarget mips*-*-linux*] \
 		     || [istarget mips*-sde-elf*] \
-		     || [istarget mips*-mti-elf*]]
+		     || [istarget mips*-mti-elf*] \
+		     || [istarget mips*-img-elf*]]
 set linux_gnu [expr [istarget mips*-*-linux*]]
 set embedded_elf [expr [istarget mips*-*-elf]]
 
@@ -79,7 +80,7 @@ if { [istarget *-*-irix6*] } {
     set abi_ldflags(o32) -melf32btsmip_fbsd
 }
 if { [istarget mips*-*-linux*] || [istarget mips*-sde-elf*]
-     || [istarget mips*-mti-elf*] } {
+     || [istarget mips*-mti-elf*] || [istarget mips*-img-elf*]} {
     set abi_ldflags(n32) -melf32btsmipn32
     set abi_ldflags(n64) -melf64btsmip
 } elseif { [istarget mips64*-*freebsd*] } {
diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c
index 0f8624e..7a5aa27 100644
--- a/opcodes/mips-dis.c
+++ b/opcodes/mips-dis.c
@@ -556,6 +556,13 @@ const struct mips_arch_choice mips_arch_choices[] =
     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
     mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
 
+  { "mips32r6",	1, bfd_mach_mipsisa32r6, CPU_MIPS32R6,
+    ISA_MIPS32R6,
+    (ASE_EVA | ASE_MSA | ASE_VIRT | ASE_XPA | ASE_MCU | ASE_MT),
+    mips_cp0_names_mips3264r2,
+    mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
+    mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
+
   /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs.  */
   { "mips64",	1, bfd_mach_mipsisa64, CPU_MIPS64,
     ISA_MIPS64,  ASE_MIPS3D | ASE_MDMX,
@@ -571,6 +578,14 @@ const struct mips_arch_choice mips_arch_choices[] =
     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
     mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
 
+  { "mips64r6",	1, bfd_mach_mipsisa64r6, CPU_MIPS64R6,
+    ISA_MIPS64R6,
+    (ASE_EVA | ASE_MSA | ASE_MSA64 | ASE_XPA | ASE_VIRT | ASE_VIRT64 
+     | ASE_MCU | ASE_MT),
+    mips_cp0_names_mips3264r2,
+    mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
+    mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
+
   { "sb1",	1, bfd_mach_mips_sb1, CPU_SB1,
     ISA_MIPS64 | INSN_SB1,  ASE_MIPS3D,
     mips_cp0_names_sb1,
@@ -798,7 +813,8 @@ parse_mips_dis_option (const char *option, unsigned int len)
   if (CONST_STRNEQ (option, "msa"))
     {
       mips_ase |= ASE_MSA;
-      if ((mips_isa & INSN_ISA_MASK) == ISA_MIPS64R2)
+      if ((mips_isa & INSN_ISA_MASK) == ISA_MIPS64R2
+	   || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6)
 	  mips_ase |= ASE_MSA64;
       return;
     }
@@ -806,7 +822,8 @@ parse_mips_dis_option (const char *option, unsigned int len)
   if (CONST_STRNEQ (option, "virt"))
     {
       mips_ase |= ASE_VIRT;
-      if (mips_isa & ISA_MIPS64R2)
+      if (mips_isa & ISA_MIPS64R2
+	  || mips_isa & ISA_MIPS64R6)
 	mips_ase |= ASE_VIRT64;
       return;
     }
@@ -1048,6 +1065,8 @@ struct mips_print_arg_state {
      OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG.  */
   enum mips_reg_operand_type last_reg_type;
   unsigned int last_regno;
+  unsigned int dest_regno;
+  unsigned int seen_dest;
 };
 
 /* Initialize STATE for the start of an instruction.  */
@@ -1077,6 +1096,23 @@ print_vu0_channel (struct disassemble_info *info,
     abort ();
 }
 
+/* Record information about a register operand */
+
+static void
+mips_seen_register (struct mips_print_arg_state *state,
+		    unsigned int regno,
+		    enum mips_reg_operand_type reg_type)
+{
+  state->last_reg_type = reg_type;
+  state->last_regno = regno;
+
+  if (!state->seen_dest)
+    {
+      state->seen_dest = 1;
+      state->dest_regno = regno;
+    }
+}
+
 /* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
    UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
    the base address for OP_PCREL operands.  */
@@ -1143,8 +1179,7 @@ print_insn_arg (struct disassemble_info *info,
 	uval = mips_decode_reg_operand (reg_op, uval);
 	print_reg (info, opcode, reg_op->reg_type, uval);
 
-	state->last_reg_type = reg_op->reg_type;
-	state->last_regno = uval;
+	mips_seen_register (state, uval, reg_op->reg_type);
       }
       break;
 
@@ -1210,6 +1245,87 @@ print_insn_arg (struct disassemble_info *info,
       }
       break;
 
+    case OP_SAME_RS_RT:
+      {
+	unsigned int reg1, reg2;
+
+	reg1 = uval & 31;
+	reg2 = uval >> 5;
+
+	if (reg1 == reg2 && reg1 != 0)
+	  infprintf (is, "%s", mips_gpr_names[reg1]);
+	else
+	  infprintf (is, "(ERROR)\t%s,%s", mips_gpr_names[reg2],
+		     mips_gpr_names[reg1]);
+      }
+      break;
+
+    case OP_GP_NOT_ZERO:
+      {
+	if (uval != 0)
+	  infprintf (is, "%s", mips_gpr_names[uval]);
+	else
+	  infprintf (is, "(ERROR)\t%s", mips_gpr_names[uval]);
+
+	mips_seen_register (state, uval, OP_REG_GP);
+      }
+      break;
+
+    case OP_GP_NOT_ZERO_LT_PREV:
+      {
+	if (uval != 0 && uval < state->last_regno)
+	  infprintf (is, "%s", mips_gpr_names[uval]);
+	else
+	  infprintf (is, "(ERROR)\t%s", mips_gpr_names[uval]);
+
+	mips_seen_register (state, uval, OP_REG_GP);
+      }
+      break;
+
+    case OP_GP_GT_PREV:
+      {
+	if (uval > state->last_regno)
+	  infprintf (is, "%s", mips_gpr_names[uval]);
+	else
+	  infprintf (is, "(ERROR)\t%s", mips_gpr_names[uval]);
+
+	mips_seen_register (state, uval, OP_REG_GP);
+      }
+      break;
+
+    case OP_GP_LE_PREV:
+      {
+	if (uval <= state->last_regno)
+	  infprintf (is, "%s", mips_gpr_names[uval]);
+	else
+	  infprintf (is, "(ERROR)\t%s", mips_gpr_names[uval]);
+
+	mips_seen_register (state, uval, OP_REG_GP);
+      }
+      break;
+
+    case OP_GP_GE_PREV:
+      {
+	if (uval >= state->last_regno)
+	  infprintf (is, "%s", mips_gpr_names[uval]);
+	else
+	  infprintf (is, "(ERROR)\t%s", mips_gpr_names[uval]);
+
+	mips_seen_register (state, uval, OP_REG_GP);
+      }
+      break;
+
+    case OP_GP_NOT_ZERO_NOT_PREV:
+      {
+	if (uval != 0 && uval != state->last_regno)
+	  infprintf (is, "%s", mips_gpr_names[uval]);
+	else
+	  infprintf (is, "(ERROR)\t%s", mips_gpr_names[uval]);
+
+	mips_seen_register (state, uval, OP_REG_GP);
+      }
+      break;
+
     case OP_LWM_SWM_LIST:
       if (operand->size == 2)
 	{
@@ -1332,8 +1448,7 @@ print_insn_arg (struct disassemble_info *info,
       break;
 
     case OP_REPEAT_DEST_REG:
-      /* Should always match OP_REPEAT_PREV_REG first.  */
-      abort ();
+      print_reg (info, opcode, state->last_reg_type, state->dest_regno);
 
     case OP_PC:
       infprintf (is, "$pc");
@@ -1358,13 +1473,14 @@ print_insn_arg (struct disassemble_info *info,
 
 /* Print the arguments for INSN, which is described by OPCODE.
    Use DECODE_OPERAND to get the encoding of each operand.  Use BASE_PC
-   as the base of OP_PCREL operands.  */
+   as the base of OP_PCREL operands adjusting by LENGTH if the OP_PCREL
+   operand is for a branch or jump.  */
 
 static void
 print_insn_args (struct disassemble_info *info,
 		 const struct mips_opcode *opcode,
 		 const struct mips_operand *(*decode_operand) (const char *),
-		 unsigned int insn, bfd_vma base_pc)
+		 unsigned int insn, bfd_vma insn_pc, unsigned int length)
 {
   const fprintf_ftype infprintf = info->fprintf_func;
   void *is = info->stream;
@@ -1426,9 +1542,27 @@ print_insn_args (struct disassemble_info *info,
 		infprintf (is, "$%d,%d", reg, sel);
 	    }
 	  else
-	    print_insn_arg (info, &state, opcode, operand, base_pc,
-			    mips_extract_operand (operand, insn));
-	  if (*s == 'm' || *s == '+')
+	    {
+	      bfd_vma base_pc = insn_pc;
+
+	      /* Adjust the PC relative base so that branch/jump insns use
+		 the following PC as the base but genuinely PC relative
+		 operands use the current PC.  */
+	      if (operand->type == OP_PCREL)
+		{
+		  const struct mips_pcrel_operand *pcrel_op;
+
+		  pcrel_op = (const struct mips_pcrel_operand *) operand;
+		  /* The include_isa_bit flag is sufficient to distinguish
+		     branch/jump from other PC relative operands.  */
+		  if (pcrel_op->include_isa_bit)
+		    base_pc += length;
+		}
+
+	      print_insn_arg (info, &state, opcode, operand, base_pc,
+			      mips_extract_operand (operand, insn));
+	    }
+	  if (*s == 'm' || *s == '+' || *s == '-')
 	    ++s;
 	  break;
 	}
@@ -1494,9 +1628,60 @@ print_insn_mips (bfd_vma memaddr,
 	      && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
 	      && (word & op->mask) == op->match)
 	    {
+	      if (strcmp (op->name, "bgezc") == 0
+		  || strcmp (op->name, "bltzc") == 0
+		  || strcmp (op->name, "bgezalc") == 0
+		  || strcmp (op->name, "bltzalc") == 0)
+		{
+		  if (((word >> 16) & 31) != ((word >> 21) & 31)
+		      || ((word >> 16) & 31) == 0)
+		    continue;
+		}
+	      else if (strcmp (op->name, "blezalc") == 0
+		       || strcmp (op->name, "bgtzalc") == 0
+		       || strcmp (op->name, "blezc") == 0
+		       || strcmp (op->name, "bgtzc") == 0
+		       || strcmp (op->name, "beqzalc") == 0
+		       || strcmp (op->name, "bnezalc") == 0)
+		{
+		  if (((word >> 16) & 31) == 0)
+		    continue;
+		}
+	      else if (strcmp (op->name, "bgec") == 0
+		       || strcmp (op->name, "bltc") == 0
+		       || strcmp (op->name, "bbec") == 0
+		       || strcmp (op->name, "bstc") == 0)
+		{
+		  if (((word >> 16) & 31) == ((word >> 21) & 31)
+		      || ((word >> 21) & 31) == 0
+		      || ((word >> 16) & 31) == 0)
+		    continue;
+		}
+	      else if (strcmp (op->name, "beqc") == 0
+		       || strcmp (op->name, "bnec") == 0)
+		{
+		  if (((word >> 21) & 31) >= ((word >> 16) & 31)
+		      || ((word >> 21) & 31) == 0)
+		    continue;
+		}
+	      else if (strcmp (op->name, "bovc") == 0
+		       || strcmp (op->name, "bnvc") == 0)
+		{
+		  if (((word >> 21) & 31) < ((word >> 16) & 31))
+		    continue;
+		}
+	      else if (strcmp (op->name, "beqzc") == 0
+		       || strcmp (op->name, "bnezc") == 0)
+		{
+		  if (((word >> 21) & 31) == 0)
+		    continue;
+		}
+
 	      /* We always allow to disassemble the jalx instruction.  */
 	      if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
-		  && strcmp (op->name, "jalx"))
+		 && (strcmp (op->name, "jalx")
+		     || (mips_isa & INSN_ISA_MASK) == ISA_MIPS32R6
+		     || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6))
 		continue;
 
 	      /* Figure out instruction type and branch delay information.  */
@@ -1535,7 +1720,7 @@ print_insn_mips (bfd_vma memaddr,
 		{
 		  infprintf (is, "\t");
 		  print_insn_args (info, op, decode_mips_operand, word,
-				   memaddr + 4);
+				   memaddr, 4);
 		}
 
 	      return INSNLEN;
@@ -2047,7 +2232,7 @@ print_insn_micromips (bfd_vma memaddr, struct disassemble_info *info)
 	    {
 	      infprintf (is, "\t");
 	      print_insn_args (info, op, decode_micromips_operand, insn,
-			       memaddr + length + 1);
+			       memaddr + 1, length);
 	    }
 
 	  /* Figure out instruction type and branch delay information.  */
diff --git a/opcodes/mips-opc.c b/opcodes/mips-opc.c
index 9181c3f..4b6ebb1 100644
--- a/opcodes/mips-opc.c
+++ b/opcodes/mips-opc.c
@@ -40,6 +40,24 @@ decode_mips_operand (const char *p)
 {
   switch (p[0])
     {
+    case '-':
+      switch (p[1])
+	{
+	case 'a': INT_ADJ (19, 0, 262143, 2, FALSE);
+	case 'b': INT_ADJ (18, 0, 131071, 3, FALSE);
+	case 'd': SPECIAL (0, 0, REPEAT_DEST_REG);
+	case 's': SPECIAL (5, 21, GP_NOT_ZERO);
+	case 't': SPECIAL (5, 16, GP_NOT_ZERO);
+	case 'u': SPECIAL (5, 16, GP_GT_PREV);
+	case 'v': SPECIAL (5, 16, GP_NOT_ZERO_NOT_PREV);
+	case 'w': SPECIAL (5, 16, GP_LE_PREV);
+	case 'x': SPECIAL (5, 21, GP_GE_PREV);
+	case 'y': SPECIAL (5, 21, GP_NOT_ZERO_LT_PREV);
+	case 'A': PCREL (19, 0, TRUE, 2, 2, FALSE, FALSE);
+	case 'B': PCREL (18, 0, TRUE, 3, 3, FALSE, FALSE);
+	}
+      break;
+
     case '+':
       switch (p[1])
 	{
@@ -61,13 +79,16 @@ decode_mips_operand (const char *p)
 	case 'F': MSB (5, 11, 33, TRUE, 64);	/* (33 .. 64), 64-bit op */
 	case 'G': MSB (5, 11, 33, FALSE, 64);	/* (33 .. 64), 64-bit op */
 	case 'H': MSB (5, 11, 1, FALSE, 64);	/* (1 .. 32), 64-bit op */
+	case 'I': UINT (2, 6);
 	case 'J': HINT (10, 11);
 	case 'K': SPECIAL (4, 21, VU0_MATCH_SUFFIX);
 	case 'L': SPECIAL (2, 21, VU0_SUFFIX);
 	case 'M': SPECIAL (2, 23, VU0_SUFFIX);
 	case 'N': SPECIAL (2, 0, VU0_MATCH_SUFFIX);
+	case 'O': UINT (3, 6);
 	case 'P': BIT (5, 6, 32);		/* (32 .. 63) */
 	case 'Q': SINT (10, 6);
+	case 'R': SPECIAL (0, 0, PC);
 	case 'S': MSB (5, 11, 0, FALSE, 63);	/* (0 .. 31), 64-bit op */
 	case 'T': INT_ADJ (10, 16, 511, 0, FALSE); /* (-512 .. 511) << 0 */
 	case 'U': INT_ADJ (10, 16, 511, 1, FALSE); /* (-512 .. 511) << 1 */
@@ -113,6 +134,10 @@ decode_mips_operand (const char *p)
 	case '&': SPECIAL (0, 0, IMM_INDEX);
 	case '*': SPECIAL (5, 16, REG_INDEX);
 	case '|': BIT (8, 16, 0);		/* (0 .. 255) */
+	case ':': SINT (11, 0);
+	case '\'': BRANCH (26, 0, 2);
+	case '"': BRANCH (21, 0, 2);
+	case ';': SPECIAL (10, 16, SAME_RS_RT);
 	}
       break;
 
@@ -241,6 +266,9 @@ decode_mips_operand (const char *p)
 #define WR_MACC INSN2_WRITE_MDMX_ACC
 #define RD_MACC INSN2_READ_MDMX_ACC
 
+#define RD_pc   INSN2_READ_PC
+#define FS      INSN2_FORBIDDEN_SLOT
+
 #define I1	INSN_ISA1
 #define I2	INSN_ISA2
 #define I3	INSN_ISA3
@@ -250,6 +278,8 @@ decode_mips_operand (const char *p)
 #define I64     INSN_ISA64
 #define I33	INSN_ISA32R2
 #define I65	INSN_ISA64R2
+#define I34	INSN_ISA32R6
+#define I66	INSN_ISA64R6
 #define I3_32   INSN_ISA3_32
 #define I3_33   INSN_ISA3_32R2
 #define I4_32   INSN_ISA4_32
@@ -381,9 +411,10 @@ const struct mips_opcode mips_builtin_opcodes[] =
    them first.  The assemblers uses a hash table based on the
    instruction name anyhow.  */
 /* name,		args,		match,	    mask,	pinfo,          	pinfo2,		membership,	ase,	exclusions */
-{"pref",		"k,o(b)",	0xcc000000, 0xfc000000, RD_3|LM,           	0,		I4_32|G3,	0,	0 },
-{"pref",		"k,A(b)",	0,    (int) M_PREF_AB,	INSN_MACRO,		0,		I4_32|G3,	0,	0 },
-{"prefx",		"h,t(b)",	0x4c00000f, 0xfc0007ff, RD_2|RD_3|FP_S|LM,		0,		I4_33,		0,	0 },
+{"pref",		"k,+j(b)",	0x7c000035, 0xfc00007f, RD_3,			0,		I34,		0,	0 },
+{"pref",		"k,o(b)",	0xcc000000, 0xfc000000, RD_3|LM,           	0,		I4_32|G3,	0,	I34 },
+{"pref",		"k,A(b)",	0,    (int) M_PREF_AB,	INSN_MACRO,		0,		I4_32|G3,	0,	I34 },
+{"prefx",		"h,t(b)",	0x4c00000f, 0xfc0007ff, RD_2|RD_3|FP_S|LM,		0,		I4_33,		0,	I34 },
 {"nop",			"",		0x00000000, 0xffffffff, 0,              	INSN2_ALIAS,	I1,		0,	0 }, /* sll */
 {"ssnop",		"",		0x00000040, 0xffffffff, 0,              	INSN2_ALIAS,	I1,		0,	0 }, /* sll */
 {"ehb",			"",		0x000000c0, 0xffffffff, 0,              	INSN2_ALIAS,	I1,		0,	0 }, /* sll */
@@ -396,7 +427,12 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"move",		"d,s",		0x00000025, 0xfc1f07ff,	WR_1|RD_2,		INSN2_ALIAS,	I1,		0,	0 },/* or */
 {"b",			"p",		0x10000000, 0xffff0000,	UBD,			INSN2_ALIAS,	I1,		0,	0 },/* beq 0,0 */
 {"b",			"p",		0x04010000, 0xffff0000,	UBD,			INSN2_ALIAS,	I1,		0,	0 },/* bgez 0 */
+{"nal",			"p",		0x04100000, 0xffff0000,	WR_31|CBD,		INSN2_ALIAS,	I1,		0,	0 },/* bltzal 0 */
 {"bal",			"p",		0x04110000, 0xffff0000,	WR_31|UBD,		INSN2_ALIAS,	I1,		0,	0 },/* bgezal 0*/
+{"bc",			"+'",		0xc8000000, 0xfc000000,	NODS,			0,		I34,		0,	0 },
+{"balc",		"+'",		0xe8000000, 0xfc000000,	WR_31|NODS,		0,		I34,		0,	0 },
+{"lapc",		"s,-A",		0xec000000, 0xfc180000, WR_1|RD_pc,		0,		I34,		0,	0 },
+{"la",			"t,A(b)",	0,    (int) M_LA_AB,	INSN_MACRO,		0,		I1,		0,	0 },
 
 /* Loongson specific instructions.  Loongson 3A redefines the Coprocessor 2
    instructions.  Put them here so that disassembler will find them first.
@@ -590,26 +626,27 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"abs",			"d,v",		0,    (int) M_ABS,	INSN_MACRO,		0,		I1,		0,	0 },
 {"abs.s",		"D,V",		0x46000005, 0xffff003f,	WR_1|RD_2|FP_S,		0,		I1,		0,	0 },
 {"abs.d",		"D,V",		0x46200005, 0xffff003f,	WR_1|RD_2|FP_D,		0,		I1,		0,	SF },
-{"abs.ps",		"D,V",		0x46c00005, 0xffff003f,	WR_1|RD_2|FP_D,		0,		I5_33|IL2F,	0,	0 },
+{"abs.ps",		"D,V",		0x46c00005, 0xffff003f,	WR_1|RD_2|FP_D,		0,		I5_33|IL2F,	0,	I34 },
 {"abs.ps",		"D,V",		0x45600005, 0xffff003f,	WR_1|RD_2|FP_D,		0,		IL2E,		0,	0 },
 {"aclr",		"\\,~(b)",	0x04070000, 0xfc1f8000,	RD_3|LM|SM|NODS,	0,		0,		MC,	0 },
 {"aclr",		"\\,A(b)",	0,    (int) M_ACLR_AB,	INSN_MACRO,		0,		0,		MC,	0 },
 {"add",			"d,v,t",	0x00000020, 0xfc0007ff,	WR_1|RD_2|RD_3,		0,		I1,		0,	0 },
-{"add",			"t,r,I",	0,    (int) M_ADD_I,	INSN_MACRO,		0,		I1,		0,	0 },
+{"add",			"t,r,I",	0,    (int) M_ADD_I,	INSN_MACRO,		0,		I1,		0,	I34 },
 {"add",			"D,S,T",	0x45c00000, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		IL2E,		0,	0 },
 {"add",			"D,S,T",	0x4b40000c, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		IL2F|IL3A,	0,	0 },
 {"add.s",		"D,V,T",	0x46000000, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I1,		0,	0 },
 {"add.d",		"D,V,T",	0x46200000, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I1,		0,	SF },
 {"add.ob",		"X,Y,Q",	0x7800000b, 0xfc20003f,	WR_1|RD_2|RD_3|FP_D,	0,		SB1,		MX,	0 },
 {"add.ob",		"D,S,Q",	0x4800000b, 0xfc20003f,	WR_1|RD_2|RD_3|FP_D,	0,		N54,		0,	0 },
-{"add.ps",		"D,V,T",	0x46c00000, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"add.ps",		"D,V,T",	0x46c00000, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"add.ps",		"D,V,T",	0x45600000, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2E,		0,	0 },
 {"add.qh",		"X,Y,Q",	0x7820000b, 0xfc20003f,	WR_1|RD_2|RD_3|FP_D,	0,		0,		MX,	0 },
 {"adda.ob",		"Y,Q",		0x78000037, 0xfc2007ff,	RD_1|RD_2|FP_D,		WR_MACC,	SB1,		MX,	0 },
 {"adda.qh",		"Y,Q",		0x78200037, 0xfc2007ff,	RD_1|RD_2|FP_D,		WR_MACC,	0,		MX,	0 },
 {"adda.s",		"S,T",		0x46000018, 0xffe007ff,	RD_1|RD_2|FP_S,		0,		EE,		0,	0 },
-{"addi",		"t,r,j",	0x20000000, 0xfc000000,	WR_1|RD_2,		0,		I1,		0,	0 },
+{"addi",		"t,r,j",	0x20000000, 0xfc000000,	WR_1|RD_2,		0,		I1,		0,	I34 },
 {"addiu",		"t,r,j",	0x24000000, 0xfc000000,	WR_1|RD_2,		0,		I1,		0,	0 },
+{"addiupc",		"s,-a",		0xec000000, 0xfc180000, WR_1|RD_pc,		0,		I34,		0,	0 },
 {"addl.ob",		"Y,Q",		0x78000437, 0xfc2007ff,	RD_1|RD_2|FP_D,		WR_MACC,	SB1,		MX,	0 },
 {"addl.qh",		"Y,Q",		0x78200437, 0xfc2007ff,	RD_1|RD_2|FP_D,		WR_MACC,	0,		MX,	0 },
 {"addr.ps",		"D,S,T",	0x46c00018, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		0,		M3D,	0 },
@@ -620,7 +657,7 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"alni.ob",		"X,Y,Z,O",	0x78000018, 0xff00003f,	WR_1|RD_2|RD_3|FP_D,	0,		SB1,		MX,	0 },
 {"alni.ob",		"D,S,T,%",	0x48000018, 0xff00003f,	WR_1|RD_2|RD_3|FP_D, 	0,		N54,		0,	0 },
 {"alni.qh",		"X,Y,Z,O",	0x7800001a, 0xff00003f,	WR_1|RD_2|RD_3|FP_D,	0,		0,		MX,	0 },
-{"alnv.ps",		"D,V,T,s",	0x4c00001e, 0xfc00003f,	WR_1|RD_2|RD_3|RD_4|FP_D, 0,		I5_33,		0,	0 },
+{"alnv.ps",		"D,V,T,s",	0x4c00001e, 0xfc00003f,	WR_1|RD_2|RD_3|RD_4|FP_D, 0,		I5_33,		0,	I34 },
 {"alnv.ob",		"X,Y,Z,s",	0x78000019, 0xfc00003f,	WR_1|RD_2|RD_3|RD_4|FP_D, 0,		SB1,		MX,	0 },
 {"alnv.qh",		"X,Y,Z,s",	0x7800001b, 0xfc00003f,	WR_1|RD_2|RD_3|RD_4|FP_D, 0,		0,		MX,	0 },
 {"and",			"d,v,t",	0x00000024, 0xfc0007ff,	WR_1|RD_2|RD_3,		0,		I1,		0,	0 },
@@ -647,198 +684,200 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"bc1any2t",		"N,p",		0x45210000, 0xffe30000,	RD_CC|CBD|FP_S,		0,		0,		M3D,	0 },
 {"bc1any4f",		"N,p",		0x45400000, 0xffe30000,	RD_CC|CBD|FP_S,		0,		0,		M3D,	0 },
 {"bc1any4t",		"N,p",		0x45410000, 0xffe30000,	RD_CC|CBD|FP_S,		0,		0,		M3D,	0 },
-{"bc1f",		"p",		0x45000000, 0xffff0000,	RD_CC|CBD|FP_S,		0,		I1,		0,	0 },
-{"bc1f",		"N,p",		0x45000000, 0xffe30000, RD_CC|CBD|FP_S, 	0,		I4_32,		0,	0 },
-{"bc1fl",		"p",		0x45020000, 0xffff0000,	RD_CC|CBL|FP_S,		0,		I2|T3,		0,	0 },
-{"bc1fl",		"N,p",		0x45020000, 0xffe30000, RD_CC|CBL|FP_S, 	0,		I4_32,		0,	0 },
-{"bc1t",		"p",		0x45010000, 0xffff0000,	RD_CC|CBD|FP_S,		0,		I1,		0,	0 },
-{"bc1t",		"N,p",		0x45010000, 0xffe30000, RD_CC|CBD|FP_S, 	0,		I4_32,		0,	0 },
-{"bc1tl",		"p",		0x45030000, 0xffff0000,	RD_CC|CBL|FP_S,		0,		I2|T3,		0,	0 },
-{"bc1tl",		"N,p",		0x45030000, 0xffe30000, RD_CC|CBL|FP_S, 	0,		I4_32,		0,	0 },
+{"bc1eqz",		"T,p",		0x45200000, 0xffe00000,	RD_1|CBD|FP_D,		0,		I34,		0,	0 },
+{"bc1f",		"p",		0x45000000, 0xffff0000,	RD_CC|CBD|FP_S,		0,		I1,		0,	I34 },
+{"bc1f",		"N,p",		0x45000000, 0xffe30000, RD_CC|CBD|FP_S, 	0,		I4_32,		0,	I34 },
+{"bc1fl",		"p",		0x45020000, 0xffff0000,	RD_CC|CBL|FP_S,		0,		I2|T3,		0,	I34 },
+{"bc1fl",		"N,p",		0x45020000, 0xffe30000, RD_CC|CBL|FP_S, 	0,		I4_32,		0,	I34 },
+{"bc1nez",		"T,p",		0x45a00000, 0xffe00000,	RD_1|CBD|FP_D,		0,		I34,		0,	0 },
+{"bc1t",		"p",		0x45010000, 0xffff0000,	RD_CC|CBD|FP_S,		0,		I1,		0,	I34 },
+{"bc1t",		"N,p",		0x45010000, 0xffe30000, RD_CC|CBD|FP_S, 	0,		I4_32,		0,	I34 },
+{"bc1tl",		"p",		0x45030000, 0xffff0000,	RD_CC|CBL|FP_S,		0,		I2|T3,		0,	I34 },
+{"bc1tl",		"N,p",		0x45030000, 0xffe30000, RD_CC|CBL|FP_S, 	0,		I4_32,		0,	I34 },
 /* bc2* are at the bottom of the table.  */
 /* bc3* are at the bottom of the table.  */
 {"beqz",		"s,p",		0x10000000, 0xfc1f0000,	RD_1|CBD,		0,		I1,		0,	0 },
-{"beqzl",		"s,p",		0x50000000, 0xfc1f0000,	RD_1|CBL,		0,		I2|T3,		0,	0 },
+{"beqzl",		"s,p",		0x50000000, 0xfc1f0000,	RD_1|CBL,		0,		I2|T3,		0,	I34 },
 {"beq",			"s,t,p",	0x10000000, 0xfc000000,	RD_1|RD_2|CBD,		0,		I1,		0,	0 },
 {"beq",			"s,I,p",	0,    (int) M_BEQ_I,	INSN_MACRO,		0,		I1,		0,	0 },
-{"beql",		"s,t,p",	0x50000000, 0xfc000000,	RD_1|RD_2|CBL,		0,		I2|T3,		0,	0 },
-{"beql",		"s,I,p",	0,    (int) M_BEQL_I,	INSN_MACRO,		0,		I2|T3,		0,	0 },
+{"beql",		"s,t,p",	0x50000000, 0xfc000000,	RD_1|RD_2|CBL,		0,		I2|T3,		0,	I34 },
+{"beql",		"s,I,p",	0,    (int) M_BEQL_I,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
 {"bge",			"s,t,p",	0,    (int) M_BGE,	INSN_MACRO,		0,		I1,		0,	0 },
 {"bge",			"s,I,p",	0,    (int) M_BGE_I,	INSN_MACRO,		0,		I1,		0,	0 },
-{"bgel",		"s,t,p",	0,    (int) M_BGEL,	INSN_MACRO,		0,		I2|T3,		0,	0 },
-{"bgel",		"s,I,p",	0,    (int) M_BGEL_I,	INSN_MACRO,		0,		I2|T3,		0,	0 },
+{"bgel",		"s,t,p",	0,    (int) M_BGEL,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
+{"bgel",		"s,I,p",	0,    (int) M_BGEL_I,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
 {"bgeu",		"s,t,p",	0,    (int) M_BGEU,	INSN_MACRO,		0,		I1,		0,	0 },
 {"bgeu",		"s,I,p",	0,    (int) M_BGEU_I,	INSN_MACRO,		0,		I1,		0,	0 },
-{"bgeul",		"s,t,p",	0,    (int) M_BGEUL,	INSN_MACRO,		0,		I2|T3,		0,	0 },
-{"bgeul",		"s,I,p",	0,    (int) M_BGEUL_I,	INSN_MACRO,		0,		I2|T3,		0,	0 },
+{"bgeul",		"s,t,p",	0,    (int) M_BGEUL,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
+{"bgeul",		"s,I,p",	0,    (int) M_BGEUL_I,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
 {"bgez",		"s,p",		0x04010000, 0xfc1f0000,	RD_1|CBD,		0,		I1,		0,	0 },
-{"bgezl",		"s,p",		0x04030000, 0xfc1f0000,	RD_1|CBL,		0,		I2|T3,		0,	0 },
-{"bgezal",		"s,p",		0x04110000, 0xfc1f0000,	RD_1|WR_31|CBD,		0,		I1,		0,	0 },
-{"bgezall",		"s,p",		0x04130000, 0xfc1f0000,	RD_1|WR_31|CBL,		0,		I2|T3,		0,	0 },
+{"bgezl",		"s,p",		0x04030000, 0xfc1f0000,	RD_1|CBL,		0,		I2|T3,		0,	I34 },
+{"bgezal",		"s,p",		0x04110000, 0xfc1f0000,	RD_1|WR_31|CBD,		0,		I1,		0,	I34 },
+{"bgezall",		"s,p",		0x04130000, 0xfc1f0000,	RD_1|WR_31|CBL,		0,		I2|T3,		0,	I34 },
 {"bgt",			"s,t,p",	0,    (int) M_BGT,	INSN_MACRO,		0,		I1,		0,	0 },
 {"bgt",			"s,I,p",	0,    (int) M_BGT_I,	INSN_MACRO,		0,		I1,		0,	0 },
-{"bgtl",		"s,t,p",	0,    (int) M_BGTL,	INSN_MACRO,		0,		I2|T3,		0,	0 },
-{"bgtl",		"s,I,p",	0,    (int) M_BGTL_I,	INSN_MACRO,		0,		I2|T3,		0,	0 },
+{"bgtl",		"s,t,p",	0,    (int) M_BGTL,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
+{"bgtl",		"s,I,p",	0,    (int) M_BGTL_I,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
 {"bgtu",		"s,t,p",	0,    (int) M_BGTU,	INSN_MACRO,		0,		I1,		0,	0 },
 {"bgtu",		"s,I,p",	0,    (int) M_BGTU_I,	INSN_MACRO,		0,		I1,		0,	0 },
-{"bgtul",		"s,t,p",	0,    (int) M_BGTUL,	INSN_MACRO,		0,		I2|T3,		0,	0 },
-{"bgtul",		"s,I,p",	0,    (int) M_BGTUL_I,	INSN_MACRO,		0,		I2|T3,		0,	0 },
+{"bgtul",		"s,t,p",	0,    (int) M_BGTUL,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
+{"bgtul",		"s,I,p",	0,    (int) M_BGTUL_I,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
 {"bgtz",		"s,p",		0x1c000000, 0xfc1f0000,	RD_1|CBD,		0,		I1,		0,	0 },
-{"bgtzl",		"s,p",		0x5c000000, 0xfc1f0000,	RD_1|CBL,		0,		I2|T3,		0,	0 },
+{"bgtzl",		"s,p",		0x5c000000, 0xfc1f0000,	RD_1|CBL,		0,		I2|T3,		0,	I34 },
 {"ble",			"s,t,p",	0,    (int) M_BLE,	INSN_MACRO,		0,		I1,		0,	0 },
 {"ble",			"s,I,p",	0,    (int) M_BLE_I,	INSN_MACRO,		0,		I1,		0,	0 },
-{"blel",		"s,t,p",	0,    (int) M_BLEL,	INSN_MACRO,		0,		I2|T3,		0,	0 },
-{"blel",		"s,I,p",	0,    (int) M_BLEL_I,	INSN_MACRO,		0,		I2|T3,		0,	0 },
+{"blel",		"s,t,p",	0,    (int) M_BLEL,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
+{"blel",		"s,I,p",	0,    (int) M_BLEL_I,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
 {"bleu",		"s,t,p",	0,    (int) M_BLEU,	INSN_MACRO,		0,		I1,		0,	0 },
 {"bleu",		"s,I,p",	0,    (int) M_BLEU_I,	INSN_MACRO,		0,		I1,		0,	0 },
-{"bleul",		"s,t,p",	0,    (int) M_BLEUL,	INSN_MACRO,		0,		I2|T3,		0,	0 },
-{"bleul",		"s,I,p",	0,    (int) M_BLEUL_I,	INSN_MACRO,		0,		I2|T3,		0,	0 },
+{"bleul",		"s,t,p",	0,    (int) M_BLEUL,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
+{"bleul",		"s,I,p",	0,    (int) M_BLEUL_I,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
 {"blez",		"s,p",		0x18000000, 0xfc1f0000,	RD_1|CBD,		0,		I1,		0,	0 },
-{"blezl",		"s,p",		0x58000000, 0xfc1f0000,	RD_1|CBL,		0,		I2|T3,		0,	0 },
+{"blezl",		"s,p",		0x58000000, 0xfc1f0000,	RD_1|CBL,		0,		I2|T3,		0,	I34 },
 {"blt",			"s,t,p",	0,    (int) M_BLT,	INSN_MACRO,		0,		I1,		0,	0 },
 {"blt",			"s,I,p",	0,    (int) M_BLT_I,	INSN_MACRO,		0,		I1,		0,	0 },
-{"bltl",		"s,t,p",	0,    (int) M_BLTL,	INSN_MACRO,		0,		I2|T3,		0,	0 },
-{"bltl",		"s,I,p",	0,    (int) M_BLTL_I,	INSN_MACRO,		0,		I2|T3,		0,	0 },
+{"bltl",		"s,t,p",	0,    (int) M_BLTL,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
+{"bltl",		"s,I,p",	0,    (int) M_BLTL_I,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
 {"bltu",		"s,t,p",	0,    (int) M_BLTU,	INSN_MACRO,		0,		I1,		0,	0 },
 {"bltu",		"s,I,p",	0,    (int) M_BLTU_I,	INSN_MACRO,		0,		I1,		0,	0 },
-{"bltul",		"s,t,p",	0,    (int) M_BLTUL,	INSN_MACRO,		0,		I2|T3,		0,	0 },
-{"bltul",		"s,I,p",	0,    (int) M_BLTUL_I,	INSN_MACRO,		0,		I2|T3,		0,	0 },
+{"bltul",		"s,t,p",	0,    (int) M_BLTUL,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
+{"bltul",		"s,I,p",	0,    (int) M_BLTUL_I,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
 {"bltz",		"s,p",		0x04000000, 0xfc1f0000,	RD_1|CBD,		0,		I1,		0,	0 },
-{"bltzl",		"s,p",		0x04020000, 0xfc1f0000,	RD_1|CBL,		0,		I2|T3,		0,	0 },
-{"bltzal",		"s,p",		0x04100000, 0xfc1f0000,	RD_1|WR_31|CBD,		0,		I1,		0,	0 },
-{"bltzall",		"s,p",		0x04120000, 0xfc1f0000,	RD_1|WR_31|CBL,		0,		I2|T3,		0,	0 },
+{"bltzl",		"s,p",		0x04020000, 0xfc1f0000,	RD_1|CBL,		0,		I2|T3,		0,	I34 },
+{"bltzal",		"s,p",		0x04100000, 0xfc1f0000,	RD_1|WR_31|CBD,		0,		I1,		0,	I34 },
+{"bltzall",		"s,p",		0x04120000, 0xfc1f0000,	RD_1|WR_31|CBL,		0,		I2|T3,		0,	I34 },
 {"bnez",		"s,p",		0x14000000, 0xfc1f0000,	RD_1|CBD,		0,		I1,		0,	0 },
-{"bnezl",		"s,p",		0x54000000, 0xfc1f0000,	RD_1|CBL,		0,		I2|T3,		0,	0 },
+{"bnezl",		"s,p",		0x54000000, 0xfc1f0000,	RD_1|CBL,		0,		I2|T3,		0,	I34 },
 {"bne",			"s,t,p",	0x14000000, 0xfc000000,	RD_1|RD_2|CBD,		0,		I1,		0,	0 },
 {"bne",			"s,I,p",	0,    (int) M_BNE_I,	INSN_MACRO,		0,		I1,		0,	0 },
-{"bnel",		"s,t,p",	0x54000000, 0xfc000000,	RD_1|RD_2|CBL, 		0,		I2|T3,		0,	0 },
-{"bnel",		"s,I,p",	0,    (int) M_BNEL_I,	INSN_MACRO,		0,		I2|T3,		0,	0 },
+{"bnel",		"s,t,p",	0x54000000, 0xfc000000,	RD_1|RD_2|CBL, 		0,		I2|T3,		0,	I34 },
+{"bnel",		"s,I,p",	0,    (int) M_BNEL_I,	INSN_MACRO,		0,		I2|T3,		0,	I34 },
 {"break",		"",		0x0000000d, 0xffffffff,	TRAP,			0,		I1,		0,	0 },
 {"break",		"c",		0x0000000d, 0xfc00ffff,	TRAP,			0,		I1,		0,	0 },
 {"break",		"c,q",		0x0000000d, 0xfc00003f,	TRAP,			0,		I1,		0,	0 },
-{"c.f.d",		"S,T",		0x46200030, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF },
-{"c.f.d",		"M,S,T",	0x46200030, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	0 },
-{"c.f.s",		"S,T",      	0x46000030, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	0 },
-{"c.f.s",		"M,S,T",	0x46000030, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	0 },
-{"c.f.ps",		"S,T",		0x46c00030, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"c.f.d",		"S,T",		0x46200030, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF|I34 },
+{"c.f.d",		"M,S,T",	0x46200030, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	I34 },
+{"c.f.s",		"S,T",      	0x46000030, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	I34 },
+{"c.f.s",		"M,S,T",	0x46000030, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	I34 },
+{"c.f.ps",		"S,T",		0x46c00030, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"c.f.ps",		"S,T",		0x45600030, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		IL2E,		0,	0 },
-{"c.f.ps",		"M,S,T",	0x46c00030, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	0 },
-{"c.un.d",		"S,T",		0x46200031, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF },
-{"c.un.d",		"M,S,T",	0x46200031, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	0 },
-{"c.un.s",		"S,T",		0x46000031, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE },
-{"c.un.s",		"M,S,T",	0x46000031, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	0 },
-{"c.un.ps",		"S,T",		0x46c00031, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"c.f.ps",		"M,S,T",	0x46c00030, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	I34 },
+{"c.un.d",		"S,T",		0x46200031, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF|I34 },
+{"c.un.d",		"M,S,T",	0x46200031, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	I34 },
+{"c.un.s",		"S,T",		0x46000031, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE|I34 },
+{"c.un.s",		"M,S,T",	0x46000031, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	I34 },
+{"c.un.ps",		"S,T",		0x46c00031, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"c.un.ps",		"S,T",		0x45600031, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		IL2E,		0,	0 },
-{"c.un.ps",		"M,S,T",	0x46c00031, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	0 },
-{"c.eq.d",		"S,T",		0x46200032, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF },
-{"c.eq.d",		"M,S,T",	0x46200032, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	0 },
-{"c.eq.s",		"S,T",		0x46000032, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	0 },
-{"c.eq.s",		"M,S,T",	0x46000032, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	0 },
+{"c.un.ps",		"M,S,T",	0x46c00031, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	I34 },
+{"c.eq.d",		"S,T",		0x46200032, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF|I34 },
+{"c.eq.d",		"M,S,T",	0x46200032, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	I34 },
+{"c.eq.s",		"S,T",		0x46000032, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	I34 },
+{"c.eq.s",		"M,S,T",	0x46000032, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	I34 },
 {"c.eq.ob",		"Y,Q",		0x78000001, 0xfc2007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		SB1,		MX,	0 },
 {"c.eq.ob",		"S,Q",		0x48000001, 0xfc2007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		N54,		0,	0 },
-{"c.eq.ps",		"S,T",		0x46c00032, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"c.eq.ps",		"S,T",		0x46c00032, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"c.eq.ps",		"S,T",		0x45600032, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		IL2E,		0,	0 },
-{"c.eq.ps",		"M,S,T",	0x46c00032, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	0 },
+{"c.eq.ps",		"M,S,T",	0x46c00032, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	I34 },
 {"c.eq.qh",		"Y,Q",		0x78200001, 0xfc2007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		0,		MX,	0 },
-{"c.ueq.d",		"S,T",		0x46200033, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF },
-{"c.ueq.d",		"M,S,T",	0x46200033, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	0 },
-{"c.ueq.s",		"S,T",		0x46000033, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE },
-{"c.ueq.s",		"M,S,T",	0x46000033, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	0 },
-{"c.ueq.ps",		"S,T",		0x46c00033, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"c.ueq.d",		"S,T",		0x46200033, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF|I34 },
+{"c.ueq.d",		"M,S,T",	0x46200033, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	I34 },
+{"c.ueq.s",		"S,T",		0x46000033, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE|I34 },
+{"c.ueq.s",		"M,S,T",	0x46000033, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	I34 },
+{"c.ueq.ps",		"S,T",		0x46c00033, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"c.ueq.ps",		"S,T",		0x45600033, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		IL2E,		0,	0 },
-{"c.ueq.ps",		"M,S,T",	0x46c00033, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	0 },
-{"c.olt.d",		"S,T",		0x46200034, 0xffe007ff, RD_1|RD_2|WR_CC|FP_D,   0,		I1,		0,	SF },
-{"c.olt.d",		"M,S,T",	0x46200034, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	0 },
-{"c.olt.s",		"S,T",		0x46000034, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_S,	0,		I1,		0,	EE },
-{"c.olt.s",		"M,S,T",	0x46000034, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	0 },
-{"c.olt.ps",		"S,T",		0x46c00034, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"c.ueq.ps",		"M,S,T",	0x46c00033, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	I34 },
+{"c.olt.d",		"S,T",		0x46200034, 0xffe007ff, RD_1|RD_2|WR_CC|FP_D,   0,		I1,		0,	SF|I34 },
+{"c.olt.d",		"M,S,T",	0x46200034, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	I34 },
+{"c.olt.s",		"S,T",		0x46000034, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_S,	0,		I1,		0,	EE|I34 },
+{"c.olt.s",		"M,S,T",	0x46000034, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	I34 },
+{"c.olt.ps",		"S,T",		0x46c00034, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"c.olt.ps",		"S,T",		0x45600034, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		IL2E,		0,	0 },
-{"c.olt.ps",		"M,S,T",	0x46c00034, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	0 },
-{"c.ult.d",		"S,T",		0x46200035, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF },
-{"c.ult.d",		"M,S,T",	0x46200035, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	0 },
-{"c.ult.s",		"S,T",		0x46000035, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE },
-{"c.ult.s",		"M,S,T",	0x46000035, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	0 },
-{"c.ult.ps",		"S,T",		0x46c00035, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"c.olt.ps",		"M,S,T",	0x46c00034, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	I34 },
+{"c.ult.d",		"S,T",		0x46200035, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF|I34 },
+{"c.ult.d",		"M,S,T",	0x46200035, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	I34 },
+{"c.ult.s",		"S,T",		0x46000035, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE|I34 },
+{"c.ult.s",		"M,S,T",	0x46000035, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	I34 },
+{"c.ult.ps",		"S,T",		0x46c00035, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"c.ult.ps",		"S,T",		0x45600035, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		IL2E,		0,	0 },
-{"c.ult.ps",		"M,S,T",	0x46c00035, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	0 },
-{"c.ole.d",		"S,T",		0x46200036, 0xffe007ff, RD_1|RD_2|WR_CC|FP_D,   0,		I1,		0,	SF },
-{"c.ole.d",		"M,S,T",	0x46200036, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	0 },
-{"c.ole.s",		"S,T",		0x46000036, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE },
-{"c.ole.s",		"M,S,T",	0x46000036, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	0 },
-{"c.ole.ps",		"S,T",		0x46c00036, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"c.ult.ps",		"M,S,T",	0x46c00035, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	I34 },
+{"c.ole.d",		"S,T",		0x46200036, 0xffe007ff, RD_1|RD_2|WR_CC|FP_D,   0,		I1,		0,	SF|I34 },
+{"c.ole.d",		"M,S,T",	0x46200036, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	I34 },
+{"c.ole.s",		"S,T",		0x46000036, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE|I34 },
+{"c.ole.s",		"M,S,T",	0x46000036, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	I34 },
+{"c.ole.ps",		"S,T",		0x46c00036, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"c.ole.ps",		"S,T",		0x45600036, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		IL2E,		0,	0 },
-{"c.ole.ps",		"M,S,T",	0x46c00036, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	0 },
-{"c.ule.d",		"S,T",		0x46200037, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF },
-{"c.ule.d",		"M,S,T",	0x46200037, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	0 },
-{"c.ule.s",		"S,T",		0x46000037, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE },
-{"c.ule.s",		"M,S,T",	0x46000037, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	0 },
-{"c.ule.ps",		"S,T",		0x46c00037, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"c.ole.ps",		"M,S,T",	0x46c00036, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	I34 },
+{"c.ule.d",		"S,T",		0x46200037, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF|I34 },
+{"c.ule.d",		"M,S,T",	0x46200037, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	I34 },
+{"c.ule.s",		"S,T",		0x46000037, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE|I34 },
+{"c.ule.s",		"M,S,T",	0x46000037, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	I34 },
+{"c.ule.ps",		"S,T",		0x46c00037, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"c.ule.ps",		"S,T",		0x45600037, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		IL2E,		0,	0 },
-{"c.ule.ps",		"M,S,T",	0x46c00037, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	0 },
-{"c.sf.d",		"S,T",		0x46200038, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF },
-{"c.sf.d",		"M,S,T",	0x46200038, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	0 },
-{"c.sf.s",		"S,T",		0x46000038, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE },
-{"c.sf.s",		"M,S,T",	0x46000038, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	0 },
-{"c.sf.ps",		"S,T",		0x46c00038, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"c.ule.ps",		"M,S,T",	0x46c00037, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	I34 },
+{"c.sf.d",		"S,T",		0x46200038, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF|I34 },
+{"c.sf.d",		"M,S,T",	0x46200038, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	I34 },
+{"c.sf.s",		"S,T",		0x46000038, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE|I34 },
+{"c.sf.s",		"M,S,T",	0x46000038, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	I34 },
+{"c.sf.ps",		"S,T",		0x46c00038, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"c.sf.ps",		"S,T",		0x45600038, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		IL2E,		0,	0 },
-{"c.sf.ps",		"M,S,T",	0x46c00038, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	0 },
-{"c.ngle.d",		"S,T",		0x46200039, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF },
-{"c.ngle.d",		"M,S,T",	0x46200039, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	0 },
-{"c.ngle.s",		"S,T",		0x46000039, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE },
-{"c.ngle.s",		"M,S,T",	0x46000039, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	0 },
-{"c.ngle.ps",		"S,T",		0x46c00039, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"c.sf.ps",		"M,S,T",	0x46c00038, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	I34 },
+{"c.ngle.d",		"S,T",		0x46200039, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF|I34 },
+{"c.ngle.d",		"M,S,T",	0x46200039, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	I34 },
+{"c.ngle.s",		"S,T",		0x46000039, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE|I34 },
+{"c.ngle.s",		"M,S,T",	0x46000039, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	I34 },
+{"c.ngle.ps",		"S,T",		0x46c00039, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"c.ngle.ps",		"S,T",		0x45600039, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		IL2E,		0,	0 },
-{"c.ngle.ps",		"M,S,T",	0x46c00039, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	0 },
-{"c.seq.d",		"S,T",		0x4620003a, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF },
-{"c.seq.d",		"M,S,T",	0x4620003a, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	0 },
-{"c.seq.s",		"S,T",		0x4600003a, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE },
-{"c.seq.s",		"M,S,T",	0x4600003a, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	0 },
-{"c.seq.ps",		"S,T",		0x46c0003a, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"c.ngle.ps",		"M,S,T",	0x46c00039, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	I34 },
+{"c.seq.d",		"S,T",		0x4620003a, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF|I34 },
+{"c.seq.d",		"M,S,T",	0x4620003a, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	I34 },
+{"c.seq.s",		"S,T",		0x4600003a, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE|I34 },
+{"c.seq.s",		"M,S,T",	0x4600003a, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	I34 },
+{"c.seq.ps",		"S,T",		0x46c0003a, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"c.seq.ps",		"S,T",		0x4560003a, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		IL2E,		0,	0 },
-{"c.seq.ps",		"M,S,T",	0x46c0003a, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	0 },
-{"c.ngl.d",		"S,T",		0x4620003b, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF },
-{"c.ngl.d",		"M,S,T",	0x4620003b, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	0 },
-{"c.ngl.s",		"S,T",		0x4600003b, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE },
-{"c.ngl.s",		"M,S,T",	0x4600003b, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	0 },
-{"c.ngl.ps",		"S,T",		0x46c0003b, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"c.seq.ps",		"M,S,T",	0x46c0003a, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	I34 },
+{"c.ngl.d",		"S,T",		0x4620003b, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF|I34 },
+{"c.ngl.d",		"M,S,T",	0x4620003b, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	I34 },
+{"c.ngl.s",		"S,T",		0x4600003b, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE|I34 },
+{"c.ngl.s",		"M,S,T",	0x4600003b, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	I34 },
+{"c.ngl.ps",		"S,T",		0x46c0003b, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"c.ngl.ps",		"S,T",		0x4560003b, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		IL2E,		0,	0 },
-{"c.ngl.ps",		"M,S,T",	0x46c0003b, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	0 },
-{"c.lt.d",		"S,T",		0x4620003c, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF },
-{"c.lt.d",		"M,S,T",	0x4620003c, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	0 },
+{"c.ngl.ps",		"M,S,T",	0x46c0003b, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	I34 },
+{"c.lt.d",		"S,T",		0x4620003c, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF|I34 },
+{"c.lt.d",		"M,S,T",	0x4620003c, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	I34 },
 {"c.lt.s",		"S,T",		0x46000034, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_S,	0,		EE,		0,	0 },
-{"c.lt.s",		"S,T",		0x4600003c, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_S,	0,		I1,		0,	EE },
-{"c.lt.s",		"M,S,T",	0x4600003c, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	0 },
+{"c.lt.s",		"S,T",		0x4600003c, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_S,	0,		I1,		0,	EE|I34 },
+{"c.lt.s",		"M,S,T",	0x4600003c, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	I34 },
 {"c.lt.ob",		"Y,Q",		0x78000004, 0xfc2007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		SB1,		MX,	0 },
 {"c.lt.ob",		"S,Q",		0x48000004, 0xfc2007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		N54,		0,	0 },
-{"c.lt.ps",		"S,T",		0x46c0003c, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"c.lt.ps",		"S,T",		0x46c0003c, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"c.lt.ps",		"S,T",		0x4560003c, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		IL2E,		0,	0 },
-{"c.lt.ps",		"M,S,T",	0x46c0003c, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	0 },
+{"c.lt.ps",		"M,S,T",	0x46c0003c, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	I34 },
 {"c.lt.qh",		"Y,Q",		0x78200004, 0xfc2007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		0,		MX,	0 },
-{"c.nge.d",		"S,T",		0x4620003d, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF },
-{"c.nge.d",		"M,S,T",	0x4620003d, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	0 },
-{"c.nge.s",		"S,T",		0x4600003d, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE },
-{"c.nge.s",		"M,S,T",	0x4600003d, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	0 },
-{"c.nge.ps",		"S,T",		0x46c0003d, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"c.nge.d",		"S,T",		0x4620003d, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF|I34 },
+{"c.nge.d",		"M,S,T",	0x4620003d, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	I34 },
+{"c.nge.s",		"S,T",		0x4600003d, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE|I34 },
+{"c.nge.s",		"M,S,T",	0x4600003d, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	I34 },
+{"c.nge.ps",		"S,T",		0x46c0003d, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"c.nge.ps",		"S,T",		0x4560003d, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		IL2E,		0,	0 },
-{"c.nge.ps",		"M,S,T",	0x46c0003d, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	0 },
-{"c.le.d",		"S,T",		0x4620003e, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF },
-{"c.le.d",		"M,S,T",	0x4620003e, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	0 },
+{"c.nge.ps",		"M,S,T",	0x46c0003d, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	I34 },
+{"c.le.d",		"S,T",		0x4620003e, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF|I34 },
+{"c.le.d",		"M,S,T",	0x4620003e, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	I34 },
 {"c.le.s",		"S,T",		0x46000036, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_S,	0,		EE,		0,	0 },
-{"c.le.s",		"S,T",		0x4600003e, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_S,	0,		I1,		0,	EE },
-{"c.le.s",		"M,S,T",	0x4600003e, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	0 },
+{"c.le.s",		"S,T",		0x4600003e, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_S,	0,		I1,		0,	EE|I34 },
+{"c.le.s",		"M,S,T",	0x4600003e, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	I34 },
 {"c.le.ob",		"Y,Q",		0x78000005, 0xfc2007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		SB1,		MX,	0 },
 {"c.le.ob",		"S,Q",		0x48000005, 0xfc2007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		N54,		0,	0 },
-{"c.le.ps",		"S,T",		0x46c0003e, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"c.le.ps",		"S,T",		0x46c0003e, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"c.le.ps",		"S,T",		0x4560003e, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		IL2E,		0,	0 },
-{"c.le.ps",		"M,S,T",	0x46c0003e, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	0 },
+{"c.le.ps",		"M,S,T",	0x46c0003e, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	I34 },
 {"c.le.qh",		"Y,Q",		0x78200005, 0xfc2007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		0,		MX,	0 },
-{"c.ngt.d",		"S,T",		0x4620003f, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF },
-{"c.ngt.d",		"M,S,T",	0x4620003f, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	0 },
-{"c.ngt.s",		"S,T",		0x4600003f, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE },
-{"c.ngt.s",		"M,S,T",	0x4600003f, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	0 },
-{"c.ngt.ps",		"S,T",		0x46c0003f, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"c.ngt.d",		"S,T",		0x4620003f, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I1,		0,	SF|I34 },
+{"c.ngt.d",		"M,S,T",	0x4620003f, 0xffe000ff, RD_2|RD_3|WR_CC|FP_D,   0,		I4_32,		0,	I34 },
+{"c.ngt.s",		"S,T",		0x4600003f, 0xffe007ff, RD_1|RD_2|WR_CC|FP_S,   0,		I1,		0,	EE|I34 },
+{"c.ngt.s",		"M,S,T",	0x4600003f, 0xffe000ff, RD_2|RD_3|WR_CC|FP_S,   0,		I4_32,		0,	I34 },
+{"c.ngt.ps",		"S,T",		0x46c0003f, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"c.ngt.ps",		"S,T",		0x4560003f, 0xffe007ff,	RD_1|RD_2|WR_CC|FP_D,	0,		IL2E,		0,	0 },
-{"c.ngt.ps",		"M,S,T",	0x46c0003f, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	0 },
+{"c.ngt.ps",		"M,S,T",	0x46c0003f, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		I5_33,		0,	I34 },
 {"cabs.eq.d",		"M,S,T",	0x46200072, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		0,		M3D,	0 },
 {"cabs.eq.ps",		"M,S,T",	0x46c00072, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_D,	0,		0,		M3D,	0 },
 {"cabs.eq.s",		"M,S,T",	0x46000072, 0xffe000ff,	RD_2|RD_3|WR_CC|FP_S,	0,		0,		M3D,	0 },
@@ -892,8 +931,9 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"flushd",		"",		0xbc020000, 0xffffffff, 0, 			0,		L1,		0,	0 },
 {"flushid",		"",		0xbc030000, 0xffffffff, 0, 			0,		L1,		0,	0 },
 {"wb",			"o(b)",		0xbc040000, 0xfc1f0000, RD_2|SM,		0,		L1,		0,	0 },
-{"cache",		"k,o(b)",	0xbc000000, 0xfc000000, RD_3,           	0,		I3_32|T3,	0,	0},
-{"cache",		"k,A(b)",	0,    (int) M_CACHE_AB, INSN_MACRO,		0,		I3_32|T3,	0,	0},
+{"cache",		"k,+j(b)",	0x7c000025, 0xfc00007f, RD_3,			0,		I34,		0,	0 },
+{"cache",		"k,o(b)",	0xbc000000, 0xfc000000, RD_3,           	0,		I3_32|T3,	0,	I34 },
+{"cache",		"k,A(b)",	0,    (int) M_CACHE_AB, INSN_MACRO,		0,		I3_32|T3,	0,	I34 },
 {"ceil.l.d",		"D,S",		0x4620000a, 0xffff003f, WR_1|RD_2|FP_D,		0,		I3_33,		0,	0 },
 {"ceil.l.s",		"D,S",		0x4600000a, 0xffff003f, WR_1|RD_2|FP_S|FP_D,	0,		I3_33,		0,	0 },
 {"ceil.w.d",		"D,S",		0x4620000e, 0xffff003f, WR_1|RD_2|FP_S|FP_D,	0,		I2,		0,	SF },
@@ -909,8 +949,10 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"cins32",		"t,r,+p,+s",	0x70000033, 0xfc00003f, WR_1|RD_2,		0,		IOCT,		0,	0 },
 {"cins",		"t,r,+P,+S",	0x70000033, 0xfc00003f, WR_1|RD_2,		0,		IOCT,		0,	0 }, /* cins32 */
 {"cins",		"t,r,+p,+S",	0x70000032, 0xfc00003f, WR_1|RD_2,		0,		IOCT,		0,	0 },
-{"clo",			"U,s",		0x70000021, 0xfc0007ff, WR_1|RD_2, 	0,		I32|N55,	0,	0 },
-{"clz",			"U,s",		0x70000020, 0xfc0007ff, WR_1|RD_2, 	0,		I32|N55,	0,	0 },
+{"clo",			"d,s",		0x00000051, 0xfc1f07ff, WR_1|RD_2,		0,		I34,		0,	0 },
+{"clo",			"U,s",		0x70000021, 0xfc0007ff, WR_1|RD_2,		0,		I32|N55,	0,	I34 },
+{"clz",			"d,s",		0x00000050, 0xfc1f07ff, WR_1|RD_2,		0,		I34,		0,	0 },
+{"clz",			"U,s",		0x70000020, 0xfc0007ff, WR_1|RD_2,		0,		I32|N55,	0,	I34 },
 /* ctc0 is at the bottom of the table.  */
 {"ctc1",		"t,G",		0x44c00000, 0xffe007ff,	RD_1|WR_CC|COD|FP_S,	0,		I1,		0,	0 },
 {"ctc1",		"t,S",		0x44c00000, 0xffe007ff,	RD_1|WR_CC|COD|FP_S,	0,		I1,		0,	0 },
@@ -932,21 +974,23 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"cvt.w.d",		"D,S",		0x46200024, 0xffff003f,	WR_1|RD_2|FP_S|FP_D,	0,		I1,		0,	SF },
 {"cvt.w.s",		"D,S",		0x46000024, 0xffff003f,	WR_1|RD_2|FP_S,		0,		I1,		0,	EE },
 {"cvt.ps.pw",		"D,S",		0x46800026, 0xffff003f,	WR_1|RD_2|FP_S|FP_D,	0,		0,		M3D,	0 },
-{"cvt.ps.s",		"D,V,T",	0x46000026, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S|FP_D, 0,		I5_33,		0,	0 },
+{"cvt.ps.s",		"D,V,T",	0x46000026, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S|FP_D, 0,		I5_33,		0,	I34 },
 {"cvt.pw.ps",		"D,S",		0x46c00024, 0xffff003f,	WR_1|RD_2|FP_S|FP_D,	0,		0,		M3D,	0 },
 {"dabs",		"d,v",		0,    (int) M_DABS,	INSN_MACRO,		0,		I3,		0,	0 },
 {"dadd",		"d,v,t",	0x0000002c, 0xfc0007ff, WR_1|RD_2|RD_3,		0,		I3,		0,	0 },
-{"dadd",		"t,r,I",	0,    (int) M_DADD_I,	INSN_MACRO,		0,		I3,		0,	0 },
+{"dadd",		"t,r,I",	0,    (int) M_DADD_I,	INSN_MACRO,		0,		I3,		0,	I66 },
 {"dadd",		"D,S,T",	0x45e00000, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2E,		0,	0 },
 {"dadd",		"D,S,T",	0x4b60000c, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2F|IL3A,	0,	0 },
-{"daddi",		"t,r,j",	0x60000000, 0xfc000000, WR_1|RD_2,		0,		I3,		0,	0 },
+{"daddi",		"t,r,j",	0x60000000, 0xfc000000, WR_1|RD_2,		0,		I3,		0,	I66 },
 {"daddiu",		"t,r,j",	0x64000000, 0xfc000000, WR_1|RD_2,		0,		I3,		0,	0 },
 {"daddu",		"d,v,t",	0x0000002d, 0xfc0007ff, WR_1|RD_2|RD_3,		0,		I3,		0,	0 },
 {"daddu",		"t,r,I",	0,    (int) M_DADDU_I,	INSN_MACRO,		0,		I3,		0,	0 },
 {"daddwc",		"d,s,t", 	0x70000038, 0xfc0007ff, WR_1|RD_2|RD_3|WR_C0|RD_C0, 0,		XLR,		0,	0 },
 {"dbreak",		"",		0x7000003f, 0xffffffff,	0,			0,		N5,		0,	0 },
-{"dclo",		"U,s",	 	0x70000025, 0xfc0007ff, WR_1|RD_2, 	0,		I64|N55,	0,	0 },
-{"dclz",		"U,s",	 	0x70000024, 0xfc0007ff, WR_1|RD_2, 	0,		I64|N55,	0,	0 },
+{"dclo",		"d,s",		0x00000053, 0xfc1f07ff, WR_1|RD_2,		0,		I66,		0,	0 },
+{"dclo",		"U,s",	 	0x70000025, 0xfc0007ff, WR_1|RD_2, 	0,		I64|N55,	0,	I66 },
+{"dclz",		"d,s",		0x00000052, 0xfc1f07ff, WR_1|RD_2,		0,		I66,		0,	0 },
+{"dclz",		"U,s",	 	0x70000024, 0xfc0007ff, WR_1|RD_2, 	0,		I64|N55,	0,	I66 },
 /* dctr and dctw are used on the r5000.  */
 {"dctr",		"o(b)",	 	0xbc050000, 0xfc1f0000, RD_2,			0,		I3,		0,	0 },
 {"dctw",		"o(b)",		0xbc090000, 0xfc1f0000, RD_2,			0,		I3,		0,	0 },
@@ -957,13 +1001,17 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"dextm",		"t,r,+A,+G",	0x7c000001, 0xfc00003f, WR_1|RD_2,    		0,		I65,		0,	0 },
 {"dextu",		"t,r,+E,+H",	0x7c000002, 0xfc00003f, WR_1|RD_2,    		0,		I65,		0,	0 },
 /* For ddiv, see the comments about div.  */
-{"ddiv",		"z,s,t",	0x0000001e, 0xfc00ffff, RD_2|RD_3|WR_HILO,      0,		I3,		0,	M32 },
-{"ddiv",		"d,v,t",	0,    (int) M_DDIV_3,	INSN_MACRO,		0,		I3,		0,	M32 },
-{"ddiv",		"d,v,I",	0,    (int) M_DDIV_3I,	INSN_MACRO,		0,		I3,		0,	M32 },
+{"dmod",		"d,s,t",	0x000000de, 0xfc0007ff, WR_1|RD_2|RD_3,		0,		I66,		0,	0 },
+{"ddiv",		"d,s,t",	0x0000009e, 0xfc0007ff, WR_1|RD_2|RD_3,		0,		I66,		0,	0 },
+{"ddiv",		"z,s,t",	0x0000001e, 0xfc00ffff, RD_2|RD_3|WR_HILO,      0,		I3,		0,	M32|I66 },
+{"ddiv",		"d,v,t",	0,    (int) M_DDIV_3,	INSN_MACRO,		0,		I3,		0,	M32|I66 },
+{"ddiv",		"d,v,I",	0,    (int) M_DDIV_3I,	INSN_MACRO,		0,		I3,		0,	M32|I66 },
 /* For ddivu, see the comments about div.  */
-{"ddivu",		"z,s,t",	0x0000001f, 0xfc00ffff, RD_2|RD_3|WR_HILO,      0,		I3,		0,	M32 },
-{"ddivu",		"d,v,t",	0,    (int) M_DDIVU_3,	INSN_MACRO,		0,		I3,		0,	M32 },
-{"ddivu",		"d,v,I",	0,    (int) M_DDIVU_3I,	INSN_MACRO,		0,		I3,		0,	M32 },
+{"dmodu",		"d,s,t",	0x000000df, 0xfc0007ff, WR_1|RD_2|RD_3,		0,		I66,		0,	0 },
+{"ddivu",		"d,s,t",	0x0000009f, 0xfc0007ff, WR_1|RD_2|RD_3,		0,		I66,		0,	0 },
+{"ddivu",		"z,s,t",	0x0000001f, 0xfc00ffff, RD_2|RD_3|WR_HILO,      0,		I3,		0,	M32|I66 },
+{"ddivu",		"d,v,t",	0,    (int) M_DDIVU_3,	INSN_MACRO,		0,		I3,		0,	M32|I66 },
+{"ddivu",		"d,v,I",	0,    (int) M_DDIVU_3I,	INSN_MACRO,		0,		I3,		0,	M32|I66 },
 {"di",			"",		0x42000039, 0xffffffff,	WR_C0,			0,		EE,		0,	0 },
 {"di",			"",		0x41606000, 0xffffffff,	WR_C0,			0,		I33,		0,	0 },
 {"di",			"t",		0x41606000, 0xffe0ffff,	WR_1|WR_C0,		0,		I33,		0,	0 },
@@ -976,20 +1024,24 @@ const struct mips_opcode mips_builtin_opcodes[] =
    though the first operand appeared twice (the first operand is both
    a source and a destination).  To get the div machine instruction,
    you must use an explicit destination of $0.  */
-{"div",			"z,s,t",	0x0000001a, 0xfc00ffff, RD_2|RD_3|WR_HILO,      0,		I1,		0,	0 },
-{"div",			"z,t",		0x0000001a, 0xffe0ffff, RD_2|WR_HILO,		0,		I1,		0,	0 },
-{"div",			"d,v,t",	0,    (int) M_DIV_3,	INSN_MACRO,		0,		I1,		0,	0 },
-{"div",			"d,v,I",	0,    (int) M_DIV_3I,	INSN_MACRO,		0,		I1,		0,	0 },
+{"mod",			"d,v,t",	0x000000da, 0xfc0007ff, WR_1|RD_2|RD_3, 	0,		I34,		0,	0},
+{"modu",		"d,v,t",	0x000000db, 0xfc0007ff, WR_1|RD_2|RD_3, 	0,		I34,		0,	0},
+{"div",			"d,v,t",	0x0000009a, 0xfc0007ff, WR_1|RD_2|RD_3, 	0,		I34,		0,	0},
+{"div",			"z,s,t",	0x0000001a, 0xfc00ffff, RD_2|RD_3|WR_HILO,      0,		I1,		0,	I34 },
+{"div",			"z,t",		0x0000001a, 0xffe0ffff, RD_2|WR_HILO,		0,		I1,		0,	I34 },
+{"div",			"d,v,t",	0,    (int) M_DIV_3,	INSN_MACRO,		0,		I1,		0,	I34 },
+{"div",			"d,v,I",	0,    (int) M_DIV_3I,	INSN_MACRO,		0,		I1,		0,	I34 },
 {"div1",		"z,s,t",	0x7000001a, 0xfc00ffff, RD_2|RD_3|WR_HILO,      0,		EE,		0,	0 },
 {"div1",		"z,t",		0x7000001a, 0xffe0ffff, RD_2|WR_HILO,		0,		EE,		0,	0 },
 {"div.d",		"D,V,T",	0x46200003, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I1,		0,	SF },
 {"div.s",		"D,V,T",	0x46000003, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I1,		0,	0 },
 {"div.ps",		"D,V,T",	0x46c00003, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		SB1,		0,	0 },
 /* For divu, see the comments about div.  */
-{"divu",		"z,s,t",	0x0000001b, 0xfc00ffff, RD_2|RD_3|WR_HILO,      0,		I1,		0,	0 },
-{"divu",		"z,t",		0x0000001b, 0xffe0ffff, RD_2|WR_HILO,		0,		I1,		0,	0 },
-{"divu",		"d,v,t",	0,    (int) M_DIVU_3,	INSN_MACRO,		0,		I1,		0,	0 },
-{"divu",		"d,v,I",	0,    (int) M_DIVU_3I,	INSN_MACRO,		0,		I1,		0,	0 },
+{"divu",		"d,v,t",	0x0000009b, 0xfc0007ff, WR_1|RD_2|RD_3, 	0,		I34,		0,	0},
+{"divu",		"z,s,t",	0x0000001b, 0xfc00ffff, RD_2|RD_3|WR_HILO,      0,		I1,		0,	I34 },
+{"divu",		"z,t",		0x0000001b, 0xffe0ffff, RD_2|WR_HILO,		0,		I1,		0,	I34 },
+{"divu",		"d,v,t",	0,    (int) M_DIVU_3,	INSN_MACRO,		0,		I1,		0,	I34 },
+{"divu",		"d,v,I",	0,    (int) M_DIVU_3I,	INSN_MACRO,		0,		I1,		0,	I34 },
 {"divu1",		"z,s,t",	0x7000001b, 0xfc00ffff, RD_2|RD_3|WR_HILO,      0,		EE,		0,	0 },
 {"divu1",		"z,t",		0x7000001b, 0xffe0ffff, RD_2|WR_HILO,		0,		EE,		0,	0 },
 {"dla",			"t,A(b)",	0,    (int) M_DLA_AB,	INSN_MACRO,		0,		I3,		0,	0 },
@@ -1024,24 +1076,28 @@ const struct mips_opcode mips_builtin_opcodes[] =
 /* dmtc2 is at the bottom of the table.  */
 /* dmfc3 is at the bottom of the table.  */
 /* dmtc3 is at the bottom of the table.  */
+{"dmuh",		"d,s,t",	0x000000dc, 0xfc0007ff, WR_1|RD_2|RD_3,		0,		I66,		0,	0 },
+{"dmul",		"d,s,t",	0x0000009c, 0xfc0007ff, WR_1|RD_2|RD_3,		0,		I66,		0,	0 },
 {"dmul",		"d,v,t",	0x70000003, 0xfc0007ff, WR_1|RD_2|RD_3|WR_HILO,	0,		IOCT,		0,	0 },
-{"dmul",		"d,v,t",	0,    (int) M_DMUL,	INSN_MACRO,		0,		I3,		0,	M32 },
-{"dmul",		"d,v,I",	0,    (int) M_DMUL_I,	INSN_MACRO,		0,		I3,		0,	M32 },
-{"dmulo",		"d,v,t",	0,    (int) M_DMULO,	INSN_MACRO,		0,		I3,		0,	M32 },
-{"dmulo",		"d,v,I",	0,    (int) M_DMULO_I,	INSN_MACRO,		0,		I3,		0,	M32 },
-{"dmulou",		"d,v,t",	0,    (int) M_DMULOU,	INSN_MACRO,		0,		I3,		0,	M32 },
-{"dmulou",		"d,v,I",	0,    (int) M_DMULOU_I,	INSN_MACRO,		0,		I3,		0,	M32 },
-{"dmult",		"s,t",		0x0000001c, 0xfc00ffff, RD_1|RD_2|WR_HILO,      0,		I3,		0,	M32 },
-{"dmultu",		"s,t",		0x0000001d, 0xfc00ffff, RD_1|RD_2|WR_HILO,      0,		I3,		0,	M32 },
+{"dmul",		"d,v,t",	0,    (int) M_DMUL,	INSN_MACRO,		0,		I3,		0,	M32|I66 },
+{"dmul",		"d,v,I",	0,    (int) M_DMUL_I,	INSN_MACRO,		0,		I3,		0,	M32|I66 },
+{"dmulo",		"d,v,t",	0,    (int) M_DMULO,	INSN_MACRO,		0,		I3,		0,	M32|I66 },
+{"dmulo",		"d,v,I",	0,    (int) M_DMULO_I,	INSN_MACRO,		0,		I3,		0,	M32|I66 },
+{"dmulou",		"d,v,t",	0,    (int) M_DMULOU,	INSN_MACRO,		0,		I3,		0,	M32|I66 },
+{"dmulou",		"d,v,I",	0,    (int) M_DMULOU_I,	INSN_MACRO,		0,		I3,		0,	M32|I66 },
+{"dmult",		"s,t",		0x0000001c, 0xfc00ffff, RD_1|RD_2|WR_HILO,      0,		I3,		0,	M32|I66 },
+{"dmulu",		"d,s,t",	0x0000009d, 0xfc0007ff, WR_1|RD_2|RD_3,      	0,		I66,		0,	0 },
+{"dmuhu",		"d,s,t",	0x000000dd, 0xfc0007ff, WR_1|RD_2|RD_3,      	0,		I66,		0,	0 },
+{"dmultu",		"s,t",		0x0000001d, 0xfc00ffff, RD_1|RD_2|WR_HILO,      0,		I3,		0,	M32|I66 },
 {"dneg",		"d,w",		0x0000002e, 0xffe007ff,	WR_1|RD_2,		0,		I3,		0,	0 }, /* dsub 0 */
 {"dnegu",		"d,w",		0x0000002f, 0xffe007ff,	WR_1|RD_2,		0,		I3,		0,	0 }, /* dsubu 0*/
 {"dpop",		"d,v",		0x7000002d, 0xfc1f07ff, WR_1|RD_2,		0,		IOCT,		0,	0 },
-{"drem",		"z,s,t",	0x0000001e, 0xfc00ffff, RD_2|RD_3|WR_HILO,      0,		I3,		0,	M32 },
-{"drem",		"d,v,t",	0,    (int) M_DREM_3,	INSN_MACRO,		0,		I3,		0,	M32 },
-{"drem",		"d,v,I",	0,    (int) M_DREM_3I,	INSN_MACRO,		0,		I3,		0,	M32 },
-{"dremu",		"z,s,t",	0x0000001f, 0xfc00ffff, RD_2|RD_3|WR_HILO,      0,		I3,		0,	M32 },
-{"dremu",		"d,v,t",	0,    (int) M_DREMU_3,	INSN_MACRO,		0,		I3,		0,	M32 },
-{"dremu",		"d,v,I",	0,    (int) M_DREMU_3I,	INSN_MACRO,		0,		I3,		0,	M32 },
+{"drem",		"z,s,t",	0x0000001e, 0xfc00ffff, RD_2|RD_3|WR_HILO,      0,		I3,		0,	M32|I66 },
+{"drem",		"d,v,t",	0,    (int) M_DREM_3,	INSN_MACRO,		0,		I3,		0,	M32|I66 },
+{"drem",		"d,v,I",	0,    (int) M_DREM_3I,	INSN_MACRO,		0,		I3,		0,	M32|I66 },
+{"dremu",		"z,s,t",	0x0000001f, 0xfc00ffff, RD_2|RD_3|WR_HILO,      0,		I3,		0,	M32|I66 },
+{"dremu",		"d,v,t",	0,    (int) M_DREMU_3,	INSN_MACRO,		0,		I3,		0,	M32|I66 },
+{"dremu",		"d,v,I",	0,    (int) M_DREMU_3I,	INSN_MACRO,		0,		I3,		0,	M32|I66 },
 {"dret",		"",		0x7000003e, 0xffffffff,	0,			0,		N5,		0,	0 },
 {"drol",		"d,v,t",	0,    (int) M_DROL,	INSN_MACRO,		0,		I3,		0,	0 },
 {"drol",		"d,v,I",	0,    (int) M_DROL_I,	INSN_MACRO,		0,		I3,		0,	0 },
@@ -1080,7 +1136,7 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"dsrl",		"D,S,T",	0x45a00003, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2E,		0,	0 },
 {"dsrl",		"D,S,T",	0x4b20000f, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2F|IL3A,	0,	0 },
 {"dsub",		"d,v,t",	0x0000002e, 0xfc0007ff,	WR_1|RD_2|RD_3,		0,		I3,		0,	0 },
-{"dsub",		"d,v,I",	0,    (int) M_DSUB_I,	INSN_MACRO,		0,		I3,		0,	0 },
+{"dsub",		"d,v,I",	0,    (int) M_DSUB_I,	INSN_MACRO,		0,		I3,		0,	I66 },
 {"dsub",		"D,S,T",	0x45e00001, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2E,		0,	0 },
 {"dsub",		"D,S,T",	0x4b60000d, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2F|IL3A,	0,	0 },
 {"dsubu",		"d,v,t",	0x0000002f, 0xfc0007ff,	WR_1|RD_2|RD_3,		0,		I3,		0,	0 },
@@ -1108,11 +1164,15 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"hypcall",		"+J",		0x42000028, 0xffe007ff, TRAP,			0,		0,		IVIRT,	0 },
 {"ins",			"t,r,+A,+B",	0x7c000004, 0xfc00003f, WR_1|RD_2,    		0,		I33,		0,	0 },
 {"iret",		"",		0x42000038, 0xffffffff,	NODS,			0,		0,		MC,	0 },
-{"jr",			"s",		0x00000008, 0xfc1fffff,	RD_1|UBD,		0,		I1,		0,	0 },
+{"jr",			"s",		0x00000009, 0xfc1fffff,	RD_1|UBD,		INSN2_ALIAS,	I34,		0,	0 }, /* jalr $0 */
+{"jr",			"s",		0x00000008, 0xfc1fffff,	RD_1|UBD,		0,		I1,		0,	I34 },
+/* MIPS R6 jic appears before beqzc and jialc appears before bnezc */
 /* jr.hb is officially MIPS{32,64}R2, but it works on R1 as jr with
    the same hazard barrier effect.  */
-{"jr.hb",		"s",		0x00000408, 0xfc1fffff,	RD_1|UBD,		0,		I32,		0,	0 },
-{"j",			"s",		0x00000008, 0xfc1fffff,	RD_1|UBD,		0,		I1,		0,	0 }, /* jr */
+{"jr.hb",		"s",		0x00000409, 0xfc1fffff,	RD_1|UBD,		INSN2_ALIAS,	I34,		0,	0 }, /* jalr.hb $0 */
+{"jr.hb",		"s",		0x00000408, 0xfc1fffff,	RD_1|UBD,		0,		I32,		0,	I34 },
+{"j",			"s",		0x00000009, 0xfc1fffff,	RD_1|UBD,		INSN2_ALIAS,	I34,		0,	0 }, /* jalr $0 */
+{"j",			"s",		0x00000008, 0xfc1fffff,	RD_1|UBD,		0,		I1,		0,	I34 }, /* jr */
 /* SVR4 PIC code requires special handling for j, so it must be a
    macro.  */
 {"j",			"a",		0,     (int) M_J_A,	INSN_MACRO,		0,		I1,		0,	0 },
@@ -1135,8 +1195,7 @@ const struct mips_opcode mips_builtin_opcodes[] =
    assembler, but will never match user input (because the line above
    will match first).  */
 {"jal",			"a",		0x0c000000, 0xfc000000,	WR_31|UBD,		0,		I1,		0,	0 },
-{"jalx",		"+i",		0x74000000, 0xfc000000, WR_31|UBD,		0,		I1,		0,	0 },
-{"la",			"t,A(b)",	0,    (int) M_LA_AB,	INSN_MACRO,		0,		I1,		0,	0 },
+{"jalx",		"+i",		0x74000000, 0xfc000000, WR_31|UBD,		0,		I1,		0,	I34 },
 {"laa",			"d,(b),t",	0x7000049f, 0xfc0007ff, WR_1|RD_2|RD_3|LM|SM,	0,		IOCT2,		0,	0 },
 {"laad",		"d,(b),t",	0x700004df, 0xfc0007ff, WR_1|RD_2|RD_3|LM|SM,	0,		IOCT2,		0,	0 },
 {"lac",			"d,(b)",	0x7000039f, 0xfc1f07ff, WR_1|RD_2|LM|SM,	0,		IOCT2,		0,	0 },
@@ -1161,7 +1220,9 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"lwx",			"d,t(b)",	0x7c00000a, 0xfc0007ff, WR_1|RD_2|RD_3|LM,	0,		IOCT2,		D32,	0},
 {"lwux",		"d,t(b)",	0x7c00040a, 0xfc0007ff, WR_1|RD_2|RD_3|LM,	0,		IOCT2,		0,	0 },
 {"lca",			"t,A(b)",	0,    (int) M_LCA_AB,	INSN_MACRO,		0,		I1,		0,	0 },
+{"ldpc",		"s,-B",		0xec180000, 0xfc1c0000, WR_1|RD_pc,		0,		I66,		0,	0 },
 /* The macro has to be first to handle o32 correctly.  */
+{"ld",			"s,-b(+R)",	0xec180000, 0xfc1c0000, WR_1|RD_pc,		0,		I66,		0,	0 },
 {"ld",			"t,A(b)",	0,    (int) M_LD_AB,	INSN_MACRO,		0,		I1,		0,	0 },
 {"ld",			"t,o(b)",	0xdc000000, 0xfc000000, WR_1|RD_3|LM,		0,		I3,		0,	0 },
 {"ldaddw",		"t,b",		0x70000010, 0xfc00ffff,	MOD_1|RD_2|LM|SM,	0,		XLR,		0,	0 },
@@ -1173,15 +1234,16 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"ldc1",		"E,A(b)",	0,    (int) M_LDC1_AB,	INSN_MACRO,		INSN2_M_FP_D,	I2,		0,	SF },
 {"l.d",			"T,o(b)",	0xd4000000, 0xfc000000, WR_1|RD_3|CLD|FP_D,	0,		I2,		0,	SF }, /* ldc1 */
 {"l.d",			"T,A(b)",	0,    (int) M_L_DAB,	INSN_MACRO,		INSN2_M_FP_D,	I1,		0,	0 },
-{"ldc2",		"E,o(b)",	0xd8000000, 0xfc000000,	RD_3|WR_CC|CLD,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE },
-{"ldc2",		"E,A(b)",	0,    (int) M_LDC2_AB,	INSN_MACRO,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE },
+{"ldc2",		"E,+:(d)",	0x49c00000, 0xffe00000,	RD_3|WR_C2|CLD,		0,		I34,		0,	0 },
+{"ldc2",		"E,o(b)",	0xd8000000, 0xfc000000,	RD_3|WR_CC|CLD,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"ldc2",		"E,A(b)",	0,    (int) M_LDC2_AB,	INSN_MACRO,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
 {"ldc3",		"E,o(b)",	0xdc000000, 0xfc000000,	RD_3|WR_CC|CLD,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE },
 {"ldc3",		"E,A(b)",	0,    (int) M_LDC3_AB,	INSN_MACRO,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE },
-{"ldl",			"t,o(b)",	0x68000000, 0xfc000000, WR_1|RD_3|LM,		0,		I3,		0,	0 },
-{"ldl",			"t,A(b)",	0,    (int) M_LDL_AB,	INSN_MACRO,		0,		I3,		0,	0 },
-{"ldr",			"t,o(b)",	0x6c000000, 0xfc000000, WR_1|RD_3|LM,		0,		I3,		0,	0 },
-{"ldr",			"t,A(b)",	0,    (int) M_LDR_AB,	INSN_MACRO,		0,		I3,		0,	0 },
-{"ldxc1",		"D,t(b)",	0x4c000001, 0xfc00f83f, WR_1|RD_2|RD_3|LM|FP_D, 0,		I4_33,		0,	0 },
+{"ldl",			"t,o(b)",	0x68000000, 0xfc000000, WR_1|RD_3|LM,		0,		I3,		0,	I66 },
+{"ldl",			"t,A(b)",	0,    (int) M_LDL_AB,	INSN_MACRO,		0,		I3,		0,	I66 },
+{"ldr",			"t,o(b)",	0x6c000000, 0xfc000000, WR_1|RD_3|LM,		0,		I3,		0,	I66 },
+{"ldr",			"t,A(b)",	0,    (int) M_LDR_AB,	INSN_MACRO,		0,		I3,		0,	I66 },
+{"ldxc1",		"D,t(b)",	0x4c000001, 0xfc00f83f, WR_1|RD_2|RD_3|LM|FP_D, 0,		I4_33,		0,	I34 },
 {"lh",			"t,o(b)",	0x84000000, 0xfc000000,	WR_1|RD_3|LM,		0,		I1,		0,	0 },
 {"lh",			"t,A(b)",	0,    (int) M_LH_AB,	INSN_MACRO,		0,		I1,		0,	0 },
 {"lhu",			"t,o(b)",	0x94000000, 0xfc000000,	WR_1|RD_3|LM,		0,		I1,		0,	0 },
@@ -1191,42 +1253,49 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"li.d",		"T,L",		0,    (int) M_LI_DD,	INSN_MACRO,		INSN2_M_FP_D,	I1,		0,	SF },
 {"li.s",		"t,f",		0,    (int) M_LI_S,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
 {"li.s",		"T,l",		0,    (int) M_LI_SS,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
-{"ll",			"t,o(b)",	0xc0000000, 0xfc000000, WR_1|RD_3|LM,		0,		I2,		0,	EE },
-{"ll",			"t,A(b)",	0,    (int) M_LL_AB,	INSN_MACRO,		0,		I2,		0,	EE },
-{"lld",			"t,o(b)",	0xd0000000, 0xfc000000, WR_1|RD_3|LM,		0,		I3,		0,	EE },
-{"lld",			"t,A(b)",	0,    (int) M_LLD_AB,	INSN_MACRO,		0,		I3,		0,	EE },
+{"ll",			"t,+j(b)",	0x7c000036, 0xfc00007f, WR_1|RD_3|LM,		0,		I34,		0,	0 },
+{"ll",			"t,o(b)",	0xc0000000, 0xfc000000, WR_1|RD_3|LM,		0,		I2,		0,	EE|I34 },
+{"ll",			"t,A(b)",	0,    (int) M_LL_AB,	INSN_MACRO,		0,		I2,		0,	EE|I34 },
+{"lld",			"t,+j(b)",	0x7c000037, 0xfc00007f, WR_1|RD_3|LM,		0,		I66,		0,	0 },
+{"lld",			"t,o(b)",	0xd0000000, 0xfc000000, WR_1|RD_3|LM,		0,		I3,		0,	EE|I66 },
+{"lld",			"t,A(b)",	0,    (int) M_LLD_AB,	INSN_MACRO,		0,		I3,		0,	EE|I66 },
 {"lq",			"t,o(b)",	0x78000000, 0xfc000000, WR_1|RD_3|LM,		0,		MMI,		0,	0 },
 {"lq",			"t,A(b)",	0,    (int) M_LQ_AB,	INSN_MACRO,		0,		MMI,		0,	0 },
 {"lqc2",		"+7,o(b)",	0xd8000000, 0xfc000000,	RD_3|WR_C2|LM,		0,		EE,		0,	0 },
 {"lqc2",		"+7,A(b)",	0,    (int) M_LQC2_AB,	INSN_MACRO,		0,		EE,		0,	0 },
 {"lui",			"t,u",		0x3c000000, 0xffe00000,	WR_1,			0,		I1,		0,	0 },
-{"luxc1",		"D,t(b)",	0x4c000005, 0xfc00f83f, WR_1|RD_2|RD_3|LM|FP_D, 0,		I5_33|N55,	0,	0},
+{"luxc1",		"D,t(b)",	0x4c000005, 0xfc00f83f, WR_1|RD_2|RD_3|LM|FP_D, 0,		I5_33|N55,	0,	I34},
+{"lwpc",		"s,-A",		0xec080000, 0xfc180000, WR_1|RD_pc|LM,		0,		I34,		0,	0 },
 {"lw",			"t,o(b)",	0x8c000000, 0xfc000000,	WR_1|RD_3|LM,		0,		I1,		0,	0 },
+{"lw",			"s,-a(+R)",	0xec080000, 0xfc180000, WR_1|RD_pc|LM,		0,		I34,		0,	0 },
 {"lw",			"t,A(b)",	0,    (int) M_LW_AB,	INSN_MACRO,		0,		I1,		0,	0 },
-{"lwc0",		"E,o(b)",	0xc0000000, 0xfc000000,	RD_3|WR_CC|CLD,		0,		I1,		0,	IOCT|IOCTP|IOCT2 },
-{"lwc0",		"E,A(b)",	0,    (int) M_LWC0_AB,	INSN_MACRO,		0,		I1,		0,	IOCT|IOCTP|IOCT2 },
+{"lwc0",		"E,o(b)",	0xc0000000, 0xfc000000,	RD_3|WR_CC|CLD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|I34 },
+{"lwc0",		"E,A(b)",	0,    (int) M_LWC0_AB,	INSN_MACRO,		0,		I1,		0,	IOCT|IOCTP|IOCT2|I34 },
 {"lwc1",		"T,o(b)",	0xc4000000, 0xfc000000,	WR_1|RD_3|CLD|FP_S,	0,		I1,		0,	0 },
 {"lwc1",		"E,o(b)",	0xc4000000, 0xfc000000,	WR_1|RD_3|CLD|FP_S,	0,		I1,		0,	0 },
 {"lwc1",		"T,A(b)",	0,    (int) M_LWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
 {"lwc1",		"E,A(b)",	0,    (int) M_LWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
 {"l.s",			"T,o(b)",	0xc4000000, 0xfc000000,	WR_1|RD_3|CLD|FP_S,	0,		I1,		0,	0 }, /* lwc1 */
 {"l.s",			"T,A(b)",	0,    (int) M_LWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
-{"lwc2",		"E,o(b)",	0xc8000000, 0xfc000000,	RD_3|WR_CC|CLD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
-{"lwc2",		"E,A(b)",	0,    (int) M_LWC2_AB,	INSN_MACRO,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
-{"lwc3",		"E,o(b)",	0xcc000000, 0xfc000000,	RD_3|WR_CC|CLD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
-{"lwc3",		"E,A(b)",	0,    (int) M_LWC3_AB,	INSN_MACRO,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
-{"lwl",			"t,o(b)",	0x88000000, 0xfc000000,	WR_1|RD_3|LM,		0,		I1,		0,	0 },
-{"lwl",			"t,A(b)",	0,    (int) M_LWL_AB,	INSN_MACRO,		0,		I1,		0,	0 },
-{"lcache",		"t,o(b)",	0x88000000, 0xfc000000,	WR_1|RD_3|LM,		0,		I2,		0,	0 }, /* same */
-{"lcache",		"t,A(b)",	0,    (int) M_LWL_AB,	INSN_MACRO,		0,		I2,		0,	0 }, /* as lwl */
-{"lwr",			"t,o(b)",	0x98000000, 0xfc000000,	WR_1|RD_3|LM,		0,		I1,		0,	0 },
-{"lwr",			"t,A(b)",	0,    (int) M_LWR_AB,	INSN_MACRO,		0,		I1,		0,	0 },
-{"flush",		"t,o(b)",	0x98000000, 0xfc000000,	WR_1|RD_3|LM,		0,		I2,		0,	0 }, /* same */
-{"flush",		"t,A(b)",	0,    (int) M_LWR_AB,	INSN_MACRO,		0,		I2,		0,	0 }, /* as lwr */
+{"lwc2",		"E,+:(d)",	0x49400000, 0xffe00000,	RD_3|WR_C2|CLD,		0,		I34,		0,	0 },
+{"lwc2",		"E,o(b)",	0xc8000000, 0xfc000000,	RD_3|WR_CC|CLD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"lwc2",		"E,A(b)",	0,    (int) M_LWC2_AB,	INSN_MACRO,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"lwc3",		"E,o(b)",	0xcc000000, 0xfc000000,	RD_3|WR_CC|CLD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"lwc3",		"E,A(b)",	0,    (int) M_LWC3_AB,	INSN_MACRO,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"lwl",			"t,o(b)",	0x88000000, 0xfc000000,	WR_1|RD_3|LM,		0,		I1,		0,	I34 },
+{"lwl",			"t,A(b)",	0,    (int) M_LWL_AB,	INSN_MACRO,		0,		I1,		0,	I34 },
+{"lcache",		"t,o(b)",	0x88000000, 0xfc000000,	WR_1|RD_3|LM,		0,		I2,		0,	I34 }, /* same */
+{"lcache",		"t,A(b)",	0,    (int) M_LWL_AB,	INSN_MACRO,		0,		I2,		0,	I34 }, /* as lwl */
+{"lwr",			"t,o(b)",	0x98000000, 0xfc000000,	WR_1|RD_3|LM,		0,		I1,		0,	I34 },
+{"lwr",			"t,A(b)",	0,    (int) M_LWR_AB,	INSN_MACRO,		0,		I1,		0,	I34 },
+{"flush",		"t,o(b)",	0x98000000, 0xfc000000,	WR_1|RD_3|LM,		0,		I2,		0,	I34 }, /* same */
+{"flush",		"t,A(b)",	0,    (int) M_LWR_AB,	INSN_MACRO,		0,		I2,		0,	I34 }, /* as lwr */
 {"fork",		"d,s,t",	0x7c000008, 0xfc0007ff, WR_1|RD_2|RD_3|TRAP,	0,		0,		MT32,	0 },
+{"lwupc",		"s,-A",		0xec100000, 0xfc180000, WR_1|RD_pc,		0,		I66,		0,	0 },
 {"lwu",			"t,o(b)",	0x9c000000, 0xfc000000,	WR_1|RD_3|LM,		0,		I3,		0,	0 },
+{"lwu"	,		"s,-a(+R)",	0xec100000, 0xfc180000, WR_1|RD_pc,		0,		I66,		0,	0 },
 {"lwu",			"t,A(b)",	0,    (int) M_LWU_AB,	INSN_MACRO,		0,		I3,		0,	0 },
-{"lwxc1",		"D,t(b)",	0x4c000000, 0xfc00f83f, WR_1|RD_2|RD_3|LM|FP_S,     0,		I4_33,		0,	0 },
+{"lwxc1",		"D,t(b)",	0x4c000000, 0xfc00f83f, WR_1|RD_2|RD_3|LM|FP_S,     0,		I4_33,		0,	I34 },
 {"lwxs",		"d,t(b)",	0x70000088, 0xfc0007ff,	WR_1|RD_2|RD_3|LM,	     0,		0,		SMT,	0 },
 {"macc",		"d,s,t",	0x00000028, 0xfc0007ff, WR_1|RD_2|RD_3|WR_HILO,	     0,		N412,		0,	0 },
 {"macc",		"d,s,t",	0x00000158, 0xfc0007ff, WR_1|RD_2|RD_3|WR_HILO,	     0,		N5,		0,	0 },
@@ -1242,18 +1311,18 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"maccus",		"d,s,t",	0x00000468, 0xfc0007ff,	WR_1|RD_2|RD_3|WR_HILO,	     0,		N412,		0,	0 },
 {"mad",			"s,t",		0x70000000, 0xfc00ffff, RD_1|RD_2|MOD_HILO,	     0,		P3,		0,	0 },
 {"madu",		"s,t",		0x70000001, 0xfc00ffff, RD_1|RD_2|MOD_HILO,	     0,		P3,		0,	0 },
-{"madd.d",		"D,R,S,T",	0x4c000021, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_D,    0,		I4_33,		0,	0 },
+{"madd.d",		"D,R,S,T",	0x4c000021, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_D,    0,		I4_33,		0,	I34 },
 {"madd.d",		"D,S,T",	0x46200018, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	     0,		IL2E,		0,	0 },
 {"madd.d",		"D,S,T",	0x72200018, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	     0,		IL2F,		0,	0 },
-{"madd.s",		"D,R,S,T",	0x4c000020, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_S,    0,		I4_33,		0,	0 },
+{"madd.s",		"D,R,S,T",	0x4c000020, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_S,    0,		I4_33,		0,	I34 },
 {"madd.s",		"D,S,T",	0x46000018, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	     0,		IL2E,		0,	0 },
 {"madd.s",		"D,S,T",	0x72000018, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	     0,		IL2F,		0,	0 },
 {"madd.s",		"D,S,T",	0x4600001c, 0xffe0003f, WR_1|RD_2|RD_3|FP_S,	     0,		EE,		0,	0 },
-{"madd.ps",		"D,R,S,T",	0x4c000026, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_D,    0,		I5_33,		0,	0 },
+{"madd.ps",		"D,R,S,T",	0x4c000026, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_D,    0,		I5_33,		0,	I34 },
 {"madd.ps",		"D,S,T",	0x45600018, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	     0,		IL2E,		0,	0 },
 {"madd.ps",		"D,S,T",	0x72c00018, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	     0,		IL2F,		0,	0 },
 {"madd",		"s,t",		0x0000001c, 0xfc00ffff, RD_1|RD_2|WR_HILO,           0,		L1,		0,	0 },
-{"madd",		"s,t",		0x70000000, 0xfc00ffff, RD_1|RD_2|MOD_HILO,          0,		I32|N55,	0,	0 },
+{"madd",		"s,t",		0x70000000, 0xfc00ffff, RD_1|RD_2|MOD_HILO,          0,		I32|N55,	0,	I34 },
 {"madd",		"s,t",		0x70000000, 0xfc00ffff, RD_1|RD_2|WR_HILO|IS_M,      0,		G1,		0,	0 },
 {"madd",		"7,s,t",	0x70000000, 0xfc00e7ff, RD_2|RD_3|MOD_a,             0,         0,		D32,	0 },
 {"madd",		"d,s,t",	0x70000000, 0xfc0007ff, WR_1|RD_2|RD_3|WR_HILO|IS_M, 0,		G1,		0,	0 },
@@ -1262,7 +1331,7 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"madda.s",		"S,T",		0x4600001e, 0xffe007ff, RD_1|RD_2|FP_S,		     0,		EE,		0,	0 },
 {"maddp",		"s,t",		0x70000441, 0xfc00ffff,	RD_1|RD_2|MOD_HILO,	     0,		0,		SMT,	0 },
 {"maddu",		"s,t",		0x0000001d, 0xfc00ffff, RD_1|RD_2|WR_HILO,           0,		L1,		0,	0 },
-{"maddu",		"s,t",		0x70000001, 0xfc00ffff, RD_1|RD_2|MOD_HILO,          0,		I32|N55,	0,	0 },
+{"maddu",		"s,t",		0x70000001, 0xfc00ffff, RD_1|RD_2|MOD_HILO,          0,		I32|N55,	0,	I34 },
 {"maddu",		"s,t",		0x70000001, 0xfc00ffff, RD_1|RD_2|WR_HILO|IS_M,      0,		G1,		0,	0 },
 {"maddu",		"7,s,t",	0x70000001, 0xfc00e7ff, RD_2|RD_3|MOD_a,             0,         0,		D32,	0 },
 {"maddu",		"d,s,t",	0x70000001, 0xfc0007ff, WR_1|RD_2|RD_3|WR_HILO|IS_M, 0,		G1,		0,	0 },
@@ -1273,6 +1342,7 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"max.ob",		"D,S,Q",	0x48000007, 0xfc20003f,	WR_1|RD_2|RD_3|FP_D,	0,		N54,		0,	0 },
 {"max.qh",		"X,Y,Q",	0x78200007, 0xfc20003f,	WR_1|RD_2|RD_3|FP_D,	0,		0,		MX,	0 },
 {"max.s",		"D,S,T",	0x46000028, 0xffe0003f, WR_1|RD_2|RD_3|FP_S,	0,		EE,		0,	0 },
+{"max.s",		"D,S,T",	0x4600001e, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
 {"mfbpc",		"t",		0x4000c000, 0xffe0ffff,	WR_1|RD_C0|LCD,		0,		EE,		0,	0 },
 {"mfdab",		"t",		0x4000c004, 0xffe0ffff,	WR_1|RD_C0|LCD,		0,		EE,		0,	0 },
 {"mfdabm",		"t",		0x4000c005, 0xffe0ffff,	WR_1|RD_C0|LCD,		0,		EE,		0,	0 },
@@ -1315,10 +1385,10 @@ const struct mips_opcode mips_builtin_opcodes[] =
 /* mfhc2 is at the bottom of the table.  */
 /* mfc3 is at the bottom of the table.  */
 {"mfdr",		"t,G",		0x7000003d, 0xffe007ff,	WR_1|RD_C0|LCD,		0,		N5,		0,	0 },
-{"mfhi",		"d",		0x00000010, 0xffff07ff,	WR_1|RD_HI,		0,		I1,		0,	0 },
+{"mfhi",		"d",		0x00000010, 0xffff07ff,	WR_1|RD_HI,		0,		I1,		0,	I34 },
 {"mfhi",		"d,9",		0x00000010, 0xff9f07ff, WR_1|RD_HI,		0,		0,		D32,	0 },
 {"mfhi1",		"d",		0x70000010, 0xffff07ff,	WR_1|RD_HI,		0,		EE,		0,	0 },
-{"mflo",		"d",		0x00000012, 0xffff07ff,	WR_1|RD_LO,		0,		I1,		0,	0 },
+{"mflo",		"d",		0x00000012, 0xffff07ff,	WR_1|RD_LO,		0,		I1,		0,	I34 },
 {"mflo",		"d,9",		0x00000012, 0xff9f07ff, WR_1|RD_LO,		0,		0,		D32,	0 },
 {"mflo1",		"d",		0x70000012, 0xffff07ff,	WR_1|RD_LO,		0,		EE,		0,	0 },
 {"mflhxu",		"d",		0x00000052, 0xffff07ff,	WR_1|MOD_HILO,		0,		0,		SMT,	0 },
@@ -1328,37 +1398,38 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"min.ob",		"D,S,Q",	0x48000006, 0xfc20003f,	WR_1|RD_2|RD_3|FP_D,	0,		N54,		0,	0 },
 {"min.qh",		"X,Y,Q",	0x78200006, 0xfc20003f,	WR_1|RD_2|RD_3|FP_D,	0,		0,		MX,	0 },
 {"min.s",		"D,S,T",	0x46000029, 0xffe0003f, WR_1|RD_2|RD_3|FP_S,	0,		EE,		0,	0 },
+{"min.s",		"D,S,T",	0x4600001c, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
 {"mov.d",		"D,S",		0x46200006, 0xffff003f,	WR_1|RD_2|FP_D,		0,		I1,		0,	SF },
 {"mov.s",		"D,S",		0x46000006, 0xffff003f,	WR_1|RD_2|FP_S,		0,		I1,		0,	0 },
-{"mov.ps",		"D,S",		0x46c00006, 0xffff003f,	WR_1|RD_2|FP_D,		0,		I5_33|IL2F,	0,	0 },
+{"mov.ps",		"D,S",		0x46c00006, 0xffff003f,	WR_1|RD_2|FP_D,		0,		I5_33|IL2F,	0,	I34 },
 {"mov.ps",		"D,S",		0x45600006, 0xffff003f,	WR_1|RD_2|FP_D,		0,		IL2E,		0,	0 },
-{"movf",		"d,s,N",	0x00000001, 0xfc0307ff, WR_1|RD_2|RD_CC|FP_S|FP_D, 0,		I4_32,		0,	0  },
-{"movf.d",		"D,S,N",	0x46200011, 0xffe3003f, WR_1|RD_2|RD_CC|FP_D,   0,		I4_32,		0,	0 },
+{"movf",		"d,s,N",	0x00000001, 0xfc0307ff, WR_1|RD_2|RD_CC|FP_S|FP_D, 0,		I4_32,		0,	I34  },
+{"movf.d",		"D,S,N",	0x46200011, 0xffe3003f, WR_1|RD_2|RD_CC|FP_D,   0,		I4_32,		0,	I34 },
 {"movf.l",		"D,S,N",	0x46a00011, 0xffe3003f, WR_1|RD_2|RD_CC|FP_D,	0,		SB1,		MX,	0 },
 {"movf.l",		"X,Y,N",	0x46a00011, 0xffe3003f, WR_1|RD_2|RD_CC|FP_D,	0,		SB1,		MX,	0 },
-{"movf.s",		"D,S,N",	0x46000011, 0xffe3003f, WR_1|RD_2|RD_CC|FP_S,   0,		I4_32,		0,	0 },
-{"movf.ps",		"D,S,N",	0x46c00011, 0xffe3003f, WR_1|RD_2|RD_CC|FP_D,	0,		I5_33,		0,	0 },
-{"movn",		"d,v,t",	0x0000000b, 0xfc0007ff, WR_1|RD_2|RD_3, 	0,		I4_32|IL2E|IL2F|EE, 0,	0 },
+{"movf.s",		"D,S,N",	0x46000011, 0xffe3003f, WR_1|RD_2|RD_CC|FP_S,   0,		I4_32,		0,	I34 },
+{"movf.ps",		"D,S,N",	0x46c00011, 0xffe3003f, WR_1|RD_2|RD_CC|FP_D,	0,		I5_33,		0,	I34 },
+{"movn",		"d,v,t",	0x0000000b, 0xfc0007ff, WR_1|RD_2|RD_3, 	0,		I4_32|IL2E|IL2F|EE, 0,	I34 },
 {"movnz",		"d,v,t",	0x0000000b, 0xfc0007ff, WR_1|RD_2|RD_3, 	0,		IL2E|IL2F|IL3A,	0,	0 },
 {"ffc",			"d,v",		0x0000000b, 0xfc1f07ff,	WR_1|RD_2,		0,		L1,		0,	0 },
-{"movn.d",		"D,S,t",	0x46200013, 0xffe0003f, WR_1|RD_2|RD_3|FP_D,    0,		I4_32,		0,	0 },
+{"movn.d",		"D,S,t",	0x46200013, 0xffe0003f, WR_1|RD_2|RD_3|FP_D,    0,		I4_32,		0,	I34 },
 {"movn.l",		"D,S,t",	0x46a00013, 0xffe0003f, WR_1|RD_2|RD_3|FP_D,    0,		SB1,		MX,	0 },
 {"movn.l",		"X,Y,t",	0x46a00013, 0xffe0003f, WR_1|RD_2|RD_3|FP_D,    0,		SB1,		MX,	0 },
-{"movn.s",		"D,S,t",	0x46000013, 0xffe0003f, WR_1|RD_2|RD_3|FP_S,    0,		I4_32,		0,	0 },
-{"movn.ps",		"D,S,t",	0x46c00013, 0xffe0003f, WR_1|RD_2|RD_3|FP_D,    0,		I5_33,		0,	0 },
-{"movt",		"d,s,N",	0x00010001, 0xfc0307ff, WR_1|RD_2|RD_CC|FP_S|FP_D, 0,		I4_32,		0,	0 },
-{"movt.d",		"D,S,N",	0x46210011, 0xffe3003f, WR_1|RD_2|RD_CC|FP_D,   0,		I4_32,		0,	0 },
+{"movn.s",		"D,S,t",	0x46000013, 0xffe0003f, WR_1|RD_2|RD_3|FP_S,    0,		I4_32,		0,	I34 },
+{"movn.ps",		"D,S,t",	0x46c00013, 0xffe0003f, WR_1|RD_2|RD_3|FP_D,    0,		I5_33,		0,	I34 },
+{"movt",		"d,s,N",	0x00010001, 0xfc0307ff, WR_1|RD_2|RD_CC|FP_S|FP_D, 0,		I4_32,		0,	I34 },
+{"movt.d",		"D,S,N",	0x46210011, 0xffe3003f, WR_1|RD_2|RD_CC|FP_D,   0,		I4_32,		0,	I34 },
 {"movt.l",		"D,S,N",	0x46a10011, 0xffe3003f, WR_1|RD_2|RD_CC|FP_D,   0,		SB1,		MX,	0 },
 {"movt.l",		"X,Y,N",	0x46a10011, 0xffe3003f, WR_1|RD_2|RD_CC|FP_D,   0,		SB1,		MX,	0 },
-{"movt.s",		"D,S,N",	0x46010011, 0xffe3003f, WR_1|RD_2|RD_CC|FP_S,   0,		I4_32,		0,	0 },
-{"movt.ps",		"D,S,N",	0x46c10011, 0xffe3003f, WR_1|RD_2|RD_CC|FP_D,	0,		I5_33,		0,	0 },
-{"movz",		"d,v,t",	0x0000000a, 0xfc0007ff, WR_1|RD_2|RD_3, 	0,		I4_32|IL2E|IL2F|EE, 0,	0 },
+{"movt.s",		"D,S,N",	0x46010011, 0xffe3003f, WR_1|RD_2|RD_CC|FP_S,   0,		I4_32,		0,	I34 },
+{"movt.ps",		"D,S,N",	0x46c10011, 0xffe3003f, WR_1|RD_2|RD_CC|FP_D,	0,		I5_33,		0,	I34 },
+{"movz",		"d,v,t",	0x0000000a, 0xfc0007ff, WR_1|RD_2|RD_3, 	0,		I4_32|IL2E|IL2F|EE, 0,	I34 },
 {"ffs",			"d,v",		0x0000000a, 0xfc1f07ff,	WR_1|RD_2,		0,		L1,		0,	0 },
-{"movz.d",		"D,S,t",	0x46200012, 0xffe0003f, WR_1|RD_2|RD_3|FP_D,    0,		I4_32,		0,	0 },
+{"movz.d",		"D,S,t",	0x46200012, 0xffe0003f, WR_1|RD_2|RD_3|FP_D,    0,		I4_32,		0,	I34 },
 {"movz.l",		"D,S,t",	0x46a00012, 0xffe0003f, WR_1|RD_2|RD_3|FP_D,    0,		SB1,		MX,	0 },
 {"movz.l",		"X,Y,t",	0x46a00012, 0xffe0003f, WR_1|RD_2|RD_3|FP_D,    0,		SB1,		MX,	0 },
-{"movz.s",		"D,S,t",	0x46000012, 0xffe0003f, WR_1|RD_2|RD_3|FP_S,    0,		I4_32,		0,	0 },
-{"movz.ps",		"D,S,t",	0x46c00012, 0xffe0003f, WR_1|RD_2|RD_3|FP_D,    0,		I5_33,		0,	0 },
+{"movz.s",		"D,S,t",	0x46000012, 0xffe0003f, WR_1|RD_2|RD_3|FP_S,    0,		I4_32,		0,	I34 },
+{"movz.ps",		"D,S,t",	0x46c00012, 0xffe0003f, WR_1|RD_2|RD_3|FP_D,    0,		I5_33,		0,	I34 },
 {"msac",		"d,s,t",	0x000001d8, 0xfc0007ff,	WR_1|RD_2|RD_3|WR_HILO,	0,		N5,		0,	0 },
 {"msacu",		"d,s,t",	0x000001d9, 0xfc0007ff,	WR_1|RD_2|RD_3|WR_HILO,	0,		N5,		0,	0 },
 {"msachi",		"d,s,t",	0x000003d8, 0xfc0007ff,	WR_1|RD_2|RD_3|WR_HILO,	0,		N5,		0,	0 },
@@ -1370,22 +1441,22 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"msgld",		"t",		0,    (int) M_MSGLD_T,	INSN_MACRO,		0,		XLR,		0,	0 },
 {"msgwait",		"", 		0,    (int) M_MSGWAIT,	INSN_MACRO,		0,		XLR,		0,	0 },
 {"msgwait",		"t",		0,    (int) M_MSGWAIT_T,INSN_MACRO,		0,		XLR,		0,	0 },
-{"msub.d",		"D,R,S,T",	0x4c000029, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_D, 0,		I4_33,		0,	0 },
+{"msub.d",		"D,R,S,T",	0x4c000029, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_D, 0,		I4_33,		0,	I34 },
 {"msub.d",		"D,S,T",	0x46200019, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2E,		0,	0 },
 {"msub.d",		"D,S,T",	0x72200019, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2F,		0,	0 },
-{"msub.s",		"D,R,S,T",	0x4c000028, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_S, 0,		I4_33,		0,	0 },
+{"msub.s",		"D,R,S,T",	0x4c000028, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_S, 0,		I4_33,		0,	I34 },
 {"msub.s",		"D,S,T",	0x46000019, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		IL2E,		0,	0 },
 {"msub.s",		"D,S,T",	0x72000019, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		IL2F,		0,	0 },
 {"msub.s",		"D,S,T",	0x4600001d, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		EE,		0,	0 },
-{"msub.ps",		"D,R,S,T",	0x4c00002e, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_D, 0,		I5_33,		0,	0 },
+{"msub.ps",		"D,R,S,T",	0x4c00002e, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_D, 0,		I5_33,		0,	I34 },
 {"msub.ps",		"D,S,T",	0x45600019, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2E,		0,	0 },
 {"msub.ps",		"D,S,T",	0x72c00019, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2F,		0,	0 },
 {"msub",		"s,t",		0x0000001e, 0xfc00ffff, RD_1|RD_2|WR_HILO,	0,		L1,		0,	0 },
-{"msub",		"s,t",		0x70000004, 0xfc00ffff, RD_1|RD_2|MOD_HILO,     0,		I32|N55,	0,	0 },
+{"msub",		"s,t",		0x70000004, 0xfc00ffff, RD_1|RD_2|MOD_HILO,     0,		I32|N55,	0,	I34 },
 {"msub",		"7,s,t",	0x70000004, 0xfc00e7ff, RD_2|RD_3|MOD_a,        0,              0,		D32,	0 },
 {"msuba.s",		"S,T",		0x4600001f, 0xffe007ff,	RD_1|RD_2|FP_S,		0,		EE,		0,	0 },
 {"msubu",		"s,t",		0x0000001f, 0xfc00ffff, RD_1|RD_2|WR_HILO,	0,		L1,		0,	0 },
-{"msubu",		"s,t",		0x70000005, 0xfc00ffff, RD_1|RD_2|MOD_HILO,     0,		I32|N55,	0,	0 },
+{"msubu",		"s,t",		0x70000005, 0xfc00ffff, RD_1|RD_2|MOD_HILO,     0,		I32|N55,	0,	I34 },
 {"msubu",		"7,s,t",	0x70000005, 0xfc00e7ff, RD_2|RD_3|MOD_a,        0,              0,		D32,	0 },
 {"mtbpc",		"t",		0x4080c000, 0xffe0ffff,	RD_1|WR_C0|COD,		0,		EE,		0,	0 },
 {"mtdab",		"t",		0x4080c004, 0xffe0ffff,	RD_1|WR_C0|COD,		0,		EE,		0,	0 },
@@ -1412,10 +1483,10 @@ const struct mips_opcode mips_builtin_opcodes[] =
 /* mthc2 is at the bottom of the table.  */
 /* mtc3 is at the bottom of the table.  */
 {"mtdr",		"t,G",		0x7080003d, 0xffe007ff,	RD_1|WR_C0|COD,		0,		N5,		0,	0 },
-{"mthi",		"s",		0x00000011, 0xfc1fffff,	RD_1|WR_HI,		0,		I1,		0,	0 },
+{"mthi",		"s",		0x00000011, 0xfc1fffff,	RD_1|WR_HI,		0,		I1,		0,	I34 },
 {"mthi",		"s,7",		0x00000011, 0xfc1fe7ff, RD_1|WR_HI,		0,		0,		D32,	0 },
 {"mthi1",		"s",		0x70000011, 0xfc1fffff,	RD_1|WR_HI,		0,		EE,		0,	0 },
-{"mtlo",		"s",		0x00000013, 0xfc1fffff,	RD_1|WR_LO,		0,		I1,		0,	0 },
+{"mtlo",		"s",		0x00000013, 0xfc1fffff,	RD_1|WR_LO,		0,		I1,		0,	I34 },
 {"mtlo",		"s,7",		0x00000013, 0xfc1fe7ff, RD_1|WR_LO,		0,		0,		D32,	0 },
 {"mtlo1",		"s",		0x70000013, 0xfc1fffff,	RD_1|WR_LO,		0,		EE,		0,	0 },
 {"mtlhx",		"s",		0x00000053, 0xfc1fffff,	RD_1|MOD_HILO,		0,		0,		SMT,	0 },
@@ -1450,13 +1521,16 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"mul.s",		"D,V,T",	0x46000002, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I1,		0,	0 },
 {"mul.ob",		"X,Y,Q",	0x78000030, 0xfc20003f,	WR_1|RD_2|RD_3|FP_D,	0,		SB1,		MX,	0 },
 {"mul.ob",		"D,S,Q",	0x48000030, 0xfc20003f,	WR_1|RD_2|RD_3|FP_D,	0,		N54,		0,	0 },
-{"mul.ps",		"D,V,T",	0x46c00002, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"mul.ps",		"D,V,T",	0x46c00002, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"mul.ps",		"D,V,T",	0x45600002, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2E,		0,	0 },
 {"mul.qh",		"X,Y,Q",	0x78200030, 0xfc20003f,	WR_1|RD_2|RD_3|FP_D,	0,		0,		MX,	0 },
-{"mul",			"d,v,t",	0x70000002, 0xfc0007ff, WR_1|RD_2|RD_3|WR_HILO, 0,		I32|P3|N55,	0,	0},
+{"muh",			"d,v,t",	0x000000d8, 0xfc0007ff, WR_1|RD_2|RD_3, 	0,		I34,		0,	0},
+{"muhu",		"d,v,t",	0x000000d9, 0xfc0007ff, WR_1|RD_2|RD_3, 	0,		I34,		0,	0},
+{"mul",			"d,v,t",	0x00000098, 0xfc0007ff, WR_1|RD_2|RD_3, 	0,		I34,		0,	0},
+{"mul",			"d,v,t",	0x70000002, 0xfc0007ff, WR_1|RD_2|RD_3|WR_HILO, 0,		I32|P3|N55,	0,	I34},
 {"mul",			"d,s,t",	0x00000058, 0xfc0007ff,	WR_1|RD_2|RD_3|WR_HILO,	0,		N54,		0,	0 },
-{"mul",			"d,v,t",	0,    (int) M_MUL,	INSN_MACRO,		0,		I1,		0,	0 },
-{"mul",			"d,v,I",	0,    (int) M_MUL_I,	INSN_MACRO,		0,		I1,		0,	0 },
+{"mul",			"d,v,t",	0,    (int) M_MUL,	INSN_MACRO,		0,		I1,		0,	I34 },
+{"mul",			"d,v,I",	0,    (int) M_MUL_I,	INSN_MACRO,		0,		I1,		0,	I34 },
 {"mula.ob",		"Y,Q",		0x78000033, 0xfc2007ff,	RD_1|RD_2|FP_D,		WR_MACC,	SB1,		MX,	0 },
 {"mula.ob",		"S,Q",		0x48000033, 0xfc2007ff,	RD_1|RD_2|FP_D,		WR_MACC,	N54,		0,	0 },
 {"mula.qh",		"Y,Q",		0x78200033, 0xfc2007ff,	RD_1|RD_2|FP_D,		WR_MACC,	0,		MX,	0 },
@@ -1466,10 +1540,10 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"mull.ob",		"Y,Q",		0x78000433, 0xfc2007ff,	RD_1|RD_2|FP_D, 	WR_MACC,	SB1,		MX,	0 },
 {"mull.ob",		"S,Q",		0x48000433, 0xfc2007ff,	RD_1|RD_2|FP_D,		WR_MACC,	N54,		0,	0 },
 {"mull.qh",		"Y,Q",		0x78200433, 0xfc2007ff,	RD_1|RD_2|FP_D,		WR_MACC,	0,		MX,	0 },
-{"mulo",		"d,v,t",	0,    (int) M_MULO,	INSN_MACRO,		0,		I1,		0,	0 },
-{"mulo",		"d,v,I",	0,    (int) M_MULO_I,	INSN_MACRO,		0,		I1,		0,	0 },
-{"mulou",		"d,v,t",	0,    (int) M_MULOU,	INSN_MACRO,		0,		I1,		0,	0 },
-{"mulou",		"d,v,I",	0,    (int) M_MULOU_I,	INSN_MACRO,		0,		I1,		0,	0 },
+{"mulo",		"d,v,t",	0,    (int) M_MULO,	INSN_MACRO,		0,		I1,		0,	I34 },
+{"mulo",		"d,v,I",	0,    (int) M_MULO_I,	INSN_MACRO,		0,		I1,		0,	I34 },
+{"mulou",		"d,v,t",	0,    (int) M_MULOU,	INSN_MACRO,		0,		I1,		0,	I34 },
+{"mulou",		"d,v,I",	0,    (int) M_MULOU_I,	INSN_MACRO,		0,		I1,		0,	I34 },
 {"mulr.ps",		"D,S,T",	0x46c0001a, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		0,		M3D,	0 },
 {"muls",		"d,s,t",	0x000000d8, 0xfc0007ff,	WR_1|RD_2|RD_3|WR_HILO,	0,		N5,		0,	0 },
 {"mulsu",		"d,s,t",	0x000000d9, 0xfc0007ff,	WR_1|RD_2|RD_3|WR_HILO,	0,		N5,		0,	0 },
@@ -1481,40 +1555,41 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"mulsl.ob",		"Y,Q",		0x78000432, 0xfc2007ff,	RD_1|RD_2|FP_D,		WR_MACC,	SB1,		MX,	0 },
 {"mulsl.ob",		"S,Q",		0x48000432, 0xfc2007ff,	RD_1|RD_2|FP_D,		WR_MACC,	N54,		0,	0 },
 {"mulsl.qh",		"Y,Q",		0x78200432, 0xfc2007ff,	RD_1|RD_2|FP_D,		WR_MACC,	0,		MX,	0 },
-{"mult",		"s,t",		0x00000018, 0xfc00ffff, RD_1|RD_2|WR_HILO|IS_M, 0,		I1,		0,	0 },
+{"mult",		"s,t",		0x00000018, 0xfc00ffff, RD_1|RD_2|WR_HILO|IS_M, 0,		I1,		0,	I34 },
 {"mult",		"7,s,t",	0x00000018, 0xfc00e7ff, RD_2|RD_3|WR_a,         0,              0,		D32,	0 },
 {"mult",		"d,s,t",	0x00000018, 0xfc0007ff, WR_1|RD_2|RD_3|WR_HILO|IS_M, 0,		G1,		0,	0 },
 {"mult1",		"s,t",		0x70000018, 0xfc00ffff, RD_1|RD_2|WR_HILO|IS_M, 0,		EE,		0,	0 },
 {"mult1",		"d,s,t",	0x70000018, 0xfc0007ff, WR_1|RD_2|RD_3|WR_HILO|IS_M, 0,		EE,		0,	0 },
 {"multp",		"s,t",		0x00000459, 0xfc00ffff,	RD_1|RD_2|MOD_HILO,	0,		0,		SMT,	0 },
-{"multu",		"s,t",		0x00000019, 0xfc00ffff, RD_1|RD_2|WR_HILO|IS_M, 0,		I1,		0,	0 },
+{"multu",		"s,t",		0x00000019, 0xfc00ffff, RD_1|RD_2|WR_HILO|IS_M, 0,		I1,		0,	I34 },
 {"multu",		"7,s,t",	0x00000019, 0xfc00e7ff, RD_2|RD_3|WR_a,         0,              0,		D32,	0 },
 {"multu",		"d,s,t",	0x00000019, 0xfc0007ff, WR_1|RD_2|RD_3|WR_HILO|IS_M, 0,		G1,		0,	0 },
 {"multu1",		"s,t",		0x70000019, 0xfc00ffff, RD_1|RD_2|WR_HILO|IS_M, 0,		EE,		0,	0 },
 {"multu1",		"d,s,t",	0x70000019, 0xfc0007ff, WR_1|RD_2|RD_3|WR_HILO|IS_M, 0,		EE,		0,	0 },
+{"mulu",		"d,v,t",	0x00000099, 0xfc0007ff, WR_1|RD_2|RD_3, 	0,		I34,		0,	0},
 {"mulu",		"d,s,t",	0x00000059, 0xfc0007ff,	WR_1|RD_2|RD_3|WR_HILO,	0,		N5,		0,	0 },
 {"neg",			"d,w",		0x00000022, 0xffe007ff,	WR_1|RD_2,		0,		I1,		0,	0 }, /* sub 0 */
 {"negu",		"d,w",		0x00000023, 0xffe007ff,	WR_1|RD_2,		0,		I1,		0,	0 }, /* subu 0 */
 {"neg.d",		"D,V",		0x46200007, 0xffff003f,	WR_1|RD_2|FP_D,		0,		I1,		0,	SF },
 {"neg.s",		"D,V",		0x46000007, 0xffff003f,	WR_1|RD_2|FP_S,		0,		I1,		0,	0 },
-{"neg.ps",		"D,V",		0x46c00007, 0xffff003f,	WR_1|RD_2|FP_D,		0,		I5_33|IL2F,	0,	0 },
+{"neg.ps",		"D,V",		0x46c00007, 0xffff003f,	WR_1|RD_2|FP_D,		0,		I5_33|IL2F,	0,	I34 },
 {"neg.ps",		"D,V",		0x45600007, 0xffff003f,	WR_1|RD_2|FP_D,		0,		IL2E,		0,	0 },
-{"nmadd.d",		"D,R,S,T",	0x4c000031, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_D, 0,		I4_33,		0,	0 },
+{"nmadd.d",		"D,R,S,T",	0x4c000031, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_D, 0,		I4_33,		0,	I34 },
 {"nmadd.d",		"D,S,T",	0x4620001a, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2E,		0,	0 },
 {"nmadd.d",		"D,S,T",	0x7220001a, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2F,		0,	0 },
-{"nmadd.s",		"D,R,S,T",	0x4c000030, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_S, 0,		I4_33,		0,	0 },
+{"nmadd.s",		"D,R,S,T",	0x4c000030, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_S, 0,		I4_33,		0,	I34 },
 {"nmadd.s",		"D,S,T",	0x4600001a, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		IL2E,		0,	0 },
 {"nmadd.s",		"D,S,T",	0x7200001a, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		IL2F,		0,	0 },
-{"nmadd.ps",		"D,R,S,T",	0x4c000036, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_D, 0,		I5_33,		0,	0 },
+{"nmadd.ps",		"D,R,S,T",	0x4c000036, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_D, 0,		I5_33,		0,	I34 },
 {"nmadd.ps",		"D,S,T",	0x4560001a, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2E,		0,	0 },
 {"nmadd.ps",		"D,S,T",	0x72c0001a, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2F,		0,	0 },
-{"nmsub.d",		"D,R,S,T",	0x4c000039, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_D, 0,		I4_33,		0,	0 },
+{"nmsub.d",		"D,R,S,T",	0x4c000039, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_D, 0,		I4_33,		0,	I34 },
 {"nmsub.d",		"D,S,T",	0x4620001b, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2E,		0,	0 },
 {"nmsub.d",		"D,S,T",	0x7220001b, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2F,		0,	0 },
-{"nmsub.s",		"D,R,S,T",	0x4c000038, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_S, 0,		I4_33,		0,	0 },
+{"nmsub.s",		"D,R,S,T",	0x4c000038, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_S, 0,		I4_33,		0,	I34 },
 {"nmsub.s",		"D,S,T",	0x4600001b, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		IL2E,		0,	0 },
 {"nmsub.s",		"D,S,T",	0x7200001b, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		IL2F,		0,	0 },
-{"nmsub.ps",		"D,R,S,T",	0x4c00003e, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_D, 0,		I5_33,		0,	0 },
+{"nmsub.ps",		"D,R,S,T",	0x4c00003e, 0xfc00003f, WR_1|RD_2|RD_3|RD_4|FP_D, 0,		I5_33,		0,	I34 },
 {"nmsub.ps",		"D,S,T",	0x4560001b, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2E,		0,	0 },
 {"nmsub.ps",		"D,S,T",	0x72c0001b, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2F,		0,	0 },
 /* nop is at the start of the table.  */
@@ -1579,8 +1654,8 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"pickt.qh",		"X,Y,Q",	0x78200003, 0xfc20003f,	WR_1|RD_2|RD_3|FP_D,	0,		0,		MX,	0 },
 {"pinteh",		"d,s,t",	0x700002a9, 0xfc0007ff, WR_1|RD_2|RD_3,		0,		MMI,		0,	0 },
 {"pinth",		"d,s,t",	0x70000289, 0xfc0007ff, WR_1|RD_2|RD_3,		0,		MMI,		0,	0 },
-{"pll.ps",		"D,V,T",	0x46c0002c, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I5_33,		0,	0 },
-{"plu.ps",		"D,V,T",	0x46c0002d, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I5_33,		0,	0 },
+{"pll.ps",		"D,V,T",	0x46c0002c, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I5_33,		0,	I34 },
+{"plu.ps",		"D,V,T",	0x46c0002d, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I5_33,		0,	I34 },
 {"plzcw",		"d,s",		0x70000004, 0xfc1f07ff, WR_1|RD_2,		0,		MMI,		0,	0 },
 {"pmaddh",		"d,s,t",	0x70000409, 0xfc0007ff, WR_1|RD_2|RD_3|WR_HILO,	0,		MMI,		0,	0 },
 {"pmadduw",		"d,s,t",	0x70000029, 0xfc0007ff, WR_1|RD_2|RD_3|MOD_HILO, 0,		MMI,		0,	0 },
@@ -1622,8 +1697,8 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"psubuw",		"d,s,t",	0x70000468, 0xfc0007ff, WR_1|RD_2|RD_3,		0,		MMI,		0,	0 },
 {"pxor",		"d,s,t",	0x700004c9, 0xfc0007ff, WR_1|RD_2|RD_3,		0,		MMI,		0,	0 },
   /* pref and prefx are at the start of the table.  */
-{"pul.ps",		"D,V,T",	0x46c0002e, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I5_33,		0,	0 },
-{"puu.ps",		"D,V,T",	0x46c0002f, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I5_33,		0,	0 },
+{"pul.ps",		"D,V,T",	0x46c0002e, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I5_33,		0,	I34 },
+{"puu.ps",		"D,V,T",	0x46c0002f, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I5_33,		0,	I34 },
 {"pperm",		"s,t",		0x70000481, 0xfc00ffff,	RD_1|RD_2|MOD_HILO,	0,		0,		SMT,	0 },
 {"qfsrv",		"d,s,t",	0x700006e8, 0xfc0007ff, WR_1|RD_2|RD_3,		0,		MMI,		0,	0 },
 {"qmac.00",		"s,t",		0x70000412, 0xfc00ffff, RD_1|RD_2|MOD_HILO,	0,		IOCT2,		0,	0 },
@@ -1652,12 +1727,12 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"recip2.d",		"D,S,T",	0x4620001c, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		0,		M3D,	0 },
 {"recip2.ps",		"D,S,T",	0x46c0001c, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		0,		M3D,	0 },
 {"recip2.s",		"D,S,T",	0x4600001c, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		0,		M3D,	0 },
-{"rem",			"z,s,t",	0x0000001a, 0xfc00ffff, RD_2|RD_3|WR_HILO,      0,		I1,		0,	0 },
-{"rem",			"d,v,t",	0,    (int) M_REM_3,	INSN_MACRO,		0,		I1,		0,	0 },
-{"rem",			"d,v,I",	0,    (int) M_REM_3I,	INSN_MACRO,		0,		I1,		0,	0 },
-{"remu",		"z,s,t",	0x0000001b, 0xfc00ffff, RD_2|RD_3|WR_HILO,      0,		I1,		0,	0 },
-{"remu",		"d,v,t",	0,    (int) M_REMU_3,	INSN_MACRO,		0,		I1,		0,	0 },
-{"remu",		"d,v,I",	0,    (int) M_REMU_3I,	INSN_MACRO,		0,		I1,		0,	0 },
+{"rem",			"z,s,t",	0x0000001a, 0xfc00ffff, RD_2|RD_3|WR_HILO,      INSN2_ALIAS,	I1,		0,	I34 },
+{"rem",			"d,v,t",	0,    (int) M_REM_3,	INSN_MACRO,		0,		I1,		0,	I34 },
+{"rem",			"d,v,I",	0,    (int) M_REM_3I,	INSN_MACRO,		0,		I1,		0,	I34 },
+{"remu",		"z,s,t",	0x0000001b, 0xfc00ffff, RD_2|RD_3|WR_HILO,      INSN2_ALIAS,	I1,		0,	I34 },
+{"remu",		"d,v,t",	0,    (int) M_REMU_3,	INSN_MACRO,		0,		I1,		0,	I34 },
+{"remu",		"d,v,I",	0,    (int) M_REMU_3I,	INSN_MACRO,		0,		I1,		0,	I34 },
 {"rdhwr",		"t,K",		0x7c00003b, 0xffe007ff, WR_1,			0,		I33,		0,	0 },
 {"rdpgpr",		"d,w",		0x41400000, 0xffe007ff, WR_1,			0,		I33,		0,	0 },
 /* rfe is moved below as it now conflicts with tlbgp */
@@ -1702,33 +1777,38 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"saad",		"t,(b)",	0x70000019, 0xfc00ffff,	RD_1|RD_2|SM,		0,		IOCTP,		0,	0 },
 {"sb",			"t,o(b)",	0xa0000000, 0xfc000000,	RD_1|RD_3|SM,		0,		I1,		0,	0 },
 {"sb",			"t,A(b)",	0,    (int) M_SB_AB,	INSN_MACRO,		0,		I1,		0,	0 },
-{"sc",			"t,o(b)",	0xe0000000, 0xfc000000, MOD_1|RD_3|SM,		0,		I2,		0,	EE },
-{"sc",			"t,A(b)",	0,    (int) M_SC_AB,	INSN_MACRO,		0,		I2,		0,	EE },
-{"scd",			"t,o(b)",	0xf0000000, 0xfc000000, MOD_1|RD_3|SM,		0,		I3,		0,	EE },
-{"scd",			"t,A(b)",	0,    (int) M_SCD_AB,	INSN_MACRO,		0,		I3,		0,	EE },
+{"sc",			"t,+j(b)",	0x7c000026, 0xfc00007f, MOD_1|RD_3|SM,		0,		I34,		0,	0 },
+{"sc",			"t,o(b)",	0xe0000000, 0xfc000000, MOD_1|RD_3|SM,		0,		I2,		0,	EE|I34 },
+{"sc",			"t,A(b)",	0,    (int) M_SC_AB,	INSN_MACRO,		0,		I2,		0,	EE|I34 },
+{"scd",			"t,+j(b)",	0x7c000027, 0xfc00007f, MOD_1|RD_3|SM,		0,		I66,		0,	0 },
+{"scd",			"t,o(b)",	0xf0000000, 0xfc000000, MOD_1|RD_3|SM,		0,		I3,		0,	EE|I66 },
+{"scd",			"t,A(b)",	0,    (int) M_SCD_AB,	INSN_MACRO,		0,		I3,		0,	EE|I66 },
 /* The macro has to be first to handle o32 correctly.  */
 {"sd",			"t,A(b)",	0,    (int) M_SD_AB,	INSN_MACRO,		0,		I1,		0,	0 },
 {"sd",			"t,o(b)",	0xfc000000, 0xfc000000,	RD_1|RD_3|SM,		0,		I3,		0,	0 },
 {"sdbbp",		"",		0x0000000e, 0xffffffff,	TRAP,           	0,		G2,		0,	0 },
 {"sdbbp",		"c",		0x0000000e, 0xfc00ffff,	TRAP,			0,		G2,		0,	0 },
 {"sdbbp",		"c,q",		0x0000000e, 0xfc00003f,	TRAP,			0,		G2,		0,	0 },
-{"sdbbp",		"",		0x7000003f, 0xffffffff, TRAP,           	0,		I32,		0,	0 },
-{"sdbbp",		"B",		0x7000003f, 0xfc00003f, TRAP,           	0,		I32,		0,	0 },
+{"sdbbp",		"",		0x0000000e, 0xffffffff, TRAP,           	0,		I34,		0,	0 },
+{"sdbbp",		"",		0x7000003f, 0xffffffff, TRAP,           	0,		I32,		0,	I34 },
+{"sdbbp",		"B",		0x0000000e, 0xfc00003f, TRAP,           	0,		I34,		0,	0 },
+{"sdbbp",		"B",		0x7000003f, 0xfc00003f, TRAP,           	0,		I32,		0,	I34 },
 {"sdc1",		"T,o(b)",	0xf4000000, 0xfc000000, RD_1|RD_3|SM|FP_D,	0,		I2,		0,	SF },
 {"sdc1",		"E,o(b)",	0xf4000000, 0xfc000000, RD_1|RD_3|SM|FP_D,	0,		I2,		0,	SF },
 {"sdc1",		"T,A(b)",	0,    (int) M_SDC1_AB,	INSN_MACRO,		INSN2_M_FP_D,	I2,		0,	SF },
 {"sdc1",		"E,A(b)",	0,    (int) M_SDC1_AB,	INSN_MACRO,		INSN2_M_FP_D,	I2,		0,	SF },
-{"sdc2",		"E,o(b)",	0xf8000000, 0xfc000000,	RD_3|RD_C2|SM,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE },
-{"sdc2",		"E,A(b)",	0,    (int) M_SDC2_AB,	INSN_MACRO,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE },
+{"sdc2",		"E,+:(d)",	0x49e00000, 0xffe00000,	RD_3|RD_C2|SM,		0,		I34,		0,	0 },
+{"sdc2",		"E,o(b)",	0xf8000000, 0xfc000000,	RD_3|RD_C2|SM,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"sdc2",		"E,A(b)",	0,    (int) M_SDC2_AB,	INSN_MACRO,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
 {"sdc3",		"E,o(b)",	0xfc000000, 0xfc000000,	RD_3|RD_C3|SM,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE },
 {"sdc3",		"E,A(b)",	0,    (int) M_SDC3_AB,	INSN_MACRO,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE },
 {"s.d",			"T,o(b)",	0xf4000000, 0xfc000000, RD_1|RD_3|SM|FP_D,	0,		I2,		0,	SF },
 {"s.d",			"T,A(b)",	0,    (int) M_S_DAB,	INSN_MACRO,		INSN2_M_FP_D,	I1,		0,	0 },
-{"sdl",			"t,o(b)",	0xb0000000, 0xfc000000,	RD_1|RD_3|SM,		0,		I3,		0,	0 },
-{"sdl",			"t,A(b)",	0,    (int) M_SDL_AB,	INSN_MACRO,		0,		I3,		0,	0 },
-{"sdr",			"t,o(b)",	0xb4000000, 0xfc000000,	RD_1|RD_3|SM,		0,		I3,		0,	0 },
-{"sdr",			"t,A(b)",	0,    (int) M_SDR_AB,	INSN_MACRO,		0,		I3,		0,	0 },
-{"sdxc1",		"S,t(b)",	0x4c000009, 0xfc0007ff, RD_1|RD_2|RD_3|SM|FP_D,	0,		I4_33,		0,	0 },
+{"sdl",			"t,o(b)",	0xb0000000, 0xfc000000,	RD_1|RD_3|SM,		0,		I3,		0,	I66 },
+{"sdl",			"t,A(b)",	0,    (int) M_SDL_AB,	INSN_MACRO,		0,		I3,		0,	I66 },
+{"sdr",			"t,o(b)",	0xb4000000, 0xfc000000,	RD_1|RD_3|SM,		0,		I3,		0,	I66 },
+{"sdr",			"t,A(b)",	0,    (int) M_SDR_AB,	INSN_MACRO,		0,		I3,		0,	I66 },
+{"sdxc1",		"S,t(b)",	0x4c000009, 0xfc0007ff, RD_1|RD_2|RD_3|SM|FP_D,	0,		I4_33,		0,	I34 },
 {"seb",			"d,w",		0x7c000420, 0xffe007ff,	WR_1|RD_2,		0,		I33,		0,	0 },
 {"seh",			"d,w",		0x7c000620, 0xffe007ff,	WR_1|RD_2,		0,		I33,		0,	0 },
 {"selsl",		"d,v,t",	0x00000005, 0xfc0007ff,	WR_1|RD_2|RD_3,		0,		L1,		0,	0 },
@@ -1817,14 +1897,14 @@ const struct mips_opcode mips_builtin_opcodes[] =
 /* ssnop is at the start of the table.  */
 {"standby",		"",		0x42000021, 0xffffffff,	0,			0,		V1,		0,	0 },
 {"sub",			"d,v,t",	0x00000022, 0xfc0007ff,	WR_1|RD_2|RD_3,		0,		I1,		0,	0 },
-{"sub",			"d,v,I",	0,    (int) M_SUB_I,	INSN_MACRO,		0,		I1,		0,	0 },
+{"sub",			"d,v,I",	0,    (int) M_SUB_I,	INSN_MACRO,		0,		I1,		0,	I34 },
 {"sub",			"D,S,T",	0x45c00001, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		IL2E,		0,	0 },
 {"sub",			"D,S,T",	0x4b40000d, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		IL2F|IL3A,	0,	0 },
 {"sub.d",		"D,V,T",	0x46200001, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I1,		0,	SF },
 {"sub.s",		"D,V,T",	0x46000001, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I1,		0,	0 },
 {"sub.ob",		"X,Y,Q",	0x7800000a, 0xfc20003f,	WR_1|RD_2|RD_3|FP_D,	0,		SB1,		MX,	0 },
 {"sub.ob",		"D,S,Q",	0x4800000a, 0xfc20003f,	WR_1|RD_2|RD_3|FP_D,	0,		N54,		0,	0 },
-{"sub.ps",		"D,V,T",	0x46c00001, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I5_33|IL2F,	0,	0 },
+{"sub.ps",		"D,V,T",	0x46c00001, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I5_33|IL2F,	0,	I34 },
 {"sub.ps",		"D,V,T",	0x45600001, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		IL2E,		0,	0 },
 {"sub.qh",		"X,Y,Q",	0x7820000a, 0xfc20003f,	WR_1|RD_2|RD_3|FP_D,	0,		0,		MX,	0 },
 {"suba.ob",		"Y,Q",		0x78000036, 0xfc2007ff,	RD_1|RD_2|FP_D,		WR_MACC,	SB1,		MX,	0 },
@@ -1837,33 +1917,34 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"subu",		"D,S,T",	0x45800001, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		IL2E,		0,	0 },
 {"subu",		"D,S,T",	0x4b00000d, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		IL2F|IL3A,	0,	0 },
 {"suspend",		"",		0x42000022, 0xffffffff,	0,			0,		V1,		0,	0 },
-{"suxc1",		"S,t(b)",	0x4c00000d, 0xfc0007ff, RD_1|RD_2|RD_3|SM|FP_D,	0,		I5_33|N55,	0,	0},
+{"suxc1",		"S,t(b)",	0x4c00000d, 0xfc0007ff, RD_1|RD_2|RD_3|SM|FP_D,	0,		I5_33|N55,	0,	I34},
 {"sw",			"t,o(b)",	0xac000000, 0xfc000000,	RD_1|RD_3|SM,		0,		I1,		0,	0 },
 {"sw",			"t,A(b)",	0,    (int) M_SW_AB,	INSN_MACRO,		0,		I1,		0,	0 },
 {"swapw",		"t,b",		0x70000014, 0xfc00ffff, MOD_1|RD_2|LM|SM,	0,		XLR,		0,	0 },
 {"swapwu",		"t,b",		0x70000015, 0xfc00ffff, MOD_1|RD_2|LM|SM,	0,		XLR,		0,	0 },
 {"swapd",		"t,b",		0x70000016, 0xfc00ffff, MOD_1|RD_2|LM|SM,	0,		XLR,		0,	0 },
-{"swc0",		"E,o(b)",	0xe0000000, 0xfc000000,	RD_3|RD_C0|SM,		0,		I1,		0,	IOCT|IOCTP|IOCT2 },
-{"swc0",		"E,A(b)",	0,    (int) M_SWC0_AB,	INSN_MACRO,		0,		I1,		0,	IOCT|IOCTP|IOCT2 },
+{"swc0",		"E,o(b)",	0xe0000000, 0xfc000000,	RD_3|RD_C0|SM,		0,		I1,		0,	IOCT|IOCTP|IOCT2|I34 },
+{"swc0",		"E,A(b)",	0,    (int) M_SWC0_AB,	INSN_MACRO,		0,		I1,		0,	IOCT|IOCTP|IOCT2|I34 },
 {"swc1",		"T,o(b)",	0xe4000000, 0xfc000000,	RD_1|RD_3|SM|FP_S,	0,		I1,		0,	0 },
 {"swc1",		"E,o(b)",	0xe4000000, 0xfc000000,	RD_1|RD_3|SM|FP_S,	0,		I1,		0,	0 },
 {"swc1",		"T,A(b)",	0,    (int) M_SWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
 {"swc1",		"E,A(b)",	0,    (int) M_SWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
 {"s.s",			"T,o(b)",	0xe4000000, 0xfc000000,	RD_1|RD_3|SM|FP_S,	0,		I1,		0,	0 }, /* swc1 */
 {"s.s",			"T,A(b)",	0,    (int) M_SWC1_AB,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	0 },
-{"swc2",		"E,o(b)",	0xe8000000, 0xfc000000,	RD_3|RD_C2|SM,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
-{"swc2",		"E,A(b)",	0,    (int) M_SWC2_AB,	INSN_MACRO,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
-{"swc3",		"E,o(b)",	0xec000000, 0xfc000000,	RD_3|RD_C3|SM,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
-{"swc3",		"E,A(b)",	0,    (int) M_SWC3_AB,	INSN_MACRO,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
-{"swl",			"t,o(b)",	0xa8000000, 0xfc000000,	RD_1|RD_3|SM,		0,		I1,		0,	0 },
-{"swl",			"t,A(b)",	0,    (int) M_SWL_AB,	INSN_MACRO,		0,		I1,		0,	0 },
-{"scache",		"t,o(b)",	0xa8000000, 0xfc000000,	RD_1|RD_3,		0,		I2,		0,	0 }, /* same */
-{"scache",		"t,A(b)",	0,    (int) M_SWL_AB,	INSN_MACRO,		0,		I2,		0,	0 }, /* as swl */
-{"swr",			"t,o(b)",	0xb8000000, 0xfc000000,	RD_1|RD_3|SM,		0,		I1,		0,	0 },
-{"swr",			"t,A(b)",	0,    (int) M_SWR_AB,	INSN_MACRO,		0,		I1,		0,	0 },
-{"invalidate",		"t,o(b)",	0xb8000000, 0xfc000000,	RD_1|RD_3,		0,		I2,		0,	0 }, /* same */
-{"invalidate",		"t,A(b)",	0,    (int) M_SWR_AB,	INSN_MACRO,		0,		I2,		0,	0 }, /* as swr */
-{"swxc1",		"S,t(b)",	0x4c000008, 0xfc0007ff, RD_1|RD_2|RD_3|SM|FP_S,	0,		I4_33,		0,	0 },
+{"swc2",		"E,+:(d)",	0x49600000, 0xffe00000,	RD_3|RD_C2|SM,		0,		I34,		0,	0 },
+{"swc2",		"E,o(b)",	0xe8000000, 0xfc000000,	RD_3|RD_C2|SM,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"swc2",		"E,A(b)",	0,    (int) M_SWC2_AB,	INSN_MACRO,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"swc3",		"E,o(b)",	0xec000000, 0xfc000000,	RD_3|RD_C3|SM,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"swc3",		"E,A(b)",	0,    (int) M_SWC3_AB,	INSN_MACRO,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"swl",			"t,o(b)",	0xa8000000, 0xfc000000,	RD_1|RD_3|SM,		0,		I1,		0,	I34 },
+{"swl",			"t,A(b)",	0,    (int) M_SWL_AB,	INSN_MACRO,		0,		I1,		0,	I34 },
+{"scache",		"t,o(b)",	0xa8000000, 0xfc000000,	RD_1|RD_3,		0,		I2,		0,	I34 }, /* same */
+{"scache",		"t,A(b)",	0,    (int) M_SWL_AB,	INSN_MACRO,		0,		I2,		0,	I34 }, /* as swl */
+{"swr",			"t,o(b)",	0xb8000000, 0xfc000000,	RD_1|RD_3|SM,		0,		I1,		0,	I34 },
+{"swr",			"t,A(b)",	0,    (int) M_SWR_AB,	INSN_MACRO,		0,		I1,		0,	I34 },
+{"invalidate",		"t,o(b)",	0xb8000000, 0xfc000000,	RD_1|RD_3,		0,		I2,		0,	I34 }, /* same */
+{"invalidate",		"t,A(b)",	0,    (int) M_SWR_AB,	INSN_MACRO,		0,		I2,		0,	I34 }, /* as swr */
+{"swxc1",		"S,t(b)",	0x4c000008, 0xfc0007ff, RD_1|RD_2|RD_3|SM|FP_S,	0,		I4_33,		0,	I34 },
 {"synciobdma",		"",		0x0000008f, 0xffffffff,	NODS,			0,		IOCT,		0,	0 },
 {"syncs",		"",		0x0000018f, 0xffffffff,	NODS,			0,		IOCT,		0,	0 },
 {"syncw",		"",		0x0000010f, 0xffffffff,	NODS,			0,		IOCT,		0,	0 },
@@ -1880,20 +1961,20 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"synci",		"o(b)",		0x041f0000, 0xfc1f0000,	RD_2|SM,		0,		I33,		0,	0 },
 {"syscall",		"",		0x0000000c, 0xffffffff,	TRAP,			0,		I1,		0,	0 },
 {"syscall",		"B",		0x0000000c, 0xfc00003f,	TRAP,			0,		I1,		0,	0 },
-{"teqi",		"s,j",		0x040c0000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	0 },
+{"teqi",		"s,j",		0x040c0000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	I34 },
 {"teq",			"s,t",		0x00000034, 0xfc00ffff, RD_1|RD_2|TRAP,		0,		I2,		0,	0 },
 {"teq",			"s,t,q",	0x00000034, 0xfc00003f, RD_1|RD_2|TRAP,		0,		I2,		0,	0 },
-{"teq",			"s,j",		0x040c0000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	0 }, /* teqi */
+{"teq",			"s,j",		0x040c0000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	I34 }, /* teqi */
 {"teq",			"s,I",		0,    (int) M_TEQ_I,	INSN_MACRO,		0,		I2,		0,	0 },
-{"tgei",		"s,j",		0x04080000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	0 },
+{"tgei",		"s,j",		0x04080000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	I34 },
 {"tge",			"s,t",		0x00000030, 0xfc00ffff,	RD_1|RD_2|TRAP,		0,		I2,		0,	0 },
 {"tge",			"s,t,q",	0x00000030, 0xfc00003f,	RD_1|RD_2|TRAP,		0,		I2,		0,	0 },
-{"tge",			"s,j",		0x04080000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	0 }, /* tgei */
+{"tge",			"s,j",		0x04080000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	I34 }, /* tgei */
 {"tge",			"s,I",		0,    (int) M_TGE_I,    INSN_MACRO,		0,		I2,		0,	0 },
-{"tgeiu",		"s,j",		0x04090000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	0 },
+{"tgeiu",		"s,j",		0x04090000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	I34 },
 {"tgeu",		"s,t",		0x00000031, 0xfc00ffff, RD_1|RD_2|TRAP,		0,		I2,		0,	0 },
 {"tgeu",		"s,t,q",	0x00000031, 0xfc00003f, RD_1|RD_2|TRAP,		0,		I2,		0,	0 },
-{"tgeu",		"s,j",		0x04090000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	0 }, /* tgeiu */
+{"tgeu",		"s,j",		0x04090000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	I34 }, /* tgeiu */
 {"tgeu",		"s,I",		0,    (int) M_TGEU_I,	INSN_MACRO,		0,		I2,		0,	0 },
 {"tlbinv",		"",		0x42000003, 0xffffffff, INSN_TLB,       	0,		0,		TLBINV,	0 },
 {"tlbinvf",		"",		0x42000004, 0xffffffff, INSN_TLB,       	0,		0,		TLBINV,	0 },
@@ -1907,20 +1988,20 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"tlbginvf",		"",		0x4200000c, 0xffffffff, INSN_TLB,       	0,		0,		IVIRT,	0 },
 {"tlbgwr",		"",		0x4200000e, 0xffffffff, INSN_TLB,       	0,		0,		IVIRT,	0 },
 {"tlbgp",		"",		0x42000010, 0xffffffff, INSN_TLB,       	0,		0,		IVIRT,	0 },
-{"tlti",		"s,j",		0x040a0000, 0xfc1f0000,	RD_1|TRAP,		0,		I2,		0,	0 },
+{"tlti",		"s,j",		0x040a0000, 0xfc1f0000,	RD_1|TRAP,		0,		I2,		0,	I34 },
 {"tlt",			"s,t",		0x00000032, 0xfc00ffff, RD_1|RD_2|TRAP,		0,		I2,		0,	0 },
 {"tlt",			"s,t,q",	0x00000032, 0xfc00003f, RD_1|RD_2|TRAP,		0,		I2,		0,	0 },
-{"tlt",			"s,j",		0x040a0000, 0xfc1f0000,	RD_1|TRAP,		0,		I2,		0,	0 }, /* tlti */
+{"tlt",			"s,j",		0x040a0000, 0xfc1f0000,	RD_1|TRAP,		0,		I2,		0,	I34 }, /* tlti */
 {"tlt",			"s,I",		0,    (int) M_TLT_I,	INSN_MACRO,		0,		I2,		0,	0 },
-{"tltiu",		"s,j",		0x040b0000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	0 },
+{"tltiu",		"s,j",		0x040b0000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	I34 },
 {"tltu",		"s,t",		0x00000033, 0xfc00ffff, RD_1|RD_2|TRAP,		0,		I2,		0,	0 },
 {"tltu",		"s,t,q",	0x00000033, 0xfc00003f, RD_1|RD_2|TRAP,		0,		I2,		0,	0 },
-{"tltu",		"s,j",		0x040b0000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	0 }, /* tltiu */
+{"tltu",		"s,j",		0x040b0000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	I34 }, /* tltiu */
 {"tltu",		"s,I",		0,    (int) M_TLTU_I,	INSN_MACRO,		0,		I2,		0,	0 },
-{"tnei",		"s,j",		0x040e0000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	0 },
+{"tnei",		"s,j",		0x040e0000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	I34 },
 {"tne",			"s,t",		0x00000036, 0xfc00ffff, RD_1|RD_2|TRAP,		0,		I2,		0,	0 },
 {"tne",			"s,t,q",	0x00000036, 0xfc00003f, RD_1|RD_2|TRAP,		0,		I2,		0,	0 },
-{"tne",			"s,j",		0x040e0000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	0 }, /* tnei */
+{"tne",			"s,j",		0x040e0000, 0xfc1f0000, RD_1|TRAP,		0,		I2,		0,	I34 }, /* tnei */
 {"tne",			"s,I",		0,    (int) M_TNE_I,	INSN_MACRO,		0,		I2,		0,	0 },
 {"trunc.l.d",		"D,S",		0x46200009, 0xffff003f, WR_1|RD_2|FP_D,		0,		I3_33,		0,	0 },
 {"trunc.l.s",		"D,S",		0x46000009, 0xffff003f,	WR_1|RD_2|FP_S|FP_D,	0,		I3_33,		0,	0 },
@@ -1931,13 +2012,13 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"trunc.w.s",		"D,S",		0x4600000d, 0xffff003f,	WR_1|RD_2|FP_S,		0,		I2,		0,	EE },
 {"trunc.w.s",		"D,S,x",	0x4600000d, 0xffff003f,	WR_1|RD_2|FP_S,		0,		I2,		0,	EE },
 {"trunc.w.s",		"D,S,t",	0,    (int) M_TRUNCWS,	INSN_MACRO,		INSN2_M_FP_S,	I1,		0,	EE },
-{"uld",			"t,A(b)",	0,    (int) M_ULD_AB,	INSN_MACRO,		0,		I3,		0,	0 },
-{"ulh",			"t,A(b)",	0,    (int) M_ULH_AB,	INSN_MACRO,		0,		I1,		0,	0 },
-{"ulhu",		"t,A(b)",	0,    (int) M_ULHU_AB,	INSN_MACRO,		0,		I1,		0,	0 },
-{"ulw",			"t,A(b)",	0,    (int) M_ULW_AB,	INSN_MACRO,		0,		I1,		0,	0 },
-{"usd",			"t,A(b)",	0,    (int) M_USD_AB,	INSN_MACRO,		0,		I3,		0,	0 },
-{"ush",			"t,A(b)",	0,    (int) M_USH_AB,	INSN_MACRO,		0,		I1,		0,	0 },
-{"usw",			"t,A(b)",	0,    (int) M_USW_AB,	INSN_MACRO,		0,		I1,		0,	0 },
+{"uld",			"t,A(b)",	0,    (int) M_ULD_AB,	INSN_MACRO,		0,		I3,		0,	I66 },
+{"ulh",			"t,A(b)",	0,    (int) M_ULH_AB,	INSN_MACRO,		0,		I1,		0,	I34 },
+{"ulhu",		"t,A(b)",	0,    (int) M_ULHU_AB,	INSN_MACRO,		0,		I1,		0,	I34 },
+{"ulw",			"t,A(b)",	0,    (int) M_ULW_AB,	INSN_MACRO,		0,		I1,		0,	I34 },
+{"usd",			"t,A(b)",	0,    (int) M_USD_AB,	INSN_MACRO,		0,		I3,		0,	I66 },
+{"ush",			"t,A(b)",	0,    (int) M_USH_AB,	INSN_MACRO,		0,		I1,		0,	I34 },
+{"usw",			"t,A(b)",	0,    (int) M_USW_AB,	INSN_MACRO,		0,		I1,		0,	I34 },
 {"v3mulu",		"d,v,t",	0x70000011, 0xfc0007ff, WR_1|RD_2|RD_3,		0,		IOCT,		0,	0 },
 {"vmm0",		"d,v,t",	0x70000010, 0xfc0007ff, WR_1|RD_2|RD_3,		0,		IOCT,		0,	0 },
 {"vmulu",		"d,v,t",	0x7000000f, 0xfc0007ff, WR_1|RD_2|RD_3,		0,		IOCT,		0,	0 },
@@ -1973,14 +2054,16 @@ const struct mips_opcode mips_builtin_opcodes[] =
 
 /* 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,	RD_CC|CBD,		0,		I1,		0,	IOCT|IOCTP|IOCT2 },
-{"bc2f",		"N,p",		0x49000000, 0xffe30000,	RD_CC|CBD,		0,		I32,		0,	IOCT|IOCTP|IOCT2 },
-{"bc2fl",		"p",		0x49020000, 0xffff0000,	RD_CC|CBL,		0,		I2|T3,		0,	IOCT|IOCTP|IOCT2 },
-{"bc2fl",		"N,p",		0x49020000, 0xffe30000,	RD_CC|CBL,		0,		I32,		0,	IOCT|IOCTP|IOCT2 },
-{"bc2t",		"p",		0x49010000, 0xffff0000,	RD_CC|CBD,		0,		I1,		0,	IOCT|IOCTP|IOCT2 },
-{"bc2t",		"N,p",		0x49010000, 0xffe30000,	RD_CC|CBD,		0,		I32,		0,	IOCT|IOCTP|IOCT2 },
-{"bc2tl",		"p",		0x49030000, 0xffff0000,	RD_CC|CBL,		0,		I2|T3,		0,	IOCT|IOCTP|IOCT2 },
-{"bc2tl",		"N,p",		0x49030000, 0xffe30000,	RD_CC|CBL,		0,		I32,		0,	IOCT|IOCTP|IOCT2 },
+{"bc2eqz",		"E,p",		0x49200000, 0xffe00000, RD_C2|CBD,		0,		I34,		0,	0 },
+{"bc2f",		"p",		0x49000000, 0xffff0000,	RD_CC|CBD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|I34 },
+{"bc2f",		"N,p",		0x49000000, 0xffe30000,	RD_CC|CBD,		0,		I32,		0,	IOCT|IOCTP|IOCT2|I34 },
+{"bc2fl",		"p",		0x49020000, 0xffff0000,	RD_CC|CBL,		0,		I2|T3,		0,	IOCT|IOCTP|IOCT2|I34 },
+{"bc2fl",		"N,p",		0x49020000, 0xffe30000,	RD_CC|CBL,		0,		I32,		0,	IOCT|IOCTP|IOCT2|I34 },
+{"bc2nez",		"E,p",		0x49a00000, 0xffe00000, RD_C2|CBD,		0,		I34,		0,	0 },
+{"bc2t",		"p",		0x49010000, 0xffff0000,	RD_CC|CBD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|I34 },
+{"bc2t",		"N,p",		0x49010000, 0xffe30000,	RD_CC|CBD,		0,		I32,		0,	IOCT|IOCTP|IOCT2|I34 },
+{"bc2tl",		"p",		0x49030000, 0xffff0000,	RD_CC|CBL,		0,		I2|T3,		0,	IOCT|IOCTP|IOCT2|I34 },
+{"bc2tl",		"N,p",		0x49030000, 0xffe30000,	RD_CC|CBL,		0,		I32,		0,	IOCT|IOCTP|IOCT2|I34 },
 {"cfc2",		"t,G",		0x48400000, 0xffe007ff,	WR_1|RD_C2|LCD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
 {"cfc2",		"t,+9",		0x48400000, 0xffe007ff,	WR_1|RD_C2|LCD,		0,		EE,		0,	0 },
 {"cfc2.i",		"t,+9",		0x48400001, 0xffe007ff, WR_1|RD_C2|LCD,		0,		EE,		0,	0 },
@@ -2013,18 +2096,18 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"qmtc2.ni",		"t,+6",		0x48a00000, 0xffe007ff,	RD_1|WR_C2,		0,		EE,		0,	0 },
 /* 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,	RD_CC|CBD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
-{"bc3fl",		"p",		0x4d020000, 0xffff0000,	RD_CC|CBL,		0,		I2|T3,		0,	IOCT|IOCTP|IOCT2|EE },
-{"bc3t",		"p",		0x4d010000, 0xffff0000,	RD_CC|CBD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
-{"bc3tl",		"p",		0x4d030000, 0xffff0000,	RD_CC|CBL,		0,		I2|T3,		0,	IOCT|IOCTP|IOCT2|EE },
-{"cfc3",		"t,G",		0x4c400000, 0xffe007ff,	WR_1|RD_C3|LCD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
-{"ctc3",		"t,G",		0x4cc00000, 0xffe007ff,	RD_1|WR_CC|COD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
-{"dmfc3",		"t,G",		0x4c200000, 0xffe007ff,	WR_1|RD_C3|LCD,		0,		I3,		0,	IOCT|IOCTP|IOCT2|EE },
-{"dmtc3",		"t,G",		0x4ca00000, 0xffe007ff,	RD_1|WR_C3|WR_CC|COD,	0,		I3,		0,	IOCT|IOCTP|IOCT2|EE },
-{"mfc3",		"t,G",		0x4c000000, 0xffe007ff,	WR_1|RD_C3|LCD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
-{"mfc3",		"t,G,H",	0x4c000000, 0xffe007f8,	WR_1|RD_C3|LCD,		0,		I32,		0,	IOCT|IOCTP|IOCT2|EE },
-{"mtc3",		"t,G",		0x4c800000, 0xffe007ff,	RD_1|WR_C3|WR_CC|COD,	0,		I1,		0,	IOCT|IOCTP|IOCT2|EE },
-{"mtc3",		"t,G,H",	0x4c800000, 0xffe007f8,	RD_1|WR_C3|WR_CC|COD,	0,		I32,		0,	IOCT|IOCTP|IOCT2|EE },
+{"bc3f",		"p",		0x4d000000, 0xffff0000,	RD_CC|CBD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"bc3fl",		"p",		0x4d020000, 0xffff0000,	RD_CC|CBL,		0,		I2|T3,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"bc3t",		"p",		0x4d010000, 0xffff0000,	RD_CC|CBD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"bc3tl",		"p",		0x4d030000, 0xffff0000,	RD_CC|CBL,		0,		I2|T3,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"cfc3",		"t,G",		0x4c400000, 0xffe007ff,	WR_1|RD_C3|LCD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"ctc3",		"t,G",		0x4cc00000, 0xffe007ff,	RD_1|WR_CC|COD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"dmfc3",		"t,G",		0x4c200000, 0xffe007ff,	WR_1|RD_C3|LCD,		0,		I3,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"dmtc3",		"t,G",		0x4ca00000, 0xffe007ff,	RD_1|WR_C3|WR_CC|COD,	0,		I3,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"mfc3",		"t,G",		0x4c000000, 0xffe007ff,	WR_1|RD_C3|LCD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"mfc3",		"t,G,H",	0x4c000000, 0xffe007f8,	WR_1|RD_C3|LCD,		0,		I32,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"mtc3",		"t,G",		0x4c800000, 0xffe007ff,	RD_1|WR_C3|WR_CC|COD,	0,		I1,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
+{"mtc3",		"t,G,H",	0x4c800000, 0xffe007f8,	RD_1|WR_C3|WR_CC|COD,	0,		I32,		0,	IOCT|IOCTP|IOCT2|EE|I34 },
 
   /* Conflicts with the 4650's "mul" instruction.  Nobody's using the
      4010 any more, so move this insn out of the way.  If the object
@@ -2311,10 +2394,10 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"dpsqx_s.w.ph",	"7,s,t",	0x7c000670, 0xfc00e7ff, RD_2|RD_3|MOD_a,	0,              0,		D33,	0 },
 {"dpsqx_sa.w.ph",	"7,s,t",	0x7c0006f0, 0xfc00e7ff, RD_2|RD_3|MOD_a,	0,              0,		D33,	0 },
 /* Move bc0* after mftr and mttr to avoid opcode collision.  */
-{"bc0f",		"p",		0x41000000, 0xffff0000,	RD_CC|CBD,		0,		I1,		0,	IOCT|IOCTP|IOCT2 },
-{"bc0fl",		"p",		0x41020000, 0xffff0000,	RD_CC|CBL,		0,		I2|T3,		0,	IOCT|IOCTP|IOCT2 },
-{"bc0t",		"p",		0x41010000, 0xffff0000,	RD_CC|CBD,		0,		I1,		0,	IOCT|IOCTP|IOCT2 },
-{"bc0tl",		"p",		0x41030000, 0xffff0000,	RD_CC|CBL,		0,		I2|T3,		0,	IOCT|IOCTP|IOCT2 },
+{"bc0f",		"p",		0x41000000, 0xffff0000,	RD_CC|CBD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|I34 },
+{"bc0fl",		"p",		0x41020000, 0xffff0000,	RD_CC|CBL,		0,		I2|T3,		0,	IOCT|IOCTP|IOCT2|I34 },
+{"bc0t",		"p",		0x41010000, 0xffff0000,	RD_CC|CBD,		0,		I1,		0,	IOCT|IOCTP|IOCT2|I34 },
+{"bc0tl",		"p",		0x41030000, 0xffff0000,	RD_CC|CBL,		0,		I2|T3,		0,	IOCT|IOCTP|IOCT2|I34 },
 /* ST Microelectronics Loongson-2E and -2F.  */
 {"mult.g",		"d,s,t",	0x7c000018, 0xfc0007ff,	WR_1|RD_2|RD_3,		0,		IL2E,		0,	0 },
 {"mult.g",		"d,s,t",	0x70000010, 0xfc0007ff,	WR_1|RD_2|RD_3,		0,		IL2F,		0,	0 },
@@ -2499,10 +2582,10 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"lle",			"t,A(b)",	0,    (int) M_LLE_AB,	INSN_MACRO,		0,		0,		EVA,	0 },
 {"lwe",			"t,+j(b)",	0x7c00002f, 0xfc00007f, WR_1|RD_3|LM,		0,		0,		EVA,	0 },
 {"lwe",			"t,A(b)",	0,    (int) M_LWE_AB,	INSN_MACRO,		0,		0,		EVA,	0 },
-{"lwle",		"t,+j(b)",	0x7c000019, 0xfc00007f, WR_1|RD_3|LM,		0,		0,		EVA,	0 },
-{"lwle",		"t,A(b)",	0,    (int) M_LWLE_AB,	INSN_MACRO,		0,		0,		EVA,	0 },
-{"lwre",		"t,+j(b)",	0x7c00001a, 0xfc00007f, WR_1|RD_3|LM,		0,		0,		EVA,	0 },
-{"lwre",		"t,A(b)",	0,    (int) M_LWRE_AB,	INSN_MACRO,		0,		0,		EVA,	0 },
+{"lwle",		"t,+j(b)",	0x7c000019, 0xfc00007f, WR_1|RD_3|LM,		0,		0,		EVA,	I34 },
+{"lwle",		"t,A(b)",	0,    (int) M_LWLE_AB,	INSN_MACRO,		0,		0,		EVA,	I34 },
+{"lwre",		"t,+j(b)",	0x7c00001a, 0xfc00007f, WR_1|RD_3|LM,		0,		0,		EVA,	I34 },
+{"lwre",		"t,A(b)",	0,    (int) M_LWRE_AB,	INSN_MACRO,		0,		0,		EVA,	I34 },
 {"sbe",			"t,+j(b)",	0x7c00001c, 0xfc00007f, RD_1|RD_3|SM,		0,		0,		EVA,	0 },
 {"sbe",			"t,A(b)",	0,    (int) M_SBE_AB,	INSN_MACRO,		0,		0,		EVA,	0 },
 {"sce",			"t,+j(b)",	0x7c00001e, 0xfc00007f, MOD_1|RD_3|SM,		0,		0,		EVA,	0 },
@@ -2511,10 +2594,10 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"she",			"t,A(b)",	0,    (int) M_SHE_AB,	INSN_MACRO,		0,		0,		EVA,	0 },
 {"swe",			"t,+j(b)",	0x7c00001f, 0xfc00007f, RD_1|RD_3|SM,		0,		0,		EVA,	0 },
 {"swe",			"t,A(b)",	0,    (int) M_SWE_AB,	INSN_MACRO,		0,		0,		EVA,	0 },
-{"swle",		"t,+j(b)",	0x7c000021, 0xfc00007f, RD_1|RD_3|SM,		0,		0,		EVA,	0 },
-{"swle",		"t,A(b)",	0,    (int) M_SWLE_AB,	INSN_MACRO,		0,		0,		EVA,	0 },
-{"swre",		"t,+j(b)",	0x7c000022, 0xfc00007f, RD_1|RD_3|SM,		0,		0,		EVA,	0 },
-{"swre",		"t,A(b)",	0,    (int) M_SWRE_AB,	INSN_MACRO,		0,		0,		EVA,	0 },
+{"swle",		"t,+j(b)",	0x7c000021, 0xfc00007f, RD_1|RD_3|SM,		0,		0,		EVA,	I34 },
+{"swle",		"t,A(b)",	0,    (int) M_SWLE_AB,	INSN_MACRO,		0,		0,		EVA,	I34 },
+{"swre",		"t,+j(b)",	0x7c000022, 0xfc00007f, RD_1|RD_3|SM,		0,		0,		EVA,	I34 },
+{"swre",		"t,A(b)",	0,    (int) M_SWRE_AB,	INSN_MACRO,		0,		0,		EVA,	I34 },
 {"cachee",		"k,+j(b)",	0x7c00001b, 0xfc00007f, RD_3,			0,		0,		EVA,	0 },
 {"cachee",		"k,A(b)",	0,    (int) M_CACHEE_AB,INSN_MACRO,		0,		0,		EVA,	0 },
 {"prefe",		"k,+j(b)",	0x7c000023, 0xfc00007f, RD_3|LM,		0,		0,		EVA,	0 },
@@ -3050,8 +3133,6 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"ctcmsa",		"+l,d",		0x783e0019, 0xffff003f,	RD_2|COD,		0,		0,		MSA,	0 },
 {"cfcmsa",		"+k,+n",	0x787e0019, 0xffff003f,	WR_1|COD,		0,		0,		MSA,	0 },
 {"move.v",		"+d,+e",	0x78be0019, 0xffff003f,	WR_1|RD_2,		0,		0,		MSA,	0 },
-{"lsa",			"d,v,t,+~",	0x00000005, 0xfc00073f,	WR_1|RD_2|RD_3,		0,		0,		MSA,	0 },
-{"dlsa",		"d,v,t,+~",	0x00000015, 0xfc00073f,	WR_1|RD_2|RD_3,		0,		0,		MSA64,	0 },
 
 /* User Defined Instruction.  */
 {"udi0",		"s,t,d,+1",	0x70000010, 0xfc00003f,	UDI,			0,		I33,		0,	0 },
@@ -3118,6 +3199,124 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"udi15",		"s,t,+2",	0x7000001f, 0xfc00003f,	UDI,			0,		I33,		0,	0 },
 {"udi15",		"s,+3",		0x7000001f, 0xfc00003f,	UDI,			0,		I33,		0,	0 },
 {"udi15",		"+4",		0x7000001f, 0xfc00003f,	UDI,			0,		I33,		0,	0 },
+{"lsa",			"d,v,t,+~",	0x00000005, 0xfc00073f,	WR_1|RD_2|RD_3,		0,		I34,		MSA,	0 },
+{"dlsa",		"d,v,t,+~",	0x00000015, 0xfc00073f,	WR_1|RD_2|RD_3,		0,		I66,		MSA64,	0 },
+/* MIPS r6.  */
+
+{"aui",			"t,s,u",	0x3c000000, 0xfc000000,	WR_1|RD_2,		0,		I34,		0,	0 },
+{"auipc",		"s,u",		0xec1e0000, 0xfc1f0000, WR_1|RD_pc,		0,		I34,		0,	0 },
+{"daui",		"t,s,u",	0x74000000, 0xfc000000,	WR_1|RD_2,		0,		I34,		0,	0 },
+{"dahi",		"s,-d,u",	0x04060000, 0xfc1f0000,	MOD_1,			0,		I66,		0,	0 },
+{"dati",		"s,-d,u",	0x041e0000, 0xfc1f0000,	MOD_1,			0,		I66,		0,	0 },
+
+{"align",		"d,s,t,+I",	0x7c000220, 0xfc00073f,	WR_1|RD_2|RD_3,		0,		I34,		0,	0 },
+{"dalign",		"d,s,t,+O",	0x7c000224, 0xfc00063f,	WR_1|RD_2|RD_3,		0,		I66,		0,	0 },
+{"bitswap",		"d,t",		0x7c000020, 0xffe007ff,	WR_1|RD_2,		0,		I34,		0,	0 },
+{"dbitswap",		"d,t",		0x7c000024, 0xffe007ff,	WR_1|RD_2,		0,		I66,		0,	0 },
+
+{"bovc",		"s,-w,p",	0x20000000, 0xfc000000,	RD_1|RD_2|NODS,		FS,		I34,		0,	0 },
+{"bovc",		"t,-x,p",	0x20000000, 0xfc000000,	RD_1|RD_2|NODS,		FS|INSN2_ALIAS,	I34,		0,	0 },
+{"beqzalc",		"-t,p",		0x20000000, 0xffe00000,	RD_1|WR_31|NODS,	FS,		I34,		0,	0 },
+{"beqc",		"-s,-u,p",	0x20000000, 0xfc000000,	RD_1|RD_2|NODS,		FS,		I34,		0,	0 },
+{"beqc",		"t,-y,p",	0x20000000, 0xfc000000,	RD_1|RD_2|NODS,		FS|INSN2_ALIAS,	I34,		0,	0 },
+{"bnvc",		"s,-w,p",	0x60000000, 0xfc000000,	RD_1|RD_2|NODS,		FS,		I34,		0,	0 },
+{"bnvc",		"t,-x,p",	0x60000000, 0xfc000000,	RD_1|RD_2|NODS,		FS|INSN2_ALIAS,	I34,		0,	0 },
+{"bnezalc",		"-t,p",		0x60000000, 0xffe00000,	RD_1|WR_31|NODS,	FS,		I34,		0,	0 },
+{"bnec",		"-s,-u,p",	0x60000000, 0xfc000000,	RD_1|RD_2|NODS,		FS,		I34,		0,	0 },
+{"bnec",		"t,-y,p",	0x60000000, 0xfc000000,	RD_1|RD_2|NODS,		FS|INSN2_ALIAS,	I34,		0,	0 },
+
+{"blezc",		"-t,p",		0x58000000, 0xffe00000,	RD_1|NODS,		FS,		I34,		0,	0 },
+{"bgezc",		"+;,p",		0x58000000, 0xfc000000,	RD_1|NODS,		FS,		I34,		0,	0 },
+{"bgec",		"-s,-v,p",	0x58000000, 0xfc000000,	RD_1|RD_2|NODS,		FS,		I34,		0,	0 },
+{"bgtzc",		"-t,p",		0x5c000000, 0xffe00000,	RD_1|NODS,		FS,		I34,		0,	0 },
+{"bltzc",		"+;,p",		0x5c000000, 0xfc000000,	RD_1|NODS,		FS,		I34,		0,	0 },
+{"bltc",		"-s,-v,p",	0x5c000000, 0xfc000000,	RD_1|RD_2|NODS,		FS,		I34,		0,	0 },
+{"blezalc",		"-t,p",		0x18000000, 0xffe00000,	RD_1|WR_31|NODS,	FS,		I34,		0,	0 },
+{"bgezalc",		"+;,p",		0x18000000, 0xfc000000,	RD_1|WR_31|NODS,	FS,		I34,		0,	0 },
+{"bgeuc",		"-s,-v,p",	0x18000000, 0xfc000000,	RD_1|RD_2|NODS,		FS,		I34,		0,	0 },
+{"bgtzalc",		"-t,p",		0x1c000000, 0xffe00000,	RD_1|WR_31|NODS,	FS,		I34,		0,	0 },
+{"bltzalc",		"+;,p",		0x1c000000, 0xfc000000,	RD_1|WR_31|NODS,	FS,		I34,		0,	0 },
+{"bltuc",		"-s,-v,p",	0x1c000000, 0xfc000000,	RD_1|RD_2|NODS,		FS,		I34,		0,	0 },
+
+{"beqzc",		"-s,+\"",	0xd8000000, 0xfc000000,	RD_1|NODS,		FS,		I34,		0,	0 },
+{"jrc",			"t",		0xd8000000, 0xffe0ffff,	RD_1|NODS,		INSN2_ALIAS,	I34,		0,	0 },
+{"jic",			"t,j",		0xd8000000, 0xffe00000,	RD_1|NODS,		0,		I34,		0,	0 },
+
+{"bnezc",		"-s,+\"",	0xf8000000, 0xfc000000,	RD_1|NODS,		FS,		I34,		0,	0 },
+{"jialc",		"t,j",		0xf8000000, 0xffe00000,	RD_1|NODS,		0,		I34,		0,	0 },
+
+{"cmp.af.s",		"D,S,T",	0x46800000, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.af.d",		"D,S,T",	0x46a00000, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.eq.s",		"D,S,T",	0x46800002, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.eq.d",		"D,S,T",	0x46a00002, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.le.s",		"D,S,T",	0x46800006, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.le.d",		"D,S,T",	0x46a00006, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.lt.s",		"D,S,T",	0x46800004, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.lt.d",		"D,S,T",	0x46a00004, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.ne.s",		"D,S,T",	0x46800013, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.ne.d",		"D,S,T",	0x46a00013, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.or.s",		"D,S,T",	0x46800011, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.or.d",		"D,S,T",	0x46a00011, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.ueq.s",		"D,S,T",	0x46800003, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.ueq.d",		"D,S,T",	0x46a00003, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.ule.s",		"D,S,T",	0x46800007, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.ule.d",		"D,S,T",	0x46a00007, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.ult.s",		"D,S,T",	0x46800005, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.ult.d",		"D,S,T",	0x46a00005, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.un.s",		"D,S,T",	0x46800001, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.un.d",		"D,S,T",	0x46a00001, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.une.s",		"D,S,T",	0x46800012, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.une.d",		"D,S,T",	0x46a00012, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.saf.s",		"D,S,T",	0x46800008, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.saf.d",		"D,S,T",	0x46a00008, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.seq.s",		"D,S,T",	0x4680000a, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.seq.d",		"D,S,T",	0x46a0000a, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.sle.s",		"D,S,T",	0x4680000e, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.sle.d",		"D,S,T",	0x46a0000e, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.slt.s",		"D,S,T",	0x4680000c, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.slt.d",		"D,S,T",	0x46a0000c, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.sne.s",		"D,S,T",	0x4680001b, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.sne.d",		"D,S,T",	0x46a0001b, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.sor.s",		"D,S,T",	0x46800019, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.sor.d",		"D,S,T",	0x46a00019, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.sueq.s",		"D,S,T",	0x4680000b, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.sueq.d",		"D,S,T",	0x46a0000b, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.sule.s",		"D,S,T",	0x4680000f, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.sule.d",		"D,S,T",	0x46a0000f, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.sult.s",		"D,S,T",	0x4680000d, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.sult.d",		"D,S,T",	0x46a0000d, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"cmp.sun.s",		"D,S,T",	0x46800009, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.sun.d",		"D,S,T",	0x46a00009, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.sune.s",		"D,S,T",	0x4680001a, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"cmp.sune.d",		"D,S,T",	0x46a0001a, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+
+{"maddf.s",		"D,S,T",	0x46000018, 0xffe0003f,	MOD_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"msubf.s",		"D,S,T",	0x46000019, 0xffe0003f,	MOD_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"maddf.d",		"D,S,T",	0x46200018, 0xffe0003f,	MOD_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"msubf.d",		"D,S,T",	0x46200019, 0xffe0003f,	MOD_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+
+{"rint.s",		"D,S",		0x4600001a, 0xffff003f,	WR_1|RD_2|FP_S,		0,		I34,		0,	0 },
+{"rint.d",		"D,S",		0x4620001a, 0xffff003f,	WR_1|RD_2|FP_D,		0,		I34,		0,	0 },
+{"class.s",		"D,S",		0x4600001b, 0xffff003f,	WR_1|RD_2|FP_S,		0,		I34,		0,	0 },
+{"class.d",		"D,S",		0x4620001b, 0xffff003f,	WR_1|RD_2|FP_D,		0,		I34,		0,	0 },
+{"min.d",		"D,S,T",	0x4620001c, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"max.d",		"D,S,T",	0x4620001e, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"mina.s",		"D,S,T",	0x4600001d, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"mina.d",		"D,S,T",	0x4620001d, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"maxa.s",		"D,S,T",	0x4600001f, 0xffe0003f,	WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"maxa.d",		"D,S,T",	0x4620001f, 0xffe0003f,	WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+
+{"sel.s",		"D,S,T",	0x46000010, 0xffe0003f, MOD_1|RD_2|RD_3|FP_S,   0,		I34,		0,	0 },
+{"sel.d",		"D,S,T",	0x46200010, 0xffe0003f, MOD_1|RD_2|RD_3|FP_D,   0,		I34,		0,	0 },
+{"selnez",		"d,s,t",	0x00000037, 0xfc0007ff, WR_1|RD_2|RD_3, 	0,		I34,		0,	0 },
+{"selnez.s",		"D,S,T",	0x46000017, 0xffe0003f, WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"selnez.d",		"D,S,T",	0x46200017, 0xffe0003f, WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+{"seleqz",		"d,s,t",	0x00000035, 0xfc0007ff, WR_1|RD_2|RD_3, 	0,		I34,		0,	0 },
+{"seleqz.s",		"D,S,T",	0x46000014, 0xffe0003f, WR_1|RD_2|RD_3|FP_S,	0,		I34,		0,	0 },
+{"seleqz.d",		"D,S,T",	0x46200014, 0xffe0003f, WR_1|RD_2|RD_3|FP_D,	0,		I34,		0,	0 },
+
+{"aluipc",		"s,u",		0xec1f0000, 0xfc1f0000, WR_1|RD_pc,		0,		I34,		0,	0 },
+
 /* No hazard protection on coprocessor instructions--they shouldn't
    change the state of the processor and if they do it's up to the
    user to put in nops as necessary.  These are at the end so that the
-- 
1.7.1

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Add support for MIPS64r6
  2014-04-29 19:17 [PATCH] Add support for MIPS64r6 Andrew Bennett
@ 2014-04-29 19:33 ` Andreas Schwab
  2014-04-30 12:23   ` Andrew Bennett
  2014-05-07 17:52 ` Richard Sandiford
  1 sibling, 1 reply; 14+ messages in thread
From: Andreas Schwab @ 2014-04-29 19:33 UTC (permalink / raw)
  To: Andrew Bennett
  Cc: binutils, Rich Fuhler, Matthew Fortune, rdsandiford, Saeed Ghazanfar

Andrew Bennett <Andrew.Bennett@imgtec.com> writes:

>  	* config.sub: Add support for mips32r6 and mips64r6.

This needs to be sent upstream first, which is <config-patches@gnu.org>.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [PATCH] Add support for MIPS64r6
  2014-04-29 19:33 ` Andreas Schwab
@ 2014-04-30 12:23   ` Andrew Bennett
  2014-05-01 10:05     ` Andrew Bennett
  0 siblings, 1 reply; 14+ messages in thread
From: Andrew Bennett @ 2014-04-30 12:23 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: binutils, Rich Fuhler, Matthew Fortune, rdsandiford, Saeed Ghazanfar

> From: Andreas Schwab [mailto:schwab@linux-m68k.org] 
> Andrew Bennett <Andrew.Bennett@imgtec.com> writes:
>>
>>  	* config.sub: Add support for mips32r6 and mips64r6.
>>
> This needs to be sent upstream first, which is <config-patches@gnu.org>.

I have sent this section of the patch to config-patches.  

Regards,


Andrew

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [PATCH] Add support for MIPS64r6
  2014-04-30 12:23   ` Andrew Bennett
@ 2014-05-01 10:05     ` Andrew Bennett
  2014-05-01 20:52       ` Richard Sandiford
  0 siblings, 1 reply; 14+ messages in thread
From: Andrew Bennett @ 2014-05-01 10:05 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: binutils, Rich Fuhler, Matthew Fortune, rdsandiford, Saeed Ghazanfar

>> From: Andreas Schwab [mailto:schwab@linux-m68k.org] 
>> Andrew Bennett <Andrew.Bennett@imgtec.com> writes:
>>>
>>>  	* config.sub: Add support for mips32r6 and mips64r6.
>>>
>> This needs to be sent upstream first, which is 
>> <config-patches@gnu.org>.
>
> I have sent this section of the patch to config-patches.  

The patch has now been committed to the master config.* repository
as the following commit:

Author: Chao-ying Fu <chao-ying.fu@imgtec.com>
Date:   Thu May 1 12:48:36 2014 +1000

        * config.sub (mipsisa32r6, mipsisa64r6): New.
        * testsuite/config-sub.data: Add test cases for mipsisa*r6.
    
    Signed-off-by: Ben Elliston <bje@gnu.org>


Would it be possible for the config.sub in the binutils tree to be
updated?

Many thanks.


Andrew

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Add support for MIPS64r6
  2014-05-01 10:05     ` Andrew Bennett
@ 2014-05-01 20:52       ` Richard Sandiford
  0 siblings, 0 replies; 14+ messages in thread
From: Richard Sandiford @ 2014-05-01 20:52 UTC (permalink / raw)
  To: Andrew Bennett
  Cc: Andreas Schwab, binutils, Rich Fuhler, Matthew Fortune, Saeed Ghazanfar

Andrew Bennett <Andrew.Bennett@imgtec.com> writes:
>>> From: Andreas Schwab [mailto:schwab@linux-m68k.org] 
>>> Andrew Bennett <Andrew.Bennett@imgtec.com> writes:
>>>>
>>>>  	* config.sub: Add support for mips32r6 and mips64r6.
>>>>
>>> This needs to be sent upstream first, which is 
>>> <config-patches@gnu.org>.
>>
>> I have sent this section of the patch to config-patches.  
>
> The patch has now been committed to the master config.* repository
> as the following commit:
>
> Author: Chao-ying Fu <chao-ying.fu@imgtec.com>
> Date:   Thu May 1 12:48:36 2014 +1000
>
>         * config.sub (mipsisa32r6, mipsisa64r6): New.
>         * testsuite/config-sub.data: Add test cases for mipsisa*r6.
>     
>     Signed-off-by: Ben Elliston <bje@gnu.org>
>
>
> Would it be possible for the config.sub in the binutils tree to be
> updated?

OK, done for binutils and GCC.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Add support for MIPS64r6
  2014-04-29 19:17 [PATCH] Add support for MIPS64r6 Andrew Bennett
  2014-04-29 19:33 ` Andreas Schwab
@ 2014-05-07 17:52 ` Richard Sandiford
  2014-05-14 11:23   ` Andrew Bennett
  1 sibling, 1 reply; 14+ messages in thread
From: Richard Sandiford @ 2014-05-07 17:52 UTC (permalink / raw)
  To: Andrew Bennett; +Cc: binutils, Rich Fuhler, Matthew Fortune, Saeed Ghazanfar

Sorry for taking so long to get to this.

Andrew Bennett <Andrew.Bennett@imgtec.com> writes:
> This patch adds support for MIPS64r6.  MIPS64r6 includes most of MIPS64r5 
> but there are some instructions that have been re-coded or removed in order 
> to support the new MIPS64r6 instructions.  
>
> For more information please refer to:
> http://www.imgtec.com/mips/mips64-architecture.asp
>
> Some notes on the changes:
>
> A dense encoding has been used for several new instructions leading to the
> introduction of new special operand types. Some special casing during
> disassembly has also been necessary to handle these cases. While some checks
> are redundant due to the ordering of the opcode table they are present for
> safety in case of any future re-ordering of the table.
>
> A new PLT template has been added for R6 as the explicit JR opcode has been
> removed instead relying on JALR $0, <reg>.  Although JALR exists for <=r5
> we are being cautious in case the use of JALR is interpreted as a call in
> pre-existing MIPS implementations as part of hardware optimisations.
>
> MicroMIPSr5 is not compatible with MIPSr6 and as such is disabled. The JALX
> instruction has also been removed and the encoding re-used. If a new
> compressed ISA is defined then the interlinking support will need updating.
>
> ABI related changes for R6 are:
> 1) Introduction of new PC relative relocations
> 2) Definition of the new ISAs in e_flags.
>
> We would like to get early feedback on the ABI so that work in other tools
> can also be finalised.  The decision to define the new ISA in e_flags instead
> of the newly proposed .MIPS.abiflags section is due to the need for preventing
> linking of R<6 and R6 code.  While mixing ISAs within executables and DSOs is
> not supported we do not intend to prevent mixing of executables and DSOs.  The
> linux kernel will handle the emulation of instructions that do not exist.

This all looks good to me FWIW.

> The current patch does not contain any test cases, as we would like your 
> opinions on how to proceed with this.  There are three main issues.  Firstly,
> disabling all tests that check instructions that have been removed in 
> MIPSr6.  The problem here is that typically these tests contain valid, and
> non-valid R6 instructions, so there needs to be a way to prevent the non-valid
> instructions from being assembled if we are testing for R6.  One approach is to
> break the testcases up into the valid and non-valid instructions, and then just
> predicate the non-valid instruction tests in mips.exp for R6. What do you think
> about doing this?

Typically we run those tests via run_dump_test_arch, so we could just
add a "--defsym r6=0" or "--defsym r6=1" to the assembler command line
and use .if-based directives to skip the removed instructions.

> Secondly, updating tests that check for instructions that have been recoded in
> R6.  Would you be happy if we used the micromips@ approach for the disassembly
> files; we could use something like mipsr6@ ?

Yeah, that sounds like the right way to do it.  Or more specifically,
if the architecture extends mips32r6 and mips64r6, check for mipsr6@.

> Finally, should we cover all new instructions in one file and all removed
> instructions in another or break it down further?

I don't really have a strong opinion about that.  If you prefer one of the
other, go for it, otherwise maybe single tests make it easier to check
that all insns are covered?

> diff --git a/bfd/archures.c b/bfd/archures.c
> index 4ab5f1d..92bf821 100644
> --- a/bfd/archures.c
> +++ b/bfd/archures.c
> @@ -182,8 +182,10 @@ DESCRIPTION
>  .#define bfd_mach_mips_xlr              887682   {* decimal 'XLR'  *}
>  .#define bfd_mach_mipsisa32             32
>  .#define bfd_mach_mipsisa32r2           33
> +.#define bfd_mach_mipsisa32r6           34
>  .#define bfd_mach_mipsisa64             64
>  .#define bfd_mach_mipsisa64r2           65
> +.#define bfd_mach_mipsisa64r6           66
>  .#define bfd_mach_mips_micromips        96
>  .  bfd_arch_i386,      {* Intel 386 *}
>  .#define bfd_mach_i386_intel_syntax	(1 << 0)

Obviously r3 and r5 have gone in since you posted this so now it
should be 37 and 69.

> +static const bfd_vma mipsr6_exec_plt_entry[] =
> +{
> +  0x3c0f0000,	/* lui $15, %hi(.got.plt entry)			*/
> +  0x01f90000,	/* l[wd] $25, %lo(.got.plt entry)($15)		*/
> +  0x25f80000,	/* addiu $24, $15, %lo(.got.plt entry)		*/
> +  0x03200009	/* jr $25					*/
> +};

We don't need to worry about MIPS I compatibility here, so we could put
the JR before the ADDIU and avoid executing the LUI from the following
PLT.  What you have is fine too if you think it's better though.

> +    case R_MIPS_PCHI16:
> +      if (howto->partial_inplace)
> +	addend = _bfd_mips_elf_sign_extend (addend, 16);
> +      value = mips_elf_high (symbol + addend - p);
> +      BFD_ASSERT (howto->rightshift == 16);
> +      overflowed_p = mips_elf_overflow_p (value, 16);
> +      value &= howto->dst_mask;
> +      break;

Is the REL handling deliberately different from other HI16s here?
Normally the idea is that the HI16 is paired with a following LO16
and you combine the in-place addends from both to get the full
HI16 addend.  "addend" would then already be the full addend
in this case.

> +    case R_MIPS_PCLO16:
> +      if (howto->partial_inplace)
> +	addend = _bfd_mips_elf_sign_extend (addend, 16);
> +      value = symbol + addend - p;
> +      overflowed_p = mips_elf_overflow_p (value, 32);
> +      value &= howto->dst_mask;
> +      break;

LO16s can't overflow.  I think this should just be:

      value = symbol + _bfd_mips_elf_sign_extend (addend, 16) - p;
      value &= howto->dst_mask;
      break;

with the overflow check being left to the HI16.

> @@ -10048,6 +10141,13 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>  		(info, msg, name, input_bfd, input_section, rel->r_offset);
>  	      return FALSE;
>  	    }
> +	  if (aligned_pcrel_reloc_p (howto->type))
> +	    {
> +	      msg = _("pc relative load using unaligned address");

"PC-relative".  Maybe also "from" rather than "using"?

> diff --git a/binutils/testsuite/binutils-all/objcopy.exp b/binutils/testsuite/binutils-all/objcopy.exp
> index 6159b9d..9b22744 100644
> --- a/binutils/testsuite/binutils-all/objcopy.exp
> +++ b/binutils/testsuite/binutils-all/objcopy.exp
> @@ -986,6 +986,7 @@ if [is_elf_format] {
>      # targ_defvec=bfd_elf32_nlittlemips_vec in config.bfd.  When syncing,
>      # don't forget that earlier case-matches trump later ones.
>      if { ![istarget "mips*-sde-elf*"] && ![istarget "mips*-mti-elf*"]
> +	 && ![istarget "mips*-img-elf*"]
>           && ![istarget "mips64*-*-openbsd*"] } {
>  	setup_xfail "mips*-*-irix5*" "mips*-*-irix6*" "mips*-*-elf*" \
>  	    "mips*-*-rtems*" "mips*-*-windiss" "mips*-*-none" \
> diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp
> index 2a6bc6a..e45d6ea 100644
> --- a/binutils/testsuite/binutils-all/readelf.exp
> +++ b/binutils/testsuite/binutils-all/readelf.exp
> @@ -103,6 +103,7 @@ proc readelf_test { options binary_file regexp_file xfails } {
>  	if { [istarget "mips*-*-*linux*"]
>  	     || [istarget "mips*-sde-elf*"]
>  	     || [istarget "mips*-mti-elf*"]
> +	     || [istarget "mips*-img-elf*"]
>  	     || [istarget "mips*-*freebsd*"] } then {
>  	    set target_machine tmips
>  	} else {

Please submit the img-elf bits separately.

> +/* OP_SAME_RS_RT matcher.  */
> +
> +static bfd_boolean
> +match_same_rs_rt_operand (struct mips_arg_info *arg,
> +			  const struct mips_operand *operand)
> +{
> +  unsigned int regno;
> +
> +  if (!match_reg (arg, OP_REG_GP, &regno))
> +    return FALSE;
> +
> +  if (regno == 0)
> +    {
> +      set_insn_error (arg->argnum, _("the source register must not be $0"));
> +      return FALSE;
> +    }
> +
> +  arg->last_regno = regno;
> +
> +  insn_insert_operand (arg->insn, operand, regno | (regno << 5));
> +  return TRUE;
> +}

Looks good, but after this...

> +
> +/* OP_GP_NOT_ZERO matcher.  */
> +
> +static bfd_boolean
> +match_gp_not_zero_operand (struct mips_arg_info *arg,
> +			   const struct mips_operand *operand)
> +{
> +  unsigned int regno;
> +
> +  if (!match_reg (arg, OP_REG_GP, &regno))
> +    return FALSE;
> +
> +  if (regno == 0)
> +    {
> +      set_insn_error (arg->argnum, _("the source register must not be $0"));
> +      return FALSE;
> +    }
> +
> +  arg->last_regno = regno;
> +
> +  insn_insert_operand (arg->insn, operand, regno);
> +  return TRUE;
> +}
> +
> +/* OP_GP_NOT_ZERO_LT_PREV matcher.  */
> +
> +static bfd_boolean
> +match_gp_not_zero_lt_prev_operand (struct mips_arg_info *arg,
> +				   const struct mips_operand *operand)
> +{
> +  unsigned int regno;
> +
> +  if (!match_reg (arg, OP_REG_GP, &regno))
> +    return FALSE;
> +
> +  if (regno == 0)
> +    {
> +      set_insn_error (arg->argnum, _("the source register must not be $0"));
> +      return FALSE;
> +    }
> +
> +  if (regno >= arg->last_regno)
> +    return FALSE;
> +
> +  arg->last_regno = regno;
> +
> +  insn_insert_operand (arg->insn, operand, regno);
> +  return TRUE;
> +}
> +
> +/* OP_GP_GT_PREV matcher.  */
> +
> +static bfd_boolean
> +match_gp_gt_prev_operand (struct mips_arg_info *arg,
> +			  const struct mips_operand *operand)
> +{
> +  unsigned int regno;
> +
> +  if (!match_reg (arg, OP_REG_GP, &regno))
> +    return FALSE;
> +
> +  if (regno <= arg->last_regno)
> +    return FALSE;
> +
> +  arg->last_regno = regno;
> +
> +  insn_insert_operand (arg->insn, operand, regno);
> +  return TRUE;
> +}
> +
> +/* OP_GP_LE_PREV matcher.  */
> +
> +static bfd_boolean
> +match_gp_le_prev_operand (struct mips_arg_info *arg,
> +			  const struct mips_operand *operand)
> +{
> +  unsigned int regno;
> +
> +  if (!match_reg (arg, OP_REG_GP, &regno))
> +    return FALSE;
> +
> +  if (regno > arg->last_regno)
> +    return FALSE;
> +
> +  arg->last_regno = regno;
> +
> +  insn_insert_operand (arg->insn, operand, regno);
> +  return TRUE;
> +}
> +
> +/* OP_GP_GE_PREV matcher.  */
> +
> +static bfd_boolean
> +match_gp_ge_prev_operand (struct mips_arg_info *arg,
> +			  const struct mips_operand *operand)
> +{
> +  unsigned int regno;
> +
> +  if (!match_reg (arg, OP_REG_GP, &regno))
> +    return FALSE;
> +
> +  if (regno < arg->last_regno)
> +    return FALSE;
> +
> +  arg->last_regno = regno;
> +
> +  insn_insert_operand (arg->insn, operand, regno);
> +  return TRUE;
> +}
> +
> +/* OP_GP_NOT_ZERO_NOT_PREV matcher.  */
> +
> +static bfd_boolean
> +match_gp_not_zero_not_prev_operand (struct mips_arg_info *arg,
> +				    const struct mips_operand *operand)
> +{
> +  unsigned int regno;
> +
> +  if (!match_reg (arg, OP_REG_GP, &regno))
> +    return FALSE;
> +
> +  if (regno == 0 || regno == arg->last_regno)
> +    {
> +      set_insn_error (arg->argnum, _("the source registers must not be $0 and different"));
> +      return FALSE;
> +    }
> +
> +  arg->last_regno = regno;
> +
> +  insn_insert_operand (arg->insn, operand, regno);
> +  return TRUE;
> +}

...there's a lot of commonality.  Please try to find some way of factoring
this.  One way would be to have a new mips_operand-derived structure
(along the lines of mips_reg_pair_operand) that says which of <, =, and >
are acceptable and whether $0 is allowed.  OP_REPEAT_PREV_REG could
use it too.

> @@ -5245,11 +5483,13 @@ match_pc_operand (struct mips_arg_info *arg)
>     register that we need to match.  */
>  
>  static bfd_boolean
> -match_tied_reg_operand (struct mips_arg_info *arg, unsigned int other_regno)
> +match_tied_reg_operand (struct mips_arg_info *arg,
> +			enum mips_reg_operand_type type,
> +			unsigned int other_regno)
>  {
>    unsigned int regno;
>  
> -  return match_reg (arg, OP_REG_GP, &regno) && regno == other_regno;
> +  return match_reg (arg, type, &regno) && regno == other_regno;
>  }
>  
>  /* Read a floating-point constant from S for LI.S or LI.D.  LENGTH is
> @@ -5495,10 +5735,10 @@ match_operand (struct mips_arg_info *arg,
>        return match_mdmx_imm_reg_operand (arg, operand);
>  
>      case OP_REPEAT_DEST_REG:
> -      return match_tied_reg_operand (arg, arg->dest_regno);
> +      return match_tied_reg_operand (arg, OP_REG_GP, arg->dest_regno);
>  
>      case OP_REPEAT_PREV_REG:
> -      return match_tied_reg_operand (arg, arg->last_regno);
> +      return match_tied_reg_operand (arg, OP_REG_GP, arg->last_regno);
>  
>      case OP_PC:
>        return match_pc_operand (arg);

Couldn't tell off-hand why you need this (although it looks OK).

> @@ -5714,6 +5976,11 @@ insns_between (const struct mips_cl_insn *insn1,
>  	return 1;
>      }
>  
> +  if (insn1->insn_mo->pinfo2 & INSN2_FORBIDDEN_SLOT
> +      && (pinfo2 & INSN_NO_DELAY_SLOT
> +	  || (insn2 && delayed_branch_p (insn2))))
> +    return 1;
> +

Please add a comment and use (....) round the "&"s.

> @@ -6571,6 +6838,46 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
>  	  }
>  	  break;
>  
> +	case BFD_RELOC_MIPS_21_PCREL_S2:
> +	  {
> +	    int shift;
> +
> +	    shift = 2;
> +	    if ((address_expr->X_add_number & ((1 << shift) - 1)) != 0)
> +	      as_bad (_("branch to misaligned address (0x%lx)"),
> +		      (unsigned long) address_expr->X_add_number);
> +	    if (!mips_relax_branch)
> +	      {
> +		if ((address_expr->X_add_number + (1 << (shift + 20)))
> +		    & ~((1 << (shift + 21)) - 1))
> +		  as_bad (_("branch address range overflow (0x%lx)"),
> +			  (unsigned long) address_expr->X_add_number);
> +		ip->insn_opcode |= ((address_expr->X_add_number >> shift)
> +				    & 0x1fffff);
> +	      }
> +	  }
> +	  break;
> +
> +	case BFD_RELOC_MIPS_26_PCREL_S2:
> +	  {
> +	    int shift;
> +
> +	    shift = 2;
> +	    if ((address_expr->X_add_number & ((1 << shift) - 1)) != 0)
> +	      as_bad (_("branch to misaligned address (0x%lx)"),
> +		      (unsigned long) address_expr->X_add_number);
> +	    if (!mips_relax_branch)
> +	      {
> +		if ((address_expr->X_add_number + (1 << (shift + 25)))
> +		    & ~((1 << (shift + 26)) - 1))
> +		  as_bad (_("branch address range overflow (0x%lx)"),
> +			  (unsigned long) address_expr->X_add_number);
> +		ip->insn_opcode |= ((address_expr->X_add_number >> shift)
> +				    & 0x3ffffff);
> +	      }
> +	  }
> +	  break;

I think we should drop the !mips_relax_branch test until branch relaxation
is supported for r6.

> @@ -14226,6 +14583,17 @@ mips_force_relocation (fixS *fixp)
>        || fixp->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1)
>      return 1;
>  
> +  /* We want all relocations to be kept for R6 relaxation */
> +  if (ISA_IS_R6 (mips_opts.isa)
> +      && (fixp->fx_r_type == BFD_RELOC_16_PCREL_S2
> +	  || fixp->fx_r_type == BFD_RELOC_MIPS_21_PCREL_S2
> +	  || fixp->fx_r_type == BFD_RELOC_MIPS_26_PCREL_S2
> +	  || fixp->fx_r_type == BFD_RELOC_MIPS_18_PCREL_S3
> +	  || fixp->fx_r_type == BFD_RELOC_MIPS_19_PCREL_S2
> +	  || fixp->fx_r_type == BFD_RELOC_HI16_S_PCREL
> +	  || fixp->fx_r_type == BFD_RELOC_LO16_PCREL))
> +    return 1;

"all PC-relative relocations"?

> @@ -14462,6 +14836,81 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
>  	md_number_to_chars (buf, *valP, fixP->fx_size);
>        break;
>  
> +    case BFD_RELOC_MIPS_21_PCREL_S2:
> +      if ((*valP & 0x3) != 0)
> +	as_bad_where (fixP->fx_file, fixP->fx_line,
> +		      _("branch to misaligned address (%lx)"), (long) *valP);
> +
> +      /* We need to save the bits in the instruction since fixup_segment()
> +	 might be deleting the relocation entry (i.e., a branch within
> +	 the current segment).  */
> +      if (! fixP->fx_done)
> +	break;
> +
> +      /* Update old instruction data.  */
> +      insn = read_insn (buf);
> +
> +      if (*valP + 0x400000 <= 0x7fffff)
> +	{
> +	  insn |= (*valP >> 2) & 0x1fffff;
> +	  write_insn (buf, insn);
> +	}
> +      else
> +	{
> +	  /* CFU FIXME.  */
> +	  gas_assert (0);
> +	}
> +      break;
> +
> +    case BFD_RELOC_MIPS_26_PCREL_S2:
> +      if ((*valP & 0x3) != 0)
> +	as_bad_where (fixP->fx_file, fixP->fx_line,
> +		      _("branch to misaligned address (%lx)"), (long) *valP);
> +
> +      /* We need to save the bits in the instruction since fixup_segment()
> +	 might be deleting the relocation entry (i.e., a branch within
> +	 the current segment).  */
> +      if (! fixP->fx_done)
> +	break;
> +
> +      /* Update old instruction data.  */
> +      insn = read_insn (buf);
> +
> +      if (*valP + 0x8000000 <= 0xfffffff)
> +	{
> +	  insn |= (*valP >> 2) & 0x3ffffff;
> +	  write_insn (buf, insn);
> +	}
> +      else
> +	{
> +	  /* CFU FIXME.  */
> +	  gas_assert (0);
> +	}
> +      break;

Can fx_done ever happen given the mips_force_relocation change?
I think we should assert if not, like you do for the others.

> +    case BFD_RELOC_MIPS_18_PCREL_S3:
> +      if ((*valP & 0x3) != 0)
> +	as_bad_where (fixP->fx_file, fixP->fx_line,
> +		      _("pc rel from misaligned address (%lx)"),
> +		      (long) *valP);
> +
> +      gas_assert(!fixP->fx_done);
> +      break;

Should this be 7 rather than 3?

> diff --git a/gas/doc/c-mips.texi b/gas/doc/c-mips.texi
> index 0c5e82d..ffcf27f 100644
> --- a/gas/doc/c-mips.texi
> +++ b/gas/doc/c-mips.texi
> @@ -81,17 +81,20 @@ VxWorks-style position-independent macro expansions.
>  @itemx -mips5
>  @itemx -mips32
>  @itemx -mips32r2
> +@itemx -mips32r6
>  @itemx -mips64
>  @itemx -mips64r2
> +@itemx -mips64r6
>  Generate code for a particular MIPS Instruction Set Architecture level.
>  @samp{-mips1} corresponds to the R2000 and R3000 processors,
>  @samp{-mips2} to the R6000 processor, @samp{-mips3} to the
>  R4000 processor, and @samp{-mips4} to the R8000 and R10000 processors.
> -@samp{-mips5}, @samp{-mips32}, @samp{-mips32r2}, @samp{-mips64}, and
> -@samp{-mips64r2} correspond to generic MIPS V, MIPS32, MIPS32 Release 2,
> -MIPS64, and MIPS64 Release 2 ISA processors, respectively.  You can also
> -switch instruction sets during the assembly; see @ref{MIPS ISA,
> -Directives to override the ISA level}.
> +@samp{-mips5}, @samp{-mips32}, @samp{-mips32r2}, @samp{-mips32r6},
> +@samp{-mips64}, @samp{-mips64r2} and @samp{-mips64r6} correspond to
> +generic MIPS V, MIPS32, MIPS32 Release 2, MIPS32 Release 6, MIPS64,
> +MIPS64 Release 2, and MIPS64 Release 6 ISA processors, respectively.
> +You can also switch instruction sets during the assembly; see
> +@ref{MIPS ISA, Directives to override the ISA level}.
>  
>  @item -mgp32
>  @itemx -mfp32
> @@ -652,8 +655,8 @@ Small data is not supported for SVR4-style PIC.
>  @kindex @code{.set mips@var{n}}
>  @sc{gnu} @code{@value{AS}} supports an additional directive to change
>  the MIPS Instruction Set Architecture level on the fly: @code{.set
> -mips@var{n}}.  @var{n} should be a number from 0 to 5, or 32, 32r2, 64
> -or 64r2.
> +mips@var{n}}.  @var{n} should be a number from 0 to 5, or 32, 32r2,
> +32r6, 64, 64r2 or 64r6.
>  The values other than 0 make the assembler accept instructions
>  for the corresponding ISA level, from that point on in the
>  assembly.  @code{.set mips@var{n}} affects not only which instructions

This needs to be duplicated in as.texinfo.

> @@ -1089,7 +1146,8 @@ struct mips_opcode
>     (mips_isa_table[(Y & INSN_ISA_MASK) - 1] >> ((X & INSN_ISA_MASK) - 1)) & 1
>     is non-zero.  */
>  static const unsigned int mips_isa_table[] =
> -  { 0x0001, 0x0003, 0x0607, 0x1e0f, 0x3e1f, 0x0a23, 0x3e63, 0x3ebf, 0x3fff };
> +  { 0x0001, 0x0003, 0x0607, 0x1e0f, 0x3e1f, 0x0a23, 0x3e63, 0x3ebf, 0x3fff,
> +    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7e63, 0xffff };

Is it really true that r6 allows everything, given the incompatibility?

> @@ -1077,6 +1096,23 @@ print_vu0_channel (struct disassemble_info *info,
>      abort ();
>  }
>  
> +/* Record information about a register operand */
> +
> +static void
> +mips_seen_register (struct mips_print_arg_state *state,
> +		    unsigned int regno,
> +		    enum mips_reg_operand_type reg_type)
> +{
> +  state->last_reg_type = reg_type;
> +  state->last_regno = regno;
> +
> +  if (!state->seen_dest)
> +    {
> +      state->seen_dest = 1;
> +      state->dest_regno = regno;
> +    }
> +}

Nice.  Thanks for factoring this out.

> @@ -1358,13 +1473,14 @@ print_insn_arg (struct disassemble_info *info,
>  
>  /* Print the arguments for INSN, which is described by OPCODE.
>     Use DECODE_OPERAND to get the encoding of each operand.  Use BASE_PC
> -   as the base of OP_PCREL operands.  */
> +   as the base of OP_PCREL operands adjusting by LENGTH if the OP_PCREL
> +   operand is for a branch or jump.  */

Comma before "adjusting".

> @@ -1426,9 +1542,27 @@ print_insn_args (struct disassemble_info *info,
>  		infprintf (is, "$%d,%d", reg, sel);
>  	    }
>  	  else
> -	    print_insn_arg (info, &state, opcode, operand, base_pc,
> -			    mips_extract_operand (operand, insn));
> -	  if (*s == 'm' || *s == '+')
> +	    {
> +	      bfd_vma base_pc = insn_pc;
> +
> +	      /* Adjust the PC relative base so that branch/jump insns use
> +		 the following PC as the base but genuinely PC relative
> +		 operands use the current PC.  */
> +	      if (operand->type == OP_PCREL)
> +		{
> +		  const struct mips_pcrel_operand *pcrel_op;
> +
> +		  pcrel_op = (const struct mips_pcrel_operand *) operand;
> +		  /* The include_isa_bit flag is sufficient to distinguish
> +		     branch/jump from other PC relative operands.  */
> +		  if (pcrel_op->include_isa_bit)
> +		    base_pc += length;
> +		}
> +
> +	      print_insn_arg (info, &state, opcode, operand, base_pc,
> +			      mips_extract_operand (operand, insn));
> +	    }
> +	  if (*s == 'm' || *s == '+' || *s == '-')
>  	    ++s;
>  	  break;
>  	}
> @@ -1494,9 +1628,60 @@ print_insn_mips (bfd_vma memaddr,
>  	      && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
>  	      && (word & op->mask) == op->match)
>  	    {
> +	      if (strcmp (op->name, "bgezc") == 0
> +		  || strcmp (op->name, "bltzc") == 0
> +		  || strcmp (op->name, "bgezalc") == 0
> +		  || strcmp (op->name, "bltzalc") == 0)
> +		{
> +		  if (((word >> 16) & 31) != ((word >> 21) & 31)
> +		      || ((word >> 16) & 31) == 0)
> +		    continue;
> +		}
> +	      else if (strcmp (op->name, "blezalc") == 0
> +		       || strcmp (op->name, "bgtzalc") == 0
> +		       || strcmp (op->name, "blezc") == 0
> +		       || strcmp (op->name, "bgtzc") == 0
> +		       || strcmp (op->name, "beqzalc") == 0
> +		       || strcmp (op->name, "bnezalc") == 0)
> +		{
> +		  if (((word >> 16) & 31) == 0)
> +		    continue;
> +		}
> +	      else if (strcmp (op->name, "bgec") == 0
> +		       || strcmp (op->name, "bltc") == 0
> +		       || strcmp (op->name, "bbec") == 0
> +		       || strcmp (op->name, "bstc") == 0)
> +		{
> +		  if (((word >> 16) & 31) == ((word >> 21) & 31)
> +		      || ((word >> 21) & 31) == 0
> +		      || ((word >> 16) & 31) == 0)
> +		    continue;
> +		}
> +	      else if (strcmp (op->name, "beqc") == 0
> +		       || strcmp (op->name, "bnec") == 0)
> +		{
> +		  if (((word >> 21) & 31) >= ((word >> 16) & 31)
> +		      || ((word >> 21) & 31) == 0)
> +		    continue;
> +		}
> +	      else if (strcmp (op->name, "bovc") == 0
> +		       || strcmp (op->name, "bnvc") == 0)
> +		{
> +		  if (((word >> 21) & 31) < ((word >> 16) & 31))
> +		    continue;
> +		}
> +	      else if (strcmp (op->name, "beqzc") == 0
> +		       || strcmp (op->name, "bnezc") == 0)
> +		{
> +		  if (((word >> 21) & 31) == 0)
> +		    continue;
> +		}

Looks like this is just reinforcing the restrictions from the OP_*s,
is that right?  If so, I think it would be cleaner to use the
mips_operand information rather than checks for specific instructions.

>  	      /* We always allow to disassemble the jalx instruction.  */
>  	      if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
> -		  && strcmp (op->name, "jalx"))
> +		 && (strcmp (op->name, "jalx")
> +		     || (mips_isa & INSN_ISA_MASK) == ISA_MIPS32R6
> +		     || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6))
>  		continue;

Comment needs updating.

I'm going to take the opcodes changes on faith :-)

Thanks,
Richard

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [PATCH] Add support for MIPS64r6
  2014-05-07 17:52 ` Richard Sandiford
@ 2014-05-14 11:23   ` Andrew Bennett
  2014-05-14 20:03     ` Richard Sandiford
  0 siblings, 1 reply; 14+ messages in thread
From: Andrew Bennett @ 2014-05-14 11:23 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: binutils, Rich Fuhler, Matthew Fortune, Saeed Ghazanfar

> Sorry for taking so long to get to this.

That's ok.  We are working on quite a few patches at the moment, so 
sorry for the delay in replying.
 
> > +static const bfd_vma mipsr6_exec_plt_entry[] =
> > +{
> > +  0x3c0f0000,	/* lui $15, %hi(.got.plt entry)			*/
> > +  0x01f90000,	/* l[wd] $25, %lo(.got.plt entry)($15)		*/
> > +  0x25f80000,	/* addiu $24, $15, %lo(.got.plt entry)		*/
> > +  0x03200009	/* jr $25					*/
> > +};
> 
> We don't need to worry about MIPS I compatibility here, so we could put
> the JR before the ADDIU and avoid executing the LUI from the following
> PLT.  What you have is fine too if you think it's better though.

Agreed.  We hadn't understood the rationale for the existing structure
but as you say the MIPS I issue is no longer relevant.
 
> > +    case R_MIPS_PCHI16:
> > +      if (howto->partial_inplace)
> > +	addend = _bfd_mips_elf_sign_extend (addend, 16);
> > +      value = mips_elf_high (symbol + addend - p);
> > +      BFD_ASSERT (howto->rightshift == 16);
> > +      overflowed_p = mips_elf_overflow_p (value, 16);
> > +      value &= howto->dst_mask;
> > +      break;
> 
> Is the REL handling deliberately different from other HI16s here?
> Normally the idea is that the HI16 is paired with a following LO16
> and you combine the in-place addends from both to get the full
> HI16 addend.  "addend" would then already be the full addend
> in this case.

You are correct here: there should be no difference in the REL handling.  I 
I will add some code to correctly calculate the addend for the 
R_MIPS_PCHI16 relocation.

> > diff --git a/binutils/testsuite/binutils-all/objcopy.exp
> b/binutils/testsuite/binutils-all/objcopy.exp
> > index 6159b9d..9b22744 100644
> > --- a/binutils/testsuite/binutils-all/objcopy.exp
> > +++ b/binutils/testsuite/binutils-all/objcopy.exp
> > @@ -986,6 +986,7 @@ if [is_elf_format] {
> >      # targ_defvec=bfd_elf32_nlittlemips_vec in config.bfd.  When syncing,
> >      # don't forget that earlier case-matches trump later ones.
> >      if { ![istarget "mips*-sde-elf*"] && ![istarget "mips*-mti-elf*"]
> > +	 && ![istarget "mips*-img-elf*"]
> >           && ![istarget "mips64*-*-openbsd*"] } {
> >  	setup_xfail "mips*-*-irix5*" "mips*-*-irix6*" "mips*-*-elf*" \
> >  	    "mips*-*-rtems*" "mips*-*-windiss" "mips*-*-none" \
> > diff --git a/binutils/testsuite/binutils-all/readelf.exp
> b/binutils/testsuite/binutils-all/readelf.exp
> > index 2a6bc6a..e45d6ea 100644
> > --- a/binutils/testsuite/binutils-all/readelf.exp
> > +++ b/binutils/testsuite/binutils-all/readelf.exp
> > @@ -103,6 +103,7 @@ proc readelf_test { options binary_file regexp_file
> xfails } {
> >  	if { [istarget "mips*-*-*linux*"]
> >  	     || [istarget "mips*-sde-elf*"]
> >  	     || [istarget "mips*-mti-elf*"]
> > +	     || [istarget "mips*-img-elf*"]
> >  	     || [istarget "mips*-*freebsd*"] } then {
> >  	    set target_machine tmips
> >  	} else {
> 
> Please submit the img-elf bits separately.

Done.

> > @@ -5245,11 +5483,13 @@ match_pc_operand (struct mips_arg_info *arg)
> >     register that we need to match.  */
> >
> >  static bfd_boolean
> > -match_tied_reg_operand (struct mips_arg_info *arg, unsigned int
> other_regno)
> > +match_tied_reg_operand (struct mips_arg_info *arg,
> > +			enum mips_reg_operand_type type,
> > +			unsigned int other_regno)
> >  {
> >    unsigned int regno;
> >
> > -  return match_reg (arg, OP_REG_GP, &regno) && regno == other_regno;
> > +  return match_reg (arg, type, &regno) && regno == other_regno;
> >  }
> >
> >  /* Read a floating-point constant from S for LI.S or LI.D.  LENGTH is
> > @@ -5495,10 +5735,10 @@ match_operand (struct mips_arg_info *arg,
> >        return match_mdmx_imm_reg_operand (arg, operand);
> >
> >      case OP_REPEAT_DEST_REG:
> > -      return match_tied_reg_operand (arg, arg->dest_regno);
> > +      return match_tied_reg_operand (arg, OP_REG_GP, arg->dest_regno);
> >
> >      case OP_REPEAT_PREV_REG:
> > -      return match_tied_reg_operand (arg, arg->last_regno);
> > +      return match_tied_reg_operand (arg, OP_REG_GP, arg->last_regno);
> >
> >      case OP_PC:
> >        return match_pc_operand (arg);
> 
> Couldn't tell off-hand why you need this (although it looks OK).

The introduction of the new argument is actually left over from intermediate
work on the R6 ISA.  There were plans for supporting some floating-point
mnemonics which required register matching but these were dropped.  We will
remove this and add it if we do end up with a need to match registers in
FP instructions.

> > @@ -6571,6 +6838,46 @@ append_insn (struct mips_cl_insn *ip, expressionS
> *address_expr,
> >  	  }
> >  	  break;
> >
> > +	case BFD_RELOC_MIPS_21_PCREL_S2:
> > +	  {
> > +	    int shift;
> > +
> > +	    shift = 2;
> > +	    if ((address_expr->X_add_number & ((1 << shift) - 1)) != 0)
> > +	      as_bad (_("branch to misaligned address (0x%lx)"),
> > +		      (unsigned long) address_expr->X_add_number);
> > +	    if (!mips_relax_branch)
> > +	      {
> > +		if ((address_expr->X_add_number + (1 << (shift + 20)))
> > +		    & ~((1 << (shift + 21)) - 1))
> > +		  as_bad (_("branch address range overflow (0x%lx)"),
> > +			  (unsigned long) address_expr->X_add_number);
> > +		ip->insn_opcode |= ((address_expr->X_add_number >> shift)
> > +				    & 0x1fffff);
> > +	      }
> > +	  }
> > +	  break;
> > +
> > +	case BFD_RELOC_MIPS_26_PCREL_S2:
> > +	  {
> > +	    int shift;
> > +
> > +	    shift = 2;
> > +	    if ((address_expr->X_add_number & ((1 << shift) - 1)) != 0)
> > +	      as_bad (_("branch to misaligned address (0x%lx)"),
> > +		      (unsigned long) address_expr->X_add_number);
> > +	    if (!mips_relax_branch)
> > +	      {
> > +		if ((address_expr->X_add_number + (1 << (shift + 25)))
> > +		    & ~((1 << (shift + 26)) - 1))
> > +		  as_bad (_("branch address range overflow (0x%lx)"),
> > +			  (unsigned long) address_expr->X_add_number);
> > +		ip->insn_opcode |= ((address_expr->X_add_number >> shift)
> > +				    & 0x3ffffff);
> > +	      }
> > +	  }
> > +	  break;
> 
> I think we should drop the !mips_relax_branch test until branch relaxation
> is supported for r6.

Thats fine.  The code was there as a marker to remind us that branch relaxation 
support needs to be added for R6.

> > @@ -14462,6 +14836,81 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg
> ATTRIBUTE_UNUSED)
> >  	md_number_to_chars (buf, *valP, fixP->fx_size);
> >        break;
> >
> > +    case BFD_RELOC_MIPS_21_PCREL_S2:
> > +      if ((*valP & 0x3) != 0)
> > +	as_bad_where (fixP->fx_file, fixP->fx_line,
> > +		      _("branch to misaligned address (%lx)"), (long) *valP);
> > +
> > +      /* We need to save the bits in the instruction since fixup_segment()
> > +	 might be deleting the relocation entry (i.e., a branch within
> > +	 the current segment).  */
> > +      if (! fixP->fx_done)
> > +	break;
> > +
> > +      /* Update old instruction data.  */
> > +      insn = read_insn (buf);
> > +
> > +      if (*valP + 0x400000 <= 0x7fffff)
> > +	{
> > +	  insn |= (*valP >> 2) & 0x1fffff;
> > +	  write_insn (buf, insn);
> > +	}
> > +      else
> > +	{
> > +	  /* CFU FIXME.  */
> > +	  gas_assert (0);
> > +	}
> > +      break;
> > +
> > +    case BFD_RELOC_MIPS_26_PCREL_S2:
> > +      if ((*valP & 0x3) != 0)
> > +	as_bad_where (fixP->fx_file, fixP->fx_line,
> > +		      _("branch to misaligned address (%lx)"), (long) *valP);
> > +
> > +      /* We need to save the bits in the instruction since fixup_segment()
> > +	 might be deleting the relocation entry (i.e., a branch within
> > +	 the current segment).  */
> > +      if (! fixP->fx_done)
> > +	break;
> > +
> > +      /* Update old instruction data.  */
> > +      insn = read_insn (buf);
> > +
> > +      if (*valP + 0x8000000 <= 0xfffffff)
> > +	{
> > +	  insn |= (*valP >> 2) & 0x3ffffff;
> > +	  write_insn (buf, insn);
> > +	}
> > +      else
> > +	{
> > +	  /* CFU FIXME.  */
> > +	  gas_assert (0);
> > +	}
> > +      break;
> 
> Can fx_done ever happen given the mips_force_relocation change?
> I think we should assert if not, like you do for the others.

You are correct.   I will make the code the same as the other cases.

> 
> > +    case BFD_RELOC_MIPS_18_PCREL_S3:
> > +      if ((*valP & 0x3) != 0)
> > +	as_bad_where (fixP->fx_file, fixP->fx_line,
> > +		      _("pc rel from misaligned address (%lx)"),
> > +		      (long) *valP);
> > +
> > +      gas_assert(!fixP->fx_done);
> > +      break;
> 
> Should this be 7 rather than 3?

Yes.

> > @@ -1089,7 +1146,8 @@ struct mips_opcode
> >     (mips_isa_table[(Y & INSN_ISA_MASK) - 1] >> ((X & INSN_ISA_MASK) - 1)) &
> 1
> >     is non-zero.  */
> >  static const unsigned int mips_isa_table[] =
> > -  { 0x0001, 0x0003, 0x0607, 0x1e0f, 0x3e1f, 0x0a23, 0x3e63, 0x3ebf, 0x3fff
> };
> > +  { 0x0001, 0x0003, 0x0607, 0x1e0f, 0x3e1f, 0x0a23, 0x3e63, 0x3ebf, 0x3fff,
> > +    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7e63, 0xffff };
> 
> Is it really true that r6 allows everything, given the incompatibility?

The problem is that the removed instructions in R6 come from different ISAs.  One 
approach to solve this is to describe in the membership field the different ISAs an 
instruction belongs to.  This would require us to create a large amount of different ISA
combinations which is hard to manage.  A cleaner approach (and implemented in the patch) 
is to say that R6 is an extension of R5 and then to deal with the removed instructions by 
adding instruction exclusions for R6.  

> > @@ -1426,9 +1542,27 @@ print_insn_args (struct disassemble_info *info,
> >  		infprintf (is, "$%d,%d", reg, sel);
> >  	    }
> >  	  else
> > -	    print_insn_arg (info, &state, opcode, operand, base_pc,
> > -			    mips_extract_operand (operand, insn));
> > -	  if (*s == 'm' || *s == '+')
> > +	    {
> > +	      bfd_vma base_pc = insn_pc;
> > +
> > +	      /* Adjust the PC relative base so that branch/jump insns use
> > +		 the following PC as the base but genuinely PC relative
> > +		 operands use the current PC.  */
> > +	      if (operand->type == OP_PCREL)
> > +		{
> > +		  const struct mips_pcrel_operand *pcrel_op;
> > +
> > +		  pcrel_op = (const struct mips_pcrel_operand *) operand;
> > +		  /* The include_isa_bit flag is sufficient to distinguish
> > +		     branch/jump from other PC relative operands.  */
> > +		  if (pcrel_op->include_isa_bit)
> > +		    base_pc += length;
> > +		}
> > +
> > +	      print_insn_arg (info, &state, opcode, operand, base_pc,
> > +			      mips_extract_operand (operand, insn));
> > +	    }
> > +	  if (*s == 'm' || *s == '+' || *s == '-')
> >  	    ++s;
> >  	  break;
> >  	}
> > @@ -1494,9 +1628,60 @@ print_insn_mips (bfd_vma memaddr,
> >  	      && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
> >  	      && (word & op->mask) == op->match)
> >  	    {
> > +	      if (strcmp (op->name, "bgezc") == 0
> > +		  || strcmp (op->name, "bltzc") == 0
> > +		  || strcmp (op->name, "bgezalc") == 0
> > +		  || strcmp (op->name, "bltzalc") == 0)
> > +		{
> > +		  if (((word >> 16) & 31) != ((word >> 21) & 31)
> > +		      || ((word >> 16) & 31) == 0)
> > +		    continue;
> > +		}
> > +	      else if (strcmp (op->name, "blezalc") == 0
> > +		       || strcmp (op->name, "bgtzalc") == 0
> > +		       || strcmp (op->name, "blezc") == 0
> > +		       || strcmp (op->name, "bgtzc") == 0
> > +		       || strcmp (op->name, "beqzalc") == 0
> > +		       || strcmp (op->name, "bnezalc") == 0)
> > +		{
> > +		  if (((word >> 16) & 31) == 0)
> > +		    continue;
> > +		}
> > +	      else if (strcmp (op->name, "bgec") == 0
> > +		       || strcmp (op->name, "bltc") == 0
> > +		       || strcmp (op->name, "bbec") == 0
> > +		       || strcmp (op->name, "bstc") == 0)
> > +		{
> > +		  if (((word >> 16) & 31) == ((word >> 21) & 31)
> > +		      || ((word >> 21) & 31) == 0
> > +		      || ((word >> 16) & 31) == 0)
> > +		    continue;
> > +		}
> > +	      else if (strcmp (op->name, "beqc") == 0
> > +		       || strcmp (op->name, "bnec") == 0)
> > +		{
> > +		  if (((word >> 21) & 31) >= ((word >> 16) & 31)
> > +		      || ((word >> 21) & 31) == 0)
> > +		    continue;
> > +		}
> > +	      else if (strcmp (op->name, "bovc") == 0
> > +		       || strcmp (op->name, "bnvc") == 0)
> > +		{
> > +		  if (((word >> 21) & 31) < ((word >> 16) & 31))
> > +		    continue;
> > +		}
> > +	      else if (strcmp (op->name, "beqzc") == 0
> > +		       || strcmp (op->name, "bnezc") == 0)
> > +		{
> > +		  if (((word >> 21) & 31) == 0)
> > +		    continue;
> > +		}
> 
> Looks like this is just reinforcing the restrictions from the OP_*s,
> is that right?  If so, I think it would be cleaner to use the
> mips_operand information rather than checks for specific instructions.

I agree with you that the code could be better here.  The problem is that
for some of the R6 instructions the match and mask fields are identical 
(one example is the bnvc and bnec instructions).  Currently the print_insn_mips 
function uses the match and mask fields to find the first instruction in the 
opcode table which matches the instruction to disassemble.  Then it takes each 
of the operands in turn and checks that they are valid.  This approach will obviously 
not work when decoding some R6 instructions.  The current fix is to skip over 
R6 instructions where the operands don't match (which as we said before is not 
very maintainable).  We could do a more generic fix, but that would require rewriting 
the print_insn_mips, print_insn_args, and print_insn_arg functions to find an 
instruction in the opcode table where firstly the match and mask fields match the 
instruction to disassemble; and secondly all the operand constraints are met.  If 
this is the case the instruction could then be printed out.

I was wondering what you felt would be the best approach here?


Regards,


Andrew

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Add support for MIPS64r6
  2014-05-14 11:23   ` Andrew Bennett
@ 2014-05-14 20:03     ` Richard Sandiford
  2014-06-19 16:28       ` Andrew Bennett
  0 siblings, 1 reply; 14+ messages in thread
From: Richard Sandiford @ 2014-05-14 20:03 UTC (permalink / raw)
  To: Andrew Bennett; +Cc: binutils, Rich Fuhler, Matthew Fortune, Saeed Ghazanfar

Andrew Bennett <Andrew.Bennett@imgtec.com> writes:
>> > @@ -1089,7 +1146,8 @@ struct mips_opcode
>> >     (mips_isa_table[(Y & INSN_ISA_MASK) - 1] >> ((X & INSN_ISA_MASK) - 1)) &
>> 1
>> >     is non-zero.  */
>> >  static const unsigned int mips_isa_table[] =
>> > -  { 0x0001, 0x0003, 0x0607, 0x1e0f, 0x3e1f, 0x0a23, 0x3e63, 0x3ebf, 0x3fff
>> };
>> > +  { 0x0001, 0x0003, 0x0607, 0x1e0f, 0x3e1f, 0x0a23, 0x3e63, 0x3ebf, 0x3fff,
>> > +    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7e63, 0xffff };
>> 
>> Is it really true that r6 allows everything, given the incompatibility?
>
> The problem is that the removed instructions in R6 come from different
> ISAs.  One approach to solve this is to describe in the membership
> field the different ISAs an instruction belongs to.  This would
> require us to create a large amount of different ISA combinations
> which is hard to manage.  A cleaner approach (and implemented in the
> patch) is to say that R6 is an extension of R5 and then to deal with
> the removed instructions by adding instruction exclusions for R6.

OK, sounds good, thanks.  Please add a comment along those lines.

>> > @@ -1426,9 +1542,27 @@ print_insn_args (struct disassemble_info *info,
>> >  		infprintf (is, "$%d,%d", reg, sel);
>> >  	    }
>> >  	  else
>> > -	    print_insn_arg (info, &state, opcode, operand, base_pc,
>> > -			    mips_extract_operand (operand, insn));
>> > -	  if (*s == 'm' || *s == '+')
>> > +	    {
>> > +	      bfd_vma base_pc = insn_pc;
>> > +
>> > +	      /* Adjust the PC relative base so that branch/jump insns use
>> > +		 the following PC as the base but genuinely PC relative
>> > +		 operands use the current PC.  */
>> > +	      if (operand->type == OP_PCREL)
>> > +		{
>> > +		  const struct mips_pcrel_operand *pcrel_op;
>> > +
>> > +		  pcrel_op = (const struct mips_pcrel_operand *) operand;
>> > +		  /* The include_isa_bit flag is sufficient to distinguish
>> > +		     branch/jump from other PC relative operands.  */
>> > +		  if (pcrel_op->include_isa_bit)
>> > +		    base_pc += length;
>> > +		}
>> > +
>> > +	      print_insn_arg (info, &state, opcode, operand, base_pc,
>> > +			      mips_extract_operand (operand, insn));
>> > +	    }
>> > +	  if (*s == 'm' || *s == '+' || *s == '-')
>> >  	    ++s;
>> >  	  break;
>> >  	}
>> > @@ -1494,9 +1628,60 @@ print_insn_mips (bfd_vma memaddr,
>> >  	      && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
>> >  	      && (word & op->mask) == op->match)
>> >  	    {
>> > +	      if (strcmp (op->name, "bgezc") == 0
>> > +		  || strcmp (op->name, "bltzc") == 0
>> > +		  || strcmp (op->name, "bgezalc") == 0
>> > +		  || strcmp (op->name, "bltzalc") == 0)
>> > +		{
>> > +		  if (((word >> 16) & 31) != ((word >> 21) & 31)
>> > +		      || ((word >> 16) & 31) == 0)
>> > +		    continue;
>> > +		}
>> > +	      else if (strcmp (op->name, "blezalc") == 0
>> > +		       || strcmp (op->name, "bgtzalc") == 0
>> > +		       || strcmp (op->name, "blezc") == 0
>> > +		       || strcmp (op->name, "bgtzc") == 0
>> > +		       || strcmp (op->name, "beqzalc") == 0
>> > +		       || strcmp (op->name, "bnezalc") == 0)
>> > +		{
>> > +		  if (((word >> 16) & 31) == 0)
>> > +		    continue;
>> > +		}
>> > +	      else if (strcmp (op->name, "bgec") == 0
>> > +		       || strcmp (op->name, "bltc") == 0
>> > +		       || strcmp (op->name, "bbec") == 0
>> > +		       || strcmp (op->name, "bstc") == 0)
>> > +		{
>> > +		  if (((word >> 16) & 31) == ((word >> 21) & 31)
>> > +		      || ((word >> 21) & 31) == 0
>> > +		      || ((word >> 16) & 31) == 0)
>> > +		    continue;
>> > +		}
>> > +	      else if (strcmp (op->name, "beqc") == 0
>> > +		       || strcmp (op->name, "bnec") == 0)
>> > +		{
>> > +		  if (((word >> 21) & 31) >= ((word >> 16) & 31)
>> > +		      || ((word >> 21) & 31) == 0)
>> > +		    continue;
>> > +		}
>> > +	      else if (strcmp (op->name, "bovc") == 0
>> > +		       || strcmp (op->name, "bnvc") == 0)
>> > +		{
>> > +		  if (((word >> 21) & 31) < ((word >> 16) & 31))
>> > +		    continue;
>> > +		}
>> > +	      else if (strcmp (op->name, "beqzc") == 0
>> > +		       || strcmp (op->name, "bnezc") == 0)
>> > +		{
>> > +		  if (((word >> 21) & 31) == 0)
>> > +		    continue;
>> > +		}
>> 
>> Looks like this is just reinforcing the restrictions from the OP_*s,
>> is that right?  If so, I think it would be cleaner to use the
>> mips_operand information rather than checks for specific instructions.
>
> I agree with you that the code could be better here.  The problem is
> that for some of the R6 instructions the match and mask fields are
> identical (one example is the bnvc and bnec instructions).  Currently
> the print_insn_mips function uses the match and mask fields to find
> the first instruction in the opcode table which matches the
> instruction to disassemble.  Then it takes each of the operands in
> turn and checks that they are valid.  This approach will obviously not
> work when decoding some R6 instructions.  The current fix is to skip
> over R6 instructions where the operands don't match (which as we said
> before is not very maintainable).  We could do a more generic fix, but
> that would require rewriting the print_insn_mips, print_insn_args, and
> print_insn_arg functions to find an instruction in the opcode table
> where firstly the match and mask fields match the instruction to
> disassemble; and secondly all the operand constraints are met.  If
> this is the case the instruction could then be printed out.
>
> I was wondering what you felt would be the best approach here?

Yeah, rewriting it to treat the new mips_operand type as part of the
matching criteria sounds better to me.  I realise that might be quite
invasive, but to be fair, it wasn't easy to predict that this would
happen when the code was written :-)  I think we should extend what's
there rather than work around it.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [PATCH] Add support for MIPS64r6
  2014-05-14 20:03     ` Richard Sandiford
@ 2014-06-19 16:28       ` Andrew Bennett
  2014-06-22 11:56         ` Richard Sandiford
  0 siblings, 1 reply; 14+ messages in thread
From: Andrew Bennett @ 2014-06-19 16:28 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: binutils, Rich Fuhler, Matthew Fortune, Saeed Ghazanfar

[-- Attachment #1: Type: text/plain, Size: 18680 bytes --]

> From: Richard Sandiford [mailto:rdsandiford@googlemail.com]
> Sent: 14 May 2014 21:03
> To: Andrew Bennett
> Cc: binutils@sourceware.org; Rich Fuhler; Matthew Fortune; Saeed Ghazanfar
> Subject: Re: [PATCH] Add support for MIPS64r6
> 
> Andrew Bennett <Andrew.Bennett@imgtec.com> writes:
> >> > @@ -1089,7 +1146,8 @@ struct mips_opcode
> >> >     (mips_isa_table[(Y & INSN_ISA_MASK) - 1] >> ((X & INSN_ISA_MASK) -
> 1)) &
> >> 1
> >> >     is non-zero.  */
> >> >  static const unsigned int mips_isa_table[] =
> >> > -  { 0x0001, 0x0003, 0x0607, 0x1e0f, 0x3e1f, 0x0a23, 0x3e63, 0x3ebf,
> 0x3fff
> >> };
> >> > +  { 0x0001, 0x0003, 0x0607, 0x1e0f, 0x3e1f, 0x0a23, 0x3e63, 0x3ebf,
> 0x3fff,
> >> > +    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7e63, 0xffff };
> >>
> >> Is it really true that r6 allows everything, given the incompatibility?
> >
> > The problem is that the removed instructions in R6 come from different
> > ISAs.  One approach to solve this is to describe in the membership
> > field the different ISAs an instruction belongs to.  This would
> > require us to create a large amount of different ISA combinations
> > which is hard to manage.  A cleaner approach (and implemented in the
> > patch) is to say that R6 is an extension of R5 and then to deal with
> > the removed instructions by adding instruction exclusions for R6.
> 
> OK, sounds good, thanks.  Please add a comment along those lines.
> 
> >> > @@ -1426,9 +1542,27 @@ print_insn_args (struct disassemble_info *info,
> >> >  		infprintf (is, "$%d,%d", reg, sel);
> >> >  	    }
> >> >  	  else
> >> > -	    print_insn_arg (info, &state, opcode, operand, base_pc,
> >> > -			    mips_extract_operand (operand, insn));
> >> > -	  if (*s == 'm' || *s == '+')
> >> > +	    {
> >> > +	      bfd_vma base_pc = insn_pc;
> >> > +
> >> > +	      /* Adjust the PC relative base so that branch/jump insns use
> >> > +		 the following PC as the base but genuinely PC relative
> >> > +		 operands use the current PC.  */
> >> > +	      if (operand->type == OP_PCREL)
> >> > +		{
> >> > +		  const struct mips_pcrel_operand *pcrel_op;
> >> > +
> >> > +		  pcrel_op = (const struct mips_pcrel_operand *) operand;
> >> > +		  /* The include_isa_bit flag is sufficient to distinguish
> >> > +		     branch/jump from other PC relative operands.  */
> >> > +		  if (pcrel_op->include_isa_bit)
> >> > +		    base_pc += length;
> >> > +		}
> >> > +
> >> > +	      print_insn_arg (info, &state, opcode, operand, base_pc,
> >> > +			      mips_extract_operand (operand, insn));
> >> > +	    }
> >> > +	  if (*s == 'm' || *s == '+' || *s == '-')
> >> >  	    ++s;
> >> >  	  break;
> >> >  	}
> >> > @@ -1494,9 +1628,60 @@ print_insn_mips (bfd_vma memaddr,
> >> >  	      && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
> >> >  	      && (word & op->mask) == op->match)
> >> >  	    {
> >> > +	      if (strcmp (op->name, "bgezc") == 0
> >> > +		  || strcmp (op->name, "bltzc") == 0
> >> > +		  || strcmp (op->name, "bgezalc") == 0
> >> > +		  || strcmp (op->name, "bltzalc") == 0)
> >> > +		{
> >> > +		  if (((word >> 16) & 31) != ((word >> 21) & 31)
> >> > +		      || ((word >> 16) & 31) == 0)
> >> > +		    continue;
> >> > +		}
> >> > +	      else if (strcmp (op->name, "blezalc") == 0
> >> > +		       || strcmp (op->name, "bgtzalc") == 0
> >> > +		       || strcmp (op->name, "blezc") == 0
> >> > +		       || strcmp (op->name, "bgtzc") == 0
> >> > +		       || strcmp (op->name, "beqzalc") == 0
> >> > +		       || strcmp (op->name, "bnezalc") == 0)
> >> > +		{
> >> > +		  if (((word >> 16) & 31) == 0)
> >> > +		    continue;
> >> > +		}
> >> > +	      else if (strcmp (op->name, "bgec") == 0
> >> > +		       || strcmp (op->name, "bltc") == 0
> >> > +		       || strcmp (op->name, "bbec") == 0
> >> > +		       || strcmp (op->name, "bstc") == 0)
> >> > +		{
> >> > +		  if (((word >> 16) & 31) == ((word >> 21) & 31)
> >> > +		      || ((word >> 21) & 31) == 0
> >> > +		      || ((word >> 16) & 31) == 0)
> >> > +		    continue;
> >> > +		}
> >> > +	      else if (strcmp (op->name, "beqc") == 0
> >> > +		       || strcmp (op->name, "bnec") == 0)
> >> > +		{
> >> > +		  if (((word >> 21) & 31) >= ((word >> 16) & 31)
> >> > +		      || ((word >> 21) & 31) == 0)
> >> > +		    continue;
> >> > +		}
> >> > +	      else if (strcmp (op->name, "bovc") == 0
> >> > +		       || strcmp (op->name, "bnvc") == 0)
> >> > +		{
> >> > +		  if (((word >> 21) & 31) < ((word >> 16) & 31))
> >> > +		    continue;
> >> > +		}
> >> > +	      else if (strcmp (op->name, "beqzc") == 0
> >> > +		       || strcmp (op->name, "bnezc") == 0)
> >> > +		{
> >> > +		  if (((word >> 21) & 31) == 0)
> >> > +		    continue;
> >> > +		}
> >>
> >> Looks like this is just reinforcing the restrictions from the OP_*s,
> >> is that right?  If so, I think it would be cleaner to use the
> >> mips_operand information rather than checks for specific instructions.
> >
> > I agree with you that the code could be better here.  The problem is
> > that for some of the R6 instructions the match and mask fields are
> > identical (one example is the bnvc and bnec instructions).  Currently
> > the print_insn_mips function uses the match and mask fields to find
> > the first instruction in the opcode table which matches the
> > instruction to disassemble.  Then it takes each of the operands in
> > turn and checks that they are valid.  This approach will obviously not
> > work when decoding some R6 instructions.  The current fix is to skip
> > over R6 instructions where the operands don't match (which as we said
> > before is not very maintainable).  We could do a more generic fix, but
> > that would require rewriting the print_insn_mips, print_insn_args, and
> > print_insn_arg functions to find an instruction in the opcode table
> > where firstly the match and mask fields match the instruction to
> > disassemble; and secondly all the operand constraints are met.  If
> > this is the case the instruction could then be printed out.
> >
> > I was wondering what you felt would be the best approach here?
> 
> Yeah, rewriting it to treat the new mips_operand type as part of the
> matching criteria sounds better to me.  I realise that might be quite
> invasive, but to be fair, it wasn't easy to predict that this would
> happen when the code was written :-)  I think we should extend what's
> there rather than work around it.

An updated r6 patch is attached that addresses the comments on both this and
the previous email.  I have also added in gas testsuite support for r6 in the
manner described previously.  

The ChangeLog entry is below and the two r6 patches are attached.

Ok to commit?

Regards,


Andrew


/
 	* configure.ac: Add mips*-img-elf* triple.
 	* configure: Regenerate.

bfd/
 	* aoutx.h (NAME (aout, machine_type)): Add mips32r6 and mips64r6.
 	* archures.c (bfd_architecture): Likewise.
 	* bfd-in2.h (bfd_architecture): Likewise.
 	(bfd_reloc_code_real): Add relocs BFD_RELOC_MIPS_21_PCREL_S2,
 	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3 and
 	BFD_RELOC_MIPS_19_PCREL_S2.
 	* cpu-mips.c (arch_info_struct): Add mips32r6 and mips64r6.
 	* config.bfd: Add mips*-img-elf* triple.
 	* elf32-mips.c: Define relocs R_MIPS_PC21_S2, R_MIPS_PC26_S2
 	R_MIPS_PC18_S3, R_MIPS_PC19_S2, R_MIPS_PCHI16 and R_MIPS_PCLO16.
 	(mips_reloc_map): Add entries for BFD_RELOC_MIPS_21_PCREL_S2,
 	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
 	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
 	BFD_RELOC_LO16_PCREL.
 	* elf64-mips.c: Define partial inplace and non-partial
 	inplace relocs R_MIPS_PC21_S2, R_MIPS_PC26_S2, R_MIPS_PC18_S3,
 	R_MIPS_PC19_S2, R_MIPS_PCHI16 and R_MIPS_PCLO16.
 	(mips_reloc_map): Add entries for BFD_RELOC_MIPS_21_PCREL_S2,
 	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
 	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
 	BFD_RELOC_LO16_PCREL.
 	* elfn32-mips.c: Define partial inplace and non-partial
 	inplace relocs R_MIPS_PC21_S2, R_MIPS_PC26_S2, R_MIPS_PC18_S3,
 	R_MIPS_PC19_S2, R_MIPS_PCHI16 and R_MIPS_PCLO16.
 	(mips_reloc_map): Add entries for BFD_RELOC_MIPS_21_PCREL_S2,
 	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
 	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
 	BFD_RELOC_LO16_PCREL.
 	* elfxx-mips.c (MIPSR6_P): New define.
 	(mipsr6_exec_plt_entry): New array.
	(hi16_reloc_p): Add support for R_MIPS_PCHI16.
	(lo16_reloc_p): Add support for R_MIPS_PCLO16.
 	(aligned_pcrel_reloc_p): New function.
 	(mips_elf_relocation_needs_la25_stub): Add support for relocs:
 	R_MIPS_PC21_S2 and R_MIPS_PC26_S2.
 	(mips_elf_calculate_relocation): Add support for relocs:
 	R_MIPS_PC21_S2, R_MIPS_PC26_S2, R_MIPS_PC18_S3, R_MIPS_PC19_S2,
 	R_MIPS_PCHI16 and R_MIPS_PCLO16. Also allow relocs R_MIPS_PC16 and
 	R_MIPS_GNU_REL16_S2 to support partial inplace.
 	(_bfd_elf_mips_mach): Add support for mips32r6 and mips64r6.
	(mips_elf_add_lo16_rel_addend): Add support for R_MIPS_PCHI16.
 	(_bfd_mips_elf_check_relocs): Add support for relocs: 
	R_MIPS_PC21_S2 and R_MIPS_PC26_S2.
 	(_bfd_mips_elf_relocate_section): Add a check for unaligned
 	pc relative relocs.
 	(_bfd_mips_elf_finish_dynamic_symbol): Add support for MIPS r6
 	plt entry.
 	(mips_set_isa_flags): Add support for mips32r6 and mips64r6.
 	(mips_32bit_flags_p): Add supprt for mips32r6.
 	(_bfd_mips_elf_print_private_bfd_data): Add support for mips32r6 
	and mips64r6.
 	* libbfd.h (bfd_reloc_code_real_names): Add entries for
 	BFD_RELOC_MIPS_21_PCREL_S2, BFD_RELOC_MIPS_26_PCREL_S2,
 	BFD_RELOC_MIPS_18_PCREL_S3 and BFD_RELOC_MIPS_19_PCREL_S2.
 	* reloc.c: Document relocs BFD_RELOC_MIPS_21_PCREL_S2,
 	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3 and
 	BFD_RELOC_MIPS_19_PCREL_S2.

binutils/
 	* readelf.c (get_machine_flags): Add support for mips32r6 and
 	mips64r6.

elfcpp/
 	* mips.h (E_MIPS_ARCH_32R6, E_MIPS_ARCH_64R6): New enum constants.

gas/
 	* config/tc-mips.c (mips_nan2008): New variable.
	(mips_flag_nan2008): Removed variable.
	(ISA_IS_R6): New define.
 	(ISA_HAS_64BIT_REGS): Add mips64r6.
 	(ISA_HAS_DROR): Likewise.
 	(ISA_HAS_64BIT_FPRS): Add mips32r6 and mips64r6.
 	(ISA_HAS_ROR): Likewise.
 	(ISA_HAS_ODD_SINGLE_FPR): Likewise.
 	(ISA_HAS_MXHC1): Likewise.
 	(hilo_interlocks): Likewise.
 	(md_longopts): Likewise.
	(ISA_HAS_LEGACY_NAN): New define.
 	(options): Add OPTION_MIPS32R6 and OPTION_MIPS64R6.
 	(mips_ase): Add fields mips32_rem_rev, mips64_rem_rev,
 	micromips32_rem_rev and micromips64_rem_rev.
 	(mips_ases): Updated to add which ISA an ASE was removed in.
 	(mips_isa_rev): Add support for mips32r6 and mips64r6.
 	(mips_check_isa_supports_ase): Add support to check if an ASE
 	has been removed in the specified MIPS ISA revision.
 	(validate_mips_insn): Skip '-' character.
	(macro_build): Likewise.
	(mips_check_options): Prevent R6 working with fp32, mips16,
	micromips, or branch relaxation. 
	(file_mips_check_options): Set R6 floating point registers to
	64 bit.  Also deal with the nan2008 option.
 	(limited_pcrel_reloc_p): Add relocs: BFD_RELOC_MIPS_21_PCREL_S2,
 	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
 	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
 	BFD_RELOC_LO16_PCREL.
 	(operand_reg_mask): Add support for OP_SAME_RS_RT, OP_CHECK_PREV.
 	(match_check_prev_operand): New function.
 	(match_same_rs_rt_operand): New function.
 	(match_operand): Added entries for: OP_SAME_RS_RT and OP_CHECK_PREV.
 	(insns_between): Added case to deal with forbidden slots.
 	(append_insn): Added support for relocs: BFD_RELOC_MIPS_21_PCREL_S2
 	and BFD_RELOC_MIPS_26_PCREL_S2
 	(match_insn): Add support for operands -A, -B, +' and +".  Also
 	skip '-' character.
 	(mips_percent_op): Add entries for %pcrel_hi and %pcrel_lo.
 	(md_parse_option): Add support for mips32r6 and mips64r6.  Also
	update the nan option handling.
 	(md_pcrel_from): Add cases for relocs: BFD_RELOC_MIPS_21_PCREL_S2,
 	BFD_RELOC_MIPS_26_PCREL_S2. 
 	(mips_force_relocation): Prevent forced relaxation for MIPS r6.
 	(md_apply_fix): Add support for relocs: BFD_RELOC_MIPS_21_PCREL_S2,
 	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
 	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
 	BFD_RELOC_LO16_PCREL.
 	(s_mipsset): Add support for mips32r6 and mips64r6.  
	(s_nan): Update to support the new nan2008 framework.
 	(tc_gen_reloc): Add relocs: BFD_RELOC_MIPS_21_PCREL_S2,
 	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
 	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
 	BFD_RELOC_LO16_PCREL.
	(mips_elf_final_processing): Updated to use the new nan2008 flag
	variable.
 	(mips_cpu_info_table): Add entries for mips32r6 and mips64r6.
 	* configure.in: Add support for mips32r6 and mips64r6.
 	* configure: Regenerate.
 	* configure.tgt: Add mips*-img-elf* target triple.
 	* doc/c-mips.texi: Document the -mips32r6 and -mips64r6 command line
 	options.
	* doc/as.texinfo: Likewise.

gas/testsuite
	* gas/mips/24k-triple-stores-1.s: If testing for r6 prevent 
	non-supported instructions from being tested.
	* gas/mips/24k-triple-stores-2.s: Likewise.
	* gas/mips/24k-triple-stores-3.s: Likewise.
	* gas/mips/24k-triple-stores-6.s: Likewise.
	* gas/mips/add.s: Likewise.
	* gas/mips/beq.s: Likewise.
	* gas/mips/eva.s: Likewise. 
	* gas/mips/ld-zero-3.s: Likewise.
	* gas/mips/mips32-cp2.s: Likewise.
	* gas/mips/mips32.s: Likewise.
	* gas/mips/mips4.s: Likewise.
	* gas/mips/mipsr6@24k-branch-delay-1.d: New file.
	* gas/mips/mipsr6@24k-triple-stores-1.d: New file.
	* gas/mips/mipsr6@24k-triple-stores-2-llsc.d: New file.
	* gas/mips/mipsr6@24k-triple-stores-2.d: New file.  
	* gas/mips/mipsr6@24k-triple-stores-3.d: New file. 
	* gas/mips/mipsr6@24k-triple-stores-6.d: New file.
	* gas/mips/mipsr6@add.d: New file.
	* gas/mips/mipsr6@beq.d: New file.
	* gas/mips/mipsr6@bge.d: New file.
	* gas/mips/mipsr6@bgeu.d: New file. 
	* gas/mips/mipsr6@blt.d: New file.
	* gas/mips/mipsr6@bltu.d: New file.
	* gas/mips/mipsr6@branch-misc-1.d: New file.
	* gas/mips/mipsr6@cache.d: New file.
	* gas/mips/mipsr6@eva.d: New file.
	* gas/mips/mipsr6@jal-svr4pic-noreorder.d: New file.
	* gas/mips/mipsr6@jal-svr4pic.d: New file.
	* gas/mips/mipsr6@ld-zero-3.d: New file.
	* gas/mips/mipsr6@loc-swap-dis.d: New file.
	* gas/mips/mipsr6@mips32-cp2.d: New file.
	* gas/mips/mipsr6@mips32-imm.d: New file. 
	* gas/mips/mipsr6@mips32.d: New file.
	* gas/mips/mipsr6@mips32r2.d: New file.
	* gas/mips/mipsr6@mips4-fp.d: New file.
	* gas/mips/mipsr6@mips4-fp.l: New file.
	* gas/mips/mipsr6@mips4-fp.s: New file.  
	* gas/mips/mipsr6@mips4.d: New file.
	* gas/mips/mipsr6@mips5-fp.d: New file.
	* gas/mips/mipsr6@mips5-fp.l: New file.
	* gas/mips/mipsr6@mips5-fp.s: New file.
	* gas/mips/mipsr6@mips64.d: New file.
	* gas/mips/mipsr6@msa-branch.d: New file.
	* gas/mips/mipsr6@msa.d: New file.
	* gas/mips/mipsr6@pref.d: New file.
	* gas/mips/mipsr6@relax-swap3.d: New file.
	* gas/mips/r6-64-removed.l: New file.
	* gas/mips/r6-64-removed.s: New file.
	* gas/mips/r6-64.d: New file.
	* gas/mips/r6-64.s: New file.
	* gas/mips/r6-removed.l: New file.
	* gas/mips/r6-removed.s: New file.
	* gas/mips/r6.d: New file.
	* gas/mips/r6.s: New file.
	* gas/mips/cache.s: Add r6 instruction varients.
	* gas/mips/mips.exp: Add support for the mips32r6 and mips64r6
	architectures.  Also prevent non r6 supported tests from running.  
	Finally, add in support for running the new r6 tests.
	(run_dump_test_arch): Add support for mipsr6 tests.
	(run_list_test_arch): Add support for using files of the 
	form arch@testname.l . 

include/elf
 	* mips.h: Add relocs: R_MIPS_PC21_S2, R_MIPS_PC26_S2, R_MIPS_PC18_S3,
 	R_MIPS_PC19_S2, R_MIPS_PCHI16 and R_MIPS_PCLO16.
 	(E_MIPS_ARCH_32R6): New define.
 	(E_MIPS_ARCH_64R6): New define.

include/opcode
 	* mips.h (mips_operand_type): Add new entries: OP_SAME_RS_RT and
 	OP_CHECK_PREV.  Add descriptions for the MIPS R6 instruction 
	arguments: -a, -b, -d, -s, -t, -u, -v, -w, -x, -y, -A, -B, +I, 
	+O, +R, +:, +\, +", +;
	(mips_check_prev_operand): New struct.
 	(INSN2_FORBIDDEN_SLOT): New define.
 	(INSN_ISA32R6): New define.
 	(INSN_ISA64R6): New define.
	(INSN_UPTO32R6): New define.
	(INSN_UPTO64R6): New define.
	(mips_isa_table): Add INSN_UPTO32R6 and INSN_UPTO64R6.
 	(ISA_MIPS32R6): New define.
 	(ISA_MIPS64R6): New define.
 	(CPU_MIPS32R6): New define.
 	(CPU_MIPS64R6): New define.
 	(cpu_is_member): Add cases for CPU_MIPS32R6, and CPU_MIPS64R6.

ld/
 	* configure.tgt: Add img*-mips-elf* target triple.
 	* ldmain.c (get_emulation): Add support for -mips32r6 and -mips64r6.

ld/testsuite/
 	* ld-mips-elf/mips-elf.exp: Add support for mips*-img-elf* target
 	triple.

opcodes/
 	* mips-dis.c (mips_arch_choices): Add entries for mips32r6 and
 	mips64r6.
 	(parse_mips_dis_option): Allow MSA and virtualization support for
 	mips64r6.
 	(mips_print_arg_state): Add fields dest_regno and seen_dest.
 	(mips_seen_register): New function.
	(print_insn_arg): 
 	(print_insn_arg): Change return type to be bfd_boolean. 
	Refactored code to use mips_seen_register function.  Add 
	support for OP_SAME_RS_RT, OP_CHECK_PREV.  Changed
	OP_REPEAT_DEST_REG case to print out the register rather than
	aborting.
 	(print_insn_args): Add length argument.  Changed return type to 
	bfd_boolean.  Add code to correctly calculate the instruction 
	address for pc relative instructions.  Return if the call to
	print_insn_arg was successful.
	(DIS_BUF_SIZE): New define.
	(line_dis_buf): New array.
	(line_dis_ptr): New variable.
	(fprintf_dis_buf): New function.
 	(print_insn_mips): Prevent jalx disassembling for r6.  Only output 
	the disassembled instruction if all the arguments are valid.  
	(print_mips16_insn_arg): Changed return type to bfd_boolean. Return
	if the call to print_insn_arg was successful.
	(print_insn_mips16): Only output the disassembled instruction if 
	all the arguments are valid.
	(print_insn_micromips): Likewise.
	* mips-formats.h (PREV_CHECK): New define.
 	* mips-opc.c (decode_mips_operand): Add support for -a, -b, -d, -s,
 	-t, -u, -v, -w, -x, -y, -A, -B, +I, +O, +R, +:, +\, +", +;
 	(RD_pc): New define.
 	(FS): New define.
 	(I37): New define.
 	(I69): New define.
 	(mips_builtin_opcodes): Add MIPS R6 instructions.  Exclude recoded
 	MIPS R6 instructions from MIPS R2 instructions.

[-- Attachment #2: r6.tar.gz --]
[-- Type: application/x-gzip, Size: 66579 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Add support for MIPS64r6
  2014-06-19 16:28       ` Andrew Bennett
@ 2014-06-22 11:56         ` Richard Sandiford
  2014-09-10 21:30           ` Andrew Bennett
  0 siblings, 1 reply; 14+ messages in thread
From: Richard Sandiford @ 2014-06-22 11:56 UTC (permalink / raw)
  To: Andrew Bennett; +Cc: binutils, Rich Fuhler, Matthew Fortune, Saeed Ghazanfar

Andrew Bennett <Andrew.Bennett@imgtec.com> writes:
> diff --git a/bfd/config.bfd b/bfd/config.bfd
> index 1f822f2..fa6b560 100644
> --- a/bfd/config.bfd
> +++ b/bfd/config.bfd
> @@ -1030,7 +1030,7 @@ case "${targ}" in
>      targ_defvec=mips_elf32_trad_le_vec
>      targ_selvecs="mips_elf32_trad_be_vec mips_elf32_ntrad_be_vec mips_elf32_ntrad_le_vec mips_elf64_trad_be_vec mips_elf64_trad_le_vec"
>      ;;
> -  mips*-sde-elf* | mips*-mti-elf*)
> +  mips*-sde-elf* | mips*-mti-elf* | mips*-img-elf*)
>      targ_defvec=mips_elf32_trad_be_vec
>      targ_selvecs="mips_elf32_trad_le_vec mips_elf32_ntrad_be_vec mips_elf32_ntrad_le_vec mips_elf64_trad_be_vec mips_elf64_trad_le_vec"
>      ;;
> diff --git a/configure b/configure
> index 3645571..30b2a50 100755
> --- a/configure
> +++ b/configure
> @@ -3778,7 +3778,7 @@ case "${target}" in
>    microblaze*)
>      noconfigdirs="$noconfigdirs gprof"
>      ;;
> -  mips*-sde-elf* | mips*-mti-elf*)
> +  mips*-sde-elf* | mips*-mti-elf* | mips*-img-elf*)
>      if test x$with_newlib = xyes; then
>        noconfigdirs="$noconfigdirs gprof"
>      fi
> @@ -6983,7 +6983,7 @@ case "${target}" in
>    spu-*-*)
>      target_makefile_frag="config/mt-spu"
>      ;;
> -  mips*-sde-elf* | mips*-mti-elf*)
> +  mips*-sde-elf* | mips*-mti-elf* | mips*-img-elf*)
>      target_makefile_frag="config/mt-sde"
>      ;;
>    mipsisa*-*-elfoabi*)
> diff --git a/configure.ac b/configure.ac
> index 07c3a66..f1d8d0c 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -1106,7 +1106,7 @@ case "${target}" in
>    microblaze*)
>      noconfigdirs="$noconfigdirs gprof"
>      ;;
> -  mips*-sde-elf* | mips*-mti-elf*)
> +  mips*-sde-elf* | mips*-mti-elf* | mips*-img-elf*)
>      if test x$with_newlib = xyes; then
>        noconfigdirs="$noconfigdirs gprof"
>      fi
> @@ -2361,7 +2361,7 @@ case "${target}" in
>    spu-*-*)
>      target_makefile_frag="config/mt-spu"
>      ;;
> -  mips*-sde-elf* | mips*-mti-elf*)
> +  mips*-sde-elf* | mips*-mti-elf* | mips*-img-elf*)
>      target_makefile_frag="config/mt-sde"
>      ;;
>    mipsisa*-*-elfoabi*)
> diff --git a/gas/configure.tgt b/gas/configure.tgt
> index 7d5afa9..11f2688 100644
> --- a/gas/configure.tgt
> +++ b/gas/configure.tgt
> @@ -326,7 +326,8 @@ case ${generic_target} in
>    mips*-*-freebsd* | mips*-*-kfreebsd*-gnu)
>  					fmt=elf em=freebsd ;;
>    mips-*-sysv4*MP* | mips-*-gnu*)	fmt=elf em=tmips ;;
> -  mips*-sde-elf* | mips*-mti-elf*)	fmt=elf em=tmips ;;
> +  mips*-sde-elf* | mips*-mti-elf* | mips*-img-elf*)
> +					fmt=elf em=tmips ;;
>    mips-*-elf* | mips-*-rtems*)		fmt=elf ;;
>    mips-*-netbsd*)			fmt=elf em=tmips ;;
>    mips-*-openbsd*)			fmt=elf em=tmips ;;
> diff --git a/ld/configure.tgt b/ld/configure.tgt
> index 0eb743d..133ded3 100644
> --- a/ld/configure.tgt
> +++ b/ld/configure.tgt
> @@ -454,7 +454,7 @@ mips*vr5000el-*-elf*)	targ_emul=elf32l4300 ;;
>  mips*vr5000-*-elf*)	targ_emul=elf32b4300 ;;
>  mips*el-sde-elf*)	targ_emul=elf32ltsmip
>  			targ_extra_emuls="elf32btsmip elf32ltsmipn32 elf64ltsmip elf32btsmipn32 elf64btsmip" ;;
> -mips*-sde-elf* | mips*-mti-elf*)
> +mips*-sde-elf* | mips*-mti-elf* | mips*-img-elf*)
>  			targ_emul=elf32btsmip
>  			targ_extra_emuls="elf32ltsmip elf32btsmipn32 elf64btsmip elf32ltsmipn32 elf64ltsmip" ;;
>  mips64*el-ps2-elf*)	targ_emul=elf32lr5900n32
> diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp
> index a2632b2..2d3f052 100644
> --- a/ld/testsuite/ld-mips-elf/mips-elf.exp
> +++ b/ld/testsuite/ld-mips-elf/mips-elf.exp
> @@ -55,7 +55,8 @@ if {![istarget mips*-*-*] || ![is_elf_format]} {
>  set has_newabi [expr [istarget *-*-irix6*] \
>  		     || [istarget mips*-*-linux*] \
>  		     || [istarget mips*-sde-elf*] \
> -		     || [istarget mips*-mti-elf*]]
> +		     || [istarget mips*-mti-elf*] \
> +		     || [istarget mips*-img-elf*]]
>  set linux_gnu [expr [istarget mips*-*-linux*]]
>  set embedded_elf [expr [istarget mips*-*-elf]]
> @@ -79,7 +80,7 @@ if { [istarget *-*-irix6*] } {
>      set abi_ldflags(o32) -melf32btsmip_fbsd
>  }
>  if { [istarget mips*-*-linux*] || [istarget mips*-sde-elf*]
> -     || [istarget mips*-mti-elf*] } {
> +     || [istarget mips*-mti-elf*] || [istarget mips*-img-elf*]} {
>      set abi_ldflags(n32) -melf32btsmipn32
>      set abi_ldflags(n64) -melf64btsmip
>  } elseif { [istarget mips64*-*freebsd*] } {

Please add these parts to 0001 rather than 0002.  0001 is OK with
that change, thanks.

> +  HOWTO (R_MIPS_PCLO16,		/* type */
> +	 0,			/* rightshift */
> +	 2,			/* size (0 = byte, 1 = short, 2 = long) */
> +	 16,			/* bitsize */
> +	 TRUE,			/* pc_relative */
> +	 0,			/* bitpos */
> +	 complain_overflow_signed, /* complain_on_overflow */
> +	 _bfd_mips_elf_generic_reloc,   /* special_function */
> +	 "R_MIPS_PCLO16",	/* name */
> +	 TRUE,			/* partial_inplace */
> +	 0x0000ffff,		/* src_mask */
> +	 0x0000ffff,		/* dst_mask */
> +	 TRUE),			/* pcrel_offset */
> +
>  };

I think this should be complain_overflow_dont.

Nit: no blank line at end of brace list.

> @@ -1088,6 +1093,14 @@ static const bfd_vma mips_exec_plt_entry[] =
>    0x03200008	/* jr $25					*/
>  };
 
> +static const bfd_vma mipsr6_exec_plt_entry[] =
> +{
> +  0x3c0f0000,	/* lui $15, %hi(.got.plt entry)			*/
> +  0x01f90000,	/* l[wd] $25, %lo(.got.plt entry)($15)		*/
> +  0x25f80000,	/* addiu $24, $15, %lo(.got.plt entry)		*/
> +  0x03200009	/* jr $25					*/
> +};
> +
>  /* The format of subsequent MIPS16 o32 PLT entries.  We use v0 ($2)
>     and v1 ($3) as temporaries because t8 ($24) and t9 ($25) are not
>     directly addressable.  */

Might be worth adding a comment saying that the JR and ADDIU will
be swapped due to LOAD_INTERLOCKS_P being true.

>      case R_MIPS_PC16:
>      case R_MIPS_GNU_REL16_S2:
> -      value = symbol + _bfd_mips_elf_sign_extend (addend, 18) - p;
> +      if (howto->partial_inplace)
> +	addend = _bfd_mips_elf_sign_extend (addend, 18);
> +      value = symbol + addend - p;
>        overflowed_p = mips_elf_overflow_p (value, 18);
>        value >>= howto->rightshift;
>        value &= howto->dst_mask;
>        break;
>
> +    case R_MIPS_PC21_S2:
> +      if (howto->partial_inplace)
> +	addend = _bfd_mips_elf_sign_extend (addend, 23);
> +      value = symbol + addend - p;
> +      overflowed_p = mips_elf_overflow_p (value, 23);
> +      value >>= howto->rightshift;
> +      value &= howto->dst_mask;
> +      break;
> +
> +    case R_MIPS_PC26_S2:
> +      if (howto->partial_inplace)
> +	addend = _bfd_mips_elf_sign_extend (addend, 28);
> +      value = symbol + addend - p;
> +      overflowed_p = mips_elf_overflow_p (value, 28);
> +      value >>= howto->rightshift;
> +      value &= howto->dst_mask;
> +      break;
> +
> +    case R_MIPS_PC18_S3:
> +      if (howto->partial_inplace)
> +	addend = _bfd_mips_elf_sign_extend (addend, 21);
> +
> +      if ((symbol + addend) & 7)
> +	return bfd_reloc_outofrange;
> +
> +      value = symbol + addend - ((p | 7) ^ 7);
> +      overflowed_p = mips_elf_overflow_p (value, 21);
> +      value >>= howto->rightshift;
> +      value &= howto->dst_mask;
> +      break;
> +
> +    case R_MIPS_PC19_S2:
> +      if (howto->partial_inplace)
> +	addend = _bfd_mips_elf_sign_extend (addend, 21);
> +
> +      if ((symbol + addend) & 3)
> +	return bfd_reloc_outofrange;
> +
> +      value = symbol + addend - p;
> +      overflowed_p = mips_elf_overflow_p (value, 21);
> +      value >>= howto->rightshift;
> +      value &= howto->dst_mask;
> +      break;

I think we should be consistent and check the low 2 bits for all S2s
or none.  Probably all is better (including R_MIPS_GNU_REL16_S2).
I realise it should never happen for insn-to-insn references, but still.

> @@ -1592,55 +1631,73 @@ struct mips_ase
>    int mips64_rev;
>    int micromips32_rev;
>    int micromips64_rev;
> +
> +  /* The architecture revisions for MIPS32, MIPS64, microMIPS32 and microMIPS64
> +     where the ASE was removed or -1 if the extension has not been removed.  */
> +  int mips32_rem_rev;
> +  int mips64_rem_rev;
> +  int micromips32_rem_rev;
> +  int micromips64_rem_rev;
>  };

Sorry, I should have flagged this up last time, but wouldn't it be
better to have just one "rem_rev" field here?  AFAIK there's no
intention of removing ASEs from 32rN but keeping them for 64rN, or
removing them from the standard encoding but keeping them for microMIPS.

With that change, this:

> @@ -1953,6 +2021,16 @@ mips_check_isa_supports_ase (const struct mips_ase *ase)
>  	as_warn (_("the `%s' extension requires %s%d revision %d or greater"),
>  		 ase->name, base, size, min_rev);
>      }
> +  if ((rem_rev > 0 && mips_isa_rev () >= rem_rev)
> +      && (warned_isa & ase->flags) != ase->flags)
> +    {
> +      warned_isa |= ase->flags;
> +      base = mips_opts.micromips ? "microMIPS" : "MIPS";
> +      size = ISA_HAS_64BIT_REGS (mips_opts.isa) ? 64 : 32;
> +      as_warn (_("the `%s' extension was removed in %s%d revision %d"),
> +	       ase->name, base, size, rem_rev);
> +    }
> +
>    if ((ase->flags & FP64_ASES)
>        && mips_opts.fp != 64
>        && (warned_fp32 & ase->flags) != ase->flags)

would become an "else".

> @@ -3665,6 +3743,8 @@ mips_check_options (struct mips_set_options *opts, bfd_boolean abi_checks)
>        if (abi_checks
>  	  && ABI_NEEDS_64BIT_REGS (mips_abi))
>  	as_warn (_("`fp=32' used with a 64-bit ABI"));
> +      if (ISA_IS_R6 (mips_opts.isa))
> +	as_bad (_("`fp=32' used with a MIPS R6 cpu"));
>        break;
>      default:
>        as_bad (_("Unknown size of floating point registers"));
[...]
> @@ -3721,6 +3810,9 @@ file_mips_check_options (void)
>  	       && ISA_HAS_64BIT_FPRS (file_mips_opts.isa))
>  	/* Handle ASEs that require 64-bit float registers, if possible.  */
>  	file_mips_opts.fp = 64;
> +      else if (ISA_IS_R6 (mips_opts.isa))
> +	/* R6 implies 64-bit float registers.  */
> +	file_mips_opts.fp = 64;
>        else
>  	/* 32-bit float registers.  */
>  	file_mips_opts.fp = 32;

When this came up in GCC, it sounded like r6 does support -mfp32 for
-msingle-float (but not otherwise).

> @@ -3673,6 +3753,15 @@ mips_check_options (struct mips_set_options *opts, bfd_boolean abi_checks)
 
>    if (opts->micromips == 1 && opts->mips16 == 1)
>      as_bad (_("`mips16' cannot be used with `micromips'"));
> +  else if (ISA_IS_R6 (mips_opts.isa)
> +	   && (opts->micromips == 1
> +	       || opts->mips16 == 1))
> +    as_fatal (_("neither `micromips' nor `mips16' can be used with "
> +		"`mips32r6' or `mips64r6'"));
> +
> +  if (ISA_IS_R6 (opts->isa) && mips_relax_branch)
> +    as_fatal (_("branch relaxation is not supported in `mips32r6' "
> +		"or `mips64r6'"));
>  }
> 
>  /* Perform consistency checks on the module level options exactly once.

Please make the errors specific: we know whether it's micromips or mips16,
and whether it's mips32r6 or mips64r6.

> @@ -3748,6 +3840,11 @@ file_mips_check_options (void)
>      file_mips_opts.micromips = (CPU_HAS_MICROMIPS (file_mips_opts.arch))
>  				? 1 : 0;
> 
> +  if (mips_nan2008 == -1)
> +    mips_nan2008 = (ISA_HAS_LEGACY_NAN (file_mips_opts.isa)) ? 0 : 1;
> +  else if (!ISA_HAS_LEGACY_NAN (file_mips_opts.isa) && mips_nan2008 == 0)
> +    as_fatal (_("current isa does not support legacy NaN"));
> +
>    /* Some ASEs require 64-bit FPRs, so -mfp32 should stop those ASEs from
>       being selected implicitly.  */
>    if (file_mips_opts.fp != 64)

current isa == mips_cpu_info_from_arch (file_mips_opts.arch)->name

> +  if (operand->check_not_zero && regno == 0)
> +    {
> +      set_insn_error (arg->argnum, _("the source register must not be $0"));
> +      return FALSE;
> +    }
> +
> +  if (operand->check_not_zero && operand->check_not_equal
> +      && regno == 0 && regno == arg->last_regno)
> +    {
> +      set_insn_error (arg->argnum,
> +                      _("the source registers must not be $0 and different"));
> +      return FALSE;
> +    }
> +

This doesn't look right: the second condition can never trigger after
the first.  With this and:

> +  if (operand->check_greater_than && regno <= arg->last_regno)
> +    return FALSE;
> +  else if (operand->check_less_than && regno >= arg->last_regno)
> +    return FALSE;
> +  else if (operand->check_greater_than_or_equal && regno < arg->last_regno)
> +    return FALSE;
> +  else if (operand->check_less_than_or_equal && regno > arg->last_regno)
> +    return FALSE;

...this I think it would be simpler to have three fields: less_than_ok,
equal_ok and greater_than_ok, with more than one being set where necessary.
Probably also zero_ok for consistency.

> @@ -5680,6 +5862,13 @@ match_operand (struct mips_arg_info *arg,
 
>      case OP_REG_INDEX:
>        return match_reg_index_operand (arg, operand);
> +
> +    case OP_SAME_RS_RT:
> +      return match_same_rs_rt_operand (arg, operand);
> +
> +    case OP_CHECK_PREV:
> +      return match_check_prev_operand (arg, operand);
> +
>      }

No blank line before "}".

> +    case BFD_RELOC_MIPS_18_PCREL_S3:
> +      if ((*valP & 0x7) != 0)
> +	as_bad_where (fixP->fx_file, fixP->fx_line,
> +		      _("pc rel from misaligned address (%lx)"),
> +		      (long) *valP);
> +
> +      gas_assert(!fixP->fx_done);
> +      break;
> +
> +    case BFD_RELOC_MIPS_19_PCREL_S2:
> +      if ((*valP & 0x3) != 0)
> +	as_bad_where (fixP->fx_file, fixP->fx_line,
> +		      _("pc rel from misaligned address (%lx)"),
> +		      (long) *valP);
> +
> +      gas_assert(!fixP->fx_done);
> +      break;

"PC-relative access to misaligned address", for consistency with
"branch to misaligned address"?

Nit: space after gas_assert.

> @@ -15856,10 +16181,15 @@ s_nan (int ignore ATTRIBUTE_UNUSED)
 
>    if (i == sizeof (str_2008) - 1
>        && memcmp (input_line_pointer, str_2008, i) == 0)
> -    mips_flag_nan2008 = TRUE;
> +    mips_nan2008 = 1;
>    else if (i == sizeof (str_legacy) - 1
>  	   && memcmp (input_line_pointer, str_legacy, i) == 0)
> -    mips_flag_nan2008 = FALSE;
> +    {
> +      if (ISA_HAS_LEGACY_NAN (file_mips_opts.isa))
> +	mips_nan2008 = 0;
> +      else
> +	as_fatal (_("current isa does not support legacy NaN"));
> +    }
>    else
>      as_bad (_("bad .nan directive"));

Same "current isa" comment as above.

> diff --git a/gas/testsuite/gas/mips/ld-zero-3.s b/gas/testsuite/gas/mips/ld-zero-3.s
> index 7ca414c..15d62ed 100644
> --- a/gas/testsuite/gas/mips/ld-zero-3.s
> +++ b/gas/testsuite/gas/mips/ld-zero-3.s
> @@ -2,7 +2,9 @@
>  foo:
>  	lwu	$0, 0x12345678($2)
>  	ld	$0, 0x12345678($2)
> +.ifndef r6
>  	lld	$0, 0x12345678($2)
> +.endif
> 
>  # Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
>  	.align	4, 0
> @@ -653,7 +680,7 @@ if { [istarget mips*-*-vxworks*] } {
>  					[mips_arch_list_matching mips3 !singlefloat]
>      }
>      run_dump_test_arches "ld-zero"	[mips_arch_list_matching mips1]
> -    run_dump_test_arches "ld-zero-2"	[mips_arch_list_matching mips2 !nollsc]
> +    run_dump_test_arches "ld-zero-2"	[mips_arch_list_matching mips2 !nollsc !mips32r6]
>      run_dump_test_arches "ld-zero-3"	[mips_arch_list_matching mips3 !nollsc]
>      run_dump_test_arches "ld-zero-u"	[mips_arch_list_matching micromips]
>      run_dump_test_arches "ld-zero-q"	[mips_arch_list_matching r5900]

Until now the macro code has been updated to handle reduced-range offsets,
so that "lld $0, 0x12345678($2)" would still work.  It would mean extending:

    case M_LL_AB:
      s = "ll";
      fmt = MEM12_FMT;
      offbits = (mips_opts.micromips ? 12 : 16);
      goto ld;
    case M_LLD_AB:
      s = "lld";
      fmt = MEM12_FMT;
      offbits = (mips_opts.micromips ? 12 : 16);
      goto ld;

to handle the r6 case.

On the other hand, macros are an abomination so personally I wouldn't
mind if we say that they're deprecated for r6 and later.

> @@ -1206,4 +1233,9 @@ if { [istarget mips*-*-vxworks*] } {
>      run_dump_test "module-override"
>      run_dump_test "module-defer-warn1"
>      run_list_test "module-defer-warn2" -32
> +
> +    run_dump_test_arches "r6"		[mips_arch_list_matching mips32r6 !micromips]
> +    run_dump_test_arches "r6-64"	[mips_arch_list_matching mips64r6 !micromips]
> +    run_list_test_arches "r6-removed"	[mips_arch_list_matching mips32r6]
> +    run_list_test_arches "r6-64-removed"	[mips_arch_list_matching mips64r6]
>  }

Are the "!micromips"es here needed?  I think it'd be more robust to drop
them if they're not doing anything at the moment

> @@ -1368,8 +1437,7 @@ print_insn_arg (struct disassemble_info *info,
>        break;
>
>      case OP_REPEAT_DEST_REG:
> -      /* Should always match OP_REPEAT_PREV_REG first.  */
> -      abort ();
> +      print_reg (info, opcode, state->last_reg_type, state->dest_regno);
> 
>      case OP_PC:
>        infprintf (is, "$pc");

Missing break, although rather than have:

>  /* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
>     UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
>     the base address for OP_PCREL operands.  */
> 
> -static void
> +static bfd_boolean
>  print_insn_arg (struct disassemble_info *info,
>  		struct mips_print_arg_state *state,
>  		const struct mips_opcode *opcode,

I think it would be better to have a separate function that checks
these constraints first.  Something like:

  init_print_arg_state (&state);
  for (s = opcode->args; *s; ++s)
    {
      operand = decode_operand (s);
      if (operand)
        switch (operand->type)
          {
          case OP_REG:
          case OP_OPTIONAL_REG:
            {
              const struct mips_reg_operand *reg_op;

              reg_op = (const struct mips_reg_operand *) operand;
              uval = mips_decode_reg_operand (reg_op, uval);
              mips_seen_register (state, uval, reg_op->reg_type);
            }
            break;

          ...your new checks here...
          }
      ...move onto next char...
    }
  return TRUE;

That would avoid having to use a temporary buffer.

Looks good otherwise, thanks.

Richard

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [PATCH] Add support for MIPS64r6
  2014-06-22 11:56         ` Richard Sandiford
@ 2014-09-10 21:30           ` Andrew Bennett
  2014-09-11  9:15             ` Matthew Fortune
  2014-09-13  8:44             ` Richard Sandiford
  0 siblings, 2 replies; 14+ messages in thread
From: Andrew Bennett @ 2014-09-10 21:30 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: binutils, Rich Fuhler, Matthew Fortune, Saeed Ghazanfar

[-- Attachment #1: Type: text/plain, Size: 13153 bytes --]

> -----Original Message-----
> From: Richard Sandiford [mailto:rdsandiford@googlemail.com]
> Sent: 22 June 2014 12:57
> To: Andrew Bennett
> Cc: binutils@sourceware.org; Rich Fuhler; Matthew Fortune; Saeed Ghazanfar
> Subject: Re: [PATCH] Add support for MIPS64r6
> 
> Andrew Bennett <Andrew.Bennett@imgtec.com> writes:
> > diff --git a/bfd/config.bfd b/bfd/config.bfd
> > index 1f822f2..fa6b560 100644
> > --- a/bfd/config.bfd
> > +++ b/bfd/config.bfd
> > @@ -1030,7 +1030,7 @@ case "${targ}" in
> >      targ_defvec=mips_elf32_trad_le_vec
> >      targ_selvecs="mips_elf32_trad_be_vec mips_elf32_ntrad_be_vec
> mips_elf32_ntrad_le_vec mips_elf64_trad_be_vec mips_elf64_trad_le_vec"
> >      ;;
> > -  mips*-sde-elf* | mips*-mti-elf*)
> > +  mips*-sde-elf* | mips*-mti-elf* | mips*-img-elf*)
> >      targ_defvec=mips_elf32_trad_be_vec
> >      targ_selvecs="mips_elf32_trad_le_vec mips_elf32_ntrad_be_vec
> mips_elf32_ntrad_le_vec mips_elf64_trad_be_vec mips_elf64_trad_le_vec"
> >      ;;

[snip]

> 
> That would avoid having to use a temporary buffer.
> 
> Looks good otherwise, thanks.
> 
> Richard

Attached is the updated MIPS R6 patch that addresses your previous comments.
The ChangeLog is below.


Ok to commit?


Many thanks,


Andrew


bfd/
 	* aoutx.h (NAME (aout, machine_type)): Add mips32r6 and mips64r6.
 	* archures.c (bfd_architecture): Likewise.
 	* bfd-in2.h (bfd_architecture): Likewise.
 	(bfd_reloc_code_real): Add relocs BFD_RELOC_MIPS_21_PCREL_S2,
 	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3 and
 	BFD_RELOC_MIPS_19_PCREL_S2.
 	* cpu-mips.c (arch_info_struct): Add mips32r6 and mips64r6.
 	* elf32-mips.c: Define relocs R_MIPS_PC21_S2, R_MIPS_PC26_S2
 	R_MIPS_PC18_S3, R_MIPS_PC19_S2, R_MIPS_PCHI16 and R_MIPS_PCLO16.
 	(mips_reloc_map): Add entries for BFD_RELOC_MIPS_21_PCREL_S2,
 	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
 	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
 	BFD_RELOC_LO16_PCREL.
 	* elf64-mips.c: Define REL, and RELA relocations R_MIPS_PC21_S2,
	R_MIPS_PC26_S2, R_MIPS_PC18_S3, R_MIPS_PC19_S2, R_MIPS_PCHI16
	and R_MIPS_PCLO16.
 	(mips_reloc_map): Add entries for BFD_RELOC_MIPS_21_PCREL_S2,
 	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
 	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
 	BFD_RELOC_LO16_PCREL.
 	* elfn32-mips.c: Likewise.
 	* elfxx-mips.c (MIPSR6_P): New define.
 	(mipsr6_exec_plt_entry): New array.
	(hi16_reloc_p): Add support for R_MIPS_PCHI16.
	(lo16_reloc_p): Add support for R_MIPS_PCLO16.
 	(aligned_pcrel_reloc_p): New function.
 	(mips_elf_relocation_needs_la25_stub): Add support for relocs:
 	R_MIPS_PC21_S2 and R_MIPS_PC26_S2.
 	(mips_elf_calculate_relocation): Add support for relocs:
 	R_MIPS_PC21_S2, R_MIPS_PC26_S2, R_MIPS_PC18_S3, R_MIPS_PC19_S2,
 	R_MIPS_PCHI16 and R_MIPS_PCLO16.
 	(_bfd_elf_mips_mach): Add support for mips32r6 and mips64r6.
	(mips_elf_add_lo16_rel_addend): Add support for R_MIPS_PCHI16.
 	(_bfd_mips_elf_check_relocs): Add support for relocs:
	R_MIPS_PC21_S2 and R_MIPS_PC26_S2.
 	(_bfd_mips_elf_relocate_section): Add a check for unaligned
 	pc relative relocs.
 	(_bfd_mips_elf_finish_dynamic_symbol): Add support for MIPS r6
 	plt entry.
 	(mips_set_isa_flags): Add support for mips32r6 and mips64r6.
 	(_bfd_mips_elf_print_private_bfd_data): Likewise.
 	(mips_32bit_flags_p): Add support for mips32r6.
 	* libbfd.h (bfd_reloc_code_real_names): Add entries for
 	BFD_RELOC_MIPS_21_PCREL_S2, BFD_RELOC_MIPS_26_PCREL_S2,
 	BFD_RELOC_MIPS_18_PCREL_S3 and BFD_RELOC_MIPS_19_PCREL_S2.
 	* reloc.c: Document relocs BFD_RELOC_MIPS_21_PCREL_S2,
 	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3 and
 	BFD_RELOC_MIPS_19_PCREL_S2.

binutils/
 	* readelf.c (get_machine_flags): Add support for mips32r6 and
 	mips64r6.

elfcpp/
 	* mips.h (E_MIPS_ARCH_32R6, E_MIPS_ARCH_64R6): New enum constants.

gas/
 	* config/tc-mips.c (mips_nan2008): New static global.
	(mips_flag_nan2008): Removed.
	(ISA_IS_R6): New define.
 	(ISA_HAS_64BIT_REGS): Add mips64r6.
 	(ISA_HAS_DROR): Likewise.
 	(ISA_HAS_64BIT_FPRS): Add mips32r6 and mips64r6.
 	(ISA_HAS_ROR): Likewise.
 	(ISA_HAS_ODD_SINGLE_FPR): Likewise.
 	(ISA_HAS_MXHC1): Likewise.
 	(hilo_interlocks): Likewise.
 	(md_longopts): Likewise.
	(ISA_HAS_LEGACY_NAN): New define.
 	(options): Add OPTION_MIPS32R6 and OPTION_MIPS64R6.
 	(mips_ase): Add field rem_rev.
 	(mips_ases): Updated to add which ISA an ASE was removed in.
 	(mips_isa_rev): Add support for mips32r6 and mips64r6.
 	(mips_check_isa_supports_ase): Add support to check if an ASE
 	has been removed in the specified MIPS ISA revision.
 	(validate_mips_insn): Skip '-' character.
	(macro_build): Likewise.
	(mips_check_options): Prevent R6 working with fp32, mips16,
	micromips, or branch relaxation.
	(file_mips_check_options): Set R6 floating point registers to
	64 bit.  Also deal with the nan2008 option.
 	(limited_pcrel_reloc_p): Add relocs: BFD_RELOC_MIPS_21_PCREL_S2,
 	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
 	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
 	BFD_RELOC_LO16_PCREL.
 	(operand_reg_mask): Add support for OP_SAME_RS_RT, OP_CHECK_PREV
	and OP_NON_ZERO_REG.
 	(match_check_prev_operand): New static function.
 	(match_same_rs_rt_operand): New static function.
	(match_non_zero_reg_operand): New static function.
 	(match_operand): Added entries for: OP_SAME_RS_RT, OP_CHECK_PREV
	and OP_NON_ZERO_REG.
 	(insns_between): Added case to deal with forbidden slots.
 	(append_insn): Added support for relocs: BFD_RELOC_MIPS_21_PCREL_S2
 	and BFD_RELOC_MIPS_26_PCREL_S2.
 	(match_insn): Add support for operands -A, -B, +' and +".  Also
 	skip '-' character.
 	(mips_percent_op): Add entries for %pcrel_hi and %pcrel_lo.
 	(md_parse_option): Add support for mips32r6 and mips64r6.  Also
	update the nan option handling.
 	(md_pcrel_from): Add cases for relocs: BFD_RELOC_MIPS_21_PCREL_S2,
 	BFD_RELOC_MIPS_26_PCREL_S2.
 	(mips_force_relocation): Prevent forced relaxation for MIPS r6.
 	(md_apply_fix): Add support for relocs: BFD_RELOC_MIPS_21_PCREL_S2,
 	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
 	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
 	BFD_RELOC_LO16_PCREL.
 	(s_mipsset): Add support for mips32r6 and mips64r6.
	(s_nan): Update to support the new nan2008 framework.
 	(tc_gen_reloc): Add relocs: BFD_RELOC_MIPS_21_PCREL_S2,
 	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
 	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
 	BFD_RELOC_LO16_PCREL.
	(mips_elf_final_processing): Updated to use the mips_nan2008.
 	(mips_cpu_info_table): Add entries for mips32r6 and mips64r6.
	(macro): Enable ldc2, sdc2, ll, lld, swc2, sc, scd, cache, pref
	macros for R6.
	(mips_fix_adjustable): Make PC relative R6 relocations relative
	to the symbol and not the section.
 	* configure.ac: Add support for mips32r6 and mips64r6.
 	* configure: Regenerate.
 	* doc/c-mips.texi: Document the -mips32r6 and -mips64r6 command line
 	options.
	* doc/as.texinfo: Likewise.

gas/testsuite
	* gas/mips/24k-triple-stores-1.s: If testing for r6 prevent
	non-supported instructions from being tested.
	* gas/mips/24k-triple-stores-2.s: Likewise.
	* gas/mips/24k-triple-stores-3.s: Likewise.
	* gas/mips/24k-triple-stores-6.s: Likewise.
	* gas/mips/beq.s: Likewise.
	* gas/mips/eva.s: Likewise.
	* gas/mips/ld-zero-3.s: Likewise.
	* gas/mips/mips32-cp2.s: Likewise.
	* gas/mips/mips32.s: Likewise.
	* gas/mips/mips4.s: Likewise.
	* gas/mips/add.s: Don't test the add instructions if r6, and
	add padding.
	* gas/mips/add.d: Check for a triple dot not a nop at the end of the
	disassembly output.
	* gas/mips/micromips@add.d: Likewise.
	* gas/mips/mipsr6@24k-branch-delay-1.d: New file.
	* gas/mips/mipsr6@24k-triple-stores-1.d: New file.
	* gas/mips/mipsr6@24k-triple-stores-2-llsc.d: New file.
	* gas/mips/mipsr6@24k-triple-stores-2.d: New file.
	* gas/mips/mipsr6@24k-triple-stores-3.d: New file.
	* gas/mips/mipsr6@24k-triple-stores-6.d: New file.
	* gas/mips/mipsr6@add.d: New file.
	* gas/mips/mipsr6@attr-gnu-4-1-msingle-float.l: New file.
	* gas/mips/mipsr6@attr-gnu-4-1-msingle-float.s: New file.
	* gas/mips/mipsr6@attr-gnu-4-1-msoft-float.l: New file.
	* gas/mips/mipsr6@attr-gnu-4-1-msoft-float.s: New file.
	* gas/mips/mipsr6@attr-gnu-4-2-mdouble-float.l: New file.
	* gas/mips/mipsr6@attr-gnu-4-2-mdouble-float.s: New file.
	* gas/mips/mipsr6@beq.d: New file.
	* gas/mips/mipsr6@bge.d: New file.
	* gas/mips/mipsr6@bgeu.d: New file.
	* gas/mips/mipsr6@blt.d: New file.
	* gas/mips/mipsr6@bltu.d: New file.
	* gas/mips/mipsr6@branch-misc-1.d: New file.
	* gas/mips/mipsr6@branch-misc-2-64.d: New file.
	* gas/mips/mipsr6@branch-misc-2pic-64.d: New file.
	* gas/mips/mipsr6@branch-misc-4-64.d: New file.
	* gas/mips/mipsr6@cache.d: New file.
	* gas/mips/mipsr6@eva.d: New file.
	* gas/mips/mipsr6@jal-svr4pic-noreorder.d: New file.
	* gas/mips/mipsr6@jal-svr4pic.d: New file.
	* gas/mips/mipsr6@ld-zero-2.d: New file.
	* gas/mips/mipsr6@ld-zero-3.d: New file.
	* gas/mips/mipsr6@loc-swap-dis.d: New file.
	* gas/mips/mipsr6@mips32-cp2.d: New file.
	* gas/mips/mipsr6@mips32-imm.d: New file.
	* gas/mips/mipsr6@mips32.d: New file.
	* gas/mips/mipsr6@mips32r2.d: New file.
	* gas/mips/mipsr6@mips4-fp.d: New file.
	* gas/mips/mipsr6@mips4-fp.l: New file.
	* gas/mips/mipsr6@mips4-fp.s: New file.
	* gas/mips/mipsr6@mips4.d: New file.
	* gas/mips/mipsr6@mips5-fp.d: New file.
	* gas/mips/mipsr6@mips5-fp.l: New file.
	* gas/mips/mipsr6@mips5-fp.s: New file.
	* gas/mips/mipsr6@mips64.d: New file.
	* gas/mips/mipsr6@msa-branch.d: New file.
	* gas/mips/mipsr6@msa.d: New file.
	* gas/mips/mipsr6@pref.d: New file.
	* gas/mips/mipsr6@relax-swap3.d: New file.
	* gas/mips/r6-64-n32.d: New file.
	* gas/mips/r6-64-n64.d: New file.
	* gas/mips/r6-64-removed.l: New file.
	* gas/mips/r6-64-removed.s: New file.
	* gas/mips/r6-64.s: New file.
	* gas/mips/r6-attr-none-double.d: New file.
	* gas/mips/r6-n32.d: New file.
	* gas/mips/r6-n64.d: New file.
	* gas/mips/r6-removed.l: New file.
	* gas/mips/r6-removed.s: New file.
	* gas/mips/r6.d: New file.
	* gas/mips/r6.s: New file.
	* gas/mips/mipsr6@mips32-dsp.d: New file.
	* gas/mips/mipsr6@mips32-dspr2.d: New file.
	* gas/mips/mipsr6@mips32r2-ill.l: New file.
	* gas/mips/mipsr6@mips32r2-ill.s: New file.
	* gas/mips/cache.s: Add r6 instruction varients.
	* gas/mips/mips.exp: Add support for the mips32r6 and mips64r6
	architectures.  Also prevent non r6 supported tests from running.
	Finally, add in support for running the new r6 tests.
	(run_dump_test_arch): Add support for mipsr6 tests.
	(run_list_test_arch): Add support for using files of the
	form arch@testname.l .

include/elf
 	* mips.h: Add relocs: R_MIPS_PC21_S2, R_MIPS_PC26_S2, R_MIPS_PC18_S3,
 	R_MIPS_PC19_S2, R_MIPS_PCHI16 and R_MIPS_PCLO16.
 	(E_MIPS_ARCH_32R6): New define.
 	(E_MIPS_ARCH_64R6): New define.

include/opcode
 	* mips.h (mips_operand_type): Add new entries: OP_SAME_RS_RT,
 	OP_CHECK_PREV and OP_NON_ZERO_REG.  Add descriptions for the MIPS R6
	instruction arguments: -a, -b, -d, -s, -t, -u, -v, -w, -x, -y, -A, -B,
	 +I, +O, +R, +:, +\, +", +;
	(mips_check_prev_operand): New struct.
 	(INSN2_FORBIDDEN_SLOT): New define.
 	(INSN_ISA32R6): New define.
 	(INSN_ISA64R6): New define.
	(INSN_UPTO32R6): New define.
	(INSN_UPTO64R6): New define.
	(mips_isa_table): Add INSN_UPTO32R6 and INSN_UPTO64R6.
 	(ISA_MIPS32R6): New define.
 	(ISA_MIPS64R6): New define.
 	(CPU_MIPS32R6): New define.
 	(CPU_MIPS64R6): New define.
 	(cpu_is_member): Add cases for CPU_MIPS32R6, and CPU_MIPS64R6.

ld/
 	* ldmain.c (get_emulation): Add support for -mips32r6 and -mips64r6.

opcodes/
 	* mips-dis.c (mips_arch_choices): Add entries for mips32r6 and
 	mips64r6.
 	(parse_mips_dis_option): Allow MSA and virtualization support for
 	mips64r6.
 	(mips_print_arg_state): Add fields dest_regno and seen_dest.
 	(mips_seen_register): New function.
 	(print_insn_arg): Refactored code to use mips_seen_register
	function.  Add support for OP_SAME_RS_RT, OP_CHECK_PREV and
	OP_NON_ZERO_REG.  Changed OP_REPEAT_DEST_REG case to print out
	the register rather than aborting.
 	(print_insn_args): Add length argument.  Add code to correctly
	calculate the instruction address for pc relative instructions.
	(validate_insn_args): New static function.
 	(print_insn_mips): Prevent jalx disassembling for r6.  Use
	validate_insn_args.
	(print_insn_micromips): Use validate_insn_args.
	all the arguments are valid.
	* mips-formats.h (PREV_CHECK): New define.
 	* mips-opc.c (decode_mips_operand): Add support for -a, -b, -d, -s,
 	-t, -u, -v, -w, -x, -y, -A, -B, +I, +O, +R, +:, +\, +", +;
 	(RD_pc): New define.
 	(FS): New define.
 	(I37): New define.
 	(I69): New define.
 	(mips_builtin_opcodes): Add MIPS R6 instructions.  Exclude recoded
 	MIPS R6 instructions from MIPS R2 instructions.

[-- Attachment #2: Add-support-for-MIPS-R6.patch.gz --]
[-- Type: application/x-gzip, Size: 74411 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [PATCH] Add support for MIPS64r6
  2014-09-10 21:30           ` Andrew Bennett
@ 2014-09-11  9:15             ` Matthew Fortune
  2014-09-13  8:44             ` Richard Sandiford
  1 sibling, 0 replies; 14+ messages in thread
From: Matthew Fortune @ 2014-09-11  9:15 UTC (permalink / raw)
  To: Andrew Bennett, Richard Sandiford; +Cc: binutils, Rich Fuhler, Saeed Ghazanfar

Andrew Bennett <Andrew.Bennett@imgtec.com> writes:
> bfd/
>  	* aoutx.h (NAME (aout, machine_type)): Add mips32r6 and mips64r6.
>  	* archures.c (bfd_architecture): Likewise.
>  	* bfd-in2.h (bfd_architecture): Likewise.
>  	(bfd_reloc_code_real): Add relocs BFD_RELOC_MIPS_21_PCREL_S2,
>  	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3 and
>  	BFD_RELOC_MIPS_19_PCREL_S2.
>  	* cpu-mips.c (arch_info_struct): Add mips32r6 and mips64r6.
>  	* elf32-mips.c: Define relocs R_MIPS_PC21_S2, R_MIPS_PC26_S2
>  	R_MIPS_PC18_S3, R_MIPS_PC19_S2, R_MIPS_PCHI16 and R_MIPS_PCLO16.
>  	(mips_reloc_map): Add entries for BFD_RELOC_MIPS_21_PCREL_S2,
>  	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
>  	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
>  	BFD_RELOC_LO16_PCREL.
>  	* elf64-mips.c: Define REL, and RELA relocations R_MIPS_PC21_S2,
> 	R_MIPS_PC26_S2, R_MIPS_PC18_S3, R_MIPS_PC19_S2, R_MIPS_PCHI16
> 	and R_MIPS_PCLO16.
>  	(mips_reloc_map): Add entries for BFD_RELOC_MIPS_21_PCREL_S2,
>  	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
>  	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
>  	BFD_RELOC_LO16_PCREL.
>  	* elfn32-mips.c: Likewise.
>  	* elfxx-mips.c (MIPSR6_P): New define.
>  	(mipsr6_exec_plt_entry): New array.
> 	(hi16_reloc_p): Add support for R_MIPS_PCHI16.
> 	(lo16_reloc_p): Add support for R_MIPS_PCLO16.
>  	(aligned_pcrel_reloc_p): New function.
>  	(mips_elf_relocation_needs_la25_stub): Add support for relocs:
>  	R_MIPS_PC21_S2 and R_MIPS_PC26_S2.
>  	(mips_elf_calculate_relocation): Add support for relocs:
>  	R_MIPS_PC21_S2, R_MIPS_PC26_S2, R_MIPS_PC18_S3, R_MIPS_PC19_S2,
>  	R_MIPS_PCHI16 and R_MIPS_PCLO16.
>  	(_bfd_elf_mips_mach): Add support for mips32r6 and mips64r6.
> 	(mips_elf_add_lo16_rel_addend): Add support for R_MIPS_PCHI16.
>  	(_bfd_mips_elf_check_relocs): Add support for relocs:
> 	R_MIPS_PC21_S2 and R_MIPS_PC26_S2.
>  	(_bfd_mips_elf_relocate_section): Add a check for unaligned
>  	pc relative relocs.
>  	(_bfd_mips_elf_finish_dynamic_symbol): Add support for MIPS r6
>  	plt entry.
>  	(mips_set_isa_flags): Add support for mips32r6 and mips64r6.
>  	(_bfd_mips_elf_print_private_bfd_data): Likewise.
>  	(mips_32bit_flags_p): Add support for mips32r6.
>  	* libbfd.h (bfd_reloc_code_real_names): Add entries for
>  	BFD_RELOC_MIPS_21_PCREL_S2, BFD_RELOC_MIPS_26_PCREL_S2,
>  	BFD_RELOC_MIPS_18_PCREL_S3 and BFD_RELOC_MIPS_19_PCREL_S2.
>  	* reloc.c: Document relocs BFD_RELOC_MIPS_21_PCREL_S2,
>  	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3 and
>  	BFD_RELOC_MIPS_19_PCREL_S2.
> 
> binutils/
>  	* readelf.c (get_machine_flags): Add support for mips32r6 and
>  	mips64r6.
> 
> elfcpp/
>  	* mips.h (E_MIPS_ARCH_32R6, E_MIPS_ARCH_64R6): New enum constants.
> 
> gas/
>  	* config/tc-mips.c (mips_nan2008): New static global.
> 	(mips_flag_nan2008): Removed.
> 	(ISA_IS_R6): New define.
>  	(ISA_HAS_64BIT_REGS): Add mips64r6.
>  	(ISA_HAS_DROR): Likewise.
>  	(ISA_HAS_64BIT_FPRS): Add mips32r6 and mips64r6.
>  	(ISA_HAS_ROR): Likewise.
>  	(ISA_HAS_ODD_SINGLE_FPR): Likewise.
>  	(ISA_HAS_MXHC1): Likewise.
>  	(hilo_interlocks): Likewise.
>  	(md_longopts): Likewise.
> 	(ISA_HAS_LEGACY_NAN): New define.
>  	(options): Add OPTION_MIPS32R6 and OPTION_MIPS64R6.
>  	(mips_ase): Add field rem_rev.
>  	(mips_ases): Updated to add which ISA an ASE was removed in.
>  	(mips_isa_rev): Add support for mips32r6 and mips64r6.
>  	(mips_check_isa_supports_ase): Add support to check if an ASE
>  	has been removed in the specified MIPS ISA revision.
>  	(validate_mips_insn): Skip '-' character.
> 	(macro_build): Likewise.
> 	(mips_check_options): Prevent R6 working with fp32, mips16,
> 	micromips, or branch relaxation.
> 	(file_mips_check_options): Set R6 floating point registers to
> 	64 bit.  Also deal with the nan2008 option.
>  	(limited_pcrel_reloc_p): Add relocs: BFD_RELOC_MIPS_21_PCREL_S2,
>  	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
>  	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
>  	BFD_RELOC_LO16_PCREL.
>  	(operand_reg_mask): Add support for OP_SAME_RS_RT, OP_CHECK_PREV
> 	and OP_NON_ZERO_REG.
>  	(match_check_prev_operand): New static function.
>  	(match_same_rs_rt_operand): New static function.
> 	(match_non_zero_reg_operand): New static function.
>  	(match_operand): Added entries for: OP_SAME_RS_RT, OP_CHECK_PREV
> 	and OP_NON_ZERO_REG.
>  	(insns_between): Added case to deal with forbidden slots.
>  	(append_insn): Added support for relocs: BFD_RELOC_MIPS_21_PCREL_S2
>  	and BFD_RELOC_MIPS_26_PCREL_S2.
>  	(match_insn): Add support for operands -A, -B, +' and +".  Also
>  	skip '-' character.
>  	(mips_percent_op): Add entries for %pcrel_hi and %pcrel_lo.
>  	(md_parse_option): Add support for mips32r6 and mips64r6.  Also
> 	update the nan option handling.
>  	(md_pcrel_from): Add cases for relocs: BFD_RELOC_MIPS_21_PCREL_S2,
>  	BFD_RELOC_MIPS_26_PCREL_S2.
>  	(mips_force_relocation): Prevent forced relaxation for MIPS r6.
>  	(md_apply_fix): Add support for relocs: BFD_RELOC_MIPS_21_PCREL_S2,
>  	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
>  	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
>  	BFD_RELOC_LO16_PCREL.
>  	(s_mipsset): Add support for mips32r6 and mips64r6.
> 	(s_nan): Update to support the new nan2008 framework.
>  	(tc_gen_reloc): Add relocs: BFD_RELOC_MIPS_21_PCREL_S2,
>  	BFD_RELOC_MIPS_26_PCREL_S2, BFD_RELOC_MIPS_18_PCREL_S3,
>  	BFD_RELOC_MIPS_19_PCREL_S2, BFD_RELOC_HI16_S_PCREL and
>  	BFD_RELOC_LO16_PCREL.
> 	(mips_elf_final_processing): Updated to use the mips_nan2008.
>  	(mips_cpu_info_table): Add entries for mips32r6 and mips64r6.
> 	(macro): Enable ldc2, sdc2, ll, lld, swc2, sc, scd, cache, pref
> 	macros for R6.
> 	(mips_fix_adjustable): Make PC relative R6 relocations relative
> 	to the symbol and not the section.
>  	* configure.ac: Add support for mips32r6 and mips64r6.
>  	* configure: Regenerate.
>  	* doc/c-mips.texi: Document the -mips32r6 and -mips64r6 command
> line
>  	options.
> 	* doc/as.texinfo: Likewise.
> 
> gas/testsuite
> 	* gas/mips/24k-triple-stores-1.s: If testing for r6 prevent
> 	non-supported instructions from being tested.
> 	* gas/mips/24k-triple-stores-2.s: Likewise.
> 	* gas/mips/24k-triple-stores-3.s: Likewise.
> 	* gas/mips/24k-triple-stores-6.s: Likewise.
> 	* gas/mips/beq.s: Likewise.
> 	* gas/mips/eva.s: Likewise.
> 	* gas/mips/ld-zero-3.s: Likewise.
> 	* gas/mips/mips32-cp2.s: Likewise.
> 	* gas/mips/mips32.s: Likewise.
> 	* gas/mips/mips4.s: Likewise.
> 	* gas/mips/add.s: Don't test the add instructions if r6, and
> 	add padding.
> 	* gas/mips/add.d: Check for a triple dot not a nop at the end of
> the
> 	disassembly output.
> 	* gas/mips/micromips@add.d: Likewise.
> 	* gas/mips/mipsr6@24k-branch-delay-1.d: New file.
> 	* gas/mips/mipsr6@24k-triple-stores-1.d: New file.
> 	* gas/mips/mipsr6@24k-triple-stores-2-llsc.d: New file.
> 	* gas/mips/mipsr6@24k-triple-stores-2.d: New file.
> 	* gas/mips/mipsr6@24k-triple-stores-3.d: New file.
> 	* gas/mips/mipsr6@24k-triple-stores-6.d: New file.
> 	* gas/mips/mipsr6@add.d: New file.
> 	* gas/mips/mipsr6@attr-gnu-4-1-msingle-float.l: New file.
> 	* gas/mips/mipsr6@attr-gnu-4-1-msingle-float.s: New file.
> 	* gas/mips/mipsr6@attr-gnu-4-1-msoft-float.l: New file.
> 	* gas/mips/mipsr6@attr-gnu-4-1-msoft-float.s: New file.
> 	* gas/mips/mipsr6@attr-gnu-4-2-mdouble-float.l: New file.
> 	* gas/mips/mipsr6@attr-gnu-4-2-mdouble-float.s: New file.
> 	* gas/mips/mipsr6@beq.d: New file.
> 	* gas/mips/mipsr6@bge.d: New file.
> 	* gas/mips/mipsr6@bgeu.d: New file.
> 	* gas/mips/mipsr6@blt.d: New file.
> 	* gas/mips/mipsr6@bltu.d: New file.
> 	* gas/mips/mipsr6@branch-misc-1.d: New file.
> 	* gas/mips/mipsr6@branch-misc-2-64.d: New file.
> 	* gas/mips/mipsr6@branch-misc-2pic-64.d: New file.
> 	* gas/mips/mipsr6@branch-misc-4-64.d: New file.
> 	* gas/mips/mipsr6@cache.d: New file.
> 	* gas/mips/mipsr6@eva.d: New file.
> 	* gas/mips/mipsr6@jal-svr4pic-noreorder.d: New file.
> 	* gas/mips/mipsr6@jal-svr4pic.d: New file.
> 	* gas/mips/mipsr6@ld-zero-2.d: New file.
> 	* gas/mips/mipsr6@ld-zero-3.d: New file.
> 	* gas/mips/mipsr6@loc-swap-dis.d: New file.
> 	* gas/mips/mipsr6@mips32-cp2.d: New file.
> 	* gas/mips/mipsr6@mips32-imm.d: New file.
> 	* gas/mips/mipsr6@mips32.d: New file.
> 	* gas/mips/mipsr6@mips32r2.d: New file.
> 	* gas/mips/mipsr6@mips4-fp.d: New file.
> 	* gas/mips/mipsr6@mips4-fp.l: New file.
> 	* gas/mips/mipsr6@mips4-fp.s: New file.
> 	* gas/mips/mipsr6@mips4.d: New file.
> 	* gas/mips/mipsr6@mips5-fp.d: New file.
> 	* gas/mips/mipsr6@mips5-fp.l: New file.
> 	* gas/mips/mipsr6@mips5-fp.s: New file.
> 	* gas/mips/mipsr6@mips64.d: New file.
> 	* gas/mips/mipsr6@msa-branch.d: New file.
> 	* gas/mips/mipsr6@msa.d: New file.
> 	* gas/mips/mipsr6@pref.d: New file.
> 	* gas/mips/mipsr6@relax-swap3.d: New file.
> 	* gas/mips/r6-64-n32.d: New file.
> 	* gas/mips/r6-64-n64.d: New file.
> 	* gas/mips/r6-64-removed.l: New file.
> 	* gas/mips/r6-64-removed.s: New file.
> 	* gas/mips/r6-64.s: New file.
> 	* gas/mips/r6-attr-none-double.d: New file.
> 	* gas/mips/r6-n32.d: New file.
> 	* gas/mips/r6-n64.d: New file.
> 	* gas/mips/r6-removed.l: New file.
> 	* gas/mips/r6-removed.s: New file.
> 	* gas/mips/r6.d: New file.
> 	* gas/mips/r6.s: New file.
> 	* gas/mips/mipsr6@mips32-dsp.d: New file.
> 	* gas/mips/mipsr6@mips32-dspr2.d: New file.
> 	* gas/mips/mipsr6@mips32r2-ill.l: New file.
> 	* gas/mips/mipsr6@mips32r2-ill.s: New file.
> 	* gas/mips/cache.s: Add r6 instruction varients.
> 	* gas/mips/mips.exp: Add support for the mips32r6 and mips64r6
> 	architectures.  Also prevent non r6 supported tests from running.
> 	Finally, add in support for running the new r6 tests.
> 	(run_dump_test_arch): Add support for mipsr6 tests.
> 	(run_list_test_arch): Add support for using files of the
> 	form arch@testname.l .
> 
> include/elf
>  	* mips.h: Add relocs: R_MIPS_PC21_S2, R_MIPS_PC26_S2,
> R_MIPS_PC18_S3,
>  	R_MIPS_PC19_S2, R_MIPS_PCHI16 and R_MIPS_PCLO16.
>  	(E_MIPS_ARCH_32R6): New define.
>  	(E_MIPS_ARCH_64R6): New define.
> 
> include/opcode
>  	* mips.h (mips_operand_type): Add new entries: OP_SAME_RS_RT,
>  	OP_CHECK_PREV and OP_NON_ZERO_REG.  Add descriptions for the MIPS
> R6
> 	instruction arguments: -a, -b, -d, -s, -t, -u, -v, -w, -x, -y, -A,
> -B,
> 	 +I, +O, +R, +:, +\, +", +;
> 	(mips_check_prev_operand): New struct.
>  	(INSN2_FORBIDDEN_SLOT): New define.
>  	(INSN_ISA32R6): New define.
>  	(INSN_ISA64R6): New define.
> 	(INSN_UPTO32R6): New define.
> 	(INSN_UPTO64R6): New define.
> 	(mips_isa_table): Add INSN_UPTO32R6 and INSN_UPTO64R6.
>  	(ISA_MIPS32R6): New define.
>  	(ISA_MIPS64R6): New define.
>  	(CPU_MIPS32R6): New define.
>  	(CPU_MIPS64R6): New define.
>  	(cpu_is_member): Add cases for CPU_MIPS32R6, and CPU_MIPS64R6.
> 
> ld/
>  	* ldmain.c (get_emulation): Add support for -mips32r6 and -
> mips64r6.
> 
> opcodes/
>  	* mips-dis.c (mips_arch_choices): Add entries for mips32r6 and
>  	mips64r6.
>  	(parse_mips_dis_option): Allow MSA and virtualization support for
>  	mips64r6.
>  	(mips_print_arg_state): Add fields dest_regno and seen_dest.
>  	(mips_seen_register): New function.
>  	(print_insn_arg): Refactored code to use mips_seen_register
> 	function.  Add support for OP_SAME_RS_RT, OP_CHECK_PREV and
> 	OP_NON_ZERO_REG.  Changed OP_REPEAT_DEST_REG case to print out
> 	the register rather than aborting.
>  	(print_insn_args): Add length argument.  Add code to correctly
> 	calculate the instruction address for pc relative instructions.
> 	(validate_insn_args): New static function.
>  	(print_insn_mips): Prevent jalx disassembling for r6.  Use
> 	validate_insn_args.
> 	(print_insn_micromips): Use validate_insn_args.
> 	all the arguments are valid.
> 	* mips-formats.h (PREV_CHECK): New define.
>  	* mips-opc.c (decode_mips_operand): Add support for -a, -b, -d, -s,
>  	-t, -u, -v, -w, -x, -y, -A, -B, +I, +O, +R, +:, +\, +", +;
>  	(RD_pc): New define.
>  	(FS): New define.
>  	(I37): New define.
>  	(I69): New define.
>  	(mips_builtin_opcodes): Add MIPS R6 instructions.  Exclude recoded
>  	MIPS R6 instructions from MIPS R2 instructions.

FWIW I have done a review on this code prior to it being sent to the list
and several minor issues have been corrected.  We have had the previous
version of this patch in use for internal R6 development for some time
now and this update addresses a couple of minor issues discovered during
general use. The only serious issue was the lack of macro support for the
reduced displacement fields in instructions like LL/CACHE/PREF etc where
GCC inline ASM using the 'm' constraint would lead to the compiler
assuming support for base+16bit displacement. Micromips relies on the same
solution so this is at least consistent with how reduced displacements
have been handled previously.

Thanks,
Matthew

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Add support for MIPS64r6
  2014-09-10 21:30           ` Andrew Bennett
  2014-09-11  9:15             ` Matthew Fortune
@ 2014-09-13  8:44             ` Richard Sandiford
  2014-09-14 20:31               ` Andrew Bennett
  1 sibling, 1 reply; 14+ messages in thread
From: Richard Sandiford @ 2014-09-13  8:44 UTC (permalink / raw)
  To: Andrew Bennett; +Cc: binutils, Rich Fuhler, Matthew Fortune, Saeed Ghazanfar

Andrew Bennett <Andrew.Bennett@imgtec.com> writes:
> +/* OP_NON_ZERO_REG matcher.  */
> +
> +static bfd_boolean
> +match_non_zero_reg_operand (struct mips_arg_info *arg, const struct mips_operand *operand)

Long line.

> @@ -11044,8 +11294,11 @@ macro (struct mips_cl_insn *ip, char *str)
>        goto ld_st;
>      case M_LWC2_AB:
>        s = "lwc2";
> -      fmt = COP12_FMT;
> -      offbits = (mips_opts.micromips ? 12 : 16);
> +      fmt = (ISA_IS_R6 (mips_opts.isa) ? "E,+:(d)"
> +	     : COP12_FMT);

You do this for all uses of COP12_FMT, so please do it in COP12_FMT itself.

> @@ -11103,13 +11359,19 @@ macro (struct mips_cl_insn *ip, char *str)
>        goto ld_st;
>      case M_LL_AB:
>        s = "ll";
> -      fmt = MEM12_FMT;
> -      offbits = (mips_opts.micromips ? 12 : 16);
> +      fmt = (ISA_IS_R6 (mips_opts.isa) ? "t,+j(b)"
> +	     : MEM12_FMT);
> +      offbits = (mips_opts.micromips ? 12
> +		 : ISA_IS_R6 (mips_opts.isa) ? 9
> +		 : 16);

And here I think we want to put the fmt ?: in a new LL_SC_FMT macro,
for all LL and SC variants.

> @@ -16018,10 +16366,16 @@ s_nan (int ignore ATTRIBUTE_UNUSED)
>  
>    if (i == sizeof (str_2008) - 1
>        && memcmp (input_line_pointer, str_2008, i) == 0)
> -    mips_flag_nan2008 = TRUE;
> +    mips_nan2008 = 1;
>    else if (i == sizeof (str_legacy) - 1
>  	   && memcmp (input_line_pointer, str_legacy, i) == 0)
> -    mips_flag_nan2008 = FALSE;
> +    {
> +      if (ISA_HAS_LEGACY_NAN (file_mips_opts.isa))
> +	mips_nan2008 = 0;
> +      else
> +	as_fatal (_("`%s' does not support legacy NaN"),
> +	          mips_cpu_info_from_isa (file_mips_opts.isa)->name);

This should be as_bad rather than as_fatal.  Fatal errors are good for
bogus command lines, but for directives we should try to continue.

OK with those changes, thanks.

Richard

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [PATCH] Add support for MIPS64r6
  2014-09-13  8:44             ` Richard Sandiford
@ 2014-09-14 20:31               ` Andrew Bennett
  0 siblings, 0 replies; 14+ messages in thread
From: Andrew Bennett @ 2014-09-14 20:31 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: binutils, Rich Fuhler, Matthew Fortune, Saeed Ghazanfar

> From: Richard Sandiford [mailto:rdsandiford@googlemail.com]
> Sent: 13 September 2014 09:45
> To: Andrew Bennett
> Cc: binutils@sourceware.org; Rich Fuhler; Matthew Fortune; Saeed Ghazanfar
> Subject: Re: [PATCH] Add support for MIPS64r6
> 
> Andrew Bennett <Andrew.Bennett@imgtec.com> writes:
> > +/* OP_NON_ZERO_REG matcher.  */
> > +
> > +static bfd_boolean
> > +match_non_zero_reg_operand (struct mips_arg_info *arg, const struct
> mips_operand *operand)
> 
> Long line.
> 
> > @@ -11044,8 +11294,11 @@ macro (struct mips_cl_insn *ip, char *str)
> >        goto ld_st;
> >      case M_LWC2_AB:
> >        s = "lwc2";
> > -      fmt = COP12_FMT;
> > -      offbits = (mips_opts.micromips ? 12 : 16);
> > +      fmt = (ISA_IS_R6 (mips_opts.isa) ? "E,+:(d)"
> > +	     : COP12_FMT);
> 
> You do this for all uses of COP12_FMT, so please do it in COP12_FMT itself.
> 
> > @@ -11103,13 +11359,19 @@ macro (struct mips_cl_insn *ip, char *str)
> >        goto ld_st;
> >      case M_LL_AB:
> >        s = "ll";
> > -      fmt = MEM12_FMT;
> > -      offbits = (mips_opts.micromips ? 12 : 16);
> > +      fmt = (ISA_IS_R6 (mips_opts.isa) ? "t,+j(b)"
> > +	     : MEM12_FMT);
> > +      offbits = (mips_opts.micromips ? 12
> > +		 : ISA_IS_R6 (mips_opts.isa) ? 9
> > +		 : 16);
> 
> And here I think we want to put the fmt ?: in a new LL_SC_FMT macro,
> for all LL and SC variants.
> 
> > @@ -16018,10 +16366,16 @@ s_nan (int ignore ATTRIBUTE_UNUSED)
> >
> >    if (i == sizeof (str_2008) - 1
> >        && memcmp (input_line_pointer, str_2008, i) == 0)
> > -    mips_flag_nan2008 = TRUE;
> > +    mips_nan2008 = 1;
> >    else if (i == sizeof (str_legacy) - 1
> >  	   && memcmp (input_line_pointer, str_legacy, i) == 0)
> > -    mips_flag_nan2008 = FALSE;
> > +    {
> > +      if (ISA_HAS_LEGACY_NAN (file_mips_opts.isa))
> > +	mips_nan2008 = 0;
> > +      else
> > +	as_fatal (_("`%s' does not support legacy NaN"),
> > +	          mips_cpu_info_from_isa (file_mips_opts.isa)->name);
> 
> This should be as_bad rather than as_fatal.  Fatal errors are good for
> bogus command lines, but for directives we should try to continue.
> 
> OK with those changes, thanks.


I have now made these changes, and are ready to commit the patch, but I
forgot to mention that this patch relies on the soft float/single float
patch that Matthew submitted to have clean testsuite results.  Are you 
happy for me to still commit the patch, or shall I wait until Matthew 
has committed his work first?

Many thanks,



Andrew

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2014-09-14 20:31 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-29 19:17 [PATCH] Add support for MIPS64r6 Andrew Bennett
2014-04-29 19:33 ` Andreas Schwab
2014-04-30 12:23   ` Andrew Bennett
2014-05-01 10:05     ` Andrew Bennett
2014-05-01 20:52       ` Richard Sandiford
2014-05-07 17:52 ` Richard Sandiford
2014-05-14 11:23   ` Andrew Bennett
2014-05-14 20:03     ` Richard Sandiford
2014-06-19 16:28       ` Andrew Bennett
2014-06-22 11:56         ` Richard Sandiford
2014-09-10 21:30           ` Andrew Bennett
2014-09-11  9:15             ` Matthew Fortune
2014-09-13  8:44             ` Richard Sandiford
2014-09-14 20:31               ` Andrew Bennett

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).