1*84d9c625SLionel Sambuc/* $NetBSD: modf.S,v 1.7 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.7 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 - 4] saved %fsr 752fe8fb19SBen Gras * 4@[%fp - 8] new %fsr with rounding set to `towards 0' 762fe8fb19SBen Gras * 8@[%fp - 16] space for moving between %i and %f registers 772fe8fb19SBen Gras * Register usage: 782fe8fb19SBen Gras * %i0%i1 double val; 792fe8fb19SBen Gras * %l0 scratch 802fe8fb19SBen Gras * %l1 sign bit (0x80000000) 812fe8fb19SBen Gras * %i2 double *iptr; 822fe8fb19SBen Gras * %f2:f3 `magic number' 2^52, in fpu registers 832fe8fb19SBen Gras * %f4:f5 double v, in fpu registers 842fe8fb19SBen Gras */ 852fe8fb19SBen Gras 862fe8fb19SBen Gras .align 8 872fe8fb19SBen GrasLmagic: 882fe8fb19SBen Gras .word 0x43300000 ! sign = 0, exponent = 52 + 1023, mantissa = 0 892fe8fb19SBen Gras .word 0 ! (i.e., .double 0r4503599627370496e+00) 902fe8fb19SBen Gras 912fe8fb19SBen GrasL0: 922fe8fb19SBen Gras .word 0 ! 0.0 932fe8fb19SBen Gras .word 0 942fe8fb19SBen Gras 952fe8fb19SBen GrasENTRY(modf) 962fe8fb19SBen Gras save %sp, -64-16, %sp 972fe8fb19SBen Gras 982fe8fb19SBen Gras /* 992fe8fb19SBen Gras * First, compute v = abs(val) by clearing sign bit, 1002fe8fb19SBen Gras * and then set up the fpu registers. This would be 1012fe8fb19SBen Gras * much easier if we could do alu operations on fpu registers! 1022fe8fb19SBen Gras */ 1032fe8fb19SBen Gras sethi %hi(0x80000000), %l1 ! sign bit 1042fe8fb19SBen Gras andn %i0, %l1, %l0 1052fe8fb19SBen Gras st %l0, [%fp - 16] 106*84d9c625SLionel Sambuc#ifdef __PIC__ 1072fe8fb19SBen Gras PICCY_SET(Lmagic, %l0, %o7) 1082fe8fb19SBen Gras ldd [%l0], %f2 1092fe8fb19SBen Gras#else 1102fe8fb19SBen Gras sethi %hi(Lmagic), %l0 1112fe8fb19SBen Gras ldd [%l0 + %lo(Lmagic)], %f2 1122fe8fb19SBen Gras#endif 1132fe8fb19SBen Gras st %i1, [%fp - 12] 1142fe8fb19SBen Gras ldd [%fp - 16], %f4 ! %f4:f5 = v 1152fe8fb19SBen Gras 1162fe8fb19SBen Gras /* 1172fe8fb19SBen Gras * Is %f4:f5 >= %f2:f3 ? If so, it is all integer bits. 1182fe8fb19SBen Gras * It is probably less, though. 1192fe8fb19SBen Gras */ 1202fe8fb19SBen Gras fcmped %f4, %f2 1212fe8fb19SBen Gras nop ! fpop2 delay 1222fe8fb19SBen Gras fbuge Lbig ! if >= (or unordered), go out 1232fe8fb19SBen Gras nop 1242fe8fb19SBen Gras 1252fe8fb19SBen Gras /* 1262fe8fb19SBen Gras * v < 2^52, so add 2^52, then subtract 2^52, but do it all 1272fe8fb19SBen Gras * with rounding set towards zero. We leave any enabled 1282fe8fb19SBen Gras * traps enabled, but change the rounding mode. This might 1292fe8fb19SBen Gras * not be so good. Oh well.... 1302fe8fb19SBen Gras */ 1312fe8fb19SBen Gras st %fsr, [%fp - 4] ! %l5 = current FSR mode 1322fe8fb19SBen Gras set FSR_RD, %l3 ! %l3 = rounding direction mask 1332fe8fb19SBen Gras ld [%fp - 4], %l5 1342fe8fb19SBen Gras set FSR_RD_RZ << FSR_RD_SHIFT, %l4 1352fe8fb19SBen Gras andn %l5, %l3, %l6 1362fe8fb19SBen Gras or %l6, %l4, %l6 ! round towards zero, please 1372fe8fb19SBen Gras and %l5, %l3, %l5 ! save original rounding mode 1382fe8fb19SBen Gras st %l6, [%fp - 8] 1392fe8fb19SBen Gras ld [%fp - 8], %fsr 1402fe8fb19SBen Gras 1412fe8fb19SBen Gras faddd %f4, %f2, %f4 ! %f4:f5 += 2^52 1422fe8fb19SBen Gras fsubd %f4, %f2, %f4 ! %f4:f5 -= 2^52 1432fe8fb19SBen Gras 1442fe8fb19SBen Gras /* 1452fe8fb19SBen Gras * Restore %fsr, but leave exceptions accrued. 1462fe8fb19SBen Gras */ 1472fe8fb19SBen Gras st %fsr, [%fp - 4] 1482fe8fb19SBen Gras ld [%fp - 4], %l6 1492fe8fb19SBen Gras andn %l6, %l3, %l6 ! %l6 = %fsr & ~FSR_RD; 1502fe8fb19SBen Gras or %l5, %l6, %l5 ! %l5 |= %l6; 1512fe8fb19SBen Gras st %l5, [%fp - 4] 1522fe8fb19SBen Gras ld [%fp - 4], %fsr ! restore %fsr, leaving accrued stuff 1532fe8fb19SBen Gras 1542fe8fb19SBen Gras /* 1552fe8fb19SBen Gras * Now insert the original sign in %f4:f5. 1562fe8fb19SBen Gras * This is a lot of work, so it is conditional here. 1572fe8fb19SBen Gras */ 1582fe8fb19SBen Gras btst %l1, %i0 1592fe8fb19SBen Gras be 1f 1602fe8fb19SBen Gras nop 1612fe8fb19SBen Gras st %f4, [%fp - 16] 1622fe8fb19SBen Gras ld [%fp - 16], %g1 1632fe8fb19SBen Gras or %l1, %g1, %g1 1642fe8fb19SBen Gras st %g1, [%fp - 16] 1652fe8fb19SBen Gras ld [%fp - 16], %f4 1662fe8fb19SBen Gras1: 1672fe8fb19SBen Gras 1682fe8fb19SBen Gras /* 1692fe8fb19SBen Gras * The value in %f4:f5 is now the integer portion of the original 1702fe8fb19SBen Gras * argument. We need to store this in *ival (%i2), subtract it 1712fe8fb19SBen Gras * from the original value argument (%i0:i1), and return the result. 1722fe8fb19SBen Gras */ 1732fe8fb19SBen Gras std %f4, [%i2] ! *ival = %f4:f5; 1742fe8fb19SBen Gras std %i0, [%fp - 16] 1752fe8fb19SBen Gras ldd [%fp - 16], %f0 ! %f0:f1 = val; 1762fe8fb19SBen Gras fsubd %f0, %f4, %f0 ! %f0:f1 -= %f4:f5; 1772fe8fb19SBen Gras ret 1782fe8fb19SBen Gras restore 1792fe8fb19SBen Gras 1802fe8fb19SBen GrasLbig: 1812fe8fb19SBen Gras /* 1822fe8fb19SBen Gras * We get here if the original comparison of %f4:f5 (v) to 1832fe8fb19SBen Gras * %f2:f3 (2^52) came out `greater or unordered'. In this 1842fe8fb19SBen Gras * case the integer part is the original value, and the 1852fe8fb19SBen Gras * fractional part is 0. 1862fe8fb19SBen Gras */ 187*84d9c625SLionel Sambuc#ifdef __PIC__ 1882fe8fb19SBen Gras PICCY_SET(L0, %l0, %o7) 1892fe8fb19SBen Gras std %f0, [%i2] ! *ival = val; 1902fe8fb19SBen Gras ldd [%l0], %f0 ! return 0.0; 1912fe8fb19SBen Gras#else 1922fe8fb19SBen Gras sethi %hi(L0), %l0 1932fe8fb19SBen Gras std %f0, [%i2] ! *ival = val; 1942fe8fb19SBen Gras ldd [%l0 + %lo(L0)], %f0 ! return 0.0; 1952fe8fb19SBen Gras#endif 1962fe8fb19SBen Gras ret 1972fe8fb19SBen Gras restore 198