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