summaryrefslogtreecommitdiffstats
path: root/private/mvdm/wow16/gdi/muldiv.asm
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/wow16/gdi/muldiv.asm')
-rw-r--r--private/mvdm/wow16/gdi/muldiv.asm110
1 files changed, 110 insertions, 0 deletions
diff --git a/private/mvdm/wow16/gdi/muldiv.asm b/private/mvdm/wow16/gdi/muldiv.asm
new file mode 100644
index 000000000..066fd0f8d
--- /dev/null
+++ b/private/mvdm/wow16/gdi/muldiv.asm
@@ -0,0 +1,110 @@
+ Title Muldiv - (A*B)/C With Correct Rounding
+ %out MulDiv
+ page ,132
+;----------------------------Module-Header------------------------------;
+; Module Name: muldiv.asm
+;
+; (w * Numer) / Denom with correct rounding.
+;
+; Created:
+; Author:
+;
+; Copyright (c) 1985, 1986, 1987 Microsoft Corporation
+;
+; MulDiv(w, Numer, Denom) returns (w * Numer) / Denom rounded to the nearest
+; integer. A check is made so that division by zero is not attempted.
+;-----------------------------------------------------------------------;
+
+
+ .xlist
+ include cmacros.inc
+; include gditype.inc
+ .list
+
+
+sBegin code
+assumes cs,code
+
+;--------------------------Public-Routine-------------------------------;
+; short FAR PASCAL MulDiv(short, short, short)
+; short w;
+; short Numer;
+; short Denom;
+;
+; (w * Numer)/ Denom with correct rounding.
+;
+; Returns: AX = result.
+; DX = 1 if no overflow.
+; DX = 0 if overflow.
+;
+; Preserves: BX,CX
+; Doesn't lose: SI,DI,ES,DS
+;
+; Warnings:
+;
+; Effects:
+;
+; History:
+; Mon 22-Dec-1986 17:08:55 -by- Kent Settle [kentse]
+; Added headers and comments.
+;-----------------------------------------------------------------------;
+
+cProc MulDiv,<FAR,PUBLIC>,<bx,cx>
+
+ parmW <w, Numer, Denom>
+
+cBegin MulDiv
+
+ mov bx,Denom ; get the demoninator
+ mov cx,bx ; CX holds the final sign
+ or bx,bx ; ensure the denominator is positive
+ jns md1
+ neg bx
+
+md1:
+ mov ax,w ; get the word we are multiplying
+ xor cx,ax ; make CX reflect any sign change
+ or ax,ax ; ensure this word is positive
+ jns md2
+ neg ax
+
+md2:
+ mov dx,Numer ; get the numerator
+ xor cx,dx ; make CX reflect any sign change
+ or dx,dx ; ensure the numerator is positive
+ jns md3
+ neg dx
+
+md3:
+ mul dx ; multiply
+ mov cl,bl ; get half of the demoninator to adjust for rounding
+ sar bx,1
+ add ax,bx ; adjust for possible rounding error
+ adc dx,0 ; this is really a long addition
+ sal bx,1 ; restore the demoninator
+ or bl,cl
+ cmp dx,bx ; check for overflow
+ jae md5 ; (ae handles /0 case)
+ div bx ; divide
+ or ax,ax ; If sign is set, then overflow occured
+ js md5 ; Overflow.
+ or cx,cx ; put the sign on the result
+ jns md4
+ neg ax
+md4:
+ mov dx,1 ; indicate no overflow.
+md6:
+
+cEnd MulDiv
+
+
+md5:
+ xor dx,dx ; indicate overflow.
+ mov ax,7FFFh ; return the largest integer
+ or cx,cx ; with the correct sign
+ jns md6
+ not ax
+ jmp md6
+
+sEnd code
+end