Artifact d64a1b0991b7ca470fc6bb4b5dda337e73ccea12edccfe24acc8cbe8b01e0adb:
- Executable file
r36/cslbase/imulnt.asm
— part of check-in
[f2fda60abd]
at
2011-09-02 18:13:33
on branch master
— Some historical releases purely for archival purposes
git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/trunk/historical@1375 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: arthurcnorman@users.sourceforge.net, size: 4473) [annotate] [blame] [check-ins using] [more...]
TITLE imul.asm ;; imulnt.asm Copyright (C) Codemist Ltd, 1993 ;; ;; This code implements Imultiply and Idivide in 80386 (and up) assembly ;; code. In fact two versions of the functions are provided, one for ;; the usual "__cdecl" calling conventions (all args passed on the stack) ;; and one for the Microsoft so-called "fastcall" where two args are passed ;; in registers. Name conventions permit the two versions to co-exist. ;; .386P if @Version gt 510 .model FLAT else _TEXT SEGMENT PARA USE32 PUBLIC 'CODE' _TEXT ENDS _DATA SEGMENT DWORD USE32 PUBLIC 'DATA' _DATA ENDS CONST SEGMENT DWORD USE32 PUBLIC 'CONST' CONST ENDS _BSS SEGMENT DWORD USE32 PUBLIC 'BSS' _BSS ENDS _TLS SEGMENT DWORD USE32 PUBLIC 'TLS' _TLS ENDS FLAT GROUP _DATA, CONST, _BSS ASSUME CS: FLAT, DS: FLAT, SS: FLAT endif ; ; unsigned32 Imultiply(unsigned32 *rlow, ; unsigned32 a, unsigned32 b, unsigned32 c) ; { ; /* uns64 is a 64-bit integral type here */ ; uns64 r = (uns64)a*(uns64)b + (uns64)c; ; *rlow = (unsigned32)(r & 0x7fffffff); ; return (unsigned32)(r >> 31); ; } ; PUBLIC _Imultiply _TEXT SEGMENT _rlow$ = 8 _a$ = 12 _b$ = 16 _c$ = 20 _Imultiply PROC NEAR mov eax, DWORD PTR _b$[esp-4] mul DWORD PTR _a$[esp-4] mov ecx, DWORD PTR _rlow$[esp-4] add eax, DWORD PTR _c$[esp-4] adc edx, 0 ; carry into top half add eax, eax adc edx, edx shr eax, 1 mov DWORD PTR [ecx], eax mov eax, edx ret 0 nop nop _Imultiply ENDP _TEXT ENDS ; unsigned32 Idiv10_9(unsigned32 *qp, unsigned32 high, unsigned32 low) ; { ; uns64 p = ((uns64)high << 31) | (uns64)low; ; *qp = (unsigned32)(p / (uns64)1000000000U); ; return (unsigned32)(p % (uns64)1000000000U); ; } ; PUBLIC _Idiv10_9 _TEXT SEGMENT _qp$ = 8 _high$ = 12 _low$ = 16 _Idiv10_9 PROC NEAR mov edx, DWORD PTR _high$[esp-4] mov eax, DWORD PTR _low$[esp-4] shl eax, 1 shr edx, 1 rcr eax, 1 ; That glued together 31+31 bits mov ecx, 1000000000 div ecx mov ecx, DWORD PTR _qp$[esp-4] mov DWORD PTR [ecx], eax mov eax, edx ret 0 nop nop _Idiv10_9 ENDP _TEXT ENDS ; unsigned32 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); ; } ; PUBLIC _Idivide _TEXT SEGMENT _qp$ = 8 _a$ = 12 _b$ = 16 _c$ = 20 _Idivide PROC NEAR mov edx, DWORD PTR _high$[esp-4] mov eax, DWORD PTR _low$[esp-4] shl eax, 1 shr edx, 1 rcr eax, 1 ; That glued together 31+31 bits mov ecx, DWORD PTR _c$[esp-4] div ecx mov ecx, DWORD PTR _qp$[esp-4] mov DWORD PTR [ecx], eax mov eax, edx ret 0 nop nop nop _Idivide ENDP ;; ;; Now for the versions that take args in registers. ;; _TEXT ENDS ; ; unsigned32 Imultiply(unsigned32 *rlow, ; unsigned32 a, unsigned32 b, unsigned32 c) ; { ; /* uns64 is a 64-bit integral type here */ ; uns64 r = (uns64)a*(uns64)b + (uns64)c; ; *rlow = (unsigned32)(r & 0x7fffffff); ; return (unsigned32)(r >> 31); ; } ; PUBLIC @Imultiply@16 _TEXT SEGMENT @Imultiply@16 PROC NEAR mov eax, DWORD PTR 4[esp] mul edx add eax, DWORD PTR 8[esp] adc edx, 0 ; carry into top half add eax, eax adc edx, edx shr eax, 1 mov DWORD PTR [ecx], eax mov eax, edx ret 8 nop nop nop nop nop nop @Imultiply@16 ENDP _TEXT ENDS ; unsigned32 Idiv10_9(unsigned32 *qp, unsigned32 high, unsigned32 low) ; { ; uns64 p = ((uns64)high << 31) | (uns64)low; ; *qp = (unsigned32)(p / (uns64)1000000000U); ; return (unsigned32)(p % (uns64)1000000000U); ; } ; PUBLIC @Idiv10_9@12 _TEXT SEGMENT @Idiv10_9@12 PROC NEAR mov eax, DWORD PTR 4 [esp] shl eax, 1 shr edx, 1 rcr eax, 1 ; That glued together 31+31 bits push 1000000000 div DWORD PTR [esp] mov DWORD PTR [ecx], eax pop eax mov eax, edx ret 4 nop nop nop nop nop nop @Idiv10_9@12 ENDP _TEXT ENDS ; unsigned32 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); ; } ; PUBLIC @Idivide@16 _TEXT SEGMENT @Idivide@16 PROC NEAR mov eax, DWORD PTR 4 [esp] shl eax, 1 shr edx, 1 rcr eax, 1 ; That glued together 31+31 bits div DWORD PTR 8[esp] mov DWORD PTR [ecx], eax mov eax, edx ret 8 nop nop nop @Idivide@16 ENDP _TEXT ENDS END