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