/[pcsx2_0.9.7]/trunk/pcsx2/SPR.cpp
ViewVC logotype

Annotation of /trunk/pcsx2/SPR.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (hide annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (10 years, 4 months ago) by william
File size: 10089 byte(s)
Auto Commited Import of: pcsx2-0.9.7-r3738-debug in ./trunk
1 william 31 /* 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     #include "PrecompiledHeader.h"
17     #include "Common.h"
18    
19     #include "SPR.h"
20     #include "VUmicro.h"
21    
22     extern void mfifoGIFtransfer(int);
23    
24     static bool spr0finished = false;
25     static bool spr1finished = false;
26    
27     static u32 mfifotransferred = 0;
28    
29     void sprInit()
30     {
31     }
32    
33     static void TestClearVUs(u32 madr, u32 size)
34     {
35     if (madr >= 0x11000000)
36     {
37     if (madr < 0x11004000)
38     {
39     DbgCon.Warning("scratch pad clearing vu0");
40     CpuVU0->Clear(madr&0xfff, size);
41     }
42     else if (madr >= 0x11008000 && madr < 0x1100c000)
43     {
44     DbgCon.Warning("scratch pad clearing vu1");
45     CpuVU1->Clear(madr&0x3fff, size);
46     }
47     }
48     }
49    
50     int _SPR0chain()
51     {
52     tDMA_TAG *pMem;
53    
54 william 62 if (spr0ch.qwc == 0) return 0;
55     pMem = SPRdmaGetAddr(spr0ch.madr, true);
56 william 31 if (pMem == NULL) return -1;
57    
58 william 62 switch (dmacRegs.ctrl.MFD)
59 william 31 {
60     case MFD_VIF1:
61     case MFD_GIF:
62 william 62 if ((spr0ch.madr & ~dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR)
63 william 31 Console.WriteLn("SPR MFIFO Write outside MFIFO area");
64     else
65 william 62 mfifotransferred += spr0ch.qwc;
66 william 31
67 william 62 hwMFIFOWrite(spr0ch.madr, &psSu128(spr0ch.sadr), spr0ch.qwc);
68     spr0ch.madr += spr0ch.qwc << 4;
69     spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK);
70 william 31 break;
71    
72     case NO_MFD:
73     case MFD_RESERVED:
74 william 62 memcpy_qwc(pMem, &psSu128(spr0ch.sadr), spr0ch.qwc);
75 william 31
76     // clear VU mem also!
77 william 62 TestClearVUs(spr0ch.madr, spr0ch.qwc << 2); // Wtf is going on here? AFAIK, only VIF should affect VU micromem (cottonvibes)
78     spr0ch.madr += spr0ch.qwc << 4;
79 william 31 break;
80     }
81    
82 william 62 spr0ch.sadr += spr0ch.qwc << 4;
83 william 31
84 william 62 return (spr0ch.qwc); // bus is 1/2 the ee speed
85 william 31 }
86    
87 william 62 __fi void SPR0chain()
88 william 31 {
89 william 62 CPU_INT(DMAC_FROM_SPR, _SPR0chain() / BIAS);
90     spr0ch.qwc = 0;
91 william 31 }
92    
93     void _SPR0interleave()
94     {
95 william 62 int qwc = spr0ch.qwc;
96     int sqwc = dmacRegs.sqwc.SQWC;
97     int tqwc = dmacRegs.sqwc.TQWC;
98 william 31 tDMA_TAG *pMem;
99    
100     if (tqwc == 0) tqwc = qwc;
101     //Console.WriteLn("dmaSPR0 interleave");
102     SPR_LOG("SPR0 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
103 william 62 spr0ch.qwc, tqwc, sqwc, spr0ch.madr, spr0ch.sadr);
104 william 31
105 william 62 CPU_INT(DMAC_FROM_SPR, qwc / BIAS);
106    
107 william 31 while (qwc > 0)
108     {
109 william 62 spr0ch.qwc = std::min(tqwc, qwc);
110     qwc -= spr0ch.qwc;
111     pMem = SPRdmaGetAddr(spr0ch.madr, true);
112 william 31
113 william 62 switch (dmacRegs.ctrl.MFD)
114 william 31 {
115     case MFD_VIF1:
116     case MFD_GIF:
117 william 62 hwMFIFOWrite(spr0ch.madr, &psSu128(spr0ch.sadr), spr0ch.qwc);
118     mfifotransferred += spr0ch.qwc;
119 william 31 break;
120    
121     case NO_MFD:
122     case MFD_RESERVED:
123     // clear VU mem also!
124 william 62 TestClearVUs(spr0ch.madr, spr0ch.qwc << 2);
125     memcpy_qwc(pMem, &psSu128(spr0ch.sadr), spr0ch.qwc);
126 william 31 break;
127     }
128 william 62 spr0ch.sadr += spr0ch.qwc * 16;
129     spr0ch.madr += (sqwc + spr0ch.qwc) * 16;
130 william 31 }
131    
132 william 62 spr0ch.qwc = 0;
133 william 31 }
134    
135 william 62 static __fi void _dmaSPR0()
136 william 31 {
137 william 62 if (dmacRegs.ctrl.STS == STS_fromSPR)
138 william 31 {
139 william 62 Console.WriteLn("SPR0 stall %d", dmacRegs.ctrl.STS);
140 william 31 }
141    
142     // Transfer Dn_QWC from SPR to Dn_MADR
143 william 62 switch(spr0ch.chcr.MOD)
144 william 31 {
145     case NORMAL_MODE:
146     {
147     SPR0chain();
148     spr0finished = true;
149     return;
150     }
151     case CHAIN_MODE:
152     {
153     tDMA_TAG *ptag;
154 william 62 bool done = false;
155 william 31
156 william 62 if (spr0ch.qwc > 0)
157 william 31 {
158     SPR0chain();
159     return;
160     }
161     // Destination Chain Mode
162 william 62 ptag = (tDMA_TAG*)&psSu32(spr0ch.sadr);
163     spr0ch.sadr += 16;
164 william 31
165 william 62 spr0ch.unsafeTransfer(ptag);
166 william 31
167 william 62 spr0ch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
168 william 31
169     SPR_LOG("spr0 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx",
170 william 62 ptag[1]._u32, ptag[0]._u32, spr0ch.qwc, ptag->ID, spr0ch.madr, spr0ch.sadr);
171 william 31
172 william 62 if (dmacRegs.ctrl.STS == STS_fromSPR) // STS == fromSPR
173 william 31 {
174     Console.WriteLn("SPR stall control");
175     }
176    
177     switch (ptag->ID)
178     {
179     case TAG_CNTS: // CNTS - Transfer QWC following the tag (Stall Control)
180 william 62 if (dmacRegs.ctrl.STS == STS_fromSPR) dmacRegs.stadr.ADDR = spr0ch.madr + (spr0ch.qwc * 16); //Copy MADR to DMAC_STADR stall addr register
181 william 31 break;
182    
183     case TAG_CNT: // CNT - Transfer QWC following the tag.
184     done = false;
185     break;
186    
187     case TAG_END: // End - Transfer QWC following the tag
188     done = true;
189     break;
190     }
191    
192     SPR0chain();
193    
194 william 62 if (spr0ch.chcr.TIE && ptag->IRQ) //Check TIE bit of CHCR and IRQ bit of tag
195 william 31 {
196     //Console.WriteLn("SPR0 TIE");
197     done = true;
198     }
199    
200     spr0finished = done;
201     SPR_LOG("spr0 dmaChain complete %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx",
202 william 62 ptag[1]._u32, ptag[0]._u32, spr0ch.qwc, ptag->ID, spr0ch.madr);
203 william 31 break;
204     }
205     //case INTERLEAVE_MODE:
206     default:
207     {
208     _SPR0interleave();
209 william 62 spr0finished = true;
210 william 31 break;
211     }
212     }
213     }
214    
215     void SPRFROMinterrupt()
216     {
217 william 62
218     if (!spr0finished || spr0ch.qwc > 0)
219     {
220     _dmaSPR0();
221 william 31
222 william 62 if(mfifotransferred != 0)
223 william 31 {
224 william 62 switch (dmacRegs.ctrl.MFD)
225 william 31 {
226 william 62 case MFD_VIF1: // Most common case.
227     {
228     if ((spr0ch.madr & ~dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR) Console.WriteLn("VIF MFIFO Write outside MFIFO area");
229     spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK);
230     //Console.WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", vif1ch.chcr._u32, vif1ch.madr, vif1ch.tadr);
231     mfifoVIF1transfer(mfifotransferred);
232     mfifotransferred = 0;
233     break;
234     }
235     case MFD_GIF:
236     {
237     if ((spr0ch.madr & ~dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR) Console.WriteLn("GIF MFIFO Write outside MFIFO area");
238     spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK);
239     //Console.WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr);
240     mfifoGIFtransfer(mfifotransferred);
241     mfifotransferred = 0;
242     break;
243     }
244     default:
245     break;
246 william 31 }
247     }
248 william 62 return;
249 william 31 }
250    
251    
252 william 62 spr0ch.chcr.STR = false;
253 william 31 hwDmacIrq(DMAC_FROM_SPR);
254     }
255    
256     void dmaSPR0() // fromSPR
257     {
258     SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx",
259 william 62 spr0ch.chcr._u32, spr0ch.madr, spr0ch.qwc, spr0ch.sadr);
260 william 31
261 william 62
262     spr0finished = false; //Init
263    
264     if(spr0ch.chcr.MOD == CHAIN_MODE && spr0ch.qwc > 0)
265 william 31 {
266 william 62 //DevCon.Warning(L"SPR0 QWC on Chain " + spr0ch.chcr.desc());
267     if (spr0ch.chcr.tag().ID == TAG_END) // but not TAG_REFE?
268     {
269     spr0finished = true;
270     }
271 william 31 }
272 william 62
273     SPRFROMinterrupt();
274 william 31 }
275    
276 william 62 __fi static void SPR1transfer(const void* data, int qwc)
277 william 31 {
278 william 62 memcpy_qwc(&psSu128(spr1ch.sadr), data, qwc);
279     spr1ch.sadr += qwc * 16;
280 william 31 }
281    
282     int _SPR1chain()
283     {
284     tDMA_TAG *pMem;
285    
286 william 62 if (spr1ch.qwc == 0) return 0;
287 william 31
288 william 62 pMem = SPRdmaGetAddr(spr1ch.madr, false);
289 william 31 if (pMem == NULL) return -1;
290    
291 william 62 SPR1transfer(pMem, spr1ch.qwc);
292     spr1ch.madr += spr1ch.qwc * 16;
293 william 31
294 william 62 return (spr1ch.qwc);
295 william 31 }
296    
297 william 62 __fi void SPR1chain()
298 william 31 {
299 william 62 CPU_INT(DMAC_TO_SPR, _SPR1chain() / BIAS);
300     spr1ch.qwc = 0;
301 william 31 }
302    
303     void _SPR1interleave()
304     {
305 william 62 int qwc = spr1ch.qwc;
306     int sqwc = dmacRegs.sqwc.SQWC;
307     int tqwc = dmacRegs.sqwc.TQWC;
308 william 31 tDMA_TAG *pMem;
309    
310     if (tqwc == 0) tqwc = qwc;
311     SPR_LOG("SPR1 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
312 william 62 spr1ch.qwc, tqwc, sqwc, spr1ch.madr, spr1ch.sadr);
313     CPU_INT(DMAC_TO_SPR, qwc / BIAS);
314 william 31 while (qwc > 0)
315     {
316 william 62 spr1ch.qwc = std::min(tqwc, qwc);
317     qwc -= spr1ch.qwc;
318     pMem = SPRdmaGetAddr(spr1ch.madr, false);
319     memcpy_qwc(&psSu128(spr1ch.sadr), pMem, spr1ch.qwc);
320     spr1ch.sadr += spr1ch.qwc * 16;
321     spr1ch.madr += (sqwc + spr1ch.qwc) * 16;
322 william 31 }
323    
324 william 62 spr1ch.qwc = 0;
325 william 31 }
326    
327     void _dmaSPR1() // toSPR work function
328     {
329 william 62 switch(spr1ch.chcr.MOD)
330 william 31 {
331     case NORMAL_MODE:
332     {
333     //int cycles = 0;
334     // Transfer Dn_QWC from Dn_MADR to SPR1
335     SPR1chain();
336     spr1finished = true;
337     return;
338     }
339     case CHAIN_MODE:
340     {
341     tDMA_TAG *ptag;
342     bool done = false;
343    
344 william 62 if (spr1ch.qwc > 0)
345 william 31 {
346 william 62 SPR_LOG("spr1 Normal or in Progress size=%d, addr=%lx taddr=%lx saddr=%lx", spr1ch.qwc, spr1ch.madr, spr1ch.tadr, spr1ch.sadr);
347 william 31 // Transfer Dn_QWC from Dn_MADR to SPR1
348     SPR1chain();
349     return;
350     }
351     // Chain Mode
352    
353 william 62 ptag = SPRdmaGetAddr(spr1ch.tadr, false); //Set memory pointer to TADR
354 william 31
355 william 62 if (!spr1ch.transfer("SPR1 Tag", ptag))
356 william 31 {
357     done = true;
358     spr1finished = done;
359     }
360    
361 william 62 spr1ch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
362 william 31
363     // Transfer dma tag if tte is set
364 william 62 if (spr1ch.chcr.TTE)
365 william 31 {
366     SPR_LOG("SPR TTE: %x_%x\n", ptag[3]._u32, ptag[2]._u32);
367 william 62 SPR1transfer(ptag, 1); //Transfer Tag
368 william 31 }
369    
370 william 62 SPR_LOG("spr1 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx taddr=%lx saddr=%lx",
371     ptag[1]._u32, ptag[0]._u32, spr1ch.qwc, ptag->ID, spr1ch.madr, spr1ch.tadr, spr1ch.sadr);
372 william 31
373 william 62 done = (hwDmacSrcChain(spr1ch, ptag->ID));
374 william 31 SPR1chain(); //Transfers the data set by the switch
375    
376 william 62 if (spr1ch.chcr.TIE && ptag->IRQ) //Check TIE bit of CHCR and IRQ bit of tag
377 william 31 {
378     SPR_LOG("dmaIrq Set");
379    
380     //Console.WriteLn("SPR1 TIE");
381     done = true;
382     }
383    
384     spr1finished = done;
385     break;
386     }
387     //case INTERLEAVE_MODE:
388     default:
389     {
390     _SPR1interleave();
391 william 62 spr1finished = true;
392 william 31 break;
393     }
394     }
395     }
396    
397     void dmaSPR1() // toSPR
398     {
399     SPR_LOG("dmaSPR1 chcr = 0x%x, madr = 0x%x, qwc = 0x%x\n"
400     " tadr = 0x%x, sadr = 0x%x",
401 william 62 spr1ch.chcr._u32, spr1ch.madr, spr1ch.qwc,
402     spr1ch.tadr, spr1ch.sadr);
403    
404     spr1finished = false; //Init
405    
406     if(spr1ch.chcr.MOD == CHAIN_MODE && spr1ch.qwc > 0)
407 william 31 {
408 william 62 //DevCon.Warning(L"SPR1 QWC on Chain " + spr1ch.chcr.desc());
409     if ((spr1ch.chcr.tag().ID == TAG_END) || (spr1ch.chcr.tag().ID == TAG_REFE))
410     {
411     spr1finished = true;
412     }
413 william 31 }
414 william 62
415     SPRTOinterrupt();
416 william 31 }
417    
418     void SPRTOinterrupt()
419     {
420 william 62 SPR_LOG("SPR1 Interrupt");
421     if (!spr1finished || spr1ch.qwc > 0)
422     {
423     _dmaSPR1();
424     return;
425     }
426 william 31
427 william 62 SPR_LOG("SPR1 End");
428     spr1ch.chcr.STR = false;
429 william 31 hwDmacIrq(DMAC_TO_SPR);
430     }
431    
432     void SaveStateBase::sprFreeze()
433     {
434     FreezeTag("SPRdma");
435    
436     Freeze(spr0finished);
437     Freeze(spr1finished);
438     Freeze(mfifotransferred);
439     }

  ViewVC Help
Powered by ViewVC 1.1.22