blob: 4c7066432a8d431d93dfcd6b9cf12b44e73386cc [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:
213 return inheritsFrom(child, IC_EVEX_W_OPSIZE_K) ||
214 inheritsFrom(child, IC_EVEX_W_OPSIZE_K);
215 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:
219 return false;
220 case IC_EVEX_L_K:
221 case IC_EVEX_L_XS_K:
222 case IC_EVEX_L_XD_K:
223 case IC_EVEX_L_OPSIZE_K:
224 return false;
Elena Demikhovskydacddb02013-11-03 13:46:31 +0000225 case IC_EVEX_W_KZ:
226 case IC_EVEX_W_XS_KZ:
227 case IC_EVEX_W_XD_KZ:
228 case IC_EVEX_W_OPSIZE_KZ:
229 return false;
230 case IC_EVEX_L_KZ:
231 case IC_EVEX_L_XS_KZ:
232 case IC_EVEX_L_XD_KZ:
233 case IC_EVEX_L_OPSIZE_KZ:
234 return false;
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000235 case IC_EVEX_L_W_K:
236 case IC_EVEX_L_W_XS_K:
237 case IC_EVEX_L_W_XD_K:
238 case IC_EVEX_L_W_OPSIZE_K:
Elena Demikhovskydacddb02013-11-03 13:46:31 +0000239 case IC_EVEX_L_W_KZ:
240 case IC_EVEX_L_W_XS_KZ:
241 case IC_EVEX_L_W_XD_KZ:
242 case IC_EVEX_L_W_OPSIZE_KZ:
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000243 return false;
244 case IC_EVEX_L2_K:
245 case IC_EVEX_L2_B:
246 case IC_EVEX_L2_XS_K:
Elena Demikhovskyde3f7512014-01-01 15:12:34 +0000247 case IC_EVEX_L2_XS_B:
248 case IC_EVEX_L2_XD_B:
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000249 case IC_EVEX_L2_XD_K:
250 case IC_EVEX_L2_OPSIZE_K:
251 case IC_EVEX_L2_OPSIZE_B:
Elena Demikhovskydacddb02013-11-03 13:46:31 +0000252 case IC_EVEX_L2_OPSIZE_K_B:
253 case IC_EVEX_L2_KZ:
254 case IC_EVEX_L2_XS_KZ:
255 case IC_EVEX_L2_XD_KZ:
256 case IC_EVEX_L2_OPSIZE_KZ:
257 case IC_EVEX_L2_OPSIZE_KZ_B:
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000258 return false;
259 case IC_EVEX_L2_W_K:
Elena Demikhovskydacddb02013-11-03 13:46:31 +0000260 case IC_EVEX_L2_W_B:
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000261 case IC_EVEX_L2_W_XS_K:
262 case IC_EVEX_L2_W_XD_K:
Elena Demikhovskyde3f7512014-01-01 15:12:34 +0000263 case IC_EVEX_L2_W_XD_B:
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000264 case IC_EVEX_L2_W_OPSIZE_K:
265 case IC_EVEX_L2_W_OPSIZE_B:
Elena Demikhovskydacddb02013-11-03 13:46:31 +0000266 case IC_EVEX_L2_W_OPSIZE_K_B:
267 case IC_EVEX_L2_W_KZ:
268 case IC_EVEX_L2_W_XS_KZ:
269 case IC_EVEX_L2_W_XD_KZ:
270 case IC_EVEX_L2_W_OPSIZE_KZ:
271 case IC_EVEX_L2_W_OPSIZE_KZ_B:
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000272 return false;
Sean Callanan04cc3072009-12-19 02:59:52 +0000273 default:
Elena Demikhovskyde3f7512014-01-01 15:12:34 +0000274 errs() << "Unknown instruction class: " <<
275 stringForContext((InstructionContext)parent) << "\n";
Craig Topper94ce5352011-09-02 04:17:54 +0000276 llvm_unreachable("Unknown instruction class");
Sean Callanan04cc3072009-12-19 02:59:52 +0000277 }
278}
279
280/// outranks - Indicates whether, if an instruction has two different applicable
281/// classes, which class should be preferred when performing decode. This
282/// imposes a total ordering (ties are resolved toward "lower")
283///
284/// @param upper - The class that may be preferable
285/// @param lower - The class that may be less preferable
286/// @return - True if upper is to be preferred, false otherwise.
Craig Topper0c4253f2012-07-31 05:27:01 +0000287static inline bool outranks(InstructionContext upper,
Sean Callanan04cc3072009-12-19 02:59:52 +0000288 InstructionContext lower) {
289 assert(upper < IC_max);
290 assert(lower < IC_max);
Craig Topper0c4253f2012-07-31 05:27:01 +0000291
Sean Callanan04cc3072009-12-19 02:59:52 +0000292#define ENUM_ENTRY(n, r, d) r,
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000293#define ENUM_ENTRY_K_B(n, r, d) ENUM_ENTRY(n, r, d) \
Elena Demikhovskydacddb02013-11-03 13:46:31 +0000294 ENUM_ENTRY(n##_K_B, r, d) ENUM_ENTRY(n##_KZ_B, r, d) \
295 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 +0000296 static int ranks[IC_max] = {
297 INSTRUCTION_CONTEXTS
298 };
299#undef ENUM_ENTRY
Elena Demikhovsky003e7d72013-07-28 08:28:38 +0000300#undef ENUM_ENTRY_K_B
Craig Topper0c4253f2012-07-31 05:27:01 +0000301
Sean Callanan04cc3072009-12-19 02:59:52 +0000302 return (ranks[upper] > ranks[lower]);
303}
304
Sean Callanan04cc3072009-12-19 02:59:52 +0000305/// getDecisionType - Determines whether a ModRM decision with 255 entries can
306/// be compacted by eliminating redundant information.
307///
308/// @param decision - The decision to be compacted.
309/// @return - The compactest available representation for the decision.
Craig Topperb61024c2012-07-31 05:42:02 +0000310static ModRMDecisionType getDecisionType(ModRMDecision &decision) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000311 bool satisfiesOneEntry = true;
312 bool satisfiesSplitRM = true;
Craig Toppera0cd9702012-02-09 08:58:07 +0000313 bool satisfiesSplitReg = true;
Craig Topper963305b2012-09-13 05:45:42 +0000314 bool satisfiesSplitMisc = true;
Craig Toppera0cd9702012-02-09 08:58:07 +0000315
Craig Topper6f142742012-07-31 06:02:05 +0000316 for (unsigned index = 0; index < 256; ++index) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000317 if (decision.instructionIDs[index] != decision.instructionIDs[0])
318 satisfiesOneEntry = false;
Craig Toppera0cd9702012-02-09 08:58:07 +0000319
Sean Callanan04cc3072009-12-19 02:59:52 +0000320 if (((index & 0xc0) == 0xc0) &&
321 (decision.instructionIDs[index] != decision.instructionIDs[0xc0]))
322 satisfiesSplitRM = false;
Craig Toppera0cd9702012-02-09 08:58:07 +0000323
Sean Callanan04cc3072009-12-19 02:59:52 +0000324 if (((index & 0xc0) != 0xc0) &&
325 (decision.instructionIDs[index] != decision.instructionIDs[0x00]))
326 satisfiesSplitRM = false;
Craig Toppera0cd9702012-02-09 08:58:07 +0000327
328 if (((index & 0xc0) == 0xc0) &&
329 (decision.instructionIDs[index] != decision.instructionIDs[index&0xf8]))
330 satisfiesSplitReg = false;
331
332 if (((index & 0xc0) != 0xc0) &&
333 (decision.instructionIDs[index] != decision.instructionIDs[index&0x38]))
Craig Topper963305b2012-09-13 05:45:42 +0000334 satisfiesSplitMisc = false;
Sean Callanan04cc3072009-12-19 02:59:52 +0000335 }
Craig Toppera0cd9702012-02-09 08:58:07 +0000336
Sean Callanan04cc3072009-12-19 02:59:52 +0000337 if (satisfiesOneEntry)
338 return MODRM_ONEENTRY;
Craig Toppera0cd9702012-02-09 08:58:07 +0000339
Sean Callanan04cc3072009-12-19 02:59:52 +0000340 if (satisfiesSplitRM)
341 return MODRM_SPLITRM;
Craig Toppera0cd9702012-02-09 08:58:07 +0000342
Craig Topper963305b2012-09-13 05:45:42 +0000343 if (satisfiesSplitReg && satisfiesSplitMisc)
Craig Toppera0cd9702012-02-09 08:58:07 +0000344 return MODRM_SPLITREG;
345
Craig Topper963305b2012-09-13 05:45:42 +0000346 if (satisfiesSplitMisc)
347 return MODRM_SPLITMISC;
348
Sean Callanan04cc3072009-12-19 02:59:52 +0000349 return MODRM_FULL;
350}
351
352/// stringForDecisionType - Returns a statically-allocated string corresponding
353/// to a particular decision type.
354///
355/// @param dt - The decision type.
Craig Topper0c4253f2012-07-31 05:27:01 +0000356/// @return - A pointer to the statically-allocated string (e.g.,
Sean Callanan04cc3072009-12-19 02:59:52 +0000357/// "MODRM_ONEENTRY" for MODRM_ONEENTRY).
Craig Topperb61024c2012-07-31 05:42:02 +0000358static const char* stringForDecisionType(ModRMDecisionType dt) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000359#define ENUM_ENTRY(n) case n: return #n;
360 switch (dt) {
361 default:
Craig Topper0c4253f2012-07-31 05:27:01 +0000362 llvm_unreachable("Unknown decision type");
Sean Callanan04cc3072009-12-19 02:59:52 +0000363 MODRMTYPES
Craig Topper0c4253f2012-07-31 05:27:01 +0000364 };
Sean Callanan04cc3072009-12-19 02:59:52 +0000365#undef ENUM_ENTRY
366}
Craig Topper0c4253f2012-07-31 05:27:01 +0000367
Sean Callanan04cc3072009-12-19 02:59:52 +0000368DisassemblerTables::DisassemblerTables() {
369 unsigned i;
Craig Topper0c4253f2012-07-31 05:27:01 +0000370
Joerg Sonnenbergerc94780c2011-04-04 16:25:38 +0000371 for (i = 0; i < array_lengthof(Tables); i++) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000372 Tables[i] = new ContextDecision;
Daniel Dunbar3a821f72009-12-19 04:16:57 +0000373 memset(Tables[i], 0, sizeof(ContextDecision));
Sean Callanan04cc3072009-12-19 02:59:52 +0000374 }
Craig Topper0c4253f2012-07-31 05:27:01 +0000375
Sean Callanan04cc3072009-12-19 02:59:52 +0000376 HasConflicts = false;
377}
Craig Topper0c4253f2012-07-31 05:27:01 +0000378
Sean Callanan04cc3072009-12-19 02:59:52 +0000379DisassemblerTables::~DisassemblerTables() {
380 unsigned i;
Craig Topper0c4253f2012-07-31 05:27:01 +0000381
Joerg Sonnenbergerc94780c2011-04-04 16:25:38 +0000382 for (i = 0; i < array_lengthof(Tables); i++)
Sean Callanan04cc3072009-12-19 02:59:52 +0000383 delete Tables[i];
384}
Craig Topper0c4253f2012-07-31 05:27:01 +0000385
Craig Topperb61024c2012-07-31 05:42:02 +0000386void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
Craig Topper6f142742012-07-31 06:02:05 +0000387 unsigned &i1, unsigned &i2,
Craig Topper009de602013-09-30 06:23:19 +0000388 unsigned &ModRMTableNum,
Craig Topperb61024c2012-07-31 05:42:02 +0000389 ModRMDecision &decision) const {
Craig Topper6f142742012-07-31 06:02:05 +0000390 static uint32_t sTableNumber = 0;
391 static uint32_t sEntryNumber = 1;
Sean Callanan04cc3072009-12-19 02:59:52 +0000392 ModRMDecisionType dt = getDecisionType(decision);
Craig Topper487e7442012-02-09 07:45:30 +0000393
Sean Callanan04cc3072009-12-19 02:59:52 +0000394 if (dt == MODRM_ONEENTRY && decision.instructionIDs[0] == 0)
395 {
396 o2.indent(i2) << "{ /* ModRMDecision */" << "\n";
397 i2++;
Craig Topper487e7442012-02-09 07:45:30 +0000398
Sean Callanan04cc3072009-12-19 02:59:52 +0000399 o2.indent(i2) << stringForDecisionType(dt) << "," << "\n";
Craig Topper487e7442012-02-09 07:45:30 +0000400 o2.indent(i2) << 0 << " /* EmptyTable */\n";
401
Sean Callanan04cc3072009-12-19 02:59:52 +0000402 i2--;
403 o2.indent(i2) << "}";
404 return;
405 }
Sean Callanan04cc3072009-12-19 02:59:52 +0000406
Craig Topper009de602013-09-30 06:23:19 +0000407 std::vector<unsigned> ModRMDecision;
Craig Topper487e7442012-02-09 07:45:30 +0000408
Sean Callanan04cc3072009-12-19 02:59:52 +0000409 switch (dt) {
410 default:
411 llvm_unreachable("Unknown decision type");
412 case MODRM_ONEENTRY:
Craig Topper009de602013-09-30 06:23:19 +0000413 ModRMDecision.push_back(decision.instructionIDs[0]);
Sean Callanan04cc3072009-12-19 02:59:52 +0000414 break;
415 case MODRM_SPLITRM:
Craig Topper009de602013-09-30 06:23:19 +0000416 ModRMDecision.push_back(decision.instructionIDs[0x00]);
417 ModRMDecision.push_back(decision.instructionIDs[0xc0]);
Sean Callanan04cc3072009-12-19 02:59:52 +0000418 break;
Craig Toppera0cd9702012-02-09 08:58:07 +0000419 case MODRM_SPLITREG:
Craig Topper6f142742012-07-31 06:02:05 +0000420 for (unsigned index = 0; index < 64; index += 8)
Craig Topper009de602013-09-30 06:23:19 +0000421 ModRMDecision.push_back(decision.instructionIDs[index]);
Craig Topper6f142742012-07-31 06:02:05 +0000422 for (unsigned index = 0xc0; index < 256; index += 8)
Craig Topper009de602013-09-30 06:23:19 +0000423 ModRMDecision.push_back(decision.instructionIDs[index]);
Craig Toppera0cd9702012-02-09 08:58:07 +0000424 break;
Craig Topper963305b2012-09-13 05:45:42 +0000425 case MODRM_SPLITMISC:
426 for (unsigned index = 0; index < 64; index += 8)
Craig Topper009de602013-09-30 06:23:19 +0000427 ModRMDecision.push_back(decision.instructionIDs[index]);
Craig Topper963305b2012-09-13 05:45:42 +0000428 for (unsigned index = 0xc0; index < 256; ++index)
Craig Topper009de602013-09-30 06:23:19 +0000429 ModRMDecision.push_back(decision.instructionIDs[index]);
Craig Topper963305b2012-09-13 05:45:42 +0000430 break;
Sean Callanan04cc3072009-12-19 02:59:52 +0000431 case MODRM_FULL:
Craig Topper6f142742012-07-31 06:02:05 +0000432 for (unsigned index = 0; index < 256; ++index)
Craig Topper009de602013-09-30 06:23:19 +0000433 ModRMDecision.push_back(decision.instructionIDs[index]);
Sean Callanan04cc3072009-12-19 02:59:52 +0000434 break;
435 }
Craig Topper487e7442012-02-09 07:45:30 +0000436
Craig Topper009de602013-09-30 06:23:19 +0000437 unsigned &EntryNumber = ModRMTable[ModRMDecision];
438 if (EntryNumber == 0) {
439 EntryNumber = ModRMTableNum;
440
441 ModRMTableNum += ModRMDecision.size();
442 o1 << "/* Table" << EntryNumber << " */\n";
443 i1++;
444 for (std::vector<unsigned>::const_iterator I = ModRMDecision.begin(),
445 E = ModRMDecision.end(); I != E; ++I) {
446 o1.indent(i1 * 2) << format("0x%hx", *I) << ", /* "
447 << InstructionSpecifiers[*I].name << " */\n";
448 }
449 i1--;
450 }
Craig Topper487e7442012-02-09 07:45:30 +0000451
Sean Callanan04cc3072009-12-19 02:59:52 +0000452 o2.indent(i2) << "{ /* struct ModRMDecision */" << "\n";
453 i2++;
Craig Topper487e7442012-02-09 07:45:30 +0000454
Sean Callanan04cc3072009-12-19 02:59:52 +0000455 o2.indent(i2) << stringForDecisionType(dt) << "," << "\n";
Craig Topper009de602013-09-30 06:23:19 +0000456 o2.indent(i2) << EntryNumber << " /* Table" << EntryNumber << " */\n";
Craig Topper487e7442012-02-09 07:45:30 +0000457
Sean Callanan04cc3072009-12-19 02:59:52 +0000458 i2--;
459 o2.indent(i2) << "}";
Craig Topper487e7442012-02-09 07:45:30 +0000460
461 switch (dt) {
462 default:
463 llvm_unreachable("Unknown decision type");
464 case MODRM_ONEENTRY:
465 sEntryNumber += 1;
466 break;
467 case MODRM_SPLITRM:
468 sEntryNumber += 2;
469 break;
Craig Toppera0cd9702012-02-09 08:58:07 +0000470 case MODRM_SPLITREG:
471 sEntryNumber += 16;
472 break;
Craig Topper963305b2012-09-13 05:45:42 +0000473 case MODRM_SPLITMISC:
474 sEntryNumber += 8 + 64;
475 break;
Craig Topper487e7442012-02-09 07:45:30 +0000476 case MODRM_FULL:
477 sEntryNumber += 256;
478 break;
479 }
480
Craig Topper8702c5b2012-09-11 04:19:21 +0000481 // We assume that the index can fit into uint16_t.
482 assert(sEntryNumber < 65536U &&
483 "Index into ModRMDecision is too large for uint16_t!");
484
Sean Callanan04cc3072009-12-19 02:59:52 +0000485 ++sTableNumber;
486}
487
Craig Topperb61024c2012-07-31 05:42:02 +0000488void DisassemblerTables::emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
Craig Topper6f142742012-07-31 06:02:05 +0000489 unsigned &i1, unsigned &i2,
Craig Topper009de602013-09-30 06:23:19 +0000490 unsigned &ModRMTableNum,
Craig Topperb61024c2012-07-31 05:42:02 +0000491 OpcodeDecision &decision) const {
Sean Callanan04cc3072009-12-19 02:59:52 +0000492 o2.indent(i2) << "{ /* struct OpcodeDecision */" << "\n";
493 i2++;
494 o2.indent(i2) << "{" << "\n";
495 i2++;
496
Craig Topper6f142742012-07-31 06:02:05 +0000497 for (unsigned index = 0; index < 256; ++index) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000498 o2.indent(i2);
499
500 o2 << "/* 0x" << format("%02hhx", index) << " */" << "\n";
501
Craig Topper009de602013-09-30 06:23:19 +0000502 emitModRMDecision(o1, o2, i1, i2, ModRMTableNum,
503 decision.modRMDecisions[index]);
Sean Callanan04cc3072009-12-19 02:59:52 +0000504
505 if (index < 255)
506 o2 << ",";
507
508 o2 << "\n";
509 }
510
511 i2--;
512 o2.indent(i2) << "}" << "\n";
513 i2--;
514 o2.indent(i2) << "}" << "\n";
515}
516
Craig Topperb61024c2012-07-31 05:42:02 +0000517void DisassemblerTables::emitContextDecision(raw_ostream &o1, raw_ostream &o2,
Craig Topper6f142742012-07-31 06:02:05 +0000518 unsigned &i1, unsigned &i2,
Craig Topper009de602013-09-30 06:23:19 +0000519 unsigned &ModRMTableNum,
Craig Topperb61024c2012-07-31 05:42:02 +0000520 ContextDecision &decision,
521 const char* name) const {
Benjamin Kramerde0a4fb2010-10-23 09:10:44 +0000522 o2.indent(i2) << "static const struct ContextDecision " << name << " = {\n";
Sean Callanan04cc3072009-12-19 02:59:52 +0000523 i2++;
524 o2.indent(i2) << "{ /* opcodeDecisions */" << "\n";
525 i2++;
526
Craig Topper6f142742012-07-31 06:02:05 +0000527 for (unsigned index = 0; index < IC_max; ++index) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000528 o2.indent(i2) << "/* ";
529 o2 << stringForContext((InstructionContext)index);
530 o2 << " */";
531 o2 << "\n";
532
Craig Topper009de602013-09-30 06:23:19 +0000533 emitOpcodeDecision(o1, o2, i1, i2, ModRMTableNum,
534 decision.opcodeDecisions[index]);
Sean Callanan04cc3072009-12-19 02:59:52 +0000535
536 if (index + 1 < IC_max)
537 o2 << ", ";
538 }
539
540 i2--;
541 o2.indent(i2) << "}" << "\n";
542 i2--;
543 o2.indent(i2) << "};" << "\n";
544}
545
Craig Topper6f142742012-07-31 06:02:05 +0000546void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
547 unsigned &i) const {
Craig Topperb8aec082012-08-01 07:39:18 +0000548 unsigned NumInstructions = InstructionSpecifiers.size();
549
550 o << "static const struct OperandSpecifier x86OperandSets[]["
551 << X86_MAX_OPERANDS << "] = {\n";
552
553 typedef std::vector<std::pair<const char *, const char *> > OperandListTy;
554 std::map<OperandListTy, unsigned> OperandSets;
555
556 unsigned OperandSetNum = 0;
557 for (unsigned Index = 0; Index < NumInstructions; ++Index) {
558 OperandListTy OperandList;
559
560 for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
561 ++OperandIndex) {
562 const char *Encoding =
563 stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[Index]
564 .operands[OperandIndex].encoding);
565 const char *Type =
566 stringForOperandType((OperandType)InstructionSpecifiers[Index]
567 .operands[OperandIndex].type);
568 OperandList.push_back(std::make_pair(Encoding, Type));
569 }
570 unsigned &N = OperandSets[OperandList];
571 if (N != 0) continue;
572
573 N = ++OperandSetNum;
574
575 o << " { /* " << (OperandSetNum - 1) << " */\n";
576 for (unsigned i = 0, e = OperandList.size(); i != e; ++i) {
577 o << " { " << OperandList[i].first << ", "
578 << OperandList[i].second << " },\n";
579 }
580 o << " },\n";
581 }
582 o << "};" << "\n\n";
583
Benjamin Kramerde0a4fb2010-10-23 09:10:44 +0000584 o.indent(i * 2) << "static const struct InstructionSpecifier ";
585 o << INSTRUCTIONS_STR "[" << InstructionSpecifiers.size() << "] = {\n";
Craig Topper0c4253f2012-07-31 05:27:01 +0000586
Sean Callanan04cc3072009-12-19 02:59:52 +0000587 i++;
588
Craig Topperb8aec082012-08-01 07:39:18 +0000589 for (unsigned index = 0; index < NumInstructions; ++index) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000590 o.indent(i * 2) << "{ /* " << index << " */" << "\n";
591 i++;
Craig Topper6dedbae2012-03-04 02:16:41 +0000592
Craig Topperb8aec082012-08-01 07:39:18 +0000593 OperandListTy OperandList;
594 for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
595 ++OperandIndex) {
596 const char *Encoding =
597 stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[index]
598 .operands[OperandIndex].encoding);
599 const char *Type =
600 stringForOperandType((OperandType)InstructionSpecifiers[index]
601 .operands[OperandIndex].type);
602 OperandList.push_back(std::make_pair(Encoding, Type));
Sean Callanan04cc3072009-12-19 02:59:52 +0000603 }
Craig Topperb8aec082012-08-01 07:39:18 +0000604 o.indent(i * 2) << (OperandSets[OperandList] - 1) << ",\n";
Craig Topper0c4253f2012-07-31 05:27:01 +0000605
Benjamin Kramer478e8de2012-02-11 14:50:54 +0000606 o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */";
Sean Callanan04cc3072009-12-19 02:59:52 +0000607 o << "\n";
608
609 i--;
610 o.indent(i * 2) << "}";
611
Craig Topperb8aec082012-08-01 07:39:18 +0000612 if (index + 1 < NumInstructions)
Sean Callanan04cc3072009-12-19 02:59:52 +0000613 o << ",";
614
615 o << "\n";
616 }
617
618 i--;
619 o.indent(i * 2) << "};" << "\n";
620}
621
Craig Topper6f142742012-07-31 06:02:05 +0000622void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
Elena Demikhovsky371e3632013-12-25 11:40:51 +0000623 const unsigned int tableSize = 16384;
Craig Topper9caea122012-07-31 06:15:39 +0000624 o.indent(i * 2) << "static const uint8_t " CONTEXTS_STR
Elena Demikhovsky371e3632013-12-25 11:40:51 +0000625 "[" << tableSize << "] = {\n";
Sean Callanan04cc3072009-12-19 02:59:52 +0000626 i++;
627
Elena Demikhovsky371e3632013-12-25 11:40:51 +0000628 for (unsigned index = 0; index < tableSize; ++index) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000629 o.indent(i * 2);
630
Elena Demikhovsky371e3632013-12-25 11:40:51 +0000631 if (index & ATTR_EVEX) {
632 o << "IC_EVEX";
633 if (index & ATTR_EVEXL2)
634 o << "_L2";
635 else if (index & ATTR_EVEXL)
636 o << "_L";
637 if (index & ATTR_REXW)
638 o << "_W";
639 if (index & ATTR_OPSIZE)
640 o << "_OPSIZE";
641 else if (index & ATTR_XD)
642 o << "_XD";
643 else if (index & ATTR_XS)
644 o << "_XS";
645 if (index & ATTR_EVEXKZ)
646 o << "_KZ";
647 else if (index & ATTR_EVEXK)
648 o << "_K";
649 if (index & ATTR_EVEXB)
650 o << "_B";
651 }
652 else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
Craig Topperf01f1b52011-11-06 23:04:08 +0000653 o << "IC_VEX_L_W_OPSIZE";
Craig Toppered59dd32013-09-30 02:46:36 +0000654 else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XD))
655 o << "IC_VEX_L_W_XD";
656 else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XS))
657 o << "IC_VEX_L_W_XS";
658 else if ((index & ATTR_VEXL) && (index & ATTR_REXW))
659 o << "IC_VEX_L_W";
Craig Topperf01f1b52011-11-06 23:04:08 +0000660 else if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE))
Sean Callananc3fd5232011-03-15 01:23:15 +0000661 o << "IC_VEX_L_OPSIZE";
662 else if ((index & ATTR_VEXL) && (index & ATTR_XD))
663 o << "IC_VEX_L_XD";
664 else if ((index & ATTR_VEXL) && (index & ATTR_XS))
665 o << "IC_VEX_L_XS";
666 else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
667 o << "IC_VEX_W_OPSIZE";
668 else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XD))
669 o << "IC_VEX_W_XD";
670 else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XS))
671 o << "IC_VEX_W_XS";
672 else if (index & ATTR_VEXL)
673 o << "IC_VEX_L";
674 else if ((index & ATTR_VEX) && (index & ATTR_REXW))
675 o << "IC_VEX_W";
676 else if ((index & ATTR_VEX) && (index & ATTR_OPSIZE))
677 o << "IC_VEX_OPSIZE";
678 else if ((index & ATTR_VEX) && (index & ATTR_XD))
679 o << "IC_VEX_XD";
680 else if ((index & ATTR_VEX) && (index & ATTR_XS))
681 o << "IC_VEX_XS";
Craig Topper76e3e0b2011-08-25 07:42:00 +0000682 else if (index & ATTR_VEX)
683 o << "IC_VEX";
Sean Callananc3fd5232011-03-15 01:23:15 +0000684 else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS))
Sean Callanan04cc3072009-12-19 02:59:52 +0000685 o << "IC_64BIT_REXW_XS";
686 else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD))
687 o << "IC_64BIT_REXW_XD";
Craig Topper0c4253f2012-07-31 05:27:01 +0000688 else if ((index & ATTR_64BIT) && (index & ATTR_REXW) &&
Sean Callanan04cc3072009-12-19 02:59:52 +0000689 (index & ATTR_OPSIZE))
690 o << "IC_64BIT_REXW_OPSIZE";
Craig Topper88cb33e2011-10-01 19:54:56 +0000691 else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE))
692 o << "IC_64BIT_XD_OPSIZE";
Craig Toppera6978522011-10-11 04:34:23 +0000693 else if ((index & ATTR_64BIT) && (index & ATTR_XS) && (index & ATTR_OPSIZE))
694 o << "IC_64BIT_XS_OPSIZE";
Sean Callanan04cc3072009-12-19 02:59:52 +0000695 else if ((index & ATTR_64BIT) && (index & ATTR_XS))
696 o << "IC_64BIT_XS";
697 else if ((index & ATTR_64BIT) && (index & ATTR_XD))
698 o << "IC_64BIT_XD";
699 else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE))
700 o << "IC_64BIT_OPSIZE";
Craig Topper6491c802012-02-27 01:54:29 +0000701 else if ((index & ATTR_64BIT) && (index & ATTR_ADSIZE))
702 o << "IC_64BIT_ADSIZE";
Sean Callanan04cc3072009-12-19 02:59:52 +0000703 else if ((index & ATTR_64BIT) && (index & ATTR_REXW))
704 o << "IC_64BIT_REXW";
705 else if ((index & ATTR_64BIT))
706 o << "IC_64BIT";
Craig Toppera6978522011-10-11 04:34:23 +0000707 else if ((index & ATTR_XS) && (index & ATTR_OPSIZE))
708 o << "IC_XS_OPSIZE";
Craig Topper88cb33e2011-10-01 19:54:56 +0000709 else if ((index & ATTR_XD) && (index & ATTR_OPSIZE))
710 o << "IC_XD_OPSIZE";
Sean Callanan04cc3072009-12-19 02:59:52 +0000711 else if (index & ATTR_XS)
712 o << "IC_XS";
713 else if (index & ATTR_XD)
714 o << "IC_XD";
715 else if (index & ATTR_OPSIZE)
716 o << "IC_OPSIZE";
Craig Topper6491c802012-02-27 01:54:29 +0000717 else if (index & ATTR_ADSIZE)
718 o << "IC_ADSIZE";
Sean Callanan04cc3072009-12-19 02:59:52 +0000719 else
720 o << "IC";
721
Elena Demikhovsky371e3632013-12-25 11:40:51 +0000722 if (index < tableSize - 1)
Sean Callanan04cc3072009-12-19 02:59:52 +0000723 o << ",";
724 else
725 o << " ";
726
727 o << " /* " << index << " */";
728
729 o << "\n";
730 }
731
732 i--;
733 o.indent(i * 2) << "};" << "\n";
734}
735
Craig Topperb61024c2012-07-31 05:42:02 +0000736void DisassemblerTables::emitContextDecisions(raw_ostream &o1, raw_ostream &o2,
Craig Topper009de602013-09-30 06:23:19 +0000737 unsigned &i1, unsigned &i2,
738 unsigned &ModRMTableNum) const {
739 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[0], ONEBYTE_STR);
740 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[1], TWOBYTE_STR);
741 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[2], THREEBYTE38_STR);
742 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[3], THREEBYTE3A_STR);
743 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[4], THREEBYTEA6_STR);
744 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[5], THREEBYTEA7_STR);
Craig Topper9e3e38a2013-10-03 05:17:48 +0000745 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[6], XOP8_MAP_STR);
746 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[7], XOP9_MAP_STR);
747 emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[8], XOPA_MAP_STR);
Sean Callanan04cc3072009-12-19 02:59:52 +0000748}
749
750void DisassemblerTables::emit(raw_ostream &o) const {
Craig Topper6f142742012-07-31 06:02:05 +0000751 unsigned i1 = 0;
752 unsigned i2 = 0;
Craig Topper0c4253f2012-07-31 05:27:01 +0000753
Sean Callanan04cc3072009-12-19 02:59:52 +0000754 std::string s1;
755 std::string s2;
Craig Topper0c4253f2012-07-31 05:27:01 +0000756
Sean Callanan04cc3072009-12-19 02:59:52 +0000757 raw_string_ostream o1(s1);
758 raw_string_ostream o2(s2);
Craig Topper0c4253f2012-07-31 05:27:01 +0000759
Sean Callanan04cc3072009-12-19 02:59:52 +0000760 emitInstructionInfo(o, i2);
761 o << "\n";
762
763 emitContextTable(o, i2);
764 o << "\n";
Craig Topper487e7442012-02-09 07:45:30 +0000765
Craig Topper009de602013-09-30 06:23:19 +0000766 unsigned ModRMTableNum = 0;
767
Craig Topper487e7442012-02-09 07:45:30 +0000768 o << "static const InstrUID modRMTable[] = {\n";
769 i1++;
Craig Topper009de602013-09-30 06:23:19 +0000770 std::vector<unsigned> EmptyTable(1, 0);
771 ModRMTable[EmptyTable] = ModRMTableNum;
772 ModRMTableNum += EmptyTable.size();
773 o1 << "/* EmptyTable */\n";
774 o1.indent(i1 * 2) << "0x0,\n";
Craig Topper487e7442012-02-09 07:45:30 +0000775 i1--;
Craig Topper009de602013-09-30 06:23:19 +0000776 emitContextDecisions(o1, o2, i1, i2, ModRMTableNum);
Craig Topper487e7442012-02-09 07:45:30 +0000777
Sean Callanan04cc3072009-12-19 02:59:52 +0000778 o << o1.str();
Craig Topper487e7442012-02-09 07:45:30 +0000779 o << " 0x0\n";
780 o << "};\n";
Sean Callanan04cc3072009-12-19 02:59:52 +0000781 o << "\n";
782 o << o2.str();
783 o << "\n";
784 o << "\n";
785}
786
787void DisassemblerTables::setTableFields(ModRMDecision &decision,
788 const ModRMFilter &filter,
789 InstrUID uid,
790 uint8_t opcode) {
Craig Topper6f142742012-07-31 06:02:05 +0000791 for (unsigned index = 0; index < 256; ++index) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000792 if (filter.accepts(index)) {
793 if (decision.instructionIDs[index] == uid)
794 continue;
795
796 if (decision.instructionIDs[index] != 0) {
797 InstructionSpecifier &newInfo =
798 InstructionSpecifiers[uid];
799 InstructionSpecifier &previousInfo =
800 InstructionSpecifiers[decision.instructionIDs[index]];
Craig Topper0c4253f2012-07-31 05:27:01 +0000801
Sean Callanan04cc3072009-12-19 02:59:52 +0000802 if(newInfo.filtered)
803 continue; // filtered instructions get lowest priority
Craig Topper0c4253f2012-07-31 05:27:01 +0000804
Craig Toppera948cb92011-09-11 20:23:20 +0000805 if(previousInfo.name == "NOOP" && (newInfo.name == "XCHG16ar" ||
806 newInfo.name == "XCHG32ar" ||
Craig Topper5aebebe2011-10-07 05:35:38 +0000807 newInfo.name == "XCHG32ar64" ||
Craig Toppera948cb92011-09-11 20:23:20 +0000808 newInfo.name == "XCHG64ar"))
809 continue; // special case for XCHG*ar and NOOP
Sean Callanan04cc3072009-12-19 02:59:52 +0000810
811 if (outranks(previousInfo.insnContext, newInfo.insnContext))
812 continue;
Craig Topper0c4253f2012-07-31 05:27:01 +0000813
Sean Callanan04cc3072009-12-19 02:59:52 +0000814 if (previousInfo.insnContext == newInfo.insnContext &&
815 !previousInfo.filtered) {
816 errs() << "Error: Primary decode conflict: ";
817 errs() << newInfo.name << " would overwrite " << previousInfo.name;
818 errs() << "\n";
819 errs() << "ModRM " << index << "\n";
820 errs() << "Opcode " << (uint16_t)opcode << "\n";
821 errs() << "Context " << stringForContext(newInfo.insnContext) << "\n";
822 HasConflicts = true;
823 }
824 }
825
826 decision.instructionIDs[index] = uid;
827 }
828 }
829}
830
831void DisassemblerTables::setTableFields(OpcodeType type,
832 InstructionContext insnContext,
833 uint8_t opcode,
834 const ModRMFilter &filter,
Craig Topper526adab2011-09-23 06:57:25 +0000835 InstrUID uid,
Craig Topperf18c8962011-10-04 06:30:42 +0000836 bool is32bit,
837 bool ignoresVEX_L) {
Sean Callanan04cc3072009-12-19 02:59:52 +0000838 ContextDecision &decision = *Tables[type];
839
Craig Topper6f142742012-07-31 06:02:05 +0000840 for (unsigned index = 0; index < IC_max; ++index) {
Craig Topper526adab2011-09-23 06:57:25 +0000841 if (is32bit && inheritsFrom((InstructionContext)index, IC_64BIT))
842 continue;
843
Craig Topper0c4253f2012-07-31 05:27:01 +0000844 if (inheritsFrom((InstructionContext)index,
Craig Topperf18c8962011-10-04 06:30:42 +0000845 InstructionSpecifiers[uid].insnContext, ignoresVEX_L))
Craig Topper0c4253f2012-07-31 05:27:01 +0000846 setTableFields(decision.opcodeDecisions[index].modRMDecisions[opcode],
Sean Callanan04cc3072009-12-19 02:59:52 +0000847 filter,
848 uid,
849 opcode);
850 }
851}