PageRenderTime 68ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/src/freebsd/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp

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