106f32e7eSjoerg//===-- X86InstrControl.td - Control Flow Instructions -----*- tablegen -*-===// 206f32e7eSjoerg// 306f32e7eSjoerg// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406f32e7eSjoerg// See https://llvm.org/LICENSE.txt for license information. 506f32e7eSjoerg// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606f32e7eSjoerg// 706f32e7eSjoerg//===----------------------------------------------------------------------===// 806f32e7eSjoerg// 906f32e7eSjoerg// This file describes the X86 jump, return, call, and related instructions. 1006f32e7eSjoerg// 1106f32e7eSjoerg//===----------------------------------------------------------------------===// 1206f32e7eSjoerg 1306f32e7eSjoerg//===----------------------------------------------------------------------===// 1406f32e7eSjoerg// Control Flow Instructions. 1506f32e7eSjoerg// 1606f32e7eSjoerg 1706f32e7eSjoerg// Return instructions. 1806f32e7eSjoerg// 1906f32e7eSjoerg// The X86retflag return instructions are variadic because we may add ST0 and 2006f32e7eSjoerg// ST1 arguments when returning values on the x87 stack. 2106f32e7eSjoerglet isTerminator = 1, isReturn = 1, isBarrier = 1, 2206f32e7eSjoerg hasCtrlDep = 1, FPForm = SpecialFP, SchedRW = [WriteJumpLd] in { 2306f32e7eSjoerg def RETL : I <0xC3, RawFrm, (outs), (ins variable_ops), 2406f32e7eSjoerg "ret{l}", []>, OpSize32, Requires<[Not64BitMode]>; 2506f32e7eSjoerg def RETQ : I <0xC3, RawFrm, (outs), (ins variable_ops), 2606f32e7eSjoerg "ret{q}", []>, OpSize32, Requires<[In64BitMode]>; 2706f32e7eSjoerg def RETW : I <0xC3, RawFrm, (outs), (ins), 2806f32e7eSjoerg "ret{w}", []>, OpSize16; 2906f32e7eSjoerg def RETIL : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops), 3006f32e7eSjoerg "ret{l}\t$amt", []>, OpSize32, Requires<[Not64BitMode]>; 3106f32e7eSjoerg def RETIQ : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops), 3206f32e7eSjoerg "ret{q}\t$amt", []>, OpSize32, Requires<[In64BitMode]>; 3306f32e7eSjoerg def RETIW : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt), 3406f32e7eSjoerg "ret{w}\t$amt", []>, OpSize16; 3506f32e7eSjoerg def LRETL : I <0xCB, RawFrm, (outs), (ins), 3606f32e7eSjoerg "{l}ret{l|f}", []>, OpSize32; 3706f32e7eSjoerg def LRETQ : RI <0xCB, RawFrm, (outs), (ins), 3806f32e7eSjoerg "{l}ret{|f}q", []>, Requires<[In64BitMode]>; 3906f32e7eSjoerg def LRETW : I <0xCB, RawFrm, (outs), (ins), 4006f32e7eSjoerg "{l}ret{w|f}", []>, OpSize16; 4106f32e7eSjoerg def LRETIL : Ii16<0xCA, RawFrm, (outs), (ins i16imm:$amt), 4206f32e7eSjoerg "{l}ret{l|f}\t$amt", []>, OpSize32; 4306f32e7eSjoerg def LRETIQ : RIi16<0xCA, RawFrm, (outs), (ins i16imm:$amt), 4406f32e7eSjoerg "{l}ret{|f}q\t$amt", []>, Requires<[In64BitMode]>; 4506f32e7eSjoerg def LRETIW : Ii16<0xCA, RawFrm, (outs), (ins i16imm:$amt), 4606f32e7eSjoerg "{l}ret{w|f}\t$amt", []>, OpSize16; 4706f32e7eSjoerg 4806f32e7eSjoerg // The machine return from interrupt instruction, but sometimes we need to 4906f32e7eSjoerg // perform a post-epilogue stack adjustment. Codegen emits the pseudo form 5006f32e7eSjoerg // which expands to include an SP adjustment if necessary. 5106f32e7eSjoerg def IRET16 : I <0xcf, RawFrm, (outs), (ins), "iret{w}", []>, 5206f32e7eSjoerg OpSize16; 5306f32e7eSjoerg def IRET32 : I <0xcf, RawFrm, (outs), (ins), "iret{l|d}", []>, OpSize32; 5406f32e7eSjoerg def IRET64 : RI <0xcf, RawFrm, (outs), (ins), "iretq", []>, Requires<[In64BitMode]>; 5506f32e7eSjoerg let isCodeGenOnly = 1 in 5606f32e7eSjoerg def IRET : PseudoI<(outs), (ins i32imm:$adj), [(X86iret timm:$adj)]>; 5706f32e7eSjoerg def RET : PseudoI<(outs), (ins i32imm:$adj, variable_ops), [(X86retflag timm:$adj)]>; 5806f32e7eSjoerg} 5906f32e7eSjoerg 6006f32e7eSjoerg// Unconditional branches. 6106f32e7eSjoerglet isBarrier = 1, isBranch = 1, isTerminator = 1, SchedRW = [WriteJump] in { 6206f32e7eSjoerg def JMP_1 : Ii8PCRel<0xEB, RawFrm, (outs), (ins brtarget8:$dst), 6306f32e7eSjoerg "jmp\t$dst", [(br bb:$dst)]>; 6406f32e7eSjoerg let hasSideEffects = 0, isCodeGenOnly = 1, ForceDisassemble = 1 in { 6506f32e7eSjoerg def JMP_2 : Ii16PCRel<0xE9, RawFrm, (outs), (ins brtarget16:$dst), 6606f32e7eSjoerg "jmp\t$dst", []>, OpSize16; 6706f32e7eSjoerg def JMP_4 : Ii32PCRel<0xE9, RawFrm, (outs), (ins brtarget32:$dst), 6806f32e7eSjoerg "jmp\t$dst", []>, OpSize32; 6906f32e7eSjoerg } 7006f32e7eSjoerg} 7106f32e7eSjoerg 7206f32e7eSjoerg// Conditional Branches. 7306f32e7eSjoerglet isBranch = 1, isTerminator = 1, Uses = [EFLAGS], SchedRW = [WriteJump], 7406f32e7eSjoerg isCodeGenOnly = 1, ForceDisassemble = 1 in { 7506f32e7eSjoerg def JCC_1 : Ii8PCRel <0x70, AddCCFrm, (outs), 7606f32e7eSjoerg (ins brtarget8:$dst, ccode:$cond), 7706f32e7eSjoerg "j${cond}\t$dst", 7806f32e7eSjoerg [(X86brcond bb:$dst, timm:$cond, EFLAGS)]>; 7906f32e7eSjoerg let hasSideEffects = 0 in { 8006f32e7eSjoerg def JCC_2 : Ii16PCRel<0x80, AddCCFrm, (outs), 8106f32e7eSjoerg (ins brtarget16:$dst, ccode:$cond), 8206f32e7eSjoerg "j${cond}\t$dst", 8306f32e7eSjoerg []>, OpSize16, TB; 8406f32e7eSjoerg def JCC_4 : Ii32PCRel<0x80, AddCCFrm, (outs), 8506f32e7eSjoerg (ins brtarget32:$dst, ccode:$cond), 8606f32e7eSjoerg "j${cond}\t$dst", 8706f32e7eSjoerg []>, TB, OpSize32; 8806f32e7eSjoerg } 8906f32e7eSjoerg} 9006f32e7eSjoerg 9106f32e7eSjoergdef : InstAlias<"jo\t$dst", (JCC_1 brtarget8:$dst, 0), 0>; 9206f32e7eSjoergdef : InstAlias<"jno\t$dst", (JCC_1 brtarget8:$dst, 1), 0>; 9306f32e7eSjoergdef : InstAlias<"jb\t$dst", (JCC_1 brtarget8:$dst, 2), 0>; 9406f32e7eSjoergdef : InstAlias<"jae\t$dst", (JCC_1 brtarget8:$dst, 3), 0>; 9506f32e7eSjoergdef : InstAlias<"je\t$dst", (JCC_1 brtarget8:$dst, 4), 0>; 9606f32e7eSjoergdef : InstAlias<"jne\t$dst", (JCC_1 brtarget8:$dst, 5), 0>; 9706f32e7eSjoergdef : InstAlias<"jbe\t$dst", (JCC_1 brtarget8:$dst, 6), 0>; 9806f32e7eSjoergdef : InstAlias<"ja\t$dst", (JCC_1 brtarget8:$dst, 7), 0>; 9906f32e7eSjoergdef : InstAlias<"js\t$dst", (JCC_1 brtarget8:$dst, 8), 0>; 10006f32e7eSjoergdef : InstAlias<"jns\t$dst", (JCC_1 brtarget8:$dst, 9), 0>; 10106f32e7eSjoergdef : InstAlias<"jp\t$dst", (JCC_1 brtarget8:$dst, 10), 0>; 10206f32e7eSjoergdef : InstAlias<"jnp\t$dst", (JCC_1 brtarget8:$dst, 11), 0>; 10306f32e7eSjoergdef : InstAlias<"jl\t$dst", (JCC_1 brtarget8:$dst, 12), 0>; 10406f32e7eSjoergdef : InstAlias<"jge\t$dst", (JCC_1 brtarget8:$dst, 13), 0>; 10506f32e7eSjoergdef : InstAlias<"jle\t$dst", (JCC_1 brtarget8:$dst, 14), 0>; 10606f32e7eSjoergdef : InstAlias<"jg\t$dst", (JCC_1 brtarget8:$dst, 15), 0>; 10706f32e7eSjoerg 10806f32e7eSjoerg// jcx/jecx/jrcx instructions. 10906f32e7eSjoerglet isBranch = 1, isTerminator = 1, hasSideEffects = 0, SchedRW = [WriteJump] in { 11006f32e7eSjoerg // These are the 32-bit versions of this instruction for the asmparser. In 11106f32e7eSjoerg // 32-bit mode, the address size prefix is jcxz and the unprefixed version is 11206f32e7eSjoerg // jecxz. 11306f32e7eSjoerg let Uses = [CX] in 11406f32e7eSjoerg def JCXZ : Ii8PCRel<0xE3, RawFrm, (outs), (ins brtarget8:$dst), 11506f32e7eSjoerg "jcxz\t$dst", []>, AdSize16, Requires<[Not64BitMode]>; 11606f32e7eSjoerg let Uses = [ECX] in 11706f32e7eSjoerg def JECXZ : Ii8PCRel<0xE3, RawFrm, (outs), (ins brtarget8:$dst), 11806f32e7eSjoerg "jecxz\t$dst", []>, AdSize32; 11906f32e7eSjoerg 12006f32e7eSjoerg let Uses = [RCX] in 12106f32e7eSjoerg def JRCXZ : Ii8PCRel<0xE3, RawFrm, (outs), (ins brtarget8:$dst), 12206f32e7eSjoerg "jrcxz\t$dst", []>, AdSize64, Requires<[In64BitMode]>; 12306f32e7eSjoerg} 12406f32e7eSjoerg 12506f32e7eSjoerg// Indirect branches 12606f32e7eSjoerglet isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { 12706f32e7eSjoerg def JMP16r : I<0xFF, MRM4r, (outs), (ins GR16:$dst), "jmp{w}\t{*}$dst", 12806f32e7eSjoerg [(brind GR16:$dst)]>, Requires<[Not64BitMode]>, 12906f32e7eSjoerg OpSize16, Sched<[WriteJump]>; 13006f32e7eSjoerg def JMP16m : I<0xFF, MRM4m, (outs), (ins i16mem:$dst), "jmp{w}\t{*}$dst", 13106f32e7eSjoerg [(brind (loadi16 addr:$dst))]>, Requires<[Not64BitMode]>, 13206f32e7eSjoerg OpSize16, Sched<[WriteJumpLd]>; 13306f32e7eSjoerg 13406f32e7eSjoerg def JMP32r : I<0xFF, MRM4r, (outs), (ins GR32:$dst), "jmp{l}\t{*}$dst", 13506f32e7eSjoerg [(brind GR32:$dst)]>, Requires<[Not64BitMode]>, 13606f32e7eSjoerg OpSize32, Sched<[WriteJump]>; 13706f32e7eSjoerg def JMP32m : I<0xFF, MRM4m, (outs), (ins i32mem:$dst), "jmp{l}\t{*}$dst", 13806f32e7eSjoerg [(brind (loadi32 addr:$dst))]>, Requires<[Not64BitMode]>, 13906f32e7eSjoerg OpSize32, Sched<[WriteJumpLd]>; 14006f32e7eSjoerg 14106f32e7eSjoerg def JMP64r : I<0xFF, MRM4r, (outs), (ins GR64:$dst), "jmp{q}\t{*}$dst", 14206f32e7eSjoerg [(brind GR64:$dst)]>, Requires<[In64BitMode]>, 14306f32e7eSjoerg Sched<[WriteJump]>; 14406f32e7eSjoerg def JMP64m : I<0xFF, MRM4m, (outs), (ins i64mem:$dst), "jmp{q}\t{*}$dst", 14506f32e7eSjoerg [(brind (loadi64 addr:$dst))]>, Requires<[In64BitMode]>, 14606f32e7eSjoerg Sched<[WriteJumpLd]>; 14706f32e7eSjoerg 14806f32e7eSjoerg // Win64 wants indirect jumps leaving the function to have a REX_W prefix. 14906f32e7eSjoerg // These are switched from TAILJMPr/m64_REX in MCInstLower. 15006f32e7eSjoerg let isCodeGenOnly = 1, hasREX_WPrefix = 1 in { 15106f32e7eSjoerg def JMP64r_REX : I<0xFF, MRM4r, (outs), (ins GR64:$dst), 15206f32e7eSjoerg "rex64 jmp{q}\t{*}$dst", []>, Sched<[WriteJump]>; 15306f32e7eSjoerg let mayLoad = 1 in 15406f32e7eSjoerg def JMP64m_REX : I<0xFF, MRM4m, (outs), (ins i64mem:$dst), 15506f32e7eSjoerg "rex64 jmp{q}\t{*}$dst", []>, Sched<[WriteJumpLd]>; 15606f32e7eSjoerg 15706f32e7eSjoerg } 15806f32e7eSjoerg 15906f32e7eSjoerg // Non-tracking jumps for IBT, use with caution. 16006f32e7eSjoerg let isCodeGenOnly = 1 in { 16106f32e7eSjoerg def JMP16r_NT : I<0xFF, MRM4r, (outs), (ins GR16 : $dst), "jmp{w}\t{*}$dst", 16206f32e7eSjoerg [(X86NoTrackBrind GR16 : $dst)]>, Requires<[Not64BitMode]>, 16306f32e7eSjoerg OpSize16, Sched<[WriteJump]>, NOTRACK; 16406f32e7eSjoerg 16506f32e7eSjoerg def JMP16m_NT : I<0xFF, MRM4m, (outs), (ins i16mem : $dst), "jmp{w}\t{*}$dst", 16606f32e7eSjoerg [(X86NoTrackBrind (loadi16 addr : $dst))]>, 16706f32e7eSjoerg Requires<[Not64BitMode]>, OpSize16, Sched<[WriteJumpLd]>, 16806f32e7eSjoerg NOTRACK; 16906f32e7eSjoerg 17006f32e7eSjoerg def JMP32r_NT : I<0xFF, MRM4r, (outs), (ins GR32 : $dst), "jmp{l}\t{*}$dst", 17106f32e7eSjoerg [(X86NoTrackBrind GR32 : $dst)]>, Requires<[Not64BitMode]>, 17206f32e7eSjoerg OpSize32, Sched<[WriteJump]>, NOTRACK; 17306f32e7eSjoerg def JMP32m_NT : I<0xFF, MRM4m, (outs), (ins i32mem : $dst), "jmp{l}\t{*}$dst", 17406f32e7eSjoerg [(X86NoTrackBrind (loadi32 addr : $dst))]>, 17506f32e7eSjoerg Requires<[Not64BitMode]>, OpSize32, Sched<[WriteJumpLd]>, 17606f32e7eSjoerg NOTRACK; 17706f32e7eSjoerg 17806f32e7eSjoerg def JMP64r_NT : I<0xFF, MRM4r, (outs), (ins GR64 : $dst), "jmp{q}\t{*}$dst", 17906f32e7eSjoerg [(X86NoTrackBrind GR64 : $dst)]>, Requires<[In64BitMode]>, 18006f32e7eSjoerg Sched<[WriteJump]>, NOTRACK; 18106f32e7eSjoerg def JMP64m_NT : I<0xFF, MRM4m, (outs), (ins i64mem : $dst), "jmp{q}\t{*}$dst", 18206f32e7eSjoerg [(X86NoTrackBrind(loadi64 addr : $dst))]>, 18306f32e7eSjoerg Requires<[In64BitMode]>, Sched<[WriteJumpLd]>, NOTRACK; 18406f32e7eSjoerg } 18506f32e7eSjoerg 18606f32e7eSjoerg let Predicates = [Not64BitMode], AsmVariantName = "att" in { 18706f32e7eSjoerg def FARJMP16i : Iseg16<0xEA, RawFrmImm16, (outs), 18806f32e7eSjoerg (ins i16imm:$off, i16imm:$seg), 18906f32e7eSjoerg "ljmp{w}\t$seg, $off", []>, 19006f32e7eSjoerg OpSize16, Sched<[WriteJump]>; 19106f32e7eSjoerg def FARJMP32i : Iseg32<0xEA, RawFrmImm16, (outs), 19206f32e7eSjoerg (ins i32imm:$off, i16imm:$seg), 19306f32e7eSjoerg "ljmp{l}\t$seg, $off", []>, 19406f32e7eSjoerg OpSize32, Sched<[WriteJump]>; 19506f32e7eSjoerg } 196*da58b97aSjoerg let mayLoad = 1 in { 197*da58b97aSjoerg def FARJMP64m : RI<0xFF, MRM5m, (outs), (ins opaquemem:$dst), 19806f32e7eSjoerg "ljmp{q}\t{*}$dst", []>, Sched<[WriteJump]>, Requires<[In64BitMode]>; 19906f32e7eSjoerg 20006f32e7eSjoerg let AsmVariantName = "att" in 20106f32e7eSjoerg def FARJMP16m : I<0xFF, MRM5m, (outs), (ins opaquemem:$dst), 20206f32e7eSjoerg "ljmp{w}\t{*}$dst", []>, OpSize16, Sched<[WriteJumpLd]>; 20306f32e7eSjoerg def FARJMP32m : I<0xFF, MRM5m, (outs), (ins opaquemem:$dst), 20406f32e7eSjoerg "{l}jmp{l}\t{*}$dst", []>, OpSize32, Sched<[WriteJumpLd]>; 20506f32e7eSjoerg } 206*da58b97aSjoerg} 20706f32e7eSjoerg 20806f32e7eSjoerg// Loop instructions 20906f32e7eSjoerglet SchedRW = [WriteJump] in { 21006f32e7eSjoergdef LOOP : Ii8PCRel<0xE2, RawFrm, (outs), (ins brtarget8:$dst), "loop\t$dst", []>; 21106f32e7eSjoergdef LOOPE : Ii8PCRel<0xE1, RawFrm, (outs), (ins brtarget8:$dst), "loope\t$dst", []>; 21206f32e7eSjoergdef LOOPNE : Ii8PCRel<0xE0, RawFrm, (outs), (ins brtarget8:$dst), "loopne\t$dst", []>; 21306f32e7eSjoerg} 21406f32e7eSjoerg 21506f32e7eSjoerg//===----------------------------------------------------------------------===// 21606f32e7eSjoerg// Call Instructions... 21706f32e7eSjoerg// 21806f32e7eSjoerglet isCall = 1 in 21906f32e7eSjoerg // All calls clobber the non-callee saved registers. ESP is marked as 22006f32e7eSjoerg // a use to prevent stack-pointer assignments that appear immediately 22106f32e7eSjoerg // before calls from potentially appearing dead. Uses for argument 22206f32e7eSjoerg // registers are added manually. 22306f32e7eSjoerg let Uses = [ESP, SSP] in { 22406f32e7eSjoerg def CALLpcrel32 : Ii32PCRel<0xE8, RawFrm, 225*da58b97aSjoerg (outs), (ins i32imm_brtarget:$dst), 22606f32e7eSjoerg "call{l}\t$dst", []>, OpSize32, 22706f32e7eSjoerg Requires<[Not64BitMode]>, Sched<[WriteJump]>; 22806f32e7eSjoerg let hasSideEffects = 0 in 22906f32e7eSjoerg def CALLpcrel16 : Ii16PCRel<0xE8, RawFrm, 230*da58b97aSjoerg (outs), (ins i16imm_brtarget:$dst), 23106f32e7eSjoerg "call{w}\t$dst", []>, OpSize16, 23206f32e7eSjoerg Sched<[WriteJump]>; 23306f32e7eSjoerg def CALL16r : I<0xFF, MRM2r, (outs), (ins GR16:$dst), 23406f32e7eSjoerg "call{w}\t{*}$dst", [(X86call GR16:$dst)]>, 23506f32e7eSjoerg OpSize16, Requires<[Not64BitMode]>, Sched<[WriteJump]>; 23606f32e7eSjoerg def CALL16m : I<0xFF, MRM2m, (outs), (ins i16mem:$dst), 23706f32e7eSjoerg "call{w}\t{*}$dst", [(X86call (loadi16 addr:$dst))]>, 23806f32e7eSjoerg OpSize16, Requires<[Not64BitMode,FavorMemIndirectCall]>, 23906f32e7eSjoerg Sched<[WriteJumpLd]>; 24006f32e7eSjoerg def CALL32r : I<0xFF, MRM2r, (outs), (ins GR32:$dst), 24106f32e7eSjoerg "call{l}\t{*}$dst", [(X86call GR32:$dst)]>, OpSize32, 242*da58b97aSjoerg Requires<[Not64BitMode,NotUseIndirectThunkCalls]>, 24306f32e7eSjoerg Sched<[WriteJump]>; 24406f32e7eSjoerg def CALL32m : I<0xFF, MRM2m, (outs), (ins i32mem:$dst), 24506f32e7eSjoerg "call{l}\t{*}$dst", [(X86call (loadi32 addr:$dst))]>, 24606f32e7eSjoerg OpSize32, 24706f32e7eSjoerg Requires<[Not64BitMode,FavorMemIndirectCall, 248*da58b97aSjoerg NotUseIndirectThunkCalls]>, 24906f32e7eSjoerg Sched<[WriteJumpLd]>; 25006f32e7eSjoerg 25106f32e7eSjoerg // Non-tracking calls for IBT, use with caution. 25206f32e7eSjoerg let isCodeGenOnly = 1 in { 25306f32e7eSjoerg def CALL16r_NT : I<0xFF, MRM2r, (outs), (ins GR16 : $dst), 25406f32e7eSjoerg "call{w}\t{*}$dst",[(X86NoTrackCall GR16 : $dst)]>, 25506f32e7eSjoerg OpSize16, Requires<[Not64BitMode]>, Sched<[WriteJump]>, NOTRACK; 25606f32e7eSjoerg def CALL16m_NT : I<0xFF, MRM2m, (outs), (ins i16mem : $dst), 25706f32e7eSjoerg "call{w}\t{*}$dst",[(X86NoTrackCall(loadi16 addr : $dst))]>, 25806f32e7eSjoerg OpSize16, Requires<[Not64BitMode,FavorMemIndirectCall]>, 25906f32e7eSjoerg Sched<[WriteJumpLd]>, NOTRACK; 26006f32e7eSjoerg def CALL32r_NT : I<0xFF, MRM2r, (outs), (ins GR32 : $dst), 26106f32e7eSjoerg "call{l}\t{*}$dst",[(X86NoTrackCall GR32 : $dst)]>, 26206f32e7eSjoerg OpSize32, Requires<[Not64BitMode]>, Sched<[WriteJump]>, NOTRACK; 26306f32e7eSjoerg def CALL32m_NT : I<0xFF, MRM2m, (outs), (ins i32mem : $dst), 26406f32e7eSjoerg "call{l}\t{*}$dst",[(X86NoTrackCall(loadi32 addr : $dst))]>, 26506f32e7eSjoerg OpSize32, Requires<[Not64BitMode,FavorMemIndirectCall]>, 26606f32e7eSjoerg Sched<[WriteJumpLd]>, NOTRACK; 26706f32e7eSjoerg } 26806f32e7eSjoerg 26906f32e7eSjoerg let Predicates = [Not64BitMode], AsmVariantName = "att" in { 27006f32e7eSjoerg def FARCALL16i : Iseg16<0x9A, RawFrmImm16, (outs), 27106f32e7eSjoerg (ins i16imm:$off, i16imm:$seg), 27206f32e7eSjoerg "lcall{w}\t$seg, $off", []>, 27306f32e7eSjoerg OpSize16, Sched<[WriteJump]>; 27406f32e7eSjoerg def FARCALL32i : Iseg32<0x9A, RawFrmImm16, (outs), 27506f32e7eSjoerg (ins i32imm:$off, i16imm:$seg), 27606f32e7eSjoerg "lcall{l}\t$seg, $off", []>, 27706f32e7eSjoerg OpSize32, Sched<[WriteJump]>; 27806f32e7eSjoerg } 27906f32e7eSjoerg 280*da58b97aSjoerg let mayLoad = 1 in { 28106f32e7eSjoerg def FARCALL16m : I<0xFF, MRM3m, (outs), (ins opaquemem:$dst), 28206f32e7eSjoerg "lcall{w}\t{*}$dst", []>, OpSize16, Sched<[WriteJumpLd]>; 28306f32e7eSjoerg def FARCALL32m : I<0xFF, MRM3m, (outs), (ins opaquemem:$dst), 28406f32e7eSjoerg "{l}call{l}\t{*}$dst", []>, OpSize32, Sched<[WriteJumpLd]>; 28506f32e7eSjoerg } 286*da58b97aSjoerg } 28706f32e7eSjoerg 28806f32e7eSjoerg 28906f32e7eSjoerg// Tail call stuff. 29006f32e7eSjoerglet isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, 29106f32e7eSjoerg isCodeGenOnly = 1, Uses = [ESP, SSP] in { 292*da58b97aSjoerg def TCRETURNdi : PseudoI<(outs), (ins i32imm_brtarget:$dst, i32imm:$offset), 29306f32e7eSjoerg []>, Sched<[WriteJump]>, NotMemoryFoldable; 29406f32e7eSjoerg def TCRETURNri : PseudoI<(outs), (ins ptr_rc_tailcall:$dst, i32imm:$offset), 29506f32e7eSjoerg []>, Sched<[WriteJump]>, NotMemoryFoldable; 29606f32e7eSjoerg let mayLoad = 1 in 29706f32e7eSjoerg def TCRETURNmi : PseudoI<(outs), (ins i32mem_TC:$dst, i32imm:$offset), 29806f32e7eSjoerg []>, Sched<[WriteJumpLd]>; 29906f32e7eSjoerg 300*da58b97aSjoerg def TAILJMPd : PseudoI<(outs), (ins i32imm_brtarget:$dst), 30106f32e7eSjoerg []>, Sched<[WriteJump]>; 30206f32e7eSjoerg 30306f32e7eSjoerg def TAILJMPr : PseudoI<(outs), (ins ptr_rc_tailcall:$dst), 30406f32e7eSjoerg []>, Sched<[WriteJump]>; 30506f32e7eSjoerg let mayLoad = 1 in 30606f32e7eSjoerg def TAILJMPm : PseudoI<(outs), (ins i32mem_TC:$dst), 30706f32e7eSjoerg []>, Sched<[WriteJumpLd]>; 30806f32e7eSjoerg} 30906f32e7eSjoerg 31006f32e7eSjoerg// Conditional tail calls are similar to the above, but they are branches 31106f32e7eSjoerg// rather than barriers, and they use EFLAGS. 31206f32e7eSjoerglet isCall = 1, isTerminator = 1, isReturn = 1, isBranch = 1, 31306f32e7eSjoerg isCodeGenOnly = 1, SchedRW = [WriteJump] in 31406f32e7eSjoerg let Uses = [ESP, EFLAGS, SSP] in { 31506f32e7eSjoerg def TCRETURNdicc : PseudoI<(outs), 316*da58b97aSjoerg (ins i32imm_brtarget:$dst, i32imm:$offset, i32imm:$cond), 317*da58b97aSjoerg []>; 31806f32e7eSjoerg 31906f32e7eSjoerg // This gets substituted to a conditional jump instruction in MC lowering. 320*da58b97aSjoerg def TAILJMPd_CC : PseudoI<(outs), (ins i32imm_brtarget:$dst, i32imm:$cond), []>; 32106f32e7eSjoerg} 32206f32e7eSjoerg 32306f32e7eSjoerg 32406f32e7eSjoerg//===----------------------------------------------------------------------===// 32506f32e7eSjoerg// Call Instructions... 32606f32e7eSjoerg// 32706f32e7eSjoerg 32806f32e7eSjoerg// RSP is marked as a use to prevent stack-pointer assignments that appear 32906f32e7eSjoerg// immediately before calls from potentially appearing dead. Uses for argument 33006f32e7eSjoerg// registers are added manually. 33106f32e7eSjoerglet isCall = 1, Uses = [RSP, SSP], SchedRW = [WriteJump] in { 33206f32e7eSjoerg // NOTE: this pattern doesn't match "X86call imm", because we do not know 33306f32e7eSjoerg // that the offset between an arbitrary immediate and the call will fit in 33406f32e7eSjoerg // the 32-bit pcrel field that we have. 33506f32e7eSjoerg def CALL64pcrel32 : Ii32PCRel<0xE8, RawFrm, 336*da58b97aSjoerg (outs), (ins i64i32imm_brtarget:$dst), 33706f32e7eSjoerg "call{q}\t$dst", []>, OpSize32, 33806f32e7eSjoerg Requires<[In64BitMode]>; 33906f32e7eSjoerg def CALL64r : I<0xFF, MRM2r, (outs), (ins GR64:$dst), 34006f32e7eSjoerg "call{q}\t{*}$dst", [(X86call GR64:$dst)]>, 341*da58b97aSjoerg Requires<[In64BitMode,NotUseIndirectThunkCalls]>; 34206f32e7eSjoerg def CALL64m : I<0xFF, MRM2m, (outs), (ins i64mem:$dst), 34306f32e7eSjoerg "call{q}\t{*}$dst", [(X86call (loadi64 addr:$dst))]>, 34406f32e7eSjoerg Requires<[In64BitMode,FavorMemIndirectCall, 345*da58b97aSjoerg NotUseIndirectThunkCalls]>; 34606f32e7eSjoerg 34706f32e7eSjoerg // Non-tracking calls for IBT, use with caution. 34806f32e7eSjoerg let isCodeGenOnly = 1 in { 34906f32e7eSjoerg def CALL64r_NT : I<0xFF, MRM2r, (outs), (ins GR64 : $dst), 35006f32e7eSjoerg "call{q}\t{*}$dst",[(X86NoTrackCall GR64 : $dst)]>, 35106f32e7eSjoerg Requires<[In64BitMode]>, NOTRACK; 35206f32e7eSjoerg def CALL64m_NT : I<0xFF, MRM2m, (outs), (ins i64mem : $dst), 35306f32e7eSjoerg "call{q}\t{*}$dst", 35406f32e7eSjoerg [(X86NoTrackCall(loadi64 addr : $dst))]>, 35506f32e7eSjoerg Requires<[In64BitMode,FavorMemIndirectCall]>, NOTRACK; 35606f32e7eSjoerg } 35706f32e7eSjoerg 358*da58b97aSjoerg let mayLoad = 1 in 359*da58b97aSjoerg def FARCALL64m : RI<0xFF, MRM3m, (outs), (ins opaquemem:$dst), 36006f32e7eSjoerg "lcall{q}\t{*}$dst", []>; 36106f32e7eSjoerg} 36206f32e7eSjoerg 36306f32e7eSjoerglet isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, 36406f32e7eSjoerg isCodeGenOnly = 1, Uses = [RSP, SSP] in { 36506f32e7eSjoerg def TCRETURNdi64 : PseudoI<(outs), 366*da58b97aSjoerg (ins i64i32imm_brtarget:$dst, i32imm:$offset), 36706f32e7eSjoerg []>, Sched<[WriteJump]>; 36806f32e7eSjoerg def TCRETURNri64 : PseudoI<(outs), 36906f32e7eSjoerg (ins ptr_rc_tailcall:$dst, i32imm:$offset), 37006f32e7eSjoerg []>, Sched<[WriteJump]>, NotMemoryFoldable; 37106f32e7eSjoerg let mayLoad = 1 in 37206f32e7eSjoerg def TCRETURNmi64 : PseudoI<(outs), 37306f32e7eSjoerg (ins i64mem_TC:$dst, i32imm:$offset), 37406f32e7eSjoerg []>, Sched<[WriteJumpLd]>, NotMemoryFoldable; 37506f32e7eSjoerg 376*da58b97aSjoerg def TAILJMPd64 : PseudoI<(outs), (ins i64i32imm_brtarget:$dst), 37706f32e7eSjoerg []>, Sched<[WriteJump]>; 37806f32e7eSjoerg 37906f32e7eSjoerg def TAILJMPr64 : PseudoI<(outs), (ins ptr_rc_tailcall:$dst), 38006f32e7eSjoerg []>, Sched<[WriteJump]>; 38106f32e7eSjoerg 38206f32e7eSjoerg let mayLoad = 1 in 38306f32e7eSjoerg def TAILJMPm64 : PseudoI<(outs), (ins i64mem_TC:$dst), 38406f32e7eSjoerg []>, Sched<[WriteJumpLd]>; 38506f32e7eSjoerg 38606f32e7eSjoerg // Win64 wants indirect jumps leaving the function to have a REX_W prefix. 38706f32e7eSjoerg let hasREX_WPrefix = 1 in { 38806f32e7eSjoerg def TAILJMPr64_REX : PseudoI<(outs), (ins ptr_rc_tailcall:$dst), 38906f32e7eSjoerg []>, Sched<[WriteJump]>; 39006f32e7eSjoerg 39106f32e7eSjoerg let mayLoad = 1 in 39206f32e7eSjoerg def TAILJMPm64_REX : PseudoI<(outs), (ins i64mem_TC:$dst), 39306f32e7eSjoerg []>, Sched<[WriteJumpLd]>; 39406f32e7eSjoerg } 39506f32e7eSjoerg} 39606f32e7eSjoerg 39706f32e7eSjoerglet isPseudo = 1, isCall = 1, isCodeGenOnly = 1, 39806f32e7eSjoerg Uses = [RSP, SSP], 39906f32e7eSjoerg usesCustomInserter = 1, 40006f32e7eSjoerg SchedRW = [WriteJump] in { 401*da58b97aSjoerg def INDIRECT_THUNK_CALL32 : 40206f32e7eSjoerg PseudoI<(outs), (ins GR32:$dst), [(X86call GR32:$dst)]>, 403*da58b97aSjoerg Requires<[Not64BitMode,UseIndirectThunkCalls]>; 40406f32e7eSjoerg 405*da58b97aSjoerg def INDIRECT_THUNK_CALL64 : 40606f32e7eSjoerg PseudoI<(outs), (ins GR64:$dst), [(X86call GR64:$dst)]>, 407*da58b97aSjoerg Requires<[In64BitMode,UseIndirectThunkCalls]>; 40806f32e7eSjoerg 409*da58b97aSjoerg // Indirect thunk variant of indirect tail calls. 41006f32e7eSjoerg let isTerminator = 1, isReturn = 1, isBarrier = 1 in { 411*da58b97aSjoerg def INDIRECT_THUNK_TCRETURN64 : 41206f32e7eSjoerg PseudoI<(outs), (ins GR64:$dst, i32imm:$offset), []>; 413*da58b97aSjoerg def INDIRECT_THUNK_TCRETURN32 : 41406f32e7eSjoerg PseudoI<(outs), (ins GR32:$dst, i32imm:$offset), []>; 41506f32e7eSjoerg } 41606f32e7eSjoerg} 41706f32e7eSjoerg 418*da58b97aSjoerglet isPseudo = 1, isCall = 1, isCodeGenOnly = 1, 419*da58b97aSjoerg Uses = [RSP, SSP], 420*da58b97aSjoerg SchedRW = [WriteJump] in { 421*da58b97aSjoerg def CALL64m_RVMARKER : 422*da58b97aSjoerg PseudoI<(outs), (ins i32imm:$sel, i64mem:$dst), [(X86call_rvmarker timm:$sel, (loadi64 addr:$dst))]>, 423*da58b97aSjoerg Requires<[In64BitMode]>; 424*da58b97aSjoerg 425*da58b97aSjoerg def CALL64r_RVMARKER : 426*da58b97aSjoerg PseudoI<(outs), (ins i32imm:$sel, GR64:$dst), [(X86call_rvmarker timm:$sel, GR64:$dst)]>, 427*da58b97aSjoerg Requires<[In64BitMode]>; 428*da58b97aSjoerg 429*da58b97aSjoerg def CALL64pcrel32_RVMARKER : 430*da58b97aSjoerg PseudoI<(outs), (ins i32imm:$sel, i64i32imm_brtarget:$dst), []>, 431*da58b97aSjoerg Requires<[In64BitMode]>; 432*da58b97aSjoerg} 433*da58b97aSjoerg 43406f32e7eSjoerg// Conditional tail calls are similar to the above, but they are branches 43506f32e7eSjoerg// rather than barriers, and they use EFLAGS. 43606f32e7eSjoerglet isCall = 1, isTerminator = 1, isReturn = 1, isBranch = 1, 43706f32e7eSjoerg isCodeGenOnly = 1, SchedRW = [WriteJump] in 43806f32e7eSjoerg let Uses = [RSP, EFLAGS, SSP] in { 43906f32e7eSjoerg def TCRETURNdi64cc : PseudoI<(outs), 440*da58b97aSjoerg (ins i64i32imm_brtarget:$dst, i32imm:$offset, 44106f32e7eSjoerg i32imm:$cond), []>; 44206f32e7eSjoerg 44306f32e7eSjoerg // This gets substituted to a conditional jump instruction in MC lowering. 44406f32e7eSjoerg def TAILJMPd64_CC : PseudoI<(outs), 445*da58b97aSjoerg (ins i64i32imm_brtarget:$dst, i32imm:$cond), []>; 44606f32e7eSjoerg} 447