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