home *** CD-ROM | disk | FTP | other *** search
- /* ---------------------------------------------------------------------- */
- /* 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!!
- */
-
-