From: miod Date: Sun, 13 Aug 2023 06:55:37 +0000 (+0000) Subject: Make sure modf() returns correct values for infinities. While there, drop X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=f78f1c7c95a263d9fb01c2ea8977757437feec00;p=openbsd Make sure modf() returns correct values for infinities. While there, drop the few assembler versions as has been done on other *BSD systems; this function (modf) turns out to be non-trivial enough, having only one known-to-work version is preferrable. Reported by Willemijn Coene. --- diff --git a/lib/libc/arch/amd64/gen/Makefile.inc b/lib/libc/arch/amd64/gen/Makefile.inc index 7dcd8bd9f79..c9f2c976e77 100644 --- a/lib/libc/arch/amd64/gen/Makefile.inc +++ b/lib/libc/arch/amd64/gen/Makefile.inc @@ -1,6 +1,6 @@ -# $OpenBSD: Makefile.inc,v 1.13 2020/07/06 13:33:05 pirofti Exp $ +# $OpenBSD: Makefile.inc,v 1.14 2023/08/13 06:55:37 miod Exp $ -SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.S nan.c setjmp.S \ +SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c setjmp.S \ sigsetjmp.S SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c \ usertc.c diff --git a/lib/libc/arch/amd64/gen/modf.S b/lib/libc/arch/amd64/gen/modf.S deleted file mode 100644 index 394e682b086..00000000000 --- a/lib/libc/arch/amd64/gen/modf.S +++ /dev/null @@ -1,94 +0,0 @@ -/* $OpenBSD: modf.S,v 1.6 2018/07/03 23:14:05 mortimer Exp $ */ -/* $NetBSD: modf.S,v 1.1 2001/06/19 00:25:03 fvdl Exp $ */ - -/*- - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Sean Eric Fagan. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)modf.s 5.5 (Berkeley) 3/18/91 - */ - -#include - -/* - * modf(value, iptr): return fractional part of value, and stores the - * integral part into iptr (a pointer to double). - * - * Written by Sean Eric Fagan (sef@kithrup.COM) - * Sun Mar 11 20:27:30 PST 1990 - */ - -/* With CHOP mode on, frndint behaves as TRUNC does. Useful. */ -ENTRY(modf) - RETGUARD_SETUP(modf, r11) - - /* - * Set chop mode. - */ - fnstcw -12(%rsp) - movw -12(%rsp),%dx - orw $3072,%dx - movw %dx,-16(%rsp) - fldcw -16(%rsp) - - /* - * Get integral part. - */ - movsd %xmm0,-24(%rsp) - fldl -24(%rsp) - frndint - fstpl -8(%rsp) - - /* - * Restore control word. - */ - fldcw -12(%rsp) - - /* - * Store integral part. - */ - movsd -8(%rsp),%xmm0 - movsd %xmm0,(%rdi) - - /* - * Get fractional part and return it. - */ - fldl -24(%rsp) - fsubl -8(%rsp) - fstpl -8(%rsp) - movsd -8(%rsp),%xmm0 - - RETGUARD_CHECK(modf, r11) - ret -END(modf) diff --git a/lib/libc/arch/i386/gen/Makefile.inc b/lib/libc/arch/i386/gen/Makefile.inc index 30b5f8726c5..45d0108a148 100644 --- a/lib/libc/arch/i386/gen/Makefile.inc +++ b/lib/libc/arch/i386/gen/Makefile.inc @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile.inc,v 1.15 2020/07/06 13:33:05 pirofti Exp $ +# $OpenBSD: Makefile.inc,v 1.16 2023/08/13 06:55:37 miod Exp $ SRCS+= _setjmp.S fabs.S infinity.c ldexp.c usertc.c \ - modf.S nan.c setjmp.S sigsetjmp.S + modf.c nan.c setjmp.S sigsetjmp.S SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S fpsetmask.S \ fpsetround.S fpsetsticky.S diff --git a/lib/libc/arch/i386/gen/modf.S b/lib/libc/arch/i386/gen/modf.S deleted file mode 100644 index 4b623611a60..00000000000 --- a/lib/libc/arch/i386/gen/modf.S +++ /dev/null @@ -1,68 +0,0 @@ -/* $OpenBSD: modf.S,v 1.7 2011/07/08 22:28:33 martynas Exp $ */ -/*- - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Sean Eric Fagan. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include - -/* - * modf(value, iptr): return fractional part of value, and stores the - * integral part into iptr (a pointer to double). - * - * Written by Sean Eric Fagan (sef@kithrup.COM) - * Sun Mar 11 20:27:30 PST 1990 - */ - -/* With CHOP mode on, frndint behaves as TRUNC does. Useful. */ -ENTRY(modf) - pushl %ebp - movl %esp,%ebp - subl $16,%esp - fnstcw -12(%ebp) - movw -12(%ebp),%dx - orw $3072,%dx - movw %dx,-16(%ebp) - fldcw -16(%ebp) - fldl 8(%ebp) - frndint - fstpl -8(%ebp) - fldcw -12(%ebp) - movl 16(%ebp),%eax - movl -8(%ebp),%edx - movl -4(%ebp),%ecx - movl %edx,(%eax) - movl %ecx,4(%eax) - fldl 8(%ebp) - fsubl -8(%ebp) - jmp L1 -L1: - leave - ret diff --git a/lib/libc/arch/mips64/gen/Makefile.inc b/lib/libc/arch/mips64/gen/Makefile.inc index f3f88957860..ca34aefd3e4 100644 --- a/lib/libc/arch/mips64/gen/Makefile.inc +++ b/lib/libc/arch/mips64/gen/Makefile.inc @@ -1,6 +1,6 @@ -# $OpenBSD: Makefile.inc,v 1.13 2020/07/06 13:33:05 pirofti Exp $ +# $OpenBSD: Makefile.inc,v 1.14 2023/08/13 06:55:37 miod Exp $ -SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c usertc.c +SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.c nan.c usertc.c SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \ fpsetround.c fpsetsticky.c SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c diff --git a/lib/libc/arch/mips64/gen/modf.S b/lib/libc/arch/mips64/gen/modf.S deleted file mode 100644 index 029e7044191..00000000000 --- a/lib/libc/arch/mips64/gen/modf.S +++ /dev/null @@ -1,71 +0,0 @@ -/* $OpenBSD: modf.S,v 1.5 2011/07/08 22:28:33 martynas Exp $ */ -/*- - * Copyright (c) 1991, 1993, 1995 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include - -/* - * double modf(val, iptr) - * double val, *iptr; - * returns: xxx and n (in *iptr) where val == n.xxx - */ -LEAF(modf, 0) - .set reorder - cfc1 t0, $31 # get the control register - li.d $f2, 4503599627370496e0 # f2 <- 2^52 - - or t1, t0, 0x3 # set rounding mode to round to zero - xor t1, t1, 0x2 # (i.e., 01) - ctc1 t1, $31 - - mov.d $f0, $f12 # f0 <- f12 - abs.d $f4, $f12 # f4 <- |f12| - c.olt.d $f4, $f2 # f4 ? < f2 - bc1f 1f # leave f0 alone if Nan, infinity - # or >=2^52 - c.eq.d $f12,$f4 # was f12 positive ? - add.d $f4,$f2,$f4 # round off to integer - bc1f 2f # No -> will have to negate result - sub.d $f0,$f4,$f2 # Remove fudge factor - j 1f # integer fraction got -2: - sub.d $f0,$f2,$f4 # Remove fudge factor and negate -1: - ctc1 t0, $31 # restore old rounding mode -#ifdef __mips64 - s.d $f0, 0(a1) # save the integer part -#else - s.d $f0, 0(a2) # save the integer part -#endif - sub.d $f0, $f12, $f0 # subtract val - integer part - j ra -END(modf) diff --git a/lib/libc/arch/sparc64/gen/Makefile.inc b/lib/libc/arch/sparc64/gen/Makefile.inc index 6d19faf9502..5cbb1e62227 100644 --- a/lib/libc/arch/sparc64/gen/Makefile.inc +++ b/lib/libc/arch/sparc64/gen/Makefile.inc @@ -1,9 +1,9 @@ -# $OpenBSD: Makefile.inc,v 1.16 2020/07/08 09:20:28 kettenis Exp $ +# $OpenBSD: Makefile.inc,v 1.17 2023/08/13 06:55:37 miod Exp $ SRCS+= _setjmp.S fabs.S fixunsdfsi.S flt_rounds.c fpclassifyl.c \ fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \ fpsetround.c fpsetsticky.c infinity.c isfinitel.c \ - isinfl.c isnanl.c isnormall.c ldexp.c usertc.c modf.S \ + isinfl.c isnanl.c isnormall.c ldexp.c usertc.c modf.c \ mul.S nan.c setjmp.S signbitl.c sigsetjmp.S umul.S CFLAGS += -Wa,-Av9b diff --git a/lib/libc/arch/sparc64/gen/modf.S b/lib/libc/arch/sparc64/gen/modf.S deleted file mode 100644 index 4fa2ea515f2..00000000000 --- a/lib/libc/arch/sparc64/gen/modf.S +++ /dev/null @@ -1,188 +0,0 @@ -/* $OpenBSD: modf.S,v 1.7 2023/01/13 17:52:08 miod Exp $ */ -/* $NetBSD: modf.S,v 1.3 2000/11/01 23:32:41 eeh Exp $ */ - -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This software was developed by the Computer Systems Engineering group - * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and - * contributed to Berkeley. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include - -#include - -/* - * double modf(double val, double *iptr) - * - * Returns the fractional part of `val', storing the integer part of - * `val' in *iptr. Both *iptr and the return value have the same sign - * as `val'. - * - * Method: - * - * We use the fpu's normalization hardware to compute the integer portion - * of the double precision argument. Sun IEEE double precision numbers - * have 52 bits of mantissa, 11 bits of exponent, and one bit of sign, - * with the sign occupying bit 31 of word 0, and the exponent bits 30:20 - * of word 0. Thus, values >= 2^52 are by definition integers. - * - * If we take a value that is in the range [+0..2^52) and add 2^52, all - * of the fractional bits fall out and all of the integer bits are summed - * with 2^52. If we then subtract 2^52, we get those integer bits back. - * This must be done with rounding set to `towards 0' or `towards -inf'. - * `Toward -inf' fails when the value is 0 (we get -0 back).... - * - * Note that this method will work anywhere, but is machine dependent in - * various aspects. - * - * Stack usage: - * 4@[%fp + BIAS - 4] saved %fsr - * 4@[%fp + BIAS - 8] new %fsr with rounding set to `towards 0' - * 8@[%fp + BIAS - 16] space for moving between %i and %f registers - * Register usage: - * %f0:f1 double val; - * %l0 scratch - * %l1 sign bit (0x80000000) - * %i1 double *iptr; - * %f2:f3 `magic number' 2^52, in fpu registers - * %f4:f5 double v, in fpu registers - * %f6:f7 double temp. - */ - - .section .rodata - .align 8 -Lmagic: - .word 0x43300000 ! sign = 0, exponent = 52 + 1023, mantissa = 0 - .word 0 ! (i.e., .double 0r4503599627370496e+00) - -L0: - .word 0 ! 0.0 - .word 0 - - .text -ENTRY(modf) - save %sp, -CC64FSZ-16, %sp -#ifdef __PIC__ - PIC_PROLOGUE(%o5, %o4) -#endif - - /* - * First, compute v = abs(val) - */ - fabsd %f0, %f4 ! %f4:f5 = v - fcmped %fcc1, %f0, %f4 ! %fcc1 = (val == abs(val)) -#ifdef __PIC__ - set Lmagic, %o4 - ldx [%o5 + %o4], %l0 - ldd [%l0], %f2 -#else - sethi %hi(Lmagic), %l0 - ldd [%l0 + %lo(Lmagic)], %f2 -#endif - - /* - * Is %f4:f5 >= %f2:f3 ? If so, it is all integer bits. - * It is probably less, though. - */ - fcmped %f4, %f2 - fbuge Lbig ! if >= (or unordered), go out - nop - - /* - * v < 2^52, so add 2^52, then subtract 2^52, but do it all - * with rounding set towards zero. We leave any enabled - * traps enabled, but change the rounding mode. This might - * not be so good. Oh well.... - */ - st %fsr, [%fp + BIAS - 4] ! %l5 = current FSR mode - set FSR_RD, %l3 ! %l3 = rounding direction mask - ld [%fp + BIAS - 4], %l5 - set FSR_RD_RZ << FSR_RD_SHIFT, %l4 - andn %l5, %l3, %l6 - or %l6, %l4, %l6 ! round towards zero, please - and %l5, %l3, %l5 ! save original rounding mode - st %l6, [%fp + BIAS - 8] - ld [%fp + BIAS - 8], %fsr - - faddd %f4, %f2, %f4 ! %f4:f5 += 2^52 - fsubd %f4, %f2, %f4 ! %f4:f5 -= 2^52 - - /* - * Restore %fsr, but leave exceptions accrued. - */ - st %fsr, [%fp + BIAS - 4] - ld [%fp + BIAS - 4], %l6 - andn %l6, %l3, %l6 ! %l6 = %fsr & ~FSR_RD; - or %l5, %l6, %l5 ! %l5 |= %l6; - st %l5, [%fp + BIAS - 4] - ld [%fp + BIAS - 4], %fsr ! restore %fsr, leaving accrued stuff - - /* - * Now insert the original sign in %f4:f5. - * %fcc1 should still have the reults of (val == abs(val)) - * from above, so we use a conditional move on %fcc1 to: - * - * %f4 = (val == abs(val)) ? %f4 : -%f4 - * - */ - fnegd %f4, %f6 - fmovdnz %fcc1, %f6, %f4 -1: - - /* - * The value in %f4:f5 is now the integer portion of the original - * argument. We need to store this in *ival (%i1), subtract it - * from the original value argument (%d0), and return the result. - */ - std %f4, [%i1] ! *ival = %f4:f5; - fsubd %f0, %f4, %f0 ! %f0:f1 -= %f4:f5; - ret - restore - -Lbig: - /* - * We get here if the original comparison of %f4:f5 (v) to - * %f2:f3 (2^52) came out `greater or unordered'. In this - * case the integer part is the original value, and the - * fractional part is 0. - */ -#ifdef __PIC__ - set L0, %o4 - ldx [%o5 + %o4], %l0 - std %f0, [%i1] ! *ival = val; - ldd [%l0], %f0 ! return 0.0; -#else - sethi %hi(L0), %l0 - std %f0, [%i1] ! *ival = val; - ldd [%l0 + %lo(L0)], %f0 ! return 0.0; -#endif - ret - restore - diff --git a/lib/libc/gen/modf.c b/lib/libc/gen/modf.c index 5c523519ba6..e02e8c106bf 100644 --- a/lib/libc/gen/modf.c +++ b/lib/libc/gen/modf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: modf.c,v 1.6 2013/07/03 04:46:36 espie Exp $ */ +/* $OpenBSD: modf.c,v 1.7 2023/08/13 06:55:37 miod Exp $ */ /* $NetBSD: modf.c,v 1.1 1995/02/10 17:50:25 cgd Exp $ */ /* @@ -51,11 +51,13 @@ modf(double val, double *iptr) u_int64_t frac; /* - * If input is Inf or NaN, return it and leave i alone. + * If input is +/-Inf or NaN, return +/-0 or NaN. */ u.v = val; - if (u.s.dbl_exp == DBL_EXP_INFNAN) - return (u.v); + if (u.s.dbl_exp == DBL_EXP_INFNAN) { + *iptr = u.v; + return (0.0 / u.v); + } /* * If input can't have a fractional part, return