| 514 | } |
| 515 | |
| 516 | void OpDispatchBuilder::CALLOp(OpcodeArgs) { |
| 517 | const auto GPRSize = GetGPROpSize(); |
| 518 | |
| 519 | BlockSetRIP = true; |
| 520 | |
| 521 | // ABI Optimization: Flags don't survive calls or rets |
| 522 | if (CTX->Config.ABILocalFlags) { |
| 523 | _InvalidateFlags(~0UL); // all flags |
| 524 | InvalidatePF_AF(); |
| 525 | } |
| 526 | |
| 527 | // Call instruction only uses up to 32-bit signed displacement |
| 528 | int64_t TargetOffset = Op->Src[0].Literal(); |
| 529 | |
| 530 | auto ConstantPC = GetRelocatedPC(Op); |
| 531 | |
| 532 | // Push the return address. |
| 533 | Push(GPRSize, ConstantPC); |
| 534 | |
| 535 | const uint64_t NextRIP = Op->PC + Op->InstSize; |
| 536 | uint64_t TargetRIP = NextRIP + TargetOffset; |
| 537 | |
| 538 | if (NextRIP != TargetRIP) { |
| 539 | // Store the RIP |
| 540 | ExitRelocatedPC(Op, TargetOffset, BranchHint::Call, ConstantPC, [&]() { |
| 541 | auto CallReturnJumpTarget = JumpTargets.find(NextRIP); |
| 542 | if (CallReturnJumpTarget != JumpTargets.end() && CallReturnJumpTarget->second.IsEntryPoint) { |
| 543 | return CallReturnJumpTarget->second.BlockEntry; |
| 544 | } |
| 545 | return InvalidNode; |
| 546 | }()); |
| 547 | } else { |
| 548 | NeedsBlockEnd = true; |
| 549 | } |
| 550 | } |
| 551 | |
| 552 | void OpDispatchBuilder::CALLAbsoluteOp(OpcodeArgs) { |
| 553 | BlockSetRIP = true; |