rendered paste body#define BITS8 0x00000001L#define BITS16 0x00000002L#define BITS32 0x00000004L#define BITS64 0x00000008L /* FPU only */#define BITS80 0x00000010L /* FPU only */#define FAR 0x00000020L /* grotty: this means 16:16 or *//* 16:32, like in CALL/JMP */#define NEAR 0x00000040L#define SHORT 0x00000080L /* and this means what it says :) */#define SIZE_MASK 0x000000FFL /* all the size attributes */#define NON_SIZE (~SIZE_MASK)#define TO 0x00000100L /* reverse effect in FADD, FSUB &c */#define COLON 0x00000200L /* operand is followed by a colon *//* type of operand: memory reference, register, etc. */#define MEMORY 0x00204000L#define REGISTER 0x00001000L /* register number in 'basereg' */#define IMMEDIATE 0x00002000L#define REGMEM 0x00200000L /* for r/m, ie EA, operands */#define REGNORM 0x00201000L /* 'normal' reg, qualifies as EA */#define REG8 0x00201001L#define REG16 0x00201002L#define REG32 0x00201004L#define MMXREG 0x00201008L /* MMX registers */#define FPUREG 0x01000000L /* floating point stack registers */#define FPU0 0x01000800L /* FPU stack register zero *//* special register operands: these may be treated differently */#define REG_SMASK 0x00070000L /* a mask for the following */#define REG_ACCUM 0x00211000L /* accumulator: AL, AX or EAX */#define REG_AL 0x00211001L /* REG_ACCUM | BITSxx */#define REG_AX 0x00211002L /* ditto */#define REG_EAX 0x00211004L /* and again */#define REG_COUNT 0x00221000L /* counter: CL, CX or ECX */#define REG_CL 0x00221001L /* REG_COUNT | BITSxx */#define REG_CX 0x00221002L /* ditto */#define REG_ECX 0x00221004L /* another one */#define REG_DX 0x00241002L#define REG_SREG 0x00081002L /* any segment register */#define REG_CS 0x01081002L /* CS */#define REG_DESS 0x02081002L /* DS, ES, SS (non-CS 86 registers) */#define REG_FSGS 0x04081002L /* FS, GS (386 extended registers) */#define REG_CDT 0x00101004L /* CRn, DRn and TRn */#define REG_CREG 0x08101004L /* CRn */#define REG_CR4 0x08101404L /* CR4 (Pentium only) */#define REG_DREG 0x10101004L /* DRn */#define REG_TREG 0x20101004L /* TRn */typedef struct { /* operand to an instruction */ long type; /* type of operand */ int addr_size; /* 0 means default; 16; 32 */ int basereg, indexreg, scale; /* registers and scale involved */ int hintbase, hinttype; /* hint as to real base register */ long segment; /* immediate segment, if needed */ long offset; /* any immediate number */ long wrt; /* segment base it's relative to */ int eaflags; /* special EA flags */} operand;typedef struct extop { /* extended operand */ struct extop *next; /* linked list */ long type; /* defined above */ char *stringval; /* if it's a string, then here it is */ int stringlen; /* ... and here's how long it is */ long segment; /* if it's a number/address, then... */ long offset; /* ... it's given here ... */ long wrt; /* ... and here */} extop;#define MAXPREFIX 4typedef struct { /* an instruction itself */ char *label; /* the label defined, or NULL */ int prefixes[MAXPREFIX]; /* instruction prefixes, if any */ int nprefix; /* number of entries in above */ int opcode; /* the opcode - not just the string */ int condition; /* the condition code, if Jcc/SETcc */ int operands; /* how many operands? 0-3 */ operand oprs[3]; /* the operands, defined as above */ extop *eops; /* extended operands */ long times; /* repeat count (TIMES prefix) */ int forw_ref; /* is there a forward reference? */} insn;struct itemplate { int opcode; /* the token, passed from "parser.c" */ int operands; /* number of operands */ long opd[3]; /* bit flags for operand types */ char *code; /* the code it assembles to */ int flags; /* some flags */};#define SEG_RELATIVE 1#define SEG_32BIT 2#define SEG_RMREG 4#define SEG_DISP8 8#define SEG_DISP16 16#define SEG_DISP32 32#define SEG_NODISP 64#define SEG_SIGNED 128#define EXPR_REG_START 1#define EXPR_REG_END 124#define EXPR_UNKNOWN 125L /* for forward references */#define EXPR_SIMPLE 126L#define EXPR_WRT 127L#define EXPR_SEGBASE 128Lenum { /* register names */ R_AH = EXPR_REG_START, R_AL, R_AX, R_BH, R_BL, R_BP, R_BX, R_CH, R_CL, R_CR0, R_CR2, R_CR3, R_CR4, R_CS, R_CX, R_DH, R_DI, R_DL, R_DR0, R_DR1, R_DR2, R_DR3, R_DR6, R_DR7, R_DS, R_DX, R_EAX, R_EBP, R_EBX, R_ECX, R_EDI, R_EDX, R_ES, R_ESI, R_ESP, R_FS, R_GS, R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7, R_SI, R_SP, R_SS, R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7, R_TR3, R_TR4, R_TR5, R_TR6, R_TR7, REG_ENUM_LIMIT};enum { /* instruction names */ I_AAA, I_AAD, I_AAM, I_AAS, I_ADC, I_ADD, I_AND, I_ARPL, I_BOUND, I_BSF, I_BSR, I_BSWAP, I_BT, I_BTC, I_BTR, I_BTS, I_CALL, I_CBW, I_CDQ, I_CLC, I_CLD, I_CLI, I_CLTS, I_CMC, I_CMP, I_CMPSB, I_CMPSD, I_CMPSW, I_CMPXCHG, I_CMPXCHG486, I_CMPXCHG8B, I_CPUID, I_CWD, I_CWDE, I_DAA, I_DAS, I_DB, I_DD, I_DEC, I_DIV, I_DQ, I_DT, I_DW, I_EMMS, I_ENTER, I_EQU, I_F2XM1, I_FABS, I_FADD, I_FADDP, I_FBLD, I_FBSTP, I_FCHS, I_FCLEX, I_FCMOVB, I_FCMOVBE, I_FCMOVE, I_FCMOVNB, I_FCMOVNBE, I_FCMOVNE, I_FCMOVNU, I_FCMOVU, I_FCOM, I_FCOMI, I_FCOMIP, I_FCOMP, I_FCOMPP, I_FCOS, I_FDECSTP, I_FDISI, I_FDIV, I_FDIVP, I_FDIVR, I_FDIVRP, I_FENI, I_FFREE, I_FIADD, I_FICOM, I_FICOMP, I_FIDIV, I_FIDIVR, I_FILD, I_FIMUL, I_FINCSTP, I_FINIT, I_FIST, I_FISTP, I_FISUB, I_FISUBR, I_FLD, I_FLD1, I_FLDCW, I_FLDENV, I_FLDL2E, I_FLDL2T, I_FLDLG2, I_FLDLN2, I_FLDPI, I_FLDZ, I_FMUL, I_FMULP, I_FNCLEX, I_FNDISI, I_FNENI, I_FNINIT, I_FNOP, I_FNSAVE, I_FNSTCW, I_FNSTENV, I_FNSTSW, I_FPATAN, I_FPREM, I_FPREM1, I_FPTAN, I_FRNDINT, I_FRSTOR, I_FSAVE, I_FSCALE, I_FSETPM, I_FSIN, I_FSINCOS, I_FSQRT, I_FST, I_FSTCW, I_FSTENV, I_FSTP, I_FSTSW, I_FSUB, I_FSUBP, I_FSUBR, I_FSUBRP, I_FTST, I_FUCOM, I_FUCOMI, I_FUCOMIP, I_FUCOMP, I_FUCOMPP, I_FXAM, I_FXCH, I_FXTRACT, I_FYL2X, I_FYL2XP1, I_HLT, I_IBTS, I_ICEBP, I_IDIV, I_IMUL, I_IN, I_INC, I_INCBIN, I_INSB, I_INSD, I_INSW, I_INT, I_INT1, I_INT01, I_INT3, I_INTO, I_INVD, I_INVLPG, I_IRET, I_IRETD, I_IRETW, I_JCXZ, I_JECXZ, I_JMP, I_LAHF, I_LAR, I_LDS, I_LEA, I_LEAVE, I_LES, I_LFS, I_LGDT, I_LGS, I_LIDT, I_LLDT, I_LMSW, I_LOADALL, I_LOADALL286, I_LODSB, I_LODSD, I_LODSW, I_LOOP, I_LOOPE, I_LOOPNE, I_LOOPNZ, I_LOOPZ, I_LSL, I_LSS, I_LTR, I_MOV, I_MOVD, I_MOVQ, I_MOVSB, I_MOVSD, I_MOVSW, I_MOVSX, I_MOVZX, I_MUL, I_NEG, I_NOP, I_NOT, I_OR, I_OUT, I_OUTSB, I_OUTSD, I_OUTSW, I_PACKSSDW, I_PACKSSWB, I_PACKUSWB, I_PADDB, I_PADDD, I_PADDSB, I_PADDSIW, I_PADDSW, I_PADDUSB, I_PADDUSW, I_PADDW, I_PAND, I_PANDN, I_PAVEB, I_PCMPEQB, I_PCMPEQD, I_PCMPEQW, I_PCMPGTB, I_PCMPGTD, I_PCMPGTW, I_PDISTIB, I_PMACHRIW, I_PMADDWD, I_PMAGW, I_PMULHRW, I_PMULHRIW, I_PMULHW, I_PMULLW, I_PMVGEZB, I_PMVLZB, I_PMVNZB, I_PMVZB, I_POP, I_POPA, I_POPAD, I_POPAW, I_POPF, I_POPFD, I_POPFW, I_POR, I_PSLLD, I_PSLLQ, I_PSLLW, I_PSRAD, I_PSRAW, I_PSRLD, I_PSRLQ, I_PSRLW, I_PSUBB, I_PSUBD, I_PSUBSB, I_PSUBSIW, I_PSUBSW, I_PSUBUSB, I_PSUBUSW, I_PSUBW, I_PUNPCKHBW, I_PUNPCKHDQ, I_PUNPCKHWD, I_PUNPCKLBW, I_PUNPCKLDQ, I_PUNPCKLWD, I_PUSH, I_PUSHA, I_PUSHAD, I_PUSHAW, I_PUSHF, I_PUSHFD, I_PUSHFW, I_PXOR, I_RCL, I_RCR, I_RDMSR, I_RDPMC, I_RDTSC, I_RESB, I_RESD, I_RESQ, I_REST, I_RESW, I_RET, I_RETF, I_RETN, I_ROL, I_ROR, I_RSM, I_SAHF, I_SAL, I_SALC, I_SAR, I_SBB, I_SCASB, I_SCASD, I_SCASW, I_SGDT, I_SHL, I_SHLD, I_SHR, I_SHRD, I_SIDT, I_SLDT, I_SMI, I_SMSW, I_STC, I_STD, I_STI, I_STOSB, I_STOSD, I_STOSW, I_STR, I_SUB, I_TEST, I_UMOV, I_VERR, I_VERW, I_WAIT, I_WBINVD, I_WRMSR, I_XADD, I_XBTS, I_XCHG, I_XLATB, I_XOR, I_CMOVcc, I_Jcc, I_SETcc};enum { /* condition code names */ C_A, C_AE, C_B, C_BE, C_C, C_E, C_G, C_GE, C_L, C_LE, C_NA, C_NAE, C_NB, C_NBE, C_NC, C_NE, C_NG, C_NGE, C_NL, C_NLE, C_NO, C_NP, C_NS, C_NZ, C_O, C_P, C_PE, C_PO, C_S, C_Z};static int whichreg(long regflags, int regval) { static int reg32[] = { R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI }; static int reg16[] = { R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI }; static int reg8[] = { R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH }; static int sreg[] = { R_ES, R_CS, R_SS, R_DS, R_FS, R_GS, 0, 0 }; static int creg[] = { R_CR0, 0, R_CR2, R_CR3, R_CR4, 0, 0, 0 }; static int dreg[] = { R_DR0, R_DR1, R_DR2, R_DR3, 0, 0, R_DR6, R_DR7 }; static int treg[] = { 0, 0, 0, R_TR3, R_TR4, R_TR5, R_TR6, R_TR7 }; static int fpureg[] = { R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7 }; static int mmxreg[] = { R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7 }; if (!(REG_AL & ~regflags)) return R_AL; if (!(REG_AX & ~regflags)) return R_AX; if (!(REG_EAX & ~regflags)) return R_EAX; if (!(REG_DX & ~regflags)) return R_DX; if (!(REG_CL & ~regflags)) return R_CL; if (!(REG_CX & ~regflags)) return R_CX; if (!(REG_ECX & ~regflags)) return R_ECX; if (!(REG_CR4 & ~regflags)) return R_CR4; if (!(FPU0 & ~regflags)) return R_ST0; if (!(REG_CS & ~regflags)) return R_CS; if (!(REG_DESS & ~regflags)) return (regval == 0 || regval == 2 || regval == 3 ? sreg[regval] : 0); if (!(REG_FSGS & ~regflags)) return (regval == 4 || regval == 5 ? sreg[regval] : 0); if (!((REGMEM|BITS8) & ~regflags)) return reg8[regval]; if (!((REGMEM|BITS16) & ~regflags)) return reg16[regval]; if (!((REGMEM|BITS32) & ~regflags)) return reg32[regval]; if (!(REG_SREG & ~regflags)) return sreg[regval]; if (!(REG_CREG & ~regflags)) return creg[regval]; if (!(REG_DREG & ~regflags)) return dreg[regval]; if (!(REG_TREG & ~regflags)) return treg[regval]; if (!(FPUREG & ~regflags)) return fpureg[regval]; if (!(MMXREG & ~regflags)) return mmxreg[regval]; return 0;}static char *reg_names[] = { /* register names, as strings */ "ah", "al", "ax", "bh", "bl", "bp", "bx", "ch", "cl", "cr0", "cr2", "cr3", "cr4", "cs", "cx", "dh", "di", "dl", "dr0", "dr1", "dr2", "dr3", "dr6", "dr7", "ds", "dx", "eax", "ebp", "ebx", "ecx", "edi", "edx", "es", "esi", "esp", "fs", "gs", "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", "si", "sp", "ss", "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7", "tr3", "tr4", "tr5", "tr6", "tr7"};static char *insn_names[] = { /* instruction names, as strings */ "aaa", "aad", "aam", "aas", "adc", "add", "and", "arpl", "bound", "bsf", "bsr", "bswap", "bt", "btc", "btr", "bts", "call", "cbw", "cdq", "clc", "cld", "cli", "clts", "cmc", "cmp", "cmpsb", "cmpsd", "cmpsw", "cmpxchg", "cmpxchg486", "cmpxchg8b", "cpuid", "cwd", "cwde", "daa", "das", "db", "dd", "dec", "div", "dq", "dt", "dw", "emms", "enter", "equ", "f2xm1", "fabs", "fadd", "faddp", "fbld", "fbstp", "fchs", "fclex", "fcmovb", "fcmovbe", "fcmove", "fcmovnb", "fcmovnbe", "fcmovne", "fcmovnu", "fcmovu", "fcom", "fcomi", "fcomip", "fcomp", "fcompp", "fcos", "fdecstp", "fdisi", "fdiv", "fdivp", "fdivr", "fdivrp", "feni", "ffree", "fiadd", "ficom", "ficomp", "fidiv", "fidivr", "fild", "fimul", "fincstp", "finit", "fist", "fistp", "fisub", "fisubr", "fld", "fld1", "fldcw", "fldenv", "fldl2e", "fldl2t", "fldlg2", "fldln2", "fldpi", "fldz", "fmul", "fmulp", "fnclex", "fndisi", "fneni", "fninit", "fnop", "fnsave", "fnstcw", "fnstenv", "fnstsw", "fpatan", "fprem", "fprem1", "fptan", "frndint", "frstor", "fsave", "fscale", "fsetpm", "fsin", "fsincos", "fsqrt", "fst", "fstcw", "fstenv", "fstp", "fstsw", "fsub", "fsubp", "fsubr", "fsubrp", "ftst", "fucom", "fucomi", "fucomip", "fucomp", "fucompp", "fxam", "fxch", "fxtract", "fyl2x", "fyl2xp1", "hlt", "ibts", "icebp", "idiv", "imul", "in", "inc", "incbin", "insb", "insd", "insw", "int", "int1", "int01", "int3", "into", "invd", "invlpg", "iret", "iretd", "iretw", "jcxz", "jecxz", "jmp", "lahf", "lar", "lds", "lea", "leave", "les", "lfs", "lgdt", "lgs", "lidt", "lldt", "lmsw", "loadall", "loadall286", "lodsb", "lodsd", "lodsw", "loop", "loope", "loopne", "loopnz", "loopz", "lsl", "lss", "ltr", "mov", "movd", "movq", "movsb", "movsd", "movsw", "movsx", "movzx", "mul", "neg", "nop", "not", "or", "out", "outsb", "outsd", "outsw", "packssdw", "packsswb", "packuswb", "paddb", "paddd", "paddsb", "paddsiw", "paddsw", "paddusb", "paddusw", "paddw", "pand", "pandn", "paveb", "pcmpeqb", "pcmpeqd", "pcmpeqw", "pcmpgtb", "pcmpgtd", "pcmpgtw", "pdistib", "pmachriw", "pmaddwd", "pmagw", "pmulhrw", "pmulhriw", "pmulhw", "pmullw", "pmvgezb", "pmvlzb", "pmvnzb", "pmvzb", "pop", "popa", "popad", "popaw", "popf", "popfd", "popfw", "por", "pslld", "psllq", "psllw", "psrad", "psraw", "psrld", "psrlq", "psrlw", "psubb", "psubd", "psubsb", "psubsiw", "psubsw", "psubusb", "psubusw", "psubw", "punpckhbw", "punpckhdq", "punpckhwd", "punpcklbw", "punpckldq", "punpcklwd", "push", "pusha", "pushad", "pushaw", "pushf", "pushfd", "pushfw", "pxor", "rcl", "rcr", "rdmsr", "rdpmc", "rdtsc", "resb", "resd", "resq", "rest", "resw", "ret", "retf", "retn", "rol", "ror", "rsm", "sahf", "sal", "salc", "sar", "sbb", "scasb", "scasd", "scasw", "sgdt", "shl", "shld", "shr", "shrd", "sidt", "sldt", "smi", "smsw", "stc", "std", "sti", "stosb", "stosd", "stosw", "str", "sub", "test", "umov", "verr", "verw", "wait", "wbinvd", "wrmsr", "xadd", "xbts", "xchg", "xlatb", "xor"};static char *icn[] = { /* conditional instructions */ "cmov", "j", "set"};static int ico[] = { /* and the corresponding opcodes */ I_CMOVcc, I_Jcc, I_SETcc};static char *conditions[] = { /* condition code names */ "a", "ae", "b", "be", "c", "e", "g", "ge", "l", "le", "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no", "np", "ns", "nz", "o", "p", "pe", "po", "s", "z"};static char *whichcond(int condval) { static int conds[] = { C_O, C_NO, C_C, C_NC, C_Z, C_NZ, C_NA, C_A, C_S, C_NS, C_PE, C_PO, C_L, C_NL, C_NG, C_G }; return conditions[conds[condval]];}