home *** CD-ROM | disk | FTP | other *** search
- /* PARSERFP.C -- Part of FRACTINT fractal drawer. */
-
- /* By Chuck Ebbert CompuServe [76306,1226] */
- /* internet: 76306.1226@compuserve.com */
-
- /* Fast floating-point parser code. The functions beginning with */
- /* "fStk" are in PARSERA.ASM. PARSER.C calls this code after */
- /* it has parsed the formula. */
-
- /* Converts the function pointers/load pointers/store pointers */
- /* built by parsestr() into an optimized array of function */
- /* pointer/operand pointer pairs. */
-
- /* As of 31 Dec 93, also generates executable code in memory. */
- /* Define the varible COMPILER to generate executable code. */
- /* COMPILER must also be defined in PARSERA.ASM. */
-
-
- /* Revision history: */
-
- /* 15 Feb 1995 CAE */
- /* added safety tests to pointer conversion code */
- /* added the capability for functions to require 4 free regs */
-
- /* 8 Feb 1995 CAE */
- /* Comments changed. */
-
- /* 8 Jan 1995 JCO */
- /* Function fStkASin added to support new 'asin' function in v19 */
- /* Function fStkASinh added to support new 'asinh' function in v19 */
- /* Function fStkACos added to support new 'acos' function in v19 */
- /* Function fStkACosh added to support new 'acosh' function in v19 */
- /* Function fStkATan added to support new 'atan' function in v19 */
- /* Function fStkATanh added to support new 'atanh' function in v19 */
- /* Function fStkSqrt added to support new 'sqrt' function in v19 */
- /* Function fStkCAbs added to support new 'cabs' function in v19 */
- /* Added support for a third parameter p3 */
-
- /* 31 Dec 1993 CAE */
- /* Fixed optimizer bug discovered while testing compiler. */
-
- /* 29 Dec 1993 CAE */
- /* Added compiler. */
-
- /* 04 Dec 1993 CAE */
- /* Added optimizations for LodImagAdd/Sub/Mul. */
-
- /* 06 Nov 1993 CAE */
- /* Added optimizer support for LodRealPwr and ORClr2 functions. */
- /* If stack top is a real, a simpler sqr() or mod() fn will be */
- /* called (fStkSqr3() was added.) */
- /* The identities x^0=1, x^1=x, and x^-1=recip(x) are now used by the */
- /* optimizer. (fStkOne() was added for this.) */
-
- /* 31 Oct 1993 CAE */
- /* Optimizer converts '2*x' and 'x*2' to 'x+x'. */
- /* " recognizes LastSqr as a real if not stored to. */
-
- /* 9 Oct 1993 CAE */
- /* Functions are now converted via table search. */
- /* Added "real" stack count variable and debug msgs for stack size. */
- /* Added optimizer extension for commutative multiply. */
- /* P1, P2 will be treated as consts if they are never stored to. */
- /* Function fStkStoClr2 now emitted for sto,clr with 2 on stack. */
- /* " fStkZero added to support new 'zero' function in v18 */
- /* Added optimization for x^2 -> sqr(x). */
- /* Changed "stopmsg" to "DBUGMSG" and made all macros upper case. */
- /* (debugflag=324 now needed for debug msgs to print.) */
-
- /* 12 July 1993 (for v18.1) by CAE to fix optimizer bug */
-
- /* 22 MAR 1993 (for Fractint v18.0) */
-
- /* ******************************************************************* */
- /* */
- /* (c) Copyright 1992-1995 Chuck Ebbert. All rights reserved. */
- /* */
- /* 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. */
- /* */
- /* ******************************************************************* */
-
- /* Uncomment the next line to enable debug messages. */
- /* --#define TESTFP 1 */
-
- /* Use startup parameter "debugflag=324" to show debug messages after */
- /* compiling with above #define uncommented. */
-
- /* uncomment this to gen for compiler (IT WORKS!!!) */
- /*#define COMPILER 1 */
-
- #include <string.h>
- #include <ctype.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <float.h>
- #include <time.h>
- #ifndef XFRACT
- #include <dos.h>
- #endif
- #include "fractint.h"
- #include "mpmath.h"
- #include "prototyp.h"
-
- /* global data */
- struct fls far *pfls = (struct fls far *)0;
-
- #ifndef XFRACT /* -- */
-
- /* not moved to PROTOTYPE.H because these only communicate within
- PARSER.C and other parser modules */
-
- extern union Arg *Arg1, *Arg2;
- extern double _1_, _2_;
- extern union Arg s[20], far * far *Store, far * far *Load;
- extern int StoPtr, LodPtr, OpPtr;
- extern unsigned vsp, LastOp;
- extern struct ConstArg far *v;
- extern int InitLodPtr, InitStoPtr, InitOpPtr, LastInitOp;
- extern void (far * far *f)(void);
- extern char far compiled_fn_1[];
- extern char far compiled_fn_2[];
-
- int fFormula(void);
-
- typedef void OLD_FN(void); /* old C functions */
-
- OLD_FN StkLod, StkClr, StkSto, EndInit;
- OLD_FN dStkAdd, dStkSub, dStkMul, dStkDiv;
- OLD_FN dStkSqr, dStkMod;
- OLD_FN dStkSin, dStkCos, dStkSinh, dStkCosh, dStkCosXX;
- OLD_FN dStkTan, dStkTanh, dStkCoTan, dStkCoTanh;
- OLD_FN dStkLog, dStkExp, dStkPwr;
- OLD_FN dStkLT, dStkLTE;
- OLD_FN dStkFlip, dStkReal, dStkImag;
- OLD_FN dStkConj, dStkNeg, dStkAbs;
- OLD_FN dStkRecip, StkIdent;
- OLD_FN dStkGT, dStkGTE, dStkNE, dStkEQ;
- OLD_FN dStkAND, dStkOR;
- OLD_FN dStkZero;
- OLD_FN dStkSqrt;
- OLD_FN dStkASin, dStkACos, dStkASinh, dStkACosh;
- OLD_FN dStkATanh, dStkATan;
- OLD_FN dStkCAbs;
-
- typedef void (near NEW_FN)(void); /* new 387-only ASM functions */
-
- NEW_FN fStkPull2; /* pull up fpu stack from 2 to 4 */
- NEW_FN fStkPush2; /* push down fpu stack from 8 to 6 */
- NEW_FN fStkPush2a; /* push down fpu stack from 6 to 4 */
- NEW_FN fStkPush4; /* push down fpu stack from 8 to 4 */
- NEW_FN fStkLodDup; /* lod, dup */
- NEW_FN fStkLodSqr; /* lod, sqr, dont save magnitude(i.e. lastsqr) */
- NEW_FN fStkLodSqr2; /* lod, sqr, save lastsqr */
- NEW_FN fStkStoDup; /* store, duplicate */
- NEW_FN fStkStoSqr; /* store, sqr, save lastsqr */
- NEW_FN fStkStoSqr0; /* store, sqr, dont save lastsqr */
- NEW_FN fStkLodDbl; /* load, double */
- NEW_FN fStkStoDbl; /* store, double */
- NEW_FN fStkReal2; /* fast ver. of real */
- NEW_FN fStkSqr; /* sqr, save magnitude in lastsqr */
- NEW_FN fStkSqr0; /* sqr, no save magnitude */
- NEW_FN fStkClr1; /* clear fpu */
- NEW_FN fStkClr2; /* test stack top, clear fpu */
- NEW_FN fStkStoClr1; /* store, clr1 */
- NEW_FN fStkAdd, fStkSub;
- NEW_FN fStkSto, fStkSto2; /* fast ver. of sto */
- NEW_FN fStkLod, fStkEndInit;
- NEW_FN fStkMod, fStkMod2; /* faster mod */
- NEW_FN fStkLodMod2, fStkStoMod2;
- NEW_FN fStkLTE, fStkLodLTEMul, fStkLTE2, fStkLodLTE;
- NEW_FN fStkLodLTE2, fStkLodLTEAnd2;
- NEW_FN fStkLT, fStkLodLTMul, fStkLT2, fStkLodLT;
- NEW_FN fStkLodLT2;
- NEW_FN fStkGTE, fStkLodGTE, fStkLodGTE2;
- NEW_FN fStkGT, fStkGT2, fStkLodGT, fStkLodGT2;
- NEW_FN fStkEQ, fStkLodEQ, fStkNE, fStkLodNE;
- NEW_FN fStkAND, fStkANDClr2, fStkOR, fStkORClr2;
- NEW_FN fStkSin, fStkSinh, fStkCos, fStkCosh, fStkCosXX;
- NEW_FN fStkTan, fStkTanh, fStkCoTan, fStkCoTanh;
- NEW_FN fStkLog, fStkExp, fStkPwr;
- NEW_FN fStkMul, fStkDiv;
- NEW_FN fStkFlip, fStkReal, fStkImag, fStkRealFlip, fStkImagFlip;
- NEW_FN fStkConj, fStkNeg, fStkAbs, fStkRecip;
- NEW_FN fStkLodReal, fStkLodRealC, fStkLodImag;
- NEW_FN fStkLodRealFlip, fStkLodRealAbs;
- NEW_FN fStkLodRealMul, fStkLodRealAdd, fStkLodRealSub, fStkLodRealPwr;
- NEW_FN fStkLodImagMul, fStkLodImagAdd, fStkLodImagSub; /* CAE 4Dec93 */
- NEW_FN fStkLodImagFlip, fStkLodImagAbs;
- NEW_FN fStkLodConj;
- NEW_FN fStkLodAdd, fStkLodSub, fStkLodSubMod, fStkLodMul;
- NEW_FN fStkPLodAdd, fStkPLodSub; /* push-lod-add/sub */
- NEW_FN fStkIdent;
- NEW_FN fStkStoClr2; /* store, clear stack by popping */
- NEW_FN fStkZero; /* to support new parser fn. */
- NEW_FN fStkDbl; /* double the stack top CAE 31OCT93 */
- NEW_FN fStkOne, fStkSqr3; /* sqr3 is sqr/mag of a real CAE 09NOV93 */
- NEW_FN fStkSqrt;
- NEW_FN fStkASin, fStkACos, fStkASinh, fStkACosh;
- NEW_FN fStkATanh, fStkATan;
- NEW_FN fStkCAbs;
-
- /* check to see if a const is being loaded */
- /* the really awful hack below gets the first char of the name */
- /* of the variable being accessed */
- /* if first char not alpha, or const p1, p2, or p3 are being accessed */
- /* then this is a const. */
- #define IS_CONST(x) \
- (!isalpha(**(((char * far *)x ) - 2 ) ) \
- || (x==&PARM1 && p1const ) \
- || (x==&PARM2 && p2const ) \
- || (x==&PARM3 && p3const ) )
-
- /* is stack top a real? */
- #define STACK_TOP_IS_REAL \
- ( prevfptr == fStkReal || prevfptr == fStkReal2 \
- || prevfptr == fStkLodReal || prevfptr == fStkLodRealC \
- || prevfptr == fStkLodRealAbs \
- || prevfptr == fStkImag || prevfptr == fStkLodImag )
-
- /* remove push operator from stack top */
- #define REMOVE_PUSH --cvtptrx, stkcnt+=2
-
- #define CLEAR_STK 127
- #define FNPTR(x) pfls[(x)].function /* function pointer */
- #define OPPTR(x) pfls[(x)].operand /* operand pointer */
- #define NO_OPERAND (union Arg near *)0
- #define NO_FUNCTION (void (near *)(void))0
- #define LASTSQR v[4].a
- #define PARM1 v[1].a
- #define PARM2 v[2].a
- #define PARM3 v[8].a
- #define MAX_ARGS 100 /* maximum memory variables */
- #define MAX_STACK 8 /* max # of stack register avail */
-
- #ifdef TESTFP
-
- #define DBUGMSG(x,y) if (debugflag==324 ) stopmsg((x), (y) )
- #define DBUGMSG1(x,y,p) \
- if (debugflag==324 ){ \
- sprintf(cDbgMsg, (y), (p) ); \
- stopmsg((x), cDbgMsg ); \
- }
- #define DBUGMSG2(x,y,p,q) \
- if (debugflag==324 ){ \
- sprintf(cDbgMsg, (y), (p), (q) ); \
- stopmsg((x), cDbgMsg ); \
- }
- #define DBUGMSG3(x,y,p,q,r) \
- if (debugflag==324 ){ \
- sprintf(cDbgMsg, (y), (p), (q), (r) ); \
- stopmsg((x), cDbgMsg ); \
- }
- #define DBUGMSG4(x,y,p,q,r,s) \
- if (debugflag==324 ){ \
- sprintf(cDbgMsg, (y), (p), (q), (r), (s) ); \
- stopmsg((x), cDbgMsg ); \
- }
-
- #else
-
- #define DBUGMSG(x,y)
- #define DBUGMSG1(x,y,p)
- #define DBUGMSG2(x,y,p,q)
- #define DBUGMSG3(x,y,p,q,r)
- #define DBUGMSG4(x,y,p,q,r,s)
-
- #endif /* TESTFP */
-
- #define FN_LOD 0
- #define FN_CLR 1
- #define FN_ADD 2
- #define FN_SUB 3
- #define FN_MUL 4
- #define FN_DIV 5
- #define FN_STO 6
- #define FN_SQR 7
- #define FN_ENDINIT 8
- #define FN_MOD 9
- #define FN_LTE 10
- #define FN_SIN 11
- #define FN_COS 12
- #define FN_SINH 13
- #define FN_COSH 14
- #define FN_COSXX 15
- #define FN_TAN 16
- #define FN_TANH 17
- #define FN_COTAN 18
- #define FN_COTANH 19
- #define FN_LOG 20
- #define FN_EXP 21
- #define FN_PWR 22
- #define FN_LT 23
- #define FN_FLIP 24
- #define FN_REAL 25
- #define FN_IMAG 26
- #define FN_CONJ 27
- #define FN_NEG 28
- #define FN_ABS 29
- #define FN_RECIP 30
- #define FN_IDENT 31
- #define FN_GT 32
- #define FN_GTE 33
- #define FN_NE 34
- #define FN_EQ 35
- #define FN_AND 36
- #define FN_OR 37
- #define FN_ZERO 38
- #define FN_SQRT 39
- #define FN_ASIN 40
- #define FN_ACOS 41
- #define FN_ASINH 42
- #define FN_ACOSH 43
- #define FN_ATANH 44
- #define FN_ATAN 45
- #define FN_CABS 46
-
- /* number of "old" functions in the table. */
- /* these are the ones that the parser outputs */
-
- #define LAST_OLD_FN FN_CABS
- #define NUM_OLD_FNS LAST_OLD_FN + 1
-
- /* total number of functions in the table. */
-
- #define LAST_FN FN_CABS
- #define NUM_FNS LAST_FN + 1
-
- static unsigned char
- realstkcnt, /* how many scalars are really on stack */
- stkcnt, /* # scalars on FPU stack */
- cvtptrx, /* subscript of next free entry in pfls */
- lastsqrused, /* was lastsqr loaded in the formula? */
- lastsqrreal, /* was lastsqr stored explicitly in the formula? */
- p1const, /* is p1 a constant? */
- p2const, /* ...and p2? */
- p3const; /* ...and p3? */
-
- static void (near *prevfptr )(void); /* previous function pointer */
-
- /* the entries in this table must be in the same order as */
- /* the #defines above */
- /* this table is searched sequentially */
- struct fn_entry {
-
- char far *fname; /* function name */
-
- void (far *infn)(void); /* 'old' function pointer */
- /* (infn points to an operator fn in parser.c) */
-
- void (near *outfn)(void); /* pointer to equiv. fast fn. */
-
- char min_regs; /* min regs needed on stack by this fn. */
- /* (legal values are 0, 2, 4) */
-
- char free_regs; /* free regs required by this fn */
- /* (legal values are 0, 2, 4) */
-
- char delta; /* net change to # of values on the fp stack */
- /* (legal values are -2, 0, +2) */
-
- } static far afe[NUM_OLD_FNS] = { /* array of function entries */
-
- {"Lod", StkLod, fStkLod, 0, 2, +2 }, /* 0 */
- {"Clr", StkClr, fStkClr1, 0, 0, CLEAR_STK }, /* 1 */
- {"+", dStkAdd, fStkAdd, 4, 0, -2 }, /* 2 */
- {"-", dStkSub, fStkSub, 4, 0, -2 }, /* 3 */
- {"*", dStkMul, fStkMul, 4, 2, -2 }, /* 4 */
- {"/", dStkDiv, fStkDiv, 4, 2, -2 }, /* 5 */
- {"Sto", StkSto, fStkSto, 2, 0, 0 }, /* 6 */
- {"Sqr", dStkSqr, fStkSqr, 2, 2, 0 }, /* 7 */
- {":", EndInit, fStkEndInit,0, 0, CLEAR_STK }, /* 8 */
- {"Mod", dStkMod, fStkMod, 2, 0, 0 }, /* 9 */
- {"<=", dStkLTE, fStkLTE, 4, 0, -2 }, /* 10 */
- {"Sin", dStkSin, fStkSin, 2, 2, 0 }, /* 11 */
- {"Cos", dStkCos, fStkCos, 2, 2, 0 }, /* 12 */
- {"Sinh", dStkSinh, fStkSinh, 2, 2, 0 }, /* 13 */
- {"Cosh", dStkCosh, fStkCosh, 2, 2, 0 }, /* 14 */
- {"Cosxx", dStkCosXX, fStkCosXX, 2, 2, 0 }, /* 15 */
- {"Tan", dStkTan, fStkTan, 2, 2, 0 }, /* 16 */
- {"Tanh", dStkTanh, fStkTanh, 2, 2, 0 }, /* 17 */
- {"CoTan", dStkCoTan, fStkCoTan, 2, 2, 0 }, /* 18 */
- {"CoTanh", dStkCoTanh, fStkCoTanh, 2, 2, 0 }, /* 19 */
- {"Log", dStkLog, fStkLog, 2, 2, 0 }, /* 20 */
- {"Exp", dStkExp, fStkExp, 2, 2, 0 }, /* 21 */
- {"^", dStkPwr, fStkPwr, 4, 2, -2 }, /* 22 */
- {"<", dStkLT, fStkLT, 4, 0, -2 }, /* 23 */
- {"Flip", dStkFlip, fStkFlip, 2, 0, 0 }, /* 24 */
- {"Real", dStkReal, fStkReal, 2, 0, 0 }, /* 25 */
- {"Imag", dStkImag, fStkImag, 2, 0, 0 }, /* 26 */
- {"Conj", dStkConj, fStkConj, 2, 0, 0 }, /* 27 */
- {"Neg", dStkNeg, fStkNeg, 2, 0, 0 }, /* 28 */
- {"Abs", dStkAbs, fStkAbs, 2, 0, 0 }, /* 29 */
- {"Recip", dStkRecip, fStkRecip, 2, 2, 0 }, /* 30 */
- {"Ident", StkIdent, fStkIdent, 2, 0, 0 }, /* 31 */
- {">", dStkGT, fStkGT, 4, 0, -2 }, /* 32 */
- {">=", dStkGTE, fStkGTE, 4, 0, -2 }, /* 33 */
- {"!=", dStkNE, fStkNE, 4, 0, -2 }, /* 34 */
- {"==", dStkEQ, fStkEQ, 4, 0, -2 }, /* 35 */
- {"&&", dStkAND, fStkAND, 4, 0, -2 }, /* 36 */
- {"||", dStkOR, fStkOR, 4, 0, -2 }, /* 37 */
- {"Zero", dStkZero, fStkZero, 2, 0, 0 }, /* 38 */
- {"Sqrt", dStkSqrt, fStkSqrt, 2, 2, 0 }, /* 39 */
- {"ASin", dStkASin, fStkASin, 2, 4, 0 }, /* 40 */
- {"ACos", dStkACos, fStkACos, 2, 4, 0 }, /* 41 */
- {"ASinh", dStkASinh, fStkASinh, 2, 4, 0 }, /* 42 */
- {"ACosh", dStkACosh, fStkACosh, 2, 4, 0 }, /* 43 */
- {"ATanh", dStkATanh, fStkATanh, 2, 4, 0 }, /* 44 */
- {"ATan", dStkATan, fStkATan, 2, 4, 0 }, /* 45 */
- {"CAbs", dStkCAbs, fStkCAbs, 2, 0, 0 } /* 46 */
- };
-
- #ifdef COMPILER
- struct fn_header {
- unsigned int fn_size; /* size of function code in bytes */
- char near *pcode; /* pointer to actual code */
- char near *incl_addr; /* addr of included fn (offset from seg base) */
- char x_fixup; /* offset of any x fixup (-1 if none) */
- char y_fixup; /* " " " y " " " " */
- char incl_offset; /* " " included fn. " " " */
- };
- #endif /* COMPILER */
-
- #ifdef TESTFP
- static char cDbgMsg[255];
- #endif /* TESTFP */
-
-
- #ifdef COMPILER
-
- static int near fIncl_fn(char far *pcIncl, char far *pcTarget ){
-
- int i, iIncl_len = *(int far *)pcIncl & 0x007f; /* max 127 */
-
- for (i=0, pcIncl+=2; i<iIncl_len; i++ ){
- *pcTarget++ = *pcIncl++;
- }
-
- return iIncl_len;
- }
-
- static int near fNormal_fn(struct fn_header far *psIn, char far *pcTarget,
- char near *npcOperand ){
-
- int i; /* temp loop variable (offset into src fn) */
- int iBytesCopied; /* another temp */
- int iCount = 0; /* count of bytes copied to target */
- long lSegment = (long)compiled_fn_1 & 0xFFFF0000L;
- int iCodeSize = psIn->fn_size & 0x007f; /* max 127 bytes */
- char far *pcCode;
-
- pcCode = (char far *)((long)lSegment | (int)(psIn->pcode) );
-
- for (i=0; i<iCodeSize; i++){
- if (i == psIn->incl_offset ){
- DBUGMSG(0, "Including a function" );
- if (*pcCode == -1 ){ /* sanity check */
- iBytesCopied = fIncl_fn(
- (char far *)(lSegment | (unsigned int)(psIn->incl_addr )),
- pcTarget );
- pcTarget += iBytesCopied;
- pcCode++; /* to skip 1-byte placeholder */
- iCount += iBytesCopied;
- }
- else {
- DBUGMSG(0, "Unexpected error, incl_placeholder != -1" );
- }
- }
- else if (i == psIn->x_fixup || i == psIn->y_fixup ){
- if (i == psIn->x_fixup ){
- DBUGMSG(0, "X fixup" );
- *(char near * far *)pcTarget = npcOperand;
- }
- else {
- DBUGMSG(0, "Y fixup" );
- *(char near * far *)pcTarget = npcOperand + sizeof(double);
- }
- pcTarget+=2, pcCode+=2; /* two bytes copied from src to target */
- i++; /* two bytes were taken from source instead of one */
- iCount += 2;
- }
- else {
- *pcTarget++ = *pcCode++;
- iCount++;
- }
- }
-
- return iCount;
- }
-
- static void near fCompile(void){
-
- int i;
- struct fn_header far *pfnh;
- long lSegment = (long)compiled_fn_1 & 0xFFFF0000L;
- char far *pcTarget;
-
- for (i=0,pcTarget=compiled_fn_1; i<cvtptrx; i++ ){
- pfnh = (struct fn_header far *)
- (lSegment | (unsigned int)(pfls[i].function));
- if (pfnh->fn_size & 0x8000 ){
- /* Normal function */
- pcTarget += fNormal_fn(pfnh, pcTarget, (char near *)pfls[i].operand );
- }
- else {
- pcTarget += fIncl_fn((char far *)pfnh, pcTarget );
- }
- if (pfls[i].function == fStkEndInit ){
- *pcTarget++ = '\xC3'; /* opcode for near return */
- break;
- }
- }
-
- for (i++,pcTarget=compiled_fn_2; i<cvtptrx; i++ ){
- pfnh = (struct fn_header far *)
- (lSegment | (unsigned int)(pfls[i].function));
- if (pfnh->fn_size & 0x8000 ){
- pcTarget +=
- fNormal_fn(pfnh, pcTarget, (char near *)pfls[i].operand );
- }
- else {
- pcTarget += fIncl_fn((char far *)pfnh, pcTarget );
- }
- }
- *pcTarget++ = '\xC3'; /* near return at end of fn */
-
- return;
- }
-
- #endif /* COMPILER */
-
-
- static int CvtFptr(void (near * ffptr)(void), int MinStk, int FreeStk,
- int Delta )
- {
- union Arg near *otemp; /* temp operand ptr */
- union Arg far *testload;
- #ifdef TESTFP
- int prevstkcnt;
- #endif
- double dTemp;
-
- int Max_On_Stack = MAX_STACK - FreeStk; /* max regs allowed on stack */
- int Num_To_Push; /* number of regs to push */
-
- /* first do some sanity checks */ /* CAE 15Feb95 */
- if ( (Delta != -2 && Delta != 0 && Delta != 2 && Delta != CLEAR_STK)
- || (FreeStk != 0 && FreeStk != 2 && FreeStk != 4)
- || (MinStk != 0 && MinStk != 2 && MinStk != 4) ){
- awful_error:
- stopmsg (0,"FATAL INTERNAL PARSER ERROR!");
- return 0; /* put out dire message and revert to old parser */
- }
-
- /* this if statement inserts a stack push or pull into the token array */
- /* it would be much better to do this *after* optimization */
- if ((int)stkcnt < MinStk ) { /* not enough operands on fpu stack */
- DBUGMSG2(0, "Inserted pull. Stack: %2d --> %2d", stkcnt, stkcnt+2 );
- OPPTR(cvtptrx) = NO_OPERAND;
- FNPTR(cvtptrx++) = fStkPull2; /* so adjust the stack, pull operand */
- stkcnt += 2;
- }
- else if ((int)stkcnt > Max_On_Stack ) { /* too many operands */
-
- Num_To_Push = stkcnt - Max_On_Stack;
- if (Num_To_Push == 2 ){
- if (stkcnt == MAX_STACK ){
- /* push stack down from max to max-2 */
- FNPTR(cvtptrx) = fStkPush2;
- }
- else if (stkcnt == MAX_STACK - 2 ){
- /* push stack down from max-2 to max-4 */
- FNPTR(cvtptrx) = fStkPush2a;
- }
- else {
- goto awful_error;
- }
- DBUGMSG2(0,
- "Inserted push. Stack: %2d --> %2d", stkcnt, stkcnt-2 );
- OPPTR(cvtptrx++) = NO_OPERAND;
- stkcnt -= 2;
- }
- else if (Num_To_Push == 4 ){
- /* push down from max to max-4 */
- FNPTR(cvtptrx) = fStkPush4;
- DBUGMSG2(0,
- "Inserted push. Stack: %2d --> %2d", stkcnt, stkcnt-4 );
- OPPTR(cvtptrx++) = NO_OPERAND;
- stkcnt -= 4;
- }
- else {
- goto awful_error;
- }
- }
-
- /* set the operand pointer here for store function */
- if (ffptr == fStkSto ){
- OPPTR(cvtptrx) = (void near *)FP_OFF((Store[StoPtr++]));
- }
- else if (ffptr == fStkLod && debugflag == 322 ){
- /* when disabling optimizer, set load pointer here */
- OPPTR(cvtptrx) = (void near *)FP_OFF((Load[LodPtr++]));
- }
- else { /* the optimizer will set the pointer for load fn. */
- OPPTR(cvtptrx) = NO_OPERAND;
- }
-
- if (debugflag == 322 ){
- goto SkipOptimizer;
- } /* -------------------------- begin optimizer --------------------- */
-
- /* This optimizer grew from a simple if statement into a monster. */
-
- /* Most of the bugs in the optimizer have been in the code that */
- /* juggles the overflow stack. */
-
- /* For the following: */
- /* * == cvtptrx points to this */
- /* () == this is about to be added to the array */
-
- /* ******************************************************************** */
- if (ffptr == fStkLod) { /* about to add Lod to the array */
-
- if (prevfptr == fStkLod && Load[LodPtr-1] == Load[LodPtr] ) {
- /* previous non-adjust operator was Lod of same operand */
- /* ? lodx ? (*lodx) */
- if (FNPTR(--cvtptrx) == fStkPush2 ){ /* prev fn was push */
- /* ? lod *push (lod) */
- --cvtptrx; /* found *lod push (lod) */
- if (FNPTR(cvtptrx-1) == fStkPush2){ /* always more ops here */
- DBUGMSG(0, "push *lod push (lod) -> push4 (*loddup)" );
- FNPTR(cvtptrx-1) = fStkPush4;
- }
- else { /* prev op not push */
- DBUGMSG(0, "op *lod push (lod) -> op pusha(p=0) (*loddup)" );
- OPPTR(cvtptrx) = NO_OPERAND; /* use 'alternate' push fn. */
- FNPTR(cvtptrx++) = fStkPush2a; /* push w/2 free on stack */
- /* operand ptr will be set below */
- }
- }
- else { /* never push *lod (lod) so must be */
- DBUGMSG(0, "op *lod (lod) -> op (*loddup)" );
- }
- ffptr = fStkLodDup;
- }
- else if (prevfptr == fStkSto2
- && Store[StoPtr-1] == Load[LodPtr] ){
- /* store, load of same value */
- /* only one operand on stack here when prev oper is Sto2 */
- DBUGMSG(0, "*sto2 (lod) -> (*stodup)" );
- --cvtptrx;
- ffptr = fStkStoDup;
- }
- /* This may cause roundoff problems when later operators */
- /* use the rounded value that was stored here, while the next */
- /* operator uses the more accurate internal value. */
- else if (prevfptr == fStkStoClr2
- && Store[StoPtr-1] == Load[LodPtr] ){
- /* store, clear, load same value found */
- /* only one operand was on stack so this is safe */
- DBUGMSG (0, "*StoClr2 (Lod) -> (*Sto2)" );
- --cvtptrx;
- ffptr = fStkSto2; /* use different Sto fn */
- }
- else {
- testload = Load[LodPtr];
- if (testload == &LASTSQR && lastsqrreal ){
- /* -- LastSqr is a real. CAE 31OCT93 */
- DBUGMSG(0, "(*lod[lastsqr]) -> (*lodreal)" );
- ffptr = fStkLodReal;
- }
- else if (IS_CONST(testload) && testload->d.y == 0.0 ){
- DBUGMSG(0, "(*lod) -> (*lodrealc)" );
- ffptr = fStkLodRealC; /* a real const is being loaded */
- }
- }
- /* set the operand ptr here */
- OPPTR(cvtptrx) = (void near *)FP_OFF((Load[LodPtr++]));
- }
- /* ******************************************************************** */
- else if (ffptr == fStkAdd ){
-
- if (prevfptr == fStkLodDup ){ /* there is never a push before add */
- --cvtptrx; /* found ? *loddup (add) */
- if (cvtptrx!=0 && FNPTR(cvtptrx-1) == fStkPush2a ){
- /* because push lod lod is impossible so is push loddup */
- DBUGMSG(0, "pusha *loddup (add) -> (*loddbl),stk+=2" );
- REMOVE_PUSH;
- OPPTR(cvtptrx) = OPPTR(cvtptrx+1); /* fix opptr */
- }
- else if (cvtptrx!=0 && FNPTR(cvtptrx-1) == fStkPush4 ){
- DBUGMSG(0, "push4 *loddup (add) -> push2 (*loddbl),stk+=2" );
- FNPTR(cvtptrx-1) = fStkPush2;
- stkcnt += 2; /* CAE added 12 July 1993 to fix bug */
- }
- else {
- DBUGMSG(0, "op *loddup (add) -> op (*loddbl)" );
- }
- ffptr = fStkLodDbl;
- }
- else if (prevfptr == fStkStoDup ){
- DBUGMSG(0, "stodup (*add) -> (*stodbl)" );
- /* there are always exactly 4 on stack here */
- --cvtptrx;
- ffptr = fStkStoDbl;
- }
- else if (prevfptr == fStkLod ){ /* have found lod (*add) */
- --cvtptrx; /* ? *lod (add) */
- if (FNPTR(cvtptrx-1) == fStkPush2 ){
- DBUGMSG(0, "*push load (add) -> (*plodadd),stk+=2" );
- REMOVE_PUSH;
- OPPTR(cvtptrx) = OPPTR(cvtptrx+1); /* fix opptrs */
- ffptr = fStkPLodAdd;
- }
- else {
- DBUGMSG(0, "op *lod (add) -> op (*lodadd)" );
- ffptr = fStkLodAdd;
- }
- }
- else if (prevfptr == fStkLodReal || prevfptr == fStkLodRealC ){
- --cvtptrx; /* found ? *lodreal (add) */
- if (FNPTR(cvtptrx-1) == fStkPush2 ){
- DBUGMSG(0, "*push lodreal (add) -> (*lodrealadd),stk+=2" );
- REMOVE_PUSH;
- OPPTR(cvtptrx) = OPPTR(cvtptrx+1); /* fix opptrs */
- }
- else {
- DBUGMSG(0, "*lodreal (add) -> (*lodrealadd)" );
- }
- ffptr = fStkLodRealAdd;
- }
- else if (prevfptr == fStkLodImag ){ /* CAE 4DEC93 */
- --cvtptrx; /* found ? *lodimag (add) */
- if (FNPTR(cvtptrx-1) == fStkPush2 ){
- DBUGMSG(0, "*push lodimag (add) -> (*lodimagadd),stk+=2" );
- REMOVE_PUSH;
- OPPTR(cvtptrx) = OPPTR(cvtptrx+1); /* fix opptrs */
- }
- else {
- DBUGMSG(0, "*lodimag (add) -> (*lodimagadd)" );
- }
- ffptr = fStkLodImagAdd;
- }
- }
- /* ******************************************************************** */
- else if (ffptr == fStkSub ){
-
- if (prevfptr == fStkLod ){
- /* found lod (*sub) */
- --cvtptrx; /* *lod (sub) */
- /* there is never a sequence (lod push sub ) */
- if (FNPTR(cvtptrx-1) == fStkPush2 ){
- DBUGMSG(0, "*push lod (sub) -> (*plodsub),stk+=2" );
- REMOVE_PUSH;
- OPPTR(cvtptrx) = OPPTR(cvtptrx+1); /* fix opptrs */
- ffptr = fStkPLodSub;
- }
- else {
- DBUGMSG(0, "*lod (sub) -> (*lodsub)" );
- ffptr = fStkLodSub;
- }
- }
- else if (prevfptr == fStkLodReal || prevfptr == fStkLodRealC ){
- --cvtptrx; /* ? *lodreal (sub) */
- if (FNPTR(cvtptrx-1) == fStkPush2 ){
- DBUGMSG(0, "*push lodreal (sub) -> (*lodrealsub),stk+=2" );
- REMOVE_PUSH;
- OPPTR(cvtptrx) = OPPTR(cvtptrx+1); /* fix opptrs */
- }
- else {
- DBUGMSG(0, "*lodreal (sub) -> (*lodrealsub)" );
- }
- ffptr = fStkLodRealSub;
- }
- else if (prevfptr == fStkLodImag ){ /* CAE 4DEC93 */
- --cvtptrx; /* ? *lodimag (sub) */
- if (FNPTR(cvtptrx-1) == fStkPush2 ){
- DBUGMSG(0, "*push lodimag (sub) -> (*lodimagsub),stk+=2" );
- REMOVE_PUSH;
- OPPTR(cvtptrx) = OPPTR(cvtptrx+1); /* fix opptrs */
- }
- else {
- DBUGMSG(0, "*lodimag (sub) -> (*lodimagsub)" );
- }
- ffptr = fStkLodImagSub;
- }
- }
- /* ******************************************************************** */
- else if (ffptr == fStkMul ){
-
- if (prevfptr == fStkLodDup ){
- /* found loddup ? (*mul) */
- if (FNPTR(--cvtptrx) == fStkPush2 ){
- DBUGMSG(0, "loddup *push (mul) -> (*lodsqr),stk+=2" );
- REMOVE_PUSH;
- }
- else {
- DBUGMSG(0, "*loddup (mul) -> (*lodsqr)" );
- }
- ffptr = fStkLodSqr;
- }
- else if (prevfptr == fStkStoDup ){ /* no pushes here, 4 on stk. */
- DBUGMSG(0, "stodup (mul) -> (*stosqr0)" );
- --cvtptrx;
- ffptr = fStkStoSqr0; /* dont save lastsqr here ever */
- }
- else if (prevfptr == fStkLod ){
- --cvtptrx; /* lod *? (mul) */
- if (FNPTR(cvtptrx) == fStkPush2 ){ /* lod *push (mul) */
- --cvtptrx; /* ? *lod push (mul) */
- if(FNPTR(cvtptrx-1) == fStkPush2 ){
- DBUGMSG(0, "push *lod push (mul) -> push4 (*lodmul)" );
- FNPTR(cvtptrx-1) = fStkPush4;
- }
- else {
- DBUGMSG(0, "op *lod push (mul) -> op pusha (*lodmul)" );
- OPPTR(cvtptrx+1) = OPPTR(cvtptrx); /* fix operand ptr */
- FNPTR(cvtptrx) = fStkPush2a;
- OPPTR(cvtptrx) = NO_OPERAND;
- cvtptrx++;
- }
- }
- else {
- DBUGMSG(0, "*lod (mul) -> (*lodmul)" );
- }
- ffptr = fStkLodMul;
-
- /********************** begin extension *** CAE 9 Oct 93 ****/
- /* change loadreal a, lodmul b --> lod b, lodrealmul a */
-
- FNPTR(cvtptrx) = NO_FUNCTION; /* mark the pending fn as null */
- if (FNPTR(cvtptrx-1) == fStkPush4
- || FNPTR(cvtptrx-1) == fStkPush2a ){
- --cvtptrx; /* look back past this push */
- }
-
- if (FNPTR(cvtptrx-1) == fStkLodRealC
- && Load[LodPtr-2]->d.x == _2_ ){
- /* -- Convert '2*a' into 'a+a'. CAE 31OCT93 */
- if (FNPTR(cvtptrx) == NO_FUNCTION ){
- DBUGMSG(0, "lodreal[2] (*lodmul[b])"
- " -> (*loddbl[b])" );
- OPPTR(cvtptrx-1) = OPPTR(cvtptrx);
- }
- else if (FNPTR(cvtptrx) == fStkPush2a ){
- DBUGMSG(0, "lodreal[2] *pusha (lodmul[b])"
- " -> loddbl[b],stk+=2" );
- OPPTR(cvtptrx-1) = OPPTR(cvtptrx+1);
- stkcnt += 2;
- }
- else if (FNPTR(cvtptrx) == fStkPush4 ){
- DBUGMSG(0, "lodreal[2] *push4 (lodmul[b])"
- " -> loddbl[b],stk+=4" );
- OPPTR(cvtptrx-1) = OPPTR(cvtptrx+1);
- stkcnt += 4;
- }
- FNPTR(--cvtptrx) = NO_FUNCTION; /* so no increment later */
- ffptr = fStkLodDbl;
- }
- else if (FNPTR(cvtptrx-1) == fStkLodReal
- || FNPTR(cvtptrx-1) == fStkLodRealC ){
- /* lodreal *?push?? (*?lodmul) */
- otemp = OPPTR(cvtptrx-1); /* save previous fn's operand */
- FNPTR(cvtptrx-1) = fStkLod; /* prev fn = lod */
- /* Moved setting of prev lodptr to below CAE 31DEC93 */
- /* This was a bug causing a bad loadptr to be set here */
- /* 3 lines marked 'prev lodptr=this' below replace this line */
- if (FNPTR(cvtptrx) == NO_FUNCTION ){
- DBUGMSG(0, "lodreal[a] (*lodmul[b])"
- " -> lod[b] (*lodrealmul[a])" );
- OPPTR(cvtptrx-1) = OPPTR(cvtptrx); /* prev lodptr=this */
- }
- else if (FNPTR(cvtptrx) == fStkPush2a ){
- DBUGMSG(0, "lodreal[a] *pusha (lodmul[b])"
- " -> lod[b] (*lodrealmul[a]),stk+=2" );
- /* set this fn ptr to null so cvtptrx won't be incr later */
- FNPTR(cvtptrx) = NO_FUNCTION;
- OPPTR(cvtptrx-1) = OPPTR(cvtptrx+1); /* prev lodptr=this */
- stkcnt += 2;
- }
- else if (FNPTR(cvtptrx) == fStkPush4 ){
- DBUGMSG(0, "lodreal[a] *push4 (lodmul[b])"
- " -> lod[b] push2 (*lodrealmul[a]),stk+=2" );
- FNPTR(cvtptrx++) = fStkPush2;
- OPPTR(cvtptrx-2) = OPPTR(cvtptrx); /* prev lodptr=this */
- /* we know cvtptrx points to a null function now */
- stkcnt += 2;
- }
- OPPTR(cvtptrx) = otemp; /* switch the operands */
- ffptr = fStkLodRealMul; /* next fn is now lodrealmul */
- }
-
- if (FNPTR(cvtptrx) != NO_FUNCTION ){
- cvtptrx++; /* adjust cvtptrx back to normal if needed */
- }
- /* ********************** end extension *********************** */
- }
- else if (prevfptr == fStkLodReal || prevfptr == fStkLodRealC ){
-
- --cvtptrx; /* found lodreal *? (mul) */
- if (FNPTR(cvtptrx) == fStkPush2 ){
- DBUGMSG(0, "lodreal *push2 (mul) -> (*lodrealmul),stk+=2" );
- REMOVE_PUSH;
- }
- else {
- DBUGMSG(0, "*lodreal (mul) -> (*lodrealmul)" );
- }
- ffptr = fStkLodRealMul;
-
- /********************** begin extension *** CAE 31OCT93 ****/
- if (prevfptr == fStkLodRealC /* use prevfptr here */
- && Load[LodPtr-1]->d.x == _2_ ){
- if (FNPTR(cvtptrx) == fStkPush2 ){
- DBUGMSG(0, "push (*lodrealmul[2]) -> (*dbl),stk+=2" );
- REMOVE_PUSH;
- }
- else {
- DBUGMSG(0, "*lodrealmul[2] -> (*dbl)" );
- }
- OPPTR(cvtptrx) = NO_OPERAND;
- ffptr = fStkDbl;
-
- if (FNPTR(cvtptrx-1) == fStkLod ){
- DBUGMSG(0, "lod (*dbl) -> (*loddbl)" );
- --cvtptrx;
- ffptr = fStkLodDbl;
- }
- else if (FNPTR(cvtptrx-1) == fStkSto2 ){
- DBUGMSG(0, "sto2 (*dbl) -> (*stodbl)" );
- --cvtptrx;
- ffptr = fStkStoDbl;
- }
- }
- /************************ end extension *** CAE 31OCT93 ****/
- }
- else if (prevfptr == fStkLodImag ){ /* CAE 4DEC93 */
-
- --cvtptrx; /* found lodimag *? (mul) */
- if (FNPTR(cvtptrx) == fStkPush2 ){
- DBUGMSG(0, "lodimag *push2 (mul) -> (*lodimagmul),stk+=2" );
- REMOVE_PUSH;
- }
- else {
- DBUGMSG(0, "*lodimag (mul) -> (*lodimagmul)" );
- }
- ffptr = fStkLodImagMul;
- }
- else if (prevfptr == fStkLodLT && FNPTR(cvtptrx-1) != fStkPull2 ){
- /* this shortcut fails if Lod LT Pull Mul found */
- DBUGMSG(0, "LodLT (*Mul) -> (*LodLTMul)" );
- --cvtptrx; /* never lod LT Push Mul here */
- ffptr = fStkLodLTMul;
- }
- else if (prevfptr == fStkLodLTE && FNPTR(cvtptrx-1) != fStkPull2 ){
- DBUGMSG(0, "LodLTE (*mul) -> (*LodLTEmul)" );
- --cvtptrx;
- ffptr = fStkLodLTEMul;
- }
- }
- /* ******************************************************************** */
- else if (ffptr == fStkClr1 && prevfptr == fStkSto ){
-
- --cvtptrx;
- if (stkcnt == 2 ){
- DBUGMSG(0, "sto (*clr1) -> (*stoclr2)" );
- ffptr = fStkStoClr2;
- }
- else {
- DBUGMSG(0, "sto (*clr1) -> (*stoclr1)" );
- ffptr = fStkStoClr1;
- }
- }
- /* ******************************************************************** */
- else if (ffptr == fStkDiv ){
-
- if (prevfptr == fStkLodRealC && vsp < MAX_ARGS - 1 ){
- /* have found a divide by a real constant */
- /* and there is space to create a new one */
- /* lodrealc ? (*div) */
- if (FNPTR(--cvtptrx) == fStkPush2 ){
- DBUGMSG(0, "lodrealc *push (div) -> (*lodrealmul),stk+=2" );
- REMOVE_PUSH;
- }
- else {
- DBUGMSG(0, "*lodrealc (div) -> (*lodrealmul)" );
- }
- v[vsp].s = (void near *)0; /* this constant has no name */
- v[vsp].len = 0;
- v[vsp].a.d.x = _1_ / Load[LodPtr-1]->d.x;
- v[vsp].a.d.y = 0.0;
- {
- void far *p = &v[vsp++].a;
- OPPTR(cvtptrx) = (void near *)FP_OFF(p); /* isn't C fun! */
- }
- ffptr = fStkLodRealMul;
- }
- }
- /* ******************************************************************** */
- else if (ffptr == fStkReal ){
-
- if (prevfptr == fStkLod ){
- DBUGMSG(0, "lod (*real) -> (*lodreal)" );
- --cvtptrx;
- ffptr = fStkLodReal;
- }
- else if (stkcnt < MAX_STACK ){
- DBUGMSG(0, "(*real) -> (*real2)" );
- ffptr = fStkReal2;
- }
- }
- /* ******************************************************************** */
- else if (ffptr == fStkImag && prevfptr == fStkLod ){
-
- DBUGMSG(0, "lod (*imag) -> lodimag" );
- --cvtptrx;
- ffptr = fStkLodImag;
- }
- /* ******************************************************************** */
- else if (ffptr == fStkConj && prevfptr == fStkLod ){
-
- DBUGMSG(0, "lod (*conj) -> (*lodconj)" );
- --cvtptrx;
- ffptr = fStkLodConj;
- }
- /* ******************************************************************** */
- else if (ffptr == fStkMod && stkcnt < MAX_STACK ){
-
- DBUGMSG(0, "(*mod) -> (*mod2)" );
- ffptr = fStkMod2; /* use faster version if room on stack */
- if (prevfptr == fStkLod ){
- DBUGMSG(0, "lod (*mod2) -> (*lodmod2)" );
- --cvtptrx;
- ffptr = fStkLodMod2;
- }
- else if (prevfptr == fStkSto || prevfptr == fStkSto2 ){
- DBUGMSG(0, "sto (*mod2) -> (*stomod2)" );
- --cvtptrx;
- ffptr = fStkStoMod2;
- }
- else if (prevfptr == fStkLodSub ){
- DBUGMSG(0, "lodsub (*mod2) -> (*lodsubmod)" );
- --cvtptrx;
- ffptr = fStkLodSubMod;
- }
- else if (STACK_TOP_IS_REAL){ /* CAE 06NOV93 */
- DBUGMSG(0, "(*mod2[st real]) -> (*sqr3)" );
- ffptr = fStkSqr3;
- }
- }
- /* ******************************************************************** */
- else if (ffptr == fStkFlip ){
-
- if (prevfptr == fStkReal || prevfptr == fStkReal2 ){
- DBUGMSG(0, "real (*flip) -> (*realflip)" );
- --cvtptrx;
- ffptr = fStkRealFlip;
- }
- else if (prevfptr == fStkImag ){
- DBUGMSG(0, "imag (*flip) -> (*imagflip)" );
- --cvtptrx;
- ffptr = fStkImagFlip;
- }
- else if (prevfptr == fStkLodReal ){
- DBUGMSG(0, "lodreal (*flip) -> (*lodrealflip)" );
- --cvtptrx;
- ffptr = fStkLodRealFlip;
- }
- else if (prevfptr == fStkLodImag ){
- DBUGMSG(0, "lodimag (*flip) -> (*lodimagflip)" );
- --cvtptrx;
- ffptr = fStkLodImagFlip;
- }
- }
- /* ******************************************************************** */
- else if (ffptr == fStkAbs ){
-
- if (prevfptr == fStkLodReal ){
- DBUGMSG(0, "lodreal (*abs) -> (*lodrealabs)" );
- --cvtptrx;
- ffptr = fStkLodRealAbs;
- }
- else if (prevfptr == fStkLodImag ){
- DBUGMSG(0, "lodimag (*abs) -> (*lodimagabs)" );
- --cvtptrx;
- ffptr = fStkLodImagAbs;
- }
- }
- /* ******************************************************************** */
- else if (ffptr == fStkSqr ){
-
- if (prevfptr == fStkLod && FNPTR(cvtptrx-1) != fStkPush2 ){
- DBUGMSG(0, "lod (*sqr) -> (*lodsqr)" );
- --cvtptrx;
- ffptr = fStkLodSqr; /* assume no need to save lastsqr */
- if (lastsqrused){
- DBUGMSG(0, "(*lodsqr) -> (*lodsqr2)" );
- ffptr = fStkLodSqr2; /* lastsqr is being used */
- }
- }
- else if (prevfptr == fStkSto2 ){
- DBUGMSG(0, "sto2 (*sqr) -> (*stosqr0)" );
- --cvtptrx;
- ffptr = fStkStoSqr0; /* assume no need to save lastsqr */
- if (lastsqrused) {
- DBUGMSG(0, "(*stosqr0) -> (*stosqr)" );
- ffptr = fStkStoSqr; /* save lastsqr */
- }
- }
- else {
- if (!lastsqrused) {
- DBUGMSG(0, "(*sqr) -> (*sqr0)" );
- ffptr = fStkSqr0; /* don't save lastsqr */
- if (STACK_TOP_IS_REAL){ /* CAE 06NOV93 */
- DBUGMSG(0, "(*sqr0[st real]) -> (*sqr3)" );
- ffptr = fStkSqr3;
- }
- }
- }
- }
- /* ******************************************************************** */
- else if (ffptr == fStkPwr ){
-
- if (prevfptr == fStkLodRealC ){
- dTemp = Load[LodPtr-1]->d.x;
- if (dTemp == _2_ || dTemp == _1_ || dTemp == -1.0 || dTemp == 0.0 ){
- /* change ^[-1,0,1,or 2] to recip,one,ident,sqr CAE 06NOV93 */
- if (FNPTR(cvtptrx-1) == fStkPush2 ){
- DBUGMSG(0, "LodRealC[-1,0,1,2] Push (*Pwr)"
- " -> (*[recip,1,ident,Sqr0]), stk+=2" );
- REMOVE_PUSH; /* lod[?] (push) *pwr */
- }
- else {
- DBUGMSG(0, "LodRealC[-1,0,1,2] (*Pwr)"
- " -> (*[recip,1,ident,sqr0])" );
- }
- --cvtptrx;
- OPPTR(cvtptrx) = NO_OPERAND;
- if (dTemp == _2_ ){
- DBUGMSG(0, "[]=Sqr0" );
- ffptr = fStkSqr0; /* no need to compute lastsqr here */
- if (FNPTR(cvtptrx-1) == fStkLod ){
- DBUGMSG(0, "Lod (*Sqr0) -> (*LodSqr)" );
- --cvtptrx;
- ffptr = fStkLodSqr; /* dont save lastsqr */
- }
- else if (FNPTR(cvtptrx-1) == fStkSto2 ){
- DBUGMSG(0, "Sto2 (*Sqr0) -> (*StoSqr0)" );
- --cvtptrx;
- ffptr = fStkStoSqr0; /* dont save lastsqr */
- }
- }
- else if (dTemp == _1_ ){
- DBUGMSG(0, "[]=Ident" );
- ffptr = fStkIdent;
- }
- else if (dTemp == 0.0 ){
- DBUGMSG(0, "[]=One" );
- ffptr = fStkOne;
- }
- else if (dTemp == -1.0 ){
- DBUGMSG(0, "[]=Recip" );
- ffptr = fStkRecip;
- }
- }
- else if (FNPTR(cvtptrx-1) == prevfptr ){
- --cvtptrx;
- ffptr = fStkLodRealPwr; /* see comments below */
- }
- }
- else if (prevfptr == fStkLodReal && FNPTR(cvtptrx-1) == prevfptr ){
- /* CAE 6NOV93 */
- /* don't handle pushes here, lodrealpwr needs 4 free */
- DBUGMSG(0, "LodReal (*Pwr) -> (*LodRealPwr)" );
- --cvtptrx;
- ffptr = fStkLodRealPwr;
- }
- }
- /* ******************************************************************** */
- else if (ffptr == fStkLTE ){
-
- if (prevfptr == fStkLod
- || prevfptr == fStkLodReal || prevfptr == fStkLodRealC ){
- DBUGMSG(0, "Lod (*LTE) -> (*LodLTE)" );
- --cvtptrx;
- ffptr = fStkLodLTE;
- }
- }
- /* ******************************************************************** */
- else if (ffptr == fStkLT ){
-
- if (prevfptr == fStkLod || prevfptr == fStkLodReal
- || prevfptr == fStkLodRealC ){
- DBUGMSG(0, "Lod (*LT) -> (*LodLT)" );
- --cvtptrx;
- ffptr = fStkLodLT;
- }
- }
- /* ******************************************************************** */
- else if (ffptr == fStkGT ){
-
- if (prevfptr == fStkLod
- || prevfptr == fStkLodReal || prevfptr == fStkLodRealC ){
- DBUGMSG(0, "Lod (*GT) -> (*LodGT)" );
- --cvtptrx;
- ffptr = fStkLodGT;
- }
- }
- /* ******************************************************************** */
- else if (ffptr == fStkGTE ){
-
- if (prevfptr == fStkLod
- || prevfptr == fStkLodReal || prevfptr == fStkLodRealC ){
- DBUGMSG(0, "Lod (*GTE) -> (*LodGTE)" );
- --cvtptrx;
- ffptr = fStkLodGTE;
- }
- }
- /* ******************************************************************** */
- else if (ffptr == fStkNE ){
-
- if (prevfptr == fStkLod
- || prevfptr == fStkLodReal || prevfptr == fStkLodRealC ){
- DBUGMSG(0, "Lod (*NE) -> (*LodNE)" );
- --cvtptrx;
- ffptr = fStkLodNE;
- }
- }
- /* ******************************************************************** */
- else if (ffptr == fStkEQ ){
-
- if (prevfptr == fStkLod
- || prevfptr == fStkLodReal || prevfptr == fStkLodRealC ){
- DBUGMSG(0, "Lod (*EQ) -> (*LodEQ)" );
- --cvtptrx;
- ffptr = fStkLodEQ;
- }
- }
- /* ******************************************************************** */
- SkipOptimizer: /* ------------- end of optimizer ----------------------- */
-
- FNPTR(cvtptrx++) = prevfptr = ffptr;
- #ifdef TESTFP
- prevstkcnt = stkcnt;
- #endif
- if (Delta == CLEAR_STK ){
- realstkcnt = stkcnt = 0;
- }
- else {
- stkcnt = (unsigned char)(stkcnt + Delta);
- realstkcnt = (unsigned char)(realstkcnt + Delta);
- }
-
- DBUGMSG3(0, "Stack: %2d --> %2d, Real stack: %2d",
- prevstkcnt, stkcnt, realstkcnt );
-
- return 1; /* return 1 for success */
- }
-
- extern int fform_per_pixel(void); /* these fns are in parsera.asm */
- extern int BadFormula(void);
- extern void (far Img_Setup )(void);
-
- int CvtStk() { /* convert the array of ptrs */
- extern char FormName[];
- void (far *ftst)(void);
- void (near *ntst)(void);
- union Arg far *testoperand;
- struct fn_entry far *pfe;
- int fnfound;
-
- lastsqrreal = 1; /* assume lastsqr is real (not stored explicitly) */
- p1const = p2const = p3const = (unsigned char)1; /* . . . p1, p2, p3 const */
- lastsqrused = 0; /* ... and LastSqr is not used */
-
- /* now see if the above assumptions are true */
- for (OpPtr = LodPtr = StoPtr = 0; OpPtr < (int)LastOp; OpPtr++ ){
- ftst = f[OpPtr];
- if (ftst == StkLod ){
- if (Load[LodPtr++] == &LASTSQR ){
- lastsqrused = 1;
- }
- }
- else if (ftst == StkSto ){
- testoperand = Store[StoPtr++];
- if (testoperand == &PARM1 ){
- p1const = 0;
- }
- else if (testoperand == &PARM2 ){
- p2const = 0;
- }
- else if (testoperand == &PARM3 ){
- p3const = 0;
- }
- else if (testoperand == &LASTSQR ){
- lastsqrreal = 0;
- }
- }
- }
-
- if (!p1const) {
- DBUGMSG(0, "p1 not constant" );
- }
- if (!p2const) {
- DBUGMSG(0, "p2 not constant" );
- }
- if (!p3const) {
- DBUGMSG(0, "p3 not constant" );
- }
- if (lastsqrused) {
- DBUGMSG(0, "LastSqr loaded" );
- if (!lastsqrreal) {
- DBUGMSG(0, "LastSqr stored" );
- }
- }
-
- if (f[LastOp-1] != StkClr ){
- DBUGMSG(0, "Missing clr added at end" );
- /* should be safe to modify this */
- f[LastOp++] = StkClr;
- }
-
- prevfptr = (void (near *)(void))0;
- realstkcnt = stkcnt = cvtptrx = 0;
-
- for (OpPtr = LodPtr = StoPtr = 0; OpPtr < (int)LastOp; OpPtr++) {
- ftst = f[OpPtr];
- fnfound = 0;
- for (pfe = &afe[0]; pfe <= &afe[LAST_OLD_FN]; pfe++ ){
- if (ftst == pfe->infn ){
- fnfound = 1;
- ntst = pfe->outfn;
- if (ntst == fStkClr1 && OpPtr == (int)(LastOp-1) ){
- ntst = fStkClr2; /* convert the last clear to a clr2 */
- DBUGMSG(0, "Last fn (CLR) --> (is really CLR2)" );
- }
- if (ntst == fStkIdent && debugflag != 322 ){
- /* ident will be skipped here */
- /* this is really part of the optimizer */
- DBUGMSG(0, "IDENT was skipped" );
- }
- else {
- DBUGMSG4(0, "fn=%Fs, minstk=%1i, freestk=%1i, delta=%3i",
- pfe->fname,
- (int)(pfe->min_regs),
- (int)(pfe->free_regs),
- (int)(pfe->delta) );
- if (!CvtFptr(ntst,
- pfe->min_regs,
- pfe->free_regs,
- pfe->delta) ){
- return 1;
- }
- }
- }
- }
- if (!fnfound ){
- /* return success so old code will be used */
- /* stopmsg(0, "Fast 387 parser failed, reverting to slower code." );*/
- return 1; /* this should only happen if random numbers are used */
- }
- } /* end for */
-
- if (debugflag == 322 ){
- goto skipfinalopt;
- } /* ------------------------------ final optimizations ---------- */
-
- /* cvtptrx -> one past last operator (always clr2) */
- --cvtptrx; /* now it points to the last operator */
- ntst = FNPTR(cvtptrx-1);
- /* ntst is the next-to-last operator */
-
- if (ntst == fStkLT ){
- DBUGMSG(0, "LT Clr2 -> LT2" );
- FNPTR(cvtptrx-1) = fStkLT2;
- }
- else if (ntst == fStkLodLT ){
- DBUGMSG(0, "LodLT Clr2 -> LodLT2" );
- FNPTR(cvtptrx-1) = fStkLodLT2;
- }
- else if (ntst == fStkLTE ){
- DBUGMSG(0, "LTE Clr2 -> LTE2" );
- FNPTR(cvtptrx-1) = fStkLTE2;
- }
- else if (ntst == fStkLodLTE ){
- DBUGMSG(0, "LodLTE Clr2 -> LodLTE2" );
- FNPTR(cvtptrx-1) = fStkLodLTE2;
- }
- else if (ntst == fStkGT ){
- DBUGMSG(0, "GT Clr2 -> GT2" );
- FNPTR(cvtptrx-1) = fStkGT2;
- }
- else if (ntst == fStkLodGT ){
- DBUGMSG(0, "LodGT Clr2 -> LodGT2" );
- FNPTR(cvtptrx-1) = fStkLodGT2;
- }
- else if (ntst == fStkLodGTE ){
- DBUGMSG(0, "LodGTE Clr2 -> LodGTE2" );
- FNPTR(cvtptrx-1) = fStkLodGTE2;
- }
- else if (ntst == fStkAND ){
- DBUGMSG(0, "AND Clr2 -> ANDClr2" );
- FNPTR(cvtptrx-1) = fStkANDClr2;
- ntst = FNPTR(cvtptrx-2);
- if (ntst == fStkLodLTE ){
- DBUGMSG(0, "LodLTE ANDClr2 -> LodLTEAnd2" );
- --cvtptrx;
- FNPTR(cvtptrx-1) = fStkLodLTEAnd2;
- }
- }
- else if (ntst == fStkOR ){ /* CAE 06NOV93 */
- DBUGMSG(0, "OR Clr2 -> ORClr2" );
- FNPTR(cvtptrx-1) = fStkORClr2;
- }
- else {
- ++cvtptrx; /* adjust this back since no optimization was found */
- }
-
- skipfinalopt: /* -------------- end of final optimizations ------------ */
-
- LastOp = cvtptrx; /* save the new operator count */
- LASTSQR.d.y = 0.0; /* do this once per image */
-
- /* now change the pointers */
- if (FormName[0] != 0 ){ /* but only if parse succeeded */
- curfractalspecific->per_pixel = fform_per_pixel;
- curfractalspecific->orbitcalc = fFormula;
- }
- else {
- curfractalspecific->per_pixel = BadFormula;
- curfractalspecific->orbitcalc = BadFormula;
- }
-
- #ifdef COMPILER
- fCompile();
- #endif
- Img_Setup(); /* call assembler setup code */
- return 1;
- }
-
- #endif /* XFRACT */
-