aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-arm.c13
-rw-r--r--gas/config/tc-ia64.c188
-rw-r--r--gas/config/tc-ia64.h8
-rw-r--r--gas/config/tc-m68k.c4
-rw-r--r--gas/config/tc-m68k.h9
-rw-r--r--gas/config/tc-mips.c2949
-rw-r--r--gas/config/tc-mips.h5
7 files changed, 1430 insertions, 1746 deletions
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index c290a92..5f79508 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -11809,6 +11809,9 @@ md_begin ()
bfd_set_section_flags (stdoutput, arm_arch,
SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
| SEC_HAS_CONTENTS);
+#else
+ bfd_set_section_flags (stdoutput, arm_arch,
+ SEC_READONLY | SEC_HAS_CONTENTS);
#endif
arm_arch->output_section = arm_arch;
subseg_set (arm_arch, 0);
@@ -12823,6 +12826,16 @@ tc_gen_reloc (section, fixp)
return NULL;
case BFD_RELOC_ARM_OFFSET_IMM:
+ if (fixp->fx_addsy != NULL
+ && !S_IS_DEFINED (fixp->fx_addsy)
+ && S_IS_LOCAL (fixp->fx_addsy))
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("undefined local label `%s'"),
+ S_GET_NAME (fixp->fx_addsy));
+ return NULL;
+ }
+
as_bad_where (fixp->fx_file, fixp->fx_line,
_("internal_relocation (type: OFFSET_IMM) not fixed up"));
return NULL;
diff --git a/gas/config/tc-ia64.c b/gas/config/tc-ia64.c
index 4e98aa4..fe66ffa 100644
--- a/gas/config/tc-ia64.c
+++ b/gas/config/tc-ia64.c
@@ -822,6 +822,7 @@ static void output_X2_format PARAMS ((vbyte_func, int, int, int, int, int, unsig
static void output_X3_format PARAMS ((vbyte_func, unw_record_type, int, int, int, unsigned long,
unsigned long));
static void output_X4_format PARAMS ((vbyte_func, int, int, int, int, int, int, unsigned long));
+static unw_rec_list *output_endp PARAMS ((void));
static unw_rec_list *output_prologue PARAMS ((void));
static unw_rec_list *output_prologue_gr PARAMS ((unsigned int, unsigned int));
static unw_rec_list *output_body PARAMS ((void));
@@ -896,7 +897,6 @@ static void process_one_record PARAMS ((unw_rec_list *, vbyte_func));
static void process_unw_records PARAMS ((unw_rec_list *, vbyte_func));
static int calc_record_size PARAMS ((unw_rec_list *));
static void set_imask PARAMS ((unw_rec_list *, unsigned long, unsigned long, unsigned int));
-static int count_bits PARAMS ((unsigned long));
static unsigned long slot_index PARAMS ((unsigned long, fragS *,
unsigned long, fragS *));
static unw_rec_list *optimize_unw_records PARAMS ((unw_rec_list *));
@@ -1088,12 +1088,12 @@ ia64_flush_insns ()
CURR_SLOT.tag_fixups = 0;
/* In case there are unwind directives following the last instruction,
- resolve those now. We only handle body and prologue directives here.
- Give an error for others. */
+ resolve those now. We only handle prologue, body, and endp directives
+ here. Give an error for others. */
for (ptr = unwind.current_entry; ptr; ptr = ptr->next)
{
if (ptr->r.type == prologue || ptr->r.type == prologue_gr
- || ptr->r.type == body)
+ || ptr->r.type == body || ptr->r.type == endp)
{
ptr->slot_number = (unsigned long) frag_more (0);
ptr->slot_frag = frag_now;
@@ -1712,6 +1712,16 @@ alloc_record (unw_record_type t)
return ptr;
}
+/* Dummy unwind record used for calculating the length of the last prologue or
+ body region. */
+
+static unw_rec_list *
+output_endp ()
+{
+ unw_rec_list *ptr = alloc_record (endp);
+ return ptr;
+}
+
static unw_rec_list *
output_prologue ()
{
@@ -2332,6 +2342,10 @@ process_one_record (ptr, f)
switch (ptr->r.type)
{
+ /* This is a dummy record that takes up no space in the output. */
+ case endp:
+ break;
+
case gr_mem:
case fr_mem:
case br_mem:
@@ -2574,19 +2588,6 @@ set_imask (region, regmask, t, type)
}
}
-static int
-count_bits (unsigned long mask)
-{
- int n = 0;
-
- while (mask)
- {
- mask &= mask - 1;
- ++n;
- }
- return n;
-}
-
/* Return the number of instruction slots from FIRST_ADDR to SLOT_ADDR.
SLOT_FRAG is the frag containing SLOT_ADDR, and FIRST_FRAG is the frag
containing FIRST_ADDR. */
@@ -2680,8 +2681,8 @@ optimize_unw_records (list)
/* If the only unwind record is ".prologue" or ".prologue" followed
by ".body", then we can optimize the unwind directives away. */
if (list->r.type == prologue
- && (list->next == NULL
- || (list->next->r.type == body && list->next->next == NULL)))
+ && (list->next->r.type == endp
+ || (list->next->r.type == body && list->next->next->r.type == endp)))
return NULL;
return list;
@@ -2713,59 +2714,23 @@ fixup_unw_records (list)
case body:
{
unw_rec_list *last;
- int size, dir_len = 0;
- unsigned long last_addr;
- fragS *last_frag;
+ int size;
+ unsigned long last_addr = 0;
+ fragS *last_frag = NULL;
first_addr = ptr->slot_number;
first_frag = ptr->slot_frag;
/* Find either the next body/prologue start, or the end of
- the list, and determine the size of the region. */
- last_addr = list->next_slot_number;
- last_frag = list->next_slot_frag;
+ the function, and determine the size of the region. */
for (last = ptr->next; last != NULL; last = last->next)
if (last->r.type == prologue || last->r.type == prologue_gr
- || last->r.type == body)
+ || last->r.type == body || last->r.type == endp)
{
last_addr = last->slot_number;
last_frag = last->slot_frag;
break;
}
- else if (!last->next)
- {
- /* In the absence of an explicit .body directive,
- the prologue ends after the last instruction
- covered by an unwind directive. */
- if (ptr->r.type != body)
- {
- last_addr = last->slot_number;
- last_frag = last->slot_frag;
- switch (last->r.type)
- {
- case frgr_mem:
- dir_len = (count_bits (last->r.record.p.frmask)
- + count_bits (last->r.record.p.grmask));
- break;
- case fr_mem:
- case gr_mem:
- dir_len += count_bits (last->r.record.p.rmask);
- break;
- case br_mem:
- case br_gr:
- dir_len += count_bits (last->r.record.p.brmask);
- break;
- case gr_gr:
- dir_len += count_bits (last->r.record.p.grmask);
- break;
- default:
- dir_len = 1;
- break;
- }
- }
- break;
- }
- size = (slot_index (last_addr, last_frag, first_addr, first_frag)
- + dir_len);
+ size = slot_index (last_addr, last_frag, first_addr, first_frag);
rlen = ptr->r.record.r.rlen = size;
if (ptr->r.type == body)
/* End of region. */
@@ -2911,6 +2876,12 @@ ia64_convert_frag (fragS *frag)
/* Skip the header. */
vbyte_mem_ptr = frag->fr_literal + 8;
process_unw_records (list, output_vbyte_mem);
+
+ /* Fill the padding bytes with zeros. */
+ if (pad != 0)
+ md_number_to_chars (frag->fr_literal + len + 8 - md.pointer_size + pad, 0,
+ md.pointer_size - pad);
+
frag->fr_fix += size;
frag->fr_type = rs_fill;
frag->fr_var = 0;
@@ -3283,6 +3254,10 @@ generate_unwind_image (text_name)
int size, pad;
unw_rec_list *list;
+ /* Mark the end of the unwind info, so that we can compute the size of the
+ last unwind region. */
+ add_unwind_entry (output_endp ());
+
/* Force out pending instructions, to make sure all unwind records have
a valid slot_number field. */
ia64_flush_insns ();
@@ -6032,7 +6007,7 @@ emit_one_bundle ()
struct ia64_opcode *idesc;
int end_of_insn_group = 0, user_template = -1;
int n, i, j, first, curr;
- unw_rec_list *ptr;
+ unw_rec_list *ptr, *last_ptr, *end_ptr;
bfd_vma t0 = 0, t1 = 0;
struct label_fix *lfix;
struct insn_fix *ifix;
@@ -6076,18 +6051,39 @@ emit_one_bundle ()
end_of_insn_group = 0;
for (i = 0; i < 3 && md.num_slots_in_use > 0; ++i)
{
- /* Set the slot number for prologue/body records now as those
- refer to the current point, not the point after the
- instruction has been issued: */
- /* Don't try to delete prologue/body records here, as that will cause
- them to also be deleted from the master list of unwind records. */
- for (ptr = md.slot[curr].unwind_record; ptr; ptr = ptr->next)
- if (ptr->r.type == prologue || ptr->r.type == prologue_gr
- || ptr->r.type == body)
- {
- ptr->slot_number = (unsigned long) f + i;
- ptr->slot_frag = frag_now;
- }
+ /* If we have unwind records, we may need to update some now. */
+ ptr = md.slot[curr].unwind_record;
+ if (ptr)
+ {
+ /* Find the last prologue/body record in the list for the current
+ insn, and set the slot number for all records up to that point.
+ This needs to be done now, because prologue/body records refer to
+ the current point, not the point after the instruction has been
+ issued. This matters because there may have been nops emitted
+ meanwhile. Any non-prologue non-body record followed by a
+ prologue/body record must also refer to the current point. */
+ last_ptr = NULL;
+ end_ptr = md.slot[(curr + 1) % NUM_SLOTS].unwind_record;
+ for (; ptr != end_ptr; ptr = ptr->next)
+ if (ptr->r.type == prologue || ptr->r.type == prologue_gr
+ || ptr->r.type == body)
+ last_ptr = ptr;
+ if (last_ptr)
+ {
+ /* Make last_ptr point one after the last prologue/body
+ record. */
+ last_ptr = last_ptr->next;
+ for (ptr = md.slot[curr].unwind_record; ptr != last_ptr;
+ ptr = ptr->next)
+ {
+ ptr->slot_number = (unsigned long) f + i;
+ ptr->slot_frag = frag_now;
+ }
+ /* Remove the initialized records, so that we won't accidentally
+ update them again if we insert a nop and continue. */
+ md.slot[curr].unwind_record = last_ptr;
+ }
+ }
if (idesc->flags & IA64_OPCODE_SLOT2)
{
@@ -6292,15 +6288,20 @@ emit_one_bundle ()
build_insn (md.slot + curr, insn + i);
- /* Set slot counts for non prologue/body unwind records. */
- for (ptr = md.slot[curr].unwind_record; ptr; ptr = ptr->next)
- if (ptr->r.type != prologue && ptr->r.type != prologue_gr
- && ptr->r.type != body)
- {
- ptr->slot_number = (unsigned long) f + i;
- ptr->slot_frag = frag_now;
- }
- md.slot[curr].unwind_record = NULL;
+ ptr = md.slot[curr].unwind_record;
+ if (ptr)
+ {
+ /* Set slot numbers for all remaining unwind records belonging to the
+ current insn. There can not be any prologue/body unwind records
+ here. */
+ end_ptr = md.slot[(curr + 1) % NUM_SLOTS].unwind_record;
+ for (; ptr != end_ptr; ptr = ptr->next)
+ {
+ ptr->slot_number = (unsigned long) f + i;
+ ptr->slot_frag = frag_now;
+ }
+ md.slot[curr].unwind_record = NULL;
+ }
if (required_unit == IA64_UNIT_L)
{
@@ -6375,8 +6376,8 @@ emit_one_bundle ()
if (unwind.list)
{
- unwind.list->next_slot_number = (unsigned long) f + 16;
- unwind.list->next_slot_frag = frag_now;
+ unwind.list->next_slot_number = (unsigned long) f + 16;
+ unwind.list->next_slot_frag = frag_now;
}
}
@@ -7118,6 +7119,23 @@ ia64_frob_label (sym)
}
}
+#ifdef TE_HPUX
+/* The HP-UX linker will give unresolved symbol errors for symbols
+ that are declared but unused. This routine removes declared,
+ unused symbols from an object. */
+int
+ia64_frob_symbol (sym)
+ struct symbol *sym;
+{
+ if ((S_GET_SEGMENT (sym) == &bfd_und_section && ! symbol_used_p (sym) &&
+ ELF_ST_VISIBILITY (S_GET_OTHER (sym)) == STV_DEFAULT)
+ || (S_GET_SEGMENT (sym) == &bfd_abs_section
+ && ! S_IS_EXTERNAL (sym)))
+ return 1;
+ return 0;
+}
+#endif
+
void
ia64_flush_pending_output ()
{
diff --git a/gas/config/tc-ia64.h b/gas/config/tc-ia64.h
index 6fd049f..d1a04ee 100644
--- a/gas/config/tc-ia64.h
+++ b/gas/config/tc-ia64.h
@@ -91,6 +91,9 @@ extern void ia64_end_of_source PARAMS((void));
extern void ia64_start_line PARAMS((void));
extern int ia64_unrecognized_line PARAMS((int ch));
extern void ia64_frob_label PARAMS((struct symbol *sym));
+#ifdef TE_HPUX
+extern int ia64_frob_symbol PARAMS((struct symbol *sym));
+#endif
extern void ia64_flush_pending_output PARAMS((void));
extern int ia64_parse_name (char *name, expressionS *e);
extern int ia64_optimize_expr PARAMS((expressionS *l, operatorT op,
@@ -118,6 +121,9 @@ extern void ia64_convert_frag (fragS *);
#define md_start_line_hook() ia64_start_line ()
#define tc_unrecognized_line(ch) ia64_unrecognized_line (ch)
#define tc_frob_label(s) ia64_frob_label (s)
+#ifdef TE_HPUX
+#define tc_frob_symbol(s,p) p |= ia64_frob_symbol (s)
+#endif /* TE_HPUX */
#define md_flush_pending_output() ia64_flush_pending_output ()
#define md_parse_name(s,e,c) ia64_parse_name (s, e)
#define tc_canonicalize_symbol_name(s) ia64_canonicalize_symbol_name (s)
@@ -202,7 +208,7 @@ typedef enum
bspstore_gr, bspstore_psprel, bspstore_sprel, rnat_when, rnat_gr,
rnat_psprel, rnat_sprel, epilogue, label_state, copy_state,
spill_psprel, spill_sprel, spill_reg, spill_psprel_p, spill_sprel_p,
- spill_reg_p, unwabi
+ spill_reg_p, unwabi, endp
} unw_record_type;
/* These structures declare the fields that can be used in each of the
diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c
index 09a8396..5bef34b 100644
--- a/gas/config/tc-m68k.c
+++ b/gas/config/tc-m68k.c
@@ -1,6 +1,6 @@
/* tc-m68k.c -- Assemble for the m68k family
Copyright 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -732,7 +732,7 @@ tc_coff_fix2rtype (fixP)
libraries, and we can relax any external sym. */
#define relaxable_symbol(symbol) \
- (!((S_IS_EXTERNAL (symbol) && strcmp (TARGET_OS, "elf") != 0) \
+ (!((S_IS_EXTERNAL (symbol) && EXTERN_FORCE_RELOC) \
|| S_IS_WEAK (symbol)))
/* Compute the relocation code for a fixup of SIZE bytes, using pc
diff --git a/gas/config/tc-m68k.h b/gas/config/tc-m68k.h
index 1182820..559d5e3 100644
--- a/gas/config/tc-m68k.h
+++ b/gas/config/tc-m68k.h
@@ -1,6 +1,6 @@
/* This file is tc-m68k.h
Copyright 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002, 2003
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -169,8 +169,11 @@ while (0)
#define tc_fix_adjustable(X) tc_m68k_fix_adjustable(X)
extern int tc_m68k_fix_adjustable PARAMS ((struct fix *));
-/* Target *-*-elf implies an embedded target. No shared libs. */
-#define EXTERN_FORCE_RELOC (strcmp (TARGET_OS, "elf") != 0)
+/* Target *-*-elf implies an embedded target. No shared libs.
+ *-*-uclinux also requires special casing to prevent GAS from
+ generating unsupported R_68K_PC16 relocs. */
+#define EXTERN_FORCE_RELOC \
+ ((strcmp (TARGET_OS, "elf") != 0) && (strcmp (TARGET_OS, "uclinux") != 0))
/* Values passed to md_apply_fix3 don't include symbol values. */
#define MD_APPLY_SYM_VALUE(FIX) 0
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index e0aa61e..66f52b0 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -325,15 +325,30 @@ static int mips_32bitmode = 0;
/* True if CPU has a ror instruction. */
#define CPU_HAS_ROR(CPU) CPU_HAS_DROR (CPU)
-/* Whether the processor uses hardware interlocks to protect
- reads from the HI and LO registers, and thus does not
- require nops to be inserted. */
-
-#define hilo_interlocks (mips_opts.arch == CPU_R4010 \
- || mips_opts.arch == CPU_VR5500 \
- || mips_opts.arch == CPU_RM7000 \
- || mips_opts.arch == CPU_SB1 \
- )
+/* True if mflo and mfhi can be immediately followed by instructions
+ which write to the HI and LO registers.
+
+ According to MIPS specifications, MIPS ISAs I, II, and III need
+ (at least) two instructions between the reads of HI/LO and
+ instructions which write them, and later ISAs do not. Contradicting
+ the MIPS specifications, some MIPS IV processor user manuals (e.g.
+ the UM for the NEC Vr5000) document needing the instructions between
+ HI/LO reads and writes, as well. Therefore, we declare only MIPS32,
+ MIPS64 and later ISAs to have the interlocks, plus any specific
+ earlier-ISA CPUs for which CPU documentation declares that the
+ instructions are really interlocked. */
+#define hilo_interlocks \
+ (mips_opts.isa == ISA_MIPS32 \
+ || mips_opts.isa == ISA_MIPS32R2 \
+ || mips_opts.isa == ISA_MIPS64 \
+ || mips_opts.isa == ISA_MIPS64R2 \
+ || mips_opts.arch == CPU_R4010 \
+ || mips_opts.arch == CPU_R10000 \
+ || mips_opts.arch == CPU_R12000 \
+ || mips_opts.arch == CPU_RM7000 \
+ || mips_opts.arch == CPU_SB1 \
+ || mips_opts.arch == CPU_VR5500 \
+ )
/* Whether the processor uses hardware interlocks to protect reads
from the GPRs after they are loaded from memory, and thus does not
@@ -616,81 +631,61 @@ static int mips_fix_4122_bugs;
static int mips_relax_branch;
-/* Since the MIPS does not have multiple forms of PC relative
- instructions, we do not have to do relaxing as is done on other
- platforms. However, we do have to handle GP relative addressing
- correctly, which turns out to be a similar problem.
-
- Every macro that refers to a symbol can occur in (at least) two
- forms, one with GP relative addressing and one without. For
- example, loading a global variable into a register generally uses
- a macro instruction like this:
- lw $4,i
- If i can be addressed off the GP register (this is true if it is in
- the .sbss or .sdata section, or if it is known to be smaller than
- the -G argument) this will generate the following instruction:
- lw $4,i($gp)
- This instruction will use a GPREL reloc. If i can not be addressed
- off the GP register, the following instruction sequence will be used:
- lui $at,i
- lw $4,i($at)
- In this case the first instruction will have a HI16 reloc, and the
- second reloc will have a LO16 reloc. Both relocs will be against
- the symbol i.
-
- The issue here is that we may not know whether i is GP addressable
- until after we see the instruction that uses it. Therefore, we
- want to be able to choose the final instruction sequence only at
- the end of the assembly. This is similar to the way other
- platforms choose the size of a PC relative instruction only at the
- end of assembly.
-
- When generating position independent code we do not use GP
- addressing in quite the same way, but the issue still arises as
- external symbols and local symbols must be handled differently.
-
- We handle these issues by actually generating both possible
- instruction sequences. The longer one is put in a frag_var with
- type rs_machine_dependent. We encode what to do with the frag in
- the subtype field. We encode (1) the number of existing bytes to
- replace, (2) the number of new bytes to use, (3) the offset from
- the start of the existing bytes to the first reloc we must generate
- (that is, the offset is applied from the start of the existing
- bytes after they are replaced by the new bytes, if any), (4) the
- offset from the start of the existing bytes to the second reloc,
- (5) whether a third reloc is needed (the third reloc is always four
- bytes after the second reloc), and (6) whether to warn if this
- variant is used (this is sometimes needed if .set nomacro or .set
- noat is in effect). All these numbers are reasonably small.
-
- Generating two instruction sequences must be handled carefully to
- ensure that delay slots are handled correctly. Fortunately, there
- are a limited number of cases. When the second instruction
- sequence is generated, append_insn is directed to maintain the
- existing delay slot information, so it continues to apply to any
- code after the second instruction sequence. This means that the
- second instruction sequence must not impose any requirements not
- required by the first instruction sequence.
-
- These variant frags are then handled in functions called by the
- machine independent code. md_estimate_size_before_relax returns
- the final size of the frag. md_convert_frag sets up the final form
- of the frag. tc_gen_reloc adjust the first reloc and adds a second
- one if needed. */
-#define RELAX_ENCODE(old, new, reloc1, reloc2, reloc3, warn) \
- ((relax_substateT) \
- (((old) << 23) \
- | ((new) << 16) \
- | (((reloc1) + 64) << 9) \
- | (((reloc2) + 64) << 2) \
- | ((reloc3) ? (1 << 1) : 0) \
- | ((warn) ? 1 : 0)))
-#define RELAX_OLD(i) (((i) >> 23) & 0x7f)
-#define RELAX_NEW(i) (((i) >> 16) & 0x7f)
-#define RELAX_RELOC1(i) ((valueT) (((i) >> 9) & 0x7f) - 64)
-#define RELAX_RELOC2(i) ((valueT) (((i) >> 2) & 0x7f) - 64)
-#define RELAX_RELOC3(i) (((i) >> 1) & 1)
-#define RELAX_WARN(i) ((i) & 1)
+/* The expansion of many macros depends on the type of symbol that
+ they refer to. For example, when generating position-dependent code,
+ a macro that refers to a symbol may have two different expansions,
+ one which uses GP-relative addresses and one which uses absolute
+ addresses. When generating SVR4-style PIC, a macro may have
+ different expansions for local and global symbols.
+
+ We handle these situations by generating both sequences and putting
+ them in variant frags. In position-dependent code, the first sequence
+ will be the GP-relative one and the second sequence will be the
+ absolute one. In SVR4 PIC, the first sequence will be for global
+ symbols and the second will be for local symbols.
+
+ The frag's "subtype" is RELAX_ENCODE (FIRST, SECOND), where FIRST and
+ SECOND are the lengths of the two sequences in bytes. These fields
+ can be extracted using RELAX_FIRST() and RELAX_SECOND(). In addition,
+ the subtype has the following flags:
+
+ RELAX_USE_SECOND
+ Set if it has been decided that we should use the second
+ sequence instead of the first.
+
+ RELAX_SECOND_LONGER
+ Set in the first variant frag if the macro's second implementation
+ is longer than its first. This refers to the macro as a whole,
+ not an individual relaxation.
+
+ RELAX_NOMACRO
+ Set in the first variant frag if the macro appeared in a .set nomacro
+ block and if one alternative requires a warning but the other does not.
+
+ RELAX_DELAY_SLOT
+ Like RELAX_NOMACRO, but indicates that the macro appears in a branch
+ delay slot.
+
+ The frag's "opcode" points to the first fixup for relaxable code.
+
+ Relaxable macros are generated using a sequence such as:
+
+ relax_start (SYMBOL);
+ ... generate first expansion ...
+ relax_switch ();
+ ... generate second expansion ...
+ relax_end ();
+
+ The code and fixups for the unwanted alternative are discarded
+ by md_convert_frag. */
+#define RELAX_ENCODE(FIRST, SECOND) (((FIRST) << 8) | (SECOND))
+
+#define RELAX_FIRST(X) (((X) >> 8) & 0xff)
+#define RELAX_SECOND(X) ((X) & 0xff)
+#define RELAX_USE_SECOND 0x10000
+#define RELAX_SECOND_LONGER 0x20000
+#define RELAX_NOMACRO 0x40000
+#define RELAX_DELAY_SLOT 0x80000
/* Branch without likely bit. If label is out of range, we turn:
@@ -823,6 +818,42 @@ static int mips_relax_branch;
|| (((x) &~ (offsetT) 0x7fff) == ~ (offsetT) 0x7fff))
+/* Global variables used when generating relaxable macros. See the
+ comment above RELAX_ENCODE for more details about how relaxation
+ is used. */
+static struct {
+ /* 0 if we're not emitting a relaxable macro.
+ 1 if we're emitting the first of the two relaxation alternatives.
+ 2 if we're emitting the second alternative. */
+ int sequence;
+
+ /* The first relaxable fixup in the current frag. (In other words,
+ the first fixup that refers to relaxable code.) */
+ fixS *first_fixup;
+
+ /* sizes[0] says how many bytes of the first alternative are stored in
+ the current frag. Likewise sizes[1] for the second alternative. */
+ unsigned int sizes[2];
+
+ /* The symbol on which the choice of sequence depends. */
+ symbolS *symbol;
+} mips_relax;
+
+/* Global variables used to decide whether a macro needs a warning. */
+static struct {
+ /* True if the macro is in a branch delay slot. */
+ bfd_boolean delay_slot_p;
+
+ /* For relaxable macros, sizes[0] is the length of the first alternative
+ in bytes and sizes[1] is the length of the second alternative.
+ For non-relaxable macros, both elements give the length of the
+ macro in bytes. */
+ unsigned int sizes[2];
+
+ /* The first variant frag for this macro. */
+ fragS *first_frag;
+} mips_macro_warning;
+
/* Prototypes for static functions. */
#define internalError() \
@@ -831,12 +862,13 @@ static int mips_relax_branch;
enum mips_regclass { MIPS_GR_REG, MIPS_FP_REG, MIPS16_REG };
static void append_insn
- (char *place, struct mips_cl_insn *ip, expressionS *p,
- bfd_reloc_code_real_type *r);
+ (struct mips_cl_insn *ip, expressionS *p, bfd_reloc_code_real_type *r);
static void mips_no_prev_insn (int);
static void mips16_macro_build
- (char *, int *, expressionS *, const char *, const char *, va_list);
-static void load_register (int *, int, expressionS *, int);
+ (expressionS *, const char *, const char *, va_list);
+static void load_register (int, expressionS *, int);
+static void macro_start (void);
+static void macro_end (void);
static void macro (struct mips_cl_insn * ip);
static void mips16_macro (struct mips_cl_insn * ip);
#ifdef LOSING_COMPILER
@@ -1354,19 +1386,21 @@ md_assemble (char *str)
if (insn.insn_mo->pinfo == INSN_MACRO)
{
+ macro_start ();
if (mips_opts.mips16)
mips16_macro (&insn);
else
macro (&insn);
+ macro_end ();
}
else
{
if (imm_expr.X_op != O_absent)
- append_insn (NULL, &insn, &imm_expr, imm_reloc);
+ append_insn (&insn, &imm_expr, imm_reloc);
else if (offset_expr.X_op != O_absent)
- append_insn (NULL, &insn, &offset_expr, offset_reloc);
+ append_insn (&insn, &offset_expr, offset_reloc);
else
- append_insn (NULL, &insn, NULL, unused_reloc);
+ append_insn (&insn, NULL, unused_reloc);
}
}
@@ -1526,13 +1560,58 @@ mips16_mark_labels (void)
}
}
-/* Output an instruction. PLACE is where to put the instruction; if
- it is NULL, this uses frag_more to get room. IP is the instruction
- information. ADDRESS_EXPR is an operand of the instruction to be
- used with RELOC_TYPE. */
+/* End the current frag. Make it a variant frag and record the
+ relaxation info. */
+
+static void
+relax_close_frag (void)
+{
+ mips_macro_warning.first_frag = frag_now;
+ frag_var (rs_machine_dependent, 0, 0,
+ RELAX_ENCODE (mips_relax.sizes[0], mips_relax.sizes[1]),
+ mips_relax.symbol, 0, (char *) mips_relax.first_fixup);
+
+ memset (&mips_relax.sizes, 0, sizeof (mips_relax.sizes));
+ mips_relax.first_fixup = 0;
+}
+
+/* Start a new relaxation sequence whose expansion depends on SYMBOL.
+ See the comment above RELAX_ENCODE for more details. */
+
+static void
+relax_start (symbolS *symbol)
+{
+ assert (mips_relax.sequence == 0);
+ mips_relax.sequence = 1;
+ mips_relax.symbol = symbol;
+}
+
+/* Start generating the second version of a relaxable sequence.
+ See the comment above RELAX_ENCODE for more details. */
+
+static void
+relax_switch (void)
+{
+ assert (mips_relax.sequence == 1);
+ mips_relax.sequence = 2;
+}
+
+/* End the current relaxable sequence. */
+
+static void
+relax_end (void)
+{
+ assert (mips_relax.sequence == 2);
+ relax_close_frag ();
+ mips_relax.sequence = 0;
+}
+
+/* Output an instruction. IP is the instruction information.
+ ADDRESS_EXPR is an operand of the instruction to be used with
+ RELOC_TYPE. */
static void
-append_insn (char *place, struct mips_cl_insn *ip, expressionS *address_expr,
+append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
bfd_reloc_code_real_type *reloc_type)
{
register unsigned long prev_pinfo, pinfo;
@@ -1549,7 +1628,8 @@ append_insn (char *place, struct mips_cl_insn *ip, expressionS *address_expr,
prev_pinfo = prev_insn.insn_mo->pinfo;
pinfo = ip->insn_mo->pinfo;
- if (place == NULL && (! mips_opts.noreorder || prev_nop_frag != NULL))
+ if (mips_relax.sequence != 2
+ && (!mips_opts.noreorder || prev_nop_frag != NULL))
{
int prev_prev_nop;
@@ -1925,8 +2005,7 @@ append_insn (char *place, struct mips_cl_insn *ip, expressionS *address_expr,
if (prev_insn_frag)
prev_insn_frag_type = prev_insn_frag->fr_type;
- if (place == NULL
- && address_expr
+ if (address_expr
&& *reloc_type == BFD_RELOC_16_PCREL_S2
&& (pinfo & INSN_UNCOND_BRANCH_DELAY || pinfo & INSN_COND_BRANCH_DELAY
|| pinfo & INSN_COND_BRANCH_LIKELY)
@@ -1967,8 +2046,6 @@ append_insn (char *place, struct mips_cl_insn *ip, expressionS *address_expr,
== BFD_RELOC_MIPS16_JMP)),
make_expr_symbol (address_expr), 0, NULL);
}
- else if (place != NULL)
- f = place;
else if (mips_opts.mips16
&& ! ip->use_extend
&& *reloc_type != BFD_RELOC_MIPS16_JMP)
@@ -1985,6 +2062,21 @@ append_insn (char *place, struct mips_cl_insn *ip, expressionS *address_expr,
&& (prev_pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
as_warn (_("extended instruction in delay slot"));
+ if (mips_relax.sequence)
+ {
+ /* If we've reached the end of this frag, turn it into a variant
+ frag and record the information for the instructions we've
+ written so far. */
+ if (frag_room () < 4)
+ relax_close_frag ();
+ mips_relax.sizes[mips_relax.sequence - 1] += 4;
+ }
+
+ if (mips_relax.sequence != 2)
+ mips_macro_warning.sizes[0] += 4;
+ if (mips_relax.sequence != 1)
+ mips_macro_warning.sizes[1] += 4;
+
f = frag_more (4);
}
@@ -2058,84 +2150,85 @@ append_insn (char *place, struct mips_cl_insn *ip, expressionS *address_expr,
}
}
else
- {
need_reloc:
- /* Don't generate a reloc if we are writing into a variant frag. */
- if (place == NULL)
- {
- reloc_howto_type *howto;
- int i;
+ {
+ reloc_howto_type *howto;
+ int i;
- /* In a compound relocation, it is the final (outermost)
- operator that determines the relocated field. */
- for (i = 1; i < 3; i++)
- if (reloc_type[i] == BFD_RELOC_UNUSED)
- break;
+ /* In a compound relocation, it is the final (outermost)
+ operator that determines the relocated field. */
+ for (i = 1; i < 3; i++)
+ if (reloc_type[i] == BFD_RELOC_UNUSED)
+ break;
- howto = bfd_reloc_type_lookup (stdoutput, reloc_type[i - 1]);
- fixp[0] = fix_new_exp (frag_now, f - frag_now->fr_literal,
- bfd_get_reloc_size(howto),
- address_expr,
- reloc_type[0] == BFD_RELOC_16_PCREL_S2,
- reloc_type[0]);
-
- /* These relocations can have an addend that won't fit in
- 4 octets for 64bit assembly. */
- if (HAVE_64BIT_GPRS
- && ! howto->partial_inplace
- && (reloc_type[0] == BFD_RELOC_16
- || reloc_type[0] == BFD_RELOC_32
- || reloc_type[0] == BFD_RELOC_MIPS_JMP
- || reloc_type[0] == BFD_RELOC_HI16_S
- || reloc_type[0] == BFD_RELOC_LO16
- || reloc_type[0] == BFD_RELOC_GPREL16
- || reloc_type[0] == BFD_RELOC_MIPS_LITERAL
- || reloc_type[0] == BFD_RELOC_GPREL32
- || reloc_type[0] == BFD_RELOC_64
- || reloc_type[0] == BFD_RELOC_CTOR
- || reloc_type[0] == BFD_RELOC_MIPS_SUB
- || reloc_type[0] == BFD_RELOC_MIPS_HIGHEST
- || reloc_type[0] == BFD_RELOC_MIPS_HIGHER
- || reloc_type[0] == BFD_RELOC_MIPS_SCN_DISP
- || reloc_type[0] == BFD_RELOC_MIPS_REL16
- || reloc_type[0] == BFD_RELOC_MIPS_RELGOT))
- fixp[0]->fx_no_overflow = 1;
-
- if (reloc_needs_lo_p (*reloc_type))
- {
- struct mips_hi_fixup *hi_fixup;
+ howto = bfd_reloc_type_lookup (stdoutput, reloc_type[i - 1]);
+ fixp[0] = fix_new_exp (frag_now, f - frag_now->fr_literal,
+ bfd_get_reloc_size(howto),
+ address_expr,
+ reloc_type[0] == BFD_RELOC_16_PCREL_S2,
+ reloc_type[0]);
+
+ /* These relocations can have an addend that won't fit in
+ 4 octets for 64bit assembly. */
+ if (HAVE_64BIT_GPRS
+ && ! howto->partial_inplace
+ && (reloc_type[0] == BFD_RELOC_16
+ || reloc_type[0] == BFD_RELOC_32
+ || reloc_type[0] == BFD_RELOC_MIPS_JMP
+ || reloc_type[0] == BFD_RELOC_HI16_S
+ || reloc_type[0] == BFD_RELOC_LO16
+ || reloc_type[0] == BFD_RELOC_GPREL16
+ || reloc_type[0] == BFD_RELOC_MIPS_LITERAL
+ || reloc_type[0] == BFD_RELOC_GPREL32
+ || reloc_type[0] == BFD_RELOC_64
+ || reloc_type[0] == BFD_RELOC_CTOR
+ || reloc_type[0] == BFD_RELOC_MIPS_SUB
+ || reloc_type[0] == BFD_RELOC_MIPS_HIGHEST
+ || reloc_type[0] == BFD_RELOC_MIPS_HIGHER
+ || reloc_type[0] == BFD_RELOC_MIPS_SCN_DISP
+ || reloc_type[0] == BFD_RELOC_MIPS_REL16
+ || reloc_type[0] == BFD_RELOC_MIPS_RELGOT))
+ fixp[0]->fx_no_overflow = 1;
+
+ if (mips_relax.sequence)
+ {
+ if (mips_relax.first_fixup == 0)
+ mips_relax.first_fixup = fixp[0];
+ }
+ else if (reloc_needs_lo_p (*reloc_type))
+ {
+ struct mips_hi_fixup *hi_fixup;
- /* Reuse the last entry if it already has a matching %lo. */
- hi_fixup = mips_hi_fixup_list;
- if (hi_fixup == 0
- || !fixup_has_matching_lo_p (hi_fixup->fixp))
- {
- hi_fixup = ((struct mips_hi_fixup *)
- xmalloc (sizeof (struct mips_hi_fixup)));
- hi_fixup->next = mips_hi_fixup_list;
- mips_hi_fixup_list = hi_fixup;
- }
- hi_fixup->fixp = fixp[0];
- hi_fixup->seg = now_seg;
+ /* Reuse the last entry if it already has a matching %lo. */
+ hi_fixup = mips_hi_fixup_list;
+ if (hi_fixup == 0
+ || !fixup_has_matching_lo_p (hi_fixup->fixp))
+ {
+ hi_fixup = ((struct mips_hi_fixup *)
+ xmalloc (sizeof (struct mips_hi_fixup)));
+ hi_fixup->next = mips_hi_fixup_list;
+ mips_hi_fixup_list = hi_fixup;
}
+ hi_fixup->fixp = fixp[0];
+ hi_fixup->seg = now_seg;
+ }
- /* Add fixups for the second and third relocations, if given.
- Note that the ABI allows the second relocation to be
- against RSS_UNDEF, RSS_GP, RSS_GP0 or RSS_LOC. At the
- moment we only use RSS_UNDEF, but we could add support
- for the others if it ever becomes necessary. */
- for (i = 1; i < 3; i++)
- if (reloc_type[i] != BFD_RELOC_UNUSED)
- {
- address_expr->X_op = O_absent;
- address_expr->X_add_symbol = 0;
- address_expr->X_add_number = 0;
+ /* Add fixups for the second and third relocations, if given.
+ Note that the ABI allows the second relocation to be
+ against RSS_UNDEF, RSS_GP, RSS_GP0 or RSS_LOC. At the
+ moment we only use RSS_UNDEF, but we could add support
+ for the others if it ever becomes necessary. */
+ for (i = 1; i < 3; i++)
+ if (reloc_type[i] != BFD_RELOC_UNUSED)
+ {
+ address_expr->X_op = O_absent;
+ address_expr->X_add_symbol = 0;
+ address_expr->X_add_number = 0;
- fixp[i] = fix_new_exp (frag_now, fixp[0]->fx_where,
- fixp[0]->fx_size, address_expr,
- FALSE, reloc_type[i]);
- }
- }
+ fixp[i] = fix_new_exp (frag_now, fixp[0]->fx_where,
+ fixp[0]->fx_size, address_expr,
+ FALSE, reloc_type[i]);
+ }
}
}
@@ -2223,7 +2316,7 @@ append_insn (char *place, struct mips_cl_insn *ip, expressionS *address_expr,
& MIPS16OP_MASK_REGR32);
}
- if (place == NULL && ! mips_opts.noreorder)
+ if (mips_relax.sequence != 2 && !mips_opts.noreorder)
{
/* Filling the branch delay slot is more complex. We try to
switch the branch with the previous instruction, which we can
@@ -2647,7 +2740,7 @@ append_insn (char *place, struct mips_cl_insn *ip, expressionS *address_expr,
prev_insn_where = f - frag_now->fr_literal;
prev_insn_valid = 1;
}
- else if (place == NULL)
+ else if (mips_relax.sequence != 2)
{
/* We need to record a bit of information even when we are not
reordering, in order to determine the base address for mips16
@@ -2663,15 +2756,6 @@ append_insn (char *place, struct mips_cl_insn *ip, expressionS *address_expr,
/* We just output an insn, so the next one doesn't have a label. */
mips_clear_insn_labels ();
-
- /* We must ensure that the frag to which an instruction that was
- moved from a non-variant frag doesn't become a variant frag,
- otherwise tc_gen_reloc may get confused. */
- if (force_new_frag)
- {
- frag_wane (frag_now);
- frag_new (0);
- }
}
/* This function forgets that there was any previous instruction or
@@ -2819,14 +2903,78 @@ mips_emit_delays (bfd_boolean insns)
mips_no_prev_insn (insns);
}
+/* Set up global variables for the start of a new macro. */
+
+static void
+macro_start (void)
+{
+ memset (&mips_macro_warning.sizes, 0, sizeof (mips_macro_warning.sizes));
+ mips_macro_warning.delay_slot_p = (mips_opts.noreorder
+ && (prev_insn.insn_mo->pinfo
+ & (INSN_UNCOND_BRANCH_DELAY
+ | INSN_COND_BRANCH_DELAY
+ | INSN_COND_BRANCH_LIKELY)) != 0);
+}
+
+/* Given that a macro is longer than 4 bytes, return the appropriate warning
+ for it. Return null if no warning is needed. SUBTYPE is a bitmask of
+ RELAX_DELAY_SLOT and RELAX_NOMACRO. */
+
+static const char *
+macro_warning (relax_substateT subtype)
+{
+ if (subtype & RELAX_DELAY_SLOT)
+ return _("Macro instruction expanded into multiple instructions"
+ " in a branch delay slot");
+ else if (subtype & RELAX_NOMACRO)
+ return _("Macro instruction expanded into multiple instructions");
+ else
+ return 0;
+}
+
+/* Finish up a macro. Emit warnings as appropriate. */
+
+static void
+macro_end (void)
+{
+ if (mips_macro_warning.sizes[0] > 4 || mips_macro_warning.sizes[1] > 4)
+ {
+ relax_substateT subtype;
+
+ /* Set up the relaxation warning flags. */
+ subtype = 0;
+ if (mips_macro_warning.sizes[1] > mips_macro_warning.sizes[0])
+ subtype |= RELAX_SECOND_LONGER;
+ if (mips_opts.warn_about_macros)
+ subtype |= RELAX_NOMACRO;
+ if (mips_macro_warning.delay_slot_p)
+ subtype |= RELAX_DELAY_SLOT;
+
+ if (mips_macro_warning.sizes[0] > 4 && mips_macro_warning.sizes[1] > 4)
+ {
+ /* Either the macro has a single implementation or both
+ implementations are longer than 4 bytes. Emit the
+ warning now. */
+ const char *msg = macro_warning (subtype);
+ if (msg != 0)
+ as_warn (msg);
+ }
+ else
+ {
+ /* One implementation might need a warning but the other
+ definitely doesn't. */
+ mips_macro_warning.first_frag->fr_subtype |= subtype;
+ }
+ }
+}
+
/* Build an instruction created by a macro expansion. This is passed
a pointer to the count of instructions created so far, an
expression, the name of the instruction to build, an operand format
string, and corresponding arguments. */
static void
-macro_build (char *place, int *counter, expressionS *ep, const char *name,
- const char *fmt, ...)
+macro_build (expressionS *ep, const char *name, const char *fmt, ...)
{
struct mips_cl_insn insn;
bfd_reloc_code_real_type r[3];
@@ -2834,32 +2982,9 @@ macro_build (char *place, int *counter, expressionS *ep, const char *name,
va_start (args, fmt);
- /*
- * If the macro is about to expand into a second instruction,
- * print a warning if needed. We need to pass ip as a parameter
- * to generate a better warning message here...
- */
- if (mips_opts.warn_about_macros && place == NULL && *counter == 1)
- as_warn (_("Macro instruction expanded into multiple instructions"));
-
- /*
- * If the macro is about to expand into a second instruction,
- * and it is in a delay slot, print a warning.
- */
- if (place == NULL
- && *counter == 1
- && mips_opts.noreorder
- && (prev_prev_insn.insn_mo->pinfo
- & (INSN_UNCOND_BRANCH_DELAY | INSN_COND_BRANCH_DELAY
- | INSN_COND_BRANCH_LIKELY)) != 0)
- as_warn (_("Macro instruction expanded into multiple instructions in a branch delay slot"));
-
- if (place == NULL)
- ++*counter; /* bump instruction counter */
-
if (mips_opts.mips16)
{
- mips16_macro_build (place, counter, ep, name, fmt, args);
+ mips16_macro_build (ep, name, fmt, args);
va_end (args);
return;
}
@@ -3073,12 +3198,11 @@ macro_build (char *place, int *counter, expressionS *ep, const char *name,
va_end (args);
assert (*r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
- append_insn (place, &insn, ep, r);
+ append_insn (&insn, ep, r);
}
static void
-mips16_macro_build (char *place, int *counter ATTRIBUTE_UNUSED,
- expressionS *ep, const char *name, const char *fmt,
+mips16_macro_build (expressionS *ep, const char *name, const char *fmt,
va_list args)
{
struct mips_cl_insn insn;
@@ -3195,7 +3319,7 @@ mips16_macro_build (char *place, int *counter ATTRIBUTE_UNUSED,
assert (*r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
- append_insn (place, &insn, ep, r);
+ append_insn (&insn, ep, r);
}
/*
@@ -3203,7 +3327,7 @@ mips16_macro_build (char *place, int *counter ATTRIBUTE_UNUSED,
* function. This occurs in NewABI PIC code.
*/
static void
-macro_build_jalr (int icnt, expressionS *ep)
+macro_build_jalr (expressionS *ep)
{
char *f = NULL;
@@ -3212,7 +3336,7 @@ macro_build_jalr (int icnt, expressionS *ep)
frag_grow (8);
f = frag_more (0);
}
- macro_build (NULL, &icnt, NULL, "jalr", "d,s", RA, PIC_CALL_REG);
+ macro_build (NULL, "jalr", "d,s", RA, PIC_CALL_REG);
if (HAVE_NEWABI)
fix_new_exp (frag_now, f - frag_now->fr_literal,
4, ep, FALSE, BFD_RELOC_MIPS_JALR);
@@ -3222,7 +3346,7 @@ macro_build_jalr (int icnt, expressionS *ep)
* Generate a "lui" instruction.
*/
static void
-macro_build_lui (char *place, int *counter, expressionS *ep, int regnum)
+macro_build_lui (expressionS *ep, int regnum)
{
expressionS high_expr;
struct mips_cl_insn insn;
@@ -3233,13 +3357,7 @@ macro_build_lui (char *place, int *counter, expressionS *ep, int regnum)
assert (! mips_opts.mips16);
- if (place == NULL)
- high_expr = *ep;
- else
- {
- high_expr.X_op = O_constant;
- high_expr.X_add_number = ep->X_add_number;
- }
+ high_expr = *ep;
if (high_expr.X_op == O_constant)
{
@@ -3258,17 +3376,6 @@ macro_build_lui (char *place, int *counter, expressionS *ep, int regnum)
*r = BFD_RELOC_HI16_S;
}
- /*
- * If the macro is about to expand into a second instruction,
- * print a warning if needed. We need to pass ip as a parameter
- * to generate a better warning message here...
- */
- if (mips_opts.warn_about_macros && place == NULL && *counter == 1)
- as_warn (_("Macro instruction expanded into multiple instructions"));
-
- if (place == NULL)
- ++*counter; /* bump instruction counter */
-
insn.insn_mo = (struct mips_opcode *) hash_find (op_hash, name);
assert (insn.insn_mo);
assert (strcmp (name, insn.insn_mo->name) == 0);
@@ -3278,18 +3385,18 @@ macro_build_lui (char *place, int *counter, expressionS *ep, int regnum)
if (*r == BFD_RELOC_UNUSED)
{
insn.insn_opcode |= high_expr.X_add_number;
- append_insn (place, &insn, NULL, r);
+ append_insn (&insn, NULL, r);
}
else
- append_insn (place, &insn, &high_expr, r);
+ append_insn (&insn, &high_expr, r);
}
/* Generate a sequence of instructions to do a load or store from a constant
offset off of a base register (breg) into/from a target register (treg),
using AT if necessary. */
static void
-macro_build_ldst_constoffset (char *place, int *counter, expressionS *ep,
- const char *op, int treg, int breg, int dbl)
+macro_build_ldst_constoffset (expressionS *ep, const char *op,
+ int treg, int breg, int dbl)
{
assert (ep->X_op == O_constant);
@@ -3311,8 +3418,7 @@ macro_build_ldst_constoffset (char *place, int *counter, expressionS *ep,
if (IS_SEXT_16BIT_NUM(ep->X_add_number))
{
/* Signed 16-bit offset will fit in the op. Easy! */
- macro_build (place, counter, ep, op, "t,o(b)", treg, BFD_RELOC_LO16,
- breg);
+ macro_build (ep, op, "t,o(b)", treg, BFD_RELOC_LO16, breg);
}
else
{
@@ -3321,15 +3427,9 @@ macro_build_ldst_constoffset (char *place, int *counter, expressionS *ep,
addu $tempreg,$tempreg,$breg
<op> $treg,const_lo($tempreg) (BFD_RELOC_LO16)
to handle the complete offset. */
- macro_build_lui (place, counter, ep, AT);
- if (place != NULL)
- place += 4;
- macro_build (place, counter, NULL, ADDRESS_ADD_INSN, "d,v,t", AT, AT,
- breg);
- if (place != NULL)
- place += 4;
- macro_build (place, counter, ep, op, "t,o(b)", treg, BFD_RELOC_LO16,
- AT);
+ macro_build_lui (ep, AT);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, AT, breg);
+ macro_build (ep, op, "t,o(b)", treg, BFD_RELOC_LO16, AT);
if (mips_opts.noat)
as_warn (_("Macro used $at after \".set noat\""));
@@ -3341,18 +3441,17 @@ macro_build_ldst_constoffset (char *place, int *counter, expressionS *ep,
* if reg is less than the immediate expression.
*/
static void
-set_at (int *counter, int reg, int unsignedp)
+set_at (int reg, int unsignedp)
{
if (imm_expr.X_op == O_constant
&& imm_expr.X_add_number >= -0x8000
&& imm_expr.X_add_number < 0x8000)
- macro_build (NULL, counter, &imm_expr, unsignedp ? "sltiu" : "slti",
- "t,r,j", AT, reg, BFD_RELOC_LO16);
+ macro_build (&imm_expr, unsignedp ? "sltiu" : "slti", "t,r,j",
+ AT, reg, BFD_RELOC_LO16);
else
{
- load_register (counter, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build (NULL, counter, NULL, unsignedp ? "sltu" : "slt",
- "d,v,t", AT, reg, AT);
+ load_register (AT, &imm_expr, HAVE_64BIT_GPRS);
+ macro_build (NULL, unsignedp ? "sltu" : "slt", "d,v,t", AT, reg, AT);
}
}
@@ -3458,7 +3557,7 @@ check_absolute_expr (struct mips_cl_insn *ip, expressionS *ex)
* an absolute expression value into a register.
*/
static void
-load_register (int *counter, int reg, expressionS *ep, int dbl)
+load_register (int reg, expressionS *ep, int dbl)
{
int freg;
expressionS hi32, lo32;
@@ -3483,25 +3582,22 @@ load_register (int *counter, int reg, expressionS *ep, int dbl)
/* We can handle 16 bit signed values with an addiu to
$zero. No need to ever use daddiu here, since $zero and
the result are always correct in 32 bit mode. */
- macro_build (NULL, counter, ep, "addiu", "t,r,j", reg, 0,
- BFD_RELOC_LO16);
+ macro_build (ep, "addiu", "t,r,j", reg, 0, BFD_RELOC_LO16);
return;
}
else if (ep->X_add_number >= 0 && ep->X_add_number < 0x10000)
{
/* We can handle 16 bit unsigned values with an ori to
$zero. */
- macro_build (NULL, counter, ep, "ori", "t,r,i", reg, 0,
- BFD_RELOC_LO16);
+ macro_build (ep, "ori", "t,r,i", reg, 0, BFD_RELOC_LO16);
return;
}
else if ((IS_SEXT_32BIT_NUM (ep->X_add_number)))
{
/* 32 bit values require an lui. */
- macro_build (NULL, counter, ep, "lui", "t,u", reg, BFD_RELOC_HI16);
+ macro_build (ep, "lui", "t,u", reg, BFD_RELOC_HI16);
if ((ep->X_add_number & 0xffff) != 0)
- macro_build (NULL, counter, ep, "ori", "t,r,i", reg, reg,
- BFD_RELOC_LO16);
+ macro_build (ep, "ori", "t,r,i", reg, reg, BFD_RELOC_LO16);
return;
}
}
@@ -3512,8 +3608,7 @@ load_register (int *counter, int reg, expressionS *ep, int dbl)
{
as_bad (_("Number (0x%lx) larger than 32 bits"),
(unsigned long) ep->X_add_number);
- macro_build (NULL, counter, ep, "addiu", "t,r,j", reg, 0,
- BFD_RELOC_LO16);
+ macro_build (ep, "addiu", "t,r,j", reg, 0, BFD_RELOC_LO16);
return;
}
@@ -3550,17 +3645,14 @@ load_register (int *counter, int reg, expressionS *ep, int dbl)
{
if ((lo32.X_add_number & 0xffff8000) == 0xffff8000)
{
- macro_build (NULL, counter, &lo32, "addiu", "t,r,j", reg, 0,
- BFD_RELOC_LO16);
+ macro_build (&lo32, "addiu", "t,r,j", reg, 0, BFD_RELOC_LO16);
return;
}
if (lo32.X_add_number & 0x80000000)
{
- macro_build (NULL, counter, &lo32, "lui", "t,u", reg,
- BFD_RELOC_HI16);
+ macro_build (&lo32, "lui", "t,u", reg, BFD_RELOC_HI16);
if (lo32.X_add_number & 0xffff)
- macro_build (NULL, counter, &lo32, "ori", "t,r,i", reg, reg,
- BFD_RELOC_LO16);
+ macro_build (&lo32, "ori", "t,r,i", reg, reg, BFD_RELOC_LO16);
return;
}
}
@@ -3594,12 +3686,9 @@ load_register (int *counter, int reg, expressionS *ep, int dbl)
| (lo32.X_add_number >> shift));
else
tmp.X_add_number = hi32.X_add_number >> (shift - 32);
- macro_build (NULL, counter, &tmp, "ori", "t,r,i", reg, 0,
- BFD_RELOC_LO16);
- macro_build (NULL, counter, NULL,
- (shift >= 32) ? "dsll32" : "dsll",
- "d,w,<", reg, reg,
- (shift >= 32) ? shift - 32 : shift);
+ macro_build (&tmp, "ori", "t,r,i", reg, 0, BFD_RELOC_LO16);
+ macro_build (NULL, (shift >= 32) ? "dsll32" : "dsll", "d,w,<",
+ reg, reg, (shift >= 32) ? shift - 32 : shift);
return;
}
++shift;
@@ -3646,20 +3735,15 @@ load_register (int *counter, int reg, expressionS *ep, int dbl)
ones. */
tmp.X_op = O_constant;
tmp.X_add_number = (offsetT) -1;
- macro_build (NULL, counter, &tmp, "addiu", "t,r,j", reg, 0,
- BFD_RELOC_LO16);
+ macro_build (&tmp, "addiu", "t,r,j", reg, 0, BFD_RELOC_LO16);
if (bit != 0)
{
bit += shift;
- macro_build (NULL, counter, NULL,
- (bit >= 32) ? "dsll32" : "dsll",
- "d,w,<", reg, reg,
- (bit >= 32) ? bit - 32 : bit);
+ macro_build (NULL, (bit >= 32) ? "dsll32" : "dsll", "d,w,<",
+ reg, reg, (bit >= 32) ? bit - 32 : bit);
}
- macro_build (NULL, counter, NULL,
- (shift >= 32) ? "dsrl32" : "dsrl",
- "d,w,<", reg, reg,
- (shift >= 32) ? shift - 32 : shift);
+ macro_build (NULL, (shift >= 32) ? "dsrl32" : "dsrl", "d,w,<",
+ reg, reg, (shift >= 32) ? shift - 32 : shift);
return;
}
}
@@ -3668,14 +3752,14 @@ load_register (int *counter, int reg, expressionS *ep, int dbl)
generally get better code when we load a sign extended value. */
if ((hi32.X_add_number & 0x80000000) != 0)
hi32.X_add_number |= ~(offsetT) 0xffffffff;
- load_register (counter, reg, &hi32, 0);
+ load_register (reg, &hi32, 0);
freg = reg;
}
if ((lo32.X_add_number & 0xffff0000) == 0)
{
if (freg != 0)
{
- macro_build (NULL, counter, NULL, "dsll32", "d,w,<", reg, freg, 0);
+ macro_build (NULL, "dsll32", "d,w,<", reg, freg, 0);
freg = reg;
}
}
@@ -3685,36 +3769,31 @@ load_register (int *counter, int reg, expressionS *ep, int dbl)
if ((freg == 0) && (lo32.X_add_number == (offsetT) 0xffffffff))
{
- macro_build (NULL, counter, &lo32, "lui", "t,u", reg,
- BFD_RELOC_HI16);
- macro_build (NULL, counter, NULL, "dsrl32", "d,w,<", reg, reg, 0);
+ macro_build (&lo32, "lui", "t,u", reg, BFD_RELOC_HI16);
+ macro_build (NULL, "dsrl32", "d,w,<", reg, reg, 0);
return;
}
if (freg != 0)
{
- macro_build (NULL, counter, NULL, "dsll", "d,w,<", reg, freg, 16);
+ macro_build (NULL, "dsll", "d,w,<", reg, freg, 16);
freg = reg;
}
mid16 = lo32;
mid16.X_add_number >>= 16;
- macro_build (NULL, counter, &mid16, "ori", "t,r,i", reg, freg,
- BFD_RELOC_LO16);
- macro_build (NULL, counter, NULL, "dsll", "d,w,<", reg, reg, 16);
+ macro_build (&mid16, "ori", "t,r,i", reg, freg, BFD_RELOC_LO16);
+ macro_build (NULL, "dsll", "d,w,<", reg, reg, 16);
freg = reg;
}
if ((lo32.X_add_number & 0xffff) != 0)
- macro_build (NULL, counter, &lo32, "ori", "t,r,i", reg, freg,
- BFD_RELOC_LO16);
+ macro_build (&lo32, "ori", "t,r,i", reg, freg, BFD_RELOC_LO16);
}
/* Load an address into a register. */
static void
-load_address (int *counter, int reg, expressionS *ep, int *used_at)
+load_address (int reg, expressionS *ep, int *used_at)
{
- char *p = NULL;
-
if (ep->X_op != O_constant
&& ep->X_op != O_symbol)
{
@@ -3724,7 +3803,7 @@ load_address (int *counter, int reg, expressionS *ep, int *used_at)
if (ep->X_op == O_constant)
{
- load_register (counter, reg, ep, HAVE_64BIT_ADDRESSES);
+ load_register (reg, ep, HAVE_64BIT_ADDRESSES);
return;
}
@@ -3756,35 +3835,30 @@ load_address (int *counter, int reg, expressionS *ep, int *used_at)
*/
if (HAVE_64BIT_ADDRESSES)
{
- /* We don't do GP optimization for now because RELAX_ENCODE can't
- hold the data for such large chunks. */
+ /* ??? We don't provide a GP-relative alternative for these macros.
+ It used not to be possible with the original relaxation code,
+ but it could be done now. */
if (*used_at == 0 && ! mips_opts.noat)
{
- macro_build (p, counter, ep, "lui", "t,u",
- reg, BFD_RELOC_MIPS_HIGHEST);
- macro_build (p, counter, ep, "lui", "t,u",
- AT, BFD_RELOC_HI16_S);
- macro_build (p, counter, ep, "daddiu", "t,r,j",
- reg, reg, BFD_RELOC_MIPS_HIGHER);
- macro_build (p, counter, ep, "daddiu", "t,r,j",
- AT, AT, BFD_RELOC_LO16);
- macro_build (p, counter, NULL, "dsll32", "d,w,<", reg, reg, 0);
- macro_build (p, counter, NULL, "daddu", "d,v,t", reg, reg, AT);
+ macro_build (ep, "lui", "t,u", reg, BFD_RELOC_MIPS_HIGHEST);
+ macro_build (ep, "lui", "t,u", AT, BFD_RELOC_HI16_S);
+ macro_build (ep, "daddiu", "t,r,j", reg, reg,
+ BFD_RELOC_MIPS_HIGHER);
+ macro_build (ep, "daddiu", "t,r,j", AT, AT, BFD_RELOC_LO16);
+ macro_build (NULL, "dsll32", "d,w,<", reg, reg, 0);
+ macro_build (NULL, "daddu", "d,v,t", reg, reg, AT);
*used_at = 1;
}
else
{
- macro_build (p, counter, ep, "lui", "t,u",
- reg, BFD_RELOC_MIPS_HIGHEST);
- macro_build (p, counter, ep, "daddiu", "t,r,j",
- reg, reg, BFD_RELOC_MIPS_HIGHER);
- macro_build (p, counter, NULL, "dsll", "d,w,<", reg, reg, 16);
- macro_build (p, counter, ep, "daddiu", "t,r,j",
- reg, reg, BFD_RELOC_HI16_S);
- macro_build (p, counter, NULL, "dsll", "d,w,<", reg, reg, 16);
- macro_build (p, counter, ep, "daddiu", "t,r,j",
- reg, reg, BFD_RELOC_LO16);
+ macro_build (ep, "lui", "t,u", reg, BFD_RELOC_MIPS_HIGHEST);
+ macro_build (ep, "daddiu", "t,r,j", reg, reg,
+ BFD_RELOC_MIPS_HIGHER);
+ macro_build (NULL, "dsll", "d,w,<", reg, reg, 16);
+ macro_build (ep, "daddiu", "t,r,j", reg, reg, BFD_RELOC_HI16_S);
+ macro_build (NULL, "dsll", "d,w,<", reg, reg, 16);
+ macro_build (ep, "daddiu", "t,r,j", reg, reg, BFD_RELOC_LO16);
}
}
else
@@ -3792,19 +3866,16 @@ load_address (int *counter, int reg, expressionS *ep, int *used_at)
if ((valueT) ep->X_add_number <= MAX_GPREL_OFFSET
&& ! nopic_need_relax (ep->X_add_symbol, 1))
{
- frag_grow (20);
- macro_build (NULL, counter, ep, ADDRESS_ADDI_INSN, "t,r,j", reg,
+ relax_start (ep->X_add_symbol);
+ macro_build (ep, ADDRESS_ADDI_INSN, "t,r,j", reg,
mips_gp_register, BFD_RELOC_GPREL16);
- p = frag_var (rs_machine_dependent, 8, 0,
- RELAX_ENCODE (4, 8, 0, 4, 0,
- mips_opts.warn_about_macros),
- ep->X_add_symbol, 0, NULL);
+ relax_switch ();
}
- macro_build_lui (p, counter, ep, reg);
- if (p != NULL)
- p += 4;
- macro_build (p, counter, ep, ADDRESS_ADDI_INSN, "t,r,j", reg, reg,
- BFD_RELOC_LO16);
+ macro_build_lui (ep, reg);
+ macro_build (ep, ADDRESS_ADDI_INSN, "t,r,j",
+ reg, reg, BFD_RELOC_LO16);
+ if (mips_relax.sequence)
+ relax_end ();
}
}
else if (mips_pic == SVR4_PIC && ! mips_big_got)
@@ -3825,59 +3896,45 @@ load_address (int *counter, int reg, expressionS *ep, int *used_at)
offset, in which case cst must be added separately. */
if (HAVE_NEWABI)
{
- frag_grow (12);
-
if (ep->X_add_number)
{
- frag_now->tc_frag_data.tc_fr_offset =
- ex.X_add_number = ep->X_add_number;
+ ex.X_add_number = ep->X_add_number;
ep->X_add_number = 0;
- macro_build (NULL, counter, ep, ADDRESS_LOAD_INSN, "t,o(b)",
- reg, BFD_RELOC_MIPS_GOT_DISP, mips_gp_register);
+ relax_start (ep->X_add_symbol);
+ macro_build (ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
+ BFD_RELOC_MIPS_GOT_DISP, mips_gp_register);
if (ex.X_add_number < -0x8000 || ex.X_add_number >= 0x8000)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
ex.X_op = O_constant;
- macro_build (NULL, counter, &ex, ADDRESS_ADDI_INSN, "t,r,j",
+ macro_build (&ex, ADDRESS_ADDI_INSN, "t,r,j",
reg, reg, BFD_RELOC_LO16);
- p = frag_var (rs_machine_dependent, 8, 0,
- RELAX_ENCODE (8, 4, 0, 0, 0,
- mips_opts.warn_about_macros),
- ep->X_add_symbol, 0, NULL);
ep->X_add_number = ex.X_add_number;
+ relax_switch ();
}
-
- macro_build (p, counter, ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
+ macro_build (ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
BFD_RELOC_MIPS_GOT_DISP, mips_gp_register);
-
- if (! p)
- {
- /* To avoid confusion in tc_gen_reloc, we must ensure
- that this does not become a variant frag. */
- frag_wane (frag_now);
- frag_new (0);
- }
+ if (mips_relax.sequence)
+ relax_end ();
}
else
{
ex.X_add_number = ep->X_add_number;
ep->X_add_number = 0;
- frag_grow (20);
- macro_build (NULL, counter, ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
- BFD_RELOC_MIPS_GOT16,
- mips_gp_register);
- macro_build (NULL, counter, NULL, "nop", "");
- p = frag_var (rs_machine_dependent, 4, 0,
- RELAX_ENCODE (0, 4, -8, 0, 0, mips_opts.warn_about_macros),
- ep->X_add_symbol, 0, NULL);
- macro_build (p, counter, ep, ADDRESS_ADDI_INSN, "t,r,j", reg, reg,
+ macro_build (ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
+ BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ macro_build (NULL, "nop", "");
+ relax_start (ep->X_add_symbol);
+ relax_switch ();
+ macro_build (ep, ADDRESS_ADDI_INSN, "t,r,j", reg, reg,
BFD_RELOC_LO16);
+ relax_end ();
if (ex.X_add_number != 0)
{
if (ex.X_add_number < -0x8000 || ex.X_add_number >= 0x8000)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
ex.X_op = O_constant;
- macro_build (NULL, counter, &ex, ADDRESS_ADDI_INSN, "t,r,j",
+ macro_build (&ex, ADDRESS_ADDI_INSN, "t,r,j",
reg, reg, BFD_RELOC_LO16);
}
}
@@ -3885,7 +3942,6 @@ load_address (int *counter, int reg, expressionS *ep, int *used_at)
else if (mips_pic == SVR4_PIC)
{
expressionS ex;
- int off;
/* This is the large GOT case. If this is a reference to an
external symbol, we want
@@ -3905,79 +3961,64 @@ load_address (int *counter, int reg, expressionS *ep, int *used_at)
*/
if (HAVE_NEWABI)
{
- frag_grow (24);
-
- frag_now->tc_frag_data.tc_fr_offset =
- ex.X_add_number = ep->X_add_number;
+ ex.X_add_number = ep->X_add_number;
ep->X_add_number = 0;
- macro_build (NULL, counter, ep, "lui", "t,u", reg,
- BFD_RELOC_MIPS_GOT_HI16);
- macro_build (NULL, counter, NULL, ADDRESS_ADD_INSN, "d,v,t", reg,
- reg, mips_gp_register);
- macro_build (NULL, counter, ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
- BFD_RELOC_MIPS_GOT_LO16, reg);
+ relax_start (ep->X_add_symbol);
+ macro_build (ep, "lui", "t,u", reg, BFD_RELOC_MIPS_GOT_HI16);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
+ reg, reg, mips_gp_register);
+ macro_build (ep, ADDRESS_LOAD_INSN, "t,o(b)",
+ reg, BFD_RELOC_MIPS_GOT_LO16, reg);
if (ex.X_add_number < -0x8000 || ex.X_add_number >= 0x8000)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
else if (ex.X_add_number)
{
ex.X_op = O_constant;
- macro_build (NULL, counter, &ex, ADDRESS_ADDI_INSN, "t,r,j",
- reg, reg, BFD_RELOC_LO16);
+ macro_build (&ex, ADDRESS_ADDI_INSN, "t,r,j", reg, reg,
+ BFD_RELOC_LO16);
}
ep->X_add_number = ex.X_add_number;
- p = frag_var (rs_machine_dependent, 8, 0,
- RELAX_ENCODE (ex.X_add_number ? 16 : 12, 8, 0, 4, 0,
- mips_opts.warn_about_macros),
- ep->X_add_symbol, 0, NULL);
- macro_build (p, counter, ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
+ relax_switch ();
+ macro_build (ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
BFD_RELOC_MIPS_GOT_PAGE, mips_gp_register);
- macro_build (p + 4, counter, ep, ADDRESS_ADDI_INSN, "t,r,j", reg,
- reg, BFD_RELOC_MIPS_GOT_OFST);
+ macro_build (ep, ADDRESS_ADDI_INSN, "t,r,j", reg, reg,
+ BFD_RELOC_MIPS_GOT_OFST);
+ relax_end ();
}
else
{
ex.X_add_number = ep->X_add_number;
ep->X_add_number = 0;
+ relax_start (ep->X_add_symbol);
+ macro_build (ep, "lui", "t,u", reg, BFD_RELOC_MIPS_GOT_HI16);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
+ reg, reg, mips_gp_register);
+ macro_build (ep, ADDRESS_LOAD_INSN, "t,o(b)",
+ reg, BFD_RELOC_MIPS_GOT_LO16, reg);
+ relax_switch ();
if (reg_needs_delay (mips_gp_register))
- off = 4;
- else
- off = 0;
- frag_grow (32);
- macro_build (NULL, counter, ep, "lui", "t,u", reg,
- BFD_RELOC_MIPS_GOT_HI16);
- macro_build (NULL, counter, NULL, ADDRESS_ADD_INSN, "d,v,t", reg,
- reg, mips_gp_register);
- macro_build (NULL, counter, ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
- BFD_RELOC_MIPS_GOT_LO16, reg);
- p = frag_var (rs_machine_dependent, 12 + off, 0,
- RELAX_ENCODE (12, 12 + off, off, 8 + off, 0,
- mips_opts.warn_about_macros),
- ep->X_add_symbol, 0, NULL);
- if (off > 0)
{
/* We need a nop before loading from $gp. This special
check is required because the lui which starts the main
instruction stream does not refer to $gp, and so will not
insert the nop which may be required. */
- macro_build (p, counter, NULL, "nop", "");
- p += 4;
+ macro_build (NULL, "nop", "");
}
- macro_build (p, counter, ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
+ macro_build (ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
BFD_RELOC_MIPS_GOT16, mips_gp_register);
- p += 4;
- macro_build (p, counter, NULL, "nop", "");
- p += 4;
- macro_build (p, counter, ep, ADDRESS_ADDI_INSN, "t,r,j", reg, reg,
+ macro_build (NULL, "nop", "");
+ macro_build (ep, ADDRESS_ADDI_INSN, "t,r,j", reg, reg,
BFD_RELOC_LO16);
+ relax_end ();
if (ex.X_add_number != 0)
{
if (ex.X_add_number < -0x8000 || ex.X_add_number >= 0x8000)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
ex.X_op = O_constant;
- macro_build (NULL, counter, &ex, ADDRESS_ADDI_INSN, "t,r,j",
- reg, reg, BFD_RELOC_LO16);
+ macro_build (&ex, ADDRESS_ADDI_INSN, "t,r,j", reg, reg,
+ BFD_RELOC_LO16);
}
}
}
@@ -3986,8 +4027,8 @@ load_address (int *counter, int reg, expressionS *ep, int *used_at)
/* We always do
addiu $reg,$gp,<sym> (BFD_RELOC_GPREL16)
*/
- macro_build (NULL, counter, ep, ADDRESS_ADDI_INSN, "t,r,j", reg,
- mips_gp_register, BFD_RELOC_GPREL16);
+ macro_build (ep, ADDRESS_ADDI_INSN, "t,r,j",
+ reg, mips_gp_register, BFD_RELOC_GPREL16);
}
else
abort ();
@@ -3996,10 +4037,85 @@ load_address (int *counter, int reg, expressionS *ep, int *used_at)
/* Move the contents of register SOURCE into register DEST. */
static void
-move_register (int *counter, int dest, int source)
+move_register (int dest, int source)
+{
+ macro_build (NULL, HAVE_32BIT_GPRS ? "addu" : "daddu", "d,v,t",
+ dest, source, 0);
+}
+
+/* Emit an SVR4 PIC sequence to load address LOCAL into DEST, where
+ LOCAL is the sum of a symbol and a 16-bit or 32-bit displacement.
+ The two alternatives are:
+
+ Global symbol Local sybmol
+ ------------- ------------
+ lw DEST,%got(SYMBOL) lw DEST,%got(SYMBOL + OFFSET)
+ ... ...
+ addiu DEST,DEST,OFFSET addiu DEST,DEST,%lo(SYMBOL + OFFSET)
+
+ load_got_offset emits the first instruction and add_got_offset
+ emits the second for a 16-bit offset or add_got_offset_hilo emits
+ a sequence to add a 32-bit offset using a scratch register. */
+
+static void
+load_got_offset (int dest, expressionS *local)
+{
+ expressionS global;
+
+ global = *local;
+ global.X_add_number = 0;
+
+ relax_start (local->X_add_symbol);
+ macro_build (&global, ADDRESS_LOAD_INSN, "t,o(b)", dest,
+ BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ relax_switch ();
+ macro_build (local, ADDRESS_LOAD_INSN, "t,o(b)", dest,
+ BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ relax_end ();
+}
+
+static void
+add_got_offset (int dest, expressionS *local)
{
- macro_build (NULL, counter, NULL, HAVE_32BIT_GPRS ? "addu" : "daddu",
- "d,v,t", dest, source, 0);
+ expressionS global;
+
+ global.X_op = O_constant;
+ global.X_op_symbol = NULL;
+ global.X_add_symbol = NULL;
+ global.X_add_number = local->X_add_number;
+
+ relax_start (local->X_add_symbol);
+ macro_build (&global, ADDRESS_ADDI_INSN, "t,r,j",
+ dest, dest, BFD_RELOC_LO16);
+ relax_switch ();
+ macro_build (local, ADDRESS_ADDI_INSN, "t,r,j", dest, dest, BFD_RELOC_LO16);
+ relax_end ();
+}
+
+static void
+add_got_offset_hilo (int dest, expressionS *local, int tmp)
+{
+ expressionS global;
+ int hold_mips_optimize;
+
+ global.X_op = O_constant;
+ global.X_op_symbol = NULL;
+ global.X_add_symbol = NULL;
+ global.X_add_number = local->X_add_number;
+
+ relax_start (local->X_add_symbol);
+ load_register (tmp, &global, HAVE_64BIT_ADDRESSES);
+ relax_switch ();
+ /* Set mips_optimize around the lui instruction to avoid
+ inserting an unnecessary nop after the lw. */
+ hold_mips_optimize = mips_optimize;
+ mips_optimize = 2;
+ macro_build_lui (&global, tmp);
+ mips_optimize = hold_mips_optimize;
+ macro_build (local, ADDRESS_ADDI_INSN, "t,r,j", tmp, tmp, BFD_RELOC_LO16);
+ relax_end ();
+
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", dest, dest, tmp);
}
/*
@@ -4026,7 +4142,6 @@ macro (struct mips_cl_insn *ip)
register int treg, sreg, dreg, breg;
int tempreg;
int mask;
- int icnt = 0;
int used_at = 0;
expressionS expr1;
const char *s;
@@ -4038,8 +4153,8 @@ macro (struct mips_cl_insn *ip)
int lr = 0;
int imm = 0;
int call = 0;
- offsetT maxnum;
int off;
+ offsetT maxnum;
bfd_reloc_code_real_type r;
int hold_mips_optimize;
@@ -4055,30 +4170,6 @@ macro (struct mips_cl_insn *ip)
expr1.X_add_symbol = NULL;
expr1.X_add_number = 1;
- /* Unmatched fixups should not be put in the same frag as a relaxable
- macro. For example, suppose we have:
-
- lui $4,%hi(l1) # 1
- la $5,l2 # 2
- addiu $4,$4,%lo(l1) # 3
-
- If instructions 1 and 2 were put in the same frag, md_frob_file would
- move the fixup for #1 after the fixups for the "unrelaxed" version of
- #2. This would confuse tc_gen_reloc, which expects the relocations
- for #2 to be the last for that frag.
-
- Also, if tc_gen_reloc sees certain relocations in a variant frag,
- it assumes that they belong to a relaxable macro. We mustn't put
- other uses of such relocations into a variant frag.
-
- To avoid both problems, finish the current frag it contains a
- %reloc() operator. The macro then goes into a new frag. */
- if (prev_reloc_op_frag == frag_now)
- {
- frag_wane (frag_now);
- frag_new (0);
- }
-
switch (mask)
{
case M_DABS:
@@ -4094,13 +4185,12 @@ macro (struct mips_cl_insn *ip)
mips_any_noreorder = 1;
expr1.X_add_number = 8;
- macro_build (NULL, &icnt, &expr1, "bgez", "s,p", sreg);
+ macro_build (&expr1, "bgez", "s,p", sreg);
if (dreg == sreg)
- macro_build (NULL, &icnt, NULL, "nop", "", 0);
+ macro_build (NULL, "nop", "", 0);
else
- move_register (&icnt, dreg, sreg);
- macro_build (NULL, &icnt, NULL, dbl ? "dsub" : "sub", "d,v,t", dreg, 0,
- sreg);
+ move_register (dreg, sreg);
+ macro_build (NULL, dbl ? "dsub" : "sub", "d,v,t", dreg, 0, sreg);
--mips_opts.noreorder;
return;
@@ -4127,12 +4217,11 @@ macro (struct mips_cl_insn *ip)
&& imm_expr.X_add_number >= -0x8000
&& imm_expr.X_add_number < 0x8000)
{
- macro_build (NULL, &icnt, &imm_expr, s, "t,r,j", treg, sreg,
- BFD_RELOC_LO16);
+ macro_build (&imm_expr, s, "t,r,j", treg, sreg, BFD_RELOC_LO16);
return;
}
- load_register (&icnt, AT, &imm_expr, dbl);
- macro_build (NULL, &icnt, NULL, s2, "d,v,t", treg, sreg, AT);
+ load_register (AT, &imm_expr, dbl);
+ macro_build (NULL, s2, "d,v,t", treg, sreg, AT);
break;
case M_AND_I:
@@ -4156,19 +4245,18 @@ macro (struct mips_cl_insn *ip)
&& imm_expr.X_add_number < 0x10000)
{
if (mask != M_NOR_I)
- macro_build (NULL, &icnt, &imm_expr, s, "t,r,i", treg, sreg,
- BFD_RELOC_LO16);
+ macro_build (&imm_expr, s, "t,r,i", treg, sreg, BFD_RELOC_LO16);
else
{
- macro_build (NULL, &icnt, &imm_expr, "ori", "t,r,i", treg, sreg,
- BFD_RELOC_LO16);
- macro_build (NULL, &icnt, NULL, "nor", "d,v,t", treg, treg, 0);
+ macro_build (&imm_expr, "ori", "t,r,i",
+ treg, sreg, BFD_RELOC_LO16);
+ macro_build (NULL, "nor", "d,v,t", treg, treg, 0);
}
return;
}
- load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build (NULL, &icnt, NULL, s2, "d,v,t", treg, sreg, AT);
+ load_register (AT, &imm_expr, HAVE_64BIT_GPRS);
+ macro_build (NULL, s2, "d,v,t", treg, sreg, AT);
break;
case M_BEQ_I:
@@ -4187,11 +4275,11 @@ macro (struct mips_cl_insn *ip)
beq_i:
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
{
- macro_build (NULL, &icnt, &offset_expr, s, "s,t,p", sreg, 0);
+ macro_build (&offset_expr, s, "s,t,p", sreg, 0);
return;
}
- load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build (NULL, &icnt, &offset_expr, s, "s,t,p", sreg, AT);
+ load_register (AT, &imm_expr, HAVE_64BIT_GPRS);
+ macro_build (&offset_expr, s, "s,t,p", sreg, AT);
break;
case M_BGEL:
@@ -4199,19 +4287,16 @@ macro (struct mips_cl_insn *ip)
case M_BGE:
if (treg == 0)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "bgezl" : "bgez",
- "s,p", sreg);
+ macro_build (&offset_expr, likely ? "bgezl" : "bgez", "s,p", sreg);
return;
}
if (sreg == 0)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "blezl" : "blez",
- "s,p", treg);
+ macro_build (&offset_expr, likely ? "blezl" : "blez", "s,p", treg);
return;
}
- macro_build (NULL, &icnt, NULL, "slt", "d,v,t", AT, sreg, treg);
- macro_build (NULL, &icnt, &offset_expr, likely ? "beql" : "beq",
- "s,t,p", AT, 0);
+ macro_build (NULL, "slt", "d,v,t", AT, sreg, treg);
+ macro_build (&offset_expr, likely ? "beql" : "beq", "s,t,p", AT, 0);
break;
case M_BGTL_I:
@@ -4233,9 +4318,9 @@ macro (struct mips_cl_insn *ip)
do_false:
/* result is always false */
if (! likely)
- macro_build (NULL, &icnt, NULL, "nop", "", 0);
+ macro_build (NULL, "nop", "", 0);
else
- macro_build (NULL, &icnt, &offset_expr, "bnel", "s,t,p", 0, 0);
+ macro_build (&offset_expr, "bnel", "s,t,p", 0, 0);
return;
}
if (imm_expr.X_op != O_constant)
@@ -4248,14 +4333,12 @@ macro (struct mips_cl_insn *ip)
likely = 1;
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "bgezl" : "bgez",
- "s,p", sreg);
+ macro_build (&offset_expr, likely ? "bgezl" : "bgez", "s,p", sreg);
return;
}
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "bgtzl" : "bgtz",
- "s,p", sreg);
+ macro_build (&offset_expr, likely ? "bgtzl" : "bgtz", "s,p", sreg);
return;
}
maxnum = 0x7fffffff;
@@ -4274,12 +4357,11 @@ macro (struct mips_cl_insn *ip)
do_true:
/* result is always true */
as_warn (_("Branch %s is always true"), ip->insn_mo->name);
- macro_build (NULL, &icnt, &offset_expr, "b", "p");
+ macro_build (&offset_expr, "b", "p");
return;
}
- set_at (&icnt, sreg, 0);
- macro_build (NULL, &icnt, &offset_expr, likely ? "beql" : "beq",
- "s,t,p", AT, 0);
+ set_at (sreg, 0);
+ macro_build (&offset_expr, likely ? "beql" : "beq", "s,t,p", AT, 0);
break;
case M_BGEUL:
@@ -4289,13 +4371,12 @@ macro (struct mips_cl_insn *ip)
goto do_true;
if (sreg == 0)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "beql" : "beq",
+ macro_build (&offset_expr, likely ? "beql" : "beq",
"s,t,p", 0, treg);
return;
}
- macro_build (NULL, &icnt, NULL, "sltu", "d,v,t", AT, sreg, treg);
- macro_build (NULL, &icnt, &offset_expr, likely ? "beql" : "beq",
- "s,t,p", AT, 0);
+ macro_build (NULL, "sltu", "d,v,t", AT, sreg, treg);
+ macro_build (&offset_expr, likely ? "beql" : "beq", "s,t,p", AT, 0);
break;
case M_BGTUL_I:
@@ -4318,13 +4399,12 @@ macro (struct mips_cl_insn *ip)
goto do_true;
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "bnel" : "bne",
+ macro_build (&offset_expr, likely ? "bnel" : "bne",
"s,t,p", sreg, 0);
return;
}
- set_at (&icnt, sreg, 1);
- macro_build (NULL, &icnt, &offset_expr, likely ? "beql" : "beq",
- "s,t,p", AT, 0);
+ set_at (sreg, 1);
+ macro_build (&offset_expr, likely ? "beql" : "beq", "s,t,p", AT, 0);
break;
case M_BGTL:
@@ -4332,19 +4412,16 @@ macro (struct mips_cl_insn *ip)
case M_BGT:
if (treg == 0)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "bgtzl" : "bgtz",
- "s,p", sreg);
+ macro_build (&offset_expr, likely ? "bgtzl" : "bgtz", "s,p", sreg);
return;
}
if (sreg == 0)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "bltzl" : "bltz",
- "s,p", treg);
+ macro_build (&offset_expr, likely ? "bltzl" : "bltz", "s,p", treg);
return;
}
- macro_build (NULL, &icnt, NULL, "slt", "d,v,t", AT, treg, sreg);
- macro_build (NULL, &icnt, &offset_expr, likely ? "bnel" : "bne",
- "s,t,p", AT, 0);
+ macro_build (NULL, "slt", "d,v,t", AT, treg, sreg);
+ macro_build (&offset_expr, likely ? "bnel" : "bne", "s,t,p", AT, 0);
break;
case M_BGTUL:
@@ -4352,15 +4429,14 @@ macro (struct mips_cl_insn *ip)
case M_BGTU:
if (treg == 0)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "bnel" : "bne",
+ macro_build (&offset_expr, likely ? "bnel" : "bne",
"s,t,p", sreg, 0);
return;
}
if (sreg == 0)
goto do_false;
- macro_build (NULL, &icnt, NULL, "sltu", "d,v,t", AT, treg, sreg);
- macro_build (NULL, &icnt, &offset_expr, likely ? "bnel" : "bne",
- "s,t,p", AT, 0);
+ macro_build (NULL, "sltu", "d,v,t", AT, treg, sreg);
+ macro_build (&offset_expr, likely ? "bnel" : "bne", "s,t,p", AT, 0);
break;
case M_BLEL:
@@ -4368,19 +4444,16 @@ macro (struct mips_cl_insn *ip)
case M_BLE:
if (treg == 0)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "blezl" : "blez",
- "s,p", sreg);
+ macro_build (&offset_expr, likely ? "blezl" : "blez", "s,p", sreg);
return;
}
if (sreg == 0)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "bgezl" : "bgez",
- "s,p", treg);
+ macro_build (&offset_expr, likely ? "bgezl" : "bgez", "s,p", treg);
return;
}
- macro_build (NULL, &icnt, NULL, "slt", "d,v,t", AT, treg, sreg);
- macro_build (NULL, &icnt, &offset_expr, likely ? "beql" : "beq",
- "s,t,p", AT, 0);
+ macro_build (NULL, "slt", "d,v,t", AT, treg, sreg);
+ macro_build (&offset_expr, likely ? "beql" : "beq", "s,t,p", AT, 0);
break;
case M_BLEL_I:
@@ -4408,19 +4481,16 @@ macro (struct mips_cl_insn *ip)
likely = 1;
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "bltzl" : "bltz",
- "s,p", sreg);
+ macro_build (&offset_expr, likely ? "bltzl" : "bltz", "s,p", sreg);
return;
}
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "blezl" : "blez",
- "s,p", sreg);
+ macro_build (&offset_expr, likely ? "blezl" : "blez", "s,p", sreg);
return;
}
- set_at (&icnt, sreg, 0);
- macro_build (NULL, &icnt, &offset_expr, likely ? "bnel" : "bne",
- "s,t,p", AT, 0);
+ set_at (sreg, 0);
+ macro_build (&offset_expr, likely ? "bnel" : "bne", "s,t,p", AT, 0);
break;
case M_BLEUL:
@@ -4428,15 +4498,14 @@ macro (struct mips_cl_insn *ip)
case M_BLEU:
if (treg == 0)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "beql" : "beq",
+ macro_build (&offset_expr, likely ? "beql" : "beq",
"s,t,p", sreg, 0);
return;
}
if (sreg == 0)
goto do_true;
- macro_build (NULL, &icnt, NULL, "sltu", "d,v,t", AT, treg, sreg);
- macro_build (NULL, &icnt, &offset_expr, likely ? "beql" : "beq",
- "s,t,p", AT, 0);
+ macro_build (NULL, "sltu", "d,v,t", AT, treg, sreg);
+ macro_build (&offset_expr, likely ? "beql" : "beq", "s,t,p", AT, 0);
break;
case M_BLEUL_I:
@@ -4459,13 +4528,12 @@ macro (struct mips_cl_insn *ip)
goto do_false;
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "beql" : "beq",
+ macro_build (&offset_expr, likely ? "beql" : "beq",
"s,t,p", sreg, 0);
return;
}
- set_at (&icnt, sreg, 1);
- macro_build (NULL, &icnt, &offset_expr, likely ? "bnel" : "bne",
- "s,t,p", AT, 0);
+ set_at (sreg, 1);
+ macro_build (&offset_expr, likely ? "bnel" : "bne", "s,t,p", AT, 0);
break;
case M_BLTL:
@@ -4473,19 +4541,16 @@ macro (struct mips_cl_insn *ip)
case M_BLT:
if (treg == 0)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "bltzl" : "bltz",
- "s,p", sreg);
+ macro_build (&offset_expr, likely ? "bltzl" : "bltz", "s,p", sreg);
return;
}
if (sreg == 0)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "bgtzl" : "bgtz",
- "s,p", treg);
+ macro_build (&offset_expr, likely ? "bgtzl" : "bgtz", "s,p", treg);
return;
}
- macro_build (NULL, &icnt, NULL, "slt", "d,v,t", AT, sreg, treg);
- macro_build (NULL, &icnt, &offset_expr, likely ? "bnel" : "bne",
- "s,t,p", AT, 0);
+ macro_build (NULL, "slt", "d,v,t", AT, sreg, treg);
+ macro_build (&offset_expr, likely ? "bnel" : "bne", "s,t,p", AT, 0);
break;
case M_BLTUL:
@@ -4495,13 +4560,12 @@ macro (struct mips_cl_insn *ip)
goto do_false;
if (sreg == 0)
{
- macro_build (NULL, &icnt, &offset_expr, likely ? "bnel" : "bne",
+ macro_build (&offset_expr, likely ? "bnel" : "bne",
"s,t,p", 0, treg);
return;
}
- macro_build (NULL, &icnt, NULL, "sltu", "d,v,t", AT, sreg, treg);
- macro_build (NULL, &icnt, &offset_expr, likely ? "bnel" : "bne",
- "s,t,p", AT, 0);
+ macro_build (NULL, "sltu", "d,v,t", AT, sreg, treg);
+ macro_build (&offset_expr, likely ? "bnel" : "bne", "s,t,p", AT, 0);
break;
case M_DEXT:
@@ -4548,8 +4612,7 @@ macro (struct mips_cl_insn *ip)
s = "dextm";
fmt = "t,r,+A,+G";
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s,
- fmt, treg, sreg, pos, size - 1);
+ macro_build ((expressionS *) NULL, s, fmt, treg, sreg, pos, size - 1);
}
return;
@@ -4597,8 +4660,8 @@ macro (struct mips_cl_insn *ip)
s = "dinsm";
fmt = "t,r,+A,+F";
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s,
- fmt, treg, sreg, pos, pos + size - 1);
+ macro_build ((expressionS *) NULL, s, fmt, treg, sreg, pos,
+ pos + size - 1);
}
return;
@@ -4616,9 +4679,9 @@ macro (struct mips_cl_insn *ip)
{
as_warn (_("Divide by zero."));
if (mips_trap)
- macro_build (NULL, &icnt, NULL, "teq", "s,t,q", 0, 0, 7);
+ macro_build (NULL, "teq", "s,t,q", 0, 0, 7);
else
- macro_build (NULL, &icnt, NULL, "break", "c", 7);
+ macro_build (NULL, "break", "c", 7);
return;
}
@@ -4627,39 +4690,34 @@ macro (struct mips_cl_insn *ip)
mips_any_noreorder = 1;
if (mips_trap)
{
- macro_build (NULL, &icnt, NULL, "teq", "s,t,q", treg, 0, 7);
- macro_build (NULL, &icnt, NULL, dbl ? "ddiv" : "div", "z,s,t",
- sreg, treg);
+ macro_build (NULL, "teq", "s,t,q", treg, 0, 7);
+ macro_build (NULL, dbl ? "ddiv" : "div", "z,s,t", sreg, treg);
}
else
{
expr1.X_add_number = 8;
- macro_build (NULL, &icnt, &expr1, "bne", "s,t,p", treg, 0);
- macro_build (NULL, &icnt, NULL, dbl ? "ddiv" : "div", "z,s,t",
- sreg, treg);
- macro_build (NULL, &icnt, NULL, "break", "c", 7);
+ macro_build (&expr1, "bne", "s,t,p", treg, 0);
+ macro_build (NULL, dbl ? "ddiv" : "div", "z,s,t", sreg, treg);
+ macro_build (NULL, "break", "c", 7);
}
expr1.X_add_number = -1;
- macro_build (NULL, &icnt, &expr1, dbl ? "daddiu" : "addiu", "t,r,j",
- AT, 0, BFD_RELOC_LO16);
+ load_register (AT, &expr1, dbl);
expr1.X_add_number = mips_trap ? (dbl ? 12 : 8) : (dbl ? 20 : 16);
- macro_build (NULL, &icnt, &expr1, "bne", "s,t,p", treg, AT);
+ macro_build (&expr1, "bne", "s,t,p", treg, AT);
if (dbl)
{
expr1.X_add_number = 1;
- macro_build (NULL, &icnt, &expr1, "daddiu", "t,r,j", AT, 0,
- BFD_RELOC_LO16);
- macro_build (NULL, &icnt, NULL, "dsll32", "d,w,<", AT, AT, 31);
+ load_register (AT, &expr1, dbl);
+ macro_build (NULL, "dsll32", "d,w,<", AT, AT, 31);
}
else
{
expr1.X_add_number = 0x80000000;
- macro_build (NULL, &icnt, &expr1, "lui", "t,u", AT,
- BFD_RELOC_HI16);
+ macro_build (&expr1, "lui", "t,u", AT, BFD_RELOC_HI16);
}
if (mips_trap)
{
- macro_build (NULL, &icnt, NULL, "teq", "s,t,q", sreg, AT, 6);
+ macro_build (NULL, "teq", "s,t,q", sreg, AT, 6);
/* We want to close the noreorder block as soon as possible, so
that later insns are available for delay slot filling. */
--mips_opts.noreorder;
@@ -4667,16 +4725,16 @@ macro (struct mips_cl_insn *ip)
else
{
expr1.X_add_number = 8;
- macro_build (NULL, &icnt, &expr1, "bne", "s,t,p", sreg, AT);
- macro_build (NULL, &icnt, NULL, "nop", "", 0);
+ macro_build (&expr1, "bne", "s,t,p", sreg, AT);
+ macro_build (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 (NULL, &icnt, NULL, "break", "c", 6);
+ macro_build (NULL, "break", "c", 6);
}
- macro_build (NULL, &icnt, NULL, s, "d", dreg);
+ macro_build (NULL, s, "d", dreg);
break;
case M_DIV_3I:
@@ -4719,17 +4777,17 @@ macro (struct mips_cl_insn *ip)
{
as_warn (_("Divide by zero."));
if (mips_trap)
- macro_build (NULL, &icnt, NULL, "teq", "s,t,q", 0, 0, 7);
+ macro_build (NULL, "teq", "s,t,q", 0, 0, 7);
else
- macro_build (NULL, &icnt, NULL, "break", "c", 7);
+ macro_build (NULL, "break", "c", 7);
return;
}
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1)
{
if (strcmp (s2, "mflo") == 0)
- move_register (&icnt, dreg, sreg);
+ move_register (dreg, sreg);
else
- move_register (&icnt, dreg, 0);
+ move_register (dreg, 0);
return;
}
if (imm_expr.X_op == O_constant
@@ -4738,17 +4796,16 @@ macro (struct mips_cl_insn *ip)
{
if (strcmp (s2, "mflo") == 0)
{
- macro_build (NULL, &icnt, NULL, dbl ? "dneg" : "neg", "d,w",
- dreg, sreg);
+ macro_build (NULL, dbl ? "dneg" : "neg", "d,w", dreg, sreg);
}
else
- move_register (&icnt, dreg, 0);
+ move_register (dreg, 0);
return;
}
- load_register (&icnt, AT, &imm_expr, dbl);
- macro_build (NULL, &icnt, NULL, s, "z,s,t", sreg, AT);
- macro_build (NULL, &icnt, NULL, s2, "d", dreg);
+ load_register (AT, &imm_expr, dbl);
+ macro_build (NULL, s, "z,s,t", sreg, AT);
+ macro_build (NULL, s2, "d", dreg);
break;
case M_DIVU_3:
@@ -4772,8 +4829,8 @@ macro (struct mips_cl_insn *ip)
mips_any_noreorder = 1;
if (mips_trap)
{
- macro_build (NULL, &icnt, NULL, "teq", "s,t,q", treg, 0, 7);
- macro_build (NULL, &icnt, NULL, s, "z,s,t", sreg, treg);
+ macro_build (NULL, "teq", "s,t,q", treg, 0, 7);
+ macro_build (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;
@@ -4781,15 +4838,15 @@ macro (struct mips_cl_insn *ip)
else
{
expr1.X_add_number = 8;
- macro_build (NULL, &icnt, &expr1, "bne", "s,t,p", treg, 0);
- macro_build (NULL, &icnt, NULL, s, "z,s,t", sreg, treg);
+ macro_build (&expr1, "bne", "s,t,p", treg, 0);
+ macro_build (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 (NULL, &icnt, NULL, "break", "c", 7);
+ macro_build (NULL, "break", "c", 7);
}
- macro_build (NULL, &icnt, NULL, s2, "d", dreg);
+ macro_build (NULL, s2, "d", dreg);
return;
case M_DLCA_AB:
@@ -4814,7 +4871,7 @@ macro (struct mips_cl_insn *ip)
&& offset_expr.X_add_number >= -0x8000
&& offset_expr.X_add_number < 0x8000)
{
- macro_build (NULL, &icnt, &offset_expr,
+ macro_build (&offset_expr,
(dbl || HAVE_64BIT_ADDRESSES) ? "daddiu" : "addiu",
"t,r,j", treg, sreg, BFD_RELOC_LO16);
return;
@@ -4856,18 +4913,18 @@ macro (struct mips_cl_insn *ip)
{
tempreg = treg;
used_at = 0;
- macro_build (NULL, &icnt, &offset_expr, "lui", "t,u", tempreg,
- BFD_RELOC_PCREL_HI16_S);
+ macro_build (&offset_expr, "lui", "t,u",
+ tempreg, BFD_RELOC_PCREL_HI16_S);
}
else
{
- macro_build (NULL, &icnt, &offset_expr, "lui", "t,u", tempreg,
- BFD_RELOC_PCREL_HI16_S);
- macro_build (NULL, &icnt, NULL,
+ macro_build (&offset_expr, "lui", "t,u",
+ tempreg, BFD_RELOC_PCREL_HI16_S);
+ macro_build (NULL,
(dbl || HAVE_64BIT_ADDRESSES) ? "daddu" : "addu",
"d,v,t", tempreg, tempreg, breg);
}
- macro_build (NULL, &icnt, &offset_expr,
+ macro_build (&offset_expr,
(dbl || HAVE_64BIT_ADDRESSES) ? "daddiu" : "addiu",
"t,r,j", treg, tempreg, BFD_RELOC_PCREL_LO16);
if (! used_at)
@@ -4883,7 +4940,7 @@ macro (struct mips_cl_insn *ip)
}
if (offset_expr.X_op == O_constant)
- load_register (&icnt, tempreg, &offset_expr,
+ load_register (tempreg, &offset_expr,
((mips_pic == EMBEDDED_PIC || mips_pic == NO_PIC)
? (dbl || HAVE_64BIT_ADDRESSES)
: HAVE_64BIT_ADDRESSES));
@@ -4914,41 +4971,37 @@ macro (struct mips_cl_insn *ip)
dsll $tempreg,16
daddiu $tempreg,<sym> (BFD_RELOC_LO16)
*/
- char *p = NULL;
if (HAVE_64BIT_ADDRESSES)
{
- /* We don't do GP optimization for now because RELAX_ENCODE can't
- hold the data for such large chunks. */
+ /* ??? We don't provide a GP-relative alternative for
+ these macros. It used not to be possible with the
+ original relaxation code, but it could be done now. */
if (used_at == 0 && ! mips_opts.noat)
{
- macro_build (p, &icnt, &offset_expr, "lui", "t,u",
+ macro_build (&offset_expr, "lui", "t,u",
tempreg, BFD_RELOC_MIPS_HIGHEST);
- macro_build (p, &icnt, &offset_expr, "lui", "t,u",
+ macro_build (&offset_expr, "lui", "t,u",
AT, BFD_RELOC_HI16_S);
- macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
+ macro_build (&offset_expr, "daddiu", "t,r,j",
tempreg, tempreg, BFD_RELOC_MIPS_HIGHER);
- macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
+ macro_build (&offset_expr, "daddiu", "t,r,j",
AT, AT, BFD_RELOC_LO16);
- 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 (NULL, "dsll32", "d,w,<", tempreg, tempreg, 0);
+ macro_build (NULL, "daddu", "d,v,t", tempreg, tempreg, AT);
used_at = 1;
}
else
{
- macro_build (p, &icnt, &offset_expr, "lui", "t,u",
+ macro_build (&offset_expr, "lui", "t,u",
tempreg, BFD_RELOC_MIPS_HIGHEST);
- macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
+ macro_build (&offset_expr, "daddiu", "t,r,j",
tempreg, tempreg, BFD_RELOC_MIPS_HIGHER);
- macro_build (p, &icnt, NULL, "dsll", "d,w,<",
- tempreg, tempreg, 16);
- macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
+ macro_build (NULL, "dsll", "d,w,<", tempreg, tempreg, 16);
+ macro_build (&offset_expr, "daddiu", "t,r,j",
tempreg, tempreg, BFD_RELOC_HI16_S);
- macro_build (p, &icnt, NULL, "dsll", "d,w,<",
- tempreg, tempreg, 16);
- macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
+ macro_build (NULL, "dsll", "d,w,<", tempreg, tempreg, 16);
+ macro_build (&offset_expr, "daddiu", "t,r,j",
tempreg, tempreg, BFD_RELOC_LO16);
}
}
@@ -4957,20 +5010,16 @@ macro (struct mips_cl_insn *ip)
if ((valueT) offset_expr.X_add_number <= MAX_GPREL_OFFSET
&& ! nopic_need_relax (offset_expr.X_add_symbol, 1))
{
- frag_grow (20);
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_ADDI_INSN,
- "t,r,j", tempreg, mips_gp_register,
- BFD_RELOC_GPREL16);
- p = frag_var (rs_machine_dependent, 8, 0,
- RELAX_ENCODE (4, 8, 0, 4, 0,
- mips_opts.warn_about_macros),
- offset_expr.X_add_symbol, 0, NULL);
+ relax_start (offset_expr.X_add_symbol);
+ macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
+ tempreg, mips_gp_register, BFD_RELOC_GPREL16);
+ relax_switch ();
}
- macro_build_lui (p, &icnt, &offset_expr, tempreg);
- if (p != NULL)
- p += 4;
- macro_build (p, &icnt, &offset_expr, ADDRESS_ADDI_INSN,
- "t,r,j", tempreg, tempreg, BFD_RELOC_LO16);
+ macro_build_lui (&offset_expr, tempreg);
+ macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
+ tempreg, tempreg, BFD_RELOC_LO16);
+ if (mips_relax.sequence)
+ relax_end ();
}
}
else if (mips_pic == SVR4_PIC && ! mips_big_got && ! HAVE_NEWABI)
@@ -5007,60 +5056,46 @@ macro (struct mips_cl_insn *ip)
addiu instruction.
*/
- expr1.X_add_number = offset_expr.X_add_number;
- offset_expr.X_add_number = 0;
- frag_grow (32);
- if (expr1.X_add_number == 0 && breg == 0
- && (call || tempreg == PIC_CALL_REG))
- lw_reloc_type = (int) BFD_RELOC_MIPS_CALL16;
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
- tempreg, lw_reloc_type, mips_gp_register);
- if (expr1.X_add_number == 0)
+ if (offset_expr.X_add_number == 0)
{
- int off;
- char *p;
+ if (breg == 0 && (call || tempreg == PIC_CALL_REG))
+ lw_reloc_type = (int) BFD_RELOC_MIPS_CALL16;
- if (breg == 0)
- off = 0;
- else
+ relax_start (offset_expr.X_add_symbol);
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
+ lw_reloc_type, mips_gp_register);
+ if (breg != 0)
{
/* We're going to put in an addu instruction using
tempreg, so we may as well insert the nop right
now. */
- macro_build (NULL, &icnt, NULL, "nop", "");
- off = 4;
+ macro_build (NULL, "nop", "");
}
- p = frag_var (rs_machine_dependent, 8 - off, 0,
- RELAX_ENCODE (0, 8 - off, -4 - off, 4 - off, 0,
- (breg == 0
- ? mips_opts.warn_about_macros
- : 0)),
- offset_expr.X_add_symbol, 0, NULL);
- if (breg == 0)
- {
- macro_build (p, &icnt, NULL, "nop", "");
- p += 4;
- }
- macro_build (p, &icnt, &expr1, ADDRESS_ADDI_INSN,
- "t,r,j", tempreg, tempreg, BFD_RELOC_LO16);
+ relax_switch ();
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
+ tempreg, BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ macro_build (NULL, "nop", "");
+ macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
+ tempreg, tempreg, BFD_RELOC_LO16);
+ relax_end ();
/* FIXME: If breg == 0, and the next instruction uses
$tempreg, then if this variant case is used an extra
nop will be generated. */
}
- else if (expr1.X_add_number >= -0x8000
- && expr1.X_add_number < 0x8000)
+ else if (offset_expr.X_add_number >= -0x8000
+ && offset_expr.X_add_number < 0x8000)
{
- macro_build (NULL, &icnt, NULL, "nop", "");
- macro_build (NULL, &icnt, &expr1, ADDRESS_ADDI_INSN,
- "t,r,j", tempreg, tempreg, BFD_RELOC_LO16);
- frag_var (rs_machine_dependent, 0, 0,
- RELAX_ENCODE (0, 0, -12, -4, 0, 0),
- offset_expr.X_add_symbol, 0, NULL);
+ load_got_offset (tempreg, &offset_expr);
+ macro_build (NULL, "nop", "");
+ add_got_offset (tempreg, &offset_expr);
}
else
{
- int off1;
-
+ expr1.X_add_number = offset_expr.X_add_number;
+ offset_expr.X_add_number =
+ ((offset_expr.X_add_number + 0x8000) & 0xffff) - 0x8000;
+ load_got_offset (tempreg, &offset_expr);
+ offset_expr.X_add_number = expr1.X_add_number;
/* If we are going to add in a base register, and the
target register and the base register are the same,
then we are using AT as a temporary register. Since
@@ -5068,40 +5103,21 @@ macro (struct mips_cl_insn *ip)
current AT (from the global offset table) and the
register into the register now, and pretend we were
not using a base register. */
- if (breg != treg)
- off1 = 0;
- else
+ if (breg == treg)
{
- macro_build (NULL, &icnt, NULL, "nop", "");
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build (NULL, "nop", "");
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
treg, AT, breg);
breg = 0;
tempreg = treg;
- off1 = -8;
}
-
- /* Set mips_optimize around the lui instruction to avoid
- inserting an unnecessary nop after the lw. */
- hold_mips_optimize = mips_optimize;
- mips_optimize = 2;
- macro_build_lui (NULL, &icnt, &expr1, AT);
- mips_optimize = hold_mips_optimize;
-
- macro_build (NULL, &icnt, &expr1, ADDRESS_ADDI_INSN, "t,r,j",
- AT, AT, BFD_RELOC_LO16);
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
- tempreg, tempreg, AT);
- frag_var (rs_machine_dependent, 0, 0,
- RELAX_ENCODE (0, 0, -16 + off1, -8, 0, 0),
- offset_expr.X_add_symbol, 0, NULL);
+ add_got_offset_hilo (tempreg, &offset_expr, AT);
used_at = 1;
}
}
else if (mips_pic == SVR4_PIC && ! mips_big_got && HAVE_NEWABI)
{
- char *p = NULL;
- int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_DISP;
- int adj = 0;
+ int add_breg_early = 0;
/* If this is a reference to an external, and there is no
constant, or local symbol (*), with or without a
@@ -5126,28 +5142,20 @@ macro (struct mips_cl_insn *ip)
local symbols, even though it introduces an additional
instruction. */
- frag_grow (28);
- if (offset_expr.X_add_number == 0 && breg == 0
- && (call || tempreg == PIC_CALL_REG))
- lw_reloc_type = (int) BFD_RELOC_MIPS_CALL16;
if (offset_expr.X_add_number)
{
- frag_now->tc_frag_data.tc_fr_offset =
- expr1.X_add_number = offset_expr.X_add_number;
+ expr1.X_add_number = offset_expr.X_add_number;
offset_expr.X_add_number = 0;
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
- "t,o(b)", tempreg, lw_reloc_type,
- mips_gp_register);
+ relax_start (offset_expr.X_add_symbol);
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
+ BFD_RELOC_MIPS_GOT_DISP, mips_gp_register);
if (expr1.X_add_number >= -0x8000
&& expr1.X_add_number < 0x8000)
{
- macro_build (NULL, &icnt, &expr1, ADDRESS_ADDI_INSN,
- "t,r,j", tempreg, tempreg, BFD_RELOC_LO16);
- p = frag_var (rs_machine_dependent, 4, 0,
- RELAX_ENCODE (8, 4, 0, 0, 0, 0),
- offset_expr.X_add_symbol, 0, NULL);
+ macro_build (&expr1, ADDRESS_ADDI_INSN, "t,r,j",
+ tempreg, tempreg, BFD_RELOC_LO16);
}
else if (IS_SEXT_32BIT_NUM (expr1.X_add_number + 0x8000))
{
@@ -5165,64 +5173,54 @@ macro (struct mips_cl_insn *ip)
else
{
assert (tempreg == AT);
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN,
- "d,v,t", treg, AT, breg);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
+ treg, AT, breg);
dreg = treg;
- adj = 4;
+ add_breg_early = 1;
}
- macro_build_lui (NULL, &icnt, &expr1, AT);
- macro_build (NULL, &icnt, &expr1, ADDRESS_ADDI_INSN,
- "t,r,j", AT, AT, BFD_RELOC_LO16);
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ load_register (AT, &expr1, HAVE_64BIT_ADDRESSES);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
dreg, dreg, AT);
- p = frag_var (rs_machine_dependent, 4 + adj, 0,
- RELAX_ENCODE (16 + adj, 4 + adj,
- 0, 0, 0, 0),
- offset_expr.X_add_symbol, 0, NULL);
-
used_at = 1;
}
else
as_bad (_("PIC code offset overflow (max 32 signed bits)"));
+ relax_switch ();
offset_expr.X_add_number = expr1.X_add_number;
- macro_build (p, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
- "t,o(b)", tempreg, BFD_RELOC_MIPS_GOT_DISP,
- mips_gp_register);
- if (adj)
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
+ BFD_RELOC_MIPS_GOT_DISP, mips_gp_register);
+ if (add_breg_early)
{
- macro_build (p + 4, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
treg, tempreg, breg);
breg = 0;
tempreg = treg;
}
+ relax_end ();
}
- else
+ else if (breg == 0 && (call || tempreg == PIC_CALL_REG))
{
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
- "t,o(b)", tempreg, lw_reloc_type,
- mips_gp_register);
- if (lw_reloc_type != BFD_RELOC_MIPS_GOT_DISP)
- p = frag_var (rs_machine_dependent, 0, 0,
- RELAX_ENCODE (0, 0, -4, 0, 0, 0),
- offset_expr.X_add_symbol, 0, NULL);
+ relax_start (offset_expr.X_add_symbol);
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
+ BFD_RELOC_MIPS_CALL16, mips_gp_register);
+ relax_switch ();
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
+ BFD_RELOC_MIPS_GOT_DISP, mips_gp_register);
+ relax_end ();
}
-
- if (! p)
+ else
{
- /* To avoid confusion in tc_gen_reloc, we must ensure
- that this does not become a variant frag. */
- frag_wane (frag_now);
- frag_new (0);
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
+ BFD_RELOC_MIPS_GOT_DISP, mips_gp_register);
}
}
else if (mips_pic == SVR4_PIC && ! HAVE_NEWABI)
{
- int gpdel;
- char *p;
+ int gpdelay;
int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16;
int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_LO16;
int local_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
@@ -5270,63 +5268,39 @@ macro (struct mips_cl_insn *ip)
expr1.X_add_number = offset_expr.X_add_number;
offset_expr.X_add_number = 0;
- frag_grow (52);
- if (reg_needs_delay (mips_gp_register))
- gpdel = 4;
- else
- gpdel = 0;
+ relax_start (offset_expr.X_add_symbol);
+ gpdelay = reg_needs_delay (mips_gp_register);
if (expr1.X_add_number == 0 && breg == 0
&& (call || tempreg == PIC_CALL_REG))
{
lui_reloc_type = (int) BFD_RELOC_MIPS_CALL_HI16;
lw_reloc_type = (int) BFD_RELOC_MIPS_CALL_LO16;
}
- macro_build (NULL, &icnt, &offset_expr, "lui", "t,u",
- tempreg, lui_reloc_type);
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build (&offset_expr, "lui", "t,u", tempreg, lui_reloc_type);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, tempreg, mips_gp_register);
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
tempreg, lw_reloc_type, tempreg);
if (expr1.X_add_number == 0)
{
- int off;
-
- if (breg == 0)
- off = 0;
- else
+ if (breg != 0)
{
/* We're going to put in an addu instruction using
tempreg, so we may as well insert the nop right
now. */
- macro_build (NULL, &icnt, NULL, "nop", "");
- off = 4;
+ macro_build (NULL, "nop", "");
}
-
- p = frag_var (rs_machine_dependent, 12 + gpdel, 0,
- RELAX_ENCODE (12 + off, 12 + gpdel, gpdel,
- 8 + gpdel, 0,
- (breg == 0
- ? mips_opts.warn_about_macros
- : 0)),
- offset_expr.X_add_symbol, 0, NULL);
}
else if (expr1.X_add_number >= -0x8000
&& expr1.X_add_number < 0x8000)
{
- macro_build (NULL, &icnt, NULL, "nop", "");
- macro_build (NULL, &icnt, &expr1, ADDRESS_ADDI_INSN, "t,r,j",
+ macro_build (NULL, "nop", "");
+ macro_build (&expr1, ADDRESS_ADDI_INSN, "t,r,j",
tempreg, tempreg, BFD_RELOC_LO16);
-
- p = frag_var (rs_machine_dependent, 12 + gpdel, 0,
- RELAX_ENCODE (20, 12 + gpdel, gpdel, 8 + gpdel, 0,
- (breg == 0
- ? mips_opts.warn_about_macros
- : 0)),
- offset_expr.X_add_symbol, 0, NULL);
}
else
{
- int adj, dreg;
+ int dreg;
/* If we are going to add in a base register, and the
target register and the base register are the same,
@@ -5336,61 +5310,40 @@ macro (struct mips_cl_insn *ip)
register into the register now, and pretend we were
not using a base register. */
if (breg != treg)
- {
- adj = 0;
- dreg = tempreg;
- }
+ dreg = tempreg;
else
{
assert (tempreg == AT);
- macro_build (NULL, &icnt, NULL, "nop", "");
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build (NULL, "nop", "");
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
treg, AT, breg);
dreg = treg;
- adj = 8;
}
- /* Set mips_optimize around the lui instruction to avoid
- inserting an unnecessary nop after the lw. */
- hold_mips_optimize = mips_optimize;
- mips_optimize = 2;
- macro_build_lui (NULL, &icnt, &expr1, AT);
- mips_optimize = hold_mips_optimize;
-
- macro_build (NULL, &icnt, &expr1, ADDRESS_ADDI_INSN, "t,r,j",
- AT, AT, BFD_RELOC_LO16);
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
- dreg, dreg, AT);
-
- p = frag_var (rs_machine_dependent, 16 + gpdel + adj, 0,
- RELAX_ENCODE (24 + adj, 16 + gpdel + adj, gpdel,
- 8 + gpdel, 0,
- (breg == 0
- ? mips_opts.warn_about_macros
- : 0)),
- offset_expr.X_add_symbol, 0, NULL);
+ load_register (AT, &expr1, HAVE_64BIT_ADDRESSES);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", dreg, dreg, AT);
used_at = 1;
}
+ offset_expr.X_add_number =
+ ((expr1.X_add_number + 0x8000) & 0xffff) - 0x8000;
+ relax_switch ();
- if (gpdel > 0)
+ if (gpdelay)
{
/* This is needed because this instruction uses $gp, but
the first instruction on the main stream does not. */
- macro_build (p, &icnt, NULL, "nop", "");
- p += 4;
+ macro_build (NULL, "nop", "");
}
- macro_build (p, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
- tempreg, local_reloc_type, mips_gp_register);
- p += 4;
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
+ local_reloc_type, mips_gp_register);
if (expr1.X_add_number >= -0x8000
&& expr1.X_add_number < 0x8000)
{
- macro_build (p, &icnt, NULL, "nop", "");
- p += 4;
- macro_build (p, &icnt, &expr1, ADDRESS_ADDI_INSN,
- "t,r,j", tempreg, tempreg, BFD_RELOC_LO16);
+ macro_build (NULL, "nop", "");
+ macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
+ tempreg, tempreg, BFD_RELOC_LO16);
/* FIXME: If add_number is 0, and there was no base
register, the external symbol case ended with a load,
so if the symbol turns out to not be external, and
@@ -5404,33 +5357,28 @@ macro (struct mips_cl_insn *ip)
/* We must add in the base register now, as in the
external symbol case. */
assert (tempreg == AT);
- macro_build (p, &icnt, NULL, "nop", "");
- p += 4;
- macro_build (p, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build (NULL, "nop", "");
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
treg, AT, breg);
- p += 4;
tempreg = treg;
/* We set breg to 0 because we have arranged to add
it in in both cases. */
breg = 0;
}
- macro_build_lui (p, &icnt, &expr1, AT);
- p += 4;
- macro_build (p, &icnt, &expr1, ADDRESS_ADDI_INSN, "t,r,j",
+ macro_build_lui (&expr1, AT);
+ macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
AT, AT, BFD_RELOC_LO16);
- p += 4;
- macro_build (p, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, tempreg, AT);
- p += 4;
}
+ relax_end ();
}
else if (mips_pic == SVR4_PIC && HAVE_NEWABI)
{
- char *p = NULL;
int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16;
int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_LO16;
- int adj = 0;
+ int add_breg_early = 0;
/* This is the large GOT case. If this is a reference to an
external symbol, and there is no constant, we want
@@ -5463,10 +5411,9 @@ macro (struct mips_cl_insn *ip)
addiu $reg,$reg,<sym> (BFD_RELOC_MIPS_GOT_OFST)
otherwise we have to resort to GOT_HI16/GOT_LO16. */
- frag_grow (40);
+ relax_start (offset_expr.X_add_symbol);
- frag_now->tc_frag_data.tc_fr_offset =
- expr1.X_add_number = offset_expr.X_add_number;
+ expr1.X_add_number = offset_expr.X_add_number;
offset_expr.X_add_number = 0;
if (expr1.X_add_number == 0 && breg == 0
@@ -5475,29 +5422,19 @@ macro (struct mips_cl_insn *ip)
lui_reloc_type = (int) BFD_RELOC_MIPS_CALL_HI16;
lw_reloc_type = (int) BFD_RELOC_MIPS_CALL_LO16;
}
- macro_build (NULL, &icnt, &offset_expr, "lui", "t,u",
- tempreg, lui_reloc_type);
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build (&offset_expr, "lui", "t,u", tempreg, lui_reloc_type);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, tempreg, mips_gp_register);
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
- "t,o(b)", tempreg, lw_reloc_type, tempreg);
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
+ tempreg, lw_reloc_type, tempreg);
if (expr1.X_add_number == 0)
- {
- p = frag_var (rs_machine_dependent, 8, 0,
- RELAX_ENCODE (12, 8, 0, 4, 0,
- mips_opts.warn_about_macros),
- offset_expr.X_add_symbol, 0, NULL);
- }
+ ;
else if (expr1.X_add_number >= -0x8000
&& expr1.X_add_number < 0x8000)
{
- macro_build (NULL, &icnt, &expr1, ADDRESS_ADDI_INSN, "t,r,j",
+ macro_build (&expr1, ADDRESS_ADDI_INSN, "t,r,j",
tempreg, tempreg, BFD_RELOC_LO16);
- p = frag_var (rs_machine_dependent, 8, 0,
- RELAX_ENCODE (16, 8, 0, 4, 0,
- mips_opts.warn_about_macros),
- offset_expr.X_add_symbol, 0, NULL);
}
else if (IS_SEXT_32BIT_NUM (expr1.X_add_number + 0x8000))
{
@@ -5515,53 +5452,42 @@ macro (struct mips_cl_insn *ip)
else
{
assert (tempreg == AT);
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
treg, AT, breg);
dreg = treg;
- adj = 4;
+ add_breg_early = 1;
}
- /* Set mips_optimize around the lui instruction to avoid
- inserting an unnecessary nop after the lw. */
- macro_build_lui (NULL, &icnt, &expr1, AT);
- macro_build (NULL, &icnt, &expr1, ADDRESS_ADDI_INSN,
- "t,r,j", AT, AT, BFD_RELOC_LO16);
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
- dreg, dreg, AT);
-
- p = frag_var (rs_machine_dependent, 8 + adj, 0,
- RELAX_ENCODE (24 + adj, 8 + adj,
- 0, 4, 0,
- (breg == 0
- ? mips_opts.warn_about_macros
- : 0)),
- offset_expr.X_add_symbol, 0, NULL);
+ load_register (AT, &expr1, HAVE_64BIT_ADDRESSES);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", dreg, dreg, AT);
used_at = 1;
}
else
as_bad (_("PIC code offset overflow (max 32 signed bits)"));
+ relax_switch ();
offset_expr.X_add_number = expr1.X_add_number;
- macro_build (p, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
- tempreg, BFD_RELOC_MIPS_GOT_PAGE, mips_gp_register);
- macro_build (p + 4, &icnt, &offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
- tempreg, tempreg, BFD_RELOC_MIPS_GOT_OFST);
- if (adj)
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
+ BFD_RELOC_MIPS_GOT_PAGE, mips_gp_register);
+ macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", tempreg,
+ tempreg, BFD_RELOC_MIPS_GOT_OFST);
+ if (add_breg_early)
{
- macro_build (p + 8, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
treg, tempreg, breg);
breg = 0;
tempreg = treg;
}
+ relax_end ();
}
else if (mips_pic == EMBEDDED_PIC)
{
/* We use
addiu $tempreg,$gp,<sym> (BFD_RELOC_GPREL16)
*/
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
- tempreg, mips_gp_register, BFD_RELOC_GPREL16);
+ macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", tempreg,
+ mips_gp_register, BFD_RELOC_GPREL16);
}
else
abort ();
@@ -5575,7 +5501,7 @@ macro (struct mips_cl_insn *ip)
else
s = ADDRESS_ADD_INSN;
- macro_build (NULL, &icnt, NULL, s, "d,v,t", treg, tempreg, breg);
+ macro_build (NULL, s, "d,v,t", treg, tempreg, breg);
}
if (! used_at)
@@ -5588,9 +5514,9 @@ macro (struct mips_cl_insn *ip)
requires an absolute address. We convert it to a b
instruction. */
if (mips_pic == NO_PIC)
- macro_build (NULL, &icnt, &offset_expr, "j", "a");
+ macro_build (&offset_expr, "j", "a");
else
- macro_build (NULL, &icnt, &offset_expr, "b", "p");
+ macro_build (&offset_expr, "b", "p");
return;
/* The jal instructions must be handled as macros because when
@@ -5602,13 +5528,13 @@ macro (struct mips_cl_insn *ip)
case M_JAL_2:
if (mips_pic == NO_PIC
|| mips_pic == EMBEDDED_PIC)
- macro_build (NULL, &icnt, NULL, "jalr", "d,s", dreg, sreg);
+ macro_build (NULL, "jalr", "d,s", dreg, sreg);
else if (mips_pic == SVR4_PIC)
{
if (sreg != PIC_CALL_REG)
as_warn (_("MIPS PIC call to register other than $25"));
- macro_build (NULL, &icnt, NULL, "jalr", "d,s", dreg, sreg);
+ macro_build (NULL, "jalr", "d,s", dreg, sreg);
if (! HAVE_NEWABI)
{
if (mips_cprestore_offset < 0)
@@ -5628,8 +5554,7 @@ macro (struct mips_cl_insn *ip)
mips_cprestore_valid = 1;
}
expr1.X_add_number = mips_cprestore_offset;
- macro_build_ldst_constoffset (NULL, &icnt, &expr1,
- ADDRESS_LOAD_INSN,
+ macro_build_ldst_constoffset (&expr1, ADDRESS_LOAD_INSN,
mips_gp_register,
mips_frame_reg,
HAVE_64BIT_ADDRESSES);
@@ -5643,11 +5568,9 @@ macro (struct mips_cl_insn *ip)
case M_JAL_A:
if (mips_pic == NO_PIC)
- macro_build (NULL, &icnt, &offset_expr, "jal", "a");
+ macro_build (&offset_expr, "jal", "a");
else if (mips_pic == SVR4_PIC)
{
- char *p;
-
/* If this is a reference to an external symbol, and we are
using a small GOT, we want
lw $25,<sym>($gp) (BFD_RELOC_MIPS_CALL16)
@@ -5680,86 +5603,74 @@ macro (struct mips_cl_insn *ip)
{
if (! mips_big_got)
{
- frag_grow (4);
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
- "t,o(b)", PIC_CALL_REG, BFD_RELOC_MIPS_CALL16,
+ relax_start (offset_expr.X_add_symbol);
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
+ PIC_CALL_REG, BFD_RELOC_MIPS_CALL16,
+ mips_gp_register);
+ relax_switch ();
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
+ PIC_CALL_REG, BFD_RELOC_MIPS_GOT_DISP,
mips_gp_register);
- frag_var (rs_machine_dependent, 0, 0,
- RELAX_ENCODE (0, 0, -4, 0, 0, 0),
- offset_expr.X_add_symbol, 0, NULL);
+ relax_end ();
}
else
{
- frag_grow (20);
- macro_build (NULL, &icnt, &offset_expr, "lui", "t,u",
- PIC_CALL_REG, BFD_RELOC_MIPS_CALL_HI16);
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
- PIC_CALL_REG, PIC_CALL_REG, mips_gp_register);
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
- "t,o(b)", PIC_CALL_REG,
- BFD_RELOC_MIPS_CALL_LO16, PIC_CALL_REG);
- p = frag_var (rs_machine_dependent, 8, 0,
- RELAX_ENCODE (12, 8, 0, 4, 0, 0),
- offset_expr.X_add_symbol, 0, NULL);
- macro_build (p, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
- "t,o(b)", PIC_CALL_REG,
- BFD_RELOC_MIPS_GOT_PAGE, mips_gp_register);
- macro_build (p + 4, &icnt, &offset_expr, ADDRESS_ADDI_INSN,
- "t,r,j", PIC_CALL_REG, PIC_CALL_REG,
+ relax_start (offset_expr.X_add_symbol);
+ macro_build (&offset_expr, "lui", "t,u", PIC_CALL_REG,
+ BFD_RELOC_MIPS_CALL_HI16);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", PIC_CALL_REG,
+ PIC_CALL_REG, mips_gp_register);
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
+ PIC_CALL_REG, BFD_RELOC_MIPS_CALL_LO16,
+ PIC_CALL_REG);
+ relax_switch ();
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
+ PIC_CALL_REG, BFD_RELOC_MIPS_GOT_PAGE,
+ mips_gp_register);
+ macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
+ PIC_CALL_REG, PIC_CALL_REG,
BFD_RELOC_MIPS_GOT_OFST);
+ relax_end ();
}
- macro_build_jalr (icnt, &offset_expr);
+ macro_build_jalr (&offset_expr);
}
else
{
- frag_grow (40);
+ relax_start (offset_expr.X_add_symbol);
if (! mips_big_got)
{
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
- "t,o(b)", PIC_CALL_REG, BFD_RELOC_MIPS_CALL16,
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
+ PIC_CALL_REG, BFD_RELOC_MIPS_CALL16,
mips_gp_register);
- macro_build (NULL, &icnt, NULL, "nop", "");
- p = frag_var (rs_machine_dependent, 4, 0,
- RELAX_ENCODE (0, 4, -8, 0, 0, 0),
- offset_expr.X_add_symbol, 0, NULL);
+ macro_build (NULL, "nop", "");
+ relax_switch ();
}
else
{
- int gpdel;
-
- if (reg_needs_delay (mips_gp_register))
- gpdel = 4;
- else
- gpdel = 0;
- macro_build (NULL, &icnt, &offset_expr, "lui", "t,u",
- PIC_CALL_REG, BFD_RELOC_MIPS_CALL_HI16);
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
- PIC_CALL_REG, PIC_CALL_REG, mips_gp_register);
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
- "t,o(b)", PIC_CALL_REG,
- BFD_RELOC_MIPS_CALL_LO16, PIC_CALL_REG);
- macro_build (NULL, &icnt, NULL, "nop", "");
- p = frag_var (rs_machine_dependent, 12 + gpdel, 0,
- RELAX_ENCODE (16, 12 + gpdel, gpdel,
- 8 + gpdel, 0, 0),
- offset_expr.X_add_symbol, 0, NULL);
- if (gpdel > 0)
- {
- macro_build (p, &icnt, NULL, "nop", "");
- p += 4;
- }
- macro_build (p, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
- "t,o(b)", PIC_CALL_REG, BFD_RELOC_MIPS_GOT16,
- mips_gp_register);
- p += 4;
- macro_build (p, &icnt, NULL, "nop", "");
- p += 4;
+ int gpdelay;
+
+ gpdelay = reg_needs_delay (mips_gp_register);
+ macro_build (&offset_expr, "lui", "t,u", PIC_CALL_REG,
+ BFD_RELOC_MIPS_CALL_HI16);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", PIC_CALL_REG,
+ PIC_CALL_REG, mips_gp_register);
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
+ PIC_CALL_REG, BFD_RELOC_MIPS_CALL_LO16,
+ PIC_CALL_REG);
+ macro_build (NULL, "nop", "");
+ relax_switch ();
+ if (gpdelay)
+ macro_build (NULL, "nop", "");
}
- macro_build (p, &icnt, &offset_expr, ADDRESS_ADDI_INSN,
- "t,r,j", PIC_CALL_REG, PIC_CALL_REG,
- BFD_RELOC_LO16);
- macro_build_jalr (icnt, &offset_expr);
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
+ PIC_CALL_REG, BFD_RELOC_MIPS_GOT16,
+ mips_gp_register);
+ macro_build (NULL, "nop", "");
+ macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
+ PIC_CALL_REG, PIC_CALL_REG, BFD_RELOC_LO16);
+ relax_end ();
+ macro_build_jalr (&offset_expr);
if (mips_cprestore_offset < 0)
as_warn (_("No .cprestore pseudo-op used in PIC code"));
@@ -5778,10 +5689,9 @@ macro (struct mips_cl_insn *ip)
mips_cprestore_valid = 1;
}
if (mips_opts.noreorder)
- macro_build (NULL, &icnt, NULL, "nop", "");
+ macro_build (NULL, "nop", "");
expr1.X_add_number = mips_cprestore_offset;
- macro_build_ldst_constoffset (NULL, &icnt, &expr1,
- ADDRESS_LOAD_INSN,
+ macro_build_ldst_constoffset (&expr1, ADDRESS_LOAD_INSN,
mips_gp_register,
mips_frame_reg,
HAVE_64BIT_ADDRESSES);
@@ -5790,7 +5700,7 @@ macro (struct mips_cl_insn *ip)
}
else if (mips_pic == EMBEDDED_PIC)
{
- macro_build (NULL, &icnt, &offset_expr, "bal", "p");
+ macro_build (&offset_expr, "bal", "p");
/* The linker may expand the call to a longer sequence which
uses $at, so we must break rather than return. */
break;
@@ -6016,15 +5926,15 @@ macro (struct mips_cl_insn *ip)
nice to emit:
<op> $treg,<sym>($breg) (BFD_RELOC_PCREL_LO16)
instead, but that seems quite difficult. */
- macro_build (NULL, &icnt, &offset_expr, "lui", "t,u", tempreg,
+ macro_build (&offset_expr, "lui", "t,u", tempreg,
BFD_RELOC_PCREL_HI16_S);
- macro_build (NULL, &icnt, 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 (NULL, &icnt, &offset_expr, s, fmt, treg,
- BFD_RELOC_PCREL_LO16, tempreg);
+ macro_build (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 (&offset_expr, s, fmt, treg,
+ BFD_RELOC_PCREL_LO16, tempreg);
if (! used_at)
return;
break;
@@ -6042,8 +5952,6 @@ macro (struct mips_cl_insn *ip)
if (mips_pic == NO_PIC
|| offset_expr.X_op == O_constant)
{
- char *p;
-
/* If this is a reference to a GP relative symbol, and there
is no base register, we want
<op> $treg,<sym>($gp) (BFD_RELOC_GPREL16)
@@ -6129,46 +6037,40 @@ macro (struct mips_cl_insn *ip)
&& offset_expr.X_op == O_constant
&& ! IS_SEXT_32BIT_NUM (offset_expr.X_add_number + 0x8000)))
{
- p = NULL;
-
- /* We don't do GP optimization for now because RELAX_ENCODE can't
- hold the data for such large chunks. */
+ /* ??? We don't provide a GP-relative alternative for
+ these macros. It used not to be possible with the
+ original relaxation code, but it could be done now. */
if (used_at == 0 && ! mips_opts.noat)
{
- macro_build (p, &icnt, &offset_expr, "lui", "t,u",
- tempreg, BFD_RELOC_MIPS_HIGHEST);
- macro_build (p, &icnt, &offset_expr, "lui", "t,u",
- AT, BFD_RELOC_HI16_S);
- macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
- tempreg, tempreg, BFD_RELOC_MIPS_HIGHER);
+ macro_build (&offset_expr, "lui", "t,u", tempreg,
+ BFD_RELOC_MIPS_HIGHEST);
+ macro_build (&offset_expr, "lui", "t,u", AT,
+ BFD_RELOC_HI16_S);
+ macro_build (&offset_expr, "daddiu", "t,r,j", tempreg,
+ tempreg, 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, &offset_expr, s, fmt, treg,
- BFD_RELOC_LO16, tempreg);
+ macro_build (NULL, "daddu", "d,v,t", AT, AT, breg);
+ macro_build (NULL, "dsll32", "d,w,<", tempreg, tempreg, 0);
+ macro_build (NULL, "daddu", "d,v,t", tempreg, tempreg, AT);
+ macro_build (&offset_expr, s, fmt, treg, BFD_RELOC_LO16,
+ tempreg);
used_at = 1;
}
else
{
- macro_build (p, &icnt, &offset_expr, "lui", "t,u",
- tempreg, BFD_RELOC_MIPS_HIGHEST);
- macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
- tempreg, tempreg, BFD_RELOC_MIPS_HIGHER);
- macro_build (p, &icnt, NULL, "dsll", "d,w,<",
- tempreg, tempreg, 16);
- macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
- tempreg, tempreg, BFD_RELOC_HI16_S);
- macro_build (p, &icnt, NULL, "dsll", "d,w,<",
- tempreg, tempreg, 16);
+ macro_build (&offset_expr, "lui", "t,u", tempreg,
+ BFD_RELOC_MIPS_HIGHEST);
+ macro_build (&offset_expr, "daddiu", "t,r,j", tempreg,
+ tempreg, BFD_RELOC_MIPS_HIGHER);
+ macro_build (NULL, "dsll", "d,w,<", tempreg, tempreg, 16);
+ macro_build (&offset_expr, "daddiu", "t,r,j", tempreg,
+ tempreg, BFD_RELOC_HI16_S);
+ macro_build (NULL, "dsll", "d,w,<", tempreg, tempreg, 16);
if (breg != 0)
- macro_build (p, &icnt, NULL, "daddu", "d,v,t",
+ macro_build (NULL, "daddu", "d,v,t",
tempreg, tempreg, breg);
- macro_build (p, &icnt, &offset_expr, s, fmt, treg,
+ macro_build (&offset_expr, s, fmt, treg,
BFD_RELOC_LO16, tempreg);
}
@@ -6181,58 +6083,44 @@ macro (struct mips_cl_insn *ip)
if (breg == 0)
{
- if ((valueT) offset_expr.X_add_number > MAX_GPREL_OFFSET
- || nopic_need_relax (offset_expr.X_add_symbol, 1))
- p = NULL;
- else
+ if ((valueT) offset_expr.X_add_number <= MAX_GPREL_OFFSET
+ && ! nopic_need_relax (offset_expr.X_add_symbol, 1))
{
- frag_grow (20);
- macro_build (NULL, &icnt, &offset_expr, s, fmt, treg,
- BFD_RELOC_GPREL16, mips_gp_register);
- p = frag_var (rs_machine_dependent, 8, 0,
- RELAX_ENCODE (4, 8, 0, 4, 0,
- (mips_opts.warn_about_macros
- || (used_at
- && mips_opts.noat))),
- offset_expr.X_add_symbol, 0, NULL);
+ relax_start (offset_expr.X_add_symbol);
+ macro_build (&offset_expr, s, fmt, treg, BFD_RELOC_GPREL16,
+ mips_gp_register);
+ relax_switch ();
used_at = 0;
}
- macro_build_lui (p, &icnt, &offset_expr, tempreg);
- if (p != NULL)
- p += 4;
- macro_build (p, &icnt, &offset_expr, s, fmt, treg,
+ macro_build_lui (&offset_expr, tempreg);
+ macro_build (&offset_expr, s, fmt, treg,
BFD_RELOC_LO16, tempreg);
+ if (mips_relax.sequence)
+ relax_end ();
}
else
{
- if ((valueT) offset_expr.X_add_number > MAX_GPREL_OFFSET
- || nopic_need_relax (offset_expr.X_add_symbol, 1))
- p = NULL;
- else
+ if ((valueT) offset_expr.X_add_number <= MAX_GPREL_OFFSET
+ && ! nopic_need_relax (offset_expr.X_add_symbol, 1))
{
- frag_grow (28);
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ relax_start (offset_expr.X_add_symbol);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, breg, mips_gp_register);
- macro_build (NULL, &icnt, &offset_expr, s, fmt, treg,
+ macro_build (&offset_expr, s, fmt, treg,
BFD_RELOC_GPREL16, tempreg);
- p = frag_var (rs_machine_dependent, 12, 0,
- RELAX_ENCODE (8, 12, 0, 8, 0, 0),
- offset_expr.X_add_symbol, 0, NULL);
+ relax_switch ();
}
- macro_build_lui (p, &icnt, &offset_expr, tempreg);
- if (p != NULL)
- p += 4;
- macro_build (p, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build_lui (&offset_expr, tempreg);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, tempreg, breg);
- if (p != NULL)
- p += 4;
- macro_build (p, &icnt, &offset_expr, s, fmt, treg,
+ macro_build (&offset_expr, s, fmt, treg,
BFD_RELOC_LO16, tempreg);
+ if (mips_relax.sequence)
+ relax_end ();
}
}
else if (mips_pic == SVR4_PIC && ! mips_big_got)
{
- char *p;
int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
/* If this is a reference to an external symbol, we want
@@ -6258,13 +6146,12 @@ macro (struct mips_cl_insn *ip)
assert (offset_expr.X_op == O_symbol);
if (HAVE_NEWABI)
{
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
- "t,o(b)", tempreg, BFD_RELOC_MIPS_GOT_PAGE,
- mips_gp_register);
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
+ BFD_RELOC_MIPS_GOT_PAGE, mips_gp_register);
if (breg != 0)
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, tempreg, breg);
- macro_build (NULL, &icnt, &offset_expr, s, fmt, treg,
+ macro_build (&offset_expr, s, fmt, treg,
BFD_RELOC_MIPS_GOT_OFST, tempreg);
if (! used_at)
@@ -6277,25 +6164,22 @@ macro (struct mips_cl_insn *ip)
if (expr1.X_add_number < -0x8000
|| expr1.X_add_number >= 0x8000)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
- frag_grow (20);
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
- tempreg, lw_reloc_type, mips_gp_register);
- macro_build (NULL, &icnt, NULL, "nop", "");
- p = frag_var (rs_machine_dependent, 4, 0,
- RELAX_ENCODE (0, 4, -8, 0, 0, 0),
- offset_expr.X_add_symbol, 0, NULL);
- macro_build (p, &icnt, &offset_expr, ADDRESS_ADDI_INSN,
- "t,r,j", tempreg, tempreg, BFD_RELOC_LO16);
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
+ lw_reloc_type, mips_gp_register);
+ macro_build (NULL, "nop", "");
+ relax_start (offset_expr.X_add_symbol);
+ relax_switch ();
+ macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", tempreg,
+ tempreg, BFD_RELOC_LO16);
+ relax_end ();
if (breg != 0)
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, tempreg, breg);
- macro_build (NULL, &icnt, &expr1, s, fmt, treg, BFD_RELOC_LO16,
- tempreg);
+ macro_build (&expr1, s, fmt, treg, BFD_RELOC_LO16, tempreg);
}
else if (mips_pic == SVR4_PIC && ! HAVE_NEWABI)
{
- int gpdel;
- char *p;
+ int gpdelay;
/* If this is a reference to an external symbol, we want
lui $tempreg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
@@ -6319,43 +6203,31 @@ macro (struct mips_cl_insn *ip)
if (expr1.X_add_number < -0x8000
|| expr1.X_add_number >= 0x8000)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
- if (reg_needs_delay (mips_gp_register))
- gpdel = 4;
- else
- gpdel = 0;
- frag_grow (36);
- macro_build (NULL, &icnt, &offset_expr, "lui", "t,u", tempreg,
+ gpdelay = reg_needs_delay (mips_gp_register);
+ relax_start (offset_expr.X_add_symbol);
+ macro_build (&offset_expr, "lui", "t,u", tempreg,
BFD_RELOC_MIPS_GOT_HI16);
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
- tempreg, tempreg, mips_gp_register);
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
- tempreg, BFD_RELOC_MIPS_GOT_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, 0, NULL);
- if (gpdel > 0)
- {
- macro_build (p, &icnt, NULL, "nop", "");
- p += 4;
- }
- macro_build (p, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
- tempreg, BFD_RELOC_MIPS_GOT16, mips_gp_register);
- p += 4;
- macro_build (p, &icnt, NULL, "nop", "");
- p += 4;
- macro_build (p, &icnt, &offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
- tempreg, tempreg, BFD_RELOC_LO16);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", tempreg, tempreg,
+ mips_gp_register);
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
+ BFD_RELOC_MIPS_GOT_LO16, tempreg);
+ relax_switch ();
+ if (gpdelay)
+ macro_build (NULL, "nop", "");
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
+ BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ macro_build (NULL, "nop", "");
+ macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", tempreg,
+ tempreg, BFD_RELOC_LO16);
+ relax_end ();
+
if (breg != 0)
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, tempreg, breg);
- macro_build (NULL, &icnt, &expr1, s, fmt, treg, BFD_RELOC_LO16,
- tempreg);
+ macro_build (&expr1, s, fmt, treg, BFD_RELOC_LO16, tempreg);
}
else if (mips_pic == SVR4_PIC && HAVE_NEWABI)
{
- char *p;
- int bregsz = breg != 0 ? 4 : 0;
-
/* If this is a reference to an external symbol, we want
lui $tempreg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
add $tempreg,$tempreg,$gp
@@ -6365,37 +6237,33 @@ macro (struct mips_cl_insn *ip)
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_PAGE)
<op> $treg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_OFST) */
assert (offset_expr.X_op == O_symbol);
- frag_grow (36);
- frag_now->tc_frag_data.tc_fr_offset =
- expr1.X_add_number = offset_expr.X_add_number;
+ expr1.X_add_number = offset_expr.X_add_number;
offset_expr.X_add_number = 0;
if (expr1.X_add_number < -0x8000
|| expr1.X_add_number >= 0x8000)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
- macro_build (NULL, &icnt, &offset_expr, "lui", "t,u", tempreg,
+ relax_start (offset_expr.X_add_symbol);
+ macro_build (&offset_expr, "lui", "t,u", tempreg,
BFD_RELOC_MIPS_GOT_HI16);
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
- tempreg, tempreg, mips_gp_register);
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
- tempreg, BFD_RELOC_MIPS_GOT_LO16, tempreg);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", tempreg, tempreg,
+ mips_gp_register);
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
+ BFD_RELOC_MIPS_GOT_LO16, tempreg);
if (breg != 0)
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, tempreg, breg);
- macro_build (NULL, &icnt, &expr1, s, fmt, treg, BFD_RELOC_LO16,
- tempreg);
+ macro_build (&expr1, s, fmt, treg, BFD_RELOC_LO16, tempreg);
+ relax_switch ();
offset_expr.X_add_number = expr1.X_add_number;
- p = frag_var (rs_machine_dependent, 12 + bregsz, 0,
- RELAX_ENCODE (16 + bregsz, 8 + bregsz,
- 0, 4 + bregsz, 0, 0),
- offset_expr.X_add_symbol, 0, NULL);
- macro_build (p, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
- tempreg, BFD_RELOC_MIPS_GOT_PAGE, mips_gp_register);
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
+ BFD_RELOC_MIPS_GOT_PAGE, mips_gp_register);
if (breg != 0)
- macro_build (p + 4, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, tempreg, breg);
- macro_build (p + 4 + bregsz, &icnt, &offset_expr, s, fmt, treg,
+ macro_build (&offset_expr, s, fmt, treg,
BFD_RELOC_MIPS_GOT_OFST, tempreg);
+ relax_end ();
}
else if (mips_pic == EMBEDDED_PIC)
{
@@ -6408,15 +6276,15 @@ macro (struct mips_cl_insn *ip)
assert (offset_expr.X_op == O_symbol);
if (breg == 0)
{
- macro_build (NULL, &icnt, &offset_expr, s, fmt, treg,
- BFD_RELOC_GPREL16, mips_gp_register);
+ macro_build (&offset_expr, s, fmt, treg, BFD_RELOC_GPREL16,
+ mips_gp_register);
used_at = 0;
}
else
{
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, breg, mips_gp_register);
- macro_build (NULL, &icnt, &offset_expr, s, fmt, treg,
+ macro_build (&offset_expr, s, fmt, treg,
BFD_RELOC_GPREL16, tempreg);
}
}
@@ -6430,18 +6298,18 @@ macro (struct mips_cl_insn *ip)
case M_LI:
case M_LI_S:
- load_register (&icnt, treg, &imm_expr, 0);
+ load_register (treg, &imm_expr, 0);
return;
case M_DLI:
- load_register (&icnt, treg, &imm_expr, 1);
+ load_register (treg, &imm_expr, 1);
return;
case M_LI_SS:
if (imm_expr.X_op == O_constant)
{
- load_register (&icnt, AT, &imm_expr, 0);
- macro_build (NULL, &icnt, NULL, "mtc1", "t,G", AT, treg);
+ load_register (AT, &imm_expr, 0);
+ macro_build (NULL, "mtc1", "t,G", AT, treg);
break;
}
else
@@ -6451,7 +6319,7 @@ macro (struct mips_cl_insn *ip)
(offset_expr.X_add_symbol)),
".lit4") == 0
&& offset_expr.X_add_number == 0);
- macro_build (NULL, &icnt, &offset_expr, "lwc1", "T,o(b)", treg,
+ macro_build (&offset_expr, "lwc1", "T,o(b)", treg,
BFD_RELOC_MIPS_LITERAL, mips_gp_register);
return;
}
@@ -6464,7 +6332,7 @@ macro (struct mips_cl_insn *ip)
if (imm_expr.X_op == O_constant || imm_expr.X_op == O_big)
{
if (HAVE_64BIT_GPRS)
- load_register (&icnt, treg, &imm_expr, 1);
+ load_register (treg, &imm_expr, 1);
else
{
int hreg, lreg;
@@ -6481,15 +6349,15 @@ macro (struct mips_cl_insn *ip)
}
if (hreg <= 31)
- load_register (&icnt, hreg, &imm_expr, 0);
+ load_register (hreg, &imm_expr, 0);
if (lreg <= 31)
{
if (offset_expr.X_op == O_absent)
- move_register (&icnt, lreg, 0);
+ move_register (lreg, 0);
else
{
assert (offset_expr.X_op == O_constant);
- load_register (&icnt, lreg, &offset_expr, 0);
+ load_register (lreg, &offset_expr, 0);
}
}
}
@@ -6500,19 +6368,19 @@ macro (struct mips_cl_insn *ip)
upper 16 bits of the address. */
if (mips_pic == NO_PIC)
{
- macro_build_lui (NULL, &icnt, &offset_expr, AT);
+ macro_build_lui (&offset_expr, AT);
}
else if (mips_pic == SVR4_PIC)
{
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
- AT, BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", AT,
+ BFD_RELOC_MIPS_GOT16, mips_gp_register);
}
else if (mips_pic == EMBEDDED_PIC)
{
/* For embedded PIC we pick up the entire address off $gp in
a single instruction. */
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
- AT, mips_gp_register, BFD_RELOC_GPREL16);
+ macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", AT,
+ mips_gp_register, BFD_RELOC_GPREL16);
offset_expr.X_op = O_constant;
offset_expr.X_add_number = 0;
}
@@ -6521,27 +6389,19 @@ macro (struct mips_cl_insn *ip)
/* Now we load the register(s). */
if (HAVE_64BIT_GPRS)
- macro_build (NULL, &icnt, &offset_expr, "ld", "t,o(b)", treg,
- BFD_RELOC_LO16, AT);
+ macro_build (&offset_expr, "ld", "t,o(b)", treg, BFD_RELOC_LO16, AT);
else
{
- macro_build (NULL, &icnt, &offset_expr, "lw", "t,o(b)", treg,
- BFD_RELOC_LO16, AT);
+ macro_build (&offset_expr, "lw", "t,o(b)", treg, BFD_RELOC_LO16, AT);
if (treg != RA)
{
/* FIXME: How in the world do we deal with the possible
overflow here? */
offset_expr.X_add_number += 4;
- macro_build (NULL, &icnt, &offset_expr, "lw", "t,o(b)",
+ macro_build (&offset_expr, "lw", "t,o(b)",
treg + 1, BFD_RELOC_LO16, AT);
}
}
-
- /* To avoid confusion in tc_gen_reloc, we must ensure that this
- does not become a variant frag. */
- frag_wane (frag_now);
- frag_new (0);
-
break;
case M_LI_DD:
@@ -6552,22 +6412,22 @@ macro (struct mips_cl_insn *ip)
OFFSET_EXPR. */
if (imm_expr.X_op == O_constant || imm_expr.X_op == O_big)
{
- load_register (&icnt, AT, &imm_expr, HAVE_64BIT_FPRS);
+ load_register (AT, &imm_expr, HAVE_64BIT_FPRS);
if (HAVE_64BIT_FPRS)
{
assert (HAVE_64BIT_GPRS);
- macro_build (NULL, &icnt, NULL, "dmtc1", "t,S", AT, treg);
+ macro_build (NULL, "dmtc1", "t,S", AT, treg);
}
else
{
- macro_build (NULL, &icnt, NULL, "mtc1", "t,G", AT, treg + 1);
+ macro_build (NULL, "mtc1", "t,G", AT, treg + 1);
if (offset_expr.X_op == O_absent)
- macro_build (NULL, &icnt, NULL, "mtc1", "t,G", 0, treg);
+ macro_build (NULL, "mtc1", "t,G", 0, treg);
else
{
assert (offset_expr.X_op == O_constant);
- load_register (&icnt, AT, &offset_expr, 0);
- macro_build (NULL, &icnt, NULL, "mtc1", "t,G", AT, treg);
+ load_register (AT, &offset_expr, 0);
+ macro_build (NULL, "mtc1", "t,G", AT, treg);
}
}
break;
@@ -6580,7 +6440,7 @@ macro (struct mips_cl_insn *ip)
{
if (mips_opts.isa != ISA_MIPS1)
{
- macro_build (NULL, &icnt, &offset_expr, "ldc1", "T,o(b)", treg,
+ macro_build (&offset_expr, "ldc1", "T,o(b)", treg,
BFD_RELOC_MIPS_LITERAL, mips_gp_register);
return;
}
@@ -6592,25 +6452,18 @@ macro (struct mips_cl_insn *ip)
{
assert (strcmp (s, RDATA_SECTION_NAME) == 0);
if (mips_pic == SVR4_PIC)
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
- "t,o(b)", AT, BFD_RELOC_MIPS_GOT16,
- mips_gp_register);
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", AT,
+ BFD_RELOC_MIPS_GOT16, mips_gp_register);
else
{
/* FIXME: This won't work for a 64 bit address. */
- macro_build_lui (NULL, &icnt, &offset_expr, AT);
+ macro_build_lui (&offset_expr, AT);
}
if (mips_opts.isa != ISA_MIPS1)
{
- macro_build (NULL, &icnt, &offset_expr, "ldc1", "T,o(b)", treg,
- BFD_RELOC_LO16, AT);
-
- /* To avoid confusion in tc_gen_reloc, we must ensure
- that this does not become a variant frag. */
- frag_wane (frag_now);
- frag_new (0);
-
+ macro_build (&offset_expr, "ldc1", "T,o(b)",
+ treg, BFD_RELOC_LO16, AT);
break;
}
breg = AT;
@@ -6629,19 +6482,14 @@ macro (struct mips_cl_insn *ip)
r = BFD_RELOC_LO16;
dob:
assert (mips_opts.isa == ISA_MIPS1);
- macro_build (NULL, &icnt, &offset_expr, "lwc1", "T,o(b)",
+ macro_build (&offset_expr, "lwc1", "T,o(b)",
target_big_endian ? treg + 1 : treg, r, breg);
/* FIXME: A possible overflow which I don't know how to deal
with. */
offset_expr.X_add_number += 4;
- macro_build (NULL, &icnt, &offset_expr, "lwc1", "T,o(b)",
+ macro_build (&offset_expr, "lwc1", "T,o(b)",
target_big_endian ? treg : treg + 1, r, breg);
- /* To avoid confusion in tc_gen_reloc, we must ensure that this
- does not become a variant frag. */
- frag_wane (frag_now);
- frag_new (0);
-
if (breg != AT)
return;
break;
@@ -6738,8 +6586,6 @@ macro (struct mips_cl_insn *ip)
if (mips_pic == NO_PIC
|| offset_expr.X_op == O_constant)
{
- char *p;
-
/* If this is a reference to a GP relative symbol, we want
<op> $treg,<sym>($gp) (BFD_RELOC_GPREL16)
<op> $treg+1,<sym>+4($gp) (BFD_RELOC_GPREL16)
@@ -6756,34 +6602,25 @@ macro (struct mips_cl_insn *ip)
the last case. */
if ((valueT) offset_expr.X_add_number > MAX_GPREL_OFFSET
|| nopic_need_relax (offset_expr.X_add_symbol, 1))
- {
- p = NULL;
- used_at = 1;
- }
+ used_at = 1;
else
{
- int off;
-
+ relax_start (offset_expr.X_add_symbol);
if (breg == 0)
{
- frag_grow (28);
tempreg = mips_gp_register;
- off = 0;
used_at = 0;
}
else
{
- frag_grow (36);
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
AT, breg, mips_gp_register);
tempreg = AT;
- off = 4;
used_at = 1;
}
/* Itbl support may require additional care here. */
- macro_build (NULL, &icnt, &offset_expr, s, fmt,
- coproc ? treg + 1 : treg,
+ macro_build (&offset_expr, s, fmt, coproc ? treg + 1 : treg,
BFD_RELOC_GPREL16, tempreg);
offset_expr.X_add_number += 4;
@@ -6792,15 +6629,11 @@ macro (struct mips_cl_insn *ip)
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
/* Itbl support may require additional care here. */
- macro_build (NULL, &icnt, &offset_expr, s, fmt,
- coproc ? treg : treg + 1,
+ macro_build (&offset_expr, s, fmt, coproc ? treg : treg + 1,
BFD_RELOC_GPREL16, tempreg);
mips_optimize = hold_mips_optimize;
- p = frag_var (rs_machine_dependent, 12 + off, 0,
- RELAX_ENCODE (8 + off, 12 + off, 0, 4 + off, 1,
- used_at && mips_opts.noat),
- offset_expr.X_add_symbol, 0, NULL);
+ relax_switch ();
/* We just generated two relocs. When tc_gen_reloc
handles this case, it will skip the first reloc and
@@ -6823,33 +6656,22 @@ macro (struct mips_cl_insn *ip)
offset_expr.X_op = O_constant;
}
}
- macro_build_lui (p, &icnt, &offset_expr, AT);
- if (p != NULL)
- p += 4;
+ macro_build_lui (&offset_expr, AT);
if (breg != 0)
- {
- macro_build (p, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
- AT, breg, AT);
- if (p != NULL)
- p += 4;
- }
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, breg, AT);
/* Itbl support may require additional care here. */
- macro_build (p, &icnt, &offset_expr, s, fmt,
- coproc ? treg + 1 : treg,
+ macro_build (&offset_expr, s, fmt, coproc ? treg + 1 : treg,
BFD_RELOC_LO16, AT);
- if (p != NULL)
- 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,
+ macro_build (&offset_expr, s, fmt, coproc ? treg : treg + 1,
BFD_RELOC_LO16, AT);
+ if (mips_relax.sequence)
+ relax_end ();
}
else if (mips_pic == SVR4_PIC && ! mips_big_got)
{
- int off;
-
/* If this is a reference to an external symbol, we want
lw $at,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
nop
@@ -6865,43 +6687,39 @@ macro (struct mips_cl_insn *ip)
in the lwc1 instructions. */
used_at = 1;
expr1.X_add_number = offset_expr.X_add_number;
- offset_expr.X_add_number = 0;
if (expr1.X_add_number < -0x8000
|| expr1.X_add_number >= 0x8000 - 4)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
- if (breg == 0)
- off = 0;
- else
- off = 4;
- frag_grow (24 + off);
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
- AT, BFD_RELOC_MIPS_GOT16, mips_gp_register);
- macro_build (NULL, &icnt, NULL, "nop", "");
+ load_got_offset (AT, &offset_expr);
+ macro_build (NULL, "nop", "");
if (breg != 0)
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
- AT, breg, AT);
- /* Itbl support may require additional care here. */
- macro_build (NULL, &icnt, &expr1, s, fmt, coproc ? treg + 1 : treg,
- BFD_RELOC_LO16, AT);
- expr1.X_add_number += 4;
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, breg, AT);
/* Set mips_optimize to 2 to avoid inserting an undesired
nop. */
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
+
/* Itbl support may require additional care here. */
- macro_build (NULL, &icnt, &expr1, s, fmt, coproc ? treg : treg + 1,
+ relax_start (offset_expr.X_add_symbol);
+ macro_build (&expr1, s, fmt, coproc ? treg + 1 : treg,
BFD_RELOC_LO16, AT);
- mips_optimize = hold_mips_optimize;
+ expr1.X_add_number += 4;
+ macro_build (&expr1, s, fmt, coproc ? treg : treg + 1,
+ BFD_RELOC_LO16, AT);
+ relax_switch ();
+ macro_build (&offset_expr, s, fmt, coproc ? treg + 1 : treg,
+ BFD_RELOC_LO16, AT);
+ offset_expr.X_add_number += 4;
+ macro_build (&offset_expr, s, fmt, coproc ? treg : treg + 1,
+ BFD_RELOC_LO16, AT);
+ relax_end ();
- (void) frag_var (rs_machine_dependent, 0, 0,
- RELAX_ENCODE (0, 0, -16 - off, -8, 1, 0),
- offset_expr.X_add_symbol, 0, NULL);
+ mips_optimize = hold_mips_optimize;
}
else if (mips_pic == SVR4_PIC)
{
- int gpdel, off;
- char *p;
+ int gpdelay;
/* If this is a reference to an external symbol, we want
lui $at,<sym> (BFD_RELOC_MIPS_GOT_HI16)
@@ -6924,27 +6742,19 @@ macro (struct mips_cl_insn *ip)
if (expr1.X_add_number < -0x8000
|| expr1.X_add_number >= 0x8000 - 4)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
- if (reg_needs_delay (mips_gp_register))
- gpdel = 4;
- else
- gpdel = 0;
- if (breg == 0)
- off = 0;
- else
- off = 4;
- frag_grow (56);
- macro_build (NULL, &icnt, &offset_expr, "lui", "t,u", AT,
- BFD_RELOC_MIPS_GOT_HI16);
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ gpdelay = reg_needs_delay (mips_gp_register);
+ relax_start (offset_expr.X_add_symbol);
+ macro_build (&offset_expr, "lui", "t,u",
+ AT, BFD_RELOC_MIPS_GOT_HI16);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
AT, AT, mips_gp_register);
- macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
AT, BFD_RELOC_MIPS_GOT_LO16, AT);
- macro_build (NULL, &icnt, NULL, "nop", "");
+ macro_build (NULL, "nop", "");
if (breg != 0)
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
- AT, breg, AT);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, breg, AT);
/* Itbl support may require additional care here. */
- macro_build (NULL, &icnt, &expr1, s, fmt, coproc ? treg + 1 : treg,
+ macro_build (&expr1, s, fmt, coproc ? treg + 1 : treg,
BFD_RELOC_LO16, AT);
expr1.X_add_number += 4;
@@ -6953,45 +6763,34 @@ macro (struct mips_cl_insn *ip)
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
/* Itbl support may require additional care here. */
- macro_build (NULL, &icnt, &expr1, s, fmt, coproc ? treg : treg + 1,
+ macro_build (&expr1, s, fmt, coproc ? treg : treg + 1,
BFD_RELOC_LO16, AT);
mips_optimize = hold_mips_optimize;
expr1.X_add_number -= 4;
- 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, 0, NULL);
- if (gpdel > 0)
- {
- macro_build (p, &icnt, NULL, "nop", "");
- p += 4;
- }
- macro_build (p, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
- AT, BFD_RELOC_MIPS_GOT16, mips_gp_register);
- p += 4;
- macro_build (p, &icnt, NULL, "nop", "");
- p += 4;
+ relax_switch ();
+ offset_expr.X_add_number = expr1.X_add_number;
+ if (gpdelay)
+ macro_build (NULL, "nop", "");
+ macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", AT,
+ BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ macro_build (NULL, "nop", "");
if (breg != 0)
- {
- macro_build (p, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
- AT, breg, AT);
- p += 4;
- }
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, breg, AT);
/* Itbl support may require additional care here. */
- macro_build (p, &icnt, &expr1, s, fmt, coproc ? treg + 1 : treg,
+ macro_build (&offset_expr, s, fmt, coproc ? treg + 1 : treg,
BFD_RELOC_LO16, AT);
- p += 4;
- expr1.X_add_number += 4;
+ offset_expr.X_add_number += 4;
/* Set mips_optimize to 2 to avoid inserting an undesired
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,
+ macro_build (&offset_expr, s, fmt, coproc ? treg : treg + 1,
BFD_RELOC_LO16, AT);
mips_optimize = hold_mips_optimize;
+ relax_end ();
}
else if (mips_pic == EMBEDDED_PIC)
{
@@ -7010,20 +6809,18 @@ macro (struct mips_cl_insn *ip)
}
else
{
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
AT, breg, mips_gp_register);
tempreg = AT;
used_at = 1;
}
/* Itbl support may require additional care here. */
- macro_build (NULL, &icnt, &offset_expr, s, fmt,
- coproc ? treg + 1 : treg,
+ macro_build (&offset_expr, s, fmt, coproc ? treg + 1 : treg,
BFD_RELOC_GPREL16, tempreg);
offset_expr.X_add_number += 4;
/* Itbl support may require additional care here. */
- macro_build (NULL, &icnt, &offset_expr, s, fmt,
- coproc ? treg : treg + 1,
+ macro_build (&offset_expr, s, fmt, coproc ? treg : treg + 1,
BFD_RELOC_GPREL16, tempreg);
}
else
@@ -7041,11 +6838,9 @@ macro (struct mips_cl_insn *ip)
s = "sw";
sd_ob:
assert (HAVE_32BIT_ADDRESSES);
- macro_build (NULL, &icnt, &offset_expr, s, "t,o(b)", treg,
- BFD_RELOC_LO16, breg);
+ macro_build (&offset_expr, s, "t,o(b)", treg, BFD_RELOC_LO16, breg);
offset_expr.X_add_number += 4;
- macro_build (NULL, &icnt, &offset_expr, s, "t,o(b)", treg + 1,
- BFD_RELOC_LO16, breg);
+ macro_build (&offset_expr, s, "t,o(b)", treg + 1, BFD_RELOC_LO16, breg);
return;
/* New code added to support COPZ instructions.
@@ -7079,11 +6874,11 @@ macro (struct mips_cl_insn *ip)
copz:
/* For now we just do C (same as Cz). The parameter will be
stored in insn_opcode by mips_ip. */
- macro_build (NULL, &icnt, NULL, s, "C", ip->insn_opcode);
+ macro_build (NULL, s, "C", ip->insn_opcode);
return;
case M_MOVE:
- move_register (&icnt, dreg, sreg);
+ move_register (dreg, sreg);
return;
#ifdef LOSING_COMPILER
@@ -7102,7 +6897,7 @@ macro (struct mips_cl_insn *ip)
s = ip->insn_mo->name;
s2 = "cop3";
coproc = ITBL_DECODE_PNUM (immed_expr);;
- macro_build (NULL, &icnt, &immed_expr, s, "C");
+ macro_build (&immed_expr, s, "C");
return;
}
macro2 (ip);
@@ -7118,7 +6913,6 @@ macro2 (struct mips_cl_insn *ip)
register int treg, sreg, dreg, breg;
int tempreg;
int mask;
- int icnt = 0;
int used_at;
expressionS expr1;
const char *s;
@@ -7132,7 +6926,6 @@ macro2 (struct mips_cl_insn *ip)
int off;
offsetT maxnum;
bfd_reloc_code_real_type r;
- char *p;
treg = (ip->insn_opcode >> 16) & 0x1f;
dreg = (ip->insn_opcode >> 11) & 0x1f;
@@ -7151,9 +6944,8 @@ macro2 (struct mips_cl_insn *ip)
case M_DMUL:
dbl = 1;
case M_MUL:
- macro_build (NULL, &icnt, NULL, dbl ? "dmultu" : "multu", "s,t",
- sreg, treg);
- macro_build (NULL, &icnt, NULL, "mflo", "d", dreg);
+ macro_build (NULL, dbl ? "dmultu" : "multu", "s,t", sreg, treg);
+ macro_build (NULL, "mflo", "d", dreg);
return;
case M_DMUL_I:
@@ -7162,10 +6954,9 @@ macro2 (struct mips_cl_insn *ip)
/* The MIPS assembler some times generates shifts and adds. I'm
not trying to be that fancy. GCC should do this for us
anyway. */
- load_register (&icnt, AT, &imm_expr, dbl);
- macro_build (NULL, &icnt, NULL, dbl ? "dmult" : "mult", "s,t",
- sreg, AT);
- macro_build (NULL, &icnt, NULL, "mflo", "d", dreg);
+ load_register (AT, &imm_expr, dbl);
+ macro_build (NULL, dbl ? "dmult" : "mult", "s,t", sreg, AT);
+ macro_build (NULL, "mflo", "d", dreg);
break;
case M_DMULO_I:
@@ -7182,24 +6973,22 @@ macro2 (struct mips_cl_insn *ip)
++mips_opts.noreorder;
mips_any_noreorder = 1;
if (imm)
- load_register (&icnt, AT, &imm_expr, dbl);
- macro_build (NULL, &icnt, NULL, dbl ? "dmult" : "mult", "s,t",
- sreg, imm ? AT : treg);
- macro_build (NULL, &icnt, NULL, "mflo", "d", dreg);
- macro_build (NULL, &icnt, NULL, dbl ? "dsra32" : "sra", "d,w,<",
- dreg, dreg, RA);
- macro_build (NULL, &icnt, NULL, "mfhi", "d", AT);
+ load_register (AT, &imm_expr, dbl);
+ macro_build (NULL, dbl ? "dmult" : "mult", "s,t", sreg, imm ? AT : treg);
+ macro_build (NULL, "mflo", "d", dreg);
+ macro_build (NULL, dbl ? "dsra32" : "sra", "d,w,<", dreg, dreg, RA);
+ macro_build (NULL, "mfhi", "d", AT);
if (mips_trap)
- macro_build (NULL, &icnt, NULL, "tne", "s,t,q", dreg, AT, 6);
+ macro_build (NULL, "tne", "s,t,q", dreg, AT, 6);
else
{
expr1.X_add_number = 8;
- macro_build (NULL, &icnt, &expr1, "beq", "s,t,p", dreg, AT);
- macro_build (NULL, &icnt, NULL, "nop", "", 0);
- macro_build (NULL, &icnt, NULL, "break", "c", 6);
+ macro_build (&expr1, "beq", "s,t,p", dreg, AT);
+ macro_build (NULL, "nop", "", 0);
+ macro_build (NULL, "break", "c", 6);
}
--mips_opts.noreorder;
- macro_build (NULL, &icnt, NULL, "mflo", "d", dreg);
+ macro_build (NULL, "mflo", "d", dreg);
break;
case M_DMULOU_I:
@@ -7216,19 +7005,19 @@ macro2 (struct mips_cl_insn *ip)
++mips_opts.noreorder;
mips_any_noreorder = 1;
if (imm)
- load_register (&icnt, AT, &imm_expr, dbl);
- macro_build (NULL, &icnt, NULL, dbl ? "dmultu" : "multu", "s,t",
+ load_register (AT, &imm_expr, dbl);
+ macro_build (NULL, dbl ? "dmultu" : "multu", "s,t",
sreg, imm ? AT : treg);
- macro_build (NULL, &icnt, NULL, "mfhi", "d", AT);
- macro_build (NULL, &icnt, NULL, "mflo", "d", dreg);
+ macro_build (NULL, "mfhi", "d", AT);
+ macro_build (NULL, "mflo", "d", dreg);
if (mips_trap)
- macro_build (NULL, &icnt, NULL, "tne", "s,t,q", AT, 0, 6);
+ macro_build (NULL, "tne", "s,t,q", AT, 0, 6);
else
{
expr1.X_add_number = 8;
- macro_build (NULL, &icnt, &expr1, "beq", "s,t,p", AT, 0);
- macro_build (NULL, &icnt, NULL, "nop", "", 0);
- macro_build (NULL, &icnt, NULL, "break", "c", 6);
+ macro_build (&expr1, "beq", "s,t,p", AT, 0);
+ macro_build (NULL, "nop", "", 0);
+ macro_build (NULL, "break", "c", 6);
}
--mips_opts.noreorder;
break;
@@ -7246,17 +7035,16 @@ macro2 (struct mips_cl_insn *ip)
tempreg = dreg;
used_at = 0;
}
- macro_build (NULL, &icnt, NULL, "dnegu", "d,w", tempreg, treg);
- macro_build (NULL, &icnt, NULL, "drorv", "d,t,s", dreg, sreg,
- tempreg);
+ macro_build (NULL, "dnegu", "d,w", tempreg, treg);
+ macro_build (NULL, "drorv", "d,t,s", dreg, sreg, tempreg);
if (used_at)
break;
return;
}
- macro_build (NULL, &icnt, NULL, "dsubu", "d,v,t", AT, 0, treg);
- macro_build (NULL, &icnt, NULL, "dsrlv", "d,t,s", AT, sreg, AT);
- macro_build (NULL, &icnt, NULL, "dsllv", "d,t,s", dreg, sreg, treg);
- macro_build (NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
+ macro_build (NULL, "dsubu", "d,v,t", AT, 0, treg);
+ macro_build (NULL, "dsrlv", "d,t,s", AT, sreg, AT);
+ macro_build (NULL, "dsllv", "d,t,s", dreg, sreg, treg);
+ macro_build (NULL, "or", "d,v,t", dreg, dreg, AT);
break;
case M_ROL:
@@ -7272,17 +7060,16 @@ macro2 (struct mips_cl_insn *ip)
tempreg = dreg;
used_at = 0;
}
- macro_build (NULL, &icnt, NULL, "negu", "d,w", tempreg, treg);
- macro_build (NULL, &icnt, NULL, "rorv", "d,t,s", dreg, sreg,
- tempreg);
+ macro_build (NULL, "negu", "d,w", tempreg, treg);
+ macro_build (NULL, "rorv", "d,t,s", dreg, sreg, tempreg);
if (used_at)
break;
return;
}
- macro_build (NULL, &icnt, NULL, "subu", "d,v,t", AT, 0, treg);
- macro_build (NULL, &icnt, NULL, "srlv", "d,t,s", AT, sreg, AT);
- macro_build (NULL, &icnt, NULL, "sllv", "d,t,s", dreg, sreg, treg);
- macro_build (NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
+ macro_build (NULL, "subu", "d,v,t", AT, 0, treg);
+ macro_build (NULL, "srlv", "d,t,s", AT, sreg, AT);
+ macro_build (NULL, "sllv", "d,t,s", dreg, sreg, treg);
+ macro_build (NULL, "or", "d,v,t", dreg, dreg, AT);
break;
case M_DROL_I:
@@ -7297,25 +7084,22 @@ macro2 (struct mips_cl_insn *ip)
{
rot = (64 - rot) & 0x3f;
if (rot >= 32)
- macro_build (NULL, &icnt, NULL, "dror32", "d,w,<",
- dreg, sreg, rot - 32);
+ macro_build (NULL, "dror32", "d,w,<", dreg, sreg, rot - 32);
else
- macro_build (NULL, &icnt, NULL, "dror", "d,w,<",
- dreg, sreg, rot);
+ macro_build (NULL, "dror", "d,w,<", dreg, sreg, rot);
return;
}
if (rot == 0)
{
- macro_build (NULL, &icnt, NULL, "dsrl", "d,w,<", dreg, sreg, 0);
+ macro_build (NULL, "dsrl", "d,w,<", dreg, sreg, 0);
return;
}
l = (rot < 0x20) ? "dsll" : "dsll32";
r = ((0x40 - rot) < 0x20) ? "dsrl" : "dsrl32";
rot &= 0x1f;
- macro_build (NULL, &icnt, NULL, l, "d,w,<", AT, sreg, rot);
- macro_build (NULL, &icnt, NULL, r, "d,w,<", dreg, sreg,
- (0x20 - rot) & 0x1f);
- macro_build (NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
+ macro_build (NULL, l, "d,w,<", AT, sreg, rot);
+ macro_build (NULL, r, "d,w,<", dreg, sreg, (0x20 - rot) & 0x1f);
+ macro_build (NULL, "or", "d,v,t", dreg, dreg, AT);
}
break;
@@ -7328,44 +7112,42 @@ macro2 (struct mips_cl_insn *ip)
rot = imm_expr.X_add_number & 0x1f;
if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_opts.arch))
{
- macro_build (NULL, &icnt, NULL, "ror", "d,w,<", dreg, sreg,
- (32 - rot) & 0x1f);
+ macro_build (NULL, "ror", "d,w,<", dreg, sreg, (32 - rot) & 0x1f);
return;
}
if (rot == 0)
{
- macro_build (NULL, &icnt, NULL, "srl", "d,w,<", dreg, sreg, 0);
+ macro_build (NULL, "srl", "d,w,<", dreg, sreg, 0);
return;
}
- macro_build (NULL, &icnt, NULL, "sll", "d,w,<", AT, sreg, rot);
- macro_build (NULL, &icnt, NULL, "srl", "d,w,<", dreg, sreg,
- (0x20 - rot) & 0x1f);
- macro_build (NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
+ macro_build (NULL, "sll", "d,w,<", AT, sreg, rot);
+ macro_build (NULL, "srl", "d,w,<", dreg, sreg, (0x20 - rot) & 0x1f);
+ macro_build (NULL, "or", "d,v,t", dreg, dreg, AT);
}
break;
case M_DROR:
if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_opts.arch))
{
- macro_build (NULL, &icnt, NULL, "drorv", "d,t,s", dreg, sreg, treg);
+ macro_build (NULL, "drorv", "d,t,s", dreg, sreg, treg);
return;
}
- macro_build (NULL, &icnt, NULL, "dsubu", "d,v,t", AT, 0, treg);
- macro_build (NULL, &icnt, NULL, "dsllv", "d,t,s", AT, sreg, AT);
- macro_build (NULL, &icnt, NULL, "dsrlv", "d,t,s", dreg, sreg, treg);
- macro_build (NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
+ macro_build (NULL, "dsubu", "d,v,t", AT, 0, treg);
+ macro_build (NULL, "dsllv", "d,t,s", AT, sreg, AT);
+ macro_build (NULL, "dsrlv", "d,t,s", dreg, sreg, treg);
+ macro_build (NULL, "or", "d,v,t", dreg, dreg, AT);
break;
case M_ROR:
if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_opts.arch))
{
- macro_build (NULL, &icnt, NULL, "rorv", "d,t,s", dreg, sreg, treg);
+ macro_build (NULL, "rorv", "d,t,s", dreg, sreg, treg);
return;
}
- macro_build (NULL, &icnt, NULL, "subu", "d,v,t", AT, 0, treg);
- macro_build (NULL, &icnt, NULL, "sllv", "d,t,s", AT, sreg, AT);
- macro_build (NULL, &icnt, NULL, "srlv", "d,t,s", dreg, sreg, treg);
- macro_build (NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
+ macro_build (NULL, "subu", "d,v,t", AT, 0, treg);
+ macro_build (NULL, "sllv", "d,t,s", AT, sreg, AT);
+ macro_build (NULL, "srlv", "d,t,s", dreg, sreg, treg);
+ macro_build (NULL, "or", "d,v,t", dreg, dreg, AT);
break;
case M_DROR_I:
@@ -7379,25 +7161,22 @@ macro2 (struct mips_cl_insn *ip)
if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_opts.arch))
{
if (rot >= 32)
- macro_build (NULL, &icnt, NULL, "dror32", "d,w,<",
- dreg, sreg, rot - 32);
+ macro_build (NULL, "dror32", "d,w,<", dreg, sreg, rot - 32);
else
- macro_build (NULL, &icnt, NULL, "dror", "d,w,<",
- dreg, sreg, rot);
+ macro_build (NULL, "dror", "d,w,<", dreg, sreg, rot);
return;
}
if (rot == 0)
{
- macro_build (NULL, &icnt, NULL, "dsrl", "d,w,<", dreg, sreg, 0);
+ macro_build (NULL, "dsrl", "d,w,<", dreg, sreg, 0);
return;
}
r = (rot < 0x20) ? "dsrl" : "dsrl32";
l = ((0x40 - rot) < 0x20) ? "dsll" : "dsll32";
rot &= 0x1f;
- macro_build (NULL, &icnt, NULL, r, "d,w,<", AT, sreg, rot);
- macro_build (NULL, &icnt, NULL, l, "d,w,<", dreg, sreg,
- (0x20 - rot) & 0x1f);
- macro_build (NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
+ macro_build (NULL, r, "d,w,<", AT, sreg, rot);
+ macro_build (NULL, l, "d,w,<", dreg, sreg, (0x20 - rot) & 0x1f);
+ macro_build (NULL, "or", "d,v,t", dreg, dreg, AT);
}
break;
@@ -7410,18 +7189,17 @@ macro2 (struct mips_cl_insn *ip)
rot = imm_expr.X_add_number & 0x1f;
if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_opts.arch))
{
- macro_build (NULL, &icnt, NULL, "ror", "d,w,<", dreg, sreg, rot);
+ macro_build (NULL, "ror", "d,w,<", dreg, sreg, rot);
return;
}
if (rot == 0)
{
- macro_build (NULL, &icnt, NULL, "srl", "d,w,<", dreg, sreg, 0);
+ macro_build (NULL, "srl", "d,w,<", dreg, sreg, 0);
return;
}
- macro_build (NULL, &icnt, NULL, "srl", "d,w,<", AT, sreg, rot);
- macro_build (NULL, &icnt, NULL, "sll", "d,w,<", dreg, sreg,
- (0x20 - rot) & 0x1f);
- macro_build (NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
+ macro_build (NULL, "srl", "d,w,<", AT, sreg, rot);
+ macro_build (NULL, "sll", "d,w,<", dreg, sreg, (0x20 - rot) & 0x1f);
+ macro_build (NULL, "or", "d,v,t", dreg, dreg, AT);
}
break;
@@ -7434,50 +7212,43 @@ macro2 (struct mips_cl_insn *ip)
assert (mips_opts.isa == ISA_MIPS1);
/* Even on a big endian machine $fn comes before $fn+1. We have
to adjust when storing to memory. */
- macro_build (NULL, &icnt, &offset_expr, "swc1", "T,o(b)",
- target_big_endian ? treg + 1 : treg,
- BFD_RELOC_LO16, breg);
+ macro_build (&offset_expr, "swc1", "T,o(b)",
+ target_big_endian ? treg + 1 : treg, BFD_RELOC_LO16, breg);
offset_expr.X_add_number += 4;
- macro_build (NULL, &icnt, &offset_expr, "swc1", "T,o(b)",
- target_big_endian ? treg : treg + 1,
- BFD_RELOC_LO16, breg);
+ macro_build (&offset_expr, "swc1", "T,o(b)",
+ target_big_endian ? treg : treg + 1, BFD_RELOC_LO16, breg);
return;
case M_SEQ:
if (sreg == 0)
- macro_build (NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg, treg,
- BFD_RELOC_LO16);
+ macro_build (&expr1, "sltiu", "t,r,j", dreg, treg, BFD_RELOC_LO16);
else if (treg == 0)
- macro_build (NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg, sreg,
- BFD_RELOC_LO16);
+ macro_build (&expr1, "sltiu", "t,r,j", dreg, sreg, BFD_RELOC_LO16);
else
{
- macro_build (NULL, &icnt, NULL, "xor", "d,v,t", dreg, sreg, treg);
- macro_build (NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg, dreg,
- BFD_RELOC_LO16);
+ macro_build (NULL, "xor", "d,v,t", dreg, sreg, treg);
+ macro_build (&expr1, "sltiu", "t,r,j", dreg, dreg, BFD_RELOC_LO16);
}
return;
case M_SEQ_I:
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
{
- macro_build (NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg, sreg,
- BFD_RELOC_LO16);
+ macro_build (&expr1, "sltiu", "t,r,j", dreg, sreg, BFD_RELOC_LO16);
return;
}
if (sreg == 0)
{
as_warn (_("Instruction %s: result is always false"),
ip->insn_mo->name);
- move_register (&icnt, dreg, 0);
+ move_register (dreg, 0);
return;
}
if (imm_expr.X_op == O_constant
&& imm_expr.X_add_number >= 0
&& imm_expr.X_add_number < 0x10000)
{
- macro_build (NULL, &icnt, &imm_expr, "xori", "t,r,i", dreg, sreg,
- BFD_RELOC_LO16);
+ macro_build (&imm_expr, "xori", "t,r,i", dreg, sreg, BFD_RELOC_LO16);
used_at = 0;
}
else if (imm_expr.X_op == O_constant
@@ -7485,19 +7256,17 @@ macro2 (struct mips_cl_insn *ip)
&& imm_expr.X_add_number < 0)
{
imm_expr.X_add_number = -imm_expr.X_add_number;
- macro_build (NULL, &icnt, &imm_expr,
- HAVE_32BIT_GPRS ? "addiu" : "daddiu",
+ macro_build (&imm_expr, HAVE_32BIT_GPRS ? "addiu" : "daddiu",
"t,r,j", dreg, sreg, BFD_RELOC_LO16);
used_at = 0;
}
else
{
- load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build (NULL, &icnt, NULL, "xor", "d,v,t", dreg, sreg, AT);
+ load_register (AT, &imm_expr, HAVE_64BIT_GPRS);
+ macro_build (NULL, "xor", "d,v,t", dreg, sreg, AT);
used_at = 1;
}
- macro_build (NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg, dreg,
- BFD_RELOC_LO16);
+ macro_build (&expr1, "sltiu", "t,r,j", dreg, dreg, BFD_RELOC_LO16);
if (used_at)
break;
return;
@@ -7508,9 +7277,8 @@ macro2 (struct mips_cl_insn *ip)
case M_SGEU:
s = "sltu";
sge:
- macro_build (NULL, &icnt, NULL, s, "d,v,t", dreg, sreg, treg);
- macro_build (NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,
- BFD_RELOC_LO16);
+ macro_build (NULL, s, "d,v,t", dreg, sreg, treg);
+ macro_build (&expr1, "xori", "t,r,i", dreg, dreg, BFD_RELOC_LO16);
return;
case M_SGE_I: /* sreg >= I <==> not (sreg < I) */
@@ -7519,20 +7287,18 @@ macro2 (struct mips_cl_insn *ip)
&& imm_expr.X_add_number >= -0x8000
&& imm_expr.X_add_number < 0x8000)
{
- macro_build (NULL, &icnt, &imm_expr,
- mask == M_SGE_I ? "slti" : "sltiu",
- "t,r,j", dreg, sreg, BFD_RELOC_LO16);
+ macro_build (&imm_expr, mask == M_SGE_I ? "slti" : "sltiu", "t,r,j",
+ dreg, sreg, BFD_RELOC_LO16);
used_at = 0;
}
else
{
- load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build (NULL, &icnt, NULL, mask == M_SGE_I ? "slt" : "sltu",
- "d,v,t", dreg, sreg, AT);
+ load_register (AT, &imm_expr, HAVE_64BIT_GPRS);
+ macro_build (NULL, mask == M_SGE_I ? "slt" : "sltu", "d,v,t",
+ dreg, sreg, AT);
used_at = 1;
}
- macro_build (NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,
- BFD_RELOC_LO16);
+ macro_build (&expr1, "xori", "t,r,i", dreg, dreg, BFD_RELOC_LO16);
if (used_at)
break;
return;
@@ -7543,7 +7309,7 @@ macro2 (struct mips_cl_insn *ip)
case M_SGTU:
s = "sltu";
sgt:
- macro_build (NULL, &icnt, NULL, s, "d,v,t", dreg, treg, sreg);
+ macro_build (NULL, s, "d,v,t", dreg, treg, sreg);
return;
case M_SGT_I: /* sreg > I <==> I < sreg */
@@ -7552,8 +7318,8 @@ macro2 (struct mips_cl_insn *ip)
case M_SGTU_I:
s = "sltu";
sgti:
- load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build (NULL, &icnt, NULL, s, "d,v,t", dreg, AT, sreg);
+ load_register (AT, &imm_expr, HAVE_64BIT_GPRS);
+ macro_build (NULL, s, "d,v,t", dreg, AT, sreg);
break;
case M_SLE: /* sreg <= treg <==> treg >= sreg <==> not (treg < sreg) */
@@ -7562,9 +7328,8 @@ macro2 (struct mips_cl_insn *ip)
case M_SLEU:
s = "sltu";
sle:
- macro_build (NULL, &icnt, NULL, s, "d,v,t", dreg, treg, sreg);
- macro_build (NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,
- BFD_RELOC_LO16);
+ macro_build (NULL, s, "d,v,t", dreg, treg, sreg);
+ macro_build (&expr1, "xori", "t,r,i", dreg, dreg, BFD_RELOC_LO16);
return;
case M_SLE_I: /* sreg <= I <==> I >= sreg <==> not (I < sreg) */
@@ -7573,10 +7338,9 @@ macro2 (struct mips_cl_insn *ip)
case M_SLEU_I:
s = "sltu";
slei:
- load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build (NULL, &icnt, NULL, s, "d,v,t", dreg, AT, sreg);
- macro_build (NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,
- BFD_RELOC_LO16);
+ load_register (AT, &imm_expr, HAVE_64BIT_GPRS);
+ macro_build (NULL, s, "d,v,t", dreg, AT, sreg);
+ macro_build (&expr1, "xori", "t,r,i", dreg, dreg, BFD_RELOC_LO16);
break;
case M_SLT_I:
@@ -7584,12 +7348,11 @@ macro2 (struct mips_cl_insn *ip)
&& imm_expr.X_add_number >= -0x8000
&& imm_expr.X_add_number < 0x8000)
{
- macro_build (NULL, &icnt, &imm_expr, "slti", "t,r,j", dreg, sreg,
- BFD_RELOC_LO16);
+ macro_build (&imm_expr, "slti", "t,r,j", dreg, sreg, BFD_RELOC_LO16);
return;
}
- load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build (NULL, &icnt, NULL, "slt", "d,v,t", dreg, sreg, AT);
+ load_register (AT, &imm_expr, HAVE_64BIT_GPRS);
+ macro_build (NULL, "slt", "d,v,t", dreg, sreg, AT);
break;
case M_SLTU_I:
@@ -7597,47 +7360,45 @@ macro2 (struct mips_cl_insn *ip)
&& imm_expr.X_add_number >= -0x8000
&& imm_expr.X_add_number < 0x8000)
{
- macro_build (NULL, &icnt, &imm_expr, "sltiu", "t,r,j", dreg, sreg,
+ macro_build (&imm_expr, "sltiu", "t,r,j", dreg, sreg,
BFD_RELOC_LO16);
return;
}
- load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build (NULL, &icnt, NULL, "sltu", "d,v,t", dreg, sreg, AT);
+ load_register (AT, &imm_expr, HAVE_64BIT_GPRS);
+ macro_build (NULL, "sltu", "d,v,t", dreg, sreg, AT);
break;
case M_SNE:
if (sreg == 0)
- macro_build (NULL, &icnt, NULL, "sltu","d,v,t", dreg, 0, treg);
+ macro_build (NULL, "sltu", "d,v,t", dreg, 0, treg);
else if (treg == 0)
- macro_build (NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0, sreg);
+ macro_build (NULL, "sltu", "d,v,t", dreg, 0, sreg);
else
{
- macro_build (NULL, &icnt, NULL, "xor", "d,v,t", dreg, sreg, treg);
- macro_build (NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0, dreg);
+ macro_build (NULL, "xor", "d,v,t", dreg, sreg, treg);
+ macro_build (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 (NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0, sreg);
+ macro_build (NULL, "sltu", "d,v,t", dreg, 0, sreg);
return;
}
if (sreg == 0)
{
as_warn (_("Instruction %s: result is always true"),
ip->insn_mo->name);
- macro_build (NULL, &icnt, &expr1,
- HAVE_32BIT_GPRS ? "addiu" : "daddiu",
- "t,r,j", dreg, 0, BFD_RELOC_LO16);
+ macro_build (&expr1, HAVE_32BIT_GPRS ? "addiu" : "daddiu", "t,r,j",
+ dreg, 0, BFD_RELOC_LO16);
return;
}
if (imm_expr.X_op == O_constant
&& imm_expr.X_add_number >= 0
&& imm_expr.X_add_number < 0x10000)
{
- macro_build (NULL, &icnt, &imm_expr, "xori", "t,r,i", dreg, sreg,
- BFD_RELOC_LO16);
+ macro_build (&imm_expr, "xori", "t,r,i", dreg, sreg, BFD_RELOC_LO16);
used_at = 0;
}
else if (imm_expr.X_op == O_constant
@@ -7645,18 +7406,17 @@ macro2 (struct mips_cl_insn *ip)
&& imm_expr.X_add_number < 0)
{
imm_expr.X_add_number = -imm_expr.X_add_number;
- macro_build (NULL, &icnt, &imm_expr,
- HAVE_32BIT_GPRS ? "addiu" : "daddiu",
+ macro_build (&imm_expr, HAVE_32BIT_GPRS ? "addiu" : "daddiu",
"t,r,j", dreg, sreg, BFD_RELOC_LO16);
used_at = 0;
}
else
{
- load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build (NULL, &icnt, NULL, "xor", "d,v,t", dreg, sreg, AT);
+ load_register (AT, &imm_expr, HAVE_64BIT_GPRS);
+ macro_build (NULL, "xor", "d,v,t", dreg, sreg, AT);
used_at = 1;
}
- macro_build (NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0, dreg);
+ macro_build (NULL, "sltu", "d,v,t", dreg, 0, dreg);
if (used_at)
break;
return;
@@ -7669,13 +7429,12 @@ macro2 (struct mips_cl_insn *ip)
&& imm_expr.X_add_number <= 0x8000)
{
imm_expr.X_add_number = -imm_expr.X_add_number;
- macro_build (NULL, &icnt, &imm_expr, dbl ? "daddi" : "addi",
- "t,r,j", dreg, sreg, BFD_RELOC_LO16);
+ macro_build (&imm_expr, dbl ? "daddi" : "addi", "t,r,j",
+ dreg, sreg, BFD_RELOC_LO16);
return;
}
- load_register (&icnt, AT, &imm_expr, dbl);
- macro_build (NULL, &icnt, NULL, dbl ? "dsub" : "sub", "d,v,t",
- dreg, sreg, AT);
+ load_register (AT, &imm_expr, dbl);
+ macro_build (NULL, dbl ? "dsub" : "sub", "d,v,t", dreg, sreg, AT);
break;
case M_DSUBU_I:
@@ -7686,13 +7445,12 @@ macro2 (struct mips_cl_insn *ip)
&& imm_expr.X_add_number <= 0x8000)
{
imm_expr.X_add_number = -imm_expr.X_add_number;
- macro_build (NULL, &icnt, &imm_expr, dbl ? "daddiu" : "addiu",
- "t,r,j", dreg, sreg, BFD_RELOC_LO16);
+ macro_build (&imm_expr, dbl ? "daddiu" : "addiu", "t,r,j",
+ dreg, sreg, BFD_RELOC_LO16);
return;
}
- load_register (&icnt, AT, &imm_expr, dbl);
- macro_build (NULL, &icnt, NULL, dbl ? "dsubu" : "subu", "d,v,t",
- dreg, sreg, AT);
+ load_register (AT, &imm_expr, dbl);
+ macro_build (NULL, dbl ? "dsubu" : "subu", "d,v,t", dreg, sreg, AT);
break;
case M_TEQ_I:
@@ -7713,8 +7471,8 @@ macro2 (struct mips_cl_insn *ip)
case M_TNE_I:
s = "tne";
trap:
- load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build (NULL, &icnt, NULL, s, "s,t", sreg, AT);
+ load_register (AT, &imm_expr, HAVE_64BIT_GPRS);
+ macro_build (NULL, s, "s,t", sreg, AT);
break;
case M_TRUNCWS:
@@ -7730,22 +7488,19 @@ macro2 (struct mips_cl_insn *ip)
mips_emit_delays (TRUE);
++mips_opts.noreorder;
mips_any_noreorder = 1;
- macro_build (NULL, &icnt, NULL, "cfc1", "t,G", treg, RA);
- macro_build (NULL, &icnt, NULL, "cfc1", "t,G", treg, RA);
- macro_build (NULL, &icnt, NULL, "nop", "");
+ macro_build (NULL, "cfc1", "t,G", treg, RA);
+ macro_build (NULL, "cfc1", "t,G", treg, RA);
+ macro_build (NULL, "nop", "");
expr1.X_add_number = 3;
- macro_build (NULL, &icnt, &expr1, "ori", "t,r,i", AT, treg,
- BFD_RELOC_LO16);
+ macro_build (&expr1, "ori", "t,r,i", AT, treg, BFD_RELOC_LO16);
expr1.X_add_number = 2;
- macro_build (NULL, &icnt, &expr1, "xori", "t,r,i", AT, AT,
- BFD_RELOC_LO16);
- macro_build (NULL, &icnt, NULL, "ctc1", "t,G", AT, RA);
- macro_build (NULL, &icnt, NULL, "nop", "");
- macro_build (NULL, &icnt, NULL,
- mask == M_TRUNCWD ? "cvt.w.d" : "cvt.w.s",
- "D,S", dreg, sreg);
- macro_build (NULL, &icnt, NULL, "ctc1", "t,G", treg, RA);
- macro_build (NULL, &icnt, NULL, "nop", "");
+ macro_build (&expr1, "xori", "t,r,i", AT, AT, BFD_RELOC_LO16);
+ macro_build (NULL, "ctc1", "t,G", AT, RA);
+ macro_build (NULL, "nop", "");
+ macro_build (NULL, mask == M_TRUNCWD ? "cvt.w.d" : "cvt.w.s", "D,S",
+ dreg, sreg);
+ macro_build (NULL, "ctc1", "t,G", treg, RA);
+ macro_build (NULL, "nop", "");
--mips_opts.noreorder;
break;
@@ -7759,16 +7514,14 @@ macro2 (struct mips_cl_insn *ip)
as_bad (_("operand overflow"));
if (! target_big_endian)
++offset_expr.X_add_number;
- macro_build (NULL, &icnt, &offset_expr, s, "t,o(b)", AT,
- BFD_RELOC_LO16, breg);
+ macro_build (&offset_expr, s, "t,o(b)", AT, BFD_RELOC_LO16, breg);
if (! target_big_endian)
--offset_expr.X_add_number;
else
++offset_expr.X_add_number;
- macro_build (NULL, &icnt, &offset_expr, "lbu", "t,o(b)", treg,
- BFD_RELOC_LO16, breg);
- macro_build (NULL, &icnt, NULL, "sll", "d,w,<", AT, AT, 8);
- macro_build (NULL, &icnt, NULL, "or", "d,v,t", treg, treg, AT);
+ macro_build (&offset_expr, "lbu", "t,o(b)", treg, BFD_RELOC_LO16, breg);
+ macro_build (NULL, "sll", "d,w,<", AT, AT, 8);
+ macro_build (NULL, "or", "d,v,t", treg, treg, AT);
break;
case M_ULD:
@@ -7789,22 +7542,20 @@ macro2 (struct mips_cl_insn *ip)
tempreg = AT;
if (! target_big_endian)
offset_expr.X_add_number += off;
- macro_build (NULL, &icnt, &offset_expr, s, "t,o(b)", tempreg,
- BFD_RELOC_LO16, breg);
+ macro_build (&offset_expr, s, "t,o(b)", tempreg, BFD_RELOC_LO16, breg);
if (! target_big_endian)
offset_expr.X_add_number -= off;
else
offset_expr.X_add_number += off;
- macro_build (NULL, &icnt, &offset_expr, s2, "t,o(b)", tempreg,
- BFD_RELOC_LO16, breg);
+ macro_build (&offset_expr, s2, "t,o(b)", tempreg, BFD_RELOC_LO16, breg);
/* If necessary, move the result in tempreg the final destination. */
if (treg == tempreg)
return;
/* Protect second load's delay slot. */
if (!gpr_interlocks)
- macro_build (NULL, &icnt, NULL, "nop", "");
- move_register (&icnt, treg, tempreg);
+ macro_build (NULL, "nop", "");
+ move_register (treg, tempreg);
break;
case M_ULD_A:
@@ -7818,44 +7569,38 @@ macro2 (struct mips_cl_insn *ip)
off = 3;
ulwa:
used_at = 1;
- load_address (&icnt, AT, &offset_expr, &used_at);
+ load_address (AT, &offset_expr, &used_at);
if (breg != 0)
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
- AT, AT, breg);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, AT, breg);
if (! target_big_endian)
expr1.X_add_number = off;
else
expr1.X_add_number = 0;
- macro_build (NULL, &icnt, &expr1, s, "t,o(b)", treg,
- BFD_RELOC_LO16, AT);
+ macro_build (&expr1, s, "t,o(b)", treg, BFD_RELOC_LO16, AT);
if (! target_big_endian)
expr1.X_add_number = 0;
else
expr1.X_add_number = off;
- macro_build (NULL, &icnt, &expr1, s2, "t,o(b)", treg,
- BFD_RELOC_LO16, AT);
+ macro_build (&expr1, s2, "t,o(b)", treg, BFD_RELOC_LO16, AT);
break;
case M_ULH_A:
case M_ULHU_A:
used_at = 1;
- load_address (&icnt, AT, &offset_expr, &used_at);
+ load_address (AT, &offset_expr, &used_at);
if (breg != 0)
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
- AT, AT, breg);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, AT, breg);
if (target_big_endian)
expr1.X_add_number = 0;
- macro_build (NULL, &icnt, &expr1,
- mask == M_ULH_A ? "lb" : "lbu", "t,o(b)",
+ macro_build (&expr1, mask == M_ULH_A ? "lb" : "lbu", "t,o(b)",
treg, BFD_RELOC_LO16, AT);
if (target_big_endian)
expr1.X_add_number = 1;
else
expr1.X_add_number = 0;
- macro_build (NULL, &icnt, &expr1, "lbu", "t,o(b)",
- AT, BFD_RELOC_LO16, AT);
- macro_build (NULL, &icnt, NULL, "sll", "d,w,<", treg, treg, 8);
- macro_build (NULL, &icnt, NULL, "or", "d,v,t", treg, treg, AT);
+ macro_build (&expr1, "lbu", "t,o(b)", AT, BFD_RELOC_LO16, AT);
+ macro_build (NULL, "sll", "d,w,<", treg, treg, 8);
+ macro_build (NULL, "or", "d,v,t", treg, treg, AT);
break;
case M_USH:
@@ -7863,15 +7608,13 @@ macro2 (struct mips_cl_insn *ip)
as_bad (_("operand overflow"));
if (target_big_endian)
++offset_expr.X_add_number;
- macro_build (NULL, &icnt, &offset_expr, "sb", "t,o(b)", treg,
- BFD_RELOC_LO16, breg);
- macro_build (NULL, &icnt, NULL, "srl", "d,w,<", AT, treg, 8);
+ macro_build (&offset_expr, "sb", "t,o(b)", treg, BFD_RELOC_LO16, breg);
+ macro_build (NULL, "srl", "d,w,<", AT, treg, 8);
if (target_big_endian)
--offset_expr.X_add_number;
else
++offset_expr.X_add_number;
- macro_build (NULL, &icnt, &offset_expr, "sb", "t,o(b)", AT,
- BFD_RELOC_LO16, breg);
+ macro_build (&offset_expr, "sb", "t,o(b)", AT, BFD_RELOC_LO16, breg);
break;
case M_USD:
@@ -7888,14 +7631,12 @@ macro2 (struct mips_cl_insn *ip)
as_bad (_("operand overflow"));
if (! target_big_endian)
offset_expr.X_add_number += off;
- macro_build (NULL, &icnt, &offset_expr, s, "t,o(b)", treg,
- BFD_RELOC_LO16, breg);
+ macro_build (&offset_expr, s, "t,o(b)", treg, BFD_RELOC_LO16, breg);
if (! target_big_endian)
offset_expr.X_add_number -= off;
else
offset_expr.X_add_number += off;
- macro_build (NULL, &icnt, &offset_expr, s2, "t,o(b)", treg,
- BFD_RELOC_LO16, breg);
+ macro_build (&offset_expr, s2, "t,o(b)", treg, BFD_RELOC_LO16, breg);
return;
case M_USD_A:
@@ -7909,49 +7650,42 @@ macro2 (struct mips_cl_insn *ip)
off = 3;
uswa:
used_at = 1;
- load_address (&icnt, AT, &offset_expr, &used_at);
+ load_address (AT, &offset_expr, &used_at);
if (breg != 0)
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
- AT, AT, breg);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, AT, breg);
if (! target_big_endian)
expr1.X_add_number = off;
else
expr1.X_add_number = 0;
- macro_build (NULL, &icnt, &expr1, s, "t,o(b)", treg,
- BFD_RELOC_LO16, AT);
+ macro_build (&expr1, s, "t,o(b)", treg, BFD_RELOC_LO16, AT);
if (! target_big_endian)
expr1.X_add_number = 0;
else
expr1.X_add_number = off;
- macro_build (NULL, &icnt, &expr1, s2, "t,o(b)", treg,
- BFD_RELOC_LO16, AT);
+ macro_build (&expr1, s2, "t,o(b)", treg, BFD_RELOC_LO16, AT);
break;
case M_USH_A:
used_at = 1;
- load_address (&icnt, AT, &offset_expr, &used_at);
+ load_address (AT, &offset_expr, &used_at);
if (breg != 0)
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
- AT, AT, breg);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, AT, breg);
if (! target_big_endian)
expr1.X_add_number = 0;
- macro_build (NULL, &icnt, &expr1, "sb", "t,o(b)", treg,
- BFD_RELOC_LO16, AT);
- macro_build (NULL, &icnt, NULL, "srl", "d,w,<", treg, treg, 8);
+ macro_build (&expr1, "sb", "t,o(b)", treg, BFD_RELOC_LO16, AT);
+ macro_build (NULL, "srl", "d,w,<", treg, treg, 8);
if (! target_big_endian)
expr1.X_add_number = 1;
else
expr1.X_add_number = 0;
- macro_build (NULL, &icnt, &expr1, "sb", "t,o(b)", treg,
- BFD_RELOC_LO16, AT);
+ macro_build (&expr1, "sb", "t,o(b)", treg, BFD_RELOC_LO16, AT);
if (! target_big_endian)
expr1.X_add_number = 0;
else
expr1.X_add_number = 1;
- macro_build (NULL, &icnt, &expr1, "lbu", "t,o(b)", AT,
- BFD_RELOC_LO16, AT);
- macro_build (NULL, &icnt, NULL, "sll", "d,w,<", treg, treg, 8);
- macro_build (NULL, &icnt, NULL, "or", "d,v,t", treg, treg, AT);
+ macro_build (&expr1, "lbu", "t,o(b)", AT, BFD_RELOC_LO16, AT);
+ macro_build (NULL, "sll", "d,w,<", treg, treg, 8);
+ macro_build (NULL, "or", "d,v,t", treg, treg, AT);
break;
default:
@@ -7971,7 +7705,6 @@ mips16_macro (struct mips_cl_insn *ip)
{
int mask;
int xreg, yreg, zreg, tmp;
- int icnt;
expressionS expr1;
int dbl;
const char *s, *s2, *s3;
@@ -7982,8 +7715,6 @@ mips16_macro (struct mips_cl_insn *ip)
yreg = (ip->insn_opcode >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY;
zreg = (ip->insn_opcode >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
- icnt = 0;
-
expr1.X_op = O_constant;
expr1.X_op_symbol = NULL;
expr1.X_add_symbol = NULL;
@@ -8009,18 +7740,17 @@ mips16_macro (struct mips_cl_insn *ip)
mips_emit_delays (TRUE);
++mips_opts.noreorder;
mips_any_noreorder = 1;
- macro_build (NULL, &icnt, NULL, dbl ? "ddiv" : "div", "0,x,y",
- xreg, yreg);
+ macro_build (NULL, dbl ? "ddiv" : "div", "0,x,y", xreg, yreg);
expr1.X_add_number = 2;
- macro_build (NULL, &icnt, &expr1, "bnez", "x,p", yreg);
- macro_build (NULL, &icnt, NULL, "break", "6", 7);
+ macro_build (&expr1, "bnez", "x,p", yreg);
+ macro_build (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 (NULL, &icnt, NULL, s, "x", zreg);
+ macro_build (NULL, s, "x", zreg);
break;
case M_DIVU_3:
@@ -8042,20 +7772,19 @@ mips16_macro (struct mips_cl_insn *ip)
mips_emit_delays (TRUE);
++mips_opts.noreorder;
mips_any_noreorder = 1;
- macro_build (NULL, &icnt, NULL, s, "0,x,y", xreg, yreg);
+ macro_build (NULL, s, "0,x,y", xreg, yreg);
expr1.X_add_number = 2;
- macro_build (NULL, &icnt, &expr1, "bnez", "x,p", yreg);
- macro_build (NULL, &icnt, NULL, "break", "6", 7);
+ macro_build (&expr1, "bnez", "x,p", yreg);
+ macro_build (NULL, "break", "6", 7);
--mips_opts.noreorder;
- macro_build (NULL, &icnt, NULL, s2, "x", zreg);
+ macro_build (NULL, s2, "x", zreg);
break;
case M_DMUL:
dbl = 1;
case M_MUL:
- macro_build (NULL, &icnt, NULL, dbl ? "dmultu" : "multu", "x,y",
- xreg, yreg);
- macro_build (NULL, &icnt, NULL, "mflo", "x", zreg);
+ macro_build (NULL, dbl ? "dmultu" : "multu", "x,y", xreg, yreg);
+ macro_build (NULL, "mflo", "x", zreg);
return;
case M_DSUBU_I:
@@ -8066,22 +7795,21 @@ mips16_macro (struct mips_cl_insn *ip)
if (imm_expr.X_op != O_constant)
as_bad (_("Unsupported large constant"));
imm_expr.X_add_number = -imm_expr.X_add_number;
- macro_build (NULL, &icnt, &imm_expr, dbl ? "daddiu" : "addiu", "y,x,4",
- yreg, xreg);
+ macro_build (&imm_expr, dbl ? "daddiu" : "addiu", "y,x,4", yreg, xreg);
break;
case M_SUBU_I_2:
if (imm_expr.X_op != O_constant)
as_bad (_("Unsupported large constant"));
imm_expr.X_add_number = -imm_expr.X_add_number;
- macro_build (NULL, &icnt, &imm_expr, "addiu", "x,k", xreg);
+ macro_build (&imm_expr, "addiu", "x,k", xreg);
break;
case M_DSUBU_I_2:
if (imm_expr.X_op != O_constant)
as_bad (_("Unsupported large constant"));
imm_expr.X_add_number = -imm_expr.X_add_number;
- macro_build (NULL, &icnt, &imm_expr, "daddiu", "y,j", yreg);
+ macro_build (&imm_expr, "daddiu", "y,j", yreg);
break;
case M_BEQ:
@@ -8130,8 +7858,8 @@ mips16_macro (struct mips_cl_insn *ip)
yreg = tmp;
do_branch:
- macro_build (NULL, &icnt, NULL, s, "x,y", xreg, yreg);
- macro_build (NULL, &icnt, &offset_expr, s2, "p");
+ macro_build (NULL, s, "x,y", xreg, yreg);
+ macro_build (&offset_expr, s2, "p");
break;
case M_BEQ_I:
@@ -8190,18 +7918,18 @@ mips16_macro (struct mips_cl_insn *ip)
++imm_expr.X_add_number;
do_branch_i:
- macro_build (NULL, &icnt, &imm_expr, s, s3, xreg);
- macro_build (NULL, &icnt, &offset_expr, s2, "p");
+ macro_build (&imm_expr, s, s3, xreg);
+ macro_build (&offset_expr, s2, "p");
break;
case M_ABS:
expr1.X_add_number = 0;
- macro_build (NULL, &icnt, &expr1, "slti", "x,8", yreg);
+ macro_build (&expr1, "slti", "x,8", yreg);
if (xreg != yreg)
- move_register (&icnt, xreg, yreg);
+ move_register (xreg, yreg);
expr1.X_add_number = 2;
- macro_build (NULL, &icnt, &expr1, "bteqz", "p");
- macro_build (NULL, &icnt, NULL, "neg", "x,w", xreg, xreg);
+ macro_build (&expr1, "bteqz", "p");
+ macro_build (NULL, "neg", "x,w", xreg, xreg);
}
}
@@ -12318,7 +12046,6 @@ static void
s_cpload (int ignore ATTRIBUTE_UNUSED)
{
expressionS ex;
- int icnt = 0;
/* If we are not generating SVR4 PIC code, or if this is NewABI code,
.cpload is ignored. */
@@ -12340,12 +12067,13 @@ s_cpload (int ignore ATTRIBUTE_UNUSED)
/* In ELF, this symbol is implicitly an STT_OBJECT symbol. */
symbol_get_bfdsym (ex.X_add_symbol)->flags |= BSF_OBJECT;
- macro_build_lui (NULL, &icnt, &ex, mips_gp_register);
- macro_build (NULL, &icnt, &ex, "addiu", "t,r,j", mips_gp_register,
+ macro_start ();
+ macro_build_lui (&ex, mips_gp_register);
+ macro_build (&ex, "addiu", "t,r,j", mips_gp_register,
mips_gp_register, BFD_RELOC_LO16);
-
- macro_build (NULL, &icnt, NULL, "addu", "d,v,t", mips_gp_register,
+ macro_build (NULL, "addu", "d,v,t", mips_gp_register,
mips_gp_register, tc_get_register (0));
+ macro_end ();
demand_empty_rest_of_line ();
}
@@ -12371,7 +12099,6 @@ s_cpsetup (int ignore ATTRIBUTE_UNUSED)
expressionS ex_off;
expressionS ex_sym;
int reg1;
- int icnt = 0;
char *f;
/* If we are not generating SVR4 PIC code, .cpsetup is ignored.
@@ -12413,6 +12140,7 @@ s_cpsetup (int ignore ATTRIBUTE_UNUSED)
SKIP_WHITESPACE ();
expression (&ex_sym);
+ macro_start ();
if (mips_cpreturn_register == -1)
{
ex_off.X_op = O_constant;
@@ -12420,34 +12148,34 @@ s_cpsetup (int ignore ATTRIBUTE_UNUSED)
ex_off.X_op_symbol = NULL;
ex_off.X_add_number = mips_cpreturn_offset;
- macro_build (NULL, &icnt, &ex_off, "sd", "t,o(b)", mips_gp_register,
+ macro_build (&ex_off, "sd", "t,o(b)", mips_gp_register,
BFD_RELOC_LO16, SP);
}
else
- macro_build (NULL, &icnt, NULL, "daddu", "d,v,t", mips_cpreturn_register,
+ macro_build (NULL, "daddu", "d,v,t", mips_cpreturn_register,
mips_gp_register, 0);
/* Ensure there's room for the next two instructions, so that `f'
doesn't end up with an address in the wrong frag. */
frag_grow (8);
f = frag_more (0);
- macro_build (NULL, &icnt, &ex_sym, "lui", "t,u", mips_gp_register,
- BFD_RELOC_GPREL16);
+ macro_build (&ex_sym, "lui", "t,u", mips_gp_register, BFD_RELOC_GPREL16);
fix_new (frag_now, f - frag_now->fr_literal,
8, NULL, 0, 0, BFD_RELOC_MIPS_SUB);
fix_new (frag_now, f - frag_now->fr_literal,
4, NULL, 0, 0, BFD_RELOC_HI16_S);
f = frag_more (0);
- macro_build (NULL, &icnt, &ex_sym, "addiu", "t,r,j", mips_gp_register,
+ macro_build (&ex_sym, "addiu", "t,r,j", mips_gp_register,
mips_gp_register, BFD_RELOC_GPREL16);
fix_new (frag_now, f - frag_now->fr_literal,
8, NULL, 0, 0, BFD_RELOC_MIPS_SUB);
fix_new (frag_now, f - frag_now->fr_literal,
4, NULL, 0, 0, BFD_RELOC_LO16);
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t", mips_gp_register,
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", mips_gp_register,
mips_gp_register, reg1);
+ macro_end ();
demand_empty_rest_of_line ();
}
@@ -12475,7 +12203,6 @@ static void
s_cprestore (int ignore ATTRIBUTE_UNUSED)
{
expressionS ex;
- int icnt = 0;
/* If we are not generating SVR4 PIC code, or if this is NewABI code,
.cprestore is ignored. */
@@ -12493,8 +12220,10 @@ s_cprestore (int ignore ATTRIBUTE_UNUSED)
ex.X_op_symbol = NULL;
ex.X_add_number = mips_cprestore_offset;
- macro_build_ldst_constoffset (NULL, &icnt, &ex, ADDRESS_STORE_INSN,
- mips_gp_register, SP, HAVE_64BIT_ADDRESSES);
+ macro_start ();
+ macro_build_ldst_constoffset (&ex, ADDRESS_STORE_INSN, mips_gp_register,
+ SP, HAVE_64BIT_ADDRESSES);
+ macro_end ();
demand_empty_rest_of_line ();
}
@@ -12510,7 +12239,6 @@ static void
s_cpreturn (int ignore ATTRIBUTE_UNUSED)
{
expressionS ex;
- int icnt = 0;
/* If we are not generating SVR4 PIC code, .cpreturn is ignored.
We also need NewABI support. */
@@ -12520,6 +12248,7 @@ s_cpreturn (int ignore ATTRIBUTE_UNUSED)
return;
}
+ macro_start ();
if (mips_cpreturn_register == -1)
{
ex.X_op = O_constant;
@@ -12527,12 +12256,12 @@ s_cpreturn (int ignore ATTRIBUTE_UNUSED)
ex.X_op_symbol = NULL;
ex.X_add_number = mips_cpreturn_offset;
- macro_build (NULL, &icnt, &ex, "ld", "t,o(b)", mips_gp_register,
- BFD_RELOC_LO16, SP);
+ macro_build (&ex, "ld", "t,o(b)", mips_gp_register, BFD_RELOC_LO16, SP);
}
else
- macro_build (NULL, &icnt, NULL, "daddu", "d,v,t", mips_gp_register,
+ macro_build (NULL, "daddu", "d,v,t", mips_gp_register,
mips_cpreturn_register, 0);
+ macro_end ();
demand_empty_rest_of_line ();
}
@@ -12644,7 +12373,6 @@ s_gpdword (int ignore ATTRIBUTE_UNUSED)
static void
s_cpadd (int ignore ATTRIBUTE_UNUSED)
{
- int icnt = 0;
int reg;
/* This is ignored when not generating SVR4 PIC code. */
@@ -12655,9 +12383,10 @@ s_cpadd (int ignore ATTRIBUTE_UNUSED)
}
/* Add $gp to the register named as an argument. */
+ macro_start ();
reg = tc_get_register (0);
- macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
- reg, reg, mips_gp_register);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", reg, reg, mips_gp_register);
+ macro_end ();
demand_empty_rest_of_line ();
}
@@ -13264,22 +12993,11 @@ md_estimate_size_before_relax (fragS *fragp, asection *segtype)
if (change)
{
- /* Record the offset to the first reloc in the fr_opcode field.
- This lets md_convert_frag and tc_gen_reloc know that the code
- must be expanded. */
- fragp->fr_opcode = (fragp->fr_literal
- + fragp->fr_fix
- - RELAX_OLD (fragp->fr_subtype)
- + RELAX_RELOC1 (fragp->fr_subtype));
- /* FIXME: This really needs as_warn_where. */
- if (RELAX_WARN (fragp->fr_subtype))
- as_warn (_("AT used after \".set noat\" or macro used after "
- "\".set nomacro\""));
-
- return RELAX_NEW (fragp->fr_subtype) - RELAX_OLD (fragp->fr_subtype);
+ fragp->fr_subtype |= RELAX_USE_SECOND;
+ return -RELAX_FIRST (fragp->fr_subtype);
}
-
- return 0;
+ else
+ return -RELAX_SECOND (fragp->fr_subtype);
}
/* This is called to see whether a reloc against a defined symbol
@@ -13383,112 +13101,6 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
else
reloc->addend = fixp->fx_addnumber;
- /* If this is a variant frag, we may need to adjust the existing
- reloc and generate a new one. */
- if (fixp->fx_frag->fr_opcode != NULL
- && ((fixp->fx_r_type == BFD_RELOC_GPREL16
- && ! HAVE_NEWABI)
- || (fixp->fx_r_type == BFD_RELOC_MIPS_GOT_DISP
- && HAVE_NEWABI)
- || fixp->fx_r_type == BFD_RELOC_MIPS_GOT16
- || fixp->fx_r_type == BFD_RELOC_MIPS_CALL16
- || fixp->fx_r_type == BFD_RELOC_MIPS_GOT_HI16
- || fixp->fx_r_type == BFD_RELOC_MIPS_GOT_LO16
- || fixp->fx_r_type == BFD_RELOC_MIPS_CALL_HI16
- || fixp->fx_r_type == BFD_RELOC_MIPS_CALL_LO16)
- )
- {
- arelent *reloc2;
-
- assert (! RELAX_MIPS16_P (fixp->fx_frag->fr_subtype));
-
- /* If this is not the last reloc in this frag, then we have two
- GPREL relocs, or a GOT_HI16/GOT_LO16 pair, or a
- CALL_HI16/CALL_LO16, both of which are being replaced. Let
- the second one handle all of them. */
- if (fixp->fx_next != NULL
- && fixp->fx_frag == fixp->fx_next->fx_frag)
- {
- assert ((fixp->fx_r_type == BFD_RELOC_GPREL16
- && fixp->fx_next->fx_r_type == BFD_RELOC_GPREL16)
- || (fixp->fx_r_type == BFD_RELOC_MIPS_GOT_HI16
- && (fixp->fx_next->fx_r_type
- == BFD_RELOC_MIPS_GOT_LO16))
- || (fixp->fx_r_type == BFD_RELOC_MIPS_CALL_HI16
- && (fixp->fx_next->fx_r_type
- == BFD_RELOC_MIPS_CALL_LO16)));
- retval[0] = NULL;
- return retval;
- }
-
- fixp->fx_where = fixp->fx_frag->fr_opcode - fixp->fx_frag->fr_literal;
- reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
- reloc->addend += fixp->fx_frag->tc_frag_data.tc_fr_offset;
- reloc2 = retval[1] = (arelent *) xmalloc (sizeof (arelent));
- reloc2->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
- *reloc2->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
- reloc2->address = (reloc->address
- + (RELAX_RELOC2 (fixp->fx_frag->fr_subtype)
- - RELAX_RELOC1 (fixp->fx_frag->fr_subtype)));
- reloc2->addend = reloc->addend;
- reloc2->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
- assert (reloc2->howto != NULL);
-
- if (RELAX_RELOC3 (fixp->fx_frag->fr_subtype))
- {
- arelent *reloc3;
-
- reloc3 = retval[2] = (arelent *) xmalloc (sizeof (arelent));
- *reloc3 = *reloc2;
- reloc3->address += 4;
- }
-
- if (mips_pic == NO_PIC)
- {
- assert (fixp->fx_r_type == BFD_RELOC_GPREL16);
- fixp->fx_r_type = BFD_RELOC_HI16_S;
- }
- else if (mips_pic == SVR4_PIC)
- {
- switch (fixp->fx_r_type)
- {
- default:
- abort ();
- case BFD_RELOC_MIPS_GOT16:
- break;
- case BFD_RELOC_MIPS_GOT_LO16:
- case BFD_RELOC_MIPS_CALL_LO16:
- if (HAVE_NEWABI)
- {
- fixp->fx_r_type = BFD_RELOC_MIPS_GOT_PAGE;
- reloc2->howto = bfd_reloc_type_lookup
- (stdoutput, BFD_RELOC_MIPS_GOT_OFST);
- }
- else
- fixp->fx_r_type = BFD_RELOC_MIPS_GOT16;
- break;
- case BFD_RELOC_MIPS_CALL16:
- case BFD_RELOC_MIPS_GOT_OFST:
- case BFD_RELOC_MIPS_GOT_DISP:
- if (HAVE_NEWABI)
- {
- /* It may seem nonsensical to relax GOT_DISP to
- GOT_DISP, but we're actually turning a GOT_DISP
- without offset into a GOT_DISP with an offset,
- getting rid of the separate addition, which we can
- do when the symbol is found to be local. */
- fixp->fx_r_type = BFD_RELOC_MIPS_GOT_DISP;
- retval[1] = NULL;
- }
- else
- fixp->fx_r_type = BFD_RELOC_MIPS_GOT16;
- break;
- }
- }
- else
- abort ();
- }
-
/* Since the old MIPS ELF ABI uses Rel instead of Rela, encode the vtable
entry to be used in the relocation's section offset. */
if (! HAVE_NEWABI && fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
@@ -13596,9 +13208,6 @@ mips_relax_frag (asection *sec, fragS *fragp, long stretch)
void
md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
{
- int old, new;
- char *fixptr;
-
if (RELAX_BRANCH_P (fragp->fr_subtype))
{
bfd_byte *buf;
@@ -13898,17 +13507,57 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
}
else
{
- if (fragp->fr_opcode == NULL)
- return;
+ int first, second;
+ fixS *fixp;
- old = RELAX_OLD (fragp->fr_subtype);
- new = RELAX_NEW (fragp->fr_subtype);
- fixptr = fragp->fr_literal + fragp->fr_fix;
+ first = RELAX_FIRST (fragp->fr_subtype);
+ second = RELAX_SECOND (fragp->fr_subtype);
+ fixp = (fixS *) fragp->fr_opcode;
- if (new > 0)
- memmove (fixptr - old, fixptr, new);
+ /* Possibly emit a warning if we've chosen the longer option. */
+ if (((fragp->fr_subtype & RELAX_USE_SECOND) != 0)
+ == ((fragp->fr_subtype & RELAX_SECOND_LONGER) != 0))
+ {
+ const char *msg = macro_warning (fragp->fr_subtype);
+ if (msg != 0)
+ as_warn_where (fragp->fr_file, fragp->fr_line, msg);
+ }
- fragp->fr_fix += new - old;
+ /* Go through all the fixups for the first sequence. Disable them
+ (by marking them as done) if we're going to use the second
+ sequence instead. */
+ while (fixp
+ && fixp->fx_frag == fragp
+ && fixp->fx_where < fragp->fr_fix - second)
+ {
+ if (fragp->fr_subtype & RELAX_USE_SECOND)
+ fixp->fx_done = 1;
+ fixp = fixp->fx_next;
+ }
+
+ /* Go through the fixups for the second sequence. Disable them if
+ we're going to use the first sequence, otherwise adjust their
+ addresses to account for the relaxation. */
+ while (fixp && fixp->fx_frag == fragp)
+ {
+ if (fragp->fr_subtype & RELAX_USE_SECOND)
+ fixp->fx_where -= first;
+ else
+ fixp->fx_done = 1;
+ fixp = fixp->fx_next;
+ }
+
+ /* Now modify the frag contents. */
+ if (fragp->fr_subtype & RELAX_USE_SECOND)
+ {
+ char *start;
+
+ start = fragp->fr_literal + fragp->fr_fix - first - second;
+ memmove (start, start + first, second);
+ fragp->fr_fix -= first;
+ }
+ else
+ fragp->fr_fix -= second;
}
}
diff --git a/gas/config/tc-mips.h b/gas/config/tc-mips.h
index fc96ef3..110dc09 100644
--- a/gas/config/tc-mips.h
+++ b/gas/config/tc-mips.h
@@ -186,9 +186,4 @@ extern enum dwarf2_format mips_dwarf2_format (void);
#define DWARF2_ADDR_SIZE(bfd) \
(DWARF2_FORMAT () == dwarf2_format_32bit ? 4 : 8)
-typedef struct {
- offsetT tc_fr_offset;
-} tc_frag_data_type;
-#define TC_FRAG_TYPE tc_frag_data_type
-
#endif /* TC_MIPS */