Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
  2. #include<libc/asm.h>
  3. pinf:
  4.         .long   0x7F800000
  5.  
  6. NaN:
  7.         .long   0xFFC00000
  8.  
  9.  
  10. MK_C_SYM(expm1)
  11.         movl    8(%esp), %eax           /* Test for special cases. */
  12.         andl    $0x7FFFFFFF, %eax
  13.         cmpl    $0x40862E42, %eax
  14.         jge     bigarg                  /* normal args: */
  15.                                         /* 0 < |x| <= log(DBL_MAX) */
  16. argok:                                  /* N.B. */
  17.                                         /* log(DBL_MAX) = 0x40862E42FEFA39EF */
  18.         fldl    4(%esp)
  19.         fldl2e                          /* log2(e)  x                      */
  20.         fmulp                           /* xs                              */
  21.         fld     %st                     /* xs       xs                     */
  22.         frndint                         /* nint(xs) xs                     */
  23.         fxch    %st(1)                  /* xs       nint                   */
  24.         fsub    %st(1),%st              /* fract    nint                   */
  25.         f2xm1                           /* exps-1   nint                   */
  26.         fxch    %st(1)                  /* nint     exps-1                 */
  27.         fld1                            /* 1        nint    exps-1         */
  28.         fscale                          /* scale    nint    exps-1         */
  29.         fld1                            /* 1        scale   nint    exps-1 */
  30.         /* Should be fsubp %st,%st(1) (gas bug) */
  31.         .byte   0xDE, 0xE9              /* scale-1  nint    exps-1         */
  32.         fxch    %st(2)                  /* exps-1   nint    scale-1        */
  33.         fscale                          /* expm     nint    scale-1        */
  34.         fstp    %st(1)                  /* exp      scale-1                */
  35.         faddp                           /* exp-1                           */
  36.         ret
  37.  
  38. bigarg:
  39.         je      edge
  40.         andl    $0x7FF00000, %eax       /* |x| > log(DBL_MAX) */
  41.         cmpl    $0x7FF00000, %eax
  42.         je      abarg
  43.  
  44. posneg:
  45.         testl   $0x80000000, 8(%esp)
  46.         jnz     argok                   /* Large negative -- OK */
  47.         movl    $2, C_SYM(errno)        /* |x| is really big, but finite */
  48.         jmp     argok
  49.  
  50. edge:                                   /* |x| is nearly log(DBL_MAX) */
  51.         cmpl    $0xFEFA39EF, 4(%esp)
  52.         jbe     argok
  53.         jmp     posneg
  54.  
  55. abarg:                                  /* x = +/-inf, or +NaN */
  56.         testl   $0x000FFFFF, 8(%esp)
  57.         jnz     badarg
  58.         movl    4(%esp), %eax
  59.         testl   %eax, %eax
  60.         jnz     badarg
  61.  
  62. infarg:                                 /* |x| = inf */
  63.         testl   $0x80000000, 8(%esp)
  64.         jz      posinf
  65.  
  66. neginf:
  67.         fld1
  68.         fchs
  69.         ret
  70.  
  71. posinf:
  72.         movl    $2, C_SYM(errno)
  73.         flds    pinf
  74.         ret
  75.  
  76. badarg:                                 /* arg is NaN */
  77.         movl    $1, C_SYM(errno)
  78.         flds    NaN
  79.         ret
  80.