llvm.org GIT mirror llvm / 048f392
[X86][3DNOW] Teach decoder about AMD 3DNow! instrs Summary: This patch makes the decoder understand old AMD 3DNow! instructions that have never been properly supported in the X86 disassembler, despite being supported in other subsystems. Hopefully this should make the X86 decoder more complete with respect to binaries containing legacy code. Reviewers: craig.topper Reviewed By: craig.topper Subscribers: llvm-commits, maksfb, bruno Differential Revision: https://reviews.llvm.org/D43311 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@325295 91177308-0d34-0410-b5e6-96231b3b80d8 Rafael Auler 2 years ago
8 changed file(s) with 156 addition(s) and 32 deletion(s). Raw diff Collapse all Expand all
587587 insn->vectorExtensionPrefix[0], insn->vectorExtensionPrefix[1],
588588 insn->vectorExtensionPrefix[2]);
589589 }
590 } else if (byte == 0x0f) {
591 uint8_t byte1;
592
593 // Check for AMD 3DNow without a REX prefix
594 if (consumeByte(insn, &byte1)) {
595 unconsumeByte(insn);
596 } else {
597 if (byte1 != 0x0f) {
598 unconsumeByte(insn);
599 unconsumeByte(insn);
600 } else {
601 dbgprintf(insn, "Found AMD 3DNow prefix 0f0f");
602 insn->vectorExtensionType = TYPE_3DNOW;
603 }
604 }
590605 } else if (isREX(insn, byte)) {
591606 if (lookAtByte(insn, &nextByte))
592607 return -1;
593608 insn->rexPrefix = byte;
594609 dbgprintf(insn, "Found REX prefix 0x%hhx", byte);
610
611 // Check for AMD 3DNow with a REX prefix
612 if (nextByte == 0x0f) {
613 consumeByte(insn, &nextByte);
614 uint8_t byte1;
615
616 if (consumeByte(insn, &byte1)) {
617 unconsumeByte(insn);
618 } else {
619 if (byte1 != 0x0f) {
620 unconsumeByte(insn);
621 unconsumeByte(insn);
622 } else {
623 dbgprintf(insn, "Found AMD 3DNow prefix 0f0f");
624 insn->vectorExtensionType = TYPE_3DNOW;
625 }
626 }
627 }
595628 } else
596629 unconsumeByte(insn);
597630
622655 return 0;
623656 }
624657
658 static int readModRM(struct InternalInstruction* insn);
659
625660 /*
626661 * readOpcode - Reads the opcode (excepting the ModR/M byte in the case of
627662 * extended or escape opcodes).
689724 insn->opcodeType = XOPA_MAP;
690725 return consumeByte(insn, &insn->opcode);
691726 }
727 } else if (insn->vectorExtensionType == TYPE_3DNOW) {
728 // Consume operands before the opcode to comply with the 3DNow encoding
729 if (readModRM(insn))
730 return -1;
731 insn->opcodeType = TWOBYTE;
732 return consumeByte(insn, &insn->opcode);
692733 }
693734
694735 if (consumeByte(insn, ¤t))
733774
734775 return 0;
735776 }
736
737 static int readModRM(struct InternalInstruction* insn);
738777
739778 /*
740779 * getIDWithAttrMask - Determines the ID of an instruction, consuming
911950
912951 if (lFromXOP3of3(insn->vectorExtensionPrefix[2]))
913952 attrMask |= ATTR_VEXL;
953 } else if (insn->vectorExtensionType == TYPE_3DNOW) {
954 attrMask |= ATTR_3DNOW;
914955 } else {
915956 return -1;
916957 }
492492 TYPE_VEX_2B = 0x1,
493493 TYPE_VEX_3B = 0x2,
494494 TYPE_EVEX = 0x3,
495 TYPE_XOP = 0x4
495 TYPE_XOP = 0x4,
496 TYPE_3DNOW = 0x5
496497 };
497498
498499 /// \brief Type for the byte reader that the consumer must provide to
5959 ENUM_ENTRY(ATTR_EVEXL2, (0x1 << 10)) \
6060 ENUM_ENTRY(ATTR_EVEXK, (0x1 << 11)) \
6161 ENUM_ENTRY(ATTR_EVEXKZ, (0x1 << 12)) \
62 ENUM_ENTRY(ATTR_EVEXB, (0x1 << 13))
62 ENUM_ENTRY(ATTR_EVEXB, (0x1 << 13)) \
63 ENUM_ENTRY(ATTR_3DNOW, (0x1 << 14))
6364
6465 #define ENUM_ENTRY(n, v) n = v,
6566 enum attributeBits {
269270 ENUM_ENTRY(IC_EVEX_L2_W_KZ, 3, "requires EVEX_KZ, L2 and W") \
270271 ENUM_ENTRY(IC_EVEX_L2_W_XS_KZ, 4, "requires EVEX_KZ, L2, W and XS prefix") \
271272 ENUM_ENTRY(IC_EVEX_L2_W_XD_KZ, 4, "requires EVEX_KZ, L2, W and XD prefix") \
272 ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_KZ, 4, "requires EVEX_KZ, L2, W and OpSize")
273 ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_KZ, 4, "requires EVEX_KZ, L2, W and OpSize") \
274 ENUM_ENTRY(IC_3DNOW, 8, "requires AMD 3DNow prefix 0f0f")
273275
274276 #define ENUM_ENTRY(n, r, d) n,
275277 enum InstructionContext {
5151 : I3DNow
5252 !strconcat(Mnemonic, "\t{$src2, $dst|$dst, $src2}"), pat, itin>,
5353 Has3DNow0F0FOpcode {
54 // FIXME: The disassembler doesn't support Has3DNow0F0FOpcode yet.
55 let isAsmParserOnly = 1;
5654 let Constraints = "$src1 = $dst";
5755 }
5856
6058 InstrItinClass itin>
6159 : I3DNow
6260 !strconcat(Mnemonic, "\t{$src, $dst|$dst, $src}"), pat, itin>,
63 Has3DNow0F0FOpcode {
64 // FIXME: The disassembler doesn't support Has3DNow0F0FOpcode yet.
65 let isAsmParserOnly = 1;
66 }
61 Has3DNow0F0FOpcode;
6762
6863 multiclass I3DNow_binop_rm_int opc, string Mn, OpndItins itins,
6964 bit Commutable = 0, string Ver = ""> {
0 # RUN: llvm-mc --disassemble %s -triple=x86_64-unknown-linux-gnu | FileCheck %s
1
2 # Reference: AMD64 Architecture Programmer's Manual Vol.3
3 # Pub no. 24594 - Rev. 3.25 - Dec 2017 - pgs.468-469
4
5 # CHECK: pfcmpge %mm0, %mm1
6 0x0f 0x0f 0xc8 0x90
7
8 # CHECK: pfcmpgt %mm2, %mm0
9 0x0f 0x0f 0xc2 0xa0
10
11 # CHECK: pfcmpeq %mm5, %mm2
12 0x0f 0x0f 0xd5 0xb0
13
14 # CHECK: pfmin %mm1, %mm0
15 0x0f 0x0f 0xc1 0x94
16
17 # CHECK: pfmax (%rax), %mm0
18 0x0f 0x0f 0x00 0xa4
19
20 # CHECK: pfmul %mm6, %mm0
21 0x0f 0x0f 0xc6 0xb4
22
23 # CHECK: pfrcp (%rbx), %mm1
24 0x0f 0x0f 0x0b 0x96
25
26 # CHECK: pfrcpit1 %mm0, %mm2
27 0x0f 0x0f 0xd0 0xa6
28
29 # CHECK: pfrcpit2 %mm0, %mm1
30 0x0f 0x0f 0xc8 0xb6
31
32 # CHECK: pfrsqrt (%eax), %mm1
33 0x67 0x0f 0x0f 0x08 0x97
34
35 # CHECK: pfrsqit1 (%ebx), %mm4
36 0x67 0x0f 0x0f 0x23 0xa7
37
38 # CHECK: pmulhrw %mm3, %mm0
39 0x0f 0x0f 0xc3 0xb7
40
41 # CHECK: pi2fw %mm1, %mm3
42 0x0f 0x0f 0xd9 0x0c
43
44 # CHECK: pf2iw %mm2, %mm4
45 0x0f 0x0f 0xe2 0x1c
46
47 # CHECK: pi2fd %mm3, %mm1
48 0x0f 0x0f 0xcb 0x0d
49
50 # CHECK: pf2id (%rdi,%r8), %mm1
51 0x42 0x0f 0x0f 0x0c 0x07 0x1d
52
53 # CHECK: pfnacc 16(%eax,%ebx,4), %mm0
54 0x67 0x0f 0x0f 0x44 0x98 0x10 0x8a
55
56 # CHECK: pfsub %mm1, %mm0
57 0x0f 0x0f 0xc1 0x9a
58
59 # CHECK: pfsubr %mm2, %mm1
60 0x0f 0x0f 0xca 0xaa
61
62 # CHECK: pswapd %mm1, %mm3
63 0x0f 0x0f 0xd9 0xbb
64
65 # CHECK: pfpnacc %mm0, %mm2
66 0x0f 0x0f 0xd0 0x8e
67
68 # CHECK: pfadd %mm4, %mm3
69 0x0f 0x0f 0xdc 0x9e
70
71 # CHECK: pfacc %mm1, %mm2
72 0x0f 0x0f 0xd1 0xae
73
74 # CHECK: pavgusb %mm1, %mm3
75 0x0f 0x0f 0xd9 0xbf
545545 case IC_EVEX_L2_W_XD_KZ_B:
546546 case IC_EVEX_L2_W_OPSIZE_KZ_B:
547547 return false;
548 case IC_3DNOW:
549 return false;
548550 default:
549551 errs() << "Unknown instruction class: " <<
550552 stringForContext((InstructionContext)parent) << "\n";
887889 }
888890
889891 void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
890 const unsigned int tableSize = 16384;
892 const unsigned int tableSize = 32768;
891893 o.indent(i * 2) << "static const uint8_t " CONTEXTS_STR
892894 "[" << tableSize << "] = {\n";
893895 i++;
895897 for (unsigned index = 0; index < tableSize; ++index) {
896898 o.indent(i * 2);
897899
898 if (index & ATTR_EVEX) {
900 if (index & ATTR_3DNOW)
901 o << "IC_3DNOW";
902 else if (index & ATTR_EVEX) {
899903 o << "IC_EVEX";
900904 if (index & ATTR_EVEXL2)
901905 o << "_L2";
7979 Form = byteFromRec(Rec, "FormBits");
8080 Encoding = byteFromRec(Rec, "OpEncBits");
8181
82 OpSize = byteFromRec(Rec, "OpSizeBits");
83 AdSize = byteFromRec(Rec, "AdSizeBits");
84 HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix");
85 HasVEX_4V = Rec->getValueAsBit("hasVEX_4V");
86 VEX_WPrefix = byteFromRec(Rec,"VEX_WPrefix");
87 IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L");
88 HasEVEX_L2Prefix = Rec->getValueAsBit("hasEVEX_L2");
89 HasEVEX_K = Rec->getValueAsBit("hasEVEX_K");
90 HasEVEX_KZ = Rec->getValueAsBit("hasEVEX_Z");
91 HasEVEX_B = Rec->getValueAsBit("hasEVEX_B");
92 IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly");
93 ForceDisassemble = Rec->getValueAsBit("ForceDisassemble");
94 CD8_Scale = byteFromRec(Rec, "CD8_Scale");
82 OpSize = byteFromRec(Rec, "OpSizeBits");
83 AdSize = byteFromRec(Rec, "AdSizeBits");
84 HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix");
85 HasVEX_4V = Rec->getValueAsBit("hasVEX_4V");
86 VEX_WPrefix = byteFromRec(Rec,"VEX_WPrefix");
87 IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L");
88 HasEVEX_L2Prefix = Rec->getValueAsBit("hasEVEX_L2");
89 HasEVEX_K = Rec->getValueAsBit("hasEVEX_K");
90 HasEVEX_KZ = Rec->getValueAsBit("hasEVEX_Z");
91 HasEVEX_B = Rec->getValueAsBit("hasEVEX_B");
92 Has3DNow0F0FOpcode = Rec->getValueAsBit("has3DNow0F0FOpcode");
93 IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly");
94 ForceDisassemble = Rec->getValueAsBit("ForceDisassemble");
95 CD8_Scale = byteFromRec(Rec, "CD8_Scale");
9596
9697 Name = Rec->getName();
9798
287288 errs() << "Instruction does not use a prefix: " << Name << "\n";
288289 llvm_unreachable("Invalid prefix");
289290 }
291 } else if (Has3DNow0F0FOpcode) {
292 insnContext = IC_3DNOW;
290293 } else if (Is64Bit || HasREX_WPrefix || AdSize == X86Local::AdSize64) {
291294 if (HasREX_WPrefix && (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD))
292295 insnContext = IC_64BIT_REXW_OPSIZE;
190190 bool HasEVEX_KZ;
191191 /// The hasEVEX_B field from the record
192192 bool HasEVEX_B;
193 /// The has3DNow0F0FOpcode field from the record
194 bool Has3DNow0F0FOpcode;
193195 /// Indicates that the instruction uses the L and L' fields for RC.
194196 bool EncodeRC;
195197 /// The isCodeGenOnly field from the record
209211 /// Indicates whether the instruction should be emitted into the decode
210212 /// tables; regardless, it will be emitted into the instruction info table
211213 bool ShouldBeEmitted;
212
214
213215 /// The operands of the instruction, as listed in the CodeGenInstruction.
214216 /// They are not one-to-one with operands listed in the MCInst; for example,
215217 /// memory operands expand to 5 operands in the MCInst
216218 const std::vector* Operands;
217
219
218220 /// The description of the instruction that is emitted into the instruction
219221 /// info table
220222 InstructionSpecifier* Spec;
282284 /// operand exists.
283285 /// @param operandIndex - The index into the generated operand table.
284286 /// Incremented by this function one or more
285 /// times to reflect possible duplicate
287 /// times to reflect possible duplicate
286288 /// operands).
287289 /// @param physicalOperandIndex - The index of the current operand into the
288290 /// set of non-duplicate ('physical') operands.
313315 bool shouldBeEmitted() const {
314316 return ShouldBeEmitted;
315317 }
316
318
317319 /// emitInstructionSpecifier - Loads the instruction specifier for the current
318320 /// instruction into a DisassemblerTables.
319321 ///
320322 void emitInstructionSpecifier();
321
323
322324 /// emitDecodePath - Populates the proper fields in the decode tables
323325 /// corresponding to the decode paths for this instruction.
324326 ///
348350 const CodeGenInstruction &insn,
349351 InstrUID uid);
350352 };
351
353
352354 } // namespace X86Disassembler
353355
354356 } // namespace llvm