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

Contents of /trunk/pcsx2/COP0.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 273 - (show annotations) (download)
Fri Nov 12 01:10:22 2010 UTC (9 years, 3 months ago) by william
File size: 15884 byte(s)
Auto Commited Import of: pcsx2-0.9.7-DEBUG (upstream: v0.9.7.4013 local: v0.9.7.197-latest) in ./trunk
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
17 #include "PrecompiledHeader.h"
18 #include "Common.h"
19
20 u32 s_iLastCOP0Cycle = 0;
21 u32 s_iLastPERFCycle[2] = { 0, 0 };
22
23 // Updates the CPU's mode of operation (either, Kernel, Supervisor, or User modes).
24 // Currently the different modes are not implemented.
25 // Given this function is called so much, it's commented out for now. (rama)
26 __ri void cpuUpdateOperationMode() {
27
28 //u32 value = cpuRegs.CP0.n.Status.val;
29
30 //if (value & 0x06 ||
31 // (value & 0x18) == 0) { // Kernel Mode (KSU = 0 | EXL = 1 | ERL = 1)*/
32 // memSetKernelMode(); // Kernel memory always
33 //} else { // User Mode
34 // memSetUserMode();
35 //}
36 }
37
38 void __fastcall WriteCP0Status(u32 value) {
39
40 //DMA_LOG("COP0 Status write = 0x%08x", value);
41
42 cpuRegs.CP0.n.Status.val = value;
43 cpuUpdateOperationMode();
44 cpuSetNextEventDelta(4);
45 }
46
47 void MapTLB(int i)
48 {
49 u32 mask, addr;
50 u32 saddr, eaddr;
51
52 DevCon.WriteLn("MAP TLB %d: 0x%08X-> [0x%08X 0x%08X] S=0x%08X G=%d ASID=%d Mask=0x%03X",
53 i, tlb[i].VPN2, tlb[i].PFN0, tlb[i].PFN1, tlb[i].S, tlb[i].G, tlb[i].ASID, tlb[i].Mask);
54
55 if (tlb[i].S)
56 {
57 vtlb_VMapBuffer(tlb[i].VPN2, eeMem->Scratch, Ps2MemSize::Scratch);
58 }
59
60 if (tlb[i].VPN2 == 0x70000000) return; //uh uhh right ...
61 if (tlb[i].EntryLo0 & 0x2) {
62 mask = ((~tlb[i].Mask) << 1) & 0xfffff;
63 saddr = tlb[i].VPN2 >> 12;
64 eaddr = saddr + tlb[i].Mask + 1;
65
66 for (addr=saddr; addr<eaddr; addr++) {
67 if ((addr & mask) == ((tlb[i].VPN2 >> 12) & mask)) { //match
68 memSetPageAddr(addr << 12, tlb[i].PFN0 + ((addr - saddr) << 12));
69 Cpu->Clear(addr << 12, 0x400);
70 }
71 }
72 }
73
74 if (tlb[i].EntryLo1 & 0x2) {
75 mask = ((~tlb[i].Mask) << 1) & 0xfffff;
76 saddr = (tlb[i].VPN2 >> 12) + tlb[i].Mask + 1;
77 eaddr = saddr + tlb[i].Mask + 1;
78
79 for (addr=saddr; addr<eaddr; addr++) {
80 if ((addr & mask) == ((tlb[i].VPN2 >> 12) & mask)) { //match
81 memSetPageAddr(addr << 12, tlb[i].PFN1 + ((addr - saddr) << 12));
82 Cpu->Clear(addr << 12, 0x400);
83 }
84 }
85 }
86 }
87
88 void UnmapTLB(int i)
89 {
90 //Console.WriteLn("Clear TLB %d: %08x-> [%08x %08x] S=%d G=%d ASID=%d Mask= %03X", i,tlb[i].VPN2,tlb[i].PFN0,tlb[i].PFN1,tlb[i].S,tlb[i].G,tlb[i].ASID,tlb[i].Mask);
91 u32 mask, addr;
92 u32 saddr, eaddr;
93
94 if (tlb[i].S)
95 {
96 vtlb_VMapUnmap(tlb[i].VPN2,0x4000);
97 return;
98 }
99
100 if (tlb[i].EntryLo0 & 0x2)
101 {
102 mask = ((~tlb[i].Mask) << 1) & 0xfffff;
103 saddr = tlb[i].VPN2 >> 12;
104 eaddr = saddr + tlb[i].Mask + 1;
105 // Console.WriteLn("Clear TLB: %08x ~ %08x",saddr,eaddr-1);
106 for (addr=saddr; addr<eaddr; addr++) {
107 if ((addr & mask) == ((tlb[i].VPN2 >> 12) & mask)) { //match
108 memClearPageAddr(addr << 12);
109 Cpu->Clear(addr << 12, 0x400);
110 }
111 }
112 }
113
114 if (tlb[i].EntryLo1 & 0x2) {
115 mask = ((~tlb[i].Mask) << 1) & 0xfffff;
116 saddr = (tlb[i].VPN2 >> 12) + tlb[i].Mask + 1;
117 eaddr = saddr + tlb[i].Mask + 1;
118 // Console.WriteLn("Clear TLB: %08x ~ %08x",saddr,eaddr-1);
119 for (addr=saddr; addr<eaddr; addr++) {
120 if ((addr & mask) == ((tlb[i].VPN2 >> 12) & mask)) { //match
121 memClearPageAddr(addr << 12);
122 Cpu->Clear(addr << 12, 0x400);
123 }
124 }
125 }
126 }
127
128 void WriteTLB(int i)
129 {
130 tlb[i].PageMask = cpuRegs.CP0.n.PageMask;
131 tlb[i].EntryHi = cpuRegs.CP0.n.EntryHi;
132 tlb[i].EntryLo0 = cpuRegs.CP0.n.EntryLo0;
133 tlb[i].EntryLo1 = cpuRegs.CP0.n.EntryLo1;
134
135 tlb[i].Mask = (cpuRegs.CP0.n.PageMask >> 13) & 0xfff;
136 tlb[i].nMask = (~tlb[i].Mask) & 0xfff;
137 tlb[i].VPN2 = ((cpuRegs.CP0.n.EntryHi >> 13) & (~tlb[i].Mask)) << 13;
138 tlb[i].ASID = cpuRegs.CP0.n.EntryHi & 0xfff;
139 tlb[i].G = cpuRegs.CP0.n.EntryLo0 & cpuRegs.CP0.n.EntryLo1 & 0x1;
140 tlb[i].PFN0 = (((cpuRegs.CP0.n.EntryLo0 >> 6) & 0xFFFFF) & (~tlb[i].Mask)) << 12;
141 tlb[i].PFN1 = (((cpuRegs.CP0.n.EntryLo1 >> 6) & 0xFFFFF) & (~tlb[i].Mask)) << 12;
142 tlb[i].S = cpuRegs.CP0.n.EntryLo0&0x80000000;
143
144 MapTLB(i);
145 }
146
147 //////////////////////////////////////////////////////////////////////////////////////////
148 // Performance Counters Update Stuff!
149 //
150 // Note regarding updates of PERF and TIMR registers: never allow increment to be 0.
151 // That happens when a game loads the MFC0 twice in the same recompiled block (before the
152 // cpuRegs.cycles update), and can cause games to lock up since it's an unexpected result.
153 //
154 // PERF Overflow exceptions: The exception is raised when the MSB of the Performance
155 // Counter Register is set. I'm assuming the exception continues to re-raise until the
156 // app clears the bit manually (needs testing).
157 //
158 // PERF Events:
159 // * Event 0 on PCR 0 is unused (counter disable)
160 // * Event 16 is usable as a specific counter disable bit (since CTE affects both counters)
161 // * Events 17-31 are reserved (act as counter disable)
162 //
163 // Most event mode aren't supported, and issue a warning and do a standard instruction
164 // count. But only mode 1 (instruction counter) has been found to be used by games thus far.
165 //
166
167 static __fi bool PERF_ShouldCountEvent( uint evt )
168 {
169 switch( evt )
170 {
171 // This is a rough table of actions for various PCR modes. Some of these
172 // can be implemented more accurately later. Others (WBBs in particular)
173 // probably cannot without some severe complications.
174
175 // left sides are PCR0 / right sides are PCR1
176
177 case 1: // cpu cycle counter.
178 case 2: // single/dual instruction issued
179 case 3: // Branch issued / Branch mispredicated
180 return true;
181
182 case 4: // BTAC/TLB miss
183 case 5: // ITLB/DTLB miss
184 case 6: // Data/Instruction cache miss
185 return false;
186
187 case 7: // Access to DTLB / WBB single request fail
188 case 8: // Non-blocking load / WBB burst request fail
189 case 9:
190 case 10:
191 return false;
192
193 case 11: // CPU address bus busy / CPU data bus busy
194 return false;
195
196 case 12: // Instruction completed
197 case 13: // non-delayslot instruction completed
198 case 14: // COP2/COP1 instruction complete
199 case 15: // Load/Store completed
200 return true;
201 }
202
203 return false;
204 }
205
206 // Diagnostics for event modes that we just ignore for now. Using these perf units could
207 // cause compat issues in some very odd/rare games, so if this msg comes up who knows,
208 // might save some debugging effort. :)
209 void COP0_DiagnosticPCCR()
210 {
211 if( cpuRegs.PERF.n.pccr.b.Event0 >= 7 && cpuRegs.PERF.n.pccr.b.Event0 <= 10 )
212 Console.Warning( "PERF/PCR0 Unsupported Update Event Mode = 0x%x", cpuRegs.PERF.n.pccr.b.Event0 );
213
214 if( cpuRegs.PERF.n.pccr.b.Event1 >= 7 && cpuRegs.PERF.n.pccr.b.Event1 <= 10 )
215 Console.Warning( "PERF/PCR1 Unsupported Update Event Mode = 0x%x", cpuRegs.PERF.n.pccr.b.Event1 );
216 }
217 extern int branch;
218 __fi void COP0_UpdatePCCR()
219 {
220 //if( cpuRegs.CP0.n.Status.b.ERL || !cpuRegs.PERF.n.pccr.b.CTE ) return;
221
222 // TODO : Implement memory mode checks here (kernel/super/user)
223 // For now we just assume kernel mode.
224
225 if( cpuRegs.PERF.n.pccr.val & 0xf )
226 {
227 // ----------------------------------
228 // Update Performance Counter 0
229 // ----------------------------------
230
231 if( PERF_ShouldCountEvent( cpuRegs.PERF.n.pccr.b.Event0 ) )
232 {
233 u32 incr = cpuRegs.cycle - s_iLastPERFCycle[0];
234 if( incr == 0 ) incr++;
235
236 // use prev/XOR method for one-time exceptions (but likely less correct)
237 //u32 prev = cpuRegs.PERF.n.pcr0;
238 cpuRegs.PERF.n.pcr0 += incr;
239 s_iLastPERFCycle[0] = cpuRegs.cycle;
240
241 //prev ^= (1UL<<31); // XOR is fun!
242 //if( (prev & cpuRegs.PERF.n.pcr0) & (1UL<<31) )
243 if( (cpuRegs.PERF.n.pcr0 & 0x80000000) && (cpuRegs.CP0.n.Status.b.ERL == 1) && cpuRegs.PERF.n.pccr.b.CTE)
244 {
245 // TODO: Vector to the appropriate exception here.
246 // This code *should* be correct, but is untested (and other parts of the emu are
247 // not prepared to handle proper Level 2 exception vectors yet)
248
249 //branch == 1 is probably not the best way to check for the delay slot, but it beats nothing! (Refraction)
250 /* if( branch == 1 )
251 {
252 cpuRegs.CP0.n.ErrorEPC = cpuRegs.pc - 4;
253 cpuRegs.CP0.n.Cause |= 0x40000000;
254 }
255 else
256 {
257 cpuRegs.CP0.n.ErrorEPC = cpuRegs.pc;
258 cpuRegs.CP0.n.Cause &= ~0x40000000;
259 }
260
261 if( cpuRegs.CP0.n.Status.b.DEV )
262 {
263 // Bootstrap vector
264 cpuRegs.pc = 0xbfc00280;
265 }
266 else
267 {
268 cpuRegs.pc = 0x80000080;
269 }
270 cpuRegs.CP0.n.Status.b.ERL = 1;
271 cpuRegs.CP0.n.Cause |= 0x20000;*/
272 }
273 }
274 }
275
276 if( cpuRegs.PERF.n.pccr.b.U1 )
277 {
278 // ----------------------------------
279 // Update Performance Counter 1
280 // ----------------------------------
281
282 if( PERF_ShouldCountEvent( cpuRegs.PERF.n.pccr.b.Event1 ) )
283 {
284 u32 incr = cpuRegs.cycle - s_iLastPERFCycle[1];
285 if( incr == 0 ) incr++;
286
287 cpuRegs.PERF.n.pcr1 += incr;
288 s_iLastPERFCycle[1] = cpuRegs.cycle;
289
290 if( (cpuRegs.PERF.n.pcr1 & 0x80000000) && (cpuRegs.CP0.n.Status.b.ERL == 1) && cpuRegs.PERF.n.pccr.b.CTE)
291 {
292 // TODO: Vector to the appropriate exception here.
293 // This code *should* be correct, but is untested (and other parts of the emu are
294 // not prepared to handle proper Level 2 exception vectors yet)
295
296 //branch == 1 is probably not the best way to check for the delay slot, but it beats nothing! (Refraction)
297
298 /*if( branch == 1 )
299 {
300 cpuRegs.CP0.n.ErrorEPC = cpuRegs.pc - 4;
301 cpuRegs.CP0.n.Cause |= 0x40000000;
302 }
303 else
304 {
305 cpuRegs.CP0.n.ErrorEPC = cpuRegs.pc;
306 cpuRegs.CP0.n.Cause &= ~0x40000000;
307 }
308
309 if( cpuRegs.CP0.n.Status.b.DEV )
310 {
311 // Bootstrap vector
312 cpuRegs.pc = 0xbfc00280;
313 }
314 else
315 {
316 cpuRegs.pc = 0x80000080;
317 }
318 cpuRegs.CP0.n.Status.b.ERL = 1;
319 cpuRegs.CP0.n.Cause |= 0x20000;*/
320 }
321 }
322 }
323 }
324
325 //////////////////////////////////////////////////////////////////////////////////////////
326 //
327
328 namespace R5900 {
329 namespace Interpreter {
330 namespace OpcodeImpl {
331 namespace COP0 {
332
333 void MFC0()
334 {
335 // Note on _Rd_ Condition 9: CP0.Count should be updated even if _Rt_ is 0.
336 if ((_Rd_ != 9) && !_Rt_ ) return;
337 if (_Rd_ != 9) { COP0_LOG("%s", disR5900Current.getCString() ); }
338
339 //if(bExecBIOS == FALSE && _Rd_ == 25) Console.WriteLn("MFC0 _Rd_ %x = %x", _Rd_, cpuRegs.CP0.r[_Rd_]);
340 switch (_Rd_)
341 {
342 case 12:
343 cpuRegs.GPR.r[_Rt_].SD[0] = (s32)(cpuRegs.CP0.r[_Rd_] & 0xf0c79c1f);
344 break;
345
346 case 25:
347 switch(_Imm_ & 0x3F)
348 {
349 case 0: // MFPS [LSB is clear]
350 cpuRegs.GPR.r[_Rt_].SD[0] = (s32)cpuRegs.PERF.n.pccr.val;
351 break;
352
353 case 1: // MFPC [LSB is set] - read PCR0
354 COP0_UpdatePCCR();
355 cpuRegs.GPR.r[_Rt_].SD[0] = (s32)cpuRegs.PERF.n.pcr0;
356 break;
357
358 case 3: // MFPC [LSB is set] - read PCR1
359 COP0_UpdatePCCR();
360 cpuRegs.GPR.r[_Rt_].SD[0] = (s32)cpuRegs.PERF.n.pcr1;
361 break;
362 }
363 /*Console.WriteLn("MFC0 PCCR = %x PCR0 = %x PCR1 = %x IMM= %x", params
364 cpuRegs.PERF.n.pccr, cpuRegs.PERF.n.pcr0, cpuRegs.PERF.n.pcr1, _Imm_ & 0x3F);*/
365 break;
366
367 case 24:
368 Console.WriteLn("MFC0 Breakpoint debug Registers code = %x", cpuRegs.code & 0x3FF);
369 break;
370
371 case 9:
372 {
373 u32 incr = cpuRegs.cycle-s_iLastCOP0Cycle;
374 if( incr == 0 ) incr++;
375 cpuRegs.CP0.n.Count += incr;
376 s_iLastCOP0Cycle = cpuRegs.cycle;
377 if( !_Rt_ ) break;
378 }
379
380 default:
381 cpuRegs.GPR.r[_Rt_].UD[0] = (s64)cpuRegs.CP0.r[_Rd_];
382 }
383 }
384
385 void MTC0()
386 {
387 COP0_LOG("%s\n", disR5900Current.getCString());
388 //if(bExecBIOS == FALSE && _Rd_ == 25) Console.WriteLn("MTC0 _Rd_ %x = %x", _Rd_, cpuRegs.CP0.r[_Rd_]);
389 switch (_Rd_)
390 {
391 case 9:
392 s_iLastCOP0Cycle = cpuRegs.cycle;
393 cpuRegs.CP0.r[9] = cpuRegs.GPR.r[_Rt_].UL[0];
394 break;
395
396 case 12:
397 WriteCP0Status(cpuRegs.GPR.r[_Rt_].UL[0]);
398 break;
399
400 case 24:
401 Console.WriteLn("MTC0 Breakpoint debug Registers code = %x", cpuRegs.code & 0x3FF);
402 break;
403
404 case 25:
405 /*if(bExecBIOS == FALSE && _Rd_ == 25) Console.WriteLn("MTC0 PCCR = %x PCR0 = %x PCR1 = %x IMM= %x", params
406 cpuRegs.PERF.n.pccr, cpuRegs.PERF.n.pcr0, cpuRegs.PERF.n.pcr1, _Imm_ & 0x3F);*/
407 switch(_Imm_ & 0x3F)
408 {
409 case 0: // MTPS [LSB is clear]
410 // Updates PCRs and sets the PCCR.
411 COP0_UpdatePCCR();
412 cpuRegs.PERF.n.pccr.val = cpuRegs.GPR.r[_Rt_].UL[0];
413 COP0_DiagnosticPCCR();
414 break;
415
416 case 1: // MTPC [LSB is set] - set PCR0
417 cpuRegs.PERF.n.pcr0 = cpuRegs.GPR.r[_Rt_].UL[0];
418 s_iLastPERFCycle[0] = cpuRegs.cycle;
419 break;
420
421 case 3: // MTPC [LSB is set] - set PCR0
422 cpuRegs.PERF.n.pcr1 = cpuRegs.GPR.r[_Rt_].UL[0];
423 s_iLastPERFCycle[1] = cpuRegs.cycle;
424 break;
425 }
426 break;
427
428 default:
429 cpuRegs.CP0.r[_Rd_] = cpuRegs.GPR.r[_Rt_].UL[0];
430 break;
431 }
432 }
433
434 int CPCOND0() {
435 return ((dmacRegs.stat.CIS | ~dmacRegs.pcr.CPC) == 0x3ff);
436 }
437
438 //#define CPCOND0 1
439
440 void BC0F() {
441 if (CPCOND0() == 0) intDoBranch(_BranchTarget_);
442 }
443
444 void BC0T() {
445 if (CPCOND0() == 1) intDoBranch(_BranchTarget_);
446 }
447
448 void BC0FL() {
449 if (CPCOND0() == 0)
450 intDoBranch(_BranchTarget_);
451 else
452 cpuRegs.pc+= 4;
453
454 }
455
456 void BC0TL() {
457 if (CPCOND0() == 1)
458 intDoBranch(_BranchTarget_);
459 else
460 cpuRegs.pc+= 4;
461 }
462
463 void TLBR() {
464 /* CPU_LOG("COP0_TLBR %d:%x,%x,%x,%x\n",
465 cpuRegs.CP0.n.Random, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi,
466 cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);*/
467
468 int i = cpuRegs.CP0.n.Index&0x1f;
469
470 cpuRegs.CP0.n.PageMask = tlb[i].PageMask;
471 cpuRegs.CP0.n.EntryHi = tlb[i].EntryHi&~(tlb[i].PageMask|0x1f00);
472 cpuRegs.CP0.n.EntryLo0 = (tlb[i].EntryLo0&~1)|((tlb[i].EntryHi>>12)&1);
473 cpuRegs.CP0.n.EntryLo1 =(tlb[i].EntryLo1&~1)|((tlb[i].EntryHi>>12)&1);
474 }
475
476 void TLBWI() {
477 int j = cpuRegs.CP0.n.Index & 0x3f;
478
479 if (j > 48) return;
480
481 /* CPU_LOG("COP0_TLBWI %d:%x,%x,%x,%x\n",
482 cpuRegs.CP0.n.Index, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi,
483 cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);*/
484
485 UnmapTLB(j);
486 WriteTLB(j);
487 }
488
489 void TLBWR() {
490 int j = cpuRegs.CP0.n.Random & 0x3f;
491
492 if (j > 48) return;
493
494 /* CPU_LOG("COP0_TLBWR %d:%x,%x,%x,%x\n",
495 cpuRegs.CP0.n.Random, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi,
496 cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);*/
497
498 // if( !bExecBIOS )
499 // __Log("TLBWR %d\n", j);
500
501 UnmapTLB(j);
502 WriteTLB(j);
503 }
504
505 void TLBP() {
506 int i;
507
508 union {
509 struct {
510 u32 VPN2:19;
511 u32 VPN2X:2;
512 u32 G:3;
513 u32 ASID:8;
514 } s;
515 u32 u;
516 } EntryHi32;
517
518 EntryHi32.u = cpuRegs.CP0.n.EntryHi;
519
520 cpuRegs.CP0.n.Index=0xFFFFFFFF;
521 for(i=0;i<48;i++){
522 if (tlb[i].VPN2 == ((~tlb[i].Mask) & (EntryHi32.s.VPN2))
523 && ((tlb[i].G&1) || ((tlb[i].ASID & 0xff) == EntryHi32.s.ASID))) {
524 cpuRegs.CP0.n.Index = i;
525 break;
526 }
527 }
528 if(cpuRegs.CP0.n.Index == 0xFFFFFFFF) cpuRegs.CP0.n.Index = 0x80000000;
529 }
530
531 void ERET() {
532 if (cpuRegs.CP0.n.Status.b.ERL) {
533 cpuRegs.pc = cpuRegs.CP0.n.ErrorEPC;
534 cpuRegs.CP0.n.Status.b.ERL = 0;
535 } else {
536 cpuRegs.pc = cpuRegs.CP0.n.EPC;
537 cpuRegs.CP0.n.Status.b.EXL = 0;
538 }
539 cpuUpdateOperationMode();
540 cpuSetNextEventDelta(4);
541 intSetBranch();
542 }
543
544 void DI() {
545 if (cpuRegs.CP0.n.Status.b._EDI || cpuRegs.CP0.n.Status.b.EXL ||
546 cpuRegs.CP0.n.Status.b.ERL || (cpuRegs.CP0.n.Status.b.KSU == 0)) {
547 cpuRegs.CP0.n.Status.b.EIE = 0;
548 // IRQs are disabled so no need to do a cpu exception/event test...
549 //cpuSetNextEventDelta();
550 }
551 }
552
553 void EI() {
554 if (cpuRegs.CP0.n.Status.b._EDI || cpuRegs.CP0.n.Status.b.EXL ||
555 cpuRegs.CP0.n.Status.b.ERL || (cpuRegs.CP0.n.Status.b.KSU == 0)) {
556 cpuRegs.CP0.n.Status.b.EIE = 1;
557 // schedule an event test, which will check for and raise pending IRQs.
558 cpuSetNextEventDelta(4);
559 }
560 }
561
562 } } } } // end namespace R5900::Interpreter::OpcodeImpl

  ViewVC Help
Powered by ViewVC 1.1.22