backend/A64: Port a32_jitstate
This commit is contained in:
parent
1a2cd53847
commit
f9da068670
169
src/backend/A64/a32_jitstate.cpp
Normal file
169
src/backend/A64/a32_jitstate.cpp
Normal file
@ -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<u64>(Reg[15]) << 32);
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::BackendX64
|
86
src/backend/A64/a32_jitstate.h
Normal file
86
src/backend/A64/a32_jitstate.h
Normal file
@ -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 <array>
|
||||
|
||||
#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<u32, 16> 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<u32, 64> ExtReg{}; // Extension registers.
|
||||
|
||||
static constexpr size_t SpillCount = 64;
|
||||
std::array<u64, SpillCount> Spill{}; // Spill.
|
||||
static size_t GetSpillLocationOffsetFromIndex(size_t i) {
|
||||
return static_cast<u64>(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<u64, RSBSize> rsb_location_descriptors;
|
||||
std::array<u64, RSBSize> 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
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user