Discussion:
[PATCH] Add support for MIPS64r6
(too old to reply)
Andrew Bennett
2014-04-29 19:17:08 UTC
Permalink
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-***@imgtec.com>
Matthew Fortune <***@imgtec.com>
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 ***@var{n}}
@sc{gnu} @code{@value{AS}} supports an additional directive to change
the MIPS Instruction Set Architecture level on the fly: @code{.set
-***@var{n}}. @var{n} should be a number from 0 to 5, or 32, 32r2, 64
-or 64r2.
+***@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 ***@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
Andreas Schwab
2014-04-29 19:33:31 UTC
Permalink
Post by Andrew Bennett
* config.sub: Add support for mips32r6 and mips64r6.
This needs to be sent upstream first, which is <config-***@gnu.org>.

Andreas.
--
Andreas Schwab, ***@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
Andrew Bennett
2014-04-30 12:23:16 UTC
Permalink
Post by Andrew Bennett
* config.sub: Add support for mips32r6 and mips64r6.
I have sent this section of the patch to config-patches.

Regards,


Andrew
Andrew Bennett
2014-05-01 10:05:23 UTC
Permalink
Post by Andrew Bennett
Post by Andreas Schwab
Post by Andrew Bennett
* config.sub: Add support for mips32r6 and mips64r6.
This needs to be sent upstream first, which is
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-***@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 <***@gnu.org>


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

Many thanks.


Andrew
Richard Sandiford
2014-05-01 20:51:55 UTC
Permalink
Post by Andrew Bennett
Post by Andrew Bennett
Post by Andreas Schwab
Post by Andrew Bennett
* config.sub: Add support for mips32r6 and mips64r6.
This needs to be sent upstream first, which is
I have sent this section of the patch to config-patches.
The patch has now been committed to the master config.* repository
Date: Thu May 1 12:48:36 2014 +1000
* config.sub (mipsisa32r6, mipsisa64r6): New.
* testsuite/config-sub.data: Add test cases for mipsisa*r6.
Would it be possible for the config.sub in the binutils tree to be
updated?
OK, done for binutils and GCC.

Thanks,
Richard
Richard Sandiford
2014-05-07 17:52:31 UTC
Permalink
Sorry for taking so long to get to this.
Post by Andrew Bennett
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.
http://www.imgtec.com/mips/mips64-architecture.asp
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.
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.
Post by Andrew Bennett
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.
Post by Andrew Bennett
Secondly, updating tests that check for instructions that have been recoded in
Yeah, that sounds like the right way to do it. Or more specifically,
Post by Andrew Bennett
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?
Post by Andrew Bennett
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.
Post by Andrew Bennett
+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.
Post by Andrew Bennett
+ 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.
Post by Andrew Bennett
+ 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.
Post by Andrew Bennett
@@ -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"?
Post by Andrew Bennett
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.
Post by Andrew Bennett
+/* 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...
Post by Andrew Bennett
+
+/* 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.
Post by Andrew Bennett
@@ -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);
- return match_tied_reg_operand (arg, arg->dest_regno);
+ return match_tied_reg_operand (arg, OP_REG_GP, arg->dest_regno);
- return match_tied_reg_operand (arg, arg->last_regno);
+ return match_tied_reg_operand (arg, OP_REG_GP, arg->last_regno);
return match_pc_operand (arg);
Couldn't tell off-hand why you need this (although it looks OK).
Post by Andrew Bennett
@@ -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.
Post by Andrew Bennett
@@ -6571,6 +6838,46 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
}
break;
+ {
+ 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;
+
+ {
+ 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.
Post by Andrew Bennett
@@ -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"?
Post by Andrew Bennett
@@ -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;
+ 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;
+
+ 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.
Post by Andrew Bennett
+ 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?
Post by Andrew Bennett
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 -mips64
@itemx -mips64r2
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
-MIPS64, and MIPS64 Release 2 ISA processors, respectively. You can also
-Directives to override the ISA level}.
+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
@item -mgp32
@itemx -mfp32
@@ -652,8 +655,8 @@ Small data is not supported for SVR4-style PIC.
@kindex @code{.set ***@var{n}}
@sc{gnu} @code{@value{AS}} supports an additional directive to change
-or 64r2.
+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
This needs to be duplicated in as.texinfo.
Post by Andrew Bennett
@@ -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?
Post by Andrew Bennett
@@ -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.
Post by Andrew Bennett
@@ -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".
Post by Andrew Bennett
@@ -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.
Post by Andrew Bennett
/* 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
Andrew Bennett
2014-05-14 11:23:23 UTC
Permalink
Post by Richard Sandiford
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.
Post by Richard Sandiford
Post by Andrew Bennett
+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.
Post by Richard Sandiford
Post by Andrew Bennett
+ 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.
Post by Richard Sandiford
Post by Andrew Bennett
diff --git a/binutils/testsuite/binutils-all/objcopy.exp
b/binutils/testsuite/binutils-all/objcopy.exp
Post by Andrew Bennett
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
Post by Andrew Bennett
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 } {
Post by Andrew Bennett
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.
Post by Richard Sandiford
Post by Andrew Bennett
@@ -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)
Post by Andrew Bennett
+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);
- return match_tied_reg_operand (arg, arg->dest_regno);
+ return match_tied_reg_operand (arg, OP_REG_GP, arg->dest_regno);
- return match_tied_reg_operand (arg, arg->last_regno);
+ return match_tied_reg_operand (arg, OP_REG_GP, arg->last_regno);
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.
Post by Richard Sandiford
Post by Andrew Bennett
@@ -6571,6 +6838,46 @@ append_insn (struct mips_cl_insn *ip, expressionS
*address_expr,
Post by Andrew Bennett
}
break;
+ {
+ 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;
+
+ {
+ 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.
Post by Richard Sandiford
Post by Andrew Bennett
@@ -14462,6 +14836,81 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg
ATTRIBUTE_UNUSED)
Post by Andrew Bennett
md_number_to_chars (buf, *valP, fixP->fx_size);
break;
+ 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;
+
+ 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.
Post by Richard Sandiford
Post by Andrew Bennett
+ 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.
Post by Richard Sandiford
Post by Andrew Bennett
@@ -1089,7 +1146,8 @@ struct mips_opcode
(mips_isa_table[(Y & INSN_ISA_MASK) - 1] >> ((X & INSN_ISA_MASK) - 1)) &
1
Post by Andrew Bennett
is non-zero. */
static const unsigned int mips_isa_table[] =
- { 0x0001, 0x0003, 0x0607, 0x1e0f, 0x3e1f, 0x0a23, 0x3e63, 0x3ebf, 0x3fff
};
Post by Andrew Bennett
+ { 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.
Post by Richard Sandiford
Post by Andrew Bennett
@@ -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
Richard Sandiford
2014-05-14 20:03:05 UTC
Permalink
Post by Andrew Bennett
Post by Richard Sandiford
Post by Andrew Bennett
@@ -1089,7 +1146,8 @@ struct mips_opcode
(mips_isa_table[(Y & INSN_ISA_MASK) - 1] >> ((X & INSN_ISA_MASK) - 1)) &
1
Post by Andrew Bennett
is non-zero. */
static const unsigned int mips_isa_table[] =
- { 0x0001, 0x0003, 0x0607, 0x1e0f, 0x3e1f, 0x0a23, 0x3e63, 0x3ebf, 0x3fff
};
Post by Andrew Bennett
+ { 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.
Post by Andrew Bennett
Post by Richard Sandiford
Post by Andrew Bennett
@@ -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
Andrew Bennett
2014-06-19 16:28:04 UTC
Permalink
Sent: 14 May 2014 21:03
To: Andrew Bennett
Subject: Re: [PATCH] Add support for MIPS64r6
Post by Andrew Bennett
Post by Richard Sandiford
Post by Andrew Bennett
@@ -1089,7 +1146,8 @@ struct mips_opcode
(mips_isa_table[(Y & INSN_ISA_MASK) - 1] >> ((X & INSN_ISA_MASK) -
1)) &
Post by Andrew Bennett
Post by Richard Sandiford
1
Post by Andrew Bennett
is non-zero. */
static const unsigned int mips_isa_table[] =
- { 0x0001, 0x0003, 0x0607, 0x1e0f, 0x3e1f, 0x0a23, 0x3e63, 0x3ebf,
0x3fff
Post by Andrew Bennett
Post by Richard Sandiford
};
Post by Andrew Bennett
+ { 0x0001, 0x0003, 0x0607, 0x1e0f, 0x3e1f, 0x0a23, 0x3e63, 0x3ebf,
0x3fff,
Post by Andrew Bennett
Post by Richard Sandiford
Post by Andrew Bennett
+ 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.
Post by Andrew Bennett
Post by Richard Sandiford
Post by Andrew Bennett
@@ -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/***@24k-branch-delay-1.d: New file.
* gas/mips/***@24k-triple-stores-1.d: New file.
* gas/mips/***@24k-triple-stores-2-llsc.d: New file.
* gas/mips/***@24k-triple-stores-2.d: New file.
* gas/mips/***@24k-triple-stores-3.d: New file.
* gas/mips/***@24k-triple-stores-6.d: New file.
* gas/mips/***@add.d: New file.
* gas/mips/***@beq.d: New file.
* gas/mips/***@bge.d: New file.
* gas/mips/***@bgeu.d: New file.
* gas/mips/***@blt.d: New file.
* gas/mips/***@bltu.d: New file.
* gas/mips/***@branch-misc-1.d: New file.
* gas/mips/***@cache.d: New file.
* gas/mips/***@eva.d: New file.
* gas/mips/***@jal-svr4pic-noreorder.d: New file.
* gas/mips/***@jal-svr4pic.d: New file.
* gas/mips/***@ld-zero-3.d: New file.
* gas/mips/***@loc-swap-dis.d: New file.
* gas/mips/***@mips32-cp2.d: New file.
* gas/mips/***@mips32-imm.d: New file.
* gas/mips/***@mips32.d: New file.
* gas/mips/***@mips32r2.d: New file.
* gas/mips/***@mips4-fp.d: New file.
* gas/mips/***@mips4-fp.l: New file.
* gas/mips/***@mips4-fp.s: New file.
* gas/mips/***@mips4.d: New file.
* gas/mips/***@mips5-fp.d: New file.
* gas/mips/***@mips5-fp.l: New file.
* gas/mips/***@mips5-fp.s: New file.
* gas/mips/***@mips64.d: New file.
* gas/mips/***@msa-branch.d: New file.
* gas/mips/***@msa.d: New file.
* gas/mips/***@pref.d: New file.
* gas/mips/***@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 ***@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.
Richard Sandiford
2014-06-22 11:56:33 UTC
Permalink
Post by Andrew Bennett
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.
Post by Andrew Bennett
+ 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.
Post by Andrew Bennett
@@ -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.
Post by Andrew Bennett
- 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;
+ 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;
+
+ 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;
+
+ 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;
+
+ 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.
Post by Andrew Bennett
@@ -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.
Post by Andrew Bennett
@@ -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".
Post by Andrew Bennett
@@ -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;
as_bad (_("Unknown size of floating point registers"));
[...]
Post by Andrew Bennett
@@ -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).
Post by Andrew Bennett
@@ -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.
Post by Andrew Bennett
@@ -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
Post by Andrew Bennett
+ 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
Post by Andrew Bennett
+ 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.
Post by Andrew Bennett
@@ -5680,6 +5862,13 @@ match_operand (struct mips_arg_info *arg,
return match_reg_index_operand (arg, operand);
+
+ return match_same_rs_rt_operand (arg, operand);
+
+ return match_check_prev_operand (arg, operand);
+
}
No blank line before "}".
Post by Andrew Bennett
+ 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;
+
+ 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.
Post by Andrew Bennett
@@ -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.
Post by Andrew Bennett
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 @@
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.
Post by Andrew Bennett
@@ -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
Post by Andrew Bennett
@@ -1368,8 +1437,7 @@ print_insn_arg (struct disassemble_info *info,
break;
- /* Should always match OP_REPEAT_PREV_REG first. */
- abort ();
+ print_reg (info, opcode, state->last_reg_type, state->dest_regno);
infprintf (is, "$pc");
/* 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
Andrew Bennett
2014-09-10 21:30:28 UTC
Permalink
-----Original Message-----
Sent: 22 June 2014 12:57
To: Andrew Bennett
Subject: Re: [PATCH] Add support for MIPS64r6
Post by Andrew Bennett
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"
Post by Andrew Bennett
;;
- 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"
Post by Andrew Bennett
;;
[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/***@add.d: Likewise.
* gas/mips/***@24k-branch-delay-1.d: New file.
* gas/mips/***@24k-triple-stores-1.d: New file.
* gas/mips/***@24k-triple-stores-2-llsc.d: New file.
* gas/mips/***@24k-triple-stores-2.d: New file.
* gas/mips/***@24k-triple-stores-3.d: New file.
* gas/mips/***@24k-triple-stores-6.d: New file.
* gas/mips/***@add.d: New file.
* gas/mips/***@attr-gnu-4-1-msingle-float.l: New file.
* gas/mips/***@attr-gnu-4-1-msingle-float.s: New file.
* gas/mips/***@attr-gnu-4-1-msoft-float.l: New file.
* gas/mips/***@attr-gnu-4-1-msoft-float.s: New file.
* gas/mips/***@attr-gnu-4-2-mdouble-float.l: New file.
* gas/mips/***@attr-gnu-4-2-mdouble-float.s: New file.
* gas/mips/***@beq.d: New file.
* gas/mips/***@bge.d: New file.
* gas/mips/***@bgeu.d: New file.
* gas/mips/***@blt.d: New file.
* gas/mips/***@bltu.d: New file.
* gas/mips/***@branch-misc-1.d: New file.
* gas/mips/***@branch-misc-2-64.d: New file.
* gas/mips/***@branch-misc-2pic-64.d: New file.
* gas/mips/***@branch-misc-4-64.d: New file.
* gas/mips/***@cache.d: New file.
* gas/mips/***@eva.d: New file.
* gas/mips/***@jal-svr4pic-noreorder.d: New file.
* gas/mips/***@jal-svr4pic.d: New file.
* gas/mips/***@ld-zero-2.d: New file.
* gas/mips/***@ld-zero-3.d: New file.
* gas/mips/***@loc-swap-dis.d: New file.
* gas/mips/***@mips32-cp2.d: New file.
* gas/mips/***@mips32-imm.d: New file.
* gas/mips/***@mips32.d: New file.
* gas/mips/***@mips32r2.d: New file.
* gas/mips/***@mips4-fp.d: New file.
* gas/mips/***@mips4-fp.l: New file.
* gas/mips/***@mips4-fp.s: New file.
* gas/mips/***@mips4.d: New file.
* gas/mips/***@mips5-fp.d: New file.
* gas/mips/***@mips5-fp.l: New file.
* gas/mips/***@mips5-fp.s: New file.
* gas/mips/***@mips64.d: New file.
* gas/mips/***@msa-branch.d: New file.
* gas/mips/***@msa.d: New file.
* gas/mips/***@pref.d: New file.
* gas/mips/***@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/***@mips32-dsp.d: New file.
* gas/mips/***@mips32-dspr2.d: New file.
* gas/mips/***@mips32r2-ill.l: New file.
* gas/mips/***@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 ***@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.
Matthew Fortune
2014-09-11 09:14:50 UTC
Permalink
Post by Andrew Bennett
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.
R_MIPS_PC21_S2 and R_MIPS_PC26_S2.
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.
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/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/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
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
Richard Sandiford
2014-09-13 08:44:46 UTC
Permalink
+/* 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;
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;
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
Andrew Bennett
2014-09-14 20:31:23 UTC
Permalink
Sent: 13 September 2014 09:45
To: Andrew Bennett
Subject: Re: [PATCH] Add support for MIPS64r6
+/* 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;
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;
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

Continue reading on narkive:
Loading...