backend/A64: refactor to fpscr from mxcsr
This commit is contained in:
parent
47c0632e16
commit
bb39f419e2
@ -306,7 +306,6 @@ void A32EmitA64::GenTerminalHandlers() {
|
||||
code.ANDI2R(fast_dispatch_entry_reg, fast_dispatch_entry_reg, fast_dispatch_table_mask);
|
||||
code.ADD(fast_dispatch_entry_reg, fast_dispatch_entry_reg, code.ABI_SCRATCH1);
|
||||
|
||||
// code.cmp(location_descriptor_reg, qword[fast_dispatch_entry_reg + offsetof(FastDispatchEntry, location_descriptor)]);
|
||||
code.LDR(INDEX_UNSIGNED, code.ABI_SCRATCH1, fast_dispatch_entry_reg, offsetof(FastDispatchEntry, location_descriptor));
|
||||
code.CMP(location_descriptor_reg, code.ABI_SCRATCH1);
|
||||
fast_dispatch_cache_miss = code.B(CC_NEQ);
|
||||
@ -397,7 +396,6 @@ void A32EmitA64::EmitA32GetCpsr(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
ctx.reg_alloc.HostCall(inst);
|
||||
code.MOV(code.ABI_PARAM1, X28);
|
||||
code.QuickCallFunction(&GetCpsrImpl);
|
||||
|
||||
}
|
||||
|
||||
static void SetCpsrImpl(u32 value, A32JitState* jit_state) {
|
||||
@ -416,7 +414,6 @@ void A32EmitA64::EmitA32SetCpsr(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
|
||||
code.MOV(code.ABI_PARAM2, X28);
|
||||
code.QuickCallFunction(&SetCpsrImpl);
|
||||
|
||||
}
|
||||
|
||||
void A32EmitA64::EmitA32SetCpsrNZCV(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
@ -425,7 +422,6 @@ void A32EmitA64::EmitA32SetCpsrNZCV(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
|
||||
code.ANDI2R(a, a, 0xF0000000);
|
||||
code.STR(INDEX_UNSIGNED, a, X28, offsetof(A32JitState, CPSR_nzcv));
|
||||
|
||||
}
|
||||
|
||||
void A32EmitA64::EmitA32SetCpsrNZCVQ(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
@ -686,7 +682,7 @@ void A32EmitA64::EmitA32CallSupervisor(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
ctx.reg_alloc.HostCall(nullptr);
|
||||
ARM64Reg cycles_remaining = ctx.reg_alloc.ScratchGpr();
|
||||
|
||||
code.SwitchMxcsrOnExit();
|
||||
code.SwitchFpscrOnExit();
|
||||
code.LDR(INDEX_UNSIGNED, code.ABI_PARAM2, X28, offsetof(A32JitState, cycles_to_run));
|
||||
code.LDR(INDEX_UNSIGNED, cycles_remaining, X28, offsetof(A32JitState, cycles_remaining));
|
||||
code.SUB(code.ABI_PARAM2, code.ABI_PARAM2, cycles_remaining);
|
||||
@ -699,7 +695,7 @@ void A32EmitA64::EmitA32CallSupervisor(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
Devirtualize<&A32::UserCallbacks::GetTicksRemaining>(config.callbacks).EmitCall(code);
|
||||
code.STR(INDEX_UNSIGNED, code.ABI_RETURN, X28, offsetof(A32JitState, cycles_to_run));
|
||||
code.STR(INDEX_UNSIGNED, code.ABI_RETURN, X28, offsetof(A32JitState, cycles_remaining));
|
||||
code.SwitchMxcsrOnEntry();
|
||||
code.SwitchFpscrOnEntry();
|
||||
}
|
||||
|
||||
void A32EmitA64::EmitA32ExceptionRaised(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
@ -1243,7 +1239,7 @@ void A32EmitA64::EmitTerminalImpl(IR::Term::Interpret terminal, IR::LocationDesc
|
||||
code.MOVI2R(DecodeReg(code.ABI_PARAM2), A32::LocationDescriptor{terminal.next}.PC());
|
||||
code.MOVI2R(DecodeReg(code.ABI_PARAM3), terminal.num_instructions);
|
||||
code.STR(INDEX_UNSIGNED,DecodeReg(code.ABI_PARAM2), X28, MJitStateReg(A32::Reg::PC));
|
||||
code.SwitchMxcsrOnExit();
|
||||
code.SwitchFpscrOnExit();
|
||||
Devirtualize<&A32::UserCallbacks::InterpreterFallback>(config.callbacks).EmitCall(code);
|
||||
code.ReturnFromRunCode(true); // TODO: Check cycles
|
||||
}
|
||||
|
@ -134,22 +134,22 @@ void BlockOfCode::RunCodeFrom(void* jit_state, CodePtr code_ptr) const {
|
||||
run_code_from(jit_state, code_ptr);
|
||||
}
|
||||
|
||||
void BlockOfCode::ReturnFromRunCode(bool mxcsr_already_exited) {
|
||||
void BlockOfCode::ReturnFromRunCode(bool fpscr_already_exited) {
|
||||
size_t index = 0;
|
||||
if (mxcsr_already_exited)
|
||||
index |= MXCSR_ALREADY_EXITED;
|
||||
if (fpscr_already_exited)
|
||||
index |= FPSCR_ALREADY_EXITED;
|
||||
B(return_from_run_code[index]);
|
||||
}
|
||||
|
||||
void BlockOfCode::ForceReturnFromRunCode(bool mxcsr_already_exited) {
|
||||
void BlockOfCode::ForceReturnFromRunCode(bool fpscr_already_exited) {
|
||||
size_t index = FORCE_RETURN;
|
||||
if (mxcsr_already_exited)
|
||||
index |= MXCSR_ALREADY_EXITED; //TODO: refactor to fpcr
|
||||
if (fpscr_already_exited)
|
||||
index |= FPSCR_ALREADY_EXITED;
|
||||
B(return_from_run_code[index]);
|
||||
}
|
||||
|
||||
void BlockOfCode::GenRunCode() {
|
||||
const u8* loop, *enter_mxcsr_then_loop;
|
||||
const u8* loop, *enter_fpscr_then_loop;
|
||||
|
||||
run_code_from = (RunCodeFromFuncType) const_cast<u8*>(AlignCode16());
|
||||
|
||||
@ -163,7 +163,7 @@ void BlockOfCode::GenRunCode() {
|
||||
STR(Arm64Gen::INDEX_UNSIGNED, ABI_RETURN, Arm64Gen::X28, jsi.offsetof_cycles_to_run);
|
||||
STR(Arm64Gen::INDEX_UNSIGNED, ABI_RETURN, Arm64Gen::X28, jsi.offsetof_cycles_remaining);
|
||||
|
||||
SwitchMxcsrOnEntry();
|
||||
SwitchFpscrOnEntry();
|
||||
BR(Arm64Gen::X27);
|
||||
|
||||
run_code = (RunCodeFuncType) const_cast<u8*>(AlignCode16());
|
||||
@ -180,23 +180,23 @@ void BlockOfCode::GenRunCode() {
|
||||
STR(Arm64Gen::INDEX_UNSIGNED, ABI_RETURN, Arm64Gen::X28, jsi.offsetof_cycles_to_run);
|
||||
STR(Arm64Gen::INDEX_UNSIGNED, ABI_RETURN, Arm64Gen::X28, jsi.offsetof_cycles_remaining);
|
||||
|
||||
enter_mxcsr_then_loop = GetCodePtr();
|
||||
SwitchMxcsrOnEntry();
|
||||
enter_fpscr_then_loop = GetCodePtr();
|
||||
SwitchFpscrOnEntry();
|
||||
loop = GetCodePtr();
|
||||
|
||||
cb.LookupBlock->EmitCall(*this);
|
||||
BR(ABI_RETURN);
|
||||
|
||||
// Return from run code variants
|
||||
const auto emit_return_from_run_code = [this, &loop, &enter_mxcsr_then_loop](bool mxcsr_already_exited, bool force_return){
|
||||
const auto emit_return_from_run_code = [this, &loop, &enter_fpscr_then_loop](bool fpscr_already_exited, bool force_return){
|
||||
if (!force_return) {
|
||||
LDR(Arm64Gen::INDEX_UNSIGNED, ABI_SCRATCH1, Arm64Gen::X28, jsi.offsetof_cycles_remaining);
|
||||
CMP(ABI_SCRATCH1, Arm64Gen::ZR);
|
||||
B(CC_GT, mxcsr_already_exited ? enter_mxcsr_then_loop : loop);
|
||||
B(CC_GT, fpscr_already_exited ? enter_fpscr_then_loop : loop);
|
||||
}
|
||||
|
||||
if (!mxcsr_already_exited) {
|
||||
SwitchMxcsrOnExit();
|
||||
if (!fpscr_already_exited) {
|
||||
SwitchFpscrOnExit();
|
||||
}
|
||||
|
||||
cb.AddTicks->EmitCall(*this, [this](RegList param) {
|
||||
@ -212,19 +212,19 @@ void BlockOfCode::GenRunCode() {
|
||||
return_from_run_code[0] = AlignCode16();
|
||||
emit_return_from_run_code(false, false);
|
||||
|
||||
return_from_run_code[MXCSR_ALREADY_EXITED] = AlignCode16();
|
||||
return_from_run_code[FPSCR_ALREADY_EXITED] = AlignCode16();
|
||||
emit_return_from_run_code(true, false);
|
||||
|
||||
return_from_run_code[FORCE_RETURN] = AlignCode16();
|
||||
emit_return_from_run_code(false, true);
|
||||
|
||||
return_from_run_code[MXCSR_ALREADY_EXITED | FORCE_RETURN] = AlignCode16();
|
||||
return_from_run_code[FPSCR_ALREADY_EXITED | FORCE_RETURN] = AlignCode16();
|
||||
emit_return_from_run_code(true, true);
|
||||
|
||||
PerfMapRegister(run_code_from, GetCodePtr(), "dynarmic_dispatcher");
|
||||
}
|
||||
|
||||
void BlockOfCode::SwitchMxcsrOnEntry() {
|
||||
void BlockOfCode::SwitchFpscrOnEntry() {
|
||||
MRS(ABI_SCRATCH1, Arm64Gen::FIELD_FPCR);
|
||||
STR(Arm64Gen::INDEX_UNSIGNED, ABI_SCRATCH1, Arm64Gen::X28, jsi.offsetof_save_host_FPCR);
|
||||
|
||||
@ -234,7 +234,7 @@ void BlockOfCode::SwitchMxcsrOnEntry() {
|
||||
_MSR(Arm64Gen::FIELD_FPSR, ABI_SCRATCH1);
|
||||
}
|
||||
|
||||
void BlockOfCode::SwitchMxcsrOnExit() {
|
||||
void BlockOfCode::SwitchFpscrOnExit() {
|
||||
MRS(ABI_SCRATCH1, Arm64Gen::FIELD_FPCR);
|
||||
STR(Arm64Gen::INDEX_UNSIGNED, ABI_SCRATCH1, Arm64Gen::X28, jsi.offsetof_guest_FPCR);
|
||||
MRS(ABI_SCRATCH1, Arm64Gen::FIELD_FPSR);
|
||||
|
@ -48,13 +48,13 @@ public:
|
||||
/// Runs emulated code from code_ptr.
|
||||
void RunCodeFrom(void* jit_state, CodePtr code_ptr) const;
|
||||
/// Code emitter: Returns to dispatcher
|
||||
void ReturnFromRunCode(bool mxcsr_already_exited = false);
|
||||
void ReturnFromRunCode(bool fpscr_already_exited = false);
|
||||
/// Code emitter: Returns to dispatcher, forces return to host
|
||||
void ForceReturnFromRunCode(bool mxcsr_already_exited = false);
|
||||
/// Code emitter: Makes guest MXCSR the current MXCSR
|
||||
void SwitchMxcsrOnEntry();
|
||||
/// Code emitter: Makes saved host MXCSR the current MXCSR
|
||||
void SwitchMxcsrOnExit();
|
||||
void ForceReturnFromRunCode(bool fpscr_already_exited = false);
|
||||
/// Code emitter: Makes guest FPSR and FPCR the current FPSR and FPCR
|
||||
void SwitchFpscrOnEntry();
|
||||
/// Code emitter: Makes saved host FPCR the current FPCR
|
||||
void SwitchFpscrOnExit();
|
||||
/// Code emitter: Updates cycles remaining my calling cb.AddTicks and cb.GetTicksRemaining
|
||||
/// @note this clobbers ABI caller-save registers
|
||||
void UpdateTicks();
|
||||
@ -132,7 +132,7 @@ private:
|
||||
using RunCodeFromFuncType = void(*)(void*, CodePtr);
|
||||
RunCodeFuncType run_code = nullptr;
|
||||
RunCodeFromFuncType run_code_from = nullptr;
|
||||
static constexpr size_t MXCSR_ALREADY_EXITED = 1 << 0;
|
||||
static constexpr size_t FPSCR_ALREADY_EXITED = 1 << 0;
|
||||
static constexpr size_t FORCE_RETURN = 1 << 1;
|
||||
std::array<const void*, 4> return_from_run_code;
|
||||
void GenRunCode();
|
||||
|
Loading…
x
Reference in New Issue
Block a user