backend/A64: refactor to fpscr from mxcsr

This commit is contained in:
SachinVin 2019-08-17 18:28:41 +05:30
parent 47c0632e16
commit bb39f419e2
3 changed files with 28 additions and 32 deletions

View File

@ -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
}

View File

@ -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);

View File

@ -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();