typedef ulong Reg;
/*
* 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,
};
/* processor flags */
enum {
CF = 1<<0, /* carry flag */
PF = 1<<2, /* parity flag */
AF = 1<<4, /* aux carry flag */
ZF = 1<<6, /* zero flag */
SF = 1<<7, /* sign flag */
TF = 1<<8, /* trap flag */
IF = 1<<9, /* interrupts enabled flag */
DF = 1<<10, /* direction flag */
OF = 1<<11, /* overflow flag */
IOPL = 3<<12, /* I/O privelege level */
NT = 1<<14, /* nested task */
RF = 1<<16, /* resume flag */
VM = 1<<17, /* virtual-8086 mode */
AC = 1<<18, /* alignment check */
VIF = 1<<19, /* virtual interrupt flag */
VIP = 1<<20, /* virtual interrupt pending */
ID = 1<<21, /* ID flag */
SFOF = 1<<31, /* pseudo-flag, not stored, means SF == OF */
};
#define FLAGMASK (CF|PF|AF|ZF|SF|TF|IF|DF|OF|IOPL|NT|RF|VM|AC|VIF|VIP|ID)
#define FLAGSET (0x00000002)
typedef struct Cpu Cpu;
typedef struct Wordop Wordop;
typedef struct Inst Inst;
struct Cpu {
int (*inb)(int);
int (*inw)(int);
long (*inl)(int);
void (*outb)(int, int);
void (*outw)(int, int);
void (*outl)(int, long);
void (*trap)(Cpu*, Inst*, int);
ulong present64k;
uchar *mem; /* memory; best to segattach in middle of nowhere */
ulong npc; /* next pc, cs */
ushort ncs;
Reg reg[NREG];
ulong flags; /* processor flags */
ulong pc;
uchar trace;
uchar nflag;
int instcount;
ulong addr;
/* internal */
jmp_buf jmp;
jmp_buf exitjmp;
int opsize;
int addrsize;
Inst *inst; /* currently-executing instruction */
};
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,
OCMOV,
OCMP,
OCMPS,
OCWD,
ODAA,
ODAS,
ODEC,
ODIV,
OENTER,
OGP1,
OGP2,
OGP3b,
OGP3v,
OGP4,
OGP5,
OHLT,
OIDIV,
OIMUL,
OIN,
OINC,
OINS,
OINT,
OIRET,
OJUMP,
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,
OREPE,
OREPNE,
ORET,
ORETF,
OROL,
OROR,
OSAHF,
OSAR,
OSBB,
OSCAS,
OSEG,
OSET,
OSHL,
OSHLD,
OSHR,
OSHRD,
OSTC,
OSTD,
OSTI,
OSTOS,
OSUB,
OTEST,
OWAIT,
OXCHG,
OXLAT,
OXOR,
NUMOP,
};
typedef struct Iarg Iarg;
struct Iarg {
long val; /* value of argument */
void (*w)(Cpu*, int, ulong, long); /* write function */
void (*p)(Cpu*, Inst*, Iarg*); /* post-instruction callback */
ushort seg;
uchar sreg;
ulong off;
int atype;
};
struct Inst {
uchar op; /* instruction pseudo-opcode (OFOO) */
uchar i; /* first byte of instruction */
uchar rop;
uchar mod;
uchar rm;
uchar havemodrm;
uchar repeat; /* repeat prefix */
uchar opsize; /* operand size */
uchar addrsize; /* address size */
uchar sreg; /* segment register to use */
int seg; /* segment to use */
ulong spc; /* program counter for start of inst */
ulong epc; /* program counter for end of inst */
ulong off; /* memory address from modrm */
long disp; /* displacement from modrm */
Iarg arg1;
Iarg arg2;
Iarg arg3;
};
struct Wordop {
long (*rreg)(Cpu*, int, ulong); /* ulong ignored; to match fetch */
void (*wreg)(Cpu*, int, ulong, long);
ulong (*fetch)(Cpu*, int, ulong);
long (*fetchs)(Cpu*, int, ulong);
void (*store)(Cpu*, int, ulong, long);
int len; /* bytes: 1, 2, 4 */
};
enum {
TDIV0 = 0, /* software interrupts */
TBADOP = 256, /* pseudo-interrupts */
THALT,
TGP0,
TSEGFAULT,
};
extern Wordop wop8, wop16, wop32;
extern void putflags(Cpu*, int, ulong, long); /* int,ulong ignored */
extern void bumpesdi(Cpu*, Inst*, Iarg*);
extern void bumpdssi(Cpu*, Inst*, Iarg*);
extern void trap(Cpu*, int);
extern int instfmt(Fmt*);
extern int pcfmt(Fmt*);
extern void nextinst(Cpu*, Inst*);
extern void run(Cpu*);
extern void sreg(Cpu*, char**, int);
extern void dumpreg(Cpu*);
extern void push(Cpu*, int, long);
#pragma varargck type "I" Inst*
#pragma varargck type "P" Cpu*
|