diff options
Diffstat (limited to 'sysdeps/x86_64')
72 files changed, 4867 insertions, 0 deletions
diff --git a/sysdeps/x86_64/Implies b/sysdeps/x86_64/Implies new file mode 100644 index 0000000000..2b8412b0b6 --- /dev/null +++ b/sysdeps/x86_64/Implies @@ -0,0 +1,4 @@ +wordsize-64 +ieee754/ldbl-96 +ieee754/dbl-64 +ieee754/flt-32 diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile new file mode 100644 index 0000000000..4e64fb0a5e --- /dev/null +++ b/sysdeps/x86_64/Makefile @@ -0,0 +1,6 @@ +# The i387 `long double' is a distinct type we support. +long-double-fcts = yes + +ifeq ($(subdir),csu) +sysdep_routines += hp-timing +endif diff --git a/sysdeps/x86_64/Versions b/sysdeps/x86_64/Versions new file mode 100644 index 0000000000..42386f4dcc --- /dev/null +++ b/sysdeps/x86_64/Versions @@ -0,0 +1,5 @@ +ld { + GLIBC_2.2.5 { + _dl_cpuclock_offset; + } +} diff --git a/sysdeps/x86_64/__longjmp.S b/sysdeps/x86_64/__longjmp.S new file mode 100644 index 0000000000..1962b7f1aa --- /dev/null +++ b/sysdeps/x86_64/__longjmp.S @@ -0,0 +1,44 @@ +/* Copyright (C) 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#define _ASM +#define _SETJMP_H +#include <bits/setjmp.h> +#include <asm-syntax.h> + +/* Jump to the position specified by ENV, causing the + setjmp call there to return VAL, or 1 if VAL is 0. + void __longjmp (__jmp_buf env, int val). */ +ENTRY(__longjmp) + /* Restore registers. */ + movq (JB_RBX*8)(%rdi),%rbx + movq (JB_RBP*8)(%rdi),%rbp + movq (JB_R12*8)(%rdi),%r12 + movq (JB_R13*8)(%rdi),%r13 + movq (JB_R14*8)(%rdi),%r14 + movq (JB_R15*8)(%rdi),%r15 + /* Set return value for setjmp. */ + test %esi,%esi + mov $01,%eax + cmove %eax,%esi + mov %esi, %eax + movq (JB_PC*8)(%rdi),%rdx + movq (JB_RSP*8)(%rdi),%rsp + jmpq *%rdx +END (BP_SYM (__longjmp)) diff --git a/sysdeps/x86_64/abort-instr.h b/sysdeps/x86_64/abort-instr.h new file mode 100644 index 0000000000..810f10379b --- /dev/null +++ b/sysdeps/x86_64/abort-instr.h @@ -0,0 +1,2 @@ +/* An instruction which should crash any program is `hlt'. */ +#define ABORT_INSTRUCTION asm ("hlt") diff --git a/sysdeps/x86_64/atomicity.h b/sysdeps/x86_64/atomicity.h new file mode 100644 index 0000000000..925c9f9da5 --- /dev/null +++ b/sysdeps/x86_64/atomicity.h @@ -0,0 +1,57 @@ +/* Low-level functions for atomic operations. x86-64 version. + Copyright (C) 1997, 2000, 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ATOMICITY_H +#define _ATOMICITY_H 1 + +#include <inttypes.h> + + +static inline uint32_t +__attribute__ ((unused)) +exchange_and_add (volatile uint32_t *mem, uint32_t val) +{ + register uint32_t result; + __asm__ __volatile__ ("lock; xaddl %0,%1" + : "=r" (result), "=m" (*mem) : "0" (val), "1" (*mem)); + return result; +} + +static inline void +__attribute__ ((unused)) +atomic_add (volatile uint32_t *mem, int val) +{ + __asm__ __volatile__ ("lock; addl %1,%0" + : "=m" (*mem) : "er" (val), "0" (*mem)); +} + +static inline char +__attribute__ ((unused)) +compare_and_swap (volatile long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgq %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (newval), "1" (*p), "a" (oldval)); + return ret; +} + +#endif /* atomicity.h */ diff --git a/sysdeps/x86_64/bits/endian.h b/sysdeps/x86_64/bits/endian.h new file mode 100644 index 0000000000..2f59eada25 --- /dev/null +++ b/sysdeps/x86_64/bits/endian.h @@ -0,0 +1,7 @@ +/* x86_64 is little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use <bits/endian.h> directly; include <endian.h> instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/sysdeps/x86_64/bits/setjmp.h b/sysdeps/x86_64/bits/setjmp.h new file mode 100644 index 0000000000..be39482d09 --- /dev/null +++ b/sysdeps/x86_64/bits/setjmp.h @@ -0,0 +1,47 @@ +/* Copyright (C) 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. x86-64 version. */ + +#ifndef _SETJMP_H +# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead." +#endif + +/* We only need to save callee-saved registers plus stackpointer and + program counter. */ +#if defined __USE_MISC || defined _ASM +# define JB_RBX 0 +# define JB_RBP 1 +# define JB_R12 2 +# define JB_R13 3 +# define JB_R14 4 +# define JB_R15 5 +# define JB_RSP 6 +# define JB_PC 7 +# define JB_SIZE (8*8) +#endif + +#ifndef _ASM + +typedef long int __jmp_buf[8]; + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[JB_RSP]) +#endif diff --git a/sysdeps/x86_64/bits/string.h b/sysdeps/x86_64/bits/string.h new file mode 100644 index 0000000000..708ce78d61 --- /dev/null +++ b/sysdeps/x86_64/bits/string.h @@ -0,0 +1,26 @@ +/* Optimized, inlined string functions. AMD x86-64 version. + Copyright (C) 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _STRING_H +# error "Never use <bits/string.h> directly; include <string.h> instead." +#endif + +/* Currently the only purpose of this file is to tell the generic inline + macros that unaligned memory access is possible for x86-64. */ +#define _STRING_ARCH_unaligned 1 diff --git a/sysdeps/x86_64/bp-asm.h b/sysdeps/x86_64/bp-asm.h new file mode 100644 index 0000000000..ff140ce181 --- /dev/null +++ b/sysdeps/x86_64/bp-asm.h @@ -0,0 +1,141 @@ +/* Bounded-pointer definitions for x86-64 assembler. + Copyright (C) 2001 Free Software Foundation, Inc. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _bp_asm_h_ +# define _bp_asm_h_ 1 + +# if __ASSEMBLER__ + +# if __BOUNDED_POINTERS__ + +/* Bounded pointers occupy three words. */ +# define PTR_SIZE 24 +/* Bounded pointer return values are passed back through a hidden + argument that points to caller-allocate space. The hidden arg + occupies one word on the stack. */ +# define RTN_SIZE 6 +/* Although the caller pushes the hidden arg, the callee is + responsible for popping it. */ +# define RET_PTR ret $RTN_SIZE +/* Maintain frame pointer chain in leaf assembler functions for the benefit + of debugging stack traces when bounds violations occur. */ +# define ENTER pushq %rbp; movq %rsp, %rbp +# define LEAVE movq %rbp, %rsp; popq %rbp +/* Stack space overhead of procedure-call linkage: return address and + frame pointer. */ +# define LINKAGE 16 +/* Stack offset of return address after calling ENTER. */ +# define PCOFF 8 + +/* Int 5 is the "bound range" exception also raised by the "bound" + instruction. */ +# define BOUNDS_VIOLATED int $5 + +# define CHECK_BOUNDS_LOW(VAL_REG, BP_MEM) \ + cmpq 8+BP_MEM, VAL_REG; \ + jae 0f; /* continue if value >= low */ \ + BOUNDS_VIOLATED; \ + 0: + +# define CHECK_BOUNDS_HIGH(VAL_REG, BP_MEM, Jcc) \ + cmpq 16+BP_MEM, VAL_REG; \ + Jcc 0f; /* continue if value < high */ \ + BOUNDS_VIOLATED; \ + 0: + +# define CHECK_BOUNDS_BOTH(VAL_REG, BP_MEM) \ + cmpq 8+BP_MEM, VAL_REG; \ + jb 1f; /* die if value < low */ \ + cmpq 16+BP_MEM, VAL_REG; \ + jb 0f; /* continue if value < high */ \ + 1: BOUNDS_VIOLATED; \ + 0: + +# define CHECK_BOUNDS_BOTH_WIDE(VAL_REG, BP_MEM, LENGTH) \ + CHECK_BOUNDS_LOW(VAL_REG, BP_MEM); \ + addl LENGTH, VAL_REG; \ + cmpq 16+BP_MEM, VAL_REG; \ + jbe 0f; /* continue if value <= high */ \ + BOUNDS_VIOLATED; \ + 0: subq LENGTH, VAL_REG /* restore value */ + +/* Take bounds from BP_MEM and affix them to the pointer + value in %rax, stuffing all into memory at RTN(%esp). + Use %rdx as a scratch register. */ + +# define RETURN_BOUNDED_POINTER(BP_MEM) \ + movq RTN(%rsp), %rdx; \ + movq %rax, 0(%rdx); \ + movq 8+BP_MEM, %rax; \ + movq %rax, 4(%rdx); \ + movq 16+BP_MEM, %rax; \ + movq %rax, 8(%rdx) + +# define RETURN_NULL_BOUNDED_POINTER \ + movl RTN(%rsp), %rdx; \ + movl %rax, 0(%rdx); \ + movl %rax, 4(%rdx); \ + movl %rax, 8(%rdx) + +/* The caller of __errno_location is responsible for allocating space + for the three-word BP return-value and passing pushing its address + as an implicit first argument. */ +# define PUSH_ERRNO_LOCATION_RETURN \ + subl $16, %esp; \ + subl $8, %esp; \ + pushq %rsp + +/* __errno_location is responsible for popping the implicit first + argument, but we must pop the space for the BP itself. We also + dereference the return value in order to dig out the pointer value. */ +# define POP_ERRNO_LOCATION_RETURN \ + popq %rax; \ + addq $16, %rsp + +# else /* !__BOUNDED_POINTERS__ */ + +/* Unbounded pointers occupy one word. */ +# define PTR_SIZE 8 +/* Unbounded pointer return values are passed back in the register %rax. */ +# define RTN_SIZE 0 +/* Use simple return instruction for unbounded pointer values. */ +# define RET_PTR ret +/* Don't maintain frame pointer chain for leaf assembler functions. */ +# define ENTER +# define LEAVE +/* Stack space overhead of procedure-call linkage: return address only. */ +# define LINKAGE 8 +/* Stack offset of return address after calling ENTER. */ +# define PCOFF 0 + +# define CHECK_BOUNDS_LOW(VAL_REG, BP_MEM) +# define CHECK_BOUNDS_HIGH(VAL_REG, BP_MEM, Jcc) +# define CHECK_BOUNDS_BOTH(VAL_REG, BP_MEM) +# define CHECK_BOUNDS_BOTH_WIDE(VAL_REG, BP_MEM, LENGTH) +# define RETURN_BOUNDED_POINTER(BP_MEM) + +# define RETURN_NULL_BOUNDED_POINTER + +# define PUSH_ERRNO_LOCATION_RETURN +# define POP_ERRNO_LOCATION_RETURN + +# endif /* !__BOUNDED_POINTERS__ */ + +# endif /* __ASSEMBLER__ */ + +#endif /* _bp_asm_h_ */ diff --git a/sysdeps/x86_64/bsd-_setjmp.S b/sysdeps/x86_64/bsd-_setjmp.S new file mode 100644 index 0000000000..5f29adc7b8 --- /dev/null +++ b/sysdeps/x86_64/bsd-_setjmp.S @@ -0,0 +1,39 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. x86-64 version. + Copyright (C) 1994,1995,1996,1997,2000,2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 0)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +#include <sysdep.h> +#define _ASM +#define _SETJMP_H +#include <bits/setjmp.h> +#include "bp-sym.h" +#include "bp-asm.h" + +ENTRY (BP_SYM (_setjmp)) + /* Set up arguments, we only need to set the second arg. */ + xorq %rsi, %rsi +#ifdef PIC + jmp C_SYMBOL_NAME (BP_SYM (__sigsetjmp))@PLT +#else + jmp BP_SYM (__sigsetjmp) +#endif +END (BP_SYM (_setjmp)) diff --git a/sysdeps/x86_64/bsd-setjmp.S b/sysdeps/x86_64/bsd-setjmp.S new file mode 100644 index 0000000000..c168f81867 --- /dev/null +++ b/sysdeps/x86_64/bsd-setjmp.S @@ -0,0 +1,38 @@ +/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. x86-64 version. + Copyright (C) 1994,1995,1996,1997,2000,2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +#include <sysdep.h> +#define _ASM +#define _SETJMP_H +#include <bits/setjmp.h> +#include "bp-sym.h" +#include "bp-asm.h" + +ENTRY (BP_SYM (setjmp)) + /* Set up arguments, we only need to set the 2nd arg. */ + movq $1, %rsi +#ifdef PIC +#else + jmp BP_SYM (__sigsetjmp) +#endif +END (BP_SYM (setjmp)) diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h new file mode 100644 index 0000000000..268c2c31d6 --- /dev/null +++ b/sysdeps/x86_64/dl-machine.h @@ -0,0 +1,417 @@ +/* Machine-dependent ELF dynamic relocation inline functions. x86-64 version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger <aj@suse.de>. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef dl_machine_h +#define dl_machine_h + +#define ELF_MACHINE_NAME "x86_64" + +#include <sys/param.h> + +/* Return nonzero iff ELF header is compatible with the running host. */ +static inline int __attribute__ ((unused)) +elf_machine_matches_host (const Elf64_Ehdr *ehdr) +{ + return ehdr->e_machine == EM_X86_64; +} + + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static inline Elf64_Addr __attribute__ ((unused)) +elf_machine_dynamic (void) +{ + register Elf64_Addr addr; + + asm ("leaq _DYNAMIC, %0\n" : "=r" (addr)); + return addr; +} + + +/* Return the run-time load address of the shared object. */ +static inline Elf64_Addr __attribute__ ((unused)) +elf_machine_load_address (void) +{ + register Elf64_Addr addr, tmp; + + asm ("leaq _dl_start, %0\n" + "leaq _dl_start(%%rip), %1\n" + "subq %0, %1\n" + : "=r" (tmp), "=r" (addr) : : "cc"); + return addr; +} + +/* Set up the loaded object described by L so its unrelocated PLT + entries will jump to the on-demand fixup code in dl-runtime.c. */ + +static inline int __attribute__ ((unused)) +elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) +{ + Elf64_Addr *got; + extern void _dl_runtime_resolve (Elf64_Word); + extern void _dl_runtime_profile (Elf64_Word); + + if (l->l_info[DT_JMPREL] && lazy) + { + /* The GOT entries for functions in the PLT have not yet been filled + in. Their initial contents will arrange when called to push an + offset into the .rel.plt section, push _GLOBAL_OFFSET_TABLE_[1], + and then jump to _GLOBAL_OFFSET_TABLE[2]. */ + got = (Elf64_Addr *) D_PTR (l, l_info[DT_PLTGOT]); + got[1] = (Elf64_Addr) l; /* Identify this shared object. */ + + /* The got[2] entry contains the address of a function which gets + called to get the address of a so far unresolved function and + jump to it. The profiling extension of the dynamic linker allows + to intercept the calls to collect information. In this case we + don't store the address in the GOT so that all future calls also + end in this function. */ + if (__builtin_expect (profile, 0)) + { + got[2] = (Elf64_Addr) &_dl_runtime_profile; + + if (_dl_name_match_p (_dl_profile, l)) + /* This is the object we are looking for. Say that we really + want profiling and the timers are started. */ + _dl_profile_map = l; + } + else + /* This function will get called to fix up the GOT entry indicated by + the offset on the stack, and then jump to the resolved address. */ + got[2] = (Elf64_Addr) &_dl_runtime_resolve; + } + + return lazy; +} + +/* This code is used in dl-runtime.c to call the `fixup' function + and then redirect to the address it returns. */ +#ifndef PROF +# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\n\ + .text\n\ + .globl _dl_runtime_resolve\n\ + .type _dl_runtime_resolve, @function\n\ + .align 16\n\ +_dl_runtime_resolve:\n\ + pushq %rax # Preserve registers otherwise clobbered.\n\ + pushq %rcx\n\ + pushq %rdx\n\ + pushq %rsi\n\ + pushq %rdi\n\ + pushq %r8\n\ + pushq %r9\n\ + movq 64(%rsp), %rsi # Copy args pushed by PLT in register.\n\ + movq %rsi,%r11 # Multiply by 24\n\ + addq %r11,%rsi\n\ + addq %r11,%rsi\n\ + shlq $3, %rsi\n\ + movq 56(%rsp), %rdi # %rdi: link_map, %rsi: reloc_offset\n\ + call fixup # Call resolver.\n\ + movq %rax, %r11 # Save return value\n\ + popq %r9 # Get register content back.\n\ + popq %r8\n\ + popq %rdi\n\ + popq %rsi\n\ + popq %rdx\n\ + popq %rcx\n\ + popq %rax\n\ + addq $16,%rsp # Adjust stack\n\ + jmp *%r11 # Jump to function address.\n\ + .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\ +\n\ + .globl _dl_runtime_profile\n\ + .type _dl_runtime_profile, @function\n\ + .align 16\n\ +_dl_runtime_profile:\n\ + pushq %rax # Preserve registers otherwise clobbered.\n\ + pushq %rcx\n\ + pushq %rdx\n\ + pushq %rsi\n\ + pushq %rdi\n\ + pushq %r8\n\ + pushq %r9\n\ + movq 72(%rsp), %rdx # Load return address if needed\n\ + movq 64(%rsp), %rsi # Copy args pushed by PLT in register.\n\ + movq %rsi,%r11 # Multiply by 24\n\ + addq %r11,%rsi\n\ + addq %r11,%rsi\n\ + shlq $3, %rsi\n\ + movq 56(%rsp), %rdi # %rdi: link_map, %rsi: reloc_offset\n\ + call profile_fixup # Call resolver.\n\ + movq %rax, %r11 # Save return value\n\ + popq %r9 # Get register content back.\n\ + popq %r8\n\ + popq %rdi\n\ + popq %rsi\n\ + popq %rdx\n\ + popq %rcx\n\ + popq %rax\n\ + addq $16,%rsp # Adjust stack\n\ + jmp *%r11 # Jump to function address.\n\ + .size _dl_runtime_profile, .-_dl_runtime_profile\n\ + .previous\n\ +"); +#else +# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\n\ + .text\n\ + .globl _dl_runtime_resolve\n\ + .globl _dl_runtime_profile\n\ + .type _dl_runtime_resolve, @function\n\ + .type _dl_runtime_profile, @function\n\ + .align 16\n\ +_dl_runtime_resolve:\n\ +_dl_runtime_profile:\n\ + pushq %rax # Preserve registers otherwise clobbered.\n\ + pushq %rcx\n\ + pushq %rdx\n\ + pushq %rsi\n\ + pushq %rdi\n\ + pushq %r8\n\ + pushq %r9\n\ + movq 64(%rsp), %rsi # Copy args pushed by PLT in register.\n\ + movq %rsi,%r11 # Multiply by 24\n\ + addq %r11,%rsi\n\ + addq %r11,%rsi\n\ + shlq $3, %rsi\n\ + movq 56(%rsp), %rdi # %rdi: link_map, %rsi: reloc_offset\n\ + call fixup # Call resolver.\n\ + movq %rax, %r11 # Save return value\n\ + popq %r9 # Get register content back.\n\ + popq %r8\n\ + popq %rdi\n\ + popq %rsi\n\ + popq %rdx\n\ + popq %rcx\n\ + popq %rax\n\ + addq $16,%rsp # Adjust stack\n\ + jmp *%r11 # Jump to function address.\n\ + .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\ + .size _dl_runtime_profile, .-_dl_runtime_profile\n\ + .previous\n\ +"); +#endif + +/* Initial entry point code for the dynamic linker. + The C function `_dl_start' is the real entry point; + its return value is the user program's entry point. */ +#define RTLD_START asm ("\n\ +.text\n\ + .align 16\n\ +.globl _start\n\ +.globl _dl_start_user\n\ +_start:\n\ + movq %rsp, %rdi\n\ + call _dl_start\n\ +_dl_start_user:\n\ + # Save the user entry point address in %r12.\n\ + movq %rax, %r12\n\ + # Store the highest stack address\n\ + movq __libc_stack_end@GOTPCREL(%rip), %rax\n\ + movq %rsp, (%rax)\n\ + # See if we were run as a command with the executable file\n\ + # name as an extra leading argument.\n\ + movq _dl_skip_args@GOTPCREL(%rip), %rax\n\ + movl (%rax), %eax\n\ + # Pop the original argument count.\n\ + popq %rdx\n\ + # Adjust the stack pointer to skip _dl_skip_args words.\n\ + leaq (%rsp,%rax,8), %rsp\n\ + # Subtract _dl_skip_args from argc.\n\ + subl %eax, %edx\n\ + # Push argc back on the stack.\n\ + pushq %rdx\n\ + # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env)\n\ + # argc -> rsi\n\ + movq %rdx, %rsi\n\ + # _dl_loaded -> rdi\n\ + movq _dl_loaded@GOTPCREL(%rip), %rdi\n\ + movq (%rdi), %rdi\n\ + # env -> rcx\n\ + leaq 16(%rsp,%rdx,8), %rcx\n\ + # argv -> rdx\n\ + leaq 8(%rsp), %rdx\n\ + # Call the function to run the initializers.\n\ + call _dl_init@PLT\n\ + # Pass our finalizer function to the user in %rdx, as per ELF ABI.\n\ + movq _dl_fini@GOTPCREL(%rip), %rdx\n\ + # Jump to the user's entry point.\n\ + jmp *%r12\n\ +.previous\n\ +"); + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so + PLT entries should not be allowed to define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_X86_64_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_X86_64_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ +#define ELF_MACHINE_JMP_SLOT R_X86_64_JUMP_SLOT + +/* The x86-64 never uses Elf64_Rel relocations. */ +#define ELF_MACHINE_NO_REL 1 + +/* We define an initialization functions. This is called very early in + _dl_sysdep_start. */ +#define DL_PLATFORM_INIT dl_platform_init () + +extern const char *_dl_platform; + +static inline void __attribute__ ((unused)) +dl_platform_init (void) +{ + if (_dl_platform != NULL && *_dl_platform == '\0') + /* Avoid an empty string which would disturb us. */ + _dl_platform = NULL; +} + +static inline Elf64_Addr +elf_machine_fixup_plt (struct link_map *map, lookup_t t, + const Elf64_Rela *reloc, + Elf64_Addr *reloc_addr, Elf64_Addr value) +{ + return *reloc_addr = value; +} + +/* Return the final value of a plt relocation. On x86-64 the + JUMP_SLOT relocation ignores the addend. */ +static inline Elf64_Addr +elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc, + Elf64_Addr value) +{ + return value; +} + +#endif /* !dl_machine_h */ + +#ifdef RESOLVE + +/* Perform the relocation specified by RELOC and SYM (which is fully resolved). + MAP is the object containing the reloc. */ + +static inline void +elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, + const Elf64_Sym *sym, const struct r_found_version *version, + Elf64_Addr *const reloc_addr) +{ + const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info); + +#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC + if (__builtin_expect (r_type == R_X86_64_RELATIVE, 0)) + { +# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC + /* This is defined in rtld.c, but nowhere in the static libc.a; + make the reference weak so static programs can still link. + This declaration cannot be done when compiling rtld.c + (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the + common defn for _dl_rtld_map, which is incompatible with a + weak decl in the same file. */ + weak_extern (_dl_rtld_map); + if (map != &_dl_rtld_map) /* Already done in rtld itself. */ +# endif + *reloc_addr = map->l_addr + reloc->r_addend; + } + else +#endif + if (__builtin_expect (r_type == R_X86_64_NONE, 0)) + return; + else + { +#ifndef RTLD_BOOTSTRAP + const Elf64_Sym *const refsym = sym; +#endif + Elf64_Addr value = RESOLVE (&sym, version, r_type); + if (sym) + value += sym->st_value; + +#ifdef RTLD_BOOTSTRAP + assert (r_type == R_X86_64_GLOB_DAT || r_type == R_X86_64_JUMP_SLOT); + *reloc_addr = value + reloc->r_addend; +#else + switch (r_type) + { + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: + *reloc_addr = value + reloc->r_addend; + break; + case R_X86_64_64: + *reloc_addr = value + reloc->r_addend; + break; + case R_X86_64_32: + *(unsigned int *) reloc_addr = value + reloc->r_addend; + break; + case R_X86_64_PC32: + *(unsigned int *) reloc_addr = value + reloc->r_addend + - (Elf64_Addr) reloc_addr; + break; + case R_X86_64_COPY: + if (sym == NULL) + /* This can happen in trace mode if an object could not be + found. */ + break; + if (__builtin_expect (sym->st_size > refsym->st_size, 0) + || (__builtin_expect (sym->st_size < refsym->st_size, 0) + && _dl_verbose)) + { + const char *strtab; + + strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]); + _dl_error_printf ("\ +%s: Symbol `%s' has different size in shared object, consider re-linking\n", + _dl_argv[0] ?: "<program name unknown>", + strtab + refsym->st_name); + } + memcpy (reloc_addr, (void *) value, MIN (sym->st_size, + refsym->st_size)); + break; + default: + _dl_reloc_bad_type (map, r_type, 0); + break; + } +#endif + } +} + +static inline void +elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc, + Elf64_Addr *const reloc_addr) +{ + assert (ELF64_R_TYPE (reloc->r_info) == R_X86_64_RELATIVE); + *reloc_addr = l_addr + reloc->r_addend; +} + +static inline void +elf_machine_lazy_rel (struct link_map *map, + Elf64_Addr l_addr, const Elf64_Rela *reloc) +{ + Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset); + const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info); + + /* Check for unexpected PLT reloc type. */ + if (__builtin_expect (r_type == R_X86_64_JUMP_SLOT, 1)) + *reloc_addr += l_addr; + else + _dl_reloc_bad_type (map, r_type, 1); +} + +#endif /* RESOLVE */ diff --git a/sysdeps/x86_64/elf/initfini.c b/sysdeps/x86_64/elf/initfini.c new file mode 100644 index 0000000000..b0638aca2f --- /dev/null +++ b/sysdeps/x86_64/elf/initfini.c @@ -0,0 +1,100 @@ +/* Special .init and .fini section support for x86-64. + Copyright (C) 2001 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +__asm__ ("\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ + .align 4\n\ + .type call_gmon_start,@function\n\ +call_gmon_start:\n\ + subq $8, %rsp\n\ + movq __gmon_start__@GOTPCREL(%rip), %rax\n\ + testq %rax, %rax\n\ + je .L22\n\ + call *%rax\n\ +.L22:\n\ + addq $8, %rsp\n\ + ret\n\ +\n\ + .section .init\n\ + .align 4\n\ +.globl _init\n\ + .type _init,@function\n\ +_init:\n\ + subq $8, %rsp\n\ + /* call call_gmon_start */\n\ + ALIGN\n\ + END_INIT\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ + .section .init\n\ + addq $8, %rsp\n\ + ret\n\ + END_INIT\n\ +\n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ + .section .fini\n\ + .align 4\n\ +.globl _fini\n\ + .type _fini,@function\n\ +_fini:\n\ + subq $8, %rsp\n\ + ALIGN\n\ + END_FINI\n\ +\n\ +/*@_fini_PROLOG_ENDS*/\n\ + call i_am_not_a_leaf@PLT\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ + .section .fini\n\ + addq $8, %rsp\n\ + ret\n\ + END_FINI\n\ +\n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\n\ + .weak __gmon_start__\n\ +"); diff --git a/sysdeps/x86_64/elf/start.S b/sysdeps/x86_64/elf/start.S new file mode 100644 index 0000000000..600aaf2566 --- /dev/null +++ b/sysdeps/x86_64/elf/start.S @@ -0,0 +1,95 @@ +/* Startup code compliant to the ELF x86-64 ABI. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger <aj@suse.de>, 2001. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This is the canonical entry point, usually the first thing in the text + segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry + point runs, most registers' values are unspecified, except for: + + %rdx Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + %rsp The stack contains the arguments and environment: + 0(%rsp) argc + 8(%rsp) argv[0] + ... + (8*argc)(%rsp) NULL + (8*(argc+1))(%rsp) envp[0] + ... + NULL +*/ + +#include "bp-sym.h" + + .text + .globl _start + .type _start,@function +_start: + /* Clear the frame pointer. The ABI suggests this be done, to mark + the outermost frame obviously. */ + xorq %rbp, %rbp + + /* Extract the arguments as encoded on the stack and set up + the arguments for __libc_start_main (int (*main) (int, char **, char **), + int argc, char *argv, + void (*init) (void), void (*fini) (void), + void (*rtld_fini) (void), void *stack_end). + The arguments are passed via registers and on the stack: + main: %rdi + argc: %rsi + argv: %rdx + init: %rcx + fini: %r8 + rtld_fini: %r9 + stack_end: stack. */ + + movq %rdx, %r9 /* Address of the shared library termination + function. */ + popq %rsi /* Pop the argument count. */ + movq %rsp, %rdx /* argv starts just at the current stack top. */ + /* Align the stack to a 16 byte boundary to follow the ABI. */ + andq $~15, %rsp + + pushq %rax /* Push garbage because we push 8 more bytes. */ + + /* Provide the highest stack address to the user code (for stacks + which grow downwards). */ + pushq %rsp + + /* Pass address of our own entry points to .fini and .init. */ + movq $_fini, %r8 + movq $_init, %rcx + + movq $BP_SYM (main), %rdi + + /* Call the user's main function, and exit with its value. + But let the libc call main. */ + call BP_SYM (__libc_start_main) + + hlt /* Crash if somehow `exit' does return. */ + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/sysdeps/x86_64/ffs.c b/sysdeps/x86_64/ffs.c new file mode 100644 index 0000000000..791e6ead70 --- /dev/null +++ b/sysdeps/x86_64/ffs.c @@ -0,0 +1,38 @@ +/* ffs -- find first set bit in a word, counted from least significant end. + For AMD x86-64. + This file is part of the GNU C Library. + Copyright (C) 1991,92,93,94,97,98,2001 Free Software Foundation, Inc. + Contributed by Ulrich Drepper <drepper@cygnus.com>. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <string.h> + +#undef ffs + +int +__ffs (int x) +{ + int cnt; + int tmp; + + asm ("bsfl %2,%0\n" /* Count low bits in X and store in %1. */ + "cmovel %1,%0\n" /* If number was zero, use -1 as result. */ + : "=&r" (cnt), "=r" (tmp) : "rm" (x), "1" (-1)); + + return cnt + 1; +} +weak_alias (__ffs, ffs) diff --git a/sysdeps/x86_64/ffsll.c b/sysdeps/x86_64/ffsll.c new file mode 100644 index 0000000000..7213c0363b --- /dev/null +++ b/sysdeps/x86_64/ffsll.c @@ -0,0 +1,41 @@ +/* ffsll -- find first set bit in a word, counted from least significant end. + For AMD x86-64. + This file is part of the GNU C Library. + Copyright (C) 1991,92,93,94,97,98,2001 Free Software Foundation, Inc. + Contributed by Ulrich Drepper <drepper@cygnus.com>. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define ffsl __something_else +#include <string.h> + +#undef ffsll + +int +ffsll (long long int x) +{ + long long int cnt; + long long int tmp; + + asm ("bsfq %2,%0\n" /* Count low bits in X and store in %1. */ + "cmoveq %1,%0\n" /* If number was zero, use -1 as result. */ + : "=&r" (cnt), "=r" (tmp) : "rm" (x), "1" (-1)); + + return cnt + 1; +} + +#undef ffsl +weak_alias (ffsll, ffsl) diff --git a/sysdeps/x86_64/fpu/bits/fenv.h b/sysdeps/x86_64/fpu/bits/fenv.h new file mode 100644 index 0000000000..04576933f5 --- /dev/null +++ b/sysdeps/x86_64/fpu/bits/fenv.h @@ -0,0 +1,93 @@ +/* Copyright (C) 1997,1998,1999,2000,2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use <bits/fenv.h> directly; include <fenv.h> instead." +#endif + + +/* Define bits representing the exception. We use the bit positions + of the appropriate bits in the FPU control word. */ +enum + { + FE_INVALID = 0x01, +#define FE_INVALID FE_INVALID + __FE_DENORM = 0x02, + FE_DIVBYZERO = 0x04, +#define FE_DIVBYZERO FE_DIVBYZERO + FE_OVERFLOW = 0x08, +#define FE_OVERFLOW FE_OVERFLOW + FE_UNDERFLOW = 0x10, +#define FE_UNDERFLOW FE_UNDERFLOW + FE_INEXACT = 0x20 +#define FE_INEXACT FE_INEXACT + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The ix87 FPU supports all of the four defined rounding modes. We + use again the bit positions in the FPU control word as the values + for the appropriate macros. */ +enum + { + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + FE_DOWNWARD = 0x400, +#define FE_DOWNWARD FE_DOWNWARD + FE_UPWARD = 0x800, +#define FE_UPWARD FE_UPWARD + FE_TOWARDZERO = 0xc00 +#define FE_TOWARDZERO FE_TOWARDZERO + }; + + +/* Type representing exception flags. */ +typedef unsigned short int fexcept_t; + + +/* Type representing floating-point environment. This structure + corresponds to the layout of the block written by the `fstenv' + instruction and has additional fields for the contents of the MXCSR + register as written by the `stmxcsr' instruction. */ +typedef struct + { + unsigned short int __control_word; + unsigned short int __unused1; + unsigned short int __status_word; + unsigned short int __unused2; + unsigned short int __tags; + unsigned short int __unused3; + unsigned int __eip; + unsigned short int __cs_selector; + unsigned int __opcode:11; + unsigned int __unused4:5; + unsigned int __data_offset; + unsigned short int __data_selector; + unsigned short int __unused5; + unsigned int __mxcsr; + } +fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((__const fenv_t *) -1) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exception is masked. */ +# define FE_NOMASK_ENV ((__const fenv_t *) -2) +#endif diff --git a/sysdeps/x86_64/fpu/bits/mathdef.h b/sysdeps/x86_64/fpu/bits/mathdef.h new file mode 100644 index 0000000000..4131d86565 --- /dev/null +++ b/sysdeps/x86_64/fpu/bits/mathdef.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use <bits/mathdef.h> directly; include <math.h> instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* The x86-64 architecture computes values with the precission of the + used type. */ +typedef float float_t; /* `float' expressions are evaluated as `float'. */ +typedef double double_t; /* `double' expressions are evaluated + as `double'. */ + +/* Define `INFINITY' as value of type `float'. */ +# define INFINITY HUGE_VALF + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647 - 1) +# define FP_ILOGBNAN (-2147483647 - 1) + +#endif /* ISO C99 */ diff --git a/sysdeps/x86_64/fpu/e_acosl.c b/sysdeps/x86_64/fpu/e_acosl.c new file mode 100644 index 0000000000..1ef6d3c94a --- /dev/null +++ b/sysdeps/x86_64/fpu/e_acosl.c @@ -0,0 +1 @@ +#include "sysdeps/i386/fpu/e_acosl.c" diff --git a/sysdeps/x86_64/fpu/e_atan2l.c b/sysdeps/x86_64/fpu/e_atan2l.c new file mode 100644 index 0000000000..bbd549f307 --- /dev/null +++ b/sysdeps/x86_64/fpu/e_atan2l.c @@ -0,0 +1,2 @@ +#include "sysdeps/i386/fpu/e_atan2l.c" + diff --git a/sysdeps/x86_64/fpu/e_exp2l.S b/sysdeps/x86_64/fpu/e_exp2l.S new file mode 100644 index 0000000000..336b989098 --- /dev/null +++ b/sysdeps/x86_64/fpu/e_exp2l.S @@ -0,0 +1,38 @@ +/* + * Written by J.T. Conklin <jtc@netbsd.org>. + * Adapted for exp2 by Ulrich Drepper <drepper@cygnus.com>. + * Adapted for x86-64 by Andreas Jaeger <aj@suse.de>. + * Public domain. + */ + +#include <machine/asm.h> + +ENTRY(__ieee754_exp2l) + fldt 8(%rsp) +/* I added the following ugly construct because exp(+-Inf) resulted + in NaN. The ugliness results from the bright minds at Intel. + For the i686 the code can be written better. + -- drepper@cygnus.com. */ + fxam /* Is NaN or +-Inf? */ + fstsw %ax + movb $0x45, %dh + andb %ah, %dh + cmpb $0x05, %dh + je 1f /* Is +-Inf, jump. */ + fld %st + frndint /* int(x) */ + fsubr %st,%st(1) /* fract(x) */ + fxch + f2xm1 /* 2^(fract(x)) - 1 */ + fld1 + faddp /* 2^(fract(x)) */ + fscale /* e^x */ + fstp %st(1) + ret + +1: testl $0x200, %eax /* Test sign. */ + jz 2f /* If positive, jump. */ + fstp %st + fldz /* Set result to 0. */ +2: ret +END (__ieee754_exp2l) diff --git a/sysdeps/x86_64/fpu/e_expl.c b/sysdeps/x86_64/fpu/e_expl.c new file mode 100644 index 0000000000..5042e02db9 --- /dev/null +++ b/sysdeps/x86_64/fpu/e_expl.c @@ -0,0 +1 @@ +#include "sysdeps/i386/fpu/e_expl.c" diff --git a/sysdeps/x86_64/fpu/e_fmodl.S b/sysdeps/x86_64/fpu/e_fmodl.S new file mode 100644 index 0000000000..2967bf224b --- /dev/null +++ b/sysdeps/x86_64/fpu/e_fmodl.S @@ -0,0 +1,22 @@ +/* + * Written by J.T. Conklin <jtc@netbsd.org>. + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. + * Adapted for x86-64 by Andreas Jaeger <aj@suse.de>. + */ + +#include <machine/asm.h> + +RCSID("$NetBSD: $") + +ENTRY(__ieee754_fmodl) + fldt 24(%rsp) + fldt 8(%rsp) +1: fprem + fstsw %ax + and $04,%ah + jnz 1b + fstp %st(1) + ret +END (__ieee754_fmodl) diff --git a/sysdeps/x86_64/fpu/e_log10l.S b/sysdeps/x86_64/fpu/e_log10l.S new file mode 100644 index 0000000000..b4343bef45 --- /dev/null +++ b/sysdeps/x86_64/fpu/e_log10l.S @@ -0,0 +1,66 @@ +/* + * Written by J.T. Conklin <jtc@netbsd.org>. + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. + * + * Changed to use fyl2xp1 for values near 1, <drepper@cygnus.com>. + * Adapted for x86-64 by Andreas Jaeger <aj@suse.de>. + */ + +#include <machine/asm.h> + +RCSID("$NetBSD: $") + +#ifdef __ELF__ + .section .rodata +#else + .text +#endif + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(one,@object) +one: .double 1.0 + ASM_SIZE_DIRECTIVE(one) + /* It is not important that this constant is precise. It is only + a value which is known to be on the safe side for using the + fyl2xp1 instruction. */ + ASM_TYPE_DIRECTIVE(limit,@object) +limit: .double 0.29 + ASM_SIZE_DIRECTIVE(limit) + + +#ifdef PIC +#define MO(op) op##(%rip) +#else +#define MO(op) op +#endif + + .text +ENTRY(__ieee754_log10l) + fldlg2 // log10(2) + fldt 8(%rsp) // x : log10(2) + fxam + fnstsw + fld %st // x : x : log10(2) + andb $1,%ah + jnz 3f // in case x is NaN or ħInf +4: fsubl MO(one) // x-1 : x : log10(2) + fld %st // x-1 : x-1 : x : log10(2) + fabs // |x-1| : x-1 : x : log10(2) + fcompl MO(limit) // x-1 : x : log10(2) + fnstsw // x-1 : x : log10(2) + andb $0x45, %ah + jz 2f + fstp %st(1) // x-1 : log10(2) + fyl2xp1 // log10(x) + ret + +2: fstp %st(0) // x : log10(2) + fyl2x // log10(x) + ret + +3: jp 4b // in case x is ħInf + fstp %st(1) + fstp %st(1) + ret +END(__ieee754_log10l) diff --git a/sysdeps/x86_64/fpu/e_log2l.S b/sysdeps/x86_64/fpu/e_log2l.S new file mode 100644 index 0000000000..7a89b94d9f --- /dev/null +++ b/sysdeps/x86_64/fpu/e_log2l.S @@ -0,0 +1,63 @@ +/* + * Written by J.T. Conklin <jtc@netbsd.org>. + * Adapted for use as log2 by Ulrich Drepper <drepper@cygnus.com>. + * Public domain. + * + * Changed to use fyl2xp1 for values near 1, <drepper@cygnus.com>. + * Adapted for x86-64 by Andreas Jaeger <aj@suse.de>. + */ + +#include <machine/asm.h> + +#ifdef __ELF__ + .section .rodata +#else + .text +#endif + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(one,@object) +one: .double 1.0 + ASM_SIZE_DIRECTIVE(one) + /* It is not important that this constant is precise. It is only + a value which is known to be on the safe side for using the + fyl2xp1 instruction. */ + ASM_TYPE_DIRECTIVE(limit,@object) +limit: .double 0.29 + ASM_SIZE_DIRECTIVE(limit) + + +#ifdef PIC +#define MO(op) op##(%rip) +#else +#define MO(op) op +#endif + + .text +ENTRY(__ieee754_log2l) + fldl MO(one) + fldt 8(%rsp) // x : 1 + fxam + fnstsw + fld %st // x : x : 1 + andb $1,%ah + jnz 3f // in case x is NaN or ħInf +4: fsub %st(2), %st // x-1 : x : 1 + fld %st // x-1 : x-1 : x : 1 + fabs // |x-1| : x-1 : x : 1 + fcompl MO(limit) // x-1 : x : 1 + fnstsw // x-1 : x : 1 + andb $0x45, %ah + jz 2f + fstp %st(1) // x-1 : 1 + fyl2xp1 // log(x) + ret + +2: fstp %st(0) // x : 1 + fyl2x // log(x) + ret + +3: jp 4b // in case x is ħInf + fstp %st(1) + fstp %st(1) + ret +END (__ieee754_log2l) diff --git a/sysdeps/x86_64/fpu/e_logl.S b/sysdeps/x86_64/fpu/e_logl.S new file mode 100644 index 0000000000..a0bed663c8 --- /dev/null +++ b/sysdeps/x86_64/fpu/e_logl.S @@ -0,0 +1,56 @@ +/* + * Written by J.T. Conklin <jtc@netbsd.org>. + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. + * Adapted for x86-64 by Andreas Jaeger <aj@suse.de>. + */ + +#include <machine/asm.h> + +RCSID("$NetBSD: $") + + +#ifdef __ELF__ + .section .rodata +#else + .text +#endif + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(one,@object) +one: .double 1.0 + ASM_SIZE_DIRECTIVE(one) + /* It is not important that this constant is precise. It is only + a value which is known to be on the safe side for using the + fyl2xp1 instruction. */ + ASM_TYPE_DIRECTIVE(limit,@object) +limit: .double 0.29 + ASM_SIZE_DIRECTIVE(limit) + + +#ifdef PIC +#define MO(op) op##(%rip) +#else +#define MO(op) op +#endif + + .text +ENTRY(__ieee754_logl) + fldln2 // log(2) + fldt 8(%rsp) // x : log(2) + fld %st // x : x : log(2) + fsubl MO(one) // x-1 : x : log(2) + fld %st // x-1 : x-1 : x : log(2) + fabs // |x-1| : x-1 : x : log(2) + fcompl MO(limit) // x-1 : x : log(2) + fnstsw // x-1 : x : log(2) + andb $0x45, %ah + jz 2f + fstp %st(1) // x-1 : log(2) + fyl2xp1 // log(x) + ret + +2: fstp %st(0) // x : log(2) + fyl2x // log(x) + ret +END (__ieee754_logl) diff --git a/sysdeps/x86_64/fpu/e_powl.S b/sysdeps/x86_64/fpu/e_powl.S new file mode 100644 index 0000000000..8c690e16cc --- /dev/null +++ b/sysdeps/x86_64/fpu/e_powl.S @@ -0,0 +1,316 @@ +/* ix87 specific implementation of pow function. + Copyright (C) 1996, 1997, 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <machine/asm.h> + +#ifdef __ELF__ + .section .rodata +#else + .text +#endif + + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(infinity,@object) +inf_zero: +infinity: + .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f + ASM_SIZE_DIRECTIVE(infinity) + ASM_TYPE_DIRECTIVE(zero,@object) +zero: .double 0.0 + ASM_SIZE_DIRECTIVE(zero) + ASM_TYPE_DIRECTIVE(minf_mzero,@object) +minf_mzero: +minfinity: + .byte 0, 0, 0, 0, 0, 0, 0xf0, 0xff +mzero: + .byte 0, 0, 0, 0, 0, 0, 0, 0x80 + ASM_SIZE_DIRECTIVE(minf_mzero) + ASM_TYPE_DIRECTIVE(one,@object) +one: .double 1.0 + ASM_SIZE_DIRECTIVE(one) + ASM_TYPE_DIRECTIVE(limit,@object) +limit: .double 0.29 + ASM_SIZE_DIRECTIVE(limit) + +#ifdef PIC +#define MO(op) op##(%rip) +#else +#define MO(op) op +#endif + + .text +ENTRY(__ieee754_powl) + fldt 24(%rsp) // y + fxam + + + fnstsw + movb %ah, %dl + andb $0x45, %ah + cmpb $0x40, %ah // is y == 0 ? + je 11f + + cmpb $0x05, %ah // is y == ħinf ? + je 12f + + cmpb $0x01, %ah // is y == NaN ? + je 30f + + fldt 8(%rsp) // x : y + + fxam + fnstsw + movb %ah, %dh + andb $0x45, %ah + cmpb $0x40, %ah + je 20f // x is ħ0 + + cmpb $0x05, %ah + je 15f // x is ħinf + + fxch // y : x + + /* First see whether `y' is a natural number. In this case we + can use a more precise algorithm. */ + fld %st // y : y : x + fistpll -8(%rsp) // y : x + fildll -8(%rsp) // int(y) : y : x + fucomip %st(1),%st // y : x + jne 2f + + /* OK, we have an integer value for y. */ + mov -8(%rsp),%eax + mov -4(%rsp),%edx + orl $0, %edx + fstp %st(0) // x + jns 4f // y >= 0, jump + fdivrl MO(one) // 1/x (now referred to as x) + negl %eax + adcl $0, %edx + negl %edx +4: fldl MO(one) // 1 : x + fxch + +6: shrdl $1, %edx, %eax + jnc 5f + fxch + fmul %st(1) // x : ST*x + fxch +5: fmul %st(0), %st // x*x : ST*x + shrl $1, %edx + movl %eax, %ecx + orl %edx, %ecx + jnz 6b + fstp %st(0) // ST*x + ret + + /* y is ħNAN */ +30: fldt 8(%rsp) // x : y + fldl MO(one) // 1.0 : x : y + fucomip %st(1),%st // x : y + je 31f + fxch // y : x +31: fstp %st(1) + ret + + .align ALIGNARG(4) +2: /* y is a real number. */ + fxch // x : y + fldl MO(one) // 1.0 : x : y + fld %st(1) // x : 1.0 : x : y + fsub %st(1) // x-1 : 1.0 : x : y + fabs // |x-1| : 1.0 : x : y + fcompl MO(limit) // 1.0 : x : y + fnstsw + fxch // x : 1.0 : y + test $4500,%eax + jz 7f + fsub %st(1) // x-1 : 1.0 : y + fyl2xp1 // log2(x) : y + jmp 8f + +7: fyl2x // log2(x) : y +8: fmul %st(1) // y*log2(x) : y + fst %st(1) // y*log2(x) : y*log2(x) + frndint // int(y*log2(x)) : y*log2(x) + fsubr %st, %st(1) // int(y*log2(x)) : fract(y*log2(x)) + fxch // fract(y*log2(x)) : int(y*log2(x)) + f2xm1 // 2^fract(y*log2(x))-1 : int(y*log2(x)) + faddl MO(one) // 2^fract(y*log2(x)) : int(y*log2(x)) + fscale // 2^fract(y*log2(x))*2^int(y*log2(x)) : int(y*log2(x)) + fstp %st(1) // 2^fract(y*log2(x))*2^int(y*log2(x)) + ret + + + // pow(x,ħ0) = 1 + .align ALIGNARG(4) +11: fstp %st(0) // pop y + fldl MO(one) + ret + + // y == ħinf + .align ALIGNARG(4) +12: fstp %st(0) // pop y + fldt 8(%rsp) // x + fabs + fcompl MO(one) // < 1, == 1, or > 1 + fnstsw + andb $0x45, %ah + cmpb $0x45, %ah + je 13f // jump if x is NaN + + cmpb $0x40, %ah + je 14f // jump if |x| == 1 + + shlb $1, %ah + xorb %ah, %dl + andl $2, %edx +#ifdef PIC + lea inf_zero(%rip),%rcx + fldl (%rcx, %rdx, 4) +#else + fldl inf_zero(,%rdx, 4) +#endif + ret + + .align ALIGNARG(4) +14: fldl MO(one) + ret + + .align ALIGNARG(4) +13: fldt 8(%rsp) // load x == NaN + ret + + .align ALIGNARG(4) + // x is ħinf +15: fstp %st(0) // y + testb $2, %dh + jz 16f // jump if x == +inf + + // We must find out whether y is an odd integer. + fld %st // y : y + fistpll -8(%rsp) // y + fildll -8(%rsp) // int(y) : y + fucomip %st(1),%st + ffreep %st // <empty> + jne 17f + + // OK, the value is an integer, but is it odd? + mov -8(%rsp), %eax + mov -4(%rsp), %edx + andb $1, %al + jz 18f // jump if not odd + // It's an odd integer. + shrl $31, %edx +#ifdef PIC + lea minf_mzero(%rip),%rcx + fldl (%rcx, %rdx, 8) +#else + fldl minf_mzero(,%rdx, 8) +#endif + ret + + .align ALIGNARG(4) +16: fcompl MO(zero) + fnstsw + shrl $5, %eax + andl $8, %eax +#ifdef PIC + lea inf_zero(%rip),%rcx + fldl (%rcx, %rax, 1) +#else + fldl inf_zero(,%rax, 1) +#endif + ret + + .align ALIGNARG(4) +17: shll $30, %edx // sign bit for y in right position +18: shrl $31, %edx +#ifdef PIC + lea inf_zero(%rip),%rcx + fldl (%rcx, %rdx, 8) +#else + fldl inf_zero(,%rdx, 8) +#endif + ret + + .align ALIGNARG(4) + // x is ħ0 +20: fstp %st(0) // y + testb $2, %dl + jz 21f // y > 0 + + // x is ħ0 and y is < 0. We must find out whether y is an odd integer. + testb $2, %dh + jz 25f + + fld %st // y : y + fistpll -8(%rsp) // y + fildll -8(%rsp) // int(y) : y + fucomip %st(1),%st + ffreep %st // <empty> + jne 26f + + // OK, the value is an integer, but is it odd? + mov -8(%rsp),%eax + mov -4(%rsp),%edx + andb $1, %al + jz 27f // jump if not odd + // It's an odd integer. + // Raise divide-by-zero exception and get minus infinity value. + fldl MO(one) + fdivl MO(zero) + fchs + ret + +25: fstp %st(0) +26: +27: // Raise divide-by-zero exception and get infinity value. + fldl MO(one) + fdivl MO(zero) + ret + + .align ALIGNARG(4) + // x is ħ0 and y is > 0. We must find out whether y is an odd integer. +21: testb $2, %dh + jz 22f + + fld %st // y : y + fistpll -8(%rsp) // y + fildll -8(%rsp) // int(y) : y + fucomip %st(1),%st + ffreep %st // <empty> + jne 23f + + // OK, the value is an integer, but is it odd? + mov -8(%rsp),%eax + mov -4(%rsp),%edx + andb $1, %al + jz 24f // jump if not odd + // It's an odd integer. + fldl MO(mzero) + ret + +22: fstp %st(0) +23: +24: fldl MO(zero) + ret + +END(__ieee754_powl) diff --git a/sysdeps/x86_64/fpu/e_rem_pio2l.c b/sysdeps/x86_64/fpu/e_rem_pio2l.c new file mode 100644 index 0000000000..1347b0468c --- /dev/null +++ b/sysdeps/x86_64/fpu/e_rem_pio2l.c @@ -0,0 +1,3 @@ +/* Empty. This file is only meant to avoid compiling the file with the + same name in the libm-ieee754 directory. The code is not used since + there is an assembler version for all users of this file. */ diff --git a/sysdeps/x86_64/fpu/e_scalbl.S b/sysdeps/x86_64/fpu/e_scalbl.S new file mode 100644 index 0000000000..6b229705ba --- /dev/null +++ b/sysdeps/x86_64/fpu/e_scalbl.S @@ -0,0 +1,100 @@ +/* + * Written by J.T. Conklin <jtc@netbsd.org>. + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. + * Adapted for x86-64 by Andreas Jaeger <aj@suse.de> + * + * Correct handling of y==-inf <drepper@gnu> + */ + +#include <machine/asm.h> + +RCSID("$NetBSD: $") + +#ifdef __ELF__ + .section .rodata +#else + .text +#endif + + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(zero_nan,@object) +zero_nan: + .double 0.0 +nan: .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f +minus_zero: + .byte 0, 0, 0, 0, 0, 0, 0, 0x80 + .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f + ASM_SIZE_DIRECTIVE(zero_nan) + + +#ifdef PIC +#define MO(op) op##(%rip) +#else +#define MO(op) op +#endif + + .text +ENTRY(__ieee754_scalbl) + fldt 24(%rsp) + fxam + fnstsw + fldt 8(%rsp) + andl $0x4700, %eax + cmpl $0x0700, %eax + je 1f + andl $0x4500, %eax + cmpl $0x0100, %eax + je 2f + fxam + fnstsw + andl $0x4500, %eax + cmpl $0x0100, %eax + je 3f + fld %st(1) + frndint + fcomip %st(2), %st + jne 4f + fscale + fstp %st(1) + ret + + /* y is -inf */ +1: fxam + fnstsw + movl 16(%rsp), %edx + shrl $5, %eax + fstp %st + fstp %st + andl $0x8000, %edx + andl $8, %eax + jnz 4f + shrl $11, %edx + addl %edx, %eax +#ifdef PIC + lea zero_nan(%rip),%rdx + fldl (%rdx,%rax,1) +#else + fldl zero_nan(%rax, 1) +#endif + ret + + /* The result is NaN, but we must not raise an exception. + So use a variable. */ +2: fstp %st + fstp %st + fldl MO(nan) + ret + + /* The first parameter is a NaN. Return it. */ +3: fstp %st(1) + ret + + /* Return NaN and raise the invalid exception. */ +4: fstp %st + fstp %st + fldz + fdiv %st + ret +END(__ieee754_scalbl) diff --git a/sysdeps/x86_64/fpu/e_sqrtl.c b/sysdeps/x86_64/fpu/e_sqrtl.c new file mode 100644 index 0000000000..90e4e164e5 --- /dev/null +++ b/sysdeps/x86_64/fpu/e_sqrtl.c @@ -0,0 +1 @@ +#include "sysdeps/i386/fpu/e_sqrtl.c" diff --git a/sysdeps/x86_64/fpu/fclrexcpt.c b/sysdeps/x86_64/fpu/fclrexcpt.c new file mode 100644 index 0000000000..4fc3bfbdc7 --- /dev/null +++ b/sysdeps/x86_64/fpu/fclrexcpt.c @@ -0,0 +1,52 @@ +/* Clear given exceptions in current floating-point environment. + Copyright (C) 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <fenv.h> + +int +feclearexcept (int excepts) +{ + fenv_t temp; + unsigned int mxcsr; + + /* Mask out unsupported bits/exceptions. */ + excepts &= FE_ALL_EXCEPT; + + /* Bah, we have to clear selected exceptions. Since there is no + `fldsw' instruction we have to do it the hard way. */ + __asm__ ("fnstenv %0" : "=m" (*&temp)); + + /* Clear the relevant bits. */ + temp.__status_word &= excepts ^ FE_ALL_EXCEPT; + + /* Put the new data in effect. */ + __asm__ ("fldenv %0" : : "m" (*&temp)); + + /* And the same procedure for SSE. */ + __asm__ ("stmxcsr %0" : "=m" (*&mxcsr)); + + /* Clear the relevant bits. */ + mxcsr &= ~excepts; + + /* And put them into effect. */ + __asm__ ("ldmxcsr %0" : : "m" (*&mxcsr)); + + /* Success. */ + return 0; +} diff --git a/sysdeps/x86_64/fpu/fedisblxcpt.c b/sysdeps/x86_64/fpu/fedisblxcpt.c new file mode 100644 index 0000000000..e8157da126 --- /dev/null +++ b/sysdeps/x86_64/fpu/fedisblxcpt.c @@ -0,0 +1,49 @@ +/* Disable floating-point exceptions. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger <aj@suse.de>, 2001. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <fenv.h> + +int +fedisableexcept (int excepts) +{ + unsigned short int new_exc, old_exc; + unsigned int new, old; + + excepts &= FE_ALL_EXCEPT; + + /* Get the current control word of the x87 FPU. */ + __asm__ ("fstcw %0" : "=m" (*&new_exc)); + + old_exc = (~new_exc) & FE_ALL_EXCEPT; + + new_exc |= excepts; + __asm__ ("fldcw %0" : : "m" (*&new_exc)); + + /* And now the same for the SSE MXCSR register. */ + __asm__ ("stmxcsr %0" : "=m" (*&new)); + + /* The SSE exception masks are shifted by 7 bits. */ + old = (~new) & (FE_ALL_EXCEPT << 7); + + new |= excepts << 7; + __asm__ ("ldmxcsr %0" : : "m" (*&new)); + + return old_exc; +} diff --git a/sysdeps/x86_64/fpu/feenablxcpt.c b/sysdeps/x86_64/fpu/feenablxcpt.c new file mode 100644 index 0000000000..43259d0cfb --- /dev/null +++ b/sysdeps/x86_64/fpu/feenablxcpt.c @@ -0,0 +1,49 @@ +/* Enable floating-point exceptions. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger <aj@suse.de>, 2001. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <fenv.h> + +int +feenableexcept (int excepts) +{ + unsigned short int new_exc, old_exc; + unsigned int new, old; + + excepts &= FE_ALL_EXCEPT; + + /* Get the current control word of the x87 FPU. */ + __asm__ ("fstcw %0" : "=m" (*&new_exc)); + + old_exc = (~new_exc) & FE_ALL_EXCEPT; + + new_exc &= ~excepts; + __asm__ ("fldcw %0" : : "m" (*&new_exc)); + + /* And now the same for the SSE MXCSR register. */ + __asm__ ("stmxcsr %0" : "=m" (*&new)); + + /* The SSE exception masks are shifted by 7 bits. */ + old = (~new) & (FE_ALL_EXCEPT << 7); + + new &= ~(excepts << 7); + __asm__ ("ldmxcsr %0" : : "m" (*&new)); + + return old_exc; +} diff --git a/sysdeps/x86_64/fpu/fegetenv.c b/sysdeps/x86_64/fpu/fegetenv.c new file mode 100644 index 0000000000..fa5a8dadcb --- /dev/null +++ b/sysdeps/x86_64/fpu/fegetenv.c @@ -0,0 +1,30 @@ +/* Store current floating-point environment. + Copyright (C) 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <fenv.h> + +int +fegetenv (fenv_t *envp) +{ + __asm__ ("fnstenv %0\n" + "stmxcsr %1" : "=m" (*envp), "=m" (envp->__mxcsr)); + + /* Success. */ + return 0; +} diff --git a/sysdeps/x86_64/fpu/fegetexcept.c b/sysdeps/x86_64/fpu/fegetexcept.c new file mode 100644 index 0000000000..04df4b66a2 --- /dev/null +++ b/sysdeps/x86_64/fpu/fegetexcept.c @@ -0,0 +1,32 @@ +/* Get enabled floating-point exceptions. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger <aj@suse.de>, 2001. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <fenv.h> + +int +fegetexcept (void) +{ + unsigned short int exc; + + /* Get the current control word. */ + __asm__ ("fstcw %0" : "=m" (*&exc)); + + return (~exc) & FE_ALL_EXCEPT; +} diff --git a/sysdeps/x86_64/fpu/fegetround.c b/sysdeps/x86_64/fpu/fegetround.c new file mode 100644 index 0000000000..f237b18d1d --- /dev/null +++ b/sysdeps/x86_64/fpu/fegetround.c @@ -0,0 +1,33 @@ +/* Return current rounding direction. + Copyright (C) 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <fenv.h> + +int +fegetround (void) +{ + int cw; + /* We only check the x87 FPU unit. The SSE unit should be the same + - and if it's not the same there's no way to signal it. */ + + __asm__ ("fnstcw %0" : "=m" (*&cw)); + + return cw & 0xc00; +} diff --git a/sysdeps/x86_64/fpu/feholdexcpt.c b/sysdeps/x86_64/fpu/feholdexcpt.c new file mode 100644 index 0000000000..db53d0f07f --- /dev/null +++ b/sysdeps/x86_64/fpu/feholdexcpt.c @@ -0,0 +1,41 @@ +/* Store current floating-point environment and clear exceptions. + Copyright (C) 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <fenv.h> + +int +feholdexcept (fenv_t *envp) +{ + unsigned short int work; + unsigned int mxcsr; + + /* Store the environment. */ + __asm__ ("fnstenv %0\n" + "stmxcsr %1" : "=m" (*envp), "=m" (envp->__mxcsr)); + + /* Now set all exceptions to non-stop, first the x87 FPU. */ + work = envp->__control_word | 0x3f; + __asm__ ("fldcw %0" : : "m" (*&work)); + + /* Set the SSE MXCSR register. */ + mxcsr = envp->__mxcsr | 0x1f80; + __asm__ ("ldmxcsr %0" : : "m" (*&mxcsr)); + + return 0; +} diff --git a/sysdeps/x86_64/fpu/fesetenv.c b/sysdeps/x86_64/fpu/fesetenv.c new file mode 100644 index 0000000000..4527b16ed9 --- /dev/null +++ b/sysdeps/x86_64/fpu/fesetenv.c @@ -0,0 +1,89 @@ +/* Install given floating-point environment. + Copyright (C) 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <fenv.h> +#include <assert.h> + + +int +fesetenv (const fenv_t *envp) +{ + fenv_t temp; + + /* Install the environment specified by ENVP. But there are a few + values which we do not want to come from the saved environment. + Therefore, we get the current environment and replace the values + we want to use from the environment specified by the parameter. */ + __asm__ ("fnstenv %0\n" + "stmxcsr %1" : "=m" (*&temp), "=m" (*&temp.__mxcsr)); + + if (envp == FE_DFL_ENV) + { + temp.__control_word |= FE_ALL_EXCEPT; + temp.__control_word &= ~FE_TOWARDZERO; + temp.__status_word &= ~FE_ALL_EXCEPT; + temp.__eip = 0; + temp.__cs_selector = 0; + temp.__opcode = 0; + temp.__data_offset = 0; + temp.__data_selector = 0; + /* Set mask for SSE MXCSR. */ + temp.__mxcsr |= (FE_ALL_EXCEPT << 7); + /* Set rounding to FE_TOWARDZERO. */ + temp.__mxcsr &= ~(FE_TOWARDZERO << 3); + /* Disable exceptions. */ + temp.__mxcsr &= ~FE_ALL_EXCEPT; + } + else if (envp == FE_NOMASK_ENV) + { + temp.__control_word &= ~(FE_ALL_EXCEPT | FE_TOWARDZERO); + temp.__status_word &= ~FE_ALL_EXCEPT; + temp.__eip = 0; + temp.__cs_selector = 0; + temp.__opcode = 0; + temp.__data_offset = 0; + temp.__data_selector = 0; + /* Set mask for SSE MXCSR. */ + temp.__mxcsr &= ~(FE_ALL_EXCEPT << 7); + /* Set rounding to FE_TOWARDZERO. */ + temp.__mxcsr &= ~(FE_TOWARDZERO << 3); + /* Disable exceptions. */ + temp.__mxcsr &= ~FE_ALL_EXCEPT; + } + else + { + temp.__control_word &= ~(FE_ALL_EXCEPT | FE_TOWARDZERO); + temp.__control_word |= (envp->__control_word + & (FE_ALL_EXCEPT | FE_TOWARDZERO)); + temp.__status_word &= ~FE_ALL_EXCEPT; + temp.__status_word |= envp->__status_word & FE_ALL_EXCEPT; + temp.__eip = envp->__eip; + temp.__cs_selector = envp->__cs_selector; + temp.__opcode = envp->__opcode; + temp.__data_offset = envp->__data_offset; + temp.__data_selector = envp->__data_selector; + temp.__mxcsr = envp->__mxcsr; + } + + __asm__ ("fldenv %0\n" + "ldmxcsr %1" : : "m" (temp), "m" (temp.__mxcsr)); + + /* Success. */ + return 0; +} diff --git a/sysdeps/x86_64/fpu/fesetround.c b/sysdeps/x86_64/fpu/fesetround.c new file mode 100644 index 0000000000..429b7f1d0c --- /dev/null +++ b/sysdeps/x86_64/fpu/fesetround.c @@ -0,0 +1,46 @@ +/* Set current rounding direction. + Copyright (C) 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <fenv.h> + +int +fesetround (int round) +{ + unsigned short int cw; + int mxcsr; + + if ((round & ~0xc00) != 0) + /* ROUND is no valid rounding mode. */ + return 1; + + /* First set the x87 FPU. */ + asm ("fnstcw %0" : "=m" (*&cw)); + cw &= ~0xc00; + cw |= round; + asm ("fldcw %0" : : "m" (*&cw)); + + /* And now the MSCSR register for SSE, the precision is at different bit + positions in the different units, we need to shift it 3 bits. */ + asm ("stmxcsr %0" : "=m" (*&mxcsr)); + mxcsr &= ~ 0x6000; + mxcsr |= round << 3; + asm ("ldmxcsr %0" : : "m" (*&mxcsr)); + + return 0; +} diff --git a/sysdeps/x86_64/fpu/fgetexcptflg.c b/sysdeps/x86_64/fpu/fgetexcptflg.c new file mode 100644 index 0000000000..f0681dc9d4 --- /dev/null +++ b/sysdeps/x86_64/fpu/fgetexcptflg.c @@ -0,0 +1,36 @@ +/* Store current representation for exceptions. + Copyright (C) 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <fenv.h> + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ + fexcept_t temp; + unsigned int mxscr; + + /* Get the current exceptions for the x87 FPU and SSE unit. */ + __asm__ ("fnstsw %0\n" + "stmxcsr %1" : "=m" (*&temp), "=m" (*&mxscr)); + + *flagp = (temp | mxscr) & FE_ALL_EXCEPT & excepts; + + /* Success. */ + return 0; +} diff --git a/sysdeps/x86_64/fpu/fraiseexcpt.c b/sysdeps/x86_64/fpu/fraiseexcpt.c new file mode 100644 index 0000000000..96ebb6dea2 --- /dev/null +++ b/sysdeps/x86_64/fpu/fraiseexcpt.c @@ -0,0 +1,119 @@ +/* Raise given exceptions. + Copyright (C) 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <fenv.h> +#include <math.h> + +int +feraiseexcept (int excepts) +{ + /* Raise exceptions represented by EXPECTS. But we must raise only + one signal at a time. It is important that if the overflow/underflow + exception and the inexact exception are given at the same time, + the overflow/underflow exception follows the inexact exception. */ + + /* First: invalid exception. */ + if ((FE_INVALID & excepts) != 0) + { + /* One example of a invalid operation is 0.0 / 0.0. */ + float f = 0.0; + + __asm__ __volatile__ ("divss %0, %0 " : : "x" (f)); + (void) &f; + } + + /* Next: division by zero. */ + if ((FE_DIVBYZERO & excepts) != 0) + { + float f = 1.0; + float g = 0.0; + + __asm__ __volatile__ ("divss %1, %0" : : "x" (f), "x" (g)); + (void) &f; + } + + /* Next: overflow. */ + if ((FE_OVERFLOW & excepts) != 0) + { + /* XXX: Is it ok to only set the x87 FPU? */ + /* There is no way to raise only the overflow flag. Do it the + hard way. */ + fenv_t temp; + + /* Bah, we have to clear selected exceptions. Since there is no + `fldsw' instruction we have to do it the hard way. */ + __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); + + /* Set the relevant bits. */ + temp.__status_word |= FE_OVERFLOW; + + /* Put the new data in effect. */ + __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); + + /* And raise the exception. */ + __asm__ __volatile__ ("fwait"); + } + + /* Next: underflow. */ + if ((FE_UNDERFLOW & excepts) != 0) + { + /* XXX: Is it ok to only set the x87 FPU? */ + /* There is no way to raise only the underflow flag. Do it the + hard way. */ + fenv_t temp; + + /* Bah, we have to clear selected exceptions. Since there is no + `fldsw' instruction we have to do it the hard way. */ + __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); + + /* Set the relevant bits. */ + temp.__status_word |= FE_UNDERFLOW; + + /* Put the new data in effect. */ + __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); + + /* And raise the exception. */ + __asm__ __volatile__ ("fwait"); + } + + /* Last: inexact. */ + if ((FE_INEXACT & excepts) != 0) + { + /* XXX: Is it ok to only set the x87 FPU? */ + /* There is no way to raise only the inexact flag. Do it the + hard way. */ + fenv_t temp; + + /* Bah, we have to clear selected exceptions. Since there is no + `fldsw' instruction we have to do it the hard way. */ + __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); + + /* Set the relevant bits. */ + temp.__status_word |= FE_INEXACT; + + /* Put the new data in effect. */ + __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); + + /* And raise the exception. */ + __asm__ __volatile__ ("fwait"); + } + + /* Success. */ + return 0; +} diff --git a/sysdeps/x86_64/fpu/fsetexcptflg.c b/sysdeps/x86_64/fpu/fsetexcptflg.c new file mode 100644 index 0000000000..fc4a42cf31 --- /dev/null +++ b/sysdeps/x86_64/fpu/fsetexcptflg.c @@ -0,0 +1,54 @@ +/* Set floating-point environment exception handling. + Copyright (C) 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <fenv.h> +#include <math.h> + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ + fenv_t temp; + unsigned int mxcsr; + + /* XXX: Do we really need to set both the exception in both units? + Shouldn't it be enough to set only the SSE unit? */ + + /* Get the current x87 FPU environment. We have to do this since we + cannot separately set the status word. */ + __asm__ ("fnstenv %0" : "=m" (*&temp)); + + temp.__status_word &= ~(excepts & FE_ALL_EXCEPT); + temp.__status_word |= *flagp & excepts & FE_ALL_EXCEPT; + + /* Store the new status word (along with the rest of the environment. + Possibly new exceptions are set but they won't get executed unless + the next floating-point instruction. */ + __asm__ ("fldenv %0" : : "m" (*&temp)); + + /* And now the same for SSE. */ + __asm__ ("stmxcsr %0" : "=m" (*&mxcsr)); + + mxcsr &= (excepts & FE_ALL_EXCEPT); + mxcsr |= *flagp & excepts & FE_ALL_EXCEPT; + + __asm__ ("ldmxcsr %0" : : "m" (*&mxcsr)); + + /* Success. */ + return 0; +} diff --git a/sysdeps/x86_64/fpu/ftestexcept.c b/sysdeps/x86_64/fpu/ftestexcept.c new file mode 100644 index 0000000000..091c25157b --- /dev/null +++ b/sysdeps/x86_64/fpu/ftestexcept.c @@ -0,0 +1,33 @@ +/* Test exception in current environment. + Copyright (C) 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <fenv.h> + +int +fetestexcept (int excepts) +{ + int temp; + unsigned int mxscr; + + /* Get current exceptions. */ + __asm__ ("fnstsw %0\n" + "stmxcsr %1" : "=m" (*&temp), "=m" (*&mxscr)); + + return (temp | mxscr) & excepts & FE_ALL_EXCEPT; +} diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps new file mode 100644 index 0000000000..f533d69c6e --- /dev/null +++ b/sysdeps/x86_64/fpu/libm-test-ulps @@ -0,0 +1,1493 @@ +# Begin of automatic generation + +# asin +Test "asin (-0.5) == -pi/6": +ildouble: 1 +ldouble: 1 +Test "asin (-1.0) == -pi/2": +ildouble: 1 +ldouble: 1 +Test "asin (0.5) == pi/6": +ildouble: 1 +ldouble: 1 +Test "asin (0.7) == 0.77539749661075306374035335271498708": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 +Test "asin (1.0) == pi/2": +ildouble: 1 +ldouble: 1 + +# asinh +Test "asinh (0.7) == 0.652666566082355786": +ildouble: 15 +ldouble: 15 + +# atan2 +Test "atan2 (-0.7, -1.0) == -2.530866689200584621918884506789267": +float: 3 +ifloat: 3 +Test "atan2 (0.7, -1.0) == 2.530866689200584621918884506789267": +float: 3 +ifloat: 3 +Test "atan2 (1.4, -0.93) == 2.1571487668237843754887415992772736": +float: 4 +ifloat: 4 + +# atanh +Test "atanh (0.7) == 0.8673005276940531944": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 + +# cabs +Test "cabs (-0.7 + 12.4 i) == 12.419742348374220601176836866763271": +float: 1 +ifloat: 1 +Test "cabs (-0.7 - 12.4 i) == 12.419742348374220601176836866763271": +float: 1 +ifloat: 1 +Test "cabs (-12.4 + 0.7 i) == 12.419742348374220601176836866763271": +float: 1 +ifloat: 1 +Test "cabs (-12.4 - 0.7 i) == 12.419742348374220601176836866763271": +float: 1 +ifloat: 1 +Test "cabs (0.7 + 1.2 i) == 1.3892443989449804508432547041028554": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 +Test "cabs (0.7 + 12.4 i) == 12.419742348374220601176836866763271": +float: 1 +ifloat: 1 + +# cacos +Test "Real part of: cacos (0.7 + 1.2 i) == 1.1351827477151551088992008271819053 - 1.0927647857577371459105272080819308 i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "Imaginary part of: cacos (0.7 + 1.2 i) == 1.1351827477151551088992008271819053 - 1.0927647857577371459105272080819308 i": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +# cacosh +Test "Real part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i": +double: 1 +float: 7 +idouble: 1 +ifloat: 7 +ildouble: 6 +ldouble: 6 +Test "Imaginary part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i": +double: 1 +float: 3 +idouble: 1 +ifloat: 3 +ildouble: 1 +ldouble: 1 +Test "Real part of: cacosh (0.7 + 1.2 i) == 1.0927647857577371459105272080819308 + 1.1351827477151551088992008271819053 i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "Imaginary part of: cacosh (0.7 + 1.2 i) == 1.0927647857577371459105272080819308 + 1.1351827477151551088992008271819053 i": +ildouble: 1 +ldouble: 1 + +# casin +Test "Real part of: casin (0.7 + 1.2 i) == 0.4356135790797415103321208644578462 + 1.0927647857577371459105272080819308 i": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +Test "Imaginary part of: casin (0.7 + 1.2 i) == 0.4356135790797415103321208644578462 + 1.0927647857577371459105272080819308 i": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +# casinh +Test "Real part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i": +double: 5 +float: 1 +idouble: 5 +ifloat: 1 +ildouble: 5 +ldouble: 5 +Test "Imaginary part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i": +double: 3 +float: 6 +idouble: 3 +ifloat: 6 +ildouble: 5 +ldouble: 5 +Test "Real part of: casinh (0.7 + 1.2 i) == 0.97865459559367387689317593222160964 + 0.91135418953156011567903546856170941 i": +double: 1 +idouble: 1 +Test "Imaginary part of: casinh (0.7 + 1.2 i) == 0.97865459559367387689317593222160964 + 0.91135418953156011567903546856170941 i": +float: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +# catan +Test "Real part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i": +float: 3 +ifloat: 3 +Test "Imaginary part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "Real part of: catan (0.7 + 1.2 i) == 1.0785743834118921877443707996386368 + 0.57705737765343067644394541889341712 i": +float: 4 +ifloat: 4 +ildouble: 1 +ldouble: 1 +Test "Imaginary part of: catan (0.7 + 1.2 i) == 1.0785743834118921877443707996386368 + 0.57705737765343067644394541889341712 i": +double: 1 +idouble: 1 + +# catanh +Test "Real part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i": +double: 4 +idouble: 4 +ildouble: 1 +ldouble: 1 +Test "Imaginary part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i": +float: 4 +ifloat: 4 +Test "Real part of: catanh (0.7 + 1.2 i) == 0.2600749516525135959200648705635915 + 0.97024030779509898497385130162655963 i": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "Imaginary part of: catanh (0.7 + 1.2 i) == 0.2600749516525135959200648705635915 + 0.97024030779509898497385130162655963 i": +float: 6 +ifloat: 6 + +# cbrt +Test "cbrt (-0.001) == -0.1": +ildouble: 102 +ldouble: 102 +Test "cbrt (-27.0) == -3.0": +double: 1 +idouble: 1 +ildouble: 948 +ldouble: 948 +Test "cbrt (0.7) == 0.8879040017426007084": +ildouble: 345 +ldouble: 345 +Test "cbrt (0.970299) == 0.99": +double: 1 +idouble: 1 +ildouble: 142 +ldouble: 142 +Test "cbrt (8) == 2": +ildouble: 191 +ldouble: 191 + +# ccos +Test "Imaginary part of: ccos (-2 - 3 i) == -4.1896256909688072301 - 9.1092278937553365979 i": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "Real part of: ccos (0.7 + 1.2 i) == 1.3848657645312111080 - 0.97242170335830028619 i": +double: 1 +idouble: 1 +Test "Imaginary part of: ccos (0.7 + 1.2 i) == 1.3848657645312111080 - 0.97242170335830028619 i": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 + +# ccosh +Test "Real part of: ccosh (-2 - 3 i) == -3.7245455049153225654 + 0.5118225699873846088 i": +float: 1 +ifloat: 1 +Test "Imaginary part of: ccosh (-2 - 3 i) == -3.7245455049153225654 + 0.5118225699873846088 i": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "Real part of: ccosh (0.7 + 1.2 i) == 0.4548202223691477654 + 0.7070296600921537682 i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "Imaginary part of: ccosh (0.7 + 1.2 i) == 0.4548202223691477654 + 0.7070296600921537682 i": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 + +# cexp +Test "Real part of: cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i": +ildouble: 1 +ldouble: 1 +Test "Imaginary part of: cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "Real part of: cexp (0.7 + 1.2 i) == 0.72969890915032360123451688642930727 + 1.8768962328348102821139467908203072 i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 +Test "Imaginary part of: cexp (0.7 + 1.2 i) == 0.72969890915032360123451688642930727 + 1.8768962328348102821139467908203072 i": +float: 1 +ifloat: 1 + +# clog +Test "Imaginary part of: clog (-2 - 3 i) == 1.2824746787307683680267437207826593 - 2.1587989303424641704769327722648368 i": +float: 3 +ifloat: 3 + +# clog10 +Test "Imaginary part of: clog10 (-0 + inf i) == inf + pi/2*log10(e) i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "Imaginary part of: clog10 (-0 - inf i) == inf - pi/2*log10(e) i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "Imaginary part of: clog10 (-2 - 3 i) == 0.5569716761534183846 - 0.9375544629863747085 i": +double: 1 +float: 5 +idouble: 1 +ifloat: 5 +ildouble: 1 +ldouble: 1 +Test "Imaginary part of: clog10 (-3 + inf i) == inf + pi/2*log10(e) i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "Imaginary part of: clog10 (-3 - inf i) == inf - pi/2*log10(e) i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "Imaginary part of: clog10 (-inf + 0 i) == inf + pi*log10(e) i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "Imaginary part of: clog10 (-inf + 1 i) == inf + pi*log10(e) i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "Imaginary part of: clog10 (-inf + inf i) == inf + 3/4 pi*log10(e) i": +double: 1 +idouble: 1 +Test "Imaginary part of: clog10 (-inf - 0 i) == inf - pi*log10(e) i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "Imaginary part of: clog10 (-inf - 1 i) == inf - pi*log10(e) i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "Imaginary part of: clog10 (0 + inf i) == inf + pi/2*log10(e) i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "Imaginary part of: clog10 (0 - inf i) == inf - pi/2*log10(e) i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "Real part of: clog10 (0.7 + 1.2 i) == 0.1427786545038868803 + 0.4528483579352493248 i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "Imaginary part of: clog10 (0.7 + 1.2 i) == 0.1427786545038868803 + 0.4528483579352493248 i": +double: 1 +idouble: 1 +ildouble: 3 +ldouble: 3 +Test "Imaginary part of: clog10 (3 + inf i) == inf + pi/2*log10(e) i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "Imaginary part of: clog10 (3 - inf i) == inf - pi/2*log10(e) i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "Imaginary part of: clog10 (inf + inf i) == inf + pi/4*log10(e) i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "Imaginary part of: clog10 (inf - inf i) == inf - pi/4*log10(e) i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 + +# cos +Test "cos (0.7) == 0.76484218728448842625585999019186495": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "cos (M_PI_6l * 2.0) == 0.5": +double: 1 +float: 0.5 +idouble: 1 +ifloat: 0.5 +Test "cos (M_PI_6l * 4.0) == -0.5": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 0.5 +ldouble: 0.5 +Test "cos (pi/2) == 0": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 0.25 +ldouble: 0.25 + +# cosh +Test "cosh (0.7) == 1.255169005630943018": +ildouble: 2 +ldouble: 2 + +# cpow +Test "Real part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i": +double: 1 +float: 4 +idouble: 1 +ifloat: 4 +Test "Imaginary part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i": +float: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 +Test "Imaginary part of: cpow (e + 0 i, 0 + 2 * M_PIl i) == 1.0 + 0.0 i": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 1 +ldouble: 1 +Test "Real part of: cpow (2 + 0 i, 10 + 0 i) == 1024.0 + 0.0 i": +ildouble: 1 +ldouble: 1 + +# csin +Test "Imaginary part of: csin (0.7 + 1.2 i) == 1.1664563419657581376 + 1.1544997246948547371 i": +float: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +# csinh +Test "Imaginary part of: csinh (-2 - 3 i) == 3.5905645899857799520 - 0.5309210862485198052 i": +double: 1 +idouble: 1 +ildouble: 2 +ldouble: 2 +Test "Real part of: csinh (0.7 + 1.2 i) == 0.27487868678117583582 + 1.1698665727426565139 i": +float: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 +Test "Imaginary part of: csinh (0.7 + 1.2 i) == 0.27487868678117583582 + 1.1698665727426565139 i": +float: 1 +ifloat: 1 + +# csqrt +Test "Real part of: csqrt (-2 + 3 i) == 0.89597747612983812471573375529004348 + 1.6741492280355400404480393008490519 i": +float: 1 +ifloat: 1 +Test "Real part of: csqrt (-2 - 3 i) == 0.89597747612983812471573375529004348 - 1.6741492280355400404480393008490519 i": +float: 1 +ifloat: 1 +Test "Real part of: csqrt (0.7 + 1.2 i) == 1.022067610030026450706487883081139 + 0.58704531296356521154977678719838035 i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "Imaginary part of: csqrt (0.7 + 1.2 i) == 1.022067610030026450706487883081139 + 0.58704531296356521154977678719838035 i": +float: 1 +ifloat: 1 + +# ctan +Test "Real part of: ctan (-2 - 3 i) == 0.0037640256415042482 - 1.0032386273536098014 i": +double: 1 +idouble: 1 +ildouble: 439 +ldouble: 439 +Test "Imaginary part of: ctan (-2 - 3 i) == 0.0037640256415042482 - 1.0032386273536098014 i": +ildouble: 2 +ldouble: 2 +Test "Real part of: ctan (0.7 + 1.2 i) == 0.1720734197630349001 + 0.9544807059989405538 i": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "Imaginary part of: ctan (0.7 + 1.2 i) == 0.1720734197630349001 + 0.9544807059989405538 i": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +# ctanh +Test "Real part of: ctanh (-2 - 3 i) == -0.9653858790221331242 + 0.0098843750383224937 i": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 5 +ldouble: 5 +Test "Imaginary part of: ctanh (-2 - 3 i) == -0.9653858790221331242 + 0.0098843750383224937 i": +ildouble: 25 +ldouble: 25 +Test "Imaginary part of: ctanh (0 + pi/4 i) == 0.0 + 1.0 i": +float: 1 +ifloat: 1 +Test "Real part of: ctanh (0.7 + 1.2 i) == 1.3472197399061191630 + 0.4778641038326365540 i": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "Imaginary part of: ctanh (0.7 + 1.2 i) == 1.3472197399061191630 + 0.4778641038326365540 i": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +# erfc +Test "erfc (0.7) == 0.32219880616258152702": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 +Test "erfc (1.2) == 0.089686021770364619762": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 3 +ldouble: 3 +Test "erfc (2.0) == 0.0046777349810472658379": +double: 1 +idouble: 1 +Test "erfc (4.1) == 0.67000276540848983727e-8": +double: 24 +float: 12 +idouble: 24 +ifloat: 12 +ildouble: 12 +ldouble: 12 +Test "erfc (9) == 0.41370317465138102381e-36": +ildouble: 36 +ldouble: 36 + +# exp10 +Test "exp10 (-1) == 0.1": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 2 +ldouble: 2 +Test "exp10 (0.7) == 5.0118723362727228500155418688494574": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "exp10 (3) == 1000": +double: 6 +float: 2 +idouble: 6 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +# expm1 +Test "expm1 (0.7) == 1.0137527074704765216": +ildouble: 1 +ldouble: 1 +Test "expm1 (1) == M_El - 1.0": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 + +# fmod +Test "fmod (-6.5, -2.3) == -1.9": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "fmod (-6.5, 2.3) == -1.9": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "fmod (6.5, -2.3) == 1.9": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "fmod (6.5, 2.3) == 1.9": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +# gamma +Test "gamma (-0.5) == log(2*sqrt(pi))": +ildouble: 1 +ldouble: 1 + +# hypot +Test "hypot (-0.7, -12.4) == 12.419742348374220601176836866763271": +float: 1 +ifloat: 1 +Test "hypot (-0.7, 12.4) == 12.419742348374220601176836866763271": +float: 1 +ifloat: 1 +Test "hypot (-12.4, -0.7) == 12.419742348374220601176836866763271": +float: 1 +ifloat: 1 +Test "hypot (-12.4, 0.7) == 12.419742348374220601176836866763271": +float: 1 +ifloat: 1 +Test "hypot (0.7, -12.4) == 12.419742348374220601176836866763271": +float: 1 +ifloat: 1 +Test "hypot (0.7, 1.2) == 1.3892443989449804508432547041028554": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 +Test "hypot (0.7, 12.4) == 12.419742348374220601176836866763271": +float: 1 +ifloat: 1 +Test "hypot (12.4, -0.7) == 12.419742348374220601176836866763271": +float: 1 +ifloat: 1 +Test "hypot (12.4, 0.7) == 12.419742348374220601176836866763271": +float: 1 +ifloat: 1 + +# j0 +Test "j0 (10.0) == -0.24593576445134833520": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +Test "j0 (2.0) == 0.22389077914123566805": +float: 2 +ifloat: 2 +Test "j0 (8.0) == 0.17165080713755390609": +float: 1 +ifloat: 1 + +# j1 +Test "j1 (10.0) == 0.043472746168861436670": +float: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 +Test "j1 (2.0) == 0.57672480775687338720": +double: 1 +idouble: 1 +Test "j1 (8.0) == 0.23463634685391462438": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 + +# jn +Test "jn (0, 10.0) == -0.24593576445134833520": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +Test "jn (0, 2.0) == 0.22389077914123566805": +float: 2 +ifloat: 2 +Test "jn (0, 8.0) == 0.17165080713755390609": +float: 1 +ifloat: 1 +Test "jn (1, 10.0) == 0.043472746168861436670": +float: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 +Test "jn (1, 2.0) == 0.57672480775687338720": +double: 1 +idouble: 1 +Test "jn (1, 8.0) == 0.23463634685391462438": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 +Test "jn (10, -1.0) == 0.26306151236874532070e-9": +ildouble: 1 +ldouble: 1 +Test "jn (10, 0.1) == 0.26905328954342155795e-19": +double: 6 +float: 4 +idouble: 6 +ifloat: 4 +ildouble: 1 +ldouble: 1 +Test "jn (10, 0.7) == 0.75175911502153953928e-11": +double: 3 +float: 1 +idouble: 3 +ifloat: 1 +ildouble: 2 +ldouble: 2 +Test "jn (10, 1.0) == 0.26306151236874532070e-9": +ildouble: 1 +ldouble: 1 +Test "jn (10, 10.0) == 0.20748610663335885770": +double: 4 +float: 3 +idouble: 4 +ifloat: 3 +ildouble: 2 +ldouble: 2 +Test "jn (10, 2.0) == 0.25153862827167367096e-6": +float: 4 +ifloat: 4 +ildouble: 1 +ldouble: 1 +Test "jn (3, -1.0) == -0.019563353982668405919": +ildouble: 1 +ldouble: 1 +Test "jn (3, 0.1) == 0.000020820315754756261429": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 +Test "jn (3, 0.7) == 0.0069296548267508408077": +float: 1 +ifloat: 1 +Test "jn (3, 1.0) == 0.019563353982668405919": +ildouble: 1 +ldouble: 1 +Test "jn (3, 10.0) == 0.058379379305186812343": +double: 3 +float: 1 +idouble: 3 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "jn (3, 2.0) == 0.12894324947440205110": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 + +# lgamma +Test "lgamma (-0.5) == log(2*sqrt(pi))": +ildouble: 1 +ldouble: 1 +Test "lgamma (0.7) == 0.26086724653166651439": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "lgamma (1.2) == -0.853740900033158497197e-1": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 1 +ldouble: 1 + +# log +Test "log (0.7) == -0.35667494393873237891263871124118447": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +# log10 +Test "log10 (0.7) == -0.15490195998574316929": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "log10 (e) == log10(e)": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +# log1p +Test "log1p (-0.3) == -0.35667494393873237891263871124118447": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +# log2 +Test "log2 (0.7) == -0.51457317282975824043": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 + +# sin +Test "sin (0.7) == 0.64421768723769105367261435139872014": +ildouble: 1 +ldouble: 1 + +# sincos +Test "sincos (0.7, &sin_res, &cos_res) puts 0.64421768723769105367261435139872014 in sin_res": +ildouble: 1 +ldouble: 1 +Test "sincos (0.7, &sin_res, &cos_res) puts 0.76484218728448842625585999019186495 in cos_res": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.5 in cos_res": +double: 1 +float: 0.5 +idouble: 1 +ifloat: 0.5 +Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in sin_res": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "sincos (pi/2, &sin_res, &cos_res) puts 0 in cos_res": +double: 0.2758 +float: 0.3667 +idouble: 0.2758 +ifloat: 0.3667 +ildouble: 0.25 +ldouble: 0.25 +Test "sincos (pi/6, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in cos_res": +float: 1 +ifloat: 1 + +# sinh +Test "sinh (0.7) == 0.75858370183953350346": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +# tan +Test "tan (0.7) == 0.84228838046307944812813500221293775": +ildouble: 1 +ldouble: 1 +Test "tan (pi/4) == 1": +double: 0.5 +idouble: 0.5 + +# tanh +Test "tanh (0.7) == 0.60436777711716349631": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Test "tanh (-0.7) == -0.60436777711716349631": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +# tgamma +Test "tgamma (-0.5) == -2 sqrt (pi)": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 +Test "tgamma (0.5) == sqrt (pi)": +float: 1 +ifloat: 1 +Test "tgamma (0.7) == 1.29805533264755778568": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "tgamma (4) == 6": +ildouble: 2 +ldouble: 2 + +# y0 +Test "y0 (0.7) == -0.19066492933739506743": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 2 +ldouble: 2 +Test "y0 (1.0) == 0.088256964215676957983": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +Test "y0 (1.5) == 0.38244892379775884396": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +Test "y0 (10.0) == 0.055671167283599391424": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "y0 (8.0) == 0.22352148938756622053": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +# y1 +Test "y1 (0.1) == -6.4589510947020269877": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 +Test "y1 (0.7) == -1.1032498719076333697": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "y1 (1.5) == -0.41230862697391129595": +float: 1 +ifloat: 1 +Test "y1 (10.0) == 0.24901542420695388392": +double: 3 +float: 1 +idouble: 3 +ifloat: 1 +Test "y1 (2.0) == -0.10703243154093754689": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "y1 (8.0) == -0.15806046173124749426": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +# yn +Test "yn (0, 0.7) == -0.19066492933739506743": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 2 +ldouble: 2 +Test "yn (0, 1.0) == 0.088256964215676957983": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +Test "yn (0, 1.5) == 0.38244892379775884396": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +Test "yn (0, 10.0) == 0.055671167283599391424": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "yn (0, 8.0) == 0.22352148938756622053": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "yn (1, 0.1) == -6.4589510947020269877": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 +Test "yn (1, 0.7) == -1.1032498719076333697": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "yn (1, 1.5) == -0.41230862697391129595": +float: 1 +ifloat: 1 +Test "yn (1, 10.0) == 0.24901542420695388392": +double: 3 +float: 1 +idouble: 3 +ifloat: 1 +Test "yn (1, 2.0) == -0.10703243154093754689": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 +Test "yn (1, 8.0) == -0.15806046173124749426": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 +Test "yn (10, 0.1) == -0.11831335132045197885e19": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 +Test "yn (10, 0.7) == -0.42447194260703866924e10": +double: 3 +idouble: 3 +ildouble: 7 +ldouble: 7 +Test "yn (10, 1.0) == -0.12161801427868918929e9": +double: 1 +idouble: 1 +Test "yn (10, 10.0) == -0.35981415218340272205": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "yn (10, 2.0) == -129184.54220803928264": +double: 2 +idouble: 2 +ildouble: 1 +ldouble: 1 +Test "yn (3, 0.1) == -5099.3323786129048894": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 +Test "yn (3, 0.7) == -15.819479052819633505": +double: 3 +float: 1 +idouble: 3 +ifloat: 1 +ildouble: 2 +ldouble: 2 +Test "yn (3, 10.0) == -0.25136265718383732978": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +Test "yn (3, 2.0) == -1.1277837768404277861": +double: 1 +idouble: 1 + +# Maximal error of functions: +Function: "asin": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 + +Function: "asinh": +ildouble: 15 +ldouble: 15 + +Function: "atan2": +float: 4 +ifloat: 4 + +Function: "atanh": +double: 1 +idouble: 1 +ildouble: 1 +ldouble: 1 + +Function: "cabs": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Real part of "cacos": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Imaginary part of "cacos": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Real part of "cacosh": +double: 1 +float: 7 +idouble: 1 +ifloat: 7 +ildouble: 6 +ldouble: 6 + +Function: Imaginary part of "cacosh": +double: 1 +float: 3 +idouble: 1 +ifloat: 3 +ildouble: 1 +ldouble: 1 + +Function: Real part of "casin": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 + +Function: Imaginary part of "casin": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Real part of "casinh": +double: 5 +float: 1 +idouble: 5 +ifloat: 1 +ildouble: 5 +ldouble: 5 + +Function: Imaginary part of "casinh": +double: 3 +float: 6 +idouble: 3 +ifloat: 6 +ildouble: 5 +ldouble: 5 + +Function: Real part of "catan": +float: 4 +ifloat: 4 +ildouble: 1 +ldouble: 1 + +Function: Imaginary part of "catan": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 + +Function: Real part of "catanh": +double: 4 +float: 1 +idouble: 4 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Imaginary part of "catanh": +float: 6 +ifloat: 6 + +Function: "cbrt": +double: 1 +idouble: 1 +ildouble: 948 +ldouble: 948 + +Function: Real part of "ccos": +double: 1 +idouble: 1 + +Function: Imaginary part of "ccos": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Real part of "ccosh": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Imaginary part of "ccosh": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Real part of "cexp": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "cexp": +float: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Imaginary part of "clog": +float: 3 +ifloat: 3 + +Function: Real part of "clog10": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Imaginary part of "clog10": +double: 1 +float: 5 +idouble: 1 +ifloat: 5 +ildouble: 3 +ldouble: 3 + +Function: "cos": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 0.5 +ldouble: 0.5 + +Function: "cosh": +ildouble: 2 +ldouble: 2 + +Function: Real part of "cpow": +double: 1 +float: 4 +idouble: 1 +ifloat: 4 +ildouble: 1 +ldouble: 1 + +Function: Imaginary part of "cpow": +double: 1.1031 +float: 2 +idouble: 1.1031 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "csin": +float: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: Real part of "csinh": +float: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "csinh": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: Real part of "csqrt": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 + +Function: Imaginary part of "csqrt": +float: 1 +ifloat: 1 + +Function: Real part of "ctan": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 439 +ldouble: 439 + +Function: Imaginary part of "ctan": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: Real part of "ctanh": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 5 +ldouble: 5 + +Function: Imaginary part of "ctanh": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 25 +ldouble: 25 + +Function: "erfc": +double: 24 +float: 12 +idouble: 24 +ifloat: 12 +ildouble: 36 +ldouble: 36 + +Function: "exp10": +double: 6 +float: 2 +idouble: 6 +ifloat: 2 +ildouble: 3 +ldouble: 3 + +Function: "expm1": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "fmod": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "gamma": +ildouble: 1 +ldouble: 1 + +Function: "hypot": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "j0": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 + +Function: "j1": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "jn": +double: 6 +float: 4 +idouble: 6 +ifloat: 4 +ildouble: 2 +ldouble: 2 + +Function: "lgamma": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 1 +ldouble: 1 + +Function: "log": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "log10": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "log1p": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "log2": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 + +Function: "sin": +ildouble: 1 +ldouble: 1 + +Function: "sincos": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "sinh": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "tan": +double: 0.5 +idouble: 0.5 +ildouble: 1 +ldouble: 1 + +Function: "tanh": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "tgamma": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "y0": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: "y1": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: "yn": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 7 +ldouble: 7 + +# end of automatic generation diff --git a/sysdeps/x86_64/fpu/math_ldbl.h b/sysdeps/x86_64/fpu/math_ldbl.h new file mode 100644 index 0000000000..b9ff8dadaf --- /dev/null +++ b/sysdeps/x86_64/fpu/math_ldbl.h @@ -0,0 +1,79 @@ +#ifndef _MATH_PRIVATE_H_ +#error "Never use <math_ldbl.h> directly; include <math_private.h> instead." +#endif + +/* A union which permits us to convert between a long double and + three 32 bit ints. */ + +typedef union +{ + long double value; + struct + { + u_int32_t lsw; + u_int32_t msw; + int sign_exponent:16; + unsigned int empty1:16; + unsigned int empty0:32; + } parts; +} ieee_long_double_shape_type; + +/* Get three 32 bit ints from a double. */ + +#define GET_LDOUBLE_WORDS(exp,ix0,ix1,d) \ +do { \ + ieee_long_double_shape_type ew_u; \ + ew_u.value = (d); \ + (exp) = ew_u.parts.sign_exponent; \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ +} while (0) + +/* Set a double from two 32 bit ints. */ + +#define SET_LDOUBLE_WORDS(d,exp,ix0,ix1) \ +do { \ + ieee_long_double_shape_type iw_u; \ + iw_u.parts.sign_exponent = (exp); \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ +} while (0) + +/* Get the more significant 32 bits of a long double mantissa. */ + +#define GET_LDOUBLE_MSW(v,d) \ +do { \ + ieee_long_double_shape_type sh_u; \ + sh_u.value = (d); \ + (v) = sh_u.parts.msw; \ +} while (0) + +/* Set the more significant 32 bits of a long double mantissa from an int. */ + +#define SET_LDOUBLE_MSW(d,v) \ +do { \ + ieee_long_double_shape_type sh_u; \ + sh_u.value = (d); \ + sh_u.parts.msw = (v); \ + (d) = sh_u.value; \ +} while (0) + +/* Get int from the exponent of a long double. */ + +#define GET_LDOUBLE_EXP(exp,d) \ +do { \ + ieee_long_double_shape_type ge_u; \ + ge_u.value = (d); \ + (exp) = ge_u.parts.sign_exponent; \ +} while (0) + +/* Set exponent of a long double from an int. */ + +#define SET_LDOUBLE_EXP(d,exp) \ +do { \ + ieee_long_double_shape_type se_u; \ + se_u.value = (d); \ + se_u.parts.sign_exponent = (exp); \ + (d) = se_u.value; \ +} while (0) diff --git a/sysdeps/x86_64/fpu/printf_fphex.c b/sysdeps/x86_64/fpu/printf_fphex.c new file mode 100644 index 0000000000..d6ca102a88 --- /dev/null +++ b/sysdeps/x86_64/fpu/printf_fphex.c @@ -0,0 +1,92 @@ +/* Print floating point number in hexadecimal notation according to ISO C99. + Copyright (C) 1997, 1998, 1999, 2000, 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef LONG_DOUBLE_DENORM_BIAS +# define LONG_DOUBLE_DENORM_BIAS (IEEE854_LONG_DOUBLE_BIAS - 1) +#endif + +#define PRINT_FPHEX_LONG_DOUBLE \ +do { \ + /* The "strange" 80 bit format on ix86 and m68k has an explicit \ + leading digit in the 64 bit mantissa. */ \ + unsigned long long int num; \ + \ + \ + num = (((unsigned long long int) fpnum.ldbl.ieee.mantissa0) << 32 \ + | fpnum.ldbl.ieee.mantissa1); \ + \ + zero_mantissa = num == 0; \ + \ + if (sizeof (unsigned long int) > 6) \ + { \ + numstr = _itoa_word (num, numbuf + sizeof numbuf, 16, \ + info->spec == 'A'); \ + wnumstr = _itowa_word (num, \ + wnumbuf + sizeof (wnumbuf) / sizeof (wchar_t),\ + 16, info->spec == 'A'); \ + } \ + else \ + { \ + numstr = _itoa (num, numbuf + sizeof numbuf, 16, info->spec == 'A');\ + wnumstr = _itowa (num, \ + wnumbuf + sizeof (wnumbuf) / sizeof (wchar_t), \ + 16, info->spec == 'A'); \ + } \ + \ + /* Fill with zeroes. */ \ + while (numstr > numbuf + (sizeof numbuf - 64 / 4)) \ + { \ + *--numstr = '0'; \ + *--wnumstr = L'0'; \ + } \ + \ + /* We use a full nibble for the leading digit. */ \ + leading = *numstr++; \ + \ + /* We have 3 bits from the mantissa in the leading nibble. \ + Therefore we are here using `IEEE854_LONG_DOUBLE_BIAS + 3'. */ \ + exponent = fpnum.ldbl.ieee.exponent; \ + \ + if (exponent == 0) \ + { \ + if (zero_mantissa) \ + expnegative = 0; \ + else \ + { \ + /* This is a denormalized number. */ \ + expnegative = 1; \ + /* This is a hook for the m68k long double format, where the \ + exponent bias is the same for normalized and denormalized \ + numbers. */ \ + exponent = LONG_DOUBLE_DENORM_BIAS + 3; \ + } \ + } \ + else if (exponent >= IEEE854_LONG_DOUBLE_BIAS + 3) \ + { \ + expnegative = 0; \ + exponent -= IEEE854_LONG_DOUBLE_BIAS + 3; \ + } \ + else \ + { \ + expnegative = 1; \ + exponent = -(exponent - (IEEE854_LONG_DOUBLE_BIAS + 3)); \ + } \ +} while (0) + +#include <sysdeps/generic/printf_fphex.c> diff --git a/sysdeps/x86_64/fpu/s_atanl.c b/sysdeps/x86_64/fpu/s_atanl.c new file mode 100644 index 0000000000..fd4a455b55 --- /dev/null +++ b/sysdeps/x86_64/fpu/s_atanl.c @@ -0,0 +1 @@ +#include "sysdeps/i386/fpu/s_atanl.c" diff --git a/sysdeps/x86_64/fpu/s_cosl.S b/sysdeps/x86_64/fpu/s_cosl.S new file mode 100644 index 0000000000..6636fb5ec6 --- /dev/null +++ b/sysdeps/x86_64/fpu/s_cosl.S @@ -0,0 +1,32 @@ +/* + * Written by J.T. Conklin <jtc@netbsd.org>. + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. + * Adapted for x86-64 by Andreas Jaeger <aj@suse.de>. + */ + +#include <machine/asm.h> + +RCSID("$NetBSD: $") + +ENTRY(__cosl) + fldt 8(%rsp) + fcos + fnstsw %ax + testl $0x400,%eax + jnz 1f + ret + .align ALIGNARG(4) +1: fldpi + fadd %st(0) + fxch %st(1) +2: fprem1 + fnstsw %ax + testl $0x400,%eax + jnz 2b + fstp %st(1) + fcos + ret +END (__cosl) +weak_alias (__cosl, cosl) diff --git a/sysdeps/x86_64/fpu/s_expm1l.S b/sysdeps/x86_64/fpu/s_expm1l.S new file mode 100644 index 0000000000..fa40e05572 --- /dev/null +++ b/sysdeps/x86_64/fpu/s_expm1l.S @@ -0,0 +1,83 @@ +/* ix87 specific implementation of exp(x)-1. + Copyright (C) 1996, 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + Based on code by John C. Bowman <bowman@ipp-garching.mpg.de>. + Corrections by H.J. Lu (hjl@gnu.ai.mit.edu), 1997. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + /* Using: e^x - 1 = 2^(x * log2(e)) - 1 */ + +#include <machine/asm.h> + +#ifdef __ELF__ + .section .rodata +#else + .text +#endif + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(minus1,@object) +minus1: .double -1.0 + ASM_SIZE_DIRECTIVE(minus1) + ASM_TYPE_DIRECTIVE(one,@object) +one: .double 1.0 + ASM_SIZE_DIRECTIVE(one) + ASM_TYPE_DIRECTIVE(l2e,@object) +l2e: .tfloat 1.442695040888963407359924681002 + ASM_SIZE_DIRECTIVE(l2e) + +#ifdef PIC +#define MO(op) op##(%rip) +#else +#define MO(op) op +#endif + + .text +ENTRY(__expm1l) + fldt 8(%rsp) // x + fxam // Is NaN or +-Inf? + fstsw %ax + movb $0x45, %ch + andb %ah, %ch + cmpb $0x40, %ch + je 3f // If +-0, jump. + cmpb $0x05, %ch + je 2f // If +-Inf, jump. + + fldt MO(l2e) // log2(e) : x + fmulp // log2(e)*x + fld %st // log2(e)*x : log2(e)*x + frndint // int(log2(e)*x) : log2(e)*x + fsubr %st, %st(1) // int(log2(e)*x) : fract(log2(e)*x) + fxch // fract(log2(e)*x) : int(log2(e)*x) + f2xm1 // 2^fract(log2(e)*x)-1 : int(log2(e)*x) + fscale // 2^(log2(e)*x)-2^int(log2(e)*x) : int(log2(e)*x) + fxch // int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) + fldl MO(one) // 1 : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) + fscale // 2^int(log2(e)*x) : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) + fsubrl MO(one) // 1-2^int(log2(e)*x) : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) + fstp %st(1) // 1-2^int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) + fsubrp %st, %st(1) // 2^(log2(e)*x) + ret + +2: testl $0x200, %eax // Test sign. + jz 3f // If positive, jump. + fstp %st + fldl MO(minus1) // Set result to -1.0. +3: ret +END(__expm1l) +weak_alias (__expm1l, expm1l) diff --git a/sysdeps/x86_64/fpu/s_fpclassifyl.c b/sysdeps/x86_64/fpu/s_fpclassifyl.c new file mode 100644 index 0000000000..856854b0f5 --- /dev/null +++ b/sysdeps/x86_64/fpu/s_fpclassifyl.c @@ -0,0 +1,2 @@ +#include <sysdeps/i386/fpu/s_fpclassifyl.c> + diff --git a/sysdeps/x86_64/fpu/s_isinfl.c b/sysdeps/x86_64/fpu/s_isinfl.c new file mode 100644 index 0000000000..ca818b5e90 --- /dev/null +++ b/sysdeps/x86_64/fpu/s_isinfl.c @@ -0,0 +1 @@ +#include <sysdeps/i386/fpu/s_isinfl.c> diff --git a/sysdeps/x86_64/fpu/s_isnanl.c b/sysdeps/x86_64/fpu/s_isnanl.c new file mode 100644 index 0000000000..06e69c3aeb --- /dev/null +++ b/sysdeps/x86_64/fpu/s_isnanl.c @@ -0,0 +1 @@ +#include <sysdeps/i386/fpu/s_isnanl.c> diff --git a/sysdeps/x86_64/fpu/s_log1pl.S b/sysdeps/x86_64/fpu/s_log1pl.S new file mode 100644 index 0000000000..7fbd0e5aaa --- /dev/null +++ b/sysdeps/x86_64/fpu/s_log1pl.S @@ -0,0 +1,71 @@ +/* + * Written by J.T. Conklin <jtc@netbsd.org>. + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. + * Adapted for x86-64 by Andreas Jaeger <aj@suse.de>. + */ + +#include <machine/asm.h> + +RCSID("$NetBSD: s_log1p.S,v 1.7 1995/05/09 00:10:58 jtc Exp $") + +#ifdef __ELF__ + .section .rodata +#else + .text +#endif + .align ALIGNARG(4) + /* The fyl2xp1 can only be used for values in + -1 + sqrt(2) / 2 <= x <= 1 - sqrt(2) / 2 + 0.29 is a safe value. + */ +limit: .tfloat 0.29 + /* Please note: we use a double value here. Since 1.0 has + an exact representation this does not effect the accuracy + but it helps to optimize the code. */ +one: .double 1.0 + +/* + * Use the fyl2xp1 function when the argument is in the range -0.29 to 0.29, + * otherwise fyl2x with the needed extra computation. + */ +#ifdef PIC +#define MO(op) op##(%rip) +#else +#define MO(op) op +#endif + + .text +ENTRY(__log1pl) + fldln2 + + fldt 8(%rsp) + + fxam + fnstsw + fld %st + andb $1,%ah + jnz 3f // in case x is NaN or ħInf +4: + fabs + fldt MO(limit) + fcompp + fnstsw + andb $1,%ah + jz 2f + + faddl MO(one) + fyl2x + ret + +2: fyl2xp1 + ret + +3: jp 4b // in case x is ħInf + fstp %st(1) + fstp %st(1) + ret + +END (__log1pl) +weak_alias (__log1pl, log1pl) diff --git a/sysdeps/x86_64/fpu/s_logbl.c b/sysdeps/x86_64/fpu/s_logbl.c new file mode 100644 index 0000000000..4791ba64e8 --- /dev/null +++ b/sysdeps/x86_64/fpu/s_logbl.c @@ -0,0 +1 @@ +#include <sysdeps/i386/fpu/s_logbl.c> diff --git a/sysdeps/x86_64/fpu/s_nextafterl.c b/sysdeps/x86_64/fpu/s_nextafterl.c new file mode 100644 index 0000000000..f59f16848f --- /dev/null +++ b/sysdeps/x86_64/fpu/s_nextafterl.c @@ -0,0 +1 @@ +#include <sysdeps/i386/fpu/s_nextafterl.c> diff --git a/sysdeps/x86_64/fpu/s_nexttoward.c b/sysdeps/x86_64/fpu/s_nexttoward.c new file mode 100644 index 0000000000..aee2bb5895 --- /dev/null +++ b/sysdeps/x86_64/fpu/s_nexttoward.c @@ -0,0 +1 @@ +#include <sysdeps/i386/fpu/s_nexttoward.c> diff --git a/sysdeps/x86_64/fpu/s_nexttowardf.c b/sysdeps/x86_64/fpu/s_nexttowardf.c new file mode 100644 index 0000000000..55e95f6916 --- /dev/null +++ b/sysdeps/x86_64/fpu/s_nexttowardf.c @@ -0,0 +1 @@ +#include <sysdeps/i386/fpu/s_nexttowardf.c> diff --git a/sysdeps/x86_64/fpu/s_rintl.c b/sysdeps/x86_64/fpu/s_rintl.c new file mode 100644 index 0000000000..1cad42e921 --- /dev/null +++ b/sysdeps/x86_64/fpu/s_rintl.c @@ -0,0 +1 @@ +#include <sysdeps/i386/fpu/s_rintl.c> diff --git a/sysdeps/x86_64/fpu/s_significandl.c b/sysdeps/x86_64/fpu/s_significandl.c new file mode 100644 index 0000000000..a4ad986164 --- /dev/null +++ b/sysdeps/x86_64/fpu/s_significandl.c @@ -0,0 +1 @@ +#include <sysdeps/i386/fpu/s_significandl.c> diff --git a/sysdeps/x86_64/fpu/s_sincosl.S b/sysdeps/x86_64/fpu/s_sincosl.S new file mode 100644 index 0000000000..9a3025ab5f --- /dev/null +++ b/sysdeps/x86_64/fpu/s_sincosl.S @@ -0,0 +1,61 @@ +/* Compute sine and cosine of argument. + Copyright (C) 1997, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <machine/asm.h> +#include "bp-sym.h" +#include "bp-asm.h" + +#define PARMS LINKAGE /* no space for saved regs */ +#define ANGLE PARMS +#define SINP ANGLE+12 +#define COSP SINP+PTR_SIZE + + .text +ENTRY (BP_SYM (__sincosl)) + ENTER + + fldt 8(%rsp) + fsincos + fnstsw %ax + testl $0x400,%eax + jnz 1f + fstpt (%rsi) + fstpt (%rdi) + + LEAVE + ret + + .align ALIGNARG(4) +1: fldpi + fadd %st(0) + fxch %st(1) +2: fprem1 + fnstsw %ax + testl $0x400,%eax + jnz 2b + fstp %st(1) + fsincos + fstpt (%rsi) + fstpt (%rdi) + + LEAVE + ret +END (BP_SYM (__sincosl)) +weak_alias (BP_SYM (__sincosl), BP_SYM (sincosl)) diff --git a/sysdeps/x86_64/fpu/s_sinl.S b/sysdeps/x86_64/fpu/s_sinl.S new file mode 100644 index 0000000000..181f112f4f --- /dev/null +++ b/sysdeps/x86_64/fpu/s_sinl.S @@ -0,0 +1,30 @@ +/* + * Written by J.T. Conklin <jtc@netbsd.org>. + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. + * Adapted for x86-64 by Andreas Jaeger <aj@suse.de>. + */ + +#include <machine/asm.h> + +ENTRY(__sinl) + fldt 8(%rsp) + fsin + fnstsw %ax + testl $0x400,%eax + jnz 1f + ret + .align ALIGNARG(4) +1: fldpi + fadd %st(0) + fxch %st(1) +2: fprem1 + fnstsw %ax + testl $0x400,%eax + jnz 2b + fstp %st(1) + fsin + ret +END (__sinl) +weak_alias (__sinl, sinl) diff --git a/sysdeps/x86_64/fpu/s_tanl.S b/sysdeps/x86_64/fpu/s_tanl.S new file mode 100644 index 0000000000..674e908acc --- /dev/null +++ b/sysdeps/x86_64/fpu/s_tanl.S @@ -0,0 +1,33 @@ +/* + * Written by J.T. Conklin <jtc@netbsd.org>. + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. + * Adapted for x86-64 by Andreas Jaeger <aj@suse.de>. + */ + +#include <machine/asm.h> + +RCSID("$NetBSD: $") + +ENTRY(__tanl) + fldt 8(%rsp) + fptan + fnstsw %ax + testl $0x400,%eax + jnz 1f + fstp %st(0) + ret +1: fldpi + fadd %st(0) + fxch %st(1) +2: fprem1 + fstsw %ax + testl $0x400,%eax + jnz 2b + fstp %st(1) + fptan + fstp %st(0) + ret +END (__tanl) +weak_alias (__tanl, tanl) diff --git a/sysdeps/x86_64/gmp-mparam.h b/sysdeps/x86_64/gmp-mparam.h new file mode 100644 index 0000000000..615e23bd0a --- /dev/null +++ b/sysdeps/x86_64/gmp-mparam.h @@ -0,0 +1,27 @@ +/* gmp-mparam.h -- Compiler/machine parameter header file. + +Copyright (C) 2001 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP 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 Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#define BITS_PER_MP_LIMB 64 +#define BYTES_PER_MP_LIMB 8 +#define BITS_PER_LONGINT 64 +#define BITS_PER_INT 32 +#define BITS_PER_SHORTINT 16 +#define BITS_PER_CHAR 8 diff --git a/sysdeps/x86_64/hp-timing.c b/sysdeps/x86_64/hp-timing.c new file mode 100644 index 0000000000..289ca4c3c4 --- /dev/null +++ b/sysdeps/x86_64/hp-timing.c @@ -0,0 +1,2 @@ +/* We can use the i686 implementation without changes. */ +#include <sysdeps/i386/i686/hp-timing.c> diff --git a/sysdeps/x86_64/hp-timing.h b/sysdeps/x86_64/hp-timing.h new file mode 100644 index 0000000000..1f24ffcf5e --- /dev/null +++ b/sysdeps/x86_64/hp-timing.h @@ -0,0 +1,2 @@ +/* We can use the i686 implementation without changes. */ +#include <sysdeps/i386/i686/hp-timing.h> diff --git a/sysdeps/x86_64/htonl.S b/sysdeps/x86_64/htonl.S new file mode 100644 index 0000000000..5aba9b3f28 --- /dev/null +++ b/sysdeps/x86_64/htonl.S @@ -0,0 +1,35 @@ +/* Change byte order in word. For AMD x86-64. + Copyright (C) 1997, 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" + +/* + INPUT PARAMETERS: + word %rdi +*/ + + .text +ENTRY (htonl) + movl %edi, %eax + bswap %eax + ret +END (htonl) + +weak_alias (htonl, ntohl) diff --git a/sysdeps/x86_64/memusage.h b/sysdeps/x86_64/memusage.h new file mode 100644 index 0000000000..d267cf573e --- /dev/null +++ b/sysdeps/x86_64/memusage.h @@ -0,0 +1,22 @@ +/* Copyright (C) 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define GETSP() ({ register uintptr_t stack_ptr asm ("rsp"); stack_ptr; }) +#define GETTIME(low,high) asm ("rdtsc" : "=a" (low), "=d" (high)) + +#include <sysdeps/generic/memusage.h> diff --git a/sysdeps/x86_64/setjmp.S b/sysdeps/x86_64/setjmp.S new file mode 100644 index 0000000000..e40381da31 --- /dev/null +++ b/sysdeps/x86_64/setjmp.S @@ -0,0 +1,45 @@ +/* setjmp for x86-64. + Copyright (C) 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#define _ASM +#define _SETJMP_H +#include <bits/setjmp.h> +#include <asm-syntax.h> + +ENTRY (__sigsetjmp) + /* Save registers. */ + movq %rbx, (JB_RBX*8)(%rdi) + movq %rbp, (JB_RBP*8)(%rdi) + movq %r12, (JB_R12*8)(%rdi) + movq %r13, (JB_R13*8)(%rdi) + movq %r14, (JB_R14*8)(%rdi) + movq %r15, (JB_R15*8)(%rdi) + leaq 8(%rsp), %rdx /* Save SP as it will be after we return. */ + movq %rdx, (JB_RSP*8)(%rdi) + movq (%rsp), %rax /* Save PC we are returning to now. */ + movq %rax, (JB_PC*8)(%rdi) + + /* Make a tail call to __sigjmp_save; it takes the same args. */ +#ifdef PIC + jmp C_SYMBOL_NAME (BP_SYM (__sigjmp_save))@PLT +#else + jmp BP_SYM (__sigjmp_save) +#endif +END (BP_SYM (__sigsetjmp)) diff --git a/sysdeps/x86_64/soft-fp/sfp-machine.h b/sysdeps/x86_64/soft-fp/sfp-machine.h new file mode 100644 index 0000000000..1cc4e24c68 --- /dev/null +++ b/sysdeps/x86_64/soft-fp/sfp-machine.h @@ -0,0 +1,49 @@ +#define _FP_W_TYPE_SIZE 64 +#define _FP_W_TYPE unsigned long +#define _FP_WS_TYPE signed long +#define _FP_I_TYPE long + +#define __FP_CLZ(r, x) \ + do { \ + __asm__("bsrq %1,%0" : "=r"(r) : "g"(x) : "cc"); \ + r ^= 63; \ + } while (0) + +#define _FP_NANFRAC_S _FP_QNANBIT_S +#define _FP_NANFRAC_D _FP_QNANBIT_D, 0 +#define _FP_NANSIGN_S 1 +#define _FP_NANSIGN_D 1 + +#define _FP_KEEPNANFRACP 1 +/* Here is something Intel misdesigned: the specs don't define + the case where we have two NaNs with same mantissas, but + different sign. Different operations pick up different NaNs. + */ +#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ + do { \ + if (_FP_FRAC_GT_##wc(X, Y) \ + || (_FP_FRAC_EQ_##wc(X,Y) && (OP == '+' || OP == '*'))) \ + { \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc(R,X); \ + } \ + else \ + { \ + R##_s = Y##_s; \ + _FP_FRAC_COPY_##wc(R,Y); \ + } \ + R##_c = FP_CLS_NAN; \ + } while (0) + +#define FP_EX_INVALID (1 << 0) +#define FP_EX_DENORM (1 << 1) +#define FP_EX_DIVZERO (1 << 2) +#define FP_EX_OVERFLOW (1 << 3) +#define FP_EX_UNDERFLOW (1 << 4) +#define FP_EX_INEXACT (1 << 5) + +#define FP_RND_NEAREST 0 +#define FP_RND_ZERO 3 +#define FP_RND_PINF 2 +#define FP_RND_MINF 1 + diff --git a/sysdeps/x86_64/stackinfo.h b/sysdeps/x86_64/stackinfo.h new file mode 100644 index 0000000000..60668d10b1 --- /dev/null +++ b/sysdeps/x86_64/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On x86_64 the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/sysdeps/x86_64/sysdep.h b/sysdeps/x86_64/sysdep.h new file mode 100644 index 0000000000..2a2ad41e52 --- /dev/null +++ b/sysdeps/x86_64/sysdep.h @@ -0,0 +1,101 @@ +/* Assembler macros for x86-64. + Copyright (C) 2001 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdeps/generic/sysdep.h> + +#ifdef __ASSEMBLER__ + +/* Syntactic details of assembler. */ + +#ifdef HAVE_ELF + +/* ELF uses byte-counts for .align, most others use log2 of count of bytes. */ +#define ALIGNARG(log2) 1<<log2 +/* For ELF we need the `.type' directive to make shared libs work right. */ +#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg; +#define ASM_SIZE_DIRECTIVE(name) .size name,.-name; + +/* In ELF C symbols are asm symbols. */ +#undef NO_UNDERSCORES +#define NO_UNDERSCORES + +#else + +#define ALIGNARG(log2) log2 +#define ASM_TYPE_DIRECTIVE(name,type) /* Nothing is specified. */ +#define ASM_SIZE_DIRECTIVE(name) /* Nothing is specified. */ + +#endif + + +/* Define an entry point visible from C. */ +#define ENTRY(name) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ + .align ALIGNARG(4); \ + C_LABEL(name) \ + CALL_MCOUNT + +#undef END +#define END(name) \ + ASM_SIZE_DIRECTIVE(name) \ + +/* If compiled for profiling, call `mcount' at the start of each function. */ +#ifdef PROF +/* XXX this does not work yet! */ +/* 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; movl %esp, %ebp; call JUMPTARGET(mcount); popl %ebp; +#else +#define CALL_MCOUNT /* Do nothing. */ +#endif + +#ifdef NO_UNDERSCORES +/* 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 +#endif + +#define PSEUDO(name, syscall_name, args) \ +lose: \ + jmp JUMPTARGET(syscall_error) \ + .globl syscall_error; \ + ENTRY (name) \ + DO_CALL (syscall_name, args); \ + jb lose + +#undef PSEUDO_END +#define PSEUDO_END(name) \ + END (name) + +#ifdef PIC +#define JUMPTARGET(name) name##@PLT +#else +#define JUMPTARGET(name) name +#endif + +/* Local label name for asm code. */ +#ifndef L +#define L(name) name +#endif + +#endif /* __ASSEMBLER__ */ |