/[pcsx2_0.9.7]/trunk/pcsx2/x86/microVU.h
ViewVC logotype

Contents of /trunk/pcsx2/x86/microVU.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 280 - (show annotations) (download)
Thu Dec 23 12:02:12 2010 UTC (9 years, 2 months ago) by william
File MIME type: text/plain
File size: 10356 byte(s)
re-commit (had local access denied errors when committing)
1 /* PCSX2 - PS2 Emulator for PCs
2 * Copyright (C) 2002-2010 PCSX2 Dev Team
3 *
4 * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU Lesser General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with PCSX2.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16 #pragma once
17 //#define mVUlogProg // Dumps MicroPrograms to \logs\*.html
18
19 class AsciiFile;
20 using namespace std;
21 using namespace x86Emitter;
22
23 #include <deque>
24
25 #include "VU.h"
26 #include "GS.h"
27 #include "Gif.h"
28 #include "iR5900.h"
29 #include "R5900OpcodeTables.h"
30 #include "x86emitter/x86emitter.h"
31 #include "microVU_Misc.h"
32 #include "microVU_IR.h"
33
34 struct microBlockLink {
35 microBlock block;
36 microBlockLink* next;
37 };
38
39 class microBlockManager {
40 private:
41 microBlockLink* blockList;
42 microBlockLink* blockEnd;
43 int listI;
44
45 public:
46 microBlockManager() {
47 listI = 0;
48 blockEnd = blockList = NULL;
49 }
50 ~microBlockManager() { reset(); }
51 void reset() {
52 for(microBlockLink* linkI = blockList; linkI != NULL; ) {
53 microBlockLink* freeI = linkI;
54 safe_delete_array(linkI->block.jumpCache);
55 linkI = linkI->next;
56 _aligned_free(freeI);
57 }
58 listI = 0;
59 blockEnd = blockList = NULL;
60 };
61 microBlock* add(microBlock* pBlock) {
62 microBlock* thisBlock = search(&pBlock->pState);
63 if (!thisBlock) {
64 listI++;
65 microBlockLink* newBlock = (microBlockLink*)_aligned_malloc(sizeof(microBlockLink), 16);
66 newBlock->block.jumpCache = NULL;
67 newBlock->next = NULL;
68
69 if (blockEnd) {
70 blockEnd->next = newBlock;
71 blockEnd = newBlock;
72 }
73 else {
74 blockEnd = blockList = newBlock;
75 }
76
77 memcpy_const(&newBlock->block, pBlock, sizeof(microBlock));
78 thisBlock = &newBlock->block;
79 }
80 return thisBlock;
81 }
82 __ri microBlock* search(microRegInfo* pState) {
83 if (pState->needExactMatch) { // Needs Detailed Search (Exact Match of Pipeline State)
84 for (microBlockLink* linkI = blockList; linkI != NULL; linkI = linkI->next) {
85 if (mVUquickSearch((void*)pState, (void*)&linkI->block.pState, sizeof(microRegInfo)))
86 return &linkI->block;
87 }
88 }
89 else { // Can do Simple Search (Only Matches the Important Pipeline Stuff)
90 for (microBlockLink* linkI = blockList; linkI != NULL; linkI = linkI->next) {
91 if (doConstProp && (linkI->block.pState.vi15 != pState->vi15)) continue;
92 if (linkI->block.pState.quick32[0] != pState->quick32[0]) continue;
93 if (linkI->block.pState.quick32[1] != pState->quick32[1]) continue;
94 return &linkI->block;
95 }
96 }
97 return NULL;
98 }
99 void printInfo(int pc) {
100 if (listI < 7) return;
101 microBlockLink* linkI = blockList;
102 for (int i = 0; i <= listI; i++) {
103 u32 viCRC = 0, vfCRC = 0, crc = 0, z = sizeof(microRegInfo)/4;
104 for (u32 j = 0; j < 4; j++) viCRC -= ((u32*)linkI->block.pState.VI)[j];
105 for (u32 j = 0; j < 32; j++) vfCRC -= linkI->block.pState.VF[j].reg;
106 for (u32 j = 0; j < z; j++) crc -= ((u32*)&linkI->block.pState)[j];
107 DevCon.WriteLn(Color_Green, "[%04x][Block #%d][crc=%08x][q=%02d][p=%02d][xgkick=%d][vi15=%08x][viBackup=%02d]"
108 "[flags=%02x][exactMatch=%x][blockType=%d][viCRC=%08x][vfCRC=%08x]", pc, i, crc, linkI->block.pState.q,
109 linkI->block.pState.p, linkI->block.pState.xgkick, linkI->block.pState.vi15, linkI->block.pState.viBackUp,
110 linkI->block.pState.flags, linkI->block.pState.needExactMatch, linkI->block.pState.blockType, viCRC, vfCRC);
111 linkI = linkI->next;
112 }
113 }
114 };
115
116 struct microRange {
117 s32 start; // Start PC (The opcode the block starts at)
118 s32 end; // End PC (The opcode the block ends with)
119 };
120
121 #define mProgSize (0x4000/4)
122 struct microProgram {
123 u32 data [mProgSize]; // Holds a copy of the VU microProgram
124 microBlockManager* block[mProgSize/2]; // Array of Block Managers
125 deque<microRange>* ranges; // The ranges of the microProgram that have already been recompiled
126 u32 startPC; // Start PC of this program
127 int idx; // Program index
128 };
129
130 typedef deque<microProgram*> microProgramList;
131
132 struct microProgramQuick {
133 microBlockManager* block; // Quick reference to valid microBlockManager for current startPC
134 microProgram* prog; // The microProgram who is the owner of 'block'
135 };
136
137 struct microProgManager {
138 microIR<mProgSize> IRinfo; // IR information
139 microProgramList* prog [mProgSize/2]; // List of microPrograms indexed by startPC values
140 microProgramQuick quick[mProgSize/2]; // Quick reference to valid microPrograms for current execution
141 microProgram* cur; // Pointer to currently running MicroProgram
142 int total; // Total Number of valid MicroPrograms
143 int isSame; // Current cached microProgram is Exact Same program as mVU->regs().Micro (-1 = unknown, 0 = No, 1 = Yes)
144 int cleared; // Micro Program is Indeterminate so must be searched for (and if no matches are found then recompile a new one)
145 u32 curFrame; // Frame Counter
146 u8* x86ptr; // Pointer to program's recompilation code
147 u8* x86start; // Start of program's rec-cache
148 u8* x86end; // Limit of program's rec-cache
149 microRegInfo lpState; // Pipeline state from where program left off (useful for continuing execution)
150 };
151
152 static const uint mVUdispCacheSize = __pagesize; // Dispatcher Cache Size (in bytes)
153 static const uint mVUcacheSafeZone = 3; // Safe-Zone for program recompilation (in megabytes)
154 static const uint mVUcacheInitReserve = 64; // Initial Reserve Cache Size (in megabytes)
155 static const uint mVUcacheMaxReserve = 128; // Max Reserve Cache Size (in megabytes)
156
157 struct microVU {
158
159 __aligned16 u32 macFlag[4]; // 4 instances of mac flag (used in execution)
160 __aligned16 u32 clipFlag[4]; // 4 instances of clip flag (used in execution)
161 __aligned16 u32 xmmCTemp[4]; // Backup used in mVUclamp2()
162 __aligned16 u32 xmmBackup[8][4]; // Backup for xmm0~xmm7
163
164 u32 index; // VU Index (VU0 or VU1)
165 u32 cop2; // VU is in COP2 mode? (No/Yes)
166 u32 vuMemSize; // VU Main Memory Size (in bytes)
167 u32 microMemSize; // VU Micro Memory Size (in bytes)
168 u32 progSize; // VU Micro Memory Size (in u32's)
169 u32 progMemMask; // VU Micro Memory Size (in u32's)
170 u32 cacheSize; // VU Cache Size
171
172 microProgManager prog; // Micro Program Data
173 ScopedPtr<microRegAlloc> regAlloc; // Reg Alloc Class
174 ScopedPtr<AsciiFile> logFile; // Log File Pointer
175
176
177 RecompiledCodeReserve* cache_reserve;
178 u8* cache; // Dynarec Cache Start (where we will start writing the recompiled code to)
179 u8* dispCache; // Dispatchers Cache (where startFunct and exitFunct are written to)
180 u8* startFunct; // Ptr Function to the Start code for recompiled programs
181 u8* exitFunct; // Ptr Function to the Exit code for recompiled programs
182 u32 code; // Contains the current Instruction
183 u32 divFlag; // 1 instance of I/D flags
184 u32 VIbackup; // Holds a backup of a VI reg if modified before a branch
185 u32 VIxgkick; // Holds a backup of a VI reg used for xgkick-delays
186 u32 branch; // Holds branch compare result (IBxx) OR Holds address to Jump to (JALR/JR)
187 u32 badBranch; // For Branches in Branch Delay Slots, holds Address the first Branch went to + 8
188 u32 evilBranch; // For Branches in Branch Delay Slots, holds Address to Jump to
189 u32 p; // Holds current P instance index
190 u32 q; // Holds current Q instance index
191 u32 totalCycles; // Total Cycles that mVU is expected to run for
192 u32 cycles; // Cycles Counter
193
194 VURegs& regs() const { return ::vuRegs[index]; }
195
196 VIFregisters& getVifRegs() const { return regs().GetVifRegs(); }
197 __fi REG_VI& getVI(uint reg) const { return regs().VI[reg]; }
198 __fi VECTOR& getVF(uint reg) const { return regs().VF[reg]; }
199
200
201 __fi s16 Imm5() const { return ((code & 0x400) ? 0xfff0 : 0) | ((code >> 6) & 0xf); }
202 __fi s32 Imm11() const { return (code & 0x400) ? (0xfffffc00 | (code & 0x3ff)) : (code & 0x3ff); }
203 __fi u32 Imm12() const { return (((code >> 21) & 0x1) << 11) | (code & 0x7ff); }
204 __fi u32 Imm15() const { return ((code >> 10) & 0x7800) | (code & 0x7ff); }
205 __fi u32 Imm24() const { return code & 0xffffff; }
206
207 // Fetches the PC and instruction opcode relative to the current PC. Used to rewind and
208 // fast-forward the IR state while calculating VU pipeline conditions (branches, writebacks, etc)
209 __fi void advancePC( int x )
210 {
211 prog.IRinfo.curPC += x;
212 prog.IRinfo.curPC &= progMemMask;
213 code = ((u32*)regs().Micro)[prog.IRinfo.curPC];
214 }
215
216 __ri uint getBranchAddr() const
217 {
218 pxAssumeDev((prog.IRinfo.curPC & 1) == 0, "microVU recompiler: Upper instructions cannot have valid branch addresses.");
219 return (((prog.IRinfo.curPC + 2) + (Imm11() * 2)) & progMemMask) * 4;
220 }
221
222 __ri uint getBranchAddrN() const
223 {
224 pxAssumeDev((prog.IRinfo.curPC & 1) == 0, "microVU recompiler: Upper instructions cannot have valid branch addresses.");
225 return (((prog.IRinfo.curPC + 4) + (Imm11() * 2)) & progMemMask) * 4;
226 }
227
228 microVU()
229 {
230 cacheSize = mVUcacheInitReserve;
231 cache = NULL;
232 dispCache = NULL;
233 startFunct = NULL;
234 exitFunct = NULL;
235 }
236
237 void reserveCache();
238 void init(uint vuIndex);
239 void reset();
240 void close();
241 };
242
243 // microVU rec structs
244 extern __aligned16 microVU microVU0;
245 extern __aligned16 microVU microVU1;
246
247 // Debug Helper
248 int mVUdebugNow = 0;
249
250 // Main Functions
251 static void mVUclear(mV, u32, u32);
252 static void* mVUblockFetch(microVU* mVU, u32 startPC, uptr pState);
253 _mVUt extern void* __fastcall mVUcompileJIT(u32 startPC, uptr ptr);
254
255 // Prototypes for Linux
256 extern void __fastcall mVUcleanUpVU0();
257 extern void __fastcall mVUcleanUpVU1();
258 mVUop(mVUopU);
259 mVUop(mVUopL);
260
261 // Private Functions
262 _mVUt extern void mVUcacheProg (microProgram& prog);
263 _mVUt extern void mVUdeleteProg(microProgram*& prog);
264 _mVUt extern void* mVUsearchProg(u32 startPC, uptr pState);
265 _mVUt extern microProgram* mVUfindLeastUsedProg();
266 extern void* __fastcall mVUexecuteVU0(u32 startPC, u32 cycles);
267 extern void* __fastcall mVUexecuteVU1(u32 startPC, u32 cycles);
268
269 // recCall Function Pointer
270 typedef void (__fastcall *mVUrecCall)(u32, u32);
271

  ViewVC Help
Powered by ViewVC 1.1.22