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