#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ctype.h>
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);
|