Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit f712548

Browse files
committed
[x86] Fix retq/retl handling in 64-bit mode
This finishes the job started in r198756, and creates separate opcodes for 64-bit vs. 32-bit versions of the rest of the RET instructions too. LRETL/LRETQ are interesting... I can't see any justification for their existence in the SDM. There should be no 'LRETL' in 64-bit mode, and no need for a REX.W prefix for LRETQ. But this is what GAS does, and my Sandybridge CPU and an Opteron 6376 concur when tested as follows: asm __volatile__("pushq $0x1234\nmovq $0x33,%rax\nsalq $32,%rax\norq $1f,%rax\npushq %rax\nlretl $8\n1:"); asm __volatile__("pushq $1234\npushq $0x33\npushq $1f\nlretq $8\n1:"); asm __volatile__("pushq $0x33\npushq $1f\nlretq\n1:"); asm __volatile__("pushq $0x1234\npushq $0x33\npushq $1f\nlretq $8\n1:"); cf. PR8592 and commit r118903, which added LRETQ. I only added LRETIQ to match it. I don't quite understand how the Intel syntax parsing for ret instructions is working, despite r154468 allegedly fixing it. Aren't the explicitly sized 'retw', 'retd' and 'retq' supposed to work? I have at least made the 'lretq' work with (and indeed *require*) the 'q'. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199106 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 7f2eff7 commit f712548

File tree

6 files changed

+110
-11
lines changed

6 files changed

+110
-11
lines changed

lib/Target/X86/X86FloatingPoint.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1673,7 +1673,8 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) {
16731673

16741674
case X86::RETQ:
16751675
case X86::RETL:
1676-
case X86::RETI:
1676+
case X86::RETIL:
1677+
case X86::RETIQ:
16771678
// If RET has an FP register use operand, pass the first one in ST(0) and
16781679
// the second one in ST(1).
16791680

lib/Target/X86/X86FrameLowering.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ static unsigned findDeadCallerSavedReg(MachineBasicBlock &MBB,
109109
default: return 0;
110110
case X86::RETL:
111111
case X86::RETQ:
112-
case X86::RETI:
112+
case X86::RETIL:
113+
case X86::RETIQ:
113114
case X86::TCRETURNdi:
114115
case X86::TCRETURNri:
115116
case X86::TCRETURNmi:
@@ -731,7 +732,8 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
731732
llvm_unreachable("Can only insert epilog into returning blocks");
732733
case X86::RETQ:
733734
case X86::RETL:
734-
case X86::RETI:
735+
case X86::RETIL:
736+
case X86::RETIQ:
735737
case X86::TCRETURNdi:
736738
case X86::TCRETURNri:
737739
case X86::TCRETURNmi:
@@ -888,8 +890,9 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
888890

889891
// Delete the pseudo instruction TCRETURN.
890892
MBB.erase(MBBI);
891-
} else if ((RetOpcode == X86::RETQ || RetOpcode == X86::RETI ||
892-
RetOpcode == X86::RETL) && (X86FI->getTCReturnAddrDelta() < 0)) {
893+
} else if ((RetOpcode == X86::RETQ || RetOpcode == X86::RETL ||
894+
RetOpcode == X86::RETIQ || RetOpcode == X86::RETIL) &&
895+
(X86FI->getTCReturnAddrDelta() < 0)) {
893896
// Add the return addr area delta back since we are not tail calling.
894897
int delta = -1*X86FI->getTCReturnAddrDelta();
895898
MBBI = MBB.getLastNonDebugInstr();

lib/Target/X86/X86InstrControl.td

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,27 @@ let isTerminator = 1, isReturn = 1, isBarrier = 1,
3030
def RETW : I <0xC3, RawFrm, (outs), (ins),
3131
"ret{w}",
3232
[], IIC_RET>, OpSize;
33-
def RETI : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops),
33+
def RETIL : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops),
3434
"ret{l}\t$amt",
35-
[(X86retflag timm:$amt)], IIC_RET_IMM>, OpSize16;
35+
[(X86retflag timm:$amt)], IIC_RET_IMM>, OpSize16,
36+
Requires<[Not64BitMode]>;
37+
def RETIQ : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops),
38+
"ret{q}\t$amt",
39+
[(X86retflag timm:$amt)], IIC_RET_IMM>,
40+
Requires<[In64BitMode]>;
3641
def RETIW : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt),
3742
"ret{w}\t$amt",
3843
[], IIC_RET_IMM>, OpSize;
3944
def LRETL : I <0xCB, RawFrm, (outs), (ins),
4045
"{l}ret{l|f}", [], IIC_RET>, OpSize16;
46+
def LRETQ : RI <0xCB, RawFrm, (outs), (ins),
47+
"{l}ret{|f}q", [], IIC_RET>, Requires<[In64BitMode]>;
4148
def LRETW : I <0xCB, RawFrm, (outs), (ins),
4249
"{l}ret{w|f}", [], IIC_RET>, OpSize;
43-
def LRETQ : RI <0xCB, RawFrm, (outs), (ins),
44-
"{l}ret{q|f}", [], IIC_RET>;
45-
def LRETI : Ii16<0xCA, RawFrm, (outs), (ins i16imm:$amt),
50+
def LRETIL : Ii16<0xCA, RawFrm, (outs), (ins i16imm:$amt),
4651
"{l}ret{l|f}\t$amt", [], IIC_RET>, OpSize16;
52+
def LRETIQ : RIi16<0xCA, RawFrm, (outs), (ins i16imm:$amt),
53+
"{l}ret{|f}q\t$amt", [], IIC_RET>, Requires<[In64BitMode]>;
4754
def LRETIW : Ii16<0xCA, RawFrm, (outs), (ins i16imm:$amt),
4855
"{l}ret{w|f}\t$amt", [], IIC_RET>, OpSize;
4956
}

lib/Target/X86/X86InstrFormats.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,9 @@ class RI<bits<8> o, Format F, dag outs, dag ins, string asm,
736736
class RIi8 <bits<8> o, Format F, dag outs, dag ins, string asm,
737737
list<dag> pattern, InstrItinClass itin = NoItinerary>
738738
: Ii8<o, F, outs, ins, asm, pattern, itin>, REX_W;
739+
class RIi16 <bits<8> o, Format F, dag outs, dag ins, string asm,
740+
list<dag> pattern, InstrItinClass itin = NoItinerary>
741+
: Ii16<o, F, outs, ins, asm, pattern, itin>, REX_W;
739742
class RIi32 <bits<8> o, Format F, dag outs, dag ins, string asm,
740743
list<dag> pattern, InstrItinClass itin = NoItinerary>
741744
: Ii32<o, F, outs, ins, asm, pattern, itin>, REX_W;

lib/Target/X86/X86InstrInfo.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2162,7 +2162,7 @@ def : MnemonicAlias<"cdq", "cltd", "att">;
21622162
def : MnemonicAlias<"cdqe", "cltq", "att">;
21632163
def : MnemonicAlias<"cqo", "cqto", "att">;
21642164

2165-
// lret maps to lretl, it is not ambiguous with lretq.
2165+
// In 64-bit mode lret maps to lretl; it is not ambiguous with lretq.
21662166
def : MnemonicAlias<"lret", "lretw", "att">, Requires<[In16BitMode]>;
21672167
def : MnemonicAlias<"lret", "lretl", "att">, Requires<[Not16BitMode]>;
21682168

test/MC/X86/ret.s

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// RUN: not llvm-mc -triple x86_64-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=64 %s
2+
// RUN: FileCheck --check-prefix=ERR64 < %t.err %s
3+
// RUN: not llvm-mc -triple i386-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=32 %s
4+
// RUN: FileCheck --check-prefix=ERR32 < %t.err %s
5+
6+
7+
ret
8+
// 64: retq
9+
// 64: encoding: [0xc3]
10+
// 32: retl
11+
// 32: encoding: [0xc3]
12+
retw
13+
// 64: retw
14+
// 64: encoding: [0x66,0xc3]
15+
// 32: retw
16+
// 32: encoding: [0x66,0xc3]
17+
retl
18+
// ERR64: error: instruction requires: Not 64-bit mode
19+
// 32: retl
20+
// 32: encoding: [0xc3]
21+
retq
22+
// 64: retq
23+
// 64: encoding: [0xc3]
24+
// ERR32: error: instruction requires: 64-bit mode
25+
26+
ret $0
27+
// 64: retq $0
28+
// 64: encoding: [0xc2,0x00,0x00]
29+
// 32: retl $0
30+
// 32: encoding: [0xc2,0x00,0x00]
31+
retw $0
32+
// 64: retw $0
33+
// 64: encoding: [0x66,0xc2,0x00,0x00]
34+
// 32: retw $0
35+
// 32: encoding: [0x66,0xc2,0x00,0x00]
36+
retl $0
37+
// ERR64: error: instruction requires: Not 64-bit mode
38+
// 32: retl $0
39+
// 32: encoding: [0xc2,0x00,0x00]
40+
retq $0
41+
// 64: retq $0
42+
// 64: encoding: [0xc2,0x00,0x00]
43+
// ERR32: error: instruction requires: 64-bit mode
44+
45+
lret
46+
// 64: lretl
47+
// 64: encoding: [0xcb]
48+
// 32: lretl
49+
// 32: encoding: [0xcb]
50+
lretw
51+
// 64: lretw
52+
// 64: encoding: [0x66,0xcb]
53+
// 32: lretw
54+
// 32: encoding: [0x66,0xcb]
55+
lretl
56+
// 64: lretl
57+
// 64: encoding: [0xcb]
58+
// 32: lretl
59+
// 32: encoding: [0xcb]
60+
lretq
61+
// 64: lretq
62+
// 64: encoding: [0x48,0xcb]
63+
// ERR32: error: instruction requires: 64-bit mode
64+
65+
lret $0
66+
// 64: lretl $0
67+
// 64: encoding: [0xca,0x00,0x00]
68+
// 32: lretl $0
69+
// 32: encoding: [0xca,0x00,0x00]
70+
lretw $0
71+
// 64: lretw $0
72+
// 64: encoding: [0x66,0xca,0x00,0x00]
73+
// 32: lretw $0
74+
// 32: encoding: [0x66,0xca,0x00,0x00]
75+
lretl $0
76+
// 64: lretl $0
77+
// 64: encoding: [0xca,0x00,0x00]
78+
// 32: lretl $0
79+
// 32: encoding: [0xca,0x00,0x00]
80+
lretq $0
81+
// 64: lretq $0
82+
// 64: encoding: [0x48,0xca,0x00,0x00]
83+
// ERR32: error: instruction requires: 64-bit mode
84+
85+

0 commit comments

Comments
 (0)