* config/obj-coff.h (TC_SPARC): Don't define TARGET_FORMAT.

* config/tc-sparc.c (sparc_target_format): Handle coff here.
	(sparc_ip): Add %hix,%lox.
	(md_apply_fix3): Call as_bad_where, not as_bad.
	Add support for BFD_RELOC_SPARC_{HIX22,LOX10}.
	(tc_gen_reloc): Add support for BFD_RELOC_SPARC_{HIX22,LOX10}.
This commit is contained in:
David Edelsohn 1997-10-08 23:13:52 +00:00
parent 2f0e18834b
commit 54b9ebdd55
3 changed files with 356 additions and 170 deletions

View File

@ -1,3 +1,12 @@
Wed Oct 8 16:11:15 1997 Doug Evans <dje@canuck.cygnus.com>
* config/obj-coff.h (TC_SPARC): Don't define TARGET_FORMAT.
* config/tc-sparc.c (sparc_target_format): Handle coff here.
(sparc_ip): Add %hix,%lox.
(md_apply_fix3): Call as_bad_where, not as_bad.
Add support for BFD_RELOC_SPARC_{HIX22,LOX10}.
(tc_gen_reloc): Add support for BFD_RELOC_SPARC_{HIX22,LOX10}.
Wed Oct 8 12:33:32 1997 Richard Henderson <rth@cygnus.com>
* configure.in: Change alpha-*-* to alpha*-*-*; config.guess now

View File

@ -1,5 +1,6 @@
/* coff object file format
Copyright (C) 1989, 1990, 1991, 1992, 1994 Free Software Foundation, Inc.
Copyright (C) 1989, 90, 91, 92, 94, 95, 96, 1997
Free Software Foundation, Inc.
This file is part of GAS.
@ -14,8 +15,9 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
along with GAS; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
#ifndef OBJ_FORMAT_H
#define OBJ_FORMAT_H
@ -46,26 +48,21 @@
#ifdef TC_ARM
#include "coff/arm.h"
#ifdef TE_PE
#define TARGET_FORMAT "pe-arm"
#endif
#ifndef TARGET_FORMAT
#define TARGET_FORMAT "coff-arm"
#endif
#endif
#ifdef TC_PPC
#ifdef TE_PE
#include "coff/powerpc.h"
#else
#include "coff/rs6000.h"
#endif
#endif
#ifdef TC_SPARC
#include "coff/sparc.h"
#ifdef TE_LYNX
#define TARGET_FORMAT "coff-sparc-lynx"
#else
#define TARGET_FORMAT "coff-sparc"
#endif
#endif
#ifdef TC_I386
@ -127,6 +124,14 @@
#define TARGET_FORMAT "coff-w65"
#endif
/* start-sanitize-tic80 */
#ifdef TC_TIC80
#include "coff/tic80.h"
#define TARGET_FORMAT "coff-tic80"
#define ALIGNMENT_IN_S_FLAGS 1
#endif
/* end-sanitize-tic80 */
/* Targets may also set this. Also, if BFD_ASSEMBLER is defined, this
will already have been defined. */
#undef SYMBOLS_NEED_BACKPOINTERS
@ -136,6 +141,12 @@
#define OBJ_COFF_MAX_AUXENTRIES 1
#endif /* OBJ_COFF_MAX_AUXENTRIES */
extern void coff_obj_symbol_new_hook PARAMS ((struct symbol *));
#define obj_symbol_new_hook coff_obj_symbol_new_hook
extern void coff_obj_read_begin_hook PARAMS ((void));
#define obj_read_begin_hook coff_obj_read_begin_hook
/* ***********************************************************************
This file really contains two implementations of the COFF back end.
@ -197,7 +208,6 @@
#define SYM_AUXENT(S) (&coffsymbol ((S)->bsym)->native[1].u.auxent)
#define DO_NOT_STRIP 0
#define DO_STRIP 1
extern void obj_coff_section PARAMS ((int));
@ -319,6 +329,7 @@ extern void SA_SET_SYM_ENDNDX PARAMS ((struct symbol *, struct symbol *));
/* -------------- Line number handling ------- */
extern int text_lineno_number;
extern int coff_line_base;
extern int coff_n_line_nos;
#define obj_emit_lineno(WHERE,LINE,FILE_START) abort ()
extern void coff_add_linesym PARAMS ((struct symbol *));
@ -331,11 +342,11 @@ extern void coff_frob_symbol PARAMS ((struct symbol *, int *));
extern void coff_adjust_symtab PARAMS ((void));
extern void coff_frob_section PARAMS ((segT));
extern void coff_adjust_section_syms PARAMS ((bfd *, asection *, PTR));
extern void coff_frob_file PARAMS ((void));
extern void coff_frob_file_after_relocs PARAMS ((void));
#define obj_frob_symbol(S,P) coff_frob_symbol(S,&P)
#define obj_adjust_symtab() coff_adjust_symtab()
#define obj_frob_section(S) coff_frob_section (S)
#define obj_frob_file() coff_frob_file ()
#define obj_frob_file_after_relocs() coff_frob_file_after_relocs ()
extern struct symbol *coff_last_function;
@ -401,7 +412,6 @@ typedef struct
#ifndef DO_NOT_STRIP
#define DO_NOT_STRIP 0
#define DO_STRIP 1
#endif
/* Symbol table macros and constants */
@ -414,7 +424,7 @@ typedef struct
#define C_DEBUG_SECTION N_DEBUG
#define C_NTV_SECTION N_TV
#define C_PTV_SECTION P_TV
#define C_REGISTER_SECTION 20
#define C_REGISTER_SECTION 50
/*
* Macros to extract information from a symbol table entry.
@ -439,8 +449,9 @@ typedef struct
/* A symbol name whose name includes ^A is a gas internal pseudo symbol */
#define S_IS_LOCAL(s) \
((s)->sy_symbol.ost_entry.n_scnum == C_REGISTER_SECTION \
|| (S_LOCAL_NAME(s) && !flag_keep_locals) \
|| (strchr (S_GET_NAME (s), '\001') != NULL))
|| (S_LOCAL_NAME(s) && ! flag_keep_locals && ! S_IS_DEBUG (s)) \
|| strchr (S_GET_NAME (s), '\001') != NULL \
|| strchr (S_GET_NAME (s), '\002') != NULL)
/* True if a symbol is not defined in this file */
#define S_IS_EXTERN(s) ((s)->sy_symbol.ost_entry.n_scnum == 0 \
&& S_GET_VALUE (s) == 0)
@ -550,6 +561,7 @@ typedef struct
#define SF_TAG (0x00080000) /* Is a tag */
#define SF_DEBUG (0x00100000) /* Is in debug or abs section */
#define SF_GET_SEGMENT (0x00200000) /* Get the section of the forward symbol. */
#define SF_ADJ_LNNOPTR (0x00400000) /* Has a lnnoptr */
/* All other bits are unused. */
/* Accessors */
@ -567,6 +579,7 @@ typedef struct
#define SF_GET_TAGGED(s) (SF_GET (s) & SF_TAGGED)
#define SF_GET_TAG(s) (SF_GET (s) & SF_TAG)
#define SF_GET_GET_SEGMENT(s) (SF_GET (s) & SF_GET_SEGMENT)
#define SF_GET_ADJ_LNNOPTR(s) (SF_GET (s) & SF_ADJ_LNNOPTR)
#define SF_GET_I960(s) (SF_GET (s) & SF_I960_MASK) /* used by i960 */
#define SF_GET_BALNAME(s) (SF_GET (s) & SF_BALNAME) /* used by i960 */
#define SF_GET_CALLNAME(s) (SF_GET (s) & SF_CALLNAME) /* used by i960 */
@ -589,6 +602,7 @@ typedef struct
#define SF_SET_TAGGED(s) (SF_GET (s) |= SF_TAGGED)
#define SF_SET_TAG(s) (SF_GET (s) |= SF_TAG)
#define SF_SET_GET_SEGMENT(s) (SF_GET (s) |= SF_GET_SEGMENT)
#define SF_SET_ADJ_LNNOPTR(s) (SF_GET (s) |= SF_ADJ_LNNOPTR)
#define SF_SET_I960(s,v) (SF_GET (s) |= ((v) & SF_I960_MASK)) /* used by i960 */
#define SF_SET_BALNAME(s) (SF_GET (s) |= SF_BALNAME) /* used by i960 */
#define SF_SET_CALLNAME(s) (SF_GET (s) |= SF_CALLNAME) /* used by i960 */
@ -768,6 +782,11 @@ extern struct internal_scnhdr text_section_header;
? (S_SET_SEGMENT (dest, S_GET_SEGMENT (src)), 0) \
: 0)
#ifdef TE_PE
#define obj_handle_link_once(t) obj_coff_pe_handle_link_once (t)
extern void obj_coff_pe_handle_link_once ();
#endif
#endif /* not BFD_ASSEMBLER */
/* Stabs in a coff file go into their own section. */

View File

@ -24,11 +24,13 @@
#include "as.h"
#include "subsegs.h"
/* careful, this file includes data *declarations* */
#include "opcode/sparc.h"
static struct sparc_arch *lookup_arch PARAMS ((char *));
static void init_default_arch PARAMS ((void));
static void sparc_ip PARAMS ((char *, const struct sparc_opcode **));
static int in_signed_range PARAMS ((bfd_signed_vma, bfd_signed_vma));
static int in_unsigned_range PARAMS ((bfd_vma, bfd_vma));
static int in_bitfield_range PARAMS ((bfd_signed_vma, bfd_signed_vma));
static int sparc_ffs PARAMS ((unsigned int));
static bfd_vma BSR PARAMS ((bfd_vma, int));
@ -37,6 +39,19 @@ static int parse_keyword_arg PARAMS ((int (*) (const char *), char **, int *));
static int parse_const_expr_arg PARAMS ((char **, int *));
static int get_expression PARAMS ((char *str));
/* Default architecture. */
/* ??? The default value should be V8, but sparclite support was added
by making it the default. GCC now passes -Asparclite, so maybe sometime in
the future we can set this to V8. */
#ifndef DEFAULT_ARCH
#define DEFAULT_ARCH "sparclite"
#endif
static char *default_arch = DEFAULT_ARCH;
/* Non-zero if the initial values of `max_architecture' and `sparc_arch_size'
have been set. */
static int default_init_p;
/* Current architecture. We don't bump up unless necessary. */
static enum sparc_opcode_arch_val current_architecture = SPARC_OPCODE_ARCH_V6;
@ -44,15 +59,11 @@ static enum sparc_opcode_arch_val current_architecture = SPARC_OPCODE_ARCH_V6;
In a 32 bit environment, don't allow bumping up to v9 by default.
The native assembler works this way. The user is required to pass
an explicit argument before we'll create v9 object files. However, if
we don't see any v9 insns, a v9 object file is not created. */
#ifdef SPARC_ARCH64
static enum sparc_opcode_arch_val max_architecture = SPARC_OPCODE_ARCH_V9;
#else
/* ??? This should be V8, but sparclite support was added by making it the
default. GCC now passes -Asparclite, so maybe sometime in the future
we can set this to V8. */
static enum sparc_opcode_arch_val max_architecture = SPARC_OPCODE_ARCH_SPARCLITE;
#endif
we don't see any v9 insns, a v8plus object file is not created. */
static enum sparc_opcode_arch_val max_architecture;
/* Either 32 or 64, selects file format. */
static int sparc_arch_size;
static int architecture_requested;
static int warn_on_bump;
@ -164,6 +175,103 @@ struct sparc_it the_insn, set_insn;
static void output_insn
PARAMS ((const struct sparc_opcode *, struct sparc_it *));
/* Table of arguments to -A.
The sparc_opcode_arch table in sparc-opc.c is insufficient and incorrect
for this use. That table is for opcodes only. This table is for opcodes
and file formats. */
static struct sparc_arch {
char *name;
char *opcode_arch;
int arch_size;
} sparc_arch_table[] = {
{ "v6", "v6", 32 },
{ "v7", "v7", 32 },
{ "v8", "v8", 32 },
{ "sparclet", "sparclet", 32 },
{ "sparclite", "sparclite", 32 },
{ "v8plus", "v9", 32 },
{ "v8plusa", "v9a", 32 },
#ifdef BFD64
{ "v9", "v9", 64 },
{ "v9a", "v9a", 64 },
#endif
{ NULL, NULL, 0 }
};
static struct sparc_arch *
lookup_arch (name)
char *name;
{
struct sparc_arch *sa;
for (sa = &sparc_arch_table[0]; sa->name != NULL; sa++)
if (strcmp (sa->name, name) == 0)
break;
if (sa->name == NULL)
return NULL;
return sa;
}
/* Initialize the default opcode arch and word size from the default
architecture name. */
static void
init_default_arch ()
{
struct sparc_arch *sa = lookup_arch (default_arch);
if (sa == NULL)
as_fatal ("Invalid default architecture, broken assembler.");
max_architecture = sparc_opcode_lookup_arch (sa->opcode_arch);
if (max_architecture == SPARC_OPCODE_ARCH_BAD)
as_fatal ("Bad opcode table, broken assembler.");
sparc_arch_size = sa->arch_size;
default_init_p = 1;
}
/* Called by TARGET_FORMAT. */
const char *
sparc_target_format ()
{
/* We don't get a chance to initialize anything before we're called,
so handle that now. */
if (! default_init_p)
init_default_arch ();
#ifdef OBJ_AOUT
#ifdef TE_NetBSD
return "a.out-sparc-netbsd";
#else
#ifdef TE_SPARCAOUT
return target_big_endian ? "a.out-sunos-big" : "a.out-sparc-little";
#else
return "a.out-sunos-big";
#endif
#endif
#endif
#ifdef OBJ_BOUT
return "b.out.big";
#endif
#ifdef OBJ_COFF
#ifdef TE_LYNX
return "coff-sparc-lynx";
#else
return "coff-sparc";
#endif
#endif
#ifdef OBJ_ELF
return sparc_arch_size == 64 ? "elf64-sparc" : "elf32-sparc";
#endif
abort ();
}
/*
* md_parse_option
* Invocation line includes a switch not recognized by the base assembler.
@ -186,10 +294,9 @@ static void output_insn
* architecture cause fatal errors.
*
* The default is to start at v6, and bump the architecture up
* whenever an instruction is seen at a higher level. If 32 bit
* environments, v9 is not bumped up to, the user must pass -Av9.
*
* -xarch=v8plus{,a} is for compatibility with the Sun assembler.
* whenever an instruction is seen at a higher level. In 32 bit
* environments, v9 is not bumped up to, the user must pass
* -Av8plus{,a}.
*
* If -bump is specified, a warning is printing when bumping to
* higher levels.
@ -197,15 +304,15 @@ static void output_insn
* If an architecture is specified, all instructions must match
* that architecture. Any higher level instructions are flagged
* as errors. Note that in the 32 bit environment specifying
* -Av9 does not automatically create a v9 object file, a v9
* insn must be seen.
* -Av8plus does not automatically create a v8plus object file, a
* v9 insn must be seen.
*
* If both an architecture and -bump are specified, the
* architecture starts at the specified level, but bumps are
* warnings. Note that we can't set `current_architecture' to
* the requested level in this case: in the 32 bit environment,
* we still must avoid creating v9 object files unless v9 insns
* are seen.
* we still must avoid creating v8plus object files unless v9
* insns are seen.
*
* Note:
* Bumping between incompatible architectures is always an
@ -245,6 +352,11 @@ md_parse_option (c, arg)
int c;
char *arg;
{
/* We don't get a chance to initialize anything before we're called,
so handle that now. */
if (! default_init_p)
init_default_arch ();
switch (c)
{
case OPTION_BUMP:
@ -253,16 +365,9 @@ md_parse_option (c, arg)
break;
case OPTION_XARCH:
/* This is for compatibility with Sun's assembler.
We could add v8plus and v8plusa to sparc_opcode_archs,
but that table is used to describe architectures whereas here we
want the argument to describe *both* the architecture and the file
format. */
if (strcmp (arg, "v8plus") == 0)
arg = "v9";
else if (strcmp (arg, "v8plusa") == 0)
arg = "v9a";
else
/* This is for compatibility with Sun's assembler. */
if (strcmp (arg, "v8plus") != 0
&& strcmp (arg, "v8plusa") != 0)
{
as_bad ("invalid architecture -xarch=%s", arg);
return 0;
@ -272,15 +377,22 @@ md_parse_option (c, arg)
case 'A':
{
enum sparc_opcode_arch_val new_arch = sparc_opcode_lookup_arch (arg);
struct sparc_arch *sa;
enum sparc_opcode_arch_val opcode_arch;
if (new_arch == SPARC_OPCODE_ARCH_BAD)
sa = lookup_arch (arg);
if (sa == NULL)
{
as_bad ("invalid architecture -A%s", arg);
return 0;
}
max_architecture = new_arch;
opcode_arch = sparc_opcode_lookup_arch (sa->opcode_arch);
if (opcode_arch == SPARC_OPCODE_ARCH_BAD)
as_fatal ("Bad opcode table, broken assembler.");
max_architecture = opcode_arch;
sparc_arch_size = sa->arch_size;
architecture_requested = 1;
}
break;
@ -345,12 +457,12 @@ void
md_show_usage (stream)
FILE *stream;
{
const struct sparc_opcode_arch *arch;
const struct sparc_arch *arch;
fprintf(stream, "SPARC options:\n");
for (arch = &sparc_opcode_archs[0]; arch->name; arch++)
for (arch = &sparc_arch_table[0]; arch->name; arch++)
{
if (arch != &sparc_opcode_archs[0])
if (arch != &sparc_arch_table[0])
fprintf (stream, " | ");
fprintf (stream, "-A%s", arch->name);
}
@ -430,6 +542,12 @@ md_begin ()
int lose = 0;
register unsigned int i = 0;
/* We don't get a chance to initialize anything before md_parse_option
is called, and it may not be called, so handle default initialization
now if not already done. */
if (! default_init_p)
init_default_arch ();
op_hash = hash_new ();
while (i < sparc_num_opcodes)
@ -501,26 +619,29 @@ md_begin ()
void
sparc_md_end ()
{
#ifdef SPARC_ARCH64
if (current_architecture == SPARC_OPCODE_ARCH_V9A)
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v9a);
else
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v9);
#else
if (current_architecture == SPARC_OPCODE_ARCH_V9)
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v8plus);
else if (current_architecture == SPARC_OPCODE_ARCH_V9A)
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v8plusa);
else if (current_architecture == SPARC_OPCODE_ARCH_SPARCLET)
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_sparclet);
if (sparc_arch_size == 64)
{
if (current_architecture == SPARC_OPCODE_ARCH_V9A)
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v9a);
else
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v9);
}
else
{
/* The sparclite is treated like a normal sparc. Perhaps it shouldn't
be but for now it is (since that's the way it's always been
treated). */
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc);
if (current_architecture == SPARC_OPCODE_ARCH_V9)
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v8plus);
else if (current_architecture == SPARC_OPCODE_ARCH_V9A)
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v8plusa);
else if (current_architecture == SPARC_OPCODE_ARCH_SPARCLET)
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_sparclet);
else
{
/* The sparclite is treated like a normal sparc. Perhaps it shouldn't
be but for now it is (since that's the way it's always been
treated). */
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc);
}
}
#endif
}
/* Return non-zero if VAL is in the range -(MAX+1) to MAX. */
@ -538,6 +659,17 @@ in_signed_range (val, max)
return 1;
}
/* Return non-zero if VAL is in the range 0 to MAX. */
static INLINE int
in_unsigned_range (val, max)
bfd_vma val, max;
{
if (val > max)
return 0;
return 1;
}
/* Return non-zero if VAL is in the range -(MAX/2+1) to MAX.
(e.g. -15 to +31). */
@ -885,7 +1017,6 @@ sparc_ip (str, pinsn)
unsigned int mask = 0;
int match = 0;
int comma = 0;
long immediate_max = 0;
int v9_arg_p;
for (s = str; islower (*s) || (*s >= '0' && *s <= '3'); ++s)
@ -1090,12 +1221,10 @@ sparc_ip (str, pinsn)
case 'I':
the_insn.reloc = BFD_RELOC_SPARC_11;
immediate_max = 0x03FF;
goto immediate;
case 'j':
the_insn.reloc = BFD_RELOC_SPARC_10;
immediate_max = 0x01FF;
goto immediate;
case 'X':
@ -1106,7 +1235,6 @@ sparc_ip (str, pinsn)
the_insn.reloc = BFD_RELOC_SPARC13;
/* These fields are unsigned, but for upward compatibility,
allow negative values as well. */
immediate_max = 0x1f;
goto immediate;
case 'Y':
@ -1117,7 +1245,6 @@ sparc_ip (str, pinsn)
the_insn.reloc = BFD_RELOC_SPARC13;
/* These fields are unsigned, but for upward compatibility,
allow negative values as well. */
immediate_max = 0x3f;
goto immediate;
case 'k':
@ -1559,44 +1686,57 @@ sparc_ip (str, pinsn)
case 'i': /* 13 bit immediate */
the_insn.reloc = BFD_RELOC_SPARC13;
immediate_max = 0x0FFF;
/*FALLTHROUGH */
/* fallthrough */
immediate:
if (*s == ' ')
s++;
/* Check for %hi, etc. */
if (*s == '%')
{
if ((c = s[1]) == 'h' && s[2] == 'i')
{
the_insn.reloc = BFD_RELOC_HI22;
s += 3;
}
else if (c == 'l' && s[2] == 'o')
{
the_insn.reloc = BFD_RELOC_LO10;
s += 3;
}
else if (c == 'u'
&& s[2] == 'h'
&& s[3] == 'i')
{
the_insn.reloc = BFD_RELOC_SPARC_HH22;
s += 4;
v9_arg_p = 1;
}
else if (c == 'u'
&& s[2] == 'l'
&& s[3] == 'o')
{
the_insn.reloc = BFD_RELOC_SPARC_HM10;
s += 4;
v9_arg_p = 1;
}
else
static struct ops {
/* The name as it appears in assembler. */
char *name;
/* strlen (name), precomputed for speed */
int len;
/* The reloc this pseudo-op translates to. */
int reloc;
/* Non-zero if for v9 only. */
int v9_p;
/* Non-zero if can be used in pc-relative contexts. */
int pcrel_p;/*FIXME:wip*/
} ops[] = {
/* hix/lox must appear before hi/lo so %hix won't be
mistaken for %hi. */
{ "hix", 3, BFD_RELOC_SPARC_HIX22, 1, 0 },
{ "lox", 3, BFD_RELOC_SPARC_LOX10, 1, 0 },
{ "hi", 2, BFD_RELOC_HI22, 0, 1 },
{ "lo", 2, BFD_RELOC_LO10, 0, 1 },
{ "hh", 2, BFD_RELOC_SPARC_HH22, 1, 1 },
{ "hm", 2, BFD_RELOC_SPARC_HM10, 1, 1 },
{ "lm", 2, BFD_RELOC_SPARC_LM22, 1, 1 },
{ "h44", 3, BFD_RELOC_SPARC_H44, 1, 0 },
{ "m44", 3, BFD_RELOC_SPARC_M44, 1, 0 },
{ "l44", 3, BFD_RELOC_SPARC_L44, 1, 0 },
{ "uhi", 3, BFD_RELOC_SPARC_HH22, 1, 0 },
{ "ulo", 3, BFD_RELOC_SPARC_HM10, 1, 0 },
{ NULL }
};
struct ops *o;
for (o = ops; o->name; o++)
if (strncmp (s + 1, o->name, o->len) == 0)
break;
if (o->name == NULL)
break;
the_insn.reloc = o->reloc;
s += o->len + 1;
v9_arg_p = o->v9_p;
}
/* Note that if the get_expression() fails, we will still
have created U entries in the symbol table for the
'symbols' in the input string. Try not to create U
@ -1636,70 +1776,30 @@ sparc_ip (str, pinsn)
(void) get_expression (s);
s = expr_end;
/* Check for constants that don't require emitting a reloc. */
if (the_insn.exp.X_op == O_constant
&& the_insn.exp.X_add_symbol == 0
&& the_insn.exp.X_op_symbol == 0)
{
/* Handle %uhi/%ulo by moving the upper word to the lower
one and pretending it's %hi/%lo. We also need to watch
for %hi/%lo: the top word needs to be zeroed otherwise
fixup_segment will complain the value is too big. */
switch (the_insn.reloc)
{
case BFD_RELOC_SPARC_HH22:
the_insn.reloc = BFD_RELOC_HI22;
the_insn.exp.X_add_number = BSR (the_insn.exp.X_add_number, 32);
break;
case BFD_RELOC_SPARC_HM10:
the_insn.reloc = BFD_RELOC_LO10;
the_insn.exp.X_add_number = BSR (the_insn.exp.X_add_number, 32);
break;
case BFD_RELOC_HI22:
case BFD_RELOC_LO10:
the_insn.exp.X_add_number &= 0xffffffff;
break;
default:
break;
}
/* For pc-relative call instructions, we reject
constants to get better code. */
if (the_insn.pcrel
&& the_insn.reloc == BFD_RELOC_32_PCREL_S2
&& in_signed_range (the_insn.exp.X_add_number, 0x3fff)
)
&& in_signed_range (the_insn.exp.X_add_number, 0x3fff))
{
error_message = ": PC-relative operand can't be a constant";
goto error;
}
/* Check for invalid constant values. Don't warn if
constant was inside %hi or %lo, since these
truncate the constant to fit. */
if (immediate_max != 0
&& the_insn.reloc != BFD_RELOC_LO10
&& the_insn.reloc != BFD_RELOC_HI22
&& !in_signed_range (the_insn.exp.X_add_number,
immediate_max)
)
{
if (the_insn.pcrel)
/* Who knows? After relocation, we may be within
range. Let the linker figure it out. */
{
the_insn.exp.X_op = O_symbol;
the_insn.exp.X_add_symbol = section_symbol (absolute_section);
}
else
/* Immediate value is non-pcrel, and out of
range. */
as_bad ("constant value %ld out of range (%ld .. %ld)",
the_insn.exp.X_add_number,
~immediate_max, immediate_max);
}
}
/* Reset to prevent extraneous range check. */
immediate_max = 0;
/* Constants that won't fit are checked in md_apply_fix3
and bfd_install_relocation.
??? It would be preferable to install the constants
into the insn here and save having to create a fixS
for each one. There already exists code to handle
all the various cases (e.g. in md_apply_fix3 and
bfd_install_relocation) so duplicating all that code
here isn't right. */
}
continue;
@ -2069,12 +2169,17 @@ output_insn (insn, the_insn)
/* put out the symbol-dependent stuff */
if (the_insn->reloc != BFD_RELOC_NONE)
{
fix_new_exp (frag_now, /* which frag */
(toP - frag_now->fr_literal), /* where */
4, /* size */
&the_insn->exp,
the_insn->pcrel,
the_insn->reloc);
fixS *fixP = fix_new_exp (frag_now, /* which frag */
(toP - frag_now->fr_literal), /* where */
4, /* size */
&the_insn->exp,
the_insn->pcrel,
the_insn->reloc);
/* Turn off overflow checking in fixup_segment. We'll do our
own overflow checking in md_apply_fix3. This is necessary because
the insn size is 4 and fixup_segment will signal an overflow for
large 8 byte quantities. */
fixP->fx_no_overflow = 1;
}
last_insn = insn;
@ -2288,25 +2393,31 @@ md_apply_fix3 (fixP, value, segment)
case BFD_RELOC_SPARC_11:
if (! in_signed_range (val, 0x7ff))
as_bad ("relocation overflow.");
as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
insn |= val & 0x7ff;
break;
case BFD_RELOC_SPARC_10:
if (! in_signed_range (val, 0x3ff))
as_bad ("relocation overflow.");
as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
insn |= val & 0x3ff;
break;
case BFD_RELOC_SPARC_7:
if (! in_bitfield_range (val, 0x7f))
as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
insn |= val & 0x7f;
break;
case BFD_RELOC_SPARC_6:
if (! in_bitfield_range (val, 0x3f))
as_bad ("relocation overflow.");
as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
insn |= val & 0x3f;
break;
case BFD_RELOC_SPARC_5:
if (! in_bitfield_range (val, 0x1f))
as_bad ("relocation overflow.");
as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
insn |= val & 0x1f;
break;
@ -2314,7 +2425,7 @@ md_apply_fix3 (fixP, value, segment)
/* FIXME: simplify */
if (((val > 0) && (val & ~0x3fffc))
|| ((val < 0) && (~(val - 1) & ~0x3fffc)))
as_bad ("relocation overflow.");
as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
/* FIXME: The +1 deserves a comment. */
val = (val >> 2) + 1;
insn |= ((val & 0xc000) << 6) | (val & 0x3fff);
@ -2324,7 +2435,7 @@ md_apply_fix3 (fixP, value, segment)
/* FIXME: simplify */
if (((val > 0) && (val & ~0x1ffffc))
|| ((val < 0) && (~(val - 1) & ~0x1ffffc)))
as_bad ("relocation overflow.");
as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
/* FIXME: The +1 deserves a comment. */
val = (val >> 2) + 1;
insn |= val & 0x7ffff;
@ -2336,6 +2447,7 @@ md_apply_fix3 (fixP, value, segment)
case BFD_RELOC_SPARC_LM22:
case BFD_RELOC_HI22:
/* FIXME: HI22 should signal overflow for 64 bit ABI. */
if (!fixP->fx_addsy)
{
insn |= (val >> 10) & 0x3fffff;
@ -2349,7 +2461,7 @@ md_apply_fix3 (fixP, value, segment)
case BFD_RELOC_SPARC22:
if (val & ~0x003fffff)
as_bad ("relocation overflow");
as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
insn |= (val & 0x3fffff);
break;
@ -2371,7 +2483,7 @@ md_apply_fix3 (fixP, value, segment)
case BFD_RELOC_SPARC13:
if (! in_signed_range (val, 0x1fff))
as_bad ("relocation overflow");
as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
insn |= val & 0x1fff;
break;
@ -2382,9 +2494,49 @@ md_apply_fix3 (fixP, value, segment)
insn |= val & 0x3fffff;
break;
case BFD_RELOC_SPARC_H44:
if (!fixP->fx_addsy)
{
bfd_vma tval = val;
tval >>= 22;
if (! in_unsigned_range (tval, 0x3fffff))
as_bad_where (fixP->fx_file, fixP->fx_line,
"relocation overflow");
insn |= tval & 0x3fffff;
}
break;
case BFD_RELOC_SPARC_M44:
if (!fixP->fx_addsy)
insn |= (val >> 12) & 0x3ff;
break;
case BFD_RELOC_SPARC_L44:
if (!fixP->fx_addsy)
insn |= val & 0xfff;
break;
case BFD_RELOC_SPARC_HIX22:
if (!fixP->fx_addsy)
{
val ^= ~ (offsetT) 0;
if ((val & ~ (offsetT) 0xffffffff) != 0)
as_bad_where (fixP->fx_file, fixP->fx_line,
"relocation overflow");
insn |= (val >> 10) & 0x3fffff;
}
break;
case BFD_RELOC_SPARC_LOX10:
if (!fixP->fx_addsy)
insn |= 0x1c00 | (val & 0x3ff);
break;
case BFD_RELOC_NONE:
default:
as_bad ("bad or unhandled relocation type: 0x%02x", fixP->fx_r_type);
as_bad_where (fixP->fx_file, fixP->fx_line,
"bad or unhandled relocation type: 0x%02x",
fixP->fx_r_type);
break;
}
@ -2431,6 +2583,7 @@ tc_gen_reloc (section, fixp)
case BFD_RELOC_64:
case BFD_RELOC_SPARC_5:
case BFD_RELOC_SPARC_6:
case BFD_RELOC_SPARC_7:
case BFD_RELOC_SPARC_10:
case BFD_RELOC_SPARC_11:
case BFD_RELOC_SPARC_HH22:
@ -2439,6 +2592,11 @@ tc_gen_reloc (section, fixp)
case BFD_RELOC_SPARC_PC_HH22:
case BFD_RELOC_SPARC_PC_HM10:
case BFD_RELOC_SPARC_PC_LM22:
case BFD_RELOC_SPARC_H44:
case BFD_RELOC_SPARC_M44:
case BFD_RELOC_SPARC_L44:
case BFD_RELOC_SPARC_HIX22:
case BFD_RELOC_SPARC_LOX10:
code = fixp->fx_r_type;
break;
default: