Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

571 lines
10 KiB

; SCCSID = @(#)emsincos.asm 13.5 90/03/27
page ,132
subttl emsincos - fsin, fcos and fsincos
;***
;emulator.asm - 80387 emulator
;
; IBM/Microsoft Confidential
;
; Copyright (c) IBM Corporation 1987, 1989
; Copyright (c) Microsoft Corporation 1987, 1989
;
; All Rights Reserved
;
;Purpose:
; Code for fsin, fcos and fsincos
;
;Revision History:
; See emulator.hst
;
;*******************************************************************************
lab eFsincosStackOver
or SEL[CURerr], StackFlag or Invalid
test SEL[CWmask], Invalid
JSZ eFsincosStackOverRet
mov SEL[rsi.lMan0], 0 ; st(0) = Ind
mov SEL[rsi.lMan1], 0c0000000h
mov SEL[rsi.wExp], 7fffh - IexpBias
mov SEL[rsi.bTag], bTAG_NAN
mov SEL[rsi.bFlags], bSign
mov SEL[rdi.lMan0], 0 ; st(-1) = Ind
mov SEL[rdi.lMan1], 0c0000000h
mov SEL[rdi.wExp], 7fffh - IexpBias
mov SEL[rdi.bTag], bTAG_NAN
mov SEL[rdi.bFlags], bSign
mov SEL[CURstk], rdi ; push stack
lab eFsincosStackOverRet
ret
lab eFSINCOS
mov esi, SEL[CURStk] ; esi = st(0)
mov edi, esi
PrevStackElem edi ; edi = st(-1)
cmp SEL[edi.bTag], bTAG_EMPTY
JSNE eFsincosStackOver
cmp SEL[esi.bTag], bTAG_NAN
JSNE eFsincosNotSNaN
test SEL[esi.bMan7], 40h
JSNZ eFsincosNotSNaN
test SEL[CWmask], Invalid
JSNZ eFsincosNotSNaN
or SEL[CURerr], Invalid
ret
lab eFsincosNotSNaN
ifdef NT386
push eax
mov eax, dword ptr SEL[rsi]
mov dword ptr SEL[rdi], eax
mov eax, dword ptr SEL[rsi+4]
mov dword ptr SEL[rdi+4], eax
mov eax, dword ptr SEL[rsi+8]
mov dword ptr SEL[rdi+8], eax
add rsi, Reg87Len
add rdi, Reg87Len
pop eax
else
push ds ; Copy current stack into st(-1)
pop es
movsd
movsd
movsd
endif
call eFSIN
PUSHST
call eFCOS
ret
lab eFcosSpecial
mov esp, ebp
pop ebp
mov SEL[RESULT], esi
mov al, SEL[esi.bTag]
cmp al, bTAG_ZERO
JSNE eFcosInf
lab eFcosRetOne
mov SEL[esi.lMan0], 0
mov SEL[esi.lMan1], 080000000h
mov SEL[esi.wExp], 3fffh - IexpBias
mov SEL[esi.bFlags], 0
mov SEL[esi.bTag], bTAG_VALID
ret
lab eFcosInf
cmp al, bTAG_INF
JE RetIndInv
lab eFcosNaN
jmp OneArgOpNaNRet
cProc eFCOS,<PLM,PUBLIC>,<>
localT temp
localB SignFlag
cBegin
mov esi, SEL[CURstk]
cmp SEL[esi.bTag], bTAG_VALID
jne eFcosSpecial
or SEL[CURerr], Precision
and SEL[esi].bFlags, not bSign ; st(0) = fabs( st(0) );
call SinCosReduce ; Set ah to condition code.
add SEL[esi].wExp, IExpBias
push SEL[esi].wExp
push SEL[esi].lMan1
push SEL[esi].lMan0
lea ecx, [temp]
push ecx
mov bl, ah ; if octant 2, 3, 4, or 5 then final
and bl, bOCT2 or bOCT4 ; result must be negative
mov [SignFlag], bl
test ah, bOCT1 or bOCT2 ; if octant is 1, 2, 5, 6 then must
jpo CosCallSin ; do sin()
call __FASTLDCOS
jmp short CosCopyRes
CosCallSin:
call __FASTLDSIN
CosCopyRes:
mov eax, dword ptr [temp]
mov SEL[esi].lMan0, eax
mov eax, dword ptr [temp+4]
mov SEL[esi].lMan1, eax
mov ax, word ptr [temp+8]
sub ax, IExpBias
mov SEL[esi].wExp, ax
cmp [SignFlag], 0
jpe CosDone
or SEL[esi].bFlags, bSign ; Make result negative.
CosDone:
cEnd
lab eFsinSpecial
mov esp, ebp
pop ebp
mov al, SEL[esi.bTag]
cmp al, bTAG_ZERO
JSNE eFsinInf
lab eFsinZero
ret
lab eFsinInf
cmp al, bTAG_INF
JE RetIndInv
lab eFsinNaN
jmp OneArgOpNaNRet
cProc eFSIN,<PLM,PUBLIC>,<>
localT temp
localB SignFlag
cBegin
mov esi, SEL[CURstk]
cmp SEL[esi.bTag], bTAG_VALID
jne eFsinSpecial
or SEL[CURerr], Precision
mov al, SEL[esi].bFlags
and SEL[esi].bFlags, not bSign
shl al, 1 ; shift sign into carry.
sbb cl, cl ; set cl to -1 if argument is negative.
push ecx
call SinCosReduce ; Set ah to condition code.
pop ecx
cmp SEL[esi].bTag, bTAG_ZERO
je SinDone
add SEL[esi].wExp, IExpBias
push SEL[esi].wExp
push SEL[esi].lMan1
push SEL[esi].lMan0
lea ebx, [temp]
push ebx
mov bl, ah ; if octant 4, 5, 6 or 7 then final
and bl, bOCT4 ; result must be negative
neg cl ; set cl to odd parity if arg was < 0.0
xor bl, cl ; set bl to odd parity if result must be negative
mov [SignFlag], bl
test ah, bOCT1 or bOCT2 ; if octant is 1, 2, 5, 6 then must
jpo SinCallCos ; do cos()
call __FASTLDSIN
jmp short SinCopyResult
SinCallCos:
call __FASTLDCOS
SinCopyResult:
mov eax, dword ptr [temp]
mov SEL[esi].lMan0, eax
mov eax, dword ptr [temp+4]
mov SEL[esi].lMan1, eax
mov ax, word ptr [temp+8]
sub ax, IExpBias
mov SEL[esi].wExp, ax
cmp [SignFlag], 0
jpe SinDone
or SEL[esi].bFlags, bSign ; Make result negative.
SinDone:
cEnd
lab SinCosReduce
mov SEL[TEMP1.bFlags], 0 ; TEMP1 = pi/4
mov SEL[TEMP1.bTag], bTAG_VALID
mov SEL[TEMP1.wExp], 3ffeh-IExpBias
mov SEL[TEMP1.wMan3], 0c90fh
mov SEL[TEMP1.wMan2], 0daa2h
mov SEL[TEMP1.wMan1], 2168h
mov SEL[TEMP1.wMan0], 0c235h
ifdef NT386
mov edi, TEMP1
else
mov edi, edataOFFSET TEMP1
endif
push esi
call InternFPREM ; rsi = st(0), rdi = st(0)
pop esi
mov ah, SEL[SWcc]
test ah, bOCT1 ; check for even octant
jz EvenOct ; yes
add SEL[esi.wExp], IExpBias ; convert to true long double
push ds
push esi
push cs
push ecodeOFFSET PIBY4
push ds
push esi
push -1
call __FASTLDADD ; st(0) = pi/4 - st(0)
mov ah, SEL[SWcc]
sub SEL[esi.wExp], IExpBias ; convert to squirly emulator long double
EvenOct:
retn
labelW PIBY4
dw 0c235h, 02168h, 0daa2h, 0c90fh, 3ffeh
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; NOTE tedm: NT masm can't handle floating-point constants ;
; because strtod and _strtold C-runtimes aren't ;
; there. So the constants below must be pre- ;
; assembled and defined as a byte stream. ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ifdef NOTDEF
staticT FourByPI, +0.1273239544735162686151e+01
staticT SinP0, +0.7853981633974483096141845e+00
staticT SinP1, -0.8074551218828078152025820e-01
staticT SinP2, +0.2490394570192716275251900e-02
staticT SinP3, -0.3657620418214640005290000e-04
staticT SinP4, +0.3133616889173253480000000e-06
staticT SinP5, -0.1757247417617080600000000e-08
staticT SinP6, +0.6948152035052200000000000e-11
staticT SinP7, -0.2022531292930000000000000e-13
staticT CosP0, +0.99999999999999999996415e+00
staticT CosP1, -0.30842513753404245242414e+00
staticT CosP2, +0.15854344243815410897540e-01
staticT CosP3, -0.32599188692668755044000e-03
staticT CosP4, +0.35908604458858195300000e-05
staticT CosP5, -0.24611363826370050000000e-07
staticT CosP6, +0.11500497024263000000000e-09
staticT CosP7, -0.38577620372000000000000e-12
else
staticB FourByPI, <02Ah,015h,044h,04Eh,06Eh,083h,0F9h,0A2h,0FFh,03Fh>
staticB SinP0 , <035h,0C2h,068h,021h,0A2h,0DAh,00Fh,0C9h,0FEh,03Fh>
staticB SinP1 , <0DAh,095h,0F2h,02Dh,031h,0E7h,05Dh,0A5h,0FBh,0BFh>
staticB SinP2 , <0E9h,0C6h,056h,0ADh,03Bh,0E3h,035h,0A3h,0F6h,03Fh>
staticB SinP3 , <0D5h,0E7h,05Dh,015h,073h,066h,069h,099h,0F0h,0BFh>
staticB SinP4 , <0BCh,032h,069h,0E1h,042h,01Ah,03Ch,0A8h,0E9h,03Fh>
staticB SinP5 , <021h,077h,004h,05Fh,0A1h,0A5h,083h,0F1h,0E1h,0BFh>
staticB SinP6 , <0FCh,01Ah,0D1h,006h,0CCh,063h,077h,0F4h,0D9h,03Fh>
staticB SinP7 , <04Ah,003h,086h,040h,07Ch,065h,02Ch,0B6h,0D1h,0BFh>
staticB CosP0 , <0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FEh,03Fh>
staticB CosP1 , <02Fh,0F2h,02Eh,0F2h,04Dh,0E6h,0E9h,09Dh,0FDh,0BFh>
staticB CosP2 , <02Fh,04Eh,0D5h,0DAh,040h,0F8h,0E0h,081h,0F9h,03Fh>
staticB CosP3 , <09Dh,0DEh,06Ah,0E4h,0F1h,0E3h,0E9h,0AAh,0F3h,0BFh>
staticB CosP4 , <031h,01Eh,0F9h,081h,041h,083h,0FAh,0F0h,0ECh,03Fh>
staticB CosP5 , <076h,0B1h,000h,0A4h,01Eh,0F6h,068h,0D3h,0E5h,0BFh>
staticB CosP6 , <0D8h,005h,06Fh,08Ah,0EAh,00Ah,0E6h,0FCh,0DDh,03Fh>
staticB CosP7 , <003h,0D5h,00Ah,0ACh,0CCh,035h,02Ch,0D9h,0D5h,0BFh>
endif
cProc __FASTLDSIN,<PLM,PUBLIC>,<isi,idi>
parmT x
parmI RetOff
localT x2
localT poly
localI count
cBegin
lea isi, [x] ; x = x * (4/PI)
push ss
push isi
push ss
push isi
mov iax, codeOFFSET FourByPI
push cs
push iax
call __FASTLDMULT
lea idi, [x2] ; x2 = x * x
push ss
push idi
push ss
push isi
push ss
push isi
call __FASTLDMULT
if 0
push ss
pop es
lea idi, [poly]
mov isi, codeOFFSET SinP7
movsw
movsw
movsw
movsw
movsw
endif
mov eax, dword ptr [SinP7] ; poly = SinP7
mov dword ptr [poly], eax
mov eax, dword ptr [SinP7+4]
mov dword ptr [poly+4], eax
mov ax, word ptr [SinP7+8]
mov word ptr [poly+8], ax
lea isi, [poly]
mov idi, codeOFFSET SinP6
mov [count], 7
SinPolyLoop:
push ss
push isi ; poly = poly * x2
push ss
push isi
lea iax, [x2]
push ss
push iax
call __FASTLDMULT
push ss
push isi ; poly = poly + SinP[n]
push ss
push isi
push cs
push idi
xor iax, iax
push iax
call __FASTLDADD
sub idi, 10
dec [count]
jnz SinPolyLoop
push ss
push [RetOff] ; return x * poly
lea iax, [x]
push ss
push iax
push ss
push isi
call __FASTLDMULT
mov iax, [RetOff]
mov idx, ss
cEnd
cProc __FASTLDCOS,<PLM,PUBLIC>,<isi,idi>
parmT x
parmI RetOff
localT x2
localI count
cBegin
lea isi, [x] ; x = x * (4/PI)
push ss
push isi
push ss
push isi
mov iax, codeOFFSET FourByPI
push cs
push iax
call __FASTLDMULT
lea idi, [x2] ; x2 = x * x
push ss
push idi
push ss
push isi
push ss
push isi
call __FASTLDMULT
if 0
push ss ; (return) = CosP7
pop es
mov idi, [RetOff]
mov isi, codeOFFSET CosP7
movsw
movsw
movsw
movsw
movsw
endif
mov isi, [RetOff]
mov eax, dword ptr [CosP7]
mov dword ptr ss:[isi], eax
mov eax, dword ptr [CosP7+4]
mov dword ptr ss:[isi+4], eax
mov ax, word ptr [CosP7+8]
mov word ptr ss:[isi+8], ax
mov idi, codeOFFSET CosP6
mov [count], 7
CosPolyLoop:
push ss
push isi ; (return) = (return) * x2
push ss
push isi
lea iax, [x2]
push ss
push iax
call __FASTLDMULT
push ss
push isi ; (return) = (return) + SinP[n]
push ss
push isi
push cs
push idi
xor iax, iax
push iax
call __FASTLDADD
sub idi, 10
dec [count]
jnz CosPolyLoop
mov iax, isi
mov idx, ss
cEnd