diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | linuxthreads/ChangeLog | 9 | ||||
-rw-r--r-- | linuxthreads/Makefile | 5 | ||||
-rw-r--r-- | linuxthreads/internals.h | 19 | ||||
-rw-r--r-- | linuxthreads/sighandler.c | 69 | ||||
-rw-r--r-- | linuxthreads/signals.c | 79 | ||||
-rw-r--r-- | sysdeps/generic/dl-tls.c | 17 | ||||
-rw-r--r-- | sysdeps/ia64/Makefile | 7 | ||||
-rw-r--r-- | sysdeps/ia64/Versions | 7 | ||||
-rw-r--r-- | sysdeps/ia64/ia64libgcc.S | 350 |
10 files changed, 490 insertions, 85 deletions
@@ -1,3 +1,16 @@ +2002-05-02 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/ia64/Makefile: Add ia64libgcc in csu subdir. + * sysdeps/ia64/Versions (__divtf3, __divdf3, __divsf3, __divdi3, + __moddi3, __udivdi3, __umoddi3, __multi3): Export at GLIBC_2.0. + * sysdeps/ia64/ia64libgcc.S: New file. + +2002-05-02 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/generic/dl-tls.c (oom): Implement using _dl_fatal_printf. + + * malloc/memusage.c: Distinguish anonymous mmap. + 2002-05-01 Roland McGrath <roland@frob.com> * sysdeps/mach/hurd/close.c: #undef __close before function defn, diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog index 747e409..9a58488 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -1,3 +1,12 @@ +2002-05-03 Ulrich Drepper <drepper@redhat.com> + + * signals.c: Move sighandler functions to... + * sighandler.c: ...here. New file. + * signals.c: Move signal handler related type definitions to... + * internals.h: ...here. Add prototypes for signal handlers. + * Makefile (libpthread-routines): Add sighandler. + (CFLAGS-sighandler.c): Add $(exceptions). + 2002-04-30 Jakub Jelinek <jakub@redhat.com> * sysdeps/unix/sysv/linux/x86_64/Makefile: New file. diff --git a/linuxthreads/Makefile b/linuxthreads/Makefile index 33c041e..4143284 100644 --- a/linuxthreads/Makefile +++ b/linuxthreads/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. +# Copyright (C) 1996-2001, 2002 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 @@ -36,7 +36,7 @@ libpthread-routines := attr cancel condvar join manager mutex ptfork \ ptlongjmp pthread signals specific errno lockfile \ semaphore spinlock wrapsyscall rwlock pt-machine \ oldsemaphore events getcpuclockid pspinlock barrier \ - ptclock_gettime ptclock_settime + ptclock_gettime ptclock_settime sighandler nodelete-yes = -Wl,--enable-new-dtags,-z,nodelete initfirst-yes = -Wl,--enable-new-dtags,-z,initfirst @@ -80,6 +80,7 @@ CFLAGS-pthread.c += -D__NO_WEAK_PTHREAD_ALIASES $(znodelete-$(have-z-nodelete)) CFLAGS-ptfork.c += -D__NO_WEAK_PTHREAD_ALIASES CFLAGS-cancel.c += -D__NO_WEAK_PTHREAD_ALIASES -D_RPC_THREAD_SAFE_ CFLAGS-unload.c += -DPREFIX=\"$(objpfx)\" +CFLAGS-sighandler.c += $(exceptions) # Depend on libc.so so a DT_NEEDED is generated in the shared objects. # This ensures they will load libc.so for needed symbols if loaded by diff --git a/linuxthreads/internals.h b/linuxthreads/internals.h index 45a73ad..39c545c 100644 --- a/linuxthreads/internals.h +++ b/linuxthreads/internals.h @@ -20,8 +20,10 @@ /* Includes */ #include <limits.h> +#include <signal.h> #include <unistd.h> #include <stackinfo.h> +#include <sigcontextinfo.h> #include <tls.h> #include "descr.h" @@ -93,6 +95,16 @@ struct pthread_request { }; + +typedef void (*arch_sighandler_t) (int, SIGCONTEXT); +union sighandler +{ + arch_sighandler_t old; + void (*rt) (int, struct siginfo *, struct ucontext *); +}; +extern union sighandler __sighandler[NSIG]; + + /* Signals used for suspend/restart and for cancellation notification. */ extern int __pthread_sig_restart; @@ -367,4 +379,11 @@ extern void __linuxthreads_reap_event (void); /* This function is called to initialize the pthread library. */ extern void __pthread_initialize (void); + +/* Sighandler wrappers. */ +extern void __pthread_sighandler(int signo, SIGCONTEXT ctx); +extern void __pthread_sighandler_rt(int signo, struct siginfo *si, + struct ucontext *uc); +extern void __pthread_null_sighandler(int sig); + #endif /* internals.h */ diff --git a/linuxthreads/sighandler.c b/linuxthreads/sighandler.c new file mode 100644 index 0000000..ab8b38e --- /dev/null +++ b/linuxthreads/sighandler.c @@ -0,0 +1,69 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program 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. */ +/* */ +/* This program 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. */ + +/* Signal handlers */ + +#include "internals.h" + + +/* The wrapper around user-provided signal handlers */ +void __pthread_sighandler(int signo, SIGCONTEXT ctx) +{ + pthread_descr self; + char * in_sighandler; + self = thread_self(); + /* If we're in a sigwait operation, just record the signal received + and return without calling the user's handler */ + if (THREAD_GETMEM(self, p_sigwaiting)) { + THREAD_SETMEM(self, p_sigwaiting, 0); + THREAD_SETMEM(self, p_signal, signo); + return; + } + /* Record that we're in a signal handler and call the user's + handler function */ + in_sighandler = THREAD_GETMEM(self, p_in_sighandler); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME); + CALL_SIGHANDLER(__sighandler[signo].old, signo, ctx); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, NULL); +} + +/* The same, this time for real-time signals. */ +void __pthread_sighandler_rt(int signo, struct siginfo *si, + struct ucontext *uc) +{ + pthread_descr self; + char * in_sighandler; + self = thread_self(); + /* If we're in a sigwait operation, just record the signal received + and return without calling the user's handler */ + if (THREAD_GETMEM(self, p_sigwaiting)) { + THREAD_SETMEM(self, p_sigwaiting, 0); + THREAD_SETMEM(self, p_signal, signo); + return; + } + /* Record that we're in a signal handler and call the user's + handler function */ + in_sighandler = THREAD_GETMEM(self, p_in_sighandler); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME); + __sighandler[signo].rt(signo, si, uc); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, NULL); +} + + +/* A signal handler that does nothing */ +void __pthread_null_sighandler(int sig) { } diff --git a/linuxthreads/signals.c b/linuxthreads/signals.c index da3ce69..a11f865 100644 --- a/linuxthreads/signals.c +++ b/linuxthreads/signals.c @@ -20,7 +20,7 @@ #include "internals.h" #include "spinlock.h" #include <ucontext.h> -#include <sigcontextinfo.h> + int pthread_sigmask(int how, const sigset_t * newmask, sigset_t * oldmask) { @@ -68,60 +68,8 @@ int pthread_kill(pthread_t thread, int signo) return 0; } -/* User-provided signal handlers */ -typedef void (*arch_sighandler_t) (int, SIGCONTEXT); -static union -{ - arch_sighandler_t old; - void (*rt) (int, struct siginfo *, struct ucontext *); -} sighandler[NSIG] = { [1 ... NSIG - 1] = { (arch_sighandler_t) SIG_ERR } }; - -/* The wrapper around user-provided signal handlers */ -static void pthread_sighandler(int signo, SIGCONTEXT ctx) -{ - pthread_descr self; - char * in_sighandler; - self = thread_self(); - /* If we're in a sigwait operation, just record the signal received - and return without calling the user's handler */ - if (THREAD_GETMEM(self, p_sigwaiting)) { - THREAD_SETMEM(self, p_sigwaiting, 0); - THREAD_SETMEM(self, p_signal, signo); - return; - } - /* Record that we're in a signal handler and call the user's - handler function */ - in_sighandler = THREAD_GETMEM(self, p_in_sighandler); - if (in_sighandler == NULL) - THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME); - CALL_SIGHANDLER(sighandler[signo].old, signo, ctx); - if (in_sighandler == NULL) - THREAD_SETMEM(self, p_in_sighandler, NULL); -} - -/* The same, this time for real-time signals. */ -static void pthread_sighandler_rt(int signo, struct siginfo *si, - struct ucontext *uc) -{ - pthread_descr self; - char * in_sighandler; - self = thread_self(); - /* If we're in a sigwait operation, just record the signal received - and return without calling the user's handler */ - if (THREAD_GETMEM(self, p_sigwaiting)) { - THREAD_SETMEM(self, p_sigwaiting, 0); - THREAD_SETMEM(self, p_signal, signo); - return; - } - /* Record that we're in a signal handler and call the user's - handler function */ - in_sighandler = THREAD_GETMEM(self, p_in_sighandler); - if (in_sighandler == NULL) - THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME); - sighandler[signo].rt(signo, si, uc); - if (in_sighandler == NULL) - THREAD_SETMEM(self, p_in_sighandler, NULL); -} +union sighandler __sighandler[NSIG] = + { [1 ... NSIG - 1] = { (arch_sighandler_t) SIG_ERR } }; /* The wrapper around sigaction. Install our own signal handler around the signal. */ @@ -145,9 +93,9 @@ int __sigaction(int sig, const struct sigaction * act, && sig > 0 && sig < NSIG) { if (act->sa_flags & SA_SIGINFO) - newact.sa_handler = (__sighandler_t) pthread_sighandler_rt; + newact.sa_handler = (__sighandler_t) __pthread_sighandler_rt; else - newact.sa_handler = (__sighandler_t) pthread_sighandler; + newact.sa_handler = (__sighandler_t) __pthread_sighandler; } newactp = &newact; } @@ -161,20 +109,17 @@ int __sigaction(int sig, const struct sigaction * act, /* We may have inherited SIG_IGN from the parent, so return the kernel's idea of the signal handler the first time through. */ - && (__sighandler_t) sighandler[sig].old != SIG_ERR) - oact->sa_handler = (__sighandler_t) sighandler[sig].old; + && (__sighandler_t) __sighandler[sig].old != SIG_ERR) + oact->sa_handler = (__sighandler_t) __sighandler[sig].old; if (act) /* For the assignment it does not matter whether it's a normal or real-time signal. */ - sighandler[sig].old = (arch_sighandler_t) act->sa_handler; + __sighandler[sig].old = (arch_sighandler_t) act->sa_handler; } return 0; } strong_alias(__sigaction, sigaction) -/* A signal handler that does nothing */ -static void pthread_null_sighandler(int sig) { } - /* sigwait -- synchronously wait for a signal */ int sigwait(const sigset_t * set, int * sig) { @@ -198,10 +143,10 @@ int sigwait(const sigset_t * set, int * sig) s != __pthread_sig_cancel && s != __pthread_sig_debug) { sigdelset(&mask, s); - if (sighandler[s].old == (arch_sighandler_t) SIG_ERR || - sighandler[s].old == (arch_sighandler_t) SIG_DFL || - sighandler[s].old == (arch_sighandler_t) SIG_IGN) { - sa.sa_handler = pthread_null_sighandler; + if (__sighandler[s].old == (arch_sighandler_t) SIG_ERR || + __sighandler[s].old == (arch_sighandler_t) SIG_DFL || + __sighandler[s].old == (arch_sighandler_t) SIG_IGN) { + sa.sa_handler = __pthread_null_sighandler; sigfillset(&sa.sa_mask); sa.sa_flags = 0; sigaction(s, &sa, NULL); diff --git a/sysdeps/generic/dl-tls.c b/sysdeps/generic/dl-tls.c index 8d98786..0d6fcec 100644 --- a/sysdeps/generic/dl-tls.c +++ b/sysdeps/generic/dl-tls.c @@ -23,7 +23,6 @@ #include <unistd.h> #include <sys/param.h> -#include <abort-instr.h> #include <tls.h> /* We don't need any of this if TLS is not supported. */ @@ -42,21 +41,7 @@ static void __attribute__ ((__noreturn__)) oom (void) { - static const char msg[] = "\ -cannot allocate memory for thread-local data: ABORT\n"; - - __libc_write (STDERR_FILENO, msg, sizeof (msg) - 1); - - /* Kill ourself. */ - __kill (__getpid (), SIGKILL); - - /* Just in case something goes wrong with the kill. */ - while (1) - { -# ifdef ABORT_INSTRUCTION - ABORT_INSTRUCTION; -# endif - } + _dl_fatal_printf ("cannot allocate memory for thread-local data: ABORT\n"); } # endif diff --git a/sysdeps/ia64/Makefile b/sysdeps/ia64/Makefile index a9848b7..dd7365c 100644 --- a/sysdeps/ia64/Makefile +++ b/sysdeps/ia64/Makefile @@ -9,6 +9,13 @@ ifeq ($(subdir), csu) CPPFLAGS-start.S = -D__ASSEMBLY__ sysdep_routines += hp-timing static-only-routines += hp-timing + +ifeq (yes,$(build-shared)) +# Compatibility +sysdep_routines += ia64libgcc +shared-only-routines += ia64libgcc +endif +endif endif ifeq ($(subdir),elf) diff --git a/sysdeps/ia64/Versions b/sysdeps/ia64/Versions index 70a183c..6910566 100644 --- a/sysdeps/ia64/Versions +++ b/sysdeps/ia64/Versions @@ -5,3 +5,10 @@ ld { _dl_function_address; } } +libc { + GLIBC_2.2 { + # Functions from libgcc. + __divtf3; __divdf3; __divsf3; __divdi3; __moddi3; __udivdi3; __umoddi3; + __multi3; + } +} diff --git a/sysdeps/ia64/ia64libgcc.S b/sysdeps/ia64/ia64libgcc.S new file mode 100644 index 0000000..0ff29de --- /dev/null +++ b/sysdeps/ia64/ia64libgcc.S @@ -0,0 +1,350 @@ +/* From the Intel IA-64 Optimization Guide, choose the minimum latency + alternative. */ + +#include <sysdep.h> +#undef ret + +#include <shlib-compat.h> + +#if SHLIB_COMPAT(libc, GLIBC_2_2, GLIBC_2_2_6) + +/* __divtf3 + Compute a 80-bit IEEE double-extended quotient. + farg0 holds the dividend. farg1 holds the divisor. */ + +ENTRY(___divtf3) + cmp.eq p7, p0 = r0, r0 + frcpa.s0 f10, p6 = farg0, farg1 + ;; +(p6) cmp.ne p7, p0 = r0, r0 + .pred.rel.mutex p6, p7 +(p6) fnma.s1 f11 = farg1, f10, f1 +(p6) fma.s1 f12 = farg0, f10, f0 + ;; +(p6) fma.s1 f13 = f11, f11, f0 +(p6) fma.s1 f14 = f11, f11, f11 + ;; +(p6) fma.s1 f11 = f13, f13, f11 +(p6) fma.s1 f13 = f14, f10, f10 + ;; +(p6) fma.s1 f10 = f13, f11, f10 +(p6) fnma.s1 f11 = farg1, f12, farg0 + ;; +(p6) fma.s1 f11 = f11, f10, f12 +(p6) fnma.s1 f12 = farg1, f10, f1 + ;; +(p6) fma.s1 f10 = f12, f10, f10 +(p6) fnma.s1 f12 = farg1, f11, farg0 + ;; +(p6) fma.s0 fret0 = f12, f10, f11 +(p7) mov fret0 = f10 + br.ret.sptk rp +END(___divtf3) + .symver ___divtf3, __divtf3@GLIBC_2.2 + +/* __divdf3 + Compute a 64-bit IEEE double quotient. + farg0 holds the dividend. farg1 holds the divisor. */ + +ENTRY(___divdf3) + cmp.eq p7, p0 = r0, r0 + frcpa.s0 f10, p6 = farg0, farg1 + ;; +(p6) cmp.ne p7, p0 = r0, r0 + .pred.rel.mutex p6, p7 +(p6) fmpy.s1 f11 = farg0, f10 +(p6) fnma.s1 f12 = farg1, f10, f1 + ;; +(p6) fma.s1 f11 = f12, f11, f11 +(p6) fmpy.s1 f13 = f12, f12 + ;; +(p6) fma.s1 f10 = f12, f10, f10 +(p6) fma.s1 f11 = f13, f11, f11 + ;; +(p6) fmpy.s1 f12 = f13, f13 +(p6) fma.s1 f10 = f13, f10, f10 + ;; +(p6) fma.d.s1 f11 = f12, f11, f11 +(p6) fma.s1 f10 = f12, f10, f10 + ;; +(p6) fnma.d.s1 f8 = farg1, f11, farg0 + ;; +(p6) fma.d fret0 = f8, f10, f11 +(p7) mov fret0 = f10 + br.ret.sptk rp + ;; +END(___divdf3) + .symver ___divdf3, __divdf3@GLIBC_2.2 + +/* __divsf3 + Compute a 32-bit IEEE float quotient. + farg0 holds the dividend. farg1 holds the divisor. */ + +ENTRY(___divsf3) + cmp.eq p7, p0 = r0, r0 + frcpa.s0 f10, p6 = farg0, farg1 + ;; +(p6) cmp.ne p7, p0 = r0, r0 + .pred.rel.mutex p6, p7 +(p6) fmpy.s1 f8 = farg0, f10 +(p6) fnma.s1 f9 = farg1, f10, f1 + ;; +(p6) fma.s1 f8 = f9, f8, f8 +(p6) fmpy.s1 f9 = f9, f9 + ;; +(p6) fma.s1 f8 = f9, f8, f8 +(p6) fmpy.s1 f9 = f9, f9 + ;; +(p6) fma.d.s1 f10 = f9, f8, f8 + ;; +(p6) fnorm.s.s0 fret0 = f10 +(p7) mov fret0 = f10 + br.ret.sptk rp + ;; +END(___divsf3) + .symver ___divsf3, __divsf3@GLIBC2.2 + +/* __divdi3 + Compute a 64-bit integer quotient. + in0 holds the dividend. in1 holds the divisor. */ + +ENTRY(___divdi3) + .regstk 2,0,0,0 + /* Transfer inputs to FP registers. */ + setf.sig f8 = in0 + setf.sig f9 = in1 + ;; + /* Convert the inputs to FP, so that they won't be treated as + unsigned. */ + fcvt.xf f8 = f8 + fcvt.xf f9 = f9 + ;; + /* Compute the reciprocal approximation. */ + frcpa.s1 f10, p6 = f8, f9 + ;; + /* 3 Newton-Raphson iterations. */ +(p6) fnma.s1 f11 = f9, f10, f1 +(p6) fmpy.s1 f12 = f8, f10 + ;; +(p6) fmpy.s1 f13 = f11, f11 +(p6) fma.s1 f12 = f11, f12, f12 + ;; +(p6) fma.s1 f10 = f11, f10, f10 +(p6) fma.s1 f11 = f13, f12, f12 + ;; +(p6) fma.s1 f10 = f13, f10, f10 +(p6) fnma.s1 f12 = f9, f11, f8 + ;; +(p6) fma.s1 f10 = f12, f10, f11 + ;; + /* Round quotient to an integer. */ + fcvt.fx.trunc.s1 f10 = f10 + ;; + /* Transfer result to GP registers. */ + getf.sig ret0 = f10 + br.ret.sptk rp + ;; +END(___divdi3) + .symver ___divdi3, __divdi3@GLIBC_2.2 + +/* __moddi3 + Compute a 64-bit integer modulus. + in0 holds the dividend (a). in1 holds the divisor (b). */ + +ENTRY(___moddi3) + .regstk 2,0,0,0 + /* Transfer inputs to FP registers. */ + setf.sig f14 = in0 + setf.sig f9 = in1 + ;; + /* Convert the inputs to FP, so that they won't be treated as + unsigned. */ + fcvt.xf f8 = f14 + fcvt.xf f9 = f9 + ;; + /* Compute the reciprocal approximation. */ + frcpa.s1 f10, p6 = f8, f9 + ;; + /* 3 Newton-Raphson iterations. */ +(p6) fmpy.s1 f12 = f8, f10 +(p6) fnma.s1 f11 = f9, f10, f1 + ;; +(p6) fma.s1 f12 = f11, f12, f12 +(p6) fmpy.s1 f13 = f11, f11 + ;; +(p6) fma.s1 f10 = f11, f10, f10 +(p6) fma.s1 f11 = f13, f12, f12 + ;; + sub in1 = r0, in1 +(p6) fma.s1 f10 = f13, f10, f10 +(p6) fnma.s1 f12 = f9, f11, f8 + ;; + setf.sig f9 = in1 +(p6) fma.s1 f10 = f12, f10, f11 + ;; + fcvt.fx.trunc.s1 f10 = f10 + ;; + /* r = q * (-b) + a */ + xma.l f10 = f10, f9, f14 + ;; + /* Transfer result to GP registers. */ + getf.sig ret0 = f10 + br.ret.sptk rp + ;; +END(___moddi3) + .symver ___moddi3, __moddi3@GLIBC_2.2 + +/* __udivdi3 + Compute a 64-bit unsigned integer quotient. + in0 holds the dividend. in1 holds the divisor. */ + +ENTRY(___udivdi3) + .regstk 2,0,0,0 + /* Transfer inputs to FP registers. */ + setf.sig f8 = in0 + setf.sig f9 = in1 + ;; + /* Convert the inputs to FP, to avoid FP software-assist faults. */ + fcvt.xuf.s1 f8 = f8 + fcvt.xuf.s1 f9 = f9 + ;; + /* Compute the reciprocal approximation. */ + frcpa.s1 f10, p6 = f8, f9 + ;; + /* 3 Newton-Raphson iterations. */ +(p6) fnma.s1 f11 = f9, f10, f1 +(p6) fmpy.s1 f12 = f8, f10 + ;; +(p6) fmpy.s1 f13 = f11, f11 +(p6) fma.s1 f12 = f11, f12, f12 + ;; +(p6) fma.s1 f10 = f11, f10, f10 +(p6) fma.s1 f11 = f13, f12, f12 + ;; +(p6) fma.s1 f10 = f13, f10, f10 +(p6) fnma.s1 f12 = f9, f11, f8 + ;; +(p6) fma.s1 f10 = f12, f10, f11 + ;; + /* Round quotient to an unsigned integer. */ + fcvt.fxu.trunc.s1 f10 = f10 + ;; + /* Transfer result to GP registers. */ + getf.sig ret0 = f10 + br.ret.sptk rp + ;; +END(___udivdi3) + .symver ___udivdi3, __udivdi3@GLIBC_2.2 + +/* __umoddi3 + Compute a 64-bit unsigned integer modulus. + in0 holds the dividend (a). in1 holds the divisor (b). */ + +ENTRY(___umoddi3) + .regstk 2,0,0,0 + /* Transfer inputs to FP registers. */ + setf.sig f14 = in0 + setf.sig f9 = in1 + ;; + /* Convert the inputs to FP, to avoid FP software assist faults. */ + fcvt.xuf.s1 f8 = f14 + fcvt.xuf.s1 f9 = f9 + ;; + /* Compute the reciprocal approximation. */ + frcpa.s1 f10, p6 = f8, f9 + ;; + /* 3 Newton-Raphson iterations. */ +(p6) fmpy.s1 f12 = f8, f10 +(p6) fnma.s1 f11 = f9, f10, f1 + ;; +(p6) fma.s1 f12 = f11, f12, f12 +(p6) fmpy.s1 f13 = f11, f11 + ;; +(p6) fma.s1 f10 = f11, f10, f10 +(p6) fma.s1 f11 = f13, f12, f12 + ;; + sub in1 = r0, in1 +(p6) fma.s1 f10 = f13, f10, f10 +(p6) fnma.s1 f12 = f9, f11, f8 + ;; + setf.sig f9 = in1 +(p6) fma.s1 f10 = f12, f10, f11 + ;; + /* Round quotient to an unsigned integer. */ + fcvt.fxu.trunc.s1 f10 = f10 + ;; + /* r = q * (-b) + a */ + xma.l f10 = f10, f9, f14 + ;; + /* Transfer result to GP registers. */ + getf.sig ret0 = f10 + br.ret.sptk rp + ;; +END(___umoddi3) + .symver ___umoddi3, __umoddi3@GLIBC_2.2 + +/* __multi3 + Compute a 128-bit multiply of 128-bit multiplicands. + in0/in1 holds one multiplicand (a), in2/in3 holds the other one (b). */ + +ENTRY(___multi3) + .regstk 4,0,0,0 + setf.sig f6 = in1 + movl r19 = 0xffffffff + setf.sig f7 = in2 + ;; + and r14 = r19, in0 + ;; + setf.sig f10 = r14 + and r14 = r19, in2 + xmpy.l f9 = f6, f7 + ;; + setf.sig f6 = r14 + shr.u r14 = in0, 32 + ;; + setf.sig f7 = r14 + shr.u r14 = in2, 32 + ;; + setf.sig f8 = r14 + xmpy.l f11 = f10, f6 + xmpy.l f6 = f7, f6 + ;; + getf.sig r16 = f11 + xmpy.l f7 = f7, f8 + ;; + shr.u r14 = r16, 32 + and r16 = r19, r16 + getf.sig r17 = f6 + setf.sig f6 = in0 + ;; + setf.sig f11 = r14 + getf.sig r21 = f7 + setf.sig f7 = in3 + ;; + xma.l f11 = f10, f8, f11 + xma.l f6 = f6, f7, f9 + ;; + getf.sig r18 = f11 + ;; + add r18 = r18, r17 + ;; + and r15 = r19, r18 + cmp.ltu p7, p6 = r18, r17 + ;; + getf.sig r22 = f6 +(p7) adds r14 = 1, r19 + ;; +(p7) add r21 = r21, r14 + shr.u r14 = r18, 32 + shl r15 = r15, 32 + ;; + add r20 = r21, r14 + ;; + add ret0 = r15, r16 + add ret1 = r22, r20 + br.ret.sptk rp + ;; +END(___multi3) + .symver ___multi3, __multi3@GLIBC_2.2 + +#endif |