Merge from amd64-branch:
[reactos.git] / reactos / lib / sdk / crt / math / i386 / pow_asm.s
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Run-Time Library
5 * FILE: lib/rtl/i386/pow.S
6 * PROGRAMER: Alex Ionescu (alex@relsoft.net)
7 *
8 * Copyright (C) 2002 Michael Ringgaard.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the project nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES// LOSS OF USE, DATA, OR PROFITS// OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 .globl _pow
38
39 /* DATA ********************************************************************/
40
41 fzero:
42 .long 0 // Floating point zero
43 .long 0 // Floating point zero
44
45 .intel_syntax noprefix
46
47 /* FUNCTIONS ***************************************************************/
48
49 _pow:
50 push ebp
51 mov ebp,esp
52 sub esp,12 // Allocate temporary space
53 push edi // Save register edi
54 push eax // Save register eax
55 mov dword ptr [ebp-12],0 // Set negation flag to zero
56 fld qword ptr [ebp+16] // Load real from stack
57 fld qword ptr [ebp+8] // Load real from stack
58 mov edi,offset flat:fzero // Point to real zero
59 fcom qword ptr [edi] // Compare x with zero
60 fstsw ax // Get the FPU status word
61 mov al,ah // Move condition flags to AL
62 lahf // Load Flags into AH
63 and al, 0b01000101 // Isolate C0, C2 and C3
64 and ah, 0b10111010 // Turn off CF, PF and ZF
65 or ah,al // Set new CF, PF and ZF
66 sahf // Store AH into Flags
67 jb __fpow1 // Re-direct if x < 0
68 ja __fpow2 // Re-direct if x > 0
69 fxch // Swap st, st(1)
70 fcom qword ptr [edi] // Compare y with zero
71 fxch // Restore x as top of stack
72 fstsw ax // Get the FPU status word
73 mov al,ah // Move condition flags to AL
74 lahf // Load Flags into AH
75 and al, 0b01000101 // Isolate C0, C2 and C3
76 and ah, 0b10111010 // Turn off CF, PF and ZF
77 or ah,al // Set new CF, PF and ZF
78 sahf // Store AH into Flags
79 jmp __fpow2 // Re-direct
80 __fpow1: fxch // Put y on top of stack
81 fld st // Duplicate y as st(1)
82 frndint // Round to integer
83 fxch // Put y on top of stack
84 fcomp // y = int(y) ?
85 fstsw ax // Get the FPU status word
86 mov al,ah // Move condition flags to AL
87 lahf // Load Flags into AH
88 and al, 0b01000101 // Isolate C0, C2 and C3
89 and ah, 0b10111010 // Turn off CF, PF and ZF
90 or ah,al // Set new CF, PF and ZF
91 sahf // Store AH into Flags
92 jne __fpow4 // Proceed if y = int(y)
93 fist dword ptr [ebp-12] // Store y as integer
94 and dword ptr [ebp-12],1 // Set bit if y is odd
95 fxch // Put x on top of stack
96 fabs // x = |x|
97 __fpow2: fldln2 // Load log base e of 2
98 fxch st(1) // Exchange st, st(1)
99 fyl2x // Compute the natural log(x)
100 fmulp // Compute y * ln(x)
101 fldl2e // Load log base 2(e)
102 fmulp st(1),st // Multiply x * log base 2(e)
103 fst st(1) // Push result
104 frndint // Round to integer
105 fsub st(1),st // Subtract
106 fxch // Exchange st, st(1)
107 f2xm1 // Compute 2 to the (x - 1)
108 fld1 // Load real number 1
109 faddp // 2 to the x
110 fscale // Scale by power of 2
111 fstp st(1) // Set new stack top and pop
112 test dword ptr [ebp-12],1 // Negation required ?
113 jz __fpow3 // No, re-direct
114 fchs // Negate the result
115 __fpow3: fstp qword ptr [ebp-8] // Save (double)pow(x, y)
116 fld qword ptr [ebp-8] // Load (double)pow(x, y)
117 __fpow4: pop eax // Restore register eax
118 pop edi // Restore register edi
119 mov esp,ebp // Deallocate temporary space
120 pop ebp
121 ret