emit_arm64_a64: Take into account currently loaded FPSR
Previously we just retrieved the last stored FPSR and used that when the guest asks for the current FPSR. This is incorrect behaviour. We failed to take into account the current state of the host FPSR. Here we take this into account. This bug was discovered via #795.
This commit is contained in:
parent
ba8192d890
commit
4ae4750b5a
3 changed files with 15 additions and 2 deletions
|
@ -10,6 +10,7 @@
|
|||
#include "dynarmic/backend/arm64/abi.h"
|
||||
#include "dynarmic/backend/arm64/emit_arm64.h"
|
||||
#include "dynarmic/backend/arm64/emit_context.h"
|
||||
#include "dynarmic/backend/arm64/fpsr_manager.h"
|
||||
#include "dynarmic/backend/arm64/reg_alloc.h"
|
||||
#include "dynarmic/interface/halt_reason.h"
|
||||
#include "dynarmic/ir/basic_block.h"
|
||||
|
@ -277,11 +278,11 @@ void EmitIR<IR::Opcode::A64GetFPCR>(oaknut::CodeGenerator& code, EmitContext& ct
|
|||
}
|
||||
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::A64GetFPSR>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
void EmitIR<IR::Opcode::A64GetFPSR>(oaknut::CodeGenerator&, EmitContext& ctx, IR::Inst* inst) {
|
||||
auto Wresult = ctx.reg_alloc.WriteW(inst);
|
||||
RegAlloc::Realize(Wresult);
|
||||
|
||||
code.LDR(Wresult, Xstate, offsetof(A64JitState, fpsr));
|
||||
ctx.fpsr.GetFpsr(Wresult);
|
||||
}
|
||||
|
||||
template<>
|
||||
|
|
|
@ -37,4 +37,13 @@ void FpsrManager::Load() {
|
|||
fpsr_loaded = true;
|
||||
}
|
||||
|
||||
void FpsrManager::GetFpsr(oaknut::WReg dest) {
|
||||
code.LDR(dest, Xstate, state_fpsr_offset);
|
||||
|
||||
if (fpsr_loaded) {
|
||||
code.MRS(Xscratch1, oaknut::SystemReg::FPSR);
|
||||
code.ORR(dest, dest, Wscratch1);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::Backend::Arm64
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
namespace oaknut {
|
||||
struct CodeGenerator;
|
||||
struct WReg;
|
||||
} // namespace oaknut
|
||||
|
||||
namespace Dynarmic::Backend::Arm64 {
|
||||
|
@ -21,6 +22,8 @@ public:
|
|||
void Load();
|
||||
void Overwrite() { fpsr_loaded = false; }
|
||||
|
||||
void GetFpsr(oaknut::WReg);
|
||||
|
||||
private:
|
||||
oaknut::CodeGenerator& code;
|
||||
size_t state_fpsr_offset;
|
||||
|
|
Loading…
Reference in a new issue