mirror of
https://github.com/yuzu-mirror/dynarmic.git
synced 2026-01-30 11:54:19 +01:00
Generally hash functions shouldn't throw exceptions. It's also a requirement for the standard library-provided hash functions to not throw exceptions. An exception to this rule is made for user-defined specializations, however we can just be consistent with the standard library on this to allow it to play nicer with it. While we're at it, we can also make the std::less specializations noexcpet as well, since they also can't throw.
122 lines
3.7 KiB
C++
122 lines
3.7 KiB
C++
/* 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/x64/a64_jitstate.h"
|
|
#include "common/bit_util.h"
|
|
#include "frontend/A64/location_descriptor.h"
|
|
|
|
namespace Dynarmic::BackendX64 {
|
|
|
|
u64 A64JitState::GetUniqueHash() const noexcept {
|
|
const u64 fpcr_u64 = static_cast<u64>(fpcr & A64::LocationDescriptor::FPCR_MASK) << 37;
|
|
const u64 pc_u64 = pc & A64::LocationDescriptor::PC_MASK;
|
|
return pc_u64 | fpcr_u64;
|
|
}
|
|
|
|
/**
|
|
* Comparing MXCSR and FPCR
|
|
* ========================
|
|
*
|
|
* SSE MSCSR exception masks
|
|
* -------------------------
|
|
* PM bit 12 Precision Mask
|
|
* UM bit 11 Underflow Mask
|
|
* OM bit 10 Overflow Mask
|
|
* ZM bit 9 Divide By Zero Mask
|
|
* DM bit 8 Denormal Mask
|
|
* IM bit 7 Invalid Operation Mask
|
|
*
|
|
* A64 FPCR 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
|
|
*
|
|
* SSE MXCSR mode bits
|
|
* -------------------
|
|
* FZ bit 15 Flush To Zero
|
|
* DAZ bit 6 Denormals Are Zero
|
|
* RN bits 13-14 Round to {0 = Nearest, 1 = Negative, 2 = Positive, 3 = Zero}
|
|
*
|
|
* A64 FPCR mode bits
|
|
* ------------------
|
|
* AHP bit 26 Alternative half-precision
|
|
* 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}
|
|
* FZ16 bit 19 Flush to Zero for half-precision
|
|
*/
|
|
|
|
constexpr u32 FPCR_MASK = 0x07C89F00;
|
|
|
|
u32 A64JitState::GetFpcr() const {
|
|
return fpcr;
|
|
}
|
|
|
|
void A64JitState::SetFpcr(u32 value) {
|
|
fpcr = value & FPCR_MASK;
|
|
|
|
guest_MXCSR &= 0x0000003D;
|
|
guest_MXCSR |= 0x00001f80; // Mask all exceptions
|
|
|
|
// RMode
|
|
const std::array<u32, 4> MXCSR_RMode {0x0, 0x4000, 0x2000, 0x6000};
|
|
guest_MXCSR |= MXCSR_RMode[(value >> 22) & 0x3];
|
|
|
|
if (Common::Bit<24>(value)) {
|
|
guest_MXCSR |= (1 << 15); // SSE Flush to Zero
|
|
guest_MXCSR |= (1 << 6); // SSE Denormals are Zero
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Comparing MXCSR and FPSR
|
|
* ========================
|
|
*
|
|
* SSE MXCSR exception flags
|
|
* -------------------------
|
|
* PE bit 5 Precision Flag
|
|
* UE bit 4 Underflow Flag
|
|
* OE bit 3 Overflow Flag
|
|
* ZE bit 2 Divide By Zero Flag
|
|
* DE bit 1 Denormal Flag // Appears to only be set when MXCSR.DAZ = 0
|
|
* IE bit 0 Invalid Operation Flag
|
|
*
|
|
* A64 FPSR cumulative exception bits
|
|
* ----------------------------------
|
|
* QC bit 27 Cumulative saturation bit
|
|
* IDC bit 7 Input Denormal cumulative exception bit // Only ever set when FPCR.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
|
|
*/
|
|
|
|
u32 A64JitState::GetFpsr() const {
|
|
u32 fpsr = 0;
|
|
fpsr |= (guest_MXCSR & 0b0000000000001); // IOC = IE
|
|
fpsr |= (guest_MXCSR & 0b0000000111100) >> 1; // IXC, UFC, OFC, DZC = PE, UE, OE, ZE
|
|
fpsr |= FPSCR_IDC;
|
|
fpsr |= FPSCR_UFC;
|
|
fpsr |= fpsr_exc;
|
|
fpsr |= (fpsr_qc == 0 ? 0 : 1) << 27;
|
|
return fpsr;
|
|
}
|
|
|
|
void A64JitState::SetFpsr(u32 value) {
|
|
guest_MXCSR &= ~0x0000003D;
|
|
FPSCR_IDC = 0;
|
|
FPSCR_UFC = 0;
|
|
fpsr_qc = (value >> 27) & 1;
|
|
fpsr_exc = value & 0x9F;
|
|
}
|
|
|
|
} // namespace Dynarmic::BackendX64
|