1 #pragma once
2 
3 #include "Types.h"
4 #include "MemoryMap.h"
5 #include "MipsExecutor.h"
6 #include "MIPSArchitecture.h"
7 #include "MIPSCoprocessor.h"
8 #include "MIPSAnalysis.h"
9 #include "MIPSTags.h"
10 #include "uint128.h"
11 #include <set>
12 
13 struct REGISTER_PIPELINE
14 {
15 	uint32 counter;
16 	uint32 heldValue;
17 };
18 
19 enum
20 {
21 	//Must be a power of 2
22 	FLAG_PIPELINE_SLOTS = 8,
23 };
24 
25 //Invariants:
26 //- Pipe times are sorted when iterating from index to index + PIPELINE_SLOTS
27 //- The value at index - 1 is the latest value
28 struct FLAG_PIPELINE
29 {
30 	uint32 index;
31 	uint32 values[FLAG_PIPELINE_SLOTS];
32 	uint32 pipeTimes[FLAG_PIPELINE_SLOTS];
33 };
34 
35 enum
36 {
37 	MIPS_EXCEPTION_NONE = 0,
38 	MIPS_EXCEPTION_SYSCALL,
39 	MIPS_EXCEPTION_CHECKPENDINGINT,
40 	MIPS_EXCEPTION_IDLE,
41 	MIPS_EXCEPTION_RETURNFROMEXCEPTION,
42 	MIPS_EXCEPTION_CALLMS,
43 	MIPS_EXCEPTION_BREAKPOINT,
44 	MIPS_EXCEPTION_TLB,
45 };
46 
47 struct TLBENTRY
48 {
49 	uint32 entryLo0;
50 	uint32 entryLo1;
51 	uint32 entryHi;
52 	uint32 pageMask;
53 };
54 
55 #define MIPS_EXECUTION_STATUS_QUOTADONE 0x80
56 
57 struct MIPSSTATE
58 {
59 	uint32 nPC;
60 	uint32 nDelayedJumpAddr;
61 	uint32 nHasException;
62 	int32 cycleQuota;
63 
64 #ifdef _WIN32
65 	__declspec(align(16))
66 #else
67 	__attribute__((aligned(16)))
68 #endif
69 	    uint128 nGPR[32];
70 
71 	uint32 nHI[2];
72 	uint32 nLO[2];
73 	uint32 nHI1[2];
74 	uint32 nLO1[2];
75 	uint32 nSA;
76 
77 	//COP0
78 	uint32 nCOP0[32];
79 
80 	uint32 cop0_pccr;
81 	uint32 cop0_pcr[2];
82 
83 	//COP1
84 	uint32 nCOP1[32];
85 	uint32 nCOP1A;
86 	uint32 nFCSR;
87 
88 	//COP2
89 #ifdef _WIN32
90 	__declspec(align(16))
91 #else
92 	__attribute__((aligned(16)))
93 #endif
94 	    uint128 nCOP2[33];
95 
96 	uint128 nCOP2A;
97 
98 	uint128 nCOP2VF_PreUp;
99 	uint128 nCOP2VF_UpRes;
100 
101 	uint32 nCOP2Q;
102 	uint32 nCOP2I;
103 	uint32 nCOP2P;
104 	uint32 nCOP2R;
105 	uint32 nCOP2CF; //Mirror of CLIP flag (computed with values from pipeClip)
106 	uint32 nCOP2MF; //Mirror of MACflag (computed with values from pipeMac)
107 	uint32 nCOP2SF; //Sticky values of sign and zero MACflag (ie.: SxSySzSw ZxZyZzZw)
108 	uint32 nCOP2DF; //Division by 0 flag from DIV operations
109 	uint32 nCOP2T;
110 
111 	uint32 nCOP2VI[16];
112 
113 	REGISTER_PIPELINE pipeQ;
114 	REGISTER_PIPELINE pipeP;
115 	FLAG_PIPELINE pipeMac;
116 	FLAG_PIPELINE pipeSticky;
117 	FLAG_PIPELINE pipeClip;
118 
119 	uint32 pipeTime;
120 
121 	uint32 cmsar0;
122 	uint32 callMsEnabled;
123 	uint32 callMsAddr;
124 
125 	uint32 savedIntReg;
126 	uint32 savedIntRegTemp;
127 	uint32 xgkickAddress;
128 
129 	enum
130 	{
131 		TLB_ENTRY_MAX = 48,
132 	};
133 
134 	TLBENTRY tlbEntries[TLB_ENTRY_MAX];
135 };
136 
137 #define MIPS_INVALID_PC (0x00000001)
138 #define MIPS_PAGE_SIZE (0x1000)
139 
140 class CMIPS
141 {
142 public:
143 	typedef uint32 (*AddressTranslator)(CMIPS*, uint32);
144 	typedef uint32 (*TLBExceptionChecker)(CMIPS*, uint32, uint32);
145 
146 	typedef std::set<uint32> BreakpointSet;
147 
148 	CMIPS(MEMORYMAP_ENDIANESS, bool usePageTable = false);
149 	~CMIPS();
150 	void ToggleBreakpoint(uint32);
151 	bool HasBreakpointInRange(uint32, uint32) const;
152 	bool IsBranch(uint32);
153 	static int32 GetBranch(uint16);
154 	static uint32 TranslateAddress64(CMIPS*, uint32);
155 
156 	void Reset();
157 
158 	bool CanGenerateInterrupt() const;
159 	bool GenerateInterrupt(uint32);
160 	bool GenerateException(uint32);
161 
162 	void MapPages(uint32, uint32, uint8*);
163 
164 	MIPSSTATE m_State;
165 
166 	void* m_vuMem = nullptr;
167 	void** m_pageLookup = nullptr;
168 
169 	std::function<void(CMIPS*)> m_emptyBlockHandler;
170 
171 	CMIPSArchitecture* m_pArch = nullptr;
172 	CMIPSCoprocessor* m_pCOP[4];
173 	CMemoryMap* m_pMemoryMap = nullptr;
174 	std::unique_ptr<CMipsExecutor> m_executor;
175 	BreakpointSet m_breakpoints;
176 
177 	CMIPSAnalysis* m_analysis = nullptr;
178 	CMIPSTags m_Comments;
179 	CMIPSTags m_Functions;
180 
181 	AddressTranslator m_pAddrTranslator = nullptr;
182 	TLBExceptionChecker m_TLBExceptionChecker = nullptr;
183 
184 	enum REGISTER
185 	{
186 		R0 = 0,
187 		AT,
188 		V0,
189 		V1,
190 		A0,
191 		A1,
192 		A2,
193 		A3,
194 		T0,
195 		T1,
196 		T2,
197 		T3,
198 		T4,
199 		T5,
200 		T6,
201 		T7,
202 		S0,
203 		S1,
204 		S2,
205 		S3,
206 		S4,
207 		S5,
208 		S6,
209 		S7,
210 		T8,
211 		T9,
212 		K0,
213 		K1,
214 		GP,
215 		SP,
216 		FP,
217 		RA
218 	};
219 
220 	enum
221 	{
222 		STATUS_IE = (1 << 0),
223 		STATUS_EXL = (1 << 1),
224 		STATUS_ERL = (1 << 2),
225 		STATUS_EIE = (1 << 16), //PS2 EE specific
226 	};
227 
228 	static const char* m_sGPRName[];
229 };
230