renamed .S files so msvc does not try to compile the .c files with the same name...
[reactos.git] / reactos / lib / rtl / i386 / math_asm.S
diff --git a/reactos/lib/rtl/i386/math_asm.S b/reactos/lib/rtl/i386/math_asm.S
new file mode 100644 (file)
index 0000000..ca1d6ca
--- /dev/null
@@ -0,0 +1,631 @@
+/*\r
+ * COPYRIGHT:         See COPYING in the top level directory\r
+ * PROJECT:           ReactOS kernel\r
+ * PURPOSE:           Run-Time Library\r
+ * FILE:              lib/rtl/i386/math.S\r
+ * PROGRAMER:         Alex Ionescu (alex@relsoft.net)\r
+ *                    Eric Kohl (ekohl@rz-online.de)\r
+ *\r
+ * Copyright (C) 2002 Michael Ringgaard.\r
+ * All rights reserved. \r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * \r
+ * 1. Redistributions of source code must retain the above copyright \r
+ *    notice, this list of conditions and the following disclaimer.  \r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ *    notice, this list of conditions and the following disclaimer in the\r
+ *    documentation and/or other materials provided with the distribution.  \r
+ * 3. Neither the name of the project nor the names of its contributors\r
+ *    may be used to endorse or promote products derived from this software\r
+ *    without specific prior written permission. \r
+\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * 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
+ * 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
+ * SUCH DAMAGE.\r
+ */\r
\r
+/* GLOBALS ****************************************************************/\r
+\r
+.globl __ftol\r
+.globl __aullshr\r
+.globl __allrem\r
+.globl __aulldiv\r
+.globl __allshr\r
+.globl __allshl\r
+.globl __aullrem\r
+.globl __allmul\r
+.globl __alldiv\r
+.globl __aulldvrm\r
+.globl __alldvrm\r
+\r
+/* FUNCTIONS ***************************************************************/\r
+\r
+/*\r
+ * long long\r
+ * __alldiv(long long Dividend, long long Divisor);\r
+ *\r
+ * Parameters:\r
+ *   [ESP+04h] - long long Dividend\r
+ *   [ESP+0Ch] - long long Divisor\r
+ * Registers:\r
+ *   Unknown\r
+ * Returns:\r
+ *   EDX:EAX - long long quotient (Dividend/Divisor)\r
+ * Notes:\r
+ *   Routine removes the arguments from the stack.\r
+ */\r
+__alldiv:\r
+       call    ___divdi3\r
+       ret             $0x10\r
+\r
+/*\r
+ * long long\r
+ * __allmul(long long Multiplier, long long Multiplicand);\r
+ *\r
+ * Parameters:\r
+ *   [ESP+04h] - long long Multiplier\r
+ *   [ESP+0Ch] - long long Multiplicand\r
+ * Registers:\r
+ *   Unknown\r
+ * Returns:\r
+ *   EDX:EAX - long long product (Multiplier*Multiplicand)\r
+ * Notes:\r
+ *   Routine removes the arguments from the stack.\r
+ */\r
+__allmul:\r
+       pushl   %ebp\r
+       movl    %esp, %ebp\r
+       pushl   %edi\r
+       pushl   %esi\r
+       pushl   %ebx\r
+       subl    $12, %esp\r
+       movl    16(%ebp), %ebx\r
+       movl    8(%ebp), %eax\r
+       mull    %ebx\r
+       movl    20(%ebp), %ecx\r
+       movl    %eax, -24(%ebp)\r
+       movl    8(%ebp), %eax\r
+       movl    %edx, %esi\r
+       imull   %ecx, %eax\r
+       addl    %eax, %esi\r
+       movl    12(%ebp), %eax\r
+       imull   %eax, %ebx\r
+       leal    (%ebx,%esi), %eax\r
+       movl    %eax, -20(%ebp)\r
+       movl    -24(%ebp), %eax\r
+       movl    -20(%ebp), %edx\r
+       addl    $12, %esp\r
+       popl    %ebx\r
+       popl    %esi\r
+       popl    %edi\r
+       popl    %ebp\r
+       ret             $0x10\r
+\r
+/*\r
+ * unsigned long long\r
+ * __aullrem(unsigned long long Dividend, unsigned long long Divisor);\r
+ *\r
+ * Parameters:\r
+ *   [ESP+04h] - unsigned long long Dividend\r
+ *   [ESP+0Ch] - unsigned long long Divisor\r
+ * Registers:\r
+ *   Unknown\r
+ * Returns:\r
+ *   EDX:EAX - unsigned long long remainder (Dividend%Divisor)\r
+ * Notes:\r
+ *   Routine removes the arguments from the stack.\r
+ */\r
+__aullrem:\r
+       call    ___umoddi3\r
+       ret     $16\r
+\r
+/*\r
+ * long long\r
+ * __allshl(long long Value, unsigned char Shift);\r
+ *\r
+ * Parameters:\r
+ *   EDX:EAX - signed long long value to be shifted left\r
+ *   CL      - number of bits to shift by\r
+ * Registers:\r
+ *   Destroys CL\r
+ * Returns:\r
+ *   EDX:EAX - shifted value\r
+ */\r
+__allshl:\r
+       shldl   %cl, %eax, %edx\r
+       sall    %cl, %eax\r
+       andl    $32, %ecx\r
+       je              1f\r
+       movl    %eax, %edx\r
+       xorl    %eax, %eax\r
+1:\r
+       ret\r
+\r
+/*\r
+ * long long\r
+ * __allshr(long long Value, unsigned char Shift);\r
+ *\r
+ * Parameters:\r
+ *   EDX:EAX - signed long long value to be shifted right\r
+ *   CL      - number of bits to shift by\r
+ * Registers:\r
+ *   Destroys CL\r
+ * Returns:\r
+ *   EDX:EAX - shifted value\r
+ */\r
+__allshr:\r
+       shrdl   %cl, %edx, %eax\r
+       sarl    %cl, %edx\r
+       andl    $32, %ecx\r
+       je              1f\r
+       movl    %edx, %eax\r
+       sarl    $31, %edx\r
+1:\r
+       ret\r
+\r
+/*\r
+ * unsigned long long\r
+ * __aulldiv(unsigned long long Dividend, unsigned long long Divisor);\r
+ *\r
+ * Parameters:\r
+ *   [ESP+04h] - unsigned long long Dividend\r
+ *   [ESP+0Ch] - unsigned long long Divisor\r
+ * Registers:\r
+ *   Unknown\r
+ * Returns:\r
+ *   EDX:EAX - unsigned long long quotient (Dividend/Divisor)\r
+ * Notes:\r
+ *   Routine removes the arguments from the stack.\r
+ */\r
+__aulldiv:\r
+       call    ___udivdi3\r
+       ret     $16\r
+\r
+/*\r
+ * unsigned long long\r
+ * __aullshr(unsigned long long Value, unsigned char Shift);\r
+ *\r
+ * Parameters:\r
+ *   EDX:EAX - unsigned long long value to be shifted right\r
+ *   CL      - number of bits to shift by\r
+ * Registers:\r
+ *   Destroys CL\r
+ * Returns:\r
+ *   EDX:EAX - shifted value\r
+ */\r
+__aullshr:\r
+       shrdl   %cl, %edx, %eax\r
+       shrl    %cl, %edx\r
+       andl    $32, %ecx\r
+       je              1f\r
+       movl    %edx, %eax\r
+1:\r
+       ret\r
+       \r
+/*\r
+ * long long\r
+ * __allrem(long long Dividend, long long Divisor);\r
+ *\r
+ * Parameters:\r
+ *   [ESP+04h] - long long Dividend\r
+ *   [ESP+0Ch] - long long Divisor\r
+ * Registers:\r
+ *   Unknown\r
+ * Returns:\r
+ *   EDX:EAX - long long remainder (Dividend/Divisor)\r
+ * Notes:\r
+ *   Routine removes the arguments from the stack.\r
+ */\r
+__allrem:\r
+       call    ___moddi3\r
+       ret             $16\r
+       \r
+.intel_syntax noprefix\r
+\r
+/*\r
+ * This routine is called by MSVC-generated code to convert from floating point\r
+ * to integer representation. The floating point number to be converted is\r
+ * on the top of the floating point stack.\r
+ */\r
+__ftol:\r
+    /* Set up stack frame */\r
+    push ebp\r
+    mov ebp, esp\r
+    \r
+    /* Set "round towards zero" mode */\r
+    fstcw [ebp-2]\r
+    wait\r
+    mov ax, [ebp-2]\r
+    or ah, 0xC\r
+    mov [ebp-4], ax\r
+    fldcw [ebp-4]\r
+    \r
+    /* Do the conversion */\r
+    fistp qword ptr [ebp-12]\r
+    \r
+    /* Restore rounding mode */\r
+    fldcw [ebp-2]\r
+    \r
+    /* Return value */\r
+    mov eax, [ebp-12]\r
+    mov edx, [ebp-8]\r
+    \r
+    /* Remove stack frame and return*/\r
+    leave\r
+    ret\r
+\r
+__alldvrm:\r
+        push    edi\r
+        push    esi\r
+        push    ebp\r
+\r
+// Set up the local stack and save the index registers.  When this is done\r
+// the stack frame will look as follows (assuming that the expression a/b will\r
+// generate a call to alldvrm(a, b)):\r
+//\r
+//               -----------------\r
+//               |               |\r
+//               |---------------|\r
+//               |               |\r
+//               |--divisor (b)--|\r
+//               |               |\r
+//               |---------------|\r
+//               |               |\r
+//               |--dividend (a)-|\r
+//               |               |\r
+//               |---------------|\r
+//               | return addr** |\r
+//               |---------------|\r
+//               |      EDI      |\r
+//               |---------------|\r
+//               |      ESI      |\r
+//               |---------------|\r
+//       ESP---->|      EBP      |\r
+//               -----------------\r
+//\r
+\r
+#define DVNDLO  [esp + 16]       // stack address of dividend (a)\r
+#define DVNDHI  [esp + 20]       // stack address of dividend (a)\r
+#define DVSRLO  [esp + 24]      // stack address of divisor (b)\r
+#define DVSRHI  [esp + 28]      // stack address of divisor (b)\r
+\r
+// Determine sign of the quotient (edi = 0 if result is positive, non-zero\r
+// otherwise) and make operands positive.\r
+// Sign of the remainder is kept in ebp.\r
+\r
+        xor     edi,edi         // result sign assumed positive\r
+        xor     ebp,ebp         // result sign assumed positive\r
+\r
+        mov     eax,DVNDHI // hi word of a\r
+        or      eax,eax         // test to see if signed\r
+        jge     short L1        // skip rest if a is already positive\r
+        inc     edi             // complement result sign flag\r
+        inc     ebp             // complement result sign flag\r
+        mov     edx,DVNDLO // lo word of a\r
+        neg     eax             // make a positive\r
+        neg     edx\r
+        sbb     eax,0\r
+        mov     DVNDHI,eax // save positive value\r
+        mov     DVNDLO,edx\r
+L1:\r
+        mov     eax,DVSRHI // hi word of b\r
+        or      eax,eax         // test to see if signed\r
+        jge     short L2        // skip rest if b is already positive\r
+        inc     edi             // complement the result sign flag\r
+        mov     edx,DVSRLO // lo word of a\r
+        neg     eax             // make b positive\r
+        neg     edx\r
+        sbb     eax,0\r
+        mov     DVSRHI,eax // save positive value\r
+        mov     DVSRLO,edx\r
+L2:\r
+\r
+//\r
+// Now do the divide.  First look to see if the divisor is less than 4194304K.\r
+// If so, then we can use a simple algorithm with word divides, otherwise\r
+// things get a little more complex.\r
+//\r
+// NOTE - eax currently contains the high order word of DVSR\r
+//\r
+\r
+        or      eax,eax         // check to see if divisor < 4194304K\r
+        jnz     short L3        // nope, gotta do this the hard way\r
+        mov     ecx,DVSRLO // load divisor\r
+        mov     eax,DVNDHI // load high word of dividend\r
+        xor     edx,edx\r
+        div     ecx             // eax <- high order bits of quotient\r
+        mov     ebx,eax         // save high bits of quotient\r
+        mov     eax,DVNDLO // edx:eax <- remainder:lo word of dividend\r
+        div     ecx             // eax <- low order bits of quotient\r
+        mov     esi,eax         // ebx:esi <- quotient\r
+//\r
+// Now we need to do a multiply so that we can compute the remainder.\r
+//\r
+        mov     eax,ebx         // set up high word of quotient\r
+        mul     dword ptr DVSRLO // HIWORD(QUOT) * DVSR\r
+        mov     ecx,eax         // save the result in ecx\r
+        mov     eax,esi         // set up low word of quotient\r
+        mul     dword ptr DVSRLO // LOWORD(QUOT) * DVSR\r
+        add     edx,ecx         // EDX:EAX = QUOT * DVSR\r
+        jmp     short L4        // complete remainder calculation\r
+\r
+//\r
+// Here we do it the hard way.  Remember, eax contains the high word of DVSR\r
+//\r
+\r
+L3:\r
+        mov     ebx,eax         // ebx:ecx <- divisor\r
+        mov     ecx,DVSRLO\r
+        mov     edx,DVNDHI // edx:eax <- dividend\r
+        mov     eax,DVNDLO\r
+L5:\r
+        shr     ebx,1           // shift divisor right one bit\r
+        rcr     ecx,1\r
+        shr     edx,1           // shift dividend right one bit\r
+        rcr     eax,1\r
+        or      ebx,ebx\r
+        jnz     short L5        // loop until divisor < 4194304K\r
+        div     ecx             // now divide, ignore remainder\r
+        mov     esi,eax         // save quotient\r
+\r
+//\r
+// We may be off by one, so to check, we will multiply the quotient\r
+// by the divisor and check the result against the orignal dividend\r
+// Note that we must also check for overflow, which can occur if the\r
+// dividend is close to 2**64 and the quotient is off by 1.\r
+//\r
+\r
+        mul     dword ptr DVSRHI // QUOT * DVSRHI\r
+        mov     ecx,eax\r
+        mov     eax,DVSRLO\r
+        mul     esi             // QUOT * DVSRLO\r
+        add     edx,ecx         // EDX:EAX = QUOT * DVSR\r
+        jc      short L6        // carry means Quotient is off by 1\r
+\r
+//\r
+// do long compare here between original dividend and the result of the\r
+// multiply in edx:eax.  If original is larger or equal, we are ok, otherwise\r
+// subtract one (1) from the quotient.\r
+//\r
+\r
+        cmp     edx,DVNDHI // compare hi words of result and original\r
+        ja      short L6        // if result > original, do subtract\r
+        jb      short L7        // if result < original, we are ok\r
+        cmp     eax,DVNDLO // hi words are equal, compare lo words\r
+        jbe     short L7        // if less or equal we are ok, else subtract\r
+L6:\r
+        dec     esi             // subtract 1 from quotient\r
+        sub     eax,DVSRLO // subtract divisor from result\r
+        sbb     edx,DVSRHI\r
+L7:\r
+        xor     ebx,ebx         // ebx:esi <- quotient\r
+\r
+L4:\r
+//\r
+// Calculate remainder by subtracting the result from the original dividend.\r
+// Since the result is already in a register, we will do the subtract in the\r
+// opposite direction and negate the result if necessary.\r
+//\r
+\r
+        sub     eax,DVNDLO // subtract dividend from result\r
+        sbb     edx,DVNDHI\r
+\r
+//\r
+// Now check the result sign flag to see if the result is supposed to be positive\r
+// or negative.  It is currently negated (because we subtracted in the 'wrong'\r
+// direction), so if the sign flag is set we are done, otherwise we must negate\r
+// the result to make it positive again.\r
+//\r
+\r
+        dec     ebp             // check result sign flag\r
+        jns     short L9        // result is ok, set up the quotient\r
+        neg     edx             // otherwise, negate the result\r
+        neg     eax\r
+        sbb     edx,0\r
+\r
+//\r
+// Now we need to get the quotient into edx:eax and the remainder into ebx:ecx.\r
+//\r
+L9:\r
+        mov     ecx,edx\r
+        mov     edx,ebx\r
+        mov     ebx,ecx\r
+        mov     ecx,eax\r
+        mov     eax,esi\r
+\r
+//\r
+// Just the cleanup left to do.  edx:eax contains the quotient.  Set the sign\r
+// according to the save value, cleanup the stack, and return.\r
+//\r
+\r
+        dec     edi             // check to see if result is negative\r
+        jnz     short L8        // if EDI == 0, result should be negative\r
+        neg     edx             // otherwise, negate the result\r
+        neg     eax\r
+        sbb     edx,0\r
+\r
+//\r
+// Restore the saved registers and return.\r
+//\r
+\r
+L8:\r
+        pop     ebp\r
+        pop     esi\r
+        pop     edi\r
+\r
+        ret     16\r
+\r
+__aulldvrm:\r
+\r
+// ulldvrm - unsigned long divide and remainder\r
+//\r
+// Purpose:\r
+//       Does a unsigned long divide and remainder of the arguments.  Arguments\r
+//       are not changed.\r
+//\r
+// Entry:\r
+//       Arguments are passed on the stack:\r
+//               1st pushed: divisor (QWORD)\r
+//               2nd pushed: dividend (QWORD)\r
+//\r
+// Exit:\r
+//       EDX:EAX contains the quotient (dividend/divisor)\r
+//       EBX:ECX contains the remainder (divided % divisor)\r
+//       NOTE: this routine removes the parameters from the stack.\r
+//\r
+// Uses:\r
+//       ECX\r
+//\r
+        push    esi\r
+\r
+// Set up the local stack and save the index registers.  When this is done\r
+// the stack frame will look as follows (assuming that the expression a/b will\r
+// generate a call to aulldvrm(a, b)):\r
+//\r
+//               -----------------\r
+//               |               |\r
+//               |---------------|\r
+//               |               |\r
+//               |--divisor (b)--|\r
+//               |               |\r
+//               |---------------|\r
+//               |               |\r
+//               |--dividend (a)-|\r
+//               |               |\r
+//               |---------------|\r
+//               | return addr** |\r
+//               |---------------|\r
+//       ESP---->|      ESI      |\r
+//               -----------------\r
+//\r
+\r
+#undef DVNDLO\r
+#undef DVNDHI\r
+#undef DVSRLO\r
+#undef DVSRHI\r
+#define DVNDLO  [esp + 8]       // stack address of dividend (a)\r
+#define DVNDHI  [esp + 8]       // stack address of dividend (a)\r
+#define DVSRLO  [esp + 16]      // stack address of divisor (b)\r
+#define DVSRHI  [esp + 20]      // stack address of divisor (b)\r
+\r
+//\r
+// Now do the divide.  First look to see if the divisor is less than 4194304K.\r
+// If so, then we can use a simple algorithm with word divides, otherwise\r
+// things get a little more complex.\r
+//\r
+\r
+        mov     eax,DVSRHI // check to see if divisor < 4194304K\r
+        or      eax,eax\r
+        jnz     short .L1        // nope, gotta do this the hard way\r
+        mov     ecx,DVSRLO // load divisor\r
+        mov     eax,DVNDHI // load high word of dividend\r
+        xor     edx,edx\r
+        div     ecx             // get high order bits of quotient\r
+        mov     ebx,eax         // save high bits of quotient\r
+        mov     eax,DVNDLO // edx:eax <- remainder:lo word of dividend\r
+        div     ecx             // get low order bits of quotient\r
+        mov     esi,eax         // ebx:esi <- quotient\r
+\r
+//\r
+// Now we need to do a multiply so that we can compute the remainder.\r
+//\r
+        mov     eax,ebx         // set up high word of quotient\r
+        mul     dword ptr DVSRLO // HIWORD(QUOT) * DVSR\r
+        mov     ecx,eax         // save the result in ecx\r
+        mov     eax,esi         // set up low word of quotient\r
+        mul     dword ptr DVSRLO // LOWORD(QUOT) * DVSR\r
+        add     edx,ecx         // EDX:EAX = QUOT * DVSR\r
+        jmp     short .L2        // complete remainder calculation\r
+\r
+//\r
+// Here we do it the hard way.  Remember, eax contains DVSRHI\r
+//\r
+\r
+.L1:\r
+        mov     ecx,eax         // ecx:ebx <- divisor\r
+        mov     ebx,DVSRLO\r
+        mov     edx,DVNDHI // edx:eax <- dividend\r
+        mov     eax,DVNDLO\r
+.L3:\r
+        shr     ecx,1           // shift divisor right one bit// hi bit <- 0\r
+        rcr     ebx,1\r
+        shr     edx,1           // shift dividend right one bit// hi bit <- 0\r
+        rcr     eax,1\r
+        or      ecx,ecx\r
+        jnz     short .L3        // loop until divisor < 4194304K\r
+        div     ebx             // now divide, ignore remainder\r
+        mov     esi,eax         // save quotient\r
+\r
+//\r
+// We may be off by one, so to check, we will multiply the quotient\r
+// by the divisor and check the result against the orignal dividend\r
+// Note that we must also check for overflow, which can occur if the\r
+// dividend is close to 2**64 and the quotient is off by 1.\r
+//\r
+\r
+        mul     dword ptr DVSRHI // QUOT * DVSRHI\r
+        mov     ecx,eax\r
+        mov     eax,DVSRLO\r
+        mul     esi             // QUOT * DVSRLO\r
+        add     edx,ecx         // EDX:EAX = QUOT * DVSR\r
+        jc      short .L4        // carry means Quotient is off by 1\r
+\r
+//\r
+// do long compare here between original dividend and the result of the\r
+// multiply in edx:eax.  If original is larger or equal, we are ok, otherwise\r
+// subtract one (1) from the quotient.\r
+//\r
+\r
+        cmp     edx,DVNDHI // compare hi words of result and original\r
+        ja      short .L4        // if result > original, do subtract\r
+        jb      short .L5        // if result < original, we are ok\r
+        cmp     eax,DVNDLO // hi words are equal, compare lo words\r
+        jbe     short .L5        // if less or equal we are ok, else subtract\r
+.L4:\r
+        dec     esi             // subtract 1 from quotient\r
+        sub     eax,DVSRLO // subtract divisor from result\r
+        sbb     edx,DVSRHI\r
+.L5:\r
+        xor     ebx,ebx         // ebx:esi <- quotient\r
+\r
+.L2:\r
+//\r
+// Calculate remainder by subtracting the result from the original dividend.\r
+// Since the result is already in a register, we will do the subtract in the\r
+// opposite direction and negate the result.\r
+//\r
+\r
+        sub     eax,DVNDLO // subtract dividend from result\r
+        sbb     edx,DVNDHI\r
+        neg     edx             // otherwise, negate the result\r
+        neg     eax\r
+        sbb     edx,0\r
+\r
+//\r
+// Now we need to get the quotient into edx:eax and the remainder into ebx:ecx.\r
+//\r
+        mov     ecx,edx\r
+        mov     edx,ebx\r
+        mov     ebx,ecx\r
+        mov     ecx,eax\r
+        mov     eax,esi\r
+//\r
+// Just the cleanup left to do.  edx:eax contains the quotient.\r
+// Restore the saved registers and return.\r
+//\r
+\r
+        pop     esi\r
+\r
+        ret     16\r
+\r