diff options
98 files changed, 3695 insertions, 1030 deletions
@@ -1,5 +1,239 @@ +Tue Mar 19 14:18:42 1996 Roland McGrath <roland@charlie-brown.gnu.ai.mit.edu> + + * sysdeps/unix/bsd/pause.c: Moved to sysdeps/unix/common/pause.c. + +Mon Mar 4 20:17:28 1996 David Mosberger-Tang <davidm@azstarnet.com> + + * sysdeps/unix/sysv/linux/adjtime.c: Use INT_MAX instead of LONG_MAX. + + * sysdeps/unix/sysv/Makefile (sysdep_routines): Don't add s_getdents. + + * sysdeps/unix/sysv/linux/Makefile (sysdep_routines): Don't add mount, + umount. + + * sysdeps/alpha/__math.h (atan, cabs): New functions. + + * sysdeps/unix/sysv/linux/alpha/sigsuspend.S: new file (syscall + expects set-value, not pointer to it). + +Sun Feb 25 22:36:10 1996 David Mosberger-Tang <davidm@azstarnet.com> + + * sysdeps/unix/sysv/linux/alpha/profil-counter.h: New file. + + * gmon/gmon.c (__bb_head): new variable. + (write_hist, write_call_graph, write_bb_counts): new functions. + (_mcleanup): modified to call above functions instead of directly + writing out gmon.out. + * gmon/sys/gmon.h (struct __bb): New type. + (struct gmonhdr): Type removed. + (struct gmonparam): New member `log_hashfraction'. + (GMONVERSION): Macro removed. + + * gmon/sys/gmon_out.h, gmon/bb_exit_func.c, + sysdeps/generic/bb_init_func.c, sysdeps/alpha/bb_init_func.S: new + files. + * gmon/Makefile (headers): Add sys/gmon_out.h. + (routines): Add bb_init_func, bb_exit_func. + + * gmon/mcount.c: Avoid integer division. + +Wed Feb 21 23:56:41 1996 David Mosberger-Tang <davidm@azstarnet.com> + + * sysdeps/alpha/setjmp.S: switched order in which sp and fp are + passed to match what __sigsetjmp_aux() expects. + +Tue Feb 20 11:33:46 1996 David Mosberger-Tang <davidm@azstarnet.com> + + * sysdeps/unix/sysv/linux/alpha/syscalls.list (select, bind, + connect, getpeername, getsockname, listen, recv, recvfrom, + recvmsg, send, sendmsg, sendto, setsockopt, shutdown, socketpair): + added to override same-name assembly file in the parent directory. + + * stdlib/stdlib.h: add include of sys/types.h in front of random + etc declarations to ensure int32_t is declared. + + * stdlib/random.c, stdlib/random_r.c: replaced "long int" by int32_t + where 32 bit integers are required. Also change LONG_MAX into + 0x7fffffff since the intent is to turn off the sign bit in a + 32 bit integer. + + * time/offtime.c (__offtime): Use Paul Eggert's code to deal + with very large values for "days" (e.g., 64 bit values). + +Mon Feb 19 22:22:12 1996 David Mosberger-Tang <davidm@azstarnet.com> + + * stdlib/stdlib.h (__random, __random_r, random_r, struct + random_data): use int32_t instead of `long int'. + +Sat Feb 17 11:29:29 1996 David Mosberger-Tang <davidm@azstarnet.com> + + * sysdeps/unix/sysv/linux/alpha/ioperm.c: new file. + + * sysdeps/alpha/ffs.S: new file. + + * sysdeps/alpha/fabs.c: File removed. + + * time/tzfile.c (__tzfile_read): counter variable is i, *not* + num_transitions! + + * time/offtime.c: make capable of dealing with very large (64 bit) + time_t values. Use old algorithm until a year is reached that + is an integer multiple of 400, then use DAYS_PER_400_YEARS to + do the remainder in a single division. + + * sysdeps/generic/ffs.c (ffs): fix variable declarations to + be unsigned int, not unsigned long. + + * string/test-ffs.c (main): add test case with all upper bits + set. + + * stdlib/tst-strtol.c: add tests cases for machines where + sizeof(long)==8. + + * stdlib/testrand.c (main): disallow rand() to return negative + integers. + + * stdlib/testmb.c (main): fix format to use %lx instead of %x. + + * stdlib/stdlib.h: on 64 bit machines, declare + struct random_data, __random(), __random_r, and random_r to + return "int" instead of "long int". + + * stdlib/random_r.c: 64 bit machines use "int" instead of "long + int". Similarly, use INT_MAX instead of LONG_MAX. + + * stdlib/random.c: on 64 bit machines, randtbl[] and __random[] + need to operate on "int" instead of "long int". + + * locale/locfile-hash.c (compute_hashval): make shifted constant + a long to avoid loosing bits on 64 bit machines. + + * dirent/tst-seekdir.c (main): fix confusing comment; print + a line to mark point where directory is rewound. + +Fri Feb 16 15:01:49 1996 David Mosberger-Tang <davidm@azstarnet.com> + + * time/strftime.c (strftime): any hour > 11 is PM (not > 12!). + +Wed Feb 14 00:21:17 1996 David Mosberger-Tang <davidm@azstarnet.com> + + * sysdeps/unix/sysv/linux/alpha/Makefile, + sysdeps/unix/sysv/linux/alpha/brk.S, + sysdeps/unix/sysv/linux/alpha/fpu_control.c, + sysdeps/unix/sysv/linux/alpha/fpu_control.h, + sysdeps/unix/sysv/linux/alpha/ieee_get_fp_control.S, + sysdeps/unix/sysv/linux/alpha/ieee_set_fp_control.S, + sysdeps/unix/sysv/linux/alpha/pipe.S, + sysdeps/unix/sysv/linux/alpha/setfpucw.c, + sysdeps/unix/sysv/linux/alpha/sigprocmask.c, + sysdeps/unix/sysv/linux/alpha/speed.c, + sysdeps/unix/sysv/linux/alpha/start.S, + sysdeps/unix/sysv/linux/alpha/syscall.S, + sysdeps/unix/sysv/linux/alpha/syscalls.list, + sysdeps/unix/sysv/linux/alpha/alpha/regdef.h, + sysdeps/unix/sysv/linux/alpha/sysdep.S, + sysdeps/unix/sysv/linux/alpha/sysdep.h: New files. + + * sysdeps/alpha/setjmp_aux.c (__sigsetjmp_aux): restore return + address register before returning (gcc 2.7.1 doesn't do it, + presumably because $26 is declared as a global variable). + + * sysdeps/unix/sysv/linux/sys/mman.h: msync was missing "flags" + argument. + + * sysdeps/unix/alarm.c (alarm): do roundup using test & increment + instead of multiplication. + + * sysdeps/posix/sleep.c (sleep): initialize sa_mask to mask of + currently blocked signals instead of the empty mask to ensure + that execution of alarm handler occurs with none of the currently + blocked signals enabled. + + * sysdeps/unix/alpha/sysdep.h: new file (adapted from OSF/1 version). + + * sysdeps/unix/bsd/osf/alpha/sysdep.h: include + sysdeps/unix/alpha/sysdep.h and removed definitions now in that file. + + * sysdeps/alpha/divrem.S, sysdeps/alpha/htonl.S, + sysdeps/alpha/htons.S, sysdeps/alpha/machine-gmon.h, + sysdeps/alpha/_mcount.S, sysdeps/alpha/ntohl.s, sysdeps/alpha/ntohs.s, + sysdeps/alpha/strlen.S: New files. + + * sysdeps/alpha/divl.S, sysdeps/alpha/divlu.S, sysdeps/alpha/divq.S, + sysdeps/alpha/divqu.S, sysdeps/alpha/divrem.m4, + sysdeps/alpha/macros.m4, sysdeps/alpha/reml.S, sysdeps/alpha/remlu.S, + sysdeps/alpha/remq.S, sysdeps/alpha/remqu.S, sysdeps/alpha/strlen.c: + Removed. + + * sysdeps/generic/sbrk.c (__sbrk): argument is of type ptrdiff_t, not + int. + + * sysdeps/alpha/__longjmp.c (__longjmp): moved dummy while loop + to end of function to avoid a jump across NOPs. + + * sysdeps/alpha/Makefile (sysdep_routines): Removed all rules + pertaining to integer division/remainder routines since new code + doesn't require them. + + * sunrpc/xdr_mem.c, sunrpc/xdr_stdio.c: Use 4 instead of sizeof(long) + where 32 bit quantities are consumed/stored. Various other minor + 64-bit cleanups (casting). + + * sunrpc/xdr.c (xdr_int): test for sizeof(int)==4 to determine + whether xdr_long or xdr_short should be used to encode an int. + Notice that an xdr_long is 4 bytes independent of the architecture + (otherwise no Alpha could interoperate with existing NFS servers, + for example). Ditto for enums. + + * sunrpc/svc_udp.c (svcudp_recv): changed test from 4*sizeof(u_long) + to 16 since it really wants 16 bytes. + + * sunrpc/svc.c (maskp): changed from u_long* to u_int32*. + + * sunrpc/rpc_cmsg.c (xdr_callmsg), sunrpc/svc_authux.c: increment + "buf" pointer by casting it to a char* first since a long* may be 8 + bytes or more and oa->oa_length may be any multiple of 4. + + * sunrpc/rpc/xdr.h (IXDR_GET_LONG, IXDR_PUT_LONG): change casts to + u_int32_t (instead of u_long). + + * sunrpc/clnt_udp.c (clntudp_call): replaced sizeof(u_long) by 4 + since it really is testing for 32 bits. Fixed casts to use + u_int32 instead of u_long. + * sunrpc/xdr_rec.c: Likewise. + + * sunrpc/clnt_tcp.c (clnttcp_call): replaced u_long by u_int32. + * sunrpc/rpc/auth.h: Likewise. + + * limits.h (LONG_MAX, LONG_MIN, ULONG_MAX): use 64 bit values + for Alpha. + +Tue Mar 19 13:27:49 1996 Roland McGrath <roland@charlie-brown.gnu.ai.mit.edu> + + * sysdeps/i386/fpu/__math.h: New file. + Contributed by John C. Bowman <bowman@hagar.ph.utexas.edu>. + +Sun Mar 17 00:28:16 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * sysdeps/posix/clock.c: Don't multiply the return value by + CLOCKS_PER_SEC or CLK_TCK. + Mon Mar 18 13:20:46 1996 Roland McGrath <roland@charlie-brown.gnu.ai.mit.edu> + * sysdeps/mach/hurd/getcwd.c: Fail with ENOENT if a parent directory + scan finds no match. + + * posix/unistd.h (setpgrp): Declare no-arg version unless __FAVOR_BSD. + * misc/bsd-compat.c (setpgrp): New function, two arg version. + * sysdeps/stub/setpgid.c: Remove setpgrp alias. + * sysdeps/mach/hurd/setpgid.c: Likewise. + * sysdeps/unix/sysv/sysv4/setpgid.c: Likewise. + * sysdeps/unix/common/syscalls.list (setpgid): Remove setpgrp alias. + * sysdeps/unix/sysv/irix4/syscalls.list: Likewise. + * sysdeps/unix/sysv/linux/setpgrp.c: Obsolete file removed. + * posix/setpgrp.c (setpgrp): New file. + * posix/Makefile (routines): Add setpgrp. + * elf/Makefile (rtld-link): New canned sequence. (ld.so, ld-linux.so.1): Use it. Pass -soname option. @@ -780,6 +1014,11 @@ Wed Feb 7 14:16:36 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu> "" is only special for FS_RETRY_NORMAL; for FS_RETRY_REAUTH, do another dir_lookup of "". +Tue Feb 6 12:46:29 1996 David Mosberger-Tang <davidm@azstarnet.com> + + * libc-symbols.h (weak_alias, weak_symbol): added definitions + for ECOFF (HAVE_ECOFF). + Fri Feb 2 13:09:18 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu> * sysdeps/mach/hurd/fork.c: Clear trace flag in child. @@ -2977,7 +3216,6 @@ Wed Sep 27 00:27:25 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> * sysdeps/stub/socketpair.c: Likewise. * sysdeps/stub/sqrt.c: Likewise. * sysdeps/stub/sync.c: Likewise. -M sysd-stdio.c * sysdeps/stub/system.c: Likewise. * sysdeps/stub/tan.c: Likewise. * sysdeps/stub/tanh.c: Likewise. diff --git a/dirent/tst-seekdir.c b/dirent/tst-seekdir.c index fc28246..3022783 100644 --- a/dirent/tst-seekdir.c +++ b/dirent/tst-seekdir.c @@ -14,7 +14,7 @@ main () dirp = opendir("."); for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { - /* save position 3 (fourth entry) */ + /* save position 3 (after fourth entry) */ if (i++ == 3) save3 = telldir(dirp); @@ -26,6 +26,8 @@ main () break; } + printf("going back past 4-th entry...\n"); + /* go back to saved entry */ seekdir (dirp, save3); diff --git a/gmon/Makefile b/gmon/Makefile index 3c6f85d..2d4c501 100644 --- a/gmon/Makefile +++ b/gmon/Makefile @@ -21,9 +21,9 @@ # subdir := gmon -headers := sys/gmon.h +headers := sys/gmon.h sys/gmon_out.h distribute := machine-gmon.h -routines := gmon mcount profil +routines := gmon mcount profil bb_init_func bb_exit_func include ../Rules diff --git a/gmon/bb_exit_func.c b/gmon/bb_exit_func.c new file mode 100644 index 0000000..215f0ba --- /dev/null +++ b/gmon/bb_exit_func.c @@ -0,0 +1,156 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@cs.arizona.edu). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* __bb_exit_func() dumps all the basic-block statistics linked into + the bb_head chain to .d files. */ + +#include <sys/gmon_out.h> +#include <sys/types.h> + +#include <ansidecl.h> +#include <stdio.h> +#include <strings.h> + +/* structure emitted by -a */ +struct bb { + long zero_word; + const char *filename; + long *counts; + long ncounts; + struct bb *next; + const unsigned long *addresses; +}; + +extern struct bb *__bb_head; /* from gmon.c */ + +#define OUT_NAME "gmon.out" + + +void +DEFUN_VOID(__bb_exit_func) +{ + const int version = GMON_VERSION; + struct gmon_hdr ghdr; + struct bb *ptr; + FILE *fp; + fp = fopen(OUT_NAME, "wb"); + if (!fp) + { + perror(OUT_NAME); + return; + } + bcopy(GMON_MAGIC, &ghdr.cookie[0], 4); + bcopy(&version, &ghdr.version, sizeof(version)); + fwrite(&ghdr, sizeof(ghdr), 1, fp); + + for (ptr = __bb_head; ptr != 0; ptr = ptr->next) { + u_int ncounts = ptr->ncounts; + u_char tag; + u_int i; + + tag = GMON_TAG_BB_COUNT; + fwrite(&tag, sizeof(tag), 1, fp); + fwrite(&ncounts, sizeof(ncounts), 1, fp); + + for (i = 0; i < ncounts; ++i) { + fwrite(&ptr->addresses[i], sizeof(ptr->addresses[0]), 1, fp); + fwrite(&ptr->counts[i], sizeof(ptr->counts[0]), 1, fp); + } + } + fclose (fp); +} +/* Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@cs.arizona.edu). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* __bb_exit_func() dumps all the basic-block statistics linked into + the bb_head chain to .d files. */ + +#include <sys/gmon_out.h> +#include <sys/types.h> + +#include <ansidecl.h> +#include <stdio.h> +#include <strings.h> + +/* structure emitted by -a */ +struct bb { + long zero_word; + const char *filename; + long *counts; + long ncounts; + struct bb *next; + const unsigned long *addresses; +}; + +extern struct bb *__bb_head; /* from gmon.c */ + +#define OUT_NAME "gmon.out" + + +void +DEFUN_VOID(__bb_exit_func) +{ + const int version = GMON_VERSION; + struct gmon_hdr ghdr; + struct bb *ptr; + FILE *fp; + fp = fopen(OUT_NAME, "wb"); + if (!fp) + { + perror(OUT_NAME); + return; + } + bcopy(GMON_MAGIC, &ghdr.cookie[0], 4); + bcopy(&version, &ghdr.version, sizeof(version)); + fwrite(&ghdr, sizeof(ghdr), 1, fp); + + for (ptr = __bb_head; ptr != 0; ptr = ptr->next) { + u_int ncounts = ptr->ncounts; + u_char tag; + u_int i; + + tag = GMON_TAG_BB_COUNT; + fwrite(&tag, sizeof(tag), 1, fp); + fwrite(&ncounts, sizeof(ncounts), 1, fp); + + for (i = 0; i < ncounts; ++i) { + fwrite(&ptr->addresses[i], sizeof(ptr->addresses[0]), 1, fp); + fwrite(&ptr->counts[i], sizeof(ptr->counts[0]), 1, fp); + } + } + fclose (fp); +} diff --git a/gmon/gmon.c b/gmon/gmon.c index 3428016..8e47c52 100644 --- a/gmon/gmon.c +++ b/gmon/gmon.c @@ -30,203 +30,261 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ - -#if !defined(lint) && defined(LIBC_SCCS) -static char sccsid[] = "@(#)gmon.c 8.1 (Berkeley) 6/4/93"; -#endif - #include <sys/param.h> #include <sys/time.h> #include <sys/gmon.h> +#include <sys/gmon_out.h> +#include <ansidecl.h> #include <stdio.h> #include <fcntl.h> +#include <unistd.h> + +#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> +struct __bb *__bb_head; /* Head of basic-block list or NULL. */ + struct gmonparam _gmonparam = { GMON_PROF_OFF }; +/* + * See profil(2) where this is described: + */ static int s_scale; -/* see profil(2) where this is describe (incorrectly) */ #define SCALE_1_TO_1 0x10000L -#define ERR(s) write(2, s, sizeof(s) - 1) +#define ERR(s) write(2, s, sizeof(s)) + +/* + * Discover the tick frequency of the machine if something goes wrong, + * we return 0, an impossible hertz. + */ +static int +DEFUN_VOID(hertz) +{ + struct itimerval tim; + + tim.it_interval.tv_sec = 0; + tim.it_interval.tv_usec = 1; + tim.it_value.tv_sec = 0; + tim.it_value.tv_usec = 0; + setitimer(ITIMER_REAL, &tim, 0); + setitimer(ITIMER_REAL, 0, &tim); + if (tim.it_interval.tv_usec < 2) + return 0; + return (1000000 / tim.it_interval.tv_usec); +} + + +/* + * Control profiling + * profiling is what mcount checks to see if + * all the data structures are ready. + */ +void +DEFUN(moncontrol, (mode), int mode) +{ + struct gmonparam *p = &_gmonparam; + + if (mode) + { + /* start */ + profil((void *) p->kcount, p->kcountsize, p->lowpc, s_scale); + p->state = GMON_PROF_ON; + } + else + { + /* stop */ + profil((void *) 0, 0, 0, 0); + p->state = GMON_PROF_OFF; + } +} -void moncontrol __P((int)); -static int hertz __P((void)); void -monstartup(lowpc, highpc) - u_long lowpc; - u_long highpc; +DEFUN(monstartup, (lowpc, highpc), u_long lowpc AND u_long highpc) { - register int o; - char *cp; - struct gmonparam *p = &_gmonparam; - - /* - * round lowpc and highpc to multiples of the density we're using - * so the rest of the scaling (here and in gprof) stays in ints. - */ - p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER)); - p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER)); - p->textsize = p->highpc - p->lowpc; - p->kcountsize = p->textsize / HISTFRACTION; - p->hashfraction = HASHFRACTION; - p->fromssize = p->textsize / HASHFRACTION; - p->tolimit = p->textsize * ARCDENSITY / 100; - if (p->tolimit < MINARCS) - p->tolimit = MINARCS; - else if (p->tolimit > MAXARCS) - p->tolimit = MAXARCS; - p->tossize = p->tolimit * sizeof(struct tostruct); - - cp = malloc (p->kcountsize + p->fromssize + p->tossize); - if (! cp) { - ERR("monstartup: out of memory\n"); - return; - } - bzero(cp, p->kcountsize + p->fromssize + p->tossize); - p->tos = (struct tostruct *)cp; - cp += p->tossize; - p->kcount = (u_short *)cp; - cp += p->kcountsize; - p->froms = (u_short *)cp; + register int o; + char *cp; + struct gmonparam *p = &_gmonparam; + + /* + * round lowpc and highpc to multiples of the density we're using + * so the rest of the scaling (here and in gprof) stays in ints. + */ + p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER)); + p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER)); + p->textsize = p->highpc - p->lowpc; + p->kcountsize = p->textsize / HISTFRACTION; + p->hashfraction = HASHFRACTION; + p->log_hashfraction = -1; + if ((HASHFRACTION & (HASHFRACTION - 1)) == 0) { + /* if HASHFRACTION is a power of two, mcount can use shifting + instead of integer division. Precompute shift amount. */ + p->log_hashfraction = ffs(p->hashfraction * sizeof(*p->froms)) - 1; + } + p->fromssize = p->textsize / HASHFRACTION; + p->tolimit = p->textsize * ARCDENSITY / 100; + if (p->tolimit < MINARCS) + p->tolimit = MINARCS; + else if (p->tolimit > MAXARCS) + p->tolimit = MAXARCS; + p->tossize = p->tolimit * sizeof(struct tostruct); - p->tos[0].link = 0; + cp = malloc (p->kcountsize + p->fromssize + p->tossize); + if (! cp) + { + ERR("monstartup: out of memory\n"); + return; + } + bzero(cp, p->kcountsize + p->fromssize + p->tossize); + p->tos = (struct tostruct *)cp; + cp += p->tossize; + p->kcount = (u_short *)cp; + cp += p->kcountsize; + p->froms = (u_short *)cp; - o = p->highpc - p->lowpc; - if (p->kcountsize < o) { + p->tos[0].link = 0; + + o = p->highpc - p->lowpc; + if (p->kcountsize < o) + { #ifndef hp300 - s_scale = ((float)p->kcountsize / o ) * SCALE_1_TO_1; -#else /* avoid floating point */ - int quot = o / p->kcountsize; - - if (quot >= 0x10000) - s_scale = 1; - else if (quot >= 0x100) - s_scale = 0x10000 / quot; - else if (o >= 0x800000) - s_scale = 0x1000000 / (o / (p->kcountsize >> 8)); - else - s_scale = 0x1000000 / ((o << 8) / p->kcountsize); + s_scale = ((float)p->kcountsize / o ) * SCALE_1_TO_1; +#else + /* avoid floating point operations */ + int quot = o / p->kcountsize; + + if (quot >= 0x10000) + s_scale = 1; + else if (quot >= 0x100) + s_scale = 0x10000 / quot; + else if (o >= 0x800000) + s_scale = 0x1000000 / (o / (p->kcountsize >> 8)); + else + s_scale = 0x1000000 / ((o << 8) / p->kcountsize); #endif - } else - s_scale = SCALE_1_TO_1; + } else + s_scale = SCALE_1_TO_1; - moncontrol(1); + moncontrol(1); } -void -_mcleanup() + +static void +DEFUN(write_hist, (fd), int fd) { - int fd; - int fromindex; - int endfrom; - u_long frompc; - int toindex; - struct rawarc rawarc; - struct gmonparam *p = &_gmonparam; - struct gmonhdr gmonhdr, *hdr; -#ifdef DEBUG - int log, len; - char buf[200]; -#endif + const u_char tag = GMON_TAG_TIME_HIST; + struct gmon_hist_hdr thdr; + int size, rate; - if (p->state == GMON_PROF_ERROR) - ERR("_mcleanup: tos overflow\n"); + if (_gmonparam.kcountsize > 0) + { + size = _gmonparam.kcountsize / sizeof(HISTCOUNTER); + rate = hertz(); + bcopy(&_gmonparam.lowpc, &thdr.low_pc, sizeof(thdr.low_pc)); + bcopy(&_gmonparam.highpc, &thdr.high_pc, sizeof(thdr.high_pc)); + bcopy(&size, &thdr.hist_size, sizeof(thdr.hist_size)); + bcopy(&rate, &thdr.prof_rate, sizeof(thdr.prof_rate)); + strcpy(thdr.dimen, "seconds"); + thdr.dimen_abbrev = 's'; - moncontrol(0); - fd = open("gmon.out", O_CREAT|O_TRUNC|O_WRONLY, 0666); - if (fd < 0) { - perror("mcount: gmon.out"); - return; - } -#ifdef DEBUG - log = open("gmon.log", O_CREAT|O_TRUNC|O_WRONLY, 0664); - if (log < 0) { - perror("mcount: gmon.log"); - return; - } - len = sprintf(buf, "[mcleanup1] kcount 0x%x ssiz %d\n", - p->kcount, p->kcountsize); - write(log, buf, len); -#endif - hdr = (struct gmonhdr *)&gmonhdr; - hdr->lpc = p->lowpc; - hdr->hpc = p->highpc; - hdr->ncnt = p->kcountsize + sizeof(gmonhdr); - hdr->version = GMONVERSION; - hdr->profrate = hertz(); - write(fd, (char *)hdr, sizeof *hdr); - write(fd, p->kcount, p->kcountsize); - endfrom = p->fromssize / sizeof(*p->froms); - for (fromindex = 0; fromindex < endfrom; fromindex++) { - if (p->froms[fromindex] == 0) - continue; - - frompc = p->lowpc; - frompc += fromindex * p->hashfraction * sizeof(*p->froms); - for (toindex = p->froms[fromindex]; toindex != 0; - toindex = p->tos[toindex].link) { -#ifdef DEBUG - len = sprintf(buf, - "[mcleanup2] frompc 0x%x selfpc 0x%x count %d\n" , - frompc, p->tos[toindex].selfpc, - p->tos[toindex].count); - write(log, buf, len); -#endif - rawarc.raw_frompc = frompc; - rawarc.raw_selfpc = p->tos[toindex].selfpc; - rawarc.raw_count = p->tos[toindex].count; - write(fd, &rawarc, sizeof rawarc); - } - } - close(fd); + write(fd, &tag, sizeof(tag)); + write(fd, &thdr, sizeof(thdr)); + write(fd, _gmonparam.kcount, _gmonparam.kcountsize); + } } -/* - * Control profiling - * profiling is what mcount checks to see if - * all the data structures are ready. - */ -void -moncontrol(mode) - int mode; + +static void +DEFUN(write_call_graph, (fd), int fd) { - struct gmonparam *p = &_gmonparam; - - if (mode) { - /* start */ - profil(p->kcount, p->kcountsize, (int)p->lowpc, - s_scale); - p->state = GMON_PROF_ON; - } else { - /* stop */ - profil(0, 0, 0, 0); - p->state = GMON_PROF_OFF; + const u_char tag = GMON_TAG_CG_ARC; + struct gmon_cg_arc_record raw_arc; + int from_index, to_index, from_len; + u_long frompc; + + from_len = _gmonparam.fromssize / sizeof(*_gmonparam.froms); + for (from_index = 0; from_index < from_len; ++from_index) + { + if (_gmonparam.froms[from_index] == 0) + continue; + + frompc = _gmonparam.lowpc; + frompc += (from_index * _gmonparam.hashfraction + * sizeof(*_gmonparam.froms)); + for (to_index = _gmonparam.froms[from_index]; + to_index != 0; + to_index = _gmonparam.tos[to_index].link) + { + bcopy(&frompc, &raw_arc.from_pc, sizeof(raw_arc.from_pc)); + bcopy(&_gmonparam.tos[to_index].selfpc, &raw_arc.self_pc, + sizeof(raw_arc.self_pc)); + bcopy(&_gmonparam.tos[to_index].count, &raw_arc.count, + sizeof(raw_arc.count)); + + write(fd, &tag, sizeof(tag)); + write(fd, &raw_arc, sizeof(raw_arc)); } + } } -/* - * discover the tick frequency of the machine - * if something goes wrong, we return 0, an impossible hertz. - */ -static int -hertz() + +static void +DEFUN(write_bb_counts, (fd), int fd) { - struct itimerval tim; - - tim.it_interval.tv_sec = 0; - tim.it_interval.tv_usec = 1; - tim.it_value.tv_sec = 0; - tim.it_value.tv_usec = 0; - setitimer(ITIMER_REAL, &tim, 0); - setitimer(ITIMER_REAL, 0, &tim); - if (tim.it_interval.tv_usec < 2) - return(0); - return (1000000 / tim.it_interval.tv_usec); + struct __bb *grp; + const u_char tag = GMON_TAG_BB_COUNT; + int ncounts; + int i; + + /* Write each group of basic-block info (all basic-blocks in a + compilation unit form a single group). */ + + for (grp = __bb_head; grp; grp = grp->next) + { + ncounts = grp->ncounts; + write(fd, &tag, sizeof(tag)); + write(fd, &ncounts, sizeof(ncounts)); + for (i = 0; i < ncounts; ++i) + { + write(fd, &grp->addresses[i], sizeof(grp->addresses[0])); + write(fd, &grp->counts[i], sizeof(grp->counts[0])); + } + } } +void +DEFUN_VOID(_mcleanup) +{ + const int version = GMON_VERSION; + struct gmon_hdr ghdr; + int fd; + + moncontrol(0); + fd = open("gmon.out", O_CREAT|O_TRUNC|O_WRONLY, 0666); + if (fd < 0) + { + perror("_mcleanup: gmon.out"); + return; + } + + /* write gmon.out header: */ + bcopy(GMON_MAGIC, &ghdr.cookie[0], 4); + bcopy(&version, &ghdr.version, sizeof(version)); + write(fd, &ghdr, sizeof(ghdr)); + + /* write PC histogram: */ + write_hist(fd); + + /* write call-graph: */ + write_call_graph(fd); + + /* write basic-block execution counts: */ + write_bb_counts(fd); + + close(fd); +} diff --git a/gmon/mcount.c b/gmon/mcount.c index ea60afc..4d3097f 100644 --- a/gmon/mcount.c +++ b/gmon/mcount.c @@ -34,6 +34,7 @@ #if !defined(lint) && !defined(KERNEL) && defined(LIBC_SCCS) static char sccsid[] = "@(#)mcount.c 8.1 (Berkeley) 6/4/93"; #endif + int i; #include <sys/param.h> #include <sys/gmon.h> @@ -67,6 +68,7 @@ _MCOUNT_DECL(frompc, selfpc) /* _mcount; may be static, inline, etc */ #ifdef KERNEL register int s; #endif + int i; p = &_gmonparam; /* @@ -89,7 +91,13 @@ _MCOUNT_DECL(frompc, selfpc) /* _mcount; may be static, inline, etc */ if (frompc > p->textsize) goto done; - frompcindex = &p->froms[frompc / (p->hashfraction * sizeof(*p->froms))]; + /* avoid integer divide if possible: */ + if (p->log_hashfraction >= 0) { + i = frompc >> p->log_hashfraction; + } else { + i = frompc / (p->hashfraction * sizeof(*p->froms)); + } + frompcindex = &p->froms[i]; toindex = *frompcindex; if (toindex == 0) { /* diff --git a/gmon/sys/gmon.h b/gmon/sys/gmon.h index f7af72b..8cbd6bd 100644 --- a/gmon/sys/gmon.h +++ b/gmon/sys/gmon.h @@ -39,17 +39,23 @@ #include <sys/cdefs.h> /* - * Structure prepended to gmon.out profiling data file. + * See gmon_out.h for gmon.out format. */ -struct gmonhdr { - u_long lpc; /* base pc address of sample buffer */ - u_long hpc; /* max pc address of sampled buffer */ - int ncnt; /* size of sample buffer (plus this header) */ - int version; /* version number */ - int profrate; /* profiling clock rate */ - int spare[3]; /* reserved */ + +/* structure emitted by "gcc -a". This must match struct bb in + gcc/libgcc2.c. It is OK for gcc to declare a longer structure as + long as the members below are present. */ +struct __bb +{ + long zero_word; + const char *filename; + long *counts; + long ncounts; + struct __bb *next; + const unsigned long *addresses; }; -#define GMONVERSION 0x00051879 + +extern struct __bb *__bb_head; /* * histogram counters are unsigned shorts (according to the kernel). @@ -137,6 +143,7 @@ struct gmonparam { u_long highpc; u_long textsize; u_long hashfraction; + long log_hashfraction; }; extern struct gmonparam _gmonparam; diff --git a/gmon/sys/gmon_out.h b/gmon/sys/gmon_out.h new file mode 100644 index 0000000..6eab094 --- /dev/null +++ b/gmon/sys/gmon_out.h @@ -0,0 +1,132 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@cs.arizona.edu). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* This file specifies the format of gmon.out files. It should have +as few external dependencies as possible as it is going to be included +in many different programs. That is, minimize the number of #include's. + +A gmon.out file consists of a header (defined by gmon_hdr) followed by +a sequence of records. Each record starts with a one-byte tag +identifying the type of records, followed by records specific data. */ + +#ifndef _SYS_GMON_OUT_H_ +#define _SYS_GMON_OUT_H_ + +#define GMON_MAGIC "gmon" /* magic cookie */ +#define GMON_VERSION 1 /* version number */ + +/* + * Raw header as it appears on file (without padding). This header + * always comes first in gmon.out and is then followed by a series + * records defined below. + */ +struct gmon_hdr { + char cookie[4]; + char version[4]; + char spare[3 * 4]; +}; + +/* types of records in this file: */ +typedef enum { + GMON_TAG_TIME_HIST = 0, GMON_TAG_CG_ARC = 1, GMON_TAG_BB_COUNT = 2 +} GMON_Record_Tag; + +struct gmon_hist_hdr { + char low_pc[sizeof (char *)]; /* base pc address of sample buffer */ + char high_pc[sizeof (char *)]; /* max pc address of sampled buffer */ + char hist_size[4]; /* size of sample buffer */ + char prof_rate[4]; /* profiling clock rate */ + char dimen[15]; /* phys. dim., usually "seconds" */ + char dimen_abbrev; /* usually 's' for "seconds" */ +}; + +struct gmon_cg_arc_record { + char from_pc[sizeof (char *)]; /* address within caller's body */ + char self_pc[sizeof (char *)]; /* address within callee's body */ + char count[4]; /* number of arc traversals */ +}; + +#endif /* !_SYS_GMON_OUT_H_ */ +/* Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@cs.arizona.edu). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* This file specifies the format of gmon.out files. It should have +as few external dependencies as possible as it is going to be included +in many different programs. That is, minimize the number of #include's. + +A gmon.out file consists of a header (defined by gmon_hdr) followed by +a sequence of records. Each record starts with a one-byte tag +identifying the type of records, followed by records specific data. */ + +#ifndef _SYS_GMON_OUT_H_ +#define _SYS_GMON_OUT_H_ + +#define GMON_MAGIC "gmon" /* magic cookie */ +#define GMON_VERSION 1 /* version number */ + +/* + * Raw header as it appears on file (without padding). This header + * always comes first in gmon.out and is then followed by a series + * records defined below. + */ +struct gmon_hdr { + char cookie[4]; + char version[4]; + char spare[3 * 4]; +}; + +/* types of records in this file: */ +typedef enum { + GMON_TAG_TIME_HIST = 0, GMON_TAG_CG_ARC = 1, GMON_TAG_BB_COUNT = 2 +} GMON_Record_Tag; + +struct gmon_hist_hdr { + char low_pc[sizeof (char *)]; /* base pc address of sample buffer */ + char high_pc[sizeof (char *)]; /* max pc address of sampled buffer */ + char hist_size[4]; /* size of sample buffer */ + char prof_rate[4]; /* profiling clock rate */ + char dimen[15]; /* phys. dim., usually "seconds" */ + char dimen_abbrev; /* usually 's' for "seconds" */ +}; + +struct gmon_cg_arc_record { + char from_pc[sizeof (char *)]; /* address within caller's body */ + char self_pc[sizeof (char *)]; /* address within callee's body */ + char count[4]; /* number of arc traversals */ +}; + +#endif /* !_SYS_GMON_OUT_H_ */ @@ -101,12 +101,26 @@ Cambridge, MA 02139, USA. */ #define UINT_MAX 4294967295 #endif +#ifdef __alpha__ + +/* Minimum and maximum values a `signed long int' can hold. */ +#define LONG_MAX 9223372036854775807L +#define LONG_MIN (- LONG_MAX - 1L) + +/* Maximum value an `unsigned long int' can hold. (Minimum is 0.) */ +#define ULONG_MAX 18446744073709551615L + +#else + /* Minimum and maximum values a `signed long int' can hold. */ -#define LONG_MIN INT_MIN #define LONG_MAX INT_MAX +#define LONG_MIN INT_MIN /* Maximum value an `unsigned long int' can hold. (Minimum is 0.) */ #define ULONG_MAX UINT_MAX +#endif + + #endif /* limits.h */ #endif /* GCC 2. */ diff --git a/locale/locfile-hash.c b/locale/locfile-hash.c index 75cb77f..d977822 100644 --- a/locale/locfile-hash.c +++ b/locale/locfile-hash.c @@ -205,7 +205,7 @@ compute_hashval(const char *key, size_t keylen) { hval <<= 4; hval += key[cnt++]; - g = hval & (0xf << (LONGBITS - 4)); + g = hval & (0xfL << (LONGBITS - 4)); if (g != 0) { hval ^= g >> (LONGBITS - 8); diff --git a/misc/bsd-compat.c b/misc/bsd-compat.c index ad593b9..5fb9188 100644 --- a/misc/bsd-compat.c +++ b/misc/bsd-compat.c @@ -23,9 +23,16 @@ Cambridge, MA 02139, USA. */ /* Don't include unistd.h because it declares a conflicting prototype for the POSIX.1 `getpgrp' function. */ extern pid_t __getpgid __P ((pid_t)); +extern int __setpgid __P ((pid_t, pid_t)); pid_t getpgrp (pid_t pid) { return __getpgid (pid); } + +int +setpgrp (pid_t pid, pid_t pgrp) +{ + return __setpgid (pid, pgrp); +} diff --git a/posix/Makefile b/posix/Makefile index fef1415..052c17c 100644 --- a/posix/Makefile +++ b/posix/Makefile @@ -37,7 +37,7 @@ routines := \ execve fexecve execv execle execl execvp execlp \ getpid getppid \ getuid geteuid getgid getegid getgroups setuid setgid group_member \ - getpgid setpgid getpgrp getsid setsid \ + getpgid setpgid getpgrp setpgrp getsid setsid \ getlogin setlogin \ pathconf sysconf fpathconf \ glob fnmatch regex \ diff --git a/sysdeps/unix/sysv/linux/setpgrp.c b/posix/setpgrp.c index 4497e07..56102a3 100644 --- a/sysdeps/unix/sysv/linux/setpgrp.c +++ b/posix/setpgrp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1995 Free Software Foundation, Inc. +/* Copyright (C) 1996 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 diff --git a/posix/unistd.h b/posix/unistd.h index 516f288..2ac0b2f 100644 --- a/posix/unistd.h +++ b/posix/unistd.h @@ -339,10 +339,30 @@ extern __pid_t __getpgid __P ((__pid_t __pid)); extern __pid_t getpgid __P ((__pid_t __pid)); #endif -#ifdef __USE_BSD -/* Another name for `setpgid'. */ +#if defined (__USE_SVID) || defined (__USE_BSD) +/* Both System V and BSD have `setpgrp' functions, but with different + calling conventions. The BSD function is the same as POSIX.1 `setpgid' + (above). The System V function takes no arguments and puts the calling + process in its on group like `setpgid (0, 0)'. + + New programs should always use `setpgid' instead. + + The default in GNU is to provide the System V function. The BSD + function is available under -D_BSD_SOURCE with -lbsd-compat. */ + +#ifndef __FAVOR_BSD + +/* Set the process group ID of the calling process to its own PID. + This is exactly the same as `setpgid (0, 0)'. */ +extern int setpgrp __P ((void)); + +#else + +/* Another name for `setpgid' (above). */ extern int setpgrp __P ((__pid_t __pid, __pid_t __pgrp)); -#endif /* Use BSD. */ + +#endif /* Favor BSD. */ +#endif /* Use SVID or BSD. */ /* Create a new session with the calling process as its leader. The process group IDs of the session and the calling process diff --git a/stdlib/random.c b/stdlib/random.c index c3f8eaa..0ab8f05 100644 --- a/stdlib/random.c +++ b/stdlib/random.c @@ -114,7 +114,7 @@ position of the rear pointer is just (MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3. */ -static long int randtbl[DEG_3 + 1] = +static int32_t randtbl[DEG_3 + 1] = { TYPE_3, @@ -239,10 +239,10 @@ weak_alias (__setstate, setstate) rear pointers can't wrap on the same call by not testing the rear pointer if the front one has wrapped. Returns a 31-bit random number. */ -long int +int __random () { - long int retval; + int32_t retval; (void) __random_r (&unsafe_state, &retval); diff --git a/stdlib/random_r.c b/stdlib/random_r.c index aa7a33f..611deaf 100644 --- a/stdlib/random_r.c +++ b/stdlib/random_r.c @@ -145,7 +145,7 @@ __srandom_r (x, buf) buf->rptr = &buf->state[0]; for (i = 0; i < 10 * buf->rand_deg; ++i) { - long int discard; + int32_t discard; (void) __random_r (buf, &discard); } } @@ -217,7 +217,7 @@ __initstate_r (seed, arg_state, n, buf) buf->rand_sep = SEP_4; } - buf->state = &((long int *) arg_state)[1]; /* First location. */ + buf->state = &((int32_t *) arg_state)[1]; /* First location. */ /* Must set END_PTR before srandom. */ buf->end_ptr = &buf->state[buf->rand_deg]; @@ -246,7 +246,7 @@ __setstate_r (arg_state, buf) void *arg_state; struct random_data *buf; { - long int *new_state = (long int *) arg_state; + int32_t *new_state = (int32_t *) arg_state; int type = new_state[0] % MAX_TYPES; int rear = new_state[0] / MAX_TYPES; @@ -303,21 +303,21 @@ weak_alias (__setstate_r, setstate_r) int __random_r (buf, result) struct random_data *buf; - long int *result; + int32_t *result; { if (buf == NULL || result == NULL) return -1; if (buf->rand_type == TYPE_0) { - buf->state[0] = ((buf->state[0] * 1103515245) + 12345) & LONG_MAX; + buf->state[0] = ((buf->state[0] * 1103515245) + 12345) & 0x7fffffff; *result = buf->state[0]; } else { *buf->fptr += *buf->rptr; /* Chucking least random bit. */ - *result = (*buf->fptr >> 1) & LONG_MAX; + *result = (*buf->fptr >> 1) & 0x7fffffff; ++buf->fptr; if (buf->fptr >= buf->end_ptr) { diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h index 7c9c689..65932e3 100644 --- a/stdlib/stdlib.h +++ b/stdlib/stdlib.h @@ -172,12 +172,16 @@ extern int rand __P ((void)); /* Seed the random number generator with the given number. */ extern void srand __P ((unsigned int __seed)); +#ifdef __USE_BSD + +#include <sys/types.h> /* we need int32_t... */ + /* These are the functions that actually do things. The `random', `srandom', `initstate' and `setstate' functions are those from BSD Unices. The `rand' and `srand' functions are required by the ANSI standard. We provide both interfaces to the same random number generator. */ /* Return a random long integer between 0 and RAND_MAX inclusive. */ -extern long int __random __P ((void)); +extern int32_t __random __P ((void)); /* Seed the random number generator with the given number. */ extern void __srandom __P ((unsigned int __seed)); @@ -191,7 +195,6 @@ extern __ptr_t __initstate __P ((unsigned int __seed, __ptr_t __statebuf, which should have been previously initialized by `initstate'. */ extern __ptr_t __setstate __P ((__ptr_t __statebuf)); -#ifdef __USE_BSD extern long int random __P ((void)); extern void srandom __P ((unsigned int __seed)); extern __ptr_t initstate __P ((unsigned int __seed, __ptr_t __statebuf, @@ -217,22 +220,22 @@ extern __inline __ptr_t setstate (__ptr_t __statebuf) struct random_data { - long int *fptr; /* Front pointer. */ - long int *rptr; /* Rear pointer. */ - long int *state; /* Array of state values. */ + int32_t *fptr; /* Front pointer. */ + int32_t *rptr; /* Rear pointer. */ + int32_t *state; /* Array of state values. */ int rand_type; /* Type of random number generator. */ int rand_deg; /* Degree of random number generator. */ int rand_sep; /* Distance between front and rear. */ - long int *end_ptr; /* Pointer behind state table. */ + int32_t *end_ptr; /* Pointer behind state table. */ }; -extern int __random_r __P ((struct random_data *__buf, long int *__result)); +extern int __random_r __P ((struct random_data *__buf, int32_t *__result)); +extern int random_r __P ((struct random_data *__buf, int32_t *__result)); extern int __srandom_r __P ((unsigned int __seed, struct random_data *__buf)); extern int __initstate_r __P ((unsigned int __seed, __ptr_t __statebuf, size_t __statelen, struct random_data *__buf)); extern int __setstate_r __P ((__ptr_t __statebuf, struct random_data *__buf)); -extern int random_r __P ((struct random_data *__buf, long int *__result)); extern int srandom_r __P ((unsigned int __seed, struct random_data *__buf)); extern int initstate_r __P ((unsigned int __seed, __ptr_t __statebuf, size_t __statelen, struct random_data *__buf)); diff --git a/stdlib/testmb.c b/stdlib/testmb.c index c840ce1..a70fe08 100644 --- a/stdlib/testmb.c +++ b/stdlib/testmb.c @@ -53,7 +53,7 @@ main () } else { - printf ("wide value: 0x%04x\n", (unsigned long) wc); + printf ("wide value: 0x%04lx\n", (unsigned long) wc); mbc[0] = '\0'; if ((r = wctomb (mbc, wc)) <= 0) { diff --git a/stdlib/testrand.c b/stdlib/testrand.c index b66dca9..b31082e 100644 --- a/stdlib/testrand.c +++ b/stdlib/testrand.c @@ -34,6 +34,9 @@ DEFUN_VOID(main) srand (1); j1 = rand(); j2 = rand(); + if (i1 < 0 || i2 < 0 || j1 < 0 || j2 < 0) { + puts ("Test FAILED!"); + } if (j1 == i1 && j2 == i2) { puts ("Test succeeded."); diff --git a/stdlib/tst-strtol.c b/stdlib/tst-strtol.c index 0682da3..5c3e2cb 100644 --- a/stdlib/tst-strtol.c +++ b/stdlib/tst-strtol.c @@ -18,6 +18,7 @@ struct ltest }; static CONST struct ltest tests[] = { +#if ~0UL == 0xffffffff /* First, signed numbers. */ { " -17", -17, 0, 0, 0 }, { " +0x123fg", 0x123f, 0, 'g', 0 }, @@ -40,6 +41,35 @@ static CONST struct ltest tests[] = { "-0x123456789", 0xffffffff, 0, 0, ERANGE }, { "-0xfedcba98", -0xfedcba98, 0, 0, 0 }, { NULL, 0, 0, 0, 0 }, +#else + /* assume 64 bit long... */ + + /* First, signed numbers. */ + { " -17", -17, 0, 0, 0 }, + { " +0x123fg", 0x123f, 0, 'g', 0 }, + { "2147483647", 2147483647, 0, 0, 0 }, + { "9223372036854775807", 9223372036854775807, 0, 0, 0 }, + { "9223372036854775808", 9223372036854775807, 0, 0, ERANGE }, + { "922337203685477580777", 9223372036854775807, 0, 0, ERANGE }, + { "9223372036854775810", 9223372036854775807, 0, 0, ERANGE }, + { "-2147483648", -2147483648, 0, 0, 0 }, + { "-9223372036854775808", -9223372036854775808, 0, 0, 0 }, + { "-9223372036854775809", -9223372036854775808, 0, 0, ERANGE }, + { "0123", 0123, 0, 0, 0 }, + { "0x112233445566778899z", 9223372036854775807, 16, 'z', ERANGE }, + { "0x0xc", 0, 0, 'x', 0 }, + { "yz!", 34*36+35, 36, '!', 0 }, + { NULL, 0, 0, 0, 0 }, + + /* Then unsigned. */ + { " 0", 0, 0, 0, 0 }, + { "0xffffffffg", 0xffffffff, 0, 'g', 0 }, + { "0xffffffffffffffffg", 0xffffffffffffffff, 0, 'g', 0 }, + { "0xf1f2f3f4f5f6f7f8f9", 0xffffffffffffffff, 0, 0, ERANGE }, + { "-0x123456789abcdef01", 0xffffffffffffffff, 0, 0, ERANGE }, + { "-0xfedcba987654321", -0xfedcba987654321, 0, 0, 0 }, + { NULL, 0, 0, 0, 0 }, +#endif }; static void EXFUN(expand, (char *dst, int c)); diff --git a/string/test-ffs.c b/string/test-ffs.c index bbe6278..ef40171 100644 --- a/string/test-ffs.c +++ b/string/test-ffs.c @@ -43,6 +43,8 @@ DEFUN(main, (argc, argv), try (0, 0); for (i=0 ; i<32 ; i++) try (1<<i, i+1); + for (i=0 ; i<32 ; i++) + try ((~0 >> i) << i, i+1); try (0x80008000, 16); if (failures) diff --git a/sunrpc/clnt_tcp.c b/sunrpc/clnt_tcp.c index 2222bc6..f6b28b3 100644 --- a/sunrpc/clnt_tcp.c +++ b/sunrpc/clnt_tcp.c @@ -233,7 +233,7 @@ clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout) register XDR *xdrs = &(ct->ct_xdrs); struct rpc_msg reply_msg; u_long x_id; - u_long *msg_x_id = (u_long *)(ct->ct_mcall); /* yuk */ + u_int32_t *msg_x_id = (u_int32_t *)(ct->ct_mcall); /* yuk */ register bool_t shipnow; int refreshes = 2; diff --git a/sunrpc/clnt_udp.c b/sunrpc/clnt_udp.c index 815cbb4..706457a 100644 --- a/sunrpc/clnt_udp.c +++ b/sunrpc/clnt_udp.c @@ -324,10 +324,10 @@ send_again: cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTRECV); } - if (inlen < sizeof(u_long)) + if (inlen < 4) continue; /* see if reply transaction id matches sent id */ - if (*((u_long *)(cu->cu_inbuf)) != *((u_long *)(cu->cu_outbuf))) + if (*((u_int32_t *)(cu->cu_inbuf)) != *((u_int32_t *)(cu->cu_outbuf))) continue; /* we now assume we have the proper reply */ break; diff --git a/sunrpc/rpc/xdr.h b/sunrpc/rpc/xdr.h index 6cd3e6f..0d9b5df 100644 --- a/sunrpc/rpc/xdr.h +++ b/sunrpc/rpc/xdr.h @@ -203,8 +203,8 @@ struct xdr_discrim { * N.B. and frozen for all time: each data type here uses 4 bytes * of external representation. */ -#define IXDR_GET_LONG(buf) ((long)ntohl((u_long)*(buf)++)) -#define IXDR_PUT_LONG(buf, v) (*(buf)++ = (long)htonl((u_long)v)) +#define IXDR_GET_LONG(buf) ((long)ntohl((u_long)*((u_int32_t*)buf)++)) +#define IXDR_PUT_LONG(buf, v) (*((u_int32_t*)(buf))++ = (long)htonl((u_long)v)) #define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf)) #define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf)) diff --git a/sunrpc/rpc_cmsg.c b/sunrpc/rpc_cmsg.c index d9d815a..a4d5ef3 100644 --- a/sunrpc/rpc_cmsg.c +++ b/sunrpc/rpc_cmsg.c @@ -82,7 +82,7 @@ xdr_callmsg(xdrs, cmsg) IXDR_PUT_LONG(buf, oa->oa_length); if (oa->oa_length) { bcopy(oa->oa_base, (caddr_t)buf, oa->oa_length); - buf += RNDUP(oa->oa_length) / sizeof (long); + buf = (long *) ((char *) buf + RNDUP(oa->oa_length)); } oa = &cmsg->rm_call.cb_verf; IXDR_PUT_ENUM(buf, oa->oa_flavor); @@ -90,7 +90,7 @@ xdr_callmsg(xdrs, cmsg) if (oa->oa_length) { bcopy(oa->oa_base, (caddr_t)buf, oa->oa_length); /* no real need.... - buf += RNDUP(oa->oa_length) / sizeof (long); + buf = (long *) ((char *) buf + RNDUP(oa->oa_length)); */ } return (TRUE); @@ -132,8 +132,8 @@ xdr_callmsg(xdrs, cmsg) bcopy((caddr_t)buf, oa->oa_base, oa->oa_length); /* no real need.... - buf += RNDUP(oa->oa_length) / - sizeof (long); + buf = (long *) ((char *) buf + + RNDUP(oa->oa_length)); */ } } @@ -166,8 +166,8 @@ xdr_callmsg(xdrs, cmsg) bcopy((caddr_t)buf, oa->oa_base, oa->oa_length); /* no real need... - buf += RNDUP(oa->oa_length) / - sizeof (long); + buf = (long *) ((char *) buf + + RNDUP(oa->oa_length)); */ } } diff --git a/sunrpc/svc.c b/sunrpc/svc.c index 3327ee5..7bfe680 100644 --- a/sunrpc/svc.c +++ b/sunrpc/svc.c @@ -400,7 +400,7 @@ svc_getreqset(readfds) register SVCXPRT *xprt; register u_long mask; register int bit; - register u_long *maskp; + register u_int32_t *maskp; register int setsize; register int sock; char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE]; @@ -411,7 +411,7 @@ svc_getreqset(readfds) #ifdef FD_SETSIZE setsize = _rpc_dtablesize(); - maskp = (u_long *)readfds->fds_bits; + maskp = (u_int32_t *)readfds->fds_bits; for (sock = 0; sock < setsize; sock += NFDBITS) { for (mask = *maskp++; bit = ffs(mask); mask ^= (1 << (bit - 1))) { /* sock has input waiting */ diff --git a/sunrpc/svc_udp.c b/sunrpc/svc_udp.c index 079502c..a910452 100644 --- a/sunrpc/svc_udp.c +++ b/sunrpc/svc_udp.c @@ -181,7 +181,7 @@ svcudp_recv(xprt, msg) 0, (struct sockaddr *)&(xprt->xp_raddr), &(xprt->xp_addrlen)); if (rlen == -1 && errno == EINTR) goto again; - if (rlen < 4*sizeof(u_long)) + if (rlen < 16) /* < 4 32-bit ints? */ return (FALSE); xdrs->x_op = XDR_DECODE; XDR_SETPOS(xdrs, 0); diff --git a/sunrpc/xdr.c b/sunrpc/xdr.c index b8248c2..a79db85 100644 --- a/sunrpc/xdr.c +++ b/sunrpc/xdr.c @@ -99,7 +99,7 @@ xdr_int(xdrs, ip) (void) (xdr_short(xdrs, (short *)ip)); return (xdr_long(xdrs, (long *)ip)); #else - if (sizeof (int) == sizeof (long)) { + if (sizeof (int) == 4) { return (xdr_long(xdrs, (long *)ip)); } else { return (xdr_short(xdrs, (short *)ip)); @@ -120,7 +120,7 @@ xdr_u_int(xdrs, up) (void) (xdr_short(xdrs, (short *)up)); return (xdr_u_long(xdrs, (u_long *)up)); #else - if (sizeof (u_int) == sizeof (u_long)) { + if (sizeof (u_int) == 4) { return (xdr_u_long(xdrs, (u_long *)up)); } else { return (xdr_short(xdrs, (short *)up)); @@ -307,7 +307,7 @@ xdr_enum(xdrs, ep) /* * enums are treated as ints */ - if (sizeof (enum sizecheck) == sizeof (long)) { + if (sizeof (enum sizecheck) == 4) { return (xdr_long(xdrs, (long *)ep)); } else if (sizeof (enum sizecheck) == sizeof (short)) { return (xdr_short(xdrs, (short *)ep)); diff --git a/sunrpc/xdr_mem.c b/sunrpc/xdr_mem.c index 558d369..fb15f11 100644 --- a/sunrpc/xdr_mem.c +++ b/sunrpc/xdr_mem.c @@ -97,10 +97,10 @@ xdrmem_getlong(xdrs, lp) long *lp; { - if ((xdrs->x_handy -= sizeof(long)) < 0) + if ((xdrs->x_handy -= 4) < 0) return (FALSE); - *lp = (long)ntohl((u_long)(*((long *)(xdrs->x_private)))); - xdrs->x_private += sizeof(long); + *lp = (long)ntohl((u_long)(*((int32_t *)(xdrs->x_private)))); + xdrs->x_private += 4; return (TRUE); } @@ -110,10 +110,10 @@ xdrmem_putlong(xdrs, lp) long *lp; { - if ((xdrs->x_handy -= sizeof(long)) < 0) + if ((xdrs->x_handy -= 4) < 0) return (FALSE); - *(long *)xdrs->x_private = (long)htonl((u_long)(*lp)); - xdrs->x_private += sizeof(long); + *(int32_t *)xdrs->x_private = (long)htonl((u_long)(*(int32_t*)lp)); + xdrs->x_private += 4; return (TRUE); } @@ -150,7 +150,7 @@ xdrmem_getpos(xdrs) register XDR *xdrs; { - return ((u_int)xdrs->x_private - (u_int)xdrs->x_base); + return ((u_long)xdrs->x_private - (u_long)xdrs->x_base); } static bool_t @@ -164,7 +164,7 @@ xdrmem_setpos(xdrs, pos) if ((long)newaddr > (long)lastaddr) return (FALSE); xdrs->x_private = newaddr; - xdrs->x_handy = (int)lastaddr - (int)newaddr; + xdrs->x_handy = (long)lastaddr - (long)newaddr; return (TRUE); } diff --git a/sunrpc/xdr_stdio.c b/sunrpc/xdr_stdio.c index 694774f..da4877a 100644 --- a/sunrpc/xdr_stdio.c +++ b/sunrpc/xdr_stdio.c @@ -104,12 +104,11 @@ xdrstdio_getlong(xdrs, lp) XDR *xdrs; register long *lp; { + int32_t mycopy; - if (fread((caddr_t)lp, sizeof(long), 1, (FILE *)xdrs->x_private) != 1) + if (fread((caddr_t)&mycopy, 4, 1, (FILE *)xdrs->x_private) != 1) return (FALSE); -#ifndef mc68000 - *lp = ntohl(*lp); -#endif + *(int32_t*)lp = ntohl(mycopy); return (TRUE); } @@ -119,11 +118,9 @@ xdrstdio_putlong(xdrs, lp) long *lp; { -#ifndef mc68000 - long mycopy = htonl(*lp); + int32_t mycopy = htonl(*(int32_t*)lp); lp = &mycopy; -#endif - if (fwrite((caddr_t)lp, sizeof(long), 1, (FILE *)xdrs->x_private) != 1) + if (fwrite((caddr_t)lp, 4, 1, (FILE *)xdrs->x_private) != 1) return (FALSE); return (TRUE); } diff --git a/sysdeps/alpha/Makefile b/sysdeps/alpha/Makefile index 8573ca8..4bb1f29 100644 --- a/sysdeps/alpha/Makefile +++ b/sysdeps/alpha/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. +# Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc. # Contributed by Brendan Kehoe (brendan@zen.org). # The GNU C Library is free software; you can redistribute it and/or @@ -16,79 +16,16 @@ # not, write to the Free Software Foundation, Inc., 675 Mass Ave, # Cambridge, MA 02139, USA. +ifeq ($(subdir),gmon) +sysdep_routines := bb_init_func _mcount +endif + ifeq ($(subdir),setjmp) sysdep_routines := $(sysdep_routines) setjmp_aux endif ifeq ($(subdir),gnulib) -routines = $(divrem) +routines = $(divrem) endif # gnulib -# We distribute these files, even though they are generated, -# so as to avoid the need for a functioning m4 to build the library. divrem := divl divlu divq divqu reml remlu remq remqu - -+divrem-NAME-divl := divl -+divrem-NAME-divlu := divlu -+divrem-NAME-divq := divq -+divrem-NAME-divqu := divqu -+divrem-NAME-reml := reml -+divrem-NAME-remlu := remlu -+divrem-NAME-remq := remq -+divrem-NAME-remqu := remqu -+divrem-NAME = $(+divrem-NAME-$(basename $(notdir $@))) - -+divrem-OP-divl := divl -+divrem-OP-divlu := divlu -+divrem-OP-divq := divq -+divrem-OP-divqu := divqu -+divrem-OP-reml := reml -+divrem-OP-remlu := remlu -+divrem-OP-remq := remq -+divrem-OP-remqu := remqu -+divrem-BASEOP-divl := div -+divrem-BASEOP-divlu := div -+divrem-BASEOP-divq := div -+divrem-BASEOP-divqu := div -+divrem-BASEOP-reml := rem -+divrem-BASEOP-remlu := rem -+divrem-BASEOP-remq := rem -+divrem-BASEOP-remqu := rem -+divrem-S-divl := true -+divrem-S-divlu := false -+divrem-S-divq := true -+divrem-S-divqu := false -+divrem-S-reml := true -+divrem-S-remlu := false -+divrem-S-remq := true -+divrem-S-remqu := false -+divrem-SIZE-divl := l -+divrem-SIZE-divlu := l -+divrem-SIZE-divq := q -+divrem-SIZE-divqu := q -+divrem-SIZE-reml := l -+divrem-SIZE-remlu := l -+divrem-SIZE-remq := q -+divrem-SIZE-remqu := q -+divrem-MODE-divl := l -+divrem-MODE-divlu := lu -+divrem-MODE-divq := q -+divrem-MODE-divqu := qu -+divrem-MODE-reml := l -+divrem-MODE-remlu := lu -+divrem-MODE-remq := q -+divrem-MODE-remqu := qu - -$(divrem:%=$(sysdep_dir)/alpha/%.S): $(sysdep_dir)/alpha/divrem.m4 $(sysdep_dir)/alpha/DEFS.h $(sysdep_dir)/alpha/macros.m4 - (echo "define(OP,\`$(+divrem-NAME)')\ - define(BASEOP,\`$(+divrem-BASEOP-$(+divrem-NAME))')\ - define(MODE,\`$(+divrem-MODE-$(+divrem-NAME))')\ - define(SIZE,\`$(+divrem-SIZE-$(+divrem-NAME))')\ - define(SIGNED,\`$(+divrem-S-$(+divrem-NAME))')\ - define(SYSDEP_DIR, \`$(sysdep_dir)/alpha')\ - /* This file is generated from divrem.m4; DO NOT EDIT! */"; \ - cat $<) | $(M4) > $@-tmp -# Make it unwritable so noone will edit it by mistake. - -chmod a-w $@-tmp - mv -f $@-tmp $@ - test ! -d CVS || cvs commit -m'Regenerated from $<' $@ diff --git a/sysdeps/alpha/__longjmp.c b/sysdeps/alpha/__longjmp.c index f3f35ee..65b6804 100644 --- a/sysdeps/alpha/__longjmp.c +++ b/sysdeps/alpha/__longjmp.c @@ -38,6 +38,8 @@ register double void __longjmp (__jmp_buf env, int val) { + register long int retval asm ("$0"); + /* Restore the integer registers. */ r9 = env[0].__9; r10 = env[0].__10; @@ -73,18 +75,18 @@ __longjmp (__jmp_buf env, int val) precisely the FP and SP the desired environment needs, we must avoid the compiler doing anything with the stack. */ + + asm volatile + ("cmoveq %1, 1, %0\n\t" /* $0 = val ?: 1; */ + "ret $31, (%2), 1" /* return $0 */ + : "=r" (retval) + /* The "0" constraint should force VAL into $0. */ + : "0" (val), "r" (retpc)); + while (1) { /* The loop is just to avoid `volatile function does return' warnings. The instruction will only be executed once. */ - - register long int retval asm ("$0"); - - asm volatile - ("cmoveq %1, 1, %0\n\t" /* $0 = val ?: 1; */ - "ret $31, (%2), 1" /* return $0 */ - : "=r" (retval) - /* The "0" constraint should force VAL into $0. */ - : "0" (val), "r" (retpc)); + asm volatile (""); } } diff --git a/sysdeps/alpha/__math.h b/sysdeps/alpha/__math.h index 5461fca..9aea9d7 100644 --- a/sysdeps/alpha/__math.h +++ b/sysdeps/alpha/__math.h @@ -1,5 +1,7 @@ -/* Copyright (C) 1992 Free Software Foundation, Inc. +/* Inline math functions for Alpha. +Copyright (C) 1996 Free Software Foundation, Inc. This file is part of the GNU C Library. +Contributed by David Mosberger-Tang. 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 @@ -32,4 +34,20 @@ fabs (double __x) return __x; } +extern __inline double +atan (double __x) +{ + extern double __atan2 (double, double); + return __atan2 (__x, 1.0); +} + +#ifdef __USE_MISC +extern __inline double +cabs (struct __cabs_complex __z) +{ + extern double __hypot (double, double); + return __hypot(__z.__x, __z.__y); +} +#endif + #endif diff --git a/sysdeps/alpha/_mcount.S b/sysdeps/alpha/_mcount.S new file mode 100644 index 0000000..2d6e2ed --- /dev/null +++ b/sysdeps/alpha/_mcount.S @@ -0,0 +1,112 @@ +/* Machine-specific calling sequence for `mcount' profiling function. alpha +Copyright (C) 1995 Free Software Foundation, Inc. +Contributed by David Mosberger (davidm@cs.arizona.edu). +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* Assembly stub to invoke _mcount(). Compiler generated code calls +this stub after executing a function's prologue and without saving any +registers. It is therefore necessary to preserve a0..a5 as they may +contain function arguments. To work correctly with frame- less +functions, it is also necessary to preserve ra. Finally, division +routines are invoked with a special calling convention and the +compiler treats those calls as if they were instructions. In +particular, it doesn't save any of the temporary registers (caller +saved registers). It is therefore necessary to preserve all +caller-saved registers as well + +Upon entering _mcount, register $at holds the return address and ra +holds the return address of the function's caller (selfpc and frompc, +respectively in gmon.c language...). */ + +#include <sysdep.h> +#ifdef __linux__ +# include <alpha/regdef.h> +#else +# include <regdef.h> +#endif + +#undef ret /* discard `ret' as defined in sysdep.h */ + + .set noat + .set noreorder + +ENTRY(_mcount) + subq sp, 0xb0, sp + stq a0, 0x00(sp) + mov ra, a0 # a0 = caller-pc + stq a1, 0x08(sp) + mov $at, a1 # a1 = self-pc + stq $at, 0x10(sp) + + stq a2, 0x18(sp) + stq a3, 0x20(sp) + stq a4, 0x28(sp) + stq a5, 0x30(sp) + stq ra, 0x38(sp) + stq gp, 0x40(sp) + + br gp, 1f +1: ldgp gp, 0(gp) + + stq t0, 0x48(sp) + stq t1, 0x50(sp) + stq t2, 0x58(sp) + stq t3, 0x60(sp) + stq t4, 0x68(sp) + stq t5, 0x70(sp) + stq t6, 0x78(sp) + + lda pv, __mcount + + stq t7, 0x80(sp) + stq t8, 0x88(sp) + stq t9, 0x90(sp) + stq t10, 0x98(sp) + stq t11, 0xa0(sp) + stq v0, 0xa8(sp) + + jsr ra, (pv), __mcount + + ldq a0, 0x00(sp) + ldq a1, 0x08(sp) + ldq $at, 0x10(sp) # restore self-pc + ldq a2, 0x18(sp) + ldq a3, 0x20(sp) + ldq a4, 0x28(sp) + ldq a5, 0x30(sp) + ldq ra, 0x38(sp) + ldq gp, 0x40(sp) + mov $at, pv # make pv point to return address + ldq t0, 0x48(sp) # this is important under OSF/1 to + ldq t1, 0x50(sp) # ensure that the code that we return + ldq t2, 0x58(sp) # can correctly compute its gp + ldq t3, 0x60(sp) + ldq t4, 0x68(sp) + ldq t5, 0x70(sp) + ldq t6, 0x78(sp) + ldq t7, 0x80(sp) + ldq t8, 0x88(sp) + ldq t9, 0x90(sp) + ldq t10, 0x98(sp) + ldq t11, 0xa0(sp) + ldq v0, 0xa8(sp) + + addq sp, 0xb0, sp + ret zero,($at),1 + + .end _mcount diff --git a/sysdeps/alpha/bb_init_func.S b/sysdeps/alpha/bb_init_func.S new file mode 100644 index 0000000..9bf985c --- /dev/null +++ b/sysdeps/alpha/bb_init_func.S @@ -0,0 +1,85 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@cs.arizona.edu). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* __bb_init_func is invoked at the beginning of each function, before +any registers have been saved. It is therefore safe to use any +caller-saved (call-used) registers (except for argument registers +a1-a5). */ + +#include <sysdep.h> +#ifdef __linux__ +# include <alpha/regdef.h> +#else +# include <regdef.h> +#endif + +/* + * These offsets should match with "struct bb" declared in gcc/libgcc2.c. + */ +#define ZERO_WORD 0x00 +#define NEXT 0x20 + + .set noat + .set noreorder + +ENTRY(__bb_init_func) + ldq t0, ZERO_WORD(a0) /* t0 <- blocks->zero_word */ + beq t0, init /* not initialized yet -> */ + ret + + +init: subq sp, 0x38, sp + stq pv, 0x30(sp) + br pv, 1f +1: ldgp gp, 0(pv) + + lda t1, __bb_head + lda t3, _gmonparam + ldq t2, 0(t1) + ldl t3, 0(t3) /* t3 = _gmonparam.state */ + ldi t0, 1 + stq t0, ZERO_WORD(a0) /* blocks->zero_word = 1 */ + stq t2, NEXT(a0) /* blocks->next = __bb_head */ + stq a0, 0(t1) + bne t2, leave + beq t3, leave /* t3 == GMON_PROF_ON? yes -> */ + + /* also need to initialize destructor: */ + stq ra, 0x00(sp) + lda a0, __bb_exit_func + stq a1, 0x08(sp) + lda pv, atexit + stq a2, 0x10(sp) + stq a3, 0x18(sp) + stq a4, 0x20(sp) + stq a5, 0x28(sp) + jsr ra, (pv), atexit + ldq ra, 0x00(sp) + ldq a1, 0x08(sp) + ldq a2, 0x10(sp) + ldq a3, 0x18(sp) + ldq a4, 0x20(sp) + ldq a5, 0x28(sp) + +leave: ldq pv, 0x30(sp) + addq sp, 0x38, sp + ret + + .end __bb_init_func diff --git a/sysdeps/alpha/divl.S b/sysdeps/alpha/divl.S index 5c94362..7dbb504 100644 --- a/sysdeps/alpha/divl.S +++ b/sysdeps/alpha/divl.S @@ -1,57 +1,6 @@ - /* This file is generated from divrem.m4; DO NOT EDIT! */ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) +#define IS_REM 0 +#define SIZE 4 +#define SIGNED 1 +#define FUNC_NAME __divl - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - - - - - - -FUNC__(divl) - /* First set up the dividend. */ - sextl t10, t10 - - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - - - /* Then set up the divisor. */ - sextl t11, t11 - - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - sextl t12, t12 - - - - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(divl) +#include "divrem.S" diff --git a/sysdeps/alpha/divlu.S b/sysdeps/alpha/divlu.S index 3a7589d..9cc71da 100644 --- a/sysdeps/alpha/divlu.S +++ b/sysdeps/alpha/divlu.S @@ -1,57 +1,6 @@ - /* This file is generated from divrem.m4; DO NOT EDIT! */ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) +#define IS_REM 0 +#define SIZE 4 +#define SIGNED 0 +#define FUNC_NAME __divlu - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - - - - - - -FUNC__(divlu) - /* First set up the dividend. */ - zapnot t10, 0xf, t10 - - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - - - /* Then set up the divisor. */ - zapnot t11, 0xf, t11 - - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - sextl t12, t12 - - - - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(divlu) +#include "divrem.S" diff --git a/sysdeps/alpha/divq.S b/sysdeps/alpha/divq.S index 730a338..f7af8d6 100644 --- a/sysdeps/alpha/divq.S +++ b/sysdeps/alpha/divq.S @@ -1,54 +1,6 @@ - /* This file is generated from divrem.m4; DO NOT EDIT! */ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) +#define IS_REM 0 +#define SIZE 8 +#define SIGNED 1 +#define FUNC_NAME __divq - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - - - - - - -FUNC__(divq) - /* First set up the dividend. */ - - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - - - /* Then set up the divisor. */ - - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - - - - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(divq) +#include "divrem.S" diff --git a/sysdeps/alpha/divqu.S b/sysdeps/alpha/divqu.S index 7614742..faf2932 100644 --- a/sysdeps/alpha/divqu.S +++ b/sysdeps/alpha/divqu.S @@ -1,60 +1,6 @@ - /* This file is generated from divrem.m4; DO NOT EDIT! */ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) +#define IS_REM 0 +#define SIZE 8 +#define SIGNED 0 +#define FUNC_NAME __divqu - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - - - - - - -FUNC__(divqu) - /* First set up the dividend. */ - - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - ldit $f26, 18446744073709551616.0 - addt $f26, $f10, $f26 - fcmovlt $f10, $f26, $f10 - - - /* Then set up the divisor. */ - - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - ldit $f26, 18446744073709551616.0 - addt $f26, $f1, $f26 - fcmovlt $f1, $f26, $f1 - - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - - - - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(divqu) +#include "divrem.S" diff --git a/sysdeps/alpha/divrem.S b/sysdeps/alpha/divrem.S new file mode 100644 index 0000000..e6293bf --- /dev/null +++ b/sysdeps/alpha/divrem.S @@ -0,0 +1,169 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@cs.arizona.edu). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* The current Alpha chips don't provide hardware for integer +division. The C compiler expects the functions + + __divqu: 64-bit unsigned long divide + __remqu: 64-bit unsigned long remainder + __divqs/__remqs: signed 64-bit + __divlu/__remlu: unsigned 32-bit + __divls/__remls: signed 32-bit + +These are not normal C functions: instead of the normal calling +sequence, these expect their arguments in registers t10 and t11, and +return the result in t12 (aka pv). Registers AT and v0 may be +clobbered (assembly temporary), anything else must be saved. */ + +#ifdef __linux__ +# include <alpha/regdef.h> +# include <asm/gentrap.h> +# include <asm/pal.h> +#else +# include <regdef.h> +# include <machine/pal.h> +#endif + +#ifdef DEBUG +# define arg1 a0 +# define arg2 a1 +# define result v0 +# define mask t0 +# define tmp0 t1 +# define tmp1 t2 +# define sign t3 +# define retaddr ra +#else +# define arg1 t10 +# define arg2 t11 +# define result t12 +# define mask v0 +# define tmp0 t0 +# define tmp1 t1 +# define sign t2 +# define retaddr t9 +#endif + +# define divisor arg2 +#if IS_REM +# define dividend result +# define quotient arg1 +# define GETDIVIDEND bis arg1,zero,dividend +#else +# define dividend arg1 +# define quotient result +# define GETDIVIDEND +#endif + +#if SIZE == 8 +# define LONGIFYarg1 GETDIVIDEND +# define LONGIFYarg2 +#else +# if SIGNED +# define LONGIFYarg1 addl arg1,zero,dividend +# define LONGIFYarg2 addl arg2,zero,divisor +# else +# define LONGIFYarg1 zapnot arg1,0x0f,dividend +# define LONGIFYarg2 zapnot arg2,0x0f,divisor +# endif +#endif + +#if SIGNED +# define SETSIGN(sign,reg,tmp) subq zero,reg,tmp; cmovlt sign,tmp,reg +# if IS_REM +# define GETSIGN(x,y,s) bis x,zero,s +# else +# define GETSIGN(x,y,s) xor x,y,s +# endif +#else +# define SETSIGN(sign,reg,tmp) +# define GETSIGN(x,y,s) +#endif + + .set noreorder + .set noat + + .ent FUNC_NAME + .globl FUNC_NAME + + .align 5 +FUNC_NAME: +# define FRAME_SIZE 0x30 + .frame sp,FRAME_SIZE,ra,0 + lda sp,-FRAME_SIZE(sp) + .prologue 1 + stq arg1,0x00(sp) + LONGIFYarg1 + stq arg2,0x08(sp) + LONGIFYarg2 + stq mask,0x10(sp) + bis zero,1,mask + stq tmp0,0x18(sp) + bis zero,zero,quotient + stq tmp1,0x20(sp) + beq divisor,divbyzero + stq sign,0x28(sp) + GETSIGN(dividend,divisor,sign) +#if SIGNED + subq zero,dividend,tmp0 + subq zero,divisor,tmp1 + cmovlt dividend,tmp0,dividend + cmovlt divisor,tmp1,divisor +#endif + /* + * Shift divisor left until either bit 63 is set or until it + * is at least as big as the dividend: + */ + .align 3 +1: cmpule dividend,divisor,AT + blt divisor,2f + blbs AT,2f + addq mask,mask,mask + addq divisor,divisor,divisor + br 1b + + .align 3 +2: addq mask,quotient,tmp0 + cmpule divisor,dividend,AT + subq dividend,divisor,tmp1 + srl divisor,1,divisor + srl mask,1,mask + cmovlbs AT,tmp0,quotient + cmovlbs AT,tmp1,dividend + bne mask,2b + + ldq arg1,0x00(sp) + SETSIGN(sign,result,tmp0) +done: ldq arg2,0x08(sp) + ldq mask,0x10(sp) + ldq tmp0,0x18(sp) + ldq tmp1,0x20(sp) + ldq sign,0x28(sp) + lda sp,FRAME_SIZE(sp) + ret zero,(retaddr),0 + +divbyzero: + lda a0,GEN_INTDIV(zero) + call_pal PAL_gentrap + bis zero,zero,result /* if trap returns, return 0 */ + ldq arg1,0x00(sp) + br done + + .end FUNC_NAME diff --git a/sysdeps/alpha/divrem.m4 b/sysdeps/alpha/divrem.m4 deleted file mode 100644 index d2f3638..0000000 --- a/sysdeps/alpha/divrem.m4 +++ /dev/null @@ -1,51 +0,0 @@ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) - - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - -define(path, `SYSDEP_DIR/macros.m4')dnl -include(path) - -FUNC__(OP) - /* First set up the dividend. */ - EXTEND(t10) - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - ADJQU($f10) - - /* Then set up the divisor. */ - EXTEND(t11) - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - ADJQU($f1) - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - FULLEXTEND(t12) - - DOREM - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(OP) diff --git a/sysdeps/alpha/ffs.S b/sysdeps/alpha/ffs.S new file mode 100644 index 0000000..7676b85 --- /dev/null +++ b/sysdeps/alpha/ffs.S @@ -0,0 +1,71 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@cs.arizona.edu). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* Finds the first bit set in an integer. Optimized for the Alpha +architecture. */ + +#include <sysdep.h> +#ifdef __linux__ +# include <alpha/regdef.h> +#else +#include <regdef.h> +#endif + + .set noreorder + .set noat + +ENTRY(ffs) + .prologue 0 + + ldq_u zero, 0(sp) # on the 21064, this helps dual-issuing + addl a0, zero, a0 # the last insn and reduces the stall + negq a0, t0 # due to the srl instruction + and a0, t0, t0 + clr v0 + beq a0, done + + # now do binary search for first non-zero bit + + zapnot t0, 0x03, t2 + addq v0, 16, t3 + cmoveq t2, t3, v0 + + zapnot t0, 0x05, t2 + addq v0, 8, t3 + cmoveq t2, t3, v0 + + srl t0, v0, t0 + addq v0, 1, v0 + + and t0, 0x0f, t2 + addq v0, 4, t3 + cmoveq t2, t3, v0 + + and t0, 0x33, t2 + addq v0, 2, t3 + cmoveq t2, t3, v0 + + and t0, 0x55, t2 + addq v0, 1, t3 + cmoveq t2, t3, v0 + +done: ret + + .end ffs diff --git a/sysdeps/alpha/htonl.S b/sysdeps/alpha/htonl.S new file mode 100644 index 0000000..d0bf7e1 --- /dev/null +++ b/sysdeps/alpha/htonl.S @@ -0,0 +1,42 @@ +/* Copyright (C) 1996 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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <sysdep.h> +#ifdef __linux__ +# include <alpha/regdef.h> +#else +#include <regdef.h> +#endif + +ENTRY(__htonl) + extlh a0,5,t1 # t1 = dd000000 + zap a0,0xfd,t2 # t2 = 0000cc00 + sll t2,5,t2 # t2 = 00198000 + s8addl t2,t1,t1 # t1 = ddcc0000 + zap a0,0xfb,t2 # t2 = 00bb0000 + srl t2,8,t2 # t2 = 0000bb00 + extbl a0,3,v0 # v0 = 000000aa + or t1,v0,v0 # v0 = ddcc00aa + or t2,v0,v0 # v0 = ddccbbaa + ret + + .end __htonl + +strong_alias_asm(__htonl, __ntohl) +weak_alias(__htonl, htonl) +weak_alias(__htonl, ntohl) diff --git a/sysdeps/alpha/htons.S b/sysdeps/alpha/htons.S new file mode 100644 index 0000000..6e18c7c --- /dev/null +++ b/sysdeps/alpha/htons.S @@ -0,0 +1,36 @@ +/* Copyright (C) 1996 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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <sysdep.h> +#ifdef __linux__ +# include <alpha/regdef.h> +#else +#include <regdef.h> +#endif + +ENTRY(__htons) + extwh a0,7,t1 # t1 = bb00 + extbl a0,1,v0 # v0 = 00aa + bis v0,t1,v0 # v0 = bbaa + ret + + .end __htons + +strong_alias_asm(__htons, __ntohs) +weak_alias(__htons, htons) +weak_alias(__htons, ntohs) diff --git a/sysdeps/alpha/machine-gmon.h b/sysdeps/alpha/machine-gmon.h new file mode 100644 index 0000000..a551e9f --- /dev/null +++ b/sysdeps/alpha/machine-gmon.h @@ -0,0 +1,25 @@ +/* Machine-specific calling sequence for `mcount' profiling function. alpha +Copyright (C) 1995 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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#define _MCOUNT_DECL void __mcount + +/* Call __mcount with our the return PC for our caller, and the return + PC our caller will return to. Empty since we use an assembly stub + instead. */ +#define MCOUNT diff --git a/sysdeps/alpha/macros.m4 b/sysdeps/alpha/macros.m4 deleted file mode 100644 index f8c1fe9..0000000 --- a/sysdeps/alpha/macros.m4 +++ /dev/null @@ -1,34 +0,0 @@ -dnl NOTE: The $1 below is the argument to EXTEND, not register $1. -define(EXTEND, -`ifelse(SIZE, `l', -`ifelse(SIGNED, `true', -` sextl $1, $1 -',dnl -` zapnot $1, 0xf, $1 -')')')dnl - -dnl FULLEXTEND -- extend the register named in the first argument -define(FULLEXTEND, -`ifelse(SIZE, `l', -` sextl $1, $1 -')')dnl - -dnl This is used by divqu. -define(ADJQU, -`ifelse(MODE, `qu', -` ldit $f26, 18446744073709551616.0 - addt $f26, $1, $f26 - fcmovlt $1, $f26, $1 -')')dnl - -define(DOREM, -`ifelse(BASEOP, `rem', -` /* Compute the remainder. */ -ifelse(SIZE, `l', -` mull t11, t12, t11 - subl t10, t11, t12 -',dnl Note mulq/subq were only really used in remq, but we will find out -dnl if assuming they apply to remqu as well is wrong or not. -` mulq t11, t12, t11 - subq t10, t11, t12 -')')')dnl diff --git a/sysdeps/alpha/ntohl.s b/sysdeps/alpha/ntohl.s new file mode 100644 index 0000000..6a99a01 --- /dev/null +++ b/sysdeps/alpha/ntohl.s @@ -0,0 +1,2 @@ +/* This is a dummy to avoid including the generic version. htonl and +ntohl are identical and htonl.S defines appropriate aliases. */ diff --git a/sysdeps/alpha/ntohs.s b/sysdeps/alpha/ntohs.s new file mode 100644 index 0000000..69992a8 --- /dev/null +++ b/sysdeps/alpha/ntohs.s @@ -0,0 +1,2 @@ +/* This is a dummy to avoid including the generic version. htons and +ntohs are identical and htons.S defines appropriate aliases. */ diff --git a/sysdeps/alpha/reml.S b/sysdeps/alpha/reml.S index 95896fb..cede136 100644 --- a/sysdeps/alpha/reml.S +++ b/sysdeps/alpha/reml.S @@ -1,60 +1,6 @@ - /* This file is generated from divrem.m4; DO NOT EDIT! */ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) +#define IS_REM 1 +#define SIZE 4 +#define SIGNED 1 +#define FUNC_NAME __reml - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - - - - - - -FUNC__(reml) - /* First set up the dividend. */ - sextl t10, t10 - - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - - - /* Then set up the divisor. */ - sextl t11, t11 - - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - sextl t12, t12 - - - /* Compute the remainder. */ - mull t11, t12, t11 - subl t10, t11, t12 - - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(reml) +#include "divrem.S" diff --git a/sysdeps/alpha/remlu.S b/sysdeps/alpha/remlu.S index 24e07cf..3658d92 100644 --- a/sysdeps/alpha/remlu.S +++ b/sysdeps/alpha/remlu.S @@ -1,60 +1,6 @@ - /* This file is generated from divrem.m4; DO NOT EDIT! */ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) +#define IS_REM 1 +#define SIZE 4 +#define SIGNED 0 +#define FUNC_NAME __remlu - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - - - - - - -FUNC__(remlu) - /* First set up the dividend. */ - zapnot t10, 0xf, t10 - - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - - - /* Then set up the divisor. */ - zapnot t11, 0xf, t11 - - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - sextl t12, t12 - - - /* Compute the remainder. */ - mull t11, t12, t11 - subl t10, t11, t12 - - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(remlu) +#include "divrem.S" diff --git a/sysdeps/alpha/remq.S b/sysdeps/alpha/remq.S index ce38c24..61f2067 100644 --- a/sysdeps/alpha/remq.S +++ b/sysdeps/alpha/remq.S @@ -1,57 +1,6 @@ - /* This file is generated from divrem.m4; DO NOT EDIT! */ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) +#define IS_REM 1 +#define SIZE 8 +#define SIGNED 1 +#define FUNC_NAME __remq - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - - - - - - -FUNC__(remq) - /* First set up the dividend. */ - - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - - - /* Then set up the divisor. */ - - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - - - /* Compute the remainder. */ - mulq t11, t12, t11 - subq t10, t11, t12 - - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(remq) +#include "divrem.S" diff --git a/sysdeps/alpha/remqu.S b/sysdeps/alpha/remqu.S index 26bdd3b..e22d5ac 100644 --- a/sysdeps/alpha/remqu.S +++ b/sysdeps/alpha/remqu.S @@ -1,63 +1,6 @@ - /* This file is generated from divrem.m4; DO NOT EDIT! */ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) +#define IS_REM 1 +#define SIZE 8 +#define SIGNED 0 +#define FUNC_NAME __remqu - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - - - - - - -FUNC__(remqu) - /* First set up the dividend. */ - - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - ldit $f26, 18446744073709551616.0 - addt $f26, $f10, $f26 - fcmovlt $f10, $f26, $f10 - - - /* Then set up the divisor. */ - - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - ldit $f26, 18446744073709551616.0 - addt $f26, $f1, $f26 - fcmovlt $f1, $f26, $f1 - - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - - - /* Compute the remainder. */ - mulq t11, t12, t11 - subq t10, t11, t12 - - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(remqu) +#include "divrem.S" diff --git a/sysdeps/alpha/setjmp.S b/sysdeps/alpha/setjmp.S index 08932cc..8ea2b50 100644 --- a/sysdeps/alpha/setjmp.S +++ b/sysdeps/alpha/setjmp.S @@ -23,7 +23,7 @@ Cambridge, MA 02139, USA. */ extra arguments. */ ENTRY (__sigsetjmp) lda $27, __sigsetjmp_aux/* Load address to jump to. */ - bis $15, $15, $18 /* Pass FP as 3rd arg. */ - bis $30, $30, $19 /* Pass SP as 4th arg. */ + bis $30, $30, $18 /* Pass SP as 3rd arg. */ + bis $15, $15, $19 /* Pass FP as 4th arg. */ jmp $31, ($27), __sigsetjmp_aux /* Call __sigsetjmp_aux. */ .end __sigsetjmp diff --git a/sysdeps/alpha/setjmp_aux.c b/sysdeps/alpha/setjmp_aux.c index f92517b..0f05f8b 100644 --- a/sysdeps/alpha/setjmp_aux.c +++ b/sysdeps/alpha/setjmp_aux.c @@ -69,6 +69,8 @@ __sigsetjmp_aux (sigjmp_buf env, int savemask, long int *sp, long int *fp) /* Save the signal mask if requested. */ __sigjmp_save (env, savemask); + retpc = env[0].__jmpbuf[0].__pc; /* restore ra, ugly... */ + /* Return to the original caller of __sigsetjmp. */ return 0; } diff --git a/sysdeps/alpha/strlen.S b/sysdeps/alpha/strlen.S new file mode 100644 index 0000000..7e6a61b --- /dev/null +++ b/sysdeps/alpha/strlen.S @@ -0,0 +1,75 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@cs.arizona.edu). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* Finds length of a 0-terminated string. Optimized for the Alpha +architecture: + + - memory accessed as aligned quadwords only + - uses bcmpge to compare 8 bytes in parallel + - does binary search to find 0 byte in last + quadword (HAKMEM needed 12 instructions to + do this instead of the 9 instructions that + binary search needs). */ + +#include <sysdep.h> +#ifdef __linux__ +# include <alpha/regdef.h> +#else +#include <regdef.h> +#endif + + .set noreorder + .set noat + +ENTRY(strlen) + ldq_u t0, 0(a0) # load first quadword (a0 may be misaligned) + lda t1, -1(zero) + insqh t1, a0, t1 + andnot a0, 7, v0 + or t1, t0, t0 + cmpbge zero, t0, t1 # t1 <- bitmask: bit i == 1 <==> i-th byte == 0 + bne t1, found + +loop: ldq t0, 8(v0) + addq v0, 8, v0 # addr += 8 + nop # helps dual issue last two insns + cmpbge zero, t0, t1 + beq t1, loop + +found: blbs t1, done # make aligned case fast + negq t1, t2 + and t1, t2, t1 + + and t1, 0x0f, t0 + addq v0, 4, t2 + cmoveq t0, t2, v0 + + and t1, 0x33, t0 + addq v0, 2, t2 + cmoveq t0, t2, v0 + + and t1, 0x55, t0 + addq v0, 1, t2 + cmoveq t0, t2, v0 + +done: subq v0, a0, v0 + ret + + .end strlen diff --git a/sysdeps/alpha/strlen.c b/sysdeps/alpha/strlen.c deleted file mode 100644 index 36f106c..0000000 --- a/sysdeps/alpha/strlen.c +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright (C) 1992 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., 675 Mass Ave, -Cambridge, MA 02139, USA. */ - -#include <string.h> - -/* Return the length of the null-terminated string STR. Scan for - the null terminator quickly by testing eight bytes at a time. */ - -size_t -strlen (const char *str) -{ - const char *char_ptr; - const unsigned long int *longword_ptr; - - /* Handle the first few characters by reading one character at a time. - Do this until STR is aligned on a 8-byte border. */ - for (char_ptr = str; ((unsigned long int) char_ptr & 7) != 0; ++char_ptr) - if (*char_ptr == '\0') - return char_ptr - str; - - longword_ptr = (unsigned long int *) char_ptr; - - for (;;) - { - const unsigned long int longword = *longword_ptr++; - int mask; - - /* Set bits in MASK if bytes in LONGWORD are zero. */ - asm ("cmpbge $31, %1, %0" : "=r" (mask) : "r" (longword)); - if (mask) - { - /* Which of the bytes was the zero? */ - const char *cp = (const char *) (longword_ptr - 1); - int i; - - for (i = 0; i < 8; i++) - if (cp[i] == 0) - return cp - str + i; - } - } -} diff --git a/sysdeps/generic/bb_init_func.c b/sysdeps/generic/bb_init_func.c new file mode 100644 index 0000000..0c768c3 --- /dev/null +++ b/sysdeps/generic/bb_init_func.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@cs.arizona.edu). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* __bb_init_func is invoked at the beginning of each function, before +any registers have been saved. This generic routine should work +provided that calling this function doesn't mangle the arguments +passed to the function being called. If that's not the case, a system +specific routine must be provided. */ + +#include <sys/types.h> +#include <sys/gmon.h> + +#include <ansidecl.h> +#include <stdlib.h> + +void +DEFUN(__bb_init_func, (bb), struct __bb *bb) +{ + struct gmonparam *p = &_gmonparam; + + if (bb->zero_word != 0) + { + return; /* handle common case quickly */ + } + + /* insert this basic-block into basic-block list: */ + bb->zero_word = 1; + bb->next = __bb_head; + __bb_head = bb; + + if (bb->next == 0 && p->state != GMON_PROF_ON) + { + /* we didn't register _mcleanup yet and pc profiling doesn't seem + to be active, so let's register it now: */ + atexit(_mcleanup); + } +} diff --git a/sysdeps/generic/ffs.c b/sysdeps/generic/ffs.c index 016f033..18239cb 100644 --- a/sysdeps/generic/ffs.c +++ b/sysdeps/generic/ffs.c @@ -38,8 +38,8 @@ DEFUN(ffs, (i), int i) 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 }; - unsigned long int a; - unsigned long int x = i & -i; + unsigned int a; + unsigned int x = i & -i; a = x <= 0xffff ? (x <= 0xff ? 0 : 8) : (x <= 0xffffff ? 16 : 24); diff --git a/sysdeps/generic/sbrk.c b/sysdeps/generic/sbrk.c index 83e2536..de77946 100644 --- a/sysdeps/generic/sbrk.c +++ b/sysdeps/generic/sbrk.c @@ -26,7 +26,7 @@ extern int __brk (void *addr); If INCREMENT is negative, shrink data space by - INCREMENT. Return start of new space allocated, or -1 for errors. */ void * -__sbrk (int increment) +__sbrk (ptrdiff_t increment) { void *oldbrk; diff --git a/sysdeps/i386/fpu/__math.h b/sysdeps/i386/fpu/__math.h new file mode 100644 index 0000000..2a759c2 --- /dev/null +++ b/sysdeps/i386/fpu/__math.h @@ -0,0 +1,512 @@ +/* Inline math functions for i387. +Copyright (C) 1995, 1996 Free Software Foundation, Inc. +Contributed by John C. Bowman <bowman@hagar.ph.utexas.edu> + +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 __MATH_H +#define __MATH_H + +#ifdef __GNUC__ +#ifndef __NO_MATH_INLINES + +#ifdef __cplusplus +#define __MATH_INLINE __inline +#else +#define __MATH_INLINE extern __inline +#endif + +__MATH_INLINE double cos (double); +__MATH_INLINE double sin (double); + + +__MATH_INLINE double __expm1 (double __x); +__MATH_INLINE double +__expm1 (double __x) +{ + register double __value, __exponent, __temp; + __asm __volatile__ + ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" + "fmul %%st(1) # x * log2(e)\n\t" + "fstl %%st(1)\n\t" + "frndint # int(x * log2(e))\n\t" + "fxch\n\t" + "fsub %%st(1) # fract(x * log2(e))\n\t" + "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" + "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" + : "=t" (__value), "=u" (__exponent) : "0" (__x)); + __asm __volatile__ + ("fscale # 2^int(x * log2(e))\n\t" + : "=t" (__temp) : "0" (1.0), "u" (__exponent)); + __temp -= 1.0; + + return __temp + __value; +} + +__MATH_INLINE double __sgn1 (double __x); +__MATH_INLINE double +__sgn1 (double __x) +{ + return __x >= 0.0 ? 1.0 : -1.0; +} + +__MATH_INLINE double sqrt (double __x); +__MATH_INLINE double +sqrt (double __x) +{ + register double __value; + __asm __volatile__ + ("fsqrt" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +__MATH_INLINE double fabs (double __x); +__MATH_INLINE double +fabs (double __x) +{ + register double __value; + __asm __volatile__ + ("fabs" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +__MATH_INLINE double sin (double __x); +__MATH_INLINE double +sin (double __x) +{ + register double value; + __asm __volatile__ + ("fsin" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +__MATH_INLINE double cos (double __x); +__MATH_INLINE double +cos (double __x) +{ + register double __value; + __asm __volatile__ + ("fcos" + : "=t" (__value): "0" (__x)); + + return __value; +} + +__MATH_INLINE double tan (double __x); +__MATH_INLINE double +tan (double __x) +{ + register double __value; + __asm __volatile__ + ("fptan" + : "=u" (__value) : "t" (__x)); + + return __value; +} + +__MATH_INLINE double atan2 (double __y, double __x); +__MATH_INLINE double +atan2 (double __y, double __x) +{ + register double __value; + __asm __volatile__ + ("fpatan\n\t" + "fldl %%st(0)" + : "=t" (__value) : "0" (__x), "u" (__y)); + + return __value; +} + +__MATH_INLINE double asin (double __x); +__MATH_INLINE double +asin (double __x) +{ + return atan2 (__x, sqrt (1.0 - __x * __x)); +} + +__MATH_INLINE double acos (double __x); +__MATH_INLINE double +acos (double __x) +{ + return atan2 (sqrt (1.0 - __x * __x), __x); +} + +__MATH_INLINE double atan (double __x); +__MATH_INLINE double +atan (double __x) +{ + register double __value; + __asm __volatile__ + ("fld1\n\t" + "fpatan" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +__MATH_INLINE double exp (double __x); +__MATH_INLINE double +exp (double __x) +{ + register double __value, __exponent; + __asm __volatile__ + ("fldl2e # e^x = 2^(x * log2(e))\n\t" + "fmul %%st(1) # x * log2(e)\n\t" + "fstl %%st(1)\n\t" + "frndint # int(x * log2(e))\n\t" + "fxch\n\t" + "fsub %%st(1) # fract(x * log2(e))\n\t" + "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" + : "=t" (__value), "=u" (__exponent) : "0" (__x)); + value += 1.0; + __asm __volatile__ + ("fscale" + : "=t" (__value) : "0" (__value), "u" (__exponent)); + + return __value; +} + +__MATH_INLINE double sinh (double __x); +__MATH_INLINE double +sinh (double __x) +{ + register double __exm1 = __expm1 (fabs (__x)); + + return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1 (__x); +} + +__MATH_INLINE double cosh (double __x); +__MATH_INLINE double +cosh (double __x) +{ + register double __ex = exp (__x); + + return 0.5 * (__ex + 1.0 / __ex); +} + +__MATH_INLINE double tanh (double __x); +__MATH_INLINE double +tanh (double __x) +{ + register double __exm1 = __expm1 (-fabs (__x + __x)); + + return __exm1 / (__exm1 + 2.0) * __sgn1 (-__x); +} + +__MATH_INLINE double log (double __x); +__MATH_INLINE double +log (double __x) +{ + register double __value; + __asm __volatile__ + ("fldln2\n\t" + "fxch\n\t" + "fyl2x" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +__MATH_INLINE double log10 (double __x); +__MATH_INLINE double +log10 (double __x) +{ + register double __value; + __asm __volatile__ + ("fldlg2\n\t" + "fxch\n\t" + "fyl2x" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +__MATH_INLINE double __log2 (double __x); +__MATH_INLINE double +__log2 (double __x) +{ + register double __value; + __asm __volatile__ + ("fld1\n\t" + "fxch\n\t" + "fyl2x" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +__MATH_INLINE double fmod (double __x, double __y); +__MATH_INLINE double +fmod (double __x, double __y) +{ + register double __value; + __asm __volatile__ + ("1: fprem\n\t" + "fstsw %%ax\n\t" + "sahf\n\t" + "jp 1b" + : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); + + return __value; +} + +__MATH_INLINE double ldexp (double __x, int __y); +__MATH_INLINE double +ldexp (double __x, int __y) +{ + register double __value; + __asm __volatile__ + ("fscale" + : "=t" (__value) : "0" (__x), "u" ((double) __y)); + + return __value; +} + +__MATH_INLINE double pow (double __x, double __y); +__MATH_INLINE double +pow (double __x, double __y) +{ + register double __value, __exponent; + long __p = (long) __y; + + if (__x == 0.0 && __y > 0.0) + return 0.0; + if (__y == (double) __p) + { + double __r = 1.0; + if (__p == 0) + return 1.0; + if (__p < 0) + { + __p = -__p; + __x = 1.0 / __x; + } + while (1) + { + if (__p & 1) + __r *= __x; + __p >>= 1; + if (__p == 0) + return __r; + __x *= __x; + } + /* NOTREACHED */ + } + __asm __volatile__ + ("fmul %%st(1) # y * log2(x)\n\t" + "fstl %%st(1)\n\t" + "frndint # int(y * log2(x))\n\t" + "fxch\n\t" + "fsub %%st(1) # fract(y * log2(x))\n\t" + "f2xm1 # 2^(fract(y * log2(x))) - 1\n\t" + : "=t" (__value), "=u" (__exponent) : "0" (__log2 (__x)), "1" (__y)); + __value += 1.0; + __asm __volatile__ + ("fscale" + : "=t" (__value) : "0" (__value), "u" (__exponent)); + + return __value; +} + +__MATH_INLINE double floor (double __x); +__MATH_INLINE double +floor (double __x) +{ + register double __value; + volatile short __cw, __cwtmp; + + __asm volatile ("fnstcw %0" : "=m" (__cw)); + __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */ + __asm volatile ("fldcw %0" : : "m" (__cwtmp)); + __asm volatile ("frndint" : "=t" (__value) : "0" (__x)); + __asm volatile ("fldcw %0" : : "m" (__cw)); + + return __value; +} + +__MATH_INLINE double ceil (double __x); +__MATH_INLINE double +ceil (double __x) +{ + register double __value; + volatile short __cw, __cwtmp; + + __asm volatile ("fnstcw %0" : "=m" (__cw)); + __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */ + __asm volatile ("fldcw %0" : : "m" (__cwtmp)); + __asm volatile ("frndint" : "=t" (__value) : "0" (__x)); + __asm volatile ("fldcw %0" : : "m" (__cw)); + + return __value; +} + + +/* Optimized versions for some non-standardized functions. */ +#ifdef __USE_MISC + +__MATH_INLINE double __hypot (double __x, double __y); +__MATH_INLINE double +hypot (double __x, double __y) +{ + return sqrt (__x * __x + __y * __y); +} + +__MATH_INLINE double __log1p (double __x); +__MATH_INLINE double +log1p (double __x) +{ + register double __value; + + if (fabs (__x) >= 1.0 - 0.5 * M_SQRT2) + __value = log (1.0 + __x); + else + __asm __volatile__ + ("fldln2\n\t" + "fxch\n\t" + "fyl2xp1" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +__MATH_INLINE double __asinh (double __x); +__MATH_INLINE double +asinh (double __x) +{ + register double __y = fabs (__x); + + return __log1p ((__y * __y / (sqrt (__y * __y + 1.0) + 1.0) + __y) + * __sgn1 (__x)); +} + +__MATH_INLINE double __acosh (double __x); +__MATH_INLINE double +acosh (double __x) +{ + return log (__x + sqrt (__x - 1.0) * sqrt (__x + 1.0)); +} + +__MATH_INLINE double __atanh (double __x); +__MATH_INLINE double +atanh (double __x) +{ + register double __y = fabs (__x); + + return -0.5 * __log1p (-(__y + __y) / (1.0 + __y)) * __sgn1 (__x); +} + +__MATH_INLINE double __coshm1 (double __x); +__MATH_INLINE double +coshm1 (double __x) +{ + register double __exm1 = __expm1 (fabs (__x)); + + return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1; +} + +__MATH_INLINE double __acosh1p (double __x); +__MATH_INLINE double +acosh1p (double __x) +{ + return __log1p (__x + sqrt (__x) * sqrt (__x + 2.0)); +} + +__MATH_INLINE double __logb (double __x); +__MATH_INLINE double +logb (double __x) +{ + register double __value; + __asm __volatile__ + ("fxtract\n\t" + : "=u" (__value) : "0" (__x)); + + return __value; +} + +__MATH_INLINE double __drem (double __x, double __y); +__MATH_INLINE double +drem (double __x, double __y) +{ + register double __value; + __asm __volatile__ + ("1: fprem1\n\t" + "fstsw %%ax\n\t" + "sahf\n\t" + "jp 1b" + : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); + + return __value; +} + +__MATH_INLINE void __sincos (double __x, double *__sinx, double *__cosx); +__MATH_INLINE void +sincos (double __x, double *__sinx, double *__cosx) +{ + register double __cosr, __sinr; + __asm __volatile__ + ("fsincos" + : "=t" (__cosr), "=u" (__sinr) : "0" (__x)); + + *__sinx = __sinr; + *__cosx = __cosr; +} + +__MATH_INLINE double __sgn (double __x); +__MATH_INLINE double +sgn (double __x) +{ + return (__x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0)); +} + +__MATH_INLINE double __pow2 (double __x); +__MATH_INLINE double +pow2 (double __x) +{ + register double __value, __exponent; + long __p = (long) __x; + + if (__x == (double) __p) + return ldexp (1.0, __p); + + __asm __volatile__ + ("fldl %%st(0)\n\t" + "frndint # int(x)\n\t" + "fxch\n\t" + "fsub %%st(1) # fract(x)\n\t" + "f2xm1 # 2^(fract(x)) - 1\n\t" + : "=t" (__value), "=u" (__exponent) : "0" (__x)); + __value += 1.0; + __asm __volatile__ + ("fscale" + : "=t" (__value) : "0" (__value), "u" (__exponent)); + + return __value; +} + +#endif /* __USE_MISC */ + +#endif /* __NO_MATH_INLINES */ +#endif /* __GNUC__ */ + +#endif /* __MATH_H */ diff --git a/sysdeps/mach/hurd/getcwd.c b/sysdeps/mach/hurd/getcwd.c index b42e097..abec22c 100644 --- a/sysdeps/mach/hurd/getcwd.c +++ b/sysdeps/mach/hurd/getcwd.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. +/* Copyright (C) 1991, 92, 93, 94, 95, 96 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 @@ -57,7 +57,7 @@ __getcwd (char *buf, size_t size) (vm_address_t) dirbuf, dirbufsize); } - + if (size == 0) { if (buf != NULL) @@ -139,7 +139,7 @@ __getcwd (char *buf, size_t size) dirdatasize = dirbufsize; while (!(err = __dir_readdir (parent, &dirdata, &dirdatasize, direntry, -1, 0, &nentries)) && - nentries != 0) + nentries != 0) { /* We have a block of directory entries. */ @@ -167,7 +167,7 @@ __getcwd (char *buf, size_t size) d = (struct dirent *) &dirdata[offset]; offset += d->d_reclen; - /* Ignore `.' and `..'. */ + /* Ignore `.' and `..'. */ if (d->d_name[0] == '.' && (d->d_namlen == 1 || (d->d_namlen == 2 && d->d_name[1] == '.'))) @@ -191,6 +191,14 @@ __getcwd (char *buf, size_t size) if (err) goto errlose; + else if (nentries == 0) + { + /* We got to the end of the directory without finding anything! + We are in a directory that has been unlinked, or something is + broken. */ + err = ENOENT; + goto errlose; + } else { /* Prepend the directory name just discovered. */ diff --git a/sysdeps/mach/hurd/setpgid.c b/sysdeps/mach/hurd/setpgid.c index 7c74ef8..cda54e1 100644 --- a/sysdeps/mach/hurd/setpgid.c +++ b/sysdeps/mach/hurd/setpgid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1994, 1995, 1996 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 @@ -54,4 +54,3 @@ DEFUN(__setpgid, (pid, pgid), pid_t pid AND pid_t pgid) } weak_alias (__setpgid, setpgid) -weak_alias (__setpgid, setpgrp) diff --git a/sysdeps/posix/clock.c b/sysdeps/posix/clock.c index c34593b..9eadc78 100644 --- a/sysdeps/posix/clock.c +++ b/sysdeps/posix/clock.c @@ -29,5 +29,5 @@ DEFUN_VOID(clock) if (__times(&buf) < 0) return (clock_t) -1; - return ((buf.tms_utime + buf.tms_stime) * CLK_TCK * CLOCKS_PER_SEC); + return buf.tms_utime + buf.tms_stime; } diff --git a/sysdeps/posix/sleep.c b/sysdeps/posix/sleep.c index 36864cb..20f78a0 100644 --- a/sysdeps/posix/sleep.c +++ b/sysdeps/posix/sleep.c @@ -58,8 +58,8 @@ DEFUN(sleep, (seconds), unsigned int seconds) act.sa_handler = sleep_handler; act.sa_flags = 0; - if (sigemptyset (&act.sa_mask) < 0 || - sigaction (SIGALRM, &act, &oact) < 0) + act.sa_mask = oset; /* execute handler with original mask */ + if (sigaction (SIGALRM, &act, &oact) < 0) return seconds; before = time ((time_t *) NULL); diff --git a/sysdeps/stub/setpgid.c b/sysdeps/stub/setpgid.c index 7e1d1a9..c694215 100644 --- a/sysdeps/stub/setpgid.c +++ b/sysdeps/stub/setpgid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1995 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1995, 1996 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,4 +32,3 @@ DEFUN(__setpgid, (pid, pgid), int pid AND int pgid) stub_warning (setpgid) weak_alias (__setpgid, setpgid) -weak_alias (__setpgid, setpgrp) diff --git a/sysdeps/unix/alarm.c b/sysdeps/unix/alarm.c index 7743256..e0dd3db 100644 --- a/sysdeps/unix/alarm.c +++ b/sysdeps/unix/alarm.c @@ -31,6 +31,7 @@ unsigned int DEFUN(alarm, (seconds), unsigned int seconds) { struct itimerval old, new; + unsigned int retval; new.it_interval.tv_usec = 0; new.it_interval.tv_sec = 0; @@ -39,5 +40,8 @@ DEFUN(alarm, (seconds), unsigned int seconds) if (__setitimer(ITIMER_REAL, &new, &old) < 0) return 0; - return (old.it_value.tv_sec + (old.it_value.tv_usec + 999999) / 1000000); + retval = old.it_value.tv_sec; + if (old.it_value.tv_usec) + ++retval; + return retval; } diff --git a/sysdeps/unix/alpha/sysdep.h b/sysdeps/unix/alpha/sysdep.h new file mode 100644 index 0000000..9eb9032 --- /dev/null +++ b/sysdeps/unix/alpha/sysdep.h @@ -0,0 +1,86 @@ +/* Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc. + Contributed by Brendan Kehoe (brendan@zen.org). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <sysdeps/unix/sysdep.h> + +#ifdef ASSEMBLER + +#ifdef __STDC__ +#define ENTRY(name) \ + .globl name; \ + .align 3; \ + .ent name,0; \ + name##: \ + .frame sp,0,ra +#else +#define ENTRY(name) \ + .globl name; \ + .align 3; \ + .ent name,0; \ + name/**/: \ + .frame sp,0,ra +#endif + +/* Note that while it's better structurally, going back to set errno + can make things confusing if you're debugging---it looks like it's jumping + backwards into the previous fn. */ +#ifdef __STDC__ +#define PSEUDO(name, syscall_name, args) \ + .globl name; \ + .align 3; \ + .ent name,0; \ + \ +1: br gp,2f; \ +2: ldgp gp,0(gp); \ + lda pv,syscall_error; \ + jmp zero,(pv); \ + \ +name##: \ + ldi v0,SYS_ify(syscall_name); \ + .set noat; \ + call_pal PAL_callsys; \ + .set at; \ + bne a3,1b; \ +3: +#else +#define PSEUDO(name, syscall_name, args) \ + .globl name; \ + .align 3; \ + .ent name,0; \ + \ +1: br gp,2f; \ +2: ldgp gp,0(gp); \ + lda pv,syscall_error; \ + jmp zero,(pv); \ + \ +name/**/: \ + ldi v0,SYS_ify(syscall_name); \ + .set noat; \ + call_pal PAL_callsys; \ + .set at; \ + bne a3,1b; \ +3: +#endif + +#define ret ret zero,(ra),1 +#define r0 v0 +#define r1 a4 + +#define MOVE(x,y) mov x,y + +#endif diff --git a/sysdeps/unix/bsd/osf/alpha/sysdep.h b/sysdeps/unix/bsd/osf/alpha/sysdep.h index fc661a6..7bd7192 100644 --- a/sysdeps/unix/bsd/osf/alpha/sysdep.h +++ b/sysdeps/unix/bsd/osf/alpha/sysdep.h @@ -19,58 +19,11 @@ Cambridge, MA 02139, USA. */ /* OSF/1 does not precede the asm names of C symbols with a `_'. */ #define NO_UNDERSCORES -#include <sysdeps/unix/sysdep.h> +#include <sysdeps/unix/alpha/sysdep.h> -#ifdef ASSEMBLER +#ifdef ASSEMBLER #include <machine/pal.h> /* get PAL_callsys */ #include <regdef.h> -#ifdef __STDC__ -#define ENTRY(name) \ - .globl name; \ - .ent name,0; \ - name##:; \ - .frame sp,0,ra -#else -#define ENTRY(name) \ - .globl name; \ - .ent name,0; \ - name/**/:; \ - .frame sp,0,ra #endif - -#ifdef __STDC__ -#define PSEUDO(name, syscall_name, args) \ - ENTRY(name); \ - ldiq v0, SYS_##syscall_name; \ - .set noat; \ - call_pal PAL_callsys; \ - .set at; \ - beq a3, 10f; \ - br gp, 20f; \ -20:; \ - ldgp gp, 0(gp); \ - jmp zero, syscall_error; \ -10: -#else -#define PSEUDO(name, syscall_name, args) \ - ENTRY(name); \ - ldiq v0, SYS_/**/syscall_name; \ - .set noat; \ - call_pal PAL_callsys; \ - .set at; \ - beq a3, 10f; \ - br gp, 20f; \ -20:; \ - ldgp gp, 0(gp); \ - jmp zero, syscall_error; \ -10: -#endif - -#define ret ret zero,(ra),1 -#define r0 v0 -#define r1 a4 -#define MOVE(x,y) mov x, y - -#endif /* ASSEMBLER */ diff --git a/sysdeps/unix/bsd/pause.c b/sysdeps/unix/common/pause.c index b2fafb9..b2fafb9 100644 --- a/sysdeps/unix/bsd/pause.c +++ b/sysdeps/unix/common/pause.c diff --git a/sysdeps/unix/common/syscalls.list b/sysdeps/unix/common/syscalls.list index 654f73a..e859dd2 100644 --- a/sysdeps/unix/common/syscalls.list +++ b/sysdeps/unix/common/syscalls.list @@ -8,7 +8,7 @@ getpgid - getpgrp 1 __getpgid getpgid getrusage - getrusage 2 __getrusage getrusage gettimeofday - gettimeofday 2 __gettimeofday gettimeofday settimeofday - settimeofday 2 __settimeofday settimeofday -setpgid - setpgrp 2 __setpgid setpgid setpgrp +setpgid - setpgrp 2 __setpgid setpgid setregid - setregid 2 __setregid setregid setreuid - setreuid 2 __setreuid setreuid sigaction - sigaction 3 __sigaction sigaction diff --git a/sysdeps/unix/sysv/Makefile b/sysdeps/unix/sysv/Makefile index 6bd4240..2854237 100644 --- a/sysdeps/unix/sysv/Makefile +++ b/sysdeps/unix/sysv/Makefile @@ -35,11 +35,5 @@ $(objpfx)termio.h: $(..)sysdeps/unix/sysv/sysv_termio.h endif -ifeq ($(subdir),dirent) - -sysdep_routines := $(sysdep_routines) s_getdents - -endif - # In SYSV style archives the symbol table member has an empty name. ar-symtab-name = diff --git a/sysdeps/unix/sysv/irix4/syscalls.list b/sysdeps/unix/sysv/irix4/syscalls.list index 47e1c48..a57529e 100644 --- a/sysdeps/unix/sysv/irix4/syscalls.list +++ b/sysdeps/unix/sysv/irix4/syscalls.list @@ -2,7 +2,7 @@ getpgid - bsdgetpgrp 1 __getpgid getpgid msync - msync 3 msync -setpgid - bsdsetpgrp 2 __setpgid setpgid setpgrp +setpgid - bsdsetpgrp 2 __setpgid setpgid signal - signal 3 __raw_signal sysmp - sysmp 4 __sysmp syssgi - syssgi 2 __syssgi diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 79334e6..c33a190 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -15,7 +15,7 @@ sysdep_routines += fxstat lxstat xstat endif ifeq ($(subdir), misc) -sysdep_routines += xmknod mount umount s_ptrace +sysdep_routines += xmknod s_ptrace headers += sys/mount.h endif diff --git a/sysdeps/unix/sysv/linux/adjtime.c b/sysdeps/unix/sysv/linux/adjtime.c index c4b5002..44a0cbb 100644 --- a/sysdeps/unix/sysv/linux/adjtime.c +++ b/sysdeps/unix/sysv/linux/adjtime.c @@ -20,8 +20,8 @@ Boston, MA 02111-1307, USA. */ #include <sys/time.h> #include <sys/timex.h> -#define MAX_SEC (LONG_MAX / 1000000L - 2) -#define MIN_SEC (LONG_MIN / 1000000L + 2) +#define MAX_SEC (INT_MAX / 1000000L - 2) +#define MIN_SEC (INT_MIN / 1000000L + 2) #ifndef MOD_OFFSET #define modes mode diff --git a/sysdeps/unix/sysv/linux/alpha/Makefile b/sysdeps/unix/sysv/linux/alpha/Makefile new file mode 100644 index 0000000..9e12a0d --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/Makefile @@ -0,0 +1,7 @@ +ifeq ($(subdir), misc) +headers += alpha/regdef.h + +sysdep_routines := $(sysdep_routines) \ + ieee_get_fp_control ieee_set_fp_control fpu_control setfpucw \ + sethae ioperm osf_sigprocmask fstatfs statfs +endif diff --git a/sysdeps/unix/sysv/linux/alpha/alpha/regdef.h b/sysdeps/unix/sysv/linux/alpha/alpha/regdef.h new file mode 100644 index 0000000..142df9c --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/alpha/regdef.h @@ -0,0 +1,44 @@ +#ifndef __alpha_regdef_h__ +#define __alpha_regdef_h__ + +#define v0 $0 /* function return value */ + +#define t0 $1 /* temporary registers (caller-saved) */ +#define t1 $2 +#define t2 $3 +#define t3 $4 +#define t4 $5 +#define t5 $6 +#define t6 $7 +#define t7 $8 + +#define s0 $9 /* saved-registers (callee-saved registers) */ +#define s1 $10 +#define s2 $11 +#define s3 $12 +#define s4 $13 +#define s5 $14 +#define s6 $15 +#define fp s6 /* frame-pointer (s6 in frame-less procedures) */ + +#define a0 $16 /* argument registers (caller-saved) */ +#define a1 $17 +#define a2 $18 +#define a3 $19 +#define a4 $20 +#define a5 $21 + +#define t8 $22 /* more temps (caller-saved) */ +#define t9 $23 +#define t10 $24 +#define t11 $25 +#define ra $26 /* return address register */ +#define t12 $27 + +#define pv t12 /* procedure-variable register */ +#define AT $at /* assembler temporary */ +#define gp $29 /* global pointer */ +#define sp $30 /* stack pointer */ +#define zero $31 /* reads as zero, writes are noops */ + +#endif /* __alpha_regdef_h__ */ diff --git a/sysdeps/unix/sysv/linux/alpha/brk.S b/sysdeps/unix/sysv/linux/alpha/brk.S new file mode 100644 index 0000000..afd2e32 --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/brk.S @@ -0,0 +1,60 @@ +/* Copyright (C) 1993, 1995 Free Software Foundation, Inc. + Contributed by Brendan Kehoe (brendan@zen.org). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* __brk is a special syscall under Linux since it never returns an +error. Instead, the error condition is indicated by returning the old +break value (instead of the new, requested one). */ + +#include <sysdep.h> +#include <errnos.h> + +#ifndef HAVE_GNU_LD +#define _end end +#endif + + .extern _end,8 + + .data + + .globl __curbrk +__curbrk: + .quad _end + + .text +ENTRY(__brk) + ldgp gp, 0(t12) + .prologue 1 + + ldi v0, __NR_brk + call_pal PAL_callsys + subq a0, v0, t0 + bne t0, error + + /* Update __curbrk and return cleanly. */ + stl a0, __curbrk + mov zero, v0 + ret + + /* What a horrible way to die. */ +error: ldi v0, ENOMEM + lda pv, syscall_error + jmp zero,(pv) + + .end __brk + +weak_alias (__brk, brk) diff --git a/sysdeps/alpha/fabs.c b/sysdeps/unix/sysv/linux/alpha/fpu_control.c index 321df0d..20c032a 100644 --- a/sysdeps/alpha/fabs.c +++ b/sysdeps/unix/sysv/linux/alpha/fpu_control.c @@ -1,5 +1,5 @@ -/* Copyright (C) 1992 Free Software Foundation, Inc. -This file is part of the GNU C Library. +/* Copyright (C) 1993, 1995 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@azstarnet.com). 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 @@ -16,13 +16,6 @@ License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define __NO_MATH_INLINES +#include <fpu_control.h> -#include <math.h> - -__inline double -fabs (double __x) -{ - __asm ("cpys $f31, %1, %0" : "=f" (__x) : "f" (__x)); - return __x; -} +fpu_control_t __fpu_control = _FPU_DEFAULT; diff --git a/sysdeps/unix/sysv/linux/alpha/fpu_control.h b/sysdeps/unix/sysv/linux/alpha/fpu_control.h new file mode 100644 index 0000000..782f33e --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/fpu_control.h @@ -0,0 +1,105 @@ +/* Copyright (C) 1993 Olaf Flebbe +This file is part of the Linux C Library. + +The Linux 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 Linux 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. */ + +#ifndef _ALPHA_FPU_CONTROL_H +#define _ALPHA_FPU_CONTROL_H + +/* + * Since many programs seem to hardcode the values passed to __setfpucw() + * (rather than using the manifest constants) we emulate the x87 interface + * here (at least where this makes sense). + * + * 15-13 12 11-10 9-8 7-6 5 4 3 2 1 0 + * | reserved | IC | RC | PC | reserved | PM | UM | OM | ZM | DM | IM + * + * IM: Invalid operation mask + * DM: Denormalized operand mask + * ZM: Zero-divide mask + * OM: Overflow mask + * UM: Underflow mask + * PM: Precision (inexact result) mask + * + * Mask bit is 1 means no interrupt. + * + * PC: Precision control + * 11 - round to extended precision + * 10 - round to double precision + * 00 - round to single precision + * + * RC: Rounding control + * 00 - rounding to nearest + * 01 - rounding down (toward - infinity) + * 10 - rounding up (toward + infinity) + * 11 - rounding toward zero + * + * IC: Infinity control + * That is for 8087 and 80287 only. + * + * The hardware default is 0x037f. I choose 0x1372. + */ + +#include <features.h> + +/* masking of interrupts */ +#define _FPU_MASK_IM 0x01 +#define _FPU_MASK_DM 0x02 +#define _FPU_MASK_ZM 0x04 +#define _FPU_MASK_OM 0x08 +#define _FPU_MASK_UM 0x10 +#define _FPU_MASK_PM 0x20 + +/* precision control */ +#define _FPU_EXTENDED 0x300 /* RECOMMENDED */ +#define _FPU_DOUBLE 0x200 +#define _FPU_SINGLE 0x0 /* DO NOT USE */ + +/* + * rounding control---notice that on the Alpha this affects only + * instructions with the dynamic rounding mode qualifier (/d). + */ +#define _FPU_RC_NEAREST 0x000 /* RECOMMENDED */ +#define _FPU_RC_DOWN 0x400 +#define _FPU_RC_UP 0x800 +#define _FPU_RC_ZERO 0xC00 + +#define _FPU_RESERVED 0xF0C0 /* Reserved bits in cw */ + + +/* Now two recommended cw */ + +/* Linux default: + - extended precision + - rounding to positive infinity. There is no /p instruction + qualifier. By setting the dynamic rounding mode to +infinity, + one can use /d to get round to +infinity with no extra overhead + (so long as the default isn't changed, of course...) + - exceptions on overflow, zero divide and NaN */ +#define _FPU_DEFAULT 0x1f72 + +/* IEEE: same as above, but exceptions */ +#define _FPU_IEEE 0x1f7f + +/* Type of the control word. */ +typedef unsigned int fpu_control_t; + +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; + +__BEGIN_DECLS + +/* called by start.o. It can be used to manipulate fpu control word. */ +extern void __setfpucw __P ((unsigned short)); + +__END_DECLS + +#endif /* _ALPHA_FPU_CONTROL */ diff --git a/sysdeps/unix/sysv/linux/alpha/ieee_get_fp_control.S b/sysdeps/unix/sysv/linux/alpha/ieee_get_fp_control.S new file mode 100644 index 0000000..4c86e39 --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/ieee_get_fp_control.S @@ -0,0 +1,44 @@ +/* Copyright (C) 1993, 1995 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@azstarnet.com). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <sysdep.h> + +#define GSI_IEEE_FP_CONTROL 45 + + .text +ENTRY(__ieee_get_fp_control) + lda sp, -8(sp) + .prologue 1 + + mov sp, a1 + ldi a0, GSI_IEEE_FP_CONTROL + ldi v0, __NR_osf_getsysinfo + call_pal PAL_callsys + bne a3, error + + ldq v0, 0(sp) + lda sp, 8(sp) + ret + +error: lda sp, 8(sp) + lda pv, syscall_error + jmp zero,(pv) + + .end __ieee_get_fp_control + +weak_alias (__ieee_get_fp_control, ieee_get_fp_control) diff --git a/sysdeps/unix/sysv/linux/alpha/ieee_set_fp_control.S b/sysdeps/unix/sysv/linux/alpha/ieee_set_fp_control.S new file mode 100644 index 0000000..d10e9bc --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/ieee_set_fp_control.S @@ -0,0 +1,44 @@ +/* Copyright (C) 1993, 1995 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@azstarnet.com). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <sysdep.h> + +#define SSI_IEEE_FP_CONTROL 14 + + .text +ENTRY(__ieee_set_fp_control) + lda sp, -8(sp) + .prologue 1 + + stq a0, 0(sp) + mov sp, a1 + ldi a0, SSI_IEEE_FP_CONTROL + ldi v0, __NR_osf_setsysinfo + call_pal PAL_callsys + + lda sp, 8(sp) + + bne a3, error + ret + +error: lda pv, syscall_error + jmp zero,(pv) + + .end __ieee_set_fp_control + +weak_alias (__ieee_set_fp_control, ieee_set_fp_control) diff --git a/sysdeps/unix/sysv/linux/alpha/ioperm.c b/sysdeps/unix/sysv/linux/alpha/ioperm.c new file mode 100644 index 0000000..306c86b --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/ioperm.c @@ -0,0 +1,441 @@ +/* Copyright (C) 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. +Contributed by David Mosberger. + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* I/O access is restricted to ISA port space (ports 0..65535). +Modern devices hopefully are sane enough not to put any performance +critical registers in i/o space. + +On the first call to ioperm() or _sethae(), the entire (E)ISA port +space is mapped into the virtual address space at address io.base. +mprotect() calls are then used to enable/disable access to ports. Per +page, there are PAGE_SIZE>>IO_SHIFT I/O ports (e.g., 256 ports on a +Low Cost Alpha based system using 8KB pages). + +Keep in mind that this code should be able to run in a 32bit address +space. It is therefore unreasonable to expect mmap'ing the entire +sparse address space would work (e.g., the Low Cost Alpha chip has an +I/O address space that's 512MB large!). */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> + +#include <sys/types.h> +#include <sys/mman.h> + +#include <asm/io.h> +#include <asm/page.h> +#include <asm/system.h> + +#undef inb +#undef inw +#undef inl +#undef outb +#undef outw +#undef outl + +#define PATH_CPUINFO "/proc/cpuinfo" + +#define MAX_PORT 0x10000 +#define vuip volatile unsigned int * + +#define JENSEN_IO_BASE (IDENT_ADDR + 0x0300000000UL) +#define APECS_IO_BASE (IDENT_ADDR + 0x01c0000000UL) +#define ALCOR_IO_BASE (IDENT_ADDR + 0x8580000000UL) + +enum { + IOSYS_JENSEN = 0, IOSYS_APECS = 1, IOSYS_ALCOR = 2 +} iosys_t; + +struct ioswtch { + void (*sethae)(unsigned long addr); + void (*outb)(unsigned char b, unsigned long port); + void (*outw)(unsigned short b, unsigned long port); + void (*outl)(unsigned int b, unsigned long port); + unsigned int (*inb)(unsigned long port); + unsigned int (*inw)(unsigned long port); + unsigned int (*inl)(unsigned long port); +}; + +static struct platform { + const char *name; + int io_sys; +} platform[] = { + {"Alcor", IOSYS_ALCOR}, + {"Avanti", IOSYS_APECS}, + {"Cabriolet", IOSYS_APECS}, + {"EB64+", IOSYS_APECS}, + {"EB66", IOSYS_APECS}, + {"EB66P", IOSYS_APECS}, + {"Jensen", IOSYS_JENSEN}, + {"Mustang", IOSYS_APECS}, + {"Noname", IOSYS_APECS}, +}; + + +static struct { + struct hae hae; + unsigned long base; + struct ioswtch * swp; + int sys; +} io; + + +static inline unsigned long +port_to_cpu_addr (unsigned long port, int iosys, int size) +{ + if (iosys == IOSYS_JENSEN) { + return (port << 7) + ((size - 1) << 4) + io.base; + } else { + return (port << 5) + ((size - 1) << 3) + io.base; + } +} + + +static inline void +inline_sethae (unsigned long addr, int iosys) +{ + if (iosys == IOSYS_JENSEN) { + /* hae on the Jensen is bits 31:25 shifted right */ + addr >>= 25; + if (addr != io.hae.cache) { + __sethae (addr); + io.hae.cache = addr; + } + } else { + unsigned long msb; + + /* no need to set hae if msb is 0: */ + msb = addr & 0xf8000000; + if (msb && msb != io.hae.cache) { + __sethae (msb); + io.hae.cache = msb; + } + } +} + + +static inline void +inline_outb (unsigned char b, unsigned long port, int iosys) +{ + unsigned int w; + unsigned long addr = port_to_cpu_addr (port, iosys, 1); + + inline_sethae (0, iosys); + asm ("insbl %2,%1,%0" : "r=" (w) : "ri" (port & 0x3), "r" (b)); + *(vuip)addr = w; + mb (); +} + + +static inline void +inline_outw (unsigned short b, unsigned long port, int iosys) +{ + unsigned int w; + unsigned long addr = port_to_cpu_addr (port, iosys, 2); + + inline_sethae (0, iosys); + asm ("inswl %2,%1,%0" : "r=" (w) : "ri" (port & 0x3), "r" (b)); + *(vuip)addr = w; + mb (); +} + + +static inline void +inline_outl (unsigned int b, unsigned long port, int iosys) +{ + unsigned long addr = port_to_cpu_addr (port, iosys, 4); + + if (port >= MAX_PORT) + return; + + inline_sethae (0, iosys); + *(vuip)addr = b; + mb (); +} + + +static inline unsigned int +inline_inb (unsigned long port, int iosys) +{ + unsigned long result, addr = port_to_cpu_addr (port, iosys, 1); + + inline_sethae (0, iosys); + result = *(vuip) addr; + result >>= (port & 3) * 8; + return 0xffUL & result; +} + + +static inline unsigned int +inline_inw (unsigned long port, int iosys) +{ + unsigned long result, addr = port_to_cpu_addr (port, iosys, 2); + + inline_sethae (0, iosys); + result = *(vuip) addr; + result >>= (port & 3) * 8; + return 0xffffUL & result; +} + + +static inline unsigned int +inline_inl (unsigned long port, int iosys) +{ + unsigned long addr = port_to_cpu_addr (port, iosys, 4); + + inline_sethae (0, iosys); + return *(vuip) addr; +} + + +#define DCL_SETHAE(name, iosys) \ +static void \ +name##_sethae (unsigned long addr) \ +{ \ + inline_sethae (addr, IOSYS_##iosys); \ +} + +#define DCL_OUT(name, func, type, iosys) \ +static void \ +name##_##func (unsigned type b, unsigned long addr) \ +{ \ + inline_##func (b, addr, IOSYS_##iosys); \ +} + + +#define DCL_IN(name, func, iosys) \ +static unsigned int \ +name##_##func (unsigned long addr) \ +{ \ + return inline_##func (addr, IOSYS_##iosys); \ +} + + +DCL_SETHAE(jensen, JENSEN) +DCL_OUT(jensen, outb, char, JENSEN) +DCL_OUT(jensen, outw, short, JENSEN) +DCL_OUT(jensen, outl, int, JENSEN) +DCL_IN(jensen, inb, JENSEN) +DCL_IN(jensen, inw, JENSEN) +DCL_IN(jensen, inl, JENSEN) + +/* The APECS functions are also used for ALCOR since they are + identical. */ + +DCL_SETHAE(apecs, APECS) +DCL_OUT(apecs, outb, char, APECS) +DCL_OUT(apecs, outw, short, APECS) +DCL_OUT(apecs, outl, int, APECS) +DCL_IN(apecs, inb, APECS) +DCL_IN(apecs, inw, APECS) +DCL_IN(apecs, inl, APECS) + +struct ioswtch ioswtch[] = { + { + jensen_sethae, + jensen_outb, jensen_outw, jensen_outl, + jensen_inb, jensen_inw, jensen_inl + }, + { + apecs_sethae, + apecs_outb, apecs_outw, apecs_outl, + apecs_inb, apecs_inw, apecs_inl + } +}; + + +static int +init_iosys (void) +{ + char name[256], value[256]; + FILE * fp; + int i; + + fp = fopen (PATH_CPUINFO, "r"); + if (!fp) + return -1; + + while (fscanf (fp, "%256[^:]: %256[^\n]\n", name, value) == 2) { + if (strncmp (name, "system type", 11) == 0) { + for (i = 0; i < sizeof (platform) / sizeof (platform[0]); ++i) { + if (strcmp (platform[i].name, value) == 0) { + fclose (fp); + io.sys = platform[i].io_sys; + if (io.sys == IOSYS_JENSEN) + io.swp = &ioswtch[0]; + else + io.swp = &ioswtch[1]; + return 0; + } + } + } + } + fclose (fp); + errno = ENODEV; + return -1; +} + + +int +_ioperm (unsigned long from, unsigned long num, int turn_on) +{ + unsigned long addr, len; + int prot; + + if (!io.swp && init_iosys () < 0) + return -1; + + /* this test isn't as silly as it may look like; consider overflows! */ + if (from >= MAX_PORT || from + num > MAX_PORT) { + errno = EINVAL; + return -1; + } + + if (turn_on) { + if (!io.base) { + unsigned long base; + int fd; + + io.hae.reg = 0; /* not used in user-level */ + io.hae.cache = 0; + __sethae (io.hae.cache); /* synchronize with hw */ + + fd = open ("/dev/mem", O_RDWR); + if (fd < 0) + return fd; + + switch (io.sys) { + case IOSYS_JENSEN: base = JENSEN_IO_BASE; break; + case IOSYS_APECS: base = APECS_IO_BASE; break; + case IOSYS_ALCOR: base = ALCOR_IO_BASE; break; + default: + errno = ENODEV; + return -1; + } + addr = port_to_cpu_addr (from, io.sys, 1); + addr &= PAGE_MASK; + len = port_to_cpu_addr (MAX_PORT, io.sys, 1) - addr; + io.base = + (unsigned long) __mmap (0, len, PROT_NONE, MAP_SHARED, fd, base); + close (fd); + if ((long) io.base == -1) + return -1; + } + prot = PROT_READ | PROT_WRITE; + } else { + if (!io.base) + return 0; /* never was turned on... */ + + /* turnoff access to relevant pages: */ + prot = PROT_NONE; + } + addr = port_to_cpu_addr (from, io.sys, 1); + addr &= PAGE_MASK; + len = port_to_cpu_addr (from + num, io.sys, 1) - addr; + return mprotect ((void *) addr, len, prot); +} + + +int +_iopl (unsigned int level) +{ + if (level > 3) { + errno = EINVAL; + return -1; + } + if (level) { + return _ioperm (0, MAX_PORT, 1); + } + return 0; +} + + +void +_sethae (unsigned long addr) +{ + if (!io.swp && init_iosys () < 0) + return; + + io.swp->sethae (addr); +} + + +void +_outb (unsigned char b, unsigned long port) +{ + if (port >= MAX_PORT) + return; + + io.swp->outb (b, port); +} + + +void +_outw (unsigned short b, unsigned long port) +{ + if (port >= MAX_PORT) + return; + + io.swp->outw (b, port); +} + + +void +_outl (unsigned int b, unsigned long port) +{ + if (port >= MAX_PORT) + return; + + io.swp->outl (b, port); +} + + +unsigned int +_inb (unsigned long port) +{ + return io.swp->inb (port); +} + + +unsigned int +_inw (unsigned long port) +{ + return io.swp->inw (port); +} + + +unsigned int +_inl (unsigned long port) +{ + return io.swp->inl (port); +} + + +weak_alias (_sethae, sethae); +weak_alias (_ioperm, ioperm); +weak_alias (_iopl, iopl); +weak_alias (_inb, inb); +weak_alias (_inw, inw); +weak_alias (_inl, inl); +weak_alias (_outb, outb); +weak_alias (_outw, outw); +weak_alias (_outl, outl); diff --git a/sysdeps/unix/sysv/linux/alpha/pipe.S b/sysdeps/unix/sysv/linux/alpha/pipe.S new file mode 100644 index 0000000..f613b08 --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/pipe.S @@ -0,0 +1,43 @@ +/* Copyright (C) 1993, 1995 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@cs.arizona.edu). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* __pipe is a special syscall since it returns two values. */ + +#include <sysdep.h> + + .text +ENTRY(__pipe) + .prologue 0 + + ldi v0, __NR_pipe + call_pal PAL_callsys + bne a3, error + + stl r0, 0(a0) + stl r1, 4(a0) + mov zero, v0 + ret + +error: br gp, 1f +1: ldgp gp, 0(gp) + lda pv, syscall_error + jmp zero, (pv) + + .end __pipe + +weak_alias (__pipe, pipe) diff --git a/sysdeps/unix/sysv/linux/alpha/profil-counter.h b/sysdeps/unix/sysv/linux/alpha/profil-counter.h new file mode 100644 index 0000000..6ab5a88 --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/profil-counter.h @@ -0,0 +1,28 @@ +/* Low-level statistical profiling support function. Mostly POSIX.1 version. +Copyright (C) 1996 Free Software Foundation, Inc. +Contributed by David Mosberger <davidm@azstarnet.com> +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <asm/sigcontext.h> + +void +profil_counter (int signal, long a1, long a2, long a3, long a4, long a5, + struct sigcontext_struct sc) +{ + profil_count((void *) sc.sc_pc); +} diff --git a/sysdeps/unix/sysv/linux/alpha/setfpucw.c b/sysdeps/unix/sysv/linux/alpha/setfpucw.c new file mode 100644 index 0000000..43e8536 --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/setfpucw.c @@ -0,0 +1,65 @@ +#include <fpu_control.h> + +#include <asm/fpu.h> + +extern void __ieee_set_fp_control (unsigned long); +extern unsigned long __ieee_get_fp_control (void); + + +static inline unsigned long +rdfpcr (void) +{ + unsigned long fpcr; + + asm ("trapb; mf_fpcr $f0; trapb; stt $f0,%0" : "m="(fpcr)); + return fpcr; +} + + +static inline void +wrfpcr (unsigned long fpcr) +{ + asm volatile ("ldt $f0,%0; trapb; mt_fpcr $f0; trapb" :: "m"(fpcr)); +} + + +void +__setfpucw (unsigned short fpu_control) +{ + unsigned long fpcr = 0, fpcw = 0; + + if (!fpu_control) + fpu_control = _FPU_DEFAULT; + + /* first, set dynamic rounding mode: */ + + fpcr = rdfpcr(); + fpcr &= ~FPCR_DYN_MASK; + switch (fpu_control & 0xc00) { + case _FPU_RC_NEAREST: fpcr |= FPCR_DYN_NORMAL; break; + case _FPU_RC_DOWN: fpcr |= FPCR_DYN_MINUS; break; + case _FPU_RC_UP: fpcr |= FPCR_DYN_PLUS; break; + case _FPU_RC_ZERO: fpcr |= FPCR_DYN_CHOPPED; break; + } + wrfpcr(fpcr); + + /* now tell kernel about traps that we like to hear about: */ + + fpcw = __ieee_get_fp_control(); + fpcw &= ~IEEE_TRAP_ENABLE_MASK; + + if (!(fpu_control & _FPU_MASK_IM)) + fpcw |= IEEE_TRAP_ENABLE_INV; + if (!(fpu_control & _FPU_MASK_DM)) + fpcw |= IEEE_TRAP_ENABLE_UNF; + if (!(fpu_control & _FPU_MASK_ZM)) + fpcw |= IEEE_TRAP_ENABLE_DZE; + if (!(fpu_control & _FPU_MASK_OM)) + fpcw |= IEEE_TRAP_ENABLE_OVF; + if (!(fpu_control & _FPU_MASK_PM)) + fpcw |= IEEE_TRAP_ENABLE_INE; + + __ieee_set_fp_control(fpcw); + + __fpu_control = fpu_control; /* update global copy */ +} diff --git a/sysdeps/unix/sysv/linux/alpha/sigprocmask.c b/sysdeps/unix/sysv/linux/alpha/sigprocmask.c new file mode 100644 index 0000000..a1d5636 --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/sigprocmask.c @@ -0,0 +1,49 @@ +/* Copyright (C) 1993, 1995 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@azstarnet.com). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <sysdep.h> +#include <signal.h> + +extern unsigned long __osf_sigprocmask (int how, unsigned long newmask); + +int +__sigprocmask (int how, const sigset_t *set, sigset_t *oset) +{ + sigset_t setval; + long result; + + if (set) { + setval = *set; + } else { + sigemptyset(&setval); + how = SIG_BLOCK; /* ensure blocked mask doesn't get changed */ + } + result = __osf_sigprocmask(how, setval); + if (result == -1) { + /* if there are ever more than 63 signals, we need to recode this + in assembler since we wouldn't be able to distinguish a mask of + all 1s from -1, but for now, we're doing just fine... */ + return result; + } + if (oset) { + *oset = result; + } + return 0; +} + +weak_alias (__sigprocmask, sigprocmask); diff --git a/sysdeps/unix/sysv/linux/alpha/sigsuspend.S b/sysdeps/unix/sysv/linux/alpha/sigsuspend.S new file mode 100644 index 0000000..29cba8d --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/sigsuspend.S @@ -0,0 +1,39 @@ +/* Copyright (C) 1993, 1995 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@cs.arizona.edu). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* sigsuspend is a special syscall since it needs to dereference the +sigset. */ + +#include <sysdep.h> + + .text +ENTRY(sigsuspend) + .prologue 0 + + ldq a0, 0(a0) + ldi v0, __NR_sigsuspend + call_pal PAL_callsys + bne a3, error + ret + +error: br gp, 1f +1: ldgp gp, 0(gp) + lda pv, syscall_error + jmp zero, (pv) + + .end sigsuspend diff --git a/sysdeps/unix/sysv/linux/alpha/speed.c b/sysdeps/unix/sysv/linux/alpha/speed.c new file mode 100644 index 0000000..b61cfbb --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/speed.c @@ -0,0 +1,102 @@ +/* `struct termios' speed frobnication functions. Linux version. +Copyright (C) 1991, 1992, 1993, 1995 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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <stddef.h> +#include <errno.h> +#include <termios.h> + +static const speed_t speeds[] = + { + 0, + 50, + 75, + 110, + 134, + 150, + 200, + 300, + 600, + 1200, + 1800, + 2400, + 4800, + 9600, + 19200, + 38400, + 57600, + 115200, + 230400, + }; + + +/* Return the output baud rate stored in *TERMIOS_P. */ +speed_t +cfgetospeed (termios_p) + const struct termios *termios_p; +{ + speed_t retval = termios_p->c_cflag & (CBAUD | CBAUDEX); + + if (retval & CBAUDEX) + { + retval &= ~CBAUDEX; + retval |= CBAUD + 1; + } + + return retval; +} + +/* Return the input baud rate stored in *TERMIOS_P. + For Linux there is no difference between input and output speed. */ +strong_alias (cfgetospeed, cfgetispeed); + +/* Set the output baud rate stored in *TERMIOS_P to SPEED. */ +int +cfsetospeed (termios_p, speed) + struct termios *termios_p; + speed_t speed; +{ + register unsigned int i; + + if (termios_p == NULL) + { + errno = EINVAL; + return -1; + } + + /* This allows either B1200 or 1200 to work. XXX + Do we really want to try to support this, given that + fetching the speed must return one or the other? */ + + for (i = 0; i < sizeof (speeds) / sizeof (speeds[0]); ++i) + if (i == speed || speeds[i] == speed) + { + termios_p->c_cflag &= ~(CBAUD | CBAUDEX); + termios_p->c_cflag |= (i & CBAUD); + if (i & ~CBAUD) + termios_p->c_cflag |= CBAUDEX; + return 0; + } + + errno = EINVAL; + return -1; +} + +/* Set the input baud rate stored in *TERMIOS_P to SPEED. + For Linux there is no difference between input and output speed. */ +strong_alias (cfsetospeed, cfsetispeed); diff --git a/sysdeps/unix/sysv/linux/alpha/start.S b/sysdeps/unix/sysv/linux/alpha/start.S new file mode 100644 index 0000000..d1966a8 --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/start.S @@ -0,0 +1,93 @@ +/* Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc. + Contributed by Brendan Kehoe (brendan@zen.org). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <sysdep.h> + +.comm errno, 4 + + .text +ENTRY(__start) + lda sp, -16(sp) + stq zero, 8(sp) /* terminate frame chain */ + + br t0, 1f +1: ldgp gp, 0(t0) + + mov zero, a0 /* establish __fpu_control w/kernel */ + jsr ra, __setfpucw + ldgp gp, 0(ra) + + /* clear out errno. */ + lda t0, errno + stl zero, 0(t0) + + ldl a0, 16(sp) /* get argc */ + lda a1, 24(sp) /* get argv */ + + /* initialize environ: */ + lda t0, environ + s8addq a0, a1, a2 + addq a2, 0x8, a2 + stq a2, 0(t0) + +#ifndef HAVE_INITFINI + mov a0, s0 + mov a1, s1 + mov a2, s2 + + jsr ra, __libc_init + ldgp gp, 0(ra) + + mov s0, a0 + mov s1, a1 + mov s2, a2 + + /* initialize constructors: */ + jsr ra, __main + ldgp gp, 0(ra) + + mov s0, a0 + mov s1, a1 + mov s2, a2 +#endif + + jsr ra, main + ldgp gp, 0(ra) + + mov v0, a0 + + lda pv, exit + jsr ra, (pv), 1 + ldgp gp, 0(ra) + + /* in case exit returns: */ + +1: ldi v0, __NR_exit + call_pal PAL_callsys + br 1b + + .end __start + + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + +weak_alias(__data_start, data_start) diff --git a/sysdeps/unix/sysv/linux/alpha/syscall.S b/sysdeps/unix/sysv/linux/alpha/syscall.S new file mode 100644 index 0000000..54a8484 --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/syscall.S @@ -0,0 +1,61 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@azstarnet.com). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <sysdep.h> + +/* + * This is for COMPATIBILITY with Linux/x86 only. Linux/Alpha system + * calls return an error indication in a3. This allows to return + * arbitrary 64bit values in v0 (because negative values are not + * mistaken as error numbers). However, C allows to return only one + * value so the interface below folds the error indication passed in + * a3 back into v0: it sets v0 to -errno if an error occurs. Thus, + * no negative 64bit numbers can be returned. To avoid this problem, + * use assembly stubs wherever possible/convenient. + * + * Usage: + * + * long syscall(syscall_number, arg1, arg2, arg3, arg4, arg5) + * + * syscall_number = the index of the system call we're invoking + * arg1-arg5 = up to 5 integer arguments to the system call + * + * We need to do some arg shifting: the kernel expects the + * syscall number in v0 and the first five args in a0-a4. + * + */ + + +1: br gp,2f +2: ldgp gp,0(gp) + jmp zero,syscall_error + + +ENTRY (__syscall) + bis a0,a0,v0 # Syscall number -> v0 + bis a1,a1,a0 # arg1-arg5 -> a0-a4 + bis a2,a2,a1 + bis a3,a3,a2 + bis a4,a4,a3 + bis a5,a5,a4 + + call_pal PAL_callsys # Invoke system call + bne a3,1b + ret + +weak_alias(__syscall, syscall) diff --git a/sysdeps/unix/sysv/linux/alpha/syscalls.list b/sysdeps/unix/sysv/linux/alpha/syscalls.list new file mode 100644 index 0000000..a842908 --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/syscalls.list @@ -0,0 +1,45 @@ +# File name Caller Syscall name # args Strong name Weak names + +# used to implement inb()/outb() etc. +sethae - sethae 1 __sethae + +msgctl - msgctl 3 __msgctl msgctl +msgget - msgget 2 __msgget msgget +msgrcv - msgrcv 5 __msgrcv msgrcv +msgsnd - msgsnd 4 __msgsnd msgsnd +shmat - osf_shmat 3 __shmat shmat +shmctl - shmctl 3 __shmctl shmctl +shmdt - shmdt 1 __shmdt shmdt +shmget - shmget 3 __shmget shmget +semop - semop 3 __semop semop +semget - semget 3 __semget semget +semctl - semctl 4 __semctl semctl + +osf_sigprocmask - osf_sigprocmask 2 __osf_sigprocmask + +getdents - getdents 3 __getdirentries getdirentries +getpeername - getpeername 3 __getpeername getpeername +getpriority - getpriority 2 __getpriority getpriority +mmap - mmap 6 __mmap mmap + +# these are actually common with the x86: +fstatfs - fstatfs 2 __fstatfs fstatfs +statfs - statfs 2 __statfs statfs + +# override select.S in parent directory: +select - select 5 __select select +accept - accept 3 __accept accept +bind - bind 3 __bind bind +connect - connect 3 __connect connect +getpeername - getpeername 3 __getpeername getpeername +getsockname - getsockname 3 __getsockname getsockname +listen - listen 2 __listen listen +recv - recv 4 __recv recv +recvfrom - recvfrom 6 __recvfrom recvfrom +recvmsg - recvmsg 3 __recvmsg recvmsg +send - send 4 __send send +sendmsg - sendmsg 3 __sendmsg sendmsg +sendto - sendto 6 __sendto sendto +setsockopt - setsockopt 5 __setsockopt setsockopt +shutdown - shutdown 2 __shutdown shutdown +socketpair - socketpair 4 __socketpair socketpair diff --git a/sysdeps/unix/sysv/linux/alpha/sysdep.S b/sysdeps/unix/sysv/linux/alpha/sysdep.S new file mode 100644 index 0000000..74b153e --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/sysdep.S @@ -0,0 +1,33 @@ +/* Copyright (C) 1993 Free Software Foundation, Inc. + Contributed by Brendan Kehoe (brendan@zen.org). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <sysdep.h> +#define _ERRNO_H +#include <errnos.h> + +ENTRY(syscall_error) + /* Store return value in errno... */ + ldgp gp, 0(t12) + lda t0, errno + stl v0, 0(t0) + + /* And just kick back a -1. */ + ldi v0, -1 + ret + + .end syscall_error diff --git a/sysdeps/unix/sysv/linux/alpha/sysdep.h b/sysdeps/unix/sysv/linux/alpha/sysdep.h new file mode 100644 index 0000000..febfa3a --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/sysdep.h @@ -0,0 +1,60 @@ +/* Copyright (C) 1992, 1993, 1995, 1996 Free Software Foundation, Inc. +This file is part of the GNU C Library. +Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>, August 1995. + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* In the Linux ELF and ECOFF worlds, C symbols are asm symbols. */ +#define NO_UNDERSCORES + +#ifdef ASSEMBLER + +#include <asm/pal.h> +#include <alpha/regdef.h> + +#endif + +/* There is some commonality. */ +#include <sysdeps/unix/alpha/sysdep.h> + +/* For Linux we can use the system call table in the header file + /usr/include/asm/unistd.h + of the kernel. But these symbols do not follow the SYS_* syntax + so we have to redefine the `SYS_ify' macro here. */ +#undef SYS_ify +#ifdef __STDC__ +# define SYS_ify(syscall_name) __NR_##syscall_name +#else +# define SYS_ify(syscall_name) __NR_/**/syscall_name +#endif + +/* + * Define some aliases for syscalls that return two values (in r0 and r1): + */ +#define __NR_getpid __NR_getxpid +#define __NR_getppid __NR_getxpid +#define __NR_getuid __NR_getxuid +#define __NR_geteuid __NR_getxuid +#define __NR_getgid __NR_getxgid +#define __NR_getegid __NR_getxgid + +/* + * Some syscalls no Linux program should know about: + */ +#define __NR_osf_sigprocmask 48 +#define __NR_osf_shmat 209 +#define __NR_osf_getsysinfo 256 +#define __NR_osf_setsysinfo 257 diff --git a/sysdeps/unix/sysv/linux/sys/mman.h b/sysdeps/unix/sysv/linux/sys/mman.h index 007dbfd..3336154 100644 --- a/sysdeps/unix/sysv/linux/sys/mman.h +++ b/sysdeps/unix/sysv/linux/sys/mman.h @@ -66,7 +66,7 @@ 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 msync __P ((__caddr_t __addr, size_t __len, int flags)); /* Advise the system about particular usage patterns the program follows for the region starting at ADDR and extending LEN bytes. */ diff --git a/sysdeps/unix/sysv/sysv4/setpgid.c b/sysdeps/unix/sysv/sysv4/setpgid.c index b9e06dc..743b8ca 100644 --- a/sysdeps/unix/sysv/sysv4/setpgid.c +++ b/sysdeps/unix/sysv/sysv4/setpgid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1996 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,4 +32,3 @@ DEFUN(__setpgid, (pid, pgid), int pid AND int pgid) } weak_alias (__setpgid, setpgid) -weak_alias (__setpgid, setpgrp) diff --git a/time/offtime.c b/time/offtime.c index 4b8ddb1..4e062df 100644 --- a/time/offtime.c +++ b/time/offtime.c @@ -19,7 +19,6 @@ Cambridge, MA 02139, USA. */ #include <ansidecl.h> #include <time.h> - /* Defined in mktime.c. */ extern CONST unsigned short int __mon_yday[2][13]; @@ -33,8 +32,7 @@ void DEFUN(__offtime, (t, offset, tp), CONST time_t *t AND long int offset AND struct tm *tp) { - register long int days, rem; - register int y; + register long int days, rem, y; register CONST unsigned short int *ip; days = *t / SECS_PER_DAY; @@ -59,15 +57,19 @@ DEFUN(__offtime, (t, offset, tp), if (tp->tm_wday < 0) tp->tm_wday += 7; y = 1970; - while (days >= (rem = __isleap(y) ? 366 : 365)) - { - ++y; - days -= rem; - } - while (days < 0) + +# define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400) + + while (days < 0 || days >= (__isleap (y) ? 366 : 365)) { - --y; - days += __isleap(y) ? 366 : 365; + /* Guess a corrected year, assuming 365 days per year. */ + int yg = y + days / 365 - (days % 365 < 0); + + /* Adjust DAYS and Y to match the guessed year. */ + days -= ((yg - y) * 365 + + LEAPS_THRU_END_OF (yg - 1) + - LEAPS_THRU_END_OF (y - 1)); + y = yg; } tp->tm_year = y - 1900; tp->tm_yday = days; diff --git a/time/strftime.c b/time/strftime.c index 73f1ac2..02f72b3 100644 --- a/time/strftime.c +++ b/time/strftime.c @@ -149,7 +149,7 @@ strftime (s, maxsize, format, tp) const char *const a_month = _NL_CURRENT (LC_TIME, ABMON_1 + tp->tm_mon); const char *const f_month = _NL_CURRENT (LC_TIME, MON_1 + tp->tm_mon); const char *const ampm = _NL_CURRENT (LC_TIME, - hour12 > 12 ? PM_STR : AM_STR); + hour12 > 11 ? PM_STR : AM_STR); size_t aw_len = strlen(a_wkday); size_t am_len = strlen(a_month); size_t ap_len = strlen (ampm); @@ -158,7 +158,7 @@ strftime (s, maxsize, format, tp) const char *const f_month = month_name[tp->tm_mon]; const char *const a_wkday = f_wkday; const char *const a_month = f_month; - const char *const ampm = "AMPM" + 2 * (hour12 > 12); + const char *const ampm = "AMPM" + 2 * (hour12 > 11); size_t aw_len = 3; size_t am_len = 3; size_t ap_len = 2; diff --git a/time/tzfile.c b/time/tzfile.c index cc99802..e78a05e 100644 --- a/time/tzfile.c +++ b/time/tzfile.c @@ -60,19 +60,20 @@ static struct leap *leaps = NULL; static inline int decode (const void *ptr) { -#if BYTE_ORDER == BIG_ENDIAN - return *(const int *) ptr; -#else - const unsigned char *p = ptr; - int result = 0; - - result = (result << 8) | *p++; - result = (result << 8) | *p++; - result = (result << 8) | *p++; - result = (result << 8) | *p++; - - return result; -#endif + if ((BYTE_ORDER == BIG_ENDIAN) && sizeof (int) == 4) + return *(const int *) ptr; + else + { + const unsigned char *p = ptr; + int result = *p & (1 << (CHAR_BIT - 1)) ? ~0 : 0; + + result = (result << 8) | *p++; + result = (result << 8) | *p++; + result = (result << 8) | *p++; + result = (result << 8) | *p++; + + return result; + } } void @@ -158,6 +159,9 @@ DEFUN(__tzfile_read, (file), CONST char *file) goto lose; } + if (sizeof (time_t) < 4) + abort (); + if (fread((PTR) transitions, 4, num_transitions, f) != num_transitions || fread((PTR) type_idxs, 1, num_transitions, f) != num_transitions) goto lose; @@ -169,7 +173,7 @@ DEFUN(__tzfile_read, (file), CONST char *file) the array so as not to clobber the next element to be processed when sizeof (time_t) > 4. */ i = num_transitions; - while (num_transitions-- > 0) + while (i-- > 0) transitions[i] = decode ((char *) transitions + i*4); } |