Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | #ifndef IA32_INSN_H |
michael@0 | 2 | #define IA32_INSN_H |
michael@0 | 3 | /* this file contains the structure of opcode definitions and the |
michael@0 | 4 | * constants they use */ |
michael@0 | 5 | |
michael@0 | 6 | #include <sys/types.h> |
michael@0 | 7 | #include "libdis.h" |
michael@0 | 8 | |
michael@0 | 9 | |
michael@0 | 10 | #define GET_BYTE( buf, buf_len ) buf_len ? *buf : 0 |
michael@0 | 11 | |
michael@0 | 12 | #define OP_SIZE_16 1 |
michael@0 | 13 | #define OP_SIZE_32 2 |
michael@0 | 14 | #define ADDR_SIZE_16 4 |
michael@0 | 15 | #define ADDR_SIZE_32 8 |
michael@0 | 16 | |
michael@0 | 17 | #define MAX_INSTRUCTION_SIZE 20 |
michael@0 | 18 | |
michael@0 | 19 | /* invalid instructions are handled by returning 0 [error] from the |
michael@0 | 20 | * function, setting the size of the insn to 1 byte, and copying |
michael@0 | 21 | * the byte at the start of the invalid insn into the x86_insn_t. |
michael@0 | 22 | * if the caller is saving the x86_insn_t for invalid instructions, |
michael@0 | 23 | * instead of discarding them, this will maintain a consistent |
michael@0 | 24 | * address space in the x86_insn_ts */ |
michael@0 | 25 | |
michael@0 | 26 | #define INVALID_INSN ((size_t) -1) /* return value for invalid insn */ |
michael@0 | 27 | #define MAKE_INVALID( i, buf ) \ |
michael@0 | 28 | strcpy( i->mnemonic, "invalid" ); \ |
michael@0 | 29 | x86_oplist_free( i ); \ |
michael@0 | 30 | i->size = 1; \ |
michael@0 | 31 | i->group = insn_none; \ |
michael@0 | 32 | i->type = insn_invalid; \ |
michael@0 | 33 | memcpy( i->bytes, buf, 1 ); |
michael@0 | 34 | |
michael@0 | 35 | |
michael@0 | 36 | size_t ia32_disasm_addr( unsigned char * buf, size_t buf_len, |
michael@0 | 37 | x86_insn_t *insn); |
michael@0 | 38 | |
michael@0 | 39 | |
michael@0 | 40 | /* --------------------------------------------------------- Table Lookup */ |
michael@0 | 41 | /* IA32 Instruction defintion for ia32_opcodes.c */ |
michael@0 | 42 | typedef struct { |
michael@0 | 43 | unsigned int table; /* escape to this sub-table */ |
michael@0 | 44 | unsigned int mnem_flag; /* Flags referring to mnemonic */ |
michael@0 | 45 | unsigned int notes; /* Notes for this instruction */ |
michael@0 | 46 | unsigned int dest_flag, src_flag, aux_flag; /* and for specific operands */ |
michael@0 | 47 | unsigned int cpu; /* minimumCPU [AND with clocks?? */ |
michael@0 | 48 | char mnemonic[16]; /* buffers for building instruction */ |
michael@0 | 49 | char mnemonic_att[16]; /* at&t style mnemonic name */ |
michael@0 | 50 | int32_t dest; |
michael@0 | 51 | int32_t src; |
michael@0 | 52 | int32_t aux; |
michael@0 | 53 | unsigned int flags_effected; |
michael@0 | 54 | unsigned int implicit_ops; /* implicit operands */ |
michael@0 | 55 | } ia32_insn_t; |
michael@0 | 56 | |
michael@0 | 57 | |
michael@0 | 58 | |
michael@0 | 59 | /* --------------------------------------------------------- Prefixes */ |
michael@0 | 60 | /* Prefix Flags */ |
michael@0 | 61 | /* Prefixes, same order as in the manual */ |
michael@0 | 62 | /* had to reverse the values of the first three as they were entered into |
michael@0 | 63 | * libdis.h incorrectly. */ |
michael@0 | 64 | #define PREFIX_LOCK 0x0004 |
michael@0 | 65 | #define PREFIX_REPNZ 0x0002 |
michael@0 | 66 | #define PREFIX_REPZ 0x0001 |
michael@0 | 67 | #define PREFIX_OP_SIZE 0x0010 |
michael@0 | 68 | #define PREFIX_ADDR_SIZE 0x0020 |
michael@0 | 69 | #define PREFIX_CS 0x0100 |
michael@0 | 70 | #define PREFIX_SS 0x0200 |
michael@0 | 71 | #define PREFIX_DS 0x0300 |
michael@0 | 72 | #define PREFIX_ES 0x0400 |
michael@0 | 73 | #define PREFIX_FS 0x0500 |
michael@0 | 74 | #define PREFIX_GS 0x0600 |
michael@0 | 75 | #define PREFIX_TAKEN 0x1000 /* branch taken */ |
michael@0 | 76 | #define PREFIX_NOTTAKEN 0x2000 /* branch not taken */ |
michael@0 | 77 | #define PREFIX_REG_MASK 0x0F00 |
michael@0 | 78 | #define BRANCH_HINT_MASK 0x3000 |
michael@0 | 79 | #define PREFIX_PRINT_MASK 0x000F /* printable prefixes */ |
michael@0 | 80 | #define PREFIX_MASK 0xFFFF |
michael@0 | 81 | |
michael@0 | 82 | /* ---------------------------------------------------------- CPU Type */ |
michael@0 | 83 | |
michael@0 | 84 | #define cpu_8086 0x0001 |
michael@0 | 85 | #define cpu_80286 0x0002 |
michael@0 | 86 | #define cpu_80386 0x0003 |
michael@0 | 87 | #define cpu_80387 0x0004 /* originally these were a co-proc */ |
michael@0 | 88 | #define cpu_80486 0x0005 |
michael@0 | 89 | #define cpu_PENTIUM 0x0006 |
michael@0 | 90 | #define cpu_PENTPRO 0x0007 |
michael@0 | 91 | #define cpu_PENTIUM2 0x0008 |
michael@0 | 92 | #define cpu_PENTIUM3 0x0009 |
michael@0 | 93 | #define cpu_PENTIUM4 0x000A |
michael@0 | 94 | #define cpu_K6 0x0010 |
michael@0 | 95 | #define cpu_K7 0x0020 |
michael@0 | 96 | #define cpu_ATHLON 0x0030 |
michael@0 | 97 | #define CPU_MODEL_MASK 0xFFFF |
michael@0 | 98 | #define CPU_MODEL(cpu) (cpu & CPU_MODEL_MASK) |
michael@0 | 99 | /* intel instruction subsets */ |
michael@0 | 100 | #define isa_GP 0x10000 /* General Purpose Instructions */ |
michael@0 | 101 | #define isa_FPU 0x20000 /* FPU instructions */ |
michael@0 | 102 | #define isa_FPUMGT 0x30000 /* FPU/SIMD Management */ |
michael@0 | 103 | #define isa_MMX 0x40000 /* MMX */ |
michael@0 | 104 | #define isa_SSE1 0x50000 /* SSE */ |
michael@0 | 105 | #define isa_SSE2 0x60000 /* SSE 2 */ |
michael@0 | 106 | #define isa_SSE3 0x70000 /* SSE 3 */ |
michael@0 | 107 | #define isa_3DNOW 0x80000 /* AMD 3d Now */ |
michael@0 | 108 | #define isa_SYS 0x90000 /* System Instructions */ |
michael@0 | 109 | #define ISA_SUBSET_MASK 0xFFFF0000 |
michael@0 | 110 | #define ISA_SUBSET(isa) (isa & ISA_SUBSET_MASK) |
michael@0 | 111 | |
michael@0 | 112 | |
michael@0 | 113 | /* ------------------------------------------------------ Operand Decoding */ |
michael@0 | 114 | #define ARG_NONE 0 |
michael@0 | 115 | |
michael@0 | 116 | /* Using a mask allows us to store info such as OP_SIGNED in the |
michael@0 | 117 | * operand flags field */ |
michael@0 | 118 | #define OPFLAGS_MASK 0x0000FFFF |
michael@0 | 119 | |
michael@0 | 120 | /* Operand Addressing Methods, per intel manual */ |
michael@0 | 121 | #define ADDRMETH_MASK 0x00FF0000 |
michael@0 | 122 | |
michael@0 | 123 | /* note: for instructions with implied operands, use no ADDRMETH */ |
michael@0 | 124 | #define ADDRMETH_A 0x00010000 |
michael@0 | 125 | #define ADDRMETH_C 0x00020000 |
michael@0 | 126 | #define ADDRMETH_D 0x00030000 |
michael@0 | 127 | #define ADDRMETH_E 0x00040000 |
michael@0 | 128 | #define ADDRMETH_F 0x00050000 |
michael@0 | 129 | #define ADDRMETH_G 0x00060000 |
michael@0 | 130 | #define ADDRMETH_I 0x00070000 |
michael@0 | 131 | #define ADDRMETH_J 0x00080000 |
michael@0 | 132 | #define ADDRMETH_M 0x00090000 |
michael@0 | 133 | #define ADDRMETH_O 0x000A0000 |
michael@0 | 134 | #define ADDRMETH_P 0x000B0000 |
michael@0 | 135 | #define ADDRMETH_Q 0x000C0000 |
michael@0 | 136 | #define ADDRMETH_R 0x000D0000 |
michael@0 | 137 | #define ADDRMETH_S 0x000E0000 |
michael@0 | 138 | #define ADDRMETH_T 0x000F0000 |
michael@0 | 139 | #define ADDRMETH_V 0x00100000 |
michael@0 | 140 | #define ADDRMETH_W 0x00110000 |
michael@0 | 141 | #define ADDRMETH_X 0x00120000 |
michael@0 | 142 | #define ADDRMETH_Y 0x00130000 |
michael@0 | 143 | #define ADDRMETH_RR 0x00140000 /* gen reg hard-coded in opcode */ |
michael@0 | 144 | #define ADDRMETH_RS 0x00150000 /* seg reg hard-coded in opcode */ |
michael@0 | 145 | #define ADDRMETH_RT 0x00160000 /* test reg hard-coded in opcode */ |
michael@0 | 146 | #define ADDRMETH_RF 0x00170000 /* fpu reg hard-coded in opcode */ |
michael@0 | 147 | #define ADDRMETH_II 0x00180000 /* immediate hard-coded in opcode */ |
michael@0 | 148 | #define ADDRMETH_PP 0x00190000 /* mm reg ONLY in modr/m field */ |
michael@0 | 149 | #define ADDRMETH_VV 0x001A0000 /* xmm reg ONLY in mod/rm field */ |
michael@0 | 150 | |
michael@0 | 151 | /* Operand Types, per intel manual */ |
michael@0 | 152 | #define OPTYPE_MASK 0xFF000000 |
michael@0 | 153 | |
michael@0 | 154 | #define OPTYPE_a 0x01000000 /* BOUND: h:h or w:w */ |
michael@0 | 155 | #define OPTYPE_b 0x02000000 /* byte */ |
michael@0 | 156 | #define OPTYPE_c 0x03000000 /* byte or word */ |
michael@0 | 157 | #define OPTYPE_d 0x04000000 /* word */ |
michael@0 | 158 | #define OPTYPE_dq 0x05000000 /* qword */ |
michael@0 | 159 | #define OPTYPE_p 0x06000000 /* 16:16 or 16:32 pointer */ |
michael@0 | 160 | #define OPTYPE_pi 0x07000000 /* dword MMX reg */ |
michael@0 | 161 | #define OPTYPE_ps 0x08000000 /* 128-bit single fp */ |
michael@0 | 162 | #define OPTYPE_q 0x09000000 /* dword */ |
michael@0 | 163 | #define OPTYPE_s 0x0A000000 /* 6-byte descriptor */ |
michael@0 | 164 | #define OPTYPE_ss 0x0B000000 /* scalar of 128-bit single fp */ |
michael@0 | 165 | #define OPTYPE_si 0x0C000000 /* word general register */ |
michael@0 | 166 | #define OPTYPE_v 0x0D000000 /* hword or word */ |
michael@0 | 167 | #define OPTYPE_w 0x0E000000 /* hword */ |
michael@0 | 168 | #define OPTYPE_m 0x0F000000 /* to handle LEA */ |
michael@0 | 169 | #define OPTYPE_none 0xFF000000 /* no valid operand size, INVLPG */ |
michael@0 | 170 | |
michael@0 | 171 | /* custom ones for FPU instructions */ |
michael@0 | 172 | #define OPTYPE_fs 0x10000000 /* pointer to single-real*/ |
michael@0 | 173 | #define OPTYPE_fd 0x20000000 /* pointer to double real */ |
michael@0 | 174 | #define OPTYPE_fe 0x30000000 /* pointer to extended real */ |
michael@0 | 175 | #define OPTYPE_fb 0x40000000 /* pointer to packed BCD */ |
michael@0 | 176 | #define OPTYPE_fv 0x50000000 /* pointer to FPU env: 14|28-bytes */ |
michael@0 | 177 | #define OPTYPE_ft 0x60000000 /* pointer to FPU state: 94|108-bytes */ |
michael@0 | 178 | #define OPTYPE_fx 0x70000000 /* pointer to FPU regs: 512 bites */ |
michael@0 | 179 | #define OPTYPE_fp 0x80000000 /* general fpu register: dbl ext */ |
michael@0 | 180 | |
michael@0 | 181 | /* SSE2 operand types */ |
michael@0 | 182 | #define OPTYPE_sd 0x90000000 /* scalar of 128-bit double fp */ |
michael@0 | 183 | #define OPTYPE_pd 0xA0000000 /* 128-bit double fp */ |
michael@0 | 184 | |
michael@0 | 185 | |
michael@0 | 186 | |
michael@0 | 187 | /* ---------------------------------------------- Opcode Table Descriptions */ |
michael@0 | 188 | /* the table type describes how to handle byte/size increments before |
michael@0 | 189 | * and after lookup. Some tables re-use the current byte, others |
michael@0 | 190 | * consume a byte only if the ModR/M encodes no operands, etc */ |
michael@0 | 191 | enum ia32_tbl_type_id { |
michael@0 | 192 | tbl_opcode = 0, /* standard opcode table: no surprises */ |
michael@0 | 193 | tbl_prefix, /* Prefix Override, e.g. 66/F2/F3 */ |
michael@0 | 194 | tbl_suffix, /* 3D Now style */ |
michael@0 | 195 | tbl_extension, /* ModR/M extension: 00-FF -> 00-07 */ |
michael@0 | 196 | tbl_ext_ext, /* extension of modr/m using R/M field */ |
michael@0 | 197 | tbl_fpu, /* fpu table: 00-BF -> 00-0F */ |
michael@0 | 198 | tbl_fpu_ext /* fpu extension : C0-FF -> 00-1F */ |
michael@0 | 199 | }; |
michael@0 | 200 | |
michael@0 | 201 | /* How it works: |
michael@0 | 202 | * Bytes are 'consumed' if the next table lookup requires that the byte |
michael@0 | 203 | * pointer be advanced in the instruction stream. 'Does not consume' means |
michael@0 | 204 | * that, when the lookup function recurses, the same byte it re-used in the |
michael@0 | 205 | * new table. It also means that size is not decremented, for example when |
michael@0 | 206 | * a ModR/M byte is used. Note that tbl_extension (ModR/M) instructions that |
michael@0 | 207 | * do not increase the size of an insn with their operands have a forced |
michael@0 | 208 | 3 size increase in the lookup algo. Weird, yes, confusing, yes, welcome |
michael@0 | 209 | * to the Intel ISA. Another note: tbl_prefix is used as an override, so an |
michael@0 | 210 | * empty insn in a prefix table causes the instruction in the original table |
michael@0 | 211 | * to be used, rather than an invalid insn being generated. |
michael@0 | 212 | * tbl_opcode uses current byte and consumes it |
michael@0 | 213 | * tbl_prefix uses current byte but does not consume it |
michael@0 | 214 | * tbl_suffix uses and consumes last byte in insn |
michael@0 | 215 | * tbl_extension uses current byte but does not consume it |
michael@0 | 216 | * tbl_ext_ext uses current byte but does not consume it |
michael@0 | 217 | * tbl_fpu uses current byte and consumes it |
michael@0 | 218 | * tbl_fpu_ext uses current byte but does not consume it |
michael@0 | 219 | */ |
michael@0 | 220 | |
michael@0 | 221 | /* Convenience struct for opcode tables : these will be stored in a |
michael@0 | 222 | * 'table of tables' so we can use a table index instead of a pointer */ |
michael@0 | 223 | typedef struct { /* Assembly instruction tables */ |
michael@0 | 224 | ia32_insn_t *table; /* Pointer to table of instruction encodings */ |
michael@0 | 225 | enum ia32_tbl_type_id type; |
michael@0 | 226 | unsigned char shift; /* amount to shift modrm byte */ |
michael@0 | 227 | unsigned char mask; /* bit mask for look up */ |
michael@0 | 228 | unsigned char minlim,maxlim; /* limits on min/max entries. */ |
michael@0 | 229 | } ia32_table_desc_t; |
michael@0 | 230 | |
michael@0 | 231 | |
michael@0 | 232 | /* ---------------------------------------------- 'Cooked' Operand Type Info */ |
michael@0 | 233 | /* Permissions: */ |
michael@0 | 234 | #define OP_R 0x001 /* operand is READ */ |
michael@0 | 235 | #define OP_W 0x002 /* operand is WRITTEN */ |
michael@0 | 236 | #define OP_RW 0x003 /* (OP_R|OP_W): convenience macro */ |
michael@0 | 237 | #define OP_X 0x004 /* operand is EXECUTED */ |
michael@0 | 238 | |
michael@0 | 239 | #define OP_PERM_MASK 0x0000007 /* perms are NOT mutually exclusive */ |
michael@0 | 240 | #define OP_PERM( type ) (type & OP_PERM_MASK) |
michael@0 | 241 | |
michael@0 | 242 | /* Flags */ |
michael@0 | 243 | #define OP_SIGNED 0x010 /* operand is signed */ |
michael@0 | 244 | |
michael@0 | 245 | #define OP_FLAG_MASK 0x0F0 /* mods are NOT mutually exclusive */ |
michael@0 | 246 | #define OP_FLAGS( type ) (type & OP_FLAG_MASK) |
michael@0 | 247 | |
michael@0 | 248 | #define OP_REG_MASK 0x0000FFFF /* lower WORD is register ID */ |
michael@0 | 249 | #define OP_REGTBL_MASK 0xFFFF0000 /* higher word is register type [gen/dbg] */ |
michael@0 | 250 | #define OP_REGID( type ) (type & OP_REG_MASK) |
michael@0 | 251 | #define OP_REGTYPE( type ) (type & OP_REGTBL_MASK) |
michael@0 | 252 | |
michael@0 | 253 | /* ------------------------------------------'Cooked' Instruction Type Info */ |
michael@0 | 254 | /* high-bit opcode types/insn meta-types */ |
michael@0 | 255 | #define INS_FLAG_PREFIX 0x10000000 /* insn is a prefix */ |
michael@0 | 256 | #define INS_FLAG_SUFFIX 0x20000000 /* followed by a suffix byte */ |
michael@0 | 257 | #define INS_FLAG_MASK 0xFF000000 |
michael@0 | 258 | |
michael@0 | 259 | /* insn notes */ |
michael@0 | 260 | #define INS_NOTE_RING0 0x00000001 /* insn is privileged */ |
michael@0 | 261 | #define INS_NOTE_SMM 0x00000002 /* Sys Mgt Mode only */ |
michael@0 | 262 | #define INS_NOTE_SERIAL 0x00000004 /* serializes */ |
michael@0 | 263 | #define INS_NOTE_NONSWAP 0x00000008 /* insn is not swapped in att format */ // could be separate field? |
michael@0 | 264 | #define INS_NOTE_NOSUFFIX 0x00000010 /* insn has no size suffix in att format */ // could be separate field? |
michael@0 | 265 | //#define INS_NOTE_NMI |
michael@0 | 266 | |
michael@0 | 267 | #define INS_INVALID 0 |
michael@0 | 268 | |
michael@0 | 269 | /* instruction groups */ |
michael@0 | 270 | #define INS_EXEC 0x1000 |
michael@0 | 271 | #define INS_ARITH 0x2000 |
michael@0 | 272 | #define INS_LOGIC 0x3000 |
michael@0 | 273 | #define INS_STACK 0x4000 |
michael@0 | 274 | #define INS_COND 0x5000 |
michael@0 | 275 | #define INS_LOAD 0x6000 |
michael@0 | 276 | #define INS_ARRAY 0x7000 |
michael@0 | 277 | #define INS_BIT 0x8000 |
michael@0 | 278 | #define INS_FLAG 0x9000 |
michael@0 | 279 | #define INS_FPU 0xA000 |
michael@0 | 280 | #define INS_TRAPS 0xD000 |
michael@0 | 281 | #define INS_SYSTEM 0xE000 |
michael@0 | 282 | #define INS_OTHER 0xF000 |
michael@0 | 283 | |
michael@0 | 284 | #define INS_GROUP_MASK 0xF000 |
michael@0 | 285 | #define INS_GROUP( type ) ( type & INS_GROUP_MASK ) |
michael@0 | 286 | |
michael@0 | 287 | /* INS_EXEC group */ |
michael@0 | 288 | #define INS_BRANCH (INS_EXEC | 0x01) /* Unconditional branch */ |
michael@0 | 289 | #define INS_BRANCHCC (INS_EXEC | 0x02) /* Conditional branch */ |
michael@0 | 290 | #define INS_CALL (INS_EXEC | 0x03) /* Jump to subroutine */ |
michael@0 | 291 | #define INS_CALLCC (INS_EXEC | 0x04) /* Jump to subroutine */ |
michael@0 | 292 | #define INS_RET (INS_EXEC | 0x05) /* Return from subroutine */ |
michael@0 | 293 | |
michael@0 | 294 | /* INS_ARITH group */ |
michael@0 | 295 | #define INS_ADD (INS_ARITH | 0x01) |
michael@0 | 296 | #define INS_SUB (INS_ARITH | 0x02) |
michael@0 | 297 | #define INS_MUL (INS_ARITH | 0x03) |
michael@0 | 298 | #define INS_DIV (INS_ARITH | 0x04) |
michael@0 | 299 | #define INS_INC (INS_ARITH | 0x05) /* increment */ |
michael@0 | 300 | #define INS_DEC (INS_ARITH | 0x06) /* decrement */ |
michael@0 | 301 | #define INS_SHL (INS_ARITH | 0x07) /* shift right */ |
michael@0 | 302 | #define INS_SHR (INS_ARITH | 0x08) /* shift left */ |
michael@0 | 303 | #define INS_ROL (INS_ARITH | 0x09) /* rotate left */ |
michael@0 | 304 | #define INS_ROR (INS_ARITH | 0x0A) /* rotate right */ |
michael@0 | 305 | #define INS_MIN (INS_ARITH | 0x0B) /* min func */ |
michael@0 | 306 | #define INS_MAX (INS_ARITH | 0x0C) /* max func */ |
michael@0 | 307 | #define INS_AVG (INS_ARITH | 0x0D) /* avg func */ |
michael@0 | 308 | #define INS_FLR (INS_ARITH | 0x0E) /* floor func */ |
michael@0 | 309 | #define INS_CEIL (INS_ARITH | 0x0F) /* ceiling func */ |
michael@0 | 310 | |
michael@0 | 311 | /* INS_LOGIC group */ |
michael@0 | 312 | #define INS_AND (INS_LOGIC | 0x01) |
michael@0 | 313 | #define INS_OR (INS_LOGIC | 0x02) |
michael@0 | 314 | #define INS_XOR (INS_LOGIC | 0x03) |
michael@0 | 315 | #define INS_NOT (INS_LOGIC | 0x04) |
michael@0 | 316 | #define INS_NEG (INS_LOGIC | 0x05) |
michael@0 | 317 | #define INS_NAND (INS_LOGIC | 0x06) |
michael@0 | 318 | |
michael@0 | 319 | /* INS_STACK group */ |
michael@0 | 320 | #define INS_PUSH (INS_STACK | 0x01) |
michael@0 | 321 | #define INS_POP (INS_STACK | 0x02) |
michael@0 | 322 | #define INS_PUSHREGS (INS_STACK | 0x03) /* push register context */ |
michael@0 | 323 | #define INS_POPREGS (INS_STACK | 0x04) /* pop register context */ |
michael@0 | 324 | #define INS_PUSHFLAGS (INS_STACK | 0x05) /* push all flags */ |
michael@0 | 325 | #define INS_POPFLAGS (INS_STACK | 0x06) /* pop all flags */ |
michael@0 | 326 | #define INS_ENTER (INS_STACK | 0x07) /* enter stack frame */ |
michael@0 | 327 | #define INS_LEAVE (INS_STACK | 0x08) /* leave stack frame */ |
michael@0 | 328 | |
michael@0 | 329 | /* INS_COND group */ |
michael@0 | 330 | #define INS_TEST (INS_COND | 0x01) |
michael@0 | 331 | #define INS_CMP (INS_COND | 0x02) |
michael@0 | 332 | |
michael@0 | 333 | /* INS_LOAD group */ |
michael@0 | 334 | #define INS_MOV (INS_LOAD | 0x01) |
michael@0 | 335 | #define INS_MOVCC (INS_LOAD | 0x02) |
michael@0 | 336 | #define INS_XCHG (INS_LOAD | 0x03) |
michael@0 | 337 | #define INS_XCHGCC (INS_LOAD | 0x04) |
michael@0 | 338 | #define INS_CONV (INS_LOAD | 0x05) /* move and convert type */ |
michael@0 | 339 | |
michael@0 | 340 | /* INS_ARRAY group */ |
michael@0 | 341 | #define INS_STRCMP (INS_ARRAY | 0x01) |
michael@0 | 342 | #define INS_STRLOAD (INS_ARRAY | 0x02) |
michael@0 | 343 | #define INS_STRMOV (INS_ARRAY | 0x03) |
michael@0 | 344 | #define INS_STRSTOR (INS_ARRAY | 0x04) |
michael@0 | 345 | #define INS_XLAT (INS_ARRAY | 0x05) |
michael@0 | 346 | |
michael@0 | 347 | /* INS_BIT group */ |
michael@0 | 348 | #define INS_BITTEST (INS_BIT | 0x01) |
michael@0 | 349 | #define INS_BITSET (INS_BIT | 0x02) |
michael@0 | 350 | #define INS_BITCLR (INS_BIT | 0x03) |
michael@0 | 351 | |
michael@0 | 352 | /* INS_FLAG group */ |
michael@0 | 353 | #define INS_CLEARCF (INS_FLAG | 0x01) /* clear Carry flag */ |
michael@0 | 354 | #define INS_CLEARZF (INS_FLAG | 0x02) /* clear Zero flag */ |
michael@0 | 355 | #define INS_CLEAROF (INS_FLAG | 0x03) /* clear Overflow flag */ |
michael@0 | 356 | #define INS_CLEARDF (INS_FLAG | 0x04) /* clear Direction flag */ |
michael@0 | 357 | #define INS_CLEARSF (INS_FLAG | 0x05) /* clear Sign flag */ |
michael@0 | 358 | #define INS_CLEARPF (INS_FLAG | 0x06) /* clear Parity flag */ |
michael@0 | 359 | #define INS_SETCF (INS_FLAG | 0x07) |
michael@0 | 360 | #define INS_SETZF (INS_FLAG | 0x08) |
michael@0 | 361 | #define INS_SETOF (INS_FLAG | 0x09) |
michael@0 | 362 | #define INS_SETDF (INS_FLAG | 0x0A) |
michael@0 | 363 | #define INS_SETSF (INS_FLAG | 0x0B) |
michael@0 | 364 | #define INS_SETPF (INS_FLAG | 0x0C) |
michael@0 | 365 | #define INS_TOGCF (INS_FLAG | 0x10) /* toggle */ |
michael@0 | 366 | #define INS_TOGZF (INS_FLAG | 0x20) |
michael@0 | 367 | #define INS_TOGOF (INS_FLAG | 0x30) |
michael@0 | 368 | #define INS_TOGDF (INS_FLAG | 0x40) |
michael@0 | 369 | #define INS_TOGSF (INS_FLAG | 0x50) |
michael@0 | 370 | #define INS_TOGPF (INS_FLAG | 0x60) |
michael@0 | 371 | |
michael@0 | 372 | /* INS_FPU */ |
michael@0 | 373 | #define INS_FMOV (INS_FPU | 0x1) |
michael@0 | 374 | #define INS_FMOVCC (INS_FPU | 0x2) |
michael@0 | 375 | #define INS_FNEG (INS_FPU | 0x3) |
michael@0 | 376 | #define INS_FABS (INS_FPU | 0x4) |
michael@0 | 377 | #define INS_FADD (INS_FPU | 0x5) |
michael@0 | 378 | #define INS_FSUB (INS_FPU | 0x6) |
michael@0 | 379 | #define INS_FMUL (INS_FPU | 0x7) |
michael@0 | 380 | #define INS_FDIV (INS_FPU | 0x8) |
michael@0 | 381 | #define INS_FSQRT (INS_FPU | 0x9) |
michael@0 | 382 | #define INS_FCMP (INS_FPU | 0xA) |
michael@0 | 383 | #define INS_FCOS (INS_FPU | 0xC) /* cosine */ |
michael@0 | 384 | #define INS_FLDPI (INS_FPU | 0xD) /* load pi */ |
michael@0 | 385 | #define INS_FLDZ (INS_FPU | 0xE) /* load 0 */ |
michael@0 | 386 | #define INS_FTAN (INS_FPU | 0xF) /* tanget */ |
michael@0 | 387 | #define INS_FSINE (INS_FPU | 0x10) /* sine */ |
michael@0 | 388 | #define INS_FSYS (INS_FPU | 0x20) /* misc */ |
michael@0 | 389 | |
michael@0 | 390 | /* INS_TRAP */ |
michael@0 | 391 | #define INS_TRAP (INS_TRAPS | 0x01) /* generate trap */ |
michael@0 | 392 | #define INS_TRAPCC (INS_TRAPS | 0x02) /* conditional trap gen */ |
michael@0 | 393 | #define INS_TRET (INS_TRAPS | 0x03) /* return from trap */ |
michael@0 | 394 | #define INS_BOUNDS (INS_TRAPS | 0x04) /* gen bounds trap */ |
michael@0 | 395 | #define INS_DEBUG (INS_TRAPS | 0x05) /* gen breakpoint trap */ |
michael@0 | 396 | #define INS_TRACE (INS_TRAPS | 0x06) /* gen single step trap */ |
michael@0 | 397 | #define INS_INVALIDOP (INS_TRAPS | 0x07) /* gen invalid insn */ |
michael@0 | 398 | #define INS_OFLOW (INS_TRAPS | 0x08) /* gen overflow trap */ |
michael@0 | 399 | #define INS_ICEBP (INS_TRAPS | 0x09) /* ICE breakpoint */ |
michael@0 | 400 | |
michael@0 | 401 | /* INS_SYSTEM */ |
michael@0 | 402 | #define INS_HALT (INS_SYSTEM | 0x01) /* halt machine */ |
michael@0 | 403 | #define INS_IN (INS_SYSTEM | 0x02) /* input form port */ |
michael@0 | 404 | #define INS_OUT (INS_SYSTEM | 0x03) /* output to port */ |
michael@0 | 405 | #define INS_CPUID (INS_SYSTEM | 0x04) /* identify cpu */ |
michael@0 | 406 | |
michael@0 | 407 | /* INS_OTHER */ |
michael@0 | 408 | #define INS_NOP (INS_OTHER | 0x01) |
michael@0 | 409 | #define INS_BCDCONV (INS_OTHER | 0x02) /* convert to/from BCD */ |
michael@0 | 410 | #define INS_SZCONV (INS_OTHER | 0x03) /* convert size of operand */ |
michael@0 | 411 | #define INS_SALC (INS_OTHER | 0x04) /* set %al on carry */ |
michael@0 | 412 | #define INS_UNKNOWN (INS_OTHER | 0x05) |
michael@0 | 413 | |
michael@0 | 414 | |
michael@0 | 415 | #define INS_TYPE_MASK 0xFFFF |
michael@0 | 416 | #define INS_TYPE( type ) ( type & INS_TYPE_MASK ) |
michael@0 | 417 | |
michael@0 | 418 | /* flags effected by instruction */ |
michael@0 | 419 | #define INS_TEST_CARRY 0x01 /* carry */ |
michael@0 | 420 | #define INS_TEST_ZERO 0x02 /* zero/equal */ |
michael@0 | 421 | #define INS_TEST_OFLOW 0x04 /* overflow */ |
michael@0 | 422 | #define INS_TEST_DIR 0x08 /* direction */ |
michael@0 | 423 | #define INS_TEST_SIGN 0x10 /* negative */ |
michael@0 | 424 | #define INS_TEST_PARITY 0x20 /* parity */ |
michael@0 | 425 | #define INS_TEST_OR 0x40 /* used in jle */ |
michael@0 | 426 | #define INS_TEST_NCARRY 0x100 /* ! carry */ |
michael@0 | 427 | #define INS_TEST_NZERO 0x200 /* ! zero */ |
michael@0 | 428 | #define INS_TEST_NOFLOW 0x400 /* ! oflow */ |
michael@0 | 429 | #define INS_TEST_NDIR 0x800 /* ! dir */ |
michael@0 | 430 | #define INS_TEST_NSIGN 0x100 /* ! sign */ |
michael@0 | 431 | #define INS_TEST_NPARITY 0x2000 /* ! parity */ |
michael@0 | 432 | /* SF == OF */ |
michael@0 | 433 | #define INS_TEST_SFEQOF 0x4000 |
michael@0 | 434 | /* SF != OF */ |
michael@0 | 435 | #define INS_TEST_SFNEOF 0x8000 |
michael@0 | 436 | |
michael@0 | 437 | #define INS_TEST_ALL INS_TEST_CARRY | INS_TEST_ZERO | \ |
michael@0 | 438 | INS_TEST_OFLOW | INS_TEST_SIGN | \ |
michael@0 | 439 | INS_TEST_PARITY |
michael@0 | 440 | |
michael@0 | 441 | #define INS_SET_CARRY 0x010000 /* carry */ |
michael@0 | 442 | #define INS_SET_ZERO 0x020000 /* zero/equal */ |
michael@0 | 443 | #define INS_SET_OFLOW 0x040000 /* overflow */ |
michael@0 | 444 | #define INS_SET_DIR 0x080000 /* direction */ |
michael@0 | 445 | #define INS_SET_SIGN 0x100000 /* negative */ |
michael@0 | 446 | #define INS_SET_PARITY 0x200000 /* parity */ |
michael@0 | 447 | #define INS_SET_NCARRY 0x1000000 |
michael@0 | 448 | #define INS_SET_NZERO 0x2000000 |
michael@0 | 449 | #define INS_SET_NOFLOW 0x4000000 |
michael@0 | 450 | #define INS_SET_NDIR 0x8000000 |
michael@0 | 451 | #define INS_SET_NSIGN 0x10000000 |
michael@0 | 452 | #define INS_SET_NPARITY 0x20000000 |
michael@0 | 453 | #define INS_SET_SFEQOF 0x40000000 |
michael@0 | 454 | #define INS_SET_SFNEOF 0x80000000 |
michael@0 | 455 | |
michael@0 | 456 | #define INS_SET_ALL INS_SET_CARRY | INS_SET_ZERO | \ |
michael@0 | 457 | INS_SET_OFLOW | INS_SET_SIGN | \ |
michael@0 | 458 | INS_SET_PARITY |
michael@0 | 459 | |
michael@0 | 460 | #define INS_TEST_MASK 0x0000FFFF |
michael@0 | 461 | #define INS_FLAGS_TEST(x) (x & INS_TEST_MASK) |
michael@0 | 462 | #define INS_SET_MASK 0xFFFF0000 |
michael@0 | 463 | #define INS_FLAGS_SET(x) (x & INS_SET_MASK) |
michael@0 | 464 | |
michael@0 | 465 | #if 0 |
michael@0 | 466 | /* TODO: actually start using these */ |
michael@0 | 467 | #define X86_PAIR_NP 1 /* not pairable; execs in U */ |
michael@0 | 468 | #define X86_PAIR_PU 2 /* pairable in U pipe */ |
michael@0 | 469 | #define X86_PAIR_PV 3 /* pairable in V pipe */ |
michael@0 | 470 | #define X86_PAIR_UV 4 /* pairable in UV pipe */ |
michael@0 | 471 | #define X86_PAIR_FX 5 /* pairable with FXCH */ |
michael@0 | 472 | |
michael@0 | 473 | #define X86_EXEC_PORT_0 1 |
michael@0 | 474 | #define X86_EXEC_PORT_1 2 |
michael@0 | 475 | #define X86_EXEC_PORT_2 4 |
michael@0 | 476 | #define X86_EXEC_PORT_3 8 |
michael@0 | 477 | #define X86_EXEC_PORT_4 16 |
michael@0 | 478 | |
michael@0 | 479 | #define X86_EXEC_UNITS |
michael@0 | 480 | |
michael@0 | 481 | typedef struct { /* representation of an insn during decoding */ |
michael@0 | 482 | uint32_t flags; /* runtime settings */ |
michael@0 | 483 | /* instruction prefixes and other foolishness */ |
michael@0 | 484 | uint32_t prefix; /* encoding of prefix */ |
michael@0 | 485 | char prefix_str[16]; /* mnemonics for prefix */ |
michael@0 | 486 | uint32_t branch_hint; /* gah! */ |
michael@0 | 487 | unsigned int cpu_ver; /* TODO: cpu version */ |
michael@0 | 488 | unsigned int clocks; /* TODO: clock cycles: min/max */ |
michael@0 | 489 | unsigned char last_prefix; |
michael@0 | 490 | /* runtime intruction decoding helpers */ |
michael@0 | 491 | unsigned char mode; /* 16, 32, 64 */ |
michael@0 | 492 | unsigned char gen_regs; /* offset of default general reg set */ |
michael@0 | 493 | unsigned char sz_operand; /* operand size for insn */ |
michael@0 | 494 | unsigned char sz_address; /* address size for insn */ |
michael@0 | 495 | unsigned char uops; /* uops per insn */ |
michael@0 | 496 | unsigned char pairing; /* np,pu,pv.lv */ |
michael@0 | 497 | unsigned char exec_unit; |
michael@0 | 498 | unsigned char exec_port; |
michael@0 | 499 | unsigned char latency; |
michael@0 | 500 | } ia32_info_t; |
michael@0 | 501 | #define MODE_32 0 /* default */ |
michael@0 | 502 | #define MODE_16 1 |
michael@0 | 503 | #define MODE_64 2 |
michael@0 | 504 | #endif |
michael@0 | 505 | |
michael@0 | 506 | #endif |