|
|
/* asmchksp.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 <float.h>
#include <stdlib.h>
#include <math.h>
#include <errno.h>
#include "asm86.h"
#include "asmfcn.h"
#include "asmctype.h"
#include "asmexpr.h"
#include "asmopcod.h"
extern UCHAR opprec []; VOID CODESIZE setdispmode(struct ar *); SHORT CODESIZE simpleExpr (struct ar *); char fValidSym;
/*** createsym - make item entry for symbol
* * createsym (itemkind, 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 createsym ( ){ register struct psop *pso; /* parse stack operand structure */ register SYMBOL FARSYM *symp = symptr; char aliasAttr = (char) 0xFF; struct dscrec *itemptrT;
pso = &(itemptr->dsckind.opnd); if (!symp) { undefined: pso->dflag = UNDEFINED; pso->dtype = M_CODE | M_FORTYPE; return; }
if (symp->symkind == EQU && symp->symu.equ.equtyp == ALIAS) {
aliasAttr = symptr->attr;
symptr = symp = chasealias (symp); if (!symp) goto undefined; } else if (symp->symkind == REC && (PEEKC () == '<')) {
itemptrT = itemptr; pso->doffset = recordparse (); itemptr = itemptrT; return; }
/* Assume symbol is defined */
if (M_XTERN & symp->attr) pso->dflag = XTERNAL;
else if (!(M_DEFINED & symp->attr)) { /* Cause error if undefined */ pso->dflag = UNDEFINED; errorn (E_SND); } else if (!(M_BACKREF & (symp->attr & aliasAttr))) pso->dflag = FORREF; else pso->dflag = KNOWN;
if (M_MULTDEFINED & symp->attr) errorc (E_RMD);
pso->dsize = symp->symtype; pso->dlength = symp->length; pso->doffset = symp->offset; pso->dcontext = (SYMBOL FARSYM *)NULL;
if ((symp->symkind == EQU) && (symp->symu.equ.equtyp == EXPR)) { pso->dsign = symp->symu.equ.equrec.expr.esign; pso->dcontext = symp->symu.equ.equrec.expr.eassume; } if (1 << symp->symkind & (M_CLABEL | M_PROC)) if (isCodeLabel(symp) && emittext) pso->dcontext = symp->symu.clabel.csassume;
if (1 << symp->symkind & (M_REGISTER | M_GROUP | M_SEGMENT)) pso->dsegment = symp; else pso->dsegment = symp->symsegptr;
if ((M_XTERN & symp->attr) || (1 << symp->symkind & (M_REC | M_RECFIELD))) pso->dextptr = symp;
pso->dtype = xltsymtoresult[symp->symkind]; if (symp->symkind == CLABEL || symp->symkind == EQU && pso->dsegment)
if (isCodeLabel(symp)) pso->dtype = M_CODE; else pso->dtype = M_DATA;
if (!(M_BACKREF & (symp->attr & aliasAttr))) pso->dtype |= M_FORTYPE;
if ((pso->dtype == xltsymtoresult[REGISTER]) && (symp->symu.regsym.regtype == STKREG)) { /* 8087 support */ flteval (); }
}
/*** evalalpha - evaluate alpha
* * type = evalpha (p); * * Entry p = pointer to parser activation record * Exit alpha item added to parse stack * Returns type of item added to parse stack * Calls */
UCHAR PASCAL CODESIZE evalalpha ( register struct ar *p ){ register struct psop *pso; /* parse stack operand entry */
if (! fValidSym) getatom ();
if (fValidSym == 2 || symsearch ()){
fValidSym = 0;
if (symptr->symkind == EQU && symptr->symu.equ.equtyp == TEXTMACRO) {
#ifdef BCBOPT
goodlbufp = FALSE; #endif
expandTM (symptr->symu.equ.equrec.txtmacro.equtext);
return (getitem (p)); } else if (symptr->symkind == CLASS) errorn( E_IOT ); else { addplusflagCur = FALSE; createitem (OPERAND, ISYM); p->addplusflag = addplusflagCur;
return (OPERAND); } } fValidSym = 0;
if (fnoper ()) if ((opertype == OPNOTHING) || (opertype == OPDUP)) { lbufp = begatom; dupflag = (opertype == OPDUP); return (ENDEXPR); } else { createitem (OPERATOR, ISYM); return (OPERATOR); } else if (*naim.pszName == '.') { lbufp = begatom + 1; operprec = opprec[opertype = OPDOT]; createitem (OPERATOR, ISYM); return (OPERATOR); } else if (fnsize ()) { createitem (OPERAND, ISIZE); return (OPERAND); } else if ((*naim.pszName == '$') && (naim.pszName[1] == 0)) { itemptr = defaultdsc (); pso = &(itemptr->dsckind.opnd); /* Create result entry */ pso->doffset = pcoffset; pso->dsegment = pcsegment; pso->dcontext = pcsegment; pso->dtype = M_CODE; pso->dsize = CSNEAR; return (OPERAND); } else if ((*naim.pszName == '?') && (naim.pszName[1] == 0)) { createitem (OPERAND, IUNKNOWN); if (emittext) errorc (E_UID); return (OPERAND); } else { symptr = (SYMBOL FARSYM *)NULL; error (E_SND, naim.pszName); /* common pass1 error */ createitem (OPERAND, ISYM); return (OPERAND); } }
/* Dup tree is organized left to right horizonatally for each
item in a DUP list at the same level( i. e. 5 DUP(1,2,3) ). This is considered the 'list' part. Any item in the list may be another DUP header instead of a data entry, in which case you go down a level and have another list. */
/*** scanlist - scan duprec list
* * scanlist (ptr, disp); * * Entry *ptr = duprec entry * disp = function to execute on entry * Exit depends upon function * Returns none * Calls */
VOID PASCAL CODESIZE scanlist ( struct duprec FARSYM *ptr, VOID (PASCAL CODESIZE *disp) (struct duprec FARSYM *) ){ struct duprec FARSYM *iptr; struct duprec FARSYM *dptr;
nestCur++;
while (ptr) { /* set pointer to next entry */ iptr = ptr->itemlst; if (ptr->dupkind == NEST) /* dptr = pointer to duplicated item */ dptr = ptr->duptype.dupnext.dup; else dptr = (struct duprec FARSYM *)NULL; if (!(ptr->rptcnt == 1 && ptr->itemcnt) || !(strucflag && initflag)) (*disp) (ptr); if (dptr) { /* Go thru DUP list */ scanlist (dptr, disp); if (displayflag) if (!(ptr->rptcnt == 1 && ptr->itemcnt) || !(strucflag && initflag)) enddupdisplay (); } if (ptr == iptr) /* corrupt data structure */ break;
/* Handle next in list */ ptr = iptr; } nestCur--; }
/*** calcsize - calculate size of DUP list
* * value = calcsize (ptr); * * Entry *ptr = dup list * Exit none * Returns size of structure * Calls calcsize */
OFFSET PASCAL CODESIZE calcsize ( struct duprec FARSYM *ptr ){ unsigned long clsize = 0, nextSize, limit; struct duprec FARSYM *p;
limit = (wordsize == 2)? 0x10000: 0xffffffff;
for (p = ptr; p; p = p->itemlst) {
if (p->dupkind == NEST) { /* Process nested dup */ nextSize = calcsize (p->duptype.dupnext.dup);
if (nextSize && (p->rptcnt > limit / nextSize)) errorc(E_VOR);
nextSize *= p->rptcnt; } else { if (p->dupkind == LONG) { nextSize = p->duptype.duplong.llen; resvspace = FALSE; } else { /* Size is that of directive */ nextSize = p->duptype.dupitem.ddata->dsckind.opnd.dsize; if (p->duptype.dupitem.ddata->dsckind.opnd.dflag != INDETER) resvspace = FALSE; } }
if (nextSize > limit - clsize) errorc(E_VOR);
clsize += nextSize;
if (p == p->itemlst) /* corrupt data structure */ break; } return (clsize); }
/*** datascan - scan next data item
* * datascan (); * * Entry * Exit * Returns * Calls */
struct duprec FARSYM * PASCAL CODESIZE datascan ( struct datarec *p ){ register char cc; struct dsr a;
if (ISBLANK (PEEKC ())) skipblanks ();
a.initlist = a.flag = a.longstr = FALSE;
/* check for textmacro substitution */ a.dirscan = lbufp; xcreflag--; getatom ();
if (fnsize()) goto isASize;
if (symsrch ()) if (symptr->symkind == EQU && symptr->symu.equ.equtyp == TEXTMACRO) {
expandTM (symptr->symu.equ.equrec.txtmacro.equtext); a.dirscan = begatom; } else if (symptr->symkind == STRUC) { isASize: switchname(); getatom();
if (tokenIS("ptr")) { switchname(); p->type = fnPtr(datadsize[optyp - TDB]);
if (p->type > 512) goto noRescan; } } lbufp = a.dirscan; noRescan:
xcreflag++; if ((optyp == TDB && ((cc = PEEKC ()) == '\'' || cc == '"')) && !initflag)
datadb (&a);
if (optyp != TDB && optyp != TDW) /* entry can be DD | DQ | DT */ parselong (&a);
if (!a.longstr) datacon (&a);
else if (strucflag && initflag) errorc( E_OIL );
if (!a.flag) { if (!strucflag || !initflag) { a.dupdsc->rptcnt = 1; a.dupdsc->itemcnt = 0; a.dupdsc->itemlst = (struct duprec FARSYM *)NULL; } } return (a.dupdsc); }
/*** realeval - evaluate IEEE 8087 floating point number
* * realeval (p); * * Entry * Exit * Returns * Calls */
struct ddecrec { USHORT realv[5]; USHORT intgv[2]; USHORT cflag; };
#if !defined FLATMODEL
// Because this is called so seldom and it's so slow anyhow put it in
// a far segment.
# pragma alloc_text (FA_TEXT, realeval)
#endif
VOID PASCAL realeval ( struct realrec *p ){ register char cc, *cp; char numtext[61]; struct ddecrec fltres; #if !defined NOFLOAT
float *pTmpFloat; double *pTmpDouble; double TmpDouble; double AbsDouble; long double *pTmpLongDouble; char *pEnd; #endif
cp = numtext; /* Copy the number - must have at least 1 char */ *cp++ = NEXTC (); /* get leading sign or 1st char */ do { cc = NEXTC (); *cp++ = cc; } while (isdigit (cc) || cc == '.'); if ((cc = MAP (cc)) == 'E') { /* Get the next + - or digit */ *cp++ = NEXTC (); /* Copy the exponent over */ do { cc = NEXTC (); *cp++ = cc; } while (isdigit (cc)); } *cp = '\0'; BACKC ();
// NOFLOAT is used when there are no floating point libraries available
// Any masm version produced with NOFLOAT defined will cause a divide
// by 0 error to be logged when a real number initializer is used.
#if defined NOFLOAT
ferrorc( E_DVZ ); #else
switch(optyp) { case TDD: errno = 0; TmpDouble = strtod( numtext, &pEnd ); if( errno == ERANGE ){ ferrorc( E_DVZ ); } AbsDouble = TmpDouble > 0 ? TmpDouble : -TmpDouble; if( AbsDouble > FLT_MAX || AbsDouble < FLT_MIN ){ ferrorc( E_DVZ ); }else{ // Convert the double to a float (8 byte to 4 byte)
pTmpFloat = (float *)(p->num); *pTmpFloat = (float)TmpDouble; } break; case TDQ: pTmpDouble = (double *)(p->num); errno = 0; *pTmpDouble = strtod( numtext, &pEnd ); if( errno == ERANGE ){ ferrorc( E_DVZ ); } break; case TDT: pTmpLongDouble = (long double *)(p->num); errno = 0; *pTmpLongDouble = _strtold( numtext, &pEnd ); if( errno == ERANGE ){ ferrorc( E_DVZ ); } break; default: ferrorc(E_TIL); break; } #endif
}
/*** simpleExpr - short curcuit expression evaluator
* */
/* following are three protype parse records for the three simple
* expressions that we simpleExpr understands */
#ifdef EXPR_STATS
long cExpr, cHardExpr; extern char verbose;
#endif
#define SHORT_CIR 1
#if SHORT_CIR
DSCREC consDS = {
NULL, 0, 0, /* previtem, prec, type */ { NULL, NULL, NULL, 0, /* dsegment, dcontext, dexptr, dlength */ 6, /* rm */ 1 << RCONST, /* dtype */ 0, 0, /* 0, */ /* doffset, dsize, type */ 4, /* mode */ FALSE, FALSE, FALSE, /* w, s, sized*/ NOSEG, /* seg */ KNOWN, /* dflag */ FCONSTANT, /* fixtype */ FALSE /* dsign */ } };
DSCREC regDS = {
NULL, 0, 0, /* previtem, prec, type */ { NULL, NULL, NULL, 0, /* dsegment, dcontext, dexptr, dlength */ 0, /* rm */ 1 << REGRESULT, /* dtype */ 0, 2, /* 0, */ /* doffset, dsize, type */ 3, /* mode */ TRUE, FALSE, TRUE, /* w, s, sized*/ NOSEG, /* seg */ KNOWN, /* dflag */ FCONSTANT, /* fixtype */ FALSE /* dsign */ } };
DSCREC labelDS = { NULL, 0, 0, /* previtem, prec, type */ { NULL, NULL, NULL, 0, /* dsegment, dcontext, dexptr, dlength */ 6, /* rm */ 1 << DATA, /* dtype */ 0, 2, /* 0, */ /* doffset, dsize, type */ 0, /* mode */ TRUE, FALSE, TRUE, /* w, s, sized*/ NOSEG, /* seg */ KNOWN, /* dflag */ FNONE, /* fixtype */ FALSE /* dsign */ } };
#if !defined XENIX286 && !defined FLATMODEL
#pragma check_stack-
#endif
SHORT CODESIZE simpleExpr ( struct ar *pAR ){ register DSCREC *pDES; /* parse stack operand structure */ register char kind; char cc; char *lbufSav;
fValidSym = noexp = 0; lbufSav = lbufp;
#ifdef EXPR_STATS
cExpr++; #endif
if (ISTERM (cc = skipblanks())) {
notSimple: lbufp = lbufSav; notSimpleLab:
#ifdef EXPR_STATS
cHardExpr++; #endif
return (FALSE); }
if (LEGAL1ST (cc)){
getatom (); fValidSym++; /* 1 means valid token */
if (! (ISTERM (PEEKC()) || PEEKC() == ',')){
#ifdef EXPR_STATS
if (verbose && pass2) fprintf(stdout, "Not a Simple Expression: %s\n", lbufSav); #endif
goto notSimpleLab; }
if (symsearch ()){
fValidSym++; /* 2 means valid symptr */
if ((kind = symptr->symkind) == REGISTER && (symptr->symu.regsym.regtype != STKREG)) {
pAR->curresult = pDES = dalloc(); *pDES = regDS;
pDES->dsckind.opnd.dsegment = symptr;
switch (symptr->symu.regsym.regtype) {
case BYTREG: pDES->dsckind.opnd.dsize = 1; pDES->dsckind.opnd.w--; pDES->dsckind.opnd.s++; break; #ifdef V386
case CREG: if (opctype != PMOV) errorc(E_WRT);
case DWRDREG: pDES->dsckind.opnd.dsize = 4; break; #endif
} pDES->dsckind.opnd.rm = (unsigned short)symptr->offset; return(TRUE); }
else if (kind == CLABEL || kind == PROC || kind == DVAR || (kind == EQU && symptr->symu.equ.equtyp == EXPR)) {
pAR->curresult = pDES = dalloc(); *pDES = labelDS;
pDES->dsckind.opnd.doffset = symptr->offset; pDES->dsckind.opnd.dsegment = symptr->symsegptr;
if (kind == EQU) {
if (! (pDES->dsckind.opnd.dcontext = symptr->symu.equ.equrec.expr.eassume) && ! pDES->dsckind.opnd.dsegment){
val = pDES->dsckind.opnd.doffset;
*pDES = consDS; pDES->dsckind.opnd.dsign = symptr->symu.equ.equrec.expr.esign;
if (!(M_BACKREF & symptr->attr)){ pDES->dsckind.opnd.dtype |= M_FORTYPE; pDES->dsckind.opnd.dflag = FORREF; }
if (M_XTERN & symptr->attr){ pDES->dsckind.opnd.dflag = XTERNAL; pDES->dsckind.opnd.dextptr = symptr; return (TRUE); }
goto constEqu; } }
pDES->dsckind.opnd.dsize = symptr->symtype; pDES->dsckind.opnd.dlength = symptr->length;
if (M_XTERN & symptr->attr){ pDES->dsckind.opnd.dflag = XTERNAL; pDES->dsckind.opnd.dextptr = symptr; } else if (!(M_DEFINED & symptr->attr)) { /* Cause error if undefined */ pDES->dsckind.opnd.dflag = UNDEFINED; pDES->dsckind.opnd.dsize = wordsize; pDES->dsckind.opnd.dtype = M_CODE; errorn (E_SND); } else if (!(M_BACKREF & symptr->attr)){ pDES->dsckind.opnd.dflag = FORREF; pDES->dsckind.opnd.dtype |= M_FORTYPE; } if (M_MULTDEFINED & symptr->attr) errorc (E_RMD);
if (pDES->dsckind.opnd.dsize < 2) { pDES->dsckind.opnd.w--; pDES->dsckind.opnd.s++; } #ifdef V386
if (wordsize == 4 || (symptr->symsegptr && symptr->symsegptr->symu.segmnt.use32 == 4)) { pDES->dsckind.opnd.mode = 5; pDES->dsckind.opnd.rm--; /* = 5 */ } #endif
if (isCodeLabel(symptr)){
pDES->dsckind.opnd.dtype = (unsigned short) (pDES->dsckind.opnd.dtype & ~M_DATA | M_CODE);
if (emittext && kind != EQU) pDES->dsckind.opnd.dcontext = symptr->symu.clabel.csassume; } else {
pAR->linktype = FNONE; pAR->rstype = M_DATA; findsegment ((UCHAR)pAR->index, pAR);
pDES->dsckind.opnd.seg = pAR->segovr; } pDES->dsckind.opnd.fixtype = FOFFSET;
return(TRUE); } #ifdef EXPR_STATS
if (verbose && pass2) fprintf(stdout, "Not a Simple Label: %s\n", naim.pszName); #endif
} goto notSimpleLab; }
if (isdigit (cc)){
evalconst (); /* value in global val */ if (! (ISTERM (skipblanks()) || PEEKC() == ',')) goto notSimple;
pAR->curresult = pDES = dalloc(); *pDES = consDS; constEqu: if (pDES->dsckind.opnd.dflag != FORREF) {
if (val < 128) pDES->dsckind.opnd.s++;
else {
#ifdef V386 /* only consider 16 bits */
if (wordsize == 2) pDES->dsckind.opnd.s = (char)((USHORT)(((USHORT) val & ~0x7F ) == (USHORT)(~0x7F))); else #endif
pDES->dsckind.opnd.s = ((val & ~0x7F ) == ~0x7F); } }
pDES->dsckind.opnd.doffset = val;
if (val > 256){ pDES->dsckind.opnd.w++; pDES->dsckind.opnd.sized++; }
return(TRUE); } goto notSimple; }
#if !defined XENIX286 && !defined FLATMODEL
#pragma check_stack+
#endif
#endif
/*** expreval - expression evaluator
* * routine (); * * Entry * Exit * Returns * Calls */
DSCREC * PASCAL CODESIZE expreval ( UCHAR *dseg ){ register struct psop *psoi; /* parse stack operand structure */ struct ar a; SHORT i;
dupflag = FALSE; nilseg = NOSEG; a.segovr = NOSEG; a.index = *dseg;
#if SHORT_CIR
if (simpleExpr(&a)){ fSecondArg++; return (a.curresult); } #endif
a.exprdone = a.addplusflag = FALSE; a.lastitem = (DSCREC *)NULL;
/* No parens or [] yet, Lowest precedence, haven't found anything yet */
a.parenlevel = a.bracklevel = a.lastprec = 0; a.index = 0; a.base = 0; noexp = 1;
/* Start expression loop */
while (!a.exprdone){
switch (getitem (&a)) {
case OPERAND: itemptr->previtem = a.lastitem; a.lastitem = itemptr; itemptr->prec = a.lastprec; noexp = 0; break;
case OPERATOR: exprop (&a); noexp = 0; break;
case ENDEXPR: a.exprdone = TRUE; } }
/* Do some easy error checking */
if (a.parenlevel + a.bracklevel) errorc (E_PAR);
itemptr = (DSCREC *)NULL;
if (!a.lastitem) a.curresult = defaultdsc (); else evaluate (&a); /* Evaluate whole expression */
psoi = &(a.curresult->dsckind.opnd);
a.rstype = (unsigned short)(psoi->dtype & (M_CODE|M_DATA|M_RCONST|M_REGRESULT|M_SEGRESULT|M_GROUPSEG));
a.linktype = FNONE; /* Leave bits for link type */ a.vmode = 4; psoi->sized = FALSE; psoi->w = TRUE; psoi->s = FALSE;
#ifdef V386
if ((a.base|a.index) & 0xf8) { /* have 386 index or base */
if (a.index) {
if (!(a.index&8)) errorc(E_OCI);
if ((a.index&7) == 4) errorc(E_DBR);
a.vmode = 10; /* two register modes */
/* here we are putting what goes into the SIB
* into a.index. from here on, we have to * to a.index with masks, so we dont trash * the high order stuff * the encoding we derive this from is tricky-- * see regcheck() for details -Hans * stick in the index register */
i = (a.index&7) << 3;
/* stick in base. ebp if there is none */
if (a.base){
if (!(a.base&8)) errorc(E_OCI);
i |= (a.base&7); } else { i |= 5; a.vmode = 8; } /* stick in scale. *1 if there is none */
if (a.index&0x70) i |= ((a.index & 0x70) - 0x10) << 2;
a.index = i; } else if (a.base == (4|8)) { /* esp */ a.vmode = 10; a.index = 044; } else { /* one register modes */
a.vmode = 7; a.index = (unsigned short)(a.base & 7); } /* note dirty way of checking for BP or SP */
if (*dseg != ESSEG && (a.base&6) == 4) *dseg = SSSEG; } else
#endif /* V386 */
if (a.base + a.index){ /* Have some index or base */
a.vmode = 2;
/* Assume offset is direct */
if (a.base && a.index) /* Have both */ a.index = (unsigned short)(a.base - 3 + a.index - 6);
else if (a.base) /* Have base address */ a.index = (a.base == 3)? 7: 6;
else /* Have only index address*/ a.index = a.index - 2;
if (1 << a.index & (1 << 2 | 1 << 3 | 1 << 6) && *dseg != ESSEG) *dseg = SSSEG; } /* No indexing */
else if (a.rstype == xltsymtoresult[REGISTER]) {
/* Have register */
a.vmode = 3; psoi->sized = TRUE;
switch(psoi->dsegment->symu.regsym.regtype) {
case BYTREG: psoi->dsize = 1; goto mask7;
case WRDREG: case INDREG: case SEGREG: case STKREG: psoi->dsize = 2; goto mask7; #ifdef V386
case CREG:/* probably should turn this into memref if !386P */ if (opctype != PMOV) errorc(E_WRT); psoi->dsize = 4; a.index = (unsigned short)psoi->doffset; break;
case DWRDREG: psoi->dsize = 4; #endif
mask7: if ((psoi->doffset > 7) || psoi->dsign) errorc (E_IRV);
/* Set register # */
a.index = (unsigned short)(psoi->doffset & 7); break;
default: errorc(E_WRT); break; } } /* Might be segment result */
else if (a.rstype & (M_SEGRESULT | M_GROUPSEG)) {
/* we get here if we had offset operator with segment or group
* or offset operator with data and rconst * Result is SEG. Rconst if OFFSET grp:var */
if (a.rstype & (M_SEGRESULT | M_EXPLOFFSET)) { psoi->dsize = 2; /* Leave size if not OFFSET or */ psoi->sized = TRUE; } a.linktype = FOFFSET; if ((M_GROUPSEG & a.rstype) && (psoi->fixtype != FOFFSET)) { a.linktype = FGROUPSEG; setdispmode(&a); } if ((a.vmode == 4) && (psoi->fixtype != FOFFSET)) a.linktype = FBASESEG; } else a.index = 6;
/**** Evaluate offset part of result ****/
a.base = psoi->doffset; if (psoi->fixtype == FOFFSET || a.vmode == 2 || a.vmode == 7 || a.vmode == 10)
psoi->dtype |= M_RCONST;
/* [] implicit const */
if ((M_RCONST & psoi->dtype) && (a.linktype == FNONE) && (a.vmode != 3)) {
/* Need to make sure <s> not set if memory */
if (!(psoi->dflag & (FORREF|UNDEFINED|XTERNAL)) && !psoi->dsegment && psoi->fixtype == FCONSTANT) {
psoi->s = (a.base < 128 && !psoi->dsign) || (a.base < 129 && psoi->dsign);
if (!(psoi->s || psoi->dsign))
#ifdef V386 /* only consider 16 bits */
if (wordsize == 2 && a.vmode < 6) psoi->s = (char)((USHORT)(((USHORT) a.base & ~0x7F ) == (USHORT)(~0x7F))); else #endif
psoi->s = ((a.base & ~0x7F ) == ~0x7F); }
psoi->w = (psoi->dsign && a.base > 256) || (a.base > 255 && !psoi->dsign);
if (a.vmode != 4) {
/* This is offset for index */ /* If value not known, don't allow shortning to mode 1 */ /* Word or byte offset */
if (!(M_FORTYPE & psoi->dtype) && psoi->dsegment == 0 && psoi->s && a.vmode != 8) {
/* one byte offset */
a.vmode--; if (a.base == 0 && psoi->dflag == KNOWN) {
/* perhaps 0 byte offset */
switch(a.vmode) {
case 1: if (a.index != 6) a.vmode--; break; case 6: case 9: if ((a.index&7) != 5) a.vmode--; break; } } } }
else { /* Must be immediate */
if (!psoi->dsegment && !psoi->dcontext) a.linktype = FCONSTANT;
/******????? I'm not exactly sure why
* we think we have a size yet. seems * to me mov BYTE PTR mem,500 is legal */
psoi->sized = psoi->w;
if (!(M_EXPLOFFSET & psoi->dtype) && psoi->dcontext) {
/* Have segreg:const */
a.vmode = 0; if (!(M_PTRSIZE & psoi->dtype) && psoi->dsize == 0) psoi->dsize = wordsize; } } } else if ((a.rstype & (M_DATA | M_CODE)) && a.linktype == FNONE) {
/* Have direct mode and Want offset */
a.linktype = FOFFSET; setdispmode(&a);
if (psoi->dsize == CSFAR && emittext) a.linktype = FPOINTER; }
if (psoi->dflag == UNDEFINED) {
/* Forward ref pass 1 */
if (psoi->dsize == 0) psoi->dsize = wordsize;
if (!(M_RCONST & psoi->dtype) && a.vmode == 4) setdispmode(&a); }
if (!psoi->dsegment || (1 << a.linktype & (M_FNONE|M_FOFFSET|M_FPOINTER|M_FGROUPSEG))){
if (psoi->dcontext && psoi->dcontext->symkind == REGISTER)
/* Have reg:var */
if (psoi->dcontext->symu.regsym.regtype == SEGREG) {
/* Have segreg:VAR */
a.segovr = (char)(psoi->dcontext->offset); psoi->dcontext = regsegment[a.segovr];
/* Context is that of segreg */
if (!psoi->dsegment && (psoi->dflag != XTERNAL)) {
psoi->dcontext = NULL; psoi->dtype = xltsymtoresult[REC]; psoi->mode = 4; a.linktype = FCONSTANT; } } else errorc (E_IUR); else /* Find if seg:var or no :, but needed */ findsegment (*dseg, &a); } /* bogus error check removed, dcontext can be other then register
* * else if (psoi->dcontext && * psoi->dcontext->symu.regsym.regtype == SEGREG) * * errorc (E_IOT); */
if (a.segovr != NOSEG) psoi->dtype |= xltsymtoresult[DVAR];
if (a.vmode == 2 || a.vmode == 7 || a.vmode == 10) {
if (a.segovr == NOSEG && *dseg != NOSEG && (psoi->dsegment || psoi->dflag == XTERNAL))
psoi->dcontext = regsegment[*dseg];
psoi->dtype |= xltsymtoresult[DVAR]; }
if (! (1 << a.linktype & (M_FNONE | M_FCONSTANT)) || psoi->dflag == XTERNAL) {
if (M_HIGH & psoi->dtype) a.linktype = FHIGH;
if (M_LOW & psoi->dtype) a.linktype = FLOW; }
if ((psoi->dtype & (M_PTRSIZE | M_HIGH | M_LOW)) || psoi->dsize && a.vmode != 4) {
psoi->sized = TRUE; psoi->w = (psoi->dsize > 1); psoi->s = !psoi->w; } psoi->seg = a.segovr; psoi->mode = (char)(a.vmode); psoi->fixtype = a.linktype; psoi->rm = a.index;
if ((M_REGRESULT & a.rstype) && (a.vmode != 3))
errorc (E_IUR); /* bad use of regs, like CS:SI */
fSecondArg++; return (a.curresult); }
/* setdispmode -- set up elements of the ar structure to reflect
the encoding of the disp addressing mode: [BP] or [EBP] means. there is a wordsize length displacement following and a zero index. input : struct ar *a; a pointer to the upper frame variable output : none modifies : a->vmode, a->index. */ VOID CODESIZE setdispmode( register struct ar *a ){
#ifdef V386
if (a->vmode > 7) {
a->vmode = 8; /* scaled index byte, not r/m */ a->index = (a->index&~7) | 5; }
else if (wordsize == 4 || highWord(a->curresult->dsckind.opnd.doffset) || (a->curresult->dsckind.opnd.dsegment && a->curresult->dsckind.opnd.dsegment->symu.segmnt.use32 == 4)) {
a->vmode = 5; a->index = (a->index&~7) | 5; } else #endif
{ a->vmode = 0; a->index = 6; } }
|