/* tc-sparc.c -- Assemble for the SPARC
- Copyright (C) 1989-2018 Free Software Foundation, Inc.
+ Copyright (C) 1989-2020 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GAS is free software; you can redistribute it and/or modify
#include "opcode/sparc.h"
#include "dw2gencfi.h"
-#ifdef OBJ_ELF
#include "elf/sparc.h"
#include "dwarf2dbg.h"
-#endif
/* Some ancient Sun C compilers would not take such hex constants as
unsigned, and would end up sign-extending them to form an offsetT,
changes the value before md_show_usage is called. */
static int default_arch_size;
-#ifdef OBJ_ELF
/* The currently selected v9 memory model. Currently only used for
ELF. */
static enum { MM_TSO, MM_PSO, MM_RMO } sparc_memory_model = MM_RMO;
GNU attributes section with hwcap information. */
static bfd_uint64_t hwcap_seen;
#endif
-#endif
static bfd_uint64_t hwcap_allowed;
static void s_empty (int);
static void s_uacons (int);
static void s_ncons (int);
-#ifdef OBJ_ELF
static void s_register (int);
-#endif
const pseudo_typeS md_pseudo_table[] =
{
{"uahalf", s_uacons, 2},
{"uaword", s_uacons, 4},
{"uaxword", s_uacons, 8},
-#ifdef OBJ_ELF
/* These are specific to sparc/svr4. */
{"2byte", s_uacons, 2},
{"4byte", s_uacons, 4},
{"8byte", s_uacons, 8},
{"register", s_register, 0},
-#endif
{NULL, 0, 0},
};
default_arch_type = sa->arch_type;
}
-/* Called by TARGET_FORMAT. */
+/* Called by TARGET_MACH. */
-const char *
-sparc_target_format (void)
+unsigned long
+sparc_mach (void)
{
/* 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
- if (target_big_endian)
- return "a.out-sunos-big";
- else if (default_arch_type == sparc86x && target_little_endian_data)
- return "a.out-sunos-big";
- else
- return "a.out-sparc-little";
-#else
- return "a.out-sunos-big";
-#endif
-#endif
-#endif
+ return sparc_arch_size == 64 ? bfd_mach_sparc_v9 : bfd_mach_sparc;
+}
-#ifdef OBJ_BOUT
- return "b.out.big";
-#endif
+/* Called by TARGET_FORMAT. */
-#ifdef OBJ_COFF
-#ifdef TE_LYNX
- return "coff-sparc-lynx";
-#else
- return "coff-sparc";
-#endif
-#endif
+const char *
+sparc_target_format (void)
+{
+ /* 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 TE_VXWORKS
return "elf32-sparc-vxworks";
#endif
-#ifdef OBJ_ELF
return sparc_arch_size == 64 ? ELF64_TARGET_FORMAT : ELF_TARGET_FORMAT;
-#endif
-
- abort ();
}
\f
/* md_parse_option
* error. For example, from sparclite to v9.
*/
-#ifdef OBJ_ELF
const char *md_shortopts = "A:K:VQ:sq";
-#else
-#ifdef OBJ_AOUT
-const char *md_shortopts = "A:k";
-#else
-const char *md_shortopts = "A:";
-#endif
-#endif
struct option md_longopts[] = {
#define OPTION_BUMP (OPTION_MD_BASE)
{"bump", no_argument, NULL, OPTION_BUMP},
{"sparc", no_argument, NULL, OPTION_SPARC},
#define OPTION_XARCH (OPTION_MD_BASE + 2)
{"xarch", required_argument, NULL, OPTION_XARCH},
-#ifdef OBJ_ELF
#define OPTION_32 (OPTION_MD_BASE + 3)
{"32", no_argument, NULL, OPTION_32},
#define OPTION_64 (OPTION_MD_BASE + 4)
{"PSO", no_argument, NULL, OPTION_PSO},
#define OPTION_RMO (OPTION_MD_BASE + 7)
{"RMO", no_argument, NULL, OPTION_RMO},
-#endif
#ifdef SPARC_BIENDIAN
#define OPTION_LITTLE_ENDIAN (OPTION_MD_BASE + 8)
{"EL", no_argument, NULL, OPTION_LITTLE_ENDIAN},
{"enforce-aligned-data", no_argument, NULL, OPTION_ENFORCE_ALIGNED_DATA},
#define OPTION_LITTLE_ENDIAN_DATA (OPTION_MD_BASE + 11)
{"little-endian-data", no_argument, NULL, OPTION_LITTLE_ENDIAN_DATA},
-#ifdef OBJ_ELF
#define OPTION_NO_UNDECLARED_REGS (OPTION_MD_BASE + 12)
{"no-undeclared-regs", no_argument, NULL, OPTION_NO_UNDECLARED_REGS},
#define OPTION_UNDECLARED_REGS (OPTION_MD_BASE + 13)
{"undeclared-regs", no_argument, NULL, OPTION_UNDECLARED_REGS},
-#endif
#define OPTION_RELAX (OPTION_MD_BASE + 14)
{"relax", no_argument, NULL, OPTION_RELAX},
#define OPTION_NO_RELAX (OPTION_MD_BASE + 15)
break;
case OPTION_XARCH:
-#ifdef OBJ_ELF
if (!strncmp (arg, "v9", 2))
md_parse_option (OPTION_64, NULL);
else
|| !strcmp (arg, "sparc86x"))
md_parse_option (OPTION_32, NULL);
}
-#endif
/* Fall through. */
case 'A':
break;
#endif
-#ifdef OBJ_AOUT
- case 'k':
- sparc_pic_code = 1;
- break;
-#endif
-
-#ifdef OBJ_ELF
case OPTION_32:
case OPTION_64:
{
case OPTION_UNDECLARED_REGS:
no_undeclared_regs = 0;
break;
-#endif
case OPTION_RELAX:
sparc_relax = 1;
--enforce-aligned-data force .long, etc., to be aligned correctly\n\
-relax relax jumps and branches (default)\n\
-no-relax avoid changing any jumps and branches\n"));
-#ifdef OBJ_AOUT
- fprintf (stream, _("\
--k generate PIC\n"));
-#endif
-#ifdef OBJ_ELF
fprintf (stream, _("\
-32 create 32 bit object file\n\
-64 create 64 bit object file\n"));
-q ignored\n\
-Qy, -Qn ignored\n\
-s ignored\n"));
-#endif
#ifdef SPARC_BIENDIAN
fprintf (stream, _("\
-EL generate code for a little endian machine\n\
void
sparc_md_end (void)
{
- unsigned long mach = bfd_mach_sparc;
-#if defined(OBJ_ELF) && !defined(TE_SOLARIS)
+ unsigned long mach;
+#ifndef TE_SOLARIS
int hwcaps, hwcaps2;
#endif
/* 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). */
- default: break;
+ default: mach = bfd_mach_sparc; break;
}
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, mach);
-#if defined(OBJ_ELF) && !defined(TE_SOLARIS)
+#ifndef TE_SOLARIS
hwcaps = hwcap_seen & U0xffffffff;
hwcaps2 = hwcap_seen >> 32;
as_warn (_("FP branch in delay slot"));
}
- /* SPARC before v9 requires a nop instruction between a floating
- point instruction and a floating point branch. We insert one
- automatically, with a warning. */
+ /* SPARC before v9 does not allow a floating point compare
+ directly before a floating point branch. Insert a nop
+ instruction if needed, with a warning. */
if (max_architecture < SPARC_OPCODE_ARCH_V9
&& last_insn != NULL
&& (insn->flags & F_FBR) != 0
- && (last_insn->flags & F_FLOAT) != 0)
+ && (last_insn->flags & F_FLOAT) != 0
+ && (last_insn->match & OP3 (0x35)) == OP3 (0x35))
{
struct sparc_it nop_insn;
nop_insn.opcode = NOP_INSN;
nop_insn.reloc = BFD_RELOC_NONE;
output_insn (insn, &nop_insn);
- as_warn (_("FP branch preceded by FP instruction; NOP inserted"));
+ as_warn (_("FP branch preceded by FP compare; NOP inserted"));
}
switch (special_case)
bfd_uint64_t hwcaps
= (((bfd_uint64_t) insn->hwcaps2) << 32) | insn->hwcaps;
-#if defined(OBJ_ELF) && !defined(TE_SOLARIS)
+#ifndef TE_SOLARIS
if (hwcaps)
hwcap_seen |= hwcaps;
#endif
last_insn = insn;
last_opcode = theinsn->opcode;
-#ifdef OBJ_ELF
dwarf2_emit_insn (4);
-#endif
}
\f
const char *
fixP->fx_addnumber = val; /* Remember value for emit_reloc. */
-#ifdef OBJ_ELF
/* SPARC ELF relocations don't use an addend in the data field. */
if (fixP->fx_addsy != NULL)
{
return;
}
-#endif
/* This is a hack. There should be a better way to
handle this. Probably in terms of howto fields, once
if (fixP->fx_r_type == BFD_RELOC_32_PCREL_S2 && fixP->fx_addsy)
val += fixP->fx_where + fixP->fx_frag->fr_address;
-#ifdef OBJ_AOUT
- /* FIXME: More ridiculous gas reloc hacking. If we are going to
- generate a reloc, then we just want to let the reloc addend set
- the value. We do not want to also stuff the addend into the
- object file. Including the addend in the object file works when
- doing a static link, because the linker will ignore the object
- file contents. However, the dynamic linker does not ignore the
- object file contents. */
- if (fixP->fx_addsy != NULL
- && fixP->fx_r_type != BFD_RELOC_32_PCREL_S2)
- val = 0;
-
- /* When generating PIC code, we do not want an addend for a reloc
- against a local symbol. We adjust fx_addnumber to cancel out the
- value already included in val, and to also cancel out the
- adjustment which bfd_install_relocation will create. */
- if (sparc_pic_code
- && fixP->fx_r_type != BFD_RELOC_32_PCREL_S2
- && fixP->fx_addsy != NULL
- && ! S_IS_COMMON (fixP->fx_addsy)
- && symbol_section_p (fixP->fx_addsy))
- fixP->fx_addnumber -= 2 * S_GET_VALUE (fixP->fx_addsy);
-
- /* When generating PIC code, we need to fiddle to get
- bfd_install_relocation to do the right thing for a PC relative
- reloc against a local symbol which we are going to keep. */
- if (sparc_pic_code
- && fixP->fx_r_type == BFD_RELOC_32_PCREL_S2
- && fixP->fx_addsy != NULL
- && (S_IS_EXTERNAL (fixP->fx_addsy)
- || S_IS_WEAK (fixP->fx_addsy))
- && S_IS_DEFINED (fixP->fx_addsy)
- && ! S_IS_COMMON (fixP->fx_addsy))
- {
- val = 0;
- fixP->fx_addnumber -= 2 * S_GET_VALUE (fixP->fx_addsy);
- }
-#endif
-
/* If this is a data relocation, just output VAL. */
if (fixP->fx_r_type == BFD_RELOC_8)
return NULL;
}
-#if defined (OBJ_ELF) || defined (OBJ_AOUT)
/* If we are generating PIC code, we need to generate a different
set of relocs. */
-#ifdef OBJ_ELF
#define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
-#else
-#define GOT_NAME "__GLOBAL_OFFSET_TABLE_"
-#endif
#ifdef TE_VXWORKS
#define GOTT_BASE "__GOTT_BASE__"
#define GOTT_INDEX "__GOTT_INDEX__"
#endif
- /* This code must be parallel to the OBJ_ELF tc_fix_adjustable. */
+ /* This code must be parallel to tc_fix_adjustable. */
if (sparc_pic_code)
{
break;
}
}
-#endif /* defined (OBJ_ELF) || defined (OBJ_AOUT) */
/* Nothing is aligned in DWARF debugging sections. */
- if (bfd_get_section_flags (stdoutput, section) & SEC_DEBUGGING)
+ if (bfd_section_flags (section) & SEC_DEBUGGING)
switch (code)
{
case BFD_RELOC_16: code = BFD_RELOC_SPARC_UA16; break;
}
/* @@ Why fx_addnumber sometimes and fx_offset other times? */
-#ifdef OBJ_AOUT
-
- if (reloc->howto->pc_relative == 0
- || code == BFD_RELOC_SPARC_PC10
- || code == BFD_RELOC_SPARC_PC22)
- reloc->addend = fixp->fx_addnumber;
- else if (sparc_pic_code
- && fixp->fx_r_type == BFD_RELOC_32_PCREL_S2
- && fixp->fx_addsy != NULL
- && (S_IS_EXTERNAL (fixp->fx_addsy)
- || S_IS_WEAK (fixp->fx_addsy))
- && S_IS_DEFINED (fixp->fx_addsy)
- && ! S_IS_COMMON (fixp->fx_addsy))
- reloc->addend = fixp->fx_addnumber;
- else
- reloc->addend = fixp->fx_offset - reloc->address;
-
-#else /* elf or coff */
-
if (code != BFD_RELOC_32_PCREL_S2
&& code != BFD_RELOC_SPARC_WDISP22
&& code != BFD_RELOC_SPARC_WDISP16
+ md_pcrel_from (fixp));
else
reloc->addend = fixp->fx_offset;
-#endif
/* We expand R_SPARC_OLO10 to R_SPARC_LO10 and R_SPARC_13
on the same location. */
valueT
md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
{
-#ifndef OBJ_ELF
- /* This is not right for ELF; a.out wants it, and COFF will force
- the alignment anyways. */
- valueT align = ((valueT) 1
- << (valueT) bfd_get_section_alignment (stdoutput, segment));
- valueT newsize;
-
- /* Turn alignment value into a mask. */
- align--;
- newsize = (size + align) & ~align;
- return newsize;
-#else
return size;
-#endif
}
/* Exactly what point is a PC-relative offset relative TO?
/* Sort of like s_lcomm. */
-#ifndef OBJ_ELF
-static int max_alignment = 15;
-#endif
-
static void
s_reserve (int ignore ATTRIBUTE_UNUSED)
{
align = (int) get_absolute_expression ();
-#ifndef OBJ_ELF
- if (align > max_alignment)
- {
- align = max_alignment;
- as_warn (_("alignment too large; assuming %d"), align);
- }
-#endif
-
if (align < 0)
{
as_bad (_("negative alignment"));
else
align = 0;
- if (!S_IS_DEFINED (symbolP)
-#ifdef OBJ_AOUT
- && S_GET_OTHER (symbolP) == 0
- && S_GET_DESC (symbolP) == 0
-#endif
- )
+ if (!S_IS_DEFINED (symbolP))
{
if (! need_pass_2)
{
subseg_set (current_seg, current_subseg);
-#ifdef OBJ_ELF
S_SET_SIZE (symbolP, size);
-#endif
}
}
else
S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), (long) size);
}
}
- else
- {
-#ifndef OBJ_ELF
- S_SET_VALUE (symbolP, (valueT) size);
- S_SET_EXTERNAL (symbolP);
-#endif
- }
know (symbol_get_frag (symbolP) == &zero_address_frag);
if (*input_line_pointer != ',')
{
{
temp = get_absolute_expression ();
-#ifndef OBJ_ELF
- if (temp > max_alignment)
- {
- temp = max_alignment;
- as_warn (_("alignment too large; assuming %ld"), (long) temp);
- }
-#endif
-
if (temp < 0)
{
as_bad (_("negative alignment"));
return;
}
-#ifdef OBJ_ELF
if (symbol_get_obj (symbolP)->local)
{
segT old_sec;
subseg_set (old_sec, old_subsec);
}
else
-#endif /* OBJ_ELF */
{
allocate_common:
S_SET_VALUE (symbolP, (valueT) size);
-#ifdef OBJ_ELF
S_SET_ALIGN (symbolP, temp);
S_SET_SIZE (symbolP, size);
-#endif
S_SET_EXTERNAL (symbolP);
S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
}
cons (sparc_arch_size == 32 ? 4 : 8);
}
-#ifdef OBJ_ELF
/* Handle the SPARC ELF .register pseudo-op. This sets the binding of a
global register.
The syntax is:
S_SET_SEGMENT (sym, undefined_section);
}
}
-#endif
/* If the --enforce-aligned-data option is used, we require .word,
et. al., to be aligned correctly. We do it by setting up an
}
}
-#ifdef OBJ_ELF
/* Some special processing for a Sparc ELF file. */
void
return sparc_cons_special_reloc;
}
-#endif
-
/* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
reloc for a cons. We could use the definition there, except that
we want to handle little endian relocs specially. */