home *** CD-ROM | disk | FTP | other *** search
/ Fractal Creations (Second Edition) / FRACTALS_2E.iso / frasrc.exe / PARSERA.ASM < prev    next >
Assembly Source File  |  1993-07-13  |  69KB  |  1,518 lines

  1.    PAGE          ,132
  2.  
  3. ;    Name: PARSERA.ASM
  4. ;  Author: Chuck Ebbert  CompuServe [76306,1226]
  5. ;                         internet: 76306.1226@compuserve.com
  6. ;    Date: 12 July 1993
  7.  
  8. ; Fast floating-point routines for Fractint.
  9.  
  10. ;   Copyright (C) 1992, 1993 Chuck Ebbert.  All rights reserved.
  11.  
  12. ; This program is an assembler version of the C 'execution engine' part
  13. ;    of Mark Peterson's FRACTINT Formula Parser.  Many of the operator
  14. ;    functions were copied from Mark's code in the files FPU087.ASM
  15. ;    and FPU387.ASM.  The basic operator functions are assembler versions
  16. ;    of the code in PARSER.C.  Many 'combined' operators functions were
  17. ;    added to the program as well.
  18.  
  19. ;    This code may be freely distributed and used in non-commercial
  20. ;    programs provided the author is credited either during program
  21. ;    execution or in the documentation, and this copyright notice
  22. ;    is left intact.  Sale of this code, or its use in any commercial
  23. ;    product requires permission from the author.  Nominal distribution
  24. ;    and handling fees may be charged by shareware and freeware
  25. ;    distributors.
  26.  
  27. ;       Chuck Ebbert
  28. ;       1915 Blust Ln.
  29. ;       Enola, PA  17025
  30.  
  31.    .386                                ; this only works on a 386
  32.    .387                                ;  with a 387
  33.  
  34. ifdef ??version
  35.    masm51
  36.    quirks
  37. endif
  38.  
  39. ARGSZ              equ 16              ; size of complex arg
  40. ;;;ARGSZ              equ 32              ; size of hypercomplex arg
  41. CPFX               equ 4               ; size of constarg prefix
  42. CARG               equ CPFX+ARGSZ      ; size of constarg
  43. LASTSQR            equ CARG*4+CPFX     ; offset of lastsqr from start of v
  44.  
  45. ; ---------------------------------------------------------------------------
  46. FRAME              MACRO regs          ; build a stack frame
  47.       push         bp
  48.       mov          bp, sp
  49.    IRP             reg, <regs>
  50.       push         reg
  51.       ENDM
  52.    ENDM
  53.  
  54. UNFRAME            MACRO regs          ; unframe before return
  55.    IRP             reg, <regs>
  56.       pop          reg
  57.       ENDM
  58.       pop          bp
  59.    ENDM
  60.  
  61. ; ---------------------------------------------------------------------------
  62. ; Pop a number of scalars from the FPU stack.
  63. ; Generate as many 'fcompp' instr.'s as possible.
  64. ; Then a 'fstp st(0)' if needed.
  65. POP_STK            MACRO StkPop
  66.    NumToPop        = StkPop SHR 1
  67.    REPT            NumToPop
  68.       fcompp
  69.       ENDM
  70.    NumToPop        = StkPop - ( NumToPop SHL 1 )
  71.    REPT            NumToPop
  72.       fstp         st(0)
  73.       ENDM
  74.    ENDM
  75.  
  76. ; Uncomment the following line to enable compiler code generation.
  77. ;;;COMPILER           EQU 1
  78. ; ---------------------------------------------------------------------------
  79. ; Generate beginning code for operator fn.
  80. BEGN_OPER          MACRO OperName
  81.    ifdef           COMPILER
  82. ;; generate the fixups for compiler
  83. ;; size of fn.
  84.       db           Size_&OperName
  85. ;; offset of x fixup
  86.       db           XFixup_&OperName
  87. ;; offset of y fixup
  88.       db           YFixup_&OperName
  89. ;; offset of included(called) fn
  90.       db           Incl_&OperName
  91. ;; addr of fn to include
  92.       dw           IAddr_&OperName
  93. ;; size of fn to include
  94.       db           ILen_&OperName
  95.    else
  96.  
  97. ;; only align when no compiler
  98.    align           4
  99.    endif
  100.  
  101. ;; always generate public and begin of proc
  102.    public          _fStk&OperName
  103. _fStk&OperName     proc near
  104.    ENDM
  105.  
  106. ; ---------------------------------------------------------------------------
  107. ; Generate end of operator fn. code.
  108. ;
  109. END_OPER           MACRO OperName
  110.    ifndef          COMPILER
  111. ;; gen a return instr.
  112.       ret
  113.    else
  114.  
  115. ;; gen a jump label
  116. End_&OperName:
  117. ;; generate zero for fixups not generated during fn.
  118.    ifndef          Incl_&OperName
  119. ;; No included operator. Generate zero offset, address, and size.
  120. Incl_&OperName     EQU 0
  121. IAddr_&OperName    EQU 0
  122. ILen_&OperName     EQU 0
  123.    endif
  124.    ifndef          XFixup_&OperName
  125. ;; No X fixup.
  126. XFixup_&OperName   EQU 0
  127.    endif
  128.    ifndef          YFixup_&OperName
  129. ;; No Y fixup
  130. YFixup_&OperName   EQU 0
  131.    endif
  132.    endif
  133.  
  134. ;; Always gen size of fn
  135. Size_&OperName     EQU $ - _fStk&OperName
  136. ;; and end of procedure.
  137. _fStk&OperName     endp
  138.    ENDM
  139.  
  140. ; ---------------------------------------------------------------------------
  141. ; Generate beginning code for 'included' operator fn.
  142. ; No fixups here.
  143. BEGN_INCL          MACRO OperName
  144.    ifndef          COMPILER
  145. ;; No align for 'compiler' mode.
  146.    align           4
  147.    endif
  148.  
  149. ;; Generate public (incl fns. can be called directly) and begin of proc.
  150.    public          _fStk&OperName
  151. _fStk&OperName     proc near
  152.    ENDM
  153.  
  154. ; ---------------------------------------------------------------------------
  155. ; Generate end of 'included' operator fn. code.
  156. END_INCL           MACRO OperName
  157.    ifndef          COMPILER
  158. ;; generate return
  159.       ret
  160.    else
  161.  
  162. ;; generate label for jump to end of fn.
  163. End_&OperName:
  164.    endif
  165.  
  166. ;; always generate actual size of fn.
  167.    Size_&OperName  EQU $ - _fStk&OperName
  168. ;; always generate end-of-proc
  169. _fStk&OperName     endp
  170.    ENDM
  171.  
  172. ; ---------------------------------------------------------------------------
  173. ; 'Include' a function inside another one
  174. INCL_OPER          MACRO CallingOper,OperToIncl
  175.    ifdef           COMPILER
  176. ;; Offset of include in outer fn.
  177. Incl_&CallingOper  EQU $ - _fStk&CallingOper
  178. ;; Address of included fn.
  179. IAddr_&CallingOper EQU _fStk&OperToIncl
  180. ;; Length of included fn.
  181. ILen_&CallingOper  EQU Size_&OperToIncl
  182.    else
  183.  
  184. ;; Generate a call to the included fn.
  185.       call         _fStk&OperToIncl
  186.    endif
  187.    ENDM
  188.  
  189. ; ---------------------------------------------------------------------------
  190. ; Exit early from an operator function.
  191. EXIT_OPER          MACRO FnToExit
  192.    ifdef           COMPILER
  193. ;; jump to end of operator fn
  194.       jmp          short End_&FnToExit
  195.    else
  196.  
  197. ;; return to caller
  198.       ret
  199.    endif
  200.    ENDM
  201.  
  202. ; ---------------------------------------------------------------------------
  203. ; Generate an FPU instruction and a fixup.
  204. ; AddrToFix is = X or Y
  205. FIXUP              MACRO OperName, InstrToFix, Addr
  206.    ifdef           COMPILER
  207.  
  208. ;; Generate a fixup as an offset from start of fn.
  209. ;; This is why no includes allowed before a fixup.
  210. ;; Fixup is two bytes into the instruction, thus the '+ 2'.
  211. ;; This may not be true for all instructions.
  212.    ifidni          <Addr>, <X>
  213. XFixup_&OperName   EQU $ - _fStk&OperName + 2
  214.    else
  215. ;; assume fixup is for y
  216. YFixup_&OperName   EQU $ - _fStk&OperName + 2
  217.    endif
  218. ;; Generate a load, store or whatever of any convenient value using DS.
  219.       &InstrToFix  QWORD PTR ds:_fLastOp
  220.    else
  221.  
  222.    ifidni          <Addr>, <X>
  223. ;; Gen load of X using SI.
  224.       &InstrToFix  QWORD PTR [si]
  225.    else
  226. ;; Assume fixup is for y, use SI+8.
  227.       &InstrToFix  QWORD PTR [si+8]
  228.    endif
  229.    endif
  230.  
  231.    ENDM
  232.  
  233. ; ---------------------------------------------------------------------------
  234. ; Align 4 if no compiler.
  235. PARSALIGN          macro AlignFn
  236.    ifndef          COMPILER
  237.    align           4
  238.    endif
  239.    ENDM
  240.  
  241. ; ---------------------------------------------------------------------------
  242. ; external functions
  243.    extrn           _TranspPerPixel:far
  244.  
  245. ; ---------------------------------------------------------------------------
  246. _DATA              segment word public use16 'DATA'
  247.    extrn           _maxit:WORD
  248.    extrn           _inside:WORD
  249.    extrn           _outside:WORD
  250.    extrn           _color:WORD
  251.    extrn           _realcolor:WORD
  252.    extrn           _kbdcount:WORD      ; keyboard counter
  253.    extrn           _dotmode:WORD
  254.    extrn           __1_:QWORD, _PointFive:QWORD, __2_:QWORD, _infinity:QWORD
  255.    extrn           _LastOp:WORD, _LastInitOp:WORD
  256.    extrn           _InitOpPtr:WORD, _InitStoPtr:WORD, _InitLodPtr:WORD
  257.    extrn           _s:WORD
  258.    extrn           _OpPtr:WORD, _LodPtr:WORD, _StoPtr:WORD
  259.    extrn           _Load:DWORD, _Store:DWORD
  260.    extrn           _FormName:byte
  261.    extrn           _dy1:DWORD, _dx1:DWORD, _dy0:DWORD, _dx0:DWORD
  262.    extrn           _new:WORD, _old:WORD
  263.    extrn           _overflow:WORD
  264.    extrn           _col:WORD, _row:WORD
  265.    extrn           _Transparent3D:WORD
  266.    extrn           _Arg1:WORD, _Arg2:WORD
  267.    extrn           _f:DWORD, _pfls:DWORD, _v:DWORD
  268. _DATA               ends
  269.  
  270. _BSS               segment word public use16 'BSS'
  271. _fLastOp           label DWORD         ; save seg, offset of lastop here
  272.       dd           ?
  273. _PtrToZ            label WORD
  274.       dw           ?
  275. _BSS               ends
  276.  
  277. DGROUP             group _DATA,_BSS
  278.  
  279. ; ---------------------------------------------------------------------------
  280. ; Operator Functions follow.
  281. ; ---------------------------------------------------------------------------
  282.  
  283. ; NOTE: None of these operator functions may change any registers but
  284. ;       ax and si.  The exceptions are those functions that update
  285. ;       the current values of the 'status' regs as needed.
  286.  
  287. ;  On entry to these functions:
  288. ;   FPU stack is used as the evaluation stack.
  289. ;         The FPU stack can overflow into memory.  Accuracy is not lost but
  290. ;         calculations are slower.
  291. ;   es -> DGROUP
  292. ;   ds -> seg pfls, seg v
  293. ;   cx -> lastop
  294. ;   dx == orbit counter (if calcfrmfpasm is running)
  295. ;   di -> stack overflow area, used by push and pull functions
  296. ;   bx -> current operator, operand pair
  297. ;    [bx] = operator function address, i.e. addr. of current '_fStkXXX'
  298. ;    [bx+2] = operand pointer or zero if no operand
  299. ;   si = operand pointer (loaded from [bx+2] before call of operator fn.)
  300.  
  301. ; New rules Feb 1993:
  302. ;  1. No EXIT_OPER before an INCL_OPER.
  303. ;  2. No jumps can be made past an included function.
  304. ;  2. No included fn may include another, or have any fixups.
  305. ;  3. Only one included fn. allowed per 'normal' fn.
  306. ;  4. Fixups must be before any included fn.
  307.  
  308. ; --------------------------------------------------------------------------
  309.    ;  Put this code in PARSERFP.C's code segment.
  310. PARSERFP_TEXT     segment para public use16 'CODE'
  311.    ;  Non-standard segment register setup.
  312.    assume         es:DGROUP, ds:nothing, cs:PARSERFP_TEXT
  313. ; --------------------------------------------------------------------------
  314. ; Included functions must be first.
  315. ; --------------------------------------------------------------------------
  316.    BEGN_INCL       Log                 ; Log
  317.    ; From FPU387.ASM
  318.    ; Log is called by Pwr and is also called directly.
  319.       ftst
  320.       fstsw        ax
  321.       sahf
  322.       jnz          short NotBothZero
  323.       fxch                             ; y x
  324.       ftst
  325.       fstsw        ax
  326.       sahf
  327.       fxch                             ; x y
  328.       jnz          short NotBothZero
  329.       POP_STK      2                   ; clear two numbers
  330.       fldz
  331.       fldz
  332.       EXIT_OPER    Log                 ; return (0,0)
  333.    PARSALIGN
  334. NotBothZero:
  335.       fld          st(1)               ; y x y
  336.       fld          st(1)               ; x y x y
  337.       fpatan                           ; z.y x y
  338.       fxch         st(2)               ; y x z.y
  339.       fmul         st,st(0)            ; yy x z.y
  340.       fxch                             ; x yy z.y
  341.       fmul         st,st(0)            ; xx yy z.y
  342.       fadd                             ; mod z.y
  343.       fldln2                           ; ln2, mod, z.y
  344.       fmul         _PointFive          ; ln2/2, mod, z.y
  345.       fxch                             ; mod, ln2/2, z.y
  346.       fyl2x                            ; z.x, z.y
  347.    END_INCL        Log
  348. ; --------------------------------------------------------------------------
  349.    BEGN_INCL       SinhCosh            ; Included fn, Sinh, Cosh of st
  350.    ; From FPU087.ASM with mods to use less registers.
  351.       fstcw        _Arg2               ; use arg2 to hold CW
  352.       fwait
  353.       fldln2                           ; ln(2) x
  354.       fdivp        st(1),st            ; x/ln(2), start the fdivr instr.
  355.       mov          ax,_Arg2            ; Now do some integer instr.'s
  356.       push         ax                  ; Save control word on stack
  357.       or           ax,0000110000000000b
  358.       mov          _Arg2,ax
  359.       fldcw        _Arg2               ; Set control to round towards zero
  360.       ftst                             ; save the sign of x in ax
  361.       fstsw        ax                  ; sahf instr. is below
  362.       fabs                             ; |x|/ln2
  363.       fld          st                  ; |x|/ln(2), |x|/ln(2)
  364.       frndint                          ; int = integer(|x|/ln(2)), |x|/ln(2)
  365.       fxch                             ; |x|/ln(2), int
  366.       fsub         st,st(1)            ; rem < 1.0, int
  367.       fmul         _PointFive          ; rem/2 < 0.5, int
  368.       f2xm1                            ; (2**(rem/2))-1, int
  369.       fadd         __1_                ; 2**(rem/2), int
  370.       fmul         st,st               ; 2**rem, int
  371.       sahf                             ; ah has result of ftst above
  372.       fscale                           ; e**|x|, int
  373.       fstp         st(1)               ; e**|x|
  374.       jae          short ExitFexp      ; skip divide if x was >= 0
  375.  
  376.       fdivr        __1_                ; e**x
  377.    PARSALIGN
  378. ExitFexp:
  379.       fld          st                  ; e**x, e**x
  380.       fmul         _PointFive          ; e^x/2 e^x
  381.       fstp         QWORD PTR es:[di]   ; e^x  use overflow stk for temp here
  382.       fdivr        _PointFive          ; e**-x/2
  383.       pop          ax                  ; restore old CW to Arg2 after fdivr
  384.       mov          _Arg2,ax
  385.       fld          st                  ; e**-x/2, e**-x/2
  386.       fadd         QWORD PTR es:[di]   ; coshx, e**-x/2
  387.       fxch                             ; e^-x/2, coshx
  388.       fsubr        QWORD PTR es:[di]   ; sinhx, coshx
  389.       fldcw        _Arg2               ; Restore control word
  390.    END_INCL        SinhCosh
  391. ; --------------------------------------------------------------------------
  392.    BEGN_OPER       Conj                ; Complex conjugate
  393.       fxch                             ; y x ...
  394.       fchs                             ; y=-y x ...
  395.       fxch                             ; x y ...
  396.    END_OPER        Conj
  397. ; --------------------------------------------------------------------------
  398.    BEGN_OPER       Real                ; Real
  399.       fstp         st(1)               ; x ...
  400.       fldz                             ; 0 x ...
  401.       fxch                             ; x 0 ...
  402.    END_OPER        Real
  403. ; --------------------------------------------------------------------------
  404.    BEGN_OPER       RealFlip            ; Real, flip combined.
  405.       fstp         st(1)               ; y=x ...
  406.       fldz                             ; x=0 y ...
  407.    END_OPER        RealFlip
  408. ; --------------------------------------------------------------------------
  409.    BEGN_OPER       Add                 ; Add
  410.       faddp        st(2),st            ; Arg2->d.x += Arg1->d.x;
  411.       faddp        st(2),st            ; Arg2->d.y += Arg1->d.y;
  412.    END_OPER        Add
  413. ; --------------------------------------------------------------------------
  414.    BEGN_OPER       Sub                 ; Subtract
  415.       fsubp        st(2),st            ; Arg2->d.x -= Arg1->d.x;
  416.       fsubp        st(2),st            ; Arg2->d.y -= Arg1->d.y;
  417.    END_OPER        Sub
  418. ; --------------------------------------------------------------------------
  419.    BEGN_OPER       LodRealAdd          ; Load, Real, Add combined
  420.       FIXUP        LodRealAdd, fadd, X ; Add x-value from memory
  421.    END_OPER        LodRealAdd
  422. ; --------------------------------------------------------------------------
  423.    BEGN_OPER       LodRealSub          ; Load, Real, Subtract combined
  424.       FIXUP        LodRealSub, fsub, X ; (fsub qword ptr X)
  425.    END_OPER        LodRealSub
  426. ; --------------------------------------------------------------------------
  427.    BEGN_OPER       Real2               ; Real value (fast version)
  428.       fldz                             ; 0 x y ... (uses a reg)
  429.       fstp         st(2)               ; x 0 ...
  430.    END_OPER        Real2
  431. ; --------------------------------------------------------------------------
  432.    BEGN_OPER       Lod                 ; Load
  433.       FIXUP        Lod, fld, Y         ; y ...
  434.       FIXUP        Lod, fld, X         ; x y ...
  435.    END_OPER        Lod
  436. ; --------------------------------------------------------------------------
  437.    BEGN_OPER       Clr1                ; Clear stack
  438.       fninit
  439.    END_OPER        Clr1
  440. ; --------------------------------------------------------------------------
  441.    BEGN_OPER       Imag                ; Imaginary value
  442.       POP_STK      1                   ; y
  443.       fldz                             ; 0 y
  444.       fxch                             ; x=y 0
  445.    END_OPER        Imag
  446. ; --------------------------------------------------------------------------
  447.    BEGN_OPER       ImagFlip            ; Imaginary value, flip combined
  448.       POP_STK      1                   ; y ...
  449.       fldz                             ; x=0 y ...
  450.    END_OPER        ImagFlip
  451. ; --------------------------------------------------------------------------
  452.    BEGN_OPER Abs                       ; Absolute value
  453.       fxch
  454.       fabs
  455.       fxch
  456.       fabs
  457.    END_OPER Abs
  458. ; --------------------------------------------------------------------------
  459.    BEGN_OPER       LodRealMul          ; Load, Real, Multiply
  460.       FIXUP        LodRealMul, fld, X  ; y.x x.x x.y
  461.       fmul         st(2),st            ; y.x x.x z.y
  462.       fmul                             ; z.x z.y
  463.    END_OPER        LodRealMul
  464. ; --------------------------------------------------------------------------
  465.    BEGN_OPER       Neg                 ; Negative
  466.       fxch
  467.       fchs                             ; Arg1->d.y = -Arg1->d.y;
  468.       fxch
  469.       fchs
  470.    END_OPER        Neg
  471. ; --------------------------------------------------------------------------
  472.    BEGN_OPER       EndInit             ; End of initialization expr.
  473.       fninit
  474.       mov          _LastInitOp,bx      ; LastInitOp=OpPtr
  475.    END_OPER        EndInit
  476. ; --------------------------------------------------------------------------
  477.    BEGN_OPER       StoClr1             ; Store, clear FPU
  478.       FIXUP        StoClr1, fstp, X    ; y ...
  479.       FIXUP        StoClr1, fst, Y     ; y ...
  480.       finit                            ; use finit, not fninit
  481.    END_OPER        StoClr1
  482. ; --------------------------------------------------------------------------
  483.    BEGN_OPER       Sto                 ; Store, leave on ST
  484.       fxch                             ; y x ...
  485.       FIXUP        Sto, fst, Y
  486.       fxch                             ; x y ...
  487.       FIXUP        Sto, fst, X
  488.       fwait                            ; to be safe
  489.    END_OPER        Sto
  490. ; --------------------------------------------------------------------------
  491.    BEGN_OPER       Sto2                ; Store, leave on ST (uses a reg)
  492.       fld          st(1)               ; y x y
  493.       FIXUP        Sto2, fstp, Y       ; x y
  494.       FIXUP        Sto2, fst, X
  495.    ; FWAIT should not be needed here since next operator is never Clr.
  496.    END_OPER        Sto2
  497. ; --------------------------------------------------------------------------
  498.    BEGN_OPER       LodReal             ; Load a real
  499.       fldz                             ; 0 ...
  500.       FIXUP        LodReal, fld, X     ; x 0 ...
  501.    END_OPER        LodReal
  502. ; --------------------------------------------------------------------------
  503.    BEGN_OPER       LodRealC            ; Load real const
  504.       fldz                             ; y=0 ...
  505.       FIXUP        LodRealC, fld, X    ; x 0 ...
  506.    END_OPER        LodRealC
  507. ; --------------------------------------------------------------------------
  508.    BEGN_OPER       LodRealFlip         ; Load real, flip
  509.       FIXUP        LodRealFlip, fld, X ; y=x ...
  510.       fldz                             ; x=0 y ...
  511.    END_OPER        LodRealFlip
  512. ; --------------------------------------------------------------------------
  513.    BEGN_OPER       LodRealAbs          ; Load real, abs
  514.       fldz                             ; 0 ...
  515.       FIXUP        LodRealAbs, fld, X  ; x 0 ...
  516.       fabs                             ; x=abs(x) 0 ...
  517.    END_OPER        LodRealAbs
  518. ; --------------------------------------------------------------------------
  519.    BEGN_OPER       Flip                ; Exchange real, imag
  520.       fxch                             ; x=y y=x ...
  521.    END_OPER        Flip
  522. ; --------------------------------------------------------------------------
  523.    BEGN_OPER       LodImag             ; Load, imaginary
  524.       fldz                             ; 0 ...
  525.       FIXUP        LodImag, fld, Y     ; x=y 0
  526.    END_OPER        LodImag
  527. ; --------------------------------------------------------------------------
  528.    BEGN_OPER       LodImagFlip         ; Load, imaginary, flip
  529.       FIXUP        LodImagFlip, fld, Y ; y ...
  530.       fldz                             ; 0 y ...
  531.    END_OPER        LodImagFlip
  532. ; --------------------------------------------------------------------------
  533.    BEGN_OPER       LodImagAbs          ; Load, imaginary, absolute value
  534.       fldz                             ; 0 ...
  535.       FIXUP        LodImagAbs, fld, Y  ; x=y 0 ...
  536.       fabs                             ; x=abs(y) 0 ...
  537.    END_OPER        LodImagAbs
  538. ; --------------------------------------------------------------------------
  539.    BEGN_OPER       LodConj             ; Load, conjugate
  540.       FIXUP        LodConj, fld, Y     ; y ...
  541.       fchs                             ; y=-y ...
  542.       FIXUP        LodConj, fld, X     ; x y ...
  543.    END_OPER        LodConj
  544. ; --------------------------------------------------------------------------
  545.    BEGN_OPER       LodAdd              ; Load, Add (uses a reg)
  546.       FIXUP        LodAdd, fadd, X
  547.       FIXUP        LodAdd, fld, Y
  548.       faddp        st(2),st
  549.    END_OPER        LodAdd
  550. ; --------------------------------------------------------------------------
  551.    BEGN_OPER       LodSub              ; Load, Subtract (uses a reg)
  552.       FIXUP        LodSub, fsub, X
  553.       FIXUP        LodSub, fld, Y
  554.       fsubp        st(2),st
  555.    END_OPER        LodSub
  556. ; --------------------------------------------------------------------------
  557.    BEGN_OPER       StoDup              ; Store, duplicate top operand
  558.       FIXUP        StoDup, fst, X      ; x y
  559.       fld          st(1)               ; y x y
  560.       FIXUP        StoDup, fst, Y      ; y x y
  561.       fld          st(1)               ; x y x y
  562.    END_OPER        StoDup
  563. ; --------------------------------------------------------------------------
  564.    BEGN_OPER       StoDbl              ; Store, double (uses a reg)
  565.       FIXUP        StoDbl, fst, X      ; x y (store x)
  566.       fadd         st,st               ; 2x y
  567.       fld          st(1)               ; y 2x y
  568.       FIXUP        StoDbl, fst, Y      ; y 2x y (store y)
  569.       faddp        st(2),st            ; 2x 2y
  570.    END_OPER        StoDbl
  571. ; --------------------------------------------------------------------------
  572.    BEGN_OPER       LodSubMod           ; Load, Subtract, Mod
  573.       FIXUP        LodSubMod, fsub, X  ; x.x-y.x  x.y  ...
  574.       fmul         st,st               ; sqr(x.x-y.x) x.y ...
  575.       fldz                             ; 0 sqrx x.y ...
  576.       fxch         st(2)               ; x.y sqrx 0 ...
  577.       FIXUP        LodSubMod, fsub, Y  ; x.y-y.y sqrx 0 ...
  578.       fmul         st,st               ; sqry sqrx 0 ...
  579.       fadd                             ; mod 0
  580.    END_OPER        LodSubMod
  581. ; --------------------------------------------------------------------------
  582.    BEGN_OPER       Sqr                 ; Square, save magnitude in LastSqr
  583.       fld          st(0)               ; x x y
  584.       fmul         st(1),st            ; x x*x y
  585.       fmul         st,st(2)            ; xy xx y
  586.       mov          si, WORD PTR _v     ; si -> variables
  587.       fadd         st,st(0)            ; 2xy xx y
  588.       fxch         st(2)               ; y xx 2xy
  589.       fmul         st,st(0)            ; yy xx 2xy
  590.       fld          st(1)               ; xx yy xx 2xy
  591.       fadd         st,st(1)            ; xx+yy yy xx 2xy
  592.       fstp         QWORD PTR [si+LASTSQR] ; yy xx 2xy
  593.       fsubp        st(1),st            ; xx-yy 2xy
  594.    END_OPER        Sqr
  595. ; --------------------------------------------------------------------------
  596.    BEGN_OPER       Sqr0                ; Square, don't save magnitude
  597.       fld          st(0)               ; x x y
  598.       fld          st(0)               ; x x x y
  599.       fmul         st,st(3)            ; xy x x y
  600.       fadd         st,st               ; 2xy x x y
  601.       fxch         st(3)               ; y x x 2xy
  602.       fadd         st(2),st            ; y x x+y 2xy
  603.       fsubp        st(1),st            ; x-y x+y 2xy
  604.       fmulp        st(1),st            ; xx-yy 2xy
  605.    END_OPER        Sqr0
  606. ; --------------------------------------------------------------------------
  607.    BEGN_OPER       Mul                 ; Multiply
  608.    ; From FPU087.ASM
  609.       fld          st(1)               ; y.y, y.x, y.y, x.x, x.y
  610.       fmul         st,st(4)            ; y.y*x.y, y.x. y.y, x.x, x.y
  611.       fld          st(1)               ; y.x, y.y*x.y, y.x, y.y, x.x, x.y
  612.       fmul         st,st(4)            ; y.x*x.x,y.y*x.y,y.x y.y,x.x,x.y
  613.       fsubr                            ; newx=y.x*x.x-y.y*x.y,y.x,y.y,x.x,x.y
  614.       fxch         st(3)               ; x.x, y.x, y.y, newx, x.y
  615.       fmulp        st(2),st            ; y.x, y.y*x.x, newx, x.y
  616.       fmulp        st(3),st            ; y.y*x.x, newx, y.x*x.y
  617.       faddp        st(2),st            ; newx newy = y.x*x.y + x.x*y.y
  618.    END_OPER        Mul
  619. ; --------------------------------------------------------------------------
  620.    BEGN_OPER       LodMul              ; Load, Multiply
  621.    ; This is just load followed by multiply but it saves a fn. call.
  622.       FIXUP        LodMul, fld, Y      ; y.y x.x x.y
  623.       FIXUP        LodMul, fld, X      ; y.x y.y x.x x.y
  624.       fld          st(1)               ; y.y, y.x, y.y, x.x, x.y
  625.       fmul         st,st(4)            ; y.y*x.y, y.x. y.y, x.x, x.y
  626.       fld          st(1)               ; y.x, y.y*x.y, y.x, y.y, x.x, x.y
  627.       fmul         st, st(4)           ; y.x*x.x, y.y*x.y, y.x, y.y, x.x, x.y
  628.       fsubr                            ; newx=y.x*x.x-y.y*x.y,y.x,y.y,x.x,x.y
  629.       fxch         st(3)               ; x.x, y.x, y.y, newx, x.y
  630.       fmulp        st(2), st           ; y.x, y.y*x.x, newx, x.y
  631.       fmulp        st(3), st           ; y.y*x.x, newx, y.x*x.y
  632.       faddp        st(2), st           ; newx newy = y.x*x.y + x.x*y.y
  633.    END_OPER        LodMul
  634. ; --------------------------------------------------------------------------
  635.    BEGN_OPER       Div                 ; Divide
  636.    ; From FPU087.ASM with speedups
  637.       fld          st(1)               ; y.y,y.x,y.y,x.x,x.y
  638.       fmul         st,st               ; y.y*y.y,y.x,y.y,x.x,x.y
  639.       fld          st(1)               ; y.x,y.y*y.y,y.x,y.y,x.x,x.y
  640.       fmul         st,st               ; y.x*y.x,y.y*y.y,y.x,y.y,x.x,x.y
  641.       fadd                             ; mod,y.x,y.y,x.x,x.y
  642.       ftst
  643.       fstsw        ax
  644.       sahf
  645.       jz           short DivNotOk
  646.                                        ; can't do this divide until now
  647.       fdiv         st(1),st            ; mod,y.x=y.x/mod,y.y,x.x,x.y
  648.       fdivp        st(2),st            ; y.x,y.y=y.y/mod,x.x,x.y
  649.       fld          st(1)               ; y.y,y.x,y.y,x.x,x.y
  650.       fmul         st,st(4)            ; y.y*x.y,y.x,y.y,x.x,x.y
  651.       fld          st(1)               ; y.x,y.y*x.y,y.x,y.y,x.x,x.y
  652.       fmul         st,st(4)            ; y.x*x.x,y.y*x.y,y.x,y.y,x.x,x.y
  653.       fadd                             ; y.x*x.x+y.y*x.y,y.x,y.y,x.x,x.y
  654.       fxch         st(3)               ; x.x,y.x,y.y,newx,x.y
  655.       fmulp        st(2),st            ; y.x,y.y*x.x,newx,x.y
  656.       fmulp        st(3),st            ; x.x*y.y,newx,y.x*x.y
  657.       fsubp        st(2),st            ; newx,newy
  658.       EXIT_OPER    Div
  659. DivNotOk:
  660.       POP_STK      5                   ; clear 5 from stack (!)
  661.       fld          _infinity           ; return a very large number
  662.       fld          st(0)
  663.    END_OPER        Div
  664. ; --------------------------------------------------------------------------
  665.    BEGN_OPER       Recip               ; Reciprocal
  666.    ; From FPU087.ASM
  667.       fld          st(1)               ; y, x, y
  668.       fmul         st,st               ; y*y, x, y
  669.       fld          st(1)               ; x, y*y, x, y
  670.       fmul         st,st               ; x*x, y*y, x, y
  671.       fadd                             ; mod, x, y
  672.       ftst
  673.       fstsw        ax
  674.       sahf
  675.       jz           short RecipNotOk
  676.       fdiv         st(1),st            ; mod, newx=x/mod, y
  677.       fchs                             ; -mod newx y
  678.       fdivp        st(2),st            ; newx, newy=y/-mod
  679.       EXIT_OPER    Recip
  680. RecipNotOk:
  681.       POP_STK      3                   ; clear three from stack
  682.       fld          _infinity           ; return a very large number
  683.       fld          st(0)
  684.    END_OPER        Recip
  685. ; --------------------------------------------------------------------------
  686.    BEGN_OPER       StoSqr              ; Sto, Square, save magnitude
  687.       fld          st(0)               ; x x y
  688.       FIXUP        StoSqr, fst, X      ;   "   (store x)
  689.       fmul         st(1),st            ; x x*x y
  690.       fmul         st,st(2)            ; xy xx y
  691.       fadd         st,st(0)            ; 2xy xx y
  692.       fxch         st(2)               ; y xx 2xy
  693.       FIXUP        StoSqr, fst, Y      ;    "     (store y)
  694.       fmul         st,st(0)            ; yy xx 2xy
  695.    ; It is now safe to overlay si here
  696.       mov          si, WORD PTR _v     ; si -> variables
  697.       fld          st(1)               ; xx yy xx 2xy
  698.       fadd         st,st(1)            ; xx+yy yy xx 2xy
  699.       fstp         QWORD PTR [si+LASTSQR] ; yy xx 2xy
  700.       fsubp        st(1),st            ; xx-yy 2xy
  701.    END_OPER        StoSqr
  702. ; --------------------------------------------------------------------------
  703.    BEGN_OPER       StoSqr0             ; Sto, Square, don't save magnitude
  704.       fld          st(0)               ; x x y
  705.       FIXUP        StoSqr0, fst, X     ; store x
  706.       fld          st(0)               ; x x x y
  707.       fmul         st,st(3)            ; xy x x y
  708.       fadd         st,st               ; 2xy x x y
  709.       fxch         st(3)               ; y x x 2xy
  710.       FIXUP        StoSqr0, fst, Y     ; store y
  711.       fadd         st(2),st            ; y x x+y 2xy
  712.       fsubp        st(1),st            ; x-y x+y 2xy
  713.       fmulp        st(1),st            ; xx-yy 2xy
  714.    END_OPER        StoSqr0
  715. ; --------------------------------------------------------------------------
  716.    BEGN_OPER       Mod2                ; Modulus (uses a reg)
  717.       fmul         st,st               ; xx y
  718.       fldz                             ; 0 xx y
  719.       fxch         st(2)               ; y xx 0
  720.       fmul         st,st               ; yy xx 0
  721.       fadd                             ; mod 0
  722.    END_OPER        Mod2
  723. ; --------------------------------------------------------------------------
  724.    BEGN_OPER       LodMod2             ; Load, Modulus (uses a reg)
  725.       fldz                             ; 0 ...
  726.       FIXUP        LodMod2, fld, X     ; x 0 ...
  727.       fmul         st,st               ; xx 0
  728.       FIXUP        LodMod2, fld, Y     ; y xx 0
  729.       fmul         st,st               ; yy xx 0
  730.       fadd                             ; mod 0
  731.    END_OPER        LodMod2
  732. ; --------------------------------------------------------------------------
  733.    BEGN_OPER       StoMod2             ; Store, Modulus (uses a reg)
  734.       FIXUP        StoMod2, fst, X     ; x y
  735.       fmul         st,st               ; xx y
  736.       fldz                             ; 0 xx y
  737.       fxch         st(2)               ; y xx 0
  738.       FIXUP        StoMod2, fst, Y     ; y xx 0
  739.       fmul         st,st               ; yy xx 0
  740.       fadd                             ; mod 0
  741.    END_OPER        StoMod2
  742. ; --------------------------------------------------------------------------
  743.    BEGN_OPER       Clr2                ; Test ST, clear FPU
  744.       ftst
  745.       fstsw        ax
  746.       fninit
  747.       and          ah,01000000b        ; return 1 if zf=1
  748.       shr          ax,14               ; AX will be returned by fFormula()
  749.    END_OPER        Clr2
  750. ; --------------------------------------------------------------------------
  751.    BEGN_OPER       PLodAdd             ; Load, Add (uses no regs)
  752.       fxch                             ; y x
  753.       FIXUP        PLodAdd, fadd, Y    ; add y from memory
  754.       fxch                             ; x y
  755.       FIXUP        PLodAdd, fadd, X    ; add x, overlap execution
  756.    END_OPER        PLodAdd
  757. ; --------------------------------------------------------------------------
  758.    BEGN_OPER       PLodSub             ; Load, Subtract (uses no regs)
  759.       fxch
  760.       FIXUP        PLodSub, fsub, Y    ; sub y from memory
  761.       fxch                             ; x y
  762.       FIXUP        PLodSub, fsub, X    ; sub x, overlap execution
  763.    END_OPER        PLodSub
  764. ; --------------------------------------------------------------------------
  765.    BEGN_OPER       LodDup              ; Load, duplicate
  766.       FIXUP        LodDup, fld, Y      ; y ...
  767.       FIXUP        LodDup, fld, X      ; x y ...
  768.       fld          st(1)               ; y x y ...
  769.       fld          st(1)               ; x y x y ...
  770.    END_OPER        LodDup
  771. ; --------------------------------------------------------------------------
  772.    BEGN_OPER       LodSqr              ; Load, square (no save lastsqr)
  773.       FIXUP        LodSqr, fld, Y      ; y ...
  774.       fld          st(0)               ; y y ...
  775.       fadd         st(1),st            ; y 2y ...
  776.       fld          st(0)               ; y y 2y
  777.       FIXUP        LodSqr, fld, X      ; x y y 2y ...
  778.       fmul         st(3),st            ; x y y 2xy ...
  779.       fadd         st(2),st                ; x y X+y 2xy ...
  780.       fsubrp       st(1),st            ; x-y x+y 2xy ...
  781.       fmul                             ; xx-yy 2xy ...
  782.    END_OPER        LodSqr
  783. ; --------------------------------------------------------------------------
  784.    BEGN_OPER       LodSqr2             ; Load, square (save lastsqr)
  785.       FIXUP        LodSqr2, fld, Y     ; y ...
  786.       fld          st(0)               ; y y ...
  787.       fadd         st(1),st            ; y 2y ...
  788.       fmul         st,st(0)            ; yy 2y ...
  789.       FIXUP        LodSqr2, fld, X     ; x yy 2y ...
  790.       fmul         st(2),st            ; x yy 2xy ...
  791.       mov          si,WORD PTR _v      ; put address of v in si
  792.       fmul         st,st(0)            ; xx yy 2xy ...
  793.       fld          st(0)               ; xx xx yy 2xy
  794.       fadd         st,st(2)            ; mod xx yy 2xy
  795.       fstp         QWORD PTR [si+LASTSQR] ; xx yy 2xy ... (save lastsqr)
  796.       fsubrp       st(1),st            ; xx-yy 2xy ...
  797.    END_OPER        LodSqr2
  798. ; --------------------------------------------------------------------------
  799.    BEGN_OPER       LodDbl              ; Load, double
  800.       FIXUP        LodDbl, fld, Y      ; load y
  801.       fadd         st,st(0)            ; double it
  802.       FIXUP        LodDbl, fld, X      ; same for x
  803.       fadd         st,st(0)
  804.    END_OPER        LodDbl
  805. ; --------------------------------------------------------------------------
  806.    BEGN_OPER       Mod                 ; Modulus (uses no regs)
  807.       fmul         st,st               ; x*x y
  808.       fxch                             ; y x*x
  809.       fmul         st,st               ; y*y x*x
  810.       fadd                             ; mod
  811.       fldz                             ; 0 mod
  812.       fxch                             ; mod 0
  813.    END_OPER        Mod
  814. ; --------------------------------------------------------------------------
  815. ; The following code was 'discovered' by experimentation.  The Intel manuals
  816. ;   really don't help much in writing this kind of code.
  817. ; --------------------------------------------------------------------------
  818.    BEGN_OPER       Push2               ; Push stack down from 8 to 6
  819.       fdecstp                          ; roll the stack
  820.       fdecstp                          ; ...
  821.       fstp         tbyte PTR es:[di]   ; store x on overflow stack
  822.       fstp         tbyte PTR es:[di+10] ; and y (ten bytes each)
  823.       add          di,20               ; adjust di
  824.    END_OPER        Push2
  825. ; --------------------------------------------------------------------------
  826.    BEGN_OPER       Pull2               ; Pull stack up from 2 to 4
  827.       fld          tbyte PTR es:[di-10] ; oldy x y
  828.       sub          di,20               ; adjust di
  829.       fxch         st(2)               ; y x oldy
  830.       fld          tbyte PTR es:[di]   ; oldx y x oldy
  831.       fxch         st(2)               ; x y oldx oldy
  832.    END_OPER        Pull2
  833. ; --------------------------------------------------------------------------
  834.    BEGN_OPER       Push4               ; Push stack down from 8 to 4
  835.       fdecstp                          ; roll the stack four times
  836.       fdecstp
  837.       fdecstp
  838.       fdecstp
  839.       fstp         tbyte PTR es:[di+20] ; save the bottom four numbers
  840.       fstp         tbyte PTR es:[di+30] ; save full precision on overflow
  841.       fstp         tbyte PTR es:[di]
  842.       fstp         tbyte PTR es:[di+10]
  843.       add          di,40                ; adjust di
  844.    END_OPER        Push4
  845. ; --------------------------------------------------------------------------
  846.    BEGN_OPER       Push2a              ; Push stack down from 6 to 4
  847.       fdecstp                          ; roll the stack 4 times
  848.       fdecstp
  849.       fdecstp
  850.       fdecstp
  851.       fstp         tbyte PTR es:[di]   ; save only two numbers
  852.       fstp         tbyte PTR es:[di+10]
  853.       add          di, 20
  854.       fincstp                          ; roll back 2 times
  855.       fincstp
  856.    END_OPER        Push2a
  857. ; --------------------------------------------------------------------------
  858. ; End of stack overflow/underflow code.
  859. ; --------------------------------------------------------------------------
  860.    BEGN_OPER       Exp                 ; Exponent
  861.    ; From FPU387.ASM with mods to use less registers.
  862.       fstp         QWORD PTR es:[di]   ; y
  863.       fsincos                          ; cosy, siny
  864.       fld1                             ; 1, cos, sin
  865.       fldln2                           ; ln2, 1, cos, sin
  866.       fdivr        QWORD PTR es:[di]   ; x.x/ln2, 1, cos, sin
  867.       fst          QWORD PTR es:[di]
  868.       fprem                            ; prem, 1, cos, sin
  869.       f2xm1                            ; e**prem-1, 1, cos, sin
  870.       fadd                             ; e**prem, cos, sin
  871.       fld          QWORD PTR es:[di]   ; x.x/ln2, e**prem, cos, sin
  872.       fxch                             ; e**prem, x.x/ln2, cos, sin
  873.       fscale                           ; e**x.x, x.x/ln2, cos, sin
  874.       fstp         st(1)               ; e**x.x, cos, sin
  875.       fmul         st(2),st            ; e**x.x, cos, z.y
  876.       fmul                             ; z.x, z.y
  877.    END_OPER        Exp
  878. ; --------------------------------------------------------------------------
  879.    BEGN_OPER       Pwr                 ; Power
  880.    ; First exchange the top two complex numbers.
  881.       fxch         st(2)               ; x.x y.y y.x x.y
  882.       fxch                             ; y.y x.x y.x x.y
  883.       fxch         st(3)               ; x.y x.x y.x y.y
  884.       fxch                             ; x.x x.y y.x y.y
  885.    ; Now take the log of the # on st.
  886.       INCL_OPER    Pwr, Log            ; l.x l.y y.x y.y
  887.    ; Inline multiply function from FPU087.ASM instead of include.
  888.       fld          st(1)               ; y.y, y.x, y.y, x.x, x.y
  889.       fmul         st,st(4)            ; y.y*x.y, y.x. y.y, x.x, x.y
  890.       fld          st(1)               ; y.x, y.y*x.y, y.x, y.y, x.x, x.y
  891.       fmul         st,st(4)            ; y.x*x.x, y.y*x.y, y.x, y.y, x.x, x.y
  892.       fsubr                            ; newx = y.x*x.x - y.y*x.y, y.x, y.y, x.x, x.y
  893.       fxch         st(3)               ; x.x, y.x, y.y, newx, x.y
  894.       fmulp        st(2),st            ; y.x, y.y*x.x, newx, x.y
  895.       fmulp        st(3),st            ; y.y*x.x, newx, y.x*x.y
  896.       faddp        st(2),st            ; newx newy = y.x*x.y + x.x*y.y
  897.    ; Exp function from FPU387.ASM with mods to use less registers.
  898.       fstp         QWORD PTR es:[di]   ; y
  899.       fsincos                          ; cosy, siny
  900.       fld1                             ; 1, cos, sin
  901.       fldln2                           ; ln2, 1, cos, sin
  902.       fdivr        QWORD PTR es:[di]   ; x.x/ln2, 1, cos, sin
  903.       fst          QWORD PTR es:[di]
  904.       fprem                            ; prem, 1, cos, sin
  905.       f2xm1                            ; e**prem-1, 1, cos, sin
  906.       fadd                             ; e**prem, cos, sin
  907.       fld          QWORD PTR es:[di]   ; x.x/ln2, e**prem, cos, sin
  908.       fxch                             ; e**prem, x.x/ln2, cos, sin
  909.       fscale                           ; e**x.x, x.x/ln2, cos, sin
  910.       fstp         st(1)               ; e**x.x, cos, sin
  911.       fmul         st(2),st            ; e**x.x, cos, z.y
  912.       fmul                             ; z.x, z.y
  913.    END_OPER        Pwr
  914. ; --------------------------------------------------------------------------
  915.    BEGN_OPER       Cosh                ; Cosh
  916.       INCL_OPER    Cosh, SinhCosh      ; sinhx coshx y
  917.       fxch         st(2)               ; y coshx sinhx
  918.       fsincos                          ; cosy siny coshx sinhx
  919.       fxch                             ; siny cosy coshx sinhx
  920.       fmulp        st(3),st            ; cosy coshx y=sinhx*siny
  921.       fmulp        st(1),st            ; x=cosy*coshx y
  922.    END_OPER        Cosh
  923. ; --------------------------------------------------------------------------
  924.    BEGN_OPER       Sinh                ; Sinh
  925.       INCL_OPER    Sinh, SinhCosh      ; sinhx coshx y
  926.       fxch         st(2)               ; y coshx sinhx
  927.       fsincos                          ; cosy siny coshx sinhx
  928.       fmulp        st(3),st            ; siny coshx x=sinhx*cosy
  929.       fmulp        st(1),st            ; y=coshx*siny x
  930.       fxch                             ; x y
  931.    END_OPER        Sinh
  932. ; --------------------------------------------------------------------------
  933.    BEGN_OPER       Sin                 ; Sin
  934.       fsincos                          ; cosx sinx y
  935.       fxch         st(2)               ; y sinx cosx
  936.       INCL_OPER    Sin, SinhCosh       ; sinhy coshy sinx cosx
  937.       fmulp        st(3),st            ; coshy sinx y=cosx*sinhy
  938.       fmulp        st(1),st            ; x=sinx*coshy y
  939.    END_OPER        Sin
  940. ; --------------------------------------------------------------------------
  941.    BEGN_OPER       Cos                 ; Cos
  942.       fsincos                          ; cosx sinx y
  943.       fxch         st(2)               ; y sinx cosx
  944.       INCL_OPER    Cos, SinhCosh       ; sinhy coshy sinx cosx
  945.       fchs                             ; -sinhy coshy sinx cosx
  946.       fmulp        st(2),st            ; coshy y=-sinhy*sinx cosx
  947.       fmulp        st(2),st            ; y x=cosx*coshy
  948.       fxch                             ; x y
  949.    END_OPER        Cos
  950. ; --------------------------------------------------------------------------
  951.    BEGN_OPER       CosXX               ; CosXX
  952.       fsincos                          ; cosx sinx y
  953.       fxch         st(2)               ; y sinx cosx
  954.       INCL_OPER    CosXX, SinhCosh     ; sinhy coshy sinx cosx
  955.       ; note missing fchs here
  956.       fmulp        st(2),st            ; coshy y=sinhy*sinx cosx
  957.       fmulp        st(2),st            ; y x=cosx*coshy
  958.       fxch                             ; x y
  959.    END_OPER        CosXX
  960. ; --------------------------------------------------------------------------
  961.    BEGN_OPER       Tan                 ; Tan
  962.       fadd         st,st               ; 2x y
  963.       fsincos                          ; cos2x sin2x y
  964.       fxch         st(2)               ; y sin2x cos2x
  965.       fadd         st,st               ; 2y sin2x cos2x
  966.       INCL_OPER    Tan, SinhCosh       ; sinh2y cosh2y sin2x cos2x
  967.       fxch                             ; cosh2y sinh2y sin2x cos2x
  968.       faddp        st(3),st            ; sinhy sinx denom=cos2x+cosh2y
  969.       fld          st(2)               ; denom sinh2y sin2x denom
  970.       fdivp        st(2),st            ; sinh2y x=sin2x/denom denom
  971.       fdivrp       st(2),st            ; x y=sinh2y/denom
  972.    END_OPER        Tan
  973. ; --------------------------------------------------------------------------
  974.    BEGN_OPER       CoTan               ; CoTan
  975.       fadd         st,st               ; 2x y
  976.       fsincos                          ; cos2x sin2x y
  977.       fxch         st(2)               ; y sin2x cos2x
  978.       fadd         st,st               ; 2y sin2x cos2x
  979.       INCL_OPER    CoTan, SinhCosh     ; sinh2y cosh2y sin2x cos2x
  980.       fxch                             ; cosh2y sinh2y sin2x cos2x
  981.       fsubrp       st(3),st            ; sinh2y sin2x denom=cosh2y-cos2x
  982.       fld          st(2)               ; denom sinh2y sin2x denom
  983.       fdivp        st(2),st            ; sinh2y x=sin2x/denom denom
  984.       fchs                             ; -sinh2y x denom
  985.       fdivrp       st(2),st            ; x y=-sinh2y/denom
  986.    END_OPER        CoTan
  987. ; --------------------------------------------------------------------------
  988.    BEGN_OPER       Tanh                ; Tanh
  989.       fadd         st,st               ; 2x y
  990.       INCL_OPER    Tanh, SinhCosh      ; sinh2x cosh2x y
  991.       fxch         st(2)               ; y cosh2x sinh2x
  992.       fadd         st,st               ; 2y cosh2x sinh2x
  993.       fsincos                          ; cos2y sin2y cosh2x sinh2x
  994.       faddp        st(2),st            ; sin2y denom=cos2y+cosh2x sinh2x
  995.       fxch                             ; denom sin2y sinh2x
  996.       fdiv         st(1),st            ; denom y=sin2y/denom sinh2x
  997.       fdivp        st(2),st            ; y x=sinh2x/denom
  998.       fxch                             ; x y
  999.    END_OPER        Tanh
  1000. ; --------------------------------------------------------------------------
  1001.    BEGN_OPER       CoTanh              ; CoTanh
  1002.       fadd         st,st               ; 2x y
  1003.       INCL_OPER    CoTanh, SinhCosh    ; sinh2x cosh2x y
  1004.       fxch         st(2)               ; y cosh2x sinh2x
  1005.       fadd         st,st               ; 2y cosh2x sinh2x
  1006.       fsincos                          ; cos2y sin2y cosh2x sinh2x
  1007.       fsubp        st(2),st            ; sin2y denom=cosh2x-cos2y sinh2x
  1008.       fchs                             ; -sin2y denom sinh2x
  1009.       fxch                             ; denom -sin2y sinh2x
  1010.       fdiv         st(1),st            ; denom y=-sin2y/denom sinh2x
  1011.       fdivp        st(2),st            ; y x=sinh2x/denom
  1012.       fxch                             ; x y
  1013.    END_OPER CoTanh
  1014. ; --------------------------------------------------------------------------
  1015.    BEGN_OPER       LT                  ; <
  1016.    ; Arg2->d.x = (double)(Arg2->d.x < Arg1->d.x);
  1017.       fcomp        st(2)               ; y.y, x.x, x.y, comp arg1 to arg2
  1018.       fstsw        ax
  1019.       POP_STK      3
  1020.       sahf
  1021.       fldz                             ; 0 (Arg2->d.y = 0.0;)
  1022.       jbe          short LTfalse       ; jump if arg1 <= arg2
  1023.       fld1                             ; 1 0 (return arg2 < arg1)
  1024.       EXIT_OPER    LT
  1025. LTfalse:
  1026.       fldz                             ; 0 0
  1027.    END_OPER        LT
  1028. ; --------------------------------------------------------------------------
  1029.    BEGN_OPER       LT2                 ; LT, set AX, clear FPU
  1030.    ; returns !(Arg2->d.x < Arg1->d.x) in ax
  1031.       fcom         st(2)               ; compare arg1, arg2
  1032.       fstsw        ax
  1033.       fninit
  1034.       sahf
  1035.       setbe        al                  ; return (Arg1 <= Arg2) in AX
  1036.       xor          ah,ah
  1037.    END_OPER        LT2
  1038. ; --------------------------------------------------------------------------
  1039.    BEGN_OPER       LodLT               ; load, LT
  1040.    ; return (1,0) on stack if arg2 < arg1
  1041.       FIXUP        LodLT, fcomp, X     ; compare arg2 to arg1, pop st
  1042.       fstsw        ax                  ; y ...
  1043.       POP_STK      1                   ; ...
  1044.       sahf
  1045.       fldz                             ; 0 ...
  1046.       jae          short LodLTfalse    ; jump when arg2 >= arg1
  1047.       fld1                             ; 1 0 ...
  1048.       EXIT_OPER    LodLT
  1049. LodLTfalse:
  1050.       fldz                             ; 0 0 ...
  1051.    END_OPER        LodLT
  1052. ; --------------------------------------------------------------------------
  1053.    BEGN_OPER       LodLT2              ; Lod, LT, set AX, clear FPU
  1054.    ; returns !(Arg2->d.x < Arg1->d.x) in ax
  1055.       FIXUP        LodLT2, fcom, X     ; compare arg2, arg1
  1056.       fstsw        ax
  1057.       fninit                           ; clear fpu
  1058.       sahf
  1059.       setae        al                  ; set al when arg2 >= arg1
  1060.       xor          ah,ah               ; clear ah
  1061.    END_OPER        LodLT2              ; ret 0 in ax for true, 1 for false
  1062. ; --------------------------------------------------------------------------
  1063.    BEGN_OPER       LodLTMul            ; Lod, LT, Multiply (needs 4 on stack)
  1064.    ; for '<expr> * ( <expr> < <var> )'
  1065.    ; return number on stack if arg2 < arg1
  1066.       FIXUP        LodLTMul, fcomp, X  ; comp Arg2 to Arg1, pop st
  1067.       fstsw        ax                  ; save status
  1068.       POP_STK      1                   ; clear 1 from stack
  1069.       sahf
  1070.       jae          short LodLTMulfalse ; jump if arg2 >= arg1
  1071.       EXIT_OPER    LodLTMul            ; return value on st
  1072.    PARSALIGN
  1073. LodLTMulfalse:
  1074.       POP_STK      2                   ; return (0,0)
  1075.       fldz
  1076.       fldz
  1077.    END_OPER        LodLTMul
  1078. ; --------------------------------------------------------------------------
  1079.    BEGN_OPER       GT                  ; >
  1080.    ; Arg2->d.x = (double)(Arg2->d.x > Arg1->d.x);
  1081.       fcomp        st(2)               ; compare arg1, arg2
  1082.       fstsw        ax
  1083.       POP_STK      3
  1084.       sahf
  1085.       fldz                             ; 0 (Arg2->d.y = 0.0;)
  1086.       jae          short GTfalse       ; jump if Arg1 >= Arg2
  1087.       fld1                             ; 1 0, return arg2 > arg1
  1088.       EXIT_OPER    GT
  1089. GTfalse:
  1090.       fldz                             ; 0 0
  1091.    END_OPER        GT
  1092. ; --------------------------------------------------------------------------
  1093.    BEGN_OPER       GT2                 ; GT, set AX, clear FPU
  1094.    ; returns !(Arg2->d.x > Arg1->d.x) in ax
  1095.       fcom         st(2)               ; compare arg1, arg2
  1096.       fstsw        ax
  1097.       fninit
  1098.       sahf
  1099.       setae        al                  ; return (Arg1 >= Arg2) in AX
  1100.       xor          ah,ah
  1101.    END_OPER        GT2
  1102. ; --------------------------------------------------------------------------
  1103.    BEGN_OPER       LodGT               ; load, GT
  1104.    ; return (1,0) on stack if arg2 > arg1
  1105.       FIXUP        LodGT, fcomp, X     ; compare arg2 to arg1, pop st
  1106.       fstsw        ax                  ; y ...
  1107.       POP_STK      1                   ; ...
  1108.       sahf
  1109.       fldz                             ; 0 ...
  1110.       jbe          short LodGTfalse    ; jump when arg2 <= arg1
  1111.       fld1                             ; 1 0 ...
  1112.       EXIT_OPER    LodGT
  1113. LodGTfalse:
  1114.       fldz                             ; 0 0 ...
  1115.    END_OPER        LodGT
  1116. ; --------------------------------------------------------------------------
  1117.    BEGN_OPER       LodGT2              ; Lod, GT, set AX, clear FPU
  1118.    ; returns !(Arg2->d.x > Arg1->d.x) in AX
  1119.       FIXUP        LodGT2, fcom, X     ; compare arg2, arg1
  1120.       fstsw        ax
  1121.       fninit                           ; clear fpu
  1122.       sahf
  1123.       setbe        al                  ; set al when arg2 <= arg1
  1124.       xor          ah,ah               ; clear ah
  1125.    END_OPER        LodGT2              ; ret 0 in ax for true, 1 for false
  1126. ; --------------------------------------------------------------------------
  1127.    BEGN_OPER       LTE                 ; <=
  1128.    ; Arg2->d.x = (double)(Arg2->d.x <= Arg1->d.x);
  1129.       fcomp        st(2)               ; y x y, comp Arg1 to Arg2
  1130.       fstsw        ax                  ; save status now
  1131.       POP_STK      3
  1132.       fldz                             ; 0 (Arg2->d.y = 0.0;)
  1133.       sahf
  1134.       jb           short LTEfalse      ; jump if arg1 > arg2
  1135.       fld1                             ; 1 0, ret arg2 <= arg1
  1136.       EXIT_OPER    LTE
  1137. LTEfalse:
  1138.       fldz                             ; 0 0
  1139.    END_OPER        LTE
  1140. ; --------------------------------------------------------------------------
  1141.    BEGN_OPER       LTE2                ; LTE, test ST, clear
  1142.    ; return !(Arg2->d.x <= Arg1->d.x) in AX
  1143.       fcom         st(2)               ; comp Arg1 to Arg2
  1144.       fstsw        ax
  1145.       fninit                           ; clear stack
  1146.       and          ah,1                ; mask cf
  1147.       shr          ax,8                ; ax=1 when arg1 < arg1
  1148.    END_OPER        LTE2                ; return (Arg1 < Arg2),
  1149. ; --------------------------------------------------------------------------
  1150.    BEGN_OPER       LodLTE              ; load, LTE
  1151.    ; return (1,0) on stack if arg2 <= arg1
  1152.       FIXUP        LodLTE, fcomp, X    ; compare arg2 to arg1, pop st
  1153.       fstsw        ax                  ; y ...
  1154.       POP_STK      1                   ; ...
  1155.       sahf
  1156.       fldz                             ; 0 ...
  1157.       ja           short LodLTEfalse   ; jump when arg2 > arg1
  1158.       fld1                             ; 1 0 ...
  1159.       EXIT_OPER    LodLTE
  1160. LodLTEfalse:
  1161.       fldz                             ; 0 0 ...
  1162.    END_OPER        LodLTE
  1163. ; --------------------------------------------------------------------------
  1164.    BEGN_OPER       LodLTE2             ; Load, LTE, test ST, clear
  1165.    ; return !(Arg2->d.x <= Arg1->d.x) in AX
  1166.       FIXUP        LodLTE2, fcom, X    ; comp Arg2 to Arg1
  1167.       fstsw        ax
  1168.       fninit
  1169.       sahf
  1170.       seta         al
  1171.       xor          ah,ah               ; ax=1 for expr. false
  1172.    END_OPER        LodLTE2             ; return (Arg2 > Arg1)
  1173. ; --------------------------------------------------------------------------
  1174.    BEGN_OPER       LodLTEMul           ; Lod, LTE, Multiply (needs 4 on stack)
  1175.    ; for '<expr> * ( <expr> <= <var> )'
  1176.    ; return number on stack if arg2 <= arg1
  1177.       FIXUP        LodLTEMul, fcomp, X ; comp Arg2 to Arg1, pop st
  1178.       fstsw        ax                  ; save status
  1179.       POP_STK      1                   ; clear 1 from stack
  1180.       sahf
  1181.       ja           short LodLTEMulfalse ; jump if arg2 > arg1
  1182.       EXIT_OPER    LodLTEMul           ; return value on st
  1183.    PARSALIGN
  1184. LodLTEMulfalse:
  1185.       POP_STK      2                   ; return (0,0)
  1186.       fldz
  1187.       fldz
  1188.    END_OPER        LodLTEMul
  1189. ; --------------------------------------------------------------------------
  1190.    BEGN_OPER       LodLTEAnd2          ; Load, LTE, AND, test ST, clear
  1191.    ; this is for 'expression && (expression <= value)'
  1192.    ; stack has {arg2.x arg2.y logical.x junk} on entry (arg1 in memory)
  1193.    ; Arg2->d.x = (double)(Arg2->d.x <= Arg1->d.x);
  1194.       FIXUP        LodLTEAnd2, fcom, X ; comp Arg2 to Arg1
  1195.       fstsw        ax
  1196.       sahf
  1197.       fxch         st(2)               ; logical.x arg2.y arg2.x junk ...
  1198.       ja           LTEA2RFalse         ; right side is false, Arg2 > Arg1
  1199.       ftst                             ; now see if left side of expr is true
  1200.       fstsw        ax
  1201.       sahf
  1202.       fninit                           ; clear fpu
  1203.       jz           LTEA2LFalse         ; jump if left side of && is false
  1204.       xor          ax,ax               ; return zero in ax for expr true
  1205.       EXIT_OPER    LodLTEAnd2
  1206. LTEA2RFalse:
  1207.       fninit
  1208. LTEA2LFalse:
  1209.       mov          ax,1                ; return ax=1 for condition false
  1210.    END_OPER        LodLTEAnd2
  1211. ; --------------------------------------------------------------------------
  1212.    BEGN_OPER       GTE                 ; >=
  1213.    ; Arg2->d.x = (double)(Arg2->d.x >= Arg1->d.x);
  1214.       fcomp        st(2)               ; y x y (compare arg1,arg2)
  1215.       fstsw        ax
  1216.       POP_STK      3                   ; clear 3 from stk
  1217.       sahf
  1218.       fldz                             ; 0 (Arg2->d.y = 0.0;)
  1219.       ja           short GTEfalse      ; jmp if arg1 > arg2
  1220.       fld1                             ; 1 0 (return arg2 >= arg1 on stack)
  1221.       EXIT_OPER    GTE
  1222. GTEfalse:
  1223.       fldz                             ; 0 0
  1224.    END_OPER        GTE
  1225. ; --------------------------------------------------------------------------
  1226.    BEGN_OPER       LodGTE              ; load, GTE
  1227.    ; return (1,0) on stack if arg2 >= arg1
  1228.       FIXUP        LodGTE, fcomp, X    ; compare arg2 to arg1, pop st
  1229.       fstsw        ax                  ; y ...
  1230.       POP_STK      1                   ; ...
  1231.       fldz                             ; 0 ...
  1232.       sahf
  1233.       jb           short LodGTEfalse   ; jump when arg2 < arg1
  1234.       fld1                             ; 1 0 ...
  1235.       EXIT_OPER    LodGTE
  1236. LodGTEfalse:
  1237.       fldz                             ; 0 0 ...
  1238.    END_OPER        LodGTE
  1239. ; --------------------------------------------------------------------------
  1240.    BEGN_OPER       LodGTE2             ; Lod, GTE, set AX, clear FPU
  1241.    ; return !(Arg2->d.x >= Arg1->d.x) in AX
  1242.       FIXUP        LodGTE2, fcom, X    ; compare arg2, arg1
  1243.       fstsw        ax
  1244.       fninit                           ; clear fpu
  1245.       and          ah,1                ; mask cf
  1246.       shr          ax,8                ; shift it (AX = 1 when arg2 < arg1)
  1247.    END_OPER        LodGTE2             ; ret 0 in ax for true, 1 for false
  1248. ; --------------------------------------------------------------------------
  1249.    BEGN_OPER       EQ                  ; ==
  1250.    ; Arg2->d.x = (double)(Arg2->d.x == Arg1->d.x);
  1251.       fcomp        st(2)               ; compare arg1, arg2
  1252.       fstsw        ax
  1253.       POP_STK      3
  1254.       sahf
  1255.       fldz                             ; 0 (Arg2->d.y = 0.0;)
  1256.       jne          short EQfalse       ; jmp if arg1 != arg2
  1257.       fld1                             ; 1 0 (ret arg2 == arg1)
  1258.       EXIT_OPER    EQ
  1259. EQfalse:
  1260.       fldz
  1261.    END_OPER        EQ
  1262. ; --------------------------------------------------------------------------
  1263.    BEGN_OPER       LodEQ               ; load, EQ
  1264.    ; return (1,0) on stack if arg2 == arg1
  1265.       FIXUP        LodEQ, fcomp, X     ; compare arg2 to arg1, pop st
  1266.       fstsw        ax                  ; y ...
  1267.       POP_STK      1                   ; ...
  1268.       fldz                             ; 0 ...
  1269.       sahf
  1270.       jne          short LodEQfalse    ; jump when arg2 != arg1
  1271.       fld1                             ; 1 0 ... (return arg2 == arg1)
  1272.       EXIT_OPER    LodEQ
  1273. LodEQfalse:
  1274.       fldz                             ; 0 0 ...
  1275.    END_OPER        LodEQ
  1276. ; --------------------------------------------------------------------------
  1277.    BEGN_OPER       NE                  ; !=
  1278.    ; Arg2->d.x = (double)(Arg2->d.x != Arg1->d.x);
  1279.       fcomp        st(2)               ; compare arg1,arg2
  1280.       fstsw        ax
  1281.       POP_STK      3
  1282.       sahf
  1283.       fldz
  1284.       je           short NEfalse       ; jmp if arg1 == arg2
  1285.       fld1                             ; ret arg2 != arg1
  1286.       EXIT_OPER    NE
  1287. NEfalse:
  1288.       fldz
  1289.    END_OPER        NE
  1290. ; --------------------------------------------------------------------------
  1291.    BEGN_OPER       LodNE               ; load, NE
  1292.    ; return (1,0) on stack if arg2 != arg1
  1293.       FIXUP        LodNE, fcomp, X     ; compare arg2 to arg1, pop st
  1294.       fstsw        ax                  ; y ...
  1295.       POP_STK      1                   ; ...
  1296.       fldz                             ; 0 ...
  1297.       sahf
  1298.       je           short LodNEfalse    ; jump when arg2 == arg1
  1299.    ; CAE changed above 'jne' to 'je' 9 MAR 1993
  1300.       fld1                             ; 1 0 ...
  1301.       EXIT_OPER    LodNE
  1302. LodNEfalse:
  1303.       fldz                             ; 0 0 ...
  1304.    END_OPER        LodNE
  1305. ; --------------------------------------------------------------------------
  1306.    BEGN_OPER       OR                  ; Or
  1307.    ; Arg2->d.x = (double)(Arg2->d.x || Arg1->d.x);
  1308.       ftst                             ; a1.x a1.y a2.x a2.y ...
  1309.       fstsw        ax
  1310.       sahf
  1311.       POP_STK      2                   ; a2.x a2.y ...
  1312.       jnz          short Arg1True
  1313.       ftst
  1314.       fstsw        ax
  1315.       sahf
  1316.       POP_STK      2                   ; ...
  1317.       fldz                             ; 0 ...
  1318.       jz           short NoneTrue
  1319.       fld1                             ; 1 0 ...
  1320.       EXIT_OPER    OR
  1321.    PARSALIGN
  1322. Arg1True:
  1323.       POP_STK      2                   ; ...
  1324.       fldz                             ; 0 ...
  1325.       fld1                             ; 1 0 ...
  1326.       EXIT_OPER    OR
  1327. NoneTrue:                              ; 0 ...
  1328.       fldz                             ; 0 0 ...
  1329.    END_OPER        OR
  1330. ; --------------------------------------------------------------------------
  1331.    BEGN_OPER       AND                 ; And
  1332.    ; Arg2->d.x = (double)(Arg2->d.x && Arg1->d.x);
  1333.       ftst                             ; a1.x a1.y a2.x a2.y ...
  1334.       fstsw        ax
  1335.       sahf
  1336.       POP_STK      2                   ; a2.x a2.y ...
  1337.       jz           short Arg1False
  1338.       ftst
  1339.       fstsw        ax
  1340.       sahf
  1341.       POP_STK      2                   ; ...
  1342.       fldz                             ; 0 ...
  1343.       jz           short Arg2False
  1344.       fld1                             ; 1 0 ...
  1345.       EXIT_OPER    AND
  1346. Arg1False:
  1347.       POP_STK      2                   ; ...
  1348.       fldz                             ; 0 ...
  1349. Arg2False:
  1350.       fldz                             ; 0 0 ...
  1351.    END_OPER        AND
  1352. ; --------------------------------------------------------------------------
  1353.    BEGN_OPER       ANDClr2           ; And, test ST, clear FPU
  1354.    ; for bailouts using <condition> && <condition>
  1355.    ;  Arg2->d.x = (double)(Arg2->d.x && Arg1->d.x);
  1356.    ;  Returns !(Arg1 && Arg2) in ax
  1357.       ftst                             ; y.x y.y x.x x.y
  1358.       fstsw        ax
  1359.       sahf
  1360.       jz           short Arg1False2
  1361.       fxch         st(2)               ; x.x y.y y.x x.y
  1362.       ftst
  1363.       fstsw        ax
  1364.       sahf
  1365.       fninit
  1366.       jz           short Arg2False2
  1367. BothTrue2:
  1368.       xor          ax,ax
  1369.       EXIT_OPER    ANDClr2
  1370. Arg1False2:
  1371.       fninit
  1372. Arg2False2:
  1373.       mov           ax, 1
  1374.    END_OPER        ANDClr2
  1375.  
  1376. ; --------------------------------------------------------------------------
  1377.    assume          ds:DGROUP, es:nothing
  1378. ; called once per image
  1379.    public          _Img_Setup
  1380.    align           4
  1381. _Img_Setup         proc near
  1382.       les          si,_pfls            ; es:si = &pfls[0]
  1383.       mov          di,_LastOp          ; load index of lastop
  1384.       shl          di,2                ; convert to offset
  1385.       mov          bx,offset DGROUP:_fLastOp ; set bx for store
  1386.       add          di,si               ; di = offset lastop
  1387.       mov          WORD PTR [bx],di    ; save value of flastop
  1388.       mov          ax,es               ; es has segment value
  1389.       mov          WORD PTR [bx+2],ax  ; save seg for easy reload
  1390.       mov          ax,word ptr _v      ; build a ptr to Z
  1391.       add          ax,3*CARG+CPFX
  1392.       mov          _PtrToZ,ax          ; and save it
  1393.       ret
  1394. _Img_Setup         endp
  1395. ; --------------------------------------------------------------------------
  1396. ;    orbitcalc function follows
  1397. ; --------------------------------------------------------------------------
  1398.    public          _fFormula
  1399.    align           16
  1400. _fFormula          proc far
  1401.       push         di                  ; don't build a frame here
  1402.       mov          di,offset DGROUP:_s ; reset this for stk overflow area
  1403.       mov          bx,_InitOpPtr       ; bx -> one before first token
  1404.       mov          ax,ds               ; save ds in ax
  1405.       lds          cx,_fLastOp         ; ds:cx -> one past last token
  1406.       mov          es,ax
  1407.    assume          es:DGROUP, ds:nothing ; swap es, ds before any fn. calls
  1408.       push         si
  1409. inner_loop:
  1410.       add          bx,4                ; point to next pointer pair
  1411.       cmp          bx,cx               ; time to quit yet?
  1412.       jae          short past_loop
  1413.       mov          si,WORD PTR [bx+2]  ; set si to operand pointer
  1414.       push         offset PARSERFP_TEXT:inner_loop
  1415.       jmp          WORD PTR [bx]       ; jmp to operator fn
  1416. past_loop:
  1417.    ; NOTE: AX is set by the last operator fn that was called.
  1418.       mov          si,_PtrToZ          ; ds:si -> z
  1419.       mov          di,offset DGROUP:_new ; es:di -> new
  1420.       mov          cx,4
  1421.       rep          movsd               ; new = z
  1422.       mov          bx,es
  1423.       pop          si
  1424.       pop          di                  ; restore si, di
  1425.       mov          ds,bx               ; restore ds before return
  1426.    assume          ds:DGROUP, es:nothing
  1427.       ret                              ; return AX unmodified
  1428. _fFormula          endp
  1429. ; --------------------------------------------------------------------------
  1430.    public          _fform_per_pixel    ; called once per pixel
  1431.    align           4
  1432. _fform_per_pixel   proc far
  1433.       FRAME        <si, di>
  1434.    ; if(!Transparent3D){
  1435.       cmp          _Transparent3D,0
  1436.       jne           abNormal_Pixel
  1437.    ;   /* v[5].a.d.x = */ (v[0].a.d.x = dx0[col]+dShiftx);
  1438.       mov          ax,_col
  1439.       shl          ax,3
  1440.       les          bx,_dx0
  1441.       add          bx,ax
  1442.       fld          QWORD PTR es:[bx]
  1443.       mov          ax,_row
  1444.       shl          ax,3
  1445.       les          bx,_dx1
  1446.       add          bx,ax
  1447.       fadd         QWORD PTR es:[bx]
  1448.       les          bx,_v
  1449.       fstp         QWORD PTR es:[bx+CPFX]
  1450.    ;;;;;;;;;fstp    QWORD PTR es:[bx+104]  kill this & prev=fstp
  1451.    ;   /* v[5].a.d.x = */ (v[0].a.d.y = dy0[row]+dShifty);
  1452.       mov          ax,_row
  1453.       shl          ax,3
  1454.       les          bx,_dy0
  1455.       add          bx,ax
  1456.       fld          QWORD PTR es:[bx]
  1457.       mov          ax,_col
  1458.       shl          ax,3
  1459.       les          bx,_dy1
  1460.       add          bx,ax
  1461.       fadd         QWORD PTR es:[bx]
  1462.       les          bx,_v
  1463.       fstp         QWORD PTR es:[bx+CPFX+8] ; make this an fstp
  1464.    ;;;;;;;;;fstp    QWORD PTR es:[bx+104]    ; kill this
  1465. after_load:
  1466.       mov          di,offset DGROUP:_s ; di points to stack overflow area
  1467.       mov          ax,ds
  1468.       mov          bx,WORD PTR _pfls   ; bx -> pfls
  1469.       lds          cx,_fLastOp         ; cx = offset &f[LastOp],load ds
  1470.       mov          es,ax
  1471.    assume          es:DGROUP, ds:nothing
  1472.       cmp          _LastInitOp,0
  1473.       je           short skip_initloop ; no operators to do here
  1474.       mov          _LastInitOp,cx      ; lastinitop=lastop
  1475.    align           4
  1476. pixel_loop:
  1477.       mov          si,WORD PTR [bx+2]  ; get address of load or store
  1478.       call         WORD PTR [bx]       ; (*opptr)()
  1479.       add          bx,4                ; ++opptr
  1480.       cmp          bx,_LastInitOp
  1481.       jb           short pixel_loop
  1482. skip_initloop:
  1483.       mov          ax,es
  1484.       mov          ds,ax
  1485.    assume          ds:DGROUP, es:nothing ; for the rest of the program
  1486.       sub          bx,4                ; make initopptr point 1 token b4 1st
  1487.       mov          _InitOpPtr, bx      ; InitOptPtr = OpPtr;
  1488.       UNFRAME      <di, si>
  1489.       xor          ax,ax
  1490.       ret
  1491.  
  1492. abNormal_Pixel:
  1493.    ;   TranspPerPixel(MathType, &v[5].a, &v[6].a);
  1494.       mov          ax,WORD PTR _v
  1495.       add          ax,6*CARG+CPFX      ;v[6].a
  1496.       push         WORD PTR _v+2
  1497.       push         ax
  1498.       mov          ax,WORD PTR _v
  1499.       add          ax,5*CARG+CPFX      ;v[5].a
  1500.       push         WORD PTR _v+2
  1501.       push         ax
  1502.       push         1                   ;_MathType
  1503.       call         far PTR _TranspPerPixel
  1504.       add          sp,10
  1505.    ;   v[0].a = v[5].a;
  1506.       les          bx,_v
  1507.       fld          QWORD PTR es:[bx+5*CARG+CPFX]
  1508.       fstp         QWORD PTR es:[bx+CPFX]
  1509.       fld          QWORD PTR es:[bx+5*CARG+CPFX+8]
  1510.       fstp         QWORD PTR es:[bx+CPFX+8]
  1511.    ; }
  1512.       jmp          short after_load
  1513. _fform_per_pixel   endp
  1514. ; --------------------------------------------------------------------------
  1515. PARSERFP_TEXT      ends
  1516.    end
  1517.  
  1518.