|
|
/* asmexpr.c -- microsoft 80x86 assembler
** ** microsoft (r) macro assembler ** copyright (c) microsoft corp 1986. all rights reserved ** ** randy nevin ** ** 10/90 - Quick conversion to 32 bit by Jeff Spencer */
#include <stdio.h>
#include <ctype.h>
#include "asm86.h"
#include "asmfcn.h"
#include "asmctype.h"
#include "asmexpr.h"
#include "asmmsg.h"
extern UCHAR opprec []; extern char fValidSym, addplusflagCur;
/*** endstring - check for end of string
* * flag = endstring (); * * Entry delim = string delimiter character * Exit none * Returns TRUE if at end of string * FALSE if not at end of string * Calls error * Note Double occurances of delimiter character are returned as a * single occurance of the delimiter character. */
UCHAR PASCAL CODESIZE endstring () { register UCHAR cc;
if ((cc = PEEKC ()) == 0) { /* End of line before delim */ errorc (E_UEL); return (TRUE); } else if (cc == delim) { /* check for escaped quote character */ SKIPC (); if ((cc = PEEKC ()) != delim) { BACKC (); return (TRUE); } } return (FALSE); }
/*** oblititem - release parse stack record
* * oblititem (arg); * * Entry *arg = parse stack record * Exit parse stack record released * Returns none * Calls free */
VOID PASCAL CODESIZE oblititem ( register DSCREC *arg ){ register char c;
if ((c = arg->itype) == ENDEXPR || c == OPERATOR || c == OPERAND) dfree( (UCHAR *)arg ); }
/*** flteval - Look at ST | ST(i) and create entry
* * flteval (); * * Entry *ptr = parse stack entry * Exit * Returns * Calls */
VOID PASCAL CODESIZE flteval () { *itemptr = emptydsc; /* ST means ST(0) */ /* We are 8087 stack */ itemptr->dsckind.opnd.dtype = M_RCONST | M_FLTSTACK; /* Need + if ST(i) */ addplusflagCur = (PEEKC () == '('); }
/*** createitem - make item entry
* * createitem (itemkind, itemsub, p); * * Entry itemkind = kind of item * itemsub = * *p = activation record * Exit * Returns * Calls * Note If symbol, look further to see if EQU, record name * and do appropriate thing. */
VOID PASCAL CODESIZE createitem ( UCHAR itemkind, UCHAR itemsub ){ register struct psop *pso; /* parse stack operand structure */
switch (itemkind) { case OPERAND: /* Create default record */ itemptr = defaultdsc (); pso = &(itemptr->dsckind.opnd); switch (itemsub) { case ICONST: pso->doffset = val; break; case ISIZE: #ifdef V386
pso->doffset = (long) (SHORT) varsize; #else
pso->doffset = varsize; #endif
pso->s++; /* note for expr evaluator */ break; case IUNKNOWN: pso->dflag = INDETER; break; case ISYM: createsym (); break; } break; case OPERATOR: itemptr = dalloc(); itemptr->dsckind.opr.oidx = opertype; break; } /* Set type of entry */ itemptr->itype = itemkind; }
/*** numeric - evaluate numeric string
* * numeric (count, base, p); * * Entry count = number of characters in string * base = conversion base * *p = activation record * Exit * Returns * Calls */
VOID PASCAL CODESIZE numeric ( SHORT cnt, SHORT base ){ register UCHAR t; register long temp = 0; OFFSET maxInt;
maxInt = (fArth32)? OFFSETMAX: 0xffff;
if (base > 10) for (; cnt; cnt--) { if ((t = MAP (NEXTC ()) - '0') > 9) t -= 'A' - '9' - 1; if (t >= base) errorc (E_NDN); if ((OFFSET)(temp = temp * base + t) > maxInt) errorc (E_DVZ); } else for (; cnt; cnt--) { if ((t = NEXTC () - '0') >= base) errorc (E_NDN);
if ((OFFSET)(temp = temp * base + t) > maxInt) errorc (E_DVZ); } val = temp; }
/*** evalconst - evaluate constant
* * type = evalconst (p); * * Entry *p = parser activation record * Exit numeric item added to parse stack entry * Returns type of item added to parse stack * Calls */
void PASCAL CODESIZE evalconst () { register char cc; register SHORT i = 0; char *endscan, *begscan; SHORT rbase;
begscan = lbufp; while (isxdigit (cc = PEEKC ())) { SKIPC (); i++; } switch (MAP (cc)) { case 'H': rbase = 16; SKIPC (); break; case 'O': case 'Q': rbase = 8; SKIPC (); break; default: BACKC (); switch (MAP (NEXTC ())) { case 'B': rbase = 2; i--; break; case 'D': rbase = 10; i--; break; default: if (cc == '.') errorcSYN (); if (radixescape) rbase = 10; else rbase = radix; break; } break; } endscan = lbufp; lbufp = begscan; numeric (i, rbase); lbufp = endscan; }
/*** evalstring - evaluate quoted string
* * type = evalstring (); * * Entry * Exit new item added to parse stack * Returns type of item added to stack * Calls */
char PASCAL CODESIZE evalstring () { register USHORT i, max;
max = 2; if (cputype & P386) max += 2;
delim = NEXTC (); /* Set delim for string */ i = 0; val = 0; while (!endstring () && i <= max) {
val = (val << 8) + ((UCHAR)NEXTC ()); i++; } if (i == 0) errorc (E_EMS);
else if (i > max) { /* Too long */ while (!endstring ()) SKIPC (); errorcSYN (); } if (PEEKC () == delim) SKIPC ();
createitem (OPERAND, ICONST); return (OPERAND); }
/*** getitem - get next item on line
* * getitem (p); * * Entry *p = activation record * Exit *itemptr = description of item * Returns * Calls */
char PASCAL CODESIZE getitem ( struct ar *p ){ register char cc; #ifdef FIXCOMPILERBUG
char cc1; #endif
if (fValidSym) return (evalalpha (p));
/* The compiler bug looses the correct value for cc when optimization is
turned on. This in turn caused an exception to occure near getitem+1C0. The bogus code below sidesteps the problem. */ #ifdef FIXCOMPILERBUG // This was put in to get around a MIPS compiler bug(12/3/90)
cc1 = skipblanks(); if (ISTERM (cc1)) return (ENDEXPR); cc = cc1; #else
if (ISTERM (cc = skipblanks())) return (ENDEXPR); #endif
if (LEGAL1ST (cc)) return (evalalpha (p));
/* token is not alpha string or .string (.TYPE) operator */
if (ISOPER (cc)) { SKIPC (); switch (cc) { case '(': opertype = OPLPAR; break; case '+': opertype = OPPLUS; break; case '-': opertype = OPMINUS; break; case '*': opertype = OPMULT; break; case '/': opertype = OPDIV; break; case ')': opertype = OPRPAR; break; case '.': errorcSYN (); opertype = OPDOT; break; case ',': /* should never get here, for density */ break; default: if (cc == '[') opertype = OPLBRK; else if (cc == ']') opertype = OPRBRK; else if (cc == ':') opertype = OPCOLON; break; } operprec = opprec [opertype]; createitem (OPERATOR, ISYM); return (OPERATOR); } else if (isdigit (cc)){
evalconst (); createitem (OPERAND, ICONST); return (OPERAND); }
else if ((cc == '"') || (cc == '\'')) /* String may be made into constant if <=2 */ return (evalstring ()); else return (ENDEXPR); }
/*** defaultdsc - create a default parse stack entry
* * ptr = defaultdsc (); * * Entry none * Exit none * Returns *ptr = default parse stack entry * Calls malloc */
DSCREC * PASCAL CODESIZE defaultdsc () { register DSCREC *valu;
valu = dalloc(); *valu = emptydsc; return (valu); }
VOID PASCAL makedefaultdsc () { register struct psop *p; /* parse stack operand structure */
emptydsc.itype = OPERAND; p = &emptydsc.dsckind.opnd; p->dtype = xltsymtoresult[REC]; p->dflag = KNOWN; p->fixtype = FCONSTANT; }
/*** checksegment - see if sreg is correct segment register for variable
* * routine (); * * Entry * Exit * Returns * Calls */
char PASCAL CODESIZE checksegment ( UCHAR sreg, register struct ar *p ){ register SYMBOL FARSYM *segctx; register SYMBOL FARSYM *segptr;
if (sreg != NOSEG) { /* NOseg never found */
/* Current Sreg assume */ segctx = regsegment[sreg];
/* Assume looking for left arg to : */ segptr = p->curresult->dsckind.opnd.dcontext;
if (!segptr) /* If no :, use segment */ segptr = p->curresult->dsckind.opnd.dsegment;
if (segptr && segctx) {
#ifndef FEATURE
if (segctx == pFlatGroup) /* flat space matchs all */ goto found; #endif
/* if same segorg or ptr is segment ... and Same group */
if (segctx == segptr ||
(segptr->symkind == SEGMENT && segctx == segptr->symu.segmnt.grouptr)) { found: p->segovr = sreg; p->curresult->dsckind.opnd.dcontext = segctx;
return (TRUE); } } } return (FALSE); }
/*** findsegment - find segment for variable
* * routine (); * * Entry * Exit * Returns * Calls */
VOID PASCAL CODESIZE findsegment ( UCHAR dseg, register struct ar *p ){ register struct psop *pso; /* parse stack operand structure */
pso = &(p->curresult->dsckind.opnd); if ((M_DATA & p->rstype) && (pso->dsegment || pso->dcontext) && p->linktype != FCONSTANT && pso->fixtype != FOFFSET && emittext) { /* Should find segment */ if (!checksegment (dseg, p)) { /* If not in default */ checksegment (CSSEG, p); checksegment (ESSEG, p); checksegment (SSSEG, p); checksegment (DSSEG, p); #ifdef V386
if (cputype&P386) { checksegment (FSSEG, p); checksegment (GSSEG, p); } #endif
if (p->segovr == NOSEG) /* If not found,UNKNOWN */ p->segovr = NOSEG+1; } } }
/*** exprop - process expression operator
* * exprop (p); * * Entry * Exit * Returns * Calls */
VOID PASCAL CODESIZE exprop ( register struct ar *p ){ register struct dscrec *pTop = itemptr;
p->curprec = (unsigned char)operprec; /* Get prec of new operator */
if (!p->lastitem) /* start */ pTop->prec = 0; else pTop->prec = p->lastitem->prec;
switch (pTop->dsckind.opr.oidx) {
case OPRPAR:
if (--p->parenlevel >= 0) break;
/* Unmatched right paren is from count dup (xx) */
p->parenlevel = 0; BACKC (); dfree((char *)pTop); p->exprdone = TRUE; return;
case OPRBRK: if (--p->bracklevel >= 0) break;
p->exprdone = TRUE; return;
case OPLPAR: p->parenlevel++; goto leftComm;
case OPLBRK:
p->bracklevel++; leftComm: /* See if could have no oper in which case kludge + */
if ((p->lastitem || p->addplusflag) && p->lastitem->itype != OPERATOR) {
/* make + OPERATOR */ opertype = OPPLUS; createitem (OPERATOR, ISYM);
p->bracklevel--; exprop(p); p->bracklevel++; p->lastprec = 6; } break;
default: pTop->prec = p->curprec; break; } p->unaryflag = FALSE;
if (pTop->dsckind.opr.oidx == OPPLUS || pTop->dsckind.opr.oidx == OPMINUS) {
if (!p->lastitem) p->unaryflag = TRUE;
else if (p->lastitem->itype == OPERATOR)
p->unaryflag = !(p->lastitem->dsckind.opr.oidx == OPRPAR || p->lastitem->dsckind.opr.oidx == OPRBRK); }
if (p->unaryflag || (p->curprec > p->lastprec && !(pTop->dsckind.opr.oidx == OPRPAR || pTop->dsckind.opr.oidx == OPRBRK))) {
/* Push OPERATOR */
pTop->previtem = p->lastitem; p->lastitem = pTop;
if (p->unaryflag) {
if (pTop->dsckind.opr.oidx == OPPLUS)
pTop->dsckind.opr.oidx = OPUNPLUS; else pTop->dsckind.opr.oidx = OPUNMINUS;
pTop->prec = p->lastprec; p->lastprec = 10; } else p->lastprec = p->curprec;
if (pTop->dsckind.opr.oidx == OPLPAR || pTop->dsckind.opr.oidx == OPLBRK)
p->lastprec = 0; } else /* Evaluate top OPERATOR */
evaluate (p); }
/*** forceimmed - generate error if value is not immediate
* * routine (); * * Entry * Exit * Returns * Calls */
VOID PASCAL CODESIZE forceimmed ( register DSCREC *dsc ){ if (dsc->dsckind.opnd.mode != 4) /* Must be constant */ errorc (E_CXP); }
/*** exprconst - check for constant expression
* * routine (); * * Entry * Exit * Returns * Calls */
OFFSET PASCAL CODESIZE exprconst () { char sign; register OFFSET ret;
ret = exprsmag(&sign);
if (sign) {
/* change to simple unary minus
* pso->doffset = 65535 - ret + 1; */
ret = -(long)ret;
if (!fArth32) ret &= 0xffff; }
return (ret); }
/*** exprsmag - evaluate constant expression and return sign/magnitude
* * ushort = exprsmag (sign, magnitude); * * Entry none * Exit sign = TRUE if sign of result is set * magnitude = magnitude of result * Returns 16 bit integer result * Calls expreval */
OFFSET PASCAL CODESIZE exprsmag ( char *sign ){ register struct psop *pso; /* parse stack operand structure */ register OFFSET ret; DSCREC *dsc;
dsc = expreval (&nilseg); forceimmed (dsc); pso = &(dsc->dsckind.opnd); *sign = pso->dsign; ret = pso->doffset;
dfree ((char *)dsc ); return (ret); }
|