windows-nt/Source/XPSP1/NT/base/mvdm/wow16/win87em/emfmul.asm
2020-09-26 16:20:57 +08:00

196 lines
3.9 KiB
NASM

page ,132
subttl emfmul.asm - Multiplication
;***
;emfmisc.asm - Multiplication
;
; Copyright (c) 1986-89, Microsoft Corporation
;
;Purpose:
; Multiplication
;
;
; This Module contains Proprietary Information of Microsoft
; Corporation and should be treated as Confidential.
;
;Revision History:
; See emulator.hst
;
;*******************************************************************************
;-----------------------------------------;
; ;
; Multiplication ;
; ;
;-----------------------------------------;
; Perform multiply by summing partial products of 16x16 hardware multiply.
; Before each multiply, the operands are checked for zero to see if it can be
; skipped, since it's a slow operation on the 8086. The sum is kept in
; registers as much as possible. Any insignificant bits lost are ORed together
; and kept in a word on the top of the stack. This can be used for sticky bit
; rounding. First we will need some macros.
ProfBegin FMUL
MULP MACRO SIOFFSET,DIOFFSET,NEXTLOC
;Will multiply the words found at the given offsets if those words
;are non-0. since we assume the numbers are normalized and the
;most significant word has offset 6 we know that words with offset
;6 are non-0 hence the conditional code in this macro.
MOV AX,SIOFFSET[esi]
IF SIOFFSET - 6 ;When SI offset is 6 it is most sig word hence not 0
OR AX,AX
JZ short NEXTLOC
ENDIF
IF DIOFFSET - 6
MOV DX,DIOFFSET[edi]
OR DX,DX
JZ short NEXTLOC
MUL DX
ELSE
MUL WORD PTR DIOFFSET[edi]
ENDIF
ENDM
ADDP MACRO HI,MID,LO
;Will add the double word result of a multiply to the triple word
; at HI:MID:LO using HI to record overflow
ADD LO,AX
ADC MID,DX
ADC HI,0
ENDM
STICKY MACRO R
;R is the register containing the least significant word which
;should be ORed to the sticky bit (kept on the stack) and then
;cleared so the register can be reused
POP eax
OR AX,R
PUSH eax
XOR R,R
ENDM
page
RMBRQQ: ; Routine MUL Both must see if we have two singles.
if fastSP
MOV BX,DX
XOR BX,Single + 256*Single
TEST BX,Single + 256*Single
JNZ RMDRQQ
MOV BX,OFFSET TMSRQQ
JMP [BX]
endif ;fastSP
pub RMDRQQ ;RoutineMulDouble SI & DI point to valid non-0 reals
; AX CX are the exponents
; DL DH are the signs
if fastSP
CALL CoerceToDouble ; insure that both args are double
endif ;fastSP
PUSH ebp ; Must save BP
MOV BH,DH ; Save Single double flag
XOR DH,DL ; Get sign onto stack
PUSH edx
ADD AX,CX ; New exponent is sum of old plus 1
INC AX ; because of the normalize step
PUSH eax ; Save it while we Multiply
AND BH,DL
pub PROD1
XOR BX,BX
MOV BP,BX
MOV CX,BX
MULP 0,0,PROD2
MOV BP,AX ; Save insignificant bits
MOV CX,DX
pub PROD2
PUSH ebp ; Save Sticky bit on stack
xor ebp, ebp ; bp is now the working high word of bp:bx:cx
MULP 0,2,PROD3
ADDP BP,BX,CX
pub PROD3
MULP 2,0,PROD4
ADDP BP,BX,CX
pub PROD4
STICKY CX
MULP 0,4,PROD5
ADDP CX,BP,BX
pub PROD5
MULP 2,2,PROD6
ADDP CX,BP,BX
pub PROD6
MULP 4,0,PROD7
ADDP CX,BP,BX
pub PROD7
STICKY BX
MULP 0,6,PROD8
ADDP BX,CX,BP
pub PROD8
MULP 2,4,PROD9
ADDP BX,CX,BP
pub PROD9
MULP 4,2,PROD10
ADDP BX,CX,BP
pub PROD10
MULP 6,0,PROD11
ADDP BX,CX,BP
pub PROD11
MOV DX,BP ; Everything but guard and round go to sticky
AND BP,03FFFH
STICKY BP
PUSH edx ; Save guard and round on stack
MULP 2,6,PROD12
ADDP BP,BX,CX
pub PROD12
MULP 4,4,PROD13
ADDP BP,BX,CX
pub PROD13
MULP 6,2,PROD14
ADDP BP,BX,CX
pub PROD14
PUSH ecx ; Save LSW on stack (not enough registers)
XOR CX,CX
MULP 4,6,PROD15
ADDP CX,BP,BX
pub PROD15
MULP 6,4,PROD16
ADDP CX,BP,BX
pub PROD16
MULP 6,6,PROD17
ADD AX,BP
ADC DX,CX
POP ecx
POP ebp ; Result in DX:AX:BX:CX:BP Sticky on stack
MOV DI,DX
MOV DX,CX
MOV CX,BX
MOV BX,AX ; Result in DI:BX:CX:DX:BP
POP eax ; Merge Sticky bit into BP
OR AX,AX
JZ short STBITOK
OR BP,1
pub STBITOK
POP esi ; Exponent in SI, Sign on Stack, Old BP on Stack
JMP NORMSHF ; Result must be normalized at most 1 bit
ProfEnd FMUL