/* tc-ppc.h -- Header file for tc-ppc.c.
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
This file is part of GAS, the GNU Assembler.
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. */
#define TC_PPC
+#ifdef ANSI_PROTOTYPES
+struct fix;
+#endif
+
+/* Set the endianness we are using. Default to big endian. */
+#ifndef TARGET_BYTES_BIG_ENDIAN
+#define TARGET_BYTES_BIG_ENDIAN 1
+#endif
+
#ifndef BFD_ASSEMBLER
#error PowerPC support requires BFD_ASSEMBLER
#endif
+/* If OBJ_COFF is defined, and TE_PE is not defined, we are assembling
+ XCOFF for AIX or PowerMac. If TE_PE is defined, we are assembling
+ COFF for Windows NT. */
+
+#ifdef OBJ_COFF
+#ifndef TE_PE
+#define OBJ_XCOFF
+#endif
+#endif
+
/* The target BFD architecture. */
#define TARGET_ARCH (ppc_arch ())
extern enum bfd_architecture ppc_arch PARAMS ((void));
/* The target BFD format. */
#ifdef OBJ_COFF
+#ifdef TE_PE
+#define TARGET_FORMAT (target_big_endian ? "pe-powerpc" : "pe-powerpcle")
+#else
#define TARGET_FORMAT "aixcoff-rs6000"
#endif
+#endif
+
+/* PowerMac has a BFD slightly different from AIX's. */
+#ifdef TE_POWERMAC
+#ifdef TARGET_FORMAT
+#undef TARGET_FORMAT
+#endif
+#define TARGET_FORMAT "xcoff-powermac"
+#endif
+
#ifdef OBJ_ELF
-#define TARGET_FORMAT (target_big_endian) ? "elf32-powerpc" : "elf32-powerpcle"
+#define TARGET_FORMAT (target_big_endian ? "elf32-powerpc" : "elf32-powerpcle")
#endif
/* Permit temporary numeric labels. */
#define NO_STRING_ESCAPES
#endif
-/* When using COFF, we determine whether or not to output a symbol
- based on sy_tc.output, not on the name. */
-#ifdef OBJ_COFF
-#define LOCAL_LABEL(name) 0
-#endif
#ifdef OBJ_ELF
-/* When using ELF, local labels start with '.'. */
-#define LOCAL_LABEL(name) (name[0] == '.' \
- && (name[1] == 'L' || name[1] == '.'))
-#define FAKE_LABEL_NAME ".L0\001"
-#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */
+#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs */
#endif
-/* Set the endianness we are using. Default to big endian. */
-#ifndef TARGET_BYTES_BIG_ENDIAN
-#ifndef TARGET_BYTES_LITTLE_ENDIAN
-#define TARGET_BYTES_BIG_ENDIAN 1
-#endif
-#endif
-
-#ifdef TARGET_BYTES_BIG_ENDIAN
+#if TARGET_BYTES_BIG_ENDIAN
#define PPC_BIG_ENDIAN 1
#else
#define PPC_BIG_ENDIAN 0
/* We set the fx_done field appropriately in md_apply_fix. */
#define TC_HANDLES_FX_DONE
\f
-#ifdef OBJ_COFF
+#ifdef TE_PE
+
+/* Question marks are permitted in symbol names. */
+#define LEX_QM 1
+
+/* Don't adjust TOC relocs. */
+#define tc_fix_adjustable(fixp) ppc_pe_fix_adjustable (fixp)
+extern int ppc_pe_fix_adjustable PARAMS ((struct fix *));
+
+#endif
+
+#ifdef OBJ_XCOFF
/* Declarations needed when generating XCOFF code. XCOFF is an
extension of COFF, used only on the RS/6000. Rather than create an
struct ppc_tc_sy
{
/* We keep a few linked lists of symbols. */
- struct symbol *next;
+ symbolS *next;
/* Non-zero if the symbol should be output. The RS/6000 assembler
only outputs symbols that are external or are mentioned in a
.globl or .lglobl statement. */
int align;
/* For a function symbol, a symbol whose value is the size. The
field is NULL if there is no size. */
- struct symbol *size;
+ symbolS *size;
/* For a csect symbol, the last symbol which has been defined in
this csect, or NULL if none have been defined so far. For a .bs
symbol, the referenced csect symbol. */
- struct symbol *within;
+ symbolS *within;
};
#define TC_SYMFIELD_TYPE struct ppc_tc_sy
/* Get the symbol class from the name. */
#define tc_symbol_new_hook(sym) ppc_symbol_new_hook (sym)
-extern void ppc_symbol_new_hook PARAMS ((struct symbol *));
+extern void ppc_symbol_new_hook PARAMS ((symbolS *));
/* Set the symbol class of a label based on the csect. */
#define tc_frob_label(sym) ppc_frob_label (sym)
-extern void ppc_frob_label PARAMS ((struct symbol *));
+extern void ppc_frob_label PARAMS ((symbolS *));
/* TOC relocs requires special handling. */
#define tc_fix_adjustable(fixp) ppc_fix_adjustable (fixp)
extern int ppc_fix_adjustable PARAMS ((struct fix *));
+/* A relocation from one csect to another must be kept. */
+#define TC_FORCE_RELOCATION(FIXP) ppc_force_relocation (FIXP)
+extern int ppc_force_relocation PARAMS ((struct fix *));
+
/* We need to set the section VMA. */
#define tc_frob_section(sec) ppc_frob_section (sec)
extern void ppc_frob_section PARAMS ((asection *));
/* Finish up the symbol. */
#define tc_frob_symbol(sym, punt) punt = ppc_frob_symbol (sym)
-extern int ppc_frob_symbol PARAMS ((struct symbol *));
+extern int ppc_frob_symbol PARAMS ((symbolS *));
+
+/* Finish up the entire symtab. */
+#define tc_adjust_symtab() ppc_adjust_symtab ()
+extern void ppc_adjust_symtab PARAMS ((void));
/* Niclas Andersson <nican@ida.liu.se> says this is needed. */
#define SUB_SEGMENT_ALIGN(SEG) 2
-/* Finish up the file. */
-#define tc_frob_file() ppc_frob_file ()
-extern void ppc_frob_file PARAMS ((void));
-
-#endif /* OBJ_COFF */
+#endif /* OBJ_XCOFF */
#ifdef OBJ_ELF
-/* The name of the global offset table generated by the compiler. Allow
- this to be overridden if need be. */
-#ifndef GLOBAL_OFFSET_TABLE_NAME
-#define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_"
-#endif
-/* Branch prediction relocations must force relocation */
+/* Branch prediction relocations must force relocation, as must
+ the vtable description relocs. */
#define TC_FORCE_RELOCATION(FIXP) \
((FIXP)->fx_r_type == BFD_RELOC_PPC_B16_BRTAKEN \
|| (FIXP)->fx_r_type == BFD_RELOC_PPC_B16_BRNTAKEN \
|| (FIXP)->fx_r_type == BFD_RELOC_PPC_BA16_BRTAKEN \
- || (FIXP)->fx_r_type == BFD_RELOC_PPC_BA16_BRNTAKEN)
+ || (FIXP)->fx_r_type == BFD_RELOC_PPC_BA16_BRNTAKEN \
+ || (FIXP)->fx_r_type == BFD_RELOC_VTABLE_INHERIT \
+ || (FIXP)->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+
+#define TC_FORCE_RELOCATION_SECTION(FIXP,SEC) \
+(TC_FORCE_RELOCATION (FIXP) \
+ || ((FIXP)->fx_addsy && !(FIXP)->fx_subsy \
+ && S_GET_SEGMENT ((FIXP)->fx_addsy) != SEC))
+
+/* Support for SHF_EXCLUDE and SHT_ORDERED */
+extern int ppc_section_letter PARAMS ((int, char **));
+extern int ppc_section_type PARAMS ((char *, size_t));
+extern int ppc_section_word PARAMS ((char *, size_t));
+extern int ppc_section_flags PARAMS ((int, int, int));
+
+#define md_elf_section_letter(LETTER, PTR_MSG) ppc_section_letter (LETTER, PTR_MSG)
+#define md_elf_section_type(STR, LEN) ppc_section_type (STR, LEN)
+#define md_elf_section_word(STR, LEN) ppc_section_word (STR, LEN)
+#define md_elf_section_flags(FLAGS, ATTR, TYPE) ppc_section_flags (FLAGS, ATTR, TYPE)
+
+/* Add extra PPC sections -- Note, for now, make .sbss2 and .PPC.EMB.sbss0 a
+ normal section, and not a bss section so that the linker doesn't crater
+ when trying to make more than 2 sections. */
+#define ELF_TC_SPECIAL_SECTIONS \
+ { ".tags", SHT_ORDERED, SHF_ALLOC }, \
+ { ".sdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, \
+ { ".sbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, \
+ { ".sdata2", SHT_PROGBITS, SHF_ALLOC }, \
+ { ".sbss2", SHT_PROGBITS, SHF_ALLOC }, \
+ { ".PPC.EMB.sdata0", SHT_PROGBITS, SHF_ALLOC }, \
+ { ".PPC.EMB.sbss0", SHT_PROGBITS, SHF_ALLOC },
+
+#define tc_comment_chars ppc_comment_chars
+extern const char *ppc_comment_chars;
+
+/* Keep relocations relative to the GOT, or non-PC relative. */
+#define tc_fix_adjustable(FIX) \
+ ((FIX)->fx_r_type != BFD_RELOC_16_GOTOFF \
+ && (FIX)->fx_r_type != BFD_RELOC_LO16_GOTOFF \
+ && (FIX)->fx_r_type != BFD_RELOC_HI16_GOTOFF \
+ && (FIX)->fx_r_type != BFD_RELOC_HI16_S_GOTOFF \
+ && (FIX)->fx_r_type != BFD_RELOC_GPREL16 \
+ && (FIX)->fx_r_type != BFD_RELOC_VTABLE_INHERIT \
+ && (FIX)->fx_r_type != BFD_RELOC_VTABLE_ENTRY \
+ && ! S_IS_EXTERNAL ((FIX)->fx_addsy) \
+ && ! S_IS_WEAK ((FIX)->fx_addsy) \
+ && ((FIX)->fx_pcrel \
+ || ((FIX)->fx_subsy != NULL \
+ && (S_GET_SEGMENT ((FIX)->fx_subsy) \
+ == S_GET_SEGMENT ((FIX)->fx_addsy))) \
+ || strchr (S_GET_NAME ((FIX)->fx_addsy), '\001') != NULL \
+ || strchr (S_GET_NAME ((FIX)->fx_addsy), '\002') != NULL))
+
+/* We must never ever try to resolve references to externally visible
+ symbols in the assembler, because the .o file might go into a shared
+ library, and some other shared library might override that symbol. */
+#define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \
+ ((FIX)->fx_addsy == NULL \
+ || (! S_IS_EXTERNAL ((FIX)->fx_addsy) \
+ && ! S_IS_WEAK ((FIX)->fx_addsy) \
+ && S_IS_DEFINED ((FIX)->fx_addsy) \
+ && ! S_IS_COMMON ((FIX)->fx_addsy)))
#endif /* OBJ_ELF */
/* call md_apply_fix3 with segment instead of md_apply_fix */
#define MD_APPLY_FIX3
+/* call md_pcrel_from_section, not md_pcrel_from */
+#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section(FIXP, SEC)
+extern long md_pcrel_from_section PARAMS ((struct fix *, segT));
+
+#define md_parse_name(name, exp) ppc_parse_name (name, exp)
+extern int ppc_parse_name PARAMS ((const char *, struct expressionS *));
+
#define md_operand(x)
+