| /* Assembler macros for i386. | 
 |    Copyright (C) 1991-2016 Free Software Foundation, Inc. | 
 |    This file is part of the GNU C Library. | 
 |  | 
 |    The GNU C Library is free software; you can redistribute it and/or | 
 |    modify it under the terms of the GNU Lesser General Public | 
 |    License as published by the Free Software Foundation; either | 
 |    version 2.1 of the License, or (at your option) any later version. | 
 |  | 
 |    The GNU C Library is distributed in the hope that it will be useful, | 
 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
 |    Lesser General Public License for more details. | 
 |  | 
 |    You should have received a copy of the GNU Lesser General Public | 
 |    License along with the GNU C Library; if not, see | 
 |    <http://www.gnu.org/licenses/>.  */ | 
 |  | 
 | #include <sysdeps/generic/sysdep.h> | 
 |  | 
 | #include <features.h> /* For __GNUC_PREREQ.  */ | 
 |  | 
 | /* It is desirable that the names of PIC thunks match those used by | 
 |    GCC so that multiple copies are eliminated by the linker.  Because | 
 |    GCC 4.6 and earlier use __i686 in the names, it is necessary to | 
 |    override that predefined macro.  */ | 
 | #if defined __i686 && defined __ASSEMBLER__ | 
 | #undef __i686 | 
 | #define __i686 __i686 | 
 | #endif | 
 |  | 
 | #ifdef	__ASSEMBLER__ | 
 | # define GET_PC_THUNK(reg) __x86.get_pc_thunk.reg | 
 | #else | 
 | # define GET_PC_THUNK_STR(reg) "__x86.get_pc_thunk." #reg | 
 | #endif | 
 |  | 
 | #ifdef	__ASSEMBLER__ | 
 |  | 
 | /* Syntactic details of assembler.  */ | 
 |  | 
 | /* ELF uses byte-counts for .align, most others use log2 of count of bytes.  */ | 
 | #define ALIGNARG(log2) 1<<log2 | 
 | #define ASM_SIZE_DIRECTIVE(name) .size name,.-name; | 
 |  | 
 |  | 
 | /* Define an entry point visible from C. | 
 |  | 
 |    There is currently a bug in gdb which prevents us from specifying | 
 |    incomplete stabs information.  Fake some entries here which specify | 
 |    the current source file.  */ | 
 | #define	ENTRY(name)							      \ | 
 |   .globl C_SYMBOL_NAME(name);						      \ | 
 |   .type C_SYMBOL_NAME(name),@function;					      \ | 
 |   .align ALIGNARG(4);							      \ | 
 |   C_LABEL(name)								      \ | 
 |   cfi_startproc;							      \ | 
 |   CALL_MCOUNT | 
 |  | 
 | #undef	END | 
 | #define END(name)							      \ | 
 |   cfi_endproc;								      \ | 
 |   ASM_SIZE_DIRECTIVE(name) | 
 |  | 
 | #define ENTRY_CHK(name) ENTRY (name) | 
 | #define END_CHK(name) END (name) | 
 |  | 
 | /* If compiled for profiling, call `mcount' at the start of each function.  */ | 
 | #ifdef	PROF | 
 | /* The mcount code relies on a normal frame pointer being on the stack | 
 |    to locate our caller, so push one just for its benefit.  */ | 
 | #define CALL_MCOUNT \ | 
 |   pushl %ebp; cfi_adjust_cfa_offset (4); movl %esp, %ebp; \ | 
 |   cfi_def_cfa_register (ebp); call JUMPTARGET(mcount); \ | 
 |   popl %ebp; cfi_def_cfa (esp, 4); | 
 | #else | 
 | #define CALL_MCOUNT		/* Do nothing.  */ | 
 | #endif | 
 |  | 
 | /* Since C identifiers are not normally prefixed with an underscore | 
 |    on this system, the asm identifier `syscall_error' intrudes on the | 
 |    C name space.  Make sure we use an innocuous name.  */ | 
 | #define	syscall_error	__syscall_error | 
 | #define mcount		_mcount | 
 |  | 
 | #define	PSEUDO(name, syscall_name, args)				      \ | 
 |   .globl syscall_error;							      \ | 
 | lose: SYSCALL_PIC_SETUP							      \ | 
 |   jmp JUMPTARGET(syscall_error);					      \ | 
 |   ENTRY (name)								      \ | 
 |   DO_CALL (syscall_name, args);						      \ | 
 |   jb lose | 
 |  | 
 | #undef	PSEUDO_END | 
 | #define	PSEUDO_END(name)						      \ | 
 |   END (name) | 
 |  | 
 | # define SETUP_PIC_REG(reg) \ | 
 |   .ifndef GET_PC_THUNK(reg);						      \ | 
 |   .section .gnu.linkonce.t.GET_PC_THUNK(reg),"ax",@progbits;		      \ | 
 |   .globl GET_PC_THUNK(reg);						      \ | 
 |   .hidden GET_PC_THUNK(reg);						      \ | 
 |   .p2align 4;								      \ | 
 |   .type GET_PC_THUNK(reg),@function;					      \ | 
 | GET_PC_THUNK(reg):							      \ | 
 |   movl (%esp), %e##reg;							      \ | 
 |   ret;									      \ | 
 |   .size GET_PC_THUNK(reg), . - GET_PC_THUNK(reg);			      \ | 
 |   .previous;								      \ | 
 |   .endif;								      \ | 
 |   call GET_PC_THUNK(reg) | 
 |  | 
 | # define LOAD_PIC_REG(reg) \ | 
 |   SETUP_PIC_REG(reg); addl $_GLOBAL_OFFSET_TABLE_, %e##reg | 
 |  | 
 | #undef JUMPTARGET | 
 | #ifdef PIC | 
 | #define JUMPTARGET(name)	name##@PLT | 
 | #define SYSCALL_PIC_SETUP \ | 
 |     pushl %ebx;								      \ | 
 |     cfi_adjust_cfa_offset (4);						      \ | 
 |     call 0f;								      \ | 
 | 0:  popl %ebx;								      \ | 
 |     cfi_adjust_cfa_offset (-4);						      \ | 
 |     addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx; | 
 |  | 
 | #else | 
 | #define JUMPTARGET(name)	name | 
 | #define SYSCALL_PIC_SETUP	/* Nothing.  */ | 
 | #endif | 
 |  | 
 | /* Local label name for asm code. */ | 
 | #ifndef L | 
 | #define L(name)		.L##name | 
 | #endif | 
 |  | 
 | #define atom_text_section .section ".text.atom", "ax" | 
 |  | 
 | #else /* __ASSEMBLER__ */ | 
 |  | 
 | # define SETUP_PIC_REG_STR(reg)						\ | 
 |   ".ifndef " GET_PC_THUNK_STR (reg) "\n"				\ | 
 |   ".section .gnu.linkonce.t." GET_PC_THUNK_STR (reg) ",\"ax\",@progbits\n" \ | 
 |   ".globl " GET_PC_THUNK_STR (reg) "\n"					\ | 
 |   ".hidden " GET_PC_THUNK_STR (reg) "\n"				\ | 
 |   ".p2align 4\n"							\ | 
 |   ".type " GET_PC_THUNK_STR (reg) ",@function\n"			\ | 
 | GET_PC_THUNK_STR (reg) ":"						\ | 
 |   "movl (%%esp), %%e" #reg "\n"						\ | 
 |   "ret\n"								\ | 
 |   ".size " GET_PC_THUNK_STR (reg) ", . - " GET_PC_THUNK_STR (reg) "\n"	\ | 
 |   ".previous\n"								\ | 
 |   ".endif\n"								\ | 
 |   "call " GET_PC_THUNK_STR (reg) | 
 |  | 
 | # define LOAD_PIC_REG_STR(reg) \ | 
 |   SETUP_PIC_REG_STR (reg) "\naddl $_GLOBAL_OFFSET_TABLE_, %%e" #reg | 
 |  | 
 | #endif	/* __ASSEMBLER__ */ |