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