home *** CD-ROM | disk | FTP | other *** search
- PAGE ,132
-
- ; Name: PARSERA.ASM
- ; Author: Chuck Ebbert CompuServe [76306,1226]
- ; internet: 76306.1226@compuserve.com
-
- ; Fast floating-point routines for Fractint.
-
- ; (c) Copyright 1992-1995 Chuck Ebbert. All rights reserved.
-
- ; This program is an assembler version of the C 'execution engine' part
- ; of Mark Peterson's FRACTINT Formula Parser. Many of the operator
- ; functions were copied from Mark's code in the files FPU087.ASM
- ; and FPU387.ASM. The basic operator functions are assembler versions
- ; of the code in PARSER.C. Many 'combined' operator functions were
- ; added to the program as well.
-
- ; As of 31 Decmember 1993 this is also an in-memory compiler. The code
- ; generator is in PARSERFP.C. Define the variable COMPILER to
- ; build the compiler, otherwise the interpreter will be built.
- ; COMPILER must also be #defined in PARSERFP.C to build compiler.
-
-
- ; This code may be freely distributed and used in non-commercial
- ; programs provided the author is credited either during program
- ; execution or in the documentation, and this copyright notice
- ; is left intact. Sale of this code, or its use in any commercial
- ; product requires permission from the author. Nominal distribution
- ; and handling fees may be charged by shareware and freeware
- ; distributors.
-
-
- ; Date Init Change description
-
- ; 7 Mar 1995 TIW Added PWR (0,0) domain check
- ; 21 Feb 1995 TIW Shortened ATanh/ATan for MASM 6 compatibility
- ; 21 Feb 1995 CAE Changes ATan and ATanh
-
- ; 15 Feb 1995 CAE Added safety tests to macros.
- ; Changed fStkASin, etc. to work with compiler.
- ; Added fwait to Sto2 function for safety.
-
- ; 8 Feb 1995 CAE Removed transparent3d code.
- ; Added inversion support (compiler untested.)
-
- ; 8 Jan 1995 JCO Added fStkASin, fStkASinh, fStkACos, fStkACosh,
- ; fStkATan, fStkATanh, fStkSqrt, fStkCAbs.
-
- ; 31 Dec 1994 JCO Made changes to keep code in line with C code.
- ; Not necessary, since code isn't called. Will
- ; make it easier to make it run later. Added
- ; old <- z to end of fform_per_pixel to match
- ; C code.
-
- ; 30 Dec 1993 CAE Compiler is working
- ; Changed EXIT_OPER -> ret in 3 operator fns
- ; Added safety test for fn size in macros
-
- ; 12 Dec 1993 CAE Compiler additions
-
- ; 4 Dec 1993 CAE SinhCosh function accuracy improved
- ; Added LoadImagAdd/Sub/Mul
-
- ; 19 Nov 1993 CAE Revised macros for compiler mode.
-
- ; 10 Nov 1993 CAE Changed Exp function for more accuracy.
-
- ; 06 Nov 93 CAE Added 'LodRealPwr', 'One', 'ORClr2', 'Sqr3'.
- ; Revised Pwr function to use regs vs. memory.
- ; Changed many functions to 'included' type.
-
- ; 31 Oct 93 CAE Added 'Dbl' function.
-
- ; 09 Oct 1993 CAE Changed SinhCosh to use wider range of 387.
- ; Most FNINITs changed to FINIT.
- ; Loop logic revised slightly.
- ; Separated code from parserfp.c's codeseg.
- ; Added fStkStoClr2, fStkZero and fStkIdent.
- ; New 'pseudo calctype' fn. fFormulaX added.
-
- ; 12 Jul 1993 CAE Moved BadFormula to PARSER.C.
-
-
- .386 ; this only works on a 386
- .387 ; with a 387
-
- ifdef ??version
- masm51
- quirks
- endif
-
- ARGSZ equ 16 ; size of complex arg
- ;;;ARGSZ equ 32 ; size of hypercomplex arg
- CPFX equ 4 ; size of constarg prefix
- CARG equ CPFX+ARGSZ ; size of constarg
- LASTSQR equ CARG*4+CPFX ; offset of lastsqr from start of v
-
- ; ---------------------------------------------------------------------------
- FRAME MACRO regs ; build a stack frame
- push bp
- mov bp, sp
- IRP reg, <regs>
- push reg
- ENDM
- ENDM
-
- UNFRAME MACRO regs ; unframe before return
- IRP reg, <regs>
- pop reg
- ENDM
- pop bp
- ENDM
-
- ; ---------------------------------------------------------------------------
- ; Pop a number of scalars from the FPU stack.
- ; Generate as many 'fcompp' instr.'s as possible.
- ; Then a 'fstp st(0)' if needed.
- POP_STK MACRO StkPop
- NumToPop = StkPop SHR 1
- REPT NumToPop
- fcompp
- ENDM
- NumToPop = StkPop - ( NumToPop SHL 1 )
- REPT NumToPop
- fstp st(0)
- ENDM
- ENDM
-
- ; Uncomment the following line to enable compiler code generation.
- ;COMPILER EQU 1
-
- ; ---------------------------------------------------------------------------
- ; Generate beginning code for operator fn.
- BEGN_OPER MACRO OperName
- ifndef COMPILER
- ;; only align when no compiler
- align 4
- endif
-
- ;; always generate public and begin of proc (before fixups)
- public _fStk&OperName
- _fStk&OperName proc near
-
- ifdef COMPILER
- ;; generate the fixups for compiler
- ;; size of fn. | 8000h to mark it as an OPER instead of an INCL CAE 27Dec93
- dw Size_&OperName OR 8000h
- ;; near pointer to the start of actual code CAE 19Dec93
- dw offset PARSERA_TEXT:Code_&OperName
- ;; addr of fn to include (undefined if Incl_&OperName==255 below)
- dw IAddr_&OperName
- ;; offset of x fixup or 255 if none
- db XFixup_&OperName
- ;; offset of y fixup or 255 if none
- db YFixup_&OperName
- ;; offset of included(called) fn or 255 if none
- db Incl_&OperName
-
- endif
-
- ;; added label for code begin point CAE 25Nov93
- Code_&OperName:
-
- ENDM
-
- ; ---------------------------------------------------------------------------
- END_OPER MACRO OperName
- ; Generate end of operator fn. code.
-
- ifndef COMPILER
- ;; gen a return instr.
- ret
- else
-
- ;; gen a jump label
- End_&OperName:
-
- ;; generate zero for fixups not generated during fn.
-
- ifndef Incl_&OperName
- ;; No included operator. Generate 255 offset, 0 address. CAE 19Nov93
- Incl_&OperName EQU 255
- IAddr_&OperName EQU 0
- endif
-
- ifndef XFixup_&OperName
- XFixup_&OperName EQU 255
- endif
-
- ifndef YFixup_&OperName
- YFixup_&OperName EQU 255
- endif
-
- endif
-
- ;; Always gen size of fn (subtract size of header here)
- Size_&OperName EQU $ - Code_&OperName
- ;; Make sure fn is of legal size CAE 30DEC93
- .errnz (Size_&OperName GT 127)
-
- ;; and end of procedure.
- _fStk&OperName endp
- ENDM
-
- ; ---------------------------------------------------------------------------
- BEGN_INCL MACRO OperName
- ;; Generate beginning code for 'included' operator fn.
- ;; No fixups allowed in one of these functions.
-
- ;; Safety test: generate an equate here so the INCL_OPER CAE 15Feb95
- ;; macro can test to see if this really is includable.
- Is_Incl_&OperName EQU 1
-
- ;; Don't bother with align in compiler mode.
- ifndef COMPILER
- align 4
- endif
-
- ;; Generate public (incl fns. can be called directly) and begin of proc.
- public _fStk&OperName
- _fStk&OperName proc near
-
- ifdef COMPILER
- ;; Size of included fn. changed to word CAE 27Dec93
- dw Size_&OperName
- endif
-
- ;; added label for code begin point CAE 25Nov93
- Code_&OperName:
-
- ENDM
-
- ; ---------------------------------------------------------------------------
- ; Generate end of 'included' operator fn. code.
- END_INCL MACRO OperName
- ifndef COMPILER
- ;; generate return
- ret
- else
-
- ;; generate label for jump to end of fn.
- End_&OperName:
- endif
-
- ;; always generate actual size of fn. (subtract hdr. size)
- Size_&OperName EQU $ - Code_&OperName
- ;; Make sure fn is of legal size CAE 30DEC93
- .errnz (Size_&OperName GT 127)
- ;; always generate end-of-proc
- _fStk&OperName endp
- ENDM
-
- ; ---------------------------------------------------------------------------
- ; 'Include' a function inside another one
- INCL_OPER MACRO CallingOper,OperToIncl
-
- ;; Make sure the included fn was defined with the BEGN_INCL macro.
- ifndef Is_Incl_&OperToIncl ; CAE 15Feb95
- .error "Included function was not defined with BEGN_INCL macro"
- endif
-
- ;; Gen equate for offset of include in outer fn.
- ;; Always generate this to prevent >1 include even when not CAE 15FEB95
- ;; building the compiler.
- Incl_&CallingOper EQU $ - Code_&CallingOper
- ifdef COMPILER
- ;; Address of included fn.
- IAddr_&CallingOper EQU _fStk&OperToIncl
- ;; Gen 1 1-byte placeholder for the included fn to make codegen easier
- db 0ffH
- else
-
- ;; Generate a call to the included fn.
- call _fStk&OperToIncl
- endif
- ENDM
-
- ; ---------------------------------------------------------------------------
- ; Exit early from an operator function.
- EXIT_OPER MACRO FnToExit
- ifdef COMPILER
- ;; jump to end of operator fn
- jmp short End_&FnToExit
- else
-
- ;; return to caller
- ret
- endif
- ENDM
-
- ; ---------------------------------------------------------------------------
- ; Generate an FPU instruction and a fixup.
- ; AddrToFix is = X or Y
- FIXUP MACRO OperName, InstrToFix, Addr
- ifdef COMPILER
-
- ;; Generate a fixup as an offset from start of fn.
- ;; Fixup is two bytes into the instruction, thus the '+ 2'.
- ;; This may not be true for all instructions.
- ifidni <Addr>, <X>
- XFixup_&OperName EQU $ - Code_&OperName + 2
- else
- ;; assume fixup is for y
- YFixup_&OperName EQU $ - Code_&OperName + 2
- endif
- ;; Generate a load, store or whatever of any convenient value using DS.
- &InstrToFix QWORD PTR ds:_fLastOp
- else
-
- ifidni <Addr>, <X>
- ;; Gen load of X using SI.
- &InstrToFix QWORD PTR [si]
- else
- ;; Assume fixup is for y, use SI+8.
- &InstrToFix QWORD PTR [si+8]
- endif
- endif
-
- ENDM
-
- ; ---------------------------------------------------------------------------
- ; Align 4 if no compiler.
- PARSALIGN macro AlignFn
- ifndef COMPILER
- align 4
- endif
- ENDM
-
- ; CAE added macros for common operations Feb 1995
-
- GEN_SQR0 macro
- ;; square the stack top, don't save magnitude in lastsqr CAE 15FEB95
- fld st(0) ; x x y
- fld st(0) ; x x x y
- fmul st,st(3) ; xy x x y
- fadd st,st ; 2xy x x y
- fxch st(3) ; y x x 2xy
- fadd st(2),st ; y x x+y 2xy
- fsubp st(1),st ; x-y x+y 2xy
- fmulp st(1),st ; xx-yy 2xy
- ENDM
-
- GEN_SQRT macro ; CAE 15Feb95
- ; can use a max of 2 regs
- fld st(1) ; y x y
- fld st(1) ; x y x y
- fpatan ; atan x y
- fdiv __2_ ; theta=atan/2 x y
- fsincos ; cos sin x y
- fxch st(3) ; y sin x cos
- fmul st,st(0) ; yy sin x cos
- fxch st(2) ; x sin yy cos
- fmul st,st(0) ; xx sin yy cos
- faddp st(2),st ; sin xx+yy cos
- fxch st(2) ; cos xx+yy sin
- fxch ; xx+yy cos sin
- fsqrt ; sqrt(xx+yy) cos sin
- fsqrt ; mag=sqrt(sqrt(xx+yy)) cos sin
- fmul st(2),st ; mag cos mag*sin
- fmulp st(1),st ; mag*cos mag*sin
- ENDM
- ; ---------------------------------------------------------------------------
- ; external functions
- extrn _invertz2:far
-
- ; ---------------------------------------------------------------------------
- _DATA segment word public use16 'DATA'
- extrn _invert:WORD
- extrn _maxit:DWORD
- extrn _inside:WORD
- extrn _outside:WORD
- extrn _coloriter:DWORD
- extrn _kbdcount:WORD ; keyboard counter
- extrn _dotmode:WORD
- extrn __1_:QWORD, _PointFive:QWORD, __2_:QWORD, _infinity:QWORD
- extrn _LastOp:WORD, _LastInitOp:WORD
- extrn _InitOpPtr:WORD, _InitStoPtr:WORD, _InitLodPtr:WORD
- extrn _s:WORD
- extrn _OpPtr:WORD, _LodPtr:WORD, _StoPtr:WORD
- extrn _Load:DWORD, _Store:DWORD
- extrn _FormName:byte
- extrn _dy1:DWORD, _dx1:DWORD, _dy0:DWORD, _dx0:DWORD
- extrn _new:WORD, _old:WORD
- extrn _overflow:WORD
- extrn _col:WORD, _row:WORD
- extrn _Arg1:WORD, _Arg2:WORD
- extrn _f:DWORD, _pfls:DWORD, _v:DWORD
- extrn _debugflag:WORD
- _DATA ends
-
- ; ---------------------------------------------------------------------------
-
- _BSS segment word public use16 'BSS'
- _fLastOp label DWORD ; save seg, offset of lastop here
- dd ?
- _PtrToZ label WORD ; offset of z
- dw ?
- _BSS ends
-
- DGROUP group _DATA,_BSS
-
- ; ---------------------------------------------------------------------------
- ; Operator Functions follow.
- ; ---------------------------------------------------------------------------
-
- ; NOTE: None of these operator functions may change any registers but
- ; ax and si. The exceptions are those functions that update
- ; the current values of the 'status' regs as needed.
-
- ; On entry to these functions:
- ; FPU stack is used as the evaluation stack.
- ; The FPU stack can overflow into memory. Accuracy is not lost but
- ; calculations are slower.
- ; es -> DGROUP
- ; ds -> parser data
- ; cx -> lastop
- ; edx == orbit counter (in fFormulaX)
- ; di -> stack overflow area, used by push and pull functions and as
- ; a temporary storage area
- ; bx -> current operator, operand pair
- ; [bx] = operator function address, i.e. addr. of current '_fStkXXX'
- ; [bx+2] = operand pointer or zero if no operand
- ; si = operand pointer (loaded from [bx+2] before call of operator fn.)
-
- ; New rules Feb 1993:
- ; 1. No EXIT_OPER before an INCL_OPER
- ; (no jumps can be made past an included function.)
- ; 2. No included fn may include another, or have any fixups.
- ; 3. Only one included fn. allowed per 'normal' fn.
-
- ; --------------------------------------------------------------------------
- ; Put this code in PARSERA_TEXT, not PARSERFP_TEXT CAE 09OCT93
- PARSERA_TEXT segment para public use16 'CODE'
- ; Non-standard segment register setup.
- assume es:DGROUP, ds:nothing, cs:PARSERA_TEXT
-
- ; --------------------------------------------------------------------------
- ; Included functions must be before any fns that include them.
- ; --------------------------------------------------------------------------
- BEGN_INCL Log ; Log
- ; From FPU387.ASM
- ; Log is called by Pwr and is also called directly.
- ftst
- fstsw ax
- sahf
- jnz short NotBothZero
- fxch ; y x
- ftst
- fstsw ax
- sahf
- fxch ; x y
- jnz short NotBothZero
- POP_STK 2 ; clear two numbers
- fldz
- fldz
- mov ax, 1 ; domain error (1 in ax)
- EXIT_OPER Log ; return (0,0)
- PARSALIGN
- NotBothZero:
- xor ax,ax ; no domain error (0 in ax)
- fld st(1) ; y x y
- fld st(1) ; x y x y
- fpatan ; z.y x y
- fxch st(2) ; y x z.y
- fmul st,st(0) ; yy x z.y
- fxch ; x yy z.y
- fmul st,st(0) ; xx yy z.y
- fadd ; mod z.y
- fldln2 ; ln2, mod, z.y
- fmul _PointFive ; ln2/2, mod, z.y
- fxch ; mod, ln2/2, z.y
- fyl2x ; z.x, z.y
- END_INCL Log
- ; --------------------------------------------------------------------------
- BEGN_INCL SinhCosh ; Included fn, Sinh, Cosh of st
- ; From FPU087.ASM with mods to use less registers & for 387.
- ; Mod for 387-only after Fractint v18. CAE 09OCT93
- ; NOTE: Full 80-bit accuracy is *NOT* maintained in this function!
- ; Only 1 additional register can be used here.
- ; Changed fn so that rounding errors are less. CAE 04DEC93
- fstcw _Arg2 ; use arg2 to hold CW
- fwait
- fldln2 ; ln(2) x
- fdivp st(1),st ; x/ln(2), start the fdivr instr.
- mov ax,_Arg2 ; Now do some integer instr.'s
- push ax ; Save control word on stack
- or ax,0000110000000000b
- mov _Arg2,ax
- fld st ; x/ln(2), x/ln(2)
- fldcw _Arg2 ; Now set control to round toward zero
- ; Chop toward zero rounding applies now CAE 4DEC93
- frndint ; int = integer(x/ln(2)), x/ln(2)
- pop ax ; restore old CW to AX
- mov _Arg2,ax ; ...then move it to Arg2
- fldcw _Arg2 ; Restore control word from Arg2
- ; Normal rounding is in effect again CAE 4DEC93
- fxch ; x/ln(2), int
- fsub st,st(1) ; -1 < rem < 1.0, int
- f2xm1 ; 2**rem-1, int
- fadd __1_ ; 2**rem, int
- fscale ; e**x, int
- fstp st(1) ; e**x
- fld st ; e**x, e**x
- fmul _PointFive ; e^x/2 e^x
- fstp QWORD PTR es:[di] ; e^x use overflow stk for temp here
- fdivr _PointFive ; e**-x/2
- fld st ; e**-x/2, e**-x/2
- fadd QWORD PTR es:[di] ; coshx, e**-x/2
- fxch ; e^-x/2, coshx
- fsubr QWORD PTR es:[di] ; sinhx, coshx (fsubr pending)
- END_INCL SinhCosh
- ; --------------------------------------------------------------------------
- BEGN_INCL Ident ; Ident CAE 09OCT93
- END_INCL Ident
- ; --------------------------------------------------------------------------
- BEGN_INCL Sqr3 ; Sqr3 CAE 06NOV93
- fmul st,st(0) ; Magnitude/sqr of a real# on st
- END_INCL Sqr3 ; x^2 0 ...
- ; --------------------------------------------------------------------------
- BEGN_INCL Conj ; Complex conjugate
- fxch ; y x ...
- fchs ; -y x ...
- fxch ; x -y ...
- END_INCL Conj
- ; --------------------------------------------------------------------------
- BEGN_INCL Conj2 ; Complex conjugate (uses a reg)
- fldz ; 0 x y ... CAE 20Nov93
- fsubrp st(2),st ; x -y ...
- END_INCL Conj2
- ; --------------------------------------------------------------------------
- BEGN_INCL Real ; Real
- fstp st(1) ; x ...
- fldz ; 0 x ...
- fxch ; x 0 ...
- END_INCL Real
- ; --------------------------------------------------------------------------
- BEGN_INCL RealFlip ; Real, flip combined.
- fstp st(1) ; y=x ...
- fldz ; x=0 y ...
- END_INCL RealFlip
- ; --------------------------------------------------------------------------
- BEGN_INCL Add ; Add
- faddp st(2),st ; Arg2->d.x += Arg1->d.x;
- faddp st(2),st ; Arg2->d.y += Arg1->d.y;
- END_INCL Add
- ; --------------------------------------------------------------------------
- BEGN_INCL Sub ; Subtract
- fsubp st(2),st ; Arg2->d.x -= Arg1->d.x;
- fsubp st(2),st ; Arg2->d.y -= Arg1->d.y;
- END_INCL Sub
- ; --------------------------------------------------------------------------
- BEGN_OPER LodRealAdd ; Load, Real, Add combined
- FIXUP LodRealAdd, fadd, X ; Add x-value from memory
- END_OPER LodRealAdd
- ; --------------------------------------------------------------------------
- BEGN_OPER LodRealSub ; Load, Real, Subtract combined
- FIXUP LodRealSub, fsub, X ; (fsub qword ptr X)
- END_OPER LodRealSub
- ; --------------------------------------------------------------------------
- BEGN_OPER LodImagAdd ; Load, Imag, Add combined CAE 4DEC93
- FIXUP LodImagAdd, fadd, Y ; Add x-value from memory
- END_OPER LodImagAdd
- ; --------------------------------------------------------------------------
- BEGN_OPER LodImagSub ; Load, Imag, Sub combined CAE 4DEC93
- FIXUP LodImagSub, fsub, Y ; (fsub qword ptr X)
- END_OPER LodImagSub
- ; --------------------------------------------------------------------------
- BEGN_INCL Real2 ; Real value (fast version)
- fldz ; 0 x y ... (uses a reg)
- fstp st(2) ; x 0 ...
- END_INCL Real2
- ; --------------------------------------------------------------------------
- BEGN_OPER Lod ; Load
- FIXUP Lod, fld, Y ; y ...
- FIXUP Lod, fld, X ; x y ...
- END_OPER Lod
- ; --------------------------------------------------------------------------
- BEGN_INCL Clr1 ; Clear stack
- finit ; changed from fninit CAE 09OCT93
- END_INCL Clr1
- ; --------------------------------------------------------------------------
- BEGN_INCL Imag ; Imaginary value
- POP_STK 1 ; y
- fldz ; 0 y
- fxch ; x=y 0
- END_INCL Imag
- ; --------------------------------------------------------------------------
- BEGN_INCL ImagFlip ; Imaginary value, flip combined
- POP_STK 1 ; y ...
- fldz ; x=0 y ...
- END_INCL ImagFlip
- ; --------------------------------------------------------------------------
- BEGN_INCL Abs ; Absolute value
- fxch
- fabs
- fxch
- fabs
- END_INCL Abs
- ; --------------------------------------------------------------------------
- BEGN_OPER LodRealMul ; Load, Real, Multiply
- FIXUP LodRealMul, fld, X ; y.x x.x x.y
- fmul st(2),st ; y.x x.x z.y
- fmul ; z.x z.y
- END_OPER LodRealMul
- ; --------------------------------------------------------------------------
- BEGN_OPER LodImagMul ; Load, Imag, Multiply CAE 4DEC93
- FIXUP LodImagMul, fld, Y ; y.y x.x x.y
- fmul st(2),st ; y.y x.x z.y
- fmul ; z.x z.y
- END_OPER LodImagMul
- ; --------------------------------------------------------------------------
- BEGN_INCL Neg ; Negative
- fxch
- fchs ; Arg1->d.y = -Arg1->d.y;
- fxch
- fchs
- END_INCL Neg
- ; --------------------------------------------------------------------------
- BEGN_OPER EndInit ; End of initialization expr.
- ifndef COMPILER ; this instr not needed CAE 30DEC93
- mov _LastInitOp,bx ; LastInitOp=OpPtr
- endif
- finit ; changed from fninit CAE 09OCT93
- END_OPER EndInit
- ; --------------------------------------------------------------------------
- BEGN_OPER StoClr1 ; Store, clear FPU
- FIXUP StoClr1, fstp, X ; y ...
- FIXUP StoClr1, fst, Y ; y ...
- finit ; use finit, not fninit
- END_OPER StoClr1
- ; --------------------------------------------------------------------------
- BEGN_OPER StoClr2 ; Store, clear FPU CAE 09OCT93
- FIXUP StoClr2, fstp, X ; y
- FIXUP StoClr2, fstp, Y ; <empty> (store pending)
- END_OPER StoClr2
- ; --------------------------------------------------------------------------
- BEGN_OPER Sto ; Store, leave on ST
- ; Revised to do store first, then exchange. CAE 10NOV93
- FIXUP Sto, fst, X
- fxch ; y x ...
- FIXUP Sto, fst, Y
- fxch ; x y ...
- END_OPER Sto
- ; --------------------------------------------------------------------------
- BEGN_OPER Sto2 ; Store, leave on ST (uses a reg)
- fld st(1) ; y x y
- FIXUP Sto2, fstp, Y ; x y
- FIXUP Sto2, fst, X
- fwait ; CAE added fwait for safety 15Feb95
- END_OPER Sto2
- ; --------------------------------------------------------------------------
- BEGN_OPER LodReal ; Load a real
- fldz ; 0 ...
- FIXUP LodReal, fld, X ; x 0 ...
- END_OPER LodReal
- ; --------------------------------------------------------------------------
- BEGN_OPER LodRealC ; Load real const
- fldz ; y=0 ...
- FIXUP LodRealC, fld, X ; x 0 ...
- END_OPER LodRealC
- ; --------------------------------------------------------------------------
- BEGN_OPER LodRealFlip ; Load real, flip
- FIXUP LodRealFlip, fld, X ; y=x ...
- fldz ; x=0 y ...
- END_OPER LodRealFlip
- ; --------------------------------------------------------------------------
- BEGN_OPER LodRealAbs ; Load real, abs
- fldz ; 0 ...
- FIXUP LodRealAbs, fld, X ; x 0 ...
- fabs ; x=abs(x) 0 ...
- END_OPER LodRealAbs
- ; --------------------------------------------------------------------------
- BEGN_INCL Flip ; Exchange real, imag
- fxch ; x=y y=x ...
- END_INCL Flip
- ; --------------------------------------------------------------------------
- BEGN_OPER LodImag ; Load, imaginary
- fldz ; 0 ...
- FIXUP LodImag, fld, Y ; x=y 0
- END_OPER LodImag
- ; --------------------------------------------------------------------------
- BEGN_OPER LodImagFlip ; Load, imaginary, flip
- FIXUP LodImagFlip, fld, Y ; y ...
- fldz ; 0 y ...
- END_OPER LodImagFlip
- ; --------------------------------------------------------------------------
- BEGN_OPER LodImagAbs ; Load, imaginary, absolute value
- fldz ; 0 ...
- FIXUP LodImagAbs, fld, Y ; x=y 0 ...
- fabs ; x=abs(y) 0 ...
- END_OPER LodImagAbs
- ; --------------------------------------------------------------------------
- BEGN_OPER LodConj ; Load, conjugate
- FIXUP LodConj, fld, Y ; y ...
- fchs ; y=-y ...
- FIXUP LodConj, fld, X ; x y ...
- END_OPER LodConj
- ; --------------------------------------------------------------------------
- BEGN_OPER LodAdd ; Load, Add (uses a reg)
- FIXUP LodAdd, fadd, X
- FIXUP LodAdd, fld, Y
- faddp st(2),st
- END_OPER LodAdd
- ; --------------------------------------------------------------------------
- BEGN_OPER LodSub ; Load, Subtract (uses a reg)
- FIXUP LodSub, fsub, X
- FIXUP LodSub, fld, Y
- fsubp st(2),st
- END_OPER LodSub
- ; --------------------------------------------------------------------------
- BEGN_OPER StoDup ; Store, duplicate top operand
- FIXUP StoDup, fst, X ; x y
- fld st(1) ; y x y
- FIXUP StoDup, fst, Y ; y x y
- fld st(1) ; x y x y
- END_OPER StoDup
- ; --------------------------------------------------------------------------
- BEGN_OPER StoDbl ; Store, double (uses a reg)
- FIXUP StoDbl, fst, X ; x y (store x)
- fadd st,st ; 2x y
- fld st(1) ; y 2x y
- FIXUP StoDbl, fst, Y ; y 2x y (store y)
- faddp st(2),st ; 2x 2y
- END_OPER StoDbl
- ; --------------------------------------------------------------------------
- BEGN_INCL Zero ; Zero CAE 09OCT93
- POP_STK 2 ; ...
- fldz ; 0 ...
- fldz ; 0 0 ...
- END_INCL Zero
- ; --------------------------------------------------------------------------
- BEGN_INCL One ; One CAE 06NOV93
- POP_STK 2 ; ...
- fldz ; 0 ...
- fld1 ; 1 0 ...
- END_INCL One
- ; --------------------------------------------------------------------------
- BEGN_OPER LodSubMod ; Load, Subtract, Mod
- FIXUP LodSubMod, fsub, X ; x.x-y.x x.y ...
- fmul st,st ; sqr(x.x-y.x) x.y ...
- fldz ; 0 sqrx x.y ...
- fxch st(2) ; x.y sqrx 0 ...
- FIXUP LodSubMod, fsub, Y ; x.y-y.y sqrx 0 ...
- fmul st,st ; sqry sqrx 0 ...
- fadd ; mod 0
- END_OPER LodSubMod
- ; --------------------------------------------------------------------------
- BEGN_INCL Sqr ; Square, save magnitude in LastSqr
- fld st(0) ; x x y
- fmul st(1),st ; x x*x y
- fmul st,st(2) ; xy xx y
- mov si, WORD PTR _v ; si -> variables
- fadd st,st(0) ; 2xy xx y
- fxch st(2) ; y xx 2xy
- fmul st,st(0) ; yy xx 2xy
- fld st(1) ; xx yy xx 2xy
- fadd st,st(1) ; xx+yy yy xx 2xy
- fstp QWORD PTR [si+LASTSQR] ; yy xx 2xy
- fsubp st(1),st ; xx-yy 2xy
- END_INCL Sqr
- ; --------------------------------------------------------------------------
- BEGN_INCL Sqr0 ; Square, don't save magnitude
- GEN_SQR0
- END_INCL Sqr0
- ; --------------------------------------------------------------------------
- BEGN_INCL Mul ; Multiply
- ; From FPU087.ASM
- fld st(1) ; y.y, y.x, y.y, x.x, x.y
- fmul st,st(4) ; y.y*x.y, y.x. y.y, x.x, x.y
- fld st(1) ; y.x, y.y*x.y, y.x, y.y, x.x, x.y
- fmul st,st(4) ; y.x*x.x,y.y*x.y,y.x y.y,x.x,x.y
- fsubr ; newx=y.x*x.x-y.y*x.y,y.x,y.y,x.x,x.y
- fxch st(3) ; x.x, y.x, y.y, newx, x.y
- fmulp st(2),st ; y.x, y.y*x.x, newx, x.y
- fmulp st(3),st ; y.y*x.x, newx, y.x*x.y
- faddp st(2),st ; newx newy = y.x*x.y + x.x*y.y
- END_INCL Mul
- ; --------------------------------------------------------------------------
- BEGN_OPER LodMul ; Load, Multiply
- ; This is just load followed by multiply but it saves a fn. call
- ; and also allows optimizer enhancements.
- FIXUP LodMul, fld, Y ; y.y x.x x.y
- FIXUP LodMul, fld, X ; y.x y.y x.x x.y
- fld st(1) ; y.y, y.x, y.y, x.x, x.y
- fmul st,st(4) ; y.y*x.y, y.x. y.y, x.x, x.y
- fld st(1) ; y.x, y.y*x.y, y.x, y.y, x.x, x.y
- fmul st, st(4) ; y.x*x.x, y.y*x.y, y.x, y.y, x.x, x.y
- fsubr ; newx=y.x*x.x-y.y*x.y,y.x,y.y,x.x,x.y
- fxch st(3) ; x.x, y.x, y.y, newx, x.y
- fmulp st(2), st ; y.x, y.y*x.x, newx, x.y
- fmulp st(3), st ; y.y*x.x, newx, y.x*x.y
- faddp st(2), st ; newx newy = y.x*x.y + x.x*y.y
- END_OPER LodMul
- ; --------------------------------------------------------------------------
- BEGN_INCL Div ; Divide
- ; From FPU087.ASM with speedups
- fld st(1) ; y.y,y.x,y.y,x.x,x.y
- fmul st,st ; y.y*y.y,y.x,y.y,x.x,x.y
- fld st(1) ; y.x,y.y*y.y,y.x,y.y,x.x,x.y
- fmul st,st ; y.x*y.x,y.y*y.y,y.x,y.y,x.x,x.y
- fadd ; mod,y.x,y.y,x.x,x.y
- ftst
- fstsw ax
- sahf
- jz short DivNotOk
- ; can't do this divide until now
- fdiv st(1),st ; mod,y.x=y.x/mod,y.y,x.x,x.y
- fdivp st(2),st ; y.x,y.y=y.y/mod,x.x,x.y
- fld st(1) ; y.y,y.x,y.y,x.x,x.y
- fmul st,st(4) ; y.y*x.y,y.x,y.y,x.x,x.y
- fld st(1) ; y.x,y.y*x.y,y.x,y.y,x.x,x.y
- fmul st,st(4) ; y.x*x.x,y.y*x.y,y.x,y.y,x.x,x.y
- fadd ; y.x*x.x+y.y*x.y,y.x,y.y,x.x,x.y
- fxch st(3) ; x.x,y.x,y.y,newx,x.y
- fmulp st(2),st ; y.x,y.y*x.x,newx,x.y
- fmulp st(3),st ; x.x*y.y,newx,y.x*x.y
- fsubp st(2),st ; newx,newy
- EXIT_OPER Div
- DivNotOk:
- POP_STK 5 ; clear 5 from stack (!)
- fld _infinity ; return a very large number
- fld st(0)
- END_INCL Div
- ; --------------------------------------------------------------------------
- BEGN_INCL Recip ; Reciprocal
- ; From FPU087.ASM
- fld st(1) ; y, x, y
- fmul st,st ; y*y, x, y
- fld st(1) ; x, y*y, x, y
- fmul st,st ; x*x, y*y, x, y
- fadd ; mod, x, y
- ftst
- fstsw ax
- sahf
- jz short RecipNotOk
- fdiv st(1),st ; mod, newx=x/mod, y
- fchs ; -mod newx y
- fdivp st(2),st ; newx, newy=y/-mod
- EXIT_OPER Recip
- RecipNotOk:
- POP_STK 3 ; clear three from stack
- fld _infinity ; return a very large number
- fld st(0)
- END_INCL Recip
- ; --------------------------------------------------------------------------
- BEGN_OPER StoSqr ; Sto, Square, save magnitude
- fld st(0) ; x x y
- FIXUP StoSqr, fst, X ; " (store x)
- fmul st(1),st ; x x*x y
- fmul st,st(2) ; xy xx y
- fadd st,st(0) ; 2xy xx y
- fxch st(2) ; y xx 2xy
- FIXUP StoSqr, fst, Y ; " (store y)
- fmul st,st(0) ; yy xx 2xy
- ; It is now safe to overlay si here
- mov si, WORD PTR _v ; si -> variables
- fld st(1) ; xx yy xx 2xy
- fadd st,st(1) ; xx+yy yy xx 2xy
- fstp QWORD PTR [si+LASTSQR] ; yy xx 2xy
- fsubp st(1),st ; xx-yy 2xy
- END_OPER StoSqr
- ; --------------------------------------------------------------------------
- BEGN_OPER StoSqr0 ; Sto, Square, don't save magnitude
- fld st(0) ; x x y
- FIXUP StoSqr0, fst, X ; store x
- fld st(0) ; x x x y
- fmul st,st(3) ; xy x x y
- fadd st,st ; 2xy x x y
- fxch st(3) ; y x x 2xy
- FIXUP StoSqr0, fst, Y ; store y
- fadd st(2),st ; y x x+y 2xy
- fsubp st(1),st ; x-y x+y 2xy
- fmulp st(1),st ; xx-yy 2xy
- END_OPER StoSqr0
- ; --------------------------------------------------------------------------
- BEGN_INCL Mod2 ; Modulus (uses a reg)
- fmul st,st ; xx y
- fldz ; 0 xx y
- fxch st(2) ; y xx 0
- fmul st,st ; yy xx 0
- fadd ; mod 0
- END_INCL Mod2
- ; --------------------------------------------------------------------------
- BEGN_OPER LodMod2 ; Load, Modulus (uses a reg)
- fldz ; 0 ...
- FIXUP LodMod2, fld, X ; x 0 ...
- fmul st,st ; xx 0
- FIXUP LodMod2, fld, Y ; y xx 0
- fmul st,st ; yy xx 0
- fadd ; mod 0
- END_OPER LodMod2
- ; --------------------------------------------------------------------------
- BEGN_OPER StoMod2 ; Store, Modulus (uses a reg)
- FIXUP StoMod2, fst, X ; x y
- fmul st,st ; xx y
- fldz ; 0 xx y
- fxch st(2) ; y xx 0
- FIXUP StoMod2, fst, Y ; y xx 0
- fmul st,st ; yy xx 0
- fadd ; mod 0
- END_OPER StoMod2
- ; --------------------------------------------------------------------------
- BEGN_OPER Clr2 ; Test ST, clear FPU
- ftst
- fstsw ax
- fninit ; fstsw will complete first
- and ah,01000000b ; return 1 if zf=1
- shr ax,14 ; AX will be returned by fFormula()
- END_OPER Clr2
- ; --------------------------------------------------------------------------
- BEGN_OPER PLodAdd ; Load, Add (uses no regs)
- fxch ; y x
- FIXUP PLodAdd, fadd, Y ; add y from memory
- fxch ; x y
- FIXUP PLodAdd, fadd, X ; add x, overlap execution
- END_OPER PLodAdd
- ; --------------------------------------------------------------------------
- BEGN_OPER PLodSub ; Load, Subtract (uses no regs)
- fxch
- FIXUP PLodSub, fsub, Y ; sub y from memory
- fxch ; x y
- FIXUP PLodSub, fsub, X ; sub x, overlap execution
- END_OPER PLodSub
- ; --------------------------------------------------------------------------
- BEGN_OPER LodDup ; Load, duplicate
- FIXUP LodDup, fld, Y ; y ...
- FIXUP LodDup, fld, X ; x y ...
- fld st(1) ; y x y ...
- fld st(1) ; x y x y ...
- END_OPER LodDup
- ; --------------------------------------------------------------------------
- BEGN_OPER LodSqr ; Load, square (no save lastsqr)
- FIXUP LodSqr, fld, Y ; y ...
- fld st(0) ; y y ...
- fadd st(1),st ; y 2y ...
- fld st(0) ; y y 2y
- FIXUP LodSqr, fld, X ; x y y 2y ...
- fmul st(3),st ; x y y 2xy ...
- fadd st(2),st ; x y X+y 2xy ...
- fsubrp st(1),st ; x-y x+y 2xy ...
- fmul ; xx-yy 2xy ...
- END_OPER LodSqr
- ; --------------------------------------------------------------------------
- BEGN_OPER LodSqr2 ; Load, square (save lastsqr)
- FIXUP LodSqr2, fld, Y ; y ...
- fld st(0) ; y y ...
- fadd st(1),st ; y 2y ...
- fmul st,st(0) ; yy 2y ...
- FIXUP LodSqr2, fld, X ; x yy 2y ...
- fmul st(2),st ; x yy 2xy ...
- mov si,WORD PTR _v ; put address of v in si
- fmul st,st(0) ; xx yy 2xy ...
- fld st(0) ; xx xx yy 2xy
- fadd st,st(2) ; mod xx yy 2xy
- fstp QWORD PTR [si+LASTSQR] ; xx yy 2xy ... (save lastsqr)
- fsubrp st(1),st ; xx-yy 2xy ...
- END_OPER LodSqr2
- ; --------------------------------------------------------------------------
- BEGN_OPER LodDbl ; Load, double
- FIXUP LodDbl, fld, Y ; load y
- fadd st,st(0) ; double it
- FIXUP LodDbl, fld, X ; same for x
- fadd st,st(0)
- END_OPER LodDbl
- ; --------------------------------------------------------------------------
- BEGN_INCL Dbl ; Double CAE 31OCT93
- fxch ; y x ...
- fadd st,st(0) ; 2y x ...
- fxch ; x 2y ...
- fadd st,st(0) ; 2x 2y ...
- END_INCL Dbl
- ; --------------------------------------------------------------------------
- BEGN_INCL Mod ; Modulus (uses no regs)
- fmul st,st ; x*x y
- fxch ; y x*x
- fmul st,st ; y*y x*x
- fadd ; mod
- fldz ; 0 mod
- fxch ; mod 0
- END_INCL Mod
- ; --------------------------------------------------------------------------
- ; The following code was 'discovered' by experimentation. The Intel manuals
- ; really don't help much in writing this kind of code.
- ; --------------------------------------------------------------------------
- BEGN_INCL Push2 ; Push stack down from 8 to 6
- fdecstp ; roll the stack
- fdecstp ; ...
- fstp tbyte PTR es:[di] ; store x on overflow stack
- fstp tbyte PTR es:[di+10] ; and y (ten bytes each)
- add di,20 ; adjust di
- END_INCL Push2
- ; --------------------------------------------------------------------------
- BEGN_INCL Pull2 ; Pull stack up from 2 to 4
- fld tbyte PTR es:[di-10] ; oldy x y
- sub di,20 ; adjust di now
- fxch st(2) ; y x oldy
- fld tbyte PTR es:[di] ; oldx y x oldy
- fxch st(2) ; x y oldx oldy
- END_INCL Pull2
- ; --------------------------------------------------------------------------
- BEGN_INCL Push4 ; Push stack down from 8 to 4
- fdecstp ; roll the stack four times
- fdecstp
- fdecstp
- fdecstp
- fstp tbyte PTR es:[di+20] ; save the bottom four numbers
- fstp tbyte PTR es:[di+30] ; save full precision on overflow
- fstp tbyte PTR es:[di]
- fstp tbyte PTR es:[di+10]
- add di,40 ; adjust di
- END_INCL Push4
- ; --------------------------------------------------------------------------
- BEGN_INCL Push2a ; Push stack down from 6 to 4
- fdecstp ; roll the stack 4 times
- fdecstp
- fdecstp
- fdecstp
- fstp tbyte PTR es:[di] ; save only two numbers
- fstp tbyte PTR es:[di+10]
- add di, 20
- fincstp ; roll back 2 times
- fincstp
- END_INCL Push2a
- ; --------------------------------------------------------------------------
- ; End of stack overflow/underflow code.
- ; --------------------------------------------------------------------------
- BEGN_INCL Exp ; Exponent
- ; From FPU387.ASM with mods to use less registers.
- ; Modified to preserve 80-bit accuracy. CAE 10NOV93
- fldln2 ; ln2 x y
- fdivp st(1),st ; x/ln2 y
- fstp TBYTE PTR es:[di] ; y
- fsincos ; cosy, siny
- fld1 ; 1 cos sin
- fld TBYTE PTR es:[di] ; x/ln2 1 cos sin
- fprem ; prem, 1, cos, sin
- f2xm1 ; e**prem-1, 1, cos, sin
- fadd ; e**prem, cos, sin
- fld TBYTE PTR es:[di] ; x.x/ln2, e**prem, cos, sin
- fxch ; e**prem, x.x/ln2, cos, sin
- fscale ; e**x.x, x.x/ln2, cos, sin
- fstp st(1) ; e**x.x, cos, sin
- fmul st(2),st ; e**x.x, cos, z.y
- fmul ; z.x, z.y
- END_INCL Exp
- ; --------------------------------------------------------------------------
- BEGN_OPER Pwr ; Power
- ; First exchange the top two complex numbers.
- fxch st(2) ; x.x y.y y.x x.y
- fxch ; y.y x.x y.x x.y
- fxch st(3) ; x.y x.x y.x y.y
- fxch ; x.x x.y y.x y.y
- ; Now take the log of the # on st.
- INCL_OPER Pwr, Log ; l.x l.y y.x y.y
- cmp ax,1 ; log domain error?
- jne domainok ; nope
- cmp _debugflag, 94 ; user wants old pwr?
- je domainok ; yup
- POP_STK 4 ; clear stack completely
- fldz ; 0
- fldz ; 0 0
- EXIT_OPER Pwr ; return (0,0)
- PARSALIGN
- domainok:
- ; Inline multiply function from FPU087.ASM instead of include.
- fld st(1) ; y.y y.x y.y x.x x.y
- fmul st,st(4) ; y.y*x.y y.x y.y x.x x.y
- fld st(1) ; y.x y.y*x.y y.x y.y x.x x.y
- fmul st,st(4) ; y.x*x.x y.y*x.y y.x y.y x.x x.y
- fsubr ; newx=y.x*x.x-y.y*x.y y.x y.y x.x x.y
- fxch st(3) ; x.x y.x y.y newx x.y
- fmulp st(2),st ; y.x y.y*x.x newx x.y
- fmulp st(3),st ; y.y*x.x newx y.x*x.y
- faddp st(2),st ; newx newy=y.x*x.y+x.x*y.y
- ; Exp function from FPU387.ASM. 4 regs are free here.
- ; Modified to use the regs instead of memory. CAE 06NOV93
- fldln2 ; ln2 x y
- fdiv ; x/ln2 y
- fxch ; y x/ln2
- fsincos ; cosy, siny, x/ln2
- fxch ; sin, cos, x/ln2
- fxch st(2) ; x/ln2, cos, sin
- fld1 ; 1, x/ln2, cos, sin
- fld st(1) ; x/ln2, 1, x/ln2, cos, sin
- fprem ; prem, 1, x/ln2, cos, sin
- f2xm1 ; e**prem-1, 1, x/ln2, cos, sin
- fadd ; e**prem, x/ln2, cos, sin
- fscale ; e**x.x, x.x/ln2, cos, sin
- fstp st(1) ; e**x.x, cos, sin
- fmul st(2),st ; e**x.x, cos, z.y
- fmul ; z.x, z.y
- END_OPER Pwr
- ; --------------------------------------------------------------------------
- BEGN_OPER LodRealPwr ; lod, real, power CAE 6NOV93
- ; First take the log of the # on st.
- INCL_OPER LodRealPwr, Log ; l.x l.y
- ; Inline multiply by a real.
- FIXUP LodRealPwr, fld, X ; y.x, x.x, x.y
- fmul st(2),st ; y.x, x.x, z.y
- fmulp st(1),st ; z.x z.y
- ; Exp function from FPU387.ASM. 4 regs are free here, so use them.
- fldln2 ; ln2 x y
- fdiv ; x/ln2 y
- fxch ; y x/ln2
- fsincos ; cosy, siny, x/ln2
- fxch ; sin, cos, x/ln2
- fxch st(2) ; x/ln2, cos, sin
- fld1 ; 1, x/ln2, cos, sin
- fld st(1) ; x/ln2, 1, x/ln2, cos, sin
- fprem ; prem, 1, x/ln2, cos, sin
- f2xm1 ; e**prem-1, 1, x/ln2, cos, sin
- fadd ; e**prem, x/ln2, cos, sin
- fscale ; e**x.x, x.x/ln2, cos, sin
- fstp st(1) ; e**x.x, cos, sin
- fmul st(2),st ; e**x.x, cos, z.y
- fmul ; z.x, z.y
- END_OPER LodRealPwr
- ; --------------------------------------------------------------------------
- BEGN_OPER Cosh ; Cosh
- INCL_OPER Cosh, SinhCosh ; sinhx coshx y
- fxch st(2) ; y coshx sinhx
- fsincos ; cosy siny coshx sinhx
- fmulp st(2),st ; siny x=cosy*coshx sinhx
- fmulp st(2),st ; x y=sinhx*siny
- END_OPER Cosh
- ; --------------------------------------------------------------------------
- BEGN_OPER Sinh ; Sinh
- INCL_OPER Sinh, SinhCosh ; sinhx coshx y
- fxch st(2) ; y coshx sinhx
- fsincos ; cosy siny coshx sinhx
- fmulp st(3),st ; siny coshx x=sinhx*cosy
- fmulp st(1),st ; y=coshx*siny x
- fxch ; x y
- END_OPER Sinh
- ; --------------------------------------------------------------------------
- BEGN_OPER Sin ; Sin
- fsincos ; cosx sinx y
- fxch st(2) ; y sinx cosx
- INCL_OPER Sin, SinhCosh ; sinhy coshy sinx cosx
- fmulp st(3),st ; coshy sinx y=cosx*sinhy
- fmulp st(1),st ; x=sinx*coshy y
- END_OPER Sin
- ; --------------------------------------------------------------------------
- BEGN_OPER Cos ; Cos
- fsincos ; cosx sinx y
- fxch st(2) ; y sinx cosx
- INCL_OPER Cos, SinhCosh ; sinhy coshy sinx cosx
- fchs ; -sinhy coshy sinx cosx
- fmulp st(2),st ; coshy y=-sinhy*sinx cosx
- fmulp st(2),st ; y x=cosx*coshy
- fxch ; x y
- END_OPER Cos
- ; --------------------------------------------------------------------------
- BEGN_OPER CosXX ; CosXX
- fsincos ; cosx sinx y
- fxch st(2) ; y sinx cosx
- INCL_OPER CosXX, SinhCosh ; sinhy coshy sinx cosx
- ; note missing fchs here
- fmulp st(2),st ; coshy y=sinhy*sinx cosx
- fmulp st(2),st ; y x=cosx*coshy
- fxch ; x y
- END_OPER CosXX
- ; --------------------------------------------------------------------------
- BEGN_OPER Tan ; Tan
- fadd st,st ; 2x y
- fsincos ; cos2x sin2x y
- fxch st(2) ; y sin2x cos2x
- fadd st,st ; 2y sin2x cos2x
- INCL_OPER Tan, SinhCosh ; sinh2y cosh2y sin2x cos2x
- fxch ; cosh2y sinh2y sin2x cos2x
- faddp st(3),st ; sinhy sinx denom=cos2x+cosh2y
- fld st(2) ; denom sinh2y sin2x denom
- fdivp st(2),st ; sinh2y x=sin2x/denom denom
- fdivrp st(2),st ; x y=sinh2y/denom
- END_OPER Tan
- ; --------------------------------------------------------------------------
- BEGN_OPER CoTan ; CoTan
- fadd st,st ; 2x y
- fsincos ; cos2x sin2x y
- fxch st(2) ; y sin2x cos2x
- fadd st,st ; 2y sin2x cos2x
- INCL_OPER CoTan, SinhCosh ; sinh2y cosh2y sin2x cos2x
- fxch ; cosh2y sinh2y sin2x cos2x
- fsubrp st(3),st ; sinh2y sin2x denom=cosh2y-cos2x
- fld st(2) ; denom sinh2y sin2x denom
- fdivp st(2),st ; sinh2y x=sin2x/denom denom
- fchs ; -sinh2y x denom
- fdivrp st(2),st ; x y=-sinh2y/denom
- END_OPER CoTan
- ; --------------------------------------------------------------------------
- BEGN_OPER Tanh ; Tanh
- fadd st,st ; 2x y
- INCL_OPER Tanh, SinhCosh ; sinh2x cosh2x y
- fxch st(2) ; y cosh2x sinh2x
- fadd st,st ; 2y cosh2x sinh2x
- fsincos ; cos2y sin2y cosh2x sinh2x
- faddp st(2),st ; sin2y denom=cos2y+cosh2x sinh2x
- fxch ; denom sin2y sinh2x
- fdiv st(1),st ; denom y=sin2y/denom sinh2x
- fdivp st(2),st ; y x=sinh2x/denom
- fxch ; x y
- END_OPER Tanh
- ; --------------------------------------------------------------------------
- BEGN_OPER CoTanh ; CoTanh
- fadd st,st ; 2x y
- INCL_OPER CoTanh, SinhCosh ; sinh2x cosh2x y
- fxch st(2) ; y cosh2x sinh2x
- fadd st,st ; 2y cosh2x sinh2x
- fsincos ; cos2y sin2y cosh2x sinh2x
- fsubp st(2),st ; sin2y denom=cosh2x-cos2y sinh2x
- fchs ; -sin2y denom sinh2x
- fxch ; denom -sin2y sinh2x
- fdiv st(1),st ; denom y=-sin2y/denom sinh2x
- fdivp st(2),st ; y x=sinh2x/denom
- fxch ; x y
- END_OPER CoTanh
- ; --------------------------------------------------------------------------
- ; JCO added Sqrt .. CAbs for version 19.
- ; CAE updated them 15Feb94 to work with compiler mode.
- ; --------------------------------------------------------------------------
- BEGN_OPER Sqrt ; Sqrt
- GEN_SQRT
- END_OPER Sqrt
- ; --------------------------------------------------------------------------
- BEGN_OPER ASin ; ArcSin
- fld st(1) ; y x y
- fld st(1) ; x y x y
- GEN_SQR0 ; tz1.x tz1.y x y
- fxch st(1) ; tz1.y tz1.x x y
- fchs ; -tz1.y tz1.x x y
- fxch st(1) ; tz1.x -tz1.y x y
- fsubr __1_ ; 1-tz1.x -tz1.y x y
- GEN_SQRT ; tz1.x tz1.y x y
- fsubrp st(3),st ; tz1.y x tz1.x-y
- fadd ; tz1.y+x tz1.x-y
- fxch st(1) ; tz1.x-y tz1.y+x
- INCL_OPER ASin, Log ; l.x l.y
- fchs ; -l.x l.y
- fxch st(1) ; l.y -l.x ;; rz = (-i)*l
- END_OPER ASin
- ; --------------------------------------------------------------------------
- BEGN_OPER ACos ; ArcCos
- fld st(1) ; y x y
- fld st(1) ; x y x y
- GEN_SQR0 ; tz1.x tz1.y x y
- fsub __1_ ; tz1.x-1 tz1.y x y
- GEN_SQRT ; tz.x tz.y x y
- faddp st(2),st ; tz.y tz.x+x y
- faddp st(2),st ; tz.x+x tz.y+y
- INCL_OPER ACos, Log ; l.x l.y
- fchs ; -l.x l.y
- fxch st(1) ; l.y -l.x ;; rz = (-i)*l
- END_OPER ACos
- ; --------------------------------------------------------------------------
- BEGN_OPER ASinh ; ArcSinh
- fld st(1) ; y x y
- fld st(1) ; x y x y
- GEN_SQR0 ; tz1.x tz1.y x y
- fadd __1_ ; tz1.x+1 tz1.y x y
- GEN_SQRT ; tz.x tz.y x y
- faddp st(2),st ; tz.y tz.x+x y
- faddp st(2),st ; tz.x+x tz.y+y
- INCL_OPER ASinh, Log ; l.x l.y
- END_OPER ASinh
- ; --------------------------------------------------------------------------
- BEGN_OPER ACosh ; ArcCosh
- fld st(1) ; y x y
- fld st(1) ; x y x y
- GEN_SQR0 ; tz1.x tz1.y x y
- fsub __1_ ; tz1.x+1 tz1.y x y
- GEN_SQRT ; tz.x tz.y x y
- faddp st(2),st ; tz.y tz.x+x y
- faddp st(2),st ; tz.x+x tz.y+y
- INCL_OPER ACosh, Log ; l.x l.y
- END_OPER ACosh
- ; --------------------------------------------------------------------------
- BEGN_OPER ATanh ; ArcTanh
- fld st(1) ; y x y
- fchs ; -y x y
- fld st(1) ; x -y x y
- fld1 ; 1 x -y x y
- fadd st(3),st ; 1 x -y 1+x y
- fsubr ; 1-x -y 1+x y
- INCL_OPER ATanh, Div ; d.x d.y
- ; From FPU387.ASM
- ; Log is called by Pwr and is also called directly.
- ftst
- fstsw ax
- sahf
- jnz short ATanh_NotBothZero
- fxch ; y x
- ftst
- fstsw ax
- sahf
- fxch ; x y
- jnz short ATanh_NotBothZero
- POP_STK 2 ; clear two numbers
- fldz
- fldz
- jmp SHORT End_Log_ATanh ; return (0,0)
- PARSALIGN
- ATanh_NotBothZero:
- fld st(1) ; y x y
- fld st(1) ; x y x y
- fpatan ; z.y x y
- fxch st(2) ; y x z.y
- fmul st,st(0) ; yy x z.y
- fxch ; x yy z.y
- fmul st,st(0) ; xx yy z.y
- fadd ; mod z.y
- fldln2 ; ln2, mod, z.y
- fmul _PointFive ; ln2/2, mod, z.y
- fxch ; mod, ln2/2, z.y
- fyl2x ; z.x, z.y
- End_Log_ATanh:
- fld _PointFive ; .5 l.x l.y
- fmul st(1),st ; .5 l.x/2 l.y
- fmulp st(2),st ; l.x/2 l.y/2
- END_OPER ATanh
- ; --------------------------------------------------------------------------
- BEGN_OPER ATan ; ArcTan
- fxch ; y x
- fld st(1) ; x y x
- fchs ; -x y x
- fxch st(2) ; x y -x
- fld st(1) ; y x y -x
- fld1 ; 1 y x y -x
- fadd st(3),st ; 1 y x 1+y -x
- fsubr ; 1-y x 1+y -x
- INCL_OPER ATan, Div ; d.x d.y
- ; CAE put log fn inline 15Feb95
- ftst
- fstsw ax
- sahf
- jnz short ATan_NotBothZero
- fxch ; y x
- ftst
- fstsw ax
- sahf
- fxch ; x y
- jnz short ATan_NotBothZero
- POP_STK 2 ; clear two numbers
- fldz
- fldz
- jmp short End_Log_ATan ; return (0,0)
- PARSALIGN
- ATan_NotBothZero:
- fld st(1) ; y x y
- fld st(1) ; x y x y
- fpatan ; z.y x y
- fxch st(2) ; y x z.y
- fmul st,st(0) ; yy x z.y
- fxch ; x yy z.y
- fmul st,st(0) ; xx yy z.y
- fadd ; mod z.y
- fldln2 ; ln2, mod, z.y
- fmul _PointFive ; ln2/2, mod, z.y
- fxch ; mod, ln2/2, z.y
- fyl2x ; z.x, z.y
- End_Log_ATan:
- fld _PointFive ; .5 l.x l.y
- fmul st(1),st ; .5 z.y=l.x/2 l.y
- fmulp st(2),st ; z.y l.y/2
- fxch ; l.y/2 z.y
- fchs ; z.x=-l.y/2 z.y
- END_OPER ATan
- ; --------------------------------------------------------------------------
- BEGN_OPER CAbs ; Complex Absolute Value
- fmul st,st ; x*x y
- fxch ; y x*x
- fmul st,st ; y*y x*x
- fadd ; y*y+x*x
- fsqrt ; mag=sqrt(yy+xx)
- fldz ; 0 mag
- fxch ; mag 0
- END_OPER CAbs
- ; --------------------------------------------------------------------------
- ; End of new functions. CAE 15Feb95
- ; --------------------------------------------------------------------------
- BEGN_OPER LT ; <
- ; Arg2->d.x = (double)(Arg2->d.x < Arg1->d.x);
- fcomp st(2) ; y.y, x.x, x.y, comp arg1 to arg2
- fstsw ax
- POP_STK 3
- sahf
- fldz ; 0 (Arg2->d.y = 0.0;)
- jbe short LTfalse ; jump if arg1 <= arg2
- fld1 ; 1 0 (return arg2 < arg1)
- EXIT_OPER LT
- LTfalse:
- fldz ; 0 0
- END_OPER LT
- ; --------------------------------------------------------------------------
- BEGN_INCL LT2 ; LT, set AX, clear FPU
- ; returns !(Arg2->d.x < Arg1->d.x) in ax
- fcom st(2) ; compare arg1, arg2
- fstsw ax
- fninit
- sahf
- setbe al ; return (Arg1 <= Arg2) in AX
- xor ah,ah
- END_INCL LT2
- ; --------------------------------------------------------------------------
- BEGN_OPER LodLT ; load, LT
- ; return (1,0) on stack if arg2 < arg1
- FIXUP LodLT, fcomp, X ; compare arg2 to arg1, pop st
- fstsw ax ; y ...
- POP_STK 1 ; ...
- sahf
- fldz ; 0 ...
- jae short LodLTfalse ; jump when arg2 >= arg1
- fld1 ; 1 0 ...
- EXIT_OPER LodLT
- LodLTfalse:
- fldz ; 0 0 ...
- END_OPER LodLT
- ; --------------------------------------------------------------------------
- BEGN_OPER LodLT2 ; Lod, LT, set AX, clear FPU
- ; returns !(Arg2->d.x < Arg1->d.x) in ax
- FIXUP LodLT2, fcom, X ; compare arg2, arg1
- fstsw ax
- fninit ; clear fpu
- sahf
- setae al ; set al when arg2 >= arg1
- xor ah,ah ; clear ah
- END_OPER LodLT2 ; ret 0 in ax for true, 1 for false
- ; --------------------------------------------------------------------------
- BEGN_OPER LodLTMul ; Lod, LT, Multiply (needs 4 on stack)
- ; for '<expr> * ( <expr> < <var> )'
- ; return number on stack if arg2 < arg1
- FIXUP LodLTMul, fcomp, X ; comp Arg2 to Arg1, pop st
- fstsw ax ; save status
- POP_STK 1 ; clear 1 from stack
- sahf
- jae short LodLTMulfalse ; jump if arg2 >= arg1
- EXIT_OPER LodLTMul ; return value on st
- PARSALIGN
- LodLTMulfalse:
- POP_STK 2 ; return (0,0)
- fldz
- fldz
- END_OPER LodLTMul
- ; --------------------------------------------------------------------------
- BEGN_INCL GT ; >
- ; Arg2->d.x = (double)(Arg2->d.x > Arg1->d.x);
- fcomp st(2) ; compare arg1, arg2
- fstsw ax
- POP_STK 3
- sahf
- fldz ; 0 (Arg2->d.y = 0.0;)
- jae short GTfalse ; jump if Arg1 >= Arg2
- fld1 ; 1 0, return arg2 > arg1
- EXIT_OPER GT
- GTfalse:
- fldz ; 0 0
- END_INCL GT
- ; --------------------------------------------------------------------------
- BEGN_INCL GT2 ; GT, set AX, clear FPU
- ; returns !(Arg2->d.x > Arg1->d.x) in ax
- fcom st(2) ; compare arg1, arg2
- fstsw ax
- fninit
- sahf
- setae al ; return (Arg1 >= Arg2) in AX
- xor ah,ah
- END_INCL GT2
- ; --------------------------------------------------------------------------
- BEGN_OPER LodGT ; load, GT
- ; return (1,0) on stack if arg2 > arg1
- FIXUP LodGT, fcomp, X ; compare arg2 to arg1, pop st
- fstsw ax ; y ...
- POP_STK 1 ; ...
- sahf
- fldz ; 0 ...
- jbe short LodGTfalse ; jump when arg2 <= arg1
- fld1 ; 1 0 ...
- EXIT_OPER LodGT
- LodGTfalse:
- fldz ; 0 0 ...
- END_OPER LodGT
- ; --------------------------------------------------------------------------
- BEGN_OPER LodGT2 ; Lod, GT, set AX, clear FPU
- ; returns !(Arg2->d.x > Arg1->d.x) in AX
- FIXUP LodGT2, fcom, X ; compare arg2, arg1
- fstsw ax
- fninit ; clear fpu
- sahf
- setbe al ; set al when arg2 <= arg1
- xor ah,ah ; clear ah
- END_OPER LodGT2 ; ret 0 in ax for true, 1 for false
- ; --------------------------------------------------------------------------
- BEGN_INCL LTE ; <=
- ; Arg2->d.x = (double)(Arg2->d.x <= Arg1->d.x);
- fcomp st(2) ; y x y, comp Arg1 to Arg2
- fstsw ax ; save status now
- POP_STK 3
- fldz ; 0 (Arg2->d.y = 0.0;)
- sahf
- jb short LTEfalse ; jump if arg1 > arg2
- fld1 ; 1 0, ret arg2 <= arg1
- EXIT_OPER LTE
- LTEfalse:
- fldz ; 0 0
- END_INCL LTE
- ; --------------------------------------------------------------------------
- BEGN_INCL LTE2 ; LTE, test ST, clear
- ; return !(Arg2->d.x <= Arg1->d.x) in AX
- fcom st(2) ; comp Arg1 to Arg2
- fstsw ax
- fninit ; clear stack
- and ah,1 ; mask cf
- shr ax,8 ; ax=1 when arg1 < arg1
- END_INCL LTE2 ; return (Arg1 < Arg2),
- ; --------------------------------------------------------------------------
- BEGN_OPER LodLTE ; load, LTE
- ; return (1,0) on stack if arg2 <= arg1
- FIXUP LodLTE, fcomp, X ; compare arg2 to arg1, pop st
- fstsw ax ; y ...
- POP_STK 1 ; ...
- sahf
- fldz ; 0 ...
- ja short LodLTEfalse ; jump when arg2 > arg1
- fld1 ; 1 0 ...
- EXIT_OPER LodLTE
- LodLTEfalse:
- fldz ; 0 0 ...
- END_OPER LodLTE
- ; --------------------------------------------------------------------------
- BEGN_OPER LodLTE2 ; Load, LTE, test ST, clear
- ; return !(Arg2->d.x <= Arg1->d.x) in AX
- FIXUP LodLTE2, fcom, X ; comp Arg2 to Arg1
- fstsw ax
- fninit
- sahf
- seta al
- xor ah,ah ; ax=1 for expr. false
- END_OPER LodLTE2 ; return (Arg2 > Arg1)
- ; --------------------------------------------------------------------------
- BEGN_OPER LodLTEMul ; Lod, LTE, Multiply (needs 4 on stk)
- ; for '<expr> * ( <expr> <= <var> )'
- ; return number on stack if arg2 <= arg1
- FIXUP LodLTEMul, fcomp, X ; comp Arg2 to Arg1, pop st
- fstsw ax ; save status
- POP_STK 1 ; clear 1 from stack
- sahf
- ja short LodLTEMulfalse ; jump if arg2 > arg1
- EXIT_OPER LodLTEMul ; return value on st
- PARSALIGN
- LodLTEMulfalse:
- POP_STK 2 ; return (0,0)
- fldz
- fldz
- END_OPER LodLTEMul
- ; --------------------------------------------------------------------------
- BEGN_OPER LodLTEAnd2 ; Load, LTE, AND, test ST, clear
- ; this is for 'expression && (expression <= value)'
- ; stack has {arg2.x arg2.y logical.x junk} on entry (arg1 in memory)
- ; Arg2->d.x = (double)(Arg2->d.x <= Arg1->d.x);
- FIXUP LodLTEAnd2, fcom, X ; comp Arg2 to Arg1
- fstsw ax
- sahf
- fxch st(2) ; logical.x arg2.y arg2.x junk ...
- ja LTEA2RFalse ; right side is false, Arg2 > Arg1
- ftst ; now see if left side of expr is true
- fstsw ax
- sahf
- fninit ; clear fpu
- jz LTEA2LFalse ; jump if left side of && is false
- xor ax,ax ; return zero in ax for expr true
- ret ; changed EXIT_OPER->ret CAE 30DEC93
- LTEA2RFalse:
- fninit
- LTEA2LFalse:
- mov ax,1 ; return ax=1 for condition false
- END_OPER LodLTEAnd2
- ; --------------------------------------------------------------------------
- BEGN_INCL GTE ; >=
- ; Arg2->d.x = (double)(Arg2->d.x >= Arg1->d.x);
- fcomp st(2) ; y x y (compare arg1,arg2)
- fstsw ax
- POP_STK 3 ; clear 3 from stk
- sahf
- fldz ; 0 (Arg2->d.y = 0.0;)
- ja short GTEfalse ; jmp if arg1 > arg2
- fld1 ; 1 0 (return arg2 >= arg1 on stack)
- EXIT_OPER GTE
- GTEfalse:
- fldz ; 0 0
- END_INCL GTE
- ; --------------------------------------------------------------------------
- BEGN_OPER LodGTE ; load, GTE
- ; return (1,0) on stack if arg2 >= arg1
- FIXUP LodGTE, fcomp, X ; compare arg2 to arg1, pop st
- fstsw ax ; y ...
- POP_STK 1 ; ...
- fldz ; 0 ...
- sahf
- jb short LodGTEfalse ; jump when arg2 < arg1
- fld1 ; 1 0 ...
- EXIT_OPER LodGTE
- LodGTEfalse:
- fldz ; 0 0 ...
- END_OPER LodGTE
- ; --------------------------------------------------------------------------
- BEGN_OPER LodGTE2 ; Lod, GTE, set AX, clear FPU
- ; return !(Arg2->d.x >= Arg1->d.x) in AX
- FIXUP LodGTE2, fcom, X ; compare arg2, arg1
- fstsw ax
- fninit ; clear fpu
- and ah,1 ; mask cf
- shr ax,8 ; shift it (AX = 1 when arg2 < arg1)
- END_OPER LodGTE2 ; ret 0 in ax for true, 1 for false
- ; --------------------------------------------------------------------------
- BEGN_INCL EQ ; ==
- ; Arg2->d.x = (double)(Arg2->d.x == Arg1->d.x);
- fcomp st(2) ; compare arg1, arg2
- fstsw ax
- POP_STK 3
- sahf
- fldz ; 0 (Arg2->d.y = 0.0;)
- jne short EQfalse ; jmp if arg1 != arg2
- fld1 ; 1 0 (ret arg2 == arg1)
- EXIT_OPER EQ
- EQfalse:
- fldz
- END_INCL EQ
- ; --------------------------------------------------------------------------
- BEGN_OPER LodEQ ; load, EQ
- ; return (1,0) on stack if arg2 == arg1
- FIXUP LodEQ, fcomp, X ; compare arg2 to arg1, pop st
- fstsw ax ; y ...
- POP_STK 1 ; ...
- fldz ; 0 ...
- sahf
- jne short LodEQfalse ; jump when arg2 != arg1
- fld1 ; 1 0 ... (return arg2 == arg1)
- EXIT_OPER LodEQ
- LodEQfalse:
- fldz ; 0 0 ...
- END_OPER LodEQ
- ; --------------------------------------------------------------------------
- BEGN_INCL NE ; !=
- ; Arg2->d.x = (double)(Arg2->d.x != Arg1->d.x);
- fcomp st(2) ; compare arg1,arg2
- fstsw ax
- POP_STK 3
- sahf
- fldz
- je short NEfalse ; jmp if arg1 == arg2
- fld1 ; ret arg2 != arg1
- EXIT_OPER NE
- NEfalse:
- fldz
- END_INCL NE
- ; --------------------------------------------------------------------------
- BEGN_OPER LodNE ; load, NE
- ; return (1,0) on stack if arg2 != arg1
- FIXUP LodNE, fcomp, X ; compare arg2 to arg1, pop st
- fstsw ax ; y ...
- POP_STK 1 ; ...
- fldz ; 0 ...
- sahf
- je short LodNEfalse ; jump when arg2 == arg1
- ; CAE changed above 'jne' to 'je' 9 MAR 1993
- fld1 ; 1 0 ...
- EXIT_OPER LodNE
- LodNEfalse:
- fldz ; 0 0 ...
- END_OPER LodNE
- ; --------------------------------------------------------------------------
- BEGN_INCL OR ; Or
- ; Arg2->d.x = (double)(Arg2->d.x || Arg1->d.x);
- ftst ; a1.x a1.y a2.x a2.y ...
- fstsw ax
- sahf
- POP_STK 2 ; a2.x a2.y ...
- jnz short Arg1True
- ftst
- fstsw ax
- sahf
- POP_STK 2 ; ...
- fldz ; 0 ...
- jz short NoneTrue
- fld1 ; 1 0 ...
- EXIT_OPER OR
- PARSALIGN
- Arg1True:
- POP_STK 2 ; ...
- fldz ; 0 ...
- fld1 ; 1 0 ...
- EXIT_OPER OR
- NoneTrue: ; 0 ...
- fldz ; 0 0 ...
- END_INCL OR
- ; --------------------------------------------------------------------------
- BEGN_INCL AND ; And
- ; Arg2->d.x = (double)(Arg2->d.x && Arg1->d.x);
- ftst ; a1.x a1.y a2.x a2.y ...
- fstsw ax
- sahf
- POP_STK 2 ; a2.x a2.y ...
- jz short Arg1False
- ftst
- fstsw ax
- sahf
- POP_STK 2 ; ...
- fldz ; 0 ...
- jz short Arg2False
- fld1 ; 1 0 ...
- EXIT_OPER AND
- PARSALIGN
- Arg1False:
- POP_STK 2 ; ...
- fldz ; 0 ...
- Arg2False:
- fldz ; 0 0 ...
- END_INCL AND
- ; --------------------------------------------------------------------------
- BEGN_INCL ANDClr2 ; And, test ST, clear FPU
- ; for bailouts using <condition> && <condition>
- ; Arg2->d.x = (double)(Arg2->d.x && Arg1->d.x);
- ; Returns !(Arg1 && Arg2) in ax
- ftst ; y.x y.y x.x x.y
- fstsw ax
- sahf
- jz short Arg1False2
- fxch st(2) ; x.x y.y y.x x.y
- ftst
- fstsw ax
- sahf
- fninit
- jz short Arg2False2
- BothTrue2:
- xor ax,ax
- ret ; changed EXIT_OPER->ret CAE 30DEC93
- Arg1False2:
- fninit
- Arg2False2:
- mov ax,1
- END_INCL ANDClr2
- ; --------------------------------------------------------------------------
- BEGN_INCL ORClr2 ; Or, test ST, clear FPU CAE 6NOV93
- ; for bailouts using <condition> || <condition>
- ; Arg2->d.x = (double)(Arg2->d.x || Arg1->d.x);
- ; Returns !(Arg1 || Arg2) in ax
- ftst ; y.x y.y x.x x.y
- fstsw ax
- sahf
- jnz short ORArg1True
- fxch st(2) ; x.x y.y y.x x.y
- ftst
- fstsw ax
- sahf
- fninit
- jnz short ORArg2True
- ORNeitherTrue:
- mov ax,1
- ret ; changed EXIT_OPER->ret CAE 30DEC93
- ORArg1True:
- fninit
- ORArg2True:
- xor ax,ax
- END_INCL ORClr2
-
- ; --------------------------------------------------------------------------
- assume ds:DGROUP, es:nothing
- ; --------------------------------------------------------------------------
-
- ifndef COMPILER
-
- ; --------------------------------------------------------------------------
- ; called once per image
- ; --------------------------------------------------------------------------
- public _Img_Setup
- align 2
- ; Changed to FAR, FRAME/UNFRAME added by CAE 09OCT93
- _Img_Setup proc far
- FRAME <si,di>
- les si,_pfls ; es:si = &pfls[0]
-
- mov di,_LastOp ; load index of lastop
-
- dec di ; flastop now points at last operator
- ; above added by CAE 09OCT93 because of loop logic changes
-
- shl di,2 ; convert to offset
- mov bx,offset DGROUP:_fLastOp ; set bx for store
- add di,si ; di = offset lastop
- mov WORD PTR [bx],di ; save value of flastop
- mov ax,es ; es has segment value
- mov WORD PTR [bx+2],ax ; save seg for easy reload
- mov ax,word ptr _v ; build a ptr to Z
- add ax,3*CARG+CPFX
- mov _PtrToZ,ax ; and save it
- UNFRAME <di,si>
- ret
- _Img_Setup endp
- ; --------------------------------------------------------------------------
- ; Hybrid orbitcalc/per-pixel routine (tested, but not implemented.)
- ;
- ; To implement, stick the following code in calcfrac.c around line 788,
- ; just before the line that says "while (++coloriter < maxit)".
- ; --------------------------------------------------------------------------
- ; if (curfractalspecific->orbitcalc == fFormula /* 387 parser */
- ; && periodicitycheck == 0
- ; && !show_orbit
- ; && inside >= -5
- ; && attractors == 0
- ; && !distest ){
- ; fFormulaX(); /* orbit till done */
- ; } else
- ; --------------------------------------------------------------------------
- public _fFormulaX ; CAE 09OCT93
- align 16
- _fFormulaX proc far
- push si
- push di
- mov edx,_maxit ; edx holds coloriter during loop
- mov _coloriter,edx ; set coloriter to maxit
- mov ax,ds ; save ds in ax
- lds cx,_fLastOp ; ds:cx -> one past last token
- mov es,ax ; es -> DGROUP
- assume es:DGROUP, ds:nothing ; swap es, ds before any fn. calls
- jmp short skipfirst ; skip bailout test first time
- align 16
- outer_loop:
- or ax,ax ; did bailout occur?
- jnz short doneloop ; yes, exit
- skipfirst:
- dec edx ; ++coloriter
- jle short doneloop ; yes, exit because of maxiter
- mov bx,_InitOpPtr ; bx -> one before first token
- mov di,offset DGROUP:_s ; reset stk overflow ptr
- align 16
- inner_loop2:
- cmp bx,cx ; time to quit yet?
- jae short outer_loop ; yes, bx points to last function
- add bx,4 ; point to next pointer pair
- push offset PARSERA_TEXT:inner_loop2 ; do this first
- mov si,WORD PTR [bx+2] ; set si to operand pointer
- jmp WORD PTR [bx] ; jmp to operator fn
- align 16
- doneloop:
- ; NOTE: edx must be preserved here.
- mov si,_PtrToZ ; ds:si -> z
- mov di,offset DGROUP:_new ; es:di -> new
- mov cx,4
- rep movsd ; new = z
- mov ax,es
- pop di
- pop si
- mov ds,ax ; restore ds before return
- assume ds:DGROUP, es:nothing
- sub _coloriter,edx ; now put new coloriter back from edx
- ret
- _fFormulaX endp
- ; --------------------------------------------------------------------------
- ; orbitcalc function follows
- ; --------------------------------------------------------------------------
- public _fFormula
- align 16
- _fFormula proc far
- push di ; don't build a frame here
- mov di,offset DGROUP:_s ; reset this for stk overflow area
- mov bx,_InitOpPtr ; bx -> one before first token
- mov ax,ds ; save ds in ax
- lds cx,_fLastOp ; ds:cx -> last token
- mov es,ax ; es -> DGROUP
- assume es:DGROUP, ds:nothing
- align 16 ; already aligned 16
- push si ; 1-byte instruction
- inner_loop: ; loop revised CAE 09OCT93
- cmp bx,cx ; time to quit yet?
- jae short past_loop ; yes, bx points to last token
- add bx,4 ; point to next token
- push offset PARSERA_TEXT:inner_loop ; push return addr first
- mov si,WORD PTR [bx+2] ; now set si to operand pointer
- jmp WORD PTR [bx] ; ...and jump to operator fn
- past_loop: ; 15-byte loop
- ; NOTE: AX was set by the last operator fn called.
- mov si,_PtrToZ ; ds:si -> z
- mov di,offset DGROUP:_new ; es:di -> new
- mov cx,4 ; get ready to move 4 dwords
- rep movsd ; new = z
- mov bx,es ; put seg dgroup in bx
- pop si
- pop di ; restore si, di
- mov ds,bx ; restore ds from bx before return
- assume ds:DGROUP, es:nothing
- ret ; return AX unmodified
- _fFormula endp
- ; --------------------------------------------------------------------------
- public _fform_per_pixel ; called once per pixel
- align 4
- _fform_per_pixel proc far
- FRAME <si, di>
- cmp _invert,0 ; inversion support added
- je skip_invert ; CAE 08FEB95
- mov si,offset DGROUP:_old
- push si
- call far ptr _invertz2
- add sp,2
- ; now copy old to v[0].a.d
- les di,_v ; ds:si already points to old
- add di,CPFX ; make es:di point to v[0].a.d
- mov cx,4
- rep movsd
- jmp after_load
- skip_invert:
- ; /* v[5].a.d.x = */ (v[0].a.d.x = dx0[col]+dShiftx);
- mov ax,_col
- shl ax,3
- les bx,_dx0
- add bx,ax
- fld QWORD PTR es:[bx]
- mov ax,_row
- shl ax,3
- les bx,_dx1
- add bx,ax
- fadd QWORD PTR es:[bx]
- les bx,_v
- fstp QWORD PTR es:[bx+CPFX]
- ; /* v[5].a.d.x = */ (v[0].a.d.y = dy0[row]+dShifty);
- mov ax,_row
- shl ax,3
- les bx,_dy0
- add bx,ax
- fld QWORD PTR es:[bx]
- mov ax,_col
- shl ax,3
- les bx,_dy1
- add bx,ax
- fadd QWORD PTR es:[bx]
- les bx,_v
- fstp QWORD PTR es:[bx+CPFX+8] ; make this an fstp
- after_load:
- mov di,offset DGROUP:_s ; di points to stack overflow area
- mov ax,ds
- mov bx,WORD PTR _pfls ; bx -> pfls
- lds cx,_fLastOp ; cx = offset &f[LastOp],load ds
- mov es,ax
- assume es:DGROUP, ds:nothing
- cmp _LastInitOp,0
- je short skip_initloop ; no operators to do here
- mov _LastInitOp,cx ; lastinitop=lastop
- jmp short pixel_loop
- align 16
- pixel_loop:
- mov si,WORD PTR [bx+2] ; get address of load or store
- call WORD PTR [bx] ; (*opptr)()
- add bx,4 ; ++opptr
- cmp bx,_LastInitOp
- jb short pixel_loop
- skip_initloop:
- mov si,_PtrToZ ; ds:si -> z
- mov di,offset DGROUP:_old ; es:di -> old
- mov cx,4 ; get ready to move 4 dwords
- rep movsd ; old = z
- mov ax,es
- mov ds,ax
- assume ds:DGROUP, es:nothing ; for the rest of the program
- sub bx,4 ; make initopptr point 1 token b4 1st
- mov _InitOpPtr, bx ; InitOptPtr = OpPtr;
- UNFRAME <di, si>
- xor ax,ax
- ret
- _fform_per_pixel endp
- ; --------------------------------------------------------------------------
-
- else ; Compiler
-
- ; --------------------------------------------------------------------------
- ; . . . and now for the real fun!
- ; --------------------------------------------------------------------------
- public _Img_Setup
- align 2
- _Img_Setup proc far
- mov ax,word ptr _v ; build a ptr to Z
- add ax,3*CARG+CPFX
- mov _PtrToZ,ax ; and save it
- ret
- _Img_Setup endp
- ; --------------------------------------------------------------------------
- ; Hybrid orbitcalc/per-pixel routine.
- ; --------------------------------------------------------------------------
- public _fFormulaX
- align 16
- _fFormulaX proc far
- push si
- push di
- mov edx,_maxit ; edx holds coloriter during loop
- mov _coloriter,edx ; set coloriter to maxit
- mov ax,ds ; save ds in ax
- mov cx,word ptr _pfls+2 ; just get the seg part
- mov es,ax ; es -> DGROUP
- mov ds,cx ; ds -> parser data
- assume es:DGROUP, ds:nothing
- jmp short skipfirst ; skip bailout test first time
- align 16
- outer_loop:
- or ax,ax ; did bailout occur?
- jnz short doneloop ; yes, exit
- skipfirst:
- dec edx ; ++coloriter, was maxiter reached?
- jle short doneloop ; yes, exit because of maxiter
- push offset PARSERA_TEXT:outer_loop
- mov di,offset DGROUP:_s ; reset this for stk overflow area
- jmp _compiled_fn_2 ; call the compiled code
- doneloop:
- ; NOTE: edx must be preserved here.
- mov si,_PtrToZ ; ds:si -> z
- mov di,offset DGROUP:_new ; es:di -> new
- mov cx,4
- rep movsd ; new = z
- mov ax,es
- pop di
- pop si
- mov ds,ax ; restore ds before return
- assume ds:DGROUP, es:nothing
- sub _coloriter,edx ; now put new coloriter back from edx
- ret
- _fFormulaX endp
- ; --------------------------------------------------------------------------
- ; orbitcalc function follows
- ; --------------------------------------------------------------------------
- public _fFormula
- align 16
- _fFormula proc far
- push di ; don't build a frame here
- mov di,offset DGROUP:_s ; reset this for stk overflow area
- mov ax,ds ; save ds in ax
- mov cx,WORD PTR _pfls+2 ; just load seg value
- mov es,ax ; es -> DGROUP
- mov ds,cx ; ds -> parser data
- assume es:DGROUP, ds:nothing
- push si ; compiled_fn modifies si
- call _compiled_fn_2 ; call the compiled code
- ; NOTE: AX was set by the compiled code and must be preserved here.
- mov si,_PtrToZ ; ds:si -> z
- mov di,offset DGROUP:_new ; es:di -> new
- mov cx,4 ; get ready to move 4 dwords
- rep movsd ; new = z
- mov bx,es ; put seg dgroup in bx
- pop si
- pop di ; restore si, di
- mov ds,bx ; restore ds from bx before return
- assume ds:DGROUP, es:nothing
- ret ; return AX unmodified
- _fFormula endp
- ; --------------------------------------------------------------------------
- public _fform_per_pixel ; called once per pixel
- align 4
- _fform_per_pixel proc far
- FRAME <si, di>
- cmp _invert,0 ; inversion support added
- je skip_invert ; CAE 08FEB95
- mov si,offset DGROUP:_old
- push si
- call far ptr _invertz2
- add sp,2
- ; now copy old to v[0].a.d
- les di,_v ; ds:si already points to old
- add di,CPFX ; make es:di point to v[0].a.d
- mov cx,4
- rep movsd
- jmp after_load
- skip_invert:
- ; /* v[5].a.d.x = */ (v[0].a.d.x = dx0[col]+dShiftx);
- mov ax,_col
- shl ax,3
- les bx,_dx0
- add bx,ax
- fld QWORD PTR es:[bx]
- mov ax,_row
- shl ax,3
- les bx,_dx1
- add bx,ax
- fadd QWORD PTR es:[bx]
- les bx,_v
- fstp QWORD PTR es:[bx+CPFX]
- ; /* v[5].a.d.x = */ (v[0].a.d.y = dy0[row]+dShifty);
- mov ax,_row
- shl ax,3
- les bx,_dy0
- add bx,ax
- fld QWORD PTR es:[bx]
- mov ax,_col
- shl ax,3
- les bx,_dy1
- add bx,ax
- fadd QWORD PTR es:[bx]
- les bx,_v
- fstp QWORD PTR es:[bx+CPFX+8] ; make this an fstp
- after_load:
- mov di,offset DGROUP:_s ; di points to stack overflow area
- mov ax,ds
- mov cx,word ptr _pfls+2 ; just to load ds
- mov es,ax ; es -> DGROUP
- mov ds,cx ; ds -> parser data
- assume es:DGROUP, ds:nothing
- call _compiled_fn_1 ; call compiled code
- mov ax,es
- mov ds,ax
- assume ds:DGROUP, es:nothing ; for the rest of the program
- UNFRAME <di, si>
- xor ax,ax
- ret
- _fform_per_pixel endp
-
- align 16
- public _compiled_fn_1
- _compiled_fn_1 proc near
- retn ; compiled code will be put here
- db 1023 DUP (?)
- _compiled_fn_1 endp
-
- align 16
- public _compiled_fn_2
- _compiled_fn_2 proc near
- retn ; ...and here
- db 1023 DUP (?)
- _compiled_fn_2 endp
- ; --------------------------------------------------------------------------
-
- endif ; COMPILER
-
- ; --------------------------------------------------------------------------
-
-
- PARSERA_TEXT ends
- end
-