02111-1307, USA. */
#include <ctype.h>
-#define NO_RELOC 0
#include "as.h"
#include "obstack.h"
#include "subsegs.h"
/* Are we trying to generate PIC code? If so, absolute references
ought to be made into linkage table references or pc-relative
- references. */
+ references. Not implemented. For ELF there are other means
+ to denote pic relocations. */
int flag_want_pic;
static int flag_short_refs; /* -l option */
significance of some values (in the branch instruction, for
example). */
int pcrel_fix;
+#ifdef OBJ_ELF
+ /* Whether this expression needs special pic relocation, and if
+ so, which. */
+ enum pic_relocation pic_reloc;
+#endif
}
reloc[5]; /* Five is enough??? */
};
the_ins.reloc[the_ins.nrel].exp = exp->exp;
the_ins.reloc[the_ins.nrel].wid = width;
the_ins.reloc[the_ins.nrel].pcrel_fix = pc_fix;
+#ifdef OBJ_ELF
+ the_ins.reloc[the_ins.nrel].pic_reloc = exp->pic_reloc;
+#endif
the_ins.reloc[the_ins.nrel++].pcrel = pc_rel;
}
{"even", s_even, 0},
{"skip", s_space, 0},
{"proc", s_proc, 0},
-#ifdef TE_SUN3
+#if defined (TE_SUN3) || defined (OBJ_ELF)
{"align", s_align_bytes, 0},
#endif
#ifdef OBJ_ELF
{"dsb", s_space, 1},
{"xdef", s_globl, 0},
+#ifdef OBJ_ELF
+ {"align", s_align_bytes, 0},
+#else
{"align", s_align_ptwo, 0},
+#endif
#ifdef M68KCOFF
{"sect", obj_coff_section, 0},
{"section", obj_coff_section, 0},
#endif
+#ifdef OBJ_ELF
+
+/* Compute the relocation code for a fixup of SIZE bytes, using pc
+ relative relocation if PCREL is non-zero. PIC says whether a special
+ pic relocation was requested. */
+
+static bfd_reloc_code_real_type get_reloc_code
+ PARAMS ((int, int, enum pic_relocation));
+
+static bfd_reloc_code_real_type
+get_reloc_code (size, pcrel, pic)
+ int size;
+ int pcrel;
+ enum pic_relocation pic;
+{
+ switch (pic)
+ {
+ case pic_got_pcrel:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_GOT_PCREL;
+ case 2:
+ return BFD_RELOC_16_GOT_PCREL;
+ case 4:
+ return BFD_RELOC_32_GOT_PCREL;
+ }
+ break;
+
+ case pic_got_off:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_GOTOFF;
+ case 2:
+ return BFD_RELOC_16_GOTOFF;
+ case 4:
+ return BFD_RELOC_32_GOTOFF;
+ }
+ break;
+
+ case pic_plt_pcrel:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_PLT_PCREL;
+ case 2:
+ return BFD_RELOC_16_PLT_PCREL;
+ case 4:
+ return BFD_RELOC_32_PLT_PCREL;
+ }
+ break;
+
+ case pic_plt_off:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_PLTOFF;
+ case 2:
+ return BFD_RELOC_16_PLTOFF;
+ case 4:
+ return BFD_RELOC_32_PLTOFF;
+ }
+ break;
+
+ case pic_none:
+ if (pcrel)
+ {
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_PCREL;
+ case 2:
+ return BFD_RELOC_16_PCREL;
+ case 4:
+ return BFD_RELOC_32_PCREL;
+ }
+ }
+ else
+ {
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8;
+ case 2:
+ return BFD_RELOC_16;
+ case 4:
+ return BFD_RELOC_32;
+ }
+ }
+ }
+
+ as_bad ("Can not do %d byte %s%srelocation", size,
+ pcrel ? "pc-relative " : "",
+ pic == pic_none ? "" : "pic ");
+ return BFD_RELOC_NONE;
+}
+
+/* Here we decide which fixups can be adjusted to make them relative
+ to the beginning of the section instead of the symbol. Basically
+ we need to make sure that the dynamic relocations are done
+ correctly, so in some cases we force the original symbol to be
+ used. */
+int
+tc_m68k_fix_adjustable (fixP)
+ fixS *fixP;
+{
+ /* Prevent all adjustments to global symbols. */
+ if (S_IS_EXTERNAL (fixP->fx_addsy))
+ return 0;
+
+ /* adjust_reloc_syms doesn't know about the GOT */
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_8_GOT_PCREL:
+ case BFD_RELOC_16_GOT_PCREL:
+ case BFD_RELOC_32_GOT_PCREL:
+ case BFD_RELOC_8_GOTOFF:
+ case BFD_RELOC_16_GOTOFF:
+ case BFD_RELOC_32_GOTOFF:
+ case BFD_RELOC_8_PLT_PCREL:
+ case BFD_RELOC_16_PLT_PCREL:
+ case BFD_RELOC_32_PLT_PCREL:
+ case BFD_RELOC_8_PLTOFF:
+ case BFD_RELOC_16_PLTOFF:
+ case BFD_RELOC_32_PLTOFF:
+ return 0;
+
+ default:
+ return 1;
+ }
+}
+
+#else /* !OBJ_ELF */
+
+#define get_reloc_code(SIZE,PCREL,OTHER) NO_RELOC
+
+#endif /* OBJ_ELF */
+
#ifdef BFD_ASSEMBLER
arelent *
if (fixp->fx_tcbit)
abort ();
-#define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
- switch (F (fixp->fx_size, fixp->fx_pcrel))
+ if (fixp->fx_r_type != BFD_RELOC_NONE)
+ code = fixp->fx_r_type;
+ else
{
+#define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
+ switch (F (fixp->fx_size, fixp->fx_pcrel))
+ {
#define MAP(SZ,PCREL,TYPE) case F(SZ,PCREL): code = (TYPE); break
- MAP (1, 0, BFD_RELOC_8);
- MAP (2, 0, BFD_RELOC_16);
- MAP (4, 0, BFD_RELOC_32);
- MAP (1, 1, BFD_RELOC_8_PCREL);
- MAP (2, 1, BFD_RELOC_16_PCREL);
- MAP (4, 1, BFD_RELOC_32_PCREL);
- default:
- abort ();
+ MAP (1, 0, BFD_RELOC_8);
+ MAP (2, 0, BFD_RELOC_16);
+ MAP (4, 0, BFD_RELOC_32);
+ MAP (1, 1, BFD_RELOC_8_PCREL);
+ MAP (2, 1, BFD_RELOC_16_PCREL);
+ MAP (4, 1, BFD_RELOC_32_PCREL);
+ default:
+ abort ();
+ }
}
+#undef F
+#undef MAP
reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
assert (reloc != 0);
reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+#ifndef OBJ_ELF
if (fixp->fx_pcrel)
reloc->addend = fixp->fx_addnumber;
else
reloc->addend = 0;
+#else
+ if (!fixp->fx_pcrel)
+ reloc->addend = fixp->fx_addnumber;
+ else if ((fixp->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
+ reloc->addend = (section->vma
+ + (fixp->fx_pcrel_adjust == 64
+ ? -1 : fixp->fx_pcrel_adjust)
+ + fixp->fx_addnumber
+ + md_pcrel_from (fixp));
+ else
+ reloc->addend = (fixp->fx_offset
+ + (fixp->fx_pcrel_adjust == 64
+ ? -1 : fixp->fx_pcrel_adjust));
+#endif
reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
assert (reloc->howto != 0);
{
if (opP->reg == PC)
{
-#if 0
- addword (0x0170);
- add_fix ('l', &opP->disp, 1, 2);
- addword (0), addword (0);
-#else
- add_frag (adds (&opP->disp),
- offs (&opP->disp),
- TAB (PCLEA, SZ_UNDEF));
+ if (opP->disp.size == SIZE_LONG
+#ifdef OBJ_ELF
+ /* If the displacement needs pic
+ relocation it cannot be relaxed. */
+ || opP->disp.pic_reloc != pic_none
#endif
- break;
+ )
+ {
+ addword (0x0170);
+ add_fix ('l', &opP->disp, 1, 2);
+ }
+ else
+ {
+ add_frag (adds (&opP->disp),
+ offs (&opP->disp),
+ TAB (PCLEA, SZ_UNDEF));
+ break;
+ }
}
else
{
else if (siz1 == SIZE_UNSPEC
&& opP->reg == PC
&& isvar (&opP->disp)
- && subs (&opP->disp) == NULL)
+ && subs (&opP->disp) == NULL
+#ifdef OBJ_ELF
+ /* If the displacement needs pic
+ relocation it cannot be relaxed. */
+ && opP->disp.pic_reloc == pic_none
+#endif
+ )
{
nextword += baseo & 0xff;
addword (nextword);
if (isvar (&opP->disp)
&& !subs (&opP->disp)
&& adds (&opP->disp)
+#ifdef OBJ_ELF
+ /* If the displacement needs pic relocation it
+ cannot be relaxed. */
+ && opP->disp.pic_reloc == pic_none
+#endif
&& S_GET_SEGMENT (adds (&opP->disp)) == now_seg
&& cpu_of_arch (current_architecture) >= m68020
&& !flag_long_jumps
if (subs (&opP->disp)) /* We can't relax it */
goto long_branch;
+#ifdef OBJ_ELF
+ /* If the displacement needs pic relocation it cannot be
+ relaxed. */
+ if (opP->disp.pic_reloc != pic_none)
+ goto long_branch;
+#endif
+
/* This could either be a symbol, or an absolute
address. No matter, the frag hacking will finger it
out. Not quite: it can't switch from BRANCH to
n,
&the_ins.reloc[m].exp,
the_ins.reloc[m].pcrel,
- NO_RELOC);
+ get_reloc_code (n, the_ins.reloc[m].pcrel,
+ the_ins.reloc[m].pic_reloc));
fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
}
return;
wid,
&the_ins.reloc[m].exp,
the_ins.reloc[m].pcrel,
- NO_RELOC);
+ get_reloc_code (wid, the_ins.reloc[m].pcrel,
+ the_ins.reloc[m].pic_reloc));
fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
}
(void) frag_var (rs_machine_dependent, 10, 0,
wid,
&the_ins.reloc[m].exp,
the_ins.reloc[m].pcrel,
- NO_RELOC);
+ get_reloc_code (wid, the_ins.reloc[m].pcrel,
+ the_ins.reloc[m].pic_reloc));
fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
}
}
#endif
init_regtable ();
+
+#ifdef OBJ_ELF
+ record_alignment (text_section, 2);
+ record_alignment (data_section, 2);
+ record_alignment (bss_section, 2);
+#endif
}
void
else
val &= 0x7fffffff;
+#ifdef OBJ_ELF
+ if (fixP->fx_addsy)
+ {
+ memset (buf, 0, fixP->fx_size);
+ fixP->fx_addnumber = val; /* Remember value for emit_reloc */
+ return;
+ }
+#endif
+
switch (fixP->fx_size)
{
/* The cast to offsetT below are necessary to make code correct for
flag_reg_prefix_optional = 1;
break;
- case 'Q':
+ /* -V: SVR4 argument to print version ID. */
case 'V':
+ print_version_id ();
+ break;
+
+ /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
+ should be emitted or not. FIXME: Not implemented. */
+ case 'Q':
break;
default:
/* This file is tc-m68k.h
- Copyright (C) 1987-1992 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 90, 91, 92, 93, 94, 95, 1996
+ Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
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. */
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define TC_M68K 1
+#define TARGET_BYTES_BIG_ENDIAN 1
+
#ifdef OBJ_AOUT
+#ifdef TE_SUN3
#define TARGET_FORMAT "a.out-sunos-big"
+#else
+#ifdef TE_NetBSD
+#define TARGET_FORMAT "a.out-m68k-netbsd"
+#else
+#define TARGET_FORMAT "a.out-zero-big"
+#endif
+#endif
+#endif
+
+#ifdef OBJ_ELF
+#define TARGET_FORMAT "elf32-m68k"
#endif
#ifdef TE_APOLLO
#ifdef TE_LYNX
#define TARGET_FORMAT "coff-m68k-lynx"
#endif
+#ifdef TE_AUX
+#define TARGET_FORMAT "coff-m68k-aux"
+#endif
#ifndef COFF_MAGIC
#define COFF_MAGIC MC68MAGIC
#endif
-#define BFD_ARCH bfd_arch_m68k
+#define BFD_ARCH bfd_arch_m68k /* for non-BFD_ASSEMBLER */
+#define TARGET_ARCH bfd_arch_m68k /* BFD_ASSEMBLER */
#define COFF_FLAGS F_AR32W
#define TC_COUNT_RELOC(x) ((x)->fx_addsy||(x)->fx_subsy)
#define TC_COFF_FIX2RTYPE(fixP) tc_coff_fix2rtype(fixP)
#define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep(frag)
+extern int tc_coff_sizemachdep PARAMS ((struct frag *));
#ifdef TE_SUN3
/* This variable contains the value to write out at the beginning of
the a.out file. The 2<<16 means that this is a 68020 file instead
#endif
#if !defined (REGISTER_PREFIX_OPTIONAL)
-#ifdef M68KCOFF
+#if defined (M68KCOFF) || defined (OBJ_ELF)
#define LOCAL_LABEL(name) (name[0] == '.' \
&& (name[1] == 'L' || name[1] == '.'))
#define FAKE_LABEL_NAME ".L0\001"
can't be used as the initial character. If that's not true, more
work will be needed to fix this up. */
#define LEX_PCT 1
+/* On the Delta, dots are not required before pseudo-ops. */
+#define NO_PSEUDO_DOT
#endif
#ifdef BFD_ASSEMBLER
+
#define tc_frob_symbol(sym,punt) \
if (S_GET_SEGMENT (sym) == reg_section) punt = 1
+
+#define NO_RELOC BFD_RELOC_NONE
+
+#ifdef OBJ_ELF
+
+/* This expression evaluates to false if the relocation is for a local object
+ for which we still want to do the relocation at runtime. True if we
+ are willing to perform this relocation while building the .o file. */
+
+#define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \
+ ((FIX)->fx_r_type != BFD_RELOC_8_PLT_PCREL \
+ && (FIX)->fx_r_type != BFD_RELOC_16_PLT_PCREL \
+ && (FIX)->fx_r_type != BFD_RELOC_32_PLT_PCREL \
+ && (FIX)->fx_r_type != BFD_RELOC_8_GOT_PCREL \
+ && (FIX)->fx_r_type != BFD_RELOC_16_GOT_PCREL \
+ && (FIX)->fx_r_type != BFD_RELOC_32_GOT_PCREL)
+
+#define tc_fix_adjustable(X) tc_m68k_fix_adjustable(X)
+#endif
+
+#else
+#define NO_RELOC 0
#endif
#define DIFF_EXPR_OK
extern int m68k_parse_long_option PARAMS ((char *));
#define md_parse_long_option m68k_parse_long_option
+#define md_operand(x)
+
+#define TARGET_WORD_SIZE 32
+#define TARGET_ARCH bfd_arch_m68k
+
+extern struct relax_type md_relax_table[];
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+
/* end of tc-m68k.h */
/* write.c - emit .o file
- Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 1995
+ Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 1996
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
#endif /* BFD_ASSEMBLER */
+static int n_fixups;
+
#ifdef BFD_ASSEMBLER
static fixS *fix_new_internal PARAMS ((fragS *, int where, int size,
symbolS *add, symbolS *sub,
{
fixS *fixP;
+ n_fixups++;
+
fixP = (fixS *) obstack_alloc (¬es, sizeof (fixS));
fixP->fx_frag = frag;
{
arelent *reloc;
bfd_reloc_status_type s;
+ symbolS *sym;
if (fixp->fx_done)
{
n--;
continue;
}
+
+ /* If this is an undefined symbol which was equated to another
+ symbol, then use generate the reloc against the latter symbol
+ rather than the former. */
+ sym = fixp->fx_addsy;
+ while (sym->sy_value.X_op == O_symbol
+ && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
+ sym = sym->sy_value.X_add_symbol;
+ fixp->fx_addsy = sym;
+
reloc = tc_gen_reloc (sec, fixp);
if (!reloc)
{
arelent **reloc;
char *data;
bfd_reloc_status_type s;
+ symbolS *sym;
int j;
if (fixp->fx_done)
n--;
continue;
}
+
+ /* If this is an undefined symbol which was equated to another
+ symbol, then use generate the reloc against the latter symbol
+ rather than the former. */
+ sym = fixp->fx_addsy;
+ while (sym->sy_value.X_op == O_symbol
+ && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
+ sym = sym->sy_value.X_add_symbol;
+ fixp->fx_addsy = sym;
+
reloc = tc_gen_reloc (sec, fixp);
for (j = 0; reloc[j]; j++)
resolve_symbol_value (symp);
}
+ /* Skip symbols which were equated to undefined or common
+ symbols. */
+ if (symp->sy_value.X_op == O_symbol
+ && (! S_IS_DEFINED (symp) || S_IS_COMMON (symp)))
+ {
+ symbol_remove (symp, &symbol_rootP, &symbol_lastP);
+ continue;
+ }
+
/* So far, common symbols have been treated like undefined symbols.
Put them in the common section now. */
if (S_IS_DEFINED (symp) == 0
/* Now do any format-specific adjustments to the symbol table, such
as adding file symbols. */
+#ifdef tc_adjust_symtab
+ tc_adjust_symtab ();
+#endif
#ifdef obj_adjust_symtab
obj_adjust_symtab ();
#endif
else
{
seg_reloc_count++;
+#if !(defined (TC_M68K) && defined (OBJ_ELF))
#if !defined (TC_I386) || !(defined (OBJ_ELF) || defined (OBJ_COFF))
add_number += S_GET_VALUE (add_symbolP);
+#endif
#endif
}
}
}
}
+void
+write_print_statistics (file)
+ FILE *file;
+{
+ fprintf (stderr, "fixups: %d\n", n_fixups);
+}
+
/* for debugging */
extern int indent_level;
extern void print_symbol_value_1 ();