/[pcsx2_0.9.7]/trunk/pcsx2/x86/microVU_Compile.inl
ViewVC logotype

Diff of /trunk/pcsx2/x86/microVU_Compile.inl

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 31 by william, Tue Sep 7 03:24:11 2010 UTC revision 280 by william, Thu Dec 23 12:02:12 2010 UTC
# Line 16  Line 16 
16  #pragma once  #pragma once
17    
18  //------------------------------------------------------------------  //------------------------------------------------------------------
19  // Helper Macros  // Messages Called at Execution Time...
20  //------------------------------------------------------------------  //------------------------------------------------------------------
21    
22  #define calcCycles(reg, x)      { reg = ((reg > x) ? (reg - x) : 0); }  static void __fastcall mVUbadOp0(u32 prog, u32 pc)      { Console.Error("microVU0 Warning: Exiting... Block started with illegal opcode. [%04x] [%x]", pc, prog); }
23  #define optimizeReg(rState) { rState = (rState==1) ? 0 : rState; }  static void __fastcall mVUbadOp1(u32 prog, u32 pc)      { Console.Error("microVU1 Warning: Exiting... Block started with illegal opcode. [%04x] [%x]", pc, prog); }
24  #define tCycles(dest, src)      { dest = aMax(dest, src); }  static void __fastcall mVUwarning0(u32 prog)            { Console.Error("microVU0 Warning: Exiting from Possible Infinite Loop [%04x] [%x]", prog); }
25  #define incP()                          { mVU->p = (mVU->p+1) & 1; }  static void __fastcall mVUwarning1(u32 prog)            { Console.Error("microVU1 Warning: Exiting from Possible Infinite Loop [%04x] [%x]", prog); }
26  #define incQ()                          { mVU->q = (mVU->q+1) & 1; }  static void __fastcall mVUprintPC1(u32 pc)                      { Console.WriteLn("Block Start PC = 0x%04x", pc); }
27  #define doUpperOp()                     { mVUopU(mVU, 1); mVUdivSet(mVU); }  static void __fastcall mVUprintPC2(u32 pc)                      { Console.WriteLn("Block End PC   = 0x%04x", pc); }
 #define doLowerOp()                     { incPC(-1); mVUopL(mVU, 1); incPC(1); }  
28    
29  //------------------------------------------------------------------  //------------------------------------------------------------------
30  // Helper Functions  // Program Range Checking and Setting up Ranges
31  //------------------------------------------------------------------  //------------------------------------------------------------------
32    
33  // Used by mVUsetupRange  // Used by mVUsetupRange
34  _f void mVUcheckIsSame(mV) {  static __fi void mVUcheckIsSame(mV) {
35          if (mVU->prog.isSame == -1) {          if (mVU->prog.isSame == -1) {
36                  mVU->prog.isSame = !memcmp_mmx((u8*)mVUcurProg.data, mVU->regs->Micro, mVU->microMemSize);                  mVU->prog.isSame = !memcmp_mmx((u8*)mVUcurProg.data, mVU->regs().Micro, mVU->microMemSize);
37          }          }
38          if (mVU->prog.isSame == 0) {          if (mVU->prog.isSame == 0) {
39                  if (!isVU1)     mVUcacheProg<0>(*mVU->prog.cur);                  if (!isVU1)     mVUcacheProg<0>(*mVU->prog.cur);
# Line 44  _f void mVUcheckIsSame(mV) { Line 43  _f void mVUcheckIsSame(mV) {
43  }  }
44    
45  // Sets up microProgram PC ranges based on whats been recompiled  // Sets up microProgram PC ranges based on whats been recompiled
46  _f void mVUsetupRange(microVU* mVU, s32 pc, bool isStartPC) {  static void mVUsetupRange(microVU* mVU, s32 pc, bool isStartPC) {
47          deque<microRange>*& ranges = mVUcurProg.ranges;          deque<microRange>*& ranges = mVUcurProg.ranges;
48          pc &= mVU->microMemSize - 8;          pc &= mVU->microMemSize - 8;
49    
50          if (isStartPC) { // Check if startPC is already within a block we've recompiled          if (isStartPC) { // Check if startPC is already within a block we've recompiled
51                  deque<microRange>::const_iterator it = ranges->begin();                  deque<microRange>::const_iterator it(ranges->begin());
52                  for ( ; it != ranges->end(); it++) {                  for ( ; it != ranges->end(); ++it) {
53                          if ((pc >= it[0].start) && (pc <= it[0].end)) {                          if ((pc >= it[0].start) && (pc <= it[0].end)) {
54                                  if (it[0].start != it[0].end)                                  if (it[0].start != it[0].end)
55                                          return; // Last case makes sure its not a 1-opcode EvilBlock                                          return; // Last case makes sure its not a 1-opcode EvilBlock
# Line 71  _f void mVUsetupRange(microVU* mVU, s32 Line 70  _f void mVUsetupRange(microVU* mVU, s32
70                  bool mergedRange = 0;                  bool mergedRange = 0;
71                  s32  rStart = mVUrange.start;                  s32  rStart = mVUrange.start;
72                  s32  rEnd   = mVUrange.end;                  s32  rEnd   = mVUrange.end;
73                  deque<microRange>::iterator it = ranges->begin();                  deque<microRange>::iterator it(ranges->begin());
74                  for (it++; it != ranges->end(); it++) {                  for (++it; it != ranges->end(); ++it) {
75                          if((it[0].start >= rStart) && (it[0].start <= rEnd)) {                          if((it[0].start >= rStart) && (it[0].start <= rEnd)) {
76                                  it[0].end   = aMax(it[0].end, rEnd);                                  it[0].end   = aMax(it[0].end, rEnd);
77                                  mergedRange = 1;                                  mergedRange = 1;
# Line 88  _f void mVUsetupRange(microVU* mVU, s32 Line 87  _f void mVUsetupRange(microVU* mVU, s32
87                  }                  }
88          }          }
89          else {          else {
90                  //DevCon.WriteLn(Color_Green, "microVU%d: Prog Range Wrap [%04x] [%d]", mVU->index, mVUrange.start, mVUrange.end);                  DevCon.WriteLn(Color_Green, "microVU%d: Prog Range Wrap [%04x] [%d]", mVU->index, mVUrange.start, mVUrange.end);
91                  mVUrange.end = mVU->microMemSize;                  mVUrange.end = mVU->microMemSize;
92                  microRange mRange = {0, pc};                  microRange mRange = {0, pc};
93                  ranges->push_front(mRange);                  ranges->push_front(mRange);
94          }          }
95  }  }
96    
97  _f void startLoop(mV) {  //------------------------------------------------------------------
98          if (curI & _Mbit_)      { Console.WriteLn(Color_Green, "microVU%d: M-bit set!", getIndex); }  // Execute VU Opcode/Instruction (Upper and Lower)
99          if (curI & _Dbit_)      { DevCon.WriteLn (Color_Green, "microVU%d: D-bit set!", getIndex); }  //------------------------------------------------------------------
100          if (curI & _Tbit_)      { DevCon.WriteLn (Color_Green, "microVU%d: T-bit set!", getIndex); }  
101          memzero(mVUinfo);  __ri void doUpperOp(mV) { mVUopU(mVU, 1); mVUdivSet(mVU); }
102          memzero(mVUregsTemp);  __ri void doLowerOp(mV) { incPC(-1); mVUopL(mVU, 1); incPC(1); }
103  }  __ri void flushRegs(mV) { if (!doRegAlloc) mVU->regAlloc->flushAll(); }
104    
105  _f void doIbit(mV) {  static void doIbit(mV) {
106          if (mVUup.iBit) {          if (mVUup.iBit) {
107                  incPC(-1);                  incPC(-1);
108                  u32 tempI;                  u32 tempI;
109                  mVU->regAlloc->clearRegVF(33);                  mVU->regAlloc->clearRegVF(33);
110    
111                  if (CHECK_VU_OVERFLOW && ((curI & 0x7fffffff) >= 0x7f800000)) {                  if (CHECK_VU_OVERFLOW && ((curI & 0x7fffffff) >= 0x7f800000)) {
112                          Console.WriteLn(Color_Green,"microVU%d: Clamping I Reg", mVU->index);                          DevCon.WriteLn(Color_Green,"microVU%d: Clamping I Reg", mVU->index);
113                          tempI = (0x80000000 & curI) | 0x7f7fffff; // Clamp I Reg                          tempI = (0x80000000 & curI) | 0x7f7fffff; // Clamp I Reg
114                  }                  }
115                  else tempI = curI;                  else tempI = curI;
116                                    
117                  MOV32ItoM((uptr)&mVU->regs->VI[REG_I].UL, tempI);                  xMOV(ptr32[&mVU->getVI(REG_I)], tempI);
118                  incPC(1);                  incPC(1);
119          }          }
120  }  }
121    
122  _f void doSwapOp(mV) {  static void doSwapOp(mV) {
123          if (mVUinfo.backupVF && !mVUlow.noWriteVF) {          if (mVUinfo.backupVF && !mVUlow.noWriteVF) {
124                  DevCon.WriteLn(Color_Green, "microVU%d: Backing Up VF Reg [%04x]", getIndex, xPC);                  DevCon.WriteLn(Color_Green, "microVU%d: Backing Up VF Reg [%04x]", getIndex, xPC);
125                  int t1 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg);  
126                  int t2 = mVU->regAlloc->allocReg();                  // Allocate t1 first for better chance of reg-alloc
127                  SSE_MOVAPS_XMM_to_XMM(t2, t1);                  const xmm& t1 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg);
128                    const xmm& t2 = mVU->regAlloc->allocReg();
129                    xMOVAPS(t2, t1); // Backup VF reg
130                  mVU->regAlloc->clearNeeded(t1);                  mVU->regAlloc->clearNeeded(t1);
131    
132                  mVUopL(mVU, 1);                  mVUopL(mVU, 1);
133                  t1 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg, mVUlow.VF_write.reg, 0xf, 0);  
134                  SSE_XORPS_XMM_to_XMM(t2, t1);                  const xmm& t3 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg, mVUlow.VF_write.reg, 0xf, 0);
135                  SSE_XORPS_XMM_to_XMM(t1, t2);                  xXOR.PS(t2, t3); // Swap new and old values of the register
136                  SSE_XORPS_XMM_to_XMM(t2, t1);                  xXOR.PS(t3, t2); // Uses xor swap trick...
137                  mVU->regAlloc->clearNeeded(t1);                  xXOR.PS(t2, t3);
138                    mVU->regAlloc->clearNeeded(t3);
139    
140                  incPC(1);                  incPC(1);
141                  doUpperOp();                  doUpperOp(mVU);
142                  t1 = mVU->regAlloc->allocReg(-1, mVUlow.VF_write.reg, 0xf);  
143                  SSE_MOVAPS_XMM_to_XMM(t1, t2);                  const xmm& t4 = mVU->regAlloc->allocReg(-1, mVUlow.VF_write.reg, 0xf);
144                  mVU->regAlloc->clearNeeded(t1);                  xMOVAPS(t4, t2);
145                    mVU->regAlloc->clearNeeded(t4);
146                  mVU->regAlloc->clearNeeded(t2);                  mVU->regAlloc->clearNeeded(t2);
147          }          }
148          else { mVUopL(mVU, 1); incPC(1); doUpperOp(); }          else { mVUopL(mVU, 1); incPC(1); flushRegs(mVU); doUpperOp(mVU); }
149    }
150    
151    static void mVUexecuteInstruction(mV) {
152            if   (mVUlow.isNOP)        { incPC(1); doUpperOp(mVU); flushRegs(mVU); doIbit(mVU);    }
153            elif(!mVUinfo.swapOps) { incPC(1); doUpperOp(mVU); flushRegs(mVU); doLowerOp(mVU); }
154            else doSwapOp(mVU);
155            flushRegs(mVU);
156    }
157    
158    //------------------------------------------------------------------
159    // Warnings / Errors / Illegal Instructions
160    //------------------------------------------------------------------
161    
162    // If 1st op in block is a bad opcode, then don't compile rest of block (Dawn of Mana Level 2)
163    static __fi void mVUcheckBadOp(mV) {
164            if (mVUinfo.isBadOp && mVUcount == 0) {
165                    mVUinfo.isEOB = true;
166                    Console.Warning("microVU Warning: First Instruction of block contains illegal opcode...");
167            }
168  }  }
169    
170  _f void branchWarning(mV) {  // Prints msg when exiting block early if 1st op was a bad opcode (Dawn of Mana Level 2)
171    static __fi void handleBadOp(mV, int count) {
172            if (mVUinfo.isBadOp && count == 0) {
173                    mVUbackupRegs(mVU, true);
174                    xMOV(gprT2, mVU->prog.cur->idx);
175                    xMOV(gprT3, xPC);
176                    if (!isVU1) xCALL(mVUbadOp0);
177                    else            xCALL(mVUbadOp1);
178                    mVUrestoreRegs(mVU, true);
179            }
180    }
181    
182    static __ri void branchWarning(mV) {
183          incPC(-2);          incPC(-2);
184          if (mVUup.eBit && mVUbranch) {          if (mVUup.eBit && mVUbranch) {
185                  incPC(2);                  incPC(2);
# Line 159  _f void branchWarning(mV) { Line 195  _f void branchWarning(mV) {
195          }          }
196  }  }
197    
198  _f void eBitPass1(mV, int& branch) {  static __fi void eBitPass1(mV, int& branch) {
199          if (mVUregs.blockType != 1) {          if (mVUregs.blockType != 1) {
200                  branch = 1;                  branch = 1;
201                  mVUup.eBit = 1;                  mVUup.eBit = 1;
202          }          }
203  }  }
204    
205  _f void eBitWarning(mV) {  static __ri void eBitWarning(mV) {
206          if (mVUpBlock->pState.blockType == 1) Console.Error("microVU%d Warning: Branch, E-bit, Branch! [%04x]",  mVU->index, xPC);          if (mVUpBlock->pState.blockType == 1) Console.Error("microVU%d Warning: Branch, E-bit, Branch! [%04x]",  mVU->index, xPC);
207          if (mVUpBlock->pState.blockType == 2) Console.Error("microVU%d Warning: Branch, Branch, Branch! [%04x]", mVU->index, xPC);          if (mVUpBlock->pState.blockType == 2) Console.Error("microVU%d Warning: Branch, Branch, Branch! [%04x]", mVU->index, xPC);
208          incPC(2);          incPC(2);
# Line 177  _f void eBitWarning(mV) { Line 213  _f void eBitWarning(mV) {
213          incPC(-2);          incPC(-2);
214  }  }
215    
216    //------------------------------------------------------------------
217    // Cycles / Pipeline State / Early Exit from Execution
218    //------------------------------------------------------------------
219    __fi void optimizeReg(u8& rState)        { rState = (rState==1) ? 0 : rState; }
220    __fi void calcCycles(u8& reg, u8 x)      { reg = ((reg > x) ? (reg - x) : 0); }
221    __fi void tCycles(u8& dest, u8& src) { dest = aMax(dest, src); }
222    __fi void incP(mV)                                       { mVU->p ^= 1; }
223    __fi void incQ(mV)                                       { mVU->q ^= 1; }
224    
225  // Optimizes the End Pipeline State Removing Unnecessary Info  // Optimizes the End Pipeline State Removing Unnecessary Info
226  _f void mVUoptimizePipeState(mV) {  // If the cycles remaining is just '1', we don't have to transfer it to the next block
227    // because mVU automatically decrements this number at the start of its loop,
228    // so essentially '1' will be the same as '0'...
229    static void mVUoptimizePipeState(mV) {
230          for (int i = 0; i < 32; i++) {          for (int i = 0; i < 32; i++) {
231                  optimizeReg(mVUregs.VF[i].x);                  optimizeReg(mVUregs.VF[i].x);
232                  optimizeReg(mVUregs.VF[i].y);                  optimizeReg(mVUregs.VF[i].y);
# Line 188  _f void mVUoptimizePipeState(mV) { Line 236  _f void mVUoptimizePipeState(mV) {
236          for (int i = 0; i < 16; i++) {          for (int i = 0; i < 16; i++) {
237                  optimizeReg(mVUregs.VI[i]);                  optimizeReg(mVUregs.VI[i]);
238          }          }
239          if (mVUregs.q) { optimizeReg(mVUregs.q); if (!mVUregs.q) { incQ(); } }          if (mVUregs.q) { optimizeReg(mVUregs.q); if (!mVUregs.q) { incQ(mVU); } }
240          if (mVUregs.p) { optimizeReg(mVUregs.p); if (!mVUregs.p) { incP(); } }          if (mVUregs.p) { optimizeReg(mVUregs.p); if (!mVUregs.p) { incP(mVU); } }
241          mVUregs.r = 0; // There are no stalls on the R-reg, so its Safe to discard info          mVUregs.r = 0; // There are no stalls on the R-reg, so its Safe to discard info
242  }  }
243    
244  _f void mVUincCycles(mV, int x) {  void mVUincCycles(mV, int x) {
245          mVUcycles += x;          mVUcycles += x;
246          for (int z = 31; z > 0; z--) {          for (int z = 31; z > 0; z--) {
247                  calcCycles(mVUregs.VF[z].x, x);                  calcCycles(mVUregs.VF[z].x, x);
# Line 207  _f void mVUincCycles(mV, int x) { Line 255  _f void mVUincCycles(mV, int x) {
255          if (mVUregs.q) {          if (mVUregs.q) {
256                  if (mVUregs.q > 4) { calcCycles(mVUregs.q, x); if (mVUregs.q <= 4) { mVUinfo.doDivFlag = 1; } }                  if (mVUregs.q > 4) { calcCycles(mVUregs.q, x); if (mVUregs.q <= 4) { mVUinfo.doDivFlag = 1; } }
257                  else                       { calcCycles(mVUregs.q, x); }                  else                       { calcCycles(mVUregs.q, x); }
258                  if (!mVUregs.q) { incQ(); }                  if (!mVUregs.q)    { incQ(mVU); }
259          }          }
260          if (mVUregs.p) {          if (mVUregs.p) {
261                  calcCycles(mVUregs.p, x);                  calcCycles(mVUregs.p, x);
262                  if (!mVUregs.p || mVUregsTemp.p) { incP(); }                  if (!mVUregs.p || mVUregsTemp.p) { incP(mVU); }
263          }          }
264          if (mVUregs.xgkick) {          if (mVUregs.xgkick) {
265                  calcCycles(mVUregs.xgkick, x);                  calcCycles(mVUregs.xgkick, x);
# Line 220  _f void mVUincCycles(mV, int x) { Line 268  _f void mVUincCycles(mV, int x) {
268          calcCycles(mVUregs.r, x);          calcCycles(mVUregs.r, x);
269  }  }
270    
271  #define cmpVFregs(VFreg1, VFreg2, xVar) {       \  // Helps check if upper/lower ops read/write to same regs...
272          if (VFreg1.reg == VFreg2.reg) {                 \  void cmpVFregs(microVFreg& VFreg1, microVFreg& VFreg2, bool& xVar) {
273                  if ((VFreg1.x && VFreg2.x)                      \          if (VFreg1.reg == VFreg2.reg) {
274                  ||      (VFreg1.y && VFreg2.y)                  \                  if ((VFreg1.x && VFreg2.x) || (VFreg1.y && VFreg2.y)
275                  ||      (VFreg1.z && VFreg2.z)                  \                  ||      (VFreg1.z && VFreg2.z) || (VFreg1.w && VFreg2.w))
276                  ||      (VFreg1.w && VFreg2.w))                 \                  { xVar = 1; }
277                  { xVar = 1; }                                           \          }
         }                                                                               \  
278  }  }
279    
280  _f void mVUsetCycles(mV) {  void mVUsetCycles(mV) {
281          mVUincCycles(mVU, mVUstall);          mVUincCycles(mVU, mVUstall);
282          // If upper Op && lower Op write to same VF reg:          // If upper Op && lower Op write to same VF reg:
283          if ((mVUregsTemp.VFreg[0] == mVUregsTemp.VFreg[1]) && mVUregsTemp.VFreg[0]) {          if ((mVUregsTemp.VFreg[0] == mVUregsTemp.VFreg[1]) && mVUregsTemp.VFreg[0]) {
# Line 265  _f void mVUsetCycles(mV) { Line 312  _f void mVUsetCycles(mV) {
312          tCycles(mVUregs.xgkick,                                 mVUregsTemp.xgkick);          tCycles(mVUregs.xgkick,                                 mVUregsTemp.xgkick);
313  }  }
314    
315  void __fastcall mVUwarning0(mV)         { Console.Error("microVU0 Warning: Exiting from Possible Infinite Loop [%04x] [%x]", xPC, mVU->prog.cur); }  // Prints Start/End PC of blocks executed, for debugging...
316  void __fastcall mVUwarning1(mV)         { Console.Error("microVU1 Warning: Exiting from Possible Infinite Loop [%04x] [%x]", xPC, mVU->prog.cur); }  static void mVUdebugPrintBlocks(microVU* mVU, bool isEndPC) {
317  void __fastcall mVUprintPC1(u32 PC) { Console.Write("Block PC [%04x] ", PC); }          if (mVUdebugNow) {
318  void __fastcall mVUprintPC2(u32 PC) { Console.Write("[%04x]\n", PC); }                  mVUbackupRegs(mVU, true);
319                    xMOV(gprT2, xPC);
320                    if (isEndPC) xCALL(mVUprintPC2);
321                    else             xCALL(mVUprintPC1);
322                    mVUrestoreRegs(mVU, true);
323            }
324    }
325    
326  // vu0 is allowed to exit early, so are dev builds (for inf loops)  // vu0 is allowed to exit early, so are dev builds (for inf loops)
327  _f bool doEarlyExit(microVU* mVU) {  __fi bool doEarlyExit(microVU* mVU) {
328          return IsDevBuild || !isVU1;          return IsDevBuild || !isVU1;
329  }  }
330    
331  // Saves Pipeline State for resuming from early exits  // Saves Pipeline State for resuming from early exits
332  _f void mVUsavePipelineState(microVU* mVU) {  static __fi void mVUsavePipelineState(microVU* mVU) {
333          u32* lpS = (u32*)&mVU->prog.lpState.vi15;          u32* lpS = (u32*)&mVU->prog.lpState.vi15;
334          for (int i = 0; i < (sizeof(microRegInfo)-4)/4; i++, lpS++) {          for (int i = 0; i < (sizeof(microRegInfo)-4)/4; i++, lpS++) {
335                  MOV32ItoM((uptr)lpS, lpS[0]);                  xMOV(ptr32[lpS], lpS[0]);
336          }          }
337  }  }
338    
339  _f void mVUtestCycles(microVU* mVU) {  // Test cycles to see if we need to exit-early...
340          //u32* vu0jmp;  static void mVUtestCycles(microVU* mVU) {
341          iPC = mVUstartPC;          iPC = mVUstartPC;
         mVUdebugNOW(0);  
342          if (doEarlyExit(mVU)) {          if (doEarlyExit(mVU)) {
343                  CMP32ItoM((uptr)&mVU->cycles, 0);                  xCMP(ptr32[&mVU->cycles], 0);
344                  u32* jmp32 = JG32(0);                  xForwardJG32 skip;
345                  //if (!isVU1) { TEST32ItoM((uptr)&mVU->regs->flags, VUFLAG_MFLAGSET); vu0jmp = JZ32(0); }                  if (isVU0) {
346                          MOV32ItoR(gprT2, (uptr)mVU);                          // TEST32ItoM((uptr)&mVU->regs().flags, VUFLAG_MFLAGSET);
347                          if (isVU1)  CALLFunc((uptr)mVUwarning1);                          // xFowardJZ32 vu0jmp;
348                          //else          CALLFunc((uptr)mVUwarning0); // VU0 is allowed early exit for COP2 Interlock Simulation                          // mVUbackupRegs(mVU, true);
349                            // xMOV(gprT2, mVU->prog.cur->idx);
350                            // xCALL(mVUwarning0); // VU0 is allowed early exit for COP2 Interlock Simulation
351                            // mVUbackupRegs(mVU, true);
352                            mVUsavePipelineState(mVU);
353                            mVUendProgram(mVU, NULL, 0);
354                            // vu0jmp.SetTarget();
355                    }
356                    else {
357                            mVUbackupRegs(mVU, true);
358                            xMOV(gprT2, mVU->prog.cur->idx);
359                            xCALL(mVUwarning1);
360                            mVUbackupRegs(mVU, true);
361                          mVUsavePipelineState(mVU);                          mVUsavePipelineState(mVU);
362                          mVUendProgram(mVU, NULL, 0);                          mVUendProgram(mVU, NULL, 0);
363                  //if (!isVU1) x86SetJ32(vu0jmp);                  }
364                  x86SetJ32(jmp32);                  skip.SetTarget();
365          }          }
366          SUB32ItoM((uptr)&mVU->cycles, mVUcycles);          xSUB(ptr32[&mVU->cycles], mVUcycles);
367    }
368    
369    //------------------------------------------------------------------
370    // Initializing
371    //------------------------------------------------------------------
372    
373    // This gets run at the start of every loop of mVU's first pass
374    static __fi void startLoop(mV) {
375            if (curI & _Mbit_)      { DevCon.WriteLn (Color_Green, "microVU%d: M-bit set!", getIndex); }
376            if (curI & _Dbit_)      { DevCon.WriteLn (Color_Green, "microVU%d: D-bit set!", getIndex); }
377            if (curI & _Tbit_)      { DevCon.WriteLn (Color_Green, "microVU%d: T-bit set!", getIndex); }
378            memzero(mVUinfo);
379            memzero(mVUregsTemp);
380  }  }
381    
382  // Initialize VI Constants (vi15 propagates through blocks)  // Initialize VI Constants (vi15 propagates through blocks)
383  _f void mVUinitConstValues(microVU* mVU) {  static __fi void mVUinitConstValues(microVU* mVU) {
384          for (int i = 0; i < 16; i++) {          for (int i = 0; i < 16; i++) {
385                  mVUconstReg[i].isValid  = 0;                  mVUconstReg[i].isValid  = 0;
386                  mVUconstReg[i].regValue = 0;                  mVUconstReg[i].regValue = 0;
# Line 313  _f void mVUinitConstValues(microVU* mVU) Line 390  _f void mVUinitConstValues(microVU* mVU)
390  }  }
391    
392  // Initialize Variables  // Initialize Variables
393  _f void mVUinitFirstPass(microVU* mVU, uptr pState, u8* thisPtr) {  static __fi void mVUinitFirstPass(microVU* mVU, uptr pState, u8* thisPtr) {
394          mVUstartPC                              = iPC;  // Block Start PC          mVUstartPC                              = iPC;  // Block Start PC
395          mVUbranch                               = 0;    // Branch Type          mVUbranch                               = 0;    // Branch Type
396          mVUcount                                = 0;    // Number of instructions ran          mVUcount                                = 0;    // Number of instructions ran
# Line 327  _f void mVUinitFirstPass(microVU* mVU, u Line 404  _f void mVUinitFirstPass(microVU* mVU, u
404                  memcpy_const((u8*)&mVU->prog.lpState, (u8*)pState, sizeof(microRegInfo));                  memcpy_const((u8*)&mVU->prog.lpState, (u8*)pState, sizeof(microRegInfo));
405          }          }
406          mVUblock.x86ptrStart    = thisPtr;          mVUblock.x86ptrStart    = thisPtr;
407          mVUpBlock                               = mVUblocks[mVUstartPC/2]->add(&mVUblock); // Add this block to block manager          mVUpBlock                               = mVUblocks[mVUstartPC/2]->add(&mVUblock);  // Add this block to block manager
408            mVUregs.needExactMatch  =(mVUregs.blockType || noFlagOpts) ? 7 : 0; // 1-Op blocks should just always set exactMatch (Sly Cooper)
409          mVUregs.blockType               = 0;          mVUregs.blockType               = 0;
410          mVUregs.viBackUp                = 0;          mVUregs.viBackUp                = 0;
411          mVUregs.flags                   = 0;          mVUregs.flags                   = 0;
         mVUregs.needExactMatch  = 0;  
412          mVUsFlagHack                    = CHECK_VU_FLAGHACK;          mVUsFlagHack                    = CHECK_VU_FLAGHACK;
413          mVUinitConstValues(mVU);          mVUinitConstValues(mVU);
414  }  }
# Line 340  _f void mVUinitFirstPass(microVU* mVU, u Line 417  _f void mVUinitFirstPass(microVU* mVU, u
417  // Recompiler  // Recompiler
418  //------------------------------------------------------------------  //------------------------------------------------------------------
419    
420  _r void* mVUcompile(microVU* mVU, u32 startPC, uptr pState) {  void* mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
421                    
422          microFlagCycles mFC;          microFlagCycles mFC;
423          u8*                             thisPtr  = x86Ptr;          u8*                             thisPtr  = x86Ptr;
# Line 348  _r void* mVUcompile(microVU* mVU, u32 st Line 425  _r void* mVUcompile(microVU* mVU, u32 st
425    
426          // First Pass          // First Pass
427          iPC = startPC / 4;          iPC = startPC / 4;
428          mVUsetupRange(mVU, startPC, 1); // Setup Program Bounds/Range          mVUsetupRange(mVU, startPC, 1); // Setup Program Bounds/Range
429          mVU->regAlloc->reset();                 // Reset regAlloc          mVU->regAlloc->reset(); // Reset regAlloc
430          mVUinitFirstPass(mVU, pState, thisPtr);          mVUinitFirstPass(mVU, pState, thisPtr);
431          for (int branch = 0; mVUcount < endCount; mVUcount++) {          for (int branch = 0; mVUcount < endCount; mVUcount++) {
432                  incPC(1);                  incPC(1);
433                  startLoop(mVU);                  startLoop(mVU);
434                  mVUincCycles(mVU, 1);                  mVUincCycles(mVU, 1);
435                  mVUopU(mVU, 0);                  mVUopU(mVU, 0);
436                    mVUcheckBadOp(mVU);
437                  if (curI & _Ebit_)        { eBitPass1(mVU, branch); }                  if (curI & _Ebit_)        { eBitPass1(mVU, branch); }
438                  if (curI & _DTbit_)       { branch = 4; }                  if (curI & _DTbit_)       { branch = 4; }
439                  if (curI & _Mbit_)        { mVUup.mBit = 1; }                  if (curI & _Mbit_)        { mVUup.mBit = 1; }
# Line 373  _r void* mVUcompile(microVU* mVU, u32 st Line 451  _r void* mVUcompile(microVU* mVU, u32 st
451          }          }
452    
453          // Fix up vi15 const info for propagation through blocks          // Fix up vi15 const info for propagation through blocks
454          mVUregs.vi15 = (mVUconstReg[15].isValid && CHECK_VU_CONSTPROP) ? ((1<<31) | (mVUconstReg[15].regValue&0xffff)) : 0;          mVUregs.vi15 = (mVUconstReg[15].isValid && doConstProp) ? ((1<<31) | (mVUconstReg[15].regValue&0xffff)) : 0;
455                    
456          mVUsetFlags(mVU, mFC);     // Sets Up Flag instances          mVUsetFlags(mVU, mFC);     // Sets Up Flag instances
457          mVUoptimizePipeState(mVU); // Optimize the End Pipeline State for nicer Block Linking          mVUoptimizePipeState(mVU); // Optimize the End Pipeline State for nicer Block Linking
458            mVUdebugPrintBlocks(mVU,0);// Prints Start/End PC of blocks executed, for debugging...
459          mVUtestCycles(mVU);                // Update VU Cycles and Exit Early if Necessary          mVUtestCycles(mVU);                // Update VU Cycles and Exit Early if Necessary
460    
461          // Second Pass          // Second Pass
# Line 385  _r void* mVUcompile(microVU* mVU, u32 st Line 464  _r void* mVUcompile(microVU* mVU, u32 st
464          mVUbranch = 0;          mVUbranch = 0;
465          u32 x = 0;          u32 x = 0;
466          for (; x < endCount; x++) {          for (; x < endCount; x++) {
467                  if (mVUinfo.isEOB)                      { x = 0xffff; }                  if (mVUinfo.isEOB)                      { handleBadOp(mVU, x); x = 0xffff; }
468                  if (mVUup.mBit)                         { OR32ItoM((uptr)&mVU->regs->flags, VUFLAG_MFLAGSET); }                  if (mVUup.mBit)                         { xOR(ptr32[&mVU->regs().flags], VUFLAG_MFLAGSET); }
469                  if (mVUlow.isNOP)                       { incPC(1); doUpperOp(); doIbit(mVU); }                  mVUexecuteInstruction(mVU);
                 else if (!mVUinfo.swapOps)      { incPC(1); doUpperOp(); doLowerOp(); }  
                 else                                            { doSwapOp(mVU); }  
470                  if (mVUinfo.doXGKICK)           { mVU_XGKICK_DELAY(mVU, 1); }                  if (mVUinfo.doXGKICK)           { mVU_XGKICK_DELAY(mVU, 1); }
                 if (!doRegAlloc)                        { mVU->regAlloc->flushAll(); }  
471                  if (isEvilBlock)                        { mVUsetupRange(mVU, xPC, 0); normJumpCompile(mVU, mFC, 1); return thisPtr; }                  if (isEvilBlock)                        { mVUsetupRange(mVU, xPC, 0); normJumpCompile(mVU, mFC, 1); return thisPtr; }
472                  else if (!mVUinfo.isBdelay)     { incPC(1); }                  else if (!mVUinfo.isBdelay)     { incPC(1); }
473                  else {                  else {
474                          mVUsetupRange(mVU, xPC, 0);                          mVUsetupRange(mVU, xPC, 0);
475                          mVUdebugNOW(1);                          mVUdebugPrintBlocks(mVU,1);
476                          incPC(-3); // Go back to branch opcode                          incPC(-3); // Go back to branch opcode
477                          switch (mVUlow.branch) {                          switch (mVUlow.branch) {
478                                  case 1: case 2:  normBranch(mVU, mFC);                    return thisPtr; // B/BAL                                  case 1: case 2:  normBranch(mVU, mFC);                    return thisPtr; // B/BAL
# Line 419  _r void* mVUcompile(microVU* mVU, u32 st Line 495  _r void* mVUcompile(microVU* mVU, u32 st
495  }  }
496    
497  // Returns the entry point of the block (compiles it if not found)  // Returns the entry point of the block (compiles it if not found)
498  _f void* mVUentryGet(microVU* mVU, microBlockManager* block, u32 startPC, uptr pState) {  static __fi void* mVUentryGet(microVU* mVU, microBlockManager* block, u32 startPC, uptr pState) {
499          microBlock* pBlock = block->search((microRegInfo*)pState);          microBlock* pBlock = block->search((microRegInfo*)pState);
500          if (pBlock) return pBlock->x86ptrStart;          if (pBlock) return pBlock->x86ptrStart;
501          else        return mVUcompile(mVU, startPC, pState);          else        return mVUcompile(mVU, startPC, pState);
502  }  }
503    
504   // Search for Existing Compiled Block (if found, return x86ptr; else, compile and return x86ptr)   // Search for Existing Compiled Block (if found, return x86ptr; else, compile and return x86ptr)
505  _f void* mVUblockFetch(microVU* mVU, u32 startPC, uptr pState) {  static __fi void* mVUblockFetch(microVU* mVU, u32 startPC, uptr pState) {
506    
507          if (startPC > mVU->microMemSize-8) { DevCon.Error("microVU%d: invalid startPC [%04x]", mVU->index, startPC); }          pxAssumeDev( (startPC & 7) == 0,                        pxsFmt("microVU%d: unaligned startPC=0x%04x", mVU->index, startPC) );
508            pxAssumeDev( startPC < mVU->microMemSize-8,     pxsFmt("microVU%d: invalid startPC=0x%04x", mVU->index, startPC) );
509          startPC    &= mVU->microMemSize-8;          startPC    &= mVU->microMemSize-8;
510    
511          blockCreate(startPC/8);          blockCreate(startPC/8);
# Line 436  _f void* mVUblockFetch(microVU* mVU, u32 Line 513  _f void* mVUblockFetch(microVU* mVU, u32
513  }  }
514    
515  // mVUcompileJIT() - Called By JR/JALR during execution  // mVUcompileJIT() - Called By JR/JALR during execution
516  _mVUt void* __fastcall mVUcompileJIT(u32 startPC, uptr pState) {  _mVUt void* __fastcall mVUcompileJIT(u32 startPC, uptr ptr) {
517          //return mVUblockFetch(mVUx, startPC, pState);          if (doJumpCaching) { // When doJumpCaching, ptr is a microBlock pointer
518          return mVUsearchProg<vuIndex>(startPC, pState); // Find and set correct program                  microVU* mVU = mVUx;
519                    microBlock* pBlock = (microBlock*)ptr;
520                    microJumpCache& jc = pBlock->jumpCache[startPC/8];
521                    if (jc.prog && jc.prog == mVU->prog.quick[startPC/8].prog) return jc.x86ptrStart;
522                    void* v = mVUsearchProg<vuIndex>(startPC, (uptr)&pBlock->pStateEnd);
523                    jc.prog = mVU->prog.quick[startPC/8].prog;
524                    jc.x86ptrStart = v;
525                    return v;
526            }
527            else { // When !doJumpCaching, pBlock param is really a microRegInfo pointer
528                    //return mVUblockFetch(mVUx, startPC, ptr);
529                    return mVUsearchProg<vuIndex>(startPC, ptr); // Find and set correct program
530            }
531  }  }

Legend:
Removed from v.31  
changed lines
  Added in v.280

  ViewVC Help
Powered by ViewVC 1.1.22