mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 19:00:07 +00:00
62f29da7cb
2003-01-26 Andreas Schwab <schwab@suse.de> * sysdeps/wordsize-32/divdi3.c: Export the functions only as compatibility symbols. Remove INTDEF for __divdi3. * sysdeps/wordsize-32/lldiv.c: Don't use __divdi3_internal. * sysdeps/powerpc/powerpc32/divdi3.c: Remove. * sysdeps/powerpc/powerpc32/Makefile (CPPFLAGS-divdi3.c): Don't define. * sysdeps/powerpc/powerpc32/Dist: Remove divdi3.c. 2003-01-24 Jakub Jelinek <jakub@redhat.com> * elf/tls-macros.h: Add SPARC 32-bit definitions. * sysdeps/sparc/sparc32/elf/configure.in: Add TLS check. * sysdeps/sparc/sparc32/dl-machine.h: Add dl_machine_h guards for the first half of the header. Include tls.h. (elf_machine_type_class): Return ELF_RTYPE_CLASS_PLT for TLS relocs too. (elf_machine_rela): Handle TLS relocs. * sysdeps/sparc/dl-tls.h: New file. * sysdeps/unix/sysv/linux/sparc/sparc32/socket.S: Add cancellation support. * sysdeps/sparc/sparc32/sparcv9/hp-timing.h: Use %g6 instead of %g7. * sysdeps/sparc/sparc32/memchr.S: Likewise. * sysdeps/sparc/sparc32/memcpy.S: Likewise. * sysdeps/sparc/sparc32/strcat.S: Likewise. * sysdeps/sparc/sparc32/strchr.S: Likewise. * sysdeps/sparc/sparc32/strcmp.S: Likewise. * sysdeps/sparc/sparc32/strcpy.S: Likewise. * sysdeps/sparc/sparc64/sparcv9b/memcpy.S: Likewise. * sysdeps/sparc/sparc64/hp-timing.h: Likewise. * sysdeps/sparc/sparc64/memcpy.S: Likewise. * sysdeps/sparc/sparc64/stpcpy.S: Likewise. * sysdeps/sparc/sparc64/stpncpy.S: Likewise. * sysdeps/sparc/sparc64/strcat.S: Likewise. * sysdeps/sparc/sparc64/strchr.S: Likewise. * sysdeps/sparc/sparc64/strcmp.S: Likewise. * sysdeps/sparc/sparc64/strcpy.S: Likewise. * sysdeps/sparc/sparc64/strncmp.S: Likewise. * sysdeps/sparc/sparc64/strncpy.S: Likewise. * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep.h: Likewise. 2003-01-24 Andreas Schwab <schwab@suse.de> * elf/dl-close.c (_dl_close): Don't relocate DT_FINI_ARRAY elements, and process them backwards. * elf/Makefile ($(objpfx)tst-array4): New target. ($(objpfx)tst-array4.out): Likewise. (tests) [$(have-initfini-array) = yes]: Add tst-array4. * elf/tst-array4.c: New file. * elf/tst-array4.exp: Likewise. 2003-01-24 Steven Munroe <sjmunroe@us.ibm.com> * sysdeps/unix/sysv/linux/powerpc/powerpc64/fe_nomask.c: New file. 2003-01-27 Guido Guenther <agx@sigxcpu.org> * sysdeps/unix/sysv/linux/mips/sysdep.h (SYSCALL_ERROR_LABEL): Define. * sysdeps/unix/sysv/linux/mips/pread.c: Add support for cancellation handling and handle both __NR_pread64 and __NR_pread. * sysdeps/unix/sysv/linux/mips/pread64.c: Likewise. * sysdeps/unix/sysv/linux/mips/pwrite.c: Add support for cancellation handling and handle both __NR_pwrite64 and __NR_pwrite. * sysdeps/unix/sysv/linux/mips/pwrite64.c: Likewise. * sysdeps/unix/mips/sysdep.S: Don't set errno in the _LIBC_REENTRANT case, use register names consistently. 2003-01-27 Wolfram Gloger <wg@malloc.de> * malloc/hooks.c (mem2chunk_check): Check alignment of mem pointer, not of the computed chunk. Bug report from Carlos O'Donell <carlos@baldric.uwo.ca>.
341 lines
6.6 KiB
C
341 lines
6.6 KiB
C
/* 64-bit multiplication and division
|
|
Copyright (C) 1989, 1992-1999, 2000, 2001, 2002, 2003
|
|
Free Software Foundation, Inc.
|
|
This file is part of the GNU C Library.
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with the GNU C Library; if not, write to the Free
|
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
02111-1307 USA. */
|
|
|
|
#include <endian.h>
|
|
#include <stdlib.h>
|
|
#include <bits/wordsize.h>
|
|
|
|
#if __WORDSIZE != 32
|
|
#error This is for 32-bit targets only
|
|
#endif
|
|
|
|
typedef unsigned int UQItype __attribute__ ((mode (QI)));
|
|
typedef int SItype __attribute__ ((mode (SI)));
|
|
typedef unsigned int USItype __attribute__ ((mode (SI)));
|
|
typedef int DItype __attribute__ ((mode (DI)));
|
|
typedef unsigned int UDItype __attribute__ ((mode (DI)));
|
|
#define Wtype SItype
|
|
#define HWtype SItype
|
|
#define DWtype DItype
|
|
#define UWtype USItype
|
|
#define UHWtype USItype
|
|
#define UDWtype UDItype
|
|
#define W_TYPE_SIZE 32
|
|
|
|
#include <stdlib/longlong.h>
|
|
|
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
|
struct DWstruct { Wtype high, low;};
|
|
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
|
struct DWstruct { Wtype low, high;};
|
|
#else
|
|
#error Unhandled endianity
|
|
#endif
|
|
typedef union { struct DWstruct s; DWtype ll; } DWunion;
|
|
|
|
/* Prototypes of exported functions. */
|
|
extern DWtype __divdi3 (DWtype u, DWtype v);
|
|
extern DWtype __moddi3 (DWtype u, DWtype v);
|
|
extern UDWtype __udivdi3 (UDWtype u, UDWtype v);
|
|
extern UDWtype __umoddi3 (UDWtype u, UDWtype v);
|
|
|
|
static UDWtype
|
|
__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
|
|
{
|
|
DWunion ww;
|
|
DWunion nn, dd;
|
|
DWunion rr;
|
|
UWtype d0, d1, n0, n1, n2;
|
|
UWtype q0, q1;
|
|
UWtype b, bm;
|
|
|
|
nn.ll = n;
|
|
dd.ll = d;
|
|
|
|
d0 = dd.s.low;
|
|
d1 = dd.s.high;
|
|
n0 = nn.s.low;
|
|
n1 = nn.s.high;
|
|
|
|
#if !UDIV_NEEDS_NORMALIZATION
|
|
if (d1 == 0)
|
|
{
|
|
if (d0 > n1)
|
|
{
|
|
/* 0q = nn / 0D */
|
|
|
|
udiv_qrnnd (q0, n0, n1, n0, d0);
|
|
q1 = 0;
|
|
|
|
/* Remainder in n0. */
|
|
}
|
|
else
|
|
{
|
|
/* qq = NN / 0d */
|
|
|
|
if (d0 == 0)
|
|
d0 = 1 / d0; /* Divide intentionally by zero. */
|
|
|
|
udiv_qrnnd (q1, n1, 0, n1, d0);
|
|
udiv_qrnnd (q0, n0, n1, n0, d0);
|
|
|
|
/* Remainder in n0. */
|
|
}
|
|
|
|
if (rp != 0)
|
|
{
|
|
rr.s.low = n0;
|
|
rr.s.high = 0;
|
|
*rp = rr.ll;
|
|
}
|
|
}
|
|
|
|
#else /* UDIV_NEEDS_NORMALIZATION */
|
|
|
|
if (d1 == 0)
|
|
{
|
|
if (d0 > n1)
|
|
{
|
|
/* 0q = nn / 0D */
|
|
|
|
count_leading_zeros (bm, d0);
|
|
|
|
if (bm != 0)
|
|
{
|
|
/* Normalize, i.e. make the most significant bit of the
|
|
denominator set. */
|
|
|
|
d0 = d0 << bm;
|
|
n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
|
|
n0 = n0 << bm;
|
|
}
|
|
|
|
udiv_qrnnd (q0, n0, n1, n0, d0);
|
|
q1 = 0;
|
|
|
|
/* Remainder in n0 >> bm. */
|
|
}
|
|
else
|
|
{
|
|
/* qq = NN / 0d */
|
|
|
|
if (d0 == 0)
|
|
d0 = 1 / d0; /* Divide intentionally by zero. */
|
|
|
|
count_leading_zeros (bm, d0);
|
|
|
|
if (bm == 0)
|
|
{
|
|
/* From (n1 >= d0) /\ (the most significant bit of d0 is set),
|
|
conclude (the most significant bit of n1 is set) /\ (the
|
|
leading quotient digit q1 = 1).
|
|
|
|
This special case is necessary, not an optimization.
|
|
(Shifts counts of W_TYPE_SIZE are undefined.) */
|
|
|
|
n1 -= d0;
|
|
q1 = 1;
|
|
}
|
|
else
|
|
{
|
|
/* Normalize. */
|
|
|
|
b = W_TYPE_SIZE - bm;
|
|
|
|
d0 = d0 << bm;
|
|
n2 = n1 >> b;
|
|
n1 = (n1 << bm) | (n0 >> b);
|
|
n0 = n0 << bm;
|
|
|
|
udiv_qrnnd (q1, n1, n2, n1, d0);
|
|
}
|
|
|
|
/* n1 != d0... */
|
|
|
|
udiv_qrnnd (q0, n0, n1, n0, d0);
|
|
|
|
/* Remainder in n0 >> bm. */
|
|
}
|
|
|
|
if (rp != 0)
|
|
{
|
|
rr.s.low = n0 >> bm;
|
|
rr.s.high = 0;
|
|
*rp = rr.ll;
|
|
}
|
|
}
|
|
#endif /* UDIV_NEEDS_NORMALIZATION */
|
|
|
|
else
|
|
{
|
|
if (d1 > n1)
|
|
{
|
|
/* 00 = nn / DD */
|
|
|
|
q0 = 0;
|
|
q1 = 0;
|
|
|
|
/* Remainder in n1n0. */
|
|
if (rp != 0)
|
|
{
|
|
rr.s.low = n0;
|
|
rr.s.high = n1;
|
|
*rp = rr.ll;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* 0q = NN / dd */
|
|
|
|
count_leading_zeros (bm, d1);
|
|
if (bm == 0)
|
|
{
|
|
/* From (n1 >= d1) /\ (the most significant bit of d1 is set),
|
|
conclude (the most significant bit of n1 is set) /\ (the
|
|
quotient digit q0 = 0 or 1).
|
|
|
|
This special case is necessary, not an optimization. */
|
|
|
|
/* The condition on the next line takes advantage of that
|
|
n1 >= d1 (true due to program flow). */
|
|
if (n1 > d1 || n0 >= d0)
|
|
{
|
|
q0 = 1;
|
|
sub_ddmmss (n1, n0, n1, n0, d1, d0);
|
|
}
|
|
else
|
|
q0 = 0;
|
|
|
|
q1 = 0;
|
|
|
|
if (rp != 0)
|
|
{
|
|
rr.s.low = n0;
|
|
rr.s.high = n1;
|
|
*rp = rr.ll;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UWtype m1, m0;
|
|
/* Normalize. */
|
|
|
|
b = W_TYPE_SIZE - bm;
|
|
|
|
d1 = (d1 << bm) | (d0 >> b);
|
|
d0 = d0 << bm;
|
|
n2 = n1 >> b;
|
|
n1 = (n1 << bm) | (n0 >> b);
|
|
n0 = n0 << bm;
|
|
|
|
udiv_qrnnd (q0, n1, n2, n1, d1);
|
|
umul_ppmm (m1, m0, q0, d0);
|
|
|
|
if (m1 > n1 || (m1 == n1 && m0 > n0))
|
|
{
|
|
q0--;
|
|
sub_ddmmss (m1, m0, m1, m0, d1, d0);
|
|
}
|
|
|
|
q1 = 0;
|
|
|
|
/* Remainder in (n1n0 - m1m0) >> bm. */
|
|
if (rp != 0)
|
|
{
|
|
sub_ddmmss (n1, n0, n1, n0, m1, m0);
|
|
rr.s.low = (n1 << b) | (n0 >> bm);
|
|
rr.s.high = n1 >> bm;
|
|
*rp = rr.ll;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ww.s.low = q0;
|
|
ww.s.high = q1;
|
|
return ww.ll;
|
|
}
|
|
|
|
DWtype
|
|
__divdi3 (DWtype u, DWtype v)
|
|
{
|
|
Wtype c = 0;
|
|
DWtype w;
|
|
|
|
if (u < 0)
|
|
{
|
|
c = ~c;
|
|
u = -u;
|
|
}
|
|
if (v < 0)
|
|
{
|
|
c = ~c;
|
|
v = -v;
|
|
}
|
|
w = __udivmoddi4 (u, v, NULL);
|
|
if (c)
|
|
w = -w;
|
|
return w;
|
|
}
|
|
|
|
DWtype
|
|
__moddi3 (DWtype u, DWtype v)
|
|
{
|
|
Wtype c = 0;
|
|
DWtype w;
|
|
|
|
if (u < 0)
|
|
{
|
|
c = ~c;
|
|
u = -u;
|
|
}
|
|
if (v < 0)
|
|
v = -v;
|
|
__udivmoddi4 (u, v, &w);
|
|
if (c)
|
|
w = -w;
|
|
return w;
|
|
}
|
|
|
|
UDWtype
|
|
__udivdi3 (UDWtype u, UDWtype v)
|
|
{
|
|
return __udivmoddi4 (u, v, NULL);
|
|
}
|
|
|
|
UDWtype
|
|
__umoddi3 (UDWtype u, UDWtype v)
|
|
{
|
|
UDWtype w;
|
|
|
|
__udivmoddi4 (u, v, &w);
|
|
return w;
|
|
}
|
|
|
|
/* We declare these with compat_symbol so that they are not visible at
|
|
link time. Programs must use the functions from libgcc. */
|
|
#if defined HAVE_ELF && defined SHARED && defined DO_VERSIONING
|
|
# include <shlib-compat.h>
|
|
compat_symbol (libc, __divdi3, __divdi3, GLIBC_2_0);
|
|
compat_symbol (libc, __moddi3, __moddi3, GLIBC_2_0);
|
|
compat_symbol (libc, __udivdi3, __udivdi3, GLIBC_2_0);
|
|
compat_symbol (libc, __umoddi3, __umoddi3, GLIBC_2_0);
|
|
#endif
|