page ,132 subttl emfsqrt.asm - Square root ;*** ;emfsqrt.asm - Square root ; ; Copyright (c) 1986-89, Microsoft Corporation ; ;Purpose: ; Square root ; ; This Module contains Proprietary Information of Microsoft ; Corporation and should be treated as Confidential. ; ;Revision History: ; See emulator.hst ; ;******************************************************************************* ;-----------------------------------------; ; ; ; Square root ; ; ; ;-----------------------------------------; ProfBegin FSQRT pub eFSQRT MOV esi,[CURstk] CALL $FSQRT RET ;--------------------------------------------------- ; ! ; 8087 emulator square root ! ; ! ;--------------------------------------------------- ; With 0<=x={TOS=[SI]}=r3a then r3a=r3a+ya,qc=qc-1 endif, ; r3a=r3a-p3a,qd*ya+r4a=r3a:0h, ; ya:yb:yc:yd=(ya:yb:0h:0h+qa:qb:qc:qd)/2 pub SQRTSPECIAL RCR AH,1 ;if NAN JNC short SETFLAG ; set invalid flag and return RCL AL,1 ;if -infinity JC short SQRTERROR ; return real indefinite MOV AL,[CWcntl] ;get Infinity control TEST AL,ICaffine ;if affine closure JNZ short SQRTDONE ; return +infinity JMP SHORT SQRTERROR ;else return real indefinite pub NOTPOSVALID TEST AH,2 ;if special JNZ SQRTSPECIAL ; process special RCR AH,1 ;if zero JC SHORT SQRTDONE ; return argument ;otherwise -ve, return NAN pub SQRTERROR MOV edi,esi MOV esi,offset IEEEindefinite CALL csMOVRQQ MOV esi,edi ;return indefinite pub SETFLAG OR [CURerr],Invalid+SquareRootNeg ;Set flag indicating invalid pub SQRTDONE RET pub $FSQRT MOV AX,[esi+Flag] ;get flags TEST AX,00380H ;if Sign, Invalid or Zero JNZ NOTPOSVALID ; perform special processing PUSH esi ;save ptr to x MOV edi,offset TEMP1 ;[DI]=y=temp MOV word ptr [edi+Flag],0 ;clear flags in y MOV AX,[esi+Expon] ;get exponent of x DEC AX ;adjust for shift divide by 2 MOV BX,[esi+6] MOV CX,[esi+4] MOV DX,[esi+2] ;get first three mantissa words of x TEST AL,1 ;if exponent is even JZ short EXPEVEN ; bypass adjust INC AX ;increment exponent SHR BX,1 RCR CX,1 RCR DX,1 ;divide mantissa by 2 pub EXPEVEN SAR AX,1 ;divide exponent by 2 MOV [edi+Expon],AX ;store exponent of y CMP BX,0FFFEH ;if mantissa < 0.FFFEh JB short NOTNEARONE1 ; perform main root routine STC ;otherwise x to become (1+x)/2 JMP SHORT SINGLEDONE ;single precision complete pub NOTNEARONE1 PUSH edx ;save third mantissa word MOV AX,0B075H ;AX=.B075h MUL BX ;DX=.B075h*x MOV BP,057D8H ;BP=.57D8h ADD BP,DX ;BP=.B075h*x+.57D8h JNC short NORMEST ;if y is more than one MOV BP,0FFFFH ; replace y with .FFFFh pub NORMEST MOV DX,BX XOR AX,AX ;load divide regs with xa:0h DIV BP ;qa*ya+r1a=xa:0h ADD BP,AX ;ya=ya+qa RCR BP,1 ;ya=ya/2 MOV DX,BX MOV AX,CX ;load divide regs with xa:xb DIV BP ;qa*ya+r1a=xa:xb STC ;add one to qa for better rounding ADC BP,AX ;ya=ya+qa RCR BP,1 ;ya=ya/2 MOV DX,BX MOV AX,CX ;load divide regs with xa:xb DIV BP ;qa*ya+r1a=xa:xb MOV SI,AX ;save qa POP eax ;load divide regs with r1a:xc DIV BP ;qb*ya+r2a=r1a:xc MOV BX,BP MOV CX,AX ;move qa:qb ADD CX,1 ;add one to qa:qb for better rounding ADC BX,SI ;ya:yb=ya:0h+qa:qb pub SINGLEDONE RCR BX,1 RCR CX,1 ;ya:yb=(ya:0h+qa:qb)/2 MOV word ptr [edi+6],BX MOV word ptr [edi+4],CX MOV word ptr [edi+2],0 MOV word ptr [edi],0 ;save ya:yb:0h:0h MOV esi,edi ;[SI]=y POP edi ;[DI]=x MOV [RESULT],edi ;result=[DI] CALL DIDRQQ ;[DI]=x/y MOV esi,offset TEMP1 ;[SI]=y CALL ADDRQQ ;[DI]=y+x/y DEC word ptr [edi+Expon] ;[DI]=(y+x/y)/2=TOS MOV esi,edi ;[SI]=sqrt(x) RET ProfEnd FSQRT