/* 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; 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 MXCSR_RMode {0x0, 0x4000, 0x2000, 0x6000}; guest_MXCSR |= MXCSR_RMode[(FPSCR >> 22) & 0x3]; // Cumulative flags IOC, IXC, UFC, OFC, DZC guest_MXCSR |= ( FPSCR ) & 0b0000000000001; // IE = IOC guest_MXCSR |= ( FPSCR << 1) & 0b0000000111100; // PE, UE, OE, ZE = IXC, UFC, OFC, DZC // Cumulative flag IDC, UFC FPSCR_IDC = FPSCR & (1 << 7); FPSCR_UFC = FPSCR & (1 << 3); 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