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