- Implement remaining functions in rtl/i386/math_asm.S
[reactos.git] / reactos / lib / rtl / i386 / math_asm.S
index ca1d6ca..ebc8e67 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
+.intel_syntax noprefix\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
+// lldiv - signed long divide\r
+//\r
+// Purpose:\r
+//       Does a signed long divide of the arguments.  Arguments are\r
+//       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
+//       NOTE: this routine removes the parameters from the stack.\r
+//\r
+// Uses:\r
+//       ECX\r
+//\r
+\r
+__alldiv:\r
+\r
+        push    edi\r
+        push    esi\r
+        push    ebx\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 lldiv(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---->|      EBX      |\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 result (edi = 0 if result is positive, non-zero\r
+// otherwise) and make operands positive.\r
+\r
+        xor     edi,edi         // 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
+        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     edx,ebx         // edx:eax <- quotient\r
+        jmp     short L4        // set sign, restore stack and return\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
+L7:\r
+        xor     edx,edx         // edx:eax <- quotient\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
+L4:\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     ebx\r
+        pop     esi\r
+        pop     edi\r
+\r
+        ret     16\r
+\r
+//\r
+// llmul - long multiply routine\r
+//\r
+// Purpose:\r
+//       Does a long multiply (same for signed/unsigned)\r
+//       Parameters are not changed.\r
+//\r
+// Entry:\r
+//       Parameters are passed on the stack:\r
+//               1st pushed: multiplier (QWORD)\r
+//               2nd pushed: multiplicand (QWORD)\r
+//\r
+// Exit:\r
+//       EDX:EAX - product of multiplier and multiplicand\r
+//       NOTE: parameters are removed from the stack\r
+//\r
+// Uses:\r
+//       ECX\r
+//\r
+\r
+__allmul:\r
+\r
+#define ALO  [esp + 4]       // stack address of a\r
+#define AHI  [esp + 8]       // stack address of a\r
+#define BLO  [esp + 12]      // stack address of b\r
+#define BHI  [esp + 16]      // stack address of b\r
+\r
+//\r
+//       AHI, BHI : upper 32 bits of A and B\r
+//       ALO, BLO : lower 32 bits of A and B\r
+//\r
+//             ALO * BLO\r
+//       ALO * BHI\r
+// +     BLO * AHI\r
+// ---------------------\r
+//\r
+\r
+        mov     eax,AHI\r
+        mov     ecx,BHI\r
+        or      ecx,eax         //test for both hiwords zero.\r
+        mov     ecx,BLO\r
+        jnz     short hard      //both are zero, just mult ALO and BLO\r
+\r
+        mov     eax,AHI\r
+        mul     ecx\r
+\r
+        ret     16              // callee restores the stack\r
+\r
+hard:\r
+        push    ebx\r
+\r
+// must redefine A and B since esp has been altered\r
+\r
+#define A2LO  [esp + 4]       // stack address of a\r
+#define A2HI  [esp + 8]       // stack address of a\r
+#define B2LO  [esp + 12]      // stack address of b\r
+#define B2HI  [esp + 16]      // stack address of b\r
+\r
+        mul     ecx             //eax has AHI, ecx has BLO, so AHI * BLO\r
+        mov     ebx,eax         //save result\r
+\r
+        mov     eax,A2LO\r
+        mul     dword ptr B2HI //ALO * BHI\r
+        add     ebx,eax         //ebx = ((ALO * BHI) + (AHI * BLO))\r
+\r
+        mov     eax,A2LO  //ecx = BLO\r
+        mul     ecx             //so edx:eax = ALO*BLO\r
+        add     edx,ebx         //now edx has all the LO*HI stuff\r
+\r
+        pop     ebx\r
+\r
+        ret     16              // callee restores the stack\r
+\r
+//\r
+// llrem - signed long remainder\r
+//\r
+// Purpose:\r
+//       Does a signed long remainder of the arguments.  Arguments are\r
+//       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 remainder (dividend%divisor)\r
+//       NOTE: this routine removes the parameters from the stack.\r
+//\r
+// Uses:\r
+//       ECX\r
+//\r
+\r
+__allrem :\r
+\r
+        push    ebx\r
+        push    edi\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 lrem(a, b)):\r
+//\r
+//               -----------------\r
+//               |               |\r
+//               |---------------|\r
+//               |               |\r
+//               |--divisor (b)--|\r
+//               |               |\r
+//               |---------------|\r
+//               |               |\r
+//               |--dividend (a)-|\r
+//               |               |\r
+//               |---------------|\r
+//               | return addr** |\r
+//               |---------------|\r
+//               |       EBX     |\r
+//               |---------------|\r
+//       ESP---->|       EDI     |\r
+//               -----------------\r
+//\r
+\r
+#undef DVNDLO\r
+#undef DVNDHI\r
+#undef DVSRLO\r
+#undef DVSRHI\r
+#define DVNDLO  [esp + 12]       // stack address of dividend (a)\r
+#define DVNDHI  [esp + 16]       // stack address of dividend (a)\r
+#define DVSRLO  [esp + 20]      // stack address of divisor (b)\r
+#define DVSRHI  [esp + 24]      // stack address of divisor (b)\r
+\r
+// Determine sign of the result (edi = 0 if result is positive, non-zero\r
+// otherwise) and make operands positive.\r
+\r
+        xor     edi,edi         // 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 bit\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
+        mov     edx,DVSRLO // lo word of b\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             // edx <- remainder\r
+        mov     eax,DVNDLO // edx:eax <- remainder:lo word of dividend\r
+        div     ecx             // edx <- final remainder\r
+        mov     eax,edx         // edx:eax <- remainder\r
+        xor     edx,edx\r
+        dec     edi             // check result sign flag\r
+        jns     short .L4        // negate result, restore stack and return\r
+        jmp     short .L8        // result sign ok, restore stack and return\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
+\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
+        mov     ecx,eax         // save a copy of quotient in ECX\r
+        mul     dword ptr DVSRHI\r
+        xchg    ecx,eax         // save product, get quotient in EAX\r
+        mul     dword ptr 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 the original divisor from the result.\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
+        sub     eax,DVSRLO // subtract divisor from result\r
+        sbb     edx,DVSRHI\r
+.L7:\r
+\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     edi             // check result sign flag\r
+        jns     short .L8        // result is ok, restore stack and return\r
+.L4:\r
+        neg     edx             // otherwise, negate the result\r
+        neg     eax\r
+        sbb     edx,0\r
+\r
+//\r
+// Just the cleanup left to do.  edx:eax contains the quotient.\r
+// Restore the saved registers and return.\r
+//\r
+\r
+.L8:\r
+        pop     edi\r
+        pop     ebx\r
+\r
+        ret     16\r
+\r
+//\r
+// llshl - long shift left\r
+//\r
+// Purpose:\r
+//       Does a Long Shift Left (signed and unsigned are identical)\r
+//       Shifts a long left any number of bits.\r
+//\r
+// Entry:\r
+//       EDX:EAX - long value to be shifted\r
+//       CL      - number of bits to shift by\r
+//\r
+// Exit:\r
+//       EDX:EAX - shifted value\r
+//\r
+// Uses:\r
+//       CL is destroyed.\r
+//\r
+\r
+__allshl:\r
+\r
+//\r
+// Handle shifts of 64 or more bits (all get 0)\r
+//\r
+        cmp     cl, 64\r
+        jae     short RETZERO\r
+\r
+//\r
+// Handle shifts of between 0 and 31 bits\r
+//\r
+        cmp     cl, 32\r
+        jae     short MORE32\r
+        shld    edx,eax,cl\r
+        shl     eax,cl\r
+        ret\r
+\r
+//\r
+// Handle shifts of between 32 and 63 bits\r
+//\r
+MORE32:\r
+        mov     edx,eax\r
+        xor     eax,eax\r
+        and     cl,31\r
+        shl     edx,cl\r
+        ret\r
+\r
+//\r
+// return 0 in edx:eax\r
+//\r
+RETZERO:\r
+        xor     eax,eax\r
+        xor     edx,edx\r
+        ret\r
+\r
+//\r
+// llshr - long shift right\r
+//\r
+// Purpose:\r
+//       Does a signed Long Shift Right\r
+//       Shifts a long right any number of bits.\r
+//\r
+// Entry:\r
+//       EDX:EAX - long value to be shifted\r
+//       CL      - number of bits to shift by\r
+//\r
+// Exit:\r
+//       EDX:EAX - shifted value\r
+//\r
+// Uses:\r
+//       CL is destroyed.\r
+//\r
+\r
+__allshr:\r
+\r
+//\r
+// Handle shifts of 64 bits or more (if shifting 64 bits or more, the result\r
+// depends only on the high order bit of edx).\r
+//\r
+        cmp     cl,64\r
+        jae     short .RETSIGN\r
+\r
+//\r
+// Handle shifts of between 0 and 31 bits\r
+//\r
+        cmp     cl, 32\r
+        jae     short .MORE32\r
+        shrd    eax,edx,cl\r
+        sar     edx,cl\r
+        ret\r
+\r
+//\r
+// Handle shifts of between 32 and 63 bits\r
+//\r
+.MORE32:\r
+        mov     eax,edx\r
+        sar     edx,31\r
+        and     cl,31\r
+        sar     eax,cl\r
+        ret\r
+\r
+//\r
+// Return double precision 0 or -1, depending on the sign of edx\r
+//\r
+.RETSIGN:\r
+        sar     edx,31\r
+        mov     eax,edx\r
+        ret\r
+\r
+//\r
+// ulldiv - unsigned long divide\r
+//\r
+// Purpose:\r
+//       Does a unsigned long divide of the arguments.  Arguments are\r
+//       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
+//       NOTE: this routine removes the parameters from the stack.\r
+//\r
+// Uses:\r
+//       ECX\r
+//\r
+\r
+__aulldiv:\r
+\r
+        push    ebx\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 uldiv(a, b)):\r
+//\r
+//               -----------------\r
+//               |               |\r
+//               |---------------|\r
+//               |               |\r
+//               |--divisor (b)--|\r
+//               |               |\r
+//               |---------------|\r
+//               |               |\r
+//               |--dividend (a)-|\r
+//               |               |\r
+//               |---------------|\r
+//               | return addr** |\r
+//               |---------------|\r
+//               |      EBX      |\r
+//               |---------------|\r
+//       ESP---->|      ESI      |\r
+//               -----------------\r
+//\r
+\r
+#undef DVNDLO\r
+#undef DVNDHI\r
+#undef DVSRLO\r
+#undef DVSRHI\r
+#define DVNDLO  [esp + 12]       // stack address of dividend (a)\r
+#define DVNDHI  [esp + 16]       // stack address of dividend (a)\r
+#define DVSRLO  [esp + 20]      // stack address of divisor (b)\r
+#define DVSRHI  [esp + 24]      // 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     edx,ebx         // edx:eax <- quotient hi:quotient lo\r
+        jmp     short ..L2        // restore stack and return\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
-/*\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
+        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
- * 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
+// 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
-/*\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
+        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
+..L5:\r
+        xor     edx,edx         // edx:eax <- quotient\r
+        mov     eax,esi\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
+// Just the cleanup left to do.  edx:eax contains the quotient.\r
+// Restore the saved registers and return.\r
+//\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
+..L2:\r
+\r
+        pop     esi\r
+        pop     ebx\r
+\r
+        ret     16\r
+\r
+//\r
+// ullshr - long shift right\r
+//\r
+// Purpose:\r
+//       Does a unsigned Long Shift Right\r
+//       Shifts a long right any number of bits.\r
+//\r
+// Entry:\r
+//       EDX:EAX - long value to be shifted\r
+//       CL      - number of bits to shift by\r
+//\r
+// Exit:\r
+//       EDX:EAX - shifted value\r
+//\r
+// Uses:\r
+//       CL is destroyed.\r
+//\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
+// Handle shifts of 64 bits or more (if shifting 64 bits or more, the result\r
+// depends only on the high order bit of edx).\r
+//\r
+        cmp     cl,64\r
+        jae     short ..RETZERO\r
+\r
+//\r
+// Handle shifts of between 0 and 31 bits\r
+//\r
+        cmp     cl, 32\r
+        jae     short ..MORE32\r
+        shrd    eax,edx,cl\r
+        shr     edx,cl\r
+        ret\r
+\r
+//\r
+// Handle shifts of between 32 and 63 bits\r
+//\r
+..MORE32:\r
+        mov     eax,edx\r
+        xor     edx,edx\r
+        and     cl,31\r
+        shr     eax,cl\r
+        ret\r
+\r
+//\r
+// return 0 in edx:eax\r
+//\r
+..RETZERO:\r
+        xor     eax,eax\r
+        xor     edx,edx\r
+        ret\r
+\r
+//\r
+// ullrem - unsigned long remainder\r
+//\r
+// Purpose:\r
+//       Does a unsigned long remainder of the arguments.  Arguments are\r
+//       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 remainder (dividend%divisor)\r
+//       NOTE: this routine removes the parameters from the stack.\r
+//\r
+// Uses:\r
+//       ECX\r
+//\r
+\r
+__aullrem:\r
+\r
+        push    ebx\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 ullrem(a, b)):\r
+//\r
+//               -----------------\r
+//               |               |\r
+//               |---------------|\r
+//               |               |\r
+//               |--divisor (b)--|\r
+//               |               |\r
+//               |---------------|\r
+//               |               |\r
+//               |--dividend (a)-|\r
+//               |               |\r
+//               |---------------|\r
+//               | return addr** |\r
+//               |---------------|\r
+//       ESP---->|      EBX      |\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
+// 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             // edx <- remainder, eax <- quotient\r
+        mov     eax,DVNDLO // edx:eax <- remainder:lo word of dividend\r
+        div     ecx             // edx <- final remainder\r
+        mov     eax,edx         // edx:eax <- remainder\r
+        xor     edx,edx\r
+        jmp     short ...L2        // restore stack and return\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
+\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
+        mov     ecx,eax         // save a copy of quotient in ECX\r
+        mul     dword ptr DVSRHI\r
+        xchg    ecx,eax         // put partial product in ECX, get quotient in EAX\r
+        mul     dword ptr 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're ok, otherwise\r
+// subtract the original divisor from the result.\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're ok\r
+        cmp     eax,DVNDLO // hi words are equal, compare lo words\r
+        jbe     short ...L5        // if less or equal we're ok, else subtract\r
+...L4:\r
+        sub     eax,DVSRLO // subtract divisor from result\r
+        sbb     edx,DVSRHI\r
+...L5:\r
+\r
+//\r
+// Calculate remainder by subtracting the result from the original dividend.\r
+// Since the result is already in a register, we will perform the subtract in\r
+// the opposite direction and negate the result to make it positive.\r
+//\r
+\r
+        sub     eax,DVNDLO // subtract original dividend from result\r
+        sbb     edx,DVNDHI\r
+        neg     edx             // and negate it\r
+        neg     eax\r
+        sbb     edx,0\r
+\r
+//\r
+// Just the cleanup left to do.  dx:ax contains the remainder.\r
+// Restore the saved registers and return.\r
+//\r
+\r
+...L2:\r
+\r
+        pop     ebx\r
+\r
+        ret     16\r
+\r
 \r
 /*\r
  * This routine is called by MSVC-generated code to convert from floating point\r
@@ -295,6 +1016,10 @@ __alldvrm:
 //               -----------------\r
 //\r
 \r
+#undef DVNDLO\r
+#undef DVNDHI\r
+#undef DVSRLO\r
+#undef DVSRHI\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
@@ -309,7 +1034,7 @@ __alldvrm:
 \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
+        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
@@ -318,10 +1043,10 @@ __alldvrm:
         sbb     eax,0\r
         mov     DVNDHI,eax // save positive value\r
         mov     DVNDLO,edx\r
-L1:\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
+        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
@@ -329,7 +1054,7 @@ L1:
         sbb     eax,0\r
         mov     DVSRHI,eax // save positive value\r
         mov     DVSRLO,edx\r
-L2:\r
+....L2:\r
 \r
 //\r
 // Now do the divide.  First look to see if the divisor is less than 4194304K.\r
@@ -340,7 +1065,7 @@ L2:
 //\r
 \r
         or      eax,eax         // check to see if divisor < 4194304K\r
-        jnz     short L3        // nope, gotta do this the hard way\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
@@ -358,24 +1083,24 @@ L2:
         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
+        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
+....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
+....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
+        jnz     short ....L5        // loop until divisor < 4194304K\r
         div     ecx             // now divide, ignore remainder\r
         mov     esi,eax         // save quotient\r
 \r
@@ -391,7 +1116,7 @@ L5:
         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
+        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
@@ -400,18 +1125,18 @@ L5:
 //\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
+        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
+        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
+....L7:\r
         xor     ebx,ebx         // ebx:esi <- quotient\r
 \r
-L4:\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
@@ -429,7 +1154,7 @@ L4:
 //\r
 \r
         dec     ebp             // check result sign flag\r
-        jns     short L9        // result is ok, set up the quotient\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
@@ -437,7 +1162,7 @@ L4:
 //\r
 // Now we need to get the quotient into edx:eax and the remainder into ebx:ecx.\r
 //\r
-L9:\r
+....L9:\r
         mov     ecx,edx\r
         mov     edx,ebx\r
         mov     ebx,ecx\r
@@ -450,7 +1175,7 @@ L9:
 //\r
 \r
         dec     edi             // check to see if result is negative\r
-        jnz     short L8        // if EDI == 0, result should be 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
@@ -459,7 +1184,7 @@ L9:
 // Restore the saved registers and return.\r
 //\r
 \r
-L8:\r
+....L8:\r
         pop     ebp\r
         pop     esi\r
         pop     edi\r
@@ -527,7 +1252,7 @@ __aulldvrm:
 \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
+        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
@@ -546,24 +1271,24 @@ __aulldvrm:
         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
+        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
+.....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
+.....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
+        jnz     short .....L3        // loop until divisor < 4194304K\r
         div     ebx             // now divide, ignore remainder\r
         mov     esi,eax         // save quotient\r
 \r
@@ -579,7 +1304,7 @@ __aulldvrm:
         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
+        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
@@ -588,18 +1313,18 @@ __aulldvrm:
 //\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
+        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
+        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
+.....L5:\r
         xor     ebx,ebx         // ebx:esi <- quotient\r
 \r
-.L2:\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
@@ -629,3 +1354,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