Exemple #1
0
void emitCall(Asm& a, CppCall call) {
    if (call.isDirect()) {
        return emitCall(a, (TCA)call.getAddress());
    } else if (call.isVirtual()) {
        // 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()]);
    } else {
        assert(call.isIndirect());
        a.  call   (call.getReg());
    }
}
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;
}