-
Notifications
You must be signed in to change notification settings - Fork 0
/
Coprocessor0.h
executable file
·280 lines (243 loc) · 8.66 KB
/
Coprocessor0.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
//
// Coprocessor0.h
// MIPS_Emulator
//
// Created by Matt on 1/8/16.
// Copyright © 2016 Matt. All rights reserved.
//
#ifndef Coprocessor0_h
#define Coprocessor0_h
#include "SharedDefs.h"
#include "COP0Register.h"
#include <thread> // For std::thread
#include <atomic> // For std::atomic
#include <mutex> // For std::mutex
#include <cstdlib> // For rand()
#include <ctime> // For time()
// Register Name Macros (number,sel)
#define CO0_INDEX 0,0
#define CO0_RANDOM 1,0
#define CO0_ENTRYLO0 2,0
#define CO0_ENTRYLO1 3,0
#define CO0_CONTEXT 4,0
#define CO0_USERLOCAL 4,2
#define CO0_PAGEMASK 5,0
#define CO0_PAGEGRAIN 5,1
#define CO0_WIRED 6,0
#define CO0_HWRENA 7,0
#define CO0_BADVADDR 8,0
#define CO0_COUNT 9,0
#define CO0_ENTRYHI 10,0
#define CO0_COMPARE 11,0
#define CO0_STATUS 12,0
#define CO0_INTCTL 12,1
#define CO0_SRSCTL 12,2
#define CO0_SRSMAP 12,3
#define CO0_CAUSE 13,0
#define CO0_EPC 14,0
#define CO0_PRID 15,0
#define CO0_EBASE 15,1
#define CO0_CONFIG0 16,0
#define CO0_CONFIG1 16,1
#define CO0_CONFIG2 16,2
#define CO0_CONFIG3 16,3
#define CO0_LLADDR 17,0
#define CO0_WATCHLO 18,0
#define CO0_WATCHHI 19,0
#define CO0_XCONTEXT 20,0
#define CO0_TAGLO 28,0
#define CO0_TAGHI 29,0
#define CO0_ERROREPC 30,0
// Index Register Fields (CP0 Register 0, Select 0)
#define INDEX_P 0x80000000
#define INDEX_INDEX 0x0000003F
// Random Register Fields (CP0 Register 1, Select 0)
#define RANDOM_RANDOM 0x0000003F
// EntryLo0 Register Fields (CP0 Register 2, Select 0)
#define ENTRYLO0_FILL 0xC0000000
#define ENTRYLO0_PFN 0x3FFFFFC0
#define ENTRYLO0_C 0x00000038
#define ENTRYLO0_D 0x00000004
#define ENTRYLO0_V 0x00000002
#define ENTRYLO0_G 0x00000001
// EntryLo1 Register Fields (CP0 Register 3, Select 0)
#define ENTRYLO1_FILL 0xC0000000
#define ENTRYLO1_PFN 0x3FFFFFC0
#define ENTRYLO1_C 0x00000038
#define ENTRYLO1_D 0x00000004
#define ENTRYLO1_V 0x00000002
#define ENTRYLO1_G 0x00000001
// Context Register Fields (CP0 Register 4, Select 0)
#define CONTEXT_PTEBASE 0xFF800000
#define CONTEXT_BADVPN2 0x007FFFF0
// ContextConfig Register Fields (CP0 Register 4, Select 1)
#define CONTEXTCONFIG_VIRTUALINDEX 0xFFFFFFFF
// UserLocal Register Fields (CP0 Register 4, Select 2)
#define USERLOCAL_USERINFORMATION 0xFFFFFFFF
// PageMask Register Fields (CP0 Register 5, Select 0)
#define PAGEMASK_MASK 0x1FFFE000
#define PAGEMASK_MASKX 0x00001800
// PageGrain Register Fields (CP0 Register 5, Select 1)
#define PAGEGRAIN_RIE 0x80000000
#define PAGEGRAIN_XIE 0x40000000
#define PAGEGRAIN_ELPA 0x20000000
#define PAGEGRAIN_ESP 0x10000000
#define PAGEGRAIN_IEC 0x08000000
#define PAGEGRAIN_S32 0x04000000
#define PAGEGRAIN_ASE 0x00001F00
#define PAGEGRAIN_MCCAUSE 0x0000001F
// EntryHi Register Fields (CP0 Register 10, Select 0)
#define ENTRYHI_VPN2 0xFFFFE000
#define ENTRYHI_VPN2X 0x00001800
#define ENTRYHI_FULLVPN 0xFFFFF800
#define ENTRYHI_EH 0x00000400
#define ENTRYHI_INV 0x00000400
#define ENTRYHI_ASIDX 0x00000300
#define ENTRYHI_ASID 0x000000FF
// Status Register Fields (CP0 Register 12, Select 0)
#define STATUS_CU3 0x80000000
#define STATUS_CU2 0x40000000
#define STATUS_CU1 0x20000000
#define STATUS_CU0 0x10000000
#define STATUS_RP 0x08000000
#define STATUS_FR 0x04000000
#define STATUS_RE 0x02000000
#define STATUS_MX 0x01000000
#define STATUS_PX 0x00800000
#define STATUS_BEV 0x00400000
#define STATUS_TS 0x00200000
#define STATUS_SR 0x00100000
#define STATUS_NMI 0x00080000
#define STATUS_IMPL1 0x00020000
#define STATUS_IMPL0 0x00010000
#define STATUS_IM7 0x00008000
#define STATUS_IM6 0x00004000
#define STATUS_IM5 0x00002000
#define STATUS_IM4 0x00001000
#define STATUS_IM3 0x00000800
#define STATUS_IM2 0x00000400
#define STATUS_IM1 0x00000200
#define STATUS_IM0 0x00000100
#define STATUS_KX 0x00000080
#define STATUS_SX 0x00000040
#define STATUS_UX 0x00000020
#define STATUS_KSU 0x00000018
#define STATUS_UM 0x00000010
#define STATUS_R0 0x00000008
#define STATUS_ERL 0x00000004
#define STATUS_EXL 0x00000002
#define STATUS_IE 0x00000001
#define STATUS_INTS 0x00000007
// IntCtl Register Fields (CP0 Register 12, Select 1)
#define INTCTL_IPTI 0xE0000000
#define INTCTL_IPPCI 0x1C000000
#define INTCTL_IPFDC 0x03800000
#define INTCTL_MCUASE 0x007FC000
#define INTCTL_VS 0x000003E0
// SRSCtl Register (CP0 Register 12, Select 2)
#define SRSCTL_HSS 0x3C000000
#define SRSCTL_EICSS 0x003C0000
#define SRSCTL_ESS 0x0000F000
#define SRSCTL_PSS 0x000003C0
#define SRSCTL_CSS 0x0000000F
// Cause Register (CP0 Register 13, Select 0)
#define CAUSE_BD 0x80000000
#define CAUSE_TI 0x40000000
#define CAUSE_CE 0x30000000
#define CAUSE_DC 0x08000000
#define CAUSE_PCI 0x04000000
#define CAUSE_ASE1 0x03000000
#define CAUSE_IV 0x00800000
#define CAUSE_WP 0x00400000
#define CAUSE_FDCI 0x00200000
#define CAUSE_ASE2 0x00030000
#define CAUSE_RIPL 0x0000FC00
#define CAUSE_INTS 0x0000FF00
#define CAUSE_IP7 0x00008000
#define CAUSE_IP6 0x00004000
#define CAUSE_IP5 0x00002000
#define CAUSE_IP4 0x00001000
#define CAUSE_IP3 0x00000800
#define CAUSE_IP2 0x00000400
#define CAUSE_IP1 0x00000200
#define CAUSE_IP0 0x00000100
#define CAUSE_EXCCODE 0x0000007C
// EBase Register (CP0 Register 15, Select 1)
#define EBASE_EBASEFULL 0xFFFFF000
#define EBASE_EBASE 0x3FFFF000
#define EBASE_CPUNUM 0x000003FF
// Config Register (CP0 Register 16, Select 0)
#define CONFIG0_M 0x80000000
#define CONFIG0_K23 0x70000000
#define CONFIG0_KU 0x0E000000
#define CONFIG0_IMPL 0x01FF0000
#define CONFIG0_BE 0x00008000
#define CONFIG0_AT 0x00006000
#define CONFIG0_AR 0x00001C00
#define CONFIG0_MT 0x00000380
#define CONFIG0_VI 0x00000008
#define CONFIG0_K0 0x00000007
// Config3 Register (CP0 Register 16, Select 3)
#define CONFIG3_M 0x80000000
#define CONFIG3_CMGCR 0x20000000
#define CONFIG3_MSAP 0x10000000
#define CONFIG3_BP 0x08000000
#define CONFIG3_BI 0x04000000
#define CONFIG3_SC 0x02000000
#define CONFIG3_PW 0x01000000
#define CONFIG3_VZ 0x00800000
#define CONFIG3_IPLW 0x00600000
#define CONFIG3_MMAR 0x001C0000
#define CONFIG3_MUCON 0x00020000
#define CONFIG3_ISAONEXEC 0x00010000
#define CONFIG3_ISA 0x0000C000
#define CONFIG3_ULRI 0x00002000
#define CONFIG3_RXI 0x00001000
#define CONFIG3_DSP2P 0x00000800
#define CONFIG3_DSPP 0x00000400
#define CONFIG3_CTXTC 0x00000200
#define CONFIG3_ITL 0x00000100
#define CONFIG3_LPA 0x00000080
#define CONFIG3_VEIC 0x00000040
#define CONFIG3_VINT 0x00000020
#define CONFIG3_SP 0x00000010
#define CONFIG3_CDMM 0x00000008
#define CONFIG3_MT 0x00000004
#define CONFIG3_SM 0x00000002
#define CONFIG3_TL 0x00000001
// Forward reference to CPU
class CPU;
class Coprocessor0 {
private:
// Coprocessor Register File
COP0Register* registerFile[32][32];
public:
Coprocessor0();
~Coprocessor0();
// Tests for various operating modes
bool inKernelMode();
bool interruptsEnabled();
// Returns the value in a register for software
uint32_t getRegisterSW(uint8_t regnum, uint8_t sel);
// Returns the value in a register
uint32_t getRegister(uint8_t regnum, uint8_t sel);
#ifdef TEST_PROJECT
// Gets the reset value for a register, for unit testing
uint32_t getRegisterReset(uint8_t regnum, uint8_t sel);
#endif
// Sets a register in software mode (i.e. mips programs) atomically
void setRegisterSW(uint8_t regnum, uint8_t sel, uint32_t value);
// Sets a register in hardware mode (i.e. mmu) atomically
void setRegisterHW(uint8_t regnum, uint8_t sel, uint32_t value);
// Does an atomic and on the register with mask
void andRegisterHW(uint8_t regnum, uint8_t sel, uint32_t mask);
// Does an atomic or on the register with mask
void orRegisterHW(uint8_t regnum, uint8_t sel, uint32_t mask);
// Resets a register to its original startup state atomically
void resetRegister(uint8_t regnum, uint8_t sel);
// Called by CPU to update Random Register
void updateRandom();
// Read Hardware Register
uint32_t readHWRegister(uint8_t rd);
};
#endif /* Coprocessor0_h */