67443efb62
Makes namespacing a little less noisy
223 lines
5.6 KiB
C++
223 lines
5.6 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.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "common/bit_util.h"
|
|
#include "common/common_types.h"
|
|
|
|
namespace Dynarmic::A32 {
|
|
|
|
/**
|
|
* Program Status Register
|
|
*
|
|
* | Bit(s) | Description |
|
|
* |:-------:|:----------------------------------------------|
|
|
* | N | Negative |
|
|
* | Z | Zero |
|
|
* | C | Carry |
|
|
* | V | Overflow |
|
|
* | Q | Sticky overflow for DSP-oriented instructions |
|
|
* | IT[1:0] | Lower two bits of the If-Then execution state |
|
|
* | J | Jazelle bit |
|
|
* | GE | Greater-than or Equal |
|
|
* | IT[7:2] | Upper six bits of the If-Then execution state |
|
|
* | E | Endian (0 is little endian, 1 is big endian) |
|
|
* | A | Imprecise data abort (disables them when set) |
|
|
* | I | IRQ interrupts (disabled when set) |
|
|
* | F | FIQ interrupts (disabled when set) |
|
|
* | T | Thumb bit |
|
|
* | M | Current processor mode |
|
|
*/
|
|
class PSR final {
|
|
public:
|
|
/// Valid processor modes that may be indicated.
|
|
enum class Mode : u32
|
|
{
|
|
User = 0b10000,
|
|
FIQ = 0b10001,
|
|
IRQ = 0b10010,
|
|
Supervisor = 0b10011,
|
|
Monitor = 0b10110,
|
|
Abort = 0b10111,
|
|
Hypervisor = 0b11010,
|
|
Undefined = 0b11011,
|
|
System = 0b11111
|
|
};
|
|
|
|
/// Instruction sets that may be signified through a PSR.
|
|
enum class InstructionSet
|
|
{
|
|
ARM,
|
|
Jazelle,
|
|
Thumb,
|
|
ThumbEE
|
|
};
|
|
|
|
PSR() = default;
|
|
explicit PSR(u32 data) : value{data & mask} {}
|
|
|
|
PSR& operator=(u32 data) {
|
|
value = data & mask;
|
|
return *this;
|
|
}
|
|
|
|
bool N() const {
|
|
return Common::Bit<31>(value);
|
|
}
|
|
void N(bool set) {
|
|
value = (value & ~0x80000000) | static_cast<u32>(set) << 31;
|
|
}
|
|
|
|
bool Z() const {
|
|
return Common::Bit<30>(value);
|
|
}
|
|
void Z(bool set) {
|
|
value = (value & ~0x40000000) | static_cast<u32>(set) << 30;
|
|
}
|
|
|
|
bool C() const {
|
|
return Common::Bit<29>(value);
|
|
}
|
|
void C(bool set) {
|
|
value = (value & ~0x20000000) | static_cast<u32>(set) << 29;
|
|
}
|
|
|
|
bool V() const {
|
|
return Common::Bit<28>(value);
|
|
}
|
|
void V(bool set) {
|
|
value = (value & ~0x10000000) | static_cast<u32>(set) << 28;
|
|
}
|
|
|
|
bool Q() const {
|
|
return Common::Bit<27>(value);
|
|
}
|
|
void Q(bool set) {
|
|
value = (value & ~0x8000000) | static_cast<u32>(set) << 27;
|
|
}
|
|
|
|
bool J() const {
|
|
return Common::Bit<24>(value);
|
|
}
|
|
void J(bool set) {
|
|
value = (value & ~0x1000000) | static_cast<u32>(set) << 24;
|
|
}
|
|
|
|
u32 GE() const {
|
|
return Common::Bits<16, 19>(value);
|
|
}
|
|
void GE(u32 data) {
|
|
value = (value & ~0xF0000) | (data & 0xF) << 16;
|
|
}
|
|
|
|
u32 IT() const {
|
|
return (value & 0x6000000) >> 25 | (value & 0xFC00) >> 8;
|
|
}
|
|
void IT(u32 data) {
|
|
value = (value & ~0x000FC00) | (data & 0b11111100) << 8;
|
|
value = (value & ~0x6000000) | (data & 0b00000011) << 25;
|
|
}
|
|
|
|
bool E() const {
|
|
return Common::Bit<9>(value);
|
|
}
|
|
void E(bool set) {
|
|
value = (value & ~0x200) | static_cast<u32>(set) << 9;
|
|
}
|
|
|
|
bool A() const {
|
|
return Common::Bit<8>(value);
|
|
}
|
|
void A(bool set) {
|
|
value = (value & ~0x100) | static_cast<u32>(set) << 8;
|
|
}
|
|
|
|
bool I() const {
|
|
return Common::Bit<7>(value);
|
|
}
|
|
void I(bool set) {
|
|
value = (value & ~0x80) | static_cast<u32>(set) << 7;
|
|
}
|
|
|
|
bool F() const {
|
|
return Common::Bit<6>(value);
|
|
}
|
|
void F(bool set) {
|
|
value = (value & ~0x40) | static_cast<u32>(set) << 6;
|
|
}
|
|
|
|
bool T() const {
|
|
return Common::Bit<5>(value);
|
|
}
|
|
void T(bool set) {
|
|
value = (value & ~0x20) | static_cast<u32>(set) << 5;
|
|
}
|
|
|
|
Mode M() const {
|
|
return static_cast<Mode>(Common::Bits<0, 4>(value));
|
|
}
|
|
void M(Mode mode) {
|
|
value = (value & ~0x1F) | (static_cast<u32>(mode) & 0x1F);
|
|
}
|
|
|
|
u32 Value() const {
|
|
return value;
|
|
}
|
|
|
|
InstructionSet CurrentInstructionSet() const {
|
|
const bool j_bit = J();
|
|
const bool t_bit = T();
|
|
|
|
if (j_bit && t_bit)
|
|
return InstructionSet::ThumbEE;
|
|
|
|
if (t_bit)
|
|
return InstructionSet::Thumb;
|
|
|
|
if (j_bit)
|
|
return InstructionSet::Jazelle;
|
|
|
|
return InstructionSet::ARM;
|
|
}
|
|
|
|
void CurrentInstructionSet(InstructionSet instruction_set) {
|
|
switch (instruction_set) {
|
|
case InstructionSet::ARM:
|
|
T(false);
|
|
J(false);
|
|
break;
|
|
case InstructionSet::Jazelle:
|
|
T(false);
|
|
J(true);
|
|
break;
|
|
case InstructionSet::Thumb:
|
|
T(true);
|
|
J(false);
|
|
break;
|
|
case InstructionSet::ThumbEE:
|
|
T(true);
|
|
J(true);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private:
|
|
// Bits 20-23 are reserved and should be zero.
|
|
static constexpr u32 mask = 0xFF0FFFFF;
|
|
|
|
u32 value = 0;
|
|
};
|
|
|
|
inline bool operator==(PSR lhs, PSR rhs) {
|
|
return lhs.Value() == rhs.Value();
|
|
}
|
|
|
|
inline bool operator!=(PSR lhs, PSR rhs) {
|
|
return !operator==(lhs, rhs);
|
|
}
|
|
|
|
} // namespace Dynarmic::A32
|