Instruction
CALL
Pushes the return address and jumps to a relative target, one in a register or memory, or a far pointer that also changes the code segment.
- Extensions
- Forms
- 6 (6 Legacy)
- Data
- Intel XED v2026.08.23
Compiled 64-bit code calls a function in one of two ways:
- CALL rel32 (E8) when the target is fixed at link time. The displacement counts from the end of the instruction and reaches 2 GiB either way.
- CALL r/m64 (FF /2) when the target is known only at run time, such as a function pointer or a C++ virtual function read from its table.
Both push the address of the next instruction, so RSP drops by 8, and RET pops it again. System V and Microsoft x64 both want RSP to be a multiple of 16 just before the CALL, so a function starts with RSP 8 bytes past one (see stack frames).
Things to know:
- Faults. A non-canonical target raises #GP(0) at the CALL itself, with nothing pushed, as Zen 5 recorded. A canonical target on an unmapped page faults only at the target, after the push, so the return address on the stack still names the caller.
- Return prediction. Processors predict each RET from a stack of the addresses that CALLs pushed (52 entries per thread on Zen 5, by AMD’s optimization guide). Intel’s optimization manual therefore asks for calls and returns in pairs, not a PUSH of an address followed by a JMP, and suggests turning a call in tail position into a JMP.
- CET. With shadow stacks enabled, which Intel and AMD both have, CALL also writes the return address to the shadow stack, and RET raises #CP when the two copies differ. With Intel’s indirect branch tracking, an indirect CALL must land on ENDBR64 (#CP otherwise) unless a 3E (NOTRACK) prefix exempts it where the OS allows that; AMD’s manuals do not describe this part.
- 66 prefix. Intel’s manual fixes the operand size of near calls at 64 bits in 64-bit mode. AMD’s lets a 66 prefix make it 16 bits: a 2-byte displacement, a 2-byte push and RIP cut to 16 bits. The same bytes thus have different lengths on the two; the forms table lists only Intel’s rel32 form for 64-bit mode.
- Far calls through memory remain for changing code segments. With REX.W, Intel’s processors read a 64-bit offset (m16:64); AMD’s manual allows only a 32-bit one.
32-bit position-independent code learns its own address from the return address that a CALL pushes (see the i386 ABI); 64-bit code uses RIP-relative addressing instead, as in LEA.
In the optimization guide
What the optimization guide says about CALL, a line per claim. Each links to the claim in the guide, with its sources and where they differ.
Front end
- Decoded-instruction caches: Each unconditional jump or call ends a line of Intel’s decoded cache, so at most three of them in a 32-byte block can be cached.
Branches
- Calls and returns: Returns are predicted by a return stack, which every call pushes and every return pops.
- Calls and returns: The return stack predicts returns only while calls and returns pair up, so pushing an address and jumping, or returning to a computed address, costs mispredictions.
- Calls and returns: A call that is the last thing a function does can become a jump to the callee, whose return then goes straight to the original caller.
- Calls and returns: Even predicted calls and returns cost time: each leaves the predictor idle for a cycle on Zen 3 and Zen 4, a return for two on Zen 5, and Agner Fog measured one every two cycles.
- Indirect branches: An indirect
jmporcallthat always goes to the same place is predicted from its BTB entry like a direct one. sources differ - Indirect branches: An indirect branch the predictor has no target for is assumed to fall through, so the bytes after it are fetched and may be decoded and run.
- Indirect branches: An indirect branch to a distant target is predicted worse: Zen 3 and Zen 4 track only a few targets beyond a 64 MB aligned boundary, and Intel’s cores mispredict more often beyond 2 GB.
- Indirect branches: LLVM’s retpoline options send indirect calls and jumps through a sequence that does not speculate on their target, and turn each
switchinto conditional branches rather than a jump table.
Bulldozer to Excavator
- Branches: The return address stack has 24 entries, so each
callshould have itsret: a deeper chain loses the oldest and an unpaired call desynchronises it, except a call to the very next instruction, which the core recognises.
Golden Cove and Raptor Cove
- Branches: An indirect
jmporcallthrough a register or memory whose target lies more than 2 GB away takes more of the predictor and mispredicts more often.
Jaguar and Puma
- Branches: A 16-entry return stack that a call to the next instruction puts out of step, and no need for rep ret.
Silvermont to Goldmont Plus
- Front end: On Silvermont these instructions come from the microcode ROM; Goldmont decodes them directly, except an indirect call through memory.
- Branches: Silvermont predicts an indirect branch from its last target alone, Goldmont from patterns.
- Out-of-order and in-order execution: LLVM’s tuning for all four cores loads the operand of
pushandcallinto a register first, and prefersmovbeto a load and abswap.
Skylake to Cooper Lake
- The JCC erratum: Under rare conditions a jump that crosses a 64-byte line could make these cores misbehave (erratum SKX102).
Tremont
- Integer execution: LLVM’s tuning treats
push,popandcallwith a memory operand as slow on this core and loads the operand into a register first.
Zen and Zen+
- Branches: The return address stack has 32 entries, of which 31 can be used, and 15 per thread with two threads.
Zen 2
- Branches: The return address stack has 32 entries, 31 of them usable, and 15 per thread with two threads.
Zen 3
- Branches: The return address stack has 32 entries per thread.
- Integer execution: PUSH, POP, CALL and RET update RSP without a dependency, and loads, stores,
leaandmovfrom RSP can use the tracked value.
Zen 4
- Branches: The return address stack has 32 entries per thread, against 52 on Zen 5.
- Integer execution: PUSH, POP, CALL and RET update RSP without a dependency, and loads, stores,
leaandmovfrom RSP can use the tracked value.
Zen 5
- Branches: The return address stack has 52 entries per thread.
- Integer execution: PUSH, POP, CALL and RET update RSP without a dependency, and loads, stores,
leaandaddorsubof a small immediate through RSP can use the tracked value.
Vulnerability mitigations
Mitigations of these processor vulnerabilities use CALL:
- CVE-2022-27672: Cross-Thread Return Address Predictions
- CVE-2022-23824: Incomplete Branch Prediction Barrier (IBPB and Return Stack Buffer Interactions)
Forms
| Instruction | Encoding | Requires |
|---|---|---|
CALL m16/32/64
CALL_NEAR_MEMv | FF /2 | Base instruction set |
CALL r16/32/64
CALL_NEAR_GPRv | FF /2 | Base instruction set |
CALL rel16/32 not in 64-bit mode
CALL_NEAR_RELBRz | E8 cw/cd | Base instruction set |
CALL rel32 64-bit mode only
CALL_NEAR_RELBRd | E8 cd | Base instruction set |
CALL m16:16/32/64
CALL_FAR_MEMp2 | FF /3 | Base instruction set |
CALL ptr16:16/32 not in 64-bit mode
CALL_FAR_PTRp_IMMw | 9A cw/cd iw | Base instruction set |
Latency and throughput
| Model | m64 | r64 | rel32 |
|---|---|---|---|
| Sandy Bridge | 7 / 1p5 | 5 / 1p4 p5 p23 | 5 / 1p4 p5 p23 |
| Haswell | 8 / 1p0156 | 3 / 1p01234567 | 3 / 1p01234567 |
| Broadwell, Skylake, Skylake-SP | 7 / 1p0156 | 3 / 1p01234567 | 3 / 1p01234567 |
| Ice Lake | 7 / 1p0156 | 3 / 1p01456789 | 3 / 0.5p01456789 |
| Alder Lake, Sapphire Rapids | 7 / 0.5p0 p1 p5 p6 p11 | 3 / 0.5p046789 | 3 / 0.5p4789 |
| Lunar Lake | 7 / 0.5p012345 | 3 / 0.5p0 p2 p4 p10 p11 p25 p26 p27 | 3 / 0.5p10 p11 p25 p26 p27 |
| Bonnell | 1 / 1p1 | 1 / 1p1 | 1 / 1p1 |
| Silvermont | 1 / 1IEC1 | 1 / 1IEC1 | 1 / 1IEC1 |
| Piledriver | 1 / 1Branch EX1 | 1 / 1Branch EX1 | 1 / 1Branch EX1 |
| Zen, Zen 2 | 1 / 0.25ALU0 ALU1 ALU2 ALU3 | 1 / 0.25ALU0 ALU1 ALU2 ALU3 | 1 / 0.25ALU0 ALU1 ALU2 ALU3 |
| Zen 3, Zen 4 | 1 / 0.5ALU0 BRU1 | 1 / 0.5ALU0 BRU1 | 1 / 0.5ALU0 BRU1 |
| Jaguar | 1 / 0.5ALU0 ALU1 | 1 / 0.5ALU0 ALU1 | 1 / 0.5ALU0 ALU1 |
Operation
What the forms do, in pseudocode that our tests run against results recorded on real processors. How to read.
CALL rel16/32 not in 64-bit mode CALL rel32 64-bit mode onlyw = OSIZE # the size of the target and of
n = 0 # the return address
if OSIZE == 16: # a 66 prefix
if INTEL:
w = 64 # ignored: SDM
else:
if rel.bits == 32:
n = 2 # a rel16, as JMP's: APM, Zen 5
r = rip - n # the next instruction
t = low(r + signed(rel), w)
if not canonical(t):
fault(GP, 0) # before the push
a = rsp - w // 8 # 2 bytes with 66 on AMD's
store(a, w, r) # the return address
rsp = a
rip = tRun on AMD Zen 5 (EPYC 9645): 5 cases. Its branches for Intel's processors were not run: no Intel processor ran these forms. The forms that 64-bit mode lacks were not run: the probe runs in 64-bit mode.
CALL r/m16/32/64t = target.read() # CALL RSP: RSP from before; r/m64,
# or with 66 r/m16 on AMD's,
# zero-extended
w = OSIZE # the size of the return address:
if OSIZE == 16: # with 66, 2 bytes on AMD's (APM,
if INTEL: # Zen 5)
w = 64 # ignored: SDM
if not canonical(t):
fault(GP, 0)
a = rsp - w // 8 # 8 bytes, or 2 with 66 on AMD's
store(a, w, rip)
rsp = a
rip = tRun on AMD Zen 5 (EPYC 9645): 8 cases. Its branches for Intel's processors were not run: no Intel processor ran these forms.
CALL ptr16:16/32 not in 64-bit mode CALL m16:16/32/64v = target.read() # the offset, then a 16-bit selector
n = OSIZE // 8
a = rsp - 2 * n
store(a + n, OSIZE, cs) # CS, zero-extended, then the return
store(a, OSIZE, rip) # address
rsp = a
cs = v >> OSIZE & 0xFFFF # with the checks of a far JMP; a
rip = low(v, OSIZE) # call gate to a more privileged
# level switches stacks first
Not run on a processor: a far call loads CS from a descriptor table, which the probe does not record.
Operands
| Operand | Kind | Action |
|---|---|---|
CALL r/m16/32/64 | ||
r/m16/32/64 | explicit | read |
stack | implicit | write |
rSP | implicit | read, write |
rIP | implicit | read, write |
CALL rel16/32 not in 64-bit mode CALL rel32 64-bit mode only | ||
rel16/32 | explicit | read |
stack | implicit | write |
rSP | implicit | read, write |
rIP | implicit | read, write |
CALL m16:16/32/64 | ||
m16:16/32/64 | explicit | read |
stack | implicit | write |
rSP | implicit | read, write |
rIP | implicit | write |
CALL ptr16:16/32 not in 64-bit mode | ||
ptr16:16/32 | explicit | read |
stack | implicit | write |
rSP | implicit | read, write |
EIP | implicit | write |
Flags
None: XED records no flag that the forms test or change.
Attributes
What else XED records about the forms. How to read.
CALL r/m16/32/64CALL m16:16/32/64- indirect branch
CALL ptr16:16/32not in 64-bit modeCALL m16:16/32/64- far transfer; may abort a TSX transaction
CPUID and processors
Each form belongs to an XED ISA set. A form can be used when the processor reports every CPUID bit of one of its ISA set's alternatives.
| ISA set | CPUID | Processors |
|---|---|---|
I86 | No CPUID bit: part of the base instruction set. | Every x86-64 processor in XED’s model and Zen 3 to Zen 6 |
More General-purpose instructions
Sources
- Intel XED v2026.08.23 (commit
0bcb6237345c): forms, encodings, operands, flags, exception classes, attributes, ISA sets, CPUID bits and chip model. - The CPU data of x86-64.net: Zen 3 to Zen 6, from GCC’s
-marchfeature sets and AMD’s Processor Programming References, which the page of each processor cites. - LLVM 23.1.2's x86 scheduling models (commit
85ac56026243): the latency, reciprocal throughput and ports of each form, as llvm-mca reports them. - Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 2 (325383-093, September 2026): Volume 2A, page 3-121 (CALL)
- Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 1 (253665-093, September 2026)
- AMD64 Architecture Programmer's Manual, Volume 2: System Programming (24593, rev. 3.46, October 2026)
- AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and System Instructions (24594, rev. 3.39, October 2026)
- Intel 64 and IA-32 Architectures Optimization Reference Manual, Volume 1 (248966-051, October 2026)
- Software Optimization Guide for the AMD Zen5 Microarchitecture (58455, rev. 1.00, August 2024), Wayback Machine copy of AMD's ZIP
The tables are derived from Intel XED, Copyright Intel Corporation, licensed under the Apache License 2.0; x86-64.net converted and reformatted them. The timings come from LLVM's scheduling models, part of the LLVM Project, licensed under the Apache License 2.0 with LLVM Exceptions. The text is our own.