/ exp.s (emx+gcc) -- Copyright (c) 1991-1993 by Eberhard Mattes

#include <libm.h>

        .globl  FUN(exp)

        .text

        .align  2, 0x90

/ double exp (double x)

#define cw1      0(%esp)
#define cw2      2(%esp)
/define ret_addr 4(%esp)
#define x        8(%esp)

DEF(exp)
        subl    $4, %esp                / space for control words
        FLD     x                       / x
        fldl2e                          / log2 (e)
        fmulp                           / y := x * log2 (e)
        fstcww  cw1
        movw    cw1, %ax
        andw    $0xf3ff, %ax
        orw     $0x0400, %ax            / round down towards -inf
        movw    %ax, cw2
        fldcww  cw2      
        fld     %st                     / y, y
        frndint                         / int (y), y
        fldcww  cw1
        fxch    %st(1)                  / y, int (y)
        fsub    %st(1), %st             / frac (y), int (y)
        f2xm1                           / 2 ^ frac (y) - 1, int (y)
        faddl   __const_ONE             / 2 ^ frac (y), int (y)
        fscale                          / 2 ^ frac (y) * 2 ^ int (y), int (y)
        fstp    %st(1)                  / 2 ^ frac (y) * 2 ^ int (y)
        CONV(x)                         / convert to double
        addl    $4, %esp                / Remove control words
        _xam
        j_inf   1f
        ret

        .align  2, 0x90
1:      SETERRNO($ERANGE)
        ret
