X86DisassemblerTables.cpp revision 280031
1201360Srdivacky//===- X86DisassemblerTables.cpp - Disassembler tables ----------*- C++ -*-===//
2201360Srdivacky//
3201360Srdivacky//                     The LLVM Compiler Infrastructure
4201360Srdivacky//
5201360Srdivacky// This file is distributed under the University of Illinois Open Source
6201360Srdivacky// License. See LICENSE.TXT for details.
7201360Srdivacky//
8201360Srdivacky//===----------------------------------------------------------------------===//
9201360Srdivacky//
10201360Srdivacky// This file is part of the X86 Disassembler Emitter.
11201360Srdivacky// It contains the implementation of the disassembler tables.
12201360Srdivacky// Documentation for the disassembler emitter in general can be found in
13201360Srdivacky//  X86DisasemblerEmitter.h.
14201360Srdivacky//
15201360Srdivacky//===----------------------------------------------------------------------===//
16201360Srdivacky
17249423Sdim#include "X86DisassemblerTables.h"
18201360Srdivacky#include "X86DisassemblerShared.h"
19221345Sdim#include "llvm/ADT/STLExtras.h"
20201360Srdivacky#include "llvm/Support/ErrorHandling.h"
21201360Srdivacky#include "llvm/Support/Format.h"
22239462Sdim#include <map>
23201360Srdivacky
24201360Srdivackyusing namespace llvm;
25201360Srdivackyusing namespace X86Disassembler;
26239462Sdim
27276479Sdim/// stringForContext - Returns a string containing the name of a particular
28276479Sdim///   InstructionContext, usually for diagnostic purposes.
29276479Sdim///
30276479Sdim/// @param insnContext  - The instruction class to transform to a string.
31276479Sdim/// @return           - A statically-allocated string constant that contains the
32276479Sdim///                     name of the instruction class.
33276479Sdimstatic inline const char* stringForContext(InstructionContext insnContext) {
34276479Sdim  switch (insnContext) {
35276479Sdim  default:
36276479Sdim    llvm_unreachable("Unhandled instruction class");
37276479Sdim#define ENUM_ENTRY(n, r, d)   case n: return #n; break;
38276479Sdim#define ENUM_ENTRY_K_B(n, r, d) ENUM_ENTRY(n, r, d) ENUM_ENTRY(n##_K_B, r, d)\
39276479Sdim        ENUM_ENTRY(n##_KZ, r, d) ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d)\
40276479Sdim        ENUM_ENTRY(n##_KZ_B, r, d)
41276479Sdim  INSTRUCTION_CONTEXTS
42276479Sdim#undef ENUM_ENTRY
43276479Sdim#undef ENUM_ENTRY_K_B
44276479Sdim  }
45276479Sdim}
46276479Sdim
47276479Sdim/// stringForOperandType - Like stringForContext, but for OperandTypes.
48276479Sdimstatic inline const char* stringForOperandType(OperandType type) {
49276479Sdim  switch (type) {
50276479Sdim  default:
51276479Sdim    llvm_unreachable("Unhandled type");
52276479Sdim#define ENUM_ENTRY(i, d) case i: return #i;
53276479Sdim  TYPES
54276479Sdim#undef ENUM_ENTRY
55276479Sdim  }
56276479Sdim}
57276479Sdim
58276479Sdim/// stringForOperandEncoding - like stringForContext, but for
59276479Sdim///   OperandEncodings.
60276479Sdimstatic inline const char* stringForOperandEncoding(OperandEncoding encoding) {
61276479Sdim  switch (encoding) {
62276479Sdim  default:
63276479Sdim    llvm_unreachable("Unhandled encoding");
64276479Sdim#define ENUM_ENTRY(i, d) case i: return #i;
65276479Sdim  ENCODINGS
66276479Sdim#undef ENUM_ENTRY
67276479Sdim  }
68276479Sdim}
69276479Sdim
70201360Srdivacky/// inheritsFrom - Indicates whether all instructions in one class also belong
71201360Srdivacky///   to another class.
72201360Srdivacky///
73201360Srdivacky/// @param child  - The class that may be the subset
74201360Srdivacky/// @param parent - The class that may be the superset
75201360Srdivacky/// @return       - True if child is a subset of parent, false otherwise.
76201360Srdivackystatic inline bool inheritsFrom(InstructionContext child,
77226633Sdim                                InstructionContext parent,
78280031Sdim                                bool VEX_LIG = false, bool AdSize64 = false) {
79201360Srdivacky  if (child == parent)
80201360Srdivacky    return true;
81239462Sdim
82201360Srdivacky  switch (parent) {
83201360Srdivacky  case IC:
84280031Sdim    return(inheritsFrom(child, IC_64BIT, AdSize64) ||
85226633Sdim           inheritsFrom(child, IC_OPSIZE) ||
86234353Sdim           inheritsFrom(child, IC_ADSIZE) ||
87226633Sdim           inheritsFrom(child, IC_XD) ||
88226633Sdim           inheritsFrom(child, IC_XS));
89201360Srdivacky  case IC_64BIT:
90201360Srdivacky    return(inheritsFrom(child, IC_64BIT_REXW)   ||
91201360Srdivacky           inheritsFrom(child, IC_64BIT_OPSIZE) ||
92280031Sdim           (!AdSize64 && inheritsFrom(child, IC_64BIT_ADSIZE)) ||
93201360Srdivacky           inheritsFrom(child, IC_64BIT_XD)     ||
94201360Srdivacky           inheritsFrom(child, IC_64BIT_XS));
95201360Srdivacky  case IC_OPSIZE:
96280031Sdim    return inheritsFrom(child, IC_64BIT_OPSIZE) ||
97280031Sdim           inheritsFrom(child, IC_OPSIZE_ADSIZE);
98234353Sdim  case IC_ADSIZE:
99280031Sdim    return inheritsFrom(child, IC_OPSIZE_ADSIZE);
100280031Sdim  case IC_OPSIZE_ADSIZE:
101280031Sdim    return false;
102234353Sdim  case IC_64BIT_ADSIZE:
103280031Sdim    return inheritsFrom(child, IC_64BIT_OPSIZE_ADSIZE);
104280031Sdim  case IC_64BIT_OPSIZE_ADSIZE:
105234353Sdim    return false;
106201360Srdivacky  case IC_XD:
107226633Sdim    return inheritsFrom(child, IC_64BIT_XD);
108201360Srdivacky  case IC_XS:
109226633Sdim    return inheritsFrom(child, IC_64BIT_XS);
110226633Sdim  case IC_XD_OPSIZE:
111226633Sdim    return inheritsFrom(child, IC_64BIT_XD_OPSIZE);
112226633Sdim  case IC_XS_OPSIZE:
113226633Sdim    return inheritsFrom(child, IC_64BIT_XS_OPSIZE);
114201360Srdivacky  case IC_64BIT_REXW:
115201360Srdivacky    return(inheritsFrom(child, IC_64BIT_REXW_XS) ||
116201360Srdivacky           inheritsFrom(child, IC_64BIT_REXW_XD) ||
117280031Sdim           inheritsFrom(child, IC_64BIT_REXW_OPSIZE) ||
118280031Sdim           (!AdSize64 && inheritsFrom(child, IC_64BIT_REXW_ADSIZE)));
119201360Srdivacky  case IC_64BIT_OPSIZE:
120280031Sdim    return inheritsFrom(child, IC_64BIT_REXW_OPSIZE) ||
121280031Sdim           (!AdSize64 && inheritsFrom(child, IC_64BIT_OPSIZE_ADSIZE)) ||
122280031Sdim           (!AdSize64 && inheritsFrom(child, IC_64BIT_REXW_ADSIZE));
123201360Srdivacky  case IC_64BIT_XD:
124201360Srdivacky    return(inheritsFrom(child, IC_64BIT_REXW_XD));
125201360Srdivacky  case IC_64BIT_XS:
126201360Srdivacky    return(inheritsFrom(child, IC_64BIT_REXW_XS));
127226633Sdim  case IC_64BIT_XD_OPSIZE:
128226633Sdim  case IC_64BIT_XS_OPSIZE:
129226633Sdim    return false;
130201360Srdivacky  case IC_64BIT_REXW_XD:
131201360Srdivacky  case IC_64BIT_REXW_XS:
132201360Srdivacky  case IC_64BIT_REXW_OPSIZE:
133280031Sdim  case IC_64BIT_REXW_ADSIZE:
134201360Srdivacky    return false;
135221345Sdim  case IC_VEX:
136261991Sdim    return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W)) ||
137261991Sdim           inheritsFrom(child, IC_VEX_W) ||
138226633Sdim           (VEX_LIG && inheritsFrom(child, IC_VEX_L));
139221345Sdim  case IC_VEX_XS:
140261991Sdim    return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XS)) ||
141261991Sdim           inheritsFrom(child, IC_VEX_W_XS) ||
142226633Sdim           (VEX_LIG && inheritsFrom(child, IC_VEX_L_XS));
143221345Sdim  case IC_VEX_XD:
144261991Sdim    return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XD)) ||
145261991Sdim           inheritsFrom(child, IC_VEX_W_XD) ||
146226633Sdim           (VEX_LIG && inheritsFrom(child, IC_VEX_L_XD));
147226633Sdim  case IC_VEX_OPSIZE:
148261991Sdim    return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W_OPSIZE)) ||
149261991Sdim           inheritsFrom(child, IC_VEX_W_OPSIZE) ||
150226633Sdim           (VEX_LIG && inheritsFrom(child, IC_VEX_L_OPSIZE));
151226633Sdim  case IC_VEX_W:
152261991Sdim    return VEX_LIG && inheritsFrom(child, IC_VEX_L_W);
153226633Sdim  case IC_VEX_W_XS:
154261991Sdim    return VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XS);
155226633Sdim  case IC_VEX_W_XD:
156261991Sdim    return VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XD);
157226633Sdim  case IC_VEX_W_OPSIZE:
158261991Sdim    return VEX_LIG && inheritsFrom(child, IC_VEX_L_W_OPSIZE);
159221345Sdim  case IC_VEX_L:
160261991Sdim    return inheritsFrom(child, IC_VEX_L_W);
161221345Sdim  case IC_VEX_L_XS:
162261991Sdim    return inheritsFrom(child, IC_VEX_L_W_XS);
163221345Sdim  case IC_VEX_L_XD:
164261991Sdim    return inheritsFrom(child, IC_VEX_L_W_XD);
165226633Sdim  case IC_VEX_L_OPSIZE:
166234353Sdim    return inheritsFrom(child, IC_VEX_L_W_OPSIZE);
167261991Sdim  case IC_VEX_L_W:
168261991Sdim  case IC_VEX_L_W_XS:
169261991Sdim  case IC_VEX_L_W_XD:
170234353Sdim  case IC_VEX_L_W_OPSIZE:
171221345Sdim    return false;
172261991Sdim  case IC_EVEX:
173261991Sdim    return inheritsFrom(child, IC_EVEX_W) ||
174261991Sdim           inheritsFrom(child, IC_EVEX_L_W);
175261991Sdim  case IC_EVEX_XS:
176261991Sdim    return inheritsFrom(child, IC_EVEX_W_XS) ||
177261991Sdim           inheritsFrom(child, IC_EVEX_L_W_XS);
178261991Sdim  case IC_EVEX_XD:
179261991Sdim    return inheritsFrom(child, IC_EVEX_W_XD) ||
180261991Sdim           inheritsFrom(child, IC_EVEX_L_W_XD);
181261991Sdim  case IC_EVEX_OPSIZE:
182261991Sdim    return inheritsFrom(child, IC_EVEX_W_OPSIZE) ||
183261991Sdim           inheritsFrom(child, IC_EVEX_L_W_OPSIZE);
184280031Sdim  case IC_EVEX_B:
185280031Sdim    return false;
186261991Sdim  case IC_EVEX_W:
187261991Sdim  case IC_EVEX_W_XS:
188261991Sdim  case IC_EVEX_W_XD:
189261991Sdim  case IC_EVEX_W_OPSIZE:
190261991Sdim    return false;
191261991Sdim  case IC_EVEX_L:
192280031Sdim  case IC_EVEX_L_K_B:
193280031Sdim  case IC_EVEX_L_KZ_B:
194280031Sdim  case IC_EVEX_L_B:
195261991Sdim  case IC_EVEX_L_XS:
196261991Sdim  case IC_EVEX_L_XD:
197261991Sdim  case IC_EVEX_L_OPSIZE:
198261991Sdim    return false;
199261991Sdim  case IC_EVEX_L_W:
200261991Sdim  case IC_EVEX_L_W_XS:
201261991Sdim  case IC_EVEX_L_W_XD:
202261991Sdim  case IC_EVEX_L_W_OPSIZE:
203261991Sdim    return false;
204261991Sdim  case IC_EVEX_L2:
205261991Sdim  case IC_EVEX_L2_XS:
206261991Sdim  case IC_EVEX_L2_XD:
207261991Sdim  case IC_EVEX_L2_OPSIZE:
208261991Sdim    return false;
209261991Sdim  case IC_EVEX_L2_W:
210261991Sdim  case IC_EVEX_L2_W_XS:
211261991Sdim  case IC_EVEX_L2_W_XD:
212261991Sdim  case IC_EVEX_L2_W_OPSIZE:
213261991Sdim    return false;
214261991Sdim  case IC_EVEX_K:
215261991Sdim    return inheritsFrom(child, IC_EVEX_W_K) ||
216261991Sdim           inheritsFrom(child, IC_EVEX_L_W_K);
217261991Sdim  case IC_EVEX_XS_K:
218261991Sdim    return inheritsFrom(child, IC_EVEX_W_XS_K) ||
219261991Sdim           inheritsFrom(child, IC_EVEX_L_W_XS_K);
220261991Sdim  case IC_EVEX_XD_K:
221261991Sdim    return inheritsFrom(child, IC_EVEX_W_XD_K) ||
222261991Sdim           inheritsFrom(child, IC_EVEX_L_W_XD_K);
223280031Sdim  case IC_EVEX_K_B:
224280031Sdim  case IC_EVEX_KZ:
225280031Sdim    return false;
226280031Sdim  case IC_EVEX_XS_KZ:
227280031Sdim    return inheritsFrom(child, IC_EVEX_W_XS_KZ) ||
228280031Sdim           inheritsFrom(child, IC_EVEX_L_W_XS_KZ);
229280031Sdim  case IC_EVEX_XD_KZ:
230280031Sdim    return inheritsFrom(child, IC_EVEX_W_XD_KZ) ||
231280031Sdim           inheritsFrom(child, IC_EVEX_L_W_XD_KZ);
232280031Sdim  case IC_EVEX_KZ_B:
233261991Sdim  case IC_EVEX_OPSIZE_K:
234276479Sdim  case IC_EVEX_OPSIZE_B:
235280031Sdim  case IC_EVEX_OPSIZE_K_B:
236280031Sdim  case IC_EVEX_OPSIZE_KZ:
237280031Sdim  case IC_EVEX_OPSIZE_KZ_B:
238276479Sdim    return false;
239261991Sdim  case IC_EVEX_W_K:
240261991Sdim  case IC_EVEX_W_XS_K:
241261991Sdim  case IC_EVEX_W_XD_K:
242261991Sdim  case IC_EVEX_W_OPSIZE_K:
243276479Sdim  case IC_EVEX_W_OPSIZE_B:
244280031Sdim  case IC_EVEX_W_OPSIZE_K_B:
245261991Sdim    return false;
246261991Sdim  case IC_EVEX_L_K:
247261991Sdim  case IC_EVEX_L_XS_K:
248261991Sdim  case IC_EVEX_L_XD_K:
249261991Sdim  case IC_EVEX_L_OPSIZE_K:
250280031Sdim  case IC_EVEX_L_OPSIZE_B:
251280031Sdim  case IC_EVEX_L_OPSIZE_K_B:
252261991Sdim    return false;
253261991Sdim  case IC_EVEX_W_KZ:
254261991Sdim  case IC_EVEX_W_XS_KZ:
255261991Sdim  case IC_EVEX_W_XD_KZ:
256261991Sdim  case IC_EVEX_W_OPSIZE_KZ:
257280031Sdim  case IC_EVEX_W_OPSIZE_KZ_B:
258261991Sdim    return false;
259261991Sdim  case IC_EVEX_L_KZ:
260261991Sdim  case IC_EVEX_L_XS_KZ:
261261991Sdim  case IC_EVEX_L_XD_KZ:
262261991Sdim  case IC_EVEX_L_OPSIZE_KZ:
263280031Sdim  case IC_EVEX_L_OPSIZE_KZ_B:
264261991Sdim    return false;
265261991Sdim  case IC_EVEX_L_W_K:
266261991Sdim  case IC_EVEX_L_W_XS_K:
267261991Sdim  case IC_EVEX_L_W_XD_K:
268261991Sdim  case IC_EVEX_L_W_OPSIZE_K:
269280031Sdim  case IC_EVEX_L_W_OPSIZE_B:
270280031Sdim  case IC_EVEX_L_W_OPSIZE_K_B:
271261991Sdim  case IC_EVEX_L_W_KZ:
272261991Sdim  case IC_EVEX_L_W_XS_KZ:
273261991Sdim  case IC_EVEX_L_W_XD_KZ:
274261991Sdim  case IC_EVEX_L_W_OPSIZE_KZ:
275280031Sdim  case IC_EVEX_L_W_OPSIZE_KZ_B:
276261991Sdim    return false;
277261991Sdim  case IC_EVEX_L2_K:
278261991Sdim  case IC_EVEX_L2_B:
279276479Sdim  case IC_EVEX_L2_K_B:
280276479Sdim  case IC_EVEX_L2_KZ_B:
281261991Sdim  case IC_EVEX_L2_XS_K:
282276479Sdim  case IC_EVEX_L2_XS_B:
283276479Sdim  case IC_EVEX_L2_XD_B:
284261991Sdim  case IC_EVEX_L2_XD_K:
285261991Sdim  case IC_EVEX_L2_OPSIZE_K:
286261991Sdim  case IC_EVEX_L2_OPSIZE_B:
287261991Sdim  case IC_EVEX_L2_OPSIZE_K_B:
288261991Sdim  case IC_EVEX_L2_KZ:
289261991Sdim  case IC_EVEX_L2_XS_KZ:
290261991Sdim  case IC_EVEX_L2_XD_KZ:
291261991Sdim  case IC_EVEX_L2_OPSIZE_KZ:
292261991Sdim  case IC_EVEX_L2_OPSIZE_KZ_B:
293261991Sdim    return false;
294261991Sdim  case IC_EVEX_L2_W_K:
295261991Sdim  case IC_EVEX_L2_W_B:
296261991Sdim  case IC_EVEX_L2_W_XS_K:
297261991Sdim  case IC_EVEX_L2_W_XD_K:
298276479Sdim  case IC_EVEX_L2_W_XD_B:
299261991Sdim  case IC_EVEX_L2_W_OPSIZE_K:
300261991Sdim  case IC_EVEX_L2_W_OPSIZE_B:
301261991Sdim  case IC_EVEX_L2_W_OPSIZE_K_B:
302261991Sdim  case IC_EVEX_L2_W_KZ:
303261991Sdim  case IC_EVEX_L2_W_XS_KZ:
304261991Sdim  case IC_EVEX_L2_W_XD_KZ:
305261991Sdim  case IC_EVEX_L2_W_OPSIZE_KZ:
306261991Sdim  case IC_EVEX_L2_W_OPSIZE_KZ_B:
307261991Sdim    return false;
308201360Srdivacky  default:
309276479Sdim    errs() << "Unknown instruction class: " <<
310276479Sdim      stringForContext((InstructionContext)parent) << "\n";
311226633Sdim    llvm_unreachable("Unknown instruction class");
312201360Srdivacky  }
313201360Srdivacky}
314201360Srdivacky
315201360Srdivacky/// outranks - Indicates whether, if an instruction has two different applicable
316201360Srdivacky///   classes, which class should be preferred when performing decode.  This
317201360Srdivacky///   imposes a total ordering (ties are resolved toward "lower")
318201360Srdivacky///
319201360Srdivacky/// @param upper  - The class that may be preferable
320201360Srdivacky/// @param lower  - The class that may be less preferable
321201360Srdivacky/// @return       - True if upper is to be preferred, false otherwise.
322239462Sdimstatic inline bool outranks(InstructionContext upper,
323201360Srdivacky                            InstructionContext lower) {
324201360Srdivacky  assert(upper < IC_max);
325201360Srdivacky  assert(lower < IC_max);
326239462Sdim
327201360Srdivacky#define ENUM_ENTRY(n, r, d) r,
328261991Sdim#define ENUM_ENTRY_K_B(n, r, d) ENUM_ENTRY(n, r, d) \
329261991Sdim  ENUM_ENTRY(n##_K_B, r, d) ENUM_ENTRY(n##_KZ_B, r, d) \
330261991Sdim  ENUM_ENTRY(n##_KZ, r, d) ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d)
331201360Srdivacky  static int ranks[IC_max] = {
332201360Srdivacky    INSTRUCTION_CONTEXTS
333201360Srdivacky  };
334201360Srdivacky#undef ENUM_ENTRY
335261991Sdim#undef ENUM_ENTRY_K_B
336239462Sdim
337201360Srdivacky  return (ranks[upper] > ranks[lower]);
338201360Srdivacky}
339201360Srdivacky
340201360Srdivacky/// getDecisionType - Determines whether a ModRM decision with 255 entries can
341201360Srdivacky///   be compacted by eliminating redundant information.
342201360Srdivacky///
343201360Srdivacky/// @param decision - The decision to be compacted.
344201360Srdivacky/// @return         - The compactest available representation for the decision.
345239462Sdimstatic ModRMDecisionType getDecisionType(ModRMDecision &decision) {
346201360Srdivacky  bool satisfiesOneEntry = true;
347201360Srdivacky  bool satisfiesSplitRM = true;
348234353Sdim  bool satisfiesSplitReg = true;
349243830Sdim  bool satisfiesSplitMisc = true;
350234353Sdim
351239462Sdim  for (unsigned index = 0; index < 256; ++index) {
352201360Srdivacky    if (decision.instructionIDs[index] != decision.instructionIDs[0])
353201360Srdivacky      satisfiesOneEntry = false;
354234353Sdim
355201360Srdivacky    if (((index & 0xc0) == 0xc0) &&
356201360Srdivacky       (decision.instructionIDs[index] != decision.instructionIDs[0xc0]))
357201360Srdivacky      satisfiesSplitRM = false;
358234353Sdim
359201360Srdivacky    if (((index & 0xc0) != 0xc0) &&
360201360Srdivacky       (decision.instructionIDs[index] != decision.instructionIDs[0x00]))
361201360Srdivacky      satisfiesSplitRM = false;
362234353Sdim
363234353Sdim    if (((index & 0xc0) == 0xc0) &&
364234353Sdim       (decision.instructionIDs[index] != decision.instructionIDs[index&0xf8]))
365234353Sdim      satisfiesSplitReg = false;
366234353Sdim
367234353Sdim    if (((index & 0xc0) != 0xc0) &&
368234353Sdim       (decision.instructionIDs[index] != decision.instructionIDs[index&0x38]))
369243830Sdim      satisfiesSplitMisc = false;
370201360Srdivacky  }
371234353Sdim
372201360Srdivacky  if (satisfiesOneEntry)
373201360Srdivacky    return MODRM_ONEENTRY;
374234353Sdim
375201360Srdivacky  if (satisfiesSplitRM)
376201360Srdivacky    return MODRM_SPLITRM;
377234353Sdim
378243830Sdim  if (satisfiesSplitReg && satisfiesSplitMisc)
379234353Sdim    return MODRM_SPLITREG;
380234353Sdim
381243830Sdim  if (satisfiesSplitMisc)
382243830Sdim    return MODRM_SPLITMISC;
383243830Sdim
384201360Srdivacky  return MODRM_FULL;
385201360Srdivacky}
386201360Srdivacky
387201360Srdivacky/// stringForDecisionType - Returns a statically-allocated string corresponding
388201360Srdivacky///   to a particular decision type.
389201360Srdivacky///
390201360Srdivacky/// @param dt - The decision type.
391239462Sdim/// @return   - A pointer to the statically-allocated string (e.g.,
392201360Srdivacky///             "MODRM_ONEENTRY" for MODRM_ONEENTRY).
393239462Sdimstatic const char* stringForDecisionType(ModRMDecisionType dt) {
394201360Srdivacky#define ENUM_ENTRY(n) case n: return #n;
395201360Srdivacky  switch (dt) {
396201360Srdivacky    default:
397239462Sdim      llvm_unreachable("Unknown decision type");
398201360Srdivacky    MODRMTYPES
399239462Sdim  };
400201360Srdivacky#undef ENUM_ENTRY
401201360Srdivacky}
402239462Sdim
403201360SrdivackyDisassemblerTables::DisassemblerTables() {
404201360Srdivacky  unsigned i;
405239462Sdim
406221345Sdim  for (i = 0; i < array_lengthof(Tables); i++) {
407201360Srdivacky    Tables[i] = new ContextDecision;
408201360Srdivacky    memset(Tables[i], 0, sizeof(ContextDecision));
409201360Srdivacky  }
410239462Sdim
411201360Srdivacky  HasConflicts = false;
412201360Srdivacky}
413239462Sdim
414201360SrdivackyDisassemblerTables::~DisassemblerTables() {
415201360Srdivacky  unsigned i;
416239462Sdim
417221345Sdim  for (i = 0; i < array_lengthof(Tables); i++)
418201360Srdivacky    delete Tables[i];
419201360Srdivacky}
420239462Sdim
421239462Sdimvoid DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
422239462Sdim                                           unsigned &i1, unsigned &i2,
423261991Sdim                                           unsigned &ModRMTableNum,
424239462Sdim                                           ModRMDecision &decision) const {
425239462Sdim  static uint32_t sTableNumber = 0;
426239462Sdim  static uint32_t sEntryNumber = 1;
427201360Srdivacky  ModRMDecisionType dt = getDecisionType(decision);
428234353Sdim
429201360Srdivacky  if (dt == MODRM_ONEENTRY && decision.instructionIDs[0] == 0)
430201360Srdivacky  {
431201360Srdivacky    o2.indent(i2) << "{ /* ModRMDecision */" << "\n";
432201360Srdivacky    i2++;
433234353Sdim
434201360Srdivacky    o2.indent(i2) << stringForDecisionType(dt) << "," << "\n";
435234353Sdim    o2.indent(i2) << 0 << " /* EmptyTable */\n";
436234353Sdim
437201360Srdivacky    i2--;
438201360Srdivacky    o2.indent(i2) << "}";
439201360Srdivacky    return;
440201360Srdivacky  }
441234353Sdim
442261991Sdim  std::vector<unsigned> ModRMDecision;
443234353Sdim
444201360Srdivacky  switch (dt) {
445201360Srdivacky    default:
446201360Srdivacky      llvm_unreachable("Unknown decision type");
447201360Srdivacky    case MODRM_ONEENTRY:
448261991Sdim      ModRMDecision.push_back(decision.instructionIDs[0]);
449201360Srdivacky      break;
450201360Srdivacky    case MODRM_SPLITRM:
451261991Sdim      ModRMDecision.push_back(decision.instructionIDs[0x00]);
452261991Sdim      ModRMDecision.push_back(decision.instructionIDs[0xc0]);
453201360Srdivacky      break;
454234353Sdim    case MODRM_SPLITREG:
455239462Sdim      for (unsigned index = 0; index < 64; index += 8)
456261991Sdim        ModRMDecision.push_back(decision.instructionIDs[index]);
457239462Sdim      for (unsigned index = 0xc0; index < 256; index += 8)
458261991Sdim        ModRMDecision.push_back(decision.instructionIDs[index]);
459234353Sdim      break;
460243830Sdim    case MODRM_SPLITMISC:
461243830Sdim      for (unsigned index = 0; index < 64; index += 8)
462261991Sdim        ModRMDecision.push_back(decision.instructionIDs[index]);
463243830Sdim      for (unsigned index = 0xc0; index < 256; ++index)
464261991Sdim        ModRMDecision.push_back(decision.instructionIDs[index]);
465243830Sdim      break;
466201360Srdivacky    case MODRM_FULL:
467239462Sdim      for (unsigned index = 0; index < 256; ++index)
468261991Sdim        ModRMDecision.push_back(decision.instructionIDs[index]);
469234353Sdim      break;
470201360Srdivacky  }
471201360Srdivacky
472261991Sdim  unsigned &EntryNumber = ModRMTable[ModRMDecision];
473261991Sdim  if (EntryNumber == 0) {
474261991Sdim    EntryNumber = ModRMTableNum;
475234353Sdim
476261991Sdim    ModRMTableNum += ModRMDecision.size();
477261991Sdim    o1 << "/* Table" << EntryNumber << " */\n";
478261991Sdim    i1++;
479261991Sdim    for (std::vector<unsigned>::const_iterator I = ModRMDecision.begin(),
480261991Sdim           E = ModRMDecision.end(); I != E; ++I) {
481261991Sdim      o1.indent(i1 * 2) << format("0x%hx", *I) << ", /* "
482261991Sdim                        << InstructionSpecifiers[*I].name << " */\n";
483261991Sdim    }
484261991Sdim    i1--;
485261991Sdim  }
486261991Sdim
487234353Sdim  o2.indent(i2) << "{ /* struct ModRMDecision */" << "\n";
488234353Sdim  i2++;
489234353Sdim
490234353Sdim  o2.indent(i2) << stringForDecisionType(dt) << "," << "\n";
491261991Sdim  o2.indent(i2) << EntryNumber << " /* Table" << EntryNumber << " */\n";
492234353Sdim
493234353Sdim  i2--;
494234353Sdim  o2.indent(i2) << "}";
495234353Sdim
496201360Srdivacky  switch (dt) {
497201360Srdivacky    default:
498201360Srdivacky      llvm_unreachable("Unknown decision type");
499201360Srdivacky    case MODRM_ONEENTRY:
500234353Sdim      sEntryNumber += 1;
501201360Srdivacky      break;
502201360Srdivacky    case MODRM_SPLITRM:
503234353Sdim      sEntryNumber += 2;
504201360Srdivacky      break;
505234353Sdim    case MODRM_SPLITREG:
506234353Sdim      sEntryNumber += 16;
507234353Sdim      break;
508243830Sdim    case MODRM_SPLITMISC:
509243830Sdim      sEntryNumber += 8 + 64;
510243830Sdim      break;
511201360Srdivacky    case MODRM_FULL:
512234353Sdim      sEntryNumber += 256;
513201360Srdivacky      break;
514201360Srdivacky  }
515234353Sdim
516243830Sdim  // We assume that the index can fit into uint16_t.
517243830Sdim  assert(sEntryNumber < 65536U &&
518243830Sdim         "Index into ModRMDecision is too large for uint16_t!");
519243830Sdim
520201360Srdivacky  ++sTableNumber;
521201360Srdivacky}
522201360Srdivacky
523239462Sdimvoid DisassemblerTables::emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
524239462Sdim                                            unsigned &i1, unsigned &i2,
525261991Sdim                                            unsigned &ModRMTableNum,
526239462Sdim                                            OpcodeDecision &decision) const {
527201360Srdivacky  o2.indent(i2) << "{ /* struct OpcodeDecision */" << "\n";
528201360Srdivacky  i2++;
529201360Srdivacky  o2.indent(i2) << "{" << "\n";
530201360Srdivacky  i2++;
531201360Srdivacky
532239462Sdim  for (unsigned index = 0; index < 256; ++index) {
533201360Srdivacky    o2.indent(i2);
534201360Srdivacky
535201360Srdivacky    o2 << "/* 0x" << format("%02hhx", index) << " */" << "\n";
536201360Srdivacky
537261991Sdim    emitModRMDecision(o1, o2, i1, i2, ModRMTableNum,
538261991Sdim                      decision.modRMDecisions[index]);
539201360Srdivacky
540201360Srdivacky    if (index <  255)
541201360Srdivacky      o2 << ",";
542201360Srdivacky
543201360Srdivacky    o2 << "\n";
544201360Srdivacky  }
545201360Srdivacky
546201360Srdivacky  i2--;
547201360Srdivacky  o2.indent(i2) << "}" << "\n";
548201360Srdivacky  i2--;
549201360Srdivacky  o2.indent(i2) << "}" << "\n";
550201360Srdivacky}
551201360Srdivacky
552239462Sdimvoid DisassemblerTables::emitContextDecision(raw_ostream &o1, raw_ostream &o2,
553239462Sdim                                             unsigned &i1, unsigned &i2,
554261991Sdim                                             unsigned &ModRMTableNum,
555239462Sdim                                             ContextDecision &decision,
556239462Sdim                                             const char* name) const {
557218893Sdim  o2.indent(i2) << "static const struct ContextDecision " << name << " = {\n";
558201360Srdivacky  i2++;
559201360Srdivacky  o2.indent(i2) << "{ /* opcodeDecisions */" << "\n";
560201360Srdivacky  i2++;
561201360Srdivacky
562239462Sdim  for (unsigned index = 0; index < IC_max; ++index) {
563201360Srdivacky    o2.indent(i2) << "/* ";
564201360Srdivacky    o2 << stringForContext((InstructionContext)index);
565201360Srdivacky    o2 << " */";
566201360Srdivacky    o2 << "\n";
567201360Srdivacky
568261991Sdim    emitOpcodeDecision(o1, o2, i1, i2, ModRMTableNum,
569261991Sdim                       decision.opcodeDecisions[index]);
570201360Srdivacky
571201360Srdivacky    if (index + 1 < IC_max)
572201360Srdivacky      o2 << ", ";
573201360Srdivacky  }
574201360Srdivacky
575201360Srdivacky  i2--;
576201360Srdivacky  o2.indent(i2) << "}" << "\n";
577201360Srdivacky  i2--;
578201360Srdivacky  o2.indent(i2) << "};" << "\n";
579201360Srdivacky}
580201360Srdivacky
581239462Sdimvoid DisassemblerTables::emitInstructionInfo(raw_ostream &o,
582239462Sdim                                             unsigned &i) const {
583239462Sdim  unsigned NumInstructions = InstructionSpecifiers.size();
584239462Sdim
585239462Sdim  o << "static const struct OperandSpecifier x86OperandSets[]["
586239462Sdim    << X86_MAX_OPERANDS << "] = {\n";
587239462Sdim
588239462Sdim  typedef std::vector<std::pair<const char *, const char *> > OperandListTy;
589239462Sdim  std::map<OperandListTy, unsigned> OperandSets;
590239462Sdim
591239462Sdim  unsigned OperandSetNum = 0;
592239462Sdim  for (unsigned Index = 0; Index < NumInstructions; ++Index) {
593239462Sdim    OperandListTy OperandList;
594239462Sdim
595239462Sdim    for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
596239462Sdim         ++OperandIndex) {
597239462Sdim      const char *Encoding =
598239462Sdim        stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[Index]
599239462Sdim                                 .operands[OperandIndex].encoding);
600239462Sdim      const char *Type =
601239462Sdim        stringForOperandType((OperandType)InstructionSpecifiers[Index]
602239462Sdim                             .operands[OperandIndex].type);
603239462Sdim      OperandList.push_back(std::make_pair(Encoding, Type));
604239462Sdim    }
605239462Sdim    unsigned &N = OperandSets[OperandList];
606239462Sdim    if (N != 0) continue;
607239462Sdim
608239462Sdim    N = ++OperandSetNum;
609239462Sdim
610239462Sdim    o << "  { /* " << (OperandSetNum - 1) << " */\n";
611239462Sdim    for (unsigned i = 0, e = OperandList.size(); i != e; ++i) {
612239462Sdim      o << "    { " << OperandList[i].first << ", "
613239462Sdim        << OperandList[i].second << " },\n";
614239462Sdim    }
615239462Sdim    o << "  },\n";
616239462Sdim  }
617239462Sdim  o << "};" << "\n\n";
618239462Sdim
619218893Sdim  o.indent(i * 2) << "static const struct InstructionSpecifier ";
620218893Sdim  o << INSTRUCTIONS_STR "[" << InstructionSpecifiers.size() << "] = {\n";
621239462Sdim
622201360Srdivacky  i++;
623201360Srdivacky
624239462Sdim  for (unsigned index = 0; index < NumInstructions; ++index) {
625201360Srdivacky    o.indent(i * 2) << "{ /* " << index << " */" << "\n";
626201360Srdivacky    i++;
627234353Sdim
628239462Sdim    OperandListTy OperandList;
629239462Sdim    for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
630239462Sdim         ++OperandIndex) {
631239462Sdim      const char *Encoding =
632239462Sdim        stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[index]
633239462Sdim                                 .operands[OperandIndex].encoding);
634239462Sdim      const char *Type =
635239462Sdim        stringForOperandType((OperandType)InstructionSpecifiers[index]
636239462Sdim                             .operands[OperandIndex].type);
637239462Sdim      OperandList.push_back(std::make_pair(Encoding, Type));
638201360Srdivacky    }
639239462Sdim    o.indent(i * 2) << (OperandSets[OperandList] - 1) << ",\n";
640201360Srdivacky
641234353Sdim    o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */";
642201360Srdivacky    o << "\n";
643201360Srdivacky
644201360Srdivacky    i--;
645201360Srdivacky    o.indent(i * 2) << "}";
646201360Srdivacky
647239462Sdim    if (index + 1 < NumInstructions)
648201360Srdivacky      o << ",";
649201360Srdivacky
650201360Srdivacky    o << "\n";
651201360Srdivacky  }
652201360Srdivacky
653201360Srdivacky  i--;
654201360Srdivacky  o.indent(i * 2) << "};" << "\n";
655201360Srdivacky}
656201360Srdivacky
657239462Sdimvoid DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
658276479Sdim  const unsigned int tableSize = 16384;
659239462Sdim  o.indent(i * 2) << "static const uint8_t " CONTEXTS_STR
660276479Sdim                     "[" << tableSize << "] = {\n";
661201360Srdivacky  i++;
662201360Srdivacky
663276479Sdim  for (unsigned index = 0; index < tableSize; ++index) {
664201360Srdivacky    o.indent(i * 2);
665201360Srdivacky
666276479Sdim    if (index & ATTR_EVEX) {
667276479Sdim      o << "IC_EVEX";
668276479Sdim      if (index & ATTR_EVEXL2)
669276479Sdim        o << "_L2";
670276479Sdim      else if (index & ATTR_EVEXL)
671276479Sdim        o << "_L";
672276479Sdim      if (index & ATTR_REXW)
673276479Sdim        o << "_W";
674276479Sdim      if (index & ATTR_OPSIZE)
675276479Sdim        o << "_OPSIZE";
676276479Sdim      else if (index & ATTR_XD)
677276479Sdim        o << "_XD";
678276479Sdim      else if (index & ATTR_XS)
679276479Sdim        o << "_XS";
680276479Sdim      if (index & ATTR_EVEXKZ)
681276479Sdim        o << "_KZ";
682276479Sdim      else if (index & ATTR_EVEXK)
683276479Sdim        o << "_K";
684276479Sdim      if (index & ATTR_EVEXB)
685276479Sdim        o << "_B";
686276479Sdim    }
687276479Sdim    else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
688234353Sdim      o << "IC_VEX_L_W_OPSIZE";
689261991Sdim    else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XD))
690261991Sdim      o << "IC_VEX_L_W_XD";
691261991Sdim    else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XS))
692261991Sdim      o << "IC_VEX_L_W_XS";
693261991Sdim    else if ((index & ATTR_VEXL) && (index & ATTR_REXW))
694261991Sdim      o << "IC_VEX_L_W";
695234353Sdim    else if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE))
696221345Sdim      o << "IC_VEX_L_OPSIZE";
697221345Sdim    else if ((index & ATTR_VEXL) && (index & ATTR_XD))
698221345Sdim      o << "IC_VEX_L_XD";
699221345Sdim    else if ((index & ATTR_VEXL) && (index & ATTR_XS))
700221345Sdim      o << "IC_VEX_L_XS";
701221345Sdim    else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
702221345Sdim      o << "IC_VEX_W_OPSIZE";
703221345Sdim    else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XD))
704221345Sdim      o << "IC_VEX_W_XD";
705221345Sdim    else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XS))
706221345Sdim      o << "IC_VEX_W_XS";
707221345Sdim    else if (index & ATTR_VEXL)
708221345Sdim      o << "IC_VEX_L";
709221345Sdim    else if ((index & ATTR_VEX) && (index & ATTR_REXW))
710221345Sdim      o << "IC_VEX_W";
711221345Sdim    else if ((index & ATTR_VEX) && (index & ATTR_OPSIZE))
712221345Sdim      o << "IC_VEX_OPSIZE";
713221345Sdim    else if ((index & ATTR_VEX) && (index & ATTR_XD))
714221345Sdim      o << "IC_VEX_XD";
715221345Sdim    else if ((index & ATTR_VEX) && (index & ATTR_XS))
716221345Sdim      o << "IC_VEX_XS";
717226633Sdim    else if (index & ATTR_VEX)
718226633Sdim      o << "IC_VEX";
719221345Sdim    else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS))
720201360Srdivacky      o << "IC_64BIT_REXW_XS";
721201360Srdivacky    else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD))
722201360Srdivacky      o << "IC_64BIT_REXW_XD";
723239462Sdim    else if ((index & ATTR_64BIT) && (index & ATTR_REXW) &&
724201360Srdivacky             (index & ATTR_OPSIZE))
725201360Srdivacky      o << "IC_64BIT_REXW_OPSIZE";
726280031Sdim    else if ((index & ATTR_64BIT) && (index & ATTR_REXW) &&
727280031Sdim             (index & ATTR_ADSIZE))
728280031Sdim      o << "IC_64BIT_REXW_ADSIZE";
729226633Sdim    else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE))
730226633Sdim      o << "IC_64BIT_XD_OPSIZE";
731226633Sdim    else if ((index & ATTR_64BIT) && (index & ATTR_XS) && (index & ATTR_OPSIZE))
732226633Sdim      o << "IC_64BIT_XS_OPSIZE";
733201360Srdivacky    else if ((index & ATTR_64BIT) && (index & ATTR_XS))
734201360Srdivacky      o << "IC_64BIT_XS";
735201360Srdivacky    else if ((index & ATTR_64BIT) && (index & ATTR_XD))
736201360Srdivacky      o << "IC_64BIT_XD";
737280031Sdim    else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE) &&
738280031Sdim             (index & ATTR_ADSIZE))
739280031Sdim      o << "IC_64BIT_OPSIZE_ADSIZE";
740201360Srdivacky    else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE))
741201360Srdivacky      o << "IC_64BIT_OPSIZE";
742234353Sdim    else if ((index & ATTR_64BIT) && (index & ATTR_ADSIZE))
743234353Sdim      o << "IC_64BIT_ADSIZE";
744201360Srdivacky    else if ((index & ATTR_64BIT) && (index & ATTR_REXW))
745201360Srdivacky      o << "IC_64BIT_REXW";
746201360Srdivacky    else if ((index & ATTR_64BIT))
747201360Srdivacky      o << "IC_64BIT";
748226633Sdim    else if ((index & ATTR_XS) && (index & ATTR_OPSIZE))
749226633Sdim      o << "IC_XS_OPSIZE";
750226633Sdim    else if ((index & ATTR_XD) && (index & ATTR_OPSIZE))
751226633Sdim      o << "IC_XD_OPSIZE";
752201360Srdivacky    else if (index & ATTR_XS)
753201360Srdivacky      o << "IC_XS";
754201360Srdivacky    else if (index & ATTR_XD)
755201360Srdivacky      o << "IC_XD";
756280031Sdim    else if ((index & ATTR_OPSIZE) && (index & ATTR_ADSIZE))
757280031Sdim      o << "IC_OPSIZE_ADSIZE";
758201360Srdivacky    else if (index & ATTR_OPSIZE)
759201360Srdivacky      o << "IC_OPSIZE";
760234353Sdim    else if (index & ATTR_ADSIZE)
761234353Sdim      o << "IC_ADSIZE";
762201360Srdivacky    else
763201360Srdivacky      o << "IC";
764201360Srdivacky
765276479Sdim    if (index < tableSize - 1)
766201360Srdivacky      o << ",";
767201360Srdivacky    else
768201360Srdivacky      o << " ";
769201360Srdivacky
770201360Srdivacky    o << " /* " << index << " */";
771201360Srdivacky
772201360Srdivacky    o << "\n";
773201360Srdivacky  }
774201360Srdivacky
775201360Srdivacky  i--;
776201360Srdivacky  o.indent(i * 2) << "};" << "\n";
777201360Srdivacky}
778201360Srdivacky
779239462Sdimvoid DisassemblerTables::emitContextDecisions(raw_ostream &o1, raw_ostream &o2,
780261991Sdim                                              unsigned &i1, unsigned &i2,
781261991Sdim                                              unsigned &ModRMTableNum) const {
782261991Sdim  emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[0], ONEBYTE_STR);
783261991Sdim  emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[1], TWOBYTE_STR);
784261991Sdim  emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[2], THREEBYTE38_STR);
785261991Sdim  emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[3], THREEBYTE3A_STR);
786276479Sdim  emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[4], XOP8_MAP_STR);
787276479Sdim  emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[5], XOP9_MAP_STR);
788276479Sdim  emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[6], XOPA_MAP_STR);
789201360Srdivacky}
790201360Srdivacky
791201360Srdivackyvoid DisassemblerTables::emit(raw_ostream &o) const {
792239462Sdim  unsigned i1 = 0;
793239462Sdim  unsigned i2 = 0;
794239462Sdim
795201360Srdivacky  std::string s1;
796201360Srdivacky  std::string s2;
797239462Sdim
798201360Srdivacky  raw_string_ostream o1(s1);
799201360Srdivacky  raw_string_ostream o2(s2);
800239462Sdim
801201360Srdivacky  emitInstructionInfo(o, i2);
802201360Srdivacky  o << "\n";
803201360Srdivacky
804201360Srdivacky  emitContextTable(o, i2);
805201360Srdivacky  o << "\n";
806234353Sdim
807261991Sdim  unsigned ModRMTableNum = 0;
808261991Sdim
809234353Sdim  o << "static const InstrUID modRMTable[] = {\n";
810234353Sdim  i1++;
811261991Sdim  std::vector<unsigned> EmptyTable(1, 0);
812261991Sdim  ModRMTable[EmptyTable] = ModRMTableNum;
813261991Sdim  ModRMTableNum += EmptyTable.size();
814261991Sdim  o1 << "/* EmptyTable */\n";
815261991Sdim  o1.indent(i1 * 2) << "0x0,\n";
816234353Sdim  i1--;
817261991Sdim  emitContextDecisions(o1, o2, i1, i2, ModRMTableNum);
818234353Sdim
819201360Srdivacky  o << o1.str();
820234353Sdim  o << "  0x0\n";
821234353Sdim  o << "};\n";
822201360Srdivacky  o << "\n";
823201360Srdivacky  o << o2.str();
824201360Srdivacky  o << "\n";
825201360Srdivacky  o << "\n";
826201360Srdivacky}
827201360Srdivacky
828201360Srdivackyvoid DisassemblerTables::setTableFields(ModRMDecision     &decision,
829201360Srdivacky                                        const ModRMFilter &filter,
830201360Srdivacky                                        InstrUID          uid,
831201360Srdivacky                                        uint8_t           opcode) {
832239462Sdim  for (unsigned index = 0; index < 256; ++index) {
833201360Srdivacky    if (filter.accepts(index)) {
834201360Srdivacky      if (decision.instructionIDs[index] == uid)
835201360Srdivacky        continue;
836201360Srdivacky
837201360Srdivacky      if (decision.instructionIDs[index] != 0) {
838201360Srdivacky        InstructionSpecifier &newInfo =
839201360Srdivacky          InstructionSpecifiers[uid];
840201360Srdivacky        InstructionSpecifier &previousInfo =
841201360Srdivacky          InstructionSpecifiers[decision.instructionIDs[index]];
842239462Sdim
843226633Sdim        if(previousInfo.name == "NOOP" && (newInfo.name == "XCHG16ar" ||
844226633Sdim                                           newInfo.name == "XCHG32ar" ||
845226633Sdim                                           newInfo.name == "XCHG32ar64" ||
846226633Sdim                                           newInfo.name == "XCHG64ar"))
847226633Sdim          continue; // special case for XCHG*ar and NOOP
848201360Srdivacky
849201360Srdivacky        if (outranks(previousInfo.insnContext, newInfo.insnContext))
850201360Srdivacky          continue;
851239462Sdim
852276479Sdim        if (previousInfo.insnContext == newInfo.insnContext) {
853201360Srdivacky          errs() << "Error: Primary decode conflict: ";
854201360Srdivacky          errs() << newInfo.name << " would overwrite " << previousInfo.name;
855201360Srdivacky          errs() << "\n";
856201360Srdivacky          errs() << "ModRM   " << index << "\n";
857201360Srdivacky          errs() << "Opcode  " << (uint16_t)opcode << "\n";
858201360Srdivacky          errs() << "Context " << stringForContext(newInfo.insnContext) << "\n";
859201360Srdivacky          HasConflicts = true;
860201360Srdivacky        }
861201360Srdivacky      }
862201360Srdivacky
863201360Srdivacky      decision.instructionIDs[index] = uid;
864201360Srdivacky    }
865201360Srdivacky  }
866201360Srdivacky}
867201360Srdivacky
868201360Srdivackyvoid DisassemblerTables::setTableFields(OpcodeType          type,
869201360Srdivacky                                        InstructionContext  insnContext,
870201360Srdivacky                                        uint8_t             opcode,
871201360Srdivacky                                        const ModRMFilter   &filter,
872226633Sdim                                        InstrUID            uid,
873226633Sdim                                        bool                is32bit,
874280031Sdim                                        bool                ignoresVEX_L,
875280031Sdim                                        unsigned            addressSize) {
876201360Srdivacky  ContextDecision &decision = *Tables[type];
877201360Srdivacky
878239462Sdim  for (unsigned index = 0; index < IC_max; ++index) {
879280031Sdim    if ((is32bit || addressSize == 16) &&
880280031Sdim        inheritsFrom((InstructionContext)index, IC_64BIT))
881226633Sdim      continue;
882226633Sdim
883280031Sdim    bool adSize64 = addressSize == 64;
884239462Sdim    if (inheritsFrom((InstructionContext)index,
885280031Sdim                     InstructionSpecifiers[uid].insnContext, ignoresVEX_L,
886280031Sdim                     adSize64))
887239462Sdim      setTableFields(decision.opcodeDecisions[index].modRMDecisions[opcode],
888201360Srdivacky                     filter,
889201360Srdivacky                     uid,
890201360Srdivacky                     opcode);
891201360Srdivacky  }
892201360Srdivacky}
893