page ,132 subttl emftran.asm - Transcendentals ;*** ;emftran.asm - Transcendentals ; ; Copyright (c) 1986-89, Microsoft Corporation ; ;Purpose: ; Transcendentals ; ; This Module contains Proprietary Information of Microsoft ; Corporation and should be treated as Confidential. ; ;Revision History: ; See emulator.hst ; ;******************************************************************************* ;-----------------------------------------; ; ; ; Transcendentals ; ; ; ;-----------------------------------------; ProfBegin FTRAN pub MoveCodeSItoDataSI PUSH edi MOV edi,offset COEFFICIENT ifdef i386 rept Reg87Len/4 MOVS dword ptr es:[edi],dword ptr cs:[esi] endm else rept Reg87Len/2 MOVS word ptr es:[edi],word ptr cs:[esi] endm endif MOV esi,offset COEFFICIENT POP edi RET ;--------------------------------------------------- ; ! ; 8087 emulator transcendental utilities ! ; ! ;--------------------------------------------------- ; COMPcsSIDI is analogous to the 8086 CMP instruction with operands ; cs:[SI],[DI]. All registers except CX and DX are left unaltered. ; Zero and negative zero are determined to be unequal. NAN's and ; infinities may not be compared with this routine. ; ; FRAT2X performs {TOS=[DI]} <-- {TOS=[SI]}*PNUM({TOS=[SI]}^2), ; and program created {temp=[SI]} <-- PDEN({TOS=[SI]}^2). On input, ; [BX] must contain the degree of PNUM, the coefficients of PNUM ; in descending order, the degree-1 of PDEN and the coefficients ; of PDEN in descending order. PDEN is evaluated assuming an implied ; highest coefficient of one. [BX] is left unaltered, ARG2 is loaded ; with {TOS}^2, DENORX is used, all registers are destroyed with ; DI returning the value input in SI. pub BOTHZERO CMP CH,CH ;set flags to equal JMP short COMPDONE ;compare finished pub COMPcsSIDI MOV CX,CS MOV DS,CX MOV CX,[esi+Flag] ;get sign byte of [SI] AND CL,Sign ;mask for sign MOV DX,ES:[edi+Flag] ;get sign byte of [DI] AND DL,Sign ;mask for sign CMP DL,CL ;compare signs JNE short SIGNDIFF PUSH ES PUSH esi PUSH edi ;save pointers OR CL,CL ;if signs are + JNS short BOTHPOS ; don't exchange pointers PUSH DS PUSH ES POP DS POP ES XCHG esi,edi ;exchange pointers XCHG CX,DX ;exchange flags pub BOTHPOS AND CH,ZROorINF ;mask for zero AND DH,ZROorINF ;mask for zero CMP DH,CH ;if exactly one zero JNE short COMPDONE ; then finished OR CH,CH ;if both zero JA BOTHZERO ; then done after flags set MOV CX,[esi+Expon] ;get exponent of [SI] ADD CX,IexpBias ;make it unbiased MOV DX,ES:[edi+Expon] ;get exponent of [DI] ADD DX,IexpBias ;make it unbiased CMP CX,DX JNE short COMPDONE ;compare exponents ADD esi,MB6 ADD edi,MB6 STD CMPS word ptr [edi],word ptr [esi] JNE short COMPDONE CMPS word ptr [edi],word ptr [esi] JNE short COMPDONE CMPS word ptr [edi],word ptr [esi] JNE short COMPDONE CMPS word ptr [edi],word ptr [esi] ;compare mantissas pub COMPDONE CLD POP edi POP esi POP ES pub SIGNDIFF MOV CX,ES MOV DS,CX RET pub FRAT2X MOV edi,offset DENORX ;[DI]=temp CALL MOVRQQ ;[DI]=x=temp PUSH edi ;save ptr to x=temp PUSH esi ;save ptr to TOS PUSH ebx ;save ptr to polynomials MOV edi,offset ARG2 ;get ptr to space for x^2 CALL MOVRQQ ;copy x to space for x^2 MOV [RESULT],edi ;result=[DI] CALL MUDRQQ ;ARG2 gets x^2 POP esi ;get ptr to numerator poly ifdef i386 xor ecx,ecx endif LODS word ptr CS:[esi] XCHG CX,AX ;CX=denominator degree-1 POP edi ;[DI]=TOS CALL csMOVRQQ ;[DI]=first coeff=TOS MOV [RESULT],edi ;result=[DI] pub POLYLOOPA PUSH ecx ;save no. of terms left PUSH esi ;save ptr to next coeff MOV esi,offset ARG2 ;get ptr to x^2 CALL MUDRQQ ;multiply TOS by x^2 POP esi ;get pointer to coeff ADD esi,Reg87Len ;point to next coeff PUSH esi ;save pointer to coeff CALL MoveCodeSItoDataSI CALL ADDRQQ ;add coeff to TOS POP esi ;get ptr to coeff POP ecx ;get no. of terms remaining LOOP POLYLOOPA ;loop until no terms left MOV ebx,esi ;move poly ptr POP esi ;[SI]=x=temp PUSH esi ;save ptr to x PUSH ebx ;save poly ptr CALL MUDRQQ ;multiply poly by x POP esi ;get ptr to poly ADD esi,12 ;[SI]=denominator degree-1 ifdef i386 xor ecx,ecx endif LODS word ptr CS:[esi] XCHG CX,AX ;CX=denominator degree-1 POP ebx ;[BX]=temp PUSH edi ;save denominator ptr MOV edi,ebx ;[DI]=temp CALL csMOVRQQ ;move second coeff to temp PUSH ecx ;save poly degree-1 PUSH esi ;save ptr to denominator poly MOV esi,offset ARG2 ;get ptr to x^2 MOV [RESULT],edi ;result=[DI] CALL ADDRQQ ;add x^2 to temp POP esi ;get ptr to second coeff POP ecx ;get poly degree-1 pub POLYLOOPB PUSH ecx ;save no. of terms left ADD esi,Reg87Len ;point to next coeff PUSH esi ;save ptr to next coeff MOV esi,offset ARG2 ;get ptr to x^2 CALL MUDRQQ ;multiply temp by x^2 POP esi ;get pointer to coeff PUSH esi ;save pointer to coeff CALL MoveCodeSItoDataSI CALL ADDRQQ ;add coeff to temp POP esi ;get ptr to coeff POP ecx ;get no. of terms remaining LOOP POLYLOOPB ;loop until no terms left MOV esi,edi ;[SI]=denominator=temp POP edi ;[DI]=numerator=TOS RET ;------------------------------------------------------------------------------- pub eFPTAN MOV esi,[CURstk] CALL $FPTAN PUSH esi PUSHST MOV edi,[CURstk] POP esi CALL MOVRQQ RET ;--------------------------------------------------- ; ! ; 8087 emulator partial tangent ! ; ! ;--------------------------------------------------- ; When 0<=x={TOS=[SI]}<=pi/4 then $FPTAN performs {TOS=[DI]} <-- ; numerator tangent ({TOS=[SI]}), system created {temp=[SI]} <-- ; denominator tangent ({TOS=[SI]). Every register except DI is ; destroyed. pub $FPTAN MOV ebx,offset TANRAT ;[BX]=rational function CALL FRAT2X ;[DI]=numerator=TOS, RET ; [SI]=denominator=temp ;------------------------------------------------------------------------------- pub eFPATAN MOV edi,[CURstk] MOV esi,edi MOV AX,Flag[esi] SUB edi,Reg87Len pub CALLFPATAN CALL $FPATAN MOV esi,[CURstk] POPST RET ;--------------------------------------------------- ; ! ; 8087 emulator arctangent ! ; ! ;--------------------------------------------------- ; When 0= x JNB short ATNREDUCED ; then bypass arg reduction MOV esi,edi ;[SI]=x=NOS MOV edi,offset TEMP1 ;[DI]=temp CALL MOVRQQ ;[DI]=x=temp PUSH esi ;save NOS MOV esi,offset RT3 ;[SI]=3^.5 CALL MoveCodeSItoDataSI MOV [RESULT],edi ;result=[DI] CALL MUDRQQ ;[DI]=3^.5*x=temp MOV esi,offset cFLD1 ;[SI]=1 CALL MoveCodeSItoDataSI CALL SUDRQQ ;[DI]=3^.5*x-1 POP esi ;get NOS PUSH edi ;save ptr to 3^.5*x-1 MOV edi,esi ;DI gets NOS MOV esi,offset RT3 ;[SI]=3^.5 CALL MoveCodeSItoDataSI MOV [RESULT],edi ;result=[DI] CALL ADDRQQ ;[DI]=x+3^.5=NOS POP esi ;[SI]=3^.5*x-1 CALL DRDRQQ ;[DI]=(3^.5*x-1)/(x+3^.5)=NOS MOV AL,1 ;flag set pub ATNREDUCED PUSH eax ;save flag MOV esi,edi ;[SI]=reduced x=NOS MOV ebx,offset ATNRAT ;[BX]=rational function CALL FRAT2X ;[DI]=numerator=NOS, ; [SI]=denominator=temp MOV [RESULT],edi ;result=[DI] CALL DIDRQQ ;[DI]=arctan(reduced x)=NOS POP eax ;get flag OR AL,AL ;if flag=0 JZ short ATNCOMPLETE ; bypass adjust MOV esi,offset PIBY6 ;[SI]=pi/6 CALL MoveCodeSItoDataSI CALL ADDRQQ ;[DI]=arctan(x)=NOS pub ATNCOMPLETE RET ;------------------------------------------------------------------------------- pub eF2XM1 MOV esi,[CURstk] CALL $F2XM1 RET ;--------------------------------------------------- ; ! ; 8087 emulator exponential ! ; ! ;--------------------------------------------------- ; When 0<=x={TOS=[SI]}<=.5 then $F2XM1 performs {TOS=[SI]} <-- ; 2^{TOS=[SI]}-1. All registers except SI are destroyed. pub $F2XM1 MOV ebx,offset EXPRAT ;[BX]=rational function CALL FRAT2X ;[DI]=numerator=TOS PUSH edi ;save numerator=TOS XCHG esi,edi ;[SI]=numerator, [DI]=denominator MOV [RESULT],edi ;result=[DI] CALL SUDRQQ ;[DI]=denominator-numerator MOV esi,edi ;[SI]=denominator-numerator POP edi ;[DI]=numerator=TOS MOV [RESULT],edi ;result=[DI] CALL DIDRQQ ;[DI]=(2^x-1)/2 INC word ptr [edi+Expon] ;[DI]=2^x-1 MOV esi,edi ;[SI]=2^x-1 RET ;------------------------------------------------------------------------------- pub eFYL2X MOV edi,[CURstk] MOV esi,edi MOV AX,Flag[esi] SUB edi,Reg87Len pub CALLFYL2X CALL $FYL2X MOV esi,[CURstk] POPST RET ;--------------------------------------------------- ; ! ; 8087 emulator multiple of logarithm ! ; ! ;--------------------------------------------------- ; When -infinity