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