static long prev_insn_where;
/* The reloc type for the previous instruction, if any. */
-static bfd_reloc_code_real_type prev_insn_reloc_type;
+static bfd_reloc_code_real_type prev_insn_reloc_type[3];
/* The reloc for the previous instruction, if any. */
-static fixS *prev_insn_fixp;
+static fixS *prev_insn_fixp[3];
/* Non-zero if the previous instruction was in a delay slot. */
static int prev_insn_is_delay_slot;
static void append_insn PARAMS ((char *place,
struct mips_cl_insn * ip,
expressionS * p,
- bfd_reloc_code_real_type r,
+ bfd_reloc_code_real_type *r,
boolean));
static void mips_no_prev_insn PARAMS ((int));
static void mips_emit_delays PARAMS ((boolean));
/* Relocs associated with imm_expr and offset_expr. */
-static bfd_reloc_code_real_type imm_reloc;
-static bfd_reloc_code_real_type offset_reloc;
+static bfd_reloc_code_real_type imm_reloc[3]
+ = {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
+static bfd_reloc_code_real_type offset_reloc[3]
+ = {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
/* This is set by mips_ip if imm_reloc is an unmatched HI16_S reloc. */
char *str;
{
struct mips_cl_insn insn;
+ bfd_reloc_code_real_type unused_reloc[3]
+ = {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
imm_expr.X_op = O_absent;
- imm_reloc = BFD_RELOC_UNUSED;
imm_unmatched_hi = false;
offset_expr.X_op = O_absent;
- offset_reloc = BFD_RELOC_UNUSED;
+ imm_reloc[0] = BFD_RELOC_UNUSED;
+ imm_reloc[1] = BFD_RELOC_UNUSED;
+ imm_reloc[2] = BFD_RELOC_UNUSED;
+ offset_reloc[0] = BFD_RELOC_UNUSED;
+ offset_reloc[1] = BFD_RELOC_UNUSED;
+ offset_reloc[2] = BFD_RELOC_UNUSED;
if (mips_opts.mips16)
mips16_ip (str, &insn);
else if (offset_expr.X_op != O_absent)
append_insn ((char *) NULL, &insn, &offset_expr, offset_reloc, false);
else
- append_insn ((char *) NULL, &insn, NULL, BFD_RELOC_UNUSED, false);
+ append_insn ((char *) NULL, &insn, NULL, unused_reloc, false);
}
}
char *place;
struct mips_cl_insn *ip;
expressionS *address_expr;
- bfd_reloc_code_real_type reloc_type;
+ bfd_reloc_code_real_type *reloc_type;
boolean unmatched_hi;
{
register unsigned long prev_pinfo, pinfo;
char *f;
- fixS *fixp;
+ fixS *fixp[3];
int nops = 0;
/* Mark instruction labels in mips16 mode. */
}
}
- if (reloc_type > BFD_RELOC_UNUSED)
+ if (*reloc_type > BFD_RELOC_UNUSED)
{
/* We need to set up a variant frag. */
assert (mips_opts.mips16 && address_expr != NULL);
f = frag_var (rs_machine_dependent, 4, 0,
- RELAX_MIPS16_ENCODE (reloc_type - BFD_RELOC_UNUSED,
+ RELAX_MIPS16_ENCODE (*reloc_type - BFD_RELOC_UNUSED,
mips16_small, mips16_ext,
(prev_pinfo
& INSN_UNCOND_BRANCH_DELAY),
- (prev_insn_reloc_type
+ (*prev_insn_reloc_type
== BFD_RELOC_MIPS16_JMP)),
make_expr_symbol (address_expr), (offsetT) 0,
(char *) NULL);
f = place;
else if (mips_opts.mips16
&& ! ip->use_extend
- && reloc_type != BFD_RELOC_MIPS16_JMP)
+ && *reloc_type != BFD_RELOC_MIPS16_JMP)
{
/* Make sure there is enough room to swap this instruction with
a following jump instruction. */
f = frag_more (4);
}
- fixp = NULL;
- if (address_expr != NULL && reloc_type < BFD_RELOC_UNUSED)
+ fixp[0] = fixp[1] = fixp[2] = NULL;
+ if (address_expr != NULL && *reloc_type < BFD_RELOC_UNUSED)
{
if (address_expr->X_op == O_constant)
{
- switch (reloc_type)
+ unsigned long tmp;
+
+ switch (*reloc_type)
{
case BFD_RELOC_32:
ip->insn_opcode |= address_expr->X_add_number;
break;
+ case BFD_RELOC_MIPS_HIGHEST:
+ tmp = (address_expr->X_add_number + 0x800080008000) >> 16;
+ tmp >>= 16;
+ ip->insn_opcode |= (tmp >> 16) & 0xffff;
+ break;
+
+ case BFD_RELOC_MIPS_HIGHER:
+ tmp = (address_expr->X_add_number + 0x80008000) >> 16;
+ ip->insn_opcode |= (tmp >> 16) & 0xffff;
+ break;
+
+ case BFD_RELOC_HI16_S:
+ ip->insn_opcode |= ((address_expr->X_add_number + 0x8000)
+ >> 16) & 0xffff;
+ break;
+
+ case BFD_RELOC_HI16:
+ ip->insn_opcode |= (address_expr->X_add_number >> 16) & 0xffff;
+ break;
+
case BFD_RELOC_LO16:
ip->insn_opcode |= address_expr->X_add_number & 0xffff;
break;
else
{
need_reloc:
- /* Don't generate a reloc if we are writing into a variant
- frag. */
+ /* Don't generate a reloc if we are writing into a variant frag. */
if (place == NULL)
{
- fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
- address_expr,
- (reloc_type == BFD_RELOC_16_PCREL
- || reloc_type == BFD_RELOC_16_PCREL_S2),
- reloc_type);
+ fixp[0] = fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
+ address_expr,
+ (*reloc_type == BFD_RELOC_16_PCREL
+ || *reloc_type == BFD_RELOC_16_PCREL_S2),
+ reloc_type[0]);
+
+ /* These relocations can have a addend that won't fit in
+ 4 octets for 64bit assembly. */
+ if (HAVE_64BIT_GPRS &&
+ (*reloc_type == BFD_RELOC_16
+ || *reloc_type == BFD_RELOC_32
+ || *reloc_type == BFD_RELOC_MIPS_JMP
+ || *reloc_type == BFD_RELOC_HI16_S
+ || *reloc_type == BFD_RELOC_LO16
+ || *reloc_type == BFD_RELOC_GPREL16
+ || *reloc_type == BFD_RELOC_MIPS_LITERAL
+ || *reloc_type == BFD_RELOC_GPREL32
+ || *reloc_type == BFD_RELOC_64
+ || *reloc_type == BFD_RELOC_CTOR
+ || *reloc_type == BFD_RELOC_MIPS_SUB
+ || *reloc_type == BFD_RELOC_MIPS_HIGHEST
+ || *reloc_type == BFD_RELOC_MIPS_HIGHER
+ || *reloc_type == BFD_RELOC_MIPS_SCN_DISP
+ || *reloc_type == BFD_RELOC_MIPS_REL16
+ || *reloc_type == BFD_RELOC_MIPS_RELGOT))
+ fixp[0]->fx_no_overflow = 1;
+
if (unmatched_hi)
{
struct mips_hi_fixup *hi_fixup;
- assert (reloc_type == BFD_RELOC_HI16_S);
+ assert (*reloc_type == BFD_RELOC_HI16_S);
hi_fixup = ((struct mips_hi_fixup *)
xmalloc (sizeof (struct mips_hi_fixup)));
- hi_fixup->fixp = fixp;
+ hi_fixup->fixp = fixp[0];
hi_fixup->seg = now_seg;
hi_fixup->next = mips_hi_fixup_list;
mips_hi_fixup_list = hi_fixup;
}
+
+ if (reloc_type[1] != BFD_RELOC_UNUSED)
+ {
+ /* FIXME: This symbol can be one of
+ RSS_UNDEF, RSS_GP, RSS_GP0, RSS_LOC. */
+ address_expr->X_op = O_absent;
+ address_expr->X_add_symbol = 0;
+ address_expr->X_add_number = 0;
+
+ fixp[1] = fix_new_exp (frag_now, f - frag_now->fr_literal,
+ 4, address_expr, false,
+ reloc_type[1]);
+
+ /* These relocations can have a addend that won't fit in
+ 4 octets for 64bit assembly. */
+ if (HAVE_64BIT_GPRS &&
+ (*reloc_type == BFD_RELOC_16
+ || *reloc_type == BFD_RELOC_32
+ || *reloc_type == BFD_RELOC_MIPS_JMP
+ || *reloc_type == BFD_RELOC_HI16_S
+ || *reloc_type == BFD_RELOC_LO16
+ || *reloc_type == BFD_RELOC_GPREL16
+ || *reloc_type == BFD_RELOC_MIPS_LITERAL
+ || *reloc_type == BFD_RELOC_GPREL32
+ || *reloc_type == BFD_RELOC_64
+ || *reloc_type == BFD_RELOC_CTOR
+ || *reloc_type == BFD_RELOC_MIPS_SUB
+ || *reloc_type == BFD_RELOC_MIPS_HIGHEST
+ || *reloc_type == BFD_RELOC_MIPS_HIGHER
+ || *reloc_type == BFD_RELOC_MIPS_SCN_DISP
+ || *reloc_type == BFD_RELOC_MIPS_REL16
+ || *reloc_type == BFD_RELOC_MIPS_RELGOT))
+ fixp[1]->fx_no_overflow = 1;
+
+ if (reloc_type[2] != BFD_RELOC_UNUSED)
+ {
+ address_expr->X_op = O_absent;
+ address_expr->X_add_symbol = 0;
+ address_expr->X_add_number = 0;
+
+ fixp[2] = fix_new_exp (frag_now,
+ f - frag_now->fr_literal, 4,
+ address_expr, false,
+ reloc_type[2]);
+
+ /* These relocations can have a addend that won't fit in
+ 4 octets for 64bit assembly. */
+ if (HAVE_64BIT_GPRS &&
+ (*reloc_type == BFD_RELOC_16
+ || *reloc_type == BFD_RELOC_32
+ || *reloc_type == BFD_RELOC_MIPS_JMP
+ || *reloc_type == BFD_RELOC_HI16_S
+ || *reloc_type == BFD_RELOC_LO16
+ || *reloc_type == BFD_RELOC_GPREL16
+ || *reloc_type == BFD_RELOC_MIPS_LITERAL
+ || *reloc_type == BFD_RELOC_GPREL32
+ || *reloc_type == BFD_RELOC_64
+ || *reloc_type == BFD_RELOC_CTOR
+ || *reloc_type == BFD_RELOC_MIPS_SUB
+ || *reloc_type == BFD_RELOC_MIPS_HIGHEST
+ || *reloc_type == BFD_RELOC_MIPS_HIGHER
+ || *reloc_type == BFD_RELOC_MIPS_SCN_DISP
+ || *reloc_type == BFD_RELOC_MIPS_REL16
+ || *reloc_type == BFD_RELOC_MIPS_RELGOT))
+ fixp[2]->fx_no_overflow = 1;
+ }
+ }
}
}
}
if (! mips_opts.mips16)
md_number_to_chars (f, ip->insn_opcode, 4);
- else if (reloc_type == BFD_RELOC_MIPS16_JMP)
+ else if (*reloc_type == BFD_RELOC_MIPS16_JMP)
{
md_number_to_chars (f, ip->insn_opcode >> 16, 2);
md_number_to_chars (f + 2, ip->insn_opcode & 0xffff, 2);
/* If the previous instruction had a fixup in mips16
mode, we can not swap. This normally means that the
previous instruction was a 4 byte branch anyhow. */
- || (mips_opts.mips16 && prev_insn_fixp)
+ || (mips_opts.mips16 && prev_insn_fixp[0])
/* If the previous instruction is a sync, sync.l, or
sync.p, we can not swap. */
|| (prev_pinfo & INSN_SYNC))
memcpy (temp, prev_f, 4);
memcpy (prev_f, f, 4);
memcpy (f, temp, 4);
- if (prev_insn_fixp)
+ if (prev_insn_fixp[0])
+ {
+ prev_insn_fixp[0]->fx_frag = frag_now;
+ prev_insn_fixp[0]->fx_where = f - frag_now->fr_literal;
+ }
+ if (prev_insn_fixp[1])
+ {
+ prev_insn_fixp[1]->fx_frag = frag_now;
+ prev_insn_fixp[1]->fx_where = f - frag_now->fr_literal;
+ }
+ if (prev_insn_fixp[2])
{
- prev_insn_fixp->fx_frag = frag_now;
- prev_insn_fixp->fx_where = f - frag_now->fr_literal;
+ prev_insn_fixp[2]->fx_frag = frag_now;
+ prev_insn_fixp[2]->fx_where = f - frag_now->fr_literal;
}
- if (fixp)
+ if (fixp[0])
{
- fixp->fx_frag = prev_insn_frag;
- fixp->fx_where = prev_insn_where;
+ fixp[0]->fx_frag = prev_insn_frag;
+ fixp[0]->fx_where = prev_insn_where;
+ }
+ if (fixp[1])
+ {
+ fixp[1]->fx_frag = prev_insn_frag;
+ fixp[1]->fx_where = prev_insn_where;
+ }
+ if (fixp[2])
+ {
+ fixp[2]->fx_frag = prev_insn_frag;
+ fixp[2]->fx_where = prev_insn_where;
}
}
else
char *prev_f;
char temp[2];
- assert (prev_insn_fixp == NULL);
+ assert (prev_insn_fixp[0] == NULL);
+ assert (prev_insn_fixp[1] == NULL);
+ assert (prev_insn_fixp[2] == NULL);
prev_f = prev_insn_frag->fr_literal + prev_insn_where;
memcpy (temp, prev_f, 2);
memcpy (prev_f, f, 2);
- if (reloc_type != BFD_RELOC_MIPS16_JMP)
+ if (*reloc_type != BFD_RELOC_MIPS16_JMP)
{
- assert (reloc_type == BFD_RELOC_UNUSED);
+ assert (*reloc_type == BFD_RELOC_UNUSED);
memcpy (f, temp, 2);
}
else
memcpy (f, f + 2, 2);
memcpy (f + 2, temp, 2);
}
- if (fixp)
+ if (fixp[0])
+ {
+ fixp[0]->fx_frag = prev_insn_frag;
+ fixp[0]->fx_where = prev_insn_where;
+ }
+ if (fixp[1])
+ {
+ fixp[1]->fx_frag = prev_insn_frag;
+ fixp[1]->fx_where = prev_insn_where;
+ }
+ if (fixp[2])
{
- fixp->fx_frag = prev_insn_frag;
- fixp->fx_where = prev_insn_where;
+ fixp[2]->fx_frag = prev_insn_frag;
+ fixp[2]->fx_where = prev_insn_where;
}
}
prev_insn.insn_mo = &dummy_opcode;
}
- prev_insn_fixp = NULL;
- prev_insn_reloc_type = BFD_RELOC_UNUSED;
+ prev_insn_fixp[0] = NULL;
+ prev_insn_fixp[1] = NULL;
+ prev_insn_fixp[2] = NULL;
+ prev_insn_reloc_type[0] = BFD_RELOC_UNUSED;
+ prev_insn_reloc_type[1] = BFD_RELOC_UNUSED;
+ prev_insn_reloc_type[2] = BFD_RELOC_UNUSED;
prev_insn_extended = 0;
}
else if (pinfo & INSN_COND_BRANCH_LIKELY)
/* Update the previous insn information. */
prev_prev_insn = *ip;
prev_insn.insn_mo = &dummy_opcode;
- prev_insn_fixp = NULL;
- prev_insn_reloc_type = BFD_RELOC_UNUSED;
+ prev_insn_fixp[0] = NULL;
+ prev_insn_fixp[1] = NULL;
+ prev_insn_fixp[2] = NULL;
+ prev_insn_reloc_type[0] = BFD_RELOC_UNUSED;
+ prev_insn_reloc_type[1] = BFD_RELOC_UNUSED;
+ prev_insn_reloc_type[2] = BFD_RELOC_UNUSED;
prev_insn_extended = 0;
}
else
is not in a delay slot. */
prev_insn_is_delay_slot = 0;
- prev_insn_fixp = fixp;
- prev_insn_reloc_type = reloc_type;
+ prev_insn_fixp[0] = fixp[0];
+ prev_insn_fixp[1] = fixp[1];
+ prev_insn_fixp[2] = fixp[2];
+ prev_insn_reloc_type[0] = reloc_type[0];
+ prev_insn_reloc_type[1] = reloc_type[1];
+ prev_insn_reloc_type[2] = reloc_type[2];
if (mips_opts.mips16)
prev_insn_extended = (ip->use_extend
- || reloc_type > BFD_RELOC_UNUSED);
+ || *reloc_type > BFD_RELOC_UNUSED);
}
prev_prev_insn_unreordered = prev_insn_unreordered;
PC relative relocs. */
prev_prev_insn = prev_insn;
prev_insn = *ip;
- prev_insn_reloc_type = reloc_type;
+ prev_insn_reloc_type[0] = reloc_type[0];
+ prev_insn_reloc_type[1] = reloc_type[1];
+ prev_insn_reloc_type[2] = reloc_type[2];
prev_prev_insn_unreordered = prev_insn_unreordered;
prev_insn_unreordered = 1;
}
prev_insn_is_delay_slot = 0;
prev_insn_unreordered = 0;
prev_insn_extended = 0;
- prev_insn_reloc_type = BFD_RELOC_UNUSED;
+ prev_insn_reloc_type[0] = BFD_RELOC_UNUSED;
+ prev_insn_reloc_type[1] = BFD_RELOC_UNUSED;
+ prev_insn_reloc_type[2] = BFD_RELOC_UNUSED;
prev_prev_insn_unreordered = 0;
mips_clear_insn_labels ();
}
#endif
{
struct mips_cl_insn insn;
- bfd_reloc_code_real_type r;
+ bfd_reloc_code_real_type r[3];
va_list args;
#ifdef USE_STDARG
return;
}
- r = BFD_RELOC_UNUSED;
+ r[0] = BFD_RELOC_UNUSED;
+ r[1] = BFD_RELOC_UNUSED;
+ r[2] = BFD_RELOC_UNUSED;
insn.insn_mo = (struct mips_opcode *) hash_find (op_hash, name);
assert (insn.insn_mo);
assert (strcmp (name, insn.insn_mo->name) == 0);
case 'i':
case 'j':
case 'o':
- r = (bfd_reloc_code_real_type) va_arg (args, int);
- assert (r == BFD_RELOC_MIPS_GPREL
- || r == BFD_RELOC_MIPS_LITERAL
- || r == BFD_RELOC_LO16
- || r == BFD_RELOC_MIPS_GOT16
- || r == BFD_RELOC_MIPS_CALL16
- || r == BFD_RELOC_MIPS_GOT_LO16
- || r == BFD_RELOC_MIPS_CALL_LO16
+ *r = (bfd_reloc_code_real_type) va_arg (args, int);
+ assert (*r == BFD_RELOC_MIPS_GPREL
+ || *r == BFD_RELOC_MIPS_LITERAL
+ || *r == BFD_RELOC_MIPS_HIGHER
+ || *r == BFD_RELOC_HI16_S
+ || *r == BFD_RELOC_LO16
+ || *r == BFD_RELOC_MIPS_GOT16
+ || *r == BFD_RELOC_MIPS_CALL16
+ || *r == BFD_RELOC_MIPS_GOT_LO16
+ || *r == BFD_RELOC_MIPS_CALL_LO16
|| (ep->X_op == O_subtract
- && r == BFD_RELOC_PCREL_LO16));
+ && *r == BFD_RELOC_PCREL_LO16));
continue;
case 'u':
- r = (bfd_reloc_code_real_type) va_arg (args, int);
+ *r = (bfd_reloc_code_real_type) va_arg (args, int);
assert (ep != NULL
&& (ep->X_op == O_constant
|| (ep->X_op == O_symbol
- && (r == BFD_RELOC_HI16_S
- || r == BFD_RELOC_HI16
- || r == BFD_RELOC_MIPS_GOT_HI16
- || r == BFD_RELOC_MIPS_CALL_HI16))
+ && (*r == BFD_RELOC_MIPS_HIGHEST
+ || *r == BFD_RELOC_HI16_S
+ || *r == BFD_RELOC_HI16
+ || *r == BFD_RELOC_GPREL16
+ || *r == BFD_RELOC_MIPS_GOT_HI16
+ || *r == BFD_RELOC_MIPS_CALL_HI16))
|| (ep->X_op == O_subtract
- && r == BFD_RELOC_PCREL_HI16_S)));
- if (ep->X_op == O_constant)
- {
- insn.insn_opcode |= (ep->X_add_number >> 16) & 0xffff;
- ep = NULL;
- r = BFD_RELOC_UNUSED;
- }
+ && *r == BFD_RELOC_PCREL_HI16_S)));
continue;
case 'p':
}
else
if (mips_pic == EMBEDDED_PIC)
- r = BFD_RELOC_16_PCREL_S2;
+ *r = BFD_RELOC_16_PCREL_S2;
else
- r = BFD_RELOC_16_PCREL;
+ *r = BFD_RELOC_16_PCREL;
continue;
case 'a':
assert (ep != NULL);
- r = BFD_RELOC_MIPS_JMP;
+ *r = BFD_RELOC_MIPS_JMP;
continue;
case 'C':
break;
}
va_end (args);
- assert (r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
+ assert (*r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
append_insn (place, &insn, ep, r, false);
}
va_list args;
{
struct mips_cl_insn insn;
- bfd_reloc_code_real_type r;
+ bfd_reloc_code_real_type r[3]
+ = {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
- r = BFD_RELOC_UNUSED;
insn.insn_mo = (struct mips_opcode *) hash_find (mips16_op_hash, name);
assert (insn.insn_mo);
assert (strcmp (name, insn.insn_mo->name) == 0);
assert (ep != NULL);
if (ep->X_op != O_constant)
- r = BFD_RELOC_UNUSED + c;
+ *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);
ep = NULL;
- r = BFD_RELOC_UNUSED;
+ *r = BFD_RELOC_UNUSED;
}
}
continue;
break;
}
- assert (r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
+ assert (*r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
append_insn (place, &insn, ep, r, false);
}
{
expressionS high_expr;
struct mips_cl_insn insn;
- bfd_reloc_code_real_type r;
+ bfd_reloc_code_real_type r[3]
+ = {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
CONST char *name = "lui";
CONST char *fmt = "t,u";
/* we can compute the instruction now without a relocation entry */
high_expr.X_add_number = ((high_expr.X_add_number + 0x8000)
>> 16) & 0xffff;
- r = BFD_RELOC_UNUSED;
+ *r = BFD_RELOC_UNUSED;
}
- else
+ else if (! HAVE_NEWABI)
{
assert (ep->X_op == O_symbol);
/* _gp_disp is a special case, used from s_cpload. */
assert (mips_pic == NO_PIC
|| strcmp (S_GET_NAME (ep->X_add_symbol), "_gp_disp") == 0);
- r = BFD_RELOC_HI16_S;
+ *r = BFD_RELOC_HI16_S;
}
/*
assert (strcmp (fmt, insn.insn_mo->args) == 0);
insn.insn_opcode = insn.insn_mo->match | (regnum << OP_SH_RT);
- if (r == BFD_RELOC_UNUSED)
+ if (*r == BFD_RELOC_UNUSED)
{
insn.insn_opcode |= high_expr.X_add_number;
append_insn (place, &insn, NULL, r, false);
case 'A':
my_getExpression (&offset_expr, s);
- imm_reloc = BFD_RELOC_32;
+ *imm_reloc = BFD_RELOC_32;
s = expr_end;
continue;
case 'i': /* 16 bit unsigned immediate */
case 'j': /* 16 bit signed immediate */
- imm_reloc = BFD_RELOC_LO16;
+ *imm_reloc = BFD_RELOC_LO16;
c = my_getSmallExpression (&imm_expr, s);
if (c != S_EX_NONE)
{
imm_expr.X_add_number =
(imm_expr.X_add_number >> 16) & 0xffff;
else if (c == S_EX_HIGHEST)
- imm_reloc = BFD_RELOC_MIPS_HIGHEST;
+ *imm_reloc = BFD_RELOC_MIPS_HIGHEST;
else if (c == S_EX_HIGHER)
- imm_reloc = BFD_RELOC_MIPS_HIGHER;
+ *imm_reloc = BFD_RELOC_MIPS_HIGHER;
else if (c == S_EX_HI)
{
- imm_reloc = BFD_RELOC_HI16_S;
+ *imm_reloc = BFD_RELOC_HI16_S;
imm_unmatched_hi = true;
}
else
- imm_reloc = BFD_RELOC_HI16;
+ *imm_reloc = BFD_RELOC_HI16;
}
else if (imm_expr.X_op == O_constant)
imm_expr.X_add_number &= 0xffff;
offset_expr.X_add_number =
(offset_expr.X_add_number >> 16) & 0xffff;
}
- offset_reloc = BFD_RELOC_LO16;
+ *offset_reloc = BFD_RELOC_LO16;
s = expr_end;
continue;
case 'p': /* pc relative offset */
if (mips_pic == EMBEDDED_PIC)
- offset_reloc = BFD_RELOC_16_PCREL_S2;
+ *offset_reloc = BFD_RELOC_16_PCREL_S2;
else
- offset_reloc = BFD_RELOC_16_PCREL;
+ *offset_reloc = BFD_RELOC_16_PCREL;
my_getExpression (&offset_expr, s);
s = expr_end;
continue;
case 'u': /* upper 16 bits */
c = my_getSmallExpression (&imm_expr, s);
- imm_reloc = BFD_RELOC_LO16;
+ *imm_reloc = BFD_RELOC_LO16;
if (c != S_EX_NONE)
{
if (c != S_EX_LO)
imm_expr.X_add_number =
(imm_expr.X_add_number >> 16) & 0xffff;
else if (c == S_EX_HIGHEST)
- imm_reloc = BFD_RELOC_MIPS_HIGHEST;
+ *imm_reloc = BFD_RELOC_MIPS_HIGHEST;
else if (c == S_EX_HI)
{
- imm_reloc = BFD_RELOC_HI16_S;
+ *imm_reloc = BFD_RELOC_HI16_S;
imm_unmatched_hi = true;
}
else
- imm_reloc = BFD_RELOC_HI16;
+ *imm_reloc = BFD_RELOC_HI16;
}
else if (imm_expr.X_op == O_constant)
imm_expr.X_add_number &= 0xffff;
case 'a': /* 26 bit address */
my_getExpression (&offset_expr, s);
s = expr_end;
- offset_reloc = BFD_RELOC_MIPS_JMP;
+ *offset_reloc = BFD_RELOC_MIPS_JMP;
continue;
case 'N': /* 3 bit branch condition code */
ip->insn_opcode = insn->match;
ip->use_extend = false;
imm_expr.X_op = O_absent;
- imm_reloc = BFD_RELOC_UNUSED;
+ imm_reloc[0] = BFD_RELOC_UNUSED;
+ imm_reloc[1] = BFD_RELOC_UNUSED;
+ imm_reloc[2] = BFD_RELOC_UNUSED;
offset_expr.X_op = O_absent;
- offset_reloc = BFD_RELOC_UNUSED;
+ offset_reloc[0] = BFD_RELOC_UNUSED;
+ offset_reloc[1] = BFD_RELOC_UNUSED;
+ offset_reloc[2] = BFD_RELOC_UNUSED;
for (args = insn->args; 1; ++args)
{
int c;
{
/* Stuff the immediate value in now, if we can. */
if (imm_expr.X_op == O_constant
- && imm_reloc > BFD_RELOC_UNUSED
+ && *imm_reloc > BFD_RELOC_UNUSED
&& insn->pinfo != INSN_MACRO)
{
mips16_immed ((char *) NULL, 0,
- imm_reloc - BFD_RELOC_UNUSED,
+ *imm_reloc - BFD_RELOC_UNUSED,
imm_expr.X_add_number, true, mips16_small,
mips16_ext, &ip->insn_opcode,
&ip->use_extend, &ip->extend);
imm_expr.X_op = O_absent;
- imm_reloc = BFD_RELOC_UNUSED;
+ *imm_reloc = BFD_RELOC_UNUSED;
}
return;
if (imm_expr.X_op == O_symbol)
{
mips16_ext = true;
- imm_reloc = BFD_RELOC_MIPS16_GPREL;
+ *imm_reloc = BFD_RELOC_MIPS16_GPREL;
s = expr_end;
ip->use_extend = true;
ip->extend = 0;
explicit extensions correctly. */
imm_expr.X_op = O_constant;
imm_expr.X_add_number = 0;
- imm_reloc = (int) BFD_RELOC_UNUSED + c;
+ *imm_reloc = (int) BFD_RELOC_UNUSED + c;
continue;
}
}
/* We need to relax this instruction. */
- imm_reloc = (int) BFD_RELOC_UNUSED + c;
+ *imm_reloc = (int) BFD_RELOC_UNUSED + c;
s = expr_end;
continue;
break;
/* We need to relax this instruction. */
- offset_reloc = (int) BFD_RELOC_UNUSED + c;
+ *offset_reloc = (int) BFD_RELOC_UNUSED + c;
s = expr_end;
continue;
case 'a': /* 26 bit address */
my_getExpression (&offset_expr, s);
s = expr_end;
- offset_reloc = BFD_RELOC_MIPS16_JMP;
+ *offset_reloc = BFD_RELOC_MIPS16_JMP;
ip->insn_opcode <<= 16;
continue;
/* When generating embedded PIC code we must keep all PC relative
relocations, in case the linker has to relax a call. We also need
- to keep relocations for switch table entries. */
+ to keep relocations for switch table entries.
+
+ We may have combined relocations without symbols in the N32/N64 ABI.
+ We have to prevent gas from dropping them. */
int
mips_force_relocation (fixp)
|| fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
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)
assert (fixP->fx_size == 4
|| fixP->fx_r_type == BFD_RELOC_16
+ || fixP->fx_r_type == BFD_RELOC_32
+ || fixP->fx_r_type == BFD_RELOC_MIPS_JMP
+ || 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_GPREL32
|| fixP->fx_r_type == BFD_RELOC_64
+ || fixP->fx_r_type == BFD_RELOC_CTOR
+ || fixP->fx_r_type == BFD_RELOC_MIPS_SUB
+ || fixP->fx_r_type == BFD_RELOC_MIPS_HIGHEST
+ || fixP->fx_r_type == BFD_RELOC_MIPS_HIGHER
+ || fixP->fx_r_type == BFD_RELOC_MIPS_SCN_DISP
+ || fixP->fx_r_type == BFD_RELOC_MIPS_REL16
+ || fixP->fx_r_type == BFD_RELOC_MIPS_RELGOT
|| fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY);