? ".rodata" \
: (abort (), ""))
+/* 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 file_mips_abi = NO_ABI;
+
/* 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. */
/* Non-zero if we should not autoextend mips16 instructions.
Changed by `.set autoextend' and `.set noautoextend'. */
int noautoextend;
+ /* 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;
+ /* The ABI currently in use. This is changed by .set mipsN to loosen
+ restrictions and doesn't affect the whole file. */
+ enum mips_abi_level abi;
};
+/* True if -mgp32 was passed. */
+static int file_mips_gp32 = -1;
+
+/* True if -mfp32 was passed. */
+static int file_mips_fp32 = -1;
+
/* 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 mips16 field to
-1 to indicate that they have not been initialized. */
static struct mips_set_options mips_opts =
{
- ISA_UNKNOWN, -1, 0, 0, 0, 0, 0, 0
+ ISA_UNKNOWN, -1, 0, 0, 0, 0, 0, 0, 0, 0, NO_ABI
};
/* These variables are filled in with the masks of registers used.
are optimizing. */
static int mips_tune = CPU_UNKNOWN;
-/* The ABI to use. */
-enum mips_abi_level
-{
- NO_ABI = 0,
- O32_ABI,
- O64_ABI,
- N32_ABI,
- N64_ABI,
- EABI_ABI
-};
-
-static enum mips_abi_level mips_abi = NO_ABI;
-
/* Whether we should mark the file EABI64 or EABI32. */
static int mips_eabi64 = 0;
mips3 or greater, then mark the object file 32BITMODE. */
static int mips_32bitmode = 0;
-/* True if -mgp32 was passed. */
-static int mips_gp32 = 0;
-
-/* True if -mfp32 was passed. */
-static int mips_fp32 = 0;
-
/* Some ISA's have delay slots for instructions which read or write
from a coprocessor (eg. mips1-mips3); some don't (eg mips4).
Return true if instructions marked INSN_LOAD_COPROC_DELAY,
)
#define HAVE_32BIT_GPRS \
- (mips_gp32 \
- || mips_abi == O32_ABI \
+ (mips_opts.gp32 \
+ || mips_opts.abi == O32_ABI \
|| ! ISA_HAS_64BIT_REGS (mips_opts.isa))
#define HAVE_32BIT_FPRS \
- (mips_fp32 \
- || mips_abi == O32_ABI \
+ (mips_opts.fp32 \
+ || mips_opts.abi == O32_ABI \
|| ! ISA_HAS_64BIT_REGS (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_NEWABI (mips_opts.abi == N32_ABI || mips_opts.abi == N64_ABI)
-#define HAVE_64BIT_OBJECTS (mips_abi == N64_ABI)
+#define HAVE_64BIT_OBJECTS (mips_opts.abi == N64_ABI)
/* We can only have 64bit addresses if the object file format
supports it. */
/* Similiar 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 than GP as global pointer. */
+ 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;
+/* 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. */
static void mips16_immed PARAMS ((char *, unsigned int, int, offsetT, boolean,
boolean, boolean, unsigned long *,
boolean *, unsigned short *));
+static int my_getPercentOp PARAMS ((char **, unsigned int *, int *));
static int my_getSmallParser PARAMS ((char **, unsigned int *, int *));
static int my_getSmallExpression PARAMS ((expressionS *, char *));
static void my_getExpression PARAMS ((expressionS *, char *));
+#ifdef OBJ_ELF
static int support_64bit_objects PARAMS((void));
+#endif
static symbolS *get_symbol PARAMS ((void));
static void mips_align PARAMS ((int to, int fill, symbolS *label));
static void s_align PARAMS ((int));
static const char *mips_cpu_to_str PARAMS ((int));
static int validate_mips_insn PARAMS ((const struct mips_opcode *));
static void show PARAMS ((FILE *, char *, int *, int *));
+#ifdef OBJ_ELF
+static int mips_need_elf_addend_fixup PARAMS ((fixS *));
+#endif
/* Return values of my_getSmallExpression(). */
"Use -march instead of -mcpu."));
}
+#if 1
+ /* For backward compatibility, let -mipsN set various defaults. */
+ /* This code should go away, to be replaced with something rather more
+ draconian. Until GCC 3.1 has been released for some reasonable
+ amount of time, however, we need to support this. */
+ if (mips_opts.isa != ISA_UNKNOWN)
+ {
+ /* Translate -mipsN to the appropriate settings of file_mips_gp32
+ and file_mips_fp32. Tag binaries as using the mipsN ISA. */
+ if (file_mips_gp32 < 0)
+ {
+ if (ISA_HAS_64BIT_REGS (mips_opts.isa))
+ file_mips_gp32 = 0;
+ else
+ file_mips_gp32 = 1;
+ }
+ if (file_mips_fp32 < 0)
+ {
+ if (ISA_HAS_64BIT_REGS (mips_opts.isa))
+ file_mips_fp32 = 0;
+ else
+ file_mips_fp32 = 1;
+ }
+
+ ci = mips_cpu_info_from_isa (mips_opts.isa);
+ assert (ci != NULL);
+ /* -mipsN has higher priority than -mcpu but lower than -march. */
+ if (mips_arch == CPU_UNKNOWN)
+ mips_arch = ci->cpu;
+
+ /* Default mips_abi. */
+ if (mips_opts.abi == NO_ABI)
+ {
+ if (mips_opts.isa == ISA_MIPS1 || mips_opts.isa == ISA_MIPS2)
+ mips_opts.abi = O32_ABI;
+ else if (mips_opts.isa == ISA_MIPS3 || mips_opts.isa == ISA_MIPS4)
+ mips_opts.abi = O64_ABI;
+ }
+ }
+
+ if (mips_arch == CPU_UNKNOWN && mips_cpu != CPU_UNKNOWN)
+ {
+ ci = mips_cpu_info_from_cpu (mips_cpu);
+ assert (ci != NULL);
+ mips_arch = ci->cpu;
+ as_warn (_("The -mcpu option is deprecated. Please use -march and "
+ "-mtune instead."));
+ }
+
+ /* Set tune from -mcpu, not from -mipsN. */
+ if (mips_tune == CPU_UNKNOWN && mips_cpu != CPU_UNKNOWN)
+ {
+ ci = mips_cpu_info_from_cpu (mips_cpu);
+ assert (ci != NULL);
+ mips_tune = ci->cpu;
+ }
+
+ /* At this point, mips_arch will either be CPU_UNKNOWN if no ARCH was
+ specified on the command line, or some other value if one was.
+ Similarly, mips_opts.isa will be ISA_UNKNOWN if not specified on
+ the command line, or will be set otherwise if one was. */
+
+ if (mips_arch != CPU_UNKNOWN && mips_opts.isa != ISA_UNKNOWN)
+ /* Handled above. */;
+#else
if (mips_arch == CPU_UNKNOWN && mips_cpu != CPU_UNKNOWN)
{
ci = mips_cpu_info_from_cpu (mips_cpu);
specified on the command line, or some other value if one was.
Similarly, mips_opts.isa will be ISA_UNKNOWN if not specified on
the command line, or will be set otherwise if one was. */
+
if (mips_arch != CPU_UNKNOWN && mips_opts.isa != ISA_UNKNOWN)
{
/* We have to check if the isa is the default isa of arch. Otherwise
mips_arch = ci->cpu;
}
}
+#endif
else if (mips_arch != CPU_UNKNOWN && mips_opts.isa == ISA_UNKNOWN)
{
/* We have ARCH, we need ISA. */
to change the ISA with directives. This isn't really
the best, but then neither is basing the abi on the isa. */
if (ISA_HAS_64BIT_REGS (mips_opts.isa)
- && mips_abi == EABI_ABI)
+ && mips_opts.abi == EABI_ABI)
mips_eabi64 = 1;
/* If they asked for mips1 or mips2 and a cpu that is
if (! bfd_set_arch_mach (stdoutput, bfd_arch_mips, mips_arch))
as_warn (_("Could not set architecture and machine"));
+ if (file_mips_gp32 < 0)
+ file_mips_gp32 = 0;
+ if (file_mips_fp32 < 0)
+ file_mips_fp32 = 0;
+
file_mips_isa = mips_opts.isa;
+ file_mips_abi = mips_opts.abi;
+ mips_opts.gp32 = file_mips_gp32;
+ mips_opts.fp32 = file_mips_fp32;
op_hash = hash_new ();
else
{
if (imm_expr.X_op != O_absent)
- append_insn ((char *) NULL, &insn, &imm_expr, imm_reloc,
- imm_unmatched_hi);
+ append_insn (NULL, &insn, &imm_expr, imm_reloc, imm_unmatched_hi);
else if (offset_expr.X_op != O_absent)
- append_insn ((char *) NULL, &insn, &offset_expr, offset_reloc, false);
+ append_insn (NULL, &insn, &offset_expr, offset_reloc, false);
else
- append_insn ((char *) NULL, &insn, NULL, unused_reloc, false);
+ append_insn (NULL, &insn, NULL, unused_reloc, false);
}
}
& INSN_UNCOND_BRANCH_DELAY),
(*prev_insn_reloc_type
== BFD_RELOC_MIPS16_JMP)),
- make_expr_symbol (address_expr), (offsetT) 0,
- (char *) NULL);
+ make_expr_symbol (address_expr), 0, NULL);
}
else if (place != NULL)
f = place;
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
+ || address_expr->X_add_number > 0x7fffffc)
+ 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;
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
+ || address_expr->X_add_number > 0x7fffffc)
+ 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)
case 'j':
case 'o':
*r = (bfd_reloc_code_real_type) va_arg (args, int);
- assert (*r == BFD_RELOC_MIPS_GPREL
+ assert (*r == BFD_RELOC_GPREL16
|| *r == BFD_RELOC_MIPS_LITERAL
|| *r == BFD_RELOC_MIPS_HIGHER
|| *r == BFD_RELOC_HI16_S
*r = BFD_RELOC_UNUSED + c;
else
{
- mips16_immed ((char *) NULL, 0, c, ep->X_add_number, false,
- false, false, &insn.insn_opcode,
- &insn.use_extend, &insn.extend);
+ mips16_immed (NULL, 0, c, ep->X_add_number, false, false,
+ false, &insn.insn_opcode, &insn.use_extend,
+ &insn.extend);
ep = NULL;
*r = BFD_RELOC_UNUSED;
}
else
{
load_register (counter, AT, &imm_expr, 0);
- macro_build ((char *) NULL, counter, NULL,
+ macro_build ((char *) NULL, counter, (expressionS *) NULL,
unsignedp ? "sltu" : "slt",
"d,v,t", AT, reg, AT);
}
? 1 \
: 0)
+/* 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))
+
/* load_register()
* This routine generates the least number of instructions neccessary to load
* an absolute expression value into a register.
(int) BFD_RELOC_LO16);
return;
}
- else if ((((ep->X_add_number &~ (offsetT) 0x7fffffff) == 0
- || ((ep->X_add_number &~ (offsetT) 0x7fffffff)
- == ~ (offsetT) 0x7fffffff))
+ else if ((IS_SEXT_32BIT_NUM (ep->X_add_number)
&& (! dbl
|| ! ep->X_unsigned
|| sizeof (ep->X_add_number) > 4
if (HAVE_32BIT_GPRS)
{
- as_bad (_("Number larger than 32 bits"));
+ as_bad (_("Number (0x%lx) larger than 32 bits"),
+ (unsigned long) ep->X_add_number);
macro_build ((char *) NULL, counter, ep, "addiu", "t,r,j", reg, 0,
(int) BFD_RELOC_LO16);
return;
int shift, bit;
unsigned long hi, lo;
- if (hi32.X_add_number == 0xffffffff)
+ if (hi32.X_add_number == (offsetT) 0xffffffff)
{
if ((lo32.X_add_number & 0xffff8000) == 0xffff8000)
{
macro_build ((char *) NULL, counter, &tmp,
"ori", "t,r,i", reg, 0,
(int) BFD_RELOC_LO16);
- macro_build ((char *) NULL, counter, NULL,
+ macro_build ((char *) NULL, counter, (expressionS *) NULL,
(shift >= 32) ? "dsll32" : "dsll",
"d,w,<", reg, reg,
(shift >= 32) ? shift - 32 : shift);
if (bit != 0)
{
bit += shift;
- macro_build ((char *) NULL, counter, NULL,
+ macro_build ((char *) NULL, counter, (expressionS *) NULL,
(bit >= 32) ? "dsll32" : "dsll",
"d,w,<", reg, reg,
(bit >= 32) ? bit - 32 : bit);
}
- macro_build ((char *) NULL, counter, NULL,
+ macro_build ((char *) NULL, counter, (expressionS *) NULL,
(shift >= 32) ? "dsrl32" : "dsrl",
"d,w,<", reg, reg,
(shift >= 32) ? shift - 32 : shift);
{
if (freg != 0)
{
- macro_build ((char *) NULL, counter, NULL, "dsll32", "d,w,<", reg,
- freg, 0);
+ macro_build ((char *) NULL, counter, (expressionS *) NULL,
+ "dsll32", "d,w,<", reg, freg, 0);
freg = reg;
}
}
{
expressionS mid16;
- if ((freg == 0) && (lo32.X_add_number == 0xffffffff))
+ if ((freg == 0) && (lo32.X_add_number == (offsetT) 0xffffffff))
{
macro_build ((char *) NULL, counter, &lo32, "lui", "t,u", reg,
(int) BFD_RELOC_HI16);
- macro_build ((char *) NULL, counter, NULL, "dsrl32", "d,w,<", reg,
- reg, 0);
+ macro_build ((char *) NULL, counter, (expressionS *) NULL,
+ "dsrl32", "d,w,<", reg, reg, 0);
return;
}
if (freg != 0)
{
- macro_build ((char *) NULL, counter, NULL, "dsll", "d,w,<", reg,
- freg, 16);
+ macro_build ((char *) NULL, counter, (expressionS *) NULL, "dsll",
+ "d,w,<", reg, freg, 16);
freg = reg;
}
mid16 = lo32;
mid16.X_add_number >>= 16;
macro_build ((char *) NULL, counter, &mid16, "ori", "t,r,i", reg,
freg, (int) BFD_RELOC_LO16);
- macro_build ((char *) NULL, counter, NULL, "dsll", "d,w,<", reg,
- reg, 16);
+ macro_build ((char *) NULL, counter, (expressionS *) NULL, "dsll",
+ "d,w,<", reg, reg, 16);
freg = reg;
}
if ((lo32.X_add_number & 0xffff) != 0)
if (mips_pic == NO_PIC)
{
/* If this is a reference to a GP relative symbol, we want
- addiu $reg,$gp,<sym> (BFD_RELOC_MIPS_GPREL)
+ addiu $reg,$gp,<sym> (BFD_RELOC_GPREL16)
Otherwise we want
lui $reg,<sym> (BFD_RELOC_HI16_S)
addiu $reg,$reg,<sym> (BFD_RELOC_LO16)
dsll $reg,16
daddiu $reg,<sym> (BFD_RELOC_LO16)
*/
- if (HAVE_64BIT_ADDRESSES)
+ if (dbl)
{
p = NULL;
reg, reg, (int) BFD_RELOC_MIPS_HIGHER);
macro_build (p, counter, ep, "daddiu", "t,r,j",
AT, AT, (int) BFD_RELOC_LO16);
- macro_build (p, counter, NULL, "dsll32", "d,w,<",
- reg, reg, 0);
- macro_build (p, counter, NULL, "dadd", "d,v,t",
- reg, reg, AT);
+ macro_build (p, counter, (expressionS *) NULL, "dsll32",
+ "d,w,<", reg, reg, 0);
+ macro_build (p, counter, (expressionS *) NULL, "dadd",
+ "d,v,t", reg, reg, AT);
*used_at = 1;
}
else
reg, (int) BFD_RELOC_MIPS_HIGHEST);
macro_build (p, counter, ep, "daddiu", "t,r,j",
reg, reg, (int) BFD_RELOC_MIPS_HIGHER);
- macro_build (p, counter, NULL, "dsll", "d,w,<",
- reg, reg, 16);
+ macro_build (p, counter, (expressionS *) NULL, "dsll",
+ "d,w,<", reg, reg, 16);
macro_build (p, counter, ep, "daddiu", "t,r,j",
reg, reg, (int) BFD_RELOC_HI16_S);
- macro_build (p, counter, NULL, "dsll", "d,w,<",
- reg, reg, 16);
+ macro_build (p, counter, (expressionS *) NULL, "dsll",
+ "d,w,<", reg, reg, 16);
macro_build (p, counter, ep, "daddiu", "t,r,j",
reg, reg, (int) BFD_RELOC_LO16);
}
{
frag_grow (20);
macro_build ((char *) NULL, counter, ep,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", reg, GP, (int) BFD_RELOC_MIPS_GPREL);
+ dbl ? "daddiu" : "addiu", "t,r,j", reg, GP,
+ (int) BFD_RELOC_GPREL16);
p = frag_var (rs_machine_dependent, 8, 0,
RELAX_ENCODE (4, 8, 0, 4, 0,
mips_opts.warn_about_macros),
- ep->X_add_symbol, (offsetT) 0, (char *) NULL);
+ ep->X_add_symbol, 0, NULL);
}
macro_build_lui (p, counter, ep, reg);
if (p != NULL)
p += 4;
- macro_build (p, counter, ep,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
+ macro_build (p, counter, ep, dbl ? "daddiu" : "addiu",
"t,r,j", reg, reg, (int) BFD_RELOC_LO16);
}
}
macro_build ((char *) NULL, counter, ep, "lui", "t,u", reg,
(int) BFD_RELOC_MIPS_GOT_HI16);
macro_build ((char *) NULL, counter, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", reg, reg, GP);
- macro_build ((char *) NULL, counter, ep,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
+ dbl ? "daddu" : "addu", "d,v,t", reg, reg, GP);
+ macro_build ((char *) NULL, counter, ep, dbl ? "ld" : "lw",
"t,o(b)", reg, (int) BFD_RELOC_MIPS_GOT_LO16, reg);
p = frag_var (rs_machine_dependent, 12 + off, 0,
RELAX_ENCODE (12, 12 + off, off, 8 + off, 0,
mips_opts.warn_about_macros),
- ep->X_add_symbol, (offsetT) 0, (char *) NULL);
+ ep->X_add_symbol, 0, NULL);
if (off > 0)
{
/* We need a nop before loading from $gp. This special
macro_build (p, counter, (expressionS *) NULL, "nop", "");
p += 4;
}
- macro_build (p, counter, ep, HAVE_32BIT_ADDRESSES ? "lw" : "ld",
+ macro_build (p, counter, ep, dbl ? "ld" : "lw",
"t,o(b)", reg, (int) BFD_RELOC_MIPS_GOT16, GP);
p += 4;
macro_build (p, counter, (expressionS *) NULL, "nop", "");
p += 4;
- macro_build (p, counter, ep, HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
+ macro_build (p, counter, ep, dbl ? "daddiu" : "addiu",
"t,r,j", reg, reg, (int) BFD_RELOC_LO16);
if (ex.X_add_number != 0)
{
if (ex.X_add_number < -0x8000 || ex.X_add_number >= 0x8000)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
ex.X_op = O_constant;
- macro_build ((char *) NULL, counter, &ex,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
+ macro_build ((char *) NULL, counter, &ex, dbl ? "daddiu" : "addiu",
"t,r,j", reg, reg, (int) BFD_RELOC_LO16);
}
}
else if (mips_pic == EMBEDDED_PIC)
{
/* We always do
- addiu $reg,$gp,<sym> (BFD_RELOC_MIPS_GPREL)
+ addiu $reg,$gp,<sym> (BFD_RELOC_GPREL16)
*/
- macro_build ((char *) NULL, counter, ep,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", reg, GP, (int) BFD_RELOC_MIPS_GPREL);
+ macro_build ((char *) NULL, counter, ep, dbl ? "daddiu" : "addiu",
+ "t,r,j", reg, GP, (int) BFD_RELOC_GPREL16);
}
else
abort ();
expr1.X_add_number = 8;
macro_build ((char *) NULL, &icnt, &expr1, "bgez", "s,p", sreg);
if (dreg == sreg)
- macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "",
+ 0);
else
move_register (&icnt, dreg, sreg);
- macro_build ((char *) NULL, &icnt, NULL,
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
dbl ? "dsub" : "sub", "d,v,t", dreg, 0, sreg);
--mips_opts.noreorder;
return;
}
load_register (&icnt, AT, &imm_expr, dbl);
- macro_build ((char *) NULL, &icnt, NULL, s2, "d,v,t", treg, sreg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s2, "d,v,t",
+ treg, sreg, AT);
break;
case M_AND_I:
{
macro_build ((char *) NULL, &icnt, &imm_expr, "ori", "t,r,i",
treg, sreg, (int) BFD_RELOC_LO16);
- macro_build ((char *) NULL, &icnt, NULL, "nor", "d,v,t",
- treg, treg, 0);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nor",
+ "d,v,t", treg, treg, 0);
}
return;
}
load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build ((char *) NULL, &icnt, NULL, s2, "d,v,t", treg, sreg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s2, "d,v,t",
+ treg, sreg, AT);
break;
case M_BEQ_I:
if (treg == 0)
{
macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bgezl" : "bgez",
- "s,p", sreg);
+ likely ? "bgezl" : "bgez", "s,p", sreg);
return;
}
if (sreg == 0)
{
macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "blezl" : "blez",
- "s,p", treg);
+ likely ? "blezl" : "blez", "s,p", treg);
return;
}
- macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", AT, sreg, treg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "slt", "d,v,t",
+ AT, sreg, treg);
macro_build ((char *) NULL, &icnt, &offset_expr,
likely ? "beql" : "beq", "s,t,p", AT, 0);
break;
if (warn_nops)
as_warn (_("Branch %s is always false (nop)"),
ip->insn_mo->name);
- macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop",
+ "", 0);
}
else
{
likely ? "beql" : "beq", "s,t,p", 0, treg);
return;
}
- macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", AT, sreg,
- treg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
+ "d,v,t", AT, sreg, treg);
macro_build ((char *) NULL, &icnt, &offset_expr,
likely ? "beql" : "beq", "s,t,p", AT, 0);
break;
if (sreg == 0
|| (HAVE_32BIT_GPRS
&& imm_expr.X_op == O_constant
- && imm_expr.X_add_number == 0xffffffff))
+ && imm_expr.X_add_number == (offsetT) 0xffffffff))
goto do_false;
if (imm_expr.X_op != O_constant)
as_bad (_("Unsupported large constant"));
likely ? "bltzl" : "bltz", "s,p", treg);
return;
}
- macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", AT, treg, sreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "slt", "d,v,t",
+ AT, treg, sreg);
macro_build ((char *) NULL, &icnt, &offset_expr,
likely ? "bnel" : "bne", "s,t,p", AT, 0);
break;
}
if (sreg == 0)
goto do_false;
- macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", AT, treg,
- sreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
+ "d,v,t", AT, treg, sreg);
macro_build ((char *) NULL, &icnt, &offset_expr,
likely ? "bnel" : "bne", "s,t,p", AT, 0);
break;
likely ? "bgezl" : "bgez", "s,p", treg);
return;
}
- macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", AT, treg, sreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "slt", "d,v,t",
+ AT, treg, sreg);
macro_build ((char *) NULL, &icnt, &offset_expr,
likely ? "beql" : "beq", "s,t,p", AT, 0);
break;
}
if (sreg == 0)
goto do_true;
- macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", AT, treg,
- sreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
+ "d,v,t", AT, treg, sreg);
macro_build ((char *) NULL, &icnt, &offset_expr,
likely ? "beql" : "beq", "s,t,p", AT, 0);
break;
if (sreg == 0
|| (HAVE_32BIT_GPRS
&& imm_expr.X_op == O_constant
- && imm_expr.X_add_number == 0xffffffff))
+ && imm_expr.X_add_number == (offsetT) 0xffffffff))
goto do_true;
if (imm_expr.X_op != O_constant)
as_bad (_("Unsupported large constant"));
likely ? "bgtzl" : "bgtz", "s,p", treg);
return;
}
- macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", AT, sreg, treg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "slt", "d,v,t",
+ AT, sreg, treg);
macro_build ((char *) NULL, &icnt, &offset_expr,
likely ? "bnel" : "bne", "s,t,p", AT, 0);
break;
likely ? "bnel" : "bne", "s,t,p", 0, treg);
return;
}
- macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", AT, sreg,
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
+ "d,v,t", AT, sreg,
treg);
macro_build ((char *) NULL, &icnt, &offset_expr,
likely ? "bnel" : "bne", "s,t,p", AT, 0);
{
as_warn (_("Divide by zero."));
if (mips_trap)
- macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", 0, 0);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq",
+ "s,t", 0, 0);
else
- macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
+ "c", 7);
return;
}
mips_any_noreorder = 1;
if (mips_trap)
{
- macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", treg, 0);
- macro_build ((char *) NULL, &icnt, NULL,
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq",
+ "s,t", treg, 0);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
dbl ? "ddiv" : "div", "z,s,t", sreg, treg);
}
else
{
expr1.X_add_number = 8;
macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", treg, 0);
- macro_build ((char *) NULL, &icnt, NULL,
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
dbl ? "ddiv" : "div", "z,s,t", sreg, treg);
- macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
+ "c", 7);
}
expr1.X_add_number = -1;
macro_build ((char *) NULL, &icnt, &expr1,
expr1.X_add_number = 1;
macro_build ((char *) NULL, &icnt, &expr1, "daddiu", "t,r,j", AT, 0,
(int) BFD_RELOC_LO16);
- macro_build ((char *) NULL, &icnt, NULL, "dsll32", "d,w,<", AT, AT,
- 31);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "dsll32",
+ "d,w,<", AT, AT, 31);
}
else
{
}
if (mips_trap)
{
- macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", sreg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq",
+ "s,t", sreg, AT);
/* We want to close the noreorder block as soon as possible, so
that later insns are available for delay slot filling. */
--mips_opts.noreorder;
{
expr1.X_add_number = 8;
macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", sreg, AT);
- macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "",
+ 0);
/* We want to close the noreorder block as soon as possible, so
that later insns are available for delay slot filling. */
--mips_opts.noreorder;
- macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
+ "c", 6);
}
- macro_build ((char *) NULL, &icnt, NULL, s, "d", dreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d", dreg);
break;
case M_DIV_3I:
{
as_warn (_("Divide by zero."));
if (mips_trap)
- macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", 0, 0);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq",
+ "s,t", 0, 0);
else
- macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
+ "c", 7);
return;
}
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1)
{
if (strcmp (s2, "mflo") == 0)
{
- macro_build ((char *) NULL, &icnt, NULL, dbl ? "dneg" : "neg",
- "d,w", dreg, sreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ dbl ? "dneg" : "neg", "d,w", dreg, sreg);
}
else
move_register (&icnt, dreg, 0);
}
load_register (&icnt, AT, &imm_expr, dbl);
- macro_build ((char *) NULL, &icnt, NULL, s, "z,s,t", sreg, AT);
- macro_build ((char *) NULL, &icnt, NULL, s2, "d", dreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "z,s,t",
+ sreg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s2, "d", dreg);
break;
case M_DIVU_3:
mips_any_noreorder = 1;
if (mips_trap)
{
- macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", treg, 0);
- macro_build ((char *) NULL, &icnt, NULL, s, "z,s,t", sreg, treg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq",
+ "s,t", treg, 0);
+ macro_build ((char *) NULL, &icnt, (expressionS *) 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;
{
expr1.X_add_number = 8;
macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", treg, 0);
- macro_build ((char *) NULL, &icnt, NULL, s, "z,s,t", sreg, treg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) 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;
- macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
+ "c", 7);
}
- macro_build ((char *) NULL, &icnt, NULL, s2, "d", dreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s2, "d", dreg);
return;
case M_DLA_AB:
else if (mips_pic == NO_PIC)
{
/* If this is a reference to a GP relative symbol, we want
- addiu $tempreg,$gp,<sym> (BFD_RELOC_MIPS_GPREL)
+ addiu $tempreg,$gp,<sym> (BFD_RELOC_GPREL16)
Otherwise we want
lui $tempreg,<sym> (BFD_RELOC_HI16_S)
addiu $tempreg,$tempreg,<sym> (BFD_RELOC_LO16)
tempreg, tempreg, (int) BFD_RELOC_MIPS_HIGHER);
macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
AT, AT, (int) BFD_RELOC_LO16);
- macro_build (p, &icnt, NULL, "dsll32", "d,w,<",
- tempreg, tempreg, 0);
- macro_build (p, &icnt, NULL, "dadd", "d,v,t",
+ macro_build (p, &icnt, (expressionS *) NULL, "dsll32",
+ "d,w,<", tempreg, tempreg, 0);
+ macro_build (p, &icnt, (expressionS *) NULL, "dadd", "d,v,t",
tempreg, tempreg, AT);
used_at = 1;
}
tempreg, (int) BFD_RELOC_MIPS_HIGHEST);
macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
tempreg, tempreg, (int) BFD_RELOC_MIPS_HIGHER);
- macro_build (p, &icnt, NULL, "dsll", "d,w,<",
+ macro_build (p, &icnt, (expressionS *) NULL, "dsll", "d,w,<",
tempreg, tempreg, 16);
macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
tempreg, tempreg, (int) BFD_RELOC_HI16_S);
- macro_build (p, &icnt, NULL, "dsll", "d,w,<",
+ macro_build (p, &icnt, (expressionS *) NULL, "dsll", "d,w,<",
tempreg, tempreg, 16);
macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
tempreg, tempreg, (int) BFD_RELOC_LO16);
frag_grow (20);
macro_build ((char *) NULL, &icnt, &offset_expr,
HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", tempreg, GP, (int) BFD_RELOC_MIPS_GPREL);
+ "t,r,j", tempreg, GP, (int) BFD_RELOC_GPREL16);
p = frag_var (rs_machine_dependent, 8, 0,
RELAX_ENCODE (4, 8, 0, 4, 0,
mips_opts.warn_about_macros),
- offset_expr.X_add_symbol, (offsetT) 0,
- (char *) NULL);
+ offset_expr.X_add_symbol, 0, NULL);
}
macro_build_lui (p, &icnt, &offset_expr, tempreg);
if (p != NULL)
frag_grow (32);
if (expr1.X_add_number == 0 && tempreg == PIC_CALL_REG)
lw_reloc_type = (int) BFD_RELOC_MIPS_CALL16;
- macro_build ((char *) NULL, &icnt, &offset_expr,
- dbl ? "ld" : "lw",
+ macro_build ((char *) NULL, &icnt, &offset_expr, dbl ? "ld" : "lw",
"t,o(b)", tempreg, lw_reloc_type, GP);
if (expr1.X_add_number == 0)
{
(breg == 0
? mips_opts.warn_about_macros
: 0)),
- offset_expr.X_add_symbol, (offsetT) 0,
- (char *) NULL);
+ offset_expr.X_add_symbol, 0, NULL);
if (breg == 0)
{
macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
macro_build ((char *) NULL, &icnt, &expr1,
HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
"t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
- (void) frag_var (rs_machine_dependent, 0, 0,
- RELAX_ENCODE (0, 0, -12, -4, 0, 0),
- offset_expr.X_add_symbol, (offsetT) 0,
- (char *) NULL);
+ frag_var (rs_machine_dependent, 0, 0,
+ RELAX_ENCODE (0, 0, -12, -4, 0, 0),
+ offset_expr.X_add_symbol, 0, NULL);
}
else
{
inserting an unnecessary nop after the lw. */
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
- macro_build_lui ((char *) NULL, &icnt, &expr1, AT);
+ macro_build_lui (NULL, &icnt, &expr1, AT);
mips_optimize = hold_mips_optimize;
macro_build ((char *) NULL, &icnt, &expr1,
macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
"d,v,t", tempreg, tempreg, AT);
- (void) frag_var (rs_machine_dependent, 0, 0,
- RELAX_ENCODE (0, 0, -16 + off1, -8, 0, 0),
- offset_expr.X_add_symbol, (offsetT) 0,
- (char *) NULL);
+ frag_var (rs_machine_dependent, 0, 0,
+ RELAX_ENCODE (0, 0, -16 + off1, -8, 0, 0),
+ offset_expr.X_add_symbol, 0, NULL);
used_at = 1;
}
}
(breg == 0
? mips_opts.warn_about_macros
: 0)),
- offset_expr.X_add_symbol, (offsetT) 0,
- (char *) NULL);
+ offset_expr.X_add_symbol, 0, NULL);
}
else if (expr1.X_add_number >= -0x8000
&& expr1.X_add_number < 0x8000)
(breg == 0
? mips_opts.warn_about_macros
: 0)),
- offset_expr.X_add_symbol, (offsetT) 0,
- (char *) NULL);
+ offset_expr.X_add_symbol, 0, NULL);
}
else
{
inserting an unnecessary nop after the lw. */
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
- macro_build_lui ((char *) NULL, &icnt, &expr1, AT);
+ macro_build_lui (NULL, &icnt, &expr1, AT);
mips_optimize = hold_mips_optimize;
macro_build ((char *) NULL, &icnt, &expr1,
(breg == 0
? mips_opts.warn_about_macros
: 0)),
- offset_expr.X_add_symbol, (offsetT) 0,
- (char *) NULL);
+ offset_expr.X_add_symbol, 0, NULL);
used_at = 1;
}
else if (mips_pic == EMBEDDED_PIC)
{
/* We use
- addiu $tempreg,$gp,<sym> (BFD_RELOC_MIPS_GPREL)
+ addiu $tempreg,$gp,<sym> (BFD_RELOC_GPREL16)
*/
macro_build ((char *) NULL, &icnt, &offset_expr,
HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", tempreg, GP, (int) BFD_RELOC_MIPS_GPREL);
+ "t,r,j", tempreg, GP, (int) BFD_RELOC_GPREL16);
}
else
abort ();
as_warn (_("No .cprestore pseudo-op used in PIC code"));
else
{
+ if (! mips_frame_reg_valid)
+ {
+ as_warn (_("No .frame pseudo-op used in PIC code"));
+ /* Quiet this warning. */
+ mips_frame_reg_valid = 1;
+ }
+ if (! mips_cprestore_valid)
+ {
+ as_warn (_("No .cprestore pseudo-op used in PIC code"));
+ /* Quiet this warning. */
+ mips_cprestore_valid = 1;
+ }
expr1.X_add_number = mips_cprestore_offset;
macro_build ((char *) NULL, &icnt, &expr1,
HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)",
"nop", "");
p = frag_var (rs_machine_dependent, 4, 0,
RELAX_ENCODE (0, 4, -8, 0, 0, 0),
- offset_expr.X_add_symbol, (offsetT) 0,
- (char *) NULL);
+ offset_expr.X_add_symbol, 0, NULL);
}
else
{
p = frag_var (rs_machine_dependent, 12 + gpdel, 0,
RELAX_ENCODE (16, 12 + gpdel, gpdel, 8 + gpdel,
0, 0),
- offset_expr.X_add_symbol, (offsetT) 0,
- (char *) NULL);
+ offset_expr.X_add_symbol, 0, NULL);
if (gpdel > 0)
{
macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
as_warn (_("No .cprestore pseudo-op used in PIC code"));
else
{
+ if (! mips_frame_reg_valid)
+ {
+ as_warn (_("No .frame pseudo-op used in PIC code"));
+ /* Quiet this warning. */
+ mips_frame_reg_valid = 1;
+ }
+ if (! mips_cprestore_valid)
+ {
+ as_warn (_("No .cprestore pseudo-op used in PIC code"));
+ /* Quiet this warning. */
+ mips_cprestore_valid = 1;
+ }
if (mips_opts.noreorder)
macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
"nop", "");
{
/* If this is a reference to a GP relative symbol, and there
is no base register, we want
- <op> $treg,<sym>($gp) (BFD_RELOC_MIPS_GPREL)
+ <op> $treg,<sym>($gp) (BFD_RELOC_GPREL16)
Otherwise, if there is no base register, we want
lui $tempreg,<sym> (BFD_RELOC_HI16_S)
<op> $treg,<sym>($tempreg) (BFD_RELOC_LO16)
If we have a base register, and this is a reference to a
GP relative symbol, we want
addu $tempreg,$breg,$gp
- <op> $treg,<sym>($tempreg) (BFD_RELOC_MIPS_GPREL)
+ <op> $treg,<sym>($tempreg) (BFD_RELOC_GPREL16)
Otherwise we want
lui $tempreg,<sym> (BFD_RELOC_HI16_S)
addu $tempreg,$tempreg,$breg
dsll $tempreg,16
daddu $tempreg,$tempreg,$breg
<op> $treg,<sym>($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. This code should
+ probably attempt to generate 64-bit constants more
+ efficiently in general.
*/
- if (HAVE_64BIT_ADDRESSES)
+ if (HAVE_64BIT_ADDRESSES
+ && !(offset_expr.X_op == O_constant
+ && IS_SEXT_32BIT_NUM (offset_expr.X_add_number)))
{
p = NULL;
macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
tempreg, tempreg, (int) BFD_RELOC_MIPS_HIGHER);
if (breg != 0)
- macro_build (p, &icnt, NULL, "daddu", "d,v,t",
- AT, AT, breg);
- macro_build (p, &icnt, NULL, "dsll32", "d,w,<",
- tempreg, tempreg, 0);
- macro_build (p, &icnt, NULL, "daddu", "d,v,t",
- tempreg, tempreg, AT);
+ macro_build (p, &icnt, (expressionS *) NULL, "daddu",
+ "d,v,t", AT, AT, breg);
+ macro_build (p, &icnt, (expressionS *) NULL, "dsll32",
+ "d,w,<", tempreg, tempreg, 0);
+ macro_build (p, &icnt, (expressionS *) NULL, "daddu",
+ "d,v,t", tempreg, tempreg, AT);
macro_build (p, &icnt, &offset_expr, s,
fmt, treg, (int) BFD_RELOC_LO16, tempreg);
used_at = 1;
tempreg, (int) BFD_RELOC_MIPS_HIGHEST);
macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
tempreg, tempreg, (int) BFD_RELOC_MIPS_HIGHER);
- macro_build (p, &icnt, NULL, "dsll", "d,w,<",
- tempreg, tempreg, 16);
+ macro_build (p, &icnt, (expressionS *) NULL, "dsll",
+ "d,w,<", tempreg, tempreg, 16);
macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
tempreg, tempreg, (int) BFD_RELOC_HI16_S);
- macro_build (p, &icnt, NULL, "dsll", "d,w,<",
- tempreg, tempreg, 16);
+ macro_build (p, &icnt, (expressionS *) NULL, "dsll",
+ "d,w,<", tempreg, tempreg, 16);
if (breg != 0)
- macro_build (p, &icnt, NULL, "daddu", "d,v,t",
- tempreg, tempreg, breg);
+ macro_build (p, &icnt, (expressionS *) NULL, "daddu",
+ "d,v,t", tempreg, tempreg, breg);
macro_build (p, &icnt, &offset_expr, s,
fmt, treg, (int) BFD_RELOC_LO16, tempreg);
}
{
frag_grow (20);
macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
- treg, (int) BFD_RELOC_MIPS_GPREL, GP);
+ treg, (int) BFD_RELOC_GPREL16, GP);
p = frag_var (rs_machine_dependent, 8, 0,
RELAX_ENCODE (4, 8, 0, 4, 0,
(mips_opts.warn_about_macros
|| (used_at
&& mips_opts.noat))),
- offset_expr.X_add_symbol, (offsetT) 0,
- (char *) NULL);
+ offset_expr.X_add_symbol, 0, NULL);
used_at = 0;
}
macro_build_lui (p, &icnt, &offset_expr, tempreg);
HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
"d,v,t", tempreg, breg, GP);
macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
- treg, (int) BFD_RELOC_MIPS_GPREL, tempreg);
+ treg, (int) BFD_RELOC_GPREL16, tempreg);
p = frag_var (rs_machine_dependent, 12, 0,
RELAX_ENCODE (8, 12, 0, 8, 0, 0),
- offset_expr.X_add_symbol, (offsetT) 0,
- (char *) NULL);
+ offset_expr.X_add_symbol, 0, NULL);
}
macro_build_lui (p, &icnt, &offset_expr, tempreg);
if (p != NULL)
macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
p = frag_var (rs_machine_dependent, 4, 0,
RELAX_ENCODE (0, 4, -8, 0, 0, 0),
- offset_expr.X_add_symbol, (offsetT) 0,
- (char *) NULL);
+ offset_expr.X_add_symbol, 0, NULL);
macro_build (p, &icnt, &offset_expr,
HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
"t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
tempreg);
p = frag_var (rs_machine_dependent, 12 + gpdel, 0,
RELAX_ENCODE (12, 12 + gpdel, gpdel, 8 + gpdel, 0, 0),
- offset_expr.X_add_symbol, (offsetT) 0, (char *) NULL);
+ offset_expr.X_add_symbol, 0, NULL);
if (gpdel > 0)
{
macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
else if (mips_pic == EMBEDDED_PIC)
{
/* If there is no base register, we want
- <op> $treg,<sym>($gp) (BFD_RELOC_MIPS_GPREL)
+ <op> $treg,<sym>($gp) (BFD_RELOC_GPREL16)
If there is a base register, we want
addu $tempreg,$breg,$gp
- <op> $treg,<sym>($tempreg) (BFD_RELOC_MIPS_GPREL)
+ <op> $treg,<sym>($tempreg) (BFD_RELOC_GPREL16)
*/
assert (offset_expr.X_op == O_symbol);
if (breg == 0)
{
macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
- treg, (int) BFD_RELOC_MIPS_GPREL, GP);
+ treg, (int) BFD_RELOC_GPREL16, GP);
used_at = 0;
}
else
HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
"d,v,t", tempreg, breg, GP);
macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
- treg, (int) BFD_RELOC_MIPS_GPREL, tempreg);
+ treg, (int) BFD_RELOC_GPREL16, tempreg);
}
}
else
upper 16 bits of the address. */
if (mips_pic == NO_PIC)
{
- /* FIXME: This won't work for a 64 bit address. */
- macro_build_lui ((char *) NULL, &icnt, &offset_expr, AT);
+ macro_build_lui (NULL, &icnt, &offset_expr, AT);
}
else if (mips_pic == SVR4_PIC)
{
a single instruction. */
macro_build ((char *) NULL, &icnt, &offset_expr,
HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", AT, GP, (int) BFD_RELOC_MIPS_GPREL);
+ "t,r,j", AT, GP, (int) BFD_RELOC_GPREL16);
offset_expr.X_op = O_constant;
offset_expr.X_add_number = 0;
}
else
{
/* FIXME: This won't work for a 64 bit address. */
- macro_build_lui ((char *) NULL, &icnt, &offset_expr, AT);
+ macro_build_lui (NULL, &icnt, &offset_expr, AT);
}
if (mips_opts.isa != ISA_MIPS1)
|| offset_expr.X_op == O_constant)
{
/* If this is a reference to a GP relative symbol, we want
- <op> $treg,<sym>($gp) (BFD_RELOC_MIPS_GPREL)
- <op> $treg+1,<sym>+4($gp) (BFD_RELOC_MIPS_GPREL)
+ <op> $treg,<sym>($gp) (BFD_RELOC_GPREL16)
+ <op> $treg+1,<sym>+4($gp) (BFD_RELOC_GPREL16)
If we have a base register, we use this
addu $at,$breg,$gp
- <op> $treg,<sym>($at) (BFD_RELOC_MIPS_GPREL)
- <op> $treg+1,<sym>+4($at) (BFD_RELOC_MIPS_GPREL)
+ <op> $treg,<sym>($at) (BFD_RELOC_GPREL16)
+ <op> $treg+1,<sym>+4($at) (BFD_RELOC_GPREL16)
If this is not a GP relative symbol, we want
lui $at,<sym> (BFD_RELOC_HI16_S)
<op> $treg,<sym>($at) (BFD_RELOC_LO16)
/* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
coproc ? treg + 1 : treg,
- (int) BFD_RELOC_MIPS_GPREL, tempreg);
+ (int) BFD_RELOC_GPREL16, tempreg);
offset_expr.X_add_number += 4;
/* Set mips_optimize to 2 to avoid inserting an
/* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
coproc ? treg : treg + 1,
- (int) BFD_RELOC_MIPS_GPREL, tempreg);
+ (int) BFD_RELOC_GPREL16, tempreg);
mips_optimize = hold_mips_optimize;
p = frag_var (rs_machine_dependent, 12 + off, 0,
RELAX_ENCODE (8 + off, 12 + off, 0, 4 + off, 1,
used_at && mips_opts.noat),
- offset_expr.X_add_symbol, (offsetT) 0,
- (char *) NULL);
+ offset_expr.X_add_symbol, 0, NULL);
/* We just generated two relocs. When tc_gen_reloc
handles this case, it will skip the first reloc and
(void) frag_var (rs_machine_dependent, 0, 0,
RELAX_ENCODE (0, 0, -16 - off, -8, 1, 0),
- offset_expr.X_add_symbol, (offsetT) 0,
- (char *) NULL);
+ offset_expr.X_add_symbol, 0, NULL);
}
else if (mips_pic == SVR4_PIC)
{
p = frag_var (rs_machine_dependent, 16 + gpdel + off, 0,
RELAX_ENCODE (24 + off, 16 + gpdel + off, gpdel,
8 + gpdel + off, 1, 0),
- offset_expr.X_add_symbol, (offsetT) 0,
- (char *) NULL);
+ offset_expr.X_add_symbol, 0, NULL);
if (gpdel > 0)
{
macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
else if (mips_pic == EMBEDDED_PIC)
{
/* If there is no base register, we use
- <op> $treg,<sym>($gp) (BFD_RELOC_MIPS_GPREL)
- <op> $treg+1,<sym>+4($gp) (BFD_RELOC_MIPS_GPREL)
+ <op> $treg,<sym>($gp) (BFD_RELOC_GPREL16)
+ <op> $treg+1,<sym>+4($gp) (BFD_RELOC_GPREL16)
If we have a base register, we use
addu $at,$breg,$gp
- <op> $treg,<sym>($at) (BFD_RELOC_MIPS_GPREL)
- <op> $treg+1,<sym>+4($at) (BFD_RELOC_MIPS_GPREL)
+ <op> $treg,<sym>($at) (BFD_RELOC_GPREL16)
+ <op> $treg+1,<sym>+4($at) (BFD_RELOC_GPREL16)
*/
if (breg == 0)
{
/* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
coproc ? treg + 1 : treg,
- (int) BFD_RELOC_MIPS_GPREL, tempreg);
+ (int) BFD_RELOC_GPREL16, tempreg);
offset_expr.X_add_number += 4;
/* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
coproc ? treg : treg + 1,
- (int) BFD_RELOC_MIPS_GPREL, tempreg);
+ (int) BFD_RELOC_GPREL16, tempreg);
}
else
abort ();
case M_DMUL:
dbl = 1;
case M_MUL:
- macro_build ((char *) NULL, &icnt, NULL,
- dbl ? "dmultu" : "multu",
- "s,t", sreg, treg);
- macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ dbl ? "dmultu" : "multu", "s,t", sreg, treg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "d",
+ dreg);
return;
case M_DMUL_I:
not trying to be that fancy. GCC should do this for us
anyway. */
load_register (&icnt, AT, &imm_expr, dbl);
- macro_build ((char *) NULL, &icnt, NULL,
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
dbl ? "dmult" : "mult", "s,t", sreg, AT);
- macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "d",
+ dreg);
break;
case M_DMULO_I:
mips_any_noreorder = 1;
if (imm)
load_register (&icnt, AT, &imm_expr, dbl);
- macro_build ((char *) NULL, &icnt, NULL,
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
dbl ? "dmult" : "mult", "s,t", sreg, imm ? AT : treg);
- macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg);
- macro_build ((char *) NULL, &icnt, NULL,
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "d",
+ dreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
dbl ? "dsra32" : "sra", "d,w,<", dreg, dreg, 31);
- macro_build ((char *) NULL, &icnt, NULL, "mfhi", "d", AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mfhi", "d",
+ AT);
if (mips_trap)
- macro_build ((char *) NULL, &icnt, NULL, "tne", "s,t", dreg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "tne", "s,t",
+ dreg, AT);
else
{
expr1.X_add_number = 8;
- macro_build ((char *) NULL, &icnt, &expr1, "beq", "s,t,p", dreg, AT);
- macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);
- macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
+ macro_build ((char *) NULL, &icnt, &expr1, "beq", "s,t,p", dreg,
+ AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "",
+ 0);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
+ "c", 6);
}
--mips_opts.noreorder;
- macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "d", dreg);
break;
case M_DMULOU_I:
mips_any_noreorder = 1;
if (imm)
load_register (&icnt, AT, &imm_expr, dbl);
- macro_build ((char *) NULL, &icnt, NULL,
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
dbl ? "dmultu" : "multu",
"s,t", sreg, imm ? AT : treg);
- macro_build ((char *) NULL, &icnt, NULL, "mfhi", "d", AT);
- macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mfhi", "d",
+ AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "d",
+ dreg);
if (mips_trap)
- macro_build ((char *) NULL, &icnt, NULL, "tne", "s,t", AT, 0);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "tne", "s,t",
+ AT, 0);
else
{
expr1.X_add_number = 8;
macro_build ((char *) NULL, &icnt, &expr1, "beq", "s,t,p", AT, 0);
- macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);
- macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "",
+ 0);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
+ "c", 6);
}
--mips_opts.noreorder;
break;
case M_ROL:
- macro_build ((char *) NULL, &icnt, NULL, "subu", "d,v,t", AT, 0, treg);
- macro_build ((char *) NULL, &icnt, NULL, "srlv", "d,t,s", AT, sreg, AT);
- macro_build ((char *) NULL, &icnt, NULL, "sllv", "d,t,s", dreg, sreg,
- treg);
- macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "subu",
+ "d,v,t", AT, 0, treg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srlv",
+ "d,t,s", AT, sreg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sllv",
+ "d,t,s", dreg, sreg, treg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or",
+ "d,v,t", dreg, dreg, AT);
break;
case M_ROL_I:
if (imm_expr.X_op != O_constant)
as_bad (_("rotate count too large"));
- macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", AT, sreg,
- (int) (imm_expr.X_add_number & 0x1f));
- macro_build ((char *) NULL, &icnt, NULL, "srl", "d,w,<", dreg, sreg,
- (int) ((0 - imm_expr.X_add_number) & 0x1f));
- macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sll", "d,w,<",
+ AT, sreg, (int) (imm_expr.X_add_number & 0x1f));
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srl", "d,w,<",
+ dreg, sreg, (int) ((0 - imm_expr.X_add_number) & 0x1f));
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or", "d,v,t",
+ dreg, dreg, AT);
break;
case M_ROR:
- macro_build ((char *) NULL, &icnt, NULL, "subu", "d,v,t", AT, 0, treg);
- macro_build ((char *) NULL, &icnt, NULL, "sllv", "d,t,s", AT, sreg, AT);
- macro_build ((char *) NULL, &icnt, NULL, "srlv", "d,t,s", dreg, sreg,
- treg);
- macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "subu",
+ "d,v,t", AT, 0, treg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sllv",
+ "d,t,s", AT, sreg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srlv",
+ "d,t,s", dreg, sreg, treg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or",
+ "d,v,t", dreg, dreg, AT);
break;
case M_ROR_I:
if (imm_expr.X_op != O_constant)
as_bad (_("rotate count too large"));
- macro_build ((char *) NULL, &icnt, NULL, "srl", "d,w,<", AT, sreg,
- (int) (imm_expr.X_add_number & 0x1f));
- macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", dreg, sreg,
- (int) ((0 - imm_expr.X_add_number) & 0x1f));
- macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srl", "d,w,<",
+ AT, sreg, (int) (imm_expr.X_add_number & 0x1f));
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sll", "d,w,<",
+ dreg, sreg, (int) ((0 - imm_expr.X_add_number) & 0x1f));
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or", "d,v,t",
+ dreg, dreg, AT);
break;
case M_S_DOB:
sreg, (int) BFD_RELOC_LO16);
else
{
- macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg,
- sreg, treg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "xor",
+ "d,v,t", dreg, sreg, treg);
macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg,
dreg, (int) BFD_RELOC_LO16);
}
else
{
load_register (&icnt, AT, &imm_expr, 0);
- macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg,
- sreg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "xor",
+ "d,v,t", dreg, sreg, AT);
used_at = 1;
}
macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg, dreg,
case M_SGEU:
s = "sltu";
sge:
- macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, sreg, treg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d,v,t",
+ dreg, sreg, treg);
macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,
(int) BFD_RELOC_LO16);
return;
else
{
load_register (&icnt, AT, &imm_expr, 0);
- macro_build ((char *) NULL, &icnt, NULL,
- mask == M_SGE_I ? "slt" : "sltu",
- "d,v,t", dreg, sreg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ mask == M_SGE_I ? "slt" : "sltu", "d,v,t", dreg, sreg,
+ AT);
used_at = 1;
}
macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,
case M_SGTU:
s = "sltu";
sgt:
- macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, treg, sreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d,v,t",
+ dreg, treg, sreg);
return;
case M_SGT_I: /* sreg > I <==> I < sreg */
s = "sltu";
sgti:
load_register (&icnt, AT, &imm_expr, 0);
- macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, AT, sreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d,v,t",
+ dreg, AT, sreg);
break;
- case M_SLE: /* sreg <= treg <==> treg >= sreg <==> not (treg < sreg) */
+ case M_SLE: /* sreg <= treg <==> treg >= sreg <==> not (treg < sreg) */
s = "slt";
goto sle;
case M_SLEU:
s = "sltu";
sle:
- macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, treg, sreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d,v,t",
+ dreg, treg, sreg);
macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,
(int) BFD_RELOC_LO16);
return;
- case M_SLE_I: /* sreg <= I <==> I >= sreg <==> not (I < sreg) */
+ case M_SLE_I: /* sreg <= I <==> I >= sreg <==> not (I < sreg) */
s = "slt";
goto slei;
case M_SLEU_I:
s = "sltu";
slei:
load_register (&icnt, AT, &imm_expr, 0);
- macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, AT, sreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d,v,t",
+ dreg, AT, sreg);
macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,
(int) BFD_RELOC_LO16);
break;
return;
}
load_register (&icnt, AT, &imm_expr, 0);
- macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", dreg, sreg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "slt", "d,v,t",
+ dreg, sreg, AT);
break;
case M_SLTU_I:
return;
}
load_register (&icnt, AT, &imm_expr, 0);
- macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, sreg,
- AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
+ "d,v,t", dreg, sreg, AT);
break;
case M_SNE:
if (sreg == 0)
- macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0,
- treg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
+ "d,v,t", dreg, 0, treg);
else if (treg == 0)
- macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0,
- sreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
+ "d,v,t", dreg, 0, sreg);
else
{
- macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg,
- sreg, treg);
- macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0,
- dreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "xor",
+ "d,v,t", dreg, sreg, treg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
+ "d,v,t", dreg, 0, dreg);
}
return;
case M_SNE_I:
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
{
- macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0,
- sreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
+ "d,v,t", dreg, 0, sreg);
return;
}
if (sreg == 0)
else
{
load_register (&icnt, AT, &imm_expr, 0);
- macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg,
- sreg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "xor",
+ "d,v,t", dreg, sreg, AT);
used_at = 1;
}
- macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0, dreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
+ "d,v,t", dreg, 0, dreg);
if (used_at)
break;
return;
return;
}
load_register (&icnt, AT, &imm_expr, dbl);
- macro_build ((char *) NULL, &icnt, NULL,
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
dbl ? "dsub" : "sub", "d,v,t", dreg, sreg, AT);
break;
return;
}
load_register (&icnt, AT, &imm_expr, dbl);
- macro_build ((char *) NULL, &icnt, NULL,
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
dbl ? "dsubu" : "subu", "d,v,t", dreg, sreg, AT);
break;
s = "tne";
trap:
load_register (&icnt, AT, &imm_expr, 0);
- macro_build ((char *) NULL, &icnt, NULL, s, "s,t", sreg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "s,t", sreg,
+ AT);
break;
case M_TRUNCWS:
mips_emit_delays (true);
++mips_opts.noreorder;
mips_any_noreorder = 1;
- macro_build ((char *) NULL, &icnt, NULL, "cfc1", "t,G", treg, 31);
- macro_build ((char *) NULL, &icnt, NULL, "cfc1", "t,G", treg, 31);
- macro_build ((char *) NULL, &icnt, NULL, "nop", "");
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "cfc1", "t,G",
+ treg, 31);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "cfc1", "t,G",
+ treg, 31);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
expr1.X_add_number = 3;
macro_build ((char *) NULL, &icnt, &expr1, "ori", "t,r,i", AT, treg,
(int) BFD_RELOC_LO16);
expr1.X_add_number = 2;
macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", AT, AT,
(int) BFD_RELOC_LO16);
- macro_build ((char *) NULL, &icnt, NULL, "ctc1", "t,G", AT, 31);
- macro_build ((char *) NULL, &icnt, NULL, "nop", "");
- macro_build ((char *) NULL, &icnt, NULL,
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "ctc1", "t,G",
+ AT, 31);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
mask == M_TRUNCWD ? "cvt.w.d" : "cvt.w.s", "D,S", dreg, sreg);
- macro_build ((char *) NULL, &icnt, NULL, "ctc1", "t,G", treg, 31);
- macro_build ((char *) NULL, &icnt, NULL, "nop", "");
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "ctc1", "t,G",
+ treg, 31);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
--mips_opts.noreorder;
break;
offset_expr.X_add_number += 1;
macro_build ((char *) NULL, &icnt, &offset_expr, "lbu", "t,o(b)", AT,
(int) BFD_RELOC_LO16, breg);
- macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", treg, treg, 8);
- macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", treg, treg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sll", "d,w,<",
+ treg, treg, 8);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or", "d,v,t",
+ treg, treg, AT);
break;
case M_ULD:
expr1.X_add_number = 0;
macro_build ((char *) NULL, &icnt, &expr1, "lbu", "t,o(b)", AT,
(int) BFD_RELOC_LO16, AT);
- macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", treg,
- treg, 8);
- macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", treg,
- treg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sll", "d,w,<",
+ treg, treg, 8);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or", "d,v,t",
+ treg, treg, AT);
break;
case M_USH:
offset_expr.X_add_number += 1;
macro_build ((char *) NULL, &icnt, &offset_expr, "sb", "t,o(b)", treg,
(int) BFD_RELOC_LO16, breg);
- macro_build ((char *) NULL, &icnt, NULL, "srl", "d,w,<", AT, treg, 8);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srl", "d,w,<",
+ AT, treg, 8);
if (target_big_endian)
offset_expr.X_add_number -= 1;
else
expr1.X_add_number = 0;
macro_build ((char *) NULL, &icnt, &expr1, "sb", "t,o(b)", treg,
(int) BFD_RELOC_LO16, AT);
- macro_build ((char *) NULL, &icnt, NULL, "srl", "d,w,<", treg,
- treg, 8);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srl", "d,w,<",
+ treg, treg, 8);
if (! target_big_endian)
expr1.X_add_number = 1;
else
expr1.X_add_number = 1;
macro_build ((char *) NULL, &icnt, &expr1, "lbu", "t,o(b)", AT,
(int) BFD_RELOC_LO16, AT);
- macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", treg,
- treg, 8);
- macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", treg,
- treg, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sll", "d,w,<",
+ treg, treg, 8);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or", "d,v,t",
+ treg, treg, AT);
break;
default:
mips_emit_delays (true);
++mips_opts.noreorder;
mips_any_noreorder = 1;
- macro_build ((char *) NULL, &icnt, NULL,
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
dbl ? "ddiv" : "div",
"0,x,y", xreg, yreg);
expr1.X_add_number = 2;
macro_build ((char *) NULL, &icnt, &expr1, "bnez", "x,p", yreg);
- macro_build ((char *) NULL, &icnt, NULL, "break", "6", 7);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break", "6",
+ 7);
/* FIXME: The normal code checks for of -1 / -0x80000000 here,
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;
- macro_build ((char *) NULL, &icnt, NULL, s, "x", zreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "x", zreg);
break;
case M_DIVU_3:
mips_emit_delays (true);
++mips_opts.noreorder;
mips_any_noreorder = 1;
- macro_build ((char *) NULL, &icnt, NULL, s, "0,x,y", xreg, yreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "0,x,y",
+ xreg, yreg);
expr1.X_add_number = 2;
macro_build ((char *) NULL, &icnt, &expr1, "bnez", "x,p", yreg);
- macro_build ((char *) NULL, &icnt, NULL, "break", "6", 7);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
+ "6", 7);
--mips_opts.noreorder;
- macro_build ((char *) NULL, &icnt, NULL, s2, "x", zreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s2, "x", zreg);
break;
case M_DMUL:
dbl = 1;
case M_MUL:
- macro_build ((char *) NULL, &icnt, NULL,
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
dbl ? "dmultu" : "multu", "x,y", xreg, yreg);
- macro_build ((char *) NULL, &icnt, NULL, "mflo", "x", zreg);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "x",
+ zreg);
return;
case M_DSUBU_I:
if (imm_expr.X_op == O_constant)
imm_expr.X_add_number =
(imm_expr.X_add_number >> 16) & 0xffff;
-#ifdef OBJ_ELF
- else if (c == S_EX_HIGHEST)
- *imm_reloc = BFD_RELOC_MIPS_HIGHEST;
else if (c == S_EX_HI)
{
*imm_reloc = BFD_RELOC_HI16_S;
imm_unmatched_hi = true;
}
+#ifdef OBJ_ELF
+ else if (c == S_EX_HIGHEST)
+ *imm_reloc = BFD_RELOC_MIPS_HIGHEST;
else if (c == S_EX_GP_REL)
{
/* This occurs in NewABI only. */
&& *imm_reloc > BFD_RELOC_UNUSED
&& insn->pinfo != INSN_MACRO)
{
- mips16_immed ((char *) NULL, 0,
- *imm_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,
&ip->use_extend, &ip->extend);
const enum small_ex_type type;
} percent_op[] =
{
-#ifdef OBJ_ELF
- {"%half", S_EX_HALF},
-#endif
- {"%hi", S_EX_HI},
{"%lo", S_EX_LO},
#ifdef OBJ_ELF
- {"%gp_rel", S_EX_GP_REL},
- {"%got", S_EX_GOT},
+ {"%call_hi", S_EX_CALL_HI},
+ {"%call_lo", S_EX_CALL_LO},
{"%call16", S_EX_CALL16},
{"%got_disp", S_EX_GOT_DISP},
{"%got_page", S_EX_GOT_PAGE},
{"%got_ofst", S_EX_GOT_OFST},
{"%got_hi", S_EX_GOT_HI},
{"%got_lo", S_EX_GOT_LO},
- {"%neg", S_EX_NEG},
- {"%higher", S_EX_HIGHER},
+ {"%got", S_EX_GOT},
+ {"%gp_rel", S_EX_GP_REL},
+ {"%half", S_EX_HALF},
{"%highest", S_EX_HIGHEST},
- {"%call_hi", S_EX_CALL_HI},
- {"%call_lo", S_EX_CALL_LO}
+ {"%higher", S_EX_HIGHER},
+ {"%neg", S_EX_NEG},
#endif
+ {"%hi", S_EX_HI}
};
/* Parse small expression input. STR gets adjusted to eat up whitespace.
unsigned int *len;
int *nestlevel;
{
- int type = S_EX_NONE;
-
*len = 0;
*str += strspn (*str, " \t");
+ /* Check for expression in parentheses. */
if (**str == '(')
{
char *b = *str + 1 + strspn (*str + 1, " \t");
}
}
}
+ /* Check for percent_op (in parentheses). */
else if (b[0] == '%')
{
*str = b;
- goto percent_op;
+ return my_getPercentOp (str, len, nestlevel);
}
- /* Some other expression in the braces. */
- *len = strcspn (*str, ")") + 1;
+ /* Some other expression in the parentheses, which can contain
+ parentheses itself. Attempt to find the matching one. */
+ {
+ int pcnt = 1;
+ char *s;
+
+ *len = 1;
+ for (s = *str + 1; *s && pcnt; s++, (*len)++)
+ {
+ if (*s == '(')
+ pcnt++;
+ else if (*s == ')')
+ pcnt--;
+ }
+ }
}
- /* Check for percent_op. */
+ /* Check for percent_op (outside of parentheses). */
else if (*str[0] == '%')
- {
- char *tmp;
- unsigned int i;
+ return my_getPercentOp (str, len, nestlevel);
-percent_op:
- tmp = *str + 1;
- i = 0;
+ /* Any other expression. */
+ return S_EX_NONE;
+}
- while (ISALPHA (*tmp) || *tmp == '_')
- {
- *tmp = TOLOWER (*tmp);
- tmp++;
- }
- while (i < (sizeof (percent_op) / sizeof (struct percent_op_match)))
+static int
+my_getPercentOp (str, len, nestlevel)
+ char **str;
+ unsigned int *len;
+ int *nestlevel;
+{
+ char *tmp = *str + 1;
+ unsigned int i = 0;
+
+ while (ISALPHA (*tmp) || *tmp == '_')
+ {
+ *tmp = TOLOWER (*tmp);
+ tmp++;
+ }
+ while (i < (sizeof (percent_op) / sizeof (struct percent_op_match)))
+ {
+ if (strncmp (*str, percent_op[i].str, strlen (percent_op[i].str)))
+ i++;
+ else
{
- if (strncmp (*str, percent_op[i].str, strlen (percent_op[i].str)))
- i++;
- else
- {
- type = percent_op[i].type;
+ int type = percent_op[i].type;
- /* Only %hi and %lo are allowed for OldABI. */
- if (! HAVE_NEWABI && type != S_EX_HI && type != S_EX_LO)
- return S_EX_NONE;
+ /* Only %hi and %lo are allowed for OldABI. */
+ if (! HAVE_NEWABI && type != S_EX_HI && type != S_EX_LO)
+ return S_EX_NONE;
- *len = strlen (percent_op[i].str);
- (*nestlevel)++;
- return type;
- }
+ *len = strlen (percent_op[i].str);
+ (*nestlevel)++;
+ return type;
}
}
-
- /* Any other expression. */
return S_EX_NONE;
}
static char *oldstr = NULL;
int c = S_EX_NONE;
int oldc;
- int nest_level = 0;
+ int nestlevel = -1;
unsigned int len;
- /* Don't update oldstr if the last call had nested percent_op's. */
+ /* Don't update oldstr if the last call had nested percent_op's. We need
+ it to parse the outer ones later. */
if (! oldstr)
oldstr = str;
do
{
oldc = c;
- c = my_getSmallParser (&str, &len, &nest_level);
+ c = my_getSmallParser (&str, &len, &nestlevel);
if (c != S_EX_NONE && c != S_EX_REGISTER)
str += len;
}
while (c != S_EX_NONE && c != S_EX_REGISTER);
- /* A percent_op was encountered. */
- if (nest_level)
+ if (nestlevel >= 0)
{
- /* Don't try to get an expression if it is already blanked out. */
+ /* A percent_op was encountered. Don't try to get an expression if
+ it is already blanked out. */
if (*(str + strspn (str + 1, " )")) != ')')
{
char save;
+ /* Let my_getExpression() stop at the closing parenthesis. */
save = *(str + len);
*(str + len) = '\0';
my_getExpression (ep, str);
*(str + len) = save;
}
- if (nest_level > 1)
+ if (nestlevel > 0)
{
- /* blank out including the % sign. */
- char *p = strrchr (oldstr, '%');
- memset (p, ' ', str - p + len);
+ /* Blank out including the % sign and the proper matching
+ parenthesis. */
+ int pcnt = 1;
+ char *s = strrchr (oldstr, '%');
+ char *end;
+
+ for (end = strchr (s, '(') + 1; *end && pcnt; end++)
+ {
+ if (*end == '(')
+ pcnt++;
+ else if (*end == ')')
+ pcnt--;
+ }
+
+ memset (s, ' ', end - s);
str = oldstr;
}
else
- {
- expr_end = strchr (str, ')') + 1;
- }
+ expr_end = str + len;
+
c = oldc;
}
else if (c == S_EX_NONE)
as_fatal(_("internal error"));
}
- if (nest_level <= 1)
+ if (nestlevel <= 0)
+ /* All percent_op's have been handled. */
oldstr = NULL;
return c;
number_to_chars_littleendian (buf, val, n);
}
\f
+#ifdef OBJ_ELF
static int support_64bit_objects(void)
{
const char **list, **l;
free (list);
return (*l != NULL);
}
+#endif /* OBJ_ELF */
CONST char *md_shortopts = "nO::g::G:";
{"mips3", no_argument, NULL, OPTION_MIPS3},
#define OPTION_MIPS4 (OPTION_MD_BASE + 4)
{"mips4", no_argument, NULL, OPTION_MIPS4},
-#define OPTION_MCPU (OPTION_MD_BASE + 5)
- {"mcpu", required_argument, NULL, OPTION_MCPU},
-#define OPTION_MEMBEDDED_PIC (OPTION_MD_BASE + 6)
+#define OPTION_MIPS5 (OPTION_MD_BASE + 5)
+ {"mips5", no_argument, NULL, OPTION_MIPS5},
+#define OPTION_MIPS32 (OPTION_MD_BASE + 6)
+ {"mips32", no_argument, NULL, OPTION_MIPS32},
+#define OPTION_MIPS64 (OPTION_MD_BASE + 7)
+ {"mips64", no_argument, NULL, OPTION_MIPS64},
+#define OPTION_MEMBEDDED_PIC (OPTION_MD_BASE + 8)
{"membedded-pic", no_argument, NULL, OPTION_MEMBEDDED_PIC},
-#define OPTION_TRAP (OPTION_MD_BASE + 7)
+#define OPTION_TRAP (OPTION_MD_BASE + 9)
{"trap", no_argument, NULL, OPTION_TRAP},
{"no-break", no_argument, NULL, OPTION_TRAP},
-#define OPTION_BREAK (OPTION_MD_BASE + 8)
+#define OPTION_BREAK (OPTION_MD_BASE + 10)
{"break", no_argument, NULL, OPTION_BREAK},
{"no-trap", no_argument, NULL, OPTION_BREAK},
-#define OPTION_EB (OPTION_MD_BASE + 9)
+#define OPTION_EB (OPTION_MD_BASE + 11)
{"EB", no_argument, NULL, OPTION_EB},
-#define OPTION_EL (OPTION_MD_BASE + 10)
+#define OPTION_EL (OPTION_MD_BASE + 12)
{"EL", no_argument, NULL, OPTION_EL},
-#define OPTION_M4650 (OPTION_MD_BASE + 11)
- {"m4650", no_argument, NULL, OPTION_M4650},
-#define OPTION_NO_M4650 (OPTION_MD_BASE + 12)
- {"no-m4650", no_argument, NULL, OPTION_NO_M4650},
-#define OPTION_M4010 (OPTION_MD_BASE + 13)
- {"m4010", no_argument, NULL, OPTION_M4010},
-#define OPTION_NO_M4010 (OPTION_MD_BASE + 14)
- {"no-m4010", no_argument, NULL, OPTION_NO_M4010},
-#define OPTION_M4100 (OPTION_MD_BASE + 15)
- {"m4100", no_argument, NULL, OPTION_M4100},
-#define OPTION_NO_M4100 (OPTION_MD_BASE + 16)
- {"no-m4100", no_argument, NULL, OPTION_NO_M4100},
-#define OPTION_MIPS16 (OPTION_MD_BASE + 17)
+#define OPTION_MIPS16 (OPTION_MD_BASE + 13)
{"mips16", no_argument, NULL, OPTION_MIPS16},
-#define OPTION_NO_MIPS16 (OPTION_MD_BASE + 18)
+#define OPTION_NO_MIPS16 (OPTION_MD_BASE + 14)
{"no-mips16", no_argument, NULL, OPTION_NO_MIPS16},
-#define OPTION_M3900 (OPTION_MD_BASE + 19)
- {"m3900", no_argument, NULL, OPTION_M3900},
-#define OPTION_NO_M3900 (OPTION_MD_BASE + 20)
- {"no-m3900", no_argument, NULL, OPTION_NO_M3900},
-#define OPTION_MABI (OPTION_MD_BASE + 21)
- {"mabi", required_argument, NULL, OPTION_MABI},
-#define OPTION_M7000_HILO_FIX (OPTION_MD_BASE + 22)
+#define OPTION_M7000_HILO_FIX (OPTION_MD_BASE + 15)
{"mfix7000", no_argument, NULL, OPTION_M7000_HILO_FIX},
-#define OPTION_NO_M7000_HILO_FIX (OPTION_MD_BASE + 23)
+#define OPTION_NO_M7000_HILO_FIX (OPTION_MD_BASE + 16)
{"no-fix-7000", no_argument, NULL, OPTION_NO_M7000_HILO_FIX},
-#define OPTION_GP32 (OPTION_MD_BASE + 24)
+#define OPTION_FP32 (OPTION_MD_BASE + 17)
+ {"mfp32", no_argument, NULL, OPTION_FP32},
+#define OPTION_GP32 (OPTION_MD_BASE + 18)
{"mgp32", no_argument, NULL, OPTION_GP32},
-#define OPTION_GP64 (OPTION_MD_BASE + 25)
- {"mgp64", no_argument, NULL, OPTION_GP64},
-#define OPTION_CONSTRUCT_FLOATS (OPTION_MD_BASE + 26)
+#define OPTION_CONSTRUCT_FLOATS (OPTION_MD_BASE + 19)
{"construct-floats", no_argument, NULL, OPTION_CONSTRUCT_FLOATS},
-#define OPTION_NO_CONSTRUCT_FLOATS (OPTION_MD_BASE + 27)
+#define OPTION_NO_CONSTRUCT_FLOATS (OPTION_MD_BASE + 20)
{"no-construct-floats", no_argument, NULL, OPTION_NO_CONSTRUCT_FLOATS},
-#define OPTION_MIPS32 (OPTION_MD_BASE + 28)
- {"mips32", no_argument, NULL, OPTION_MIPS32},
-#define OPTION_MIPS5 (OPTION_MD_BASE + 29)
- {"mips5", no_argument, NULL, OPTION_MIPS5},
-#define OPTION_MIPS64 (OPTION_MD_BASE + 30)
- {"mips64", no_argument, NULL, OPTION_MIPS64},
-#define OPTION_MARCH (OPTION_MD_BASE + 31)
+#define OPTION_MARCH (OPTION_MD_BASE + 21)
{"march", required_argument, NULL, OPTION_MARCH},
-#define OPTION_MTUNE (OPTION_MD_BASE + 32)
+#define OPTION_MTUNE (OPTION_MD_BASE + 22)
{"mtune", required_argument, NULL, OPTION_MTUNE},
-#define OPTION_FP32 (OPTION_MD_BASE + 33)
- {"mfp32", no_argument, NULL, OPTION_FP32},
+#define OPTION_MCPU (OPTION_MD_BASE + 23)
+ {"mcpu", required_argument, NULL, OPTION_MCPU},
+#define OPTION_M4650 (OPTION_MD_BASE + 24)
+ {"m4650", no_argument, NULL, OPTION_M4650},
+#define OPTION_NO_M4650 (OPTION_MD_BASE + 25)
+ {"no-m4650", no_argument, NULL, OPTION_NO_M4650},
+#define OPTION_M4010 (OPTION_MD_BASE + 26)
+ {"m4010", no_argument, NULL, OPTION_M4010},
+#define OPTION_NO_M4010 (OPTION_MD_BASE + 27)
+ {"no-m4010", no_argument, NULL, OPTION_NO_M4010},
+#define OPTION_M4100 (OPTION_MD_BASE + 28)
+ {"m4100", no_argument, NULL, OPTION_M4100},
+#define OPTION_NO_M4100 (OPTION_MD_BASE + 29)
+ {"no-m4100", no_argument, NULL, OPTION_NO_M4100},
+#define OPTION_M3900 (OPTION_MD_BASE + 30)
+ {"m3900", no_argument, NULL, OPTION_M3900},
+#define OPTION_NO_M3900 (OPTION_MD_BASE + 31)
+ {"no-m3900", no_argument, NULL, OPTION_NO_M3900},
+#define OPTION_GP64 (OPTION_MD_BASE + 32)
+ {"mgp64", no_argument, NULL, OPTION_GP64},
#ifdef OBJ_ELF
-#define OPTION_ELF_BASE (OPTION_MD_BASE + 35)
+#define OPTION_ELF_BASE (OPTION_MD_BASE + 33)
#define OPTION_CALL_SHARED (OPTION_ELF_BASE + 0)
-#define OPTION_NON_SHARED (OPTION_ELF_BASE + 1)
-#define OPTION_XGOT (OPTION_ELF_BASE + 2)
-#define OPTION_32 (OPTION_ELF_BASE + 3)
-#define OPTION_N32 (OPTION_ELF_BASE + 4)
-#define OPTION_64 (OPTION_ELF_BASE + 5)
{"KPIC", no_argument, NULL, OPTION_CALL_SHARED},
{"call_shared", no_argument, NULL, OPTION_CALL_SHARED},
+#define OPTION_NON_SHARED (OPTION_ELF_BASE + 1)
{"non_shared", no_argument, NULL, OPTION_NON_SHARED},
+#define OPTION_XGOT (OPTION_ELF_BASE + 2)
{"xgot", no_argument, NULL, OPTION_XGOT},
+#define OPTION_MABI (OPTION_ELF_BASE + 3)
+ {"mabi", required_argument, NULL, OPTION_MABI},
+#define OPTION_32 (OPTION_ELF_BASE + 4)
{"32", no_argument, NULL, OPTION_32},
+#define OPTION_N32 (OPTION_ELF_BASE + 5)
{"n32", no_argument, NULL, OPTION_N32},
+#define OPTION_64 (OPTION_ELF_BASE + 6)
{"64", no_argument, NULL, OPTION_64},
-#endif
-
+#endif /* OBJ_ELF */
{NULL, no_argument, NULL, 0}
};
size_t md_longopts_size = sizeof (md_longopts);
break;
#ifdef OBJ_ELF
- /* The -32 and -64 options tell the assembler to output the 32
- bit or the 64 bit MIPS ELF format. */
+ /* The -32, -n32 and -64 options are shortcuts for -mabi=32, -mabi=n32
+ and -mabi=64. */
case OPTION_32:
- mips_abi = O32_ABI;
+ if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+ {
+ as_bad (_("-32 is supported for ELF format only"));
+ return 0;
+ }
+ mips_opts.abi = O32_ABI;
break;
case OPTION_N32:
- mips_abi = N32_ABI;
+ if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+ {
+ as_bad (_("-n32 is supported for ELF format only"));
+ return 0;
+ }
+ mips_opts.abi = N32_ABI;
break;
case OPTION_64:
- mips_abi = N64_ABI;
+ if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+ {
+ as_bad (_("-64 is supported for ELF format only"));
+ return 0;
+ }
+ mips_opts.abi = N64_ABI;
if (! support_64bit_objects())
as_fatal (_("No compiled in support for 64 bit object file format"));
break;
+#endif /* OBJ_ELF */
case OPTION_GP32:
- mips_gp32 = 1;
- if (mips_abi != O32_ABI)
- mips_abi = NO_ABI;
+ file_mips_gp32 = 1;
+ if (mips_opts.abi != O32_ABI)
+ mips_opts.abi = NO_ABI;
break;
case OPTION_GP64:
- mips_gp32 = 0;
- if (mips_abi == O32_ABI)
- mips_abi = NO_ABI;
+ file_mips_gp32 = 0;
+ if (mips_opts.abi == O32_ABI)
+ mips_opts.abi = NO_ABI;
break;
case OPTION_FP32:
- mips_fp32 = 1;
- if (mips_abi != O32_ABI)
- mips_abi = NO_ABI;
+ file_mips_fp32 = 1;
+ if (mips_opts.abi != O32_ABI)
+ mips_opts.abi = NO_ABI;
break;
+#ifdef OBJ_ELF
case OPTION_MABI:
+ if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+ {
+ as_bad (_("-mabi is supported for ELF format only"));
+ return 0;
+ }
if (strcmp (arg, "32") == 0)
- mips_abi = O32_ABI;
+ mips_opts.abi = O32_ABI;
else if (strcmp (arg, "o64") == 0)
- mips_abi = O64_ABI;
+ mips_opts.abi = O64_ABI;
else if (strcmp (arg, "n32") == 0)
- mips_abi = N32_ABI;
+ mips_opts.abi = N32_ABI;
else if (strcmp (arg, "64") == 0)
{
- mips_abi = N64_ABI;
+ mips_opts.abi = N64_ABI;
if (! support_64bit_objects())
as_fatal (_("No compiled in support for 64 bit object file "
"format"));
}
else if (strcmp (arg, "eabi") == 0)
- mips_abi = EABI_ABI;
+ mips_opts.abi = EABI_ABI;
else
- mips_abi = NO_ABI;
+ mips_opts.abi = NO_ABI;
break;
#endif /* OBJ_ELF */
-KPIC, -call_shared generate SVR4 position independent code\n\
-non_shared do not generate position independent code\n\
-xgot assume a 32 bit GOT\n\
+-mabi=ABI create ABI conformant object file for:\n"));
+
+ first = 1;
+
+ show (stream, "32", &column, &first);
+ show (stream, "o64", &column, &first);
+ show (stream, "n32", &column, &first);
+ show (stream, "64", &column, &first);
+ show (stream, "eabi", &column, &first);
+
+ fputc ('\n', stream);
+
+ fprintf (stream, _("\
-32 create o32 ABI object file (default)\n\
-n32 create n32 ABI object file\n\
-64 create 64 ABI object file\n"));
}
/* Sort any unmatched HI16_S relocs so that they immediately precede
- the corresponding LO reloc. This is called before md_apply_fix and
+ 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. */
|| fixp->fx_r_type == BFD_RELOC_PCREL_LO16));
}
+#ifdef OBJ_ELF
+static int
+mips_need_elf_addend_fixup (fixP)
+ fixS *fixP;
+{
+ return (S_GET_OTHER (fixP->fx_addsy) == STO_MIPS16
+ || ((S_IS_WEAK (fixP->fx_addsy)
+ || S_IS_EXTERN (fixP->fx_addsy))
+ && !S_IS_COMMON (fixP->fx_addsy))
+ || (symbol_used_in_reloc_p (fixP->fx_addsy)
+ && (((bfd_get_section_flags (stdoutput,
+ S_GET_SEGMENT (fixP->fx_addsy))
+ & SEC_LINK_ONCE) != 0)
+ || !strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
+ ".gnu.linkonce",
+ sizeof (".gnu.linkonce") - 1))));
+}
+#endif
+
/* Apply a fixup to the object file. */
-int
-md_apply_fix (fixP, valueP)
+void
+md_apply_fix3 (fixP, valP, seg)
fixS *fixP;
- valueT *valueP;
+ valueT * valP;
+ segT seg ATTRIBUTE_UNUSED;
{
unsigned char *buf;
long insn;
|| fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY);
- value = *valueP;
+ value = * valP;
/* If we aren't adjusting this fixup to be against the section
symbol, we need to adjust the value. */
#ifdef OBJ_ELF
if (fixP->fx_addsy != NULL && OUTPUT_FLAVOR == bfd_target_elf_flavour)
{
- if (S_GET_OTHER (fixP->fx_addsy) == STO_MIPS16
- || ((S_IS_WEAK (fixP->fx_addsy)
- || S_IS_EXTERN (fixP->fx_addsy))
- && !S_IS_COMMON (fixP->fx_addsy))
- || (symbol_used_in_reloc_p (fixP->fx_addsy)
- && (((bfd_get_section_flags (stdoutput,
- S_GET_SEGMENT (fixP->fx_addsy))
- & SEC_LINK_ONCE) != 0)
- || !strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
- ".gnu.linkonce",
- sizeof (".gnu.linkonce") - 1))))
-
+ if (mips_need_elf_addend_fixup (fixP))
{
valueT symval = S_GET_VALUE (fixP->fx_addsy);
+
value -= symval;
- if (value != 0
- && ! fixP->fx_pcrel
- && fixP->fx_r_type != BFD_RELOC_MIPS_GPREL)
+ if (value != 0 && ! fixP->fx_pcrel)
{
/* In this case, the bfd_install_relocation routine will
incorrectly add the symbol value back in. We just want
}
#endif
- fixP->fx_addnumber = value; /* Remember value for tc_gen_reloc */
+ fixP->fx_addnumber = value; /* Remember value for tc_gen_reloc. */
if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel)
fixP->fx_done = 1;
case BFD_RELOC_MIPS_JALR:
case BFD_RELOC_HI16:
case BFD_RELOC_HI16_S:
- case BFD_RELOC_MIPS_GPREL:
+ case BFD_RELOC_GPREL16:
case BFD_RELOC_MIPS_LITERAL:
case BFD_RELOC_MIPS_CALL16:
case BFD_RELOC_MIPS_GOT16:
- case BFD_RELOC_MIPS_GPREL32:
+ case BFD_RELOC_GPREL32:
case BFD_RELOC_MIPS_GOT_HI16:
case BFD_RELOC_MIPS_GOT_LO16:
case BFD_RELOC_MIPS_CALL_HI16:
default:
internalError ();
}
-
- return 1;
}
#if 0
else if (strncmp (name, "mips", 4) == 0)
{
int isa;
- static int saved_mips_gp32;
- static int saved_mips_fp32;
- static enum mips_abi_level saved_mips_abi;
- static int is_saved;
/* Permit the user to change the ISA on the fly. Needless to
say, misuse can cause serious problems. */
switch (isa)
{
case 0:
- mips_gp32 = saved_mips_gp32;
- mips_fp32 = saved_mips_fp32;
- mips_abi = saved_mips_abi;
- is_saved = 0;
+ mips_opts.gp32 = file_mips_gp32;
+ mips_opts.fp32 = file_mips_fp32;
+ mips_opts.abi = file_mips_abi;
break;
case 1:
case 2:
case 32:
- if (! is_saved)
- {
- saved_mips_gp32 = mips_gp32;
- saved_mips_fp32 = mips_fp32;
- saved_mips_abi = mips_abi;
- }
- mips_gp32 = 1;
- mips_fp32 = 1;
- is_saved = 1;
+ mips_opts.gp32 = 1;
+ mips_opts.fp32 = 1;
break;
case 3:
case 4:
case 5:
case 64:
- if (! is_saved)
- {
- saved_mips_gp32 = mips_gp32;
- saved_mips_fp32 = mips_fp32;
- saved_mips_abi = mips_abi;
- }
- mips_gp32 = 0;
- mips_fp32 = 0;
- mips_abi = NO_ABI;
- is_saved = 1;
+ /* Loosen ABI register width restriction. */
+ if (mips_opts.abi == O32_ABI)
+ mips_opts.abi = NO_ABI;
+ mips_opts.gp32 = 0;
+ mips_opts.fp32 = 0;
break;
default:
- as_bad (_("unknown ISA level"));
+ as_bad (_("unknown ISA level %s"), name + 4);
break;
}
case 5: mips_opts.isa = ISA_MIPS5; break;
case 32: mips_opts.isa = ISA_MIPS32; break;
case 64: mips_opts.isa = ISA_MIPS64; break;
- default: as_bad (_("unknown ISA level")); break;
+ default: as_bad (_("unknown ISA level %s"), name + 4); break;
}
}
else if (strcmp (name, "autoextend") == 0)
/* In ELF, this symbol is implicitly an STT_OBJECT symbol. */
symbol_get_bfdsym (ex.X_add_symbol)->flags |= BSF_OBJECT;
- macro_build_lui ((char *) NULL, &icnt, &ex, GP);
+ macro_build_lui (NULL, &icnt, &ex, GP);
macro_build ((char *) NULL, &icnt, &ex, "addiu", "t,r,j", GP, GP,
(int) BFD_RELOC_LO16);
If offset is given, this results in:
sd $gp, offset($sp)
- lui $gp, %gp_rel(%neg(%hi(label)))
- daddiu $gp, $gp, %gp_rel(%neg(%lo(label)))
+ lui $gp, %hi(%neg(%gp_rel(label)))
+ daddiu $gp, $gp, %lo(%neg(%gp_rel(label)))
addu $gp, $gp, $reg1
If $reg2 is given, this results in:
daddu $reg2, $gp, $0
- lui $gp, %gp_rel(%neg(%hi(label)))
- daddiu $gp, $gp, %gp_rel(%neg(%lo(label)))
+ lui $gp, %hi(%neg(%gp_rel(label)))
+ daddiu $gp, $gp, %lo(%neg(%gp_rel(label)))
addu $gp, $gp, $reg1
*/
static void
}
mips_cprestore_offset = get_absolute_expression ();
+ mips_cprestore_valid = 1;
ex.X_op = O_constant;
ex.X_add_symbol = NULL;
p = frag_more (4);
md_number_to_chars (p, (valueT) 0, 4);
fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, 0,
- BFD_RELOC_MIPS_GPREL32);
+ BFD_RELOC_GPREL32);
demand_empty_rest_of_line ();
}
{
if (S_IS_DEFINED (symbolP))
{
- as_bad ("Ignoring attempt to redefine symbol `%s'.",
+ as_bad ("ignoring attempt to redefine symbol %s",
S_GET_NAME (symbolP));
ignore_rest_of_line ();
return;
input_line_pointer += 2;
}
if (frame)
- mips_frame_reg = reg != 0 ? reg : SP;
+ {
+ mips_frame_reg = reg != 0 ? reg : SP;
+ mips_frame_reg_valid = 1;
+ mips_cprestore_valid = 0;
+ }
return reg;
}
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 == 0 || OUTPUT_FLAVOR == bfd_target_elf_flavour)
- reloc->addend = fixp->fx_addnumber;
else if (fixp->fx_r_type == BFD_RELOC_PCREL_LO16)
{
- /* We use a special addend for an internal RELLO reloc. */
- if (symbol_section_p (fixp->fx_addsy))
- reloc->addend = reloc->address - S_GET_VALUE (fixp->fx_subsy);
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
+ reloc->addend = fixp->fx_addnumber;
else
- reloc->addend = fixp->fx_addnumber + reloc->address;
+ {
+ /* We use a special addend for an internal RELLO reloc. */
+ if (symbol_section_p (fixp->fx_addsy))
+ reloc->addend = reloc->address - S_GET_VALUE (fixp->fx_subsy);
+ else
+ reloc->addend = fixp->fx_addnumber + reloc->address;
+ }
}
else if (fixp->fx_r_type == BFD_RELOC_PCREL_HI16_S)
{
assert (fixp->fx_next != NULL
&& fixp->fx_next->fx_r_type == BFD_RELOC_PCREL_LO16);
- /* We use a special addend for an internal RELHI reloc. The
- reloc is relative to the RELLO; adjust the addend
+
+ /* The reloc is relative to the RELLO; adjust the addend
accordingly. */
- if (symbol_section_p (fixp->fx_addsy))
- reloc->addend = (fixp->fx_next->fx_frag->fr_address
- + fixp->fx_next->fx_where
- - S_GET_VALUE (fixp->fx_subsy));
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
+ reloc->addend = fixp->fx_next->fx_addnumber;
else
- reloc->addend = (fixp->fx_addnumber
- + fixp->fx_next->fx_frag->fr_address
- + fixp->fx_next->fx_where);
+ {
+ /* We use a special addend for an internal RELHI reloc. */
+ if (symbol_section_p (fixp->fx_addsy))
+ reloc->addend = (fixp->fx_next->fx_frag->fr_address
+ + fixp->fx_next->fx_where
+ - S_GET_VALUE (fixp->fx_subsy));
+ else
+ reloc->addend = (fixp->fx_addnumber
+ + fixp->fx_next->fx_frag->fr_address
+ + fixp->fx_next->fx_where);
+ }
}
+ else if (fixp->fx_pcrel == 0 || OUTPUT_FLAVOR == bfd_target_elf_flavour)
+ reloc->addend = fixp->fx_addnumber;
else
{
if (OUTPUT_FLAVOR != bfd_target_aout_flavour)
/* If this is a variant frag, we may need to adjust the existing
reloc and generate a new one. */
if (fixp->fx_frag->fr_opcode != NULL
- && (fixp->fx_r_type == BFD_RELOC_MIPS_GPREL
+ && (fixp->fx_r_type == BFD_RELOC_GPREL16
|| fixp->fx_r_type == BFD_RELOC_MIPS_GOT16
|| fixp->fx_r_type == BFD_RELOC_MIPS_CALL16
|| fixp->fx_r_type == BFD_RELOC_MIPS_GOT_HI16
if (fixp->fx_next != NULL
&& fixp->fx_frag == fixp->fx_next->fx_frag)
{
- assert ((fixp->fx_r_type == BFD_RELOC_MIPS_GPREL
- && fixp->fx_next->fx_r_type == BFD_RELOC_MIPS_GPREL)
+ assert ((fixp->fx_r_type == BFD_RELOC_GPREL16
+ && fixp->fx_next->fx_r_type == BFD_RELOC_GPREL16)
|| (fixp->fx_r_type == BFD_RELOC_MIPS_GOT_HI16
&& (fixp->fx_next->fx_r_type
== BFD_RELOC_MIPS_GOT_LO16))
if (mips_pic == NO_PIC)
{
- assert (fixp->fx_r_type == BFD_RELOC_MIPS_GPREL);
+ assert (fixp->fx_r_type == BFD_RELOC_GPREL16);
fixp->fx_r_type = BFD_RELOC_HI16_S;
}
else if (mips_pic == SVR4_PIC)
}
}
+#ifdef OBJ_ELF
+ /* md_apply_fix3 has a double-subtraction hack to get
+ bfd_install_relocation to behave nicely. GPREL relocations are
+ handled correctly without this hack, so undo it here. We can't
+ stop md_apply_fix3 from subtracting twice in the first place since
+ the fake addend is required for variant frags above. */
+ if (fixp->fx_addsy != NULL && OUTPUT_FLAVOR == bfd_target_elf_flavour
+ && code == BFD_RELOC_GPREL16
+ && reloc->addend != 0
+ && mips_need_elf_addend_fixup (fixp))
+ reloc->addend += S_GET_VALUE (fixp->fx_addsy);
+#endif
+
/* 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 (! RELAX_MIPS16_P (fragp->fr_subtype))
return 0;
- if (mips16_extended_frag (fragp, (asection *) NULL, stretch))
+ if (mips16_extended_frag (fragp, NULL, stretch))
{
if (RELAX_MIPS16_EXTENDED (fragp->fr_subtype))
return 0;
elf_elfheader (stdoutput)->e_flags |= EF_MIPS_PIC;
/* Set the MIPS ELF ABI flags. */
- if (mips_abi == NO_ABI)
+ if (file_mips_abi == NO_ABI)
;
- else if (mips_abi == O32_ABI)
+ else if (file_mips_abi == O32_ABI)
elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_O32;
- else if (mips_abi == O64_ABI)
+ else if (file_mips_abi == O64_ABI)
elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_O64;
- else if (mips_abi == EABI_ABI)
+ else if (file_mips_abi == EABI_ABI)
{
if (mips_eabi64)
elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_EABI64;
else
elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_EABI32;
}
- else if (mips_abi == N32_ABI)
+ else if (file_mips_abi == N32_ABI)
elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ABI2;
/* Nothing to do for "64". */
negative = 1;
}
if (!ISDIGIT (*input_line_pointer))
- as_bad (_("Expected simple number."));
+ as_bad (_("expected simple number"));
if (input_line_pointer[0] == '0')
{
if (input_line_pointer[1] == 'x')
{
printf (_(" *input_line_pointer == '%c' 0x%02x\n"),
*input_line_pointer, *input_line_pointer);
- as_warn (_("Invalid number"));
+ as_warn (_("invalid number"));
return -1;
}
while (ISDIGIT (*input_line_pointer))
symbolS *p;
int maybe_text;
+ /* Following functions need their own .frame and .cprestore directives. */
+ mips_frame_reg_valid = 0;
+ mips_cprestore_valid = 0;
+
if (!is_end_of_line[(unsigned char) *input_line_pointer])
{
p = get_symbol ();
if (!aent)
{
+ /* This function needs its own .frame and .cprestore directives. */
+ mips_frame_reg_valid = 0;
+ mips_cprestore_valid = 0;
+
cur_proc_ptr = &cur_proc;
memset (cur_proc_ptr, '\0', sizeof (procS));