📄 decode-table.c
字号:
/* * Copyright (c) 2005, Johns Hopkins University and The EROS Group, LLC. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * * Neither the name of the Johns Hopkins University, nor the name * of The EROS Group, LLC, nor the names of their contributors may * be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. *//* * Table-assisted decoder for the x86 instruction set. */#include <stdbool.h>#include "switches.h"#include "debug.h"#include "machine.h"#include "decode.h"#include "emit.h"/* The following opcode table was obtained from the Appendix A "Opcode * Map" tables of the Pentium family architectural manuals. AMD has * added subsequent enhancements in defining the x86/64 * architecture. Those are NOT reflected here, as we are not trying to * emulate an x86/64 at this time. They probably should be. * * For each opcode, all operands are described. Where an operand is an * "implied" operand, it is indicated with a leading lowercase letter. * * Codes for addressing method: * * A direct address, encoded as an immediate in the instruction * stream. * C reg field of modR/M byte selects a control register. * D reg field of modR/M byte selects a debug register * E a modR/M byte follows opcode and specifies the operand. This may * in turn imply a SIB byte. * F flags register * G the reg field of the modR/M byte selects a general register. * I immediate data * J offset relative to start of next instruction. * M modR/M byte may only refer to memory (BOUND, LES, LDS, LSS, LFS, * LGS, CMPXCHG8b) * O The instruction has no modR/M byte; offset is coded as a word or * double word depending on address size attribute. * R The mod field of the modR/M byte may refer only to a general * register. * S The reg field of the modR/M byte selects a segment register * T The reg field of the modR/M byte selects a test register * X Memory addresses by the DS:SI register pair. * Y Memory addresses by the ES:DI register pair. * * Codes for operand type: * * a Two one word operands in memory or two double word operands in * memory, depending on operand size attribute (BOUND only) * b Byte (regardless of operand size attribute) * c Byte or word, depending on operand size attribute * d Double word (regardless of operand size attribute) * p 32-bit or 48-bit pointer, depending on operand size attribute * q Quad word (regardless of operand size attribute) * s Six-byte pseudo-descriptor * v Word or double word, depending on operand size attribute * w word (regardless of operand size attribute) * * Other encodings: * * 1. register name in all caps indicates that exact register of that * exact size. * 2. three letter name with leading letter downcased (eAX) indicates * either word or double word register according to operand size * * note that neither of these "operands" is ever explicitly encoded! *//* FIX: Check Ib vs sIB *//* After building my original decoder, I looked at the GDB decoder to * see how they handled suffixes. The idea of using capital letters to * signal suffixes was elegant, so I adopted it here. This adoption * was NOT done by copying. * * I independently had used the same capture structure for opcode * arguments. After getting everything keyed I compared the result to * GDB's i386-opcode.c to check for errors. * * B -- trailing 'b' suffix * L -- trailing 'w' or 'l' suffix according to mode. * Q -- trailinq 'd' or 'q' suffix according to mode * W -- b or w (cbw/cwd) according to mode * R -- w or d (cbw/cwd) according to mode * N -- 16 or 32 according to mode (inverted -- for size prefixes) */#define AH ADDR_implied_reg, reg_AH#define AL ADDR_implied_reg, reg_AL#define BH ADDR_implied_reg, reg_BH#define BL ADDR_implied_reg, reg_BL#define CH ADDR_implied_reg, reg_CH#define CL ADDR_implied_reg, reg_CL#define DH ADDR_implied_reg, reg_DH#define DL ADDR_implied_reg, reg_DL#define DX ADDR_implied_reg, reg_DX#define indirDX ADDR_implied_reg, reg_indirDX#define eAX ADDR_implied_reg, reg_EAX#define eBP ADDR_implied_reg, reg_EBP#define eBX ADDR_implied_reg, reg_EBX#define eCX ADDR_implied_reg, reg_ECX#define eDI ADDR_implied_reg, reg_EDI#define eDX ADDR_implied_reg, reg_EDX#define eSI ADDR_implied_reg, reg_ESI#define eSP ADDR_implied_reg, reg_ESP#define EAX ADDR_implied_reg, reg_EAX#define EBP ADDR_implied_reg, reg_EBP#define EBX ADDR_implied_reg, reg_EBX#define ECX ADDR_implied_reg, reg_ECX#define EDI ADDR_implied_reg, reg_EDI#define EDX ADDR_implied_reg, reg_EDX#define ESI ADDR_implied_reg, reg_ESI#define ESP ADDR_implied_reg, reg_ESP#define CS ADDR_seg, reg_CS#define DS ADDR_seg, reg_DS#define ES ADDR_seg, reg_ES#define FS ADDR_seg, reg_FS#define GS ADDR_seg, reg_GS#define SS ADDR_seg, reg_SS#define Ap ADDR_direct, p_mode#define Eb ADDR_E, b_mode#define Ev ADDR_E, v_mode#define Ep ADDR_E, p_mode#define Ew ADDR_E, w_mode#define Gb ADDR_G, b_mode#define Gv ADDR_G, v_mode#define Gw ADDR_G, w_mode#define Ib ADDR_imm, b_mode#define Iv ADDR_imm, v_mode#define Iw ADDR_imm, w_mode#define Jb ADDR_jmp, b_mode#define Jv ADDR_jmp, v_mode#define M ADDR_E, 0#define Ma ADDR_E, v_mode#define Mb ADDR_E, b_mode#define Md ADDR_E, d_mode#define Mp ADDR_E, p_mode#define Mq ADDR_E, q_mode#define Ms ADDR_E, s_mode#define Mw ADDR_E, w_mode#define Mx ADDR_E, x_mode#define My ADDR_E, y_mode#define Mz ADDR_E, z_mode#define Ob ADDR_offset, b_mode#define Ov ADDR_offset, v_mode#define Rd ADDR_R, d_mode /* ?? */#define Cd ADDR_C, d_mode /* ?? */#define Dd ADDR_D, d_mode /* ?? */#define Td ADDR_T, d_mode /* ?? */#define Sw ADDR_seg_reg, w_mode#define Xb ADDR_ds, reg_ESI#define Xv ADDR_ds, reg_ESI#define Yb ADDR_es, reg_EDI#define Yv ADDR_es, reg_EDI#define FREG ADDR_FREG, 0#define NONE 0, 0#define PREFIX(s) s, NONE, NONE, NONE, 0, "(prefix)", DF_PREFIX#define RESERVED "(reserved)", NONE, NONE, NONE, 0, "(reserved)", DF_UNDEFINED#define GROUP(nm) "(group)", NONE, NONE, NONE, (const void *)nm, #nm, DF_GROUP#define TABLE(nm) "(table)", NONE, NONE, NONE, (const void *)nm, #nm, DF_TABLE#define FLOAT(nm) "(float)", NONE, NONE, NONE, (const void *)nm, #nm, DF_FLOAT#define FTABLE(nm) "(float)", NONE, NONE, NONE, (const void *)nm, #nm, DF_ONE_MORE_LEVEL#define EMIT(nm) emit_##nm, "emit_" #nm#define XX 0x0u#define AX DF_ADDRSZ_PREFIX#define XO DF_OPSZ_PREFIX#define AO DF_ADDRSZ_PREFIX | DF_OPSZ_PREFIX#define JJ DF_BRANCH/* Support for MMX Technology, SSE Extensions and SSE2 Extensions Instruction Set Enhancements: (For Now!) */#define MMX_SSE_SSE2 "MMX/SSE/SSE2", M, NONE, NONE, EMIT(normal), AX, NF#define MMX_SSE_SSE2_Ib "MMX/SSE/SSE2", M, Ib, NONE, EMIT(normal), AX, NF#define MMX_SSE_SSE2_None "MMX/SSE/SSE2", NONE, NONE, NONE, EMIT(normal), AX, NFconstOpCode nopbyte0[256] = { { 0x00u, "addB", Eb, Gb, NONE, EMIT(normal), AX, WF }, { 0x01u, "addL", Ev, Gv, NONE, EMIT(normal), AO, WF }, { 0x02u, "addB", Gb, Eb, NONE, EMIT(normal), AX, WF }, { 0x03u, "addL", Gv, Ev, NONE, EMIT(normal), AO, WF }, { 0x04u, "addB", AL, Ib, NONE, EMIT(normal), XX, WF }, { 0x05u, "addL", eAX, Iv, NONE, EMIT(normal), XO, WF }, { 0x06u, "push", ES, NONE, NONE, EMIT(normal), XO, NF }, { 0x07u, "pop", ES, NONE, NONE, EMIT(normal), XO, NF }, /* 0x08 */ { 0x08u, "orB", Eb, Gb, NONE, EMIT(normal), AX, WF }, { 0x09u, "orL", Ev, Gv, NONE, EMIT(normal), AO, WF }, { 0x0au, "orB", Gb, Eb, NONE, EMIT(normal), AX, WF }, { 0x0bu, "orL", Gv, Ev, NONE, EMIT(normal), AO, WF }, { 0x0cu, "orB", AL, Ib, NONE, EMIT(normal), XX, WF }, { 0x0du, "orL", eAX, Iv, NONE, EMIT(normal), XO, WF }, { 0x0eu, "push", CS, NONE, NONE, EMIT(normal), XO, NF }, /* 0x0f is a two-byte opcode escape */ { 0x0fu, TABLE(twoByteOpcodes) }, /* 0x10 */ { 0x10u, "adcB", Eb, Gb, NONE, EMIT(normal), AX, RWF }, { 0x11u, "adcL", Ev, Gv, NONE, EMIT(normal), AO, RWF }, { 0x12u, "adcB", Gb, Eb, NONE, EMIT(normal), AX, RWF }, { 0x13u, "adcL", Gv, Ev, NONE, EMIT(normal), AO, RWF }, { 0x14u, "adcB", AL, Ib, NONE, EMIT(normal), XX, RWF }, { 0x15u, "adcL", eAX, Iv, NONE, EMIT(normal), XO, RWF }, { 0x16u, "push", SS, NONE, NONE, EMIT(normal), XO, NF }, { 0x17u, "pop", SS, NONE, NONE, EMIT(normal), XO, NF }, /* 0x18 */ { 0x18u, "sbbB", Eb, Gb, NONE, EMIT(normal), AX, RWF }, { 0x19u, "sbbL", Ev, Gv, NONE, EMIT(normal), AO, RWF }, { 0x1au, "sbbB", Gb, Eb, NONE, EMIT(normal), AX, RWF }, { 0x1bu, "sbbL", Gv, Ev, NONE, EMIT(normal), AO, RWF }, { 0x1cu, "sbbB", AL, Ib, NONE, EMIT(normal), XX, RWF }, { 0x1du, "sbbL", eAX, Iv, NONE, EMIT(normal), XO, RWF }, { 0x1eu, "push", DS, NONE, NONE, EMIT(normal), XO, NF }, { 0x1fu, "pop", DS, NONE, NONE, EMIT(normal), XO, NF }, /* 0x20 */ { 0x20u, "andB", Eb, Gb, NONE, EMIT(normal), AX, WF }, { 0x21u, "andL", Ev, Gv, NONE, EMIT(normal), AO, WF }, { 0x22u, "andB", Gb, Eb, NONE, EMIT(normal), AX, WF }, { 0x23u, "andL", Gv, Ev, NONE, EMIT(normal), AO, WF }, { 0x24u, "andB", AL, Ib, NONE, EMIT(normal), XX, WF }, { 0x25u, "andL", eAX, Iv, NONE, EMIT(normal), XO, WF }, { 0x26u, PREFIX("es") }, { 0x27u, "daa", NONE, NONE, NONE, EMIT(normal), XX, RWF }, /* 0x28 */ { 0x28u, "subB", Eb, Gb, NONE, EMIT(normal), AX, WF }, { 0x29u, "subL", Ev, Gv, NONE, EMIT(normal), AO, WF }, { 0x2au, "subB", Gb, Eb, NONE, EMIT(normal), AX, WF }, { 0x2bu, "subL", Gv, Ev, NONE, EMIT(normal), AO, WF }, { 0x2cu, "subB", AL, Ib, NONE, EMIT(normal), XX, WF }, { 0x2du, "subL", eAX, Iv, NONE, EMIT(normal), XO, WF }, { 0x2eu, PREFIX("cs") }, { 0x2fu, "das", NONE, NONE, NONE, EMIT(normal), XX, RWF }, /* 0x30 */ { 0x30u, "xorB", Eb, Gb, NONE, EMIT(normal), AX, WF }, { 0x31u, "xorL", Ev, Gv, NONE, EMIT(normal), AO, WF }, { 0x32u, "xorB", Gb, Eb, NONE, EMIT(normal), AX, WF }, { 0x33u, "xorL", Gv, Ev, NONE, EMIT(normal), AO, WF }, { 0x34u, "xorB", AL, Ib, NONE, EMIT(normal), XX, WF }, { 0x35u, "xorL", eAX, Iv, NONE, EMIT(normal), XO, WF }, { 0x36u, PREFIX("ss") }, { 0x37u, "aaa", NONE, NONE, NONE, EMIT(normal), XX , RWF }, /* 0x38 */ { 0x38u, "cmpB", Eb, Gb, NONE, EMIT(normal), AX, WF }, { 0x39u, "cmpL", Ev, Gv, NONE, EMIT(normal), AO, WF }, { 0x3au, "cmpB", Gb, Eb, NONE, EMIT(normal), AX, WF }, { 0x3bu, "cmpL", Gv, Ev, NONE, EMIT(normal), AO, WF }, { 0x3cu, "cmpB", AL, Ib, NONE, EMIT(normal), XX, WF }, { 0x3du, "cmpL", eAX, Iv, NONE, EMIT(normal), XO, WF }, { 0x3eu, PREFIX("ds") }, { 0x3fu, "aas", NONE, NONE, NONE, EMIT(normal), XX , RWF }, /* 0x40 */ { 0x40u, "incL", eAX, NONE, NONE, EMIT(normal), XO, WAOF }, { 0x41u, "incL", eCX, NONE, NONE, EMIT(normal), XO, WAOF }, { 0x42u, "incL", eDX, NONE, NONE, EMIT(normal), XO, WAOF }, { 0x43u, "incL", eBX, NONE, NONE, EMIT(normal), XO, WAOF }, { 0x44u, "incL", eSP, NONE, NONE, EMIT(normal), XO, WAOF }, { 0x45u, "incL", eBP, NONE, NONE, EMIT(normal), XO, WAOF }, { 0x46u, "incL", eSI, NONE, NONE, EMIT(normal), XO, WAOF }, { 0x47u, "incL", eDI, NONE, NONE, EMIT(normal), XO, WAOF }, /* 0x48 */ { 0x48u, "decL", eAX, NONE, NONE, EMIT(normal), XO, WAOF }, { 0x49u, "decL", eCX, NONE, NONE, EMIT(normal), XO, WAOF }, { 0x4au, "decL", eDX, NONE, NONE, EMIT(normal), XO, WAOF }, { 0x4bu, "decL", eBX, NONE, NONE, EMIT(normal), XO, WAOF }, { 0x4cu, "decL", eSP, NONE, NONE, EMIT(normal), XO, WAOF }, { 0x4du, "decL", eBP, NONE, NONE, EMIT(normal), XO, WAOF }, { 0x4eu, "decL", eSI, NONE, NONE, EMIT(normal), XO, WAOF }, { 0x4fu, "decL", eDI, NONE, NONE, EMIT(normal), XO, WAOF }, /* 0x50 */ { 0x50u, "pushL", eAX, NONE, NONE, EMIT(normal), XO, NF }, { 0x51u, "pushL", eCX, NONE, NONE, EMIT(normal), XO, NF }, { 0x52u, "pushL", eDX, NONE, NONE, EMIT(normal), XO, NF }, { 0x53u, "pushL", eBX, NONE, NONE, EMIT(normal), XO, NF }, { 0x54u, "pushL", eSP, NONE, NONE, EMIT(normal), XO, NF }, { 0x55u, "pushL", eBP, NONE, NONE, EMIT(normal), XO, NF }, { 0x56u, "pushL", eSI, NONE, NONE, EMIT(normal), XO, NF }, { 0x57u, "pushL", eDI, NONE, NONE, EMIT(normal), XO, NF }, /* 0x58 */ { 0x58u, "popL", eAX, NONE, NONE, EMIT(normal), XO, NF }, { 0x59u, "popL", eCX, NONE, NONE, EMIT(normal), XO, NF }, { 0x5au, "popL", eDX, NONE, NONE, EMIT(normal), XO, NF }, { 0x5bu, "popL", eBX, NONE, NONE, EMIT(normal), XO, NF }, { 0x5cu, "popL", eSP, NONE, NONE, EMIT(normal), XO, NF }, { 0x5du, "popL", eBP, NONE, NONE, EMIT(normal), XO, NF },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -