home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 1
/
crawlyvol1.bin
/
program
/
compiler
/
nasm20b
/
nasm_src
/
exprasm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-19
|
11KB
|
396 lines
/* ---------------------------------------------------------------------- */
/* 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.
*/