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