__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
-/*\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
+ 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
- * 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
+// Here we do it the hard way. Remember, eax contains DVSRHI\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
+..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
- * 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
+// 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
- * 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
+ 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
+..L5:\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.\r
+// Restore the saved registers and return.\r
+//\r
+\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
// -----------------\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
\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
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
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
//\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
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
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
//\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
//\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
//\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
//\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
// Restore the saved registers and return.\r
//\r
\r
-L8:\r
+....L8:\r
pop ebp\r
pop esi\r
pop edi\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
+ 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
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
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
//\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