1 //===- X86DisassemblerTables.cpp - Disassembler tables ----------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
15 //===----------------------------------------------------------------------===//
17 #include "X86DisassemblerTables.h"
18 #include "X86DisassemblerShared.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/Support/Format.h"
25 using namespace X86Disassembler
;
27 /// stringForContext - Returns a string containing the name of a particular
28 /// InstructionContext, usually for diagnostic purposes.
30 /// @param insnContext - The instruction class to transform to a string.
31 /// @return - A statically-allocated string constant that contains the
32 /// name of the instruction class.
33 static inline const char* stringForContext(InstructionContext insnContext
) {
34 switch (insnContext
) {
36 llvm_unreachable("Unhandled instruction class");
37 #define ENUM_ENTRY(n, r, d) case n: return #n; break;
38 #define ENUM_ENTRY_K_B(n, r, d) ENUM_ENTRY(n, r, d) ENUM_ENTRY(n##_K_B, r, d)\
39 ENUM_ENTRY(n##_KZ, r, d) ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d)\
40 ENUM_ENTRY(n##_KZ_B, r, d)
47 /// stringForOperandType - Like stringForContext, but for OperandTypes.
48 static inline const char* stringForOperandType(OperandType type
) {
51 llvm_unreachable("Unhandled type");
52 #define ENUM_ENTRY(i, d) case i: return #i;
58 /// stringForOperandEncoding - like stringForContext, but for
60 static inline const char* stringForOperandEncoding(OperandEncoding encoding
) {
63 llvm_unreachable("Unhandled encoding");
64 #define ENUM_ENTRY(i, d) case i: return #i;
70 /// inheritsFrom - Indicates whether all instructions in one class also belong
73 /// @param child - The class that may be the subset
74 /// @param parent - The class that may be the superset
75 /// @return - True if child is a subset of parent, false otherwise.
76 static inline bool inheritsFrom(InstructionContext child
,
77 InstructionContext parent
,
78 bool VEX_LIG
= false, bool AdSize64
= false) {
84 return(inheritsFrom(child
, IC_64BIT
, AdSize64
) ||
85 inheritsFrom(child
, IC_OPSIZE
) ||
86 inheritsFrom(child
, IC_ADSIZE
) ||
87 inheritsFrom(child
, IC_XD
) ||
88 inheritsFrom(child
, IC_XS
));
90 return(inheritsFrom(child
, IC_64BIT_REXW
) ||
91 inheritsFrom(child
, IC_64BIT_OPSIZE
) ||
92 (!AdSize64
&& inheritsFrom(child
, IC_64BIT_ADSIZE
)) ||
93 inheritsFrom(child
, IC_64BIT_XD
) ||
94 inheritsFrom(child
, IC_64BIT_XS
));
96 return inheritsFrom(child
, IC_64BIT_OPSIZE
) ||
97 inheritsFrom(child
, IC_OPSIZE_ADSIZE
);
99 return inheritsFrom(child
, IC_OPSIZE_ADSIZE
);
100 case IC_OPSIZE_ADSIZE
:
102 case IC_64BIT_ADSIZE
:
103 return inheritsFrom(child
, IC_64BIT_OPSIZE_ADSIZE
);
104 case IC_64BIT_OPSIZE_ADSIZE
:
107 return inheritsFrom(child
, IC_64BIT_XD
);
109 return inheritsFrom(child
, IC_64BIT_XS
);
111 return inheritsFrom(child
, IC_64BIT_XD_OPSIZE
);
113 return inheritsFrom(child
, IC_64BIT_XS_OPSIZE
);
115 return(inheritsFrom(child
, IC_64BIT_REXW_XS
) ||
116 inheritsFrom(child
, IC_64BIT_REXW_XD
) ||
117 inheritsFrom(child
, IC_64BIT_REXW_OPSIZE
) ||
118 (!AdSize64
&& inheritsFrom(child
, IC_64BIT_REXW_ADSIZE
)));
119 case IC_64BIT_OPSIZE
:
120 return inheritsFrom(child
, IC_64BIT_REXW_OPSIZE
) ||
121 (!AdSize64
&& inheritsFrom(child
, IC_64BIT_OPSIZE_ADSIZE
)) ||
122 (!AdSize64
&& inheritsFrom(child
, IC_64BIT_REXW_ADSIZE
));
124 return(inheritsFrom(child
, IC_64BIT_REXW_XD
));
126 return(inheritsFrom(child
, IC_64BIT_REXW_XS
));
127 case IC_64BIT_XD_OPSIZE
:
128 case IC_64BIT_XS_OPSIZE
:
130 case IC_64BIT_REXW_XD
:
131 case IC_64BIT_REXW_XS
:
132 case IC_64BIT_REXW_OPSIZE
:
133 case IC_64BIT_REXW_ADSIZE
:
136 return (VEX_LIG
&& inheritsFrom(child
, IC_VEX_L_W
)) ||
137 inheritsFrom(child
, IC_VEX_W
) ||
138 (VEX_LIG
&& inheritsFrom(child
, IC_VEX_L
));
140 return (VEX_LIG
&& inheritsFrom(child
, IC_VEX_L_W_XS
)) ||
141 inheritsFrom(child
, IC_VEX_W_XS
) ||
142 (VEX_LIG
&& inheritsFrom(child
, IC_VEX_L_XS
));
144 return (VEX_LIG
&& inheritsFrom(child
, IC_VEX_L_W_XD
)) ||
145 inheritsFrom(child
, IC_VEX_W_XD
) ||
146 (VEX_LIG
&& inheritsFrom(child
, IC_VEX_L_XD
));
148 return (VEX_LIG
&& inheritsFrom(child
, IC_VEX_L_W_OPSIZE
)) ||
149 inheritsFrom(child
, IC_VEX_W_OPSIZE
) ||
150 (VEX_LIG
&& inheritsFrom(child
, IC_VEX_L_OPSIZE
));
152 return VEX_LIG
&& inheritsFrom(child
, IC_VEX_L_W
);
154 return VEX_LIG
&& inheritsFrom(child
, IC_VEX_L_W_XS
);
156 return VEX_LIG
&& inheritsFrom(child
, IC_VEX_L_W_XD
);
157 case IC_VEX_W_OPSIZE
:
158 return VEX_LIG
&& inheritsFrom(child
, IC_VEX_L_W_OPSIZE
);
160 return inheritsFrom(child
, IC_VEX_L_W
);
162 return inheritsFrom(child
, IC_VEX_L_W_XS
);
164 return inheritsFrom(child
, IC_VEX_L_W_XD
);
165 case IC_VEX_L_OPSIZE
:
166 return inheritsFrom(child
, IC_VEX_L_W_OPSIZE
);
170 case IC_VEX_L_W_OPSIZE
:
173 return inheritsFrom(child
, IC_EVEX_W
) ||
174 inheritsFrom(child
, IC_EVEX_L_W
);
176 return inheritsFrom(child
, IC_EVEX_W_XS
) ||
177 inheritsFrom(child
, IC_EVEX_L_W_XS
);
179 return inheritsFrom(child
, IC_EVEX_W_XD
) ||
180 inheritsFrom(child
, IC_EVEX_L_W_XD
);
182 return inheritsFrom(child
, IC_EVEX_W_OPSIZE
) ||
183 inheritsFrom(child
, IC_EVEX_L_W_OPSIZE
);
189 case IC_EVEX_W_OPSIZE
:
197 case IC_EVEX_L_OPSIZE
:
202 case IC_EVEX_L_W_OPSIZE
:
207 case IC_EVEX_L2_OPSIZE
:
210 case IC_EVEX_L2_W_XS
:
211 case IC_EVEX_L2_W_XD
:
212 case IC_EVEX_L2_W_OPSIZE
:
215 return inheritsFrom(child
, IC_EVEX_W_K
) ||
216 inheritsFrom(child
, IC_EVEX_L_W_K
);
218 return inheritsFrom(child
, IC_EVEX_W_XS_K
) ||
219 inheritsFrom(child
, IC_EVEX_L_W_XS_K
);
221 return inheritsFrom(child
, IC_EVEX_W_XD_K
) ||
222 inheritsFrom(child
, IC_EVEX_L_W_XD_K
);
227 return inheritsFrom(child
, IC_EVEX_W_XS_KZ
) ||
228 inheritsFrom(child
, IC_EVEX_L_W_XS_KZ
);
230 return inheritsFrom(child
, IC_EVEX_W_XD_KZ
) ||
231 inheritsFrom(child
, IC_EVEX_L_W_XD_KZ
);
233 case IC_EVEX_OPSIZE_K
:
234 case IC_EVEX_OPSIZE_B
:
235 case IC_EVEX_OPSIZE_K_B
:
236 case IC_EVEX_OPSIZE_KZ
:
237 case IC_EVEX_OPSIZE_KZ_B
:
242 case IC_EVEX_W_OPSIZE_K
:
243 case IC_EVEX_W_OPSIZE_B
:
244 case IC_EVEX_W_OPSIZE_K_B
:
249 case IC_EVEX_L_OPSIZE_K
:
250 case IC_EVEX_L_OPSIZE_B
:
251 case IC_EVEX_L_OPSIZE_K_B
:
254 case IC_EVEX_W_XS_KZ
:
255 case IC_EVEX_W_XD_KZ
:
256 case IC_EVEX_W_OPSIZE_KZ
:
257 case IC_EVEX_W_OPSIZE_KZ_B
:
260 case IC_EVEX_L_XS_KZ
:
261 case IC_EVEX_L_XD_KZ
:
262 case IC_EVEX_L_OPSIZE_KZ
:
263 case IC_EVEX_L_OPSIZE_KZ_B
:
266 case IC_EVEX_L_W_XS_K
:
267 case IC_EVEX_L_W_XD_K
:
268 case IC_EVEX_L_W_OPSIZE_K
:
269 case IC_EVEX_L_W_OPSIZE_B
:
270 case IC_EVEX_L_W_OPSIZE_K_B
:
272 case IC_EVEX_L_W_XS_KZ
:
273 case IC_EVEX_L_W_XD_KZ
:
274 case IC_EVEX_L_W_OPSIZE_KZ
:
275 case IC_EVEX_L_W_OPSIZE_KZ_B
:
280 case IC_EVEX_L2_KZ_B
:
281 case IC_EVEX_L2_XS_K
:
282 case IC_EVEX_L2_XS_B
:
283 case IC_EVEX_L2_XD_B
:
284 case IC_EVEX_L2_XD_K
:
285 case IC_EVEX_L2_OPSIZE_K
:
286 case IC_EVEX_L2_OPSIZE_B
:
287 case IC_EVEX_L2_OPSIZE_K_B
:
289 case IC_EVEX_L2_XS_KZ
:
290 case IC_EVEX_L2_XD_KZ
:
291 case IC_EVEX_L2_OPSIZE_KZ
:
292 case IC_EVEX_L2_OPSIZE_KZ_B
:
296 case IC_EVEX_L2_W_XS_K
:
297 case IC_EVEX_L2_W_XD_K
:
298 case IC_EVEX_L2_W_XD_B
:
299 case IC_EVEX_L2_W_OPSIZE_K
:
300 case IC_EVEX_L2_W_OPSIZE_B
:
301 case IC_EVEX_L2_W_OPSIZE_K_B
:
302 case IC_EVEX_L2_W_KZ
:
303 case IC_EVEX_L2_W_XS_KZ
:
304 case IC_EVEX_L2_W_XD_KZ
:
305 case IC_EVEX_L2_W_OPSIZE_KZ
:
306 case IC_EVEX_L2_W_OPSIZE_KZ_B
:
309 errs() << "Unknown instruction class: " <<
310 stringForContext((InstructionContext
)parent
) << "\n";
311 llvm_unreachable("Unknown instruction class");
315 /// outranks - Indicates whether, if an instruction has two different applicable
316 /// classes, which class should be preferred when performing decode. This
317 /// imposes a total ordering (ties are resolved toward "lower")
319 /// @param upper - The class that may be preferable
320 /// @param lower - The class that may be less preferable
321 /// @return - True if upper is to be preferred, false otherwise.
322 static inline bool outranks(InstructionContext upper
,
323 InstructionContext lower
) {
324 assert(upper
< IC_max
);
325 assert(lower
< IC_max
);
327 #define ENUM_ENTRY(n, r, d) r,
328 #define ENUM_ENTRY_K_B(n, r, d) ENUM_ENTRY(n, r, d) \
329 ENUM_ENTRY(n##_K_B, r, d) ENUM_ENTRY(n##_KZ_B, r, d) \
330 ENUM_ENTRY(n##_KZ, r, d) ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d)
331 static int ranks
[IC_max
] = {
335 #undef ENUM_ENTRY_K_B
337 return (ranks
[upper
] > ranks
[lower
]);
340 /// getDecisionType - Determines whether a ModRM decision with 255 entries can
341 /// be compacted by eliminating redundant information.
343 /// @param decision - The decision to be compacted.
344 /// @return - The compactest available representation for the decision.
345 static ModRMDecisionType
getDecisionType(ModRMDecision
&decision
) {
346 bool satisfiesOneEntry
= true;
347 bool satisfiesSplitRM
= true;
348 bool satisfiesSplitReg
= true;
349 bool satisfiesSplitMisc
= true;
351 for (unsigned index
= 0; index
< 256; ++index
) {
352 if (decision
.instructionIDs
[index
] != decision
.instructionIDs
[0])
353 satisfiesOneEntry
= false;
355 if (((index
& 0xc0) == 0xc0) &&
356 (decision
.instructionIDs
[index
] != decision
.instructionIDs
[0xc0]))
357 satisfiesSplitRM
= false;
359 if (((index
& 0xc0) != 0xc0) &&
360 (decision
.instructionIDs
[index
] != decision
.instructionIDs
[0x00]))
361 satisfiesSplitRM
= false;
363 if (((index
& 0xc0) == 0xc0) &&
364 (decision
.instructionIDs
[index
] != decision
.instructionIDs
[index
&0xf8]))
365 satisfiesSplitReg
= false;
367 if (((index
& 0xc0) != 0xc0) &&
368 (decision
.instructionIDs
[index
] != decision
.instructionIDs
[index
&0x38]))
369 satisfiesSplitMisc
= false;
372 if (satisfiesOneEntry
)
373 return MODRM_ONEENTRY
;
375 if (satisfiesSplitRM
)
376 return MODRM_SPLITRM
;
378 if (satisfiesSplitReg
&& satisfiesSplitMisc
)
379 return MODRM_SPLITREG
;
381 if (satisfiesSplitMisc
)
382 return MODRM_SPLITMISC
;
387 /// stringForDecisionType - Returns a statically-allocated string corresponding
388 /// to a particular decision type.
390 /// @param dt - The decision type.
391 /// @return - A pointer to the statically-allocated string (e.g.,
392 /// "MODRM_ONEENTRY" for MODRM_ONEENTRY).
393 static const char* stringForDecisionType(ModRMDecisionType dt
) {
394 #define ENUM_ENTRY(n) case n: return #n;
397 llvm_unreachable("Unknown decision type");
403 DisassemblerTables::DisassemblerTables() {
406 for (i
= 0; i
< array_lengthof(Tables
); i
++) {
407 Tables
[i
] = new ContextDecision
;
408 memset(Tables
[i
], 0, sizeof(ContextDecision
));
411 HasConflicts
= false;
414 DisassemblerTables::~DisassemblerTables() {
417 for (i
= 0; i
< array_lengthof(Tables
); i
++)
421 void DisassemblerTables::emitModRMDecision(raw_ostream
&o1
, raw_ostream
&o2
,
422 unsigned &i1
, unsigned &i2
,
423 unsigned &ModRMTableNum
,
424 ModRMDecision
&decision
) const {
425 static uint32_t sTableNumber
= 0;
426 static uint32_t sEntryNumber
= 1;
427 ModRMDecisionType dt
= getDecisionType(decision
);
429 if (dt
== MODRM_ONEENTRY
&& decision
.instructionIDs
[0] == 0)
431 o2
.indent(i2
) << "{ /* ModRMDecision */" << "\n";
434 o2
.indent(i2
) << stringForDecisionType(dt
) << "," << "\n";
435 o2
.indent(i2
) << 0 << " /* EmptyTable */\n";
438 o2
.indent(i2
) << "}";
442 std::vector
<unsigned> ModRMDecision
;
446 llvm_unreachable("Unknown decision type");
448 ModRMDecision
.push_back(decision
.instructionIDs
[0]);
451 ModRMDecision
.push_back(decision
.instructionIDs
[0x00]);
452 ModRMDecision
.push_back(decision
.instructionIDs
[0xc0]);
455 for (unsigned index
= 0; index
< 64; index
+= 8)
456 ModRMDecision
.push_back(decision
.instructionIDs
[index
]);
457 for (unsigned index
= 0xc0; index
< 256; index
+= 8)
458 ModRMDecision
.push_back(decision
.instructionIDs
[index
]);
460 case MODRM_SPLITMISC
:
461 for (unsigned index
= 0; index
< 64; index
+= 8)
462 ModRMDecision
.push_back(decision
.instructionIDs
[index
]);
463 for (unsigned index
= 0xc0; index
< 256; ++index
)
464 ModRMDecision
.push_back(decision
.instructionIDs
[index
]);
467 for (unsigned index
= 0; index
< 256; ++index
)
468 ModRMDecision
.push_back(decision
.instructionIDs
[index
]);
472 unsigned &EntryNumber
= ModRMTable
[ModRMDecision
];
473 if (EntryNumber
== 0) {
474 EntryNumber
= ModRMTableNum
;
476 ModRMTableNum
+= ModRMDecision
.size();
477 o1
<< "/* Table" << EntryNumber
<< " */\n";
479 for (std::vector
<unsigned>::const_iterator I
= ModRMDecision
.begin(),
480 E
= ModRMDecision
.end(); I
!= E
; ++I
) {
481 o1
.indent(i1
* 2) << format("0x%hx", *I
) << ", /* "
482 << InstructionSpecifiers
[*I
].name
<< " */\n";
487 o2
.indent(i2
) << "{ /* struct ModRMDecision */" << "\n";
490 o2
.indent(i2
) << stringForDecisionType(dt
) << "," << "\n";
491 o2
.indent(i2
) << EntryNumber
<< " /* Table" << EntryNumber
<< " */\n";
494 o2
.indent(i2
) << "}";
498 llvm_unreachable("Unknown decision type");
508 case MODRM_SPLITMISC
:
509 sEntryNumber
+= 8 + 64;
516 // We assume that the index can fit into uint16_t.
517 assert(sEntryNumber
< 65536U &&
518 "Index into ModRMDecision is too large for uint16_t!");
523 void DisassemblerTables::emitOpcodeDecision(raw_ostream
&o1
, raw_ostream
&o2
,
524 unsigned &i1
, unsigned &i2
,
525 unsigned &ModRMTableNum
,
526 OpcodeDecision
&decision
) const {
527 o2
.indent(i2
) << "{ /* struct OpcodeDecision */" << "\n";
529 o2
.indent(i2
) << "{" << "\n";
532 for (unsigned index
= 0; index
< 256; ++index
) {
535 o2
<< "/* 0x" << format("%02hhx", index
) << " */" << "\n";
537 emitModRMDecision(o1
, o2
, i1
, i2
, ModRMTableNum
,
538 decision
.modRMDecisions
[index
]);
547 o2
.indent(i2
) << "}" << "\n";
549 o2
.indent(i2
) << "}" << "\n";
552 void DisassemblerTables::emitContextDecision(raw_ostream
&o1
, raw_ostream
&o2
,
553 unsigned &i1
, unsigned &i2
,
554 unsigned &ModRMTableNum
,
555 ContextDecision
&decision
,
556 const char* name
) const {
557 o2
.indent(i2
) << "static const struct ContextDecision " << name
<< " = {\n";
559 o2
.indent(i2
) << "{ /* opcodeDecisions */" << "\n";
562 for (unsigned index
= 0; index
< IC_max
; ++index
) {
563 o2
.indent(i2
) << "/* ";
564 o2
<< stringForContext((InstructionContext
)index
);
568 emitOpcodeDecision(o1
, o2
, i1
, i2
, ModRMTableNum
,
569 decision
.opcodeDecisions
[index
]);
571 if (index
+ 1 < IC_max
)
576 o2
.indent(i2
) << "}" << "\n";
578 o2
.indent(i2
) << "};" << "\n";
581 void DisassemblerTables::emitInstructionInfo(raw_ostream
&o
,
583 unsigned NumInstructions
= InstructionSpecifiers
.size();
585 o
<< "static const struct OperandSpecifier x86OperandSets[]["
586 << X86_MAX_OPERANDS
<< "] = {\n";
588 typedef std::vector
<std::pair
<const char *, const char *> > OperandListTy
;
589 std::map
<OperandListTy
, unsigned> OperandSets
;
591 unsigned OperandSetNum
= 0;
592 for (unsigned Index
= 0; Index
< NumInstructions
; ++Index
) {
593 OperandListTy OperandList
;
595 for (unsigned OperandIndex
= 0; OperandIndex
< X86_MAX_OPERANDS
;
597 const char *Encoding
=
598 stringForOperandEncoding((OperandEncoding
)InstructionSpecifiers
[Index
]
599 .operands
[OperandIndex
].encoding
);
601 stringForOperandType((OperandType
)InstructionSpecifiers
[Index
]
602 .operands
[OperandIndex
].type
);
603 OperandList
.push_back(std::make_pair(Encoding
, Type
));
605 unsigned &N
= OperandSets
[OperandList
];
606 if (N
!= 0) continue;
610 o
<< " { /* " << (OperandSetNum
- 1) << " */\n";
611 for (unsigned i
= 0, e
= OperandList
.size(); i
!= e
; ++i
) {
612 o
<< " { " << OperandList
[i
].first
<< ", "
613 << OperandList
[i
].second
<< " },\n";
619 o
.indent(i
* 2) << "static const struct InstructionSpecifier ";
620 o
<< INSTRUCTIONS_STR
"[" << InstructionSpecifiers
.size() << "] = {\n";
624 for (unsigned index
= 0; index
< NumInstructions
; ++index
) {
625 o
.indent(i
* 2) << "{ /* " << index
<< " */" << "\n";
628 OperandListTy OperandList
;
629 for (unsigned OperandIndex
= 0; OperandIndex
< X86_MAX_OPERANDS
;
631 const char *Encoding
=
632 stringForOperandEncoding((OperandEncoding
)InstructionSpecifiers
[index
]
633 .operands
[OperandIndex
].encoding
);
635 stringForOperandType((OperandType
)InstructionSpecifiers
[index
]
636 .operands
[OperandIndex
].type
);
637 OperandList
.push_back(std::make_pair(Encoding
, Type
));
639 o
.indent(i
* 2) << (OperandSets
[OperandList
] - 1) << ",\n";
641 o
.indent(i
* 2) << "/* " << InstructionSpecifiers
[index
].name
<< " */";
645 o
.indent(i
* 2) << "}";
647 if (index
+ 1 < NumInstructions
)
654 o
.indent(i
* 2) << "};" << "\n";
657 void DisassemblerTables::emitContextTable(raw_ostream
&o
, unsigned &i
) const {
658 const unsigned int tableSize
= 16384;
659 o
.indent(i
* 2) << "static const uint8_t " CONTEXTS_STR
660 "[" << tableSize
<< "] = {\n";
663 for (unsigned index
= 0; index
< tableSize
; ++index
) {
666 if (index
& ATTR_EVEX
) {
668 if (index
& ATTR_EVEXL2
)
670 else if (index
& ATTR_EVEXL
)
672 if (index
& ATTR_REXW
)
674 if (index
& ATTR_OPSIZE
)
676 else if (index
& ATTR_XD
)
678 else if (index
& ATTR_XS
)
680 if (index
& ATTR_EVEXKZ
)
682 else if (index
& ATTR_EVEXK
)
684 if (index
& ATTR_EVEXB
)
687 else if ((index
& ATTR_VEXL
) && (index
& ATTR_REXW
) && (index
& ATTR_OPSIZE
))
688 o
<< "IC_VEX_L_W_OPSIZE";
689 else if ((index
& ATTR_VEXL
) && (index
& ATTR_REXW
) && (index
& ATTR_XD
))
690 o
<< "IC_VEX_L_W_XD";
691 else if ((index
& ATTR_VEXL
) && (index
& ATTR_REXW
) && (index
& ATTR_XS
))
692 o
<< "IC_VEX_L_W_XS";
693 else if ((index
& ATTR_VEXL
) && (index
& ATTR_REXW
))
695 else if ((index
& ATTR_VEXL
) && (index
& ATTR_OPSIZE
))
696 o
<< "IC_VEX_L_OPSIZE";
697 else if ((index
& ATTR_VEXL
) && (index
& ATTR_XD
))
699 else if ((index
& ATTR_VEXL
) && (index
& ATTR_XS
))
701 else if ((index
& ATTR_VEX
) && (index
& ATTR_REXW
) && (index
& ATTR_OPSIZE
))
702 o
<< "IC_VEX_W_OPSIZE";
703 else if ((index
& ATTR_VEX
) && (index
& ATTR_REXW
) && (index
& ATTR_XD
))
705 else if ((index
& ATTR_VEX
) && (index
& ATTR_REXW
) && (index
& ATTR_XS
))
707 else if (index
& ATTR_VEXL
)
709 else if ((index
& ATTR_VEX
) && (index
& ATTR_REXW
))
711 else if ((index
& ATTR_VEX
) && (index
& ATTR_OPSIZE
))
712 o
<< "IC_VEX_OPSIZE";
713 else if ((index
& ATTR_VEX
) && (index
& ATTR_XD
))
715 else if ((index
& ATTR_VEX
) && (index
& ATTR_XS
))
717 else if (index
& ATTR_VEX
)
719 else if ((index
& ATTR_64BIT
) && (index
& ATTR_REXW
) && (index
& ATTR_XS
))
720 o
<< "IC_64BIT_REXW_XS";
721 else if ((index
& ATTR_64BIT
) && (index
& ATTR_REXW
) && (index
& ATTR_XD
))
722 o
<< "IC_64BIT_REXW_XD";
723 else if ((index
& ATTR_64BIT
) && (index
& ATTR_REXW
) &&
724 (index
& ATTR_OPSIZE
))
725 o
<< "IC_64BIT_REXW_OPSIZE";
726 else if ((index
& ATTR_64BIT
) && (index
& ATTR_REXW
) &&
727 (index
& ATTR_ADSIZE
))
728 o
<< "IC_64BIT_REXW_ADSIZE";
729 else if ((index
& ATTR_64BIT
) && (index
& ATTR_XD
) && (index
& ATTR_OPSIZE
))
730 o
<< "IC_64BIT_XD_OPSIZE";
731 else if ((index
& ATTR_64BIT
) && (index
& ATTR_XS
) && (index
& ATTR_OPSIZE
))
732 o
<< "IC_64BIT_XS_OPSIZE";
733 else if ((index
& ATTR_64BIT
) && (index
& ATTR_XS
))
735 else if ((index
& ATTR_64BIT
) && (index
& ATTR_XD
))
737 else if ((index
& ATTR_64BIT
) && (index
& ATTR_OPSIZE
) &&
738 (index
& ATTR_ADSIZE
))
739 o
<< "IC_64BIT_OPSIZE_ADSIZE";
740 else if ((index
& ATTR_64BIT
) && (index
& ATTR_OPSIZE
))
741 o
<< "IC_64BIT_OPSIZE";
742 else if ((index
& ATTR_64BIT
) && (index
& ATTR_ADSIZE
))
743 o
<< "IC_64BIT_ADSIZE";
744 else if ((index
& ATTR_64BIT
) && (index
& ATTR_REXW
))
745 o
<< "IC_64BIT_REXW";
746 else if ((index
& ATTR_64BIT
))
748 else if ((index
& ATTR_XS
) && (index
& ATTR_OPSIZE
))
750 else if ((index
& ATTR_XD
) && (index
& ATTR_OPSIZE
))
752 else if (index
& ATTR_XS
)
754 else if (index
& ATTR_XD
)
756 else if ((index
& ATTR_OPSIZE
) && (index
& ATTR_ADSIZE
))
757 o
<< "IC_OPSIZE_ADSIZE";
758 else if (index
& ATTR_OPSIZE
)
760 else if (index
& ATTR_ADSIZE
)
765 if (index
< tableSize
- 1)
770 o
<< " /* " << index
<< " */";
776 o
.indent(i
* 2) << "};" << "\n";
779 void DisassemblerTables::emitContextDecisions(raw_ostream
&o1
, raw_ostream
&o2
,
780 unsigned &i1
, unsigned &i2
,
781 unsigned &ModRMTableNum
) const {
782 emitContextDecision(o1
, o2
, i1
, i2
, ModRMTableNum
, *Tables
[0], ONEBYTE_STR
);
783 emitContextDecision(o1
, o2
, i1
, i2
, ModRMTableNum
, *Tables
[1], TWOBYTE_STR
);
784 emitContextDecision(o1
, o2
, i1
, i2
, ModRMTableNum
, *Tables
[2], THREEBYTE38_STR
);
785 emitContextDecision(o1
, o2
, i1
, i2
, ModRMTableNum
, *Tables
[3], THREEBYTE3A_STR
);
786 emitContextDecision(o1
, o2
, i1
, i2
, ModRMTableNum
, *Tables
[4], XOP8_MAP_STR
);
787 emitContextDecision(o1
, o2
, i1
, i2
, ModRMTableNum
, *Tables
[5], XOP9_MAP_STR
);
788 emitContextDecision(o1
, o2
, i1
, i2
, ModRMTableNum
, *Tables
[6], XOPA_MAP_STR
);
791 void DisassemblerTables::emit(raw_ostream
&o
) const {
798 raw_string_ostream
o1(s1
);
799 raw_string_ostream
o2(s2
);
801 emitInstructionInfo(o
, i2
);
804 emitContextTable(o
, i2
);
807 unsigned ModRMTableNum
= 0;
809 o
<< "static const InstrUID modRMTable[] = {\n";
811 std::vector
<unsigned> EmptyTable(1, 0);
812 ModRMTable
[EmptyTable
] = ModRMTableNum
;
813 ModRMTableNum
+= EmptyTable
.size();
814 o1
<< "/* EmptyTable */\n";
815 o1
.indent(i1
* 2) << "0x0,\n";
817 emitContextDecisions(o1
, o2
, i1
, i2
, ModRMTableNum
);
828 void DisassemblerTables::setTableFields(ModRMDecision
&decision
,
829 const ModRMFilter
&filter
,
832 for (unsigned index
= 0; index
< 256; ++index
) {
833 if (filter
.accepts(index
)) {
834 if (decision
.instructionIDs
[index
] == uid
)
837 if (decision
.instructionIDs
[index
] != 0) {
838 InstructionSpecifier
&newInfo
=
839 InstructionSpecifiers
[uid
];
840 InstructionSpecifier
&previousInfo
=
841 InstructionSpecifiers
[decision
.instructionIDs
[index
]];
843 if(previousInfo
.name
== "NOOP" && (newInfo
.name
== "XCHG16ar" ||
844 newInfo
.name
== "XCHG32ar" ||
845 newInfo
.name
== "XCHG32ar64" ||
846 newInfo
.name
== "XCHG64ar"))
847 continue; // special case for XCHG*ar and NOOP
849 if (outranks(previousInfo
.insnContext
, newInfo
.insnContext
))
852 if (previousInfo
.insnContext
== newInfo
.insnContext
) {
853 errs() << "Error: Primary decode conflict: ";
854 errs() << newInfo
.name
<< " would overwrite " << previousInfo
.name
;
856 errs() << "ModRM " << index
<< "\n";
857 errs() << "Opcode " << (uint16_t)opcode
<< "\n";
858 errs() << "Context " << stringForContext(newInfo
.insnContext
) << "\n";
863 decision
.instructionIDs
[index
] = uid
;
868 void DisassemblerTables::setTableFields(OpcodeType type
,
869 InstructionContext insnContext
,
871 const ModRMFilter
&filter
,
875 unsigned addressSize
) {
876 ContextDecision
&decision
= *Tables
[type
];
878 for (unsigned index
= 0; index
< IC_max
; ++index
) {
879 if ((is32bit
|| addressSize
== 16) &&
880 inheritsFrom((InstructionContext
)index
, IC_64BIT
))
883 bool adSize64
= addressSize
== 64;
884 if (inheritsFrom((InstructionContext
)index
,
885 InstructionSpecifiers
[uid
].insnContext
, ignoresVEX_L
,
887 setTableFields(decision
.opcodeDecisions
[index
].modRMDecisions
[opcode
],