diff --git a/src/xenia/cpu/backend/x64/x64_backend.cc b/src/xenia/cpu/backend/x64/x64_backend.cc index 7f51db92b..beed2af8e 100644 --- a/src/xenia/cpu/backend/x64/x64_backend.cc +++ b/src/xenia/cpu/backend/x64/x64_backend.cc @@ -446,14 +446,13 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() { sub(rsp, stack_size); // Save off volatile registers. - // TODO(DrChat): Enable when necessary. - // EmitSaveVolatileRegs(); + EmitSaveVolatileRegs(); mov(rax, rcx); // function mov(rcx, GetContextReg()); // context call(rax); - // EmitLoadVolatileRegs(); + EmitLoadVolatileRegs(); add(rsp, stack_size); ret(); @@ -468,21 +467,22 @@ extern "C" uint64_t ResolveFunction(void* raw_context, uint32_t target_address); ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk() { // ebx = target PPC address // rcx = context - uint32_t stack_size = 0x18; + const size_t stack_size = StackLayout::THUNK_STACK_SIZE; // rsp + 0 = return address - mov(qword[rsp + 8 * 2], rdx); - mov(qword[rsp + 8 * 1], rcx); sub(rsp, stack_size); + // Save volatile registers + EmitSaveVolatileRegs(); + mov(rcx, rsi); // context mov(rdx, rbx); mov(rax, uint64_t(&ResolveFunction)); call(rax); + EmitLoadVolatileRegs(); + add(rsp, stack_size); - mov(rcx, qword[rsp + 8 * 1]); - mov(rdx, qword[rsp + 8 * 2]); jmp(rax); void* fn = Emplace(stack_size); @@ -491,34 +491,38 @@ ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk() { void X64ThunkEmitter::EmitSaveVolatileRegs() { // Save off volatile registers. - mov(qword[rsp + offsetof(StackLayout::Thunk, r[0])], rcx); - mov(qword[rsp + offsetof(StackLayout::Thunk, r[1])], rdx); - mov(qword[rsp + offsetof(StackLayout::Thunk, r[2])], r8); - mov(qword[rsp + offsetof(StackLayout::Thunk, r[3])], r9); - mov(qword[rsp + offsetof(StackLayout::Thunk, r[4])], r10); - mov(qword[rsp + offsetof(StackLayout::Thunk, r[5])], r11); + // mov(qword[rsp + offsetof(StackLayout::Thunk, r[0])], rax); + mov(qword[rsp + offsetof(StackLayout::Thunk, r[1])], rcx); + mov(qword[rsp + offsetof(StackLayout::Thunk, r[2])], rdx); + mov(qword[rsp + offsetof(StackLayout::Thunk, r[3])], r8); + mov(qword[rsp + offsetof(StackLayout::Thunk, r[4])], r9); + mov(qword[rsp + offsetof(StackLayout::Thunk, r[5])], r10); + mov(qword[rsp + offsetof(StackLayout::Thunk, r[6])], r11); - movaps(qword[rsp + offsetof(StackLayout::Thunk, xmm[0])], xmm1); - movaps(qword[rsp + offsetof(StackLayout::Thunk, xmm[1])], xmm2); - movaps(qword[rsp + offsetof(StackLayout::Thunk, xmm[2])], xmm3); - movaps(qword[rsp + offsetof(StackLayout::Thunk, xmm[3])], xmm4); - movaps(qword[rsp + offsetof(StackLayout::Thunk, xmm[4])], xmm5); + // movaps(qword[rsp + offsetof(StackLayout::Thunk, xmm[0])], xmm0); + movaps(qword[rsp + offsetof(StackLayout::Thunk, xmm[1])], xmm1); + movaps(qword[rsp + offsetof(StackLayout::Thunk, xmm[2])], xmm2); + movaps(qword[rsp + offsetof(StackLayout::Thunk, xmm[3])], xmm3); + movaps(qword[rsp + offsetof(StackLayout::Thunk, xmm[4])], xmm4); + movaps(qword[rsp + offsetof(StackLayout::Thunk, xmm[5])], xmm5); } void X64ThunkEmitter::EmitLoadVolatileRegs() { // Load volatile registers from our stack frame. - movaps(xmm1, qword[rsp + offsetof(StackLayout::Thunk, xmm[0])]); - movaps(xmm2, qword[rsp + offsetof(StackLayout::Thunk, xmm[1])]); - movaps(xmm3, qword[rsp + offsetof(StackLayout::Thunk, xmm[2])]); - movaps(xmm4, qword[rsp + offsetof(StackLayout::Thunk, xmm[3])]); - movaps(xmm5, qword[rsp + offsetof(StackLayout::Thunk, xmm[4])]); + // movaps(xmm0, qword[rsp + offsetof(StackLayout::Thunk, xmm[0])]); + movaps(xmm1, qword[rsp + offsetof(StackLayout::Thunk, xmm[1])]); + movaps(xmm2, qword[rsp + offsetof(StackLayout::Thunk, xmm[2])]); + movaps(xmm3, qword[rsp + offsetof(StackLayout::Thunk, xmm[3])]); + movaps(xmm4, qword[rsp + offsetof(StackLayout::Thunk, xmm[4])]); + movaps(xmm5, qword[rsp + offsetof(StackLayout::Thunk, xmm[5])]); - mov(rcx, qword[rsp + offsetof(StackLayout::Thunk, r[0])]); - mov(rdx, qword[rsp + offsetof(StackLayout::Thunk, r[1])]); - mov(r8, qword[rsp + offsetof(StackLayout::Thunk, r[2])]); - mov(r9, qword[rsp + offsetof(StackLayout::Thunk, r[3])]); - mov(r10, qword[rsp + offsetof(StackLayout::Thunk, r[4])]); - mov(r11, qword[rsp + offsetof(StackLayout::Thunk, r[5])]); + // mov(rax, qword[rsp + offsetof(StackLayout::Thunk, r[0])]); + mov(rcx, qword[rsp + offsetof(StackLayout::Thunk, r[1])]); + mov(rdx, qword[rsp + offsetof(StackLayout::Thunk, r[2])]); + mov(r8, qword[rsp + offsetof(StackLayout::Thunk, r[3])]); + mov(r9, qword[rsp + offsetof(StackLayout::Thunk, r[4])]); + mov(r10, qword[rsp + offsetof(StackLayout::Thunk, r[5])]); + mov(r11, qword[rsp + offsetof(StackLayout::Thunk, r[6])]); } void X64ThunkEmitter::EmitSaveNonvolatileRegs() { diff --git a/src/xenia/cpu/backend/x64/x64_emitter.cc b/src/xenia/cpu/backend/x64/x64_emitter.cc index 3cf7f5813..7ffd7b582 100644 --- a/src/xenia/cpu/backend/x64/x64_emitter.cc +++ b/src/xenia/cpu/backend/x64/x64_emitter.cc @@ -56,12 +56,13 @@ static const size_t kStashOffset = 32; // static const size_t kStashOffsetHigh = 32 + 32; const uint32_t X64Emitter::gpr_reg_map_[X64Emitter::GPR_COUNT] = { - Xbyak::Operand::RBX, Xbyak::Operand::R12, Xbyak::Operand::R13, - Xbyak::Operand::R14, Xbyak::Operand::R15, + Xbyak::Operand::RBX, Xbyak::Operand::R10, Xbyak::Operand::R11, + Xbyak::Operand::R12, Xbyak::Operand::R13, Xbyak::Operand::R14, + Xbyak::Operand::R15, }; const uint32_t X64Emitter::xmm_reg_map_[X64Emitter::XMM_COUNT] = { - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, }; X64Emitter::X64Emitter(X64Backend* backend, XbyakAllocator* allocator) @@ -494,30 +495,20 @@ void X64Emitter::CallExtern(const hir::Instr* instr, const Function* function) { } } -void X64Emitter::CallNative(void* fn) { - mov(rax, reinterpret_cast(fn)); - mov(rcx, GetContextReg()); - call(rax); -} +void X64Emitter::CallNative(void* fn) { CallNativeSafe(fn); } void X64Emitter::CallNative(uint64_t (*fn)(void* raw_context)) { - mov(rax, reinterpret_cast(fn)); - mov(rcx, GetContextReg()); - call(rax); + CallNativeSafe(reinterpret_cast(fn)); } void X64Emitter::CallNative(uint64_t (*fn)(void* raw_context, uint64_t arg0)) { - mov(rax, reinterpret_cast(fn)); - mov(rcx, GetContextReg()); - call(rax); + CallNativeSafe(reinterpret_cast(fn)); } void X64Emitter::CallNative(uint64_t (*fn)(void* raw_context, uint64_t arg0), uint64_t arg0) { - mov(rax, reinterpret_cast(fn)); - mov(rcx, GetContextReg()); - mov(rdx, arg0); - call(rax); + mov(GetNativeParam(0), arg0); + CallNativeSafe(reinterpret_cast(fn)); } void X64Emitter::CallNativeSafe(void* fn) { @@ -537,8 +528,7 @@ void X64Emitter::SetReturnAddress(uint64_t value) { mov(qword[rsp + StackLayout::GUEST_CALL_RET_ADDR], rax); } -Xbyak::Reg64 X64Emitter::GetNativeParam(uint32_t param) -{ +Xbyak::Reg64 X64Emitter::GetNativeParam(uint32_t param) { if (param == 0) return rdx; else if (param == 1) diff --git a/src/xenia/cpu/backend/x64/x64_emitter.h b/src/xenia/cpu/backend/x64/x64_emitter.h index 3fb32d58d..a35c2d2b0 100644 --- a/src/xenia/cpu/backend/x64/x64_emitter.h +++ b/src/xenia/cpu/backend/x64/x64_emitter.h @@ -139,13 +139,13 @@ class X64Emitter : public Xbyak::CodeGenerator { std::vector* out_source_map); public: - // Reserved: rsp + // Reserved: rsp, rsi, rdi // Scratch: rax/rcx/rdx // xmm0-2 - // Available: rbx, r12-r15 (save to get r8-r11, rbp, rsi, rdi?) - // xmm6-xmm15 (save to get xmm3-xmm5) - static const int GPR_COUNT = 5; - static const int XMM_COUNT = 10; + // Available: rbx, r10-r15 + // xmm4-xmm15 (save to get xmm3) + static const int GPR_COUNT = 7; + static const int XMM_COUNT = 12; static void SetupReg(const hir::Value* v, Xbyak::Reg8& r) { auto idx = gpr_reg_map_[v->reg.index];