/* asmtab.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 #include "asm86.h" #include "asmfcn.h" #include "asmopcod.h" #include "asmctype.h" #include "asmtab.h" /* common between asmtab.c and asmtabtb.c */ extern struct pseudo FAR dir1tok[]; extern struct pseudo FAR dir2tok[]; extern struct opcentry FAR opctab[]; extern UCHAR opprec[]; extern KEYWORDS FAR t_siz_table; extern KEYWORDS FAR t_op_table; extern KEYWORDS FAR t_oc_table; extern KEYWORDS FAR t_seg_table; extern KEYWORDS FAR t_ps1_table; extern KEYWORDS FAR t_ps2_table; /*** fnsize - return size of operand * * flag = fnsize (); * * Entry naim = token to search for * Exit varsize = size of symbol * Returns TRUE if symbol found in size table * FALSE if symbol not found in size table * Calls none * Note 8/1/88 - MCH - Modified to perform text macro substitution. * This is a complete hack. iskey() is hardcoded to lookup * the string in naim, while symFet() sets symptr to the * symbol following the text macro expansion. Thus, lots of * contortions are necessary to get these routines to mesh. */ /* size table */ USHORT dirsize[] = { /* I_BYTE */ 1, /* I_DWORD */ 4, /* I_FAR */ CSFAR, /* I_NEAR */ CSNEAR, /* I_QWORD */ 8, /* I_TBYTE */ 10, /* I_WORD */ 2, /* I_FWORD */ 6, /* I_PROC */ CSNEAR }; SHORT PASCAL CODESIZE fnsize () { #ifdef FEATURE register USHORT v; if (*naim.pszName && ((v = iskey (&t_siz_table)) != NOTFOUND)) { varsize = dirsize[v]; return (TRUE); } return (FALSE); #else register USHORT v; SYMBOL FARSYM * pSYsave; char * savelbufp, * savebegatom, * saveendatom; char szname[SYMMAX+1]; FASTNAME saveInfo; char szSave[SYMMAX+1]; if (*naim.pszName) { pSYsave = symptr; savelbufp = lbufp; savebegatom = begatom; saveendatom = endatom; memcpy (&saveInfo, &naim, sizeof( FASTNAME ) ); memcpy (szSave, naim.pszName, SYMMAX + 1); if (symFet()) { STRNFCPY (szname, symptr->nampnt->id); lbufp = szname; getatom(); } symptr = pSYsave; lbufp = savelbufp; begatom = savebegatom; endatom = saveendatom; if (*naim.pszName && ((v = iskey (&t_siz_table)) != NOTFOUND)) { varsize = dirsize[v]; return (TRUE); } memcpy (naim.pszName, szSave, SYMMAX + 1); memcpy (&naim, &saveInfo, sizeof( FASTNAME ) ); } return (FALSE); #endif } /*** fnPtr - find a type to a pointer or size and return a CV type * * flag = fnPtr (ptrSize) * * Entry token = token to search for * Exit CV - type */ SHORT PASCAL CODESIZE fnPtr ( SHORT sizePtr ){ SYMBOL FARSYM *pSYtype, FARSYM *pT, FARSYM *pSY; SHORT fFarPtr; fFarPtr = sizePtr > wordsize; if (fnsize() || *naim.pszName == 0) return (typeFet(varsize) | makeType(0, ((fFarPtr)? BT_FARP: BT_NEARP), 0)); pT = symptr; if (symsrch()) { pSY = symptr; /* restore old symptr */ symptr = pT; if (pSY->symkind == STRUC) { if (fFarPtr) { if (pSY->symu.rsmsym.rsmtype.rsmstruc.typePtrFar) return(pSY->symu.rsmsym.rsmtype.rsmstruc.typePtrFar); } else if (pSY->symu.rsmsym.rsmtype.rsmstruc.typePtrNear) return(pSY->symu.rsmsym.rsmtype.rsmstruc.typePtrNear); /* Neither derived type is allocated, so make an allocation */ pSYtype = (SYMBOL FARSYM *)falloc((SHORT)( &(((SYMBOL FARSYM *)0)->symu) ), "fnPtr" ); if (pStrucCur) pStrucCur->alpha = pSYtype; else pStrucFirst = pSYtype; pStrucCur = pSYtype; pSYtype->attr = fFarPtr; pSYtype->symkind = 0; pSYtype->alpha = 0; pSYtype->symtype = pSY->symu.rsmsym.rsmtype.rsmstruc.type; if (fFarPtr) pSY->symu.rsmsym.rsmtype.rsmstruc.typePtrFar = typeIndex; else pSY->symu.rsmsym.rsmtype.rsmstruc.typePtrNear = typeIndex; return(typeIndex++); } } return (FALSE); } /*** fnoper - search for operator * * flag = fnoper (token, type, prec); * * Entry token = token to search for * Exit opertype = type of operator * operprec = precedence of operator * Returns TRUE if token is an operator * FALSE if token is not an operator * Calls none */ SHORT PASCAL CODESIZE fnoper () { register USHORT v; if (*naim.pszName && ((v = iskey (&t_op_table)) != NOTFOUND)) { opertype = v; operprec = opprec[v]; return (TRUE); } return (FALSE); } /*** opcodesearch - search for opcode * * flag = opcodesearch (); * * Entry *naim.pszName = token to search for * cputype = cpu type (8086, 186, 286) * Exit opcbase = opcode base value * opctype = type of opcode * modrm = modrm value * Returns TRUE if token is an opcode * FALSE if token is not an opcode * Calls none */ char PASCAL CODESIZE opcodesearch () { register USHORT v; struct opcentry FAR *opc; UCHAR cputypeandprot; UCHAR opctabmask; int workaround; if (*naim.pszName && ((v = iskey (&t_oc_table)) != NOTFOUND)) { cputypeandprot = cputype & PROT; opctabmask = opctab[v].cpumask&PROT; workaround = cputypeandprot >= opctabmask ? 1 : 0; if (((cpu = (opc = &(opctab[v]))->cpumask) & cputype) && workaround) { opcbase = opc->opcb; modrm = opc->mr; opctype = opc->opct; if (crefing) { fSecondArg = FALSE; switch (opctype) { case PJUMP: case PRELJMP: case PCALL: opcref = REF_XFER << 4 | REF_NONE; break; default: v = opc->cpumask; opcref = (v&F_W)? REF_WRITE << 4: REF_READ << 4; opcref |= (v&S_W)? REF_WRITE: REF_READ; } } return (TRUE); } } return (FALSE); } /*** fnspar - return token index and type from table. * * flag = fnspar (); * * Entry naim = token to search for * Exit segtyp = type of segment * segidx = index of token in table * Returns TRUE if symbol found in size table * FALSE if symbol not found in size table * Calls iskey * * I spent several hours trying to debug through the silly * redundant level of indirection, so I removed it for the * index. this changes all the token numbers by 1, so they * are consistent. see accompanying change in asmdir:segalign * -Hans Apr 8 1986 */ SHORT PASCAL CODESIZE fnspar () { register USHORT v; /* Must match IS_... in asmindex.h under "segment attributes. These values are the segment types put in the segdef OMF */ static char tokseg[] = { /* IS_AT */ 0, /* IS_BYTE */ 1, /* IS_COMMON */ 6, /* IS_MEMORY */ 1, /* IS_PAGE */ 4, /* IS_PARA */ 3, /* IS_PUBLIC */ 2, /* IS_STACK */ 5, /* IS_WORD */ 2, /* IS_DWORD */ 5, /* IS_USE32 */ 0, /* IS_USE16 */ 0, }; if (*naim.pszName && ((v = iskey (&t_seg_table)) != NOTFOUND)) { segtyp = tokseg[v]; segidx = v; return (TRUE); } return (FALSE); } /*** fndir - return size of operand * * flag = fndir (); * * Entry naim = token to search for * Exit opty = size of symbol * opkind = kind of symbol * Returns TRUE if symbol found in size table * FALSE if symbol not found in size table * Calls none */ SHORT PASCAL CODESIZE fndir () { register USHORT v; if (*naim.pszName && ((v = iskey (&t_ps1_table)) != NOTFOUND)) { optyp = dir1tok[v].type; opkind = dir1tok[v].kind; return (TRUE); } return (FALSE); } /*** fndir2 - return type of directive * * flag = fndir2 (); * Entry naim = token to search for * Exit opty = size of symbol * opkind = kind of symbol * * Returns TRUE if symbol found in size table * FALSE if symbol not found in size table * Calls none */ SHORT PASCAL CODESIZE fndir2 () { register USHORT v; if (*naim.pszName && ((v = iskey (&t_ps2_table)) != NOTFOUND)) { optyp = dir2tok[v].type; opkind = dir2tok[v].kind; return (TRUE); } return (FALSE); } SHORT PASCAL CODESIZE checkRes() { USHORT v; xcreflag--; if (fCheckRes && (((v = iskey (&t_oc_table)) != NOTFOUND && (opctab[v].cpumask & cputype)) || iskey (&t_ps1_table) != NOTFOUND || iskey (&t_ps2_table) != NOTFOUND || iskey (&t_op_table) != NOTFOUND || iskey (&t_siz_table) != NOTFOUND || /* iskey (&t_seg_table) != NOTFOUND || */ (symsearch() && symptr->symkind == REGISTER) || (naim.pszName[1] == 0 && (*naim.pszName == '$'|| *naim.pszName == '%' || *naim.pszName == '?')))){ errorn(E_RES); xcreflag++; return(TRUE); } xcreflag++; return(FALSE); }