diff --git a/contrib/binutils/bfd/archures.c b/contrib/binutils/bfd/archures.c index f8aeeef88389..58893b02290b 100644 --- a/contrib/binutils/bfd/archures.c +++ b/contrib/binutils/bfd/archures.c @@ -1,6 +1,6 @@ /* BFD library support routines for architectures. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003 + 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Hacked by John Gilmore and Steve Chamberlain of Cygnus Support. @@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "bfd.h" #include "sysdep.h" @@ -141,10 +141,12 @@ DESCRIPTION .#define bfd_mach_mips6000 6000 .#define bfd_mach_mips7000 7000 .#define bfd_mach_mips8000 8000 +.#define bfd_mach_mips9000 9000 .#define bfd_mach_mips10000 10000 .#define bfd_mach_mips12000 12000 .#define bfd_mach_mips16 16 .#define bfd_mach_mips5 5 +.#define bfd_mach_mips_octeon 6502 .#define bfd_mach_mips_sb1 12310201 {* octal 'SB', 01 *} .#define bfd_mach_mipsisa32 32 .#define bfd_mach_mipsisa32r2 33 diff --git a/contrib/binutils/bfd/bfd-in2.h b/contrib/binutils/bfd/bfd-in2.h index 2464d27e399d..91447a12cbb1 100644 --- a/contrib/binutils/bfd/bfd-in2.h +++ b/contrib/binutils/bfd/bfd-in2.h @@ -8,7 +8,8 @@ /* Main header file for the bfd library -- portable access to object files. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. Contributed by Cygnus Support. @@ -26,7 +27,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __BFD_H_SEEN__ #define __BFD_H_SEEN__ diff --git a/contrib/binutils/bfd/cpu-mips.c b/contrib/binutils/bfd/cpu-mips.c index 01ecc4e40d0b..c232f85d0fce 100644 --- a/contrib/binutils/bfd/cpu-mips.c +++ b/contrib/binutils/bfd/cpu-mips.c @@ -1,6 +1,6 @@ /* bfd back-end for mips support Copyright 1990, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2001, - 2002, 2003 Free Software Foundation, Inc. + 2002, 2003, 2004 Free Software Foundation, Inc. Written by Steve Chamberlain of Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -17,7 +17,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "bfd.h" #include "sysdep.h" @@ -76,6 +76,7 @@ enum I_mips6000, I_mips7000, I_mips8000, + I_mips9000, I_mips10000, I_mips12000, I_mips16, @@ -84,6 +85,7 @@ enum I_mipsisa32r2, I_mipsisa64, I_mipsisa64r2, + I_mipsocteon, I_sb1, }; @@ -108,6 +110,7 @@ static const bfd_arch_info_type arch_info_struct[] = N (32, 32, bfd_mach_mips6000, "mips:6000", FALSE, NN(I_mips6000)), N (64, 64, bfd_mach_mips7000, "mips:7000", FALSE, NN(I_mips7000)), N (64, 64, bfd_mach_mips8000, "mips:8000", FALSE, NN(I_mips8000)), + N (64, 64, bfd_mach_mips9000, "mips:9000", FALSE, NN(I_mips9000)), N (64, 64, bfd_mach_mips10000,"mips:10000", FALSE, NN(I_mips10000)), N (64, 64, bfd_mach_mips12000,"mips:12000", FALSE, NN(I_mips12000)), N (64, 64, bfd_mach_mips16, "mips:16", FALSE, NN(I_mips16)), @@ -116,6 +119,7 @@ static const bfd_arch_info_type arch_info_struct[] = N (32, 32, bfd_mach_mipsisa32r2,"mips:isa32r2", FALSE, NN(I_mipsisa32r2)), 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_mips_octeon,"mips:octeon", FALSE, NN(I_mipsocteon)), N (64, 64, bfd_mach_mips_sb1, "mips:sb1", FALSE, 0), }; diff --git a/contrib/binutils/bfd/elfxx-mips.c b/contrib/binutils/bfd/elfxx-mips.c index 8fb20d8a7e41..0a7495ad5e27 100644 --- a/contrib/binutils/bfd/elfxx-mips.c +++ b/contrib/binutils/bfd/elfxx-mips.c @@ -1,6 +1,6 @@ /* MIPS-specific support for ELF Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Most of the information added by Ian Lance Taylor, Cygnus Support, . @@ -23,7 +23,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* This file handles functionality common to the different MIPS ABI's. */ @@ -4088,6 +4088,12 @@ _bfd_elf_mips_mach (flagword flags) case E_MIPS_MACH_5500: return bfd_mach_mips5500; + case E_MIPS_MACH_9000: + return bfd_mach_mips9000; + + case E_MIPS_MACH_OCTEON: + return bfd_mach_mips_octeon; + case E_MIPS_MACH_SB1: return bfd_mach_mips_sb1; @@ -7142,6 +7148,10 @@ mips_set_isa_flags (bfd *abfd) val = E_MIPS_ARCH_4 | E_MIPS_MACH_5500; break; + case bfd_mach_mips9000: + val = E_MIPS_ARCH_4 | E_MIPS_MACH_9000; + break; + case bfd_mach_mips5000: case bfd_mach_mips7000: case bfd_mach_mips8000: @@ -7154,6 +7164,10 @@ mips_set_isa_flags (bfd *abfd) val = E_MIPS_ARCH_5; break; + case bfd_mach_mips_octeon: + val = E_MIPS_ARCH_64R2 | E_MIPS_MACH_OCTEON; + break; + case bfd_mach_mips_sb1: val = E_MIPS_ARCH_64 | E_MIPS_MACH_SB1; break; @@ -8856,6 +8870,9 @@ struct mips_mach_extension { are ordered topologically with MIPS I extensions listed last. */ static const struct mips_mach_extension mips_mach_extensions[] = { + /* MIPS64r2 extensions. */ + { bfd_mach_mips_octeon, bfd_mach_mipsisa64r2 }, + /* MIPS64 extensions. */ { bfd_mach_mipsisa64r2, bfd_mach_mipsisa64 }, { bfd_mach_mips_sb1, bfd_mach_mipsisa64 }, @@ -8879,6 +8896,7 @@ static const struct mips_mach_extension mips_mach_extensions[] = { { bfd_mach_mips10000, bfd_mach_mips8000 }, { bfd_mach_mips5000, bfd_mach_mips8000 }, { bfd_mach_mips7000, bfd_mach_mips8000 }, + { bfd_mach_mips9000, bfd_mach_mips8000 }, /* VR4100 extensions. */ { bfd_mach_mips4120, bfd_mach_mips4100 }, @@ -8913,11 +8931,26 @@ mips_mach_extends_p (unsigned long base, unsigned long extension) { size_t i; - for (i = 0; extension != base && i < ARRAY_SIZE (mips_mach_extensions); i++) - if (extension == mips_mach_extensions[i].extension) - extension = mips_mach_extensions[i].base; + if (extension == base) + return TRUE; - return extension == base; + if (base == bfd_mach_mipsisa32 + && mips_mach_extends_p (bfd_mach_mipsisa64, extension)) + return TRUE; + + if (base == bfd_mach_mipsisa32r2 + && mips_mach_extends_p (bfd_mach_mipsisa64r2, extension)) + return TRUE; + + for (i = 0; i < ARRAY_SIZE (mips_mach_extensions); i++) + if (extension == mips_mach_extensions[i].extension) + { + extension = mips_mach_extensions[i].base; + if (extension == base) + return TRUE; + } + + return FALSE; } diff --git a/contrib/binutils/gas/config/tc-mips.c b/contrib/binutils/gas/config/tc-mips.c index d6d29799a678..b8ef69eea341 100644 --- a/contrib/binutils/gas/config/tc-mips.c +++ b/contrib/binutils/gas/config/tc-mips.c @@ -1,6 +1,6 @@ /* tc-mips.c -- assemble code for a MIPS chip. Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004 Free Software Foundation, Inc. + 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by the OSF and Ralph Campbell. Written by Keith Knowles and Ralph Campbell, working independently. Modified for ECOFF and R4000 support by Ian Lance Taylor of Cygnus @@ -20,8 +20,8 @@ You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free - Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ #include "as.h" #include "config.h" @@ -33,6 +33,7 @@ #include "opcode/mips.h" #include "itbl-ops.h" #include "dwarf2dbg.h" +#include "dw2gencfi.h" #ifdef DEBUG #define DBG(x) printf x @@ -83,6 +84,25 @@ int mips_flag_pdr = FALSE; int mips_flag_pdr = TRUE; #endif +/* Control generation of error message for unsupported instructions in + Octeon. Octeon does not have floating point, and all the instructions + that use floating point registers are not allowed in Elf targets but + are allowed in Linux targets by default. */ +#ifdef OCTEON_ERROR_ON_UNSUPPORTED +static int octeon_error_on_unsupported = 1; +#else +static int octeon_error_on_unsupported = 0; +#endif + +/* Control generation of Octeon/MIPS unaligned load/store instructions. + For ELF target, default to Octeon load/store instructions. + For Linux target, default to MIPS load/store instructions. */ +#ifdef OCTEON_USE_UNALIGN +static int octeon_use_unalign = 1; +#else +static int octeon_use_unalign = 0; +#endif + #include "ecoff.h" #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) @@ -111,9 +131,7 @@ static char *mips_regmask_frag; extern int target_big_endian; /* The name of the readonly data section. */ -#define RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \ - ? ".data" \ - : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \ +#define RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_ecoff_flavour \ ? ".rdata" \ : OUTPUT_FLAVOR == bfd_target_coff_flavour \ ? ".rdata" \ @@ -121,6 +139,43 @@ extern int target_big_endian; ? ".rodata" \ : (abort (), "")) +/* Information about an instruction, including its format, operands + and fixups. */ +struct mips_cl_insn +{ + /* The opcode's entry in mips_opcodes or mips16_opcodes. */ + const struct mips_opcode *insn_mo; + + /* True if this is a mips16 instruction and if we want the extended + form of INSN_MO. */ + bfd_boolean use_extend; + + /* The 16-bit extension instruction to use when USE_EXTEND is true. */ + unsigned short extend; + + /* The 16-bit or 32-bit bitstring of the instruction itself. This is + a copy of INSN_MO->match with the operands filled in. */ + unsigned long insn_opcode; + + /* The frag that contains the instruction. */ + struct frag *frag; + + /* The offset into FRAG of the first instruction byte. */ + long where; + + /* The relocs associated with the instruction, if any. */ + fixS *fixp[3]; + + /* True if this entry cannot be moved from its current position. */ + unsigned int fixed_p : 1; + + /* True if this instruction occured in a .set noreorder block. */ + unsigned int noreorder_p : 1; + + /* True for mips16 instructions that jump to an absolute address. */ + unsigned int mips16_absolute_jump_p : 1; +}; + /* The ABI to use. */ enum mips_abi_level { @@ -138,6 +193,10 @@ static enum mips_abi_level mips_abi = NO_ABI; /* Whether or not we have code that can call pic code. */ int mips_abicalls = FALSE; +/* Whether or not we have code which can be put into a shared + library. */ +static bfd_boolean mips_in_shared = TRUE; + /* This is the set of options which may be modified by the .set pseudo-op. We use a struct so that .set push and .set pop are more reliable. */ @@ -153,6 +212,8 @@ struct mips_set_options command line options, and based on the default architecture. */ int ase_mips3d; int ase_mdmx; + int ase_dsp; + int ase_mt; /* Whether we are assembling for the mips16 processor. 0 if we are not, 1 if we are, and -1 if the value has not been initialized. Changed by `.set mips16' and `.set nomips16', and the -mips16 and @@ -187,6 +248,8 @@ struct mips_set_options /* MIPS architecture (CPU) type. Changed by .set arch=FOO, the -march command line option, and the default CPU. */ int arch; + /* True if ".set sym32" is in effect. */ + bfd_boolean sym32; }; /* True if -mgp32 was passed. */ @@ -201,7 +264,7 @@ static int file_mips_fp32 = -1; static struct mips_set_options mips_opts = { - ISA_UNKNOWN, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, CPU_UNKNOWN + ISA_UNKNOWN, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, CPU_UNKNOWN, FALSE }; /* These variables are filled in with the masks of registers used. @@ -225,6 +288,14 @@ static int file_ase_mips3d; command line (e.g., by -march). */ static int file_ase_mdmx; +/* True if -mdsp was passed or implied by arguments passed on the + command line (e.g., by -march). */ +static int file_ase_dsp; + +/* True if -mmt was passed or implied by arguments passed on the + command line (e.g., by -march). */ +static int file_ase_mt; + /* The argument of the -march= flag. The architecture we are assembling. */ static int file_mips_arch = CPU_UNKNOWN; static const char *mips_arch_string; @@ -268,6 +339,12 @@ static int mips_32bitmode = 0; || (ISA) == ISA_MIPS64R2 \ ) +/* Return true if ISA supports ins instructions. */ +#define ISA_HAS_INS(ISA) ( \ + (ISA) == ISA_MIPS32R2 \ + || (ISA) == ISA_MIPS64R2 \ + ) + #define HAVE_32BIT_GPRS \ (mips_opts.gp32 || ! ISA_HAS_64BIT_REGS (mips_opts.isa)) @@ -284,15 +361,16 @@ static int mips_32bitmode = 0; /* True if relocations are stored in-place. */ #define HAVE_IN_PLACE_ADDENDS (!HAVE_NEWABI) -/* We can only have 64bit addresses if the object file format - supports it. */ -#define HAVE_32BIT_ADDRESSES \ - (HAVE_32BIT_GPRS \ - || ((bfd_arch_bits_per_address (stdoutput) == 32 \ - || ! HAVE_64BIT_OBJECTS) \ - && mips_pic != EMBEDDED_PIC)) +/* The ABI-derived address size. */ +#define HAVE_64BIT_ADDRESSES \ + (HAVE_64BIT_GPRS && (mips_abi == EABI_ABI || mips_abi == N64_ABI)) +#define HAVE_32BIT_ADDRESSES (!HAVE_64BIT_ADDRESSES) -#define HAVE_64BIT_ADDRESSES (! HAVE_32BIT_ADDRESSES) +/* The size of symbolic constants (i.e., expressions of the form + "SYMBOL" or "SYMBOL + OFFSET"). */ +#define HAVE_32BIT_SYMBOLS \ + (HAVE_32BIT_ADDRESSES || !HAVE_64BIT_OBJECTS || mips_opts.sym32) +#define HAVE_64BIT_SYMBOLS (!HAVE_32BIT_SYMBOLS) /* Addresses are loaded in different ways, depending on the address size in use. The n32 ABI Documentation also mandates the use of additions @@ -322,6 +400,14 @@ static int mips_32bitmode = 0; #define CPU_HAS_MDMX(cpu) (FALSE \ ) +/* Return true if the given CPU supports the DSP ASE. */ +#define CPU_HAS_DSP(cpu) (FALSE \ + ) + +/* Return true if the given CPU supports the MT ASE. */ +#define CPU_HAS_MT(cpu) (FALSE \ + ) + /* True if CPU has a dror instruction. */ #define CPU_HAS_DROR(CPU) ((CPU) == CPU_VR5400 || (CPU) == CPU_VR5500) @@ -349,7 +435,6 @@ static int mips_32bitmode = 0; || mips_opts.arch == CPU_R10000 \ || mips_opts.arch == CPU_R12000 \ || mips_opts.arch == CPU_RM7000 \ - || mips_opts.arch == CPU_SB1 \ || mips_opts.arch == CPU_VR5500 \ ) @@ -360,8 +445,6 @@ static int mips_32bitmode = 0; level I. */ #define gpr_interlocks \ (mips_opts.isa != ISA_MIPS1 \ - || mips_opts.arch == CPU_VR5400 \ - || mips_opts.arch == CPU_VR5500 \ || mips_opts.arch == CPU_R3900) /* Whether the processor uses hardware interlocks to avoid delays @@ -377,9 +460,6 @@ static int mips_32bitmode = 0; && mips_opts.isa != ISA_MIPS2 \ && mips_opts.isa != ISA_MIPS3) \ || mips_opts.arch == CPU_R4300 \ - || mips_opts.arch == CPU_VR5400 \ - || mips_opts.arch == CPU_VR5500 \ - || mips_opts.arch == CPU_SB1 \ ) /* Whether the processor uses hardware interlocks to protect reads @@ -521,44 +601,27 @@ static int mips_optimize = 2; equivalent to seeing no -g option at all. */ static int mips_debug = 0; -/* The previous instruction. */ -static struct mips_cl_insn prev_insn; +/* The maximum number of NOPs needed to avoid the VR4130 mflo/mfhi errata. */ +#define MAX_VR4130_NOPS 4 -/* The instruction before prev_insn. */ -static struct mips_cl_insn prev_prev_insn; +/* The maximum number of NOPs needed to fill delay slots. */ +#define MAX_DELAY_NOPS 2 -/* If we don't want information for prev_insn or prev_prev_insn, we - point the insn_mo field at this dummy integer. */ -static const struct mips_opcode dummy_opcode = { NULL, NULL, 0, 0, 0, 0 }; +/* The maximum number of NOPs needed for any purpose. */ +#define MAX_NOPS 4 -/* Non-zero if prev_insn is valid. */ -static int prev_insn_valid; +/* A list of previous instructions, with index 0 being the most recent. + We need to look back MAX_NOPS instructions when filling delay slots + or working around processor errata. We need to look back one + instruction further if we're thinking about using history[0] to + fill a branch delay slot. */ +static struct mips_cl_insn history[1 + MAX_NOPS]; -/* The frag for the previous instruction. */ -static struct frag *prev_insn_frag; +/* Nop instructions used by emit_nop. */ +static struct mips_cl_insn nop_insn, mips16_nop_insn; -/* The offset into prev_insn_frag for the previous instruction. */ -static long prev_insn_where; - -/* The reloc type for the previous instruction, if any. */ -static bfd_reloc_code_real_type prev_insn_reloc_type[3]; - -/* The reloc for the previous instruction, if any. */ -static fixS *prev_insn_fixp[3]; - -/* Non-zero if the previous instruction was in a delay slot. */ -static int prev_insn_is_delay_slot; - -/* Non-zero if the previous instruction was in a .set noreorder. */ -static int prev_insn_unreordered; - -/* Non-zero if the previous instruction uses an extend opcode (if - mips16). */ -static int prev_insn_extended; - -/* Non-zero if the previous previous instruction was in a .set - noreorder. */ -static int prev_prev_insn_unreordered; +/* The appropriate nop for the current mode. */ +#define NOP_INSN (mips_opts.mips16 ? &mips16_nop_insn : &nop_insn) /* If this is set, it points to a frag holding nop instructions which were inserted before the start of a noreorder section. If those @@ -625,8 +688,29 @@ static const unsigned int mips16_to_32_reg_map[] = 16, 17, 2, 3, 4, 5, 6, 7 }; +/* Classifies the kind of instructions we're interested in when + implementing -mfix-vr4120. */ +enum fix_vr4120_class { + FIX_VR4120_MACC, + FIX_VR4120_DMACC, + FIX_VR4120_MULT, + FIX_VR4120_DMULT, + FIX_VR4120_DIV, + FIX_VR4120_MTHILO, + NUM_FIX_VR4120_CLASSES +}; + +/* Given two FIX_VR4120_* values X and Y, bit Y of element X is set if + there must be at least one other instruction between an instruction + of type X and an instruction of type Y. */ +static unsigned int vr4120_conflicts[NUM_FIX_VR4120_CLASSES]; + +/* True if -mfix-vr4120 is in force. */ static int mips_fix_vr4120; +/* ...likewise -mfix-vr4130. */ +static int mips_fix_vr4130; + /* We don't relax branches by default, since this causes us to expand `la .l2 - .l1' if there's a branch between .l1 and .l2, because we fail to compute the offset before expanding the macro to the most @@ -820,6 +904,41 @@ static int mips_relax_branch; (((x) &~ (offsetT) 0x7fff) == 0 \ || (((x) &~ (offsetT) 0x7fff) == ~ (offsetT) 0x7fff)) +/* Is the given value a zero-extended 32-bit value? Or a negated one? */ +#define IS_ZEXT_32BIT_NUM(x) \ + (((x) &~ (offsetT) 0xffffffff) == 0 \ + || (((x) &~ (offsetT) 0xffffffff) == ~ (offsetT) 0xffffffff)) + +/* Replace bits MASK << SHIFT of STRUCT with the equivalent bits in + VALUE << SHIFT. VALUE is evaluated exactly once. */ +#define INSERT_BITS(STRUCT, VALUE, MASK, SHIFT) \ + (STRUCT) = (((STRUCT) & ~((MASK) << (SHIFT))) \ + | (((VALUE) & (MASK)) << (SHIFT))) + +/* Extract bits MASK << SHIFT from STRUCT and shift them right + SHIFT places. */ +#define EXTRACT_BITS(STRUCT, MASK, SHIFT) \ + (((STRUCT) >> (SHIFT)) & (MASK)) + +/* Change INSN's opcode so that the operand given by FIELD has value VALUE. + INSN is a mips_cl_insn structure and VALUE is evaluated exactly once. + + include/opcode/mips.h specifies operand fields using the macros + OP_MASK_ and OP_SH_. The MIPS16 equivalents start + with "MIPS16OP" instead of "OP". */ +#define INSERT_OPERAND(FIELD, INSN, VALUE) \ + INSERT_BITS ((INSN).insn_opcode, VALUE, OP_MASK_##FIELD, OP_SH_##FIELD) +#define MIPS16_INSERT_OPERAND(FIELD, INSN, VALUE) \ + INSERT_BITS ((INSN).insn_opcode, VALUE, \ + MIPS16OP_MASK_##FIELD, MIPS16OP_SH_##FIELD) + +/* Extract the operand given by FIELD from mips_cl_insn INSN. */ +#define EXTRACT_OPERAND(FIELD, INSN) \ + EXTRACT_BITS ((INSN).insn_opcode, OP_MASK_##FIELD, OP_SH_##FIELD) +#define MIPS16_EXTRACT_OPERAND(FIELD, INSN) \ + EXTRACT_BITS ((INSN).insn_opcode, \ + MIPS16OP_MASK_##FIELD, \ + MIPS16OP_SH_##FIELD) /* Global variables used when generating relaxable macros. See the comment above RELAX_ENCODE for more details about how relaxation @@ -866,7 +985,7 @@ enum mips_regclass { MIPS_GR_REG, MIPS_FP_REG, MIPS16_REG }; static void append_insn (struct mips_cl_insn *ip, expressionS *p, bfd_reloc_code_real_type *r); -static void mips_no_prev_insn (int); +static void mips_no_prev_insn (void); static void mips16_macro_build (expressionS *, const char *, const char *, va_list); static void load_register (int, expressionS *, int); @@ -1092,8 +1211,6 @@ mips_target_format (void) { switch (OUTPUT_FLAVOR) { - case bfd_target_aout_flavour: - return target_big_endian ? "a.out-mips-big" : "a.out-mips-little"; case bfd_target_ecoff_flavour: return target_big_endian ? "ecoff-bigmips" : ECOFF_LITTLE_FORMAT; case bfd_target_coff_flavour: @@ -1127,6 +1244,174 @@ mips_target_format (void) } } +/* Return the length of instruction INSN. */ + +static inline unsigned int +insn_length (const struct mips_cl_insn *insn) +{ + if (!mips_opts.mips16) + return 4; + return insn->mips16_absolute_jump_p || insn->use_extend ? 4 : 2; +} + +/* Initialise INSN from opcode entry MO. Leave its position unspecified. */ + +static void +create_insn (struct mips_cl_insn *insn, const struct mips_opcode *mo) +{ + size_t i; + + insn->insn_mo = mo; + insn->use_extend = FALSE; + insn->extend = 0; + insn->insn_opcode = mo->match; + insn->frag = NULL; + insn->where = 0; + for (i = 0; i < ARRAY_SIZE (insn->fixp); i++) + insn->fixp[i] = NULL; + insn->fixed_p = (mips_opts.noreorder > 0); + insn->noreorder_p = (mips_opts.noreorder > 0); + insn->mips16_absolute_jump_p = 0; +} + +/* Install INSN at the location specified by its "frag" and "where" fields. */ + +static void +install_insn (const struct mips_cl_insn *insn) +{ + char *f = insn->frag->fr_literal + insn->where; + if (!mips_opts.mips16) + md_number_to_chars (f, insn->insn_opcode, 4); + else if (insn->mips16_absolute_jump_p) + { + md_number_to_chars (f, insn->insn_opcode >> 16, 2); + md_number_to_chars (f + 2, insn->insn_opcode & 0xffff, 2); + } + else + { + if (insn->use_extend) + { + md_number_to_chars (f, 0xf000 | insn->extend, 2); + f += 2; + } + md_number_to_chars (f, insn->insn_opcode, 2); + } +} + +/* Move INSN to offset WHERE in FRAG. Adjust the fixups accordingly + and install the opcode in the new location. */ + +static void +move_insn (struct mips_cl_insn *insn, fragS *frag, long where) +{ + size_t i; + + insn->frag = frag; + insn->where = where; + for (i = 0; i < ARRAY_SIZE (insn->fixp); i++) + if (insn->fixp[i] != NULL) + { + insn->fixp[i]->fx_frag = frag; + insn->fixp[i]->fx_where = where; + } + install_insn (insn); +} + +/* Add INSN to the end of the output. */ + +static void +add_fixed_insn (struct mips_cl_insn *insn) +{ + char *f = frag_more (insn_length (insn)); + move_insn (insn, frag_now, f - frag_now->fr_literal); +} + +/* Start a variant frag and move INSN to the start of the variant part, + marking it as fixed. The other arguments are as for frag_var. */ + +static void +add_relaxed_insn (struct mips_cl_insn *insn, int max_chars, int var, + relax_substateT subtype, symbolS *symbol, offsetT offset) +{ + frag_grow (max_chars); + move_insn (insn, frag_now, frag_more (0) - frag_now->fr_literal); + insn->fixed_p = 1; + frag_var (rs_machine_dependent, max_chars, var, + subtype, symbol, offset, NULL); +} + +/* Insert N copies of INSN into the history buffer, starting at + position FIRST. Neither FIRST nor N need to be clipped. */ + +static void +insert_into_history (unsigned int first, unsigned int n, + const struct mips_cl_insn *insn) +{ + if (mips_relax.sequence != 2) + { + unsigned int i; + + for (i = ARRAY_SIZE (history); i-- > first;) + if (i >= first + n) + history[i] = history[i - n]; + else + history[i] = *insn; + } +} + +/* Emit a nop instruction, recording it in the history buffer. */ + +static void +emit_nop (void) +{ + add_fixed_insn (NOP_INSN); + insert_into_history (0, 1, NOP_INSN); +} + +/* Initialize vr4120_conflicts. There is a bit of duplication here: + the idea is to make it obvious at a glance that each errata is + included. */ + +static void +init_vr4120_conflicts (void) +{ +#define CONFLICT(FIRST, SECOND) \ + vr4120_conflicts[FIX_VR4120_##FIRST] |= 1 << FIX_VR4120_##SECOND + + /* Errata 21 - [D]DIV[U] after [D]MACC */ + CONFLICT (MACC, DIV); + CONFLICT (DMACC, DIV); + + /* Errata 23 - Continuous DMULT[U]/DMACC instructions. */ + CONFLICT (DMULT, DMULT); + CONFLICT (DMULT, DMACC); + CONFLICT (DMACC, DMULT); + CONFLICT (DMACC, DMACC); + + /* Errata 24 - MT{LO,HI} after [D]MACC */ + CONFLICT (MACC, MTHILO); + CONFLICT (DMACC, MTHILO); + + /* VR4181A errata MD(1): "If a MULT, MULTU, DMULT or DMULTU + instruction is executed immediately after a MACC or DMACC + instruction, the result of [either instruction] is incorrect." */ + CONFLICT (MACC, MULT); + CONFLICT (MACC, DMULT); + CONFLICT (DMACC, MULT); + CONFLICT (DMACC, DMULT); + + /* VR4181A errata MD(4): "If a MACC or DMACC instruction is + executed immediately after a DMULT, DMULTU, DIV, DIVU, + DDIV or DDIVU instruction, the result of the MACC or + DMACC instruction is incorrect.". */ + CONFLICT (DMULT, MACC); + CONFLICT (DMULT, DMACC); + CONFLICT (DIV, MACC); + CONFLICT (DIV, DMACC); + +#undef CONFLICT +} + /* This function is called once, at assembler startup time. It should set up all the tables, etc. that the MD part of the assembler will need. */ @@ -1137,6 +1422,13 @@ md_begin (void) int i = 0; int broken = 0; + if (mips_pic != NO_PIC) + { + if (g_switch_seen && g_switch_value != 0) + as_bad (_("-G may not be used in position-independent code")); + g_switch_value = 0; + } + if (! bfd_set_arch_mach (stdoutput, bfd_arch_mips, file_mips_arch)) as_warn (_("Could not set architecture and machine")); @@ -1160,6 +1452,11 @@ md_begin (void) { if (!validate_mips_insn (&mips_opcodes[i])) broken = 1; + if (nop_insn.insn_mo == NULL && strcmp (name, "nop") == 0) + { + create_insn (&nop_insn, mips_opcodes + i); + nop_insn.fixed_p = 1; + } } ++i; } @@ -1187,6 +1484,11 @@ md_begin (void) mips16_opcodes[i].name, mips16_opcodes[i].args); broken = 1; } + if (mips16_nop_insn.insn_mo == NULL && strcmp (name, "nop") == 0) + { + create_insn (&mips16_nop_insn, mips16_opcodes + i); + mips16_nop_insn.fixed_p = 1; + } ++i; } while (i < bfd_mips16_num_opcodes @@ -1239,7 +1541,7 @@ md_begin (void) &zero_address_frag)); } - mips_no_prev_insn (FALSE); + mips_no_prev_insn (); mips_gprmask = 0; mips_cprmask[0] = 0; @@ -1250,15 +1552,15 @@ md_begin (void) /* set the default alignment for the text section (2**2) */ record_alignment (text_section, 2); - if (USE_GLOBAL_POINTER_OPT) - bfd_set_gp_size (stdoutput, g_switch_value); + bfd_set_gp_size (stdoutput, g_switch_value); if (OUTPUT_FLAVOR == bfd_target_elf_flavour) { /* On a native system, sections must be aligned to 16 byte - boundaries. When configured for an embedded ELF target, we + boundaries. When configured for an embedded ELF target, we don't bother. */ - if (strcmp (TARGET_OS, "elf") != 0) + if (strcmp (TARGET_OS, "elf") != 0 + && strcmp (TARGET_OS, "vxworks") != 0) { (void) bfd_set_section_alignment (stdoutput, text_section, 4); (void) bfd_set_section_alignment (stdoutput, data_section, 4); @@ -1346,6 +1648,9 @@ md_begin (void) if (! ECOFF_DEBUGGING) md_obj_begin (); + + if (mips_fix_vr4120) + init_vr4120_conflicts (); } void @@ -1408,8 +1713,8 @@ md_assemble (char *str) } /* Return true if the given relocation might need a matching %lo(). - Note that R_MIPS_GOT16 relocations only need a matching %lo() when - applied to local symbols. */ + This is only "might" because SVR4 R_MIPS_GOT16 relocations only + need a matching %lo() when applied to local symbols. */ static inline bfd_boolean reloc_needs_lo_p (bfd_reloc_code_real_type reloc) @@ -1434,7 +1739,7 @@ fixup_has_matching_lo_p (fixS *fixp) of register. */ static int -insn_uses_reg (struct mips_cl_insn *ip, unsigned int reg, +insn_uses_reg (const struct mips_cl_insn *ip, unsigned int reg, enum mips_regclass class) { if (class == MIPS16_REG) @@ -1459,38 +1764,33 @@ insn_uses_reg (struct mips_cl_insn *ip, unsigned int reg, because there is no instruction that sets both $f0 and $f1 and requires a delay. */ if ((ip->insn_mo->pinfo & INSN_READ_FPR_S) - && ((((ip->insn_opcode >> OP_SH_FS) & OP_MASK_FS) &~(unsigned)1) + && ((EXTRACT_OPERAND (FS, *ip) & ~(unsigned) 1) == (reg &~ (unsigned) 1))) return 1; if ((ip->insn_mo->pinfo & INSN_READ_FPR_T) - && ((((ip->insn_opcode >> OP_SH_FT) & OP_MASK_FT) &~(unsigned)1) + && ((EXTRACT_OPERAND (FT, *ip) & ~(unsigned) 1) == (reg &~ (unsigned) 1))) return 1; } else if (! mips_opts.mips16) { if ((ip->insn_mo->pinfo & INSN_READ_GPR_S) - && ((ip->insn_opcode >> OP_SH_RS) & OP_MASK_RS) == reg) + && EXTRACT_OPERAND (RS, *ip) == reg) return 1; if ((ip->insn_mo->pinfo & INSN_READ_GPR_T) - && ((ip->insn_opcode >> OP_SH_RT) & OP_MASK_RT) == reg) + && EXTRACT_OPERAND (RT, *ip) == reg) return 1; } else { if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_X) - && (mips16_to_32_reg_map[((ip->insn_opcode >> MIPS16OP_SH_RX) - & MIPS16OP_MASK_RX)] - == reg)) + && mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RX, *ip)] == reg) return 1; if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_Y) - && (mips16_to_32_reg_map[((ip->insn_opcode >> MIPS16OP_SH_RY) - & MIPS16OP_MASK_RY)] - == reg)) + && mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RY, *ip)] == reg) return 1; if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_Z) - && (mips16_to_32_reg_map[((ip->insn_opcode >> MIPS16OP_SH_MOVE32Z) - & MIPS16OP_MASK_MOVE32Z)] + && (mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (MOVE32Z, *ip)] == reg)) return 1; if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_T) && reg == TREG) @@ -1500,8 +1800,7 @@ insn_uses_reg (struct mips_cl_insn *ip, unsigned int reg, if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_31) && reg == RA) return 1; if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_GPR_X) - && ((ip->insn_opcode >> MIPS16OP_SH_REGR32) - & MIPS16OP_MASK_REGR32) == reg) + && MIPS16_EXTRACT_OPERAND (REGR32, *ip) == reg) return 1; } @@ -1516,7 +1815,7 @@ reg_needs_delay (unsigned int reg) { unsigned long prev_pinfo; - prev_pinfo = prev_insn.insn_mo->pinfo; + prev_pinfo = history[0].insn_mo->pinfo; if (! mips_opts.noreorder && (((prev_pinfo & INSN_LOAD_MEMORY_DELAY) && ! gpr_interlocks) @@ -1527,13 +1826,33 @@ reg_needs_delay (unsigned int reg) delay the use of general register rt for one instruction. */ /* Itbl support may require additional care here. */ know (prev_pinfo & INSN_WRITE_GPR_T); - if (reg == ((prev_insn.insn_opcode >> OP_SH_RT) & OP_MASK_RT)) + if (reg == EXTRACT_OPERAND (RT, history[0])) return 1; } return 0; } +/* Move all labels in insn_labels to the current insertion point. */ + +static void +mips_move_labels (void) +{ + struct insn_label_list *l; + valueT val; + + for (l = insn_labels; l != NULL; l = l->next) + { + assert (S_GET_SEGMENT (l->label) == now_seg); + symbol_set_frag (l->label, frag_now); + val = (valueT) frag_now_fix (); + /* mips16 text labels are stored as odd. */ + if (mips_opts.mips16) + ++val; + S_SET_VALUE (l->label, val); + } +} + /* Mark instruction labels in mips16 mode. This permits the linker to handle them specially, such as generating jalx instructions when needed. We also make them odd for the duration of the assembly, in @@ -1609,6 +1928,273 @@ relax_end (void) mips_relax.sequence = 0; } +/* Classify an instruction according to the FIX_VR4120_* enumeration. + Return NUM_FIX_VR4120_CLASSES if the instruction isn't affected + by VR4120 errata. */ + +static unsigned int +classify_vr4120_insn (const char *name) +{ + if (strncmp (name, "macc", 4) == 0) + return FIX_VR4120_MACC; + if (strncmp (name, "dmacc", 5) == 0) + return FIX_VR4120_DMACC; + if (strncmp (name, "mult", 4) == 0) + return FIX_VR4120_MULT; + if (strncmp (name, "dmult", 5) == 0) + return FIX_VR4120_DMULT; + if (strstr (name, "div")) + return FIX_VR4120_DIV; + if (strcmp (name, "mtlo") == 0 || strcmp (name, "mthi") == 0) + return FIX_VR4120_MTHILO; + return NUM_FIX_VR4120_CLASSES; +} + +/* Return the number of instructions that must separate INSN1 and INSN2, + where INSN1 is the earlier instruction. Return the worst-case value + for any INSN2 if INSN2 is null. */ + +static unsigned int +insns_between (const struct mips_cl_insn *insn1, + const struct mips_cl_insn *insn2) +{ + unsigned long pinfo1, pinfo2; + + /* This function needs to know which pinfo flags are set for INSN2 + and which registers INSN2 uses. The former is stored in PINFO2 and + the latter is tested via INSN2_USES_REG. If INSN2 is null, PINFO2 + will have every flag set and INSN2_USES_REG will always return true. */ + pinfo1 = insn1->insn_mo->pinfo; + pinfo2 = insn2 ? insn2->insn_mo->pinfo : ~0U; + +#define INSN2_USES_REG(REG, CLASS) \ + (insn2 == NULL || insn_uses_reg (insn2, REG, CLASS)) + + /* For most targets, write-after-read dependencies on the HI and LO + registers must be separated by at least two instructions. */ + if (!hilo_interlocks) + { + if ((pinfo1 & INSN_READ_LO) && (pinfo2 & INSN_WRITE_LO)) + return 2; + if ((pinfo1 & INSN_READ_HI) && (pinfo2 & INSN_WRITE_HI)) + return 2; + } + + /* If we're working around r7000 errata, there must be two instructions + between an mfhi or mflo and any instruction that uses the result. */ + if (mips_7000_hilo_fix + && MF_HILO_INSN (pinfo1) + && INSN2_USES_REG (EXTRACT_OPERAND (RD, *insn1), MIPS_GR_REG)) + return 2; + + /* If working around VR4120 errata, check for combinations that need + a single intervening instruction. */ + if (mips_fix_vr4120) + { + unsigned int class1, class2; + + class1 = classify_vr4120_insn (insn1->insn_mo->name); + if (class1 != NUM_FIX_VR4120_CLASSES && vr4120_conflicts[class1] != 0) + { + if (insn2 == NULL) + return 1; + class2 = classify_vr4120_insn (insn2->insn_mo->name); + if (vr4120_conflicts[class1] & (1 << class2)) + return 1; + } + } + + if (!mips_opts.mips16) + { + /* Check for GPR or coprocessor load delays. All such delays + are on the RT register. */ + /* Itbl support may require additional care here. */ + if ((!gpr_interlocks && (pinfo1 & INSN_LOAD_MEMORY_DELAY)) + || (!cop_interlocks && (pinfo1 & INSN_LOAD_COPROC_DELAY))) + { + know (pinfo1 & INSN_WRITE_GPR_T); + if (INSN2_USES_REG (EXTRACT_OPERAND (RT, *insn1), MIPS_GR_REG)) + return 1; + } + + /* Check for generic coprocessor hazards. + + This case is not handled very well. There is no special + knowledge of CP0 handling, and the coprocessors other than + the floating point unit are not distinguished at all. */ + /* Itbl support may require additional care here. FIXME! + Need to modify this to include knowledge about + user specified delays! */ + else if ((!cop_interlocks && (pinfo1 & INSN_COPROC_MOVE_DELAY)) + || (!cop_mem_interlocks && (pinfo1 & INSN_COPROC_MEMORY_DELAY))) + { + /* Handle cases where INSN1 writes to a known general coprocessor + register. There must be a one instruction delay before INSN2 + if INSN2 reads that register, otherwise no delay is needed. */ + if (pinfo1 & INSN_WRITE_FPR_T) + { + if (INSN2_USES_REG (EXTRACT_OPERAND (FT, *insn1), MIPS_FP_REG)) + return 1; + } + else if (pinfo1 & INSN_WRITE_FPR_S) + { + if (INSN2_USES_REG (EXTRACT_OPERAND (FS, *insn1), MIPS_FP_REG)) + return 1; + } + else + { + /* Read-after-write dependencies on the control registers + require a two-instruction gap. */ + if ((pinfo1 & INSN_WRITE_COND_CODE) + && (pinfo2 & INSN_READ_COND_CODE)) + return 2; + + /* We don't know exactly what INSN1 does. If INSN2 is + also a coprocessor instruction, assume there must be + a one instruction gap. */ + if (pinfo2 & INSN_COP) + return 1; + } + } + + /* Check for read-after-write dependencies on the coprocessor + control registers in cases where INSN1 does not need a general + coprocessor delay. This means that INSN1 is a floating point + comparison instruction. */ + /* Itbl support may require additional care here. */ + else if (!cop_interlocks + && (pinfo1 & INSN_WRITE_COND_CODE) + && (pinfo2 & INSN_READ_COND_CODE)) + return 1; + } + +#undef INSN2_USES_REG + + return 0; +} + +/* Return the number of nops that would be needed to work around the + VR4130 mflo/mfhi errata if instruction INSN immediately followed + the MAX_VR4130_NOPS instructions described by HISTORY. */ + +static int +nops_for_vr4130 (const struct mips_cl_insn *history, + const struct mips_cl_insn *insn) +{ + int i, j, reg; + + /* Check if the instruction writes to HI or LO. MTHI and MTLO + are not affected by the errata. */ + if (insn != 0 + && ((insn->insn_mo->pinfo & (INSN_WRITE_HI | INSN_WRITE_LO)) == 0 + || strcmp (insn->insn_mo->name, "mtlo") == 0 + || strcmp (insn->insn_mo->name, "mthi") == 0)) + return 0; + + /* Search for the first MFLO or MFHI. */ + for (i = 0; i < MAX_VR4130_NOPS; i++) + if (!history[i].noreorder_p && MF_HILO_INSN (history[i].insn_mo->pinfo)) + { + /* Extract the destination register. */ + if (mips_opts.mips16) + reg = mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RX, history[i])]; + else + reg = EXTRACT_OPERAND (RD, history[i]); + + /* No nops are needed if INSN reads that register. */ + if (insn != NULL && insn_uses_reg (insn, reg, MIPS_GR_REG)) + return 0; + + /* ...or if any of the intervening instructions do. */ + for (j = 0; j < i; j++) + if (insn_uses_reg (&history[j], reg, MIPS_GR_REG)) + return 0; + + return MAX_VR4130_NOPS - i; + } + return 0; +} + +/* Return the number of nops that would be needed if instruction INSN + immediately followed the MAX_NOPS instructions given by HISTORY, + where HISTORY[0] is the most recent instruction. If INSN is null, + return the worse-case number of nops for any instruction. */ + +static int +nops_for_insn (const struct mips_cl_insn *history, + const struct mips_cl_insn *insn) +{ + int i, nops, tmp_nops; + + nops = 0; + for (i = 0; i < MAX_DELAY_NOPS; i++) + if (!history[i].noreorder_p) + { + tmp_nops = insns_between (history + i, insn) - i; + if (tmp_nops > nops) + nops = tmp_nops; + } + + if (mips_fix_vr4130) + { + tmp_nops = nops_for_vr4130 (history, insn); + if (tmp_nops > nops) + nops = tmp_nops; + } + + return nops; +} + +/* The variable arguments provide NUM_INSNS extra instructions that + might be added to HISTORY. Return the largest number of nops that + would be needed after the extended sequence. */ + +static int +nops_for_sequence (int num_insns, const struct mips_cl_insn *history, ...) +{ + va_list args; + struct mips_cl_insn buffer[MAX_NOPS]; + struct mips_cl_insn *cursor; + int nops; + + va_start (args, history); + cursor = buffer + num_insns; + memcpy (cursor, history, (MAX_NOPS - num_insns) * sizeof (*cursor)); + while (cursor > buffer) + *--cursor = *va_arg (args, const struct mips_cl_insn *); + + nops = nops_for_insn (buffer, NULL); + va_end (args); + return nops; +} + +/* Like nops_for_insn, but if INSN is a branch, take into account the + worst-case delay for the branch target. */ + +static int +nops_for_insn_or_target (const struct mips_cl_insn *history, + const struct mips_cl_insn *insn) +{ + int nops, tmp_nops; + + nops = nops_for_insn (history, insn); + if (insn->insn_mo->pinfo & (INSN_UNCOND_BRANCH_DELAY + | INSN_COND_BRANCH_DELAY + | INSN_COND_BRANCH_LIKELY)) + { + tmp_nops = nops_for_sequence (2, history, insn, NOP_INSN); + if (tmp_nops > nops) + nops = tmp_nops; + } + else if (mips_opts.mips16 && (insn->insn_mo->pinfo & MIPS16_INSN_BRANCH)) + { + tmp_nops = nops_for_sequence (1, history, insn); + if (tmp_nops > nops) + nops = tmp_nops; + } + return nops; +} + /* Output an instruction. IP is the instruction information. ADDRESS_EXPR is an operand of the instruction to be used with RELOC_TYPE. */ @@ -1618,314 +2204,32 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, bfd_reloc_code_real_type *reloc_type) { register unsigned long prev_pinfo, pinfo; - char *f; - fixS *fixp[3]; - int nops = 0; relax_stateT prev_insn_frag_type = 0; bfd_boolean relaxed_branch = FALSE; - bfd_boolean force_new_frag = FALSE; /* Mark instruction labels in mips16 mode. */ mips16_mark_labels (); - prev_pinfo = prev_insn.insn_mo->pinfo; + prev_pinfo = history[0].insn_mo->pinfo; pinfo = ip->insn_mo->pinfo; - if (mips_relax.sequence != 2 - && (!mips_opts.noreorder || prev_nop_frag != NULL)) + if (mips_relax.sequence != 2 && !mips_opts.noreorder) { - int prev_prev_nop; - - /* If the previous insn required any delay slots, see if we need - to insert a NOP or two. There are eight kinds of possible - hazards, of which an instruction can have at most one type. - (1) a load from memory delay - (2) a load from a coprocessor delay - (3) an unconditional branch delay - (4) a conditional branch delay - (5) a move to coprocessor register delay - (6) a load coprocessor register from memory delay - (7) a coprocessor condition code delay - (8) a HI/LO special register delay - - There are a lot of optimizations we could do that we don't. + /* There are a lot of optimizations we could do that we don't. In particular, we do not, in general, reorder instructions. If you use gcc with optimization, it will reorder instructions and generally do much more optimization then we do here; repeating all that work in the assembler would only benefit hand written assembly code, and does not seem worth it. */ - - /* This is how a NOP is emitted. */ -#define emit_nop() \ - (mips_opts.mips16 \ - ? md_number_to_chars (frag_more (2), 0x6500, 2) \ - : md_number_to_chars (frag_more (4), 0, 4)) - - /* The previous insn might require a delay slot, depending upon - the contents of the current insn. */ - if (! mips_opts.mips16 - && (((prev_pinfo & INSN_LOAD_MEMORY_DELAY) - && ! gpr_interlocks) - || ((prev_pinfo & INSN_LOAD_COPROC_DELAY) - && ! cop_interlocks))) - { - /* A load from a coprocessor or from memory. All load - delays delay the use of general register rt for one - instruction. */ - /* Itbl support may require additional care here. */ - know (prev_pinfo & INSN_WRITE_GPR_T); - if (mips_optimize == 0 - || insn_uses_reg (ip, - ((prev_insn.insn_opcode >> OP_SH_RT) - & OP_MASK_RT), - MIPS_GR_REG)) - ++nops; - } - else if (! mips_opts.mips16 - && (((prev_pinfo & INSN_COPROC_MOVE_DELAY) - && ! cop_interlocks) - || ((prev_pinfo & INSN_COPROC_MEMORY_DELAY) - && ! cop_mem_interlocks))) - { - /* A generic coprocessor delay. The previous instruction - modified a coprocessor general or control register. If - it modified a control register, we need to avoid any - coprocessor instruction (this is probably not always - required, but it sometimes is). If it modified a general - register, we avoid using that register. - - This case is not handled very well. There is no special - knowledge of CP0 handling, and the coprocessors other - than the floating point unit are not distinguished at - all. */ - /* Itbl support may require additional care here. FIXME! - Need to modify this to include knowledge about - user specified delays! */ - if (prev_pinfo & INSN_WRITE_FPR_T) - { - if (mips_optimize == 0 - || insn_uses_reg (ip, - ((prev_insn.insn_opcode >> OP_SH_FT) - & OP_MASK_FT), - MIPS_FP_REG)) - ++nops; - } - else if (prev_pinfo & INSN_WRITE_FPR_S) - { - if (mips_optimize == 0 - || insn_uses_reg (ip, - ((prev_insn.insn_opcode >> OP_SH_FS) - & OP_MASK_FS), - MIPS_FP_REG)) - ++nops; - } - else - { - /* We don't know exactly what the previous instruction - does. If the current instruction uses a coprocessor - register, we must insert a NOP. If previous - instruction may set the condition codes, and the - current instruction uses them, we must insert two - NOPS. */ - /* Itbl support may require additional care here. */ - if (mips_optimize == 0 - || ((prev_pinfo & INSN_WRITE_COND_CODE) - && (pinfo & INSN_READ_COND_CODE))) - nops += 2; - else if (pinfo & INSN_COP) - ++nops; - } - } - else if (! mips_opts.mips16 - && (prev_pinfo & INSN_WRITE_COND_CODE) - && ! cop_interlocks) - { - /* The previous instruction sets the coprocessor condition - codes, but does not require a general coprocessor delay - (this means it is a floating point comparison - instruction). If this instruction uses the condition - codes, we need to insert a single NOP. */ - /* Itbl support may require additional care here. */ - if (mips_optimize == 0 - || (pinfo & INSN_READ_COND_CODE)) - ++nops; - } - - /* If we're fixing up mfhi/mflo for the r7000 and the - previous insn was an mfhi/mflo and the current insn - reads the register that the mfhi/mflo wrote to, then - insert two nops. */ - - else if (mips_7000_hilo_fix - && MF_HILO_INSN (prev_pinfo) - && insn_uses_reg (ip, ((prev_insn.insn_opcode >> OP_SH_RD) - & OP_MASK_RD), - MIPS_GR_REG)) - { - nops += 2; - } - - /* If we're fixing up mfhi/mflo for the r7000 and the - 2nd previous insn was an mfhi/mflo and the current insn - reads the register that the mfhi/mflo wrote to, then - insert one nop. */ - - else if (mips_7000_hilo_fix - && MF_HILO_INSN (prev_prev_insn.insn_opcode) - && insn_uses_reg (ip, ((prev_prev_insn.insn_opcode >> OP_SH_RD) - & OP_MASK_RD), - MIPS_GR_REG)) - - { - ++nops; - } - - else if (prev_pinfo & INSN_READ_LO) - { - /* The previous instruction reads the LO register; if the - current instruction writes to the LO register, we must - insert two NOPS. Some newer processors have interlocks. - Also the tx39's multiply instructions can be executed - immediately after a read from HI/LO (without the delay), - though the tx39's divide insns still do require the - delay. */ - if (! (hilo_interlocks - || (mips_opts.arch == CPU_R3900 && (pinfo & INSN_MULT))) - && (mips_optimize == 0 - || (pinfo & INSN_WRITE_LO))) - nops += 2; - /* Most mips16 branch insns don't have a delay slot. - If a read from LO is immediately followed by a branch - to a write to LO we have a read followed by a write - less than 2 insns away. We assume the target of - a branch might be a write to LO, and insert a nop - between a read and an immediately following branch. */ - else if (mips_opts.mips16 - && (mips_optimize == 0 - || (pinfo & MIPS16_INSN_BRANCH))) - ++nops; - } - else if (prev_insn.insn_mo->pinfo & INSN_READ_HI) - { - /* The previous instruction reads the HI register; if the - current instruction writes to the HI register, we must - insert a NOP. Some newer processors have interlocks. - Also the note tx39's multiply above. */ - if (! (hilo_interlocks - || (mips_opts.arch == CPU_R3900 && (pinfo & INSN_MULT))) - && (mips_optimize == 0 - || (pinfo & INSN_WRITE_HI))) - nops += 2; - /* Most mips16 branch insns don't have a delay slot. - If a read from HI is immediately followed by a branch - to a write to HI we have a read followed by a write - less than 2 insns away. We assume the target of - a branch might be a write to HI, and insert a nop - between a read and an immediately following branch. */ - else if (mips_opts.mips16 - && (mips_optimize == 0 - || (pinfo & MIPS16_INSN_BRANCH))) - ++nops; - } - - /* If the previous instruction was in a noreorder section, then - we don't want to insert the nop after all. */ - /* Itbl support may require additional care here. */ - if (prev_insn_unreordered) - nops = 0; - - /* There are two cases which require two intervening - instructions: 1) setting the condition codes using a move to - coprocessor instruction which requires a general coprocessor - delay and then reading the condition codes 2) reading the HI - or LO register and then writing to it (except on processors - which have interlocks). If we are not already emitting a NOP - instruction, we must check for these cases compared to the - instruction previous to the previous instruction. */ - if ((! mips_opts.mips16 - && (prev_prev_insn.insn_mo->pinfo & INSN_COPROC_MOVE_DELAY) - && (prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE) - && (pinfo & INSN_READ_COND_CODE) - && ! cop_interlocks) - || ((prev_prev_insn.insn_mo->pinfo & INSN_READ_LO) - && (pinfo & INSN_WRITE_LO) - && ! (hilo_interlocks - || (mips_opts.arch == CPU_R3900 && (pinfo & INSN_MULT)))) - || ((prev_prev_insn.insn_mo->pinfo & INSN_READ_HI) - && (pinfo & INSN_WRITE_HI) - && ! (hilo_interlocks - || (mips_opts.arch == CPU_R3900 && (pinfo & INSN_MULT))))) - prev_prev_nop = 1; - else - prev_prev_nop = 0; - - if (prev_prev_insn_unreordered) - prev_prev_nop = 0; - - if (prev_prev_nop && nops == 0) - ++nops; - - if (mips_fix_vr4120 && prev_insn.insn_mo->name) - { - /* We're out of bits in pinfo, so we must resort to string - ops here. Shortcuts are selected based on opcodes being - limited to the VR4120 instruction set. */ - int min_nops = 0; - const char *pn = prev_insn.insn_mo->name; - const char *tn = ip->insn_mo->name; - if (strncmp(pn, "macc", 4) == 0 - || strncmp(pn, "dmacc", 5) == 0) - { - /* Errata 21 - [D]DIV[U] after [D]MACC */ - if (strstr (tn, "div")) - { - min_nops = 1; - } - - /* Errata 23 - Continuous DMULT[U]/DMACC instructions */ - if (pn[0] == 'd' /* dmacc */ - && (strncmp(tn, "dmult", 5) == 0 - || strncmp(tn, "dmacc", 5) == 0)) - { - min_nops = 1; - } - - /* Errata 24 - MT{LO,HI} after [D]MACC */ - if (strcmp (tn, "mtlo") == 0 - || strcmp (tn, "mthi") == 0) - { - min_nops = 1; - } - - } - else if (strncmp(pn, "dmult", 5) == 0 - && (strncmp(tn, "dmult", 5) == 0 - || strncmp(tn, "dmacc", 5) == 0)) - { - /* Here is the rest of errata 23. */ - min_nops = 1; - } - if (nops < min_nops) - nops = min_nops; - } - - /* If we are being given a nop instruction, don't bother with - one of the nops we would otherwise output. This will only - happen when a nop instruction is used with mips_optimize set - to 0. */ - if (nops > 0 - && ! mips_opts.noreorder - && ip->insn_opcode == (unsigned) (mips_opts.mips16 ? 0x6500 : 0)) - --nops; - - /* Now emit the right number of NOP instructions. */ - if (nops > 0 && ! mips_opts.noreorder) + int nops = (mips_optimize == 0 + ? nops_for_insn (history, NULL) + : nops_for_insn_or_target (history, ip)); + if (nops > 0) { fragS *old_frag; unsigned long old_frag_offset; int i; - struct insn_label_list *l; old_frag = frag_now; old_frag_offset = frag_now_fix (); @@ -1947,66 +2251,54 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, frag_grow (40); } - for (l = insn_labels; l != NULL; l = l->next) - { - valueT val; - - assert (S_GET_SEGMENT (l->label) == now_seg); - symbol_set_frag (l->label, frag_now); - val = (valueT) frag_now_fix (); - /* mips16 text labels are stored as odd. */ - if (mips_opts.mips16) - ++val; - S_SET_VALUE (l->label, val); - } + mips_move_labels (); #ifndef NO_ECOFF_DEBUGGING if (ECOFF_DEBUGGING) ecoff_fix_loc (old_frag, old_frag_offset); #endif } - else if (prev_nop_frag != NULL) + } + else if (mips_relax.sequence != 2 && prev_nop_frag != NULL) + { + /* Work out how many nops in prev_nop_frag are needed by IP. */ + int nops = nops_for_insn_or_target (history, ip); + assert (nops <= prev_nop_frag_holds); + + /* Enforce NOPS as a minimum. */ + if (nops > prev_nop_frag_required) + prev_nop_frag_required = nops; + + if (prev_nop_frag_holds == prev_nop_frag_required) { - /* We have a frag holding nops we may be able to remove. If - we don't need any nops, we can decrease the size of - prev_nop_frag by the size of one instruction. If we do - need some nops, we count them in prev_nops_required. */ - if (prev_nop_frag_since == 0) - { - if (nops == 0) - { - prev_nop_frag->fr_fix -= mips_opts.mips16 ? 2 : 4; - --prev_nop_frag_holds; - } - else - prev_nop_frag_required += nops; - } - else - { - if (prev_prev_nop == 0) - { - prev_nop_frag->fr_fix -= mips_opts.mips16 ? 2 : 4; - --prev_nop_frag_holds; - } - else - ++prev_nop_frag_required; - } - - if (prev_nop_frag_holds <= prev_nop_frag_required) - prev_nop_frag = NULL; - - ++prev_nop_frag_since; - - /* Sanity check: by the time we reach the second instruction - after prev_nop_frag, we should have used up all the nops - one way or another. */ - assert (prev_nop_frag_since <= 1 || prev_nop_frag == NULL); + /* Settle for the current number of nops. Update the history + accordingly (for the benefit of any future .set reorder code). */ + prev_nop_frag = NULL; + insert_into_history (prev_nop_frag_since, + prev_nop_frag_holds, NOP_INSN); + } + else + { + /* Allow this instruction to replace one of the nops that was + tentatively added to prev_nop_frag. */ + prev_nop_frag->fr_fix -= mips_opts.mips16 ? 2 : 4; + prev_nop_frag_holds--; + prev_nop_frag_since++; } } +#ifdef OBJ_ELF + /* The value passed to dwarf2_emit_insn is the distance between + the beginning of the current instruction and the address that + should be recorded in the debug tables. For MIPS16 debug info + we want to use ISA-encoded addresses, so we pass -1 for an + address higher by one than the current. */ + dwarf2_emit_insn (mips_opts.mips16 ? -1 : 0); +#endif + /* Record the frag type before frag_var. */ - if (prev_insn_frag) - prev_insn_frag_type = prev_insn_frag->fr_type; + if (history[0].frag) + prev_insn_frag_type = history[0].frag->fr_type; if (address_expr && *reloc_type == BFD_RELOC_16_PCREL_S2 @@ -2021,42 +2313,41 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, && !mips_opts.mips16) { relaxed_branch = TRUE; - f = frag_var (rs_machine_dependent, - relaxed_branch_length - (NULL, NULL, - (pinfo & INSN_UNCOND_BRANCH_DELAY) ? -1 - : (pinfo & INSN_COND_BRANCH_LIKELY) ? 1 : 0), 4, - RELAX_BRANCH_ENCODE - (pinfo & INSN_UNCOND_BRANCH_DELAY, - pinfo & INSN_COND_BRANCH_LIKELY, - pinfo & INSN_WRITE_GPR_31, - 0), - address_expr->X_add_symbol, - address_expr->X_add_number, - 0); + add_relaxed_insn (ip, (relaxed_branch_length + (NULL, NULL, + (pinfo & INSN_UNCOND_BRANCH_DELAY) ? -1 + : (pinfo & INSN_COND_BRANCH_LIKELY) ? 1 + : 0)), 4, + RELAX_BRANCH_ENCODE + (pinfo & INSN_UNCOND_BRANCH_DELAY, + pinfo & INSN_COND_BRANCH_LIKELY, + pinfo & INSN_WRITE_GPR_31, + 0), + address_expr->X_add_symbol, + address_expr->X_add_number); *reloc_type = BFD_RELOC_UNUSED; } else if (*reloc_type > BFD_RELOC_UNUSED) { /* We need to set up a variant frag. */ assert (mips_opts.mips16 && address_expr != NULL); - f = frag_var (rs_machine_dependent, 4, 0, - RELAX_MIPS16_ENCODE (*reloc_type - BFD_RELOC_UNUSED, - mips16_small, mips16_ext, - (prev_pinfo - & INSN_UNCOND_BRANCH_DELAY), - (*prev_insn_reloc_type - == BFD_RELOC_MIPS16_JMP)), - make_expr_symbol (address_expr), 0, NULL); + add_relaxed_insn (ip, 4, 0, + RELAX_MIPS16_ENCODE + (*reloc_type - BFD_RELOC_UNUSED, + mips16_small, mips16_ext, + prev_pinfo & INSN_UNCOND_BRANCH_DELAY, + history[0].mips16_absolute_jump_p), + make_expr_symbol (address_expr), 0); } else if (mips_opts.mips16 && ! ip->use_extend && *reloc_type != BFD_RELOC_MIPS16_JMP) { - /* Make sure there is enough room to swap this instruction with - a following jump instruction. */ - frag_grow (6); - f = frag_more (2); + if ((pinfo & INSN_UNCOND_BRANCH_DELAY) == 0) + /* Make sure there is enough room to swap this instruction with + a following jump instruction. */ + frag_grow (6); + add_fixed_insn (ip); } else { @@ -2080,15 +2371,19 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, if (mips_relax.sequence != 1) mips_macro_warning.sizes[1] += 4; - f = frag_more (4); + if (mips_opts.mips16) + { + ip->fixed_p = 1; + ip->mips16_absolute_jump_p = (*reloc_type == BFD_RELOC_MIPS16_JMP); + } + add_fixed_insn (ip); } - fixp[0] = fixp[1] = fixp[2] = NULL; - if (address_expr != NULL && *reloc_type < BFD_RELOC_UNUSED) + if (address_expr != NULL && *reloc_type <= BFD_RELOC_UNUSED) { if (address_expr->X_op == O_constant) { - valueT tmp; + unsigned int tmp; switch (*reloc_type) { @@ -2097,26 +2392,25 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, break; case BFD_RELOC_MIPS_HIGHEST: - tmp = (address_expr->X_add_number - + ((valueT) 0x8000 << 32) + 0x80008000) >> 16; - tmp >>= 16; - ip->insn_opcode |= (tmp >> 16) & 0xffff; + tmp = (address_expr->X_add_number + 0x800080008000ull) >> 48; + ip->insn_opcode |= tmp & 0xffff; break; case BFD_RELOC_MIPS_HIGHER: - tmp = (address_expr->X_add_number + 0x80008000) >> 16; - ip->insn_opcode |= (tmp >> 16) & 0xffff; + tmp = (address_expr->X_add_number + 0x80008000ull) >> 32; + ip->insn_opcode |= tmp & 0xffff; break; case BFD_RELOC_HI16_S: - ip->insn_opcode |= ((address_expr->X_add_number + 0x8000) - >> 16) & 0xffff; + tmp = (address_expr->X_add_number + 0x8000) >> 16; + ip->insn_opcode |= tmp & 0xffff; break; case BFD_RELOC_HI16: ip->insn_opcode |= (address_expr->X_add_number >> 16) & 0xffff; break; + case BFD_RELOC_UNUSED: case BFD_RELOC_LO16: case BFD_RELOC_MIPS_GOT_DISP: ip->insn_opcode |= address_expr->X_add_number & 0xffff; @@ -2126,9 +2420,6 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, if ((address_expr->X_add_number & 3) != 0) as_bad (_("jump to misaligned address (0x%lx)"), (unsigned long) address_expr->X_add_number); - if (address_expr->X_add_number & ~0xfffffff) - as_bad (_("jump address range overflow (0x%lx)"), - (unsigned long) address_expr->X_add_number); ip->insn_opcode |= (address_expr->X_add_number >> 2) & 0x3ffffff; break; @@ -2136,9 +2427,6 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, if ((address_expr->X_add_number & 3) != 0) as_bad (_("jump to misaligned address (0x%lx)"), (unsigned long) address_expr->X_add_number); - if (address_expr->X_add_number & ~0xfffffff) - as_bad (_("jump address range overflow (0x%lx)"), - (unsigned long) address_expr->X_add_number); ip->insn_opcode |= (((address_expr->X_add_number & 0x7c0000) << 3) | ((address_expr->X_add_number & 0xf800000) >> 7) @@ -2146,13 +2434,22 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, break; case BFD_RELOC_16_PCREL_S2: - goto need_reloc; + if ((address_expr->X_add_number & 3) != 0) + as_bad (_("branch to misaligned address (0x%lx)"), + (unsigned long) address_expr->X_add_number); + if (mips_relax_branch) + goto need_reloc; + if ((address_expr->X_add_number + 0x20000) & ~0x3ffff) + as_bad (_("branch address range overflow (0x%lx)"), + (unsigned long) address_expr->X_add_number); + ip->insn_opcode |= (address_expr->X_add_number >> 2) & 0xffff; + break; default: internalError (); } } - else + else if (*reloc_type < BFD_RELOC_UNUSED) need_reloc: { reloc_howto_type *howto; @@ -2165,11 +2462,11 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, break; howto = bfd_reloc_type_lookup (stdoutput, reloc_type[i - 1]); - fixp[0] = fix_new_exp (frag_now, f - frag_now->fr_literal, - bfd_get_reloc_size(howto), - address_expr, - reloc_type[0] == BFD_RELOC_16_PCREL_S2, - reloc_type[0]); + ip->fixp[0] = fix_new_exp (ip->frag, ip->where, + bfd_get_reloc_size (howto), + address_expr, + reloc_type[0] == BFD_RELOC_16_PCREL_S2, + reloc_type[0]); /* These relocations can have an addend that won't fit in 4 octets for 64bit assembly. */ @@ -2191,12 +2488,12 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, || reloc_type[0] == BFD_RELOC_MIPS_SCN_DISP || reloc_type[0] == BFD_RELOC_MIPS_REL16 || reloc_type[0] == BFD_RELOC_MIPS_RELGOT)) - fixp[0]->fx_no_overflow = 1; + ip->fixp[0]->fx_no_overflow = 1; if (mips_relax.sequence) { if (mips_relax.first_fixup == 0) - mips_relax.first_fixup = fixp[0]; + mips_relax.first_fixup = ip->fixp[0]; } else if (reloc_needs_lo_p (*reloc_type)) { @@ -2212,7 +2509,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, hi_fixup->next = mips_hi_fixup_list; mips_hi_fixup_list = hi_fixup; } - hi_fixup->fixp = fixp[0]; + hi_fixup->fixp = ip->fixp[0]; hi_fixup->seg = now_seg; } @@ -2224,64 +2521,37 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, for (i = 1; i < 3; i++) if (reloc_type[i] != BFD_RELOC_UNUSED) { - address_expr->X_op = O_absent; - address_expr->X_add_symbol = 0; - address_expr->X_add_number = 0; - - fixp[i] = fix_new_exp (frag_now, fixp[0]->fx_where, - fixp[0]->fx_size, address_expr, + ip->fixp[i] = fix_new (ip->frag, ip->where, + ip->fixp[0]->fx_size, NULL, 0, FALSE, reloc_type[i]); + + /* Use fx_tcbit to mark compound relocs. */ + ip->fixp[0]->fx_tcbit = 1; + ip->fixp[i]->fx_tcbit = 1; } } } - - if (! mips_opts.mips16) - { - md_number_to_chars (f, ip->insn_opcode, 4); -#ifdef OBJ_ELF - dwarf2_emit_insn (4); -#endif - } - else if (*reloc_type == BFD_RELOC_MIPS16_JMP) - { - md_number_to_chars (f, ip->insn_opcode >> 16, 2); - md_number_to_chars (f + 2, ip->insn_opcode & 0xffff, 2); -#ifdef OBJ_ELF - dwarf2_emit_insn (4); -#endif - } - else - { - if (ip->use_extend) - { - md_number_to_chars (f, 0xf000 | ip->extend, 2); - f += 2; - } - md_number_to_chars (f, ip->insn_opcode, 2); -#ifdef OBJ_ELF - dwarf2_emit_insn (ip->use_extend ? 4 : 2); -#endif - } + install_insn (ip); /* Update the register mask information. */ if (! mips_opts.mips16) { if (pinfo & INSN_WRITE_GPR_D) - mips_gprmask |= 1 << ((ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD); + mips_gprmask |= 1 << EXTRACT_OPERAND (RD, *ip); if ((pinfo & (INSN_WRITE_GPR_T | INSN_READ_GPR_T)) != 0) - mips_gprmask |= 1 << ((ip->insn_opcode >> OP_SH_RT) & OP_MASK_RT); + mips_gprmask |= 1 << EXTRACT_OPERAND (RT, *ip); if (pinfo & INSN_READ_GPR_S) - mips_gprmask |= 1 << ((ip->insn_opcode >> OP_SH_RS) & OP_MASK_RS); + mips_gprmask |= 1 << EXTRACT_OPERAND (RS, *ip); if (pinfo & INSN_WRITE_GPR_31) mips_gprmask |= 1 << RA; if (pinfo & INSN_WRITE_FPR_D) - mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FD) & OP_MASK_FD); + mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FD, *ip); if ((pinfo & (INSN_WRITE_FPR_S | INSN_READ_FPR_S)) != 0) - mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FS) & OP_MASK_FS); + mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FS, *ip); if ((pinfo & (INSN_WRITE_FPR_T | INSN_READ_FPR_T)) != 0) - mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FT) & OP_MASK_FT); + mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FT, *ip); if ((pinfo & INSN_READ_FPR_R) != 0) - mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FR) & OP_MASK_FR); + mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FR, *ip); if (pinfo & INSN_COP) { /* We don't keep enough information to sort these cases out. @@ -2295,14 +2565,11 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, else { if (pinfo & (MIPS16_INSN_WRITE_X | MIPS16_INSN_READ_X)) - mips_gprmask |= 1 << ((ip->insn_opcode >> MIPS16OP_SH_RX) - & MIPS16OP_MASK_RX); + mips_gprmask |= 1 << MIPS16_EXTRACT_OPERAND (RX, *ip); if (pinfo & (MIPS16_INSN_WRITE_Y | MIPS16_INSN_READ_Y)) - mips_gprmask |= 1 << ((ip->insn_opcode >> MIPS16OP_SH_RY) - & MIPS16OP_MASK_RY); + mips_gprmask |= 1 << MIPS16_EXTRACT_OPERAND (RY, *ip); if (pinfo & MIPS16_INSN_WRITE_Z) - mips_gprmask |= 1 << ((ip->insn_opcode >> MIPS16OP_SH_RZ) - & MIPS16OP_MASK_RZ); + mips_gprmask |= 1 << MIPS16_EXTRACT_OPERAND (RZ, *ip); if (pinfo & (MIPS16_INSN_WRITE_T | MIPS16_INSN_READ_T)) mips_gprmask |= 1 << TREG; if (pinfo & (MIPS16_INSN_WRITE_SP | MIPS16_INSN_READ_SP)) @@ -2312,11 +2579,9 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, if (pinfo & MIPS16_INSN_WRITE_GPR_Y) mips_gprmask |= 1 << MIPS16OP_EXTRACT_REG32R (ip->insn_opcode); if (pinfo & MIPS16_INSN_READ_Z) - mips_gprmask |= 1 << ((ip->insn_opcode >> MIPS16OP_SH_MOVE32Z) - & MIPS16OP_MASK_MOVE32Z); + mips_gprmask |= 1 << MIPS16_EXTRACT_OPERAND (MOVE32Z, *ip); if (pinfo & MIPS16_INSN_READ_GPR_X) - mips_gprmask |= 1 << ((ip->insn_opcode >> MIPS16OP_SH_REGR32) - & MIPS16OP_MASK_REGR32); + mips_gprmask |= 1 << MIPS16_EXTRACT_OPERAND (REGR32, *ip); } if (mips_relax.sequence != 2 && !mips_opts.noreorder) @@ -2333,15 +2598,9 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, /* If we have seen .set volatile or .set nomove, don't optimize. */ || mips_opts.nomove != 0 - /* If we had to emit any NOP instructions, then we - already know we can not swap. */ - || nops != 0 - /* If we don't even know the previous insn, we can not - swap. */ - || ! prev_insn_valid - /* If the previous insn is already in a branch delay - slot, then we can not swap. */ - || prev_insn_is_delay_slot + /* We can't swap if the previous instruction's position + is fixed. */ + || history[0].fixed_p /* If the previous previous insn was in a .set noreorder, we can't swap. Actually, the MIPS assembler will swap in this situation. However, gcc @@ -2353,12 +2612,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, bne $4,$0,foo in which we can not swap the bne and INSN. If gcc is not configured -with-gnu-as, it does not output the - .set pseudo-ops. We don't have to check - prev_insn_unreordered, because prev_insn_valid will - be 0 in that case. We don't want to use - prev_prev_insn_valid, because we do want to be able - to swap at the start of a function. */ - || prev_prev_insn_unreordered + .set pseudo-ops. */ + || history[1].noreorder_p /* If the branch is itself the target of a branch, we can not swap. We cheat on this; all we check for is whether there is a label on this instruction. If @@ -2371,44 +2626,12 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, frags for different purposes. */ || (! mips_opts.mips16 && prev_insn_frag_type == rs_machine_dependent) - /* If the branch reads the condition codes, we don't - even try to swap, because in the sequence - ctc1 $X,$31 - INSN - INSN - bc1t LABEL - we can not swap, and I don't feel like handling that - case. */ - || (! mips_opts.mips16 - && (pinfo & INSN_READ_COND_CODE) - && ! cop_interlocks) - /* We can not swap with an instruction that requires a - delay slot, because the target of the branch might - interfere with that instruction. */ - || (! mips_opts.mips16 - && (prev_pinfo - /* Itbl support may require additional care here. */ - & (INSN_LOAD_COPROC_DELAY - | INSN_COPROC_MOVE_DELAY - | INSN_WRITE_COND_CODE)) - && ! cop_interlocks) - || (! (hilo_interlocks - || (mips_opts.arch == CPU_R3900 && (pinfo & INSN_MULT))) - && (prev_pinfo - & (INSN_READ_LO - | INSN_READ_HI))) - || (! mips_opts.mips16 - && (prev_pinfo & INSN_LOAD_MEMORY_DELAY) - && ! gpr_interlocks) - || (! mips_opts.mips16 - /* Itbl support may require additional care here. */ - && (prev_pinfo & INSN_COPROC_MEMORY_DELAY) - && ! cop_mem_interlocks) - /* We can not swap with a branch instruction. */ - || (prev_pinfo - & (INSN_UNCOND_BRANCH_DELAY - | INSN_COND_BRANCH_DELAY - | INSN_COND_BRANCH_LIKELY)) + /* Check for conflicts between the branch and the instructions + before the candidate delay slot. */ + || nops_for_insn (history + 1, ip) > 0 + /* Check for conflicts between the swapped sequence and the + target of the branch. */ + || nops_for_sequence (2, history + 1, ip, history) > 0 /* We do not swap with a trap instruction, since it complicates trap handlers to have the trap instruction be in a delay slot. */ @@ -2417,43 +2640,33 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, instruction sets, we can not swap. */ || (! mips_opts.mips16 && (prev_pinfo & INSN_WRITE_GPR_T) - && insn_uses_reg (ip, - ((prev_insn.insn_opcode >> OP_SH_RT) - & OP_MASK_RT), + && insn_uses_reg (ip, EXTRACT_OPERAND (RT, history[0]), MIPS_GR_REG)) || (! mips_opts.mips16 && (prev_pinfo & INSN_WRITE_GPR_D) - && insn_uses_reg (ip, - ((prev_insn.insn_opcode >> OP_SH_RD) - & OP_MASK_RD), + && insn_uses_reg (ip, EXTRACT_OPERAND (RD, history[0]), MIPS_GR_REG)) || (mips_opts.mips16 && (((prev_pinfo & MIPS16_INSN_WRITE_X) - && insn_uses_reg (ip, - ((prev_insn.insn_opcode - >> MIPS16OP_SH_RX) - & MIPS16OP_MASK_RX), - MIPS16_REG)) + && (insn_uses_reg + (ip, MIPS16_EXTRACT_OPERAND (RX, history[0]), + MIPS16_REG))) || ((prev_pinfo & MIPS16_INSN_WRITE_Y) - && insn_uses_reg (ip, - ((prev_insn.insn_opcode - >> MIPS16OP_SH_RY) - & MIPS16OP_MASK_RY), - MIPS16_REG)) + && (insn_uses_reg + (ip, MIPS16_EXTRACT_OPERAND (RY, history[0]), + MIPS16_REG))) || ((prev_pinfo & MIPS16_INSN_WRITE_Z) - && insn_uses_reg (ip, - ((prev_insn.insn_opcode - >> MIPS16OP_SH_RZ) - & MIPS16OP_MASK_RZ), - MIPS16_REG)) + && (insn_uses_reg + (ip, MIPS16_EXTRACT_OPERAND (RZ, history[0]), + MIPS16_REG))) || ((prev_pinfo & MIPS16_INSN_WRITE_T) && insn_uses_reg (ip, TREG, MIPS_GR_REG)) || ((prev_pinfo & MIPS16_INSN_WRITE_31) && insn_uses_reg (ip, RA, MIPS_GR_REG)) || ((prev_pinfo & MIPS16_INSN_WRITE_GPR_Y) && insn_uses_reg (ip, - MIPS16OP_EXTRACT_REG32R (prev_insn. - insn_opcode), + MIPS16OP_EXTRACT_REG32R + (history[0].insn_opcode), MIPS_GR_REG)))) /* If the branch writes a register that the previous instruction sets, we can not swap (we know that @@ -2461,61 +2674,37 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, || (! mips_opts.mips16 && (prev_pinfo & INSN_WRITE_GPR_T) && (((pinfo & INSN_WRITE_GPR_D) - && (((prev_insn.insn_opcode >> OP_SH_RT) & OP_MASK_RT) - == ((ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD))) + && (EXTRACT_OPERAND (RT, history[0]) + == EXTRACT_OPERAND (RD, *ip))) || ((pinfo & INSN_WRITE_GPR_31) - && (((prev_insn.insn_opcode >> OP_SH_RT) - & OP_MASK_RT) - == RA)))) + && EXTRACT_OPERAND (RT, history[0]) == RA))) || (! mips_opts.mips16 && (prev_pinfo & INSN_WRITE_GPR_D) && (((pinfo & INSN_WRITE_GPR_D) - && (((prev_insn.insn_opcode >> OP_SH_RD) & OP_MASK_RD) - == ((ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD))) + && (EXTRACT_OPERAND (RD, history[0]) + == EXTRACT_OPERAND (RD, *ip))) || ((pinfo & INSN_WRITE_GPR_31) - && (((prev_insn.insn_opcode >> OP_SH_RD) - & OP_MASK_RD) - == RA)))) + && EXTRACT_OPERAND (RD, history[0]) == RA))) || (mips_opts.mips16 && (pinfo & MIPS16_INSN_WRITE_31) && ((prev_pinfo & MIPS16_INSN_WRITE_31) || ((prev_pinfo & MIPS16_INSN_WRITE_GPR_Y) - && (MIPS16OP_EXTRACT_REG32R (prev_insn.insn_opcode) + && (MIPS16OP_EXTRACT_REG32R (history[0].insn_opcode) == RA)))) /* If the branch writes a register that the previous instruction reads, we can not swap (we know that branches only write to RD or to $31). */ || (! mips_opts.mips16 && (pinfo & INSN_WRITE_GPR_D) - && insn_uses_reg (&prev_insn, - ((ip->insn_opcode >> OP_SH_RD) - & OP_MASK_RD), + && insn_uses_reg (&history[0], + EXTRACT_OPERAND (RD, *ip), MIPS_GR_REG)) || (! mips_opts.mips16 && (pinfo & INSN_WRITE_GPR_31) - && insn_uses_reg (&prev_insn, RA, MIPS_GR_REG)) + && insn_uses_reg (&history[0], RA, MIPS_GR_REG)) || (mips_opts.mips16 && (pinfo & MIPS16_INSN_WRITE_31) - && insn_uses_reg (&prev_insn, RA, MIPS_GR_REG)) - /* If we are generating embedded PIC code, the branch - might be expanded into a sequence which uses $at, so - we can't swap with an instruction which reads it. */ - || (mips_pic == EMBEDDED_PIC - && insn_uses_reg (&prev_insn, AT, MIPS_GR_REG)) - /* If the previous previous instruction has a load - delay, and sets a register that the branch reads, we - can not swap. */ - || (! mips_opts.mips16 - /* Itbl support may require additional care here. */ - && (((prev_prev_insn.insn_mo->pinfo & INSN_LOAD_COPROC_DELAY) - && ! cop_interlocks) - || ((prev_prev_insn.insn_mo->pinfo - & INSN_LOAD_MEMORY_DELAY) - && ! gpr_interlocks)) - && insn_uses_reg (ip, - ((prev_prev_insn.insn_opcode >> OP_SH_RT) - & OP_MASK_RT), - MIPS_GR_REG)) + && insn_uses_reg (&history[0], RA, MIPS_GR_REG)) /* If one instruction sets a condition code and the other one uses a condition code, we can not swap. */ || ((pinfo & INSN_READ_COND_CODE) @@ -2526,173 +2715,75 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, swap. */ || (mips_opts.mips16 && (prev_pinfo & MIPS16_INSN_READ_PC)) - /* If the previous instruction was extended, we can not - swap. */ - || (mips_opts.mips16 && prev_insn_extended) /* If the previous instruction had a fixup in mips16 mode, we can not swap. This normally means that the previous instruction was a 4 byte branch anyhow. */ - || (mips_opts.mips16 && prev_insn_fixp[0]) + || (mips_opts.mips16 && history[0].fixp[0]) /* If the previous instruction is a sync, sync.l, or sync.p, we can not swap. */ || (prev_pinfo & INSN_SYNC)) { - /* We could do even better for unconditional branches to - portions of this object file; we could pick up the - instruction at the destination, put it in the delay - slot, and bump the destination address. */ - emit_nop (); - /* Update the previous insn information. */ - prev_prev_insn = *ip; - prev_insn.insn_mo = &dummy_opcode; + if (mips_opts.mips16 + && (pinfo & INSN_UNCOND_BRANCH_DELAY) + && (pinfo & (MIPS16_INSN_READ_X | MIPS16_INSN_READ_31)) + && (mips_opts.isa == ISA_MIPS32 + || mips_opts.isa == ISA_MIPS32R2 + || mips_opts.isa == ISA_MIPS64 + || mips_opts.isa == ISA_MIPS64R2)) + { + /* Convert MIPS16 jr/jalr into a "compact" jump. */ + ip->insn_opcode |= 0x0080; + install_insn (ip); + insert_into_history (0, 1, ip); + } + else + { + /* We could do even better for unconditional branches to + portions of this object file; we could pick up the + instruction at the destination, put it in the delay + slot, and bump the destination address. */ + insert_into_history (0, 1, ip); + emit_nop (); + } + + if (mips_relax.sequence) + mips_relax.sizes[mips_relax.sequence - 1] += 4; } else { /* It looks like we can actually do the swap. */ - if (! mips_opts.mips16) + struct mips_cl_insn delay = history[0]; + if (mips_opts.mips16) { - char *prev_f; - char temp[4]; - - prev_f = prev_insn_frag->fr_literal + prev_insn_where; - if (!relaxed_branch) - { - /* If this is not a relaxed branch, then just - swap the instructions. */ - memcpy (temp, prev_f, 4); - memcpy (prev_f, f, 4); - memcpy (f, temp, 4); - } - else - { - /* If this is a relaxed branch, then we move the - instruction to be placed in the delay slot to - the current frag, shrinking the fixed part of - the originating frag. If the branch occupies - the tail of the latter, we move it backwards, - into the space freed by the moved instruction. */ - f = frag_more (4); - memcpy (f, prev_f, 4); - prev_insn_frag->fr_fix -= 4; - if (prev_insn_frag->fr_type == rs_machine_dependent) - memmove (prev_f, prev_f + 4, prev_insn_frag->fr_var); - } - - if (prev_insn_fixp[0]) - { - prev_insn_fixp[0]->fx_frag = frag_now; - prev_insn_fixp[0]->fx_where = f - frag_now->fr_literal; - } - if (prev_insn_fixp[1]) - { - prev_insn_fixp[1]->fx_frag = frag_now; - prev_insn_fixp[1]->fx_where = f - frag_now->fr_literal; - } - if (prev_insn_fixp[2]) - { - prev_insn_fixp[2]->fx_frag = frag_now; - prev_insn_fixp[2]->fx_where = f - frag_now->fr_literal; - } - if (prev_insn_fixp[0] && HAVE_NEWABI - && prev_insn_frag != frag_now - && (prev_insn_fixp[0]->fx_r_type - == BFD_RELOC_MIPS_GOT_DISP - || (prev_insn_fixp[0]->fx_r_type - == BFD_RELOC_MIPS_CALL16))) - { - /* To avoid confusion in tc_gen_reloc, we must - ensure that this does not become a variant - frag. */ - force_new_frag = TRUE; - } - - if (!relaxed_branch) - { - if (fixp[0]) - { - fixp[0]->fx_frag = prev_insn_frag; - fixp[0]->fx_where = prev_insn_where; - } - if (fixp[1]) - { - fixp[1]->fx_frag = prev_insn_frag; - fixp[1]->fx_where = prev_insn_where; - } - if (fixp[2]) - { - fixp[2]->fx_frag = prev_insn_frag; - fixp[2]->fx_where = prev_insn_where; - } - } - else if (prev_insn_frag->fr_type == rs_machine_dependent) - { - if (fixp[0]) - fixp[0]->fx_where -= 4; - if (fixp[1]) - fixp[1]->fx_where -= 4; - if (fixp[2]) - fixp[2]->fx_where -= 4; - } + know (delay.frag == ip->frag); + move_insn (ip, delay.frag, delay.where); + move_insn (&delay, ip->frag, ip->where + insn_length (ip)); + } + else if (relaxed_branch) + { + /* Add the delay slot instruction to the end of the + current frag and shrink the fixed part of the + original frag. If the branch occupies the tail of + the latter, move it backwards to cover the gap. */ + delay.frag->fr_fix -= 4; + if (delay.frag == ip->frag) + move_insn (ip, ip->frag, ip->where - 4); + add_fixed_insn (&delay); } else { - char *prev_f; - char temp[2]; - - assert (prev_insn_fixp[0] == NULL); - assert (prev_insn_fixp[1] == NULL); - assert (prev_insn_fixp[2] == NULL); - prev_f = prev_insn_frag->fr_literal + prev_insn_where; - memcpy (temp, prev_f, 2); - memcpy (prev_f, f, 2); - if (*reloc_type != BFD_RELOC_MIPS16_JMP) - { - assert (*reloc_type == BFD_RELOC_UNUSED); - memcpy (f, temp, 2); - } - else - { - memcpy (f, f + 2, 2); - memcpy (f + 2, temp, 2); - } - if (fixp[0]) - { - fixp[0]->fx_frag = prev_insn_frag; - fixp[0]->fx_where = prev_insn_where; - } - if (fixp[1]) - { - fixp[1]->fx_frag = prev_insn_frag; - fixp[1]->fx_where = prev_insn_where; - } - if (fixp[2]) - { - fixp[2]->fx_frag = prev_insn_frag; - fixp[2]->fx_where = prev_insn_where; - } + move_insn (&delay, ip->frag, ip->where); + move_insn (ip, history[0].frag, history[0].where); } - - /* Update the previous insn information; leave prev_insn - unchanged. */ - prev_prev_insn = *ip; + history[0] = *ip; + delay.fixed_p = 1; + insert_into_history (0, 1, &delay); } - prev_insn_is_delay_slot = 1; /* If that was an unconditional branch, forget the previous insn information. */ if (pinfo & INSN_UNCOND_BRANCH_DELAY) - { - prev_prev_insn.insn_mo = &dummy_opcode; - prev_insn.insn_mo = &dummy_opcode; - } - - prev_insn_fixp[0] = NULL; - prev_insn_fixp[1] = NULL; - prev_insn_fixp[2] = NULL; - prev_insn_reloc_type[0] = BFD_RELOC_UNUSED; - prev_insn_reloc_type[1] = BFD_RELOC_UNUSED; - prev_insn_reloc_type[2] = BFD_RELOC_UNUSED; - prev_insn_extended = 0; + mips_no_prev_insn (); } else if (pinfo & INSN_COND_BRANCH_LIKELY) { @@ -2700,169 +2791,70 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, is look at the target, copy the instruction found there into the delay slot, and increment the branch to jump to the next instruction. */ + insert_into_history (0, 1, ip); emit_nop (); - /* Update the previous insn information. */ - prev_prev_insn = *ip; - prev_insn.insn_mo = &dummy_opcode; - prev_insn_fixp[0] = NULL; - prev_insn_fixp[1] = NULL; - prev_insn_fixp[2] = NULL; - prev_insn_reloc_type[0] = BFD_RELOC_UNUSED; - prev_insn_reloc_type[1] = BFD_RELOC_UNUSED; - prev_insn_reloc_type[2] = BFD_RELOC_UNUSED; - prev_insn_extended = 0; } else - { - /* Update the previous insn information. */ - if (nops > 0) - prev_prev_insn.insn_mo = &dummy_opcode; - else - prev_prev_insn = prev_insn; - prev_insn = *ip; - - /* Any time we see a branch, we always fill the delay slot - immediately; since this insn is not a branch, we know it - is not in a delay slot. */ - prev_insn_is_delay_slot = 0; - - prev_insn_fixp[0] = fixp[0]; - prev_insn_fixp[1] = fixp[1]; - prev_insn_fixp[2] = fixp[2]; - prev_insn_reloc_type[0] = reloc_type[0]; - prev_insn_reloc_type[1] = reloc_type[1]; - prev_insn_reloc_type[2] = reloc_type[2]; - if (mips_opts.mips16) - prev_insn_extended = (ip->use_extend - || *reloc_type > BFD_RELOC_UNUSED); - } - - prev_prev_insn_unreordered = prev_insn_unreordered; - prev_insn_unreordered = 0; - prev_insn_frag = frag_now; - prev_insn_where = f - frag_now->fr_literal; - prev_insn_valid = 1; - } - else if (mips_relax.sequence != 2) - { - /* We need to record a bit of information even when we are not - reordering, in order to determine the base address for mips16 - PC relative relocs. */ - prev_prev_insn = prev_insn; - prev_insn = *ip; - prev_insn_reloc_type[0] = reloc_type[0]; - prev_insn_reloc_type[1] = reloc_type[1]; - prev_insn_reloc_type[2] = reloc_type[2]; - prev_prev_insn_unreordered = prev_insn_unreordered; - prev_insn_unreordered = 1; + insert_into_history (0, 1, ip); } + else + insert_into_history (0, 1, ip); /* We just output an insn, so the next one doesn't have a label. */ mips_clear_insn_labels (); } -/* This function forgets that there was any previous instruction or - label. If PRESERVE is non-zero, it remembers enough information to - know whether nops are needed before a noreorder section. */ +/* Forget that there was any previous instruction or label. */ static void -mips_no_prev_insn (int preserve) +mips_no_prev_insn (void) { - if (! preserve) - { - prev_insn.insn_mo = &dummy_opcode; - prev_prev_insn.insn_mo = &dummy_opcode; - prev_nop_frag = NULL; - prev_nop_frag_holds = 0; - prev_nop_frag_required = 0; - prev_nop_frag_since = 0; - } - prev_insn_valid = 0; - prev_insn_is_delay_slot = 0; - prev_insn_unreordered = 0; - prev_insn_extended = 0; - prev_insn_reloc_type[0] = BFD_RELOC_UNUSED; - prev_insn_reloc_type[1] = BFD_RELOC_UNUSED; - prev_insn_reloc_type[2] = BFD_RELOC_UNUSED; - prev_prev_insn_unreordered = 0; + prev_nop_frag = NULL; + insert_into_history (0, ARRAY_SIZE (history), NOP_INSN); mips_clear_insn_labels (); } -/* This function must be called whenever we turn on noreorder or emit - something other than instructions. It inserts any NOPS which might - be needed by the previous instruction, and clears the information - kept for the previous instructions. The INSNS parameter is true if - instructions are to follow. */ +/* This function must be called before we emit something other than + instructions. It is like mips_no_prev_insn except that it inserts + any NOPS that might be needed by previous instructions. */ -static void -mips_emit_delays (bfd_boolean insns) +void +mips_emit_delays (void) { if (! mips_opts.noreorder) { - int nops; - - nops = 0; - if ((! mips_opts.mips16 - && ((prev_insn.insn_mo->pinfo - & (INSN_LOAD_COPROC_DELAY - | INSN_COPROC_MOVE_DELAY - | INSN_WRITE_COND_CODE)) - && ! cop_interlocks)) - || (! hilo_interlocks - && (prev_insn.insn_mo->pinfo - & (INSN_READ_LO - | INSN_READ_HI))) - || (! mips_opts.mips16 - && (prev_insn.insn_mo->pinfo & INSN_LOAD_MEMORY_DELAY) - && ! gpr_interlocks) - || (! mips_opts.mips16 - && (prev_insn.insn_mo->pinfo & INSN_COPROC_MEMORY_DELAY) - && ! cop_mem_interlocks)) - { - /* Itbl support may require additional care here. */ - ++nops; - if ((! mips_opts.mips16 - && ((prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE) - && ! cop_interlocks)) - || (! hilo_interlocks - && ((prev_insn.insn_mo->pinfo & INSN_READ_HI) - || (prev_insn.insn_mo->pinfo & INSN_READ_LO)))) - ++nops; - - if (prev_insn_unreordered) - nops = 0; - } - else if ((! mips_opts.mips16 - && ((prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE) - && ! cop_interlocks)) - || (! hilo_interlocks - && ((prev_prev_insn.insn_mo->pinfo & INSN_READ_HI) - || (prev_prev_insn.insn_mo->pinfo & INSN_READ_LO)))) - { - /* Itbl support may require additional care here. */ - if (! prev_prev_insn_unreordered) - ++nops; - } - - if (mips_fix_vr4120 && prev_insn.insn_mo->name) - { - int min_nops = 0; - const char *pn = prev_insn.insn_mo->name; - if (strncmp(pn, "macc", 4) == 0 - || strncmp(pn, "dmacc", 5) == 0 - || strncmp(pn, "dmult", 5) == 0) - { - min_nops = 1; - } - if (nops < min_nops) - nops = min_nops; - } - + int nops = nops_for_insn (history, NULL); if (nops > 0) { - struct insn_label_list *l; + while (nops-- > 0) + add_fixed_insn (NOP_INSN); + mips_move_labels (); + } + } + mips_no_prev_insn (); +} - if (insns) +/* Start a (possibly nested) noreorder block. */ + +static void +start_noreorder (void) +{ + if (mips_opts.noreorder == 0) + { + unsigned int i; + int nops; + + /* None of the instructions before the .set noreorder can be moved. */ + for (i = 0; i < ARRAY_SIZE (history); i++) + history[i].fixed_p = 1; + + /* Insert any nops that might be needed between the .set noreorder + block and the previous instructions. We will later remove any + nops that turn out not to be needed. */ + nops = nops_for_insn (history, NULL); + if (nops > 0) + { + if (mips_optimize != 0) { /* Record the frag which holds the nop instructions, so that we can remove them if we don't need them. */ @@ -2874,36 +2866,37 @@ mips_emit_delays (bfd_boolean insns) } for (; nops > 0; --nops) - emit_nop (); + add_fixed_insn (NOP_INSN); - if (insns) - { - /* Move on to a new frag, so that it is safe to simply - decrease the size of prev_nop_frag. */ - frag_wane (frag_now); - frag_new (0); - } - - for (l = insn_labels; l != NULL; l = l->next) - { - valueT val; - - assert (S_GET_SEGMENT (l->label) == now_seg); - symbol_set_frag (l->label, frag_now); - val = (valueT) frag_now_fix (); - /* mips16 text labels are stored as odd. */ - if (mips_opts.mips16) - ++val; - S_SET_VALUE (l->label, val); - } + /* Move on to a new frag, so that it is safe to simply + decrease the size of prev_nop_frag. */ + frag_wane (frag_now); + frag_new (0); + mips_move_labels (); } + mips16_mark_labels (); + mips_clear_insn_labels (); } + mips_opts.noreorder++; + mips_any_noreorder = 1; +} - /* Mark instruction labels in mips16 mode. */ - if (insns) - mips16_mark_labels (); +/* End a nested noreorder block. */ - mips_no_prev_insn (insns); +static void +end_noreorder (void) +{ + mips_opts.noreorder--; + if (mips_opts.noreorder == 0 && prev_nop_frag != NULL) + { + /* Commit to inserting prev_nop_frag_required nops and go back to + handling nop insertion the .set reorder way. */ + prev_nop_frag->fr_fix -= ((prev_nop_frag_holds - prev_nop_frag_required) + * (mips_opts.mips16 ? 2 : 4)); + insert_into_history (prev_nop_frag_since, + prev_nop_frag_required, NOP_INSN); + prev_nop_frag = NULL; + } } /* Set up global variables for the start of a new macro. */ @@ -2913,7 +2906,7 @@ macro_start (void) { memset (&mips_macro_warning.sizes, 0, sizeof (mips_macro_warning.sizes)); mips_macro_warning.delay_slot_p = (mips_opts.noreorder - && (prev_insn.insn_mo->pinfo + && (history[0].insn_mo->pinfo & (INSN_UNCOND_BRANCH_DELAY | INSN_COND_BRANCH_DELAY | INSN_COND_BRANCH_LIKELY)) != 0); @@ -2971,6 +2964,24 @@ macro_end (void) } } +/* Read a macro's relocation codes from *ARGS and store them in *R. + The first argument in *ARGS will be either the code for a single + relocation or -1 followed by the three codes that make up a + composite relocation. */ + +static void +macro_read_relocs (va_list *args, bfd_reloc_code_real_type *r) +{ + int i, next; + + next = va_arg (*args, int); + if (next >= 0) + r[0] = (bfd_reloc_code_real_type) next; + else + for (i = 0; i < 3; i++) + r[i] = (bfd_reloc_code_real_type) va_arg (*args, int); +} + /* Build an instruction created by a macro expansion. This is passed a pointer to the count of instructions created so far, an expression, the name of the instruction to build, an operand format @@ -2979,6 +2990,7 @@ macro_end (void) static void macro_build (expressionS *ep, const char *name, const char *fmt, ...) { + const struct mips_opcode *mo; struct mips_cl_insn insn; bfd_reloc_code_real_type r[3]; va_list args; @@ -2995,30 +3007,26 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...) r[0] = BFD_RELOC_UNUSED; r[1] = BFD_RELOC_UNUSED; r[2] = BFD_RELOC_UNUSED; - insn.insn_mo = (struct mips_opcode *) hash_find (op_hash, name); - assert (insn.insn_mo); - assert (strcmp (name, insn.insn_mo->name) == 0); + mo = (struct mips_opcode *) hash_find (op_hash, name); + assert (mo); + assert (strcmp (name, mo->name) == 0); - /* Search until we get a match for NAME. */ - while (1) - { - /* It is assumed here that macros will never generate - MDMX or MIPS-3D instructions. */ - if (strcmp (fmt, insn.insn_mo->args) == 0 - && insn.insn_mo->pinfo != INSN_MACRO - && OPCODE_IS_MEMBER (insn.insn_mo, - (mips_opts.isa - | (file_ase_mips16 ? INSN_MIPS16 : 0)), + /* Search until we get a match for NAME. It is assumed here that + macros will never generate MDMX or MIPS-3D instructions. */ + while (strcmp (fmt, mo->args) != 0 + || mo->pinfo == INSN_MACRO + || !OPCODE_IS_MEMBER (mo, + (mips_opts.isa + | (file_ase_mips16 ? INSN_MIPS16 : 0)), mips_opts.arch) - && (mips_opts.arch != CPU_R4650 || (insn.insn_mo->pinfo & FP_D) == 0)) - break; - - ++insn.insn_mo; - assert (insn.insn_mo->name); - assert (strcmp (name, insn.insn_mo->name) == 0); + || (mips_opts.arch == CPU_R4650 && (mo->pinfo & FP_D) != 0)) + { + ++mo; + assert (mo->name); + assert (strcmp (name, mo->name) == 0); } - insn.insn_opcode = insn.insn_mo->match; + create_insn (&insn, mo); for (;;) { switch (*fmt++) @@ -3036,8 +3044,7 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...) { case 'A': case 'E': - insn.insn_opcode |= (va_arg (args, int) - & OP_MASK_SHAMT) << OP_SH_SHAMT; + INSERT_OPERAND (SHAMT, insn, va_arg (args, int)); continue; case 'B': @@ -3046,8 +3053,7 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...) in MSB form. (When handling the instruction in the non-macro case, these arguments are sizes from which MSB values must be calculated.) */ - insn.insn_opcode |= (va_arg (args, int) - & OP_MASK_INSMSB) << OP_SH_INSMSB; + INSERT_OPERAND (INSMSB, insn, va_arg (args, int)); continue; case 'C': @@ -3057,8 +3063,7 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...) in MSBD form. (When handling the instruction in the non-macro case, these arguments are sizes from which MSBD values must be calculated.) */ - insn.insn_opcode |= (va_arg (args, int) - & OP_MASK_EXTMSBD) << OP_SH_EXTMSBD; + INSERT_OPERAND (EXTMSBD, insn, va_arg (args, int)); continue; default: @@ -3069,72 +3074,72 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...) case 't': case 'w': case 'E': - insn.insn_opcode |= va_arg (args, int) << OP_SH_RT; + INSERT_OPERAND (RT, insn, va_arg (args, int)); continue; case 'c': - insn.insn_opcode |= va_arg (args, int) << OP_SH_CODE; + INSERT_OPERAND (CODE, insn, va_arg (args, int)); continue; case 'T': case 'W': - insn.insn_opcode |= va_arg (args, int) << OP_SH_FT; + INSERT_OPERAND (FT, insn, va_arg (args, int)); continue; case 'd': case 'G': case 'K': - insn.insn_opcode |= va_arg (args, int) << OP_SH_RD; + INSERT_OPERAND (RD, insn, va_arg (args, int)); continue; case 'U': { int tmp = va_arg (args, int); - insn.insn_opcode |= tmp << OP_SH_RT; - insn.insn_opcode |= tmp << OP_SH_RD; + INSERT_OPERAND (RT, insn, tmp); + INSERT_OPERAND (RD, insn, tmp); continue; } case 'V': case 'S': - insn.insn_opcode |= va_arg (args, int) << OP_SH_FS; + INSERT_OPERAND (FS, insn, va_arg (args, int)); continue; case 'z': continue; case '<': - insn.insn_opcode |= va_arg (args, int) << OP_SH_SHAMT; + INSERT_OPERAND (SHAMT, insn, va_arg (args, int)); continue; case 'D': - insn.insn_opcode |= va_arg (args, int) << OP_SH_FD; + INSERT_OPERAND (FD, insn, va_arg (args, int)); continue; case 'B': - insn.insn_opcode |= va_arg (args, int) << OP_SH_CODE20; + INSERT_OPERAND (CODE20, insn, va_arg (args, int)); continue; case 'J': - insn.insn_opcode |= va_arg (args, int) << OP_SH_CODE19; + INSERT_OPERAND (CODE19, insn, va_arg (args, int)); continue; case 'q': - insn.insn_opcode |= va_arg (args, int) << OP_SH_CODE2; + INSERT_OPERAND (CODE2, insn, va_arg (args, int)); continue; case 'b': case 's': case 'r': case 'v': - insn.insn_opcode |= va_arg (args, int) << OP_SH_RS; + INSERT_OPERAND (RS, insn, va_arg (args, int)); continue; case 'i': case 'j': case 'o': - *r = (bfd_reloc_code_real_type) va_arg (args, int); + macro_read_relocs (&args, r); assert (*r == BFD_RELOC_GPREL16 || *r == BFD_RELOC_MIPS_LITERAL || *r == BFD_RELOC_MIPS_HIGHER @@ -3146,13 +3151,11 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...) || *r == BFD_RELOC_MIPS_GOT_PAGE || *r == BFD_RELOC_MIPS_GOT_OFST || *r == BFD_RELOC_MIPS_GOT_LO16 - || *r == BFD_RELOC_MIPS_CALL_LO16 - || (ep->X_op == O_subtract - && *r == BFD_RELOC_PCREL_LO16)); + || *r == BFD_RELOC_MIPS_CALL_LO16); continue; case 'u': - *r = (bfd_reloc_code_real_type) va_arg (args, int); + macro_read_relocs (&args, r); assert (ep != NULL && (ep->X_op == O_constant || (ep->X_op == O_symbol @@ -3161,22 +3164,27 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...) || *r == BFD_RELOC_HI16 || *r == BFD_RELOC_GPREL16 || *r == BFD_RELOC_MIPS_GOT_HI16 - || *r == BFD_RELOC_MIPS_CALL_HI16)) - || (ep->X_op == O_subtract - && *r == BFD_RELOC_PCREL_HI16_S))); + || *r == BFD_RELOC_MIPS_CALL_HI16)))); continue; case 'p': assert (ep != NULL); + /* * This allows macro() to pass an immediate expression for * creating short branches without creating a symbol. - * Note that the expression still might come from the assembly - * input, in which case the value is not checked for range nor - * is a relocation entry generated (yuck). + * + * We don't allow branch relaxation for these branches, as + * they should only appear in ".set nomacro" anyway. */ if (ep->X_op == O_constant) { + if ((ep->X_add_number & 3) != 0) + as_bad (_("branch to misaligned address (0x%lx)"), + (unsigned long) ep->X_add_number); + if ((ep->X_add_number + 0x20000) & ~0x3ffff) + as_bad (_("branch address range overflow (0x%lx)"), + (unsigned long) ep->X_add_number); insn.insn_opcode |= (ep->X_add_number >> 2) & 0xffff; ep = NULL; } @@ -3208,25 +3216,23 @@ static void mips16_macro_build (expressionS *ep, const char *name, const char *fmt, va_list args) { + struct mips_opcode *mo; struct mips_cl_insn insn; bfd_reloc_code_real_type r[3] = {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED}; - insn.insn_mo = (struct mips_opcode *) hash_find (mips16_op_hash, name); - assert (insn.insn_mo); - assert (strcmp (name, insn.insn_mo->name) == 0); + mo = (struct mips_opcode *) hash_find (mips16_op_hash, name); + assert (mo); + assert (strcmp (name, mo->name) == 0); - while (strcmp (fmt, insn.insn_mo->args) != 0 - || insn.insn_mo->pinfo == INSN_MACRO) + while (strcmp (fmt, mo->args) != 0 || mo->pinfo == INSN_MACRO) { - ++insn.insn_mo; - assert (insn.insn_mo->name); - assert (strcmp (name, insn.insn_mo->name) == 0); + ++mo; + assert (mo->name); + assert (strcmp (name, mo->name) == 0); } - insn.insn_opcode = insn.insn_mo->match; - insn.use_extend = FALSE; - + create_insn (&insn, mo); for (;;) { int c; @@ -3244,20 +3250,20 @@ mips16_macro_build (expressionS *ep, const char *name, const char *fmt, case 'y': case 'w': - insn.insn_opcode |= va_arg (args, int) << MIPS16OP_SH_RY; + MIPS16_INSERT_OPERAND (RY, insn, va_arg (args, int)); continue; case 'x': case 'v': - insn.insn_opcode |= va_arg (args, int) << MIPS16OP_SH_RX; + MIPS16_INSERT_OPERAND (RX, insn, va_arg (args, int)); continue; case 'z': - insn.insn_opcode |= va_arg (args, int) << MIPS16OP_SH_RZ; + MIPS16_INSERT_OPERAND (RZ, insn, va_arg (args, int)); continue; case 'Z': - insn.insn_opcode |= va_arg (args, int) << MIPS16OP_SH_MOVE32Z; + MIPS16_INSERT_OPERAND (MOVE32Z, insn, va_arg (args, int)); continue; case '0': @@ -3267,7 +3273,7 @@ mips16_macro_build (expressionS *ep, const char *name, const char *fmt, continue; case 'X': - insn.insn_opcode |= va_arg (args, int) << MIPS16OP_SH_REGR32; + MIPS16_INSERT_OPERAND (REGR32, insn, va_arg (args, int)); continue; case 'Y': @@ -3313,7 +3319,7 @@ mips16_macro_build (expressionS *ep, const char *name, const char *fmt, continue; case '6': - insn.insn_opcode |= va_arg (args, int) << MIPS16OP_SH_IMM6; + MIPS16_INSERT_OPERAND (IMM6, insn, va_arg (args, int)); continue; } @@ -3325,6 +3331,33 @@ mips16_macro_build (expressionS *ep, const char *name, const char *fmt, append_insn (&insn, ep, r); } +/* + * Sign-extend 32-bit mode constants that have bit 31 set and all + * higher bits unset. + */ +static void +normalize_constant_expr (expressionS *ex) +{ + if (ex->X_op == O_constant + && IS_ZEXT_32BIT_NUM (ex->X_add_number)) + ex->X_add_number = (((ex->X_add_number & 0xffffffff) ^ 0x80000000) + - 0x80000000); +} + +/* + * Sign-extend 32-bit mode address offsets that have bit 31 set and + * all higher bits unset. + */ +static void +normalize_address_expr (expressionS *ex) +{ + if (((ex->X_op == O_constant && HAVE_32BIT_ADDRESSES) + || (ex->X_op == O_symbol && HAVE_32BIT_SYMBOLS)) + && IS_ZEXT_32BIT_NUM (ex->X_add_number)) + ex->X_add_number = (((ex->X_add_number & 0xffffffff) ^ 0x80000000) + - 0x80000000); +} + /* * Generate a "jalr" instruction with a relocation hint to the called * function. This occurs in NewABI PIC code. @@ -3352,6 +3385,7 @@ static void macro_build_lui (expressionS *ep, int regnum) { expressionS high_expr; + const struct mips_opcode *mo; struct mips_cl_insn insn; bfd_reloc_code_real_type r[3] = {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED}; @@ -3372,19 +3406,24 @@ macro_build_lui (expressionS *ep, int regnum) else { assert (ep->X_op == O_symbol); - /* _gp_disp is a special case, used from s_cpload. */ + /* _gp_disp is a special case, used from s_cpload. + __gnu_local_gp is used if mips_no_shared. */ assert (mips_pic == NO_PIC || (! HAVE_NEWABI - && strcmp (S_GET_NAME (ep->X_add_symbol), "_gp_disp") == 0)); + && strcmp (S_GET_NAME (ep->X_add_symbol), "_gp_disp") == 0) + || (! mips_in_shared + && strcmp (S_GET_NAME (ep->X_add_symbol), + "__gnu_local_gp") == 0)); *r = BFD_RELOC_HI16_S; } - insn.insn_mo = (struct mips_opcode *) hash_find (op_hash, name); - assert (insn.insn_mo); - assert (strcmp (name, insn.insn_mo->name) == 0); - assert (strcmp (fmt, insn.insn_mo->args) == 0); + mo = hash_find (op_hash, name); + assert (strcmp (name, mo->name) == 0); + assert (strcmp (fmt, mo->args) == 0); + create_insn (&insn, mo); - insn.insn_opcode = insn.insn_mo->match | (regnum << OP_SH_RT); + insn.insn_opcode = insn.insn_mo->match; + INSERT_OPERAND (RT, insn, regnum); if (*r == BFD_RELOC_UNUSED) { insn.insn_opcode |= high_expr.X_add_number; @@ -3404,15 +3443,8 @@ macro_build_ldst_constoffset (expressionS *ep, const char *op, assert (ep->X_op == O_constant); /* Sign-extending 32-bit constants makes their handling easier. */ - if (! dbl && ! ((ep->X_add_number & ~((bfd_vma) 0x7fffffff)) - == ~((bfd_vma) 0x7fffffff))) - { - if (ep->X_add_number & ~((bfd_vma) 0xffffffff)) - as_bad (_("constant too large")); - - ep->X_add_number = (((ep->X_add_number & 0xffffffff) ^ 0x80000000) - - 0x80000000); - } + if (!dbl) + normalize_constant_expr (ep); /* Right now, this routine can only handle signed 32-bit constants. */ if (! IS_SEXT_32BIT_NUM(ep->X_add_number + 0x8000)) @@ -3435,7 +3467,7 @@ macro_build_ldst_constoffset (expressionS *ep, const char *op, macro_build (ep, op, "t,o(b)", treg, BFD_RELOC_LO16, AT); if (mips_opts.noat) - as_warn (_("Macro used $at after \".set noat\"")); + as_bad (_("Macro used $at after \".set noat\"")); } } @@ -3458,14 +3490,6 @@ set_at (int reg, int unsignedp) } } -static void -normalize_constant_expr (expressionS *ex) -{ - if (ex->X_op == O_constant && HAVE_32BIT_GPRS) - ex->X_add_number = (((ex->X_add_number & 0xffffffff) ^ 0x80000000) - - 0x80000000); -} - /* Warn if an expression is not a constant. */ static void @@ -3474,9 +3498,11 @@ check_absolute_expr (struct mips_cl_insn *ip, expressionS *ex) if (ex->X_op == O_big) as_bad (_("unsupported large constant")); else if (ex->X_op != O_constant) - as_bad (_("Instruction %s requires absolute expression"), ip->insn_mo->name); + as_bad (_("Instruction %s requires absolute expression"), + ip->insn_mo->name); - normalize_constant_expr (ex); + if (HAVE_32BIT_GPRS) + normalize_constant_expr (ex); } /* Count the leading zeroes by performing a binary chop. This is a @@ -3570,15 +3596,8 @@ load_register (int reg, expressionS *ep, int dbl) assert (ep->X_op == O_constant); /* Sign-extending 32-bit constants makes their handling easier. */ - if (! dbl && ! ((ep->X_add_number & ~((bfd_vma) 0x7fffffff)) - == ~((bfd_vma) 0x7fffffff))) - { - if (ep->X_add_number & ~((bfd_vma) 0xffffffff)) - as_bad (_("constant too large")); - - ep->X_add_number = (((ep->X_add_number & 0xffffffff) ^ 0x80000000) - - 0x80000000); - } + if (!dbl) + normalize_constant_expr (ep); if (IS_SEXT_16BIT_NUM (ep->X_add_number)) { @@ -3607,10 +3626,12 @@ load_register (int reg, expressionS *ep, int dbl) /* The value is larger than 32 bits. */ - if (HAVE_32BIT_GPRS) + if (!dbl || HAVE_32BIT_GPRS) { - as_bad (_("Number (0x%lx) larger than 32 bits"), - (unsigned long) ep->X_add_number); + char value[32]; + + sprintf_vma (value, ep->X_add_number); + as_bad (_("Number (0x%s) larger than 32 bits"), value); macro_build (ep, "addiu", "t,r,j", reg, 0, BFD_RELOC_LO16); return; } @@ -3792,6 +3813,13 @@ load_register (int reg, expressionS *ep, int dbl) macro_build (&lo32, "ori", "t,r,i", reg, freg, BFD_RELOC_LO16); } +static inline void +load_delay_nop (void) +{ + if (!gpr_interlocks) + macro_build (NULL, "nop", ""); +} + /* Load an address into a register. */ static void @@ -3835,14 +3863,21 @@ load_address (int reg, expressionS *ep, int *used_at) daddiu $reg, (BFD_RELOC_HI16_S) dsll $reg,16 daddiu $reg, (BFD_RELOC_LO16) - */ - if (HAVE_64BIT_ADDRESSES) - { - /* ??? We don't provide a GP-relative alternative for these macros. - It used not to be possible with the original relaxation code, - but it could be done now. */ - if (*used_at == 0 && ! mips_opts.noat) + For GP relative symbols in 64bit address space we can use + the same sequence as in 32bit address space. */ + if (HAVE_64BIT_SYMBOLS) + { + if ((valueT) ep->X_add_number <= MAX_GPREL_OFFSET + && !nopic_need_relax (ep->X_add_symbol, 1)) + { + relax_start (ep->X_add_symbol); + macro_build (ep, ADDRESS_ADDI_INSN, "t,r,j", reg, + mips_gp_register, BFD_RELOC_GPREL16); + relax_switch (); + } + + if (*used_at == 0 && !mips_opts.noat) { macro_build (ep, "lui", "t,u", reg, BFD_RELOC_MIPS_HIGHEST); macro_build (ep, "lui", "t,u", AT, BFD_RELOC_HI16_S); @@ -3863,11 +3898,14 @@ load_address (int reg, expressionS *ep, int *used_at) macro_build (NULL, "dsll", "d,w,<", reg, reg, 16); macro_build (ep, "daddiu", "t,r,j", reg, reg, BFD_RELOC_LO16); } + + if (mips_relax.sequence) + relax_end (); } else { if ((valueT) ep->X_add_number <= MAX_GPREL_OFFSET - && ! nopic_need_relax (ep->X_add_symbol, 1)) + && !nopic_need_relax (ep->X_add_symbol, 1)) { relax_start (ep->X_add_symbol); macro_build (ep, ADDRESS_ADDI_INSN, "t,r,j", reg, @@ -3881,7 +3919,7 @@ load_address (int reg, expressionS *ep, int *used_at) relax_end (); } } - else if (mips_pic == SVR4_PIC && ! mips_big_got) + else if (!mips_big_got) { expressionS ex; @@ -3925,7 +3963,7 @@ load_address (int reg, expressionS *ep, int *used_at) ep->X_add_number = 0; macro_build (ep, ADDRESS_LOAD_INSN, "t,o(b)", reg, BFD_RELOC_MIPS_GOT16, mips_gp_register); - macro_build (NULL, "nop", ""); + load_delay_nop (); relax_start (ep->X_add_symbol); relax_switch (); macro_build (ep, ADDRESS_ADDI_INSN, "t,r,j", reg, reg, @@ -3942,7 +3980,7 @@ load_address (int reg, expressionS *ep, int *used_at) } } } - else if (mips_pic == SVR4_PIC) + else if (mips_big_got) { expressionS ex; @@ -4010,7 +4048,7 @@ load_address (int reg, expressionS *ep, int *used_at) } macro_build (ep, ADDRESS_LOAD_INSN, "t,o(b)", reg, BFD_RELOC_MIPS_GOT16, mips_gp_register); - macro_build (NULL, "nop", ""); + load_delay_nop (); macro_build (ep, ADDRESS_ADDI_INSN, "t,r,j", reg, reg, BFD_RELOC_LO16); relax_end (); @@ -4025,16 +4063,11 @@ load_address (int reg, expressionS *ep, int *used_at) } } } - else if (mips_pic == EMBEDDED_PIC) - { - /* We always do - addiu $reg,$gp, (BFD_RELOC_GPREL16) - */ - macro_build (ep, ADDRESS_ADDI_INSN, "t,r,j", - reg, mips_gp_register, BFD_RELOC_GPREL16); - } else abort (); + + if (mips_opts.noat && *used_at == 1) + as_bad (_("Macro used $at after \".set noat\"")); } /* Move the contents of register SOURCE into register DEST. */ @@ -4183,9 +4216,7 @@ macro (struct mips_cl_insn *ip) sub v0,$zero,$a0 */ - mips_emit_delays (TRUE); - ++mips_opts.noreorder; - mips_any_noreorder = 1; + start_noreorder (); expr1.X_add_number = 8; macro_build (&expr1, "bgez", "s,p", sreg); @@ -4195,8 +4226,8 @@ macro (struct mips_cl_insn *ip) move_register (dreg, sreg); macro_build (NULL, dbl ? "dsub" : "sub", "d,v,t", dreg, 0, sreg); - --mips_opts.noreorder; - return; + end_noreorder (); + break; case M_ADD_I: s = "addi"; @@ -4221,8 +4252,9 @@ macro (struct mips_cl_insn *ip) && imm_expr.X_add_number < 0x8000) { macro_build (&imm_expr, s, "t,r,j", treg, sreg, BFD_RELOC_LO16); - return; + break; } + used_at = 1; load_register (AT, &imm_expr, dbl); macro_build (NULL, s2, "d,v,t", treg, sreg, AT); break; @@ -4255,9 +4287,10 @@ macro (struct mips_cl_insn *ip) treg, sreg, BFD_RELOC_LO16); macro_build (NULL, "nor", "d,v,t", treg, treg, 0); } - return; + break; } + used_at = 1; load_register (AT, &imm_expr, HAVE_64BIT_GPRS); macro_build (NULL, s2, "d,v,t", treg, sreg, AT); break; @@ -4279,8 +4312,9 @@ macro (struct mips_cl_insn *ip) if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0) { macro_build (&offset_expr, s, "s,t,p", sreg, 0); - return; + break; } + used_at = 1; load_register (AT, &imm_expr, HAVE_64BIT_GPRS); macro_build (&offset_expr, s, "s,t,p", sreg, AT); break; @@ -4291,13 +4325,14 @@ macro (struct mips_cl_insn *ip) if (treg == 0) { macro_build (&offset_expr, likely ? "bgezl" : "bgez", "s,p", sreg); - return; + break; } if (sreg == 0) { macro_build (&offset_expr, likely ? "blezl" : "blez", "s,p", treg); - return; + break; } + used_at = 1; macro_build (NULL, "slt", "d,v,t", AT, sreg, treg); macro_build (&offset_expr, likely ? "beql" : "beq", "s,t,p", AT, 0); break; @@ -4324,7 +4359,7 @@ macro (struct mips_cl_insn *ip) macro_build (NULL, "nop", "", 0); else macro_build (&offset_expr, "bnel", "s,t,p", 0, 0); - return; + break; } if (imm_expr.X_op != O_constant) as_bad (_("Unsupported large constant")); @@ -4337,12 +4372,12 @@ macro (struct mips_cl_insn *ip) if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0) { macro_build (&offset_expr, likely ? "bgezl" : "bgez", "s,p", sreg); - return; + break; } if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1) { macro_build (&offset_expr, likely ? "bgtzl" : "bgtz", "s,p", sreg); - return; + break; } maxnum = 0x7fffffff; if (HAVE_64BIT_GPRS && sizeof (maxnum) > 4) @@ -4361,8 +4396,9 @@ macro (struct mips_cl_insn *ip) /* result is always true */ as_warn (_("Branch %s is always true"), ip->insn_mo->name); macro_build (&offset_expr, "b", "p"); - return; + break; } + used_at = 1; set_at (sreg, 0); macro_build (&offset_expr, likely ? "beql" : "beq", "s,t,p", AT, 0); break; @@ -4376,8 +4412,9 @@ macro (struct mips_cl_insn *ip) { macro_build (&offset_expr, likely ? "beql" : "beq", "s,t,p", 0, treg); - return; + break; } + used_at = 1; macro_build (NULL, "sltu", "d,v,t", AT, sreg, treg); macro_build (&offset_expr, likely ? "beql" : "beq", "s,t,p", AT, 0); break; @@ -4404,8 +4441,9 @@ macro (struct mips_cl_insn *ip) { macro_build (&offset_expr, likely ? "bnel" : "bne", "s,t,p", sreg, 0); - return; + break; } + used_at = 1; set_at (sreg, 1); macro_build (&offset_expr, likely ? "beql" : "beq", "s,t,p", AT, 0); break; @@ -4416,13 +4454,14 @@ macro (struct mips_cl_insn *ip) if (treg == 0) { macro_build (&offset_expr, likely ? "bgtzl" : "bgtz", "s,p", sreg); - return; + break; } if (sreg == 0) { macro_build (&offset_expr, likely ? "bltzl" : "bltz", "s,p", treg); - return; + break; } + used_at = 1; macro_build (NULL, "slt", "d,v,t", AT, treg, sreg); macro_build (&offset_expr, likely ? "bnel" : "bne", "s,t,p", AT, 0); break; @@ -4434,10 +4473,11 @@ macro (struct mips_cl_insn *ip) { macro_build (&offset_expr, likely ? "bnel" : "bne", "s,t,p", sreg, 0); - return; + break; } if (sreg == 0) goto do_false; + used_at = 1; macro_build (NULL, "sltu", "d,v,t", AT, treg, sreg); macro_build (&offset_expr, likely ? "bnel" : "bne", "s,t,p", AT, 0); break; @@ -4448,13 +4488,14 @@ macro (struct mips_cl_insn *ip) if (treg == 0) { macro_build (&offset_expr, likely ? "blezl" : "blez", "s,p", sreg); - return; + break; } if (sreg == 0) { macro_build (&offset_expr, likely ? "bgezl" : "bgez", "s,p", treg); - return; + break; } + used_at = 1; macro_build (NULL, "slt", "d,v,t", AT, treg, sreg); macro_build (&offset_expr, likely ? "beql" : "beq", "s,t,p", AT, 0); break; @@ -4485,13 +4526,14 @@ macro (struct mips_cl_insn *ip) if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0) { macro_build (&offset_expr, likely ? "bltzl" : "bltz", "s,p", sreg); - return; + break; } if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1) { macro_build (&offset_expr, likely ? "blezl" : "blez", "s,p", sreg); - return; + break; } + used_at = 1; set_at (sreg, 0); macro_build (&offset_expr, likely ? "bnel" : "bne", "s,t,p", AT, 0); break; @@ -4503,10 +4545,11 @@ macro (struct mips_cl_insn *ip) { macro_build (&offset_expr, likely ? "beql" : "beq", "s,t,p", sreg, 0); - return; + break; } if (sreg == 0) goto do_true; + used_at = 1; macro_build (NULL, "sltu", "d,v,t", AT, treg, sreg); macro_build (&offset_expr, likely ? "beql" : "beq", "s,t,p", AT, 0); break; @@ -4533,8 +4576,9 @@ macro (struct mips_cl_insn *ip) { macro_build (&offset_expr, likely ? "beql" : "beq", "s,t,p", sreg, 0); - return; + break; } + used_at = 1; set_at (sreg, 1); macro_build (&offset_expr, likely ? "bnel" : "bne", "s,t,p", AT, 0); break; @@ -4545,13 +4589,14 @@ macro (struct mips_cl_insn *ip) if (treg == 0) { macro_build (&offset_expr, likely ? "bltzl" : "bltz", "s,p", sreg); - return; + break; } if (sreg == 0) { macro_build (&offset_expr, likely ? "bgtzl" : "bgtz", "s,p", treg); - return; + break; } + used_at = 1; macro_build (NULL, "slt", "d,v,t", AT, sreg, treg); macro_build (&offset_expr, likely ? "bnel" : "bne", "s,t,p", AT, 0); break; @@ -4565,8 +4610,9 @@ macro (struct mips_cl_insn *ip) { macro_build (&offset_expr, likely ? "bnel" : "bne", "s,t,p", 0, treg); - return; + break; } + used_at = 1; macro_build (NULL, "sltu", "d,v,t", AT, sreg, treg); macro_build (&offset_expr, likely ? "bnel" : "bne", "s,t,p", AT, 0); break; @@ -4617,7 +4663,7 @@ macro (struct mips_cl_insn *ip) } macro_build ((expressionS *) NULL, s, fmt, treg, sreg, pos, size - 1); } - return; + break; case M_DINS: { @@ -4666,7 +4712,7 @@ macro (struct mips_cl_insn *ip) macro_build ((expressionS *) NULL, s, fmt, treg, sreg, pos, pos + size - 1); } - return; + break; case M_DDIV_3: dbl = 1; @@ -4685,12 +4731,10 @@ macro (struct mips_cl_insn *ip) macro_build (NULL, "teq", "s,t,q", 0, 0, 7); else macro_build (NULL, "break", "c", 7); - return; + break; } - mips_emit_delays (TRUE); - ++mips_opts.noreorder; - mips_any_noreorder = 1; + start_noreorder (); if (mips_trap) { macro_build (NULL, "teq", "s,t,q", treg, 0, 7); @@ -4704,6 +4748,7 @@ macro (struct mips_cl_insn *ip) macro_build (NULL, "break", "c", 7); } expr1.X_add_number = -1; + used_at = 1; load_register (AT, &expr1, dbl); expr1.X_add_number = mips_trap ? (dbl ? 12 : 8) : (dbl ? 20 : 16); macro_build (&expr1, "bne", "s,t,p", treg, AT); @@ -4723,7 +4768,7 @@ macro (struct mips_cl_insn *ip) macro_build (NULL, "teq", "s,t,q", sreg, AT, 6); /* We want to close the noreorder block as soon as possible, so that later insns are available for delay slot filling. */ - --mips_opts.noreorder; + end_noreorder (); } else { @@ -4733,7 +4778,7 @@ macro (struct mips_cl_insn *ip) /* We want to close the noreorder block as soon as possible, so that later insns are available for delay slot filling. */ - --mips_opts.noreorder; + end_noreorder (); macro_build (NULL, "break", "c", 6); } @@ -4783,7 +4828,7 @@ macro (struct mips_cl_insn *ip) macro_build (NULL, "teq", "s,t,q", 0, 0, 7); else macro_build (NULL, "break", "c", 7); - return; + break; } if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1) { @@ -4791,7 +4836,7 @@ macro (struct mips_cl_insn *ip) move_register (dreg, sreg); else move_register (dreg, 0); - return; + break; } if (imm_expr.X_op == O_constant && imm_expr.X_add_number == -1 @@ -4803,9 +4848,10 @@ macro (struct mips_cl_insn *ip) } else move_register (dreg, 0); - return; + break; } + used_at = 1; load_register (AT, &imm_expr, dbl); macro_build (NULL, s, "z,s,t", sreg, AT); macro_build (NULL, s2, "d", dreg); @@ -4827,16 +4873,14 @@ macro (struct mips_cl_insn *ip) s = "ddivu"; s2 = "mfhi"; do_divu3: - mips_emit_delays (TRUE); - ++mips_opts.noreorder; - mips_any_noreorder = 1; + start_noreorder (); if (mips_trap) { macro_build (NULL, "teq", "s,t,q", treg, 0, 7); macro_build (NULL, s, "z,s,t", sreg, treg); /* We want to close the noreorder block as soon as possible, so that later insns are available for delay slot filling. */ - --mips_opts.noreorder; + end_noreorder (); } else { @@ -4846,11 +4890,11 @@ macro (struct mips_cl_insn *ip) /* We want to close the noreorder block as soon as possible, so that later insns are available for delay slot filling. */ - --mips_opts.noreorder; + end_noreorder (); macro_build (NULL, "break", "c", 7); } macro_build (NULL, s2, "d", dreg); - return; + break; case M_DLCA_AB: dbl = 1; @@ -4874,13 +4918,12 @@ macro (struct mips_cl_insn *ip) && offset_expr.X_add_number >= -0x8000 && offset_expr.X_add_number < 0x8000) { - macro_build (&offset_expr, - (dbl || HAVE_64BIT_ADDRESSES) ? "daddiu" : "addiu", + macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", treg, sreg, BFD_RELOC_LO16); - return; + break; } - if (treg == breg) + if (!mips_opts.noat && (treg == breg)) { tempreg = AT; used_at = 1; @@ -4888,51 +4931,6 @@ macro (struct mips_cl_insn *ip) else { tempreg = treg; - used_at = 0; - } - - /* When generating embedded PIC code, we permit expressions of - the form - la $treg,foo-bar - la $treg,foo-bar($breg) - where bar is an address in the current section. These are used - when getting the addresses of functions. We don't permit - X_add_number to be non-zero, because if the symbol is - external the relaxing code needs to know that any addend is - purely the offset to X_op_symbol. */ - if (mips_pic == EMBEDDED_PIC - && offset_expr.X_op == O_subtract - && (symbol_constant_p (offset_expr.X_op_symbol) - ? S_GET_SEGMENT (offset_expr.X_op_symbol) == now_seg - : (symbol_equated_p (offset_expr.X_op_symbol) - && (S_GET_SEGMENT - (symbol_get_value_expression (offset_expr.X_op_symbol) - ->X_add_symbol) - == now_seg))) - && (offset_expr.X_add_number == 0 - || OUTPUT_FLAVOR == bfd_target_elf_flavour)) - { - if (breg == 0) - { - tempreg = treg; - used_at = 0; - macro_build (&offset_expr, "lui", "t,u", - tempreg, BFD_RELOC_PCREL_HI16_S); - } - else - { - macro_build (&offset_expr, "lui", "t,u", - tempreg, BFD_RELOC_PCREL_HI16_S); - macro_build (NULL, - (dbl || HAVE_64BIT_ADDRESSES) ? "daddu" : "addu", - "d,v,t", tempreg, tempreg, breg); - } - macro_build (&offset_expr, - (dbl || HAVE_64BIT_ADDRESSES) ? "daddiu" : "addiu", - "t,r,j", treg, tempreg, BFD_RELOC_PCREL_LO16); - if (! used_at) - return; - break; } if (offset_expr.X_op != O_symbol @@ -4943,10 +4941,7 @@ macro (struct mips_cl_insn *ip) } if (offset_expr.X_op == O_constant) - load_register (tempreg, &offset_expr, - ((mips_pic == EMBEDDED_PIC || mips_pic == NO_PIC) - ? (dbl || HAVE_64BIT_ADDRESSES) - : HAVE_64BIT_ADDRESSES)); + load_register (tempreg, &offset_expr, HAVE_64BIT_ADDRESSES); else if (mips_pic == NO_PIC) { /* If this is a reference to a GP relative symbol, we want @@ -4957,30 +4952,37 @@ macro (struct mips_cl_insn *ip) If we have a constant, we need two instructions anyhow, so we may as well always use the latter form. - With 64bit address space and a usable $at we want - lui $tempreg, (BFD_RELOC_MIPS_HIGHEST) - lui $at, (BFD_RELOC_HI16_S) - daddiu $tempreg, (BFD_RELOC_MIPS_HIGHER) - daddiu $at, (BFD_RELOC_LO16) - dsll32 $tempreg,0 - daddu $tempreg,$tempreg,$at + With 64bit address space and a usable $at we want + lui $tempreg, (BFD_RELOC_MIPS_HIGHEST) + lui $at, (BFD_RELOC_HI16_S) + daddiu $tempreg, (BFD_RELOC_MIPS_HIGHER) + daddiu $at, (BFD_RELOC_LO16) + dsll32 $tempreg,0 + daddu $tempreg,$tempreg,$at - If $at is already in use, we use a path which is suboptimal - on superscalar processors. - lui $tempreg, (BFD_RELOC_MIPS_HIGHEST) - daddiu $tempreg, (BFD_RELOC_MIPS_HIGHER) - dsll $tempreg,16 - daddiu $tempreg, (BFD_RELOC_HI16_S) - dsll $tempreg,16 - daddiu $tempreg, (BFD_RELOC_LO16) - */ - if (HAVE_64BIT_ADDRESSES) + If $at is already in use, we use a path which is suboptimal + on superscalar processors. + lui $tempreg, (BFD_RELOC_MIPS_HIGHEST) + daddiu $tempreg, (BFD_RELOC_MIPS_HIGHER) + dsll $tempreg,16 + daddiu $tempreg, (BFD_RELOC_HI16_S) + dsll $tempreg,16 + daddiu $tempreg, (BFD_RELOC_LO16) + + For GP relative symbols in 64bit address space we can use + the same sequence as in 32bit address space. */ + if (HAVE_64BIT_SYMBOLS) { - /* ??? We don't provide a GP-relative alternative for - these macros. It used not to be possible with the - original relaxation code, but it could be done now. */ + if ((valueT) offset_expr.X_add_number <= MAX_GPREL_OFFSET + && !nopic_need_relax (offset_expr.X_add_symbol, 1)) + { + relax_start (offset_expr.X_add_symbol); + macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", + tempreg, mips_gp_register, BFD_RELOC_GPREL16); + relax_switch (); + } - if (used_at == 0 && ! mips_opts.noat) + if (used_at == 0 && !mips_opts.noat) { macro_build (&offset_expr, "lui", "t,u", tempreg, BFD_RELOC_MIPS_HIGHEST); @@ -5007,17 +5009,22 @@ macro (struct mips_cl_insn *ip) macro_build (&offset_expr, "daddiu", "t,r,j", tempreg, tempreg, BFD_RELOC_LO16); } + + if (mips_relax.sequence) + relax_end (); } else { if ((valueT) offset_expr.X_add_number <= MAX_GPREL_OFFSET - && ! nopic_need_relax (offset_expr.X_add_symbol, 1)) + && !nopic_need_relax (offset_expr.X_add_symbol, 1)) { relax_start (offset_expr.X_add_symbol); macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", tempreg, mips_gp_register, BFD_RELOC_GPREL16); relax_switch (); } + if (!IS_SEXT_32BIT_NUM (offset_expr.X_add_number)) + as_bad (_("offset too large")); macro_build_lui (&offset_expr, tempreg); macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", tempreg, tempreg, BFD_RELOC_LO16); @@ -5025,7 +5032,7 @@ macro (struct mips_cl_insn *ip) relax_end (); } } - else if (mips_pic == SVR4_PIC && ! mips_big_got && ! HAVE_NEWABI) + else if (!mips_big_got && !HAVE_NEWABI) { int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16; @@ -5061,7 +5068,9 @@ macro (struct mips_cl_insn *ip) if (offset_expr.X_add_number == 0) { - if (breg == 0 && (call || tempreg == PIC_CALL_REG)) + if (mips_pic == SVR4_PIC + && breg == 0 + && (call || tempreg == PIC_CALL_REG)) lw_reloc_type = (int) BFD_RELOC_MIPS_CALL16; relax_start (offset_expr.X_add_symbol); @@ -5072,12 +5081,12 @@ macro (struct mips_cl_insn *ip) /* We're going to put in an addu instruction using tempreg, so we may as well insert the nop right now. */ - macro_build (NULL, "nop", ""); + load_delay_nop (); } relax_switch (); macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg, BFD_RELOC_MIPS_GOT16, mips_gp_register); - macro_build (NULL, "nop", ""); + load_delay_nop (); macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", tempreg, tempreg, BFD_RELOC_LO16); relax_end (); @@ -5089,7 +5098,7 @@ macro (struct mips_cl_insn *ip) && offset_expr.X_add_number < 0x8000) { load_got_offset (tempreg, &offset_expr); - macro_build (NULL, "nop", ""); + load_delay_nop (); add_got_offset (tempreg, &offset_expr); } else @@ -5108,7 +5117,7 @@ macro (struct mips_cl_insn *ip) not using a base register. */ if (breg == treg) { - macro_build (NULL, "nop", ""); + load_delay_nop (); macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", treg, AT, breg); breg = 0; @@ -5118,7 +5127,7 @@ macro (struct mips_cl_insn *ip) used_at = 1; } } - else if (mips_pic == SVR4_PIC && ! mips_big_got && HAVE_NEWABI) + else if (!mips_big_got && HAVE_NEWABI) { int add_breg_early = 0; @@ -5221,7 +5230,7 @@ macro (struct mips_cl_insn *ip) BFD_RELOC_MIPS_GOT_DISP, mips_gp_register); } } - else if (mips_pic == SVR4_PIC && ! HAVE_NEWABI) + else if (mips_big_got && !HAVE_NEWABI) { int gpdelay; int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16; @@ -5291,13 +5300,13 @@ macro (struct mips_cl_insn *ip) /* We're going to put in an addu instruction using tempreg, so we may as well insert the nop right now. */ - macro_build (NULL, "nop", ""); + load_delay_nop (); } } else if (expr1.X_add_number >= -0x8000 && expr1.X_add_number < 0x8000) { - macro_build (NULL, "nop", ""); + load_delay_nop (); macro_build (&expr1, ADDRESS_ADDI_INSN, "t,r,j", tempreg, tempreg, BFD_RELOC_LO16); } @@ -5317,7 +5326,7 @@ macro (struct mips_cl_insn *ip) else { assert (tempreg == AT); - macro_build (NULL, "nop", ""); + load_delay_nop (); macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", treg, AT, breg); dreg = treg; @@ -5344,7 +5353,7 @@ macro (struct mips_cl_insn *ip) if (expr1.X_add_number >= -0x8000 && expr1.X_add_number < 0x8000) { - macro_build (NULL, "nop", ""); + load_delay_nop (); macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", tempreg, tempreg, BFD_RELOC_LO16); /* FIXME: If add_number is 0, and there was no base @@ -5360,7 +5369,7 @@ macro (struct mips_cl_insn *ip) /* We must add in the base register now, as in the external symbol case. */ assert (tempreg == AT); - macro_build (NULL, "nop", ""); + load_delay_nop (); macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", treg, AT, breg); tempreg = treg; @@ -5374,10 +5383,11 @@ macro (struct mips_cl_insn *ip) AT, AT, BFD_RELOC_LO16); macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", tempreg, tempreg, AT); + used_at = 1; } relax_end (); } - else if (mips_pic == SVR4_PIC && HAVE_NEWABI) + else if (mips_big_got && HAVE_NEWABI) { int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16; int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_LO16; @@ -5484,32 +5494,11 @@ macro (struct mips_cl_insn *ip) } relax_end (); } - else if (mips_pic == EMBEDDED_PIC) - { - /* We use - addiu $tempreg,$gp, (BFD_RELOC_GPREL16) - */ - macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", tempreg, - mips_gp_register, BFD_RELOC_GPREL16); - } else abort (); if (breg != 0) - { - char *s; - - if (mips_pic == EMBEDDED_PIC || mips_pic == NO_PIC) - s = (dbl || HAVE_64BIT_ADDRESSES) ? "daddu" : "addu"; - else - s = ADDRESS_ADD_INSN; - - macro_build (NULL, s, "d,v,t", treg, tempreg, breg); - } - - if (! used_at) - return; - + macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", treg, tempreg, breg); break; case M_J_A: @@ -5520,7 +5509,7 @@ macro (struct mips_cl_insn *ip) macro_build (&offset_expr, "j", "a"); else macro_build (&offset_expr, "b", "p"); - return; + break; /* The jal instructions must be handled as macros because when generating PIC code they expand to multi-instruction @@ -5529,16 +5518,15 @@ macro (struct mips_cl_insn *ip) dreg = RA; /* Fall through. */ case M_JAL_2: - if (mips_pic == NO_PIC - || mips_pic == EMBEDDED_PIC) + if (mips_pic == NO_PIC) macro_build (NULL, "jalr", "d,s", dreg, sreg); - else if (mips_pic == SVR4_PIC) + else { if (sreg != PIC_CALL_REG) as_warn (_("MIPS PIC call to register other than $25")); macro_build (NULL, "jalr", "d,s", dreg, sreg); - if (! HAVE_NEWABI) + if (mips_pic == SVR4_PIC && !HAVE_NEWABI) { if (mips_cprestore_offset < 0) as_warn (_("No .cprestore pseudo-op used in PIC code")); @@ -5564,10 +5552,8 @@ macro (struct mips_cl_insn *ip) } } } - else - abort (); - return; + break; case M_JAL_A: if (mips_pic == NO_PIC) @@ -5646,7 +5632,7 @@ macro (struct mips_cl_insn *ip) macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", PIC_CALL_REG, BFD_RELOC_MIPS_CALL16, mips_gp_register); - macro_build (NULL, "nop", ""); + load_delay_nop (); relax_switch (); } else @@ -5661,7 +5647,7 @@ macro (struct mips_cl_insn *ip) macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", PIC_CALL_REG, BFD_RELOC_MIPS_CALL_LO16, PIC_CALL_REG); - macro_build (NULL, "nop", ""); + load_delay_nop (); relax_switch (); if (gpdelay) macro_build (NULL, "nop", ""); @@ -5669,7 +5655,7 @@ macro (struct mips_cl_insn *ip) macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", PIC_CALL_REG, BFD_RELOC_MIPS_GOT16, mips_gp_register); - macro_build (NULL, "nop", ""); + load_delay_nop (); macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", PIC_CALL_REG, PIC_CALL_REG, BFD_RELOC_LO16); relax_end (); @@ -5701,17 +5687,10 @@ macro (struct mips_cl_insn *ip) } } } - else if (mips_pic == EMBEDDED_PIC) - { - macro_build (&offset_expr, "bal", "p"); - /* The linker may expand the call to a longer sequence which - uses $at, so we must break rather than return. */ - break; - } else abort (); - return; + break; case M_LB_AB: s = "lb"; @@ -5760,7 +5739,7 @@ macro (struct mips_cl_insn *ip) if (mips_opts.arch == CPU_R4650) { as_bad (_("opcode not supported on this processor")); - return; + break; } s = "ldc1"; /* Itbl support may require additional care here. */ @@ -5793,6 +5772,16 @@ macro (struct mips_cl_insn *ip) case M_LWU_AB: s = "lwu"; ld: + if (mips_opts.arch == CPU_OCTEON + && octeon_error_on_unsupported + && (mask == M_LDC1_AB || mask == M_LDC2_AB || mask == M_LDC3_AB + || mask == M_L_DOB || mask == M_L_DAB + || mask == M_LI_D || mask == M_LI_DD + || mask == M_LI_S || mask == M_LI_SS)) + { + as_bad (_("opcode not implemented in Octeon `%s'"), ip->insn_mo->name); + return; + } if (breg == treg || coproc || lr) { tempreg = AT; @@ -5801,7 +5790,6 @@ macro (struct mips_cl_insn *ip) else { tempreg = treg; - used_at = 0; } goto ld_st; case M_SB_AB: @@ -5849,7 +5837,7 @@ macro (struct mips_cl_insn *ip) if (mips_opts.arch == CPU_R4650) { as_bad (_("opcode not supported on this processor")); - return; + break; } s = "sdc1"; coproc = 1; @@ -5871,6 +5859,15 @@ macro (struct mips_cl_insn *ip) case M_SDR_AB: s = "sdr"; st: + if (mips_opts.arch == CPU_OCTEON + && octeon_error_on_unsupported + && (mask == M_SWC0_AB || mask == M_SWC1_AB || mask == M_SWC2_AB + || mask == M_SDC1_AB || mask == M_SDC2_AB || mask == M_SDC3_AB + || mask == M_S_DAB || mask == M_S_DOB)) + { + as_bad (_("opcode not implemented in Octeon `%s'"), ip->insn_mo->name); + return; + } tempreg = AT; used_at = 1; ld_st: @@ -5887,62 +5884,6 @@ macro (struct mips_cl_insn *ip) else fmt = "t,o(b)"; - /* Sign-extending 32-bit constants makes their handling easier. - The HAVE_64BIT_GPRS... part is due to the linux kernel hack - described below. */ - if ((! HAVE_64BIT_ADDRESSES - && (! HAVE_64BIT_GPRS && offset_expr.X_op == O_constant)) - && (offset_expr.X_op == O_constant) - && ! ((offset_expr.X_add_number & ~((bfd_vma) 0x7fffffff)) - == ~((bfd_vma) 0x7fffffff))) - { - if (offset_expr.X_add_number & ~((bfd_vma) 0xffffffff)) - as_bad (_("constant too large")); - - offset_expr.X_add_number = (((offset_expr.X_add_number & 0xffffffff) - ^ 0x80000000) - 0x80000000); - } - - /* For embedded PIC, we allow loads where the offset is calculated - by subtracting a symbol in the current segment from an unknown - symbol, relative to a base register, e.g.: - $treg, -($breg) - This is used by the compiler for switch statements. */ - if (mips_pic == EMBEDDED_PIC - && offset_expr.X_op == O_subtract - && (symbol_constant_p (offset_expr.X_op_symbol) - ? S_GET_SEGMENT (offset_expr.X_op_symbol) == now_seg - : (symbol_equated_p (offset_expr.X_op_symbol) - && (S_GET_SEGMENT - (symbol_get_value_expression (offset_expr.X_op_symbol) - ->X_add_symbol) - == now_seg))) - && breg != 0 - && (offset_expr.X_add_number == 0 - || OUTPUT_FLAVOR == bfd_target_elf_flavour)) - { - /* For this case, we output the instructions: - lui $tempreg, (BFD_RELOC_PCREL_HI16_S) - addiu $tempreg,$tempreg,$breg - $treg,($tempreg) (BFD_RELOC_PCREL_LO16) - If the relocation would fit entirely in 16 bits, it would be - nice to emit: - $treg,($breg) (BFD_RELOC_PCREL_LO16) - instead, but that seems quite difficult. */ - macro_build (&offset_expr, "lui", "t,u", tempreg, - BFD_RELOC_PCREL_HI16_S); - macro_build (NULL, - ((bfd_arch_bits_per_address (stdoutput) == 32 - || ! ISA_HAS_64BIT_REGS (mips_opts.isa)) - ? "addu" : "daddu"), - "d,v,t", tempreg, tempreg, breg); - macro_build (&offset_expr, s, fmt, treg, - BFD_RELOC_PCREL_LO16, tempreg); - if (! used_at) - return; - break; - } - if (offset_expr.X_op != O_constant && offset_expr.X_op != O_symbol) { @@ -5950,10 +5891,29 @@ macro (struct mips_cl_insn *ip) offset_expr.X_op = O_constant; } + if (HAVE_32BIT_ADDRESSES + && !IS_SEXT_32BIT_NUM (offset_expr.X_add_number)) + { + char value [32]; + + sprintf_vma (value, offset_expr.X_add_number); + as_bad (_("Number (0x%s) larger than 32 bits"), value); + } + /* A constant expression in PIC code can be handled just as it is in non PIC code. */ - if (mips_pic == NO_PIC - || offset_expr.X_op == O_constant) + if (offset_expr.X_op == O_constant) + { + expr1.X_add_number = ((offset_expr.X_add_number + 0x8000) + & ~(bfd_vma) 0xffff); + normalize_address_expr (&expr1); + load_register (tempreg, &expr1, HAVE_64BIT_ADDRESSES); + if (breg != 0) + macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", + tempreg, tempreg, breg); + macro_build (&offset_expr, s, fmt, treg, BFD_RELOC_LO16, tempreg); + } + else if (mips_pic == NO_PIC) { /* If this is a reference to a GP relative symbol, and there is no base register, we want @@ -6008,43 +5968,30 @@ macro (struct mips_cl_insn *ip) daddu $tempreg,$tempreg,$breg $treg,($tempreg) (BFD_RELOC_LO16) - If we have 64-bit addresses, as an optimization, for - addresses which are 32-bit constants (e.g. kseg0/kseg1 - addresses) we fall back to the 32-bit address generation - mechanism since it is more efficient. Note that due to - the signed offset used by memory operations, the 32-bit - range is shifted down by 32768 here. This code should - probably attempt to generate 64-bit constants more - efficiently in general. - - As an extension for architectures with 64-bit registers, - we don't truncate 64-bit addresses given as literal - constants down to 32 bits, to support existing practice - in the mips64 Linux (the kernel), that compiles source - files with -mabi=64, assembling them as o32 or n32 (with - -Wa,-32 or -Wa,-n32). This is not beautiful, but since - the whole kernel is loaded into a memory region that is - addressable with sign-extended 32-bit addresses, it is - wasteful to compute the upper 32 bits of every - non-literal address, that takes more space and time. - Some day this should probably be implemented as an - assembler option, such that the kernel doesn't have to - use such ugly hacks, even though it will still have to - end up converting the binary to ELF32 for a number of - platforms whose boot loaders don't support ELF64 - binaries. */ - if ((HAVE_64BIT_ADDRESSES - && ! (offset_expr.X_op == O_constant - && IS_SEXT_32BIT_NUM (offset_expr.X_add_number + 0x8000))) - || (HAVE_64BIT_GPRS - && offset_expr.X_op == O_constant - && ! IS_SEXT_32BIT_NUM (offset_expr.X_add_number + 0x8000))) + For GP relative symbols in 64bit address space we can use + the same sequence as in 32bit address space. */ + if (HAVE_64BIT_SYMBOLS) { - /* ??? We don't provide a GP-relative alternative for - these macros. It used not to be possible with the - original relaxation code, but it could be done now. */ + if ((valueT) offset_expr.X_add_number <= MAX_GPREL_OFFSET + && !nopic_need_relax (offset_expr.X_add_symbol, 1)) + { + relax_start (offset_expr.X_add_symbol); + if (breg == 0) + { + macro_build (&offset_expr, s, fmt, treg, + BFD_RELOC_GPREL16, mips_gp_register); + } + else + { + macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", + tempreg, breg, mips_gp_register); + macro_build (&offset_expr, s, fmt, treg, + BFD_RELOC_GPREL16, tempreg); + } + relax_switch (); + } - if (used_at == 0 && ! mips_opts.noat) + if (used_at == 0 && !mips_opts.noat) { macro_build (&offset_expr, "lui", "t,u", tempreg, BFD_RELOC_MIPS_HIGHEST); @@ -6077,23 +6024,20 @@ macro (struct mips_cl_insn *ip) BFD_RELOC_LO16, tempreg); } - return; + if (mips_relax.sequence) + relax_end (); + break; } - if (offset_expr.X_op == O_constant - && ! IS_SEXT_32BIT_NUM (offset_expr.X_add_number + 0x8000)) - as_bad (_("load/store address overflow (max 32 bits)")); - if (breg == 0) { if ((valueT) offset_expr.X_add_number <= MAX_GPREL_OFFSET - && ! nopic_need_relax (offset_expr.X_add_symbol, 1)) + && !nopic_need_relax (offset_expr.X_add_symbol, 1)) { relax_start (offset_expr.X_add_symbol); macro_build (&offset_expr, s, fmt, treg, BFD_RELOC_GPREL16, mips_gp_register); relax_switch (); - used_at = 0; } macro_build_lui (&offset_expr, tempreg); macro_build (&offset_expr, s, fmt, treg, @@ -6104,7 +6048,7 @@ macro (struct mips_cl_insn *ip) else { if ((valueT) offset_expr.X_add_number <= MAX_GPREL_OFFSET - && ! nopic_need_relax (offset_expr.X_add_symbol, 1)) + && !nopic_need_relax (offset_expr.X_add_symbol, 1)) { relax_start (offset_expr.X_add_symbol); macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", @@ -6122,7 +6066,7 @@ macro (struct mips_cl_insn *ip) relax_end (); } } - else if (mips_pic == SVR4_PIC && ! mips_big_got) + else if (!mips_big_got) { int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16; @@ -6156,10 +6100,6 @@ macro (struct mips_cl_insn *ip) tempreg, tempreg, breg); macro_build (&offset_expr, s, fmt, treg, BFD_RELOC_MIPS_GOT_OFST, tempreg); - - if (! used_at) - return; - break; } expr1.X_add_number = offset_expr.X_add_number; @@ -6169,7 +6109,7 @@ macro (struct mips_cl_insn *ip) as_bad (_("PIC code offset overflow (max 16 signed bits)")); macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg, lw_reloc_type, mips_gp_register); - macro_build (NULL, "nop", ""); + load_delay_nop (); relax_start (offset_expr.X_add_symbol); relax_switch (); macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", tempreg, @@ -6180,7 +6120,7 @@ macro (struct mips_cl_insn *ip) tempreg, tempreg, breg); macro_build (&expr1, s, fmt, treg, BFD_RELOC_LO16, tempreg); } - else if (mips_pic == SVR4_PIC && ! HAVE_NEWABI) + else if (mips_big_got && !HAVE_NEWABI) { int gpdelay; @@ -6219,7 +6159,7 @@ macro (struct mips_cl_insn *ip) macro_build (NULL, "nop", ""); macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg, BFD_RELOC_MIPS_GOT16, mips_gp_register); - macro_build (NULL, "nop", ""); + load_delay_nop (); macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", tempreg, tempreg, BFD_RELOC_LO16); relax_end (); @@ -6229,7 +6169,7 @@ macro (struct mips_cl_insn *ip) tempreg, tempreg, breg); macro_build (&expr1, s, fmt, treg, BFD_RELOC_LO16, tempreg); } - else if (mips_pic == SVR4_PIC && HAVE_NEWABI) + else if (mips_big_got && HAVE_NEWABI) { /* If this is a reference to an external symbol, we want lui $tempreg, (BFD_RELOC_MIPS_GOT_HI16) @@ -6268,49 +6208,24 @@ macro (struct mips_cl_insn *ip) BFD_RELOC_MIPS_GOT_OFST, tempreg); relax_end (); } - else if (mips_pic == EMBEDDED_PIC) - { - /* If there is no base register, we want - $treg,($gp) (BFD_RELOC_GPREL16) - If there is a base register, we want - addu $tempreg,$breg,$gp - $treg,($tempreg) (BFD_RELOC_GPREL16) - */ - assert (offset_expr.X_op == O_symbol); - if (breg == 0) - { - macro_build (&offset_expr, s, fmt, treg, BFD_RELOC_GPREL16, - mips_gp_register); - used_at = 0; - } - else - { - macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", - tempreg, breg, mips_gp_register); - macro_build (&offset_expr, s, fmt, treg, - BFD_RELOC_GPREL16, tempreg); - } - } else abort (); - if (! used_at) - return; - break; case M_LI: case M_LI_S: load_register (treg, &imm_expr, 0); - return; + break; case M_DLI: load_register (treg, &imm_expr, 1); - return; + break; case M_LI_SS: if (imm_expr.X_op == O_constant) { + used_at = 1; load_register (AT, &imm_expr, 0); macro_build (NULL, "mtc1", "t,G", AT, treg); break; @@ -6324,7 +6239,7 @@ macro (struct mips_cl_insn *ip) && offset_expr.X_add_number == 0); macro_build (&offset_expr, "lwc1", "T,o(b)", treg, BFD_RELOC_MIPS_LITERAL, mips_gp_register); - return; + break; } case M_LI_D: @@ -6364,7 +6279,7 @@ macro (struct mips_cl_insn *ip) } } } - return; + break; } /* We know that sym is in the .rdata section. First we get the @@ -6372,29 +6287,24 @@ macro (struct mips_cl_insn *ip) if (mips_pic == NO_PIC) { macro_build_lui (&offset_expr, AT); + used_at = 1; } - else if (mips_pic == SVR4_PIC) + else { macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", AT, BFD_RELOC_MIPS_GOT16, mips_gp_register); + used_at = 1; } - else if (mips_pic == EMBEDDED_PIC) - { - /* For embedded PIC we pick up the entire address off $gp in - a single instruction. */ - macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", AT, - mips_gp_register, BFD_RELOC_GPREL16); - offset_expr.X_op = O_constant; - offset_expr.X_add_number = 0; - } - else - abort (); /* Now we load the register(s). */ if (HAVE_64BIT_GPRS) - macro_build (&offset_expr, "ld", "t,o(b)", treg, BFD_RELOC_LO16, AT); + { + used_at = 1; + macro_build (&offset_expr, "ld", "t,o(b)", treg, BFD_RELOC_LO16, AT); + } else { + used_at = 1; macro_build (&offset_expr, "lw", "t,o(b)", treg, BFD_RELOC_LO16, AT); if (treg != RA) { @@ -6415,6 +6325,7 @@ macro (struct mips_cl_insn *ip) OFFSET_EXPR. */ if (imm_expr.X_op == O_constant || imm_expr.X_op == O_big) { + used_at = 1; load_register (AT, &imm_expr, HAVE_64BIT_FPRS); if (HAVE_64BIT_FPRS) { @@ -6445,7 +6356,7 @@ macro (struct mips_cl_insn *ip) { macro_build (&offset_expr, "ldc1", "T,o(b)", treg, BFD_RELOC_MIPS_LITERAL, mips_gp_register); - return; + break; } breg = mips_gp_register; r = BFD_RELOC_MIPS_LITERAL; @@ -6454,7 +6365,8 @@ macro (struct mips_cl_insn *ip) else { assert (strcmp (s, RDATA_SECTION_NAME) == 0); - if (mips_pic == SVR4_PIC) + used_at = 1; + if (mips_pic != NO_PIC) macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", AT, BFD_RELOC_MIPS_GOT16, mips_gp_register); else @@ -6478,7 +6390,7 @@ macro (struct mips_cl_insn *ip) if (mips_opts.arch == CPU_R4650) { as_bad (_("opcode not supported on this processor")); - return; + break; } /* Even on a big endian machine $fn comes before $fn+1. We have to adjust when loading from memory. */ @@ -6492,9 +6404,6 @@ macro (struct mips_cl_insn *ip) offset_expr.X_add_number += 4; macro_build (&offset_expr, "lwc1", "T,o(b)", target_big_endian ? treg : treg + 1, r, breg); - - if (breg != AT) - return; break; case M_L_DAB: @@ -6512,7 +6421,7 @@ macro (struct mips_cl_insn *ip) if (mips_opts.arch == CPU_R4650) { as_bad (_("opcode not supported on this processor")); - return; + break; } /* Itbl support may require additional care here. */ coproc = 1; @@ -6530,7 +6439,7 @@ macro (struct mips_cl_insn *ip) if (mips_opts.arch == CPU_R4650) { as_bad (_("opcode not supported on this processor")); - return; + break; } if (mips_opts.isa != ISA_MIPS1) @@ -6567,11 +6476,6 @@ macro (struct mips_cl_insn *ip) fmt = "t,o(b)"; ldd_std: - /* We do _not_ bother to allow embedded PIC (symbol-local_symbol) - loads for the case of doing a pair of loads to simulate an 'ld'. - This is not currently done by the compiler, and assembly coders - writing embedded-pic code can cope. */ - if (offset_expr.X_op != O_symbol && offset_expr.X_op != O_constant) { @@ -6579,6 +6483,15 @@ macro (struct mips_cl_insn *ip) offset_expr.X_op = O_constant; } + if (HAVE_32BIT_ADDRESSES + && !IS_SEXT_32BIT_NUM (offset_expr.X_add_number)) + { + char value [32]; + + sprintf_vma (value, offset_expr.X_add_number); + as_bad (_("Number (0x%s) larger than 32 bits"), value); + } + /* Even on a big endian machine $fn comes before $fn+1. We have to adjust when loading from memory. We set coproc if we must load $fn+1 first. */ @@ -6603,16 +6516,14 @@ macro (struct mips_cl_insn *ip) If there is a base register, we add it to $at after the lui instruction. If there is a constant, we always use the last case. */ - if ((valueT) offset_expr.X_add_number > MAX_GPREL_OFFSET - || nopic_need_relax (offset_expr.X_add_symbol, 1)) - used_at = 1; - else + if (offset_expr.X_op == O_symbol + && (valueT) offset_expr.X_add_number <= MAX_GPREL_OFFSET + && !nopic_need_relax (offset_expr.X_add_symbol, 1)) { relax_start (offset_expr.X_add_symbol); if (breg == 0) { tempreg = mips_gp_register; - used_at = 0; } else { @@ -6659,6 +6570,7 @@ macro (struct mips_cl_insn *ip) offset_expr.X_op = O_constant; } } + used_at = 1; macro_build_lui (&offset_expr, AT); if (breg != 0) macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, breg, AT); @@ -6673,7 +6585,7 @@ macro (struct mips_cl_insn *ip) if (mips_relax.sequence) relax_end (); } - else if (mips_pic == SVR4_PIC && ! mips_big_got) + else if (!mips_big_got) { /* If this is a reference to an external symbol, we want lw $at,($gp) (BFD_RELOC_MIPS_GOT16) @@ -6694,7 +6606,7 @@ macro (struct mips_cl_insn *ip) || expr1.X_add_number >= 0x8000 - 4) as_bad (_("PIC code offset overflow (max 16 signed bits)")); load_got_offset (AT, &offset_expr); - macro_build (NULL, "nop", ""); + load_delay_nop (); if (breg != 0) macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, breg, AT); @@ -6720,7 +6632,7 @@ macro (struct mips_cl_insn *ip) mips_optimize = hold_mips_optimize; } - else if (mips_pic == SVR4_PIC) + else if (mips_big_got) { int gpdelay; @@ -6753,7 +6665,7 @@ macro (struct mips_cl_insn *ip) AT, AT, mips_gp_register); macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", AT, BFD_RELOC_MIPS_GOT_LO16, AT); - macro_build (NULL, "nop", ""); + load_delay_nop (); if (breg != 0) macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, breg, AT); /* Itbl support may require additional care here. */ @@ -6777,7 +6689,7 @@ macro (struct mips_cl_insn *ip) macro_build (NULL, "nop", ""); macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", AT, BFD_RELOC_MIPS_GOT16, mips_gp_register); - macro_build (NULL, "nop", ""); + load_delay_nop (); if (breg != 0) macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, breg, AT); /* Itbl support may require additional care here. */ @@ -6795,43 +6707,9 @@ macro (struct mips_cl_insn *ip) mips_optimize = hold_mips_optimize; relax_end (); } - else if (mips_pic == EMBEDDED_PIC) - { - /* If there is no base register, we use - $treg,($gp) (BFD_RELOC_GPREL16) - $treg+1,+4($gp) (BFD_RELOC_GPREL16) - If we have a base register, we use - addu $at,$breg,$gp - $treg,($at) (BFD_RELOC_GPREL16) - $treg+1,+4($at) (BFD_RELOC_GPREL16) - */ - if (breg == 0) - { - tempreg = mips_gp_register; - used_at = 0; - } - else - { - macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", - AT, breg, mips_gp_register); - tempreg = AT; - used_at = 1; - } - - /* Itbl support may require additional care here. */ - macro_build (&offset_expr, s, fmt, coproc ? treg + 1 : treg, - BFD_RELOC_GPREL16, tempreg); - offset_expr.X_add_number += 4; - /* Itbl support may require additional care here. */ - macro_build (&offset_expr, s, fmt, coproc ? treg : treg + 1, - BFD_RELOC_GPREL16, tempreg); - } else abort (); - if (! used_at) - return; - break; case M_LD_OB: @@ -6844,8 +6722,49 @@ macro (struct mips_cl_insn *ip) macro_build (&offset_expr, s, "t,o(b)", treg, BFD_RELOC_LO16, breg); offset_expr.X_add_number += 4; macro_build (&offset_expr, s, "t,o(b)", treg + 1, BFD_RELOC_LO16, breg); - return; + break; + case M_SAA_AB: + s = "saa"; + goto saa_saad; + + case M_SAAD_AB: + s = "saad"; + + saa_saad: + /* The "saa/saad" instructions are new in CN58XX. These instructions + do not specify offset. When invoked with address or symbol, then + load the address or value of symbol in a register using the dla macro + into AT, and pass the register for emitting "saa/saad" instruction. + This will get expanded to + + dla AT, constant/label + saa/saad $treg,(AT) */ + { + char *name = "dla"; + char *fmt = "t,A(b)"; + const struct mips_opcode *mo; + struct mips_cl_insn insn; + + mo = hash_find (op_hash, name); + assert (strcmp (name, mo->name) == 0); + assert (strcmp (fmt, mo->args) == 0); + create_insn (&insn, mo); + + insn.insn_opcode = insn.insn_mo->match; + + used_at = 1; + INSERT_OPERAND (RT, insn, AT); + if (breg) + INSERT_OPERAND (RS, insn, breg); + + /* The address part is forwarded through the global offset_expr. */ + macro (&insn); + + macro_build (NULL, s, "t,(b)", treg, AT); + break; + } + /* New code added to support COPZ instructions. This code builds table entries out of the macros in mip_opcodes. R4000 uses interlocks to handle coproc delays. @@ -6875,14 +6794,20 @@ macro (struct mips_cl_insn *ip) case M_COP3: s = "c3"; copz: + if (!strcmp (s,"c2") && mips_opts.arch == CPU_OCTEON + && octeon_error_on_unsupported) + { + as_bad (_("opcode not implemented in Octeon `%s'"), ip->insn_mo->name); + return; + } /* For now we just do C (same as Cz). The parameter will be stored in insn_opcode by mips_ip. */ macro_build (NULL, s, "C", ip->insn_opcode); - return; + break; case M_MOVE: move_register (dreg, sreg); - return; + break; #ifdef LOSING_COMPILER default: @@ -6901,13 +6826,13 @@ macro (struct mips_cl_insn *ip) s2 = "cop3"; coproc = ITBL_DECODE_PNUM (immed_expr);; macro_build (&immed_expr, s, "C"); - return; + break; } macro2 (ip); - return; + break; } - if (mips_opts.noat) - as_warn (_("Macro used $at after \".set noat\"")); + if (mips_opts.noat && used_at) + as_bad (_("Macro used $at after \".set noat\"")); } static void @@ -6949,7 +6874,7 @@ macro2 (struct mips_cl_insn *ip) case M_MUL: macro_build (NULL, dbl ? "dmultu" : "multu", "s,t", sreg, treg); macro_build (NULL, "mflo", "d", dreg); - return; + break; case M_DMUL_I: dbl = 1; @@ -6957,6 +6882,7 @@ macro2 (struct mips_cl_insn *ip) /* The MIPS assembler some times generates shifts and adds. I'm not trying to be that fancy. GCC should do this for us anyway. */ + used_at = 1; load_register (AT, &imm_expr, dbl); macro_build (NULL, dbl ? "dmult" : "mult", "s,t", sreg, AT); macro_build (NULL, "mflo", "d", dreg); @@ -6972,9 +6898,8 @@ macro2 (struct mips_cl_insn *ip) dbl = 1; case M_MULO: do_mulo: - mips_emit_delays (TRUE); - ++mips_opts.noreorder; - mips_any_noreorder = 1; + start_noreorder (); + used_at = 1; if (imm) load_register (AT, &imm_expr, dbl); macro_build (NULL, dbl ? "dmult" : "mult", "s,t", sreg, imm ? AT : treg); @@ -6990,7 +6915,7 @@ macro2 (struct mips_cl_insn *ip) macro_build (NULL, "nop", "", 0); macro_build (NULL, "break", "c", 6); } - --mips_opts.noreorder; + end_noreorder (); macro_build (NULL, "mflo", "d", dreg); break; @@ -7004,9 +6929,8 @@ macro2 (struct mips_cl_insn *ip) dbl = 1; case M_MULOU: do_mulou: - mips_emit_delays (TRUE); - ++mips_opts.noreorder; - mips_any_noreorder = 1; + start_noreorder (); + used_at = 1; if (imm) load_register (AT, &imm_expr, dbl); macro_build (NULL, dbl ? "dmultu" : "multu", "s,t", @@ -7022,7 +6946,7 @@ macro2 (struct mips_cl_insn *ip) macro_build (NULL, "nop", "", 0); macro_build (NULL, "break", "c", 6); } - --mips_opts.noreorder; + end_noreorder (); break; case M_DROL: @@ -7036,14 +6960,12 @@ macro2 (struct mips_cl_insn *ip) else { tempreg = dreg; - used_at = 0; } macro_build (NULL, "dnegu", "d,w", tempreg, treg); macro_build (NULL, "drorv", "d,t,s", dreg, sreg, tempreg); - if (used_at) - break; - return; + break; } + used_at = 1; macro_build (NULL, "dsubu", "d,v,t", AT, 0, treg); macro_build (NULL, "dsrlv", "d,t,s", AT, sreg, AT); macro_build (NULL, "dsllv", "d,t,s", dreg, sreg, treg); @@ -7061,14 +6983,12 @@ macro2 (struct mips_cl_insn *ip) else { tempreg = dreg; - used_at = 0; } macro_build (NULL, "negu", "d,w", tempreg, treg); macro_build (NULL, "rorv", "d,t,s", dreg, sreg, tempreg); - if (used_at) - break; - return; + break; } + used_at = 1; macro_build (NULL, "subu", "d,v,t", AT, 0, treg); macro_build (NULL, "srlv", "d,t,s", AT, sreg, AT); macro_build (NULL, "sllv", "d,t,s", dreg, sreg, treg); @@ -7090,16 +7010,17 @@ macro2 (struct mips_cl_insn *ip) macro_build (NULL, "dror32", "d,w,<", dreg, sreg, rot - 32); else macro_build (NULL, "dror", "d,w,<", dreg, sreg, rot); - return; + break; } if (rot == 0) { macro_build (NULL, "dsrl", "d,w,<", dreg, sreg, 0); - return; + break; } l = (rot < 0x20) ? "dsll" : "dsll32"; r = ((0x40 - rot) < 0x20) ? "dsrl" : "dsrl32"; rot &= 0x1f; + used_at = 1; macro_build (NULL, l, "d,w,<", AT, sreg, rot); macro_build (NULL, r, "d,w,<", dreg, sreg, (0x20 - rot) & 0x1f); macro_build (NULL, "or", "d,v,t", dreg, dreg, AT); @@ -7116,13 +7037,14 @@ macro2 (struct mips_cl_insn *ip) if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_opts.arch)) { macro_build (NULL, "ror", "d,w,<", dreg, sreg, (32 - rot) & 0x1f); - return; + break; } if (rot == 0) { macro_build (NULL, "srl", "d,w,<", dreg, sreg, 0); - return; + break; } + used_at = 1; macro_build (NULL, "sll", "d,w,<", AT, sreg, rot); macro_build (NULL, "srl", "d,w,<", dreg, sreg, (0x20 - rot) & 0x1f); macro_build (NULL, "or", "d,v,t", dreg, dreg, AT); @@ -7133,8 +7055,9 @@ macro2 (struct mips_cl_insn *ip) if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_opts.arch)) { macro_build (NULL, "drorv", "d,t,s", dreg, sreg, treg); - return; + break; } + used_at = 1; macro_build (NULL, "dsubu", "d,v,t", AT, 0, treg); macro_build (NULL, "dsllv", "d,t,s", AT, sreg, AT); macro_build (NULL, "dsrlv", "d,t,s", dreg, sreg, treg); @@ -7145,8 +7068,9 @@ macro2 (struct mips_cl_insn *ip) if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_opts.arch)) { macro_build (NULL, "rorv", "d,t,s", dreg, sreg, treg); - return; + break; } + used_at = 1; macro_build (NULL, "subu", "d,v,t", AT, 0, treg); macro_build (NULL, "sllv", "d,t,s", AT, sreg, AT); macro_build (NULL, "srlv", "d,t,s", dreg, sreg, treg); @@ -7167,16 +7091,17 @@ macro2 (struct mips_cl_insn *ip) macro_build (NULL, "dror32", "d,w,<", dreg, sreg, rot - 32); else macro_build (NULL, "dror", "d,w,<", dreg, sreg, rot); - return; + break; } if (rot == 0) { macro_build (NULL, "dsrl", "d,w,<", dreg, sreg, 0); - return; + break; } r = (rot < 0x20) ? "dsrl" : "dsrl32"; l = ((0x40 - rot) < 0x20) ? "dsll" : "dsll32"; rot &= 0x1f; + used_at = 1; macro_build (NULL, r, "d,w,<", AT, sreg, rot); macro_build (NULL, l, "d,w,<", dreg, sreg, (0x20 - rot) & 0x1f); macro_build (NULL, "or", "d,v,t", dreg, dreg, AT); @@ -7193,13 +7118,14 @@ macro2 (struct mips_cl_insn *ip) if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_opts.arch)) { macro_build (NULL, "ror", "d,w,<", dreg, sreg, rot); - return; + break; } if (rot == 0) { macro_build (NULL, "srl", "d,w,<", dreg, sreg, 0); - return; + break; } + used_at = 1; macro_build (NULL, "srl", "d,w,<", AT, sreg, rot); macro_build (NULL, "sll", "d,w,<", dreg, sreg, (0x20 - rot) & 0x1f); macro_build (NULL, "or", "d,v,t", dreg, dreg, AT); @@ -7210,7 +7136,7 @@ macro2 (struct mips_cl_insn *ip) if (mips_opts.arch == CPU_R4650) { as_bad (_("opcode not supported on this processor")); - return; + break; } assert (mips_opts.isa == ISA_MIPS1); /* Even on a big endian machine $fn comes before $fn+1. We have @@ -7220,7 +7146,7 @@ macro2 (struct mips_cl_insn *ip) offset_expr.X_add_number += 4; macro_build (&offset_expr, "swc1", "T,o(b)", target_big_endian ? treg : treg + 1, BFD_RELOC_LO16, breg); - return; + break; case M_SEQ: if (sreg == 0) @@ -7232,27 +7158,26 @@ macro2 (struct mips_cl_insn *ip) macro_build (NULL, "xor", "d,v,t", dreg, sreg, treg); macro_build (&expr1, "sltiu", "t,r,j", dreg, dreg, BFD_RELOC_LO16); } - return; + break; case M_SEQ_I: if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0) { macro_build (&expr1, "sltiu", "t,r,j", dreg, sreg, BFD_RELOC_LO16); - return; + break; } if (sreg == 0) { as_warn (_("Instruction %s: result is always false"), ip->insn_mo->name); move_register (dreg, 0); - return; + break; } if (imm_expr.X_op == O_constant && imm_expr.X_add_number >= 0 && imm_expr.X_add_number < 0x10000) { macro_build (&imm_expr, "xori", "t,r,i", dreg, sreg, BFD_RELOC_LO16); - used_at = 0; } else if (imm_expr.X_op == O_constant && imm_expr.X_add_number > -0x8000 @@ -7261,7 +7186,6 @@ macro2 (struct mips_cl_insn *ip) imm_expr.X_add_number = -imm_expr.X_add_number; macro_build (&imm_expr, HAVE_32BIT_GPRS ? "addiu" : "daddiu", "t,r,j", dreg, sreg, BFD_RELOC_LO16); - used_at = 0; } else { @@ -7270,9 +7194,7 @@ macro2 (struct mips_cl_insn *ip) used_at = 1; } macro_build (&expr1, "sltiu", "t,r,j", dreg, dreg, BFD_RELOC_LO16); - if (used_at) - break; - return; + break; case M_SGE: /* sreg >= treg <==> not (sreg < treg) */ s = "slt"; @@ -7282,7 +7204,7 @@ macro2 (struct mips_cl_insn *ip) sge: macro_build (NULL, s, "d,v,t", dreg, sreg, treg); macro_build (&expr1, "xori", "t,r,i", dreg, dreg, BFD_RELOC_LO16); - return; + break; case M_SGE_I: /* sreg >= I <==> not (sreg < I) */ case M_SGEU_I: @@ -7292,7 +7214,6 @@ macro2 (struct mips_cl_insn *ip) { macro_build (&imm_expr, mask == M_SGE_I ? "slti" : "sltiu", "t,r,j", dreg, sreg, BFD_RELOC_LO16); - used_at = 0; } else { @@ -7302,9 +7223,7 @@ macro2 (struct mips_cl_insn *ip) used_at = 1; } macro_build (&expr1, "xori", "t,r,i", dreg, dreg, BFD_RELOC_LO16); - if (used_at) - break; - return; + break; case M_SGT: /* sreg > treg <==> treg < sreg */ s = "slt"; @@ -7313,7 +7232,7 @@ macro2 (struct mips_cl_insn *ip) s = "sltu"; sgt: macro_build (NULL, s, "d,v,t", dreg, treg, sreg); - return; + break; case M_SGT_I: /* sreg > I <==> I < sreg */ s = "slt"; @@ -7321,6 +7240,7 @@ macro2 (struct mips_cl_insn *ip) case M_SGTU_I: s = "sltu"; sgti: + used_at = 1; load_register (AT, &imm_expr, HAVE_64BIT_GPRS); macro_build (NULL, s, "d,v,t", dreg, AT, sreg); break; @@ -7333,7 +7253,7 @@ macro2 (struct mips_cl_insn *ip) sle: macro_build (NULL, s, "d,v,t", dreg, treg, sreg); macro_build (&expr1, "xori", "t,r,i", dreg, dreg, BFD_RELOC_LO16); - return; + break; case M_SLE_I: /* sreg <= I <==> I >= sreg <==> not (I < sreg) */ s = "slt"; @@ -7341,6 +7261,7 @@ macro2 (struct mips_cl_insn *ip) case M_SLEU_I: s = "sltu"; slei: + used_at = 1; load_register (AT, &imm_expr, HAVE_64BIT_GPRS); macro_build (NULL, s, "d,v,t", dreg, AT, sreg); macro_build (&expr1, "xori", "t,r,i", dreg, dreg, BFD_RELOC_LO16); @@ -7352,8 +7273,9 @@ macro2 (struct mips_cl_insn *ip) && imm_expr.X_add_number < 0x8000) { macro_build (&imm_expr, "slti", "t,r,j", dreg, sreg, BFD_RELOC_LO16); - return; + break; } + used_at = 1; load_register (AT, &imm_expr, HAVE_64BIT_GPRS); macro_build (NULL, "slt", "d,v,t", dreg, sreg, AT); break; @@ -7365,8 +7287,9 @@ macro2 (struct mips_cl_insn *ip) { macro_build (&imm_expr, "sltiu", "t,r,j", dreg, sreg, BFD_RELOC_LO16); - return; + break; } + used_at = 1; load_register (AT, &imm_expr, HAVE_64BIT_GPRS); macro_build (NULL, "sltu", "d,v,t", dreg, sreg, AT); break; @@ -7381,13 +7304,13 @@ macro2 (struct mips_cl_insn *ip) macro_build (NULL, "xor", "d,v,t", dreg, sreg, treg); macro_build (NULL, "sltu", "d,v,t", dreg, 0, dreg); } - return; + break; case M_SNE_I: if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0) { macro_build (NULL, "sltu", "d,v,t", dreg, 0, sreg); - return; + break; } if (sreg == 0) { @@ -7395,14 +7318,13 @@ macro2 (struct mips_cl_insn *ip) ip->insn_mo->name); macro_build (&expr1, HAVE_32BIT_GPRS ? "addiu" : "daddiu", "t,r,j", dreg, 0, BFD_RELOC_LO16); - return; + break; } if (imm_expr.X_op == O_constant && imm_expr.X_add_number >= 0 && imm_expr.X_add_number < 0x10000) { macro_build (&imm_expr, "xori", "t,r,i", dreg, sreg, BFD_RELOC_LO16); - used_at = 0; } else if (imm_expr.X_op == O_constant && imm_expr.X_add_number > -0x8000 @@ -7411,7 +7333,6 @@ macro2 (struct mips_cl_insn *ip) imm_expr.X_add_number = -imm_expr.X_add_number; macro_build (&imm_expr, HAVE_32BIT_GPRS ? "addiu" : "daddiu", "t,r,j", dreg, sreg, BFD_RELOC_LO16); - used_at = 0; } else { @@ -7420,9 +7341,7 @@ macro2 (struct mips_cl_insn *ip) used_at = 1; } macro_build (NULL, "sltu", "d,v,t", dreg, 0, dreg); - if (used_at) - break; - return; + break; case M_DSUB_I: dbl = 1; @@ -7434,8 +7353,9 @@ macro2 (struct mips_cl_insn *ip) imm_expr.X_add_number = -imm_expr.X_add_number; macro_build (&imm_expr, dbl ? "daddi" : "addi", "t,r,j", dreg, sreg, BFD_RELOC_LO16); - return; + break; } + used_at = 1; load_register (AT, &imm_expr, dbl); macro_build (NULL, dbl ? "dsub" : "sub", "d,v,t", dreg, sreg, AT); break; @@ -7450,8 +7370,9 @@ macro2 (struct mips_cl_insn *ip) imm_expr.X_add_number = -imm_expr.X_add_number; macro_build (&imm_expr, dbl ? "daddiu" : "addiu", "t,r,j", dreg, sreg, BFD_RELOC_LO16); - return; + break; } + used_at = 1; load_register (AT, &imm_expr, dbl); macro_build (NULL, dbl ? "dsubu" : "subu", "d,v,t", dreg, sreg, AT); break; @@ -7474,13 +7395,20 @@ macro2 (struct mips_cl_insn *ip) case M_TNE_I: s = "tne"; trap: + used_at = 1; load_register (AT, &imm_expr, HAVE_64BIT_GPRS); macro_build (NULL, s, "s,t", sreg, AT); break; case M_TRUNCWS: case M_TRUNCWD: + if (mips_opts.arch == CPU_OCTEON && octeon_error_on_unsupported) + { + as_bad (_("opcode not implemented in Octeon `%s'"), ip->insn_mo->name); + return; + } assert (mips_opts.isa == ISA_MIPS1); + used_at = 1; sreg = (ip->insn_opcode >> 11) & 0x1f; /* floating reg */ dreg = (ip->insn_opcode >> 06) & 0x1f; /* floating reg */ @@ -7488,9 +7416,7 @@ macro2 (struct mips_cl_insn *ip) * Is the double cfc1 instruction a bug in the mips assembler; * or is there a reason for it? */ - mips_emit_delays (TRUE); - ++mips_opts.noreorder; - mips_any_noreorder = 1; + start_noreorder (); macro_build (NULL, "cfc1", "t,G", treg, RA); macro_build (NULL, "cfc1", "t,G", treg, RA); macro_build (NULL, "nop", ""); @@ -7504,7 +7430,7 @@ macro2 (struct mips_cl_insn *ip) dreg, sreg); macro_build (NULL, "ctc1", "t,G", treg, RA); macro_build (NULL, "nop", ""); - --mips_opts.noreorder; + end_noreorder (); break; case M_ULH: @@ -7513,8 +7439,10 @@ macro2 (struct mips_cl_insn *ip) case M_ULHU: s = "lbu"; ulh: + used_at = 1; if (offset_expr.X_add_number >= 0x7fff) as_bad (_("operand overflow")); + /* Expand the ulh to "lb, lbu, ins" instead of "lb, lbu, sll, ori". */ if (! target_big_endian) ++offset_expr.X_add_number; macro_build (&offset_expr, s, "t,o(b)", AT, BFD_RELOC_LO16, breg); @@ -7523,8 +7451,13 @@ macro2 (struct mips_cl_insn *ip) else ++offset_expr.X_add_number; macro_build (&offset_expr, "lbu", "t,o(b)", treg, BFD_RELOC_LO16, breg); - macro_build (NULL, "sll", "d,w,<", AT, AT, 8); - macro_build (NULL, "or", "d,v,t", treg, treg, AT); + if (ISA_HAS_INS (mips_opts.isa)) + macro_build (NULL, "ins", "t,r,+A,+B", treg, AT, 8, 31); + else + { + macro_build (NULL, "sll", "d,w,<", AT, AT, 8); + macro_build (NULL, "or", "d,v,t", treg, treg, AT); + } break; case M_ULD: @@ -7542,22 +7475,42 @@ macro2 (struct mips_cl_insn *ip) if (treg != breg) tempreg = treg; else - tempreg = AT; + { + used_at = 1; + tempreg = AT; + } + + /* For small variables the compiler uses gp_rel to load the value of + the variables. While parsing instructions "uld $2,%gp_rel(var)($28)" + the offset_reloc[0] is set to BFD_RELOC_GPREL16. Use this relocation + type while emitting instructions otherwise use BFD_RELOC_LO16. */ + if (offset_reloc[0] == BFD_RELOC_UNUSED) + offset_reloc[0] = BFD_RELOC_LO16; + + if (octeon_use_unalign && mips_opts.arch == CPU_OCTEON) + { + /* Reset used_at as tempreg is not used while generating Octeon + unaligned load/store. */ + used_at = 0; + macro_build (&offset_expr, (mask == M_ULW ? "ulw" : "uld"), "t,o(b)", + treg, offset_reloc[0], breg); + break; + } + if (! target_big_endian) offset_expr.X_add_number += off; - macro_build (&offset_expr, s, "t,o(b)", tempreg, BFD_RELOC_LO16, breg); + macro_build (&offset_expr, s, "t,o(b)", tempreg, offset_reloc[0], breg); if (! target_big_endian) offset_expr.X_add_number -= off; else offset_expr.X_add_number += off; - macro_build (&offset_expr, s2, "t,o(b)", tempreg, BFD_RELOC_LO16, breg); + macro_build (&offset_expr, s2, "t,o(b)", tempreg, offset_reloc[0], breg); /* If necessary, move the result in tempreg the final destination. */ if (treg == tempreg) - return; + break; /* Protect second load's delay slot. */ - if (!gpr_interlocks) - macro_build (NULL, "nop", ""); + load_delay_nop (); move_register (treg, tempreg); break; @@ -7575,16 +7528,31 @@ macro2 (struct mips_cl_insn *ip) load_address (AT, &offset_expr, &used_at); if (breg != 0) macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, AT, breg); + + /* For small variables the compiler uses gp_rel to load the value of + the variables. While parsing instructions "uld $2,%gp_rel(var)($28)" + the offset_reloc[0] is set to BFD_RELOC_GPREL16. Use this relocation + type while emitting instructions otherwise use BFD_RELOC_LO16. */ + if (offset_reloc[0] == BFD_RELOC_UNUSED) + offset_reloc[0] = BFD_RELOC_LO16; + + if (octeon_use_unalign && mips_opts.arch == CPU_OCTEON) + { + macro_build (&offset_expr, (mask == M_ULW_A ? "ulw" : "uld"), + "t,o(b)", treg, offset_reloc[0], AT); + break; + } + if (! target_big_endian) expr1.X_add_number = off; else expr1.X_add_number = 0; - macro_build (&expr1, s, "t,o(b)", treg, BFD_RELOC_LO16, AT); + macro_build (&expr1, s, "t,o(b)", treg, offset_reloc[0], AT); if (! target_big_endian) expr1.X_add_number = 0; else expr1.X_add_number = off; - macro_build (&expr1, s2, "t,o(b)", treg, BFD_RELOC_LO16, AT); + macro_build (&expr1, s2, "t,o(b)", treg, offset_reloc[0], AT); break; case M_ULH_A: @@ -7593,6 +7561,23 @@ macro2 (struct mips_cl_insn *ip) load_address (AT, &offset_expr, &used_at); if (breg != 0) macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, AT, breg); + + if (ISA_HAS_INS (mips_opts.isa)) + { + if (target_big_endian) + expr1.X_add_number = 1; + else + expr1.X_add_number = 0; + macro_build (&expr1, "lbu", "t,o(b)", treg, BFD_RELOC_LO16, AT); + if (target_big_endian) + expr1.X_add_number = 0; + else + expr1.X_add_number = 1; + macro_build (&expr1, mask == M_ULH_A ? "lb" : "lbu", "t,o(b)", + AT, BFD_RELOC_LO16, AT); + macro_build (NULL, "ins", "t,r,+A,+B", treg, AT, 8, 31); + break; + } if (target_big_endian) expr1.X_add_number = 0; macro_build (&expr1, mask == M_ULH_A ? "lb" : "lbu", "t,o(b)", @@ -7607,6 +7592,7 @@ macro2 (struct mips_cl_insn *ip) break; case M_USH: + used_at = 1; if (offset_expr.X_add_number >= 0x7fff) as_bad (_("operand overflow")); if (target_big_endian) @@ -7632,15 +7618,29 @@ macro2 (struct mips_cl_insn *ip) usw: if (offset_expr.X_add_number >= 0x8000 - off) as_bad (_("operand overflow")); + + /* For small variables the compiler uses gp_rel to load the value of + the variables. While parsing instructions "uld $2,%gp_rel(var)($28)" + the offset_reloc[0] is set to BFD_RELOC_GPREL16. Use this relocation + type while emitting instructions otherwise use BFD_RELOC_LO16. */ + if (offset_reloc[0] == BFD_RELOC_UNUSED) + offset_reloc[0] = BFD_RELOC_LO16; + + if (octeon_use_unalign && mips_opts.arch == CPU_OCTEON) + { + macro_build (&offset_expr, (mask == M_USD ? "usd" : "usw"), + "t,o(b)", treg, offset_reloc[0], breg); + break; + } if (! target_big_endian) offset_expr.X_add_number += off; - macro_build (&offset_expr, s, "t,o(b)", treg, BFD_RELOC_LO16, breg); + macro_build (&offset_expr, s, "t,o(b)", treg, offset_reloc[0], breg); if (! target_big_endian) offset_expr.X_add_number -= off; else offset_expr.X_add_number += off; - macro_build (&offset_expr, s2, "t,o(b)", treg, BFD_RELOC_LO16, breg); - return; + macro_build (&offset_expr, s2, "t,o(b)", treg, offset_reloc[0], breg); + break; case M_USD_A: s = "sdl"; @@ -7656,16 +7656,30 @@ macro2 (struct mips_cl_insn *ip) load_address (AT, &offset_expr, &used_at); if (breg != 0) macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, AT, breg); + + /* For small variables the compiler uses gp_rel to load the value of + the variables. While parsing instructions "uld $2,%gp_rel(var)($28)" + the offset_reloc[0] is set to BFD_RELOC_GPREL16. Use this relocation + type while emitting instructions otherwise use BFD_RELOC_LO16. */ + if (offset_reloc[0] == BFD_RELOC_UNUSED) + offset_reloc[0] = BFD_RELOC_LO16; + + if (octeon_use_unalign && mips_opts.arch == CPU_OCTEON) + { + macro_build (&offset_expr, (mask == M_USW_A ? "usw" : "usd"), + "t,o(b)", treg, offset_reloc[0], AT); + break; + } if (! target_big_endian) expr1.X_add_number = off; else expr1.X_add_number = 0; - macro_build (&expr1, s, "t,o(b)", treg, BFD_RELOC_LO16, AT); + macro_build (&expr1, s, "t,o(b)", treg, offset_reloc[0], AT); if (! target_big_endian) expr1.X_add_number = 0; else expr1.X_add_number = off; - macro_build (&expr1, s2, "t,o(b)", treg, BFD_RELOC_LO16, AT); + macro_build (&expr1, s2, "t,o(b)", treg, offset_reloc[0], AT); break; case M_USH_A: @@ -7697,8 +7711,8 @@ macro2 (struct mips_cl_insn *ip) as_bad (_("Macro %s not implemented yet"), ip->insn_mo->name); break; } - if (mips_opts.noat) - as_warn (_("Macro used $at after \".set noat\"")); + if (mips_opts.noat && used_at) + as_bad (_("Macro used $at after \".set noat\"")); } /* Implement macros in mips16 mode. */ @@ -7714,9 +7728,9 @@ mips16_macro (struct mips_cl_insn *ip) mask = ip->insn_mo->mask; - xreg = (ip->insn_opcode >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX; - yreg = (ip->insn_opcode >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY; - zreg = (ip->insn_opcode >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ; + xreg = MIPS16_EXTRACT_OPERAND (RX, *ip); + yreg = MIPS16_EXTRACT_OPERAND (RY, *ip); + zreg = MIPS16_EXTRACT_OPERAND (RZ, *ip); expr1.X_op = O_constant; expr1.X_op_symbol = NULL; @@ -7740,9 +7754,7 @@ mips16_macro (struct mips_cl_insn *ip) case M_REM_3: s = "mfhi"; do_div3: - mips_emit_delays (TRUE); - ++mips_opts.noreorder; - mips_any_noreorder = 1; + start_noreorder (); macro_build (NULL, dbl ? "ddiv" : "div", "0,x,y", xreg, yreg); expr1.X_add_number = 2; macro_build (&expr1, "bnez", "x,p", yreg); @@ -7752,7 +7764,7 @@ mips16_macro (struct mips_cl_insn *ip) since that causes an overflow. We should do that as well, but I don't see how to do the comparisons without a temporary register. */ - --mips_opts.noreorder; + end_noreorder (); macro_build (NULL, s, "x", zreg); break; @@ -7772,14 +7784,12 @@ mips16_macro (struct mips_cl_insn *ip) s = "ddivu"; s2 = "mfhi"; do_divu3: - mips_emit_delays (TRUE); - ++mips_opts.noreorder; - mips_any_noreorder = 1; + start_noreorder (); macro_build (NULL, s, "0,x,y", xreg, yreg); expr1.X_add_number = 2; macro_build (&expr1, "bnez", "x,p", yreg); macro_build (NULL, "break", "6", 7); - --mips_opts.noreorder; + end_noreorder (); macro_build (NULL, s2, "x", zreg); break; @@ -7788,7 +7798,7 @@ mips16_macro (struct mips_cl_insn *ip) case M_MUL: macro_build (NULL, dbl ? "dmultu" : "multu", "x,y", xreg, yreg); macro_build (NULL, "mflo", "x", zreg); - return; + break; case M_DSUBU_I: dbl = 1; @@ -7959,6 +7969,8 @@ validate_mips_insn (const struct mips_opcode *opc) case ',': break; case '(': break; case ')': break; + case '^': USE_BITS (OP_MASK_BITIND, OP_SH_BITIND); break; + case '~': USE_BITS (OP_MASK_BITIND, OP_SH_BITIND); break; case '+': switch (c = *p++) { @@ -7972,6 +7984,9 @@ validate_mips_insn (const struct mips_opcode *opc) case 'G': USE_BITS (OP_MASK_EXTMSBD, OP_SH_EXTMSBD); break; case 'H': USE_BITS (OP_MASK_EXTMSBD, OP_SH_EXTMSBD); break; case 'I': break; + case 't': USE_BITS (OP_MASK_RT, OP_SH_RT); break; + case 'T': USE_BITS (OP_MASK_RT, OP_SH_RT); + USE_BITS (OP_MASK_SEL, OP_SH_SEL); break; default: as_bad (_("internal: bad mips opcode (unknown extension operand type `+%c'): %s %s"), c, opc->name, opc->args); @@ -8025,6 +8040,7 @@ validate_mips_insn (const struct mips_opcode *opc) case 'v': USE_BITS (OP_MASK_RS, OP_SH_RS); break; case 'w': USE_BITS (OP_MASK_RT, OP_SH_RT); break; case 'x': break; + case 'y': USE_BITS (OP_MASK_CODE2, OP_SH_CODE2); break; case 'z': break; case 'P': USE_BITS (OP_MASK_PERFREG, OP_SH_PERFREG); break; case 'U': USE_BITS (OP_MASK_RD, OP_SH_RD); @@ -8033,6 +8049,22 @@ validate_mips_insn (const struct mips_opcode *opc) case '%': USE_BITS (OP_MASK_VECALIGN, OP_SH_VECALIGN); break; case '[': break; case ']': break; + case '3': USE_BITS (OP_MASK_SA3, OP_SH_SA3); break; + case '4': USE_BITS (OP_MASK_SA4, OP_SH_SA4); break; + case '5': USE_BITS (OP_MASK_IMM8, OP_SH_IMM8); break; + case '6': USE_BITS (OP_MASK_RS, OP_SH_RS); break; + case '7': USE_BITS (OP_MASK_DSPACC, OP_SH_DSPACC); break; + case '8': USE_BITS (OP_MASK_WRDSP, OP_SH_WRDSP); break; + case '9': USE_BITS (OP_MASK_DSPACC_S, OP_SH_DSPACC_S);break; + case '0': USE_BITS (OP_MASK_DSPSFT, OP_SH_DSPSFT); break; + case '\'': USE_BITS (OP_MASK_RDDSP, OP_SH_RDDSP); break; + case ':': USE_BITS (OP_MASK_DSPSFT_7, OP_SH_DSPSFT_7);break; + case '@': USE_BITS (OP_MASK_IMM10, OP_SH_IMM10); break; + case '!': USE_BITS (OP_MASK_MT_U, OP_SH_MT_U); break; + case '$': USE_BITS (OP_MASK_MT_H, OP_SH_MT_H); break; + case '*': USE_BITS (OP_MASK_MTACC_T, OP_SH_MTACC_T); break; + case '&': USE_BITS (OP_MASK_MTACC_D, OP_SH_MTACC_D); break; + case 'g': USE_BITS (OP_MASK_RD, OP_SH_RD); break; default: as_bad (_("internal: bad mips opcode (unknown operand type `%c'): %s %s"), c, opc->name, opc->args); @@ -8067,6 +8099,7 @@ mips_ip (char *str, struct mips_cl_insn *ip) unsigned int limlo, limhi; char *s_reset; char save_c = 0; + offsetT min_range, max_range; insn_error = NULL; @@ -8129,6 +8162,8 @@ mips_ip (char *str, struct mips_cl_insn *ip) (mips_opts.isa | (file_ase_mips16 ? INSN_MIPS16 : 0) | (mips_opts.ase_mdmx ? INSN_MDMX : 0) + | (mips_opts.ase_dsp ? INSN_DSP : 0) + | (mips_opts.ase_mt ? INSN_MT : 0) | (mips_opts.ase_mips3d ? INSN_MIPS3D : 0)), mips_opts.arch)) ok = TRUE; @@ -8139,6 +8174,82 @@ mips_ip (char *str, struct mips_cl_insn *ip) { if (mips_opts.arch == CPU_R4650 && (insn->pinfo & FP_D) != 0) ok = FALSE; + + if (mips_opts.arch == CPU_OCTEON + && octeon_error_on_unsupported + && ((insn->pinfo & FP_D) != 0 + || (insn->pinfo & FP_S) !=0 + || strcmp (insn->name, "prefx") == 0)) + { + insn_error = "opcode not implemented in Octeon"; + return; + } + + if (mips_opts.arch == CPU_OCTEON + && octeon_error_on_unsupported + && (strcmp (insn->name, "swc2") == 0 + || strcmp (insn->name, "lwc2") == 0 + || strcmp (insn->name, "sdc2") == 0 + || strcmp (insn->name, "ldc2") == 0 + || strcmp (insn->name, "bc2f") == 0 + || strcmp (insn->name, "bc2t") == 0 + || strcmp (insn->name, "mfc2") == 0 + || strcmp (insn->name, "mtc2") == 0 + || strcmp (insn->name, "ctc2") == 0 + || strcmp (insn->name, "cfc2") == 0 + || strcmp (insn->name, "mfhc2") == 0 + || strcmp (insn->name, "mthc2") == 0)) + { + insn_error = "opcode not implemented in Octeon"; + return; + } + + /* Issue a warning message for Octeon unaligned load/store + instructions used when octeon_use_unalign is not set. */ + if (mips_opts.arch == CPU_OCTEON && ! octeon_use_unalign + && (strcmp (insn->name, "ulw") == 0 + || strcmp (insn->name, "uld") == 0 + || strcmp (insn->name, "usw") == 0 + || strcmp (insn->name, "usd") == 0)) + { + static char buf[120]; + sprintf (buf, _("Octeon specific unaligned load/store instructions are not allowed with -mno-octeon-useun")); + insn_error = buf; + return; + } + + /* Issue a warning message for MIPS unaligned load/store + instructions used when octeon_use_unalign is set. */ + if (mips_opts.arch == CPU_OCTEON && octeon_use_unalign + && (strcmp (insn->name, "lwl") == 0 + || strcmp (insn->name, "lwr") == 0 + || strcmp (insn->name, "ldl") == 0 + || strcmp (insn->name, "ldr") == 0 + || strcmp (insn->name, "sdl") == 0 + || strcmp (insn->name, "sdr") == 0 + || strcmp (insn->name, "swr") == 0 + || strcmp (insn->name, "swl") == 0)) + { + static char buf[100]; + sprintf (buf, _("Unaligned load/store instructions are not allowed with -mocteon-useun")); + insn_error = buf; + return; + } + } + + /* Octeon has its own version of dmtc2/dmfc2 instructions, error on + other formats. */ + if (mips_opts.arch == CPU_OCTEON + && (strcmp (insn->name, "dmtc2") == 0 + || strcmp (insn->name, "dmfc2") == 0) + && (insn->membership & INSN_OCTEON) != INSN_OCTEON) + { + static char buf[100]; + sprintf (buf, + _("opcode not supported in %s"), + mips_cpu_info_from_arch (mips_opts.arch)->name); + insn_error = buf; + ok = FALSE; } if (! ok) @@ -8166,8 +8277,7 @@ mips_ip (char *str, struct mips_cl_insn *ip) } } - ip->insn_mo = insn; - ip->insn_opcode = insn->match; + create_insn (ip, insn); insn_error = NULL; for (args = insn->args;; ++args) { @@ -8182,6 +8292,229 @@ mips_ip (char *str, struct mips_cl_insn *ip) return; break; + case '3': /* dsp 3-bit unsigned immediate in bit 21 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if (imm_expr.X_add_number & ~OP_MASK_SA3) + { + as_warn (_("DSP immediate not in range 0..%d (%lu)"), + OP_MASK_SA3, (unsigned long) imm_expr.X_add_number); + imm_expr.X_add_number &= OP_MASK_SA3; + } + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_SA3; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '4': /* dsp 4-bit unsigned immediate in bit 21 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if (imm_expr.X_add_number & ~OP_MASK_SA4) + { + as_warn (_("DSP immediate not in range 0..%d (%lu)"), + OP_MASK_SA4, (unsigned long) imm_expr.X_add_number); + imm_expr.X_add_number &= OP_MASK_SA4; + } + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_SA4; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '5': /* dsp 8-bit unsigned immediate in bit 16 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if (imm_expr.X_add_number & ~OP_MASK_IMM8) + { + as_warn (_("DSP immediate not in range 0..%d (%lu)"), + OP_MASK_IMM8, (unsigned long) imm_expr.X_add_number); + imm_expr.X_add_number &= OP_MASK_IMM8; + } + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_IMM8; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '6': /* dsp 5-bit unsigned immediate in bit 21 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if (imm_expr.X_add_number & ~OP_MASK_RS) + { + as_warn (_("DSP immediate not in range 0..%d (%lu)"), + OP_MASK_RS, (unsigned long) imm_expr.X_add_number); + imm_expr.X_add_number &= OP_MASK_RS; + } + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_RS; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '7': /* four dsp accumulators in bits 11,12 */ + if (s[0] == '$' && s[1] == 'a' && s[2] == 'c' && + s[3] >= '0' && s[3] <= '3') + { + regno = s[3] - '0'; + s += 4; + ip->insn_opcode |= regno << OP_SH_DSPACC; + continue; + } + else + as_bad (_("Invalid dsp acc register")); + break; + + case '8': /* dsp 6-bit unsigned immediate in bit 11 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if (imm_expr.X_add_number & ~OP_MASK_WRDSP) + { + as_warn (_("DSP immediate not in range 0..%d (%lu)"), + OP_MASK_WRDSP, + (unsigned long) imm_expr.X_add_number); + imm_expr.X_add_number &= OP_MASK_WRDSP; + } + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_WRDSP; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '9': /* four dsp accumulators in bits 21,22 */ + if (s[0] == '$' && s[1] == 'a' && s[2] == 'c' && + s[3] >= '0' && s[3] <= '3') + { + regno = s[3] - '0'; + s += 4; + ip->insn_opcode |= regno << OP_SH_DSPACC_S; + continue; + } + else + as_bad (_("Invalid dsp acc register")); + break; + + case '0': /* dsp 6-bit signed immediate in bit 20 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + min_range = -((OP_MASK_DSPSFT + 1) >> 1); + max_range = ((OP_MASK_DSPSFT + 1) >> 1) - 1; + if (imm_expr.X_add_number < min_range || + imm_expr.X_add_number > max_range) + { + as_warn (_("DSP immediate not in range %ld..%ld (%ld)"), + (long) min_range, (long) max_range, + (long) imm_expr.X_add_number); + } + imm_expr.X_add_number &= OP_MASK_DSPSFT; + ip->insn_opcode |= ((unsigned long) imm_expr.X_add_number + << OP_SH_DSPSFT); + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '\'': /* dsp 6-bit unsigned immediate in bit 16 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if (imm_expr.X_add_number & ~OP_MASK_RDDSP) + { + as_warn (_("DSP immediate not in range 0..%d (%lu)"), + OP_MASK_RDDSP, + (unsigned long) imm_expr.X_add_number); + imm_expr.X_add_number &= OP_MASK_RDDSP; + } + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_RDDSP; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case ':': /* dsp 7-bit signed immediate in bit 19 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + min_range = -((OP_MASK_DSPSFT_7 + 1) >> 1); + max_range = ((OP_MASK_DSPSFT_7 + 1) >> 1) - 1; + if (imm_expr.X_add_number < min_range || + imm_expr.X_add_number > max_range) + { + as_warn (_("DSP immediate not in range %ld..%ld (%ld)"), + (long) min_range, (long) max_range, + (long) imm_expr.X_add_number); + } + imm_expr.X_add_number &= OP_MASK_DSPSFT_7; + ip->insn_opcode |= ((unsigned long) imm_expr.X_add_number + << OP_SH_DSPSFT_7); + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '@': /* dsp 10-bit signed immediate in bit 16 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + min_range = -((OP_MASK_IMM10 + 1) >> 1); + max_range = ((OP_MASK_IMM10 + 1) >> 1) - 1; + if (imm_expr.X_add_number < min_range || + imm_expr.X_add_number > max_range) + { + as_warn (_("DSP immediate not in range %ld..%ld (%ld)"), + (long) min_range, (long) max_range, + (long) imm_expr.X_add_number); + } + imm_expr.X_add_number &= OP_MASK_IMM10; + ip->insn_opcode |= ((unsigned long) imm_expr.X_add_number + << OP_SH_IMM10); + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '!': /* mt 1-bit unsigned immediate in bit 5 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if (imm_expr.X_add_number & ~OP_MASK_MT_U) + { + as_warn (_("MT immediate not in range 0..%d (%lu)"), + OP_MASK_MT_U, (unsigned long) imm_expr.X_add_number); + imm_expr.X_add_number &= OP_MASK_MT_U; + } + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_MT_U; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '$': /* mt 1-bit unsigned immediate in bit 4 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if (imm_expr.X_add_number & ~OP_MASK_MT_H) + { + as_warn (_("MT immediate not in range 0..%d (%lu)"), + OP_MASK_MT_H, (unsigned long) imm_expr.X_add_number); + imm_expr.X_add_number &= OP_MASK_MT_H; + } + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_MT_H; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '*': /* four dsp accumulators in bits 18,19 */ + if (s[0] == '$' && s[1] == 'a' && s[2] == 'c' && + s[3] >= '0' && s[3] <= '3') + { + regno = s[3] - '0'; + s += 4; + ip->insn_opcode |= regno << OP_SH_MTACC_T; + continue; + } + else + as_bad (_("Invalid dsp/smartmips acc register")); + break; + + case '&': /* four dsp accumulators in bits 13,14 */ + if (s[0] == '$' && s[1] == 'a' && s[2] == 'c' && + s[3] >= '0' && s[3] <= '3') + { + regno = s[3] - '0'; + s += 4; + ip->insn_opcode |= regno << OP_SH_MTACC_D; + continue; + } + else + as_bad (_("Invalid dsp/smartmips acc register")); + break; + case ',': if (*s++ == *args) continue; @@ -8190,19 +8523,19 @@ mips_ip (char *str, struct mips_cl_insn *ip) { case 'r': case 'v': - ip->insn_opcode |= lastregno << OP_SH_RS; + INSERT_OPERAND (RS, *ip, lastregno); continue; case 'w': - ip->insn_opcode |= lastregno << OP_SH_RT; + INSERT_OPERAND (RT, *ip, lastregno); continue; case 'W': - ip->insn_opcode |= lastregno << OP_SH_FT; + INSERT_OPERAND (FT, *ip, lastregno); continue; case 'V': - ip->insn_opcode |= lastregno << OP_SH_FS; + INSERT_OPERAND (FS, *ip, lastregno); continue; } break; @@ -8247,8 +8580,7 @@ mips_ip (char *str, struct mips_cl_insn *ip) imm_expr.X_add_number = limlo; } lastpos = imm_expr.X_add_number; - ip->insn_opcode |= (imm_expr.X_add_number - & OP_MASK_SHAMT) << OP_SH_SHAMT; + INSERT_OPERAND (SHAMT, *ip, imm_expr.X_add_number); imm_expr.X_op = O_absent; s = expr_end; continue; @@ -8279,8 +8611,8 @@ mips_ip (char *str, struct mips_cl_insn *ip) (unsigned long) lastpos); imm_expr.X_add_number = limlo - lastpos; } - ip->insn_opcode |= ((lastpos + imm_expr.X_add_number - 1) - & OP_MASK_INSMSB) << OP_SH_INSMSB; + INSERT_OPERAND (INSMSB, *ip, + lastpos + imm_expr.X_add_number - 1); imm_expr.X_op = O_absent; s = expr_end; continue; @@ -8315,8 +8647,7 @@ mips_ip (char *str, struct mips_cl_insn *ip) (unsigned long) lastpos); imm_expr.X_add_number = limlo - lastpos; } - ip->insn_opcode |= ((imm_expr.X_add_number - 1) - & OP_MASK_EXTMSBD) << OP_SH_EXTMSBD; + INSERT_OPERAND (EXTMSBD, *ip, imm_expr.X_add_number - 1); imm_expr.X_op = O_absent; s = expr_end; continue; @@ -8331,10 +8662,39 @@ mips_ip (char *str, struct mips_cl_insn *ip) if (imm2_expr.X_op != O_big && imm2_expr.X_op != O_constant) insn_error = _("absolute expression required"); - normalize_constant_expr (&imm2_expr); + if (HAVE_32BIT_GPRS) + normalize_constant_expr (&imm2_expr); s = expr_end; continue; + case 'T': /* Coprocessor register */ + /* +T is for disassembly only; never match. */ + break; + + case 't': /* Coprocessor register number */ + if (s[0] == '$' && ISDIGIT (s[1])) + { + ++s; + regno = 0; + do + { + regno *= 10; + regno += *s - '0'; + ++s; + } + while (ISDIGIT (*s)); + if (regno > 31) + as_bad (_("Invalid register number (%d)"), regno); + else + { + ip->insn_opcode |= regno << OP_SH_RT; + continue; + } + } + else + as_bad (_("Invalid coprocessor 0 register number")); + break; + default: as_bad (_("internal: bad mips opcode (unknown extension operand type `+%c'): %s %s"), *args, insn->name, insn->args); @@ -8353,12 +8713,9 @@ mips_ip (char *str, struct mips_cl_insn *ip) my_getExpression (&imm_expr, s); check_absolute_expr (ip, &imm_expr); if ((unsigned long) imm_expr.X_add_number > 31) - { - as_warn (_("Improper shift amount (%lu)"), - (unsigned long) imm_expr.X_add_number); - imm_expr.X_add_number &= OP_MASK_SHAMT; - } - ip->insn_opcode |= imm_expr.X_add_number << OP_SH_SHAMT; + as_warn (_("Improper shift amount (%lu)"), + (unsigned long) imm_expr.X_add_number); + INSERT_OPERAND (SHAMT, *ip, imm_expr.X_add_number); imm_expr.X_op = O_absent; s = expr_end; continue; @@ -8369,7 +8726,35 @@ mips_ip (char *str, struct mips_cl_insn *ip) if ((unsigned long) imm_expr.X_add_number < 32 || (unsigned long) imm_expr.X_add_number > 63) break; - ip->insn_opcode |= (imm_expr.X_add_number - 32) << OP_SH_SHAMT; + INSERT_OPERAND (SHAMT, *ip, imm_expr.X_add_number - 32); + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '^': /* must be at least one digit */ + /* Decode 5-bits of bbit0/1's bit index amount. If the value is + greater than 31, issue a warning and mask out all but the low + 5 bits. */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if ((unsigned long) imm_expr.X_add_number > 31) + { + as_warn (_("Improper bit index amount (%lu)"), + (unsigned long) imm_expr.X_add_number); + imm_expr.X_add_number &= OP_MASK_BITIND; + } + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_BITIND; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '~': /* bit index minus 32 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if ((unsigned long) imm_expr.X_add_number < 32 + || (unsigned long) imm_expr.X_add_number > 63) + break; + ip->insn_opcode |= (imm_expr.X_add_number - 32) << OP_SH_BITIND; imm_expr.X_op = O_absent; s = expr_end; continue; @@ -8379,16 +8764,13 @@ mips_ip (char *str, struct mips_cl_insn *ip) my_getExpression (&imm_expr, s); check_absolute_expr (ip, &imm_expr); if ((unsigned long) imm_expr.X_add_number > 31) - { - as_warn (_("Invalid value for `%s' (%lu)"), - ip->insn_mo->name, - (unsigned long) imm_expr.X_add_number); - imm_expr.X_add_number &= 0x1f; - } + as_warn (_("Invalid value for `%s' (%lu)"), + ip->insn_mo->name, + (unsigned long) imm_expr.X_add_number); if (*args == 'k') - ip->insn_opcode |= imm_expr.X_add_number << OP_SH_CACHE; + INSERT_OPERAND (CACHE, *ip, imm_expr.X_add_number); else - ip->insn_opcode |= imm_expr.X_add_number << OP_SH_PREFX; + INSERT_OPERAND (PREFX, *ip, imm_expr.X_add_number); imm_expr.X_op = O_absent; s = expr_end; continue; @@ -8397,12 +8779,9 @@ mips_ip (char *str, struct mips_cl_insn *ip) my_getExpression (&imm_expr, s); check_absolute_expr (ip, &imm_expr); if ((unsigned long) imm_expr.X_add_number > 1023) - { - as_warn (_("Illegal break code (%lu)"), - (unsigned long) imm_expr.X_add_number); - imm_expr.X_add_number &= OP_MASK_CODE; - } - ip->insn_opcode |= imm_expr.X_add_number << OP_SH_CODE; + as_warn (_("Illegal break code (%lu)"), + (unsigned long) imm_expr.X_add_number); + INSERT_OPERAND (CODE, *ip, imm_expr.X_add_number); imm_expr.X_op = O_absent; s = expr_end; continue; @@ -8411,12 +8790,26 @@ mips_ip (char *str, struct mips_cl_insn *ip) my_getExpression (&imm_expr, s); check_absolute_expr (ip, &imm_expr); if ((unsigned long) imm_expr.X_add_number > 1023) + as_warn (_("Illegal lower break code (%lu)"), + (unsigned long) imm_expr.X_add_number); + INSERT_OPERAND (CODE2, *ip, imm_expr.X_add_number); + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case 'y': + /* Decode 10-bits of seqi/snei's signed constant offset. Issue + a warning message if the value is not within the range. */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if (((unsigned long) imm_expr.X_add_number + 0x200) > 1023) { - as_warn (_("Illegal lower break code (%lu)"), + as_warn (_("Illegal 10-bit signed constant (%lu)"), (unsigned long) imm_expr.X_add_number); - imm_expr.X_add_number &= OP_MASK_CODE2; + imm_expr.X_add_number &= OP_MASK_CODE2; } - ip->insn_opcode |= imm_expr.X_add_number << OP_SH_CODE2; + ip->insn_opcode |= (imm_expr.X_add_number & OP_MASK_CODE2) + << OP_SH_CODE2; imm_expr.X_op = O_absent; s = expr_end; continue; @@ -8427,7 +8820,7 @@ mips_ip (char *str, struct mips_cl_insn *ip) if ((unsigned long) imm_expr.X_add_number > OP_MASK_CODE20) as_warn (_("Illegal 20-bit code (%lu)"), (unsigned long) imm_expr.X_add_number); - ip->insn_opcode |= imm_expr.X_add_number << OP_SH_CODE20; + INSERT_OPERAND (CODE20, *ip, imm_expr.X_add_number); imm_expr.X_op = O_absent; s = expr_end; continue; @@ -8452,7 +8845,7 @@ mips_ip (char *str, struct mips_cl_insn *ip) if ((unsigned long) imm_expr.X_add_number > OP_MASK_CODE19) as_warn (_("Illegal 19-bit code (%lu)"), (unsigned long) imm_expr.X_add_number); - ip->insn_opcode |= imm_expr.X_add_number << OP_SH_CODE19; + INSERT_OPERAND (CODE19, *ip, imm_expr.X_add_number); imm_expr.X_op = O_absent; s = expr_end; continue; @@ -8461,12 +8854,9 @@ mips_ip (char *str, struct mips_cl_insn *ip) my_getExpression (&imm_expr, s); check_absolute_expr (ip, &imm_expr); if (imm_expr.X_add_number != 0 && imm_expr.X_add_number != 1) - { - as_warn (_("Invalid performance register (%lu)"), - (unsigned long) imm_expr.X_add_number); - imm_expr.X_add_number &= OP_MASK_PERFREG; - } - ip->insn_opcode |= (imm_expr.X_add_number << OP_SH_PERFREG); + as_warn (_("Invalid performance register (%lu)"), + (unsigned long) imm_expr.X_add_number); + INSERT_OPERAND (PERFREG, *ip, imm_expr.X_add_number); imm_expr.X_op = O_absent; s = expr_end; continue; @@ -8484,10 +8874,10 @@ mips_ip (char *str, struct mips_cl_insn *ip) case 'x': /* ignore register name */ case 'z': /* must be zero register */ case 'U': /* destination register (clo/clz). */ + case 'g': /* coprocessor destination register */ s_reset = s; if (s[0] == '$') { - if (ISDIGIT (s[1])) { ++s; @@ -8603,21 +8993,22 @@ mips_ip (char *str, struct mips_cl_insn *ip) case 's': case 'v': case 'b': - ip->insn_opcode |= regno << OP_SH_RS; + INSERT_OPERAND (RS, *ip, regno); break; case 'd': case 'G': case 'K': - ip->insn_opcode |= regno << OP_SH_RD; + case 'g': + INSERT_OPERAND (RD, *ip, regno); break; case 'U': - ip->insn_opcode |= regno << OP_SH_RD; - ip->insn_opcode |= regno << OP_SH_RT; + INSERT_OPERAND (RD, *ip, regno); + INSERT_OPERAND (RT, *ip, regno); break; case 'w': case 't': case 'E': - ip->insn_opcode |= regno << OP_SH_RT; + INSERT_OPERAND (RT, *ip, regno); break; case 'x': /* This case exists because on the r3000 trunc @@ -8648,10 +9039,10 @@ mips_ip (char *str, struct mips_cl_insn *ip) { case 'r': case 'v': - ip->insn_opcode |= lastregno << OP_SH_RS; + INSERT_OPERAND (RS, *ip, lastregno); continue; case 'w': - ip->insn_opcode |= lastregno << OP_SH_RT; + INSERT_OPERAND (RT, *ip, lastregno); continue; } break; @@ -8660,12 +9051,9 @@ mips_ip (char *str, struct mips_cl_insn *ip) my_getExpression (&imm_expr, s); check_absolute_expr (ip, &imm_expr); if ((unsigned long) imm_expr.X_add_number > OP_MASK_ALN) - { - as_warn ("Improper align amount (%ld), using low bits", - (long) imm_expr.X_add_number); - imm_expr.X_add_number &= OP_MASK_ALN; - } - ip->insn_opcode |= imm_expr.X_add_number << OP_SH_ALN; + as_warn ("Improper align amount (%ld), using low bits", + (long) imm_expr.X_add_number); + INSERT_OPERAND (ALN, *ip, imm_expr.X_add_number); imm_expr.X_op = O_absent; s = expr_end; continue; @@ -8677,17 +9065,13 @@ mips_ip (char *str, struct mips_cl_insn *ip) my_getExpression (&imm_expr, s); check_absolute_expr (ip, &imm_expr); if ((unsigned long) imm_expr.X_add_number > OP_MASK_FT) - { - as_warn (_("Invalid MDMX Immediate (%ld)"), - (long) imm_expr.X_add_number); - imm_expr.X_add_number &= OP_MASK_FT; - } - imm_expr.X_add_number &= OP_MASK_FT; + as_warn (_("Invalid MDMX Immediate (%ld)"), + (long) imm_expr.X_add_number); + INSERT_OPERAND (FT, *ip, imm_expr.X_add_number); if (ip->insn_opcode & (OP_MASK_VSEL << OP_SH_VSEL)) ip->insn_opcode |= MDMX_FMTSEL_IMM_QH << OP_SH_VSEL; else ip->insn_opcode |= MDMX_FMTSEL_IMM_OB << OP_SH_VSEL; - ip->insn_opcode |= imm_expr.X_add_number << OP_SH_FT; imm_expr.X_op = O_absent; s = expr_end; continue; @@ -8704,6 +9088,11 @@ mips_ip (char *str, struct mips_cl_insn *ip) case 'V': case 'W': s_reset = s; + if (mips_opts.arch == CPU_OCTEON && octeon_error_on_unsupported) + { + insn_error = "opcode not implemented in Octeon"; + return; + } /* Accept $fN for FP and MDMX register numbers, and in addition accept $vN for MDMX register numbers. */ if ((s[0] == '$' && s[1] == 'f' && ISDIGIT (s[2])) @@ -8730,7 +9119,13 @@ mips_ip (char *str, struct mips_cl_insn *ip) || strcmp (str, "lwc1") == 0 || strcmp (str, "swc1") == 0 || strcmp (str, "l.s") == 0 - || strcmp (str, "s.s") == 0)) + || strcmp (str, "s.s") == 0 + || strcmp (str, "mftc1") == 0 + || strcmp (str, "mfthc1") == 0 + || strcmp (str, "cftc1") == 0 + || strcmp (str, "mttc1") == 0 + || strcmp (str, "mtthc1") == 0 + || strcmp (str, "cttc1") == 0)) as_warn (_("Float register should be even, was %d"), regno); @@ -8750,12 +9145,12 @@ mips_ip (char *str, struct mips_cl_insn *ip) { case 'D': case 'X': - ip->insn_opcode |= regno << OP_SH_FD; + INSERT_OPERAND (FD, *ip, regno); break; case 'V': case 'S': case 'Y': - ip->insn_opcode |= regno << OP_SH_FS; + INSERT_OPERAND (FS, *ip, regno); break; case 'Q': /* This is like 'Z', but also needs to fix the MDMX @@ -8776,6 +9171,7 @@ mips_ip (char *str, struct mips_cl_insn *ip) ip->insn_opcode |= (imm_expr.X_add_number << (OP_SH_VSEL + (is_qh ? 2 : 1))); + imm_expr.X_op = O_absent; if (*s != ']') as_warn(_("Expecting ']' found '%s'"), s); else @@ -8794,10 +9190,10 @@ mips_ip (char *str, struct mips_cl_insn *ip) case 'W': case 'T': case 'Z': - ip->insn_opcode |= regno << OP_SH_FT; + INSERT_OPERAND (FT, *ip, regno); break; case 'R': - ip->insn_opcode |= regno << OP_SH_FR; + INSERT_OPERAND (FR, *ip, regno); break; } lastregno = regno; @@ -8807,10 +9203,10 @@ mips_ip (char *str, struct mips_cl_insn *ip) switch (*args++) { case 'V': - ip->insn_opcode |= lastregno << OP_SH_FS; + INSERT_OPERAND (FS, *ip, lastregno); continue; case 'W': - ip->insn_opcode |= lastregno << OP_SH_FT; + INSERT_OPERAND (FT, *ip, lastregno); continue; } break; @@ -8820,12 +9216,14 @@ mips_ip (char *str, struct mips_cl_insn *ip) if (imm_expr.X_op != O_big && imm_expr.X_op != O_constant) insn_error = _("absolute expression required"); - normalize_constant_expr (&imm_expr); + if (HAVE_32BIT_GPRS) + normalize_constant_expr (&imm_expr); s = expr_end; continue; case 'A': my_getExpression (&offset_expr, s); + normalize_address_expr (&offset_expr); *imm_reloc = BFD_RELOC_32; s = expr_end; continue; @@ -8865,13 +9263,6 @@ mips_ip (char *str, struct mips_cl_insn *ip) The .lit4 and .lit8 sections are only used if permitted by the -G argument. - When generating embedded PIC code, we use the - .lit8 section but not the .lit4 section (we can do - .lit4 inline easily; we need to put .lit8 - somewhere in the data segment, and using .lit8 - permits the linker to eventually combine identical - .lit8 entries). - The code below needs to know whether the target register is 32 or 64 bits wide. It relies on the fact 'f' and 'F' are used with GPR-based instructions and 'l' and @@ -8897,9 +9288,7 @@ mips_ip (char *str, struct mips_cl_insn *ip) if (*args == 'f' || (*args == 'l' - && (! USE_GLOBAL_POINTER_OPT - || mips_pic == EMBEDDED_PIC - || g_switch_value < 4 + && (g_switch_value < 4 || (temp[0] == 0 && temp[1] == 0) || (temp[2] == 0 && temp[3] == 0)))) { @@ -8986,19 +9375,14 @@ mips_ip (char *str, struct mips_cl_insn *ip) default: /* unused default case avoids warnings. */ case 'L': newname = RDATA_SECTION_NAME; - if ((USE_GLOBAL_POINTER_OPT && g_switch_value >= 8) - || mips_pic == EMBEDDED_PIC) + if (g_switch_value >= 8) newname = ".lit8"; break; case 'F': - if (mips_pic == EMBEDDED_PIC) - newname = ".lit8"; - else - newname = RDATA_SECTION_NAME; + newname = RDATA_SECTION_NAME; break; case 'l': - assert (!USE_GLOBAL_POINTER_OPT - || g_switch_value >= 4); + assert (g_switch_value >= 4); newname = ".lit4"; break; } @@ -9154,9 +9538,9 @@ mips_ip (char *str, struct mips_cl_insn *ip) as_warn(_("Condition code register should be 0 or 4 for %s, was %d"), str, regno); if (*args == 'N') - ip->insn_opcode |= regno << OP_SH_BCC; + INSERT_OPERAND (BCC, *ip, regno); else - ip->insn_opcode |= regno << OP_SH_CCC; + INSERT_OPERAND (CCC, *ip, regno); continue; case 'H': @@ -9194,7 +9578,7 @@ mips_ip (char *str, struct mips_cl_insn *ip) imm_expr.X_add_number = 0; } - ip->insn_opcode |= imm_expr.X_add_number << OP_SH_VECBYTE; + INSERT_OPERAND (VECBYTE, *ip, imm_expr.X_add_number); imm_expr.X_op = O_absent; s = expr_end; continue; @@ -9211,7 +9595,7 @@ mips_ip (char *str, struct mips_cl_insn *ip) imm_expr.X_add_number = 0; } - ip->insn_opcode |= imm_expr.X_add_number << OP_SH_VECALIGN; + INSERT_OPERAND (VECALIGN, *ip, imm_expr.X_add_number); imm_expr.X_op = O_absent; s = expr_end; continue; @@ -9238,6 +9622,8 @@ mips_ip (char *str, struct mips_cl_insn *ip) } } +#define SKIP_SPACE_TABS(S) { while (*(S) == ' ' || *(S) == '\t') ++(S); } + /* This routine assembles an instruction into its binary format when assembling for the mips16. As a side effect, it sets one of the global variables imm_reloc or offset_reloc to the type of @@ -9255,6 +9641,7 @@ mips16_ip (char *str, struct mips_cl_insn *ip) unsigned int regno; unsigned int lastregno = 0; char *s_reset; + size_t i; insn_error = NULL; @@ -9307,9 +9694,7 @@ mips16_ip (char *str, struct mips_cl_insn *ip) { assert (strcmp (insn->name, str) == 0); - ip->insn_mo = insn; - ip->insn_opcode = insn->match; - ip->use_extend = FALSE; + create_insn (ip, insn); imm_expr.X_op = O_absent; imm_reloc[0] = BFD_RELOC_UNUSED; imm_reloc[1] = BFD_RELOC_UNUSED; @@ -9341,6 +9726,8 @@ mips16_ip (char *str, struct mips_cl_insn *ip) && *imm_reloc > BFD_RELOC_UNUSED && insn->pinfo != INSN_MACRO) { + *offset_reloc = BFD_RELOC_UNUSED; + mips16_immed (NULL, 0, *imm_reloc - BFD_RELOC_UNUSED, imm_expr.X_add_number, TRUE, mips16_small, mips16_ext, &ip->insn_opcode, @@ -9360,10 +9747,10 @@ mips16_ip (char *str, struct mips_cl_insn *ip) switch (*++args) { case 'v': - ip->insn_opcode |= lastregno << MIPS16OP_SH_RX; + MIPS16_INSERT_OPERAND (RX, *ip, lastregno); continue; case 'w': - ip->insn_opcode |= lastregno << MIPS16OP_SH_RY; + MIPS16_INSERT_OPERAND (RY, *ip, lastregno); continue; } break; @@ -9379,9 +9766,9 @@ mips16_ip (char *str, struct mips_cl_insn *ip) if (s[0] != '$') { if (c == 'v') - ip->insn_opcode |= lastregno << MIPS16OP_SH_RX; + MIPS16_INSERT_OPERAND (RX, *ip, lastregno); else - ip->insn_opcode |= lastregno << MIPS16OP_SH_RY; + MIPS16_INSERT_OPERAND (RY, *ip, lastregno); ++args; continue; } @@ -9516,27 +9903,27 @@ mips16_ip (char *str, struct mips_cl_insn *ip) { case 'x': case 'v': - ip->insn_opcode |= regno << MIPS16OP_SH_RX; + MIPS16_INSERT_OPERAND (RX, *ip, regno); break; case 'y': case 'w': - ip->insn_opcode |= regno << MIPS16OP_SH_RY; + MIPS16_INSERT_OPERAND (RY, *ip, regno); break; case 'z': - ip->insn_opcode |= regno << MIPS16OP_SH_RZ; + MIPS16_INSERT_OPERAND (RZ, *ip, regno); break; case 'Z': - ip->insn_opcode |= regno << MIPS16OP_SH_MOVE32Z; + MIPS16_INSERT_OPERAND (MOVE32Z, *ip, regno); case '0': case 'S': case 'R': break; case 'X': - ip->insn_opcode |= regno << MIPS16OP_SH_REGR32; + MIPS16_INSERT_OPERAND (REGR32, *ip, regno); break; case 'Y': regno = ((regno & 7) << 2) | ((regno & 0x18) >> 3); - ip->insn_opcode |= regno << MIPS16OP_SH_REG32R; + MIPS16_INSERT_OPERAND (REG32R, *ip, regno); break; default: internalError (); @@ -9553,47 +9940,43 @@ mips16_ip (char *str, struct mips_cl_insn *ip) } break; - case '<': - case '>': - case '[': - case ']': - case '4': case '5': case 'H': case 'W': case 'D': case 'j': - case '8': case 'V': case 'C': case 'U': case 'k': case 'K': - if (s[0] == '%' - && strncmp (s + 1, "gprel(", sizeof "gprel(" - 1) == 0) + i = my_getSmallExpression (&imm_expr, imm_reloc, s); + if (i > 0) { - /* This is %gprel(SYMBOL). We need to read SYMBOL, - and generate the appropriate reloc. If the text - inside %gprel is not a symbol name with an - optional offset, then we generate a normal reloc - and will probably fail later. */ - my_getExpression (&imm_expr, s + sizeof "%gprel" - 1); - if (imm_expr.X_op == O_symbol) + if (imm_expr.X_op != O_constant) { mips16_ext = TRUE; - *imm_reloc = BFD_RELOC_MIPS16_GPREL; - s = expr_end; ip->use_extend = TRUE; ip->extend = 0; - continue; } + else + { + /* We need to relax this instruction. */ + *offset_reloc = *imm_reloc; + *imm_reloc = (int) BFD_RELOC_UNUSED + c; + } + s = expr_end; + continue; } - else - { - /* Just pick up a normal expression. */ - my_getExpression (&imm_expr, s); - } - + *imm_reloc = BFD_RELOC_UNUSED; + /* Fall through. */ + case '<': + case '>': + case '[': + case ']': + case '4': + case '8': + my_getExpression (&imm_expr, s); if (imm_expr.X_op == O_register) { /* What we thought was an expression turned out to @@ -9642,13 +10025,10 @@ mips16_ip (char *str, struct mips_cl_insn *ip) my_getExpression (&imm_expr, s); check_absolute_expr (ip, &imm_expr); if ((unsigned long) imm_expr.X_add_number > 63) - { - as_warn (_("Invalid value for `%s' (%lu)"), - ip->insn_mo->name, - (unsigned long) imm_expr.X_add_number); - imm_expr.X_add_number &= 0x3f; - } - ip->insn_opcode |= imm_expr.X_add_number << MIPS16OP_SH_IMM6; + as_warn (_("Invalid value for `%s' (%lu)"), + ip->insn_mo->name, + (unsigned long) imm_expr.X_add_number); + MIPS16_INSERT_OPERAND (IMM6, *ip, imm_expr.X_add_number); imm_expr.X_op = O_absent; s = expr_end; continue; @@ -9753,6 +10133,184 @@ mips16_ip (char *str, struct mips_cl_insn *ip) } continue; + case 'm': /* Register list for save insn. */ + case 'M': /* Register list for restore insn. */ + { + int opcode = 0; + int framesz = 0, seen_framesz = 0; + int args = 0, statics = 0, sregs = 0; + + while (*s != '\0') + { + unsigned int reg1, reg2; + + SKIP_SPACE_TABS (s); + while (*s == ',') + ++s; + SKIP_SPACE_TABS (s); + + my_getExpression (&imm_expr, s); + if (imm_expr.X_op == O_constant) + { + /* Handle the frame size. */ + if (seen_framesz) + { + as_bad (_("more than one frame size in list")); + break; + } + seen_framesz = 1; + framesz = imm_expr.X_add_number; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + } + + if (*s != '$') + { + as_bad (_("can't parse register list")); + break; + } + ++s; + + reg1 = 0; + while (ISDIGIT (*s)) + { + reg1 *= 10; + reg1 += *s - '0'; + ++s; + } + SKIP_SPACE_TABS (s); + if (*s != '-') + reg2 = reg1; + else + { + ++s; + if (*s != '$') + { + as_bad (_("can't parse register list")); + break; + } + ++s; + reg2 = 0; + while (ISDIGIT (*s)) + { + reg2 *= 10; + reg2 += *s - '0'; + ++s; + } + } + + while (reg1 <= reg2) + { + if (reg1 >= 4 && reg1 <= 7) + { + if (c == 'm' && !seen_framesz) + /* args $a0-$a3 */ + args |= 1 << (reg1 - 4); + else + /* statics $a0-$a3 */ + statics |= 1 << (reg1 - 4); + } + else if ((reg1 >= 16 && reg1 <= 23) || reg1 == 30) + { + /* $s0-$s8 */ + sregs |= 1 << ((reg1 == 30) ? 8 : (reg1 - 16)); + } + else if (reg1 == 31) + { + /* Add $ra to insn. */ + opcode |= 0x40; + } + else + { + as_bad (_("unexpected register in list")); + break; + } + if (++reg1 == 24) + reg1 = 30; + } + } + + /* Encode args/statics combination. */ + if (args & statics) + as_bad (_("arg/static registers overlap")); + else if (args == 0xf) + /* All $a0-$a3 are args. */ + opcode |= MIPS16_ALL_ARGS << 16; + else if (statics == 0xf) + /* All $a0-$a3 are statics. */ + opcode |= MIPS16_ALL_STATICS << 16; + else + { + int narg = 0, nstat = 0; + + /* Count arg registers. */ + while (args & 0x1) + { + args >>= 1; + narg++; + } + if (args != 0) + as_bad (_("invalid arg register list")); + + /* Count static registers. */ + while (statics & 0x8) + { + statics = (statics << 1) & 0xf; + nstat++; + } + if (statics != 0) + as_bad (_("invalid static register list")); + + /* Encode args/statics. */ + opcode |= ((narg << 2) | nstat) << 16; + } + + /* Encode $s0/$s1. */ + if (sregs & (1 << 0)) /* $s0 */ + opcode |= 0x20; + if (sregs & (1 << 1)) /* $s1 */ + opcode |= 0x10; + sregs >>= 2; + + if (sregs != 0) + { + /* Count regs $s2-$s8. */ + int nsreg = 0; + while (sregs & 1) + { + sregs >>= 1; + nsreg++; + } + if (sregs != 0) + as_bad (_("invalid static register list")); + /* Encode $s2-$s8. */ + opcode |= nsreg << 24; + } + + /* Encode frame size. */ + if (!seen_framesz) + as_bad (_("missing frame size")); + else if ((framesz & 7) != 0 || framesz < 0 + || framesz > 0xff * 8) + as_bad (_("invalid frame size")); + else if (framesz != 128 || (opcode >> 16) != 0) + { + framesz /= 8; + opcode |= (((framesz & 0xf0) << 16) + | (framesz & 0x0f)); + } + + /* Finally build the instruction. */ + if ((opcode >> 16) != 0 || framesz == 0) + { + ip->use_extend = TRUE; + ip->extend = opcode >> 16; + } + ip->insn_opcode |= opcode & 0x7f; + } + continue; + case 'e': /* extend code */ my_getExpression (&imm_expr, s); check_absolute_expr (ip, &imm_expr); @@ -9955,11 +10513,13 @@ mips16_immed (char *file, unsigned int line, int type, offsetT val, } } -static const struct percent_op_match +struct percent_op_match { const char *str; bfd_reloc_code_real_type reloc; -} percent_op[] = +}; + +static const struct percent_op_match mips_percent_op[] = { {"%lo", BFD_RELOC_LO16}, #ifdef OBJ_ELF @@ -9981,7 +10541,6 @@ static const struct percent_op_match {"%hi", BFD_RELOC_HI16_S} }; - /* Return true if *STR points to a relocation operator. When returning true, move *STR over the operator and store its relocation code in *RELOC. Leave both *STR and *RELOC alone when returning false. */ @@ -9989,11 +10548,20 @@ static const struct percent_op_match static bfd_boolean parse_relocation (char **str, bfd_reloc_code_real_type *reloc) { - size_t i; + const struct percent_op_match *percent_op; + size_t limit, i; - for (i = 0; i < ARRAY_SIZE (percent_op); i++) + percent_op = mips_percent_op; + limit = ARRAY_SIZE (mips_percent_op); + + for (i = 0; i < limit; i++) if (strncasecmp (*str, percent_op[i].str, strlen (percent_op[i].str)) == 0) { + int len = strlen (percent_op[i].str); + + if (!ISSPACE ((*str)[len]) && (*str)[len] != '(') + continue; + *str += strlen (percent_op[i].str); *reloc = percent_op[i].reloc; @@ -10003,7 +10571,7 @@ parse_relocation (char **str, bfd_reloc_code_real_type *reloc) { as_bad ("relocation %s isn't supported by the current ABI", percent_op[i].str); - *reloc = BFD_RELOC_LO16; + *reloc = BFD_RELOC_UNUSED; } return TRUE; } @@ -10015,8 +10583,7 @@ parse_relocation (char **str, bfd_reloc_code_real_type *reloc) expression in *EP and the relocations in the array starting at RELOC. Return the number of relocation operators used. - On exit, EXPR_END points to the first character after the expression. - If no relocation operators are used, RELOC[0] is set to BFD_RELOC_LO16. */ + On exit, EXPR_END points to the first character after the expression. */ static size_t my_getSmallExpression (expressionS *ep, bfd_reloc_code_real_type *reloc, @@ -10062,9 +10629,7 @@ my_getSmallExpression (expressionS *ep, bfd_reloc_code_real_type *reloc, expr_end = str; - if (reloc_index == 0) - reloc[0] = BFD_RELOC_LO16; - else + if (reloc_index != 0) { prev_reloc_op_frag = frag_now; for (i = 0; i < reloc_index; i++) @@ -10230,9 +10795,17 @@ struct option md_longopts[] = {"mdmx", no_argument, NULL, OPTION_MDMX}, #define OPTION_NO_MDMX (OPTION_ASE_BASE + 5) {"no-mdmx", no_argument, NULL, OPTION_NO_MDMX}, +#define OPTION_DSP (OPTION_ASE_BASE + 6) + {"mdsp", no_argument, NULL, OPTION_DSP}, +#define OPTION_NO_DSP (OPTION_ASE_BASE + 7) + {"mno-dsp", no_argument, NULL, OPTION_NO_DSP}, +#define OPTION_MT (OPTION_ASE_BASE + 8) + {"mmt", no_argument, NULL, OPTION_MT}, +#define OPTION_NO_MT (OPTION_ASE_BASE + 9) + {"mno-mt", no_argument, NULL, OPTION_NO_MT}, /* Old-style architecture options. Don't add more of these. */ -#define OPTION_COMPAT_ARCH_BASE (OPTION_ASE_BASE + 6) +#define OPTION_COMPAT_ARCH_BASE (OPTION_ASE_BASE + 10) #define OPTION_M4650 (OPTION_COMPAT_ARCH_BASE + 0) {"m4650", no_argument, NULL, OPTION_M4650}, #define OPTION_NO_M4650 (OPTION_COMPAT_ARCH_BASE + 1) @@ -10261,41 +10834,51 @@ struct option md_longopts[] = #define OPTION_NO_FIX_VR4120 (OPTION_FIX_BASE + 3) {"mfix-vr4120", no_argument, NULL, OPTION_FIX_VR4120}, {"mno-fix-vr4120", no_argument, NULL, OPTION_NO_FIX_VR4120}, +#define OPTION_FIX_VR4130 (OPTION_FIX_BASE + 4) +#define OPTION_NO_FIX_VR4130 (OPTION_FIX_BASE + 5) + {"mfix-vr4130", no_argument, NULL, OPTION_FIX_VR4130}, + {"mno-fix-vr4130", no_argument, NULL, OPTION_NO_FIX_VR4130}, /* Miscellaneous options. */ -#define OPTION_MISC_BASE (OPTION_FIX_BASE + 4) -#define OPTION_MEMBEDDED_PIC (OPTION_MISC_BASE + 0) - {"membedded-pic", no_argument, NULL, OPTION_MEMBEDDED_PIC}, -#define OPTION_TRAP (OPTION_MISC_BASE + 1) +#define OPTION_MISC_BASE (OPTION_FIX_BASE + 6) +#define OPTION_TRAP (OPTION_MISC_BASE + 0) {"trap", no_argument, NULL, OPTION_TRAP}, {"no-break", no_argument, NULL, OPTION_TRAP}, -#define OPTION_BREAK (OPTION_MISC_BASE + 2) +#define OPTION_BREAK (OPTION_MISC_BASE + 1) {"break", no_argument, NULL, OPTION_BREAK}, {"no-trap", no_argument, NULL, OPTION_BREAK}, -#define OPTION_EB (OPTION_MISC_BASE + 3) +#define OPTION_EB (OPTION_MISC_BASE + 2) {"EB", no_argument, NULL, OPTION_EB}, -#define OPTION_EL (OPTION_MISC_BASE + 4) +#define OPTION_EL (OPTION_MISC_BASE + 3) {"EL", no_argument, NULL, OPTION_EL}, -#define OPTION_FP32 (OPTION_MISC_BASE + 5) +#define OPTION_FP32 (OPTION_MISC_BASE + 4) {"mfp32", no_argument, NULL, OPTION_FP32}, -#define OPTION_GP32 (OPTION_MISC_BASE + 6) +#define OPTION_GP32 (OPTION_MISC_BASE + 5) {"mgp32", no_argument, NULL, OPTION_GP32}, -#define OPTION_CONSTRUCT_FLOATS (OPTION_MISC_BASE + 7) +#define OPTION_CONSTRUCT_FLOATS (OPTION_MISC_BASE + 6) {"construct-floats", no_argument, NULL, OPTION_CONSTRUCT_FLOATS}, -#define OPTION_NO_CONSTRUCT_FLOATS (OPTION_MISC_BASE + 8) +#define OPTION_NO_CONSTRUCT_FLOATS (OPTION_MISC_BASE + 7) {"no-construct-floats", no_argument, NULL, OPTION_NO_CONSTRUCT_FLOATS}, -#define OPTION_FP64 (OPTION_MISC_BASE + 9) +#define OPTION_FP64 (OPTION_MISC_BASE + 8) {"mfp64", no_argument, NULL, OPTION_FP64}, -#define OPTION_GP64 (OPTION_MISC_BASE + 10) +#define OPTION_GP64 (OPTION_MISC_BASE + 9) {"mgp64", no_argument, NULL, OPTION_GP64}, -#define OPTION_RELAX_BRANCH (OPTION_MISC_BASE + 11) -#define OPTION_NO_RELAX_BRANCH (OPTION_MISC_BASE + 12) +#define OPTION_RELAX_BRANCH (OPTION_MISC_BASE + 10) +#define OPTION_NO_RELAX_BRANCH (OPTION_MISC_BASE + 11) {"relax-branch", no_argument, NULL, OPTION_RELAX_BRANCH}, {"no-relax-branch", no_argument, NULL, OPTION_NO_RELAX_BRANCH}, +#define OPTION_MSHARED (OPTION_MISC_BASE + 12) +#define OPTION_MNO_SHARED (OPTION_MISC_BASE + 13) + {"mshared", no_argument, NULL, OPTION_MSHARED}, + {"mno-shared", no_argument, NULL, OPTION_MNO_SHARED}, +#define OPTION_MSYM32 (OPTION_MISC_BASE + 14) +#define OPTION_MNO_SYM32 (OPTION_MISC_BASE + 15) + {"msym32", no_argument, NULL, OPTION_MSYM32}, + {"mno-sym32", no_argument, NULL, OPTION_MNO_SYM32}, /* ELF-specific options. */ #ifdef OBJ_ELF -#define OPTION_ELF_BASE (OPTION_MISC_BASE + 13) +#define OPTION_ELF_BASE (OPTION_MISC_BASE + 16) #define OPTION_CALL_SHARED (OPTION_ELF_BASE + 0) {"KPIC", no_argument, NULL, OPTION_CALL_SHARED}, {"call_shared", no_argument, NULL, OPTION_CALL_SHARED}, @@ -10321,6 +10904,16 @@ struct option md_longopts[] = {"mno-pdr", no_argument, NULL, OPTION_NO_PDR}, #endif /* OBJ_ELF */ +#define OPTION_MOCTEON_UNSUPPORTED (OPTION_MISC_BASE + 28) +#define OPTION_NO_MOCTEON_UNSUPPORTED (OPTION_MISC_BASE + 29) + {"mocteon-unsupported", no_argument, NULL, OPTION_MOCTEON_UNSUPPORTED}, + {"mno-octeon-unsupported", no_argument, NULL, OPTION_NO_MOCTEON_UNSUPPORTED}, + +#define OPTION_MOCTEON_USEUN (OPTION_MISC_BASE + 30) +#define OPTION_NO_MOCTEON_USEUN (OPTION_MISC_BASE + 31) + {"mocteon-useun", no_argument, NULL, OPTION_MOCTEON_USEUN}, + {"mno-octeon-useun", no_argument, NULL, OPTION_NO_MOCTEON_USEUN}, + {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof (md_longopts); @@ -10371,6 +10964,22 @@ md_parse_option (int c, char *arg) target_big_endian = 0; break; + case OPTION_MOCTEON_UNSUPPORTED: + octeon_error_on_unsupported = 1; + break; + + case OPTION_NO_MOCTEON_UNSUPPORTED: + octeon_error_on_unsupported = 0; + break; + + case OPTION_MOCTEON_USEUN: + octeon_use_unalign = 1; + break; + + case OPTION_NO_MOCTEON_USEUN: + octeon_use_unalign = 0; + break; + case 'O': if (arg && arg[1] == '0') mips_optimize = 1; @@ -10474,14 +11083,30 @@ md_parse_option (int c, char *arg) mips_opts.ase_mdmx = 0; break; + case OPTION_DSP: + mips_opts.ase_dsp = 1; + break; + + case OPTION_NO_DSP: + mips_opts.ase_dsp = 0; + break; + + case OPTION_MT: + mips_opts.ase_mt = 1; + break; + + case OPTION_NO_MT: + mips_opts.ase_mt = 0; + break; + case OPTION_MIPS16: mips_opts.mips16 = 1; - mips_no_prev_insn (FALSE); + mips_no_prev_insn (); break; case OPTION_NO_MIPS16: mips_opts.mips16 = 0; - mips_no_prev_insn (FALSE); + mips_no_prev_insn (); break; case OPTION_MIPS3D: @@ -10492,16 +11117,6 @@ md_parse_option (int c, char *arg) mips_opts.ase_mips3d = 0; break; - case OPTION_MEMBEDDED_PIC: - mips_pic = EMBEDDED_PIC; - if (USE_GLOBAL_POINTER_OPT && g_switch_seen) - { - as_bad (_("-G may not be used with embedded PIC code")); - return 0; - } - g_switch_value = 0x7fffffff; - break; - case OPTION_FIX_VR4120: mips_fix_vr4120 = 1; break; @@ -10510,6 +11125,14 @@ md_parse_option (int c, char *arg) mips_fix_vr4120 = 0; break; + case OPTION_FIX_VR4130: + mips_fix_vr4130 = 1; + break; + + case OPTION_NO_FIX_VR4130: + mips_fix_vr4130 = 0; + break; + case OPTION_RELAX_BRANCH: mips_relax_branch = 1; break; @@ -10518,6 +11141,22 @@ md_parse_option (int c, char *arg) mips_relax_branch = 0; break; + case OPTION_MSHARED: + mips_in_shared = TRUE; + break; + + case OPTION_MNO_SHARED: + mips_in_shared = FALSE; + break; + + case OPTION_MSYM32: + mips_opts.sym32 = TRUE; + break; + + case OPTION_MNO_SYM32: + mips_opts.sym32 = FALSE; + break; + #ifdef OBJ_ELF /* When generating ELF code, we permit -KPIC and -call_shared to select SVR4_PIC, and -non_shared to select no PIC. This is @@ -10530,12 +11169,6 @@ md_parse_option (int c, char *arg) } mips_pic = SVR4_PIC; mips_abicalls = TRUE; - if (g_switch_seen && g_switch_value != 0) - { - as_bad (_("-G may not be used with SVR4 PIC code")); - return 0; - } - g_switch_value = 0; break; case OPTION_NON_SHARED: @@ -10548,8 +11181,8 @@ md_parse_option (int c, char *arg) mips_abicalls = FALSE; break; - /* The -xgot option tells the assembler to use 32 offsets when - accessing the got in SVR4_PIC mode. It is for Irix + /* The -xgot option tells the assembler to use 32 bit offsets + when accessing the got in SVR4_PIC mode. It is for Irix compatibility. */ case OPTION_XGOT: mips_big_got = 1; @@ -10557,18 +11190,7 @@ md_parse_option (int c, char *arg) #endif /* OBJ_ELF */ case 'G': - if (! USE_GLOBAL_POINTER_OPT) - { - as_bad (_("-G is not supported for this configuration")); - return 0; - } - else if (mips_pic == SVR4_PIC || mips_pic == EMBEDDED_PIC) - { - as_bad (_("-G may not be used with SVR4 or embedded PIC code")); - return 0; - } - else - g_switch_value = atoi (arg); + g_switch_value = atoi (arg); g_switch_seen = 1; break; @@ -10716,10 +11338,9 @@ mips_after_parse_args (void) const struct mips_cpu_info *tune_info = 0; /* GP relative stuff not working for PE */ - if (strncmp (TARGET_OS, "pe", 2) == 0 - && g_switch_value != 0) + if (strncmp (TARGET_OS, "pe", 2) == 0) { - if (g_switch_seen) + if (g_switch_seen && g_switch_value != 0) as_bad (_("-G not supported in this configuration.")); g_switch_value = 0; } @@ -10821,11 +11442,17 @@ mips_after_parse_args (void) mips_opts.ase_mips3d = (CPU_HAS_MIPS3D (file_mips_arch)) ? 1 : 0; if (mips_opts.ase_mdmx == -1) mips_opts.ase_mdmx = (CPU_HAS_MDMX (file_mips_arch)) ? 1 : 0; + if (mips_opts.ase_dsp == -1) + mips_opts.ase_dsp = (CPU_HAS_DSP (file_mips_arch)) ? 1 : 0; + if (mips_opts.ase_mt == -1) + mips_opts.ase_mt = (CPU_HAS_MT (file_mips_arch)) ? 1 : 0; file_mips_isa = mips_opts.isa; file_ase_mips16 = mips_opts.mips16; file_ase_mips3d = mips_opts.ase_mips3d; file_ase_mdmx = mips_opts.ase_mdmx; + file_ase_dsp = mips_opts.ase_dsp; + file_ase_mt = mips_opts.ase_mt; mips_opts.gp32 = file_mips_gp32; mips_opts.fp32 = file_mips_fp32; @@ -10881,10 +11508,53 @@ mips_frob_file_before_adjust (void) #endif } -/* Sort any unmatched HI16_S relocs so that they immediately precede - the corresponding LO reloc. This is called before md_apply_fix3 and - tc_gen_reloc. Unmatched HI16_S relocs can only be generated by - explicit use of the %hi modifier. */ +/* Sort any unmatched HI16 and GOT16 relocs so that they immediately precede + the corresponding LO16 reloc. This is called before md_apply_fix3 and + tc_gen_reloc. Unmatched relocs can only be generated by use of explicit + relocation operators. + + For our purposes, a %lo() expression matches a %got() or %hi() + expression if: + + (a) it refers to the same symbol; and + (b) the offset applied in the %lo() expression is no lower than + the offset applied in the %got() or %hi(). + + (b) allows us to cope with code like: + + lui $4,%hi(foo) + lh $4,%lo(foo+2)($4) + + ...which is legal on RELA targets, and has a well-defined behaviour + if the user knows that adding 2 to "foo" will not induce a carry to + the high 16 bits. + + When several %lo()s match a particular %got() or %hi(), we use the + following rules to distinguish them: + + (1) %lo()s with smaller offsets are a better match than %lo()s with + higher offsets. + + (2) %lo()s with no matching %got() or %hi() are better than those + that already have a matching %got() or %hi(). + + (3) later %lo()s are better than earlier %lo()s. + + These rules are applied in order. + + (1) means, among other things, that %lo()s with identical offsets are + chosen if they exist. + + (2) means that we won't associate several high-part relocations with + the same low-part relocation unless there's no alternative. Having + several high parts for the same low part is a GNU extension; this rule + allows careful users to avoid it. + + (3) is purely cosmetic. mips_hi_fixup_list is is in reverse order, + with the last high-part relocation being at the front of the list. + It therefore makes sense to choose the last matching low-part + relocation, all other things being equal. It's also easier + to code that way. */ void mips_frob_file (void) @@ -10894,7 +11564,8 @@ mips_frob_file (void) for (l = mips_hi_fixup_list; l != NULL; l = l->next) { segment_info_type *seginfo; - int pass; + bfd_boolean matched_lo_p; + fixS **hi_pos, **lo_pos, **pos; assert (reloc_needs_lo_p (l->fixp->fx_r_type)); @@ -10908,81 +11579,56 @@ mips_frob_file (void) if (fixup_has_matching_lo_p (l->fixp)) continue; - /* Look through the fixups for this segment for a matching %lo. - When we find one, move the %hi just in front of it. We do - this in two passes. In the first pass, we try to find a - unique %lo. In the second pass, we permit multiple %hi - relocs for a single %lo (this is a GNU extension). */ seginfo = seg_info (l->seg); - for (pass = 0; pass < 2; pass++) + + /* Set HI_POS to the position of this relocation in the chain. + Set LO_POS to the position of the chosen low-part relocation. + MATCHED_LO_P is true on entry to the loop if *POS is a low-part + relocation that matches an immediately-preceding high-part + relocation. */ + hi_pos = NULL; + lo_pos = NULL; + matched_lo_p = FALSE; + for (pos = &seginfo->fix_root; *pos != NULL; pos = &(*pos)->fx_next) { - fixS *f, *prev; + if (*pos == l->fixp) + hi_pos = pos; - prev = NULL; - for (f = seginfo->fix_root; f != NULL; f = f->fx_next) + if ((*pos)->fx_r_type == BFD_RELOC_LO16 + && (*pos)->fx_addsy == l->fixp->fx_addsy + && (*pos)->fx_offset >= l->fixp->fx_offset + && (lo_pos == NULL + || (*pos)->fx_offset < (*lo_pos)->fx_offset + || (!matched_lo_p + && (*pos)->fx_offset == (*lo_pos)->fx_offset))) + lo_pos = pos; + + matched_lo_p = (reloc_needs_lo_p ((*pos)->fx_r_type) + && fixup_has_matching_lo_p (*pos)); + } + + /* If we found a match, remove the high-part relocation from its + current position and insert it before the low-part relocation. + Make the offsets match so that fixup_has_matching_lo_p() + will return true. + + We don't warn about unmatched high-part relocations since some + versions of gcc have been known to emit dead "lui ...%hi(...)" + instructions. */ + if (lo_pos != NULL) + { + l->fixp->fx_offset = (*lo_pos)->fx_offset; + if (l->fixp->fx_next != *lo_pos) { - /* Check whether this is a %lo fixup which matches l->fixp. */ - if (f->fx_r_type == BFD_RELOC_LO16 - && f->fx_addsy == l->fixp->fx_addsy - && f->fx_offset == l->fixp->fx_offset - && (pass == 1 - || prev == NULL - || !reloc_needs_lo_p (prev->fx_r_type) - || !fixup_has_matching_lo_p (prev))) - { - fixS **pf; - - /* Move l->fixp before f. */ - for (pf = &seginfo->fix_root; - *pf != l->fixp; - pf = &(*pf)->fx_next) - assert (*pf != NULL); - - *pf = l->fixp->fx_next; - - l->fixp->fx_next = f; - if (prev == NULL) - seginfo->fix_root = l->fixp; - else - prev->fx_next = l->fixp; - - break; - } - - prev = f; + *hi_pos = l->fixp->fx_next; + l->fixp->fx_next = *lo_pos; + *lo_pos = l->fixp; } - - if (f != NULL) - break; - -#if 0 /* GCC code motion plus incomplete dead code elimination - can leave a %hi without a %lo. */ - if (pass == 1) - as_warn_where (l->fixp->fx_file, l->fixp->fx_line, - _("Unmatched %%hi reloc")); -#endif } } } -/* When generating embedded PIC code we need to use a special - relocation to represent the difference of two symbols in the .text - section (switch tables use a difference of this sort). See - include/coff/mips.h for details. This macro checks whether this - fixup requires the special reloc. */ -#define SWITCH_TABLE(fixp) \ - ((fixp)->fx_r_type == BFD_RELOC_32 \ - && OUTPUT_FLAVOR != bfd_target_elf_flavour \ - && (fixp)->fx_addsy != NULL \ - && (fixp)->fx_subsy != NULL \ - && S_GET_SEGMENT ((fixp)->fx_addsy) == text_section \ - && S_GET_SEGMENT ((fixp)->fx_subsy) == text_section) - -/* When generating embedded PIC code we must keep all PC relative - relocations, in case the linker has to relax a call. We also need - to keep relocations for switch table entries. - - We may have combined relocations without symbols in the N32/N64 ABI. +/* We may have combined relocations without symbols in the N32/N64 ABI. We have to prevent gas from dropping them. */ int @@ -10998,89 +11644,7 @@ mips_force_relocation (fixS *fixp) || fixp->fx_r_type == BFD_RELOC_LO16)) return 1; - return (mips_pic == EMBEDDED_PIC - && (fixp->fx_pcrel - || SWITCH_TABLE (fixp) - || fixp->fx_r_type == BFD_RELOC_PCREL_HI16_S - || fixp->fx_r_type == BFD_RELOC_PCREL_LO16)); -} - -/* This hook is called before a fix is simplified. We don't really - decide whether to skip a fix here. Rather, we turn global symbols - used as branch targets into local symbols, such that they undergo - simplification. We can only do this if the symbol is defined and - it is in the same section as the branch. If this doesn't hold, we - emit a better error message than just saying the relocation is not - valid for the selected object format. - - FIXP is the fix-up we're going to try to simplify, SEG is the - segment in which the fix up occurs. The return value should be - non-zero to indicate the fix-up is valid for further - simplifications. */ - -int -mips_validate_fix (struct fix *fixP, asection *seg) -{ - /* There's a lot of discussion on whether it should be possible to - use R_MIPS_PC16 to represent branch relocations. The outcome - seems to be that it can, but gas/bfd are very broken in creating - RELA relocations for this, so for now we only accept branches to - symbols in the same section. Anything else is of dubious value, - since there's no guarantee that at link time the symbol would be - in range. Even for branches to local symbols this is arguably - wrong, since it we assume the symbol is not going to be - overridden, which should be possible per ELF library semantics, - but then, there isn't a dynamic relocation that could be used to - this effect, and the target would likely be out of range as well. - - Unfortunately, it seems that there is too much code out there - that relies on branches to symbols that are global to be resolved - as if they were local, like the IRIX tools do, so we do it as - well, but with a warning so that people are reminded to fix their - code. If we ever get back to using R_MIPS_PC16 for branch - targets, this entire block should go away (and probably the - whole function). */ - - if (fixP->fx_r_type == BFD_RELOC_16_PCREL_S2 - && (((OUTPUT_FLAVOR == bfd_target_ecoff_flavour - || OUTPUT_FLAVOR == bfd_target_elf_flavour) - && mips_pic != EMBEDDED_PIC) - || bfd_reloc_type_lookup (stdoutput, BFD_RELOC_16_PCREL_S2) == NULL) - && fixP->fx_addsy) - { - if (! S_IS_DEFINED (fixP->fx_addsy)) - { - as_bad_where (fixP->fx_file, fixP->fx_line, - _("Cannot branch to undefined symbol.")); - /* Avoid any further errors about this fixup. */ - fixP->fx_done = 1; - } - else if (S_GET_SEGMENT (fixP->fx_addsy) != seg) - { - as_bad_where (fixP->fx_file, fixP->fx_line, - _("Cannot branch to symbol in another section.")); - fixP->fx_done = 1; - } - else if (S_IS_EXTERNAL (fixP->fx_addsy)) - { - symbolS *sym = fixP->fx_addsy; - - if (mips_pic == SVR4_PIC) - as_warn_where (fixP->fx_file, fixP->fx_line, - _("Pretending global symbol used as branch target is local.")); - - fixP->fx_addsy = symbol_create (S_GET_NAME (sym), - S_GET_SEGMENT (sym), - S_GET_VALUE (sym), - symbol_get_frag (sym)); - copy_symbol_attributes (fixP->fx_addsy, sym); - S_CLEAR_EXTERNAL (fixP->fx_addsy); - assert (symbol_resolved_p (sym)); - symbol_mark_resolved (fixP->fx_addsy); - } - } - - return 1; + return 0; } /* Apply a fixup to the object file. */ @@ -11090,7 +11654,6 @@ md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) { bfd_byte *buf; long insn; - static int previous_fx_r_type = 0; reloc_howto_type *howto; /* We ignore generic BFD relocations we don't know about. */ @@ -11108,17 +11671,20 @@ md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) buf = (bfd_byte *) (fixP->fx_frag->fr_literal + fixP->fx_where); - /* We are not done if this is a composite relocation to set up gp. */ - if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel - && !(fixP->fx_r_type == BFD_RELOC_MIPS_SUB - || (fixP->fx_r_type == BFD_RELOC_64 - && (previous_fx_r_type == BFD_RELOC_GPREL32 - || previous_fx_r_type == BFD_RELOC_GPREL16)) - || (previous_fx_r_type == BFD_RELOC_MIPS_SUB - && (fixP->fx_r_type == BFD_RELOC_HI16_S - || fixP->fx_r_type == BFD_RELOC_LO16)))) + assert (! fixP->fx_pcrel || fixP->fx_r_type == BFD_RELOC_16_PCREL_S2); + + /* Don't treat parts of a composite relocation as done. There are two + reasons for this: + + (1) The second and third parts will be against 0 (RSS_UNDEF) but + should nevertheless be emitted if the first part is. + + (2) In normal usage, composite relocations are never assembly-time + constants. The easiest way of dealing with the pathological + exceptions is to generate a relocation against STN_UNDEF and + leave everything up to the linker. */ + if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel && fixP->fx_tcbit == 0) fixP->fx_done = 1; - previous_fx_r_type = fixP->fx_r_type; switch (fixP->fx_r_type) { @@ -11150,9 +11716,6 @@ md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_MIPS_CALL_HI16: case BFD_RELOC_MIPS_CALL_LO16: case BFD_RELOC_MIPS16_GPREL: - if (fixP->fx_pcrel) - as_bad_where (fixP->fx_file, fixP->fx_line, - _("Invalid PC relative reloc")); /* Nothing needed to do. The value comes from the reloc entry */ break; @@ -11163,47 +11726,13 @@ md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) *valP = 0; break; - case BFD_RELOC_PCREL_HI16_S: - /* The addend for this is tricky if it is internal, so we just - do everything here rather than in bfd_install_relocation. */ - if (OUTPUT_FLAVOR == bfd_target_elf_flavour && !fixP->fx_done) - break; - if (fixP->fx_addsy - && (symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0) - { - /* For an external symbol adjust by the address to make it - pcrel_offset. We use the address of the RELLO reloc - which follows this one. */ - *valP += (fixP->fx_next->fx_frag->fr_address - + fixP->fx_next->fx_where); - } - *valP = ((*valP + 0x8000) >> 16) & 0xffff; - if (target_big_endian) - buf += 2; - md_number_to_chars (buf, *valP, 2); - break; - - case BFD_RELOC_PCREL_LO16: - /* The addend for this is tricky if it is internal, so we just - do everything here rather than in bfd_install_relocation. */ - if (OUTPUT_FLAVOR == bfd_target_elf_flavour && !fixP->fx_done) - break; - if (fixP->fx_addsy - && (symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0) - *valP += fixP->fx_frag->fr_address + fixP->fx_where; - if (target_big_endian) - buf += 2; - md_number_to_chars (buf, *valP, 2); - break; - case BFD_RELOC_64: /* This is handled like BFD_RELOC_32, but we output a sign extended value if we are only 32 bits. */ - if (fixP->fx_done - || (mips_pic == EMBEDDED_PIC && SWITCH_TABLE (fixP))) + if (fixP->fx_done) { if (8 <= sizeof (valueT)) - md_number_to_chars (buf, *valP, 8); + md_number_to_chars ((char *) buf, *valP, 8); else { valueT hiv; @@ -11212,9 +11741,9 @@ md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) hiv = 0xffffffff; else hiv = 0; - md_number_to_chars ((char *)(buf + target_big_endian ? 4 : 0), + md_number_to_chars ((char *)(buf + (target_big_endian ? 4 : 0)), *valP, 4); - md_number_to_chars ((char *)(buf + target_big_endian ? 0 : 4), + md_number_to_chars ((char *)(buf + (target_big_endian ? 0 : 4)), hiv, 4); } } @@ -11224,23 +11753,21 @@ md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_32: /* If we are deleting this reloc entry, we must fill in the value now. This can happen if we have a .word which is not - resolved when it appears but is later defined. We also need - to fill in the value if this is an embedded PIC switch table - entry. */ - if (fixP->fx_done - || (mips_pic == EMBEDDED_PIC && SWITCH_TABLE (fixP))) - md_number_to_chars (buf, *valP, 4); + resolved when it appears but is later defined. */ + if (fixP->fx_done) + md_number_to_chars ((char *) buf, *valP, 4); break; case BFD_RELOC_16: /* If we are deleting this reloc entry, we must fill in the value now. */ - assert (fixP->fx_size == 2); if (fixP->fx_done) - md_number_to_chars (buf, *valP, 2); + md_number_to_chars ((char *) buf, *valP, 2); break; case BFD_RELOC_LO16: + /* FIXME: Now that embedded-PIC is gone, some of this code/comment + may be safe to remove, but if so it's not obvious. */ /* When handling an embedded PIC switch statement, we can wind up deleting a LO16 reloc. See the 'o' case in mips_ip. */ if (fixP->fx_done) @@ -11250,14 +11777,14 @@ md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) _("relocation overflow")); if (target_big_endian) buf += 2; - md_number_to_chars (buf, *valP, 2); + md_number_to_chars ((char *) buf, *valP, 2); } break; case BFD_RELOC_16_PCREL_S2: if ((*valP & 0x3) != 0) as_bad_where (fixP->fx_file, fixP->fx_line, - _("Branch to odd address (%lx)"), (long) *valP); + _("Branch to misaligned address (%lx)"), (long) *valP); /* * We need to save the bits in the instruction since fixup_segment() @@ -11276,7 +11803,7 @@ md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) if (*valP + 0x20000 <= 0x3ffff) { insn |= (*valP >> 2) & 0xffff; - md_number_to_chars (buf, insn, 4); + md_number_to_chars ((char *) buf, insn, 4); } else if (mips_pic == NO_PIC && fixP->fx_done @@ -11298,7 +11825,7 @@ md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) fixP->fx_done = 0; fixP->fx_addsy = section_symbol (text_section); *valP += md_pcrel_from (fixP); - md_number_to_chars (buf, insn, 4); + md_number_to_chars ((char *) buf, insn, 4); } else { @@ -11330,93 +11857,6 @@ md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) fixP->fx_addnumber = *valP; } -#if 0 -void -printInsn (unsigned long oc) -{ - const struct mips_opcode *p; - int treg, sreg, dreg, shamt; - short imm; - const char *args; - int i; - - for (i = 0; i < NUMOPCODES; ++i) - { - p = &mips_opcodes[i]; - if (((oc & p->mask) == p->match) && (p->pinfo != INSN_MACRO)) - { - printf ("%08lx %s\t", oc, p->name); - treg = (oc >> 16) & 0x1f; - sreg = (oc >> 21) & 0x1f; - dreg = (oc >> 11) & 0x1f; - shamt = (oc >> 6) & 0x1f; - imm = oc; - for (args = p->args;; ++args) - { - switch (*args) - { - case '\0': - printf ("\n"); - break; - - case ',': - case '(': - case ')': - printf ("%c", *args); - continue; - - case 'r': - assert (treg == sreg); - printf ("$%d,$%d", treg, sreg); - continue; - - case 'd': - case 'G': - printf ("$%d", dreg); - continue; - - case 't': - case 'E': - printf ("$%d", treg); - continue; - - case 'k': - printf ("0x%x", treg); - continue; - - case 'b': - case 's': - printf ("$%d", sreg); - continue; - - case 'a': - printf ("0x%08lx", oc & 0x1ffffff); - continue; - - case 'i': - case 'j': - case 'o': - case 'u': - printf ("%d", imm); - continue; - - case '<': - case '>': - printf ("$%d", shamt); - continue; - - default: - internalError (); - } - break; - } - return; - } - } - printf (_("%08lx UNDEFINED\n"), oc); -} -#endif - static symbolS * get_symbol (void) { @@ -11437,7 +11877,7 @@ get_symbol (void) static void mips_align (int to, int fill, symbolS *label) { - mips_emit_delays (FALSE); + mips_emit_delays (); frag_align (to, fill, 0); record_alignment (now_seg, to); if (label != NULL) @@ -11499,25 +11939,11 @@ s_align (int x ATTRIBUTE_UNUSED) demand_empty_rest_of_line (); } -void -mips_flush_pending_output (void) -{ - mips_emit_delays (FALSE); - mips_clear_insn_labels (); -} - static void s_change_sec (int sec) { segT seg; - /* When generating embedded PIC code, we only use the .text, .lit8, - .sdata and .sbss sections. We change the .data and .rdata - pseudo-ops to use .sdata. */ - if (mips_pic == EMBEDDED_PIC - && (sec == 'd' || sec == 'r')) - sec = 's'; - #ifdef OBJ_ELF /* The ELF backend needs to know that we are changing sections, so that .previous works correctly. We could do something like check @@ -11528,7 +11954,7 @@ s_change_sec (int sec) obj_elf_section_change_hook (); #endif - mips_emit_delays (FALSE); + mips_emit_delays (); switch (sec) { case 't': @@ -11543,52 +11969,30 @@ s_change_sec (int sec) break; case 'r': - if (USE_GLOBAL_POINTER_OPT) + seg = subseg_new (RDATA_SECTION_NAME, + (subsegT) get_absolute_expression ()); + if (OUTPUT_FLAVOR == bfd_target_elf_flavour) { - seg = subseg_new (RDATA_SECTION_NAME, - (subsegT) get_absolute_expression ()); - if (OUTPUT_FLAVOR == bfd_target_elf_flavour) - { - bfd_set_section_flags (stdoutput, seg, - (SEC_ALLOC - | SEC_LOAD - | SEC_READONLY - | SEC_RELOC - | SEC_DATA)); - if (strcmp (TARGET_OS, "elf") != 0) - record_alignment (seg, 4); - } - demand_empty_rest_of_line (); - } - else - { - as_bad (_("No read only data section in this object file format")); - demand_empty_rest_of_line (); - return; + bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD + | SEC_READONLY | SEC_RELOC + | SEC_DATA)); + if (strcmp (TARGET_OS, "elf") != 0) + record_alignment (seg, 4); } + demand_empty_rest_of_line (); break; case 's': - if (USE_GLOBAL_POINTER_OPT) + seg = subseg_new (".sdata", (subsegT) get_absolute_expression ()); + if (OUTPUT_FLAVOR == bfd_target_elf_flavour) { - seg = subseg_new (".sdata", (subsegT) get_absolute_expression ()); - if (OUTPUT_FLAVOR == bfd_target_elf_flavour) - { - bfd_set_section_flags (stdoutput, seg, - SEC_ALLOC | SEC_LOAD | SEC_RELOC - | SEC_DATA); - if (strcmp (TARGET_OS, "elf") != 0) - record_alignment (seg, 4); - } - demand_empty_rest_of_line (); - break; - } - else - { - as_bad (_("Global pointers not supported; recompile -G 0")); - demand_empty_rest_of_line (); - return; + bfd_set_section_flags (stdoutput, seg, + SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA); + if (strcmp (TARGET_OS, "elf") != 0) + record_alignment (seg, 4); } + demand_empty_rest_of_line (); + break; } auto_align = 1; @@ -11681,7 +12085,7 @@ s_cons (int log_size) symbolS *label; label = insn_labels != NULL ? insn_labels->label : NULL; - mips_emit_delays (FALSE); + mips_emit_delays (); if (log_size > 0 && auto_align) mips_align (log_size, 0, label); mips_clear_insn_labels (); @@ -11695,7 +12099,7 @@ s_float_cons (int type) label = insn_labels != NULL ? insn_labels->label : NULL; - mips_emit_delays (FALSE); + mips_emit_delays (); if (auto_align) { @@ -11724,35 +12128,50 @@ s_mips_globl (int x ATTRIBUTE_UNUSED) symbolS *symbolP; flagword flag; - name = input_line_pointer; - c = get_symbol_end (); - symbolP = symbol_find_or_make (name); - *input_line_pointer = c; - SKIP_WHITESPACE (); - - /* On Irix 5, every global symbol that is not explicitly labelled as - being a function is apparently labelled as being an object. */ - flag = BSF_OBJECT; - - if (! is_end_of_line[(unsigned char) *input_line_pointer]) + do { - char *secname; - asection *sec; - - secname = input_line_pointer; + name = input_line_pointer; c = get_symbol_end (); - sec = bfd_get_section_by_name (stdoutput, secname); - if (sec == NULL) - as_bad (_("%s: no such section"), secname); + symbolP = symbol_find_or_make (name); + S_SET_EXTERNAL (symbolP); + *input_line_pointer = c; + SKIP_WHITESPACE (); - if (sec != NULL && (sec->flags & SEC_CODE) != 0) - flag = BSF_FUNCTION; + /* On Irix 5, every global symbol that is not explicitly labelled as + being a function is apparently labelled as being an object. */ + flag = BSF_OBJECT; + + if (!is_end_of_line[(unsigned char) *input_line_pointer] + && (*input_line_pointer != ',')) + { + char *secname; + asection *sec; + + secname = input_line_pointer; + c = get_symbol_end (); + sec = bfd_get_section_by_name (stdoutput, secname); + if (sec == NULL) + as_bad (_("%s: no such section"), secname); + *input_line_pointer = c; + + if (sec != NULL && (sec->flags & SEC_CODE) != 0) + flag = BSF_FUNCTION; + } + + symbol_get_bfdsym (symbolP)->flags |= flag; + + c = *input_line_pointer; + if (c == ',') + { + input_line_pointer++; + SKIP_WHITESPACE (); + if (is_end_of_line[(unsigned char) *input_line_pointer]) + c = '\n'; + } } + while (c == ','); - symbol_get_bfdsym (symbolP)->flags |= flag; - - S_SET_EXTERNAL (symbolP); demand_empty_rest_of_line (); } @@ -11784,7 +12203,7 @@ s_option (int x ATTRIBUTE_UNUSED) else as_bad (_(".option pic%d not supported"), i); - if (USE_GLOBAL_POINTER_OPT && mips_pic == SVR4_PIC) + if (mips_pic == SVR4_PIC) { if (g_switch_seen && g_switch_value != 0) as_warn (_("-G may not be used with SVR4 PIC code")); @@ -11823,22 +12242,13 @@ s_mipsset (int x ATTRIBUTE_UNUSED) if (strcmp (name, "reorder") == 0) { - if (mips_opts.noreorder && prev_nop_frag != NULL) - { - /* If we still have pending nops, we can discard them. The - usual nop handling will insert any that are still - needed. */ - prev_nop_frag->fr_fix -= (prev_nop_frag_holds - * (mips_opts.mips16 ? 2 : 4)); - prev_nop_frag = NULL; - } - mips_opts.noreorder = 0; + if (mips_opts.noreorder) + end_noreorder (); } else if (strcmp (name, "noreorder") == 0) { - mips_emit_delays (TRUE); - mips_opts.noreorder = 1; - mips_any_noreorder = 1; + if (!mips_opts.noreorder) + start_noreorder (); } else if (strcmp (name, "at") == 0) { @@ -11888,40 +12298,25 @@ s_mipsset (int x ATTRIBUTE_UNUSED) mips_opts.ase_mdmx = 1; else if (strcmp (name, "nomdmx") == 0) mips_opts.ase_mdmx = 0; + else if (strcmp (name, "dsp") == 0) + mips_opts.ase_dsp = 1; + else if (strcmp (name, "nodsp") == 0) + mips_opts.ase_dsp = 0; + else if (strcmp (name, "mt") == 0) + mips_opts.ase_mt = 1; + else if (strcmp (name, "nomt") == 0) + mips_opts.ase_mt = 0; else if (strncmp (name, "mips", 4) == 0 || strncmp (name, "arch=", 5) == 0) { int reset = 0; /* Permit the user to change the ISA and architecture on the fly. Needless to say, misuse can cause serious problems. */ - if (strcmp (name, "mips0") == 0) + if (strcmp (name, "mips0") == 0 || strcmp (name, "arch=default") == 0) { reset = 1; mips_opts.isa = file_mips_isa; - } - else if (strcmp (name, "mips1") == 0) - mips_opts.isa = ISA_MIPS1; - else if (strcmp (name, "mips2") == 0) - mips_opts.isa = ISA_MIPS2; - else if (strcmp (name, "mips3") == 0) - mips_opts.isa = ISA_MIPS3; - else if (strcmp (name, "mips4") == 0) - mips_opts.isa = ISA_MIPS4; - else if (strcmp (name, "mips5") == 0) - mips_opts.isa = ISA_MIPS5; - else if (strcmp (name, "mips32") == 0) - mips_opts.isa = ISA_MIPS32; - else if (strcmp (name, "mips32r2") == 0) - mips_opts.isa = ISA_MIPS32R2; - else if (strcmp (name, "mips64") == 0) - mips_opts.isa = ISA_MIPS64; - else if (strcmp (name, "mips64r2") == 0) - mips_opts.isa = ISA_MIPS64R2; - else if (strcmp (name, "arch=default") == 0) - { - reset = 1; mips_opts.arch = file_mips_arch; - mips_opts.isa = file_mips_isa; } else if (strncmp (name, "arch=", 5) == 0) { @@ -11936,8 +12331,21 @@ s_mipsset (int x ATTRIBUTE_UNUSED) mips_opts.isa = p->isa; } } + else if (strncmp (name, "mips", 4) == 0) + { + const struct mips_cpu_info *p; + + p = mips_parse_cpu("internal use", name); + if (!p) + as_bad (_("unknown ISA level %s"), name + 4); + else + { + mips_opts.arch = p->cpu; + mips_opts.isa = p->isa; + } + } else - as_bad (_("unknown ISA level %s"), name + 4); + as_bad (_("unknown ISA or architecture %s"), name); switch (mips_opts.isa) { @@ -11993,22 +12401,19 @@ s_mipsset (int x ATTRIBUTE_UNUSED) /* If we're changing the reorder mode we need to handle delay slots correctly. */ if (s->options.noreorder && ! mips_opts.noreorder) - mips_emit_delays (TRUE); + start_noreorder (); else if (! s->options.noreorder && mips_opts.noreorder) - { - if (prev_nop_frag != NULL) - { - prev_nop_frag->fr_fix -= (prev_nop_frag_holds - * (mips_opts.mips16 ? 2 : 4)); - prev_nop_frag = NULL; - } - } + end_noreorder (); mips_opts = s->options; mips_opts_stack = s->next; free (s); } } + else if (strcmp (name, "sym32") == 0) + mips_opts.sym32 = TRUE; + else if (strcmp (name, "nosym32") == 0) + mips_opts.sym32 = FALSE; else { as_warn (_("Tried to set unrecognized symbol: %s\n"), name); @@ -12025,12 +12430,11 @@ s_abicalls (int ignore ATTRIBUTE_UNUSED) { mips_pic = SVR4_PIC; mips_abicalls = TRUE; - if (USE_GLOBAL_POINTER_OPT) - { - if (g_switch_seen && g_switch_value != 0) - as_warn (_("-G may not be used with SVR4 PIC code")); - g_switch_value = 0; - } + + if (g_switch_seen && g_switch_value != 0) + as_warn (_("-G may not be used with SVR4 PIC code")); + g_switch_value = 0; + bfd_set_gp_size (stdoutput, 0); demand_empty_rest_of_line (); } @@ -12043,12 +12447,22 @@ s_abicalls (int ignore ATTRIBUTE_UNUSED) lui $gp,%hi(_gp_disp) addiu $gp,$gp,%lo(_gp_disp) addu $gp,$gp,.cpload argument - The .cpload argument is normally $25 == $t9. */ + The .cpload argument is normally $25 == $t9. + + The -mno-shared option changes this to: + lui $gp,%hi(__gnu_local_gp) + addiu $gp,$gp,%lo(__gnu_local_gp) + and the argument is ignored. This saves an instruction, but the + resulting code is not position independent; it uses an absolute + address for __gnu_local_gp. Thus code assembled with -mno-shared + can go into an ordinary executable, but not into a shared library. */ static void s_cpload (int ignore ATTRIBUTE_UNUSED) { expressionS ex; + int reg; + int in_shared; /* If we are not generating SVR4 PIC code, or if this is NewABI code, .cpload is ignored. */ @@ -12062,8 +12476,15 @@ s_cpload (int ignore ATTRIBUTE_UNUSED) if (mips_opts.noreorder == 0) as_warn (_(".cpload not in noreorder section")); + reg = tc_get_register (0); + + /* If we need to produce a 64-bit address, we are better off using + the default instruction sequence. */ + in_shared = mips_in_shared || HAVE_64BIT_SYMBOLS; + ex.X_op = O_symbol; - ex.X_add_symbol = symbol_find_or_make ("_gp_disp"); + ex.X_add_symbol = symbol_find_or_make (in_shared ? "_gp_disp" : + "__gnu_local_gp"); ex.X_op_symbol = NULL; ex.X_add_number = 0; @@ -12074,8 +12495,9 @@ s_cpload (int ignore ATTRIBUTE_UNUSED) macro_build_lui (&ex, mips_gp_register); macro_build (&ex, "addiu", "t,r,j", mips_gp_register, mips_gp_register, BFD_RELOC_LO16); - macro_build (NULL, "addu", "d,v,t", mips_gp_register, - mips_gp_register, tc_get_register (0)); + if (in_shared) + macro_build (NULL, "addu", "d,v,t", mips_gp_register, + mips_gp_register, reg); macro_end (); demand_empty_rest_of_line (); @@ -12095,14 +12517,19 @@ s_cpload (int ignore ATTRIBUTE_UNUSED) lui $gp, %hi(%neg(%gp_rel(label))) addiu $gp, $gp, %lo(%neg(%gp_rel(label))) daddu $gp, $gp, $reg1 - $reg1 is normally $25 == $t9. */ + $reg1 is normally $25 == $t9. + + The -mno-shared option replaces the last three instructions with + lui $gp,%hi(_gp) + addiu $gp,$gp,%lo(_gp) + */ + static void s_cpsetup (int ignore ATTRIBUTE_UNUSED) { expressionS ex_off; expressionS ex_sym; int reg1; - char *f; /* If we are not generating SVR4 PIC code, .cpsetup is ignored. We also need NewABI support. */ @@ -12158,26 +12585,36 @@ s_cpsetup (int ignore ATTRIBUTE_UNUSED) macro_build (NULL, "daddu", "d,v,t", mips_cpreturn_register, mips_gp_register, 0); - /* Ensure there's room for the next two instructions, so that `f' - doesn't end up with an address in the wrong frag. */ - frag_grow (8); - f = frag_more (0); - macro_build (&ex_sym, "lui", "t,u", mips_gp_register, BFD_RELOC_GPREL16); - fix_new (frag_now, f - frag_now->fr_literal, - 8, NULL, 0, 0, BFD_RELOC_MIPS_SUB); - fix_new (frag_now, f - frag_now->fr_literal, - 4, NULL, 0, 0, BFD_RELOC_HI16_S); + if (mips_in_shared || HAVE_64BIT_SYMBOLS) + { + macro_build (&ex_sym, "lui", "t,u", mips_gp_register, + -1, BFD_RELOC_GPREL16, BFD_RELOC_MIPS_SUB, + BFD_RELOC_HI16_S); - f = frag_more (0); - macro_build (&ex_sym, "addiu", "t,r,j", mips_gp_register, - mips_gp_register, BFD_RELOC_GPREL16); - fix_new (frag_now, f - frag_now->fr_literal, - 8, NULL, 0, 0, BFD_RELOC_MIPS_SUB); - fix_new (frag_now, f - frag_now->fr_literal, - 4, NULL, 0, 0, BFD_RELOC_LO16); + macro_build (&ex_sym, "addiu", "t,r,j", mips_gp_register, + mips_gp_register, -1, BFD_RELOC_GPREL16, + BFD_RELOC_MIPS_SUB, BFD_RELOC_LO16); + + macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", mips_gp_register, + mips_gp_register, reg1); + } + else + { + expressionS ex; + + ex.X_op = O_symbol; + ex.X_add_symbol = symbol_find_or_make ("__gnu_local_gp"); + ex.X_op_symbol = NULL; + ex.X_add_number = 0; + + /* In ELF, this symbol is implicitly an STT_OBJECT symbol. */ + symbol_get_bfdsym (ex.X_add_symbol)->flags |= BSF_OBJECT; + + macro_build_lui (&ex, mips_gp_register); + macro_build (&ex, "addiu", "t,r,j", mips_gp_register, + mips_gp_register, BFD_RELOC_LO16); + } - macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", mips_gp_register, - mips_gp_register, reg1); macro_end (); demand_empty_rest_of_line (); @@ -12306,7 +12743,7 @@ s_gpword (int ignore ATTRIBUTE_UNUSED) } label = insn_labels != NULL ? insn_labels->label : NULL; - mips_emit_delays (TRUE); + mips_emit_delays (); if (auto_align) mips_align (2, 0, label); mips_clear_insn_labels (); @@ -12342,7 +12779,7 @@ s_gpdword (int ignore ATTRIBUTE_UNUSED) } label = insn_labels != NULL ? insn_labels->label : NULL; - mips_emit_delays (TRUE); + mips_emit_delays (); if (auto_align) mips_align (3, 0, label); mips_clear_insn_labels (); @@ -12358,14 +12795,11 @@ s_gpdword (int ignore ATTRIBUTE_UNUSED) p = frag_more (8); md_number_to_chars (p, 0, 8); fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, - BFD_RELOC_GPREL32); + BFD_RELOC_GPREL32)->fx_tcbit = 1; /* GPREL32 composed with 64 gives a 64-bit GP offset. */ - ex.X_op = O_absent; - ex.X_add_symbol = 0; - ex.X_add_number = 0; - fix_new_exp (frag_now, p - frag_now->fr_literal, 8, &ex, FALSE, - BFD_RELOC_64); + fix_new (frag_now, p - frag_now->fr_literal, 8, NULL, 0, + FALSE, BFD_RELOC_64)->fx_tcbit = 1; demand_empty_rest_of_line (); } @@ -12587,7 +13021,7 @@ nopic_need_relax (symbolS *sym, int before_relaxing) if (sym == 0) return 0; - if (USE_GLOBAL_POINTER_OPT && g_switch_value > 0) + if (g_switch_value > 0) { const char *symname; int change; @@ -12694,9 +13128,7 @@ pic_need_relax (symbolS *sym, asection *segtype) #ifdef OBJ_ELF /* A global or weak symbol is treated as external. */ && (OUTPUT_FLAVOR != bfd_target_elf_flavour - || (! S_IS_WEAK (sym) - && (! S_IS_EXTERNAL (sym) - || mips_pic == EMBEDDED_PIC))) + || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym))) #endif ); } @@ -13004,15 +13436,13 @@ md_estimate_size_before_relax (fragS *fragp, asection *segtype) } /* This is called to see whether a reloc against a defined symbol - should be converted into a reloc against a section. Don't adjust - MIPS16 jump relocations, so we don't have to worry about the format - of the offset in the .o file. Don't adjust relocations against - mips16 symbols, so that the linker can find them if it needs to set - up a stub. */ + should be converted into a reloc against a section. */ int mips_fix_adjustable (fixS *fixp) { + /* Don't adjust MIPS16 jump relocations, so we don't have to worry + about the format of the offset in the .o file. */ if (fixp->fx_r_type == BFD_RELOC_MIPS16_JMP) return 0; @@ -13044,6 +13474,8 @@ mips_fix_adjustable (fixS *fixp) return 0; #ifdef OBJ_ELF + /* Don't adjust relocations against mips16 symbols, so that the linker + can find them if it needs to set up a stub. */ if (OUTPUT_FLAVOR == bfd_target_elf_flavour && S_GET_OTHER (fixp->fx_addsy) == STO_MIPS16 && fixp->fx_subsy == NULL) @@ -13069,56 +13501,20 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; - if (mips_pic == EMBEDDED_PIC - && SWITCH_TABLE (fixp)) + if (fixp->fx_pcrel) { - /* For a switch table entry we use a special reloc. The addend - is actually the difference between the reloc address and the - subtrahend. */ - reloc->addend = reloc->address - S_GET_VALUE (fixp->fx_subsy); - if (OUTPUT_FLAVOR != bfd_target_ecoff_flavour) - as_fatal (_("Double check fx_r_type in tc-mips.c:tc_gen_reloc")); - fixp->fx_r_type = BFD_RELOC_GPREL32; - } - else if (fixp->fx_pcrel) - { - bfd_vma pcrel_address; + assert (fixp->fx_r_type == BFD_RELOC_16_PCREL_S2); - /* Set PCREL_ADDRESS to this relocation's "PC". The PC for high - high-part relocs is the address of the low-part reloc. */ - if (fixp->fx_r_type == BFD_RELOC_PCREL_HI16_S) + /* At this point, fx_addnumber is "symbol offset - pcrel address". + Relocations want only the symbol offset. */ + reloc->addend = fixp->fx_addnumber + reloc->address; + if (OUTPUT_FLAVOR != bfd_target_elf_flavour) { - assert (fixp->fx_next != NULL - && fixp->fx_next->fx_r_type == BFD_RELOC_PCREL_LO16); - pcrel_address = (fixp->fx_next->fx_where - + fixp->fx_next->fx_frag->fr_address); - } - else - pcrel_address = reloc->address; - - if (OUTPUT_FLAVOR == bfd_target_elf_flavour) - { - /* At this point, fx_addnumber is "symbol offset - pcrel_address". - Relocations want only the symbol offset. */ - reloc->addend = fixp->fx_addnumber + pcrel_address; - } - else if (fixp->fx_r_type == BFD_RELOC_PCREL_LO16 - || fixp->fx_r_type == BFD_RELOC_PCREL_HI16_S) - { - /* We use a special addend for an internal RELLO or RELHI reloc. */ - if (symbol_section_p (fixp->fx_addsy)) - reloc->addend = pcrel_address - S_GET_VALUE (fixp->fx_subsy); - else - reloc->addend = fixp->fx_addnumber + pcrel_address; - } - else - { - if (OUTPUT_FLAVOR != bfd_target_aout_flavour) - /* A gruesome hack which is a result of the gruesome gas reloc - handling. */ - reloc->addend = pcrel_address; - else - reloc->addend = -pcrel_address; + /* A gruesome hack which is a result of the gruesome gas + reloc handling. What's worse, for COFF (as opposed to + ECOFF), we might need yet another copy of reloc->address. + See bfd_install_relocation. */ + reloc->addend += reloc->address; } } else @@ -13132,53 +13528,9 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) reloc->addend = 0; } - /* Since DIFF_EXPR_OK is defined in tc-mips.h, it is possible that - fixup_segment converted a non-PC relative reloc into a PC - relative reloc. In such a case, we need to convert the reloc - code. */ code = fixp->fx_r_type; - if (fixp->fx_pcrel) - { - switch (code) - { - case BFD_RELOC_8: - code = BFD_RELOC_8_PCREL; - break; - case BFD_RELOC_16: - code = BFD_RELOC_16_PCREL; - break; - case BFD_RELOC_32: - code = BFD_RELOC_32_PCREL; - break; - case BFD_RELOC_64: - code = BFD_RELOC_64_PCREL; - break; - case BFD_RELOC_8_PCREL: - case BFD_RELOC_16_PCREL: - case BFD_RELOC_32_PCREL: - case BFD_RELOC_64_PCREL: - case BFD_RELOC_16_PCREL_S2: - case BFD_RELOC_PCREL_HI16_S: - case BFD_RELOC_PCREL_LO16: - break; - default: - as_bad_where (fixp->fx_file, fixp->fx_line, - _("Cannot make %s relocation PC relative"), - bfd_get_reloc_code_name (code)); - } - } - - /* To support a PC relative reloc when generating embedded PIC code - for ECOFF, we use a Cygnus extension. We check for that here to - make sure that we don't let such a reloc escape normally. */ - if ((OUTPUT_FLAVOR == bfd_target_ecoff_flavour - || OUTPUT_FLAVOR == bfd_target_elf_flavour) - && code == BFD_RELOC_16_PCREL_S2 - && mips_pic != EMBEDDED_PIC) - reloc->howto = NULL; - else - reloc->howto = bfd_reloc_type_lookup (stdoutput, code); + reloc->howto = bfd_reloc_type_lookup (stdoutput, code); if (reloc->howto == NULL) { as_bad_where (fixp->fx_file, fixp->fx_line, @@ -13255,12 +13607,11 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp) exp.X_add_number = fragp->fr_offset; fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal, - 4, &exp, 1, - BFD_RELOC_16_PCREL_S2); + 4, &exp, 1, BFD_RELOC_16_PCREL_S2); fixp->fx_file = fragp->fr_file; fixp->fx_line = fragp->fr_line; - md_number_to_chars (buf, insn, 4); + md_number_to_chars ((char *) buf, insn, 4); buf += 4; } else @@ -13332,11 +13683,11 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp) i--; insn |= i; /* Branch over the jump. */ - md_number_to_chars (buf, insn, 4); + md_number_to_chars ((char *) buf, insn, 4); buf += 4; /* Nop */ - md_number_to_chars (buf, 0, 4); + md_number_to_chars ((char *) buf, 0, 4); buf += 4; if (RELAX_BRANCH_LIKELY (fragp->fr_subtype)) @@ -13355,10 +13706,10 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp) delay slot. */ insn |= i; - md_number_to_chars (buf, insn, 4); + md_number_to_chars ((char *) buf, insn, 4); buf += 4; - md_number_to_chars (buf, 0, 4); + md_number_to_chars ((char *) buf, 0, 4); buf += 4; } @@ -13377,7 +13728,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp) fixp->fx_file = fragp->fr_file; fixp->fx_line = fragp->fr_line; - md_number_to_chars (buf, insn, 4); + md_number_to_chars ((char *) buf, insn, 4); buf += 4; } else @@ -13399,13 +13750,13 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp) fixp->fx_file = fragp->fr_file; fixp->fx_line = fragp->fr_line; - md_number_to_chars (buf, insn, 4); + md_number_to_chars ((char *) buf, insn, 4); buf += 4; if (mips_opts.isa == ISA_MIPS1) { /* nop */ - md_number_to_chars (buf, 0, 4); + md_number_to_chars ((char *) buf, 0, 4); buf += 4; } @@ -13417,7 +13768,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp) fixp->fx_file = fragp->fr_file; fixp->fx_line = fragp->fr_line; - md_number_to_chars (buf, insn, 4); + md_number_to_chars ((char *) buf, insn, 4); buf += 4; /* j(al)r $at. */ @@ -13426,7 +13777,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp) else insn = 0x00200008; - md_number_to_chars (buf, insn, 4); + md_number_to_chars ((char *) buf, insn, 4); buf += 4; } } @@ -13519,12 +13870,12 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp) if (use_extend) { - md_number_to_chars (buf, 0xf000 | extend, 2); + md_number_to_chars ((char *) buf, 0xf000 | extend, 2); fragp->fr_fix += 2; buf += 2; } - md_number_to_chars (buf, insn, 2); + md_number_to_chars ((char *) buf, insn, 2); fragp->fr_fix += 2; buf += 2; } @@ -13692,6 +14043,10 @@ mips_elf_final_processing (void) elf_elfheader (stdoutput)->e_flags |= EF_MIPS_CPIC; /* Set MIPS ELF flags for ASEs. */ + /* We may need to define a new flag for DSP ASE, and set this flag when + file_ase_dsp is true. */ + /* We may need to define a new flag for MT ASE, and set this flag when + file_ase_mt is true. */ if (file_ase_mips16) elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ARCH_ASE_M16; #if 0 /* XXX FIXME */ @@ -13725,7 +14080,8 @@ mips_elf_final_processing (void) #endif /* OBJ_ELF || OBJ_MAYBE_ELF */ typedef struct proc { - symbolS *isym; + symbolS *func_sym; + symbolS *func_end_sym; unsigned long reg_mask; unsigned long reg_offset; unsigned long fpreg_mask; @@ -13909,7 +14265,7 @@ s_mips_end (int x ATTRIBUTE_UNUSED) if (p != NULL) { assert (S_GET_NAME (p)); - if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym))) + if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->func_sym))) as_warn (_(".end symbol does not match .ent symbol.")); if (debug_type == DEBUG_STABS) @@ -13920,6 +14276,21 @@ s_mips_end (int x ATTRIBUTE_UNUSED) as_warn (_(".end directive missing or unknown symbol")); #ifdef OBJ_ELF + /* Create an expression to calculate the size of the function. */ + if (p && cur_proc_ptr) + { + OBJ_SYMFIELD_TYPE *obj = symbol_get_obj (p); + expressionS *exp = xmalloc (sizeof (expressionS)); + + obj->size = exp; + exp->X_op = O_subtract; + exp->X_add_symbol = symbol_temp_new_now (); + exp->X_op_symbol = p; + exp->X_add_number = 0; + + cur_proc_ptr->func_end_sym = exp->X_add_symbol; + } + /* Generate a .pdr section. */ if (OUTPUT_FLAVOR == bfd_target_elf_flavour && ! ECOFF_DEBUGGING && mips_flag_pdr) @@ -13992,7 +14363,7 @@ s_mips_ent (int aent) cur_proc_ptr = &cur_proc; memset (cur_proc_ptr, '\0', sizeof (procS)); - cur_proc_ptr->isym = symbolP; + cur_proc_ptr->func_sym = symbolP; symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION; @@ -14098,29 +14469,6 @@ s_mips_mask (int reg_type) s_ignore (reg_type); } -/* The .loc directive. */ - -#if 0 -static void -s_loc (int x) -{ - symbolS *symbolP; - int lineno; - int addroff; - - assert (now_seg == text_section); - - lineno = get_number (); - addroff = frag_now_fix (); - - symbolP = symbol_new ("", N_SLINE, addroff, frag_now); - S_SET_TYPE (symbolP, N_SLINE); - S_SET_OTHER (symbolP, 0); - S_SET_DESC (symbolP, lineno); - symbolP->sy_segment = now_seg; -} -#endif - /* A table describing all the processors gas knows about. Names are matched in the order listed. @@ -14174,20 +14522,31 @@ static const struct mips_cpu_info mips_cpu_info_table[] = { "rm5261", 0, ISA_MIPS4, CPU_R5000 }, { "rm5721", 0, ISA_MIPS4, CPU_R5000 }, { "rm7000", 0, ISA_MIPS4, CPU_RM7000 }, - { "rm9000", 0, ISA_MIPS4, CPU_RM7000 }, + { "rm9000", 0, ISA_MIPS4, CPU_RM9000 }, /* MIPS 32 */ { "4kc", 0, ISA_MIPS32, CPU_MIPS32 }, { "4km", 0, ISA_MIPS32, CPU_MIPS32 }, { "4kp", 0, ISA_MIPS32, CPU_MIPS32 }, + /* MIPS32 Release 2 */ + { "m4k", 0, ISA_MIPS32R2, CPU_MIPS32R2 }, + { "24k", 0, ISA_MIPS32R2, CPU_MIPS32R2 }, + { "24kc", 0, ISA_MIPS32R2, CPU_MIPS32R2 }, + { "24kf", 0, ISA_MIPS32R2, CPU_MIPS32R2 }, + { "24kx", 0, ISA_MIPS32R2, CPU_MIPS32R2 }, + /* MIPS 64 */ { "5kc", 0, ISA_MIPS64, CPU_MIPS64 }, + { "5kf", 0, ISA_MIPS64, CPU_MIPS64 }, { "20kc", 0, ISA_MIPS64, CPU_MIPS64 }, /* Broadcom SB-1 CPU core */ { "sb1", 0, ISA_MIPS64, CPU_SB1 }, + /* Cavium Networks Octeon CPU core */ + { "octeon", 0, ISA_MIPS64R2, CPU_OCTEON }, + /* End marker */ { NULL, 0, 0, 0 } }; @@ -14354,7 +14713,6 @@ md_show_usage (FILE *stream) fprintf (stream, _("\ MIPS options:\n\ --membedded-pic generate embedded position independent code\n\ -EB generate big endian output\n\ -EL generate little endian output\n\ -g, -g2 do not remove unneeded NOPs or swap branches\n\ @@ -14396,9 +14754,18 @@ MIPS options:\n\ -mips16 generate mips16 instructions\n\ -no-mips16 do not generate mips16 instructions\n")); fprintf (stream, _("\ +-mdsp generate DSP instructions\n\ +-mno-dsp do not generate DSP instructions\n")); + fprintf (stream, _("\ +-mmt generate MT instructions\n\ +-mno-mt do not generate MT instructions\n")); + fprintf (stream, _("\ -mfix-vr4120 work around certain VR4120 errata\n\ +-mfix-vr4130 work around VR4130 mflo/mfhi errata\n\ -mgp32 use 32-bit GPRs, regardless of the chosen ISA\n\ -mfp32 use 32-bit FPRs, regardless of the chosen ISA\n\ +-mno-shared optimize output for executables\n\ +-msym32 assume all symbols have 32-bit values\n\ -O0 remove unneeded NOPs, do not swap branches\n\ -O remove unneeded NOPs and swap branches\n\ --[no-]construct-floats [dis]allow floating point values to be constructed\n\ @@ -14410,6 +14777,8 @@ MIPS options:\n\ -non_shared do not generate position independent code\n\ -xgot assume a 32 bit GOT\n\ -mpdr, -mno-pdr enable/disable creation of .pdr sections\n\ +-mshared, -mno-shared disable/enable .cpload optimization for\n\ + non-shared code\n\ -mabi=ABI create ABI conformant object file for:\n")); first = 1; @@ -14427,12 +14796,18 @@ MIPS options:\n\ -n32 create n32 ABI object file\n\ -64 create 64 ABI object file\n")); #endif + fprintf (stream, _("\ +-mocteon-unsupported error on unsupported Octeon instructions\n\ +-mno-octeon-unsupported do not error on unsupported Octeon instructions\n")); + fprintf (stream, _("\ +-mocteon-useun generate Octeon unaligned load/store instructions\n\ +-mno-octeon-useun generate MIPS unaligned load/store instructions\n")); } enum dwarf2_format mips_dwarf2_format (void) { - if (mips_abi == N64_ABI) + if (HAVE_64BIT_SYMBOLS) { #ifdef TE_IRIX return dwarf2_format_64bit_irix; @@ -14447,8 +14822,16 @@ mips_dwarf2_format (void) int mips_dwarf2_addr_size (void) { - if (mips_abi == N64_ABI) + if (HAVE_64BIT_SYMBOLS) return 8; else return 4; } + +/* Standard calling conventions leave the CFA at SP on entry. */ +void +mips_cfi_frame_initial_instructions (void) +{ + cfi_add_CFA_def_cfa_register (SP); +} + diff --git a/contrib/binutils/gas/config/tc-mips.h b/contrib/binutils/gas/config/tc-mips.h index 46a765369a16..0621b2eaf498 100644 --- a/contrib/binutils/gas/config/tc-mips.h +++ b/contrib/binutils/gas/config/tc-mips.h @@ -89,15 +89,6 @@ enum mips_pic_level extern enum mips_pic_level mips_pic; -struct mips_cl_insn -{ - unsigned long insn_opcode; - const struct mips_opcode *insn_mo; - /* The next two fields are used when generating mips16 code. */ - bfd_boolean use_extend; - unsigned short extend; -}; - extern int tc_get_register (int frame); #define md_after_parse_args() mips_after_parse_args() @@ -143,15 +134,6 @@ extern int mips_force_relocation (struct fix *); #define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEG) \ (! SEG_NORMAL (SEG) || mips_force_relocation (FIX)) -/* We use this to turn branches to global symbols into branches to - local symbols, so that they can be simplified. */ -#define TC_VALIDATE_FIX(fixp, this_segment, skip_label) \ - do \ - if (! mips_validate_fix ((fixp), (this_segment))) \ - goto skip_label; \ - while (0) -extern int mips_validate_fix (struct fix *, asection *); - /* Register mask variables. These are set by the MIPS assembly code and used by ECOFF and possibly other object file formats. */ extern unsigned long mips_gprmask; @@ -174,8 +156,8 @@ extern void md_mips_end (void); extern void mips_pop_insert (void); #define md_pop_insert() mips_pop_insert() -extern void mips_flush_pending_output (void); -#define md_flush_pending_output mips_flush_pending_output +extern void mips_emit_delays (void); +#define md_flush_pending_output mips_emit_delays extern void mips_enable_auto_align (void); #define md_elf_section_change_hook() mips_enable_auto_align() diff --git a/contrib/binutils/include/elf/mips.h b/contrib/binutils/include/elf/mips.h index ce43158123fd..3454aac1e482 100644 --- a/contrib/binutils/include/elf/mips.h +++ b/contrib/binutils/include/elf/mips.h @@ -1,5 +1,6 @@ /* MIPS ELF support for BFD. - Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003 + Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, + 2003, 2004, 2005 Free Software Foundation, Inc. By Ian Lance Taylor, Cygnus Support, , from @@ -20,7 +21,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* This file holds definitions specific to the MIPS ELF ABI. Note that most of this is not actually implemented by BFD. */ @@ -187,8 +188,10 @@ END_RELOC_NUMBERS (R_MIPS_maxext) #define E_MIPS_MACH_4120 0x00870000 #define E_MIPS_MACH_4111 0x00880000 #define E_MIPS_MACH_SB1 0x008a0000 +#define E_MIPS_MACH_OCTEON 0x008b0000 #define E_MIPS_MACH_5400 0x00910000 #define E_MIPS_MACH_5500 0x00980000 +#define E_MIPS_MACH_9000 0x00990000 /* Processor specific section indices. These sections do not actually exist. Symbols with a st_shndx field corresponding to one of these diff --git a/contrib/binutils/include/opcode/mips.h b/contrib/binutils/include/opcode/mips.h index 5c3ddfcd7b5e..15448542a698 100644 --- a/contrib/binutils/include/opcode/mips.h +++ b/contrib/binutils/include/opcode/mips.h @@ -1,5 +1,6 @@ /* mips.h. Mips opcode list for GDB, the GNU debugger. - Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 + Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, + 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Ralph Campbell and OSF Commented and modified by Ian Lance Taylor, Cygnus Support @@ -18,7 +19,7 @@ the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this file; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _MIPS_H_ #define _MIPS_H_ @@ -89,6 +90,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * #define OP_SH_CODE20 6 #define OP_MASK_SHAMT 0x1f #define OP_SH_SHAMT 6 +#define OP_MASK_BITIND OP_MASK_RT +#define OP_SH_BITIND OP_SH_RT #define OP_MASK_FD 0x1f #define OP_SH_FD 6 #define OP_MASK_TARGET 0x3ffffff @@ -147,6 +150,38 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * #define OP_MASK_EXTMSBD 0x1f /* "ext" MSBD. */ #define OP_SH_EXTMSBD 11 +/* MIPS DSP ASE */ +#define OP_SH_DSPACC 11 +#define OP_MASK_DSPACC 0x3 +#define OP_SH_DSPACC_S 21 +#define OP_MASK_DSPACC_S 0x3 +#define OP_SH_DSPSFT 20 +#define OP_MASK_DSPSFT 0x3f +#define OP_SH_DSPSFT_7 19 +#define OP_MASK_DSPSFT_7 0x7f +#define OP_SH_SA3 21 +#define OP_MASK_SA3 0x7 +#define OP_SH_SA4 21 +#define OP_MASK_SA4 0xf +#define OP_SH_IMM8 16 +#define OP_MASK_IMM8 0xff +#define OP_SH_IMM10 16 +#define OP_MASK_IMM10 0x3ff +#define OP_SH_WRDSP 11 +#define OP_MASK_WRDSP 0x3f +#define OP_SH_RDDSP 16 +#define OP_MASK_RDDSP 0x3f + +/* MIPS MT ASE */ +#define OP_SH_MT_U 5 +#define OP_MASK_MT_U 0x1 +#define OP_SH_MT_H 4 +#define OP_MASK_MT_H 0x1 +#define OP_SH_MTACC_T 18 +#define OP_MASK_MTACC_T 0x3 +#define OP_SH_MTACC_D 13 +#define OP_MASK_MTACC_D 0x3 + #define OP_OP_COP0 0x10 #define OP_OP_COP1 0x11 #define OP_OP_COP2 0x12 @@ -192,6 +227,8 @@ struct mips_opcode of bits describing the instruction, notably any relevant hazard information. */ unsigned long pinfo; + /* A collection of additional bits describing the instruction. */ + unsigned long pinfo2; /* A collection of bits describing the instruction sets of which this instruction or macro is a member. */ unsigned long membership; @@ -207,6 +244,8 @@ struct mips_opcode "<" 5 bit shift amount (OP_*_SHAMT) ">" shift amount between 32 and 63, stored after subtracting 32 (OP_*_SHAMT) + "^" 5 bit bit index amount (OP_*_BITIND) + "~" bit index between 32 and 63, stored after subtracting 32 (OP_*_BITIND) "a" 26 bit target address (OP_*_TARGET) "b" 5 bit base register (OP_*_RS) "c" 10 bit breakpoint code (OP_*_CODE) @@ -231,6 +270,7 @@ struct mips_opcode "B" 20 bit syscall/breakpoint function code (OP_*_CODE20) "J" 19 bit wait function code (OP_*_CODE19) "x" accept and ignore register name + "y" 10 bit signed const (OP_*_CODE2) "z" must be zero register "K" 5 bit Hardware Register (rdhwr instruction) (OP_*_RD) "+A" 5 bit ins/ext position, which becomes LSB (OP_*_SHAMT). @@ -293,6 +333,28 @@ struct mips_opcode "Y" MDMX source register (OP_*_FS) "Z" MDMX source register (OP_*_FT) + DSP ASE usage: + "3" 3 bit unsigned immediate (OP_*_SA3) + "4" 4 bit unsigned immediate (OP_*_SA4) + "5" 8 bit unsigned immediate (OP_*_IMM8) + "6" 5 bit unsigned immediate (OP_*_RS) + "7" 2 bit dsp accumulator register (OP_*_DSPACC) + "8" 6 bit unsigned immediate (OP_*_WRDSP) + "9" 2 bit dsp accumulator register (OP_*_DSPACC_S) + "0" 6 bit signed immediate (OP_*_DSPSFT) + ":" 7 bit signed immediate (OP_*_DSPSFT_7) + "'" 6 bit unsigned immediate (OP_*_RDDSP) + "@" 10 bit signed immediate (OP_*_IMM10) + + MT ASE usage: + "!" 1 bit immediate at bit 5 + "$" 1 bit immediate at bit 4 + "*" 2 bit dsp/smartmips accumulator register (OP_*_MTACC_T) + "&" 2 bit dsp/smartmips accumulator register (OP_*_MTACC_D) + "g" 5 bit coprocessor 1 and 2 destination register (OP_*_RD) + "+t" 5 bit coprocessor 0 destination register (OP_*_RT) + "+T" 5 bit coprocessor 0 destination register (OP_*_RT) - disassembly only + Other: "()" parens surrounding optional value "," separates operands @@ -300,13 +362,15 @@ struct mips_opcode "+" Start of extension sequence. Characters used so far, for quick reference when adding more: - "%[]<>(),+" + "34567890" + "%[]<>(),+:'@!$*&^~" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefhijklopqrstuvwxz" + "abcdefghijklopqrstuvwxyz" Extension character sequences used so far ("+" followed by the following), for quick reference when adding more: - "ABCDEFGHI" + "ABCDEFGHIT" + "t" */ /* These are the bits which may be set in the pinfo field of an @@ -376,10 +440,16 @@ struct mips_opcode #define INSN_MULT 0x40000000 /* Instruction synchronize shared memory. */ #define INSN_SYNC 0x80000000 -/* Instruction reads MDMX accumulator. XXX FIXME: No bits left! */ -#define INSN_READ_MDMX_ACC 0 -/* Instruction writes MDMX accumulator. XXX FIXME: No bits left! */ -#define INSN_WRITE_MDMX_ACC 0 + +/* These are the bits which may be set in the pinfo2 field of an + instruction. */ + +/* Instruction is a simple alias (I.E. "move" for daddu/addu/or) */ +#define INSN2_ALIAS 0x00000001 +/* Instruction reads MDMX accumulator. */ +#define INSN2_READ_MDMX_ACC 0x00000002 +/* Instruction writes MDMX accumulator. */ +#define INSN2_WRITE_MDMX_ACC 0x00000004 /* Instruction is actually a macro. It should be ignored by the disassembler, and requires special treatment by the assembler. */ @@ -402,8 +472,10 @@ struct mips_opcode #define INSN_ISA64R2 0x00000100 /* Masks used for MIPS-defined ASEs. */ -#define INSN_ASE_MASK 0x0000f000 +#define INSN_ASE_MASK 0x0400f000 +/* DSP ASE */ +#define INSN_DSP 0x00001000 /* MIPS 16 ASE */ #define INSN_MIPS16 0x00002000 /* MIPS-3D ASE */ @@ -433,6 +505,10 @@ struct mips_opcode #define INSN_5400 0x01000000 /* NEC VR5500 instruction. */ #define INSN_5500 0x02000000 +/* MT ASE */ +#define INSN_MT 0x04000000 +/* Cavium Networks Octeon instruction. */ +#define INSN_OCTEON 0x08000000 /* MIPS ISA defines, use instead of hardcoding ISA level. */ @@ -470,6 +546,7 @@ struct mips_opcode #define CPU_R6000 6000 #define CPU_RM7000 7000 #define CPU_R8000 8000 +#define CPU_RM9000 9000 #define CPU_R10000 10000 #define CPU_R12000 12000 #define CPU_MIPS16 16 @@ -479,6 +556,7 @@ struct mips_opcode #define CPU_MIPS64 64 #define CPU_MIPS64R2 65 #define CPU_SB1 12310201 /* octal 'SB', 01. */ +#define CPU_OCTEON 6502 /* Test for membership in an ISA including chip specific ISAs. INSN is pointer to an element of the opcode table; ISA is the specified @@ -489,12 +567,14 @@ struct mips_opcode (((insn)->membership & isa) != 0 \ || (cpu == CPU_R4650 && ((insn)->membership & INSN_4650) != 0) \ || (cpu == CPU_RM7000 && ((insn)->membership & INSN_4650) != 0) \ + || (cpu == CPU_RM9000 && ((insn)->membership & INSN_4650) != 0) \ || (cpu == CPU_R4010 && ((insn)->membership & INSN_4010) != 0) \ || (cpu == CPU_VR4100 && ((insn)->membership & INSN_4100) != 0) \ || (cpu == CPU_R3900 && ((insn)->membership & INSN_3900) != 0) \ || ((cpu == CPU_R10000 || cpu == CPU_R12000) \ && ((insn)->membership & INSN_10000) != 0) \ || (cpu == CPU_SB1 && ((insn)->membership & INSN_SB1) != 0) \ + || (cpu == CPU_OCTEON && ((insn)->membership & INSN_OCTEON) != 0) \ || (cpu == CPU_R4111 && ((insn)->membership & INSN_4111) != 0) \ || (cpu == CPU_VR4120 && ((insn)->membership & INSN_4120) != 0) \ || (cpu == CPU_VR5400 && ((insn)->membership & INSN_5400) != 0) \ @@ -654,6 +734,8 @@ enum M_S_DOB, M_S_DAB, M_S_S, + M_SAA_AB, + M_SAAD_AB, M_SC_AB, M_SCD_AB, M_SD_A, @@ -857,7 +939,14 @@ extern int bfd_mips_num_opcodes; "A" 8 bit PC relative address * 4 (MIPS16OP_*_IMM8) "B" 5 bit PC relative address * 8 (MIPS16OP_*_IMM5) "E" 5 bit PC relative address * 4 (MIPS16OP_*_IMM5) - */ + "m" 7 bit register list for save instruction (18 bit extended) + "M" 7 bit register list for restore instruction (18 bit extended) + */ + +/* Save/restore encoding for the args field when all 4 registers are + either saved as arguments or saved/restored as statics. */ +#define MIPS16_ALL_ARGS 0xe +#define MIPS16_ALL_STATICS 0xb /* For the mips16, we use the same opcode table format and a few of the same flags. However, most of the flags are different. */ diff --git a/contrib/binutils/opcodes/mips-dis.c b/contrib/binutils/opcodes/mips-dis.c index 43fcb3ca79a2..dab4db99331e 100644 --- a/contrib/binutils/opcodes/mips-dis.c +++ b/contrib/binutils/opcodes/mips-dis.c @@ -1,24 +1,25 @@ /* Print mips instructions for GDB, the GNU debugger, or for objdump. Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003 + 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc. Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp). -This file is part of GDB, GAS, and the GNU binutils. + This file is part of GDB, GAS, and the GNU binutils. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ #include "sysdep.h" #include "dis-asm.h" @@ -40,96 +41,95 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Mips instructions are at maximum this many bytes long. */ #define INSNLEN 4 -static void set_default_mips_dis_options - PARAMS ((struct disassemble_info *)); -static void parse_mips_dis_option - PARAMS ((const char *, unsigned int)); -static void parse_mips_dis_options - PARAMS ((const char *)); -static int _print_insn_mips - PARAMS ((bfd_vma, struct disassemble_info *, enum bfd_endian)); -static int print_insn_mips - PARAMS ((bfd_vma, unsigned long int, struct disassemble_info *)); -static void print_insn_args - PARAMS ((const char *, unsigned long, bfd_vma, struct disassemble_info *)); -static int print_insn_mips16 - PARAMS ((bfd_vma, struct disassemble_info *)); -static int is_newabi - PARAMS ((Elf_Internal_Ehdr *)); -static void print_mips16_insn_arg - PARAMS ((int, const struct mips_opcode *, int, bfd_boolean, int, bfd_vma, - struct disassemble_info *)); +/* Generate Octeon/MIPS unaligned load and store instructions. */ +#ifdef INCLUDE_OCTEON_USEUN +int octeon_use_unalign = 1; +#else +int octeon_use_unalign = 0; +#endif + /* FIXME: These should be shared with gdb somehow. */ -struct mips_cp0sel_name { - unsigned int cp0reg; - unsigned int sel; - const char * const name; +struct mips_cp0sel_name +{ + unsigned int cp0reg; + unsigned int sel; + const char * const name; }; /* The mips16 register names. */ -static const char * const mips16_reg_names[] = { +static const char * const mips16_reg_names[] = +{ "s0", "s1", "v0", "v1", "a0", "a1", "a2", "a3" }; -static const char * const mips_gpr_names_numeric[32] = { +static const char * const mips_gpr_names_numeric[32] = +{ "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31" }; -static const char * const mips_gpr_names_oldabi[32] = { +static const char * const mips_gpr_names_oldabi[32] = +{ "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra" }; -static const char * const mips_gpr_names_newabi[32] = { +static const char * const mips_gpr_names_newabi[32] = +{ "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra" }; -static const char * const mips_fpr_names_numeric[32] = { +static const char * const mips_fpr_names_numeric[32] = +{ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31" }; -static const char * const mips_fpr_names_32[32] = { +static const char * const mips_fpr_names_32[32] = +{ "fv0", "fv0f", "fv1", "fv1f", "ft0", "ft0f", "ft1", "ft1f", "ft2", "ft2f", "ft3", "ft3f", "fa0", "fa0f", "fa1", "fa1f", "ft4", "ft4f", "ft5", "ft5f", "fs0", "fs0f", "fs1", "fs1f", "fs2", "fs2f", "fs3", "fs3f", "fs4", "fs4f", "fs5", "fs5f" }; -static const char * const mips_fpr_names_n32[32] = { +static const char * const mips_fpr_names_n32[32] = +{ "fv0", "ft14", "fv1", "ft15", "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", "fa6", "fa7", "fs0", "ft8", "fs1", "ft9", "fs2", "ft10", "fs3", "ft11", "fs4", "ft12", "fs5", "ft13" }; -static const char * const mips_fpr_names_64[32] = { +static const char * const mips_fpr_names_64[32] = +{ "fv0", "ft12", "fv1", "ft13", "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", "fa6", "fa7", "ft8", "ft9", "ft10", "ft11", "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7" }; -static const char * const mips_cp0_names_numeric[32] = { +static const char * const mips_cp0_names_numeric[32] = +{ "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31" }; -static const char * const mips_cp0_names_mips3264[32] = { +static const char * const mips_cp0_names_mips3264[32] = +{ "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1", "c0_context", "c0_pagemask", "c0_wired", "$7", "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare", @@ -140,7 +140,8 @@ static const char * const mips_cp0_names_mips3264[32] = { "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave", }; -static const struct mips_cp0sel_name mips_cp0sel_names_mips3264[] = { +static const struct mips_cp0sel_name mips_cp0sel_names_mips3264[] = +{ { 16, 1, "c0_config1" }, { 16, 2, "c0_config2" }, { 16, 3, "c0_config3" }, @@ -172,7 +173,8 @@ static const struct mips_cp0sel_name mips_cp0sel_names_mips3264[] = { { 29, 1, "c0_datahi" } }; -static const char * const mips_cp0_names_mips3264r2[32] = { +static const char * const mips_cp0_names_mips3264r2[32] = +{ "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1", "c0_context", "c0_pagemask", "c0_wired", "c0_hwrena", "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare", @@ -183,7 +185,8 @@ static const char * const mips_cp0_names_mips3264r2[32] = { "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave", }; -static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2[] = { +static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2[] = +{ { 4, 1, "c0_contextconfig" }, { 5, 1, "c0_pagegrain" }, { 12, 1, "c0_intctl" }, @@ -238,7 +241,8 @@ static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2[] = { }; /* SB-1: MIPS64 (mips_cp0_names_mips3264) with minor mods. */ -static const char * const mips_cp0_names_sb1[32] = { +static const char * const mips_cp0_names_sb1[32] = +{ "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1", "c0_context", "c0_pagemask", "c0_wired", "$7", "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare", @@ -249,7 +253,8 @@ static const char * const mips_cp0_names_sb1[32] = { "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave", }; -static const struct mips_cp0sel_name mips_cp0sel_names_sb1[] = { +static const struct mips_cp0sel_name mips_cp0sel_names_sb1[] = +{ { 16, 1, "c0_config1" }, { 18, 1, "c0_watchlo,1" }, { 19, 1, "c0_watchhi,1" }, @@ -273,14 +278,46 @@ static const struct mips_cp0sel_name mips_cp0sel_names_sb1[] = { { 29, 3, "c0_datahi_d" }, }; -static const char * const mips_hwr_names_numeric[32] = { +static const char * const mips_cp0_names_octeon[32] = { + "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1", + "c0_context", "c0_pagemask", "c0_wired", "c0_hwrena", + "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare", + "c0_status", "c0_cause", "c0_epc", "c0_prid", + "c0_config", "$17", "c0_watchlo", "c0_watchhi", + "c0_xcontext", "$21", "c0_mdebug", "c0_debug", + "c0_depc", "c0_perfcnt", "$26", "c0_cacheerr", + "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave", +}; + +static const struct mips_cp0sel_name mips_cp0sel_names_octeon[] = { + { 5, 1, "c0_pagegrain" }, + { 9, 6, "c0_cvmcount" }, + { 9, 7, "c0_cvmctl" }, + { 11, 7, "c0_cvmmemctl" }, + { 12, 1, "c0_intctl" }, + { 12, 2, "c0_srsctl" }, + { 15, 1, "c0_ebase" }, + { 16, 1, "c0_config1", }, + { 16, 2, "c0_config2", }, + { 16, 3, "c0_config3", }, + { 18, 1, "c0_watchlo,1" }, + { 19, 1, "c0_watchhi,1" }, + { 25, 2, "c0_perfcnt,2" }, + { 27, 1, "c0_cacheerr,1" }, + { 28, 3, "c0_datalo" }, + { 29, 3, "c0_datahi" }, +}; + +static const char * const mips_hwr_names_numeric[32] = +{ "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31" }; -static const char * const mips_hwr_names_mips3264r2[32] = { +static const char * const mips_hwr_names_mips3264r2[32] = +{ "hwr_cpunum", "hwr_synci_step", "hwr_cc", "hwr_ccres", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", @@ -288,20 +325,23 @@ static const char * const mips_hwr_names_mips3264r2[32] = { "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31" }; -struct mips_abi_choice { - const char *name; +struct mips_abi_choice +{ + const char * name; const char * const *gpr_names; const char * const *fpr_names; }; -struct mips_abi_choice mips_abi_choices[] = { +struct mips_abi_choice mips_abi_choices[] = +{ { "numeric", mips_gpr_names_numeric, mips_fpr_names_numeric }, { "32", mips_gpr_names_oldabi, mips_fpr_names_32 }, { "n32", mips_gpr_names_newabi, mips_fpr_names_n32 }, { "64", mips_gpr_names_newabi, mips_fpr_names_64 }, }; -struct mips_arch_choice { +struct mips_arch_choice +{ const char *name; int bfd_mach_valid; unsigned long bfd_mach; @@ -313,7 +353,8 @@ struct mips_arch_choice { const char * const *hwr_names; }; -const struct mips_arch_choice mips_arch_choices[] = { +const struct mips_arch_choice mips_arch_choices[] = +{ { "numeric", 0, 0, 0, 0, mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, @@ -366,26 +407,26 @@ const struct mips_arch_choice mips_arch_choices[] = { MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95), page 1. */ { "mips32", 1, bfd_mach_mipsisa32, CPU_MIPS32, - ISA_MIPS32 | INSN_MIPS16, + ISA_MIPS32 | INSN_MIPS16 | INSN_DSP, mips_cp0_names_mips3264, mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264), mips_hwr_names_numeric }, { "mips32r2", 1, bfd_mach_mipsisa32r2, CPU_MIPS32R2, - ISA_MIPS32R2 | INSN_MIPS16, + ISA_MIPS32R2 | INSN_MIPS16 | INSN_DSP | INSN_MT, mips_cp0_names_mips3264r2, mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2), mips_hwr_names_mips3264r2 }, /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs. */ { "mips64", 1, bfd_mach_mipsisa64, CPU_MIPS64, - ISA_MIPS64 | INSN_MIPS16 | INSN_MIPS3D | INSN_MDMX, + ISA_MIPS64 | INSN_MIPS16 | INSN_MIPS3D | INSN_MDMX | INSN_DSP, mips_cp0_names_mips3264, mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264), mips_hwr_names_numeric }, { "mips64r2", 1, bfd_mach_mipsisa64r2, CPU_MIPS64R2, - ISA_MIPS64R2 | INSN_MIPS16 | INSN_MIPS3D | INSN_MDMX, + ISA_MIPS64R2 | INSN_MIPS16 | INSN_MIPS3D | INSN_MDMX | INSN_DSP, mips_cp0_names_mips3264r2, mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2), mips_hwr_names_mips3264r2 }, @@ -396,6 +437,11 @@ const struct mips_arch_choice mips_arch_choices[] = { mips_cp0sel_names_sb1, ARRAY_SIZE (mips_cp0sel_names_sb1), mips_hwr_names_numeric }, + { "octeon", 1, bfd_mach_mips_octeon, CPU_OCTEON, + ISA_MIPS64R2 | INSN_OCTEON, mips_cp0_names_octeon, + mips_cp0sel_names_octeon, ARRAY_SIZE (mips_cp0sel_names_octeon), + mips_hwr_names_numeric }, + /* This entry, mips16, is here only for ISA/processor selection; do not print its name. */ { "", 1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS3 | INSN_MIPS16, @@ -414,53 +460,39 @@ static const struct mips_cp0sel_name *mips_cp0sel_names; static int mips_cp0sel_names_len; static const char * const *mips_hwr_names; -static const struct mips_abi_choice *choose_abi_by_name - PARAMS ((const char *, unsigned int)); -static const struct mips_arch_choice *choose_arch_by_name - PARAMS ((const char *, unsigned int)); -static const struct mips_arch_choice *choose_arch_by_number - PARAMS ((unsigned long)); -static const struct mips_cp0sel_name *lookup_mips_cp0sel_name - PARAMS ((const struct mips_cp0sel_name *, unsigned int, unsigned int, - unsigned int)); +/* Other options */ +static int no_aliases; /* If set disassemble as most general inst. */ static const struct mips_abi_choice * -choose_abi_by_name (name, namelen) - const char *name; - unsigned int namelen; +choose_abi_by_name (const char *name, unsigned int namelen) { const struct mips_abi_choice *c; unsigned int i; for (i = 0, c = NULL; i < ARRAY_SIZE (mips_abi_choices) && c == NULL; i++) - { - if (strncmp (mips_abi_choices[i].name, name, namelen) == 0 - && strlen (mips_abi_choices[i].name) == namelen) - c = &mips_abi_choices[i]; - } + if (strncmp (mips_abi_choices[i].name, name, namelen) == 0 + && strlen (mips_abi_choices[i].name) == namelen) + c = &mips_abi_choices[i]; + return c; } static const struct mips_arch_choice * -choose_arch_by_name (name, namelen) - const char *name; - unsigned int namelen; +choose_arch_by_name (const char *name, unsigned int namelen) { const struct mips_arch_choice *c = NULL; unsigned int i; for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++) - { - if (strncmp (mips_arch_choices[i].name, name, namelen) == 0 - && strlen (mips_arch_choices[i].name) == namelen) - c = &mips_arch_choices[i]; - } + if (strncmp (mips_arch_choices[i].name, name, namelen) == 0 + && strlen (mips_arch_choices[i].name) == namelen) + c = &mips_arch_choices[i]; + return c; } static const struct mips_arch_choice * -choose_arch_by_number (mach) - unsigned long mach; +choose_arch_by_number (unsigned long mach) { static unsigned long hint_bfd_mach; static const struct mips_arch_choice *hint_arch_choice; @@ -487,9 +519,24 @@ choose_arch_by_number (mach) return c; } -void -set_default_mips_dis_options (info) - struct disassemble_info *info; +/* Check if the object uses NewABI conventions. */ + +static int +is_newabi (Elf_Internal_Ehdr *header) +{ + /* There are no old-style ABIs which use 64-bit ELF. */ + if (header->e_ident[EI_CLASS] == ELFCLASS64) + return 1; + + /* If a 32-bit ELF file, n32 is a new-style ABI. */ + if ((header->e_flags & EF_MIPS_ABI2) != 0) + return 1; + + return 0; +} + +static void +set_default_mips_dis_options (struct disassemble_info *info) { const struct mips_arch_choice *chosen_arch; @@ -503,6 +550,7 @@ set_default_mips_dis_options (info) mips_cp0sel_names = NULL; mips_cp0sel_names_len = 0; mips_hwr_names = mips_hwr_names_numeric; + no_aliases = 0; /* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */ if (info->flavour == bfd_target_elf_flavour && info->section != NULL) @@ -534,22 +582,37 @@ set_default_mips_dis_options (info) #endif } -void -parse_mips_dis_option (option, len) - const char *option; - unsigned int len; +static void +parse_mips_dis_option (const char *option, unsigned int len) { unsigned int i, optionlen, vallen; const char *val; const struct mips_abi_choice *chosen_abi; const struct mips_arch_choice *chosen_arch; + if (strcmp ("octeon-useun", option) == 0) + { + octeon_use_unalign = 1; + return; + } + if (strcmp ("no-octeon-useun", option) == 0) + { + octeon_use_unalign = 0; + return; + } + + /* Try to match options that are simple flags */ + if (strncmp (option, "no-aliases", 10) == 0) + { + no_aliases = 1; + return; + } + /* Look for the = that delimits the end of the option name. */ for (i = 0; i < len; i++) - { - if (option[i] == '=') - break; - } + if (option[i] == '=') + break; + if (i == 0) /* Invalid option: no name before '='. */ return; if (i == len) /* Invalid option: no '='. */ @@ -561,8 +624,8 @@ parse_mips_dis_option (option, len) val = option + (optionlen + 1); vallen = len - (optionlen + 1); - if (strncmp("gpr-names", option, optionlen) == 0 - && strlen("gpr-names") == optionlen) + if (strncmp ("gpr-names", option, optionlen) == 0 + && strlen ("gpr-names") == optionlen) { chosen_abi = choose_abi_by_name (val, vallen); if (chosen_abi != NULL) @@ -570,8 +633,8 @@ parse_mips_dis_option (option, len) return; } - if (strncmp("fpr-names", option, optionlen) == 0 - && strlen("fpr-names") == optionlen) + if (strncmp ("fpr-names", option, optionlen) == 0 + && strlen ("fpr-names") == optionlen) { chosen_abi = choose_abi_by_name (val, vallen); if (chosen_abi != NULL) @@ -579,8 +642,8 @@ parse_mips_dis_option (option, len) return; } - if (strncmp("cp0-names", option, optionlen) == 0 - && strlen("cp0-names") == optionlen) + if (strncmp ("cp0-names", option, optionlen) == 0 + && strlen ("cp0-names") == optionlen) { chosen_arch = choose_arch_by_name (val, vallen); if (chosen_arch != NULL) @@ -592,8 +655,8 @@ parse_mips_dis_option (option, len) return; } - if (strncmp("hwr-names", option, optionlen) == 0 - && strlen("hwr-names") == optionlen) + if (strncmp ("hwr-names", option, optionlen) == 0 + && strlen ("hwr-names") == optionlen) { chosen_arch = choose_arch_by_name (val, vallen); if (chosen_arch != NULL) @@ -601,8 +664,8 @@ parse_mips_dis_option (option, len) return; } - if (strncmp("reg-names", option, optionlen) == 0 - && strlen("reg-names") == optionlen) + if (strncmp ("reg-names", option, optionlen) == 0 + && strlen ("reg-names") == optionlen) { /* We check both ABI and ARCH here unconditionally, so that "numeric" will do the desirable thing: select @@ -628,9 +691,8 @@ parse_mips_dis_option (option, len) /* Invalid option. */ } -void -parse_mips_dis_options (options) - const char *options; +static void +parse_mips_dis_options (const char *options) { const char *option_end; @@ -660,9 +722,10 @@ parse_mips_dis_options (options) } static const struct mips_cp0sel_name * -lookup_mips_cp0sel_name(names, len, cp0reg, sel) - const struct mips_cp0sel_name *names; - unsigned int len, cp0reg, sel; +lookup_mips_cp0sel_name (const struct mips_cp0sel_name *names, + unsigned int len, + unsigned int cp0reg, + unsigned int sel) { unsigned int i; @@ -675,11 +738,10 @@ lookup_mips_cp0sel_name(names, len, cp0reg, sel) /* Print insn arguments for 32/64-bit code. */ static void -print_insn_args (d, l, pc, info) - const char *d; - register unsigned long int l; - bfd_vma pc; - struct disassemble_info *info; +print_insn_args (const char *d, + register unsigned long int l, + bfd_vma pc, + struct disassemble_info *info) { int op, delta; unsigned int lsb, msb, msbd; @@ -762,6 +824,34 @@ print_insn_args (d, l, pc, info) (*info->fprintf_func) (info->stream, "0x%x", msbd + 1); break; + case 't': /* Coprocessor 0 reg name */ + (*info->fprintf_func) (info->stream, "%s", + mips_cp0_names[(l >> OP_SH_RT) & + OP_MASK_RT]); + break; + + case 'T': /* Coprocessor 0 reg name */ + { + const struct mips_cp0sel_name *n; + unsigned int cp0reg, sel; + + cp0reg = (l >> OP_SH_RT) & OP_MASK_RT; + sel = (l >> OP_SH_SEL) & OP_MASK_SEL; + + /* CP0 register including 'sel' code for mftc0, to be + printed textually if known. If not known, print both + CP0 register name and sel numerically since CP0 register + with sel 0 may have a name unrelated to register being + printed. */ + n = lookup_mips_cp0sel_name(mips_cp0sel_names, + mips_cp0sel_names_len, cp0reg, sel); + if (n != NULL) + (*info->fprintf_func) (info->stream, "%s", n->name); + else + (*info->fprintf_func) (info->stream, "$%d,%d", cp0reg, sel); + break; + } + default: /* xgettext:c-format */ (*info->fprintf_func) (info->stream, @@ -771,6 +861,93 @@ print_insn_args (d, l, pc, info) } break; + case '3': + (*info->fprintf_func) (info->stream, "0x%lx", + (l >> OP_SH_SA3) & OP_MASK_SA3); + break; + + case '4': + (*info->fprintf_func) (info->stream, "0x%lx", + (l >> OP_SH_SA4) & OP_MASK_SA4); + break; + + case '5': + (*info->fprintf_func) (info->stream, "0x%lx", + (l >> OP_SH_IMM8) & OP_MASK_IMM8); + break; + + case '6': + (*info->fprintf_func) (info->stream, "0x%lx", + (l >> OP_SH_RS) & OP_MASK_RS); + break; + + case '7': + (*info->fprintf_func) (info->stream, "$ac%ld", + (l >> OP_SH_DSPACC) & OP_MASK_DSPACC); + break; + + case '8': + (*info->fprintf_func) (info->stream, "0x%lx", + (l >> OP_SH_WRDSP) & OP_MASK_WRDSP); + break; + + case '9': + (*info->fprintf_func) (info->stream, "$ac%ld", + (l >> OP_SH_DSPACC_S) & OP_MASK_DSPACC_S); + break; + + case '0': /* dsp 6-bit signed immediate in bit 20 */ + delta = ((l >> OP_SH_DSPSFT) & OP_MASK_DSPSFT); + if (delta & 0x20) /* test sign bit */ + delta |= ~OP_MASK_DSPSFT; + (*info->fprintf_func) (info->stream, "%d", delta); + break; + + case ':': /* dsp 7-bit signed immediate in bit 19 */ + delta = ((l >> OP_SH_DSPSFT_7) & OP_MASK_DSPSFT_7); + if (delta & 0x40) /* test sign bit */ + delta |= ~OP_MASK_DSPSFT_7; + (*info->fprintf_func) (info->stream, "%d", delta); + break; + + case '\'': + (*info->fprintf_func) (info->stream, "0x%lx", + (l >> OP_SH_RDDSP) & OP_MASK_RDDSP); + break; + + case '@': /* dsp 10-bit signed immediate in bit 16 */ + delta = ((l >> OP_SH_IMM10) & OP_MASK_IMM10); + if (delta & 0x200) /* test sign bit */ + delta |= ~OP_MASK_IMM10; + (*info->fprintf_func) (info->stream, "%d", delta); + break; + + case '!': + (*info->fprintf_func) (info->stream, "%ld", + (l >> OP_SH_MT_U) & OP_MASK_MT_U); + break; + + case '$': + (*info->fprintf_func) (info->stream, "%ld", + (l >> OP_SH_MT_H) & OP_MASK_MT_H); + break; + + case '*': + (*info->fprintf_func) (info->stream, "$ac%ld", + (l >> OP_SH_MTACC_T) & OP_MASK_MTACC_T); + break; + + case '&': + (*info->fprintf_func) (info->stream, "$ac%ld", + (l >> OP_SH_MTACC_D) & OP_MASK_MTACC_D); + break; + + case 'g': + /* Coprocessor register for CTTC1, MTTC2, MTHC2, CTTC2. */ + (*info->fprintf_func) (info->stream, "$%ld", + (l >> OP_SH_RD) & OP_MASK_RD); + break; + case 's': case 'b': case 'r': @@ -787,7 +964,7 @@ print_insn_args (d, l, pc, info) case 'i': case 'u': - (*info->fprintf_func) (info->stream, "0x%x", + (*info->fprintf_func) (info->stream, "0x%lx", (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE); break; @@ -861,32 +1038,49 @@ print_insn_args (d, l, pc, info) break; case '<': - (*info->fprintf_func) (info->stream, "0x%x", + (*info->fprintf_func) (info->stream, "0x%lx", (l >> OP_SH_SHAMT) & OP_MASK_SHAMT); break; case 'c': - (*info->fprintf_func) (info->stream, "0x%x", + (*info->fprintf_func) (info->stream, "0x%lx", (l >> OP_SH_CODE) & OP_MASK_CODE); break; case 'q': - (*info->fprintf_func) (info->stream, "0x%x", + (*info->fprintf_func) (info->stream, "0x%lx", (l >> OP_SH_CODE2) & OP_MASK_CODE2); break; + /* Display 5 bits of bbit0/1 bit index amount. */ + case '^': + (*info->fprintf_func) (info->stream, "0x%x", + (l >> OP_SH_BITIND) & OP_MASK_BITIND); + break; + + /* Display 10 bits signed constant from seqi/snei instruction. */ + case 'y': + { + int imm = (l >> OP_SH_CODE2) & OP_MASK_CODE2; + imm <<= 22; + imm >>= 22; + (*info->fprintf_func) (info->stream, "%d", imm); + } + break; + case 'C': - (*info->fprintf_func) (info->stream, "0x%x", + (*info->fprintf_func) (info->stream, "0x%lx", (l >> OP_SH_COPZ) & OP_MASK_COPZ); break; case 'B': - (*info->fprintf_func) (info->stream, "0x%x", + (*info->fprintf_func) (info->stream, "0x%lx", + (l >> OP_SH_CODE20) & OP_MASK_CODE20); break; case 'J': - (*info->fprintf_func) (info->stream, "0x%x", + (*info->fprintf_func) (info->stream, "0x%lx", (l >> OP_SH_CODE19) & OP_MASK_CODE19); break; @@ -920,7 +1114,7 @@ print_insn_args (d, l, pc, info) 'T' format. Therefore, until we gain understanding of cp2 register names, we can simply print the register numbers. */ - (*info->fprintf_func) (info->stream, "$%d", + (*info->fprintf_func) (info->stream, "$%ld", (l >> OP_SH_RT) & OP_MASK_RT); break; @@ -934,7 +1128,7 @@ print_insn_args (d, l, pc, info) (*info->fprintf_func) (info->stream, "%s", mips_cp0_names[(l >> OP_SH_RD) & OP_MASK_RD]); else - (*info->fprintf_func) (info->stream, "$%d", + (*info->fprintf_func) (info->stream, "$%ld", (l >> OP_SH_RD) & OP_MASK_RD); break; @@ -944,79 +1138,81 @@ print_insn_args (d, l, pc, info) break; case 'N': - (*info->fprintf_func) (info->stream, "$fcc%d", + (*info->fprintf_func) (info->stream, "$fcc%ld", (l >> OP_SH_BCC) & OP_MASK_BCC); break; case 'M': - (*info->fprintf_func) (info->stream, "$fcc%d", + (*info->fprintf_func) (info->stream, "$fcc%ld", (l >> OP_SH_CCC) & OP_MASK_CCC); break; case 'P': - (*info->fprintf_func) (info->stream, "%d", + (*info->fprintf_func) (info->stream, "%ld", (l >> OP_SH_PERFREG) & OP_MASK_PERFREG); break; case 'e': - (*info->fprintf_func) (info->stream, "%d", + (*info->fprintf_func) (info->stream, "%ld", (l >> OP_SH_VECBYTE) & OP_MASK_VECBYTE); break; case '%': - (*info->fprintf_func) (info->stream, "%d", + (*info->fprintf_func) (info->stream, "%ld", (l >> OP_SH_VECALIGN) & OP_MASK_VECALIGN); break; case 'H': - (*info->fprintf_func) (info->stream, "%d", + (*info->fprintf_func) (info->stream, "%ld", (l >> OP_SH_SEL) & OP_MASK_SEL); break; case 'O': - (*info->fprintf_func) (info->stream, "%d", + (*info->fprintf_func) (info->stream, "%ld", (l >> OP_SH_ALN) & OP_MASK_ALN); break; case 'Q': { unsigned int vsel = (l >> OP_SH_VSEL) & OP_MASK_VSEL; + if ((vsel & 0x10) == 0) { int fmt; + vsel &= 0x0f; for (fmt = 0; fmt < 3; fmt++, vsel >>= 1) if ((vsel & 1) == 0) break; - (*info->fprintf_func) (info->stream, "$v%d[%d]", + (*info->fprintf_func) (info->stream, "$v%ld[%d]", (l >> OP_SH_FT) & OP_MASK_FT, vsel >> 1); } else if ((vsel & 0x08) == 0) { - (*info->fprintf_func) (info->stream, "$v%d", + (*info->fprintf_func) (info->stream, "$v%ld", (l >> OP_SH_FT) & OP_MASK_FT); } else { - (*info->fprintf_func) (info->stream, "0x%x", + (*info->fprintf_func) (info->stream, "0x%lx", (l >> OP_SH_FT) & OP_MASK_FT); } } break; case 'X': - (*info->fprintf_func) (info->stream, "$v%d", + (*info->fprintf_func) (info->stream, "$v%ld", (l >> OP_SH_FD) & OP_MASK_FD); break; case 'Y': - (*info->fprintf_func) (info->stream, "$v%d", + (*info->fprintf_func) (info->stream, "$v%ld", (l >> OP_SH_FS) & OP_MASK_FS); break; case 'Z': - (*info->fprintf_func) (info->stream, "$v%d", + (*info->fprintf_func) (info->stream, "$v%ld", (l >> OP_SH_FT) & OP_MASK_FT); break; @@ -1030,35 +1226,17 @@ print_insn_args (d, l, pc, info) } } -/* Check if the object uses NewABI conventions. */ - -static int -is_newabi (header) - Elf_Internal_Ehdr *header; -{ - /* There are no old-style ABIs which use 64-bit ELF. */ - if (header->e_ident[EI_CLASS] == ELFCLASS64) - return 1; - - /* If a 32-bit ELF file, n32 is a new-style ABI. */ - if ((header->e_flags & EF_MIPS_ABI2) != 0) - return 1; - - return 0; -} - /* Print the mips instruction at address MEMADDR in debugged memory, on using INFO. Returns length of the instruction, in bytes, which is always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if this is little-endian code. */ static int -print_insn_mips (memaddr, word, info) - bfd_vma memaddr; - unsigned long int word; - struct disassemble_info *info; +print_insn_mips (bfd_vma memaddr, + unsigned long int word, + struct disassemble_info *info) { - register const struct mips_opcode *op; + const struct mips_opcode *op; static bfd_boolean init = 0; static const struct mips_opcode *mips_hash[OP_MASK_OP + 1]; @@ -1071,7 +1249,8 @@ print_insn_mips (memaddr, word, info) { for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++) { - if (op->pinfo == INSN_MACRO) + if (op->pinfo == INSN_MACRO + || (no_aliases && (op->pinfo2 & INSN2_ALIAS))) continue; if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP)) { @@ -1098,15 +1277,38 @@ print_insn_mips (memaddr, word, info) { for (; op < &mips_opcodes[NUMOPCODES]; op++) { - if (op->pinfo != INSN_MACRO && (word & op->mask) == op->match) + if (op->pinfo != INSN_MACRO + && !(no_aliases && (op->pinfo2 & INSN2_ALIAS)) + && (word & op->mask) == op->match) { - register const char *d; + const char *d; /* We always allow to disassemble the jalx instruction. */ if (! OPCODE_IS_MEMBER (op, mips_isa, mips_processor) && strcmp (op->name, "jalx")) continue; + if (info->mach == CPU_OCTEON && octeon_use_unalign) + { + if (strcmp (op->name, "lwl") == 0 + || strcmp (op->name, "ldl") == 0 + || strcmp (op->name, "swl") == 0 + || strcmp (op->name, "sdl") == 0 + || strcmp (op->name, "lcache") == 0 + || strcmp (op->name, "scache") == 0 + || strcmp (op->name, "flush") == 0) + continue; + + if (strcmp (op->name, "ldr") == 0 + || strcmp (op->name, "lwr") == 0 + || strcmp (op->name, "swr") == 0 + || strcmp (op->name, "sdr") == 0) + { + (*info->fprintf_func) (info->stream, "nop"); + return INSNLEN; + } + } + /* Figure out instruction type and branch delay information. */ if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0) { @@ -1145,246 +1347,20 @@ print_insn_mips (memaddr, word, info) /* Handle undefined instructions. */ info->insn_type = dis_noninsn; - (*info->fprintf_func) (info->stream, "0x%x", word); + (*info->fprintf_func) (info->stream, "0x%lx", word); return INSNLEN; } -/* In an environment where we do not know the symbol type of the - instruction we are forced to assume that the low order bit of the - instructions' address may mark it as a mips16 instruction. If we - are single stepping, or the pc is within the disassembled function, - this works. Otherwise, we need a clue. Sometimes. */ - -static int -_print_insn_mips (memaddr, info, endianness) - bfd_vma memaddr; - struct disassemble_info *info; - enum bfd_endian endianness; -{ - bfd_byte buffer[INSNLEN]; - int status; - - set_default_mips_dis_options (info); - parse_mips_dis_options (info->disassembler_options); - -#if 1 - /* FIXME: If odd address, this is CLEARLY a mips 16 instruction. */ - /* Only a few tools will work this way. */ - if (memaddr & 0x01) - return print_insn_mips16 (memaddr, info); -#endif - -#if SYMTAB_AVAILABLE - if (info->mach == bfd_mach_mips16 - || (info->flavour == bfd_target_elf_flavour - && info->symbols != NULL - && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other - == STO_MIPS16))) - return print_insn_mips16 (memaddr, info); -#endif - - status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info); - if (status == 0) - { - unsigned long insn; - - if (endianness == BFD_ENDIAN_BIG) - insn = (unsigned long) bfd_getb32 (buffer); - else - insn = (unsigned long) bfd_getl32 (buffer); - - return print_insn_mips (memaddr, insn, info); - } - else - { - (*info->memory_error_func) (status, memaddr, info); - return -1; - } -} - -int -print_insn_big_mips (memaddr, info) - bfd_vma memaddr; - struct disassemble_info *info; -{ - return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG); -} - -int -print_insn_little_mips (memaddr, info) - bfd_vma memaddr; - struct disassemble_info *info; -{ - return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE); -} - -/* Disassemble mips16 instructions. */ - -static int -print_insn_mips16 (memaddr, info) - bfd_vma memaddr; - struct disassemble_info *info; -{ - int status; - bfd_byte buffer[2]; - int length; - int insn; - bfd_boolean use_extend; - int extend = 0; - const struct mips_opcode *op, *opend; - - info->bytes_per_chunk = 2; - info->display_endian = info->endian; - info->insn_info_valid = 1; - info->branch_delay_insns = 0; - info->data_size = 0; - info->insn_type = dis_nonbranch; - info->target = 0; - info->target2 = 0; - - status = (*info->read_memory_func) (memaddr, buffer, 2, info); - if (status != 0) - { - (*info->memory_error_func) (status, memaddr, info); - return -1; - } - - length = 2; - - if (info->endian == BFD_ENDIAN_BIG) - insn = bfd_getb16 (buffer); - else - insn = bfd_getl16 (buffer); - - /* Handle the extend opcode specially. */ - use_extend = FALSE; - if ((insn & 0xf800) == 0xf000) - { - use_extend = TRUE; - extend = insn & 0x7ff; - - memaddr += 2; - - status = (*info->read_memory_func) (memaddr, buffer, 2, info); - if (status != 0) - { - (*info->fprintf_func) (info->stream, "extend 0x%x", - (unsigned int) extend); - (*info->memory_error_func) (status, memaddr, info); - return -1; - } - - if (info->endian == BFD_ENDIAN_BIG) - insn = bfd_getb16 (buffer); - else - insn = bfd_getl16 (buffer); - - /* Check for an extend opcode followed by an extend opcode. */ - if ((insn & 0xf800) == 0xf000) - { - (*info->fprintf_func) (info->stream, "extend 0x%x", - (unsigned int) extend); - info->insn_type = dis_noninsn; - return length; - } - - length += 2; - } - - /* FIXME: Should probably use a hash table on the major opcode here. */ - - opend = mips16_opcodes + bfd_mips16_num_opcodes; - for (op = mips16_opcodes; op < opend; op++) - { - if (op->pinfo != INSN_MACRO && (insn & op->mask) == op->match) - { - const char *s; - - if (strchr (op->args, 'a') != NULL) - { - if (use_extend) - { - (*info->fprintf_func) (info->stream, "extend 0x%x", - (unsigned int) extend); - info->insn_type = dis_noninsn; - return length - 2; - } - - use_extend = FALSE; - - memaddr += 2; - - status = (*info->read_memory_func) (memaddr, buffer, 2, - info); - if (status == 0) - { - use_extend = TRUE; - if (info->endian == BFD_ENDIAN_BIG) - extend = bfd_getb16 (buffer); - else - extend = bfd_getl16 (buffer); - length += 2; - } - } - - (*info->fprintf_func) (info->stream, "%s", op->name); - if (op->args[0] != '\0') - (*info->fprintf_func) (info->stream, "\t"); - - for (s = op->args; *s != '\0'; s++) - { - if (*s == ',' - && s[1] == 'w' - && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX) - == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY))) - { - /* Skip the register and the comma. */ - ++s; - continue; - } - if (*s == ',' - && s[1] == 'v' - && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ) - == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX))) - { - /* Skip the register and the comma. */ - ++s; - continue; - } - print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr, - info); - } - - if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0) - { - info->branch_delay_insns = 1; - if (info->insn_type != dis_jsr) - info->insn_type = dis_branch; - } - - return length; - } - } - - if (use_extend) - (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000); - (*info->fprintf_func) (info->stream, "0x%x", insn); - info->insn_type = dis_noninsn; - - return length; -} - /* Disassemble an operand for a mips16 instruction. */ static void -print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info) - char type; - const struct mips_opcode *op; - int l; - bfd_boolean use_extend; - int extend; - bfd_vma memaddr; - struct disassemble_info *info; +print_mips16_insn_arg (char type, + const struct mips_opcode *op, + int l, + bfd_boolean use_extend, + int extend, + bfd_vma memaddr, + struct disassemble_info *info) { switch (type) { @@ -1770,6 +1746,92 @@ print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info) } break; + case 'm': + case 'M': + /* MIPS16e save/restore. */ + { + int need_comma = 0; + int amask, args, statics; + int nsreg, smask; + int framesz; + int i, j; + + l = l & 0x7f; + if (use_extend) + l |= extend << 16; + + amask = (l >> 16) & 0xf; + if (amask == MIPS16_ALL_ARGS) + { + args = 4; + statics = 0; + } + else if (amask == MIPS16_ALL_STATICS) + { + args = 0; + statics = 4; + } + else + { + args = amask >> 2; + statics = amask & 3; + } + + if (args > 0) { + (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[4]); + if (args > 1) + (*info->fprintf_func) (info->stream, "-%s", + mips_gpr_names[4 + args - 1]); + need_comma = 1; + } + + framesz = (((l >> 16) & 0xf0) | (l & 0x0f)) * 8; + if (framesz == 0 && !use_extend) + framesz = 128; + + (*info->fprintf_func) (info->stream, "%s%d", + need_comma ? "," : "", + framesz); + + if (l & 0x40) /* $ra */ + (*info->fprintf_func) (info->stream, ",%s", mips_gpr_names[31]); + + nsreg = (l >> 24) & 0x7; + smask = 0; + if (l & 0x20) /* $s0 */ + smask |= 1 << 0; + if (l & 0x10) /* $s1 */ + smask |= 1 << 1; + if (nsreg > 0) /* $s2-$s8 */ + smask |= ((1 << nsreg) - 1) << 2; + + /* Find first set static reg bit. */ + for (i = 0; i < 9; i++) + { + if (smask & (1 << i)) + { + (*info->fprintf_func) (info->stream, ",%s", + mips_gpr_names[i == 8 ? 30 : (16 + i)]); + /* Skip over string of set bits. */ + for (j = i; smask & (2 << j); j++) + continue; + if (j > i) + (*info->fprintf_func) (info->stream, "-%s", + mips_gpr_names[j == 8 ? 30 : (16 + j)]); + i = j + 1; + } + } + + /* Statics $ax - $a3. */ + if (statics == 1) + (*info->fprintf_func) (info->stream, ",%s", mips_gpr_names[7]); + else if (statics > 0) + (*info->fprintf_func) (info->stream, ",%s-%s", + mips_gpr_names[7 - statics + 1], + mips_gpr_names[7]); + } + break; + default: /* xgettext:c-format */ (*info->fprintf_func) @@ -1780,9 +1842,228 @@ print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info) } } +/* Disassemble mips16 instructions. */ + +static int +print_insn_mips16 (bfd_vma memaddr, struct disassemble_info *info) +{ + int status; + bfd_byte buffer[2]; + int length; + int insn; + bfd_boolean use_extend; + int extend = 0; + const struct mips_opcode *op, *opend; + + info->bytes_per_chunk = 2; + info->display_endian = info->endian; + info->insn_info_valid = 1; + info->branch_delay_insns = 0; + info->data_size = 0; + info->insn_type = dis_nonbranch; + info->target = 0; + info->target2 = 0; + + status = (*info->read_memory_func) (memaddr, buffer, 2, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + + length = 2; + + if (info->endian == BFD_ENDIAN_BIG) + insn = bfd_getb16 (buffer); + else + insn = bfd_getl16 (buffer); + + /* Handle the extend opcode specially. */ + use_extend = FALSE; + if ((insn & 0xf800) == 0xf000) + { + use_extend = TRUE; + extend = insn & 0x7ff; + + memaddr += 2; + + status = (*info->read_memory_func) (memaddr, buffer, 2, info); + if (status != 0) + { + (*info->fprintf_func) (info->stream, "extend 0x%x", + (unsigned int) extend); + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + + if (info->endian == BFD_ENDIAN_BIG) + insn = bfd_getb16 (buffer); + else + insn = bfd_getl16 (buffer); + + /* Check for an extend opcode followed by an extend opcode. */ + if ((insn & 0xf800) == 0xf000) + { + (*info->fprintf_func) (info->stream, "extend 0x%x", + (unsigned int) extend); + info->insn_type = dis_noninsn; + return length; + } + + length += 2; + } + + /* FIXME: Should probably use a hash table on the major opcode here. */ + + opend = mips16_opcodes + bfd_mips16_num_opcodes; + for (op = mips16_opcodes; op < opend; op++) + { + if (op->pinfo != INSN_MACRO + && !(no_aliases && (op->pinfo2 & INSN2_ALIAS)) + && (insn & op->mask) == op->match) + { + const char *s; + + if (strchr (op->args, 'a') != NULL) + { + if (use_extend) + { + (*info->fprintf_func) (info->stream, "extend 0x%x", + (unsigned int) extend); + info->insn_type = dis_noninsn; + return length - 2; + } + + use_extend = FALSE; + + memaddr += 2; + + status = (*info->read_memory_func) (memaddr, buffer, 2, + info); + if (status == 0) + { + use_extend = TRUE; + if (info->endian == BFD_ENDIAN_BIG) + extend = bfd_getb16 (buffer); + else + extend = bfd_getl16 (buffer); + length += 2; + } + } + + (*info->fprintf_func) (info->stream, "%s", op->name); + if (op->args[0] != '\0') + (*info->fprintf_func) (info->stream, "\t"); + + for (s = op->args; *s != '\0'; s++) + { + if (*s == ',' + && s[1] == 'w' + && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX) + == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY))) + { + /* Skip the register and the comma. */ + ++s; + continue; + } + if (*s == ',' + && s[1] == 'v' + && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ) + == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX))) + { + /* Skip the register and the comma. */ + ++s; + continue; + } + print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr, + info); + } + + if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0) + { + info->branch_delay_insns = 1; + if (info->insn_type != dis_jsr) + info->insn_type = dis_branch; + } + + return length; + } + } + + if (use_extend) + (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000); + (*info->fprintf_func) (info->stream, "0x%x", insn); + info->insn_type = dis_noninsn; + + return length; +} + +/* In an environment where we do not know the symbol type of the + instruction we are forced to assume that the low order bit of the + instructions' address may mark it as a mips16 instruction. If we + are single stepping, or the pc is within the disassembled function, + this works. Otherwise, we need a clue. Sometimes. */ + +static int +_print_insn_mips (bfd_vma memaddr, + struct disassemble_info *info, + enum bfd_endian endianness) +{ + bfd_byte buffer[INSNLEN]; + int status; + + set_default_mips_dis_options (info); + parse_mips_dis_options (info->disassembler_options); + +#if 1 + /* FIXME: If odd address, this is CLEARLY a mips 16 instruction. */ + /* Only a few tools will work this way. */ + if (memaddr & 0x01) + return print_insn_mips16 (memaddr, info); +#endif + +#if SYMTAB_AVAILABLE + if (info->mach == bfd_mach_mips16 + || (info->flavour == bfd_target_elf_flavour + && info->symbols != NULL + && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other + == STO_MIPS16))) + return print_insn_mips16 (memaddr, info); +#endif + + status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info); + if (status == 0) + { + unsigned long insn; + + if (endianness == BFD_ENDIAN_BIG) + insn = (unsigned long) bfd_getb32 (buffer); + else + insn = (unsigned long) bfd_getl32 (buffer); + + return print_insn_mips (memaddr, insn, info); + } + else + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } +} + +int +print_insn_big_mips (bfd_vma memaddr, struct disassemble_info *info) +{ + return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG); +} + +int +print_insn_little_mips (bfd_vma memaddr, struct disassemble_info *info) +{ + return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE); +} + void -print_mips_disassembler_options (stream) - FILE *stream; +print_mips_disassembler_options (FILE *stream) { unsigned int i; @@ -1790,6 +2071,12 @@ print_mips_disassembler_options (stream) The following MIPS specific disassembler options are supported for use\n\ with the -M switch (multiple options should be separated by commas):\n")); + fprintf (stream, _("\n\ + octeon-useun Disassemble Octeon unaligned load/store instructions.\n")); + + fprintf (stream, _("\n\ + no-octeon-useun Disassemble mips unaligned load/store instructions.\n")); + fprintf (stream, _("\n\ gpr-names=ABI Print GPR names according to specified ABI.\n\ Default: based on binary being disassembled.\n")); diff --git a/contrib/binutils/opcodes/mips-opc.c b/contrib/binutils/opcodes/mips-opc.c index 9a80e53d43d1..145b254a7ed2 100644 --- a/contrib/binutils/opcodes/mips-opc.c +++ b/contrib/binutils/opcodes/mips-opc.c @@ -1,6 +1,6 @@ /* mips-opc.c -- MIPS opcode list. Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 - Free Software Foundation, Inc. + 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Ralph Campbell and OSF Commented and modified by Ian Lance Taylor, Cygnus Support Extended for MIPS32 support by Anders Norlander, and by SiByte, Inc. @@ -21,7 +21,7 @@ the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this file; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "sysdep.h" @@ -76,8 +76,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * #define IS_M INSN_MULT -#define WR_MACC INSN_WRITE_MDMX_ACC -#define RD_MACC INSN_READ_MDMX_ACC +#define WR_MACC INSN2_WRITE_MDMX_ACC +#define RD_MACC INSN2_READ_MDMX_ACC #define I1 INSN_ISA1 #define I2 INSN_ISA2 @@ -89,6 +89,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * #define I33 INSN_ISA32R2 #define I65 INSN_ISA64R2 +/* Octeon specific instructions. */ +#define IOCTEON INSN_OCTEON + /* MIPS64 MIPS-3D ASE support. */ #define I16 INSN_MIPS16 @@ -119,6 +122,36 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * #define G3 (I4 \ ) +/* MIPS DSP ASE support. + NOTE: + 1. MIPS DSP ASE includes 4 accumulators ($ac0 - $ac3). $ac0 is the pair + of original HI and LO. $ac1, $ac2 and $ac3 are new registers, and have + the same structure as $ac0 (HI + LO). For DSP instructions that write or + read accumulators (that may be $ac0), we add WR_a (WR_HILO) or RD_a + (RD_HILO) attritubes, such that HILO dependences are maintained + conservatively. + + 2. For some mul. instructions that use integer registers as destinations + but destroy HI+LO as side-effect, we add WR_HILO to their attritubes. + + 3. MIPS DSP ASE includes a new DSP control register, which has 6 fields + (ccond, outflag, EFI, c, scount, pos). Many DSP instructions read or write + certain fields of the DSP control register. For simplicity, we decide not + to track dependences of these fields. + However, "bposge32" is a branch instruction that depends on the "pos" + field. In order to make sure that GAS does not reorder DSP instructions + that writes the "pos" field and "bposge32", we add DSP_VOLA (INSN_TRAP) + attritube to those instructions that write the "pos" field. */ + +#define WR_a WR_HILO /* Write dsp accumulators (reuse WR_HILO) */ +#define RD_a RD_HILO /* Read dsp accumulators (reuse RD_HILO) */ +#define MOD_a WR_a|RD_a +#define DSP_VOLA INSN_TRAP +#define D32 (INSN_DSP) + +/* MIPS MT ASE support. */ +#define MT32 (INSN_MT) + /* The order of overloaded instructions matters. Label arguments and register arguments look the same. Instructions that can have either for arguments must apear in the correct order in this table for the @@ -137,1073 +170,1295 @@ const struct mips_opcode mips_builtin_opcodes[] = /* These instructions appear first so that the disassembler will find them first. The assemblers uses a hash table based on the instruction name anyhow. */ -/* name, args, match, mask, pinfo, membership */ -{"pref", "k,o(b)", 0xcc000000, 0xfc000000, RD_b, I4|I32|G3 }, -{"prefx", "h,t(b)", 0x4c00000f, 0xfc0007ff, RD_b|RD_t, I4 }, -{"nop", "", 0x00000000, 0xffffffff, 0, I1 }, /* sll */ -{"ssnop", "", 0x00000040, 0xffffffff, 0, I32|N55 }, /* sll */ -{"ehb", "", 0x000000c0, 0xffffffff, 0, I33 }, /* sll */ -{"li", "t,j", 0x24000000, 0xffe00000, WR_t, I1 }, /* addiu */ -{"li", "t,i", 0x34000000, 0xffe00000, WR_t, I1 }, /* ori */ -{"li", "t,I", 0, (int) M_LI, INSN_MACRO, I1 }, -{"move", "d,s", 0, (int) M_MOVE, INSN_MACRO, I1 }, -{"move", "d,s", 0x0000002d, 0xfc1f07ff, WR_d|RD_s, I3 },/* daddu */ -{"move", "d,s", 0x00000021, 0xfc1f07ff, WR_d|RD_s, I1 },/* addu */ -{"move", "d,s", 0x00000025, 0xfc1f07ff, WR_d|RD_s, I1 },/* or */ -{"b", "p", 0x10000000, 0xffff0000, UBD, I1 },/* beq 0,0 */ -{"b", "p", 0x04010000, 0xffff0000, UBD, I1 },/* bgez 0 */ -{"bal", "p", 0x04110000, 0xffff0000, UBD|WR_31, I1 },/* bgezal 0*/ +/* name, args, match, mask, pinfo, pinfo2, membership */ +{"pref", "k,o(b)", 0xcc000000, 0xfc000000, RD_b, 0, I4|I32|G3 }, +{"prefx", "h,t(b)", 0x4c00000f, 0xfc0007ff, RD_b|RD_t, 0, I4|I33 }, +{"nop", "", 0x00000000, 0xffffffff, 0, INSN2_ALIAS, I1 }, /* sll */ +{"ssnop", "", 0x00000040, 0xffffffff, 0, INSN2_ALIAS, I32|N55 }, /* sll */ +{"ehb", "", 0x000000c0, 0xffffffff, 0, INSN2_ALIAS, I33 }, /* sll */ +{"li", "t,j", 0x24000000, 0xffe00000, WR_t, INSN2_ALIAS, I1 }, /* addiu */ +{"li", "t,i", 0x34000000, 0xffe00000, WR_t, INSN2_ALIAS, I1 }, /* ori */ +{"li", "t,I", 0, (int) M_LI, INSN_MACRO, 0, I1 }, +{"move", "d,s", 0, (int) M_MOVE, INSN_MACRO, 0, I1 }, +{"move", "d,s", 0x0000002d, 0xfc1f07ff, WR_d|RD_s, INSN2_ALIAS, I3 },/* daddu */ +{"move", "d,s", 0x00000021, 0xfc1f07ff, WR_d|RD_s, INSN2_ALIAS, I1 },/* addu */ +{"move", "d,s", 0x00000025, 0xfc1f07ff, WR_d|RD_s, INSN2_ALIAS, I1 },/* or */ +{"b", "p", 0x10000000, 0xffff0000, UBD, INSN2_ALIAS, I1 },/* beq 0,0 */ +{"b", "p", 0x04010000, 0xffff0000, UBD, INSN2_ALIAS, I1 },/* bgez 0 */ +{"bal", "p", 0x04110000, 0xffff0000, UBD|WR_31, INSN2_ALIAS, I1 },/* bgezal 0*/ -{"abs", "d,v", 0, (int) M_ABS, INSN_MACRO, I1 }, -{"abs.s", "D,V", 0x46000005, 0xffff003f, WR_D|RD_S|FP_S, I1 }, -{"abs.d", "D,V", 0x46200005, 0xffff003f, WR_D|RD_S|FP_D, I1 }, -{"abs.ps", "D,V", 0x46c00005, 0xffff003f, WR_D|RD_S|FP_D, I5 }, -{"add", "d,v,t", 0x00000020, 0xfc0007ff, WR_d|RD_s|RD_t, I1 }, -{"add", "t,r,I", 0, (int) M_ADD_I, INSN_MACRO, I1 }, -{"add.s", "D,V,T", 0x46000000, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, I1 }, -{"add.d", "D,V,T", 0x46200000, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, I1 }, -{"add.ob", "X,Y,Q", 0x7800000b, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"add.ob", "D,S,T", 0x4ac0000b, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"add.ob", "D,S,T[e]", 0x4800000b, 0xfe20003f, WR_D|RD_S|RD_T, N54 }, -{"add.ob", "D,S,k", 0x4bc0000b, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"add.ps", "D,V,T", 0x46c00000, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, I5 }, -{"add.qh", "X,Y,Q", 0x7820000b, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"adda.ob", "Y,Q", 0x78000037, 0xfc2007ff, WR_MACC|RD_S|RD_T|FP_D, MX|SB1 }, -{"adda.qh", "Y,Q", 0x78200037, 0xfc2007ff, WR_MACC|RD_S|RD_T|FP_D, MX }, -{"addi", "t,r,j", 0x20000000, 0xfc000000, WR_t|RD_s, I1 }, -{"addiu", "t,r,j", 0x24000000, 0xfc000000, WR_t|RD_s, I1 }, -{"addl.ob", "Y,Q", 0x78000437, 0xfc2007ff, WR_MACC|RD_S|RD_T|FP_D, MX|SB1 }, -{"addl.qh", "Y,Q", 0x78200437, 0xfc2007ff, WR_MACC|RD_S|RD_T|FP_D, MX }, -{"addr.ps", "D,S,T", 0x46c00018, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, M3D }, -{"addu", "d,v,t", 0x00000021, 0xfc0007ff, WR_d|RD_s|RD_t, I1 }, -{"addu", "t,r,I", 0, (int) M_ADDU_I, INSN_MACRO, I1 }, -{"alni.ob", "X,Y,Z,O", 0x78000018, 0xff00003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"alni.ob", "D,S,T,%", 0x48000018, 0xff00003f, WR_D|RD_S|RD_T, N54 }, -{"alni.qh", "X,Y,Z,O", 0x7800001a, 0xff00003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"alnv.ps", "D,V,T,s", 0x4c00001e, 0xfc00003f, WR_D|RD_S|RD_T|FP_D, I5 }, -{"alnv.ob", "X,Y,Z,s", 0x78000019, 0xfc00003f, WR_D|RD_S|RD_T|RD_s|FP_D, MX|SB1 }, -{"alnv.qh", "X,Y,Z,s", 0x7800001b, 0xfc00003f, WR_D|RD_S|RD_T|RD_s|FP_D, MX }, -{"and", "d,v,t", 0x00000024, 0xfc0007ff, WR_d|RD_s|RD_t, I1 }, -{"and", "t,r,I", 0, (int) M_AND_I, INSN_MACRO, I1 }, -{"and.ob", "X,Y,Q", 0x7800000c, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"and.ob", "D,S,T", 0x4ac0000c, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"and.ob", "D,S,T[e]", 0x4800000c, 0xfe20003f, WR_D|RD_S|RD_T, N54 }, -{"and.ob", "D,S,k", 0x4bc0000c, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"and.qh", "X,Y,Q", 0x7820000c, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"andi", "t,r,i", 0x30000000, 0xfc000000, WR_t|RD_s, I1 }, +{"abs", "d,v", 0, (int) M_ABS, INSN_MACRO, 0, I1 }, +{"abs.s", "D,V", 0x46000005, 0xffff003f, WR_D|RD_S|FP_S, 0, I1 }, +{"abs.d", "D,V", 0x46200005, 0xffff003f, WR_D|RD_S|FP_D, 0, I1 }, +{"abs.ps", "D,V", 0x46c00005, 0xffff003f, WR_D|RD_S|FP_D, 0, I5 }, +{"add", "d,v,t", 0x00000020, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, +{"add", "t,r,I", 0, (int) M_ADD_I, INSN_MACRO, 0, I1 }, +{"add.s", "D,V,T", 0x46000000, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I1 }, +{"add.d", "D,V,T", 0x46200000, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I1 }, +{"add.ob", "X,Y,Q", 0x7800000b, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"add.ob", "D,S,T", 0x4ac0000b, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"add.ob", "D,S,T[e]", 0x4800000b, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, +{"add.ob", "D,S,k", 0x4bc0000b, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"add.ps", "D,V,T", 0x46c00000, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I5 }, +{"add.qh", "X,Y,Q", 0x7820000b, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"adda.ob", "Y,Q", 0x78000037, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, +{"adda.qh", "Y,Q", 0x78200037, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, +{"addi", "t,r,j", 0x20000000, 0xfc000000, WR_t|RD_s, 0, I1 }, +{"addiu", "t,r,j", 0x24000000, 0xfc000000, WR_t|RD_s, 0, I1 }, +{"addl.ob", "Y,Q", 0x78000437, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, +{"addl.qh", "Y,Q", 0x78200437, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, +{"addr.ps", "D,S,T", 0x46c00018, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, M3D }, +{"addu", "d,v,t", 0x00000021, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, +{"addu", "t,r,I", 0, (int) M_ADDU_I, INSN_MACRO, 0, I1 }, +{"alni.ob", "X,Y,Z,O", 0x78000018, 0xff00003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"alni.ob", "D,S,T,%", 0x48000018, 0xff00003f, WR_D|RD_S|RD_T, 0, N54 }, +{"alni.qh", "X,Y,Z,O", 0x7800001a, 0xff00003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"alnv.ps", "D,V,T,s", 0x4c00001e, 0xfc00003f, WR_D|RD_S|RD_T|FP_D, 0, I5 }, +{"alnv.ob", "X,Y,Z,s", 0x78000019, 0xfc00003f, WR_D|RD_S|RD_T|RD_s|FP_D, 0, MX|SB1 }, +{"alnv.qh", "X,Y,Z,s", 0x7800001b, 0xfc00003f, WR_D|RD_S|RD_T|RD_s|FP_D, 0, MX }, +{"and", "d,v,t", 0x00000024, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, +{"and", "t,r,I", 0, (int) M_AND_I, INSN_MACRO, 0, I1 }, +{"and.ob", "X,Y,Q", 0x7800000c, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"and.ob", "D,S,T", 0x4ac0000c, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"and.ob", "D,S,T[e]", 0x4800000c, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, +{"and.ob", "D,S,k", 0x4bc0000c, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"and.qh", "X,Y,Q", 0x7820000c, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"andi", "t,r,i", 0x30000000, 0xfc000000, WR_t|RD_s, 0, I1 }, /* b is at the top of the table. */ /* bal is at the top of the table. */ -{"bc0f", "p", 0x41000000, 0xffff0000, CBD|RD_CC, I1 }, -{"bc0fl", "p", 0x41020000, 0xffff0000, CBL|RD_CC, I2|T3 }, -{"bc0t", "p", 0x41010000, 0xffff0000, CBD|RD_CC, I1 }, -{"bc0tl", "p", 0x41030000, 0xffff0000, CBL|RD_CC, I2|T3 }, -{"bc1any2f", "N,p", 0x45200000, 0xffe30000, CBD|RD_CC|FP_S, M3D }, -{"bc1any2t", "N,p", 0x45210000, 0xffe30000, CBD|RD_CC|FP_S, M3D }, -{"bc1any4f", "N,p", 0x45400000, 0xffe30000, CBD|RD_CC|FP_S, M3D }, -{"bc1any4t", "N,p", 0x45410000, 0xffe30000, CBD|RD_CC|FP_S, M3D }, -{"bc1f", "p", 0x45000000, 0xffff0000, CBD|RD_CC|FP_S, I1 }, -{"bc1f", "N,p", 0x45000000, 0xffe30000, CBD|RD_CC|FP_S, I4|I32 }, -{"bc1fl", "p", 0x45020000, 0xffff0000, CBL|RD_CC|FP_S, I2|T3 }, -{"bc1fl", "N,p", 0x45020000, 0xffe30000, CBL|RD_CC|FP_S, I4|I32 }, -{"bc1t", "p", 0x45010000, 0xffff0000, CBD|RD_CC|FP_S, I1 }, -{"bc1t", "N,p", 0x45010000, 0xffe30000, CBD|RD_CC|FP_S, I4|I32 }, -{"bc1tl", "p", 0x45030000, 0xffff0000, CBL|RD_CC|FP_S, I2|T3 }, -{"bc1tl", "N,p", 0x45030000, 0xffe30000, CBL|RD_CC|FP_S, I4|I32 }, -{"bc2f", "p", 0x49000000, 0xffff0000, CBD|RD_CC, I1 }, -{"bc2fl", "p", 0x49020000, 0xffff0000, CBL|RD_CC, I2|T3 }, -{"bc2t", "p", 0x49010000, 0xffff0000, CBD|RD_CC, I1 }, -{"bc2tl", "p", 0x49030000, 0xffff0000, CBL|RD_CC, I2|T3 }, -{"bc3f", "p", 0x4d000000, 0xffff0000, CBD|RD_CC, I1 }, -{"bc3fl", "p", 0x4d020000, 0xffff0000, CBL|RD_CC, I2|T3 }, -{"bc3t", "p", 0x4d010000, 0xffff0000, CBD|RD_CC, I1 }, -{"bc3tl", "p", 0x4d030000, 0xffff0000, CBL|RD_CC, I2|T3 }, -{"beqz", "s,p", 0x10000000, 0xfc1f0000, CBD|RD_s, I1 }, -{"beqzl", "s,p", 0x50000000, 0xfc1f0000, CBL|RD_s, I2|T3 }, -{"beq", "s,t,p", 0x10000000, 0xfc000000, CBD|RD_s|RD_t, I1 }, -{"beq", "s,I,p", 0, (int) M_BEQ_I, INSN_MACRO, I1 }, -{"beql", "s,t,p", 0x50000000, 0xfc000000, CBL|RD_s|RD_t, I2|T3 }, -{"beql", "s,I,p", 0, (int) M_BEQL_I, INSN_MACRO, I2|T3 }, -{"bge", "s,t,p", 0, (int) M_BGE, INSN_MACRO, I1 }, -{"bge", "s,I,p", 0, (int) M_BGE_I, INSN_MACRO, I1 }, -{"bgel", "s,t,p", 0, (int) M_BGEL, INSN_MACRO, I2|T3 }, -{"bgel", "s,I,p", 0, (int) M_BGEL_I, INSN_MACRO, I2|T3 }, -{"bgeu", "s,t,p", 0, (int) M_BGEU, INSN_MACRO, I1 }, -{"bgeu", "s,I,p", 0, (int) M_BGEU_I, INSN_MACRO, I1 }, -{"bgeul", "s,t,p", 0, (int) M_BGEUL, INSN_MACRO, I2|T3 }, -{"bgeul", "s,I,p", 0, (int) M_BGEUL_I, INSN_MACRO, I2|T3 }, -{"bgez", "s,p", 0x04010000, 0xfc1f0000, CBD|RD_s, I1 }, -{"bgezl", "s,p", 0x04030000, 0xfc1f0000, CBL|RD_s, I2|T3 }, -{"bgezal", "s,p", 0x04110000, 0xfc1f0000, CBD|RD_s|WR_31, I1 }, -{"bgezall", "s,p", 0x04130000, 0xfc1f0000, CBL|RD_s|WR_31, I2|T3 }, -{"bgt", "s,t,p", 0, (int) M_BGT, INSN_MACRO, I1 }, -{"bgt", "s,I,p", 0, (int) M_BGT_I, INSN_MACRO, I1 }, -{"bgtl", "s,t,p", 0, (int) M_BGTL, INSN_MACRO, I2|T3 }, -{"bgtl", "s,I,p", 0, (int) M_BGTL_I, INSN_MACRO, I2|T3 }, -{"bgtu", "s,t,p", 0, (int) M_BGTU, INSN_MACRO, I1 }, -{"bgtu", "s,I,p", 0, (int) M_BGTU_I, INSN_MACRO, I1 }, -{"bgtul", "s,t,p", 0, (int) M_BGTUL, INSN_MACRO, I2|T3 }, -{"bgtul", "s,I,p", 0, (int) M_BGTUL_I, INSN_MACRO, I2|T3 }, -{"bgtz", "s,p", 0x1c000000, 0xfc1f0000, CBD|RD_s, I1 }, -{"bgtzl", "s,p", 0x5c000000, 0xfc1f0000, CBL|RD_s, I2|T3 }, -{"ble", "s,t,p", 0, (int) M_BLE, INSN_MACRO, I1 }, -{"ble", "s,I,p", 0, (int) M_BLE_I, INSN_MACRO, I1 }, -{"blel", "s,t,p", 0, (int) M_BLEL, INSN_MACRO, I2|T3 }, -{"blel", "s,I,p", 0, (int) M_BLEL_I, INSN_MACRO, I2|T3 }, -{"bleu", "s,t,p", 0, (int) M_BLEU, INSN_MACRO, I1 }, -{"bleu", "s,I,p", 0, (int) M_BLEU_I, INSN_MACRO, I1 }, -{"bleul", "s,t,p", 0, (int) M_BLEUL, INSN_MACRO, I2|T3 }, -{"bleul", "s,I,p", 0, (int) M_BLEUL_I, INSN_MACRO, I2|T3 }, -{"blez", "s,p", 0x18000000, 0xfc1f0000, CBD|RD_s, I1 }, -{"blezl", "s,p", 0x58000000, 0xfc1f0000, CBL|RD_s, I2|T3 }, -{"blt", "s,t,p", 0, (int) M_BLT, INSN_MACRO, I1 }, -{"blt", "s,I,p", 0, (int) M_BLT_I, INSN_MACRO, I1 }, -{"bltl", "s,t,p", 0, (int) M_BLTL, INSN_MACRO, I2|T3 }, -{"bltl", "s,I,p", 0, (int) M_BLTL_I, INSN_MACRO, I2|T3 }, -{"bltu", "s,t,p", 0, (int) M_BLTU, INSN_MACRO, I1 }, -{"bltu", "s,I,p", 0, (int) M_BLTU_I, INSN_MACRO, I1 }, -{"bltul", "s,t,p", 0, (int) M_BLTUL, INSN_MACRO, I2|T3 }, -{"bltul", "s,I,p", 0, (int) M_BLTUL_I, INSN_MACRO, I2|T3 }, -{"bltz", "s,p", 0x04000000, 0xfc1f0000, CBD|RD_s, I1 }, -{"bltzl", "s,p", 0x04020000, 0xfc1f0000, CBL|RD_s, I2|T3 }, -{"bltzal", "s,p", 0x04100000, 0xfc1f0000, CBD|RD_s|WR_31, I1 }, -{"bltzall", "s,p", 0x04120000, 0xfc1f0000, CBL|RD_s|WR_31, I2|T3 }, -{"bnez", "s,p", 0x14000000, 0xfc1f0000, CBD|RD_s, I1 }, -{"bnezl", "s,p", 0x54000000, 0xfc1f0000, CBL|RD_s, I2|T3 }, -{"bne", "s,t,p", 0x14000000, 0xfc000000, CBD|RD_s|RD_t, I1 }, -{"bne", "s,I,p", 0, (int) M_BNE_I, INSN_MACRO, I1 }, -{"bnel", "s,t,p", 0x54000000, 0xfc000000, CBL|RD_s|RD_t, I2|T3 }, -{"bnel", "s,I,p", 0, (int) M_BNEL_I, INSN_MACRO, I2|T3 }, -{"break", "", 0x0000000d, 0xffffffff, TRAP, I1 }, -{"break", "B", 0x0000000d, 0xfc00003f, TRAP, I32 }, -{"break", "c", 0x0000000d, 0xfc00ffff, TRAP, I1 }, -{"break", "c,q", 0x0000000d, 0xfc00003f, TRAP, I1 }, -{"c.f.d", "S,T", 0x46200030, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I1 }, -{"c.f.d", "M,S,T", 0x46200030, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I4|I32 }, -{"c.f.s", "S,T", 0x46000030, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, I1 }, -{"c.f.s", "M,S,T", 0x46000030, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, I4|I32 }, -{"c.f.ps", "S,T", 0x46c00030, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.f.ps", "M,S,T", 0x46c00030, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.un.d", "S,T", 0x46200031, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I1 }, -{"c.un.d", "M,S,T", 0x46200031, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I4|I32 }, -{"c.un.s", "S,T", 0x46000031, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, I1 }, -{"c.un.s", "M,S,T", 0x46000031, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, I4|I32 }, -{"c.un.ps", "S,T", 0x46c00031, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.un.ps", "M,S,T", 0x46c00031, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.eq.d", "S,T", 0x46200032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I1 }, -{"c.eq.d", "M,S,T", 0x46200032, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I4|I32 }, -{"c.eq.s", "S,T", 0x46000032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, I1 }, -{"c.eq.s", "M,S,T", 0x46000032, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, I4|I32 }, -{"c.eq.ob", "Y,Q", 0x78000001, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, MX|SB1 }, -{"c.eq.ob", "S,T", 0x4ac00001, 0xffe007ff, WR_CC|RD_S|RD_T, N54 }, -{"c.eq.ob", "S,T[e]", 0x48000001, 0xfe2007ff, WR_CC|RD_S|RD_T, N54 }, -{"c.eq.ob", "S,k", 0x4bc00001, 0xffe007ff, WR_CC|RD_S|RD_T, N54 }, -{"c.eq.ps", "S,T", 0x46c00032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.eq.ps", "M,S,T", 0x46c00032, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.eq.qh", "Y,Q", 0x78200001, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, MX }, -{"c.ueq.d", "S,T", 0x46200033, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I1 }, -{"c.ueq.d", "M,S,T", 0x46200033, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I4|I32 }, -{"c.ueq.s", "S,T", 0x46000033, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, I1 }, -{"c.ueq.s", "M,S,T", 0x46000033, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, I4|I32 }, -{"c.ueq.ps","S,T", 0x46c00033, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.ueq.ps","M,S,T", 0x46c00033, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.olt.d", "S,T", 0x46200034, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I1 }, -{"c.olt.d", "M,S,T", 0x46200034, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I4|I32 }, -{"c.olt.s", "S,T", 0x46000034, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, I1 }, -{"c.olt.s", "M,S,T", 0x46000034, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, I4|I32 }, -{"c.olt.ps","S,T", 0x46c00034, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.olt.ps","M,S,T", 0x46c00034, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.ult.d", "S,T", 0x46200035, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I1 }, -{"c.ult.d", "M,S,T", 0x46200035, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I4|I32 }, -{"c.ult.s", "S,T", 0x46000035, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, I1 }, -{"c.ult.s", "M,S,T", 0x46000035, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, I4|I32 }, -{"c.ult.ps","S,T", 0x46c00035, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.ult.ps","M,S,T", 0x46c00035, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.ole.d", "S,T", 0x46200036, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I1 }, -{"c.ole.d", "M,S,T", 0x46200036, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I4|I32 }, -{"c.ole.s", "S,T", 0x46000036, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, I1 }, -{"c.ole.s", "M,S,T", 0x46000036, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, I4|I32 }, -{"c.ole.ps","S,T", 0x46c00036, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.ole.ps","M,S,T", 0x46c00036, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.ule.d", "S,T", 0x46200037, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I1 }, -{"c.ule.d", "M,S,T", 0x46200037, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I4|I32 }, -{"c.ule.s", "S,T", 0x46000037, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, I1 }, -{"c.ule.s", "M,S,T", 0x46000037, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, I4|I32 }, -{"c.ule.ps","S,T", 0x46c00037, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.ule.ps","M,S,T", 0x46c00037, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.sf.d", "S,T", 0x46200038, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I1 }, -{"c.sf.d", "M,S,T", 0x46200038, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I4|I32 }, -{"c.sf.s", "S,T", 0x46000038, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, I1 }, -{"c.sf.s", "M,S,T", 0x46000038, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, I4|I32 }, -{"c.sf.ps", "S,T", 0x46c00038, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.sf.ps", "M,S,T", 0x46c00038, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.ngle.d","S,T", 0x46200039, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I1 }, -{"c.ngle.d","M,S,T", 0x46200039, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I4|I32 }, -{"c.ngle.s","S,T", 0x46000039, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, I1 }, -{"c.ngle.s","M,S,T", 0x46000039, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, I4|I32 }, -{"c.ngle.ps","S,T", 0x46c00039, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.ngle.ps","M,S,T", 0x46c00039, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.seq.d", "S,T", 0x4620003a, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I1 }, -{"c.seq.d", "M,S,T", 0x4620003a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I4|I32 }, -{"c.seq.s", "S,T", 0x4600003a, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, I1 }, -{"c.seq.s", "M,S,T", 0x4600003a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, I4|I32 }, -{"c.seq.ps","S,T", 0x46c0003a, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.seq.ps","M,S,T", 0x46c0003a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.ngl.d", "S,T", 0x4620003b, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I1 }, -{"c.ngl.d", "M,S,T", 0x4620003b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I4|I32 }, -{"c.ngl.s", "S,T", 0x4600003b, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, I1 }, -{"c.ngl.s", "M,S,T", 0x4600003b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, I4|I32 }, -{"c.ngl.ps","S,T", 0x46c0003b, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.ngl.ps","M,S,T", 0x46c0003b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.lt.d", "S,T", 0x4620003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I1 }, -{"c.lt.d", "M,S,T", 0x4620003c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I4|I32 }, -{"c.lt.s", "S,T", 0x4600003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, I1 }, -{"c.lt.s", "M,S,T", 0x4600003c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, I4|I32 }, -{"c.lt.ob", "Y,Q", 0x78000004, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, MX|SB1 }, -{"c.lt.ob", "S,T", 0x4ac00004, 0xffe007ff, WR_CC|RD_S|RD_T, N54 }, -{"c.lt.ob", "S,T[e]", 0x48000004, 0xfe2007ff, WR_CC|RD_S|RD_T, N54 }, -{"c.lt.ob", "S,k", 0x4bc00004, 0xffe007ff, WR_CC|RD_S|RD_T, N54 }, -{"c.lt.ps", "S,T", 0x46c0003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.lt.ps", "M,S,T", 0x46c0003c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.lt.qh", "Y,Q", 0x78200004, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, MX }, -{"c.nge.d", "S,T", 0x4620003d, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I1 }, -{"c.nge.d", "M,S,T", 0x4620003d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I4|I32 }, -{"c.nge.s", "S,T", 0x4600003d, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, I1 }, -{"c.nge.s", "M,S,T", 0x4600003d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, I4|I32 }, -{"c.nge.ps","S,T", 0x46c0003d, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.nge.ps","M,S,T", 0x46c0003d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.le.d", "S,T", 0x4620003e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I1 }, -{"c.le.d", "M,S,T", 0x4620003e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I4|I32 }, -{"c.le.s", "S,T", 0x4600003e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, I1 }, -{"c.le.s", "M,S,T", 0x4600003e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, I4|I32 }, -{"c.le.ob", "Y,Q", 0x78000005, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, MX|SB1 }, -{"c.le.ob", "S,T", 0x4ac00005, 0xffe007ff, WR_CC|RD_S|RD_T, N54 }, -{"c.le.ob", "S,T[e]", 0x48000005, 0xfe2007ff, WR_CC|RD_S|RD_T, N54 }, -{"c.le.ob", "S,k", 0x4bc00005, 0xffe007ff, WR_CC|RD_S|RD_T, N54 }, -{"c.le.ps", "S,T", 0x46c0003e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.le.ps", "M,S,T", 0x46c0003e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.le.qh", "Y,Q", 0x78200005, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, MX }, -{"c.ngt.d", "S,T", 0x4620003f, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I1 }, -{"c.ngt.d", "M,S,T", 0x4620003f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I4|I32 }, -{"c.ngt.s", "S,T", 0x4600003f, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, I1 }, -{"c.ngt.s", "M,S,T", 0x4600003f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, I4|I32 }, -{"c.ngt.ps","S,T", 0x46c0003f, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"c.ngt.ps","M,S,T", 0x46c0003f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, I5 }, -{"cabs.eq.d", "M,S,T", 0x46200072, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.eq.ps", "M,S,T", 0x46c00072, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.eq.s", "M,S,T", 0x46000072, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, M3D }, -{"cabs.f.d", "M,S,T", 0x46200070, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.f.ps", "M,S,T", 0x46c00070, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.f.s", "M,S,T", 0x46000070, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, M3D }, -{"cabs.le.d", "M,S,T", 0x4620007e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.le.ps", "M,S,T", 0x46c0007e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.le.s", "M,S,T", 0x4600007e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, M3D }, -{"cabs.lt.d", "M,S,T", 0x4620007c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.lt.ps", "M,S,T", 0x46c0007c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.lt.s", "M,S,T", 0x4600007c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, M3D }, -{"cabs.nge.d", "M,S,T", 0x4620007d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.nge.ps","M,S,T", 0x46c0007d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.nge.s", "M,S,T", 0x4600007d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, M3D }, -{"cabs.ngl.d", "M,S,T", 0x4620007b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.ngl.ps","M,S,T", 0x46c0007b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.ngl.s", "M,S,T", 0x4600007b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, M3D }, -{"cabs.ngle.d","M,S,T", 0x46200079, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.ngle.ps","M,S,T",0x46c00079, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.ngle.s","M,S,T", 0x46000079, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, M3D }, -{"cabs.ngt.d", "M,S,T", 0x4620007f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.ngt.ps","M,S,T", 0x46c0007f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.ngt.s", "M,S,T", 0x4600007f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, M3D }, -{"cabs.ole.d", "M,S,T", 0x46200076, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.ole.ps","M,S,T", 0x46c00076, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.ole.s", "M,S,T", 0x46000076, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, M3D }, -{"cabs.olt.d", "M,S,T", 0x46200074, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.olt.ps","M,S,T", 0x46c00074, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.olt.s", "M,S,T", 0x46000074, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, M3D }, -{"cabs.seq.d", "M,S,T", 0x4620007a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.seq.ps","M,S,T", 0x46c0007a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.seq.s", "M,S,T", 0x4600007a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, M3D }, -{"cabs.sf.d", "M,S,T", 0x46200078, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.sf.ps", "M,S,T", 0x46c00078, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.sf.s", "M,S,T", 0x46000078, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, M3D }, -{"cabs.ueq.d", "M,S,T", 0x46200073, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.ueq.ps","M,S,T", 0x46c00073, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.ueq.s", "M,S,T", 0x46000073, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, M3D }, -{"cabs.ule.d", "M,S,T", 0x46200077, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.ule.ps","M,S,T", 0x46c00077, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.ule.s", "M,S,T", 0x46000077, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, M3D }, -{"cabs.ult.d", "M,S,T", 0x46200075, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.ult.ps","M,S,T", 0x46c00075, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.ult.s", "M,S,T", 0x46000075, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, M3D }, -{"cabs.un.d", "M,S,T", 0x46200071, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.un.ps", "M,S,T", 0x46c00071, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, M3D }, -{"cabs.un.s", "M,S,T", 0x46000071, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, M3D }, -{"cache", "k,o(b)", 0xbc000000, 0xfc000000, RD_b, I3|I32|T3}, -{"ceil.l.d", "D,S", 0x4620000a, 0xffff003f, WR_D|RD_S|FP_D, I3 }, -{"ceil.l.s", "D,S", 0x4600000a, 0xffff003f, WR_D|RD_S|FP_S, I3 }, -{"ceil.w.d", "D,S", 0x4620000e, 0xffff003f, WR_D|RD_S|FP_D, I2 }, -{"ceil.w.s", "D,S", 0x4600000e, 0xffff003f, WR_D|RD_S|FP_S, I2 }, -{"cfc0", "t,G", 0x40400000, 0xffe007ff, LCD|WR_t|RD_C0, I1 }, -{"cfc1", "t,G", 0x44400000, 0xffe007ff, LCD|WR_t|RD_C1|FP_S, I1 }, -{"cfc1", "t,S", 0x44400000, 0xffe007ff, LCD|WR_t|RD_C1|FP_S, I1 }, -{"cfc2", "t,G", 0x48400000, 0xffe007ff, LCD|WR_t|RD_C2, I1 }, -{"cfc3", "t,G", 0x4c400000, 0xffe007ff, LCD|WR_t|RD_C3, I1 }, -{"clo", "U,s", 0x70000021, 0xfc0007ff, WR_d|WR_t|RD_s, I32|N55 }, -{"clz", "U,s", 0x70000020, 0xfc0007ff, WR_d|WR_t|RD_s, I32|N55 }, -{"ctc0", "t,G", 0x40c00000, 0xffe007ff, COD|RD_t|WR_CC, I1 }, -{"ctc1", "t,G", 0x44c00000, 0xffe007ff, COD|RD_t|WR_CC|FP_S, I1 }, -{"ctc1", "t,S", 0x44c00000, 0xffe007ff, COD|RD_t|WR_CC|FP_S, I1 }, -{"ctc2", "t,G", 0x48c00000, 0xffe007ff, COD|RD_t|WR_CC, I1 }, -{"ctc3", "t,G", 0x4cc00000, 0xffe007ff, COD|RD_t|WR_CC, I1 }, -{"cvt.d.l", "D,S", 0x46a00021, 0xffff003f, WR_D|RD_S|FP_D, I3 }, -{"cvt.d.s", "D,S", 0x46000021, 0xffff003f, WR_D|RD_S|FP_D|FP_S, I1 }, -{"cvt.d.w", "D,S", 0x46800021, 0xffff003f, WR_D|RD_S|FP_D, I1 }, -{"cvt.l.d", "D,S", 0x46200025, 0xffff003f, WR_D|RD_S|FP_D, I3 }, -{"cvt.l.s", "D,S", 0x46000025, 0xffff003f, WR_D|RD_S|FP_S, I3 }, -{"cvt.s.l", "D,S", 0x46a00020, 0xffff003f, WR_D|RD_S|FP_S, I3 }, -{"cvt.s.d", "D,S", 0x46200020, 0xffff003f, WR_D|RD_S|FP_S|FP_D, I1 }, -{"cvt.s.w", "D,S", 0x46800020, 0xffff003f, WR_D|RD_S|FP_S, I1 }, -{"cvt.s.pl","D,S", 0x46c00028, 0xffff003f, WR_D|RD_S|FP_S|FP_D, I5 }, -{"cvt.s.pu","D,S", 0x46c00020, 0xffff003f, WR_D|RD_S|FP_S|FP_D, I5 }, -{"cvt.w.d", "D,S", 0x46200024, 0xffff003f, WR_D|RD_S|FP_D, I1 }, -{"cvt.w.s", "D,S", 0x46000024, 0xffff003f, WR_D|RD_S|FP_S, I1 }, -{"cvt.ps.pw", "D,S", 0x46800026, 0xffff003f, WR_D|RD_S|FP_S|FP_D, M3D }, -{"cvt.ps.s","D,V,T", 0x46000026, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, I5 }, -{"cvt.pw.ps", "D,S", 0x46c00024, 0xffff003f, WR_D|RD_S|FP_S|FP_D, M3D }, -{"dabs", "d,v", 0, (int) M_DABS, INSN_MACRO, I3 }, -{"dadd", "d,v,t", 0x0000002c, 0xfc0007ff, WR_d|RD_s|RD_t, I3 }, -{"dadd", "t,r,I", 0, (int) M_DADD_I, INSN_MACRO, I3 }, -{"daddi", "t,r,j", 0x60000000, 0xfc000000, WR_t|RD_s, I3 }, -{"daddiu", "t,r,j", 0x64000000, 0xfc000000, WR_t|RD_s, I3 }, -{"daddu", "d,v,t", 0x0000002d, 0xfc0007ff, WR_d|RD_s|RD_t, I3 }, -{"daddu", "t,r,I", 0, (int) M_DADDU_I, INSN_MACRO, I3 }, -{"dbreak", "", 0x7000003f, 0xffffffff, 0, N5 }, -{"dclo", "U,s", 0x70000025, 0xfc0007ff, RD_s|WR_d|WR_t, I64|N55 }, -{"dclz", "U,s", 0x70000024, 0xfc0007ff, RD_s|WR_d|WR_t, I64|N55 }, +{"baddu", "d,v,t", 0x70000028, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IOCTEON }, +{"bbit032", "s,^,p", 0xd8000000, 0xfc000000, CBD|RD_s, 0, IOCTEON }, +{"bbit0", "s,~,p", 0xd8000000, 0xfc000000, CBD|RD_s, 0, IOCTEON }, /* bbit032 */ +{"bbit0", "s,^,p", 0xc8000000, 0xfc000000, CBD|RD_s, 0, IOCTEON }, +{"bbit132", "s,^,p", 0xf8000000, 0xfc000000, CBD|RD_s, 0, IOCTEON }, +{"bbit1", "s,~,p", 0xf8000000, 0xfc000000, CBD|RD_s, 0, IOCTEON }, /* bbit132 */ +{"bbit1", "s,^,p", 0xe8000000, 0xfc000000, CBD|RD_s, 0, IOCTEON }, +/* bc0[tf]l? are at the bottom of the table. */ +{"bc1any2f", "N,p", 0x45200000, 0xffe30000, CBD|RD_CC|FP_S, 0, M3D }, +{"bc1any2t", "N,p", 0x45210000, 0xffe30000, CBD|RD_CC|FP_S, 0, M3D }, +{"bc1any4f", "N,p", 0x45400000, 0xffe30000, CBD|RD_CC|FP_S, 0, M3D }, +{"bc1any4t", "N,p", 0x45410000, 0xffe30000, CBD|RD_CC|FP_S, 0, M3D }, +{"bc1f", "p", 0x45000000, 0xffff0000, CBD|RD_CC|FP_S, 0, I1 }, +{"bc1f", "N,p", 0x45000000, 0xffe30000, CBD|RD_CC|FP_S, 0, I4|I32 }, +{"bc1fl", "p", 0x45020000, 0xffff0000, CBL|RD_CC|FP_S, 0, I2|T3 }, +{"bc1fl", "N,p", 0x45020000, 0xffe30000, CBL|RD_CC|FP_S, 0, I4|I32 }, +{"bc1t", "p", 0x45010000, 0xffff0000, CBD|RD_CC|FP_S, 0, I1 }, +{"bc1t", "N,p", 0x45010000, 0xffe30000, CBD|RD_CC|FP_S, 0, I4|I32 }, +{"bc1tl", "p", 0x45030000, 0xffff0000, CBL|RD_CC|FP_S, 0, I2|T3 }, +{"bc1tl", "N,p", 0x45030000, 0xffe30000, CBL|RD_CC|FP_S, 0, I4|I32 }, +/* bc2* are at the bottom of the table. */ +{"bc3f", "p", 0x4d000000, 0xffff0000, CBD|RD_CC, 0, I1 }, +{"bc3fl", "p", 0x4d020000, 0xffff0000, CBL|RD_CC, 0, I2|T3 }, +{"bc3t", "p", 0x4d010000, 0xffff0000, CBD|RD_CC, 0, I1 }, +{"bc3tl", "p", 0x4d030000, 0xffff0000, CBL|RD_CC, 0, I2|T3 }, +{"beqz", "s,p", 0x10000000, 0xfc1f0000, CBD|RD_s, 0, I1 }, +{"beqzl", "s,p", 0x50000000, 0xfc1f0000, CBL|RD_s, 0, I2|T3 }, +{"beq", "s,t,p", 0x10000000, 0xfc000000, CBD|RD_s|RD_t, 0, I1 }, +{"beq", "s,I,p", 0, (int) M_BEQ_I, INSN_MACRO, 0, I1 }, +{"beql", "s,t,p", 0x50000000, 0xfc000000, CBL|RD_s|RD_t, 0, I2|T3 }, +{"beql", "s,I,p", 0, (int) M_BEQL_I, INSN_MACRO, 0, I2|T3 }, +{"bge", "s,t,p", 0, (int) M_BGE, INSN_MACRO, 0, I1 }, +{"bge", "s,I,p", 0, (int) M_BGE_I, INSN_MACRO, 0, I1 }, +{"bgel", "s,t,p", 0, (int) M_BGEL, INSN_MACRO, 0, I2|T3 }, +{"bgel", "s,I,p", 0, (int) M_BGEL_I, INSN_MACRO, 0, I2|T3 }, +{"bgeu", "s,t,p", 0, (int) M_BGEU, INSN_MACRO, 0, I1 }, +{"bgeu", "s,I,p", 0, (int) M_BGEU_I, INSN_MACRO, 0, I1 }, +{"bgeul", "s,t,p", 0, (int) M_BGEUL, INSN_MACRO, 0, I2|T3 }, +{"bgeul", "s,I,p", 0, (int) M_BGEUL_I, INSN_MACRO, 0, I2|T3 }, +{"bgez", "s,p", 0x04010000, 0xfc1f0000, CBD|RD_s, 0, I1 }, +{"bgezl", "s,p", 0x04030000, 0xfc1f0000, CBL|RD_s, 0, I2|T3 }, +{"bgezal", "s,p", 0x04110000, 0xfc1f0000, CBD|RD_s|WR_31, 0, I1 }, +{"bgezall", "s,p", 0x04130000, 0xfc1f0000, CBL|RD_s|WR_31, 0, I2|T3 }, +{"bgt", "s,t,p", 0, (int) M_BGT, INSN_MACRO, 0, I1 }, +{"bgt", "s,I,p", 0, (int) M_BGT_I, INSN_MACRO, 0, I1 }, +{"bgtl", "s,t,p", 0, (int) M_BGTL, INSN_MACRO, 0, I2|T3 }, +{"bgtl", "s,I,p", 0, (int) M_BGTL_I, INSN_MACRO, 0, I2|T3 }, +{"bgtu", "s,t,p", 0, (int) M_BGTU, INSN_MACRO, 0, I1 }, +{"bgtu", "s,I,p", 0, (int) M_BGTU_I, INSN_MACRO, 0, I1 }, +{"bgtul", "s,t,p", 0, (int) M_BGTUL, INSN_MACRO, 0, I2|T3 }, +{"bgtul", "s,I,p", 0, (int) M_BGTUL_I, INSN_MACRO, 0, I2|T3 }, +{"bgtz", "s,p", 0x1c000000, 0xfc1f0000, CBD|RD_s, 0, I1 }, +{"bgtzl", "s,p", 0x5c000000, 0xfc1f0000, CBL|RD_s, 0, I2|T3 }, +{"ble", "s,t,p", 0, (int) M_BLE, INSN_MACRO, 0, I1 }, +{"ble", "s,I,p", 0, (int) M_BLE_I, INSN_MACRO, 0, I1 }, +{"blel", "s,t,p", 0, (int) M_BLEL, INSN_MACRO, 0, I2|T3 }, +{"blel", "s,I,p", 0, (int) M_BLEL_I, INSN_MACRO, 0, I2|T3 }, +{"bleu", "s,t,p", 0, (int) M_BLEU, INSN_MACRO, 0, I1 }, +{"bleu", "s,I,p", 0, (int) M_BLEU_I, INSN_MACRO, 0, I1 }, +{"bleul", "s,t,p", 0, (int) M_BLEUL, INSN_MACRO, 0, I2|T3 }, +{"bleul", "s,I,p", 0, (int) M_BLEUL_I, INSN_MACRO, 0, I2|T3 }, +{"blez", "s,p", 0x18000000, 0xfc1f0000, CBD|RD_s, 0, I1 }, +{"blezl", "s,p", 0x58000000, 0xfc1f0000, CBL|RD_s, 0, I2|T3 }, +{"blt", "s,t,p", 0, (int) M_BLT, INSN_MACRO, 0, I1 }, +{"blt", "s,I,p", 0, (int) M_BLT_I, INSN_MACRO, 0, I1 }, +{"bltl", "s,t,p", 0, (int) M_BLTL, INSN_MACRO, 0, I2|T3 }, +{"bltl", "s,I,p", 0, (int) M_BLTL_I, INSN_MACRO, 0, I2|T3 }, +{"bltu", "s,t,p", 0, (int) M_BLTU, INSN_MACRO, 0, I1 }, +{"bltu", "s,I,p", 0, (int) M_BLTU_I, INSN_MACRO, 0, I1 }, +{"bltul", "s,t,p", 0, (int) M_BLTUL, INSN_MACRO, 0, I2|T3 }, +{"bltul", "s,I,p", 0, (int) M_BLTUL_I, INSN_MACRO, 0, I2|T3 }, +{"bltz", "s,p", 0x04000000, 0xfc1f0000, CBD|RD_s, 0, I1 }, +{"bltzl", "s,p", 0x04020000, 0xfc1f0000, CBL|RD_s, 0, I2|T3 }, +{"bltzal", "s,p", 0x04100000, 0xfc1f0000, CBD|RD_s|WR_31, 0, I1 }, +{"bltzall", "s,p", 0x04120000, 0xfc1f0000, CBL|RD_s|WR_31, 0, I2|T3 }, +{"bnez", "s,p", 0x14000000, 0xfc1f0000, CBD|RD_s, 0, I1 }, +{"bnezl", "s,p", 0x54000000, 0xfc1f0000, CBL|RD_s, 0, I2|T3 }, +{"bne", "s,t,p", 0x14000000, 0xfc000000, CBD|RD_s|RD_t, 0, I1 }, +{"bne", "s,I,p", 0, (int) M_BNE_I, INSN_MACRO, 0, I1 }, +{"bnel", "s,t,p", 0x54000000, 0xfc000000, CBL|RD_s|RD_t, 0, I2|T3 }, +{"bnel", "s,I,p", 0, (int) M_BNEL_I, INSN_MACRO, 0, I2|T3 }, +{"break", "", 0x0000000d, 0xffffffff, TRAP, 0, I1 }, +{"break", "c", 0x0000000d, 0xfc00ffff, TRAP, 0, I1 }, +{"break", "c,q", 0x0000000d, 0xfc00003f, TRAP, 0, I1 }, +{"c.f.d", "S,T", 0x46200030, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, +{"c.f.d", "M,S,T", 0x46200030, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4|I32 }, +{"c.f.s", "S,T", 0x46000030, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, +{"c.f.s", "M,S,T", 0x46000030, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4|I32 }, +{"c.f.ps", "S,T", 0x46c00030, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.f.ps", "M,S,T", 0x46c00030, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.un.d", "S,T", 0x46200031, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, +{"c.un.d", "M,S,T", 0x46200031, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4|I32 }, +{"c.un.s", "S,T", 0x46000031, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, +{"c.un.s", "M,S,T", 0x46000031, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4|I32 }, +{"c.un.ps", "S,T", 0x46c00031, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.un.ps", "M,S,T", 0x46c00031, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.eq.d", "S,T", 0x46200032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, +{"c.eq.d", "M,S,T", 0x46200032, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4|I32 }, +{"c.eq.s", "S,T", 0x46000032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, +{"c.eq.s", "M,S,T", 0x46000032, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4|I32 }, +{"c.eq.ob", "Y,Q", 0x78000001, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"c.eq.ob", "S,T", 0x4ac00001, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"c.eq.ob", "S,T[e]", 0x48000001, 0xfe2007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"c.eq.ob", "S,k", 0x4bc00001, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"c.eq.ps", "S,T", 0x46c00032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.eq.ps", "M,S,T", 0x46c00032, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.eq.qh", "Y,Q", 0x78200001, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, 0, MX }, +{"c.ueq.d", "S,T", 0x46200033, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, +{"c.ueq.d", "M,S,T", 0x46200033, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4|I32 }, +{"c.ueq.s", "S,T", 0x46000033, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, +{"c.ueq.s", "M,S,T", 0x46000033, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4|I32 }, +{"c.ueq.ps","S,T", 0x46c00033, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.ueq.ps","M,S,T", 0x46c00033, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.olt.d", "S,T", 0x46200034, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, +{"c.olt.d", "M,S,T", 0x46200034, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4|I32 }, +{"c.olt.s", "S,T", 0x46000034, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, +{"c.olt.s", "M,S,T", 0x46000034, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4|I32 }, +{"c.olt.ps","S,T", 0x46c00034, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.olt.ps","M,S,T", 0x46c00034, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.ult.d", "S,T", 0x46200035, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, +{"c.ult.d", "M,S,T", 0x46200035, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4|I32 }, +{"c.ult.s", "S,T", 0x46000035, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, +{"c.ult.s", "M,S,T", 0x46000035, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4|I32 }, +{"c.ult.ps","S,T", 0x46c00035, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.ult.ps","M,S,T", 0x46c00035, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.ole.d", "S,T", 0x46200036, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, +{"c.ole.d", "M,S,T", 0x46200036, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4|I32 }, +{"c.ole.s", "S,T", 0x46000036, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, +{"c.ole.s", "M,S,T", 0x46000036, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4|I32 }, +{"c.ole.ps","S,T", 0x46c00036, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.ole.ps","M,S,T", 0x46c00036, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.ule.d", "S,T", 0x46200037, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, +{"c.ule.d", "M,S,T", 0x46200037, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4|I32 }, +{"c.ule.s", "S,T", 0x46000037, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, +{"c.ule.s", "M,S,T", 0x46000037, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4|I32 }, +{"c.ule.ps","S,T", 0x46c00037, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.ule.ps","M,S,T", 0x46c00037, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.sf.d", "S,T", 0x46200038, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, +{"c.sf.d", "M,S,T", 0x46200038, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4|I32 }, +{"c.sf.s", "S,T", 0x46000038, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, +{"c.sf.s", "M,S,T", 0x46000038, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4|I32 }, +{"c.sf.ps", "S,T", 0x46c00038, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.sf.ps", "M,S,T", 0x46c00038, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.ngle.d","S,T", 0x46200039, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, +{"c.ngle.d","M,S,T", 0x46200039, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4|I32 }, +{"c.ngle.s","S,T", 0x46000039, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, +{"c.ngle.s","M,S,T", 0x46000039, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4|I32 }, +{"c.ngle.ps","S,T", 0x46c00039, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.ngle.ps","M,S,T", 0x46c00039, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.seq.d", "S,T", 0x4620003a, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, +{"c.seq.d", "M,S,T", 0x4620003a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4|I32 }, +{"c.seq.s", "S,T", 0x4600003a, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, +{"c.seq.s", "M,S,T", 0x4600003a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4|I32 }, +{"c.seq.ps","S,T", 0x46c0003a, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.seq.ps","M,S,T", 0x46c0003a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.ngl.d", "S,T", 0x4620003b, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, +{"c.ngl.d", "M,S,T", 0x4620003b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4|I32 }, +{"c.ngl.s", "S,T", 0x4600003b, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, +{"c.ngl.s", "M,S,T", 0x4600003b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4|I32 }, +{"c.ngl.ps","S,T", 0x46c0003b, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.ngl.ps","M,S,T", 0x46c0003b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.lt.d", "S,T", 0x4620003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, +{"c.lt.d", "M,S,T", 0x4620003c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4|I32 }, +{"c.lt.s", "S,T", 0x4600003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, +{"c.lt.s", "M,S,T", 0x4600003c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4|I32 }, +{"c.lt.ob", "Y,Q", 0x78000004, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"c.lt.ob", "S,T", 0x4ac00004, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"c.lt.ob", "S,T[e]", 0x48000004, 0xfe2007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"c.lt.ob", "S,k", 0x4bc00004, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"c.lt.ps", "S,T", 0x46c0003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.lt.ps", "M,S,T", 0x46c0003c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.lt.qh", "Y,Q", 0x78200004, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, 0, MX }, +{"c.nge.d", "S,T", 0x4620003d, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, +{"c.nge.d", "M,S,T", 0x4620003d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4|I32 }, +{"c.nge.s", "S,T", 0x4600003d, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, +{"c.nge.s", "M,S,T", 0x4600003d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4|I32 }, +{"c.nge.ps","S,T", 0x46c0003d, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.nge.ps","M,S,T", 0x46c0003d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.le.d", "S,T", 0x4620003e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, +{"c.le.d", "M,S,T", 0x4620003e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4|I32 }, +{"c.le.s", "S,T", 0x4600003e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, +{"c.le.s", "M,S,T", 0x4600003e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4|I32 }, +{"c.le.ob", "Y,Q", 0x78000005, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"c.le.ob", "S,T", 0x4ac00005, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"c.le.ob", "S,T[e]", 0x48000005, 0xfe2007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"c.le.ob", "S,k", 0x4bc00005, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"c.le.ps", "S,T", 0x46c0003e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.le.ps", "M,S,T", 0x46c0003e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.le.qh", "Y,Q", 0x78200005, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, 0, MX }, +{"c.ngt.d", "S,T", 0x4620003f, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, +{"c.ngt.d", "M,S,T", 0x4620003f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4|I32 }, +{"c.ngt.s", "S,T", 0x4600003f, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, +{"c.ngt.s", "M,S,T", 0x4600003f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4|I32 }, +{"c.ngt.ps","S,T", 0x46c0003f, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"c.ngt.ps","M,S,T", 0x46c0003f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5 }, +{"cabs.eq.d", "M,S,T", 0x46200072, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.eq.ps", "M,S,T", 0x46c00072, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.eq.s", "M,S,T", 0x46000072, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, +{"cabs.f.d", "M,S,T", 0x46200070, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.f.ps", "M,S,T", 0x46c00070, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.f.s", "M,S,T", 0x46000070, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, +{"cabs.le.d", "M,S,T", 0x4620007e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.le.ps", "M,S,T", 0x46c0007e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.le.s", "M,S,T", 0x4600007e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, +{"cabs.lt.d", "M,S,T", 0x4620007c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.lt.ps", "M,S,T", 0x46c0007c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.lt.s", "M,S,T", 0x4600007c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, +{"cabs.nge.d", "M,S,T", 0x4620007d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.nge.ps","M,S,T", 0x46c0007d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.nge.s", "M,S,T", 0x4600007d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, +{"cabs.ngl.d", "M,S,T", 0x4620007b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.ngl.ps","M,S,T", 0x46c0007b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.ngl.s", "M,S,T", 0x4600007b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, +{"cabs.ngle.d","M,S,T", 0x46200079, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.ngle.ps","M,S,T",0x46c00079, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.ngle.s","M,S,T", 0x46000079, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, +{"cabs.ngt.d", "M,S,T", 0x4620007f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.ngt.ps","M,S,T", 0x46c0007f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.ngt.s", "M,S,T", 0x4600007f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, +{"cabs.ole.d", "M,S,T", 0x46200076, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.ole.ps","M,S,T", 0x46c00076, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.ole.s", "M,S,T", 0x46000076, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, +{"cabs.olt.d", "M,S,T", 0x46200074, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.olt.ps","M,S,T", 0x46c00074, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.olt.s", "M,S,T", 0x46000074, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, +{"cabs.seq.d", "M,S,T", 0x4620007a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.seq.ps","M,S,T", 0x46c0007a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.seq.s", "M,S,T", 0x4600007a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, +{"cabs.sf.d", "M,S,T", 0x46200078, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.sf.ps", "M,S,T", 0x46c00078, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.sf.s", "M,S,T", 0x46000078, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, +{"cabs.ueq.d", "M,S,T", 0x46200073, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.ueq.ps","M,S,T", 0x46c00073, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.ueq.s", "M,S,T", 0x46000073, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, +{"cabs.ule.d", "M,S,T", 0x46200077, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.ule.ps","M,S,T", 0x46c00077, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.ule.s", "M,S,T", 0x46000077, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, +{"cabs.ult.d", "M,S,T", 0x46200075, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.ult.ps","M,S,T", 0x46c00075, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.ult.s", "M,S,T", 0x46000075, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, +{"cabs.un.d", "M,S,T", 0x46200071, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.un.ps", "M,S,T", 0x46c00071, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, +{"cabs.un.s", "M,S,T", 0x46000071, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, +{"cache", "k,o(b)", 0xbc000000, 0xfc000000, RD_b, 0, I3|I32|T3}, +{"ceil.l.d", "D,S", 0x4620000a, 0xffff003f, WR_D|RD_S|FP_D, 0, I3|I33 }, +{"ceil.l.s", "D,S", 0x4600000a, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I3|I33 }, +{"ceil.w.d", "D,S", 0x4620000e, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I2 }, +{"ceil.w.s", "D,S", 0x4600000e, 0xffff003f, WR_D|RD_S|FP_S, 0, I2 }, +{"cfc0", "t,G", 0x40400000, 0xffe007ff, LCD|WR_t|RD_C0, 0, I1 }, +{"cfc1", "t,G", 0x44400000, 0xffe007ff, LCD|WR_t|RD_C1|FP_S, 0, I1 }, +{"cfc1", "t,S", 0x44400000, 0xffe007ff, LCD|WR_t|RD_C1|FP_S, 0, I1 }, +/* cfc2 is at the bottom of the table. */ +{"cfc3", "t,G", 0x4c400000, 0xffe007ff, LCD|WR_t|RD_C3, 0, I1 }, +{"cftc1", "d,E", 0x41000023, 0xffe007ff, TRAP|LCD|WR_d|RD_C1|FP_S, 0, MT32 }, +{"cftc1", "d,T", 0x41000023, 0xffe007ff, TRAP|LCD|WR_d|RD_C1|FP_S, 0, MT32 }, +{"cftc2", "d,E", 0x41000025, 0xffe007ff, TRAP|LCD|WR_d|RD_C2, 0, MT32 }, +{"cins32", "t,r,<,h", 0x70000033, 0xfc00003f, WR_t|RD_s, 0, IOCTEON }, +{"cins", "t,r,>,h", 0x70000033, 0xfc00003f, WR_t|RD_s, 0, IOCTEON }, /* cins32 */ +{"cins", "t,r,<,h", 0x70000032, 0xfc00003f, WR_t|RD_s, 0, IOCTEON }, +{"clo", "U,s", 0x70000021, 0xfc0007ff, WR_d|WR_t|RD_s, 0, I32|N55 }, +{"clz", "U,s", 0x70000020, 0xfc0007ff, WR_d|WR_t|RD_s, 0, I32|N55 }, +{"ctc0", "t,G", 0x40c00000, 0xffe007ff, COD|RD_t|WR_CC, 0, I1 }, +{"ctc1", "t,G", 0x44c00000, 0xffe007ff, COD|RD_t|WR_CC|FP_S, 0, I1 }, +{"ctc1", "t,S", 0x44c00000, 0xffe007ff, COD|RD_t|WR_CC|FP_S, 0, I1 }, +/* ctc2 is at the bottom of the table. */ +{"ctc3", "t,G", 0x4cc00000, 0xffe007ff, COD|RD_t|WR_CC, 0, I1 }, +{"cttc1", "t,g", 0x41800023, 0xffe007ff, TRAP|COD|RD_t|WR_CC|FP_S, 0, MT32 }, +{"cttc1", "t,S", 0x41800023, 0xffe007ff, TRAP|COD|RD_t|WR_CC|FP_S, 0, MT32 }, +{"cttc2", "t,g", 0x41800025, 0xffe007ff, TRAP|COD|RD_t|WR_CC, 0, MT32 }, +{"cvt.d.l", "D,S", 0x46a00021, 0xffff003f, WR_D|RD_S|FP_D, 0, I3|I33 }, +{"cvt.d.s", "D,S", 0x46000021, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I1 }, +{"cvt.d.w", "D,S", 0x46800021, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I1 }, +{"cvt.l.d", "D,S", 0x46200025, 0xffff003f, WR_D|RD_S|FP_D, 0, I3|I33 }, +{"cvt.l.s", "D,S", 0x46000025, 0xffff003f, WR_D|RD_S|FP_S|FP_S, 0, I3|I33 }, +{"cvt.s.l", "D,S", 0x46a00020, 0xffff003f, WR_D|RD_S|FP_S|FP_S, 0, I3|I33 }, +{"cvt.s.d", "D,S", 0x46200020, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I1 }, +{"cvt.s.w", "D,S", 0x46800020, 0xffff003f, WR_D|RD_S|FP_S, 0, I1 }, +{"cvt.s.pl","D,S", 0x46c00028, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I5 }, +{"cvt.s.pu","D,S", 0x46c00020, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I5 }, +{"cvt.w.d", "D,S", 0x46200024, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I1 }, +{"cvt.w.s", "D,S", 0x46000024, 0xffff003f, WR_D|RD_S|FP_S, 0, I1 }, +{"cvt.ps.pw", "D,S", 0x46800026, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, M3D }, +{"cvt.ps.s","D,V,T", 0x46000026, 0xffe0003f, WR_D|RD_S|RD_T|FP_S|FP_D, 0, I5 }, +{"cvt.pw.ps", "D,S", 0x46c00024, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, M3D }, +{"dabs", "d,v", 0, (int) M_DABS, INSN_MACRO, 0, I3 }, +{"dadd", "d,v,t", 0x0000002c, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I3 }, +{"dadd", "t,r,I", 0, (int) M_DADD_I, INSN_MACRO, 0, I3 }, +{"daddi", "t,r,j", 0x60000000, 0xfc000000, WR_t|RD_s, 0, I3 }, +{"daddiu", "t,r,j", 0x64000000, 0xfc000000, WR_t|RD_s, 0, I3 }, +{"daddu", "d,v,t", 0x0000002d, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I3 }, +{"daddu", "t,r,I", 0, (int) M_DADDU_I, INSN_MACRO, 0, I3 }, +{"dbreak", "", 0x7000003f, 0xffffffff, 0, 0, N5 }, +{"dclo", "U,s", 0x70000025, 0xfc0007ff, RD_s|WR_d|WR_t, 0, I64|N55 }, +{"dclz", "U,s", 0x70000024, 0xfc0007ff, RD_s|WR_d|WR_t, 0, I64|N55 }, /* dctr and dctw are used on the r5000. */ -{"dctr", "o(b)", 0xbc050000, 0xfc1f0000, RD_b, I3 }, -{"dctw", "o(b)", 0xbc090000, 0xfc1f0000, RD_b, I3 }, -{"deret", "", 0x4200001f, 0xffffffff, 0, I32|G2 }, -{"dext", "t,r,I,+I", 0, (int) M_DEXT, INSN_MACRO, I65 }, -{"dext", "t,r,+A,+C", 0x7c000003, 0xfc00003f, WR_t|RD_s, I65 }, -{"dextm", "t,r,+A,+G", 0x7c000001, 0xfc00003f, WR_t|RD_s, I65 }, -{"dextu", "t,r,+E,+H", 0x7c000002, 0xfc00003f, WR_t|RD_s, I65 }, +{"dctr", "o(b)", 0xbc050000, 0xfc1f0000, RD_b, 0, I3 }, +{"dctw", "o(b)", 0xbc090000, 0xfc1f0000, RD_b, 0, I3 }, +{"deret", "", 0x4200001f, 0xffffffff, 0, 0, I32|G2 }, +{"dext", "t,r,I,+I", 0, (int) M_DEXT, INSN_MACRO, 0, I65 }, +{"dext", "t,r,+A,+C", 0x7c000003, 0xfc00003f, WR_t|RD_s, 0, I65 }, +{"dextm", "t,r,+A,+G", 0x7c000001, 0xfc00003f, WR_t|RD_s, 0, I65 }, +{"dextu", "t,r,+E,+H", 0x7c000002, 0xfc00003f, WR_t|RD_s, 0, I65 }, /* For ddiv, see the comments about div. */ -{"ddiv", "z,s,t", 0x0000001e, 0xfc00ffff, RD_s|RD_t|WR_HILO, I3 }, -{"ddiv", "d,v,t", 0, (int) M_DDIV_3, INSN_MACRO, I3 }, -{"ddiv", "d,v,I", 0, (int) M_DDIV_3I, INSN_MACRO, I3 }, +{"ddiv", "z,s,t", 0x0000001e, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I3 }, +{"ddiv", "d,v,t", 0, (int) M_DDIV_3, INSN_MACRO, 0, I3 }, +{"ddiv", "d,v,I", 0, (int) M_DDIV_3I, INSN_MACRO, 0, I3 }, /* For ddivu, see the comments about div. */ -{"ddivu", "z,s,t", 0x0000001f, 0xfc00ffff, RD_s|RD_t|WR_HILO, I3 }, -{"ddivu", "d,v,t", 0, (int) M_DDIVU_3, INSN_MACRO, I3 }, -{"ddivu", "d,v,I", 0, (int) M_DDIVU_3I, INSN_MACRO, I3 }, -{"di", "", 0x41606000, 0xffffffff, WR_t|WR_C0, I33 }, -{"di", "t", 0x41606000, 0xffe0ffff, WR_t|WR_C0, I33 }, -{"dins", "t,r,I,+I", 0, (int) M_DINS, INSN_MACRO, I65 }, -{"dins", "t,r,+A,+B", 0x7c000007, 0xfc00003f, WR_t|RD_s, I65 }, -{"dinsm", "t,r,+A,+F", 0x7c000005, 0xfc00003f, WR_t|RD_s, I65 }, -{"dinsu", "t,r,+E,+F", 0x7c000006, 0xfc00003f, WR_t|RD_s, I65 }, +{"ddivu", "z,s,t", 0x0000001f, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I3 }, +{"ddivu", "d,v,t", 0, (int) M_DDIVU_3, INSN_MACRO, 0, I3 }, +{"ddivu", "d,v,I", 0, (int) M_DDIVU_3I, INSN_MACRO, 0, I3 }, +{"di", "", 0x41606000, 0xffffffff, WR_t|WR_C0, 0, I33 }, +{"di", "t", 0x41606000, 0xffe0ffff, WR_t|WR_C0, 0, I33 }, +{"dins", "t,r,I,+I", 0, (int) M_DINS, INSN_MACRO, 0, I65 }, +{"dins", "t,r,+A,+B", 0x7c000007, 0xfc00003f, WR_t|RD_s, 0, I65 }, +{"dinsm", "t,r,+A,+F", 0x7c000005, 0xfc00003f, WR_t|RD_s, 0, I65 }, +{"dinsu", "t,r,+E,+F", 0x7c000006, 0xfc00003f, WR_t|RD_s, 0, I65 }, /* The MIPS assembler treats the div opcode with two operands as 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_s|RD_t|WR_HILO, I1 }, -{"div", "z,t", 0x0000001a, 0xffe0ffff, RD_s|RD_t|WR_HILO, I1 }, -{"div", "d,v,t", 0, (int) M_DIV_3, INSN_MACRO, I1 }, -{"div", "d,v,I", 0, (int) M_DIV_3I, INSN_MACRO, I1 }, -{"div.d", "D,V,T", 0x46200003, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, I1 }, -{"div.s", "D,V,T", 0x46000003, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, I1 }, -{"div.ps", "D,V,T", 0x46c00003, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, SB1 }, +{"div", "z,s,t", 0x0000001a, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I1 }, +{"div", "z,t", 0x0000001a, 0xffe0ffff, RD_s|RD_t|WR_HILO, 0, I1 }, +{"div", "d,v,t", 0, (int) M_DIV_3, INSN_MACRO, 0, I1 }, +{"div", "d,v,I", 0, (int) M_DIV_3I, INSN_MACRO, 0, I1 }, +{"div.d", "D,V,T", 0x46200003, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I1 }, +{"div.s", "D,V,T", 0x46000003, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I1 }, +{"div.ps", "D,V,T", 0x46c00003, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, SB1 }, /* For divu, see the comments about div. */ -{"divu", "z,s,t", 0x0000001b, 0xfc00ffff, RD_s|RD_t|WR_HILO, I1 }, -{"divu", "z,t", 0x0000001b, 0xffe0ffff, RD_s|RD_t|WR_HILO, I1 }, -{"divu", "d,v,t", 0, (int) M_DIVU_3, INSN_MACRO, I1 }, -{"divu", "d,v,I", 0, (int) M_DIVU_3I, INSN_MACRO, I1 }, -{"dla", "t,A(b)", 0, (int) M_DLA_AB, INSN_MACRO, I3 }, -{"dlca", "t,A(b)", 0, (int) M_DLCA_AB, INSN_MACRO, I3 }, -{"dli", "t,j", 0x24000000, 0xffe00000, WR_t, I3 }, /* addiu */ -{"dli", "t,i", 0x34000000, 0xffe00000, WR_t, I3 }, /* ori */ -{"dli", "t,I", 0, (int) M_DLI, INSN_MACRO, I3 }, -{"dmacc", "d,s,t", 0x00000029, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, N412 }, -{"dmacchi", "d,s,t", 0x00000229, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, N412 }, -{"dmacchis", "d,s,t", 0x00000629, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, N412 }, -{"dmacchiu", "d,s,t", 0x00000269, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, N412 }, -{"dmacchius", "d,s,t", 0x00000669, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, N412 }, -{"dmaccs", "d,s,t", 0x00000429, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, N412 }, -{"dmaccu", "d,s,t", 0x00000069, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, N412 }, -{"dmaccus", "d,s,t", 0x00000469, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, N412 }, -{"dmadd16", "s,t", 0x00000029, 0xfc00ffff, RD_s|RD_t|MOD_LO, N411 }, -{"dmfc0", "t,G", 0x40200000, 0xffe007ff, LCD|WR_t|RD_C0, I3 }, -{"dmfc0", "t,+D", 0x40200000, 0xffe007f8, LCD|WR_t|RD_C0, I64 }, -{"dmfc0", "t,G,H", 0x40200000, 0xffe007f8, LCD|WR_t|RD_C0, I64 }, -{"dmtc0", "t,G", 0x40a00000, 0xffe007ff, COD|RD_t|WR_C0|WR_CC, I3 }, -{"dmtc0", "t,+D", 0x40a00000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC, I64 }, -{"dmtc0", "t,G,H", 0x40a00000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC, I64 }, -{"dmfc1", "t,S", 0x44200000, 0xffe007ff, LCD|WR_t|RD_S|FP_S, I3 }, -{"dmfc1", "t,G", 0x44200000, 0xffe007ff, LCD|WR_t|RD_S|FP_S, I3 }, -{"dmtc1", "t,S", 0x44a00000, 0xffe007ff, COD|RD_t|WR_S|FP_S, I3 }, -{"dmtc1", "t,G", 0x44a00000, 0xffe007ff, COD|RD_t|WR_S|FP_S, I3 }, -{"dmfc2", "t,G", 0x48200000, 0xffe007ff, LCD|WR_t|RD_C2, I3 }, -{"dmfc2", "t,G,H", 0x48200000, 0xffe007f8, LCD|WR_t|RD_C2, I64 }, -{"dmtc2", "t,G", 0x48a00000, 0xffe007ff, COD|RD_t|WR_C2|WR_CC, I3 }, -{"dmtc2", "t,G,H", 0x48a00000, 0xffe007f8, COD|RD_t|WR_C2|WR_CC, I64 }, -{"dmfc3", "t,G", 0x4c200000, 0xffe007ff, LCD|WR_t|RD_C3, I3 }, -{"dmfc3", "t,G,H", 0x4c200000, 0xffe007f8, LCD|WR_t|RD_C3, I64 }, -{"dmtc3", "t,G", 0x4ca00000, 0xffe007ff, COD|RD_t|WR_C3|WR_CC, I3 }, -{"dmtc3", "t,G,H", 0x4ca00000, 0xffe007f8, COD|RD_t|WR_C3|WR_CC, I64 }, -{"dmul", "d,v,t", 0, (int) M_DMUL, INSN_MACRO, I3 }, -{"dmul", "d,v,I", 0, (int) M_DMUL_I, INSN_MACRO, I3 }, -{"dmulo", "d,v,t", 0, (int) M_DMULO, INSN_MACRO, I3 }, -{"dmulo", "d,v,I", 0, (int) M_DMULO_I, INSN_MACRO, I3 }, -{"dmulou", "d,v,t", 0, (int) M_DMULOU, INSN_MACRO, I3 }, -{"dmulou", "d,v,I", 0, (int) M_DMULOU_I, INSN_MACRO, I3 }, -{"dmult", "s,t", 0x0000001c, 0xfc00ffff, RD_s|RD_t|WR_HILO, I3 }, -{"dmultu", "s,t", 0x0000001d, 0xfc00ffff, RD_s|RD_t|WR_HILO, I3 }, -{"dneg", "d,w", 0x0000002e, 0xffe007ff, WR_d|RD_t, I3 }, /* dsub 0 */ -{"dnegu", "d,w", 0x0000002f, 0xffe007ff, WR_d|RD_t, I3 }, /* dsubu 0*/ -{"drem", "z,s,t", 0x0000001e, 0xfc00ffff, RD_s|RD_t|WR_HILO, I3 }, -{"drem", "d,v,t", 3, (int) M_DREM_3, INSN_MACRO, I3 }, -{"drem", "d,v,I", 3, (int) M_DREM_3I, INSN_MACRO, I3 }, -{"dremu", "z,s,t", 0x0000001f, 0xfc00ffff, RD_s|RD_t|WR_HILO, I3 }, -{"dremu", "d,v,t", 3, (int) M_DREMU_3, INSN_MACRO, I3 }, -{"dremu", "d,v,I", 3, (int) M_DREMU_3I, INSN_MACRO, I3 }, -{"dret", "", 0x7000003e, 0xffffffff, 0, N5 }, -{"drol", "d,v,t", 0, (int) M_DROL, INSN_MACRO, I3 }, -{"drol", "d,v,I", 0, (int) M_DROL_I, INSN_MACRO, I3 }, -{"dror", "d,v,t", 0, (int) M_DROR, INSN_MACRO, I3 }, -{"dror", "d,v,I", 0, (int) M_DROR_I, INSN_MACRO, I3 }, -{"dror", "d,w,<", 0x0020003a, 0xffe0003f, WR_d|RD_t, N5|I65 }, -{"drorv", "d,t,s", 0x00000056, 0xfc0007ff, RD_t|RD_s|WR_d, N5|I65 }, -{"dror32", "d,w,<", 0x0020003e, 0xffe0003f, WR_d|RD_t, N5|I65 }, -{"drotl", "d,v,t", 0, (int) M_DROL, INSN_MACRO, I65 }, -{"drotl", "d,v,I", 0, (int) M_DROL_I, INSN_MACRO, I65 }, -{"drotr", "d,v,t", 0, (int) M_DROR, INSN_MACRO, I65 }, -{"drotr", "d,v,I", 0, (int) M_DROR_I, INSN_MACRO, I65 }, -{"drotrv", "d,t,s", 0x00000056, 0xfc0007ff, RD_t|RD_s|WR_d, I65 }, -{"drotr32", "d,w,<", 0x0020003e, 0xffe0003f, WR_d|RD_t, I65 }, -{"dsbh", "d,w", 0x7c0000a4, 0xffe007ff, WR_d|RD_t, I65 }, -{"dshd", "d,w", 0x7c000164, 0xffe007ff, WR_d|RD_t, I65 }, -{"dsllv", "d,t,s", 0x00000014, 0xfc0007ff, WR_d|RD_t|RD_s, I3 }, -{"dsll32", "d,w,<", 0x0000003c, 0xffe0003f, WR_d|RD_t, I3 }, -{"dsll", "d,w,s", 0x00000014, 0xfc0007ff, WR_d|RD_t|RD_s, I3 }, /* dsllv */ -{"dsll", "d,w,>", 0x0000003c, 0xffe0003f, WR_d|RD_t, I3 }, /* dsll32 */ -{"dsll", "d,w,<", 0x00000038, 0xffe0003f, WR_d|RD_t, I3 }, -{"dsrav", "d,t,s", 0x00000017, 0xfc0007ff, WR_d|RD_t|RD_s, I3 }, -{"dsra32", "d,w,<", 0x0000003f, 0xffe0003f, WR_d|RD_t, I3 }, -{"dsra", "d,w,s", 0x00000017, 0xfc0007ff, WR_d|RD_t|RD_s, I3 }, /* dsrav */ -{"dsra", "d,w,>", 0x0000003f, 0xffe0003f, WR_d|RD_t, I3 }, /* dsra32 */ -{"dsra", "d,w,<", 0x0000003b, 0xffe0003f, WR_d|RD_t, I3 }, -{"dsrlv", "d,t,s", 0x00000016, 0xfc0007ff, WR_d|RD_t|RD_s, I3 }, -{"dsrl32", "d,w,<", 0x0000003e, 0xffe0003f, WR_d|RD_t, I3 }, -{"dsrl", "d,w,s", 0x00000016, 0xfc0007ff, WR_d|RD_t|RD_s, I3 }, /* dsrlv */ -{"dsrl", "d,w,>", 0x0000003e, 0xffe0003f, WR_d|RD_t, I3 }, /* dsrl32 */ -{"dsrl", "d,w,<", 0x0000003a, 0xffe0003f, WR_d|RD_t, I3 }, -{"dsub", "d,v,t", 0x0000002e, 0xfc0007ff, WR_d|RD_s|RD_t, I3 }, -{"dsub", "d,v,I", 0, (int) M_DSUB_I, INSN_MACRO, I3 }, -{"dsubu", "d,v,t", 0x0000002f, 0xfc0007ff, WR_d|RD_s|RD_t, I3 }, -{"dsubu", "d,v,I", 0, (int) M_DSUBU_I, INSN_MACRO, I3 }, -{"ei", "", 0x41606020, 0xffffffff, WR_t|WR_C0, I33 }, -{"ei", "t", 0x41606020, 0xffe0ffff, WR_t|WR_C0, I33 }, -{"eret", "", 0x42000018, 0xffffffff, 0, I3|I32 }, -{"ext", "t,r,+A,+C", 0x7c000000, 0xfc00003f, WR_t|RD_s, I33 }, -{"floor.l.d", "D,S", 0x4620000b, 0xffff003f, WR_D|RD_S|FP_D, I3 }, -{"floor.l.s", "D,S", 0x4600000b, 0xffff003f, WR_D|RD_S|FP_S, I3 }, -{"floor.w.d", "D,S", 0x4620000f, 0xffff003f, WR_D|RD_S|FP_D, I2 }, -{"floor.w.s", "D,S", 0x4600000f, 0xffff003f, WR_D|RD_S|FP_S, I2 }, -{"flushi", "", 0xbc010000, 0xffffffff, 0, L1 }, -{"flushd", "", 0xbc020000, 0xffffffff, 0, L1 }, -{"flushid", "", 0xbc030000, 0xffffffff, 0, L1 }, -{"hibernate","", 0x42000023, 0xffffffff, 0, V1 }, -{"ins", "t,r,+A,+B", 0x7c000004, 0xfc00003f, WR_t|RD_s, I33 }, -{"jr", "s", 0x00000008, 0xfc1fffff, UBD|RD_s, I1 }, -{"jr.hb", "s", 0x00000408, 0xfc1fffff, UBD|RD_s, I33 }, -{"j", "s", 0x00000008, 0xfc1fffff, UBD|RD_s, I1 }, /* jr */ +{"divu", "z,s,t", 0x0000001b, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I1 }, +{"divu", "z,t", 0x0000001b, 0xffe0ffff, RD_s|RD_t|WR_HILO, 0, I1 }, +{"divu", "d,v,t", 0, (int) M_DIVU_3, INSN_MACRO, 0, I1 }, +{"divu", "d,v,I", 0, (int) M_DIVU_3I, INSN_MACRO, 0, I1 }, +{"dla", "t,A(b)", 0, (int) M_DLA_AB, INSN_MACRO, 0, I3 }, +{"dlca", "t,A(b)", 0, (int) M_DLCA_AB, INSN_MACRO, 0, I3 }, +{"dli", "t,j", 0x24000000, 0xffe00000, WR_t, 0, I3 }, /* addiu */ +{"dli", "t,i", 0x34000000, 0xffe00000, WR_t, 0, I3 }, /* ori */ +{"dli", "t,I", 0, (int) M_DLI, INSN_MACRO, 0, I3 }, +{"dmacc", "d,s,t", 0x00000029, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, 0, N412 }, +{"dmacchi", "d,s,t", 0x00000229, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, 0, N412 }, +{"dmacchis", "d,s,t", 0x00000629, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, 0, N412 }, +{"dmacchiu", "d,s,t", 0x00000269, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, 0, N412 }, +{"dmacchius", "d,s,t", 0x00000669, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, 0, N412 }, +{"dmaccs", "d,s,t", 0x00000429, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, 0, N412 }, +{"dmaccu", "d,s,t", 0x00000069, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, 0, N412 }, +{"dmaccus", "d,s,t", 0x00000469, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, 0, N412 }, +{"dmadd16", "s,t", 0x00000029, 0xfc00ffff, RD_s|RD_t|MOD_LO, 0, N411 }, +{"dmfc0", "t,G", 0x40200000, 0xffe007ff, LCD|WR_t|RD_C0, 0, I3 }, +{"dmfc0", "t,+D", 0x40200000, 0xffe007f8, LCD|WR_t|RD_C0, 0, I64 }, +{"dmfc0", "t,G,H", 0x40200000, 0xffe007f8, LCD|WR_t|RD_C0, 0, I64 }, +{"dmt", "", 0x41600bc1, 0xffffffff, TRAP, 0, MT32 }, +{"dmt", "t", 0x41600bc1, 0xffe0ffff, TRAP|WR_t, 0, MT32 }, +{"dmtc0", "t,G", 0x40a00000, 0xffe007ff, COD|RD_t|WR_C0|WR_CC, 0, I3 }, +{"dmtc0", "t,+D", 0x40a00000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC, 0, I64 }, +{"dmtc0", "t,G,H", 0x40a00000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC, 0, I64 }, +{"dmfc1", "t,S", 0x44200000, 0xffe007ff, LCD|WR_t|RD_S|FP_D, 0, I3 }, +{"dmfc1", "t,G", 0x44200000, 0xffe007ff, LCD|WR_t|RD_S|FP_D, 0, I3 }, +{"dmtc1", "t,S", 0x44a00000, 0xffe007ff, COD|RD_t|WR_S|FP_D, 0, I3 }, +{"dmtc1", "t,G", 0x44a00000, 0xffe007ff, COD|RD_t|WR_S|FP_D, 0, I3 }, +/* dmfc2 is at the bottom of the table. */ +/* dmtc2 is at the bottom of the table. */ +{"dmfc3", "t,G", 0x4c200000, 0xffe007ff, LCD|WR_t|RD_C3, 0, I3 }, +{"dmfc3", "t,G,H", 0x4c200000, 0xffe007f8, LCD|WR_t|RD_C3, 0, I64 }, +{"dmtc3", "t,G", 0x4ca00000, 0xffe007ff, COD|RD_t|WR_C3|WR_CC, 0, I3 }, +{"dmtc3", "t,G,H", 0x4ca00000, 0xffe007f8, COD|RD_t|WR_C3|WR_CC, 0, I64 }, +{"dmul", "d,v,t", 0x70000003, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, IOCTEON }, +{"dmul", "d,v,t", 0, (int) M_DMUL, INSN_MACRO, 0, I3 }, +{"dmul", "d,v,I", 0, (int) M_DMUL_I, INSN_MACRO, 0, I3 }, +{"dmulo", "d,v,t", 0, (int) M_DMULO, INSN_MACRO, 0, I3 }, +{"dmulo", "d,v,I", 0, (int) M_DMULO_I, INSN_MACRO, 0, I3 }, +{"dmulou", "d,v,t", 0, (int) M_DMULOU, INSN_MACRO, 0, I3 }, +{"dmulou", "d,v,I", 0, (int) M_DMULOU_I, INSN_MACRO, 0, I3 }, +{"dmult", "s,t", 0x0000001c, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I3 }, +{"dmultu", "s,t", 0x0000001d, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I3 }, +{"dneg", "d,w", 0x0000002e, 0xffe007ff, WR_d|RD_t, 0, I3 }, /* dsub 0 */ +{"dnegu", "d,w", 0x0000002f, 0xffe007ff, WR_d|RD_t, 0, I3 }, /* dsubu 0*/ +{"dpop", "d,s", 0x7000002d, 0xfc1f07ff, RD_s|WR_d, 0, IOCTEON }, +{"drem", "z,s,t", 0x0000001e, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I3 }, +{"drem", "d,v,t", 3, (int) M_DREM_3, INSN_MACRO, 0, I3 }, +{"drem", "d,v,I", 3, (int) M_DREM_3I, INSN_MACRO, 0, I3 }, +{"dremu", "z,s,t", 0x0000001f, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I3 }, +{"dremu", "d,v,t", 3, (int) M_DREMU_3, INSN_MACRO, 0, I3 }, +{"dremu", "d,v,I", 3, (int) M_DREMU_3I, INSN_MACRO, 0, I3 }, +{"dret", "", 0x7000003e, 0xffffffff, 0, 0, N5 }, +{"drol", "d,v,t", 0, (int) M_DROL, INSN_MACRO, 0, I3 }, +{"drol", "d,v,I", 0, (int) M_DROL_I, INSN_MACRO, 0, I3 }, +{"dror", "d,v,t", 0, (int) M_DROR, INSN_MACRO, 0, I3 }, +{"dror", "d,v,I", 0, (int) M_DROR_I, INSN_MACRO, 0, I3 }, +{"dror", "d,w,<", 0x0020003a, 0xffe0003f, WR_d|RD_t, 0, N5|I65 }, +{"drorv", "d,t,s", 0x00000056, 0xfc0007ff, RD_t|RD_s|WR_d, 0, N5|I65 }, +{"dror32", "d,w,<", 0x0020003e, 0xffe0003f, WR_d|RD_t, 0, N5|I65 }, +{"drotl", "d,v,t", 0, (int) M_DROL, INSN_MACRO, 0, I65 }, +{"drotl", "d,v,I", 0, (int) M_DROL_I, INSN_MACRO, 0, I65 }, +{"drotr", "d,v,t", 0, (int) M_DROR, INSN_MACRO, 0, I65 }, +{"drotr", "d,v,I", 0, (int) M_DROR_I, INSN_MACRO, 0, I65 }, +{"drotrv", "d,t,s", 0x00000056, 0xfc0007ff, RD_t|RD_s|WR_d, 0, I65 }, +{"drotr32", "d,w,<", 0x0020003e, 0xffe0003f, WR_d|RD_t, 0, I65 }, +{"dsbh", "d,w", 0x7c0000a4, 0xffe007ff, WR_d|RD_t, 0, I65 }, +{"dshd", "d,w", 0x7c000164, 0xffe007ff, WR_d|RD_t, 0, I65 }, +{"dsllv", "d,t,s", 0x00000014, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I3 }, +{"dsll32", "d,w,<", 0x0000003c, 0xffe0003f, WR_d|RD_t, 0, I3 }, +{"dsll", "d,w,s", 0x00000014, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I3 }, /* dsllv */ +{"dsll", "d,w,>", 0x0000003c, 0xffe0003f, WR_d|RD_t, 0, I3 }, /* dsll32 */ +{"dsll", "d,w,<", 0x00000038, 0xffe0003f, WR_d|RD_t, 0, I3 }, +{"dsrav", "d,t,s", 0x00000017, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I3 }, +{"dsra32", "d,w,<", 0x0000003f, 0xffe0003f, WR_d|RD_t, 0, I3 }, +{"dsra", "d,w,s", 0x00000017, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I3 }, /* dsrav */ +{"dsra", "d,w,>", 0x0000003f, 0xffe0003f, WR_d|RD_t, 0, I3 }, /* dsra32 */ +{"dsra", "d,w,<", 0x0000003b, 0xffe0003f, WR_d|RD_t, 0, I3 }, +{"dsrlv", "d,t,s", 0x00000016, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I3 }, +{"dsrl32", "d,w,<", 0x0000003e, 0xffe0003f, WR_d|RD_t, 0, I3 }, +{"dsrl", "d,w,s", 0x00000016, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I3 }, /* dsrlv */ +{"dsrl", "d,w,>", 0x0000003e, 0xffe0003f, WR_d|RD_t, 0, I3 }, /* dsrl32 */ +{"dsrl", "d,w,<", 0x0000003a, 0xffe0003f, WR_d|RD_t, 0, I3 }, +{"dsub", "d,v,t", 0x0000002e, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I3 }, +{"dsub", "d,v,I", 0, (int) M_DSUB_I, INSN_MACRO, 0, I3 }, +{"dsubu", "d,v,t", 0x0000002f, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I3 }, +{"dsubu", "d,v,I", 0, (int) M_DSUBU_I, INSN_MACRO, 0, I3 }, +{"dvpe", "", 0x41600001, 0xffffffff, TRAP, 0, MT32 }, +{"dvpe", "t", 0x41600001, 0xffe0ffff, TRAP|WR_t, 0, MT32 }, +{"ei", "", 0x41606020, 0xffffffff, WR_t|WR_C0, 0, I33 }, +{"ei", "t", 0x41606020, 0xffe0ffff, WR_t|WR_C0, 0, I33 }, +{"emt", "", 0x41600be1, 0xffffffff, TRAP, 0, MT32 }, +{"emt", "t", 0x41600be1, 0xffe0ffff, TRAP|WR_t, 0, MT32 }, +{"eret", "", 0x42000018, 0xffffffff, 0, 0, I3|I32 }, +{"evpe", "", 0x41600021, 0xffffffff, TRAP, 0, MT32 }, +{"evpe", "t", 0x41600021, 0xffe0ffff, TRAP|WR_t, 0, MT32 }, +{"ext", "t,r,+A,+C", 0x7c000000, 0xfc00003f, WR_t|RD_s, 0, I33 }, +{"exts32", "t,r,<,h", 0x7000003b, 0xfc00003f, WR_t|RD_s, 0, IOCTEON }, +{"exts", "t,r,>,h", 0x7000003b, 0xfc00003f, WR_t|RD_s, 0, IOCTEON }, /* exts32 */ +{"exts", "t,r,<,h", 0x7000003a, 0xfc00003f, WR_t|RD_s, 0, IOCTEON }, +{"floor.l.d", "D,S", 0x4620000b, 0xffff003f, WR_D|RD_S|FP_D, 0, I3|I33 }, +{"floor.l.s", "D,S", 0x4600000b, 0xffff003f, WR_D|RD_S|FP_S|FP_S, 0, I3|I33 }, +{"floor.w.d", "D,S", 0x4620000f, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I2 }, +{"floor.w.s", "D,S", 0x4600000f, 0xffff003f, WR_D|RD_S|FP_S, 0, I2 }, +{"flushi", "", 0xbc010000, 0xffffffff, 0, 0, L1 }, +{"flushd", "", 0xbc020000, 0xffffffff, 0, 0, L1 }, +{"flushid", "", 0xbc030000, 0xffffffff, 0, 0, L1 }, +{"hibernate","", 0x42000023, 0xffffffff, 0, 0, V1 }, +{"ins", "t,r,+A,+B", 0x7c000004, 0xfc00003f, WR_t|RD_s, 0, I33 }, +{"jr", "s", 0x00000008, 0xfc1fffff, UBD|RD_s, 0, I1 }, +{"jr.hb", "s", 0x00000408, 0xfc1fffff, UBD|RD_s, 0, I33 }, +{"j", "s", 0x00000008, 0xfc1fffff, UBD|RD_s, 0, I1 }, /* jr */ /* SVR4 PIC code requires special handling for j, so it must be a macro. */ -{"j", "a", 0, (int) M_J_A, INSN_MACRO, I1 }, +{"j", "a", 0, (int) M_J_A, INSN_MACRO, 0, I1 }, /* This form of j is used by the disassembler and internally by the assembler, but will never match user input (because the line above will match first). */ -{"j", "a", 0x08000000, 0xfc000000, UBD, I1 }, -{"jalr", "s", 0x0000f809, 0xfc1fffff, UBD|RD_s|WR_d, I1 }, -{"jalr", "d,s", 0x00000009, 0xfc1f07ff, UBD|RD_s|WR_d, I1 }, -{"jalr.hb", "s", 0x0000fc09, 0xfc1fffff, UBD|RD_s|WR_d, I33 }, -{"jalr.hb", "d,s", 0x00000409, 0xfc1f07ff, UBD|RD_s|WR_d, I33 }, +{"j", "a", 0x08000000, 0xfc000000, UBD, 0, I1 }, +{"jalr", "s", 0x0000f809, 0xfc1fffff, UBD|RD_s|WR_d, 0, I1 }, +{"jalr", "d,s", 0x00000009, 0xfc1f07ff, UBD|RD_s|WR_d, 0, I1 }, +{"jalr.hb", "s", 0x0000fc09, 0xfc1fffff, UBD|RD_s|WR_d, 0, I33 }, +{"jalr.hb", "d,s", 0x00000409, 0xfc1f07ff, UBD|RD_s|WR_d, 0, I33 }, /* SVR4 PIC code requires special handling for jal, so it must be a macro. */ -{"jal", "d,s", 0, (int) M_JAL_2, INSN_MACRO, I1 }, -{"jal", "s", 0, (int) M_JAL_1, INSN_MACRO, I1 }, -{"jal", "a", 0, (int) M_JAL_A, INSN_MACRO, I1 }, +{"jal", "d,s", 0, (int) M_JAL_2, INSN_MACRO, 0, I1 }, +{"jal", "s", 0, (int) M_JAL_1, INSN_MACRO, 0, I1 }, +{"jal", "a", 0, (int) M_JAL_A, INSN_MACRO, 0, I1 }, /* This form of jal is used by the disassembler and internally by the assembler, but will never match user input (because the line above will match first). */ -{"jal", "a", 0x0c000000, 0xfc000000, UBD|WR_31, I1 }, -{"jalx", "a", 0x74000000, 0xfc000000, UBD|WR_31, I16 }, -{"la", "t,A(b)", 0, (int) M_LA_AB, INSN_MACRO, I1 }, -{"lb", "t,o(b)", 0x80000000, 0xfc000000, LDD|RD_b|WR_t, I1 }, -{"lb", "t,A(b)", 0, (int) M_LB_AB, INSN_MACRO, I1 }, -{"lbu", "t,o(b)", 0x90000000, 0xfc000000, LDD|RD_b|WR_t, I1 }, -{"lbu", "t,A(b)", 0, (int) M_LBU_AB, INSN_MACRO, I1 }, -{"lca", "t,A(b)", 0, (int) M_LCA_AB, INSN_MACRO, I1 }, -{"ld", "t,o(b)", 0xdc000000, 0xfc000000, WR_t|RD_b, I3 }, -{"ld", "t,o(b)", 0, (int) M_LD_OB, INSN_MACRO, I1 }, -{"ld", "t,A(b)", 0, (int) M_LD_AB, INSN_MACRO, I1 }, -{"ldc1", "T,o(b)", 0xd4000000, 0xfc000000, CLD|RD_b|WR_T|FP_D, I2 }, -{"ldc1", "E,o(b)", 0xd4000000, 0xfc000000, CLD|RD_b|WR_T|FP_D, I2 }, -{"ldc1", "T,A(b)", 0, (int) M_LDC1_AB, INSN_MACRO, I2 }, -{"ldc1", "E,A(b)", 0, (int) M_LDC1_AB, INSN_MACRO, I2 }, -{"l.d", "T,o(b)", 0xd4000000, 0xfc000000, CLD|RD_b|WR_T|FP_D, I2 }, /* ldc1 */ -{"l.d", "T,o(b)", 0, (int) M_L_DOB, INSN_MACRO, I1 }, -{"l.d", "T,A(b)", 0, (int) M_L_DAB, INSN_MACRO, I1 }, -{"ldc2", "E,o(b)", 0xd8000000, 0xfc000000, CLD|RD_b|WR_CC, I2 }, -{"ldc2", "E,A(b)", 0, (int) M_LDC2_AB, INSN_MACRO, I2 }, -{"ldc3", "E,o(b)", 0xdc000000, 0xfc000000, CLD|RD_b|WR_CC, I2 }, -{"ldc3", "E,A(b)", 0, (int) M_LDC3_AB, INSN_MACRO, I2 }, -{"ldl", "t,o(b)", 0x68000000, 0xfc000000, LDD|WR_t|RD_b, I3 }, -{"ldl", "t,A(b)", 0, (int) M_LDL_AB, INSN_MACRO, I3 }, -{"ldr", "t,o(b)", 0x6c000000, 0xfc000000, LDD|WR_t|RD_b, I3 }, -{"ldr", "t,A(b)", 0, (int) M_LDR_AB, INSN_MACRO, I3 }, -{"ldxc1", "D,t(b)", 0x4c000001, 0xfc00f83f, LDD|WR_D|RD_t|RD_b, I4 }, -{"lh", "t,o(b)", 0x84000000, 0xfc000000, LDD|RD_b|WR_t, I1 }, -{"lh", "t,A(b)", 0, (int) M_LH_AB, INSN_MACRO, I1 }, -{"lhu", "t,o(b)", 0x94000000, 0xfc000000, LDD|RD_b|WR_t, I1 }, -{"lhu", "t,A(b)", 0, (int) M_LHU_AB, INSN_MACRO, I1 }, +{"jal", "a", 0x0c000000, 0xfc000000, UBD|WR_31, 0, I1 }, +{"jalx", "a", 0x74000000, 0xfc000000, UBD|WR_31, 0, I16 }, +{"la", "t,A(b)", 0, (int) M_LA_AB, INSN_MACRO, 0, I1 }, +{"lb", "t,o(b)", 0x80000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 }, +{"lb", "t,A(b)", 0, (int) M_LB_AB, INSN_MACRO, 0, I1 }, +{"lbu", "t,o(b)", 0x90000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 }, +{"lbu", "t,A(b)", 0, (int) M_LBU_AB, INSN_MACRO, 0, I1 }, +{"lca", "t,A(b)", 0, (int) M_LCA_AB, INSN_MACRO, 0, I1 }, +{"ld", "t,o(b)", 0xdc000000, 0xfc000000, WR_t|RD_b, 0, I3 }, +{"ld", "t,o(b)", 0, (int) M_LD_OB, INSN_MACRO, 0, I1 }, +{"ld", "t,A(b)", 0, (int) M_LD_AB, INSN_MACRO, 0, I1 }, +{"ldc1", "T,o(b)", 0xd4000000, 0xfc000000, CLD|RD_b|WR_T|FP_D, 0, I2 }, +{"ldc1", "E,o(b)", 0xd4000000, 0xfc000000, CLD|RD_b|WR_T|FP_D, 0, I2 }, +{"ldc1", "T,A(b)", 0, (int) M_LDC1_AB, INSN_MACRO, 0, I2 }, +{"ldc1", "E,A(b)", 0, (int) M_LDC1_AB, INSN_MACRO, 0, I2 }, +{"l.d", "T,o(b)", 0xd4000000, 0xfc000000, CLD|RD_b|WR_T|FP_D, 0, I2 }, /* ldc1 */ +{"l.d", "T,o(b)", 0, (int) M_L_DOB, INSN_MACRO, 0, I1 }, +{"l.d", "T,A(b)", 0, (int) M_L_DAB, INSN_MACRO, 0, I1 }, +{"ldc2", "E,o(b)", 0xd8000000, 0xfc000000, CLD|RD_b|WR_CC, 0, I2 }, +{"ldc2", "E,A(b)", 0, (int) M_LDC2_AB, INSN_MACRO, 0, I2 }, +{"ldc3", "E,o(b)", 0xdc000000, 0xfc000000, CLD|RD_b|WR_CC, 0, I2 }, +{"ldc3", "E,A(b)", 0, (int) M_LDC3_AB, INSN_MACRO, 0, I2 }, +{"ldl", "t,o(b)", 0x68000000, 0xfc000000, LDD|WR_t|RD_b, 0, I3 }, +{"ldl", "t,A(b)", 0, (int) M_LDL_AB, INSN_MACRO, 0, I3 }, +{"ldr", "t,o(b)", 0x6c000000, 0xfc000000, LDD|WR_t|RD_b, 0, I3 }, +{"ldr", "t,A(b)", 0, (int) M_LDR_AB, INSN_MACRO, 0, I3 }, +{"ldxc1", "D,t(b)", 0x4c000001, 0xfc00f83f, LDD|WR_D|RD_t|RD_b|FP_D, 0, I4|I33 }, +{"lh", "t,o(b)", 0x84000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 }, +{"lh", "t,A(b)", 0, (int) M_LH_AB, INSN_MACRO, 0, I1 }, +{"lhu", "t,o(b)", 0x94000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 }, +{"lhu", "t,A(b)", 0, (int) M_LHU_AB, INSN_MACRO, 0, I1 }, /* li is at the start of the table. */ -{"li.d", "t,F", 0, (int) M_LI_D, INSN_MACRO, I1 }, -{"li.d", "T,L", 0, (int) M_LI_DD, INSN_MACRO, I1 }, -{"li.s", "t,f", 0, (int) M_LI_S, INSN_MACRO, I1 }, -{"li.s", "T,l", 0, (int) M_LI_SS, INSN_MACRO, I1 }, -{"ll", "t,o(b)", 0xc0000000, 0xfc000000, LDD|RD_b|WR_t, I2 }, -{"ll", "t,A(b)", 0, (int) M_LL_AB, INSN_MACRO, I2 }, -{"lld", "t,o(b)", 0xd0000000, 0xfc000000, LDD|RD_b|WR_t, I3 }, -{"lld", "t,A(b)", 0, (int) M_LLD_AB, INSN_MACRO, I3 }, -{"lui", "t,u", 0x3c000000, 0xffe00000, WR_t, I1 }, -{"luxc1", "D,t(b)", 0x4c000005, 0xfc00f83f, LDD|WR_D|RD_t|RD_b, I5|N55 }, -{"lw", "t,o(b)", 0x8c000000, 0xfc000000, LDD|RD_b|WR_t, I1 }, -{"lw", "t,A(b)", 0, (int) M_LW_AB, INSN_MACRO, I1 }, -{"lwc0", "E,o(b)", 0xc0000000, 0xfc000000, CLD|RD_b|WR_CC, I1 }, -{"lwc0", "E,A(b)", 0, (int) M_LWC0_AB, INSN_MACRO, I1 }, -{"lwc1", "T,o(b)", 0xc4000000, 0xfc000000, CLD|RD_b|WR_T|FP_S, I1 }, -{"lwc1", "E,o(b)", 0xc4000000, 0xfc000000, CLD|RD_b|WR_T|FP_S, I1 }, -{"lwc1", "T,A(b)", 0, (int) M_LWC1_AB, INSN_MACRO, I1 }, -{"lwc1", "E,A(b)", 0, (int) M_LWC1_AB, INSN_MACRO, I1 }, -{"l.s", "T,o(b)", 0xc4000000, 0xfc000000, CLD|RD_b|WR_T|FP_S, I1 }, /* lwc1 */ -{"l.s", "T,A(b)", 0, (int) M_LWC1_AB, INSN_MACRO, I1 }, -{"lwc2", "E,o(b)", 0xc8000000, 0xfc000000, CLD|RD_b|WR_CC, I1 }, -{"lwc2", "E,A(b)", 0, (int) M_LWC2_AB, INSN_MACRO, I1 }, -{"lwc3", "E,o(b)", 0xcc000000, 0xfc000000, CLD|RD_b|WR_CC, I1 }, -{"lwc3", "E,A(b)", 0, (int) M_LWC3_AB, INSN_MACRO, I1 }, -{"lwl", "t,o(b)", 0x88000000, 0xfc000000, LDD|RD_b|WR_t, I1 }, -{"lwl", "t,A(b)", 0, (int) M_LWL_AB, INSN_MACRO, I1 }, -{"lcache", "t,o(b)", 0x88000000, 0xfc000000, LDD|RD_b|WR_t, I2 }, /* same */ -{"lcache", "t,A(b)", 0, (int) M_LWL_AB, INSN_MACRO, I2 }, /* as lwl */ -{"lwr", "t,o(b)", 0x98000000, 0xfc000000, LDD|RD_b|WR_t, I1 }, -{"lwr", "t,A(b)", 0, (int) M_LWR_AB, INSN_MACRO, I1 }, -{"flush", "t,o(b)", 0x98000000, 0xfc000000, LDD|RD_b|WR_t, I2 }, /* same */ -{"flush", "t,A(b)", 0, (int) M_LWR_AB, INSN_MACRO, I2 }, /* as lwr */ -{"lwu", "t,o(b)", 0x9c000000, 0xfc000000, LDD|RD_b|WR_t, I3 }, -{"lwu", "t,A(b)", 0, (int) M_LWU_AB, INSN_MACRO, I3 }, -{"lwxc1", "D,t(b)", 0x4c000000, 0xfc00f83f, LDD|WR_D|RD_t|RD_b, I4 }, -{"macc", "d,s,t", 0x00000028, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N412 }, -{"macc", "d,s,t", 0x00000158, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N5 }, -{"maccs", "d,s,t", 0x00000428, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N412 }, -{"macchi", "d,s,t", 0x00000228, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N412 }, -{"macchi", "d,s,t", 0x00000358, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N5 }, -{"macchis", "d,s,t", 0x00000628, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N412 }, -{"macchiu", "d,s,t", 0x00000268, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N412 }, -{"macchiu", "d,s,t", 0x00000359, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N5 }, -{"macchius","d,s,t", 0x00000668, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N412 }, -{"maccu", "d,s,t", 0x00000068, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N412 }, -{"maccu", "d,s,t", 0x00000159, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N5 }, -{"maccus", "d,s,t", 0x00000468, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N412 }, -{"mad", "s,t", 0x70000000, 0xfc00ffff, RD_s|RD_t|MOD_HILO, P3 }, -{"madu", "s,t", 0x70000001, 0xfc00ffff, RD_s|RD_t|MOD_HILO, P3 }, -{"madd.d", "D,R,S,T", 0x4c000021, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, I4 }, -{"madd.s", "D,R,S,T", 0x4c000020, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_S, I4 }, -{"madd.ps", "D,R,S,T", 0x4c000026, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, I5 }, -{"madd", "s,t", 0x0000001c, 0xfc00ffff, RD_s|RD_t|WR_HILO, L1 }, -{"madd", "s,t", 0x70000000, 0xfc00ffff, RD_s|RD_t|MOD_HILO, I32|N55}, -{"madd", "s,t", 0x70000000, 0xfc00ffff, RD_s|RD_t|WR_HILO|IS_M, G1 }, -{"madd", "d,s,t", 0x70000000, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d|IS_M, G1 }, -{"maddu", "s,t", 0x0000001d, 0xfc00ffff, RD_s|RD_t|WR_HILO, L1 }, -{"maddu", "s,t", 0x70000001, 0xfc00ffff, RD_s|RD_t|MOD_HILO, I32|N55}, -{"maddu", "s,t", 0x70000001, 0xfc00ffff, RD_s|RD_t|WR_HILO|IS_M, G1 }, -{"maddu", "d,s,t", 0x70000001, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d|IS_M, G1 }, -{"madd16", "s,t", 0x00000028, 0xfc00ffff, RD_s|RD_t|MOD_HILO, N411 }, -{"max.ob", "X,Y,Q", 0x78000007, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"max.ob", "D,S,T", 0x4ac00007, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"max.ob", "D,S,T[e]", 0x48000007, 0xfe20003f, WR_D|RD_S|RD_T, N54 }, -{"max.ob", "D,S,k", 0x4bc00007, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"max.qh", "X,Y,Q", 0x78200007, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"mfpc", "t,P", 0x4000c801, 0xffe0ffc1, LCD|WR_t|RD_C0, M1|N5 }, -{"mfps", "t,P", 0x4000c800, 0xffe0ffc1, LCD|WR_t|RD_C0, M1|N5 }, -{"mfc0", "t,G", 0x40000000, 0xffe007ff, LCD|WR_t|RD_C0, I1 }, -{"mfc0", "t,+D", 0x40000000, 0xffe007f8, LCD|WR_t|RD_C0, I32 }, -{"mfc0", "t,G,H", 0x40000000, 0xffe007f8, LCD|WR_t|RD_C0, I32 }, -{"mfc1", "t,S", 0x44000000, 0xffe007ff, LCD|WR_t|RD_S|FP_S, I1 }, -{"mfc1", "t,G", 0x44000000, 0xffe007ff, LCD|WR_t|RD_S|FP_S, I1 }, -{"mfhc1", "t,S", 0x44600000, 0xffe007ff, LCD|WR_t|RD_S|FP_S, I33 }, -{"mfhc1", "t,G", 0x44600000, 0xffe007ff, LCD|WR_t|RD_S|FP_S, I33 }, -{"mfc2", "t,G", 0x48000000, 0xffe007ff, LCD|WR_t|RD_C2, I1 }, -{"mfc2", "t,G,H", 0x48000000, 0xffe007f8, LCD|WR_t|RD_C2, I32 }, -{"mfhc2", "t,i", 0x48600000, 0xffe00000, LCD|WR_t|RD_C2, I33 }, -{"mfc3", "t,G", 0x4c000000, 0xffe007ff, LCD|WR_t|RD_C3, I1 }, -{"mfc3", "t,G,H", 0x4c000000, 0xffe007f8, LCD|WR_t|RD_C3, I32 }, -{"mfdr", "t,G", 0x7000003d, 0xffe007ff, LCD|WR_t|RD_C0, N5 }, -{"mfhi", "d", 0x00000010, 0xffff07ff, WR_d|RD_HI, I1 }, -{"mflo", "d", 0x00000012, 0xffff07ff, WR_d|RD_LO, I1 }, -{"min.ob", "X,Y,Q", 0x78000006, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"min.ob", "D,S,T", 0x4ac00006, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"min.ob", "D,S,T[e]", 0x48000006, 0xfe20003f, WR_D|RD_S|RD_T, N54 }, -{"min.ob", "D,S,k", 0x4bc00006, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"min.qh", "X,Y,Q", 0x78200006, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"mov.d", "D,S", 0x46200006, 0xffff003f, WR_D|RD_S|FP_D, I1 }, -{"mov.s", "D,S", 0x46000006, 0xffff003f, WR_D|RD_S|FP_S, I1 }, -{"mov.ps", "D,S", 0x46c00006, 0xffff003f, WR_D|RD_S|FP_D, I5 }, -{"movf", "d,s,N", 0x00000001, 0xfc0307ff, WR_d|RD_s|RD_CC|FP_D|FP_S, I4|I32}, -{"movf.d", "D,S,N", 0x46200011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, I4|I32 }, -{"movf.l", "D,S,N", 0x46a00011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, MX|SB1 }, -{"movf.l", "X,Y,N", 0x46a00011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, MX|SB1 }, -{"movf.s", "D,S,N", 0x46000011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_S, I4|I32 }, -{"movf.ps", "D,S,N", 0x46c00011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, I5 }, -{"movn", "d,v,t", 0x0000000b, 0xfc0007ff, WR_d|RD_s|RD_t, I4|I32 }, -{"ffc", "d,v", 0x0000000b, 0xfc1f07ff, WR_d|RD_s, L1 }, -{"movn.d", "D,S,t", 0x46200013, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, I4|I32 }, -{"movn.l", "D,S,t", 0x46a00013, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, MX|SB1 }, -{"movn.l", "X,Y,t", 0x46a00013, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, MX|SB1 }, -{"movn.s", "D,S,t", 0x46000013, 0xffe0003f, WR_D|RD_S|RD_t|FP_S, I4|I32 }, -{"movn.ps", "D,S,t", 0x46c00013, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, I5 }, -{"movt", "d,s,N", 0x00010001, 0xfc0307ff, WR_d|RD_s|RD_CC, I4|I32 }, -{"movt.d", "D,S,N", 0x46210011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, I4|I32 }, -{"movt.l", "D,S,N", 0x46a10011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, MX|SB1 }, -{"movt.l", "X,Y,N", 0x46a10011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, MX|SB1 }, -{"movt.s", "D,S,N", 0x46010011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_S, I4|I32 }, -{"movt.ps", "D,S,N", 0x46c10011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, I5 }, -{"movz", "d,v,t", 0x0000000a, 0xfc0007ff, WR_d|RD_s|RD_t, I4|I32 }, -{"ffs", "d,v", 0x0000000a, 0xfc1f07ff, WR_d|RD_s, L1 }, -{"movz.d", "D,S,t", 0x46200012, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, I4|I32 }, -{"movz.l", "D,S,t", 0x46a00012, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, MX|SB1 }, -{"movz.l", "X,Y,t", 0x46a00012, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, MX|SB1 }, -{"movz.s", "D,S,t", 0x46000012, 0xffe0003f, WR_D|RD_S|RD_t|FP_S, I4|I32 }, -{"movz.ps", "D,S,t", 0x46c00012, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, I5 }, -{"msac", "d,s,t", 0x000001d8, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N5 }, -{"msacu", "d,s,t", 0x000001d9, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N5 }, -{"msachi", "d,s,t", 0x000003d8, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N5 }, -{"msachiu", "d,s,t", 0x000003d9, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N5 }, +{"li.d", "t,F", 0, (int) M_LI_D, INSN_MACRO, 0, I1 }, +{"li.d", "T,L", 0, (int) M_LI_DD, INSN_MACRO, 0, I1 }, +{"li.s", "t,f", 0, (int) M_LI_S, INSN_MACRO, 0, I1 }, +{"li.s", "T,l", 0, (int) M_LI_SS, INSN_MACRO, 0, I1 }, +{"ll", "t,o(b)", 0xc0000000, 0xfc000000, LDD|RD_b|WR_t, 0, I2 }, +{"ll", "t,A(b)", 0, (int) M_LL_AB, INSN_MACRO, 0, I2 }, +{"lld", "t,o(b)", 0xd0000000, 0xfc000000, LDD|RD_b|WR_t, 0, I3 }, +{"lld", "t,A(b)", 0, (int) M_LLD_AB, INSN_MACRO, 0, I3 }, +{"lui", "t,u", 0x3c000000, 0xffe00000, WR_t, 0, I1 }, +{"luxc1", "D,t(b)", 0x4c000005, 0xfc00f83f, LDD|WR_D|RD_t|RD_b, 0, I5|N55 }, +{"lw", "t,o(b)", 0x8c000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 }, +{"lw", "t,A(b)", 0, (int) M_LW_AB, INSN_MACRO, 0, I1 }, +{"lwc0", "E,o(b)", 0xc0000000, 0xfc000000, CLD|RD_b|WR_CC, 0, I1 }, +{"lwc0", "E,A(b)", 0, (int) M_LWC0_AB, INSN_MACRO, 0, I1 }, +{"lwc1", "T,o(b)", 0xc4000000, 0xfc000000, CLD|RD_b|WR_T|FP_S, 0, I1 }, +{"lwc1", "E,o(b)", 0xc4000000, 0xfc000000, CLD|RD_b|WR_T|FP_S, 0, I1 }, +{"lwc1", "T,A(b)", 0, (int) M_LWC1_AB, INSN_MACRO, 0, I1 }, +{"lwc1", "E,A(b)", 0, (int) M_LWC1_AB, INSN_MACRO, 0, I1 }, +{"l.s", "T,o(b)", 0xc4000000, 0xfc000000, CLD|RD_b|WR_T|FP_S, 0, I1 }, /* lwc1 */ +{"l.s", "T,A(b)", 0, (int) M_LWC1_AB, INSN_MACRO, 0, I1 }, +{"lwc2", "E,o(b)", 0xc8000000, 0xfc000000, CLD|RD_b|WR_CC, 0, I1 }, +{"lwc2", "E,A(b)", 0, (int) M_LWC2_AB, INSN_MACRO, 0, I1 }, +{"lwc3", "E,o(b)", 0xcc000000, 0xfc000000, CLD|RD_b|WR_CC, 0, I1 }, +{"lwc3", "E,A(b)", 0, (int) M_LWC3_AB, INSN_MACRO, 0, I1 }, +{"lwl", "t,o(b)", 0x88000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 }, +{"lwl", "t,A(b)", 0, (int) M_LWL_AB, INSN_MACRO, 0, I1 }, +{"lcache", "t,o(b)", 0x88000000, 0xfc000000, LDD|RD_b|WR_t, 0, I2 }, /* same */ +{"lcache", "t,A(b)", 0, (int) M_LWL_AB, INSN_MACRO, 0, I2 }, /* as lwl */ +{"lwr", "t,o(b)", 0x98000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 }, +{"lwr", "t,A(b)", 0, (int) M_LWR_AB, INSN_MACRO, 0, I1 }, +{"flush", "t,o(b)", 0x98000000, 0xfc000000, LDD|RD_b|WR_t, 0, I2 }, /* same */ +{"flush", "t,A(b)", 0, (int) M_LWR_AB, INSN_MACRO, 0, I2 }, /* as lwr */ +{"fork", "d,s,t", 0x7c000008, 0xfc0007ff, TRAP|WR_d|RD_s|RD_t, 0, MT32 }, +{"lwu", "t,o(b)", 0x9c000000, 0xfc000000, LDD|RD_b|WR_t, 0, I3 }, +{"lwu", "t,A(b)", 0, (int) M_LWU_AB, INSN_MACRO, 0, I3 }, +{"lwxc1", "D,t(b)", 0x4c000000, 0xfc00f83f, LDD|WR_D|RD_t|RD_b|FP_D, 0, I4|I33 }, +{"macc", "d,s,t", 0x00000028, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, +{"macc", "d,s,t", 0x00000158, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, +{"maccs", "d,s,t", 0x00000428, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, +{"macchi", "d,s,t", 0x00000228, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, +{"macchi", "d,s,t", 0x00000358, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, +{"macchis", "d,s,t", 0x00000628, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, +{"macchiu", "d,s,t", 0x00000268, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, +{"macchiu", "d,s,t", 0x00000359, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, +{"macchius","d,s,t", 0x00000668, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, +{"maccu", "d,s,t", 0x00000068, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, +{"maccu", "d,s,t", 0x00000159, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, +{"maccus", "d,s,t", 0x00000468, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, +{"mad", "s,t", 0x70000000, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, P3 }, +{"madu", "s,t", 0x70000001, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, P3 }, +{"madd.d", "D,R,S,T", 0x4c000021, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, 0, I4|I33 }, +{"madd.s", "D,R,S,T", 0x4c000020, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_S, 0, I4|I33 }, +{"madd.ps", "D,R,S,T", 0x4c000026, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, 0, I5 }, +{"madd", "s,t", 0x0000001c, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, L1 }, +{"madd", "s,t", 0x70000000, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, I32|N55}, +{"madd", "s,t", 0x70000000, 0xfc00ffff, RD_s|RD_t|WR_HILO|IS_M, 0, G1 }, +{"madd", "d,s,t", 0x70000000, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d|IS_M, 0, G1 }, +{"maddu", "s,t", 0x0000001d, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, L1 }, +{"maddu", "s,t", 0x70000001, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, I32|N55}, +{"maddu", "s,t", 0x70000001, 0xfc00ffff, RD_s|RD_t|WR_HILO|IS_M, 0, G1 }, +{"maddu", "d,s,t", 0x70000001, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d|IS_M, 0, G1 }, +{"madd16", "s,t", 0x00000028, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, N411 }, +{"max.ob", "X,Y,Q", 0x78000007, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"max.ob", "D,S,T", 0x4ac00007, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"max.ob", "D,S,T[e]", 0x48000007, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, +{"max.ob", "D,S,k", 0x4bc00007, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"max.qh", "X,Y,Q", 0x78200007, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"mfpc", "t,P", 0x4000c801, 0xffe0ffc1, LCD|WR_t|RD_C0, 0, M1|N5 }, +{"mfps", "t,P", 0x4000c800, 0xffe0ffc1, LCD|WR_t|RD_C0, 0, M1|N5 }, +{"mftacx", "d", 0x41020021, 0xffff07ff, TRAP|WR_d|RD_a, 0, MT32 }, +{"mftacx", "d,*", 0x41020021, 0xfff307ff, TRAP|WR_d|RD_a, 0, MT32 }, +{"mftc0", "d,+t", 0x41000000, 0xffe007ff, TRAP|LCD|WR_d|RD_C0, 0, MT32 }, +{"mftc0", "d,+T", 0x41000000, 0xffe007f8, TRAP|LCD|WR_d|RD_C0, 0, MT32 }, +{"mftc0", "d,E,H", 0x41000000, 0xffe007f8, TRAP|LCD|WR_d|RD_C0, 0, MT32 }, +{"mftc1", "d,T", 0x41000022, 0xffe007ff, TRAP|LCD|WR_d|RD_T|FP_S, 0, MT32 }, +{"mftc1", "d,E", 0x41000022, 0xffe007ff, TRAP|LCD|WR_d|RD_T|FP_S, 0, MT32 }, +{"mftc2", "d,E", 0x41000024, 0xffe007ff, TRAP|LCD|WR_d|RD_C2, 0, MT32 }, +{"mftdsp", "d", 0x41100021, 0xffff07ff, TRAP|WR_d, 0, MT32 }, +{"mftgpr", "d,t", 0x41000020, 0xffe007ff, TRAP|WR_d|RD_t, 0, MT32 }, +{"mfthc1", "d,T", 0x41000032, 0xffe007ff, TRAP|LCD|WR_d|RD_T|FP_D, 0, MT32 }, +{"mfthc1", "d,E", 0x41000032, 0xffe007ff, TRAP|LCD|WR_d|RD_T|FP_D, 0, MT32 }, +{"mfthc2", "d,E", 0x41000034, 0xffe007ff, TRAP|LCD|WR_d|RD_C2, 0, MT32 }, +{"mfthi", "d", 0x41010021, 0xffff07ff, TRAP|WR_d|RD_a, 0, MT32 }, +{"mfthi", "d,*", 0x41010021, 0xfff307ff, TRAP|WR_d|RD_a, 0, MT32 }, +{"mftlo", "d", 0x41000021, 0xffff07ff, TRAP|WR_d|RD_a, 0, MT32 }, +{"mftlo", "d,*", 0x41000021, 0xfff307ff, TRAP|WR_d|RD_a, 0, MT32 }, +{"mftr", "d,t,!,H,$", 0x41000000, 0xffe007c8, TRAP|WR_d, 0, MT32 }, +{"mfc0", "t,G", 0x40000000, 0xffe007ff, LCD|WR_t|RD_C0, 0, I1 }, +{"mfc0", "t,+D", 0x40000000, 0xffe007f8, LCD|WR_t|RD_C0, 0, I32 }, +{"mfc0", "t,G,H", 0x40000000, 0xffe007f8, LCD|WR_t|RD_C0, 0, I32 }, +{"mfc1", "t,S", 0x44000000, 0xffe007ff, LCD|WR_t|RD_S|FP_S, 0, I1 }, +{"mfc1", "t,G", 0x44000000, 0xffe007ff, LCD|WR_t|RD_S|FP_S, 0, I1 }, +{"mfhc1", "t,S", 0x44600000, 0xffe007ff, LCD|WR_t|RD_S|FP_D, 0, I33 }, +{"mfhc1", "t,G", 0x44600000, 0xffe007ff, LCD|WR_t|RD_S|FP_D, 0, I33 }, +/* mfc2 is at the bottom of the table. */ +/* mfhc2 is at the bottom of the table. */ +{"mfc3", "t,G", 0x4c000000, 0xffe007ff, LCD|WR_t|RD_C3, 0, I1 }, +{"mfc3", "t,G,H", 0x4c000000, 0xffe007f8, LCD|WR_t|RD_C3, 0, I32 }, +{"mfdr", "t,G", 0x7000003d, 0xffe007ff, LCD|WR_t|RD_C0, 0, N5 }, +{"mfhi", "d", 0x00000010, 0xffff07ff, WR_d|RD_HI, 0, I1 }, +{"mfhi", "d,9", 0x00000010, 0xff9f07ff, WR_d|RD_HI, 0, D32 }, +{"mflo", "d", 0x00000012, 0xffff07ff, WR_d|RD_LO, 0, I1 }, +{"mflo", "d,9", 0x00000012, 0xff9f07ff, WR_d|RD_LO, 0, D32 }, +{"min.ob", "X,Y,Q", 0x78000006, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"min.ob", "D,S,T", 0x4ac00006, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"min.ob", "D,S,T[e]", 0x48000006, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, +{"min.ob", "D,S,k", 0x4bc00006, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"min.qh", "X,Y,Q", 0x78200006, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"mov.d", "D,S", 0x46200006, 0xffff003f, WR_D|RD_S|FP_D, 0, I1 }, +{"mov.s", "D,S", 0x46000006, 0xffff003f, WR_D|RD_S|FP_S, 0, I1 }, +{"mov.ps", "D,S", 0x46c00006, 0xffff003f, WR_D|RD_S|FP_D, 0, I5 }, +{"movf", "d,s,N", 0x00000001, 0xfc0307ff, WR_d|RD_s|RD_CC|FP_S|FP_D, 0, I4|I32 }, +{"movf.d", "D,S,N", 0x46200011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, I4|I32 }, +{"movf.l", "D,S,N", 0x46a00011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, MX|SB1 }, +{"movf.l", "X,Y,N", 0x46a00011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, MX|SB1 }, +{"movf.s", "D,S,N", 0x46000011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_S, 0, I4|I32 }, +{"movf.ps", "D,S,N", 0x46c00011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, I5 }, +{"movn", "d,v,t", 0x0000000b, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I4|I32 }, +{"ffc", "d,v", 0x0000000b, 0xfc1f07ff, WR_d|RD_s, 0, L1 }, +{"movn.d", "D,S,t", 0x46200013, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, I4|I32 }, +{"movn.l", "D,S,t", 0x46a00013, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, MX|SB1 }, +{"movn.l", "X,Y,t", 0x46a00013, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, MX|SB1 }, +{"movn.s", "D,S,t", 0x46000013, 0xffe0003f, WR_D|RD_S|RD_t|FP_S, 0, I4|I32 }, +{"movn.ps", "D,S,t", 0x46c00013, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, I5 }, +{"movt", "d,s,N", 0x00010001, 0xfc0307ff, WR_d|RD_s|RD_CC|FP_S|FP_D, 0, I4|I32 }, +{"movt.d", "D,S,N", 0x46210011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, I4|I32 }, +{"movt.l", "D,S,N", 0x46a10011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, MX|SB1 }, +{"movt.l", "X,Y,N", 0x46a10011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, MX|SB1 }, +{"movt.s", "D,S,N", 0x46010011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_S, 0, I4|I32 }, +{"movt.ps", "D,S,N", 0x46c10011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, I5 }, +{"movz", "d,v,t", 0x0000000a, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I4|I32 }, +{"ffs", "d,v", 0x0000000a, 0xfc1f07ff, WR_d|RD_s, 0, L1 }, +{"movz.d", "D,S,t", 0x46200012, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, I4|I32 }, +{"movz.l", "D,S,t", 0x46a00012, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, MX|SB1 }, +{"movz.l", "X,Y,t", 0x46a00012, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, MX|SB1 }, +{"movz.s", "D,S,t", 0x46000012, 0xffe0003f, WR_D|RD_S|RD_t|FP_S, 0, I4|I32 }, +{"movz.ps", "D,S,t", 0x46c00012, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, I5 }, +{"msac", "d,s,t", 0x000001d8, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, +{"msacu", "d,s,t", 0x000001d9, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, +{"msachi", "d,s,t", 0x000003d8, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, +{"msachiu", "d,s,t", 0x000003d9, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, /* move is at the top of the table. */ -{"msgn.qh", "X,Y,Q", 0x78200000, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"msub.d", "D,R,S,T", 0x4c000029, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, I4 }, -{"msub.s", "D,R,S,T", 0x4c000028, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_S, I4 }, -{"msub.ps", "D,R,S,T", 0x4c00002e, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, I5 }, -{"msub", "s,t", 0x0000001e, 0xfc00ffff, RD_s|RD_t|WR_HILO, L1 }, -{"msub", "s,t", 0x70000004, 0xfc00ffff, RD_s|RD_t|MOD_HILO, I32|N55 }, -{"msubu", "s,t", 0x0000001f, 0xfc00ffff, RD_s|RD_t|WR_HILO, L1 }, -{"msubu", "s,t", 0x70000005, 0xfc00ffff, RD_s|RD_t|MOD_HILO, I32|N55 }, -{"mtpc", "t,P", 0x4080c801, 0xffe0ffc1, COD|RD_t|WR_C0, M1|N5 }, -{"mtps", "t,P", 0x4080c800, 0xffe0ffc1, COD|RD_t|WR_C0, M1|N5 }, -{"mtc0", "t,G", 0x40800000, 0xffe007ff, COD|RD_t|WR_C0|WR_CC, I1 }, -{"mtc0", "t,+D", 0x40800000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC, I32 }, -{"mtc0", "t,G,H", 0x40800000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC, I32 }, -{"mtc1", "t,S", 0x44800000, 0xffe007ff, COD|RD_t|WR_S|FP_S, I1 }, -{"mtc1", "t,G", 0x44800000, 0xffe007ff, COD|RD_t|WR_S|FP_S, I1 }, -{"mthc1", "t,S", 0x44e00000, 0xffe007ff, COD|RD_t|WR_S|FP_S, I33 }, -{"mthc1", "t,G", 0x44e00000, 0xffe007ff, COD|RD_t|WR_S|FP_S, I33 }, -{"mtc2", "t,G", 0x48800000, 0xffe007ff, COD|RD_t|WR_C2|WR_CC, I1 }, -{"mtc2", "t,G,H", 0x48800000, 0xffe007f8, COD|RD_t|WR_C2|WR_CC, I32 }, -{"mthc2", "t,i", 0x48e00000, 0xffe00000, COD|RD_t|WR_C2|WR_CC, I33 }, -{"mtc3", "t,G", 0x4c800000, 0xffe007ff, COD|RD_t|WR_C3|WR_CC, I1 }, -{"mtc3", "t,G,H", 0x4c800000, 0xffe007f8, COD|RD_t|WR_C3|WR_CC, I32 }, -{"mtdr", "t,G", 0x7080003d, 0xffe007ff, COD|RD_t|WR_C0, N5 }, -{"mthi", "s", 0x00000011, 0xfc1fffff, RD_s|WR_HI, I1 }, -{"mtlo", "s", 0x00000013, 0xfc1fffff, RD_s|WR_LO, I1 }, -{"mul.d", "D,V,T", 0x46200002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, I1 }, -{"mul.s", "D,V,T", 0x46000002, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, I1 }, -{"mul.ob", "X,Y,Q", 0x78000030, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"mul.ob", "D,S,T", 0x4ac00030, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"mul.ob", "D,S,T[e]", 0x48000030, 0xfe20003f, WR_D|RD_S|RD_T, N54 }, -{"mul.ob", "D,S,k", 0x4bc00030, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"mul.ps", "D,V,T", 0x46c00002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, I5 }, -{"mul.qh", "X,Y,Q", 0x78200030, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"mul", "d,v,t", 0x70000002, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, I32|P3|N55}, -{"mul", "d,s,t", 0x00000058, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N54 }, -{"mul", "d,v,t", 0, (int) M_MUL, INSN_MACRO, I1 }, -{"mul", "d,v,I", 0, (int) M_MUL_I, INSN_MACRO, I1 }, -{"mula.ob", "Y,Q", 0x78000033, 0xfc2007ff, WR_MACC|RD_S|RD_T|FP_D, MX|SB1 }, -{"mula.ob", "S,T", 0x4ac00033, 0xffe007ff, WR_CC|RD_S|RD_T, N54 }, -{"mula.ob", "S,T[e]", 0x48000033, 0xfe2007ff, WR_CC|RD_S|RD_T, N54 }, -{"mula.ob", "S,k", 0x4bc00033, 0xffe007ff, WR_CC|RD_S|RD_T, N54 }, -{"mula.qh", "Y,Q", 0x78200033, 0xfc2007ff, WR_MACC|RD_S|RD_T|FP_D, MX }, -{"mulhi", "d,s,t", 0x00000258, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N5 }, -{"mulhiu", "d,s,t", 0x00000259, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N5 }, -{"mull.ob", "Y,Q", 0x78000433, 0xfc2007ff, WR_MACC|RD_S|RD_T|FP_D, MX|SB1 }, -{"mull.ob", "S,T", 0x4ac00433, 0xffe007ff, WR_CC|RD_S|RD_T, N54 }, -{"mull.ob", "S,T[e]", 0x48000433, 0xfe2007ff, WR_CC|RD_S|RD_T, N54 }, -{"mull.ob", "S,k", 0x4bc00433, 0xffe007ff, WR_CC|RD_S|RD_T, N54 }, -{"mull.qh", "Y,Q", 0x78200433, 0xfc2007ff, WR_MACC|RD_S|RD_T|FP_D, MX }, -{"mulo", "d,v,t", 0, (int) M_MULO, INSN_MACRO, I1 }, -{"mulo", "d,v,I", 0, (int) M_MULO_I, INSN_MACRO, I1 }, -{"mulou", "d,v,t", 0, (int) M_MULOU, INSN_MACRO, I1 }, -{"mulou", "d,v,I", 0, (int) M_MULOU_I, INSN_MACRO, I1 }, -{"mulr.ps", "D,S,T", 0x46c0001a, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, M3D }, -{"muls", "d,s,t", 0x000000d8, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N5 }, -{"mulsu", "d,s,t", 0x000000d9, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N5 }, -{"mulshi", "d,s,t", 0x000002d8, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N5 }, -{"mulshiu", "d,s,t", 0x000002d9, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N5 }, -{"muls.ob", "Y,Q", 0x78000032, 0xfc2007ff, WR_MACC|RD_S|RD_T|FP_D, MX|SB1 }, -{"muls.ob", "S,T", 0x4ac00032, 0xffe007ff, WR_CC|RD_S|RD_T, N54 }, -{"muls.ob", "S,T[e]", 0x48000032, 0xfe2007ff, WR_CC|RD_S|RD_T, N54 }, -{"muls.ob", "S,k", 0x4bc00032, 0xffe007ff, WR_CC|RD_S|RD_T, N54 }, -{"muls.qh", "Y,Q", 0x78200032, 0xfc2007ff, WR_MACC|RD_S|RD_T|FP_D, MX }, -{"mulsl.ob", "Y,Q", 0x78000432, 0xfc2007ff, WR_MACC|RD_S|RD_T|FP_D, MX|SB1 }, -{"mulsl.ob", "S,T", 0x4ac00432, 0xffe007ff, WR_CC|RD_S|RD_T, N54 }, -{"mulsl.ob", "S,T[e]", 0x48000432, 0xfe2007ff, WR_CC|RD_S|RD_T, N54 }, -{"mulsl.ob", "S,k", 0x4bc00432, 0xffe007ff, WR_CC|RD_S|RD_T, N54 }, -{"mulsl.qh", "Y,Q", 0x78200432, 0xfc2007ff, WR_MACC|RD_S|RD_T|FP_D, MX }, -{"mult", "s,t", 0x00000018, 0xfc00ffff, RD_s|RD_t|WR_HILO|IS_M, I1 }, -{"mult", "d,s,t", 0x00000018, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d|IS_M, G1 }, -{"multu", "s,t", 0x00000019, 0xfc00ffff, RD_s|RD_t|WR_HILO|IS_M, I1 }, -{"multu", "d,s,t", 0x00000019, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d|IS_M, G1 }, -{"mulu", "d,s,t", 0x00000059, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, N5 }, -{"neg", "d,w", 0x00000022, 0xffe007ff, WR_d|RD_t, I1 }, /* sub 0 */ -{"negu", "d,w", 0x00000023, 0xffe007ff, WR_d|RD_t, I1 }, /* subu 0 */ -{"neg.d", "D,V", 0x46200007, 0xffff003f, WR_D|RD_S|FP_D, I1 }, -{"neg.s", "D,V", 0x46000007, 0xffff003f, WR_D|RD_S|FP_S, I1 }, -{"neg.ps", "D,V", 0x46c00007, 0xffff003f, WR_D|RD_S|FP_D, I5 }, -{"nmadd.d", "D,R,S,T", 0x4c000031, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, I4 }, -{"nmadd.s", "D,R,S,T", 0x4c000030, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_S, I4 }, -{"nmadd.ps","D,R,S,T", 0x4c000036, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, I5 }, -{"nmsub.d", "D,R,S,T", 0x4c000039, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, I4 }, -{"nmsub.s", "D,R,S,T", 0x4c000038, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_S, I4 }, -{"nmsub.ps","D,R,S,T", 0x4c00003e, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, I5 }, +{"msgn.qh", "X,Y,Q", 0x78200000, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"msub.d", "D,R,S,T", 0x4c000029, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, 0, I4|I33 }, +{"msub.s", "D,R,S,T", 0x4c000028, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_S, 0, I4|I33 }, +{"msub.ps", "D,R,S,T", 0x4c00002e, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, 0, I5 }, +{"msub", "s,t", 0x0000001e, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, L1 }, +{"msub", "s,t", 0x70000004, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, I32|N55 }, +{"msubu", "s,t", 0x0000001f, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, L1 }, +{"msubu", "s,t", 0x70000005, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, I32|N55 }, +{"mtpc", "t,P", 0x4080c801, 0xffe0ffc1, COD|RD_t|WR_C0, 0, M1|N5 }, +{"mtps", "t,P", 0x4080c800, 0xffe0ffc1, COD|RD_t|WR_C0, 0, M1|N5 }, +{"mtc0", "t,G", 0x40800000, 0xffe007ff, COD|RD_t|WR_C0|WR_CC, 0, I1 }, +{"mtc0", "t,+D", 0x40800000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC, 0, I32 }, +{"mtc0", "t,G,H", 0x40800000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC, 0, I32 }, +{"mtc1", "t,S", 0x44800000, 0xffe007ff, COD|RD_t|WR_S|FP_S, 0, I1 }, +{"mtc1", "t,G", 0x44800000, 0xffe007ff, COD|RD_t|WR_S|FP_S, 0, I1 }, +{"mthc1", "t,S", 0x44e00000, 0xffe007ff, COD|RD_t|WR_S|FP_D, 0, I33 }, +{"mthc1", "t,G", 0x44e00000, 0xffe007ff, COD|RD_t|WR_S|FP_D, 0, I33 }, +/* mtc2 is at the bottom of the table. */ +/* mthc2 is at the bottom of the table. */ +{"mtc3", "t,G", 0x4c800000, 0xffe007ff, COD|RD_t|WR_C3|WR_CC, 0, I1 }, +{"mtc3", "t,G,H", 0x4c800000, 0xffe007f8, COD|RD_t|WR_C3|WR_CC, 0, I32 }, +{"mtdr", "t,G", 0x7080003d, 0xffe007ff, COD|RD_t|WR_C0, 0, N5 }, +{"mthi", "s", 0x00000011, 0xfc1fffff, RD_s|WR_HI, 0, I1 }, +{"mthi", "s,7", 0x00000011, 0xfc1fe7ff, RD_s|WR_HI, 0, D32 }, +{"mtlo", "s", 0x00000013, 0xfc1fffff, RD_s|WR_LO, 0, I1 }, +{"mtlo", "s,7", 0x00000013, 0xfc1fe7ff, RD_s|WR_LO, 0, D32 }, +{"mtm0", "s", 0x70000008, 0xfc1fffff, RD_s, 0, IOCTEON }, +{"mtm1", "s", 0x7000000c, 0xfc1fffff, RD_s, 0, IOCTEON }, +{"mtm2", "s", 0x7000000d, 0xfc1fffff, RD_s, 0, IOCTEON }, +{"mtp0", "s", 0x70000009, 0xfc1fffff, RD_s, 0, IOCTEON }, +{"mtp1", "s", 0x7000000a, 0xfc1fffff, RD_s, 0, IOCTEON }, +{"mtp2", "s", 0x7000000b, 0xfc1fffff, RD_s, 0, IOCTEON }, +{"mttc0", "t,G", 0x41800000, 0xffe007ff, TRAP|COD|RD_t|WR_C0|WR_CC, 0, MT32 }, +{"mttc0", "t,+D", 0x41800000, 0xffe007f8, TRAP|COD|RD_t|WR_C0|WR_CC, 0, MT32 }, +{"mttc0", "t,G,H", 0x41800000, 0xffe007f8, TRAP|COD|RD_t|WR_C0|WR_CC, 0, MT32 }, +{"mttc1", "t,S", 0x41800022, 0xffe007ff, TRAP|COD|RD_t|WR_S|FP_S, 0, MT32 }, +{"mttc1", "t,G", 0x41800022, 0xffe007ff, TRAP|COD|RD_t|WR_S|FP_S, 0, MT32 }, +{"mttc2", "t,g", 0x41800024, 0xffe007ff, TRAP|COD|RD_t|WR_C2|WR_CC, 0, MT32 }, +{"mttacx", "t", 0x41801021, 0xffe0ffff, TRAP|WR_a|RD_t, 0, MT32 }, +{"mttacx", "t,&", 0x41801021, 0xffe09fff, TRAP|WR_a|RD_t, 0, MT32 }, +{"mttdsp", "t", 0x41808021, 0xffe0ffff, TRAP|RD_t, 0, MT32 }, +{"mttgpr", "t,d", 0x41800020, 0xffe007ff, TRAP|WR_d|RD_t, 0, MT32 }, +{"mtthc1", "t,S", 0x41800032, 0xffe007ff, TRAP|COD|RD_t|WR_S|FP_D, 0, MT32 }, +{"mtthc1", "t,G", 0x41800032, 0xffe007ff, TRAP|COD|RD_t|WR_S|FP_D, 0, MT32 }, +{"mtthc2", "t,g", 0x41800034, 0xffe007ff, TRAP|COD|RD_t|WR_C2|WR_CC, 0, MT32 }, +{"mtthi", "t", 0x41800821, 0xffe0ffff, TRAP|WR_a|RD_t, 0, MT32 }, +{"mtthi", "t,&", 0x41800821, 0xffe09fff, TRAP|WR_a|RD_t, 0, MT32 }, +{"mttlo", "t", 0x41800021, 0xffe0ffff, TRAP|WR_a|RD_t, 0, MT32 }, +{"mttlo", "t,&", 0x41800021, 0xffe09fff, TRAP|WR_a|RD_t, 0, MT32 }, +{"mttr", "t,d,!,H,$", 0x41800000, 0xffe007c8, TRAP|RD_t, 0, MT32 }, +{"mul.d", "D,V,T", 0x46200002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I1 }, +{"mul.s", "D,V,T", 0x46000002, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I1 }, +{"mul.ob", "X,Y,Q", 0x78000030, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"mul.ob", "D,S,T", 0x4ac00030, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"mul.ob", "D,S,T[e]", 0x48000030, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, +{"mul.ob", "D,S,k", 0x4bc00030, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"mul.ps", "D,V,T", 0x46c00002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I5 }, +{"mul.qh", "X,Y,Q", 0x78200030, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"mul", "d,v,t", 0x70000002, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, I32|P3|N55}, +{"mul", "d,s,t", 0x00000058, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N54 }, +{"mul", "d,v,t", 0, (int) M_MUL, INSN_MACRO, 0, I1 }, +{"mul", "d,v,I", 0, (int) M_MUL_I, INSN_MACRO, 0, I1 }, +{"mula.ob", "Y,Q", 0x78000033, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, +{"mula.ob", "S,T", 0x4ac00033, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"mula.ob", "S,T[e]", 0x48000033, 0xfe2007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"mula.ob", "S,k", 0x4bc00033, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"mula.qh", "Y,Q", 0x78200033, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, +{"mulhi", "d,s,t", 0x00000258, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, +{"mulhiu", "d,s,t", 0x00000259, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, +{"mull.ob", "Y,Q", 0x78000433, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, +{"mull.ob", "S,T", 0x4ac00433, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"mull.ob", "S,T[e]", 0x48000433, 0xfe2007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"mull.ob", "S,k", 0x4bc00433, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"mull.qh", "Y,Q", 0x78200433, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, +{"mulo", "d,v,t", 0, (int) M_MULO, INSN_MACRO, 0, I1 }, +{"mulo", "d,v,I", 0, (int) M_MULO_I, INSN_MACRO, 0, I1 }, +{"mulou", "d,v,t", 0, (int) M_MULOU, INSN_MACRO, 0, I1 }, +{"mulou", "d,v,I", 0, (int) M_MULOU_I, INSN_MACRO, 0, I1 }, +{"mulr.ps", "D,S,T", 0x46c0001a, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, M3D }, +{"muls", "d,s,t", 0x000000d8, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, +{"mulsu", "d,s,t", 0x000000d9, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, +{"mulshi", "d,s,t", 0x000002d8, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, +{"mulshiu", "d,s,t", 0x000002d9, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, +{"muls.ob", "Y,Q", 0x78000032, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, +{"muls.ob", "S,T", 0x4ac00032, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"muls.ob", "S,T[e]", 0x48000032, 0xfe2007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"muls.ob", "S,k", 0x4bc00032, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"muls.qh", "Y,Q", 0x78200032, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, +{"mulsl.ob", "Y,Q", 0x78000432, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, +{"mulsl.ob", "S,T", 0x4ac00432, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"mulsl.ob", "S,T[e]", 0x48000432, 0xfe2007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"mulsl.ob", "S,k", 0x4bc00432, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, +{"mulsl.qh", "Y,Q", 0x78200432, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, +{"mult", "s,t", 0x00000018, 0xfc00ffff, RD_s|RD_t|WR_HILO|IS_M, 0, I1 }, +{"mult", "d,s,t", 0x00000018, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d|IS_M, 0, G1 }, +{"multu", "s,t", 0x00000019, 0xfc00ffff, RD_s|RD_t|WR_HILO|IS_M, 0, I1 }, +{"multu", "d,s,t", 0x00000019, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d|IS_M, 0, G1 }, +{"mulu", "d,s,t", 0x00000059, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, +{"neg", "d,w", 0x00000022, 0xffe007ff, WR_d|RD_t, 0, I1 }, /* sub 0 */ +{"negu", "d,w", 0x00000023, 0xffe007ff, WR_d|RD_t, 0, I1 }, /* subu 0 */ +{"neg.d", "D,V", 0x46200007, 0xffff003f, WR_D|RD_S|FP_D, 0, I1 }, +{"neg.s", "D,V", 0x46000007, 0xffff003f, WR_D|RD_S|FP_S, 0, I1 }, +{"neg.ps", "D,V", 0x46c00007, 0xffff003f, WR_D|RD_S|FP_D, 0, I5 }, +{"nmadd.d", "D,R,S,T", 0x4c000031, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, 0, I4|I33 }, +{"nmadd.s", "D,R,S,T", 0x4c000030, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_S, 0, I4|I33 }, +{"nmadd.ps","D,R,S,T", 0x4c000036, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, 0, I5 }, +{"nmsub.d", "D,R,S,T", 0x4c000039, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, 0, I4|I33 }, +{"nmsub.s", "D,R,S,T", 0x4c000038, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_S, 0, I4|I33 }, +{"nmsub.ps","D,R,S,T", 0x4c00003e, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, 0, I5 }, /* nop is at the start of the table. */ -{"nor", "d,v,t", 0x00000027, 0xfc0007ff, WR_d|RD_s|RD_t, I1 }, -{"nor", "t,r,I", 0, (int) M_NOR_I, INSN_MACRO, I1 }, -{"nor.ob", "X,Y,Q", 0x7800000f, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"nor.ob", "D,S,T", 0x4ac0000f, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"nor.ob", "D,S,T[e]", 0x4800000f, 0xfe20003f, WR_D|RD_S|RD_T, N54 }, -{"nor.ob", "D,S,k", 0x4bc0000f, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"nor.qh", "X,Y,Q", 0x7820000f, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"not", "d,v", 0x00000027, 0xfc1f07ff, WR_d|RD_s|RD_t, I1 },/*nor d,s,0*/ -{"or", "d,v,t", 0x00000025, 0xfc0007ff, WR_d|RD_s|RD_t, I1 }, -{"or", "t,r,I", 0, (int) M_OR_I, INSN_MACRO, I1 }, -{"or.ob", "X,Y,Q", 0x7800000e, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"or.ob", "D,S,T", 0x4ac0000e, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"or.ob", "D,S,T[e]", 0x4800000e, 0xfe20003f, WR_D|RD_S|RD_T, N54 }, -{"or.ob", "D,S,k", 0x4bc0000e, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"or.qh", "X,Y,Q", 0x7820000e, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"ori", "t,r,i", 0x34000000, 0xfc000000, WR_t|RD_s, I1 }, -{"pabsdiff.ob", "X,Y,Q",0x78000009, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, SB1 }, -{"pabsdiffc.ob", "Y,Q", 0x78000035, 0xfc2007ff, WR_MACC|RD_S|RD_T|FP_D, SB1 }, -{"pavg.ob", "X,Y,Q", 0x78000008, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, SB1 }, -{"pickf.ob", "X,Y,Q", 0x78000002, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"pickf.ob", "D,S,T", 0x4ac00002, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"pickf.ob", "D,S,T[e]",0x48000002, 0xfe20003f, WR_D|RD_S|RD_T, N54 }, -{"pickf.ob", "D,S,k", 0x4bc00002, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"pickf.qh", "X,Y,Q", 0x78200002, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"pickt.ob", "X,Y,Q", 0x78000003, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"pickt.ob", "D,S,T", 0x4ac00003, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"pickt.ob", "D,S,T[e]",0x48000003, 0xfe20003f, WR_D|RD_S|RD_T, N54 }, -{"pickt.ob", "D,S,k", 0x4bc00003, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"pickt.qh", "X,Y,Q", 0x78200003, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"pll.ps", "D,V,T", 0x46c0002c, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, I5 }, -{"plu.ps", "D,V,T", 0x46c0002d, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, I5 }, +{"nor", "d,v,t", 0x00000027, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, +{"nor", "t,r,I", 0, (int) M_NOR_I, INSN_MACRO, 0, I1 }, +{"nor.ob", "X,Y,Q", 0x7800000f, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"nor.ob", "D,S,T", 0x4ac0000f, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"nor.ob", "D,S,T[e]", 0x4800000f, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, +{"nor.ob", "D,S,k", 0x4bc0000f, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"nor.qh", "X,Y,Q", 0x7820000f, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"not", "d,v", 0x00000027, 0xfc1f07ff, WR_d|RD_s|RD_t, 0, I1 },/*nor d,s,0*/ +{"or", "d,v,t", 0x00000025, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, +{"or", "t,r,I", 0, (int) M_OR_I, INSN_MACRO, 0, I1 }, +{"or.ob", "X,Y,Q", 0x7800000e, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"or.ob", "D,S,T", 0x4ac0000e, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"or.ob", "D,S,T[e]", 0x4800000e, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, +{"or.ob", "D,S,k", 0x4bc0000e, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"or.qh", "X,Y,Q", 0x7820000e, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"ori", "t,r,i", 0x34000000, 0xfc000000, WR_t|RD_s, 0, I1 }, +{"pabsdiff.ob", "X,Y,Q",0x78000009, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, SB1 }, +{"pabsdiffc.ob", "Y,Q", 0x78000035, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, SB1 }, +{"pavg.ob", "X,Y,Q", 0x78000008, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, SB1 }, +{"pickf.ob", "X,Y,Q", 0x78000002, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"pickf.ob", "D,S,T", 0x4ac00002, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"pickf.ob", "D,S,T[e]",0x48000002, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, +{"pickf.ob", "D,S,k", 0x4bc00002, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"pickf.qh", "X,Y,Q", 0x78200002, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"pickt.ob", "X,Y,Q", 0x78000003, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"pickt.ob", "D,S,T", 0x4ac00003, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"pickt.ob", "D,S,T[e]",0x48000003, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, +{"pickt.ob", "D,S,k", 0x4bc00003, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"pickt.qh", "X,Y,Q", 0x78200003, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"pll.ps", "D,V,T", 0x46c0002c, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I5 }, +{"plu.ps", "D,V,T", 0x46c0002d, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I5 }, +{"pop", "d,s", 0x7000002c, 0xfc1f07ff, WR_d|RD_s, 0, IOCTEON }, /* pref and prefx are at the start of the table. */ -{"pul.ps", "D,V,T", 0x46c0002e, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, I5 }, -{"puu.ps", "D,V,T", 0x46c0002f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, I5 }, -{"rach.ob", "X", 0x7a00003f, 0xfffff83f, WR_D|RD_MACC|FP_D, MX|SB1 }, -{"rach.ob", "D", 0x4a00003f, 0xfffff83f, WR_D, N54 }, -{"rach.qh", "X", 0x7a20003f, 0xfffff83f, WR_D|RD_MACC|FP_D, MX }, -{"racl.ob", "X", 0x7800003f, 0xfffff83f, WR_D|RD_MACC|FP_D, MX|SB1 }, -{"racl.ob", "D", 0x4800003f, 0xfffff83f, WR_D, N54 }, -{"racl.qh", "X", 0x7820003f, 0xfffff83f, WR_D|RD_MACC|FP_D, MX }, -{"racm.ob", "X", 0x7900003f, 0xfffff83f, WR_D|RD_MACC|FP_D, MX|SB1 }, -{"racm.ob", "D", 0x4900003f, 0xfffff83f, WR_D, N54 }, -{"racm.qh", "X", 0x7920003f, 0xfffff83f, WR_D|RD_MACC|FP_D, MX }, -{"recip.d", "D,S", 0x46200015, 0xffff003f, WR_D|RD_S|FP_D, I4 }, -{"recip.ps","D,S", 0x46c00015, 0xffff003f, WR_D|RD_S|FP_D, SB1 }, -{"recip.s", "D,S", 0x46000015, 0xffff003f, WR_D|RD_S|FP_S, I4 }, -{"recip1.d", "D,S", 0x4620001d, 0xffff003f, WR_D|RD_S|FP_D, M3D }, -{"recip1.ps", "D,S", 0x46c0001d, 0xffff003f, WR_D|RD_S|FP_S, M3D }, -{"recip1.s", "D,S", 0x4600001d, 0xffff003f, WR_D|RD_S|FP_S, M3D }, -{"recip2.d", "D,S,T", 0x4620001c, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, M3D }, -{"recip2.ps", "D,S,T", 0x46c0001c, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, M3D }, -{"recip2.s", "D,S,T", 0x4600001c, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, M3D }, -{"rem", "z,s,t", 0x0000001a, 0xfc00ffff, RD_s|RD_t|WR_HILO, I1 }, -{"rem", "d,v,t", 0, (int) M_REM_3, INSN_MACRO, I1 }, -{"rem", "d,v,I", 0, (int) M_REM_3I, INSN_MACRO, I1 }, -{"remu", "z,s,t", 0x0000001b, 0xfc00ffff, RD_s|RD_t|WR_HILO, I1 }, -{"remu", "d,v,t", 0, (int) M_REMU_3, INSN_MACRO, I1 }, -{"remu", "d,v,I", 0, (int) M_REMU_3I, INSN_MACRO, I1 }, -{"rdhwr", "t,K", 0x7c00003b, 0xffe007ff, WR_t, I33 }, -{"rdpgpr", "d,w", 0x41400000, 0xffe007ff, WR_d, I33 }, -{"rfe", "", 0x42000010, 0xffffffff, 0, I1|T3 }, -{"rnas.qh", "X,Q", 0x78200025, 0xfc20f83f, WR_D|RD_MACC|RD_T|FP_D, MX }, -{"rnau.ob", "X,Q", 0x78000021, 0xfc20f83f, WR_D|RD_MACC|RD_T|FP_D, MX|SB1 }, -{"rnau.qh", "X,Q", 0x78200021, 0xfc20f83f, WR_D|RD_MACC|RD_T|FP_D, MX }, -{"rnes.qh", "X,Q", 0x78200026, 0xfc20f83f, WR_D|RD_MACC|RD_T|FP_D, MX }, -{"rneu.ob", "X,Q", 0x78000022, 0xfc20f83f, WR_D|RD_MACC|RD_T|FP_D, MX|SB1 }, -{"rneu.qh", "X,Q", 0x78200022, 0xfc20f83f, WR_D|RD_MACC|RD_T|FP_D, MX }, -{"rol", "d,v,t", 0, (int) M_ROL, INSN_MACRO, I1 }, -{"rol", "d,v,I", 0, (int) M_ROL_I, INSN_MACRO, I1 }, -{"ror", "d,v,t", 0, (int) M_ROR, INSN_MACRO, I1 }, -{"ror", "d,v,I", 0, (int) M_ROR_I, INSN_MACRO, I1 }, -{"ror", "d,w,<", 0x00200002, 0xffe0003f, WR_d|RD_t, N5|I33 }, -{"rorv", "d,t,s", 0x00000046, 0xfc0007ff, RD_t|RD_s|WR_d, N5|I33 }, -{"rotl", "d,v,t", 0, (int) M_ROL, INSN_MACRO, I33 }, -{"rotl", "d,v,I", 0, (int) M_ROL_I, INSN_MACRO, I33 }, -{"rotr", "d,v,t", 0, (int) M_ROR, INSN_MACRO, I33 }, -{"rotr", "d,v,I", 0, (int) M_ROR_I, INSN_MACRO, I33 }, -{"rotrv", "d,t,s", 0x00000046, 0xfc0007ff, RD_t|RD_s|WR_d, I33 }, -{"round.l.d", "D,S", 0x46200008, 0xffff003f, WR_D|RD_S|FP_D, I3 }, -{"round.l.s", "D,S", 0x46000008, 0xffff003f, WR_D|RD_S|FP_S, I3 }, -{"round.w.d", "D,S", 0x4620000c, 0xffff003f, WR_D|RD_S|FP_D, I2 }, -{"round.w.s", "D,S", 0x4600000c, 0xffff003f, WR_D|RD_S|FP_S, I2 }, -{"rsqrt.d", "D,S", 0x46200016, 0xffff003f, WR_D|RD_S|FP_D, I4 }, -{"rsqrt.ps","D,S", 0x46c00016, 0xffff003f, WR_D|RD_S|FP_D, SB1 }, -{"rsqrt.s", "D,S", 0x46000016, 0xffff003f, WR_D|RD_S|FP_S, I4 }, -{"rsqrt1.d", "D,S", 0x4620001e, 0xffff003f, WR_D|RD_S|FP_D, M3D }, -{"rsqrt1.ps", "D,S", 0x46c0001e, 0xffff003f, WR_D|RD_S|FP_S, M3D }, -{"rsqrt1.s", "D,S", 0x4600001e, 0xffff003f, WR_D|RD_S|FP_S, M3D }, -{"rsqrt2.d", "D,S,T", 0x4620001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, M3D }, -{"rsqrt2.ps", "D,S,T", 0x46c0001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, M3D }, -{"rsqrt2.s", "D,S,T", 0x4600001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, M3D }, -{"rzs.qh", "X,Q", 0x78200024, 0xfc20f83f, WR_D|RD_MACC|RD_T|FP_D, MX }, -{"rzu.ob", "X,Q", 0x78000020, 0xfc20f83f, WR_D|RD_MACC|RD_T|FP_D, MX|SB1 }, -{"rzu.ob", "D,k", 0x4bc00020, 0xffe0f83f, WR_D|RD_S|RD_T, N54 }, -{"rzu.qh", "X,Q", 0x78200020, 0xfc20f83f, WR_D|RD_MACC|RD_T|FP_D, MX }, -{"sb", "t,o(b)", 0xa0000000, 0xfc000000, SM|RD_t|RD_b, I1 }, -{"sb", "t,A(b)", 0, (int) M_SB_AB, INSN_MACRO, I1 }, -{"sc", "t,o(b)", 0xe0000000, 0xfc000000, SM|RD_t|WR_t|RD_b, I2 }, -{"sc", "t,A(b)", 0, (int) M_SC_AB, INSN_MACRO, I2 }, -{"scd", "t,o(b)", 0xf0000000, 0xfc000000, SM|RD_t|WR_t|RD_b, I3 }, -{"scd", "t,A(b)", 0, (int) M_SCD_AB, INSN_MACRO, I3 }, -{"sd", "t,o(b)", 0xfc000000, 0xfc000000, SM|RD_t|RD_b, I3 }, -{"sd", "t,o(b)", 0, (int) M_SD_OB, INSN_MACRO, I1 }, -{"sd", "t,A(b)", 0, (int) M_SD_AB, INSN_MACRO, I1 }, -{"sdbbp", "", 0x0000000e, 0xffffffff, TRAP, G2 }, -{"sdbbp", "c", 0x0000000e, 0xfc00ffff, TRAP, G2 }, -{"sdbbp", "c,q", 0x0000000e, 0xfc00003f, TRAP, G2 }, -{"sdbbp", "", 0x7000003f, 0xffffffff, TRAP, I32 }, -{"sdbbp", "B", 0x7000003f, 0xfc00003f, TRAP, I32 }, -{"sdc1", "T,o(b)", 0xf4000000, 0xfc000000, SM|RD_T|RD_b|FP_D, I2 }, -{"sdc1", "E,o(b)", 0xf4000000, 0xfc000000, SM|RD_T|RD_b|FP_D, I2 }, -{"sdc1", "T,A(b)", 0, (int) M_SDC1_AB, INSN_MACRO, I2 }, -{"sdc1", "E,A(b)", 0, (int) M_SDC1_AB, INSN_MACRO, I2 }, -{"sdc2", "E,o(b)", 0xf8000000, 0xfc000000, SM|RD_C2|RD_b, I2 }, -{"sdc2", "E,A(b)", 0, (int) M_SDC2_AB, INSN_MACRO, I2 }, -{"sdc3", "E,o(b)", 0xfc000000, 0xfc000000, SM|RD_C3|RD_b, I2 }, -{"sdc3", "E,A(b)", 0, (int) M_SDC3_AB, INSN_MACRO, I2 }, -{"s.d", "T,o(b)", 0xf4000000, 0xfc000000, SM|RD_T|RD_b|FP_D, I2 }, -{"s.d", "T,o(b)", 0, (int) M_S_DOB, INSN_MACRO, I1 }, -{"s.d", "T,A(b)", 0, (int) M_S_DAB, INSN_MACRO, I1 }, -{"sdl", "t,o(b)", 0xb0000000, 0xfc000000, SM|RD_t|RD_b, I3 }, -{"sdl", "t,A(b)", 0, (int) M_SDL_AB, INSN_MACRO, I3 }, -{"sdr", "t,o(b)", 0xb4000000, 0xfc000000, SM|RD_t|RD_b, I3 }, -{"sdr", "t,A(b)", 0, (int) M_SDR_AB, INSN_MACRO, I3 }, -{"sdxc1", "S,t(b)", 0x4c000009, 0xfc0007ff, SM|RD_S|RD_t|RD_b, I4 }, -{"seb", "d,w", 0x7c000420, 0xffe007ff, WR_d|RD_t, I33 }, -{"seh", "d,w", 0x7c000620, 0xffe007ff, WR_d|RD_t, I33 }, -{"selsl", "d,v,t", 0x00000005, 0xfc0007ff, WR_d|RD_s|RD_t, L1 }, -{"selsr", "d,v,t", 0x00000001, 0xfc0007ff, WR_d|RD_s|RD_t, L1 }, -{"seq", "d,v,t", 0, (int) M_SEQ, INSN_MACRO, I1 }, -{"seq", "d,v,I", 0, (int) M_SEQ_I, INSN_MACRO, I1 }, -{"sge", "d,v,t", 0, (int) M_SGE, INSN_MACRO, I1 }, -{"sge", "d,v,I", 0, (int) M_SGE_I, INSN_MACRO, I1 }, -{"sgeu", "d,v,t", 0, (int) M_SGEU, INSN_MACRO, I1 }, -{"sgeu", "d,v,I", 0, (int) M_SGEU_I, INSN_MACRO, I1 }, -{"sgt", "d,v,t", 0, (int) M_SGT, INSN_MACRO, I1 }, -{"sgt", "d,v,I", 0, (int) M_SGT_I, INSN_MACRO, I1 }, -{"sgtu", "d,v,t", 0, (int) M_SGTU, INSN_MACRO, I1 }, -{"sgtu", "d,v,I", 0, (int) M_SGTU_I, INSN_MACRO, I1 }, -{"sh", "t,o(b)", 0xa4000000, 0xfc000000, SM|RD_t|RD_b, I1 }, -{"sh", "t,A(b)", 0, (int) M_SH_AB, INSN_MACRO, I1 }, -{"shfl.bfla.qh", "X,Y,Z", 0x7a20001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"shfl.mixh.ob", "X,Y,Z", 0x7980001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"shfl.mixh.ob", "D,S,T", 0x4980001f, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"shfl.mixh.qh", "X,Y,Z", 0x7820001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"shfl.mixl.ob", "X,Y,Z", 0x79c0001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"shfl.mixl.ob", "D,S,T", 0x49c0001f, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"shfl.mixl.qh", "X,Y,Z", 0x78a0001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"shfl.pach.ob", "X,Y,Z", 0x7900001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"shfl.pach.ob", "D,S,T", 0x4900001f, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"shfl.pach.qh", "X,Y,Z", 0x7920001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"shfl.pacl.ob", "D,S,T", 0x4940001f, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"shfl.repa.qh", "X,Y,Z", 0x7b20001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"shfl.repb.qh", "X,Y,Z", 0x7ba0001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"shfl.upsl.ob", "X,Y,Z", 0x78c0001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"sle", "d,v,t", 0, (int) M_SLE, INSN_MACRO, I1 }, -{"sle", "d,v,I", 0, (int) M_SLE_I, INSN_MACRO, I1 }, -{"sleu", "d,v,t", 0, (int) M_SLEU, INSN_MACRO, I1 }, -{"sleu", "d,v,I", 0, (int) M_SLEU_I, INSN_MACRO, I1 }, -{"sllv", "d,t,s", 0x00000004, 0xfc0007ff, WR_d|RD_t|RD_s, I1 }, -{"sll", "d,w,s", 0x00000004, 0xfc0007ff, WR_d|RD_t|RD_s, I1 }, /* sllv */ -{"sll", "d,w,<", 0x00000000, 0xffe0003f, WR_d|RD_t, I1 }, -{"sll.ob", "X,Y,Q", 0x78000010, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"sll.ob", "D,S,T[e]", 0x48000010, 0xfe20003f, WR_D|RD_S|RD_T, N54 }, -{"sll.ob", "D,S,k", 0x4bc00010, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"sll.qh", "X,Y,Q", 0x78200010, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"slt", "d,v,t", 0x0000002a, 0xfc0007ff, WR_d|RD_s|RD_t, I1 }, -{"slt", "d,v,I", 0, (int) M_SLT_I, INSN_MACRO, I1 }, -{"slti", "t,r,j", 0x28000000, 0xfc000000, WR_t|RD_s, I1 }, -{"sltiu", "t,r,j", 0x2c000000, 0xfc000000, WR_t|RD_s, I1 }, -{"sltu", "d,v,t", 0x0000002b, 0xfc0007ff, WR_d|RD_s|RD_t, I1 }, -{"sltu", "d,v,I", 0, (int) M_SLTU_I, INSN_MACRO, I1 }, -{"sne", "d,v,t", 0, (int) M_SNE, INSN_MACRO, I1 }, -{"sne", "d,v,I", 0, (int) M_SNE_I, INSN_MACRO, I1 }, -{"sqrt.d", "D,S", 0x46200004, 0xffff003f, WR_D|RD_S|FP_D, I2 }, -{"sqrt.s", "D,S", 0x46000004, 0xffff003f, WR_D|RD_S|FP_S, I2 }, -{"sqrt.ps", "D,S", 0x46c00004, 0xffff003f, WR_D|RD_S|FP_D, SB1 }, -{"srav", "d,t,s", 0x00000007, 0xfc0007ff, WR_d|RD_t|RD_s, I1 }, -{"sra", "d,w,s", 0x00000007, 0xfc0007ff, WR_d|RD_t|RD_s, I1 }, /* srav */ -{"sra", "d,w,<", 0x00000003, 0xffe0003f, WR_d|RD_t, I1 }, -{"sra.qh", "X,Y,Q", 0x78200013, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"srlv", "d,t,s", 0x00000006, 0xfc0007ff, WR_d|RD_t|RD_s, I1 }, -{"srl", "d,w,s", 0x00000006, 0xfc0007ff, WR_d|RD_t|RD_s, I1 }, /* srlv */ -{"srl", "d,w,<", 0x00000002, 0xffe0003f, WR_d|RD_t, I1 }, -{"srl.ob", "X,Y,Q", 0x78000012, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"srl.ob", "D,S,T[e]", 0x48000012, 0xfe20003f, WR_D|RD_S|RD_T, N54 }, -{"srl.ob", "D,S,k", 0x4bc00012, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"srl.qh", "X,Y,Q", 0x78200012, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX }, +{"pul.ps", "D,V,T", 0x46c0002e, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I5 }, +{"puu.ps", "D,V,T", 0x46c0002f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I5 }, +{"rach.ob", "X", 0x7a00003f, 0xfffff83f, WR_D|FP_D, RD_MACC, MX|SB1 }, +{"rach.ob", "D", 0x4a00003f, 0xfffff83f, WR_D, 0, N54 }, +{"rach.qh", "X", 0x7a20003f, 0xfffff83f, WR_D|FP_D, RD_MACC, MX }, +{"racl.ob", "X", 0x7800003f, 0xfffff83f, WR_D|FP_D, RD_MACC, MX|SB1 }, +{"racl.ob", "D", 0x4800003f, 0xfffff83f, WR_D, 0, N54 }, +{"racl.qh", "X", 0x7820003f, 0xfffff83f, WR_D|FP_D, RD_MACC, MX }, +{"racm.ob", "X", 0x7900003f, 0xfffff83f, WR_D|FP_D, RD_MACC, MX|SB1 }, +{"racm.ob", "D", 0x4900003f, 0xfffff83f, WR_D, 0, N54 }, +{"racm.qh", "X", 0x7920003f, 0xfffff83f, WR_D|FP_D, RD_MACC, MX }, +{"recip.d", "D,S", 0x46200015, 0xffff003f, WR_D|RD_S|FP_D, 0, I4|I33 }, +{"recip.ps","D,S", 0x46c00015, 0xffff003f, WR_D|RD_S|FP_D, 0, SB1 }, +{"recip.s", "D,S", 0x46000015, 0xffff003f, WR_D|RD_S|FP_S, 0, I4|I33 }, +{"recip1.d", "D,S", 0x4620001d, 0xffff003f, WR_D|RD_S|FP_D, 0, M3D }, +{"recip1.ps", "D,S", 0x46c0001d, 0xffff003f, WR_D|RD_S|FP_S, 0, M3D }, +{"recip1.s", "D,S", 0x4600001d, 0xffff003f, WR_D|RD_S|FP_S, 0, M3D }, +{"recip2.d", "D,S,T", 0x4620001c, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, M3D }, +{"recip2.ps", "D,S,T", 0x46c0001c, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, M3D }, +{"recip2.s", "D,S,T", 0x4600001c, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, M3D }, +{"rem", "z,s,t", 0x0000001a, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I1 }, +{"rem", "d,v,t", 0, (int) M_REM_3, INSN_MACRO, 0, I1 }, +{"rem", "d,v,I", 0, (int) M_REM_3I, INSN_MACRO, 0, I1 }, +{"remu", "z,s,t", 0x0000001b, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I1 }, +{"remu", "d,v,t", 0, (int) M_REMU_3, INSN_MACRO, 0, I1 }, +{"remu", "d,v,I", 0, (int) M_REMU_3I, INSN_MACRO, 0, I1 }, +{"rdhwr", "t,K", 0x7c00003b, 0xffe007ff, WR_t, 0, I33 }, +{"rdpgpr", "d,w", 0x41400000, 0xffe007ff, WR_d, 0, I33 }, +{"rfe", "", 0x42000010, 0xffffffff, 0, 0, I1|T3 }, +{"rnas.qh", "X,Q", 0x78200025, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX }, +{"rnau.ob", "X,Q", 0x78000021, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX|SB1 }, +{"rnau.qh", "X,Q", 0x78200021, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX }, +{"rnes.qh", "X,Q", 0x78200026, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX }, +{"rneu.ob", "X,Q", 0x78000022, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX|SB1 }, +{"rneu.qh", "X,Q", 0x78200022, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX }, +{"rol", "d,v,t", 0, (int) M_ROL, INSN_MACRO, 0, I1 }, +{"rol", "d,v,I", 0, (int) M_ROL_I, INSN_MACRO, 0, I1 }, +{"ror", "d,v,t", 0, (int) M_ROR, INSN_MACRO, 0, I1 }, +{"ror", "d,v,I", 0, (int) M_ROR_I, INSN_MACRO, 0, I1 }, +{"ror", "d,w,<", 0x00200002, 0xffe0003f, WR_d|RD_t, 0, N5|I33 }, +{"rorv", "d,t,s", 0x00000046, 0xfc0007ff, RD_t|RD_s|WR_d, 0, N5|I33 }, +{"rotl", "d,v,t", 0, (int) M_ROL, INSN_MACRO, 0, I33 }, +{"rotl", "d,v,I", 0, (int) M_ROL_I, INSN_MACRO, 0, I33 }, +{"rotr", "d,v,t", 0, (int) M_ROR, INSN_MACRO, 0, I33 }, +{"rotr", "d,v,I", 0, (int) M_ROR_I, INSN_MACRO, 0, I33 }, +{"rotrv", "d,t,s", 0x00000046, 0xfc0007ff, RD_t|RD_s|WR_d, 0, I33 }, +{"round.l.d", "D,S", 0x46200008, 0xffff003f, WR_D|RD_S|FP_D, 0, I3|I33 }, +{"round.l.s", "D,S", 0x46000008, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I3 }, +{"round.w.d", "D,S", 0x4620000c, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I2 }, +{"round.w.s", "D,S", 0x4600000c, 0xffff003f, WR_D|RD_S|FP_S, 0, I2 }, +{"rsqrt.d", "D,S", 0x46200016, 0xffff003f, WR_D|RD_S|FP_D, 0, I4|I33 }, +{"rsqrt.ps","D,S", 0x46c00016, 0xffff003f, WR_D|RD_S|FP_D, 0, SB1 }, +{"rsqrt.s", "D,S", 0x46000016, 0xffff003f, WR_D|RD_S|FP_S, 0, I4|I33 }, +{"rsqrt1.d", "D,S", 0x4620001e, 0xffff003f, WR_D|RD_S|FP_D, 0, M3D }, +{"rsqrt1.ps", "D,S", 0x46c0001e, 0xffff003f, WR_D|RD_S|FP_S, 0, M3D }, +{"rsqrt1.s", "D,S", 0x4600001e, 0xffff003f, WR_D|RD_S|FP_S, 0, M3D }, +{"rsqrt2.d", "D,S,T", 0x4620001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, M3D }, +{"rsqrt2.ps", "D,S,T", 0x46c0001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, M3D }, +{"rsqrt2.s", "D,S,T", 0x4600001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, M3D }, +{"rzs.qh", "X,Q", 0x78200024, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX }, +{"rzu.ob", "X,Q", 0x78000020, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX|SB1 }, +{"rzu.ob", "D,k", 0x4bc00020, 0xffe0f83f, WR_D|RD_S|RD_T, 0, N54 }, +{"rzu.qh", "X,Q", 0x78200020, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX }, +/* 58xx specific instructions. */ +{"saa", "t,(b)", 0x70000018, 0xfc00ffff, SM|RD_t|RD_b, 0, IOCTEON }, +{"saa", "t,A(b)", 0, (int) M_SAA_AB, INSN_MACRO, 0, IOCTEON }, +{"saad", "t,(b)", 0x70000019, 0xfc00ffff, SM|RD_t|RD_b, 0, IOCTEON }, +{"saad", "t,A(b)", 0, (int) M_SAAD_AB, INSN_MACRO, 0, IOCTEON }, +{"sb", "t,o(b)", 0xa0000000, 0xfc000000, SM|RD_t|RD_b, 0, I1 }, +{"sb", "t,A(b)", 0, (int) M_SB_AB, INSN_MACRO, 0, I1 }, +{"sc", "t,o(b)", 0xe0000000, 0xfc000000, SM|RD_t|WR_t|RD_b, 0, I2 }, +{"sc", "t,A(b)", 0, (int) M_SC_AB, INSN_MACRO, 0, I2 }, +{"scd", "t,o(b)", 0xf0000000, 0xfc000000, SM|RD_t|WR_t|RD_b, 0, I3 }, +{"scd", "t,A(b)", 0, (int) M_SCD_AB, INSN_MACRO, 0, I3 }, +{"sd", "t,o(b)", 0xfc000000, 0xfc000000, SM|RD_t|RD_b, 0, I3 }, +{"sd", "t,o(b)", 0, (int) M_SD_OB, INSN_MACRO, 0, I1 }, +{"sd", "t,A(b)", 0, (int) M_SD_AB, INSN_MACRO, 0, I1 }, +{"sdbbp", "", 0x0000000e, 0xffffffff, TRAP, 0, G2 }, +{"sdbbp", "c", 0x0000000e, 0xfc00ffff, TRAP, 0, G2 }, +{"sdbbp", "c,q", 0x0000000e, 0xfc00003f, TRAP, 0, G2 }, +{"sdbbp", "", 0x7000003f, 0xffffffff, TRAP, 0, I32 }, +{"sdbbp", "B", 0x7000003f, 0xfc00003f, TRAP, 0, I32 }, +{"sdc1", "T,o(b)", 0xf4000000, 0xfc000000, SM|RD_T|RD_b|FP_D, 0, I2 }, +{"sdc1", "E,o(b)", 0xf4000000, 0xfc000000, SM|RD_T|RD_b|FP_D, 0, I2 }, +{"sdc1", "T,A(b)", 0, (int) M_SDC1_AB, INSN_MACRO, 0, I2 }, +{"sdc1", "E,A(b)", 0, (int) M_SDC1_AB, INSN_MACRO, 0, I2 }, +{"sdc2", "E,o(b)", 0xf8000000, 0xfc000000, SM|RD_C2|RD_b, 0, I2 }, +{"sdc2", "E,A(b)", 0, (int) M_SDC2_AB, INSN_MACRO, 0, I2 }, +{"sdc3", "E,o(b)", 0xfc000000, 0xfc000000, SM|RD_C3|RD_b, 0, I2 }, +{"sdc3", "E,A(b)", 0, (int) M_SDC3_AB, INSN_MACRO, 0, I2 }, +{"s.d", "T,o(b)", 0xf4000000, 0xfc000000, SM|RD_T|RD_b|FP_D, 0, I2 }, +{"s.d", "T,o(b)", 0, (int) M_S_DOB, INSN_MACRO, 0, I1 }, +{"s.d", "T,A(b)", 0, (int) M_S_DAB, INSN_MACRO, 0, I1 }, +{"sdl", "t,o(b)", 0xb0000000, 0xfc000000, SM|RD_t|RD_b, 0, I3 }, +{"sdl", "t,A(b)", 0, (int) M_SDL_AB, INSN_MACRO, 0, I3 }, +{"sdr", "t,o(b)", 0xb4000000, 0xfc000000, SM|RD_t|RD_b, 0, I3 }, +{"sdr", "t,A(b)", 0, (int) M_SDR_AB, INSN_MACRO, 0, I3 }, +{"sdxc1", "S,t(b)", 0x4c000009, 0xfc0007ff, SM|RD_S|RD_t|RD_b|FP_D, 0, I4|I33 }, +{"seb", "d,w", 0x7c000420, 0xffe007ff, WR_d|RD_t, 0, I33 }, +{"seh", "d,w", 0x7c000620, 0xffe007ff, WR_d|RD_t, 0, I33 }, +{"selsl", "d,v,t", 0x00000005, 0xfc0007ff, WR_d|RD_s|RD_t, 0, L1 }, +{"selsr", "d,v,t", 0x00000001, 0xfc0007ff, WR_d|RD_s|RD_t, 0, L1 }, +{"seq", "d,v,t", 0x7000002a, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IOCTEON }, +{"seq", "d,v,t", 0, (int) M_SEQ, INSN_MACRO, 0, I1 }, +{"seq", "d,v,I", 0, (int) M_SEQ_I, INSN_MACRO, 0, I1 }, +{"seqi", "t,r,y", 0x7000002e, 0xfc00003f, WR_t|RD_s, 0, IOCTEON }, +{"sge", "d,v,t", 0, (int) M_SGE, INSN_MACRO, 0, I1 }, +{"sge", "d,v,I", 0, (int) M_SGE_I, INSN_MACRO, 0, I1 }, +{"sgeu", "d,v,t", 0, (int) M_SGEU, INSN_MACRO, 0, I1 }, +{"sgeu", "d,v,I", 0, (int) M_SGEU_I, INSN_MACRO, 0, I1 }, +{"sgt", "d,v,t", 0, (int) M_SGT, INSN_MACRO, 0, I1 }, +{"sgt", "d,v,I", 0, (int) M_SGT_I, INSN_MACRO, 0, I1 }, +{"sgtu", "d,v,t", 0, (int) M_SGTU, INSN_MACRO, 0, I1 }, +{"sgtu", "d,v,I", 0, (int) M_SGTU_I, INSN_MACRO, 0, I1 }, +{"sh", "t,o(b)", 0xa4000000, 0xfc000000, SM|RD_t|RD_b, 0, I1 }, +{"sh", "t,A(b)", 0, (int) M_SH_AB, INSN_MACRO, 0, I1 }, +{"shfl.bfla.qh", "X,Y,Z", 0x7a20001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"shfl.mixh.ob", "X,Y,Z", 0x7980001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"shfl.mixh.ob", "D,S,T", 0x4980001f, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"shfl.mixh.qh", "X,Y,Z", 0x7820001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"shfl.mixl.ob", "X,Y,Z", 0x79c0001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"shfl.mixl.ob", "D,S,T", 0x49c0001f, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"shfl.mixl.qh", "X,Y,Z", 0x78a0001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"shfl.pach.ob", "X,Y,Z", 0x7900001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"shfl.pach.ob", "D,S,T", 0x4900001f, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"shfl.pach.qh", "X,Y,Z", 0x7920001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"shfl.pacl.ob", "D,S,T", 0x4940001f, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"shfl.repa.qh", "X,Y,Z", 0x7b20001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"shfl.repb.qh", "X,Y,Z", 0x7ba0001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"shfl.upsl.ob", "X,Y,Z", 0x78c0001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"sle", "d,v,t", 0, (int) M_SLE, INSN_MACRO, 0, I1 }, +{"sle", "d,v,I", 0, (int) M_SLE_I, INSN_MACRO, 0, I1 }, +{"sleu", "d,v,t", 0, (int) M_SLEU, INSN_MACRO, 0, I1 }, +{"sleu", "d,v,I", 0, (int) M_SLEU_I, INSN_MACRO, 0, I1 }, +{"sllv", "d,t,s", 0x00000004, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I1 }, +{"sll", "d,w,s", 0x00000004, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I1 }, /* sllv */ +{"sll", "d,w,<", 0x00000000, 0xffe0003f, WR_d|RD_t, 0, I1 }, +{"sll.ob", "X,Y,Q", 0x78000010, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"sll.ob", "D,S,T[e]", 0x48000010, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, +{"sll.ob", "D,S,k", 0x4bc00010, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"sll.qh", "X,Y,Q", 0x78200010, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"slt", "d,v,t", 0x0000002a, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, +{"slt", "d,v,I", 0, (int) M_SLT_I, INSN_MACRO, 0, I1 }, +{"slti", "t,r,j", 0x28000000, 0xfc000000, WR_t|RD_s, 0, I1 }, +{"sltiu", "t,r,j", 0x2c000000, 0xfc000000, WR_t|RD_s, 0, I1 }, +{"sltu", "d,v,t", 0x0000002b, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, +{"sltu", "d,v,I", 0, (int) M_SLTU_I, INSN_MACRO, 0, I1 }, +{"sne", "d,v,t", 0x7000002b, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IOCTEON }, +{"sne", "d,v,t", 0, (int) M_SNE, INSN_MACRO, 0, I1 }, +{"sne", "d,v,I", 0, (int) M_SNE_I, INSN_MACRO, 0, I1 }, +{"snei", "t,r,y", 0x7000002f, 0xfc00003f, WR_t|RD_s, 0, IOCTEON }, +{"sqrt.d", "D,S", 0x46200004, 0xffff003f, WR_D|RD_S|FP_D, 0, I2 }, +{"sqrt.s", "D,S", 0x46000004, 0xffff003f, WR_D|RD_S|FP_S, 0, I2 }, +{"sqrt.ps", "D,S", 0x46c00004, 0xffff003f, WR_D|RD_S|FP_D, 0, SB1 }, +{"srav", "d,t,s", 0x00000007, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I1 }, +{"sra", "d,w,s", 0x00000007, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I1 }, /* srav */ +{"sra", "d,w,<", 0x00000003, 0xffe0003f, WR_d|RD_t, 0, I1 }, +{"sra.qh", "X,Y,Q", 0x78200013, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"srlv", "d,t,s", 0x00000006, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I1 }, +{"srl", "d,w,s", 0x00000006, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I1 }, /* srlv */ +{"srl", "d,w,<", 0x00000002, 0xffe0003f, WR_d|RD_t, 0, I1 }, +{"srl.ob", "X,Y,Q", 0x78000012, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"srl.ob", "D,S,T[e]", 0x48000012, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, +{"srl.ob", "D,S,k", 0x4bc00012, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"srl.qh", "X,Y,Q", 0x78200012, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, /* ssnop is at the start of the table. */ -{"standby", "", 0x42000021, 0xffffffff, 0, V1 }, -{"sub", "d,v,t", 0x00000022, 0xfc0007ff, WR_d|RD_s|RD_t, I1 }, -{"sub", "d,v,I", 0, (int) M_SUB_I, INSN_MACRO, I1 }, -{"sub.d", "D,V,T", 0x46200001, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, I1 }, -{"sub.s", "D,V,T", 0x46000001, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, I1 }, -{"sub.ob", "X,Y,Q", 0x7800000a, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"sub.ob", "D,S,T", 0x4ac0000a, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"sub.ob", "D,S,T[e]", 0x4800000a, 0xfe20003f, WR_D|RD_S|RD_T, N54 }, -{"sub.ob", "D,S,k", 0x4bc0000a, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"sub.ps", "D,V,T", 0x46c00001, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, I5 }, -{"sub.qh", "X,Y,Q", 0x7820000a, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"suba.ob", "Y,Q", 0x78000036, 0xfc2007ff, WR_MACC|RD_S|RD_T|FP_D, MX|SB1 }, -{"suba.qh", "Y,Q", 0x78200036, 0xfc2007ff, WR_MACC|RD_S|RD_T|FP_D, MX }, -{"subl.ob", "Y,Q", 0x78000436, 0xfc2007ff, WR_MACC|RD_S|RD_T|FP_D, MX|SB1 }, -{"subl.qh", "Y,Q", 0x78200436, 0xfc2007ff, WR_MACC|RD_S|RD_T|FP_D, MX }, -{"subu", "d,v,t", 0x00000023, 0xfc0007ff, WR_d|RD_s|RD_t, I1 }, -{"subu", "d,v,I", 0, (int) M_SUBU_I, INSN_MACRO, I1 }, -{"suspend", "", 0x42000022, 0xffffffff, 0, V1 }, -{"suxc1", "S,t(b)", 0x4c00000d, 0xfc0007ff, SM|RD_S|RD_t|RD_b, I5|N55 }, -{"sw", "t,o(b)", 0xac000000, 0xfc000000, SM|RD_t|RD_b, I1 }, -{"sw", "t,A(b)", 0, (int) M_SW_AB, INSN_MACRO, I1 }, -{"swc0", "E,o(b)", 0xe0000000, 0xfc000000, SM|RD_C0|RD_b, I1 }, -{"swc0", "E,A(b)", 0, (int) M_SWC0_AB, INSN_MACRO, I1 }, -{"swc1", "T,o(b)", 0xe4000000, 0xfc000000, SM|RD_T|RD_b|FP_S, I1 }, -{"swc1", "E,o(b)", 0xe4000000, 0xfc000000, SM|RD_T|RD_b|FP_S, I1 }, -{"swc1", "T,A(b)", 0, (int) M_SWC1_AB, INSN_MACRO, I1 }, -{"swc1", "E,A(b)", 0, (int) M_SWC1_AB, INSN_MACRO, I1 }, -{"s.s", "T,o(b)", 0xe4000000, 0xfc000000, SM|RD_T|RD_b|FP_S, I1 }, /* swc1 */ -{"s.s", "T,A(b)", 0, (int) M_SWC1_AB, INSN_MACRO, I1 }, -{"swc2", "E,o(b)", 0xe8000000, 0xfc000000, SM|RD_C2|RD_b, I1 }, -{"swc2", "E,A(b)", 0, (int) M_SWC2_AB, INSN_MACRO, I1 }, -{"swc3", "E,o(b)", 0xec000000, 0xfc000000, SM|RD_C3|RD_b, I1 }, -{"swc3", "E,A(b)", 0, (int) M_SWC3_AB, INSN_MACRO, I1 }, -{"swl", "t,o(b)", 0xa8000000, 0xfc000000, SM|RD_t|RD_b, I1 }, -{"swl", "t,A(b)", 0, (int) M_SWL_AB, INSN_MACRO, I1 }, -{"scache", "t,o(b)", 0xa8000000, 0xfc000000, RD_t|RD_b, I2 }, /* same */ -{"scache", "t,A(b)", 0, (int) M_SWL_AB, INSN_MACRO, I2 }, /* as swl */ -{"swr", "t,o(b)", 0xb8000000, 0xfc000000, SM|RD_t|RD_b, I1 }, -{"swr", "t,A(b)", 0, (int) M_SWR_AB, INSN_MACRO, I1 }, -{"invalidate", "t,o(b)",0xb8000000, 0xfc000000, RD_t|RD_b, I2 }, /* same */ -{"invalidate", "t,A(b)",0, (int) M_SWR_AB, INSN_MACRO, I2 }, /* as swr */ -{"swxc1", "S,t(b)", 0x4c000008, 0xfc0007ff, SM|RD_S|RD_t|RD_b, I4 }, -{"sync", "", 0x0000000f, 0xffffffff, INSN_SYNC, I2|G1 }, -{"sync.p", "", 0x0000040f, 0xffffffff, INSN_SYNC, I2 }, -{"sync.l", "", 0x0000000f, 0xffffffff, INSN_SYNC, I2 }, -{"synci", "o(b)", 0x041f0000, 0xfc1f0000, SM|RD_b, I33 }, -{"syscall", "", 0x0000000c, 0xffffffff, TRAP, I1 }, -{"syscall", "B", 0x0000000c, 0xfc00003f, TRAP, I1 }, -{"teqi", "s,j", 0x040c0000, 0xfc1f0000, RD_s|TRAP, I2 }, -{"teq", "s,t", 0x00000034, 0xfc00ffff, RD_s|RD_t|TRAP, I2 }, -{"teq", "s,t,q", 0x00000034, 0xfc00003f, RD_s|RD_t|TRAP, I2 }, -{"teq", "s,j", 0x040c0000, 0xfc1f0000, RD_s|TRAP, I2 }, /* teqi */ -{"teq", "s,I", 0, (int) M_TEQ_I, INSN_MACRO, I2 }, -{"tgei", "s,j", 0x04080000, 0xfc1f0000, RD_s|TRAP, I2 }, -{"tge", "s,t", 0x00000030, 0xfc00ffff, RD_s|RD_t|TRAP, I2 }, -{"tge", "s,t,q", 0x00000030, 0xfc00003f, RD_s|RD_t|TRAP, I2 }, -{"tge", "s,j", 0x04080000, 0xfc1f0000, RD_s|TRAP, I2 }, /* tgei */ -{"tge", "s,I", 0, (int) M_TGE_I, INSN_MACRO, I2 }, -{"tgeiu", "s,j", 0x04090000, 0xfc1f0000, RD_s|TRAP, I2 }, -{"tgeu", "s,t", 0x00000031, 0xfc00ffff, RD_s|RD_t|TRAP, I2 }, -{"tgeu", "s,t,q", 0x00000031, 0xfc00003f, RD_s|RD_t|TRAP, I2 }, -{"tgeu", "s,j", 0x04090000, 0xfc1f0000, RD_s|TRAP, I2 }, /* tgeiu */ -{"tgeu", "s,I", 0, (int) M_TGEU_I, INSN_MACRO, I2 }, -{"tlbp", "", 0x42000008, 0xffffffff, INSN_TLB, I1 }, -{"tlbr", "", 0x42000001, 0xffffffff, INSN_TLB, I1 }, -{"tlbwi", "", 0x42000002, 0xffffffff, INSN_TLB, I1 }, -{"tlbwr", "", 0x42000006, 0xffffffff, INSN_TLB, I1 }, -{"tlti", "s,j", 0x040a0000, 0xfc1f0000, RD_s|TRAP, I2 }, -{"tlt", "s,t", 0x00000032, 0xfc00ffff, RD_s|RD_t|TRAP, I2 }, -{"tlt", "s,t,q", 0x00000032, 0xfc00003f, RD_s|RD_t|TRAP, I2 }, -{"tlt", "s,j", 0x040a0000, 0xfc1f0000, RD_s|TRAP, I2 }, /* tlti */ -{"tlt", "s,I", 0, (int) M_TLT_I, INSN_MACRO, I2 }, -{"tltiu", "s,j", 0x040b0000, 0xfc1f0000, RD_s|TRAP, I2 }, -{"tltu", "s,t", 0x00000033, 0xfc00ffff, RD_s|RD_t|TRAP, I2 }, -{"tltu", "s,t,q", 0x00000033, 0xfc00003f, RD_s|RD_t|TRAP, I2 }, -{"tltu", "s,j", 0x040b0000, 0xfc1f0000, RD_s|TRAP, I2 }, /* tltiu */ -{"tltu", "s,I", 0, (int) M_TLTU_I, INSN_MACRO, I2 }, -{"tnei", "s,j", 0x040e0000, 0xfc1f0000, RD_s|TRAP, I2 }, -{"tne", "s,t", 0x00000036, 0xfc00ffff, RD_s|RD_t|TRAP, I2 }, -{"tne", "s,t,q", 0x00000036, 0xfc00003f, RD_s|RD_t|TRAP, I2 }, -{"tne", "s,j", 0x040e0000, 0xfc1f0000, RD_s|TRAP, I2 }, /* tnei */ -{"tne", "s,I", 0, (int) M_TNE_I, INSN_MACRO, I2 }, -{"trunc.l.d", "D,S", 0x46200009, 0xffff003f, WR_D|RD_S|FP_D, I3 }, -{"trunc.l.s", "D,S", 0x46000009, 0xffff003f, WR_D|RD_S|FP_S, I3 }, -{"trunc.w.d", "D,S", 0x4620000d, 0xffff003f, WR_D|RD_S|FP_D, I2 }, -{"trunc.w.d", "D,S,x", 0x4620000d, 0xffff003f, WR_D|RD_S|FP_D, I2 }, -{"trunc.w.d", "D,S,t", 0, (int) M_TRUNCWD, INSN_MACRO, I1 }, -{"trunc.w.s", "D,S", 0x4600000d, 0xffff003f, WR_D|RD_S|FP_S, I2 }, -{"trunc.w.s", "D,S,x", 0x4600000d, 0xffff003f, WR_D|RD_S|FP_S, I2 }, -{"trunc.w.s", "D,S,t", 0, (int) M_TRUNCWS, INSN_MACRO, I1 }, -{"uld", "t,o(b)", 0, (int) M_ULD, INSN_MACRO, I3 }, -{"uld", "t,A(b)", 0, (int) M_ULD_A, INSN_MACRO, I3 }, -{"ulh", "t,o(b)", 0, (int) M_ULH, INSN_MACRO, I1 }, -{"ulh", "t,A(b)", 0, (int) M_ULH_A, INSN_MACRO, I1 }, -{"ulhu", "t,o(b)", 0, (int) M_ULHU, INSN_MACRO, I1 }, -{"ulhu", "t,A(b)", 0, (int) M_ULHU_A, INSN_MACRO, I1 }, -{"ulw", "t,o(b)", 0, (int) M_ULW, INSN_MACRO, I1 }, -{"ulw", "t,A(b)", 0, (int) M_ULW_A, INSN_MACRO, I1 }, -{"usd", "t,o(b)", 0, (int) M_USD, INSN_MACRO, I3 }, -{"usd", "t,A(b)", 0, (int) M_USD_A, INSN_MACRO, I3 }, -{"ush", "t,o(b)", 0, (int) M_USH, INSN_MACRO, I1 }, -{"ush", "t,A(b)", 0, (int) M_USH_A, INSN_MACRO, I1 }, -{"usw", "t,o(b)", 0, (int) M_USW, INSN_MACRO, I1 }, -{"usw", "t,A(b)", 0, (int) M_USW_A, INSN_MACRO, I1 }, -{"wach.ob", "Y", 0x7a00003e, 0xffff07ff, WR_MACC|RD_S|FP_D, MX|SB1 }, -{"wach.ob", "S", 0x4a00003e, 0xffff07ff, RD_S, N54 }, -{"wach.qh", "Y", 0x7a20003e, 0xffff07ff, WR_MACC|RD_S|FP_D, MX }, -{"wacl.ob", "Y,Z", 0x7800003e, 0xffe007ff, WR_MACC|RD_S|RD_T|FP_D, MX|SB1 }, -{"wacl.ob", "S,T", 0x4800003e, 0xffe007ff, RD_S|RD_T, N54 }, -{"wacl.qh", "Y,Z", 0x7820003e, 0xffe007ff, WR_MACC|RD_S|RD_T|FP_D, MX }, -{"wait", "", 0x42000020, 0xffffffff, TRAP, I3|I32 }, -{"wait", "J", 0x42000020, 0xfe00003f, TRAP, I32|N55 }, -{"waiti", "", 0x42000020, 0xffffffff, TRAP, L1 }, -{"wb", "o(b)", 0xbc040000, 0xfc1f0000, SM|RD_b, L1 }, -{"wrpgpr", "d,w", 0x41c00000, 0xffe007ff, RD_t, I33 }, -{"wsbh", "d,w", 0x7c0000a0, 0xffe007ff, WR_d|RD_t, I33 }, -{"xor", "d,v,t", 0x00000026, 0xfc0007ff, WR_d|RD_s|RD_t, I1 }, -{"xor", "t,r,I", 0, (int) M_XOR_I, INSN_MACRO, I1 }, -{"xor.ob", "X,Y,Q", 0x7800000d, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX|SB1 }, -{"xor.ob", "D,S,T", 0x4ac0000d, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"xor.ob", "D,S,T[e]", 0x4800000d, 0xfe20003f, WR_D|RD_S|RD_T, N54 }, -{"xor.ob", "D,S,k", 0x4bc0000d, 0xffe0003f, WR_D|RD_S|RD_T, N54 }, -{"xor.qh", "X,Y,Q", 0x7820000d, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, MX }, -{"xori", "t,r,i", 0x38000000, 0xfc000000, WR_t|RD_s, I1 }, +{"standby", "", 0x42000021, 0xffffffff, 0, 0, V1 }, +{"sub", "d,v,t", 0x00000022, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, +{"sub", "d,v,I", 0, (int) M_SUB_I, INSN_MACRO, 0, I1 }, +{"sub.d", "D,V,T", 0x46200001, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I1 }, +{"sub.s", "D,V,T", 0x46000001, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I1 }, +{"sub.ob", "X,Y,Q", 0x7800000a, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"sub.ob", "D,S,T", 0x4ac0000a, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"sub.ob", "D,S,T[e]", 0x4800000a, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, +{"sub.ob", "D,S,k", 0x4bc0000a, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"sub.ps", "D,V,T", 0x46c00001, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I5 }, +{"sub.qh", "X,Y,Q", 0x7820000a, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"suba.ob", "Y,Q", 0x78000036, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, +{"suba.qh", "Y,Q", 0x78200036, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, +{"subl.ob", "Y,Q", 0x78000436, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, +{"subl.qh", "Y,Q", 0x78200436, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, +{"subu", "d,v,t", 0x00000023, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, +{"subu", "d,v,I", 0, (int) M_SUBU_I, INSN_MACRO, 0, I1 }, +{"suspend", "", 0x42000022, 0xffffffff, 0, 0, V1 }, +{"suxc1", "S,t(b)", 0x4c00000d, 0xfc0007ff, SM|RD_S|RD_t|RD_b, 0, I5|N55 }, +{"sw", "t,o(b)", 0xac000000, 0xfc000000, SM|RD_t|RD_b, 0, I1 }, +{"sw", "t,A(b)", 0, (int) M_SW_AB, INSN_MACRO, 0, I1 }, +{"swc0", "E,o(b)", 0xe0000000, 0xfc000000, SM|RD_C0|RD_b, 0, I1 }, +{"swc0", "E,A(b)", 0, (int) M_SWC0_AB, INSN_MACRO, 0, I1 }, +{"swc1", "T,o(b)", 0xe4000000, 0xfc000000, SM|RD_T|RD_b|FP_S, 0, I1 }, +{"swc1", "E,o(b)", 0xe4000000, 0xfc000000, SM|RD_T|RD_b|FP_S, 0, I1 }, +{"swc1", "T,A(b)", 0, (int) M_SWC1_AB, INSN_MACRO, 0, I1 }, +{"swc1", "E,A(b)", 0, (int) M_SWC1_AB, INSN_MACRO, 0, I1 }, +{"s.s", "T,o(b)", 0xe4000000, 0xfc000000, SM|RD_T|RD_b|FP_S, 0, I1 }, /* swc1 */ +{"s.s", "T,A(b)", 0, (int) M_SWC1_AB, INSN_MACRO, 0, I1 }, +{"swc2", "E,o(b)", 0xe8000000, 0xfc000000, SM|RD_C2|RD_b, 0, I1 }, +{"swc2", "E,A(b)", 0, (int) M_SWC2_AB, INSN_MACRO, 0, I1 }, +{"swc3", "E,o(b)", 0xec000000, 0xfc000000, SM|RD_C3|RD_b, 0, I1 }, +{"swc3", "E,A(b)", 0, (int) M_SWC3_AB, INSN_MACRO, 0, I1 }, +{"swl", "t,o(b)", 0xa8000000, 0xfc000000, SM|RD_t|RD_b, 0, I1 }, +{"swl", "t,A(b)", 0, (int) M_SWL_AB, INSN_MACRO, 0, I1 }, +{"scache", "t,o(b)", 0xa8000000, 0xfc000000, RD_t|RD_b, 0, I2 }, /* same */ +{"scache", "t,A(b)", 0, (int) M_SWL_AB, INSN_MACRO, 0, I2 }, /* as swl */ +{"swr", "t,o(b)", 0xb8000000, 0xfc000000, SM|RD_t|RD_b, 0, I1 }, +{"swr", "t,A(b)", 0, (int) M_SWR_AB, INSN_MACRO, 0, I1 }, +{"invalidate", "t,o(b)",0xb8000000, 0xfc000000, RD_t|RD_b, 0, I2 }, /* same */ +{"invalidate", "t,A(b)",0, (int) M_SWR_AB, INSN_MACRO, 0, I2 }, /* as swr */ +{"swxc1", "S,t(b)", 0x4c000008, 0xfc0007ff, SM|RD_S|RD_t|RD_b|FP_S, 0, I4|I33 }, +{"sync", "", 0x0000000f, 0xffffffff, INSN_SYNC, 0, I2|G1 }, +{"sync.p", "", 0x0000040f, 0xffffffff, INSN_SYNC, 0, I2 }, +{"sync.l", "", 0x0000000f, 0xffffffff, INSN_SYNC, 0, I2 }, +{"synci", "o(b)", 0x041f0000, 0xfc1f0000, SM|RD_b, 0, I33 }, +{"syncio", "", 0x0000004f, 0xffffffff, INSN_SYNC, 0, IOCTEON }, +{"synciobdma", "", 0x0000008f, 0xffffffff, INSN_SYNC, 0, IOCTEON }, +{"syncioall", "", 0x000000cf, 0xffffffff, INSN_SYNC, 0, IOCTEON }, +{"syncs", "", 0x0000018f, 0xffffffff, INSN_SYNC, 0, IOCTEON }, +{"syncw", "", 0x0000010f, 0xffffffff, INSN_SYNC, 0, IOCTEON }, +{"syncws", "", 0x0000014f, 0xffffffff, INSN_SYNC, 0, IOCTEON }, +{"syscall", "", 0x0000000c, 0xffffffff, TRAP, 0, I1 }, +{"syscall", "B", 0x0000000c, 0xfc00003f, TRAP, 0, I1 }, +{"teqi", "s,j", 0x040c0000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, +{"teq", "s,t", 0x00000034, 0xfc00ffff, RD_s|RD_t|TRAP, 0, I2 }, +{"teq", "s,t,q", 0x00000034, 0xfc00003f, RD_s|RD_t|TRAP, 0, I2 }, +{"teq", "s,j", 0x040c0000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, /* teqi */ +{"teq", "s,I", 0, (int) M_TEQ_I, INSN_MACRO, 0, I2 }, +{"tgei", "s,j", 0x04080000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, +{"tge", "s,t", 0x00000030, 0xfc00ffff, RD_s|RD_t|TRAP, 0, I2 }, +{"tge", "s,t,q", 0x00000030, 0xfc00003f, RD_s|RD_t|TRAP, 0, I2 }, +{"tge", "s,j", 0x04080000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, /* tgei */ +{"tge", "s,I", 0, (int) M_TGE_I, INSN_MACRO, 0, I2 }, +{"tgeiu", "s,j", 0x04090000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, +{"tgeu", "s,t", 0x00000031, 0xfc00ffff, RD_s|RD_t|TRAP, 0, I2 }, +{"tgeu", "s,t,q", 0x00000031, 0xfc00003f, RD_s|RD_t|TRAP, 0, I2 }, +{"tgeu", "s,j", 0x04090000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, /* tgeiu */ +{"tgeu", "s,I", 0, (int) M_TGEU_I, INSN_MACRO, 0, I2 }, +{"tlbp", "", 0x42000008, 0xffffffff, INSN_TLB, 0, I1 }, +{"tlbr", "", 0x42000001, 0xffffffff, INSN_TLB, 0, I1 }, +{"tlbwi", "", 0x42000002, 0xffffffff, INSN_TLB, 0, I1 }, +{"tlbwr", "", 0x42000006, 0xffffffff, INSN_TLB, 0, I1 }, +{"tlti", "s,j", 0x040a0000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, +{"tlt", "s,t", 0x00000032, 0xfc00ffff, RD_s|RD_t|TRAP, 0, I2 }, +{"tlt", "s,t,q", 0x00000032, 0xfc00003f, RD_s|RD_t|TRAP, 0, I2 }, +{"tlt", "s,j", 0x040a0000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, /* tlti */ +{"tlt", "s,I", 0, (int) M_TLT_I, INSN_MACRO, 0, I2 }, +{"tltiu", "s,j", 0x040b0000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, +{"tltu", "s,t", 0x00000033, 0xfc00ffff, RD_s|RD_t|TRAP, 0, I2 }, +{"tltu", "s,t,q", 0x00000033, 0xfc00003f, RD_s|RD_t|TRAP, 0, I2 }, +{"tltu", "s,j", 0x040b0000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, /* tltiu */ +{"tltu", "s,I", 0, (int) M_TLTU_I, INSN_MACRO, 0, I2 }, +{"tnei", "s,j", 0x040e0000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, +{"tne", "s,t", 0x00000036, 0xfc00ffff, RD_s|RD_t|TRAP, 0, I2 }, +{"tne", "s,t,q", 0x00000036, 0xfc00003f, RD_s|RD_t|TRAP, 0, I2 }, +{"tne", "s,j", 0x040e0000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, /* tnei */ +{"tne", "s,I", 0, (int) M_TNE_I, INSN_MACRO, 0, I2 }, +{"trunc.l.d", "D,S", 0x46200009, 0xffff003f, WR_D|RD_S|FP_D, 0, I3|I33 }, +{"trunc.l.s", "D,S", 0x46000009, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I3|I33 }, +{"trunc.w.d", "D,S", 0x4620000d, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I2 }, +{"trunc.w.d", "D,S,x", 0x4620000d, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I2 }, +{"trunc.w.d", "D,S,t", 0, (int) M_TRUNCWD, INSN_MACRO, 0, I1 }, +{"trunc.w.s", "D,S", 0x4600000d, 0xffff003f, WR_D|RD_S|FP_S, 0, I2 }, +{"trunc.w.s", "D,S,x", 0x4600000d, 0xffff003f, WR_D|RD_S|FP_S, 0, I2 }, +{"trunc.w.s", "D,S,t", 0, (int) M_TRUNCWS, INSN_MACRO, 0, I1 }, +{"uld", "t,o(b)", 0, (int) M_ULD, INSN_MACRO, 0, I3 }, +{"uld", "t,o(b)", 0x68000000, 0xfc000000, LDD|WR_t|RD_b, 0, IOCTEON }, +{"uld", "t,A(b)", 0, (int) M_ULD_A, INSN_MACRO, 0, I3 }, +{"ulh", "t,o(b)", 0, (int) M_ULH, INSN_MACRO, 0, I1 }, +{"ulh", "t,A(b)", 0, (int) M_ULH_A, INSN_MACRO, 0, I1 }, +{"ulhu", "t,o(b)", 0, (int) M_ULHU, INSN_MACRO, 0, I1 }, +{"ulhu", "t,A(b)", 0, (int) M_ULHU_A, INSN_MACRO, 0, I1 }, +{"ulw", "t,o(b)", 0, (int) M_ULW, INSN_MACRO, 0, I1 }, +{"ulw", "t,o(b)", 0x88000000, 0xfc000000, LDD|RD_b|WR_t, 0, IOCTEON }, +{"ulw", "t,A(b)", 0, (int) M_ULW_A, INSN_MACRO, 0, I1 }, +{"usd", "t,o(b)", 0, (int) M_USD, INSN_MACRO, 0, I3 }, +{"usd", "t,o(b)", 0xb0000000, 0xfc000000, SM|RD_t|RD_b, 0, IOCTEON }, +{"usd", "t,A(b)", 0, (int) M_USD_A, INSN_MACRO, 0, I3 }, +{"ush", "t,o(b)", 0, (int) M_USH, INSN_MACRO, 0, I1 }, +{"ush", "t,A(b)", 0, (int) M_USH_A, INSN_MACRO, 0, I1 }, +{"usw", "t,o(b)", 0, (int) M_USW, INSN_MACRO, 0, I1 }, +{"usw", "t,o(b)", 0xa8000000, 0xfc000000, SM|RD_t|RD_b, 0, IOCTEON }, +{"usw", "t,A(b)", 0, (int) M_USW_A, INSN_MACRO, 0, I1 }, +{"v3mulu", "d,v,t", 0x70000011, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IOCTEON }, +{"vmm0", "d,v,t", 0x70000010, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IOCTEON }, +{"vmulu", "d,v,t", 0x7000000f, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IOCTEON }, +{"wach.ob", "Y", 0x7a00003e, 0xffff07ff, RD_S|FP_D, WR_MACC, MX|SB1 }, +{"wach.ob", "S", 0x4a00003e, 0xffff07ff, RD_S, 0, N54 }, +{"wach.qh", "Y", 0x7a20003e, 0xffff07ff, RD_S|FP_D, WR_MACC, MX }, +{"wacl.ob", "Y,Z", 0x7800003e, 0xffe007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, +{"wacl.ob", "S,T", 0x4800003e, 0xffe007ff, RD_S|RD_T, 0, N54 }, +{"wacl.qh", "Y,Z", 0x7820003e, 0xffe007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, +{"wait", "", 0x42000020, 0xffffffff, TRAP, 0, I3|I32 }, +{"wait", "J", 0x42000020, 0xfe00003f, TRAP, 0, I32|N55 }, +{"waiti", "", 0x42000020, 0xffffffff, TRAP, 0, L1 }, +{"wb", "o(b)", 0xbc040000, 0xfc1f0000, SM|RD_b, 0, L1 }, +{"wrpgpr", "d,w", 0x41c00000, 0xffe007ff, RD_t, 0, I33 }, +{"wsbh", "d,w", 0x7c0000a0, 0xffe007ff, WR_d|RD_t, 0, I33 }, +{"xor", "d,v,t", 0x00000026, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, +{"xor", "t,r,I", 0, (int) M_XOR_I, INSN_MACRO, 0, I1 }, +{"xor.ob", "X,Y,Q", 0x7800000d, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, +{"xor.ob", "D,S,T", 0x4ac0000d, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"xor.ob", "D,S,T[e]", 0x4800000d, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, +{"xor.ob", "D,S,k", 0x4bc0000d, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, +{"xor.qh", "X,Y,Q", 0x7820000d, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, +{"xori", "t,r,i", 0x38000000, 0xfc000000, WR_t|RD_s, 0, I1 }, +{"yield", "s", 0x7c000009, 0xfc1fffff, TRAP|RD_s, 0, MT32 }, +{"yield", "d,s", 0x7c000009, 0xfc1f07ff, TRAP|WR_d|RD_s, 0, MT32 }, + +/* Coprocessor 2 move/branch operations overlap with VR5400 .ob format + instructions so they are here for the latters to take precedence. */ +{"bc2f", "p", 0x49000000, 0xffff0000, CBD|RD_CC, 0, I1 }, +{"bc2fl", "p", 0x49020000, 0xffff0000, CBL|RD_CC, 0, I2|T3 }, +{"bc2t", "p", 0x49010000, 0xffff0000, CBD|RD_CC, 0, I1 }, +{"bc2tl", "p", 0x49030000, 0xffff0000, CBL|RD_CC, 0, I2|T3 }, +{"cfc2", "t,G", 0x48400000, 0xffe007ff, LCD|WR_t|RD_C2, 0, I1 }, +{"ctc2", "t,G", 0x48c00000, 0xffe007ff, COD|RD_t|WR_CC, 0, I1 }, +{"dmfc2", "t,i", 0x48200000, 0xffe00000, LCD|WR_t|RD_C2, 0, IOCTEON }, +{"dmfc2", "t,G", 0x48200000, 0xffe007ff, LCD|WR_t|RD_C2, 0, I3 }, +{"dmfc2", "t,G,H", 0x48200000, 0xffe007f8, LCD|WR_t|RD_C2, 0, I64 }, +{"dmtc2", "t,i", 0x48a00000, 0xffe00000, COD|RD_t|WR_C2, 0, IOCTEON }, +{"dmtc2", "t,G", 0x48a00000, 0xffe007ff, COD|RD_t|WR_C2|WR_CC, 0, I3 }, +{"dmtc2", "t,G,H", 0x48a00000, 0xffe007f8, COD|RD_t|WR_C2|WR_CC, 0, I64 }, +{"mfc2", "t,G", 0x48000000, 0xffe007ff, LCD|WR_t|RD_C2, 0, I1 }, +{"mfc2", "t,G,H", 0x48000000, 0xffe007f8, LCD|WR_t|RD_C2, 0, I32 }, +{"mfhc2", "t,i", 0x48600000, 0xffe00000, LCD|WR_t|RD_C2, 0, I33 }, +{"mtc2", "t,G", 0x48800000, 0xffe007ff, COD|RD_t|WR_C2|WR_CC, 0, I1 }, +{"mtc2", "t,G,H", 0x48800000, 0xffe007f8, COD|RD_t|WR_C2|WR_CC, 0, I32 }, +{"mthc2", "t,i", 0x48e00000, 0xffe00000, COD|RD_t|WR_C2|WR_CC, 0, I33 }, /* 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 disassembler recognizes more specific versions first. */ -{"c0", "C", 0x42000000, 0xfe000000, 0, I1 }, -{"c1", "C", 0x46000000, 0xfe000000, 0, I1 }, -{"c2", "C", 0x4a000000, 0xfe000000, 0, I1 }, -{"c3", "C", 0x4e000000, 0xfe000000, 0, I1 }, -{"cop0", "C", 0, (int) M_COP0, INSN_MACRO, I1 }, -{"cop1", "C", 0, (int) M_COP1, INSN_MACRO, I1 }, -{"cop2", "C", 0, (int) M_COP2, INSN_MACRO, I1 }, -{"cop3", "C", 0, (int) M_COP3, INSN_MACRO, I1 }, +{"c0", "C", 0x42000000, 0xfe000000, 0, 0, I1 }, +{"c1", "C", 0x46000000, 0xfe000000, 0, 0, I1 }, +{"c2", "C", 0x4a000000, 0xfe000000, 0, 0, I1 }, +{"c3", "C", 0x4e000000, 0xfe000000, 0, 0, I1 }, +{"cop0", "C", 0, (int) M_COP0, INSN_MACRO, 0, I1 }, +{"cop1", "C", 0, (int) M_COP1, INSN_MACRO, 0, I1 }, +{"cop2", "C", 0, (int) M_COP2, INSN_MACRO, 0, I1 }, +{"cop3", "C", 0, (int) M_COP3, INSN_MACRO, 0, I1 }, /* 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 format gave us more info, we could do this right. */ -{"addciu", "t,r,j", 0x70000000, 0xfc000000, WR_t|RD_s, L1 }, +{"addciu", "t,r,j", 0x70000000, 0xfc000000, WR_t|RD_s, 0, L1 }, +/* MIPS DSP ASE */ +{"absq_s.ph", "d,t", 0x7c000252, 0xffe007ff, WR_d|RD_t, 0, D32 }, +{"absq_s.w", "d,t", 0x7c000452, 0xffe007ff, WR_d|RD_t, 0, D32 }, +{"addq.ph", "d,s,t", 0x7c000290, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"addq_s.ph", "d,s,t", 0x7c000390, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"addq_s.w", "d,s,t", 0x7c000590, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"addsc", "d,s,t", 0x7c000410, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"addu.qb", "d,s,t", 0x7c000010, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"addu_s.qb", "d,s,t", 0x7c000110, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"addwc", "d,s,t", 0x7c000450, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"bitrev", "d,t", 0x7c0006d2, 0xffe007ff, WR_d|RD_t, 0, D32 }, +{"bposge32", "p", 0x041c0000, 0xffff0000, CBD, 0, D32 }, +{"cmp.eq.ph", "s,t", 0x7c000211, 0xfc00ffff, RD_s|RD_t, 0, D32 }, +{"cmpgu.eq.qb", "d,s,t", 0x7c000111, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"cmpgu.le.qb", "d,s,t", 0x7c000191, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"cmpgu.lt.qb", "d,s,t", 0x7c000151, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"cmp.le.ph", "s,t", 0x7c000291, 0xfc00ffff, RD_s|RD_t, 0, D32 }, +{"cmp.lt.ph", "s,t", 0x7c000251, 0xfc00ffff, RD_s|RD_t, 0, D32 }, +{"cmpu.eq.qb", "s,t", 0x7c000011, 0xfc00ffff, RD_s|RD_t, 0, D32 }, +{"cmpu.le.qb", "s,t", 0x7c000091, 0xfc00ffff, RD_s|RD_t, 0, D32 }, +{"cmpu.lt.qb", "s,t", 0x7c000051, 0xfc00ffff, RD_s|RD_t, 0, D32 }, +{"dpaq_sa.l.w", "7,s,t", 0x7c000330, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, +{"dpaq_s.w.ph", "7,s,t", 0x7c000130, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, +{"dpau.h.qbl", "7,s,t", 0x7c0000f0, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, +{"dpau.h.qbr", "7,s,t", 0x7c0001f0, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, +{"dpsq_sa.l.w", "7,s,t", 0x7c000370, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, +{"dpsq_s.w.ph", "7,s,t", 0x7c000170, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, +{"dpsu.h.qbl", "7,s,t", 0x7c0002f0, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, +{"dpsu.h.qbr", "7,s,t", 0x7c0003f0, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, +{"extpdp", "t,7,6", 0x7c0002b8, 0xfc00e7ff, WR_t|RD_a|DSP_VOLA, 0, D32 }, +{"extpdpv", "t,7,s", 0x7c0002f8, 0xfc00e7ff, WR_t|RD_a|RD_s|DSP_VOLA, 0, D32 }, +{"extp", "t,7,6", 0x7c0000b8, 0xfc00e7ff, WR_t|RD_a, 0, D32 }, +{"extpv", "t,7,s", 0x7c0000f8, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D32 }, +{"extr_rs.w", "t,7,6", 0x7c0001b8, 0xfc00e7ff, WR_t|RD_a, 0, D32 }, +{"extr_r.w", "t,7,6", 0x7c000138, 0xfc00e7ff, WR_t|RD_a, 0, D32 }, +{"extr_s.h", "t,7,6", 0x7c0003b8, 0xfc00e7ff, WR_t|RD_a, 0, D32 }, +{"extrv_rs.w", "t,7,s", 0x7c0001f8, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D32 }, +{"extrv_r.w", "t,7,s", 0x7c000178, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D32 }, +{"extrv_s.h", "t,7,s", 0x7c0003f8, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D32 }, +{"extrv.w", "t,7,s", 0x7c000078, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D32 }, +{"extr.w", "t,7,6", 0x7c000038, 0xfc00e7ff, WR_t|RD_a, 0, D32 }, +{"insv", "t,s", 0x7c00000c, 0xfc00ffff, WR_t|RD_s, 0, D32 }, +{"lbux", "d,t(b)", 0x7c00018a, 0xfc0007ff, LDD|WR_d|RD_t|RD_b, 0, D32 }, +{"lhx", "d,t(b)", 0x7c00010a, 0xfc0007ff, LDD|WR_d|RD_t|RD_b, 0, D32 }, +{"lwx", "d,t(b)", 0x7c00000a, 0xfc0007ff, LDD|WR_d|RD_t|RD_b, 0, D32 }, +{"maq_sa.w.phl", "7,s,t", 0x7c000430, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, +{"maq_sa.w.phr", "7,s,t", 0x7c0004b0, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, +{"maq_s.w.phl", "7,s,t", 0x7c000530, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, +{"maq_s.w.phr", "7,s,t", 0x7c0005b0, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, +{"modsub", "d,s,t", 0x7c000490, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"mthlip", "s,7", 0x7c0007f8, 0xfc1fe7ff, RD_s|MOD_a|DSP_VOLA, 0, D32 }, +{"muleq_s.w.phl", "d,s,t", 0x7c000710, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D32 }, +{"muleq_s.w.phr", "d,s,t", 0x7c000750, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D32 }, +{"muleu_s.ph.qbl", "d,s,t", 0x7c000190, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D32 }, +{"muleu_s.ph.qbr", "d,s,t", 0x7c0001d0, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D32 }, +{"mulq_rs.ph", "d,s,t", 0x7c0007d0, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D32 }, +{"mulsaq_s.w.ph", "7,s,t", 0x7c0001b0, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, +{"packrl.ph", "d,s,t", 0x7c000391, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"pick.ph", "d,s,t", 0x7c0002d1, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"pick.qb", "d,s,t", 0x7c0000d1, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"precequ.ph.qbla", "d,t", 0x7c000192, 0xffe007ff, WR_d|RD_t, 0, D32 }, +{"precequ.ph.qbl", "d,t", 0x7c000112, 0xffe007ff, WR_d|RD_t, 0, D32 }, +{"precequ.ph.qbra", "d,t", 0x7c0001d2, 0xffe007ff, WR_d|RD_t, 0, D32 }, +{"precequ.ph.qbr", "d,t", 0x7c000152, 0xffe007ff, WR_d|RD_t, 0, D32 }, +{"preceq.w.phl", "d,t", 0x7c000312, 0xffe007ff, WR_d|RD_t, 0, D32 }, +{"preceq.w.phr", "d,t", 0x7c000352, 0xffe007ff, WR_d|RD_t, 0, D32 }, +{"preceu.ph.qbla", "d,t", 0x7c000792, 0xffe007ff, WR_d|RD_t, 0, D32 }, +{"preceu.ph.qbl", "d,t", 0x7c000712, 0xffe007ff, WR_d|RD_t, 0, D32 }, +{"preceu.ph.qbra", "d,t", 0x7c0007d2, 0xffe007ff, WR_d|RD_t, 0, D32 }, +{"preceu.ph.qbr", "d,t", 0x7c000752, 0xffe007ff, WR_d|RD_t, 0, D32 }, +{"precrq.ph.w", "d,s,t", 0x7c000511, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"precrq.qb.ph", "d,s,t", 0x7c000311, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"precrq_rs.ph.w", "d,s,t", 0x7c000551, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"precrqu_s.qb.ph", "d,s,t", 0x7c0003d1, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"raddu.w.qb", "d,s", 0x7c000510, 0xfc1f07ff, WR_d|RD_s, 0, D32 }, +{"rddsp", "d", 0x7fff04b8, 0xffff07ff, WR_d, 0, D32 }, +{"rddsp", "d,'", 0x7c0004b8, 0xffc007ff, WR_d, 0, D32 }, +{"repl.ph", "d,@", 0x7c000292, 0xfc0007ff, WR_d, 0, D32 }, +{"repl.qb", "d,5", 0x7c000092, 0xff0007ff, WR_d, 0, D32 }, +{"replv.ph", "d,t", 0x7c0002d2, 0xffe007ff, WR_d|RD_t, 0, D32 }, +{"replv.qb", "d,t", 0x7c0000d2, 0xffe007ff, WR_d|RD_t, 0, D32 }, +{"shilo", "7,0", 0x7c0006b8, 0xfc0fe7ff, MOD_a, 0, D32 }, +{"shilov", "7,s", 0x7c0006f8, 0xfc1fe7ff, MOD_a|RD_s, 0, D32 }, +{"shll.ph", "d,t,4", 0x7c000213, 0xfe0007ff, WR_d|RD_t, 0, D32 }, +{"shll.qb", "d,t,3", 0x7c000013, 0xff0007ff, WR_d|RD_t, 0, D32 }, +{"shll_s.ph", "d,t,4", 0x7c000313, 0xfe0007ff, WR_d|RD_t, 0, D32 }, +{"shll_s.w", "d,t,6", 0x7c000513, 0xfc0007ff, WR_d|RD_t, 0, D32 }, +{"shllv.ph", "d,t,s", 0x7c000293, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"shllv.qb", "d,t,s", 0x7c000093, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"shllv_s.ph", "d,t,s", 0x7c000393, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"shllv_s.w", "d,t,s", 0x7c000593, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"shra.ph", "d,t,4", 0x7c000253, 0xfe0007ff, WR_d|RD_t, 0, D32 }, +{"shra_r.ph", "d,t,4", 0x7c000353, 0xfe0007ff, WR_d|RD_t, 0, D32 }, +{"shra_r.w", "d,t,6", 0x7c000553, 0xfc0007ff, WR_d|RD_t, 0, D32 }, +{"shrav.ph", "d,t,s", 0x7c0002d3, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"shrav_r.ph", "d,t,s", 0x7c0003d3, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"shrav_r.w", "d,t,s", 0x7c0005d3, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"shrl.qb", "d,t,3", 0x7c000053, 0xff0007ff, WR_d|RD_t, 0, D32 }, +{"shrlv.qb", "d,t,s", 0x7c0000d3, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"subq.ph", "d,s,t", 0x7c0002d0, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"subq_s.ph", "d,s,t", 0x7c0003d0, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"subq_s.w", "d,s,t", 0x7c0005d0, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"subu.qb", "d,s,t", 0x7c000050, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"subu_s.qb", "d,s,t", 0x7c000150, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, +{"wrdsp", "s", 0x7c1ffcf8, 0xfc1fffff, RD_s|DSP_VOLA, 0, D32 }, +{"wrdsp", "s,8", 0x7c0004f8, 0xfc1e07ff, RD_s|DSP_VOLA, 0, D32 }, +/* Move bc0* after mftr and mttr to avoid opcode collision. */ +{"bc0f", "p", 0x41000000, 0xffff0000, CBD|RD_CC, 0, I1 }, +{"bc0fl", "p", 0x41020000, 0xffff0000, CBL|RD_CC, 0, I2|T3 }, +{"bc0t", "p", 0x41010000, 0xffff0000, CBD|RD_CC, 0, I1 }, +{"bc0tl", "p", 0x41030000, 0xffff0000, CBL|RD_CC, 0, I2|T3 }, }; #define MIPS_NUM_OPCODES \ diff --git a/contrib/binutils/opcodes/mips16-opc.c b/contrib/binutils/opcodes/mips16-opc.c index d7fcfc24ac44..4e5ae44752f3 100644 --- a/contrib/binutils/opcodes/mips16-opc.c +++ b/contrib/binutils/opcodes/mips16-opc.c @@ -1,5 +1,5 @@ /* mips16-opc.c. Mips16 opcode table. - Copyright 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + Copyright 1996, 1997, 1998, 2000, 2005 Free Software Foundation, Inc. Contributed by Ian Lance Taylor, Cygnus Support This file is part of GDB, GAS, and the GNU binutils. @@ -16,8 +16,8 @@ the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this file; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ +Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA +02110-1301, USA. */ #include #include "sysdep.h" @@ -64,163 +64,176 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA const struct mips_opcode mips16_opcodes[] = { -{"nop", "", 0x6500, 0xffff, RD_Z, 0 }, /* move $0,$Z */ -{"la", "x,A", 0x0800, 0xf800, WR_x|RD_PC, 0 }, -{"abs", "x,w", 0, (int) M_ABS, INSN_MACRO, 0 }, -{"addiu", "y,x,4", 0x4000, 0xf810, WR_y|RD_x, 0 }, -{"addiu", "x,k", 0x4800, 0xf800, WR_x|RD_x, 0 }, -{"addiu", "S,K", 0x6300, 0xff00, WR_SP|RD_SP, 0 }, -{"addiu", "S,S,K", 0x6300, 0xff00, WR_SP|RD_SP, 0 }, -{"addiu", "x,P,V", 0x0800, 0xf800, WR_x|RD_PC, 0 }, -{"addiu", "x,S,V", 0x0000, 0xf800, WR_x|RD_SP, 0 }, -{"addu", "z,v,y", 0xe001, 0xf803, WR_z|RD_x|RD_y, 0 }, -{"addu", "y,x,4", 0x4000, 0xf810, WR_y|RD_x, 0 }, -{"addu", "x,k", 0x4800, 0xf800, WR_x|RD_x, 0 }, -{"addu", "S,K", 0x6300, 0xff00, WR_SP|RD_SP, 0 }, -{"addu", "S,S,K", 0x6300, 0xff00, WR_SP|RD_SP, 0 }, -{"addu", "x,P,V", 0x0800, 0xf800, WR_x|RD_PC, 0 }, -{"addu", "x,S,V", 0x0000, 0xf800, WR_x|RD_SP, 0 }, -{"and", "x,y", 0xe80c, 0xf81f, WR_x|RD_x|RD_y, 0 }, -{"b", "q", 0x1000, 0xf800, BR, 0 }, -{"beq", "x,y,p", 0, (int) M_BEQ, INSN_MACRO, 0 }, -{"beq", "x,U,p", 0, (int) M_BEQ_I, INSN_MACRO, 0 }, -{"beqz", "x,p", 0x2000, 0xf800, BR|RD_x, 0 }, -{"bge", "x,y,p", 0, (int) M_BGE, INSN_MACRO, 0 }, -{"bge", "x,8,p", 0, (int) M_BGE_I, INSN_MACRO, 0 }, -{"bgeu", "x,y,p", 0, (int) M_BGEU, INSN_MACRO, 0 }, -{"bgeu", "x,8,p", 0, (int) M_BGEU_I, INSN_MACRO, 0 }, -{"bgt", "x,y,p", 0, (int) M_BGT, INSN_MACRO, 0 }, -{"bgt", "x,8,p", 0, (int) M_BGT_I, INSN_MACRO, 0 }, -{"bgtu", "x,y,p", 0, (int) M_BGTU, INSN_MACRO, 0 }, -{"bgtu", "x,8,p", 0, (int) M_BGTU_I, INSN_MACRO, 0 }, -{"ble", "x,y,p", 0, (int) M_BLE, INSN_MACRO, 0 }, -{"ble", "x,8,p", 0, (int) M_BLE_I, INSN_MACRO, 0 }, -{"bleu", "x,y,p", 0, (int) M_BLEU, INSN_MACRO, 0 }, -{"bleu", "x,8,p", 0, (int) M_BLEU_I, INSN_MACRO, 0 }, -{"blt", "x,y,p", 0, (int) M_BLT, INSN_MACRO, 0 }, -{"blt", "x,8,p", 0, (int) M_BLT_I, INSN_MACRO, 0 }, -{"bltu", "x,y,p", 0, (int) M_BLTU, INSN_MACRO, 0 }, -{"bltu", "x,8,p", 0, (int) M_BLTU_I, INSN_MACRO, 0 }, -{"bne", "x,y,p", 0, (int) M_BNE, INSN_MACRO, 0 }, -{"bne", "x,U,p", 0, (int) M_BNE_I, INSN_MACRO, 0 }, -{"bnez", "x,p", 0x2800, 0xf800, BR|RD_x, 0 }, -{"break", "6", 0xe805, 0xf81f, TRAP, 0 }, -{"bteqz", "p", 0x6000, 0xff00, BR|RD_T, 0 }, -{"btnez", "p", 0x6100, 0xff00, BR|RD_T, 0 }, -{"cmpi", "x,U", 0x7000, 0xf800, WR_T|RD_x, 0 }, -{"cmp", "x,y", 0xe80a, 0xf81f, WR_T|RD_x|RD_y, 0 }, -{"cmp", "x,U", 0x7000, 0xf800, WR_T|RD_x, 0 }, -{"dla", "y,E", 0xfe00, 0xff00, WR_y|RD_PC, I3 }, -{"daddiu", "y,x,4", 0x4010, 0xf810, WR_y|RD_x, I3 }, -{"daddiu", "y,j", 0xfd00, 0xff00, WR_y|RD_y, I3 }, -{"daddiu", "S,K", 0xfb00, 0xff00, WR_SP|RD_SP, I3 }, -{"daddiu", "S,S,K", 0xfb00, 0xff00, WR_SP|RD_SP, I3 }, -{"daddiu", "y,P,W", 0xfe00, 0xff00, WR_y|RD_PC, I3 }, -{"daddiu", "y,S,W", 0xff00, 0xff00, WR_y|RD_SP, I3 }, -{"daddu", "z,v,y", 0xe000, 0xf803, WR_z|RD_x|RD_y, I3 }, -{"daddu", "y,x,4", 0x4010, 0xf810, WR_y|RD_x, I3 }, -{"daddu", "y,j", 0xfd00, 0xff00, WR_y|RD_y, I3 }, -{"daddu", "S,K", 0xfb00, 0xff00, WR_SP|RD_SP, I3 }, -{"daddu", "S,S,K", 0xfb00, 0xff00, WR_SP|RD_SP, I3 }, -{"daddu", "y,P,W", 0xfe00, 0xff00, WR_y|RD_PC, I3 }, -{"daddu", "y,S,W", 0xff00, 0xff00, WR_y|RD_SP, I3 }, -{"ddiv", "0,x,y", 0xe81e, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, I3 }, -{"ddiv", "z,v,y", 0, (int) M_DDIV_3, INSN_MACRO, 0 }, -{"ddivu", "0,x,y", 0xe81f, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, I3 }, -{"ddivu", "z,v,y", 0, (int) M_DDIVU_3, INSN_MACRO, 0 }, -{"div", "0,x,y", 0xe81a, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0 }, -{"div", "z,v,y", 0, (int) M_DIV_3, INSN_MACRO, 0 }, -{"divu", "0,x,y", 0xe81b, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0 }, -{"divu", "z,v,y", 0, (int) M_DIVU_3, INSN_MACRO, 0 }, -{"dmul", "z,v,y", 0, (int) M_DMUL, INSN_MACRO, I3 }, -{"dmult", "x,y", 0xe81c, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, I3 }, -{"dmultu", "x,y", 0xe81d, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, I3 }, -{"drem", "0,x,y", 0xe81e, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, I3 }, -{"drem", "z,v,y", 0, (int) M_DREM_3, INSN_MACRO, 0 }, -{"dremu", "0,x,y", 0xe81f, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, I3 }, -{"dremu", "z,v,y", 0, (int) M_DREMU_3, INSN_MACRO, 0 }, -{"dsllv", "y,x", 0xe814, 0xf81f, WR_y|RD_y|RD_x, I3 }, -{"dsll", "x,w,[", 0x3001, 0xf803, WR_x|RD_y, I3 }, -{"dsll", "y,x", 0xe814, 0xf81f, WR_y|RD_y|RD_x, I3 }, -{"dsrav", "y,x", 0xe817, 0xf81f, WR_y|RD_y|RD_x, I3 }, -{"dsra", "y,]", 0xe813, 0xf81f, WR_y|RD_y, I3 }, -{"dsra", "y,x", 0xe817, 0xf81f, WR_y|RD_y|RD_x, I3 }, -{"dsrlv", "y,x", 0xe816, 0xf81f, WR_y|RD_y|RD_x, I3 }, -{"dsrl", "y,]", 0xe808, 0xf81f, WR_y|RD_y, I3 }, -{"dsrl", "y,x", 0xe816, 0xf81f, WR_y|RD_y|RD_x, I3 }, -{"dsubu", "z,v,y", 0xe002, 0xf803, WR_z|RD_x|RD_y, I3 }, -{"dsubu", "y,x,4", 0, (int) M_DSUBU_I, INSN_MACRO, 0 }, -{"dsubu", "y,j", 0, (int) M_DSUBU_I_2, INSN_MACRO, 0 }, -{"exit", "L", 0xed09, 0xff1f, TRAP, 0 }, -{"exit", "L", 0xee09, 0xff1f, TRAP, 0 }, -{"exit", "L", 0xef09, 0xff1f, TRAP, 0 }, -{"entry", "l", 0xe809, 0xf81f, TRAP, 0 }, -{"extend", "e", 0xf000, 0xf800, 0, 0 }, -{"jalr", "x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0 }, -{"jalr", "R,x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0 }, -{"jal", "x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0 }, -{"jal", "R,x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0 }, -{"jal", "a", 0x1800, 0xfc00, UBD|WR_31, 0 }, -{"jalx", "a", 0x1c00, 0xfc00, UBD|WR_31, 0 }, -{"jr", "x", 0xe800, 0xf8ff, UBD|RD_x, 0 }, -{"jr", "R", 0xe820, 0xffff, UBD|RD_31, 0 }, -{"j", "x", 0xe800, 0xf8ff, UBD|RD_x, 0 }, -{"j", "R", 0xe820, 0xffff, UBD|RD_31, 0 }, -{"lb", "y,5(x)", 0x8000, 0xf800, WR_y|RD_x, 0 }, -{"lbu", "y,5(x)", 0xa000, 0xf800, WR_y|RD_x, 0 }, -{"ld", "y,D(x)", 0x3800, 0xf800, WR_y|RD_x, I3 }, -{"ld", "y,B", 0xfc00, 0xff00, WR_y|RD_PC, I3 }, -{"ld", "y,D(P)", 0xfc00, 0xff00, WR_y|RD_PC, I3 }, -{"ld", "y,D(S)", 0xf800, 0xff00, WR_y|RD_SP, I3 }, -{"lh", "y,H(x)", 0x8800, 0xf800, WR_y|RD_x, 0 }, -{"lhu", "y,H(x)", 0xa800, 0xf800, WR_y|RD_x, 0 }, -{"li", "x,U", 0x6800, 0xf800, WR_x, 0 }, -{"lw", "y,W(x)", 0x9800, 0xf800, WR_y|RD_x, 0 }, -{"lw", "x,A", 0xb000, 0xf800, WR_x|RD_PC, 0 }, -{"lw", "x,V(P)", 0xb000, 0xf800, WR_x|RD_PC, 0 }, -{"lw", "x,V(S)", 0x9000, 0xf800, WR_x|RD_SP, 0 }, -{"lwu", "y,W(x)", 0xb800, 0xf800, WR_y|RD_x, I3 }, -{"mfhi", "x", 0xe810, 0xf8ff, WR_x|RD_HI, 0 }, -{"mflo", "x", 0xe812, 0xf8ff, WR_x|RD_LO, 0 }, -{"move", "y,X", 0x6700, 0xff00, WR_y|RD_X, 0 }, -{"move", "Y,Z", 0x6500, 0xff00, WR_Y|RD_Z, 0 }, -{"mul", "z,v,y", 0, (int) M_MUL, INSN_MACRO, 0 }, -{"mult", "x,y", 0xe818, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0 }, -{"multu", "x,y", 0xe819, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0 }, -{"neg", "x,w", 0xe80b, 0xf81f, WR_x|RD_y, 0 }, -{"not", "x,w", 0xe80f, 0xf81f, WR_x|RD_y, 0 }, -{"or", "x,y", 0xe80d, 0xf81f, WR_x|RD_x|RD_y, 0 }, -{"rem", "0,x,y", 0xe81a, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0 }, -{"rem", "z,v,y", 0, (int) M_REM_3, INSN_MACRO, 0 }, -{"remu", "0,x,y", 0xe81b, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0 }, -{"remu", "z,v,y", 0, (int) M_REMU_3, INSN_MACRO, 0 }, -{"sb", "y,5(x)", 0xc000, 0xf800, RD_y|RD_x, 0 }, -{"sd", "y,D(x)", 0x7800, 0xf800, RD_y|RD_x, I3 }, -{"sd", "y,D(S)", 0xf900, 0xff00, RD_y|RD_PC, I3 }, -{"sd", "R,C(S)", 0xfa00, 0xff00, RD_31|RD_PC, 0 }, -{"sh", "y,H(x)", 0xc800, 0xf800, RD_y|RD_x, 0 }, -{"sllv", "y,x", 0xe804, 0xf81f, WR_y|RD_y|RD_x, 0 }, -{"sll", "x,w,<", 0x3000, 0xf803, WR_x|RD_y, 0 }, -{"sll", "y,x", 0xe804, 0xf81f, WR_y|RD_y|RD_x, 0 }, -{"slti", "x,8", 0x5000, 0xf800, WR_T|RD_x, 0 }, -{"slt", "x,y", 0xe802, 0xf81f, WR_T|RD_x|RD_y, 0 }, -{"slt", "x,8", 0x5000, 0xf800, WR_T|RD_x, 0 }, -{"sltiu", "x,8", 0x5800, 0xf800, WR_T|RD_x, 0 }, -{"sltu", "x,y", 0xe803, 0xf81f, WR_T|RD_x|RD_y, 0 }, -{"sltu", "x,8", 0x5800, 0xf800, WR_T|RD_x, 0 }, -{"srav", "y,x", 0xe807, 0xf81f, WR_y|RD_y|RD_x, 0 }, -{"sra", "x,w,<", 0x3003, 0xf803, WR_x|RD_y, 0 }, -{"sra", "y,x", 0xe807, 0xf81f, WR_y|RD_y|RD_x, 0 }, -{"srlv", "y,x", 0xe806, 0xf81f, WR_y|RD_y|RD_x, 0 }, -{"srl", "x,w,<", 0x3002, 0xf803, WR_x|RD_y, 0 }, -{"srl", "y,x", 0xe806, 0xf81f, WR_y|RD_y|RD_x, 0 }, -{"subu", "z,v,y", 0xe003, 0xf803, WR_z|RD_x|RD_y, 0 }, -{"subu", "y,x,4", 0, (int) M_SUBU_I, INSN_MACRO, 0 }, -{"subu", "x,k", 0, (int) M_SUBU_I_2, INSN_MACRO,0 }, -{"sw", "y,W(x)", 0xd800, 0xf800, RD_y|RD_x, 0 }, -{"sw", "x,V(S)", 0xd000, 0xf800, RD_x|RD_SP, 0 }, -{"sw", "R,V(S)", 0x6200, 0xff00, RD_31|RD_SP, 0 }, -{"xor", "x,y", 0xe80e, 0xf81f, WR_x|RD_x|RD_y, 0 }, +{"nop", "", 0x6500, 0xffff, RD_Z, 0, 0 }, /* move $0,$Z */ +{"la", "x,A", 0x0800, 0xf800, WR_x|RD_PC, 0, 0 }, +{"abs", "x,w", 0, (int) M_ABS, INSN_MACRO, 0, 0 }, +{"addiu", "y,x,4", 0x4000, 0xf810, WR_y|RD_x, 0, 0 }, +{"addiu", "x,k", 0x4800, 0xf800, WR_x|RD_x, 0, 0 }, +{"addiu", "S,K", 0x6300, 0xff00, WR_SP|RD_SP, 0, 0 }, +{"addiu", "S,S,K", 0x6300, 0xff00, WR_SP|RD_SP, 0, 0 }, +{"addiu", "x,P,V", 0x0800, 0xf800, WR_x|RD_PC, 0, 0 }, +{"addiu", "x,S,V", 0x0000, 0xf800, WR_x|RD_SP, 0, 0 }, +{"addu", "z,v,y", 0xe001, 0xf803, WR_z|RD_x|RD_y, 0, 0 }, +{"addu", "y,x,4", 0x4000, 0xf810, WR_y|RD_x, 0, 0 }, +{"addu", "x,k", 0x4800, 0xf800, WR_x|RD_x, 0, 0 }, +{"addu", "S,K", 0x6300, 0xff00, WR_SP|RD_SP, 0, 0 }, +{"addu", "S,S,K", 0x6300, 0xff00, WR_SP|RD_SP, 0, 0 }, +{"addu", "x,P,V", 0x0800, 0xf800, WR_x|RD_PC, 0, 0 }, +{"addu", "x,S,V", 0x0000, 0xf800, WR_x|RD_SP, 0, 0 }, +{"and", "x,y", 0xe80c, 0xf81f, WR_x|RD_x|RD_y, 0, 0 }, +{"b", "q", 0x1000, 0xf800, BR, 0, 0 }, +{"beq", "x,y,p", 0, (int) M_BEQ, INSN_MACRO, 0, 0 }, +{"beq", "x,U,p", 0, (int) M_BEQ_I, INSN_MACRO, 0, 0 }, +{"beqz", "x,p", 0x2000, 0xf800, BR|RD_x, 0, 0 }, +{"bge", "x,y,p", 0, (int) M_BGE, INSN_MACRO, 0, 0 }, +{"bge", "x,8,p", 0, (int) M_BGE_I, INSN_MACRO, 0, 0 }, +{"bgeu", "x,y,p", 0, (int) M_BGEU, INSN_MACRO, 0, 0 }, +{"bgeu", "x,8,p", 0, (int) M_BGEU_I, INSN_MACRO, 0, 0 }, +{"bgt", "x,y,p", 0, (int) M_BGT, INSN_MACRO, 0, 0 }, +{"bgt", "x,8,p", 0, (int) M_BGT_I, INSN_MACRO, 0, 0 }, +{"bgtu", "x,y,p", 0, (int) M_BGTU, INSN_MACRO, 0, 0 }, +{"bgtu", "x,8,p", 0, (int) M_BGTU_I, INSN_MACRO, 0, 0 }, +{"ble", "x,y,p", 0, (int) M_BLE, INSN_MACRO, 0, 0 }, +{"ble", "x,8,p", 0, (int) M_BLE_I, INSN_MACRO, 0, 0 }, +{"bleu", "x,y,p", 0, (int) M_BLEU, INSN_MACRO, 0, 0 }, +{"bleu", "x,8,p", 0, (int) M_BLEU_I, INSN_MACRO, 0, 0 }, +{"blt", "x,y,p", 0, (int) M_BLT, INSN_MACRO, 0, 0 }, +{"blt", "x,8,p", 0, (int) M_BLT_I, INSN_MACRO, 0, 0 }, +{"bltu", "x,y,p", 0, (int) M_BLTU, INSN_MACRO, 0, 0 }, +{"bltu", "x,8,p", 0, (int) M_BLTU_I, INSN_MACRO, 0, 0 }, +{"bne", "x,y,p", 0, (int) M_BNE, INSN_MACRO, 0, 0 }, +{"bne", "x,U,p", 0, (int) M_BNE_I, INSN_MACRO, 0, 0 }, +{"bnez", "x,p", 0x2800, 0xf800, BR|RD_x, 0, 0 }, +{"break", "6", 0xe805, 0xf81f, TRAP, 0, 0 }, +{"bteqz", "p", 0x6000, 0xff00, BR|RD_T, 0, 0 }, +{"btnez", "p", 0x6100, 0xff00, BR|RD_T, 0, 0 }, +{"cmpi", "x,U", 0x7000, 0xf800, WR_T|RD_x, 0, 0 }, +{"cmp", "x,y", 0xe80a, 0xf81f, WR_T|RD_x|RD_y, 0, 0 }, +{"cmp", "x,U", 0x7000, 0xf800, WR_T|RD_x, 0, 0 }, +{"dla", "y,E", 0xfe00, 0xff00, WR_y|RD_PC, 0, I3 }, +{"daddiu", "y,x,4", 0x4010, 0xf810, WR_y|RD_x, 0, I3 }, +{"daddiu", "y,j", 0xfd00, 0xff00, WR_y|RD_y, 0, I3 }, +{"daddiu", "S,K", 0xfb00, 0xff00, WR_SP|RD_SP, 0, I3 }, +{"daddiu", "S,S,K", 0xfb00, 0xff00, WR_SP|RD_SP, 0, I3 }, +{"daddiu", "y,P,W", 0xfe00, 0xff00, WR_y|RD_PC, 0, I3 }, +{"daddiu", "y,S,W", 0xff00, 0xff00, WR_y|RD_SP, 0, I3 }, +{"daddu", "z,v,y", 0xe000, 0xf803, WR_z|RD_x|RD_y, 0, I3 }, +{"daddu", "y,x,4", 0x4010, 0xf810, WR_y|RD_x, 0, I3 }, +{"daddu", "y,j", 0xfd00, 0xff00, WR_y|RD_y, 0, I3 }, +{"daddu", "S,K", 0xfb00, 0xff00, WR_SP|RD_SP, 0, I3 }, +{"daddu", "S,S,K", 0xfb00, 0xff00, WR_SP|RD_SP, 0, I3 }, +{"daddu", "y,P,W", 0xfe00, 0xff00, WR_y|RD_PC, 0, I3 }, +{"daddu", "y,S,W", 0xff00, 0xff00, WR_y|RD_SP, 0, I3 }, +{"ddiv", "0,x,y", 0xe81e, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 }, +{"ddiv", "z,v,y", 0, (int) M_DDIV_3, INSN_MACRO, 0, 0 }, +{"ddivu", "0,x,y", 0xe81f, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 }, +{"ddivu", "z,v,y", 0, (int) M_DDIVU_3, INSN_MACRO, 0, 0 }, +{"div", "0,x,y", 0xe81a, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, 0 }, +{"div", "z,v,y", 0, (int) M_DIV_3, INSN_MACRO, 0, 0 }, +{"divu", "0,x,y", 0xe81b, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, 0 }, +{"divu", "z,v,y", 0, (int) M_DIVU_3, INSN_MACRO, 0, 0 }, +{"dmul", "z,v,y", 0, (int) M_DMUL, INSN_MACRO, 0, I3 }, +{"dmult", "x,y", 0xe81c, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 }, +{"dmultu", "x,y", 0xe81d, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 }, +{"drem", "0,x,y", 0xe81e, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 }, +{"drem", "z,v,y", 0, (int) M_DREM_3, INSN_MACRO, 0, 0 }, +{"dremu", "0,x,y", 0xe81f, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 }, +{"dremu", "z,v,y", 0, (int) M_DREMU_3, INSN_MACRO, 0, 0 }, +{"dsllv", "y,x", 0xe814, 0xf81f, WR_y|RD_y|RD_x, 0, I3 }, +{"dsll", "x,w,[", 0x3001, 0xf803, WR_x|RD_y, 0, I3 }, +{"dsll", "y,x", 0xe814, 0xf81f, WR_y|RD_y|RD_x, 0, I3 }, +{"dsrav", "y,x", 0xe817, 0xf81f, WR_y|RD_y|RD_x, 0, I3 }, +{"dsra", "y,]", 0xe813, 0xf81f, WR_y|RD_y, 0, I3 }, +{"dsra", "y,x", 0xe817, 0xf81f, WR_y|RD_y|RD_x, 0, I3 }, +{"dsrlv", "y,x", 0xe816, 0xf81f, WR_y|RD_y|RD_x, 0, I3 }, +{"dsrl", "y,]", 0xe808, 0xf81f, WR_y|RD_y, 0, I3 }, +{"dsrl", "y,x", 0xe816, 0xf81f, WR_y|RD_y|RD_x, 0, I3 }, +{"dsubu", "z,v,y", 0xe002, 0xf803, WR_z|RD_x|RD_y, 0, I3 }, +{"dsubu", "y,x,4", 0, (int) M_DSUBU_I, INSN_MACRO, 0, 0 }, +{"dsubu", "y,j", 0, (int) M_DSUBU_I_2, INSN_MACRO, 0, 0 }, +{"exit", "L", 0xed09, 0xff1f, TRAP, 0, 0 }, +{"exit", "L", 0xee09, 0xff1f, TRAP, 0, 0 }, +{"exit", "L", 0xef09, 0xff1f, TRAP, 0, 0 }, +{"entry", "l", 0xe809, 0xf81f, TRAP, 0, 0 }, +{"extend", "e", 0xf000, 0xf800, 0, 0, 0 }, +{"jalr", "x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0, 0 }, +{"jalr", "R,x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0, 0 }, +{"jal", "x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0, 0 }, +{"jal", "R,x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0, 0 }, +{"jal", "a", 0x1800, 0xfc00, UBD|WR_31, 0, 0 }, +{"jalx", "a", 0x1c00, 0xfc00, UBD|WR_31, 0, 0 }, +{"jr", "x", 0xe800, 0xf8ff, UBD|RD_x, 0, 0 }, +{"jr", "R", 0xe820, 0xffff, UBD|RD_31, 0, 0 }, +{"j", "x", 0xe800, 0xf8ff, UBD|RD_x, 0, 0 }, +{"j", "R", 0xe820, 0xffff, UBD|RD_31, 0, 0 }, +{"lb", "y,5(x)", 0x8000, 0xf800, WR_y|RD_x, 0, 0 }, +{"lbu", "y,5(x)", 0xa000, 0xf800, WR_y|RD_x, 0, 0 }, +{"ld", "y,D(x)", 0x3800, 0xf800, WR_y|RD_x, 0, I3 }, +{"ld", "y,B", 0xfc00, 0xff00, WR_y|RD_PC, 0, I3 }, +{"ld", "y,D(P)", 0xfc00, 0xff00, WR_y|RD_PC, 0, I3 }, +{"ld", "y,D(S)", 0xf800, 0xff00, WR_y|RD_SP, 0, I3 }, +{"lh", "y,H(x)", 0x8800, 0xf800, WR_y|RD_x, 0, 0 }, +{"lhu", "y,H(x)", 0xa800, 0xf800, WR_y|RD_x, 0, 0 }, +{"li", "x,U", 0x6800, 0xf800, WR_x, 0, 0 }, +{"lw", "y,W(x)", 0x9800, 0xf800, WR_y|RD_x, 0, 0 }, +{"lw", "x,A", 0xb000, 0xf800, WR_x|RD_PC, 0, 0 }, +{"lw", "x,V(P)", 0xb000, 0xf800, WR_x|RD_PC, 0, 0 }, +{"lw", "x,V(S)", 0x9000, 0xf800, WR_x|RD_SP, 0, 0 }, +{"lwu", "y,W(x)", 0xb800, 0xf800, WR_y|RD_x, 0, I3 }, +{"mfhi", "x", 0xe810, 0xf8ff, WR_x|RD_HI, 0, 0 }, +{"mflo", "x", 0xe812, 0xf8ff, WR_x|RD_LO, 0, 0 }, +{"move", "y,X", 0x6700, 0xff00, WR_y|RD_X, 0, 0 }, +{"move", "Y,Z", 0x6500, 0xff00, WR_Y|RD_Z, 0, 0 }, +{"mul", "z,v,y", 0, (int) M_MUL, INSN_MACRO, 0, 0 }, +{"mult", "x,y", 0xe818, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, 0 }, +{"multu", "x,y", 0xe819, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, 0 }, +{"neg", "x,w", 0xe80b, 0xf81f, WR_x|RD_y, 0, 0 }, +{"not", "x,w", 0xe80f, 0xf81f, WR_x|RD_y, 0, 0 }, +{"or", "x,y", 0xe80d, 0xf81f, WR_x|RD_x|RD_y, 0, 0 }, +{"rem", "0,x,y", 0xe81a, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, 0 }, +{"rem", "z,v,y", 0, (int) M_REM_3, INSN_MACRO, 0, 0 }, +{"remu", "0,x,y", 0xe81b, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, 0 }, +{"remu", "z,v,y", 0, (int) M_REMU_3, INSN_MACRO, 0, 0 }, +{"sb", "y,5(x)", 0xc000, 0xf800, RD_y|RD_x, 0, 0 }, +{"sd", "y,D(x)", 0x7800, 0xf800, RD_y|RD_x, 0, I3 }, +{"sd", "y,D(S)", 0xf900, 0xff00, RD_y|RD_PC, 0, I3 }, +{"sd", "R,C(S)", 0xfa00, 0xff00, RD_31|RD_PC, 0, 0 }, +{"sh", "y,H(x)", 0xc800, 0xf800, RD_y|RD_x, 0, 0 }, +{"sllv", "y,x", 0xe804, 0xf81f, WR_y|RD_y|RD_x, 0, 0 }, +{"sll", "x,w,<", 0x3000, 0xf803, WR_x|RD_y, 0, 0 }, +{"sll", "y,x", 0xe804, 0xf81f, WR_y|RD_y|RD_x, 0, 0 }, +{"slti", "x,8", 0x5000, 0xf800, WR_T|RD_x, 0, 0 }, +{"slt", "x,y", 0xe802, 0xf81f, WR_T|RD_x|RD_y, 0, 0 }, +{"slt", "x,8", 0x5000, 0xf800, WR_T|RD_x, 0, 0 }, +{"sltiu", "x,8", 0x5800, 0xf800, WR_T|RD_x, 0, 0 }, +{"sltu", "x,y", 0xe803, 0xf81f, WR_T|RD_x|RD_y, 0, 0 }, +{"sltu", "x,8", 0x5800, 0xf800, WR_T|RD_x, 0, 0 }, +{"srav", "y,x", 0xe807, 0xf81f, WR_y|RD_y|RD_x, 0, 0 }, +{"sra", "x,w,<", 0x3003, 0xf803, WR_x|RD_y, 0, 0 }, +{"sra", "y,x", 0xe807, 0xf81f, WR_y|RD_y|RD_x, 0, 0 }, +{"srlv", "y,x", 0xe806, 0xf81f, WR_y|RD_y|RD_x, 0, 0 }, +{"srl", "x,w,<", 0x3002, 0xf803, WR_x|RD_y, 0, 0 }, +{"srl", "y,x", 0xe806, 0xf81f, WR_y|RD_y|RD_x, 0, 0 }, +{"subu", "z,v,y", 0xe003, 0xf803, WR_z|RD_x|RD_y, 0, 0 }, +{"subu", "y,x,4", 0, (int) M_SUBU_I, INSN_MACRO, 0, 0 }, +{"subu", "x,k", 0, (int) M_SUBU_I_2, INSN_MACRO,0, 0 }, +{"sw", "y,W(x)", 0xd800, 0xf800, RD_y|RD_x, 0, 0 }, +{"sw", "x,V(S)", 0xd000, 0xf800, RD_x|RD_SP, 0, 0 }, +{"sw", "R,V(S)", 0x6200, 0xff00, RD_31|RD_SP, 0, 0 }, +{"xor", "x,y", 0xe80e, 0xf81f, WR_x|RD_x|RD_y, 0, 0 }, + /* MIPS16e additions */ +{"jalrc", "x", 0xe8c0, 0xf8ff, WR_31|RD_x|TRAP, 0, 0 }, +{"jalrc", "R,x", 0xe8c0, 0xf8ff, WR_31|RD_x|TRAP, 0, 0 }, +{"jrc", "x", 0xe880, 0xf8ff, RD_x|TRAP, 0, 0 }, +{"jrc", "R", 0xe8a0, 0xffff, RD_31|TRAP, 0, 0 }, +{"restore", "M", 0x6400, 0xff80, WR_31|RD_SP|WR_SP|TRAP, 0, 0 }, +{"save", "m", 0x6480, 0xff80, RD_31|RD_SP|WR_SP|TRAP, 0, 0 }, +{"seb", "x", 0xe891, 0xf8ff, WR_x|RD_x, 0, 0 }, +{"seh", "x", 0xe8b1, 0xf8ff, WR_x|RD_x, 0, 0 }, +{"sew", "x", 0xe8d1, 0xf8ff, WR_x|RD_x, 0, I3 }, +{"zeb", "x", 0xe811, 0xf8ff, WR_x|RD_x, 0, 0 }, +{"zeh", "x", 0xe831, 0xf8ff, WR_x|RD_x, 0, 0 }, +{"zew", "x", 0xe851, 0xf8ff, WR_x|RD_x, 0, I3 }, }; const int bfd_mips16_num_opcodes = diff --git a/contrib/gcc/config/fixdfdi.c b/contrib/gcc/config/fixdfdi.c new file mode 100644 index 000000000000..9b49228afea7 --- /dev/null +++ b/contrib/gcc/config/fixdfdi.c @@ -0,0 +1,28 @@ +/* Public domain. */ +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef unsigned int UDItype __attribute__ ((mode (DI))); +typedef float DFtype __attribute__ ((mode (DF))); + +DItype __fixdfdi (DFtype); + +/* This version is needed to prevent recursion; fixunsdfdi in libgcc + calls fixdfdi, which in turn calls calls fixunsdfdi. */ + +static DItype +local_fixunsdfdi (DFtype a) +{ + USItype hi, lo; + + hi = a / (((UDItype) 1) << (sizeof (USItype) * 8)); + lo = a - ((DFtype) hi) * (((UDItype) 1) << (sizeof (USItype) * 8)); + return ((UDItype) hi << (sizeof (USItype) * 8)) | lo; +} + +DItype +__fixdfdi (DFtype a) +{ + if (a < 0) + return - local_fixunsdfdi (-a); + return local_fixunsdfdi (a); +} diff --git a/contrib/gcc/config/fixsfdi.c b/contrib/gcc/config/fixsfdi.c new file mode 100644 index 000000000000..58b3cfccb97a --- /dev/null +++ b/contrib/gcc/config/fixsfdi.c @@ -0,0 +1,30 @@ +/* Public domain. */ +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef unsigned int UDItype __attribute__ ((mode (DI))); +typedef float SFtype __attribute__ ((mode (SF))); +typedef float DFtype __attribute__ ((mode (DF))); + +DItype __fixsfdi (SFtype); + +/* This version is needed to prevent recursion; fixunssfdi in libgcc + calls fixsfdi, which in turn calls calls fixunssfdi. */ + +static DItype +local_fixunssfdi (SFtype original_a) +{ + DFtype a = original_a; + USItype hi, lo; + + hi = a / (((UDItype) 1) << (sizeof (USItype) * 8)); + lo = a - ((DFtype) hi) * (((UDItype) 1) << (sizeof (USItype) * 8)); + return ((UDItype) hi << (sizeof (USItype) * 8)) | lo; +} + +DItype +__fixsfdi (SFtype a) +{ + if (a < 0) + return - local_fixunssfdi (-a); + return local_fixunssfdi (a); +} diff --git a/contrib/gcc/config/fixunsdfsi.c b/contrib/gcc/config/fixunsdfsi.c new file mode 100644 index 000000000000..fe7a4f8ab04e --- /dev/null +++ b/contrib/gcc/config/fixunsdfsi.c @@ -0,0 +1,18 @@ +/* Public domain. */ +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int SItype __attribute__ ((mode (SI))); +typedef float SFtype __attribute__ ((mode (SF))); +typedef float DFtype __attribute__ ((mode (DF))); + +USItype __fixunsdfsi (DFtype); + +#define SItype_MIN \ + (- ((SItype) (((USItype) 1 << ((sizeof (SItype) * 8) - 1)) - 1)) - 1) + +USItype +__fixunsdfsi (DFtype a) +{ + if (a >= - (DFtype) SItype_MIN) + return (SItype) (a + SItype_MIN) - SItype_MIN; + return (SItype) a; +} diff --git a/contrib/gcc/config/fixunssfsi.c b/contrib/gcc/config/fixunssfsi.c new file mode 100644 index 000000000000..f318749bbdea --- /dev/null +++ b/contrib/gcc/config/fixunssfsi.c @@ -0,0 +1,17 @@ +/* Public domain. */ +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int SItype __attribute__ ((mode (SI))); +typedef float SFtype __attribute__ ((mode (SF))); + +USItype __fixunssfsi (SFtype); + +#define SItype_MIN \ + (- ((SItype) (((USItype) 1 << ((sizeof (SItype) * 8) - 1)) - 1)) - 1) + +USItype +__fixunssfsi (SFtype a) +{ + if (a >= - (SFtype) SItype_MIN) + return (SItype) (a + SItype_MIN) - SItype_MIN; + return (SItype) a; +} diff --git a/contrib/gcc/config/floatdidf.c b/contrib/gcc/config/floatdidf.c new file mode 100644 index 000000000000..45bd0fd27190 --- /dev/null +++ b/contrib/gcc/config/floatdidf.c @@ -0,0 +1,17 @@ +/* Public domain. */ +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef float DFtype __attribute__ ((mode (DF))); + +DFtype __floatdidf (DItype); + +DFtype +__floatdidf (DItype u) +{ + /* When the word size is small, we never get any rounding error. */ + DFtype f = (SItype) (u >> (sizeof (SItype) * 8)); + f *= 0x1p32f; + f += (USItype) u; + return f; +} diff --git a/contrib/gcc/config/floatdisf.c b/contrib/gcc/config/floatdisf.c new file mode 100644 index 000000000000..b306044c1f97 --- /dev/null +++ b/contrib/gcc/config/floatdisf.c @@ -0,0 +1,38 @@ +/* Public domain. */ +typedef int DItype __attribute__ ((mode (DI))); +typedef unsigned int UDItype __attribute__ ((mode (DI))); +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef float SFtype __attribute__ ((mode (SF))); +typedef float DFtype __attribute__ ((mode (DF))); + +SFtype __floatdisf (DItype); + +SFtype +__floatdisf (DItype u) +{ + /* Protect against double-rounding error. + Represent any low-order bits, that might be truncated by a bit that + won't be lost. The bit can go in anywhere below the rounding position + of SFtype. A fixed mask and bit position handles all usual + configurations. */ + if (53 < (sizeof (DItype) * 8) + && 53 > ((sizeof (DItype) * 8) - 53 + 24)) + { + if (!(- ((DItype) 1 << 53) < u + && u < ((DItype) 1 << 53))) + { + if ((UDItype) u & (((UDItype) 1 << (sizeof (DItype) * 8 - 53)) - 1)) + { + u &= ~ (((UDItype) 1 << (sizeof (DItype) * 8 - 53)) - 1); + u |= (UDItype) 1 << (sizeof (DItype) * 8 - 53); + } + } + } + /* Do the calculation in a wider type so that we don't lose any of + the precision of the high word while multiplying it. */ + DFtype f = (SItype) (u >> (sizeof (SItype) * 8)); + f *= 0x1p32f; + f += (USItype) u; + return (SFtype) f; +} diff --git a/contrib/gcc/config/floatundidf.c b/contrib/gcc/config/floatundidf.c new file mode 100644 index 000000000000..0b11b0f77256 --- /dev/null +++ b/contrib/gcc/config/floatundidf.c @@ -0,0 +1,16 @@ +/* Public domain. */ +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef unsigned int UDItype __attribute__ ((mode (DI))); +typedef float DFtype __attribute__ ((mode (DF))); + +DFtype __floatundidf (UDItype); + +DFtype +__floatundidf (UDItype u) +{ + /* When the word size is small, we never get any rounding error. */ + DFtype f = (USItype) (u >> (sizeof (USItype) * 8)); + f *= 0x1p32f; + f += (USItype) u; + return f; +} diff --git a/contrib/gcc/config/floatundisf.c b/contrib/gcc/config/floatundisf.c new file mode 100644 index 000000000000..c813f0d3f96c --- /dev/null +++ b/contrib/gcc/config/floatundisf.c @@ -0,0 +1,36 @@ +/* Public domain. */ +typedef int DItype __attribute__ ((mode (DI))); +typedef unsigned int UDItype __attribute__ ((mode (DI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef float SFtype __attribute__ ((mode (SF))); +typedef float DFtype __attribute__ ((mode (DF))); + +SFtype __floatundisf (UDItype); + +SFtype +__floatundisf (UDItype u) +{ + /* Protect against double-rounding error. + Represent any low-order bits, that might be truncated by a bit that + won't be lost. The bit can go in anywhere below the rounding position + of SFTYPE. A fixed mask and bit position handles all usual + configurations. */ + if (53 < (sizeof (DItype) * 8) + && 53 > ((sizeof (DItype) * 8) - 53 + 24)) + { + if (u >= ((UDItype) 1 << 53)) + { + if ((UDItype) u & (((UDItype) 1 << (sizeof (DItype) * 8 - 53)) - 1)) + { + u &= ~ (((UDItype) 1 << (sizeof (DItype) * 8 - 53)) - 1); + u |= (UDItype) 1 << (sizeof (DItype) * 8 - 53); + } + } + } + /* Do the calculation in a wider type so that we don't lose any of + the precision of the high word while multiplying it. */ + DFtype f = (USItype) (u >> (sizeof (USItype) * 8)); + f *= 0x1p32f; + f += (USItype) u; + return (SFtype) f; +} diff --git a/contrib/gcc/config/mips/freebsd.h b/contrib/gcc/config/mips/freebsd.h index 35159ab4661b..d2ecd65c0a8d 100644 --- a/contrib/gcc/config/mips/freebsd.h +++ b/contrib/gcc/config/mips/freebsd.h @@ -75,7 +75,10 @@ Boston, MA 02110-1301, USA. */ %{mabi=o64:-melf64%{EB:b}%{EL:l}tsmip_fbsd} \ %(fbsd_link_spec)" - +#undef LINK_GCC_C_SEQUENCE_SPEC +#define LINK_GCC_C_SEQUENCE_SPEC \ + "%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}" + /* Reset our STARTFILE_SPEC which was properly set in config/freebsd.h but trashed by config/mips/elf.h. */ #undef STARTFILE_SPEC @@ -124,7 +127,7 @@ Boston, MA 02110-1301, USA. */ builtin_define ("__mips__"); \ \ if (TARGET_64BIT) \ - builtin_define ("__mips64__"); \ + builtin_define ("__mips64"); \ \ if (TARGET_FLOAT64) \ builtin_define ("__mips_fpr=64"); \ @@ -228,13 +231,13 @@ Boston, MA 02110-1301, USA. */ builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64"); \ builtin_define ("__mips_isa_rev=1"); \ } \ -/* else if (ISA_MIPS64R2) \ + else if (ISA_MIPS64R2) \ { \ builtin_define ("__mips=64"); \ builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64"); \ builtin_define ("__mips_isa_rev=2"); \ } \ -*/ \ + \ if (TARGET_HARD_FLOAT) \ builtin_define ("__mips_hard_float"); \ else if (TARGET_SOFT_FLOAT) \ @@ -255,27 +258,37 @@ Boston, MA 02110-1301, USA. */ while (0) /* Default ABI and ISA */ +/* + * XXX/juli + * Shouldn't this also be dependent on !mips*? + */ +#ifdef MIPS_CPU_STRING_DEFAULT +#define DRIVER_SELF_ISA_SPEC "%{!march=*: -march=" MIPS_CPU_STRING_DEFAULT "}" +#else +#define DRIVER_SELF_ISA_SPEC "%{!march=*: -march=from-abi}" +#endif + #undef DRIVER_SELF_SPECS #if MIPS_ABI_DEFAULT == ABI_N32 #define DRIVER_SELF_SPECS \ "%{!EB:%{!EL:%(endian_spec)}}", \ - "%{!march=*: -march=mips64}", \ - "%{!mabi=*: -mabi=n32}" + "%{!mabi=*: -mabi=n32}", \ + DRIVER_SELF_ISA_SPEC #elif MIPS_ABI_DEFAULT == ABI_64 #define DRIVER_SELF_SPECS \ "%{!EB:%{!EL:%(endian_spec)}}", \ - "%{!march=*: -march=mips64}", \ - "%{!mabi=*: -mabi=64}" + "%{!mabi=*: -mabi=64}", \ + DRIVER_SELF_ISA_SPEC #elif MIPS_ABI_DEFAULT == ABI_O64 #define DRIVER_SELF_SPECS \ "%{!EB:%{!EL:%(endian_spec)}}", \ - "%{!march=*: -march=mips64}", \ - "%{!mabi=*: -mabi=o64}" + "%{!mabi=*: -mabi=o64}", \ + DRIVER_SELF_ISA_SPEC #else /* default to o32 */ #define DRIVER_SELF_SPECS \ "%{!EB:%{!EL:%(endian_spec)}}", \ - "%{!march=*: -march=mips32}", \ - "%{!mabi=*: -mabi=32}" + "%{!mabi=*: -mabi=32}", \ + DRIVER_SELF_ISA_SPEC #endif #if 0 diff --git a/contrib/gcc/config/mips/mips.c b/contrib/gcc/config/mips/mips.c index 05498c2c21dc..e9f7c9791ab8 100644 --- a/contrib/gcc/config/mips/mips.c +++ b/contrib/gcc/config/mips/mips.c @@ -713,6 +713,7 @@ const struct mips_cpu_info mips_cpu_info_table[] = { { "mips32", PROCESSOR_4KC, 32 }, { "mips32r2", PROCESSOR_M4K, 33 }, { "mips64", PROCESSOR_5KC, 64 }, + { "mips64r2", PROCESSOR_5KC, 65 }, /* MIPS I */ { "r3000", PROCESSOR_R3000, 1 }, @@ -762,6 +763,9 @@ const struct mips_cpu_info mips_cpu_info_table[] = { { "sb1a", PROCESSOR_SB1A, 64 }, { "sr71000", PROCESSOR_SR71000, 64 }, + /* MIPS64R2 */ + { "octeon", PROCESSOR_OCTEON, 65 }, + /* End marker */ { 0, 0, 0 } }; @@ -4829,7 +4833,7 @@ override_options (void) issue those instructions unless instructed to do so by -mbranch-likely. */ if (ISA_HAS_BRANCHLIKELY - && !(ISA_MIPS32 || ISA_MIPS32R2 || ISA_MIPS64) + && !(ISA_MIPS32 || ISA_MIPS32R2 || ISA_MIPS64 || ISA_MIPS64R2) && !(TUNE_MIPS5500 || TUNE_SB1)) target_flags |= MASK_BRANCHLIKELY; else @@ -9943,6 +9947,7 @@ mips_issue_rate (void) case PROCESSOR_R5500: case PROCESSOR_R7000: case PROCESSOR_R9000: + case PROCESSOR_OCTEON: return 2; case PROCESSOR_SB1: diff --git a/contrib/gcc/config/mips/mips.h b/contrib/gcc/config/mips/mips.h index ba77d8636af1..1ba14029b29a 100644 --- a/contrib/gcc/config/mips/mips.h +++ b/contrib/gcc/config/mips/mips.h @@ -41,6 +41,7 @@ enum processor_type { PROCESSOR_24K, PROCESSOR_24KX, PROCESSOR_M4K, + PROCESSOR_OCTEON, PROCESSOR_R3900, PROCESSOR_R6000, PROCESSOR_R4000, @@ -199,6 +200,7 @@ extern const struct mips_rtx_cost_data *mips_cost; #define ISA_MIPS32 (mips_isa == 32) #define ISA_MIPS32R2 (mips_isa == 33) #define ISA_MIPS64 (mips_isa == 64) +#define ISA_MIPS64R2 (mips_isa == 65) /* Architecture target defines. */ #define TARGET_MIPS3900 (mips_arch == PROCESSOR_R3900) @@ -212,6 +214,7 @@ extern const struct mips_rtx_cost_data *mips_cost; #define TARGET_SB1 (mips_arch == PROCESSOR_SB1 \ || mips_arch == PROCESSOR_SB1A) #define TARGET_SR71K (mips_arch == PROCESSOR_SR71000) +#define TARGET_OCTEON (mips_arch == PROCESSOR_OCTEON) /* Scheduling target defines. */ #define TUNE_MIPS3000 (mips_tune == PROCESSOR_R3000) @@ -227,6 +230,7 @@ extern const struct mips_rtx_cost_data *mips_cost; #define TUNE_MIPS9000 (mips_tune == PROCESSOR_R9000) #define TUNE_SB1 (mips_tune == PROCESSOR_SB1 \ || mips_tune == PROCESSOR_SB1A) +#define TUNE_OCTEON (mips_tune == PROCESSOR_OCTEON) /* True if the pre-reload scheduler should try to create chains of multiply-add or multiply-subtract instructions. For example, @@ -379,6 +383,12 @@ extern const struct mips_rtx_cost_data *mips_cost; builtin_define ("__mips=64"); \ builtin_define ("__mips_isa_rev=1"); \ builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64"); \ + } \ + else if (ISA_MIPS64R2) \ + { \ + builtin_define ("__mips=64"); \ + builtin_define ("__mips_isa_rev=2"); \ + builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64"); \ } \ \ if (TARGET_HARD_FLOAT) \ @@ -501,7 +511,11 @@ extern const struct mips_rtx_cost_data *mips_cost; # if MIPS_ISA_DEFAULT == 64 # define MULTILIB_ISA_DEFAULT "mips64" # else -# define MULTILIB_ISA_DEFAULT "mips1" +# if MIPS_ISA_DEFAULT == 65 +# define MULTILIB_ISA_DEFAULT "mips64r2" +# else +# define MULTILIB_ISA_DEFAULT "mips1" +# endif # endif # endif # endif @@ -562,7 +576,8 @@ extern const struct mips_rtx_cost_data *mips_cost; || TARGET_MAD \ || ISA_MIPS32 \ || ISA_MIPS32R2 \ - || ISA_MIPS64) \ + || ISA_MIPS64 \ + || ISA_MIPS64R2) \ && !TARGET_MIPS16) /* Generate three-operand multiply instructions for DImode. */ @@ -584,7 +599,8 @@ extern const struct mips_rtx_cost_data *mips_cost; /* ISA has instructions for managing 64 bit fp and gp regs (e.g. mips3). */ #define ISA_HAS_64BIT_REGS (ISA_MIPS3 \ || ISA_MIPS4 \ - || ISA_MIPS64) + || ISA_MIPS64 \ + || ISA_MIPS64R2) /* ISA has branch likely instructions (e.g. mips2). */ /* Disable branchlikely for tx39 until compare rewrite. They haven't @@ -595,7 +611,8 @@ extern const struct mips_rtx_cost_data *mips_cost; #define ISA_HAS_CONDMOVE ((ISA_MIPS4 \ || ISA_MIPS32 \ || ISA_MIPS32R2 \ - || ISA_MIPS64) \ + || ISA_MIPS64 \ + || ISA_MIPS64R2) \ && !TARGET_MIPS5500 \ && !TARGET_MIPS16) @@ -604,13 +621,15 @@ extern const struct mips_rtx_cost_data *mips_cost; #define ISA_HAS_8CC (ISA_MIPS4 \ || ISA_MIPS32 \ || ISA_MIPS32R2 \ - || ISA_MIPS64) + || ISA_MIPS64 \ + || ISA_MIPS64R2) /* This is a catch all for other mips4 instructions: indexed load, the FP madd and msub instructions, and the FP recip and recip sqrt instructions. */ #define ISA_HAS_FP4 ((ISA_MIPS4 \ - || ISA_MIPS64) \ + || ISA_MIPS64 \ + || ISA_MIPS64R2) \ && !TARGET_MIPS16) /* ISA has conditional trap instructions. */ @@ -621,11 +640,13 @@ extern const struct mips_rtx_cost_data *mips_cost; #define ISA_HAS_MADD_MSUB ((ISA_MIPS32 \ || ISA_MIPS32R2 \ || ISA_MIPS64 \ + || ISA_MIPS64R2 \ ) && !TARGET_MIPS16) /* ISA has floating-point nmadd and nmsub instructions. */ #define ISA_HAS_NMADD_NMSUB ((ISA_MIPS4 \ - || ISA_MIPS64) \ + || ISA_MIPS64 \ + || ISA_MIPS64R2) \ && (!TARGET_MIPS5400 || TARGET_MAD) \ && ! TARGET_MIPS16) @@ -633,11 +654,13 @@ extern const struct mips_rtx_cost_data *mips_cost; #define ISA_HAS_CLZ_CLO ((ISA_MIPS32 \ || ISA_MIPS32R2 \ || ISA_MIPS64 \ + || ISA_MIPS64R2 \ ) && !TARGET_MIPS16) /* ISA has double-word count leading zeroes/ones instruction (not implemented). */ #define ISA_HAS_DCLZ_DCLO (ISA_MIPS64 \ + || ISA_MIPS64R2 \ && !TARGET_MIPS16) /* ISA has three operand multiply instructions that put @@ -677,6 +700,7 @@ extern const struct mips_rtx_cost_data *mips_cost; /* ISA has 32-bit rotate right instruction. */ #define ISA_HAS_ROTR_SI (!TARGET_MIPS16 \ && (ISA_MIPS32R2 \ + || ISA_MIPS64R2 \ || TARGET_MIPS5400 \ || TARGET_MIPS5500 \ || TARGET_SR71K \ @@ -694,7 +718,8 @@ extern const struct mips_rtx_cost_data *mips_cost; #define ISA_HAS_PREFETCH ((ISA_MIPS4 \ || ISA_MIPS32 \ || ISA_MIPS32R2 \ - || ISA_MIPS64) \ + || ISA_MIPS64 \ + || ISA_MIPS64R2) \ && !TARGET_MIPS16) /* ISA has data indexed prefetch instructions. This controls use of @@ -702,7 +727,8 @@ extern const struct mips_rtx_cost_data *mips_cost; (prefx is a cop1x instruction, so can only be used if FP is enabled.) */ #define ISA_HAS_PREFETCHX ((ISA_MIPS4 \ - || ISA_MIPS64) \ + || ISA_MIPS64 \ + || ISA_MIPS64R2) \ && !TARGET_MIPS16) /* True if trunc.w.s and trunc.w.d are real (not synthetic) @@ -713,11 +739,13 @@ extern const struct mips_rtx_cost_data *mips_cost; /* ISA includes the MIPS32r2 seb and seh instructions. */ #define ISA_HAS_SEB_SEH (!TARGET_MIPS16 \ && (ISA_MIPS32R2 \ + || ISA_MIPS64R2 \ )) /* ISA includes the MIPS32/64 rev 2 ext and ins instructions. */ #define ISA_HAS_EXT_INS (!TARGET_MIPS16 \ && (ISA_MIPS32R2 \ + || ISA_MIPS64R2 \ )) /* True if the result of a load is not available to the next instruction. @@ -748,6 +776,7 @@ extern const struct mips_rtx_cost_data *mips_cost; #define ISA_HAS_HILO_INTERLOCKS (ISA_MIPS32 \ || ISA_MIPS32R2 \ || ISA_MIPS64 \ + || ISA_MIPS64R2 \ || TARGET_MIPS5500) /* Add -G xx support. */ diff --git a/contrib/gcc/config/mips/mips.md b/contrib/gcc/config/mips/mips.md index 969d22fa00f5..b3716a027770 100644 --- a/contrib/gcc/config/mips/mips.md +++ b/contrib/gcc/config/mips/mips.md @@ -1041,7 +1041,8 @@ || TARGET_MIPS9000 || ISA_MIPS32 || ISA_MIPS32R2 - || ISA_MIPS64) + || ISA_MIPS64 + || ISA_MIPS64R2) return "mul\t%0,%1,%2"; return "mult\t%0,%1,%2"; } diff --git a/gnu/lib/libgcc/Makefile b/gnu/lib/libgcc/Makefile index 8c892366b450..b54e0bd797b9 100644 --- a/gnu/lib/libgcc/Makefile +++ b/gnu/lib/libgcc/Makefile @@ -118,6 +118,12 @@ LIB2FUNCS_EXTRA = floatunsidf.c floatunsisf.c .if ${TARGET_ARCH} == "mips" LIB2FUNCS_EXTRA = floatunsidf.c floatunsisf.c +.if defined(TARGET_ABI) && ${TARGET_ABI} != "o32" +LIB2FUNCS_EXTRA+= floatdidf.c fixunsdfsi.c +LIB2FUNCS_EXTRA+= floatdisf.c floatundidf.c +LIB2FUNCS_EXTRA+= fixsfdi.c floatundisf.c +LIB2FUNCS_EXTRA+= fixdfdi.c fixunssfsi.c +.endif .endif .if ${TARGET_ARCH} == "ia64" diff --git a/gnu/lib/libgomp/Makefile b/gnu/lib/libgomp/Makefile index c8052d5b4da9..097451673b12 100644 --- a/gnu/lib/libgomp/Makefile +++ b/gnu/lib/libgomp/Makefile @@ -24,7 +24,8 @@ VERSION_MAP= ${SRCDIR}/libgomp.map # Target-specific OpenMP configuration .if ${MACHINE_ARCH} == arm || ${MACHINE_ARCH} == i386 || \ - ${MACHINE_ARCH} == mips || ${MACHINE_ARCH} == powerpc + ${MACHINE_ARCH} == powerpc || \ + (${MACHINE_ARCH} == mips && (!defined(TARGET_ABI) || ${TARGET_ABI} != "n64")) OMP_LOCK_ALIGN = 4 OMP_LOCK_KIND= 4 OMP_LOCK_SIZE= 4 diff --git a/gnu/usr.bin/binutils/Makefile.inc0 b/gnu/usr.bin/binutils/Makefile.inc0 index 945c9339b4e4..5999a2e77661 100644 --- a/gnu/usr.bin/binutils/Makefile.inc0 +++ b/gnu/usr.bin/binutils/Makefile.inc0 @@ -23,7 +23,8 @@ RELSRC= ${RELTOP}/../../../contrib/binutils SRCDIR= ${.CURDIR}/${RELSRC} .if ${TARGET_ARCH} == "arm" || ${TARGET_ARCH} == "i386" || \ - ${TARGET_ARCH} == "powerpc" || ${TARGET_ARCH} == "mips" + ${TARGET_ARCH} == "powerpc" || \ + (${TARGET_ARCH} == "mips" && (!defined(TARGET_ABI) || ${TARGET_ABI} != "n64")) CFLAGS+= -DBFD_DEFAULT_TARGET_SIZE=32 .else CFLAGS+= -DBFD_DEFAULT_TARGET_SIZE=64 diff --git a/gnu/usr.bin/binutils/ld/Makefile.mips b/gnu/usr.bin/binutils/ld/Makefile.mips index d1e25ef89ca9..e0d0582df617 100644 --- a/gnu/usr.bin/binutils/ld/Makefile.mips +++ b/gnu/usr.bin/binutils/ld/Makefile.mips @@ -1,15 +1,22 @@ # $FreeBSD$ -#xxxIMPxxx: size? #xxxIMPxxx: TARGET_BIG_ENDIAN is lame. We should use the netbsd convention # of mipsel and mips. -_sz?=32 -.if defined(TARGET_BIG_ENDIAN) -NATIVE_EMULATION=elf${_sz}btsmip_fbsd +.if !defined(TARGET_BIG_ENDIAN) +_EMULATION_ENDIAN=l .else -NATIVE_EMULATION=elf${_sz}ltsmip_fbsd +_EMULATION_ENDIAN=b .endif +.if defined(TARGET_ABI) && ${TARGET_ABI} != "o32" +.if ${TARGET_ABI} == "n32" +NATIVE_EMULATION=elf32${_EMULATION_ENDIAN}tsmipn32_fbsd +.elif ${TARGET_ABI} == "n64" +NATIVE_EMULATION=elf64${_EMULATION_ENDIAN}tsmip_fbsd +.endif +.endif +NATIVE_EMULATION?=elf32${_EMULATION_ENDIAN}tsmip_fbsd + MIPS_ABIS=elf32btsmip_fbsd elf32ltsmip_fbsd elf64btsmip_fbsd elf64ltsmip_fbsd \ elf32btsmipn32_fbsd elf32ltsmipn32_fbsd .for abi in ${MIPS_ABIS} diff --git a/gnu/usr.bin/binutils/libbfd/Makefile.mips b/gnu/usr.bin/binutils/libbfd/Makefile.mips index 6f03eb7e796f..cb1e370e34d2 100644 --- a/gnu/usr.bin/binutils/libbfd/Makefile.mips +++ b/gnu/usr.bin/binutils/libbfd/Makefile.mips @@ -1,8 +1,24 @@ # $FreeBSD$ -#xxxIMPxxx: endian and size +#xxxIMPxxx: TARGET_BIG_ENDIAN is lame. We should use the netbsd convention +# of mipsel and mips. +.if !defined(TARGET_BIG_ENDIAN) +_EMULATION_ENDIAN=little +.else +_EMULATION_ENDIAN=big +.endif + DEFAULT_VECTOR= bfd_elf32_tradbigmips_vec +.if defined(TARGET_ABI) && ${TARGET_ABI} != "o32" +.if ${TARGET_ABI} == "n32" +DEFAULT_VECTOR= bfd_elf32_ntrad${_EMULATION_ENDIAN}mips_vec +.elif ${TARGET_ABI} == "n64" +DEFAULT_VECTOR= bfd_elf64_trad${_EMULATION_ENDIAN}mips_vec +.endif +.endif +DEFAULT_VECTOR?=bfd_elf32_trad${_EMULATION_ENDIAN}mips_vec + SRCS+= coff-mips.c \ cpu-mips.c \ ecoff.c \ diff --git a/gnu/usr.bin/binutils/libbfd/bfd.h b/gnu/usr.bin/binutils/libbfd/bfd.h index 6b152d53e882..5812cebbea38 100644 --- a/gnu/usr.bin/binutils/libbfd/bfd.h +++ b/gnu/usr.bin/binutils/libbfd/bfd.h @@ -1546,10 +1546,12 @@ enum bfd_architecture #define bfd_mach_mips6000 6000 #define bfd_mach_mips7000 7000 #define bfd_mach_mips8000 8000 +#define bfd_mach_mips9000 9000 #define bfd_mach_mips10000 10000 #define bfd_mach_mips12000 12000 #define bfd_mach_mips16 16 #define bfd_mach_mips5 5 +#define bfd_mach_mips_octeon 6502 #define bfd_mach_mips_sb1 12310201 /* octal 'SB', 01 */ #define bfd_mach_mipsisa32 32 #define bfd_mach_mipsisa32r2 33 diff --git a/gnu/usr.bin/cc/Makefile.inc b/gnu/usr.bin/cc/Makefile.inc index 1b7cbceda88f..3f03d2683623 100644 --- a/gnu/usr.bin/cc/Makefile.inc +++ b/gnu/usr.bin/cc/Makefile.inc @@ -32,10 +32,31 @@ CFLAGS+= -DLONG_TYPE_SIZE=${LONG_TYPE_SIZE} CFLAGS+= -DCROSS_COMPILE .endif -.if ${TARGET_ARCH} == "mips" && !defined(TARGET_BIG_ENDIAN) +.if ${TARGET_ARCH} == "mips" +# XXX This is backwards, MIPS should default to BE. +.if !defined(TARGET_BIG_ENDIAN) CFLAGS += -DTARGET_ENDIAN_DEFAULT=0 .endif +.if defined(TARGET_ABI) && ${TARGET_ABI} != "o32" +.if ${TARGET_ABI} == "n32" +MIPS_ABI_DEFAULT=ABI_N32 +.elif ${TARGET_ABI} == "n64" +MIPS_ABI_DEFAULT=ABI_64 +.endif +.endif + +MIPS_ABI_DEFAULT?=ABI_32 +CFLAGS += -DMIPS_ABI_DEFAULT=${MIPS_ABI_DEFAULT} + +# GCC by default takes the ISA from the ABI's requirements. If world is built +# with a superior ISA, since we lack multilib, we have to set the right +# default ISA to be able to link against what's in /usr/lib. Terrible stuff. +.if defined(TARGET_CPUTYPE) +CFLAGS += -DMIPS_CPU_STRING_DEFAULT=\"${TARGET_CPUTYPE}\" +.endif +.endif + .if defined(WANT_FORCE_OPTIMIZATION_DOWNGRADE) CFLAGS+= -DFORCE_OPTIMIZATION_DOWNGRADE=${WANT_FORCE_OPTIMIZATION_DOWNGRADE} .endif