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

Contents of /trunk/pcsx2/Interpreter.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (show annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (10 years, 2 months ago) by william
File size: 8787 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 #include "R5900OpcodeTables.h"
21 #include "R5900Exceptions.h"
22 #include "System/SysThreads.h"
23
24 #include "Elfheader.h"
25
26 #include <float.h>
27
28 using namespace R5900; // for OPCODE and OpcodeImpl
29
30 extern int vu0branch, vu1branch;
31
32 static int branch2 = 0;
33 static u32 cpuBlockCycles = 0; // 3 bit fixed point version of cycle count
34 static std::string disOut;
35
36 static void intEventTest();
37
38 // These macros are used to assemble the repassembler functions
39
40 static void debugI()
41 {
42 if( !IsDevBuild ) return;
43 if( cpuRegs.GPR.n.r0.UD[0] || cpuRegs.GPR.n.r0.UD[1] ) Console.Error("R0 is not zero!!!!");
44 }
45
46 //long int runs=0;
47
48 static void execI()
49 {
50 cpuRegs.code = memRead32( cpuRegs.pc );
51 if( IsDebugBuild )
52 debugI();
53
54 const OPCODE& opcode = GetCurrentInstruction();
55 //use this to find out what opcodes your game uses. very slow! (rama)
56 //runs++;
57 //if (runs > 1599999999){ //leave some time to startup the testgame
58 // if (opcode.Name[0] == 'L') { //find all opcodes beginning with "L"
59 // Console.WriteLn ("Load %s", opcode.Name);
60 // }
61 //}
62
63 // Another method of instruction dumping:
64 /*if( cpuRegs.cycle > 0x4f24d714 )
65 {
66 //CPU_LOG( "%s", disR5900Current.getCString());
67 disOut.clear();
68 opcode.disasm( disOut );
69 disOut += '\n';
70 CPU_LOG( disOut.c_str() );
71 }*/
72
73
74 cpuBlockCycles += opcode.cycles;
75 cpuRegs.pc += 4;
76
77 opcode.interpret();
78 }
79
80 static __fi void _doBranch_shared(u32 tar)
81 {
82 branch2 = cpuRegs.branch = 1;
83 execI();
84
85 // branch being 0 means an exception was thrown, since only the exception
86 // handler should ever clear it.
87
88 if( cpuRegs.branch != 0 )
89 {
90 cpuRegs.pc = tar;
91 cpuRegs.branch = 0;
92 }
93 }
94
95 static void __fastcall doBranch( u32 target )
96 {
97 _doBranch_shared( target );
98 cpuRegs.cycle += cpuBlockCycles >> 3;
99 cpuBlockCycles &= (1<<3)-1;
100 intEventTest();
101 }
102
103 void __fastcall intDoBranch(u32 target)
104 {
105 //Console.WriteLn("Interpreter Branch ");
106 _doBranch_shared( target );
107
108 if( Cpu == &intCpu )
109 {
110 cpuRegs.cycle += cpuBlockCycles >> 3;
111 cpuBlockCycles &= (1<<3)-1;
112 intEventTest();
113 }
114 }
115
116 void intSetBranch()
117 {
118 branch2 = /*cpuRegs.branch =*/ 1;
119 }
120
121 ////////////////////////////////////////////////////////////////////
122 // R5900 Branching Instructions!
123 // These are the interpreter versions of the branch instructions. Unlike other
124 // types of interpreter instructions which can be called safely from the recompilers,
125 // these instructions are not "recSafe" because they may not invoke the
126 // necessary branch test logic that the recs need to maintain sync with the
127 // cpuRegs.pc and delaySlot instruction and such.
128
129 namespace R5900 {
130 namespace Interpreter {
131 namespace OpcodeImpl {
132
133 /*********************************************************
134 * Jump to target *
135 * Format: OP target *
136 *********************************************************/
137 // fixme: looking at the other branching code, shouldn't those _SetLinks in BGEZAL and such only be set
138 // if the condition is true? --arcum42
139
140 void J()
141 {
142 doBranch(_JumpTarget_);
143 }
144
145 void JAL()
146 {
147 _SetLink(31);
148 doBranch(_JumpTarget_);
149 }
150
151 /*********************************************************
152 * Register branch logic *
153 * Format: OP rs, rt, offset *
154 *********************************************************/
155
156 void BEQ() // Branch if Rs == Rt
157 {
158 if (cpuRegs.GPR.r[_Rs_].SD[0] == cpuRegs.GPR.r[_Rt_].SD[0])
159 doBranch(_BranchTarget_);
160 else
161 intEventTest();
162 }
163
164 void BNE() // Branch if Rs != Rt
165 {
166 if (cpuRegs.GPR.r[_Rs_].SD[0] != cpuRegs.GPR.r[_Rt_].SD[0])
167 doBranch(_BranchTarget_);
168 else
169 intEventTest();
170 }
171
172 /*********************************************************
173 * Register branch logic *
174 * Format: OP rs, offset *
175 *********************************************************/
176
177 void BGEZ() // Branch if Rs >= 0
178 {
179 if(cpuRegs.GPR.r[_Rs_].SD[0] >= 0)
180 {
181 doBranch(_BranchTarget_);
182 }
183 }
184
185 void BGEZAL() // Branch if Rs >= 0 and link
186 {
187
188 if (cpuRegs.GPR.r[_Rs_].SD[0] >= 0)
189 {
190 _SetLink(31);
191 doBranch(_BranchTarget_);
192 }
193 }
194
195 void BGTZ() // Branch if Rs > 0
196 {
197 if (cpuRegs.GPR.r[_Rs_].SD[0] > 0)
198 {
199 doBranch(_BranchTarget_);
200 }
201 }
202
203 void BLEZ() // Branch if Rs <= 0
204 {
205 if (cpuRegs.GPR.r[_Rs_].SD[0] <= 0)
206 {
207 doBranch(_BranchTarget_);
208 }
209 }
210
211 void BLTZ() // Branch if Rs < 0
212 {
213 if (cpuRegs.GPR.r[_Rs_].SD[0] < 0)
214 {
215 doBranch(_BranchTarget_);
216 }
217 }
218
219 void BLTZAL() // Branch if Rs < 0 and link
220 {
221 if (cpuRegs.GPR.r[_Rs_].SD[0] < 0)
222 {
223 _SetLink(31);
224 doBranch(_BranchTarget_);
225 }
226 }
227
228 /*********************************************************
229 * Register branch logic Likely *
230 * Format: OP rs, offset *
231 *********************************************************/
232
233
234 void BEQL() // Branch if Rs == Rt
235 {
236 if(cpuRegs.GPR.r[_Rs_].SD[0] == cpuRegs.GPR.r[_Rt_].SD[0])
237 {
238 doBranch(_BranchTarget_);
239 }
240 else
241 {
242 cpuRegs.pc +=4;
243 intEventTest();
244 }
245 }
246
247 void BNEL() // Branch if Rs != Rt
248 {
249 if(cpuRegs.GPR.r[_Rs_].SD[0] != cpuRegs.GPR.r[_Rt_].SD[0])
250 {
251 doBranch(_BranchTarget_);
252 }
253 else
254 {
255 cpuRegs.pc +=4;
256 intEventTest();
257 }
258 }
259
260 void BLEZL() // Branch if Rs <= 0
261 {
262 if(cpuRegs.GPR.r[_Rs_].SD[0] <= 0)
263 {
264 doBranch(_BranchTarget_);
265 }
266 else
267 {
268 cpuRegs.pc +=4;
269 intEventTest();
270 }
271 }
272
273 void BGTZL() // Branch if Rs > 0
274 {
275 if(cpuRegs.GPR.r[_Rs_].SD[0] > 0)
276 {
277 doBranch(_BranchTarget_);
278 }
279 else
280 {
281 cpuRegs.pc +=4;
282 intEventTest();
283 }
284 }
285
286 void BLTZL() // Branch if Rs < 0
287 {
288 if(cpuRegs.GPR.r[_Rs_].SD[0] < 0)
289 {
290 doBranch(_BranchTarget_);
291 }
292 else
293 {
294 cpuRegs.pc +=4;
295 intEventTest();
296 }
297 }
298
299 void BGEZL() // Branch if Rs >= 0
300 {
301 if(cpuRegs.GPR.r[_Rs_].SD[0] >= 0)
302 {
303 doBranch(_BranchTarget_);
304 }
305 else
306 {
307 cpuRegs.pc +=4;
308 intEventTest();
309 }
310 }
311
312 void BLTZALL() // Branch if Rs < 0 and link
313 {
314
315 if(cpuRegs.GPR.r[_Rs_].SD[0] < 0)
316 {
317 _SetLink(31);
318 doBranch(_BranchTarget_);
319 }
320 else
321 {
322 cpuRegs.pc +=4;
323 intEventTest();
324 }
325 }
326
327 void BGEZALL() // Branch if Rs >= 0 and link
328 {
329
330 if(cpuRegs.GPR.r[_Rs_].SD[0] >= 0)
331 {
332 _SetLink(31);
333 doBranch(_BranchTarget_);
334 }
335 else
336 {
337 cpuRegs.pc +=4;
338 intEventTest();
339 }
340 }
341
342 /*********************************************************
343 * Register jump *
344 * Format: OP rs, rd *
345 *********************************************************/
346 void JR()
347 {
348 doBranch(cpuRegs.GPR.r[_Rs_].UL[0]);
349 }
350
351 void JALR()
352 {
353 u32 temp = cpuRegs.GPR.r[_Rs_].UL[0];
354
355 if (_Rd_) _SetLink(_Rd_);
356
357 doBranch(temp);
358 }
359
360 } } } // end namespace R5900::Interpreter::OpcodeImpl
361
362 ////////////////////////////////////////////////////////
363
364 static void intAlloc()
365 {
366 // fixme : detect cpu for use the optimize asm code
367 }
368
369 static void intReset()
370 {
371 cpuRegs.branch = 0;
372 branch2 = 0;
373 }
374
375 static void intEventTest()
376 {
377 // Perform counters, ints, and IOP updates:
378 _cpuEventTest_Shared();
379 }
380
381 static void intExecute()
382 {
383 try {
384 if (g_SkipBiosHack) {
385 do
386 execI();
387 while (cpuRegs.pc != EELOAD_START);
388 eeloadReplaceOSDSYS();
389 }
390 if (ElfEntry != -1) {
391 do
392 execI();
393 while (cpuRegs.pc != ElfEntry);
394 eeGameStarting();
395 } else {
396 while (true)
397 execI();
398 }
399 } catch( Exception::ExitCpuExecute& ) { }
400 }
401
402 static void intCheckExecutionState()
403 {
404 if( GetCoreThread().HasPendingStateChangeRequest() )
405 throw Exception::ExitCpuExecute();
406 }
407
408 static void intStep()
409 {
410 execI();
411 }
412
413 static void intClear(u32 Addr, u32 Size)
414 {
415 }
416
417 static void intShutdown() {
418 }
419
420 static void intThrowException( const BaseR5900Exception& ex )
421 {
422 // No tricks needed; C++ stack unwnding shoud suffice for MSW and GCC alike.
423 ex.Rethrow();
424 }
425
426 static void intThrowException( const BaseException& ex )
427 {
428 // No tricks needed; C++ stack unwnding shoud suffice for MSW and GCC alike.
429 ex.Rethrow();
430 }
431
432 R5900cpu intCpu =
433 {
434 intAlloc,
435 intShutdown,
436
437 intReset,
438 intStep,
439 intExecute,
440
441 intCheckExecutionState,
442 intThrowException,
443 intThrowException,
444 intClear,
445 };

  ViewVC Help
Powered by ViewVC 1.1.22