Home | History | Annotate | Line # | Download | only in i387
      1   1.1       jtc /*
      2  1.10      salo  * Written by J.T. Conklin <jtc (at) NetBSD.org>.
      3   1.6       jtc  * Public domain.
      4   1.1       jtc  */
      5   1.1       jtc 
      6  1.11  wennmach /*
      7  1.11  wennmach  * Modified by Lex Wennmacher <wennmach (at) NetBSD.org>
      8  1.11  wennmach  * Still public domain.
      9  1.11  wennmach  */
     10  1.11  wennmach 
     11   1.1       jtc #include <machine/asm.h>
     12   1.1       jtc 
     13   1.9      fvdl #include "abi.h"
     14   1.9      fvdl 
     15  1.14  riastrad RCSID("$NetBSD: s_log1p.S,v 1.14 2024/07/16 14:52:49 riastradh Exp $")
     16   1.2       jtc 
     17   1.4       jtc /*
     18  1.11  wennmach  * The log1p() function is provided to compute an accurate value of
     19  1.11  wennmach  * log(1 + x), even for tiny values of x. The i387 FPU provides the
     20  1.11  wennmach  * fyl2xp1 instruction for this purpose. However, the range of this
     21  1.11  wennmach  * instruction is limited to:
     22  1.11  wennmach  * 		-(1 - (sqrt(2) / 2)) <= x <= sqrt(2) - 1
     23  1.11  wennmach  *                         -0.292893 <= x <= 0.414214
     24  1.11  wennmach  * at least on older processor versions.
     25  1.11  wennmach  *
     26  1.11  wennmach  * log1p() is implemented by testing the range of the argument.
     27  1.11  wennmach  * If it is appropriate for fyl2xp1, this instruction is used.
     28  1.11  wennmach  * Else, we compute log1p(x) = ln(2)*ld(1 + x) the traditional way
     29  1.11  wennmach  * (using fyl2x).
     30  1.11  wennmach  *
     31  1.11  wennmach  * The range testing costs speed, but as the rationale for the very
     32  1.11  wennmach  * existence of this function is accuracy, we accept that.
     33  1.11  wennmach  *
     34  1.11  wennmach  * In order to reduce the cost for testing the range, we check if
     35  1.11  wennmach  * the argument is in the range
     36  1.11  wennmach  *                             -0.25 <= x <= 0.25
     37  1.11  wennmach  * which can be done with just one conditional branch. If x is
     38  1.11  wennmach  * inside this range, we use fyl2xp1. Outside of this range,
     39  1.11  wennmach  * the use of fyl2x is accurate enough.
     40   1.4       jtc  */
     41   1.5       jtc 
     42  1.14  riastrad WEAK_ALIAS(log1p, _log1p)
     43  1.14  riastrad 
     44  1.11  wennmach .text
     45  1.13  wennmach 	.align	4
     46  1.14  riastrad ENTRY(_log1p)
     47   1.9      fvdl 	XMM_ONE_ARG_DOUBLE_PROLOGUE
     48  1.11  wennmach 	fldl	ARG_DOUBLE_ONE
     49  1.11  wennmach 	fabs
     50  1.13  wennmach 	fld1				/* ... x 1 */
     51  1.13  wennmach 	fadd	%st(0)			/* ... x 2 */
     52  1.13  wennmach 	fadd	%st(0)			/* ... x 4 */
     53  1.13  wennmach 	fld1				/* ... 4 1 */
     54  1.13  wennmach 	fdivp				/* ... x 0.25 */
     55  1.11  wennmach 	fcompp
     56  1.13  wennmach 	fnstsw	%ax
     57  1.13  wennmach 	andb	$69,%ah
     58  1.13  wennmach 	jne	use_fyl2x
     59  1.13  wennmach 	jmp	use_fyl2xp1
     60  1.13  wennmach 
     61  1.13  wennmach 	.align	4
     62  1.13  wennmach use_fyl2x:
     63  1.11  wennmach 	fldln2
     64  1.11  wennmach         fldl	ARG_DOUBLE_ONE
     65  1.11  wennmach         fld1
     66  1.11  wennmach         faddp
     67  1.11  wennmach         fyl2x
     68  1.11  wennmach 	XMM_DOUBLE_EPILOGUE
     69  1.11  wennmach         ret
     70  1.13  wennmach 
     71  1.13  wennmach 	.align	4
     72  1.13  wennmach use_fyl2xp1:
     73   1.1       jtc 	fldln2
     74   1.9      fvdl 	fldl	ARG_DOUBLE_ONE
     75  1.11  wennmach 	fyl2xp1
     76   1.9      fvdl 	XMM_DOUBLE_EPILOGUE
     77   1.1       jtc 	ret
     78  1.14  riastrad END(_log1p)
     79