freebsd.h revision 73305
134229Speter/* Definitions for Intel 386 running FreeBSD with either a.out or ELF format 258478Sobrien Copyright (C) 1996-2000 Free Software Foundation, Inc. 334229Speter Contributed by Eric Youngdale. 434229Speter Modified for stabs-in-ELF by H.J. Lu. 551408Sobrien Adapted from GNU/Linux version by John Polstra. 634229Speter Added support for generating "old a.out gas" on the fly by Peter Wemm. 752112Sobrien Continued development by David O'Brien <obrien@freebsd.org> 818334Speter 918334SpeterThis file is part of GNU CC. 1018334Speter 1118334SpeterGNU CC is free software; you can redistribute it and/or modify 1218334Speterit under the terms of the GNU General Public License as published by 1318334Speterthe Free Software Foundation; either version 2, or (at your option) 1418334Speterany later version. 1518334Speter 1618334SpeterGNU CC is distributed in the hope that it will be useful, 1718334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of 1818334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1918334SpeterGNU General Public License for more details. 2018334Speter 2118334SpeterYou should have received a copy of the GNU General Public License 2218334Speteralong with GNU CC; see the file COPYING. If not, write to 2318334Speterthe Free Software Foundation, 59 Temple Place - Suite 330, 2418334SpeterBoston, MA 02111-1307, USA. */ 2518334Speter 2651408Sobrien/* $FreeBSD: head/contrib/gcc/config/i386/freebsd.h 73305 2001-03-02 02:46:05Z obrien $ */ 2718334Speter 2858478Sobrien#undef CPP_PREDEFINES 2958478Sobrien#define CPP_PREDEFINES \ 3058478Sobrien "-Di386 -Acpu(i386) -Amachine(i386)" \ 3158478Sobrien FBSD_CPP_PREDEFINES 3251408Sobrien 3358478Sobrien#undef CC1_SPEC 3458478Sobrien#define CC1_SPEC "\ 3558478Sobrien %{gline:%{!g:%{!g0:%{!g1:%{!g2: -g1}}}}} \ 3658478Sobrien %{maout: %{!mno-underscores: %{!munderscores: -munderscores }}}" 3751408Sobrien 3858478Sobrien#undef ASM_SPEC 3958478Sobrien#define ASM_SPEC "%{v*: -v} %{maout: %{fpic:-k} %{fPIC:-k}}" 4058478Sobrien 4158478Sobrien#undef ASM_FINAL_SPEC 4258478Sobrien#define ASM_FINAL_SPEC "%|" 4358478Sobrien 4458478Sobrien/* Provide a LINK_SPEC appropriate for FreeBSD. Here we provide support 4558478Sobrien for the special GCC options -static and -shared, which allow us to 4658478Sobrien link things in one of these three modes by applying the appropriate 4758478Sobrien combinations of options at link-time. We like to support here for 4858478Sobrien as many of the other GNU linker options as possible. But I don't 4958478Sobrien have the time to search for those flags. I am sure how to add 5058478Sobrien support for -soname shared_object_name. H.J. 5158478Sobrien 5258478Sobrien I took out %{v:%{!V:-V}}. It is too much :-(. They can use 5358478Sobrien -Wl,-V. 5458478Sobrien 5558478Sobrien When the -shared link option is used a final link is not being 5658478Sobrien done. */ 5758478Sobrien 5858478Sobrien#undef LINK_SPEC 5958478Sobrien#define LINK_SPEC "\ 6058478Sobrien %{p:%e`-p' not supported; use `-pg' and gprof(1)} \ 6158478Sobrien %{maout: %{shared:-Bshareable} \ 6258478Sobrien %{!shared:%{!nostdlib:%{!r:%{!e*:-e start}}} -dc -dp %{static:-Bstatic} \ 6358478Sobrien %{pg:-Bstatic} %{Z}} \ 6458478Sobrien %{assert*} %{R*}} \ 6558478Sobrien %{!maout: \ 6658478Sobrien -m elf_i386 \ 6758478Sobrien %{Wl,*:%*} \ 6858478Sobrien %{assert*} %{R*} %{rpath*} %{defsym*} \ 6958478Sobrien %{shared:-Bshareable %{h*} %{soname*}} \ 7058478Sobrien %{symbolic:-Bsymbolic} \ 7158478Sobrien %{!shared: \ 7258478Sobrien %{!static: \ 7358478Sobrien %{rdynamic: -export-dynamic} \ 7458478Sobrien %{!dynamic-linker: -dynamic-linker /usr/libexec/ld-elf.so.1}} \ 7558478Sobrien %{static:-Bstatic}}}" 7658478Sobrien 7758478Sobrien#undef STARTFILE_SPEC 7858478Sobrien#define STARTFILE_SPEC "\ 7958478Sobrien %{maout: %{shared:c++rt0.o%s} \ 8058478Sobrien %{!shared: \ 8158478Sobrien %{pg:gcrt0.o%s}%{!pg: \ 8258478Sobrien %{static:scrt0.o%s} \ 8358478Sobrien %{!static:crt0.o%s}}}} \ 8458478Sobrien %{!maout: \ 8558478Sobrien %{!shared: \ 8658478Sobrien %{pg:gcrt1.o%s} \ 8758478Sobrien %{!pg: \ 8858478Sobrien %{p:gcrt1.o%s} \ 8958478Sobrien %{!p:crt1.o%s}}} \ 9058478Sobrien crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}" 9158478Sobrien 9258478Sobrien/* Provide an ENDFILE_SPEC appropriate for FreeBSD/i386. Here we tack on our 9358478Sobrien own magical crtend.o file (compare w/crtstuff.c) which provides part of the 9458478Sobrien support for getting C++ file-scope static object constructed before 9558478Sobrien entering `main', followed by the normal "finalizer" file, `crtn.o'. */ 9658478Sobrien 9758478Sobrien#undef ENDFILE_SPEC 9858478Sobrien#define ENDFILE_SPEC "\ 9958478Sobrien %{!maout: \ 10058478Sobrien %{!shared:crtend.o%s} \ 10158478Sobrien %{shared:crtendS.o%s} crtn.o%s}" 10258478Sobrien 10358478Sobrien 10458478Sobrien/************************[ Target stuff ]***********************************/ 10558478Sobrien 10658478Sobrien/* Define the actual types of some ANSI-mandated types. 10758478Sobrien Needs to agree with <machine/ansi.h>. GCC defaults come from c-decl.c, 10858478Sobrien c-common.c, and config/<arch>/<arch>.h. */ 10958478Sobrien 11058478Sobrien#undef SIZE_TYPE 11158478Sobrien#define SIZE_TYPE "unsigned int" 11258478Sobrien 11358478Sobrien#undef PTRDIFF_TYPE 11458478Sobrien#define PTRDIFF_TYPE "int" 11558478Sobrien 11658478Sobrien/* This is the pseudo-op used to generate a 32-bit word of data with a 11758478Sobrien specific value in some section. */ 11858478Sobrien 11958478Sobrien#undef INT_ASM_OP 12058478Sobrien#define INT_ASM_OP ".long" 12158478Sobrien 12258478Sobrien/* Biggest alignment supported by the object file format of this 12358478Sobrien machine. Use this macro to limit the alignment which can be 12458478Sobrien specified using the `__attribute__ ((aligned (N)))' construct. If 12558478Sobrien not defined, the default value is `BIGGEST_ALIGNMENT'. */ 12658478Sobrien 12758478Sobrien#define MAX_OFILE_ALIGNMENT (32768*8) 12858478Sobrien 12958478Sobrien#undef TARGET_VERSION 13058478Sobrien#define TARGET_VERSION fprintf (stderr, " (i386 FreeBSD/ELF)"); 13158478Sobrien 13234229Speter#define MASK_PROFILER_EPILOGUE 010000000000 13334229Speter#define MASK_AOUT 004000000000 /* a.out not elf */ 13434229Speter#define MASK_UNDERSCORES 002000000000 /* use leading _ */ 13518349Speter 13634229Speter#define TARGET_PROFILER_EPILOGUE (target_flags & MASK_PROFILER_EPILOGUE) 13734229Speter#define TARGET_AOUT (target_flags & MASK_AOUT) 13834229Speter#define TARGET_ELF ((target_flags & MASK_AOUT) == 0) 13934229Speter#define TARGET_UNDERSCORES ((target_flags & MASK_UNDERSCORES) != 0) 14018349Speter 14134229Speter#undef SUBTARGET_SWITCHES 14252112Sobrien#define SUBTARGET_SWITCHES \ 14368601Sobrien { "profiler-epilogue", MASK_PROFILER_EPILOGUE, "Function profiler epilogue"}, \ 14468601Sobrien { "no-profiler-epilogue", -MASK_PROFILER_EPILOGUE, "No function profiler epilogue"}, \ 14568601Sobrien { "aout", MASK_AOUT, "Generate an a.out (vs. ELF) binary"}, \ 14668601Sobrien { "no-aout", -MASK_AOUT, "Do not generate an a.out binary"}, \ 14768601Sobrien { "underscores", MASK_UNDERSCORES, "Add leading underscores to symbols"}, \ 14868601Sobrien { "no-underscores", -MASK_UNDERSCORES, "Do not add leading underscores to symbols"}, 14918349Speter 15058478Sobrien/* This goes away when the math emulator is fixed. */ 15158478Sobrien#undef TARGET_DEFAULT 15258478Sobrien#define TARGET_DEFAULT \ 15358478Sobrien (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_NO_FANCY_MATH_387) 15458478Sobrien 15534229Speter/* Prefix for internally generated assembler labels. If we aren't using 15634229Speter underscores, we are using prefix `.'s to identify labels that should 15734229Speter be ignored, as in `i386/gas.h' --karl@cs.umb.edu */ 15834229Speter#undef LPREFIX 15934229Speter#define LPREFIX ((TARGET_UNDERSCORES) ? "L" : ".L") 16018349Speter 16158478Sobrien/* The a.out tools do not support "linkonce" sections. */ 16258478Sobrien#undef SUPPORTS_ONE_ONLY 16358478Sobrien#define SUPPORTS_ONE_ONLY TARGET_ELF 16418349Speter 16558478Sobrien/* Enable alias attribute support. */ 16658478Sobrien#undef SET_ASM_OP 16758478Sobrien#define SET_ASM_OP ".set" 16818349Speter 16958478Sobrien/* The a.out tools do not support "Lscope" .stabs symbols. */ 17058478Sobrien#undef NO_DBX_FUNCTION_END 17158478Sobrien#define NO_DBX_FUNCTION_END TARGET_AOUT 17251408Sobrien 17358478Sobrien/* In ELF, the function stabs come first, before the relative offsets. */ 17458478Sobrien#undef DBX_FUNCTION_FIRST 17558478Sobrien#define DBX_CHECK_FUNCTION_FIRST TARGET_ELF 17618349Speter 17758478Sobrien/* supply our own hook for calling __main() from main() */ 17858478Sobrien#undef INVOKE__main 17958478Sobrien#define INVOKE__main 18058478Sobrien#undef GEN_CALL__MAIN 18158478Sobrien#define GEN_CALL__MAIN \ 18258478Sobrien do { \ 18358478Sobrien if (!(TARGET_ELF)) \ 18458478Sobrien emit_library_call (gen_rtx (SYMBOL_REF, Pmode, NAME__MAIN), 0, \ 18558478Sobrien VOIDmode, 0); \ 18658478Sobrien } while (0) 18758478Sobrien 18858478Sobrien/* Indicate that jump tables go in the text section. This is 18958478Sobrien necessary when compiling PIC code. */ 19058478Sobrien#undef JUMP_TABLES_IN_TEXT_SECTION 19158478Sobrien#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) 19258478Sobrien 19358478Sobrien/* override the exception table positioning */ 19458478Sobrien#undef EXCEPTION_SECTION 19558478Sobrien#define EXCEPTION_SECTION() \ 19658478Sobrien do { \ 19758478Sobrien if (TARGET_ELF) \ 19858478Sobrien { \ 19958478Sobrien named_section (NULL_TREE, ".gcc_except_table", 0); \ 20058478Sobrien } \ 20158478Sobrien else \ 20258478Sobrien { \ 20358478Sobrien if (flag_pic) \ 20458478Sobrien data_section (); \ 20558478Sobrien else \ 20658478Sobrien readonly_data_section (); \ 20758478Sobrien } \ 20858478Sobrien } while (0); 20958478Sobrien 21058478Sobrien/* Tell final.c that we don't need a label passed to mcount. */ 21158478Sobrien#undef NO_PROFILE_DATA 21258478Sobrien#define NO_PROFILE_DATA 21358478Sobrien 21458478Sobrien/* Output assembler code to FILE to begin profiling of the current function. 21558478Sobrien LABELNO is an optional label. */ 21658478Sobrien 21758478Sobrien#undef FUNCTION_PROFILER 21858478Sobrien#define FUNCTION_PROFILER(FILE, LABELNO) \ 21958478Sobrien do { \ 22058478Sobrien char *_name = TARGET_AOUT ? "mcount" : ".mcount"; \ 22158478Sobrien if (flag_pic) \ 22258478Sobrien fprintf ((FILE), "\tcall *%s@GOT(%%ebx)\n", _name); \ 22358478Sobrien else \ 22458478Sobrien fprintf ((FILE), "\tcall %s\n", _name); \ 22558478Sobrien } while (0) 22658478Sobrien 22758478Sobrien/* Output assembler code to FILE to end profiling of the current function. */ 22858478Sobrien 22958478Sobrien#undef FUNCTION_PROFILER_EPILOGUE 23058478Sobrien#define FUNCTION_PROFILER_EPILOGUE(FILE, DO_RTL) \ 23158478Sobrien do { \ 23258478Sobrien if (TARGET_PROFILER_EPILOGUE) \ 23358478Sobrien { \ 23458478Sobrien if (DO_RTL) \ 23558478Sobrien { \ 23658478Sobrien /* ".mexitcount" is specially handled in \ 23758478Sobrien ASM_HACK_SYMBOLREF () so that we don't need to handle \ 23858478Sobrien flag_pic or TARGET_AOUT here. */ \ 23958478Sobrien rtx xop; \ 24058478Sobrien xop = gen_rtx_MEM (FUNCTION_MODE, \ 24158478Sobrien gen_rtx_SYMBOL_REF (Pmode, ".mexitcount")); \ 24258478Sobrien emit_call_insn (gen_rtx (CALL, VOIDmode, xop, const0_rtx)); \ 24358478Sobrien } \ 24458478Sobrien else \ 24558478Sobrien { \ 24658478Sobrien /* XXX this !DO_RTL case is broken but not actually used. */ \ 24758478Sobrien char *_name = TARGET_AOUT ? "mcount" : ".mcount"; \ 24858478Sobrien if (flag_pic) \ 24958478Sobrien fprintf (FILE, "\tcall *%s@GOT(%%ebx)\n", _name); \ 25058478Sobrien else \ 25158478Sobrien fprintf (FILE, "\tcall %s\n", _name); \ 25258478Sobrien } \ 25358478Sobrien } \ 25458478Sobrien } while (0) 25558478Sobrien 25658478Sobrien 25758478Sobrien/************************[ Assembler stuff ]********************************/ 25858478Sobrien 25958478Sobrien#undef ASM_APP_ON 26058478Sobrien#define ASM_APP_ON "#APP\n" 26158478Sobrien 26258478Sobrien#undef ASM_APP_OFF 26358478Sobrien#define ASM_APP_OFF "#NO_APP\n" 26458478Sobrien 26558478Sobrien/* This is how to begin an assembly language file. 26658478Sobrien The .file command should always begin the output. 26758478Sobrien ELF also needs a .version. */ 26858478Sobrien 26958478Sobrien#undef ASM_FILE_START 27034229Speter#define ASM_FILE_START(FILE) \ 27134229Speter do { \ 27258478Sobrien output_file_directive ((FILE), main_input_filename); \ 27358478Sobrien if (TARGET_ELF) \ 27458478Sobrien fprintf ((FILE), "\t.version\t\"01.01\"\n"); \ 27534229Speter } while (0) 27618349Speter 27734229Speter/* This is how to store into the string BUF 27834229Speter the symbol_ref name of an internal numbered label where 27934229Speter PREFIX is the class of label and NUM is the number within the class. 28034229Speter This is suitable for output with `assemble_name'. */ 28134229Speter#undef ASM_GENERATE_INTERNAL_LABEL 28258478Sobrien#define ASM_GENERATE_INTERNAL_LABEL(BUF, PREFIX, NUMBER) \ 28358478Sobrien sprintf ((BUF), "*%s%s%d", (TARGET_UNDERSCORES) ? "" : ".", \ 28458478Sobrien (PREFIX), (NUMBER)) 28518349Speter 28634229Speter/* This is how to output an internal numbered label where 28758478Sobrien PREFIX is the class of label and NUM is the number within the class. 28858478Sobrien For most svr4/ELF systems, the convention is that any symbol which begins 28958478Sobrien with a period is not put into the linker symbol table by the assembler. */ 29034229Speter#undef ASM_OUTPUT_INTERNAL_LABEL 29134229Speter#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ 29252112Sobrien fprintf ((FILE), "%s%s%d:\n", (TARGET_UNDERSCORES) ? "" : ".", \ 29352112Sobrien (PREFIX), (NUM)) 29418334Speter 29558478Sobrien/* This is how to output a reference to a user-level label named NAME. */ 29658478Sobrien#undef ASM_OUTPUT_LABELREF 29758478Sobrien#define ASM_OUTPUT_LABELREF(FILE, NAME) \ 29858478Sobrien do { \ 29958478Sobrien char *_name = (NAME); \ 30058478Sobrien /* Hack to avoid writing lots of rtl in \ 30158478Sobrien FUNCTION_PROFILER_EPILOGUE (). */ \ 30258478Sobrien if (*_name == '.' && strcmp(_name + 1, "mexitcount") == 0) \ 30358478Sobrien { \ 30458478Sobrien if (TARGET_AOUT) \ 30558478Sobrien _name++; \ 30658478Sobrien if (flag_pic) \ 30758478Sobrien fprintf ((FILE), "*%s@GOT(%%ebx)", _name); \ 30858478Sobrien else \ 30958478Sobrien fprintf ((FILE), "%s", _name); \ 31058478Sobrien } \ 31158478Sobrien else \ 31258478Sobrien fprintf (FILE, "%s%s", TARGET_UNDERSCORES ? "_" : "", _name); \ 31358478Sobrien} while (0) 31458478Sobrien 31556810Sobrien/* This is how to hack on the symbol code of certain relcalcitrant 31656810Sobrien symbols to modify their output in output_pic_addr_const (). */ 31756810Sobrien 31858478Sobrien#undef ASM_HACK_SYMBOLREF_CODE 31956810Sobrien#define ASM_HACK_SYMBOLREF_CODE(NAME, CODE) \ 32058478Sobrien do { \ 32158478Sobrien /* Part of hack to avoid writing lots of rtl in \ 32258478Sobrien FUNCTION_PROFILER_EPILOGUE (). */ \ 32358478Sobrien char *_name = (NAME); \ 32458478Sobrien if (*_name == '.' && strcmp(_name + 1, "mexitcount") == 0) \ 32558478Sobrien (CODE) = 'X'; \ 32658478Sobrien } while (0) 32756810Sobrien 32834229Speter/* This is how to output an element of a case-vector that is relative. 32934229Speter This is only used for PIC code. See comments by the `casesi' insn in 33034229Speter i386.md for an explanation of the expression this outputs. */ 33158478Sobrien#undef ASM_OUTPUT_ADDR_DIFF_ELT 33258478Sobrien#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ 33352112Sobrien fprintf ((FILE), "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, (VALUE)) 33418349Speter 33558478Sobrien#undef ASM_OUTPUT_ALIGN 33652112Sobrien#define ASM_OUTPUT_ALIGN(FILE, LOG) \ 33751408Sobrien if ((LOG)!=0) { \ 33851408Sobrien if (in_text_section()) \ 33951408Sobrien fprintf ((FILE), "\t.p2align %d,0x90\n", (LOG)); \ 34051408Sobrien else \ 34151408Sobrien fprintf ((FILE), "\t.p2align %d\n", (LOG)); \ 34251408Sobrien } 34318349Speter 34473305Sobrien#undef ASM_OUTPUT_ALIGNED_COMMON 34573305Sobrien#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \ 34673305Sobrien do { \ 34773305Sobrien if (TARGET_ELF) \ 34873305Sobrien { \ 34973305Sobrien fprintf ((FILE), "%s", COMMON_ASM_OP); \ 35073305Sobrien assemble_name ((FILE), (NAME)); \ 35173305Sobrien fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \ 35273305Sobrien } \ 35373305Sobrien else \ 35473305Sobrien { \ 35573305Sobrien int rounded = (SIZE); \ 35673305Sobrien if (rounded == 0) rounded = 1; \ 35773305Sobrien rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1; \ 35873305Sobrien rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) \ 35973305Sobrien * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); \ 36073305Sobrien fprintf ((FILE), "%s ", COMMON_ASM_OP); \ 36173305Sobrien assemble_name ((FILE), (NAME)); \ 36273305Sobrien fprintf ((FILE), ",%u\n", (rounded)); \ 36373305Sobrien } \ 36473305Sobrien } while (0) 36573305Sobrien 36673305Sobrien/* This says how to output assembler code to declare an 36773305Sobrien uninitialized internal linkage data object. Under SVR4, 36873305Sobrien the linker seems to want the alignment of data objects 36973305Sobrien to depend on their types. We do exactly that here. */ 37073305Sobrien 37173305Sobrien#undef ASM_OUTPUT_ALIGNED_LOCAL 37273305Sobrien#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ 37373305Sobrien do { \ 37473305Sobrien if (TARGET_ELF) \ 37573305Sobrien { \ 37673305Sobrien fprintf ((FILE), "%s", LOCAL_ASM_OP); \ 37773305Sobrien assemble_name ((FILE), (NAME)); \ 37873305Sobrien fprintf ((FILE), "\n"); \ 37973305Sobrien ASM_OUTPUT_ALIGNED_COMMON ((FILE), (NAME), (SIZE), (ALIGN)); \ 38073305Sobrien } \ 38173305Sobrien else \ 38273305Sobrien { \ 38373305Sobrien int rounded = (SIZE); \ 38473305Sobrien if (rounded == 0) rounded = 1; \ 38573305Sobrien rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1; \ 38673305Sobrien rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) \ 38773305Sobrien * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); \ 38873305Sobrien fputs ("\t.lcomm\t", (FILE)); \ 38973305Sobrien assemble_name ((FILE), (NAME)); \ 39073305Sobrien fprintf ((FILE), ",%u\n", (rounded)); \ 39173305Sobrien } \ 39273305Sobrien } while (0) 39373305Sobrien 39473305Sobrien/* How to output some space. The rules are different depending on the 39573305Sobrien object format. */ 39673305Sobrien#undef ASM_OUTPUT_SKIP 39773305Sobrien#define ASM_OUTPUT_SKIP(FILE, SIZE) \ 39873305Sobrien do { \ 39973305Sobrien if (TARGET_ELF) \ 40073305Sobrien { \ 40173305Sobrien fprintf ((FILE), "%s%u\n", SKIP_ASM_OP, (SIZE)); \ 40273305Sobrien } \ 40373305Sobrien else \ 40473305Sobrien { \ 40573305Sobrien fprintf ((FILE), "\t.space\t%u\n", (SIZE)); \ 40673305Sobrien } \ 40773305Sobrien } while (0) 40873305Sobrien 40973305Sobrien 41058478Sobrien#undef ASM_OUTPUT_SOURCE_LINE 41158478Sobrien#define ASM_OUTPUT_SOURCE_LINE(FILE, LINE) \ 41258478Sobrien do { \ 41358478Sobrien static int sym_lineno = 1; \ 41458478Sobrien if (TARGET_ELF) \ 41558478Sobrien { \ 41658478Sobrien fprintf ((FILE), ".stabn 68,0,%d,.LM%d-", (LINE), sym_lineno); \ 41758478Sobrien assemble_name ((FILE), \ 41858478Sobrien XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \ 41958478Sobrien fprintf ((FILE), "\n.LM%d:\n", sym_lineno); \ 42058478Sobrien sym_lineno += 1; \ 42158478Sobrien } \ 42258478Sobrien else \ 42358478Sobrien { \ 42458478Sobrien fprintf ((FILE), "\t%s %d,0,%d\n", ASM_STABD_OP, N_SLINE, \ 42558478Sobrien lineno); \ 42658478Sobrien } \ 42758478Sobrien } while (0) 42818334Speter 42958478Sobrien/* These macros generate the special .type and .size directives which 43058478Sobrien are used to set the corresponding fields of the linker symbol table 43158478Sobrien entries in an ELF object file under SVR4. These macros also output 43258478Sobrien the starting labels for the relevant functions/objects. */ 43351408Sobrien 43458478Sobrien/* Write the extra assembler code needed to declare a function properly. 43558478Sobrien Some svr4 assemblers need to also have something extra said about the 43658478Sobrien function's return value. We allow for that here. */ 43751408Sobrien 43858478Sobrien#undef ASM_DECLARE_FUNCTION_NAME 43958478Sobrien#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ 44034229Speter do { \ 44158478Sobrien fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ 44258478Sobrien assemble_name (FILE, NAME); \ 44358478Sobrien putc (',', FILE); \ 44458478Sobrien fprintf (FILE, TYPE_OPERAND_FMT, "function"); \ 44558478Sobrien putc ('\n', FILE); \ 44658478Sobrien ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \ 44758478Sobrien ASM_OUTPUT_LABEL(FILE, NAME); \ 44834229Speter } while (0) 44918334Speter 45058478Sobrien/* This is how to declare the size of a function. */ 45118349Speter 45258478Sobrien#undef ASM_DECLARE_FUNCTION_SIZE 45358478Sobrien#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ 45458478Sobrien do { \ 45558478Sobrien if (!flag_inhibit_size_directive) \ 45658478Sobrien { \ 45758478Sobrien char label[256]; \ 45858478Sobrien static int labelno; \ 45958478Sobrien labelno++; \ 46058478Sobrien ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \ 46158478Sobrien ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \ 46258478Sobrien fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ 46358478Sobrien assemble_name (FILE, (FNAME)); \ 46458478Sobrien fprintf (FILE, ","); \ 46558478Sobrien assemble_name (FILE, label); \ 46658478Sobrien fprintf (FILE, "-"); \ 46758478Sobrien assemble_name (FILE, (FNAME)); \ 46858478Sobrien putc ('\n', FILE); \ 46958478Sobrien } \ 47058478Sobrien } while (0) 47118334Speter 47218334Speter 47358478Sobrien/* The routine used to output NUL terminated strings. We use a special 47458478Sobrien version of this for most svr4 targets because doing so makes the 47558478Sobrien generated assembly code more compact (and thus faster to assemble) 47658478Sobrien as well as more readable, especially for targets like the i386 47758478Sobrien (where the only alternative is to output character sequences as 47858478Sobrien comma separated lists of numbers). */ 47918334Speter 48058478Sobrien#undef ASM_OUTPUT_LIMITED_STRING 48158478Sobrien#define ASM_OUTPUT_LIMITED_STRING(FILE, STR) \ 48258478Sobrien do { \ 48358478Sobrien register unsigned char *_limited_str = (unsigned char *) (STR); \ 48458478Sobrien register unsigned ch; \ 48558478Sobrien fprintf ((FILE), "\t%s\t\"", STRING_ASM_OP); \ 48658478Sobrien for (; (ch = *_limited_str); _limited_str++) \ 48758478Sobrien { \ 48858478Sobrien register int escape; \ 48958478Sobrien switch (escape = ESCAPES[ch]) \ 49058478Sobrien { \ 49158478Sobrien case 0: \ 49258478Sobrien putc (ch, (FILE)); \ 49358478Sobrien break; \ 49458478Sobrien case 1: \ 49558478Sobrien fprintf ((FILE), "\\%03o", ch); \ 49658478Sobrien break; \ 49758478Sobrien default: \ 49858478Sobrien putc ('\\', (FILE)); \ 49958478Sobrien putc (escape, (FILE)); \ 50058478Sobrien break; \ 50158478Sobrien } \ 50258478Sobrien } \ 50358478Sobrien fprintf ((FILE), "\"\n"); \ 50458478Sobrien } while (0) 50534269Speter 50658478Sobrien/* Switch into a generic section. 50758478Sobrien 50858478Sobrien We make the section read-only and executable for a function decl, 50958478Sobrien read-only for a const data decl, and writable for a non-const data decl. 51058478Sobrien 51158478Sobrien If the section has already been defined, we must not 51258478Sobrien emit the attributes here. The SVR4 assembler does not 51358478Sobrien recognize section redefinitions. 51458478Sobrien If DECL is NULL, no attributes are emitted. */ 51534284Speter 51658478Sobrien#undef ASM_OUTPUT_SECTION_NAME 51758478Sobrien#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \ 51858478Sobrien do { \ 51958478Sobrien static struct section_info \ 52058478Sobrien { \ 52158478Sobrien struct section_info *next; \ 52258478Sobrien char *name; \ 52358478Sobrien enum sect_enum {SECT_RW, SECT_RO, SECT_EXEC} type; \ 52458478Sobrien } *sections; \ 52558478Sobrien struct section_info *s; \ 52658478Sobrien char *mode; \ 52758478Sobrien enum sect_enum type; \ 52858478Sobrien \ 52958478Sobrien for (s = sections; s; s = s->next) \ 53058478Sobrien if (!strcmp (NAME, s->name)) \ 53158478Sobrien break; \ 53258478Sobrien \ 53358478Sobrien if (DECL && TREE_CODE (DECL) == FUNCTION_DECL) \ 53458478Sobrien type = SECT_EXEC, mode = "ax"; \ 53558478Sobrien else if (DECL && DECL_READONLY_SECTION (DECL, RELOC)) \ 53658478Sobrien type = SECT_RO, mode = "a"; \ 53758478Sobrien else \ 53858478Sobrien type = SECT_RW, mode = "aw"; \ 53958478Sobrien \ 54058478Sobrien if (s == 0) \ 54158478Sobrien { \ 54258478Sobrien s = (struct section_info *) xmalloc (sizeof (struct section_info)); \ 54358478Sobrien s->name = xmalloc ((strlen (NAME) + 1) * sizeof (*NAME)); \ 54458478Sobrien strcpy (s->name, NAME); \ 54558478Sobrien s->type = type; \ 54658478Sobrien s->next = sections; \ 54758478Sobrien sections = s; \ 54858478Sobrien fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, mode); \ 54958478Sobrien } \ 55058478Sobrien else \ 55158478Sobrien { \ 55258478Sobrien if (DECL && s->type != type) \ 55358478Sobrien error_with_decl (DECL, "%s causes a section type conflict"); \ 55458478Sobrien \ 55558478Sobrien fprintf (FILE, ".section\t%s\n", NAME); \ 55658478Sobrien } \ 55758478Sobrien } while (0) 55818334Speter 55958478Sobrien#undef MAKE_DECL_ONE_ONLY 56058478Sobrien#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1) 56158478Sobrien#undef UNIQUE_SECTION_P 56258478Sobrien#define UNIQUE_SECTION_P(DECL) (DECL_ONE_ONLY (DECL)) 56358478Sobrien#undef UNIQUE_SECTION 56458478Sobrien#define UNIQUE_SECTION(DECL,RELOC) \ 56558478Sobrien do { \ 56658478Sobrien int len; \ 56758478Sobrien char *name, *string, *prefix; \ 56858478Sobrien \ 56958478Sobrien name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \ 57058478Sobrien \ 57158478Sobrien if (! DECL_ONE_ONLY (DECL)) \ 57258478Sobrien { \ 57358478Sobrien prefix = "."; \ 57458478Sobrien if (TREE_CODE (DECL) == FUNCTION_DECL) \ 57558478Sobrien prefix = ".text."; \ 57658478Sobrien else if (DECL_READONLY_SECTION (DECL, RELOC)) \ 57758478Sobrien prefix = ".rodata."; \ 57858478Sobrien else \ 57958478Sobrien prefix = ".data."; \ 58058478Sobrien } \ 58158478Sobrien else if (TREE_CODE (DECL) == FUNCTION_DECL) \ 58258478Sobrien prefix = ".gnu.linkonce.t."; \ 58358478Sobrien else if (DECL_READONLY_SECTION (DECL, RELOC)) \ 58458478Sobrien prefix = ".gnu.linkonce.r."; \ 58558478Sobrien else \ 58658478Sobrien prefix = ".gnu.linkonce.d."; \ 58758478Sobrien \ 58858478Sobrien len = strlen (name) + strlen (prefix); \ 58958478Sobrien string = alloca (len + 1); \ 59058478Sobrien sprintf (string, "%s%s", prefix, name); \ 59158478Sobrien \ 59258478Sobrien DECL_SECTION_NAME (DECL) = build_string (len, string); \ 59358478Sobrien } while (0) 59434229Speter 59558478Sobrien/* A C statement or statements to switch to the appropriate 59658478Sobrien section for output of DECL. DECL is either a `VAR_DECL' node 59758478Sobrien or a constant of some sort. RELOC indicates whether forming 59858478Sobrien the initial value of DECL requires link-time relocations. */ 59934229Speter 60058478Sobrien#undef SELECT_SECTION 60158478Sobrien#define SELECT_SECTION(DECL,RELOC) \ 60258478Sobrien { \ 60358478Sobrien if (flag_pic && RELOC) \ 60458478Sobrien data_section (); \ 60558478Sobrien else if (TREE_CODE (DECL) == STRING_CST) \ 60658478Sobrien { \ 60758478Sobrien if (! flag_writable_strings) \ 60858478Sobrien const_section (); \ 60958478Sobrien else \ 61058478Sobrien data_section (); \ 61158478Sobrien } \ 61258478Sobrien else if (TREE_CODE (DECL) == VAR_DECL) \ 61358478Sobrien { \ 61458478Sobrien if (! DECL_READONLY_SECTION (DECL, RELOC)) \ 61558478Sobrien data_section (); \ 61658478Sobrien else \ 61758478Sobrien const_section (); \ 61858478Sobrien } \ 61958478Sobrien else \ 62058478Sobrien const_section (); \ 62158478Sobrien } 62258478Sobrien 62373305Sobrien/* A C statement (sans semicolon) to output an element in the table of 62473305Sobrien global constructors. */ 62573305Sobrien#undef ASM_OUTPUT_CONSTRUCTOR 62673305Sobrien#define ASM_OUTPUT_CONSTRUCTOR(FILE, NAME) \ 62773305Sobrien do { \ 62873305Sobrien if (TARGET_ELF) \ 62973305Sobrien { \ 63073305Sobrien ctors_section (); \ 63173305Sobrien fprintf ((FILE), "%s ", INT_ASM_OP); \ 63273305Sobrien assemble_name ((FILE), (NAME)); \ 63373305Sobrien fprintf ((FILE), "\n"); \ 63473305Sobrien } \ 63573305Sobrien else \ 63673305Sobrien { \ 63773305Sobrien fprintf (asm_out_file, "%s \"%s__CTOR_LIST__\",22,0,0,", \ 63873305Sobrien ASM_STABS_OP, (TARGET_UNDERSCORES) ? "_" : ""); \ 63973305Sobrien assemble_name (asm_out_file, name); \ 64073305Sobrien fputc ('\n', asm_out_file); \ 64173305Sobrien } \ 64273305Sobrien } while (0) 64373305Sobrien 64473305Sobrien/* A C statement (sans semicolon) to output an element in the table of 64573305Sobrien global destructors. */ 64673305Sobrien#undef ASM_OUTPUT_DESTRUCTOR 64773305Sobrien#define ASM_OUTPUT_DESTRUCTOR(FILE, NAME) \ 64873305Sobrien do { \ 64973305Sobrien if (TARGET_ELF) \ 65073305Sobrien { \ 65173305Sobrien dtors_section (); \ 65273305Sobrien fprintf ((FILE), "%s ", INT_ASM_OP); \ 65373305Sobrien assemble_name ((FILE), (NAME)); \ 65473305Sobrien fprintf ((FILE), "\n"); \ 65573305Sobrien } \ 65673305Sobrien else \ 65773305Sobrien { \ 65873305Sobrien fprintf (asm_out_file, "%s \"%s__DTOR_LIST__\",22,0,0,", \ 65973305Sobrien ASM_STABS_OP, (TARGET_UNDERSCORES) ? "_" : ""); \ 66073305Sobrien assemble_name (asm_out_file, name); \ 66173305Sobrien fputc ('\n', asm_out_file); \ 66273305Sobrien } \ 66373305Sobrien } while (0) 66473305Sobrien 66534229Speter/* Define macro used to output shift-double opcodes when the shift 66634229Speter count is in %cl. Some assemblers require %cl as an argument; 66734229Speter some don't. 66834229Speter 66934229Speter *OLD* GAS requires the %cl argument, so override i386/unix.h. */ 67034229Speter 67158478Sobrien#undef AS3_SHIFT_DOUBLE 67258478Sobrien#define AS3_SHIFT_DOUBLE(a,b,c,d) AS3 (a,b,c,d) 67334229Speter 67418334Speter 67558478Sobrien/************************[ Debugger stuff ]*********************************/ 67618334Speter 67751408Sobrien/* Copy this from the svr4 specifications... */ 67851408Sobrien/* Define the register numbers to be used in Dwarf debugging information. 67951408Sobrien The SVR4 reference port C compiler uses the following register numbers 68051408Sobrien in its Dwarf output code: 68151408Sobrien 0 for %eax (gnu regno = 0) 68251408Sobrien 1 for %ecx (gnu regno = 2) 68351408Sobrien 2 for %edx (gnu regno = 1) 68451408Sobrien 3 for %ebx (gnu regno = 3) 68551408Sobrien 4 for %esp (gnu regno = 7) 68651408Sobrien 5 for %ebp (gnu regno = 6) 68751408Sobrien 6 for %esi (gnu regno = 4) 68851408Sobrien 7 for %edi (gnu regno = 5) 68951408Sobrien The following three DWARF register numbers are never generated by 69051408Sobrien the SVR4 C compiler or by the GNU compilers, but SDB on x86/svr4 69151408Sobrien believes these numbers have these meanings. 69251408Sobrien 8 for %eip (no gnu equivalent) 69351408Sobrien 9 for %eflags (no gnu equivalent) 69451408Sobrien 10 for %trapno (no gnu equivalent) 69551408Sobrien It is not at all clear how we should number the FP stack registers 69651408Sobrien for the x86 architecture. If the version of SDB on x86/svr4 were 69751408Sobrien a bit less brain dead with respect to floating-point then we would 69851408Sobrien have a precedent to follow with respect to DWARF register numbers 69951408Sobrien for x86 FP registers, but the SDB on x86/svr4 is so completely 70051408Sobrien broken with respect to FP registers that it is hardly worth thinking 70151408Sobrien of it as something to strive for compatibility with. 70251408Sobrien The version of x86/svr4 SDB I have at the moment does (partially) 70351408Sobrien seem to believe that DWARF register number 11 is associated with 70451408Sobrien the x86 register %st(0), but that's about all. Higher DWARF 70551408Sobrien register numbers don't seem to be associated with anything in 70651408Sobrien particular, and even for DWARF regno 11, SDB only seems to under- 70751408Sobrien stand that it should say that a variable lives in %st(0) (when 70851408Sobrien asked via an `=' command) if we said it was in DWARF regno 11, 70951408Sobrien but SDB still prints garbage when asked for the value of the 71051408Sobrien variable in question (via a `/' command). 71151408Sobrien (Also note that the labels SDB prints for various FP stack regs 71251408Sobrien when doing an `x' command are all wrong.) 71351408Sobrien Note that these problems generally don't affect the native SVR4 71451408Sobrien C compiler because it doesn't allow the use of -O with -g and 71551408Sobrien because when it is *not* optimizing, it allocates a memory 71651408Sobrien location for each floating-point variable, and the memory 71751408Sobrien location is what gets described in the DWARF AT_location 71851408Sobrien attribute for the variable in question. 71951408Sobrien Regardless of the severe mental illness of the x86/svr4 SDB, we 72051408Sobrien do something sensible here and we use the following DWARF 72151408Sobrien register numbers. Note that these are all stack-top-relative 72251408Sobrien numbers. 72351408Sobrien 11 for %st(0) (gnu regno = 8) 72451408Sobrien 12 for %st(1) (gnu regno = 9) 72551408Sobrien 13 for %st(2) (gnu regno = 10) 72651408Sobrien 14 for %st(3) (gnu regno = 11) 72751408Sobrien 15 for %st(4) (gnu regno = 12) 72851408Sobrien 16 for %st(5) (gnu regno = 13) 72951408Sobrien 17 for %st(6) (gnu regno = 14) 73051408Sobrien 18 for %st(7) (gnu regno = 15) 73151408Sobrien*/ 73258478Sobrien#undef DWARF_DBX_REGISTER_NUMBER 73334229Speter#define DWARF_DBX_REGISTER_NUMBER(n) \ 73434229Speter((n) == 0 ? 0 \ 73534229Speter : (n) == 1 ? 2 \ 73634229Speter : (n) == 2 ? 1 \ 73734229Speter : (n) == 3 ? 3 \ 73834229Speter : (n) == 4 ? 6 \ 73934229Speter : (n) == 5 ? 7 \ 74034229Speter : (n) == 6 ? 5 \ 74134229Speter : (n) == 7 ? 4 \ 74234229Speter : ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n)+3 \ 74334229Speter : (-1)) 74434229Speter 74534229Speter/* Now what stabs expects in the register. */ 74658478Sobrien#undef STABS_DBX_REGISTER_NUMBER 74734229Speter#define STABS_DBX_REGISTER_NUMBER(n) \ 74834229Speter((n) == 0 ? 0 : \ 74934229Speter (n) == 1 ? 2 : \ 75034229Speter (n) == 2 ? 1 : \ 75134229Speter (n) == 3 ? 3 : \ 75234229Speter (n) == 4 ? 6 : \ 75334229Speter (n) == 5 ? 7 : \ 75434229Speter (n) == 6 ? 4 : \ 75534229Speter (n) == 7 ? 5 : \ 75634229Speter (n) + 4) 75734229Speter 75834229Speter#undef DBX_REGISTER_NUMBER 75958478Sobrien#define DBX_REGISTER_NUMBER(n) ((write_symbols == DWARF_DEBUG) \ 76058478Sobrien ? DWARF_DBX_REGISTER_NUMBER(n) \ 76134229Speter : STABS_DBX_REGISTER_NUMBER(n)) 76234229Speter 76358478Sobrien/* tag end of file in elf mode */ 76458478Sobrien#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END 76558478Sobrien#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \ 76658478Sobrien do { \ 76758478Sobrien if (TARGET_ELF) { \ 76858478Sobrien fprintf ((FILE), "\t.text\n\t.stabs \"\",%d,0,0,.Letext\n.Letext:\n", \ 76958478Sobrien N_SO); \ 77018334Speter } \ 77158478Sobrien } while (0) 77218334Speter 77358478Sobrien/* stabs-in-elf has offsets relative to function beginning */ 77458478Sobrien#undef DBX_OUTPUT_LBRAC 77558478Sobrien#define DBX_OUTPUT_LBRAC(FILE, NAME) \ 77658478Sobrien do { \ 77758478Sobrien fprintf (asmfile, "%s %d,0,0,", ASM_STABN_OP, N_LBRAC); \ 77858478Sobrien assemble_name (asmfile, buf); \ 77958478Sobrien if (TARGET_ELF) \ 78058478Sobrien { \ 78158478Sobrien fputc ('-', asmfile); \ 78258478Sobrien assemble_name (asmfile, \ 78358478Sobrien XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \ 78458478Sobrien } \ 78558478Sobrien fprintf (asmfile, "\n"); \ 78658478Sobrien } while (0) 78752112Sobrien 78858478Sobrien#undef DBX_OUTPUT_RBRAC 78958478Sobrien#define DBX_OUTPUT_RBRAC(FILE, NAME) \ 79058478Sobrien do { \ 79158478Sobrien fprintf (asmfile, "%s %d,0,0,", ASM_STABN_OP, N_RBRAC); \ 79258478Sobrien assemble_name (asmfile, buf); \ 79358478Sobrien if (TARGET_ELF) \ 79458478Sobrien { \ 79558478Sobrien fputc ('-', asmfile); \ 79658478Sobrien assemble_name (asmfile, \ 79758478Sobrien XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \ 79858478Sobrien } \ 79958478Sobrien fprintf (asmfile, "\n"); \ 80058478Sobrien } while (0) 801