emit_x64: Make RSB a stack

This commit is contained in:
MerryMage 2017-11-27 20:29:19 +00:00
parent 984ce22431
commit a4e85ad565
3 changed files with 39 additions and 31 deletions

View file

@ -483,41 +483,39 @@ void EmitX64::EmitSetFpscrNZCV(RegAlloc& reg_alloc, IR::Block&, IR::Inst* inst)
code->mov(dword[r15 + offsetof(JitState, FPSCR_nzcv)], value); code->mov(dword[r15 + offsetof(JitState, FPSCR_nzcv)], value);
} }
void EmitX64::EmitPushRSB(RegAlloc& reg_alloc, IR::Block&, IR::Inst* inst) { void EmitX64::PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, u64 target_hash) {
using namespace Xbyak::util; using namespace Xbyak::util;
auto args = reg_alloc.GetArgumentInfo(inst); auto iter = block_descriptors.find(target_hash);
ASSERT(args[0].IsImmediate());
u64 unique_hash_of_target = args[0].GetImmediateU64();
auto iter = block_descriptors.find(unique_hash_of_target);
CodePtr target_code_ptr = iter != block_descriptors.end() CodePtr target_code_ptr = iter != block_descriptors.end()
? iter->second.entrypoint ? iter->second.entrypoint
: code->GetReturnFromRunCodeAddress(); : code->GetReturnFromRunCodeAddress();
Xbyak::Reg64 code_ptr_reg = reg_alloc.ScratchGpr({HostLoc::RCX}); code->mov(index_reg.cvt32(), dword[r15 + offsetof(JitState, rsb_ptr)]);
Xbyak::Reg64 loc_desc_reg = reg_alloc.ScratchGpr();
Xbyak::Reg32 index_reg = reg_alloc.ScratchGpr().cvt32();
code->mov(index_reg, dword[r15 + offsetof(JitState, rsb_ptr)]); code->mov(loc_desc_reg, target_hash);
code->add(index_reg, 1);
code->and_(index_reg, u32(JitState::RSBSize - 1));
code->mov(loc_desc_reg, unique_hash_of_target); patch_information[target_hash].mov_rcx.emplace_back(code->getCurr());
patch_information[unique_hash_of_target].mov_rcx.emplace_back(code->getCurr());
EmitPatchMovRcx(target_code_ptr); EmitPatchMovRcx(target_code_ptr);
Xbyak::Label label; code->mov(qword[r15 + index_reg * 8 + offsetof(JitState, rsb_location_descriptors)], loc_desc_reg);
for (size_t i = 0; i < JitState::RSBSize; ++i) { code->mov(qword[r15 + index_reg * 8 + offsetof(JitState, rsb_codeptrs)], rcx);
code->cmp(loc_desc_reg, qword[r15 + offsetof(JitState, rsb_location_descriptors) + i * sizeof(u64)]);
code->je(label, code->T_SHORT);
}
code->mov(dword[r15 + offsetof(JitState, rsb_ptr)], index_reg); code->add(index_reg.cvt32(), 1);
code->mov(qword[r15 + index_reg.cvt64() * 8 + offsetof(JitState, rsb_location_descriptors)], loc_desc_reg); code->and_(index_reg.cvt32(), u32(JitState::RSBPtrMask));
code->mov(qword[r15 + index_reg.cvt64() * 8 + offsetof(JitState, rsb_codeptrs)], code_ptr_reg); code->mov(dword[r15 + offsetof(JitState, rsb_ptr)], index_reg.cvt32());
code->L(label); }
void EmitX64::EmitPushRSB(RegAlloc& reg_alloc, IR::Block&, IR::Inst* inst) {
auto args = reg_alloc.GetArgumentInfo(inst);
ASSERT(args[0].IsImmediate());
u64 unique_hash_of_target = args[0].GetImmediateU64();
reg_alloc.ScratchGpr({HostLoc::RCX});
Xbyak::Reg64 loc_desc_reg = reg_alloc.ScratchGpr();
Xbyak::Reg64 index_reg = reg_alloc.ScratchGpr();
PushRSBHelper(loc_desc_reg, index_reg, unique_hash_of_target);
} }
void EmitX64::EmitGetCarryFromOp(RegAlloc&, IR::Block&, IR::Inst*) { void EmitX64::EmitGetCarryFromOp(RegAlloc&, IR::Block&, IR::Inst*) {
@ -3412,9 +3410,16 @@ void EmitX64::EmitTerminal(IR::Term::LinkBlock terminal, IR::LocationDescriptor
} else { } else {
EmitPatchJg(terminal.next); EmitPatchJg(terminal.next);
} }
Xbyak::Label dest;
code->jmp(dest, Xbyak::CodeGenerator::T_NEAR);
code->SwitchToFarCode();
code->align(16);
code->L(dest);
code->mov(MJitStateReg(Arm::Reg::PC), terminal.next.PC()); code->mov(MJitStateReg(Arm::Reg::PC), terminal.next.PC());
code->ForceReturnFromRunCode(); // TODO: Check cycles, Properly do a link PushRSBHelper(rax, rbx, terminal.next.UniqueHash());
code->ForceReturnFromRunCode();
code->SwitchToNearCode();
} }
void EmitX64::EmitTerminal(IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location) { void EmitX64::EmitTerminal(IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location) {
@ -3455,12 +3460,13 @@ void EmitX64::EmitTerminal(IR::Term::PopRSBHint, IR::LocationDescriptor) {
code->shl(rbx, 32); code->shl(rbx, 32);
code->or_(rbx, rcx); code->or_(rbx, rcx);
code->mov(rax, reinterpret_cast<u64>(code->GetReturnFromRunCodeAddress())); code->mov(eax, dword[r15 + offsetof(JitState, rsb_ptr)]);
for (size_t i = 0; i < JitState::RSBSize; ++i) { code->sub(eax, 1);
code->cmp(rbx, qword[r15 + offsetof(JitState, rsb_location_descriptors) + i * sizeof(u64)]); code->and_(eax, u32(JitState::RSBPtrMask));
code->cmove(rax, qword[r15 + offsetof(JitState, rsb_codeptrs) + i * sizeof(u64)]); code->mov(dword[r15 + offsetof(JitState, rsb_ptr)], eax);
} code->cmp(rbx, qword[r15 + offsetof(JitState, rsb_location_descriptors) + rax * sizeof(u64)]);
code->jne(code->GetReturnFromRunCodeAddress());
code->mov(rax, qword[r15 + offsetof(JitState, rsb_codeptrs) + rax * sizeof(u64)]);
code->jmp(rax); code->jmp(rax);
} }

View file

@ -73,6 +73,7 @@ private:
// Helpers // Helpers
void EmitAddCycles(size_t cycles); void EmitAddCycles(size_t cycles);
void EmitCondPrelude(const IR::Block& block); void EmitCondPrelude(const IR::Block& block);
void PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, u64 target_hash);
// Terminal instruction emitters // Terminal instruction emitters
void EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location); void EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location);

View file

@ -46,6 +46,7 @@ struct JitState {
u32 exclusive_address = 0; u32 exclusive_address = 0;
static constexpr size_t RSBSize = 8; // MUST be a power of 2. static constexpr size_t RSBSize = 8; // MUST be a power of 2.
static constexpr size_t RSBPtrMask = RSBSize - 1;
u32 rsb_ptr = 0; u32 rsb_ptr = 0;
std::array<u64, RSBSize> rsb_location_descriptors; std::array<u64, RSBSize> rsb_location_descriptors;
std::array<u64, RSBSize> rsb_codeptrs; std::array<u64, RSBSize> rsb_codeptrs;