emit_x64: Make RSB a stack
This commit is contained in:
parent
984ce22431
commit
a4e85ad565
3 changed files with 39 additions and 31 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue