blob: 0ccfac7855e9555e090d02e93665fa7dd2699156 [file] [log] [blame]
Sean Callanan04cc3072009-12-19 02:59:52 +00001//===- 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
Sean Callanan04cc3072009-12-19 02:59:52 +000017#include "X86DisassemblerTables.h"
Chandler Carruth91d19d82012-12-04 10:37:14 +000018#include "X86DisassemblerShared.h"
Joerg Sonnenbergerc94780c2011-04-04 16:25:38 +000019#include "llvm/ADT/STLExtras.h"
Sean Callanan04cc3072009-12-19 02:59:52 +000020#include "llvm/Support/ErrorHandling.h"
21#include "llvm/Support/Format.h"
Chandler Carruth91d19d82012-12-04 10:37:14 +000022#include "llvm/TableGen/TableGenBackend.h"
Craig Topperb8aec082012-08-01 07:39:18 +000023#include <map>
Sean Callanan04cc3072009-12-19 02:59:52 +000024
Sean Callanan04cc3072009-12-19 02:59:52 +000025using namespace llvm;
26using namespace X86Disassembler;
Craig Topper0c4253f2012-07-31 05:27:01 +000027
Elena Demikhovskyde3f7512014-01-01 15:12:34 +000028/// stringForContext - Returns a string containing the name of a particular
29/// InstructionContext, usually for diagnostic purposes.
30///
31/// @param insnContext - The instruction class to transform to a string.
32/// @return - A statically-allocated string constant that contains the
33/// name of the instruction class.
34static inline const char* stringForContext(InstructionContext insnContext) {
35 switch (insnContext) {
36 default:
37 llvm_unreachable("Unhandled instruction class");
38#define ENUM_ENTRY(n, r, d) case n: return #n; break;
39#define ENUM_ENTRY_K_B(n, r, d) ENUM_ENTRY(n, r, d) ENUM_ENTRY(n##_K_B, r, d)\
40 ENUM_ENTRY(n##_KZ, r, d) ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d)\
41 ENUM_ENTRY(n##_KZ_B, r, d)
42 INSTRUCTION_CONTEXTS
43#undef ENUM_ENTRY
44#undef ENUM_ENTRY_K_B
45 }
46}
47
48/// stringForOperandType - Like stringForContext, but for OperandTypes.
49static inline const char* stringForOperandType(OperandType type) {
50 switch (type) {
51 default:
52 llvm_unreachable("Unhandled type");
53#define ENUM_ENTRY(i, d) case i: return #i;
54 TYPES
55#undef ENUM_ENTRY
56 }
57}
58
59/// stringForOperandEncoding - like stringForContext, but for
60/// OperandEncodings.
61static inline const char* stringForOperandEncoding(OperandEncoding encoding) {
62 switch (encoding) {
63 default:
64 llvm_unreachable("Unhandled encoding");
65#define ENUM_ENTRY(i, d) case i: return #i;
66 ENCODINGS
67#undef ENUM_ENTRY
68 }
69}
70
Sean Callanan04cc3072009-12-19 02:59:52 +000071/// inheritsFrom - Indicates whether all instructions in one class also belong
72/// to another class.
73///
74/// @param child - The class that may be the subset
75/// @param parent - The class that may be the superset
76/// @return - True if child is a subset of parent, false otherwise.
77static inline bool inheritsFrom(InstructionContext child,
Craig Topperf18c8962011-10-04 06:30:42 +000078 InstructionContext parent,
79 bool VEX_LIG = false) {
Sean Callanan04cc3072009-12-19 02:59:52 +000080 if (child == parent)
81 return true;
Craig Topper0c4253f2012-07-31 05:27:01 +000082
Sean Callanan04cc3072009-12-19 02:59:52 +000083 switch (parent) {
84 case IC:
Craig Topper94ce5352011-09-02 04:17:54 +000085 return(inheritsFrom(child, IC_64BIT) ||
86 inheritsFrom(child, IC_OPSIZE) ||
Craig Topper6491c802012-02-27 01:54:29 +000087 inheritsFrom(child, IC_ADSIZE) ||
Craig Topper94ce5352011-09-02 04:17:54 +000088 inheritsFrom(child, IC_XD) ||
89 inheritsFrom(child, IC_XS));
Sean Callanan04cc3072009-12-19 02:59:52 +000090 case IC_64BIT:
91 return(inheritsFrom(child, IC_64BIT_REXW) ||
92 inheritsFrom(child, IC_64BIT_OPSIZE) ||
Craig Topper6491c802012-02-27 01:54:29 +000093 inheritsFrom(child, IC_64BIT_ADSIZE) ||
Sean Callanan04cc3072009-12-19 02:59:52 +000094 inheritsFrom(child, IC_64BIT_XD) ||
95 inheritsFrom(child, IC_64BIT_XS));
96 case IC_OPSIZE:
David Woodhouse32da3c82014-01-08 12:58:24 +000097 return (inheritsFrom(child, IC_64BIT_OPSIZE) ||
98 inheritsFrom(child, IC_OPSIZE_ADSIZE));
Craig Topper6491c802012-02-27 01:54:29 +000099 case IC_ADSIZE:
David Woodhouse32da3c82014-01-08 12:58:24 +0000100 return inheritsFrom(child, IC_OPSIZE_ADSIZE);
101 case IC_OPSIZE_ADSIZE:
Craig Topper6491c802012-02-27 01:54:29 +0000102 case IC_64BIT_ADSIZE:
103 return false;
Sean Callanan04cc3072009-12-19 02:59:52 +0000104 case IC_XD:
Craig Topper94ce5352011-09-02 04:17:54 +0000105 return inheritsFrom(child, IC_64BIT_XD);
Sean Callanan04cc3072009-12-19 02:59:52 +0000106 case IC_XS:
Craig Topper94ce5352011-09-02 04:17:54 +0000107 return inheritsFrom(child, IC_64BIT_XS);
Craig Topper88cb33e2011-10-01 19:54:56 +0000108 case IC_XD_OPSIZE:
109 return inheritsFrom(child, IC_64BIT_XD_OPSIZE);
Craig Toppera6978522011-10-11 04:34:23 +0000110 case IC_XS_OPSIZE:
111 return inheritsFrom(child, IC_64BIT_XS_OPSIZE);
Sean Callanan04cc3072009-12-19 02:59:52 +0000112 case IC_64BIT_REXW:
113 return(inheritsFrom(child, IC_64BIT_REXW_XS) ||
114 inheritsFrom(child, IC_64BIT_REXW_XD) ||
115 inheritsFrom(child, IC_64BIT_REXW_OPSIZE));
116 case IC_64BIT_OPSIZE:
117 return(inheritsFrom(child, IC_64BIT_REXW_OPSIZE));
118 case IC_64BIT_XD:
119 return(inheritsFrom(child, IC_64BIT_REXW_XD));
120 case IC_64BIT_XS:
121 return(inheritsFrom(child, IC_64BIT_REXW_XS));
Craig Topper88cb33e2011-10-01 19:54:56 +0000122 case IC_64BIT_XD_OPSIZE:
Craig Toppera6978522011-10-11 04:34:23 +0000123 case IC_64BIT_XS_OPSIZE:
Craig Topper88cb33e2011-10-01 19:54:56 +0000124 return false;
Sean Callanan04cc3072009-12-19 02:59:52 +0000125 case IC_64BIT_REXW_XD:
Sean Callanan04cc3072009-12-19 02:59:52 +0000126 case IC_64BIT_REXW_XS:
Sean Callanan04cc3072009-12-19 02:59:52 +0000127 case IC_64BIT_REXW_OPSIZE:
128 return false;
Sean Callananc3fd5232011-03-15 01:23:15 +0000129 case IC_VEX:
Craig Toppered59dd32013-09-30 02:46:36 +0000130 return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W)) ||
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000131 inheritsFrom(child, IC_VEX_W) ||
Craig Topperf18c8962011-10-04 06:30:42 +0000132 (VEX_LIG && inheritsFrom(child, IC_VEX_L));
Sean Callananc3fd5232011-03-15 01:23:15 +0000133 case IC_VEX_XS:
Craig Toppered59dd32013-09-30 02:46:36 +0000134 return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XS)) ||
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000135 inheritsFrom(child, IC_VEX_W_XS) ||
Craig Topperf18c8962011-10-04 06:30:42 +0000136 (VEX_LIG && inheritsFrom(child, IC_VEX_L_XS));
Sean Callananc3fd5232011-03-15 01:23:15 +0000137 case IC_VEX_XD:
Craig Toppered59dd32013-09-30 02:46:36 +0000138 return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XD)) ||
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000139 inheritsFrom(child, IC_VEX_W_XD) ||
Craig Topperf18c8962011-10-04 06:30:42 +0000140 (VEX_LIG && inheritsFrom(child, IC_VEX_L_XD));
Craig Topper94ce5352011-09-02 04:17:54 +0000141 case IC_VEX_OPSIZE:
Craig Toppered59dd32013-09-30 02:46:36 +0000142 return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W_OPSIZE)) ||
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000143 inheritsFrom(child, IC_VEX_W_OPSIZE) ||
Craig Topperf18c8962011-10-04 06:30:42 +0000144 (VEX_LIG && inheritsFrom(child, IC_VEX_L_OPSIZE));
Sean Callananc3fd5232011-03-15 01:23:15 +0000145 case IC_VEX_W:
Craig Toppered59dd32013-09-30 02:46:36 +0000146 return VEX_LIG && inheritsFrom(child, IC_VEX_L_W);
Sean Callananc3fd5232011-03-15 01:23:15 +0000147 case IC_VEX_W_XS:
Craig Toppered59dd32013-09-30 02:46:36 +0000148 return VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XS);
Sean Callananc3fd5232011-03-15 01:23:15 +0000149 case IC_VEX_W_XD:
Craig Toppered59dd32013-09-30 02:46:36 +0000150 return VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XD);
Craig Topper94ce5352011-09-02 04:17:54 +0000151 case IC_VEX_W_OPSIZE:
Craig Toppered59dd32013-09-30 02:46:36 +0000152 return VEX_LIG && inheritsFrom(child, IC_VEX_L_W_OPSIZE);
Craig Topper94ce5352011-09-02 04:17:54 +0000153 case IC_VEX_L:
Craig Toppered59dd32013-09-30 02:46:36 +0000154 return inheritsFrom(child, IC_VEX_L_W);
Craig Topper94ce5352011-09-02 04:17:54 +0000155 case IC_VEX_L_XS:
Craig Toppered59dd32013-09-30 02:46:36 +0000156 return inheritsFrom(child, IC_VEX_L_W_XS);
Craig Topper94ce5352011-09-02 04:17:54 +0000157 case IC_VEX_L_XD:
Craig Toppered59dd32013-09-30 02:46:36 +0000158 return inheritsFrom(child, IC_VEX_L_W_XD);
Craig Topper94ce5352011-09-02 04:17:54 +0000159 case IC_VEX_L_OPSIZE:
Craig Toppered59dd32013-09-30 02:46:36 +0000160 return inheritsFrom(child, IC_VEX_L_W_OPSIZE);
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000161 case IC_VEX_L_W:
162 case IC_VEX_L_W_XS:
163 case IC_VEX_L_W_XD:
Craig Topperf01f1b52011-11-06 23:04:08 +0000164 case IC_VEX_L_W_OPSIZE:
Craig Topper94ce5352011-09-02 04:17:54 +0000165 return false;
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000166 case IC_EVEX:
167 return inheritsFrom(child, IC_EVEX_W) ||
168 inheritsFrom(child, IC_EVEX_L_W);
169 case IC_EVEX_XS:
170 return inheritsFrom(child, IC_EVEX_W_XS) ||
171 inheritsFrom(child, IC_EVEX_L_W_XS);
172 case IC_EVEX_XD:
173 return inheritsFrom(child, IC_EVEX_W_XD) ||
174 inheritsFrom(child, IC_EVEX_L_W_XD);
175 case IC_EVEX_OPSIZE:
176 return inheritsFrom(child, IC_EVEX_W_OPSIZE) ||
Elena Demikhovskydacddb02013-11-03 13:46:31 +0000177 inheritsFrom(child, IC_EVEX_L_W_OPSIZE);
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000178 case IC_EVEX_W:
179 case IC_EVEX_W_XS:
180 case IC_EVEX_W_XD:
181 case IC_EVEX_W_OPSIZE:
182 return false;
183 case IC_EVEX_L:
184 case IC_EVEX_L_XS:
185 case IC_EVEX_L_XD:
186 case IC_EVEX_L_OPSIZE:
187 return false;
188 case IC_EVEX_L_W:
189 case IC_EVEX_L_W_XS:
190 case IC_EVEX_L_W_XD:
191 case IC_EVEX_L_W_OPSIZE:
192 return false;
193 case IC_EVEX_L2:
194 case IC_EVEX_L2_XS:
195 case IC_EVEX_L2_XD:
196 case IC_EVEX_L2_OPSIZE:
197 return false;
198 case IC_EVEX_L2_W:
199 case IC_EVEX_L2_W_XS:
200 case IC_EVEX_L2_W_XD:
201 case IC_EVEX_L2_W_OPSIZE:
202 return false;
203 case IC_EVEX_K:
204 return inheritsFrom(child, IC_EVEX_W_K) ||
205 inheritsFrom(child, IC_EVEX_L_W_K);
206 case IC_EVEX_XS_K:
207 return inheritsFrom(child, IC_EVEX_W_XS_K) ||
208 inheritsFrom(child, IC_EVEX_L_W_XS_K);
209 case IC_EVEX_XD_K:
210 return inheritsFrom(child, IC_EVEX_W_XD_K) ||
211 inheritsFrom(child, IC_EVEX_L_W_XD_K);
212 case IC_EVEX_OPSIZE_K:
Elena Demikhovskyb19c9dc2014-01-13 12:55:03 +0000213 case IC_EVEX_OPSIZE_B:
214 return false;
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000215 case IC_EVEX_W_K:
216 case IC_EVEX_W_XS_K:
217 case IC_EVEX_W_XD_K:
218 case IC_EVEX_W_OPSIZE_K:
Elena Demikhovskyb19c9dc2014-01-13 12:55:03 +0000219 case IC_EVEX_W_OPSIZE_B:
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000220 return false;
221 case IC_EVEX_L_K:
222 case IC_EVEX_L_XS_K:
223 case IC_EVEX_L_XD_K:
224 case IC_EVEX_L_OPSIZE_K:
225 return false;
Elena Demikhovskydacddb02013-11-03 13:46:31 +0000226 case IC_EVEX_W_KZ:
227 case IC_EVEX_W_XS_KZ:
228 case IC_EVEX_W_XD_KZ:
229 case IC_EVEX_W_OPSIZE_KZ:
230 return false;
231 case IC_EVEX_L_KZ:
232 case IC_EVEX_L_XS_KZ:
233 case IC_EVEX_L_XD_KZ:
234 case IC_EVEX_L_OPSIZE_KZ:
235 return false;
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000236 case IC_EVEX_L_W_K:
237 case IC_EVEX_L_W_XS_K:
238 case IC_EVEX_L_W_XD_K:
239 case IC_EVEX_L_W_OPSIZE_K:
Elena Demikhovskydacddb02013-11-03 13:46:31 +0000240 case IC_EVEX_L_W_KZ:
241 case IC_EVEX_L_W_XS_KZ:
242 case IC_EVEX_L_W_XD_KZ:
243 case IC_EVEX_L_W_OPSIZE_KZ:
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000244 return false;
245 case IC_EVEX_L2_K:
246 case IC_EVEX_L2_B:
247 case IC_EVEX_L2_XS_K:
Elena Demikhovskyde3f7512014-01-01 15:12:34 +0000248 case IC_EVEX_L2_XS_B:
249 case IC_EVEX_L2_XD_B:
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000250 case IC_EVEX_L2_XD_K:
251 case IC_EVEX_L2_OPSIZE_K:
252 case IC_EVEX_L2_OPSIZE_B:
Elena Demikhovskydacddb02013-11-03 13:46:31 +0000253 case IC_EVEX_L2_OPSIZE_K_B:
254 case IC_EVEX_L2_KZ:
255 case IC_EVEX_L2_XS_KZ:
256 case IC_EVEX_L2_XD_KZ:
257 case IC_EVEX_L2_OPSIZE_KZ:
258 case IC_EVEX_L2_OPSIZE_KZ_B:
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000259 return false;
260 case IC_EVEX_L2_W_K:
Elena Demikhovskydacddb02013-11-03 13:46:31 +0000261 case IC_EVEX_L2_W_B:
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000262 case IC_EVEX_L2_W_XS_K:
263 case IC_EVEX_L2_W_XD_K:
Elena Demikhovskyde3f7512014-01-01 15:12:34 +0000264 case IC_EVEX_L2_W_XD_B:
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000265 case IC_EVEX_L2_W_OPSIZE_K:
266 case IC_EVEX_L2_W_OPSIZE_B:
Elena Demikhovskydacddb02013-11-03 13:46:31 +0000267 case IC_EVEX_L2_W_OPSIZE_K_B:
268 case IC_EVEX_L2_W_KZ:
269 case IC_EVEX_L2_W_XS_KZ:
270 case IC_EVEX_L2_W_XD_KZ:
271 case IC_EVEX_L2_W_OPSIZE_KZ:
272 case IC_EVEX_L2_W_OPSIZE_KZ_B:
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000273 return false;
Sean Callanan04cc3072009-12-19 02:59:52 +0000274 default:
Elena Demikhovskyde3f7512014-01-01 15:12:34 +0000275 errs() << "Unknown instruction class: " <<
276 stringForContext((InstructionContext)parent) << "\n";
Craig Topper94ce5352011-09-02 04:17:54 +0000277 llvm_unreachable("Unknown instruction class");
Sean Callanan04cc3072009-12-19 02:59:52 +0000278 }
279}
280
281/// outranks - Indicates whether, if an instruction has two different applicable
282/// classes, which class should be preferred when performing decode. This
283/// imposes a total ordering (ties are resolved toward "lower")
284///
285/// @param upper - The class that may be preferable
286/// @param lower - The class that may be less preferable
287/// @return - True if upper is to be preferred, false otherwise.
Craig Topper0c4253f2012-07-31 05:27:01 +0000288static inline bool outranks(InstructionContext upper,
Sean Callanan04cc3072009-12-19 02:59:52 +0000289 InstructionContext lower) {
290 assert(upper < IC_max);
291 assert(lower < IC_max);
Craig Topper0c4253f2012-07-31 05:27:01 +0000292
Sean Callanan04cc3072009-12-19 02:59:52 +0000293#define ENUM_ENTRY(n, r, d) r,
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000294#define ENUM_ENTRY_K_B(n, r, d) ENUM_ENTRY(n, r, d) \
Elena Demikhovskydacddb02013-11-03 13:46:31 +0000295 ENUM_ENTRY(n##_K_B, r, d) ENUM_ENTRY(n##_KZ_B, r, d) \
296 ENUM_ENTRY(n##_KZ, r, d) ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d)
Sean Callanan04cc3072009-12-19 02:59:52 +0000297 static int ranks[IC_max] = {
298 INSTRUCTION_CONTEXTS
299 };
300#undef ENUM_ENTRY
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000301#undef ENUM_ENTRY_K_B
Craig Topper0c4253f2012-07-31 05:27:01 +0000302
Sean Callanan04cc3072009-12-19 02:59:52 +0000303 return (ranks[upper] > ranks[lower]);
304}
305
Sean Callanan04cc3072009-12-19 02:59:52 +0000306/// getDecisionType - Determines whether a ModRM decision with 255 entries can
307/// be compacted by eliminating redundant information.
308///
309/// @param decision - The decision to be compacted.
310/// @return - The compactest available representation for the decision.
Craig Topperb61024c2012-07-31 05:42:02 +0000311static ModRMDecisionType getDecisionType(ModRMDecision &decision) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000312 bool satisfiesOneEntry = true;
313 bool satisfiesSplitRM = true;
Craig Toppera0cd9702012-02-09 08:58:07 +0000314 bool satisfiesSplitReg = true;
Craig Topper963305b2012-09-13 05:45:42 +0000315 bool satisfiesSplitMisc = true;
Craig Toppera0cd9702012-02-09 08:58:07 +0000316
Craig Topper6f142742012-07-31 06:02:05 +0000317 for (unsigned index = 0; index < 256; ++index) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000318 if (decision.instructionIDs[index] != decision.instructionIDs[0])
319 satisfiesOneEntry = false;
Craig Toppera0cd9702012-02-09 08:58:07 +0000320
Sean Callanan04cc3072009-12-19 02:59:52 +0000321 if (((index & 0xc0) == 0xc0) &&
322 (decision.instructionIDs[index] != decision.instructionIDs[0xc0]))
323 satisfiesSplitRM = false;
Craig Toppera0cd9702012-02-09 08:58:07 +0000324
Sean Callanan04cc3072009-12-19 02:59:52 +0000325 if (((index & 0xc0) != 0xc0) &&
326 (decision.instructionIDs[index] != decision.instructionIDs[0x00]))
327 satisfiesSplitRM = false;
Craig Toppera0cd9702012-02-09 08:58:07 +0000328
329 if (((index & 0xc0) == 0xc0) &&
330 (decision.instructionIDs[index] != decision.instructionIDs[index&0xf8]))
331 satisfiesSplitReg = false;
332
333 if (((index & 0xc0) != 0xc0) &&
334 (decision.instructionIDs[index] != decision.instructionIDs[index&0x38]))
Craig Topper963305b2012-09-13 05:45:42 +0000335 satisfiesSplitMisc = false;
Sean Callanan04cc3072009-12-19 02:59:52 +0000336 }
Craig Toppera0cd9702012-02-09 08:58:07 +0000337
Sean Callanan04cc3072009-12-19 02:59:52 +0000338 if (satisfiesOneEntry)
339 return MODRM_ONEENTRY;
Craig Toppera0cd9702012-02-09 08:58:07 +0000340
Sean Callanan04cc3072009-12-19 02:59:52 +0000341 if (satisfiesSplitRM)
342 return MODRM_SPLITRM;
Craig Toppera0cd9702012-02-09 08:58:07 +0000343
Craig Topper963305b2012-09-13 05:45:42 +0000344 if (satisfiesSplitReg && satisfiesSplitMisc)
Craig Toppera0cd9702012-02-09 08:58:07 +0000345 return MODRM_SPLITREG;
346
Craig Topper963305b2012-09-13 05:45:42 +0000347 if (satisfiesSplitMisc)
348 return MODRM_SPLITMISC;
349
Sean Callanan04cc3072009-12-19 02:59:52 +0000350 return MODRM_FULL;
351}
352
353/// stringForDecisionType - Returns a statically-allocated string corresponding
354/// to a particular decision type.
355///
356/// @param dt - The decision type.
Craig Topper0c4253f2012-07-31 05:27:01 +0000357/// @return - A pointer to the statically-allocated string (e.g.,
Sean Callanan04cc3072009-12-19 02:59:52 +0000358/// "MODRM_ONEENTRY" for MODRM_ONEENTRY).
Craig Topperb61024c2012-07-31 05:42:02 +0000359static const char* stringForDecisionType(ModRMDecisionType dt) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000360#define ENUM_ENTRY(n) case n: return #n;
361 switch (dt) {
362 default:
Craig Topper0c4253f2012-07-31 05:27:01 +0000363 llvm_unreachable("Unknown decision type");
Sean Callanan04cc3072009-12-19 02:59:52 +0000364 MODRMTYPES
Craig Topper0c4253f2012-07-31 05:27:01 +0000365 };
Sean Callanan04cc3072009-12-19 02:59:52 +0000366#undef ENUM_ENTRY
367}
Craig Topper0c4253f2012-07-31 05:27:01 +0000368
Sean Callanan04cc3072009-12-19 02:59:52 +0000369DisassemblerTables::DisassemblerTables() {
370 unsigned i;
Craig Topper0c4253f2012-07-31 05:27:01 +0000371
Joerg Sonnenbergerc94780c2011-04-04 16:25:38 +0000372 for (i = 0; i < array_lengthof(Tables); i++) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000373 Tables[i] = new ContextDecision;
Daniel Dunbar3a821f72009-12-19 04:16:57 +0000374 memset(Tables[i], 0, sizeof(ContextDecision));
Sean Callanan04cc3072009-12-19 02:59:52 +0000375 }
Craig Topper0c4253f2012-07-31 05:27:01 +0000376
Sean Callanan04cc3072009-12-19 02:59:52 +0000377 HasConflicts = false;
378}
Craig Topper0c4253f2012-07-31 05:27:01 +0000379
Sean Callanan04cc3072009-12-19 02:59:52 +0000380DisassemblerTables::~DisassemblerTables() {
381 unsigned i;
Craig Topper0c4253f2012-07-31 05:27:01 +0000382
Joerg Sonnenbergerc94780c2011-04-04 16:25:38 +0000383 for (i = 0; i < array_lengthof(Tables); i++)
Sean Callanan04cc3072009-12-19 02:59:52 +0000384 delete Tables[i];
385}
Craig Topper0c4253f2012-07-31 05:27:01 +0000386
Craig Topperb61024c2012-07-31 05:42:02 +0000387void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
Craig Topper6f142742012-07-31 06:02:05 +0000388 unsigned &i1, unsigned &i2,
Craig Topper009de602013-09-30 06:23:19 +0000389 unsigned &ModRMTableNum,
Craig Topperb61024c2012-07-31 05:42:02 +0000390 ModRMDecision &decision) const {
Craig Topper6f142742012-07-31 06:02:05 +0000391 static uint32_t sTableNumber = 0;
392 static uint32_t sEntryNumber = 1;
Sean Callanan04cc3072009-12-19 02:59:52 +0000393 ModRMDecisionType dt = getDecisionType(decision);
Craig Topper487e7442012-02-09 07:45:30 +0000394
Sean Callanan04cc3072009-12-19 02:59:52 +0000395 if (dt == MODRM_ONEENTRY && decision.instructionIDs[0] == 0)
396 {
397 o2.indent(i2) << "{ /* ModRMDecision */" << "\n";
398 i2++;
Craig Topper487e7442012-02-09 07:45:30 +0000399
Sean Callanan04cc3072009-12-19 02:59:52 +0000400 o2.indent(i2) << stringForDecisionType(dt) << "," << "\n";
Craig Topper487e7442012-02-09 07:45:30 +0000401 o2.indent(i2) << 0 << " /* EmptyTable */\n";
402
Sean Callanan04cc3072009-12-19 02:59:52 +0000403 i2--;
404 o2.indent(i2) << "}";
405 return;
406 }
Sean Callanan04cc3072009-12-19 02:59:52 +0000407
Craig Topper009de602013-09-30 06:23:19 +0000408 std::vector<unsigned> ModRMDecision;
Craig Topper487e7442012-02-09 07:45:30 +0000409
Sean Callanan04cc3072009-12-19 02:59:52 +0000410 switch (dt) {
411 default:
412 llvm_unreachable("Unknown decision type");
413 case MODRM_ONEENTRY:
Craig Topper009de602013-09-30 06:23:19 +0000414 ModRMDecision.push_back(decision.instructionIDs[0]);
Sean Callanan04cc3072009-12-19 02:59:52 +0000415 break;
416 case MODRM_SPLITRM:
Craig Topper009de602013-09-30 06:23:19 +0000417 ModRMDecision.push_back(decision.instructionIDs[0x00]);
418 ModRMDecision.push_back(decision.instructionIDs[0xc0]);
Sean Callanan04cc3072009-12-19 02:59:52 +0000419 break;
Craig Toppera0cd9702012-02-09 08:58:07 +0000420 case MODRM_SPLITREG:
Craig Topper6f142742012-07-31 06:02:05 +0000421 for (unsigned index = 0; index < 64; index += 8)
Craig Topper009de602013-09-30 06:23:19 +0000422 ModRMDecision.push_back(decision.instructionIDs[index]);
Craig Topper6f142742012-07-31 06:02:05 +0000423 for (unsigned index = 0xc0; index < 256; index += 8)
Craig Topper009de602013-09-30 06:23:19 +0000424 ModRMDecision.push_back(decision.instructionIDs[index]);
Craig Toppera0cd9702012-02-09 08:58:07 +0000425 break;
Craig Topper963305b2012-09-13 05:45:42 +0000426 case MODRM_SPLITMISC:
427 for (unsigned index = 0; index < 64; index += 8)
Craig Topper009de602013-09-30 06:23:19 +0000428 ModRMDecision.push_back(decision.instructionIDs[index]);
Craig Topper963305b2012-09-13 05:45:42 +0000429 for (unsigned index = 0xc0; index < 256; ++index)
Craig Topper009de602013-09-30 06:23:19 +0000430 ModRMDecision.push_back(decision.instructionIDs[index]);
Craig Topper963305b2012-09-13 05:45:42 +0000431 break;
Sean Callanan04cc3072009-12-19 02:59:52 +0000432 case MODRM_FULL:
Craig Topper6f142742012-07-31 06:02:05 +0000433 for (unsigned index = 0; index < 256; ++index)
Craig Topper009de602013-09-30 06:23:19 +0000434 ModRMDecision.push_back(decision.instructionIDs[index]);
Sean Callanan04cc3072009-12-19 02:59:52 +0000435 break;
436 }
Craig Topper487e7442012-02-09 07:45:30 +0000437
Craig Topper009de602013-09-30 06:23:19 +0000438 unsigned &EntryNumber = ModRMTable[ModRMDecision];
439 if (EntryNumber == 0) {
440 EntryNumber = ModRMTableNum;
441
442 ModRMTableNum += ModRMDecision.size();
443 o1 << "/* Table" << EntryNumber << " */\n";
444 i1++;
445 for (std::vector<unsigned>::const_iterator I = ModRMDecision.begin(),
446 E = ModRMDecision.end(); I != E; ++I) {
447 o1.indent(i1 * 2) << format("0x%hx", *I) << ", /* "
448 << InstructionSpecifiers[*I].name << " */\n";
449 }
450 i1--;
451 }
Craig Topper487e7442012-02-09 07:45:30 +0000452
Sean Callanan04cc3072009-12-19 02:59:52 +0000453 o2.indent(i2) << "{ /* struct ModRMDecision */" << "\n";
454 i2++;
Craig Topper487e7442012-02-09 07:45:30 +0000455
Sean Callanan04cc3072009-12-19 02:59:52 +0000456 o2.indent(i2) << stringForDecisionType(dt) << "," << "\n";
Craig Topper009de602013-09-30 06:23:19 +0000457 o2.indent(i2) << EntryNumber << " /* Table" << EntryNumber << " */\n";
Craig Topper487e7442012-02-09 07:45:30 +0000458
Sean Callanan04cc3072009-12-19 02:59:52 +0000459 i2--;
460 o2.indent(i2) << "}";
Craig Topper487e7442012-02-09 07:45:30 +0000461
462 switch (dt) {
463 default:
464 llvm_unreachable("Unknown decision type");
465 case MODRM_ONEENTRY:
466 sEntryNumber += 1;
467 break;
468 case MODRM_SPLITRM:
469 sEntryNumber += 2;
470 break;
Craig Toppera0cd9702012-02-09 08:58:07 +0000471 case MODRM_SPLITREG:
472 sEntryNumber += 16;
473 break;
Craig Topper963305b2012-09-13 05:45:42 +0000474 case MODRM_SPLITMISC:
475 sEntryNumber += 8 + 64;
476 break;
Craig Topper487e7442012-02-09 07:45:30 +0000477 case MODRM_FULL:
478 sEntryNumber += 256;
479 break;
480 }
481
Craig Topper8702c5b2012-09-11 04:19:21 +0000482 // We assume that the index can fit into uint16_t.
483 assert(sEntryNumber < 65536U &&
484 "Index into ModRMDecision is too large for uint16_t!");
485
Sean Callanan04cc3072009-12-19 02:59:52 +0000486 ++sTableNumber;
487}
488
Craig Topperb61024c2012-07-31 05:42:02 +0000489void DisassemblerTables::emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
Craig Topper6f142742012-07-31 06:02:05 +0000490 unsigned &i1, unsigned &i2,
Craig Topper009de602013-09-30 06:23:19 +0000491 unsigned &ModRMTableNum,
Craig Topperb61024c2012-07-31 05:42:02 +0000492 OpcodeDecision &decision) const {
Sean Callanan04cc3072009-12-19 02:59:52 +0000493 o2.indent(i2) << "{ /* struct OpcodeDecision */" << "\n";
494 i2++;
495 o2.indent(i2) << "{" << "\n";
496 i2++;
497
Craig Topper6f142742012-07-31 06:02:05 +0000498 for (unsigned index = 0; index < 256; ++index) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000499 o2.indent(i2);
500
501 o2 << "/* 0x" << format("%02hhx", index) << " */" << "\n";
502
Craig Topper009de602013-09-30 06:23:19 +0000503 emitModRMDecision(o1, o2, i1, i2, ModRMTableNum,
504 decision.modRMDecisions[index]);
Sean Callanan04cc3072009-12-19 02:59:52 +0000505
506 if (index < 255)
507 o2 << ",";
508
509 o2 << "\n";
510 }
511
512 i2--;
513 o2.indent(i2) << "}" << "\n";
514 i2--;
515 o2.indent(i2) << "}" << "\n";
516}
517
Craig Topperb61024c2012-07-31 05:42:02 +0000518void DisassemblerTables::emitContextDecision(raw_ostream &o1, raw_ostream &o2,
Craig Topper6f142742012-07-31 06:02:05 +0000519 unsigned &i1, unsigned &i2,
Craig Topper009de602013-09-30 06:23:19 +0000520 unsigned &ModRMTableNum,
Craig Topperb61024c2012-07-31 05:42:02 +0000521 ContextDecision &decision,
522 const char* name) const {
Benjamin Kramerde0a4fb2010-10-23 09:10:44 +0000523 o2.indent(i2) << "static const struct ContextDecision " << name << " = {\n";
Sean Callanan04cc3072009-12-19 02:59:52 +0000524 i2++;
525 o2.indent(i2) << "{ /* opcodeDecisions */" << "\n";
526 i2++;
527
Craig Topper6f142742012-07-31 06:02:05 +0000528 for (unsigned index = 0; index < IC_max; ++index) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000529 o2.indent(i2) << "/* ";
530 o2 << stringForContext((InstructionContext)index);
531 o2 << " */";
532 o2 << "\n";
533
Craig Topper009de602013-09-30 06:23:19 +0000534 emitOpcodeDecision(o1, o2, i1, i2, ModRMTableNum,
535 decision.opcodeDecisions[index]);
Sean Callanan04cc3072009-12-19 02:59:52 +0000536
537 if (index + 1 < IC_max)
538 o2 << ", ";
539 }
540
541 i2--;
542 o2.indent(i2) << "}" << "\n";
543 i2--;
544 o2.indent(i2) << "};" << "\n";
545}
546
Craig Topper6f142742012-07-31 06:02:05 +0000547void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
548 unsigned &i) const {
Craig Topperb8aec082012-08-01 07:39:18 +0000549 unsigned NumInstructions = InstructionSpecifiers.size();
550
551 o << "static const struct OperandSpecifier x86OperandSets[]["
552 << X86_MAX_OPERANDS << "] = {\n";
553
554 typedef std::vector<std::pair<const char *, const char *> > OperandListTy;
555 std::map<OperandListTy, unsigned> OperandSets;
556
557 unsigned OperandSetNum = 0;
558 for (unsigned Index = 0; Index < NumInstructions; ++Index) {
559 OperandListTy OperandList;
560
561 for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
562 ++OperandIndex) {
563 const char *Encoding =
564 stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[Index]
565 .operands[OperandIndex].encoding);
566 const char *Type =
567 stringForOperandType((OperandType)InstructionSpecifiers[Index]
568 .operands[OperandIndex].type);
569 OperandList.push_back(std::make_pair(Encoding, Type));
570 }
571 unsigned &N = OperandSets[OperandList];
572 if (N != 0) continue;
573
574 N = ++OperandSetNum;
575
576 o << " { /* " << (OperandSetNum - 1) << " */\n";
577 for (unsigned i = 0, e = OperandList.size(); i != e; ++i) {
578 o << " { " << OperandList[i].first << ", "
579 << OperandList[i].second << " },\n";
580 }
581 o << " },\n";
582 }
583 o << "};" << "\n\n";
584
Benjamin Kramerde0a4fb2010-10-23 09:10:44 +0000585 o.indent(i * 2) << "static const struct InstructionSpecifier ";
586 o << INSTRUCTIONS_STR "[" << InstructionSpecifiers.size() << "] = {\n";
Craig Topper0c4253f2012-07-31 05:27:01 +0000587
Sean Callanan04cc3072009-12-19 02:59:52 +0000588 i++;
589
Craig Topperb8aec082012-08-01 07:39:18 +0000590 for (unsigned index = 0; index < NumInstructions; ++index) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000591 o.indent(i * 2) << "{ /* " << index << " */" << "\n";
592 i++;
Craig Topper6dedbae2012-03-04 02:16:41 +0000593
Craig Topperb8aec082012-08-01 07:39:18 +0000594 OperandListTy OperandList;
595 for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
596 ++OperandIndex) {
597 const char *Encoding =
598 stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[index]
599 .operands[OperandIndex].encoding);
600 const char *Type =
601 stringForOperandType((OperandType)InstructionSpecifiers[index]
602 .operands[OperandIndex].type);
603 OperandList.push_back(std::make_pair(Encoding, Type));
Sean Callanan04cc3072009-12-19 02:59:52 +0000604 }
Craig Topperb8aec082012-08-01 07:39:18 +0000605 o.indent(i * 2) << (OperandSets[OperandList] - 1) << ",\n";
Craig Topper0c4253f2012-07-31 05:27:01 +0000606
Benjamin Kramer478e8de2012-02-11 14:50:54 +0000607 o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */";
Sean Callanan04cc3072009-12-19 02:59:52 +0000608 o << "\n";
609
610 i--;
611 o.indent(i * 2) << "}";
612
Craig Topperb8aec082012-08-01 07:39:18 +0000613 if (index + 1 < NumInstructions)
Sean Callanan04cc3072009-12-19 02:59:52 +0000614 o << ",";
615
616 o << "\n";
617 }
618
619 i--;
620 o.indent(i * 2) << "};" << "\n";
621}
622
Craig Topper6f142742012-07-31 06:02:05 +0000623void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
Elena Demikhovsky371e3632013-12-25 11:40:51 +0000624 const unsigned int tableSize = 16384;
Craig Topper9caea122012-07-31 06:15:39 +0000625 o.indent(i * 2) << "static const uint8_t " CONTEXTS_STR
Elena Demikhovsky371e3632013-12-25 11:40:51 +0000626 "[" << tableSize << "] = {\n";
Sean Callanan04cc3072009-12-19 02:59:52 +0000627 i++;
628
Elena Demikhovsky371e3632013-12-25 11:40:51 +0000629 for (unsigned index = 0; index < tableSize; ++index) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000630 o.indent(i * 2);
631
Elena Demikhovsky371e3632013-12-25 11:40:51 +0000632 if (index & ATTR_EVEX) {
633 o << "IC_EVEX";
634 if (index & ATTR_EVEXL2)
635 o << "_L2";
636 else if (index & ATTR_EVEXL)
637 o << "_L";
638 if (index & ATTR_REXW)
639 o << "_W";
640 if (index & ATTR_OPSIZE)
641 o << "_OPSIZE";
642 else if (index & ATTR_XD)
643 o << "_XD";
644 else if (index & ATTR_XS)
645 o << "_XS";
646 if (index & ATTR_EVEXKZ)
647 o << "_KZ";
648 else if (index & ATTR_EVEXK)
649 o << "_K";
650 if (index & ATTR_EVEXB)
651 o << "_B";
652 }
653 else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
Craig Topperf01f1b52011-11-06 23:04:08 +0000654 o << "IC_VEX_L_W_OPSIZE";
Craig Toppered59dd32013-09-30 02:46:36 +0000655 else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XD))
656 o << "IC_VEX_L_W_XD";
657 else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XS))
658 o << "IC_VEX_L_W_XS";
659 else if ((index & ATTR_VEXL) && (index & ATTR_REXW))
660 o << "IC_VEX_L_W";
Craig Topperf01f1b52011-11-06 23:04:08 +0000661 else if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE))
Sean Callananc3fd5232011-03-15 01:23:15 +0000662 o << "IC_VEX_L_OPSIZE";
663 else if ((index & ATTR_VEXL) && (index & ATTR_XD))
664 o << "IC_VEX_L_XD";
665 else if ((index & ATTR_VEXL) && (index & ATTR_XS))
666 o << "IC_VEX_L_XS";
667 else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
668 o << "IC_VEX_W_OPSIZE";
669 else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XD))
670 o << "IC_VEX_W_XD";
671 else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XS))
672 o << "IC_VEX_W_XS";
673 else if (index & ATTR_VEXL)
674 o << "IC_VEX_L";
675 else if ((index & ATTR_VEX) && (index & ATTR_REXW))
676 o << "IC_VEX_W";
677 else if ((index & ATTR_VEX) && (index & ATTR_OPSIZE))
678 o << "IC_VEX_OPSIZE";
679 else if ((index & ATTR_VEX) && (index & ATTR_XD))
680 o << "IC_VEX_XD";
681 else if ((index & ATTR_VEX) && (index & ATTR_XS))
682 o << "IC_VEX_XS";
Craig Topper76e3e0b2011-08-25 07:42:00 +0000683 else if (index & ATTR_VEX)
684 o << "IC_VEX";
Sean Callananc3fd5232011-03-15 01:23:15 +0000685 else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS))
Sean Callanan04cc3072009-12-19 02:59:52 +0000686 o << "IC_64BIT_REXW_XS";
687 else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD))
688 o << "IC_64BIT_REXW_XD";
Craig Topper0c4253f2012-07-31 05:27:01 +0000689 else if ((index & ATTR_64BIT) && (index & ATTR_REXW) &&
Sean Callanan04cc3072009-12-19 02:59:52 +0000690 (index & ATTR_OPSIZE))
691 o << "IC_64BIT_REXW_OPSIZE";
Craig Topper88cb33e2011-10-01 19:54:56 +0000692 else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE))
693 o << "IC_64BIT_XD_OPSIZE";
Craig Toppera6978522011-10-11 04:34:23 +0000694 else if ((index & ATTR_64BIT) && (index & ATTR_XS) && (index & ATTR_OPSIZE))
695 o << "IC_64BIT_XS_OPSIZE";
Sean Callanan04cc3072009-12-19 02:59:52 +0000696 else if ((index & ATTR_64BIT) && (index & ATTR_XS))
697 o << "IC_64BIT_XS";
698 else if ((index & ATTR_64BIT) && (index & ATTR_XD))
699 o << "IC_64BIT_XD";
700 else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE))
701 o << "IC_64BIT_OPSIZE";
Craig Topper6491c802012-02-27 01:54:29 +0000702 else if ((index & ATTR_64BIT) && (index & ATTR_ADSIZE))
703 o << "IC_64BIT_ADSIZE";
Sean Callanan04cc3072009-12-19 02:59:52 +0000704 else if ((index & ATTR_64BIT) && (index & ATTR_REXW))
705 o << "IC_64BIT_REXW";
706 else if ((index & ATTR_64BIT))
707 o << "IC_64BIT";
Craig Toppera6978522011-10-11 04:34:23 +0000708 else if ((index & ATTR_XS) && (index & ATTR_OPSIZE))
709 o << "IC_XS_OPSIZE";
Craig Topper88cb33e2011-10-01 19:54:56 +0000710 else if ((index & ATTR_XD) && (index & ATTR_OPSIZE))
711 o << "IC_XD_OPSIZE";
Sean Callanan04cc3072009-12-19 02:59:52 +0000712 else if (index & ATTR_XS)
713 o << "IC_XS";
714 else if (index & ATTR_XD)
715 o << "IC_XD";
716 else if (index & ATTR_OPSIZE)
717 o << "IC_OPSIZE";
Craig Topper6491c802012-02-27 01:54:29 +0000718 else if (index & ATTR_ADSIZE)
719 o << "IC_ADSIZE";
Sean Callanan04cc3072009-12-19 02:59:52 +0000720 else
721 o << "IC";
722
Elena Demikhovsky371e3632013-12-25 11:40:51 +0000723 if (index < tableSize - 1)
Sean Callanan04cc3072009-12-19 02:59:52 +0000724 o << ",";
725 else
726 o << " ";
727
728 o << " /* " << index << " */";
729
730 o << "\n";
731 }
732
733 i--;
734 o.indent(i * 2) << "};" << "\n";
735}
736
Craig Topperb61024c2012-07-31 05:42:02 +0000737void DisassemblerTables::emitContextDecisions(raw_ostream &o1, raw_ostream &o2,
Craig Topper009de602013-09-30 06:23:19 +0000738 unsigned &i1, unsigned &i2,
739 unsigned &ModRMTableNum) const {
740 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[0], ONEBYTE_STR);
741 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[1], TWOBYTE_STR);
742 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[2], THREEBYTE38_STR);
743 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[3], THREEBYTE3A_STR);
744 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[4], THREEBYTEA6_STR);
745 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[5], THREEBYTEA7_STR);
Craig Topper9e3e38a2013-10-03 05:17:48 +0000746 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[6], XOP8_MAP_STR);
747 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[7], XOP9_MAP_STR);
748 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[8], XOPA_MAP_STR);
Sean Callanan04cc3072009-12-19 02:59:52 +0000749}
750
751void DisassemblerTables::emit(raw_ostream &o) const {
Craig Topper6f142742012-07-31 06:02:05 +0000752 unsigned i1 = 0;
753 unsigned i2 = 0;
Craig Topper0c4253f2012-07-31 05:27:01 +0000754
Sean Callanan04cc3072009-12-19 02:59:52 +0000755 std::string s1;
756 std::string s2;
Craig Topper0c4253f2012-07-31 05:27:01 +0000757
Sean Callanan04cc3072009-12-19 02:59:52 +0000758 raw_string_ostream o1(s1);
759 raw_string_ostream o2(s2);
Craig Topper0c4253f2012-07-31 05:27:01 +0000760
Sean Callanan04cc3072009-12-19 02:59:52 +0000761 emitInstructionInfo(o, i2);
762 o << "\n";
763
764 emitContextTable(o, i2);
765 o << "\n";
Craig Topper487e7442012-02-09 07:45:30 +0000766
Craig Topper009de602013-09-30 06:23:19 +0000767 unsigned ModRMTableNum = 0;
768
Craig Topper487e7442012-02-09 07:45:30 +0000769 o << "static const InstrUID modRMTable[] = {\n";
770 i1++;
Craig Topper009de602013-09-30 06:23:19 +0000771 std::vector<unsigned> EmptyTable(1, 0);
772 ModRMTable[EmptyTable] = ModRMTableNum;
773 ModRMTableNum += EmptyTable.size();
774 o1 << "/* EmptyTable */\n";
775 o1.indent(i1 * 2) << "0x0,\n";
Craig Topper487e7442012-02-09 07:45:30 +0000776 i1--;
Craig Topper009de602013-09-30 06:23:19 +0000777 emitContextDecisions(o1, o2, i1, i2, ModRMTableNum);
Craig Topper487e7442012-02-09 07:45:30 +0000778
Sean Callanan04cc3072009-12-19 02:59:52 +0000779 o << o1.str();
Craig Topper487e7442012-02-09 07:45:30 +0000780 o << " 0x0\n";
781 o << "};\n";
Sean Callanan04cc3072009-12-19 02:59:52 +0000782 o << "\n";
783 o << o2.str();
784 o << "\n";
785 o << "\n";
786}
787
788void DisassemblerTables::setTableFields(ModRMDecision &decision,
789 const ModRMFilter &filter,
790 InstrUID uid,
791 uint8_t opcode) {
Craig Topper6f142742012-07-31 06:02:05 +0000792 for (unsigned index = 0; index < 256; ++index) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000793 if (filter.accepts(index)) {
794 if (decision.instructionIDs[index] == uid)
795 continue;
796
797 if (decision.instructionIDs[index] != 0) {
798 InstructionSpecifier &newInfo =
799 InstructionSpecifiers[uid];
800 InstructionSpecifier &previousInfo =
801 InstructionSpecifiers[decision.instructionIDs[index]];
Craig Topper0c4253f2012-07-31 05:27:01 +0000802
Sean Callanan04cc3072009-12-19 02:59:52 +0000803 if(newInfo.filtered)
804 continue; // filtered instructions get lowest priority
Craig Topper0c4253f2012-07-31 05:27:01 +0000805
Craig Toppera948cb92011-09-11 20:23:20 +0000806 if(previousInfo.name == "NOOP" && (newInfo.name == "XCHG16ar" ||
807 newInfo.name == "XCHG32ar" ||
Craig Topper5aebebe2011-10-07 05:35:38 +0000808 newInfo.name == "XCHG32ar64" ||
Craig Toppera948cb92011-09-11 20:23:20 +0000809 newInfo.name == "XCHG64ar"))
810 continue; // special case for XCHG*ar and NOOP
Sean Callanan04cc3072009-12-19 02:59:52 +0000811
812 if (outranks(previousInfo.insnContext, newInfo.insnContext))
813 continue;
Craig Topper0c4253f2012-07-31 05:27:01 +0000814
Sean Callanan04cc3072009-12-19 02:59:52 +0000815 if (previousInfo.insnContext == newInfo.insnContext &&
816 !previousInfo.filtered) {
817 errs() << "Error: Primary decode conflict: ";
818 errs() << newInfo.name << " would overwrite " << previousInfo.name;
819 errs() << "\n";
820 errs() << "ModRM " << index << "\n";
821 errs() << "Opcode " << (uint16_t)opcode << "\n";
822 errs() << "Context " << stringForContext(newInfo.insnContext) << "\n";
823 HasConflicts = true;
824 }
825 }
826
827 decision.instructionIDs[index] = uid;
828 }
829 }
830}
831
832void DisassemblerTables::setTableFields(OpcodeType type,
833 InstructionContext insnContext,
834 uint8_t opcode,
835 const ModRMFilter &filter,
Craig Topper526adab2011-09-23 06:57:25 +0000836 InstrUID uid,
Craig Topperf18c8962011-10-04 06:30:42 +0000837 bool is32bit,
838 bool ignoresVEX_L) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000839 ContextDecision &decision = *Tables[type];
840
Craig Topper6f142742012-07-31 06:02:05 +0000841 for (unsigned index = 0; index < IC_max; ++index) {
Craig Topper526adab2011-09-23 06:57:25 +0000842 if (is32bit && inheritsFrom((InstructionContext)index, IC_64BIT))
843 continue;
844
Craig Topper0c4253f2012-07-31 05:27:01 +0000845 if (inheritsFrom((InstructionContext)index,
Craig Topperf18c8962011-10-04 06:30:42 +0000846 InstructionSpecifiers[uid].insnContext, ignoresVEX_L))
Craig Topper0c4253f2012-07-31 05:27:01 +0000847 setTableFields(decision.opcodeDecisions[index].modRMDecisions[opcode],
Sean Callanan04cc3072009-12-19 02:59:52 +0000848 filter,
849 uid,
850 opcode);
851 }
852}