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