X86DisassemblerTables.cpp revision e08789f5e21c575a3c8d9ee8fa8f3f30479ae326
1//===- X86DisassemblerTables.cpp - Disassembler tables ----------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file is part of the X86 Disassembler Emitter. 11// It contains the implementation of the disassembler tables. 12// Documentation for the disassembler emitter in general can be found in 13// X86DisasemblerEmitter.h. 14// 15//===----------------------------------------------------------------------===// 16 17#include "X86DisassemblerShared.h" 18#include "X86DisassemblerTables.h" 19 20#include "llvm/TableGen/TableGenBackend.h" 21#include "llvm/ADT/STLExtras.h" 22#include "llvm/Support/ErrorHandling.h" 23#include "llvm/Support/Format.h" 24 25using namespace llvm; 26using namespace X86Disassembler; 27 28/// inheritsFrom - Indicates whether all instructions in one class also belong 29/// to another class. 30/// 31/// @param child - The class that may be the subset 32/// @param parent - The class that may be the superset 33/// @return - True if child is a subset of parent, false otherwise. 34static inline bool inheritsFrom(InstructionContext child, 35 InstructionContext parent, 36 bool VEX_LIG = false) { 37 if (child == parent) 38 return true; 39 40 switch (parent) { 41 case IC: 42 return(inheritsFrom(child, IC_64BIT) || 43 inheritsFrom(child, IC_OPSIZE) || 44 inheritsFrom(child, IC_ADSIZE) || 45 inheritsFrom(child, IC_XD) || 46 inheritsFrom(child, IC_XS)); 47 case IC_64BIT: 48 return(inheritsFrom(child, IC_64BIT_REXW) || 49 inheritsFrom(child, IC_64BIT_OPSIZE) || 50 inheritsFrom(child, IC_64BIT_ADSIZE) || 51 inheritsFrom(child, IC_64BIT_XD) || 52 inheritsFrom(child, IC_64BIT_XS)); 53 case IC_OPSIZE: 54 return inheritsFrom(child, IC_64BIT_OPSIZE); 55 case IC_ADSIZE: 56 case IC_64BIT_ADSIZE: 57 return false; 58 case IC_XD: 59 return inheritsFrom(child, IC_64BIT_XD); 60 case IC_XS: 61 return inheritsFrom(child, IC_64BIT_XS); 62 case IC_XD_OPSIZE: 63 return inheritsFrom(child, IC_64BIT_XD_OPSIZE); 64 case IC_XS_OPSIZE: 65 return inheritsFrom(child, IC_64BIT_XS_OPSIZE); 66 case IC_64BIT_REXW: 67 return(inheritsFrom(child, IC_64BIT_REXW_XS) || 68 inheritsFrom(child, IC_64BIT_REXW_XD) || 69 inheritsFrom(child, IC_64BIT_REXW_OPSIZE)); 70 case IC_64BIT_OPSIZE: 71 return(inheritsFrom(child, IC_64BIT_REXW_OPSIZE)); 72 case IC_64BIT_XD: 73 return(inheritsFrom(child, IC_64BIT_REXW_XD)); 74 case IC_64BIT_XS: 75 return(inheritsFrom(child, IC_64BIT_REXW_XS)); 76 case IC_64BIT_XD_OPSIZE: 77 case IC_64BIT_XS_OPSIZE: 78 return false; 79 case IC_64BIT_REXW_XD: 80 case IC_64BIT_REXW_XS: 81 case IC_64BIT_REXW_OPSIZE: 82 return false; 83 case IC_VEX: 84 return inheritsFrom(child, IC_VEX_W) || 85 (VEX_LIG && inheritsFrom(child, IC_VEX_L)); 86 case IC_VEX_XS: 87 return inheritsFrom(child, IC_VEX_W_XS) || 88 (VEX_LIG && inheritsFrom(child, IC_VEX_L_XS)); 89 case IC_VEX_XD: 90 return inheritsFrom(child, IC_VEX_W_XD) || 91 (VEX_LIG && inheritsFrom(child, IC_VEX_L_XD)); 92 case IC_VEX_OPSIZE: 93 return inheritsFrom(child, IC_VEX_W_OPSIZE) || 94 (VEX_LIG && inheritsFrom(child, IC_VEX_L_OPSIZE)); 95 case IC_VEX_W: 96 case IC_VEX_W_XS: 97 case IC_VEX_W_XD: 98 case IC_VEX_W_OPSIZE: 99 return false; 100 case IC_VEX_L: 101 case IC_VEX_L_XS: 102 case IC_VEX_L_XD: 103 return false; 104 case IC_VEX_L_OPSIZE: 105 return inheritsFrom(child, IC_VEX_L_W_OPSIZE); 106 case IC_VEX_L_W_OPSIZE: 107 return false; 108 default: 109 llvm_unreachable("Unknown instruction class"); 110 } 111} 112 113/// outranks - Indicates whether, if an instruction has two different applicable 114/// classes, which class should be preferred when performing decode. This 115/// imposes a total ordering (ties are resolved toward "lower") 116/// 117/// @param upper - The class that may be preferable 118/// @param lower - The class that may be less preferable 119/// @return - True if upper is to be preferred, false otherwise. 120static inline bool outranks(InstructionContext upper, 121 InstructionContext lower) { 122 assert(upper < IC_max); 123 assert(lower < IC_max); 124 125#define ENUM_ENTRY(n, r, d) r, 126 static int ranks[IC_max] = { 127 INSTRUCTION_CONTEXTS 128 }; 129#undef ENUM_ENTRY 130 131 return (ranks[upper] > ranks[lower]); 132} 133 134/// stringForContext - Returns a string containing the name of a particular 135/// InstructionContext, usually for diagnostic purposes. 136/// 137/// @param insnContext - The instruction class to transform to a string. 138/// @return - A statically-allocated string constant that contains the 139/// name of the instruction class. 140static inline const char* stringForContext(InstructionContext insnContext) { 141 switch (insnContext) { 142 default: 143 llvm_unreachable("Unhandled instruction class"); 144#define ENUM_ENTRY(n, r, d) case n: return #n; break; 145 INSTRUCTION_CONTEXTS 146#undef ENUM_ENTRY 147 } 148} 149 150/// stringForOperandType - Like stringForContext, but for OperandTypes. 151static inline const char* stringForOperandType(OperandType type) { 152 switch (type) { 153 default: 154 llvm_unreachable("Unhandled type"); 155#define ENUM_ENTRY(i, d) case i: return #i; 156 TYPES 157#undef ENUM_ENTRY 158 } 159} 160 161/// stringForOperandEncoding - like stringForContext, but for 162/// OperandEncodings. 163static inline const char* stringForOperandEncoding(OperandEncoding encoding) { 164 switch (encoding) { 165 default: 166 llvm_unreachable("Unhandled encoding"); 167#define ENUM_ENTRY(i, d) case i: return #i; 168 ENCODINGS 169#undef ENUM_ENTRY 170 } 171} 172 173void DisassemblerTables::emitOneID(raw_ostream &o, uint32_t &i, InstrUID id, 174 bool addComma) const { 175 if (id) 176 o.indent(i * 2) << format("0x%hx", id); 177 else 178 o.indent(i * 2) << 0; 179 180 if (addComma) 181 o << ", "; 182 else 183 o << " "; 184 185 o << "/* "; 186 o << InstructionSpecifiers[id].name; 187 o << "*/"; 188 189 o << "\n"; 190} 191 192/// emitEmptyTable - Emits the modRMEmptyTable, which is used as a ID table by 193/// all ModR/M decisions for instructions that are invalid for all possible 194/// ModR/M byte values. 195/// 196/// @param o - The output stream on which to emit the table. 197/// @param i - The indentation level for that output stream. 198static void emitEmptyTable(raw_ostream &o, uint32_t &i) { 199 o.indent(i * 2) << "0x0, /* EmptyTable */\n"; 200} 201 202/// getDecisionType - Determines whether a ModRM decision with 255 entries can 203/// be compacted by eliminating redundant information. 204/// 205/// @param decision - The decision to be compacted. 206/// @return - The compactest available representation for the decision. 207static ModRMDecisionType getDecisionType(ModRMDecision &decision) { 208 bool satisfiesOneEntry = true; 209 bool satisfiesSplitRM = true; 210 bool satisfiesSplitReg = true; 211 212 uint16_t index; 213 214 for (index = 0; index < 256; ++index) { 215 if (decision.instructionIDs[index] != decision.instructionIDs[0]) 216 satisfiesOneEntry = false; 217 218 if (((index & 0xc0) == 0xc0) && 219 (decision.instructionIDs[index] != decision.instructionIDs[0xc0])) 220 satisfiesSplitRM = false; 221 222 if (((index & 0xc0) != 0xc0) && 223 (decision.instructionIDs[index] != decision.instructionIDs[0x00])) 224 satisfiesSplitRM = false; 225 226 if (((index & 0xc0) == 0xc0) && 227 (decision.instructionIDs[index] != decision.instructionIDs[index&0xf8])) 228 satisfiesSplitReg = false; 229 230 if (((index & 0xc0) != 0xc0) && 231 (decision.instructionIDs[index] != decision.instructionIDs[index&0x38])) 232 satisfiesSplitReg = false; 233 } 234 235 if (satisfiesOneEntry) 236 return MODRM_ONEENTRY; 237 238 if (satisfiesSplitRM) 239 return MODRM_SPLITRM; 240 241 if (satisfiesSplitReg) 242 return MODRM_SPLITREG; 243 244 return MODRM_FULL; 245} 246 247/// stringForDecisionType - Returns a statically-allocated string corresponding 248/// to a particular decision type. 249/// 250/// @param dt - The decision type. 251/// @return - A pointer to the statically-allocated string (e.g., 252/// "MODRM_ONEENTRY" for MODRM_ONEENTRY). 253static const char* stringForDecisionType(ModRMDecisionType dt) { 254#define ENUM_ENTRY(n) case n: return #n; 255 switch (dt) { 256 default: 257 llvm_unreachable("Unknown decision type"); 258 MODRMTYPES 259 }; 260#undef ENUM_ENTRY 261} 262 263/// stringForModifierType - Returns a statically-allocated string corresponding 264/// to an opcode modifier type. 265/// 266/// @param mt - The modifier type. 267/// @return - A pointer to the statically-allocated string (e.g., 268/// "MODIFIER_NONE" for MODIFIER_NONE). 269static const char* stringForModifierType(ModifierType mt) { 270#define ENUM_ENTRY(n) case n: return #n; 271 switch(mt) { 272 default: 273 llvm_unreachable("Unknown modifier type"); 274 MODIFIER_TYPES 275 }; 276#undef ENUM_ENTRY 277} 278 279DisassemblerTables::DisassemblerTables() { 280 unsigned i; 281 282 for (i = 0; i < array_lengthof(Tables); i++) { 283 Tables[i] = new ContextDecision; 284 memset(Tables[i], 0, sizeof(ContextDecision)); 285 } 286 287 HasConflicts = false; 288} 289 290DisassemblerTables::~DisassemblerTables() { 291 unsigned i; 292 293 for (i = 0; i < array_lengthof(Tables); i++) 294 delete Tables[i]; 295} 296 297void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2, 298 uint32_t &i1, uint32_t &i2, 299 ModRMDecision &decision) const { 300 static uint64_t sTableNumber = 0; 301 static uint64_t sEntryNumber = 1; 302 ModRMDecisionType dt = getDecisionType(decision); 303 uint16_t index; 304 305 if (dt == MODRM_ONEENTRY && decision.instructionIDs[0] == 0) 306 { 307 o2.indent(i2) << "{ /* ModRMDecision */" << "\n"; 308 i2++; 309 310 o2.indent(i2) << stringForDecisionType(dt) << "," << "\n"; 311 o2.indent(i2) << 0 << " /* EmptyTable */\n"; 312 313 i2--; 314 o2.indent(i2) << "}"; 315 return; 316 } 317 318 o1 << "/* Table" << sTableNumber << " */\n"; 319 i1++; 320 321 switch (dt) { 322 default: 323 llvm_unreachable("Unknown decision type"); 324 case MODRM_ONEENTRY: 325 emitOneID(o1, i1, decision.instructionIDs[0], true); 326 break; 327 case MODRM_SPLITRM: 328 emitOneID(o1, i1, decision.instructionIDs[0x00], true); // mod = 0b00 329 emitOneID(o1, i1, decision.instructionIDs[0xc0], true); // mod = 0b11 330 break; 331 case MODRM_SPLITREG: 332 for (index = 0; index < 64; index += 8) 333 emitOneID(o1, i1, decision.instructionIDs[index], true); 334 for (index = 0xc0; index < 256; index += 8) 335 emitOneID(o1, i1, decision.instructionIDs[index], true); 336 break; 337 case MODRM_FULL: 338 for (index = 0; index < 256; ++index) 339 emitOneID(o1, i1, decision.instructionIDs[index], true); 340 break; 341 } 342 343 i1--; 344 345 o2.indent(i2) << "{ /* struct ModRMDecision */" << "\n"; 346 i2++; 347 348 o2.indent(i2) << stringForDecisionType(dt) << "," << "\n"; 349 o2.indent(i2) << sEntryNumber << " /* Table" << sTableNumber << " */\n"; 350 351 i2--; 352 o2.indent(i2) << "}"; 353 354 switch (dt) { 355 default: 356 llvm_unreachable("Unknown decision type"); 357 case MODRM_ONEENTRY: 358 sEntryNumber += 1; 359 break; 360 case MODRM_SPLITRM: 361 sEntryNumber += 2; 362 break; 363 case MODRM_SPLITREG: 364 sEntryNumber += 16; 365 break; 366 case MODRM_FULL: 367 sEntryNumber += 256; 368 break; 369 } 370 371 ++sTableNumber; 372} 373 374void DisassemblerTables::emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2, 375 uint32_t &i1, uint32_t &i2, 376 OpcodeDecision &decision) const { 377 uint16_t index; 378 379 o2.indent(i2) << "{ /* struct OpcodeDecision */" << "\n"; 380 i2++; 381 o2.indent(i2) << "{" << "\n"; 382 i2++; 383 384 for (index = 0; index < 256; ++index) { 385 o2.indent(i2); 386 387 o2 << "/* 0x" << format("%02hhx", index) << " */" << "\n"; 388 389 emitModRMDecision(o1, o2, i1, i2, decision.modRMDecisions[index]); 390 391 if (index < 255) 392 o2 << ","; 393 394 o2 << "\n"; 395 } 396 397 i2--; 398 o2.indent(i2) << "}" << "\n"; 399 i2--; 400 o2.indent(i2) << "}" << "\n"; 401} 402 403void DisassemblerTables::emitContextDecision(raw_ostream &o1, raw_ostream &o2, 404 uint32_t &i1, uint32_t &i2, 405 ContextDecision &decision, 406 const char* name) const { 407 o2.indent(i2) << "static const struct ContextDecision " << name << " = {\n"; 408 i2++; 409 o2.indent(i2) << "{ /* opcodeDecisions */" << "\n"; 410 i2++; 411 412 unsigned index; 413 414 for (index = 0; index < IC_max; ++index) { 415 o2.indent(i2) << "/* "; 416 o2 << stringForContext((InstructionContext)index); 417 o2 << " */"; 418 o2 << "\n"; 419 420 emitOpcodeDecision(o1, o2, i1, i2, decision.opcodeDecisions[index]); 421 422 if (index + 1 < IC_max) 423 o2 << ", "; 424 } 425 426 i2--; 427 o2.indent(i2) << "}" << "\n"; 428 i2--; 429 o2.indent(i2) << "};" << "\n"; 430} 431 432void DisassemblerTables::emitInstructionInfo(raw_ostream &o, uint32_t &i) 433 const { 434 o.indent(i * 2) << "static const struct InstructionSpecifier "; 435 o << INSTRUCTIONS_STR "[" << InstructionSpecifiers.size() << "] = {\n"; 436 437 i++; 438 439 uint16_t numInstructions = InstructionSpecifiers.size(); 440 uint16_t index, operandIndex; 441 442 for (index = 0; index < numInstructions; ++index) { 443 o.indent(i * 2) << "{ /* " << index << " */" << "\n"; 444 i++; 445 446 o.indent(i * 2) << stringForModifierType( 447 (ModifierType)InstructionSpecifiers[index].modifierType); 448 o << "," << "\n"; 449 450 o.indent(i * 2) << "0x"; 451 o << format("%02hhx", (uint16_t)InstructionSpecifiers[index].modifierBase); 452 o << "," << "\n"; 453 454 o.indent(i * 2) << "{" << "\n"; 455 i++; 456 457 for (operandIndex = 0; operandIndex < X86_MAX_OPERANDS; ++operandIndex) { 458 o.indent(i * 2) << "{ "; 459 o <<stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[index] 460 .operands[operandIndex] 461 .encoding); 462 o << ", "; 463 o << stringForOperandType((OperandType)InstructionSpecifiers[index] 464 .operands[operandIndex] 465 .type); 466 o << " }"; 467 468 if (operandIndex < X86_MAX_OPERANDS - 1) 469 o << ","; 470 471 o << "\n"; 472 } 473 474 i--; 475 o.indent(i * 2) << "}," << "\n"; 476 477 o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */"; 478 o << "\n"; 479 480 i--; 481 o.indent(i * 2) << "}"; 482 483 if (index + 1 < numInstructions) 484 o << ","; 485 486 o << "\n"; 487 } 488 489 i--; 490 o.indent(i * 2) << "};" << "\n"; 491} 492 493void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const { 494 uint16_t index; 495 496 o.indent(i * 2) << "static const InstructionContext " CONTEXTS_STR 497 "[256] = {\n"; 498 i++; 499 500 for (index = 0; index < 256; ++index) { 501 o.indent(i * 2); 502 503 if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) 504 o << "IC_VEX_L_W_OPSIZE"; 505 else if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE)) 506 o << "IC_VEX_L_OPSIZE"; 507 else if ((index & ATTR_VEXL) && (index & ATTR_XD)) 508 o << "IC_VEX_L_XD"; 509 else if ((index & ATTR_VEXL) && (index & ATTR_XS)) 510 o << "IC_VEX_L_XS"; 511 else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) 512 o << "IC_VEX_W_OPSIZE"; 513 else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XD)) 514 o << "IC_VEX_W_XD"; 515 else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XS)) 516 o << "IC_VEX_W_XS"; 517 else if (index & ATTR_VEXL) 518 o << "IC_VEX_L"; 519 else if ((index & ATTR_VEX) && (index & ATTR_REXW)) 520 o << "IC_VEX_W"; 521 else if ((index & ATTR_VEX) && (index & ATTR_OPSIZE)) 522 o << "IC_VEX_OPSIZE"; 523 else if ((index & ATTR_VEX) && (index & ATTR_XD)) 524 o << "IC_VEX_XD"; 525 else if ((index & ATTR_VEX) && (index & ATTR_XS)) 526 o << "IC_VEX_XS"; 527 else if (index & ATTR_VEX) 528 o << "IC_VEX"; 529 else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS)) 530 o << "IC_64BIT_REXW_XS"; 531 else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD)) 532 o << "IC_64BIT_REXW_XD"; 533 else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && 534 (index & ATTR_OPSIZE)) 535 o << "IC_64BIT_REXW_OPSIZE"; 536 else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE)) 537 o << "IC_64BIT_XD_OPSIZE"; 538 else if ((index & ATTR_64BIT) && (index & ATTR_XS) && (index & ATTR_OPSIZE)) 539 o << "IC_64BIT_XS_OPSIZE"; 540 else if ((index & ATTR_64BIT) && (index & ATTR_XS)) 541 o << "IC_64BIT_XS"; 542 else if ((index & ATTR_64BIT) && (index & ATTR_XD)) 543 o << "IC_64BIT_XD"; 544 else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE)) 545 o << "IC_64BIT_OPSIZE"; 546 else if ((index & ATTR_64BIT) && (index & ATTR_ADSIZE)) 547 o << "IC_64BIT_ADSIZE"; 548 else if ((index & ATTR_64BIT) && (index & ATTR_REXW)) 549 o << "IC_64BIT_REXW"; 550 else if ((index & ATTR_64BIT)) 551 o << "IC_64BIT"; 552 else if ((index & ATTR_XS) && (index & ATTR_OPSIZE)) 553 o << "IC_XS_OPSIZE"; 554 else if ((index & ATTR_XD) && (index & ATTR_OPSIZE)) 555 o << "IC_XD_OPSIZE"; 556 else if (index & ATTR_XS) 557 o << "IC_XS"; 558 else if (index & ATTR_XD) 559 o << "IC_XD"; 560 else if (index & ATTR_OPSIZE) 561 o << "IC_OPSIZE"; 562 else if (index & ATTR_ADSIZE) 563 o << "IC_ADSIZE"; 564 else 565 o << "IC"; 566 567 if (index < 255) 568 o << ","; 569 else 570 o << " "; 571 572 o << " /* " << index << " */"; 573 574 o << "\n"; 575 } 576 577 i--; 578 o.indent(i * 2) << "};" << "\n"; 579} 580 581void DisassemblerTables::emitContextDecisions(raw_ostream &o1, raw_ostream &o2, 582 uint32_t &i1, uint32_t &i2) const { 583 emitContextDecision(o1, o2, i1, i2, *Tables[0], ONEBYTE_STR); 584 emitContextDecision(o1, o2, i1, i2, *Tables[1], TWOBYTE_STR); 585 emitContextDecision(o1, o2, i1, i2, *Tables[2], THREEBYTE38_STR); 586 emitContextDecision(o1, o2, i1, i2, *Tables[3], THREEBYTE3A_STR); 587 emitContextDecision(o1, o2, i1, i2, *Tables[4], THREEBYTEA6_STR); 588 emitContextDecision(o1, o2, i1, i2, *Tables[5], THREEBYTEA7_STR); 589} 590 591void DisassemblerTables::emit(raw_ostream &o) const { 592 uint32_t i1 = 0; 593 uint32_t i2 = 0; 594 595 std::string s1; 596 std::string s2; 597 598 raw_string_ostream o1(s1); 599 raw_string_ostream o2(s2); 600 601 emitInstructionInfo(o, i2); 602 o << "\n"; 603 604 emitContextTable(o, i2); 605 o << "\n"; 606 607 o << "static const InstrUID modRMTable[] = {\n"; 608 i1++; 609 emitEmptyTable(o1, i1); 610 i1--; 611 emitContextDecisions(o1, o2, i1, i2); 612 613 o << o1.str(); 614 o << " 0x0\n"; 615 o << "};\n"; 616 o << "\n"; 617 o << o2.str(); 618 o << "\n"; 619 o << "\n"; 620} 621 622void DisassemblerTables::setTableFields(ModRMDecision &decision, 623 const ModRMFilter &filter, 624 InstrUID uid, 625 uint8_t opcode) { 626 unsigned index; 627 628 for (index = 0; index < 256; ++index) { 629 if (filter.accepts(index)) { 630 if (decision.instructionIDs[index] == uid) 631 continue; 632 633 if (decision.instructionIDs[index] != 0) { 634 InstructionSpecifier &newInfo = 635 InstructionSpecifiers[uid]; 636 InstructionSpecifier &previousInfo = 637 InstructionSpecifiers[decision.instructionIDs[index]]; 638 639 if(newInfo.filtered) 640 continue; // filtered instructions get lowest priority 641 642 if(previousInfo.name == "NOOP" && (newInfo.name == "XCHG16ar" || 643 newInfo.name == "XCHG32ar" || 644 newInfo.name == "XCHG32ar64" || 645 newInfo.name == "XCHG64ar")) 646 continue; // special case for XCHG*ar and NOOP 647 648 if (outranks(previousInfo.insnContext, newInfo.insnContext)) 649 continue; 650 651 if (previousInfo.insnContext == newInfo.insnContext && 652 !previousInfo.filtered) { 653 errs() << "Error: Primary decode conflict: "; 654 errs() << newInfo.name << " would overwrite " << previousInfo.name; 655 errs() << "\n"; 656 errs() << "ModRM " << index << "\n"; 657 errs() << "Opcode " << (uint16_t)opcode << "\n"; 658 errs() << "Context " << stringForContext(newInfo.insnContext) << "\n"; 659 HasConflicts = true; 660 } 661 } 662 663 decision.instructionIDs[index] = uid; 664 } 665 } 666} 667 668void DisassemblerTables::setTableFields(OpcodeType type, 669 InstructionContext insnContext, 670 uint8_t opcode, 671 const ModRMFilter &filter, 672 InstrUID uid, 673 bool is32bit, 674 bool ignoresVEX_L) { 675 unsigned index; 676 677 ContextDecision &decision = *Tables[type]; 678 679 for (index = 0; index < IC_max; ++index) { 680 if (is32bit && inheritsFrom((InstructionContext)index, IC_64BIT)) 681 continue; 682 683 if (inheritsFrom((InstructionContext)index, 684 InstructionSpecifiers[uid].insnContext, ignoresVEX_L)) 685 setTableFields(decision.opcodeDecisions[index].modRMDecisions[opcode], 686 filter, 687 uid, 688 opcode); 689 } 690} 691