From 74633301c1f52824f5145ea77d772f714591aba9 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 5 May 2019 23:45:32 +0100 Subject: [PATCH] A32: Add ITState --- src/CMakeLists.txt | 1 + src/frontend/A32/ITState.h | 72 ++++++++++++++++++++++++++++++++++++++ src/frontend/A32/PSR.h | 14 ++++---- 3 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 src/frontend/A32/ITState.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6f652afb..bcfafa39 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -91,6 +91,7 @@ add_library(dynarmic frontend/A32/FPSCR.h frontend/A32/ir_emitter.cpp frontend/A32/ir_emitter.h + frontend/A32/ITState.h frontend/A32/location_descriptor.cpp frontend/A32/location_descriptor.h frontend/A32/PSR.h diff --git a/src/frontend/A32/ITState.h b/src/frontend/A32/ITState.h new file mode 100644 index 00000000..9ce8397f --- /dev/null +++ b/src/frontend/A32/ITState.h @@ -0,0 +1,72 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2019 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 "common/common_types.h" +#include "common/bit_util.h" +#include "frontend/ir/cond.h" + +namespace Dynarmic::A32 { + +class ITState final { +public: + ITState() = default; + explicit ITState(u8 data) : value(data) {} + + ITState& operator=(u8 data) { + value = data; + return *this; + } + + IR::Cond Cond() const { + return static_cast(Common::Bits<4, 7>(value)); + } + void Cond(IR::Cond cond) { + value = Common::ModifyBits<4, 7>(value, static_cast(cond)); + } + + u8 Mask() const { + return Common::Bits<0, 3>(value); + } + void Mask(u8 mask) { + value = Common::ModifyBits<0, 3>(value, mask); + } + + bool IsInITBlock() const { + return Mask() != 0b0000; + } + + bool IsLastInITBlock() const { + return Mask() == 0b1000; + } + + ITState Advance() const { + ITState result{*this}; + result.Mask(result.Mask() << 1); + if (result.Mask() == 0) { + return ITState{0}; + } + return result; + } + + u8 Value() const { + return value; + } + +private: + u8 value; +}; + +inline bool operator==(ITState lhs, ITState rhs) { + return lhs.Value() == rhs.Value(); +} + +inline bool operator!=(ITState lhs, ITState rhs) { + return !operator==(lhs, rhs); +} + +} // namespace Dynarmic::A32 diff --git a/src/frontend/A32/PSR.h b/src/frontend/A32/PSR.h index d70745e7..f83a09ac 100644 --- a/src/frontend/A32/PSR.h +++ b/src/frontend/A32/PSR.h @@ -8,6 +8,7 @@ #include "common/bit_util.h" #include "common/common_types.h" +#include "frontend/A32/ITState.h" namespace Dynarmic::A32 { @@ -35,8 +36,7 @@ namespace Dynarmic::A32 { class PSR final { public: /// Valid processor modes that may be indicated. - enum class Mode : u32 - { + enum class Mode : u32 { User = 0b10000, FIQ = 0b10001, IRQ = 0b10010, @@ -49,8 +49,7 @@ public: }; /// Instruction sets that may be signified through a PSR. - enum class InstructionSet - { + enum class InstructionSet { ARM, Jazelle, Thumb, @@ -114,10 +113,11 @@ public: value = (value & ~0xF0000) | (data & 0xF) << 16; } - u32 IT() const { - return (value & 0x6000000) >> 25 | (value & 0xFC00) >> 8; + ITState IT() const { + return ITState{static_cast((value & 0x6000000) >> 25 | (value & 0xFC00) >> 8)}; } - void IT(u32 data) { + void IT(ITState it_state) { + const u32 data = it_state.Value(); value = (value & ~0x000FC00) | (data & 0b11111100) << 8; value = (value & ~0x6000000) | (data & 0b00000011) << 25; }