Skip to content

Commit 8c2537f

Browse files
authored
[X86][MC] Support encoding/decoding for PUSH2[P]/POP2[P] (#73233)
PUSH2 and POP2 are two new instructions for (respectively) pushing/popping 2 GPRs at a time to/from the stack. The opcodes of PUSH2 and POP2 are those of “PUSH r/m” and “POP r/m” from legacy map 0, but we require ModRM.Mod = 3 in order to disallow memory operand. The 1-bit Push-Pop Acceleration hint described in #73092 applies to PUSH2/POP2 too, then we have PUSH2P/POP2P. For AT&T syntax, PUSH2[P] pushes the registers from right to left onto the stack. POP2[P] pops the stack to registers from right to left. Intel syntax has the opposite order - from left to right. The assembly syntax is aligned with GCC & binutils https://gcc.gnu.org/pipermail/gcc-patches/2023-November/637718.html
1 parent be0307d commit 8c2537f

17 files changed

+358
-20
lines changed

llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ namespace X86Disassembler {
3131
#define XOP9_MAP_SYM x86DisassemblerXOP9Opcodes
3232
#define XOPA_MAP_SYM x86DisassemblerXOPAOpcodes
3333
#define THREEDNOW_MAP_SYM x86Disassembler3DNowOpcodes
34+
#define MAP4_SYM x86DisassemblerMap4Opcodes
3435
#define MAP5_SYM x86DisassemblerMap5Opcodes
3536
#define MAP6_SYM x86DisassemblerMap6Opcodes
3637
#define MAP7_SYM x86DisassemblerMap7Opcodes
@@ -45,6 +46,7 @@ namespace X86Disassembler {
4546
#define XOP9_MAP_STR "x86DisassemblerXOP9Opcodes"
4647
#define XOPA_MAP_STR "x86DisassemblerXOPAOpcodes"
4748
#define THREEDNOW_MAP_STR "x86Disassembler3DNowOpcodes"
49+
#define MAP4_STR "x86DisassemblerMap4Opcodes"
4850
#define MAP5_STR "x86DisassemblerMap5Opcodes"
4951
#define MAP6_STR "x86DisassemblerMap6Opcodes"
5052
#define MAP7_STR "x86DisassemblerMap7Opcodes"
@@ -324,9 +326,10 @@ enum OpcodeType {
324326
XOP9_MAP = 5,
325327
XOPA_MAP = 6,
326328
THREEDNOW_MAP = 7,
327-
MAP5 = 8,
328-
MAP6 = 9,
329-
MAP7 = 10
329+
MAP4 = 8,
330+
MAP5 = 9,
331+
MAP6 = 10,
332+
MAP7 = 11
330333
};
331334

332335
// The following structs are used for the hierarchical decode table. After

llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ static InstrUID decode(OpcodeType type, InstructionContext insnContext,
150150
dec =
151151
&THREEDNOW_MAP_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
152152
break;
153+
case MAP4:
154+
dec = &MAP4_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
155+
break;
153156
case MAP5:
154157
dec = &MAP5_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
155158
break;
@@ -929,6 +932,9 @@ static bool readOpcode(struct InternalInstruction *insn) {
929932
case VEX_LOB_0F3A:
930933
insn->opcodeType = THREEBYTE_3A;
931934
return consume(insn, insn->opcode);
935+
case VEX_LOB_MAP4:
936+
insn->opcodeType = MAP4;
937+
return consume(insn, insn->opcode);
932938
case VEX_LOB_MAP5:
933939
insn->opcodeType = MAP5;
934940
return consume(insn, insn->opcode);
@@ -1100,6 +1106,9 @@ static int getInstructionIDWithAttrMask(uint16_t *instructionID,
11001106
case THREEDNOW_MAP:
11011107
decision = &THREEDNOW_MAP_SYM;
11021108
break;
1109+
case MAP4:
1110+
decision = &MAP4_SYM;
1111+
break;
11031112
case MAP5:
11041113
decision = &MAP5_SYM;
11051114
break;

llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@ enum VEXLeadingOpcodeByte {
628628
VEX_LOB_0F = 0x1,
629629
VEX_LOB_0F38 = 0x2,
630630
VEX_LOB_0F3A = 0x3,
631+
VEX_LOB_MAP4 = 0x4,
631632
VEX_LOB_MAP5 = 0x5,
632633
VEX_LOB_MAP6 = 0x6,
633634
VEX_LOB_MAP7 = 0x7

llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -757,10 +757,11 @@ enum : uint64_t {
757757
/// we handle this by storeing the classifier in the opcode field and using
758758
/// this flag to indicate that the encoder should do the wacky 3DNow! thing.
759759
ThreeDNow = 7 << OpMapShift,
760-
/// MAP5, MAP6, MAP7 - Prefix after the 0x0F prefix.
761-
T_MAP5 = 8 << OpMapShift,
762-
T_MAP6 = 9 << OpMapShift,
763-
T_MAP7 = 10 << OpMapShift,
760+
/// MAP4, MAP5, MAP6, MAP7 - Prefix after the 0x0F prefix.
761+
T_MAP4 = 8 << OpMapShift,
762+
T_MAP5 = 9 << OpMapShift,
763+
T_MAP6 = 10 << OpMapShift,
764+
T_MAP7 = 11 << OpMapShift,
764765
//===------------------------------------------------------------------===//
765766
/// REX_W - REX prefixes are instruction prefixes used in 64-bit mode.
766767
/// They are used to specify GPRs and SSE registers, 64-bit operand size,

llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,9 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
10131013
case X86II::XOPA:
10141014
Prefix.set5M(0xA);
10151015
break;
1016+
case X86II::T_MAP4:
1017+
Prefix.set5M(0x4);
1018+
break;
10161019
case X86II::T_MAP5:
10171020
Prefix.set5M(0x5);
10181021
break;

llvm/lib/Target/X86/X86InstrFormats.td

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,10 @@ def XOP8 : Map<4>;
161161
def XOP9 : Map<5>;
162162
def XOPA : Map<6>;
163163
def ThreeDNow : Map<7>;
164-
def T_MAP5 : Map<8>;
165-
def T_MAP6 : Map<9>;
166-
def T_MAP7 : Map<10>;
164+
def T_MAP4 : Map<8>;
165+
def T_MAP5 : Map<9>;
166+
def T_MAP6 : Map<10>;
167+
def T_MAP7 : Map<11>;
167168

168169
// Class specifying the encoding
169170
class Encoding<bits<2> val> {
@@ -208,6 +209,11 @@ class XOP8 { Map OpMap = XOP8; Prefix OpPrefix = PS; }
208209
class XOP9 { Map OpMap = XOP9; Prefix OpPrefix = PS; }
209210
class XOPA { Map OpMap = XOPA; Prefix OpPrefix = PS; }
210211
class ThreeDNow { Map OpMap = ThreeDNow; }
212+
class T_MAP4 { Map OpMap = T_MAP4; }
213+
class T_MAP4PS : T_MAP4 { Prefix OpPrefix = PS; } // none
214+
class T_MAP4PD : T_MAP4 { Prefix OpPrefix = PD; } // 0x66
215+
class T_MAP4XS : T_MAP4 { Prefix OpPrefix = XS; } // 0xF3
216+
class T_MAP4XD : T_MAP4 { Prefix OpPrefix = XD; } // 0xF2
211217
class T_MAP5 { Map OpMap = T_MAP5; }
212218
class T_MAP5PS : T_MAP5 { Prefix OpPrefix = PS; } // none
213219
class T_MAP5PD : T_MAP5 { Prefix OpPrefix = PD; } // 0x66

llvm/lib/Target/X86/X86InstrMisc.td

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,13 @@ def POP64rmr: I<0x8F, MRM0r, (outs GR64:$reg), (ins), "pop{q}\t$reg", []>,
163163
} // isCodeGenOnly = 1, ForceDisassemble = 1
164164
def POPP64r : I<0x58, AddRegFrm, (outs GR64:$reg), (ins), "popp\t$reg", []>,
165165
REX_W, ExplicitREX2Prefix, Requires<[In64BitMode]>;
166+
def POP2: I<0x8F, MRM0r, (outs GR64:$reg1, GR64:$reg2), (ins),
167+
"pop2\t{$reg2, $reg1|$reg1, $reg2}",
168+
[]>, EVEX_4V, EVEX_B, T_MAP4PS;
169+
def POP2P: I<0x8F, MRM0r, (outs GR64:$reg1, GR64:$reg2), (ins),
170+
"pop2p\t{$reg2, $reg1|$reg1, $reg2}",
171+
[]>, EVEX_4V, EVEX_B, T_MAP4PS, REX_W;
172+
166173
} // mayLoad, SchedRW
167174
let mayLoad = 1, mayStore = 1, SchedRW = [WriteCopy] in
168175
def POP64rmm: I<0x8F, MRM0m, (outs), (ins i64mem:$dst), "pop{q}\t$dst", []>,
@@ -177,6 +184,12 @@ def PUSH64rmr: I<0xFF, MRM6r, (outs), (ins GR64:$reg), "push{q}\t$reg", []>,
177184
} // isCodeGenOnly = 1, ForceDisassemble = 1
178185
def PUSHP64r : I<0x50, AddRegFrm, (outs), (ins GR64:$reg), "pushp\t$reg", []>,
179186
REX_W, ExplicitREX2Prefix, Requires<[In64BitMode]>;
187+
def PUSH2: I<0xFF, MRM6r, (outs), (ins GR64:$reg1, GR64:$reg2),
188+
"push2\t{$reg2, $reg1|$reg1, $reg2}",
189+
[]>, EVEX_4V, EVEX_B, T_MAP4PS;
190+
def PUSH2P: I<0xFF, MRM6r, (outs), (ins GR64:$reg1, GR64:$reg2),
191+
"push2p\t{$reg2, $reg1|$reg1, $reg2}",
192+
[]>, EVEX_4V, EVEX_B, T_MAP4PS, REX_W;
180193
} // mayStore, SchedRW
181194
let mayLoad = 1, mayStore = 1, SchedRW = [WriteCopy] in {
182195
def PUSH64rmm: I<0xFF, MRM6m, (outs), (ins i64mem:$src), "push{q}\t$src", []>,
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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: push2 %rax, %rdi
5+
# INTEL: push2 rdi, rax
6+
0x62,0xf4,0x44,0x18,0xff,0xf0
7+
8+
# ATT: push2 %rdi, %r8
9+
# INTEL: push2 r8, rdi
10+
0x62,0xf4,0x3c,0x18,0xff,0xf7
11+
12+
# ATT: push2 %r8, %r15
13+
# INTEL: push2 r15, r8
14+
0x62,0xd4,0x04,0x18,0xff,0xf0
15+
16+
# ATT: push2 %r15, %r16
17+
# INTEL: push2 r16, r15
18+
0x62,0xd4,0x7c,0x10,0xff,0xf7
19+
20+
# ATT: push2 %r16, %r23
21+
# INTEL: push2 r23, r16
22+
0x62,0xfc,0x44,0x10,0xff,0xf0
23+
24+
# ATT: push2 %r23, %r24
25+
# INTEL: push2 r24, r23
26+
0x62,0xfc,0x3c,0x10,0xff,0xf7
27+
28+
# ATT: push2 %r24, %r31
29+
# INTEL: push2 r31, r24
30+
0x62,0xdc,0x04,0x10,0xff,0xf0
31+
32+
# ATT: pop2 %rax, %rdi
33+
# INTEL: pop2 rdi, rax
34+
0x62,0xf4,0x44,0x18,0x8f,0xc0
35+
36+
# ATT: pop2 %rdi, %r8
37+
# INTEL: pop2 r8, rdi
38+
0x62,0xf4,0x3c,0x18,0x8f,0xc7
39+
40+
# ATT: pop2 %r8, %r15
41+
# INTEL: pop2 r15, r8
42+
0x62,0xd4,0x04,0x18,0x8f,0xc0
43+
44+
# ATT: pop2 %r15, %r16
45+
# INTEL: pop2 r16, r15
46+
0x62,0xd4,0x7c,0x10,0x8f,0xc7
47+
48+
# ATT: pop2 %r16, %r23
49+
# INTEL: pop2 r23, r16
50+
0x62,0xfc,0x44,0x10,0x8f,0xc0
51+
52+
# ATT: pop2 %r23, %r24
53+
# INTEL: pop2 r24, r23
54+
0x62,0xfc,0x3c,0x10,0x8f,0xc7
55+
56+
# ATT: pop2 %r24, %r31
57+
# INTEL: pop2 r31, r24
58+
0x62,0xdc,0x04,0x10,0x8f,0xc0
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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: push2p %rax, %rdi
5+
# INTEL: push2p rdi, rax
6+
0x62,0xf4,0xc4,0x18,0xff,0xf0
7+
8+
# ATT: push2p %rdi, %r8
9+
# INTEL: push2p r8, rdi
10+
0x62,0xf4,0xbc,0x18,0xff,0xf7
11+
12+
# ATT: push2p %r8, %r15
13+
# INTEL: push2p r15, r8
14+
0x62,0xd4,0x84,0x18,0xff,0xf0
15+
16+
# ATT: push2p %r15, %r16
17+
# INTEL: push2p r16, r15
18+
0x62,0xd4,0xfc,0x10,0xff,0xf7
19+
20+
# ATT: push2p %r16, %r23
21+
# INTEL: push2p r23, r16
22+
0x62,0xfc,0xc4,0x10,0xff,0xf0
23+
24+
# ATT: push2p %r23, %r24
25+
# INTEL: push2p r24, r23
26+
0x62,0xfc,0xbc,0x10,0xff,0xf7
27+
28+
# ATT: push2p %r24, %r31
29+
# INTEL: push2p r31, r24
30+
0x62,0xdc,0x84,0x10,0xff,0xf0
31+
32+
# ATT: pop2p %rax, %rdi
33+
# INTEL: pop2p rdi, rax
34+
0x62,0xf4,0xc4,0x18,0x8f,0xc0
35+
36+
# ATT: pop2p %rdi, %r8
37+
# INTEL: pop2p r8, rdi
38+
0x62,0xf4,0xbc,0x18,0x8f,0xc7
39+
40+
# ATT: pop2p %r8, %r15
41+
# INTEL: pop2p r15, r8
42+
0x62,0xd4,0x84,0x18,0x8f,0xc0
43+
44+
# ATT: pop2p %r15, %r16
45+
# INTEL: pop2p r16, r15
46+
0x62,0xd4,0xfc,0x10,0x8f,0xc7
47+
48+
# ATT: pop2p %r16, %r23
49+
# INTEL: pop2p r23, r16
50+
0x62,0xfc,0xc4,0x10,0x8f,0xc0
51+
52+
# ATT: pop2p %r23, %r24
53+
# INTEL: pop2p r24, r23
54+
0x62,0xfc,0xbc,0x10,0x8f,0xc7
55+
56+
# ATT: pop2p %r24, %r31
57+
# INTEL: pop2p r31, r24
58+
0x62,0xdc,0x84,0x10,0x8f,0xc0

llvm/test/MC/X86/apx/push2-pop2-att.s

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# RUN: llvm-mc -triple x86_64 -show-encoding %s | FileCheck %s
2+
3+
# CHECK: push2 %rax, %rdi
4+
# CHECK: encoding: [0x62,0xf4,0x44,0x18,0xff,0xf0]
5+
push2 %rax, %rdi
6+
# CHECK: push2 %rdi, %r8
7+
# CHECK: encoding: [0x62,0xf4,0x3c,0x18,0xff,0xf7]
8+
push2 %rdi, %r8
9+
# CHECK: push2 %r8, %r15
10+
# CHECK: encoding: [0x62,0xd4,0x04,0x18,0xff,0xf0]
11+
push2 %r8, %r15
12+
# CHECK: push2 %r15, %r16
13+
# CHECK: encoding: [0x62,0xd4,0x7c,0x10,0xff,0xf7]
14+
push2 %r15, %r16
15+
# CHECK: push2 %r16, %r23
16+
# CHECK: encoding: [0x62,0xfc,0x44,0x10,0xff,0xf0]
17+
push2 %r16, %r23
18+
# CHECK: push2 %r23, %r24
19+
# CHECK: encoding: [0x62,0xfc,0x3c,0x10,0xff,0xf7]
20+
push2 %r23, %r24
21+
# CHECK: push2 %r24, %r31
22+
# CHECK: encoding: [0x62,0xdc,0x04,0x10,0xff,0xf0]
23+
push2 %r24, %r31
24+
25+
# CHECK: pop2 %rax, %rdi
26+
# CHECK: encoding: [0x62,0xf4,0x44,0x18,0x8f,0xc0]
27+
pop2 %rax, %rdi
28+
# CHECK: pop2 %rdi, %r8
29+
# CHECK: encoding: [0x62,0xf4,0x3c,0x18,0x8f,0xc7]
30+
pop2 %rdi, %r8
31+
# CHECK: pop2 %r8, %r15
32+
# CHECK: encoding: [0x62,0xd4,0x04,0x18,0x8f,0xc0]
33+
pop2 %r8, %r15
34+
# CHECK: pop2 %r15, %r16
35+
# CHECK: encoding: [0x62,0xd4,0x7c,0x10,0x8f,0xc7]
36+
pop2 %r15, %r16
37+
# CHECK: pop2 %r16, %r23
38+
# CHECK: encoding: [0x62,0xfc,0x44,0x10,0x8f,0xc0]
39+
pop2 %r16, %r23
40+
# CHECK: pop2 %r23, %r24
41+
# CHECK: encoding: [0x62,0xfc,0x3c,0x10,0x8f,0xc7]
42+
pop2 %r23, %r24
43+
# CHECK: pop2 %r24, %r31
44+
# CHECK: encoding: [0x62,0xdc,0x04,0x10,0x8f,0xc0]
45+
pop2 %r24, %r31
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# RUN: llvm-mc -triple x86_64 -show-encoding -x86-asm-syntax=intel -output-asm-variant=1 %s | FileCheck %s
2+
3+
# CHECK: push2 rdi, rax
4+
# CHECK: encoding: [0x62,0xf4,0x44,0x18,0xff,0xf0]
5+
push2 rdi, rax
6+
# CHECK: push2 r8, rdi
7+
# CHECK: encoding: [0x62,0xf4,0x3c,0x18,0xff,0xf7]
8+
push2 r8, rdi
9+
# CHECK: push2 r15, r8
10+
# CHECK: encoding: [0x62,0xd4,0x04,0x18,0xff,0xf0]
11+
push2 r15, r8
12+
# CHECK: push2 r16, r15
13+
# CHECK: encoding: [0x62,0xd4,0x7c,0x10,0xff,0xf7]
14+
push2 r16, r15
15+
# CHECK: push2 r23, r16
16+
# CHECK: encoding: [0x62,0xfc,0x44,0x10,0xff,0xf0]
17+
push2 r23, r16
18+
# CHECK: push2 r24, r23
19+
# CHECK: encoding: [0x62,0xfc,0x3c,0x10,0xff,0xf7]
20+
push2 r24, r23
21+
# CHECK: push2 r31, r24
22+
# CHECK: encoding: [0x62,0xdc,0x04,0x10,0xff,0xf0]
23+
push2 r31, r24
24+
25+
# CHECK: pop2 rdi, rax
26+
# CHECK: encoding: [0x62,0xf4,0x44,0x18,0x8f,0xc0]
27+
pop2 rdi, rax
28+
# CHECK: pop2 r8, rdi
29+
# CHECK: encoding: [0x62,0xf4,0x3c,0x18,0x8f,0xc7]
30+
pop2 r8, rdi
31+
# CHECK: pop2 r15, r8
32+
# CHECK: encoding: [0x62,0xd4,0x04,0x18,0x8f,0xc0]
33+
pop2 r15, r8
34+
# CHECK: pop2 r16, r15
35+
# CHECK: encoding: [0x62,0xd4,0x7c,0x10,0x8f,0xc7]
36+
pop2 r16, r15
37+
# CHECK: pop2 r23, r16
38+
# CHECK: encoding: [0x62,0xfc,0x44,0x10,0x8f,0xc0]
39+
pop2 r23, r16
40+
# CHECK: pop2 r24, r23
41+
# CHECK: encoding: [0x62,0xfc,0x3c,0x10,0x8f,0xc7]
42+
pop2 r24, r23
43+
# CHECK: pop2 r31, r24
44+
# CHECK: encoding: [0x62,0xdc,0x04,0x10,0x8f,0xc0]
45+
pop2 r31, r24

0 commit comments

Comments
 (0)