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

Annotation of /trunk/pcsx2/R3000A.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (hide annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (10 years, 2 months ago) by william
File size: 7909 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    
17     #include "PrecompiledHeader.h"
18     #include "IopCommon.h"
19    
20     #include "Sio.h"
21     #include "Sif.h"
22    
23     using namespace R3000A;
24    
25     R3000Acpu *psxCpu;
26    
27     // used for constant propagation
28     u32 g_psxConstRegs[32];
29     u32 g_psxHasConstReg, g_psxFlushedConstReg;
30    
31     // Controls when branch tests are performed.
32 william 62 u32 g_iopNextEventCycle = 0;
33 william 31
34     // This value is used when the IOP execution is broken to return control to the EE.
35     // (which happens when the IOP throws EE-bound interrupts). It holds the value of
36 william 62 // iopCycleEE (which is set to zero to facilitate the code break), so that the unrun
37 william 31 // cycles can be accounted for later.
38 william 62 s32 iopBreak = 0;
39 william 31
40     // tracks the IOP's current sync status with the EE. When it dips below zero,
41     // control is returned to the EE.
42 william 62 s32 iopCycleEE = -1;
43 william 31
44     // Used to signal to the EE when important actions that need IOP-attention have
45     // happened (hsyncs, vsyncs, IOP exceptions, etc). IOP runs code whenever this
46     // is true, even if it's already running ahead a bit.
47 william 62 bool iopEventAction = false;
48 william 31
49     bool iopEventTestIsActive = false;
50    
51     __aligned16 psxRegisters psxRegs;
52    
53     void psxReset()
54     {
55     memzero(psxRegs);
56    
57     psxRegs.pc = 0xbfc00000; // Start in bootstrap
58     psxRegs.CP0.n.Status = 0x10900000; // COP0 enabled | BEV = 1 | TS = 1
59     psxRegs.CP0.n.PRid = 0x0000001f; // PRevID = Revision ID, same as the IOP R3000A
60    
61 william 62 iopBreak = 0;
62     iopCycleEE = -1;
63     g_iopNextEventCycle = psxRegs.cycle + 4;
64 william 31
65     psxHwReset();
66    
67     ioman::reset();
68     }
69    
70     void psxShutdown() {
71     //psxCpu->Shutdown();
72     }
73    
74     void __fastcall psxException(u32 code, u32 bd)
75     {
76     // PSXCPU_LOG("psxException %x: %x, %x", code, psxHu32(0x1070), psxHu32(0x1074));
77     //Console.WriteLn("!! psxException %x: %x, %x", code, psxHu32(0x1070), psxHu32(0x1074));
78     // Set the Cause
79     psxRegs.CP0.n.Cause &= ~0x7f;
80     psxRegs.CP0.n.Cause |= code;
81    
82     // Set the EPC & PC
83     if (bd)
84     {
85     PSXCPU_LOG("bd set");
86     psxRegs.CP0.n.Cause|= 0x80000000;
87     psxRegs.CP0.n.EPC = (psxRegs.pc - 4);
88     }
89     else
90     psxRegs.CP0.n.EPC = (psxRegs.pc);
91    
92     if (psxRegs.CP0.n.Status & 0x400000)
93     psxRegs.pc = 0xbfc00180;
94     else
95     psxRegs.pc = 0x80000080;
96    
97     // Set the Status
98     psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status &~0x3f) |
99     ((psxRegs.CP0.n.Status & 0xf) << 2);
100    
101     /*if ((((PSXMu32(psxRegs.CP0.n.EPC) >> 24) & 0xfe) == 0x4a)) {
102     // "hokuto no ken" / "Crash Bandicot 2" ... fix
103     PSXMu32(psxRegs.CP0.n.EPC)&= ~0x02000000;
104     }*/
105    
106     /*if (psxRegs.CP0.n.Cause == 0x400 && (!(psxHu32(0x1450) & 0x8))) {
107     hwIntcIrq(INTC_SBUS);
108     }*/
109     }
110    
111 william 62 __fi void psxSetNextBranch( u32 startCycle, s32 delta )
112 william 31 {
113     // typecast the conditional to signed so that things don't blow up
114     // if startCycle is greater than our next branch cycle.
115    
116 william 62 if( (int)(g_iopNextEventCycle - startCycle) > delta )
117     g_iopNextEventCycle = startCycle + delta;
118 william 31 }
119    
120 william 62 __fi void psxSetNextBranchDelta( s32 delta )
121 william 31 {
122     psxSetNextBranch( psxRegs.cycle, delta );
123     }
124    
125 william 62 __fi int psxTestCycle( u32 startCycle, s32 delta )
126 william 31 {
127     // typecast the conditional to signed so that things don't explode
128     // if the startCycle is ahead of our current cpu cycle.
129    
130     return (int)(psxRegs.cycle - startCycle) >= delta;
131     }
132    
133 william 62 __fi void PSX_INT( IopEventId n, s32 ecycle )
134 william 31 {
135     // Generally speaking games shouldn't throw ints that haven't been cleared yet.
136     // It's usually indicative of something amiss in our emulation, so uncomment this
137     // code to help trap those sort of things.
138    
139     // Exception: IRQ16 - SIO - it drops ints like crazy when handling PAD stuff.
140     if( /*n!=16 &&*/ psxRegs.interrupt & (1<<n) )
141     DevCon.Warning( "***** IOP > Twice-thrown int on IRQ %d", n );
142    
143     // 19 is CDVD read int, it's supposed to be high.
144     //if (ecycle > 8192 && n != 19)
145     // DevCon.Warning( "IOP cycles high: %d, n %d", ecycle, n );
146    
147     psxRegs.interrupt |= 1 << n;
148    
149     psxRegs.sCycle[n] = psxRegs.cycle;
150     psxRegs.eCycle[n] = ecycle;
151    
152     psxSetNextBranchDelta( ecycle );
153    
154 william 62 if( iopCycleEE < 0 )
155 william 31 {
156     // The EE called this int, so inform it to branch as needed:
157     // fixme - this doesn't take into account EE/IOP sync (the IOP may be running
158     // ahead or behind the EE as per the EEsCycles value)
159 william 62 s32 iopDelta = (g_iopNextEventCycle-psxRegs.cycle)*8;
160     cpuSetNextEventDelta( iopDelta );
161 william 31 }
162     }
163    
164 william 62 static __fi void IopTestEvent( IopEventId n, void (*callback)() )
165 william 31 {
166     if( !(psxRegs.interrupt & (1 << n)) ) return;
167    
168     if( psxTestCycle( psxRegs.sCycle[n], psxRegs.eCycle[n] ) )
169     {
170     psxRegs.interrupt &= ~(1 << n);
171     callback();
172     }
173     else
174     psxSetNextBranch( psxRegs.sCycle[n], psxRegs.eCycle[n] );
175     }
176    
177 william 62 static __fi void sifHackInterrupt()
178 william 31 {
179     // No reason -- just that sometimes the SIF fell asleep, and this wakes it up.
180    
181     iopIntcIrq( 3 ); // IOP DMAC int
182     //hwIntcIrq(INTC_SBUS); // EE's SIF BUS notifier... maybe or maybe not needed?
183    
184     // hack is rescheduled as needed by the event handler (depending on if it's actively
185     // signalling an interrupt or not).. better there than here.
186     //PSX_INT( IopEvt_SIFhack, 128 );
187     }
188    
189 william 62 static __fi void _psxTestInterrupts()
190 william 31 {
191     IopTestEvent(IopEvt_SIF0, sif0Interrupt); // SIF0
192     IopTestEvent(IopEvt_SIF1, sif1Interrupt); // SIF1
193     #ifndef SIO_INLINE_IRQS
194     IopTestEvent(IopEvt_SIO, sioInterrupt);
195     #endif
196     IopTestEvent(IopEvt_CdvdRead, cdvdReadInterrupt);
197    
198     // Profile-guided Optimization (sorta)
199     // The following ints are rarely called. Encasing them in a conditional
200     // as follows helps speed up most games.
201    
202     if( psxRegs.interrupt & ( (1ul<<5) | (3ul<<11) | (3ul<<20) | (3ul<<17) ) )
203     {
204     IopTestEvent(IopEvt_Cdvd, cdvdActionInterrupt);
205     IopTestEvent(IopEvt_Dma11, psxDMA11Interrupt); // SIO2
206     IopTestEvent(IopEvt_Dma12, psxDMA12Interrupt); // SIO2
207     IopTestEvent(IopEvt_Cdrom, cdrInterrupt);
208     IopTestEvent(IopEvt_CdromRead, cdrReadInterrupt);
209     IopTestEvent(IopEvt_DEV9, dev9Interrupt);
210     IopTestEvent(IopEvt_USB, usbInterrupt);
211     }
212     }
213    
214 william 62 __ri void iopEventTest()
215 william 31 {
216     if( psxTestCycle( psxNextsCounter, psxNextCounter ) )
217     {
218     psxRcntUpdate();
219 william 62 iopEventAction = true;
220 william 31 }
221     else
222     {
223     // start the next branch at the next counter event by default
224     // the interrupt code below will assign nearer branches if needed.
225 william 62 g_iopNextEventCycle = psxNextsCounter+psxNextCounter;
226 william 31 }
227    
228    
229     if (psxRegs.interrupt)
230     {
231     iopEventTestIsActive = true;
232     _psxTestInterrupts();
233     iopEventTestIsActive = false;
234     }
235    
236     if( (psxHu32(0x1078) != 0) && ((psxHu32(0x1070) & psxHu32(0x1074)) != 0) )
237     {
238     if( (psxRegs.CP0.n.Status & 0xFE01) >= 0x401 )
239     {
240     PSXCPU_LOG("Interrupt: %x %x", psxHu32(0x1070), psxHu32(0x1074));
241     psxException(0, 0);
242 william 62 iopEventAction = true;
243 william 31
244     // No need to execute the SIFhack after cpuExceptions, since these by nature break SIF's
245     // thread sleep hangs and allow the IOP to "come back to life."
246     psxRegs.interrupt &= ~IopEvt_SIFhack;
247     }
248     }
249     }
250    
251     void iopTestIntc()
252     {
253     if( psxHu32(0x1078) == 0 ) return;
254     if( (psxHu32(0x1070) & psxHu32(0x1074)) == 0 ) return;
255    
256     if( !eeEventTestIsActive )
257     {
258     // An iop exception has occurred while the EE is running code.
259     // Inform the EE to branch so the IOP can handle it promptly:
260    
261 william 62 cpuSetNextEventDelta( 16 );
262     iopEventAction = true;
263     //Console.Error( "** IOP Needs an EE EventText, kthx ** %d", iopCycleEE );
264 william 31
265     // Note: No need to set the iop's branch delta here, since the EE
266     // will run an IOP branch test regardless.
267     }
268     else if( !iopEventTestIsActive )
269     psxSetNextBranchDelta( 2 );
270     }
271    

  ViewVC Help
Powered by ViewVC 1.1.22