123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- /* imulvc.c Copyright (C) 1993-2002 Codemist Ltd */
- /*
- * This code may be used and modified, and redistributed in binary
- * or source form, subject to the "CCL Public License", which should
- * accompany it. This license is a variant on the BSD license, and thus
- * permits use of code derived from this in either open and commercial
- * projects: but it does require that updates to this code be made
- * available back to the originators of the package.
- * Before merging other code in with this or linking this code
- * with other packages or libraries please check that the license terms
- * of the other material are compatible with those of this.
- */
- /* Signature: 77597f94 08-Apr-2002 */
- /*
- * This code implements Imultiply and Idivide in 80386 (and up) assembly
- * code. I use the __stdcall calling convention.
- */
- #include "machine.h"
- #include "tags.h"
- #include "externs.h"
- #include "cslerror.h"
- #include "sys.h"
- /*
- * Get rid of unwanted warnings about lack of return values...
- */
- #pragma warning (disable : 4035)
- unsigned32 __stdcall Imultiply(unsigned32 *rlow,
- unsigned32 a, unsigned32 b, unsigned32 c)
- {
- /*
- * uns64 r = (uns64)a*(uns64)b + (uns64)c;
- * *rlow = (unsigned32)(r & 0x7fffffff);
- * return (unsigned32)(r >> 31);
- */
- __asm
- {
- mov eax, b
- mul a
- mov ecx, rlow
- add eax, c
- adc edx, 0 ; carry into top half
- add eax, eax
- adc edx, edx
- shr eax, 1
- mov DWORD PTR [ecx], eax
- mov eax, edx
- }
- }
- unsigned32 __stdcall Idiv10_9(unsigned32 *qp, unsigned32 high31, unsigned32 low31)
- {
- /*
- * uns64 p = ((uns64)high31 << 31) | (uns64)low31;
- * *qp = (unsigned32)(p / (uns64)1000000000U);
- * return (unsigned32)(p % (uns64)1000000000U);
- */
- __asm {
- mov edx, high31
- mov eax, low31
- shl eax, 1
- shr edx, 1
- rcr eax, 1 ; That glued together 31+31 bits
- mov ecx, 1000000000
- div ecx
- mov ecx, qp
- mov DWORD PTR [ecx], eax
- mov eax, edx
- }
- }
- unsigned32 __stdcall Idivide(unsigned32 *qp, unsigned32 a,
- unsigned32 b, unsigned32 c)
- {
- /*
- * uns64 p = ((uns64)a << 31) | (uns64)b;
- * *qp = (unsigned32)(p / (uns64)c);
- * return (unsigned32)(p % (uns64)c);
- */
- __asm {
- mov edx, a
- mov eax, b
- shl eax, 1
- shr edx, 1
- rcr eax, 1 ; That glued together 31+31 bits
- mov ecx, c
- div ecx
- mov ecx, qp
- mov DWORD PTR [ecx], eax
- mov eax, edx
- }
- }
- /* end of imulvc.c */
|