home *** CD-ROM | disk | FTP | other *** search
- /* ---------------------------------------------------------------------- */
- /* Copyright (C) 1991 by Natürlich! */
- /* This file is copyrighted! */
- /* Refer to the documentation for details. */
- /* ---------------------------------------------------------------------- */
- #include "defines.h"
- #include "nasm.h"
- #include "debug.h"
- #include "labels.h"
- #include NMALLOC_H
- #include "exprfast.h"
- #include OSBIND
- #include "code.h"
- #include "op.h"
-
- extern byte scrtab[];
- extern int runnable;
- int _in_doteq;
-
- #if ! DORECLAIM
- #define expr_tryfree( p)
- #endif
-
- #if ! VERSION
- /* ---------------------------------------------------------- */
- /* There is this unfortunate problems with labels. They might */
- /* be defined anywhere and with nasm65 even unknown (linked */
- /* from elsewhere). That leads to problems when generating */
- /* code. REFER and DREFER (pronounce REEFER and DEEREEFER) */
- /* "Don't fear the REFER" (Blue Oyster Cult (almost)) */
- /* build up lists of places, where labels have been used and */
- /* whether the label had a value then. */
- /* drefer means define and refer */
- /* ---------------------------------------------------------- */
- /* I NEVER USE XREFs */
- /* I NEVER LOOK AT THE SYMBOLTABLE AT THE END OF THE LISTING */
- /* WHY SHOULD I WASTE MEMORY FOR FEATURES I DON'T WANT */
- /* Therefore I don't need drefer just refer. That also means */
- /* I can compress the "ref" to 8 bytes. Now if I could get */
- /* rid of that one pointer. */
- /* ---------------------------------------------------------- */
- void refer( l, ex)
- label huge *l;
- expr huge *ex;
- {
- register ref huge *p = ref_alloc();
- extern buffer huge *bp;
-
- ENTER("refer");
- IMESS("label @$%lX", (lword) l, 4);
- p->ref = ex; /* Note expression that needs fixing */
- p->line = bp->line; /* (*) */
- p->next = l->refs; /* put it in the first slot... */
- l->refs = p;
- l->type |= L_REF;
- LEAVE();
- }
- #endif
-
- /* ---------------------------------------------------------- */
- /* Recursively copy expression (deep copy or shallow copy ?) */
- /* and if needed refer as of yet unkown labels. */
- /* code looks very nice, but can conceivably use some optimi- */
- /* zation. */
- /* ---------------------------------------------------------- */
- expr *copyexpr( p)
- register expr huge *p;
- {
- ENTER("copyexpr");
- if( ! p)
- {
- LEAVE();
- return( 0);
- }
-
- {
- register expr huge *q = exp_alloc();
-
- #if EXPRSIZE != 24 || PHILOSOPHICAL_PROBLEM
- bcopy( p, q, (lword) sizeof( expr));
- #else
- *((lword huge *) q)++ = *((lword huge *) p)++; /* label */
- *((lword huge *) q)++ = *((lword huge *) p)++; /* no & val */
- *((lword huge *) q) = *(lword huge *) p; /* aux & op & fix */
- (char huge *) q -= 8;
- (char huge *) p -= 8;
- #endif
- if( q->label) /* Tell label that we need a */
- refer( q->label, q); /* fix (if we need a fix) */
- if( q->l = copyexpr( p->l))
- q->l->zonk.t = q;
- if( q->r = copyexpr( p->r))
- q->r->zonk.t = q;
- LEAVE();
- return( q);
- }
- }
-
- #if ! VERSION
- /* ----------------------------------------------------------- */
- /* Create an s_expression node by planting a value */
- /* (could be a label as well) */
- /* ----------------------------------------------------------- */
- expr *ival_pl( value)
- word value;
- {
- expr huge *p = exp_alloc();
-
- ENTER("ival_pl");
- MESS("Wolf! Right here and now!");
- p->val = value;
- LEAVE();
- return( p);
- }
- #endif
-
- expr *lval_pl( name)
- char huge *name;
- {
- register expr huge *p = exp_alloc();
- register label huge *q;
-
- ENTER("lval_pl");
- MESS("Wolf! Right here and now!");
- if( q = find_label( name))
- {
- if( q->refs)
- {
- p->label = q;
- refer( q, p);
- }
- else
- p->val = q->val;
- IMESS("p->op %u", (lword) p->op, 2);
- p->op = ((q->type & L_PC) ? O_PCREL : 0) |
- ((q->type & L_ZERO) ? O_ZEROP : 0);
- }
- else
- if( runnable && _in_doteq)
- enter_elabel( name, ival_pl( __pc), L_NORMAL);
- else
- {
- p->label = enter_flabel( name, p);
- if( ! runnable)
- p->op = O_PCREL; /* cause fwd then is PC rel */
- }
- LEAVE();
- return( p);
- }
-
- /* ----------------------------------------------------------- */
- /* Create an s_expression node by planting an operation */
- /* There is still a bug in this as expressions like foo+2+3 */
- /* are not simplified if foo is unvalued */
- /* ----------------------------------------------------------- */
- expr *op_pl( op, left, rite)
- register int op;
- register expr huge *left, huge *rite;
- {
- register int lop;
- int rop;
-
- ENTER("op_pl");
- if( (lop = left->op) == (O_PCREL | (O_MSB & O_LSB)) ||
- (rite && (rop = rite->op) == (O_PCREL | (O_MSB & O_LSB))))
- {
- nerror("You can't calculate with a short PC relative expression");
- return( left);
- }
- if( valued( left)) /* if left is value */
- {
- if( ! rite || valued( rite))
- {
- MESS("Just calcing it");
- do_calc( left, rite, op); /* calc it */
- expr_tryfree( rite);
- IMESS("After do_calc %ld", (lword) lop, 4);
- LEAVE();
- return( left);
- }
- }
- else
- if( rite && valued( rite))
- switch( lop)
- {
- case O_ADD :
- if( is_addsub( op))
- {
- if( valued( left->l))
- do_calc( left->l, rite, op);
- else
- if( valued( left->r))
- do_calc( left->r, rite, op);
- else
- break;
- expr_tryfree( rite);
- return( left);
- }
- break;
-
- case O_SUB :
- if( op == O_ADD)
- {
- if( valued( left->l))
- do_calc( left->l, rite, O_ADD);
- else
- if( valued( left->r))
- do_calc( left->r, rite, O_SUB);
- else
- break;
- }
- else
- if( op == O_SUB)
- {
- if( valued( left->l))
- do_calc( left->l, rite, O_SUB);
- else
- if( valued( left->r))
- do_calc( left->r, rite, O_ADD);
- else
- break;
- }
- else
- break;
- expr_tryfree( rite);
- return( left);
-
- case O_MUL :
- if( op == O_MUL)
- {
- if( valued( left->l))
- do_calc( left->l, rite, op);
- else
- if( valued( left->r))
- do_calc( left->r, rite, op);
- else
- break;
- expr_tryfree( rite);
- return( left);
- }
- break;
-
- case O_DIV :
- if( op == O_DIV)
- {
- if( valued( left->l))
- do_calc( left->l, rite, op);
- else
- if( valued( left->r))
- do_calc( left->r, rite, O_MUL);
- else
- break;
- expr_tryfree( rite);
- return( left);
- }
- }
-
- MESS("Creating a node");
- {
- register expr huge *p;
-
- if( rite && valued( rite) && rite->val == 1)
- {
- if( is_addsub( op))
- {
- p = rite;
- rite = 0;
- op = op == O_ADD ? O_INC : O_DEC;
- goto asusual;
- }
- }
- p = exp_alloc();
-
- asusual:
- lop &= O_PCREL;
- rop &= O_PCREL;
- switch( op)
- {
- case O_INC :
- case O_DEC :
- case O_MSB :
- case O_LSB :
- p->op = lop;
- break;
-
- case O_ADD :
- p->op = lop ^ rop;
- break;
-
- case O_SUB :
- {
- static char what[] = { 0, 0, 0x80, 0 };
-
- p->op = what[ ((lop != 0) << 1) | (rop != 0) ];
- }
- }
-
- if( (left->op | (rite ? rite->op : 0)) & O_ZEROP)
- switch( op)
- {
- case O_SUB :
- if( rite->op & O_ZEROP)
- break;
- case O_ADD :
- if( ! p->op)
- case O_INC :
- case O_DEC :
- case O_LSB :
- p->op |= O_ZEROP;
- }
-
- p->op |= op;
- p->l = left;
- left->fix = 0; /* for macros */
- left->zonk.t = p;
- if( p->r = rite)
- rite->zonk.t = p;
- LEAVE();
- return( p);
- }
- }
-
- #if ! VERSION
- lexpr *lex_pl( s, ex)
- expr huge *ex;
- char *s;
- {
- register lexpr *p = lex_alloc();
-
- ENTER("lex_pl");
- IMESS("planting string $%8.8lX", (lword) s, 4);
- IMESS(" with expr $%8.8lX", (lword) ex, 4);
- p->string = s;
- p->expr = ex;
- p->next = 0;
- LEAVE();
- return( p);
- }
- #endif
-
- lexpr *slex_ch( l, r)
- register lexpr huge *l, huge *r;
- {
- ENTER("slex_ch");
- IMESS("Chaining $%8.8lX", (lword) r, 4);
- IMESS(" to $%8.8lX", (lword) l, 4);
- l->next = r;
- LEAVE();
- return( l);
- }
-
-
- int lex_cnt( l)
- register lexpr huge *l;
- {
- register int i = 0;
-
- ENTER("lex_cnt");
- while( l)
- {
- i++;
- l = l->next;
- }
- LEAVE();
- return( i);
- }
-
- /* ---------------------------------------------------------- */
- /* Should be a macro */
- /* Error checking elsewhere */
- /* ---------------------------------------------------------- */
- lexpr *lex_get( l, no)
- register lexpr huge *l;
- register word no;
- {
- ENTER("lex_get");
- while( l && no--)
- l = l->next;
- IMESS("Returning L-expression @$%lx", (lword) l, 4);
- LEAVE();
- return( l);
- }
-
- /* ---------------------------------------------------------- */
- /* Mallocer for lexpressions */
- /* make this mallocing scheme a macro sometime in the future..*/
- /* */
- /* (Keeping the fingers crossed that this is faster than a) */
- /* (simple malloc) */
- /* ---------------------------------------------------------- */
- make_mallocer( lexpr, LEXPMAX, lex_alloc);
-
- /* (*) This isn't correct and fails when branches are made out of
- a buffer (like macro) or the buffer was changed.
- */
-