home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 1
/
crawlyvol1.bin
/
program
/
compiler
/
nasm20b
/
nasm_src
/
expr.c
< prev
next >
Wrap
Text File
|
1993-01-19
|
20KB
|
622 lines
/* ---------------------------------------------------------------------- */
/* Copyright (C) 1991 by Natuerlich! */
/* 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 OSBIND
#include "code.h"
#define _EXPR_ 1
#include "exprfast.h"
#include "op.h"
#include "ldebug.h"
#if VERSION
ref huge *rp;
expr huge *ep;
lexpr huge *lp;
#endif
#if DEBUG
# define xreturn \
LEAVE(); \
return
#else
# define xreturn return
#endif
exp_m huge *ex_h;
#if ! LINKER
unsigned branch_line;
#endif
#if ! DORECLAIM
# define expr_tryfree( x)
#endif
/* ---------------------------------------------------------- */
/* Entrefern von den der referenz list. Ist mal ein Label */
/* mit ner value versehen worden, kann die ref abgehakt */
/* werden. Danach brauch dieses label nie wieder 'ne ref */
/* ---------------------------------------------------------- */
void entrefer( p)
label huge *p;
{
ref huge *q;
register expr huge *r;
POINTER_CHECK( p);
ENTER("entrefer");
for( q = p->refs; q ; q = q->next)
{
POINTER_CHECK( q);
(r = q->ref)->val = p->val; /* init expression */
POINTER_CHECK( r);
r->label = 0;
#if DEBUG
dump_expr( r);
#endif
#if ! LINKER
branch_line = q->line;
#else
INTEGRITY_CHECK();
#endif
if( r)
recalc( r);
}
p->refs = 0;
LEAVE();
}
#if ! LINKER
# define xe_pcrel( x) ! runnable && e_pcrel( x)
extern int runnable;
static char fwd_loss[] = "label already known as PC-relative";
#else
# define xe_pcrel e_pcrel
#endif
/* ---------------------------------------------------------- */
/* Jaja, mal wat in deutsch. Falls ein Label endlich einen */
/* Wert bekommen hat und inner ref ein entry auf eine expr */
/* pointed, dann wird versucht von da aus soviel wie möglich */
/* von unten nach oben auszuwerten. Hat alles geklappt, dann */
/* kann man endlich die s-expr dahin schreiben, wo sie eigen- */
/* lich längst sein sollte (Backpatching). */
/* Da wir übrigens für jeden Scheiß einen eigenen Mallocer */
/* haben ist es eigentlich kein Problem in NASM65 einen */
/* GarbageCollector einzubauen. Das wärs noch!! */
/* For our befuddled english-speaking readers. The various */
/* MESS messages are gibberish. */
/* ---------------------------------------------------------- */
void recalc( p)
register expr huge *p;
{
register fix huge *f;
register byte huge *q;
ENTER("recalc");
for(;;)
{
#if DEBUG
dump_expr( p);
#endif
if( ! p->fix)
goto nofix;
f = p->zonk.fixp;
POINTER_CHECK( f);
switch( p->fix) /* Mmmh sind wir schon so weit ?? */
{
case FIX_NOTHING:
LEAVE();
return;
case FIX_WCODE :
MESS("Preferring the (1) wonderful");
q = __program + f->poof.block->index + f->index;
POINTER_CHECK( q);
adpoke( q, p->val); /* pack den Wert rein */
LEAVE();
return;
case FIX_DCODE :
MESS("Preferring the wonderful");
q = __program + f->poof.block->index + f->index;
POINTER_CHECK( q);
adbyte( q, p->val); /* pack den Wert rein */
LEAVE();
return;
case FIX_BRANCH :
{
register sword i;
MESS("The worx");
i = p->val - p->aux;
#if ! LINKER
if( i < -128 || i > 127)
nberror("Branch too long", branch_line);
#else
if( i < -128 || i > 127)
nerror("Branch too long");
#endif
q = __program + f->poof.block->index + f->index;
POINTER_CHECK( q);
apoke( q, i); /* pack den Wert rein */
LEAVE();
return;
}
case FIX_ZCODE :
case FIX_SZCODE :
MESS("Admiring very small wonders");
q = __program + f->poof.block->index + f->index;
POINTER_CHECK( q);
if( xe_pcrel( p))
cure_patch( f->imm, p->aux);
if( p->fix == FIX_ZCODE)
{
MESS("+");
apoke( q, p->val); /* pack den Wert rein */
}
else
{
extern byte scrtab[];
MESS("*");
apoke( q, scrtab[ p->val]); /* pack'n Wert rein */
}
MESS("-");
LEAVE();
return;
case FIX_LABEL :
{
register label huge *q = f->poof.label;
MESS("Doing the strange first");
IMESS("p->t @$%lX", (lword) p->zonk.t, 4);
q->val = p->val; /* ok mach's dem */
#if ! LINKER
if( ! runnable && (q->type & L_EQU))
{
nserror( fwd_loss, q->name);
goto skip;
}
#endif
entrefer( q);
skip:
LEAVE();
return;
}
default :
nierror("Invalid fix request");
nofix:
case 0 :
MESS("doing gods work 'ere, yessir!");
p = p->zonk.t;
{
register expr huge *l = p->l,
huge *r = p->r;
if( unvalued( l) || (r && unvalued( r))) /* if L or R */
{
LEAVE();
return; /* USED TO BE A BREAK */
}
do_calc( l, r, p->op & O_BITS);
p->val = l->val;
if( is_lsbmsb( p->op))
p->aux = l->aux;
p->op = l->op;
p->l = p->r = 0; /* leave kids to the garbage man */
}
}
}
}
/* ---------------------------------------------------------- */
/* Do the expression calculation that needs to be done for */
/* statements like LDA #>FOO&[$FF+NMIEN]/2 */
/* (never mind the sense...) */
/* ---------------------------------------------------------- */
void do_calc( l, r, op)
register expr huge *l, huge *r;
int op;
{
#if ! LINKER
extern int runnable;
#endif
static char err[] = "Can't use arithemtic w/relocatable address",
div_zero[] = "You can't / or \\ with zero";
ENTER("do_calc");
POINTER_CHECK( l);
POINTER_CHECK( r);
#if ! LINKER
if( runnable)
if( r)
switch( op)
{
case O_ADD : l->val += r->val; xreturn;
case O_SUB : l->val -= r->val; xreturn;
case O_MUL : l->val *= r->val; xreturn;
case O_DIV : if( ! r->val)
nerror( div_zero);
else
l->val /= r->val;
xreturn;
case O_MOD : if( ! r->val)
nerror( div_zero);
else
l->val %= r->val;
xreturn;
case O_AND : l->val &= r->val; xreturn;
case O_EOR : l->val ^= r->val; xreturn;
case O_OR : l->val |= r->val; xreturn;
case O_EQ : l->val = l->val == r->val; xreturn;
case O_BAND: l->val = l->val && r->val; xreturn;
case O_BOR : l->val = l->val || r->val; xreturn;
case O_NEQ : l->val = l->val != r->val; xreturn;
case O_GEQ : l->val = l->val >= r->val; xreturn;
case O_LEQ : l->val = l->val <= r->val; xreturn;
case O_GT : l->val = l->val > r->val; xreturn;
case O_LT : l->val = l->val < r->val; xreturn;
}
else
switch( op)
{
case O_INC : l->val++; xreturn;
case O_DEC : l->val--; xreturn;
case O_BNOT: l->val = ! l->val; xreturn;
case O_MIN : l->val = - l->val; xreturn;
case O_LSB : l->aux = l->val; /* stands for LSB O_LT */
l->val &= 0xFF;
xreturn;
case O_MSB : l->aux = l->val; /* stands for MSB O_GT */
{
byte huge *p = (byte huge *) &l->val;
#if ! BIGENDIAN
p[1] = *p;
*p = 0;
#else
*p = p[1];
p[1] = 0;
#endif
xreturn;
}
}
#endif
if( r)
switch( (e_pcrel( l) << 1) | e_pcrel( r))
{
case 0 : /* value op value -> value */
MESS("valü op valü");
switch( op)
{
case O_ADD : l->val += r->val; goto iszerop;
case O_SUB : l->val -= r->val;
if( r->val & O_ZEROP)
goto isvalue;
goto issame;
case O_MUL : l->val *= r->val; goto isvalue;
case O_DIV : if( ! r->val)
nerror( div_zero);
else
l->val /= r->val;
goto isvalue;
case O_MOD : if( ! r->val)
nerror( div_zero);
else
l->val %= r->val;
goto isvalue;
case O_AND : l->val &= r->val; goto isvalue;
case O_EOR : l->val ^= r->val; goto isvalue;
case O_OR : l->val |= r->val; goto isvalue;
case O_EQ : l->val = l->val == r->val; goto isvalue;
case O_BAND: l->val = l->val && r->val; goto isvalue;
case O_BOR : l->val = l->val || r->val; goto isvalue;
case O_NEQ : l->val = l->val != r->val; goto isvalue;
case O_GEQ : l->val = l->val >= r->val; goto isvalue;
case O_LEQ : l->val = l->val <= r->val; goto isvalue;
case O_GT : l->val = l->val > r->val; goto isvalue;
case O_LT : l->val = l->val < r->val; goto isvalue;
}
case 1 : /* value op reladr -> ??? */
MESS("valü op reladr");
switch( op)
{
case O_ADD : l->val += r->val; goto ispcrel;
case O_SUB :
case O_MUL :
case O_DIV :
case O_MOD :
case O_AND :
case O_EOR :
case O_OR : nerror( err); l->val = 0; goto isvalue;
case O_EQ : l->val = l->val == r->val; goto isvalue;
case O_BAND: l->val = l->val && r->val; goto isvalue;
case O_BOR : l->val = l->val || r->val; goto isvalue;
case O_NEQ : l->val = l->val != r->val; goto isvalue;
case O_GEQ : l->val = l->val >= r->val; goto isvalue;
case O_LEQ : l->val = l->val <= r->val; goto isvalue;
case O_GT : l->val = l->val > r->val; goto isvalue;
case O_LT : l->val = l->val < r->val; goto isvalue;
}
case 2 : /* reladr op value -> ??? */
MESS("reladr op valü");
switch( op)
{
case O_ADD : l->val += r->val; goto ispcrel;
case O_SUB : l->val -= r->val; goto ispcrel;
case O_MUL :
case O_DIV :
case O_MOD :
case O_AND :
case O_EOR :
case O_OR : nerror( err); l->val = 0; goto isvalue;
case O_EQ : l->val = l->val == r->val; goto isvalue;
case O_BAND: l->val = l->val && r->val; goto isvalue;
case O_BOR : l->val = l->val || r->val; goto isvalue;
case O_NEQ : l->val = l->val != r->val; goto isvalue;
case O_GEQ : l->val = l->val >= r->val; goto isvalue;
case O_LEQ : l->val = l->val <= r->val; goto isvalue;
case O_GT : l->val = l->val > r->val; goto isvalue;
case O_LT : l->val = l->val < r->val; goto isvalue;
}
case 3 :
MESS("reladr op reladr");
switch( op)
{
case O_SUB : l->val -= r->val; goto isvalue;
case O_ADD :
case O_MUL :
case O_DIV :
case O_MOD :
case O_AND :
case O_EOR :
case O_OR : nerror( err); l->val = 0; goto isvalue;
case O_EQ : l->val = l->val == r->val; goto isvalue;
case O_BAND: l->val = l->val && r->val; goto isvalue;
case O_BOR : l->val = l->val || r->val; goto isvalue;
case O_NEQ : l->val = l->val != r->val; goto isvalue;
case O_GEQ : l->val = l->val >= r->val; goto isvalue;
case O_LEQ : l->val = l->val <= r->val; goto isvalue;
case O_GT : l->val = l->val > r->val; goto isvalue;
case O_LT : l->val = l->val < r->val; goto isvalue;
}
default:
nierror("Algorithmic fuck up!");
}
else
if( e_pcrel( l))
switch( op)
{
case O_INC : l->val++; goto ispcrel;
case O_DEC : l->val--; goto ispcrel;
case O_BNOT:
case O_MIN : l->val = 0;
nerror( err);
goto isvalue;
case O_LSB : l->aux = l->val;
l->val &= 0xFF;
goto ispcrel;
case O_MSB : l->aux = l->val;
{
byte huge *p = (byte huge *) &l->val;
#if ! BIGENDIAN
p[1] = *p;
*p = 0;
#else
*p = p[1];
p[1] = 0;
#endif
goto ispcrel;
}
}
else
switch( op)
{
case O_INC : l->val++; goto issame;
case O_DEC : l->val--; goto issame;
case O_BNOT : l->val = ! l->val; goto isvalue;
case O_MIN : nerror( err); l->val = 0; goto isvalue;
case O_LSB : l->val &= 0xFF; goto issame;
case O_MSB :
{
byte huge *p = (byte huge *) &l->val;
#if ! BIGENDIAN
p[1] = *p;
*p = 0;
#else
*p = p[1];
p[1] = 0;
#endif
}
goto isvalue;
}
ispcrel:
l->op = O_PCREL | op;
xreturn;
iszerop:
l->op |= r->op & O_ZEROP;
issame:
l->op = (l->op & O_BITS) | op;
xreturn;
isvalue:
l->op = op;
xreturn;
}
/* ---------------------------------------------------------- */
/* Mallocer for the reflist */
/* */
/* (Keeping the fingers crossed that this is faster than a) */
/* (simple malloc) */
/* For added speed put the first "if" into a #define */
/* ---------------------------------------------------------- */
make_mallocer( ref, REFMAX, ref_alloc);
/* ---------------------------------------------------------- */
/* Mallocer for expressions */
/* */
/* (Keeping the fingers crossed that this is faster than a) */
/* (simple malloc) */
/* ---------------------------------------------------------- */
expr *sexp_alloc()
{
register exp_m huge *p;
extern word _a_expr, _m_expr;
extern lword _s_expr;
#if STATISTICS
_a_expr++;
#endif
if( (p = ex_h) && p->free--)
return( p->tab++);
#if STATISTICS
_m_expr++;
_s_expr = sizeof(exp_m) + EXPMAX * sizeof( expr);
#endif
p = (exp_m huge *) nmalloc( (long) sizeof(exp_m) +
EXPMAX * sizeof( expr));
p->free = (int) EXPMAX - 1;
p->tab = (expr huge *) ((char huge *) p + sizeof( exp_m));
bzero( p->tab, (long) EXPMAX * sizeof( expr)); /* Clear memory */
p->before = (exp_m huge *) ex_h;
ex_h = p;
return( p->tab++);
}
/* ---------------------------------------------------------- */
/* Try to free the expression. This will work easily in cases */
/* like LDA #2 or STA WSYNC (where WSYNC is already known */
/* Unless we are going to use GC we have to do this 'cause I */
/* expect approx. 2 expr/line (makes 60 bytes per line) */
/* We clear it so that it can be properly reused again */
/* ---------------------------------------------------------- */
#if DORECLAIM
void expr_tryfree( e)
register expr huge *e;
{
extern word _efrees, _erfrees;
#if STATISTICS
_efrees++;
#endif
if( e == (ex_h->tab - 1))
{
register lword huge *q = (lword huge *) e;
#if LINKER
# if EXPRSIZE != 26
bzero( q, (long) sizeof( expr));
# else
# if ! LATEPLUSPLUS /* like the good book says/be quick or dead [DLR] */
*(word huge *)q = (word) (*q++ = *q++ = *q++ = *q++ = *q++ = *q++ = 0);
# else
{
register lword zero = 0;
*q++ = zero; *q++ = zero; *q++ = zero; *q++ = zero;
*q++ = zero; *q++ = zero; *(word huge *)q = 0;
}
# endif
# endif
#else
# if EXPRSIZE != 24 || LATEPLUSPLUS
bzero( q, (long) sizeof( expr));
# else
# if ! LATEPLUSPLUS
*q = *q++ = *q++ = *q++ = *q++ = *q++ = 0;
# else
{
register lword zero = 0;
*q++ = zero; *q++ = zero; *q++ = zero; *q++ = zero;
*q++ = zero; *q++ = zero;
}
# endif
# endif
#endif
--ex_h->tab;
++ex_h->free;
#if STATISTICS
_erfrees++;
#endif
if( e->l)
{
if( e->r)
expr_tryfree( e->r);
expr_tryfree( e->l);
}
}
}
#endif
#if DEBUG
#include <stdio.h>
dump_expr( p)
expr huge *p;
{
if( p)
{
fprintf( ESTREAM, "\t\tEXPR @$%8.8lX\n", p);
fprintf( ESTREAM, "\t\tOp='%c' Val=$%4.4X Label=$%8.8X ",
p->op, p->val, p->label);
fprintf( ESTREAM, "Aux=$%4.4X Fixtype=%d\n",
p->aux, p->fix);
fprintf( ESTREAM, "\t\tTop/Left/Rite [ $%8.8lX | $%8.8lX | $%8.8lX ]\n\n",
p->zonk.t, p->l, p->r);
if( ! p->fix)
dump_expr( p->zonk.t);
}
}
#endif
/* [EOF][EOF][EOF][EOF][EOF][EOF][EOF][EOF][EOF][EOF][EOF][EOF][EOF][EOF]
-- Kleiner Diskurs
Deutschland heute (1/1990):
"Ich _weiß_ nicht ob 2+2 4 oder 5 ist
Ich _will_ es auch gar nicht wissen
Aus dieser Art der Fragestellung dringt
doch schon wieder diese rationale
Einstellung zur Umwelt auf, von der wir doch wissen
wo sie uns hin führt.
Es ist doch jetzt einmal an der Zeit zu begreifen,
daß wichtige Veränderungen durchgeführt werden m⇧ssen.
Und wenn die Herren Politiker sich mal wieder
nicht dazu entschließen können, die Probleme der
heutigen Zeit konkret anzufassen, dann muss eben der
Druck von der Strasse kommen" <schluck> <schnief>
<heul>
APPLAUS!!
*/