-
-
Notifications
You must be signed in to change notification settings - Fork 270
/
Copy pathMIPS.h
235 lines (192 loc) · 4.33 KB
/
MIPS.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
#pragma once
#include "Types.h"
#include "MemoryMap.h"
#include "MipsExecutor.h"
#include "MIPSArchitecture.h"
#include "MIPSCoprocessor.h"
#include "MIPSAnalysis.h"
#include "MIPSTags.h"
#include "uint128.h"
#include <set>
struct REGISTER_PIPELINE
{
uint32 counter;
uint32 heldValue;
};
enum
{
//Must be a power of 2
FLAG_PIPELINE_SLOTS = 8,
};
//Invariants:
//- Pipe times are sorted when iterating from index to index PIPELINE_SLOTS
//- The value at index - 1 is the latest value
struct FLAG_PIPELINE
{
uint32 index;
uint32 values[FLAG_PIPELINE_SLOTS];
uint32 pipeTimes[FLAG_PIPELINE_SLOTS];
};
enum
{
MIPS_EXCEPTION_NONE = 0,
MIPS_EXCEPTION_SYSCALL,
MIPS_EXCEPTION_CHECKPENDINGINT,
MIPS_EXCEPTION_IDLE,
MIPS_EXCEPTION_RETURNFROMEXCEPTION,
MIPS_EXCEPTION_BREAKPOINT,
MIPS_EXCEPTION_TLB,
MIPS_EXCEPTION_VU_CALLMS,
MIPS_EXCEPTION_VU_DBIT,
MIPS_EXCEPTION_VU_TBIT,
MIPS_EXCEPTION_VU_EBIT,
MIPS_EXCEPTION_MAX, //Used to make sure we don't conflict with the QUOTADONE status
};
static_assert(MIPS_EXCEPTION_MAX <= 0x80);
static constexpr uint32 MIPS_EXCEPTION_STATUS_QUOTADONE = 0x80;
struct TLBENTRY
{
uint32 entryLo0;
uint32 entryLo1;
uint32 entryHi;
uint32 pageMask;
};
struct MIPSSTATE
{
uint32 nPC;
uint32 nDelayedJumpAddr;
uint32 nHasException;
int32 cycleQuota;
alignas(16) uint128 nGPR[32];
uint32 nHI[2];
uint32 nLO[2];
uint32 nHI1[2];
uint32 nLO1[2];
uint32 nSA;
//COP0
uint32 nCOP0[32];
uint32 cop0_pccr;
uint32 cop0_pcr[2];
//COP1
uint32 nCOP1[32];
uint32 nCOP1A;
uint32 nFCSR;
//COP2
alignas(16) uint128 nCOP2[33];
uint128 nCOP2A;
uint128 nCOP2VF_PreUp;
uint128 nCOP2VF_UpRes;
uint32 nCOP2Q;
uint32 nCOP2I;
uint32 nCOP2P;
uint32 nCOP2R;
uint32 nCOP2CF; //Mirror of CLIP flag (computed with values from pipeClip)
uint32 nCOP2MF; //Mirror of MACflag (computed with values from pipeMac)
uint32 nCOP2SF; //Sticky values of sign and zero MACflag (ie.: SxSySzSw ZxZyZzZw)
uint32 nCOP2DF; //Division by 0 flag from DIV operations
uint32 nCOP2T;
uint32 nCOP2VI[16];
REGISTER_PIPELINE pipeQ;
REGISTER_PIPELINE pipeP;
FLAG_PIPELINE pipeMac;
FLAG_PIPELINE pipeSticky;
FLAG_PIPELINE pipeClip;
alignas(16) uint128 pipeFmacWrite[3]; //Pending FMAC write operations (for dynamic stall computation)
uint32 pipeTime;
uint32 cmsar0;
uint32 callMsEnabled;
uint32 callMsAddr;
uint32 savedIntReg;
uint32 savedIntRegTemp;
// In the case that the final delay slot includes an integer altering instruction
// save the register number here along with the value it has assuming the first
// instruction of the next block is a conditional branch on the same register.
uint32 savedNextBlockIntRegIdx;
uint32 savedNextBlockIntRegVal;
uint32 savedNextBlockIntRegValTemp;
uint32 xgkickAddress;
enum
{
TLB_ENTRY_MAX = 48,
};
TLBENTRY tlbEntries[TLB_ENTRY_MAX];
};
#define MIPS_INVALID_PC (0x00000001)
#define MIPS_PAGE_SIZE (0x1000)
class CMIPS
{
public:
typedef uint32 (*AddressTranslator)(CMIPS*, uint32);
typedef uint32 (*TLBExceptionChecker)(CMIPS*, uint32, uint32);
typedef std::set<uint32> BreakpointSet;
CMIPS(MEMORYMAP_ENDIANNESS, bool usePageTable = false);
~CMIPS();
void ToggleBreakpoint(uint32);
bool HasBreakpointInRange(uint32, uint32) const;
bool IsBranch(uint32);
static int32 GetBranch(uint16);
static uint32 TranslateAddress64(CMIPS*, uint32);
void Reset();
bool CanGenerateInterrupt() const;
bool GenerateInterrupt(uint32);
bool GenerateException(uint32);
void MapPages(uint32, uint32, uint8*);
MIPSSTATE m_State;
void* m_vuMem = nullptr;
void** m_pageLookup = nullptr;
std::function<void(CMIPS*)> m_emptyBlockHandler;
CMIPSArchitecture* m_pArch = nullptr;
CMIPSCoprocessor* m_pCOP[4];
CMemoryMap* m_pMemoryMap = nullptr;
std::unique_ptr<CMipsExecutor> m_executor;
BreakpointSet m_breakpoints;
CMIPSAnalysis* m_analysis = nullptr;
CMIPSTags m_Comments;
CMIPSTags m_Functions;
CMIPSTags m_Variables;
AddressTranslator m_pAddrTranslator = nullptr;
TLBExceptionChecker m_TLBExceptionChecker = nullptr;
enum REGISTER
{
R0 = 0,
AT,
V0,
V1,
A0,
A1,
A2,
A3,
T0,
T1,
T2,
T3,
T4,
T5,
T6,
T7,
S0,
S1,
S2,
S3,
S4,
S5,
S6,
S7,
T8,
T9,
K0,
K1,
GP,
SP,
FP,
RA
};
enum
{
STATUS_IE = (1 << 0),
STATUS_EXL = (1 << 1),
STATUS_ERL = (1 << 2),
STATUS_EIE = (1 << 16), //PS2 EE specific
};
static const char* m_sGPRName[];
};