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