- Implement RtlPrefectMemoryNonTemporal. Patch by Patrick Baggett <baggett.patrick...
[reactos.git] / reactos / lib / rtl / i386 / math_asm.S
index ca1d6ca..3ec7c07 100644 (file)
@@ -28,7 +28,7 @@
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\r
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * OR SERVICES// LOSS OF USE, DATA, OR PROFITS// OR BUSINESS INTERRUPTION)\r
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF \r
 .globl __alldiv\r
 .globl __aulldvrm\r
 .globl __alldvrm\r
+.globl _atan\r
+.globl _ceil\r
+.globl _cos\r
+.globl _fabs\r
+.globl _floor\r
+.globl _log\r
+.globl _pow\r
+.globl _sin\r
+.globl _sqrt\r
+.globl _tan\r
+.globl __fltused\r
+\r
+/* DATA ********************************************************************/\r
+\r
+fzero:\r
+        .long   0                       // Floating point zero\r
+        .long   0                       // Floating point zero\r
+\r
+__fltused:\r
+        .long 0x9875\r
 \r
 /* FUNCTIONS ***************************************************************/\r
 \r
 /*\r
  * long long\r
- * __alldiv(long long Dividend, long long Divisor);\r
+ * __alldiv(long long Dividend, long long Divisor)//\r
  *\r
  * Parameters:\r
  *   [ESP+04h] - long long Dividend\r
@@ -71,7 +91,7 @@ __alldiv:
 \r
 /*\r
  * long long\r
- * __allmul(long long Multiplier, long long Multiplicand);\r
+ * __allmul(long long Multiplier, long long Multiplicand)//\r
  *\r
  * Parameters:\r
  *   [ESP+04h] - long long Multiplier\r
@@ -114,7 +134,7 @@ __allmul:
 \r
 /*\r
  * unsigned long long\r
- * __aullrem(unsigned long long Dividend, unsigned long long Divisor);\r
+ * __aullrem(unsigned long long Dividend, unsigned long long Divisor)//\r
  *\r
  * Parameters:\r
  *   [ESP+04h] - unsigned long long Dividend\r
@@ -132,7 +152,7 @@ __aullrem:
 \r
 /*\r
  * long long\r
- * __allshl(long long Value, unsigned char Shift);\r
+ * __allshl(long long Value, unsigned char Shift)//\r
  *\r
  * Parameters:\r
  *   EDX:EAX - signed long long value to be shifted left\r
@@ -154,7 +174,7 @@ __allshl:
 \r
 /*\r
  * long long\r
- * __allshr(long long Value, unsigned char Shift);\r
+ * __allshr(long long Value, unsigned char Shift)//\r
  *\r
  * Parameters:\r
  *   EDX:EAX - signed long long value to be shifted right\r
@@ -176,7 +196,7 @@ __allshr:
 \r
 /*\r
  * unsigned long long\r
- * __aulldiv(unsigned long long Dividend, unsigned long long Divisor);\r
+ * __aulldiv(unsigned long long Dividend, unsigned long long Divisor)//\r
  *\r
  * Parameters:\r
  *   [ESP+04h] - unsigned long long Dividend\r
@@ -194,7 +214,7 @@ __aulldiv:
 \r
 /*\r
  * unsigned long long\r
- * __aullshr(unsigned long long Value, unsigned char Shift);\r
+ * __aullshr(unsigned long long Value, unsigned char Shift)//\r
  *\r
  * Parameters:\r
  *   EDX:EAX - unsigned long long value to be shifted right\r
@@ -215,7 +235,7 @@ __aullshr:
        \r
 /*\r
  * long long\r
- * __allrem(long long Dividend, long long Divisor);\r
+ * __allrem(long long Dividend, long long Divisor)//\r
  *\r
  * Parameters:\r
  *   [ESP+04h] - long long Dividend\r
@@ -629,3 +649,188 @@ __aulldvrm:
 \r
         ret     16\r
 \r
+_atan:\r
+        push    ebp\r
+        mov     ebp,esp\r
+        fld     qword ptr [ebp+8]       // Load real from stack\r
+        fld1                            // Load constant 1\r
+        fpatan                          // Take the arctangent\r
+        pop     ebp\r
+        ret\r
+\r
+_ceil:\r
+        push    ebp\r
+        mov     ebp,esp\r
+        sub     esp,4                   // Allocate temporary space\r
+        fld     qword ptr [ebp+8]       // Load real from stack\r
+        fstcw   [ebp-2]                 // Save control word\r
+        fclex                           // Clear exceptions\r
+        mov     word ptr [ebp-4],0xb63  // Rounding control word\r
+        fldcw   [ebp-4]                 // Set new rounding control\r
+        frndint                         // Round to integer\r
+        fclex                           // Clear exceptions\r
+        fldcw   [ebp-2]                 // Restore control word\r
+        mov     esp,ebp                 // Deallocate temporary space\r
+        pop     ebp\r
+        ret\r
+\r
+_cos:\r
+        push    ebp\r
+        mov     ebp,esp                 // Point to the stack frame\r
+        fld     qword ptr [ebp+8]       // Load real from stack\r
+        fcos                            // Take the cosine\r
+        pop     ebp\r
+        ret\r
+\r
+_fabs:\r
+        push    ebp\r
+        mov     ebp,esp\r
+        fld     qword ptr [ebp+8]       // Load real from stack\r
+        fabs                            // Take the absolute value\r
+        pop     ebp\r
+        ret\r
+\r
+_floor:\r
+        push    ebp\r
+        mov     ebp,esp\r
+        sub     esp,4                   // Allocate temporary space\r
+        fld     qword ptr [ebp+8]       // Load real from stack\r
+        fstcw   [ebp-2]                 // Save control word\r
+        fclex                           // Clear exceptions\r
+        mov     word ptr [ebp-4],0x763  // Rounding control word\r
+        fldcw   [ebp-4]                 // Set new rounding control\r
+        frndint                         // Round to integer\r
+        fclex                           // Clear exceptions\r
+        fldcw   [ebp-2]                 // Restore control word\r
+        mov     esp,ebp\r
+        pop     ebp\r
+        ret\r
+\r
+_log:\r
+        push    ebp\r
+        mov     ebp,esp\r
+        fld     qword ptr [ebp+8]       // Load real from stack\r
+        fldln2                          // Load log base e of 2\r
+        fxch    st(1)                   // Exchange st, st(1)\r
+        fyl2x                           // Compute the natural log(x)\r
+        pop     ebp\r
+        ret\r
+\r
+_pow:\r
+        push    ebp\r
+        mov     ebp,esp\r
+        sub     esp,12                  // Allocate temporary space\r
+        push    edi                     // Save register edi\r
+        push    eax                     // Save register eax\r
+        mov     dword ptr [ebp-12],0    // Set negation flag to zero\r
+        fld     qword ptr [ebp+16]      // Load real from stack\r
+        fld     qword ptr [ebp+8]       // Load real from stack\r
+        mov     edi,offset flat:fzero   // Point to real zero\r
+        fcom    qword ptr [edi]         // Compare x with zero\r
+        fstsw   ax                      // Get the FPU status word\r
+        mov     al,ah                   // Move condition flags to AL\r
+        lahf                            // Load Flags into AH\r
+        and     al,    0b01000101       // Isolate  C0, C2 and C3\r
+        and     ah,not 0b01000101       // Turn off CF, PF and ZF\r
+        or      ah,al                   // Set new  CF, PF and ZF\r
+        sahf                            // Store AH into Flags\r
+        jb      __fpow1                 // Re-direct if x < 0\r
+        ja      __fpow3                 // Re-direct if x > 0\r
+        fxch                            // Swap st, st(1)\r
+        fcom    qword ptr [edi]         // Compare y with zero\r
+        fxch                            // Restore x as top of stack\r
+        fstsw   ax                      // Get the FPU status word\r
+        mov     al,ah                   // Move condition flags to AL\r
+        lahf                            // Load Flags into AH\r
+        and     al,    0b01000101       // Isolate  C0, C2 and C3\r
+        and     ah,not 0b01000101       // Turn off CF, PF and ZF\r
+        or      ah,al                   // Set new  CF, PF and ZF\r
+        sahf                            // Store AH into Flags\r
+        ja      __fpow3                 // Re-direct if y > 0\r
+        fstp    st(1)                   // Set new stack top and pop\r
+        mov     eax,1                   // Set domain error (EDOM)\r
+        jmp     __fpow5                 // End of case\r
+__fpow1:        fxch                            // Put y on top of stack\r
+        fld    st                       // Duplicate y as st(1)\r
+        frndint                         // Round to integer\r
+        fxch                            // Put y on top of stack\r
+        fcomp                           // y = int(y) ?\r
+        fstsw   ax                      // Get the FPU status word\r
+        mov     al,ah                   // Move condition flags to AL\r
+        lahf                            // Load Flags into AH\r
+        and     al,    0b01000101       // Isolate  C0, C2 and C3\r
+        and     ah,not 0b01000101       // Turn off CF, PF and ZF\r
+        or      ah,al                   // Set new  CF, PF and ZF\r
+        sahf                            // Store AH into Flags\r
+        je      __fpow2                 // Proceed if y = int(y)\r
+        fstp    st(1)                   // Set new stack top and pop\r
+        fldz                            // Set result to zero\r
+        fstp    st(1)                   // Set new stack top and pop\r
+        mov     eax,1                   // Set domain error (EDOM)\r
+        jmp     __fpow5                 // End of case\r
+__fpow2:        fist    dword ptr [ebp-12]      // Store y as integer\r
+        and     dword ptr [ebp-12],1    // Set bit if y is odd\r
+        fxch                            // Put x on top of stack\r
+        fabs                            // x = |x|\r
+__fpow3:        fldln2                          // Load log base e of 2\r
+        fxch    st(1)                   // Exchange st, st(1)\r
+        fyl2x                           // Compute the natural log(x)\r
+        fmulp                           // Compute y * ln(x)\r
+        fldl2e                          // Load log base 2(e)\r
+        fmulp   st(1),st                // Multiply x * log base 2(e)\r
+        fst     st(1)                   // Push result\r
+        frndint                         // Round to integer\r
+        fsub    st(1),st                // Subtract\r
+        fxch                            // Exchange st, st(1)\r
+        f2xm1                           // Compute 2 to the (x - 1)\r
+        fld1                            // Load real number 1\r
+        faddp                           // 2 to the x\r
+        fscale                          // Scale by power of 2\r
+        fstp    st(1)                   // Set new stack top and pop\r
+        test    dword ptr [ebp-12],1    // Negation required ?\r
+        jz      __fpow4                 // No, re-direct\r
+        fchs                            // Negate the result\r
+__fpow4:        fstp    qword ptr [ebp-8]       // Save (double)pow(x, y)\r
+        fld     qword ptr [ebp-8]       // Load (double)pow(x, y)\r
+        fxam                            // Examine st\r
+        fstsw   ax                      // Get the FPU status word\r
+        cmp     ah,5                    // Infinity ?\r
+        jne     __fpow6                 // No, end of case\r
+        mov     eax,2                   // Set range error (ERANGE)\r
+                                        // Get errno pointer offset\r
+__fpow5:        int     3\r
+        mov     edi,0                   // TODO: offset flat:__crt_errno\r
+        mov     edi,[edi]               // Get C errno variable pointer\r
+        mov     dword ptr [edi],eax     // Set errno\r
+__fpow6:        pop     eax                     // Restore register eax\r
+        pop     edi                     // Restore register edi\r
+        mov     esp,ebp                 // Deallocate temporary space\r
+        pop     ebp\r
+        ret\r
+\r
+_sin:\r
+        push    ebp                     // Save register bp\r
+        mov     ebp,esp                 // Point to the stack frame\r
+        fld     qword ptr [ebp+8]       // Load real from stack\r
+        fsin                            // Take the sine\r
+        pop     ebp                     // Restore register bp\r
+        ret\r
+\r
+_sqrt:\r
+        push    ebp\r
+        mov     ebp,esp\r
+        fld     qword ptr [ebp+8]       // Load real from stack\r
+        fsqrt                           // Take the square root\r
+        pop     ebp\r
+        ret\r
+\r
+_tan:\r
+        push    ebp\r
+        mov     ebp,esp\r
+        sub     esp,4                   // Allocate temporary space\r
+        fld     qword ptr [ebp+8]       // Load real from stack\r
+        fptan                           // Take the tangent\r
+        fstp    dword ptr [ebp-4]       // Throw away the constant 1\r
+        mov     esp,ebp                 // Deallocate temporary space\r
+        pop     ebp\r
+        ret\r