dynarmic/src/backend/x64/a32_jitstate.cpp
Lioncash 7bb5440507 general: Mark hash functions as noexcept
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.
2020-04-22 21:01:43 +01:00

203 lines
6.3 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/a32_jitstate.h"
#include "backend/x64/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::BackendX64 {
/**
* 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
*
* x64 LAHF+SETO flags
* -------------------
* SF bit 15 Sign flag
* ZF bit 14 Zero flag
* AF bit 12 Auxiliary flag
* PF bit 10 Parity flag
* CF bit 8 Carry flag
* OF bit 0 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);
}
/**
* Comparing MXCSR and FPSCR
* =========================
*
* 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
*
* 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
*
* 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
*
* 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
*
* 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}
*
* 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_MXCSR & 0b0000000000001); // IOC = IE
FPSCR |= (guest_MXCSR & 0b0000000111100) >> 1; // IXC, UFC, OFC, DZC = PE, UE, OE, ZE
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_MXCSR = 0;
// Exception masks / enables
guest_MXCSR |= 0x00001f80; // mask all
//guest_MXCSR |= (~FPSCR >> 1) & 0b0000010000000; // IM = ~IOE
//guest_MXCSR |= (~FPSCR >> 7) & 0b0000100000000; // DM = ~IDE
//guest_MXCSR |= (~FPSCR ) & 0b1111000000000; // PM, UM, OM, ZM = ~IXE, ~UFE, ~OFE, ~DZE
// RMode
const std::array<u32, 4> MXCSR_RMode {0x0, 0x4000, 0x2000, 0x6000};
guest_MXCSR |= MXCSR_RMode[(FPSCR >> 22) & 0x3];
// 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 noexcept {
return CPSR_et | FPSCR_mode | (static_cast<u64>(Reg[15]) << 32);
}
} // namespace Dynarmic::BackendX64