? ".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 = 0;
+
+/* True if -mfp32 was passed. */
+static int file_mips_fp32 = 0;
+
/* 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. */
-#define HAVE_32BIT_ADDRESSES \
- (HAVE_32BIT_GPRS \
- || bfd_arch_bits_per_address (stdoutput) == 32 \
- || ! HAVE_64BIT_OBJECTS)
+#define HAVE_32BIT_ADDRESSES \
+ (HAVE_32BIT_GPRS \
+ || ((bfd_arch_bits_per_address (stdoutput) == 32 \
+ || ! HAVE_64BIT_OBJECTS) \
+ && mips_pic != EMBEDDED_PIC))
#define HAVE_64BIT_ADDRESSES (! HAVE_32BIT_ADDRESSES)
require nops to be inserted. */
#define hilo_interlocks (mips_arch == CPU_R4010 \
+ || mips_arch == CPU_SB1 \
)
/* Whether the processor uses hardware interlocks to protect reads
(co-processor) interlocks. */
/* Itbl support may require additional care here. */
#define cop_interlocks (mips_arch == CPU_R4300 \
+ || mips_arch == CPU_SB1 \
)
/* Is this a mfhi or mflo instruction? */
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));
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
as_warn (_("Could not set architecture and machine"));
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;
*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);
}
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;
}
}
lui $reg,<sym> (BFD_RELOC_HI16_S)
addiu $reg,$reg,<sym> (BFD_RELOC_LO16)
If we have an addend, we always use the latter form.
-
+
With 64bit address space and a usable $at we want
lui $reg,<sym> (BFD_RELOC_MIPS_HIGHEST)
lui $at,<sym> (BFD_RELOC_HI16_S)
daddiu $at,<sym> (BFD_RELOC_LO16)
dsll32 $reg,0
dadd $reg,$reg,$at
-
+
If $at is already in use, we use an path which is suboptimal
on superscalar processors.
lui $reg,<sym> (BFD_RELOC_MIPS_HIGHEST)
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);
}
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;
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;
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:
/* Load the address of a symbol into a register. If breg is not
zero, we then add a base register to it. */
+ if (treg == breg)
+ {
+ tempreg = AT;
+ used_at = 1;
+ }
+ else
+ {
+ tempreg = treg;
+ used_at = 0;
+ }
+
/* When generating embedded PIC code, we permit expressions of
the form
- la $4,foo-bar
+ la $treg,foo-bar
+ la $treg,foo-bar($breg)
where bar is an address in the current section. These are used
when getting the addresses of functions. We don't permit
X_add_number to be non-zero, because if the symbol is
(symbol_get_value_expression (offset_expr.X_op_symbol)
->X_add_symbol)
== now_seg)))
- && breg == 0
&& (offset_expr.X_add_number == 0
|| OUTPUT_FLAVOR == bfd_target_elf_flavour))
{
- macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
- treg, (int) BFD_RELOC_PCREL_HI16_S);
+ if (breg == 0)
+ {
+ tempreg = treg;
+ used_at = 0;
+ macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
+ tempreg, (int) BFD_RELOC_PCREL_HI16_S);
+ }
+ else
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
+ tempreg, (int) BFD_RELOC_PCREL_HI16_S);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
+ "d,v,t", tempreg, tempreg, breg);
+ }
macro_build ((char *) NULL, &icnt, &offset_expr,
HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", treg, treg, (int) BFD_RELOC_PCREL_LO16);
- return;
+ "t,r,j", treg, tempreg, (int) BFD_RELOC_PCREL_LO16);
+ if (! used_at)
+ return;
+ break;
}
if (offset_expr.X_op != O_symbol
offset_expr.X_op = O_constant;
}
- if (treg == breg)
- {
- tempreg = AT;
- used_at = 1;
- }
- else
- {
- tempreg = treg;
- used_at = 0;
- }
-
if (offset_expr.X_op == O_constant)
load_register (&icnt, tempreg, &offset_expr, dbl);
else if (mips_pic == NO_PIC)
addiu $tempreg,$tempreg,<sym> (BFD_RELOC_LO16)
If we have a constant, we need two instructions anyhow,
so we may as well always use the latter form.
-
+
With 64bit address space and a usable $at we want
lui $tempreg,<sym> (BFD_RELOC_MIPS_HIGHEST)
lui $at,<sym> (BFD_RELOC_HI16_S)
daddiu $at,<sym> (BFD_RELOC_LO16)
dsll32 $tempreg,0
dadd $tempreg,$tempreg,$at
-
+
If $at is already in use, we use an path which is suboptimal
on superscalar processors.
lui $tempreg,<sym> (BFD_RELOC_MIPS_HIGHEST)
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 (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;
}
"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", "");
else
fmt = "t,o(b)";
+ /* For embedded PIC, we allow loads where the offset is calculated
+ by subtracting a symbol in the current segment from an unknown
+ symbol, relative to a base register, e.g.:
+ <op> $treg, <sym>-<localsym>($breg)
+ This is used by the compiler for switch statements. */
+ if (mips_pic == EMBEDDED_PIC
+ && offset_expr.X_op == O_subtract
+ && (symbol_constant_p (offset_expr.X_op_symbol)
+ ? S_GET_SEGMENT (offset_expr.X_op_symbol) == now_seg
+ : (symbol_equated_p (offset_expr.X_op_symbol)
+ && (S_GET_SEGMENT
+ (symbol_get_value_expression (offset_expr.X_op_symbol)
+ ->X_add_symbol)
+ == now_seg)))
+ && breg != 0
+ && (offset_expr.X_add_number == 0
+ || OUTPUT_FLAVOR == bfd_target_elf_flavour))
+ {
+ /* For this case, we output the instructions:
+ lui $tempreg,<sym> (BFD_RELOC_PCREL_HI16_S)
+ addiu $tempreg,$tempreg,$breg
+ <op> $treg,<sym>($tempreg) (BFD_RELOC_PCREL_LO16)
+ If the relocation would fit entirely in 16 bits, it would be
+ nice to emit:
+ <op> $treg,<sym>($breg) (BFD_RELOC_PCREL_LO16)
+ instead, but that seems quite difficult. */
+ macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
+ tempreg, (int) BFD_RELOC_PCREL_HI16_S);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
+ ? "addu" : "daddu"),
+ "d,v,t", tempreg, tempreg, breg);
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt, treg,
+ (int) BFD_RELOC_PCREL_LO16, tempreg);
+ if (! used_at)
+ return;
+ break;
+ }
+
if (offset_expr.X_op != O_constant
&& offset_expr.X_op != O_symbol)
{
addu $tempreg,$tempreg,$breg
<op> $treg,<sym>($tempreg) (BFD_RELOC_LO16)
With a constant we always use the latter case.
-
+
With 64bit address space and no base register and $at usable,
we want
lui $tempreg,<sym> (BFD_RELOC_MIPS_HIGHEST)
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);
}
return;
}
-
+
if (breg == 0)
{
if ((valueT) offset_expr.X_add_number > MAX_GPREL_OFFSET
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", "");
fmt = "t,o(b)";
ldd_std:
+ /* We do _not_ bother to allow embedded PIC (symbol-local_symbol)
+ loads for the case of doing a pair of loads to simulate an 'ld'.
+ This is not currently done by the compiler, and assembly coders
+ writing embedded-pic code can cope. */
+
if (offset_expr.X_op != O_symbol
&& offset_expr.X_op != O_constant)
{
(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", "");
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 this value won't fit into a 16 bit offset, then go
find a macro that will generate the 32 bit offset
- code pattern. As a special hack, we accept the
- difference of two local symbols as a constant. This
- is required to suppose embedded PIC switches, which
- use an instruction which looks like
- lw $4,$L12-$LS12($4)
- The problem with handling this in a more general
- fashion is that the macro function doesn't expect to
- see anything which can be handled in a single
- constant instruction. */
+ code pattern. */
if (c == S_EX_NONE
&& (offset_expr.X_op != O_constant
|| offset_expr.X_add_number >= 0x8000
- || offset_expr.X_add_number < -0x8000)
- && (mips_pic != EMBEDDED_PIC
- || offset_expr.X_op != O_subtract
- || (S_GET_SEGMENT (offset_expr.X_add_symbol)
- != S_GET_SEGMENT (offset_expr.X_op_symbol))))
+ || offset_expr.X_add_number < -0x8000))
break;
if (c == S_EX_HI)
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);
*str = b;
goto percent_op;
}
- else
- /* Some other expression in the braces. */
- *len = strcspn (*str, ")") + 1;
+
+ /* Some other expression in the braces. */
+ *len = strcspn (*str, ")") + 1;
}
/* Check for percent_op. */
else if (*str[0] == '%')
/* Don't update oldstr if the last call had nested percent_op's. */
if (! oldstr)
oldstr = str;
-
+
do
{
oldc = 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);
/* The -32 and -64 options tell the assembler to output the 32
bit or the 64 bit MIPS ELF format. */
case OPTION_32:
- mips_abi = O32_ABI;
+ mips_opts.abi = O32_ABI;
break;
case OPTION_N32:
- mips_abi = N32_ABI;
+ mips_opts.abi = N32_ABI;
break;
case OPTION_64:
- 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"));
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 (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 */
}
/* 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_LO16))
return 1;
- if (HAVE_NEWABI
- && S_GET_SEGMENT (fixp->fx_addsy) == bfd_abs_section_ptr
- && (fixp->fx_r_type == BFD_RELOC_MIPS_SUB
- || fixp->fx_r_type == BFD_RELOC_HI16_S
- || fixp->fx_r_type == BFD_RELOC_LO16))
- return 1;
-
return (mips_pic == EMBEDDED_PIC
&& (fixp->fx_pcrel
|| SWITCH_TABLE (fixp)
/* 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_HI16_S
|| fixP->fx_r_type == BFD_RELOC_LO16
|| fixP->fx_r_type == BFD_RELOC_GPREL16
- || fixP->fx_r_type == BFD_RELOC_MIPS_LITERAL
+ || fixP->fx_r_type == BFD_RELOC_MIPS_LITERAL
|| fixP->fx_r_type == BFD_RELOC_GPREL32
|| fixP->fx_r_type == BFD_RELOC_64
|| fixP->fx_r_type == BFD_RELOC_CTOR
|| 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. */
{
valueT symval = S_GET_VALUE (fixP->fx_addsy);
+
value -= symval;
if (value != 0
&& ! fixP->fx_pcrel
}
#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;
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);
/* Handle the .cpreturn pseudo-op defined for NewABI PIC code. If an offset
was given in the preceeding .gpsetup, it results in:
ld $gp, offset($sp)
-
+
If a register $reg2 was given there, it results in:
daddiu $gp, $gp, $reg2
*/
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". */