diff --git a/src/backend/A64/a32_jitstate.cpp b/src/backend/A64/a32_jitstate.cpp new file mode 100644 index 00000000..b3dad84d --- /dev/null +++ b/src/backend/A64/a32_jitstate.cpp @@ -0,0 +1,169 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#include "backend/A64/a32_jitstate.h" +#include "backend/A64/block_of_code.h" +#include "common/assert.h" +#include "common/bit_util.h" +#include "common/common_types.h" +#include "frontend/A32/location_descriptor.h" + +namespace Dynarmic::BackendA64 { + +/** + * CPSR Bits + * ========= + * + * 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 + * + * A64 flags + * ------------------- + * N bit 31 Negative flag + * Z bit 30 Zero flag + * C bit 29 Carry flag + * V bit 28 oVerflow flag + */ + +u32 A32JitState::Cpsr() const { + ASSERT((CPSR_nzcv & ~0xF0000000) == 0); + ASSERT((CPSR_q & ~1) == 0); + ASSERT((CPSR_et & ~3) == 0); + ASSERT((CPSR_jaifm & ~0x010001DF) == 0); + + u32 cpsr = 0; + + // NZCV flags + cpsr |= CPSR_nzcv; + // Q flag + cpsr |= CPSR_q ? 1 << 27 : 0; + // GE flags + cpsr |= Common::Bit<31>(CPSR_ge) ? 1 << 19 : 0; + cpsr |= Common::Bit<23>(CPSR_ge) ? 1 << 18 : 0; + cpsr |= Common::Bit<15>(CPSR_ge) ? 1 << 17 : 0; + cpsr |= Common::Bit<7>(CPSR_ge) ? 1 << 16 : 0; + // E flag, T flag + cpsr |= Common::Bit<1>(CPSR_et) ? 1 << 9 : 0; + cpsr |= Common::Bit<0>(CPSR_et) ? 1 << 5 : 0; + // Other flags + cpsr |= CPSR_jaifm; + + return cpsr; +} + +void A32JitState::SetCpsr(u32 cpsr) { + // NZCV flags + CPSR_nzcv = cpsr & 0xF0000000; + // Q flag + CPSR_q = Common::Bit<27>(cpsr) ? 1 : 0; + // GE flags + CPSR_ge = 0; + CPSR_ge |= Common::Bit<19>(cpsr) ? 0xFF000000 : 0; + CPSR_ge |= Common::Bit<18>(cpsr) ? 0x00FF0000 : 0; + CPSR_ge |= Common::Bit<17>(cpsr) ? 0x0000FF00 : 0; + CPSR_ge |= Common::Bit<16>(cpsr) ? 0x000000FF : 0; + // E flag, T flag + CPSR_et = 0; + CPSR_et |= Common::Bit<9>(cpsr) ? 2 : 0; + CPSR_et |= Common::Bit<5>(cpsr) ? 1 : 0; + // Other flags + CPSR_jaifm = cpsr & 0x07F0FDDF; +} + +void A32JitState::ResetRSB() { + rsb_location_descriptors.fill(0xFFFFFFFFFFFFFFFFull); + rsb_codeptrs.fill(0); +} + +/** + * FPSCR + * ========================= + * + * VFP FPSCR cumulative exception bits + * ----------------------------------- + * IDC bit 7 Input Denormal cumulative exception bit // Only ever set when FPSCR.FTZ = 1 + * IXC bit 4 Inexact cumulative exception bit + * UFC bit 3 Underflow cumulative exception bit + * OFC bit 2 Overflow cumulative exception bit + * DZC bit 1 Division by Zero cumulative exception bit + * IOC bit 0 Invalid Operation cumulative exception bit + * + * VFP FPSCR exception trap enables + * -------------------------------- + * IDE bit 15 Input Denormal exception trap enable + * IXE bit 12 Inexact exception trap enable + * UFE bit 11 Underflow exception trap enable + * OFE bit 10 Overflow exception trap enable + * DZE bit 9 Division by Zero exception trap enable + * IOE bit 8 Invalid Operation exception trap enable + * + * VFP FPSCR mode bits + * ------------------- + * DN bit 25 Default NaN + * FZ bit 24 Flush to Zero + * RMode bits 22-23 Round to {0 = Nearest, 1 = Positive, 2 = Negative, 3 = Zero} + * Stride bits 20-21 Vector stride + * Len bits 16-18 Vector length + */ + +// NZCV; QC (ASMID only), AHP; DN, FZ, RMode, Stride; SBZP; Len; trap enables; cumulative bits +constexpr u32 FPSCR_MODE_MASK = A32::LocationDescriptor::FPSCR_MODE_MASK; +constexpr u32 FPSCR_NZCV_MASK = 0xF0000000; + +u32 A32JitState::Fpscr() const { + ASSERT((FPSCR_mode & ~FPSCR_MODE_MASK) == 0); + ASSERT((FPSCR_nzcv & ~FPSCR_NZCV_MASK) == 0); + ASSERT((FPSCR_IDC & ~(1 << 7)) == 0); + ASSERT((FPSCR_UFC & ~(1 << 3)) == 0); + + u32 FPSCR = FPSCR_mode | FPSCR_nzcv; + FPSCR |= (guest_FPSR & 0x1F); + FPSCR |= FPSCR_IDC; + FPSCR |= FPSCR_UFC; + FPSCR |= fpsr_exc; + + return FPSCR; +} + +void A32JitState::SetFpscr(u32 FPSCR) { + old_FPSCR = FPSCR; + FPSCR_mode = FPSCR & FPSCR_MODE_MASK; + FPSCR_nzcv = FPSCR & FPSCR_NZCV_MASK; + guest_FPCR = 0; + + // RMode + guest_FPCR |= FPSCR & 0xC00000; + + // Cumulative flags IDC, IOC, IXC, UFC, OFC, DZC + FPSCR_IDC = 0; + FPSCR_UFC = 0; + fpsr_exc = FPSCR & 0x9F; + + if (Common::Bit<24>(FPSCR)) { + // VFP Flush to Zero + //guest_MXCSR |= (1 << 15); // SSE Flush to Zero + //guest_MXCSR |= (1 << 6); // SSE Denormals are Zero + } +} + +u64 A32JitState::GetUniqueHash() const { + return CPSR_et | FPSCR_mode | (static_cast(Reg[15]) << 32); +} + +} // namespace Dynarmic::BackendX64 diff --git a/src/backend/A64/a32_jitstate.h b/src/backend/A64/a32_jitstate.h new file mode 100644 index 00000000..0af16273 --- /dev/null +++ b/src/backend/A64/a32_jitstate.h @@ -0,0 +1,86 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#pragma once + +#include + +#include "common/common_types.h" + +namespace Dynarmic::BackendA64 { + +class BlockOfCode; + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4324) // Structure was padded due to alignment specifier +#endif + +struct A32JitState { + using ProgramCounterType = u32; + + A32JitState() { ResetRSB(); } + + std::array Reg{}; // Current register file. + // TODO: Mode-specific register sets unimplemented. + + u32 CPSR_et = 0; + u32 CPSR_ge = 0; + u32 CPSR_q = 0; + u32 CPSR_nzcv = 0; + u32 CPSR_jaifm = 0; + + u32 Cpsr() const; + void SetCpsr(u32 cpsr); + + alignas(u64) std::array ExtReg{}; // Extension registers. + + static constexpr size_t SpillCount = 64; + std::array Spill{}; // Spill. + static size_t GetSpillLocationOffsetFromIndex(size_t i) { + return static_cast(offsetof(A32JitState, Spill) + i * sizeof(u64)); + } + + // For internal use (See: BlockOfCode::RunCode) + u64 guest_FPCR = 0; + u64 guest_FPSR = 0; + u64 save_host_FPCR = 0; + s64 cycles_to_run = 0; + s64 cycles_remaining = 0; + bool halt_requested = false; + + // Exclusive state + static constexpr u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8; + u32 exclusive_state = 0; + u32 exclusive_address = 0; + + static constexpr size_t RSBSize = 8; // MUST be a power of 2. + static constexpr size_t RSBPtrMask = RSBSize - 1; + u32 rsb_ptr = 0; + std::array rsb_location_descriptors; + std::array rsb_codeptrs; + void ResetRSB(); + + u32 fpsr_exc = 0; + u32 fpsr_qc = 0; // Dummy value + u32 FPSCR_IDC = 0; + u32 FPSCR_UFC = 0; + u32 FPSCR_mode = 0; + u32 FPSCR_nzcv = 0; + u32 old_FPSCR = 0; + u32 Fpscr() const; + void SetFpscr(u32 FPSCR); + + u64 GetUniqueHash() const; +}; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +using CodePtr = const void*; + +} // namespace Dynarmic::BackendA64 diff --git a/src/backend/A64/jitstate_info.h b/src/backend/A64/jitstate_info.h index f1e192f9..0221a073 100644 --- a/src/backend/A64/jitstate_info.h +++ b/src/backend/A64/jitstate_info.h @@ -17,8 +17,9 @@ struct JitStateInfo { JitStateInfo(const JitStateType&) : offsetof_cycles_remaining(offsetof(JitStateType, cycles_remaining)) , offsetof_cycles_to_run(offsetof(JitStateType, cycles_to_run)) - , offsetof_save_host_MXCSR(offsetof(JitStateType, save_host_MXCSR)) - , offsetof_guest_MXCSR(offsetof(JitStateType, guest_MXCSR)) + , offsetof_save_host_FPCR(offsetof(JitStateType, save_host_FPCR)) + , offsetof_guest_FPCR(offsetof(JitStateType, guest_FPCR)) + , offsetof_guest_FPSR(offsetof(JitStateType, guest_FPSR)) , offsetof_rsb_ptr(offsetof(JitStateType, rsb_ptr)) , rsb_ptr_mask(JitStateType::RSBPtrMask) , offsetof_rsb_location_descriptors(offsetof(JitStateType, rsb_location_descriptors)) @@ -32,8 +33,9 @@ struct JitStateInfo { const size_t offsetof_cycles_remaining; const size_t offsetof_cycles_to_run; - const size_t offsetof_save_host_MXCSR; - const size_t offsetof_guest_MXCSR; + const size_t offsetof_save_host_FPCR; + const size_t offsetof_guest_FPCR; + const size_t offsetof_guest_FPSR; const size_t offsetof_rsb_ptr; const size_t rsb_ptr_mask; const size_t offsetof_rsb_location_descriptors;