* 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:
parent
2f0e18834b
commit
54b9ebdd55
3 changed files with 356 additions and 170 deletions
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue