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

Contents of /trunk/pcsx2/x86/microVU_Branch.inl

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 size: 6930 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
18 extern bool doEarlyExit (microVU* mVU);
19 extern void mVUincCycles(microVU* mVU, int x);
20 extern void* mVUcompile (microVU* mVU, u32 startPC, uptr pState);
21
22 #define blockCreate(addr) { if (!mVUblocks[addr]) mVUblocks[addr] = new microBlockManager(); }
23 #define sI ((mVUpBlock->pState.needExactMatch & 1) ? 3 : ((mVUpBlock->pState.flags >> 0) & 3))
24 #define cI ((mVUpBlock->pState.needExactMatch & 4) ? 3 : ((mVUpBlock->pState.flags >> 2) & 3))
25
26 void mVU0clearlpStateJIT() { if (!microVU0.prog.cleared) memzero(microVU0.prog.lpState); }
27 void mVU1clearlpStateJIT() { if (!microVU1.prog.cleared) memzero(microVU1.prog.lpState); }
28
29 void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) {
30
31 int fStatus = (isEbit) ? findFlagInst(mFC->xStatus, 0x7fffffff) : sI;
32 int fMac = (isEbit) ? findFlagInst(mFC->xMac, 0x7fffffff) : 0;
33 int fClip = (isEbit) ? findFlagInst(mFC->xClip, 0x7fffffff) : cI;
34 int qInst = 0;
35 int pInst = 0;
36 mVU->regAlloc->flushAll();
37
38 if (isEbit) {
39 memzero(mVUinfo);
40 memzero(mVUregsTemp);
41 mVUincCycles(mVU, 100); // Ensures Valid P/Q instances (And sets all cycle data to 0)
42 mVUcycles -= 100;
43 qInst = mVU->q;
44 pInst = mVU->p;
45 if (mVUinfo.doDivFlag) {
46 sFLAG.doFlag = 1;
47 sFLAG.write = fStatus;
48 mVUdivSet(mVU);
49 }
50 if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); }
51 if (doEarlyExit(mVU)) {
52 if (!isVU1) xCALL(mVU0clearlpStateJIT);
53 else xCALL(mVU1clearlpStateJIT);
54 }
55 }
56
57 // Save P/Q Regs
58 if (qInst) { xPSHUF.D(xmmPQ, xmmPQ, 0xe5); }
59 xMOVSS(ptr32[&mVU->regs().VI[REG_Q].UL], xmmPQ);
60 if (isVU1) {
61 xPSHUF.D(xmmPQ, xmmPQ, pInst ? 3 : 2);
62 xMOVSS(ptr32[&mVU->regs().VI[REG_P].UL], xmmPQ);
63 }
64
65 // Save Flag Instances
66 #if 1 // CHECK_MACROVU0 - Always on now
67 xMOV(ptr32[&mVU->regs().VI[REG_STATUS_FLAG].UL], getFlagReg(fStatus));
68 #else
69 mVUallocSFLAGc(gprT1, gprT2, fStatus);
70 xMOV(ptr32[&mVU->regs().VI[REG_STATUS_FLAG].UL], gprT1);
71 #endif
72 mVUallocMFLAGa(mVU, gprT1, fMac);
73 mVUallocCFLAGa(mVU, gprT2, fClip);
74 xMOV(ptr32[&mVU->regs().VI[REG_MAC_FLAG].UL], gprT1);
75 xMOV(ptr32[&mVU->regs().VI[REG_CLIP_FLAG].UL], gprT2);
76
77 if (isEbit || isVU1) { // Clear 'is busy' Flags
78 xAND(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag
79 xAND(ptr32[&mVU->getVifRegs().stat], ~VIF1_STAT_VEW); // Clear VU 'is busy' signal for vif
80 }
81
82 if (isEbit != 2) { // Save PC, and Jump to Exit Point
83 xMOV(ptr32[&mVU->regs().VI[REG_TPC].UL], xPC);
84 xJMP(mVU->exitFunct);
85 }
86 }
87
88 // Recompiles Code for Proper Flags and Q/P regs on Block Linkings
89 void mVUsetupBranch(mV, microFlagCycles& mFC) {
90
91 mVU->regAlloc->flushAll(); // Flush Allocated Regs
92 mVUsetupFlags(mVU, mFC); // Shuffle Flag Instances
93
94 // Shuffle P/Q regs since every block starts at instance #0
95 if (mVU->p || mVU->q) { xPSHUF.D(xmmPQ, xmmPQ, shufflePQ); }
96 }
97
98 void normBranchCompile(microVU* mVU, u32 branchPC) {
99 microBlock* pBlock;
100 blockCreate(branchPC/8);
101 pBlock = mVUblocks[branchPC/8]->search((microRegInfo*)&mVUregs);
102 if (pBlock) { xJMP(pBlock->x86ptrStart); }
103 else { mVUcompile(mVU, branchPC, (uptr)&mVUregs); }
104 }
105
106 void normJumpCompile(mV, microFlagCycles& mFC, bool isEvilJump) {
107 memcpy_const(&mVUpBlock->pStateEnd, &mVUregs, sizeof(microRegInfo));
108 mVUsetupBranch(mVU, mFC);
109 mVUbackupRegs(mVU);
110
111 if(!mVUpBlock->jumpCache) { // Create the jump cache for this block
112 mVUpBlock->jumpCache = new microJumpCache[mProgSize/2];
113 }
114
115 if (isEvilJump) xMOV(gprT2, ptr32[&mVU->evilBranch]);
116 else xMOV(gprT2, ptr32[&mVU->branch]);
117 if (doJumpCaching) xMOV(gprT3, (uptr)mVUpBlock);
118 else xMOV(gprT3, (uptr)&mVUpBlock->pStateEnd);
119
120 if (!mVU->index) xCALL(mVUcompileJIT<0>); //(u32 startPC, uptr pState)
121 else xCALL(mVUcompileJIT<1>);
122
123 mVUrestoreRegs(mVU);
124 xJMP(gprT1); // Jump to rec-code address
125 }
126
127 void normBranch(mV, microFlagCycles& mFC) {
128
129 // E-bit Branch
130 if (mVUup.eBit) { iPC = branchAddr/4; mVUendProgram(mVU, &mFC, 1); return; }
131
132 // Normal Branch
133 mVUsetupBranch(mVU, mFC);
134 normBranchCompile(mVU, branchAddr);
135 }
136
137 void condBranch(mV, microFlagCycles& mFC, int JMPcc) {
138 mVUsetupBranch(mVU, mFC);
139 xCMP(ptr16[&mVU->branch], 0);
140 incPC(3);
141 if (mVUup.eBit) { // Conditional Branch With E-Bit Set
142 mVUendProgram(mVU, &mFC, 2);
143 xForwardJump8 eJMP((JccComparisonType)JMPcc);
144 incPC(1); // Set PC to First instruction of Non-Taken Side
145 xMOV(ptr32[&mVU->regs().VI[REG_TPC].UL], xPC);
146 xJMP(mVU->exitFunct);
147 eJMP.SetTarget();
148 incPC(-4); // Go Back to Branch Opcode to get branchAddr
149 iPC = branchAddr/4;
150 xMOV(ptr32[&mVU->regs().VI[REG_TPC].UL], xPC);
151 xJMP(mVU->exitFunct);
152 return;
153 }
154 else { // Normal Conditional Branch
155 microBlock* bBlock;
156 incPC2(1); // Check if Branch Non-Taken Side has already been recompiled
157 blockCreate(iPC/2);
158 bBlock = mVUblocks[iPC/2]->search((microRegInfo*)&mVUregs);
159 incPC2(-1);
160 if (bBlock) { // Branch non-taken has already been compiled
161 xJcc(xInvertCond((JccComparisonType)JMPcc), bBlock->x86ptrStart);
162 incPC(-3); // Go back to branch opcode (to get branch imm addr)
163 normBranchCompile(mVU, branchAddr);
164 }
165 else {
166 s32* ajmp = xJcc32((JccComparisonType)JMPcc);
167 u32 bPC = iPC; // mVUcompile can modify iPC, mVUpBlock, and mVUregs so back them up
168 microBlock* pBlock = mVUpBlock;
169 memcpy_const(&pBlock->pStateEnd, &mVUregs, sizeof(microRegInfo));
170
171 incPC2(1); // Get PC for branch not-taken
172 mVUcompile(mVU, xPC, (uptr)&mVUregs);
173
174 iPC = bPC;
175 incPC(-3); // Go back to branch opcode (to get branch imm addr)
176 uptr jumpAddr = (uptr)mVUblockFetch(mVU, branchAddr, (uptr)&pBlock->pStateEnd);
177 *ajmp = (jumpAddr - ((uptr)ajmp + 4));
178 }
179 }
180 }
181
182 void normJump(mV, microFlagCycles& mFC) {
183 if (mVUlow.constJump.isValid) { // Jump Address is Constant
184 if (mVUup.eBit) { // E-bit Jump
185 iPC = (mVUlow.constJump.regValue*2) & (mVU->progMemMask);
186 mVUendProgram(mVU, &mFC, 1);
187 return;
188 }
189 int jumpAddr = (mVUlow.constJump.regValue*8)&(mVU->microMemSize-8);
190 mVUsetupBranch(mVU, mFC);
191 normBranchCompile(mVU, jumpAddr);
192 return;
193 }
194
195 if (mVUup.eBit) { // E-bit Jump
196 mVUendProgram(mVU, &mFC, 2);
197 xMOV(gprT1, ptr32[&mVU->branch]);
198 xMOV(ptr32[&mVU->regs().VI[REG_TPC].UL], gprT1);
199 xJMP(mVU->exitFunct);
200 }
201 else normJumpCompile(mVU, mFC, 0);
202 }

  ViewVC Help
Powered by ViewVC 1.1.22