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