#include "all.h" /* implicit operands, not needed for assembly */ #define AFv ANONE #define AXb ANONE #define AXv ANONE #define AYb ANONE #define AYv ANONE #define A0 ANONE #define A1 ANONE #define A2 ANONE #define A3 ANONE #define A4 ANONE #define AMa2 ANONE typedef struct Optab Optab; struct Optab { int op; uchar arg1; uchar arg2; uchar arg3; }; static uchar needmodrm[NAMODE] = { [AEb] 1, [AEv] 1, [AGb] 1, [AGv] 1, [AM] 1, [AMp] 1, [ASw] 1, }; /* static uchar small[NAMODE] = { [ANONE] 1, [AEb] 1, [AGb] 1, [AOb] 1, [AXb] 1, [AYb] 1, [AIb] 1, [AAL] 1, [ABL] 1, [ACL] 1, [ADL] 1, [AAH] 1, [ABH] 1, [ACH] 1, [ADH] 1, }; */ static Optab optab[256] = { //00 {OADD, AEb, AGb}, {OADD, AEv, AGv}, {OADD, AGb, AEb}, {OADD, AGv, AEv}, {OADD, AAL, AIb}, {OADD, AAX, AIv}, {OPUSH, AES, }, {OPOP, AES }, {OOR, AEb, AGb}, {OOR, AEv, AGv}, {OOR, AGb, AEb}, {OOR, AGv, AEv}, {OOR, AAL, AIb}, {OOR, AAX, AIv}, {OPUSH, ACS, }, {OBAD, }, //10 {OADC, AEb, AGb}, {OADC, AEv, AGv}, {OADC, AGb, AEb}, {OADC, AGv, AEv}, {OADC, AAL, AIb}, {OADC, AAX, AIv}, {OPUSH, ASS, }, {OPOP, ASS, }, {OSBB, AEb, AGb}, {OSBB, AEv, AGv}, {OSBB, AGb, AEb}, {OSBB, AGv, AEv}, {OSBB, AAL, AIb}, {OSBB, AAX, AIv}, {OPUSH, ADS, }, {OPOP, ADS, }, //20 {OAND, AEb, AGb}, {OAND, AEv, AGv}, {OAND, AGb, AEb}, {OAND, AGv, AEv}, {OAND, AAL, AIb}, {OAND, AAX, AIv}, {OSEG, AES, }, {ODAA, }, {OSUB, AEb, AGb}, {OSUB, AEv, AGv}, {OSUB, AGb, AEb}, {OSUB, AGv, AEv}, {OSUB, AAL, AIb}, {OSUB, AAX, AIv}, {OSEG, ACS, }, {ODAS, }, //30 {OXOR, AEb, AGb}, {OXOR, AEv, AGv}, {OXOR, AGb, AEb}, {OXOR, AGv, AEv}, {OXOR, AAL, AIb}, {OXOR, AAX, AIv}, {OSEG, ASS, }, {OAAA, }, {OCMP, AEb, AGb}, {OCMP, AEv, AGv}, {OCMP, AGb, AEb}, {OCMP, AGv, AEv}, {OCMP, AAL, AIb}, {OCMP, AAX, AIv}, {OSEG, ADS, }, {OAAS, }, //40 {OINC, AAX, }, {OINC, ACX, }, {OINC, ADX, }, {OINC, ABX, }, {OINC, ASP, }, {OINC, ABP, }, {OINC, ASI, }, {OINC, ADI, }, {ODEC, AAX, }, {ODEC, ACX, }, {ODEC, ADX, }, {ODEC, ABX, }, {ODEC, ASP, }, {ODEC, ABP, }, {ODEC, ASI, }, {ODEC, ADI, }, //50 {OPUSH, AAX, }, {OPUSH, ACX, }, {OPUSH, ADX, }, {OPUSH, ABX, }, {OPUSH, ASP, }, {OPUSH, ABP, }, {OPUSH, ASI, }, {OPUSH, ADI, }, {OPOP, AAX, }, {OPOP, ACX, }, {OPOP, ADX, }, {OPOP, ABX, }, {OPOP, ASP, }, {OPOP, ABP, }, {OPOP, ASI, }, {OPOP, ADI, }, //60 {OPUSHA, }, {OPOPA, }, {OBOUND,AGv,AMa,AMa2}, {OARPL, AEw, AGw}, {OSEG, AFS, }, {OSEG, AGS, }, {OOSIZE, }, {OASIZE, }, {OPUSH, AIv, }, {OIMUL,AGv,AEv,AIv},{OPUSH, AIb, }, {OIMUL,AGv,AEv,AIb}, {OINS, AYb, ADX}, {OINS, AYv, ADX}, {OOUTS, ADX, AXb}, {OOUTS, ADX, AXv}, //70 {OJOS, AJb, }, {OJOC, AJb, }, {OJCS, AJb, }, {OJCC, AJb, }, {OJEQ, AJb, }, {OJNE, AJb, }, {OJLS, AJb, }, {OJHI, AJb, }, {OJMI, AJb, }, {OJPL, AJb, }, {OJPS, AJb, }, {OJPC, AJb, }, {OJLT, AJb, }, {OJGE, AJb, }, {OJLE, AJb, }, {OJGT, AJb, }, //80 {OGP1, AEb, AIb}, {OGP1, AEv, AIv}, {OGP1, AEv, AIc}, {OGP1, AEv, AIc}, {OTEST, AEb, AGb}, {OTEST, AEv, AGv}, {OXCHG, AEb, AGb}, {OXCHG, AEv, AGv}, {OMOV, AEb, AGb}, {OMOV, AEv, AGv}, {OMOV, AGb, AEb}, {OMOV, AGv, AEv}, {OMOV, AEw, ASw}, {OLEA, AGv, AM }, {OMOV, ASw, AEw}, {OPOP, AEv, }, //90 {ONOP, }, {OXCHG, AAX, ACX}, {OXCHG, AAX, ADX}, {OXCHG, AAX, ABX}, {OXCHG, AAX, ASP}, {OXCHG, AAX, ABP}, {OXCHG, AAX, ASI}, {OXCHG, AAX, ADI}, {OCBW, }, {OCWD, }, {OCALL, AAp, }, {OWAIT, }, {OPUSHF,AFv, }, {OPOPF, AFv, }, {OSAHF, AAH, }, {OLAHF, AAH, }, //A0 {OMOV, AAL, AOb}, {OMOV, AAX, AOv}, {OMOV, AOb, AAL}, {OMOV, AOv, AAX}, {OMOVS, AXb, AYb}, {OMOVS, AXv, AYv}, {OCMPS, AXb, AYb}, {OCMPS, AXv, AYv}, {OTEST, AAL, AIb}, {OTEST, AAX, AIv}, {OSTOS, AYb, AAL}, {OSTOS, AYv, AAX}, {OLODS, AAL, AXb}, {OLODS, AAX, AXv}, {OSCAS, AAL, AYb}, {OSCAS, AAX, AYv}, //B0 {OMOV, AAL, AIb}, {OMOV, ACL, AIb}, {OMOV, ADL, AIb}, {OMOV, ABL, AIb}, {OMOV, AAH, AIb}, {OMOV, ACH, AIb}, {OMOV, ADH, AIb}, {OMOV, ABH, AIb}, {OMOV, AAX, AIv}, {OMOV, ACX, AIv}, {OMOV, ADX, AIv}, {OMOV, ABX, AIv}, {OMOV, ASP, AIv}, {OMOV, ABP, AIv}, {OMOV, ASI, AIv}, {OMOV, ADI, AIv}, //C0 {OGP2, AEb, AIb}, {OGP2, AEv, AIb}, {ORET, AIw, }, {ORET, A0, }, {OLFP,AES,AGv,AMp},{OLFP,ADS,AGv,AMp},{OMOV, AEb, AIb}, {OMOV, AEv, AIv}, {OENTER,AIw, AIb}, {OLEAVE, }, {ORETF, AIw, }, {ORETF, A0, }, {OINT, A3, }, {OINT, AIb, }, {OINT, A4, }, {OIRET, }, //D0 {OGP2, AEb, A1 }, {OGP2, AEv, A1 }, {OGP2, AEb, ACL}, {OGP2, AEv, ACL}, {OAAM, AIb, }, {OAAD, AIb, }, {OBAD, }, {OXLAT, AAL, ABX}, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //E0 {OLOOPNZ,AJb,ACX}, {OLOOPZ,AJb, ACX}, {OLOOP, AJb, ACX}, {OJCXZ, AJb, }, {OIN, AAL, AIb}, {OIN, AAX, AIb}, {OOUT, AIb, AAL}, {OOUT, AIb, AAX}, {OCALL, AJv, }, {OJMP, AJv, }, {OJMP, AAp, }, {OJMP, AJb, }, {OIN, AAL, ADX}, {OIN, AAX, ADX}, {OOUT, ADX, AAL}, {OOUT, ADX, AAX}, //F0 {OLOCK, }, {OBAD, }, {OREPNZ, }, {OREPZ, }, {OHLT, }, {OCMC, }, {OGP3b, }, {OGP3v, }, {OCLC, }, {OSTC, }, {OCLI, }, {OSTI, }, {OCLD, }, {OSTD, }, {OGP4, }, {OGP5, }, }; static Optab optab0F[256] = { //00 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //10 - mostly floating point and quadword moves {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //20 - doubleword <-> control register moves, other arcana {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //30 - wrmsr, rdtsc, rdmsr, rdpmc, sysenter, sysexit {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //40 - conditional moves {OCMOVOS,AGv,AEv}, {OCMOVOC,AGv,AEv}, {OCMOVCS,AGv,AEv}, {OCMOVCC,AGv,AEv}, {OCMOVEQ,AGv,AEv}, {OCMOVNE,AGv,AEv}, {OCMOVLS,AGv,AEv}, {OCMOVHI,AGv,AEv}, {OCMOVMI,AGv,AEv}, {OCMOVPL,AGv,AEv}, {OCMOVPS,AGv,AEv}, {OCMOVPC,AGv,AEv}, {OCMOVLT,AGv,AEv}, {OCMOVGE,AGv,AEv}, {OCMOVLE,AGv,AEv}, {OCMOVGT,AGv,AEv}, //50 - floating point, mmx stuff {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //60 - floating point, mmx stuff {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //70 - floating point, mmx stuff {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //80 - long-displacement jumps {OJOS, AJv, }, {OJOC, AJv, }, {OJCS, AJv, }, {OJCC, AJv, }, {OJEQ, AJv, }, {OJNE, AJv, }, {OJLS, AJv, }, {OJHI, AJv, }, {OJMI, AJv, }, {OJPL, AJv, }, {OJPS, AJv, }, {OJPC, AJv, }, {OJLT, AJv, }, {OJGE, AJv, }, {OJLE, AJv, }, {OJGT, AJv, }, //90 - conditional byte set {OSETOS,AEb, }, {OSETOC,AEb, }, {OSETCS,AEb, }, {OSETCC,AEb, }, {OSETEQ,AEb, }, {OSETNE,AEb, }, {OSETLS,AEb, }, {OSETHI,AEb, }, {OSETMI,AEb, }, {OSETPL,AEb, }, {OSETPS,AEb, }, {OSETPC,AEb, }, {OSETLT,AEb, }, {OSETGE,AEb, }, {OSETLE,AEb, }, {OSETGT,AEb, }, //A0 {OPUSH, AFS, }, {OPOP, AFS, }, {OBAD, }, {OBT, AEv, AGv}, {OSHLD,AEv,AGv,AIb}, {OSHLD,AEv,AGv,ACL}, {OBAD, }, {OBAD, }, {OPUSH, AGS, }, {OPOP, AGS, }, {OBAD, }, {OBTS, AEv, AGv}, {OSHRD,AEv,AGv,AIb}, {OSHRD,AEv,AGv,ACL}, {OBAD, }, {OIMUL, AGv,AGv,AEv}, //B0 - mostly arcana {OBAD, }, {OBAD, }, {OLFP,ASS,AGv,AMp},{OBAD, }, {OLFP,AFS,AGv,AMp},{OLFP,AGS,AGv,AMp},{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //C0 - more arcana {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //D0 - mmx {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //E0 - mmx {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //F0 - mmx {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, }; /* some operands map to whole groups; group numbers from intel opcode map */ /* args filled in already (in OGP1 entries) */ static Optab optabgp1[8] = { {OADD, }, {OOR, }, {OADC, }, {OSBB, }, {OAND, }, {OSUB, }, {OXOR, }, {OCMP, }, }; /* args filled in already (in OGP2 entries) */ static Optab optabgp2[8] = { {OROL, }, {OROR, }, {ORCL, }, {ORCR, }, {OSHL, }, {OSHR, }, {OBAD, }, {OSAR, }, }; static Optab optabgp3b[8] = { {OTEST, AEb, AIb}, {OBAD, }, {ONOT, AEb, }, {ONEG, AEb, }, {OMUL,AAX,AAL,AEb},{OIMUL,AAX,AAL,AEb},{ODIV, AEb, }, {OIDIV, AEb, }, }; static Optab optabgp3v[8] = { {OTEST, AEv, AIv}, {OBAD, }, {ONOT, AEv, }, {ONEG, AEv, }, {OMUL,AAX,AAX,AEv},{OIMUL,AAX,AAX,AEv},{ODIV, AEv, }, {OIDIV, AEv, }, }; static Optab optabgp4[8] = { {OINC, AEb, }, {ODEC, AEb, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, }; static Optab optabgp5[8] = { {OINC, AEv, }, {ODEC, AEv, }, {OCALL, AEv, }, {OCALL, AEp }, {OJMP, AEv, }, {OJMP, AEp, }, {OPUSH, AEv, }, {OBAD, }, }; /* optabg6 unimplemented - mostly segment manipulation */ /* optabg7 unimplemented - more segment manipulation */ /* optabg8 unimplemented - bit tests */ /* * most of optabg9 - optabg16 decode differently depending on the mod value of * the modrm byte. they're mostly arcane instructions so they're not * implemented. */ /* * the above tables are in intel order, in which data moves right to left. * change to plan9, left to right. */ static void revtab(Optab *o, int n) { int i, t; for(i=0; iop){ case ENAME: return 1; case ECONST: return 1; case EMUL: case EADD: case ESUB: return isconst(e->arg[0]) && isconst(e->arg[1]); default: return 0; } } static int matcharg(int a, Expr *e, Istate *is) { int seg; int off; if(a==ANONE && e==nil) return 1; if(a==ANONE || e==nil) return 0; switch(a){ case AAp: /* seg:off immediate address */ if(e->op==ESEG && isconst(e->arg[0]) && isconst(e->arg[1])){ seg = e->arg[0]->con; is->byte[is->nbyte++] = seg; is->byte[is->nbyte++] = seg>>8; off = e->arg[0]->con; is->byte[is->nbyte++] = off; is->byte[is->nbyte++] = off>>8; return 1; } return 0; case AEb: /* r/m8 from modrm byte */ if(e->op==EREG && e->sz==8 && e->reg<8){ is->mod = 3; is->rm = e->reg; is->needmodrm = 1; return 1; } if(e->op==EBYTE && matchmodrm(e, is)) return 1; return 0; case AEp: /* call indirect through memory */ if(e->op==EADDR && matchmodrm(e, is)) return 1; return 0; case AEw: case AEv: /* r/m16 or r/m32 from modrm byte */ if(e->op==EREG && e->sz==16 && e->reg<8){ is->mod = 3; is->rm = e->reg; is->needmodrm = 1; return 1; } if(e->op==EWORD && matchmodrm(e, is)) return 1; return 0; case AGb: /* r8 from modrm byte */ if(e->op==EREG && e->sz==8 && e->reg<8){ is->rop = e->reg; is->needmodrm = 1; return 1; } return 0; case AGv: /* r16 or r32 from modrm byte */ if(e->op==EREG && e->sz==16 && e->reg<8){ is->rop = e->reg; is->needmodrm = 1; return 1; } return 0; case AGw: /* r/m 16 */ if(e->op==EREG && e->sz==16 && e->reg<8){ is->rop = e->reg; is->needmodrm = 1; return 1; } return 0; case AIb: /* immediate byte */ if(isconst(e) && 0x00 <= e->con && e->con <= 0xFF){ is->consz = 1; is->conoff = is->nbyte; is->byte[is->nbyte++] = e->con; return 1; } return 0; case AIc: /* immediate byte sign-extended */ if(isconst(e) && -0x80 <= e->con && e->con <= 0x7F){ is->consz = 1; is->conoff = is->nbyte; is->byte[is->nbyte++] = e->con; return 1; } return 0; case AIw: /* immediate 16-bit word */ if(isconst(e)){ is->consz = 2; is->conoff = is->nbyte; is->byte[is->nbyte++] = e->con; is->byte[is->nbyte++] = e->con>>8; return 1; } return 0; case AIv: /* immediate 16-bit or 32-bit word */ if(isconst(e)){ is->consz = 2; is->conoff = is->nbyte; is->byte[is->nbyte++] = e->con; is->byte[is->nbyte++] = e->con>>8; return 1; } return 0; case AJb: /* relative offset byte */ if(e->sz==1){ is->jmpoff = is->nbyte++; return 1; } return 0; case AJv: /* relative offset 16-bit or 32-bit word */ if(e->sz==2){ is->jmpoff = is->nbyte; is->nbyte += 2; return 1; } return 0; case AJr: /* r/m16 or r/m32 register */ if(e->op==EREG && e->sz==16 && e->reg<8){ is->needmodrm = 1; is->mod = 3; is->rm = e->reg; return 1; } return 0; case AM: /* memory address from modrm */ if(e->op==EADDR && matchmodrm(e, is)) return 1; return 0; case AMa: /* something for bound? */ if(e->op==EADDR && matchmodrm(e, is)) return 1; return 0; case AMp: /* 32-bit or 48-bit memory address */ return e->op==EADDR && matchmodrm(e, is); case AOb: /* immediate word-sized offset to a byte */ return 0; case AOv: /* immediate word-sized offset to a word */ return 0; case ASw: /* segment register selected by field of modrm */ if(e->op==EREG && e->reg >= RES && e->reg <= RDS){ is->needmodrm = 1; is->rop = e->reg - RES; return 1; } return 0; case AAL: return e->op==EREG && e->sz==8 && e->reg==RAL; case ACL: return e->op==EREG && e->sz==8 && e->reg==RCL; case ADL: return e->op==EREG && e->sz==8 && e->reg==RDL; case ABL: return e->op==EREG && e->sz==8 && e->reg==RBL; case AAH: return e->op==EREG && e->sz==8 && e->reg==RAH; case ACH: return e->op==EREG && e->sz==8 && e->reg==RCH; case ADH: return e->op==EREG && e->sz==8 && e->reg==RDH; case ABH: return e->op==EREG && e->sz==8 && e->reg==RBH; case AAX: return e->op==EREG && e->sz==16 && e->reg==RAX; case ACX: return e->op==EREG && e->sz==16 && e->reg==RCX; case ADX: return e->op==EREG && e->sz==16 && e->reg==RDX; case ABX: return e->op==EREG && e->sz==16 && e->reg==RBX; case ASP: return e->op==EREG && e->sz==16 && e->reg==RSP; case ABP: return e->op==EREG && e->sz==16 && e->reg==RBP; case ASI: return e->op==EREG && e->sz==16 && e->reg==RSI; case ADI: return e->op==EREG && e->sz==16 && e->reg==RDI; case AES: return e->op==EREG && e->sz==16 && e->reg==RES; case ACS: return e->op==EREG && e->sz==16 && e->reg==RCS; case ASS: return e->op==EREG && e->sz==16 && e->reg==RSS; case ADS: return e->op==EREG && e->sz==16 && e->reg==RDS; case AFS: return e->op==EREG && e->sz==16 && e->reg==RFS; case AGS: return e->op==EREG && e->sz==16 && e->reg==RGS; default: return 0; } } static void match(Optab *o, int b, Inst *inst, Istate *is) { uchar xb[16]; int nxb; int i, modrmoff; Istate ts, ots; Optab *og; switch(o->op){ case O0F: ots = *is; ots.byte[ots.nbyte++] = 0x0F; for(i=0; iop]; for(i=0; i<8; i++){ if(o->arg1!=ANONE) og[i].arg1 = o->arg1; if(o->arg2!=ANONE) og[i].arg2 = o->arg2; if(o->arg3!=ANONE) og[i].arg3 = o->arg3; ts = ots; ts.rop = i; ts.needmodrm = 1; match(&og[i], b, inst, &ts); } return; } if(o->op != inst->op) return; ts = *is; ts.byte[ts.nbyte++] = b; modrmoff = ts.nbyte; if(!matcharg(o->arg1, inst->arg[0], &ts)) return; if(!matcharg(o->arg2, inst->arg[1], &ts)) return; if(!matcharg(o->arg3, inst->arg[2], &ts)) return; if(ts.needmodrm){ nxb = ts.nbyte - modrmoff; memmove(xb, ts.byte+modrmoff, nxb); ts.nbyte = modrmoff; ts.byte[ts.nbyte++] = (ts.mod<<6) | (ts.rop<<3) | ts.rm; if(ts.mod==1) ts.byte[ts.nbyte++] = ts.disp; if((ts.mod==0 && ts.rm==6) || ts.mod==2){ ts.byte[ts.nbyte++] = ts.disp; ts.byte[ts.nbyte++] = ts.disp>>8; } memmove(ts.byte+ts.nbyte, xb, nxb); ts.nbyte += nxb; } if(ts.nbyte < inst->nbyte) inst->Istate = ts; } static int isjmp[NUMOP] = { [OJCXZ] 1, [OJOS] 1, [OJOC] 1, [OJCS] 1, [OJCC] 1, [OJEQ] 1, [OJNE] 1, [OJLS] 1, [OJHI] 1, [OJMI] 1, [OJPL] 1, [OJPS] 1, [OJPC] 1, [OJLT] 1, [OJGE] 1, [OJLE] 1, [OJGT] 1, [OJMP] 1, }; static uchar prefix[] = { 0xF0, 0xF2, 0xF3, 0x26, 0x2E, 0x36, 0x3E, 0x64, 0x65 }; static int domatch(Inst *inst) { int i; Istate ts; memset(&ts, 0, sizeof ts); for(i=0; inpref; i++) ts.byte[ts.nbyte++] = prefix[inst->pref[i]]; inst->nbyte = 1000; for(i=0; inbyte == 1000) return -1; return 0; } int assinst(Inst *inst) { /* calc both spans if(isjmp[inst->op] && inst->arg[0] && inst->arg[0]->op != EREG){ if(inst->arg[0]==nil) return -1; inst->arg[0]->sz = 1; if(domatch(inst) < 0) return -1; inst->span1 = inst->Istate; inst->arg[0]->sz = 2; if(domatch(inst) < 0) return -1; inst->span2 = inst->Istate; inst->isspan = 1; return 0; } */ /* punt on spans for now: */ if(isjmp[inst->op] && isconst(inst->arg[0])) inst->arg[0]->sz = 2; if(inst->op == OLABEL){ inst->nbyte = 0; return 0; } return domatch(inst); }