linux.h revision 90075
150397Sobrien/* Definitions for Intel 386 running Linux-based GNU systems with ELF format.
290075Sobrien   Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002
390075Sobrien   Free Software Foundation, Inc.
418334Speter   Contributed by Eric Youngdale.
518334Speter   Modified for stabs-in-ELF by H.J. Lu.
618334Speter
718334SpeterThis file is part of GNU CC.
818334Speter
918334SpeterGNU CC is free software; you can redistribute it and/or modify
1018334Speterit under the terms of the GNU General Public License as published by
1118334Speterthe Free Software Foundation; either version 2, or (at your option)
1218334Speterany later version.
1318334Speter
1418334SpeterGNU CC is distributed in the hope that it will be useful,
1518334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of
1618334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1718334SpeterGNU General Public License for more details.
1818334Speter
1918334SpeterYou should have received a copy of the GNU General Public License
2018334Speteralong with GNU CC; see the file COPYING.  If not, write to
2118334Speterthe Free Software Foundation, 59 Temple Place - Suite 330,
2218334SpeterBoston, MA 02111-1307, USA.  */
2318334Speter
2418334Speter#define LINUX_DEFAULT_ELF
2518334Speter
2690075Sobrien/* Output at beginning of assembler file.  */
2790075Sobrien/* The .file command should always begin the output.  */
2890075Sobrien#undef ASM_FILE_START
2990075Sobrien#define ASM_FILE_START(FILE)						\
3090075Sobrien  do {									\
3190075Sobrien	output_file_directive (FILE, main_input_filename);		\
3290075Sobrien	if (ix86_asm_dialect == ASM_INTEL)				\
3390075Sobrien	  fputs ("\t.intel_syntax\n", FILE);				\
3490075Sobrien  } while (0)
3518334Speter
3618334Speter#undef TARGET_VERSION
3718334Speter#define TARGET_VERSION fprintf (stderr, " (i386 Linux/ELF)");
3818334Speter
3918334Speter/* The svr4 ABI for the i386 says that records and unions are returned
4018334Speter   in memory.  */
4118334Speter#undef DEFAULT_PCC_STRUCT_RETURN
4218334Speter#define DEFAULT_PCC_STRUCT_RETURN 1
4318334Speter
4450397Sobrien#undef ASM_COMMENT_START
4550397Sobrien#define ASM_COMMENT_START "#"
4650397Sobrien
4718334Speter#undef DBX_REGISTER_NUMBER
4818334Speter#define DBX_REGISTER_NUMBER(n) \
4990075Sobrien  (TARGET_64BIT ? dbx64_register_map[n] : svr4_dbx_register_map[n])
5018334Speter
5190075Sobrien/* Output assembler code to FILE to call the profiler.
5290075Sobrien   To the best of my knowledge, no Linux libc has required the label
5390075Sobrien   argument to mcount.  */
5418334Speter
5590075Sobrien#define NO_PROFILE_COUNTERS
5690075Sobrien
5718334Speter#undef FUNCTION_PROFILER
5818334Speter#define FUNCTION_PROFILER(FILE, LABELNO)  \
5918334Speter{									\
6018334Speter  if (flag_pic)								\
6190075Sobrien    fprintf (FILE, "\tcall\t*mcount@GOT(%%ebx)\n");			\
6218334Speter  else									\
6390075Sobrien    fprintf (FILE, "\tcall\tmcount\n");					\
6418334Speter}
6518334Speter
6690075Sobrien/* True if it is possible to profile code that does not have a frame
6790075Sobrien   pointer.
6890075Sobrien
6990075Sobrien   The GLIBC version of mcount for the x86 assumes that there is a
7090075Sobrien   frame, so we cannot allow profiling without a frame pointer.  */
7190075Sobrien
7290075Sobrien#undef TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER
7390075Sobrien#define TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER false
7490075Sobrien
7518334Speter#undef SIZE_TYPE
7618334Speter#define SIZE_TYPE "unsigned int"
7718334Speter
7818334Speter#undef PTRDIFF_TYPE
7918334Speter#define PTRDIFF_TYPE "int"
8018334Speter
8118334Speter#undef WCHAR_TYPE
8218334Speter#define WCHAR_TYPE "long int"
8318334Speter
8418334Speter#undef WCHAR_TYPE_SIZE
8518334Speter#define WCHAR_TYPE_SIZE BITS_PER_WORD
8618334Speter
8718334Speter#undef CPP_PREDEFINES
8890075Sobrien#define CPP_PREDEFINES "-D__ELF__ -Dunix -Dlinux -Asystem=posix"
8918334Speter
9018334Speter#undef CPP_SPEC
9148743Sobrien#ifdef USE_GNULIBC_1
9250397Sobrien#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}"
9318334Speter#else
9450397Sobrien#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
9518334Speter#endif
9618334Speter
9750397Sobrien#undef CC1_SPEC
9850397Sobrien#define CC1_SPEC "%(cc1_cpu) %{profile:-p}"
9948743Sobrien
10018334Speter/* Provide a LINK_SPEC appropriate for Linux.  Here we provide support
10118334Speter   for the special GCC options -static and -shared, which allow us to
10218334Speter   link things in one of these three modes by applying the appropriate
10318334Speter   combinations of options at link-time. We like to support here for
10418334Speter   as many of the other GNU linker options as possible. But I don't
10518334Speter   have the time to search for those flags. I am sure how to add
10618334Speter   support for -soname shared_object_name. H.J.
10718334Speter
10818334Speter   I took out %{v:%{!V:-V}}. It is too much :-(. They can use
10918334Speter   -Wl,-V.
11018334Speter
11118334Speter   When the -shared link option is used a final link is not being
11218334Speter   done.  */
11318334Speter
11490075Sobrien/* If ELF is the default format, we should not use /lib/elf.  */
11518334Speter
11618334Speter#undef	LINK_SPEC
11748743Sobrien#ifdef USE_GNULIBC_1
11818334Speter#ifndef LINUX_DEFAULT_ELF
11918334Speter#define LINK_SPEC "-m elf_i386 %{shared:-shared} \
12018334Speter  %{!shared: \
12118334Speter    %{!ibcs: \
12218334Speter      %{!static: \
12318334Speter	%{rdynamic:-export-dynamic} \
12418334Speter	%{!dynamic-linker:-dynamic-linker /lib/elf/ld-linux.so.1} \
12518334Speter	%{!rpath:-rpath /lib/elf/}} %{static:-static}}}"
12618334Speter#else
12718334Speter#define LINK_SPEC "-m elf_i386 %{shared:-shared} \
12818334Speter  %{!shared: \
12918334Speter    %{!ibcs: \
13018334Speter      %{!static: \
13118334Speter	%{rdynamic:-export-dynamic} \
13218334Speter	%{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \
13318334Speter	%{static:-static}}}"
13418334Speter#endif
13550397Sobrien#else
13648743Sobrien#define LINK_SPEC "-m elf_i386 %{shared:-shared} \
13748743Sobrien  %{!shared: \
13848743Sobrien    %{!ibcs: \
13948743Sobrien      %{!static: \
14048743Sobrien	%{rdynamic:-export-dynamic} \
14148743Sobrien	%{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
14248743Sobrien	%{static:-static}}}"
14350397Sobrien#endif
14418334Speter
14550397Sobrien/* A C statement (sans semicolon) to output to the stdio stream
14650397Sobrien   FILE the assembler definition of uninitialized global DECL named
14750397Sobrien   NAME whose size is SIZE bytes and alignment is ALIGN bytes.
14850397Sobrien   Try to use asm_output_aligned_bss to implement this macro.  */
14950397Sobrien
15050397Sobrien#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
15150397Sobrien  asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
15250397Sobrien
15350397Sobrien/* A C statement to output to the stdio stream FILE an assembler
15450397Sobrien   command to advance the location counter to a multiple of 1<<LOG
15550397Sobrien   bytes if it is within MAX_SKIP bytes.
15650397Sobrien
15750397Sobrien   This is used to align code labels according to Intel recommendations.  */
15850397Sobrien
15950397Sobrien#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
16052284Sobrien#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP)			\
16152284Sobrien  do {									\
16252284Sobrien    if ((LOG) != 0) {							\
16352284Sobrien      if ((MAX_SKIP) == 0) fprintf ((FILE), "\t.p2align %d\n", (LOG));	\
16452284Sobrien      else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP));	\
16552284Sobrien    }									\
16652284Sobrien  } while (0)
16750397Sobrien#endif
16890075Sobrien
16990075Sobrien#if defined(__PIC__) && defined (USE_GNULIBC_1)
17090075Sobrien/* This is a kludge. The i386 GNU/Linux dynamic linker needs ___brk_addr,
17190075Sobrien   __environ and atexit.  We have to make sure they are in the .dynsym
17290075Sobrien   section.  We do this by forcing the assembler to create undefined
17390075Sobrien   references to these symbols in the object file.  */
17490075Sobrien#undef CRT_CALL_STATIC_FUNCTION
17590075Sobrien#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC)	\
17690075Sobrien   asm (SECTION_OP "\n\t"				\
17790075Sobrien	"call " USER_LABEL_PREFIX #FUNC "\n"		\
17890075Sobrien	TEXT_SECTION_ASM_OP "\n\t"			\
17990075Sobrien	".extern ___brk_addr\n\t"			\
18090075Sobrien	".type ___brk_addr,@object\n\t"			\
18190075Sobrien	".extern __environ\n\t"				\
18290075Sobrien	".type __environ,@object\n\t"			\
18390075Sobrien	".extern atexit\n\t"				\
18490075Sobrien	".type atexit,@function");
18590075Sobrien#endif
18690075Sobrien
18790075Sobrien/* Handle special EH pointer encodings.  Absolute, pc-relative, and
18890075Sobrien   indirect are handled automatically.  */
18990075Sobrien#define ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(FILE, ENCODING, SIZE, ADDR, DONE) \
19090075Sobrien  do {									\
19190075Sobrien    if ((SIZE) == 4 && ((ENCODING) & 0x70) == DW_EH_PE_datarel)		\
19290075Sobrien      {									\
19390075Sobrien        fputs (ASM_LONG, FILE);			\
19490075Sobrien        assemble_name (FILE, XSTR (ADDR, 0));				\
19590075Sobrien	fputs (((ENCODING) & DW_EH_PE_indirect ? "@GOT" : "@GOTOFF"), FILE); \
19690075Sobrien        goto DONE;							\
19790075Sobrien      }									\
19890075Sobrien  } while (0)
19990075Sobrien
20090075Sobrien/* Used by crtstuff.c to initialize the base of data-relative relocations.
20190075Sobrien   These are GOT relative on x86, so return the pic register.  */
20290075Sobrien#ifdef __PIC__
20390075Sobrien#define CRT_GET_RFIB_DATA(BASE)			\
20490075Sobrien  {						\
20590075Sobrien    register void *ebx_ __asm__("ebx");		\
20690075Sobrien    BASE = ebx_;				\
20790075Sobrien  }
20890075Sobrien#else
20990075Sobrien#define CRT_GET_RFIB_DATA(BASE)						\
21090075Sobrien  __asm__ ("call\t.LPR%=\n"						\
21190075Sobrien	   ".LPR%=:\n\t"						\
21290075Sobrien	   "popl\t%0\n\t"						\
21390075Sobrien	   /* Due to a GAS bug, this cannot use EAX.  That encodes	\
21490075Sobrien	      smaller than the traditional EBX, which results in the	\
21590075Sobrien	      offset being off by one.  */				\
21690075Sobrien	   "addl\t$_GLOBAL_OFFSET_TABLE_+[.-.LPR%=],%0"			\
21790075Sobrien	   : "=d"(BASE))
21890075Sobrien#endif
21990075Sobrien
22090075Sobrien/* Do code reading to identify a signal frame, and set the frame
22190075Sobrien   state data appropriately.  See unwind-dw2.c for the structs.  */
22290075Sobrien
22390075Sobrien#ifdef IN_LIBGCC2
22490075Sobrien#include <signal.h>
22590075Sobrien#include <sys/ucontext.h>
22690075Sobrien#endif
22790075Sobrien
22890075Sobrien#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS)		\
22990075Sobrien  do {									\
23090075Sobrien    unsigned char *pc_ = (CONTEXT)->ra;					\
23190075Sobrien    struct sigcontext *sc_;						\
23290075Sobrien    long new_cfa_;							\
23390075Sobrien									\
23490075Sobrien    /* popl %eax ; movl $__NR_sigreturn,%eax ; int $0x80  */		\
23590075Sobrien    if (*(unsigned short *)(pc_+0) == 0xb858				\
23690075Sobrien	&& *(unsigned int *)(pc_+2) == 119				\
23790075Sobrien	&& *(unsigned short *)(pc_+6) == 0x80cd)			\
23890075Sobrien      sc_ = (CONTEXT)->cfa + 4;						\
23990075Sobrien    /* movl $__NR_rt_sigreturn,%eax ; int $0x80  */			\
24090075Sobrien    else if (*(unsigned char *)(pc_+0) == 0xb8				\
24190075Sobrien	     && *(unsigned int *)(pc_+1) == 173				\
24290075Sobrien	     && *(unsigned short *)(pc_+5) == 0x80cd)			\
24390075Sobrien      {									\
24490075Sobrien	struct rt_sigframe {						\
24590075Sobrien	  int sig;							\
24690075Sobrien	  struct siginfo *pinfo;					\
24790075Sobrien	  void *puc;							\
24890075Sobrien	  struct siginfo info;						\
24990075Sobrien	  struct ucontext uc;						\
25090075Sobrien	} *rt_ = (CONTEXT)->cfa;					\
25190075Sobrien	sc_ = (struct sigcontext *) &rt_->uc.uc_mcontext;		\
25290075Sobrien      }									\
25390075Sobrien    else								\
25490075Sobrien      break;								\
25590075Sobrien									\
25690075Sobrien    new_cfa_ = sc_->esp;						\
25790075Sobrien    (FS)->cfa_how = CFA_REG_OFFSET;					\
25890075Sobrien    (FS)->cfa_reg = 4;							\
25990075Sobrien    (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa;		\
26090075Sobrien									\
26190075Sobrien    /* The SVR4 register numbering macros aren't usable in libgcc.  */	\
26290075Sobrien    (FS)->regs.reg[0].how = REG_SAVED_OFFSET;				\
26390075Sobrien    (FS)->regs.reg[0].loc.offset = (long)&sc_->eax - new_cfa_;		\
26490075Sobrien    (FS)->regs.reg[3].how = REG_SAVED_OFFSET;				\
26590075Sobrien    (FS)->regs.reg[3].loc.offset = (long)&sc_->ebx - new_cfa_;		\
26690075Sobrien    (FS)->regs.reg[1].how = REG_SAVED_OFFSET;				\
26790075Sobrien    (FS)->regs.reg[1].loc.offset = (long)&sc_->ecx - new_cfa_;		\
26890075Sobrien    (FS)->regs.reg[2].how = REG_SAVED_OFFSET;				\
26990075Sobrien    (FS)->regs.reg[2].loc.offset = (long)&sc_->edx - new_cfa_;		\
27090075Sobrien    (FS)->regs.reg[6].how = REG_SAVED_OFFSET;				\
27190075Sobrien    (FS)->regs.reg[6].loc.offset = (long)&sc_->esi - new_cfa_;		\
27290075Sobrien    (FS)->regs.reg[7].how = REG_SAVED_OFFSET;				\
27390075Sobrien    (FS)->regs.reg[7].loc.offset = (long)&sc_->edi - new_cfa_;		\
27490075Sobrien    (FS)->regs.reg[5].how = REG_SAVED_OFFSET;				\
27590075Sobrien    (FS)->regs.reg[5].loc.offset = (long)&sc_->ebp - new_cfa_;		\
27690075Sobrien    (FS)->regs.reg[8].how = REG_SAVED_OFFSET;				\
27790075Sobrien    (FS)->regs.reg[8].loc.offset = (long)&sc_->eip - new_cfa_;		\
27890075Sobrien    (FS)->retaddr_column = 8;						\
27990075Sobrien    goto SUCCESS;							\
28090075Sobrien  } while (0)
281