Skip to content

Commit 4daea50

Browse files
authored
[X86][MC] Support encoding/decoding for APX variant MUL/IMUL/DIV/IDIV instructions (#76919)
Four variants: promoted legacy, ND (new data destination), NF (no flags update) and NF_ND (NF + ND). The syntax of NF instructions is aligned with GNU binutils. https://sourceware.org/pipermail/binutils/2023-September/129545.html
1 parent 67963d3 commit 4daea50

File tree

15 files changed

+1438
-65
lines changed

15 files changed

+1438
-65
lines changed

llvm/lib/Target/X86/X86InstrArithmetic.td

Lines changed: 218 additions & 65 deletions
Large diffs are not rendered by default.

llvm/lib/Target/X86/X86InstrPredicates.td

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,41 @@
88

99
def TruePredicate : Predicate<"true">;
1010

11+
// Intel x86 instructions have three separate encoding spaces: legacy, VEX, and
12+
// EVEX. Not all X86 instructions are extended for EGPR. The following is an
13+
// overview of which instructions are extended and how we implement them.
14+
//
15+
// * Legacy space
16+
// All instructions in legacy maps 0 and 1 that have explicit GPR or memory
17+
// operands can use the REX2 prefix to access the EGPR, except XSAVE*/XRSTOR.
18+
//
19+
// * EVEX space
20+
// All instructions in the EVEX space can access the EGPR in their
21+
// register/memory operands.
22+
//
23+
// For the above intructions, the only difference in encoding is reflected in
24+
// the REX2/EVEX prefix when EGPR is used, i.e. the opcode and opcode name are
25+
// unchanged. We don’t add new entries in TD, and instead we extend GPR with
26+
// R16-R31 and make them allocatable only when the feature EGPR is available.
27+
//
28+
// Besides, some instructions in legacy space with map 2/3 and VEX space are
29+
// promoted into EVEX space. Encoding space changes after the promotion, opcode
30+
// and opcode map may change too sometimes. For these instructions, we add new
31+
// entries in TD to avoid overcomplicating the assembler and disassembler.
32+
//
33+
// HasEGPR is for the new entries and NoEGPR is for the entries before
34+
// promotion, so that the promoted variant can be selected first to benefit RA.
1135
def HasEGPR : Predicate<"Subtarget->hasEGPR()">;
1236
def NoEGPR : Predicate<"!Subtarget->hasEGPR()">;
37+
38+
// APX extends some instructions with a new form that has an extra register
39+
// operand called a new data destination (NDD). In such forms, NDD is the new
40+
// destination register receiving the result of the computation and all other
41+
// operands (including the original destination operand) become read-only source
42+
// operands.
43+
//
44+
// HasNDD is for the new NDD entries and NoNDD is for the legacy 2-address
45+
// entries, so that the NDD variant can be selected first to benefit RA.
1346
def HasNDD : Predicate<"Subtarget->hasNDD()">;
1447
def NoNDD : Predicate<"!Subtarget->hasNDD()">;
1548
def HasCMOV : Predicate<"Subtarget->canUseCMOV()">;
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# RUN: llvm-mc -triple x86_64 -disassemble %s | FileCheck %s --check-prefix=ATT
2+
# RUN: llvm-mc -triple x86_64 -disassemble -output-asm-variant=1 %s | FileCheck %s --check-prefix=INTEL
3+
4+
# ATT: {evex} divb %bl
5+
# INTEL: {evex} div bl
6+
0x62,0xf4,0x7c,0x08,0xf6,0xf3
7+
8+
# ATT: {nf} divb %bl
9+
# INTEL: {nf} div bl
10+
0x62,0xf4,0x7c,0x0c,0xf6,0xf3
11+
12+
# ATT: {evex} divw %dx
13+
# INTEL: {evex} div dx
14+
0x62,0xf4,0x7d,0x08,0xf7,0xf2
15+
16+
# ATT: {nf} divw %dx
17+
# INTEL: {nf} div dx
18+
0x62,0xf4,0x7d,0x0c,0xf7,0xf2
19+
20+
# ATT: {evex} divl %ecx
21+
# INTEL: {evex} div ecx
22+
0x62,0xf4,0x7c,0x08,0xf7,0xf1
23+
24+
# ATT: {nf} divl %ecx
25+
# INTEL: {nf} div ecx
26+
0x62,0xf4,0x7c,0x0c,0xf7,0xf1
27+
28+
# ATT: {evex} divq %r9
29+
# INTEL: {evex} div r9
30+
0x62,0xd4,0xfc,0x08,0xf7,0xf1
31+
32+
# ATT: {nf} divq %r9
33+
# INTEL: {nf} div r9
34+
0x62,0xd4,0xfc,0x0c,0xf7,0xf1
35+
36+
# ATT: {evex} divb 291(%r8,%rax,4)
37+
# INTEL: {evex} div byte ptr [r8 + 4*rax + 291]
38+
0x62,0xd4,0x7c,0x08,0xf6,0xb4,0x80,0x23,0x01,0x00,0x00
39+
40+
# ATT: {nf} divb 291(%r8,%rax,4)
41+
# INTEL: {nf} div byte ptr [r8 + 4*rax + 291]
42+
0x62,0xd4,0x7c,0x0c,0xf6,0xb4,0x80,0x23,0x01,0x00,0x00
43+
44+
# ATT: {evex} divw 291(%r8,%rax,4)
45+
# INTEL: {evex} div word ptr [r8 + 4*rax + 291]
46+
0x62,0xd4,0x7d,0x08,0xf7,0xb4,0x80,0x23,0x01,0x00,0x00
47+
48+
# ATT: {nf} divw 291(%r8,%rax,4)
49+
# INTEL: {nf} div word ptr [r8 + 4*rax + 291]
50+
0x62,0xd4,0x7d,0x0c,0xf7,0xb4,0x80,0x23,0x01,0x00,0x00
51+
52+
# ATT: {evex} divl 291(%r8,%rax,4)
53+
# INTEL: {evex} div dword ptr [r8 + 4*rax + 291]
54+
0x62,0xd4,0x7c,0x08,0xf7,0xb4,0x80,0x23,0x01,0x00,0x00
55+
56+
# ATT: {nf} divl 291(%r8,%rax,4)
57+
# INTEL: {nf} div dword ptr [r8 + 4*rax + 291]
58+
0x62,0xd4,0x7c,0x0c,0xf7,0xb4,0x80,0x23,0x01,0x00,0x00
59+
60+
# ATT: {evex} divq 291(%r8,%rax,4)
61+
# INTEL: {evex} div qword ptr [r8 + 4*rax + 291]
62+
0x62,0xd4,0xfc,0x08,0xf7,0xb4,0x80,0x23,0x01,0x00,0x00
63+
64+
# ATT: {nf} divq 291(%r8,%rax,4)
65+
# INTEL: {nf} div qword ptr [r8 + 4*rax + 291]
66+
0x62,0xd4,0xfc,0x0c,0xf7,0xb4,0x80,0x23,0x01,0x00,0x00
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# RUN: llvm-mc -triple x86_64 -disassemble %s | FileCheck %s --check-prefix=ATT
2+
# RUN: llvm-mc -triple x86_64 -disassemble -output-asm-variant=1 %s | FileCheck %s --check-prefix=INTEL
3+
4+
# ATT: {evex} idivb %bl
5+
# INTEL: {evex} idiv bl
6+
0x62,0xf4,0x7c,0x08,0xf6,0xfb
7+
8+
# ATT: {nf} idivb %bl
9+
# INTEL: {nf} idiv bl
10+
0x62,0xf4,0x7c,0x0c,0xf6,0xfb
11+
12+
# ATT: {evex} idivw %dx
13+
# INTEL: {evex} idiv dx
14+
0x62,0xf4,0x7d,0x08,0xf7,0xfa
15+
16+
# ATT: {nf} idivw %dx
17+
# INTEL: {nf} idiv dx
18+
0x62,0xf4,0x7d,0x0c,0xf7,0xfa
19+
20+
# ATT: {evex} idivl %ecx
21+
# INTEL: {evex} idiv ecx
22+
0x62,0xf4,0x7c,0x08,0xf7,0xf9
23+
24+
# ATT: {nf} idivl %ecx
25+
# INTEL: {nf} idiv ecx
26+
0x62,0xf4,0x7c,0x0c,0xf7,0xf9
27+
28+
# ATT: {evex} idivq %r9
29+
# INTEL: {evex} idiv r9
30+
0x62,0xd4,0xfc,0x08,0xf7,0xf9
31+
32+
# ATT: {nf} idivq %r9
33+
# INTEL: {nf} idiv r9
34+
0x62,0xd4,0xfc,0x0c,0xf7,0xf9
35+
36+
# ATT: {evex} idivb 291(%r8,%rax,4)
37+
# INTEL: {evex} idiv byte ptr [r8 + 4*rax + 291]
38+
0x62,0xd4,0x7c,0x08,0xf6,0xbc,0x80,0x23,0x01,0x00,0x00
39+
40+
# ATT: {nf} idivb 291(%r8,%rax,4)
41+
# INTEL: {nf} idiv byte ptr [r8 + 4*rax + 291]
42+
0x62,0xd4,0x7c,0x0c,0xf6,0xbc,0x80,0x23,0x01,0x00,0x00
43+
44+
# ATT: {evex} idivw 291(%r8,%rax,4)
45+
# INTEL: {evex} idiv word ptr [r8 + 4*rax + 291]
46+
0x62,0xd4,0x7d,0x08,0xf7,0xbc,0x80,0x23,0x01,0x00,0x00
47+
48+
# ATT: {nf} idivw 291(%r8,%rax,4)
49+
# INTEL: {nf} idiv word ptr [r8 + 4*rax + 291]
50+
0x62,0xd4,0x7d,0x0c,0xf7,0xbc,0x80,0x23,0x01,0x00,0x00
51+
52+
# ATT: {evex} idivl 291(%r8,%rax,4)
53+
# INTEL: {evex} idiv dword ptr [r8 + 4*rax + 291]
54+
0x62,0xd4,0x7c,0x08,0xf7,0xbc,0x80,0x23,0x01,0x00,0x00
55+
56+
# ATT: {nf} idivl 291(%r8,%rax,4)
57+
# INTEL: {nf} idiv dword ptr [r8 + 4*rax + 291]
58+
0x62,0xd4,0x7c,0x0c,0xf7,0xbc,0x80,0x23,0x01,0x00,0x00
59+
60+
# ATT: {evex} idivq 291(%r8,%rax,4)
61+
# INTEL: {evex} idiv qword ptr [r8 + 4*rax + 291]
62+
0x62,0xd4,0xfc,0x08,0xf7,0xbc,0x80,0x23,0x01,0x00,0x00
63+
64+
# ATT: {nf} idivq 291(%r8,%rax,4)
65+
# INTEL: {nf} idiv qword ptr [r8 + 4*rax + 291]
66+
0x62,0xd4,0xfc,0x0c,0xf7,0xbc,0x80,0x23,0x01,0x00,0x00

0 commit comments

Comments
 (0)