/* asmopcod.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" #ifdef FIXCOMPILERBUG // foobarfoofoo simply takes up space to get around a compiler bug void foobarfoofoo() { int foo; for( foo = 0; foo < 100000; foo++ ); for( foo = 0; foo < 100000; foo++ ); for( foo = 0; foo < 100000; foo++ ); for( foo = 0; foo < 100000; foo++ ); for( foo = 0; foo < 100000; foo++ ); for( foo = 0; foo < 100000; foo++ ); } #endif /*** forcesize - check for no size in pass 2 * * routine (); * * Entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE forcesize ( DSCREC *arg ){ register struct psop *pso; /* parse stack operand structure */ pso = &(arg->dsckind.opnd); if (pass2) if (!pso->sized) errorc (E_OHS); else if (M_CODE & pso->dtype) /* Not data assoc */ errorc (E_ASD); if (arg != fltdsc) /* Large size ok for 8087 */ if (pso->dsize > 2 && ( #ifdef V386 !(cputype&P386) || #endif pso->dsize != 4)) /* Illegal item size */ errorc (E_IIS); } /*** checkmatch - check memory and register * * checkmatch (); * * Entry * Exit * Returns * Calls * Note Give error if Dmem has a size and does not match Dreg. * Force to same size */ VOID PASCAL CODESIZE checkmatch ( DSCREC *dreg, DSCREC *dmem ){ register struct psop *psor; /* parse stack operand structure */ register struct psop *psom; /* parse stack operand structure */ psor = &(dreg->dsckind.opnd); psom = &(dmem->dsckind.opnd); if (psom->sized && (psom->w != psor->w #ifdef V386 || (psom->dsize && psor->dsize != psom->dsize) #endif )) errorc ((USHORT)(psom->mode == psor->mode? E_OMM & ~E_WARN1: E_OMM)); psom->w = psor->w; } /*** emitopcode - emit opcode to linker and display on listing * * emitopcode (val); * * Entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE emitopcode ( UCHAR v ){ if (pass2 || debug) { if (pass2 && emittext) /* Output to linker */ emitcbyte (v); /* Display on listing */ opdisplay (v); } if (emittext) pcoffset++; } /*** emitmodrm - emit modrm byte 64*p1+8*p2+p3 * * emitmodrm (p1, p2, p3); * * Entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE emitmodrm ( USHORT p1, USHORT p2, USHORT p3 ){ #ifdef V386 if (p1>7) { /* 386 SIB opcodes have wired in RM of ESP */ emitopcode ((UCHAR)(((p1-8) << 6) + (p2 << 3) + 4)); listindex--; emitopcode ((UCHAR)p3); } else #endif emitopcode ((UCHAR)(((p1 > 3 ? (p1-5) : p1) << 6) + (p2 << 3) + p3)); } /*** emitescape - emit segment escapt byte * * emitescape (); * * Entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE emitescape ( DSCREC *dsc, UCHAR sreg ){ register struct psop *pso; /* parse stack operand structure */ pso = &(dsc->dsckind.opnd); if (pso->seg < NOSEG && pso->seg != sreg && pso->mode != 4) { if (checkpure && (cputype & (P286|P386)) && pso->seg == CSSEG) impure = TRUE; if (pso->seg < FSSEG) emitopcode((UCHAR)(0x26|(pso->seg<<3))); #ifdef V386 else if (cputype & P386) emitopcode((UCHAR)(0x60|pso->seg)); #endif else errorc (E_CRS); /* Flag is prefix */ listbuffer[listindex-1] = ':'; listindex++; } if (pso->seg > NOSEG) /* Unknown segreg */ errorc (E_CRS); } #ifdef V386 VOID PASCAL CODESIZE emitsize ( USHORT value ){ if (! (cputype & P386)) { if (errorcode == (E_IIS&~E_WARN1)) errorcode = 0; errorc(E_IIS&~E_WARN1); } emitopcode((UCHAR)value); listbuffer[listindex-1] = '|'; listindex++; } #endif /*** byteimmcheck - check if value is -128 .. +127 * * routine (); * * Entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE byteimmcheck ( register struct psop *pso ){ register USHORT t; t = (USHORT)pso->doffset; if (pso->dsign) t = -t; if (t > (USHORT) 0x7F && t < (USHORT)~0x7F) errorc (E_VOR); } /*** emitOP - emit operand, value which may be in segment * * routine (); * * Entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE emitOP ( register struct psop *pso ){ USHORT i, fSegOnly; if (pso->dsign) pso->doffset = -(long)pso->doffset; pso->dsign = FALSE; if (fNeedList) { fSegOnly = (pso->fixtype == FBASESEG || pso->fixtype == FGROUPSEG); if (pso->dflag == INDETER) { /* Have ? */ for (i = 1; i <= 2 * pso->dsize; i++) { listbuffer[listindex] = '?'; if (listindex < LSTMAX) listindex++; else resetobjidx (); } } else if (pso->dsize == 1) { opdisplay ((UCHAR) pso->doffset); listindex--; } else if (!fSegOnly) { if (pso->dsize > 4 || pso->dsize == 4 && ((pso->fixtype&7) == FOFFSET || pso->fixtype == FCONSTANT)) { /* list full 32 bits, even if top is 0 */ if (!highWord(pso->doffset)){ offsetAscii((OFFSET) 0); copyascii(); } offsetAscii (pso->doffset); } else offsetAscii (pso->doffset & 0xffff); copyascii (); } if ((pso->fixtype&7) == FPOINTER || fSegOnly) { if (pso->dsize != 2) listindex++; copytext ("--"); copytext ("--"); } if (pso->dflag == XTERNAL) copytext (" E"); else if (pso->dsegment) copytext (" R"); if (pso->dflag == UNDEFINED) copytext (" U"); listindex++; if (fSegOnly && pso->dsize == 4){ copytext("00"); copytext("00"); } } if (emittext) { if (pass2) if (pso->dflag != UNDEFINED) emitobject (pso); else if (pso->dsize != 1) emitcword ((OFFSET) 0); /* Just put out word */ else { if (((USHORT) (pso->doffset >> 8)) != (USHORT)0 && ((USHORT) (pso->doffset >> 8)) != (USHORT)-1) errorc (E_VOR); emitcbyte (0); } pcoffset += pso->dsize; } } /*** emitrest - emit displacement or immediate values based on * address passed in address mode * * emitrest (opc); * * Entry *opc = parse stack entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE emitrest ( DSCREC *opc ){ register struct psop *pso; /* parse stack operand structure */ pso = &(opc->dsckind.opnd); if ((pso->mode != 3 && pso->mode != 4) && (pso->fixtype == FNONE)) pso->fixtype = FCONSTANT; switch(pso->mode) /* There is something to output */ { case 0: if(pso->rm != 6) break; case 2: pso->dsize = 2; goto bpcomm; /* 386 modes, 4 byte displacements */ case 5: case 8: if ((pso->rm&7) != 5) break; case 7: case 10: pso->dsize = 4; bpcomm: /* we get empty dsize from some callers. for this operand, * we need to make it an offset. but not for far calls and * jumps */ if ((pso->fixtype&7) == FPOINTER) pso->dsize += 2; emitOP (pso); break; case 1: case 6: case 9: pso->dsize = 1; emitOP (pso); break; case 3: break; case 4: /* Immediate mode */ if (!pso->w || pso->dsize == 0) pso->dsize = (pso->w ? wordsize : 1); emitOP (pso); } } /*** errorforward - generate error if forward reference on pass 2 * * routine (); * * Entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE errorforward ( DSCREC *arg ){ if (pass2) if (arg->dsckind.opnd.dflag == FORREF) errorc (E_IFR); } /*** errorimmed - generate error if immediate operand * * routine (); * * Entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE errorimmed ( DSCREC *dsc ){ if (dsc->dsckind.opnd.mode == 4) { errorc (E_NIM); dsc->dsckind.opnd.mode = 2; } } /*** rangecheck - check for register number within range * * routine (); * * Entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE rangecheck ( USHORT *v, UCHAR limit ){ if (*v > limit) { if (limit <= 7) errorc (E_IRV); else errorc (E_VOR); *v = limit; } } VOID PASCAL CODESIZE valuecheck( OFFSET *v, USHORT limit ){ if (*v > limit) { if (limit <= 7) errorc (E_IRV); else errorc (E_VOR); *v = limit; } } /*** forceaccum - generate error if not register AX or AL * * routine (); * * Entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE forceaccum ( DSCREC *dsc ){ if (dsc->dsckind.opnd.mode != 3 || dsc->dsckind.opnd.rm) errorc (E_AXL); } /*** errorsegreg - generate error if operand is segment register * * errorsegreg (arg); * * Entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE errorsegreg ( DSCREC *arg ){ if (1 << REGRESULT & arg->dsckind.opnd.dtype) if (arg->dsckind.opnd.dsegment->symu.regsym.regtype == SEGREG) errorc (E_ISR); }