386f2xm1.inc
来自「开放源码的编译器open watcom 1.6.0版的源代码」· INC 代码 · 共 289 行
INC
289 行
;*****************************************************************************
;*
;* Open Watcom Project
;*
;* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
;*
;* ========================================================================
;*
;* This file contains Original Code and/or Modifications of Original
;* Code as defined in and that are subject to the Sybase Open Watcom
;* Public License version 1.0 (the 'License'). You may not use this file
;* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
;* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
;* provided with the Original Code and Modifications, and is also
;* available at www.sybase.com/developer/opensource.
;*
;* The Original Code and all software distributed under the License are
;* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
;* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
;* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
;* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
;* NON-INFRINGEMENT. Please see the License for the specific language
;* governing rights and limitations under the License.
;*
;* ========================================================================
;*
;* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
;* DESCRIBE IT HERE!
;*
;*****************************************************************************
modstart 386f2xm1
xref __FLDAC ; add constant from stack
xref ___LDA ; add
xref __FLDD ; divide
xref ___LDD ; divide
xref ___LDM ; multiply
xdefp __f2xm1 ; calc 2**x - 1
;;const0:
;; dt 20.813771196523035
;;const1:
;; dt 0.057761135831801924
;;const2:
;; dt 7.213503410844819
align 2
ExpConsts dt 1.0442737824274138403 ;/* sqrt(sqrt(sqrt(sqrt(2)))) */
dt 1.0905077326652576592 ;/* sqrt(sqrt(sqrt(2))) */
dt 1.1892071150027210667 ;/* sqrt(sqrt(2)) */
dt 1.4142135623730950488 ;/* sqrt(2) */
;;void __f2xm1( long double *x )
;;/****************************/
;; -.5 <= x <= .5
;;{
;; register int sgnx;
;; register int exp;
;; register int exp2;
;; register double *poly;
;; double ipart;
;; double a;
;; double b;
;; double ee;
;;
defp __f2xm1
push EBP ; save EBP
push EDI ; save registers
push ESI ; ...
push EDX ; ...
push ECX ; ...
push EBX ; ...
mov EDI,EAX ; save pointer to operand
;; if( fabs( x ) < 4.445e-16 ) { /* if argument is too small */
;; x = 1.0;
;; } else {
;; exp = 0;
sub ESI,ESI ; exp = 0
;; exp2 = 0;
;; sgnx = _sgn( x );
;; x = fabs( x );
mov CX,8[EDI] ; get exponent and sign
and byte ptr 9[EDI],7Fh ; force number to be positive
;; if( x != 0.0 ) {
cmp word ptr 8[EDI],0 ; if x == 0.0
_if e ; then
cmp dword ptr 4[EDI],0 ; ...
_if e ; ...
cmp dword ptr [EDI],0 ; ...
_endif ; ...
_endif ; ...
_if ne ; if x != 0.0
;; if( sgnx < 0 ) {
;; --exp;
;; x = 1.0 - x;
;; }
or CX,CX ; - if number was negative
_if s ; - then calc. x = 1.0 - x
dec ESI ; - - exp = -1
push 8000h+ONE_EXP ; - - push -1.0
push ONE_HW ; - - ...
push ONE_LW ; - - ...
mov EAX,EDI ; - - ...
mov EBX,EDI ; - - ...
call __FLDAC ; - - calc. x = x + -1.0
xor byte ptr 9[EBX],80h ; - - flip sign bit
_endif ; - endif
;; x = modf( ldexp( x, 4 ), &ipart );
;; if( x != 0.0 ) {
;; x = ldexp( x, -4 );
;; }
;; exp2 = ipart;
mov BX,8[EDI] ; - get exponent
add BX,4 ; - multiply by 16
sub ECX,ECX ; - set ipart to 0
mov EDX,4[EDI] ; - get fraction
mov EAX,[EDI] ; - ...
_loop ; - loop
cmp BX,3FFFh ; - - quit if done
_quif b ; - - ...
_shl EAX,1 ; - - shift left one
_rcl EDX,1 ; - - ...
_rcl ECX,1 ; - - into integer part
dec BX ; - - decrement exponent
_endloop ; - endloop
or EDX,EDX ; - check fraction
_if e ; - if zero
or EAX,EAX ; - - check other part
_endif ; - endif
_if e ; - if fraction is zero
sub EBX,EBX ; - - zero exponent
_else ; - else
_loop ; - - loop (normalize fraction)
or EDX,EDX ; - - - check top bit
_quif s ; - - - quit if normalized
_shl EAX,1 ; - - - shift left
_rcl EDX,1 ; - - - ...
dec BX ; - - - decrement exponent
_endloop ; - - endloop
sub BX,4 ; - - divide by 16
_endif ; - endif
mov [EDI],EAX ; - store fraction
mov 4[EDI],EDX ; - ...
mov 8[EDI],BX ; - ...
_else ; else
sub ECX,ECX ; - exp2 = 0
_endif ; endif
;; }
push ESI ; save exp
push ECX ; save exp2
;; ee = x * x;
mov EAX,[EDI] ; load x
mov EDX,4[EDI] ; ...
mov SI,8[EDI] ; ...
shl ESI,16 ; load x again
mov SI,8[EDI] ; ...
mov EBX,EAX ; ...
mov ECX,EDX ; ...
call ___LDM ; calc. ee = x * x
push EAX ; save ee
push EDX ; ...
push ESI ; ...
;; a = ee + const0;
mov ECX,0A6829A79h ; load const0
mov EBX,01BF21F8Ch ; ...
and ESI,0000FFFFh ; ...
or ESI,40030000h ; ...
call ___LDA ; calc. a = ee + const0
mov EBP,ESP ; get access to stack
xchg EAX,8[EBP] ; save a, load ee
xchg EDX,4[EBP] ; ...
xchg ESI,0[EBP] ; ...
;; b = (ee * const1 + const2) * x;
mov ECX,0EC96F0D6h ; load const1
mov EBX,009D7BFDBh ; ...
and ESI,0000FFFFh ; ...
or ESI,3FFA0000h ; ...
call ___LDM ; calc. ee * const1
mov ECX,0E6D5051Ah ; load const2
mov EBX,0E536E187h ; ...
and ESI,0000FFFFh ; ...
or ESI,40010000h ; ...
call ___LDA ; calc. (ee * const1 + const2)
mov EBX,[EDI] ; load x
mov ECX,4[EDI] ; ...
rol ESI,16 ; ...
mov SI,8[EDI] ; ...
rol ESI,16 ; ...
call ___LDM ; calc. b = (ee * const1 + const2) * x;
push EAX ; save b
push EDX ; ...
push ESI ; ...
;; x = (a + b) / (a - b);
xor ESI,00008000h ; negate b
rol ESI,16 ; load a
mov SI,0[EBP] ; ...
rol ESI,16 ; ...
mov EBX,8[EBP] ; ...
mov ECX,4[EBP] ; ...
call ___LDA ; calc (a - b)
xchg EAX,(-4)[EBP] ; save (a-b) and load b
xchg EDX,(-8)[EBP] ; ...
xchg ESI,(-12)[EBP] ; ...
rol ESI,16 ; load a
mov SI,0[EBP] ; ...
rol ESI,16 ; ...
mov EBX,8[EBP] ; ...
mov ECX,4[EBP] ; ...
call ___LDA ; calc (a + b)
rol ESI,16 ; load (a-b)
mov SI,(-12)[EBP] ; ...
rol ESI,16 ; ...
pop ECX ; ...
pop ECX ; ...
pop EBX ; ...
call ___LDD ; calc. (a+b) / (a-b)
mov [EDI],EAX ; save it in x
mov 4[EDI],EDX ; ...
mov 8[EDI],SI ; ...
add ESP,12 ; clean up stack
pop ECX ; restore exp2
;; poly = ExpConsts;
lea ESI,ExpConsts
;; while( exp2 != 0 ) {
_loop ; loop
or ECX,ECX ; - quif exp2 == 0
_quif e ; - ...
;; if( exp2 & 1 ) {
shr ECX,1 ; - get next bit
_if c ; - if on
;; x *= *poly;
push ECX ; - - save ECX
push ESI ; - - save addr of poly
mov AX,8[EDI] ; - - load x
mov ECX,4[EDI] ; - - ...
mov EBX,[EDI] ; - - ...
shl EAX,16 ; - - shift exponent to top
mov AX,CS:8[ESI] ; - - load *poly
mov EDX,CS:4[ESI] ; - - ...
mov ESI,CS:[ESI] ; - - ...
xchg EAX,ESI ; - - ...
call ___LDM ; - - calc x * *poly
mov [EDI],EAX ; - - store result
mov 4[EDI],EDX ; - - ...
mov 8[EDI],SI ; - - ...
pop ESI ; - - restore addr of poly
pop ECX ; - - restore ECX
;; }
_endif ; - endif
;; ++poly;
lea ESI,10[ESI] ; - ++poly
;; exp2 = exp2 >> 1;
;; }
_endloop ; endloop
;; x = ldexp( x, exp );
pop ESI ; restore exp
add word ptr 8[EDI],SI
;; x = x - 1.0;
mov EAX,EDI ; point to x
push 8000h+ONE_EXP ; push -1.0
push ONE_HW ; ...
push ONE_LW ; ...
mov EBX,EDI ; result in x
call __FLDAC ; calc. x = x + -1.0
;; }
;; return( x );
;;}
pop EBX ; restore registers
pop ECX ; ...
pop EDX ; ...
pop ESI ; ...
pop EDI ; ...
pop EBP ; ...
ret ; return
__f2xm1 endp
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?