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