1 | //===- X86RecognizableInstr.cpp - Disassembler instruction spec -*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file is part of the X86 Disassembler Emitter. |
10 | // It contains the implementation of a single recognizable instruction. |
11 | // Documentation for the disassembler emitter in general can be found in |
12 | // X86DisassemblerEmitter.h. |
13 | // |
14 | //===----------------------------------------------------------------------===// |
15 | |
16 | #include "X86RecognizableInstr.h" |
17 | #include "X86DisassemblerShared.h" |
18 | #include "X86DisassemblerTables.h" |
19 | #include "X86ModRMFilters.h" |
20 | #include "llvm/ADT/StringSwitch.h" |
21 | #include "llvm/Support/ErrorHandling.h" |
22 | #include "llvm/TableGen/Record.h" |
23 | #include <string> |
24 | |
25 | using namespace llvm; |
26 | using namespace X86Disassembler; |
27 | |
28 | std::string X86Disassembler::getMnemonic(const CodeGenInstruction *I, |
29 | unsigned Variant) { |
30 | // Extract a mnemonic assuming it's separated by \t |
31 | std::string Mnemonic = |
32 | StringRef(I->FlattenAsmStringVariants(AsmString: I->AsmString, Variant)) |
33 | .take_until(F: [](char C) { return C == '\t'; }) |
34 | .str(); |
35 | |
36 | // Special case: CMOVCC, JCC, SETCC, CMPCCXADD have "${cond}" in mnemonic. |
37 | // Replace it with "CC" in-place. |
38 | auto CondPos = Mnemonic.find(s: "${cond}" ); |
39 | if (CondPos != std::string::npos) |
40 | Mnemonic = Mnemonic.replace(pos: CondPos, n1: 7, s: "CC" ); |
41 | return StringRef(Mnemonic).upper(); |
42 | } |
43 | |
44 | bool X86Disassembler::isRegisterOperand(const Record *Rec) { |
45 | return Rec->isSubClassOf(Name: "RegisterClass" ) || |
46 | Rec->isSubClassOf(Name: "RegisterOperand" ); |
47 | } |
48 | |
49 | bool X86Disassembler::isMemoryOperand(const Record *Rec) { |
50 | return Rec->isSubClassOf(Name: "Operand" ) && |
51 | Rec->getValueAsString(FieldName: "OperandType" ) == "OPERAND_MEMORY" ; |
52 | } |
53 | |
54 | bool X86Disassembler::isImmediateOperand(const Record *Rec) { |
55 | return Rec->isSubClassOf(Name: "Operand" ) && |
56 | Rec->getValueAsString(FieldName: "OperandType" ) == "OPERAND_IMMEDIATE" ; |
57 | } |
58 | |
59 | unsigned X86Disassembler::getRegOperandSize(const Record *RegRec) { |
60 | if (RegRec->isSubClassOf(Name: "RegisterClass" )) |
61 | return RegRec->getValueAsInt(FieldName: "Alignment" ); |
62 | if (RegRec->isSubClassOf(Name: "RegisterOperand" )) |
63 | return RegRec->getValueAsDef(FieldName: "RegClass" )->getValueAsInt(FieldName: "Alignment" ); |
64 | |
65 | llvm_unreachable("Register operand's size not known!" ); |
66 | } |
67 | |
68 | unsigned X86Disassembler::getMemOperandSize(const Record *MemRec) { |
69 | if (MemRec->isSubClassOf(Name: "X86MemOperand" )) |
70 | return MemRec->getValueAsInt(FieldName: "Size" ); |
71 | |
72 | llvm_unreachable("Memory operand's size not known!" ); |
73 | } |
74 | |
75 | /// byteFromBitsInit - Extracts a value at most 8 bits in width from a BitsInit. |
76 | /// Useful for switch statements and the like. |
77 | /// |
78 | /// @param init - A reference to the BitsInit to be decoded. |
79 | /// @return - The field, with the first bit in the BitsInit as the lowest |
80 | /// order bit. |
81 | static uint8_t byteFromBitsInit(const BitsInit &init) { |
82 | int width = init.getNumBits(); |
83 | |
84 | assert(width <= 8 && "Field is too large for uint8_t!" ); |
85 | |
86 | uint8_t mask = 0x01; |
87 | uint8_t ret = 0; |
88 | |
89 | for (int index = 0; index < width; index++) { |
90 | if (cast<BitInit>(Val: init.getBit(Bit: index))->getValue()) |
91 | ret |= mask; |
92 | |
93 | mask <<= 1; |
94 | } |
95 | |
96 | return ret; |
97 | } |
98 | |
99 | /// byteFromRec - Extract a value at most 8 bits in with from a Record given the |
100 | /// name of the field. |
101 | /// |
102 | /// @param rec - The record from which to extract the value. |
103 | /// @param name - The name of the field in the record. |
104 | /// @return - The field, as translated by byteFromBitsInit(). |
105 | static uint8_t byteFromRec(const Record *rec, StringRef name) { |
106 | const BitsInit *bits = rec->getValueAsBitsInit(FieldName: name); |
107 | return byteFromBitsInit(init: *bits); |
108 | } |
109 | |
110 | RecognizableInstrBase::RecognizableInstrBase(const CodeGenInstruction &insn) { |
111 | const Record *Rec = insn.TheDef; |
112 | assert(Rec->isSubClassOf("X86Inst" ) && "Not a X86 Instruction" ); |
113 | OpPrefix = byteFromRec(rec: Rec, name: "OpPrefixBits" ); |
114 | OpMap = byteFromRec(rec: Rec, name: "OpMapBits" ); |
115 | Opcode = byteFromRec(rec: Rec, name: "Opcode" ); |
116 | Form = byteFromRec(rec: Rec, name: "FormBits" ); |
117 | Encoding = byteFromRec(rec: Rec, name: "OpEncBits" ); |
118 | OpSize = byteFromRec(rec: Rec, name: "OpSizeBits" ); |
119 | AdSize = byteFromRec(rec: Rec, name: "AdSizeBits" ); |
120 | HasREX_W = Rec->getValueAsBit(FieldName: "hasREX_W" ); |
121 | HasVEX_4V = Rec->getValueAsBit(FieldName: "hasVEX_4V" ); |
122 | IgnoresW = Rec->getValueAsBit(FieldName: "IgnoresW" ); |
123 | IgnoresVEX_L = Rec->getValueAsBit(FieldName: "ignoresVEX_L" ); |
124 | HasEVEX_L2 = Rec->getValueAsBit(FieldName: "hasEVEX_L2" ); |
125 | HasEVEX_K = Rec->getValueAsBit(FieldName: "hasEVEX_K" ); |
126 | HasEVEX_KZ = Rec->getValueAsBit(FieldName: "hasEVEX_Z" ); |
127 | HasEVEX_B = Rec->getValueAsBit(FieldName: "hasEVEX_B" ); |
128 | HasEVEX_U = Rec->getValueAsBit(FieldName: "hasEVEX_U" ); |
129 | HasEVEX_NF = Rec->getValueAsBit(FieldName: "hasEVEX_NF" ); |
130 | HasTwoConditionalOps = Rec->getValueAsBit(FieldName: "hasTwoConditionalOps" ); |
131 | IsCodeGenOnly = Rec->getValueAsBit(FieldName: "isCodeGenOnly" ); |
132 | IsAsmParserOnly = Rec->getValueAsBit(FieldName: "isAsmParserOnly" ); |
133 | ForceDisassemble = Rec->getValueAsBit(FieldName: "ForceDisassemble" ); |
134 | CD8_Scale = byteFromRec(rec: Rec, name: "CD8_Scale" ); |
135 | HasVEX_L = Rec->getValueAsBit(FieldName: "hasVEX_L" ); |
136 | ExplicitREX2Prefix = |
137 | byteFromRec(rec: Rec, name: "explicitOpPrefixBits" ) == X86Local::ExplicitREX2; |
138 | |
139 | EncodeRC = HasEVEX_B && |
140 | (Form == X86Local::MRMDestReg || Form == X86Local::MRMSrcReg); |
141 | } |
142 | |
143 | bool RecognizableInstrBase::shouldBeEmitted() const { |
144 | return Form != X86Local::Pseudo && (!IsCodeGenOnly || ForceDisassemble) && |
145 | !IsAsmParserOnly; |
146 | } |
147 | |
148 | RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, |
149 | const CodeGenInstruction &insn, |
150 | InstrUID uid) |
151 | : RecognizableInstrBase(insn), Rec(insn.TheDef), Name(Rec->getName().str()), |
152 | Is32Bit(false), Is64Bit(false), Operands(&insn.Operands.OperandList), |
153 | UID(uid), Spec(&tables.specForUID(uid)) { |
154 | // Check for 64-bit inst which does not require REX |
155 | // FIXME: Is there some better way to check for In64BitMode? |
156 | for (const Record *Predicate : Rec->getValueAsListOfDefs(FieldName: "Predicates" )) { |
157 | if (Predicate->getName().contains(Other: "Not64Bit" ) || |
158 | Predicate->getName().contains(Other: "In32Bit" )) { |
159 | Is32Bit = true; |
160 | break; |
161 | } |
162 | if (Predicate->getName().contains(Other: "In64Bit" )) { |
163 | Is64Bit = true; |
164 | break; |
165 | } |
166 | } |
167 | } |
168 | |
169 | void RecognizableInstr::processInstr(DisassemblerTables &tables, |
170 | const CodeGenInstruction &insn, |
171 | InstrUID uid) { |
172 | if (!insn.TheDef->isSubClassOf(Name: "X86Inst" )) |
173 | return; |
174 | RecognizableInstr recogInstr(tables, insn, uid); |
175 | |
176 | if (!recogInstr.shouldBeEmitted()) |
177 | return; |
178 | recogInstr.emitInstructionSpecifier(); |
179 | recogInstr.emitDecodePath(tables); |
180 | } |
181 | |
182 | #define EVEX_KB(n) \ |
183 | (HasEVEX_KZ && HasEVEX_B \ |
184 | ? n##_KZ_B \ |
185 | : (HasEVEX_K && HasEVEX_B \ |
186 | ? n##_K_B \ |
187 | : (HasEVEX_KZ ? n##_KZ \ |
188 | : (HasEVEX_K ? n##_K : (HasEVEX_B ? n##_B : n))))) |
189 | |
190 | #define EVEX_NF(n) (HasEVEX_NF ? n##_NF : n) |
191 | #define EVEX_B_NF(n) (HasEVEX_B ? EVEX_NF(n##_B) : EVEX_NF(n)) |
192 | #define EVEX_KB_ADSIZE(n) AdSize == X86Local::AdSize32 ? n##_ADSIZE : EVEX_KB(n) |
193 | #define EVEX_KB_U(n) \ |
194 | (HasEVEX_KZ ? n##_KZ_B_U : (HasEVEX_K ? n##_K_B_U : n##_B_U)) |
195 | |
196 | InstructionContext RecognizableInstr::insnContext() const { |
197 | InstructionContext insnContext; |
198 | |
199 | if (Encoding == X86Local::EVEX) { |
200 | if (HasVEX_L && HasEVEX_L2) { |
201 | errs() << "Don't support VEX.L if EVEX_L2 is enabled: " << Name << "\n" ; |
202 | llvm_unreachable("Don't support VEX.L if EVEX_L2 is enabled" ); |
203 | } |
204 | if (EncodeRC && HasEVEX_U) { |
205 | // EVEX_U |
206 | if (HasREX_W) { |
207 | if (OpPrefix == X86Local::PD) |
208 | insnContext = EVEX_KB_U(IC_EVEX_W_OPSIZE); |
209 | else if (OpPrefix == X86Local::XS) |
210 | insnContext = EVEX_KB_U(IC_EVEX_W_XS); |
211 | else if (OpPrefix == X86Local::XD) |
212 | insnContext = EVEX_KB_U(IC_EVEX_W_XD); |
213 | else if (OpPrefix == X86Local::PS) |
214 | insnContext = EVEX_KB_U(IC_EVEX_W); |
215 | else { |
216 | errs() << "Instruction does not use a prefix: " << Name << "\n" ; |
217 | llvm_unreachable("Invalid prefix" ); |
218 | } |
219 | } else { |
220 | if (OpPrefix == X86Local::PD) |
221 | insnContext = EVEX_KB_U(IC_EVEX_OPSIZE); |
222 | else if (OpPrefix == X86Local::XS) |
223 | insnContext = EVEX_KB_U(IC_EVEX_XS); |
224 | else if (OpPrefix == X86Local::XD) |
225 | insnContext = EVEX_KB_U(IC_EVEX_XD); |
226 | else if (OpPrefix == X86Local::PS) |
227 | insnContext = EVEX_KB_U(IC_EVEX); |
228 | else { |
229 | errs() << "Instruction does not use a prefix: " << Name << "\n" ; |
230 | llvm_unreachable("Invalid prefix" ); |
231 | } |
232 | } |
233 | } else if (HasEVEX_NF) { |
234 | if (OpPrefix == X86Local::PD) |
235 | insnContext = EVEX_B_NF(IC_EVEX_OPSIZE); |
236 | else if (HasREX_W) |
237 | insnContext = EVEX_B_NF(IC_EVEX_W); |
238 | else |
239 | insnContext = EVEX_B_NF(IC_EVEX); |
240 | } else if (!EncodeRC && HasVEX_L && HasREX_W) { |
241 | // VEX_L & VEX_W |
242 | if (OpPrefix == X86Local::PD) |
243 | insnContext = EVEX_KB(IC_EVEX_L_W_OPSIZE); |
244 | else if (OpPrefix == X86Local::XS) |
245 | insnContext = EVEX_KB(IC_EVEX_L_W_XS); |
246 | else if (OpPrefix == X86Local::XD) |
247 | insnContext = EVEX_KB(IC_EVEX_L_W_XD); |
248 | else if (OpPrefix == X86Local::PS) |
249 | insnContext = EVEX_KB(IC_EVEX_L_W); |
250 | else { |
251 | errs() << "Instruction does not use a prefix: " << Name << "\n" ; |
252 | llvm_unreachable("Invalid prefix" ); |
253 | } |
254 | } else if (!EncodeRC && HasVEX_L) { |
255 | // VEX_L |
256 | if (OpPrefix == X86Local::PD) |
257 | insnContext = EVEX_KB(IC_EVEX_L_OPSIZE); |
258 | else if (OpPrefix == X86Local::XS) |
259 | insnContext = EVEX_KB(IC_EVEX_L_XS); |
260 | else if (OpPrefix == X86Local::XD) |
261 | insnContext = EVEX_KB(IC_EVEX_L_XD); |
262 | else if (OpPrefix == X86Local::PS) |
263 | insnContext = EVEX_KB(IC_EVEX_L); |
264 | else { |
265 | errs() << "Instruction does not use a prefix: " << Name << "\n" ; |
266 | llvm_unreachable("Invalid prefix" ); |
267 | } |
268 | } else if (!EncodeRC && HasEVEX_L2 && HasREX_W) { |
269 | // EVEX_L2 & VEX_W |
270 | if (OpPrefix == X86Local::PD) |
271 | insnContext = EVEX_KB(IC_EVEX_L2_W_OPSIZE); |
272 | else if (OpPrefix == X86Local::XS) |
273 | insnContext = EVEX_KB(IC_EVEX_L2_W_XS); |
274 | else if (OpPrefix == X86Local::XD) |
275 | insnContext = EVEX_KB(IC_EVEX_L2_W_XD); |
276 | else if (OpPrefix == X86Local::PS) |
277 | insnContext = EVEX_KB(IC_EVEX_L2_W); |
278 | else { |
279 | errs() << "Instruction does not use a prefix: " << Name << "\n" ; |
280 | llvm_unreachable("Invalid prefix" ); |
281 | } |
282 | } else if (!EncodeRC && HasEVEX_L2) { |
283 | // EVEX_L2 |
284 | if (OpPrefix == X86Local::PD) |
285 | insnContext = EVEX_KB(IC_EVEX_L2_OPSIZE); |
286 | else if (OpPrefix == X86Local::XD) |
287 | insnContext = EVEX_KB(IC_EVEX_L2_XD); |
288 | else if (OpPrefix == X86Local::XS) |
289 | insnContext = EVEX_KB(IC_EVEX_L2_XS); |
290 | else if (OpPrefix == X86Local::PS) |
291 | insnContext = EVEX_KB(IC_EVEX_L2); |
292 | else { |
293 | errs() << "Instruction does not use a prefix: " << Name << "\n" ; |
294 | llvm_unreachable("Invalid prefix" ); |
295 | } |
296 | } else if (HasREX_W) { |
297 | // VEX_W |
298 | if (OpPrefix == X86Local::PD) |
299 | insnContext = EVEX_KB(IC_EVEX_W_OPSIZE); |
300 | else if (OpPrefix == X86Local::XS) |
301 | insnContext = EVEX_KB(IC_EVEX_W_XS); |
302 | else if (OpPrefix == X86Local::XD) |
303 | insnContext = EVEX_KB(IC_EVEX_W_XD); |
304 | else if (OpPrefix == X86Local::PS) |
305 | insnContext = EVEX_KB(IC_EVEX_W); |
306 | else { |
307 | errs() << "Instruction does not use a prefix: " << Name << "\n" ; |
308 | llvm_unreachable("Invalid prefix" ); |
309 | } |
310 | } |
311 | // No L, no W |
312 | else if (OpPrefix == X86Local::PD) { |
313 | insnContext = EVEX_KB_ADSIZE(IC_EVEX_OPSIZE); |
314 | } else if (OpPrefix == X86Local::XD) |
315 | insnContext = EVEX_KB_ADSIZE(IC_EVEX_XD); |
316 | else if (OpPrefix == X86Local::XS) |
317 | insnContext = EVEX_KB_ADSIZE(IC_EVEX_XS); |
318 | else if (OpPrefix == X86Local::PS) |
319 | insnContext = EVEX_KB(IC_EVEX); |
320 | else { |
321 | errs() << "Instruction does not use a prefix: " << Name << "\n" ; |
322 | llvm_unreachable("Invalid prefix" ); |
323 | } |
324 | /// eof EVEX |
325 | } else if (Encoding == X86Local::VEX || Encoding == X86Local::XOP) { |
326 | if (HasVEX_L && HasREX_W) { |
327 | if (OpPrefix == X86Local::PD) |
328 | insnContext = IC_VEX_L_W_OPSIZE; |
329 | else if (OpPrefix == X86Local::XS) |
330 | insnContext = IC_VEX_L_W_XS; |
331 | else if (OpPrefix == X86Local::XD) |
332 | insnContext = IC_VEX_L_W_XD; |
333 | else if (OpPrefix == X86Local::PS) |
334 | insnContext = IC_VEX_L_W; |
335 | else { |
336 | errs() << "Instruction does not use a prefix: " << Name << "\n" ; |
337 | llvm_unreachable("Invalid prefix" ); |
338 | } |
339 | } else if (OpPrefix == X86Local::PD && HasVEX_L) |
340 | insnContext = IC_VEX_L_OPSIZE; |
341 | else if (OpPrefix == X86Local::PD && HasREX_W) |
342 | insnContext = IC_VEX_W_OPSIZE; |
343 | else if (OpPrefix == X86Local::PD) |
344 | insnContext = IC_VEX_OPSIZE; |
345 | else if (HasVEX_L && OpPrefix == X86Local::XS) |
346 | insnContext = IC_VEX_L_XS; |
347 | else if (HasVEX_L && OpPrefix == X86Local::XD) |
348 | insnContext = IC_VEX_L_XD; |
349 | else if (HasREX_W && OpPrefix == X86Local::XS) |
350 | insnContext = IC_VEX_W_XS; |
351 | else if (HasREX_W && OpPrefix == X86Local::XD) |
352 | insnContext = IC_VEX_W_XD; |
353 | else if (HasREX_W && OpPrefix == X86Local::PS) |
354 | insnContext = IC_VEX_W; |
355 | else if (HasVEX_L && OpPrefix == X86Local::PS) |
356 | insnContext = IC_VEX_L; |
357 | else if (OpPrefix == X86Local::XD) |
358 | insnContext = IC_VEX_XD; |
359 | else if (OpPrefix == X86Local::XS) |
360 | insnContext = IC_VEX_XS; |
361 | else if (OpPrefix == X86Local::PS) |
362 | insnContext = IC_VEX; |
363 | else { |
364 | errs() << "Instruction does not use a prefix: " << Name << "\n" ; |
365 | llvm_unreachable("Invalid prefix" ); |
366 | } |
367 | } else if (Is64Bit || HasREX_W || AdSize == X86Local::AdSize64) { |
368 | if (HasREX_W && (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD)) |
369 | insnContext = IC_64BIT_REXW_OPSIZE; |
370 | else if (HasREX_W && AdSize == X86Local::AdSize32) |
371 | insnContext = IC_64BIT_REXW_ADSIZE; |
372 | else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XD) |
373 | insnContext = IC_64BIT_XD_OPSIZE; |
374 | else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XS) |
375 | insnContext = IC_64BIT_XS_OPSIZE; |
376 | else if (AdSize == X86Local::AdSize32 && OpPrefix == X86Local::PD) |
377 | insnContext = IC_64BIT_OPSIZE_ADSIZE; |
378 | else if (OpSize == X86Local::OpSize16 && AdSize == X86Local::AdSize32) |
379 | insnContext = IC_64BIT_OPSIZE_ADSIZE; |
380 | else if (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD) |
381 | insnContext = IC_64BIT_OPSIZE; |
382 | else if (AdSize == X86Local::AdSize32) |
383 | insnContext = IC_64BIT_ADSIZE; |
384 | else if (HasREX_W && OpPrefix == X86Local::XS) |
385 | insnContext = IC_64BIT_REXW_XS; |
386 | else if (HasREX_W && OpPrefix == X86Local::XD) |
387 | insnContext = IC_64BIT_REXW_XD; |
388 | else if (OpPrefix == X86Local::XD) |
389 | insnContext = IC_64BIT_XD; |
390 | else if (OpPrefix == X86Local::XS) |
391 | insnContext = IC_64BIT_XS; |
392 | else if (ExplicitREX2Prefix) |
393 | insnContext = IC_64BIT_REX2; |
394 | else if (HasREX_W) |
395 | insnContext = IC_64BIT_REXW; |
396 | else |
397 | insnContext = IC_64BIT; |
398 | } else { |
399 | if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XD) |
400 | insnContext = IC_XD_OPSIZE; |
401 | else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XS) |
402 | insnContext = IC_XS_OPSIZE; |
403 | else if (AdSize == X86Local::AdSize16 && OpPrefix == X86Local::XD) |
404 | insnContext = IC_XD_ADSIZE; |
405 | else if (AdSize == X86Local::AdSize16 && OpPrefix == X86Local::XS) |
406 | insnContext = IC_XS_ADSIZE; |
407 | else if (AdSize == X86Local::AdSize16 && OpPrefix == X86Local::PD) |
408 | insnContext = IC_OPSIZE_ADSIZE; |
409 | else if (OpSize == X86Local::OpSize16 && AdSize == X86Local::AdSize16) |
410 | insnContext = IC_OPSIZE_ADSIZE; |
411 | else if (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD) |
412 | insnContext = IC_OPSIZE; |
413 | else if (AdSize == X86Local::AdSize16) |
414 | insnContext = IC_ADSIZE; |
415 | else if (OpPrefix == X86Local::XD) |
416 | insnContext = IC_XD; |
417 | else if (OpPrefix == X86Local::XS) |
418 | insnContext = IC_XS; |
419 | else |
420 | insnContext = IC; |
421 | } |
422 | |
423 | return insnContext; |
424 | } |
425 | |
426 | void RecognizableInstr::adjustOperandEncoding(OperandEncoding &encoding) { |
427 | // The scaling factor for AVX512 compressed displacement encoding is an |
428 | // instruction attribute. Adjust the ModRM encoding type to include the |
429 | // scale for compressed displacement. |
430 | if ((encoding != ENCODING_RM && encoding != ENCODING_VSIB && |
431 | encoding != ENCODING_SIB) || |
432 | CD8_Scale == 0) |
433 | return; |
434 | encoding = (OperandEncoding)(encoding + Log2_32(Value: CD8_Scale)); |
435 | assert(((encoding >= ENCODING_RM && encoding <= ENCODING_RM_CD64) || |
436 | (encoding == ENCODING_SIB) || |
437 | (encoding >= ENCODING_VSIB && encoding <= ENCODING_VSIB_CD64)) && |
438 | "Invalid CDisp scaling" ); |
439 | } |
440 | |
441 | void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex, |
442 | unsigned &physicalOperandIndex, |
443 | unsigned numPhysicalOperands, |
444 | const unsigned *operandMapping, |
445 | EncodingFn encodingFromString) { |
446 | if (optional) { |
447 | if (physicalOperandIndex >= numPhysicalOperands) |
448 | return; |
449 | } else { |
450 | assert(physicalOperandIndex < numPhysicalOperands); |
451 | } |
452 | |
453 | while (operandMapping[operandIndex] != operandIndex) { |
454 | Spec->operands[operandIndex].encoding = ENCODING_DUP; |
455 | Spec->operands[operandIndex].type = |
456 | (OperandType)(TYPE_DUP0 + operandMapping[operandIndex]); |
457 | ++operandIndex; |
458 | } |
459 | |
460 | StringRef typeName = (*Operands)[operandIndex].Rec->getName(); |
461 | |
462 | OperandEncoding encoding = encodingFromString(typeName, OpSize); |
463 | // Adjust the encoding type for an operand based on the instruction. |
464 | adjustOperandEncoding(encoding); |
465 | Spec->operands[operandIndex].encoding = encoding; |
466 | Spec->operands[operandIndex].type = |
467 | typeFromString(Str: typeName, hasREX_W: HasREX_W, OpSize); |
468 | |
469 | ++operandIndex; |
470 | ++physicalOperandIndex; |
471 | } |
472 | |
473 | void RecognizableInstr::emitInstructionSpecifier() { |
474 | Spec->name = Name; |
475 | |
476 | Spec->insnContext = insnContext(); |
477 | |
478 | const std::vector<CGIOperandList::OperandInfo> &OperandList = *Operands; |
479 | |
480 | unsigned numOperands = OperandList.size(); |
481 | unsigned numPhysicalOperands = 0; |
482 | |
483 | // operandMapping maps from operands in OperandList to their originals. |
484 | // If operandMapping[i] != i, then the entry is a duplicate. |
485 | unsigned operandMapping[X86_MAX_OPERANDS]; |
486 | assert(numOperands <= X86_MAX_OPERANDS && |
487 | "X86_MAX_OPERANDS is not large enough" ); |
488 | |
489 | for (unsigned operandIndex = 0; operandIndex < numOperands; ++operandIndex) { |
490 | if (!OperandList[operandIndex].Constraints.empty()) { |
491 | const CGIOperandList::ConstraintInfo &Constraint = |
492 | OperandList[operandIndex].Constraints[0]; |
493 | if (Constraint.isTied()) { |
494 | operandMapping[operandIndex] = operandIndex; |
495 | operandMapping[Constraint.getTiedOperand()] = operandIndex; |
496 | } else { |
497 | ++numPhysicalOperands; |
498 | operandMapping[operandIndex] = operandIndex; |
499 | } |
500 | } else { |
501 | ++numPhysicalOperands; |
502 | operandMapping[operandIndex] = operandIndex; |
503 | } |
504 | } |
505 | |
506 | #define HANDLE_OPERAND(class) \ |
507 | handleOperand(false, operandIndex, physicalOperandIndex, \ |
508 | numPhysicalOperands, operandMapping, \ |
509 | class##EncodingFromString); |
510 | |
511 | #define HANDLE_OPTIONAL(class) \ |
512 | handleOperand(true, operandIndex, physicalOperandIndex, numPhysicalOperands, \ |
513 | operandMapping, class##EncodingFromString); |
514 | |
515 | // operandIndex should always be < numOperands |
516 | unsigned operandIndex = 0; |
517 | // physicalOperandIndex should always be < numPhysicalOperands |
518 | unsigned physicalOperandIndex = 0; |
519 | |
520 | #ifndef NDEBUG |
521 | // Given the set of prefix bits, how many additional operands does the |
522 | // instruction have? |
523 | unsigned additionalOperands = 0; |
524 | if (HasVEX_4V) |
525 | ++additionalOperands; |
526 | if (HasEVEX_K) |
527 | ++additionalOperands; |
528 | if (HasTwoConditionalOps) |
529 | additionalOperands += 2; |
530 | #endif |
531 | |
532 | bool IsND = OpMap == X86Local::T_MAP4 && HasEVEX_B && HasVEX_4V; |
533 | switch (Form) { |
534 | default: |
535 | llvm_unreachable("Unhandled form" ); |
536 | case X86Local::PrefixByte: |
537 | return; |
538 | case X86Local::RawFrmSrc: |
539 | HANDLE_OPERAND(relocation); |
540 | return; |
541 | case X86Local::RawFrmDst: |
542 | HANDLE_OPERAND(relocation); |
543 | return; |
544 | case X86Local::RawFrmDstSrc: |
545 | HANDLE_OPERAND(relocation); |
546 | HANDLE_OPERAND(relocation); |
547 | return; |
548 | case X86Local::RawFrm: |
549 | // Operand 1 (optional) is an address or immediate. |
550 | assert(numPhysicalOperands <= 1 && |
551 | "Unexpected number of operands for RawFrm" ); |
552 | HANDLE_OPTIONAL(relocation) |
553 | break; |
554 | case X86Local::RawFrmMemOffs: |
555 | // Operand 1 is an address. |
556 | HANDLE_OPERAND(relocation); |
557 | break; |
558 | case X86Local::AddRegFrm: |
559 | // Operand 1 is added to the opcode. |
560 | // Operand 2 (optional) is an address. |
561 | assert(numPhysicalOperands >= 1 && numPhysicalOperands <= 2 && |
562 | "Unexpected number of operands for AddRegFrm" ); |
563 | HANDLE_OPERAND(opcodeModifier) |
564 | HANDLE_OPTIONAL(relocation) |
565 | break; |
566 | case X86Local::AddCCFrm: |
567 | // Operand 1 (optional) is an address or immediate. |
568 | assert(numPhysicalOperands == 2 && |
569 | "Unexpected number of operands for AddCCFrm" ); |
570 | HANDLE_OPERAND(relocation) |
571 | HANDLE_OPERAND(opcodeModifier) |
572 | break; |
573 | case X86Local::MRMDestRegCC: |
574 | assert(numPhysicalOperands == 3 && |
575 | "Unexpected number of operands for MRMDestRegCC" ); |
576 | HANDLE_OPERAND(rmRegister) |
577 | HANDLE_OPERAND(roRegister) |
578 | HANDLE_OPERAND(opcodeModifier) |
579 | break; |
580 | case X86Local::MRMDestReg: |
581 | // Operand 1 is a register operand in the R/M field. |
582 | // - In AVX512 there may be a mask operand here - |
583 | // Operand 2 is a register operand in the Reg/Opcode field. |
584 | // - In AVX, there is a register operand in the VEX.vvvv field here - |
585 | // Operand 3 (optional) is an immediate. |
586 | assert(numPhysicalOperands >= 2 + additionalOperands && |
587 | numPhysicalOperands <= 3 + additionalOperands && |
588 | "Unexpected number of operands for MRMDestReg" ); |
589 | |
590 | if (IsND) |
591 | HANDLE_OPERAND(vvvvRegister) |
592 | |
593 | HANDLE_OPERAND(rmRegister) |
594 | if (HasEVEX_K) |
595 | HANDLE_OPERAND(writemaskRegister) |
596 | |
597 | if (!IsND && HasVEX_4V) |
598 | // FIXME: In AVX, the register below becomes the one encoded |
599 | // in ModRMVEX and the one above the one in the VEX.VVVV field |
600 | HANDLE_OPERAND(vvvvRegister) |
601 | |
602 | HANDLE_OPERAND(roRegister) |
603 | HANDLE_OPTIONAL(immediate) |
604 | HANDLE_OPTIONAL(immediate) |
605 | break; |
606 | case X86Local::MRMDestMemCC: |
607 | assert(numPhysicalOperands == 3 && |
608 | "Unexpected number of operands for MRMDestMemCC" ); |
609 | HANDLE_OPERAND(memory) |
610 | HANDLE_OPERAND(roRegister) |
611 | HANDLE_OPERAND(opcodeModifier) |
612 | break; |
613 | case X86Local::MRMDestMem4VOp3CC: |
614 | // Operand 1 is a register operand in the Reg/Opcode field. |
615 | // Operand 2 is a register operand in the R/M field. |
616 | // Operand 3 is VEX.vvvv |
617 | // Operand 4 is condition code. |
618 | assert(numPhysicalOperands == 4 && |
619 | "Unexpected number of operands for MRMDestMem4VOp3CC" ); |
620 | HANDLE_OPERAND(roRegister) |
621 | HANDLE_OPERAND(memory) |
622 | HANDLE_OPERAND(vvvvRegister) |
623 | HANDLE_OPERAND(opcodeModifier) |
624 | break; |
625 | case X86Local::MRMDestMem: |
626 | case X86Local::MRMDestMemFSIB: |
627 | // Operand 1 is a memory operand (possibly SIB-extended) |
628 | // Operand 2 is a register operand in the Reg/Opcode field. |
629 | // - In AVX, there is a register operand in the VEX.vvvv field here - |
630 | // Operand 3 (optional) is an immediate. |
631 | assert(numPhysicalOperands >= 2 + additionalOperands && |
632 | numPhysicalOperands <= 3 + additionalOperands && |
633 | "Unexpected number of operands for MRMDestMemFrm with VEX_4V" ); |
634 | |
635 | if (IsND) |
636 | HANDLE_OPERAND(vvvvRegister) |
637 | |
638 | HANDLE_OPERAND(memory) |
639 | |
640 | if (HasEVEX_K) |
641 | HANDLE_OPERAND(writemaskRegister) |
642 | |
643 | if (!IsND && HasVEX_4V) |
644 | // FIXME: In AVX, the register below becomes the one encoded |
645 | // in ModRMVEX and the one above the one in the VEX.VVVV field |
646 | HANDLE_OPERAND(vvvvRegister) |
647 | |
648 | HANDLE_OPERAND(roRegister) |
649 | HANDLE_OPTIONAL(immediate) |
650 | HANDLE_OPTIONAL(immediate) |
651 | break; |
652 | case X86Local::MRMSrcReg: |
653 | // Operand 1 is a register operand in the Reg/Opcode field. |
654 | // Operand 2 is a register operand in the R/M field. |
655 | // - In AVX, there is a register operand in the VEX.vvvv field here - |
656 | // Operand 3 (optional) is an immediate. |
657 | // Operand 4 (optional) is an immediate. |
658 | |
659 | assert(numPhysicalOperands >= 2 + additionalOperands && |
660 | numPhysicalOperands <= 4 + additionalOperands && |
661 | "Unexpected number of operands for MRMSrcRegFrm" ); |
662 | |
663 | if (IsND) |
664 | HANDLE_OPERAND(vvvvRegister) |
665 | |
666 | HANDLE_OPERAND(roRegister) |
667 | |
668 | if (HasEVEX_K) |
669 | HANDLE_OPERAND(writemaskRegister) |
670 | |
671 | if (!IsND && HasVEX_4V) |
672 | // FIXME: In AVX, the register below becomes the one encoded |
673 | // in ModRMVEX and the one above the one in the VEX.VVVV field |
674 | HANDLE_OPERAND(vvvvRegister) |
675 | |
676 | HANDLE_OPERAND(rmRegister) |
677 | HANDLE_OPTIONAL(immediate) |
678 | HANDLE_OPTIONAL(immediate) // above might be a register in 7:4 |
679 | break; |
680 | case X86Local::MRMSrcReg4VOp3: |
681 | assert(numPhysicalOperands == 3 && |
682 | "Unexpected number of operands for MRMSrcReg4VOp3Frm" ); |
683 | HANDLE_OPERAND(roRegister) |
684 | HANDLE_OPERAND(rmRegister) |
685 | HANDLE_OPERAND(vvvvRegister) |
686 | break; |
687 | case X86Local::MRMSrcRegOp4: |
688 | assert(numPhysicalOperands >= 4 && numPhysicalOperands <= 5 && |
689 | "Unexpected number of operands for MRMSrcRegOp4Frm" ); |
690 | HANDLE_OPERAND(roRegister) |
691 | HANDLE_OPERAND(vvvvRegister) |
692 | HANDLE_OPERAND(immediate) // Register in imm[7:4] |
693 | HANDLE_OPERAND(rmRegister) |
694 | HANDLE_OPTIONAL(immediate) |
695 | break; |
696 | case X86Local::MRMSrcRegCC: |
697 | assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && |
698 | "Unexpected number of operands for MRMSrcRegCC" ); |
699 | if (IsND) |
700 | HANDLE_OPERAND(vvvvRegister) |
701 | HANDLE_OPERAND(roRegister) |
702 | HANDLE_OPERAND(rmRegister) |
703 | HANDLE_OPERAND(opcodeModifier) |
704 | break; |
705 | case X86Local::MRMSrcMem: |
706 | case X86Local::MRMSrcMemFSIB: |
707 | // Operand 1 is a register operand in the Reg/Opcode field. |
708 | // Operand 2 is a memory operand (possibly SIB-extended) |
709 | // - In AVX, there is a register operand in the VEX.vvvv field here - |
710 | // Operand 3 (optional) is an immediate. |
711 | |
712 | assert(numPhysicalOperands >= 2 + additionalOperands && |
713 | numPhysicalOperands <= 4 + additionalOperands && |
714 | "Unexpected number of operands for MRMSrcMemFrm" ); |
715 | if (IsND) |
716 | HANDLE_OPERAND(vvvvRegister) |
717 | |
718 | HANDLE_OPERAND(roRegister) |
719 | |
720 | if (HasEVEX_K) |
721 | HANDLE_OPERAND(writemaskRegister) |
722 | |
723 | if (!IsND && HasVEX_4V) |
724 | // FIXME: In AVX, the register below becomes the one encoded |
725 | // in ModRMVEX and the one above the one in the VEX.VVVV field |
726 | HANDLE_OPERAND(vvvvRegister) |
727 | |
728 | HANDLE_OPERAND(memory) |
729 | HANDLE_OPTIONAL(immediate) |
730 | HANDLE_OPTIONAL(immediate) // above might be a register in 7:4 |
731 | break; |
732 | case X86Local::MRMSrcMem4VOp3: |
733 | assert(numPhysicalOperands == 3 && |
734 | "Unexpected number of operands for MRMSrcMem4VOp3Frm" ); |
735 | HANDLE_OPERAND(roRegister) |
736 | HANDLE_OPERAND(memory) |
737 | HANDLE_OPERAND(vvvvRegister) |
738 | break; |
739 | case X86Local::MRMSrcMemOp4: |
740 | assert(numPhysicalOperands >= 4 && numPhysicalOperands <= 5 && |
741 | "Unexpected number of operands for MRMSrcMemOp4Frm" ); |
742 | HANDLE_OPERAND(roRegister) |
743 | HANDLE_OPERAND(vvvvRegister) |
744 | HANDLE_OPERAND(immediate) // Register in imm[7:4] |
745 | HANDLE_OPERAND(memory) |
746 | HANDLE_OPTIONAL(immediate) |
747 | break; |
748 | case X86Local::MRMSrcMemCC: |
749 | assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && |
750 | "Unexpected number of operands for MRMSrcMemCC" ); |
751 | if (IsND) |
752 | HANDLE_OPERAND(vvvvRegister) |
753 | HANDLE_OPERAND(roRegister) |
754 | HANDLE_OPERAND(memory) |
755 | HANDLE_OPERAND(opcodeModifier) |
756 | break; |
757 | case X86Local::MRMXrCC: |
758 | assert(numPhysicalOperands == 2 && |
759 | "Unexpected number of operands for MRMXrCC" ); |
760 | HANDLE_OPERAND(rmRegister) |
761 | HANDLE_OPERAND(opcodeModifier) |
762 | break; |
763 | case X86Local::MRMr0: |
764 | // Operand 1 is a register operand in the R/M field. |
765 | HANDLE_OPERAND(roRegister) |
766 | break; |
767 | case X86Local::MRMXr: |
768 | case X86Local::MRM0r: |
769 | case X86Local::MRM1r: |
770 | case X86Local::MRM2r: |
771 | case X86Local::MRM3r: |
772 | case X86Local::MRM4r: |
773 | case X86Local::MRM5r: |
774 | case X86Local::MRM6r: |
775 | case X86Local::MRM7r: |
776 | // Operand 1 is a register operand in the R/M field. |
777 | // Operand 2 (optional) is an immediate or relocation. |
778 | // Operand 3 (optional) is an immediate. |
779 | assert(numPhysicalOperands >= 0 + additionalOperands && |
780 | numPhysicalOperands <= 3 + additionalOperands && |
781 | "Unexpected number of operands for MRMnr" ); |
782 | |
783 | if (HasVEX_4V) |
784 | HANDLE_OPERAND(vvvvRegister) |
785 | |
786 | if (HasEVEX_K) |
787 | HANDLE_OPERAND(writemaskRegister) |
788 | HANDLE_OPTIONAL(rmRegister) |
789 | HANDLE_OPTIONAL(relocation) |
790 | HANDLE_OPTIONAL(immediate) |
791 | HANDLE_OPTIONAL(immediate) |
792 | break; |
793 | case X86Local::MRMXmCC: |
794 | assert(numPhysicalOperands == 2 && |
795 | "Unexpected number of operands for MRMXm" ); |
796 | HANDLE_OPERAND(memory) |
797 | HANDLE_OPERAND(opcodeModifier) |
798 | break; |
799 | case X86Local::MRMXm: |
800 | case X86Local::MRM0m: |
801 | case X86Local::MRM1m: |
802 | case X86Local::MRM2m: |
803 | case X86Local::MRM3m: |
804 | case X86Local::MRM4m: |
805 | case X86Local::MRM5m: |
806 | case X86Local::MRM6m: |
807 | case X86Local::MRM7m: |
808 | // Operand 1 is a memory operand (possibly SIB-extended) |
809 | // Operand 2 (optional) is an immediate or relocation. |
810 | assert(numPhysicalOperands >= 1 + additionalOperands && |
811 | numPhysicalOperands <= 2 + additionalOperands && |
812 | "Unexpected number of operands for MRMnm" ); |
813 | |
814 | if (HasVEX_4V) |
815 | HANDLE_OPERAND(vvvvRegister) |
816 | if (HasEVEX_K) |
817 | HANDLE_OPERAND(writemaskRegister) |
818 | HANDLE_OPERAND(memory) |
819 | HANDLE_OPTIONAL(relocation) |
820 | HANDLE_OPTIONAL(immediate) |
821 | HANDLE_OPTIONAL(immediate) |
822 | break; |
823 | case X86Local::RawFrmImm8: |
824 | // operand 1 is a 16-bit immediate |
825 | // operand 2 is an 8-bit immediate |
826 | assert(numPhysicalOperands == 2 && |
827 | "Unexpected number of operands for X86Local::RawFrmImm8" ); |
828 | HANDLE_OPERAND(immediate) |
829 | HANDLE_OPERAND(immediate) |
830 | break; |
831 | case X86Local::RawFrmImm16: |
832 | // operand 1 is a 16-bit immediate |
833 | // operand 2 is a 16-bit immediate |
834 | HANDLE_OPERAND(immediate) |
835 | HANDLE_OPERAND(immediate) |
836 | break; |
837 | case X86Local::MRM0X: |
838 | case X86Local::MRM1X: |
839 | case X86Local::MRM2X: |
840 | case X86Local::MRM3X: |
841 | case X86Local::MRM4X: |
842 | case X86Local::MRM5X: |
843 | case X86Local::MRM6X: |
844 | case X86Local::MRM7X: |
845 | #define MAP(from, to) case X86Local::MRM_##from: |
846 | X86_INSTR_MRM_MAPPING |
847 | #undef MAP |
848 | HANDLE_OPTIONAL(relocation) |
849 | break; |
850 | } |
851 | |
852 | #undef HANDLE_OPERAND |
853 | #undef HANDLE_OPTIONAL |
854 | } |
855 | |
856 | void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { |
857 | // Special cases where the LLVM tables are not complete |
858 | |
859 | #define MAP(from, to) case X86Local::MRM_##from: |
860 | |
861 | std::optional<OpcodeType> opcodeType; |
862 | switch (OpMap) { |
863 | default: |
864 | llvm_unreachable("Invalid map!" ); |
865 | case X86Local::OB: |
866 | opcodeType = ONEBYTE; |
867 | break; |
868 | case X86Local::TB: |
869 | opcodeType = TWOBYTE; |
870 | break; |
871 | case X86Local::T8: |
872 | opcodeType = THREEBYTE_38; |
873 | break; |
874 | case X86Local::TA: |
875 | opcodeType = THREEBYTE_3A; |
876 | break; |
877 | case X86Local::XOP8: |
878 | opcodeType = XOP8_MAP; |
879 | break; |
880 | case X86Local::XOP9: |
881 | opcodeType = XOP9_MAP; |
882 | break; |
883 | case X86Local::XOPA: |
884 | opcodeType = XOPA_MAP; |
885 | break; |
886 | case X86Local::ThreeDNow: |
887 | opcodeType = THREEDNOW_MAP; |
888 | break; |
889 | case X86Local::T_MAP4: |
890 | opcodeType = MAP4; |
891 | break; |
892 | case X86Local::T_MAP5: |
893 | opcodeType = MAP5; |
894 | break; |
895 | case X86Local::T_MAP6: |
896 | opcodeType = MAP6; |
897 | break; |
898 | case X86Local::T_MAP7: |
899 | opcodeType = MAP7; |
900 | break; |
901 | } |
902 | |
903 | std::unique_ptr<ModRMFilter> filter; |
904 | switch (Form) { |
905 | default: |
906 | llvm_unreachable("Invalid form!" ); |
907 | case X86Local::Pseudo: |
908 | llvm_unreachable("Pseudo should not be emitted!" ); |
909 | case X86Local::RawFrm: |
910 | case X86Local::AddRegFrm: |
911 | case X86Local::RawFrmMemOffs: |
912 | case X86Local::RawFrmSrc: |
913 | case X86Local::RawFrmDst: |
914 | case X86Local::RawFrmDstSrc: |
915 | case X86Local::RawFrmImm8: |
916 | case X86Local::RawFrmImm16: |
917 | case X86Local::AddCCFrm: |
918 | case X86Local::PrefixByte: |
919 | filter = std::make_unique<DumbFilter>(); |
920 | break; |
921 | case X86Local::MRMDestReg: |
922 | case X86Local::MRMDestRegCC: |
923 | case X86Local::MRMSrcReg: |
924 | case X86Local::MRMSrcReg4VOp3: |
925 | case X86Local::MRMSrcRegOp4: |
926 | case X86Local::MRMSrcRegCC: |
927 | case X86Local::MRMXrCC: |
928 | case X86Local::MRMXr: |
929 | filter = std::make_unique<ModFilter>(args: true); |
930 | break; |
931 | case X86Local::MRMDestMem: |
932 | case X86Local::MRMDestMemCC: |
933 | case X86Local::MRMDestMem4VOp3CC: |
934 | case X86Local::MRMDestMemFSIB: |
935 | case X86Local::MRMSrcMem: |
936 | case X86Local::MRMSrcMemFSIB: |
937 | case X86Local::MRMSrcMem4VOp3: |
938 | case X86Local::MRMSrcMemOp4: |
939 | case X86Local::MRMSrcMemCC: |
940 | case X86Local::MRMXmCC: |
941 | case X86Local::MRMXm: |
942 | filter = std::make_unique<ModFilter>(args: false); |
943 | break; |
944 | case X86Local::MRM0r: |
945 | case X86Local::MRM1r: |
946 | case X86Local::MRM2r: |
947 | case X86Local::MRM3r: |
948 | case X86Local::MRM4r: |
949 | case X86Local::MRM5r: |
950 | case X86Local::MRM6r: |
951 | case X86Local::MRM7r: |
952 | filter = std::make_unique<ExtendedFilter>(args: true, args: Form - X86Local::MRM0r); |
953 | break; |
954 | case X86Local::MRM0X: |
955 | case X86Local::MRM1X: |
956 | case X86Local::MRM2X: |
957 | case X86Local::MRM3X: |
958 | case X86Local::MRM4X: |
959 | case X86Local::MRM5X: |
960 | case X86Local::MRM6X: |
961 | case X86Local::MRM7X: |
962 | filter = std::make_unique<ExtendedFilter>(args: true, args: Form - X86Local::MRM0X); |
963 | break; |
964 | case X86Local::MRMr0: |
965 | filter = std::make_unique<ExtendedRMFilter>(args: true, args: Form - X86Local::MRMr0); |
966 | break; |
967 | case X86Local::MRM0m: |
968 | case X86Local::MRM1m: |
969 | case X86Local::MRM2m: |
970 | case X86Local::MRM3m: |
971 | case X86Local::MRM4m: |
972 | case X86Local::MRM5m: |
973 | case X86Local::MRM6m: |
974 | case X86Local::MRM7m: |
975 | filter = std::make_unique<ExtendedFilter>(args: false, args: Form - X86Local::MRM0m); |
976 | break; |
977 | X86_INSTR_MRM_MAPPING |
978 | filter = std::make_unique<ExactFilter>(args: 0xC0 + Form - X86Local::MRM_C0); |
979 | break; |
980 | } // switch (Form) |
981 | |
982 | uint8_t opcodeToSet = Opcode; |
983 | |
984 | unsigned AddressSize = 0; |
985 | switch (AdSize) { |
986 | case X86Local::AdSize16: |
987 | AddressSize = 16; |
988 | break; |
989 | case X86Local::AdSize32: |
990 | AddressSize = 32; |
991 | break; |
992 | case X86Local::AdSize64: |
993 | AddressSize = 64; |
994 | break; |
995 | } |
996 | |
997 | assert(opcodeType && "Opcode type not set" ); |
998 | assert(filter && "Filter not set" ); |
999 | |
1000 | if (Form == X86Local::AddRegFrm || Form == X86Local::MRMSrcRegCC || |
1001 | Form == X86Local::MRMSrcMemCC || Form == X86Local::MRMXrCC || |
1002 | Form == X86Local::MRMXmCC || Form == X86Local::AddCCFrm || |
1003 | Form == X86Local::MRMDestRegCC || Form == X86Local::MRMDestMemCC || |
1004 | Form == X86Local::MRMDestMem4VOp3CC) { |
1005 | uint8_t Count = Form == X86Local::AddRegFrm ? 8 : 16; |
1006 | assert(((opcodeToSet % Count) == 0) && "ADDREG_FRM opcode not aligned" ); |
1007 | |
1008 | uint8_t currentOpcode; |
1009 | |
1010 | for (currentOpcode = opcodeToSet; |
1011 | currentOpcode < (uint8_t)(opcodeToSet + Count); ++currentOpcode) |
1012 | tables.setTableFields(type: *opcodeType, insnContext: insnContext(), opcode: currentOpcode, filter: *filter, |
1013 | uid: UID, is32bit: Is32Bit, noPrefix: OpPrefix == 0, |
1014 | ignoresVEX_L: IgnoresVEX_L || EncodeRC, ignoresVEX_W: IgnoresW, AddrSize: AddressSize); |
1015 | } else { |
1016 | tables.setTableFields(type: *opcodeType, insnContext: insnContext(), opcode: opcodeToSet, filter: *filter, uid: UID, |
1017 | is32bit: Is32Bit, noPrefix: OpPrefix == 0, ignoresVEX_L: IgnoresVEX_L || EncodeRC, |
1018 | ignoresVEX_W: IgnoresW, AddrSize: AddressSize); |
1019 | } |
1020 | |
1021 | #undef MAP |
1022 | } |
1023 | |
1024 | OperandType RecognizableInstr::typeFromString(StringRef Str, bool hasREX_W, |
1025 | uint8_t OpSize) { |
1026 | StringSwitch<OperandType> Switch(Str); |
1027 | if (hasREX_W) { |
1028 | // For instructions with a REX_W prefix, a declared 32-bit register encoding |
1029 | // is special. |
1030 | Switch.Case(S: "GR32" , Value: TYPE_R32); |
1031 | } |
1032 | if (OpSize == X86Local::OpSize16) { |
1033 | // For OpSize16 instructions, a declared 16-bit register or |
1034 | // immediate encoding is special. |
1035 | Switch.Case(S: "GR16" , Value: TYPE_Rv); |
1036 | } else if (OpSize == X86Local::OpSize32) { |
1037 | // For OpSize32 instructions, a declared 32-bit register or |
1038 | // immediate encoding is special. |
1039 | Switch.Case(S: "GR32" , Value: TYPE_Rv); |
1040 | } |
1041 | // clang-format off |
1042 | OperandType Type = |
1043 | Switch.Case(S: "i16mem" , Value: TYPE_M) |
1044 | .Case(S: "i16imm" , Value: TYPE_IMM) |
1045 | .Case(S: "i16i8imm" , Value: TYPE_IMM) |
1046 | .Case(S: "GR16" , Value: TYPE_R16) |
1047 | .Case(S: "GR16orGR32orGR64" , Value: TYPE_R16) |
1048 | .Case(S: "i32mem" , Value: TYPE_M) |
1049 | .Case(S: "i32imm" , Value: TYPE_IMM) |
1050 | .Case(S: "i32i8imm" , Value: TYPE_IMM) |
1051 | .Case(S: "GR32" , Value: TYPE_R32) |
1052 | .Case(S: "GR32orGR64" , Value: TYPE_R32) |
1053 | .Case(S: "i64mem" , Value: TYPE_M) |
1054 | .Case(S: "i64i32imm" , Value: TYPE_IMM) |
1055 | .Case(S: "i64i8imm" , Value: TYPE_IMM) |
1056 | .Case(S: "GR64" , Value: TYPE_R64) |
1057 | .Case(S: "i8mem" , Value: TYPE_M) |
1058 | .Case(S: "i8imm" , Value: TYPE_IMM) |
1059 | .Case(S: "u4imm" , Value: TYPE_UIMM8) |
1060 | .Case(S: "u8imm" , Value: TYPE_UIMM8) |
1061 | .Case(S: "i16u8imm" , Value: TYPE_UIMM8) |
1062 | .Case(S: "i32u8imm" , Value: TYPE_UIMM8) |
1063 | .Case(S: "i64u8imm" , Value: TYPE_UIMM8) |
1064 | .Case(S: "GR8" , Value: TYPE_R8) |
1065 | .Case(S: "VR128" , Value: TYPE_XMM) |
1066 | .Case(S: "VR128X" , Value: TYPE_XMM) |
1067 | .Case(S: "f128mem" , Value: TYPE_M) |
1068 | .Case(S: "f256mem" , Value: TYPE_M) |
1069 | .Case(S: "f512mem" , Value: TYPE_M) |
1070 | .Case(S: "FR128" , Value: TYPE_XMM) |
1071 | .Case(S: "FR64" , Value: TYPE_XMM) |
1072 | .Case(S: "FR64X" , Value: TYPE_XMM) |
1073 | .Case(S: "f64mem" , Value: TYPE_M) |
1074 | .Case(S: "sdmem" , Value: TYPE_M) |
1075 | .Case(S: "FR16X" , Value: TYPE_XMM) |
1076 | .Case(S: "FR32" , Value: TYPE_XMM) |
1077 | .Case(S: "FR32X" , Value: TYPE_XMM) |
1078 | .Case(S: "f32mem" , Value: TYPE_M) |
1079 | .Case(S: "f16mem" , Value: TYPE_M) |
1080 | .Case(S: "ssmem" , Value: TYPE_M) |
1081 | .Case(S: "shmem" , Value: TYPE_M) |
1082 | .Case(S: "RST" , Value: TYPE_ST) |
1083 | .Case(S: "RSTi" , Value: TYPE_ST) |
1084 | .Case(S: "i128mem" , Value: TYPE_M) |
1085 | .Case(S: "i256mem" , Value: TYPE_M) |
1086 | .Case(S: "i512mem" , Value: TYPE_M) |
1087 | .Case(S: "i512mem_GR16" , Value: TYPE_M) |
1088 | .Case(S: "i512mem_GR32" , Value: TYPE_M) |
1089 | .Case(S: "i512mem_GR64" , Value: TYPE_M) |
1090 | .Case(S: "i64i32imm_brtarget" , Value: TYPE_REL) |
1091 | .Case(S: "i8imm_brtarget" , Value: TYPE_REL) |
1092 | .Case(S: "i16imm_brtarget" , Value: TYPE_REL) |
1093 | .Case(S: "i32imm_brtarget" , Value: TYPE_REL) |
1094 | .Case(S: "ccode" , Value: TYPE_IMM) |
1095 | .Case(S: "cflags" , Value: TYPE_IMM) |
1096 | .Case(S: "AVX512RC" , Value: TYPE_IMM) |
1097 | .Case(S: "brtarget32" , Value: TYPE_REL) |
1098 | .Case(S: "brtarget16" , Value: TYPE_REL) |
1099 | .Case(S: "brtarget8" , Value: TYPE_REL) |
1100 | .Case(S: "f80mem" , Value: TYPE_M) |
1101 | .Case(S: "lea64_8mem" , Value: TYPE_M) |
1102 | .Case(S: "lea64_16mem" , Value: TYPE_M) |
1103 | .Case(S: "lea64_32mem" , Value: TYPE_M) |
1104 | .Case(S: "lea64mem" , Value: TYPE_M) |
1105 | .Case(S: "VR64" , Value: TYPE_MM64) |
1106 | .Case(S: "i64imm" , Value: TYPE_IMM) |
1107 | .Case(S: "anymem" , Value: TYPE_M) |
1108 | .Case(S: "opaquemem" , Value: TYPE_M) |
1109 | .Case(S: "sibmem" , Value: TYPE_MSIB) |
1110 | .Case(S: "SEGMENT_REG" , Value: TYPE_SEGMENTREG) |
1111 | .Case(S: "DEBUG_REG" , Value: TYPE_DEBUGREG) |
1112 | .Case(S: "CONTROL_REG" , Value: TYPE_CONTROLREG) |
1113 | .Case(S: "srcidx8" , Value: TYPE_SRCIDX) |
1114 | .Case(S: "srcidx16" , Value: TYPE_SRCIDX) |
1115 | .Case(S: "srcidx32" , Value: TYPE_SRCIDX) |
1116 | .Case(S: "srcidx64" , Value: TYPE_SRCIDX) |
1117 | .Case(S: "dstidx8" , Value: TYPE_DSTIDX) |
1118 | .Case(S: "dstidx16" , Value: TYPE_DSTIDX) |
1119 | .Case(S: "dstidx32" , Value: TYPE_DSTIDX) |
1120 | .Case(S: "dstidx64" , Value: TYPE_DSTIDX) |
1121 | .Case(S: "offset16_8" , Value: TYPE_MOFFS) |
1122 | .Case(S: "offset16_16" , Value: TYPE_MOFFS) |
1123 | .Case(S: "offset16_32" , Value: TYPE_MOFFS) |
1124 | .Case(S: "offset32_8" , Value: TYPE_MOFFS) |
1125 | .Case(S: "offset32_16" , Value: TYPE_MOFFS) |
1126 | .Case(S: "offset32_32" , Value: TYPE_MOFFS) |
1127 | .Case(S: "offset32_64" , Value: TYPE_MOFFS) |
1128 | .Case(S: "offset64_8" , Value: TYPE_MOFFS) |
1129 | .Case(S: "offset64_16" , Value: TYPE_MOFFS) |
1130 | .Case(S: "offset64_32" , Value: TYPE_MOFFS) |
1131 | .Case(S: "offset64_64" , Value: TYPE_MOFFS) |
1132 | .Case(S: "VR256" , Value: TYPE_YMM) |
1133 | .Case(S: "VR256X" , Value: TYPE_YMM) |
1134 | .Case(S: "VR512" , Value: TYPE_ZMM) |
1135 | .Case(S: "VK1" , Value: TYPE_VK) |
1136 | .Case(S: "VK1WM" , Value: TYPE_VK) |
1137 | .Case(S: "VK2" , Value: TYPE_VK) |
1138 | .Case(S: "VK2WM" , Value: TYPE_VK) |
1139 | .Case(S: "VK4" , Value: TYPE_VK) |
1140 | .Case(S: "VK4WM" , Value: TYPE_VK) |
1141 | .Case(S: "VK8" , Value: TYPE_VK) |
1142 | .Case(S: "VK8WM" , Value: TYPE_VK) |
1143 | .Case(S: "VK16" , Value: TYPE_VK) |
1144 | .Case(S: "VK16WM" , Value: TYPE_VK) |
1145 | .Case(S: "VK32" , Value: TYPE_VK) |
1146 | .Case(S: "VK32WM" , Value: TYPE_VK) |
1147 | .Case(S: "VK64" , Value: TYPE_VK) |
1148 | .Case(S: "VK64WM" , Value: TYPE_VK) |
1149 | .Case(S: "VK1Pair" , Value: TYPE_VK_PAIR) |
1150 | .Case(S: "VK2Pair" , Value: TYPE_VK_PAIR) |
1151 | .Case(S: "VK4Pair" , Value: TYPE_VK_PAIR) |
1152 | .Case(S: "VK8Pair" , Value: TYPE_VK_PAIR) |
1153 | .Case(S: "VK16Pair" , Value: TYPE_VK_PAIR) |
1154 | .Case(S: "vx32mem" , Value: TYPE_MVSIBX) |
1155 | .Case(S: "vx64mem" , Value: TYPE_MVSIBX) |
1156 | .Case(S: "vy32mem" , Value: TYPE_MVSIBY) |
1157 | .Case(S: "vy64mem" , Value: TYPE_MVSIBY) |
1158 | .Case(S: "vx32xmem" , Value: TYPE_MVSIBX) |
1159 | .Case(S: "vx64xmem" , Value: TYPE_MVSIBX) |
1160 | .Case(S: "vy32xmem" , Value: TYPE_MVSIBY) |
1161 | .Case(S: "vy64xmem" , Value: TYPE_MVSIBY) |
1162 | .Case(S: "vz32mem" , Value: TYPE_MVSIBZ) |
1163 | .Case(S: "vz64mem" , Value: TYPE_MVSIBZ) |
1164 | .Case(S: "BNDR" , Value: TYPE_BNDR) |
1165 | .Case(S: "TILE" , Value: TYPE_TMM) |
1166 | .Case(S: "TILEPair" , Value: TYPE_TMM_PAIR) |
1167 | .Default(Value: TYPE_NONE); |
1168 | // clang-format on |
1169 | |
1170 | if (Type != TYPE_NONE) |
1171 | return Type; |
1172 | errs() << "Unhandled type string " << Str << "\n" ; |
1173 | llvm_unreachable("Unhandled type string" ); |
1174 | } |
1175 | |
1176 | OperandEncoding RecognizableInstr::immediateEncodingFromString(StringRef Str, |
1177 | uint8_t OpSize) { |
1178 | StringSwitch<OperandEncoding> Switch(Str); |
1179 | if (OpSize != X86Local::OpSize16) { |
1180 | // For instructions without an OpSize prefix, a declared 16-bit register or |
1181 | // immediate encoding is special. |
1182 | Switch.Case(S: "i16imm" , Value: ENCODING_IW); |
1183 | } |
1184 | |
1185 | // clang-format off |
1186 | OperandEncoding Encoding = |
1187 | Switch.Case(S: "i32i8imm" , Value: ENCODING_IB) |
1188 | .Case(S: "AVX512RC" , Value: ENCODING_IRC) |
1189 | .Case(S: "i16imm" , Value: ENCODING_Iv) |
1190 | .Case(S: "i16i8imm" , Value: ENCODING_IB) |
1191 | .Case(S: "i32imm" , Value: ENCODING_Iv) |
1192 | .Case(S: "i64i32imm" , Value: ENCODING_ID) |
1193 | .Case(S: "i64i8imm" , Value: ENCODING_IB) |
1194 | .Case(S: "i8imm" , Value: ENCODING_IB) |
1195 | .Case(S: "ccode" , Value: ENCODING_CC) |
1196 | .Case(S: "cflags" , Value: ENCODING_CF) |
1197 | .Case(S: "u4imm" , Value: ENCODING_IB) |
1198 | .Case(S: "u8imm" , Value: ENCODING_IB) |
1199 | .Case(S: "i16u8imm" , Value: ENCODING_IB) |
1200 | .Case(S: "i32u8imm" , Value: ENCODING_IB) |
1201 | .Case(S: "i64u8imm" , Value: ENCODING_IB) |
1202 | // This is not a typo. Instructions like BLENDVPD put |
1203 | // register IDs in 8-bit immediates nowadays. |
1204 | .Case(S: "FR32" , Value: ENCODING_IB) |
1205 | .Case(S: "FR64" , Value: ENCODING_IB) |
1206 | .Case(S: "FR128" , Value: ENCODING_IB) |
1207 | .Case(S: "VR128" , Value: ENCODING_IB) |
1208 | .Case(S: "VR256" , Value: ENCODING_IB) |
1209 | .Case(S: "FR16X" , Value: ENCODING_IB) |
1210 | .Case(S: "FR32X" , Value: ENCODING_IB) |
1211 | .Case(S: "FR64X" , Value: ENCODING_IB) |
1212 | .Case(S: "VR128X" , Value: ENCODING_IB) |
1213 | .Case(S: "VR256X" , Value: ENCODING_IB) |
1214 | .Case(S: "VR512" , Value: ENCODING_IB) |
1215 | .Case(S: "TILE" , Value: ENCODING_IB) |
1216 | .Default(Value: ENCODING_NONE); |
1217 | // clang-format on |
1218 | |
1219 | if (Encoding != ENCODING_NONE) |
1220 | return Encoding; |
1221 | errs() << "Unhandled immediate encoding " << Str << "\n" ; |
1222 | llvm_unreachable("Unhandled immediate encoding" ); |
1223 | } |
1224 | |
1225 | OperandEncoding |
1226 | RecognizableInstr::rmRegisterEncodingFromString(StringRef Str, uint8_t OpSize) { |
1227 | // clang-format off |
1228 | auto Encoding = |
1229 | StringSwitch<OperandEncoding>(Str) |
1230 | .Case(S: "RST" , Value: ENCODING_FP) |
1231 | .Case(S: "RSTi" , Value: ENCODING_FP) |
1232 | .Case(S: "GR16" , Value: ENCODING_RM) |
1233 | .Case(S: "GR16orGR32orGR64" , Value: ENCODING_RM) |
1234 | .Case(S: "GR32" , Value: ENCODING_RM) |
1235 | .Case(S: "GR32orGR64" , Value: ENCODING_RM) |
1236 | .Case(S: "GR64" , Value: ENCODING_RM) |
1237 | .Case(S: "GR8" , Value: ENCODING_RM) |
1238 | .Case(S: "VR128" , Value: ENCODING_RM) |
1239 | .Case(S: "VR128X" , Value: ENCODING_RM) |
1240 | .Case(S: "FR128" , Value: ENCODING_RM) |
1241 | .Case(S: "FR64" , Value: ENCODING_RM) |
1242 | .Case(S: "FR32" , Value: ENCODING_RM) |
1243 | .Case(S: "FR64X" , Value: ENCODING_RM) |
1244 | .Case(S: "FR32X" , Value: ENCODING_RM) |
1245 | .Case(S: "FR16X" , Value: ENCODING_RM) |
1246 | .Case(S: "VR64" , Value: ENCODING_RM) |
1247 | .Case(S: "VR256" , Value: ENCODING_RM) |
1248 | .Case(S: "VR256X" , Value: ENCODING_RM) |
1249 | .Case(S: "VR512" , Value: ENCODING_RM) |
1250 | .Case(S: "VK1" , Value: ENCODING_RM) |
1251 | .Case(S: "VK2" , Value: ENCODING_RM) |
1252 | .Case(S: "VK4" , Value: ENCODING_RM) |
1253 | .Case(S: "VK8" , Value: ENCODING_RM) |
1254 | .Case(S: "VK16" , Value: ENCODING_RM) |
1255 | .Case(S: "VK32" , Value: ENCODING_RM) |
1256 | .Case(S: "VK64" , Value: ENCODING_RM) |
1257 | .Case(S: "BNDR" , Value: ENCODING_RM) |
1258 | .Case(S: "TILE" , Value: ENCODING_RM) |
1259 | .Case(S: "TILEPair" , Value: ENCODING_RM) |
1260 | .Default(Value: ENCODING_NONE); |
1261 | // clang-format on |
1262 | if (Encoding != ENCODING_NONE) |
1263 | return Encoding; |
1264 | errs() << "Unhandled R/M register encoding " << Str << "\n" ; |
1265 | llvm_unreachable("Unhandled R/M register encoding" ); |
1266 | } |
1267 | |
1268 | OperandEncoding |
1269 | RecognizableInstr::roRegisterEncodingFromString(StringRef Str, uint8_t OpSize) { |
1270 | // clang-format off |
1271 | auto Encoding = |
1272 | StringSwitch<OperandEncoding>(Str) |
1273 | .Case(S: "GR16" , Value: ENCODING_REG) |
1274 | .Case(S: "GR16orGR32orGR64" , Value: ENCODING_REG) |
1275 | .Case(S: "GR32" , Value: ENCODING_REG) |
1276 | .Case(S: "GR32orGR64" , Value: ENCODING_REG) |
1277 | .Case(S: "GR64" , Value: ENCODING_REG) |
1278 | .Case(S: "GR8" , Value: ENCODING_REG) |
1279 | .Case(S: "VR128" , Value: ENCODING_REG) |
1280 | .Case(S: "FR128" , Value: ENCODING_REG) |
1281 | .Case(S: "FR64" , Value: ENCODING_REG) |
1282 | .Case(S: "FR32" , Value: ENCODING_REG) |
1283 | .Case(S: "VR64" , Value: ENCODING_REG) |
1284 | .Case(S: "SEGMENT_REG" , Value: ENCODING_REG) |
1285 | .Case(S: "DEBUG_REG" , Value: ENCODING_REG) |
1286 | .Case(S: "CONTROL_REG" , Value: ENCODING_REG) |
1287 | .Case(S: "VR256" , Value: ENCODING_REG) |
1288 | .Case(S: "VR256X" , Value: ENCODING_REG) |
1289 | .Case(S: "VR128X" , Value: ENCODING_REG) |
1290 | .Case(S: "FR64X" , Value: ENCODING_REG) |
1291 | .Case(S: "FR32X" , Value: ENCODING_REG) |
1292 | .Case(S: "FR16X" , Value: ENCODING_REG) |
1293 | .Case(S: "VR512" , Value: ENCODING_REG) |
1294 | .Case(S: "VK1" , Value: ENCODING_REG) |
1295 | .Case(S: "VK2" , Value: ENCODING_REG) |
1296 | .Case(S: "VK4" , Value: ENCODING_REG) |
1297 | .Case(S: "VK8" , Value: ENCODING_REG) |
1298 | .Case(S: "VK16" , Value: ENCODING_REG) |
1299 | .Case(S: "VK32" , Value: ENCODING_REG) |
1300 | .Case(S: "VK64" , Value: ENCODING_REG) |
1301 | .Case(S: "VK1Pair" , Value: ENCODING_REG) |
1302 | .Case(S: "VK2Pair" , Value: ENCODING_REG) |
1303 | .Case(S: "VK4Pair" , Value: ENCODING_REG) |
1304 | .Case(S: "VK8Pair" , Value: ENCODING_REG) |
1305 | .Case(S: "VK16Pair" , Value: ENCODING_REG) |
1306 | .Case(S: "VK1WM" , Value: ENCODING_REG) |
1307 | .Case(S: "VK2WM" , Value: ENCODING_REG) |
1308 | .Case(S: "VK4WM" , Value: ENCODING_REG) |
1309 | .Case(S: "VK8WM" , Value: ENCODING_REG) |
1310 | .Case(S: "VK16WM" , Value: ENCODING_REG) |
1311 | .Case(S: "VK32WM" , Value: ENCODING_REG) |
1312 | .Case(S: "VK64WM" , Value: ENCODING_REG) |
1313 | .Case(S: "BNDR" , Value: ENCODING_REG) |
1314 | .Case(S: "TILE" , Value: ENCODING_REG) |
1315 | .Case(S: "TILEPair" , Value: ENCODING_REG) |
1316 | .Default(Value: ENCODING_NONE); |
1317 | // clang-format on |
1318 | |
1319 | if (Encoding != ENCODING_NONE) |
1320 | return Encoding; |
1321 | |
1322 | errs() << "Unhandled reg/opcode register encoding " << Str << "\n" ; |
1323 | llvm_unreachable("Unhandled reg/opcode register encoding" ); |
1324 | } |
1325 | |
1326 | OperandEncoding |
1327 | RecognizableInstr::vvvvRegisterEncodingFromString(StringRef Str, |
1328 | uint8_t OpSize) { |
1329 | // clang-format off |
1330 | auto Encoding = |
1331 | StringSwitch<OperandEncoding>(Str) |
1332 | .Case(S: "GR8" , Value: ENCODING_VVVV) |
1333 | .Case(S: "GR16" , Value: ENCODING_VVVV) |
1334 | .Case(S: "GR32" , Value: ENCODING_VVVV) |
1335 | .Case(S: "GR64" , Value: ENCODING_VVVV) |
1336 | .Case(S: "FR32" , Value: ENCODING_VVVV) |
1337 | .Case(S: "FR128" , Value: ENCODING_VVVV) |
1338 | .Case(S: "FR64" , Value: ENCODING_VVVV) |
1339 | .Case(S: "VR128" , Value: ENCODING_VVVV) |
1340 | .Case(S: "VR256" , Value: ENCODING_VVVV) |
1341 | .Case(S: "FR16X" , Value: ENCODING_VVVV) |
1342 | .Case(S: "FR32X" , Value: ENCODING_VVVV) |
1343 | .Case(S: "FR64X" , Value: ENCODING_VVVV) |
1344 | .Case(S: "VR128X" , Value: ENCODING_VVVV) |
1345 | .Case(S: "VR256X" , Value: ENCODING_VVVV) |
1346 | .Case(S: "VR512" , Value: ENCODING_VVVV) |
1347 | .Case(S: "VK1" , Value: ENCODING_VVVV) |
1348 | .Case(S: "VK2" , Value: ENCODING_VVVV) |
1349 | .Case(S: "VK4" , Value: ENCODING_VVVV) |
1350 | .Case(S: "VK8" , Value: ENCODING_VVVV) |
1351 | .Case(S: "VK16" , Value: ENCODING_VVVV) |
1352 | .Case(S: "VK32" , Value: ENCODING_VVVV) |
1353 | .Case(S: "VK64" , Value: ENCODING_VVVV) |
1354 | .Case(S: "TILE" , Value: ENCODING_VVVV) |
1355 | .Case(S: "TILEPair" , Value: ENCODING_VVVV) |
1356 | .Default(Value: ENCODING_NONE); |
1357 | // clang-format on |
1358 | if (Encoding != ENCODING_NONE) |
1359 | return Encoding; |
1360 | |
1361 | errs() << "Unhandled VEX.vvvv register encoding " << Str << "\n" ; |
1362 | llvm_unreachable("Unhandled VEX.vvvv register encoding" ); |
1363 | } |
1364 | |
1365 | OperandEncoding |
1366 | RecognizableInstr::writemaskRegisterEncodingFromString(StringRef Str, |
1367 | uint8_t OpSize) { |
1368 | // clang-format off |
1369 | auto Encoding = |
1370 | StringSwitch<OperandEncoding>(Str) |
1371 | .Case(S: "VK1WM" , Value: ENCODING_WRITEMASK) |
1372 | .Case(S: "VK2WM" , Value: ENCODING_WRITEMASK) |
1373 | .Case(S: "VK4WM" , Value: ENCODING_WRITEMASK) |
1374 | .Case(S: "VK8WM" , Value: ENCODING_WRITEMASK) |
1375 | .Case(S: "VK16WM" , Value: ENCODING_WRITEMASK) |
1376 | .Case(S: "VK32WM" , Value: ENCODING_WRITEMASK) |
1377 | .Case(S: "VK64WM" , Value: ENCODING_WRITEMASK) |
1378 | .Default(Value: ENCODING_NONE); |
1379 | // clang-format on |
1380 | |
1381 | if (Encoding != ENCODING_NONE) |
1382 | return Encoding; |
1383 | |
1384 | errs() << "Unhandled mask register encoding " << Str << "\n" ; |
1385 | llvm_unreachable("Unhandled mask register encoding" ); |
1386 | } |
1387 | |
1388 | OperandEncoding RecognizableInstr::memoryEncodingFromString(StringRef Str, |
1389 | uint8_t OpSize) { |
1390 | // clang-format off |
1391 | auto Encoding = |
1392 | StringSwitch<OperandEncoding>(Str) |
1393 | .Case(S: "i16mem" , Value: ENCODING_RM) |
1394 | .Case(S: "i32mem" , Value: ENCODING_RM) |
1395 | .Case(S: "i64mem" , Value: ENCODING_RM) |
1396 | .Case(S: "i8mem" , Value: ENCODING_RM) |
1397 | .Case(S: "shmem" , Value: ENCODING_RM) |
1398 | .Case(S: "ssmem" , Value: ENCODING_RM) |
1399 | .Case(S: "sdmem" , Value: ENCODING_RM) |
1400 | .Case(S: "f128mem" , Value: ENCODING_RM) |
1401 | .Case(S: "f256mem" , Value: ENCODING_RM) |
1402 | .Case(S: "f512mem" , Value: ENCODING_RM) |
1403 | .Case(S: "f64mem" , Value: ENCODING_RM) |
1404 | .Case(S: "f32mem" , Value: ENCODING_RM) |
1405 | .Case(S: "f16mem" , Value: ENCODING_RM) |
1406 | .Case(S: "i128mem" , Value: ENCODING_RM) |
1407 | .Case(S: "i256mem" , Value: ENCODING_RM) |
1408 | .Case(S: "i512mem" , Value: ENCODING_RM) |
1409 | .Case(S: "i512mem_GR16" , Value: ENCODING_RM) |
1410 | .Case(S: "i512mem_GR32" , Value: ENCODING_RM) |
1411 | .Case(S: "i512mem_GR64" , Value: ENCODING_RM) |
1412 | .Case(S: "f80mem" , Value: ENCODING_RM) |
1413 | .Case(S: "lea64_8mem" , Value: ENCODING_RM) |
1414 | .Case(S: "lea64_16mem" , Value: ENCODING_RM) |
1415 | .Case(S: "lea64_32mem" , Value: ENCODING_RM) |
1416 | .Case(S: "lea64mem" , Value: ENCODING_RM) |
1417 | .Case(S: "anymem" , Value: ENCODING_RM) |
1418 | .Case(S: "opaquemem" , Value: ENCODING_RM) |
1419 | .Case(S: "sibmem" , Value: ENCODING_SIB) |
1420 | .Case(S: "vx32mem" , Value: ENCODING_VSIB) |
1421 | .Case(S: "vx64mem" , Value: ENCODING_VSIB) |
1422 | .Case(S: "vy32mem" , Value: ENCODING_VSIB) |
1423 | .Case(S: "vy64mem" , Value: ENCODING_VSIB) |
1424 | .Case(S: "vx32xmem" , Value: ENCODING_VSIB) |
1425 | .Case(S: "vx64xmem" , Value: ENCODING_VSIB) |
1426 | .Case(S: "vy32xmem" , Value: ENCODING_VSIB) |
1427 | .Case(S: "vy64xmem" , Value: ENCODING_VSIB) |
1428 | .Case(S: "vz32mem" , Value: ENCODING_VSIB) |
1429 | .Case(S: "vz64mem" , Value: ENCODING_VSIB) |
1430 | .Default(Value: ENCODING_NONE); |
1431 | // clang-format on |
1432 | |
1433 | if (Encoding != ENCODING_NONE) |
1434 | return Encoding; |
1435 | |
1436 | errs() << "Unhandled memory encoding " << Str << "\n" ; |
1437 | llvm_unreachable("Unhandled memory encoding" ); |
1438 | } |
1439 | |
1440 | OperandEncoding |
1441 | RecognizableInstr::relocationEncodingFromString(StringRef Str, uint8_t OpSize) { |
1442 | StringSwitch<OperandEncoding> Switch(Str); |
1443 | |
1444 | if (OpSize != X86Local::OpSize16) { |
1445 | // For instructions without an OpSize prefix, a declared 16-bit register or |
1446 | // immediate encoding is special. |
1447 | Switch.Case(S: "i16imm" , Value: ENCODING_IW); |
1448 | } |
1449 | |
1450 | // clang-format off |
1451 | OperandEncoding Encoding = |
1452 | Switch.Case(S: "i16imm" , Value: ENCODING_Iv) |
1453 | .Case(S: "i16i8imm" , Value: ENCODING_IB) |
1454 | .Case(S: "i32imm" , Value: ENCODING_Iv) |
1455 | .Case(S: "i32i8imm" , Value: ENCODING_IB) |
1456 | .Case(S: "i64i32imm" , Value: ENCODING_ID) |
1457 | .Case(S: "i64i8imm" , Value: ENCODING_IB) |
1458 | .Case(S: "i8imm" , Value: ENCODING_IB) |
1459 | .Case(S: "u8imm" , Value: ENCODING_IB) |
1460 | .Case(S: "i16u8imm" , Value: ENCODING_IB) |
1461 | .Case(S: "i32u8imm" , Value: ENCODING_IB) |
1462 | .Case(S: "i64u8imm" , Value: ENCODING_IB) |
1463 | .Case(S: "i64i32imm_brtarget" , Value: ENCODING_ID) |
1464 | .Case(S: "i16imm_brtarget" , Value: ENCODING_IW) |
1465 | .Case(S: "i32imm_brtarget" , Value: ENCODING_ID) |
1466 | .Case(S: "i8imm_brtarget" , Value: ENCODING_IB) |
1467 | .Case(S: "brtarget32" , Value: ENCODING_ID) |
1468 | .Case(S: "brtarget16" , Value: ENCODING_IW) |
1469 | .Case(S: "brtarget8" , Value: ENCODING_IB) |
1470 | .Case(S: "i64imm" , Value: ENCODING_IO) |
1471 | .Case(S: "offset16_8" , Value: ENCODING_Ia) |
1472 | .Case(S: "offset16_16" , Value: ENCODING_Ia) |
1473 | .Case(S: "offset16_32" , Value: ENCODING_Ia) |
1474 | .Case(S: "offset32_8" , Value: ENCODING_Ia) |
1475 | .Case(S: "offset32_16" , Value: ENCODING_Ia) |
1476 | .Case(S: "offset32_32" , Value: ENCODING_Ia) |
1477 | .Case(S: "offset32_64" , Value: ENCODING_Ia) |
1478 | .Case(S: "offset64_8" , Value: ENCODING_Ia) |
1479 | .Case(S: "offset64_16" , Value: ENCODING_Ia) |
1480 | .Case(S: "offset64_32" , Value: ENCODING_Ia) |
1481 | .Case(S: "offset64_64" , Value: ENCODING_Ia) |
1482 | .Case(S: "srcidx8" , Value: ENCODING_SI) |
1483 | .Case(S: "srcidx16" , Value: ENCODING_SI) |
1484 | .Case(S: "srcidx32" , Value: ENCODING_SI) |
1485 | .Case(S: "srcidx64" , Value: ENCODING_SI) |
1486 | .Case(S: "dstidx8" , Value: ENCODING_DI) |
1487 | .Case(S: "dstidx16" , Value: ENCODING_DI) |
1488 | .Case(S: "dstidx32" , Value: ENCODING_DI) |
1489 | .Case(S: "dstidx64" , Value: ENCODING_DI) |
1490 | .Default(Value: ENCODING_NONE); |
1491 | // clang-format on |
1492 | |
1493 | if (Encoding != ENCODING_NONE) |
1494 | return Encoding; |
1495 | |
1496 | errs() << "Unhandled relocation encoding " << Str << "\n" ; |
1497 | llvm_unreachable("Unhandled relocation encoding" ); |
1498 | } |
1499 | |
1500 | OperandEncoding |
1501 | RecognizableInstr::opcodeModifierEncodingFromString(StringRef Str, |
1502 | uint8_t OpSize) { |
1503 | // clang-format off |
1504 | auto Encoding = |
1505 | StringSwitch<OperandEncoding>(Str) |
1506 | .Case(S: "GR32" , Value: ENCODING_Rv) |
1507 | .Case(S: "GR64" , Value: ENCODING_RO) |
1508 | .Case(S: "GR16" , Value: ENCODING_Rv) |
1509 | .Case(S: "GR8" , Value: ENCODING_RB) |
1510 | .Case(S: "ccode" , Value: ENCODING_CC) |
1511 | .Default(Value: ENCODING_NONE); |
1512 | // clang-format on |
1513 | if (Encoding != ENCODING_NONE) |
1514 | return Encoding; |
1515 | |
1516 | errs() << "Unhandled opcode modifier encoding " << Str << "\n" ; |
1517 | llvm_unreachable("Unhandled opcode modifier encoding" ); |
1518 | } |
1519 | |