#include #include #include #include typedef ulong Reg; typedef struct Inst Inst; typedef struct Expr Expr; typedef struct Istate Istate; /* * Various routines depend on this order. In particular, * the order of RAX..RDI is used by pushseg, popseg, * increg, decreg, pushreg, popreg, pusha, popa, */ enum { RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, RES, RCS, RSS, RDS, RFS, RGS, NREG, RAL = 0, RCL, RDL, RBL, RAH, RCH, RDH, RBH, }; enum { /* argument types */ ANONE, /* no argument */ A0, /* constant 0 */ A1, /* constant 1 */ A3, /* constant 3 */ A4, /* constant 4 */ AAp, /* 32-bit or 48-bit direct address */ AEb, /* r/m8 from modrm byte */ AEp, /* call indirect through memory */ AEv, /* r/m16 or r/m32 from modrm byte */ AEw, /* r/m16 */ AFv, /* flag word */ AGb, /* r8 from modrm byte */ AGv, /* r16 or r32 from modrm byte */ AGw, /* r/m16 */ AIb, /* immediate byte */ AIc, /* immediate byte sign-extended */ AIw, /* immediate 16-bit word */ AIv, /* immediate 16-bit or 32-bit word */ AJb, /* relative offset byte */ AJv, /* relative offset 16-bit or 32-bit word */ AJr, /* r/m16 or r/m32 register */ AM, /* memory address from modrm */ AMa, /* something for bound */ AMa2, AMp, /* 32-bit or 48-bit memory address */ AOb, /* immediate word-sized offset to a byte */ AOv, /* immediate word-size offset to a word */ ASw, /* segment register selected by r field of modrm */ AXb, /* byte at DS:SI */ AXv, /* word at DS:SI */ AYb, /* byte at ES:DI */ AYv, /* word at ES:DI */ AAL, /* registers; should be in same order as RAL, etc. */ ACL, ADL, ABL, AAH, ACH, ADH, ABH, AAX, /* registers; should be in same order as RAX, etc. */ ACX, ADX, ABX, ASP, ABP, ASI, ADI, AES, ACS, ASS, ADS, AFS, AGS, NAMODE, }; enum { /* operators */ OBAD, O0F, OAAA, OAAD, OAAM, OAAS, OADC, OADD, OAND, OARPL, OASIZE, OBOUND, OBT, OBTS, OCALL, OCBW, OCLC, OCLD, OCLI, OCMC, OCMOVOS, OCMOVOC, OCMOVCS, OCMOVCC, OCMOVEQ, OCMOVNE, OCMOVLS, OCMOVHI, OCMOVMI, OCMOVPL, OCMOVPS, OCMOVPC, OCMOVLT, OCMOVGE, OCMOVLE, OCMOVGT, OCMP, OCMPS, OCWD, ODAA, ODAS, ODEC, ODIV, OENTER, OGP1, OGP2, OGP3b, OGP3v, OGP4, OGP5, OHLT, OIDIV, OIMUL, OIN, OINC, OINS, OINT, OIRET, OJCXZ, OJOS, OJOC, OJCS, OJCC, OJEQ, OJNE, OJLS, OJHI, OJMI, OJPL, OJPS, OJPC, OJLT, OJGE, OJLE, OJGT, OJMP, OLABEL, OLAHF, OLEA, OLEAVE, OLFP, OLOCK, OLODS, OLOOP, OLOOPNZ, OLOOPZ, OMOV, OMOVS, OMUL, ONEG, ONOP, ONOT, OOR, OOSIZE, OOUT, OOUTS, OPOP, OPOPA, OPOPF, OPUSH, OPUSHA, OPUSHF, ORCL, ORCR, OREPZ, OREPNZ, ORET, ORETF, OROL, OROR, OSAHF, OSAR, OSBB, OSCAS, OSEG, OSETOS, OSETOC, OSETCS, OSETCC, OSETEQ, OSETNE, OSETLS, OSETHI, OSETMI, OSETPL, OSETPS, OSETPC, OSETLT, OSETGE, OSETLE, OSETGT, OSHL, OSHLD, OSHR, OSHRD, OSTC, OSTD, OSTI, OSTOS, OSUB, OTEST, OWAIT, OXCHG, OXLAT, OXOR, NUMOP, }; enum { PLOCK, PREPN, PREP, PES, PCS, PSS, PDS, PFS, PGS, }; struct Istate { uchar byte[16]; /* instruction bytes */ uint nbyte; uchar rop; uchar mod; uchar rm; ulong off; /* memory address from modrm */ long disp; /* displacement from modrm */ uchar needmodrm; int jmpoff; /* index into byte array of jmp offset */ int conoff; int consz; }; struct Inst { int op; /* instruction pseudo-opcode (OFOO) */ char *label; /* text of label */ Expr *arg[3]; int narg; int pref[10]; int npref; int isspan; /* is span-dependent */ int seg; /* segment to use */ ulong spc; /* program counter for start of inst */ ulong epc; /* program counter for end of inst */ Istate; /* Istate span1; Istate span2; */ }; enum { EREG, ESEG, EBYTE, EWORD, ENAME, EADDR, EMUL, EADD, ESUB, ECONST, EINDIRECT, NEXPR, }; struct Expr { uchar op; Expr *arg[3]; int con; int sz; int reg; char *s; }; #pragma varargck type "I" Inst* #pragma varargck type "E" Expr* void *emalloc(int); char *estrdup(char*); int instfmt(Fmt*); int exprfmt(Fmt*); Inst *parseinst(char*); void parseerror(char*, ...); #pragma varargck argpos parseerror 1 int assinst(Inst*); void plan9order(void);