#endif
#include "opcode/mips.h"
+#include "itbl-ops.h"
+
+#ifdef DEBUG
+#define DBG(x) printf x
+#else
+#define DBG(x)
+#endif
#ifdef OBJ_MAYBE_ELF
/* Clean up namespace so we can include obj-elf.h too. */
+static int mips_output_flavor PARAMS ((void));
static int mips_output_flavor () { return OUTPUT_FLAVOR; }
#undef OBJ_PROCESS_STAB
#undef OUTPUT_FLAVOR
#define ILLEGAL_REG (32)
+/* Allow override of standard little-endian ECOFF format. */
+
+#ifndef ECOFF_LITTLE_FORMAT
+#define ECOFF_LITTLE_FORMAT "ecoff-littlemips"
+#endif
+
extern int target_big_endian;
/* 1 is we should use the 64 bit MIPS ELF ABI, 0 if we should use the
case bfd_target_aout_flavour:
return target_big_endian ? "a.out-mips-big" : "a.out-mips-little";
case bfd_target_ecoff_flavour:
- return target_big_endian ? "ecoff-bigmips" : "ecoff-littlemips";
+ return target_big_endian ? "ecoff-bigmips" : ECOFF_LITTLE_FORMAT;
case bfd_target_elf_flavour:
return (target_big_endian
? (mips_64 ? "elf64-bigmips" : "elf32-bigmips")
/* As with "interlocks" this is used by hardware that has FP
(co-processor) interlocks. */
+/* Itbl support may require additional care here. */
static int cop_interlocks = -1;
/* MIPS PIC level. */
else
interlocks = 0;
+ /* Itbl support may require additional care here. */
if (mips_cpu == 4300)
cop_interlocks = 1;
else
if (mips16)
mips16_ip (str, &insn);
else
- mips_ip (str, &insn);
+ {
+ mips_ip (str, &insn);
+ DBG(("returned from mips_ip(%s) insn_opcode = 0x%x\n",
+ str, insn.insn_opcode));
+ }
if (insn_error)
{
delays delay the use of general register rt for one
instruction on the r3000. The r6000 and r4000 use
interlocks. */
+ /* Itbl support may require additional care here. */
know (prev_pinfo & INSN_WRITE_GPR_T);
if (reg == ((prev_insn.insn_opcode >> OP_SH_RT) & OP_MASK_RT))
return 1;
delays delay the use of general register rt for one
instruction on the r3000. The r6000 and r4000 use
interlocks. */
+ /* Itbl support may require additional care here. */
know (prev_pinfo & INSN_WRITE_GPR_T);
if (mips_optimize == 0
|| insn_uses_reg (ip,
knowledge of CP0 handling, and the coprocessors other
than the floating point unit are not distinguished at
all. */
+ /* Itbl support may require additional care here. FIXME!
+ Need to modify this to include knowledge about
+ user specified delays! */
if (prev_pinfo & INSN_WRITE_FPR_T)
{
if (mips_optimize == 0
instruction may set the condition codes, and the
current instruction uses them, we must insert two
NOPS. */
+ /* Itbl support may require additional care here. */
if (mips_optimize == 0
|| ((prev_pinfo & INSN_WRITE_COND_CODE)
&& (pinfo & INSN_READ_COND_CODE)))
(this means it is a floating point comparison
instruction). If this instruction uses the condition
codes, we need to insert a single NOP. */
+ /* Itbl support may require additional care here. */
if (mips_optimize == 0
|| (pinfo & INSN_READ_COND_CODE))
++nops;
/* If the previous instruction was in a noreorder section, then
we don't want to insert the nop after all. */
+ /* Itbl support may require additional care here. */
if (prev_insn_unreordered)
nops = 0;
& INSN_UNCOND_BRANCH_DELAY),
(prev_insn_reloc_type
== BFD_RELOC_MIPS16_JMP)),
- make_expr_symbol (address_expr), (long) 0,
+ make_expr_symbol (address_expr), (offsetT) 0,
(char *) NULL);
}
else if (place != NULL)
mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FR) & OP_MASK_FR);
if (pinfo & INSN_COP)
{
- /* We don't keep enough information to sort these cases out. */
+ /* We don't keep enough information to sort these cases out.
+ The itbl support does keep this information however, although
+ we currently don't support itbl fprmats as part of the cop
+ instruction. May want to add this support in the future. */
}
/* Never set the bit for $0, which is always zero. */
mips_gprmask &=~ 1 << 0;
|| (! mips16
&& mips_isa < 4
&& (prev_pinfo
+ /* Itbl support may require additional care here. */
& (INSN_LOAD_COPROC_DELAY
| INSN_COPROC_MOVE_DELAY
| INSN_WRITE_COND_CODE)))
&& mips_isa < 2
&& (prev_pinfo
& (INSN_LOAD_MEMORY_DELAY
+ /* Itbl support may require additional care here. */
| INSN_COPROC_MEMORY_DELAY)))
/* We can not swap with a branch instruction. */
|| (prev_pinfo
can not swap. */
|| (! mips16
&& mips_isa < 4
+ /* Itbl support may require additional care here. */
&& ((prev_prev_insn.insn_mo->pinfo & INSN_LOAD_COPROC_DELAY)
|| (mips_isa < 2
&& (prev_prev_insn.insn_mo->pinfo
& (INSN_LOAD_MEMORY_DELAY
| INSN_COPROC_MEMORY_DELAY))))
{
+ /* Itbl support may require additional care here. */
++nops;
if ((! mips16
&& mips_isa < 4
&& ((prev_prev_insn.insn_mo->pinfo & INSN_READ_HI)
|| (prev_prev_insn.insn_mo->pinfo & INSN_READ_LO))))
{
+ /* Itbl support may require additional care here. */
if (! prev_prev_insn_unreordered)
++nops;
}
|| ! ep->X_unsigned
|| sizeof (ep->X_add_number) > 4
|| (ep->X_add_number & 0x80000000) == 0))
- || ((mips_isa < 3 || !dbl)
- && (ep->X_add_number &~ (offsetT) 0xffffffff) == 0))
+ || ((mips_isa < 3 || ! dbl)
+ && (ep->X_add_number &~ (offsetT) 0xffffffff) == 0)
+ || (mips_isa < 3
+ && ! dbl
+ && ((ep->X_add_number &~ (offsetT) 0xffffffff)
+ == ~ (offsetT) 0xffffffff)))
{
/* 32 bit values require an lui. */
macro_build ((char *) NULL, counter, ep, "lui", "t,u", reg,
"t,r,j", reg, GP, (int) BFD_RELOC_MIPS_GPREL);
p = frag_var (rs_machine_dependent, 8, 0,
RELAX_ENCODE (4, 8, 0, 4, 0, mips_warn_about_macros),
- ep->X_add_symbol, (long) 0, (char *) NULL);
+ ep->X_add_symbol, (offsetT) 0, (char *) NULL);
}
macro_build_lui (p, counter, ep, reg);
if (p != NULL)
macro_build ((char *) NULL, counter, (expressionS *) NULL, "nop", "");
p = frag_var (rs_machine_dependent, 4, 0,
RELAX_ENCODE (0, 4, -8, 0, 0, mips_warn_about_macros),
- ep->X_add_symbol, (long) 0, (char *) NULL);
+ ep->X_add_symbol, (offsetT) 0, (char *) NULL);
macro_build (p, counter, ep,
mips_isa < 3 ? "addiu" : "daddiu",
"t,r,j", reg, reg, (int) BFD_RELOC_LO16);
p = frag_var (rs_machine_dependent, 12 + off, 0,
RELAX_ENCODE (12, 12 + off, off, 8 + off, 0,
mips_warn_about_macros),
- ep->X_add_symbol, (long) 0, (char *) NULL);
+ ep->X_add_symbol, (offsetT) 0, (char *) NULL);
if (off > 0)
{
/* We need a nop before loading from $gp. This special
p = frag_var (rs_machine_dependent, 8, 0,
RELAX_ENCODE (4, 8, 0, 4, 0,
mips_warn_about_macros),
- offset_expr.X_add_symbol, (long) 0,
+ offset_expr.X_add_symbol, (offsetT) 0,
(char *) NULL);
}
macro_build_lui (p, &icnt, &offset_expr, tempreg);
(breg == 0
? mips_warn_about_macros
: 0)),
- offset_expr.X_add_symbol, (long) 0,
+ offset_expr.X_add_symbol, (offsetT) 0,
(char *) NULL);
if (breg == 0)
{
"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, (long) 0,
+ offset_expr.X_add_symbol, (offsetT) 0,
(char *) NULL);
}
else
"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, (long) 0,
+ offset_expr.X_add_symbol, (offsetT) 0,
(char *) NULL);
used_at = 1;
}
(breg == 0
? mips_warn_about_macros
: 0)),
- offset_expr.X_add_symbol, (long) 0,
+ offset_expr.X_add_symbol, (offsetT) 0,
(char *) NULL);
}
else if (expr1.X_add_number >= -0x8000
(breg == 0
? mips_warn_about_macros
: 0)),
- offset_expr.X_add_symbol, (long) 0,
+ offset_expr.X_add_symbol, (offsetT) 0,
(char *) NULL);
}
else
(breg == 0
? mips_warn_about_macros
: 0)),
- offset_expr.X_add_symbol, (long) 0,
+ offset_expr.X_add_symbol, (offsetT) 0,
(char *) 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, (long) 0, (char *) NULL);
+ offset_expr.X_add_symbol, (offsetT) 0,
+ (char *) 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, (long) 0, (char *) NULL);
+ offset_expr.X_add_symbol, (offsetT) 0,
+ (char *) NULL);
if (gpdel > 0)
{
macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
goto ld;
case M_LWC0_AB:
s = "lwc0";
+ /* Itbl support may require additional care here. */
coproc = 1;
goto ld;
case M_LWC1_AB:
s = "lwc1";
+ /* Itbl support may require additional care here. */
coproc = 1;
goto ld;
case M_LWC2_AB:
s = "lwc2";
+ /* Itbl support may require additional care here. */
coproc = 1;
goto ld;
case M_LWC3_AB:
s = "lwc3";
+ /* Itbl support may require additional care here. */
coproc = 1;
goto ld;
case M_LWL_AB:
goto ld;
case M_LDC1_AB:
s = "ldc1";
+ /* Itbl support may require additional care here. */
coproc = 1;
goto ld;
case M_LDC2_AB:
s = "ldc2";
+ /* Itbl support may require additional care here. */
coproc = 1;
goto ld;
case M_LDC3_AB:
s = "ldc3";
+ /* Itbl support may require additional care here. */
coproc = 1;
goto ld;
case M_LDL_AB:
goto st;
case M_SWC0_AB:
s = "swc0";
+ /* Itbl support may require additional care here. */
coproc = 1;
goto st;
case M_SWC1_AB:
s = "swc1";
+ /* Itbl support may require additional care here. */
coproc = 1;
goto st;
case M_SWC2_AB:
s = "swc2";
+ /* Itbl support may require additional care here. */
coproc = 1;
goto st;
case M_SWC3_AB:
s = "swc3";
+ /* Itbl support may require additional care here. */
coproc = 1;
goto st;
case M_SWL_AB:
case M_SDC1_AB:
s = "sdc1";
coproc = 1;
+ /* Itbl support may require additional care here. */
goto st;
case M_SDC2_AB:
s = "sdc2";
+ /* Itbl support may require additional care here. */
coproc = 1;
goto st;
case M_SDC3_AB:
s = "sdc3";
+ /* Itbl support may require additional care here. */
coproc = 1;
goto st;
case M_SDL_AB:
tempreg = AT;
used_at = 1;
ld_st:
+ /* Itbl support may require additional care here. */
if (mask == M_LWC1_AB
|| mask == M_SWC1_AB
|| mask == M_LDC1_AB
RELAX_ENCODE (4, 8, 0, 4, 0,
(mips_warn_about_macros
|| (used_at && mips_noat))),
- offset_expr.X_add_symbol, (long) 0,
+ offset_expr.X_add_symbol, (offsetT) 0,
(char *) NULL);
used_at = 0;
}
treg, (int) BFD_RELOC_MIPS_GPREL, tempreg);
p = frag_var (rs_machine_dependent, 12, 0,
RELAX_ENCODE (8, 12, 0, 8, 0, 0),
- offset_expr.X_add_symbol, (long) 0,
+ offset_expr.X_add_symbol, (offsetT) 0,
(char *) NULL);
}
macro_build_lui (p, &icnt, &offset_expr, tempreg);
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, (long) 0,
+ offset_expr.X_add_symbol, (offsetT) 0,
(char *) NULL);
macro_build (p, &icnt, &offset_expr,
mips_isa < 3 ? "addiu" : "daddiu",
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, (long) 0, (char *) NULL);
+ offset_expr.X_add_symbol, (offsetT) 0, (char *) NULL);
if (gpdel > 0)
{
macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
* But, the resulting address is the same after relocation so why
* generate the extra instruction?
*/
+ /* Itbl support may require additional care here. */
coproc = 1;
if (mips_isa >= 2)
{
s = "swc1";
fmt = "T,o(b)";
+ /* Itbl support may require additional care here. */
coproc = 1;
goto ldd_std;
/* Even on a big endian machine $fn comes before $fn+1. We have
to adjust when loading from memory. We set coproc if we must
load $fn+1 first. */
+ /* Itbl support may require additional care here. */
if (! target_big_endian)
coproc = 0;
used_at = 1;
}
+ /* 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);
undesired nop. */
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
+ /* 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);
p = frag_var (rs_machine_dependent, 12 + off, 0,
RELAX_ENCODE (8 + off, 12 + off, 0, 4 + off, 1,
used_at && mips_noat),
- offset_expr.X_add_symbol, (long) 0,
+ offset_expr.X_add_symbol, (offsetT) 0,
(char *) NULL);
/* We just generated two relocs. When tc_gen_reloc
if (p != NULL)
p += 4;
}
+ /* Itbl support may require additional care here. */
macro_build (p, &icnt, &offset_expr, s, fmt,
coproc ? treg + 1 : treg,
(int) BFD_RELOC_LO16, AT);
p += 4;
/* FIXME: How do we handle overflow here? */
offset_expr.X_add_number += 4;
+ /* Itbl support may require additional care here. */
macro_build (p, &icnt, &offset_expr, s, fmt,
coproc ? treg : treg + 1,
(int) BFD_RELOC_LO16, AT);
macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
mips_isa < 3 ? "addu" : "daddu",
"d,v,t", AT, breg, AT);
+ /* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
coproc ? treg + 1 : treg,
(int) BFD_RELOC_LO16, AT);
nop. */
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
+ /* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
coproc ? treg : treg + 1,
(int) BFD_RELOC_LO16, AT);
(void) frag_var (rs_machine_dependent, 0, 0,
RELAX_ENCODE (0, 0, -16 - off, -8, 1, 0),
- offset_expr.X_add_symbol, (long) 0,
+ offset_expr.X_add_symbol, (offsetT) 0,
(char *) NULL);
}
else if (mips_pic == SVR4_PIC)
macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
mips_isa < 3 ? "addu" : "daddu",
"d,v,t", AT, breg, AT);
+ /* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
coproc ? treg + 1 : treg,
(int) BFD_RELOC_LO16, AT);
nop. */
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
+ /* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
coproc ? treg : treg + 1,
(int) BFD_RELOC_LO16, AT);
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, (long) 0,
+ offset_expr.X_add_symbol, (offsetT) 0,
(char *) NULL);
if (gpdel > 0)
{
"d,v,t", AT, breg, AT);
p += 4;
}
+ /* Itbl support may require additional care here. */
macro_build (p, &icnt, &expr1, s, fmt,
coproc ? treg + 1 : treg,
(int) BFD_RELOC_LO16, AT);
nop. */
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
+ /* Itbl support may require additional care here. */
macro_build (p, &icnt, &expr1, s, fmt,
coproc ? treg : treg + 1,
(int) BFD_RELOC_LO16, AT);
used_at = 1;
}
+ /* 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);
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);
macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg + 1,
(int) BFD_RELOC_LO16, breg);
return;
+
+ /* New code added to support COPZ instructions.
+ This code builds table entries out of the macros in mip_opcodes.
+ R4000 uses interlocks to handle coproc delays.
+ Other chips (like the R3000) require nops to be inserted for delays.
+
+ FIXME: Currently, we require that the user handle delays.
+ In order to fill delay slots for non-interlocked chips,
+ we must have a way to specify delays based on the coprocessor.
+ Eg. 4 cycles if load coproc reg from memory, 1 if in cache, etc.
+ What are the side-effects of the cop instruction?
+ What cache support might we have and what are its effects?
+ Both coprocessor & memory require delays. how long???
+ What registers are read/set/modified?
+
+ If an itbl is provided to interpret cop instructions,
+ this knowledge can be encoded in the itbl spec. */
+
+ case M_COP0:
+ s = "cop0";
+ goto copz;
+ case M_COP1:
+ s = "cop1";
+ goto copz;
+ case M_COP2:
+ s = "cop2";
+ goto copz;
+ case M_COP3:
+ s = "cop3";
+ copz:
+ /* For now we just do C (same as Cz). */
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, "C");
+ return;
+
#ifdef LOSING_COMPILER
default:
+ /* Try and see if this is a new itbl instruction.
+ This code builds table entries out of the macros in mip_opcodes.
+ FIXME: For now we just assemble the expression and pass it's
+ value along as a 32-bit immediate.
+ We may want to have the assembler assemble this value,
+ so that we gain the assembler's knowledge of delay slots,
+ symbols, etc.
+ Would it be more efficient to use mask (id) here? */
+ if (itbl_have_entries
+ && (immed_expr = itbl_assemble (ip->insn_mo->name, "")))
+ {
+ s = ip->insn_mo->name;
+ s2 = "cop3";
+ coproc = ITBL_DECODE_PNUM (immed_expr);;
+ macro_build ((char *) NULL, &icnt, &immed_expr, s, "C");
+ return;
+ }
macro2 (ip);
return;
}
break;
default:
+ /* FIXME: Check if this is one of the itbl macros, since they
+ are added dynamically. */
as_bad ("Macro %s not implemented yet", ip->insn_mo->name);
break;
}
for (s = str; *s != '\0' && !isspace(*s); ++s)
continue;
- if ( isspace(*s) )
+ if (isspace (*s))
*s++ = '\0';
-
+
if ((insn = (struct mips_opcode *) hash_find (op_hash, str)) == NULL)
{
insn_error = "unrecognized opcode";
s += 4;
regno = KT1;
}
+ else if (itbl_have_entries)
+ {
+ char *p, *n;
+ int r;
+
+ p = s+1; /* advance past '$' */
+ n = itbl_get_field (&p); /* n is name */
+
+ /* See if this is a register defined in an
+ itbl entry */
+ r = itbl_get_reg_val (n);
+ if (r)
+ {
+ /* Get_field advances to the start of
+ the next field, so we need to back
+ rack to the end of the last field. */
+ if (p)
+ s = p - 1;
+ else
+ s = strchr (s,'\0');
+ regno = r;
+ }
+ else
+ goto notreg;
+ }
else
goto notreg;
}
/* 'z' only matches $0. */
if (c == 'z' && regno != 0)
break;
+
+ /* Now that we have assembled one operand, we use the args string
+ * to figure out where it goes in the instruction. */
switch (c)
{
case 'r':
is $0. This only matches $0, and is checked
outside the switch. */
break;
+ case 'D':
+ /* Itbl operand; not yet implemented. FIXME ?? */
+ break;
+ /* What about all other operands like 'i', which
+ can be specified in the opcode table? */
}
lastregno = regno;
continue;
{"mips16", no_argument, NULL, OPTION_MIPS16},
#define OPTION_NO_MIPS16 (OPTION_MD_BASE + 23)
{"no-mips16", no_argument, NULL, OPTION_NO_MIPS16},
- /* start-sanitize-5900 */
+ /* start-sanitize-r5900 */
#define OPTION_M5900 (OPTION_MD_BASE + 24)
{"m5900", no_argument, NULL, OPTION_M5900},
#define OPTION_NO_M5900 (OPTION_MD_BASE + 25)
{"no-m5900", no_argument, NULL, OPTION_NO_M5900},
- /* end-sanitize-5900 */
+ /* end-sanitize-r5900 */
#define OPTION_CALL_SHARED (OPTION_MD_BASE + 7)
#define OPTION_NON_SHARED (OPTION_MD_BASE + 8)
#endif
}
\f
+void
+mips_init_after_args ()
+{
+ /* initialize opcodes */
+ bfd_mips_num_opcodes = bfd_mips_num_builtin_opcodes;
+ mips_opcodes = (struct mips_opcode*) mips_builtin_opcodes;
+}
+
long
md_pcrel_from (fixP)
fixS *fixP;
: (nbytes == 4 ? BFD_RELOC_32 : BFD_RELOC_64)));
}
+/* This is called before the symbol table is processed. In order to
+ work with gcc when using mips-tfile, we must keep all local labels.
+ However, in other cases, we want to discard them. If we were
+ called with -g, but we didn't see any debugging information, it may
+ mean that gcc is smuggling debugging information through to
+ mips-tfile, in which case we must generate all local labels. */
+
+void
+mips_frob_file_before_adjust ()
+{
+#ifndef NO_ECOFF_DEBUGGING
+ if (ECOFF_DEBUGGING
+ && mips_debug != 0
+ && ! ecoff_debugging_seen)
+ flag_keep_locals = 1;
+#endif
+}
+
/* Sort any unmatched HI16_S relocs so that they immediately precede
the corresponding LO reloc. This is called before md_apply_fix and
tc_gen_reloc. Unmatched HI16_S relocs can only be generated by
handle these cases, but it appears to do it
incorrectly. */
as_bad_where (fixP->fx_file, fixP->fx_line,
- "Relocation overflow");
+ "Branch out of range");
}
}
{
fragS *f;
- /* Adjust stretch for any alignment frag. FIXME: This
- doesn't handle the fr_subtype field, which specifies a
- maximum number of bytes to skip when doing an alignment. */
- for (f = fragp; f != fragp->fr_symbol->sy_frag; f = f->fr_next)
+ /* Adjust stretch for any alignment frag. Note that if have
+ been expanding the earlier code, the symbol may be
+ defined in what appears to be an earlier frag. FIXME:
+ This doesn't handle the fr_subtype field, which specifies
+ a maximum number of bytes to skip when doing an
+ alignment. */
+ for (f = fragp;
+ f != NULL && f != fragp->fr_symbol->sy_frag;
+ f = f->fr_next)
{
- assert (f != NULL);
if (f->fr_type == rs_align || f->fr_type == rs_align_code)
{
if (stretch < 0)
break;
}
}
- val += stretch;
+ if (f != NULL)
+ val += stretch;
}
addr = fragp->fr_address + fragp->fr_fix;
}
else if (mips_pic == SVR4_PIC)
{
- asection *symsec = fragp->fr_symbol->bsym->section;
+ symbolS *sym;
+ asection *symsec;
+
+ sym = fragp->fr_symbol;
+
+ /* Handle the case of a symbol equated to another symbol. */
+ while (sym->sy_value.X_op == O_symbol
+ && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
+ {
+ symbolS *n;
+
+ /* It's possible to get a loop here in a badly written
+ program. */
+ n = sym->sy_value.X_add_symbol;
+ if (n == sym)
+ break;
+ sym = n;
+ }
+
+ symsec = S_GET_SEGMENT (sym);
/* This must duplicate the test in adjust_reloc_syms. */
change = (symsec != &bfd_und_section
return 1;
#ifdef S_GET_OTHER
if (OUTPUT_FLAVOR == bfd_target_elf_flavour
- && S_GET_OTHER (fixp->fx_addsy) == STO_MIPS16)
+ && S_GET_OTHER (fixp->fx_addsy) == STO_MIPS16
+ && fixp->fx_subsy == NULL)
return 0;
#endif
return 1;
l->next = insn_labels;
insn_labels = l;
}
-
-/* Decide whether a label is local. This is called by LOCAL_LABEL.
- In order to work with gcc when using mips-tfile, we must keep all
- local labels. However, in other cases, we want to discard them,
- since they are useless. */
-
-int
-mips_local_label (name)
- const char *name;
-{
-#ifndef NO_ECOFF_DEBUGGING
- if (ECOFF_DEBUGGING
- && mips_debug != 0
- && ! ecoff_debugging_seen)
- {
- /* We were called with -g, but we didn't see any debugging
- information. That may mean that gcc is smuggling debugging
- information through to mips-tfile, in which case we must
- generate all local labels. */
- return 0;
- }
-#endif
-
- /* Here it's OK to discard local labels. */
-
- return name[0] == '$';
-}
\f
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)