// Kernel call static bool kc(PPCEmuAssembler& a, Instruction instr) { auto id = instr.kcn; auto kc = cpu::getKernelCall(id); decaf_assert(kc, fmt::format("Encountered invalid Kernel Call ID {}", id)); // Evict all stored register as a KC might read or modify them. a.evictAll(); // Save NIA back to memory in case KC reads/writes it a.mov(a.niaMem, a.genCia + 4); // Call the KC a.mov(a.sysArgReg[0], asmjit::Ptr(kc->func)); a.mov(a.sysArgReg[1], asmjit::Ptr(kc->user_data)); a.call(asmjit::Ptr(&kc_stub)); a.mov(a.stateReg, asmjit::x86::rax); // Check if the KC adjusted nia. If it has, we need to return // to the dispatcher. Note that we assume the cache was already // cleared before this instruction since KC requires that anyways. auto niaUnchangedLbl = a.newLabel(); a.cmp(a.niaMem, a.genCia + 4); a.je(niaUnchangedLbl); a.mov(a.finaleNiaArgReg, a.niaMem); a.mov(a.finaleJmpSrcArgReg, 0); a.jmp(asmjit::Ptr(gFinaleFn)); a.bind(niaUnchangedLbl); return true; }