diff options
Diffstat (limited to 'bin86-0.3/as/mops.c')
-rw-r--r-- | bin86-0.3/as/mops.c | 2840 |
1 files changed, 0 insertions, 2840 deletions
diff --git a/bin86-0.3/as/mops.c b/bin86-0.3/as/mops.c deleted file mode 100644 index be4e0f6..0000000 --- a/bin86-0.3/as/mops.c +++ /dev/null @@ -1,2840 +0,0 @@ -/* - * bin86/as/mops.c - * - * Copyright (C) 1992 Bruce Evans - */ - -/* mops.c - handle pseudo-ops */ - -#include "const.h" -#include "type.h" -#include "globvar.h" -#include "opcode.h" -#include "scan.h" -#undef EXTERN -#define EXTERN -#include "address.h" - -#define is8bitadr(offset) ((offset_t) offset < 0x100) -#define is8bitsignedoffset(offset) ((offset_t) (offset) + 0x80 < 0x100) -#define pass2 pass - -FORWARD void mshort2 P((void)); -FORWARD reg_pt regchk P((void)); -FORWARD void reldata P((void)); - -#ifdef I80386 - -#define iswordadr(offset) ((offset_t) (offset) < 0x10000L) -#define iswordoffset(offset) ((offset_t) (offset) + 0x8000L < 0x10000L) -#define iswordorswordoffset(offset) ((offset_t) (offset) + 0xFFFFL < 0x1FFFEL) - -#define BYTE_SEGWORD 0x00 -#define isspecreg(r) ((r) >= CR0REG && (r) <= TR7REG) - -#define BASE_MASK 0x07 -#define BASE_SHIFT 0 -#define INDEX_MASK 0x38 -#define INDEX_SHIFT 3 -#define MOD_MASK 0xC0 -# define REG_MOD 0xC0 -# define MEM0_MOD 0x00 -# define MEM1_MOD 0x40 -# define MEM2_MOD 0x80 -#define REG_MASK 0x38 -#define REG_SHIFT 3 -#define RM_MASK 0x07 -#define RM_SHIFT 0 -# define D16_RM 0x06 -# define D32_RM 0x05 -# define SIB_NOBASE 0x05 -# define SIB_RM 0x04 -#define SREG_MASK 0x38 -#define SREG_SHIFT 3 -#define SS_MASK 0xC0 -#define SS_SHIFT 6 - -#define SEGMOV 0x04 -#define SIGNBIT 0x02 -#define TOREGBIT 0x02 -#define WORDBIT 0x01 - -PRIVATE opcode_t baseind16[] = -{ - 0x00, /* BP + BP, illegal */ - 0x00, /* BX + BP, illegal */ - 0x03, /* DI + BP */ - 0x02, /* SI + BP */ - 0x00, /* BP + BX, illegal */ - 0x00, /* BX + BX, illegal */ - 0x01, /* DI + BX */ - 0x00, /* SI + BX */ - 0x03, /* BP + DI */ - 0x01, /* BX + DI */ - 0x00, /* DI + DI, illegal */ - 0x00, /* SI + DI, illegal */ - 0x02, /* BP + SI */ - 0x00, /* BX + SI */ - 0x00, /* DI + SI, illegal */ - 0x00, /* SI + SI, illegal */ -}; - -PRIVATE opcode_t regbits[] = -{ - 0x05 << REG_SHIFT, /* BP */ - 0x03 << REG_SHIFT, /* BX */ - 0x07 << REG_SHIFT, /* DI */ - 0x06 << REG_SHIFT, /* SI */ - - 0x00 << REG_SHIFT, /* EAX */ - 0x05 << REG_SHIFT, /* EBP */ - 0x03 << REG_SHIFT, /* EBX */ - 0x01 << REG_SHIFT, /* ECX */ - 0x07 << REG_SHIFT, /* EDI */ - 0x02 << REG_SHIFT, /* EDX */ - 0x06 << REG_SHIFT, /* ESI */ - 0x04 << REG_SHIFT, /* ESP */ - - 0x00 << REG_SHIFT, /* AX */ - 0x01 << REG_SHIFT, /* CX */ - 0x02 << REG_SHIFT, /* DX */ - 0x04 << REG_SHIFT, /* SP */ - - 0x04 << REG_SHIFT, /* AH */ - 0x00 << REG_SHIFT, /* AL */ - 0x07 << REG_SHIFT, /* BH */ - 0x03 << REG_SHIFT, /* BL */ - 0x05 << REG_SHIFT, /* CH */ - 0x01 << REG_SHIFT, /* CL */ - 0x06 << REG_SHIFT, /* DH */ - 0x02 << REG_SHIFT, /* DL */ - - 0x01 << REG_SHIFT, /* CS */ - 0x03 << REG_SHIFT, /* DS */ - 0x00 << REG_SHIFT, /* ES */ - 0x04 << REG_SHIFT, /* FS */ - 0x05 << REG_SHIFT, /* GS */ - 0x02 << REG_SHIFT, /* SS */ - - 0x00 << REG_SHIFT, /* CR0 */ - 0x02 << REG_SHIFT, /* CR2 */ - 0x03 << REG_SHIFT, /* CR3 */ - - 0x00 << REG_SHIFT, /* DR0 */ - 0x01 << REG_SHIFT, /* DR1 */ - 0x02 << REG_SHIFT, /* DR2 */ - 0x03 << REG_SHIFT, /* DR3 */ - 0x06 << REG_SHIFT, /* DR6 */ - 0x07 << REG_SHIFT, /* DR7 */ - - 0x03 << REG_SHIFT, /* TR3 */ - 0x04 << REG_SHIFT, /* TR4 */ - 0x05 << REG_SHIFT, /* TR5 */ - 0x06 << REG_SHIFT, /* TR6 */ - 0x07 << REG_SHIFT, /* TR7 */ - - 0x00 << REG_SHIFT, /* ST(0) */ - 0x01 << REG_SHIFT, /* ST(1) */ - 0x02 << REG_SHIFT, /* ST(2) */ - 0x03 << REG_SHIFT, /* ST(3) */ - 0x04 << REG_SHIFT, /* ST(4) */ - 0x05 << REG_SHIFT, /* ST(5) */ - 0x06 << REG_SHIFT, /* ST(6) */ - 0x07 << REG_SHIFT, /* ST(7) */ -}; - -PRIVATE opsize_t regsize[] = -{ - 2, /* BP */ - 2, /* BX */ - 2, /* DI */ - 2, /* SI */ - - 4, /* EAX */ - 4, /* EBP */ - 4, /* EBX */ - 4, /* ECX */ - 4, /* EDI */ - 4, /* EDX */ - 4, /* ESI */ - 4, /* ESP */ - - 2, /* AX */ - 2, /* CX */ - 2, /* DX */ - 2, /* SP */ - - 1, /* AH */ - 1, /* AL */ - 1, /* BH */ - 1, /* BL */ - 1, /* CH */ - 1, /* CL */ - 1, /* DH */ - 1, /* DL */ - - 2, /* CS */ - 2, /* DS */ - 2, /* ES */ - 2, /* FS */ - 2, /* GS */ - 2, /* SS */ - - 4, /* CR0 */ - 4, /* CR2 */ - 4, /* CR3 */ - - 4, /* DR0 */ - 4, /* DR1 */ - 4, /* DR2 */ - 4, /* DR3 */ - 4, /* DR6 */ - 4, /* DR7 */ - - 4, /* TR3 */ - 4, /* TR4 */ - 4, /* TR5 */ - 4, /* TR6 */ - 4, /* TR7 */ - - 10, /* ST(0) */ - 10, /* ST(1) */ - 10, /* ST(2) */ - 10, /* ST(3) */ - 10, /* ST(4) */ - 10, /* ST(5) */ - 10, /* ST(6) */ - 10, /* ST(7) */ - - 0, /* NOREG */ -}; - -PRIVATE opcode_t regsegword[] = -{ - WORDBIT, /* BP */ - WORDBIT, /* BX */ - WORDBIT, /* DI */ - WORDBIT, /* SI */ - - WORDBIT, /* EAX */ - WORDBIT, /* EBP */ - WORDBIT, /* EBX */ - WORDBIT, /* ECX */ - WORDBIT, /* EDI */ - WORDBIT, /* EDX */ - WORDBIT, /* ESI */ - WORDBIT, /* ESP */ - - WORDBIT, /* AX */ - WORDBIT, /* CX */ - WORDBIT, /* DX */ - WORDBIT, /* SP */ - - BYTE_SEGWORD, /* AH */ - BYTE_SEGWORD, /* AL */ - BYTE_SEGWORD, /* BH */ - BYTE_SEGWORD, /* BL */ - BYTE_SEGWORD, /* CH */ - BYTE_SEGWORD, /* CL */ - BYTE_SEGWORD, /* DH */ - BYTE_SEGWORD, /* DL */ - - SEGMOV, /* CS */ - SEGMOV, /* DS */ - SEGMOV, /* ES */ - SEGMOV, /* FS */ - SEGMOV, /* GS */ - SEGMOV, /* SS */ - - 0x20, /* CR0 */ - 0x20, /* CR2 */ - 0x20, /* CR3 */ - - 0x21, /* DR0 */ - 0x21, /* DR1 */ - 0x21, /* DR2 */ - 0x21, /* DR3 */ - 0x21, /* DR6 */ - 0x21, /* DR7 */ - - 0x24, /* TR3 */ - 0x24, /* TR4 */ - 0x24, /* TR5 */ - 0x24, /* TR6 */ - 0x24, /* TR7 */ - - 0x00, /* ST(0) */ - 0x00, /* ST(1) */ - 0x00, /* ST(2) */ - 0x00, /* ST(3) */ - 0x00, /* ST(4) */ - 0x00, /* ST(5) */ - 0x00, /* ST(6) */ - 0x00, /* ST(7) */ - - 0x00, /* NOREG */ -}; - -PRIVATE opcode_t rm[] = -{ - 0x05, /* BP */ - 0x03, /* BX */ - 0x07, /* DI */ - 0x06, /* SI */ - - 0x00, /* EAX */ - 0x05, /* EBP */ - 0x03, /* EBX */ - 0x01, /* ECX */ - 0x07, /* EDI */ - 0x02, /* EDX */ - 0x06, /* ESI */ - 0x04, /* ESP */ - - 0x00, /* AX */ - 0x01, /* CX */ - 0x02, /* DX */ - 0x04, /* SP */ - - 0x04, /* AH */ - 0x00, /* AL */ - 0x07, /* BH */ - 0x03, /* BL */ - 0x05, /* CH */ - 0x01, /* CL */ - 0x06, /* DH */ - 0x02, /* DL */ - - 0x01, /* CS */ - 0x03, /* DS */ - 0x00, /* ES */ - 0x04, /* FS */ - 0x05, /* GS */ - 0x02, /* SS */ - - 0x00, /* CR0 */ - 0x00, /* CR2 */ - 0x00, /* CR3 */ - - 0x00, /* DR0 */ - 0x00, /* DR1 */ - 0x00, /* DR2 */ - 0x00, /* DR3 */ - 0x00, /* DR6 */ - 0x00, /* DR7 */ - - 0x00, /* TR3 */ - 0x00, /* TR4 */ - 0x00, /* TR5 */ - 0x00, /* TR6 */ - 0x00, /* TR7 */ - - 0x00, /* ST(0) */ - 0x00, /* ST(1) */ - 0x00, /* ST(2) */ - 0x00, /* ST(3) */ - 0x00, /* ST(4) */ - 0x00, /* ST(5) */ - 0x00, /* ST(6) */ - 0x00, /* ST(7) */ - - 0x04, /* null index reg for sib only */ -}; - -PRIVATE opcode_t rmfunny[] = -{ - 0x06, /* BP */ - 0x07, /* BX */ - 0x05, /* DI */ - 0x04, /* SI */ -}; - -PRIVATE opcode_t segoverride[] = -{ - 0x2E, /* CS */ - 0x3E, /* DS */ - 0x26, /* ES */ - 0x64, /* FS */ - 0x65, /* GS */ - 0x36, /* SS */ -}; - -PRIVATE opcode_t ss[] = /* scale to ss bits */ -{ - 0x00, /* x0, illegal */ - 0x00 << SS_SHIFT, /* x1 */ - 0x01 << SS_SHIFT, /* x2 */ - 0x00, /* x3, illegal */ - 0x02 << SS_SHIFT, /* x4 */ - 0x00, /* x5, illegal */ - 0x00, /* x6, illegal */ - 0x00, /* x7, illegal */ - 0x03 << SS_SHIFT, /* x8 */ -}; - -PRIVATE unsigned char calljmp_kludge; -PRIVATE opcode_t direction; -PRIVATE bool_t fpreg_allowed; -PRIVATE opcode_t segword; -/* - Values of segword: - BYTE_SEGWORD for byte ea's. - SEGMOV for segment registers - opcode for special registers - WORDBIT for other word and dword ea's -*/ - -PRIVATE struct ea_s source; -PRIVATE struct ea_s source2; -PRIVATE struct ea_s target; - -FORWARD void Eb P((struct ea_s *eap)); -FORWARD void Ew P((struct ea_s *eap)); -FORWARD void Ev P((struct ea_s *eap)); -FORWARD void Ex P((struct ea_s *eap)); -FORWARD void Gw P((struct ea_s *eap)); -FORWARD void Gv P((struct ea_s *eap)); -FORWARD void Gx P((struct ea_s *eap)); -FORWARD void buildea P((struct ea_s *eap)); -FORWARD void buildfloat P((void)); -FORWARD void buildfreg P((void)); -FORWARD void buildimm P((struct ea_s *eap, bool_pt signflag)); -FORWARD void buildregular P((void)); -FORWARD void buildsegword P((struct ea_s *eap)); -FORWARD void buildunary P((opcode_pt opc)); -FORWARD opsize_pt displsize P((struct ea_s *eap)); -FORWARD reg_pt fpregchk P((void)); -FORWARD bool_pt getaccumreg P((struct ea_s *eap)); -FORWARD void getbinary P((void)); -FORWARD bool_pt getdxreg P((struct ea_s *eap)); -FORWARD void getea P((struct ea_s *eap)); -FORWARD void getimmed P((struct ea_s *eap, count_t immcount)); -FORWARD void getindirect P((struct ea_s *eap)); -FORWARD void getshift P((struct ea_s *eap)); -FORWARD reg_pt indregchk P((reg_pt matchreg)); -FORWARD void kgerror P((error_pt errnum)); -FORWARD void lbranch P((unsigned backamount)); -FORWARD void notbytesize P((struct ea_s *eap)); -FORWARD void notimmed P((struct ea_s *eap)); -FORWARD void notindirect P((struct ea_s *eap)); -FORWARD void notsegorspecreg P((struct ea_s *eap)); -FORWARD void yesimmed P((struct ea_s *eap)); -FORWARD void yes_samesize P((void)); - -PRIVATE void Eb(eap) -register struct ea_s *eap; -{ - Ex(eap); - if (eap->size != 0x1) - { -#ifndef NODEFAULTSIZE - if (eap->size == 0x0) - eap->size = 0x1; - else -#endif - kgerror(ILL_SIZE); - } -} - -PRIVATE void Ew(eap) -register struct ea_s *eap; -{ - Ex(eap); - if (eap->size != 0x2) - { -#ifndef NODEFAULTSIZE - if (eap->size == 0x0) - eap->size = 0x2; - else -#endif - kgerror(ILL_SIZE); - } -} - -PRIVATE void Ev(eap) -register struct ea_s *eap; -{ - Ex(eap); - notbytesize(eap); -} - -PRIVATE void Ex(eap) -register struct ea_s *eap; -{ - getea(eap); - notimmed(eap); - notsegorspecreg(eap); -} - -PRIVATE void Gd(eap) -register struct ea_s *eap; -{ - Gx(eap); - if (eap->size != 0x4) - kgerror(ILL_SIZE); -} - -PRIVATE void Gw(eap) -register struct ea_s *eap; -{ - Gx(eap); - if (eap->size != 0x2) - kgerror(ILL_SIZE); -} - -PRIVATE void Gv(eap) -register struct ea_s *eap; -{ - Gx(eap); - notbytesize(eap); -} - -PRIVATE void Gx(eap) -register struct ea_s *eap; -{ - Ex(eap); - notindirect(eap); -} - -PRIVATE void buildea(eap) -register struct ea_s *eap; -{ - opsize_t asize; - - ++mcount; - lastexp = eap->displ; - if (eap->indcount == 0x0) - postb = REG_MOD | rm[eap->base]; - else - { - if (eap->base == NOREG) - { - if (eap->index == NOREG) - { - if ((asize = displsize(eap)) > 0x2) - postb = D32_RM; - else - postb = D16_RM; - } - else - { - asize = 0x4; - postb = SIB_NOBASE; /* for sib later */ - } - } - else - { - if (eap->base > MAX16BITINDREG) - { - asize = 0x4; - postb = rm[eap->base]; - } - else - { - asize = 0x2; - if (!(lastexp.data & UNDBIT) && - !iswordorswordoffset(lastexp.offset)) - error(ABOUNDS); - if (eap->index == NOREG) - postb = rmfunny[eap->base]; - else if (eap->base <= MAX16BITINDREG) - postb = baseind16[eap->base + 0x4 * eap->index]; - } - } - if (asize != defsize) - aprefix = 0x67; - if (eap->base == NOREG) - mcount += asize; - else if (lastexp.data & (FORBIT | RELBIT | UNDBIT) || - !is8bitsignedoffset(lastexp.offset)) - { - postb |= MEM2_MOD; - mcount += asize; - } - else if (lastexp.offset != 0x0 || - eap->base == BPREG && eap->index == NOREG || - eap->base == EBPREG) - { - postb |= MEM1_MOD; - ++mcount; - } - if (asize > 0x2 && (eap->base == ESPREG || eap->index != NOREG)) - { - sib = ss[eap->scale] | - (rm[eap->index] << INDEX_SHIFT) | - (postb & RM_MASK); - postb = (postb & MOD_MASK) | SIB_RM; - ++mcount; - } - } -} - -PRIVATE void buildfloat() -{ - if (mcount != 0x0) - { - buildea(&source); - oprefix = 0x0; - postb |= (opcode & 0x07) << REG_SHIFT; - opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4); - } -} - -PRIVATE void buildfreg() -{ - mcount += 0x2; - oprefix = 0x0; - postb = REG_MOD | ((opcode & 0x07) << REG_SHIFT) | (target.base - ST0REG); - opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4); -} - -PRIVATE void buildimm(eap, signflag) -register struct ea_s *eap; -bool_pt signflag; -{ - immadr = eap->displ; - immcount = eap->size; - if (!(immadr.data & (FORBIT | RELBIT | UNDBIT))) - { - if (immcount == 0x1) - { - if ((offset_t) (immadr.offset + 0x80) >= 0x180) - datatoobig(); - } - else if (signflag && is8bitsignedoffset(immadr.offset)) - { - opcode |= SIGNBIT; - immcount = 0x1; - } - else if (immcount == 0x2) - { - if ((offset_t) (immadr.offset + 0x8000L) >= 0x18000L) - datatoobig(); - } - } -} - -PRIVATE void buildregular() -{ - if (mcount != 0x0) - { - buildea(&target); - postb |= regbits[source.base]; - } -} - -/* Check size and build segword. */ - -PRIVATE void buildsegword(eap) -register struct ea_s *eap; -{ - if (eap->size == 0x0) -#ifdef NODEFAULTSIZE - kgerror(SIZE_UNK); -#else - eap->size = defsize; -#endif - if (eap->indcount != 0x0 || eap->base == NOREG) - { - segword = WORDBIT; - if (eap->size == 0x1) - segword = BYTE_SEGWORD; - } - else - segword = regsegword[eap->base]; -} - -PRIVATE void buildunary(opc) -opcode_pt opc; -{ - if (mcount != 0x0) - { - buildea(&target); - postb |= opcode; - opcode = opc; - } -} - -PRIVATE opsize_pt displsize(eap) -register struct ea_s *eap; -{ - opsize_t asize; - - asize = defsize; - if (!(eap->displ.data & UNDBIT)) - { - if (asize > 0x2) - { - if (!(eap->displ.data & (FORBIT | RELBIT)) && - iswordadr(eap->displ.offset)) - asize = 0x2; - } - else if (!iswordorswordoffset(eap->displ.offset)) - /* should really use iswordadr() */ - /* but compiler generates signed offsets */ - { - if (!(eap->displ.data & (FORBIT | RELBIT))) - asize = 0x4; - else if (pass2) - error(ABOUNDS); - } - } - return asize; -} - -PRIVATE reg_pt fpregchk() -{ - reg_pt fpreg; - - fpreg_allowed = TRUE; - fpreg = regchk(); - fpreg_allowed = FALSE; - if (fpreg != ST0REG) - return NOREG; - getsym(); - if (sym == LPAREN) - { - getsym(); - if (sym != INTCONST || (unsigned) number >= 0x8) - error(ILL_FP_REG); - else - { - fpreg += number; - getsym(); - if (sym != RPAREN) - error(RPEXP); - else - getsym(); - } - } - return fpreg; -} - -PRIVATE bool_pt getaccumreg(eap) -register struct ea_s *eap; -{ - if ((eap->base = regchk()) != AXREG && eap->base != ALREG - && eap->base != EAXREG) - return FALSE; - getsym(); - if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize) - oprefix = 0x66; - return TRUE; -} - -/* - Get binary ea's in target & source (flipped if direction is set). - Put size in source if not already. - Initialise direction, segword, bump mcount. -*/ - -PRIVATE void getbinary() -{ - ++mcount; - getea(&target); - if (target.indcount == 0x0 && target.base == NOREG) - { - error(ILL_IMM_MODE); - target.base = AXREG; - target.size = defsize; - } - getcomma(); - getea(&source); - if (source.size == 0x0) - source.size = target.size; - else if (target.size != 0x0 && target.size != source.size) - { - kgerror(MISMATCHED_SIZE); - return; - } - if (source.indcount == 0x0 && regsegword[target.base] < SEGMOV) - direction = 0x0; - else if (target.indcount == 0x0 && regsegword[source.base] < SEGMOV) - { - struct ea_s swap; - - direction = TOREGBIT; - swap = source; - source = target; - target = swap; - } - else if (target.indcount != 0x0) - { - kgerror(ILL_IND_TO_IND); - return; - } - else - { - kgerror(ILL_SEG_REG); - return; - } - buildsegword(&source); -} - -PRIVATE bool_pt getdxreg(eap) -register struct ea_s *eap; -{ - if ((eap->base = regchk()) != DXREG) - return FALSE; - getsym(); - return TRUE; -} - -/* parse effective address */ - -/* - Syntax is restrictive in that displacements must be in the right spots - and will not be added up. - - optional size-type prefix, which is - BYTE - BYTE PTR - WORD - WORD PTR - DWORD - DWORD PTR - PTR - reg - segreg - [scaled index] - where scaled index = - indreg - indreg*scale - indreg+indreg - indreg+indreg*scale - [scaled index+displ] - [scaled index-displ] - optional-immediate-prefix displ[scaled index] - [displ] - optional-imediate-prefix displ - (scaled index) -- anachronism - optional-imediate-prefix displ(scaled index) -- anachronism -*/ - -PRIVATE void getea(eap) -register struct ea_s *eap; -{ - bool_t leading_displ; - bool_t leading_immed; - register struct sym_s *symptr; - - leading_immed = leading_displ = lastexp.data = eap->indcount - = lastexp.offset = 0x0; - eap->index = eap->base = NOREG; - eap->scale = 0x1; - eap->size = mnsize; /* 0x1 for byte ops, else 0x0 */ - - if (sym == IDENT) - { - if ((symptr = gsymptr)->type & MNREGBIT) - { - if (symptr->data & SIZEBIT) - { - getsym(); - if (symptr->value_reg_or_op.op.opcode == 0x0) - eap->indcount = 0x2 - calljmp_kludge; - else - { - if (eap->size != 0x0) - { - if (eap->size != symptr->value_reg_or_op.op.opcode) - error(MISMATCHED_SIZE); - } - else - eap->size = symptr->value_reg_or_op.op.opcode; - if (eap->size > 0x1 && eap->size != defsize) - oprefix = 0x66; - if (sym == IDENT && - (symptr = gsymptr)->type & MNREGBIT && - symptr->data & SIZEBIT && - symptr->value_reg_or_op.op.routine == PTROP) - { - getsym(); - eap->indcount = 0x2 - calljmp_kludge; - } - } - } - } - if (!(symptr->type & (LABIT | MACBIT | MNREGBIT | VARBIT))) - symptr->data |= FORBIT; /* show seen in advance */ - } - if ((eap->base = regchk()) != NOREG) - { - getsym(); - if (eap->indcount != 0x0) - { - error(ILL_IND_PTR); - eap->indcount = 0x0; - } - if (eap->size != 0x0 && eap->size != regsize[eap->base]) - error(MISMATCHED_SIZE); - if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize) - oprefix = 0x66; - eap->displ = lastexp; - return; - } - if (sym != lindirect) - { - if (sym == IMMEDIATE || sym == STAR) - { - /* context-sensitive, STAR means signed immediate here */ - leading_immed = TRUE; - getsym(); - } - leading_displ = TRUE; - expres(); - eap->displ = lastexp; - } - if (sym == lindirect) - { - getsym(); - eap->indcount = 0x2 - calljmp_kludge; - if ((eap->base = indregchk(NOREG)) != NOREG) - { - if (eap->indcount == 0x0 && leading_displ) - error(IND_REQ); - getsym(); - if (sym == ADDOP) - { - getsym(); - if ((eap->index = indregchk(eap->base)) != NOREG) - getsym(); - else - { - if (eap->indcount == 0x0) - error(IND_REQ); - if (leading_displ) - error(REPEATED_DISPL); - expres(); /* this eats ADDOP, SUBOP, MULOP */ - } - } - if (sym == STAR) - { - /* context-sensitive, STAR means scaled here*/ - if (eap->index == NOREG && eap->base == ESPREG) - { - error(INDEX_REG_EXP); - eap->base = EAXREG; - } - getsym(); - factor(); - chkabs(); - if (!(lastexp.data & UNDBIT) && lastexp.offset != 0x1) - { - if (eap->base <= MAX16BITINDREG || - lastexp.offset != 0x2 && lastexp.offset != 0x4 && - lastexp.offset != 0x8) - error(ILL_SCALE); - else - { - eap->scale = lastexp.offset; - if (eap->index == NOREG) - { - eap->index = eap->base; - eap->base = NOREG; - } - } - } - lastexp.data = lastexp.offset = 0x0; - } - if ((sym == ADDOP || sym == SUBOP)) - { - if (eap->indcount == 0x0) - error(IND_REQ); - if (leading_displ) - error(REPEATED_DISPL); - expres(); - } - } - else - { - if (leading_displ) - error(REPEATED_DISPL); - expres(); - } - if (sym != rindirect) - error(rindexp); - else - getsym(); - } - else if (!leading_immed && idefsize <= 0x2) - eap->indcount = 0x1; /* compatibility kludge */ - if (!leading_displ) - eap->displ = lastexp; -} - -PRIVATE void getimmed(eap, immcount) -struct ea_s *eap; -count_t immcount; -{ - getea(eap); - yesimmed(eap); - if (mcount != 0x0) - { - eap->size = immcount; - buildimm(eap, FALSE); - } -} - -PRIVATE void getindirect(eap) -register struct ea_s *eap; -{ - getea(eap); - if (eap->indcount == 0x0) - kgerror(IND_REQ); -} - -PRIVATE void getshift(eap) -register struct ea_s *eap; -{ - getcomma(); - getea(eap); - if (eap->base != CLREG) - yesimmed(eap); -} - -/* - Check if current symbol is a compatible index register. - Generate error if it is a reg but not a compatible index. - Return register number (adjusted if necessary to a legal index) or NOREG. -*/ - -PRIVATE reg_pt indregchk(matchreg) -reg_pt matchreg; -{ - reg_pt reg; - - if ((reg = regchk()) != NOREG) - { - switch (matchreg) - { - case BPREG: - case BXREG: - if (reg != DIREG && reg != SIREG) - { - reg = SIREG; - error(INDEX_REG_EXP); - } - break; - case DIREG: - case SIREG: - if (reg != BPREG && reg != BXREG) - { - reg = BXREG; - error(INDEX_REG_EXP); - } - break; - case NOREG: - break; - default: - if (reg <= MAX16BITINDREG || reg == ESPREG) - { - reg = EAXREG; - error(INDEX_REG_EXP); - } - break; - } - if (reg > MAXINDREG && calljmp_kludge == 0x0) - { - if (matchreg != NOREG) - reg = EAXREG; - else - reg = BXREG; - error(INDEX_REG_EXP); - } - } - return reg; -} - -PRIVATE void kgerror(errnum) -error_pt errnum; -{ - error(errnum); - sprefix = oprefix = aprefix = mcount = 0x0; -} - -PRIVATE void lbranch(backamount) -unsigned backamount; -{ - mcount += defsize + 0x1; - if (pass2) - { - reldata(); - if (!(lastexp.data & (RELBIT | UNDBIT))) - { - lastexp.offset = lastexp.offset - lc - lcjump; - if (backamount != 0x0 && !(lastexp.data & IMPBIT) && - lastexp.offset + backamount < 0x80 + backamount) - error(SHORTB); /* -0x8? to 0x7F, warning */ - } - } -} - -/* BCC (long branches emulated by short branch over & long jump) */ - -PUBLIC void mbcc() -{ - getea(&target); - if (target.indcount >= 0x2 || target.base != NOREG) - kgerror(REL_REQ); - else - { - if (defsize != 0x2) - { - page = PAGE1_OPCODE; - ++mcount; - opcode += 0x10; - lbranch(0x84); - } - else - { - aprefix = opcode ^ 0x1; /* kludged storage for short branch - over */ - oprefix = defsize + 0x1; - mcount += 0x2; - opcode = JMP_OPCODE; - lbranch(0x83); - mcount -= 0x2; - } - } -} - -/* bswap r32 */ - -PUBLIC void mbswap() -{ - ++mcount; - Gd(&target); - opcode |= rm[target.base]; -} - -/* BR, CALL, J, JMP */ - -PUBLIC void mcall() -{ - opcode_pt far; - bool_t indirect; - register struct sym_s *symptr; - - far = 0x0; - if (sym == IDENT && (symptr = gsymptr)->type & MNREGBIT && - symptr->data & SIZEBIT && - symptr->value_reg_or_op.op.routine == FAROP) - { - far = 0x8; - getsym(); - } - indirect = FALSE; - if (asld_compatible && idefsize <= 0x2) - { - calljmp_kludge = 0x2; - if (sym == INDIRECT) - { - calljmp_kludge = 0x0; - indirect = TRUE; - getsym(); - } - } - getea(&target); - if (indirect && target.indcount == 0x1) - target.indcount = 0x2; - calljmp_kludge = 0x0; - if (sym == COLON) - { - if (opcode == JMP_SHORT_OPCODE) - opcode = JMP_OPCODE; - ++mcount; - yesimmed(&target); - getsym(); - getea(&source); - yesimmed(&source); - if (mcount != 0x0) - { - if (opcode == JMP_OPCODE) - opcode = 0xEA; - else - opcode = 0x9A; - lastexp = source.displ; - if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) && - defsize == 0x2 && - (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L) - datatoobig(); - mcount += defsize; - target.size = 0x2; - buildimm(&target, FALSE); - } - } - else if (target.indcount >= 0x2 || target.base != NOREG) - { - ++mcount; - notsegorspecreg(&target); - if (target.indcount == 0) - notbytesize(&target); - if (mcount != 0x0) - { - if (opcode == JMP_SHORT_OPCODE) - opcode = JMP_OPCODE; - buildea(&target); - if (opcode == JMP_OPCODE) - opcode = 0x20; - else - opcode = 0x10; - postb |= opcode + far; - opcode = 0xFF; - } - } - else if (opcode == JMP_SHORT_OPCODE) - { - if (jumps_long) - { - opcode = JMP_OPCODE; - lbranch(0x83); - } - else - { - lastexp = target.displ; - if (lastexp.data & IMPBIT) - { - error(NONIMPREQ); - lastexp.data = FORBIT | UNDBIT; - } - mshort2(); - } - } - else - lbranch(opcode == JMP_OPCODE ? 0x83 : 0x0); -} - -/* CALLI, JMPI */ - -PUBLIC void mcalli() -{ - bool_t indirect; - - ++mcount; - indirect = FALSE; - if (sym == INDIRECT) - { - getsym(); - indirect = TRUE; - } - getea(&target); - if (target.indcount >= 0x2 || target.base != NOREG) - indirect = TRUE; - if (indirect) - { - buildea(&target); - if (opcode == 0xEA) - opcode = 0x28; - else - opcode = 0x18; - postb |= opcode; - opcode = 0xFF; - } - else - { - getcomma(); - getea(&source); - yesimmed(&source); - if (mcount != 0x0) - { - lastexp = target.displ; - if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) && - defsize == 0x2 && - (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L) - datatoobig(); - mcount += defsize; - source.size = 0x2; - buildimm(&source, FALSE); - } - } -} - -/* DIV, IDIV, MUL */ - -PUBLIC void mdivmul() -{ - if (getaccumreg(&source)) - { - ++mcount; - getcomma(); - Ex(&target); - yes_samesize(); - buildunary(0xF6 | regsegword[source.base]); - } - else - mnegnot(); -} - -/* ENTER */ - -PUBLIC void menter() -{ - ++mcount; - getimmed(&target, 0x2); - getcomma(); - getimmed(&source, 0x1); - if (mcount != 0x0) - { - mcount += 2; - lastexp = target.displ; /* getimmed(&source) wiped it out */ - } -} - -/* arpl r/m16,r16 (Intel manual opcode chart wrongly says EwRw) */ - -PUBLIC void mEwGw() -{ - ++mcount; - Ew(&target); - getcomma(); - Gw(&source); - oprefix = 0x0; - buildregular(); -} - -/* [cmpxchg xadd] [r/m8,r8 r/m16,r16, r/m32,r32] */ - -PUBLIC void mExGx() -{ - ++mcount; - Ex(&target); - getcomma(); - Gx(&source); - yes_samesize(); - opcode |= segword; - buildregular(); -} - -PUBLIC void mf_inher() -{ - mcount += 0x2; - postb = REG_MOD | (opcode & ~REG_MOD); - opcode = ESCAPE_OPCODE_BASE | (opcode >> 0x6); - if (opcode == ESCAPE_OPCODE_BASE) - opcode = ESCAPE_OPCODE_BASE | 0x6; /* fix up encoding of fcompp */ -} - -/* [fldenv fnsave fnstenv frstor] mem */ - -PUBLIC void mf_m() -{ - ++mcount; - getindirect(&source); - if (source.size != 0x0) - kgerror(ILL_SIZE); - buildfloat(); -} - -/* [fldcw fnstcw] mem2i */ - -PUBLIC void mf_m2() -{ - ++mcount; - getindirect(&source); - if (source.size != 0x0 && source.size != 0x2) - kgerror(ILL_SIZE); - buildfloat(); -} - -/* fnstsw [mem2i ax] */ - -PUBLIC void mf_m2_ax() -{ - if (getaccumreg(&target)) - { - if (target.base != AXREG) - kgerror(ILLREG); - else - { - opcode = 0x74; - target.base = ST0REG; /* fake, really ax */ - buildfreg(); - } - } - else - mf_m2(); -} - -/* [fiadd ficom ficomp fidiv fidivr fimul fist fisub fisubr] [mem2i mem4i] */ - -PUBLIC void mf_m2_m4() -{ - ++mcount; - getindirect(&source); - if (source.size == 0x0) - kgerror(SIZE_UNK); - else if (source.size == 0x2) - opcode |= 0x40; - else if (source.size != 0x4) - kgerror(ILL_SIZE); - buildfloat(); -} - -/* [fild fistp] [mem2i mem4i mem8i] */ - -PUBLIC void mf_m2_m4_m8() -{ - ++mcount; - getindirect(&source); - if (source.size == 0x0) - kgerror(SIZE_UNK); - else if (source.size == 0x2) - opcode |= 0x40; - else if (source.size == 0x8) - opcode |= 0x45; /* low bits 0 -> 5 and 3 -> 7 */ - else if (source.size != 0x4) - kgerror(ILL_SIZE); - buildfloat(); -} - -/* [fcom fcomp] [mem4r mem8r optional-st(i)] */ - -PUBLIC void mf_m4_m8_optst() -{ - if (sym == EOLSYM) - { - target.base = ST1REG; - buildfreg(); - } - else - mf_m4_m8_st(); -} - -/* [fadd fdiv fdivr fmul fsub fsubr] [mem4r mem8r st,st(i) st(i),st] */ - -PUBLIC void mf_m4_m8_stst() -{ - target.base = fpregchk(); - if (target.base != NOREG) - { - getcomma(); - source.base = fpregchk(); - if (source.base == NOREG) - { - error(FP_REG_REQ); - source.base = ST0REG; - } - if (target.base == ST0REG) - target.base = source.base; - else - { - if (source.base != ST0REG) - error(ILL_FP_REG_PAIR); - opcode |= 0x40; - if ((opcode & 0x07) >= 0x4) - opcode ^= 0x01; /* weird swap of fdiv/fdivr, fsub/fsubr */ - } - buildfreg(); - } - else - { - ++mcount; - getindirect(&source); - if (source.size == 0x0) - kgerror(SIZE_UNK); - else if (source.size == 0x8) - opcode |= 0x40; - else if (source.size != 0x4) - kgerror(ILL_SIZE); - buildfloat(); - } -} - -/* fst [mem4r mem8r st(i)] */ - -PUBLIC void mf_m4_m8_st() -{ - target.base = fpregchk(); - if (target.base != NOREG) - { - if (opcode == FST_ENCODED) - opcode |= 0x40; - buildfreg(); - } - else - { - ++mcount; - getindirect(&source); - if (source.size == 0x0) - kgerror(SIZE_UNK); - else if (source.size == 0x8) - opcode |= 0x40; - else if (source.size != 0x4) - kgerror(ILL_SIZE); - buildfloat(); - } -} - -/* [fld fstp] [mem4r mem8r mem10r st(i)] */ - -PUBLIC void mf_m4_m8_m10_st() -{ - target.base = fpregchk(); - if (target.base != NOREG) - { - if (opcode == FSTP_ENCODED) - opcode |= 0x40; - buildfreg(); - } - else - { - ++mcount; - getindirect(&source); - if (source.size == 0x0) - kgerror(SIZE_UNK); - else if (source.size == 0x8) - opcode |= 0x40; - else if (source.size == 0xA) - opcode |= 0x25; /* low bits 0 -> 5 and 3 -> 7 */ - else if (source.size != 0x4) - kgerror(ILL_SIZE); - buildfloat(); - } -} - -/* [fbld fbstp] mem10r */ - -PUBLIC void mf_m10() -{ - ++mcount; - getindirect(&source); - if (source.size != 0xA) - kgerror(ILL_SIZE); - buildfloat(); -} - -/* ffree st(i) */ - -PUBLIC void mf_st() -{ - target.base = fpregchk(); - if (target.base == NOREG) - kgerror(FP_REG_REQ); - buildfreg(); -} - -/* [fucom fucomp fxch] optional-st(i) */ - -PUBLIC void mf_optst() -{ - if (sym == EOLSYM) - { - target.base = ST1REG; - buildfreg(); - } - else - mf_st(); -} - -/* [faddp fdivp fdivrp fmulp fsubp fsubrp] st(i),st */ - -PUBLIC void mf_stst() -{ - target.base = fpregchk(); - if (target.base == NOREG) - { - kgerror(FP_REG_REQ); - return; - } - getcomma(); - source.base = fpregchk(); - if (source.base == NOREG) - { - kgerror(FP_REG_REQ); - return; - } - if (source.base != ST0REG) - { - kgerror(ILL_FP_REG); - return; - } - buildfreg(); -} - -PUBLIC void mf_w_inher() -{ - sprefix = WAIT_OPCODE; - mf_inher(); -} - -/* [fsave fstenv] mem */ - -PUBLIC void mf_w_m() -{ - sprefix = WAIT_OPCODE; - mf_m(); -} - -/* fstcw mem2i */ - -PUBLIC void mf_w_m2() -{ - sprefix = WAIT_OPCODE; - mf_m2(); -} - -/* fstsw [mem2i ax] */ - -PUBLIC void mf_w_m2_ax() -{ - sprefix = WAIT_OPCODE; - mf_m2_ax(); -} - -/* ADC, ADD, AND, CMP, OR, SBB, SUB, XOR */ - -PUBLIC void mgroup1() -{ - getbinary(); - notsegorspecreg(&source); - if (mcount != 0x0) - { - if (source.base == NOREG) - { - if (target.indcount == 0x0 && (target.base == ALREG || - target.base == AXREG || - target.base == EAXREG && - (source.displ.data & (FORBIT | RELBIT | UNDBIT) || - !is8bitsignedoffset(source.displ.offset)))) - { - opcode |= 0x04 | segword; - buildimm(&source, FALSE); - } - else - { - buildunary(0x80 | segword); - buildimm(&source, TRUE); - } - } - else - { - opcode |= direction | segword; - buildregular(); - } - } -} - -/* RCL, RCR, ROL, ROR, SAL, SAR, SHL, SHR */ - -PUBLIC void mgroup2() -{ - ++mcount; - Ex(&target); - buildsegword(&target); - getshift(&source); - if (mcount != 0x0) - { - buildunary(0xD0 | segword); - if (source.base == CLREG) - opcode |= 0x2; - else if (source.displ.offset != 0x1) - { - opcode -= 0x10; - source.size = 0x1; - buildimm(&source, FALSE); - } - } -} - -/* LLDT, LTR, SLDT, STR, VERR, VERW */ - -PUBLIC void mgroup6() -{ - ++mcount; - Ew(&target); - oprefix = 0x0; - buildunary(0x0); -} - -/* INVLPG, LGDT, LIDT, LMSW, SGDT, SIDT, SMSW */ - -PUBLIC void mgroup7() -{ - ++mcount; - if (opcode == 0x20 || opcode == 0x30) - { - Ew(&target); - oprefix = 0x0; - } - else - { - getindirect(&target); - oprefix = 0x0; - if (target.size != 0x0 && target.size != 0x6) - error(MISMATCHED_SIZE); /* XXX - size 6 wrong for INVLPG? */ - } - buildunary(0x1); -} - -/* BT, BTR, BTS, BTC */ - -PUBLIC void mgroup8() -{ - ++mcount; - Ev(&target); - getcomma(); - /* Gv or Ib */ - getea(&source); - notindirect(&source); - notsegorspecreg(&source); - if (mcount != 0x0) - { - if (source.base == NOREG) - { - buildunary(0xBA); - source.size = 0x1; - buildimm(&source, TRUE); - } - else - { - yes_samesize(); - opcode += 0x83; - buildregular(); - } - } -} - -/* BSF, BSR, LAR, LSL (Intel manual opcode chart wrongly says GvEw for L*) */ - -PUBLIC void mGvEv() -{ - ++mcount; - Gv(&source); - getcomma(); - Ev(&target); - yes_samesize(); - buildregular(); -} - -/* bound [r16,m16&16 r32,m32&32] */ - -PUBLIC void mGvMa() -{ - ++mcount; - Gv(&source); - getcomma(); - getindirect(&target); - yes_samesize(); - buildregular(); -} - -/* LDS, LES, LFS, LGS, LSS */ - -PUBLIC void mGvMp() -{ - ++mcount; - Gv(&source); - getcomma(); - getindirect(&target); - if (target.size != 0x0 && target.size != 0x2 + source.size) - error(MISMATCHED_SIZE); - buildregular(); -} - -/* IMUL */ - -PUBLIC void mimul() -{ - ++mcount; - Ex(&target); - if (sym != COMMA) - { - buildsegword(&target); - buildunary(0xF6 | segword); - return; - } - getcomma(); - notindirect(&target); - source = target; /* direction is swapped */ - getea(&target); - notsegorspecreg(&target); - yes_samesize(); - if (sym != COMMA && (target.indcount != 0x0 || target.base != NOREG)) - { - page = PAGE1_OPCODE; - ++mcount; - opcode = 0xAF; - buildregular(); - } - else - { - if (sym == COMMA) - { - getsym(); - getea(&source2); - yesimmed(&source2); - } - else - { - source2 = target; - target = source; - } - source2.size = target.size; - if (is8bitsignedoffset(source2.displ.offset)) - { - source2.size = 0x1; - opcode = 0x6B; - } - else - { - source2.size = target.size; - opcode = 0x69; - } - buildregular(); - if (mcount != 0x0) - buildimm(&source2, FALSE); - } -} - -/* IN */ - -PUBLIC void min() -{ - ++mcount; - if (opcode & WORDBIT) /* inw; ind not supported */ - mnsize = 0x2; - if (sym == EOLSYM && mnsize != 0x0) - target.size = mnsize; - else - { - if (getaccumreg(&target)) - { - if (mnsize != 0x0 && regsize[target.base] != mnsize) - error(MISMATCHED_SIZE); - getcomma(); - } - else - target.size = regsize[target.base = mnsize < 0x2 ? ALREG : AXREG]; - opcode |= regsegword[target.base]; - if (!getdxreg(&source)) - { - getimmed(&source, 0x1); - opcode -= 0x8; - } - } - if (target.size > 0x1 && target.size != defsize) - oprefix = 0x66; -} - -/* DEC, INC */ - -PUBLIC void mincdec() -{ - ++mcount; - Ex(&target); - buildsegword(&target); - if (target.indcount == 0x0 && segword == WORDBIT) - opcode |= 0x40 | rm[target.base]; - else - buildunary(0xFE | segword); -} - -/* CBW, CWD, CMPSW, INSW, IRET, LODSW, POPA, POPF, PUSHA, PUSHF */ -/* MOVSW, OUTSW, SCASW, STOSW */ - -PUBLIC void minher16() -{ - minher(); - if (defsize != 0x2) - oprefix = 0x66; -} - -/* CWDE, CDQ, CMPSD, INSD, IRETD, LODSD, POPAD, POPFD, PUSHAD, PUSHFD */ -/* MOVSD, OUTSD, SCASD, STOSD */ - -PUBLIC void minher32() -{ - minher(); - if (defsize != 0x4) - oprefix = 0x66; -} - -/* AAD, AAM */ - -PUBLIC void minhera() -{ - ++mcount; - if (sym == EOLSYM) - { - target.displ.offset = 0xA; - target.size = 0x1; - buildimm(&target, FALSE); - } - else - getimmed(&target, 0x1); -} - -/* INT */ - -PUBLIC void mint() -{ - ++mcount; - getimmed(&target, 0x1); - if (!(immadr.data & (FORBIT | RELBIT | UNDBIT)) && - (opcode_t) immadr.offset == 0x3) - { - immcount = 0x0; - opcode = 0xCC; - } -} - -/* JCC */ - -PUBLIC void mjcc() -{ - if (jumps_long && opcode < 0x80) /* above 0x80 means loop - not long */ - mbcc(); - else - mshort(); -} - -/* JCXZ, JECXZ */ - -PUBLIC void mjcxz() -{ - if (opcode != defsize) - { - aprefix = 0x67; - ++mcount; /* quick fix - mshort() needs to know */ - } - opcode = 0xE3; - mshort(); - if (aprefix != 0x0) - --mcount; /* quick fix - main routine bumps it again */ -} - -/* LEA */ - -PUBLIC void mlea() -{ - Gv(&source); /* back to front */ - getcomma(); - ++mcount; - getindirect(&target); - yes_samesize(); - buildregular(); -} - -/* MOV */ - -PUBLIC void mmov() -{ - getbinary(); - if (segword >= SEGMOV) - { - oprefix = 0x0; - notimmed(&source); - if (segword > SEGMOV) /* special reg */ - notindirect(&target); - } - if (mcount != 0x0) - { - if (target.base == NOREG && target.index == NOREG && - (source.base == ALREG || source.base == AXREG || - source.base == EAXREG)) - { - opcode = 0xA0 | (direction ^ TOREGBIT) | segword; - lastexp = target.displ; - if ((source.size = displsize(&target)) != defsize) - aprefix = 0x67; - mcount += source.size; - } - else if (source.base == NOREG) - { - if (target.indcount == 0x0) - opcode = 0xB0 | (segword << 0x3) | rm[target.base]; - else - { - buildea(&target); - opcode = 0xC6 | segword; - } - buildimm(&source, FALSE); - } - else - { - if (isspecreg(source.base)) - { - page = PAGE1_OPCODE; - ++mcount; - opcode = 0x0; - } - opcode |= direction | segword; - buildregular(); - } - } -} - -/* MOVSX, MOVZX */ - -PUBLIC void mmovx() -{ - ++mcount; - Gv(&source); - getcomma(); - Ex(&target); - if (target.size == 0x0) - kgerror(SIZE_UNK); - if (target.size > 0x2) - kgerror(ILL_SIZE); - oprefix = 0x0; - if (source.size != defsize) - oprefix = 0x66; - buildsegword(&target); - opcode |= segword; - buildregular(); -} - -/* NEG, NOT */ - -PUBLIC void mnegnot() -{ - ++mcount; - Ex(&target); - buildsegword(&target); - buildunary(0xF6 | segword); -} - -/* OUT */ - -PUBLIC void mout() -{ - ++mcount; - if (opcode & WORDBIT) /* outw; outd not supported */ - mnsize = 0x2; - if (sym == EOLSYM && mnsize != 0x0) - source.size = mnsize; - else - { - if (!getdxreg(&target)) - { - getimmed(&target, 0x1); - opcode -= 0x8; - } - if (sym == COMMA) - { - getsym(); - if (!getaccumreg(&source)) - kgerror(AL_AX_EAX_EXP); - else if (mnsize != 0x0 && regsize[source.base] != mnsize) - error(MISMATCHED_SIZE); - } - else - source.size = regsize[source.base = mnsize < 0x2 ? ALREG : AXREG]; - opcode |= regsegword[source.base]; - } - if (source.size > 0x1 && source.size != defsize) - oprefix = 0x66; -} - -/* POP, PUSH */ - -PUBLIC void mpushpop() -{ - opcode_t oldopcode; - - ++mcount; - getea(&target); - buildsegword(&target); - notbytesize(&target); - if ((oldopcode = opcode) == POP_OPCODE) - { - notimmed(&target); - if (target.base == CSREG) - kgerror(ILL_SEG_REG); - } - if (mcount != 0x0) - { - if (target.indcount == 0x0) - { - if (segword == SEGMOV) - { - switch (target.base) - { - case CSREG: - opcode = 0x0E; - break; - case DSREG: - opcode = 0x1E; - break; - case ESREG: - opcode = 0x06; - break; - case SSREG: - opcode = 0x16; - break; - case FSREG: - opcode = 0xA0; - page = PAGE1_OPCODE; - ++mcount; - break; - case GSREG: - opcode = 0xA8; - page = PAGE1_OPCODE; - ++mcount; - break; - } - if (oldopcode == POP_OPCODE) - ++opcode; - } - else if (target.base != NOREG) - { - opcode = 0x50 | rm[target.base]; - if (oldopcode == POP_OPCODE) - opcode |= 0x8; - } - else - { - opcode = 0x68; - if (oldopcode == POP_OPCODE) - ++opcode; - buildimm(&target, TRUE); - } - } - else - { - buildea(&target); - if (oldopcode == PUSH_OPCODE) - postb |= 0x6 << REG_SHIFT; - } - } -} - -/* RET, RETF */ - -PUBLIC void mret() -{ - ++mcount; - if (sym != EOLSYM) - { - --opcode; - getimmed(&target, 0x2); - } -} - -/* SEG CS/DS/ES/FS/GS/SS */ - -PUBLIC void mseg() -{ - reg_pt reg; - - if (regsegword[reg = regchk()] != SEGMOV) - error(SEG_REG_REQ); - else - { - getsym(); - ++mcount; - opcode = (segoverride - CSREG)[reg]; - } -} - -/* SETCC */ - -PUBLIC void msetcc() -{ - ++mcount; - Eb(&target); - if (mcount != 0x0) - buildea(&target); -} - -/* SHLD, SHRD */ - -PUBLIC void mshdouble() -{ - ++mcount; - Ev(&target); - getcomma(); - Gv(&source); - yes_samesize(); - buildregular(); - getshift(&source2); - lastexp = target.displ; /* getshift() wiped it out */ - if (mcount != 0x0) - { - if (source2.base == CLREG) - opcode |= 0x1; - else - { - source2.size = 0x1; - buildimm(&source2, FALSE); - } - } -} - -/* - TEST - Similar to the regular group1 operators. - It does not allow the sign extended immediate byte forms - and does not use the relevant direction bit. -*/ - -PUBLIC void mtest() -{ - getbinary(); - notsegorspecreg(&source); - if (source.base == NOREG) - { - if (mcount != 0x0) - { - if (target.indcount == 0x0 - && (target.base == ALREG || target.base == AXREG - || target.base == EAXREG)) - opcode = 0xA8 | segword; - else - { - buildea(&target); - opcode = 0xF6 | segword; - } - } - buildimm(&source, FALSE); - } - else - { - opcode |= segword; - buildregular(); - } -} - -/* - XCHG - Similar to the regular group1 operators. - It does not allow any of the immediate forms - and does not use the irrelevant direction bit. -*/ - -PUBLIC void mxchg() -{ - getbinary(); - notimmed(&source); - notsegorspecreg(&source); - if (target.indcount == 0x0) - { - if (target.base == AXREG || target.base == EAXREG) - { - opcode = 0x90 + rm[source.base]; - return; - } - if (source.base == AXREG || source.base == EAXREG) - { - opcode = 0x90 + rm[target.base]; - return; - } - } - opcode |= segword; - buildregular(); -} - -PRIVATE void notbytesize(eap) -register struct ea_s *eap; -{ - if (eap->size == 0x1) - kgerror(ILL_SIZE); -} - -PRIVATE void notimmed(eap) -register struct ea_s *eap; -{ - if (eap->indcount == 0x0 && eap->base == NOREG) - kgerror(ILL_IMM_MODE); -} - -PRIVATE void notindirect(eap) -register struct ea_s *eap; -{ - if (eap->indcount != 0x0) - kgerror(ILL_IND); -} - -PRIVATE void notsegorspecreg(eap) -register struct ea_s *eap; -{ - if (regsegword[eap->base] >= SEGMOV) - kgerror(ILLREG); -} - -PRIVATE void yesimmed(eap) -register struct ea_s *eap; -{ - if (eap->indcount == 0x1) - eap->indcount = 0x0; - if (eap->indcount != 0x0 || eap->base != NOREG) - kgerror(IMM_REQ); -} - -PRIVATE void yes_samesize() -{ - if (target.size == 0x0) - target.size = source.size; - else if (source.size != 0x0 && target.size != source.size) - kgerror(MISMATCHED_SIZE); -} - -#endif /* I80386 */ - -#ifdef MC6809 - -/* 6809 opcode constants */ - -/* bits for indexed addressing */ - -#define INDIRECTBIT 0x10 -#define INDEXBIT 0x80 /* except 5 bit offset */ -#define PCRELBIT 0x04 /* PC relative (in certain cases) */ -#define RRBITS 0x60 /* register select bits */ - -PRIVATE opcode_t rrindex[] = /* register and index bits for indexed adr */ -{ - 0x60 | INDEXBIT, /* S */ - 0x40 | INDEXBIT, /* U */ - 0x00 | INDEXBIT, /* X */ - 0x20 | INDEXBIT, /* Y */ - PCRELBIT | INDEXBIT, /* PC */ -}; - -PRIVATE opcode_t pushpull[] = /* push/pull codes */ -{ - 0x40, /* S */ - 0x40, /* U */ - 0x10, /* X */ - 0x20, /* Y */ - 0x80, /* PC */ - 0x02, /* A */ - 0x04, /* B */ - 0x01, /* CC */ - 0x08, /* DP */ - 0x06, /* D */ -}; - -PRIVATE opcode_t tfrexg1[] = /* transfer/exchange codes for source reg */ -{ - 0x40, /* S */ - 0x30, /* U */ - 0x10, /* X */ - 0x20, /* Y */ - 0x50, /* PC */ - 0x80, /* A */ - 0x90, /* B */ - 0xA0, /* CC */ - 0xB0, /* DP */ - 0x00, /* D */ -}; - -PRIVATE opcode_t tfrexg2[] = /* transfer/exchange codes for target reg */ -{ - 0x04, /* S */ - 0x03, /* U */ - 0x01, /* X */ - 0x02, /* Y */ - 0x05, /* PC */ - 0x08, /* A */ - 0x09, /* B */ - 0x0A, /* CC */ - 0x0B, /* DP */ - 0x00, /* D */ -}; - -FORWARD void checkpostinc P((void)); -FORWARD void doaltind P((void)); -FORWARD void do1altind P((void)); -FORWARD void fixupind P((void)); -FORWARD void getindexnopost P((void)); -FORWARD void inderror P((error_pt errnum)); -FORWARD reg_pt indreg P((reg_pt maxindex)); -FORWARD void predec1 P((void)); -FORWARD void sustack P((reg_pt stackreg)); - -PRIVATE void checkpostinc() -{ - if (sym == ADDOP) - { - if (postb & INDIRECTBIT) - inderror(ILLMOD); /* single-inc indirect illegal */ - else - { - lastexp.offset &= 0xFF00; /* for printing if postbyte is 0: ,X+ */ - getsym(); - } - } - else if (sym == POSTINCOP) - { - postb |= 0x1; - getsym(); - } - else - postb |= 0x4; - fixupind(); -} - -/* common code for all-mode ops, alterable-mode ops, indexed ops */ - -PRIVATE void doaltind() -{ - mcount += 0x2; - if (sym == LBRACKET) - { - postb = INDIRECTBIT; - getsym(); - do1altind(); - if (sym != RBRACKET) - error(RBEXP); - } - else - do1altind(); -} - -PRIVATE void do1altind() -{ - bool_t byteflag; /* set if direct or short indexed adr forced */ - char *oldlineptr; - char *oldsymname; - reg_pt reg; - bool_t wordflag; /* set if extended or long indexed adr forced*/ - - if ((reg = regchk()) != NOREG) - { - switch (reg) - { - case AREG: - postb |= 0x86; - break; - case BREG: - postb |= 0x85; - break; - case DREG: - postb |= 0x8B; - break; - default: - if (indreg(MAXINDREG) != NOREG) - checkpostinc(); - return; - } - getsym(); - if (sym != COMMA) - inderror(COMEXP); - else - getindexnopost(); - return; - } - else if (sym == SUBOP) /* could be -R or - in expression */ - { - oldlineptr = lineptr; /* save state */ - oldsymname = symname; - getsym(); - reg = regchk(); - lineptr = oldlineptr; - symname = oldsymname; - if (reg != NOREG) - { - predec1(); /* it's -R */ - return; - } - sym = SUBOP; - } - else if (sym == COMMA) - { - postb |= INDEXBIT; - getsym(); - if (sym == SUBOP) - { - predec1(); - return; - } - else if (sym != PREDECOP) - { - if (indreg(MAXINDREG) != NOREG) - checkpostinc(); - return; - } - } - if (sym == PREDECOP) - { - postb |= 0x83; - getindexnopost(); - return; - } - - /* should have expression */ - - wordflag = byteflag = FALSE; - if (sym == LESSTHAN) - { - /* context-sensitive, LESSTHAN means byte-sized here */ - byteflag = TRUE; - getsym(); - } - else if (sym == GREATERTHAN) - { - /* context-sensitive, GREATERTHAN means word-sized here */ - wordflag = TRUE; - getsym(); - } - expres(); - if (sym == COMMA) - { /* offset from register */ - getsym(); - if ((reg = indreg(PCREG)) == NOREG) - return; - postb |= 0x8; /* default 8 bit offset */ - if (reg == PCREG) - { - reldata(); - if (!(lastexp.data & (RELBIT | UNDBIT))) - { - lastexp.offset = lastexp.offset - lc; - if (page != 0x0) - lastexp.offset -= 0x4; /* extra for instruction */ - else - lastexp.offset -= 0x3; /* 3 byte instruction - assuming 8 bit offset */ - } - } - if (byteflag) - { - if (!(lastexp.data & (RELBIT | UNDBIT)) && - !is8bitsignedoffset(lastexp.offset)) - error(ABOUNDS); /* forced short form is impossible */ - ++mcount; - } - else if (wordflag || lastexp.data & (FORBIT | RELBIT | UNDBIT) || - !is8bitsignedoffset(lastexp.offset)) - { /* 16 bit offset */ - if (postb & PCRELBIT && !(lastexp.data & RELBIT)) - --lastexp.offset; /* instruction 1 longer than already - allowed */ - postb |= 0x1; - mcount += 0x2; - } - else if (!(postb & PCRELBIT) && - (offset_t) (lastexp.offset + 0x10) < 0x20 && - !(postb & INDIRECTBIT && lastexp.offset != 0x0)) - { /* 5 bit offset */ - postb &= RRBITS | INDIRECTBIT; - if (lastexp.offset == 0x0) - postb |= 0x84; /* index with zero offset */ - else - postb |= (lastexp.offset & 0x1F); - } - else /* 8 bit offset */ - ++mcount; - fixupind(); - } - else if (postb & INDIRECTBIT) - { /* extended indirect */ - postb = 0x9F; - mcount += 0x2; - fixupind(); - } - else if (postb & INDEXBIT) - inderror(ILLMOD); /* e.g. LEAX $10 */ - else - { - if (byteflag || !wordflag && !(lastexp.data & (FORBIT | RELBIT)) && - (lastexp.offset >> 0x8) == dirpag) - { /* direct addressing */ - if (opcode >= 0x80) - opcode |= 0x10; - } - else /* extended addressing */ - { - if (opcode < 0x80) - opcode |= 0x70; - else - opcode |= 0x30; - ++mcount; - if (pass2 && (opcode == JSR_OPCODE || opcode == JMP_OPCODE) && - !(lastexp.data & IMPBIT) && - lastexp.offset + (0x81 - 0x3) < 0x101) - /* JSR or JMP could be done with BSR or BRA */ - error(SHORTB); - } - } -} - -PRIVATE void fixupind() -{ - if ((opcode & 0x30) == 0x0) /* change all but LEA opcodes */ - { - if (opcode < 0x80) - opcode |= 0x60; - else - opcode |= 0x20; - } -} - -PRIVATE void getindexnopost() -{ - getsym(); - if (indreg(MAXINDREG) != NOREG) - fixupind(); -} - -PRIVATE void inderror(errnum) -error_pt errnum; -{ - error(errnum); - if (postb & INDIRECTBIT) - sym = RBRACKET; /* fake right bracket to kill further errors */ - fixupind(); -} - -/* check current symbol is an index register (possibly excepting PC) */ -/* if so, modify postbyte RR and INDEXBIT for it, get next sym, return TRUE */ -/* otherwise generate error, return FALSE */ - -PRIVATE reg_pt indreg(maxindex) -reg_pt maxindex; -{ - reg_pt reg; - - if ((reg = regchk()) == NOREG) - inderror(IREGEXP); - else if (reg > maxindex) - { - inderror(ILLREG); - reg = NOREG; - } - else - { - postb |= rrindex[reg]; - getsym(); - } - return reg; -} - -/* all-mode ops */ - -PUBLIC void mall() -{ - if (sym == IMMEDIATE) - mimmed(); - else - malter(); -} - -/* alterable mode ops */ - -PUBLIC void malter() -{ - postb = 0x0; /* not yet indexed or indirect */ - doaltind(); -} - -/* indexed mode ops */ - -PUBLIC void mindex() -{ - postb = INDEXBIT; /* indexed but not yet indirect */ - doaltind(); -} - -/* immediate ops */ - -PUBLIC void mimmed() -{ - opcode_t nybble; - - mcount += 0x2; - if (sym != IMMEDIATE) - error(ILLMOD); - else - { - if (opcode >= 0x80 && ((nybble = opcode & 0xF) == 0x3 || - nybble == 0xC || nybble >= 0xE)) - ++mcount; /* magic for long immediate */ - symexpres(); - if (pass2 && mcount <= 0x2) - { - chkabs(); - checkdatabounds(); - } - } -} - -/* long branches */ - -PUBLIC void mlong() -{ - mcount += 0x3; /* may be 0x0 or 0x1 here */ - expres(); - if (pass2) - { - reldata(); - if (!(lastexp.data & (RELBIT | UNDBIT))) - { - lastexp.offset = lastexp.offset - lc - lcjump; - if (!(lastexp.data & IMPBIT) && - lastexp.offset + 0x81 < 0x101) - error(SHORTB); /* -0x81 to 0x7F, warning */ - } - } -} - -/* PSHS and PULS */ - -PUBLIC void msstak() -{ - sustack(SREG); -} - -/* TFR and EXG */ - -PUBLIC void mswap() -{ - reg_pt reg; - - mcount = 0x2; - if ((reg = regchk()) == NOREG) - error(REGEXP); - else - { - postb = tfrexg1[reg]; - getsym(); - if (sym != COMMA) - error(COMEXP); - else - { - getsym(); - if ((reg = regchk()) == NOREG) - error(REGEXP); - else if ((postb |= tfrexg2[reg]) - & 0x88 && (postb & 0x88) != 0x88) - error(ILLREG); /* registers not of same size */ - } - } -} - -/* PSHU and PULU */ - -PUBLIC void mustak() -{ - sustack(UREG); -} - -PRIVATE void predec1() -{ - if (postb & INDIRECTBIT) - inderror(ILLMOD); /* single-dec indirect illegal */ - else - { - postb |= 0x82; - getindexnopost(); - } -} - -/* common routine for PSHS/PULS/PSHU/PULU */ - -PRIVATE void sustack(stackreg) -reg_pt stackreg; -{ - reg_pt reg; - - mcount = 0x2; - while ((reg = regchk()) != NOREG) - { - if (reg == stackreg) - { - error(ILLREG); /* cannot stack self */ - break; - } - postb |= pushpull[reg]; - getsym(); - if (sym != COMMA) - break; - getsym(); - } -} - -#endif /* MC6809 */ - -/* routines common to all processors */ - -PUBLIC void getcomma() -{ - if (sym != COMMA) - error(COMEXP); - else - getsym(); -} - -/* inherent ops */ - -/* for I80386 */ -/* AAA, AAS, CLC, CLD, CLI, CLTS, CMC, CMPSB, DAA, DAS, HLT, INTO, INSB, */ -/* INVD, */ -/* LAHF, LEAVE, LOCK, LODSB, MOVSB, NOP, OUTSB, REP, REPE, REPNE, REPNZ, */ -/* REPZ, SAHF, SCASB, STC, STD, STI, STOSB, WAIT, WBINVD */ - -PUBLIC void minher() -{ - ++mcount; -} - -/* short branches */ - -PUBLIC void mshort() -{ - nonimpexpres(); - mshort2(); -} - -PRIVATE void mshort2() -{ - mcount += 0x2; - if (pass2) - { - reldata(); - if (lastexp.data & RELBIT) - showrelbad(); - else if (!(lastexp.data & UNDBIT)) - { - lastexp.offset = lastexp.offset - lc - mcount; - if (!is8bitsignedoffset(lastexp.offset)) - error(ABOUNDS); - } - } -} - -/* check if current symbol is a register, return register number or NOREG */ - -PRIVATE reg_pt regchk() -{ - register struct sym_s *symptr; - - if (sym == IDENT) - { - if ((symptr = gsymptr)->type & MNREGBIT) - { - if (symptr->data & REGBIT) - { -#ifdef I80386 - if (symptr->value_reg_or_op.reg == ST0REG && !fpreg_allowed) - error(FP_REG_NOT_ALLOWED); -#endif - return symptr->value_reg_or_op.reg; - } - } - else if (!(symptr->type & (LABIT | MACBIT | VARBIT))) - symptr->data |= FORBIT; /* show seen in advance */ - } - return NOREG; -} - -/* convert lastexp.data for PC relative */ - -PRIVATE void reldata() -{ - if ((lastexp.data ^ lcdata) & (IMPBIT | RELBIT | SEGM)) - { - if ((lastexp.data ^ lcdata) & RELBIT) - showrelbad(); /* rel - abs is weird, abs - rel is bad */ - else - { - pcrflag = OBJ_R_MASK; - lastexp.data = (lcdata & ~SEGM) | lastexp.data | RELBIT; - /* segment is that of lastexp.data */ - } - } - else /* same file, segment and relocation */ - lastexp.data = (lastexp.data | lcdata) & ~(RELBIT | SEGM); -} |