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
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
|