* config/tc-mips.c: Use USE_STDARG and USE_VARARGS instead of NO_STDARG &c.
* config/tc-mips.c (mips_target_format): Changed to a function, checking flavor and byte order at run time. (md_parse_option, cases OPTION_EB and OPTION_EL): Set target_big_endian here. (md_begin): Not here. * config/tc-mips.h (mips_target_format): Adjust declaration. (TARGET_FORMAT): Call mips_target_format. * config/tc-mips.h (USE_GLOBAL_POINTER_OPT): Define in terms of OUTPUT_FLAVOR. * config/tc-mips.c (g_switch_value, g_switch_seen): Define unconditionally. (md_begin, mips_ip, md_parse_option, s_change_sec, s_option, s_abicalls, nopic_need_relax): Check USE_GLOBAL_POINTER_OPT at run time, instead of compiling conditionally on GPOPT. (GPOPT): Don't define. (md_shortopts): Always include -G. (RDATA_SECTION_NAME): Select at run time. (md_begin): Test for ELF format at run time instead of compile time. (mips_ip, s_change_sec): Ditto. (md_parse_option, cases OPTION_CALL_SHARED and OPTION_NON_SHARED): Ditto. (OPTION_CALL_SHARED, OPTION_NON_SHARED, mips_regmask_frag): Define unconditionally.
This commit is contained in:
parent
2209b19c4e
commit
1dc1e7989f
@ -1,5 +1,5 @@
|
||||
/* tc-mips.c -- assemble code for a MIPS chip.
|
||||
Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
Copyright (C) 1993, 1995 Free Software Foundation, Inc.
|
||||
Contributed by the OSF and Ralph Campbell.
|
||||
Written by Keith Knowles and Ralph Campbell, working independently.
|
||||
Modified for ECOFF and R4000 support by Ian Lance Taylor of Cygnus
|
||||
@ -28,27 +28,20 @@
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#ifndef __STDC__
|
||||
#ifndef NO_STDARG
|
||||
#define NO_STDARG
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NO_STDARG
|
||||
#ifdef USE_STDARG
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#ifndef NO_VARARGS
|
||||
#endif
|
||||
#ifdef USE_VARARGS
|
||||
#include <varargs.h>
|
||||
#endif /* NO_VARARGS */
|
||||
#endif /* NO_STDARG */
|
||||
#endif
|
||||
|
||||
#include "opcode/mips.h"
|
||||
|
||||
#ifdef OBJ_ELF
|
||||
#include "elf/mips.h"
|
||||
#endif
|
||||
|
||||
static char *mips_regmask_frag;
|
||||
#endif
|
||||
|
||||
#define AT 1
|
||||
#define PIC_CALL_REG 25
|
||||
@ -59,51 +52,33 @@ static char *mips_regmask_frag;
|
||||
#define FP 30
|
||||
#define RA 31
|
||||
|
||||
/* Decide whether to do GP reference optimizations based on the object
|
||||
file format. */
|
||||
#undef GPOPT
|
||||
#ifdef OBJ_ECOFF
|
||||
#define GPOPT
|
||||
#endif
|
||||
#ifdef OBJ_ELF
|
||||
#define GPOPT
|
||||
#endif
|
||||
extern int target_big_endian;
|
||||
|
||||
/* The default target format to use. */
|
||||
#ifdef OBJ_AOUT
|
||||
#ifdef TARGET_BYTES_BIG_ENDIAN
|
||||
#define DEFAULT_TARGET_FORMAT "a.out-mips-big"
|
||||
#else
|
||||
#define DEFAULT_TARGET_FORMAT "a.out-mips-little"
|
||||
#endif
|
||||
#endif /* OBJ_AOUT */
|
||||
#ifdef OBJ_ECOFF
|
||||
#ifdef TARGET_BYTES_BIG_ENDIAN
|
||||
#define DEFAULT_TARGET_FORMAT "ecoff-bigmips"
|
||||
#else
|
||||
#define DEFAULT_TARGET_FORMAT "ecoff-littlemips"
|
||||
#endif
|
||||
#endif /* OBJ_ECOFF */
|
||||
#ifdef OBJ_ELF
|
||||
#ifdef TARGET_BYTES_BIG_ENDIAN
|
||||
#define DEFAULT_TARGET_FORMAT "elf32-bigmips"
|
||||
#else
|
||||
#define DEFAULT_TARGET_FORMAT "elf32-littlemips"
|
||||
#endif
|
||||
#endif /* OBJ_ELF */
|
||||
|
||||
const char *mips_target_format = DEFAULT_TARGET_FORMAT;
|
||||
const char *
|
||||
mips_target_format ()
|
||||
{
|
||||
switch (OUTPUT_FLAVOR)
|
||||
{
|
||||
case bfd_target_aout_flavour:
|
||||
return target_big_endian ? "a.out-mips-big" : "a.out-mips-little";
|
||||
case bfd_target_ecoff_flavour:
|
||||
return target_big_endian ? "ecoff-bigmips" : "ecoff-littlemips";
|
||||
case bfd_target_elf_flavour:
|
||||
return target_big_endian ? "elf32-bigmips" : "elf32-littlemips";
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* The name of the readonly data section. */
|
||||
#ifdef OBJ_AOUT
|
||||
#define RDATA_SECTION_NAME ".data"
|
||||
#endif
|
||||
#ifdef OBJ_ECOFF
|
||||
#define RDATA_SECTION_NAME ".rdata"
|
||||
#endif
|
||||
#ifdef OBJ_ELF
|
||||
#define RDATA_SECTION_NAME ".rodata"
|
||||
#endif
|
||||
#define RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \
|
||||
? ".data" \
|
||||
: OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
|
||||
? ".rdata" \
|
||||
: OUTPUT_FLAVOR == bfd_target_elf_flavour \
|
||||
? ".rodata" \
|
||||
: (abort (), ""))
|
||||
|
||||
/* These variables are filled in with the masks of registers used.
|
||||
The object format code reads them and puts them in the appropriate
|
||||
@ -158,12 +133,10 @@ static int mips_nomove;
|
||||
static int mips_noat;
|
||||
static int mips_nobopt;
|
||||
|
||||
#ifdef GPOPT
|
||||
/* The size of the small data section. */
|
||||
static int g_switch_value = 8;
|
||||
/* Whether the -G option was used. */
|
||||
static int g_switch_seen = 0;
|
||||
#endif
|
||||
|
||||
#define N_RMASK 0xc4
|
||||
#define N_VFP 0xd4
|
||||
@ -511,11 +484,6 @@ const pseudo_typeS md_pseudo_table[] =
|
||||
{NULL}
|
||||
};
|
||||
|
||||
const relax_typeS md_relax_table[] =
|
||||
{
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static char *expr_end;
|
||||
|
||||
static expressionS imm_expr;
|
||||
@ -523,9 +491,6 @@ static expressionS offset_expr;
|
||||
static bfd_reloc_code_real_type imm_reloc;
|
||||
static bfd_reloc_code_real_type offset_reloc;
|
||||
|
||||
/* FIXME: This should be handled in a different way. */
|
||||
extern int target_big_endian;
|
||||
|
||||
/*
|
||||
* This function is called once, at assembler startup time. It should
|
||||
* set up all the tables, etc. that the MD part of the assembler will need.
|
||||
@ -682,49 +647,48 @@ md_begin ()
|
||||
/* set the default alignment for the text section (2**2) */
|
||||
record_alignment (text_section, 2);
|
||||
|
||||
/* FIXME: This should be handled in a different way. */
|
||||
target_big_endian = byte_order == BIG_ENDIAN;
|
||||
if (USE_GLOBAL_POINTER_OPT)
|
||||
bfd_set_gp_size (stdoutput, g_switch_value);
|
||||
|
||||
#ifdef GPOPT
|
||||
bfd_set_gp_size (stdoutput, g_switch_value);
|
||||
#endif
|
||||
if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
|
||||
{
|
||||
/* Sections must be aligned to 16 byte boundaries. */
|
||||
(void) bfd_set_section_alignment (stdoutput, text_section, 4);
|
||||
(void) bfd_set_section_alignment (stdoutput, data_section, 4);
|
||||
(void) bfd_set_section_alignment (stdoutput, bss_section, 4);
|
||||
|
||||
/* Create a .reginfo section for register masks and a .mdebug
|
||||
section for debugging information. */
|
||||
{
|
||||
segT seg;
|
||||
subsegT subseg;
|
||||
segT sec;
|
||||
|
||||
seg = now_seg;
|
||||
subseg = now_subseg;
|
||||
sec = subseg_new (".reginfo", (subsegT) 0);
|
||||
|
||||
/* The ABI says this section should be loaded so that the
|
||||
running program can access it. */
|
||||
(void) bfd_set_section_flags (stdoutput, sec,
|
||||
(SEC_ALLOC | SEC_LOAD
|
||||
| SEC_READONLY | SEC_DATA));
|
||||
(void) bfd_set_section_alignment (stdoutput, sec, 2);
|
||||
|
||||
#ifdef OBJ_ELF
|
||||
/* Sections must be aligned to 16 byte boundaries. */
|
||||
(void) bfd_set_section_alignment (stdoutput, text_section, 4);
|
||||
(void) bfd_set_section_alignment (stdoutput, data_section, 4);
|
||||
(void) bfd_set_section_alignment (stdoutput, bss_section, 4);
|
||||
|
||||
/* Create a .reginfo section for register masks and a .mdebug
|
||||
section for debugging information. */
|
||||
{
|
||||
segT seg;
|
||||
subsegT subseg;
|
||||
segT sec;
|
||||
|
||||
seg = now_seg;
|
||||
subseg = now_subseg;
|
||||
sec = subseg_new (".reginfo", (subsegT) 0);
|
||||
|
||||
/* The ABI says this section should be loaded so that the running
|
||||
program can access it. */
|
||||
(void) bfd_set_section_flags (stdoutput, sec,
|
||||
(SEC_ALLOC | SEC_LOAD
|
||||
| SEC_READONLY | SEC_DATA));
|
||||
(void) bfd_set_section_alignment (stdoutput, sec, 2);
|
||||
|
||||
mips_regmask_frag = frag_more (sizeof (Elf32_External_RegInfo));
|
||||
|
||||
#ifdef ECOFF_DEBUGGING
|
||||
sec = subseg_new (".mdebug", (subsegT) 0);
|
||||
(void) bfd_set_section_flags (stdoutput, sec,
|
||||
SEC_HAS_CONTENTS | SEC_READONLY);
|
||||
(void) bfd_set_section_alignment (stdoutput, sec, 2);
|
||||
mips_regmask_frag = frag_more (sizeof (Elf32_External_RegInfo));
|
||||
#endif
|
||||
|
||||
subseg_set (seg, subseg);
|
||||
}
|
||||
#endif /* OBJ_ELF */
|
||||
#ifdef ECOFF_DEBUGGING
|
||||
sec = subseg_new (".mdebug", (subsegT) 0);
|
||||
(void) bfd_set_section_flags (stdoutput, sec,
|
||||
SEC_HAS_CONTENTS | SEC_READONLY);
|
||||
(void) bfd_set_section_alignment (stdoutput, sec, 2);
|
||||
#endif
|
||||
|
||||
subseg_set (seg, subseg);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ECOFF_DEBUGGING
|
||||
md_obj_begin ();
|
||||
@ -1387,7 +1351,7 @@ mips_emit_delays ()
|
||||
expression, the name of the instruction to build, an operand format
|
||||
string, and corresponding arguments. */
|
||||
|
||||
#ifndef NO_STDARG
|
||||
#ifdef USE_STDARG
|
||||
static void
|
||||
macro_build (char *place,
|
||||
int *counter,
|
||||
@ -1395,7 +1359,7 @@ macro_build (char *place,
|
||||
const char *name,
|
||||
const char *fmt,
|
||||
...)
|
||||
#else /* ! defined (NO_STDARG) */
|
||||
#else
|
||||
static void
|
||||
macro_build (place, counter, ep, name, fmt, va_alist)
|
||||
char *place;
|
||||
@ -1404,13 +1368,13 @@ macro_build (place, counter, ep, name, fmt, va_alist)
|
||||
const char *name;
|
||||
const char *fmt;
|
||||
va_dcl
|
||||
#endif /* ! defined (NO_STDARG) */
|
||||
#endif
|
||||
{
|
||||
struct mips_cl_insn insn;
|
||||
bfd_reloc_code_real_type r;
|
||||
va_list args;
|
||||
|
||||
#ifndef NO_STDARG
|
||||
#ifdef USE_STDARG
|
||||
va_start (args, fmt);
|
||||
#else
|
||||
va_start (args);
|
||||
@ -4794,10 +4758,9 @@ mips_ip (str, ip)
|
||||
|
||||
if (*args == 'f'
|
||||
|| (*args == 'l'
|
||||
#ifdef GPOPT
|
||||
&& (mips_pic == EMBEDDED_PIC
|
||||
&& (! USE_GLOBAL_POINTER_OPT
|
||||
|| mips_pic == EMBEDDED_PIC
|
||||
|| g_switch_value < 4)
|
||||
#endif
|
||||
))
|
||||
{
|
||||
imm_expr.X_op = O_constant;
|
||||
@ -4827,28 +4790,24 @@ mips_ip (str, ip)
|
||||
default: /* unused default case avoids warnings. */
|
||||
case 'L':
|
||||
newname = RDATA_SECTION_NAME;
|
||||
#ifdef GPOPT
|
||||
if (g_switch_value >= 8)
|
||||
if (USE_GLOBAL_POINTER_OPT && g_switch_value >= 8)
|
||||
newname = ".lit8";
|
||||
#endif
|
||||
break;
|
||||
case 'F':
|
||||
newname = RDATA_SECTION_NAME;
|
||||
break;
|
||||
case 'l':
|
||||
#ifdef GPOPT
|
||||
assert (g_switch_value >= 4);
|
||||
#endif
|
||||
assert (!USE_GLOBAL_POINTER_OPT
|
||||
|| g_switch_value >= 4);
|
||||
newname = ".lit4";
|
||||
break;
|
||||
}
|
||||
new_seg = subseg_new (newname, (subsegT) 0);
|
||||
frag_align (*args == 'l' ? 2 : 3, 0);
|
||||
#ifdef OBJ_ELF
|
||||
record_alignment (new_seg, 4);
|
||||
#else
|
||||
record_alignment (new_seg, *args == 'l' ? 2 : 3);
|
||||
#endif
|
||||
if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
|
||||
record_alignment (new_seg, 4);
|
||||
else
|
||||
record_alignment (new_seg, *args == 'l' ? 2 : 3);
|
||||
if (seg == now_seg)
|
||||
as_bad ("Can't use floating point insn in this section");
|
||||
|
||||
@ -5227,11 +5186,8 @@ md_number_to_chars (buf, val, n)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GPOPT
|
||||
CONST char *md_shortopts = "O::g::G:";
|
||||
#else
|
||||
CONST char *md_shortopts = "O::g::";
|
||||
#endif
|
||||
|
||||
struct option md_longopts[] = {
|
||||
#define OPTION_MIPS1 (OPTION_MD_BASE + 1)
|
||||
{"mips0", no_argument, NULL, OPTION_MIPS1},
|
||||
@ -5261,11 +5217,11 @@ struct option md_longopts[] = {
|
||||
#define OPTION_NO_M4650 (OPTION_MD_BASE + 14)
|
||||
{"no-m4650", no_argument, NULL, OPTION_NO_M4650},
|
||||
|
||||
#ifdef OBJ_ELF
|
||||
#define OPTION_CALL_SHARED (OPTION_MD_BASE + 7)
|
||||
#define OPTION_NON_SHARED (OPTION_MD_BASE + 8)
|
||||
#ifdef OBJ_ELF
|
||||
{"KPIC", no_argument, NULL, OPTION_CALL_SHARED},
|
||||
{"call_shared", no_argument, NULL, OPTION_CALL_SHARED},
|
||||
#define OPTION_NON_SHARED (OPTION_MD_BASE + 8)
|
||||
{"non_shared", no_argument, NULL, OPTION_NON_SHARED},
|
||||
#endif
|
||||
|
||||
@ -5290,28 +5246,12 @@ md_parse_option (c, arg)
|
||||
|
||||
case OPTION_EB:
|
||||
byte_order = BIG_ENDIAN;
|
||||
#ifdef OBJ_AOUT
|
||||
mips_target_format = "a.out-mips-big";
|
||||
#endif
|
||||
#ifdef OBJ_ECOFF
|
||||
mips_target_format = "ecoff-bigmips";
|
||||
#endif
|
||||
#ifdef OBJ_ELF
|
||||
mips_target_format = "elf32-bigmips";
|
||||
#endif
|
||||
target_big_endian = 1;
|
||||
break;
|
||||
|
||||
case OPTION_EL:
|
||||
byte_order = LITTLE_ENDIAN;
|
||||
#ifdef OBJ_AOUT
|
||||
mips_target_format = "a.out-mips-little";
|
||||
#endif
|
||||
#ifdef OBJ_ECOFF
|
||||
mips_target_format = "ecoff-littlemips";
|
||||
#endif
|
||||
#ifdef OBJ_ELF
|
||||
mips_target_format = "elf32-littlemips";
|
||||
#endif
|
||||
target_big_endian = 0;
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
@ -5444,21 +5384,23 @@ md_parse_option (c, arg)
|
||||
|
||||
case OPTION_MEMBEDDED_PIC:
|
||||
mips_pic = EMBEDDED_PIC;
|
||||
#ifdef GPOPT
|
||||
if (g_switch_seen)
|
||||
if (USE_GLOBAL_POINTER_OPT && g_switch_seen)
|
||||
{
|
||||
as_bad ("-G may not be used with embedded PIC code");
|
||||
return 0;
|
||||
}
|
||||
g_switch_value = 0x7fffffff;
|
||||
#endif
|
||||
break;
|
||||
|
||||
#ifdef OBJ_ELF
|
||||
/* When generating ELF code, we permit -KPIC and -call_shared to
|
||||
select SVR4_PIC, and -non_shared to select no PIC. This is
|
||||
intended to be compatible with Irix 5. */
|
||||
case OPTION_CALL_SHARED:
|
||||
if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
|
||||
{
|
||||
as_bad ("-call_shared is supported only for ELF format");
|
||||
return 0;
|
||||
}
|
||||
mips_pic = SVR4_PIC;
|
||||
if (g_switch_seen && g_switch_value != 0)
|
||||
{
|
||||
@ -5469,13 +5411,21 @@ md_parse_option (c, arg)
|
||||
break;
|
||||
|
||||
case OPTION_NON_SHARED:
|
||||
if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
|
||||
{
|
||||
as_bad ("-non_shared is supported only for ELF format");
|
||||
return 0;
|
||||
}
|
||||
mips_pic = NO_PIC;
|
||||
break;
|
||||
#endif /* OBJ_ELF */
|
||||
|
||||
#ifdef GPOPT
|
||||
case 'G':
|
||||
if (mips_pic == SVR4_PIC || mips_pic == EMBEDDED_PIC)
|
||||
if (! USE_GLOBAL_POINTER_OPT)
|
||||
{
|
||||
as_bad ("-G is not supported for this configuration");
|
||||
return 0;
|
||||
}
|
||||
else if (mips_pic == SVR4_PIC || mips_pic == EMBEDDED_PIC)
|
||||
{
|
||||
as_bad ("-G may not be used with SVR4 or embedded PIC code");
|
||||
return 0;
|
||||
@ -5484,7 +5434,6 @@ md_parse_option (c, arg)
|
||||
g_switch_value = atoi (arg);
|
||||
g_switch_seen = 1;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return 0;
|
||||
@ -5527,15 +5476,14 @@ long
|
||||
md_pcrel_from (fixP)
|
||||
fixS *fixP;
|
||||
{
|
||||
#ifndef OBJ_AOUT
|
||||
if (fixP->fx_addsy != (symbolS *) NULL
|
||||
if (OUTPUT_FLAVOR != bfd_target_aout_flavour
|
||||
&& fixP->fx_addsy != (symbolS *) NULL
|
||||
&& ! S_IS_DEFINED (fixP->fx_addsy))
|
||||
{
|
||||
/* This makes a branch to an undefined symbol be a branch to the
|
||||
current location. */
|
||||
return 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* return the address of the delay slot */
|
||||
return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
|
||||
@ -5965,9 +5913,7 @@ static void
|
||||
s_change_sec (sec)
|
||||
int sec;
|
||||
{
|
||||
#ifdef GPOPT
|
||||
segT seg;
|
||||
#endif
|
||||
|
||||
/* When generating embedded PIC code, we only use the .text, .lit8,
|
||||
.sdata and .sbss sections. We change the .data and .rdata
|
||||
@ -5991,41 +5937,50 @@ s_change_sec (sec)
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
#ifdef GPOPT
|
||||
seg = subseg_new (RDATA_SECTION_NAME,
|
||||
(subsegT) get_absolute_expression ());
|
||||
#ifdef OBJ_ELF
|
||||
bfd_set_section_flags (stdoutput, seg,
|
||||
(SEC_ALLOC
|
||||
| SEC_LOAD
|
||||
| SEC_READONLY
|
||||
| SEC_RELOC
|
||||
| SEC_DATA));
|
||||
bfd_set_section_alignment (stdoutput, seg, 4);
|
||||
#endif
|
||||
demand_empty_rest_of_line ();
|
||||
#else /* ! defined (GPOPT) */
|
||||
as_bad ("No read only data section in this object file format");
|
||||
demand_empty_rest_of_line ();
|
||||
return;
|
||||
#endif /* ! defined (GPOPT) */
|
||||
if (USE_GLOBAL_POINTER_OPT)
|
||||
{
|
||||
seg = subseg_new (RDATA_SECTION_NAME,
|
||||
(subsegT) get_absolute_expression ());
|
||||
if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
|
||||
{
|
||||
bfd_set_section_flags (stdoutput, seg,
|
||||
(SEC_ALLOC
|
||||
| SEC_LOAD
|
||||
| SEC_READONLY
|
||||
| SEC_RELOC
|
||||
| SEC_DATA));
|
||||
bfd_set_section_alignment (stdoutput, seg, 4);
|
||||
}
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
else
|
||||
{
|
||||
as_bad ("No read only data section in this object file format");
|
||||
demand_empty_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 's':
|
||||
#ifdef GPOPT
|
||||
seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
|
||||
#ifdef OBJ_ELF
|
||||
bfd_set_section_flags (stdoutput, seg,
|
||||
SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
|
||||
bfd_set_section_alignment (stdoutput, seg, 4);
|
||||
#endif
|
||||
demand_empty_rest_of_line ();
|
||||
break;
|
||||
#else /* ! defined (GPOPT) */
|
||||
as_bad ("Global pointers not supported; recompile -G 0");
|
||||
demand_empty_rest_of_line ();
|
||||
return;
|
||||
#endif /* ! defined (GPOPT) */
|
||||
if (USE_GLOBAL_POINTER_OPT)
|
||||
{
|
||||
seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
|
||||
if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
|
||||
{
|
||||
bfd_set_section_flags (stdoutput, seg,
|
||||
SEC_ALLOC | SEC_LOAD | SEC_RELOC
|
||||
| SEC_DATA);
|
||||
bfd_set_section_alignment (stdoutput, seg, 4);
|
||||
}
|
||||
demand_empty_rest_of_line ();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
as_bad ("Global pointers not supported; recompile -G 0");
|
||||
demand_empty_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto_align = 1;
|
||||
@ -6172,15 +6127,13 @@ s_option (x)
|
||||
else
|
||||
as_bad (".option pic%d not supported", i);
|
||||
|
||||
#ifdef GPOPT
|
||||
if (mips_pic == SVR4_PIC)
|
||||
if (USE_GLOBAL_POINTER_OPT && mips_pic == SVR4_PIC)
|
||||
{
|
||||
if (g_switch_seen && g_switch_value != 0)
|
||||
as_warn ("-G may not be used with SVR4 PIC code");
|
||||
g_switch_value = 0;
|
||||
bfd_set_gp_size (stdoutput, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
as_warn ("Unrecognized option \"%s\"", opt);
|
||||
@ -6291,11 +6244,12 @@ s_abicalls (ignore)
|
||||
int ignore;
|
||||
{
|
||||
mips_pic = SVR4_PIC;
|
||||
#ifdef GPOPT
|
||||
if (g_switch_seen && g_switch_value != 0)
|
||||
as_warn ("-G may not be used with SVR4 PIC code");
|
||||
g_switch_value = 0;
|
||||
#endif
|
||||
if (USE_GLOBAL_POINTER_OPT)
|
||||
{
|
||||
if (g_switch_seen && g_switch_value != 0)
|
||||
as_warn ("-G may not be used with SVR4 PIC code");
|
||||
g_switch_value = 0;
|
||||
}
|
||||
bfd_set_gp_size (stdoutput, 0);
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
@ -6512,49 +6466,49 @@ static int nopic_need_relax (sym)
|
||||
if (sym == 0)
|
||||
return 0;
|
||||
|
||||
#ifdef GPOPT
|
||||
{
|
||||
const char *symname;
|
||||
int change;
|
||||
if (USE_GLOBAL_POINTER_OPT)
|
||||
{
|
||||
const char *symname;
|
||||
int change;
|
||||
|
||||
/* Find out whether this symbol can be referenced off the GP
|
||||
register. It can be if it is smaller than the -G size or if it
|
||||
is in the .sdata or .sbss section. Certain symbols can not be
|
||||
referenced off the GP, although it appears as though they can. */
|
||||
symname = S_GET_NAME (sym);
|
||||
if (symname != (const char *) NULL
|
||||
&& (strcmp (symname, "eprol") == 0
|
||||
|| strcmp (symname, "etext") == 0
|
||||
|| strcmp (symname, "_gp") == 0
|
||||
|| strcmp (symname, "edata") == 0
|
||||
|| strcmp (symname, "_fbss") == 0
|
||||
|| strcmp (symname, "_fdata") == 0
|
||||
|| strcmp (symname, "_ftext") == 0
|
||||
|| strcmp (symname, "end") == 0
|
||||
|| strcmp (symname, "_gp_disp") == 0))
|
||||
change = 1;
|
||||
else if (! S_IS_DEFINED (sym)
|
||||
&& ((sym->ecoff_extern_size != 0
|
||||
&& sym->ecoff_extern_size <= g_switch_value)
|
||||
|| (S_GET_VALUE (sym) != 0
|
||||
&& S_GET_VALUE (sym) <= g_switch_value)))
|
||||
change = 0;
|
||||
else
|
||||
{
|
||||
const char *segname;
|
||||
/* Find out whether this symbol can be referenced off the GP
|
||||
register. It can be if it is smaller than the -G size or if
|
||||
it is in the .sdata or .sbss section. Certain symbols can
|
||||
not be referenced off the GP, although it appears as though
|
||||
they can. */
|
||||
symname = S_GET_NAME (sym);
|
||||
if (symname != (const char *) NULL
|
||||
&& (strcmp (symname, "eprol") == 0
|
||||
|| strcmp (symname, "etext") == 0
|
||||
|| strcmp (symname, "_gp") == 0
|
||||
|| strcmp (symname, "edata") == 0
|
||||
|| strcmp (symname, "_fbss") == 0
|
||||
|| strcmp (symname, "_fdata") == 0
|
||||
|| strcmp (symname, "_ftext") == 0
|
||||
|| strcmp (symname, "end") == 0
|
||||
|| strcmp (symname, "_gp_disp") == 0))
|
||||
change = 1;
|
||||
else if (! S_IS_DEFINED (sym)
|
||||
&& ((sym->ecoff_extern_size != 0
|
||||
&& sym->ecoff_extern_size <= g_switch_value)
|
||||
|| (S_GET_VALUE (sym) != 0
|
||||
&& S_GET_VALUE (sym) <= g_switch_value)))
|
||||
change = 0;
|
||||
else
|
||||
{
|
||||
const char *segname;
|
||||
|
||||
segname = segment_name (S_GET_SEGMENT (sym));
|
||||
assert (strcmp (segname, ".lit8") != 0
|
||||
&& strcmp (segname, ".lit4") != 0);
|
||||
change = (strcmp (segname, ".sdata") != 0
|
||||
&& strcmp (segname, ".sbss") != 0);
|
||||
}
|
||||
return change;
|
||||
}
|
||||
#else /* ! defined (GPOPT) */
|
||||
/* We are not optimizing for the GP register. */
|
||||
return 1;
|
||||
#endif /* ! defined (GPOPT) */
|
||||
segname = segment_name (S_GET_SEGMENT (sym));
|
||||
assert (strcmp (segname, ".lit8") != 0
|
||||
&& strcmp (segname, ".lit4") != 0);
|
||||
change = (strcmp (segname, ".sdata") != 0
|
||||
&& strcmp (segname, ".sbss") != 0);
|
||||
}
|
||||
return change;
|
||||
}
|
||||
else
|
||||
/* We are not optimizing for the GP register. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
@ -6625,9 +6579,8 @@ tc_gen_reloc (section, fixp)
|
||||
is actually the difference between the reloc address and the
|
||||
subtrahend. */
|
||||
reloc->addend = reloc->address - S_GET_VALUE (fixp->fx_subsy);
|
||||
#ifndef OBJ_ECOFF
|
||||
as_fatal ("Double check fx_r_type in tc-mips.c:tc_gen_reloc");
|
||||
#endif
|
||||
if (OUTPUT_FLAVOR != bfd_target_ecoff_flavour)
|
||||
as_fatal ("Double check fx_r_type in tc-mips.c:tc_gen_reloc");
|
||||
fixp->fx_r_type = BFD_RELOC_GPREL32;
|
||||
}
|
||||
else if (fixp->fx_r_type == BFD_RELOC_PCREL_LO16)
|
||||
@ -6658,13 +6611,12 @@ tc_gen_reloc (section, fixp)
|
||||
reloc->addend = fixp->fx_addnumber;
|
||||
else
|
||||
{
|
||||
#ifndef OBJ_AOUT
|
||||
/* A gruesome hack which is a result of the gruesome gas reloc
|
||||
handling. */
|
||||
reloc->addend = reloc->address;
|
||||
#else
|
||||
reloc->addend = -reloc->address;
|
||||
#endif
|
||||
if (OUTPUT_FLAVOR != bfd_target_aout_flavour)
|
||||
/* A gruesome hack which is a result of the gruesome gas reloc
|
||||
handling. */
|
||||
reloc->addend = reloc->address;
|
||||
else
|
||||
reloc->addend = -reloc->address;
|
||||
}
|
||||
|
||||
/* If this is a variant frag, we may need to adjust the existing
|
||||
@ -6730,12 +6682,11 @@ tc_gen_reloc (section, fixp)
|
||||
/* 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. */
|
||||
#ifdef OBJ_ECOFF
|
||||
if (fixp->fx_r_type == BFD_RELOC_16_PCREL_S2
|
||||
if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour
|
||||
&& fixp->fx_r_type == BFD_RELOC_16_PCREL_S2
|
||||
&& mips_pic != EMBEDDED_PIC)
|
||||
reloc->howto = NULL;
|
||||
else
|
||||
#endif
|
||||
reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
|
||||
|
||||
if (reloc->howto == NULL)
|
||||
|
@ -33,52 +33,36 @@
|
||||
#define MAX_RELOC_EXPANSION 3
|
||||
#define LOCAL_LABELS_FB
|
||||
|
||||
#define LOCAL_LABEL(name) ((name)[0] == '$')
|
||||
/* The MIPS assembler appears to keep all symbols. */
|
||||
#define LOCAL_LABEL(name) 0
|
||||
|
||||
#define md_relax_frag(fragp, stretch) (0)
|
||||
#define md_undefined_symbol(name) (0)
|
||||
#define md_operand(x)
|
||||
|
||||
/* We permit PC relative difference expressions when generating
|
||||
embedded PIC code. */
|
||||
#define DIFF_EXPR_OK
|
||||
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#define BIG_ENDIAN 4321
|
||||
|
||||
/* If neither TARGET_BYTES_BIG_ENDIAN nor TARGET_BYTES_LITTLE_ENDIAN
|
||||
is specified, default to big endian. */
|
||||
#ifndef TARGET_BYTES_BIG_ENDIAN
|
||||
/* Default to big endian. */
|
||||
#ifndef TARGET_BYTES_LITTLE_ENDIAN
|
||||
#define TARGET_BYTES_BIG_ENDIAN
|
||||
#endif
|
||||
#undef TARGET_BYTES_BIG_ENDIAN
|
||||
#define TARGET_BYTES_BIG_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_BYTES_BIG_ENDIAN
|
||||
#if TARGET_BYTES_BIG_ENDIAN
|
||||
#define BYTE_ORDER BIG_ENDIAN
|
||||
#else
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_FORMAT
|
||||
#ifdef OBJ_AOUT
|
||||
#ifdef TARGET_BYTES_BIG_ENDIAN
|
||||
#define TARGET_FORMAT "a.out-mips-big"
|
||||
#else
|
||||
#define TARGET_FORMAT "a.out-mips-little"
|
||||
#endif
|
||||
#endif /* OBJ_AOUT */
|
||||
#ifdef OBJ_ECOFF
|
||||
#ifdef TARGET_BYTES_BIG_ENDIAN
|
||||
#define TARGET_FORMAT "ecoff-bigmips"
|
||||
#else
|
||||
#define TARGET_FORMAT "ecoff-littlemips"
|
||||
#endif
|
||||
#endif /* OBJ_ECOFF */
|
||||
#ifdef OBJ_ELF
|
||||
#ifdef TARGET_BYTES_BIG_ENDIAN
|
||||
#define TARGET_FORMAT "elf32-bigmips"
|
||||
#else
|
||||
#define TARGET_FORMAT "elf32-littlemips"
|
||||
#endif
|
||||
#endif /* OBJ_ELF */
|
||||
#endif /* ! defined (TARGET_FORMAT) */
|
||||
/* The endianness of the target format may change based on command
|
||||
line arguments. */
|
||||
#define TARGET_FORMAT mips_target_format()
|
||||
extern const char *mips_target_format ();
|
||||
|
||||
struct mips_cl_insn {
|
||||
unsigned long insn_opcode;
|
||||
@ -87,12 +71,23 @@ struct mips_cl_insn {
|
||||
|
||||
extern int tc_get_register PARAMS ((int frame));
|
||||
|
||||
#define md_parse_long_option(arg) mips_parse_long_option (arg)
|
||||
extern int mips_parse_long_option PARAMS ((const char *));
|
||||
|
||||
#define tc_frob_label(sym) mips_define_label (sym)
|
||||
extern void mips_define_label PARAMS ((struct symbol *));
|
||||
|
||||
#define TC_CONS_FIX_NEW cons_fix_new_mips
|
||||
extern void cons_fix_new_mips ();
|
||||
|
||||
/* When generating embedded PIC code we must keep PC relative
|
||||
relocations. */
|
||||
#define TC_FORCE_RELOCATION(fixp) mips_force_relocation (fixp)
|
||||
extern int mips_force_relocation ();
|
||||
|
||||
/* md_apply_fix sets fx_done correctly. */
|
||||
#define TC_HANDLE_FX_DONE 1
|
||||
|
||||
/* Register mask variables. These are set by the MIPS assembly code
|
||||
and used by ECOFF and possibly other object file formats. */
|
||||
extern unsigned long mips_gprmask;
|
||||
@ -117,3 +112,6 @@ extern void mips_elf_final_processing PARAMS ((void));
|
||||
|
||||
extern void md_mips_end PARAMS ((void));
|
||||
#define md_end() md_mips_end()
|
||||
|
||||
#define USE_GLOBAL_POINTER_OPT (OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
|
||||
|| OUTPUT_FLAVOR == bfd_target_elf_flavour)
|
||||
|
Loading…
Reference in New Issue
Block a user