1*84d9c625SLionel Sambuc/* $NetBSD: modf.S,v 1.5 2013/09/12 15:36:16 joerg Exp $ */ 22fe8fb19SBen Gras 32fe8fb19SBen Gras/* 42fe8fb19SBen Gras * Copyright (c) 1992, 1993 52fe8fb19SBen Gras * The Regents of the University of California. All rights reserved. 62fe8fb19SBen Gras * 72fe8fb19SBen Gras * This software was developed by the Computer Systems Engineering group 82fe8fb19SBen Gras * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 92fe8fb19SBen Gras * contributed to Berkeley. 102fe8fb19SBen Gras * 112fe8fb19SBen Gras * Redistribution and use in source and binary forms, with or without 122fe8fb19SBen Gras * modification, are permitted provided that the following conditions 132fe8fb19SBen Gras * are met: 142fe8fb19SBen Gras * 1. Redistributions of source code must retain the above copyright 152fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer. 162fe8fb19SBen Gras * 2. Redistributions in binary form must reproduce the above copyright 172fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer in the 182fe8fb19SBen Gras * documentation and/or other materials provided with the distribution. 192fe8fb19SBen Gras * 3. Neither the name of the University nor the names of its contributors 202fe8fb19SBen Gras * may be used to endorse or promote products derived from this software 212fe8fb19SBen Gras * without specific prior written permission. 222fe8fb19SBen Gras * 232fe8fb19SBen Gras * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 242fe8fb19SBen Gras * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 252fe8fb19SBen Gras * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 262fe8fb19SBen Gras * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 272fe8fb19SBen Gras * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 282fe8fb19SBen Gras * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 292fe8fb19SBen Gras * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 302fe8fb19SBen Gras * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 312fe8fb19SBen Gras * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 322fe8fb19SBen Gras * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 332fe8fb19SBen Gras * SUCH DAMAGE. 342fe8fb19SBen Gras * 352fe8fb19SBen Gras * from: Header: modf.s,v 1.3 92/06/20 00:00:54 torek Exp 362fe8fb19SBen Gras */ 372fe8fb19SBen Gras 382fe8fb19SBen Gras#include <machine/asm.h> 392fe8fb19SBen Gras#if defined(LIBC_SCCS) && !defined(lint) 402fe8fb19SBen Gras#if 0 412fe8fb19SBen Gras .asciz "@(#)modf.s 8.1 (Berkeley) 6/4/93" 422fe8fb19SBen Gras#else 43*84d9c625SLionel Sambuc RCSID("$NetBSD: modf.S,v 1.5 2013/09/12 15:36:16 joerg Exp $") 442fe8fb19SBen Gras#endif 452fe8fb19SBen Gras#endif /* LIBC_SCCS and not lint */ 462fe8fb19SBen Gras 472fe8fb19SBen Gras#include <machine/fsr.h> 482fe8fb19SBen Gras 492fe8fb19SBen Gras/* 502fe8fb19SBen Gras * double modf(double val, double *iptr) 512fe8fb19SBen Gras * 522fe8fb19SBen Gras * Returns the fractional part of `val', storing the integer part of 532fe8fb19SBen Gras * `val' in *iptr. Both *iptr and the return value have the same sign 542fe8fb19SBen Gras * as `val'. 552fe8fb19SBen Gras * 562fe8fb19SBen Gras * Method: 572fe8fb19SBen Gras * 582fe8fb19SBen Gras * We use the fpu's normalization hardware to compute the integer portion 592fe8fb19SBen Gras * of the double precision argument. Sun IEEE double precision numbers 602fe8fb19SBen Gras * have 52 bits of mantissa, 11 bits of exponent, and one bit of sign, 612fe8fb19SBen Gras * with the sign occupying bit 31 of word 0, and the exponent bits 30:20 622fe8fb19SBen Gras * of word 0. Thus, values >= 2^52 are by definition integers. 632fe8fb19SBen Gras * 642fe8fb19SBen Gras * If we take a value that is in the range [+0..2^52) and add 2^52, all 652fe8fb19SBen Gras * of the fractional bits fall out and all of the integer bits are summed 662fe8fb19SBen Gras * with 2^52. If we then subtract 2^52, we get those integer bits back. 672fe8fb19SBen Gras * This must be done with rounding set to `towards 0' or `towards -inf'. 682fe8fb19SBen Gras * `Toward -inf' fails when the value is 0 (we get -0 back).... 692fe8fb19SBen Gras * 702fe8fb19SBen Gras * Note that this method will work anywhere, but is machine dependent in 712fe8fb19SBen Gras * various aspects. 722fe8fb19SBen Gras * 732fe8fb19SBen Gras * Stack usage: 742fe8fb19SBen Gras * 4@[%fp + BIAS - 4] saved %fsr 752fe8fb19SBen Gras * 4@[%fp + BIAS - 8] new %fsr with rounding set to `towards 0' 762fe8fb19SBen Gras * 8@[%fp + BIAS - 16] space for moving between %i and %f registers 772fe8fb19SBen Gras * Register usage: 782fe8fb19SBen Gras * %f0:f1 double val; 792fe8fb19SBen Gras * %l0 scratch 802fe8fb19SBen Gras * %l1 sign bit (0x80000000) 812fe8fb19SBen Gras * %i1 double *iptr; 822fe8fb19SBen Gras * %f2:f3 `magic number' 2^52, in fpu registers 832fe8fb19SBen Gras * %f4:f5 double v, in fpu registers 842fe8fb19SBen Gras * %f6:f7 double temp. 852fe8fb19SBen Gras */ 862fe8fb19SBen Gras 872fe8fb19SBen Gras .align 8 882fe8fb19SBen GrasLmagic: 892fe8fb19SBen Gras .word 0x43300000 ! sign = 0, exponent = 52 + 1023, mantissa = 0 902fe8fb19SBen Gras .word 0 ! (i.e., .double 0r4503599627370496e+00) 912fe8fb19SBen Gras 922fe8fb19SBen GrasL0: 932fe8fb19SBen Gras .word 0 ! 0.0 942fe8fb19SBen Gras .word 0 952fe8fb19SBen Gras 962fe8fb19SBen GrasENTRY(modf) 972fe8fb19SBen Gras save %sp, -CC64FSZ-16, %sp 982fe8fb19SBen Gras 992fe8fb19SBen Gras /* 1002fe8fb19SBen Gras * First, compute v = abs(val) 1012fe8fb19SBen Gras */ 1022fe8fb19SBen Gras fabsd %f0, %f4 ! %f4:f5 = v 1032fe8fb19SBen Gras fcmped %fcc1, %f0, %f4 ! %fcc1 = (val == abs(val)) 104*84d9c625SLionel Sambuc#ifdef __PIC__ 1052fe8fb19SBen Gras PICCY_SET(Lmagic, %l0, %o7) 1062fe8fb19SBen Gras ldd [%l0], %f2 1072fe8fb19SBen Gras#else 1082fe8fb19SBen Gras sethi %hi(Lmagic), %l0 1092fe8fb19SBen Gras ldd [%l0 + %lo(Lmagic)], %f2 1102fe8fb19SBen Gras#endif 1112fe8fb19SBen Gras 1122fe8fb19SBen Gras /* 1132fe8fb19SBen Gras * Is %f4:f5 >= %f2:f3 ? If so, it is all integer bits. 1142fe8fb19SBen Gras * It is probably less, though. 1152fe8fb19SBen Gras */ 1162fe8fb19SBen Gras fcmped %f4, %f2 1172fe8fb19SBen Gras fbuge Lbig ! if >= (or unordered), go out 1182fe8fb19SBen Gras nop 1192fe8fb19SBen Gras 1202fe8fb19SBen Gras /* 1212fe8fb19SBen Gras * v < 2^52, so add 2^52, then subtract 2^52, but do it all 1222fe8fb19SBen Gras * with rounding set towards zero. We leave any enabled 1232fe8fb19SBen Gras * traps enabled, but change the rounding mode. This might 1242fe8fb19SBen Gras * not be so good. Oh well.... 1252fe8fb19SBen Gras */ 1262fe8fb19SBen Gras st %fsr, [%fp + BIAS - 4] ! %l5 = current FSR mode 1272fe8fb19SBen Gras set FSR_RD, %l3 ! %l3 = rounding direction mask 1282fe8fb19SBen Gras ld [%fp + BIAS - 4], %l5 1292fe8fb19SBen Gras set FSR_RD_RZ << FSR_RD_SHIFT, %l4 1302fe8fb19SBen Gras andn %l5, %l3, %l6 1312fe8fb19SBen Gras or %l6, %l4, %l6 ! round towards zero, please 1322fe8fb19SBen Gras and %l5, %l3, %l5 ! save original rounding mode 1332fe8fb19SBen Gras st %l6, [%fp + BIAS - 8] 1342fe8fb19SBen Gras ld [%fp + BIAS - 8], %fsr 1352fe8fb19SBen Gras 1362fe8fb19SBen Gras faddd %f4, %f2, %f4 ! %f4:f5 += 2^52 1372fe8fb19SBen Gras fsubd %f4, %f2, %f4 ! %f4:f5 -= 2^52 1382fe8fb19SBen Gras 1392fe8fb19SBen Gras /* 1402fe8fb19SBen Gras * Restore %fsr, but leave exceptions accrued. 1412fe8fb19SBen Gras */ 1422fe8fb19SBen Gras st %fsr, [%fp + BIAS - 4] 1432fe8fb19SBen Gras ld [%fp + BIAS - 4], %l6 1442fe8fb19SBen Gras andn %l6, %l3, %l6 ! %l6 = %fsr & ~FSR_RD; 1452fe8fb19SBen Gras or %l5, %l6, %l5 ! %l5 |= %l6; 1462fe8fb19SBen Gras st %l5, [%fp + BIAS - 4] 1472fe8fb19SBen Gras ld [%fp + BIAS - 4], %fsr ! restore %fsr, leaving accrued stuff 1482fe8fb19SBen Gras 1492fe8fb19SBen Gras /* 1502fe8fb19SBen Gras * Now insert the original sign in %f4:f5. 1512fe8fb19SBen Gras * %fcc1 should still have the reults of (val == abs(val)) 1522fe8fb19SBen Gras * from above, so we use a conditional move on %fcc1 to: 1532fe8fb19SBen Gras * 1542fe8fb19SBen Gras * %f4 = (val == abs(val)) ? %f4 : -%f4 1552fe8fb19SBen Gras * 1562fe8fb19SBen Gras */ 1572fe8fb19SBen Gras fnegd %f4, %f6 1582fe8fb19SBen Gras fmovdnz %fcc1, %f6, %f4 1592fe8fb19SBen Gras1: 1602fe8fb19SBen Gras 1612fe8fb19SBen Gras /* 1622fe8fb19SBen Gras * The value in %f4:f5 is now the integer portion of the original 1632fe8fb19SBen Gras * argument. We need to store this in *ival (%i1), subtract it 1642fe8fb19SBen Gras * from the original value argument (%d0), and return the result. 1652fe8fb19SBen Gras */ 1662fe8fb19SBen Gras std %f4, [%i1] ! *ival = %f4:f5; 1672fe8fb19SBen Gras fsubd %f0, %f4, %f0 ! %f0:f1 -= %f4:f5; 1682fe8fb19SBen Gras ret 1692fe8fb19SBen Gras restore 1702fe8fb19SBen Gras 1712fe8fb19SBen GrasLbig: 1722fe8fb19SBen Gras /* 1732fe8fb19SBen Gras * We get here if the original comparison of %f4:f5 (v) to 1742fe8fb19SBen Gras * %f2:f3 (2^52) came out `greater or unordered'. In this 1752fe8fb19SBen Gras * case the integer part is the original value, and the 1762fe8fb19SBen Gras * fractional part is 0. 1772fe8fb19SBen Gras */ 178*84d9c625SLionel Sambuc#ifdef __PIC__ 1792fe8fb19SBen Gras PICCY_SET(L0, %l0, %o7) 1802fe8fb19SBen Gras std %f0, [%i1] ! *ival = val; 1812fe8fb19SBen Gras ldd [%l0], %f0 ! return 0.0; 1822fe8fb19SBen Gras#else 1832fe8fb19SBen Gras sethi %hi(L0), %l0 1842fe8fb19SBen Gras std %f0, [%i1] ! *ival = val; 1852fe8fb19SBen Gras ldd [%l0 + %lo(L0)], %f0 ! return 0.0; 1862fe8fb19SBen Gras#endif 1872fe8fb19SBen Gras ret 1882fe8fb19SBen Gras restore 1892fe8fb19SBen Gras 190