From 5f8eb7c51c604b1cae50e03803da8ee65d788b21 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Mon, 6 May 2019 00:18:13 +0100 Subject: [PATCH] A32/location_descriptor: Add CPSR.IT to A32::LocationDescriptor --- src/backend/x64/a32_emit_x64.cpp | 2 +- src/backend/x64/a32_jitstate.cpp | 41 +++++++++++++++----------- src/backend/x64/a32_jitstate.h | 7 +++-- src/frontend/A32/location_descriptor.h | 15 ++++++++-- 4 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/backend/x64/a32_emit_x64.cpp b/src/backend/x64/a32_emit_x64.cpp index a9871870..43fc30a4 100644 --- a/src/backend/x64/a32_emit_x64.cpp +++ b/src/backend/x64/a32_emit_x64.cpp @@ -222,7 +222,7 @@ void A32EmitX64::GenTerminalHandlers() { // This calculation has to match up with IREmitter::PushRSB constexpr size_t offsetof_pc = offsetof(A32JitState, Reg) + 15 * sizeof(u32); static_assert(offsetof_pc + 4 == offsetof(A32JitState, cpsr_et)); - static_assert(offsetof_pc + 5 == offsetof(A32JitState, padding)); + static_assert(offsetof_pc + 5 == offsetof(A32JitState, cpsr_it)); static_assert(offsetof_pc + 6 == offsetof(A32JitState, fpcr_mode)); code.mov(rbx, qword[r15 + offsetof_pc]); }; diff --git a/src/backend/x64/a32_jitstate.cpp b/src/backend/x64/a32_jitstate.cpp index cb469424..2676cbc8 100644 --- a/src/backend/x64/a32_jitstate.cpp +++ b/src/backend/x64/a32_jitstate.cpp @@ -19,19 +19,21 @@ namespace Dynarmic::BackendX64 { * * ARM CPSR flags * -------------- - * N bit 31 Negative flag - * Z bit 30 Zero flag - * C bit 29 Carry flag - * V bit 28 oVerflow flag - * Q bit 27 Saturation flag - * J bit 24 Jazelle instruction set flag - * GE bits 16-19 Greater than or Equal flags - * E bit 9 Data Endianness flag - * A bit 8 Disable imprecise Aborts - * I bit 7 Disable IRQ interrupts - * F bit 6 Disable FIQ interrupts - * T bit 5 Thumb instruction set flag - * M bits 0-4 Processor Mode bits + * N bit 31 Negative flag + * Z bit 30 Zero flag + * C bit 29 Carry flag + * V bit 28 oVerflow flag + * Q bit 27 Saturation flag + * IT[1:0] bits 25-26 If-Then execution state (lower 2 bits) + * J bit 24 Jazelle instruction set flag + * GE bits 16-19 Greater than or Equal flags + * IT[7:2] bits 10-15 If-Then execution state (upper 6 bits) + * E bit 9 Data Endianness flag + * A bit 8 Disable imprecise Aborts + * I bit 7 Disable IRQ interrupts + * F bit 6 Disable FIQ interrupts + * T bit 5 Thumb instruction set flag + * M bits 0-4 Processor Mode bits * * x64 LAHF+SETO flags * ------------------- @@ -62,6 +64,9 @@ u32 A32JitState::Cpsr() const { cpsr |= Common::Bit<7>(cpsr_ge) ? 1 << 16 : 0; // E flag, T flag cpsr |= static_cast(cpsr_et) << 5; + // IT state + cpsr |= static_cast(cpsr_it & 0b11111100) << 8; + cpsr |= static_cast(cpsr_it & 0b00000011) << 25; // Other flags cpsr |= cpsr_jaifm; @@ -81,8 +86,12 @@ void A32JitState::SetCpsr(u32 cpsr) { cpsr_ge |= Common::Bit<16>(cpsr) ? 0x000000FF : 0; // E flag, T flag cpsr_et = static_cast((cpsr >> 5) & 0x11); + // IT state + cpsr_it = 0; + cpsr_it |= static_cast((cpsr >> 8) & 0b11111100); + cpsr_it |= static_cast((cpsr >> 25) & 0b00000011); // Other flags - cpsr_jaifm = cpsr & 0x07F0FDDF; + cpsr_jaifm = cpsr & 0x010001DF; } void A32JitState::ResetRSB() { @@ -186,8 +195,4 @@ void A32JitState::SetFpscr(u32 FPSCR) { } } -u64 A32JitState::GetUniqueHash() const noexcept { - return (static_cast(cpsr_et) << 32) | (static_cast(fpcr_mode) << 48) | Reg[15]; -} - } // namespace Dynarmic::BackendX64 diff --git a/src/backend/x64/a32_jitstate.h b/src/backend/x64/a32_jitstate.h index 732bdccc..f59e8831 100644 --- a/src/backend/x64/a32_jitstate.h +++ b/src/backend/x64/a32_jitstate.h @@ -31,9 +31,12 @@ struct A32JitState { // Location Descriptor related (the order of fields is important) u8 cpsr_et = 0; ///< Format: 000E000T - u8 padding = 0; + u8 cpsr_it = 0; ///< Format: ccccmmmm u16 fpcr_mode = 0; ///< Top 16 bits of FPCR - u64 GetUniqueHash() const noexcept; + u64 GetUniqueHash() const noexcept { + const u64 upper_half = u64(cpsr_et) | (u64(cpsr_it) << 8) | (u64(fpcr_mode) << 16); + return (upper_half << 32) | Reg[15]; + } // CPSR fields u32 cpsr_ge = 0; diff --git a/src/frontend/A32/location_descriptor.h b/src/frontend/A32/location_descriptor.h index 842e44bd..d484638d 100644 --- a/src/frontend/A32/location_descriptor.h +++ b/src/frontend/A32/location_descriptor.h @@ -12,6 +12,7 @@ #include "common/common_types.h" #include "frontend/A32/FPSCR.h" #include "frontend/A32/PSR.h" +#include "frontend/A32/ITState.h" #include "frontend/ir/location_descriptor.h" namespace Dynarmic::A32 { @@ -25,7 +26,7 @@ namespace Dynarmic::A32 { class LocationDescriptor { public: // Indicates bits that should be preserved within descriptors. - static constexpr u32 CPSR_MODE_MASK = 0x00000220; + static constexpr u32 CPSR_MODE_MASK = 0x0600FE20; static constexpr u32 FPSCR_MODE_MASK = 0x07F70000; LocationDescriptor(u32 arm_pc, PSR cpsr, FPSCR fpscr) @@ -35,12 +36,14 @@ public: arm_pc = static_cast(o.Value()); cpsr.T(o.Value() & (u64(0x01) << 32)); cpsr.E(o.Value() & (u64(0x10) << 32)); + cpsr.IT(ITState{static_cast(o.Value() >> 40)}); fpscr = static_cast(o.Value() >> 32) & FPSCR_MODE_MASK; } u32 PC() const { return arm_pc; } bool TFlag() const { return cpsr.T(); } bool EFlag() const { return cpsr.E(); } + ITState IT() const { return cpsr.IT(); } A32::PSR CPSR() const { return cpsr; } A32::FPSCR FPSCR() const { return fpscr; } @@ -79,14 +82,22 @@ public: return LocationDescriptor(arm_pc, cpsr, A32::FPSCR{new_fpscr & FPSCR_MODE_MASK}); } + LocationDescriptor AdvanceIT() const { + PSR new_cpsr = cpsr; + new_cpsr.IT(new_cpsr.IT().Advance()); + + return LocationDescriptor(arm_pc, new_cpsr, fpscr); + } + u64 UniqueHash() const noexcept { // This value MUST BE UNIQUE. // This calculation has to match up with EmitX64::EmitTerminalPopRSBHint const u64 pc_u64 = u64(arm_pc); const u64 fpscr_u64 = u64(fpscr.Value()) << 32; + const u64 it_u64 = u64(cpsr.IT().Value()) << 40; const u64 t_u64 = cpsr.T() ? u64(0x01) << 32 : 0; const u64 e_u64 = cpsr.E() ? u64(0x10) << 32 : 0; - return pc_u64 | fpscr_u64 | t_u64 | e_u64; + return pc_u64 | fpscr_u64 | it_u64 | t_u64 | e_u64; } operator IR::LocationDescriptor() const {