Example #1
0
void emitCall(Asm& a, CppCall call) {
  if (call.isDirect()) {
    return emitCall(a, (TCA)call.getAddress());
  }
  // Virtual call.
  // Load method's address from proper offset off of object in rdi,
  // using rax as scratch.
  a.  loadq  (*rdi, rax);
  a.  call   (rax[call.getOffset()]);
}
void emitCall(vixl::MacroAssembler& a, CppCall call) {
  if (call.isDirect()) {
    a. Mov  (rHostCallReg, reinterpret_cast<intptr_t>(call.getAddress()));
  } else {
    a. Ldr  (rHostCallReg, argReg(0)[0]);
    a. Ldr  (rHostCallReg, rHostCallReg[call.getOffset()]);
  }

  using namespace vixl;
  a.   Push    (x30, x29);
  a.   HostCall(5);
  a.   Pop     (x29, x30);
}
TCA emitCall(vixl::MacroAssembler& a, CppCall call) {
  if (call.isDirect()) {
    a. Mov  (rHostCallReg, reinterpret_cast<intptr_t>(call.getAddress()));
  } else if (call.isVirtual()) {
    a. Ldr  (rHostCallReg, argReg(0)[0]);
    a. Ldr  (rHostCallReg, rHostCallReg[call.getOffset()]);
  } else {
    // call indirect currently not implemented. It'll be somthing like
    // a.Br(x2a(call.getReg()))
    not_implemented();
  }

  using namespace vixl;
  auto fixupAddr = a.frontier();
  a.   HostCall(6);

  // Note that the fixup address for a HostCall is directly *before* the
  // HostCall, not after as in the native case. This is because, in simulation
  // mode we look at the simulator's PC at the time the fixup is invoked, and it
  // will still be pointing to the HostCall; it's not advanced past it until the
  // host call returns. In the native case, by contrast, we'll be looking at
  // return addresses, which point after the call.
  return fixupAddr;
}