1*3ba7702bSmortimer/* $OpenBSD: e_exp.S,v 1.7 2018/07/03 22:43:34 mortimer Exp $ */ 235abca84Skettenis/* $NetBSD: e_exp.S,v 1.12 2002/02/27 16:32:46 christos Exp $ */ 335abca84Skettenis 435abca84Skettenis/* 535abca84Skettenis * Copyright (c) 1993,94 Winning Strategies, Inc. 635abca84Skettenis * All rights reserved. 735abca84Skettenis * 835abca84Skettenis * Redistribution and use in source and binary forms, with or without 935abca84Skettenis * modification, are permitted provided that the following conditions 1035abca84Skettenis * are met: 1135abca84Skettenis * 1. Redistributions of source code must retain the above copyright 1235abca84Skettenis * notice, this list of conditions and the following disclaimer. 1335abca84Skettenis * 2. Redistributions in binary form must reproduce the above copyright 1435abca84Skettenis * notice, this list of conditions and the following disclaimer in the 1535abca84Skettenis * documentation and/or other materials provided with the distribution. 1635abca84Skettenis * 3. All advertising materials mentioning features or use of this software 1735abca84Skettenis * must display the following acknowledgement: 1835abca84Skettenis * This product includes software developed by Winning Strategies, Inc. 1935abca84Skettenis * 4. The name of the author may not be used to endorse or promote products 2035abca84Skettenis * derived from this software without specific prior written permission. 2135abca84Skettenis * 2235abca84Skettenis * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2335abca84Skettenis * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2435abca84Skettenis * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2535abca84Skettenis * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2635abca84Skettenis * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2735abca84Skettenis * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2835abca84Skettenis * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2935abca84Skettenis * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3035abca84Skettenis * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3135abca84Skettenis * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3235abca84Skettenis */ 3335abca84Skettenis 3435abca84Skettenis/* 3535abca84Skettenis * Written by: 3635abca84Skettenis * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc. 3735abca84Skettenis */ 3835abca84Skettenis 3935abca84Skettenis#include <machine/asm.h> 4035abca84Skettenis 4135abca84Skettenis#include "abi.h" 4235abca84Skettenis 4335abca84Skettenis/* e^x = 2^(x * log2(e)) */ 447b36286aSmartynasENTRY(exp) 45*3ba7702bSmortimer RETGUARD_SETUP(exp, r11) 4635abca84Skettenis XMM_ONE_ARG_DOUBLE_PROLOGUE 4735abca84Skettenis /* 4835abca84Skettenis * If x is +-Inf, then the subtraction would give Inf-Inf = NaN. 4935abca84Skettenis * Avoid this. Also avoid it if x is NaN for convenience. 5035abca84Skettenis */ 5135abca84Skettenis movl -4(%rsp),%eax 5235abca84Skettenis andl $0x7fffffff,%eax 5335abca84Skettenis cmpl $0x7ff00000,%eax 5435abca84Skettenis jae x_Inf_or_NaN 5535abca84Skettenis 5635abca84Skettenis fldl ARG_DOUBLE_ONE 5735abca84Skettenis 5835abca84Skettenis /* 5935abca84Skettenis * Ensure that the rounding mode is to nearest (to give the smallest 6035abca84Skettenis * possible fraction) and that the precision is as high as possible. 6135abca84Skettenis * We may as well mask interrupts if we switch the mode. 6235abca84Skettenis */ 6335abca84Skettenis fstcw -8(%rsp) 6435abca84Skettenis movl -8(%rsp),%eax 6535abca84Skettenis andl $0x0300,%eax 6635abca84Skettenis cmpl $0x0300,%eax /* RC == 0 && PC == 3? */ 6735abca84Skettenis je 1f /* jump if mode is good */ 6835abca84Skettenis movl $0x137f,-4(%rsp) 6935abca84Skettenis fldcw -4(%rsp) 7035abca84Skettenis1: 7135abca84Skettenis fldl2e 7235abca84Skettenis fmulp /* x * log2(e) */ 7335abca84Skettenis fst %st(1) 7435abca84Skettenis frndint /* int(x * log2(e)) */ 7535abca84Skettenis fst %st(2) 7635abca84Skettenis fsubrp /* fract(x * log2(e)) */ 7735abca84Skettenis f2xm1 /* 2^(fract(x * log2(e))) - 1 */ 7835abca84Skettenis fld1 7935abca84Skettenis faddp /* 2^(fract(x * log2(e))) */ 8035abca84Skettenis fscale /* e^x */ 8135abca84Skettenis fstp %st(1) 8235abca84Skettenis je 1f 8335abca84Skettenis fldcw -8(%rsp) 8435abca84Skettenis1: 8535abca84Skettenis XMM_DOUBLE_EPILOGUE 86*3ba7702bSmortimer RETGUARD_CHECK(exp, r11) 8735abca84Skettenis ret 8835abca84Skettenis 8935abca84Skettenisx_Inf_or_NaN: 9035abca84Skettenis /* 9135abca84Skettenis * Return 0 if x is -Inf. Otherwise just return x, although the 9235abca84Skettenis * C version would return (x + x) (Real Indefinite) if x is a NaN. 9335abca84Skettenis */ 9435abca84Skettenis cmpl $0xfff00000,-4(%rsp) 9535abca84Skettenis jne x_not_minus_Inf 9635abca84Skettenis cmpl $0,-8(%rsp) 9735abca84Skettenis jne x_not_minus_Inf 9835abca84Skettenis xorpd %xmm0,%xmm0 99*3ba7702bSmortimer RETGUARD_CHECK(exp, r11) 10035abca84Skettenis ret 10135abca84Skettenis 10235abca84Skettenisx_not_minus_Inf: 10335abca84Skettenis movsd ARG_DOUBLE_ONE,%xmm0 104*3ba7702bSmortimer RETGUARD_CHECK(exp, r11) 10535abca84Skettenis ret 1062f2c0062SguentherEND_STD(exp) 107