| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | |
| 3 * Use of this source code is governed by a BSD-style license that can be | |
| 4 * found in the LICENSE file. | |
| 5 */ | |
| 6 | |
| 7 /* | |
| 8 * Defines the one byte x86 opcodes. Based on opcodes given in table A-1 of | |
| 9 * appendix "A2 - Opcode Encodings", in AMD document 24594-Rev.3.14-September | |
| 10 * 2007, "AMD64 Architecture Programmer's manual Volume 3: General-Purpose | |
| 11 * and System Instructions". | |
| 12 * | |
| 13 * TODO(karl): This file is being updated to match Appendix A2. | |
| 14 * Not all instructions have yet been converted to the form used in | |
| 15 * in table A-1 cited above. | |
| 16 */ | |
| 17 | |
| 18 #ifndef NACL_TRUSTED_BUT_NOT_TCB | |
| 19 #error("This file is not meant for use in the TCB") | |
| 20 #endif | |
| 21 | |
| 22 #include "native_client/src/include/nacl_macros.h" | |
| 23 #include "native_client/src/include/portability_io.h" | |
| 24 #include "native_client/src/trusted/validator/x86/decoder/generator/ncdecode_for
ms.h" | |
| 25 #include "native_client/src/trusted/validator/x86/decoder/generator/ncdecode_st.
h" | |
| 26 #include "native_client/src/trusted/validator/x86/decoder/generator/ncdecode_tab
legen.h" | |
| 27 | |
| 28 /* Defines the buffer size to use to generate strings */ | |
| 29 #define BUFFER_SIZE 256 | |
| 30 | |
| 31 /* Define a symbol table size that can hold a small number of | |
| 32 * symbols (i.e. limit to at most 5 definitions). | |
| 33 */ | |
| 34 #define NACL_SMALL_ST (5) | |
| 35 | |
| 36 /* Define the number of register values that can appear in an opcode. */ | |
| 37 | |
| 38 static const NaClMnemonic NaClGroup1OpcodeName[8] = { | |
| 39 InstAdd, | |
| 40 InstOr, | |
| 41 InstAdc, | |
| 42 InstSbb, | |
| 43 InstAnd, | |
| 44 InstSub, | |
| 45 InstXor, | |
| 46 InstCmp | |
| 47 }; | |
| 48 | |
| 49 static const NaClMnemonic NaClGroup1CompName[1] = { | |
| 50 InstCmp | |
| 51 }; | |
| 52 | |
| 53 /* Returns true if the given mnemonic name corresponds | |
| 54 * to Compare. | |
| 55 */ | |
| 56 static Bool NaClIsGroup1CompName(NaClMnemonic name) { | |
| 57 int i; | |
| 58 for (i = 0; i < NACL_ARRAY_SIZE(NaClGroup1CompName); ++i) { | |
| 59 if (name == NaClGroup1CompName[i]) return TRUE; | |
| 60 } | |
| 61 return FALSE; | |
| 62 } | |
| 63 | |
| 64 /* Returns the set/use categorization for a group 1 mnemonic name. */ | |
| 65 static NaClInstCat NaClGroup1Cat(NaClMnemonic name) { | |
| 66 return NaClIsGroup1CompName(name) ? Compare : Binary; | |
| 67 } | |
| 68 | |
| 69 /* Define binary operation XX+00 to XX+05, for the binary operators | |
| 70 * add, or, adc, sbb, and, sub, xor, and cmp. Base is the value XX. | |
| 71 * Name is the name of the operation. Extra flags are any additional | |
| 72 * flags that are true to a specific binary operator, rather than | |
| 73 * all binary operators. | |
| 74 */ | |
| 75 static void NaClBuildBinaryOps_00_05(const uint8_t base, | |
| 76 const NaClInstType itype, | |
| 77 const NaClMnemonic name) { | |
| 78 NaClInstCat cat = NaClGroup1Cat(name); | |
| 79 struct NaClSymbolTable* st = NaClSymbolTableCreate(NACL_SMALL_ST, NULL); | |
| 80 NaClSymbolTablePutText("name", NaClMnemonicName(name), st); | |
| 81 NaClSymbolTablePutByte("base", base, st); | |
| 82 | |
| 83 NaClDefine("@base: @name $Eb, $Gb", itype, st, cat); | |
| 84 | |
| 85 NaClSymbolTablePutByte("base", base+1, st); | |
| 86 NaClDefine("@base: @name $Ev, $Gv", itype, st, cat); | |
| 87 | |
| 88 NaClSymbolTablePutByte("base", base+2, st); | |
| 89 NaClDefine("@base: @name $Gb, $Eb", itype, st, cat); | |
| 90 | |
| 91 NaClSymbolTablePutByte("base", base+3, st); | |
| 92 NaClDefine("@base: @name $Gv, $Ev", itype, st, cat); | |
| 93 | |
| 94 NaClSymbolTablePutByte("base", base+4, st); | |
| 95 NaClDefine("@base: @name %al, $Ib", itype, st, cat); | |
| 96 | |
| 97 NaClSymbolTablePutByte("base", base+5, st); | |
| 98 NaClDefine("@base: @name $rAXv, $Iz", itype, st, cat); | |
| 99 | |
| 100 NaClSymbolTableDestroy(st); | |
| 101 } | |
| 102 | |
| 103 /* Define the Xchg operator where the register is embedded in the opcode */ | |
| 104 static void NaClDefXchgRegister(void) { | |
| 105 /* Note: xchg is commutative, so order of operands is unimportant. */ | |
| 106 int i; | |
| 107 struct NaClSymbolTable* st = NaClSymbolTableCreate(NACL_SMALL_ST, NULL); | |
| 108 for (i = 0; i <= kMaxRegisterIndexInOpcode; ++i) { | |
| 109 NaClSymbolTablePutInt("i", i, st); | |
| 110 NaClDefine("90+@i: Xchg $r8v, $rAXv", NACLi_386, st , Exchange); | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 /* Define the increment and descrement operators XX+00 to XX+07. Base is | |
| 115 * the value XX. Name is the name of the increment/decrement operator. | |
| 116 */ | |
| 117 static void NaClDefIncOrDec_00_07(const uint8_t base, | |
| 118 const NaClMnemonic name, | |
| 119 struct NaClSymbolTable* context_st) { | |
| 120 static char* reg[kMaxRegisterIndexInOpcode + 1] = { | |
| 121 "rAXv", | |
| 122 "rCXv", | |
| 123 "rDXv", | |
| 124 "rBXv", | |
| 125 "rSPv", | |
| 126 "rBPv", | |
| 127 "rSIv", | |
| 128 "rDIv" | |
| 129 }; | |
| 130 | |
| 131 struct NaClSymbolTable* st = NaClSymbolTableCreate(NACL_SMALL_ST, context_st); | |
| 132 int i; | |
| 133 NaClSymbolTablePutText("name", NaClMnemonicName(name), st); | |
| 134 for (i = 0; i <= kMaxRegisterIndexInOpcode; ++i) { | |
| 135 NaClSymbolTablePutByte("opcode", base + i, st); | |
| 136 NaClSymbolTablePutText("reg", reg[i], st); | |
| 137 /* Note: Since the following instructions are only defined in | |
| 138 * 32-bit mode, operand size 8 will not apply, and hence rXX | |
| 139 * is equivalent to eXX (as used in the ADM manual). | |
| 140 */ | |
| 141 NaClDef_32("@opcode: @name $@reg", NACLi_386, st, UnaryUpdate); | |
| 142 } | |
| 143 NaClSymbolTableDestroy(st); | |
| 144 } | |
| 145 | |
| 146 /* Define the push and pop operators XX+00 to XX+17. Base is | |
| 147 * the value of XX. Name is the name of the push/pop operator. | |
| 148 */ | |
| 149 static void NaClDefPushOrPop_00_07(const uint8_t base, | |
| 150 const NaClMnemonic name, | |
| 151 struct NaClSymbolTable* context_st) { | |
| 152 int i; | |
| 153 NaClInstCat cat = (name == InstPush ? Push : Pop); | |
| 154 struct NaClSymbolTable* st = NaClSymbolTableCreate(NACL_SMALL_ST, context_st); | |
| 155 NaClSymbolTablePutByte("base", base, st); | |
| 156 NaClSymbolTablePutText("name", NaClMnemonicName(name), st); | |
| 157 for (i = 0; i <= kMaxRegisterIndexInOpcode; ++i) { | |
| 158 NaClSymbolTablePutInt("i", i, st); | |
| 159 NaClDefine("@base+@i: @name {%@sp}, $r8v", NACLi_386, st, cat); | |
| 160 } | |
| 161 NaClSymbolTableDestroy(st); | |
| 162 } | |
| 163 | |
| 164 static void NaClDefGroup1OpcodesInModRm(struct NaClSymbolTable* context_st) { | |
| 165 int i; | |
| 166 struct NaClSymbolTable* st = NaClSymbolTableCreate(NACL_SMALL_ST, context_st); | |
| 167 for (i = 0; i < NACL_ARRAY_SIZE(NaClGroup1OpcodeName); ++i) { | |
| 168 NaClMnemonic name = NaClGroup1OpcodeName[i]; | |
| 169 NaClInstCat cat = NaClGroup1Cat(name); | |
| 170 NaClSymbolTablePutInt("i", i, st); | |
| 171 NaClSymbolTablePutText("name", NaClMnemonicName(name), st); | |
| 172 NaClDefine("80/@i: @name $Eb, $Ib", NACLi_386, st, cat); | |
| 173 NaClDefine("81/@i: @name $Ev, $Iz", NACLi_386, st, cat); | |
| 174 /* The AMD manual shows 0x82 as a synonym for 0x80 in 32-bit mode only */ | |
| 175 NaClDef_32("82/@i: @name $Eb, $Ib", NACLi_386, st, cat); | |
| 176 NaClDef_64("82/@i: Invalid", NACLi_INVALID, st, Other); | |
| 177 NaClDefine("83/@i: @name $Ev, $Ib", NACLi_386, st, cat); | |
| 178 } | |
| 179 NaClSymbolTableDestroy(st); | |
| 180 } | |
| 181 | |
| 182 static void NaClDefJump8Opcode(uint8_t opcode, NaClMnemonic name, | |
| 183 struct NaClSymbolTable* context_st) { | |
| 184 struct NaClSymbolTable* st = NaClSymbolTableCreate(NACL_SMALL_ST, context_st); | |
| 185 NaClSymbolTablePutByte("opcode", opcode, st); | |
| 186 NaClSymbolTablePutText("name", NaClMnemonicName(name), st); | |
| 187 NaClDefine("@opcode: @name {%@ip}, $Jb", NACLi_386, st, Jump); | |
| 188 } | |
| 189 | |
| 190 /* Defines a conditional jump instruction that is dependent on address size. */ | |
| 191 typedef struct { | |
| 192 /* The platform(s) the instruction is defined on. */ | |
| 193 const NaClTargetPlatform platform; | |
| 194 /* The register XX the instruction conditionalizes the jump on. */ | |
| 195 const char* reg; | |
| 196 /* The address size held in register XX. */ | |
| 197 const NaClIFlag addr_size; | |
| 198 /* Flags to add to register XX. */ | |
| 199 const NaClOpFlags xx_flags; | |
| 200 /* The mnemonic name of the instruction. */ | |
| 201 const char* name; | |
| 202 } CondJumpInst; | |
| 203 | |
| 204 /* Generates conditiona jump instructions, based on the set of specified | |
| 205 * instructions. | |
| 206 * | |
| 207 * Parameters are: | |
| 208 * context_st - Symbol table defining other values if needed. | |
| 209 * opcode - The opcode value that defines the address jump instruction. | |
| 210 * address_insts - The address jump instructions to define. | |
| 211 */ | |
| 212 static void NaClDefCondJump(struct NaClSymbolTable* context_st, | |
| 213 uint8_t opcode, | |
| 214 CondJumpInst address_insts[], | |
| 215 size_t address_insts_size) { | |
| 216 size_t i; | |
| 217 int num_32_insts = 0; | |
| 218 int num_64_insts = 0; | |
| 219 char buffer[BUFFER_SIZE]; | |
| 220 struct NaClSymbolTable* st = NaClSymbolTableCreate(NACL_SMALL_ST, context_st); | |
| 221 SNPRINTF(buffer, BUFFER_SIZE, "%02x", opcode); | |
| 222 | |
| 223 /* Count the number of forms for each type of instruction, and record. */ | |
| 224 for (i = 0; i < address_insts_size; i++) { | |
| 225 switch (address_insts[i].platform) { | |
| 226 case T32: | |
| 227 num_32_insts++; | |
| 228 break; | |
| 229 case T64: | |
| 230 num_64_insts++; | |
| 231 break; | |
| 232 case Tall: | |
| 233 num_32_insts++; | |
| 234 num_64_insts++; | |
| 235 break; | |
| 236 } | |
| 237 } | |
| 238 NaClDefPrefixInstChoices_32_64(NoPrefix, opcode, num_32_insts, num_64_insts); | |
| 239 | |
| 240 /* Generate each form of the instruction. */ | |
| 241 for (i = 0; i < address_insts_size; ++i) { | |
| 242 NaClSymbolTablePutText("opcode", buffer, st); | |
| 243 NaClSymbolTablePutText("name", address_insts[i].name, st); | |
| 244 NaClSymbolTablePutText("reg", address_insts[i].reg, st); | |
| 245 NaClBegDefPlatform(address_insts[i].platform, | |
| 246 "@opcode: @name {%@ip}, {%@reg}, $Jb", | |
| 247 NACLi_386, st); | |
| 248 NaClAddIFlags(NACL_IFLAG(address_insts[i].addr_size)); | |
| 249 NaClAddOpFlags(1, address_insts[i].xx_flags); | |
| 250 NaClEndDef(Jump); | |
| 251 } | |
| 252 } | |
| 253 | |
| 254 /* Generates a jXXz instruction, based on the use of register XX | |
| 255 * (XX in cx, ecx, rcx). | |
| 256 */ | |
| 257 static void NaClDefJumpRegZero(struct NaClSymbolTable* context_st) { | |
| 258 CondJumpInst inst[3] = { | |
| 259 { T32, "cx", AddressSize_w, NACL_EMPTY_OPFLAGS, "Jcxz" }, | |
| 260 { Tall, "ecx", AddressSize_v, NACL_EMPTY_OPFLAGS, "Jecxz" }, | |
| 261 { T64, "rcx", AddressSize_o, NACL_EMPTY_OPFLAGS, "Jrcxz" } | |
| 262 }; | |
| 263 NaClDefCondJump(context_st, 0xe3, inst, NACL_ARRAY_SIZE(inst)); | |
| 264 } | |
| 265 | |
| 266 /* Generates the loop, loopne, and loope instructions. */ | |
| 267 static void NaClDefLoop(struct NaClSymbolTable* context_st) { | |
| 268 /* The forms each loop instruction can have. */ | |
| 269 CondJumpInst inst_forms[3] = { | |
| 270 { T32, "cx", AddressSize_w, NACL_OPFLAG(OpSet), "???" }, | |
| 271 { Tall, "ecx", AddressSize_v, NACL_OPFLAG(OpSet), "???" }, | |
| 272 { T64, "rcx", AddressSize_o, NACL_OPFLAG(OpSet), "???" } | |
| 273 }; | |
| 274 /* The opcode/name of each loop instruction. */ | |
| 275 struct { | |
| 276 uint8_t opcode; | |
| 277 const char* name; | |
| 278 } loop_inst[3] = { | |
| 279 {0xe0, "Loopne"}, | |
| 280 {0xe1, "Loope"}, | |
| 281 {0xe2, "Loop"}, | |
| 282 }; | |
| 283 | |
| 284 /* Generate all combinations of the loop instruction. */ | |
| 285 size_t i; | |
| 286 for (i = 0; i < NACL_ARRAY_SIZE(loop_inst); i++) { | |
| 287 size_t j; | |
| 288 for (j = 0; j < NACL_ARRAY_SIZE(inst_forms); j++) { | |
| 289 inst_forms[j].name = loop_inst[i].name; | |
| 290 } | |
| 291 NaClDefCondJump(context_st, loop_inst[i].opcode, | |
| 292 inst_forms, NACL_ARRAY_SIZE(inst_forms)); | |
| 293 } | |
| 294 } | |
| 295 | |
| 296 static const NaClMnemonic NaClGroup2OpcodeName[8] = { | |
| 297 InstRol, | |
| 298 InstRor, | |
| 299 InstRcl, | |
| 300 InstRcr, | |
| 301 InstShl, /* same as Sal */ | |
| 302 InstShr, | |
| 303 InstShl, /* same as Sal; disallowed as an alias encoding */ | |
| 304 InstSar | |
| 305 }; | |
| 306 | |
| 307 static void NaClDefGroup2OpcodesInModRm(struct NaClSymbolTable* context_st) { | |
| 308 int i; | |
| 309 struct NaClSymbolTable* st = NaClSymbolTableCreate(NACL_SMALL_ST, context_st); | |
| 310 for (i = 0; i < NACL_ARRAY_SIZE(NaClGroup2OpcodeName); i++) { | |
| 311 /* The "/6" encodings of "Shl" are aliases of the "/4" encodings. | |
| 312 * "/4" is used by assemblers. We disallow "/6" on the grounds of | |
| 313 * minimalism. | |
| 314 */ | |
| 315 NaClInstType insttype = i == 6 ? NACLi_ILLEGAL : NACLi_386; | |
| 316 NaClMnemonic name; | |
| 317 NaClSymbolTablePutInt("i", i, st); | |
| 318 name = NaClGroup2OpcodeName[i]; | |
| 319 NaClSymbolTablePutText("name", NaClMnemonicName(name), st); | |
| 320 NaClDefine("c0/@i: @name $Eb, $Ib", insttype, st, Binary); | |
| 321 NaClDefine("c1/@i: @name $Ev, $Ib", insttype, st, Binary); | |
| 322 NaClDefine("d0/@i: @name $Eb, 1", insttype, st, Binary); | |
| 323 NaClDefine("d1/@i: @name $Ev, 1", insttype, st, Binary); | |
| 324 NaClDefine("d2/@i: @name $Eb, %cl", insttype, st, Binary); | |
| 325 NaClDefine("d3/@i: @name $Ev, %cl", insttype, st, Binary); | |
| 326 } | |
| 327 NaClSymbolTableDestroy(st); | |
| 328 } | |
| 329 | |
| 330 void NaClDefOneByteInsts(struct NaClSymbolTable* st) { | |
| 331 | |
| 332 NaClDefInstPrefix(NoPrefix); | |
| 333 | |
| 334 NaClBuildBinaryOps_00_05(0x00, NACLi_386, InstAdd); | |
| 335 NaClDef_32("06: Push {%@sp}, %es", NACLi_386, st, Push); | |
| 336 NaClDef_64("06: Invalid", NACLi_INVALID, st, Other); | |
| 337 NaClDef_32("07: Pop {%@sp}, %es", NACLi_386, st, Pop); | |
| 338 NaClDef_64("07: Invalid", NACLi_INVALID, st, Other); | |
| 339 NaClBuildBinaryOps_00_05(0x08, NACLi_386, InstOr); | |
| 340 NaClDef_32("0e: Push {%@sp}, %cs", NACLi_386, st, Push); | |
| 341 NaClDef_64("0e: Invalid", NACLi_INVALID, st, Other); | |
| 342 /* 0x0F is a two-byte opcode prefix. */ | |
| 343 NaClDefine("0f: Invalid", NACLi_INVALID, st, Other); | |
| 344 NaClBuildBinaryOps_00_05(0x10, NACLi_386, InstAdc); | |
| 345 NaClDef_32("16: Push {%@sp}, %ss", NACLi_386, st, Push); | |
| 346 NaClDef_64("16: Invalid", NACLi_INVALID, st, Other); | |
| 347 NaClDef_32("17: Pop {%@sp}, %ss", NACLi_386, st, Pop); | |
| 348 NaClDef_64("17: Invalid", NACLi_INVALID, st, Other); | |
| 349 NaClBuildBinaryOps_00_05(0x18, NACLi_386, InstSbb); | |
| 350 NaClDef_32("1e: Push {%@sp}, %ds", NACLi_386, st, Push); | |
| 351 NaClDef_64("1e: Invalid", NACLi_INVALID, st, Other); | |
| 352 NaClDef_32("1f: Pop {%@sp}, %ds", NACLi_386, st, Pop); | |
| 353 NaClDef_64("1f: Invalid", NACLi_INVALID, st, Other); | |
| 354 NaClBuildBinaryOps_00_05(0x20, NACLi_386, InstAnd); | |
| 355 /* 26: segment ES prefix */ | |
| 356 NaClDefine("26: Invalid", NACLi_INVALID, st, Other); | |
| 357 NaClDef_32("27: Daa", NACLi_386, st, Other); | |
| 358 NaClDef_64("27: Invalid", NACLi_INVALID, st, Other); | |
| 359 NaClBuildBinaryOps_00_05(0x28, NACLi_386, InstSub); | |
| 360 /* 2e: segment CS prefix*/ | |
| 361 NaClDefine("2e: Invalid", NACLi_INVALID, st, Other); | |
| 362 NaClDef_32("2f: Das", NACLi_386, st, Other); | |
| 363 NaClDef_64("2f: Invalid", NACLi_INVALID, st, Other); | |
| 364 NaClBuildBinaryOps_00_05(0x30, NACLi_386, InstXor); | |
| 365 /* 36: segment SS prefix */ | |
| 366 NaClDefine("36: Invalid", NACLi_INVALID, st, Other); | |
| 367 NaClDef_32("37: Aaa {%al}", NACLi_386, st, UnaryUpdate); | |
| 368 NaClDef_64("37: Invalid", NACLi_INVALID, st, Other); | |
| 369 NaClBuildBinaryOps_00_05(0x38, NACLi_386, InstCmp); | |
| 370 /* Ox3e segment DS prefix */ | |
| 371 NaClDefine("3e: Invalid", NACLi_INVALID, st, Other); | |
| 372 NaClDef_32("3f: Aas", NACLi_386, st, Other); | |
| 373 NaClDef_64("3f: Invalid", NACLi_INVALID, st, Other); | |
| 374 NaClDefIncOrDec_00_07(0x40, InstInc, st); | |
| 375 NaClDefIncOrDec_00_07(0x48, InstDec, st); | |
| 376 NaClDefPushOrPop_00_07(0x50, InstPush, st); | |
| 377 NaClDefPushOrPop_00_07(0x58, InstPop, st); | |
| 378 NaClDefPrefixInstChoices_32_64(NoPrefix, 0x60, 2, 1); | |
| 379 NaClBegD32("60: Pusha {%@sp}, {%gp7}", NACLi_386, st); | |
| 380 NaClAddIFlags(NACL_IFLAG(OperandSize_w)); | |
| 381 NaClEndDef(Push); | |
| 382 NaClBegD32("60: Pushad {%@sp}, {%gp7}", NACLi_386, st); | |
| 383 NaClAddIFlags(NACL_IFLAG(OperandSize_v)); | |
| 384 NaClEndDef(Push); | |
| 385 NaClDefPrefixInstChoices_32_64(NoPrefix, 0x61, 2, 1); | |
| 386 NaClDef_64("60: Invalid", NACLi_INVALID, st, Other); | |
| 387 NaClBegD32("61: Popa {%@sp}, {%gp7}", NACLi_386, st); | |
| 388 NaClAddIFlags(NACL_IFLAG(OperandSize_w)); | |
| 389 NaClEndDef(Pop); | |
| 390 NaClBegD32("61: Popad {%@sp}, {%gp7}", NACLi_386, st); | |
| 391 NaClAddIFlags(NACL_IFLAG(OperandSize_v)); | |
| 392 NaClEndDef(Pop); | |
| 393 NaClDef_64("61: Invalid", NACLi_INVALID, st, Other); | |
| 394 NaClDef_32("62: Bound $Gv, $Ma", NACLi_386, st, Uses); | |
| 395 NaClDef_64("62: Invalid", NACLi_INVALID, st, Other); | |
| 396 NaClDef_32("63: Arpl $Ew, $Gw", NACLi_SYSTEM, st, Binary); | |
| 397 NaClDef_64("63: Movsxd $Gv, $Ed", NACLi_386, st, Move); | |
| 398 /* 64: segment FS prefix */ | |
| 399 NaClDefine("64: Invalid", NACLi_INVALID, st, Other); | |
| 400 /* 65: segment GS prefix */ | |
| 401 NaClDefine("65: Invalid", NACLi_INVALID, st, Other); | |
| 402 /* 66: data size prefix */ | |
| 403 NaClDefine("66: Invalid", NACLi_INVALID, st, Other); | |
| 404 /* 67: address size prefix */ | |
| 405 NaClDefine("67: Invalid", NACLi_INVALID, st, Other); | |
| 406 NaClDefine("68: Push {%@sp} $Iz", NACLi_386, st, Push); | |
| 407 NaClDefine("69: Imul $Gv, $Ev, $Iz", NACLi_386, st, Binary); | |
| 408 NaClDefine("6a: Push {%@sp} $Ib", NACLi_386, st, Push); | |
| 409 NaClDefine("6b: Imul $Gv, $Ev, $Ib", NACLi_386, st, Binary); | |
| 410 NaClDefine("6c: Insb {$Yb}, {%dx}", NACLi_386, st, Move); | |
| 411 NaClDefPrefixInstChoices(NoPrefix, 0x6D, 2); | |
| 412 NaClDefine("6d: Insw {$Yzw}, {%dx}", NACLi_386, st, Move); | |
| 413 NaClDefine("6d: Insd {$Yzd}, {%dx}", NACLi_386, st, Move); | |
| 414 NaClDefine("6e: Outsb {%dx}, {$Xb}", NACLi_386, st, Uses); | |
| 415 NaClDefPrefixInstChoices(NoPrefix, 0x6F, 2); | |
| 416 NaClDefine("6f: Outsw {%dx}, {$Xzw}", NACLi_386, st, Uses); | |
| 417 NaClDefine("6f: Outsd {%dx}, {$Xzd}", NACLi_386, st, Uses); | |
| 418 NaClDefJump8Opcode(0x70, InstJo, st); | |
| 419 NaClDefJump8Opcode(0x71, InstJno, st); | |
| 420 NaClDefJump8Opcode(0x72, InstJb, st); | |
| 421 NaClDefJump8Opcode(0x73, InstJnb, st); | |
| 422 NaClDefJump8Opcode(0x74, InstJz, st); | |
| 423 NaClDefJump8Opcode(0x75, InstJnz, st); | |
| 424 NaClDefJump8Opcode(0x76, InstJbe, st); | |
| 425 NaClDefJump8Opcode(0x77, InstJnbe, st); | |
| 426 NaClDefJump8Opcode(0x78, InstJs, st); | |
| 427 NaClDefJump8Opcode(0x79, InstJns, st); | |
| 428 NaClDefJump8Opcode(0x7a, InstJp, st); | |
| 429 NaClDefJump8Opcode(0x7b, InstJnp, st); | |
| 430 NaClDefJump8Opcode(0x7c, InstJl, st); | |
| 431 NaClDefJump8Opcode(0x7d, InstJnl, st); | |
| 432 NaClDefJump8Opcode(0x7e, InstJle, st); | |
| 433 NaClDefJump8Opcode(0x7f, InstJnle, st); | |
| 434 /* Defines 80-83, using opcode in mod/rm */ | |
| 435 NaClDefGroup1OpcodesInModRm(st); | |
| 436 NaClDefine("84: Test $Eb, $Gb", NACLi_386, st, Compare); | |
| 437 NaClDefine("85: Test $Ev, $Gv", NACLi_386, st, Compare); | |
| 438 NaClDefine("86: Xchg $Eb, $Gb", NACLi_386, st, Exchange); | |
| 439 NaClDefine("87: Xchg $Ev, $Gv", NACLi_386, st, Exchange); | |
| 440 NaClDefine("88: Mov $Eb, $Gb", NACLi_386, st, Move); | |
| 441 NaClDefine("89: Mov $Ev, $Gv", NACLi_386, st, Move); | |
| 442 NaClDefine("8a: Mov $Gb, $Eb", NACLi_386, st, Move); | |
| 443 NaClDefine("8b: Mov $Gv, $Ev", NACLi_386, st, Move); | |
| 444 NaClDefine("8c: Mov $Mw/Rv, $Sw", NACLi_386, st, Move); | |
| 445 NaClBegDef("8d: Lea $Gv, $M", NACLi_386, st); | |
| 446 NaClAddOpFlags(1, NACL_OPFLAG(OpAddress)); | |
| 447 NaClEndDef(Lea); | |
| 448 NaClDefine("8e: Mov $Sw, $Ew", NACLi_386, st, Move); | |
| 449 NaClDefine("8f/0: Pop {%@sp}, $Ev", NACLi_386, st, Pop); | |
| 450 NaClDefine("8f/r: Invalid", NACLi_INVALID, st, Other); | |
| 451 /* 90-97: exchange register. */ | |
| 452 NaClDefXchgRegister(); | |
| 453 NaClDefPrefixInstChoices_32_64(NoPrefix, 0x98, 2, 3); | |
| 454 NaClBegDef("98: Cbw {%ax}, {%al}", NACLi_386, st); | |
| 455 NaClAddIFlags(NACL_IFLAG(OperandSize_w)); | |
| 456 NaClEndDef(Move); | |
| 457 NaClBegDef("98: Cwde {%eax}, {%ax}", NACLi_386, st); | |
| 458 NaClAddIFlags(NACL_IFLAG(OperandSize_v)); | |
| 459 NaClAddOpFlags(0, NACL_OPFLAG(OperandSignExtends_v)); | |
| 460 NaClEndDef(Move); | |
| 461 NaClBegD64("98: Cdqe {%rax}, {%eax}", NACLi_386, st); | |
| 462 NaClAddIFlags(NACL_IFLAG(OperandSize_o)); | |
| 463 NaClEndDef(Move); | |
| 464 NaClDefPrefixInstChoices_32_64(NoPrefix, 0x99, 2, 3); | |
| 465 NaClBegDef("99: Cwd {%dx}, {%ax}", NACLi_386, st); | |
| 466 NaClAddIFlags(NACL_IFLAG(OperandSize_w)); | |
| 467 NaClEndDef(Move); | |
| 468 NaClBegDef("99: Cdq {%edx}, {%eax}", NACLi_386, st); | |
| 469 NaClAddIFlags(NACL_IFLAG(OperandSize_v)); | |
| 470 NaClEndDef(Move); | |
| 471 NaClBegD64("99: Cqo {%rdx}, {%rax}", NACLi_386, st); | |
| 472 NaClAddIFlags(NACL_IFLAG(OperandSize_o)); | |
| 473 NaClEndDef(Move); | |
| 474 NaClDef_32("9a: Call {%@ip}, {%@sp}, $Ap", NACLi_386, st, Call); | |
| 475 NaClDef_64("9a: Invalid", NACLi_INVALID, st, Other); | |
| 476 NaClDefine("9b: Fwait", NACLi_X87, st, Other); | |
| 477 NaClDefPrefixInstChoices(NoPrefix, 0x9c, 2); | |
| 478 NaClDefine("9c: Pushf {%@sp}, {$Fvw}", NACLi_386, st, Push); | |
| 479 NaClDef_32("9c: Pushfd {%@sp}, {$Fvd}", NACLi_386, st, Push); | |
| 480 NaClDef_64("9c: Pushfq {%@sp}, {$Fvq}", NACLi_386, st, Push); | |
| 481 NaClDefPrefixInstChoices(NoPrefix, 0x9d, 2); | |
| 482 NaClDefine("9d: Popf {%@sp}, {$Fvw}", NACLi_386, st, Pop); | |
| 483 NaClDef_32("9d: Popfd {%@sp}, {$Fvd}", NACLi_386, st, Pop); | |
| 484 NaClDef_64("9d: Popfq {%@sp}, {$Fvq}", NACLi_386, st, Pop); | |
| 485 NaClDefine("9e: Sahf {%ah}", NACLi_LAHF, st, Uses); | |
| 486 NaClDefine("9f: Lahf {%ah}", NACLi_LAHF, st, UnarySet); | |
| 487 NaClDefine("a0: Mov %al, $Ob", NACLi_386, st, Move); | |
| 488 NaClDefine("a1: Mov $rAXv, $Ov", NACLi_386, st, Move); | |
| 489 NaClDefine("a2: Mov $Ob, %al", NACLi_386, st, Move); | |
| 490 NaClDefine("a3: Mov $Ov, $rAXv", NACLi_386, st, Move); | |
| 491 NaClDefine("a4: Movsb $Yb, $Xb", NACLi_386, st, Move); | |
| 492 NaClDefPrefixInstChoices_32_64(NoPrefix, 0xa5, 2, 3); | |
| 493 NaClDefine("a5: Movsw $Yvw, $Xvw", NACLi_386, st, Move); | |
| 494 NaClDefine("a5: Movsd $Yvd, $Xvd", NACLi_386, st, Move); | |
| 495 NaClDef_64("a5: Movsq $Yvq, $Xvq", NACLi_386, st, Move); | |
| 496 NaClDefine("a6: Cmpsb $Yb, $Xb", NACLi_386, st, Compare); | |
| 497 NaClDefPrefixInstChoices_32_64(NoPrefix, 0xa7, 2, 3); | |
| 498 NaClDefine("a7: Cmpsw $Yvw, $Xvw", NACLi_386, st, Compare); | |
| 499 NaClDefine("a7: Cmpsd $Yvd, $Xvd", NACLi_386, st, Compare); | |
| 500 NaClDef_64("a7: Cmpsq $Yvq, $Xvq", NACLi_386, st, Compare); | |
| 501 NaClDefine("a8: Test %al, $Ib", NACLi_386, st, Compare); | |
| 502 NaClDefine("a9: Test $rAXv, $Iz", NACLi_386, st, Compare); | |
| 503 NaClDefine("aa: Stosb $Yb, {%al}", NACLi_386, st, Move); | |
| 504 NaClDefPrefixInstChoices_32_64(NoPrefix, 0xab, 2, 3); | |
| 505 NaClDefine("ab: Stosw $Yvw, {$rAXvw}", NACLi_386, st, Move); | |
| 506 NaClDefine("ab: Stosd $Yvd, {$rAXvd}", NACLi_386, st, Move); | |
| 507 NaClDef_64("ab: Stosq $Yvq, {$rAXvq}", NACLi_386, st, Move); | |
| 508 NaClDefine("ac: Lodsb {%al}, $Xb", NACLi_386, st, Move); | |
| 509 NaClDefPrefixInstChoices_32_64(NoPrefix, 0xad, 2, 3); | |
| 510 NaClDefine("ad: Lodsw {$rAXvw}, $Xvw", NACLi_386, st, Move); | |
| 511 NaClDefine("ad: Lodsd {$rAXvd}, $Xvd", NACLi_386, st, Move); | |
| 512 NaClDef_64("ad: Lodsq {$rAXvq}, $Xvq", NACLi_386, st, Move); | |
| 513 NaClDefine("ae: Scasb {%al}, $Yb", NACLi_386, st, Compare); | |
| 514 NaClDefPrefixInstChoices_32_64(NoPrefix, 0xaf, 2, 3); | |
| 515 NaClDefine("af: Scasw {$rAXvw}, $Yvw", NACLi_386, st, Compare); | |
| 516 NaClDefine("af: Scasd {$rAXvd}, $Yvd", NACLi_386, st, Compare); | |
| 517 NaClDef_64("af: Scasq {$rAXvq}, $Yvq", NACLi_386, st, Compare); | |
| 518 NaClDefReg("b0+@reg: Mov $r8b, $Ib", 0, 7, NACLi_386, st, Move); | |
| 519 NaClDefReg("b8+@reg: Mov $r8v, $Iv", 0, 7, NACLi_386, st, Move); | |
| 520 /* 0xC0 and 0xC1 defined by NaClDefGroup2OpcodesInModRm, called below. */ | |
| 521 NaClDefine("c2: Ret {%@ip}, {%@sp}, $Iw", NACLi_386, st, Return); | |
| 522 NaClDefine("c3: Ret {%@ip}, {%@sp}", NACLi_386, st, Return); | |
| 523 NaClDef_32("c4: Les $SGz, $Mp", NACLi_386, st, Lea); | |
| 524 NaClDef_64("c4: Invalid", NACLi_INVALID, st, Other); | |
| 525 NaClDef_32("c5: Lds $SGz, $Mp", NACLi_386, st, Lea); | |
| 526 NaClDef_64("c5: Invalid", NACLi_INVALID, st, Other); | |
| 527 NaClDefine("c6/0: Mov $Eb, $Ib", NACLi_386, st, Move); | |
| 528 NaClDefine("c6/r: Invalid", NACLi_INVALID, st, Other); | |
| 529 NaClDefine("c7/0: Mov $Ev, $Iz", NACLi_386, st, Move); | |
| 530 NaClDefine("c7/r: Invalid", NACLi_INVALID, st, Other); | |
| 531 NaClDefine("c8: Enter {%@sp}, {%@bp}, $Iw, $I2b", NACLi_386, st, Call); | |
| 532 NaClDefine("c9: Leave {%@sp}, {%@bp}", NACLi_386, st, Return); | |
| 533 NaClDefine("ca: Ret {%@ip} {%@sp}, $Iw", NACLi_RETURN, st, Return); | |
| 534 NaClDefine("cb: Ret {%@ip} {%@sp}", NACLi_RETURN, st, Return); | |
| 535 NaClDefine("cc: Int3", NACLi_SYSTEM, st, Other); | |
| 536 NaClDefine("cd: Int $Ib", NACLi_386, st, Uses); | |
| 537 NaClDefine("ce: Into", NACLi_386, st, Other); | |
| 538 NaClDefPrefixInstChoices_32_64(NoPrefix, 0xcf, 2, 3); | |
| 539 NaClBegDef("cf: Iretd {%@ip} {%@sp}", NACLi_SYSTEM, st); | |
| 540 NaClAddIFlags(NACL_IFLAG(OperandSize_v)); | |
| 541 NaClEndDef(Return); | |
| 542 NaClBegD64("cf: Iretq {%@ip} {%@sp}", NACLi_SYSTEM, st); | |
| 543 NaClAddIFlags(NACL_IFLAG(OperandSize_o)); | |
| 544 NaClEndDef(Return); | |
| 545 NaClBegDef("cf: Iret {%@ip} {%@sp}", NACLi_SYSTEM, st); | |
| 546 NaClAddIFlags(NACL_IFLAG(OperandSize_w)); | |
| 547 NaClEndDef(Return); | |
| 548 /* Group 2 - 0xD0, 0XD1, 0xD2, 0xD3 */ | |
| 549 NaClDefGroup2OpcodesInModRm(st); | |
| 550 NaClDef_32("d4: Aam {%ax} $Ib", NACLi_386, st, Binary); | |
| 551 NaClDef_64("d4: Invalid", NACLi_INVALID, st, Other); | |
| 552 NaClDef_32("d5: Aad {%ax}, $Ib", NACLi_386, st, Binary); | |
| 553 NaClDef_64("d5: Invalid", NACLi_INVALID, st, Other); | |
| 554 /* TODO(Karl): Intel manual (see comments above) has a blank entry | |
| 555 * for opcode 0xd6, which states that blank entries in the tables | |
| 556 * correspond to reserved (undefined) values Should we treat this | |
| 557 * accordingly? (currently illegal). | |
| 558 */ | |
| 559 NaClDef_32("d6: Salc {%al}", NACLi_386, st, Other); | |
| 560 NaClDef_64("d6: Invalid", NACLi_INVALID, st, Other); | |
| 561 NaClDefine("d7: Xlat {%al}, {%DS_EBX}", NACLi_386, st, Binary); | |
| 562 /* Note: 0xd8 through 0xdf is defined in ncdecodeX87.c */ | |
| 563 NaClDefLoop(st); /* opcodes e0, e1, and e2 */ | |
| 564 /* 0xe3 - jXXz */ | |
| 565 NaClDefJumpRegZero(st); | |
| 566 NaClDefine("e4: In %al, $Ib", NACLi_386, st, Move); | |
| 567 NaClDefine("e5: In $rAXv, $Ib", NACLi_386, st, Move); | |
| 568 NaClDefine("e6: Out $Ib, %al", NACLi_386, st, Move); | |
| 569 NaClDefine("e7: Out $Ib, $rAXv", NACLi_386, st, Move); | |
| 570 /* Note: We special case the 66 prefix on direct jumps and calls, by | |
| 571 * explicitly disallowing 16-bit direct branches. This is done partly because | |
| 572 * some versions (within x86-64) are not supported in such cases. However, | |
| 573 * NaCl also doesn't want to allow 16-bit direct branches. | |
| 574 */ | |
| 575 NaClDefine("e8: Call {%@ip}, {%@sp}, $Jzd", NACLi_386, st, Call); | |
| 576 NaClDefine("e9: Jmp {%@ip}, $Jzd", NACLi_386, st, Jump); | |
| 577 NaClDef_32("ea: Jmp {%@ip}, $Ap", NACLi_386, st, Jump); | |
| 578 NaClDef_64("ea: Invalid", NACLi_INVALID, st, Other); | |
| 579 NaClDefine("eb: Jmp {%@ip}, $Jb", NACLi_386, st, Jump); | |
| 580 NaClDefine("ec: In %al, %dx", NACLi_386, st, Move); | |
| 581 NaClDefine("ed: In $rAXv, %dx", NACLi_386, st, Move); | |
| 582 NaClDefine("ee: Out %dx, %al", NACLi_386, st, Move); | |
| 583 NaClDefine("ef: Out %dx, $rAXv", NACLi_386, st, Move); | |
| 584 /* f0 : lock prefix. */ | |
| 585 NaClDefine("f0: Invalid", NACLi_INVALID, st, Other); | |
| 586 NaClDefine("f1: Int1", NACLi_386, st, Other); | |
| 587 /* f2: Repne prefix. */ | |
| 588 NaClDefine("f2: Invalid", NACLi_INVALID, st, Other); | |
| 589 /* f3: Rep prefix. */ | |
| 590 NaClDefine("f3: Invalid", NACLi_INVALID, st, Other); | |
| 591 NaClDefine("f4: Hlt", NACLi_386, st, Other); | |
| 592 NaClDefine("f5: Cmc", NACLi_386, st, Other); | |
| 593 /* The "/1" encodings of "Test" are aliases of the "/0" encodings. | |
| 594 * "/0" is used by assemblers. We disallow "/1" on the grounds of | |
| 595 * minimalism. | |
| 596 */ | |
| 597 NaClDefine("f6/0: Test $Eb, $Ib", NACLi_386, st, Compare); | |
| 598 NaClDefine("f6/1: Test $Eb, $Ib", NACLi_ILLEGAL, st, Compare); | |
| 599 NaClDefine("f6/2: Not $Eb", NACLi_386, st, UnaryUpdate); | |
| 600 NaClDefine("f6/3: Neg $Eb", NACLi_386, st, UnaryUpdate); | |
| 601 NaClDefine("f6/4: Mul {%ax}, {%al}, $Eb", NACLi_386, st, Binary); | |
| 602 NaClDefine("f6/5: Imul {%ax}, {%al}, $Eb", NACLi_386, st, Binary); | |
| 603 NaClDefine("f6/6: Div {%ax}, {%al}, $Eb", NACLi_386, st, Binary); | |
| 604 NaClDefine("f6/7: Idiv {%ax}, {%al},$Eb", NACLi_386, st, Binary); | |
| 605 NaClDefine("f7/0: Test $Ev, $Iz", NACLi_386, st, Compare); | |
| 606 NaClDefine("f7/1: Test $Ev, $Iz", NACLi_ILLEGAL, st, Compare); | |
| 607 NaClDefine("f7/2: Not $Ev", NACLi_386, st, UnaryUpdate); | |
| 608 NaClDefine("f7/3: Neg $Ev", NACLi_386, st, UnaryUpdate); | |
| 609 NaClDefine("f7/4: Mul {%redx}, {%reax}, $Ev", NACLi_386, st, O2Binary); | |
| 610 NaClDefine("f7/5: Imul {%redx}, {%reax}, $Ev", NACLi_386, st, O2Binary); | |
| 611 NaClDefine("f7/6: Div {%redx}, {%reax}, $Ev", NACLi_386, st, O2Binary); | |
| 612 NaClDefine("f7/7: Idiv {%redx}, {%reax}, $Ev", NACLi_386, st, O2Binary); | |
| 613 NaClDefine("f8: Clc", NACLi_386, st, Other); | |
| 614 NaClDefine("f9: Stc", NACLi_386, st, Other); | |
| 615 NaClDefine("fa: Cli", NACLi_SYSTEM, st, Other); | |
| 616 NaClDefine("fb: Sti", NACLi_SYSTEM, st, Other); | |
| 617 NaClDefine("fc: Cld", NACLi_386, st, Other); | |
| 618 NaClDefine("fd: Std", NACLi_386, st, Other); | |
| 619 NaClDefine("fe/0: Inc $Eb", NACLi_386, st, UnaryUpdate); | |
| 620 NaClDefine("fe/1: Dec $Eb", NACLi_386, st, UnaryUpdate); | |
| 621 NaClDefine("fe/2: Invalid", NACLi_INVALID, st, Other); | |
| 622 NaClDefine("fe/3: Invalid", NACLi_INVALID, st, Other); | |
| 623 NaClDefine("fe/4: Invalid", NACLi_INVALID, st, Other); | |
| 624 NaClDefine("fe/5: Invalid", NACLi_INVALID, st, Other); | |
| 625 NaClDefine("fe/6: Invalid", NACLi_INVALID, st, Other); | |
| 626 NaClDefine("fe/7: Invalid", NACLi_INVALID, st, Other); | |
| 627 NaClDefine("ff/0: Inc $Ev", NACLi_386, st, UnaryUpdate); | |
| 628 NaClDefine("ff/1: Dec $Ev", NACLi_386, st, UnaryUpdate); | |
| 629 NaClBegDef("ff/2: Call {%@ip}, {%@sp}, $Ev", NACLi_386, st); | |
| 630 NaClAddOpFlags(2, NACL_OPFLAG(OperandNear)); | |
| 631 NaClEndDef(Call); | |
| 632 NaClDefine("ff/3: Call {%@ip}, {%@sp}, $Mp", NACLi_386, st, Call); | |
| 633 NaClBegDef("ff/4: Jmp {%@ip}, $Ev", NACLi_386, st); | |
| 634 NaClAddOpFlags(1, NACL_OPFLAG(OperandNear)); | |
| 635 NaClEndDef(Jump); | |
| 636 NaClDefine("ff/5: Jmp {%@ip}, $Mp", NACLi_386, st, Jump); | |
| 637 NaClDefine("ff/6: Push {%@sp}, $Ev", NACLi_386, st, Push); | |
| 638 NaClDefine("ff/7: Invalid", NACLi_INVALID, st, Other); | |
| 639 } | |
| OLD | NEW |