299 lines
7.4 KiB
NASM
299 lines
7.4 KiB
NASM
|
page ,132
|
||
|
title 87disp - common transcendental dispatch routine
|
||
|
;***
|
||
|
;87disp.asm - common transcendental dispatch routine (80x87/emulator version)
|
||
|
;
|
||
|
; Copyright (c) 1984-2001, Microsoft Corporation. All rights reserved.
|
||
|
;
|
||
|
;Purpose:
|
||
|
; Common transcendental dispatch routine (80x87/emulator version)
|
||
|
;
|
||
|
;Revision History:
|
||
|
; 07-07-84 GFW initial version
|
||
|
; 11-20-85 GFW mask overflow/underflow/precision exceptions;
|
||
|
; fixed affine/projective infinity confusion
|
||
|
; 09-12-86 BCM added _Flanguage to distinguish languages
|
||
|
; 10-21-86 BCM use _cpower rather than _Flanguage to
|
||
|
; distinguish C and FORTRAN exponentiation semantics
|
||
|
; 06-11-87 GFW faster dispatch code - all in-line
|
||
|
; 10-26-87 BCM minor changes for new cmacros.inc
|
||
|
; 04-25-88 WAJ _cpower is now on stack for MTHREAD
|
||
|
; 08-24-88 WAJ 386 version
|
||
|
; 02-01-92 GDP ported to NT
|
||
|
; 09-06-94 CFW Replace MTHREAD with _MT.
|
||
|
;
|
||
|
;*******************************************************************************
|
||
|
|
||
|
.xlist
|
||
|
include cruntime.inc
|
||
|
include mrt386.inc
|
||
|
include elem87.inc
|
||
|
.list
|
||
|
|
||
|
.data
|
||
|
|
||
|
globalT _indefinite, 0FFFFC000000000000000R
|
||
|
globalT _piby2, 03FFFC90FDAA22168C235R
|
||
|
staticQ One, 03FF0000000000000R
|
||
|
|
||
|
|
||
|
ifndef _MT ; by default assume C pow() semantics
|
||
|
globalB _cpower, 1 ; if zero, assume FORTRAN (or other) exponentiation
|
||
|
endif ;_MT ; semantics
|
||
|
|
||
|
|
||
|
|
||
|
labelB XAMtoTagTab
|
||
|
; C2 C1 C0 C3 Meaning Meaning Tag 0
|
||
|
db 2 * ISIZE ; 0 0 0 0 +Unnormal => NAN 10 0
|
||
|
db 1 * ISIZE ; 0 0 0 1 +Zero => Zero 01 0
|
||
|
db 2 * ISIZE ; 0 0 1 0 +NAN => NAN 10 0
|
||
|
db 2 * ISIZE ; 0 0 1 1 Empty => NAN 10 0
|
||
|
db 2 * ISIZE ; 0 1 0 0 -Unnormal => NAN 10 0
|
||
|
db 1 * ISIZE ; 0 1 0 1 -Zero => Zero 01 0
|
||
|
db 2 * ISIZE ; 0 1 1 0 -NAN => NAN 10 0
|
||
|
db 2 * ISIZE ; 0 1 1 1 Empty => NAN 10 0
|
||
|
db 0 * ISIZE ; 1 0 0 0 +Normal => Valid 00 0
|
||
|
db 1 * ISIZE ; 1 0 0 1 +Denormal => Zero 01 0
|
||
|
db 3 * ISIZE ; 1 0 1 0 +Infinity => Infinity 11 0
|
||
|
db 2 * ISIZE ; 1 0 1 1 Empty => NAN 10 0
|
||
|
db 0 * ISIZE ; 1 1 0 0 -Normal => Valid 00 0
|
||
|
db 1 * ISIZE ; 1 1 0 1 -Denormal => Zero 01 0
|
||
|
db 3 * ISIZE ; 1 1 1 0 -Infinity => Infinity 11 0
|
||
|
db 2 * ISIZE ; 1 1 1 1 Empty => NAN 10 0
|
||
|
|
||
|
|
||
|
CODESEG
|
||
|
|
||
|
xamTOS macro
|
||
|
cmp [rdx].fnumber, OP_SQRT ; check for sqrt
|
||
|
JSNE cwdefault
|
||
|
mov bx, word ptr (DSF.savCntrl)
|
||
|
or bh, 2 ; set precision control to 53 bits
|
||
|
and bh, 0feh
|
||
|
mov bl, 03fh ; mask exceptions
|
||
|
jmp setcw
|
||
|
lab cwdefault
|
||
|
mov bx, 133fh ; default cw
|
||
|
lab setcw
|
||
|
mov DSF.setCntrl, bx ; set new control word
|
||
|
fldcw DSF.setCntrl ; load new control word
|
||
|
mov rbx, dataoffset XAMtoTagTab ; Prepare for XLAT
|
||
|
fxam
|
||
|
mov DSF.Function, rdx ; save function jmp table address
|
||
|
fstsw DSF.StatusWord
|
||
|
mov DSF.ErrorType, 0 ; clear error code
|
||
|
endm
|
||
|
|
||
|
comdisp macro
|
||
|
CBI
|
||
|
and rcx, 0404h ; clear all but signs from CX
|
||
|
mov rbx, rdx
|
||
|
add rbx, rax
|
||
|
add rbx, size funtab ; skip over name, error vals, etc.
|
||
|
jmp [rbx] ; jmp to function
|
||
|
endm
|
||
|
|
||
|
; Will dispatch to the special case routines for the single argument
|
||
|
; transcendental functions. It assumes on entry that the 8087 stack
|
||
|
; has the argument on the top of its stack and that DX has been set
|
||
|
; to the address of the dispatch table (which should be in Tag order).
|
||
|
; This routine will FXAM the top of the 8087 stack, generate Tag info
|
||
|
; from the condition code, and jump to the corresponding dispatch table
|
||
|
; entry. In the process of creating the offset for the XLAT instruction
|
||
|
; bit 2 of CL will be loaded with the sign of the argument. DI may not
|
||
|
; be used in any computations.
|
||
|
|
||
|
_trandisp1 proc near
|
||
|
|
||
|
xamTOS ; setup control word and check TOS
|
||
|
|
||
|
fwait
|
||
|
mov cl, CondCode
|
||
|
shl cl, 1
|
||
|
sar cl, 1
|
||
|
rol cl, 1
|
||
|
mov al, cl
|
||
|
and al, 0fh
|
||
|
xlat
|
||
|
|
||
|
comdisp
|
||
|
|
||
|
_trandisp1 endp
|
||
|
|
||
|
|
||
|
; Will dispatch to the special case routines for the double argument
|
||
|
; transcendental functions. It assumes on entry that the 8087 has arg1
|
||
|
; next to the top and arg2 on top of the 8087 stack and that DX has
|
||
|
; been set to the address of the dispatch table (which should be in
|
||
|
; Tag-arg1,Tag-arg2 order). This routine will FXAM the top two
|
||
|
; registers of the 8087 stack,generate Tag info from the condition
|
||
|
; codes, and jump to the corresponding dispatch table entry. In the
|
||
|
; process of creating the offsets for the XLAT statements bit 2 of
|
||
|
; CH and bit 2 of CL will be loaded with the signs of the arguments
|
||
|
; next to the top and on top, respectively, of the 8087 stack. DI may
|
||
|
; not be used in any computations.
|
||
|
|
||
|
_trandisp2 proc near
|
||
|
|
||
|
xamTOS ; setup control word and check TOS
|
||
|
|
||
|
fxch
|
||
|
mov cl, CondCode
|
||
|
fxam
|
||
|
fstsw DSF.StatusWord
|
||
|
fxch
|
||
|
mov ch, CondCode
|
||
|
shl ch, 1
|
||
|
sar ch, 1
|
||
|
rol ch, 1
|
||
|
mov al, ch
|
||
|
and al, 0fh
|
||
|
xlat
|
||
|
mov ah, al
|
||
|
shl cl, 1
|
||
|
sar cl, 1
|
||
|
rol cl, 1
|
||
|
mov al, cl
|
||
|
and al, 0fh
|
||
|
xlat
|
||
|
shl ah, 1
|
||
|
shl ah, 1
|
||
|
or al, ah
|
||
|
|
||
|
comdisp
|
||
|
|
||
|
_trandisp2 endp
|
||
|
|
||
|
|
||
|
|
||
|
page
|
||
|
;----------------------------------------------------------
|
||
|
;
|
||
|
; SPECIAL CASE RETURN FUNCTIONS
|
||
|
;
|
||
|
;----------------------------------------------------------
|
||
|
;
|
||
|
; INPUTS - The signs of the last, second to last
|
||
|
; arguments are in CH, CL respectively.
|
||
|
;
|
||
|
; OUTPUT - The result is the stack top.
|
||
|
;
|
||
|
;----------------------------------------------------------
|
||
|
|
||
|
labelNP _rttospopde, PUBLIC
|
||
|
call setDOMAIN
|
||
|
|
||
|
labelNP _rttospop, PUBLIC
|
||
|
fxch ; remove ST(1)
|
||
|
|
||
|
labelNP _rtnospop, PUBLIC
|
||
|
fstp st(0) ; remove ST(0)
|
||
|
|
||
|
labelNP _rttosnpop, PUBLIC
|
||
|
ret ; return TOS
|
||
|
|
||
|
labelNP _rtnospopde, PUBLIC
|
||
|
call setDOMAIN
|
||
|
jmp _rtnospop
|
||
|
|
||
|
|
||
|
;----------------------------------------------------------
|
||
|
|
||
|
labelNP _rtzeropop, PUBLIC
|
||
|
fstp st(0) ; remove ST(0)
|
||
|
|
||
|
labelNP _rtzeronpop, PUBLIC
|
||
|
fstp st(0) ; remove ST(0)
|
||
|
fldz ; push 0.0 onto stack
|
||
|
ret
|
||
|
|
||
|
;----------------------------------------------------------
|
||
|
|
||
|
labelNP _rtonepop, PUBLIC
|
||
|
fstp st(0) ; remove ST(0)
|
||
|
|
||
|
labelNP _rtonenpop, PUBLIC
|
||
|
fstp st(0) ; remove ST(0)
|
||
|
fld1 ; push 1.0 onto stack
|
||
|
ret
|
||
|
|
||
|
;----------------------------------------------------------
|
||
|
|
||
|
isQNAN macro
|
||
|
fstp DSF.Fac ; use ten byte storage
|
||
|
fld DSF.Fac
|
||
|
test byte ptr [DSF.Fac+7], 40h ; Test for QNaN or SNaN
|
||
|
endm
|
||
|
|
||
|
|
||
|
labelNP _tosnan1, PUBLIC ; ST(0) is a NaN
|
||
|
isQNAN
|
||
|
JSZ _tossnan1
|
||
|
mov DSF.Errortype, DOMAIN_QNAN
|
||
|
ret
|
||
|
lab _tossnan1
|
||
|
mov DSF.Errortype, DOMAIN
|
||
|
fadd [One] ; Convert SNaN to QNaN
|
||
|
ret
|
||
|
|
||
|
labelNP _nosnan2, PUBLIC ; ST(1) is a NaN
|
||
|
fxch
|
||
|
labelNP _tosnan2, PUBLIC ; ST(0) is a NaN
|
||
|
isQNAN
|
||
|
JSZ _tossnan2
|
||
|
mov DSF.Errortype, DOMAIN_QNAN
|
||
|
jmp _tosnan2ret
|
||
|
lab _tossnan2
|
||
|
mov DSF.Errortype, DOMAIN
|
||
|
lab _tosnan2ret
|
||
|
fadd ; Propagate NaN and pop
|
||
|
ret
|
||
|
|
||
|
labelNP _nan2, PUBLIC
|
||
|
isQNAN
|
||
|
JSZ _snan2
|
||
|
fxch
|
||
|
isQNAN
|
||
|
JSZ _snan2
|
||
|
mov DSF.Errortype, DOMAIN_QNAN
|
||
|
jmp _nan2ret
|
||
|
lab _snan2
|
||
|
mov DSF.Errortype, DOMAIN
|
||
|
lab _nan2ret
|
||
|
fadd ; Propagate NaN and pop
|
||
|
ret
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
;----------------------------------------------------------
|
||
|
|
||
|
labelNP _rtindfpop, PUBLIC
|
||
|
fstp st(0) ; remove ST(0)
|
||
|
|
||
|
labelNP _rtindfnpop, PUBLIC
|
||
|
fstp st(0) ; remove ST(0)
|
||
|
fld [_indefinite] ; push real indefinite onto stack
|
||
|
cmp DSF.ErrorType, 0 ; if error set
|
||
|
JSG retj ; must be SING, don't set DOMAIN
|
||
|
|
||
|
labelNP _rttosnpopde, PUBLIC
|
||
|
lab setDOMAIN
|
||
|
mov DSF.ErrorType, DOMAIN
|
||
|
lab retj
|
||
|
or cl, cl ; test sign in cl
|
||
|
ret
|
||
|
|
||
|
|
||
|
;----------------------------------------------------------
|
||
|
|
||
|
labelNP _rtchsifneg, PUBLIC
|
||
|
or cl, cl ; if arg is negative
|
||
|
JSZ chsifnegret ; negate top of stack
|
||
|
fchs
|
||
|
lab chsifnegret
|
||
|
ret
|
||
|
|
||
|
end
|