/* 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 * ------------------- * AHP bit 26 Alternate 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} * 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((fpcr_mode & ~FPSCR_MODE_MASK) == 0); ASSERT((fpsr_nzcv & ~FPSCR_NZCV_MASK) == 0); u32 FPSCR = fpcr_mode | fpsr_nzcv; FPSCR |= (guest_MXCSR & 0b0000000000001); // IOC = IE FPSCR |= (guest_MXCSR & 0b0000000111100) >> 1; // IXC, UFC, OFC, DZC = PE, UE, OE, ZE FPSCR |= fpsr_exc; return FPSCR; } void A32JitState::SetFpscr(u32 FPSCR) { fpcr_mode = FPSCR & FPSCR_MODE_MASK; fpsr_nzcv = FPSCR & FPSCR_NZCV_MASK; guest_MXCSR = 0; // Exception masks / enables guest_MXCSR |= 0x00001f80; // mask all // RMode const std::array MXCSR_RMode {0x0, 0x4000, 0x2000, 0x6000}; guest_MXCSR |= MXCSR_RMode[(FPSCR >> 22) & 0x3]; // Cumulative flags IDC, IOC, IXC, UFC, OFC, DZC 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 | fpcr_mode | (static_cast(Reg[15]) << 32); } } // namespace Dynarmic::BackendX64