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

  ViewVC Help
Powered by ViewVC 1.1.22