aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/generic/bits/utmp.h28
-rw-r--r--sysdeps/generic/bits/utmpx.h34
-rw-r--r--sysdeps/generic/sys/mman.h74
-rw-r--r--sysdeps/i386/i586/stpcpy.S6
-rw-r--r--sysdeps/i386/i586/strcpy.S147
-rw-r--r--sysdeps/i386/i686/Implies6
-rw-r--r--sysdeps/libm-i387/e_rem_pio2.c3
-rw-r--r--sysdeps/libm-i387/e_rem_pio2f.c3
-rw-r--r--sysdeps/libm-i387/e_rem_pio2l.c3
-rw-r--r--sysdeps/libm-i387/k_rem_pio2.c3
-rw-r--r--sysdeps/libm-i387/k_rem_pio2f.c3
-rw-r--r--sysdeps/libm-i387/k_rem_pio2l.c3
-rw-r--r--sysdeps/libm-i387/s_cbrt.S78
-rw-r--r--sysdeps/libm-i387/s_cbrtf.S50
-rw-r--r--sysdeps/libm-i387/s_cbrtl.S143
-rw-r--r--sysdeps/libm-ieee754/s_isinf.c8
-rw-r--r--sysdeps/libm-ieee754/s_isinff.c8
-rw-r--r--sysdeps/libm-ieee754/s_isinfl.c8
-rw-r--r--sysdeps/libm-ieee754/s_lround.c24
-rw-r--r--sysdeps/m68k/fpu/e_rem_pio2.c3
-rw-r--r--sysdeps/m68k/fpu/e_rem_pio2f.c3
-rw-r--r--sysdeps/m68k/fpu/e_rem_pio2l.c3
-rw-r--r--sysdeps/m68k/fpu/k_rem_pio2.c3
-rw-r--r--sysdeps/m68k/fpu/k_rem_pio2f.c3
-rw-r--r--sysdeps/m68k/fpu/k_rem_pio2l.c3
-rw-r--r--sysdeps/mach/bits/libc-lock.h21
-rw-r--r--sysdeps/mach/hurd/Dist1
-rw-r--r--sysdeps/mach/hurd/Makefile15
-rw-r--r--sysdeps/mach/hurd/Subdirs1
-rw-r--r--sysdeps/mach/hurd/profil.c153
-rw-r--r--sysdeps/mips/Dist2
-rw-r--r--sysdeps/mips/mips64/Dist1
-rw-r--r--sysdeps/mips/mipsel/Dist1
-rw-r--r--sysdeps/posix/defs.c2
-rw-r--r--sysdeps/powerpc/Dist1
-rw-r--r--sysdeps/powerpc/Makefile12
-rw-r--r--sysdeps/powerpc/bits/fenv.h70
-rw-r--r--sysdeps/powerpc/bits/mathdef.h6
-rw-r--r--sysdeps/powerpc/dl-machine.h55
-rw-r--r--sysdeps/powerpc/e_sqrt.c141
-rw-r--r--sysdeps/powerpc/e_sqrtf.c136
-rw-r--r--sysdeps/powerpc/fclrexcpt.c4
-rw-r--r--sysdeps/powerpc/fe_nomask.c32
-rw-r--r--sysdeps/powerpc/fegetround.c10
-rw-r--r--sysdeps/powerpc/fenv_const.c6
-rw-r--r--sysdeps/powerpc/fenv_libc.h65
-rw-r--r--sysdeps/powerpc/fgetexcptflg.c5
-rw-r--r--sysdeps/powerpc/fpu_control.h1
-rw-r--r--sysdeps/powerpc/fraiseexcpt.c11
-rw-r--r--sysdeps/powerpc/fsetexcptflg.c13
-rw-r--r--sysdeps/powerpc/ftestexcept.c11
-rw-r--r--sysdeps/powerpc/q_addsub.c549
-rw-r--r--sysdeps/powerpc/q_dtoq.c66
-rw-r--r--sysdeps/powerpc/q_feq.c65
-rw-r--r--sysdeps/powerpc/q_fne.c70
-rw-r--r--sysdeps/powerpc/q_itoq.c50
-rw-r--r--sysdeps/powerpc/q_lltoq.c52
-rw-r--r--sysdeps/powerpc/q_neg.c38
-rw-r--r--sysdeps/powerpc/q_qtoi.c65
-rw-r--r--sysdeps/powerpc/q_qtoll.c64
-rw-r--r--sysdeps/powerpc/q_qtos.c84
-rw-r--r--sysdeps/powerpc/q_qtou.c64
-rw-r--r--sysdeps/powerpc/q_qtoull.c65
-rw-r--r--sysdeps/powerpc/q_stoq.c65
-rw-r--r--sysdeps/powerpc/q_ulltoq.c46
-rw-r--r--sysdeps/powerpc/q_utoq.c44
-rw-r--r--sysdeps/powerpc/quad_float.h44
-rw-r--r--sysdeps/powerpc/s_copysign.S60
-rw-r--r--sysdeps/powerpc/s_fabs.S42
-rw-r--r--sysdeps/powerpc/s_isnan.c47
-rw-r--r--sysdeps/powerpc/s_llrint.c28
-rw-r--r--sysdeps/powerpc/s_llround.c46
-rw-r--r--sysdeps/powerpc/s_lrint.c44
-rw-r--r--sysdeps/powerpc/s_lround.c46
-rw-r--r--sysdeps/powerpc/s_rint.c45
-rw-r--r--sysdeps/powerpc/s_rintf.c41
-rw-r--r--sysdeps/powerpc/strlen.s19
-rw-r--r--sysdeps/powerpc/t_sqrt.c144
-rw-r--r--sysdeps/powerpc/test-arith.c604
-rw-r--r--sysdeps/powerpc/test-arithf.c6
-rw-r--r--sysdeps/sparc/Dist1
-rw-r--r--sysdeps/sparc64/elf/Dist4
-rw-r--r--sysdeps/standalone/arm/bits/errno.h10
-rw-r--r--sysdeps/stub/bits/libc-lock.h2
-rw-r--r--sysdeps/stub/connect.c3
-rw-r--r--sysdeps/stub/init-first.c5
-rw-r--r--sysdeps/stub/s_exp2f.c2
-rw-r--r--sysdeps/stub/send.c3
-rw-r--r--sysdeps/stub/statfs.c4
-rw-r--r--sysdeps/unix/Subdirs1
-rw-r--r--sysdeps/unix/bsd/osf/sys/mman.h77
-rw-r--r--sysdeps/unix/bsd/sun/sunos4/sys/mman.h53
-rw-r--r--sysdeps/unix/bsd/ultrix4/sys/mman.h45
-rw-r--r--sysdeps/unix/sysv/irix4/sys/mman.h77
-rw-r--r--sysdeps/unix/sysv/linux/alpha/Dist13
-rw-r--r--sysdeps/unix/sysv/linux/alpha/bits/mman.h83
-rw-r--r--sysdeps/unix/sysv/linux/bits/socket.h2
-rw-r--r--sysdeps/unix/sysv/linux/i386/Dist4
-rw-r--r--sysdeps/unix/sysv/linux/i386/bits/mman.h75
-rw-r--r--sysdeps/unix/sysv/linux/if_index.c6
-rw-r--r--sysdeps/unix/sysv/linux/m68k/Dist1
-rw-r--r--sysdeps/unix/sysv/linux/mips/Dist12
-rw-r--r--sysdeps/unix/sysv/linux/mips/bits/mman.h75
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/Dist1
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/bits/mman.h84
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/kernel_termios.h5
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/profil-counter.h26
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/profil.c2
-rw-r--r--sysdeps/unix/sysv/linux/sparc/Dist3
-rw-r--r--sysdeps/unix/sysv/linux/sparc/bits/mman.h77
-rw-r--r--sysdeps/unix/sysv/linux/sparc64/Dist7
-rw-r--r--sysdeps/unix/sysv/linux/sparc64/bits/mman.h77
-rw-r--r--sysdeps/unix/sysv/linux/sys/mman.h20
-rw-r--r--sysdeps/unix/sysv/linux/sys/sysmacros.h4
114 files changed, 4466 insertions, 427 deletions
diff --git a/sysdeps/generic/bits/utmp.h b/sysdeps/generic/bits/utmp.h
index b8decb0598..ccc318bfa1 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 0000000000..f85fce0052
--- /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 9c2a1b62ce..6484e028c9 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 0000000000..ea24fa709a
--- /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 0000000000..7f89a2c0f7
--- /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 75fde78977..b5c05ec7f2 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 0000000000..1347b0468c
--- /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 0000000000..1347b0468c
--- /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 0000000000..1347b0468c
--- /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 0000000000..1347b0468c
--- /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 0000000000..1347b0468c
--- /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 0000000000..1347b0468c
--- /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 4b9a2b11c6..3f6a0174f2 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 6978da2d40..a14e04ed2f 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 b2023d1991..6a3b9a8dc5 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 6f76ce1fba..4f063d09c5 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 18a0b5e03b..efc0935251 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 b499821441..697534ed0d 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 0f91280a79..974dbde050 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 0000000000..1347b0468c
--- /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 0000000000..1347b0468c
--- /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 0000000000..1347b0468c
--- /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 0000000000..1347b0468c
--- /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 0000000000..1347b0468c
--- /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 0000000000..1347b0468c
--- /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 79a1e00464..17eeefcdb5 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 62fe4d96c6..e6067b8a73 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 43d5eb9a2d..bf1c3b02bc 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 16b8348437..739919f4b1 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 d3c5131b10..d76cc25a3c 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 ad6ea0313a..9b6fd71f01 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 ad6ea0313a..4cde3d0e5d 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 0000000000..98a10ec269
--- /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 4a12292f55..bc0d34bf15 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 ae16c0f8fb..282cf1394e 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 4100901d62..0a50956640 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 08d998e118..8c26a2548f 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 c0e6caa843..9f91863333 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 c9d1d7332a..74436d15c1 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 0000000000..df80973f58
--- /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 0000000000..804dff3c44
--- /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 1e66140c2e..cfcf175637 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 0000000000..bca49055d1
--- /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 05395f0797..3bb9fb49e0 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 fa35fbc0cf..506bd43df0 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 45d61e1565..343be16fcb 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 d6bd58dc69..adbdfe22b9 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 d21987ffd8..c4c478672b 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 4305c3dcd2..d0c7971836 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 4279b74849..b762552dbf 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 52733f7ae7..6cb8dd5e28 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 0000000000..e4ef6d8165
--- /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 0000000000..8cab9e4689
--- /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 0000000000..3f5512a4a0
--- /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 0000000000..8f6429cd55
--- /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 0000000000..aa737391bb
--- /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 0000000000..6222eff9fc
--- /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 0000000000..8e11afdbc6
--- /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 0000000000..a2b1b3fe56
--- /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 0000000000..77a54f8bf9
--- /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 0000000000..cd2715f8e9
--- /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 0000000000..a5583cc816
--- /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 0000000000..e0b84d3e84
--- /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 0000000000..766997b97b
--- /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 0000000000..caae124781
--- /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 0000000000..84ce215a00
--- /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 0000000000..787e8d9ab9
--- /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 0000000000..adc7df226a
--- /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 0000000000..a52733568d
--- /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 0000000000..34019fdbdb
--- /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 0000000000..7ca48c029a
--- /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 0000000000..fbe3a3217c
--- /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 0000000000..647cf30c9c
--- /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 0000000000..a6cb6c96d2
--- /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 0000000000..d6d1dd2f76
--- /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 0000000000..b95c0540bf
--- /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 9d671cabc3..ea809772eb 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 0000000000..c49380c0fd
--- /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 0000000000..c846b0d0ec
--- /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 0000000000..d78ec49009
--- /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 8bd3729740..6c3b23baa5 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 0000000000..d9338c8fd6
--- /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 362b43dacf..f5020dcb7e 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 9efd799dab..c24dcd047a 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 7fbbc7fa31..9152a9449c 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 5e2cd121f1..4fcc67ddbe 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 51b268c9e0..f763efbe69 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 262818e8a9..a25eb72822 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 df13f73c57..bae8eaa8ee 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 0000000000..a46884d4f8
--- /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 72846195d2..816f271e30 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 65771a2aac..d2a8998d9a 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 989bf21754..4262fce438 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 f42a9f67aa..c3a923832a 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 1b1f771853..ae71c2feb3 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 0000000000..1bef0cb525
--- /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 fd13e124a8..2a8d6ed004 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 d5cc620549..d762dc9416 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 0000000000..e70b220f9f
--- /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 c8eefa9b98..f64fe1e1ca 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 e7d5949d51..25aa20bcfa 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 a205c94f95..6be6876fe7 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 0000000000..15a343ff76
--- /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 cd6d6d12e5..0213c45f51 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 0000000000..da5ad0eb45
--- /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 9a5e830c31..49460661e2 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 0000000000..fed0913574
--- /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 6ab8065da3..0000000000
--- 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 d93c648651..9729f0709b 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 0000000000..3e7f2900fa
--- /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 0000000000..e770e20eb9
--- /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 0000000000..3e7f2900fa
--- /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 dc9f8f7e48..0f56a70c32 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 85b1b85d2e..5c1e1f7441 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 */