Subversion Repositories Kolibri OS

Rev

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

  1. ;FpuAtoFL    PROTO :DWORD,:DWORD,:DWORD
  2. ;FpuFLtoA    PROTO :DWORD,:DWORD,:DWORD,:DWORD
  3.  
  4. ;FpuAdd      PROTO :DWORD,:DWORD,:DWORD,:DWORD
  5. ;FpuSub      PROTO :DWORD,:DWORD,:DWORD,:DWORD
  6. ;FpuMul      PROTO :DWORD,:DWORD,:DWORD,:DWORD
  7. ;FpuDiv      PROTO :DWORD,:DWORD,:DWORD,:DWORD
  8. ;FpuSqrt     PROTO :DWORD,:DWORD,:DWORD
  9. ;FpuXexpY    PROTO :DWORD,:DWORD,:DWORD,:DWORD
  10. ;FpuAbs      PROTO :DWORD,:DWORD,:DWORD
  11. ;FpuTrunc    PROTO :DWORD,:DWORD,:DWORD
  12. ;FpuRound    PROTO :DWORD,:DWORD,:DWORD
  13. ;FpuChs      PROTO :DWORD,:DWORD,:DWORD
  14.  
  15. ;FpuLnx      PROTO :DWORD,:DWORD,:DWORD
  16. ;FpuLogx     PROTO :DWORD,:DWORD,:DWORD
  17. ;FpuEexpX    PROTO :DWORD,:DWORD,:DWORD
  18. ;FpuTexpX    PROTO :DWORD,:DWORD,:DWORD
  19.  
  20. ;FpuSin      PROTO :DWORD,:DWORD,:DWORD
  21. ;FpuCos      PROTO :DWORD,:DWORD,:DWORD
  22. ;FpuTan      PROTO :DWORD,:DWORD,:DWORD
  23. ;FpuArcsin   PROTO :DWORD,:DWORD,:DWORD
  24. ;FpuArccos   PROTO :DWORD,:DWORD,:DWORD
  25. ;FpuArctan   PROTO :DWORD,:DWORD,:DWORD
  26.  
  27. ;FpuSinh     PROTO :DWORD,:DWORD,:DWORD
  28. ;FpuCosh     PROTO :DWORD,:DWORD,:DWORD
  29. ;FpuTanh     PROTO :DWORD,:DWORD,:DWORD
  30. ;FpuArcsinh  PROTO :DWORD,:DWORD,:DWORD
  31. ;FpuArccosh  PROTO :DWORD,:DWORD,:DWORD
  32. ;FpuArctanh  PROTO :DWORD,:DWORD,:DWORD
  33.  
  34. ;FpuSize     PROTO :DWORD,:DWORD,:DWORD
  35. ;FpuComp     PROTO :DWORD,:DWORD,:DWORD
  36. ;FpuExam     PROTO :DWORD,:DWORD
  37. ;FpuState    PROTO :DWORD
  38.  
  39. SRC1_FPU    EQU   1
  40. SRC1_REAL   EQU   2
  41. SRC1_DMEM   EQU   4
  42. SRC1_DIMM   EQU   8
  43. SRC1_CONST  EQU   16
  44.  
  45. ANG_DEG     EQU   0
  46. ANG_RAD     EQU   32
  47.  
  48. DEST_MEM    EQU   0
  49. DEST_IMEM   EQU   64
  50. DEST_FPU    EQU   128
  51.  
  52. SRC2_FPU    EQU   256
  53. SRC2_REAL   EQU   512
  54. SRC2_DMEM   EQU   1024
  55. SRC2_DIMM   EQU   2048
  56. SRC2_CONST  EQU   4096
  57.  
  58. STR_REG     EQU   0
  59. STR_SCI     EQU   32768
  60.  
  61. FPU_PI      EQU   1
  62. FPU_NAPIER  EQU   2
  63.  
  64. XAM_VALID   EQU   1
  65. XAM_ZERO    EQU   2
  66. XAM_NEG     EQU   4
  67. XAM_SMALL   EQU   8
  68. XAM_INFINIT EQU   16
  69.  
  70. CMP_EQU     EQU   1
  71. CMP_GREATER EQU   2
  72. CMP_LOWER   EQU   4
  73.  
  74.  
  75.  
  76.  
  77. ; #########################################################################
  78. ;
  79. ;                             FpuFLtoA
  80. ;
  81. ;##########################################################################
  82.  
  83.   ; -----------------------------------------------------------------------
  84.   ; This procedure was written by Raymond Filiatreault, December 2002
  85.   ; and modified April 2003. A minor flaw was corrected in July 2003.
  86.   ; Modified March 2004 to avoid any potential data loss from the FPU
  87.   ;
  88.   ; This FpuFLtoA function converts an 80-bit REAL number (Src) to its
  89.   ; decimal representation as a zero terminated alphanumeric string which
  90.   ; is returned at the specified memory destination unless an invalid
  91.   ; operation is reported by the FPU or the definition of the parameters
  92.   ; (with uID) is invalid.
  93.   ;
  94.   ; The format of the string can be specified as regular (default) or
  95.   ; scientific notation. The number of decimal places returned must also be
  96.   ; specified but the total number of significant digits must not exceed 16.
  97.   ; When the regular format is specified, the integer portion can also be
  98.   ; padded with preceding spaces to position the decimal point at a
  99.   ; specified location from the start of the string.
  100.   ;
  101.   ; The source can be an 80-bit REAL number from the FPU itself or from
  102.   ; memory.
  103.   ;
  104.   ; The source is not checked for validity. This is the programmer's
  105.   ; responsibility.
  106.   ;
  107.   ; This procedure is based on using an FPU instruction to convert the
  108.   ; REAL number into a specific packed decimal format. After unpacking,
  109.   ; the decimal point is positioned as required.
  110.   ;
  111.   ; Only EAX is used to return error or success. All other CPU registers
  112.   ; are preserved. All FPU registers are preserved.
  113.   ;
  114.   ; -----------------------------------------------------------------------
  115.  
  116.  
  117. ; #########################################################################
  118. align 4
  119. proc  FpuFLtoA stdcall, lpSrc:DWORD, lpDecimal:DWORD, lpDest:DWORD, uID:DWORD
  120.  
  121. locals
  122.  tempdw dd ?
  123.  esize dd ?
  124.  Padding dd ?
  125.  Decimal dd ?
  126.  content: times 108 db ?
  127.  tempst dt ?
  128.  bcdstr dt ?
  129.  oldcw dw ?
  130.  truncw dw ?
  131.  unpacked: times 20 db ?
  132. endl
  133.  
  134. ;get the specified number of decimals for result
  135. ;and make corrections if necessary
  136.  
  137.       mov   eax,[lpDecimal]
  138.       test  [uID],SRC2_DMEM
  139.       jz    @F
  140.       mov   eax,[eax]         ;get the decimals from memory
  141.    @@:
  142.       push  eax
  143.       movzx eax,al            ;low byte - number of decimal digits
  144.       cmp   eax,15
  145.       jbe   @F
  146.       mov   eax,15            ;a maximum of 15 decimals is allowed
  147.    @@:
  148.       mov   [Decimal],eax
  149.       pop   eax
  150.       movzx eax,ah            ;2nd byte - number of char before decimal point
  151.       cmp   eax,17
  152.       jbe   @F
  153.       mov   eax,17            ;a maximum of 17 characters is allowed
  154.    @@:
  155.       mov   [Padding],eax
  156.  
  157.       test  [uID],SRC1_FPU      ;is data taken from FPU?
  158.       jz    @F                ;continue if not
  159.  
  160. ;-------------------------------
  161. ;check if top register is empty
  162. ;-------------------------------
  163.  
  164.       fxam                    ;examine its content
  165.       fstsw ax                ;store results in AX
  166.       fwait                   ;for precaution
  167.       sahf                    ;transfer result bits to CPU flag
  168.       jnc   @F                ;not empty if Carry flag not set
  169.       jpe   @F                ;not empty if Parity flag set
  170.       jz    srcerr1           ;empty if Zero flag set
  171.  
  172.    @@:
  173.       fsave [content]
  174.  
  175. ;----------------------------------------
  176. ;check source for Src and load it to FPU
  177. ;----------------------------------------
  178.  
  179.       test  [uID],SRC1_FPU
  180.       jz    @F
  181.       lea   eax,[content]
  182.       fld   tbyte [eax+28]
  183.       jmp   dest0
  184.  
  185.    @@:
  186.       test  [uID],SRC1_REAL     ;is Src an 80-bit REAL in memory?
  187.       jz    srcerr            ;no proper source identificaiton
  188.       mov   eax,[lpSrc]
  189.       fld   tbyte [eax]
  190.       jmp   dest0             ;go complete process
  191.      
  192. srcerr:
  193.       frstor [content]
  194. srcerr1:
  195.       push  edi
  196.       mov   edi,[lpDest]
  197.       mov   eax,"ERRO";ORRE"
  198.       stosd
  199.       mov   ax,"R"
  200.       stosw
  201.       pop   edi
  202.       xor   eax,eax
  203.       ret
  204.  
  205. dest0:
  206.  
  207. ;-------------------------------------------
  208. ;first examine the value on FPU for validity
  209. ;-------------------------------------------
  210.  
  211.       fxam                    ;examine value on FPU
  212.       fstsw ax                ;get result
  213.       fwait
  214.       sahf                    ;transfer to CPU flags
  215.       jz    maybezero
  216.       jpo   srcerr            ;C3=0 and C2=0 would be NAN or unsupported
  217.       jnc   getnumsize        ;continue if normal finite number
  218.  
  219. ;--------------------------------
  220. ;value to be converted = INFINITY
  221. ;--------------------------------
  222.  
  223.       push  ecx
  224.       push  esi
  225.       push  edi
  226.       mov   edi,[lpDest]
  227.       mov   al,"+"
  228.       test  ah,2              ;C1 field = sign
  229.       jz    @F
  230.       mov   al,"-"
  231.    @@:
  232.       stosb
  233.       mov   eax,"INFI";IFNI"
  234.       stosd
  235.       mov   eax,"NITY";YTIN"
  236.       stosd
  237.       jmp   finish     
  238.  
  239. ;-------------------------
  240. ;value to be converted = 0
  241. ;-------------------------
  242.  
  243. maybezero:
  244.       jpe   getnumsize        ;would be denormalized number
  245.       fstp  st0             ;flush that 0 value off the FPU
  246.       push  ecx
  247.       push  esi
  248.       push  edi
  249.       mov   edi,[lpDest]
  250.       test  [uID],STR_SCI       ;scientific notation?
  251.       jnz   @F                ;no padding
  252.       mov   ecx,[Padding]
  253.       sub   ecx,2
  254.       jle   @F                ;no padding specified or necessary
  255.       mov   al," "
  256.       rep   stosb
  257.    @@:
  258.       mov   ax,3020h          ;" 0" szstring
  259.       stosw                   ;write it
  260.       jmp   finish
  261.      
  262. ;---------------------------
  263. ; get the size of the number
  264. ;---------------------------
  265.  
  266. getnumsize:
  267.       fldlg2                  ;log10(2)
  268.       fld   st1             ;copy Src
  269.       fabs                    ;insures a positive value
  270.       fyl2x                   ;->[log2(Src)]*[log10(2)] = log10(Src)
  271.      
  272.       fstcw [oldcw]             ;get current control word
  273.       fwait
  274.       mov   ax,[oldcw]
  275.       or    ax,0c00h          ;code it for truncating
  276.       mov   [truncw],ax
  277.       fldcw [truncw]            ;insure rounding code of FPU to truncating
  278.      
  279.       fist  [esize]             ;store characteristic of logarithm
  280.       fldcw [oldcw]             ;load back the former control word
  281.  
  282.       ftst                    ;test logarithm for its sign
  283.       fstsw ax                ;get result
  284.       fwait
  285.       sahf                    ;transfer to CPU flags
  286.       sbb   [esize],0           ;decrement esize if log is negative
  287.       fstp  st0             ;get rid of the logarithm
  288.  
  289. ;-----------------------------------------------------------------------
  290. ; get the power of 10 required to generate an integer with the specified
  291. ; number of significant digits
  292. ;-----------------------------------------------------------------------
  293.  
  294.       mov   eax,[uID]
  295.       and   eax,STR_SCI
  296.         jnz .els0        ;regular decimal notation
  297.             mov   eax,[esize]
  298.             or    eax,eax     ;check if number is < 1
  299.             js    @F
  300. ;            .if   eax > 15    ;if number is >= 10^16
  301.                 cmp eax,15
  302.                 jbe .endif0
  303.                   or    [uID],STR_SCI ;switch to scientific notation
  304.                   mov   [Decimal],15  ;insures 15 decimal places in result
  305.                   jmp   scific
  306.             .endif0:
  307.             add   eax,[Decimal]
  308. ;            .if   eax > 15    ;if integer + decimal digits > 16
  309.                 cmp eax,15
  310.                 jbe .endif1
  311.                   sub   eax,15
  312.                   sub   [Decimal],eax ;reduce decimal digits as required
  313.             .endif1:
  314.          @@:
  315.             push  [Decimal]
  316.             pop   [tempdw]
  317.                 jmp @f
  318.       .els0:                   ;scientific notation
  319.       scific:
  320.             mov   eax,[Decimal]
  321.             sub   eax,[esize]
  322.             mov   [tempdw],eax
  323. ;      .endif
  324.         @@:
  325.  
  326. ;----------------------------------------------------------------------------------------
  327. ; multiply the number by the power of 10 to generate required integer and store it as BCD
  328. ;----------------------------------------------------------------------------------------
  329.  
  330. ;.if   tempdw != 0
  331.         cmp [tempdw],0
  332.         je @f
  333.       fild  [tempdw]
  334.       fldl2t
  335.       fmulp st1,st0                  ;->log2(10)*exponent
  336.       fld   st0
  337.       frndint                 ;get the characteristic of the log
  338.       fxch
  339.       fsub st,st1           ;get only the fractional part but keep the characteristic
  340.       f2xm1                   ;->2^(fractional part)-1
  341.       fld1
  342.       faddp st1,st0                  ;add 1 back
  343.       fscale                  ;re-adjust the exponent part of the REAL number
  344.       fstp  st1             ;get rid of the characteristic of the log
  345.       fmulp st1,st0                  ;->16-digit integer
  346. ;.endif
  347.         @@:
  348.  
  349.       fbstp [bcdstr]            ;->TBYTE containing the packed digits
  350.       fstsw ax                ;retrieve exception flags from FPU
  351.       fwait
  352.       shr   eax,1             ;test for invalid operation
  353.       jc    srcerr            ;clean-up and return error
  354.  
  355. ;------------------------------------------------------------------------------
  356. ; unpack BCD, the 10 bytes returned by the FPU being in the little-endian style
  357. ;------------------------------------------------------------------------------
  358.  
  359.       push  ecx
  360.       push  esi
  361.       push  edi
  362.       lea   esi,[bcdstr+9]      ;go to the most significant byte (sign byte)
  363.       lea   edi,[unpacked]
  364.       mov   eax,3020h
  365.       mov   cl,byte [esi]  ;sign byte
  366. ;      .if   cl == 80h
  367.         cmp cl,0x80
  368.         jne @f
  369.             mov   al,"-"      ;insert sign if negative number
  370. ;      .endif
  371.         @@:
  372.       stosw
  373.       mov   ecx,9
  374.    @@:
  375.       dec   esi
  376.       movzx eax,byte [esi]
  377.       ror   ax,4
  378.       ror   ah,4
  379.       add   ax,3030h
  380.       stosw
  381.       dec   ecx
  382.       jnz   @B
  383.  
  384.       mov   edi,[lpDest]
  385.       lea   esi,[unpacked]
  386.       test  [uID],STR_SCI       ;scientific notation?
  387.       jnz   scientific
  388.  
  389. ;************************
  390. ; REGULAR STRING NOTATION
  391. ;************************
  392.  
  393. ;------------------------------
  394. ; check if padding is specified
  395. ;------------------------------
  396.  
  397.       mov   ecx,[Padding]
  398.       or    ecx,ecx           ;check if padding is specified
  399.       jz    nopadding
  400.      
  401.       mov   edx,2             ;at least 1 integer + sign
  402.       mov   eax,[esize]
  403.       or    eax,eax
  404.       js    @F                ;only 1 integer digit if size is < 1
  405.       add   edx,eax           ;->number of integer digits
  406.    @@:
  407.       sub   ecx,edx
  408.       jle   nopadding
  409.       mov   al," "
  410.       rep   stosb
  411.  
  412. nopadding:
  413.       pushfd                  ;save padding flags
  414.       movsb                   ;insert sign
  415.       mov   ecx,1             ;at least 1 integer digit
  416.       mov   eax,[esize]
  417.       or    eax,eax           ;is size negative (i.e. number smaller than 1)
  418.       js    @F
  419.       add   ecx,eax
  420.    @@:
  421.       mov   eax,[Decimal]
  422.       add   eax,ecx           ;->total number of digits to be displayed
  423.       sub   eax,19
  424.       sub   esi,eax           ;address of 1st digit to be displayed
  425.       pop   eax               ;retrieve padding flags in EAX
  426. ;      .if   byte ptr[esi-1] == "1"
  427.         cmp byte [esi-1],"1"
  428.         jne @f
  429.             dec   esi
  430.             inc   ecx
  431.             push  eax         ;transfer padding flags through stack
  432.             popfd             ;retrieve padding flags
  433.             jle   @F          ;no padding was necessary
  434.             dec   edi         ;adjust for one less padding byte
  435. ;      .endif
  436.         @@:
  437.    @@:
  438.       rep   movsb             ;copy required integer digits
  439.       mov   ecx,[Decimal]
  440.       or    ecx,ecx
  441.       jz    @F
  442.       mov   al,"."
  443.       stosb
  444.       rep   movsb             ;copy required decimal digits
  445.    @@:
  446.       jmp   finish
  447.  
  448. ;********************
  449. ; SCIENTIFIC NOTATION
  450. ;********************
  451.  
  452. scientific:
  453.       movsb                   ;insert sign
  454.       mov   ecx,[Decimal]
  455.       mov   eax,18
  456.       sub   eax,ecx
  457.       add   esi,eax
  458.       cmp   byte [esi-1],"1"
  459.       pushfd                  ;save flags for extra "1"
  460.       jnz   @F
  461.       dec   esi
  462.    @@:
  463.       movsb                   ;copy the integer
  464.       mov   al,"."
  465.       stosb
  466.       rep   movsb             ;copy the decimal digits
  467.  
  468.       mov   al,"E"
  469.       stosb
  470.       mov   al,"+"
  471.       mov   ecx,[esize]
  472.       popfd                   ;retrieve flags for extra "1"
  473.       jnz   @F                ;no extra "1"
  474.       inc   ecx               ;adjust exponent
  475.    @@:
  476.       or    ecx,ecx
  477.       jns   @F
  478.       mov   al,"-"
  479.       neg   ecx               ;make number positive
  480.    @@:
  481.       stosb                   ;insert proper sign
  482.  
  483. ;Note: the absolute value of the size could not exceed 4931
  484.      
  485.       mov   eax,ecx
  486.       mov   cl,100
  487.       div   cl                ;->thousands & hundreds in AL, tens & units in AH
  488.       push  eax
  489.       and   eax,0ffh          ;keep only the thousands & hundreds
  490.       mov   cl,10
  491.       div   cl                ;->thousands in AL, hundreds in AH
  492.       add   ax,3030h          ;convert to characters
  493.       stosw                   ;insert them
  494.       pop   eax
  495.       shr   eax,8             ;get the tens & units in AL
  496.       div   cl                ;tens in AL, units in AH
  497.       add   ax,3030h          ;convert to characters
  498.       stosw                   ;insert them
  499.  
  500. finish:
  501.       xor   eax,eax
  502.       stosb                   ;string terminating 0
  503.       pop   edi
  504.       pop   esi
  505.       pop   ecx
  506.  
  507.       frstor [content]
  508.  
  509.       or    al,1              ;to insure EAX!=0
  510.       ret
  511.      
  512. endp
  513.  
  514. ; #########################################################################
  515.  
  516.  
  517.  align 4
  518.  
  519. ; #########################################################################
  520. ;                             FpuCos
  521. ;##########################################################################
  522.   ;
  523.   ;                           cos(Src) -> Dest
  524. FpuCos:
  525.         test [flags],(1 shl 30)
  526.         jz @f                   ;jump if angle already in radians
  527.         fldpi                   ;load pi (3.14159...) on FPU
  528.         fmulp
  529.         test [flags],(1 shl 31)
  530.         jnz .1
  531.         pushd 200
  532.         jmp .2
  533. .1:     pushd 180
  534. .2:     fidiv dword [esp]       ;value now in radians
  535.         fwait
  536.         add esp,4               ;clean the stack
  537. @@:     fldpi
  538.         fadd  st,st             ;->2pi
  539.         fxch
  540.  
  541. @@:     fprem                   ;reduce the angle
  542.         fcos
  543.         fstsw ax                ;retrieve exception flags from FPU
  544.         fwait
  545.         shr al,1                ;test for invalid operation
  546.         sahf                    ;transfer to the CPU flags
  547.         jpe     @B              ;reduce angle again if necessary
  548.         fstp st1                ;get rid of the 2pi
  549. ret
  550.  
  551.  align 4
  552. ; #########################################################################
  553. ;                             FpuSin
  554. ;##########################################################################
  555.   ;
  556.   ;                       sin(Src) -> Dest
  557. FpuSin:
  558.         test [flags],(1 shl 30)
  559.         jz @f                   ;jump if angle already in radians
  560.         fldpi                   ;load pi (3.14159...) on FPU
  561.         fmulp
  562.         test [flags],(1 shl 31)
  563.         jnz .1
  564.         pushd 200
  565.         jmp .2
  566. .1:     pushd 180
  567. .2:     fidiv dword [esp]       ;value now in radians
  568.         fwait
  569.         add esp,4               ;clean the stack
  570.    @@:
  571.         fldpi
  572.         fadd  st,st             ;->2pi
  573.         fxch
  574.  
  575.         fprem                   ;reduce the angle
  576.         fsin
  577.         fstp  st1             ;get rid of the 2pi
  578. ret
  579.  
  580.  align 4
  581. ; #########################################################################
  582. ;                             FpuArctan
  583. ;##########################################################################
  584.   ;
  585.   ;                       atan(Src) -> Dest
  586. FpuArctan:
  587.         fld1
  588.         fpatan
  589.         test [flags],(1 shl 30)
  590.         jz @F                   ;jump if angle is required in radians
  591.         test [flags],(1 shl 31)
  592.         jnz .1
  593.         pushd 200
  594.         jmp .2
  595. .1:     pushd 180
  596. .2:     fimul dword [esp]       ;*180 degrees
  597.         fldpi                   ;load pi (3.14159...) on FPU
  598.         fdivp                   ;*180/pi, angle now in degrees
  599.         add esp,4               ;clean CPU stack
  600.  
  601.         ftst                    ;check for negative angle
  602.         fstsw ax                ;retrieve status word from FPU
  603.         fwait
  604.         sahf
  605.         jnc  @F                 ;jump if positive number
  606.         test [flags],(1 shl 31)
  607.         jnz .3
  608.         pushd 400
  609.         jmp .4
  610. .3:     pushd 360
  611. .4:     fiadd dword [esp]       ;angle now 0-360
  612.         fwait
  613.         add esp,4                       ;clean CPU stack
  614.      
  615. @@:
  616.         ret
  617.  
  618.  align 4
  619. ; #########################################################################
  620. ;                             FpuTan
  621. ;##########################################################################
  622.  
  623.   ;                           a = tan(x)
  624. FpuTan:
  625.         fldpi                   ;load pi (3.14159...) on FPU
  626.         fadd  st,st             ;->2pi
  627.         fxch
  628.         test [flags],(1 shl 30)
  629.         jz @F                   ;jump if angle already in radians
  630.         test [flags],(1 shl 31)
  631.         jnz .1
  632.         pushd 400
  633.         jmp .2
  634. .1:     pushd 360
  635. .2:     fmul st,st1
  636.         fidiv dword [esp]       ;value now in radians
  637.         pop eax                 ;clean the stack
  638. @@:     fprem                   ;reduce the angle
  639.         fptan
  640.  
  641.         fstp st                 ;get rid of the 1
  642.         fstp st1                ;get rid of the 2pi
  643. ret
  644.  
  645.  align 4
  646. ; #########################################################################
  647. ;                             FpuArccos
  648. ;##########################################################################
  649.   ;                                sqrt(1-Src^2)
  650.   ;               acos(Src) = atan -------------  -> Dest
  651.   ;                                     Src
  652.  
  653. FpuArccos:
  654.         fld st                  ;copy cosine value
  655.         fmul st0,st1                    ;cos^2
  656.         fld1
  657.         fsubrp                  ;1-cos^2 = sin^2
  658.         fsqrt                   ;->sin
  659.         fxch
  660.         fpatan                  ;i.e. arctan(sin/cos)
  661.  
  662.         test [flags],(1 shl 30)
  663.         jz @F                   ;jump if angle is required in radians
  664.         test [flags],(1 shl 31)
  665.         jnz .1
  666.         pushd 200
  667.         jmp .2
  668. .1:     pushd 180
  669. .2:     fimul dword [esp]       ;*180 degrees
  670.         fldpi                   ;load pi (3.14159...) on FPU
  671.         fdivp                   ;*180/pi, angle now in degrees
  672.         pop eax                 ;clean CPU stack
  673. @@:
  674. ret
  675.  
  676.  align 4
  677. ; #########################################################################
  678. ;                             FpuArcsin
  679. ;##########################################################################
  680.   ;                                  Src
  681.   ;            asin(Src) = atan -------------  -> Dest
  682.   ;                             sqrt(1-Src^2)
  683. FpuArcsin:
  684.         fld st0                 ;copy sine value
  685.         fmul st0,st0                    ;sin^2
  686.         fld1
  687.         fsubrp                  ;1-sin^2 = cos^2
  688.         fsqrt                   ;->cos
  689.         fpatan                  ;i.e. arctan(sin/cos) = arcsin
  690.         test [flags],(1 shl 30)
  691.         jz @F                   ;jump if angle is required in radians
  692.         test [flags],(1 shl 31)
  693.         jnz .1
  694.         pushd 200
  695.         jmp .2
  696. .1:     pushd 180
  697. .2:     fimul dword [esp]       ;*180 degrees
  698.         fldpi                   ;load pi (3.14159...) on FPU
  699.         fdivrp                  ;*180/pi, angle now in degrees
  700.         add esp,4               ;clean CPU stack
  701. @@:
  702.         ret
  703.  
  704.  align 4
  705. ; #########################################################################
  706. ;                             FpuEexpX
  707. ;##########################################################################
  708.  
  709.   ;              e^(Src) = antilog2[ log2(e) * Src ] -> Dest
  710.  
  711. FpuEexpX:
  712.  
  713.       fldl2e                  ;->log2(e)
  714.       fmulp                    ;->log2(e)*Src
  715.      
  716.       fld   st0             ;copy the logarithm
  717.       frndint                 ;keep only the characteristic
  718.       fsub  st1,st          ;keeps only the mantissa
  719.       fxch                    ;get the mantissa on top
  720.  
  721.       f2xm1                   ;->2^(mantissa)-1
  722.       fld1
  723.       faddp                    ;add 1 back
  724.  
  725.       fscale                  ;scale it with the characteristic
  726.      
  727.       fstp  st1             ;get rid of the characteristic
  728. ret
  729.  
  730.  align 4
  731. ; #########################################################################
  732. ;                             FpuXexpY
  733. ;##########################################################################
  734.  
  735.   ;            Src1^Src2 = antilog2[ log2(Src1) * Src2 ] -> Dest
  736.  
  737. FpuXexpY:
  738.       fxch                    ;set up FPU registers for next operation
  739.       fyl2x                   ;->log2(Src1)*exponent
  740.      
  741.       fld   st0             ;copy the logarithm
  742.       frndint                 ;keep only the characteristic
  743.       fsub  st1,st          ;keeps only the mantissa
  744.       fxch                    ;get the mantissa on top
  745.  
  746.       f2xm1                   ;->2^(mantissa)-1
  747.       fld1
  748.       faddp                    ;add 1 back
  749.  
  750.       fscale                  ;scale it with the characteristic
  751.      
  752.       fstp  st1             ;overwrite the characteristic
  753. ret
  754.  
  755.  
  756. if 0
  757. exp:
  758. .N equ 10
  759.         xor eax,eax
  760.         mov ecx,.N
  761.         fld1
  762. .0:     dec ecx
  763.         jz .end
  764.         mov eax,.N
  765.         sub eax,ecx
  766.         mov [.d],eax
  767.         fild [.d]
  768. @@:     dec eax
  769.         jz @f
  770.         mov [.d],eax
  771.         fild [.d]
  772.         fmulp
  773.         jmp @b
  774. @@:     mov eax,.N
  775.         sub eax,ecx
  776.         fld st2
  777. @@:     dec eax
  778.         jz @f
  779.         fld st3
  780.         fmulp
  781.         jmp @b
  782. @@:     fdivrp
  783.         faddp
  784.         jmp .0
  785. .end:   fxch
  786.         fstp st0
  787. ret
  788. .d dd 0
  789. endf