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