#include "subsegs.h"
#include "safe-ctype.h"
-#ifdef USE_STDARG
#include <stdarg.h>
-#endif
-#ifdef USE_VARARGS
-#include <varargs.h>
-#endif
#include "opcode/mips.h"
#include "itbl-ops.h"
#ifdef OBJ_MAYBE_ELF
/* Clean up namespace so we can include obj-elf.h too. */
-static int mips_output_flavor PARAMS ((void));
-static int mips_output_flavor () { return OUTPUT_FLAVOR; }
+static int mips_output_flavor (void);
+static int mips_output_flavor (void) { return OUTPUT_FLAVOR; }
#undef OBJ_PROCESS_STAB
#undef OUTPUT_FLAVOR
#undef S_GET_ALIGN
int mips_flag_mdebug = -1;
+/* Control generation of .pdr sections. Off by default on IRIX: the native
+ linker doesn't know about and discards them, but relocations against them
+ remain, leading to rld crashes. */
+#ifdef TE_IRIX
+int mips_flag_pdr = FALSE;
+#else
+int mips_flag_pdr = TRUE;
+#endif
+
#include "ecoff.h"
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
/* MIPS ABI we are using for this output file. */
static enum mips_abi_level mips_abi = NO_ABI;
+/* Whether or not we have code that can call pic code. */
+int mips_abicalls = FALSE;
+
/* This is the set of options which may be modified by the .set
pseudo-op. We use a struct so that .set push and .set pop are more
reliable. */
is passed but can changed if the assembler code uses .set mipsN. */
int gp32;
int fp32;
+ /* MIPS architecture (CPU) type. Changed by .set arch=FOO, the -march
+ command line option, and the default CPU. */
+ int arch;
};
/* True if -mgp32 was passed. */
static struct mips_set_options mips_opts =
{
- ISA_UNKNOWN, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0
+ ISA_UNKNOWN, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, CPU_UNKNOWN
};
/* These variables are filled in with the masks of registers used.
static int file_ase_mdmx;
/* The argument of the -march= flag. The architecture we are assembling. */
-static int mips_arch = CPU_UNKNOWN;
+static int file_mips_arch = CPU_UNKNOWN;
static const char *mips_arch_string;
-static const struct mips_cpu_info *mips_arch_info;
/* The argument of the -mtune= flag. The architecture for which we
are optimizing. */
static int mips_tune = CPU_UNKNOWN;
static const char *mips_tune_string;
-static const struct mips_cpu_info *mips_tune_info;
/* True when generating 32-bit code for a 64-bit processor. */
static int mips_32bitmode = 0;
&& mips_pic != EMBEDDED_PIC))
#define HAVE_64BIT_ADDRESSES (! HAVE_32BIT_ADDRESSES)
+#define HAVE_64BIT_ADDRESS_CONSTANTS (HAVE_64BIT_ADDRESSES \
+ || HAVE_64BIT_GPRS)
+
+/* Addresses are loaded in different ways, depending on the address size
+ in use. The n32 ABI Documentation also mandates the use of additions
+ with overflow checking, but existing implementations don't follow it. */
+#define ADDRESS_ADD_INSN \
+ (HAVE_32BIT_ADDRESSES ? "addu" : "daddu")
+
+#define ADDRESS_ADDI_INSN \
+ (HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu")
+
+#define ADDRESS_LOAD_INSN \
+ (HAVE_32BIT_ADDRESSES ? "lw" : "ld")
+
+#define ADDRESS_STORE_INSN \
+ (HAVE_32BIT_ADDRESSES ? "sw" : "sd")
/* Return true if the given CPU supports the MIPS16 ASE. */
#define CPU_HAS_MIPS16(cpu) \
reads from the HI and LO registers, and thus does not
require nops to be inserted. */
-#define hilo_interlocks (mips_arch == CPU_R4010 \
- || mips_arch == CPU_VR5500 \
- || mips_arch == CPU_SB1 \
+#define hilo_interlocks (mips_opts.arch == CPU_R4010 \
+ || mips_opts.arch == CPU_VR5500 \
+ || mips_opts.arch == CPU_RM7000 \
+ || mips_opts.arch == CPU_SB1 \
)
/* Whether the processor uses hardware interlocks to protect reads
from the GPRs, and thus does not require nops to be inserted. */
#define gpr_interlocks \
(mips_opts.isa != ISA_MIPS1 \
- || mips_arch == CPU_VR5400 \
- || mips_arch == CPU_VR5500 \
- || mips_arch == CPU_R3900)
+ || mips_opts.arch == CPU_VR5400 \
+ || mips_opts.arch == CPU_VR5500 \
+ || mips_opts.arch == CPU_R3900)
/* As with other "interlocks" this is used by hardware that has FP
(co-processor) interlocks. */
/* Itbl support may require additional care here. */
-#define cop_interlocks (mips_arch == CPU_R4300 \
- || mips_arch == CPU_VR5400 \
- || mips_arch == CPU_VR5500 \
- || mips_arch == CPU_SB1 \
+#define cop_interlocks (mips_opts.arch == CPU_R4300 \
+ || mips_opts.arch == CPU_VR5400 \
+ || mips_opts.arch == CPU_VR5500 \
+ || mips_opts.arch == CPU_SB1 \
)
/* Is this a mfhi or mflo instruction? */
I don't know if a fix is needed for the SVR4_PIC mode. I've only
fixed it for the non-PIC mode. KR 95/04/07 */
-static int nopic_need_relax PARAMS ((symbolS *, int));
+static int nopic_need_relax (symbolS *, int);
/* handle of the OPCODE hash table */
static struct hash_control *op_hash = NULL;
static struct mips_hi_fixup *mips_hi_fixup_list;
+/* The frag containing the last explicit relocation operator.
+ Null if explicit relocations have not been used. */
+
+static fragS *prev_reloc_op_frag;
+
/* Map normal MIPS register numbers to mips16 register numbers. */
#define X ILLEGAL_REG
\f
/* Prototypes for static functions. */
-#ifdef __STDC__
-#define internalError() \
+#define internalError() \
as_fatal (_("internal Error, line %d, %s"), __LINE__, __FILE__)
-#else
-#define internalError() as_fatal (_("MIPS internal Error"));
-#endif
enum mips_regclass { MIPS_GR_REG, MIPS_FP_REG, MIPS16_REG };
-static int insn_uses_reg
- PARAMS ((struct mips_cl_insn *ip, unsigned int reg,
- enum mips_regclass class));
-static int reg_needs_delay
- PARAMS ((unsigned int));
-static void mips16_mark_labels
- PARAMS ((void));
static void append_insn
- PARAMS ((char *place, struct mips_cl_insn * ip, expressionS * p,
- bfd_reloc_code_real_type *r));
-static void mips_no_prev_insn
- PARAMS ((int));
-static void mips_emit_delays
- PARAMS ((bfd_boolean));
-#ifdef USE_STDARG
-static void macro_build
- PARAMS ((char *place, int *counter, expressionS * ep, const char *name,
- const char *fmt, ...));
-#else
-static void macro_build ();
-#endif
+ (char *place, 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
- PARAMS ((char *, int *, expressionS *, const char *, const char *, va_list));
-static void macro_build_jalr
- PARAMS ((int, expressionS *));
-static void macro_build_lui
- PARAMS ((char *place, int *counter, expressionS * ep, int regnum));
-static void macro_build_ldst_constoffset
- PARAMS ((char *place, int *counter, expressionS * ep, const char *op,
- int valreg, int breg));
-static void set_at
- PARAMS ((int *counter, int reg, int unsignedp));
-static void check_absolute_expr
- PARAMS ((struct mips_cl_insn * ip, expressionS *));
-static void load_register
- PARAMS ((int *, int, expressionS *, int));
-static void load_address
- PARAMS ((int *, int, expressionS *, int *));
-static void move_register
- PARAMS ((int *, int, int));
-static void macro
- PARAMS ((struct mips_cl_insn * ip));
-static void mips16_macro
- PARAMS ((struct mips_cl_insn * ip));
+ (char *, int *, expressionS *, const char *, const char *, va_list);
+static void load_register (int *, int, expressionS *, int);
+static void macro (struct mips_cl_insn * ip);
+static void mips16_macro (struct mips_cl_insn * ip);
#ifdef LOSING_COMPILER
-static void macro2
- PARAMS ((struct mips_cl_insn * ip));
+static void macro2 (struct mips_cl_insn * ip);
#endif
-static void mips_ip
- PARAMS ((char *str, struct mips_cl_insn * ip));
-static void mips16_ip
- PARAMS ((char *str, struct mips_cl_insn * ip));
+static void mips_ip (char *str, struct mips_cl_insn * ip);
+static void mips16_ip (char *str, struct mips_cl_insn * ip);
static void mips16_immed
- PARAMS ((char *, unsigned int, int, offsetT, bfd_boolean, bfd_boolean,
- bfd_boolean, unsigned long *, bfd_boolean *, unsigned short *));
-static bfd_boolean parse_relocation
- PARAMS ((char **, bfd_reloc_code_real_type *));
+ (char *, unsigned int, int, offsetT, bfd_boolean, bfd_boolean, bfd_boolean,
+ unsigned long *, bfd_boolean *, unsigned short *);
static size_t my_getSmallExpression
- PARAMS ((expressionS *, bfd_reloc_code_real_type *, char *));
-static void my_getExpression
- PARAMS ((expressionS *, char *));
-#ifdef OBJ_ELF
-static int support_64bit_objects
- PARAMS((void));
-#endif
-static void mips_set_option_string
- PARAMS ((const char **, const char *));
-static symbolS *get_symbol
- PARAMS ((void));
-static void mips_align
- PARAMS ((int to, int fill, symbolS *label));
-static void s_align
- PARAMS ((int));
-static void s_change_sec
- PARAMS ((int));
-static void s_change_section
- PARAMS ((int));
-static void s_cons
- PARAMS ((int));
-static void s_float_cons
- PARAMS ((int));
-static void s_mips_globl
- PARAMS ((int));
-static void s_option
- PARAMS ((int));
-static void s_mipsset
- PARAMS ((int));
-static void s_abicalls
- PARAMS ((int));
-static void s_cpload
- PARAMS ((int));
-static void s_cpsetup
- PARAMS ((int));
-static void s_cplocal
- PARAMS ((int));
-static void s_cprestore
- PARAMS ((int));
-static void s_cpreturn
- PARAMS ((int));
-static void s_gpvalue
- PARAMS ((int));
-static void s_gpword
- PARAMS ((int));
-static void s_gpdword
- PARAMS ((int));
-static void s_cpadd
- PARAMS ((int));
-static void s_insn
- PARAMS ((int));
-static void md_obj_begin
- PARAMS ((void));
-static void md_obj_end
- PARAMS ((void));
-static long get_number
- PARAMS ((void));
-static void s_mips_ent
- PARAMS ((int));
-static void s_mips_end
- PARAMS ((int));
-static void s_mips_frame
- PARAMS ((int));
-static void s_mips_mask
- PARAMS ((int));
-static void s_mips_stab
- PARAMS ((int));
-static void s_mips_weakext
- PARAMS ((int));
-static void s_mips_file
- PARAMS ((int));
-static void s_mips_loc
- PARAMS ((int));
-static int mips16_extended_frag
- PARAMS ((fragS *, asection *, long));
+ (expressionS *, bfd_reloc_code_real_type *, char *);
+static void my_getExpression (expressionS *, char *);
+static void s_align (int);
+static void s_change_sec (int);
+static void s_change_section (int);
+static void s_cons (int);
+static void s_float_cons (int);
+static void s_mips_globl (int);
+static void s_option (int);
+static void s_mipsset (int);
+static void s_abicalls (int);
+static void s_cpload (int);
+static void s_cpsetup (int);
+static void s_cplocal (int);
+static void s_cprestore (int);
+static void s_cpreturn (int);
+static void s_gpvalue (int);
+static void s_gpword (int);
+static void s_gpdword (int);
+static void s_cpadd (int);
+static void s_insn (int);
+static void md_obj_begin (void);
+static void md_obj_end (void);
+static void s_mips_ent (int);
+static void s_mips_end (int);
+static void s_mips_frame (int);
+static void s_mips_mask (int reg_type);
+static void s_mips_stab (int);
+static void s_mips_weakext (int);
+static void s_mips_file (int);
+static void s_mips_loc (int);
+static bfd_boolean pic_need_relax (symbolS *, asection *);
static int relaxed_branch_length (fragS *, asection *, int);
-static int validate_mips_insn
- PARAMS ((const struct mips_opcode *));
-static void show
- PARAMS ((FILE *, const char *, int *, int *));
-#ifdef OBJ_ELF
-static int mips_need_elf_addend_fixup
- PARAMS ((fixS *));
-#endif
+static int validate_mips_insn (const struct mips_opcode *);
/* Table and functions used to map between CPU/ISA names, and
ISA levels, and CPU numbers. */
int cpu; /* CPU number (default CPU if ISA). */
};
-static void mips_set_architecture
- PARAMS ((const struct mips_cpu_info *));
-static void mips_set_tune
- PARAMS ((const struct mips_cpu_info *));
-static bfd_boolean mips_strict_matching_cpu_name_p
- PARAMS ((const char *, const char *));
-static bfd_boolean mips_matching_cpu_name_p
- PARAMS ((const char *, const char *));
-static const struct mips_cpu_info *mips_parse_cpu
- PARAMS ((const char *, const char *));
-static const struct mips_cpu_info *mips_cpu_info_from_isa
- PARAMS ((int));
+static const struct mips_cpu_info *mips_parse_cpu (const char *, const char *);
+static const struct mips_cpu_info *mips_cpu_info_from_isa (int);
+static const struct mips_cpu_info *mips_cpu_info_from_arch (int);
\f
/* Pseudo-op table.
{ NULL, NULL, 0 },
};
-extern void pop_insert PARAMS ((const pseudo_typeS *));
+extern void pop_insert (const pseudo_typeS *);
void
-mips_pop_insert ()
+mips_pop_insert (void)
{
pop_insert (mips_pseudo_table);
if (! ECOFF_DEBUGGING)
static struct insn_label_list *insn_labels;
static struct insn_label_list *free_insn_labels;
-static void mips_clear_insn_labels PARAMS ((void));
+static void mips_clear_insn_labels (void);
static inline void
-mips_clear_insn_labels ()
+mips_clear_insn_labels (void)
{
register struct insn_label_list **pl;
/* The default target format to use. */
const char *
-mips_target_format ()
+mips_target_format (void)
{
switch (OUTPUT_FLAVOR)
{
set up all the tables, etc. that the MD part of the assembler will need. */
void
-md_begin ()
+md_begin (void)
{
register const char *retval = NULL;
int i = 0;
int broken = 0;
- if (! bfd_set_arch_mach (stdoutput, bfd_arch_mips, mips_arch))
+ if (! bfd_set_arch_mach (stdoutput, bfd_arch_mips, file_mips_arch))
as_warn (_("Could not set architecture and machine"));
op_hash = hash_new ();
{
const char *name = mips_opcodes[i].name;
- retval = hash_insert (op_hash, name, (PTR) &mips_opcodes[i]);
+ retval = hash_insert (op_hash, name, (void *) &mips_opcodes[i]);
if (retval != NULL)
{
fprintf (stderr, _("internal error: can't hash `%s': %s\n"),
{
const char *name = mips16_opcodes[i].name;
- retval = hash_insert (mips16_op_hash, name, (PTR) &mips16_opcodes[i]);
+ retval = hash_insert (mips16_op_hash, name, (void *) &mips16_opcodes[i]);
if (retval != NULL)
as_fatal (_("internal: can't hash `%s': %s"),
mips16_opcodes[i].name, retval);
(void) bfd_set_section_alignment (stdoutput, sec, 2);
}
#ifdef OBJ_ELF
- else if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
+ else if (OUTPUT_FLAVOR == bfd_target_elf_flavour && mips_flag_pdr)
{
pdr_seg = subseg_new (".pdr", (subsegT) 0);
(void) bfd_set_section_flags (stdoutput, pdr_seg,
}
void
-md_mips_end ()
+md_mips_end (void)
{
if (! ECOFF_DEBUGGING)
md_obj_end ();
}
void
-md_assemble (str)
- char *str;
+md_assemble (char *str)
{
struct mips_cl_insn insn;
bfd_reloc_code_real_type unused_reloc[3]
}
}
+/* Return true if the given relocation might need a matching %lo().
+ Note that R_MIPS_GOT16 relocations only need a matching %lo() when
+ applied to local symbols. */
+
+static inline bfd_boolean
+reloc_needs_lo_p (bfd_reloc_code_real_type reloc)
+{
+ return (reloc == BFD_RELOC_HI16_S
+ || reloc == BFD_RELOC_MIPS_GOT16);
+}
+
+/* Return true if the given fixup is followed by a matching R_MIPS_LO16
+ relocation. */
+
+static inline bfd_boolean
+fixup_has_matching_lo_p (fixS *fixp)
+{
+ return (fixp->fx_next != NULL
+ && fixp->fx_next->fx_r_type == BFD_RELOC_LO16
+ && fixp->fx_addsy == fixp->fx_next->fx_addsy
+ && fixp->fx_offset == fixp->fx_next->fx_offset);
+}
+
/* See whether instruction IP reads register REG. CLASS is the type
of register. */
static int
-insn_uses_reg (ip, reg, class)
- struct mips_cl_insn *ip;
- unsigned int reg;
- enum mips_regclass class;
+insn_uses_reg (struct mips_cl_insn *ip, unsigned int reg,
+ enum mips_regclass class)
{
if (class == MIPS16_REG)
{
delay. */
static int
-reg_needs_delay (reg)
- unsigned int reg;
+reg_needs_delay (unsigned int reg)
{
unsigned long prev_pinfo;
to make them odd again. */
static void
-mips16_mark_labels ()
+mips16_mark_labels (void)
{
if (mips_opts.mips16)
{
used with RELOC_TYPE. */
static void
-append_insn (place, ip, address_expr, reloc_type)
- char *place;
- struct mips_cl_insn *ip;
- expressionS *address_expr;
- bfd_reloc_code_real_type *reloc_type;
+append_insn (char *place, struct mips_cl_insn *ip, expressionS *address_expr,
+ bfd_reloc_code_real_type *reloc_type)
{
register unsigned long prev_pinfo, pinfo;
char *f;
fixS *fixp[3];
int nops = 0;
- bfd_boolean unmatched_reloc_p;
+ bfd_boolean force_new_frag = FALSE;
/* Mark instruction labels in mips16 mode. */
mips16_mark_labels ();
prev_pinfo = prev_insn.insn_mo->pinfo;
pinfo = ip->insn_mo->pinfo;
- unmatched_reloc_p = FALSE;
if (place == NULL && (! mips_opts.noreorder || prev_nop_frag != NULL))
{
break;
case BFD_RELOC_MIPS_HIGHEST:
- tmp = (address_expr->X_add_number + 0x800080008000) >> 16;
+ tmp = (address_expr->X_add_number
+ + ((valueT) 0x8000 << 32) + 0x80008000) >> 16;
tmp >>= 16;
ip->insn_opcode |= (tmp >> 16) & 0xffff;
break;
/* Don't generate a reloc if we are writing into a variant frag. */
if (place == NULL)
{
- fixp[0] = fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
+ 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;
+
+ 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 == BFD_RELOC_16_PCREL_S2,
+ 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 &&
- (*reloc_type == BFD_RELOC_16
- || *reloc_type == BFD_RELOC_32
- || *reloc_type == BFD_RELOC_MIPS_JMP
- || *reloc_type == BFD_RELOC_HI16_S
- || *reloc_type == BFD_RELOC_LO16
- || *reloc_type == BFD_RELOC_GPREL16
- || *reloc_type == BFD_RELOC_MIPS_LITERAL
- || *reloc_type == BFD_RELOC_GPREL32
- || *reloc_type == BFD_RELOC_64
- || *reloc_type == BFD_RELOC_CTOR
- || *reloc_type == BFD_RELOC_MIPS_SUB
- || *reloc_type == BFD_RELOC_MIPS_HIGHEST
- || *reloc_type == BFD_RELOC_MIPS_HIGHER
- || *reloc_type == BFD_RELOC_MIPS_SCN_DISP
- || *reloc_type == BFD_RELOC_MIPS_REL16
- || *reloc_type == BFD_RELOC_MIPS_RELGOT))
+ 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_type[0] == BFD_RELOC_HI16_S)
+ if (reloc_needs_lo_p (*reloc_type))
{
struct mips_hi_fixup *hi_fixup;
- hi_fixup = ((struct mips_hi_fixup *)
- xmalloc (sizeof (struct mips_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;
- hi_fixup->next = mips_hi_fixup_list;
- mips_hi_fixup_list = hi_fixup;
- unmatched_reloc_p = TRUE;
}
- if (reloc_type[1] != BFD_RELOC_UNUSED)
- {
- /* FIXME: This symbol can be one of
- RSS_UNDEF, RSS_GP, RSS_GP0, RSS_LOC. */
- address_expr->X_op = O_absent;
- address_expr->X_add_symbol = 0;
- address_expr->X_add_number = 0;
-
- fixp[1] = fix_new_exp (frag_now, f - frag_now->fr_literal,
- 4, address_expr, FALSE,
- reloc_type[1]);
-
- /* These relocations can have an addend that won't fit in
- 4 octets for 64bit assembly. */
- if (HAVE_64BIT_GPRS &&
- (*reloc_type == BFD_RELOC_16
- || *reloc_type == BFD_RELOC_32
- || *reloc_type == BFD_RELOC_MIPS_JMP
- || *reloc_type == BFD_RELOC_HI16_S
- || *reloc_type == BFD_RELOC_LO16
- || *reloc_type == BFD_RELOC_GPREL16
- || *reloc_type == BFD_RELOC_MIPS_LITERAL
- || *reloc_type == BFD_RELOC_GPREL32
- || *reloc_type == BFD_RELOC_64
- || *reloc_type == BFD_RELOC_CTOR
- || *reloc_type == BFD_RELOC_MIPS_SUB
- || *reloc_type == BFD_RELOC_MIPS_HIGHEST
- || *reloc_type == BFD_RELOC_MIPS_HIGHER
- || *reloc_type == BFD_RELOC_MIPS_SCN_DISP
- || *reloc_type == BFD_RELOC_MIPS_REL16
- || *reloc_type == BFD_RELOC_MIPS_RELGOT))
- fixp[1]->fx_no_overflow = 1;
-
- if (reloc_type[2] != BFD_RELOC_UNUSED)
- {
- address_expr->X_op = O_absent;
- address_expr->X_add_symbol = 0;
- address_expr->X_add_number = 0;
-
- fixp[2] = fix_new_exp (frag_now,
- f - frag_now->fr_literal, 4,
- address_expr, FALSE,
- reloc_type[2]);
-
- /* These relocations can have an addend that won't fit in
- 4 octets for 64bit assembly. */
- if (HAVE_64BIT_GPRS &&
- (*reloc_type == BFD_RELOC_16
- || *reloc_type == BFD_RELOC_32
- || *reloc_type == BFD_RELOC_MIPS_JMP
- || *reloc_type == BFD_RELOC_HI16_S
- || *reloc_type == BFD_RELOC_LO16
- || *reloc_type == BFD_RELOC_GPREL16
- || *reloc_type == BFD_RELOC_MIPS_LITERAL
- || *reloc_type == BFD_RELOC_GPREL32
- || *reloc_type == BFD_RELOC_64
- || *reloc_type == BFD_RELOC_CTOR
- || *reloc_type == BFD_RELOC_MIPS_SUB
- || *reloc_type == BFD_RELOC_MIPS_HIGHEST
- || *reloc_type == BFD_RELOC_MIPS_HIGHER
- || *reloc_type == BFD_RELOC_MIPS_SCN_DISP
- || *reloc_type == BFD_RELOC_MIPS_REL16
- || *reloc_type == BFD_RELOC_MIPS_RELGOT))
- fixp[2]->fx_no_overflow = 1;
- }
- }
+ /* 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]);
+ }
}
}
}
prev_insn_fixp[2]->fx_frag = frag_now;
prev_insn_fixp[2]->fx_where = f - frag_now->fr_literal;
}
+ if (prev_insn_fixp[0] && HAVE_NEWABI
+ && prev_insn_frag != frag_now
+ && (prev_insn_fixp[0]->fx_r_type
+ == BFD_RELOC_MIPS_GOT_DISP
+ || (prev_insn_fixp[0]->fx_r_type
+ == BFD_RELOC_MIPS_CALL16)))
+ {
+ /* To avoid confusion in tc_gen_reloc, we must
+ ensure that this does not become a variant
+ frag. */
+ force_new_frag = TRUE;
+ }
if (fixp[0])
{
fixp[0]->fx_frag = prev_insn_frag;
/* We just output an insn, so the next one doesn't have a label. */
mips_clear_insn_labels ();
- /* We must ensure that a fixup associated with an unmatched %hi
- reloc does not become a variant frag. Otherwise, the
- rearrangement of %hi relocs in frob_file may confuse
- tc_gen_reloc. */
- if (unmatched_reloc_p)
+ /* 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);
know whether nops are needed before a noreorder section. */
static void
-mips_no_prev_insn (preserve)
- int preserve;
+mips_no_prev_insn (int preserve)
{
if (! preserve)
{
instructions are to follow. */
static void
-mips_emit_delays (insns)
- bfd_boolean insns;
+mips_emit_delays (bfd_boolean insns)
{
if (! mips_opts.noreorder)
{
expression, the name of the instruction to build, an operand format
string, and corresponding arguments. */
-#ifdef USE_STDARG
-static void
-macro_build (char *place,
- int *counter,
- expressionS * ep,
- const char *name,
- const char *fmt,
- ...)
-#else
static void
-macro_build (place, counter, ep, name, fmt, va_alist)
- char *place;
- int *counter;
- expressionS *ep;
- const char *name;
- const char *fmt;
- va_dcl
-#endif
+macro_build (char *place, int *counter, expressionS *ep, const char *name,
+ const char *fmt, ...)
{
struct mips_cl_insn insn;
bfd_reloc_code_real_type r[3];
va_list args;
-#ifdef USE_STDARG
va_start (args, fmt);
-#else
- va_start (args);
-#endif
/*
* If the macro is about to expand into a second instruction,
&& OPCODE_IS_MEMBER (insn.insn_mo,
(mips_opts.isa
| (file_ase_mips16 ? INSN_MIPS16 : 0)),
- mips_arch)
- && (mips_arch != CPU_R4650 || (insn.insn_mo->pinfo & FP_D) == 0))
+ mips_opts.arch)
+ && (mips_opts.arch != CPU_R4650 || (insn.insn_mo->pinfo & FP_D) == 0))
break;
++insn.insn_mo;
}
static void
-mips16_macro_build (place, counter, ep, name, fmt, args)
- char *place;
- int *counter ATTRIBUTE_UNUSED;
- expressionS *ep;
- const char *name;
- const char *fmt;
- va_list args;
+mips16_macro_build (char *place, int *counter ATTRIBUTE_UNUSED,
+ expressionS *ep, const char *name, const char *fmt,
+ va_list args)
{
struct mips_cl_insn insn;
bfd_reloc_code_real_type r[3]
* function. This occurs in NewABI PIC code.
*/
static void
-macro_build_jalr (icnt, ep)
- int icnt;
- expressionS *ep;
+macro_build_jalr (int icnt, expressionS *ep)
{
- char *f;
+ char *f = NULL;
if (HAVE_NEWABI)
{
frag_grow (4);
f = frag_more (0);
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "jalr", "d,s",
- RA, PIC_CALL_REG);
+ macro_build (NULL, &icnt, NULL, "jalr", "d,s", RA, PIC_CALL_REG);
if (HAVE_NEWABI)
fix_new_exp (frag_now, f - frag_now->fr_literal,
- 0, ep, FALSE, BFD_RELOC_MIPS_JALR);
+ 4, ep, FALSE, BFD_RELOC_MIPS_JALR);
}
/*
* Generate a "lui" instruction.
*/
static void
-macro_build_lui (place, counter, ep, regnum)
- char *place;
- int *counter;
- expressionS *ep;
- int regnum;
+macro_build_lui (char *place, int *counter, expressionS *ep, int regnum)
{
expressionS high_expr;
struct mips_cl_insn insn;
offset off of a base register (breg) into/from a target register (treg),
using AT if necessary. */
static void
-macro_build_ldst_constoffset (place, counter, ep, op, treg, breg)
- char *place;
- int *counter;
- expressionS *ep;
- const char *op;
- int treg, breg;
+macro_build_ldst_constoffset (char *place, int *counter, expressionS *ep,
+ const char *op, int treg, int breg)
{
assert (ep->X_op == O_constant);
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,
- (int) BFD_RELOC_LO16, breg);
+ macro_build (place, counter, ep, op, "t,o(b)", treg, BFD_RELOC_LO16,
+ breg);
}
else
{
macro_build_lui (place, counter, ep, AT);
if (place != NULL)
place += 4;
- macro_build (place, counter, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", AT, AT, breg);
+ 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,
- (int) BFD_RELOC_LO16, AT);
+ macro_build (place, counter, ep, op, "t,o(b)", treg, BFD_RELOC_LO16,
+ AT);
if (mips_opts.noat)
as_warn (_("Macro used $at after \".set noat\""));
* if reg is less than the immediate expression.
*/
static void
-set_at (counter, reg, unsignedp)
- int *counter;
- int reg;
- int unsignedp;
+set_at (int *counter, 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 ((char *) NULL, counter, &imm_expr,
- unsignedp ? "sltiu" : "slti",
- "t,r,j", AT, reg, (int) BFD_RELOC_LO16);
+ macro_build (NULL, counter, &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 ((char *) NULL, counter, (expressionS *) NULL,
- unsignedp ? "sltu" : "slt",
+ macro_build (NULL, counter, NULL, unsignedp ? "sltu" : "slt",
"d,v,t", AT, reg, AT);
}
}
/* Warn if an expression is not a constant. */
static void
-check_absolute_expr (ip, ex)
- struct mips_cl_insn *ip;
- expressionS *ex;
+check_absolute_expr (struct mips_cl_insn *ip, expressionS *ex)
{
if (ex->X_op == O_big)
as_bad (_("unsupported large constant"));
* an absolute expression value into a register.
*/
static void
-load_register (counter, reg, ep, dbl)
- int *counter;
- int reg;
- expressionS *ep;
- int dbl;
+load_register (int *counter, int reg, expressionS *ep, int dbl)
{
int freg;
expressionS hi32, lo32;
/* 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 ((char *) NULL, counter, ep, "addiu", "t,r,j", reg, 0,
- (int) BFD_RELOC_LO16);
+ macro_build (NULL, counter, 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 ((char *) NULL, counter, ep, "ori", "t,r,i", reg, 0,
- (int) BFD_RELOC_LO16);
+ macro_build (NULL, counter, ep, "ori", "t,r,i", reg, 0,
+ BFD_RELOC_LO16);
return;
}
else if ((IS_SEXT_32BIT_NUM (ep->X_add_number)
== ~ (offsetT) 0xffffffff)))
{
/* 32 bit values require an lui. */
- macro_build ((char *) NULL, counter, ep, "lui", "t,u", reg,
- (int) BFD_RELOC_HI16);
+ macro_build (NULL, counter, ep, "lui", "t,u", reg, BFD_RELOC_HI16);
if ((ep->X_add_number & 0xffff) != 0)
- macro_build ((char *) NULL, counter, ep, "ori", "t,r,i", reg, reg,
- (int) BFD_RELOC_LO16);
+ macro_build (NULL, counter, ep, "ori", "t,r,i", reg, reg,
+ BFD_RELOC_LO16);
return;
}
}
{
as_bad (_("Number (0x%lx) larger than 32 bits"),
(unsigned long) ep->X_add_number);
- macro_build ((char *) NULL, counter, ep, "addiu", "t,r,j", reg, 0,
- (int) BFD_RELOC_LO16);
+ macro_build (NULL, counter, ep, "addiu", "t,r,j", reg, 0,
+ BFD_RELOC_LO16);
return;
}
{
if ((lo32.X_add_number & 0xffff8000) == 0xffff8000)
{
- macro_build ((char *) NULL, counter, &lo32, "addiu", "t,r,j",
- reg, 0, (int) BFD_RELOC_LO16);
+ macro_build (NULL, counter, &lo32, "addiu", "t,r,j", reg, 0,
+ BFD_RELOC_LO16);
return;
}
if (lo32.X_add_number & 0x80000000)
{
- macro_build ((char *) NULL, counter, &lo32, "lui", "t,u", reg,
- (int) BFD_RELOC_HI16);
+ macro_build (NULL, counter, &lo32, "lui", "t,u", reg,
+ BFD_RELOC_HI16);
if (lo32.X_add_number & 0xffff)
- macro_build ((char *) NULL, counter, &lo32, "ori", "t,r,i",
- reg, reg, (int) BFD_RELOC_LO16);
+ macro_build (NULL, counter, &lo32, "ori", "t,r,i", reg, reg,
+ BFD_RELOC_LO16);
return;
}
}
| (lo32.X_add_number >> shift));
else
tmp.X_add_number = hi32.X_add_number >> (shift - 32);
- macro_build ((char *) NULL, counter, &tmp,
- "ori", "t,r,i", reg, 0,
- (int) BFD_RELOC_LO16);
- macro_build ((char *) NULL, counter, (expressionS *) NULL,
+ 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);
ones. */
tmp.X_op = O_constant;
tmp.X_add_number = (offsetT) -1;
- macro_build ((char *) NULL, counter, &tmp, "addiu", "t,r,j",
- reg, 0, (int) BFD_RELOC_LO16);
+ macro_build (NULL, counter, &tmp, "addiu", "t,r,j", reg, 0,
+ BFD_RELOC_LO16);
if (bit != 0)
{
bit += shift;
- macro_build ((char *) NULL, counter, (expressionS *) NULL,
+ macro_build (NULL, counter, NULL,
(bit >= 32) ? "dsll32" : "dsll",
"d,w,<", reg, reg,
(bit >= 32) ? bit - 32 : bit);
}
- macro_build ((char *) NULL, counter, (expressionS *) NULL,
+ macro_build (NULL, counter, NULL,
(shift >= 32) ? "dsrl32" : "dsrl",
"d,w,<", reg, reg,
(shift >= 32) ? shift - 32 : shift);
{
if (freg != 0)
{
- macro_build ((char *) NULL, counter, (expressionS *) NULL,
- "dsll32", "d,w,<", reg, freg, 0);
+ macro_build (NULL, counter, NULL, "dsll32", "d,w,<", reg, freg, 0);
freg = reg;
}
}
if ((freg == 0) && (lo32.X_add_number == (offsetT) 0xffffffff))
{
- macro_build ((char *) NULL, counter, &lo32, "lui", "t,u", reg,
- (int) BFD_RELOC_HI16);
- macro_build ((char *) NULL, counter, (expressionS *) NULL,
- "dsrl32", "d,w,<", reg, reg, 0);
+ macro_build (NULL, counter, &lo32, "lui", "t,u", reg,
+ BFD_RELOC_HI16);
+ macro_build (NULL, counter, NULL, "dsrl32", "d,w,<", reg, reg, 0);
return;
}
if (freg != 0)
{
- macro_build ((char *) NULL, counter, (expressionS *) NULL, "dsll",
- "d,w,<", reg, freg, 16);
+ macro_build (NULL, counter, NULL, "dsll", "d,w,<", reg, freg, 16);
freg = reg;
}
mid16 = lo32;
mid16.X_add_number >>= 16;
- macro_build ((char *) NULL, counter, &mid16, "ori", "t,r,i", reg,
- freg, (int) BFD_RELOC_LO16);
- macro_build ((char *) NULL, counter, (expressionS *) NULL, "dsll",
- "d,w,<", reg, reg, 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);
freg = reg;
}
if ((lo32.X_add_number & 0xffff) != 0)
- macro_build ((char *) NULL, counter, &lo32, "ori", "t,r,i", reg, freg,
- (int) BFD_RELOC_LO16);
+ macro_build (NULL, counter, &lo32, "ori", "t,r,i", reg, freg,
+ BFD_RELOC_LO16);
}
/* Load an address into a register. */
static void
-load_address (counter, reg, ep, used_at)
- int *counter;
- int reg;
- expressionS *ep;
- int *used_at;
+load_address (int *counter, int reg, expressionS *ep, int *used_at)
{
char *p = NULL;
if (*used_at == 0 && ! mips_opts.noat)
{
macro_build (p, counter, ep, "lui", "t,u",
- reg, (int) BFD_RELOC_MIPS_HIGHEST);
+ reg, BFD_RELOC_MIPS_HIGHEST);
macro_build (p, counter, ep, "lui", "t,u",
- AT, (int) BFD_RELOC_HI16_S);
+ AT, BFD_RELOC_HI16_S);
macro_build (p, counter, ep, "daddiu", "t,r,j",
- reg, reg, (int) BFD_RELOC_MIPS_HIGHER);
+ reg, reg, BFD_RELOC_MIPS_HIGHER);
macro_build (p, counter, ep, "daddiu", "t,r,j",
- AT, AT, (int) BFD_RELOC_LO16);
- macro_build (p, counter, (expressionS *) NULL, "dsll32",
- "d,w,<", reg, reg, 0);
- macro_build (p, counter, (expressionS *) NULL, "daddu",
- "d,v,t", reg, reg, AT);
+ 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);
*used_at = 1;
}
else
{
macro_build (p, counter, ep, "lui", "t,u",
- reg, (int) BFD_RELOC_MIPS_HIGHEST);
+ reg, BFD_RELOC_MIPS_HIGHEST);
macro_build (p, counter, ep, "daddiu", "t,r,j",
- reg, reg, (int) BFD_RELOC_MIPS_HIGHER);
- macro_build (p, counter, (expressionS *) NULL, "dsll",
- "d,w,<", reg, reg, 16);
+ 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, (int) BFD_RELOC_HI16_S);
- macro_build (p, counter, (expressionS *) NULL, "dsll",
- "d,w,<", reg, reg, 16);
+ 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, (int) BFD_RELOC_LO16);
+ reg, reg, BFD_RELOC_LO16);
}
}
else
&& ! nopic_need_relax (ep->X_add_symbol, 1))
{
frag_grow (20);
- macro_build ((char *) NULL, counter, ep,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu", "t,r,j",
- reg, mips_gp_register, (int) BFD_RELOC_GPREL16);
+ macro_build (NULL, counter, 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),
macro_build_lui (p, counter, ep, reg);
if (p != NULL)
p += 4;
- macro_build (p, counter, ep,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
+ macro_build (p, counter, ep, ADDRESS_ADDI_INSN, "t,r,j", reg, reg,
+ BFD_RELOC_LO16);
}
}
else if (mips_pic == SVR4_PIC && ! mips_big_got)
lw $reg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
nop
addiu $reg,$reg,<sym> (BFD_RELOC_LO16)
+ If there is a constant, it must be added in after.
+
If we have NewABI, we want
- lw $reg,<sym>($gp) (BFD_RELOC_MIPS_GOT_DISP)
- If there is a constant, it must be added in after. */
- ex.X_add_number = ep->X_add_number;
- ep->X_add_number = 0;
- frag_grow (20);
+ lw $reg,<sym+cst>($gp) (BFD_RELOC_MIPS_GOT_DISP)
+ unless we're referencing a global symbol with a non-zero
+ offset, in which case cst must be added separately. */
if (HAVE_NEWABI)
{
- macro_build ((char *) NULL, counter, ep,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)", reg,
- (int) BFD_RELOC_MIPS_GOT_DISP, mips_gp_register);
+ frag_grow (12);
+
+ if (ep->X_add_number)
+ {
+ frag_now->tc_frag_data.tc_fr_offset =
+ 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);
+ 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);
+ 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;
+ }
+
+ macro_build (p, counter, 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);
+ }
}
else
{
- macro_build ((char *) NULL, counter, ep,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)",
- reg, (int) BFD_RELOC_MIPS_GOT16, mips_gp_register);
- macro_build ((char *) NULL, counter, (expressionS *) NULL, "nop", "");
+ 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, (offsetT) 0, (char *) NULL);
- macro_build (p, counter, ep,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
- }
+ ep->X_add_symbol, 0, NULL);
+ macro_build (p, counter, ep, ADDRESS_ADDI_INSN, "t,r,j", reg, reg,
+ BFD_RELOC_LO16);
- if (ex.X_add_number != 0)
- {
- if (ex.X_add_number < -0x8000 || ex.X_add_number >= 0x8000)
- as_bad (_("PIC code offset overflow (max 16 signed bits)"));
- ex.X_op = O_constant;
- macro_build ((char *) NULL, counter, &ex,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
+ if (ex.X_add_number != 0)
+ {
+ if (ex.X_add_number < -0x8000 || ex.X_add_number >= 0x8000)
+ as_bad (_("PIC code offset overflow (max 16 signed bits)"));
+ ex.X_op = O_constant;
+ macro_build (NULL, counter, &ex, ADDRESS_ADDI_INSN, "t,r,j",
+ reg, reg, BFD_RELOC_LO16);
+ }
}
}
else if (mips_pic == SVR4_PIC)
lui $reg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
addu $reg,$reg,$gp
lw $reg,<sym>($reg) (BFD_RELOC_MIPS_GOT_LO16)
- Otherwise, for a reference to a local symbol, we want
+
+ Otherwise, for a reference to a local symbol in old ABI, we want
lw $reg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
nop
addiu $reg,$reg,<sym> (BFD_RELOC_LO16)
- If we have NewABI, we want
+ If there is a constant, it must be added in after.
+
+ In the NewABI, for local symbols, with or without offsets, we want:
lw $reg,<sym>($gp) (BFD_RELOC_MIPS_GOT_PAGE)
addiu $reg,$reg,<sym> (BFD_RELOC_MIPS_GOT_OFST)
- If there is a constant, it must be added in after. */
- ex.X_add_number = ep->X_add_number;
- ep->X_add_number = 0;
+ */
if (HAVE_NEWABI)
{
- macro_build ((char *) NULL, counter, ep,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)", reg,
- (int) BFD_RELOC_MIPS_GOT_PAGE, mips_gp_register);
- macro_build (p, counter, ep,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu", "t,r,j",
- reg, reg, (int) BFD_RELOC_MIPS_GOT_OFST);
+ frag_grow (24);
+
+ frag_now->tc_frag_data.tc_fr_offset =
+ 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);
+ 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);
+ }
+
+ 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,
+ 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);
}
else
{
+ ex.X_add_number = ep->X_add_number;
+ ep->X_add_number = 0;
if (reg_needs_delay (mips_gp_register))
off = 4;
else
off = 0;
frag_grow (32);
- macro_build ((char *) NULL, counter, ep, "lui", "t,u", reg,
- (int) BFD_RELOC_MIPS_GOT_HI16);
- macro_build ((char *) NULL, counter, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu", "d,v,t", reg,
+ 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 ((char *) NULL, counter, ep,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
- "t,o(b)", reg, (int) BFD_RELOC_MIPS_GOT_LO16, reg);
+ 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),
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, (expressionS *) NULL, "nop", "");
+ macro_build (p, counter, NULL, "nop", "");
p += 4;
}
- macro_build (p, counter, ep,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)", reg,
- (int) BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ macro_build (p, counter, ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
+ BFD_RELOC_MIPS_GOT16, mips_gp_register);
p += 4;
- macro_build (p, counter, (expressionS *) NULL, "nop", "");
+ macro_build (p, counter, NULL, "nop", "");
p += 4;
- macro_build (p, counter, ep,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
- }
+ macro_build (p, counter, ep, ADDRESS_ADDI_INSN, "t,r,j", reg, reg,
+ BFD_RELOC_LO16);
- if (ex.X_add_number != 0)
- {
- if (ex.X_add_number < -0x8000 || ex.X_add_number >= 0x8000)
- as_bad (_("PIC code offset overflow (max 16 signed bits)"));
- ex.X_op = O_constant;
- macro_build ((char *) NULL, counter, &ex,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
+ if (ex.X_add_number != 0)
+ {
+ if (ex.X_add_number < -0x8000 || ex.X_add_number >= 0x8000)
+ as_bad (_("PIC code offset overflow (max 16 signed bits)"));
+ ex.X_op = O_constant;
+ macro_build (NULL, counter, &ex, ADDRESS_ADDI_INSN, "t,r,j",
+ reg, reg, BFD_RELOC_LO16);
+ }
}
}
else if (mips_pic == EMBEDDED_PIC)
/* We always do
addiu $reg,$gp,<sym> (BFD_RELOC_GPREL16)
*/
- macro_build ((char *) NULL, counter, ep,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", reg, mips_gp_register, (int) BFD_RELOC_GPREL16);
+ macro_build (NULL, counter, ep, ADDRESS_ADDI_INSN, "t,r,j", reg,
+ mips_gp_register, BFD_RELOC_GPREL16);
}
else
abort ();
/* Move the contents of register SOURCE into register DEST. */
static void
-move_register (counter, dest, source)
- int *counter;
- int dest;
- int source;
+move_register (int *counter, int dest, int source)
{
- macro_build ((char *) NULL, counter, (expressionS *) NULL,
- HAVE_32BIT_GPRS ? "addu" : "daddu",
+ macro_build (NULL, counter, NULL, HAVE_32BIT_GPRS ? "addu" : "daddu",
"d,v,t", dest, source, 0);
}
* we're missing.
*/
static void
-macro (ip)
- struct mips_cl_insn *ip;
+macro (struct mips_cl_insn *ip)
{
register int treg, sreg, dreg, breg;
int tempreg;
expr1.X_add_symbol = NULL;
expr1.X_add_number = 1;
+ /* Umatched 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:
mips_any_noreorder = 1;
expr1.X_add_number = 8;
- macro_build ((char *) NULL, &icnt, &expr1, "bgez", "s,p", sreg);
+ macro_build (NULL, &icnt, &expr1, "bgez", "s,p", sreg);
if (dreg == sreg)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "",
- 0);
+ macro_build (NULL, &icnt, NULL, "nop", "", 0);
else
move_register (&icnt, dreg, sreg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- dbl ? "dsub" : "sub", "d,v,t", dreg, 0, sreg);
+ macro_build (NULL, &icnt, NULL, dbl ? "dsub" : "sub", "d,v,t", dreg, 0,
+ sreg);
--mips_opts.noreorder;
return;
&& imm_expr.X_add_number >= -0x8000
&& imm_expr.X_add_number < 0x8000)
{
- macro_build ((char *) NULL, &icnt, &imm_expr, s, "t,r,j", treg, sreg,
- (int) BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, &imm_expr, s, "t,r,j", treg, sreg,
+ BFD_RELOC_LO16);
return;
}
load_register (&icnt, AT, &imm_expr, dbl);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s2, "d,v,t",
- treg, sreg, AT);
+ macro_build (NULL, &icnt, NULL, s2, "d,v,t", treg, sreg, AT);
break;
case M_AND_I:
&& imm_expr.X_add_number < 0x10000)
{
if (mask != M_NOR_I)
- macro_build ((char *) NULL, &icnt, &imm_expr, s, "t,r,i", treg,
- sreg, (int) BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, &imm_expr, s, "t,r,i", treg, sreg,
+ BFD_RELOC_LO16);
else
{
- macro_build ((char *) NULL, &icnt, &imm_expr, "ori", "t,r,i",
- treg, sreg, (int) BFD_RELOC_LO16);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nor",
- "d,v,t", treg, treg, 0);
+ 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);
}
return;
}
load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s2, "d,v,t",
- treg, sreg, AT);
+ macro_build (NULL, &icnt, NULL, s2, "d,v,t", treg, sreg, AT);
break;
case M_BEQ_I:
beq_i:
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
{
- macro_build ((char *) NULL, &icnt, &offset_expr, s, "s,t,p", sreg,
- 0);
+ macro_build (NULL, &icnt, &offset_expr, s, "s,t,p", sreg, 0);
return;
}
load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build ((char *) NULL, &icnt, &offset_expr, s, "s,t,p", sreg, AT);
+ macro_build (NULL, &icnt, &offset_expr, s, "s,t,p", sreg, AT);
break;
case M_BGEL:
case M_BGE:
if (treg == 0)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bgezl" : "bgez", "s,p", sreg);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "bgezl" : "bgez",
+ "s,p", sreg);
return;
}
if (sreg == 0)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "blezl" : "blez", "s,p", treg);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "blezl" : "blez",
+ "s,p", treg);
return;
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "slt", "d,v,t",
- AT, sreg, treg);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "beql" : "beq", "s,t,p", AT, 0);
+ 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);
break;
case M_BGTL_I:
if (warn_nops)
as_warn (_("Branch %s is always false (nop)"),
ip->insn_mo->name);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop",
- "", 0);
+ macro_build (NULL, &icnt, NULL, "nop", "", 0);
}
else
{
if (warn_nops)
as_warn (_("Branch likely %s is always false"),
ip->insn_mo->name);
- macro_build ((char *) NULL, &icnt, &offset_expr, "bnel",
- "s,t,p", 0, 0);
+ macro_build (NULL, &icnt, &offset_expr, "bnel", "s,t,p", 0, 0);
}
return;
}
likely = 1;
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bgezl" : "bgez", "s,p", sreg);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "bgezl" : "bgez",
+ "s,p", sreg);
return;
}
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bgtzl" : "bgtz", "s,p", sreg);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "bgtzl" : "bgtz",
+ "s,p", sreg);
return;
}
maxnum = 0x7fffffff;
do_true:
/* result is always true */
as_warn (_("Branch %s is always true"), ip->insn_mo->name);
- macro_build ((char *) NULL, &icnt, &offset_expr, "b", "p");
+ macro_build (NULL, &icnt, &offset_expr, "b", "p");
return;
}
set_at (&icnt, sreg, 0);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "beql" : "beq", "s,t,p", AT, 0);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "beql" : "beq",
+ "s,t,p", AT, 0);
break;
case M_BGEUL:
goto do_true;
if (sreg == 0)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "beql" : "beq", "s,t,p", 0, treg);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "beql" : "beq",
+ "s,t,p", 0, treg);
return;
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
- "d,v,t", AT, sreg, treg);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "beql" : "beq", "s,t,p", AT, 0);
+ 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);
break;
case M_BGTUL_I:
goto do_true;
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bnel" : "bne", "s,t,p", sreg, 0);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "bnel" : "bne",
+ "s,t,p", sreg, 0);
return;
}
set_at (&icnt, sreg, 1);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "beql" : "beq", "s,t,p", AT, 0);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "beql" : "beq",
+ "s,t,p", AT, 0);
break;
case M_BGTL:
case M_BGT:
if (treg == 0)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bgtzl" : "bgtz", "s,p", sreg);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "bgtzl" : "bgtz",
+ "s,p", sreg);
return;
}
if (sreg == 0)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bltzl" : "bltz", "s,p", treg);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "bltzl" : "bltz",
+ "s,p", treg);
return;
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "slt", "d,v,t",
- AT, treg, sreg);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bnel" : "bne", "s,t,p", AT, 0);
+ 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);
break;
case M_BGTUL:
case M_BGTU:
if (treg == 0)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bnel" : "bne", "s,t,p", sreg, 0);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "bnel" : "bne",
+ "s,t,p", sreg, 0);
return;
}
if (sreg == 0)
goto do_false;
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
- "d,v,t", AT, treg, sreg);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bnel" : "bne", "s,t,p", AT, 0);
+ 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);
break;
case M_BLEL:
case M_BLE:
if (treg == 0)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "blezl" : "blez", "s,p", sreg);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "blezl" : "blez",
+ "s,p", sreg);
return;
}
if (sreg == 0)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bgezl" : "bgez", "s,p", treg);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "bgezl" : "bgez",
+ "s,p", treg);
return;
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "slt", "d,v,t",
- AT, treg, sreg);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "beql" : "beq", "s,t,p", AT, 0);
+ 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);
break;
case M_BLEL_I:
likely = 1;
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bltzl" : "bltz", "s,p", sreg);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "bltzl" : "bltz",
+ "s,p", sreg);
return;
}
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "blezl" : "blez", "s,p", sreg);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "blezl" : "blez",
+ "s,p", sreg);
return;
}
set_at (&icnt, sreg, 0);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bnel" : "bne", "s,t,p", AT, 0);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "bnel" : "bne",
+ "s,t,p", AT, 0);
break;
case M_BLEUL:
case M_BLEU:
if (treg == 0)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "beql" : "beq", "s,t,p", sreg, 0);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "beql" : "beq",
+ "s,t,p", sreg, 0);
return;
}
if (sreg == 0)
goto do_true;
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
- "d,v,t", AT, treg, sreg);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "beql" : "beq", "s,t,p", AT, 0);
+ 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);
break;
case M_BLEUL_I:
goto do_false;
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "beql" : "beq",
+ macro_build (NULL, &icnt, &offset_expr, likely ? "beql" : "beq",
"s,t,p", sreg, 0);
return;
}
set_at (&icnt, sreg, 1);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bnel" : "bne", "s,t,p", AT, 0);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "bnel" : "bne",
+ "s,t,p", AT, 0);
break;
case M_BLTL:
case M_BLT:
if (treg == 0)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bltzl" : "bltz", "s,p", sreg);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "bltzl" : "bltz",
+ "s,p", sreg);
return;
}
if (sreg == 0)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bgtzl" : "bgtz", "s,p", treg);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "bgtzl" : "bgtz",
+ "s,p", treg);
return;
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "slt", "d,v,t",
- AT, sreg, treg);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bnel" : "bne", "s,t,p", AT, 0);
+ 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);
break;
case M_BLTUL:
goto do_false;
if (sreg == 0)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bnel" : "bne", "s,t,p", 0, treg);
+ macro_build (NULL, &icnt, &offset_expr, likely ? "bnel" : "bne",
+ "s,t,p", 0, treg);
return;
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
- "d,v,t", AT, sreg,
- treg);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- likely ? "bnel" : "bne", "s,t,p", AT, 0);
+ 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);
break;
case M_DDIV_3:
{
as_warn (_("Divide by zero."));
if (mips_trap)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq",
- "s,t,q", 0, 0, 7);
+ macro_build (NULL, &icnt, NULL, "teq", "s,t,q", 0, 0, 7);
else
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
- "c", 7);
+ macro_build (NULL, &icnt, NULL, "break", "c", 7);
return;
}
mips_any_noreorder = 1;
if (mips_trap)
{
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq",
- "s,t,q", treg, 0, 7);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- dbl ? "ddiv" : "div", "z,s,t", sreg, treg);
+ 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);
}
else
{
expr1.X_add_number = 8;
- macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", treg, 0);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- dbl ? "ddiv" : "div", "z,s,t", sreg, treg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
- "c", 7);
+ 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);
}
expr1.X_add_number = -1;
- macro_build ((char *) NULL, &icnt, &expr1,
- dbl ? "daddiu" : "addiu",
- "t,r,j", AT, 0, (int) BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, &expr1, dbl ? "daddiu" : "addiu", "t,r,j",
+ AT, 0, BFD_RELOC_LO16);
expr1.X_add_number = mips_trap ? (dbl ? 12 : 8) : (dbl ? 20 : 16);
- macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", treg, AT);
+ macro_build (NULL, &icnt, &expr1, "bne", "s,t,p", treg, AT);
if (dbl)
{
expr1.X_add_number = 1;
- macro_build ((char *) NULL, &icnt, &expr1, "daddiu", "t,r,j", AT, 0,
- (int) BFD_RELOC_LO16);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "dsll32",
- "d,w,<", AT, AT, 31);
+ 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);
}
else
{
expr1.X_add_number = 0x80000000;
- macro_build ((char *) NULL, &icnt, &expr1, "lui", "t,u", AT,
- (int) BFD_RELOC_HI16);
+ macro_build (NULL, &icnt, &expr1, "lui", "t,u", AT,
+ BFD_RELOC_HI16);
}
if (mips_trap)
{
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq",
- "s,t,q", sreg, AT, 6);
+ macro_build (NULL, &icnt, 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;
else
{
expr1.X_add_number = 8;
- macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", sreg, AT);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "",
- 0);
+ macro_build (NULL, &icnt, &expr1, "bne", "s,t,p", sreg, AT);
+ macro_build (NULL, &icnt, NULL, "nop", "", 0);
/* We want to close the noreorder block as soon as possible, so
that later insns are available for delay slot filling. */
--mips_opts.noreorder;
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
- "c", 6);
+ macro_build (NULL, &icnt, NULL, "break", "c", 6);
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d", dreg);
+ macro_build (NULL, &icnt, NULL, s, "d", dreg);
break;
case M_DIV_3I:
{
as_warn (_("Divide by zero."));
if (mips_trap)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq",
- "s,t,q", 0, 0, 7);
+ macro_build (NULL, &icnt, NULL, "teq", "s,t,q", 0, 0, 7);
else
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
- "c", 7);
+ macro_build (NULL, &icnt, NULL, "break", "c", 7);
return;
}
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1)
{
if (strcmp (s2, "mflo") == 0)
{
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- dbl ? "dneg" : "neg", "d,w", dreg, sreg);
+ macro_build (NULL, &icnt, NULL, dbl ? "dneg" : "neg", "d,w",
+ dreg, sreg);
}
else
move_register (&icnt, dreg, 0);
}
load_register (&icnt, AT, &imm_expr, dbl);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "z,s,t",
- sreg, AT);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s2, "d", dreg);
+ macro_build (NULL, &icnt, NULL, s, "z,s,t", sreg, AT);
+ macro_build (NULL, &icnt, NULL, s2, "d", dreg);
break;
case M_DIVU_3:
mips_any_noreorder = 1;
if (mips_trap)
{
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq",
- "s,t,q", treg, 0, 7);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "z,s,t",
- sreg, treg);
+ macro_build (NULL, &icnt, NULL, "teq", "s,t,q", treg, 0, 7);
+ macro_build (NULL, &icnt, 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;
else
{
expr1.X_add_number = 8;
- macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", treg, 0);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "z,s,t",
- sreg, treg);
+ macro_build (NULL, &icnt, &expr1, "bne", "s,t,p", treg, 0);
+ macro_build (NULL, &icnt, NULL, s, "z,s,t", sreg, treg);
/* We want to close the noreorder block as soon as possible, so
that later insns are available for delay slot filling. */
--mips_opts.noreorder;
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
- "c", 7);
+ macro_build (NULL, &icnt, NULL, "break", "c", 7);
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s2, "d", dreg);
+ macro_build (NULL, &icnt, NULL, s2, "d", dreg);
return;
case M_DLA_AB:
&& offset_expr.X_add_number >= -0x8000
&& offset_expr.X_add_number < 0x8000)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
+ macro_build (NULL, &icnt, &offset_expr,
(dbl || HAVE_64BIT_ADDRESSES) ? "daddiu" : "addiu",
- "t,r,j", treg, sreg, (int) BFD_RELOC_LO16);
+ "t,r,j", treg, sreg, BFD_RELOC_LO16);
return;
}
{
tempreg = treg;
used_at = 0;
- macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
- tempreg, (int) BFD_RELOC_PCREL_HI16_S);
+ macro_build (NULL, &icnt, &offset_expr, "lui", "t,u", tempreg,
+ BFD_RELOC_PCREL_HI16_S);
}
else
{
- macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
- tempreg, (int) BFD_RELOC_PCREL_HI16_S);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ macro_build (NULL, &icnt, &offset_expr, "lui", "t,u", tempreg,
+ BFD_RELOC_PCREL_HI16_S);
+ macro_build (NULL, &icnt, NULL,
(dbl || HAVE_64BIT_ADDRESSES) ? "daddu" : "addu",
"d,v,t", tempreg, tempreg, breg);
}
- macro_build ((char *) NULL, &icnt, &offset_expr,
+ macro_build (NULL, &icnt, &offset_expr,
(dbl || HAVE_64BIT_ADDRESSES) ? "daddiu" : "addiu",
- "t,r,j", treg, tempreg, (int) BFD_RELOC_PCREL_LO16);
+ "t,r,j", treg, tempreg, BFD_RELOC_PCREL_LO16);
if (! used_at)
return;
break;
if (used_at == 0 && ! mips_opts.noat)
{
macro_build (p, &icnt, &offset_expr, "lui", "t,u",
- tempreg, (int) BFD_RELOC_MIPS_HIGHEST);
+ tempreg, BFD_RELOC_MIPS_HIGHEST);
macro_build (p, &icnt, &offset_expr, "lui", "t,u",
- AT, (int) BFD_RELOC_HI16_S);
+ AT, BFD_RELOC_HI16_S);
macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
- tempreg, tempreg, (int) BFD_RELOC_MIPS_HIGHER);
+ tempreg, tempreg, BFD_RELOC_MIPS_HIGHER);
macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
- AT, AT, (int) BFD_RELOC_LO16);
- macro_build (p, &icnt, (expressionS *) NULL, "dsll32",
- "d,w,<", tempreg, tempreg, 0);
- macro_build (p, &icnt, (expressionS *) NULL, "daddu",
- "d,v,t", tempreg, tempreg, AT);
+ 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);
used_at = 1;
}
else
{
macro_build (p, &icnt, &offset_expr, "lui", "t,u",
- tempreg, (int) BFD_RELOC_MIPS_HIGHEST);
+ tempreg, BFD_RELOC_MIPS_HIGHEST);
macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
- tempreg, tempreg, (int) BFD_RELOC_MIPS_HIGHER);
- macro_build (p, &icnt, (expressionS *) NULL, "dsll", "d,w,<",
+ 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, (int) BFD_RELOC_HI16_S);
- macro_build (p, &icnt, (expressionS *) NULL, "dsll", "d,w,<",
+ 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",
- tempreg, tempreg, (int) BFD_RELOC_LO16);
+ tempreg, tempreg, BFD_RELOC_LO16);
}
}
else
&& ! nopic_need_relax (offset_expr.X_add_symbol, 1))
{
frag_grow (20);
- macro_build ((char *) NULL, &icnt, &offset_expr, "addiu",
+ macro_build (NULL, &icnt, &offset_expr, ADDRESS_ADDI_INSN,
"t,r,j", tempreg, mips_gp_register,
- (int) BFD_RELOC_GPREL16);
+ BFD_RELOC_GPREL16);
p = frag_var (rs_machine_dependent, 8, 0,
RELAX_ENCODE (4, 8, 0, 4, 0,
mips_opts.warn_about_macros),
macro_build_lui (p, &icnt, &offset_expr, tempreg);
if (p != NULL)
p += 4;
- macro_build (p, &icnt, &offset_expr, "addiu",
- "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
+ macro_build (p, &icnt, &offset_expr, ADDRESS_ADDI_INSN,
+ "t,r,j", tempreg, tempreg, BFD_RELOC_LO16);
}
}
- else if (mips_pic == SVR4_PIC && ! mips_big_got)
+ else if (mips_pic == SVR4_PIC && ! mips_big_got && ! HAVE_NEWABI)
{
int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
For a local symbol, we want the same instruction
sequence, but we output a BFD_RELOC_LO16 reloc on the
addiu instruction.
-
- For NewABI, we want for local or external data addresses
- lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_DISP)
- For a local function symbol, we want
- lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_PAGE)
- nop
- addiu $tempreg,$tempreg,<sym> (BFD_RELOC_MIPS_GOT_OFST)
*/
expr1.X_add_number = offset_expr.X_add_number;
frag_grow (32);
if (expr1.X_add_number == 0 && tempreg == PIC_CALL_REG)
lw_reloc_type = (int) BFD_RELOC_MIPS_CALL16;
- else if (HAVE_NEWABI)
- lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_DISP;
- macro_build ((char *) NULL, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
- "t,o(b)", tempreg, lw_reloc_type, mips_gp_register);
+ 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)
{
int off;
/* We're going to put in an addu instruction using
tempreg, so we may as well insert the nop right
now. */
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- "nop", "");
+ macro_build (NULL, &icnt, NULL, "nop", "");
off = 4;
}
p = frag_var (rs_machine_dependent, 8 - off, 0,
offset_expr.X_add_symbol, 0, NULL);
if (breg == 0)
{
- macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
+ macro_build (p, &icnt, NULL, "nop", "");
p += 4;
}
- macro_build (p, &icnt, &expr1,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
+ macro_build (p, &icnt, &expr1, ADDRESS_ADDI_INSN,
+ "t,r,j", tempreg, tempreg, BFD_RELOC_LO16);
/* 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)
{
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- "nop", "");
- macro_build ((char *) NULL, &icnt, &expr1,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
+ 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);
off1 = 0;
else
{
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- "nop", "");
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", treg, AT, breg);
+ macro_build (NULL, &icnt, NULL, "nop", "");
+ macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ treg, AT, breg);
breg = 0;
tempreg = treg;
off1 = -8;
macro_build_lui (NULL, &icnt, &expr1, AT);
mips_optimize = hold_mips_optimize;
- macro_build ((char *) NULL, &icnt, &expr1,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", AT, AT, (int) BFD_RELOC_LO16);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", tempreg, tempreg, 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",
+ 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);
used_at = 1;
}
}
- else if (mips_pic == SVR4_PIC)
+ 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;
+
+ /* If this is a reference to an external, and there is no
+ constant, or local symbol (*), with or without a
+ constant, we want
+ lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_DISP)
+ or if tempreg is PIC_CALL_REG
+ lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_CALL16)
+
+ If we have a small constant, and this is a reference to
+ an external symbol, we want
+ lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_DISP)
+ addiu $tempreg,$tempreg,<constant>
+
+ If we have a large constant, and this is a reference to
+ an external symbol, we want
+ lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_DISP)
+ lui $at,<hiconstant>
+ addiu $at,$at,<loconstant>
+ addu $tempreg,$tempreg,$at
+
+ (*) Other assemblers seem to prefer GOT_PAGE/GOT_OFST for
+ local symbols, even though it introduces an additional
+ instruction. */
+
+ frag_grow (28);
+ if (offset_expr.X_add_number == 0 && 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;
+ 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);
+
+ 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);
+ }
+ else if (IS_SEXT_32BIT_NUM (expr1.X_add_number))
+ {
+ int dreg;
+
+ /* 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
+ we want to load the constant into AT, we add our
+ 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)
+ dreg = tempreg;
+ else
+ {
+ assert (tempreg == AT);
+ macro_build (NULL, &icnt,NULL, ADDRESS_ADD_INSN,
+ "d,v,t", treg, AT, breg);
+ dreg = treg;
+ adj = 4;
+ }
+
+ 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, 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)"));
+
+ 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 (p + 4, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ treg, tempreg, breg);
+ breg = 0;
+ tempreg = treg;
+ }
+ }
+ else
+ {
+ 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);
+ }
+
+ 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);
+ }
+ }
+ else if (mips_pic == SVR4_PIC && ! HAVE_NEWABI)
{
int gpdel;
char *p;
lui $at,<hiconstant>
addiu $at,$at,<loconstant> (BFD_RELOC_LO16)
addu $tempreg,$tempreg,$at
-
- For NewABI, we want for local data addresses
- lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_DISP)
- */
+ */
expr1.X_add_number = offset_expr.X_add_number;
offset_expr.X_add_number = 0;
lui_reloc_type = (int) BFD_RELOC_MIPS_CALL_HI16;
lw_reloc_type = (int) BFD_RELOC_MIPS_CALL_LO16;
}
- macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
+ macro_build (NULL, &icnt, &offset_expr, "lui", "t,u",
tempreg, lui_reloc_type);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", tempreg, tempreg, mips_gp_register);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
- "t,o(b)", tempreg, lw_reloc_type, tempreg);
+ 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, lw_reloc_type, tempreg);
if (expr1.X_add_number == 0)
{
int off;
/* We're going to put in an addu instruction using
tempreg, so we may as well insert the nop right
now. */
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- "nop", "");
+ macro_build (NULL, &icnt, NULL, "nop", "");
off = 4;
}
else if (expr1.X_add_number >= -0x8000
&& expr1.X_add_number < 0x8000)
{
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- "nop", "");
- macro_build ((char *) NULL, &icnt, &expr1,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, NULL, "nop", "");
+ macro_build (NULL, &icnt, &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,
else
{
assert (tempreg == AT);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- "nop", "");
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", treg, AT, breg);
+ macro_build (NULL, &icnt, NULL, "nop", "");
+ macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ treg, AT, breg);
dreg = treg;
adj = 8;
}
macro_build_lui (NULL, &icnt, &expr1, AT);
mips_optimize = hold_mips_optimize;
- macro_build ((char *) NULL, &icnt, &expr1,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", AT, AT, (int) BFD_RELOC_LO16);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", dreg, dreg, 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, 16 + gpdel + adj, 0,
RELAX_ENCODE (24 + adj, 16 + gpdel + adj, gpdel,
if (gpdel > 0)
{
/* This is needed because this instruction uses $gp, but
- the first instruction on the main stream does not. */
- macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
+ the first instruction on the main stream does not. */
+ macro_build (p, &icnt, NULL, "nop", "");
p += 4;
}
- if (HAVE_NEWABI)
- local_reloc_type = (int) BFD_RELOC_MIPS_GOT_DISP;
- macro_build (p, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
- "t,o(b)", tempreg,
- local_reloc_type,
- mips_gp_register);
+ macro_build (p, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
+ tempreg, local_reloc_type, mips_gp_register);
p += 4;
- if (expr1.X_add_number == 0 && HAVE_NEWABI)
- {
- /* BFD_RELOC_MIPS_GOT_DISP is sufficient for newabi */
- }
- else
- if (expr1.X_add_number >= -0x8000
+ if (expr1.X_add_number >= -0x8000
&& expr1.X_add_number < 0x8000)
{
- macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
+ macro_build (p, &icnt, NULL, "nop", "");
p += 4;
- macro_build (p, &icnt, &expr1,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
+ macro_build (p, &icnt, &expr1, 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
- the next instruction uses tempreg, an unnecessary nop
- will be inserted. */
+ register, the external symbol case ended with a load,
+ so if the symbol turns out to not be external, and
+ the next instruction uses tempreg, an unnecessary nop
+ will be inserted. */
}
else
{
if (breg == treg)
{
/* We must add in the base register now, as in the
- external symbol case. */
+ external symbol case. */
assert (tempreg == AT);
- macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
+ macro_build (p, &icnt, NULL, "nop", "");
p += 4;
- macro_build (p, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", treg, AT, breg);
+ macro_build (p, &icnt, 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. */
+ it in in both cases. */
breg = 0;
}
macro_build_lui (p, &icnt, &expr1, AT);
p += 4;
- macro_build (p, &icnt, &expr1,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", AT, AT, (int) BFD_RELOC_LO16);
+ macro_build (p, &icnt, &expr1, ADDRESS_ADDI_INSN, "t,r,j",
+ AT, AT, BFD_RELOC_LO16);
p += 4;
- macro_build (p, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", tempreg, tempreg, AT);
+ macro_build (p, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ tempreg, tempreg, AT);
p += 4;
}
}
+ 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;
+
+ /* This is the large GOT case. If this is a reference to an
+ external symbol, and there is no constant, we want
+ lui $tempreg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
+ add $tempreg,$tempreg,$gp
+ lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_LO16)
+ or if tempreg is PIC_CALL_REG
+ lui $tempreg,<sym> (BFD_RELOC_MIPS_CALL_HI16)
+ add $tempreg,$tempreg,$gp
+ lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_CALL_LO16)
+
+ If we have a small constant, and this is a reference to
+ an external symbol, we want
+ lui $tempreg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
+ add $tempreg,$tempreg,$gp
+ lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_LO16)
+ addi $tempreg,$tempreg,<constant>
+
+ If we have a large constant, and this is a reference to
+ an external symbol, we want
+ lui $tempreg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
+ addu $tempreg,$tempreg,$gp
+ lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_LO16)
+ lui $at,<hiconstant>
+ addi $at,$at,<loconstant>
+ add $tempreg,$tempreg,$at
+
+ If we have NewABI, and we know it's a local symbol, we want
+ lw $reg,<sym>($gp) (BFD_RELOC_MIPS_GOT_PAGE)
+ addiu $reg,$reg,<sym> (BFD_RELOC_MIPS_GOT_OFST)
+ otherwise we have to resort to GOT_HI16/GOT_LO16. */
+
+ frag_grow (40);
+
+ frag_now->tc_frag_data.tc_fr_offset =
+ expr1.X_add_number = offset_expr.X_add_number;
+ offset_expr.X_add_number = 0;
+
+ if (expr1.X_add_number == 0 && 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",
+ tempreg, tempreg, mips_gp_register);
+ macro_build (NULL, &icnt, &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",
+ 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))
+ {
+ int dreg;
+
+ /* 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
+ we want to load the constant into AT, we add our
+ 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)
+ dreg = tempreg;
+ else
+ {
+ assert (tempreg == AT);
+ macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ treg, AT, breg);
+ dreg = treg;
+ adj = 4;
+ }
+
+ /* 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);
+
+ used_at = 1;
+ }
+ else
+ as_bad (_("PIC code offset overflow (max 32 signed bits)"));
+
+ 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 (p + 8, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ treg, tempreg, breg);
+ breg = 0;
+ tempreg = treg;
+ }
+ }
else if (mips_pic == EMBEDDED_PIC)
{
/* We use
addiu $tempreg,$gp,<sym> (BFD_RELOC_GPREL16)
*/
- macro_build ((char *) NULL, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu", "t,r,j",
- tempreg, mips_gp_register, (int) BFD_RELOC_GPREL16);
+ macro_build (NULL, &icnt, &offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
+ tempreg, mips_gp_register, BFD_RELOC_GPREL16);
}
else
abort ();
if (mips_pic == EMBEDDED_PIC || mips_pic == NO_PIC)
s = (dbl || HAVE_64BIT_ADDRESSES) ? "daddu" : "addu";
else
- s = HAVE_64BIT_ADDRESSES ? "daddu" : "addu";
+ s = ADDRESS_ADD_INSN;
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s,
- "d,v,t", treg, tempreg, breg);
+ macro_build (NULL, &icnt, NULL, s, "d,v,t", treg, tempreg, breg);
}
if (! used_at)
requires an absolute address. We convert it to a b
instruction. */
if (mips_pic == NO_PIC)
- macro_build ((char *) NULL, &icnt, &offset_expr, "j", "a");
+ macro_build (NULL, &icnt, &offset_expr, "j", "a");
else
- macro_build ((char *) NULL, &icnt, &offset_expr, "b", "p");
+ macro_build (NULL, &icnt, &offset_expr, "b", "p");
return;
/* The jal instructions must be handled as macros because when
case M_JAL_2:
if (mips_pic == NO_PIC
|| mips_pic == EMBEDDED_PIC)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "jalr",
- "d,s", dreg, sreg);
+ macro_build (NULL, &icnt, 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 ((char *) NULL, &icnt, (expressionS *) NULL, "jalr",
- "d,s", dreg, sreg);
+ macro_build (NULL, &icnt, NULL, "jalr", "d,s", dreg, sreg);
if (! HAVE_NEWABI)
{
if (mips_cprestore_offset < 0)
mips_cprestore_valid = 1;
}
expr1.X_add_number = mips_cprestore_offset;
- macro_build_ldst_constoffset ((char *) NULL, &icnt, &expr1,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
- mips_gp_register, mips_frame_reg);
+ macro_build_ldst_constoffset (NULL, &icnt, &expr1,
+ ADDRESS_LOAD_INSN,
+ mips_gp_register,
+ mips_frame_reg);
}
}
}
case M_JAL_A:
if (mips_pic == NO_PIC)
- macro_build ((char *) NULL, &icnt, &offset_expr, "jal", "a");
+ macro_build (NULL, &icnt, &offset_expr, "jal", "a");
else if (mips_pic == SVR4_PIC)
{
char *p;
jalr $ra,$25
nop
lw $gp,cprestore($sp)
- For NewABI, we want
- lw $25,<sym>($gp) (BFD_RELOC_MIPS_GOT_DISP)
- jalr $ra,$25 (BFD_RELOC_MIPS_JALR)
- */
+
+ For NewABI, we use the same CALL16 or CALL_HI16/CALL_LO16
+ sequences above, minus nops, unless the symbol is local,
+ which enables us to use GOT_PAGE/GOT_OFST (big got) or
+ GOT_DISP. */
if (HAVE_NEWABI)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
- "t,o(b)", PIC_CALL_REG,
- (int) BFD_RELOC_MIPS_GOT_DISP, mips_gp_register);
+ 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,
+ 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);
+ }
+ 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,
+ BFD_RELOC_MIPS_GOT_OFST);
+ }
+
macro_build_jalr (icnt, &offset_expr);
}
else
frag_grow (40);
if (! mips_big_got)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
- "t,o(b)", PIC_CALL_REG,
- (int) BFD_RELOC_MIPS_CALL16, mips_gp_register);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- "nop", "");
+ macro_build (NULL, &icnt, &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);
gpdel = 4;
else
gpdel = 0;
- macro_build ((char *) NULL, &icnt, &offset_expr, "lui",
- "t,u", PIC_CALL_REG,
- (int) BFD_RELOC_MIPS_CALL_HI16);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", PIC_CALL_REG, PIC_CALL_REG,
- mips_gp_register);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
+ 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,
- (int) BFD_RELOC_MIPS_CALL_LO16, PIC_CALL_REG);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- "nop", "");
+ 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, (expressionS *) NULL, "nop", "");
+ macro_build (p, &icnt, NULL, "nop", "");
p += 4;
}
- macro_build (p, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
- "t,o(b)", PIC_CALL_REG,
- (int) BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ 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, (expressionS *) NULL, "nop", "");
+ macro_build (p, &icnt, NULL, "nop", "");
p += 4;
}
- macro_build (p, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
+ macro_build (p, &icnt, &offset_expr, ADDRESS_ADDI_INSN,
"t,r,j", PIC_CALL_REG, PIC_CALL_REG,
- (int) BFD_RELOC_LO16);
+ BFD_RELOC_LO16);
macro_build_jalr (icnt, &offset_expr);
if (mips_cprestore_offset < 0)
mips_cprestore_valid = 1;
}
if (mips_opts.noreorder)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- "nop", "");
+ macro_build (NULL, &icnt, NULL, "nop", "");
expr1.X_add_number = mips_cprestore_offset;
- macro_build_ldst_constoffset ((char *) NULL, &icnt, &expr1,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
- mips_gp_register, mips_frame_reg);
+ macro_build_ldst_constoffset (NULL, &icnt, &expr1,
+ ADDRESS_LOAD_INSN,
+ mips_gp_register,
+ mips_frame_reg);
}
}
}
else if (mips_pic == EMBEDDED_PIC)
{
- macro_build ((char *) NULL, &icnt, &offset_expr, "bal", "p");
+ macro_build (NULL, &icnt, &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;
lr = 1;
goto ld;
case M_LDC1_AB:
- if (mips_arch == CPU_R4650)
+ if (mips_opts.arch == CPU_R4650)
{
as_bad (_("opcode not supported on this processor"));
return;
s = "scd";
goto st;
case M_SDC1_AB:
- if (mips_arch == CPU_R4650)
+ if (mips_opts.arch == CPU_R4650)
{
as_bad (_("opcode not supported on this processor"));
return;
nice to emit:
<op> $treg,<sym>($breg) (BFD_RELOC_PCREL_LO16)
instead, but that seems quite difficult. */
- macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
- tempreg, (int) BFD_RELOC_PCREL_HI16_S);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ macro_build (NULL, &icnt, &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 ((char *) NULL, &icnt, &offset_expr, s, fmt, treg,
- (int) BFD_RELOC_PCREL_LO16, tempreg);
+ macro_build (NULL, &icnt, &offset_expr, s, fmt, treg,
+ BFD_RELOC_PCREL_LO16, tempreg);
if (! used_at)
return;
break;
range is shifted down by 32768 here. This code should
probably attempt to generate 64-bit constants more
efficiently in general.
- */
- if (HAVE_64BIT_ADDRESSES
- && !(offset_expr.X_op == O_constant
- && IS_SEXT_32BIT_NUM (offset_expr.X_add_number + 0x8000)))
+
+ As an extension for architectures with 64-bit registers,
+ we don't truncate 64-bit addresses given as literal
+ constants down to 32 bits, to support existing practice
+ in the mips64 Linux (the kernel), that compiles source
+ files with -mabi=64, assembling them as o32 or n32 (with
+ -Wa,-32 or -Wa,-n32). This is not beautiful, but since
+ the whole kernel is loaded into a memory region that is
+ addressible with sign-extended 32-bit addresses, it is
+ wasteful to compute the upper 32 bits of every
+ non-literal address, that takes more space and time.
+ Some day this should probably be implemented as an
+ assembler option, such that the kernel doesn't have to
+ use such ugly hacks, even though it will still have to
+ end up converting the binary to ELF32 for a number of
+ platforms whose boot loaders don't support ELF64
+ binaries. */
+ if ((offset_expr.X_op != O_constant && HAVE_64BIT_ADDRESSES)
+ || (offset_expr.X_op == O_constant
+ && !IS_SEXT_32BIT_NUM (offset_expr.X_add_number + 0x8000)
+ && HAVE_64BIT_ADDRESS_CONSTANTS))
{
p = NULL;
if (used_at == 0 && ! mips_opts.noat)
{
macro_build (p, &icnt, &offset_expr, "lui", "t,u",
- tempreg, (int) BFD_RELOC_MIPS_HIGHEST);
+ tempreg, BFD_RELOC_MIPS_HIGHEST);
macro_build (p, &icnt, &offset_expr, "lui", "t,u",
- AT, (int) BFD_RELOC_HI16_S);
+ AT, BFD_RELOC_HI16_S);
macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
- tempreg, tempreg, (int) BFD_RELOC_MIPS_HIGHER);
+ tempreg, tempreg, BFD_RELOC_MIPS_HIGHER);
if (breg != 0)
- macro_build (p, &icnt, (expressionS *) NULL, "daddu",
- "d,v,t", AT, AT, breg);
- macro_build (p, &icnt, (expressionS *) NULL, "dsll32",
- "d,w,<", tempreg, tempreg, 0);
- macro_build (p, &icnt, (expressionS *) NULL, "daddu",
- "d,v,t", tempreg, tempreg, AT);
- macro_build (p, &icnt, &offset_expr, s,
- fmt, treg, (int) BFD_RELOC_LO16, tempreg);
+ 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);
used_at = 1;
}
else
{
macro_build (p, &icnt, &offset_expr, "lui", "t,u",
- tempreg, (int) BFD_RELOC_MIPS_HIGHEST);
+ tempreg, BFD_RELOC_MIPS_HIGHEST);
macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j",
- tempreg, tempreg, (int) BFD_RELOC_MIPS_HIGHER);
- macro_build (p, &icnt, (expressionS *) NULL, "dsll",
- "d,w,<", tempreg, tempreg, 16);
+ 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, (int) BFD_RELOC_HI16_S);
- macro_build (p, &icnt, (expressionS *) NULL, "dsll",
- "d,w,<", tempreg, tempreg, 16);
+ tempreg, tempreg, BFD_RELOC_HI16_S);
+ macro_build (p, &icnt, NULL, "dsll", "d,w,<",
+ tempreg, tempreg, 16);
if (breg != 0)
- macro_build (p, &icnt, (expressionS *) NULL, "daddu",
- "d,v,t", tempreg, tempreg, breg);
- macro_build (p, &icnt, &offset_expr, s,
- fmt, treg, (int) BFD_RELOC_LO16, tempreg);
+ macro_build (p, &icnt, NULL, "daddu", "d,v,t",
+ tempreg, tempreg, breg);
+ macro_build (p, &icnt, &offset_expr, s, fmt, treg,
+ BFD_RELOC_LO16, tempreg);
}
return;
}
+ else if (offset_expr.X_op == O_constant
+ && !HAVE_64BIT_ADDRESS_CONSTANTS
+ && !IS_SEXT_32BIT_NUM (offset_expr.X_add_number))
+ as_bad (_("load/store address overflow (max 32 bits)"));
if (breg == 0)
{
else
{
frag_grow (20);
- macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
- treg, (int) BFD_RELOC_GPREL16,
- mips_gp_register);
+ 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
if (p != NULL)
p += 4;
macro_build (p, &icnt, &offset_expr, s, fmt, treg,
- (int) BFD_RELOC_LO16, tempreg);
+ BFD_RELOC_LO16, tempreg);
}
else
{
else
{
frag_grow (28);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", tempreg, breg, mips_gp_register);
- macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
- treg, (int) BFD_RELOC_GPREL16, tempreg);
+ macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ tempreg, breg, mips_gp_register);
+ macro_build (NULL, &icnt, &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);
macro_build_lui (p, &icnt, &offset_expr, tempreg);
if (p != NULL)
p += 4;
- macro_build (p, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", tempreg, tempreg, breg);
+ macro_build (p, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ tempreg, tempreg, breg);
if (p != NULL)
p += 4;
macro_build (p, &icnt, &offset_expr, s, fmt, treg,
- (int) BFD_RELOC_LO16, tempreg);
+ BFD_RELOC_LO16, tempreg);
}
}
else if (mips_pic == SVR4_PIC && ! mips_big_got)
nop
addiu $tempreg,$tempreg,<sym> (BFD_RELOC_LO16)
<op> $treg,0($tempreg)
- If we have NewABI, we want
- lw $reg,<sym>($gp) (BFD_RELOC_MIPS_GOT_DISP)
+
+ For NewABI, we want
+ lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_PAGE)
+ <op> $treg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_OFST)
+
If there is a base register, we add it to $tempreg before
the <op>. If there is a constant, we stick it in the
<op> instruction. We don't handle constants larger than
(actually, we could handle them for the subset of cases
in which we are not using $at). */
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);
+ if (breg != 0)
+ macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ tempreg, tempreg, breg);
+ macro_build (NULL, &icnt, &offset_expr, s, fmt, treg,
+ BFD_RELOC_MIPS_GOT_OFST, tempreg);
+
+ if (! used_at)
+ return;
+
+ break;
+ }
expr1.X_add_number = offset_expr.X_add_number;
offset_expr.X_add_number = 0;
- if (HAVE_NEWABI)
- lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_DISP;
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 ((char *) NULL, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)", tempreg,
- (int) lw_reloc_type, mips_gp_register);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
+ 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,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
+ macro_build (p, &icnt, &offset_expr, ADDRESS_ADDI_INSN,
+ "t,r,j", tempreg, tempreg, BFD_RELOC_LO16);
if (breg != 0)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", tempreg, tempreg, breg);
- macro_build ((char *) NULL, &icnt, &expr1, s, fmt, treg,
- (int) BFD_RELOC_LO16, tempreg);
+ macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ tempreg, tempreg, breg);
+ macro_build (NULL, &icnt, &expr1, s, fmt, treg, BFD_RELOC_LO16,
+ tempreg);
}
- else if (mips_pic == SVR4_PIC)
+ else if (mips_pic == SVR4_PIC && ! HAVE_NEWABI)
{
int gpdel;
char *p;
<op> instruction. We don't handle constants larger than
16 bits, because we have no way to load the upper 16 bits
(actually, we could handle them for the subset of cases
- in which we are not using $at).
-
- For NewABI, we want
- lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_PAGE)
- addiu $tempreg,$tempreg,<sym> (BFD_RELOC_MIPS_GOT_OFST)
- <op> $treg,0($tempreg)
- */
+ in which we are not using $at). */
assert (offset_expr.X_op == O_symbol);
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)"));
- if (HAVE_NEWABI)
- {
- macro_build ((char *) NULL, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
- "t,o(b)", tempreg, BFD_RELOC_MIPS_GOT_PAGE,
- mips_gp_register);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", tempreg, tempreg,
- BFD_RELOC_MIPS_GOT_OFST);
- if (breg != 0)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", tempreg, tempreg, breg);
- macro_build ((char *) NULL, &icnt, &expr1, s, fmt, treg,
- (int) BFD_RELOC_LO16, tempreg);
-
- if (! used_at)
- return;
-
- break;
- }
if (reg_needs_delay (mips_gp_register))
gpdel = 4;
else
gpdel = 0;
frag_grow (36);
- macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
- tempreg, (int) BFD_RELOC_MIPS_GOT_HI16);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", tempreg, tempreg, mips_gp_register);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
- "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT_LO16,
+ macro_build (NULL, &icnt, &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);
+ if (breg != 0)
+ macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ tempreg, tempreg, breg);
+ macro_build (NULL, &icnt, &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
+ lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_LO16)
+ <op> $treg,<ofst>($tempreg)
+ Otherwise, for local symbols, we want:
+ 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_now->tc_frag_data.tc_fr_offset =
+ 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)"));
+ frag_grow (36);
+ macro_build (NULL, &icnt, &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);
+ if (breg != 0)
+ macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ tempreg, tempreg, breg);
+ macro_build (NULL, &icnt, &expr1, s, fmt, treg, BFD_RELOC_LO16,
tempreg);
- p = frag_var (rs_machine_dependent, 12 + gpdel, 0,
- RELAX_ENCODE (12, 12 + gpdel, gpdel, 8 + gpdel, 0, 0),
+
+ offset_expr.X_add_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);
- if (gpdel > 0)
- {
- macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
- p += 4;
- }
- macro_build (p, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
- "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16,
- mips_gp_register);
- p += 4;
- macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
- p += 4;
- macro_build (p, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
+ macro_build (p, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
+ tempreg, BFD_RELOC_MIPS_GOT_PAGE, mips_gp_register);
if (breg != 0)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", tempreg, tempreg, breg);
- macro_build ((char *) NULL, &icnt, &expr1, s, fmt, treg,
- (int) BFD_RELOC_LO16, tempreg);
+ macro_build (p + 4, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ tempreg, tempreg, breg);
+ macro_build (p + 4 + bregsz, &icnt, &offset_expr, s, fmt, treg,
+ BFD_RELOC_MIPS_GOT_OFST, tempreg);
}
else if (mips_pic == EMBEDDED_PIC)
{
assert (offset_expr.X_op == O_symbol);
if (breg == 0)
{
- macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
- treg, (int) BFD_RELOC_GPREL16, mips_gp_register);
+ macro_build (NULL, &icnt, &offset_expr, s, fmt, treg,
+ BFD_RELOC_GPREL16, mips_gp_register);
used_at = 0;
}
else
{
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", tempreg, breg, mips_gp_register);
- macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
- treg, (int) BFD_RELOC_GPREL16, tempreg);
+ macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ tempreg, breg, mips_gp_register);
+ macro_build (NULL, &icnt, &offset_expr, s, fmt, treg,
+ BFD_RELOC_GPREL16, tempreg);
}
}
else
if (imm_expr.X_op == O_constant)
{
load_register (&icnt, AT, &imm_expr, 0);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- "mtc1", "t,G", AT, treg);
+ macro_build (NULL, &icnt, NULL, "mtc1", "t,G", AT, treg);
break;
}
else
(offset_expr.X_add_symbol)),
".lit4") == 0
&& offset_expr.X_add_number == 0);
- macro_build ((char *) NULL, &icnt, &offset_expr, "lwc1", "T,o(b)",
- treg, (int) BFD_RELOC_MIPS_LITERAL, mips_gp_register);
+ macro_build (NULL, &icnt, &offset_expr, "lwc1", "T,o(b)", treg,
+ BFD_RELOC_MIPS_LITERAL, mips_gp_register);
return;
}
}
else if (mips_pic == SVR4_PIC)
{
- macro_build ((char *) NULL, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
- "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16,
- mips_gp_register);
+ macro_build (NULL, &icnt, &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 ((char *) NULL, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu", "t,r,j", AT,
- mips_gp_register, (int) BFD_RELOC_GPREL16);
+ macro_build (NULL, &icnt, &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;
}
/* Now we load the register(s). */
if (HAVE_64BIT_GPRS)
- macro_build ((char *) NULL, &icnt, &offset_expr, "ld", "t,o(b)",
- treg, (int) BFD_RELOC_LO16, AT);
+ macro_build (NULL, &icnt, &offset_expr, "ld", "t,o(b)", treg,
+ BFD_RELOC_LO16, AT);
else
{
- macro_build ((char *) NULL, &icnt, &offset_expr, "lw", "t,o(b)",
- treg, (int) BFD_RELOC_LO16, AT);
+ macro_build (NULL, &icnt, &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 ((char *) NULL, &icnt, &offset_expr, "lw", "t,o(b)",
- treg + 1, (int) BFD_RELOC_LO16, AT);
+ macro_build (NULL, &icnt, &offset_expr, "lw", "t,o(b)",
+ treg + 1, BFD_RELOC_LO16, AT);
}
}
if (HAVE_64BIT_FPRS)
{
assert (HAVE_64BIT_GPRS);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- "dmtc1", "t,S", AT, treg);
+ macro_build (NULL, &icnt, NULL, "dmtc1", "t,S", AT, treg);
}
else
{
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- "mtc1", "t,G", AT, treg + 1);
+ macro_build (NULL, &icnt, NULL, "mtc1", "t,G", AT, treg + 1);
if (offset_expr.X_op == O_absent)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- "mtc1", "t,G", 0, treg);
+ macro_build (NULL, &icnt, NULL, "mtc1", "t,G", 0, treg);
else
{
assert (offset_expr.X_op == O_constant);
load_register (&icnt, AT, &offset_expr, 0);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- "mtc1", "t,G", AT, treg);
+ macro_build (NULL, &icnt, NULL, "mtc1", "t,G", AT, treg);
}
}
break;
{
if (mips_opts.isa != ISA_MIPS1)
{
- macro_build ((char *) NULL, &icnt, &offset_expr, "ldc1",
- "T,o(b)", treg, (int) BFD_RELOC_MIPS_LITERAL,
- mips_gp_register);
+ macro_build (NULL, &icnt, &offset_expr, "ldc1", "T,o(b)", treg,
+ BFD_RELOC_MIPS_LITERAL, mips_gp_register);
return;
}
breg = mips_gp_register;
{
assert (strcmp (s, RDATA_SECTION_NAME) == 0);
if (mips_pic == SVR4_PIC)
- macro_build ((char *) NULL, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
- "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16,
+ macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
+ "t,o(b)", AT, BFD_RELOC_MIPS_GOT16,
mips_gp_register);
else
{
if (mips_opts.isa != ISA_MIPS1)
{
- macro_build ((char *) NULL, &icnt, &offset_expr, "ldc1",
- "T,o(b)", treg, (int) BFD_RELOC_LO16, AT);
+ 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. */
}
case M_L_DOB:
- if (mips_arch == CPU_R4650)
+ if (mips_opts.arch == CPU_R4650)
{
as_bad (_("opcode not supported on this processor"));
return;
r = BFD_RELOC_LO16;
dob:
assert (mips_opts.isa == ISA_MIPS1);
- macro_build ((char *) NULL, &icnt, &offset_expr, "lwc1", "T,o(b)",
- target_big_endian ? treg + 1 : treg,
- (int) r, breg);
+ macro_build (NULL, &icnt, &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 ((char *) NULL, &icnt, &offset_expr, "lwc1", "T,o(b)",
- target_big_endian ? treg : treg + 1,
- (int) r, breg);
+ macro_build (NULL, &icnt, &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. */
* But, the resulting address is the same after relocation so why
* generate the extra instruction?
*/
- if (mips_arch == CPU_R4650)
+ if (mips_opts.arch == CPU_R4650)
{
as_bad (_("opcode not supported on this processor"));
return;
goto ldd_std;
case M_S_DAB:
- if (mips_arch == CPU_R4650)
+ if (mips_opts.arch == CPU_R4650)
{
as_bad (_("opcode not supported on this processor"));
return;
else
{
frag_grow (36);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", AT, breg, mips_gp_register);
+ macro_build (NULL, &icnt, 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 ((char *) NULL, &icnt, &offset_expr, s, fmt,
+ macro_build (NULL, &icnt, &offset_expr, s, fmt,
coproc ? treg + 1 : treg,
- (int) BFD_RELOC_GPREL16, tempreg);
+ BFD_RELOC_GPREL16, tempreg);
offset_expr.X_add_number += 4;
/* Set mips_optimize to 2 to avoid inserting an
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
/* Itbl support may require additional care here. */
- macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
+ macro_build (NULL, &icnt, &offset_expr, s, fmt,
coproc ? treg : treg + 1,
- (int) BFD_RELOC_GPREL16, tempreg);
+ BFD_RELOC_GPREL16, tempreg);
mips_optimize = hold_mips_optimize;
p = frag_var (rs_machine_dependent, 12 + off, 0,
p += 4;
if (breg != 0)
{
- macro_build (p, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", AT, breg, AT);
+ macro_build (p, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ AT, breg, AT);
if (p != NULL)
p += 4;
}
/* Itbl support may require additional care here. */
macro_build (p, &icnt, &offset_expr, s, fmt,
coproc ? treg + 1 : treg,
- (int) BFD_RELOC_LO16, AT);
+ BFD_RELOC_LO16, AT);
if (p != NULL)
p += 4;
/* FIXME: How do we handle overflow here? */
/* Itbl support may require additional care here. */
macro_build (p, &icnt, &offset_expr, s, fmt,
coproc ? treg : treg + 1,
- (int) BFD_RELOC_LO16, AT);
+ BFD_RELOC_LO16, AT);
}
else if (mips_pic == SVR4_PIC && ! mips_big_got)
{
else
off = 4;
frag_grow (24 + off);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)", AT,
- (int) BFD_RELOC_MIPS_GOT16, mips_gp_register);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
+ 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", "");
if (breg != 0)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", AT, breg, AT);
+ macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ AT, breg, AT);
/* Itbl support may require additional care here. */
- macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
- coproc ? treg + 1 : treg,
- (int) BFD_RELOC_LO16, AT);
+ macro_build (NULL, &icnt, &expr1, s, fmt, coproc ? treg + 1 : treg,
+ BFD_RELOC_LO16, AT);
expr1.X_add_number += 4;
/* Set mips_optimize to 2 to avoid inserting an undesired
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
/* Itbl support may require additional care here. */
- macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
- coproc ? treg : treg + 1,
- (int) BFD_RELOC_LO16, AT);
+ macro_build (NULL, &icnt, &expr1, s, fmt, coproc ? treg : treg + 1,
+ BFD_RELOC_LO16, AT);
mips_optimize = hold_mips_optimize;
(void) frag_var (rs_machine_dependent, 0, 0,
else
off = 4;
frag_grow (56);
- macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
- AT, (int) BFD_RELOC_MIPS_GOT_HI16);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", AT, AT, mips_gp_register);
- macro_build ((char *) NULL, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
- "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT_LO16, AT);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
+ 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",
+ AT, AT, mips_gp_register);
+ macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
+ AT, BFD_RELOC_MIPS_GOT_LO16, AT);
+ macro_build (NULL, &icnt, NULL, "nop", "");
if (breg != 0)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", AT, breg, AT);
+ macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ AT, breg, AT);
/* Itbl support may require additional care here. */
- macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
- coproc ? treg + 1 : treg,
- (int) BFD_RELOC_LO16, AT);
+ macro_build (NULL, &icnt, &expr1, s, fmt, coproc ? treg + 1 : treg,
+ BFD_RELOC_LO16, AT);
expr1.X_add_number += 4;
/* Set mips_optimize to 2 to avoid inserting an undesired
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
/* Itbl support may require additional care here. */
- macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
- coproc ? treg : treg + 1,
- (int) BFD_RELOC_LO16, AT);
+ macro_build (NULL, &icnt, &expr1, s, fmt, coproc ? treg : treg + 1,
+ BFD_RELOC_LO16, AT);
mips_optimize = hold_mips_optimize;
expr1.X_add_number -= 4;
offset_expr.X_add_symbol, 0, NULL);
if (gpdel > 0)
{
- macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
+ macro_build (p, &icnt, NULL, "nop", "");
p += 4;
}
- macro_build (p, &icnt, &offset_expr,
- HAVE_32BIT_ADDRESSES ? "lw" : "ld",
- "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16,
- mips_gp_register);
+ 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, (expressionS *) NULL, "nop", "");
+ macro_build (p, &icnt, NULL, "nop", "");
p += 4;
if (breg != 0)
{
- macro_build (p, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", AT, breg, AT);
+ macro_build (p, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ AT, breg, AT);
p += 4;
}
/* Itbl support may require additional care here. */
- macro_build (p, &icnt, &expr1, s, fmt,
- coproc ? treg + 1 : treg,
- (int) BFD_RELOC_LO16, AT);
+ macro_build (p, &icnt, &expr1, s, fmt, coproc ? treg + 1 : treg,
+ BFD_RELOC_LO16, AT);
p += 4;
expr1.X_add_number += 4;
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
/* Itbl support may require additional care here. */
- macro_build (p, &icnt, &expr1, s, fmt,
- coproc ? treg : treg + 1,
- (int) BFD_RELOC_LO16, AT);
+ macro_build (p, &icnt, &expr1, s, fmt, coproc ? treg : treg + 1,
+ BFD_RELOC_LO16, AT);
mips_optimize = hold_mips_optimize;
}
else if (mips_pic == EMBEDDED_PIC)
}
else
{
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", AT, breg, mips_gp_register);
+ macro_build (NULL, &icnt, 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 ((char *) NULL, &icnt, &offset_expr, s, fmt,
+ macro_build (NULL, &icnt, &offset_expr, s, fmt,
coproc ? treg + 1 : treg,
- (int) BFD_RELOC_GPREL16, tempreg);
+ BFD_RELOC_GPREL16, tempreg);
offset_expr.X_add_number += 4;
/* Itbl support may require additional care here. */
- macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
+ macro_build (NULL, &icnt, &offset_expr, s, fmt,
coproc ? treg : treg + 1,
- (int) BFD_RELOC_GPREL16, tempreg);
+ BFD_RELOC_GPREL16, tempreg);
}
else
abort ();
s = "sw";
sd_ob:
assert (HAVE_32BIT_ADDRESSES);
- macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg,
- (int) BFD_RELOC_LO16, breg);
+ macro_build (NULL, &icnt, &offset_expr, s, "t,o(b)", treg,
+ BFD_RELOC_LO16, breg);
offset_expr.X_add_number += 4;
- macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg + 1,
- (int) BFD_RELOC_LO16, breg);
+ macro_build (NULL, &icnt, &offset_expr, s, "t,o(b)", treg + 1,
+ BFD_RELOC_LO16, breg);
return;
/* New code added to support COPZ instructions.
copz:
/* For now we just do C (same as Cz). The parameter will be
stored in insn_opcode by mips_ip. */
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "C",
- ip->insn_opcode);
+ macro_build (NULL, &icnt, NULL, s, "C", ip->insn_opcode);
return;
case M_MOVE:
s = ip->insn_mo->name;
s2 = "cop3";
coproc = ITBL_DECODE_PNUM (immed_expr);;
- macro_build ((char *) NULL, &icnt, &immed_expr, s, "C");
+ macro_build (NULL, &icnt, &immed_expr, s, "C");
return;
}
macro2 (ip);
}
static void
-macro2 (ip)
- struct mips_cl_insn *ip;
+macro2 (struct mips_cl_insn *ip)
{
register int treg, sreg, dreg, breg;
int tempreg;
case M_DMUL:
dbl = 1;
case M_MUL:
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- dbl ? "dmultu" : "multu", "s,t", sreg, treg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "d",
- dreg);
+ macro_build (NULL, &icnt, NULL, dbl ? "dmultu" : "multu", "s,t",
+ sreg, treg);
+ macro_build (NULL, &icnt, NULL, "mflo", "d", dreg);
return;
case M_DMUL_I:
not trying to be that fancy. GCC should do this for us
anyway. */
load_register (&icnt, AT, &imm_expr, dbl);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- dbl ? "dmult" : "mult", "s,t", sreg, AT);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "d",
- dreg);
+ macro_build (NULL, &icnt, NULL, dbl ? "dmult" : "mult", "s,t",
+ sreg, AT);
+ macro_build (NULL, &icnt, NULL, "mflo", "d", dreg);
break;
case M_DMULO_I:
mips_any_noreorder = 1;
if (imm)
load_register (&icnt, AT, &imm_expr, dbl);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- dbl ? "dmult" : "mult", "s,t", sreg, imm ? AT : treg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "d",
- dreg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- dbl ? "dsra32" : "sra", "d,w,<", dreg, dreg, RA);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mfhi", "d",
- AT);
+ 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);
if (mips_trap)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "tne",
- "s,t,q", dreg, AT, 6);
+ macro_build (NULL, &icnt, NULL, "tne", "s,t,q", dreg, AT, 6);
else
{
expr1.X_add_number = 8;
- macro_build ((char *) NULL, &icnt, &expr1, "beq", "s,t,p", dreg,
- AT);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "",
- 0);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
- "c", 6);
+ 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);
}
--mips_opts.noreorder;
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "d", dreg);
+ macro_build (NULL, &icnt, NULL, "mflo", "d", dreg);
break;
case M_DMULOU_I:
mips_any_noreorder = 1;
if (imm)
load_register (&icnt, AT, &imm_expr, dbl);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- dbl ? "dmultu" : "multu",
- "s,t", sreg, imm ? AT : treg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mfhi", "d",
- AT);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "d",
- dreg);
+ macro_build (NULL, &icnt, 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);
if (mips_trap)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "tne",
- "s,t,q", AT, 0, 6);
+ macro_build (NULL, &icnt, NULL, "tne", "s,t,q", AT, 0, 6);
else
{
expr1.X_add_number = 8;
- macro_build ((char *) NULL, &icnt, &expr1, "beq", "s,t,p", AT, 0);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "",
- 0);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
- "c", 6);
+ 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);
}
--mips_opts.noreorder;
break;
case M_DROL:
- if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_arch))
+ if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_opts.arch))
{
if (dreg == sreg)
{
tempreg = dreg;
used_at = 0;
}
- macro_build ((char *) NULL, &icnt, NULL, "dnegu",
- "d,w", tempreg, treg);
- macro_build ((char *) NULL, &icnt, NULL, "drorv",
- "d,t,s", dreg, sreg, tempreg);
+ macro_build (NULL, &icnt, NULL, "dnegu", "d,w", tempreg, treg);
+ macro_build (NULL, &icnt, NULL, "drorv", "d,t,s", dreg, sreg,
+ tempreg);
if (used_at)
break;
return;
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "dsubu",
- "d,v,t", AT, 0, treg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "dsrlv",
- "d,t,s", AT, sreg, AT);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "dsllv",
- "d,t,s", dreg, sreg, treg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or",
- "d,v,t", dreg, dreg, AT);
+ 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);
break;
case M_ROL:
- if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_arch))
+ if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_opts.arch))
{
if (dreg == sreg)
{
tempreg = dreg;
used_at = 0;
}
- macro_build ((char *) NULL, &icnt, NULL, "negu",
- "d,w", tempreg, treg);
- macro_build ((char *) NULL, &icnt, NULL, "rorv",
- "d,t,s", dreg, sreg, tempreg);
+ macro_build (NULL, &icnt, NULL, "negu", "d,w", tempreg, treg);
+ macro_build (NULL, &icnt, NULL, "rorv", "d,t,s", dreg, sreg,
+ tempreg);
if (used_at)
break;
return;
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "subu",
- "d,v,t", AT, 0, treg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srlv",
- "d,t,s", AT, sreg, AT);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sllv",
- "d,t,s", dreg, sreg, treg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or",
- "d,v,t", dreg, dreg, AT);
+ 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);
break;
case M_DROL_I:
if (imm_expr.X_op != O_constant)
as_bad (_("Improper rotate count"));
rot = imm_expr.X_add_number & 0x3f;
- if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_arch))
+ if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_opts.arch))
{
rot = (64 - rot) & 0x3f;
if (rot >= 32)
- macro_build ((char *) NULL, &icnt, NULL, "dror32",
- "d,w,<", dreg, sreg, rot - 32);
+ macro_build (NULL, &icnt, NULL, "dror32", "d,w,<",
+ dreg, sreg, rot - 32);
else
- macro_build ((char *) NULL, &icnt, NULL, "dror",
- "d,w,<", dreg, sreg, rot);
+ macro_build (NULL, &icnt, NULL, "dror", "d,w,<",
+ dreg, sreg, rot);
return;
}
if (rot == 0)
{
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "dsrl",
- "d,w,<", dreg, sreg, 0);
+ macro_build (NULL, &icnt, NULL, "dsrl", "d,w,<", dreg, sreg, 0);
return;
}
l = (rot < 0x20) ? "dsll" : "dsll32";
r = ((0x40 - rot) < 0x20) ? "dsrl" : "dsrl32";
rot &= 0x1f;
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, l,
- "d,w,<", AT, sreg, rot);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, r,
- "d,w,<", dreg, sreg, (0x20 - rot) & 0x1f);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or",
- "d,v,t", dreg, dreg, AT);
+ 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);
}
break;
if (imm_expr.X_op != O_constant)
as_bad (_("Improper rotate count"));
rot = imm_expr.X_add_number & 0x1f;
- if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_arch))
+ if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_opts.arch))
{
- macro_build ((char *) NULL, &icnt, NULL, "ror",
- "d,w,<", dreg, sreg, (32 - rot) & 0x1f);
+ macro_build (NULL, &icnt, NULL, "ror", "d,w,<", dreg, sreg,
+ (32 - rot) & 0x1f);
return;
}
if (rot == 0)
{
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srl",
- "d,w,<", dreg, sreg, 0);
+ macro_build (NULL, &icnt, NULL, "srl", "d,w,<", dreg, sreg, 0);
return;
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sll",
- "d,w,<", AT, sreg, rot);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srl",
- "d,w,<", dreg, sreg, (0x20 - rot) & 0x1f);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or",
- "d,v,t", dreg, dreg, AT);
+ 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);
}
break;
case M_DROR:
- if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_arch))
+ if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_opts.arch))
{
- macro_build ((char *) NULL, &icnt, NULL, "drorv",
- "d,t,s", dreg, sreg, treg);
+ macro_build (NULL, &icnt, NULL, "drorv", "d,t,s", dreg, sreg, treg);
return;
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "dsubu",
- "d,v,t", AT, 0, treg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "dsllv",
- "d,t,s", AT, sreg, AT);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "dsrlv",
- "d,t,s", dreg, sreg, treg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or",
- "d,v,t", dreg, dreg, AT);
+ 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);
break;
case M_ROR:
- if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_arch))
+ if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_opts.arch))
{
- macro_build ((char *) NULL, &icnt, NULL, "rorv",
- "d,t,s", dreg, sreg, treg);
+ macro_build (NULL, &icnt, NULL, "rorv", "d,t,s", dreg, sreg, treg);
return;
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "subu",
- "d,v,t", AT, 0, treg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sllv",
- "d,t,s", AT, sreg, AT);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srlv",
- "d,t,s", dreg, sreg, treg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or",
- "d,v,t", dreg, dreg, AT);
+ 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);
break;
case M_DROR_I:
if (imm_expr.X_op != O_constant)
as_bad (_("Improper rotate count"));
rot = imm_expr.X_add_number & 0x3f;
- if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_arch))
+ if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_opts.arch))
{
if (rot >= 32)
- macro_build ((char *) NULL, &icnt, NULL, "dror32",
- "d,w,<", dreg, sreg, rot - 32);
+ macro_build (NULL, &icnt, NULL, "dror32", "d,w,<",
+ dreg, sreg, rot - 32);
else
- macro_build ((char *) NULL, &icnt, NULL, "dror",
- "d,w,<", dreg, sreg, rot);
+ macro_build (NULL, &icnt, NULL, "dror", "d,w,<",
+ dreg, sreg, rot);
return;
}
if (rot == 0)
{
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "dsrl",
- "d,w,<", dreg, sreg, 0);
+ macro_build (NULL, &icnt, NULL, "dsrl", "d,w,<", dreg, sreg, 0);
return;
}
r = (rot < 0x20) ? "dsrl" : "dsrl32";
l = ((0x40 - rot) < 0x20) ? "dsll" : "dsll32";
rot &= 0x1f;
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, r,
- "d,w,<", AT, sreg, rot);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, l,
- "d,w,<", dreg, sreg, (0x20 - rot) & 0x1f);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or",
- "d,v,t", dreg, dreg, AT);
+ 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);
}
break;
if (imm_expr.X_op != O_constant)
as_bad (_("Improper rotate count"));
rot = imm_expr.X_add_number & 0x1f;
- if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_arch))
+ if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_opts.arch))
{
- macro_build ((char *) NULL, &icnt, NULL, "ror",
- "d,w,<", dreg, sreg, rot);
+ macro_build (NULL, &icnt, NULL, "ror", "d,w,<", dreg, sreg, rot);
return;
}
if (rot == 0)
{
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srl",
- "d,w,<", dreg, sreg, 0);
+ macro_build (NULL, &icnt, NULL, "srl", "d,w,<", dreg, sreg, 0);
return;
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srl",
- "d,w,<", AT, sreg, rot);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sll",
- "d,w,<", dreg, sreg, (0x20 - rot) & 0x1f);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or",
- "d,v,t", dreg, dreg, AT);
+ 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);
}
break;
case M_S_DOB:
- if (mips_arch == CPU_R4650)
+ if (mips_opts.arch == CPU_R4650)
{
as_bad (_("opcode not supported on this processor"));
return;
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 ((char *) NULL, &icnt, &offset_expr, "swc1", "T,o(b)",
+ macro_build (NULL, &icnt, &offset_expr, "swc1", "T,o(b)",
target_big_endian ? treg + 1 : treg,
- (int) BFD_RELOC_LO16, breg);
+ BFD_RELOC_LO16, breg);
offset_expr.X_add_number += 4;
- macro_build ((char *) NULL, &icnt, &offset_expr, "swc1", "T,o(b)",
+ macro_build (NULL, &icnt, &offset_expr, "swc1", "T,o(b)",
target_big_endian ? treg : treg + 1,
- (int) BFD_RELOC_LO16, breg);
+ BFD_RELOC_LO16, breg);
return;
case M_SEQ:
if (sreg == 0)
- macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg,
- treg, (int) BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg, treg,
+ BFD_RELOC_LO16);
else if (treg == 0)
- macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg,
- sreg, (int) BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg, sreg,
+ BFD_RELOC_LO16);
else
{
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "xor",
- "d,v,t", dreg, sreg, treg);
- macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg,
- dreg, (int) BFD_RELOC_LO16);
+ 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);
}
return;
case M_SEQ_I:
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
{
- macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg,
- sreg, (int) BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg, sreg,
+ BFD_RELOC_LO16);
return;
}
if (sreg == 0)
&& imm_expr.X_add_number >= 0
&& imm_expr.X_add_number < 0x10000)
{
- macro_build ((char *) NULL, &icnt, &imm_expr, "xori", "t,r,i", dreg,
- sreg, (int) BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, &imm_expr, "xori", "t,r,i", dreg, sreg,
+ BFD_RELOC_LO16);
used_at = 0;
}
else if (imm_expr.X_op == O_constant
&& imm_expr.X_add_number < 0)
{
imm_expr.X_add_number = -imm_expr.X_add_number;
- macro_build ((char *) NULL, &icnt, &imm_expr,
+ macro_build (NULL, &icnt, &imm_expr,
HAVE_32BIT_GPRS ? "addiu" : "daddiu",
- "t,r,j", dreg, sreg,
- (int) BFD_RELOC_LO16);
+ "t,r,j", dreg, sreg, BFD_RELOC_LO16);
used_at = 0;
}
else
{
load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "xor",
- "d,v,t", dreg, sreg, AT);
+ macro_build (NULL, &icnt, NULL, "xor", "d,v,t", dreg, sreg, AT);
used_at = 1;
}
- macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg, dreg,
- (int) BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg, dreg,
+ BFD_RELOC_LO16);
if (used_at)
break;
return;
case M_SGEU:
s = "sltu";
sge:
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d,v,t",
- dreg, sreg, treg);
- macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,
- (int) BFD_RELOC_LO16);
+ 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);
return;
case M_SGE_I: /* sreg >= I <==> not (sreg < I) */
&& imm_expr.X_add_number >= -0x8000
&& imm_expr.X_add_number < 0x8000)
{
- macro_build ((char *) NULL, &icnt, &imm_expr,
+ macro_build (NULL, &icnt, &imm_expr,
mask == M_SGE_I ? "slti" : "sltiu",
- "t,r,j", dreg, sreg, (int) BFD_RELOC_LO16);
+ "t,r,j", dreg, sreg, BFD_RELOC_LO16);
used_at = 0;
}
else
{
load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- mask == M_SGE_I ? "slt" : "sltu", "d,v,t", dreg, sreg,
- AT);
+ macro_build (NULL, &icnt, NULL, mask == M_SGE_I ? "slt" : "sltu",
+ "d,v,t", dreg, sreg, AT);
used_at = 1;
}
- macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,
- (int) BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,
+ BFD_RELOC_LO16);
if (used_at)
break;
return;
case M_SGTU:
s = "sltu";
sgt:
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d,v,t",
- dreg, treg, sreg);
+ macro_build (NULL, &icnt, NULL, s, "d,v,t", dreg, treg, sreg);
return;
case M_SGT_I: /* sreg > I <==> I < sreg */
s = "sltu";
sgti:
load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d,v,t",
- dreg, AT, sreg);
+ macro_build (NULL, &icnt, NULL, s, "d,v,t", dreg, AT, sreg);
break;
case M_SLE: /* sreg <= treg <==> treg >= sreg <==> not (treg < sreg) */
case M_SLEU:
s = "sltu";
sle:
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d,v,t",
- dreg, treg, sreg);
- macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,
- (int) BFD_RELOC_LO16);
+ 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);
return;
case M_SLE_I: /* sreg <= I <==> I >= sreg <==> not (I < sreg) */
s = "sltu";
slei:
load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d,v,t",
- dreg, AT, sreg);
- macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,
- (int) BFD_RELOC_LO16);
+ 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);
break;
case M_SLT_I:
&& imm_expr.X_add_number >= -0x8000
&& imm_expr.X_add_number < 0x8000)
{
- macro_build ((char *) NULL, &icnt, &imm_expr, "slti", "t,r,j",
- dreg, sreg, (int) BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, &imm_expr, "slti", "t,r,j", dreg, sreg,
+ BFD_RELOC_LO16);
return;
}
load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "slt", "d,v,t",
- dreg, sreg, AT);
+ macro_build (NULL, &icnt, NULL, "slt", "d,v,t", dreg, sreg, AT);
break;
case M_SLTU_I:
&& imm_expr.X_add_number >= -0x8000
&& imm_expr.X_add_number < 0x8000)
{
- macro_build ((char *) NULL, &icnt, &imm_expr, "sltiu", "t,r,j",
- dreg, sreg, (int) BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, &imm_expr, "sltiu", "t,r,j", dreg, sreg,
+ BFD_RELOC_LO16);
return;
}
load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
- "d,v,t", dreg, sreg, AT);
+ macro_build (NULL, &icnt, NULL, "sltu", "d,v,t", dreg, sreg, AT);
break;
case M_SNE:
if (sreg == 0)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
- "d,v,t", dreg, 0, treg);
+ macro_build (NULL, &icnt,NULL, "sltu","d,v,t", dreg, 0, treg);
else if (treg == 0)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
- "d,v,t", dreg, 0, sreg);
+ macro_build (NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0, sreg);
else
{
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "xor",
- "d,v,t", dreg, sreg, treg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
- "d,v,t", dreg, 0, dreg);
+ macro_build (NULL, &icnt, NULL, "xor", "d,v,t", dreg, sreg, treg);
+ macro_build (NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0, dreg);
}
return;
case M_SNE_I:
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
{
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
- "d,v,t", dreg, 0, sreg);
+ macro_build (NULL, &icnt, 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 ((char *) NULL, &icnt, &expr1,
+ macro_build (NULL, &icnt, &expr1,
HAVE_32BIT_GPRS ? "addiu" : "daddiu",
- "t,r,j", dreg, 0, (int) BFD_RELOC_LO16);
+ "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 ((char *) NULL, &icnt, &imm_expr, "xori", "t,r,i",
- dreg, sreg, (int) BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, &imm_expr, "xori", "t,r,i", dreg, sreg,
+ BFD_RELOC_LO16);
used_at = 0;
}
else if (imm_expr.X_op == O_constant
&& imm_expr.X_add_number < 0)
{
imm_expr.X_add_number = -imm_expr.X_add_number;
- macro_build ((char *) NULL, &icnt, &imm_expr,
+ macro_build (NULL, &icnt, &imm_expr,
HAVE_32BIT_GPRS ? "addiu" : "daddiu",
- "t,r,j", dreg, sreg, (int) BFD_RELOC_LO16);
+ "t,r,j", dreg, sreg, BFD_RELOC_LO16);
used_at = 0;
}
else
{
load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "xor",
- "d,v,t", dreg, sreg, AT);
+ macro_build (NULL, &icnt, NULL, "xor", "d,v,t", dreg, sreg, AT);
used_at = 1;
}
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu",
- "d,v,t", dreg, 0, dreg);
+ macro_build (NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0, dreg);
if (used_at)
break;
return;
&& imm_expr.X_add_number <= 0x8000)
{
imm_expr.X_add_number = -imm_expr.X_add_number;
- macro_build ((char *) NULL, &icnt, &imm_expr,
- dbl ? "daddi" : "addi",
- "t,r,j", dreg, sreg, (int) BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, &imm_expr, dbl ? "daddi" : "addi",
+ "t,r,j", dreg, sreg, BFD_RELOC_LO16);
return;
}
load_register (&icnt, AT, &imm_expr, dbl);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- dbl ? "dsub" : "sub", "d,v,t", dreg, sreg, AT);
+ macro_build (NULL, &icnt, NULL, dbl ? "dsub" : "sub", "d,v,t",
+ dreg, sreg, AT);
break;
case M_DSUBU_I:
&& imm_expr.X_add_number <= 0x8000)
{
imm_expr.X_add_number = -imm_expr.X_add_number;
- macro_build ((char *) NULL, &icnt, &imm_expr,
- dbl ? "daddiu" : "addiu",
- "t,r,j", dreg, sreg, (int) BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, &imm_expr, dbl ? "daddiu" : "addiu",
+ "t,r,j", dreg, sreg, BFD_RELOC_LO16);
return;
}
load_register (&icnt, AT, &imm_expr, dbl);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- dbl ? "dsubu" : "subu", "d,v,t", dreg, sreg, AT);
+ macro_build (NULL, &icnt, NULL, dbl ? "dsubu" : "subu", "d,v,t",
+ dreg, sreg, AT);
break;
case M_TEQ_I:
s = "tne";
trap:
load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "s,t", sreg,
- AT);
+ macro_build (NULL, &icnt, NULL, s, "s,t", sreg, AT);
break;
case M_TRUNCWS:
mips_emit_delays (TRUE);
++mips_opts.noreorder;
mips_any_noreorder = 1;
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "cfc1", "t,G",
- treg, RA);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "cfc1", "t,G",
- treg, RA);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
+ 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", "");
expr1.X_add_number = 3;
- macro_build ((char *) NULL, &icnt, &expr1, "ori", "t,r,i", AT, treg,
- (int) BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, &expr1, "ori", "t,r,i", AT, treg,
+ BFD_RELOC_LO16);
expr1.X_add_number = 2;
- macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", AT, AT,
- (int) BFD_RELOC_LO16);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "ctc1", "t,G",
- AT, RA);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- mask == M_TRUNCWD ? "cvt.w.d" : "cvt.w.s", "D,S", dreg, sreg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "ctc1", "t,G",
- treg, RA);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
+ 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", "");
--mips_opts.noreorder;
break;
ulh:
if (offset_expr.X_add_number >= 0x7fff)
as_bad (_("operand overflow"));
- /* avoid load delay */
if (! target_big_endian)
++offset_expr.X_add_number;
- macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg,
- (int) BFD_RELOC_LO16, breg);
+ macro_build (NULL, &icnt, &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 ((char *) NULL, &icnt, &offset_expr, "lbu", "t,o(b)", AT,
- (int) BFD_RELOC_LO16, breg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sll", "d,w,<",
- treg, treg, 8);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or", "d,v,t",
- treg, treg, AT);
+ 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);
break;
case M_ULD:
ulw:
if (offset_expr.X_add_number >= 0x8000 - off)
as_bad (_("operand overflow"));
+ if (treg != breg)
+ tempreg = treg;
+ else
+ tempreg = AT;
if (! target_big_endian)
offset_expr.X_add_number += off;
- macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg,
- (int) BFD_RELOC_LO16, breg);
+ macro_build (NULL, &icnt, &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 ((char *) NULL, &icnt, &offset_expr, s2, "t,o(b)", treg,
- (int) BFD_RELOC_LO16, breg);
- return;
+ macro_build (NULL, &icnt, &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);
+ break;
case M_ULD_A:
s = "ldl";
used_at = 1;
load_address (&icnt, AT, &offset_expr, &used_at);
if (breg != 0)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", AT, AT, breg);
+ macro_build (NULL, &icnt, 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 ((char *) NULL, &icnt, &expr1, s, "t,o(b)", treg,
- (int) BFD_RELOC_LO16, AT);
+ macro_build (NULL, &icnt, &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 ((char *) NULL, &icnt, &expr1, s2, "t,o(b)", treg,
- (int) BFD_RELOC_LO16, AT);
+ macro_build (NULL, &icnt, &expr1, s2, "t,o(b)", treg,
+ BFD_RELOC_LO16, AT);
break;
case M_ULH_A:
used_at = 1;
load_address (&icnt, AT, &offset_expr, &used_at);
if (breg != 0)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", AT, AT, breg);
+ macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ AT, AT, breg);
if (target_big_endian)
expr1.X_add_number = 0;
- macro_build ((char *) NULL, &icnt, &expr1,
- mask == M_ULH_A ? "lb" : "lbu", "t,o(b)", treg,
- (int) BFD_RELOC_LO16, AT);
+ macro_build (NULL, &icnt, &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 ((char *) NULL, &icnt, &expr1, "lbu", "t,o(b)", AT,
- (int) BFD_RELOC_LO16, AT);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sll", "d,w,<",
- treg, treg, 8);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or", "d,v,t",
- treg, treg, AT);
+ 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);
break;
case M_USH:
as_bad (_("operand overflow"));
if (target_big_endian)
++offset_expr.X_add_number;
- macro_build ((char *) NULL, &icnt, &offset_expr, "sb", "t,o(b)", treg,
- (int) BFD_RELOC_LO16, breg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srl", "d,w,<",
- AT, treg, 8);
+ 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);
if (target_big_endian)
--offset_expr.X_add_number;
else
++offset_expr.X_add_number;
- macro_build ((char *) NULL, &icnt, &offset_expr, "sb", "t,o(b)", AT,
- (int) BFD_RELOC_LO16, breg);
+ macro_build (NULL, &icnt, &offset_expr, "sb", "t,o(b)", AT,
+ BFD_RELOC_LO16, breg);
break;
case M_USD:
as_bad (_("operand overflow"));
if (! target_big_endian)
offset_expr.X_add_number += off;
- macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg,
- (int) BFD_RELOC_LO16, breg);
+ macro_build (NULL, &icnt, &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 ((char *) NULL, &icnt, &offset_expr, s2, "t,o(b)", treg,
- (int) BFD_RELOC_LO16, breg);
+ macro_build (NULL, &icnt, &offset_expr, s2, "t,o(b)", treg,
+ BFD_RELOC_LO16, breg);
return;
case M_USD_A:
used_at = 1;
load_address (&icnt, AT, &offset_expr, &used_at);
if (breg != 0)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", AT, AT, breg);
+ macro_build (NULL, &icnt, 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 ((char *) NULL, &icnt, &expr1, s, "t,o(b)", treg,
- (int) BFD_RELOC_LO16, AT);
+ macro_build (NULL, &icnt, &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 ((char *) NULL, &icnt, &expr1, s2, "t,o(b)", treg,
- (int) BFD_RELOC_LO16, AT);
+ macro_build (NULL, &icnt, &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);
if (breg != 0)
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", AT, AT, breg);
+ macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ AT, AT, breg);
if (! target_big_endian)
expr1.X_add_number = 0;
- macro_build ((char *) NULL, &icnt, &expr1, "sb", "t,o(b)", treg,
- (int) BFD_RELOC_LO16, AT);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srl", "d,w,<",
- treg, treg, 8);
+ 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);
if (! target_big_endian)
expr1.X_add_number = 1;
else
expr1.X_add_number = 0;
- macro_build ((char *) NULL, &icnt, &expr1, "sb", "t,o(b)", treg,
- (int) BFD_RELOC_LO16, AT);
+ macro_build (NULL, &icnt, &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 ((char *) NULL, &icnt, &expr1, "lbu", "t,o(b)", AT,
- (int) BFD_RELOC_LO16, AT);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sll", "d,w,<",
- treg, treg, 8);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or", "d,v,t",
- treg, treg, AT);
+ 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);
break;
default:
/* Implement macros in mips16 mode. */
static void
-mips16_macro (ip)
- struct mips_cl_insn *ip;
+mips16_macro (struct mips_cl_insn *ip)
{
int mask;
int xreg, yreg, zreg, tmp;
mips_emit_delays (TRUE);
++mips_opts.noreorder;
mips_any_noreorder = 1;
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- dbl ? "ddiv" : "div",
- "0,x,y", xreg, yreg);
+ macro_build (NULL, &icnt, NULL, dbl ? "ddiv" : "div", "0,x,y",
+ xreg, yreg);
expr1.X_add_number = 2;
- macro_build ((char *) NULL, &icnt, &expr1, "bnez", "x,p", yreg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break", "6",
- 7);
+ macro_build (NULL, &icnt, &expr1, "bnez", "x,p", yreg);
+ macro_build (NULL, &icnt, NULL, "break", "6", 7);
/* FIXME: The normal code checks for of -1 / -0x80000000 here,
since that causes an overflow. We should do that as well,
but I don't see how to do the comparisons without a temporary
register. */
--mips_opts.noreorder;
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "x", zreg);
+ macro_build (NULL, &icnt, NULL, s, "x", zreg);
break;
case M_DIVU_3:
mips_emit_delays (TRUE);
++mips_opts.noreorder;
mips_any_noreorder = 1;
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "0,x,y",
- xreg, yreg);
+ macro_build (NULL, &icnt, NULL, s, "0,x,y", xreg, yreg);
expr1.X_add_number = 2;
- macro_build ((char *) NULL, &icnt, &expr1, "bnez", "x,p", yreg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
- "6", 7);
+ macro_build (NULL, &icnt, &expr1, "bnez", "x,p", yreg);
+ macro_build (NULL, &icnt, NULL, "break", "6", 7);
--mips_opts.noreorder;
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s2, "x", zreg);
+ macro_build (NULL, &icnt, NULL, s2, "x", zreg);
break;
case M_DMUL:
dbl = 1;
case M_MUL:
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- dbl ? "dmultu" : "multu", "x,y", xreg, yreg);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "x",
- zreg);
+ macro_build (NULL, &icnt, NULL, dbl ? "dmultu" : "multu", "x,y",
+ xreg, yreg);
+ macro_build (NULL, &icnt, NULL, "mflo", "x", zreg);
return;
case M_DSUBU_I:
if (imm_expr.X_op != O_constant)
as_bad (_("Unsupported large constant"));
imm_expr.X_add_number = -imm_expr.X_add_number;
- macro_build ((char *) NULL, &icnt, &imm_expr,
- dbl ? "daddiu" : "addiu", "y,x,4", yreg, xreg);
+ macro_build (NULL, &icnt, &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 ((char *) NULL, &icnt, &imm_expr, "addiu",
- "x,k", xreg);
+ macro_build (NULL, &icnt, &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 ((char *) NULL, &icnt, &imm_expr, "daddiu",
- "y,j", yreg);
+ macro_build (NULL, &icnt, &imm_expr, "daddiu", "y,j", yreg);
break;
case M_BEQ:
yreg = tmp;
do_branch:
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "x,y",
- xreg, yreg);
- macro_build ((char *) NULL, &icnt, &offset_expr, s2, "p");
+ macro_build (NULL, &icnt, NULL, s, "x,y", xreg, yreg);
+ macro_build (NULL, &icnt, &offset_expr, s2, "p");
break;
case M_BEQ_I:
++imm_expr.X_add_number;
do_branch_i:
- macro_build ((char *) NULL, &icnt, &imm_expr, s, s3, xreg);
- macro_build ((char *) NULL, &icnt, &offset_expr, s2, "p");
+ macro_build (NULL, &icnt, &imm_expr, s, s3, xreg);
+ macro_build (NULL, &icnt, &offset_expr, s2, "p");
break;
case M_ABS:
expr1.X_add_number = 0;
- macro_build ((char *) NULL, &icnt, &expr1, "slti", "x,8", yreg);
+ macro_build (NULL, &icnt, &expr1, "slti", "x,8", yreg);
if (xreg != yreg)
move_register (&icnt, xreg, yreg);
expr1.X_add_number = 2;
- macro_build ((char *) NULL, &icnt, &expr1, "bteqz", "p");
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- "neg", "x,w", xreg, xreg);
+ macro_build (NULL, &icnt, &expr1, "bteqz", "p");
+ macro_build (NULL, &icnt, NULL, "neg", "x,w", xreg, xreg);
}
}
by the match/mask part of the instruction definition, or by the
operand list. */
static int
-validate_mips_insn (opc)
- const struct mips_opcode *opc;
+validate_mips_insn (const struct mips_opcode *opc)
{
const char *p = opc->args;
char c;
is an address expression. */
static void
-mips_ip (str, ip)
- char *str;
- struct mips_cl_insn *ip;
+mips_ip (char *str, struct mips_cl_insn *ip)
{
char *s;
const char *args;
| (file_ase_mips16 ? INSN_MIPS16 : 0)
| (mips_opts.ase_mdmx ? INSN_MDMX : 0)
| (mips_opts.ase_mips3d ? INSN_MIPS3D : 0)),
- mips_arch))
+ mips_opts.arch))
ok = TRUE;
else
ok = FALSE;
if (insn->pinfo != INSN_MACRO)
{
- if (mips_arch == CPU_R4650 && (insn->pinfo & FP_D) != 0)
+ if (mips_opts.arch == CPU_R4650 && (insn->pinfo & FP_D) != 0)
ok = FALSE;
}
if (!insn_error)
{
static char buf[100];
- if (mips_arch_info->is_isa)
- sprintf (buf,
- _("opcode not supported at this ISA level (%s)"),
- mips_cpu_info_from_isa (mips_opts.isa)->name);
- else
- sprintf (buf,
- _("opcode not supported on this processor: %s (%s)"),
- mips_arch_info->name,
- mips_cpu_info_from_isa (mips_opts.isa)->name);
+ sprintf (buf,
+ _("opcode not supported on this processor: %s (%s)"),
+ mips_cpu_info_from_arch (mips_opts.arch)->name,
+ mips_cpu_info_from_isa (mips_opts.isa)->name);
insn_error = buf;
}
if (save_c)
requested a small or extended instruction. */
static void
-mips16_ip (str, ip)
- char *str;
- struct mips_cl_insn *ip;
+mips16_ip (char *str, struct mips_cl_insn *ip)
{
char *s;
const char *args;
WARN is true, warn if EXT does not match reality. */
static void
-mips16_immed (file, line, type, val, warn, small, ext, insn, use_extend,
- extend)
- char *file;
- unsigned int line;
- int type;
- offsetT val;
- bfd_boolean warn;
- bfd_boolean small;
- bfd_boolean ext;
- unsigned long *insn;
- bfd_boolean *use_extend;
- unsigned short *extend;
+mips16_immed (char *file, unsigned int line, int type, offsetT val,
+ bfd_boolean warn, bfd_boolean small, bfd_boolean ext,
+ unsigned long *insn, bfd_boolean *use_extend,
+ unsigned short *extend)
{
register const struct mips16_immed_operand *op;
int mintiny, maxtiny;
Leave both *STR and *RELOC alone when returning false. */
static bfd_boolean
-parse_relocation (str, reloc)
- char **str;
- bfd_reloc_code_real_type *reloc;
+parse_relocation (char **str, bfd_reloc_code_real_type *reloc)
{
size_t i;
If no relocation operators are used, RELOC[0] is set to BFD_RELOC_LO16. */
static size_t
-my_getSmallExpression (ep, reloc, str)
- expressionS *ep;
- bfd_reloc_code_real_type *reloc;
- char *str;
+my_getSmallExpression (expressionS *ep, bfd_reloc_code_real_type *reloc,
+ char *str)
{
bfd_reloc_code_real_type reversed_reloc[3];
size_t reloc_index, i;
expr_end = str;
- reloc[0] = BFD_RELOC_LO16;
- for (i = 0; i < reloc_index; i++)
- reloc[i] = reversed_reloc[reloc_index - 1 - i];
+ if (reloc_index == 0)
+ reloc[0] = BFD_RELOC_LO16;
+ else
+ {
+ prev_reloc_op_frag = frag_now;
+ for (i = 0; i < reloc_index; i++)
+ reloc[i] = reversed_reloc[reloc_index - 1 - i];
+ }
return reloc_index;
}
static void
-my_getExpression (ep, str)
- expressionS *ep;
- char *str;
+my_getExpression (expressionS *ep, char *str)
{
char *save_in;
valueT val;
returned, or NULL on OK. */
char *
-md_atof (type, litP, sizeP)
- int type;
- char *litP;
- int *sizeP;
+md_atof (int type, char *litP, int *sizeP)
{
int prec;
LITTLENUM_TYPE words[4];
{
for (i = prec - 1; i >= 0; i--)
{
- md_number_to_chars (litP, (valueT) words[i], 2);
+ md_number_to_chars (litP, words[i], 2);
litP += 2;
}
}
{
for (i = 0; i < prec; i++)
{
- md_number_to_chars (litP, (valueT) words[i], 2);
+ md_number_to_chars (litP, words[i], 2);
litP += 2;
}
}
}
void
-md_number_to_chars (buf, val, n)
- char *buf;
- valueT val;
- int n;
+md_number_to_chars (char *buf, valueT val, int n)
{
if (target_big_endian)
number_to_chars_bigendian (buf, val, n);
struct option md_longopts[] =
{
-#define OPTION_MIPS1 (OPTION_MD_BASE + 1)
+ /* Options which specify architecture. */
+#define OPTION_ARCH_BASE (OPTION_MD_BASE)
+#define OPTION_MARCH (OPTION_ARCH_BASE + 0)
+ {"march", required_argument, NULL, OPTION_MARCH},
+#define OPTION_MTUNE (OPTION_ARCH_BASE + 1)
+ {"mtune", required_argument, NULL, OPTION_MTUNE},
+#define OPTION_MIPS1 (OPTION_ARCH_BASE + 2)
{"mips0", no_argument, NULL, OPTION_MIPS1},
{"mips1", no_argument, NULL, OPTION_MIPS1},
-#define OPTION_MIPS2 (OPTION_MD_BASE + 2)
+#define OPTION_MIPS2 (OPTION_ARCH_BASE + 3)
{"mips2", no_argument, NULL, OPTION_MIPS2},
-#define OPTION_MIPS3 (OPTION_MD_BASE + 3)
+#define OPTION_MIPS3 (OPTION_ARCH_BASE + 4)
{"mips3", no_argument, NULL, OPTION_MIPS3},
-#define OPTION_MIPS4 (OPTION_MD_BASE + 4)
+#define OPTION_MIPS4 (OPTION_ARCH_BASE + 5)
{"mips4", no_argument, NULL, OPTION_MIPS4},
-#define OPTION_MIPS5 (OPTION_MD_BASE + 5)
+#define OPTION_MIPS5 (OPTION_ARCH_BASE + 6)
{"mips5", no_argument, NULL, OPTION_MIPS5},
-#define OPTION_MIPS32 (OPTION_MD_BASE + 6)
+#define OPTION_MIPS32 (OPTION_ARCH_BASE + 7)
{"mips32", no_argument, NULL, OPTION_MIPS32},
-#define OPTION_MIPS64 (OPTION_MD_BASE + 7)
+#define OPTION_MIPS64 (OPTION_ARCH_BASE + 8)
{"mips64", no_argument, NULL, OPTION_MIPS64},
-#define OPTION_MEMBEDDED_PIC (OPTION_MD_BASE + 8)
+#define OPTION_MIPS32R2 (OPTION_ARCH_BASE + 9)
+ {"mips32r2", no_argument, NULL, OPTION_MIPS32R2},
+
+ /* Options which specify Application Specific Extensions (ASEs). */
+#define OPTION_ASE_BASE (OPTION_ARCH_BASE + 10)
+#define OPTION_MIPS16 (OPTION_ASE_BASE + 0)
+ {"mips16", no_argument, NULL, OPTION_MIPS16},
+#define OPTION_NO_MIPS16 (OPTION_ASE_BASE + 1)
+ {"no-mips16", no_argument, NULL, OPTION_NO_MIPS16},
+#define OPTION_MIPS3D (OPTION_ASE_BASE + 2)
+ {"mips3d", no_argument, NULL, OPTION_MIPS3D},
+#define OPTION_NO_MIPS3D (OPTION_ASE_BASE + 3)
+ {"no-mips3d", no_argument, NULL, OPTION_NO_MIPS3D},
+#define OPTION_MDMX (OPTION_ASE_BASE + 4)
+ {"mdmx", no_argument, NULL, OPTION_MDMX},
+#define OPTION_NO_MDMX (OPTION_ASE_BASE + 5)
+ {"no-mdmx", no_argument, NULL, OPTION_NO_MDMX},
+
+ /* Old-style architecture options. Don't add more of these. */
+#define OPTION_COMPAT_ARCH_BASE (OPTION_ASE_BASE + 6)
+#define OPTION_M4650 (OPTION_COMPAT_ARCH_BASE + 0)
+ {"m4650", no_argument, NULL, OPTION_M4650},
+#define OPTION_NO_M4650 (OPTION_COMPAT_ARCH_BASE + 1)
+ {"no-m4650", no_argument, NULL, OPTION_NO_M4650},
+#define OPTION_M4010 (OPTION_COMPAT_ARCH_BASE + 2)
+ {"m4010", no_argument, NULL, OPTION_M4010},
+#define OPTION_NO_M4010 (OPTION_COMPAT_ARCH_BASE + 3)
+ {"no-m4010", no_argument, NULL, OPTION_NO_M4010},
+#define OPTION_M4100 (OPTION_COMPAT_ARCH_BASE + 4)
+ {"m4100", no_argument, NULL, OPTION_M4100},
+#define OPTION_NO_M4100 (OPTION_COMPAT_ARCH_BASE + 5)
+ {"no-m4100", no_argument, NULL, OPTION_NO_M4100},
+#define OPTION_M3900 (OPTION_COMPAT_ARCH_BASE + 6)
+ {"m3900", no_argument, NULL, OPTION_M3900},
+#define OPTION_NO_M3900 (OPTION_COMPAT_ARCH_BASE + 7)
+ {"no-m3900", no_argument, NULL, OPTION_NO_M3900},
+
+ /* Options which enable bug fixes. */
+#define OPTION_FIX_BASE (OPTION_COMPAT_ARCH_BASE + 8)
+#define OPTION_M7000_HILO_FIX (OPTION_FIX_BASE + 0)
+ {"mfix7000", no_argument, NULL, OPTION_M7000_HILO_FIX},
+#define OPTION_MNO_7000_HILO_FIX (OPTION_FIX_BASE + 1)
+ {"no-fix-7000", no_argument, NULL, OPTION_MNO_7000_HILO_FIX},
+ {"mno-fix7000", no_argument, NULL, OPTION_MNO_7000_HILO_FIX},
+#define OPTION_FIX_VR4122 (OPTION_FIX_BASE + 2)
+#define OPTION_NO_FIX_VR4122 (OPTION_FIX_BASE + 3)
+ {"mfix-vr4122-bugs", no_argument, NULL, OPTION_FIX_VR4122},
+ {"no-mfix-vr4122-bugs", no_argument, NULL, OPTION_NO_FIX_VR4122},
+
+ /* Miscellaneous options. */
+#define OPTION_MISC_BASE (OPTION_FIX_BASE + 4)
+#define OPTION_MEMBEDDED_PIC (OPTION_MISC_BASE + 0)
{"membedded-pic", no_argument, NULL, OPTION_MEMBEDDED_PIC},
-#define OPTION_TRAP (OPTION_MD_BASE + 9)
+#define OPTION_TRAP (OPTION_MISC_BASE + 1)
{"trap", no_argument, NULL, OPTION_TRAP},
{"no-break", no_argument, NULL, OPTION_TRAP},
-#define OPTION_BREAK (OPTION_MD_BASE + 10)
+#define OPTION_BREAK (OPTION_MISC_BASE + 2)
{"break", no_argument, NULL, OPTION_BREAK},
{"no-trap", no_argument, NULL, OPTION_BREAK},
-#define OPTION_EB (OPTION_MD_BASE + 11)
+#define OPTION_EB (OPTION_MISC_BASE + 3)
{"EB", no_argument, NULL, OPTION_EB},
-#define OPTION_EL (OPTION_MD_BASE + 12)
+#define OPTION_EL (OPTION_MISC_BASE + 4)
{"EL", no_argument, NULL, OPTION_EL},
-#define OPTION_MIPS16 (OPTION_MD_BASE + 13)
- {"mips16", no_argument, NULL, OPTION_MIPS16},
-#define OPTION_NO_MIPS16 (OPTION_MD_BASE + 14)
- {"no-mips16", no_argument, NULL, OPTION_NO_MIPS16},
-#define OPTION_M7000_HILO_FIX (OPTION_MD_BASE + 15)
- {"mfix7000", no_argument, NULL, OPTION_M7000_HILO_FIX},
-#define OPTION_MNO_7000_HILO_FIX (OPTION_MD_BASE + 16)
- {"no-fix-7000", no_argument, NULL, OPTION_MNO_7000_HILO_FIX},
- {"mno-fix7000", no_argument, NULL, OPTION_MNO_7000_HILO_FIX},
-#define OPTION_FP32 (OPTION_MD_BASE + 17)
+#define OPTION_FP32 (OPTION_MISC_BASE + 5)
{"mfp32", no_argument, NULL, OPTION_FP32},
-#define OPTION_GP32 (OPTION_MD_BASE + 18)
+#define OPTION_GP32 (OPTION_MISC_BASE + 6)
{"mgp32", no_argument, NULL, OPTION_GP32},
-#define OPTION_CONSTRUCT_FLOATS (OPTION_MD_BASE + 19)
+#define OPTION_CONSTRUCT_FLOATS (OPTION_MISC_BASE + 7)
{"construct-floats", no_argument, NULL, OPTION_CONSTRUCT_FLOATS},
-#define OPTION_NO_CONSTRUCT_FLOATS (OPTION_MD_BASE + 20)
+#define OPTION_NO_CONSTRUCT_FLOATS (OPTION_MISC_BASE + 8)
{"no-construct-floats", no_argument, NULL, OPTION_NO_CONSTRUCT_FLOATS},
-#define OPTION_MARCH (OPTION_MD_BASE + 21)
- {"march", required_argument, NULL, OPTION_MARCH},
-#define OPTION_MTUNE (OPTION_MD_BASE + 22)
- {"mtune", required_argument, NULL, OPTION_MTUNE},
-#define OPTION_FP64 (OPTION_MD_BASE + 23)
+#define OPTION_FP64 (OPTION_MISC_BASE + 9)
{"mfp64", no_argument, NULL, OPTION_FP64},
-#define OPTION_M4650 (OPTION_MD_BASE + 24)
- {"m4650", no_argument, NULL, OPTION_M4650},
-#define OPTION_NO_M4650 (OPTION_MD_BASE + 25)
- {"no-m4650", no_argument, NULL, OPTION_NO_M4650},
-#define OPTION_M4010 (OPTION_MD_BASE + 26)
- {"m4010", no_argument, NULL, OPTION_M4010},
-#define OPTION_NO_M4010 (OPTION_MD_BASE + 27)
- {"no-m4010", no_argument, NULL, OPTION_NO_M4010},
-#define OPTION_M4100 (OPTION_MD_BASE + 28)
- {"m4100", no_argument, NULL, OPTION_M4100},
-#define OPTION_NO_M4100 (OPTION_MD_BASE + 29)
- {"no-m4100", no_argument, NULL, OPTION_NO_M4100},
-#define OPTION_M3900 (OPTION_MD_BASE + 30)
- {"m3900", no_argument, NULL, OPTION_M3900},
-#define OPTION_NO_M3900 (OPTION_MD_BASE + 31)
- {"no-m3900", no_argument, NULL, OPTION_NO_M3900},
-#define OPTION_GP64 (OPTION_MD_BASE + 32)
+#define OPTION_GP64 (OPTION_MISC_BASE + 10)
{"mgp64", no_argument, NULL, OPTION_GP64},
-#define OPTION_MIPS3D (OPTION_MD_BASE + 33)
- {"mips3d", no_argument, NULL, OPTION_MIPS3D},
-#define OPTION_NO_MIPS3D (OPTION_MD_BASE + 34)
- {"no-mips3d", no_argument, NULL, OPTION_NO_MIPS3D},
-#define OPTION_MDMX (OPTION_MD_BASE + 35)
- {"mdmx", no_argument, NULL, OPTION_MDMX},
-#define OPTION_NO_MDMX (OPTION_MD_BASE + 36)
- {"no-mdmx", no_argument, NULL, OPTION_NO_MDMX},
-#define OPTION_FIX_VR4122 (OPTION_MD_BASE + 37)
-#define OPTION_NO_FIX_VR4122 (OPTION_MD_BASE + 38)
- {"mfix-vr4122-bugs", no_argument, NULL, OPTION_FIX_VR4122},
- {"no-mfix-vr4122-bugs", no_argument, NULL, OPTION_NO_FIX_VR4122},
-#define OPTION_RELAX_BRANCH (OPTION_MD_BASE + 39)
-#define OPTION_NO_RELAX_BRANCH (OPTION_MD_BASE + 40)
+#define OPTION_RELAX_BRANCH (OPTION_MISC_BASE + 11)
+#define OPTION_NO_RELAX_BRANCH (OPTION_MISC_BASE + 12)
{"relax-branch", no_argument, NULL, OPTION_RELAX_BRANCH},
{"no-relax-branch", no_argument, NULL, OPTION_NO_RELAX_BRANCH},
-#define OPTION_MIPS32R2 (OPTION_MD_BASE + 41)
- {"mips32r2", no_argument, NULL, OPTION_MIPS32R2},
+
+ /* ELF-specific options. */
#ifdef OBJ_ELF
-#define OPTION_ELF_BASE (OPTION_MD_BASE + 42)
+#define OPTION_ELF_BASE (OPTION_MISC_BASE + 13)
#define OPTION_CALL_SHARED (OPTION_ELF_BASE + 0)
{"KPIC", no_argument, NULL, OPTION_CALL_SHARED},
{"call_shared", no_argument, NULL, OPTION_CALL_SHARED},
{"mdebug", no_argument, NULL, OPTION_MDEBUG},
#define OPTION_NO_MDEBUG (OPTION_ELF_BASE + 8)
{"no-mdebug", no_argument, NULL, OPTION_NO_MDEBUG},
+#define OPTION_PDR (OPTION_ELF_BASE + 9)
+ {"mpdr", no_argument, NULL, OPTION_PDR},
+#define OPTION_NO_PDR (OPTION_ELF_BASE + 10)
+ {"mno-pdr", no_argument, NULL, OPTION_NO_PDR},
#endif /* OBJ_ELF */
+
{NULL, no_argument, NULL, 0}
};
size_t md_longopts_size = sizeof (md_longopts);
in a later argument. */
static void
-mips_set_option_string (string_ptr, new_value)
- const char **string_ptr, *new_value;
+mips_set_option_string (const char **string_ptr, const char *new_value)
{
if (*string_ptr != 0 && strcasecmp (*string_ptr, new_value) != 0)
as_warn (_("A different %s was already specified, is now %s"),
}
int
-md_parse_option (c, arg)
- int c;
- char *arg;
+md_parse_option (int c, char *arg)
{
switch (c)
{
return 0;
}
mips_pic = SVR4_PIC;
+ mips_abicalls = TRUE;
if (g_switch_seen && g_switch_value != 0)
{
as_bad (_("-G may not be used with SVR4 PIC code"));
return 0;
}
mips_pic = NO_PIC;
+ mips_abicalls = FALSE;
break;
/* The -xgot option tells the assembler to use 32 offsets when
case OPTION_NO_MDEBUG:
mips_flag_mdebug = FALSE;
break;
+
+ case OPTION_PDR:
+ mips_flag_pdr = TRUE;
+ break;
+
+ case OPTION_NO_PDR:
+ mips_flag_pdr = FALSE;
+ break;
#endif /* OBJ_ELF */
default:
described by INFO. */
static void
-mips_set_architecture (info)
- const struct mips_cpu_info *info;
+mips_set_architecture (const struct mips_cpu_info *info)
{
if (info != 0)
{
- mips_arch_info = info;
- mips_arch = info->cpu;
+ file_mips_arch = info->cpu;
+ mips_opts.arch = info->cpu;
mips_opts.isa = info->isa;
}
}
/* Likewise for tuning. */
static void
-mips_set_tune (info)
- const struct mips_cpu_info *info;
+mips_set_tune (const struct mips_cpu_info *info)
{
if (info != 0)
- {
- mips_tune_info = info;
- mips_tune = info->cpu;
- }
+ mips_tune = info->cpu;
}
void
-mips_after_parse_args ()
+mips_after_parse_args (void)
{
+ const struct mips_cpu_info *arch_info = 0;
+ const struct mips_cpu_info *tune_info = 0;
+
/* GP relative stuff not working for PE */
if (strncmp (TARGET_OS, "pe", 2) == 0
&& g_switch_value != 0)
g_switch_value = 0;
}
+ if (mips_abi == NO_ABI)
+ mips_abi = MIPS_DEFAULT_ABI;
+
/* The following code determines the architecture and register size.
Similar code was added to GCC 3.3 (see override_options() in
config/mips/mips.c). The GAS and GCC code should be kept in sync
as much as possible. */
if (mips_arch_string != 0)
- mips_set_architecture (mips_parse_cpu ("-march", mips_arch_string));
-
- if (mips_tune_string != 0)
- mips_set_tune (mips_parse_cpu ("-mtune", mips_tune_string));
+ arch_info = mips_parse_cpu ("-march", mips_arch_string);
if (file_mips_isa != ISA_UNKNOWN)
{
/* Handle -mipsN. At this point, file_mips_isa contains the
- ISA level specified by -mipsN, while mips_opts.isa contains
+ ISA level specified by -mipsN, while arch_info->isa contains
the -march selection (if any). */
- if (mips_arch_info != 0)
+ if (arch_info != 0)
{
/* -march takes precedence over -mipsN, since it is more descriptive.
There's no harm in specifying both as long as the ISA levels
are the same. */
- if (file_mips_isa != mips_opts.isa)
+ if (file_mips_isa != arch_info->isa)
as_bad (_("-%s conflicts with the other architecture options, which imply -%s"),
mips_cpu_info_from_isa (file_mips_isa)->name,
- mips_cpu_info_from_isa (mips_opts.isa)->name);
+ mips_cpu_info_from_isa (arch_info->isa)->name);
}
else
- mips_set_architecture (mips_cpu_info_from_isa (file_mips_isa));
+ arch_info = mips_cpu_info_from_isa (file_mips_isa);
}
- if (mips_arch_info == 0)
- mips_set_architecture (mips_parse_cpu ("default CPU",
- MIPS_CPU_STRING_DEFAULT));
+ if (arch_info == 0)
+ arch_info = mips_parse_cpu ("default CPU", MIPS_CPU_STRING_DEFAULT);
- if (ABI_NEEDS_64BIT_REGS (mips_abi) && !ISA_HAS_64BIT_REGS (mips_opts.isa))
+ if (ABI_NEEDS_64BIT_REGS (mips_abi) && !ISA_HAS_64BIT_REGS (arch_info->isa))
as_bad ("-march=%s is not compatible with the selected ABI",
- mips_arch_info->name);
+ arch_info->name);
+
+ mips_set_architecture (arch_info);
+
+ /* Optimize for file_mips_arch, unless -mtune selects a different processor. */
+ if (mips_tune_string != 0)
+ tune_info = mips_parse_cpu ("-mtune", mips_tune_string);
- /* Optimize for mips_arch, unless -mtune selects a different processor. */
- if (mips_tune_info == 0)
- mips_set_tune (mips_arch_info);
+ if (tune_info == 0)
+ mips_set_tune (arch_info);
+ else
+ mips_set_tune (tune_info);
if (file_mips_gp32 >= 0)
{
/* End of GCC-shared inference code. */
- /* ??? When do we want this flag to be set? Who uses it? */
- if (file_mips_gp32 == 1
- && mips_abi == NO_ABI
- && ISA_HAS_64BIT_REGS (mips_opts.isa))
+ /* This flag is set when we have a 64-bit capable CPU but use only
+ 32-bit wide registers. Note that EABI does not use it. */
+ if (ISA_HAS_64BIT_REGS (mips_opts.isa)
+ && ((mips_abi == NO_ABI && file_mips_gp32 == 1)
+ || mips_abi == O32_ABI))
mips_32bitmode = 1;
if (mips_opts.isa == ISA_MIPS1 && mips_trap)
/* If the selected architecture includes support for ASEs, enable
generation of code for them. */
if (mips_opts.mips16 == -1)
- mips_opts.mips16 = (CPU_HAS_MIPS16 (mips_arch)) ? 1 : 0;
+ mips_opts.mips16 = (CPU_HAS_MIPS16 (file_mips_arch)) ? 1 : 0;
if (mips_opts.ase_mips3d == -1)
- mips_opts.ase_mips3d = (CPU_HAS_MIPS3D (mips_arch)) ? 1 : 0;
+ mips_opts.ase_mips3d = (CPU_HAS_MIPS3D (file_mips_arch)) ? 1 : 0;
if (mips_opts.ase_mdmx == -1)
- mips_opts.ase_mdmx = (CPU_HAS_MDMX (mips_arch)) ? 1 : 0;
+ mips_opts.ase_mdmx = (CPU_HAS_MDMX (file_mips_arch)) ? 1 : 0;
file_mips_isa = mips_opts.isa;
file_ase_mips16 = mips_opts.mips16;
}
\f
void
-mips_init_after_args ()
+mips_init_after_args (void)
{
/* initialize opcodes */
bfd_mips_num_opcodes = bfd_mips_num_builtin_opcodes;
}
long
-md_pcrel_from (fixP)
- fixS *fixP;
+md_pcrel_from (fixS *fixP)
{
- if (OUTPUT_FLAVOR != bfd_target_aout_flavour
- && fixP->fx_addsy != (symbolS *) NULL
- && ! S_IS_DEFINED (fixP->fx_addsy))
- return 4;
-
- /* Return the address of the delay slot. */
- return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
+ valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_16_PCREL_S2:
+ case BFD_RELOC_MIPS_JMP:
+ /* Return the address of the delay slot. */
+ return addr + 4;
+ default:
+ return addr;
+ }
}
/* This is called before the symbol table is processed. In order to
mips-tfile, in which case we must generate all local labels. */
void
-mips_frob_file_before_adjust ()
+mips_frob_file_before_adjust (void)
{
#ifndef NO_ECOFF_DEBUGGING
if (ECOFF_DEBUGGING
explicit use of the %hi modifier. */
void
-mips_frob_file ()
+mips_frob_file (void)
{
struct mips_hi_fixup *l;
segment_info_type *seginfo;
int pass;
- assert (l->fixp->fx_r_type == BFD_RELOC_HI16_S);
+ assert (reloc_needs_lo_p (l->fixp->fx_r_type));
- /* Check quickly whether the next fixup happens to be a matching
- %lo. */
- if (l->fixp->fx_next != NULL
- && l->fixp->fx_next->fx_r_type == BFD_RELOC_LO16
- && l->fixp->fx_addsy == l->fixp->fx_next->fx_addsy
- && l->fixp->fx_offset == l->fixp->fx_next->fx_offset)
+ /* If a GOT16 relocation turns out to be against a global symbol,
+ there isn't supposed to be a matching LO. */
+ if (l->fixp->fx_r_type == BFD_RELOC_MIPS_GOT16
+ && !pic_need_relax (l->fixp->fx_addsy, l->seg))
+ continue;
+
+ /* Check quickly whether the next fixup happens to be a matching %lo. */
+ if (fixup_has_matching_lo_p (l->fixp))
continue;
/* Look through the fixups for this segment for a matching %lo.
&& f->fx_offset == l->fixp->fx_offset
&& (pass == 1
|| prev == NULL
- || prev->fx_r_type != BFD_RELOC_HI16_S
- || prev->fx_addsy != f->fx_addsy
- || prev->fx_offset != f->fx_offset))
+ || !reloc_needs_lo_p (prev->fx_r_type)
+ || !fixup_has_matching_lo_p (prev)))
{
fixS **pf;
We have to prevent gas from dropping them. */
int
-mips_force_relocation (fixp)
- fixS *fixp;
+mips_force_relocation (fixS *fixp)
{
if (generic_force_reloc (fixp))
return 1;
|| fixp->fx_r_type == BFD_RELOC_PCREL_LO16));
}
+/* This hook is called before a fix is simplified. We don't really
+ decide whether to skip a fix here. Rather, we turn global symbols
+ used as branch targets into local symbols, such that they undergo
+ simplification. We can only do this if the symbol is defined and
+ it is in the same section as the branch. If this doesn't hold, we
+ emit a better error message than just saying the relocation is not
+ valid for the selected object format.
+
+ FIXP is the fix-up we're going to try to simplify, SEG is the
+ segment in which the fix up occurs. The return value should be
+ non-zero to indicate the fix-up is valid for further
+ simplifications. */
+
+int
+mips_validate_fix (struct fix *fixP, asection *seg)
+{
+ /* There's a lot of discussion on whether it should be possible to
+ use R_MIPS_PC16 to represent branch relocations. The outcome
+ seems to be that it can, but gas/bfd are very broken in creating
+ RELA relocations for this, so for now we only accept branches to
+ symbols in the same section. Anything else is of dubious value,
+ since there's no guarantee that at link time the symbol would be
+ in range. Even for branches to local symbols this is arguably
+ wrong, since it we assume the symbol is not going to be
+ overridden, which should be possible per ELF library semantics,
+ but then, there isn't a dynamic relocation that could be used to
+ this effect, and the target would likely be out of range as well.
+
+ Unfortunately, it seems that there is too much code out there
+ that relies on branches to symbols that are global to be resolved
+ as if they were local, like the IRIX tools do, so we do it as
+ well, but with a warning so that people are reminded to fix their
+ code. If we ever get back to using R_MIPS_PC16 for branch
+ targets, this entire block should go away (and probably the
+ whole function). */
+
+ if (fixP->fx_r_type == BFD_RELOC_16_PCREL_S2
+ && (((OUTPUT_FLAVOR == bfd_target_ecoff_flavour
+ || OUTPUT_FLAVOR == bfd_target_elf_flavour)
+ && mips_pic != EMBEDDED_PIC)
+ || bfd_reloc_type_lookup (stdoutput, BFD_RELOC_16_PCREL_S2) == NULL)
+ && fixP->fx_addsy)
+ {
+ if (! S_IS_DEFINED (fixP->fx_addsy))
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Cannot branch to undefined symbol."));
+ /* Avoid any further errors about this fixup. */
+ fixP->fx_done = 1;
+ }
+ else if (S_GET_SEGMENT (fixP->fx_addsy) != seg)
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Cannot branch to symbol in another section."));
+ fixP->fx_done = 1;
+ }
+ else if (S_IS_EXTERNAL (fixP->fx_addsy))
+ {
+ symbolS *sym = fixP->fx_addsy;
+
+ if (mips_pic == SVR4_PIC)
+ as_warn_where (fixP->fx_file, fixP->fx_line,
+ _("Pretending global symbol used as branch target is local."));
+
+ fixP->fx_addsy = symbol_create (S_GET_NAME (sym),
+ S_GET_SEGMENT (sym),
+ S_GET_VALUE (sym),
+ symbol_get_frag (sym));
+ copy_symbol_attributes (fixP->fx_addsy, sym);
+ S_CLEAR_EXTERNAL (fixP->fx_addsy);
+ assert (symbol_resolved_p (sym));
+ symbol_mark_resolved (fixP->fx_addsy);
+ }
+ }
+
+ return 1;
+}
+
#ifdef OBJ_ELF
static int
-mips_need_elf_addend_fixup (fixP)
- fixS *fixP;
+mips_need_elf_addend_fixup (fixS *fixP)
{
if (S_GET_OTHER (fixP->fx_addsy) == STO_MIPS16)
return 1;
|| S_IS_EXTERNAL (fixP->fx_addsy))
&& !S_IS_COMMON (fixP->fx_addsy))
return 1;
- if (symbol_used_in_reloc_p (fixP->fx_addsy)
- && (((bfd_get_section_flags (stdoutput,
- S_GET_SEGMENT (fixP->fx_addsy))
- & (SEC_LINK_ONCE | SEC_MERGE)) != 0)
- || !strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
- ".gnu.linkonce",
- sizeof (".gnu.linkonce") - 1)))
+ if (((bfd_get_section_flags (stdoutput,
+ S_GET_SEGMENT (fixP->fx_addsy))
+ & (SEC_LINK_ONCE | SEC_MERGE)) != 0)
+ || !strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
+ ".gnu.linkonce",
+ sizeof (".gnu.linkonce") - 1))
return 1;
return 0;
}
/* Apply a fixup to the object file. */
void
-md_apply_fix3 (fixP, valP, seg)
- fixS *fixP;
- valueT *valP;
- segT seg ATTRIBUTE_UNUSED;
+md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
{
bfd_byte *buf;
long insn;
- valueT value;
static int previous_fx_r_type = 0;
+ reloc_howto_type *howto;
- /* FIXME: Maybe just return for all reloc types not listed below?
- Eric Christopher says: "This is stupid, please rewrite md_apply_fix3. */
- if (fixP->fx_r_type == BFD_RELOC_8)
- return;
+ /* We ignore generic BFD relocations we don't know about. */
+ howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
+ if (! howto)
+ return;
assert (fixP->fx_size == 4
|| fixP->fx_r_type == BFD_RELOC_16
- || fixP->fx_r_type == BFD_RELOC_32
- || fixP->fx_r_type == BFD_RELOC_MIPS_JMP
- || fixP->fx_r_type == BFD_RELOC_HI16_S
- || fixP->fx_r_type == BFD_RELOC_LO16
- || fixP->fx_r_type == BFD_RELOC_GPREL16
- || fixP->fx_r_type == BFD_RELOC_MIPS_LITERAL
- || fixP->fx_r_type == BFD_RELOC_GPREL32
|| fixP->fx_r_type == BFD_RELOC_64
|| fixP->fx_r_type == BFD_RELOC_CTOR
|| fixP->fx_r_type == BFD_RELOC_MIPS_SUB
- || fixP->fx_r_type == BFD_RELOC_MIPS_HIGHEST
- || fixP->fx_r_type == BFD_RELOC_MIPS_HIGHER
- || fixP->fx_r_type == BFD_RELOC_MIPS_SCN_DISP
- || fixP->fx_r_type == BFD_RELOC_MIPS_REL16
- || fixP->fx_r_type == BFD_RELOC_MIPS_RELGOT
|| fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
- || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
- || fixP->fx_r_type == BFD_RELOC_MIPS_JALR);
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY);
- value = *valP;
+ buf = (bfd_byte *) (fixP->fx_frag->fr_literal + fixP->fx_where);
/* If we aren't adjusting this fixup to be against the section
symbol, we need to adjust the value. */
#ifdef OBJ_ELF
if (fixP->fx_addsy != NULL && OUTPUT_FLAVOR == bfd_target_elf_flavour)
{
- if (mips_need_elf_addend_fixup (fixP))
- {
- reloc_howto_type *howto;
- valueT symval = S_GET_VALUE (fixP->fx_addsy);
-
- value -= symval;
-
- howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
- if (value != 0 && howto && howto->partial_inplace
- && (! fixP->fx_pcrel || howto->pcrel_offset))
- {
- /* In this case, the bfd_install_relocation routine will
- incorrectly add the symbol value back in. We just want
- the addend to appear in the object file.
-
- howto->pcrel_offset is added for R_MIPS_PC16, which is
- generated for code like
-
- globl g1 .text
- .text
- .space 20
- g1:
- x:
- bal g1
- */
- value -= symval;
-
- /* Make sure the addend is still non-zero. If it became zero
- after the last operation, set it to a spurious value and
- subtract the same value from the object file's contents. */
- if (value == 0)
- {
- value = 8;
-
- /* The in-place addends for LO16 relocations are signed;
- leave the matching HI16 in-place addends as zero. */
- if (fixP->fx_r_type != BFD_RELOC_HI16_S)
- {
- bfd_vma contents, mask, field;
-
- contents = bfd_get_bits (fixP->fx_frag->fr_literal
- + fixP->fx_where,
- fixP->fx_size * 8,
- target_big_endian);
-
- /* MASK has bits set where the relocation should go.
- FIELD is -value, shifted into the appropriate place
- for this relocation. */
- mask = 1 << (howto->bitsize - 1);
- mask = (((mask - 1) << 1) | 1) << howto->bitpos;
- field = (-value >> howto->rightshift) << howto->bitpos;
-
- bfd_put_bits ((field & mask) | (contents & ~mask),
- fixP->fx_frag->fr_literal + fixP->fx_where,
- fixP->fx_size * 8,
- target_big_endian);
- }
- }
- }
+ if (mips_need_elf_addend_fixup (fixP)
+ && howto->partial_inplace
+ && fixP->fx_r_type != BFD_RELOC_GPREL16
+ && fixP->fx_r_type != BFD_RELOC_GPREL32
+ && fixP->fx_r_type != BFD_RELOC_MIPS16_GPREL)
+ {
+ /* In this case, the bfd_install_relocation routine will
+ incorrectly add the symbol value back in. We just want
+ the addend to appear in the object file.
+
+ The condition above used to include
+ "&& (! fixP->fx_pcrel || howto->pcrel_offset)".
+
+ However, howto can't be trusted here, because we
+ might change the reloc type in tc_gen_reloc. We can
+ check howto->partial_inplace because that conversion
+ happens to preserve howto->partial_inplace; but it
+ does not preserve howto->pcrel_offset. I've just
+ eliminated the check, because all MIPS PC-relative
+ relocations are marked howto->pcrel_offset.
+
+ howto->pcrel_offset was originally added for
+ R_MIPS_PC16, which is generated for code like
+
+ globl g1 .text
+ .text
+ .space 20
+ g1:
+ x:
+ bal g1
+ */
+ *valP -= S_GET_VALUE (fixP->fx_addsy);
}
/* This code was generated using trial and error and so is
fragile and not trustworthy. If you change it, you should
rerun the elf-rel, elf-rel2, and empic testcases and ensure
they still pass. */
- if (fixP->fx_pcrel || fixP->fx_subsy != NULL)
+ if (fixP->fx_pcrel)
{
- value += fixP->fx_frag->fr_address + fixP->fx_where;
+ *valP += fixP->fx_frag->fr_address + fixP->fx_where;
/* BFD's REL handling, for MIPS, is _very_ weird.
This gives the right results, but it can't possibly
be the way things are supposed to work. */
- if (fixP->fx_r_type != BFD_RELOC_16_PCREL_S2
- || S_GET_SEGMENT (fixP->fx_addsy) != undefined_section)
- value += fixP->fx_frag->fr_address + fixP->fx_where;
+ *valP += fixP->fx_frag->fr_address + fixP->fx_where;
}
}
#endif
- fixP->fx_addnumber = value; /* Remember value for tc_gen_reloc. */
-
/* We are not done if this is a composite relocation to set up gp. */
if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel
&& !(fixP->fx_r_type == BFD_RELOC_MIPS_SUB
/* We currently always generate a reloc against a symbol, which
means that we don't want an addend even if the symbol is
defined. */
- fixP->fx_addnumber = 0;
+ *valP = 0;
break;
case BFD_RELOC_PCREL_HI16_S:
/* The addend for this is tricky if it is internal, so we just
do everything here rather than in bfd_install_relocation. */
- if (OUTPUT_FLAVOR == bfd_target_elf_flavour
- && !fixP->fx_done
- && value != 0)
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour && !fixP->fx_done)
break;
if (fixP->fx_addsy
&& (symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0)
/* For an external symbol adjust by the address to make it
pcrel_offset. We use the address of the RELLO reloc
which follows this one. */
- value += (fixP->fx_next->fx_frag->fr_address
+ *valP += (fixP->fx_next->fx_frag->fr_address
+ fixP->fx_next->fx_where);
}
- value = ((value + 0x8000) >> 16) & 0xffff;
- buf = (bfd_byte *) fixP->fx_frag->fr_literal + fixP->fx_where;
+ *valP = ((*valP + 0x8000) >> 16) & 0xffff;
if (target_big_endian)
buf += 2;
- md_number_to_chars ((char *) buf, value, 2);
+ md_number_to_chars (buf, *valP, 2);
break;
case BFD_RELOC_PCREL_LO16:
/* The addend for this is tricky if it is internal, so we just
do everything here rather than in bfd_install_relocation. */
- if (OUTPUT_FLAVOR == bfd_target_elf_flavour
- && !fixP->fx_done
- && value != 0)
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour && !fixP->fx_done)
break;
if (fixP->fx_addsy
&& (symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0)
- value += fixP->fx_frag->fr_address + fixP->fx_where;
- buf = (bfd_byte *) fixP->fx_frag->fr_literal + fixP->fx_where;
+ *valP += fixP->fx_frag->fr_address + fixP->fx_where;
if (target_big_endian)
buf += 2;
- md_number_to_chars ((char *) buf, value, 2);
+ md_number_to_chars (buf, *valP, 2);
break;
case BFD_RELOC_64:
|| (mips_pic == EMBEDDED_PIC && SWITCH_TABLE (fixP)))
{
if (8 <= sizeof (valueT))
- md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
- value, 8);
+ md_number_to_chars (buf, *valP, 8);
else
{
- long w1, w2;
- long hiv;
+ valueT hiv;
- w1 = w2 = fixP->fx_where;
- if (target_big_endian)
- w1 += 4;
- else
- w2 += 4;
- md_number_to_chars (fixP->fx_frag->fr_literal + w1, value, 4);
- if ((value & 0x80000000) != 0)
+ if ((*valP & 0x80000000) != 0)
hiv = 0xffffffff;
else
hiv = 0;
- md_number_to_chars (fixP->fx_frag->fr_literal + w2, hiv, 4);
+ md_number_to_chars ((char *)(buf + target_big_endian ? 4 : 0),
+ *valP, 4);
+ md_number_to_chars ((char *)(buf + target_big_endian ? 0 : 4),
+ hiv, 4);
}
}
break;
entry. */
if (fixP->fx_done
|| (mips_pic == EMBEDDED_PIC && SWITCH_TABLE (fixP)))
- md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
- value, 4);
+ md_number_to_chars (buf, *valP, 4);
break;
case BFD_RELOC_16:
value now. */
assert (fixP->fx_size == 2);
if (fixP->fx_done)
- md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
- value, 2);
+ md_number_to_chars (buf, *valP, 2);
break;
case BFD_RELOC_LO16:
up deleting a LO16 reloc. See the 'o' case in mips_ip. */
if (fixP->fx_done)
{
- if (value + 0x8000 > 0xffff)
+ if (*valP + 0x8000 > 0xffff)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("relocation overflow"));
- buf = (bfd_byte *) fixP->fx_frag->fr_literal + fixP->fx_where;
if (target_big_endian)
buf += 2;
- md_number_to_chars ((char *) buf, value, 2);
+ md_number_to_chars (buf, *valP, 2);
}
break;
case BFD_RELOC_16_PCREL_S2:
- if ((value & 0x3) != 0)
+ if ((*valP & 0x3) != 0)
as_bad_where (fixP->fx_file, fixP->fx_line,
- _("Branch to odd address (%lx)"), (long) value);
+ _("Branch to odd address (%lx)"), (long) *valP);
/*
* We need to save the bits in the instruction since fixup_segment()
* might be deleting the relocation entry (i.e., a branch within
* the current segment).
*/
- if (!fixP->fx_done && (value != 0 || HAVE_NEWABI))
+ if (! fixP->fx_done)
break;
- /* If 'value' is zero, the remaining reloc code won't actually
- do the store, so it must be done here. This is probably
- a bug somewhere. */
- if (!fixP->fx_done
- && (fixP->fx_r_type != BFD_RELOC_16_PCREL_S2
- || fixP->fx_addsy == NULL /* ??? */
- || ! S_IS_DEFINED (fixP->fx_addsy)))
- value -= fixP->fx_frag->fr_address + fixP->fx_where;
-
- value = (offsetT) value >> 2;
/* update old instruction data */
- buf = (bfd_byte *) (fixP->fx_where + fixP->fx_frag->fr_literal);
if (target_big_endian)
insn = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
else
insn = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
- if (value + 0x8000 <= 0xffff)
- insn |= value & 0xffff;
- else
+ if (*valP + 0x20000 <= 0x3ffff)
+ {
+ insn |= (*valP >> 2) & 0xffff;
+ md_number_to_chars (buf, insn, 4);
+ }
+ else if (mips_pic == NO_PIC
+ && fixP->fx_done
+ && fixP->fx_frag->fr_address >= text_section->vma
+ && (fixP->fx_frag->fr_address
+ < text_section->vma + text_section->_raw_size)
+ && ((insn & 0xffff0000) == 0x10000000 /* beq $0,$0 */
+ || (insn & 0xffff0000) == 0x04010000 /* bgez $0 */
+ || (insn & 0xffff0000) == 0x04110000)) /* bgezal $0 */
{
/* The branch offset is too large. If this is an
unconditional branch, and we are not generating PIC code,
we can convert it to an absolute jump instruction. */
- if (mips_pic == NO_PIC
- && fixP->fx_done
- && fixP->fx_frag->fr_address >= text_section->vma
- && (fixP->fx_frag->fr_address
- < text_section->vma + text_section->_raw_size)
- && ((insn & 0xffff0000) == 0x10000000 /* beq $0,$0 */
- || (insn & 0xffff0000) == 0x04010000 /* bgez $0 */
- || (insn & 0xffff0000) == 0x04110000)) /* bgezal $0 */
- {
- if ((insn & 0xffff0000) == 0x04110000) /* bgezal $0 */
- insn = 0x0c000000; /* jal */
- else
- insn = 0x08000000; /* j */
- fixP->fx_r_type = BFD_RELOC_MIPS_JMP;
- fixP->fx_done = 0;
- fixP->fx_addsy = section_symbol (text_section);
- fixP->fx_addnumber = (value << 2) + md_pcrel_from (fixP);
- }
+ if ((insn & 0xffff0000) == 0x04110000) /* bgezal $0 */
+ insn = 0x0c000000; /* jal */
else
- {
- /* If we got here, we have branch-relaxation disabled,
- and there's nothing we can do to fix this instruction
- without turning it into a longer sequence. */
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("Branch out of range"));
- }
+ insn = 0x08000000; /* j */
+ fixP->fx_r_type = BFD_RELOC_MIPS_JMP;
+ fixP->fx_done = 0;
+ fixP->fx_addsy = section_symbol (text_section);
+ *valP += md_pcrel_from (fixP);
+ md_number_to_chars (buf, insn, 4);
+ }
+ else
+ {
+ /* If we got here, we have branch-relaxation disabled,
+ and there's nothing we can do to fix this instruction
+ without turning it into a longer sequence. */
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Branch out of range"));
}
-
- md_number_to_chars ((char *) buf, (valueT) insn, 4);
break;
case BFD_RELOC_VTABLE_INHERIT:
default:
internalError ();
}
+
+ /* Remember value for tc_gen_reloc. */
+ fixP->fx_addnumber = *valP;
}
#if 0
void
-printInsn (oc)
- unsigned long oc;
+printInsn (unsigned long oc)
{
const struct mips_opcode *p;
int treg, sreg, dreg, shamt;
#endif
static symbolS *
-get_symbol ()
+get_symbol (void)
{
int c;
char *name;
also automatically adjusts any preceding label. */
static void
-mips_align (to, fill, label)
- int to;
- int fill;
- symbolS *label;
+mips_align (int to, int fill, symbolS *label)
{
mips_emit_delays (FALSE);
frag_align (to, fill, 0);
alignment used by the data creating pseudo-ops. */
static void
-s_align (x)
- int x ATTRIBUTE_UNUSED;
+s_align (int x ATTRIBUTE_UNUSED)
{
register int temp;
register long temp_fill;
}
void
-mips_flush_pending_output ()
+mips_flush_pending_output (void)
{
mips_emit_delays (FALSE);
mips_clear_insn_labels ();
}
static void
-s_change_sec (sec)
- int sec;
+s_change_sec (int sec)
{
segT seg;
}
void
-s_change_section (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_change_section (int ignore ATTRIBUTE_UNUSED)
{
#ifdef OBJ_ELF
char *section_name;
char c;
- char next_c;
+ char next_c = 0;
int section_type;
int section_flag;
int section_entry_size;
}
void
-mips_enable_auto_align ()
+mips_enable_auto_align (void)
{
auto_align = 1;
}
static void
-s_cons (log_size)
- int log_size;
+s_cons (int log_size)
{
symbolS *label;
}
static void
-s_float_cons (type)
- int type;
+s_float_cons (int type)
{
symbolS *label;
considered to be the address of a function. */
static void
-s_mips_globl (x)
- int x ATTRIBUTE_UNUSED;
+s_mips_globl (int x ATTRIBUTE_UNUSED)
{
char *name;
int c;
}
static void
-s_option (x)
- int x ATTRIBUTE_UNUSED;
+s_option (int x ATTRIBUTE_UNUSED)
{
char *opt;
char c;
if (i == 0)
mips_pic = NO_PIC;
else if (i == 2)
+ {
mips_pic = SVR4_PIC;
+ mips_abicalls = TRUE;
+ }
else
as_bad (_(".option pic%d not supported"), i);
/* Handle the .set pseudo-op. */
static void
-s_mipsset (x)
- int x ATTRIBUTE_UNUSED;
+s_mipsset (int x ATTRIBUTE_UNUSED)
{
char *name = input_line_pointer, ch;
mips_opts.ase_mdmx = 1;
else if (strcmp (name, "nomdmx") == 0)
mips_opts.ase_mdmx = 0;
- else if (strncmp (name, "mips", 4) == 0)
+ else if (strncmp (name, "mips", 4) == 0 || strncmp (name, "arch=", 5) == 0)
{
int reset = 0;
- /* Permit the user to change the ISA on the fly. Needless to
- say, misuse can cause serious problems. */
+ /* Permit the user to change the ISA and architecture on the fly.
+ Needless to say, misuse can cause serious problems. */
if (strcmp (name, "mips0") == 0)
{
reset = 1;
mips_opts.isa = ISA_MIPS32R2;
else if (strcmp (name, "mips64") == 0)
mips_opts.isa = ISA_MIPS64;
+ else if (strcmp (name, "arch=default") == 0)
+ {
+ reset = 1;
+ mips_opts.arch = file_mips_arch;
+ mips_opts.isa = file_mips_isa;
+ }
+ else if (strncmp (name, "arch=", 5) == 0)
+ {
+ const struct mips_cpu_info *p;
+
+ p = mips_parse_cpu("internal use", name + 5);
+ if (!p)
+ as_bad (_("unknown architecture %s"), name + 5);
+ else
+ {
+ mips_opts.arch = p->cpu;
+ mips_opts.isa = p->isa;
+ }
+ }
else
as_bad (_("unknown ISA level %s"), name + 4);
.option pic2. It means to generate SVR4 PIC calls. */
static void
-s_abicalls (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_abicalls (int ignore ATTRIBUTE_UNUSED)
{
mips_pic = SVR4_PIC;
+ mips_abicalls = TRUE;
if (USE_GLOBAL_POINTER_OPT)
{
if (g_switch_seen && g_switch_value != 0)
The .cpload argument is normally $25 == $t9. */
static void
-s_cpload (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_cpload (int ignore ATTRIBUTE_UNUSED)
{
expressionS ex;
int icnt = 0;
symbol_get_bfdsym (ex.X_add_symbol)->flags |= BSF_OBJECT;
macro_build_lui (NULL, &icnt, &ex, mips_gp_register);
- macro_build ((char *) NULL, &icnt, &ex, "addiu", "t,r,j",
- mips_gp_register, mips_gp_register, (int) BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, &ex, "addiu", "t,r,j", mips_gp_register,
+ mips_gp_register, BFD_RELOC_LO16);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "addu", "d,v,t",
- mips_gp_register, mips_gp_register, tc_get_register (0));
+ macro_build (NULL, &icnt, NULL, "addu", "d,v,t", mips_gp_register,
+ mips_gp_register, tc_get_register (0));
demand_empty_rest_of_line ();
}
daddu $gp, $gp, $reg1
$reg1 is normally $25 == $t9. */
static void
-s_cpsetup (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_cpsetup (int ignore ATTRIBUTE_UNUSED)
{
expressionS ex_off;
expressionS ex_sym;
ex_off.X_op_symbol = NULL;
ex_off.X_add_number = mips_cpreturn_offset;
- macro_build ((char *) NULL, &icnt, &ex_off, "sd", "t,o(b)",
- mips_gp_register, (int) BFD_RELOC_LO16, SP);
+ macro_build (NULL, &icnt, &ex_off, "sd", "t,o(b)", mips_gp_register,
+ BFD_RELOC_LO16, SP);
}
else
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "daddu",
- "d,v,t", mips_cpreturn_register, mips_gp_register, 0);
+ macro_build (NULL, &icnt, 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 ((char *) NULL, &icnt, &ex_sym, "lui", "t,u", mips_gp_register,
- (int) BFD_RELOC_GPREL16);
+ macro_build (NULL, &icnt, &ex_sym, "lui", "t,u", mips_gp_register,
+ BFD_RELOC_GPREL16);
fix_new (frag_now, f - frag_now->fr_literal,
- 0, NULL, 0, 0, BFD_RELOC_MIPS_SUB);
+ 8, NULL, 0, 0, BFD_RELOC_MIPS_SUB);
fix_new (frag_now, f - frag_now->fr_literal,
- 0, NULL, 0, 0, BFD_RELOC_HI16_S);
+ 4, NULL, 0, 0, BFD_RELOC_HI16_S);
f = frag_more (0);
- macro_build ((char *) NULL, &icnt, &ex_sym, "addiu", "t,r,j",
- mips_gp_register, mips_gp_register, (int) BFD_RELOC_GPREL16);
+ macro_build (NULL, &icnt, &ex_sym, "addiu", "t,r,j", mips_gp_register,
+ mips_gp_register, BFD_RELOC_GPREL16);
fix_new (frag_now, f - frag_now->fr_literal,
- 0, NULL, 0, 0, BFD_RELOC_MIPS_SUB);
+ 8, NULL, 0, 0, BFD_RELOC_MIPS_SUB);
fix_new (frag_now, f - frag_now->fr_literal,
- 0, NULL, 0, 0, BFD_RELOC_LO16);
+ 4, NULL, 0, 0, BFD_RELOC_LO16);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_64BIT_ADDRESSES ? "daddu" : "addu", "d,v,t",
- mips_gp_register, mips_gp_register, reg1);
+ macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t", mips_gp_register,
+ mips_gp_register, reg1);
demand_empty_rest_of_line ();
}
static void
-s_cplocal (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_cplocal (int ignore ATTRIBUTE_UNUSED)
{
/* If we are not generating SVR4 PIC code, or if this is not NewABI code,
.cplocal is ignored. */
call $gp is restored from that location. */
static void
-s_cprestore (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_cprestore (int ignore ATTRIBUTE_UNUSED)
{
expressionS ex;
int icnt = 0;
ex.X_op_symbol = NULL;
ex.X_add_number = mips_cprestore_offset;
- macro_build_ldst_constoffset ((char *) NULL, &icnt, &ex,
- HAVE_32BIT_ADDRESSES ? "sw" : "sd",
+ macro_build_ldst_constoffset (NULL, &icnt, &ex, ADDRESS_STORE_INSN,
mips_gp_register, SP);
demand_empty_rest_of_line ();
daddiu $gp, $gp, $reg2
*/
static void
-s_cpreturn (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_cpreturn (int ignore ATTRIBUTE_UNUSED)
{
expressionS ex;
int icnt = 0;
ex.X_op_symbol = NULL;
ex.X_add_number = mips_cpreturn_offset;
- macro_build ((char *) NULL, &icnt, &ex, "ld", "t,o(b)",
- mips_gp_register, (int) BFD_RELOC_LO16, SP);
+ macro_build (NULL, &icnt, &ex, "ld", "t,o(b)", mips_gp_register,
+ BFD_RELOC_LO16, SP);
}
else
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "daddu",
- "d,v,t", mips_gp_register, mips_cpreturn_register, 0);
+ macro_build (NULL, &icnt, NULL, "daddu", "d,v,t", mips_gp_register,
+ mips_cpreturn_register, 0);
demand_empty_rest_of_line ();
}
code. It sets the offset to use in gp_rel relocations. */
static void
-s_gpvalue (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_gpvalue (int ignore ATTRIBUTE_UNUSED)
{
/* If we are not generating SVR4 PIC code, .gpvalue is ignored.
We also need NewABI support. */
code. It generates a 32 bit GP relative reloc. */
static void
-s_gpword (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_gpword (int ignore ATTRIBUTE_UNUSED)
{
symbolS *label;
expressionS ex;
}
p = frag_more (4);
- md_number_to_chars (p, (valueT) 0, 4);
+ md_number_to_chars (p, 0, 4);
fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE,
BFD_RELOC_GPREL32);
}
static void
-s_gpdword (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_gpdword (int ignore ATTRIBUTE_UNUSED)
{
symbolS *label;
expressionS ex;
}
p = frag_more (8);
- md_number_to_chars (p, (valueT) 0, 8);
- fix_new_exp (frag_now, p - frag_now->fr_literal, 8, &ex, FALSE,
+ md_number_to_chars (p, 0, 8);
+ fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE,
BFD_RELOC_GPREL32);
/* GPREL32 composed with 64 gives a 64-bit GP offset. */
tables in SVR4 PIC code. */
static void
-s_cpadd (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_cpadd (int ignore ATTRIBUTE_UNUSED)
{
int icnt = 0;
int reg;
/* Add $gp to the register named as an argument. */
reg = tc_get_register (0);
- macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
- HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
- "d,v,t", reg, reg, mips_gp_register);
+ macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ reg, reg, mips_gp_register);
demand_empty_rest_of_line ();
}
again. */
static void
-s_insn (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_insn (int ignore ATTRIBUTE_UNUSED)
{
mips16_mark_labels ();
really a mips16 text label. */
static void
-s_mips_stab (type)
- int type;
+s_mips_stab (int type)
{
if (type == 'n')
mips16_mark_labels ();
*/
static void
-s_mips_weakext (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_mips_weakext (int ignore ATTRIBUTE_UNUSED)
{
char *name;
int c;
register, so that we can record it in mips_frame_reg. */
int
-tc_get_register (frame)
- int frame;
+tc_get_register (int frame)
{
int reg;
}
valueT
-md_section_align (seg, addr)
- asection *seg;
- valueT addr;
+md_section_align (asection *seg, valueT addr)
{
int align = bfd_get_section_alignment (stdoutput, seg);
undefined earlier.) */
static int
-nopic_need_relax (sym, before_relaxing)
- symbolS *sym;
- int before_relaxing;
+nopic_need_relax (symbolS *sym, int before_relaxing)
{
if (sym == 0)
return 0;
return 1;
}
+
+/* Return true if the given symbol should be considered local for SVR4 PIC. */
+
+static bfd_boolean
+pic_need_relax (symbolS *sym, asection *segtype)
+{
+ asection *symsec;
+ bfd_boolean linkonce;
+
+ /* Handle the case of a symbol equated to another symbol. */
+ while (symbol_equated_reloc_p (sym))
+ {
+ symbolS *n;
+
+ /* It's possible to get a loop here in a badly written
+ program. */
+ n = symbol_get_value_expression (sym)->X_add_symbol;
+ if (n == sym)
+ break;
+ sym = n;
+ }
+
+ symsec = S_GET_SEGMENT (sym);
+
+ /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
+ linkonce = FALSE;
+ if (symsec != segtype && ! S_IS_LOCAL (sym))
+ {
+ if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE)
+ != 0)
+ linkonce = TRUE;
+
+ /* The GNU toolchain uses an extension for ELF: a section
+ beginning with the magic string .gnu.linkonce is a linkonce
+ section. */
+ if (strncmp (segment_name (symsec), ".gnu.linkonce",
+ sizeof ".gnu.linkonce" - 1) == 0)
+ linkonce = TRUE;
+ }
+
+ /* This must duplicate the test in adjust_reloc_syms. */
+ return (symsec != &bfd_und_section
+ && symsec != &bfd_abs_section
+ && ! bfd_is_com_section (symsec)
+ && !linkonce
+#ifdef OBJ_ELF
+ /* A global or weak symbol is treated as external. */
+ && (OUTPUT_FLAVOR != bfd_target_elf_flavour
+ || (! S_IS_WEAK (sym)
+ && (! S_IS_EXTERNAL (sym)
+ || mips_pic == EMBEDDED_PIC)))
+#endif
+ );
+}
+
+
/* Given a mips16 variant frag FRAGP, return non-zero if it needs an
extended opcode. SEC is the section the frag is in. */
static int
-mips16_extended_frag (fragp, sec, stretch)
- fragS *fragp;
- asection *sec;
- long stretch;
+mips16_extended_frag (fragS *fragp, asection *sec, long stretch)
{
int type;
register const struct mips16_immed_operand *op;
whether an unconditional (-1), branch-likely (+1) or regular (0)
branch is to be computed. */
static int
-relaxed_branch_length (fragp, sec, update)
- fragS *fragp;
- asection *sec;
- int update;
+relaxed_branch_length (fragS *fragp, asection *sec, int update)
{
bfd_boolean toofar;
int length;
decide whether we are using an extended opcode or not. */
int
-md_estimate_size_before_relax (fragp, segtype)
- fragS *fragp;
- asection *segtype;
+md_estimate_size_before_relax (fragS *fragp, asection *segtype)
{
- int change = 0;
- bfd_boolean linkonce = FALSE;
+ int change;
if (RELAX_BRANCH_P (fragp->fr_subtype))
{
return (RELAX_MIPS16_EXTENDED (fragp->fr_subtype) ? 4 : 2);
if (mips_pic == NO_PIC)
- {
- change = nopic_need_relax (fragp->fr_symbol, 0);
- }
+ change = nopic_need_relax (fragp->fr_symbol, 0);
else if (mips_pic == SVR4_PIC)
- {
- symbolS *sym;
- asection *symsec;
-
- sym = fragp->fr_symbol;
-
- /* Handle the case of a symbol equated to another symbol. */
- while (symbol_equated_reloc_p (sym))
- {
- symbolS *n;
-
- /* It's possible to get a loop here in a badly written
- program. */
- n = symbol_get_value_expression (sym)->X_add_symbol;
- if (n == sym)
- break;
- sym = n;
- }
-
- symsec = S_GET_SEGMENT (sym);
-
- /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
- if (symsec != segtype && ! S_IS_LOCAL (sym))
- {
- if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE)
- != 0)
- linkonce = TRUE;
-
- /* The GNU toolchain uses an extension for ELF: a section
- beginning with the magic string .gnu.linkonce is a linkonce
- section. */
- if (strncmp (segment_name (symsec), ".gnu.linkonce",
- sizeof ".gnu.linkonce" - 1) == 0)
- linkonce = TRUE;
- }
-
- /* This must duplicate the test in adjust_reloc_syms. */
- change = (symsec != &bfd_und_section
- && symsec != &bfd_abs_section
- && ! bfd_is_com_section (symsec)
- && !linkonce
-#ifdef OBJ_ELF
- /* A global or weak symbol is treated as external. */
- && (OUTPUT_FLAVOR != bfd_target_elf_flavour
- || (! S_IS_WEAK (sym)
- && (! S_IS_EXTERNAL (sym)
- || mips_pic == EMBEDDED_PIC)))
-#endif
- );
- }
+ change = pic_need_relax (fragp->fr_symbol, segtype);
else
abort ();
up a stub. */
int
-mips_fix_adjustable (fixp)
- fixS *fixp;
+mips_fix_adjustable (fixS *fixp)
{
if (fixp->fx_r_type == BFD_RELOC_MIPS16_JMP)
return 0;
format. */
arelent **
-tc_gen_reloc (section, fixp)
- asection *section ATTRIBUTE_UNUSED;
- fixS *fixp;
+tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
{
static arelent *retval[4];
arelent *reloc;
bfd_reloc_code_real_type code;
- reloc = retval[0] = (arelent *) xmalloc (sizeof (arelent));
- retval[1] = NULL;
-
+ memset (retval, 0, sizeof(retval));
+ reloc = retval[0] = (arelent *) xcalloc (1, sizeof (arelent));
reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
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_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));
- retval[2] = NULL;
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 = fixp->fx_addnumber;
+ reloc2->addend = fixp->fx_addnumber - S_GET_VALUE (fixp->fx_addsy)
+ + fixp->fx_frag->tc_frag_data.tc_fr_offset;
reloc2->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
assert (reloc2->howto != NULL);
arelent *reloc3;
reloc3 = retval[2] = (arelent *) xmalloc (sizeof (arelent));
- retval[3] = NULL;
*reloc3 = *reloc2;
reloc3->address += 4;
}
break;
case BFD_RELOC_MIPS_GOT_LO16:
case BFD_RELOC_MIPS_CALL_LO16:
- fixp->fx_r_type = BFD_RELOC_MIPS_GOT16;
- break;
- case BFD_RELOC_MIPS_CALL16:
if (HAVE_NEWABI)
{
- /* BFD_RELOC_MIPS_GOT16;*/
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 ();
-
- /* newabi uses R_MIPS_GOT_DISP for local symbols */
- if (HAVE_NEWABI && fixp->fx_r_type == BFD_RELOC_MIPS_GOT_LO16)
- {
- fixp->fx_r_type = BFD_RELOC_MIPS_GOT_DISP;
- retval[1] = NULL;
- }
}
/* Since the old MIPS ELF ABI uses Rel instead of Rela, encode the vtable
}
}
-#ifdef OBJ_ELF
- /* md_apply_fix3 has a double-subtraction hack to get
- bfd_install_relocation to behave nicely. GPREL relocations are
- handled correctly without this hack, so undo it here. We can't
- stop md_apply_fix3 from subtracting twice in the first place since
- the fake addend is required for variant frags above. */
- if (fixp->fx_addsy != NULL && OUTPUT_FLAVOR == bfd_target_elf_flavour
- && (code == BFD_RELOC_GPREL16 || code == BFD_RELOC_MIPS16_GPREL)
- && reloc->addend != 0
- && mips_need_elf_addend_fixup (fixp))
- reloc->addend += S_GET_VALUE (fixp->fx_addsy);
-#endif
-
/* To support a PC relative reloc when generating embedded PIC code
for ECOFF, we use a Cygnus extension. We check for that here to
make sure that we don't let such a reloc escape normally. */
the current size of the frag should change. */
int
-mips_relax_frag (sec, fragp, stretch)
- asection *sec;
- fragS *fragp;
- long stretch;
+mips_relax_frag (asection *sec, fragS *fragp, long stretch)
{
if (RELAX_BRANCH_P (fragp->fr_subtype))
{
/* Convert a machine dependent frag. */
void
-md_convert_frag (abfd, asec, fragp)
- bfd *abfd ATTRIBUTE_UNUSED;
- segT asec;
- fragS *fragp;
+md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
{
int old, new;
char *fixptr;
fixp->fx_file = fragp->fr_file;
fixp->fx_line = fragp->fr_line;
- md_number_to_chars ((char *)buf, insn, 4);
+ md_number_to_chars (buf, insn, 4);
buf += 4;
}
else
i--;
insn |= i;
/* Branch over the jump. */
- md_number_to_chars ((char *)buf, insn, 4);
+ md_number_to_chars (buf, insn, 4);
buf += 4;
/* Nop */
- md_number_to_chars ((char*)buf, 0, 4);
+ md_number_to_chars (buf, 0, 4);
buf += 4;
if (RELAX_BRANCH_LIKELY (fragp->fr_subtype))
delay slot. */
insn |= i;
- md_number_to_chars ((char *)buf, insn, 4);
+ md_number_to_chars (buf, insn, 4);
buf += 4;
- md_number_to_chars ((char *)buf, 0, 4);
+ md_number_to_chars (buf, 0, 4);
buf += 4;
}
fixp->fx_file = fragp->fr_file;
fixp->fx_line = fragp->fr_line;
- md_number_to_chars ((char*)buf, insn, 4);
+ md_number_to_chars (buf, insn, 4);
buf += 4;
}
else
fixp->fx_file = fragp->fr_file;
fixp->fx_line = fragp->fr_line;
- md_number_to_chars ((char*)buf, insn, 4);
+ md_number_to_chars (buf, insn, 4);
buf += 4;
if (mips_opts.isa == ISA_MIPS1)
{
/* nop */
- md_number_to_chars ((char*)buf, 0, 4);
+ md_number_to_chars (buf, 0, 4);
buf += 4;
}
fixp->fx_file = fragp->fr_file;
fixp->fx_line = fragp->fr_line;
- md_number_to_chars ((char*)buf, insn, 4);
+ md_number_to_chars (buf, insn, 4);
buf += 4;
/* j(al)r $at. */
else
insn = 0x00200008;
- md_number_to_chars ((char*)buf, insn, 4);
+ md_number_to_chars (buf, insn, 4);
buf += 4;
}
}
if (use_extend)
{
- md_number_to_chars ((char *) buf, 0xf000 | extend, 2);
+ md_number_to_chars (buf, 0xf000 | extend, 2);
fragp->fr_fix += 2;
buf += 2;
}
- md_number_to_chars ((char *) buf, insn, 2);
+ md_number_to_chars (buf, insn, 2);
fragp->fr_fix += 2;
buf += 2;
}
fixptr = fragp->fr_literal + fragp->fr_fix;
if (new > 0)
- memcpy (fixptr - old, fixptr, new);
+ memmove (fixptr - old, fixptr, new);
fragp->fr_fix += new - old;
}
back to even for the convenience of the debugger. */
void
-mips_frob_file_after_relocs ()
+mips_frob_file_after_relocs (void)
{
asymbol **syms;
unsigned int count, i;
can not move it. */
void
-mips_define_label (sym)
- symbolS *sym;
+mips_define_label (symbolS *sym)
{
struct insn_label_list *l;
/* Some special processing for a MIPS ELF file. */
void
-mips_elf_final_processing ()
+mips_elf_final_processing (void)
{
/* Write out the register information. */
if (mips_abi != N64_ABI)
if (mips_any_noreorder)
elf_elfheader (stdoutput)->e_flags |= EF_MIPS_NOREORDER;
if (mips_pic != NO_PIC)
+ {
elf_elfheader (stdoutput)->e_flags |= EF_MIPS_PIC;
+ elf_elfheader (stdoutput)->e_flags |= EF_MIPS_CPIC;
+ }
+ if (mips_abicalls)
+ elf_elfheader (stdoutput)->e_flags |= EF_MIPS_CPIC;
/* Set MIPS ELF flags for ASEs. */
if (file_ase_mips16)
/* Fill in an rs_align_code fragment. */
void
-mips_handle_align (fragp)
- fragS *fragp;
+mips_handle_align (fragS *fragp)
{
if (fragp->fr_type != rs_align_code)
return;
}
static void
-md_obj_begin ()
+md_obj_begin (void)
{
}
static void
-md_obj_end ()
+md_obj_end (void)
{
/* check for premature end, nesting errors, etc */
if (cur_proc_ptr)
}
static long
-get_number ()
+get_number (void)
{
int negative = 0;
long val = 0;
case .file implies DWARF-2. */
static void
-s_mips_file (x)
- int x ATTRIBUTE_UNUSED;
+s_mips_file (int x ATTRIBUTE_UNUSED)
{
static int first_file_directive = 0;
/* The .loc directive, implying DWARF-2. */
static void
-s_mips_loc (x)
- int x ATTRIBUTE_UNUSED;
+s_mips_loc (int x ATTRIBUTE_UNUSED)
{
if (!ECOFF_DEBUGGING)
dwarf2_directive_loc (0);
/* The .end directive. */
static void
-s_mips_end (x)
- int x ATTRIBUTE_UNUSED;
+s_mips_end (int x ATTRIBUTE_UNUSED)
{
symbolS *p;
- int maybe_text;
/* Following functions need their own .frame and .cprestore directives. */
mips_frame_reg_valid = 0;
else
p = NULL;
-#ifdef BFD_ASSEMBLER
- if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
- maybe_text = 1;
- else
- maybe_text = 0;
-#else
- if (now_seg != data_section && now_seg != bss_section)
- maybe_text = 1;
- else
- maybe_text = 0;
-#endif
-
- if (!maybe_text)
+ if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) == 0)
as_warn (_(".end not in text section"));
if (!cur_proc_ptr)
#ifdef OBJ_ELF
/* Generate a .pdr section. */
- if (OUTPUT_FLAVOR == bfd_target_elf_flavour && ! ECOFF_DEBUGGING)
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour && ! ECOFF_DEBUGGING
+ && mips_flag_pdr)
{
segT saved_seg = now_seg;
subsegT saved_subseg = now_subseg;
fragp = frag_more (7 * 4);
- md_number_to_chars (fragp, (valueT) cur_proc_ptr->reg_mask, 4);
- md_number_to_chars (fragp + 4, (valueT) cur_proc_ptr->reg_offset, 4);
- md_number_to_chars (fragp + 8, (valueT) cur_proc_ptr->fpreg_mask, 4);
- md_number_to_chars (fragp + 12, (valueT) cur_proc_ptr->fpreg_offset, 4);
- md_number_to_chars (fragp + 16, (valueT) cur_proc_ptr->frame_offset, 4);
- md_number_to_chars (fragp + 20, (valueT) cur_proc_ptr->frame_reg, 4);
- md_number_to_chars (fragp + 24, (valueT) cur_proc_ptr->pc_reg, 4);
+ md_number_to_chars (fragp, cur_proc_ptr->reg_mask, 4);
+ md_number_to_chars (fragp + 4, cur_proc_ptr->reg_offset, 4);
+ md_number_to_chars (fragp + 8, cur_proc_ptr->fpreg_mask, 4);
+ md_number_to_chars (fragp + 12, cur_proc_ptr->fpreg_offset, 4);
+ md_number_to_chars (fragp + 16, cur_proc_ptr->frame_offset, 4);
+ md_number_to_chars (fragp + 20, cur_proc_ptr->frame_reg, 4);
+ md_number_to_chars (fragp + 24, cur_proc_ptr->pc_reg, 4);
subseg_set (saved_seg, saved_subseg);
}
/* The .aent and .ent directives. */
static void
-s_mips_ent (aent)
- int aent;
+s_mips_ent (int aent)
{
symbolS *symbolP;
- int maybe_text;
symbolP = get_symbol ();
if (*input_line_pointer == ',')
|| *input_line_pointer == '-')
get_number ();
-#ifdef BFD_ASSEMBLER
- if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
- maybe_text = 1;
- else
- maybe_text = 0;
-#else
- if (now_seg != data_section && now_seg != bss_section)
- maybe_text = 1;
- else
- maybe_text = 0;
-#endif
-
- if (!maybe_text)
+ if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) == 0)
as_warn (_(".ent or .aent not in text section."));
if (!aent && cur_proc_ptr)
symbol table (in the mdebug section). */
static void
-s_mips_frame (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_mips_frame (int ignore ATTRIBUTE_UNUSED)
{
#ifdef OBJ_ELF
if (OUTPUT_FLAVOR == bfd_target_elf_flavour && ! ECOFF_DEBUGGING)
make reference to the ecoff symbol table (in the mdebug section). */
static void
-s_mips_mask (reg_type)
- char reg_type;
+s_mips_mask (int reg_type)
{
#ifdef OBJ_ELF
if (OUTPUT_FLAVOR == bfd_target_elf_flavour && ! ECOFF_DEBUGGING)
#if 0
static void
-s_loc (x)
- int x;
+s_loc (int x)
{
symbolS *symbolP;
int lineno;
{ "rm5231", 0, ISA_MIPS4, CPU_R5000 },
{ "rm5261", 0, ISA_MIPS4, CPU_R5000 },
{ "rm5721", 0, ISA_MIPS4, CPU_R5000 },
- { "r7000", 0, ISA_MIPS4, CPU_R5000 },
+ { "rm7000", 0, ISA_MIPS4, CPU_RM7000 },
+ { "rm9000", 0, ISA_MIPS4, CPU_RM7000 },
/* MIPS 32 */
- { "4kc", 0, ISA_MIPS32, CPU_MIPS32, },
+ { "4kc", 0, ISA_MIPS32, CPU_MIPS32 },
{ "4km", 0, ISA_MIPS32, CPU_MIPS32 },
{ "4kp", 0, ISA_MIPS32, CPU_MIPS32 },
Note: this function is shared between GCC and GAS. */
static bfd_boolean
-mips_strict_matching_cpu_name_p (canonical, given)
- const char *canonical, *given;
+mips_strict_matching_cpu_name_p (const char *canonical, const char *given)
{
while (*given != 0 && TOLOWER (*given) == TOLOWER (*canonical))
given++, canonical++;
Note: this function is shared between GCC and GAS. */
static bfd_boolean
-mips_matching_cpu_name_p (canonical, given)
- const char *canonical, *given;
+mips_matching_cpu_name_p (const char *canonical, const char *given)
{
/* First see if the name matches exactly, or with a final "000"
turned into "k". */
A similar function exists in GCC. */
static const struct mips_cpu_info *
-mips_parse_cpu (option, cpu_string)
- const char *option, *cpu_string;
+mips_parse_cpu (const char *option, const char *cpu_string)
{
const struct mips_cpu_info *p;
ISA_MIPS* enumeration). */
static const struct mips_cpu_info *
-mips_cpu_info_from_isa (isa)
- int isa;
+mips_cpu_info_from_isa (int isa)
{
int i;
return NULL;
}
+
+static const struct mips_cpu_info *
+mips_cpu_info_from_arch (int arch)
+{
+ int i;
+
+ for (i = 0; mips_cpu_info_table[i].name != NULL; i++)
+ if (arch == mips_cpu_info_table[i].cpu)
+ return (&mips_cpu_info_table[i]);
+
+ return NULL;
+}
\f
static void
-show (stream, string, col_p, first_p)
- FILE *stream;
- const char *string;
- int *col_p;
- int *first_p;
+show (FILE *stream, const char *string, int *col_p, int *first_p)
{
if (*first_p)
{
}
void
-md_show_usage (stream)
- FILE *stream;
+md_show_usage (FILE *stream)
{
int column, first;
size_t i;
-KPIC, -call_shared generate SVR4 position independent code\n\
-non_shared do not generate position independent code\n\
-xgot assume a 32 bit GOT\n\
+-mpdr, -mno-pdr enable/disable creation of .pdr sections\n\
-mabi=ABI create ABI conformant object file for:\n"));
first = 1;
}
enum dwarf2_format
-mips_dwarf2_format ()
+mips_dwarf2_format (void)
{
if (mips_abi == N64_ABI)
{