mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-26 23:29:22 +00:00
[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
This commit is contained in:
parent
7f2eff792a
commit
f71254859e
@ -1673,7 +1673,8 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) {
|
||||
|
||||
case X86::RETQ:
|
||||
case X86::RETL:
|
||||
case X86::RETI:
|
||||
case X86::RETIL:
|
||||
case X86::RETIQ:
|
||||
// If RET has an FP register use operand, pass the first one in ST(0) and
|
||||
// the second one in ST(1).
|
||||
|
||||
|
@ -109,7 +109,8 @@ static unsigned findDeadCallerSavedReg(MachineBasicBlock &MBB,
|
||||
default: return 0;
|
||||
case X86::RETL:
|
||||
case X86::RETQ:
|
||||
case X86::RETI:
|
||||
case X86::RETIL:
|
||||
case X86::RETIQ:
|
||||
case X86::TCRETURNdi:
|
||||
case X86::TCRETURNri:
|
||||
case X86::TCRETURNmi:
|
||||
@ -731,7 +732,8 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
llvm_unreachable("Can only insert epilog into returning blocks");
|
||||
case X86::RETQ:
|
||||
case X86::RETL:
|
||||
case X86::RETI:
|
||||
case X86::RETIL:
|
||||
case X86::RETIQ:
|
||||
case X86::TCRETURNdi:
|
||||
case X86::TCRETURNri:
|
||||
case X86::TCRETURNmi:
|
||||
@ -888,8 +890,9 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
|
||||
// Delete the pseudo instruction TCRETURN.
|
||||
MBB.erase(MBBI);
|
||||
} else if ((RetOpcode == X86::RETQ || RetOpcode == X86::RETI ||
|
||||
RetOpcode == X86::RETL) && (X86FI->getTCReturnAddrDelta() < 0)) {
|
||||
} else if ((RetOpcode == X86::RETQ || RetOpcode == X86::RETL ||
|
||||
RetOpcode == X86::RETIQ || RetOpcode == X86::RETIL) &&
|
||||
(X86FI->getTCReturnAddrDelta() < 0)) {
|
||||
// Add the return addr area delta back since we are not tail calling.
|
||||
int delta = -1*X86FI->getTCReturnAddrDelta();
|
||||
MBBI = MBB.getLastNonDebugInstr();
|
||||
|
@ -30,20 +30,27 @@ let isTerminator = 1, isReturn = 1, isBarrier = 1,
|
||||
def RETW : I <0xC3, RawFrm, (outs), (ins),
|
||||
"ret{w}",
|
||||
[], IIC_RET>, OpSize;
|
||||
def RETI : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops),
|
||||
def RETIL : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops),
|
||||
"ret{l}\t$amt",
|
||||
[(X86retflag timm:$amt)], IIC_RET_IMM>, OpSize16;
|
||||
[(X86retflag timm:$amt)], IIC_RET_IMM>, OpSize16,
|
||||
Requires<[Not64BitMode]>;
|
||||
def RETIQ : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops),
|
||||
"ret{q}\t$amt",
|
||||
[(X86retflag timm:$amt)], IIC_RET_IMM>,
|
||||
Requires<[In64BitMode]>;
|
||||
def RETIW : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt),
|
||||
"ret{w}\t$amt",
|
||||
[], IIC_RET_IMM>, OpSize;
|
||||
def LRETL : I <0xCB, RawFrm, (outs), (ins),
|
||||
"{l}ret{l|f}", [], IIC_RET>, OpSize16;
|
||||
def LRETQ : RI <0xCB, RawFrm, (outs), (ins),
|
||||
"{l}ret{|f}q", [], IIC_RET>, Requires<[In64BitMode]>;
|
||||
def LRETW : I <0xCB, RawFrm, (outs), (ins),
|
||||
"{l}ret{w|f}", [], IIC_RET>, OpSize;
|
||||
def LRETQ : RI <0xCB, RawFrm, (outs), (ins),
|
||||
"{l}ret{q|f}", [], IIC_RET>;
|
||||
def LRETI : Ii16<0xCA, RawFrm, (outs), (ins i16imm:$amt),
|
||||
def LRETIL : Ii16<0xCA, RawFrm, (outs), (ins i16imm:$amt),
|
||||
"{l}ret{l|f}\t$amt", [], IIC_RET>, OpSize16;
|
||||
def LRETIQ : RIi16<0xCA, RawFrm, (outs), (ins i16imm:$amt),
|
||||
"{l}ret{|f}q\t$amt", [], IIC_RET>, Requires<[In64BitMode]>;
|
||||
def LRETIW : Ii16<0xCA, RawFrm, (outs), (ins i16imm:$amt),
|
||||
"{l}ret{w|f}\t$amt", [], IIC_RET>, OpSize;
|
||||
}
|
||||
|
@ -736,6 +736,9 @@ class RI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||||
class RIi8 <bits<8> o, Format F, dag outs, dag ins, string asm,
|
||||
list<dag> pattern, InstrItinClass itin = NoItinerary>
|
||||
: Ii8<o, F, outs, ins, asm, pattern, itin>, REX_W;
|
||||
class RIi16 <bits<8> o, Format F, dag outs, dag ins, string asm,
|
||||
list<dag> pattern, InstrItinClass itin = NoItinerary>
|
||||
: Ii16<o, F, outs, ins, asm, pattern, itin>, REX_W;
|
||||
class RIi32 <bits<8> o, Format F, dag outs, dag ins, string asm,
|
||||
list<dag> pattern, InstrItinClass itin = NoItinerary>
|
||||
: Ii32<o, F, outs, ins, asm, pattern, itin>, REX_W;
|
||||
|
@ -2162,7 +2162,7 @@ def : MnemonicAlias<"cdq", "cltd", "att">;
|
||||
def : MnemonicAlias<"cdqe", "cltq", "att">;
|
||||
def : MnemonicAlias<"cqo", "cqto", "att">;
|
||||
|
||||
// lret maps to lretl, it is not ambiguous with lretq.
|
||||
// In 64-bit mode lret maps to lretl; it is not ambiguous with lretq.
|
||||
def : MnemonicAlias<"lret", "lretw", "att">, Requires<[In16BitMode]>;
|
||||
def : MnemonicAlias<"lret", "lretl", "att">, Requires<[Not16BitMode]>;
|
||||
|
||||
|
85
test/MC/X86/ret.s
Normal file
85
test/MC/X86/ret.s
Normal file
@ -0,0 +1,85 @@
|
||||
// RUN: not llvm-mc -triple x86_64-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=64 %s
|
||||
// RUN: FileCheck --check-prefix=ERR64 < %t.err %s
|
||||
// RUN: not llvm-mc -triple i386-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=32 %s
|
||||
// RUN: FileCheck --check-prefix=ERR32 < %t.err %s
|
||||
|
||||
|
||||
ret
|
||||
// 64: retq
|
||||
// 64: encoding: [0xc3]
|
||||
// 32: retl
|
||||
// 32: encoding: [0xc3]
|
||||
retw
|
||||
// 64: retw
|
||||
// 64: encoding: [0x66,0xc3]
|
||||
// 32: retw
|
||||
// 32: encoding: [0x66,0xc3]
|
||||
retl
|
||||
// ERR64: error: instruction requires: Not 64-bit mode
|
||||
// 32: retl
|
||||
// 32: encoding: [0xc3]
|
||||
retq
|
||||
// 64: retq
|
||||
// 64: encoding: [0xc3]
|
||||
// ERR32: error: instruction requires: 64-bit mode
|
||||
|
||||
ret $0
|
||||
// 64: retq $0
|
||||
// 64: encoding: [0xc2,0x00,0x00]
|
||||
// 32: retl $0
|
||||
// 32: encoding: [0xc2,0x00,0x00]
|
||||
retw $0
|
||||
// 64: retw $0
|
||||
// 64: encoding: [0x66,0xc2,0x00,0x00]
|
||||
// 32: retw $0
|
||||
// 32: encoding: [0x66,0xc2,0x00,0x00]
|
||||
retl $0
|
||||
// ERR64: error: instruction requires: Not 64-bit mode
|
||||
// 32: retl $0
|
||||
// 32: encoding: [0xc2,0x00,0x00]
|
||||
retq $0
|
||||
// 64: retq $0
|
||||
// 64: encoding: [0xc2,0x00,0x00]
|
||||
// ERR32: error: instruction requires: 64-bit mode
|
||||
|
||||
lret
|
||||
// 64: lretl
|
||||
// 64: encoding: [0xcb]
|
||||
// 32: lretl
|
||||
// 32: encoding: [0xcb]
|
||||
lretw
|
||||
// 64: lretw
|
||||
// 64: encoding: [0x66,0xcb]
|
||||
// 32: lretw
|
||||
// 32: encoding: [0x66,0xcb]
|
||||
lretl
|
||||
// 64: lretl
|
||||
// 64: encoding: [0xcb]
|
||||
// 32: lretl
|
||||
// 32: encoding: [0xcb]
|
||||
lretq
|
||||
// 64: lretq
|
||||
// 64: encoding: [0x48,0xcb]
|
||||
// ERR32: error: instruction requires: 64-bit mode
|
||||
|
||||
lret $0
|
||||
// 64: lretl $0
|
||||
// 64: encoding: [0xca,0x00,0x00]
|
||||
// 32: lretl $0
|
||||
// 32: encoding: [0xca,0x00,0x00]
|
||||
lretw $0
|
||||
// 64: lretw $0
|
||||
// 64: encoding: [0x66,0xca,0x00,0x00]
|
||||
// 32: lretw $0
|
||||
// 32: encoding: [0x66,0xca,0x00,0x00]
|
||||
lretl $0
|
||||
// 64: lretl $0
|
||||
// 64: encoding: [0xca,0x00,0x00]
|
||||
// 32: lretl $0
|
||||
// 32: encoding: [0xca,0x00,0x00]
|
||||
lretq $0
|
||||
// 64: lretq $0
|
||||
// 64: encoding: [0x48,0xca,0x00,0x00]
|
||||
// ERR32: error: instruction requires: 64-bit mode
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user