blob: dd61d72a641c890542392a31e6e275b09f3d73bc [file] [log] [blame]
/* tc-mips.c -- assemble code for a MIPS chip.
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
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
Support.
This file is part of GAS.
GAS 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 3, or (at your option)
any later version.
GAS 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 GAS; see the file COPYING. If not, write to the Free
Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
02110-1301, USA. */
#include "as.h"
#include "config.h"
#include "subsegs.h"
#include "safe-ctype.h"
#include "opcode/mips.h"
#include "itbl-ops.h"
#include "dwarf2dbg.h"
#include "dw2gencfi.h"
/* Check assumptions made in this file. */
typedef char static_assert1[sizeof (offsetT) < 8 ? -1 : 1];
typedef char static_assert2[sizeof (valueT) < 8 ? -1 : 1];
#ifdef DEBUG
#define DBG(x) printf x
#else
#define DBG(x)
#endif
#define SKIP_SPACE_TABS(S) \
do { while (*(S) == ' ' || *(S) == '\t') ++(S); } while (0)
/* Clean up namespace so we can include obj-elf.h too. */
static int mips_output_flavor (void);
static int mips_output_flavor (void) { return OUTPUT_FLAVOR; }
#undef OBJ_PROCESS_STAB
#undef OUTPUT_FLAVOR
#undef S_GET_ALIGN
#undef S_GET_SIZE
#undef S_SET_ALIGN
#undef S_SET_SIZE
#undef obj_frob_file
#undef obj_frob_file_after_relocs
#undef obj_frob_symbol
#undef obj_pop_insert
#undef obj_sec_sym_ok_for_reloc
#undef OBJ_COPY_SYMBOL_ATTRIBUTES
#include "obj-elf.h"
/* Fix any of them that we actually care about. */
#undef OUTPUT_FLAVOR
#define OUTPUT_FLAVOR mips_output_flavor()
#include "elf/mips.h"
#ifndef ECOFF_DEBUGGING
#define NO_ECOFF_DEBUGGING
#define ECOFF_DEBUGGING 0
#endif
int mips_flag_mdebug = -1;
/* Control generation of .pdr sections. Off by default on IRIX: the native
linker doesn't know about and discards them, but relocations against them
remain, leading to rld crashes. */
#ifdef TE_IRIX
int mips_flag_pdr = FALSE;
#else
int mips_flag_pdr = TRUE;
#endif
#include "ecoff.h"
static char *mips_regmask_frag;
#define ZERO 0
#define ATREG 1
#define S0 16
#define S7 23
#define TREG 24
#define PIC_CALL_REG 25
#define KT0 26
#define KT1 27
#define GP 28
#define SP 29
#define FP 30
#define RA 31
#define ILLEGAL_REG (32)
#define AT mips_opts.at
extern int target_big_endian;
/* The name of the readonly data section. */
#define RDATA_SECTION_NAME ".rodata"
/* Ways in which an instruction can be "appended" to the output. */
enum append_method {
/* Just add it normally. */
APPEND_ADD,
/* Add it normally and then add a nop. */
APPEND_ADD_WITH_NOP,
/* Turn an instruction with a delay slot into a "compact" version. */
APPEND_ADD_COMPACT,
/* Insert the instruction before the last one. */
APPEND_SWAP
};
/* 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;
/* The 16-bit or 32-bit bitstring of the instruction itself. This is
a copy of INSN_MO->match with the operands filled in. If we have
decided to use an extended MIPS16 instruction, this includes the
extension. */
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 occurred 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;
/* True if this instruction is complete. */
unsigned int complete_p : 1;
/* True if this instruction is cleared from history by unconditional
branch. */
unsigned int cleared_p : 1;
};
/* The ABI to use. */
enum mips_abi_level
{
NO_ABI = 0,
O32_ABI,
O64_ABI,
N32_ABI,
N64_ABI,
EABI_ABI
};
/* MIPS ABI we are using for this output file. */
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. */
struct mips_set_options
{
/* MIPS ISA (Instruction Set Architecture) level. This is set to -1
if it has not been initialized. Changed by `.set mipsN', and the
-mipsN command line option, and the default CPU. */
int isa;
/* Enabled Application Specific Extensions (ASEs). Changed by `.set
<asename>', by command line options, and based on the default
architecture. */
int ase;
/* 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
-nomips16 command line options, and the default CPU. */
int mips16;
/* Whether we are assembling for the mipsMIPS ASE. 0 if we are not,
1 if we are, and -1 if the value has not been initialized. Changed
by `.set micromips' and `.set nomicromips', and the -mmicromips
and -mno-micromips command line options, and the default CPU. */
int micromips;
/* Non-zero if we should not reorder instructions. Changed by `.set
reorder' and `.set noreorder'. */
int noreorder;
/* Non-zero if we should not permit the register designated "assembler
temporary" to be used in instructions. The value is the register
number, normally $at ($1). Changed by `.set at=REG', `.set noat'
(same as `.set at=$0') and `.set at' (same as `.set at=$1'). */
unsigned int at;
/* Non-zero if we should warn when a macro instruction expands into
more than one machine instruction. Changed by `.set nomacro' and
`.set macro'. */
int warn_about_macros;
/* Non-zero if we should not move instructions. Changed by `.set
move', `.set volatile', `.set nomove', and `.set novolatile'. */
int nomove;
/* Non-zero if we should not optimize branches by moving the target
of the branch into the delay slot. Actually, we don't perform
this optimization anyhow. Changed by `.set bopt' and `.set
nobopt'. */
int nobopt;
/* Non-zero if we should not autoextend mips16 instructions.
Changed by `.set autoextend' and `.set noautoextend'. */
int noautoextend;
/* True if we should only emit 32-bit microMIPS instructions.
Changed by `.set insn32' and `.set noinsn32', and the -minsn32
and -mno-insn32 command line options. */
bfd_boolean insn32;
/* Restrict general purpose registers and floating point registers
to 32 bit. This is initially determined when -mgp32 or -mfp32
is passed but can changed if the assembler code uses .set mipsN. */
int gp32;
int fp32;
/* 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 floating-point operations are not allowed. Changed by .set
softfloat or .set hardfloat, by command line options -msoft-float or
-mhard-float. The default is false. */
bfd_boolean soft_float;
/* True if only single-precision floating-point operations are allowed.
Changed by .set singlefloat or .set doublefloat, command-line options
-msingle-float or -mdouble-float. The default is false. */
bfd_boolean single_float;
};
/* This is the struct we use to hold the current set of options. Note
that we must set the isa field to ISA_UNKNOWN and the ASE fields to
-1 to indicate that they have not been initialized. */
/* True if -mgp32 was passed. */
static int file_mips_gp32 = -1;
/* True if -mfp32 was passed. */
static int file_mips_fp32 = -1;
/* 1 if -msoft-float, 0 if -mhard-float. The default is 0. */
static int file_mips_soft_float = 0;
/* 1 if -msingle-float, 0 if -mdouble-float. The default is 0. */
static int file_mips_single_float = 0;
/* True if -mnan=2008, false if -mnan=legacy. */
static bfd_boolean mips_flag_nan2008 = FALSE;
static struct mips_set_options mips_opts =
{
/* isa */ ISA_UNKNOWN, /* ase */ 0, /* mips16 */ -1, /* micromips */ -1,
/* noreorder */ 0, /* at */ ATREG, /* warn_about_macros */ 0,
/* nomove */ 0, /* nobopt */ 0, /* noautoextend */ 0, /* insn32 */ FALSE,
/* gp32 */ 0, /* fp32 */ 0, /* arch */ CPU_UNKNOWN, /* sym32 */ FALSE,
/* soft_float */ FALSE, /* single_float */ FALSE
};
/* The set of ASEs that were selected on the command line, either
explicitly via ASE options or implicitly through things like -march. */
static unsigned int file_ase;
/* Which bits of file_ase were explicitly set or cleared by ASE options. */
static unsigned int file_ase_explicit;
/* These variables are filled in with the masks of registers used.
The object format code reads them and puts them in the appropriate
place. */
unsigned long mips_gprmask;
unsigned long mips_cprmask[4];
/* MIPS ISA we are using for this output file. */
static int file_mips_isa = ISA_UNKNOWN;
/* True if any MIPS16 code was produced. */
static int file_ase_mips16;
#define ISA_SUPPORTS_MIPS16E (mips_opts.isa == ISA_MIPS32 \
|| mips_opts.isa == ISA_MIPS32R2 \
|| mips_opts.isa == ISA_MIPS64 \
|| mips_opts.isa == ISA_MIPS64R2)
/* True if any microMIPS code was produced. */
static int file_ase_micromips;
/* True if we want to create R_MIPS_JALR for jalr $25. */
#ifdef TE_IRIX
#define MIPS_JALR_HINT_P(EXPR) HAVE_NEWABI
#else
/* As a GNU extension, we use R_MIPS_JALR for o32 too. However,
because there's no place for any addend, the only acceptable
expression is a bare symbol. */
#define MIPS_JALR_HINT_P(EXPR) \
(!HAVE_IN_PLACE_ADDENDS \
|| ((EXPR)->X_op == O_symbol && (EXPR)->X_add_number == 0))
#endif
/* The argument of the -march= flag. The architecture we are assembling. */
static int file_mips_arch = CPU_UNKNOWN;
static const char *mips_arch_string;
/* The argument of the -mtune= flag. The architecture for which we
are optimizing. */
static int mips_tune = CPU_UNKNOWN;
static const char *mips_tune_string;
/* True when generating 32-bit code for a 64-bit processor. */
static int mips_32bitmode = 0;
/* True if the given ABI requires 32-bit registers. */
#define ABI_NEEDS_32BIT_REGS(ABI) ((ABI) == O32_ABI)
/* Likewise 64-bit registers. */
#define ABI_NEEDS_64BIT_REGS(ABI) \
((ABI) == N32_ABI \
|| (ABI) == N64_ABI \
|| (ABI) == O64_ABI)
/* Return true if ISA supports 64 bit wide gp registers. */
#define ISA_HAS_64BIT_REGS(ISA) \
((ISA) == ISA_MIPS3 \
|| (ISA) == ISA_MIPS4 \
|| (ISA) == ISA_MIPS5 \
|| (ISA) == ISA_MIPS64 \
|| (ISA) == ISA_MIPS64R2)
/* Return true if ISA supports 64 bit wide float registers. */
#define ISA_HAS_64BIT_FPRS(ISA) \
((ISA) == ISA_MIPS3 \
|| (ISA) == ISA_MIPS4 \
|| (ISA) == ISA_MIPS5 \
|| (ISA) == ISA_MIPS32R2 \
|| (ISA) == ISA_MIPS64 \
|| (ISA) == ISA_MIPS64R2)
/* Return true if ISA supports 64-bit right rotate (dror et al.)
instructions. */
#define ISA_HAS_DROR(ISA) \
((ISA) == ISA_MIPS64R2 \
|| (mips_opts.micromips \
&& ISA_HAS_64BIT_REGS (ISA)) \
)
/* Return true if ISA supports 32-bit right rotate (ror et al.)
instructions. */
#define ISA_HAS_ROR(ISA) \
((ISA) == ISA_MIPS32R2 \
|| (ISA) == ISA_MIPS64R2 \
|| (mips_opts.ase & ASE_SMARTMIPS) \
|| mips_opts.micromips \
)
/* Return true if ISA supports single-precision floats in odd registers. */
#define ISA_HAS_ODD_SINGLE_FPR(ISA) \
((ISA) == ISA_MIPS32 \
|| (ISA) == ISA_MIPS32R2 \
|| (ISA) == ISA_MIPS64 \
|| (ISA) == ISA_MIPS64R2)
/* Return true if ISA supports move to/from high part of a 64-bit
floating-point register. */
#define ISA_HAS_MXHC1(ISA) \
((ISA) == ISA_MIPS32R2 \
|| (ISA) == ISA_MIPS64R2)
#define HAVE_32BIT_GPRS \
(mips_opts.gp32 || !ISA_HAS_64BIT_REGS (mips_opts.isa))
#define HAVE_32BIT_FPRS \
(mips_opts.fp32 || !ISA_HAS_64BIT_FPRS (mips_opts.isa))
#define HAVE_64BIT_GPRS (!HAVE_32BIT_GPRS)
#define HAVE_64BIT_FPRS (!HAVE_32BIT_FPRS)
#define HAVE_NEWABI (mips_abi == N32_ABI || mips_abi == N64_ABI)
#define HAVE_64BIT_OBJECTS (mips_abi == N64_ABI)
/* True if relocations are stored in-place. */
#define HAVE_IN_PLACE_ADDENDS (!HAVE_NEWABI)
/* 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)
/* 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
with overflow checking, but existing implementations don't follow it. */
#define ADDRESS_ADD_INSN \
(HAVE_32BIT_ADDRESSES ? "addu" : "daddu")
#define ADDRESS_ADDI_INSN \
(HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu")
#define ADDRESS_LOAD_INSN \
(HAVE_32BIT_ADDRESSES ? "lw" : "ld")
#define ADDRESS_STORE_INSN \
(HAVE_32BIT_ADDRESSES ? "sw" : "sd")
/* Return true if the given CPU supports the MIPS16 ASE. */
#define CPU_HAS_MIPS16(cpu) \
(strncmp (TARGET_CPU, "mips16", sizeof ("mips16") - 1) == 0 \
|| strncmp (TARGET_CANONICAL, "mips-lsi-elf", sizeof ("mips-lsi-elf") - 1) == 0)
/* Return true if the given CPU supports the microMIPS ASE. */
#define CPU_HAS_MICROMIPS(cpu) 0
/* True if CPU has a dror instruction. */
#define CPU_HAS_DROR(CPU) ((CPU) == CPU_VR5400 || (CPU) == CPU_VR5500)
/* True if CPU has a ror instruction. */
#define CPU_HAS_ROR(CPU) CPU_HAS_DROR (CPU)
/* True if CPU is in the Octeon family */
#define CPU_IS_OCTEON(CPU) ((CPU) == CPU_OCTEON || (CPU) == CPU_OCTEONP || (CPU) == CPU_OCTEON2)
/* True if CPU has seq/sne and seqi/snei instructions. */
#define CPU_HAS_SEQ(CPU) (CPU_IS_OCTEON (CPU))
/* True, if CPU has support for ldc1 and sdc1. */
#define CPU_HAS_LDC1_SDC1(CPU) \
((mips_opts.isa != ISA_MIPS1) && ((CPU) != CPU_R5900))
/* True if mflo and mfhi can be immediately followed by instructions
which write to the HI and LO registers.
According to MIPS specifications, MIPS ISAs I, II, and III need
(at least) two instructions between the reads of HI/LO and
instructions which write them, and later ISAs do not. Contradicting
the MIPS specifications, some MIPS IV processor user manuals (e.g.
the UM for the NEC Vr5000) document needing the instructions between
HI/LO reads and writes, as well. Therefore, we declare only MIPS32,
MIPS64 and later ISAs to have the interlocks, plus any specific
earlier-ISA CPUs for which CPU documentation declares that the
instructions are really interlocked. */
#define hilo_interlocks \
(mips_opts.isa == ISA_MIPS32 \
|| mips_opts.isa == ISA_MIPS32R2 \
|| mips_opts.isa == ISA_MIPS64 \
|| mips_opts.isa == ISA_MIPS64R2 \
|| mips_opts.arch == CPU_R4010 \
|| mips_opts.arch == CPU_R5900 \
|| mips_opts.arch == CPU_R10000 \
|| mips_opts.arch == CPU_R12000 \
|| mips_opts.arch == CPU_R14000 \
|| mips_opts.arch == CPU_R16000 \
|| mips_opts.arch == CPU_RM7000 \
|| mips_opts.arch == CPU_VR5500 \
|| mips_opts.micromips \
)
/* Whether the processor uses hardware interlocks to protect reads
from the GPRs after they are loaded from memory, and thus does not
require nops to be inserted. This applies to instructions marked
INSN_LOAD_MEMORY_DELAY. These nops are only required at MIPS ISA
level I and microMIPS mode instructions are always interlocked. */
#define gpr_interlocks \
(mips_opts.isa != ISA_MIPS1 \
|| mips_opts.arch == CPU_R3900 \
|| mips_opts.arch == CPU_R5900 \
|| mips_opts.micromips \
)
/* Whether the processor uses hardware interlocks to avoid delays
required by coprocessor instructions, and thus does not require
nops to be inserted. This applies to instructions marked
INSN_LOAD_COPROC_DELAY, INSN_COPROC_MOVE_DELAY, and to delays
between instructions marked INSN_WRITE_COND_CODE and ones marked
INSN_READ_COND_CODE. These nops are only required at MIPS ISA
levels I, II, and III and microMIPS mode instructions are always
interlocked. */
/* Itbl support may require additional care here. */
#define cop_interlocks \
((mips_opts.isa != ISA_MIPS1 \
&& mips_opts.isa != ISA_MIPS2 \
&& mips_opts.isa != ISA_MIPS3) \
|| mips_opts.arch == CPU_R4300 \
|| mips_opts.micromips \
)
/* Whether the processor uses hardware interlocks to protect reads
from coprocessor registers after they are loaded from memory, and
thus does not require nops to be inserted. This applies to
instructions marked INSN_COPROC_MEMORY_DELAY. These nops are only
requires at MIPS ISA level I and microMIPS mode instructions are
always interlocked. */
#define cop_mem_interlocks \
(mips_opts.isa != ISA_MIPS1 \
|| mips_opts.micromips \
)
/* Is this a mfhi or mflo instruction? */
#define MF_HILO_INSN(PINFO) \
((PINFO & INSN_READ_HI) || (PINFO & INSN_READ_LO))
/* Whether code compression (either of the MIPS16 or the microMIPS ASEs)
has been selected. This implies, in particular, that addresses of text
labels have their LSB set. */
#define HAVE_CODE_COMPRESSION \
((mips_opts.mips16 | mips_opts.micromips) != 0)
/* The minimum and maximum signed values that can be stored in a GPR. */
#define GPR_SMAX ((offsetT) (((valueT) 1 << (HAVE_64BIT_GPRS ? 63 : 31)) - 1))
#define GPR_SMIN (-GPR_SMAX - 1)
/* MIPS PIC level. */
enum mips_pic_level mips_pic;
/* 1 if we should generate 32 bit offsets from the $gp register in
SVR4_PIC mode. Currently has no meaning in other modes. */
static int mips_big_got = 0;
/* 1 if trap instructions should used for overflow rather than break
instructions. */
static int mips_trap = 0;
/* 1 if double width floating point constants should not be constructed
by assembling two single width halves into two single width floating
point registers which just happen to alias the double width destination
register. On some architectures this aliasing can be disabled by a bit
in the status register, and the setting of this bit cannot be determined
automatically at assemble time. */
static int mips_disable_float_construction;
/* Non-zero if any .set noreorder directives were used. */
static int mips_any_noreorder;
/* Non-zero if nops should be inserted when the register referenced in
an mfhi/mflo instruction is read in the next two instructions. */
static int mips_7000_hilo_fix;
/* The size of objects in the small data section. */
static unsigned int g_switch_value = 8;
/* Whether the -G option was used. */
static int g_switch_seen = 0;
#define N_RMASK 0xc4
#define N_VFP 0xd4
/* If we can determine in advance that GP optimization won't be
possible, we can skip the relaxation stuff that tries to produce
GP-relative references. This makes delay slot optimization work
better.
This function can only provide a guess, but it seems to work for
gcc output. It needs to guess right for gcc, otherwise gcc
will put what it thinks is a GP-relative instruction in a branch
delay slot.
I don't know if a fix is needed for the SVR4_PIC mode. I've only
fixed it for the non-PIC mode. KR 95/04/07 */
static int nopic_need_relax (symbolS *, int);
/* handle of the OPCODE hash table */
static struct hash_control *op_hash = NULL;
/* The opcode hash table we use for the mips16. */
static struct hash_control *mips16_op_hash = NULL;
/* The opcode hash table we use for the microMIPS ASE. */
static struct hash_control *micromips_op_hash = NULL;
/* This array holds the chars that always start a comment. If the
pre-processor is disabled, these aren't very useful */
const char comment_chars[] = "#";
/* This array holds the chars that only start a comment at the beginning of
a line. If the line seems to have the form '# 123 filename'
.line and .file directives will appear in the pre-processed output */
/* Note that input_file.c hand checks for '#' at the beginning of the
first line of the input file. This is because the compiler outputs
#NO_APP at the beginning of its output. */
/* Also note that C style comments are always supported. */
const char line_comment_chars[] = "#";
/* This array holds machine specific line separator characters. */
const char line_separator_chars[] = ";";
/* Chars that can be used to separate mant from exp in floating point nums */
const char EXP_CHARS[] = "eE";
/* Chars that mean this number is a floating point constant */
/* As in 0f12.456 */
/* or 0d1.2345e12 */
const char FLT_CHARS[] = "rRsSfFdDxXpP";
/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
changed in read.c . Ideally it shouldn't have to know about it at all,
but nothing is ideal around here.
*/
/* Types of printf format used for instruction-related error messages.
"I" means int ("%d") and "S" means string ("%s"). */
enum mips_insn_error_format {
ERR_FMT_PLAIN,
ERR_FMT_I,
ERR_FMT_SS,
};
/* Information about an error that was found while assembling the current
instruction. */
struct mips_insn_error {
/* We sometimes need to match an instruction against more than one
opcode table entry. Errors found during this matching are reported
against a particular syntactic argument rather than against the
instruction as a whole. We grade these messages so that errors
against argument N have a greater priority than an error against
any argument < N, since the former implies that arguments up to N
were acceptable and that the opcode entry was therefore a closer match.
If several matches report an error against the same argument,
we only use that error if it is the same in all cases.
min_argnum is the minimum argument number for which an error message
should be accepted. It is 0 if MSG is against the instruction as
a whole. */
int min_argnum;
/* The printf()-style message, including its format and arguments. */
enum mips_insn_error_format format;
const char *msg;
union {
int i;
const char *ss[2];
} u;
};
/* The error that should be reported for the current instruction. */
static struct mips_insn_error insn_error;
static int auto_align = 1;
/* When outputting SVR4 PIC code, the assembler needs to know the
offset in the stack frame from which to restore the $gp register.
This is set by the .cprestore pseudo-op, and saved in this
variable. */
static offsetT mips_cprestore_offset = -1;
/* Similar for NewABI PIC code, where $gp is callee-saved. NewABI has some
more optimizations, it can use a register value instead of a memory-saved
offset and even an other register than $gp as global pointer. */
static offsetT mips_cpreturn_offset = -1;
static int mips_cpreturn_register = -1;
static int mips_gp_register = GP;
static int mips_gprel_offset = 0;
/* Whether mips_cprestore_offset has been set in the current function
(or whether it has already been warned about, if not). */
static int mips_cprestore_valid = 0;
/* This is the register which holds the stack frame, as set by the
.frame pseudo-op. This is needed to implement .cprestore. */
static int mips_frame_reg = SP;
/* Whether mips_frame_reg has been set in the current function
(or whether it has already been warned about, if not). */
static int mips_frame_reg_valid = 0;
/* To output NOP instructions correctly, we need to keep information
about the previous two instructions. */
/* Whether we are optimizing. The default value of 2 means to remove
unneeded NOPs and swap branch instructions when possible. A value
of 1 means to not swap branches. A value of 0 means to always
insert NOPs. */
static int mips_optimize = 2;
/* Debugging level. -g sets this to 2. -gN sets this to N. -g0 is
equivalent to seeing no -g option at all. */
static int mips_debug = 0;
/* The maximum number of NOPs needed to avoid the VR4130 mflo/mfhi errata. */
#define MAX_VR4130_NOPS 4
/* The maximum number of NOPs needed to fill delay slots. */
#define MAX_DELAY_NOPS 2
/* The maximum number of NOPs needed for any purpose. */
#define MAX_NOPS 4
/* 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];
/* Arrays of operands for each instruction. */
#define MAX_OPERANDS 6
struct mips_operand_array {
const struct mips_operand *operand[MAX_OPERANDS];
};
static struct mips_operand_array *mips_operands;
static struct mips_operand_array *mips16_operands;
static struct mips_operand_array *micromips_operands;
/* Nop instructions used by emit_nop. */
static struct mips_cl_insn nop_insn;
static struct mips_cl_insn mips16_nop_insn;
static struct mips_cl_insn micromips_nop16_insn;
static struct mips_cl_insn micromips_nop32_insn;
/* The appropriate nop for the current mode. */
#define NOP_INSN (mips_opts.mips16 \
? &mips16_nop_insn \
: (mips_opts.micromips \
? (mips_opts.insn32 \
? &micromips_nop32_insn \
: &micromips_nop16_insn) \
: &nop_insn))
/* The size of NOP_INSN in bytes. */
#define NOP_INSN_SIZE ((mips_opts.mips16 \
|| (mips_opts.micromips && !mips_opts.insn32)) \
? 2 : 4)
/* If this is set, it points to a frag holding nop instructions which
were inserted before the start of a noreorder section. If those
nops turn out to be unnecessary, the size of the frag can be
decreased. */
static fragS *prev_nop_frag;
/* The number of nop instructions we created in prev_nop_frag. */
static int prev_nop_frag_holds;
/* The number of nop instructions that we know we need in
prev_nop_frag. */
static int prev_nop_frag_required;
/* The number of instructions we've seen since prev_nop_frag. */
static int prev_nop_frag_since;
/* Relocations against symbols are sometimes done in two parts, with a HI
relocation and a LO relocation. Each relocation has only 16 bits of
space to store an addend. This means that in order for the linker to
handle carries correctly, it must be able to locate both the HI and
the LO relocation. This means that the relocations must appear in
order in the relocation table.
In order to implement this, we keep track of each unmatched HI
relocation. We then sort them so that they immediately precede the
corresponding LO relocation. */
struct mips_hi_fixup
{
/* Next HI fixup. */
struct mips_hi_fixup *next;
/* This fixup. */
fixS *fixp;
/* The section this fixup is in. */
segT seg;
};
/* The list of unmatched HI relocs. */
static struct mips_hi_fixup *mips_hi_fixup_list;
/* The frag containing the last explicit relocation operator.
Null if explicit relocations have not been used. */
static fragS *prev_reloc_op_frag;
/* Map mips16 register numbers to normal MIPS register numbers. */
static const unsigned int mips16_to_32_reg_map[] =
{
16, 17, 2, 3, 4, 5, 6, 7
};
/* Map microMIPS register numbers to normal MIPS register numbers. */
#define micromips_to_32_reg_d_map mips16_to_32_reg_map
/* The microMIPS registers with type h. */
static const unsigned int micromips_to_32_reg_h_map1[] =
{
5, 5, 6, 4, 4, 4, 4, 4
};
static const unsigned int micromips_to_32_reg_h_map2[] =
{
6, 7, 7, 21, 22, 5, 6, 7
};
/* The microMIPS registers with type m. */
static const unsigned int micromips_to_32_reg_m_map[] =
{
0, 17, 2, 3, 16, 18, 19, 20
};
#define micromips_to_32_reg_n_map micromips_to_32_reg_m_map
/* 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
};
/* ...likewise -mfix-loongson2f-jump. */
static bfd_boolean mips_fix_loongson2f_jump;
/* ...likewise -mfix-loongson2f-nop. */
static bfd_boolean mips_fix_loongson2f_nop;
/* True if -mfix-loongson2f-nop or -mfix-loongson2f-jump passed. */
static bfd_boolean mips_fix_loongson2f;
/* 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;
/* ...likewise -mfix-24k. */
static int mips_fix_24k;
/* ...likewise -mfix-cn63xxp1 */
static bfd_boolean mips_fix_cn63xxp1;
/* 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
efficient expansion. */
static int mips_relax_branch;
/* The expansion of many macros depends on the type of symbol that
they refer to. For example, when generating position-dependent code,
a macro that refers to a symbol may have two different expansions,
one which uses GP-relative addresses and one which uses absolute
addresses. When generating SVR4-style PIC, a macro may have
different expansions for local and global symbols.
We handle these situations by generating both sequences and putting
them in variant frags. In position-dependent code, the first sequence
will be the GP-relative one and the second sequence will be the
absolute one. In SVR4 PIC, the first sequence will be for global
symbols and the second will be for local symbols.
The frag's "subtype" is RELAX_ENCODE (FIRST, SECOND), where FIRST and
SECOND are the lengths of the two sequences in bytes. These fields
can be extracted using RELAX_FIRST() and RELAX_SECOND(). In addition,
the subtype has the following flags:
RELAX_USE_SECOND
Set if it has been decided that we should use the second
sequence instead of the first.
RELAX_SECOND_LONGER
Set in the first variant frag if the macro's second implementation
is longer than its first. This refers to the macro as a whole,
not an individual relaxation.
RELAX_NOMACRO
Set in the first variant frag if the macro appeared in a .set nomacro
block and if one alternative requires a warning but the other does not.
RELAX_DELAY_SLOT
Like RELAX_NOMACRO, but indicates that the macro appears in a branch
delay slot.
RELAX_DELAY_SLOT_16BIT
Like RELAX_DELAY_SLOT, but indicates that the delay slot requires a
16-bit instruction.
RELAX_DELAY_SLOT_SIZE_FIRST
Like RELAX_DELAY_SLOT, but indicates that the first implementation of
the macro is of the wrong size for the branch delay slot.
RELAX_DELAY_SLOT_SIZE_SECOND
Like RELAX_DELAY_SLOT, but indicates that the second implementation of
the macro is of the wrong size for the branch delay slot.
The frag's "opcode" points to the first fixup for relaxable code.
Relaxable macros are generated using a sequence such as:
relax_start (SYMBOL);
... generate first expansion ...
relax_switch ();
... generate second expansion ...
relax_end ();
The code and fixups for the unwanted alternative are discarded
by md_convert_frag. */
#define RELAX_ENCODE(FIRST, SECOND) (((FIRST) << 8) | (SECOND))
#define RELAX_FIRST(X) (((X) >> 8) & 0xff)
#define RELAX_SECOND(X) ((X) & 0xff)
#define RELAX_USE_SECOND 0x10000
#define RELAX_SECOND_LONGER 0x20000
#define RELAX_NOMACRO 0x40000
#define RELAX_DELAY_SLOT 0x80000
#define RELAX_DELAY_SLOT_16BIT 0x100000
#define RELAX_DELAY_SLOT_SIZE_FIRST 0x200000
#define RELAX_DELAY_SLOT_SIZE_SECOND 0x400000
/* Branch without likely bit. If label is out of range, we turn:
beq reg1, reg2, label
delay slot
into
bne reg1, reg2, 0f
nop
j label
0: delay slot
with the following opcode replacements:
beq <-> bne
blez <-> bgtz
bltz <-> bgez
bc1f <-> bc1t
bltzal <-> bgezal (with jal label instead of j label)
Even though keeping the delay slot instruction in the delay slot of
the branch would be more efficient, it would be very tricky to do
correctly, because we'd have to introduce a variable frag *after*
the delay slot instruction, and expand that instead. Let's do it
the easy way for now, even if the branch-not-taken case now costs
one additional instruction. Out-of-range branches are not supposed
to be common, anyway.
Branch likely. If label is out of range, we turn:
beql reg1, reg2, label
delay slot (annulled if branch not taken)
into
beql reg1, reg2, 1f
nop
beql $0, $0, 2f
nop
1: j[al] label
delay slot (executed only if branch taken)
2:
It would be possible to generate a shorter sequence by losing the
likely bit, generating something like:
bne reg1, reg2, 0f
nop
j[al] label
delay slot (executed only if branch taken)
0:
beql -> bne
bnel -> beq
blezl -> bgtz
bgtzl -> blez
bltzl -> bgez
bgezl -> bltz
bc1fl -> bc1t
bc1tl -> bc1f
bltzall -> bgezal (with jal label instead of j label)
bgezall -> bltzal (ditto)
but it's not clear that it would actually improve performance. */
#define RELAX_BRANCH_ENCODE(at, uncond, likely, link, toofar) \
((relax_substateT) \
(0xc0000000 \
| ((at) & 0x1f) \
| ((toofar) ? 0x20 : 0) \
| ((link) ? 0x40 : 0) \
| ((likely) ? 0x80 : 0) \
| ((uncond) ? 0x100 : 0)))
#define RELAX_BRANCH_P(i) (((i) & 0xf0000000) == 0xc0000000)
#define RELAX_BRANCH_UNCOND(i) (((i) & 0x100) != 0)
#define RELAX_BRANCH_LIKELY(i) (((i) & 0x80) != 0)
#define RELAX_BRANCH_LINK(i) (((i) & 0x40) != 0)
#define RELAX_BRANCH_TOOFAR(i) (((i) & 0x20) != 0)
#define RELAX_BRANCH_AT(i) ((i) & 0x1f)
/* For mips16 code, we use an entirely different form of relaxation.
mips16 supports two versions of most instructions which take
immediate values: a small one which takes some small value, and a
larger one which takes a 16 bit value. Since branches also follow
this pattern, relaxing these values is required.
We can assemble both mips16 and normal MIPS code in a single
object. Therefore, we need to support this type of relaxation at
the same time that we support the relaxation described above. We
use the high bit of the subtype field to distinguish these cases.
The information we store for this type of relaxation is the
argument code found in the opcode file for this relocation, whether
the user explicitly requested a small or extended form, and whether
the relocation is in a jump or jal delay slot. That tells us the
size of the value, and how it should be stored. We also store
whether the fragment is considered to be extended or not. We also
store whether this is known to be a branch to a different section,
whether we have tried to relax this frag yet, and whether we have
ever extended a PC relative fragment because of a shift count. */
#define RELAX_MIPS16_ENCODE(type, small, ext, dslot, jal_dslot) \
(0x80000000 \
| ((type) & 0xff) \
| ((small) ? 0x100 : 0) \
| ((ext) ? 0x200 : 0) \
| ((dslot) ? 0x400 : 0) \
| ((jal_dslot) ? 0x800 : 0))
#define RELAX_MIPS16_P(i) (((i) & 0xc0000000) == 0x80000000)
#define RELAX_MIPS16_TYPE(i) ((i) & 0xff)
#define RELAX_MIPS16_USER_SMALL(i) (((i) & 0x100) != 0)
#define RELAX_MIPS16_USER_EXT(i) (((i) & 0x200) != 0)
#define RELAX_MIPS16_DSLOT(i) (((i) & 0x400) != 0)
#define RELAX_MIPS16_JAL_DSLOT(i) (((i) & 0x800) != 0)
#define RELAX_MIPS16_EXTENDED(i) (((i) & 0x1000) != 0)
#define RELAX_MIPS16_MARK_EXTENDED(i) ((i) | 0x1000)
#define RELAX_MIPS16_CLEAR_EXTENDED(i) ((i) &~ 0x1000)
#define RELAX_MIPS16_LONG_BRANCH(i) (((i) & 0x2000) != 0)
#define RELAX_MIPS16_MARK_LONG_BRANCH(i) ((i) | 0x2000)
#define RELAX_MIPS16_CLEAR_LONG_BRANCH(i) ((i) &~ 0x2000)
/* For microMIPS code, we use relaxation similar to one we use for
MIPS16 code. Some instructions that take immediate values support
two encodings: a small one which takes some small value, and a
larger one which takes a 16 bit value. As some branches also follow
this pattern, relaxing these values is required.
We can assemble both microMIPS and normal MIPS code in a single
object. Therefore, we need to support this type of relaxation at
the same time that we support the relaxation described above. We
use one of the high bits of the subtype field to distinguish these
cases.
The information we store for this type of relaxation is the argument
code found in the opcode file for this relocation, the register
selected as the assembler temporary, whether the branch is
unconditional, whether it is compact, whether it stores the link
address implicitly in $ra, whether relaxation of out-of-range 32-bit
branches to a sequence of instructions is enabled, and whether the
displacement of a branch is too large to fit as an immediate argument
of a 16-bit and a 32-bit branch, respectively. */
#define RELAX_MICROMIPS_ENCODE(type, at, uncond, compact, link, \
relax32, toofar16, toofar32) \
(0x40000000 \
| ((type) & 0xff) \
| (((at) & 0x1f) << 8) \
| ((uncond) ? 0x2000 : 0) \
| ((compact) ? 0x4000 : 0) \
| ((link) ? 0x8000 : 0) \
| ((relax32) ? 0x10000 : 0) \
| ((toofar16) ? 0x20000 : 0) \
| ((toofar32) ? 0x40000 : 0))
#define RELAX_MICROMIPS_P(i) (((i) & 0xc0000000) == 0x40000000)
#define RELAX_MICROMIPS_TYPE(i) ((i) & 0xff)
#define RELAX_MICROMIPS_AT(i) (((i) >> 8) & 0x1f)
#define RELAX_MICROMIPS_UNCOND(i) (((i) & 0x2000) != 0)
#define RELAX_MICROMIPS_COMPACT(i) (((i) & 0x4000) != 0)
#define RELAX_MICROMIPS_LINK(i) (((i) & 0x8000) != 0)
#define RELAX_MICROMIPS_RELAX32(i) (((i) & 0x10000) != 0)
#define RELAX_MICROMIPS_TOOFAR16(i) (((i) & 0x20000) != 0)
#define RELAX_MICROMIPS_MARK_TOOFAR16(i) ((i) | 0x20000)
#define RELAX_MICROMIPS_CLEAR_TOOFAR16(i) ((i) & ~0x20000)
#define RELAX_MICROMIPS_TOOFAR32(i) (((i) & 0x40000) != 0)
#define RELAX_MICROMIPS_MARK_TOOFAR32(i) ((i) | 0x40000)
#define RELAX_MICROMIPS_CLEAR_TOOFAR32(i) ((i) & ~0x40000)
/* Sign-extend 16-bit value X. */
#define SEXT_16BIT(X) ((((X) + 0x8000) & 0xffff) - 0x8000)
/* Is the given value a sign-extended 32-bit value? */
#define IS_SEXT_32BIT_NUM(x) \
(((x) &~ (offsetT) 0x7fffffff) == 0 \
|| (((x) &~ (offsetT) 0x7fffffff) == ~ (offsetT) 0x7fffffff))
/* Is the given value a sign-extended 16-bit value? */
#define IS_SEXT_16BIT_NUM(x) \
(((x) &~ (offsetT) 0x7fff) == 0 \
|| (((x) &~ (offsetT) 0x7fff) == ~ (offsetT) 0x7fff))
/* Is the given value a sign-extended 12-bit value? */
#define IS_SEXT_12BIT_NUM(x) \
(((((x) & 0xfff) ^ 0x800LL) - 0x800LL) == (x))
/* Is the given value a sign-extended 9-bit value? */
#define IS_SEXT_9BIT_NUM(x) \
(((((x) & 0x1ff) ^ 0x100LL) - 0x100LL) == (x))
/* 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))
/* Extract bits MASK << SHIFT from STRUCT and shift them right
SHIFT places. */
#define EXTRACT_BITS(STRUCT, MASK, SHIFT) \
(((STRUCT) >> (SHIFT)) & (MASK))
/* Extract the operand given by FIELD from mips_cl_insn INSN. */
#define EXTRACT_OPERAND(MICROMIPS, FIELD, INSN) \
(!(MICROMIPS) \
? EXTRACT_BITS ((INSN).insn_opcode, OP_MASK_##FIELD, OP_SH_##FIELD) \
: EXTRACT_BITS ((INSN).insn_opcode, \
MICROMIPSOP_MASK_##FIELD, MICROMIPSOP_SH_##FIELD))
#define MIPS16_EXTRACT_OPERAND(FIELD, INSN) \
EXTRACT_BITS ((INSN).insn_opcode, \
MIPS16OP_MASK_##FIELD, \
MIPS16OP_SH_##FIELD)
/* The MIPS16 EXTEND opcode, shifted left 16 places. */
#define MIPS16_EXTEND (0xf000U << 16)
/* Whether or not we are emitting a branch-likely macro. */
static bfd_boolean emit_branch_likely_macro = FALSE;
/* Global variables used when generating relaxable macros. See the
comment above RELAX_ENCODE for more details about how relaxation
is used. */
static struct {
/* 0 if we're not emitting a relaxable macro.
1 if we're emitting the first of the two relaxation alternatives.
2 if we're emitting the second alternative. */
int sequence;
/* The first relaxable fixup in the current frag. (In other words,
the first fixup that refers to relaxable code.) */
fixS *first_fixup;
/* sizes[0] says how many bytes of the first alternative are stored in
the current frag. Likewise sizes[1] for the second alternative. */
unsigned int sizes[2];
/* The symbol on which the choice of sequence depends. */
symbolS *symbol;
} mips_relax;
/* Global variables used to decide whether a macro needs a warning. */
static struct {
/* True if the macro is in a branch delay slot. */
bfd_boolean delay_slot_p;
/* Set to the length in bytes required if the macro is in a delay slot
that requires a specific length of instruction, otherwise zero. */
unsigned int delay_slot_length;
/* For relaxable macros, sizes[0] is the length of the first alternative
in bytes and sizes[1] is the length of the second alternative.
For non-relaxable macros, both elements give the length of the
macro in bytes. */
unsigned int sizes[2];
/* For relaxable macros, first_insn_sizes[0] is the length of the first
instruction of the first alternative in bytes and first_insn_sizes[1]
is the length of the first instruction of the second alternative.
For non-relaxable macros, both elements give the length of the first
instruction in bytes.
Set to zero if we haven't yet seen the first instruction. */
unsigned int first_insn_sizes[2];
/* For relaxable macros, insns[0] is the number of instructions for the
first alternative and insns[1] is the number of instructions for the
second alternative.
For non-relaxable macros, both elements give the number of
instructions for the macro. */
unsigned int insns[2];
/* The first variant frag for this macro. */
fragS *first_frag;
} mips_macro_warning;
/* Prototypes for static functions. */
enum mips_regclass { MIPS_GR_REG, MIPS_FP_REG, MIPS16_REG };
static void append_insn
(struct mips_cl_insn *, expressionS *, bfd_reloc_code_real_type *,
bfd_boolean expansionp);
static void mips_no_prev_insn (void);
static void macro_build (expressionS *, const char *, const char *, ...);
static void mips16_macro_build
(expressionS *, const char *, const char *, va_list *);
static void load_register (int, expressionS *, int);
static void macro_start (void);
static void macro_end (void);
static void macro (struct mips_cl_insn *ip, char *str);
static void mips16_macro (struct mips_cl_insn * ip);
static void mips_ip (char *str, struct mips_cl_insn * ip);
static void mips16_ip (char *str, struct mips_cl_insn * ip);
static void mips16_immed
(char *, unsigned int, int, bfd_reloc_code_real_type, offsetT,
unsigned int, unsigned long *);
static size_t my_getSmallExpression
(expressionS *, bfd_reloc_code_real_type *, char *);
static void my_getExpression (expressionS *, char *);
static void s_align (int);
static void s_change_sec (int);
static void s_change_section (int);
static void s_cons (int);
static void s_float_cons (int);
static void s_mips_globl (int);
static void s_option (int);
static void s_mipsset (int);
static void s_abicalls (int);
static void s_cpload (int);
static void s_cpsetup (int);
static void s_cplocal (int);
static void s_cprestore (int);
static void s_cpreturn (int);
static void s_dtprelword (int);
static void s_dtpreldword (int);
static void s_tprelword (int);
static void s_tpreldword (int);
static void s_gpvalue (int);
static void s_gpword (int);
static void s_gpdword (int);
static void s_ehword (int);
static void s_cpadd (int);
static void s_insn (int);
static void s_nan (int);
static void md_obj_begin (void);
static void md_obj_end (void);
static void s_mips_ent (int);
static void s_mips_end (int);
static void s_mips_frame (int);
static void s_mips_mask (int reg_type);
static void s_mips_stab (int);
static void s_mips_weakext (int);
static void s_mips_file (int);
static void s_mips_loc (int);
static bfd_boolean pic_need_relax (symbolS *, asection *);
static int relaxed_branch_length (fragS *, asection *, int);
static int relaxed_micromips_16bit_branch_length (fragS *, asection *, int);
static int relaxed_micromips_32bit_branch_length (fragS *, asection *, int);
/* Table and functions used to map between CPU/ISA names, and
ISA levels, and CPU numbers. */
struct mips_cpu_info
{
const char *name; /* CPU or ISA name. */
int flags; /* MIPS_CPU_* flags. */
int ase; /* Set of ASEs implemented by the CPU. */
int isa; /* ISA level. */
int cpu; /* CPU number (default CPU if ISA). */
};
#define MIPS_CPU_IS_ISA 0x0001 /* Is this an ISA? (If 0, a CPU.) */
static const struct mips_cpu_info *mips_parse_cpu (const char *, const char *);
static const struct mips_cpu_info *mips_cpu_info_from_isa (int);
static const struct mips_cpu_info *mips_cpu_info_from_arch (int);
/* Command-line options. */
const char *md_shortopts = "O::g::G:";
enum options
{
OPTION_MARCH = OPTION_MD_BASE,
OPTION_MTUNE,
OPTION_MIPS1,
OPTION_MIPS2,
OPTION_MIPS3,
OPTION_MIPS4,
OPTION_MIPS5,
OPTION_MIPS32,
OPTION_MIPS64,
OPTION_MIPS32R2,
OPTION_MIPS64R2,
OPTION_MIPS16,
OPTION_NO_MIPS16,
OPTION_MIPS3D,
OPTION_NO_MIPS3D,
OPTION_MDMX,
OPTION_NO_MDMX,
OPTION_DSP,
OPTION_NO_DSP,
OPTION_MT,
OPTION_NO_MT,
OPTION_VIRT,
OPTION_NO_VIRT,
OPTION_SMARTMIPS,
OPTION_NO_SMARTMIPS,
OPTION_DSPR2,
OPTION_NO_DSPR2,
OPTION_EVA,
OPTION_NO_EVA,
OPTION_MICROMIPS,
OPTION_NO_MICROMIPS,
OPTION_MCU,
OPTION_NO_MCU,
OPTION_COMPAT_ARCH_BASE,
OPTION_M4650,
OPTION_NO_M4650,
OPTION_M4010,
OPTION_NO_M4010,
OPTION_M4100,
OPTION_NO_M4100,
OPTION_M3900,
OPTION_NO_M3900,
OPTION_M7000_HILO_FIX,
OPTION_MNO_7000_HILO_FIX,
OPTION_FIX_24K,
OPTION_NO_FIX_24K,
OPTION_FIX_LOONGSON2F_JUMP,
OPTION_NO_FIX_LOONGSON2F_JUMP,
OPTION_FIX_LOONGSON2F_NOP,
OPTION_NO_FIX_LOONGSON2F_NOP,
OPTION_FIX_VR4120,
OPTION_NO_FIX_VR4120,
OPTION_FIX_VR4130,
OPTION_NO_FIX_VR4130,
OPTION_FIX_CN63XXP1,
OPTION_NO_FIX_CN63XXP1,
OPTION_TRAP,
OPTION_BREAK,
OPTION_EB,
OPTION_EL,
OPTION_FP32,
OPTION_GP32,
OPTION_CONSTRUCT_FLOATS,
OPTION_NO_CONSTRUCT_FLOATS,
OPTION_FP64,
OPTION_GP64,
OPTION_RELAX_BRANCH,
OPTION_NO_RELAX_BRANCH,
OPTION_INSN32,
OPTION_NO_INSN32,
OPTION_MSHARED,
OPTION_MNO_SHARED,
OPTION_MSYM32,
OPTION_MNO_SYM32,
OPTION_SOFT_FLOAT,
OPTION_HARD_FLOAT,
OPTION_SINGLE_FLOAT,
OPTION_DOUBLE_FLOAT,
OPTION_32,
OPTION_CALL_SHARED,
OPTION_CALL_NONPIC,
OPTION_NON_SHARED,
OPTION_XGOT,
OPTION_MABI,
OPTION_N32,
OPTION_64,
OPTION_MDEBUG,
OPTION_NO_MDEBUG,
OPTION_PDR,
OPTION_NO_PDR,
OPTION_MVXWORKS_PIC,
OPTION_NAN,
OPTION_END_OF_ENUM
};
struct option md_longopts[] =
{
/* Options which specify architecture. */
{"march", required_argument, NULL, OPTION_MARCH},
{"mtune", required_argument, NULL, OPTION_MTUNE},
{"mips0", no_argument, NULL, OPTION_MIPS1},
{"mips1", no_argument, NULL, OPTION_MIPS1},
{"mips2", no_argument, NULL, OPTION_MIPS2},
{"mips3", no_argument, NULL, OPTION_MIPS3},
{"mips4", no_argument, NULL, OPTION_MIPS4},
{"mips5", no_argument, NULL, OPTION_MIPS5},
{"mips32", no_argument, NULL, OPTION_MIPS32},
{"mips64", no_argument, NULL, OPTION_MIPS64},
{"mips32r2", no_argument, NULL, OPTION_MIPS32R2},
{"mips64r2", no_argument, NULL, OPTION_MIPS64R2},
/* Options which specify Application Specific Extensions (ASEs). */
{"mips16", no_argument, NULL, OPTION_MIPS16},
{"no-mips16", no_argument, NULL, OPTION_NO_MIPS16},
{"mips3d", no_argument, NULL, OPTION_MIPS3D},
{"no-mips3d", no_argument, NULL, OPTION_NO_MIPS3D},
{"mdmx", no_argument, NULL, OPTION_MDMX},
{"no-mdmx", no_argument, NULL, OPTION_NO_MDMX},
{"mdsp", no_argument, NULL, OPTION_DSP},
{"mno-dsp", no_argument, NULL, OPTION_NO_DSP},
{"mmt", no_argument, NULL, OPTION_MT},
{"mno-mt", no_argument, NULL, OPTION_NO_MT},
{"msmartmips", no_argument, NULL, OPTION_SMARTMIPS},
{"mno-smartmips", no_argument, NULL, OPTION_NO_SMARTMIPS},
{"mdspr2", no_argument, NULL, OPTION_DSPR2},
{"mno-dspr2", no_argument, NULL, OPTION_NO_DSPR2},
{"meva", no_argument, NULL, OPTION_EVA},
{"mno-eva", no_argument, NULL, OPTION_NO_EVA},
{"mmicromips", no_argument, NULL, OPTION_MICROMIPS},
{"mno-micromips", no_argument, NULL, OPTION_NO_MICROMIPS},
{"mmcu", no_argument, NULL, OPTION_MCU},
{"mno-mcu", no_argument, NULL, OPTION_NO_MCU},
{"mvirt", no_argument, NULL, OPTION_VIRT},
{"mno-virt", no_argument, NULL, OPTION_NO_VIRT},
/* Old-style architecture options. Don't add more of these. */
{"m4650", no_argument, NULL, OPTION_M4650},
{"no-m4650", no_argument, NULL, OPTION_NO_M4650},
{"m4010", no_argument, NULL, OPTION_M4010},
{"no-m4010", no_argument, NULL, OPTION_NO_M4010},
{"m4100", no_argument, NULL, OPTION_M4100},
{"no-m4100", no_argument, NULL, OPTION_NO_M4100},
{"m3900", no_argument, NULL, OPTION_M3900},
{"no-m3900", no_argument, NULL, OPTION_NO_M3900},
/* Options which enable bug fixes. */
{"mfix7000", no_argument, NULL, OPTION_M7000_HILO_FIX},
{"no-fix-7000", no_argument, NULL, OPTION_MNO_7000_HILO_FIX},
{"mno-fix7000", no_argument, NULL, OPTION_MNO_7000_HILO_FIX},
{"mfix-loongson2f-jump", no_argument, NULL, OPTION_FIX_LOONGSON2F_JUMP},
{"mno-fix-loongson2f-jump", no_argument, NULL, OPTION_NO_FIX_LOONGSON2F_JUMP},
{"mfix-loongson2f-nop", no_argument, NULL, OPTION_FIX_LOONGSON2F_NOP},
{"mno-fix-loongson2f-nop", no_argument, NULL, OPTION_NO_FIX_LOONGSON2F_NOP},
{"mfix-vr4120", no_argument, NULL, OPTION_FIX_VR4120},
{"mno-fix-vr4120", no_argument, NULL, OPTION_NO_FIX_VR4120},
{"mfix-vr4130", no_argument, NULL, OPTION_FIX_VR4130},
{"mno-fix-vr4130", no_argument, NULL, OPTION_NO_FIX_VR4130},
{"mfix-24k", no_argument, NULL, OPTION_FIX_24K},
{"mno-fix-24k", no_argument, NULL, OPTION_NO_FIX_24K},
{"mfix-cn63xxp1", no_argument, NULL, OPTION_FIX_CN63XXP1},
{"mno-fix-cn63xxp1", no_argument, NULL, OPTION_NO_FIX_CN63XXP1},
/* Miscellaneous options. */
{"trap", no_argument, NULL, OPTION_TRAP},
{"no-break", no_argument, NULL, OPTION_TRAP},
{"break", no_argument, NULL, OPTION_BREAK},
{"no-trap", no_argument, NULL, OPTION_BREAK},
{"EB", no_argument, NULL, OPTION_EB},
{"EL", no_argument, NULL, OPTION_EL},
{"mfp32", no_argument, NULL, OPTION_FP32},
{"mgp32", no_argument, NULL, OPTION_GP32},
{"construct-floats", no_argument, NULL, OPTION_CONSTRUCT_FLOATS},
{"no-construct-floats", no_argument, NULL, OPTION_NO_CONSTRUCT_FLOATS},
{"mfp64", no_argument, NULL, OPTION_FP64},
{"mgp64", no_argument, NULL, OPTION_GP64},
{"relax-branch", no_argument, NULL, OPTION_RELAX_BRANCH},
{"no-relax-branch", no_argument, NULL, OPTION_NO_RELAX_BRANCH},
{"minsn32", no_argument, NULL, OPTION_INSN32},
{"mno-insn32", no_argument, NULL, OPTION_NO_INSN32},
{"mshared", no_argument, NULL, OPTION_MSHARED},
{"mno-shared", no_argument, NULL, OPTION_MNO_SHARED},
{"msym32", no_argument, NULL, OPTION_MSYM32},
{"mno-sym32", no_argument, NULL, OPTION_MNO_SYM32},
{"msoft-float", no_argument, NULL, OPTION_SOFT_FLOAT},
{"mhard-float", no_argument, NULL, OPTION_HARD_FLOAT},
{"msingle-float", no_argument, NULL, OPTION_SINGLE_FLOAT},
{"mdouble-float", no_argument, NULL, OPTION_DOUBLE_FLOAT},
/* Strictly speaking this next option is ELF specific,
but we allow it for other ports as well in order to
make testing easier. */
{"32", no_argument, NULL, OPTION_32},
/* ELF-specific options. */
{"KPIC", no_argument, NULL, OPTION_CALL_SHARED},
{"call_shared", no_argument, NULL, OPTION_CALL_SHARED},
{"call_nonpic", no_argument, NULL, OPTION_CALL_NONPIC},
{"non_shared", no_argument, NULL, OPTION_NON_SHARED},
{"xgot", no_argument, NULL, OPTION_XGOT},
{"mabi", required_argument, NULL, OPTION_MABI},
{"n32", no_argument, NULL, OPTION_N32},
{"64", no_argument, NULL, OPTION_64},
{"mdebug", no_argument, NULL, OPTION_MDEBUG},
{"no-mdebug", no_argument, NULL, OPTION_NO_MDEBUG},
{"mpdr", no_argument, NULL, OPTION_PDR},
{"mno-pdr", no_argument, NULL, OPTION_NO_PDR},
{"mvxworks-pic", no_argument, NULL, OPTION_MVXWORKS_PIC},
{"mnan", required_argument, NULL, OPTION_NAN},
{NULL, no_argument, NULL, 0}
};
size_t md_longopts_size = sizeof (md_longopts);
/* Information about either an Application Specific Extension or an
optional architecture feature that, for simplicity, we treat in the
same way as an ASE. */
struct mips_ase
{
/* The name of the ASE, used in both the command-line and .set options. */
const char *name;
/* The associated ASE_* flags. If the ASE is available on both 32-bit
and 64-bit architectures, the flags here refer to the subset that
is available on both. */
unsigned int flags;
/* The ASE_* flag used for instructions that are available on 64-bit
architectures but that are not included in FLAGS. */
unsigned int flags64;
/* The command-line options that turn the ASE on and off. */
int option_on;
int option_off;
/* The minimum required architecture revisions for MIPS32, MIPS64,
microMIPS32 and microMIPS64, or -1 if the extension isn't supported. */
int mips32_rev;
int mips64_rev;
int micromips32_rev;
int micromips64_rev;
};
/* A table of all supported ASEs. */
static const struct mips_ase mips_ases[] = {
{ "dsp", ASE_DSP, ASE_DSP64,
OPTION_DSP, OPTION_NO_DSP,
2, 2, 2, 2 },
{ "dspr2", ASE_DSP | ASE_DSPR2, 0,
OPTION_DSPR2, OPTION_NO_DSPR2,
2, 2, 2, 2 },
{ "eva", ASE_EVA, 0,
OPTION_EVA, OPTION_NO_EVA,
2, 2, 2, 2 },
{ "mcu", ASE_MCU, 0,
OPTION_MCU, OPTION_NO_MCU,
2, 2, 2, 2 },
/* Deprecated in MIPS64r5, but we don't implement that yet. */
{ "mdmx", ASE_MDMX, 0,
OPTION_MDMX, OPTION_NO_MDMX,
-1, 1, -1, -1 },
/* Requires 64-bit FPRs, so the minimum MIPS32 revision is 2. */
{ "mips3d", ASE_MIPS3D, 0,
OPTION_MIPS3D, OPTION_NO_MIPS3D,
2, 1, -1, -1 },
{ "mt", ASE_MT, 0,
OPTION_MT, OPTION_NO_MT,
2, 2, -1, -1 },
{ "smartmips", ASE_SMARTMIPS, 0,
OPTION_SMARTMIPS, OPTION_NO_SMARTMIPS,
1, -1, -1, -1 },
{ "virt", ASE_VIRT, ASE_VIRT64,
OPTION_VIRT, OPTION_NO_VIRT,
2, 2, 2, 2 }
};
/* The set of ASEs that require -mfp64. */
#define FP64_ASES (ASE_MIPS3D | ASE_MDMX)
/* Groups of ASE_* flags that represent different revisions of an ASE. */
static const unsigned int mips_ase_groups[] = {
ASE_DSP | ASE_DSPR2
};
/* Pseudo-op table.
The following pseudo-ops from the Kane and Heinrich MIPS book
should be defined here, but are currently unsupported: .alias,
.galive, .gjaldef, .gjrlive, .livereg, .noalias.
The following pseudo-ops from the Kane and Heinrich MIPS book are
specific to the type of debugging information being generated, and
should be defined by the object format: .aent, .begin, .bend,
.bgnb, .end, .endb, .ent, .fmask, .frame, .loc, .mask, .verstamp,
.vreg.
The following pseudo-ops from the Kane and Heinrich MIPS book are
not MIPS CPU specific, but are also not specific to the object file
format. This file is probably the best place to define them, but
they are not currently supported: .asm0, .endr, .lab, .struct. */
static const pseudo_typeS mips_pseudo_table[] =
{
/* MIPS specific pseudo-ops. */
{"option", s_option, 0},
{"set", s_mipsset, 0},
{"rdata", s_change_sec, 'r'},
{"sdata", s_change_sec, 's'},
{"livereg", s_ignore, 0},
{"abicalls", s_abicalls, 0},
{"cpload", s_cpload, 0},
{"cpsetup", s_cpsetup, 0},
{"cplocal", s_cplocal, 0},
{"cprestore", s_cprestore, 0},
{"cpreturn", s_cpreturn, 0},
{"dtprelword", s_dtprelword, 0},
{"dtpreldword", s_dtpreldword, 0},
{"tprelword", s_tprelword, 0},
{"tpreldword", s_tpreldword, 0},
{"gpvalue", s_gpvalue, 0},
{"gpword", s_gpword, 0},
{"gpdword", s_gpdword, 0},
{"ehword", s_ehword, 0},
{"cpadd", s_cpadd, 0},
{"insn", s_insn, 0},
{"nan", s_nan, 0},
/* Relatively generic pseudo-ops that happen to be used on MIPS
chips. */
{"asciiz", stringer, 8 + 1},
{"bss", s_change_sec, 'b'},
{"err", s_err, 0},
{"half", s_cons, 1},
{"dword", s_cons, 3},
{"weakext", s_mips_weakext, 0},
{"origin", s_org, 0},
{"repeat", s_rept, 0},
/* For MIPS this is non-standard, but we define it for consistency. */
{"sbss", s_change_sec, 'B'},
/* These pseudo-ops are defined in read.c, but must be overridden
here for one reason or another. */
{"align", s_align, 0},
{"byte", s_cons, 0},
{"data", s_change_sec, 'd'},
{"double", s_float_cons, 'd'},
{"float", s_float_cons, 'f'},
{"globl", s_mips_globl, 0},
{"global", s_mips_globl, 0},
{"hword", s_cons, 1},
{"int", s_cons, 2},
{"long", s_cons, 2},
{"octa", s_cons, 4},
{"quad", s_cons, 3},
{"section", s_change_section, 0},
{"short", s_cons, 1},
{"single", s_float_cons, 'f'},
{"stabd", s_mips_stab, 'd'},
{"stabn", s_mips_stab, 'n'},
{"stabs", s_mips_stab, 's'},
{"text", s_change_sec, 't'},
{"word", s_cons, 2},
{ "extern", ecoff_directive_extern, 0},
{ NULL, NULL, 0 },
};
static const pseudo_typeS mips_nonecoff_pseudo_table[] =
{
/* These pseudo-ops should be defined by the object file format.
However, a.out doesn't support them, so we have versions here. */
{"aent", s_mips_ent, 1},
{"bgnb", s_ignore, 0},
{"end", s_mips_end, 0},
{"endb", s_ignore, 0},
{"ent", s_mips_ent, 0},
{"file", s_mips_file, 0},
{"fmask", s_mips_mask, 'F'},
{"frame", s_mips_frame, 0},
{"loc", s_mips_loc, 0},
{"mask", s_mips_mask, 'R'},
{"verstamp", s_ignore, 0},
{ NULL, NULL, 0 },
};
/* Export the ABI address size for use by TC_ADDRESS_BYTES for the
purpose of the `.dc.a' internal pseudo-op. */
int
mips_address_bytes (void)
{
return HAVE_64BIT_ADDRESSES ? 8 : 4;
}
extern void pop_insert (const pseudo_typeS *);
void
mips_pop_insert (void)
{
pop_insert (mips_pseudo_table);
if (! ECOFF_DEBUGGING)
pop_insert (mips_nonecoff_pseudo_table);
}
/* Symbols labelling the current insn. */
struct insn_label_list
{
struct insn_label_list *next;
symbolS *label;
};
static struct insn_label_list *free_insn_labels;
#define label_list tc_segment_info_data.labels
static void mips_clear_insn_labels (void);
static void mips_mark_labels (void);
static void mips_compressed_mark_labels (void);
static inline void
mips_clear_insn_labels (void)
{
register struct insn_label_list **pl;
segment_info_type *si;
if (now_seg)
{
for (pl = &free_insn_labels; *pl != NULL; pl = &(*pl)->next)
;
si = seg_info (now_seg);
*pl = si->label_list;
si->label_list = NULL;
}
}
/* Mark instruction labels in MIPS16/microMIPS mode. */
static inline void
mips_mark_labels (void)
{
if (HAVE_CODE_COMPRESSION)
mips_compressed_mark_labels ();
}
static char *expr_end;
/* An expression in a macro instruction. This is set by mips_ip and
mips16_ip and when populated is always an O_constant. */
static expressionS imm_expr;
/* The relocatable field in an instruction and the relocs associated
with it. These variables are used for instructions like LUI and
JAL as well as true offsets. They are also used for address
operands in macros. */
static expressionS offset_expr;
static bfd_reloc_code_real_type offset_reloc[3]
= {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
/* This is set to the resulting size of the instruction to be produced
by mips16_ip if an explicit extension is used or by mips_ip if an
explicit size is supplied. */
static unsigned int forced_insn_length;
/* True if we are assembling an instruction. All dot symbols defined during
this time should be treated as code labels. */
static bfd_boolean mips_assembling_insn;
/* The pdr segment for per procedure frame/regmask info. Not used for
ECOFF debugging. */
static segT pdr_seg;
/* The default target format to use. */
#if defined (TE_FreeBSD)
#define ELF_TARGET(PREFIX, ENDIAN) PREFIX "trad" ENDIAN "mips-freebsd"
#elif defined (TE_TMIPS)
#define ELF_TARGET(PREFIX, ENDIAN) PREFIX "trad" ENDIAN "mips"
#else
#define ELF_TARGET(PREFIX, ENDIAN) PREFIX ENDIAN "mips"
#endif
const char *
mips_target_format (void)
{
switch (OUTPUT_FLAVOR)
{
case bfd_target_elf_flavour:
#ifdef TE_VXWORKS
if (!HAVE_64BIT_OBJECTS && !HAVE_NEWABI)
return (target_big_endian
? "elf32-bigmips-vxworks"
: "elf32-littlemips-vxworks");
#endif
return (target_big_endian
? (HAVE_64BIT_OBJECTS
? ELF_TARGET ("elf64-", "big")
: (HAVE_NEWABI
? ELF_TARGET ("elf32-n", "big")
: ELF_TARGET ("elf32-", "big")))
: (HAVE_64BIT_OBJECTS
? ELF_TARGET ("elf64-", "little")
: (HAVE_NEWABI
? ELF_TARGET ("elf32-n", "little")
: ELF_TARGET ("elf32-", "little"))));
default:
abort ();
return NULL;
}
}
/* Return the ISA revision that is currently in use, or 0 if we are
generating code for MIPS V or below. */
static int
mips_isa_rev (void)
{
if (mips_opts.isa == ISA_MIPS32R2 || mips_opts.isa == ISA_MIPS64R2)
return 2;
/* microMIPS implies revision 2 or above. */
if (mips_opts.micromips)
return 2;
if (mips_opts.isa == ISA_MIPS32 || mips_opts.isa == ISA_MIPS64)
return 1;
return 0;
}
/* Return the mask of all ASEs that are revisions of those in FLAGS. */
static unsigned int
mips_ase_mask (unsigned int flags)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE (mips_ase_groups); i++)
if (flags & mips_ase_groups[i])
flags |= mips_ase_groups[i];
return flags;
}
/* Check whether the current ISA supports ASE. Issue a warning if
appropriate. */
static void
mips_check_isa_supports_ase (const struct mips_ase *ase)
{
const char *base;
int min_rev, size;
static unsigned int warned_isa;
static unsigned int warned_fp32;
if (ISA_HAS_64BIT_REGS (mips_opts.isa))
min_rev = mips_opts.micromips ? ase->micromips64_rev : ase->mips64_rev;
else
min_rev = mips_opts.micromips ? ase->micromips32_rev : ase->mips32_rev;
if ((min_rev < 0 || mips_isa_rev () < min_rev)
&& (warned_isa & ase->flags) != ase->flags)
{
warned_isa |= ase->flags;
base = mips_opts.micromips ? "microMIPS" : "MIPS";
size = ISA_HAS_64BIT_REGS (mips_opts.isa) ? 64 : 32;
if (min_rev < 0)
as_warn (_("the %d-bit %s architecture does not support the"
" `%s' extension"), size, base, ase->name);
else
as_warn (_("the `%s' extension requires %s%d revision %d or greater"),
ase->name, base, size, min_rev);
}
if ((ase->flags & FP64_ASES)
&& mips_opts.fp32
&& (warned_fp32 & ase->flags) != ase->flags)
{
warned_fp32 |= ase->flags;
as_warn (_("the `%s' extension requires 64-bit FPRs"), ase->name);
}
}
/* Check all enabled ASEs to see whether they are supported by the
chosen architecture. */
static void
mips_check_isa_supports_ases (void)
{
unsigned int i, mask;
for (i = 0; i < ARRAY_SIZE (mips_ases); i++)
{
mask = mips_ase_mask (mips_ases[i].flags);
if ((mips_opts.ase & mask) == mips_ases[i].flags)
mips_check_isa_supports_ase (&mips_ases[i]);
}
}
/* Set the state of ASE to ENABLED_P. Return the mask of ASE_* flags
that were affected. */
static unsigned int
mips_set_ase (const struct mips_ase *ase, bfd_boolean enabled_p)
{
unsigned int mask;
mask = mips_ase_mask (ase->flags);
mips_opts.ase &= ~mask;
if (enabled_p)
mips_opts.ase |= ase->flags;
return mask;
}
/* Return the ASE called NAME, or null if none. */
static const struct mips_ase *
mips_lookup_ase (const char *name)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE (mips_ases); i++)
if (strcmp (name, mips_ases[i].name) == 0)
return &mips_ases[i];
return NULL;
}
/* Return the length of a microMIPS instruction in bytes. If bits of
the mask beyond the low 16 are 0, then it is a 16-bit instruction.
Otherwise assume a 32-bit instruction; 48-bit instructions (0x1f
major opcode) will require further modifications to the opcode
table. */
static inline unsigned int
micromips_insn_length (const struct mips_opcode *mo)
{
return (mo->mask >> 16) == 0 ? 2 : 4;
}
/* Return the length of MIPS16 instruction OPCODE. */
static inline unsigned int
mips16_opcode_length (unsigned long opcode)
{
return (opcode >> 16) == 0 ? 2 : 4;
}
/* Return the length of instruction INSN. */
static inline unsigned int
insn_length (const struct mips_cl_insn *insn)
{
if (mips_opts.micromips)
return micromips_insn_length (insn->insn_mo);
else if (mips_opts.mips16)
return mips16_opcode_length (insn->insn_opcode);
else
return 4;
}
/* 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->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;
insn->complete_p = 0;
insn->cleared_p = 0;
}
/* Get a list of all the operands in INSN. */
static const struct mips_operand_array *
insn_operands (const struct mips_cl_insn *insn)
{
if (insn->insn_mo >= &mips_opcodes[0]
&& insn->insn_mo < &mips_opcodes[NUMOPCODES])
return &mips_operands[insn->insn_mo - &mips_opcodes[0]];
if (insn->insn_mo >= &mips16_opcodes[0]
&& insn->insn_mo < &mips16_opcodes[bfd_mips16_num_opcodes])
return &mips16_operands[insn->insn_mo - &mips16_opcodes[0]];
if (insn->insn_mo >= &micromips_opcodes[0]
&& insn->insn_mo < &micromips_opcodes[bfd_micromips_num_opcodes])
return &micromips_operands[insn->insn_mo - &micromips_opcodes[0]];
abort ();
}
/* Get a description of operand OPNO of INSN. */
static const struct mips_operand *
insn_opno (const struct mips_cl_insn *insn, unsigned opno)
{
const struct mips_operand_array *operands;
operands = insn_operands (insn);
if (opno >= MAX_OPERANDS || !operands->operand[opno])
abort ();
return operands->operand[opno];
}
/* Install UVAL as the value of OPERAND in INSN. */
static inline void
insn_insert_operand (struct mips_cl_insn *insn,
const struct mips_operand *operand, unsigned int uval)
{
insn->insn_opcode = mips_insert_operand (operand, insn->insn_opcode, uval);
}
/* Extract the value of OPERAND from INSN. */
static inline unsigned
insn_extract_operand (const struct mips_cl_insn *insn,
const struct mips_operand *operand)
{
return mips_extract_operand (operand, insn->insn_opcode);
}
/* Record the current MIPS16/microMIPS mode in now_seg. */
static void
mips_record_compressed_mode (void)
{
segment_info_type *si;
si = seg_info (now_seg);
if (si->tc_segment_info_data.mips16 != mips_opts.mips16)
si->tc_segment_info_data.mips16 = mips_opts.mips16;
if (si->tc_segment_info_data.micromips != mips_opts.micromips)
si->tc_segment_info_data.micromips = mips_opts.micromips;
}
/* Read a standard MIPS instruction from BUF. */
static unsigned long
read_insn (char *buf)
{
if (target_big_endian)
return bfd_getb32 ((bfd_byte *) buf);
else
return bfd_getl32 ((bfd_byte *) buf);
}
/* Write standard MIPS instruction INSN to BUF. Return a pointer to
the next byte. */
static char *
write_insn (char *buf, unsigned int insn)
{
md_number_to_chars (buf, insn, 4);
return buf + 4;
}
/* Read a microMIPS or MIPS16 opcode from BUF, given that it
has length LENGTH. */
static unsigned long
read_compressed_insn (char *buf, unsigned int length)
{
unsigned long insn;
unsigned int i;
insn = 0;
for (i = 0; i < length; i += 2)
{
insn <<= 16;
if (target_big_endian)
insn |= bfd_getb16 ((char *) buf);
else
insn |= bfd_getl16 ((char *) buf);
buf += 2;
}
return insn;
}
/* Write microMIPS or MIPS16 instruction INSN to BUF, given that the
instruction is LENGTH bytes long. Return a pointer to the next byte. */
static char *
write_compressed_insn (char *buf, unsigned int insn, unsigned int length)
{
unsigned int i;
for (i = 0; i < length; i += 2)
md_number_to_chars (buf + i, insn >> ((length - i - 2) * 8), 2);
return buf + length;
}
/* 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 (HAVE_CODE_COMPRESSION)
write_compressed_insn (f, insn->insn_opcode, insn_length (insn));
else
write_insn (f, insn->insn_opcode);
mips_record_compressed_mode ();
}
/* 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;
}
}
/* Clear the error in insn_error. */
static void
clear_insn_error (void)
{
memset (&insn_error, 0, sizeof (insn_error));
}
/* Possibly record error message MSG for the current instruction.
If the error is about a particular argument, ARGNUM is the 1-based
number of that argument, otherwise it is 0. FORMAT is the format
of MSG. Return true if MSG was used, false if the current message
was kept. */
static bfd_boolean
set_insn_error_format (int argnum, enum mips_insn_error_format format,
const char *msg)
{
if (argnum == 0)
{
/* Give priority to errors against specific arguments, and to
the first whole-instruction message. */
if (insn_error.msg)
return FALSE;
}
else
{
/* Keep insn_error if it is against a later argument. */
if (argnum < insn_error.min_argnum)
return FALSE;
/* If both errors are against the same argument but are different,
give up on reporting a specific error for this argument.
See the comment about mips_insn_error for details. */
if (argnum == insn_error.min_argnum
&& insn_error.msg
&& strcmp (insn_error.msg, msg) != 0)
{
insn_error.msg = 0;
insn_error.min_argnum += 1;
return FALSE;
}
}
insn_error.min_argnum = argnum;
insn_error.format = format;
insn_error.msg = msg;
return TRUE;
}
/* Record an instruction error with no % format fields. ARGNUM and MSG are
as for set_insn_error_format. */
static void
set_insn_error (int argnum, const char *msg)
{
set_insn_error_format (argnum, ERR_FMT_PLAIN, msg);
}
/* Record an instruction error with one %d field I. ARGNUM and MSG are
as for set_insn_error_format. */
static void
set_insn_error_i (int argnum, const char *msg, int i)
{
if (set_insn_error_format (argnum, ERR_FMT_I, msg))
insn_error.u.i = i;
}
/* Record an instruction error with two %s fields S1 and S2. ARGNUM and MSG
are as for set_insn_error_format. */
static void
set_insn_error_ss (int argnum, const char *msg, const char *s1, const char *s2)
{
if (set_insn_error_format (argnum, ERR_FMT_SS, msg))
{
insn_error.u.ss[0] = s1;
insn_error.u.ss[1] = s2;
}
}
/* Report the error in insn_error, which is against assembly code STR. */
static void
report_insn_error (const char *str)
{
const char *msg;
msg = ACONCAT ((insn_error.msg, " `%s'", NULL));
switch (insn_error.format)
{
case ERR_FMT_PLAIN:
as_bad (msg, str);
break;
case ERR_FMT_I:
as_bad (msg, insn_error.u.i, str);
break;
case ERR_FMT_SS:
as_bad (msg, insn_error.u.ss[0], insn_error.u.ss[1], str);
break;
}
}
/* 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
}
struct regname {
const char *name;
unsigned int num;
};
#define RNUM_MASK 0x00000ff
#define RTYPE_MASK 0x0efff00
#define RTYPE_NUM 0x0000100
#define RTYPE_FPU 0x0000200
#define RTYPE_FCC 0x0000400
#define RTYPE_VEC 0x0000800
#define RTYPE_GP 0x0001000
#define RTYPE_CP0 0x0002000
#define RTYPE_PC 0x0004000
#define RTYPE_ACC 0x0008000
#define RTYPE_CCC 0x0010000
#define RTYPE_VI 0x0020000
#define RTYPE_VF 0x0040000
#define RTYPE_R5900_I 0x0080000
#define RTYPE_R5900_Q 0x0100000
#define RTYPE_R5900_R 0x0200000
#define RTYPE_R5900_ACC 0x0400000
#define RWARN 0x8000000
#define GENERIC_REGISTER_NUMBERS \
{"$0", RTYPE_NUM | 0}, \
{"$1", RTYPE_NUM | 1}, \
{"$2", RTYPE_NUM | 2}, \
{"$3", RTYPE_NUM | 3}, \
{"$4", RTYPE_NUM | 4}, \
{"$5", RTYPE_NUM | 5}, \
{"$6", RTYPE_NUM | 6}, \
{"$7", RTYPE_NUM | 7}, \
{"$8", RTYPE_NUM | 8}, \
{"$9", RTYPE_NUM | 9}, \
{"$10", RTYPE_NUM | 10}, \
{"$11", RTYPE_NUM | 11}, \
{"$12", RTYPE_NUM | 12}, \
{"$13", RTYPE_NUM | 13}, \
{"$14", RTYPE_NUM | 14}, \
{"$15", RTYPE_NUM | 15}, \
{"$16", RTYPE_NUM | 16}, \
{"$17", RTYPE_NUM | 17}, \
{"$18", RTYPE_NUM | 18}, \
{"$19", RTYPE_NUM | 19}, \
{"$20", RTYPE_NUM | 20}, \
{"$21", RTYPE_NUM | 21}, \
{"$22", RTYPE_NUM | 22}, \
{"$23", RTYPE_NUM | 23}, \
{"$24", RTYPE_NUM | 24}, \
{"$25", RTYPE_NUM | 25}, \
{"$26", RTYPE_NUM | 26}, \
{"$27", RTYPE_NUM | 27}, \
{"$28", RTYPE_NUM | 28}, \
{"$29", RTYPE_NUM | 29}, \
{"$30", RTYPE_NUM | 30}, \
{"$31", RTYPE_NUM | 31}
#define FPU_REGISTER_NAMES \
{"$f0", RTYPE_FPU | 0}, \
{"$f1", RTYPE_FPU | 1}, \
{"$f2", RTYPE_FPU | 2}, \
{"$f3", RTYPE_FPU | 3}, \
{"$f4", RTYPE_FPU | 4}, \
{"$f5", RTYPE_FPU | 5}, \
{"$f6", RTYPE_FPU | 6}, \
{"$f7", RTYPE_FPU | 7}, \
{"$f8", RTYPE_FPU | 8}, \
{"$f9", RTYPE_FPU | 9}, \
{"$f10", RTYPE_FPU | 10}, \
{"$f11", RTYPE_FPU | 11}, \
{"$f12", RTYPE_FPU | 12}, \
{"$f13", RTYPE_FPU | 13}, \
{"$f14", RTYPE_FPU | 14}, \
{"$f15", RTYPE_FPU | 15}, \
{"$f16", RTYPE_FPU | 16}, \
{"$f17", RTYPE_FPU | 17}, \
{"$f18", RTYPE_FPU | 18}, \
{"$f19", RTYPE_FPU | 19}, \
{"$f20", RTYPE_FPU | 20}, \
{"$f21", RTYPE_FPU | 21}, \
{"$f22", RTYPE_FPU | 22}, \
{"$f23", RTYPE_FPU | 23}, \
{"$f24", RTYPE_FPU | 24}, \
{"$f25", RTYPE_FPU | 25}, \
{"$f26", RTYPE_FPU | 26}, \
{"$f27", RTYPE_FPU | 27}, \
{"$f28", RTYPE_FPU | 28}, \
{"$f29", RTYPE_FPU | 29}, \
{"$f30", RTYPE_FPU | 30}, \
{"$f31", RTYPE_FPU | 31}
#define FPU_CONDITION_CODE_NAMES \
{"$fcc0", RTYPE_FCC | 0}, \
{"$fcc1", RTYPE_FCC | 1}, \
{"$fcc2", RTYPE_FCC | 2}, \
{"$fcc3", RTYPE_FCC | 3}, \
{"$fcc4", RTYPE_FCC | 4}, \
{"$fcc5", RTYPE_FCC | 5}, \
{"$fcc6", RTYPE_FCC | 6}, \
{"$fcc7", RTYPE_FCC | 7}
#define COPROC_CONDITION_CODE_NAMES \
{"$cc0", RTYPE_FCC | RTYPE_CCC | 0}, \
{"$cc1", RTYPE_FCC | RTYPE_CCC | 1}, \
{"$cc2", RTYPE_FCC | RTYPE_CCC | 2}, \
{"$cc3", RTYPE_FCC | RTYPE_CCC | 3}, \
{"$cc4", RTYPE_FCC | RTYPE_CCC | 4}, \
{"$cc5", RTYPE_FCC | RTYPE_CCC | 5}, \
{"$cc6", RTYPE_FCC | RTYPE_CCC | 6}, \
{"$cc7", RTYPE_FCC | RTYPE_CCC | 7}
#define N32N64_SYMBOLIC_REGISTER_NAMES \
{"$a4", RTYPE_GP | 8}, \
{"$a5", RTYPE_GP | 9}, \
{"$a6", RTYPE_GP | 10}, \
{"$a7", RTYPE_GP | 11}, \
{"$ta0", RTYPE_GP | 8}, /* alias for $a4 */ \
{"$ta1", RTYPE_GP | 9}, /* alias for $a5 */ \
{"$ta2", RTYPE_GP | 10}, /* alias for $a6 */ \
{"$ta3", RTYPE_GP | 11}, /* alias for $a7 */ \
{"$t0", RTYPE_GP | 12}, \
{"$t1", RTYPE_GP | 13}, \
{"$t2", RTYPE_GP | 14}, \
{"$t3", RTYPE_GP | 15}
#define O32_SYMBOLIC_REGISTER_NAMES \
{"$t0", RTYPE_GP | 8}, \
{"$t1", RTYPE_GP | 9}, \
{"$t2", RTYPE_GP | 10}, \
{"$t3", RTYPE_GP | 11}, \
{"$t4", RTYPE_GP | 12}, \
{"$t5", RTYPE_GP | 13}, \
{"$t6", RTYPE_GP | 14}, \
{"$t7", RTYPE_GP | 15}, \
{"$ta0", RTYPE_GP | 12}, /* alias for $t4 */ \
{"$ta1", RTYPE_GP | 13}, /* alias for $t5 */ \
{"$ta2", RTYPE_GP | 14}, /* alias for $t6 */ \
{"$ta3", RTYPE_GP | 15} /* alias for $t7 */
/* Remaining symbolic register names */
#define SYMBOLIC_REGISTER_NAMES \
{"$zero", RTYPE_GP | 0}, \
{"$at", RTYPE_GP | 1}, \
{"$AT", RTYPE_GP | 1}, \
{"$v0", RTYPE_GP | 2}, \
{"$v1", RTYPE_GP | 3}, \
{"$a0", RTYPE_GP | 4}, \
{"$a1", RTYPE_GP | 5}, \
{"$a2", RTYPE_GP | 6}, \
{"$a3", RTYPE_GP | 7}, \
{"$s0", RTYPE_GP | 16}, \
{"$s1", RTYPE_GP | 17}, \
{"$s2", RTYPE_GP | 18}, \
{"$s3", RTYPE_GP | 19}, \
{"$s4", RTYPE_GP | 20}, \
{"$s5", RTYPE_GP | 21}, \
{"$s6", RTYPE_GP | 22}, \
{"$s7", RTYPE_GP | 23}, \
{"$t8", RTYPE_GP | 24}, \
{"$t9", RTYPE_GP | 25}, \
{"$k0", RTYPE_GP | 26}, \
{"$kt0", RTYPE_GP | 26}, \
{"$k1", RTYPE_GP | 27}, \
{"$kt1", RTYPE_GP | 27}, \
{"$gp", RTYPE_GP | 28}, \
{"$sp", RTYPE_GP | 29}, \
{"$s8", RTYPE_GP | 30}, \
{"$fp", RTYPE_GP | 30}, \
{"$ra", RTYPE_GP | 31}
#define MIPS16_SPECIAL_REGISTER_NAMES \
{"$pc", RTYPE_PC | 0}
#define MDMX_VECTOR_REGISTER_NAMES \
/* {"$v0", RTYPE_VEC | 0}, clash with REG 2 above */ \
/* {"$v1", RTYPE_VEC | 1}, clash with REG 3 above */ \
{"$v2", RTYPE_VEC | 2}, \
{"$v3", RTYPE_VEC | 3}, \
{"$v4", RTYPE_VEC | 4}, \
{"$v5", RTYPE_VEC | 5}, \
{"$v6", RTYPE_VEC | 6}, \
{"$v7", RTYPE_VEC | 7}, \
{"$v8", RTYPE_VEC | 8}, \
{"$v9", RTYPE_VEC | 9}, \
{"$v10", RTYPE_VEC | 10}, \
{"$v11", RTYPE_VEC | 11}, \
{"$v12", RTYPE_VEC | 12}, \
{"$v13", RTYPE_VEC | 13}, \
{"$v14", RTYPE_VEC | 14}, \
{"$v15", RTYPE_VEC | 15}, \
{"$v16", RTYPE_VEC | 16}, \
{"$v17", RTYPE_VEC | 17}, \
{"$v18", RTYPE_VEC | 18}, \
{"$v19", RTYPE_VEC | 19}, \
{"$v20", RTYPE_VEC | 20}, \
{"$v21", RTYPE_VEC | 21}, \
{"$v22", RTYPE_VEC | 22}, \
{"$v23", RTYPE_VEC | 23}, \
{"$v24", RTYPE_VEC | 24}, \
{"$v25", RTYPE_VEC | 25}, \
{"$v26", RTYPE_VEC | 26}, \
{"$v27", RTYPE_VEC | 27}, \
{"$v28", RTYPE_VEC | 28}, \
{"$v29", RTYPE_VEC | 29}, \
{"$v30", RTYPE_VEC | 30}, \
{"$v31", RTYPE_VEC | 31}
#define R5900_I_NAMES \
{"$I", RTYPE_R5900_I | 0}
#define R5900_Q_NAMES \
{"$Q", RTYPE_R5900_Q | 0}
#define R5900_R_NAMES \
{"$R", RTYPE_R5900_R | 0}
#define R5900_ACC_NAMES \
{"$ACC", RTYPE_R5900_ACC | 0 }
#define MIPS_DSP_ACCUMULATOR_NAMES \
{"$ac0", RTYPE_ACC | 0}, \
{"$ac1", RTYPE_ACC | 1}, \
{"$ac2", RTYPE_ACC | 2}, \
{"$ac3", RTYPE_ACC | 3}
static const struct regname reg_names[] = {
GENERIC_REGISTER_NUMBERS,
FPU_REGISTER_NAMES,
FPU_CONDITION_CODE_NAMES,
COPROC_CONDITION_CODE_NAMES,
/* The $txx registers depends on the abi,
these will be added later into the symbol table from
one of the tables below once mips_abi is set after
parsing of arguments from the command line. */
SYMBOLIC_REGISTER_NAMES,
MIPS16_SPECIAL_REGISTER_NAMES,
MDMX_VECTOR_REGISTER_NAMES,
R5900_I_NAMES,
R5900_Q_NAMES,
R5900_R_NAMES,
R5900_ACC_NAMES,
MIPS_DSP_ACCUMULATOR_NAMES,
{0, 0}
};
static const struct regname reg_names_o32[] = {
O32_SYMBOLIC_REGISTER_NAMES,
{0, 0}
};
static const struct regname reg_names_n32n64[] = {
N32N64_SYMBOLIC_REGISTER_NAMES,
{0, 0}
};
/* Register symbols $v0 and $v1 map to GPRs 2 and 3, but they can also be
interpreted as vector registers 0 and 1. If SYMVAL is the value of one
of these register symbols, return the associated vector register,
otherwise return SYMVAL itself. */
static unsigned int
mips_prefer_vec_regno (unsigned int symval)
{
if ((symval & -2) == (RTYPE_GP | 2))
return RTYPE_VEC | (symval & 1);
return symval;
}
/* Return true if string [S, E) is a valid register name, storing its
symbol value in *SYMVAL_PTR if so. */
static bfd_boolean
mips_parse_register_1 (char *s, char *e, unsigned int *symval_ptr)
{
char save_c;
symbolS *symbol;
/* Terminate name. */
save_c = *e;
*e = '\0';
/* Look up the name. */
symbol = symbol_find (s);
*e = save_c;
if (!symbol || S_GET_SEGMENT (symbol) != reg_section)
return FALSE;
*symval_ptr = S_GET_VALUE (symbol);
return TRUE;
}
/* Return true if the string at *SPTR is a valid register name. Allow it
to have a VU0-style channel suffix of the form x?y?z?w? if CHANNELS_PTR
is nonnull.
When returning true, move *SPTR past the register, store the
register's symbol value in *SYMVAL_PTR and the channel mask in
*CHANNELS_PTR (if nonnull). The symbol value includes the register
number (RNUM_MASK) and register type (RTYPE_MASK). The channel mask
is a 4-bit value of the form XYZW and is 0 if no suffix was given. */
static bfd_boolean
mips_parse_register (char **sptr, unsigned int *symval_ptr,
unsigned int *channels_ptr)
{
char *s, *e, *m;
const char *q;
unsigned int channels, symval, bit;
/* Find end of name. */
s = e = *sptr;
if (is_name_beginner (*e))
++e;
while (is_part_of_name (*e))
++e;
channels = 0;
if (!mips_parse_register_1 (s, e, &symval))
{
if (!channels_ptr)
return FALSE;
/* Eat characters from the end of the string that are valid
channel suffixes. The preceding register must be $ACC or
end with a digit, so there is no ambiguity. */
bit = 1;
m = e;
for (q = "wzyx"; *q; q++, bit <<= 1)
if (m > s && m[-1] == *q)
{
--m;
channels |= bit;
}
if (channels == 0
|| !mips_parse_register_1 (s, m, &symval)
|| (symval & (RTYPE_VI | RTYPE_VF | RTYPE_R5900_ACC)) == 0)
return FALSE;
}
*sptr = e;
*symval_ptr = symval;
if (channels_ptr)
*channels_ptr = channels;
return TRUE;
}
/* Check if SPTR points at a valid register specifier according to TYPES.
If so, then return 1, advance S to consume the specifier and store
the register's number in REGNOP, otherwise return 0. */
static int
reg_lookup (char **s, unsigned int types, unsigned int *regnop)
{
unsigned int regno;
if (mips_parse_register (s, &regno, NULL))
{
if (types & RTYPE_VEC)
regno = mips_prefer_vec_regno (regno);
if (regno & types)
regno &= RNUM_MASK;
else
regno = ~0;
}
else
{
if (types & RWARN)
as_warn (_("unrecognized register name `%s'"), *s);
regno = ~0;
}
if (regnop)
*regnop = regno;
return regno <= RNUM_MASK;
}
/* Parse a VU0 "x?y?z?w?" channel mask at S and store the associated
mask in *CHANNELS. Return a pointer to the first unconsumed character. */
static char *
mips_parse_vu0_channels (char *s, unsigned int *channels)
{
unsigned int i;
*channels = 0;
for (i = 0; i < 4; i++)
if (*s == "xyzw"[i])
{
*channels |= 1 << (3 - i);
++s;
}
return s;
}
/* Token types for parsed operand lists. */
enum mips_operand_token_type {
/* A plain register, e.g. $f2. */
OT_REG,
/* A 4-bit XYZW channel mask. */
OT_CHANNELS,
/* An element of a vector, e.g. $v0[1]. */
OT_REG_ELEMENT,
/* A continuous range of registers, e.g. $s0-$s4. */
OT_REG_RANGE,
/* A (possibly relocated) expression. */
OT_INTEGER,
/* A floating-point value. */
OT_FLOAT,
/* A single character. This can be '(', ')' or ',', but '(' only appears
before OT_REGs. */
OT_CHAR,
/* A doubled character, either "--" or "++". */
OT_DOUBLE_CHAR,
/* The end of the operand list. */
OT_END
};
/* A parsed operand token. */
struct mips_operand_token
{
/* The type of token. */
enum mips_operand_token_type type;
union
{
/* The register symbol value for an OT_REG. */
unsigned int regno;
/* The 4-bit channel mask for an OT_CHANNEL_SUFFIX. */
unsigned int channels;
/* The register symbol value and index for an OT_REG_ELEMENT. */
struct {
unsigned int regno;
addressT index;
} reg_element;
/* The two register symbol values involved in an OT_REG_RANGE. */
struct {
unsigned int regno1;
unsigned int regno2;
} reg_range;
/* The value of an OT_INTEGER. The value is represented as an
expression and the relocation operators that were applied to
that expression. The reloc entries are BFD_RELOC_UNUSED if no
relocation operators were used. */
struct {
expressionS value;
bfd_reloc_code_real_type relocs[3];
} integer;
/* The binary data for an OT_FLOAT constant, and the number of bytes
in the constant. */
struct {
unsigned char data[8];
int length;
} flt;
/* The character represented by an OT_CHAR or OT_DOUBLE_CHAR. */
char ch;
} u;