diff options
Diffstat (limited to 'sysdeps')
114 files changed, 4466 insertions, 427 deletions
diff --git a/sysdeps/generic/bits/utmp.h b/sysdeps/generic/bits/utmp.h index b8decb0..ccc318b 100644 --- a/sysdeps/generic/bits/utmp.h +++ b/sysdeps/generic/bits/utmp.h @@ -17,7 +17,7 @@ Boston, MA 02111-1307, USA. */ #ifndef _UTMP_H -#error "Never use <bits/utmp.h> directly; include <utmp.h> instead." +# error "Never use <bits/utmp.h> directly; include <utmp.h> instead." #endif @@ -33,21 +33,23 @@ __BEGIN_DECLS -struct lastlog { - time_t ll_time; - char ll_line[UT_LINESIZE]; - char ll_host[UT_HOSTSIZE]; -}; +struct lastlog + { + time_t ll_time; + char ll_line[UT_LINESIZE]; + char ll_host[UT_HOSTSIZE]; + }; -struct utmp { - char ut_line[UT_LINESIZE]; - char ut_name[UT_NAMESIZE]; - char ut_host[UT_HOSTSIZE]; - long ut_time; -}; +struct utmp + { + char ut_line[UT_LINESIZE]; + char ut_user[UT_NAMESIZE]; +#define ut_name ut_user + char ut_host[UT_HOSTSIZE]; + long int ut_time; + }; #define _HAVE_UT_HOST 1 /* We have the ut_host field. */ - __END_DECLS diff --git a/sysdeps/generic/bits/utmpx.h b/sysdeps/generic/bits/utmpx.h new file mode 100644 index 0000000..f85fce0 --- /dev/null +++ b/sysdeps/generic/bits/utmpx.h @@ -0,0 +1,34 @@ +/* Structures and definitions for the user accounting database. Generic/BSDish + Copyright (C) 1993, 1996, 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#ifndef _UTMPX_H +#error "Never use <bits/utmpx.h> directly; include <utmpx.h> instead." +#endif + + +#define __UT_NAMESIZE 8 +#define __UT_LINESIZE 8 +#define __UT_HOSTSIZE 16 + +struct utmpx +{ + char ut_line[__UT_LINESIZE]; + char ut_name[__UT_NAMESIZE]; + char ut_host[__UT_HOSTSIZE]; + long ut_time; +}; diff --git a/sysdeps/generic/sys/mman.h b/sysdeps/generic/sys/mman.h index 9c2a1b6..6484e02 100644 --- a/sysdeps/generic/sys/mman.h +++ b/sysdeps/generic/sys/mman.h @@ -36,38 +36,48 @@ without PROT_READ. The only guarantees are that no writing will be allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ -#define PROT_NONE 0x00 /* No access. */ -#define PROT_READ 0x04 /* Pages can be read. */ -#define PROT_WRITE 0x02 /* Pages can be written. */ -#define PROT_EXEC 0x01 /* Pages can be executed. */ +#define PROT_NONE 0x00 /* No access. */ +#define PROT_READ 0x04 /* Pages can be read. */ +#define PROT_WRITE 0x02 /* Pages can be written. */ +#define PROT_EXEC 0x01 /* Pages can be executed. */ /* Flags contain mapping type, sharing type and options. */ /* Mapping type (must choose one and only one of these). */ -#define MAP_FILE 0x0001 /* Mapped from a file or device. */ -#define MAP_ANON 0x0002 /* Allocated from anonymous virtual memory. */ -#define MAP_TYPE 0x000f /* Mask for type field. */ +#ifdef __USE_BSD +# define MAP_FILE 0x0001 /* Mapped from a file or device. */ +# define MAP_ANON 0x0002 /* Allocated from anonymous virtual memory. */ +# define MAP_TYPE 0x000f /* Mask for type field. */ +#endif /* Sharing types (must choose one and only one of these). */ -#define MAP_COPY 0x0020 /* Virtual copy of region at mapping time. */ -#define MAP_SHARED 0x0010 /* Share changes. */ -#define MAP_PRIVATE 0x0000 /* Changes private; copy pages on write. */ +#ifdef __USE_BSD +# define MAP_COPY 0x0020 /* Virtual copy of region at mapping time. */ +#endif +#define MAP_SHARED 0x0010 /* Share changes. */ +#define MAP_PRIVATE 0x0000 /* Changes private; copy pages on write. */ /* Other flags. */ -#define MAP_FIXED 0x0100 /* Map address must be exactly as requested. */ -#define MAP_NOEXTEND 0x0200 /* For MAP_FILE, don't change file size. */ -#define MAP_HASSEMPHORE 0x0400 /* Region may contain semaphores. */ -#define MAP_INHERIT 0x0800 /* Region is retained after exec. */ +#define MAP_FIXED 0x0100 /* Map address must be exactly as requested. */ +#ifdef __USE_BSD +# define MAP_NOEXTEND 0x0200 /* For MAP_FILE, don't change file size. */ +# define MAP_HASSEMPHORE 0x0400 /* Region may contain semaphores. */ +# define MAP_INHERIT 0x0800 /* Region is retained after exec. */ +#endif /* Advice to `madvise'. */ -#define MADV_NORMAL 0 /* No further special treatment. */ -#define MADV_RANDOM 1 /* Expect random page references. */ -#define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ -#define MADV_WILLNEED 3 /* Will need these pages. */ -#define MADV_DONTNEED 4 /* Don't need these pages. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +#endif + +/* Return value of `mmap' in case of an error. */ +#define MAP_FAILED ((__caddr_t) -1) -#include <sys/cdefs.h> __BEGIN_DECLS /* Map addresses starting near ADDR and extending for LEN bytes. from @@ -75,34 +85,36 @@ __BEGIN_DECLS is nonzero, it is the desired mapping address. If the MAP_FIXED bit is set in FLAGS, the mapping will be at ADDR exactly (which must be page-aligned); otherwise the system chooses a convenient nearby address. - The return value is the actual mapping address chosen or (caddr_t) -1 + The return value is the actual mapping address chosen or MAP_FAILED for errors (in which case `errno' is set). A successful `mmap' call deallocates any previous mapping for the affected region. */ -__caddr_t __mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, __off_t __offset)); -__caddr_t mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, __off_t __offset)); +extern __caddr_t __mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, __off_t __offset)); +extern __caddr_t mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, __off_t __offset)); /* Deallocate any mapping for the region starting at ADDR and extending LEN bytes. Returns 0 if successful, -1 for errors (and sets errno). */ -int __munmap __P ((__caddr_t __addr, size_t __len)); -int munmap __P ((__caddr_t __addr, size_t __len)); +extern int __munmap __P ((__caddr_t __addr, size_t __len)); +extern int munmap __P ((__caddr_t __addr, size_t __len)); /* Change the memory protection of the region starting at ADDR and extending LEN bytes to PROT. Returns 0 if successful, -1 for errors (and sets errno). */ -int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); -int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); /* Synchronize the region starting at ADDR and extending LEN bytes with the file it maps. Filesystem operations on a file being mapped are unpredictable before this is done. Flags are from the MS_* set. */ -int msync __P ((__caddr_t __addr, size_t __len, int flags)); +extern int msync __P ((__caddr_t __addr, size_t __len, int __flags)); +#ifdef __USE_BSD /* Advise the system about particular usage patterns the program follows for the region starting at ADDR and extending LEN bytes. */ -int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +extern int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +#endif __END_DECLS diff --git a/sysdeps/i386/i586/stpcpy.S b/sysdeps/i386/i586/stpcpy.S new file mode 100644 index 0000000..ea24fa7 --- /dev/null +++ b/sysdeps/i386/i586/stpcpy.S @@ -0,0 +1,6 @@ +#define USE_AS_STPCPY +#define STRCPY __stpcpy + +#include <sysdeps/i386/i586/strcpy.S> + +weak_alias (__stpcpy, stpcpy) diff --git a/sysdeps/i386/i586/strcpy.S b/sysdeps/i386/i586/strcpy.S new file mode 100644 index 0000000..7f89a2c --- /dev/null +++ b/sysdeps/i386/i586/strcpy.S @@ -0,0 +1,147 @@ +/* strcpy/stpcpy implementation for i586. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <sysdep.h> +#include "asm-syntax.h" + +#ifndef USE_AS_STPCPY +# define STRCPY strcpy +#endif + +#define magic 0xfefefeff + + .text +ENTRY(STRCPY) + pushl %edi + pushl %esi + pushl %ebx + + movl 16(%esp), %edi + movl 20(%esp), %esi + + xorl %eax, %eax + leal -1(%esi), %ecx + + movl $magic, %ebx + andl $3, %ecx + +#ifdef PIC + call 2f +2: popl %edx + /* 0xb is the distance between 2: and 1: but we avoid writing + 1f-2b because the assembler generates worse code. */ + leal 0xb(%edx,%ecx,8), %ecx +#else + leal 1f(,%ecx,8), %ecx +#endif + + jmp *%ecx + + .align 8 +1: + orb (%esi), %al + jz L(end) + stosb + xorl %eax, %eax + incl %esi + + orb (%esi), %al + jz L(end) + stosb + xorl %eax, %eax + incl %esi + + orb (%esi), %al + jz L(end) + stosb + xorl %eax, %eax + incl %esi + +L(1): movl (%esi), %ecx + leal 4(%esi),%esi + + subl %ecx, %eax + addl %ebx, %ecx + + decl %eax + jnc L(3) + + movl %ecx, %edx + xorl %ecx, %eax + + subl %ebx, %edx + andl $~magic, %eax + + jne L(4) + + movl %edx, (%edi) + leal 4(%edi),%edi + + jmp L(1) + +L(3): movl %ecx, %edx + + subl %ebx, %edx + +L(4): movb %dl, (%edi) + testb %dl, %dl + + movl %edx, %eax + jz L(end2) + + shrl $16, %eax + movb %dh, 1(%edi) +#ifdef USE_AS_STPCPY + addl $1, %edi +#endif + + cmpb $0, %dh + jz L(end2) + +#ifdef USE_AS_STPCPY + movb %al, 1(%edi) + addl $1, %edi + + cmpb $0, %al + jz L(end2) + + addl $1, %edi +#else + movb %al, 2(%edi) + testb %al, %al + + leal 3(%edi), %edi + jz L(end2) +#endif + +L(end): movb %ah, (%edi) + +L(end2): +#ifdef USE_AS_STPCPY + movl %edi, %eax +#endif + popl %ebx + popl %esi + popl %edi +#ifndef USE_AS_STPCPY + movl 4(%esp), %eax +#endif + ret +END(STRCPY) diff --git a/sysdeps/i386/i686/Implies b/sysdeps/i386/i686/Implies index 75fde78..b5c05ec 100644 --- a/sysdeps/i386/i686/Implies +++ b/sysdeps/i386/i686/Implies @@ -1,2 +1,4 @@ -# Code optimized for i586 is better than simple i386 code. -i386/i586 +# Due to the reordering and the oher nifty extensions in the i686 it is +# not really good to use heavily i586 optimized code on a i686. It's +# better to use i486/i386 code. +i386/i486 diff --git a/sysdeps/libm-i387/e_rem_pio2.c b/sysdeps/libm-i387/e_rem_pio2.c new file mode 100644 index 0000000..1347b04 --- /dev/null +++ b/sysdeps/libm-i387/e_rem_pio2.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/libm-i387/e_rem_pio2f.c b/sysdeps/libm-i387/e_rem_pio2f.c new file mode 100644 index 0000000..1347b04 --- /dev/null +++ b/sysdeps/libm-i387/e_rem_pio2f.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/libm-i387/e_rem_pio2l.c b/sysdeps/libm-i387/e_rem_pio2l.c new file mode 100644 index 0000000..1347b04 --- /dev/null +++ b/sysdeps/libm-i387/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/libm-i387/k_rem_pio2.c b/sysdeps/libm-i387/k_rem_pio2.c new file mode 100644 index 0000000..1347b04 --- /dev/null +++ b/sysdeps/libm-i387/k_rem_pio2.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/libm-i387/k_rem_pio2f.c b/sysdeps/libm-i387/k_rem_pio2f.c new file mode 100644 index 0000000..1347b04 --- /dev/null +++ b/sysdeps/libm-i387/k_rem_pio2f.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/libm-i387/k_rem_pio2l.c b/sysdeps/libm-i387/k_rem_pio2l.c new file mode 100644 index 0000000..1347b04 --- /dev/null +++ b/sysdeps/libm-i387/k_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/libm-i387/s_cbrt.S b/sysdeps/libm-i387/s_cbrt.S index 4b9a2b1..3f6a017 100644 --- a/sysdeps/libm-i387/s_cbrt.S +++ b/sysdeps/libm-i387/s_cbrt.S @@ -28,34 +28,36 @@ #endif .align ALIGNARG(4) - ASM_TYPE_DIRECTIVE(f1,@object) -f1: .double 0.354895765043919860 - ASM_SIZE_DIRECTIVE(f1) - ASM_TYPE_DIRECTIVE(f2,@object) -f2: .double 1.50819193781584896 - ASM_SIZE_DIRECTIVE(f2) - ASM_TYPE_DIRECTIVE(f3,@object) -f3: .double -2.11499494167371287 - ASM_SIZE_DIRECTIVE(f3) - ASM_TYPE_DIRECTIVE(f4,@object) -f4: .double 2.44693122563534430 - ASM_SIZE_DIRECTIVE(f4) - ASM_TYPE_DIRECTIVE(f5,@object) -f5: .double -1.83469277483613086 - ASM_SIZE_DIRECTIVE(f5) - ASM_TYPE_DIRECTIVE(f6,@object) -f6: .double 0.784932344976639262 - ASM_SIZE_DIRECTIVE(f6) ASM_TYPE_DIRECTIVE(f7,@object) f7: .double -0.145263899385486377 ASM_SIZE_DIRECTIVE(f7) + ASM_TYPE_DIRECTIVE(f6,@object) +f6: .double 0.784932344976639262 + ASM_SIZE_DIRECTIVE(f6) + ASM_TYPE_DIRECTIVE(f5,@object) +f5: .double -1.83469277483613086 + ASM_SIZE_DIRECTIVE(f5) + ASM_TYPE_DIRECTIVE(f4,@object) +f4: .double 2.44693122563534430 + ASM_SIZE_DIRECTIVE(f4) + ASM_TYPE_DIRECTIVE(f3,@object) +f3: .double -2.11499494167371287 + ASM_SIZE_DIRECTIVE(f3) + ASM_TYPE_DIRECTIVE(f2,@object) +f2: .double 1.50819193781584896 + ASM_SIZE_DIRECTIVE(f2) + ASM_TYPE_DIRECTIVE(f1,@object) +f1: .double 0.354895765043919860 + ASM_SIZE_DIRECTIVE(f1) -#define CBRT2 1.2599210498948731648 -#define SQR_CBRT2 1.5874010519681994748 +#define CBRT2 1.2599210498948731648 +#define ONE_CBRT2 0.793700525984099737355196796584 +#define SQR_CBRT2 1.5874010519681994748 +#define ONE_SQR_CBRT2 0.629960524947436582364439673883 ASM_TYPE_DIRECTIVE(factor,@object) -factor: .double 1.0 / SQR_CBRT2 - .double 1.0 / CBRT2 +factor: .double ONE_SQR_CBRT2 + .double ONE_CBRT2 .double 1.0 .double CBRT2 .double SQR_CBRT2 @@ -67,10 +69,10 @@ two54: .byte 0, 0, 0, 0, 0, 0, 0x50, 0x43 #ifdef PIC #define MO(op) op##@GOTOFF(%ebx) -#define MOX(op,x,f) op##@GOTOFF(%ebx,x,f) +#define MOX(op,x) op##@GOTOFF(%ebx,x,1) #else #define MO(op) op -#define MOX(op,x,f) op(,x,f) +#define MOX(op,x) op(x) #endif .text @@ -102,8 +104,13 @@ ENTRY(__cbrt) #endif fmull MO(two54) movl $-54, %ecx +#ifdef PIC + fstpl 8(%esp) + movl 12(%esp), %eax +#else fstpl 4(%esp) movl 8(%esp), %eax +#endif movl %eax, %edx andl $0x7fffffff, %eax @@ -123,11 +130,16 @@ ENTRY(__cbrt) #endif fabs - /* The following code has two track: + /* The following code has two tracks: a) compute the normalized cbrt value b) compute xe/3 and xe%3 The right track computes the value for b) and this is done - in an optimized way by avoiding division. */ + in an optimized way by avoiding division. + + But why two tracks at all? Very easy: efficiency. Some FP + instruction can overlap with a certain amount of integer (and + FP) instructions. So we get (except for the imull) all + instructions for free. */ fld %st(0) /* xm : xm */ @@ -161,20 +173,24 @@ ENTRY(__cbrt) fadd %st(0) /* 2*t2 : t2+2*xm : u : xm */ subl %edx, %ecx faddp %st, %st(3) /* t2+2*xm : u : 2*t2+xm */ + shll $3, %ecx fmulp /* u*(t2+2*xm) : 2*t2+xm */ fdivp %st, %st(1) /* u*(t2+2*xm)/(2*t2+xm) */ - fmull MOX(16+factor,%ecx,8) /* u*(t2+2*xm)/(2*t2+xm)*FACT */ + fmull MOX(16+factor,%ecx) /* u*(t2+2*xm)/(2*t2+xm)*FACT */ pushl %eax fildl (%esp) /* xe/3 : u*(t2+2*xm)/(2*t2+xm)*FACT */ fxch /* u*(t2+2*xm)/(2*t2+xm)*FACT : xe/3 */ - popl %eax fscale /* u*(t2+2*xm)/(2*t2+xm)*FACT*2^xe/3 */ - fstp %st(1) + popl %edx #ifdef PIC + movl 12(%esp), %eax popl %ebx +#else + movl 8(%esp), %eax #endif - testl $0x80000000, 8(%esp) - jz 4f + testl %eax, %eax + fstp %st(1) + jns 4f fchs 4: ret diff --git a/sysdeps/libm-i387/s_cbrtf.S b/sysdeps/libm-i387/s_cbrtf.S index 6978da2..a14e04e 100644 --- a/sysdeps/libm-i387/s_cbrtf.S +++ b/sysdeps/libm-i387/s_cbrtf.S @@ -28,22 +28,25 @@ #endif .align ALIGNARG(4) - ASM_TYPE_DIRECTIVE(f1,@object) -f1: .double 0.492659620528969547 - ASM_SIZE_DIRECTIVE(f1) - ASM_TYPE_DIRECTIVE(f2,@object) -f2: .double 0.697570460207922770 - ASM_SIZE_DIRECTIVE(f2) ASM_TYPE_DIRECTIVE(f3,@object) f3: .double 0.191502161678719066 ASM_SIZE_DIRECTIVE(f3) + ASM_TYPE_DIRECTIVE(f2,@object) +f2: .double 0.697570460207922770 + ASM_SIZE_DIRECTIVE(f2) + ASM_TYPE_DIRECTIVE(f1,@object) +f1: .double 0.492659620528969547 + ASM_SIZE_DIRECTIVE(f1) -#define CBRT2 1.2599210498948731648 -#define SQR_CBRT2 1.5874010519681994748 +#define CBRT2 1.2599210498948731648 +#define ONE_CBRT2 0.793700525984099737355196796584 +#define SQR_CBRT2 1.5874010519681994748 +#define ONE_SQR_CBRT2 0.629960524947436582364439673883 ASM_TYPE_DIRECTIVE(factor,@object) -factor: .double 1.0 / SQR_CBRT2 - .double 1.0 / CBRT2 + .align ALIGNARG(4) +factor: .double ONE_SQR_CBRT2 + .double ONE_CBRT2 .double 1.0 .double CBRT2 .double SQR_CBRT2 @@ -55,10 +58,10 @@ two25: .byte 0, 0, 0, 0x4c #ifdef PIC #define MO(op) op##@GOTOFF(%ebx) -#define MOX(op,x,f) op##@GOTOFF(%ebx,x,f) +#define MOX(op,x) op##@GOTOFF(%ebx,x,1) #else #define MO(op) op -#define MOX(op,x,f) op(,x,f) +#define MOX(op,x) op(x) #endif .text @@ -114,11 +117,16 @@ ENTRY(__cbrtf) #endif fabs - /* The following code has two track: + /* The following code has two tracks: a) compute the normalized cbrt value b) compute xe/3 and xe%3 The right track computes the value for b) and this is done - in an optimized way by avoiding division. */ + in an optimized way by avoiding division. + + But why two tracks at all? Very easy: efficiency. Some FP + instruction can overlap with a certain amount of integer (and + FP) instructions. So we get (except for the imull) all + instructions for free. */ fld %st(0) /* xm : xm */ fmull MO(f3) /* f3*xm : xm */ @@ -142,20 +150,24 @@ ENTRY(__cbrtf) fadd %st(0) /* 2*t2 : t2+2*xm : u : xm */ subl %edx, %ecx faddp %st, %st(3) /* t2+2*xm : u : 2*t2+xm */ + shll $3, %ecx fmulp /* u*(t2+2*xm) : 2*t2+xm */ fdivp %st, %st(1) /* u*(t2+2*xm)/(2*t2+xm) */ - fmull MOX(16+factor,%ecx,8) /* u*(t2+2*xm)/(2*t2+xm)*FACT */ + fmull MOX(16+factor,%ecx) /* u*(t2+2*xm)/(2*t2+xm)*FACT */ pushl %eax fildl (%esp) /* xe/3 : u*(t2+2*xm)/(2*t2+xm)*FACT */ fxch /* u*(t2+2*xm)/(2*t2+xm)*FACT : xe/3 */ - popl %eax fscale /* u*(t2+2*xm)/(2*t2+xm)*FACT*2^xe/3 */ - fstp %st(1) + popl %edx #ifdef PIC + movl 8(%esp), %eax popl %ebx +#else + movl 4(%esp), %eax #endif - testl $0x80000000, 4(%esp) - jz 4f + testl %eax, %eax + fstp %st(1) + jns 4f fchs 4: ret diff --git a/sysdeps/libm-i387/s_cbrtl.S b/sysdeps/libm-i387/s_cbrtl.S index b2023d1..6a3b9a8 100644 --- a/sysdeps/libm-i387/s_cbrtl.S +++ b/sysdeps/libm-i387/s_cbrtl.S @@ -28,52 +28,69 @@ #endif .align ALIGNARG(4) - ASM_TYPE_DIRECTIVE(f1,@object) -f1: .double 0.338058687610520237 - ASM_SIZE_DIRECTIVE(f1) - ASM_TYPE_DIRECTIVE(f2,@object) -f2: .double 1.67595307700780102 - ASM_SIZE_DIRECTIVE(f2) - ASM_TYPE_DIRECTIVE(f3,@object) -f3: .double -2.82414939754975962 - ASM_SIZE_DIRECTIVE(f3) - ASM_TYPE_DIRECTIVE(f4,@object) -f4: .double 4.09559907378707839 - ASM_SIZE_DIRECTIVE(f4) - ASM_TYPE_DIRECTIVE(f5,@object) -f5: .double -4.11151425200350531 - ASM_SIZE_DIRECTIVE(f5) - ASM_TYPE_DIRECTIVE(f6,@object) -f6: .double 2.65298938441952296 - ASM_SIZE_DIRECTIVE(f6) - ASM_TYPE_DIRECTIVE(f7,@object) -f7: .double -0.988553671195413709 - ASM_SIZE_DIRECTIVE(f7) ASM_TYPE_DIRECTIVE(f8,@object) -f8: .double 0.161617097923756032 +f8: .tfloat 0.161617097923756032 ASM_SIZE_DIRECTIVE(f8) + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(f7,@object) +f7: .tfloat -0.988553671195413709 + ASM_SIZE_DIRECTIVE(f7) + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(f6,@object) +f6: .tfloat 2.65298938441952296 + ASM_SIZE_DIRECTIVE(f6) + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(f5,@object) +f5: .tfloat -4.11151425200350531 + ASM_SIZE_DIRECTIVE(f5) + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(f4,@object) +f4: .tfloat 4.09559907378707839 + ASM_SIZE_DIRECTIVE(f4) + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(f3,@object) +f3: .tfloat -2.82414939754975962 + ASM_SIZE_DIRECTIVE(f3) + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(f2,@object) +f2: .tfloat 1.67595307700780102 + ASM_SIZE_DIRECTIVE(f2) + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(f1,@object) +f1: .tfloat 0.338058687610520237 + ASM_SIZE_DIRECTIVE(f1) -#define CBRT2 1.2599210498948731648 -#define SQR_CBRT2 1.5874010519681994748 +#define CBRT2 1.2599210498948731648 +#define ONE_CBRT2 0.793700525984099737355196796584 +#define SQR_CBRT2 1.5874010519681994748 +#define ONE_SQR_CBRT2 0.629960524947436582364439673883 + /* We make the entries in the following table all 16 bytes + wide to avoid having to implement a multiplication by 10. */ ASM_TYPE_DIRECTIVE(factor,@object) -factor: .double 1.0 / SQR_CBRT2 - .double 1.0 / CBRT2 - .double 1.0 - .double CBRT2 - .double SQR_CBRT2 + .align ALIGNARG(4) +factor: .tfloat ONE_SQR_CBRT2 + .byte 0, 0, 0, 0, 0, 0 + .tfloat ONE_CBRT2 + .byte 0, 0, 0, 0, 0, 0 + .tfloat 1.0 + .byte 0, 0, 0, 0, 0, 0 + .tfloat CBRT2 + .byte 0, 0, 0, 0, 0, 0 + .tfloat SQR_CBRT2 ASM_SIZE_DIRECTIVE(factor) ASM_TYPE_DIRECTIVE(two64,@object) + .align ALIGNARG(4) two64: .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x43 ASM_SIZE_DIRECTIVE(two64) #ifdef PIC #define MO(op) op##@GOTOFF(%ebx) -#define MOX(op,x,f) op##@GOTOFF(%ebx,x,f) +#define MOX(op,x) op##@GOTOFF(%ebx,x,1) #else #define MO(op) op -#define MOX(op,x,f) op(,x,f) +#define MOX(op,x) op(x) #endif .text @@ -97,7 +114,7 @@ ENTRY(__cbrtl) #endif cmpl $0, %eax - je 2f + jne 2f #ifdef PIC fldt 8(%esp) @@ -106,8 +123,13 @@ ENTRY(__cbrtl) #endif fmull MO(two64) movl $-64, %ecx +#ifdef PIC + fstpt 8(%esp) + movl 16(%esp), %eax +#else fstpt 4(%esp) movl 12(%esp), %eax +#endif movl %eax, %edx andl $0x7fff, %eax @@ -126,31 +148,45 @@ ENTRY(__cbrtl) #endif fabs - /* The following code has two track: + /* The following code has two tracks: a) compute the normalized cbrt value b) compute xe/3 and xe%3 The right track computes the value for b) and this is done - in an optimized way by avoiding division. */ + in an optimized way by avoiding division. - fld %st(0) /* xm : xm */ + But why two tracks at all? Very easy: efficiency. Some FP + instruction can overlap with a certain amount of integer (and + FP) instructions. So we get (except for the imull) all + instructions for free. */ - fmull MO(f7) /* f7*xm : xm */ + fldt MO(f8) /* f8 : xm */ + fmul %st(1) /* f8*xm : xm */ + + fldt MO(f7) + faddp /* f7+f8*xm : xm */ + fmul %st(1) /* (f7+f8*xm)*xm : xm */ movl $1431655766, %eax - faddl MO(f6) /* f6+f7*xm : xm */ + fldt MO(f6) + faddp /* f6+(f7+f8*xm)*xm : xm */ imull %ecx - fmul %st(1) /* (f6+f7*xm)*xm : xm */ + fmul %st(1) /* (f6+(f7+f8*xm)*xm)*xm : xm */ movl %ecx, %eax - faddl MO(f5) /* f5+(f6+f7*xm)*xm : xm */ + fldt MO(f5) + faddp /* f5+(f6+(f7+f8*xm)*xm)*xm : xm */ sarl $31, %eax - fmul %st(1) /* (f5+(f6+f7*xm)*xm)*xm : xm */ + fmul %st(1) /* (f5+(f6+(f7+f8*xm)*xm)*xm)*xm : xm */ subl %eax, %edx - faddl MO(f4) /* f4+(f5+(f6+f7*xm)*xm)*xm : xm */ - fmul %st(1) /* (f4+(f5+(f6+f7*xm)*xm)*xm)*xm : xm */ - faddl MO(f3) /* f3+(f4+(f5+(f6+f7*xm)*xm)*xm)*xm : xm */ - fmul %st(1) /* (f3+(f4+(f5+(f6+f7*xm)*xm)*xm)*xm)*xm : xm */ - faddl MO(f2) /* f2+(f3+(f4+(f5+(f6+f7*xm)*xm)*xm)*xm)*xm : xm */ - fmul %st(1) /* (f2+(f3+(f4+(f5+(f6+f7*xm)*xm)*xm)*xm)*xm)*xm : xm */ - faddl MO(f1) /* u:=f1+(f2+(f3+(f4+(f5+(f6+f7*xm)*xm)*xm)*xm)*xm)*xm : xm */ + fldt MO(f4) + faddp /* f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm : xm */ + fmul %st(1) /* (f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm : xm */ + fldt MO(f3) + faddp /* f3+(f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm : xm */ + fmul %st(1) /* (f3+(f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm)*xm : xm */ + fldt MO(f2) + faddp /* f2+(f3+(f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm)*xm : xm */ + fmul %st(1) /* (f2+(f3+(f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm)*xm)*xm : xm */ + fldt MO(f1) + faddp /* u:=f1+(f2+(f3+(f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm)*xm)*xm : xm */ fld %st /* u : u : xm */ fmul %st(1) /* u*u : u : xm */ @@ -164,19 +200,24 @@ ENTRY(__cbrtl) fadd %st(0) /* 2*t2 : t2+2*xm : u : xm */ subl %edx, %ecx faddp %st, %st(3) /* t2+2*xm : u : 2*t2+xm */ + shll $4, %ecx fmulp /* u*(t2+2*xm) : 2*t2+xm */ fdivp %st, %st(1) /* u*(t2+2*xm)/(2*t2+xm) */ - fmull MOX(16+factor,%ecx,8) /* u*(t2+2*xm)/(2*t2+xm)*FACT */ + fldt MOX(32+factor,%ecx) + fmulp /* u*(t2+2*xm)/(2*t2+xm)*FACT */ pushl %eax fildl (%esp) /* xe/3 : u*(t2+2*xm)/(2*t2+xm)*FACT */ fxch /* u*(t2+2*xm)/(2*t2+xm)*FACT : xe/3 */ - popl %eax fscale /* u*(t2+2*xm)/(2*t2+xm)*FACT*2^xe/3 */ - fstp %st(1) + popl %edx #ifdef PIC + movl 16(%esp), %eax popl %ebx +#else + movl 12(%esp), %eax #endif - testl $0x8000, 12(%esp) + testl $0x8000, %eax + fstp %st(1) jz 4f fchs 4: ret diff --git a/sysdeps/libm-ieee754/s_isinf.c b/sysdeps/libm-ieee754/s_isinf.c index 6f76ce1..4f063d0 100644 --- a/sysdeps/libm-ieee754/s_isinf.c +++ b/sysdeps/libm-ieee754/s_isinf.c @@ -16,12 +16,8 @@ static char rcsid[] = "$NetBSD: s_isinf.c,v 1.3 1995/05/11 23:20:14 jtc Exp $"; #include "math.h" #include "math_private.h" -#ifdef __STDC__ - int __isinf(double x) -#else - int __isinf(x) - double x; -#endif +int +__isinf (double x) { int32_t hx,lx; EXTRACT_WORDS(hx,lx,x); diff --git a/sysdeps/libm-ieee754/s_isinff.c b/sysdeps/libm-ieee754/s_isinff.c index 18a0b5e..efc0935 100644 --- a/sysdeps/libm-ieee754/s_isinff.c +++ b/sysdeps/libm-ieee754/s_isinff.c @@ -15,12 +15,8 @@ static char rcsid[] = "$NetBSD: s_isinff.c,v 1.3 1995/05/11 23:20:21 jtc Exp $"; #include "math.h" #include "math_private.h" -#ifdef __STDC__ - int __isinff(float x) -#else - int __isinff(x) - float x; -#endif +int +__isinff (float x) { int32_t ix,t; GET_FLOAT_WORD(ix,x); diff --git a/sysdeps/libm-ieee754/s_isinfl.c b/sysdeps/libm-ieee754/s_isinfl.c index b499821..697534e 100644 --- a/sysdeps/libm-ieee754/s_isinfl.c +++ b/sysdeps/libm-ieee754/s_isinfl.c @@ -16,12 +16,8 @@ static char rcsid[] = "$NetBSD: $"; #include "math.h" #include "math_private.h" -#ifdef __STDC__ - int __isinfl(long double x) -#else - int __isinfl(x) - long double x; -#endif +int +__isinfl (long double x) { int32_t se,hx,lx; GET_LDOUBLE_WORDS(se,hx,lx,x); diff --git a/sysdeps/libm-ieee754/s_lround.c b/sysdeps/libm-ieee754/s_lround.c index 0f91280..974dbde 100644 --- a/sysdeps/libm-ieee754/s_lround.c +++ b/sysdeps/libm-ieee754/s_lround.c @@ -26,40 +26,40 @@ #ifdef NO_LONG_DOUBLE /* The `long double' is in fact the IEEE `double' type. */ +/* This code does not presently work. */ + long int __lround (long double x) { int32_t j0; u_int32_t i1, i0; long int result; + int sign; EXTRACT_WORDS (i0, i1, x); j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + sign = (i0 & 0x80000000) != 0 ? -1 : 1; + i0 &= 0xfffff; if (j0 < 20) { if (j0 < 0) - result = j0 < -1 ? 0 : ((i0 & 0x80000000) ? -1 : 1); + result = j0 < -1 ? 0 : sign; else { u_int32_t i = 0xfffff >> j0; + i0 |= 0x100000; if (((i0 & i) | i1) == 0) - result = (long int) ((i0 & 0xfffff) | 0x100000) >> j0; + result = i0 >> j0; else - { - /* X is not integral. */ - u_int32_t j = i0 + (0x80000 >> j0); - if (j < i0) - result = (long int) 0x80000 >> (20 - j0); - else - result = (j | 0x100000) >> (20 - j0); - } + /* X is not integral. */ + result = (i0 + (0x80000 >> j0)) >> (20 - j0); } } else if (j0 >= 8 * sizeof (long int) || j0 > 51) { /* The number is too large. It is left implementation defined what happens. */ - result = (long int) x; + return (long int) x; } else { @@ -97,7 +97,7 @@ __lround (long double x) } } - return i0 & 0x80000000 ? -result : result; + return sign * result; } #else long int diff --git a/sysdeps/m68k/fpu/e_rem_pio2.c b/sysdeps/m68k/fpu/e_rem_pio2.c new file mode 100644 index 0000000..1347b04 --- /dev/null +++ b/sysdeps/m68k/fpu/e_rem_pio2.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/m68k/fpu/e_rem_pio2f.c b/sysdeps/m68k/fpu/e_rem_pio2f.c new file mode 100644 index 0000000..1347b04 --- /dev/null +++ b/sysdeps/m68k/fpu/e_rem_pio2f.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/m68k/fpu/e_rem_pio2l.c b/sysdeps/m68k/fpu/e_rem_pio2l.c new file mode 100644 index 0000000..1347b04 --- /dev/null +++ b/sysdeps/m68k/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/m68k/fpu/k_rem_pio2.c b/sysdeps/m68k/fpu/k_rem_pio2.c new file mode 100644 index 0000000..1347b04 --- /dev/null +++ b/sysdeps/m68k/fpu/k_rem_pio2.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/m68k/fpu/k_rem_pio2f.c b/sysdeps/m68k/fpu/k_rem_pio2f.c new file mode 100644 index 0000000..1347b04 --- /dev/null +++ b/sysdeps/m68k/fpu/k_rem_pio2f.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/m68k/fpu/k_rem_pio2l.c b/sysdeps/m68k/fpu/k_rem_pio2l.c new file mode 100644 index 0000000..1347b04 --- /dev/null +++ b/sysdeps/m68k/fpu/k_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/mach/bits/libc-lock.h b/sysdeps/mach/bits/libc-lock.h index 79a1e00..17eeefc 100644 --- a/sysdeps/mach/bits/libc-lock.h +++ b/sysdeps/mach/bits/libc-lock.h @@ -75,6 +75,27 @@ typedef cthread_key_t __libc_key_t; (*__save_FCT)(__save_ARG); \ } +/* Use mutexes as once control variables. */ + +struct __libc_once + { + __libc_lock_t lock; + int done; + }; + +#define __libc_once_define(CLASS,NAME) \ + CLASS struct __libc_once NAME = { MUTEX_INITIALZER, 0 } + + +/* Call handler iff the first call. */ +#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ + do { \ + __libc_lock_lock (ONCE_CONTROL.lock); \ + if (!ONCE_CONTROL.done) \ + (INIT_FUNCTION) (); \ + ONCE_CONTROL.done = 1; \ + __libc_lock_lock (ONCE_CONTROL.lock); \ + } while (0) #ifdef _LIBC /* We need portable names for some functions. E.g., when they are diff --git a/sysdeps/mach/hurd/Dist b/sysdeps/mach/hurd/Dist index 62fe4d9..e6067b8 100644 --- a/sysdeps/mach/hurd/Dist +++ b/sysdeps/mach/hurd/Dist @@ -1,3 +1,4 @@ errnos.awk err_hurd.sub libc-ldscript libc_p-ldscript +cthreads.c diff --git a/sysdeps/mach/hurd/Makefile b/sysdeps/mach/hurd/Makefile index 43d5eb9..bf1c3b0 100644 --- a/sysdeps/mach/hurd/Makefile +++ b/sysdeps/mach/hurd/Makefile @@ -18,6 +18,9 @@ ifdef in-Makerules +subdirs := $(filter-out sunrpc,$(subdirs)) # XXX skip broken dirs +# See hurd/Makefile for commands that install some crucial sunrpc headers. + # Look for header files in hurd/ under the top-level library source directory. # Look for generated header files where they get created. includes += -I$(..)hurd -I$(common-objpfx)hurd/ @@ -33,7 +36,6 @@ inhibit-unix-syscalls = yes # be compatible with some existing binaries for that system. inhibit-glue = yes - ifeq (,$(filter mach hurd,$(subdir))) # Subdirectories other than hurd/ might use the generated Hurd headers. # So make sure we get a chance to run in hurd/ to make them before all else. @@ -48,6 +50,12 @@ $(patsubst %,$(hurd-objpfx)hurd/%.%,auth io fs process): $(MAKE) -C $(..)hurd generated no_deps=t endif +# Hurd profil.c includes this file, so give a rule to make it. +ifeq ($(subdir),gmon) +$(common-objpfx)hurd/../mach/RPC_task_get_sampled_pcs.c: + $(MAKE) -C $(..)mach generated no_deps=t +endif + # Generate errnos.h from the section of the manual that lists all the errno # codes. @@ -115,11 +123,6 @@ $(inst_libdir)/libc.so: $(rpcuserlibs) ifeq (elf,$(subdir)) $(objpfx)librtld.so: $(rpcuserlibs:.so=_pic.a) endif - -# We need the CThreads interface. -ifeq (misc,$(subdir)) -sysdep_routines += cthreads -endif endif # in-Makerules diff --git a/sysdeps/mach/hurd/Subdirs b/sysdeps/mach/hurd/Subdirs index 16b8348..739919f 100644 --- a/sysdeps/mach/hurd/Subdirs +++ b/sysdeps/mach/hurd/Subdirs @@ -1 +1,2 @@ hurd +login diff --git a/sysdeps/mach/hurd/profil.c b/sysdeps/mach/hurd/profil.c index d3c5131..d76cc25 100644 --- a/sysdeps/mach/hurd/profil.c +++ b/sysdeps/mach/hurd/profil.c @@ -34,10 +34,20 @@ static size_t maxsamples; static size_t pc_offset; static size_t sample_scale; static sampled_pc_seqno_t seqno; -static struct mutex lock = MUTEX_INITIALIZER; +static spin_lock_t lock = SPIN_LOCK_INITIALIZER; static mach_msg_timeout_t collector_timeout; /* ms between collections. */ static int profile_tick; +/* Reply port used by profiler thread */ +static mach_port_t profil_reply_port; + +/* Forwards */ +static kern_return_t profil_task_get_sampled_pcs (mach_port_t, + sampled_pc_seqno_t *, + sampled_pc_array_t, + mach_msg_type_number_t *); +static void fetch_samples (void); + /* Enable statistical profiling, writing samples of the PC into at most SIZE bytes of SAMPLE_BUFFER; every processor clock tick while profiling is enabled, the system examines the user PC and increments @@ -87,7 +97,7 @@ update_waiter (u_short *sample_buffer, size_t size, size_t offset, u_int scale) } int -__profile_frequency () +__profile_frequency (void) { return profile_tick; } @@ -97,13 +107,20 @@ profil (u_short *sample_buffer, size_t size, size_t offset, u_int scale) { error_t err; - __mutex_lock (&lock); + __spin_lock (&lock); if (scale == 0) { /* Disable profiling. */ int count; - __thread_suspend (profile_thread); + + if (profile_thread != MACH_PORT_NULL) + __thread_suspend (profile_thread); + + /* Fetch the last set of samples */ + if (sample_scale) + fetch_samples (); + err = __task_disable_pc_sampling (__mach_task_self (), &count); sample_scale = 0; seqno = 0; @@ -111,57 +128,102 @@ profil (u_short *sample_buffer, size_t size, size_t offset, u_int scale) else err = update_waiter (sample_buffer, size, offset, scale); - __mutex_unlock (&lock); + __spin_unlock (&lock); return err ? __hurd_fail (err) : 0; } +/* Fetch PC samples. This function must be very careful not to depend + on Hurd threadvar variables. We arrange that by using a special + stub arranged for at the end of this file. */ static void -profile_waiter (void) +fetch_samples (void) { sampled_pc_t pc_samples[MAX_PC_SAMPLES]; mach_msg_type_number_t nsamples, i; - mach_port_t rcv = __mach_reply_port (); - mach_msg_header_t msg; error_t err; - while (1) + nsamples = MAX_PC_SAMPLES; + + err = profil_task_get_sampled_pcs (__mach_task_self (), &seqno, + pc_samples, &nsamples); + if (err) { - __mutex_lock (&lock); + static error_t special_profil_failure; + static volatile int a, b, c; - nsamples = sizeof pc_samples / sizeof pc_samples[0]; - err = __task_get_sampled_pcs (__mach_task_self (), &seqno, - pc_samples, &nsamples); - assert_perror (err); + special_profil_failure = err; + a = 1; + b = 0; + while (1) + c = a / b; + } - for (i = 0; i < nsamples; ++i) - { - size_t idx = (((pc_samples[i].pc - pc_offset) / 2) * - sample_scale / 65536); - if (idx < maxsamples) - ++samples[idx]; - } + for (i = 0; i < nsamples; ++i) + { + /* Do arithmetic in long long to avoid overflow problems. */ + long long pc_difference = pc_samples[i].pc - pc_offset; + size_t idx = ((pc_difference / 2) * sample_scale) / 65536; + if (idx < maxsamples) + ++samples[idx]; + } +} + + +/* This function must be very careful not to depend on Hurd threadvar + variables. We arrange that by using special stubs arranged for at the + end of this file. */ +static void +profile_waiter (void) +{ + mach_msg_header_t msg; + mach_port_t timeout_reply_port; + + profil_reply_port = __mach_reply_port (); + timeout_reply_port = __mach_reply_port (); - __vm_deallocate (__mach_task_self (), - (vm_address_t) pc_samples, - nsamples * sizeof *pc_samples); + while (1) + { + __spin_lock (&lock); + + fetch_samples (); - __mutex_unlock (&lock); + __spin_unlock (&lock); __mach_msg (&msg, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, sizeof msg, - rcv, collector_timeout, MACH_PORT_NULL); + timeout_reply_port, collector_timeout, MACH_PORT_NULL); } } -data_set_element (_hurd_fork_locks, lock); +/* Fork interaction */ + +/* Before fork, lock the interlock so that we are in a clean state. */ +static void +fork_profil_prepare (void) +{ + __spin_lock (&lock); +} +text_set_element (_hurd_fork_prepare_hook, fork_profil_prepare); + +/* In the parent, unlock the interlock once fork is complete. */ +static void +fork_profil_parent (void) +{ + __spin_unlock (&lock); +} +text_set_element (_hurd_fork_parent_hook, fork_profil_parent); +/* In the childs, unlock the interlock, and start a profiling thread up + if necessary. */ static void -fork_profil (void) +fork_profil_child (void) { u_short *sb; size_t n, o, ss; error_t err; + __spin_unlock (&lock); + if (profile_thread != MACH_PORT_NULL) { __mach_port_deallocate (__mach_task_self (), profile_thread); @@ -183,4 +245,37 @@ fork_profil (void) assert_perror (err); } } -text_set_element (_hurd_fork_child_hook, fork_profil); +text_set_element (_hurd_fork_child_hook, fork_profil_child); + + + + +/* Special RPC stubs for profile_waiter are made by including the normal + source code, with special CPP state to prevent it from doing the + usual thing. */ + +/* Include these first; then our #define's will take full effect, not + being overridden. */ +#include <mach/mig_support.h> + +/* This need not do anything; it is always associated with errors, which + are fatal in profile_waiter anyhow. */ +#define __mig_put_reply_port(foo) + +/* Use our static variable instead of the usual threadvar mechanism for + this. */ +#define __mig_get_reply_port() profil_reply_port + +/* Make the functions show up as static */ +#define mig_external static + +/* Turn off the attempt to generate ld aliasing records. */ +#undef weak_alias +#define weak_alias(a,b) + +/* And change their names to avoid confusing disasters. */ +#define __vm_deallocate_rpc profil_vm_deallocate +#define __task_get_sampled_pcs profil_task_get_sampled_pcs + +/* And include the source code */ +#include <../mach/RPC_task_get_sampled_pcs.c> diff --git a/sysdeps/mips/Dist b/sysdeps/mips/Dist index ad6ea03..9b6fd71 100644 --- a/sysdeps/mips/Dist +++ b/sysdeps/mips/Dist @@ -1 +1,3 @@ setjmp_aux.c +rtld-ldscript.in +rtld-parms diff --git a/sysdeps/mips/mips64/Dist b/sysdeps/mips/mips64/Dist index ad6ea03..4cde3d0 100644 --- a/sysdeps/mips/mips64/Dist +++ b/sysdeps/mips/mips64/Dist @@ -1 +1,2 @@ setjmp_aux.c +rtld-parms diff --git a/sysdeps/mips/mipsel/Dist b/sysdeps/mips/mipsel/Dist new file mode 100644 index 0000000..98a10ec --- /dev/null +++ b/sysdeps/mips/mipsel/Dist @@ -0,0 +1 @@ +rtld-parms diff --git a/sysdeps/posix/defs.c b/sysdeps/posix/defs.c index 4a12292..bc0d34b 100644 --- a/sysdeps/posix/defs.c +++ b/sysdeps/posix/defs.c @@ -32,7 +32,7 @@ { \ _IOMAGIC, \ NULL, NULL, NULL, NULL, 0, \ - (PTR) fd, \ + (void *) fd, \ { readwrite, /* ... */ }, \ { NULL, NULL, NULL, NULL, NULL }, \ { NULL, NULL }, \ diff --git a/sysdeps/powerpc/Dist b/sysdeps/powerpc/Dist index ae16c0f..282cf13 100644 --- a/sysdeps/powerpc/Dist +++ b/sysdeps/powerpc/Dist @@ -1,2 +1,3 @@ fenv_const.c fenv_libc.h +quad_float.h diff --git a/sysdeps/powerpc/Makefile b/sysdeps/powerpc/Makefile index 4100901..0a50956 100644 --- a/sysdeps/powerpc/Makefile +++ b/sysdeps/powerpc/Makefile @@ -1,3 +1,13 @@ ifeq ($(subdir),math) -libm-support += fenv_const +libm-support += fenv_const fe_nomask t_sqrt + +# These routines have not been tested, so it's probable they don't work; +# and they don't provide the complete list of FP routines. So there's +# no point in compiling them. +#sysdep_routines += q_feq q_fne q_utoq q_dtoq q_itoq q_stoq q_neg q_ulltoq \ +# q_lltoq q_qtou q_qtoi q_qtoull q_qtoll q_qtos + +tests += test-arith test-arithf +LDLIBS-test-arith = libm +LDLIBS-test-arithf = libm endif diff --git a/sysdeps/powerpc/bits/fenv.h b/sysdeps/powerpc/bits/fenv.h index 08d998e..8c26a25 100644 --- a/sysdeps/powerpc/bits/fenv.h +++ b/sysdeps/powerpc/bits/fenv.h @@ -37,9 +37,10 @@ enum /* ... except for FE_INVALID, for which we use bit 31. FE_INVALID actually corresponds to bits 7 through 12 and 21 through 23 in the FPSCR, but we can't use that because the current draft - says that it must be a power of 2. Instead we use bit 24 which - is the enable bit for all the FE_INVALID exceptions. */ - FE_INVALID = 1 << 31-24, + says that it must be a power of 2. Instead we use bit 2 which + is the summary bit for all the FE_INVALID exceptions, which + kind of makes sense. */ + FE_INVALID = 1 << 31-2, #define FE_INVALID FE_INVALID #ifdef __USE_GNU @@ -69,19 +70,22 @@ enum FE_INVALID_IMZ = 1 << 31-11, #define FE_INVALID_IMZ FE_INVALID_IMZ - /* Comparison with NaN or SNaN. */ + /* Comparison with NaN or SNaN. */ FE_INVALID_COMPARE = 1 << 31-12, #define FE_INVALID_COMPARE FE_INVALID_COMPARE - /* Invalid operation flag for software (not set by hardware). */ + /* Invalid operation flag for software (not set by hardware). */ + /* Note that some chips don't have this implemented, presumably + because no-one expected anyone to write software for them %-). */ FE_INVALID_SOFTWARE = 1 << 31-21, #define FE_INVALID_SOFTWARE FE_INVALID_SOFTWARE - /* Square root of negative number (including -Inf). */ + /* Square root of negative number (including -Inf). */ + /* Note that some chips don't have this implemented. */ FE_INVALID_SQRT = 1 << 31-22, #define FE_INVALID_SQRT FE_INVALID_SQRT - /* Conversion-to-integer of a NaN or a number too large or too small. */ + /* Conversion-to-integer of a NaN or a number too large or too small. */ FE_INVALID_INTEGER_CONVERSION = 1 << 31-23, #define FE_INVALID_INTEGER_CONVERSION FE_INVALID_INTEGER_CONVERSION @@ -122,7 +126,53 @@ extern const fenv_t __fe_dfl_env; #define FE_DFL_ENV (&__fe_dfl_env) #ifdef __USE_GNU -/* Floating-point environment where none of the exceptions are masked. */ -extern const fenv_t __fe_nomask_env; -# define FE_NOMASK_ENV (&__fe_nomask_env) +/* Floating-point environment where all exceptions are enabled. Note that + this is not sufficient to give you SIGFPE. */ +extern const fenv_t __fe_enabled_env; +# define FE_ENABLED_ENV (&__fe_enabled_env) + +/* Floating-point environment with (processor-dependent) non-IEEE floating + point. */ +extern const fenv_t __fe_nonieee_env; +# define FE_NONIEEE_ENV (&__fe_nonieee_env) + +/* Floating-point environment with all exceptions enabled. Note that + just evaluating this value will set the processor into 'FPU + exceptions imprecise recoverable' mode, which may cause a significant + performance penalty (but have no other visible effect). */ +extern const fenv_t *__fe_nomask_env __P ((void)); +# define FE_NOMASK_ENV (__fe_nomask_env ()) #endif + +#ifdef __OPTIMIZE__ +/* Inline definition for fegetround. */ +# define fegetround() \ + (__extension__ ({ int __fegetround_result; \ + __asm__ ("mcrfs 7,7 ; mfcr %0" \ + : "=r"(__fegetround_result) : : "cr7"); \ + __fegetround_result & 3; })) + +/* Inline definition for feraiseexcept. */ +# define feraiseexcept(__excepts) \ + (__extension__ ({ if (__builtin_constant_p (__excepts) \ + && ((__excepts) & -(__excepts)) == 0 \ + && (__excepts) != FE_INVALID) { \ + if ((__excepts) != 0) \ + __asm__ __volatile__ \ + ("mtfsb1 %0" \ + : : "i"(32 - __builtin_ffs (__excepts))); \ + } else \ + (feraiseexcept) (__excepts); })) + +/* Inline definition for feclearexcept. */ +# define feclearexcept(__excepts) \ + (__extension__ ({ if (__builtin_constant_p (__excepts) \ + && ((__excepts) & -(__excepts)) == 0 \ + && (__excepts) != FE_INVALID) { \ + if ((__excepts) != 0) \ + __asm__ __volatile__ \ + ("mtfsb0 %0" \ + : : "i"(32 - __builtin_ffs (__excepts))); \ + } else \ + (feclearexcept) (__excepts); })) +#endif /* __OPTIMIZE__ */ diff --git a/sysdeps/powerpc/bits/mathdef.h b/sysdeps/powerpc/bits/mathdef.h index c0e6caa..9f91863 100644 --- a/sysdeps/powerpc/bits/mathdef.h +++ b/sysdeps/powerpc/bits/mathdef.h @@ -30,7 +30,7 @@ #ifdef __GNUC__ #if __STDC__ == 1 -/* In GNU or ANSI mode, gcc leaves `float' expressions as-is, I think. */ +/* In GNU or ANSI mode, gcc leaves `float' expressions as-is. */ typedef float float_t; /* `float' expressions are evaluated as `float'. */ typedef double double_t; /* `double' expressions are evaluated as @@ -70,3 +70,7 @@ typedef double double_t; #define INFINITY HUGE_VAL #endif + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +#define FP_ILOGB0 0x80000001 +#define FP_ILOGBNAN 0x7fffffff diff --git a/sysdeps/powerpc/dl-machine.h b/sysdeps/powerpc/dl-machine.h index c9d1d73..74436d1 100644 --- a/sysdeps/powerpc/dl-machine.h +++ b/sysdeps/powerpc/dl-machine.h @@ -57,10 +57,11 @@ #define OPCODE_LI(rd,simm) OPCODE_ADDI(rd,0,simm) #define OPCODE_SLWI(ra,rs,sh) OPCODE_RLWINM(ra,rs,sh,0,31-sh) -#define PPC_DCBST(where) asm __volatile__ ("dcbst 0,%0" : : "r"(where)) -#define PPC_SYNC asm __volatile__ ("sync") -#define PPC_ISYNC asm __volatile__ ("sync; isync") -#define PPC_ICBI(where) asm __volatile__ ("icbi 0,%0" : : "r"(where)) +#define PPC_DCBST(where) asm volatile ("dcbst 0,%0" : : "r"(where)) +#define PPC_SYNC asm volatile ("sync") +#define PPC_ISYNC asm volatile ("sync; isync") +#define PPC_ICBI(where) asm volatile ("icbi 0,%0" : : "r"(where)) +#define PPC_DIE asm volatile ("tweq 0,0") /* Use this when you've modified some code, but it won't be in the instruction fetch queue (or when it doesn't matter if it is). */ @@ -147,9 +148,9 @@ elf_machine_load_address (void) /* The PLT uses Elf32_Rela relocs. */ #define elf_machine_relplt elf_machine_rela - /* This code is used in dl-runtime.c to call the `fixup' function - and then redirect to the address it returns. It is called - from code built in the PLT by elf_machine_runtime_setup. */ +/* This code is used in dl-runtime.c to call the `fixup' function + and then redirect to the address it returns. It is called + from code built in the PLT by elf_machine_runtime_setup. */ #define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\ .section \".text\" .align 2 @@ -511,11 +512,14 @@ elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc) static inline void elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, const Elf32_Sym *sym, const struct r_found_version *version, - Elf32_addr *const reloc_addr) + Elf32_Addr *const reloc_addr) { +#ifndef RTLD_BOOTSTRAP const Elf32_Sym *const refsym = sym; +#endif Elf32_Word loadbase, finaladdr; const int rinfo = ELF32_R_TYPE (reloc->r_info); + extern char **_dl_argv; if (rinfo == R_PPC_NONE) return; @@ -598,7 +602,6 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, if (sym->st_size > refsym->st_size || (_dl_verbose && sym->st_size < refsym->st_size)) { - extern char **_dl_argv; const char *strtab; strtab = ((void *) map->l_addr @@ -631,11 +634,31 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, plt = (Elf32_Word *)((char *)map->l_addr + map->l_info[DT_PLTGOT]->d_un.d_val); index = (reloc_addr - plt - PLT_INITIAL_ENTRY_WORDS)/2; - if (index >= PLT_DOUBLE_SIZE) { /* Slots greater than or equal to 2^13 have 4 words available instead of two. */ + /* FIXME: There are some possible race conditions in this code, + when called from 'fixup'. + + 1) Suppose that a lazy PLT entry is executing, a + context switch between threads (or a signal) occurs, + and the new thread or signal handler calls the same + lazy PLT entry. Then the PLT entry would be changed + while it's being run, which will cause a segfault + (almost always). + + 2) Suppose the reverse: that a lazy PLT entry is + being updated, a context switch occurs, and the new + code calls the lazy PLT entry that is being updated. + Then the half-fixed PLT entry will be executed, which + will also almost always cause a segfault. + + These problems don't happen with the 2-word entries, because + only one of the two instructions are changed when a lazy + entry is retargeted at the actual PLT entry; the li + instruction stays the same (we have to update it anyway, + because we might not be updating a lazy PLT entry). */ reloc_addr[0] = OPCODE_LI (11, finaladdr); reloc_addr[1] = OPCODE_ADDIS (11, 11, finaladdr + 0x8000 >> 16); reloc_addr[2] = OPCODE_MTCTR (11); @@ -648,19 +671,27 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val / sizeof(Elf32_Rela)); + plt[index+PLT_DATA_START_WORDS (num_plt_entries)] = finaladdr; reloc_addr[0] = OPCODE_LI (11, index*4); reloc_addr[1] = OPCODE_B (-(4*(index*2 + 1 - PLT_LONGBRANCH_ENTRY_WORDS + PLT_INITIAL_ENTRY_WORDS))); - plt[index+PLT_DATA_START_WORDS (num_plt_entries)] = finaladdr; } } MODIFIED_CODE (reloc_addr); } else - assert (! "unexpected dynamic reloc type"); + { +#ifdef RTLD_BOOTSTRAP + PPC_DIE; /* There is no point calling _dl_sysdep_error, it + almost certainly hasn't been relocated properly. */ +#else + _dl_sysdep_error (_dl_argv[0] ?: "<program name unknown>", + ": Unknown relocation type\n", NULL); +#endif + } if (rinfo == R_PPC_ADDR16_LO || rinfo == R_PPC_ADDR16_HI || diff --git a/sysdeps/powerpc/e_sqrt.c b/sysdeps/powerpc/e_sqrt.c new file mode 100644 index 0000000..df80973 --- /dev/null +++ b/sysdeps/powerpc/e_sqrt.c @@ -0,0 +1,141 @@ +/* Single-precision floating point square root. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <math.h> +#include <math_private.h> +#include <fenv_libc.h> +#include <inttypes.h> + +static const double almost_half = 0.5000000000000001; /* 0.5 + 2^-53 */ +static const uint32_t a_nan = 0x7fc00000; +static const uint32_t a_inf = 0x7f800000; +static const float two108 = 3.245185536584267269e+32; +static const float twom54 = 5.551115123125782702e-17; +extern const float __t_sqrt[1024]; + +/* The method is based on a description in + Computation of elementary functions on the IBM RISC System/6000 processor, + P. W. Markstein, IBM J. Res. Develop, 34(1) 1990. + Basically, it consists of two interleaved Newton-Rhapson approximations, + one to find the actual square root, and one to find its reciprocal + without the expense of a division operation. The tricky bit here + is the use of the POWER/PowerPC multiply-add operation to get the + required accuracy with high speed. + + The argument reduction works by a combination of table lookup to + obtain the initial guesses, and some careful modification of the + generated guesses (which mostly runs on the integer unit, while the + Newton-Rhapson is running on the FPU). */ +double +__sqrt(double x) +{ + const float inf = *(const float *)&a_inf; + /* x = f_wash(x); *//* This ensures only one exception for SNaN. */ + if (x > 0) + { + if (x != inf) + { + /* Variables named starting with 's' exist in the + argument-reduced space, so that 2 > sx >= 0.5, + 1.41... > sg >= 0.70.., 0.70.. >= sy > 0.35... . + Variables named ending with 'i' are integer versions of + floating-point values. */ + double sx; /* The value of which we're trying to find the + square root. */ + double sg,g; /* Guess of the square root of x. */ + double sd,d; /* Difference between the square of the guess and x. */ + double sy; /* Estimate of 1/2g (overestimated by 1ulp). */ + double sy2; /* 2*sy */ + double e; /* Difference between y*g and 1/2 (se = e * fsy). */ + double shx; /* == sx * fsg */ + double fsg; /* sg*fsg == g. */ + fenv_t fe; /* Saved floating-point environment (stores rounding + mode and whether the inexact exception is + enabled). */ + uint32_t xi0, xi1, sxi, fsgi; + const float *t_sqrt; + + fe = fegetenv_register(); + EXTRACT_WORDS (xi0,xi1,x); + relax_fenv_state(); + sxi = xi0 & 0x3fffffff | 0x3fe00000; + INSERT_WORDS (sx, sxi, xi1); + t_sqrt = __t_sqrt + (xi0 >> 52-32-8-1 & 0x3fe); + sg = t_sqrt[0]; + sy = t_sqrt[1]; + + /* Here we have three Newton-Rhapson iterations each of a + division and a square root and the remainder of the + argument reduction, all interleaved. */ + sd = -(sg*sg - sx); + fsgi = xi0 + 0x40000000 >> 1 & 0x7ff00000; + sy2 = sy + sy; + sg = sy*sd + sg; /* 16-bit approximation to sqrt(sx). */ + INSERT_WORDS (fsg, fsgi, 0); + e = -(sy*sg - almost_half); + sd = -(sg*sg - sx); + if ((xi0 & 0x7ff00000) == 0) + goto denorm; + sy = sy + e*sy2; + sg = sg + sy*sd; /* 32-bit approximation to sqrt(sx). */ + sy2 = sy + sy; + e = -(sy*sg - almost_half); + sd = -(sg*sg - sx); + sy = sy + e*sy2; + shx = sx * fsg; + sg = sg + sy*sd; /* 64-bit approximation to sqrt(sx), + but perhaps rounded incorrectly. */ + sy2 = sy + sy; + g = sg * fsg; + e = -(sy*sg - almost_half); + d = -(g*sg - shx); + sy = sy + e*sy2; + fesetenv_register (fe); + return g + sy*d; + denorm: + /* For denormalised numbers, we normalise, calculate the + square root, and return an adjusted result. */ + fesetenv_register (fe); + return __sqrt(x * two108) * twom54; + } + } + else if (x < 0) + { +#ifdef FE_INVALID_SQRT + feraiseexcept (FE_INVALID_SQRT); + /* For some reason, some PowerPC processors don't implement + FE_INVALID_SQRT. I guess no-one ever thought they'd be + used for square roots... :-) */ + if (!fetestexcept (FE_INVALID)) +#endif + feraiseexcept (FE_INVALID); +#ifndef _IEEE_LIBM + if (_LIB_VERSION != _IEEE_) + x = __kernel_standard(x,x,26); + else +#endif + x = *(const float*)&a_nan; + } + return f_wash(x); +} + +weak_alias (__sqrt, sqrt) +/* Strictly, this is wrong, but the only places where _ieee754_sqrt is + used will not pass in a negative result. */ +strong_alias(__sqrt,__ieee754_sqrt) diff --git a/sysdeps/powerpc/e_sqrtf.c b/sysdeps/powerpc/e_sqrtf.c new file mode 100644 index 0000000..804dff3 --- /dev/null +++ b/sysdeps/powerpc/e_sqrtf.c @@ -0,0 +1,136 @@ +/* Single-precision floating point square root. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <math.h> +#include <math_private.h> +#include <fenv_libc.h> +#include <inttypes.h> + +static const float almost_half = 0.50000006; /* 0.5 + 2^-24 */ +static const uint32_t a_nan = 0x7fc00000; +static const uint32_t a_inf = 0x7f800000; +static const float two48 = 281474976710656.0; +static const float twom24 = 5.9604644775390625e-8; +extern const float __t_sqrt[1024]; + +/* The method is based on a description in + Computation of elementary functions on the IBM RISC System/6000 processor, + P. W. Markstein, IBM J. Res. Develop, 34(1) 1990. + Basically, it consists of two interleaved Newton-Rhapson approximations, + one to find the actual square root, and one to find its reciprocal + without the expense of a division operation. The tricky bit here + is the use of the POWER/PowerPC multiply-add operation to get the + required accuracy with high speed. + + The argument reduction works by a combination of table lookup to + obtain the initial guesses, and some careful modification of the + generated guesses (which mostly runs on the integer unit, while the + Newton-Rhapson is running on the FPU). */ +float +__sqrtf(float x) +{ + const float inf = *(const float *)&a_inf; + /* x = f_washf(x); *//* This ensures only one exception for SNaN. */ + if (x > 0) + { + if (x != inf) + { + /* Variables named starting with 's' exist in the + argument-reduced space, so that 2 > sx >= 0.5, + 1.41... > sg >= 0.70.., 0.70.. >= sy > 0.35... . + Variables named ending with 'i' are integer versions of + floating-point values. */ + float sx; /* The value of which we're trying to find the square + root. */ + float sg,g; /* Guess of the square root of x. */ + float sd,d; /* Difference between the square of the guess and x. */ + float sy; /* Estimate of 1/2g (overestimated by 1ulp). */ + float sy2; /* 2*sy */ + float e; /* Difference between y*g and 1/2 (note that e==se). */ + float shx; /* == sx * fsg */ + float fsg; /* sg*fsg == g. */ + fenv_t fe; /* Saved floating-point environment (stores rounding + mode and whether the inexact exception is + enabled). */ + uint32_t xi, sxi, fsgi; + const float *t_sqrt; + + GET_FLOAT_WORD (xi, x); + fe = fegetenv_register (); + relax_fenv_state (); + sxi = xi & 0x3fffffff | 0x3f000000; + SET_FLOAT_WORD (sx, sxi); + t_sqrt = __t_sqrt + (xi >> 23-8-1 & 0x3fe); + sg = t_sqrt[0]; + sy = t_sqrt[1]; + + /* Here we have three Newton-Rhapson iterations each of a + division and a square root and the remainder of the + argument reduction, all interleaved. */ + sd = -(sg*sg - sx); + fsgi = xi + 0x40000000 >> 1 & 0x7f800000; + sy2 = sy + sy; + sg = sy*sd + sg; /* 16-bit approximation to sqrt(sx). */ + e = -(sy*sg - almost_half); + SET_FLOAT_WORD (fsg, fsgi); + sd = -(sg*sg - sx); + sy = sy + e*sy2; + if ((xi & 0x7f800000) == 0) + goto denorm; + shx = sx * fsg; + sg = sg + sy*sd; /* 32-bit approximation to sqrt(sx), + but perhaps rounded incorrectly. */ + sy2 = sy + sy; + g = sg * fsg; + e = -(sy*sg - almost_half); + d = -(g*sg - shx); + sy = sy + e*sy2; + fesetenv_register (fe); + return g + sy*d; + denorm: + /* For denormalised numbers, we normalise, calculate the + square root, and return an adjusted result. */ + fesetenv_register (fe); + return __sqrtf(x * two48) * twom24; + } + } + else if (x < 0) + { +#ifdef FE_INVALID_SQRT + feraiseexcept (FE_INVALID_SQRT); + /* For some reason, some PowerPC processors don't implement + FE_INVALID_SQRT. I guess no-one ever thought they'd be + used for square roots... :-) */ + if (!fetestexcept (FE_INVALID)) +#endif + feraiseexcept (FE_INVALID); +#ifndef _IEEE_LIBM + if (_LIB_VERSION != _IEEE_) + x = __kernel_standard(x,x,126); + else +#endif + x = *(const float*)&a_nan; + } + return f_washf(x); +} + +weak_alias (__sqrtf, sqrtf) +/* Strictly, this is wrong, but the only places where _ieee754_sqrt is + used will not pass in a negative result. */ +strong_alias(__sqrtf,__ieee754_sqrtf) diff --git a/sysdeps/powerpc/fclrexcpt.c b/sysdeps/powerpc/fclrexcpt.c index 1e66140..cfcf175 100644 --- a/sysdeps/powerpc/fclrexcpt.c +++ b/sysdeps/powerpc/fclrexcpt.c @@ -19,6 +19,7 @@ #include <fenv_libc.h> +#undef feclearexcept void feclearexcept (int excepts) { @@ -28,7 +29,8 @@ feclearexcept (int excepts) u.fenv = fegetenv_register (); /* Clear the relevant bits. */ - u.l[1] = u.l[1] & ~FE_to_sticky (excepts); + u.l[1] = u.l[1] & ~(-((excepts) >> 31-FPSCR_VX & 1) & FE_ALL_INVALID + | (excepts) & FPSCR_STICKY_BITS); /* Put the new state in effect. */ fesetenv_register (u.fenv); diff --git a/sysdeps/powerpc/fe_nomask.c b/sysdeps/powerpc/fe_nomask.c new file mode 100644 index 0000000..bca4905 --- /dev/null +++ b/sysdeps/powerpc/fe_nomask.c @@ -0,0 +1,32 @@ +/* Procedure definition for FE_NOMASK_ENV. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <fenv.h> +#include <errno.h> + +/* This is presently a stub, until it's decided how the kernels should + support this. */ + +const fenv_t * +__fe_nomask_env(void) +{ + __set_errno (ENOSYS); + return FE_ENABLED_ENV; +} +stub_warning (__fe_nomask_env) diff --git a/sysdeps/powerpc/fegetround.c b/sysdeps/powerpc/fegetround.c index 05395f0..3bb9fb4 100644 --- a/sysdeps/powerpc/fegetround.c +++ b/sysdeps/powerpc/fegetround.c @@ -19,13 +19,11 @@ #include <fenv_libc.h> +#undef fegetround int fegetround (void) { - fenv_union_t u; - - u.fenv = fegetenv_register (); - - /* The rounding mode is bits 30 and 31 of the FPSCR. */ - return u.l[1] & 3; + int result; + asm ("mcrfs 7,7 ; mfcr %0" : "=r"(result) : : "cr7"); \ + return result & 3; } diff --git a/sysdeps/powerpc/fenv_const.c b/sysdeps/powerpc/fenv_const.c index fa35fbc..506bd43 100644 --- a/sysdeps/powerpc/fenv_const.c +++ b/sysdeps/powerpc/fenv_const.c @@ -25,5 +25,9 @@ const unsigned long long __fe_dfl_env __attribute__ ((aligned (8))) = 0xfff8000000000000ULL; /* Floating-point environment where none of the exceptions are masked. */ -const unsigned long long __fe_nomask_env __attribute__ ((aligned (8))) = +const unsigned long long __fe_enabled_env __attribute__ ((aligned (8))) = 0xfff80000000000f8ULL; + +/* Floating-point environment with the NI bit set. */ +const unsigned long long __fe_nonieee_env __attribute__ ((aligned (8))) = +0xfff8000000000004ULL; diff --git a/sysdeps/powerpc/fenv_libc.h b/sysdeps/powerpc/fenv_libc.h index 45d61e1..343be16 100644 --- a/sysdeps/powerpc/fenv_libc.h +++ b/sysdeps/powerpc/fenv_libc.h @@ -22,23 +22,17 @@ #include <fenv.h> -/* Transform a logical or of the FE_* bits to a bit pattern for the - appropriate sticky bits in the FPSCR. */ -#define FE_to_sticky(excepts) \ - (-(excepts & FE_INVALID) & FE_ALL_INVALID \ - | (excepts) & (FE_ALL_EXCEPT & ~FE_INVALID | FE_ALL_INVALID)) - /* The sticky bits in the FPSCR indicating exceptions have occurred. */ #define FPSCR_STICKY_BITS ((FE_ALL_EXCEPT | FE_ALL_INVALID) & ~FE_INVALID) /* Equivalent to fegetenv, but returns a fenv_t instead of taking a pointer. */ #define fegetenv_register() \ - ({ fenv_t env; asm ("mffs %0" : "=f" (env)); env; }) + ({ fenv_t env; asm volatile ("mffs %0" : "=f" (env)); env; }) /* Equivalent to fesetenv, but takes a fenv_t instead of a pointer. */ #define fesetenv_register(env) \ - ({ double d = (env); asm ("mtfsf 0xff,%0" : : "f" (d)); }) + ({ double d = (env); asm volatile ("mtfsf 0xff,%0" : : "f" (d)); }) /* This very handy macro: - Sets the rounding mode to 'round to nearest'; @@ -48,10 +42,65 @@ functions. */ #define relax_fenv_state() asm ("mtfsfi 7,0") +/* Set/clear a particular FPSCR bit (for instance, + reset_fpscr_bit(FPSCR_VE); + prevents INVALID exceptions from being raised). */ +#define set_fpscr_bit(x) asm volatile ("mtfsb1 %0" : : "i"(x)) +#define reset_fpscr_bit(x) asm volatile ("mtfsb0 %0" : : "i"(x)) + typedef union { fenv_t fenv; unsigned int l[2]; } fenv_union_t; +/* Definitions of all the FPSCR bit numbers */ +enum { + FPSCR_FX = 0, /* exception summary */ + FPSCR_FEX, /* enabled exception summary */ + FPSCR_VX, /* invalid operation summary */ + FPSCR_OX, /* overflow */ + FPSCR_UX, /* underflow */ + FPSCR_ZX, /* zero divide */ + FPSCR_XX, /* inexact */ + FPSCR_VXSNAN, /* invalid operation for SNaN */ + FPSCR_VXISI, /* invalid operation for Inf-Inf */ + FPSCR_VXIDI, /* invalid operation for Inf/Inf */ + FPSCR_VXZDZ, /* invalid operation for 0/0 */ + FPSCR_VXIMZ, /* invalid operation for Inf*0 */ + FPSCR_VXVC, /* invalid operation for invalid compare */ + FPSCR_FR, /* fraction rounded [fraction was incremented by round] */ + FPSCR_FI, /* fraction inexact */ + FPSCR_FPRF_C, /* result class descriptor */ + FPSCR_FPRF_FL, /* result less than (usually, less than 0) */ + FPSCR_FPRF_FG, /* result greater than */ + FPSCR_FPRF_FE, /* result equal to */ + FPSCR_FPRF_FU, /* result unordered */ + FPSCR_20, /* reserved */ + FPSCR_VXSOFT, /* invalid operation set by software */ + FPSCR_VXSQRT, /* invalid operation for square root */ + FPSCR_VXCVI, /* invalid operation for invalid integer convert */ + FPSCR_VE, /* invalid operation exception enable */ + FPSCR_OE, /* overflow exception enable */ + FPSCR_UE, /* underflow exception enable */ + FPSCR_ZE, /* zero divide exception enable */ + FPSCR_XE, /* inexact exception enable */ + FPSCR_NI /* non-IEEE mode (typically, no denormalised numbers) */ + /* the remaining two least-significant bits keep the rounding mode */ +}; + +/* This operation (i) sets the appropriate FPSCR bits for its + parameter, (ii) converts SNaN to the corresponding NaN, and (iii) + otherwise passes its parameter through unchanged (in particular, -0 + and +0 stay as they were). The `obvious' way to do this is optimised + out by gcc. */ +#define f_wash(x) \ + ({ double d; asm volatile ("fmul %0,%1,%2" \ + : "=f"(d) \ + : "f" (x), "f"((float)1.0)); d; }) +#define f_washf(x) \ + ({ float f; asm volatile ("fmuls %0,%1,%2" \ + : "=f"(f) \ + : "f" (x), "f"((float)1.0)); f; }) + #endif /* fenv_libc.h */ diff --git a/sysdeps/powerpc/fgetexcptflg.c b/sysdeps/powerpc/fgetexcptflg.c index d6bd58d..adbdfe2 100644 --- a/sysdeps/powerpc/fgetexcptflg.c +++ b/sysdeps/powerpc/fgetexcptflg.c @@ -23,11 +23,10 @@ void fegetexceptflag (fexcept_t *flagp, int excepts) { fenv_union_t u; - unsigned int flag; /* Get the current state. */ u.fenv = fegetenv_register (); - /* Return that portion that corresponds to the requested exceptions. */ - *flagp = flag = u.l[1] & FPSCR_STICKY_BITS & FE_to_sticky (excepts); + /* Return (all of) it. */ + *flagp = u.l[1]; } diff --git a/sysdeps/powerpc/fpu_control.h b/sysdeps/powerpc/fpu_control.h index d21987f..c4c4786 100644 --- a/sysdeps/powerpc/fpu_control.h +++ b/sysdeps/powerpc/fpu_control.h @@ -52,6 +52,7 @@ typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__))); #define _FPU_GETCW(cw) ( { \ fpu_control_t tmp[2] __attribute__ ((__aligned__(8))); \ __asm__ ("mffs 0; stfd 0,%0" : "=m" (*tmp) : : "fr0"); \ + (cw)=tmp[1]; \ tmp[1]; } ) #define _FPU_SETCW(cw) { \ fpu_control_t tmp[2] __attribute__ ((__aligned__(8))); \ diff --git a/sysdeps/powerpc/fraiseexcpt.c b/sysdeps/powerpc/fraiseexcpt.c index 4305c3d..d0c7971 100644 --- a/sysdeps/powerpc/fraiseexcpt.c +++ b/sysdeps/powerpc/fraiseexcpt.c @@ -19,6 +19,7 @@ #include <fenv_libc.h> +#undef feraiseexcept void feraiseexcept (int excepts) { @@ -36,9 +37,17 @@ feraiseexcept (int excepts) u.l[1] = (u.l[1] | excepts & FPSCR_STICKY_BITS /* Turn FE_INVALID into FE_INVALID_SOFTWARE. */ - | excepts << (31 - 21) - (31 - 24) & FE_INVALID_SOFTWARE); + | (excepts >> (31 - FPSCR_VX) - (31 - FPSCR_VXSOFT) + & FE_INVALID_SOFTWARE)); /* Store the new status word (along with the rest of the environment), triggering any appropriate exceptions. */ fesetenv_register (u.fenv); + + if ((excepts & FE_INVALID) + /* For some reason, some PowerPC chips (the 601, in particular) + don't have FE_INVALID_SOFTWARE implemented. Detect this + case and raise FE_INVALID_SNAN instead. */ + && !fetestexcept (FE_INVALID)) + set_fpscr_bit (FPSCR_VXSNAN); } diff --git a/sysdeps/powerpc/fsetexcptflg.c b/sysdeps/powerpc/fsetexcptflg.c index 4279b74..b762552 100644 --- a/sysdeps/powerpc/fsetexcptflg.c +++ b/sysdeps/powerpc/fsetexcptflg.c @@ -23,15 +23,26 @@ void fesetexceptflag (const fexcept_t *flagp, int excepts) { fenv_union_t u; + fexcept_t flag; /* Get the current state. */ u.fenv = fegetenv_register (); + /* Ignore exceptions not listed in 'excepts'. */ + flag = *flagp & excepts; + /* Replace the exception status */ - u.l[1] = u.l[1] & FPSCR_STICKY_BITS | *flagp & FE_to_sticky (excepts); + u.l[1] = (u.l[1] & ~(FPSCR_STICKY_BITS & excepts) + | flag & FPSCR_STICKY_BITS + | (flag >> (31 - FPSCR_VX) - (31 - FPSCR_VXSOFT) + & FE_INVALID_SOFTWARE)); /* Store the new status word (along with the rest of the environment). This may cause floating-point exceptions if the restored state requests it. */ fesetenv_register (u.fenv); + + /* Deal with FE_INVALID_SOFTWARE not being implemented on some chips. */ + if (flag & FE_INVALID) + feraiseexcept(FE_INVALID); } diff --git a/sysdeps/powerpc/ftestexcept.c b/sysdeps/powerpc/ftestexcept.c index 52733f7..6cb8dd5 100644 --- a/sysdeps/powerpc/ftestexcept.c +++ b/sysdeps/powerpc/ftestexcept.c @@ -23,16 +23,11 @@ int fetestexcept (int excepts) { fenv_union_t u; - int flags; /* Get the current state. */ u.fenv = fegetenv_register (); - /* Find the bits that indicate exceptions have occurred. */ - flags = u.l[1] & FPSCR_STICKY_BITS; - - /* Set the FE_INVALID bit if any of the FE_INVALID_* bits are set. */ - flags |= ((u.l[1] & FE_ALL_INVALID) != 0) << 31-24; - - return flags & excepts; + /* The FE_INVALID bit is dealt with correctly by the hardware, so we can + just: */ + return u.l[1] & excepts; } diff --git a/sysdeps/powerpc/q_addsub.c b/sysdeps/powerpc/q_addsub.c new file mode 100644 index 0000000..e4ef6d8 --- /dev/null +++ b/sysdeps/powerpc/q_addsub.c @@ -0,0 +1,549 @@ +/* Add or subtract two 128-bit floating point values. C prototype. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <quad_float.h> + +/* Add 'a' to 'b' and put the result in 'result', but treat a[0]=axx, + b[0]=bxx. bxx differs from b[0] only in the high bit, similarly axx. */ +/* Exceptions to raise: + - Invalid (SNaN) + - Invalid (Inf-Inf) + - Overflow + - Underflow + - Inexact + */ + +/* Handle cases where exponent of a or b is maximum. */ +static void +handle_max_exponent(unsigned result[4], + const unsigned a[4], const unsigned b[4], + const unsigned axx, /* Treat as a[0]. */ + const unsigned bxx, /* Treat as b[0]. */ + const unsigned ax, /* axx >> 16 & 0x7fff. */ + const unsigned bx) /* bxx >> 16 & 0x7fff. */ +{ + int ax_ismax, bx_ismax; + unsigned a1,a2,a3, b1,b2,b3; + int a_zeromant, b_zeromant; + + ax_ismax = ax == 0x7fff; + bx_ismax = bx == 0x7fff; + + assert(ax_ismax || bx_ismax); + + a1 = a[1]; a2 = a[2]; a3 = a[3]; + b1 = b[1]; b2 = b[2]; b3 = b[3]; + + a_zeromant = (axx & 0xffff | a1 | a2 | a3) == 0; + b_zeromant = (bxx & 0xffff | b1 | b2 | b3) == 0; + + /* Deal with SNaNs. */ + if ( ax_ismax && !a_zeromant && (axx & 0x8000) == 0 + || bx_ismax && !b_zeromant && (bxx & 0x8000) == 0) + { + set_fpscr_bit(FPSCR_VXSNAN); + axx |= 0x8000; /* Demote the SNaN to a QNaN (whichever of */ + bxx |= 0x8000; /* a or b it was). */ + } + /* Deal with Inf-Inf. */ + else if (a_zeromant && b_zeromant && (axx ^ bxx) == 0x80000000) + { + set_fpscr_bit(FPSCR_VXISI); + bxx |= 0x8000; /* Return an appropriate QNaN. */ + } + + /* Return the lexicographically larger of a or b, ignoring the sign + bits. */ + if ((axx & 0x7fffffff) > (bxx & 0x7fffffff)) goto return_a; + else if ((axx & 0x7fffffff) < (bxx & 0x7fffffff)) goto return_b; + else if (a1 > b1) goto return_a; + else if (a1 < b1) goto return_b; + else if (a2 > b2) goto return_a; + else if (a2 < b2) goto return_b; + else if (a3 > b3) goto return_a; /* I've clearly been writing too */ + else if (a3 < b3) goto return_b; /* much Fortran... */ + + /* If they are equal except for the sign bits, return 'b'. */ + +return_b: + result[0] = bxx; result[1] = b1; result[2] = b2; result[3] = b3; + return; + +return_a: + result[0] = axx; result[1] = a1; result[2] = a2; result[3] = a3; + return; +} + +/* Renormalise and output a FP number. */ +static void +renormalise_value(unsigned result[4], + const unsigned axx, + unsigned ax, + unsigned r0, + unsigned r1, + unsigned r2, + unsigned r3) +{ + int rshift; + if (r0 != 0 || cntlzw(a1) < 16 || 32 > ax-1) + { + rshift = cntlzw(r0)-15 + (-(cntlzw(r0) >> 5) & cntlzw(a1)); + assert(rshift < 32); + if (rshift > ax-1) + { + ax--; + rshift = ax; + } + + result[0] = (axx & 0x80000000 + | ax-rshift << 16 + | r0 << rshift & 0xffff + | a1 >> 32-rshift & 0xffff); + result[1] = a1 << rshift | a2 >> 32-rshift; + result[2] = a2 << rshift | a3 >> 32-rshift; + result[3] = a3 << rshift; + return; + } + result[3] = 0; + /* Special case for zero. */ + if (a1 == 0 && a2 == 0 && a3 == 0) + { + result[0] = axx & 0x80000000; + result[1] = result[2] = 0; + return; + } + while (a1 != 0 && cntlzw(a2) >= 16 && 64 <= ax-1) + { + ax -= 32; + a1 = a2; a2 = a3; a3 = 0; + } + rshift = cntlzw(a1)-15 + (-(cntlzw(a1) >> 5) & cntlzw(a2)); + assert(rshift < 32); + if (rshift > ax-1-32) + { + ax--; + rshift = ax-32; + } + + result[0] = (axx & 0x80000000 + | ax-rshift-32 << 16 + | a1 << rshift & 0xffff + | a2 >> 32-rshift & 0xffff); + result[1] = a2 << rshift | a3 >> 32-rshift; + result[2] = a3 << rshift; + return; +} + +/* Handle the case where one or both numbers are denormalised or zero. + This case almost never happens, so we don't slow the main code + with it. */ +static void +handle_min_exponent(unsigned result[4], + const unsigned a[4], const unsigned b[4], + const unsigned axx, /* Treat as a[0]. */ + const unsigned bxx, /* Treat as b[0]. */ + const unsigned ax, /* axx >> 16 & 0x7fff. */ + const unsigned bx) /* bxx >> 16 & 0x7fff. */ +{ + int ax_denorm, bx_denorm; + unsigned a1,a2,a3, b1,b2,b3; + int a_zeromant, b_zeromant; + + ax_denorm = ax == 0; + bx_denorm = bx == 0; + + assert(ax_denorm || bx_denorm); + + a1 = a[1]; a2 = a[2]; a3 = a[3]; + b1 = b[1]; b2 = b[2]; b3 = b[3]; + + +} + +/* Add a+b+cin modulo 2^32, put result in 'r' and carry in 'cout'. */ +#define addc(r,cout,a,b,cin) \ + do { \ + unsigned long long addc_tmp = (a)+(b)+(cin); + (cout) = addc_tmp >> 32; + (r) = addc_tmp; + } + +/* Calculate a+~b+cin modulo 2^32, put result in 'r' and carry in 'cout'. */ +#define subc(r,cout,a,b,cin) \ + do { \ + unsigned long long addc_tmp = (a)-(b)+(cin)-1; + (cout) = addc_tmp >> 63; + (r) = addc_tmp; + } + +/* Handle the case where both exponents are the same. This requires quite + a different algorithm than the general case. */ +static void +handle_equal_exponents(unsigned result[4], + const unsigned a[4], const unsigned b[4], + const unsigned axx, /* Treat as a[0]. */ + const unsigned bxx, /* Treat as b[0]. */ + unsigned ax) /* [ab]xx >> 16 & 0x7fff. */ +{ + unsigned a1,a2,a3, b1,b2,b3; + int roundmode; + unsigned carry, r0; + + a1 = a[1]; a2 = a[2]; a3 = a[3]; + b1 = b[1]; b2 = b[2]; b3 = b[3]; + + if ((int)(axx ^ bxx) >= 0) + { + int roundmode; + + /* Adding. */ + roundmode = fegetround(); + + /* What about overflow? */ + if (ax == 0x7ffe) + { + /* Oh no! Too big! */ + /* Result: + rounding result + -------- ------ + nearest return Inf with sign of a,b + zero return nearest possible non-Inf value with + sign of a,b + +Inf return +Inf if a,b>0, otherwise return + value just before -Inf. + -Inf return +Inf if a,b>0, otherwise return + value just before -Inf. + */ + set_fpscr_bit(FPSCR_OX); + /* Overflow always produces inexact result. */ + set_fpscr_bit(FPSCR_XX); + + if ( roundmode == FE_TONEAREST + || roundmode == FE_UPWARD && (int)axx >= 0 + || roundmode == FE_DOWNWARD && (int)axx < 0) + { + result[3] = result[2] = result[1] = 0; + result[0] = axx & 0xffff0000 | 0x7fff0000; + } + else + { + result[3] = result[2] = result[1] = 0xffffffff; + result[0] = axx & 0xfffe0000 | 0x7ffeffff; + } + return; + } + + /* We need to worry about rounding/inexact here. Do it like this: */ + if (a3 + b3 & 1) + { + /* Need to round. Upwards? */ + set_fpscr_bit(FPSCR_XX); + carry = ( roundmode == FE_NEAREST && (a3 + b3 & 2) != 0 + || roundmode == FE_UPWARD && (int)axx >= 0 + || roundmode == FE_DOWNWARD && (int)axx < 0); + } + else + carry = 0; /* Result will be exact. */ + + /* Perform the addition. */ + addc(a3,carry,a3,b3,carry); + addc(a2,carry,a2,b2,carry); + addc(a1,carry,a1,b1,carry); + r0 = (axx & 0xffff) + (bxx & 0xffff) + carry; + + /* Shift right by 1. */ + result[3] = a3 >> 1 | a2 << 31; + result[2] = a2 >> 1 | a1 << 31; + result[1] = a1 >> 1 | r0 << 31; + /* Exponent of result is exponent of inputs plus 1. + Sign of result is common sign of inputs. */ + result[0] = r0 >> 1 & 0xffff | axx + 0x10000 & 0xffff0000; + } + else + { + /* Subtracting. */ + + /* Perform the subtraction, a-b. */ + subc(a3,carry,a3,b3,0); + subc(a2,carry,a2,b2,carry); + subc(a1,carry,a1,b1,carry); + subc(r0,carry,a0&0xffff,b0&0xffff,carry); + + /* Maybe we should have calculated b-a... */ + if (carry) + { + subc(a3,carry,0,a3,0); + subc(a2,carry,0,a2,carry); + subc(a1,carry,0,a1,carry); + subc(r0,carry,0,r0,carry); + axx ^= 0x80000000; + } + + renormalise_value(result, axx, ax, r0, a1, a2, a3); + } +} + + +static void +add(unsigned result[4], const unsigned a[4], const unsigned b[4], + unsigned axx, unsigned bxx) +{ + int ax, bx, diff, carry; + unsigned a0,a1,a2,a3, b0,b1,b2,b3,b4, sdiff; + + ax = axx >> 16 & 0x7fff; + bx = bxx >> 16 & 0x7fff; + + /* Deal with NaNs and Inf. */ + if (ax == 0x7fff || bx == 0x7fff) + { + handle_max_exponent(result, a, b, axx, bxx, ax, bx); + return; + } + /* Deal with denorms and zero. */ + if (ax == 0 || bx == 0) + { + handle_min_exponent(result, a, b, axx, bxx, ax, bx); + return; + } + /* Finally, one special case, when both exponents are equal. */ + if (ax == bx) + { + handle_equal_exponents(result, a, b, axx, bxx, ax); + return; + } + + sdiff = axx ^ bxx; + /* Swap a and b if b has a larger magnitude than a, so that a will have + the larger magnitude. */ + if (ax < bx) + { + const unsigned *t; + t = b; b = a; a = t; + diff = bx - ax; + ax = bx; + axx = bxx; + } + else + diff = ax - bx; + + a0 = a[0] & 0xffff | 0x10000; a1 = a[1]; a2 = a[2]; a3 = a[3]; + b0 = b[0] & 0xffff | 0x10000; b1 = b[1]; b2 = b[2]; b3 = b[3]; + if (diff < 32) + { + b4 = b3 << 32-diff; + b3 = b3 >> diff | b2 << 32-biff; + b2 = b2 >> diff | b1 << 32-diff; + b1 = b1 >> diff | b0 << 32-diff; + b0 = b0 >> diff; + } + else if (diff < 64) + { + diff -= 32; + b4 = b3 & 1 | b3 >> (diff == 32) | b2 << 32-biff; + b3 = b2 >> diff | b1 << 32-diff; + b2 = b1 >> diff | b0 << 32-diff; + b1 = b0 >> diff; + b0 = 0; + } + else if (diff < 96) + { + b4 = b2 | b3 | b1 << 32-diff; + b3 = b1 >> diff | b0 << 32-diff; + b2 = b0 >> diff; + b1 = b0 = 0; + } + else if (diff < 128) + { + b4 = b1 | b2 | b3 | b0 << 32-diff; + b3 = b0 >> diff; + b2 = b1 = b0 = 0; + } + else + { + b4 = b0|b1|b2|b3; + b3 = b2 = b1 = b0 = 0; + } + + /* Now, two cases: one for addition, one for subtraction. */ + if ((int)sdiff >= 0) + { + /* Addition. */ + + /* + + /* Perform the addition. */ + addc(a3,carry,a3,b3,0); + addc(a2,carry,a2,b2,carry); + addc(a1,carry,a1,b1,carry); + addc(a0,carry,a0,b0,carry); + + + + if (a0 & 0x20000) + { + /* Need to renormalise by shifting right. */ + /* Shift right by 1. */ + b4 = b4 | a3 << 31; + a3 = a3 >> 1 | a2 << 31; + a2 = a2 >> 1 | a1 << 31; + result[1] = a1 >> 1 | r0 << 31; + /* Exponent of result is exponent of inputs plus 1. + Sign of result is common sign of inputs. */ + result[0] = r0 >> 1 & 0xffff | axx + 0x10000 & 0xffff0000; + } + + + } + else + { + /* Subtraction. */ + + } +} + +/* Add the absolute values of two 128-bit floating point values, + give the result the sign of one of them. The only exception this + can raise is for SNaN. */ +static void +aadd(unsigned result[4], const unsigned a[4], const unsigned b[4]) +{ + unsigned ax, bx, xd; + const unsigned *sml; + unsigned t0,t1,t2,t3,tx, s0,s1,s2,s3,s4, carry; + int rmode, xdelta, shift; + + ax = a[0] >> 16 & 0x7fff; + bx = b[0] >> 16 & 0x7fff; + + /* Deal with . */ + if (ax == 0x7fff) + { + t0 = a[0]; t1 = a[1]; t2 = a[2]; t3 = a[3]; + /* Check for SNaN. */ + if ((t0 & 0x8000) == 0 + && (t0 & 0x7fff | t1 | t2 | t3) != 0) + set_fpscr_bit(FPSCR_VXSNAN); + /* Return b. */ + result[0] = t0; result[1] = t1; result[2] = t2; result[3] = t3; + return; + } + /* Deal with b==Inf or b==NaN. */ + if (bx == 0x7fff) + { + t0 = b[0]; t1 = b[1]; t2 = b[2]; t3 = b[3]; + /* Check for SNaN. */ + if ((t0 & 0x8000) == 0 + && (t0 & 0x7fff | t1 | t2 | t3) != 0) + set_fpscr_bit(FPSCR_VXSNAN); + /* Return b. */ + result[0] = t0; result[1] = t1; result[2] = t2; result[3] = t3; + return; + } + + /* Choose the larger of the two to be 't', and the smaller to be 's'. */ + if (ax > bx) + { + t0 = a[0] & 0xffff | (ax != 0) << 16; + t1 = a[1]; t2 = a[2]; t3 = a[3]; tx = ax; + s0 = b[0] & 0xffff | (bx != 0) << 16; + s1 = b[1]; s2 = b[2]; s3 = b[3]; + xd = ax-bx; + } + else + { + t0 = b[0] & 0xffff | (bx != 0) << 16; + t1 = b[1]; t2 = b[2]; t3 = b[3]; tx = bx; + s0 = a[0] & 0xffff | (ax != 0) << 16; + s1 = a[1]; s2 = a[2]; s3 = a[3]; + sml = a; + xd = bx-ax; + } + + /* Shift 's2' right by 'xd' bits. */ + switch (xd >> 5) + { + case 0: + s4 = 0; + break; + case 1: + s4 = s3; s3 = s2; s2 = s1; s1 = s0; s0 = 0; + break; + case 2: + s4 = s2 | s3 != 0; + s3 = s1; s2 = s0; s1 = s0 = 0; + break; + case 3: + s4 = s1 | (s3|s2) != 0; + s3 = s0; s2 = s1 = s0 = 0; + break; + default: + s4 = s0 | (s3|s2|s1) != 0; + s3 = s2 = s1 = s0 = 0; + } + xd = xd & 0x1f; + if (xd != 0) + { + s4 = s4 >> xd | (s4 << 32-xd) != 0 | s3 << 32-xd; + s3 = s3 >> xd | s2 << 32-xd; + s2 = s2 >> xd | s1 << 32-xd; + s1 = s1 >> xd | s0 << 32-xd; + s0 = s0 >> xd; + } + + /* Do the addition. */ +#define addc(r,cout,a,b,cin) \ + do { \ + unsigned long long addc_tmp = (a)+(b)+(cin); + (cout) = addc_tmp >> 32; + (r) = addc_tmp; + } + addc(t3,carry,t3,s3,0); + addc(t2,carry,t2,s2,carry); + addc(t1,carry,t1,s1,carry); + t0 = t0 + s0 + carry; + + /* Renormalise. */ + xdelta = 15-cntlzw(t0); + if (tx + xdelta <= 0x7fff) + shift = xdelta; + else + { + } +} + +/* Add two 128-bit floating point values. */ +void +__q_add(unsigned result[4], const unsigned a[4], const unsigned b[4]) +{ + if ((a[0] ^ b[0]) >= 0) + aadd(result, a, b); + else + asubtract(result, a, b); +} + +/* Subtract two 128-bit floating point values. */ +void +__q_sub(unsigned result[4], const unsigned a[4], const unsigned b[4]) +{ + if ((a[0] ^ b[0]) < 0) + aadd(result, a, b); + else + asubtract(result, a, b); +} diff --git a/sysdeps/powerpc/q_dtoq.c b/sysdeps/powerpc/q_dtoq.c new file mode 100644 index 0000000..8cab9e4 --- /dev/null +++ b/sysdeps/powerpc/q_dtoq.c @@ -0,0 +1,66 @@ +/* 64-bit floating point to 128-bit floating point. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <quad_float.h> + +/* long double _q_dtoq(double a); + Convert 'a' to long double. Don't raise exceptions. + */ + +void +__q_dtoq(unsigned long long result[2], double a) +{ + unsigned ux, rx; + union { + double d; + unsigned long long u; + } u; + + u.d = a; + result[1] = u.u << 64-4; + result[0] = u.u >> 4; + /* correct exponent bias */ + rx = ((long long)u.u >> 52 & 0x87ff) + 16383-1023; + + ux = u.u >> 52 & 0x7ff; + if (ux == 0) + { + if ((u.u & 0x7fffffffffffffffULL) == 0) + { + /* +0.0 or -0.0. */ + rx &= 0x8000; + } + else + { + /* Denormalised number. Renormalise. */ + unsigned long long um = u.u & 0x000fffffffffffffULL; + int cs = cntlzd(um) - 12 + 1; + rx -= cs; + um <<= cs; + result[0] = um >> 4; + result[1] = um << 64-4; + } + } + else if (ux == 0x7ff) + { + /* Inf or NaN. */ + rx |= 0x7fff; + } + *(unsigned short *)result = rx; +} diff --git a/sysdeps/powerpc/q_feq.c b/sysdeps/powerpc/q_feq.c new file mode 100644 index 0000000..3f5512a --- /dev/null +++ b/sysdeps/powerpc/q_feq.c @@ -0,0 +1,65 @@ +/* 128-bit floating point unordered equality. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <fenv_libc.h> + +/* int _q_feq(const long double *a, const long double *b); + Returns nonzero if a==b, 0 otherwise. + + Special cases: + NaNs are never equal to anything; + -0 == +0; + If either argument is a SNaN, we set FPSCR_VXSNAN to cause an + 'invalid operation' exception. + */ + +int +__q_feq(const unsigned a[4], const unsigned b[4]) +{ + unsigned a0, b0; + + a0 = a[0]; b0 = b[0]; + + if ((a0 >> 16 & 0x7fff) != 0x7fff && + (b0 >> 16 & 0x7fff) != 0x7fff) + { + unsigned a3,b3,a2,b2,a1,b1; + unsigned z, result; + + a3 = a[3]; b3 = b[3]; a2 = a[2]; + b2 = b[2]; a1 = a[1]; b1 = b[1]; + result = ~(a3 ^ b3); + result &= ~(a2 ^ b2); + result &= ~(a1 ^ b1); + z = a3 | a2; + z |= a1; + z = (z >> 1 | z | a0) & 0x7fffffff; + /* 'z' is 0 iff a==0.0, otherwise between 1 and 0x7fffffff */ + return (result & ~(a0^b0 & ~(-z & 0x80000000)))+1; + } + else + { + /* Deal with SNaNs */ + if (((a0|b0) & 0x8000) == 0) + { + set_fpscr_bit(FPSCR_VXSNAN); + } + return 0; + } +} diff --git a/sysdeps/powerpc/q_fne.c b/sysdeps/powerpc/q_fne.c new file mode 100644 index 0000000..8f6429c --- /dev/null +++ b/sysdeps/powerpc/q_fne.c @@ -0,0 +1,70 @@ +/* 128-bit floating point unordered not-equality. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <fenv_libc.h> + +/* int _q_fne(const long double *a, const long double *b); + Returns 0 if a==b + + Special cases: + NaNs return 1 always; + -0 == +0; + If either argument is a SNaN, we set FPSCR_VXSNAN to cause an + 'invalid operation' exception. + */ + +int +__q_fne(const unsigned a[4], const unsigned b[4]) +{ + unsigned a0, b0; + + a0 = a[0]; b0 = b[0]; + + if ((a0 >> 16 & 0x7fff) != 0x7fff && + (b0 >> 16 & 0x7fff) != 0x7fff) + { + unsigned a3,b3,a2,b2,a1,b1; + unsigned z, result; + + a3 = a[3]; b3 = b[3]; a2 = a[2]; + result = a3 ^ b3; + b2 = b[2]; + if (result != 0) + return result; + a1 = a[1]; b1 = b[1]; + result = a2 ^ b2; + result |= a1 ^ b1; + z = a3 | a2; + if (result != 0) + return result; + z |= a1; + z = (z >> 1 | z | a0) & 0x7fffffff; + /* 'z' is 0 iff a==0.0, otherwise between 1 and 0x7fffffff */ + return (a0^b0) & ~(-z & 0x80000000); + } + else + { + /* Deal with SNaNs */ + if (((a0|b0) & 0x8000) == 0) + { + set_fpscr_bit(FPSCR_VXSNAN); + } + return 1; + } +} diff --git a/sysdeps/powerpc/q_itoq.c b/sysdeps/powerpc/q_itoq.c new file mode 100644 index 0000000..aa73739 --- /dev/null +++ b/sysdeps/powerpc/q_itoq.c @@ -0,0 +1,50 @@ +/* 32-bit fixed point signed integer to 128-bit floating point. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <quad_float.h> + +/* long double _q_itoq(int a); + Convert 'a' to long double. + */ + +void +__q_itoq(unsigned int result[4], int a) +{ + unsigned rx; + int cs, css; + + /* Note that if a==-2^31, then ua will be 2^31. */ + unsigned int ua = abs(a); + + /* Normalize. */ + cs = cntlzw(ua); + ua <<= cs+1; + + /* Calculate the exponent, in 4 easy instructions. */ + css = 31-cs; + rx = 16383+css << 16 & ~css; + + /* Copy the sign bit from 'a'. */ + asm ("rlwimi %0,%1,0,0,0": "=r"(rx) : "r"(a), "0"(rx)); + + /* Put it all together. */ + result[2] = result[3] = 0; + asm ("rlwimi %0,%1,16,16,31": "=r"(result[0]) : "r"(ua), "0"(rx)); + result[1] = ua << 16; +} diff --git a/sysdeps/powerpc/q_lltoq.c b/sysdeps/powerpc/q_lltoq.c new file mode 100644 index 0000000..6222eff --- /dev/null +++ b/sysdeps/powerpc/q_lltoq.c @@ -0,0 +1,52 @@ +/* 64-bit fixed point signed integer to 128-bit floating point. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <quad_float.h> + +/* long double _q_ulltoq(long long a); + Convert 'a' to long double. + */ + +void +__q_lltoq(unsigned int result[4], long long a) +{ + unsigned rx; + int cs, css; + + /* Calculate absolute value of 'a'. */ + unsigned long long ua = (a ^ a >> 63) - (a >> 63); + + /* Normalize. */ + cs = cntlzd(a); + ua <<= cs+1; + + /* Calculate the exponent, in 4 easy instructions. */ + css = 63-cs; + rx = 16383+css << 16 & ~css; + + /* Copy the sign bit from 'a'. */ + asm ("rlwimi %0,%1,0,0,0": "=r"(rx) : "r"(a >> 32), "0"(rx)); + + /* Put it all together. */ + result[3] = 0; + asm ("rlwimi %0,%1,16,16,31": "=r"(result[0]) : "r"(ua >> 32), "0"(rx)); + ua <<= 16; + result[2] = ua; + result[1] = ua >> 32; +} diff --git a/sysdeps/powerpc/q_neg.c b/sysdeps/powerpc/q_neg.c new file mode 100644 index 0000000..8e11afd --- /dev/null +++ b/sysdeps/powerpc/q_neg.c @@ -0,0 +1,38 @@ +/* Negate a 128-bit floating point value. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <quad_float.h> + +/* long double _q_neg(const long double *a); + Negate 'a'. Don't raise exceptions. + */ + +void +__q_neg(unsigned int result[4], unsigned int a[4]) +{ + unsigned int t1,t2; + t1 = a[0]; + t2 = a[1]; + result[0] = t1 ^ 0x80000000; + t1 = a[2]; + result[1] = t2; + t2 = a[3]; + result[2] = t1; + result[3] = t2; +} diff --git a/sysdeps/powerpc/q_qtoi.c b/sysdeps/powerpc/q_qtoi.c new file mode 100644 index 0000000..a2b1b3f --- /dev/null +++ b/sysdeps/powerpc/q_qtoi.c @@ -0,0 +1,65 @@ +/* 128-bit floating point to 32-bit fixed point signed integer. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <quad_float.h> + +/* int _q_qtoi(const long double *a); + Convert 'a' to signed int by truncation. + + Special cases: + NaN: raise VXCVI, return 0x80000000 + SNaN: raise VXSNAN, VXCVI, and return 0x80000000 + >= 2^32: raise VXCVI, return 0x7fffffff + <= -2^32: raise VXCVI, return 0x80000000 + */ + +int +__q_qtoi(const unsigned long long a[2]) +{ + int ax, sgn; + unsigned long long a0; + + a0 = a[0]; + /* 'sgn' is -1 if 'a' is negative, 0 if positive. */ + sgn = (long long)a0 >> 63; + ax = (a0 >> 48 & 0x7fff) - 16383; + /* Deal with non-special cases. */ + if (ax <= 30) + /* If we had a '>>' operator that behaved properly with respect to + large shifts, we wouldn't need the '& -(ax >> 31)' term, which + clears 'result' if ax is negative. The '^ sgn) - sgn' part is + equivalent in this case to multiplication by 'sgn', but usually + faster. */ + return (((unsigned)(a0 >> 17 | 0x80000000) >> 31-ax & -(ax >> 31)) + ^ sgn) - sgn; + + /* Check for SNaN, if so raise VXSNAN. */ + if ((a0 >> 32 & 0x7fff8000) == 0x7fff0000 + && (a[1] | a0 & 0x00007fffffffffffULL) != 0) + set_fpscr_bit(FPSCR_VXSNAN); + + /* Treat all NaNs as large negative numbers. */ + sgn |= -cntlzw(~(a0 >> 32) & 0x7fff0000) >> 5; + + /* All the specials raise VXCVI. */ + set_fpscr_bit(FPSCR_VXCVI); + + /* Return 0x7fffffff (if a < 0) or 0x80000000 (otherwise). */ + return sgn ^ 0x7fffffff; +} diff --git a/sysdeps/powerpc/q_qtoll.c b/sysdeps/powerpc/q_qtoll.c new file mode 100644 index 0000000..77a54f8 --- /dev/null +++ b/sysdeps/powerpc/q_qtoll.c @@ -0,0 +1,64 @@ +/* 128-bit floating point to 64-bit fixed point signed integer. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <quad_float.h> + +/* long long _q_qtoll(const long double *a); + Convert 'a' to signed long long by truncation. + + Special cases: + NaN: raise VXCVI, return 0x8000000000000000 + SNaN: raise VXSNAN, VXCVI, and return 0x8000000000000000 + >= 2^32: raise VXCVI, return 0x7fffffffffffffff + <= -2^32: raise VXCVI, return 0x8000000000000000 + */ + +long long +__q_qtoll(const unsigned long long a[2]) +{ + int ax, sgn; + unsigned long long a0, a1; + + a0 = a[0]; a1 = a[1]; + /* 'sgn' is -1 if 'a' is negative, 0 if positive. */ + sgn = (long long)a0 >> 63; + ax = (a0 >> 48 & 0x7fff) - 16383; + /* Deal with non-special cases. */ + if (ax <= 62) + /* If we had a '>>' operator that behaved properly with respect to + large shifts, we wouldn't need the '& -(ax >> 31)' term, which + clears 'result' if ax is negative. The '^ sgn) - sgn' part is + equivalent in this case to multiplication by 'sgn', but faster. */ + return (((a0 << 15 | a1 >> 64-15 | 0x8000000000000000ULL) >> 63-ax + & -(unsigned long long)(ax >> 31)) + ^ (long long)sgn) - sgn; + + /* Check for SNaN, if so raise VXSNAN. */ + if ((a0 >> 32 & 0x7fff8000) == 0x7fff0000 + && (a1 | a0 & 0x00007fffffffffffULL) != 0) + set_fpscr_bit(FPSCR_VXSNAN); + + /* Treat all NaNs as large negative numbers. */ + sgn |= -cntlzw(~(a0 >> 32) & 0x7fff0000) >> 5; + + /* All the specials raise VXCVI. */ + set_fpscr_bit(FPSCR_VXCVI); + + return (long long)sgn ^ 0x7fffffffffffffffLL; +} diff --git a/sysdeps/powerpc/q_qtos.c b/sysdeps/powerpc/q_qtos.c new file mode 100644 index 0000000..cd2715f --- /dev/null +++ b/sysdeps/powerpc/q_qtos.c @@ -0,0 +1,84 @@ +/* 128-bit floating point to 32-bit floating point. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <quad_float.h> + +/* float _q_qtos(const long double *a); + Convert 'a' to float. Round as per current rounding flags. + + Input Rounding Output + +/-0 * +/-0 + +/-Inf * +/-Inf + +/-NaN * +/-NaN (with mantissa truncated) + +/-SNaN * +/-NaN (with mantissa truncated, MSB of mantissa <- 1) + && raise VXSNAN + [Note: just truncating the mantissa may not give you + a SNaN!] + |a|>=2^128 Nearest +/-Inf && raise overflow && raise inexact + |a|>=2^128 Truncate +/-(2^128-2^104) && raise overflow && raise inexact + a>=2^128 +Inf +Inf && raise overflow && raise inexact + a<=-2^128 +Inf -(2^128-2^104) && raise overflow && raise inexact + a>=2^128 -Inf +(2^128-2^104) && raise overflow && raise inexact + a<=-2^128 -Inf -Inf && raise overflow && raise inexact + + We also need to raise 'inexact' if the result will be inexact, which + depends on the current rounding mode. + + To avoid having to deal with all that, we convert to a 'double' + that will round correctly (but is not itself rounded correctly), + and convert that to a float. This makes this procedure much + simpler and much faster. */ + +float +__q_qtos(const unsigned long long a[2]) +{ + unsigned long long a0,d; + union { + double d; + unsigned long long ull; + } u; + + a0 = a[0]; + + /* Truncate the mantissa to 48 bits. */ + d = a0 << 4; + /* Set the low bit in the mantissa if any of the bits we are dropping + were 1. This ensures correct rounding, and also distinguishes + 0 and Inf from denormalised numbers and SNaN (respectively). */ + d |= a[1] != 0; + /* Copy the sign bit. */ + d = d & 0x7fffffffffffffffULL | a0 & 0x8000000000000000ULL; + + /* Now, we need to fix the exponent. If the exponent of a was in + the range +127 to -152, or was +16384 or -16383, it is already + correct in 'd'. Otherwise, we need to ensure that the new + exponent is in the range +1023 to +128, or -153 to -1022, with + the same sign as the exponent of 'a'. We can do this by setting + bits 1-3 (the second through fourth-most significant bit) of 'd' + to 101 if bit 1 of 'a' is 1, or 010 if bit 1 of 'a' is 0. */ + if ((a0 >> 56 & 0x7f) - 0x3f > 1) + { + unsigned t = (a0 >> 32+2 & 2 << 31-1-2)*3 + (2 << 31-2); + d = (d & 0x8fffffffffffffffULL + | (unsigned long long)t<<32 & 0x7000000000000000ULL); + } + + u.ull = d; + return (float)u.d; +} diff --git a/sysdeps/powerpc/q_qtou.c b/sysdeps/powerpc/q_qtou.c new file mode 100644 index 0000000..a5583cc --- /dev/null +++ b/sysdeps/powerpc/q_qtou.c @@ -0,0 +1,64 @@ +/* 128-bit floating point to 32-bit fixed point unsigned integer. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <quad_float.h> + +/* unsigned int _q_qtou(const long double *a); + Convert 'a' to unsigned int by truncation. + + Special cases: + -0: return 0 + NaN: raise VXCVI, return 0 + SNaN: raise VXSNAN, VXCVI, and return 0 + Negative numbers (other than -0, but including -Inf): raise VXCVI, return 0 + >= 2^32: raise VXCVI, return 0xffffffff + */ + +unsigned int +__q_qtou(const unsigned long long a[2]) +{ + int ax; + unsigned result; + unsigned long long a0; + + /* Deal with non-special cases. */ + a0 = a[0]; + ax = (a0 >> 48) - 16383; + if (ax <= 31) + /* If we had a '>>' operator that behaved properly with respect to + large shifts, we wouldn't need the '& -(ax >> 31)' term, which + clears 'result' if ax is negative. */ + return (unsigned)(a0 >> 17 | 0x80000000) >> 31-ax & -(ax >> 31); + + /* 'result' is 1 if a is negative, 0 otherwise. */ + result = a0 >> 63; + /* Check for -0, otherwise raise VXCVI. */ + if (a0 != 0x8000000000000000ULL || a[1] != 0) + { + /* Check for SNaN, if so raise VXSNAN. */ + if ((a0 >> 32 & 0x7fff8000) == 0x7fff0000 + && (a[1] | a0 & 0x00007fffffffffffULL) != 0) + set_fpscr_bit(FPSCR_VXSNAN); + /* Treat all NaNs as large negative numbers. */ + result |= cntlzw(~(a0 >> 32) & 0x7fff0000) >> 5; + + set_fpscr_bit(FPSCR_VXCVI); + } + return result-1; +} diff --git a/sysdeps/powerpc/q_qtoull.c b/sysdeps/powerpc/q_qtoull.c new file mode 100644 index 0000000..e0b84d3 --- /dev/null +++ b/sysdeps/powerpc/q_qtoull.c @@ -0,0 +1,65 @@ +/* 128-bit floating point to 64-bit fixed point unsigned integer. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <quad_float.h> + +/* unsigned long long _q_qtoull(const long double *a); + Convert 'a' to unsigned long long by truncation. + + Special cases: + -0: return 0 + NaN: raise VXCVI, return 0 + SNaN: raise VXSNAN, VXCVI, and return 0 + Negative numbers (other than -0, but including -Inf): raise VXCVI, return 0 + >= 2^32: raise VXCVI, return 0xffffffffffffffff + */ + +unsigned long long +__q_qtoull(const unsigned long long a[2]) +{ + int ax; + unsigned result; + unsigned long long a0, a1; + + /* Deal with non-special cases. */ + a0 = a[0]; a1 = a[1]; + ax = (a0 >> 48) - 16383; + if (ax <= 63) + /* If we had a '>>' operator that behaved properly with respect to + large shifts, we wouldn't need the '& -(ax >> 31)' term, which + clears 'result' if ax is negative. */ + return ((a0 << 15 | a1 >> 64-15 | 0x8000000000000000ULL) >> 63-ax + & -(unsigned long long)(ax >> 31)); + + /* 'result' is 1 if a is negative, 0 otherwise. */ + result = a0 >> 63; + /* Check for -0, otherwise raise VXCVI. */ + if (a0 != 0x8000000000000000ULL || a[1] != 0) + { + /* Check for SNaN, if so raise VXSNAN. */ + if ((a0 >> 32 & 0x7fff8000) == 0x7fff0000 + && (a1 | a0 & 0x00007fffffffffffULL) != 0) + set_fpscr_bit(FPSCR_VXSNAN); + /* Treat all NaNs as large negative numbers. */ + result |= cntlzw(~(a0 >> 32) & 0x7fff0000) >> 5; + + set_fpscr_bit(FPSCR_VXCVI); + } + return result-1LL; +} diff --git a/sysdeps/powerpc/q_stoq.c b/sysdeps/powerpc/q_stoq.c new file mode 100644 index 0000000..766997b --- /dev/null +++ b/sysdeps/powerpc/q_stoq.c @@ -0,0 +1,65 @@ +/* 32-bit floating point to 128-bit floating point. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <quad_float.h> + +/* long double _q_stoq(float a); + Convert 'a' to long double. Don't raise exceptions. + */ + +void +__q_stoq(unsigned long long result[2], float a) +{ + unsigned ux, rx; + union { + float d; + unsigned u; + } u; + + u.d = a; + result[1] = 0; + result[0] = u.u << 32-7; + /* correct exponent bias */ + rx = ((int)u.u >> 23 & 0x80ff) + 16383-127; + + ux = u.u >> 23 & 0xff; + if (ux == 0) + { + if ((u.u & 0x7fffffff) == 0) + { + /* +0.0 or -0.0. */ + rx &= 0x8000; + } + else + { + /* Denormalised number. Renormalise. */ + unsigned um = u.u & 0x007fffff; + int cs = cntlzw(um) - 9 + 1; + rx -= cs; + um <<= cs; + result[0] = um << 32-7; + } + } + else if (ux == 0xff) + { + /* Inf or NaN. */ + rx |= 0x7fff; + } + *(unsigned short *)result = rx; +} diff --git a/sysdeps/powerpc/q_ulltoq.c b/sysdeps/powerpc/q_ulltoq.c new file mode 100644 index 0000000..caae124 --- /dev/null +++ b/sysdeps/powerpc/q_ulltoq.c @@ -0,0 +1,46 @@ +/* 64-bit fixed point unsigned integer to 128-bit floating point. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <quad_float.h> + +/* long double _q_ulltoq(unsigned long long a); + Convert 'a' to long double. + */ + +void +__q_ulltoq(unsigned int result[4], unsigned long long a) +{ + unsigned rx; + int cs, css; + + /* Normalize. */ + cs = cntlzd(a); + a <<= cs+1; + + /* Calculate the exponent, in 4 easy instructions. */ + css = 63-cs; + rx = 16383+css << 16 & ~css; + + /* Put it all together. */ + result[3] = 0; + result[0] = rx & 0xffff0000 | a >> 48 & 0x0000ffff; + a <<= 16; + result[2] = a; + result[1] = a >> 32; +} diff --git a/sysdeps/powerpc/q_utoq.c b/sysdeps/powerpc/q_utoq.c new file mode 100644 index 0000000..84ce215 --- /dev/null +++ b/sysdeps/powerpc/q_utoq.c @@ -0,0 +1,44 @@ +/* 32-bit fixed point unsigned integer to 128-bit floating point. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <quad_float.h> + +/* long double _q_utoq(unsigned int a); + Convert 'a' to long double. + */ + +void +__q_utoq(unsigned int result[4], unsigned int a) +{ + unsigned rx; + int cs, css; + + /* Normalize. */ + cs = cntlzw(a); + a <<= cs+1; + + /* Calculate the exponent, in 4 easy instructions. */ + css = 31-cs; + rx = 16383+css << 16 & ~css; + + /* Put it all together. */ + result[2] = result[3] = 0; + asm ("rlwimi %0,%1,16,16,31": "=r"(result[0]) : "r"(a), "0"(rx)); + result[1] = a << 16; +} diff --git a/sysdeps/powerpc/quad_float.h b/sysdeps/powerpc/quad_float.h new file mode 100644 index 0000000..787e8d9 --- /dev/null +++ b/sysdeps/powerpc/quad_float.h @@ -0,0 +1,44 @@ +/* Internal libc stuff for 128-bit IEEE FP emulation routines. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#ifndef _QUAD_FLOAT_H +#define _QUAD_FLOAT_H 1 + +#include <fenv_libc.h> + +/* Returns the number of leading zero bits in 'x' (between 0 and 32 + inclusive). 'x' is treated as being 32 bits long. */ +#define cntlzw(x) \ + ({ unsigned p = (x); \ + unsigned r; \ + asm ("cntlzw %0,%1" : "=r"(r) : "r"(p)); \ + r; }) + +/* Returns the number of leading zero bits in 'x' (between 0 and 64 + inclusive). 'x' is treated as being 64 bits long. */ +#define cntlzd(x) \ + ({ unsigned long long q = (x); \ + unsigned int c1, c2; \ + c1 = cntlzw(q >> 32); \ + c2 = cntlzw(q); \ + c1 + (-(c1 >> 5) & c2); }) + +#define shift_and_or + +#endif /* quad_float.h */ diff --git a/sysdeps/powerpc/s_copysign.S b/sysdeps/powerpc/s_copysign.S new file mode 100644 index 0000000..adc7df2 --- /dev/null +++ b/sysdeps/powerpc/s_copysign.S @@ -0,0 +1,60 @@ +/* Copy a sign bit between floating-point values. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +/* This has been coded in assembler because GCC makes such a mess of it + when it's coded in C. */ + + .section ".text" + .align 2 + .globl __copysign + .type __copysign,@function +__copysign: +/* double [f1] copysign (double [f1] x, double [f2] y); + copysign(x,y) returns a value with the magnitude of x and + with the sign bit of y. */ + + stwu %r1,-16(%r1) + stfd %f2,8(%r1) + lwz %r3,8(%r1) + cmpwi %r3,0 + addi %r1,%r1,16 + blt 0f + fabs %f1,%f1 + blr +0: fnabs %f1,%f1 + blr +0: + .size __copysign,0b-__copysign + + .globl copysign + .globl copysignf + .globl __copysignf + .weak copysign + .weak copysignf + .set copysign,__copysign +/* It turns out that it's safe to use this code even for single-precision. */ + .set __copysignf,__copysign + .set copysignf,__copysign +#ifdef NO_LONG_DOUBLE + .globl copysignl + .globl __copysignl + .weak copysignl + .set __copysignl,__copysign + .set copysignl,__copysign +#endif diff --git a/sysdeps/powerpc/s_fabs.S b/sysdeps/powerpc/s_fabs.S new file mode 100644 index 0000000..a527335 --- /dev/null +++ b/sysdeps/powerpc/s_fabs.S @@ -0,0 +1,42 @@ +/* Floating-point absolute value. PowerPC version. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + + .section ".text" + .align 2 + .globl __fabs + .type __fabs,@function +__fabs: +/* double [f1] fabs (double [f1] x); */ + fabs %f1,%f1 + blr +0: + .size __fabs,0b-__fabs + + .globl fabs,fabsf,__fabsf + .weak fabs,fabsf + .set fabs,__fabs +/* It turns out that it's safe to use this code even for single-precision. */ + .set __fabsf,__fabs + .set fabsf,__fabs +#ifdef NO_LONG_DOUBLE + .globl fabsl,__fabsl + .weak fabsl + .set __fabsl,__fabs + .set fabsl,__fabs +#endif diff --git a/sysdeps/powerpc/s_isnan.c b/sysdeps/powerpc/s_isnan.c new file mode 100644 index 0000000..34019fd --- /dev/null +++ b/sysdeps/powerpc/s_isnan.c @@ -0,0 +1,47 @@ +/* Return 1 if argument is a NaN, else 0. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include "math.h" +#include <fenv_libc.h> + +int __isnan(double x) +{ + fenv_t savedstate; + int result; + savedstate = fegetenv_register(); + reset_fpscr_bit(FPSCR_VE); + result = !(x == x); + fesetenv_register(savedstate); + return result; +} +weak_alias (__isnan, isnan) +/* It turns out that the 'double' version will also always work for + single-precision. Use explicit assembler to stop gcc complaining + that 'isnanf' takes a float parameter, not double. */ +asm ("\ + .globl __isnanf + .globl isnanf + .weak isnanf + .set __isnanf,__isnan + .set isnanf,__isnan +"); +#ifdef NO_LONG_DOUBLE +strong_alias (__isnan, __isnanl) +weak_alias (__isnan, isnanl) +#endif diff --git a/sysdeps/powerpc/s_llrint.c b/sysdeps/powerpc/s_llrint.c new file mode 100644 index 0000000..7ca48c0 --- /dev/null +++ b/sysdeps/powerpc/s_llrint.c @@ -0,0 +1,28 @@ +/* Round a long long floating point value to an integer in the current + rounding mode. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include "math.h" + +long long int +__llrint (long double x) +{ + return (long long int) __rintl (x); +} +weak_alias (__llrint, llrint) diff --git a/sysdeps/powerpc/s_llround.c b/sysdeps/powerpc/s_llround.c new file mode 100644 index 0000000..fbe3a32 --- /dev/null +++ b/sysdeps/powerpc/s_llround.c @@ -0,0 +1,46 @@ +/* Round long double value to long int. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <math.h> + +/* I think that what this routine is supposed to do is round a value + to the nearest integer, with values exactly on the boundary rounded + away from zero. */ +/* This routine relies on (long long)x, when x is out of range of a long long, + clipping to MAX_LLONG or MIN_LLONG. */ + +long long int +__llround (long double x) +{ + long double xrf; + long long int xr; + xr = (long long int) x; + xrf = (long double) xr; + if (x >= 0.0) + if (x - xrf >= 0.5 && x - xrf < 1.0 && x+1 > 0) + return x+1; + else + return x; + else + if (xrf - x >= 0.5 && xrf - x < 1.0 && x-1 < 0) + return x-1; + else + return x; +} +weak_alias (__llround, llround) diff --git a/sysdeps/powerpc/s_lrint.c b/sysdeps/powerpc/s_lrint.c new file mode 100644 index 0000000..647cf30 --- /dev/null +++ b/sysdeps/powerpc/s_lrint.c @@ -0,0 +1,44 @@ +/* Round floating-point to integer. PowerPC version. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include "math.h" + +#ifdef NO_LONG_DOUBLE + +long int +__lrint (long double x) +{ + return (long int) __rintl(x); +} + +#else + +long int +__lrint (long double x) +{ + union { + double d; + long int ll[2]; + } u; + asm ("fctiw %0,%1" : "=f"(u.d) : "f"(x)); + return d.ll[1]; +} + +#endif +weak_alias (__lrint, lrint) diff --git a/sysdeps/powerpc/s_lround.c b/sysdeps/powerpc/s_lround.c new file mode 100644 index 0000000..a6cb6c9 --- /dev/null +++ b/sysdeps/powerpc/s_lround.c @@ -0,0 +1,46 @@ +/* Round long double value to long int. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <math.h> + +/* I think that what this routine is supposed to do is round a value + to the nearest integer, with values exactly on the boundary rounded + away from zero. */ +/* This routine relies on (long int)x, when x is out of range of a long int, + clipping to MAX_LONG or MIN_LONG. */ + +long int +__lround (long double x) +{ + long double xrf; + long int xr; + xr = (long int) x; + xrf = (long double) xr; + if (x >= 0.0) + if (x - xrf >= 0.5 && x - xrf < 1.0 && x+1 > 0) + return x+1; + else + return x; + else + if (xrf - x >= 0.5 && xrf - x < 1.0 && x-1 < 0) + return x-1; + else + return x; +} +weak_alias (__lround, lround) diff --git a/sysdeps/powerpc/s_rint.c b/sysdeps/powerpc/s_rint.c new file mode 100644 index 0000000..d6d1dd2 --- /dev/null +++ b/sysdeps/powerpc/s_rint.c @@ -0,0 +1,45 @@ +/* Round a 64-bit floating point value to the nearest integer. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include "math.h" + +double +__rint (double x) +{ + static const float TWO52 = 4503599627370496.0; + + if (fabs (x) < TWO52) + if (x > 0.0) + { + x += TWO52; + x -= TWO52; + } + else if (x < 0.0) + { + x -= TWO52; + x += TWO52; + } + + return x; +} +weak_alias (__rint, rint) +#ifdef NO_LONG_DOUBLE +strong_alias (__rint, __rintl) +weak_alias (__rint, rintl) +#endif diff --git a/sysdeps/powerpc/s_rintf.c b/sysdeps/powerpc/s_rintf.c new file mode 100644 index 0000000..b95c054 --- /dev/null +++ b/sysdeps/powerpc/s_rintf.c @@ -0,0 +1,41 @@ +/* Round a 32-bit floating point value to the nearest integer. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include "math.h" + +float +__rintf (float x) +{ + static const float TWO23 = 8388608.0; + + if (fabsf (x) < TWO23) + if (x > 0.0) + { + x += TWO23; + x -= TWO23; + } + else if (x < 0.0) + { + x -= TWO23; + x += TWO23; + } + + return x; +} +weak_alias (__rintf, rintf) diff --git a/sysdeps/powerpc/strlen.s b/sysdeps/powerpc/strlen.s index 9d671ca..ea80977 100644 --- a/sysdeps/powerpc/strlen.s +++ b/sysdeps/powerpc/strlen.s @@ -61,8 +61,8 @@ # Some notes on register usage: Under the SVR4 ABI, we can use registers # 0 and 3 through 12 (so long as we don't call any procedures) without # saving them. We can also use registers 14 through 31 if we save them. - # We can't use r1 (it's the stack pointer), nor r2 or r13 because the user - # program may expect them to be hold their usual value if we get sent + # We can't use r1 (it's the stack pointer), r2 nor r13 because the user + # program may expect them to hold their usual value if we get sent # a signal. Integer parameters are passed in r3 through r10. # We can use condition registers cr0, cr1, cr5, cr6, and cr7 without saving # them, the others we must save. @@ -80,14 +80,11 @@ strlen: # r9-12 are temporaries. r0 is used as a temporary and for discarded # results. clrrwi %r4,%r3,2 - lis %r6,0xfeff lis %r7,0x7f7f - rlwinm %r10,%r3,0,29,29 - lwz %r8,0(%r4) - addi %r7,%r7,0x7f7f rlwinm %r5,%r3,3,27,28 - cmpwi %cr1,%r10,0 + lwz %r8,0(%r4) li %r9,-1 + addi %r7,%r7,0x7f7f # That's the setup done, now do the first pair of words. # We make an exception and use method (2) on the first two words, to reduce # overhead. @@ -97,12 +94,14 @@ strlen: add %r0,%r0,%r7 nor %r0,%r10,%r0 and. %r8,%r0,%r9 + mtcrf 0x01,%r3 bne done0 - # Handle second word of pair. Put addi between branches to avoid hurting - # branch prediction. + lis %r6,0xfeff addi %r6,%r6,-0x101 + # Are we now aligned to a doubleword boundary? + bt 29,loop - bne %cr1,loop + # Handle second word of pair. lwzu %r8,4(%r4) and %r0,%r7,%r8 or %r10,%r7,%r8 diff --git a/sysdeps/powerpc/t_sqrt.c b/sysdeps/powerpc/t_sqrt.c new file mode 100644 index 0000000..c49380c --- /dev/null +++ b/sysdeps/powerpc/t_sqrt.c @@ -0,0 +1,144 @@ +const float __t_sqrt[1024] = { +0.7078,0.7064, 0.7092,0.7050, 0.7106,0.7037, 0.7119,0.7023, 0.7133,0.7010, +0.7147,0.6996, 0.7160,0.6983, 0.7174,0.6970, 0.7187,0.6957, 0.7201,0.6943, +0.7215,0.6930, 0.7228,0.6917, 0.7242,0.6905, 0.7255,0.6892, 0.7269,0.6879, +0.7282,0.6866, 0.7295,0.6854, 0.7309,0.6841, 0.7322,0.6829, 0.7335,0.6816, +0.7349,0.6804, 0.7362,0.6792, 0.7375,0.6779, 0.7388,0.6767, 0.7402,0.6755, +0.7415,0.6743, 0.7428,0.6731, 0.7441,0.6719, 0.7454,0.6708, 0.7467,0.6696, +0.7480,0.6684, 0.7493,0.6672, 0.7507,0.6661, 0.7520,0.6649, 0.7532,0.6638, +0.7545,0.6627, 0.7558,0.6615, 0.7571,0.6604, 0.7584,0.6593, 0.7597,0.6582, +0.7610,0.6570, 0.7623,0.6559, 0.7635,0.6548, 0.7648,0.6537, 0.7661,0.6527, +0.7674,0.6516, 0.7686,0.6505, 0.7699,0.6494, 0.7712,0.6484, 0.7725,0.6473, +0.7737,0.6462, 0.7750,0.6452, 0.7762,0.6441, 0.7775,0.6431, 0.7787,0.6421, +0.7800,0.6410, 0.7812,0.6400, 0.7825,0.6390, 0.7837,0.6380, 0.7850,0.6370, +0.7862,0.6359, 0.7875,0.6349, 0.7887,0.6339, 0.7900,0.6330, 0.7912,0.6320, +0.7924,0.6310, 0.7937,0.6300, 0.7949,0.6290, 0.7961,0.6281, 0.7973,0.6271, +0.7986,0.6261, 0.7998,0.6252, 0.8010,0.6242, 0.8022,0.6233, 0.8034,0.6223, +0.8046,0.6214, 0.8059,0.6205, 0.8071,0.6195, 0.8083,0.6186, 0.8095,0.6177, +0.8107,0.6168, 0.8119,0.6158, 0.8131,0.6149, 0.8143,0.6140, 0.8155,0.6131, +0.8167,0.6122, 0.8179,0.6113, 0.8191,0.6104, 0.8203,0.6096, 0.8215,0.6087, +0.8227,0.6078, 0.8238,0.6069, 0.8250,0.6060, 0.8262,0.6052, 0.8274,0.6043, +0.8286,0.6035, 0.8297,0.6026, 0.8309,0.6017, 0.8321,0.6009, 0.8333,0.6000, +0.8344,0.5992, 0.8356,0.5984, 0.8368,0.5975, 0.8379,0.5967, 0.8391,0.5959, +0.8403,0.5950, 0.8414,0.5942, 0.8426,0.5934, 0.8437,0.5926, 0.8449,0.5918, +0.8461,0.5910, 0.8472,0.5902, 0.8484,0.5894, 0.8495,0.5886, 0.8507,0.5878, +0.8518,0.5870, 0.8530,0.5862, 0.8541,0.5854, 0.8552,0.5846, 0.8564,0.5838, +0.8575,0.5831, 0.8587,0.5823, 0.8598,0.5815, 0.8609,0.5808, 0.8621,0.5800, +0.8632,0.5792, 0.8643,0.5785, 0.8655,0.5777, 0.8666,0.5770, 0.8677,0.5762, +0.8688,0.5755, 0.8700,0.5747, 0.8711,0.5740, 0.8722,0.5733, 0.8733,0.5725, +0.8744,0.5718, 0.8756,0.5711, 0.8767,0.5703, 0.8778,0.5696, 0.8789,0.5689, +0.8800,0.5682, 0.8811,0.5675, 0.8822,0.5667, 0.8833,0.5660, 0.8844,0.5653, +0.8855,0.5646, 0.8866,0.5639, 0.8877,0.5632, 0.8888,0.5625, 0.8899,0.5618, +0.8910,0.5611, 0.8921,0.5605, 0.8932,0.5598, 0.8943,0.5591, 0.8954,0.5584, +0.8965,0.5577, 0.8976,0.5570, 0.8987,0.5564, 0.8998,0.5557, 0.9008,0.5550, +0.9019,0.5544, 0.9030,0.5537, 0.9041,0.5530, 0.9052,0.5524, 0.9062,0.5517, +0.9073,0.5511, 0.9084,0.5504, 0.9095,0.5498, 0.9105,0.5491, 0.9116,0.5485, +0.9127,0.5478, 0.9138,0.5472, 0.9148,0.5465, 0.9159,0.5459, 0.9170,0.5453, +0.9180,0.5446, 0.9191,0.5440, 0.9202,0.5434, 0.9212,0.5428, 0.9223,0.5421, +0.9233,0.5415, 0.9244,0.5409, 0.9254,0.5403, 0.9265,0.5397, 0.9276,0.5391, +0.9286,0.5384, 0.9297,0.5378, 0.9307,0.5372, 0.9318,0.5366, 0.9328,0.5360, +0.9338,0.5354, 0.9349,0.5348, 0.9359,0.5342, 0.9370,0.5336, 0.9380,0.5330, +0.9391,0.5324, 0.9401,0.5319, 0.9411,0.5313, 0.9422,0.5307, 0.9432,0.5301, +0.9442,0.5295, 0.9453,0.5289, 0.9463,0.5284, 0.9473,0.5278, 0.9484,0.5272, +0.9494,0.5266, 0.9504,0.5261, 0.9515,0.5255, 0.9525,0.5249, 0.9535,0.5244, +0.9545,0.5238, 0.9556,0.5233, 0.9566,0.5227, 0.9576,0.5221, 0.9586,0.5216, +0.9596,0.5210, 0.9607,0.5205, 0.9617,0.5199, 0.9627,0.5194, 0.9637,0.5188, +0.9647,0.5183, 0.9657,0.5177, 0.9667,0.5172, 0.9677,0.5167, 0.9687,0.5161, +0.9698,0.5156, 0.9708,0.5151, 0.9718,0.5145, 0.9728,0.5140, 0.9738,0.5135, +0.9748,0.5129, 0.9758,0.5124, 0.9768,0.5119, 0.9778,0.5114, 0.9788,0.5108, +0.9798,0.5103, 0.9808,0.5098, 0.9818,0.5093, 0.9828,0.5088, 0.9838,0.5083, +0.9847,0.5077, 0.9857,0.5072, 0.9867,0.5067, 0.9877,0.5062, 0.9887,0.5057, +0.9897,0.5052, 0.9907,0.5047, 0.9917,0.5042, 0.9926,0.5037, 0.9936,0.5032, +0.9946,0.5027, 0.9956,0.5022, 0.9966,0.5017, 0.9976,0.5012, 0.9985,0.5007, +0.9995,0.5002, +1.0010,0.4995, 1.0029,0.4985, 1.0049,0.4976, 1.0068,0.4966, 1.0088,0.4957, +1.0107,0.4947, 1.0126,0.4938, 1.0145,0.4928, 1.0165,0.4919, 1.0184,0.4910, +1.0203,0.4901, 1.0222,0.4891, 1.0241,0.4882, 1.0260,0.4873, 1.0279,0.4864, +1.0298,0.4855, 1.0317,0.4846, 1.0336,0.4837, 1.0355,0.4829, 1.0374,0.4820, +1.0393,0.4811, 1.0411,0.4802, 1.0430,0.4794, 1.0449,0.4785, 1.0468,0.4777, +1.0486,0.4768, 1.0505,0.4760, 1.0523,0.4751, 1.0542,0.4743, 1.0560,0.4735, +1.0579,0.4726, 1.0597,0.4718, 1.0616,0.4710, 1.0634,0.4702, 1.0653,0.4694, +1.0671,0.4686, 1.0689,0.4678, 1.0707,0.4670, 1.0726,0.4662, 1.0744,0.4654, +1.0762,0.4646, 1.0780,0.4638, 1.0798,0.4630, 1.0816,0.4623, 1.0834,0.4615, +1.0852,0.4607, 1.0870,0.4600, 1.0888,0.4592, 1.0906,0.4585, 1.0924,0.4577, +1.0942,0.4570, 1.0960,0.4562, 1.0978,0.4555, 1.0995,0.4547, 1.1013,0.4540, +1.1031,0.4533, 1.1049,0.4525, 1.1066,0.4518, 1.1084,0.4511, 1.1101,0.4504, +1.1119,0.4497, 1.1137,0.4490, 1.1154,0.4483, 1.1172,0.4476, 1.1189,0.4469, +1.1207,0.4462, 1.1224,0.4455, 1.1241,0.4448, 1.1259,0.4441, 1.1276,0.4434, +1.1293,0.4427, 1.1311,0.4421, 1.1328,0.4414, 1.1345,0.4407, 1.1362,0.4401, +1.1379,0.4394, 1.1397,0.4387, 1.1414,0.4381, 1.1431,0.4374, 1.1448,0.4368, +1.1465,0.4361, 1.1482,0.4355, 1.1499,0.4348, 1.1516,0.4342, 1.1533,0.4335, +1.1550,0.4329, 1.1567,0.4323, 1.1584,0.4316, 1.1600,0.4310, 1.1617,0.4304, +1.1634,0.4298, 1.1651,0.4292, 1.1668,0.4285, 1.1684,0.4279, 1.1701,0.4273, +1.1718,0.4267, 1.1734,0.4261, 1.1751,0.4255, 1.1768,0.4249, 1.1784,0.4243, +1.1801,0.4237, 1.1817,0.4231, 1.1834,0.4225, 1.1850,0.4219, 1.1867,0.4213, +1.1883,0.4208, 1.1900,0.4202, 1.1916,0.4196, 1.1932,0.4190, 1.1949,0.4185, +1.1965,0.4179, 1.1981,0.4173, 1.1998,0.4167, 1.2014,0.4162, 1.2030,0.4156, +1.2046,0.4151, 1.2063,0.4145, 1.2079,0.4139, 1.2095,0.4134, 1.2111,0.4128, +1.2127,0.4123, 1.2143,0.4117, 1.2159,0.4112, 1.2175,0.4107, 1.2192,0.4101, +1.2208,0.4096, 1.2224,0.4090, 1.2239,0.4085, 1.2255,0.4080, 1.2271,0.4075, +1.2287,0.4069, 1.2303,0.4064, 1.2319,0.4059, 1.2335,0.4054, 1.2351,0.4048, +1.2366,0.4043, 1.2382,0.4038, 1.2398,0.4033, 1.2414,0.4028, 1.2429,0.4023, +1.2445,0.4018, 1.2461,0.4013, 1.2477,0.4008, 1.2492,0.4003, 1.2508,0.3998, +1.2523,0.3993, 1.2539,0.3988, 1.2555,0.3983, 1.2570,0.3978, 1.2586,0.3973, +1.2601,0.3968, 1.2617,0.3963, 1.2632,0.3958, 1.2648,0.3953, 1.2663,0.3949, +1.2678,0.3944, 1.2694,0.3939, 1.2709,0.3934, 1.2725,0.3929, 1.2740,0.3925, +1.2755,0.3920, 1.2771,0.3915, 1.2786,0.3911, 1.2801,0.3906, 1.2816,0.3901, +1.2832,0.3897, 1.2847,0.3892, 1.2862,0.3887, 1.2877,0.3883, 1.2892,0.3878, +1.2907,0.3874, 1.2923,0.3869, 1.2938,0.3865, 1.2953,0.3860, 1.2968,0.3856, +1.2983,0.3851, 1.2998,0.3847, 1.3013,0.3842, 1.3028,0.3838, 1.3043,0.3834, +1.3058,0.3829, 1.3073,0.3825, 1.3088,0.3820, 1.3103,0.3816, 1.3118,0.3812, +1.3132,0.3807, 1.3147,0.3803, 1.3162,0.3799, 1.3177,0.3794, 1.3192,0.3790, +1.3207,0.3786, 1.3221,0.3782, 1.3236,0.3778, 1.3251,0.3773, 1.3266,0.3769, +1.3280,0.3765, 1.3295,0.3761, 1.3310,0.3757, 1.3324,0.3753, 1.3339,0.3748, +1.3354,0.3744, 1.3368,0.3740, 1.3383,0.3736, 1.3397,0.3732, 1.3412,0.3728, +1.3427,0.3724, 1.3441,0.3720, 1.3456,0.3716, 1.3470,0.3712, 1.3485,0.3708, +1.3499,0.3704, 1.3514,0.3700, 1.3528,0.3696, 1.3542,0.3692, 1.3557,0.3688, +1.3571,0.3684, 1.3586,0.3680, 1.3600,0.3676, 1.3614,0.3673, 1.3629,0.3669, +1.3643,0.3665, 1.3657,0.3661, 1.3672,0.3657, 1.3686,0.3653, 1.3700,0.3650, +1.3714,0.3646, 1.3729,0.3642, 1.3743,0.3638, 1.3757,0.3634, 1.3771,0.3631, +1.3785,0.3627, 1.3800,0.3623, 1.3814,0.3620, 1.3828,0.3616, 1.3842,0.3612, +1.3856,0.3609, 1.3870,0.3605, 1.3884,0.3601, 1.3898,0.3598, 1.3912,0.3594, +1.3926,0.3590, 1.3940,0.3587, 1.3954,0.3583, 1.3968,0.3580, 1.3982,0.3576, +1.3996,0.3572, 1.4010,0.3569, 1.4024,0.3565, 1.4038,0.3562, 1.4052,0.3558, +1.4066,0.3555, 1.4080,0.3551, 1.4094,0.3548, 1.4108,0.3544, 1.4121,0.3541, +1.4135,0.3537 +}; + + +/* Generated by: */ +#if 0 +#include <math.h> +#include <stdio.h> +#include <assert.h> + +int +main(int argc, char **argv) +{ + int i, j; + + printf ("const float __t_sqrt[1024] = {"); + for (i = 0; i < 2; i++) + { + putchar('\n'); + for (j = 0; j < 256; j++) + { + double mval = j/512.0 + 0.5; + double eval = i==0 ? 1.0 : 2.0; + double ls = sqrt(mval*eval); + double hs = sqrt((mval+1/512.0)*eval); + double as = (ls+hs)*0.5; + double lx = 1/(2.0*ls); + double hx = 1/(2.0*hs); + double ax = (lx+hx)*0.5; + + printf("%.4f,%.4f%s",as,ax, + i*j==255 ? "\n" : j % 5 == 4 ? ",\n" : ", "); + assert((hs-ls)/as < 1/256.0); + assert((hx-lx)/ax < 1/256.0); + } + } + printf ("};\n"); + return 0; +} +#endif /* 0 */ diff --git a/sysdeps/powerpc/test-arith.c b/sysdeps/powerpc/test-arith.c new file mode 100644 index 0000000..c846b0d --- /dev/null +++ b/sysdeps/powerpc/test-arith.c @@ -0,0 +1,604 @@ +/* Test floating-point arithmetic operations. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fenv.h> +#include <assert.h> + +#ifndef ESIZE +typedef double tocheck_t; +#define ESIZE 11 +#define MSIZE 52 +#define FUNC(x) x +#endif + +#define R_NEAREST 1 +#define R_ZERO 2 +#define R_UP 4 +#define R_DOWN 8 +#define R_ALL (R_NEAREST|R_ZERO|R_UP|R_DOWN) +static fenv_t rmodes[4]; +static const char * const rmnames[4] = +{ "nearest","zero","+Inf","-Inf" }; + +typedef union { + tocheck_t tc; + unsigned char c[sizeof(tocheck_t)]; +} union_t; + +/* Don't try reading these in a font that doesn't distinguish + O and zero. */ +typedef enum { + P_Z = 0x0, /* 00000...0 */ + P_000O = 0x1, /* 00011...1 */ + P_001Z = 0x2, /* 00100...0 */ + P_00O = 0x3, /* 00111...1 */ + P_01Z = 0x4, /* 01000...0 */ + P_010O = 0x5, /* 01011...1 */ + P_011Z = 0x6, /* 01100...0 */ + P_0O = 0x7, /* 01111...1 */ + P_1Z = 0x8, /* 10000...0 */ + P_100O = 0x9, /* 10011...1 */ + P_101Z = 0xa, /* 10100...0 */ + P_10O = 0xb, /* 10111...1 */ + P_11Z = 0xc, /* 11000...0 */ + P_110O = 0xd, /* 11011...1 */ + P_111Z = 0xe, /* 11100...0 */ + P_O = 0xf, /* 11111...1 */ + P_Z1 = 0x11, /* 000...001 */ + P_Z10 = 0x12, /* 000...010 */ + P_Z11 = 0x13, /* 000...011 */ + P_0O00 = 0x14, /* 011...100 */ + P_0O01 = 0x15, /* 011...101 */ + P_0O0 = 0x16, /* 011...110 */ + P_1Z1 = 0x19, /* 100...001 */ + P_1Z10 = 0x1a, /* 100...010 */ + P_1Z11 = 0x1b, /* 100...011 */ + P_O00 = 0x1c, /* 111...100 */ + P_O01 = 0x1d, /* 111...101 */ + P_O0 = 0x1e, /* 111...110 */ + P_R = 0x20, /* rrr...rrr */ /* ('r' means random. ) */ + P_Ro = 0x21, /* rrr...rrr, with odd parity. */ + P_0R = 0x22, /* 0rr...rrr */ + P_1R = 0x23, /* 1rr...rrr */ + P_Rno = 0x24, /* rrr...rrr, but not all ones. */ +} pattern_t; + +static void +pattern_fill(pattern_t ptn, unsigned char *start, int bitoffset, int count) +{ +#define bitset(count, value) \ + start[(count)/8] = (start[(count)/8] & ~(1 << 7-(count)%8) \ + | (value) << 7-(count)%8) + int i; + + if (ptn >= 0 && ptn <= 0xf) + { + /* Patterns between 0 and 0xF have the following format: + The LSBit is used to fill the last n-3 bits of the pattern; + The next 3 bits are the first 3 bits of the pattern. */ + for (i = 0; i < count; i++) + if (i < 3) + bitset((bitoffset+i), ptn >> (3-i) & 1); + else + bitset((bitoffset+i), ptn >> 0 & 1); + } + else if (ptn <= 0x1f) + { + /* Patterns between 0x10 and 0x1F have the following format: + The two LSBits are the last two bits of the pattern; + The 0x8 bit is the first bit of the pattern; + The 0x4 bit is used to fill the remainder. */ + for (i = 0; i < count; i++) + if (i == 0) + bitset((bitoffset+i), ptn >> 3 & 1); + else if (i >= count-2) + bitset((bitoffset+i), ptn >> (count-1-i) & 1); + else + bitset((bitoffset+i), ptn >> 2 & 1); + } + else switch (ptn) + { + case P_0R: case P_1R: + assert(count > 0); + bitset(bitoffset, ptn & 1); + count--; + bitoffset++; + case P_R: + for (; count > 0; count--, bitoffset++) + bitset(bitoffset, rand() & 1); + break; + case P_Ro: + { + int op = 1; + assert(count > 0); + for (; count > 1; count--, bitoffset++) + bitset(bitoffset, op ^= (rand() & 1)); + bitset(bitoffset, op); + break; + } + case P_Rno: + { + int op = 1; + assert(count > 0); + for (; count > 1; count--, bitoffset++) + { + int r = rand() & 1; + op &= r; + bitset(bitoffset, r); + } + bitset(bitoffset, rand() & (op ^ 1)); + break; + } + + default: + assert(0); + } +#undef bitset +} + +static tocheck_t +pattern(int negative, pattern_t exp, pattern_t mant) +{ + union_t result; +#if 0 + int i; +#endif + + pattern_fill(negative ? P_O : P_Z, result.c, 0, 1); + pattern_fill(exp, result.c, 1, ESIZE); + pattern_fill(mant, result.c, ESIZE+1, MSIZE); +#if 0 + printf("neg=%d exp=%02x mant=%02x: ", negative, exp, mant); + for (i = 0; i < sizeof(tocheck_t); i++) + printf("%02x", result.c[i]); + printf("\n"); +#endif + return result.tc; +} + +/* Return the closest different tocheck_t to 'x' in the direction of + 'direction', or 'x' if there is no such value. Assumes 'x' is not + a NaN. */ +static tocheck_t +delta(tocheck_t x, int direction) +{ + union_t xx; + int i; + + xx.tc = x; + if (xx.c[0] & 0x80) + direction = -direction; + if (direction == +1) + { + union_t tx; + tx.tc = pattern(xx.c[0] >> 7, P_O, P_Z); + if (memcmp(tx.c, xx.c, sizeof(tocheck_t)) == 0) + return x; + } + for (i = sizeof(tocheck_t)-1; i > 0; i--) + { + xx.c[i] += direction; + if (xx.c[i] != (direction > 0 ? 0 : 0xff)) + return xx.tc; + } + if (direction < 0 && (xx.c[0] & 0x7f) == 0) + return pattern(~(xx.c[0] >> 7) & 1, P_Z, P_Z1); + else + { + xx.c[0] += direction; + return xx.tc; + } +} + +static int nerrors = 0; + +#ifdef FE_ALL_INVALID +static const int all_exceptions = FE_ALL_INVALID | FE_ALL_EXCEPT; +#else +static const int all_exceptions = FE_ALL_EXCEPT; +#endif + +static void +check_result(int line, const char *rm, tocheck_t expected, tocheck_t actual) +{ + if (memcmp(&expected, &actual, sizeof(tocheck_t)) != 0) + { + unsigned char *ex, *ac; + int i; + + printf("%s:%d:round %s:result failed\n" + " expected result 0x", __FILE__, line, rm); + ex = (unsigned char *)&expected; + ac = (unsigned char *)&actual; + for (i = 0; i < sizeof(tocheck_t); i++) + printf("%02x", ex[i]); + printf(" got 0x"); + for (i = 0; i < sizeof(tocheck_t); i++) + printf("%02x", ac[i]); + printf("\n"); + nerrors++; + } +} + +static const struct { + int except; + const char *name; +} excepts[] = { +#define except_entry(ex) { ex, #ex } , +#ifdef FE_INEXACT + except_entry(FE_INEXACT) +#else +# define FE_INEXACT 0 +#endif +#ifdef FE_DIVBYZERO + except_entry(FE_DIVBYZERO) +#else +# define FE_DIVBYZERO 0 +#endif +#ifdef FE_UNDERFLOW + except_entry(FE_UNDERFLOW) +#else +# define FE_UNDERFLOW 0 +#endif +#ifdef FE_OVERFLOW + except_entry(FE_OVERFLOW) +#else +# define FE_OVERFLOW 0 +#endif +#ifdef FE_INVALID + except_entry(FE_INVALID) +#else +# define FE_INVALID 0 +#endif +#ifdef FE_INVALID_SNAN + except_entry(FE_INVALID_SNAN) +#else +# define FE_INVALID_SNAN FE_INVALID +#endif +#ifdef FE_INVALID_ISI + except_entry(FE_INVALID_ISI) +#else +# define FE_INVALID_ISI FE_INVALID +#endif +#ifdef FE_INVALID_IDI + except_entry(FE_INVALID_IDI) +#else +# define FE_INVALID_IDI FE_INVALID +#endif +#ifdef FE_INVALID_ZDZ + except_entry(FE_INVALID_ZDZ) +#else +# define FE_INVALID_ZDZ FE_INVALID +#endif +#ifdef FE_INVALID_COMPARE + except_entry(FE_INVALID_COMPARE) +#else +# define FE_INVALID_COMPARE FE_INVALID +#endif +#ifdef FE_INVALID_SOFTWARE + except_entry(FE_INVALID_SOFTWARE) +#else +# define FE_INVALID_SOFTWARE FE_INVALID +#endif +#ifdef FE_INVALID_SQRT + except_entry(FE_INVALID_SQRT) +#else +# define FE_INVALID_SQRT FE_INVALID +#endif +#ifdef FE_INVALID_INTEGER_CONVERSION + except_entry(FE_INVALID_INTEGER_CONVERSION) +#else +# define FE_INVALID_INTEGER_CONVERSION FE_INVALID +#endif +}; + +static int excepts_missing = 0; + +static void +check_excepts(int line, const char *rm, int expected, int actual) +{ + if (expected & excepts_missing) + expected = expected & ~excepts_missing | FE_INVALID_SNAN; + if ((expected & all_exceptions) != actual) + { + int i; + printf("%s:%d:round %s:exceptions failed\n" + " expected exceptions ", __FILE__, line,rm); + for (i = 0; i < sizeof(excepts)/sizeof(excepts[0]); i++) + if (expected & excepts[i].except) + printf("%s ",excepts[i].name); + if ((expected & all_exceptions) == 0) + printf("- "); + printf("got"); + for (i = 0; i < sizeof(excepts)/sizeof(excepts[0]); i++) + if (actual & excepts[i].except) + printf(" %s",excepts[i].name); + if ((actual & all_exceptions) == 0) + printf("- "); + printf(".\n"); + nerrors++; + } +} + +typedef enum { + B_ADD, B_SUB, B_MUL, B_DIV, B_NEG, B_ABS, B_SQRT +} op_t; +typedef struct { + int line; + op_t op; + int a_sgn; + pattern_t a_exp, a_mant; + int b_sgn; + pattern_t b_exp, b_mant; + int rmode; + int excepts; + int x_sgn; + pattern_t x_exp, x_mant; +} optest_t; +static const optest_t optests[] = { + /* Additions of zero. */ + {__LINE__,B_ADD, 0,P_Z,P_Z, 0,P_Z,P_Z, R_ALL,0, 0,P_Z,P_Z }, + {__LINE__,B_ADD, 1,P_Z,P_Z, 0,P_Z,P_Z, R_ALL & ~R_DOWN,0, 0,P_Z,P_Z }, + {__LINE__,B_ADD, 1,P_Z,P_Z, 0,P_Z,P_Z, R_DOWN,0, 1,P_Z,P_Z }, + {__LINE__,B_ADD, 1,P_Z,P_Z, 1,P_Z,P_Z, R_ALL,0, 1,P_Z,P_Z }, + + /* Additions with NaN. */ + {__LINE__,B_ADD, 0,P_O,P_101Z, 0,P_Z,P_Z, R_ALL,0, 0,P_O,P_101Z }, + {__LINE__,B_ADD, 0,P_O,P_01Z, 0,P_Z,P_Z, R_ALL, + FE_INVALID | FE_INVALID_SNAN, 0,P_O,P_11Z }, + {__LINE__,B_ADD, 0,P_O,P_Z, 0,P_O,P_0O, R_ALL, + FE_INVALID | FE_INVALID_SNAN, 0,P_O,P_O }, + {__LINE__,B_ADD, 0,P_Z,P_Z, 0,P_O,P_11Z, R_ALL,0, 0,P_O,P_11Z }, + {__LINE__,B_ADD, 0,P_O,P_001Z, 0,P_O,P_001Z, R_ALL, + FE_INVALID | FE_INVALID_SNAN, 0,P_O,P_101Z }, + {__LINE__,B_ADD, 0,P_O,P_1Z, 0,P_Z,P_Z, R_ALL,0, 0,P_O,P_1Z }, + {__LINE__,B_ADD, 0,P_0O,P_Z, 0,P_O,P_10O, R_ALL,0, 0,P_O,P_10O }, + + /* Additions with infinity. */ + {__LINE__,B_ADD, 0,P_O,P_Z, 0,P_Z,P_Z, R_ALL,0, 0,P_O,P_Z }, + {__LINE__,B_ADD, 0,P_O,P_Z, 1,P_Z,P_Z, R_ALL,0, 0,P_O,P_Z }, + {__LINE__,B_ADD, 1,P_O,P_Z, 0,P_Z,P_Z, R_ALL,0, 1,P_O,P_Z }, + {__LINE__,B_ADD, 1,P_O,P_Z, 1,P_Z,P_Z, R_ALL,0, 1,P_O,P_Z }, + {__LINE__,B_ADD, 0,P_O,P_Z, 0,P_O,P_Z, R_ALL,0, 0,P_O,P_Z }, + {__LINE__,B_ADD, 1,P_O,P_Z, 1,P_O,P_Z, R_ALL,0, 1,P_O,P_Z }, + {__LINE__,B_ADD, 0,P_O,P_Z, 1,P_O,P_Z, R_ALL, + FE_INVALID | FE_INVALID_ISI, 0,P_O,P_1Z }, + {__LINE__,B_ADD, 1,P_O,P_Z, 0,P_O,P_Z, R_ALL, + FE_INVALID | FE_INVALID_ISI, 0,P_O,P_1Z }, + {__LINE__,B_ADD, 0,P_O,P_Z, 0,P_0O,P_Z, R_ALL,0, 0,P_O,P_Z }, + {__LINE__,B_ADD, 1,P_O,P_Z, 0,P_0O,P_Z, R_ALL,0, 1,P_O,P_Z }, + {__LINE__,B_ADD, 0,P_O,P_Z, 1,P_0O,P_Z, R_ALL,0, 0,P_O,P_Z }, + {__LINE__,B_ADD, 1,P_O,P_Z, 1,P_0O,P_Z, R_ALL,0, 1,P_O,P_Z }, + + /* Overflow (and zero). */ + {__LINE__,B_ADD, 0,P_O0,P_Z, 0,P_O0,P_Z, R_NEAREST | R_UP, + FE_INEXACT | FE_OVERFLOW, 0,P_O,P_Z }, + {__LINE__,B_ADD, 0,P_O0,P_Z, 0,P_O0,P_Z, R_ZERO | R_DOWN, + FE_INEXACT | FE_OVERFLOW, 0,P_O0,P_O }, + {__LINE__,B_ADD, 1,P_O0,P_Z, 1,P_O0,P_Z, R_NEAREST | R_DOWN, + FE_INEXACT | FE_OVERFLOW, 1,P_O,P_Z }, + {__LINE__,B_ADD, 1,P_O0,P_Z, 1,P_O0,P_Z, R_ZERO | R_UP, + FE_INEXACT | FE_OVERFLOW, 1,P_O0,P_O }, + {__LINE__,B_ADD, 0,P_O0,P_Z, 1,P_O0,P_Z, R_ALL & ~R_DOWN, + 0, 0,P_Z,P_Z }, + {__LINE__,B_ADD, 0,P_O0,P_Z, 1,P_O0,P_Z, R_DOWN, + 0, 1,P_Z,P_Z }, + + /* Negation. */ + {__LINE__,B_NEG, 0,P_Z,P_Z, 0,0,0, R_ALL, 0, 1,P_Z,P_Z }, + {__LINE__,B_NEG, 1,P_Z,P_Z, 0,0,0, R_ALL, 0, 0,P_Z,P_Z }, + {__LINE__,B_NEG, 0,P_O,P_Z, 0,0,0, R_ALL, 0, 1,P_O,P_Z }, + {__LINE__,B_NEG, 1,P_O,P_Z, 0,0,0, R_ALL, 0, 0,P_O,P_Z }, + {__LINE__,B_NEG, 0,P_O,P_1Z, 0,0,0, R_ALL, 0, 1,P_O,P_1Z }, + {__LINE__,B_NEG, 1,P_O,P_1Z, 0,0,0, R_ALL, 0, 0,P_O,P_1Z }, + {__LINE__,B_NEG, 0,P_O,P_01Z, 0,0,0, R_ALL, 0, 1,P_O,P_01Z }, + {__LINE__,B_NEG, 1,P_O,P_01Z, 0,0,0, R_ALL, 0, 0,P_O,P_01Z }, + {__LINE__,B_NEG, 0,P_1Z,P_1Z1, 0,0,0, R_ALL, 0, 1,P_1Z,P_1Z1 }, + {__LINE__,B_NEG, 1,P_1Z,P_1Z1, 0,0,0, R_ALL, 0, 0,P_1Z,P_1Z1 }, + {__LINE__,B_NEG, 0,P_Z,P_Z1, 0,0,0, R_ALL, 0, 1,P_Z,P_Z1 }, + {__LINE__,B_NEG, 1,P_Z,P_Z1, 0,0,0, R_ALL, 0, 0,P_Z,P_Z1 }, + + /* Absolute value. */ + {__LINE__,B_ABS, 0,P_Z,P_Z, 0,0,0, R_ALL, 0, 0,P_Z,P_Z }, + {__LINE__,B_ABS, 1,P_Z,P_Z, 0,0,0, R_ALL, 0, 0,P_Z,P_Z }, + {__LINE__,B_ABS, 0,P_O,P_Z, 0,0,0, R_ALL, 0, 0,P_O,P_Z }, + {__LINE__,B_ABS, 1,P_O,P_Z, 0,0,0, R_ALL, 0, 0,P_O,P_Z }, + {__LINE__,B_ABS, 0,P_O,P_1Z, 0,0,0, R_ALL, 0, 0,P_O,P_1Z }, + {__LINE__,B_ABS, 1,P_O,P_1Z, 0,0,0, R_ALL, 0, 0,P_O,P_1Z }, + {__LINE__,B_ABS, 0,P_O,P_01Z, 0,0,0, R_ALL, 0, 0,P_O,P_01Z }, + {__LINE__,B_ABS, 1,P_O,P_01Z, 0,0,0, R_ALL, 0, 0,P_O,P_01Z }, + {__LINE__,B_ABS, 0,P_1Z,P_1Z1, 0,0,0, R_ALL, 0, 0,P_1Z,P_1Z1 }, + {__LINE__,B_ABS, 1,P_1Z,P_1Z1, 0,0,0, R_ALL, 0, 0,P_1Z,P_1Z1 }, + {__LINE__,B_ABS, 0,P_Z,P_Z1, 0,0,0, R_ALL, 0, 0,P_Z,P_Z1 }, + {__LINE__,B_ABS, 1,P_Z,P_Z1, 0,0,0, R_ALL, 0, 0,P_Z,P_Z1 }, + + /* Square root. */ + {__LINE__,B_SQRT, 0,P_Z,P_Z, 0,0,0, R_ALL, 0, 0,P_Z,P_Z }, + {__LINE__,B_SQRT, 1,P_Z,P_Z, 0,0,0, R_ALL, 0, 1,P_Z,P_Z }, + {__LINE__,B_SQRT, 0,P_O,P_1Z, 0,0,0, R_ALL, 0, 0,P_O,P_1Z }, + {__LINE__,B_SQRT, 1,P_O,P_1Z, 0,0,0, R_ALL, 0, 1,P_O,P_1Z }, + {__LINE__,B_SQRT, 0,P_O,P_01Z, 0,0,0, R_ALL, + FE_INVALID | FE_INVALID_SNAN, 0,P_O,P_11Z }, + {__LINE__,B_SQRT, 1,P_O,P_01Z, 0,0,0, R_ALL, + FE_INVALID | FE_INVALID_SNAN, 1,P_O,P_11Z }, + + {__LINE__,B_SQRT, 0,P_O,P_Z, 0,0,0, R_ALL, 0, 0,P_O,P_Z }, + {__LINE__,B_SQRT, 0,P_0O,P_Z, 0,0,0, R_ALL, 0, 0,P_0O,P_Z }, + + {__LINE__,B_SQRT, 1,P_O,P_Z, 0,0,0, R_ALL, + FE_INVALID | FE_INVALID_SQRT, 0,P_O,P_1Z }, + {__LINE__,B_SQRT, 1,P_1Z,P_1Z1, 0,0,0, R_ALL, + FE_INVALID | FE_INVALID_SQRT, 0,P_O,P_1Z }, + {__LINE__,B_SQRT, 1,P_Z,P_Z1, 0,0,0, R_ALL, + FE_INVALID | FE_INVALID_SQRT, 0,P_O,P_1Z }, + +}; + +static void +check_op(void) +{ + int i, j; + tocheck_t r, a, b, x; + int raised; + + for (i = 0; i < sizeof(optests)/sizeof(optests[0]); i++) + { + a = pattern(optests[i].a_sgn, optests[i].a_exp, + optests[i].a_mant); + b = pattern(optests[i].b_sgn, optests[i].b_exp, + optests[i].b_mant); + x = pattern(optests[i].x_sgn, optests[i].x_exp, + optests[i].x_mant); + for (j = 0; j < 4; j++) + if (optests[i].rmode & 1<<j) + { + fesetenv(rmodes+j); + switch (optests[i].op) + { + case B_ADD: r = a + b; break; + case B_SUB: r = a - b; break; + case B_MUL: r = a * b; break; + case B_DIV: r = a / b; break; + case B_NEG: r = -a; break; + case B_ABS: r = FUNC(fabs)(a); break; + case B_SQRT: r = FUNC(sqrt)(a); break; + } + raised = fetestexcept(all_exceptions); + check_result(optests[i].line,rmnames[j],x,r); + check_excepts(optests[i].line,rmnames[j], + optests[i].excepts,raised); + } + } +} + +static void +fail_xr(int line, const char *rm, tocheck_t x, tocheck_t r, tocheck_t xx, + int xflag) +{ + int i; + unsigned char *cx, *cr, *cxx; + + printf("%s:%d:round %s:fail\n with x=0x", __FILE__, line,rm); + cx = (unsigned char *)&x; + cr = (unsigned char *)&r; + cxx = (unsigned char *)&xx; + for (i = 0; i < sizeof(tocheck_t); i++) + printf("%02x", cx[i]); + printf(" r=0x"); + for (i = 0; i < sizeof(tocheck_t); i++) + printf("%02x", cr[i]); + printf(" xx=0x"); + for (i = 0; i < sizeof(tocheck_t); i++) + printf("%02x", cxx[i]); + printf(" inexact=%d\n", xflag != 0); + nerrors++; +} + +static void +check_sqrt(tocheck_t a) +{ + int j; + tocheck_t r0, r1, r2, x0, x1, x2; + int raised = 0; + int ok; + + for (j = 0; j < 4; j++) + { + int excepts; + + fesetenv(rmodes+j); + r1 = FUNC(sqrt)(a); + excepts = fetestexcept(all_exceptions); + fesetenv(FE_DFL_ENV); + raised |= excepts & ~FE_INEXACT; + x1 = r1 * r1 - a; + if (excepts & FE_INEXACT) + { + r0 = delta(r1,-1); r2 = delta(r1,1); + switch (1 << j) + { + case R_NEAREST: + x0 = r0 * r0 - a; x2 = r2 * r2 - a; + ok = fabs(x0) >= fabs(x1) && fabs(x1) <= fabs(x2); + break; + case R_ZERO: case R_DOWN: + x2 = r2 * r2 - a; + ok = x1 <= 0 && x2 >= 0; + break; + case R_UP: + x0 = r0 * r0 - a; + ok = x1 >= 0 && x0 <= 0; + break; + default: + assert(0); + } + } + else + ok = x1 == 0; + if (!ok) + fail_xr(__LINE__,rmnames[j],a,r1,x1,excepts&FE_INEXACT); + } + check_excepts(__LINE__,"all",0,raised); +} + +int main(int argc, char **argv) +{ + int i; + + _LIB_VERSION = _IEEE_; + + /* Set up environments for rounding modes. */ + fesetenv(FE_DFL_ENV); + fesetround(FE_TONEAREST); + fegetenv(rmodes+0); + fesetround(FE_TOWARDSZERO); + fegetenv(rmodes+1); + fesetround(FE_UPWARD); + fegetenv(rmodes+2); + fesetround(FE_DOWNWARD); + fegetenv(rmodes+3); + +#if defined(FE_INVALID_SOFTWARE) || defined(FE_INVALID_SQRT) + /* There's this really stupid feature of the 601... */ + fesetenv(FE_DFL_ENV); + feraiseexcept(FE_INVALID_SOFTWARE); + if (!fetestexcept(FE_INVALID_SOFTWARE)) + excepts_missing |= FE_INVALID_SOFTWARE; + fesetenv(FE_DFL_ENV); + feraiseexcept(FE_INVALID_SQRT); + if (!fetestexcept(FE_INVALID_SQRT)) + excepts_missing |= FE_INVALID_SQRT; +#endif + + check_op(); + for (i = 0; i < 100000; i++) + check_sqrt(pattern(0, P_Rno, P_R)); + for (i = 0; i < 100; i++) + check_sqrt(pattern(0, P_Z, P_R)); + check_sqrt(pattern(0,P_Z,P_Z1)); + + printf("%d errors.\n", nerrors); + return nerrors == 0 ? 0 : 1; +} diff --git a/sysdeps/powerpc/test-arithf.c b/sysdeps/powerpc/test-arithf.c new file mode 100644 index 0000000..d78ec49 --- /dev/null +++ b/sysdeps/powerpc/test-arithf.c @@ -0,0 +1,6 @@ +typedef float tocheck_t; +#define ESIZE 8 +#define MSIZE 23 +#define FUNC(x) x##f + +#include "test-arith.c" diff --git a/sysdeps/sparc/Dist b/sysdeps/sparc/Dist index 8bd3729..6c3b23b 100644 --- a/sysdeps/sparc/Dist +++ b/sysdeps/sparc/Dist @@ -1,3 +1,4 @@ dotmul.S umul.S divrem.m4 sdiv.S udiv.S rem.S urem.S alloca.S +sys/trap.h diff --git a/sysdeps/sparc64/elf/Dist b/sysdeps/sparc64/elf/Dist new file mode 100644 index 0000000..d9338c8 --- /dev/null +++ b/sysdeps/sparc64/elf/Dist @@ -0,0 +1,4 @@ +crtbegin.S +crtbeginS.S +crtend.S +crtendS.S diff --git a/sysdeps/standalone/arm/bits/errno.h b/sysdeps/standalone/arm/bits/errno.h index 362b43d..f5020dc 100644 --- a/sysdeps/standalone/arm/bits/errno.h +++ b/sysdeps/standalone/arm/bits/errno.h @@ -38,17 +38,19 @@ # define EMFILE 10 # define ENAMETOOLONG 11 /* File name too long */ # define ELOOP 12 /* Too many symbolic links encountered */ -# define ENOMSG 13 /* No message of desired type */ +# define ENOMSG 13 /* No message of desired type */ # define E2BIG 14 /* Arg list too long */ # define EINTR 15 # define EILSEQ 16 -# define ENOEXEC 17 +# define ENOEXEC 17 # define ENOENT 18 # define EPROTOTYPE 19 # define ESRCH 20 # define EPERM 21 -# define ENOTDIR 22 -# define ESTALE 23 +# define ENOTDIR 22 +# define ESTALE 23 +# define EISDIR 24 +# define EOPNOTSUPP 25 /* Operation not supported. */ #endif #define __set_errno(val) errno = (val) diff --git a/sysdeps/stub/bits/libc-lock.h b/sysdeps/stub/bits/libc-lock.h index 9efd799..c24dcd0 100644 --- a/sysdeps/stub/bits/libc-lock.h +++ b/sysdeps/stub/bits/libc-lock.h @@ -72,7 +72,7 @@ /* Define once control variable. */ -#define __libc_once_define(NAME) int NAME = 0 +#define __libc_once_define(CLASS, NAME) CLASS int NAME = 0 /* Call handler iff the first call. */ #define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ diff --git a/sysdeps/stub/connect.c b/sysdeps/stub/connect.c index 7fbbc7f..9152a94 100644 --- a/sysdeps/stub/connect.c +++ b/sysdeps/stub/connect.c @@ -24,7 +24,7 @@ and the only address from which to accept transmissions. Return 0 on success, -1 for errors. */ int -connect (fd, addr, len) +__connect (fd, addr, len) int fd; __CONST_SOCKADDR_ARG addr; size_t len; @@ -32,6 +32,7 @@ connect (fd, addr, len) __set_errno (ENOSYS); return -1; } +weak_alias (__connect, connect) stub_warning (connect) diff --git a/sysdeps/stub/init-first.c b/sysdeps/stub/init-first.c index 5e2cd12..4fcc67d 100644 --- a/sysdeps/stub/init-first.c +++ b/sysdeps/stub/init-first.c @@ -1,5 +1,5 @@ /* Initialization code run first thing by the ELF startup code. Stub version. - Copyright (C) 1995 Free Software Foundation, Inc. + Copyright (C) 1995, 1997 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 @@ -18,12 +18,15 @@ Boston, MA 02111-1307, USA. */ #include <unistd.h> +#include <sys/types.h> int __libc_multiple_libcs = 1; extern void __libc_init (int, char **, char **); extern void __getopt_clean_environment (void); +pid_t __libc_pid; + #ifdef PIC void __libc_init_first (void) diff --git a/sysdeps/stub/s_exp2f.c b/sysdeps/stub/s_exp2f.c index 51b268c..f763efb 100644 --- a/sysdeps/stub/s_exp2f.c +++ b/sysdeps/stub/s_exp2f.c @@ -11,4 +11,4 @@ __exp2f (float x) } weak_alias (__exp2f, exp2f) -stub_warning (exp2) +stub_warning (exp2f) diff --git a/sysdeps/stub/send.c b/sysdeps/stub/send.c index 262818e..a25eb72 100644 --- a/sysdeps/stub/send.c +++ b/sysdeps/stub/send.c @@ -21,7 +21,7 @@ /* Send N bytes of BUF to socket FD. Returns the number sent or -1. */ int -send (fd, buf, n, flags) +__send (fd, buf, n, flags) int fd; __const __ptr_t buf; size_t n; @@ -30,6 +30,7 @@ send (fd, buf, n, flags) __set_errno (ENOSYS); return -1; } +weak_alias (__send, send) stub_warning (send) diff --git a/sysdeps/stub/statfs.c b/sysdeps/stub/statfs.c index df13f73..bae8eaa 100644 --- a/sysdeps/stub/statfs.c +++ b/sysdeps/stub/statfs.c @@ -28,6 +28,6 @@ __statfs (const char *file, struct statfs *buf) __set_errno (ENOSYS); return -1; } -stub_warning (statfs) - weak_alias (__statfs, statfs) + +stub_warning (statfs) diff --git a/sysdeps/unix/Subdirs b/sysdeps/unix/Subdirs new file mode 100644 index 0000000..a46884d --- /dev/null +++ b/sysdeps/unix/Subdirs @@ -0,0 +1 @@ +login diff --git a/sysdeps/unix/bsd/osf/sys/mman.h b/sysdeps/unix/bsd/osf/sys/mman.h index 7284619..816f271 100644 --- a/sysdeps/unix/bsd/osf/sys/mman.h +++ b/sysdeps/unix/bsd/osf/sys/mman.h @@ -1,5 +1,5 @@ /* Definitions for BSD-style memory management. OSF/1 version. - Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1994, 1995, 1996, 1997 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 @@ -32,46 +32,53 @@ without PROT_READ. The only guarantees are that no writing will be allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ -#define PROT_NONE 0x00 /* No access. */ -#define PROT_READ 0x01 /* Pages can be read. */ -#define PROT_WRITE 0x02 /* Pages can be written. */ -#define PROT_EXEC 0x04 /* Pages can be executed. */ +#define PROT_NONE 0x00 /* No access. */ +#define PROT_READ 0x01 /* Pages can be read. */ +#define PROT_WRITE 0x02 /* Pages can be written. */ +#define PROT_EXEC 0x04 /* Pages can be executed. */ /* Flags contain mapping type, sharing type and options. */ /* Mapping type (must choose one and only one of these). */ -#define MAP_FILE 0x00 /* Mapped from a file or device. */ -#define MAP_ANON 0x10 /* Allocated from anonymous virtual memory. */ -#define MAP_ANONYMOUS MAP_ANON -#define MAP_TYPE 0xf0 /* Mask for type field. */ +#ifdef __USE_BSD +# define MAP_FILE 0x00 /* Mapped from a file or device. */ +# define MAP_ANON 0x10 /* Allocated from anonymous virtual memory. */ +# define MAP_ANONYMOUS MAP_ANON +# define MAP_TYPE 0xf0 /* Mask for type field. */ +#endif /* Sharing types (must choose one and only one of these). */ -#define MAP_SHARED 0x01 /* Share changes. */ -#define MAP_PRIVATE 0x02 /* Changes private; copy pages on write. */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes private; copy pages on write. */ /* Other flags. */ -#define MAP_FIXED 0x0100 /* Map address must be exactly as requested. */ -#define MAP_VARIABLE 0 /* Absence of MAP_FIXED. */ -#define MAP_HASSEMPHORE 0x0200 /* Region may contain semaphores. */ -#define MAP_INHERIT 0x0400 /* Region is retained after exec. */ -#define MAP_UNALIGNED 0x0800 /* File offset need not be page-aligned. */ +#define MAP_FIXED 0x0100 /* Map address must be exactly as requested. */ +#ifdef __USE_BSD +# define MAP_VARIABLE 0 /* Absence of MAP_FIXED. */ +# define MAP_HASSEMPHORE 0x0200 /* Region may contain semaphores. */ +# define MAP_INHERIT 0x0400 /* Region is retained after exec. */ +# define MAP_UNALIGNED 0x0800 /* File offset need not be page-aligned. */ +#endif /* Advice to `madvise'. */ -#define MADV_NORMAL 0 /* No further special treatment. */ -#define MADV_RANDOM 1 /* Expect random page references. */ -#define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ -#define MADV_WILLNEED 3 /* Will need these pages. */ -#define MADV_DONTNEED 4 /* Don't need these pages. */ -#define MADV_SPACEAVAIL 5 /* Ensure that resources are available. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_SPACEAVAIL 5 /* Ensure that resources are available. */ +#endif /* Flags to `msync'. */ #define MS_ASYNC 1 /* Asynchronous cache flush. */ #define MS_SYNC 3 /* Synchronous cache flush. */ #define MS_INVALIDATE 4 /* Invalidate cached pages. */ +/* Return value of `mmap' in case of an error. */ +#define MAP_FAILED ((__caddr_t) -1) -#include <sys/cdefs.h> __BEGIN_DECLS /* Map addresses starting near ADDR and extending for LEN bytes. from @@ -79,34 +86,36 @@ __BEGIN_DECLS is nonzero, it is the desired mapping address. If the MAP_FIXED bit is set in FLAGS, the mapping will be at ADDR exactly (which must be page-aligned); otherwise the system chooses a convenient nearby address. - The return value is the actual mapping address chosen or (caddr_t) -1 + The return value is the actual mapping address chosen or MAP_FAILED for errors (in which case `errno' is set). A successful `mmap' call deallocates any previous mapping for the affected region. */ -__caddr_t __mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, off_t __offset)); -__caddr_t mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, off_t __offset)); +extern __caddr_t __mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, off_t __offset)); +extern __caddr_t mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, off_t __offset)); /* Deallocate any mapping for the region starting at ADDR and extending LEN bytes. Returns 0 if successful, -1 for errors (and sets errno). */ -int __munmap __P ((__caddr_t __addr, size_t __len)); -int munmap __P ((__caddr_t __addr, size_t __len)); +extern int __munmap __P ((__caddr_t __addr, size_t __len)); +extern int munmap __P ((__caddr_t __addr, size_t __len)); /* Change the memory protection of the region starting at ADDR and extending LEN bytes to PROT. Returns 0 if successful, -1 for errors (and sets errno). */ -int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); -int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); /* Synchronize the region starting at ADDR and extending LEN bytes with the file it maps. Filesystem operations on a file being mapped are unpredictable before this is done. */ -int msync __P ((__caddr_t __addr, size_t __len, int __flags)); +extern int msync __P ((__caddr_t __addr, size_t __len, int __flags)); +#ifdef __USE_BSD /* Advise the system about particular usage patterns the program follows for the region starting at ADDR and extending LEN bytes. */ -int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +extern int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +#endif __END_DECLS diff --git a/sysdeps/unix/bsd/sun/sunos4/sys/mman.h b/sysdeps/unix/bsd/sun/sunos4/sys/mman.h index 65771a2..d2a8998 100644 --- a/sysdeps/unix/bsd/sun/sunos4/sys/mman.h +++ b/sysdeps/unix/bsd/sun/sunos4/sys/mman.h @@ -1,5 +1,5 @@ /* Definitions for BSD-style memory management. SunOS 4 version. - Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1994, 1995, 1996, 1997 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 @@ -41,14 +41,18 @@ /* Sharing types (must choose one and only one of these). */ #define MAP_SHARED 0x01 /* Share changes. */ #define MAP_PRIVATE 0x02 /* Changes private; copy pages on write. */ -#define MAP_TYPE 0x0f /* Mask for sharing type. */ +#ifdef __USE_BSD +# define MAP_TYPE 0x0f /* Mask for sharing type. */ +#endif /* Other flags. */ #define MAP_FIXED 0x10 /* Map address must be exactly as requested. */ /* The following three flags are not actually implemented in SunOS 4.1. */ -#define MAP_RENAME 0x20 /* Rename private pages to file. */ -#define MAP_NORESERVE 0x40 /* Don't reserve needed swap area. */ -#define MAP_INHERIT 0x80 /* Region is retained after exec. */ +#ifdef __USE_BSD +# define MAP_RENAME 0x20 /* Rename private pages to file. */ +# define MAP_NORESERVE 0x40 /* Don't reserve needed swap area. */ +# define MAP_INHERIT 0x80 /* Region is retained after exec. */ +#endif /* This is an internal flag that is always set in `mmap' system calls. In older versions of SunOS 4 `mmap' did not return the actual mapping @@ -57,18 +61,21 @@ #define _MAP_NEW 0x80000000 /* Advice to `madvise'. */ -#define MADV_NORMAL 0 /* No further special treatment. */ -#define MADV_RANDOM 1 /* Expect random page references. */ -#define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ -#define MADV_WILLNEED 3 /* Will need these pages. */ -#define MADV_DONTNEED 4 /* Don't need these pages. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +#endif /* Flags to `msync'. */ #define MS_ASYNC 0x1 /* Return immediately, don't fsync. */ #define MS_INVALIDATE 0x2 /* Invalidate caches. */ +/* Return value of `mmap' in case of an error. */ +#define MAP_FAILED ((__caddr_t) -1) -#include <sys/cdefs.h> __BEGIN_DECLS /* Map addresses starting near ADDR and extending for LEN bytes. from @@ -76,34 +83,36 @@ __BEGIN_DECLS is nonzero, it is the desired mapping address. If the MAP_FIXED bit is set in FLAGS, the mapping will be at ADDR exactly (which must be page-aligned); otherwise the system chooses a convenient nearby address. - The return value is the actual mapping address chosen or (caddr_t) -1 + The return value is the actual mapping address chosen or MAP_FAILED for errors (in which case `errno' is set). A successful `mmap' call deallocates any previous mapping for the affected region. */ -__caddr_t __mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, __off_t __offset)); -__caddr_t mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, __off_t __offset)); +extern __caddr_t __mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, __off_t __offset)); +extern __caddr_t mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, __off_t __offset)); /* Deallocate any mapping for the region starting at ADDR and extending LEN bytes. Returns 0 if successful, -1 for errors (and sets errno). */ -int __munmap __P ((__caddr_t __addr, size_t __len)); -int munmap __P ((__caddr_t __addr, size_t __len)); +extern int __munmap __P ((__caddr_t __addr, size_t __len)); +extern int munmap __P ((__caddr_t __addr, size_t __len)); /* Change the memory protection of the region starting at ADDR and extending LEN bytes to PROT. Returns 0 if successful, -1 for errors (and sets errno). */ -int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); -int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); /* Synchronize the region starting at ADDR and extending LEN bytes with the file it maps. Filesystem operations on a file being mapped are unpredictable before this is done. */ -int msync __P ((__caddr_t __addr, size_t __len, int __flags)); +extern int msync __P ((__caddr_t __addr, size_t __len, int __flags)); +#ifdef __USE_BSD /* Advise the system about particular usage patterns the program follows for the region starting at ADDR and extending LEN bytes. */ -int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +extern int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +#endif __END_DECLS diff --git a/sysdeps/unix/bsd/ultrix4/sys/mman.h b/sysdeps/unix/bsd/ultrix4/sys/mman.h index 989bf21..4262fce 100644 --- a/sysdeps/unix/bsd/ultrix4/sys/mman.h +++ b/sysdeps/unix/bsd/ultrix4/sys/mman.h @@ -1,5 +1,5 @@ /* Definitions for BSD-style memory management. Ultrix 4 version. - Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1994, 1995, 1996, 1997 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 @@ -41,20 +41,25 @@ /* Sharing types (must choose one and only one of these). */ #define MAP_SHARED 0x01 /* Share changes. */ #define MAP_PRIVATE 0x02 /* Changes private; copy pages on write. */ -#define MAP_TYPE 0x0f /* Mask for sharing type. */ +#ifdef __USE_BSD +# define MAP_TYPE 0x0f /* Mask for sharing type. */ +#endif /* Other flags. */ #define MAP_FIXED 0x10 /* Map address must be exactly as requested. */ /* Advice to `madvise'. */ -#define MADV_NORMAL 0 /* No further special treatment. */ -#define MADV_RANDOM 1 /* Expect random page references. */ -#define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ -#define MADV_WILLNEED 3 /* Will need these pages. */ -#define MADV_DONTNEED 4 /* Don't need these pages. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +#endif +/* Return value of `mmap' in case of an error. */ +#define MAP_FAILED ((__caddr_t) -1) -#include <sys/cdefs.h> __BEGIN_DECLS /* Map addresses starting near ADDR and extending for LEN bytes. from @@ -62,36 +67,38 @@ __BEGIN_DECLS is nonzero, it is the desired mapping address. If the MAP_FIXED bit is set in FLAGS, the mapping will be at ADDR exactly (which must be page-aligned); otherwise the system chooses a convenient nearby address. - The return value is the actual mapping address chosen or (caddr_t) -1 + The return value is the actual mapping address chosen or MAP_FAILED for errors (in which case `errno' is set). A successful `mmap' call deallocates any previous mapping for the affected region. */ -__caddr_t __mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, off_t __offset)); -__caddr_t mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, off_t __offset)); +extern __caddr_t __mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, off_t __offset)); +extern __caddr_t mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, off_t __offset)); /* Deallocate any mapping for the region starting at ADDR and extending LEN bytes. Returns 0 if successful, -1 for errors (and sets errno). */ -int __munmap __P ((__caddr_t __addr, size_t __len)); -int munmap __P ((__caddr_t __addr, size_t __len)); +extern int __munmap __P ((__caddr_t __addr, size_t __len)); +extern int munmap __P ((__caddr_t __addr, size_t __len)); /* Change the memory protection of the region starting at ADDR and extending LEN bytes to PROT. Returns 0 if successful, -1 for errors (and sets errno). */ -int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); -int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); /* Ultrix 4 does not implement `msync' or `madvise'. */ /* Synchronize the region starting at ADDR and extending LEN bytes with the file it maps. Filesystem operations on a file being mapped are unpredictable before this is done. */ -int msync __P ((caddr_t __addr, size_t __len)); +extern int msync __P ((caddr_t __addr, size_t __len)); +#ifdef __USE_BSD /* Advise the system about particular usage patterns the program follows for the region starting at ADDR and extending LEN bytes. */ -int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +extern int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +#endif __END_DECLS diff --git a/sysdeps/unix/sysv/irix4/sys/mman.h b/sysdeps/unix/sysv/irix4/sys/mman.h index f42a9f6..c3a9238 100644 --- a/sysdeps/unix/sysv/irix4/sys/mman.h +++ b/sysdeps/unix/sysv/irix4/sys/mman.h @@ -1,5 +1,5 @@ /* Definitions for BSD-style memory management. Irix 4 version. - Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1994, 1995, 1996, 1997 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 @@ -23,8 +23,6 @@ #include <features.h> #include <bits/types.h> -#define __need_size_t -#include <stddef.h> /* Protections are chosen from these bits, OR'd together. The @@ -32,37 +30,46 @@ without PROT_READ. The only guarantees are that no writing will be allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ -#define PROT_NONE 0x00 /* No access. */ -#define PROT_READ 0x04 /* Pages can be read. */ -#define PROT_WRITE 0x02 /* Pages can be written. */ -#define PROT_EXEC 0x01 /* Pages can be executed. */ -#define PROT_EXECUTE PROT_EXEC +#define PROT_NONE 0x00 /* No access. */ +#define PROT_READ 0x04 /* Pages can be read. */ +#define PROT_WRITE 0x02 /* Pages can be written. */ +#define PROT_EXEC 0x01 /* Pages can be executed. */ +#ifdef __USE_MISC +# define PROT_EXECUTE PROT_EXEC +#endif /* Sharing types (must choose one and only one of these). */ -#define MAP_SHARED 0x01 /* Share changes. */ -#define MAP_PRIVATE 0x02 /* Changes private; copy pages on write. */ -#define MAP_TYPE 0x0f /* Mask for sharing type. */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes private; copy pages on write. */ +#ifdef __USE_BSD +# define MAP_TYPE 0x0f /* Mask for sharing type. */ +#endif /* Other flags. */ -#define MAP_FIXED 0x10 /* Map address must be exactly as requested. */ -#define MAP_RENAME 0x20 /* Rename private pages to file. */ -#define MAP_AUTOGROW 0x40 /* Grow file as pages are written. */ -#define MAP_LOCAL 0x80 /* Copy the mapped region on fork. */ +#define MAP_FIXED 0x10 /* Map address must be exactly as requested. */ +#ifdef __USE_MISC +# define MAP_RENAME 0x20 /* Rename private pages to file. */ +# define MAP_AUTOGROW 0x40 /* Grow file as pages are written. */ +# define MAP_LOCAL 0x80 /* Copy the mapped region on fork. */ +#endif /* Advice to `madvise'. */ -#define MADV_NORMAL 0 /* No further special treatment. */ -#define MADV_RANDOM 1 /* Expect random page references. */ -#define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ -#define MADV_WILLNEED 3 /* Will need these pages. */ -#define MADV_DONTNEED 4 /* Don't need these pages. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +#endif /* Flags to `msync'. */ -#define MS_ASYNC 0x1 /* Return immediately, don't fsync. */ -#define MS_INVALIDATE 0x2 /* Invalidate caches. */ +#define MS_ASYNC 0x1 /* Return immediately, don't fsync. */ +#define MS_INVALIDATE 0x2 /* Invalidate caches. */ +/* Return value of `mmap' in case of an error. */ +#define MAP_FAILED ((__caddr_t) -1) -#include <sys/cdefs.h> __BEGIN_DECLS /* Map addresses starting near ADDR and extending for LEN bytes. from @@ -70,34 +77,36 @@ __BEGIN_DECLS is nonzero, it is the desired mapping address. If the MAP_FIXED bit is set in FLAGS, the mapping will be at ADDR exactly (which must be page-aligned); otherwise the system chooses a convenient nearby address. - The return value is the actual mapping address chosen or (caddr_t) -1 + The return value is the actual mapping address chosen or MAP_FAILED for errors (in which case `errno' is set). A successful `mmap' call deallocates any previous mapping for the affected region. */ -__caddr_t __mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, __off_t __offset)); -__caddr_t mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, __off_t __offset)); +extern __caddr_t __mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, __off_t __offset)); +extern __caddr_t mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, __off_t __offset)); /* Deallocate any mapping for the region starting at ADDR and extending LEN bytes. Returns 0 if successful, -1 for errors (and sets errno). */ -int __munmap __P ((__caddr_t __addr, size_t __len)); -int munmap __P ((__caddr_t __addr, size_t __len)); +extern int __munmap __P ((__caddr_t __addr, size_t __len)); +extern int munmap __P ((__caddr_t __addr, size_t __len)); /* Change the memory protection of the region starting at ADDR and extending LEN bytes to PROT. Returns 0 if successful, -1 for errors (and sets errno). */ -int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); -int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); /* Synchronize the region starting at ADDR and extending LEN bytes with the file it maps. Filesystem operations on a file being mapped are unpredictable before this is done. */ -int msync __P ((caddr_t __addr, size_t __len, int __flags)); +extern int msync __P ((caddr_t __addr, size_t __len, int __flags)); +#ifdef __USE_BSD /* Advise the system about particular usage patterns the program follows for the region starting at ADDR and extending LEN bytes. */ -int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +extern int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +#endif __END_DECLS diff --git a/sysdeps/unix/sysv/linux/alpha/Dist b/sysdeps/unix/sysv/linux/alpha/Dist index 1b1f771..ae71c2f 100644 --- a/sysdeps/unix/sysv/linux/alpha/Dist +++ b/sysdeps/unix/sysv/linux/alpha/Dist @@ -1,11 +1,14 @@ -alpha/ptrace.h alpha/regdef.h -ieee_get_fp_control.S ieee_set_fp_control.S -ioperm.c -init-first.h +alpha/ptrace.h +alpha/regdef.h +bits/mman.h clone.S +ieee_get_fp_control.S +ieee_set_fp_control.S +init-first.h +ioperm.c kernel_sigaction.h kernel_stat.h kernel_termios.h -sys/io.h sys/acct.h +sys/io.h sys/procfs.h diff --git a/sysdeps/unix/sysv/linux/alpha/bits/mman.h b/sysdeps/unix/sysv/linux/alpha/bits/mman.h new file mode 100644 index 0000000..1bef0cb --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/bits/mman.h @@ -0,0 +1,83 @@ +/* Definitions for POSIX memory map inerface. Linux/Alpha version. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#ifndef _SYS_MMAN_H +# error "Never include this file directly. Use <sys/mman.h> instead" +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x100 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x10 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* Not used by Linux, but here to make sure we don't clash with OSF/1 + defines. */ +#ifdef __USE_BSD +# define MAP_HASSEMAPHORE 0x0200 +# define MAP_INHERIT 0x0400 +# define MAP_UNALIGNED 0x0800 +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x1000 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x2000 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x4000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x8000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x10000 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 2 /* Synchronous memory sync. */ +#define MS_INVALIDATE 4 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 8192 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 16384 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +#endif diff --git a/sysdeps/unix/sysv/linux/bits/socket.h b/sysdeps/unix/sysv/linux/bits/socket.h index fd13e12..2a8d6ed 100644 --- a/sysdeps/unix/sysv/linux/bits/socket.h +++ b/sysdeps/unix/sysv/linux/bits/socket.h @@ -136,7 +136,7 @@ struct msghdr socklen_t msg_namelen; /* Length of address data. */ struct iovec *msg_iov; /* Vector of data to send/receive into. */ - size_t msg_iovlen; /* Number of elements in the vector. */ + int msg_iovlen; /* Number of elements in the vector. */ __ptr_t msg_control; /* Ancillary data (eg BSD filedesc passing). */ socklen_t msg_controllen; /* Ancillary data buffer length. */ diff --git a/sysdeps/unix/sysv/linux/i386/Dist b/sysdeps/unix/sysv/linux/i386/Dist index d5cc620..d762dc9 100644 --- a/sysdeps/unix/sysv/linux/i386/Dist +++ b/sysdeps/unix/sysv/linux/i386/Dist @@ -1,2 +1,4 @@ -sys/perm.h sys/vm86.h +bits/mman.h clone.S +sys/perm.h +sys/vm86.h diff --git a/sysdeps/unix/sysv/linux/i386/bits/mman.h b/sysdeps/unix/sysv/linux/i386/bits/mman.h new file mode 100644 index 0000000..e70b220 --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/bits/mman.h @@ -0,0 +1,75 @@ +/* Definitions for POSIX memory map inerface. Linux/i386 version. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#ifndef _SYS_MMAN_H +# error "Never include this file directly. Use <sys/mman.h> instead" +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x2000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +#endif diff --git a/sysdeps/unix/sysv/linux/if_index.c b/sysdeps/unix/sysv/linux/if_index.c index c8eefa9..f64fe1e 100644 --- a/sysdeps/unix/sysv/linux/if_index.c +++ b/sysdeps/unix/sysv/linux/if_index.c @@ -182,11 +182,9 @@ if_indextoname (unsigned int ifindex, char *ifname) #else struct if_nameindex *idx = if_nameindex (); struct if_nameindex *p; - char *result; + char *result = NULL; - if (idx == NULL) - result = NULL; - else + if (idx != NULL) { for (p = idx; p->if_index || p->if_name; ++p) if (p->if_index == ifindex) diff --git a/sysdeps/unix/sysv/linux/m68k/Dist b/sysdeps/unix/sysv/linux/m68k/Dist index e7d5949..25aa20b 100644 --- a/sysdeps/unix/sysv/linux/m68k/Dist +++ b/sysdeps/unix/sysv/linux/m68k/Dist @@ -1,2 +1,3 @@ +bits/mman.h clone.S mremap.S diff --git a/sysdeps/unix/sysv/linux/mips/Dist b/sysdeps/unix/sysv/linux/mips/Dist index a205c94..6be6876 100644 --- a/sysdeps/unix/sysv/linux/mips/Dist +++ b/sysdeps/unix/sysv/linux/mips/Dist @@ -1,3 +1,15 @@ +bits/mman.h clone.S kernel_sigaction.h kernel_stat.h +kernel_termios.h +entry.h +regdef.h +fpregdef.h +sys/acct.h +sys/asm.h +sys/cachectl.h +sys/fpregdef.h +sys/procfs.h +sys/regdef.h +sys/sysmips.h diff --git a/sysdeps/unix/sysv/linux/mips/bits/mman.h b/sysdeps/unix/sysv/linux/mips/bits/mman.h new file mode 100644 index 0000000..15a343f --- /dev/null +++ b/sysdeps/unix/sysv/linux/mips/bits/mman.h @@ -0,0 +1,75 @@ +/* Definitions for POSIX memory map inerface. Linux/PowerPC version. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#ifndef _SYS_MMAN_H +# error "Never include this file directly. Use <sys/mman.h> instead" +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0x00 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +# define MAP_RENAME MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_NORESERVE 0x0040 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 0x2000 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 0x4000 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/Dist b/sysdeps/unix/sysv/linux/powerpc/Dist index cd6d6d1..0213c45 100644 --- a/sysdeps/unix/sysv/linux/powerpc/Dist +++ b/sysdeps/unix/sysv/linux/powerpc/Dist @@ -1,3 +1,4 @@ +bits/mman.h clone.S kernel_stat.h kernel_termios.h diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/mman.h b/sysdeps/unix/sysv/linux/powerpc/bits/mman.h new file mode 100644 index 0000000..da5ad0e --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/bits/mman.h @@ -0,0 +1,84 @@ +/* Definitions for POSIX memory map inerface. Linux/MIPS version. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#ifndef _SYS_MMAN_H +# error "Never include this file directly. Use <sys/mman.h> instead" +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x001 /* Share changes. */ +#define MAP_PRIVATE 0x002 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x00f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x010 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0x000 +# define MAP_ANONYMOUS 0x800 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* Not used by Linux, but here to make sure we don't clash with ABI + defines. */ +#ifdef __USE_MISC +# define MAP_RENAME 0x020 /* Assign page to file. */ +# define MAP_AUTOGROW 0x040 /* File may grow by writing. */ +# define MAP_LOCAL 0x080 /* Copy on fork/sproc. */ +# define MAP_AUTORSRV 0x100 /* Logical swap reserved on demand. */ +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x1000 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x2000 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x4000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x8000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x0400 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 0 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/kernel_termios.h b/sysdeps/unix/sysv/linux/powerpc/kernel_termios.h index 9a5e830..4946066 100644 --- a/sysdeps/unix/sysv/linux/powerpc/kernel_termios.h +++ b/sysdeps/unix/sysv/linux/powerpc/kernel_termios.h @@ -18,7 +18,6 @@ #ifndef _KERNEL_TERMIOS_H #define _KERNEL_TERMIOS_H 1 -/* The following corresponds to the values from the Linux 2.0.28 kernel. */ /* We need the definition of tcflag_t, cc_t, and speed_t. */ #include <bits/termios.h> @@ -33,8 +32,8 @@ struct __kernel_termios tcflag_t c_lflag; /* local mode flags */ cc_t c_cc[__KERNEL_NCCS]; /* control characters */ cc_t c_line; /* line discipline */ - int c_ispeed; /* input speed */ - int c_ospeed; /* output speed */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ }; #define _HAVE_C_ISPEED 1 diff --git a/sysdeps/unix/sysv/linux/powerpc/profil-counter.h b/sysdeps/unix/sysv/linux/powerpc/profil-counter.h new file mode 100644 index 0000000..fed0913 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/profil-counter.h @@ -0,0 +1,26 @@ +/* Low-level statistical profiling support function. Linux/PowerPC version. + Copyright (C) 1996, 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#include <signal.h> + +void +profil_counter (int signo, struct sigcontext sc) +{ + profil_count ((void *) sc.regs->nip); +} diff --git a/sysdeps/unix/sysv/linux/powerpc/profil.c b/sysdeps/unix/sysv/linux/powerpc/profil.c deleted file mode 100644 index 6ab8065..0000000 --- a/sysdeps/unix/sysv/linux/powerpc/profil.c +++ /dev/null @@ -1,2 +0,0 @@ -/* For now. */ -#include <sysdeps/stub/profil.c> diff --git a/sysdeps/unix/sysv/linux/sparc/Dist b/sysdeps/unix/sysv/linux/sparc/Dist index d93c648..9729f07 100644 --- a/sysdeps/unix/sysv/linux/sparc/Dist +++ b/sysdeps/unix/sysv/linux/sparc/Dist @@ -1,7 +1,8 @@ __sigtrampoline.S +bits/mman.h clone.S pipe.S fork.S kernel_stat.h -kernel_sigaction.h init-first.h +sys/trap.h diff --git a/sysdeps/unix/sysv/linux/sparc/bits/mman.h b/sysdeps/unix/sysv/linux/sparc/bits/mman.h new file mode 100644 index 0000000..3e7f290 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc/bits/mman.h @@ -0,0 +1,77 @@ +/* Definitions for POSIX memory map inerface. Linux/SPARC version. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#ifndef _SYS_MMAN_H +# error "Never include this file directly. Use <sys/mman.h> instead" +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0x00 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +# define MAP_RENAME MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x0100 /* Lock the mapping. */ +# define MAP_NORESERVE 0x0040 /* Don't check for reservations. */ +# define _MAP_NEW 0x80000000 /* Binary compatibility with SunOS. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 0x2000 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 0x4000 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +#endif diff --git a/sysdeps/unix/sysv/linux/sparc64/Dist b/sysdeps/unix/sysv/linux/sparc64/Dist new file mode 100644 index 0000000..e770e20 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc64/Dist @@ -0,0 +1,7 @@ +bits/mman.h +clone.S +kernel_stat.h +getcontext.S +setcontext.S +ucontext.h +init-first.h diff --git a/sysdeps/unix/sysv/linux/sparc64/bits/mman.h b/sysdeps/unix/sysv/linux/sparc64/bits/mman.h new file mode 100644 index 0000000..3e7f290 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc64/bits/mman.h @@ -0,0 +1,77 @@ +/* Definitions for POSIX memory map inerface. Linux/SPARC version. + Copyright (C) 1997 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 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 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C 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. */ + +#ifndef _SYS_MMAN_H +# error "Never include this file directly. Use <sys/mman.h> instead" +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0x00 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +# define MAP_RENAME MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x0100 /* Lock the mapping. */ +# define MAP_NORESERVE 0x0040 /* Don't check for reservations. */ +# define _MAP_NEW 0x80000000 /* Binary compatibility with SunOS. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 0x2000 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 0x4000 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +#endif diff --git a/sysdeps/unix/sysv/linux/sys/mman.h b/sysdeps/unix/sysv/linux/sys/mman.h index dc9f8f7..0f56a70 100644 --- a/sysdeps/unix/sysv/linux/sys/mman.h +++ b/sysdeps/unix/sysv/linux/sys/mman.h @@ -23,20 +23,12 @@ #include <features.h> #include <bits/types.h> -#define __need_size_t -#include <stddef.h> - -#include <sys/cdefs.h> /* Get the bit values from the kernel header file. */ -#include <linux/mman.h> +#include <bits/mman.h> -#ifndef MAP_ANON -#define MAP_ANON MAP_ANONYMOUS -#endif -#ifndef MAP_FILE -#define MAP_FILE 0 -#endif +/* Return value of `mmap' in case of an error. */ +#define MAP_FAILED ((__caddr_t) -1) __BEGIN_DECLS /* Map addresses starting near ADDR and extending for LEN bytes. from @@ -44,7 +36,7 @@ __BEGIN_DECLS is nonzero, it is the desired mapping address. If the MAP_FIXED bit is set in FLAGS, the mapping will be at ADDR exactly (which must be page-aligned); otherwise the system chooses a convenient nearby address. - The return value is the actual mapping address chosen or (caddr_t) -1 + The return value is the actual mapping address chosen or MAP_FAILED for errors (in which case `errno' is set). A successful `mmap' call deallocates any previous mapping for the affected region. */ @@ -69,9 +61,11 @@ extern int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); unpredictable before this is done. Flags are from the MS_* set. */ extern int msync __P ((__caddr_t __addr, size_t __len, int __flags)); +#ifdef __USE_BSD /* Advise the system about particular usage patterns the program follows for the region starting at ADDR and extending LEN bytes. */ extern int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +#endif /* Cause all currently mapped pages of the process to be memory resident until unlocked by a call to the `munlockall', until the process exits, @@ -89,6 +83,7 @@ extern int mlock __P ((__caddr_t __addr, size_t __len)); /* Unlock whole pages previously mapped by the range [ADDR,ADDR+LEN). */ extern int munlock __P ((__caddr_t __addr, size_t __len)); +#ifdef __USE_MISC /* Remap pages mapped by the range [ADDR,ADDR+OLD_LEN) to new length NEW_LEN. If MAY_MOVE is MREMAP_MAYMOVE the returned address may differ from ADDR. */ @@ -96,6 +91,7 @@ extern __caddr_t __mremap __P ((__caddr_t __addr, size_t __old_len, size_t __new_len, int __may_move)); extern __caddr_t mremap __P ((__caddr_t __addr, size_t __old_len, size_t __new_len, int __may_move)); +#endif __END_DECLS diff --git a/sysdeps/unix/sysv/linux/sys/sysmacros.h b/sysdeps/unix/sysv/linux/sys/sysmacros.h index 85b1b85..5c1e1f7 100644 --- a/sysdeps/unix/sysv/linux/sys/sysmacros.h +++ b/sysdeps/unix/sysv/linux/sys/sysmacros.h @@ -22,8 +22,8 @@ #define _SYS_SYSMACROS_H 1 /* For compatibility we provide alternative names. */ -#define major(dev) (((dev) >> 8) & 0xff) -#define minor(dev) ((dev) & 0xff) +#define major(dev) ((int)(((dev) >> 8) & 0xff)) +#define minor(dev) ((int)((dev) & 0xff)) #define makedev(major, minor) (((major) << 8) | (minor)) #endif /* _SYS_SYSMACROS_H */ |