windows-nt/Source/XPSP1/NT/sdktools/masm/asmopcod.c
2020-09-26 16:20:57 +08:00

569 lines
8.4 KiB
C

/* 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 <stdio.h>
#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);
}