1 /* This file is part of the dynarmic project. 2 * Copyright (c) 2016 MerryMage 3 * SPDX-License-Identifier: 0BSD 4 */ 5 6 #pragma once 7 8 #include "common/bit_util.h" 9 #include "common/common_types.h" 10 #include "frontend/A32/ITState.h" 11 12 namespace Dynarmic::A32 { 13 14 /** 15 * Program Status Register 16 * 17 * | Bit(s) | Description | 18 * |:-------:|:----------------------------------------------| 19 * | N | Negative | 20 * | Z | Zero | 21 * | C | Carry | 22 * | V | Overflow | 23 * | Q | Sticky overflow for DSP-oriented instructions | 24 * | IT[1:0] | Lower two bits of the If-Then execution state | 25 * | J | Jazelle bit | 26 * | GE | Greater-than or Equal | 27 * | IT[7:2] | Upper six bits of the If-Then execution state | 28 * | E | Endian (0 is little endian, 1 is big endian) | 29 * | A | Imprecise data abort (disables them when set) | 30 * | I | IRQ interrupts (disabled when set) | 31 * | F | FIQ interrupts (disabled when set) | 32 * | T | Thumb bit | 33 * | M | Current processor mode | 34 */ 35 class PSR final { 36 public: 37 /// Valid processor modes that may be indicated. 38 enum class Mode : u32 { 39 User = 0b10000, 40 FIQ = 0b10001, 41 IRQ = 0b10010, 42 Supervisor = 0b10011, 43 Monitor = 0b10110, 44 Abort = 0b10111, 45 Hypervisor = 0b11010, 46 Undefined = 0b11011, 47 System = 0b11111 48 }; 49 50 /// Instruction sets that may be signified through a PSR. 51 enum class InstructionSet { 52 ARM, 53 Jazelle, 54 Thumb, 55 ThumbEE 56 }; 57 58 PSR() = default; PSR(u32 data)59 explicit PSR(u32 data) : value{data & mask} {} 60 61 PSR& operator=(u32 data) { 62 value = data & mask; 63 return *this; 64 } 65 N()66 bool N() const { 67 return Common::Bit<31>(value); 68 } N(bool set)69 void N(bool set) { 70 value = Common::ModifyBit<31>(value, set); 71 } 72 Z()73 bool Z() const { 74 return Common::Bit<30>(value); 75 } Z(bool set)76 void Z(bool set) { 77 value = Common::ModifyBit<30>(value, set); 78 } 79 C()80 bool C() const { 81 return Common::Bit<29>(value); 82 } C(bool set)83 void C(bool set) { 84 value = Common::ModifyBit<29>(value, set); 85 } 86 V()87 bool V() const { 88 return Common::Bit<28>(value); 89 } V(bool set)90 void V(bool set) { 91 value = Common::ModifyBit<28>(value, set); 92 } 93 Q()94 bool Q() const { 95 return Common::Bit<27>(value); 96 } Q(bool set)97 void Q(bool set) { 98 value = Common::ModifyBit<27>(value, set); 99 } 100 J()101 bool J() const { 102 return Common::Bit<24>(value); 103 } J(bool set)104 void J(bool set) { 105 value = Common::ModifyBit<24>(value, set); 106 } 107 GE()108 u32 GE() const { 109 return Common::Bits<16, 19>(value); 110 } GE(u32 data)111 void GE(u32 data) { 112 value = Common::ModifyBits<16, 19>(value, data); 113 } 114 IT()115 ITState IT() const { 116 return ITState{static_cast<u8>((value & 0x6000000) >> 25 | (value & 0xFC00) >> 8)}; 117 } IT(ITState it_state)118 void IT(ITState it_state) { 119 const u32 data = it_state.Value(); 120 value = (value & ~0x000FC00) | (data & 0b11111100) << 8; 121 value = (value & ~0x6000000) | (data & 0b00000011) << 25; 122 } 123 E()124 bool E() const { 125 return Common::Bit<9>(value); 126 } E(bool set)127 void E(bool set) { 128 value = Common::ModifyBit<9>(value, set); 129 } 130 A()131 bool A() const { 132 return Common::Bit<8>(value); 133 } A(bool set)134 void A(bool set) { 135 value = Common::ModifyBit<8>(value, set); 136 } 137 I()138 bool I() const { 139 return Common::Bit<7>(value); 140 } I(bool set)141 void I(bool set) { 142 value = Common::ModifyBit<7>(value, set); 143 } 144 F()145 bool F() const { 146 return Common::Bit<6>(value); 147 } F(bool set)148 void F(bool set) { 149 value = Common::ModifyBit<6>(value, set); 150 } 151 T()152 bool T() const { 153 return Common::Bit<5>(value); 154 } T(bool set)155 void T(bool set) { 156 value = Common::ModifyBit<5>(value, set); 157 } 158 M()159 Mode M() const { 160 return static_cast<Mode>(Common::Bits<0, 4>(value)); 161 } M(Mode mode)162 void M(Mode mode) { 163 value = Common::ModifyBits<0, 4>(value, static_cast<u32>(mode)); 164 } 165 Value()166 u32 Value() const { 167 return value; 168 } 169 CurrentInstructionSet()170 InstructionSet CurrentInstructionSet() const { 171 const bool j_bit = J(); 172 const bool t_bit = T(); 173 174 if (j_bit && t_bit) 175 return InstructionSet::ThumbEE; 176 177 if (t_bit) 178 return InstructionSet::Thumb; 179 180 if (j_bit) 181 return InstructionSet::Jazelle; 182 183 return InstructionSet::ARM; 184 } 185 CurrentInstructionSet(InstructionSet instruction_set)186 void CurrentInstructionSet(InstructionSet instruction_set) { 187 switch (instruction_set) { 188 case InstructionSet::ARM: 189 T(false); 190 J(false); 191 break; 192 case InstructionSet::Jazelle: 193 T(false); 194 J(true); 195 break; 196 case InstructionSet::Thumb: 197 T(true); 198 J(false); 199 break; 200 case InstructionSet::ThumbEE: 201 T(true); 202 J(true); 203 break; 204 } 205 } 206 207 private: 208 // Bits 20-23 are reserved and should be zero. 209 static constexpr u32 mask = 0xFF0FFFFF; 210 211 u32 value = 0; 212 }; 213 214 inline bool operator==(PSR lhs, PSR rhs) { 215 return lhs.Value() == rhs.Value(); 216 } 217 218 inline bool operator!=(PSR lhs, PSR rhs) { 219 return !operator==(lhs, rhs); 220 } 221 222 } // namespace Dynarmic::A32 223