789 lines
21 KiB
NASM
789 lines
21 KiB
NASM
;FpuAtoFL PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuFLtoA PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
|
|
|
;FpuAdd PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
|
;FpuSub PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
|
;FpuMul PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
|
;FpuDiv PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
|
;FpuSqrt PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuXexpY PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
|
;FpuAbs PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuTrunc PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuRound PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuChs PROTO :DWORD,:DWORD,:DWORD
|
|
|
|
;FpuLnx PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuLogx PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuEexpX PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuTexpX PROTO :DWORD,:DWORD,:DWORD
|
|
|
|
;FpuSin PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuCos PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuTan PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuArcsin PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuArccos PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuArctan PROTO :DWORD,:DWORD,:DWORD
|
|
|
|
;FpuSinh PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuCosh PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuTanh PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuArcsinh PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuArccosh PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuArctanh PROTO :DWORD,:DWORD,:DWORD
|
|
|
|
;FpuSize PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuComp PROTO :DWORD,:DWORD,:DWORD
|
|
;FpuExam PROTO :DWORD,:DWORD
|
|
;FpuState PROTO :DWORD
|
|
|
|
SRC1_FPU EQU 1
|
|
SRC1_REAL EQU 2
|
|
SRC1_DMEM EQU 4
|
|
SRC1_DIMM EQU 8
|
|
SRC1_CONST EQU 16
|
|
|
|
ANG_DEG EQU 0
|
|
ANG_RAD EQU 32
|
|
|
|
DEST_MEM EQU 0
|
|
DEST_IMEM EQU 64
|
|
DEST_FPU EQU 128
|
|
|
|
SRC2_FPU EQU 256
|
|
SRC2_REAL EQU 512
|
|
SRC2_DMEM EQU 1024
|
|
SRC2_DIMM EQU 2048
|
|
SRC2_CONST EQU 4096
|
|
|
|
STR_REG EQU 0
|
|
STR_SCI EQU 32768
|
|
|
|
FPU_PI EQU 1
|
|
FPU_NAPIER EQU 2
|
|
|
|
XAM_VALID EQU 1
|
|
XAM_ZERO EQU 2
|
|
XAM_NEG EQU 4
|
|
XAM_SMALL EQU 8
|
|
XAM_INFINIT EQU 16
|
|
|
|
CMP_EQU EQU 1
|
|
CMP_GREATER EQU 2
|
|
CMP_LOWER EQU 4
|
|
|
|
|
|
|
|
|
|
; #########################################################################
|
|
;
|
|
; FpuFLtoA
|
|
;
|
|
;##########################################################################
|
|
|
|
; -----------------------------------------------------------------------
|
|
; This procedure was written by Raymond Filiatreault, December 2002
|
|
; and modified April 2003. A minor flaw was corrected in July 2003.
|
|
; Modified March 2004 to avoid any potential data loss from the FPU
|
|
;
|
|
; This FpuFLtoA function converts an 80-bit REAL number (Src) to its
|
|
; decimal representation as a zero terminated alphanumeric string which
|
|
; is returned at the specified memory destination unless an invalid
|
|
; operation is reported by the FPU or the definition of the parameters
|
|
; (with uID) is invalid.
|
|
;
|
|
; The format of the string can be specified as regular (default) or
|
|
; scientific notation. The number of decimal places returned must also be
|
|
; specified but the total number of significant digits must not exceed 16.
|
|
; When the regular format is specified, the integer portion can also be
|
|
; padded with preceding spaces to position the decimal point at a
|
|
; specified location from the start of the string.
|
|
;
|
|
; The source can be an 80-bit REAL number from the FPU itself or from
|
|
; memory.
|
|
;
|
|
; The source is not checked for validity. This is the programmer's
|
|
; responsibility.
|
|
;
|
|
; This procedure is based on using an FPU instruction to convert the
|
|
; REAL number into a specific packed decimal format. After unpacking,
|
|
; the decimal point is positioned as required.
|
|
;
|
|
; Only EAX is used to return error or success. All other CPU registers
|
|
; are preserved. All FPU registers are preserved.
|
|
;
|
|
; -----------------------------------------------------------------------
|
|
|
|
|
|
; #########################################################################
|
|
align 4
|
|
proc FpuFLtoA stdcall, lpSrc:DWORD, lpDecimal:DWORD, lpDest:DWORD, uID:DWORD
|
|
|
|
locals
|
|
tempdw dd ?
|
|
esize dd ?
|
|
Padding dd ?
|
|
Decimal dd ?
|
|
content: times 108 db ?
|
|
tempst dt ?
|
|
bcdstr dt ?
|
|
oldcw dw ?
|
|
truncw dw ?
|
|
unpacked: times 20 db ?
|
|
endl
|
|
|
|
;get the specified number of decimals for result
|
|
;and make corrections if necessary
|
|
|
|
mov eax,[lpDecimal]
|
|
test [uID],SRC2_DMEM
|
|
jz @F
|
|
mov eax,[eax] ;get the decimals from memory
|
|
@@:
|
|
push eax
|
|
movzx eax,al ;low byte - number of decimal digits
|
|
cmp eax,15
|
|
jbe @F
|
|
mov eax,15 ;a maximum of 15 decimals is allowed
|
|
@@:
|
|
mov [Decimal],eax
|
|
pop eax
|
|
movzx eax,ah ;2nd byte - number of char before decimal point
|
|
cmp eax,17
|
|
jbe @F
|
|
mov eax,17 ;a maximum of 17 characters is allowed
|
|
@@:
|
|
mov [Padding],eax
|
|
|
|
test [uID],SRC1_FPU ;is data taken from FPU?
|
|
jz @F ;continue if not
|
|
|
|
;-------------------------------
|
|
;check if top register is empty
|
|
;-------------------------------
|
|
|
|
fxam ;examine its content
|
|
fstsw ax ;store results in AX
|
|
fwait ;for precaution
|
|
sahf ;transfer result bits to CPU flag
|
|
jnc @F ;not empty if Carry flag not set
|
|
jpe @F ;not empty if Parity flag set
|
|
jz srcerr1 ;empty if Zero flag set
|
|
|
|
@@:
|
|
fsave [content]
|
|
|
|
;----------------------------------------
|
|
;check source for Src and load it to FPU
|
|
;----------------------------------------
|
|
|
|
test [uID],SRC1_FPU
|
|
jz @F
|
|
lea eax,[content]
|
|
fld tbyte [eax+28]
|
|
jmp dest0
|
|
|
|
@@:
|
|
test [uID],SRC1_REAL ;is Src an 80-bit REAL in memory?
|
|
jz srcerr ;no proper source identificaiton
|
|
mov eax,[lpSrc]
|
|
fld tbyte [eax]
|
|
jmp dest0 ;go complete process
|
|
|
|
srcerr:
|
|
frstor [content]
|
|
srcerr1:
|
|
push edi
|
|
mov edi,[lpDest]
|
|
mov eax,"ERRO";ORRE"
|
|
stosd
|
|
mov ax,"R"
|
|
stosw
|
|
pop edi
|
|
xor eax,eax
|
|
ret
|
|
|
|
dest0:
|
|
|
|
;-------------------------------------------
|
|
;first examine the value on FPU for validity
|
|
;-------------------------------------------
|
|
|
|
fxam ;examine value on FPU
|
|
fstsw ax ;get result
|
|
fwait
|
|
sahf ;transfer to CPU flags
|
|
jz maybezero
|
|
jpo srcerr ;C3=0 and C2=0 would be NAN or unsupported
|
|
jnc getnumsize ;continue if normal finite number
|
|
|
|
;--------------------------------
|
|
;value to be converted = INFINITY
|
|
;--------------------------------
|
|
|
|
push ecx
|
|
push esi
|
|
push edi
|
|
mov edi,[lpDest]
|
|
mov al,"+"
|
|
test ah,2 ;C1 field = sign
|
|
jz @F
|
|
mov al,"-"
|
|
@@:
|
|
stosb
|
|
mov eax,"INFI";IFNI"
|
|
stosd
|
|
mov eax,"NITY";YTIN"
|
|
stosd
|
|
jmp finish
|
|
|
|
;-------------------------
|
|
;value to be converted = 0
|
|
;-------------------------
|
|
|
|
maybezero:
|
|
jpe getnumsize ;would be denormalized number
|
|
fstp st0 ;flush that 0 value off the FPU
|
|
push ecx
|
|
push esi
|
|
push edi
|
|
mov edi,[lpDest]
|
|
test [uID],STR_SCI ;scientific notation?
|
|
jnz @F ;no padding
|
|
mov ecx,[Padding]
|
|
sub ecx,2
|
|
jle @F ;no padding specified or necessary
|
|
mov al," "
|
|
rep stosb
|
|
@@:
|
|
mov ax,3020h ;" 0" szstring
|
|
stosw ;write it
|
|
jmp finish
|
|
|
|
;---------------------------
|
|
; get the size of the number
|
|
;---------------------------
|
|
|
|
getnumsize:
|
|
fldlg2 ;log10(2)
|
|
fld st1 ;copy Src
|
|
fabs ;insures a positive value
|
|
fyl2x ;->[log2(Src)]*[log10(2)] = log10(Src)
|
|
|
|
fstcw [oldcw] ;get current control word
|
|
fwait
|
|
mov ax,[oldcw]
|
|
or ax,0c00h ;code it for truncating
|
|
mov [truncw],ax
|
|
fldcw [truncw] ;insure rounding code of FPU to truncating
|
|
|
|
fist [esize] ;store characteristic of logarithm
|
|
fldcw [oldcw] ;load back the former control word
|
|
|
|
ftst ;test logarithm for its sign
|
|
fstsw ax ;get result
|
|
fwait
|
|
sahf ;transfer to CPU flags
|
|
sbb [esize],0 ;decrement esize if log is negative
|
|
fstp st0 ;get rid of the logarithm
|
|
|
|
;-----------------------------------------------------------------------
|
|
; get the power of 10 required to generate an integer with the specified
|
|
; number of significant digits
|
|
;-----------------------------------------------------------------------
|
|
|
|
mov eax,[uID]
|
|
and eax,STR_SCI
|
|
jnz .els0 ;regular decimal notation
|
|
mov eax,[esize]
|
|
or eax,eax ;check if number is < 1
|
|
js @F
|
|
; .if eax > 15 ;if number is >= 10^16
|
|
cmp eax,15
|
|
jbe .endif0
|
|
or [uID],STR_SCI ;switch to scientific notation
|
|
mov [Decimal],15 ;insures 15 decimal places in result
|
|
jmp scific
|
|
.endif0:
|
|
add eax,[Decimal]
|
|
; .if eax > 15 ;if integer + decimal digits > 16
|
|
cmp eax,15
|
|
jbe .endif1
|
|
sub eax,15
|
|
sub [Decimal],eax ;reduce decimal digits as required
|
|
.endif1:
|
|
@@:
|
|
push [Decimal]
|
|
pop [tempdw]
|
|
jmp @f
|
|
.els0: ;scientific notation
|
|
scific:
|
|
mov eax,[Decimal]
|
|
sub eax,[esize]
|
|
mov [tempdw],eax
|
|
; .endif
|
|
@@:
|
|
|
|
;----------------------------------------------------------------------------------------
|
|
; multiply the number by the power of 10 to generate required integer and store it as BCD
|
|
;----------------------------------------------------------------------------------------
|
|
|
|
;.if tempdw != 0
|
|
cmp [tempdw],0
|
|
je @f
|
|
fild [tempdw]
|
|
fldl2t
|
|
fmulp st1,st0 ;->log2(10)*exponent
|
|
fld st0
|
|
frndint ;get the characteristic of the log
|
|
fxch
|
|
fsub st,st1 ;get only the fractional part but keep the characteristic
|
|
f2xm1 ;->2^(fractional part)-1
|
|
fld1
|
|
faddp st1,st0 ;add 1 back
|
|
fscale ;re-adjust the exponent part of the REAL number
|
|
fstp st1 ;get rid of the characteristic of the log
|
|
fmulp st1,st0 ;->16-digit integer
|
|
;.endif
|
|
@@:
|
|
|
|
fbstp [bcdstr] ;->TBYTE containing the packed digits
|
|
fstsw ax ;retrieve exception flags from FPU
|
|
fwait
|
|
shr eax,1 ;test for invalid operation
|
|
jc srcerr ;clean-up and return error
|
|
|
|
;------------------------------------------------------------------------------
|
|
; unpack BCD, the 10 bytes returned by the FPU being in the little-endian style
|
|
;------------------------------------------------------------------------------
|
|
|
|
push ecx
|
|
push esi
|
|
push edi
|
|
lea esi,[bcdstr+9] ;go to the most significant byte (sign byte)
|
|
lea edi,[unpacked]
|
|
mov eax,3020h
|
|
mov cl,byte [esi] ;sign byte
|
|
; .if cl == 80h
|
|
cmp cl,0x80
|
|
jne @f
|
|
mov al,"-" ;insert sign if negative number
|
|
; .endif
|
|
@@:
|
|
stosw
|
|
mov ecx,9
|
|
@@:
|
|
dec esi
|
|
movzx eax,byte [esi]
|
|
ror ax,4
|
|
ror ah,4
|
|
add ax,3030h
|
|
stosw
|
|
dec ecx
|
|
jnz @B
|
|
|
|
mov edi,[lpDest]
|
|
lea esi,[unpacked]
|
|
test [uID],STR_SCI ;scientific notation?
|
|
jnz scientific
|
|
|
|
;************************
|
|
; REGULAR STRING NOTATION
|
|
;************************
|
|
|
|
;------------------------------
|
|
; check if padding is specified
|
|
;------------------------------
|
|
|
|
mov ecx,[Padding]
|
|
or ecx,ecx ;check if padding is specified
|
|
jz nopadding
|
|
|
|
mov edx,2 ;at least 1 integer + sign
|
|
mov eax,[esize]
|
|
or eax,eax
|
|
js @F ;only 1 integer digit if size is < 1
|
|
add edx,eax ;->number of integer digits
|
|
@@:
|
|
sub ecx,edx
|
|
jle nopadding
|
|
mov al," "
|
|
rep stosb
|
|
|
|
nopadding:
|
|
pushfd ;save padding flags
|
|
movsb ;insert sign
|
|
mov ecx,1 ;at least 1 integer digit
|
|
mov eax,[esize]
|
|
or eax,eax ;is size negative (i.e. number smaller than 1)
|
|
js @F
|
|
add ecx,eax
|
|
@@:
|
|
mov eax,[Decimal]
|
|
add eax,ecx ;->total number of digits to be displayed
|
|
sub eax,19
|
|
sub esi,eax ;address of 1st digit to be displayed
|
|
pop eax ;retrieve padding flags in EAX
|
|
; .if byte ptr[esi-1] == "1"
|
|
cmp byte [esi-1],"1"
|
|
jne @f
|
|
dec esi
|
|
inc ecx
|
|
push eax ;transfer padding flags through stack
|
|
popfd ;retrieve padding flags
|
|
jle @F ;no padding was necessary
|
|
dec edi ;adjust for one less padding byte
|
|
; .endif
|
|
@@:
|
|
@@:
|
|
rep movsb ;copy required integer digits
|
|
mov ecx,[Decimal]
|
|
or ecx,ecx
|
|
jz @F
|
|
mov al,"."
|
|
stosb
|
|
rep movsb ;copy required decimal digits
|
|
@@:
|
|
jmp finish
|
|
|
|
;********************
|
|
; SCIENTIFIC NOTATION
|
|
;********************
|
|
|
|
scientific:
|
|
movsb ;insert sign
|
|
mov ecx,[Decimal]
|
|
mov eax,18
|
|
sub eax,ecx
|
|
add esi,eax
|
|
cmp byte [esi-1],"1"
|
|
pushfd ;save flags for extra "1"
|
|
jnz @F
|
|
dec esi
|
|
@@:
|
|
movsb ;copy the integer
|
|
mov al,"."
|
|
stosb
|
|
rep movsb ;copy the decimal digits
|
|
|
|
mov al,"E"
|
|
stosb
|
|
mov al,"+"
|
|
mov ecx,[esize]
|
|
popfd ;retrieve flags for extra "1"
|
|
jnz @F ;no extra "1"
|
|
inc ecx ;adjust exponent
|
|
@@:
|
|
or ecx,ecx
|
|
jns @F
|
|
mov al,"-"
|
|
neg ecx ;make number positive
|
|
@@:
|
|
stosb ;insert proper sign
|
|
|
|
;Note: the absolute value of the size could not exceed 4931
|
|
|
|
mov eax,ecx
|
|
mov cl,100
|
|
div cl ;->thousands & hundreds in AL, tens & units in AH
|
|
push eax
|
|
and eax,0ffh ;keep only the thousands & hundreds
|
|
mov cl,10
|
|
div cl ;->thousands in AL, hundreds in AH
|
|
add ax,3030h ;convert to characters
|
|
stosw ;insert them
|
|
pop eax
|
|
shr eax,8 ;get the tens & units in AL
|
|
div cl ;tens in AL, units in AH
|
|
add ax,3030h ;convert to characters
|
|
stosw ;insert them
|
|
|
|
finish:
|
|
xor eax,eax
|
|
stosb ;string terminating 0
|
|
pop edi
|
|
pop esi
|
|
pop ecx
|
|
|
|
frstor [content]
|
|
|
|
or al,1 ;to insure EAX!=0
|
|
ret
|
|
|
|
endp
|
|
|
|
; #########################################################################
|
|
|
|
|
|
align 4
|
|
|
|
; #########################################################################
|
|
; FpuCos
|
|
;##########################################################################
|
|
;
|
|
; cos(Src) -> Dest
|
|
FpuCos:
|
|
test [flags],(1 shl 30)
|
|
jz @f ;jump if angle already in radians
|
|
fldpi ;load pi (3.14159...) on FPU
|
|
fmulp
|
|
test [flags],(1 shl 31)
|
|
jnz .1
|
|
pushd 200
|
|
jmp .2
|
|
.1: pushd 180
|
|
.2: fidiv dword [esp] ;value now in radians
|
|
fwait
|
|
add esp,4 ;clean the stack
|
|
@@: fldpi
|
|
fadd st,st ;->2pi
|
|
fxch
|
|
|
|
@@: fprem ;reduce the angle
|
|
fcos
|
|
fstsw ax ;retrieve exception flags from FPU
|
|
fwait
|
|
shr al,1 ;test for invalid operation
|
|
sahf ;transfer to the CPU flags
|
|
jpe @B ;reduce angle again if necessary
|
|
fstp st1 ;get rid of the 2pi
|
|
ret
|
|
|
|
align 4
|
|
; #########################################################################
|
|
; FpuSin
|
|
;##########################################################################
|
|
;
|
|
; sin(Src) -> Dest
|
|
FpuSin:
|
|
test [flags],(1 shl 30)
|
|
jz @f ;jump if angle already in radians
|
|
fldpi ;load pi (3.14159...) on FPU
|
|
fmulp
|
|
test [flags],(1 shl 31)
|
|
jnz .1
|
|
pushd 200
|
|
jmp .2
|
|
.1: pushd 180
|
|
.2: fidiv dword [esp] ;value now in radians
|
|
fwait
|
|
add esp,4 ;clean the stack
|
|
@@:
|
|
fldpi
|
|
fadd st,st ;->2pi
|
|
fxch
|
|
|
|
fprem ;reduce the angle
|
|
fsin
|
|
fstp st1 ;get rid of the 2pi
|
|
ret
|
|
|
|
align 4
|
|
; #########################################################################
|
|
; FpuArctan
|
|
;##########################################################################
|
|
;
|
|
; atan(Src) -> Dest
|
|
FpuArctan:
|
|
fld1
|
|
fpatan
|
|
test [flags],(1 shl 30)
|
|
jz @F ;jump if angle is required in radians
|
|
test [flags],(1 shl 31)
|
|
jnz .1
|
|
pushd 200
|
|
jmp .2
|
|
.1: pushd 180
|
|
.2: fimul dword [esp] ;*180 degrees
|
|
fldpi ;load pi (3.14159...) on FPU
|
|
fdivp ;*180/pi, angle now in degrees
|
|
add esp,4 ;clean CPU stack
|
|
|
|
ftst ;check for negative angle
|
|
fstsw ax ;retrieve status word from FPU
|
|
fwait
|
|
sahf
|
|
jnc @F ;jump if positive number
|
|
test [flags],(1 shl 31)
|
|
jnz .3
|
|
pushd 400
|
|
jmp .4
|
|
.3: pushd 360
|
|
.4: fiadd dword [esp] ;angle now 0-360
|
|
fwait
|
|
add esp,4 ;clean CPU stack
|
|
|
|
@@:
|
|
ret
|
|
|
|
align 4
|
|
; #########################################################################
|
|
; FpuTan
|
|
;##########################################################################
|
|
|
|
; a = tan(x)
|
|
FpuTan:
|
|
fldpi ;load pi (3.14159...) on FPU
|
|
fadd st,st ;->2pi
|
|
fxch
|
|
test [flags],(1 shl 30)
|
|
jz @F ;jump if angle already in radians
|
|
test [flags],(1 shl 31)
|
|
jnz .1
|
|
pushd 400
|
|
jmp .2
|
|
.1: pushd 360
|
|
.2: fmul st,st1
|
|
fidiv dword [esp] ;value now in radians
|
|
pop eax ;clean the stack
|
|
@@: fprem ;reduce the angle
|
|
fptan
|
|
|
|
fstp st ;get rid of the 1
|
|
fstp st1 ;get rid of the 2pi
|
|
ret
|
|
|
|
align 4
|
|
; #########################################################################
|
|
; FpuArccos
|
|
;##########################################################################
|
|
; sqrt(1-Src^2)
|
|
; acos(Src) = atan ------------- -> Dest
|
|
; Src
|
|
|
|
FpuArccos:
|
|
fld st ;copy cosine value
|
|
fmul st0,st1 ;cos^2
|
|
fld1
|
|
fsubrp ;1-cos^2 = sin^2
|
|
fsqrt ;->sin
|
|
fxch
|
|
fpatan ;i.e. arctan(sin/cos)
|
|
|
|
test [flags],(1 shl 30)
|
|
jz @F ;jump if angle is required in radians
|
|
test [flags],(1 shl 31)
|
|
jnz .1
|
|
pushd 200
|
|
jmp .2
|
|
.1: pushd 180
|
|
.2: fimul dword [esp] ;*180 degrees
|
|
fldpi ;load pi (3.14159...) on FPU
|
|
fdivp ;*180/pi, angle now in degrees
|
|
pop eax ;clean CPU stack
|
|
@@:
|
|
ret
|
|
|
|
align 4
|
|
; #########################################################################
|
|
; FpuArcsin
|
|
;##########################################################################
|
|
; Src
|
|
; asin(Src) = atan ------------- -> Dest
|
|
; sqrt(1-Src^2)
|
|
FpuArcsin:
|
|
fld st0 ;copy sine value
|
|
fmul st0,st0 ;sin^2
|
|
fld1
|
|
fsubrp ;1-sin^2 = cos^2
|
|
fsqrt ;->cos
|
|
fpatan ;i.e. arctan(sin/cos) = arcsin
|
|
test [flags],(1 shl 30)
|
|
jz @F ;jump if angle is required in radians
|
|
test [flags],(1 shl 31)
|
|
jnz .1
|
|
pushd 200
|
|
jmp .2
|
|
.1: pushd 180
|
|
.2: fimul dword [esp] ;*180 degrees
|
|
fldpi ;load pi (3.14159...) on FPU
|
|
fdivrp ;*180/pi, angle now in degrees
|
|
add esp,4 ;clean CPU stack
|
|
@@:
|
|
ret
|
|
|
|
align 4
|
|
; #########################################################################
|
|
; FpuEexpX
|
|
;##########################################################################
|
|
|
|
; e^(Src) = antilog2[ log2(e) * Src ] -> Dest
|
|
|
|
FpuEexpX:
|
|
|
|
fldl2e ;->log2(e)
|
|
fmulp ;->log2(e)*Src
|
|
|
|
fld st0 ;copy the logarithm
|
|
frndint ;keep only the characteristic
|
|
fsub st1,st ;keeps only the mantissa
|
|
fxch ;get the mantissa on top
|
|
|
|
f2xm1 ;->2^(mantissa)-1
|
|
fld1
|
|
faddp ;add 1 back
|
|
|
|
fscale ;scale it with the characteristic
|
|
|
|
fstp st1 ;get rid of the characteristic
|
|
ret
|
|
|
|
align 4
|
|
; #########################################################################
|
|
; FpuXexpY
|
|
;##########################################################################
|
|
|
|
; Src1^Src2 = antilog2[ log2(Src1) * Src2 ] -> Dest
|
|
|
|
FpuXexpY:
|
|
fxch ;set up FPU registers for next operation
|
|
fyl2x ;->log2(Src1)*exponent
|
|
|
|
fld st0 ;copy the logarithm
|
|
frndint ;keep only the characteristic
|
|
fsub st1,st ;keeps only the mantissa
|
|
fxch ;get the mantissa on top
|
|
|
|
f2xm1 ;->2^(mantissa)-1
|
|
fld1
|
|
faddp ;add 1 back
|
|
|
|
fscale ;scale it with the characteristic
|
|
|
|
fstp st1 ;overwrite the characteristic
|
|
ret
|
|
|
|
|
|
if 0
|
|
exp:
|
|
.N equ 10
|
|
xor eax,eax
|
|
mov ecx,.N
|
|
fld1
|
|
.0: dec ecx
|
|
jz .end
|
|
mov eax,.N
|
|
sub eax,ecx
|
|
mov [.d],eax
|
|
fild [.d]
|
|
@@: dec eax
|
|
jz @f
|
|
mov [.d],eax
|
|
fild [.d]
|
|
fmulp
|
|
jmp @b
|
|
@@: mov eax,.N
|
|
sub eax,ecx
|
|
fld st2
|
|
@@: dec eax
|
|
jz @f
|
|
fld st3
|
|
fmulp
|
|
jmp @b
|
|
@@: fdivrp
|
|
faddp
|
|
jmp .0
|
|
.end: fxch
|
|
fstp st0
|
|
ret
|
|
.d dd 0
|
|
endf |