X86DisassemblerTables.cpp revision 19dbe2f5f0db6b236e76550912eff9cc2a77bca8
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, unsigned &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, unsigned &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 for (unsigned index = 0; index < 256; ++index) { 213 if (decision.instructionIDs[index] != decision.instructionIDs[0]) 214 satisfiesOneEntry = false; 215 216 if (((index & 0xc0) == 0xc0) && 217 (decision.instructionIDs[index] != decision.instructionIDs[0xc0])) 218 satisfiesSplitRM = false; 219 220 if (((index & 0xc0) != 0xc0) && 221 (decision.instructionIDs[index] != decision.instructionIDs[0x00])) 222 satisfiesSplitRM = false; 223 224 if (((index & 0xc0) == 0xc0) && 225 (decision.instructionIDs[index] != decision.instructionIDs[index&0xf8])) 226 satisfiesSplitReg = false; 227 228 if (((index & 0xc0) != 0xc0) && 229 (decision.instructionIDs[index] != decision.instructionIDs[index&0x38])) 230 satisfiesSplitReg = false; 231 } 232 233 if (satisfiesOneEntry) 234 return MODRM_ONEENTRY; 235 236 if (satisfiesSplitRM) 237 return MODRM_SPLITRM; 238 239 if (satisfiesSplitReg) 240 return MODRM_SPLITREG; 241 242 return MODRM_FULL; 243} 244 245/// stringForDecisionType - Returns a statically-allocated string corresponding 246/// to a particular decision type. 247/// 248/// @param dt - The decision type. 249/// @return - A pointer to the statically-allocated string (e.g., 250/// "MODRM_ONEENTRY" for MODRM_ONEENTRY). 251static const char* stringForDecisionType(ModRMDecisionType dt) { 252#define ENUM_ENTRY(n) case n: return #n; 253 switch (dt) { 254 default: 255 llvm_unreachable("Unknown decision type"); 256 MODRMTYPES 257 }; 258#undef ENUM_ENTRY 259} 260 261/// stringForModifierType - Returns a statically-allocated string corresponding 262/// to an opcode modifier type. 263/// 264/// @param mt - The modifier type. 265/// @return - A pointer to the statically-allocated string (e.g., 266/// "MODIFIER_NONE" for MODIFIER_NONE). 267static const char* stringForModifierType(ModifierType mt) { 268#define ENUM_ENTRY(n) case n: return #n; 269 switch(mt) { 270 default: 271 llvm_unreachable("Unknown modifier type"); 272 MODIFIER_TYPES 273 }; 274#undef ENUM_ENTRY 275} 276 277DisassemblerTables::DisassemblerTables() { 278 unsigned i; 279 280 for (i = 0; i < array_lengthof(Tables); i++) { 281 Tables[i] = new ContextDecision; 282 memset(Tables[i], 0, sizeof(ContextDecision)); 283 } 284 285 HasConflicts = false; 286} 287 288DisassemblerTables::~DisassemblerTables() { 289 unsigned i; 290 291 for (i = 0; i < array_lengthof(Tables); i++) 292 delete Tables[i]; 293} 294 295void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2, 296 unsigned &i1, unsigned &i2, 297 ModRMDecision &decision) const { 298 static uint32_t sTableNumber = 0; 299 static uint32_t sEntryNumber = 1; 300 ModRMDecisionType dt = getDecisionType(decision); 301 302 if (dt == MODRM_ONEENTRY && decision.instructionIDs[0] == 0) 303 { 304 o2.indent(i2) << "{ /* ModRMDecision */" << "\n"; 305 i2++; 306 307 o2.indent(i2) << stringForDecisionType(dt) << "," << "\n"; 308 o2.indent(i2) << 0 << " /* EmptyTable */\n"; 309 310 i2--; 311 o2.indent(i2) << "}"; 312 return; 313 } 314 315 o1 << "/* Table" << sTableNumber << " */\n"; 316 i1++; 317 318 switch (dt) { 319 default: 320 llvm_unreachable("Unknown decision type"); 321 case MODRM_ONEENTRY: 322 emitOneID(o1, i1, decision.instructionIDs[0], true); 323 break; 324 case MODRM_SPLITRM: 325 emitOneID(o1, i1, decision.instructionIDs[0x00], true); // mod = 0b00 326 emitOneID(o1, i1, decision.instructionIDs[0xc0], true); // mod = 0b11 327 break; 328 case MODRM_SPLITREG: 329 for (unsigned index = 0; index < 64; index += 8) 330 emitOneID(o1, i1, decision.instructionIDs[index], true); 331 for (unsigned index = 0xc0; index < 256; index += 8) 332 emitOneID(o1, i1, decision.instructionIDs[index], true); 333 break; 334 case MODRM_FULL: 335 for (unsigned index = 0; index < 256; ++index) 336 emitOneID(o1, i1, decision.instructionIDs[index], true); 337 break; 338 } 339 340 i1--; 341 342 o2.indent(i2) << "{ /* struct ModRMDecision */" << "\n"; 343 i2++; 344 345 o2.indent(i2) << stringForDecisionType(dt) << "," << "\n"; 346 o2.indent(i2) << sEntryNumber << " /* Table" << sTableNumber << " */\n"; 347 348 i2--; 349 o2.indent(i2) << "}"; 350 351 switch (dt) { 352 default: 353 llvm_unreachable("Unknown decision type"); 354 case MODRM_ONEENTRY: 355 sEntryNumber += 1; 356 break; 357 case MODRM_SPLITRM: 358 sEntryNumber += 2; 359 break; 360 case MODRM_SPLITREG: 361 sEntryNumber += 16; 362 break; 363 case MODRM_FULL: 364 sEntryNumber += 256; 365 break; 366 } 367 368 ++sTableNumber; 369} 370 371void DisassemblerTables::emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2, 372 unsigned &i1, unsigned &i2, 373 OpcodeDecision &decision) const { 374 o2.indent(i2) << "{ /* struct OpcodeDecision */" << "\n"; 375 i2++; 376 o2.indent(i2) << "{" << "\n"; 377 i2++; 378 379 for (unsigned index = 0; index < 256; ++index) { 380 o2.indent(i2); 381 382 o2 << "/* 0x" << format("%02hhx", index) << " */" << "\n"; 383 384 emitModRMDecision(o1, o2, i1, i2, decision.modRMDecisions[index]); 385 386 if (index < 255) 387 o2 << ","; 388 389 o2 << "\n"; 390 } 391 392 i2--; 393 o2.indent(i2) << "}" << "\n"; 394 i2--; 395 o2.indent(i2) << "}" << "\n"; 396} 397 398void DisassemblerTables::emitContextDecision(raw_ostream &o1, raw_ostream &o2, 399 unsigned &i1, unsigned &i2, 400 ContextDecision &decision, 401 const char* name) const { 402 o2.indent(i2) << "static const struct ContextDecision " << name << " = {\n"; 403 i2++; 404 o2.indent(i2) << "{ /* opcodeDecisions */" << "\n"; 405 i2++; 406 407 for (unsigned index = 0; index < IC_max; ++index) { 408 o2.indent(i2) << "/* "; 409 o2 << stringForContext((InstructionContext)index); 410 o2 << " */"; 411 o2 << "\n"; 412 413 emitOpcodeDecision(o1, o2, i1, i2, decision.opcodeDecisions[index]); 414 415 if (index + 1 < IC_max) 416 o2 << ", "; 417 } 418 419 i2--; 420 o2.indent(i2) << "}" << "\n"; 421 i2--; 422 o2.indent(i2) << "};" << "\n"; 423} 424 425void DisassemblerTables::emitInstructionInfo(raw_ostream &o, 426 unsigned &i) const { 427 o.indent(i * 2) << "static const struct InstructionSpecifier "; 428 o << INSTRUCTIONS_STR "[" << InstructionSpecifiers.size() << "] = {\n"; 429 430 i++; 431 432 unsigned numInstructions = InstructionSpecifiers.size(); 433 434 for (unsigned index = 0; index < numInstructions; ++index) { 435 o.indent(i * 2) << "{ /* " << index << " */" << "\n"; 436 i++; 437 438 o.indent(i * 2) << stringForModifierType( 439 (ModifierType)InstructionSpecifiers[index].modifierType); 440 o << "," << "\n"; 441 442 o.indent(i * 2) << "0x"; 443 o << format("%02hhx", (uint16_t)InstructionSpecifiers[index].modifierBase); 444 o << "," << "\n"; 445 446 o.indent(i * 2) << "{" << "\n"; 447 i++; 448 449 for (unsigned operandIndex = 0; operandIndex < X86_MAX_OPERANDS; 450 ++operandIndex) { 451 o.indent(i * 2) << "{ "; 452 o <<stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[index] 453 .operands[operandIndex] 454 .encoding); 455 o << ", "; 456 o << stringForOperandType((OperandType)InstructionSpecifiers[index] 457 .operands[operandIndex] 458 .type); 459 o << " }"; 460 461 if (operandIndex < X86_MAX_OPERANDS - 1) 462 o << ","; 463 464 o << "\n"; 465 } 466 467 i--; 468 o.indent(i * 2) << "}," << "\n"; 469 470 o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */"; 471 o << "\n"; 472 473 i--; 474 o.indent(i * 2) << "}"; 475 476 if (index + 1 < numInstructions) 477 o << ","; 478 479 o << "\n"; 480 } 481 482 i--; 483 o.indent(i * 2) << "};" << "\n"; 484} 485 486void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const { 487 o.indent(i * 2) << "static const uint8_t " CONTEXTS_STR 488 "[256] = {\n"; 489 i++; 490 491 for (unsigned index = 0; index < 256; ++index) { 492 o.indent(i * 2); 493 494 if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) 495 o << "IC_VEX_L_W_OPSIZE"; 496 else if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE)) 497 o << "IC_VEX_L_OPSIZE"; 498 else if ((index & ATTR_VEXL) && (index & ATTR_XD)) 499 o << "IC_VEX_L_XD"; 500 else if ((index & ATTR_VEXL) && (index & ATTR_XS)) 501 o << "IC_VEX_L_XS"; 502 else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) 503 o << "IC_VEX_W_OPSIZE"; 504 else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XD)) 505 o << "IC_VEX_W_XD"; 506 else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XS)) 507 o << "IC_VEX_W_XS"; 508 else if (index & ATTR_VEXL) 509 o << "IC_VEX_L"; 510 else if ((index & ATTR_VEX) && (index & ATTR_REXW)) 511 o << "IC_VEX_W"; 512 else if ((index & ATTR_VEX) && (index & ATTR_OPSIZE)) 513 o << "IC_VEX_OPSIZE"; 514 else if ((index & ATTR_VEX) && (index & ATTR_XD)) 515 o << "IC_VEX_XD"; 516 else if ((index & ATTR_VEX) && (index & ATTR_XS)) 517 o << "IC_VEX_XS"; 518 else if (index & ATTR_VEX) 519 o << "IC_VEX"; 520 else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS)) 521 o << "IC_64BIT_REXW_XS"; 522 else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD)) 523 o << "IC_64BIT_REXW_XD"; 524 else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && 525 (index & ATTR_OPSIZE)) 526 o << "IC_64BIT_REXW_OPSIZE"; 527 else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE)) 528 o << "IC_64BIT_XD_OPSIZE"; 529 else if ((index & ATTR_64BIT) && (index & ATTR_XS) && (index & ATTR_OPSIZE)) 530 o << "IC_64BIT_XS_OPSIZE"; 531 else if ((index & ATTR_64BIT) && (index & ATTR_XS)) 532 o << "IC_64BIT_XS"; 533 else if ((index & ATTR_64BIT) && (index & ATTR_XD)) 534 o << "IC_64BIT_XD"; 535 else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE)) 536 o << "IC_64BIT_OPSIZE"; 537 else if ((index & ATTR_64BIT) && (index & ATTR_ADSIZE)) 538 o << "IC_64BIT_ADSIZE"; 539 else if ((index & ATTR_64BIT) && (index & ATTR_REXW)) 540 o << "IC_64BIT_REXW"; 541 else if ((index & ATTR_64BIT)) 542 o << "IC_64BIT"; 543 else if ((index & ATTR_XS) && (index & ATTR_OPSIZE)) 544 o << "IC_XS_OPSIZE"; 545 else if ((index & ATTR_XD) && (index & ATTR_OPSIZE)) 546 o << "IC_XD_OPSIZE"; 547 else if (index & ATTR_XS) 548 o << "IC_XS"; 549 else if (index & ATTR_XD) 550 o << "IC_XD"; 551 else if (index & ATTR_OPSIZE) 552 o << "IC_OPSIZE"; 553 else if (index & ATTR_ADSIZE) 554 o << "IC_ADSIZE"; 555 else 556 o << "IC"; 557 558 if (index < 255) 559 o << ","; 560 else 561 o << " "; 562 563 o << " /* " << index << " */"; 564 565 o << "\n"; 566 } 567 568 i--; 569 o.indent(i * 2) << "};" << "\n"; 570} 571 572void DisassemblerTables::emitContextDecisions(raw_ostream &o1, raw_ostream &o2, 573 unsigned &i1, unsigned &i2) const { 574 emitContextDecision(o1, o2, i1, i2, *Tables[0], ONEBYTE_STR); 575 emitContextDecision(o1, o2, i1, i2, *Tables[1], TWOBYTE_STR); 576 emitContextDecision(o1, o2, i1, i2, *Tables[2], THREEBYTE38_STR); 577 emitContextDecision(o1, o2, i1, i2, *Tables[3], THREEBYTE3A_STR); 578 emitContextDecision(o1, o2, i1, i2, *Tables[4], THREEBYTEA6_STR); 579 emitContextDecision(o1, o2, i1, i2, *Tables[5], THREEBYTEA7_STR); 580} 581 582void DisassemblerTables::emit(raw_ostream &o) const { 583 unsigned i1 = 0; 584 unsigned i2 = 0; 585 586 std::string s1; 587 std::string s2; 588 589 raw_string_ostream o1(s1); 590 raw_string_ostream o2(s2); 591 592 emitInstructionInfo(o, i2); 593 o << "\n"; 594 595 emitContextTable(o, i2); 596 o << "\n"; 597 598 o << "static const InstrUID modRMTable[] = {\n"; 599 i1++; 600 emitEmptyTable(o1, i1); 601 i1--; 602 emitContextDecisions(o1, o2, i1, i2); 603 604 o << o1.str(); 605 o << " 0x0\n"; 606 o << "};\n"; 607 o << "\n"; 608 o << o2.str(); 609 o << "\n"; 610 o << "\n"; 611} 612 613void DisassemblerTables::setTableFields(ModRMDecision &decision, 614 const ModRMFilter &filter, 615 InstrUID uid, 616 uint8_t opcode) { 617 for (unsigned index = 0; index < 256; ++index) { 618 if (filter.accepts(index)) { 619 if (decision.instructionIDs[index] == uid) 620 continue; 621 622 if (decision.instructionIDs[index] != 0) { 623 InstructionSpecifier &newInfo = 624 InstructionSpecifiers[uid]; 625 InstructionSpecifier &previousInfo = 626 InstructionSpecifiers[decision.instructionIDs[index]]; 627 628 if(newInfo.filtered) 629 continue; // filtered instructions get lowest priority 630 631 if(previousInfo.name == "NOOP" && (newInfo.name == "XCHG16ar" || 632 newInfo.name == "XCHG32ar" || 633 newInfo.name == "XCHG32ar64" || 634 newInfo.name == "XCHG64ar")) 635 continue; // special case for XCHG*ar and NOOP 636 637 if (outranks(previousInfo.insnContext, newInfo.insnContext)) 638 continue; 639 640 if (previousInfo.insnContext == newInfo.insnContext && 641 !previousInfo.filtered) { 642 errs() << "Error: Primary decode conflict: "; 643 errs() << newInfo.name << " would overwrite " << previousInfo.name; 644 errs() << "\n"; 645 errs() << "ModRM " << index << "\n"; 646 errs() << "Opcode " << (uint16_t)opcode << "\n"; 647 errs() << "Context " << stringForContext(newInfo.insnContext) << "\n"; 648 HasConflicts = true; 649 } 650 } 651 652 decision.instructionIDs[index] = uid; 653 } 654 } 655} 656 657void DisassemblerTables::setTableFields(OpcodeType type, 658 InstructionContext insnContext, 659 uint8_t opcode, 660 const ModRMFilter &filter, 661 InstrUID uid, 662 bool is32bit, 663 bool ignoresVEX_L) { 664 ContextDecision &decision = *Tables[type]; 665 666 for (unsigned index = 0; index < IC_max; ++index) { 667 if (is32bit && inheritsFrom((InstructionContext)index, IC_64BIT)) 668 continue; 669 670 if (inheritsFrom((InstructionContext)index, 671 InstructionSpecifiers[uid].insnContext, ignoresVEX_L)) 672 setTableFields(decision.opcodeDecisions[index].modRMDecisions[opcode], 673 filter, 674 uid, 675 opcode); 676 } 677} 678