Sort out compiler warnings, all of them
[pcsx_rearmed.git] / libpcsxcore / psxinterpreter.c
CommitLineData
ef79bbde
P
1/***************************************************************************
2 * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
18 ***************************************************************************/
19
20/*
21 * PSX assembly interpreter.
22 */
23
24#include "psxcommon.h"
25#include "r3000a.h"
26#include "gte.h"
27#include "psxhle.h"
fc8145b7 28#include "debug.h"
ef79bbde
P
29
30static int branch = 0;
31static int branch2 = 0;
32static u32 branchPC;
33
34// These macros are used to assemble the repassembler functions
35
36#ifdef PSXCPU_LOG
37#define debugI() PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc));
38#else
39#define debugI()
40#endif
41
9361a5aa
EC
42#ifndef NDEBUG
43#include "debug.h"
44#else
11a43034 45void StartDebugger() {}
46void ProcessDebug() {}
47void StopDebugger() {}
48#endif
49
4600ba03 50void execI();
ef79bbde
P
51
52// Subsets
53void (*psxBSC[64])();
54void (*psxSPC[64])();
55void (*psxREG[32])();
56void (*psxCP0[32])();
6c0eefaf 57void (*psxCP2[64])(struct psxCP2Regs *regs);
ef79bbde
P
58void (*psxCP2BSC[32])();
59
60static void delayRead(int reg, u32 bpc) {
61 u32 rold, rnew;
62
63// SysPrintf("delayRead at %x!\n", psxRegs.pc);
64
65 rold = psxRegs.GPR.r[reg];
66 psxBSC[psxRegs.code >> 26](); // branch delay load
67 rnew = psxRegs.GPR.r[reg];
68
69 psxRegs.pc = bpc;
70
abbc1ca1 71 branch = 0;
ef79bbde
P
72
73 psxRegs.GPR.r[reg] = rold;
74 execI(); // first branch opcode
75 psxRegs.GPR.r[reg] = rnew;
76
abbc1ca1 77 psxBranchTest();
ef79bbde
P
78}
79
80static void delayWrite(int reg, u32 bpc) {
81
82/* SysPrintf("delayWrite at %x!\n", psxRegs.pc);
83
84 SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4));
85 SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/
86
87 // no changes from normal behavior
88
89 psxBSC[psxRegs.code >> 26]();
90
91 branch = 0;
92 psxRegs.pc = bpc;
93
94 psxBranchTest();
95}
96
97static void delayReadWrite(int reg, u32 bpc) {
98
99// SysPrintf("delayReadWrite at %x!\n", psxRegs.pc);
100
101 // the branch delay load is skipped
102
103 branch = 0;
104 psxRegs.pc = bpc;
105
106 psxBranchTest();
107}
108
109// this defines shall be used with the tmp
110// of the next func (instead of _Funct_...)
111#define _tFunct_ ((tmp ) & 0x3F) // The funct part of the instruction register
112#define _tRd_ ((tmp >> 11) & 0x1F) // The rd part of the instruction register
113#define _tRt_ ((tmp >> 16) & 0x1F) // The rt part of the instruction register
114#define _tRs_ ((tmp >> 21) & 0x1F) // The rs part of the instruction register
115#define _tSa_ ((tmp >> 6) & 0x1F) // The sa part of the instruction register
116
117int psxTestLoadDelay(int reg, u32 tmp) {
118 if (tmp == 0) return 0; // NOP
119 switch (tmp >> 26) {
120 case 0x00: // SPECIAL
121 switch (_tFunct_) {
122 case 0x00: // SLL
123 case 0x02: case 0x03: // SRL/SRA
124 if (_tRd_ == reg && _tRt_ == reg) return 1; else
125 if (_tRt_ == reg) return 2; else
126 if (_tRd_ == reg) return 3;
127 break;
128
129 case 0x08: // JR
130 if (_tRs_ == reg) return 2;
131 break;
132 case 0x09: // JALR
133 if (_tRd_ == reg && _tRs_ == reg) return 1; else
134 if (_tRs_ == reg) return 2; else
135 if (_tRd_ == reg) return 3;
136 break;
137
138 // SYSCALL/BREAK just a break;
139
140 case 0x20: case 0x21: case 0x22: case 0x23:
141 case 0x24: case 0x25: case 0x26: case 0x27:
142 case 0x2a: case 0x2b: // ADD/ADDU...
143 case 0x04: case 0x06: case 0x07: // SLLV...
144 if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else
145 if (_tRt_ == reg || _tRs_ == reg) return 2; else
146 if (_tRd_ == reg) return 3;
147 break;
148
149 case 0x10: case 0x12: // MFHI/MFLO
150 if (_tRd_ == reg) return 3;
151 break;
152 case 0x11: case 0x13: // MTHI/MTLO
153 if (_tRs_ == reg) return 2;
154 break;
155
156 case 0x18: case 0x19:
157 case 0x1a: case 0x1b: // MULT/DIV...
158 if (_tRt_ == reg || _tRs_ == reg) return 2;
159 break;
160 }
161 break;
162
163 case 0x01: // REGIMM
164 switch (_tRt_) {
862bfc0d 165 case 0x00: case 0x01:
166 case 0x10: case 0x11: // BLTZ/BGEZ...
167 // Xenogears - lbu v0 / beq v0
168 // - no load delay (fixes battle loading)
169 break;
170
ef79bbde
P
171 if (_tRs_ == reg) return 2;
172 break;
173 }
174 break;
175
176 // J would be just a break;
177 case 0x03: // JAL
178 if (31 == reg) return 3;
179 break;
180
181 case 0x04: case 0x05: // BEQ/BNE
862bfc0d 182 // Xenogears - lbu v0 / beq v0
183 // - no load delay (fixes battle loading)
184 break;
185
ef79bbde
P
186 if (_tRs_ == reg || _tRt_ == reg) return 2;
187 break;
188
189 case 0x06: case 0x07: // BLEZ/BGTZ
862bfc0d 190 // Xenogears - lbu v0 / beq v0
191 // - no load delay (fixes battle loading)
192 break;
193
ef79bbde
P
194 if (_tRs_ == reg) return 2;
195 break;
196
197 case 0x08: case 0x09: case 0x0a: case 0x0b:
198 case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU...
199 if (_tRt_ == reg && _tRs_ == reg) return 1; else
200 if (_tRs_ == reg) return 2; else
201 if (_tRt_ == reg) return 3;
202 break;
203
204 case 0x0f: // LUI
205 if (_tRt_ == reg) return 3;
206 break;
207
208 case 0x10: // COP0
209 switch (_tFunct_) {
210 case 0x00: // MFC0
211 if (_tRt_ == reg) return 3;
212 break;
213 case 0x02: // CFC0
214 if (_tRt_ == reg) return 3;
215 break;
216 case 0x04: // MTC0
217 if (_tRt_ == reg) return 2;
218 break;
219 case 0x06: // CTC0
220 if (_tRt_ == reg) return 2;
221 break;
222 // RFE just a break;
223 }
224 break;
225
226 case 0x12: // COP2
227 switch (_tFunct_) {
228 case 0x00:
229 switch (_tRs_) {
230 case 0x00: // MFC2
231 if (_tRt_ == reg) return 3;
232 break;
233 case 0x02: // CFC2
234 if (_tRt_ == reg) return 3;
235 break;
236 case 0x04: // MTC2
237 if (_tRt_ == reg) return 2;
238 break;
239 case 0x06: // CTC2
240 if (_tRt_ == reg) return 2;
241 break;
242 }
243 break;
244 // RTPS... break;
245 }
246 break;
247
248 case 0x22: case 0x26: // LWL/LWR
249 if (_tRt_ == reg) return 3; else
250 if (_tRs_ == reg) return 2;
251 break;
252
253 case 0x20: case 0x21: case 0x23:
254 case 0x24: case 0x25: // LB/LH/LW/LBU/LHU
255 if (_tRt_ == reg && _tRs_ == reg) return 1; else
256 if (_tRs_ == reg) return 2; else
257 if (_tRt_ == reg) return 3;
258 break;
259
260 case 0x28: case 0x29: case 0x2a:
261 case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR
262 if (_tRt_ == reg || _tRs_ == reg) return 2;
263 break;
264
265 case 0x32: case 0x3a: // LWC2/SWC2
266 if (_tRs_ == reg) return 2;
267 break;
268 }
269
270 return 0;
271}
272
273void psxDelayTest(int reg, u32 bpc) {
274 u32 *code;
275 u32 tmp;
276
277 code = (u32 *)PSXM(bpc);
278 tmp = ((code == NULL) ? 0 : SWAP32(*code));
279 branch = 1;
280
281 switch (psxTestLoadDelay(reg, tmp)) {
282 case 1:
283 delayReadWrite(reg, bpc); return;
284 case 2:
285 delayRead(reg, bpc); return;
286 case 3:
287 delayWrite(reg, bpc); return;
288 }
289 psxBSC[psxRegs.code >> 26]();
290
291 branch = 0;
292 psxRegs.pc = bpc;
293
294 psxBranchTest();
295}
296
990cb018 297static u32 psxBranchNoDelay(void) {
298 u32 *code;
299 u32 temp;
300
301 code = (u32 *)PSXM(psxRegs.pc);
302 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
303 switch (_Op_) {
304 case 0x00: // SPECIAL
305 switch (_Funct_) {
306 case 0x08: // JR
307 return _u32(_rRs_);
308 case 0x09: // JALR
309 temp = _u32(_rRs_);
310 if (_Rd_) { _SetLink(_Rd_); }
311 return temp;
312 }
313 break;
314 case 0x01: // REGIMM
315 switch (_Rt_) {
316 case 0x00: // BLTZ
317 if (_i32(_rRs_) < 0)
318 return _BranchTarget_;
319 break;
320 case 0x01: // BGEZ
321 if (_i32(_rRs_) >= 0)
322 return _BranchTarget_;
323 break;
324 case 0x08: // BLTZAL
325 if (_i32(_rRs_) < 0) {
326 _SetLink(31);
327 return _BranchTarget_;
328 }
329 break;
330 case 0x09: // BGEZAL
331 if (_i32(_rRs_) >= 0) {
332 _SetLink(31);
333 return _BranchTarget_;
334 }
335 break;
336 }
337 break;
338 case 0x02: // J
339 return _JumpTarget_;
340 case 0x03: // JAL
341 _SetLink(31);
342 return _JumpTarget_;
343 case 0x04: // BEQ
344 if (_i32(_rRs_) == _i32(_rRt_))
345 return _BranchTarget_;
346 break;
347 case 0x05: // BNE
348 if (_i32(_rRs_) != _i32(_rRt_))
349 return _BranchTarget_;
350 break;
351 case 0x06: // BLEZ
352 if (_i32(_rRs_) <= 0)
353 return _BranchTarget_;
354 break;
355 case 0x07: // BGTZ
356 if (_i32(_rRs_) > 0)
357 return _BranchTarget_;
358 break;
359 }
360
361 return (u32)-1;
362}
363
364static int psxDelayBranchExec(u32 tar) {
365 execI();
366
367 branch = 0;
368 psxRegs.pc = tar;
369 psxRegs.cycle += BIAS;
370 psxBranchTest();
371 return 1;
372}
373
374static int psxDelayBranchTest(u32 tar1) {
375 u32 tar2, tmp1, tmp2;
376
377 tar2 = psxBranchNoDelay();
378 if (tar2 == (u32)-1)
379 return 0;
380
381 debugI();
382
383 /*
384 * Branch in delay slot:
385 * - execute 1 instruction at tar1
386 * - jump to tar2 (target of branch in delay slot; this branch
387 * has no normal delay slot, instruction at tar1 was fetched instead)
388 */
389 psxRegs.pc = tar1;
390 tmp1 = psxBranchNoDelay();
391 if (tmp1 == (u32)-1) {
392 return psxDelayBranchExec(tar2);
393 }
394 debugI();
395 psxRegs.cycle += BIAS;
396
397 /*
398 * Got a branch at tar1:
399 * - execute 1 instruction at tar2
400 * - jump to target of that branch (tmp1)
401 */
402 psxRegs.pc = tar2;
403 tmp2 = psxBranchNoDelay();
404 if (tmp2 == (u32)-1) {
405 return psxDelayBranchExec(tmp1);
406 }
407 debugI();
408 psxRegs.cycle += BIAS;
409
410 /*
411 * Got a branch at tar2:
412 * - execute 1 instruction at tmp1
413 * - jump to target of that branch (tmp2)
414 */
415 psxRegs.pc = tmp1;
416 return psxDelayBranchExec(tmp2);
417}
418
4600ba03 419static void doBranch(u32 tar) {
ef79bbde
P
420 u32 *code;
421 u32 tmp;
422
423 branch2 = branch = 1;
424 branchPC = tar;
425
990cb018 426 // check for branch in delay slot
427 if (psxDelayBranchTest(tar))
428 return;
429
ef79bbde
P
430 code = (u32 *)PSXM(psxRegs.pc);
431 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
432
433 debugI();
434
435 psxRegs.pc += 4;
436 psxRegs.cycle += BIAS;
437
438 // check for load delay
439 tmp = psxRegs.code >> 26;
440 switch (tmp) {
441 case 0x10: // COP0
442 switch (_Rs_) {
443 case 0x00: // MFC0
444 case 0x02: // CFC0
445 psxDelayTest(_Rt_, branchPC);
446 return;
447 }
448 break;
449 case 0x12: // COP2
450 switch (_Funct_) {
451 case 0x00:
452 switch (_Rs_) {
453 case 0x00: // MFC2
454 case 0x02: // CFC2
455 psxDelayTest(_Rt_, branchPC);
456 return;
457 }
458 break;
459 }
460 break;
461 case 0x32: // LWC2
462 psxDelayTest(_Rt_, branchPC);
463 return;
464 default:
465 if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
466 psxDelayTest(_Rt_, branchPC);
467 return;
468 }
469 break;
470 }
471
472 psxBSC[psxRegs.code >> 26]();
473
474 branch = 0;
475 psxRegs.pc = branchPC;
476
477 psxBranchTest();
478}
479
480/*********************************************************
481* Arithmetic with immediate operand *
482* Format: OP rt, rs, immediate *
483*********************************************************/
484void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow)
485void psxADDIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im
486void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im
487void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im
488void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im
489void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed)
490void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < ((u32)_Imm_); } // Rt = Rs < Im (Unsigned)
491
492/*********************************************************
493* Register arithmetic *
494* Format: OP rd, rs, rt *
495*********************************************************/
496void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow)
497void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt
498void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow)
499void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt
500void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt
501void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt
502void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt
503void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
504void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed)
505void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned)
506
507/*********************************************************
508* Register mult/div & Register trap logic *
509* Format: OP rs, rt *
510*********************************************************/
511void psxDIV() {
f533290e
EC
512 if (!_i32(_rRt_)) {
513 _i32(_rHi_) = _i32(_rRs_);
514 if (_i32(_rRs_) & 0x80000000) {
515 _i32(_rLo_) = 1;
516 } else {
517 _i32(_rLo_) = 0xFFFFFFFF;
518 }
519 } else if (_i32(_rRs_) == 0x80000000 && _i32(_rRt_) == 0xFFFFFFFF) {
520 _i32(_rLo_) = 0x80000000;
521 _i32(_rHi_) = 0;
522 } else {
523 _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
524 _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
525 }
ef79bbde
P
526}
527
528void psxDIVU() {
529 if (_rRt_ != 0) {
530 _rLo_ = _rRs_ / _rRt_;
531 _rHi_ = _rRs_ % _rRt_;
532 }
c7a56f4f 533 else {
534 _i32(_rLo_) = 0xffffffff;
535 _i32(_rHi_) = _i32(_rRs_);
536 }
ef79bbde
P
537}
538
539void psxMULT() {
540 u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_));
541
542 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
543 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
544}
545
546void psxMULTU() {
547 u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_));
548
549 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
550 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
551}
552
553/*********************************************************
554* Register branch logic *
555* Format: OP rs, offset *
556*********************************************************/
557#define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
558#define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); }
559
560void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0
561void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
562void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0
563void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0
564void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0
565void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
566
567/*********************************************************
568* Shift arithmetic with constant shift *
569* Format: OP rd, rt, sa *
570*********************************************************/
571void psxSLL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
572void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
573void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
574
575/*********************************************************
576* Shift arithmetic with variant register shift *
577* Format: OP rd, rt, rs *
578*********************************************************/
579void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs
580void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic)
581void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical)
582
583/*********************************************************
584* Load higher 16 bits of the first word in GPR with imm *
585* Format: OP rt, immediate *
586*********************************************************/
587void psxLUI() { if (!_Rt_) return; _u32(_rRt_) = psxRegs.code << 16; } // Upper halfword of Rt = Im
588
589/*********************************************************
590* Move from HI/LO to GPR *
591* Format: OP rd *
592*********************************************************/
593void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
594void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
595
596/*********************************************************
597* Move to GPR to HI/LO & Register jump *
598* Format: OP rs *
599*********************************************************/
600void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
601void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
602
603/*********************************************************
604* Special purpose instructions *
605* Format: OP *
606*********************************************************/
607void psxBREAK() {
608 // Break exception - psx rom doens't handles this
609}
610
611void psxSYSCALL() {
612 psxRegs.pc -= 4;
613 psxException(0x20, branch);
614}
615
616void psxRFE() {
617// SysPrintf("psxRFE\n");
618 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
619 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
620}
621
622/*********************************************************
623* Register branch logic *
624* Format: OP rs, rt, offset *
625*********************************************************/
626#define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
627
628void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt
629void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt
630
631/*********************************************************
632* Jump to target *
633* Format: OP target *
634*********************************************************/
635void psxJ() { doBranch(_JumpTarget_); }
636void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); }
637
638/*********************************************************
639* Register jump *
640* Format: OP rs, rd *
641*********************************************************/
642void psxJR() {
643 doBranch(_u32(_rRs_));
644 psxJumpTest();
645}
646
647void psxJALR() {
648 u32 temp = _u32(_rRs_);
649 if (_Rd_) { _SetLink(_Rd_); }
650 doBranch(temp);
651}
652
653/*********************************************************
654* Load and store for GPR *
655* Format: OP rt, offset(base) *
656*********************************************************/
657
658#define _oB_ (_u32(_rRs_) + _Imm_)
659
660void psxLB() {
661 if (_Rt_) {
662 _i32(_rRt_) = (signed char)psxMemRead8(_oB_);
663 } else {
664 psxMemRead8(_oB_);
665 }
666}
667
668void psxLBU() {
669 if (_Rt_) {
670 _u32(_rRt_) = psxMemRead8(_oB_);
671 } else {
672 psxMemRead8(_oB_);
673 }
674}
675
676void psxLH() {
677 if (_Rt_) {
678 _i32(_rRt_) = (short)psxMemRead16(_oB_);
679 } else {
680 psxMemRead16(_oB_);
681 }
682}
683
684void psxLHU() {
685 if (_Rt_) {
686 _u32(_rRt_) = psxMemRead16(_oB_);
687 } else {
688 psxMemRead16(_oB_);
689 }
690}
691
692void psxLW() {
693 if (_Rt_) {
694 _u32(_rRt_) = psxMemRead32(_oB_);
695 } else {
696 psxMemRead32(_oB_);
697 }
698}
699
700u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
701u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
702
703void psxLWL() {
704 u32 addr = _oB_;
705 u32 shift = addr & 3;
706 u32 mem = psxMemRead32(addr & ~3);
707
708 if (!_Rt_) return;
709 _u32(_rRt_) = ( _u32(_rRt_) & LWL_MASK[shift]) |
710 ( mem << LWL_SHIFT[shift]);
711
712 /*
713 Mem = 1234. Reg = abcd
714
715 0 4bcd (mem << 24) | (reg & 0x00ffffff)
716 1 34cd (mem << 16) | (reg & 0x0000ffff)
717 2 234d (mem << 8) | (reg & 0x000000ff)
718 3 1234 (mem ) | (reg & 0x00000000)
719 */
720}
721
722u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
723u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
724
725void psxLWR() {
726 u32 addr = _oB_;
727 u32 shift = addr & 3;
728 u32 mem = psxMemRead32(addr & ~3);
729
730 if (!_Rt_) return;
731 _u32(_rRt_) = ( _u32(_rRt_) & LWR_MASK[shift]) |
732 ( mem >> LWR_SHIFT[shift]);
733
734 /*
735 Mem = 1234. Reg = abcd
736
737 0 1234 (mem ) | (reg & 0x00000000)
738 1 a123 (mem >> 8) | (reg & 0xff000000)
739 2 ab12 (mem >> 16) | (reg & 0xffff0000)
740 3 abc1 (mem >> 24) | (reg & 0xffffff00)
741 */
742}
743
b1ba0851 744void psxSB() { psxMemWrite8 (_oB_, _rRt_ & 0xff); }
745void psxSH() { psxMemWrite16(_oB_, _rRt_ & 0xffff); }
746void psxSW() { psxMemWrite32(_oB_, _rRt_); }
ef79bbde
P
747
748u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
749u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
750
751void psxSWL() {
752 u32 addr = _oB_;
753 u32 shift = addr & 3;
754 u32 mem = psxMemRead32(addr & ~3);
755
756 psxMemWrite32(addr & ~3, (_u32(_rRt_) >> SWL_SHIFT[shift]) |
757 ( mem & SWL_MASK[shift]) );
758 /*
759 Mem = 1234. Reg = abcd
760
761 0 123a (reg >> 24) | (mem & 0xffffff00)
762 1 12ab (reg >> 16) | (mem & 0xffff0000)
763 2 1abc (reg >> 8) | (mem & 0xff000000)
764 3 abcd (reg ) | (mem & 0x00000000)
765 */
766}
767
768u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
769u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
770
771void psxSWR() {
772 u32 addr = _oB_;
773 u32 shift = addr & 3;
774 u32 mem = psxMemRead32(addr & ~3);
775
776 psxMemWrite32(addr & ~3, (_u32(_rRt_) << SWR_SHIFT[shift]) |
777 ( mem & SWR_MASK[shift]) );
778
779 /*
780 Mem = 1234. Reg = abcd
781
782 0 abcd (reg ) | (mem & 0x00000000)
783 1 bcd4 (reg << 8) | (mem & 0x000000ff)
784 2 cd34 (reg << 16) | (mem & 0x0000ffff)
785 3 d234 (reg << 24) | (mem & 0x00ffffff)
786 */
787}
788
789/*********************************************************
790* Moves between GPR and COPx *
791* Format: OP rt, fs *
792*********************************************************/
793void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
794void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
795
796void psxTestSWInts() {
ef79bbde 797 if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 &&
48e74ef5 798 psxRegs.CP0.n.Status & 0x1) {
799 psxRegs.CP0.n.Cause &= ~0x7c;
ef79bbde
P
800 psxException(psxRegs.CP0.n.Cause, branch);
801 }
802}
803
4600ba03 804void MTC0(int reg, u32 val) {
ef79bbde
P
805// SysPrintf("MTC0 %d: %x\n", reg, val);
806 switch (reg) {
807 case 12: // Status
808 psxRegs.CP0.r[12] = val;
809 psxTestSWInts();
810 break;
811
812 case 13: // Cause
48e74ef5 813 psxRegs.CP0.n.Cause &= ~0x0300;
814 psxRegs.CP0.n.Cause |= val & 0x0300;
ef79bbde
P
815 psxTestSWInts();
816 break;
817
818 default:
819 psxRegs.CP0.r[reg] = val;
820 break;
821 }
822}
823
824void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
825void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
826
827/*********************************************************
828* Unknow instruction (would generate an exception) *
829* Format: ? *
830*********************************************************/
831void psxNULL() {
832#ifdef PSXCPU_LOG
833 PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
834#endif
835}
836
837void psxSPECIAL() {
838 psxSPC[_Funct_]();
839}
840
841void psxREGIMM() {
842 psxREG[_Rt_]();
843}
844
845void psxCOP0() {
846 psxCP0[_Rs_]();
847}
848
849void psxCOP2() {
6c0eefaf 850 psxCP2[_Funct_]((struct psxCP2Regs *)&psxRegs.CP2D);
ef79bbde
P
851}
852
6c0eefaf 853void psxBASIC(struct psxCP2Regs *regs) {
ef79bbde
P
854 psxCP2BSC[_Rs_]();
855}
856
857void psxHLE() {
858// psxHLEt[psxRegs.code & 0xffff]();
859 psxHLEt[psxRegs.code & 0x07](); // HDHOSHY experimental patch
860}
861
862void (*psxBSC[64])() = {
863 psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
864 psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
865 psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
866 psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
867 psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL,
868 psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL,
869 psxNULL , psxNULL , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
870 psxNULL , psxNULL , gteSWC2, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL
871};
872
873
874void (*psxSPC[64])() = {
875 psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV,
876 psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
877 psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL,
878 psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL,
879 psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR ,
880 psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL,
881 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL,
882 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL
883};
884
885void (*psxREG[32])() = {
886 psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
887 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
888 psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
889 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
890};
891
892void (*psxCP0[32])() = {
893 psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
894 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
895 psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
896 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
897};
898
6c0eefaf 899void (*psxCP2[64])(struct psxCP2Regs *regs) = {
ef79bbde
P
900 psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
901 psxNULL , psxNULL , psxNULL , psxNULL, gteOP , psxNULL , psxNULL , psxNULL, // 08
902 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
903 psxNULL , psxNULL , psxNULL , gteNCCS, gteCC , psxNULL , gteNCS , psxNULL, // 18
904 gteNCT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
905 gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28
906 gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
907 psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF , gteGPL , gteNCCT // 38
908};
909
910void (*psxCP2BSC[32])() = {
911 gteMFC2, psxNULL, gteCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, psxNULL,
912 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
913 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
914 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
915};
916
917
918///////////////////////////////////////////
919
920static int intInit() {
921 return 0;
922}
923
924static void intReset() {
925}
926
796a91ef 927void intExecute() {
928 extern int stop;
929 for (;!stop;)
ef79bbde
P
930 execI();
931}
932
796a91ef 933void intExecuteBlock() {
ef79bbde
P
934 branch2 = 0;
935 while (!branch2) execI();
936}
937
938static void intClear(u32 Addr, u32 Size) {
939}
940
941static void intShutdown() {
942}
943
944// interpreter execution
4600ba03 945void execI() {
ef79bbde
P
946 u32 *code = (u32 *)PSXM(psxRegs.pc);
947 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
948
949 debugI();
950
951 if (Config.Debug) ProcessDebug();
952
953 psxRegs.pc += 4;
954 psxRegs.cycle += BIAS;
955
956 psxBSC[psxRegs.code >> 26]();
957}
958
959R3000Acpu psxInt = {
960 intInit,
961 intReset,
962 intExecute,
963 intExecuteBlock,
964 intClear,
965 intShutdown
966};