cdrom: remove cdrWrite3 reschedule
[pcsx_rearmed.git] / libpcsxcore / ppc / pR3000A.c
CommitLineData
ef79bbde
P
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., 51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307 USA
17 */
18
19#ifdef _MSC_VER_
20#pragma warning(disable:4244)
21#pragma warning(disable:4761)
22#endif
23#include <stdlib.h>
24#include <string.h>
25#include <time.h>
26#include <sys/types.h>
27#include <sys/mman.h>
28
29#ifndef MAP_ANONYMOUS
30#define MAP_ANONYMOUS MAP_ANON
31#endif
32
33#include "../psxcommon.h"
34#include "ppc.h"
35#include "reguse.h"
36#include "../r3000a.h"
37#include "../psxhle.h"
38
39//#define NO_CONSTANT
40
41u32 *psxRecLUT;
42
43#undef _Op_
44#define _Op_ _fOp_(psxRegs.code)
45#undef _Funct_
46#define _Funct_ _fFunct_(psxRegs.code)
47#undef _Rd_
48#define _Rd_ _fRd_(psxRegs.code)
49#undef _Rt_
50#define _Rt_ _fRt_(psxRegs.code)
51#undef _Rs_
52#define _Rs_ _fRs_(psxRegs.code)
53#undef _Sa_
54#define _Sa_ _fSa_(psxRegs.code)
55#undef _Im_
56#define _Im_ _fIm_(psxRegs.code)
57#undef _Target_
58#define _Target_ _fTarget_(psxRegs.code)
59
60#undef _Imm_
61#define _Imm_ _fImm_(psxRegs.code)
62#undef _ImmU_
63#define _ImmU_ _fImmU_(psxRegs.code)
64
65#undef PC_REC
66#undef PC_REC8
67#undef PC_REC16
68#undef PC_REC32
69#define PC_REC(x) (psxRecLUT[x >> 16] + (x & 0xffff))
70#define PC_REC8(x) (*(u8 *)PC_REC(x))
71#define PC_REC16(x) (*(u16*)PC_REC(x))
72#define PC_REC32(x) (*(u32*)PC_REC(x))
73
74#define OFFSET(X,Y) ((u32)(Y)-(u32)(X))
75
76#define RECMEM_SIZE (12*1024*1024)
77
78static char *recMem; /* the recompiled blocks will be here */
79static char *recRAM; /* and the ptr to the blocks here */
80static char *recROM; /* and here */
81
82static u32 pc; /* recompiler pc */
83static u32 pcold; /* recompiler oldpc */
84static int count; /* recompiler intruction count */
85static int branch; /* set for branch */
86static u32 target; /* branch target */
87static u32 resp;
88
89u32 cop2readypc = 0;
90u32 idlecyclecount = 0;
91
92#define NUM_REGISTERS 34
93typedef struct {
94 int state;
95 u32 k;
96 int reg;
97} iRegisters;
98
99static iRegisters iRegs[34];
100
101#define ST_UNK 0x00
102#define ST_CONST 0x01
103#define ST_MAPPED 0x02
104
105#ifdef NO_CONSTANT
106#define IsConst(reg) 0
107#else
108#define IsConst(reg) (iRegs[reg].state & ST_CONST)
109#endif
110#define IsMapped(reg) (iRegs[reg].state & ST_MAPPED)
111
112static void (*recBSC[64])();
113static void (*recSPC[64])();
114static void (*recREG[32])();
115static void (*recCP0[32])();
116static void (*recCP2[64])();
117static void (*recCP2BSC[32])();
118
119#define REG_LO 32
120#define REG_HI 33
121
122// Hardware register usage
123#define HWUSAGE_NONE 0x00
124
125#define HWUSAGE_READ 0x01
126#define HWUSAGE_WRITE 0x02
127#define HWUSAGE_CONST 0x04
128#define HWUSAGE_ARG 0x08 /* used as an argument for a function call */
129
130#define HWUSAGE_RESERVED 0x10 /* won't get flushed when flushing all regs */
131#define HWUSAGE_SPECIAL 0x20 /* special purpose register */
132#define HWUSAGE_HARDWIRED 0x40 /* specific hardware register mapping that is never disposed */
133#define HWUSAGE_INITED 0x80
134#define HWUSAGE_PSXREG 0x100
135
136// Remember to invalidate the special registers if they are modified by compiler
137enum {
138 ARG1 = 3,
139 ARG2 = 4,
140 ARG3 = 5,
141 PSXREGS, // ptr
142 PSXMEM, // ptr
143 CYCLECOUNT, // ptr
144 PSXPC, // ptr
145 TARGETPTR, // ptr
146 TARGET, // ptr
147 RETVAL,
148 REG_RZERO,
149 REG_WZERO
150};
151
152typedef struct {
153 int code;
154 u32 k;
155 int usage;
156 int lastUsed;
157
158 void (*flush)(int hwreg);
159 int private;
160} HWRegister;
161static HWRegister HWRegisters[NUM_HW_REGISTERS];
162static int HWRegUseCount;
163static int DstCPUReg;
164static int UniqueRegAlloc;
165
166static int GetFreeHWReg();
167static void InvalidateCPURegs();
168static void DisposeHWReg(int index);
169static void FlushHWReg(int index);
170static void FlushAllHWReg();
171static void MapPsxReg32(int reg);
172static void FlushPsxReg32(int hwreg);
173static int UpdateHWRegUsage(int hwreg, int usage);
174static int GetHWReg32(int reg);
175static int PutHWReg32(int reg);
176static int GetSpecialIndexFromHWRegs(int which);
177static int GetHWRegFromCPUReg(int cpureg);
178static int MapRegSpecial(int which);
179static void FlushRegSpecial(int hwreg);
180static int GetHWRegSpecial(int which);
181static int PutHWRegSpecial(int which);
182static void recRecompile();
183static void recError();
184
185#pragma mark --- Generic register mapping ---
186
187static int GetFreeHWReg()
188{
189 int i, least, index;
190
191 if (DstCPUReg != -1) {
192 index = GetHWRegFromCPUReg(DstCPUReg);
193 DstCPUReg = -1;
194 } else {
195 // LRU algorith with a twist ;)
196 for (i=0; i<NUM_HW_REGISTERS; i++) {
197 if (!(HWRegisters[i].usage & HWUSAGE_RESERVED)) {
198 break;
199 }
200 }
201
202 least = HWRegisters[i].lastUsed; index = i;
203 for (; i<NUM_HW_REGISTERS; i++) {
204 if (!(HWRegisters[i].usage & HWUSAGE_RESERVED)) {
205 if (HWRegisters[i].usage == HWUSAGE_NONE && HWRegisters[i].code >= 13) {
206 index = i;
207 break;
208 }
209 else if (HWRegisters[i].lastUsed < least) {
210 least = HWRegisters[i].lastUsed;
211 index = i;
212 }
213 }
214 }
215
216 // Cycle the registers
217 if (HWRegisters[index].usage == HWUSAGE_NONE) {
218 for (; i<NUM_HW_REGISTERS; i++) {
219 if (!(HWRegisters[i].usage & HWUSAGE_RESERVED)) {
220 if (HWRegisters[i].usage == HWUSAGE_NONE &&
221 HWRegisters[i].code >= 13 &&
222 HWRegisters[i].lastUsed < least) {
223 least = HWRegisters[i].lastUsed;
224 index = i;
225 break;
226 }
227 }
228 }
229 }
230 }
231
232/* if (HWRegisters[index].code < 13 && HWRegisters[index].code > 3) {
233 SysPrintf("Allocating volatile register %i\n", HWRegisters[index].code);
234 }
235 if (HWRegisters[index].usage != HWUSAGE_NONE) {
236 SysPrintf("RegUse too big. Flushing %i\n", HWRegisters[index].code);
237 }*/
238 if (HWRegisters[index].usage & (HWUSAGE_RESERVED | HWUSAGE_HARDWIRED)) {
239 if (HWRegisters[index].usage & HWUSAGE_RESERVED) {
240 SysPrintf("Error! Trying to map a new register to a reserved register (r%i)",
241 HWRegisters[index].code);
242 }
243 if (HWRegisters[index].usage & HWUSAGE_HARDWIRED) {
244 SysPrintf("Error! Trying to map a new register to a hardwired register (r%i)",
245 HWRegisters[index].code);
246 }
247 }
248
249 if (HWRegisters[index].lastUsed != 0) {
250 UniqueRegAlloc = 0;
251 }
252
253 // Make sure the register is really flushed!
254 FlushHWReg(index);
255 HWRegisters[index].usage = HWUSAGE_NONE;
256 HWRegisters[index].flush = NULL;
257
258 return index;
259}
260
261static void FlushHWReg(int index)
262{
263 if (index < 0) return;
264 if (HWRegisters[index].usage == HWUSAGE_NONE) return;
265
266 if (HWRegisters[index].flush) {
267 HWRegisters[index].usage |= HWUSAGE_RESERVED;
268 HWRegisters[index].flush(index);
269 HWRegisters[index].flush = NULL;
270 }
271
272 if (HWRegisters[index].usage & HWUSAGE_HARDWIRED) {
273 HWRegisters[index].usage &= ~(HWUSAGE_READ | HWUSAGE_WRITE);
274 } else {
275 HWRegisters[index].usage = HWUSAGE_NONE;
276 }
277}
278
279// get rid of a mapped register without flushing the contents to the memory
280static void DisposeHWReg(int index)
281{
282 if (index < 0) return;
283 if (HWRegisters[index].usage == HWUSAGE_NONE) return;
284
285 HWRegisters[index].usage &= ~(HWUSAGE_READ | HWUSAGE_WRITE);
286 if (HWRegisters[index].usage == HWUSAGE_NONE) {
287 SysPrintf("Error! not correctly disposing register (r%i)", HWRegisters[index].code);
288 }
289
290 FlushHWReg(index);
291}
292
293// operated on cpu registers
294__inline static void FlushCPURegRange(int start, int end)
295{
296 int i;
297
298 if (end <= 0) end = 31;
299 if (start <= 0) start = 0;
300
301 for (i=0; i<NUM_HW_REGISTERS; i++) {
302 if (HWRegisters[i].code >= start && HWRegisters[i].code <= end)
303 if (HWRegisters[i].flush)
304 FlushHWReg(i);
305 }
306
307 for (i=0; i<NUM_HW_REGISTERS; i++) {
308 if (HWRegisters[i].code >= start && HWRegisters[i].code <= end)
309 FlushHWReg(i);
310 }
311}
312
313static void FlushAllHWReg()
314{
315 FlushCPURegRange(0,31);
316}
317
318static void InvalidateCPURegs()
319{
320 FlushCPURegRange(0,12);
321}
322
323#pragma mark --- Mapping utility functions ---
324
325static void MoveHWRegToCPUReg(int cpureg, int hwreg)
326{
327 int dstreg;
328
329 if (HWRegisters[hwreg].code == cpureg)
330 return;
331
332 dstreg = GetHWRegFromCPUReg(cpureg);
333
334 HWRegisters[dstreg].usage &= ~(HWUSAGE_HARDWIRED | HWUSAGE_ARG);
335 if (HWRegisters[hwreg].usage & (HWUSAGE_READ | HWUSAGE_WRITE)) {
336 FlushHWReg(dstreg);
337 MR(HWRegisters[dstreg].code, HWRegisters[hwreg].code);
338 } else {
339 if (HWRegisters[dstreg].usage & (HWUSAGE_READ | HWUSAGE_WRITE)) {
340 MR(HWRegisters[hwreg].code, HWRegisters[dstreg].code);
341 }
342 else if (HWRegisters[dstreg].usage != HWUSAGE_NONE) {
343 FlushHWReg(dstreg);
344 }
345 }
346
347 HWRegisters[dstreg].code = HWRegisters[hwreg].code;
348 HWRegisters[hwreg].code = cpureg;
349}
350
351static int UpdateHWRegUsage(int hwreg, int usage)
352{
353 HWRegisters[hwreg].lastUsed = ++HWRegUseCount;
354 if (usage & HWUSAGE_WRITE) {
355 HWRegisters[hwreg].usage &= ~HWUSAGE_CONST;
356 }
357 if (!(usage & HWUSAGE_INITED)) {
358 HWRegisters[hwreg].usage &= ~HWUSAGE_INITED;
359 }
360 HWRegisters[hwreg].usage |= usage;
361
362 return HWRegisters[hwreg].code;
363}
364
365static int GetHWRegFromCPUReg(int cpureg)
366{
367 int i;
368 for (i=0; i<NUM_HW_REGISTERS; i++) {
369 if (HWRegisters[i].code == cpureg) {
370 return i;
371 }
372 }
373
374 SysPrintf("Error! Register location failure (r%i)", cpureg);
375 return 0;
376}
377
378// this function operates on cpu registers
379void SetDstCPUReg(int cpureg)
380{
381 DstCPUReg = cpureg;
382}
383
384static void ReserveArgs(int args)
385{
386 int index, i;
387
388 for (i=0; i<args; i++) {
389 index = GetHWRegFromCPUReg(3+i);
390 HWRegisters[index].usage |= HWUSAGE_RESERVED | HWUSAGE_HARDWIRED | HWUSAGE_ARG;
391 }
392}
393
394static void ReleaseArgs()
395{
396 int i;
397
398 for (i=0; i<NUM_HW_REGISTERS; i++) {
399 if (HWRegisters[i].usage & HWUSAGE_ARG) {
400 //HWRegisters[i].usage = HWUSAGE_NONE;
401 //HWRegisters[i].flush = NULL;
402 HWRegisters[i].usage &= ~(HWUSAGE_RESERVED | HWUSAGE_HARDWIRED | HWUSAGE_ARG);
403 FlushHWReg(i);
404 }
405 }
406}
407
408#pragma mark --- Psx register mapping ---
409
410static void MapPsxReg32(int reg)
411{
412 int hwreg = GetFreeHWReg();
413 HWRegisters[hwreg].flush = FlushPsxReg32;
414 HWRegisters[hwreg].private = reg;
415
416 if (iRegs[reg].reg != -1) {
417 SysPrintf("error: double mapped psx register");
418 }
419
420 iRegs[reg].reg = hwreg;
421 iRegs[reg].state |= ST_MAPPED;
422}
423
424static void FlushPsxReg32(int hwreg)
425{
426 int reg = HWRegisters[hwreg].private;
427
428 if (iRegs[reg].reg == -1) {
429 SysPrintf("error: flushing unmapped psx register");
430 }
431
432 if (HWRegisters[hwreg].usage & HWUSAGE_WRITE) {
433 if (branch) {
434 /*int reguse = nextPsxRegUse(pc-8, reg);
435 if (reguse == REGUSE_NONE || (reguse & REGUSE_READ))*/ {
436 STW(HWRegisters[hwreg].code, OFFSET(&psxRegs, &psxRegs.GPR.r[reg]), GetHWRegSpecial(PSXREGS));
437 }
438 } else {
439 int reguse = nextPsxRegUse(pc-4, reg);
440 if (reguse == REGUSE_NONE || (reguse & REGUSE_READ)) {
441 STW(HWRegisters[hwreg].code, OFFSET(&psxRegs, &psxRegs.GPR.r[reg]), GetHWRegSpecial(PSXREGS));
442 }
443 }
444 }
445
446 iRegs[reg].reg = -1;
447 iRegs[reg].state = ST_UNK;
448}
449
450static int GetHWReg32(int reg)
451{
452 int usage = HWUSAGE_PSXREG | HWUSAGE_READ;
453
454 if (reg == 0) {
455 return GetHWRegSpecial(REG_RZERO);
456 }
457 if (!IsMapped(reg)) {
458 usage |= HWUSAGE_INITED;
459 MapPsxReg32(reg);
460
461 HWRegisters[iRegs[reg].reg].usage |= HWUSAGE_RESERVED;
462 if (IsConst(reg)) {
463 LIW(HWRegisters[iRegs[reg].reg].code, iRegs[reg].k);
464 usage |= HWUSAGE_WRITE | HWUSAGE_CONST;
465 //iRegs[reg].state &= ~ST_CONST;
466 }
467 else {
468 LWZ(HWRegisters[iRegs[reg].reg].code, OFFSET(&psxRegs, &psxRegs.GPR.r[reg]), GetHWRegSpecial(PSXREGS));
469 }
470 HWRegisters[iRegs[reg].reg].usage &= ~HWUSAGE_RESERVED;
471 }
472 else if (DstCPUReg != -1) {
473 int dst = DstCPUReg;
474 DstCPUReg = -1;
475
476 if (HWRegisters[iRegs[reg].reg].code < 13) {
477 MoveHWRegToCPUReg(dst, iRegs[reg].reg);
478 } else {
479 MR(DstCPUReg, HWRegisters[iRegs[reg].reg].code);
480 }
481 }
482
483 DstCPUReg = -1;
484
485 return UpdateHWRegUsage(iRegs[reg].reg, usage);
486}
487
488static int PutHWReg32(int reg)
489{
490 int usage = HWUSAGE_PSXREG | HWUSAGE_WRITE;
491 if (reg == 0) {
492 return PutHWRegSpecial(REG_WZERO);
493 }
494
495 if (DstCPUReg != -1 && IsMapped(reg)) {
496 if (HWRegisters[iRegs[reg].reg].code != DstCPUReg) {
497 int tmp = DstCPUReg;
498 DstCPUReg = -1;
499 DisposeHWReg(iRegs[reg].reg);
500 DstCPUReg = tmp;
501 }
502 }
503 if (!IsMapped(reg)) {
504 usage |= HWUSAGE_INITED;
505 MapPsxReg32(reg);
506 }
507
508 DstCPUReg = -1;
509 iRegs[reg].state &= ~ST_CONST;
510
511 return UpdateHWRegUsage(iRegs[reg].reg, usage);
512}
513
514#pragma mark --- Special register mapping ---
515
516static int GetSpecialIndexFromHWRegs(int which)
517{
518 int i;
519 for (i=0; i<NUM_HW_REGISTERS; i++) {
520 if (HWRegisters[i].usage & HWUSAGE_SPECIAL) {
521 if (HWRegisters[i].private == which) {
522 return i;
523 }
524 }
525 }
526 return -1;
527}
528
529static int MapRegSpecial(int which)
530{
531 int hwreg = GetFreeHWReg();
532 HWRegisters[hwreg].flush = FlushRegSpecial;
533 HWRegisters[hwreg].private = which;
534
535 return hwreg;
536}
537
538static void FlushRegSpecial(int hwreg)
539{
540 int which = HWRegisters[hwreg].private;
541
542 if (!(HWRegisters[hwreg].usage & HWUSAGE_WRITE))
543 return;
544
545 switch (which) {
546 case CYCLECOUNT:
547 STW(HWRegisters[hwreg].code, OFFSET(&psxRegs, &psxRegs.cycle), GetHWRegSpecial(PSXREGS));
548 break;
549 case PSXPC:
550 STW(HWRegisters[hwreg].code, OFFSET(&psxRegs, &psxRegs.pc), GetHWRegSpecial(PSXREGS));
551 break;
552 case TARGET:
553 STW(HWRegisters[hwreg].code, 0, GetHWRegSpecial(TARGETPTR));
554 break;
555 }
556}
557
558static int GetHWRegSpecial(int which)
559{
560 int index = GetSpecialIndexFromHWRegs(which);
561 int usage = HWUSAGE_READ | HWUSAGE_SPECIAL;
562
563 if (index == -1) {
564 usage |= HWUSAGE_INITED;
565 index = MapRegSpecial(which);
566
567 HWRegisters[index].usage |= HWUSAGE_RESERVED;
568 switch (which) {
569 case PSXREGS:
570 case PSXMEM:
571 SysPrintf("error! shouldn't be here!\n");
572 //HWRegisters[index].flush = NULL;
573 //LIW(HWRegisters[index].code, (u32)&psxRegs);
574 break;
575 case TARGETPTR:
576 HWRegisters[index].flush = NULL;
577 LIW(HWRegisters[index].code, (u32)&target);
578 break;
579 case REG_RZERO:
580 HWRegisters[index].flush = NULL;
581 LIW(HWRegisters[index].code, 0);
582 break;
583 case RETVAL:
584 MoveHWRegToCPUReg(3, index);
585 /*reg = GetHWRegFromCPUReg(3);
586 HWRegisters[reg].code = HWRegisters[index].code;
587 HWRegisters[index].code = 3;*/
588 HWRegisters[index].flush = NULL;
589
590 usage |= HWUSAGE_RESERVED;
591 break;
592
593 case CYCLECOUNT:
594 LWZ(HWRegisters[index].code, OFFSET(&psxRegs, &psxRegs.cycle), GetHWRegSpecial(PSXREGS));
595 break;
596 case PSXPC:
597 LWZ(HWRegisters[index].code, OFFSET(&psxRegs, &psxRegs.pc), GetHWRegSpecial(PSXREGS));
598 break;
599 case TARGET:
600 LWZ(HWRegisters[index].code, 0, GetHWRegSpecial(TARGETPTR));
601 break;
602 default:
603 SysPrintf("Error: Unknown special register in GetHWRegSpecial()\n");
604 break;
605 }
606 HWRegisters[index].usage &= ~HWUSAGE_RESERVED;
607 }
608 else if (DstCPUReg != -1) {
609 int dst = DstCPUReg;
610 DstCPUReg = -1;
611
612 MoveHWRegToCPUReg(dst, index);
613 }
614
615 return UpdateHWRegUsage(index, usage);
616}
617
618static int PutHWRegSpecial(int which)
619{
620 int index = GetSpecialIndexFromHWRegs(which);
621 int usage = HWUSAGE_WRITE | HWUSAGE_SPECIAL;
622
623 if (DstCPUReg != -1 && index != -1) {
624 if (HWRegisters[index].code != DstCPUReg) {
625 int tmp = DstCPUReg;
626 DstCPUReg = -1;
627 DisposeHWReg(index);
628 DstCPUReg = tmp;
629 }
630 }
631 switch (which) {
632 case PSXREGS:
633 case TARGETPTR:
634 SysPrintf("Error: Read-only special register in PutHWRegSpecial()\n");
635 case REG_WZERO:
636 if (index >= 0) {
637 if (HWRegisters[index].usage & HWUSAGE_WRITE)
638 break;
639 }
640 index = MapRegSpecial(which);
641 HWRegisters[index].flush = NULL;
642 break;
643 default:
644 if (index == -1) {
645 usage |= HWUSAGE_INITED;
646 index = MapRegSpecial(which);
647
648 HWRegisters[index].usage |= HWUSAGE_RESERVED;
649 switch (which) {
650 case ARG1:
651 case ARG2:
652 case ARG3:
653 MoveHWRegToCPUReg(3+(which-ARG1), index);
654 /*reg = GetHWRegFromCPUReg(3+(which-ARG1));
655
656 if (HWRegisters[reg].usage != HWUSAGE_NONE) {
657 HWRegisters[reg].usage &= ~(HWUSAGE_HARDWIRED | HWUSAGE_ARG);
658 if (HWRegisters[reg].flush != NULL && HWRegisters[reg].usage & (HWUSAGE_WRITE | HWUSAGE_READ)) {
659 MR(HWRegisters[index].code, HWRegisters[reg].code);
660 } else {
661 FlushHWReg(reg);
662 }
663 }
664 HWRegisters[reg].code = HWRegisters[index].code;
665 if (!(HWRegisters[index].code >= 3 && HWRegisters[index].code <=31))
666 SysPrintf("Error! Register allocation");
667 HWRegisters[index].code = 3+(which-ARG1);*/
668 HWRegisters[index].flush = NULL;
669
670 usage |= HWUSAGE_RESERVED | HWUSAGE_HARDWIRED | HWUSAGE_ARG;
671 break;
672 }
673 }
674 HWRegisters[index].usage &= ~HWUSAGE_RESERVED;
675 break;
676 }
677
678 DstCPUReg = -1;
679
680 return UpdateHWRegUsage(index, usage);
681}
682
683#pragma mark --- ---
684
685static void MapConst(int reg, u32 _const) {
686 if (reg == 0)
687 return;
688 if (IsConst(reg) && iRegs[reg].k == _const)
689 return;
690
691 DisposeHWReg(iRegs[reg].reg);
692 iRegs[reg].k = _const;
693 iRegs[reg].state = ST_CONST;
694}
695
696static void MapCopy(int dst, int src)
697{
698 // do it the lazy way for now
699 MR(PutHWReg32(dst), GetHWReg32(src));
700}
701
702static void iFlushReg(u32 nextpc, int reg) {
703 if (!IsMapped(reg) && IsConst(reg)) {
704 GetHWReg32(reg);
705 }
706 if (IsMapped(reg)) {
707 if (nextpc) {
708 int use = nextPsxRegUse(nextpc, reg);
709 if ((use & REGUSE_RW) == REGUSE_WRITE) {
710 DisposeHWReg(iRegs[reg].reg);
711 } else {
712 FlushHWReg(iRegs[reg].reg);
713 }
714 } else {
715 FlushHWReg(iRegs[reg].reg);
716 }
717 }
718}
719
720static void iFlushRegs(u32 nextpc) {
721 int i;
722
723 for (i=1; i<NUM_REGISTERS; i++) {
724 iFlushReg(nextpc, i);
725 }
726}
727
728static void Return()
729{
730 iFlushRegs(0);
731 FlushAllHWReg();
732 if (((u32)returnPC & 0x1fffffc) == (u32)returnPC) {
733 BA((u32)returnPC);
734 }
735 else {
736 LIW(0, (u32)returnPC);
737 MTLR(0);
738 BLR();
739 }
740}
741
742static void iRet() {
743 /* store cycle */
744 count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
745 ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
746 Return();
747}
748
749static int iLoadTest() {
750 u32 tmp;
751
752 // check for load delay
753 tmp = psxRegs.code >> 26;
754 switch (tmp) {
755 case 0x10: // COP0
756 switch (_Rs_) {
757 case 0x00: // MFC0
758 case 0x02: // CFC0
759 return 1;
760 }
761 break;
762 case 0x12: // COP2
763 switch (_Funct_) {
764 case 0x00:
765 switch (_Rs_) {
766 case 0x00: // MFC2
767 case 0x02: // CFC2
768 return 1;
769 }
770 break;
771 }
772 break;
773 case 0x32: // LWC2
774 return 1;
775 default:
776 if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
777 return 1;
778 }
779 break;
780 }
781 return 0;
782}
783
784/* set a pending branch */
785static void SetBranch() {
786 int treg;
787 branch = 1;
788 psxRegs.code = PSXMu32(pc);
789 pc+=4;
790
791 if (iLoadTest() == 1) {
792 iFlushRegs(0);
793 LIW(0, psxRegs.code);
794 STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS));
795 /* store cycle */
796 count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
797 ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
798
799 treg = GetHWRegSpecial(TARGET);
800 MR(PutHWRegSpecial(ARG2), treg);
801 DisposeHWReg(GetHWRegFromCPUReg(treg));
802 LIW(PutHWRegSpecial(ARG1), _Rt_);
803 LIW(GetHWRegSpecial(PSXPC), pc);
804 FlushAllHWReg();
805 CALLFunc((u32)psxDelayTest);
806
807 Return();
808 return;
809 }
810
811 recBSC[psxRegs.code>>26]();
812
813 iFlushRegs(0);
814 treg = GetHWRegSpecial(TARGET);
815 MR(PutHWRegSpecial(PSXPC), GetHWRegSpecial(TARGET)); // FIXME: this line should not be needed
816 DisposeHWReg(GetHWRegFromCPUReg(treg));
817 FlushAllHWReg();
818
819 count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
820 ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
821 FlushAllHWReg();
822 CALLFunc((u32)psxBranchTest);
823
824 // TODO: don't return if target is compiled
825 Return();
826}
827
828static void iJump(u32 branchPC) {
829 u32 *b1, *b2;
830 branch = 1;
831 psxRegs.code = PSXMu32(pc);
832 pc+=4;
833
834 if (iLoadTest() == 1) {
835 iFlushRegs(0);
836 LIW(0, psxRegs.code);
837 STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS));
838 /* store cycle */
839 count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
840 ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
841
842 LIW(PutHWRegSpecial(ARG2), branchPC);
843 LIW(PutHWRegSpecial(ARG1), _Rt_);
844 LIW(GetHWRegSpecial(PSXPC), pc);
845 FlushAllHWReg();
846 CALLFunc((u32)psxDelayTest);
847
848 Return();
849 return;
850 }
851
852 recBSC[psxRegs.code>>26]();
853
854 iFlushRegs(branchPC);
855 LIW(PutHWRegSpecial(PSXPC), branchPC);
856 FlushAllHWReg();
857
858 count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
859 //if (/*psxRegs.code == 0 &&*/ count == 2 && branchPC == pcold) {
860 // LIW(PutHWRegSpecial(CYCLECOUNT), 0);
861 //} else {
862 ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
863 //}
864 FlushAllHWReg();
865 CALLFunc((u32)psxBranchTest);
866
867 if (!Config.HLE && Config.PsxOut &&
868 ((branchPC & 0x1fffff) == 0xa0 ||
869 (branchPC & 0x1fffff) == 0xb0 ||
870 (branchPC & 0x1fffff) == 0xc0))
871 CALLFunc((u32)psxJumpTest);
872
873 // always return for now...
874 //Return();
875
876 // maybe just happened an interruption, check so
877 LIW(0, branchPC);
878 CMPLW(GetHWRegSpecial(PSXPC), 0);
879 BNE_L(b1);
880
881 LIW(3, PC_REC(branchPC));
882 LWZ(3, 0, 3);
883 CMPLWI(3, 0);
884 BNE_L(b2);
885
886 B_DST(b1);
887 Return();
888
889 // next bit is already compiled - jump right to it
890 B_DST(b2);
891 MTCTR(3);
892 BCTR();
893}
894
895static void iBranch(u32 branchPC, int savectx) {
896 HWRegister HWRegistersS[NUM_HW_REGISTERS];
897 iRegisters iRegsS[NUM_REGISTERS];
898 int HWRegUseCountS = 0;
899 u32 respold=0;
900 u32 *b1, *b2;
901
902 if (savectx) {
903 respold = resp;
904 memcpy(iRegsS, iRegs, sizeof(iRegs));
905 memcpy(HWRegistersS, HWRegisters, sizeof(HWRegisters));
906 HWRegUseCountS = HWRegUseCount;
907 }
908
909 branch = 1;
910 psxRegs.code = PSXMu32(pc);
911
912 // the delay test is only made when the branch is taken
913 // savectx == 0 will mean that :)
914 if (savectx == 0 && iLoadTest() == 1) {
915 iFlushRegs(0);
916 LIW(0, psxRegs.code);
917 STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS));
918 /* store cycle */
919 count = (idlecyclecount + ((pc+4) - pcold) / 4) * BIAS;
920 ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
921
922 LIW(PutHWRegSpecial(ARG2), branchPC);
923 LIW(PutHWRegSpecial(ARG1), _Rt_);
924 LIW(GetHWRegSpecial(PSXPC), pc);
925 FlushAllHWReg();
926 CALLFunc((u32)psxDelayTest);
927
928 Return();
929 return;
930 }
931
932 pc+= 4;
933 recBSC[psxRegs.code>>26]();
934
935 iFlushRegs(branchPC);
936 LIW(PutHWRegSpecial(PSXPC), branchPC);
937 FlushAllHWReg();
938
939 /* store cycle */
940 count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
941 //if (/*psxRegs.code == 0 &&*/ count == 2 && branchPC == pcold) {
942 // LIW(PutHWRegSpecial(CYCLECOUNT), 0);
943 //} else {
944 ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
945 //}
946 FlushAllHWReg();
947 CALLFunc((u32)psxBranchTest);
948
949 // always return for now...
950 //Return();
951
952 LIW(0, branchPC);
953 CMPLW(GetHWRegSpecial(PSXPC), 0);
954 BNE_L(b1);
955
956 LIW(3, PC_REC(branchPC));
957 LWZ(3, 0, 3);
958 CMPLWI(3, 0);
959 BNE_L(b2);
960
961 B_DST(b1);
962 Return();
963
964 B_DST(b2);
965 MTCTR(3);
966 BCTR();
967
968 // maybe just happened an interruption, check so
969/* CMP32ItoM((u32)&psxRegs.pc, branchPC);
970 j8Ptr[1] = JE8(0);
971 RET();
972
973 x86SetJ8(j8Ptr[1]);
974 MOV32MtoR(EAX, PC_REC(branchPC));
975 TEST32RtoR(EAX, EAX);
976 j8Ptr[2] = JNE8(0);
977 RET();
978
979 x86SetJ8(j8Ptr[2]);
980 JMP32R(EAX);*/
981
982 pc-= 4;
983 if (savectx) {
984 resp = respold;
985 memcpy(iRegs, iRegsS, sizeof(iRegs));
986 memcpy(HWRegisters, HWRegistersS, sizeof(HWRegisters));
987 HWRegUseCount = HWRegUseCountS;
988 }
989}
990
991
992static void iDumpRegs() {
993 int i, j;
994
995 printf("%lx %lx\n", psxRegs.pc, psxRegs.cycle);
996 for (i=0; i<4; i++) {
997 for (j=0; j<8; j++)
998 printf("%lx ", psxRegs.GPR.r[j*i]);
999 printf("\n");
1000 }
1001}
1002
1003void iDumpBlock(char *ptr) {
1004/* FILE *f;
1005 u32 i;
1006
1007 SysPrintf("dump1 %x:%x, %x\n", psxRegs.pc, pc, psxCurrentCycle);
1008
1009 for (i = psxRegs.pc; i < pc; i+=4)
1010 SysPrintf("%s\n", disR3000AF(PSXMu32(i), i));
1011
1012 fflush(stdout);
1013 f = fopen("dump1", "w");
1014 fwrite(ptr, 1, (u32)x86Ptr - (u32)ptr, f);
1015 fclose(f);
1016 system("ndisasmw -u dump1");
1017 fflush(stdout);*/
1018}
1019
1020#define REC_FUNC(f) \
1021void psx##f(); \
1022static void rec##f() { \
1023 iFlushRegs(0); \
1024 LIW(PutHWRegSpecial(ARG1), (u32)psxRegs.code); \
1025 STW(GetHWRegSpecial(ARG1), OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \
1026 LIW(PutHWRegSpecial(PSXPC), (u32)pc); \
1027 FlushAllHWReg(); \
1028 CALLFunc((u32)psx##f); \
1029/* branch = 2; */\
1030}
1031
1032#define REC_SYS(f) \
1033void psx##f(); \
1034static void rec##f() { \
1035 iFlushRegs(0); \
1036 LIW(PutHWRegSpecial(ARG1), (u32)psxRegs.code); \
1037 STW(GetHWRegSpecial(ARG1), OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \
1038 LIW(PutHWRegSpecial(PSXPC), (u32)pc); \
1039 FlushAllHWReg(); \
1040 CALLFunc((u32)psx##f); \
1041 branch = 2; \
1042 iRet(); \
1043}
1044
1045#define REC_BRANCH(f) \
1046void psx##f(); \
1047static void rec##f() { \
1048 iFlushRegs(0); \
1049 LIW(PutHWRegSpecial(ARG1), (u32)psxRegs.code); \
1050 STW(GetHWRegSpecial(ARG1), OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \
1051 LIW(PutHWRegSpecial(PSXPC), (u32)pc); \
1052 FlushAllHWReg(); \
1053 CALLFunc((u32)psx##f); \
1054 branch = 2; \
1055 iRet(); \
1056}
1057
1058static void freeMem(int all)
1059{
1060 if (recMem) free(recMem);
1061 if (recRAM) free(recRAM);
1062 if (recROM) free(recROM);
1063 recMem = recRAM = recROM = 0;
1064
1065 if (all && psxRecLUT) {
1066 free(psxRecLUT); psxRecLUT = NULL;
1067 }
1068}
1069
1070static int allocMem() {
1071 int i;
1072
1073 freeMem(0);
1074
1075 if (psxRecLUT==NULL)
1076 psxRecLUT = (u32*) malloc(0x010000 * 4);
1077
1078 recMem = (char*) malloc(RECMEM_SIZE);
1079 //recMem = mmap(NULL, RECMEM_SIZE, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
1080 recRAM = (char*) malloc(0x200000);
1081 recROM = (char*) malloc(0x080000);
1082 if (recRAM == NULL || recROM == NULL || recMem == NULL/*(void *)-1*/ || psxRecLUT == NULL) {
1083 freeMem(1);
1084 SysMessage("Error allocating memory"); return -1;
1085 }
1086
1087 for (i=0; i<0x80; i++) psxRecLUT[i + 0x0000] = (u32)&recRAM[(i & 0x1f) << 16];
1088 memcpy(psxRecLUT + 0x8000, psxRecLUT, 0x80 * 4);
1089 memcpy(psxRecLUT + 0xa000, psxRecLUT, 0x80 * 4);
1090
1091 for (i=0; i<0x08; i++) psxRecLUT[i + 0xbfc0] = (u32)&recROM[i << 16];
1092
1093 return 0;
1094}
1095
1096static int recInit() {
1097 return allocMem();
1098}
1099
1100static void recReset() {
1101 memset(recRAM, 0, 0x200000);
1102 memset(recROM, 0, 0x080000);
1103
1104 ppcInit();
1105 ppcSetPtr((u32 *)recMem);
1106
1107 branch = 0;
1108 memset(iRegs, 0, sizeof(iRegs));
1109 iRegs[0].state = ST_CONST;
1110 iRegs[0].k = 0;
1111}
1112
1113static void recShutdown() {
1114 freeMem(1);
1115 ppcShutdown();
1116}
1117
1118static void recError() {
1119 SysReset();
1120 ClosePlugins();
1121 SysMessage("Unrecoverable error while running recompiler\n");
1122 SysRunGui();
1123}
1124
1125__inline static void execute() {
1126 void (**recFunc)();
1127 char *p;
1128
1129 p = (char*)PC_REC(psxRegs.pc);
1130 /*if (p != NULL)*/ recFunc = (void (**)()) (u32)p;
1131 /*else { recError(); return; }*/
1132
1133 if (*recFunc == 0) {
1134 recRecompile();
1135 }
1136 recRun(*recFunc, (u32)&psxRegs, (u32)&psxM);
1137}
1138
1139static void recExecute() {
1140 for (;;) execute();
1141}
1142
1143static void recExecuteBlock() {
1144 execute();
1145}
1146
1147static void recClear(u32 Addr, u32 Size) {
1148 memset((void*)PC_REC(Addr), 0, Size * 4);
1149}
1150
1151static void recNULL() {
1152// SysMessage("recUNK: %8.8x\n", psxRegs.code);
1153}
1154
1155/*********************************************************
1156* goes to opcodes tables... *
1157* Format: table[something....] *
1158*********************************************************/
1159
1160//REC_SYS(SPECIAL);
1161static void recSPECIAL() {
1162 recSPC[_Funct_]();
1163}
1164
1165static void recREGIMM() {
1166 recREG[_Rt_]();
1167}
1168
1169static void recCOP0() {
1170 recCP0[_Rs_]();
1171}
1172
1173//REC_SYS(COP2);
1174static void recCOP2() {
1175 recCP2[_Funct_]();
1176}
1177
1178static void recBASIC() {
1179 recCP2BSC[_Rs_]();
1180}
1181
1182//end of Tables opcodes...
1183
1184#pragma mark - Arithmetic with immediate operand -
1185/*********************************************************
1186* Arithmetic with immediate operand *
1187* Format: OP rt, rs, immediate *
1188*********************************************************/
1189
1190#if 0
1191/*REC_FUNC(ADDI);
1192REC_FUNC(ADDIU);
1193REC_FUNC(ANDI);
1194REC_FUNC(ORI);
1195REC_FUNC(XORI);
1196REC_FUNC(SLTI);
1197REC_FUNC(SLTIU);*/
1198#else
1199static void recADDIU() {
1200// Rt = Rs + Im
1201 if (!_Rt_) return;
1202
1203 if (IsConst(_Rs_)) {
1204 MapConst(_Rt_, iRegs[_Rs_].k + _Imm_);
1205 } else {
1206 if (_Imm_ == 0) {
1207 MapCopy(_Rt_, _Rs_);
1208 } else {
1209 ADDI(PutHWReg32(_Rt_), GetHWReg32(_Rs_), _Imm_);
1210 }
1211 }
1212}
1213
1214static void recADDI() {
1215// Rt = Rs + Im
1216 recADDIU();
1217}
1218
1219//REC_FUNC(SLTI);
1220//REC_FUNC(SLTIU);
1221//CR0: SIGN | POSITIVE | ZERO | SOVERFLOW | SOVERFLOW | OVERFLOW | CARRY
1222static void recSLTI() {
1223// Rt = Rs < Im (signed)
1224 if (!_Rt_) return;
1225
1226 if (IsConst(_Rs_)) {
1227 MapConst(_Rt_, (s32)iRegs[_Rs_].k < _Imm_);
1228 } else {
1229 if (_Imm_ == 0) {
1230 SRWI(PutHWReg32(_Rt_), GetHWReg32(_Rs_), 31);
1231 } else {
1232 int reg;
1233 CMPWI(GetHWReg32(_Rs_), _Imm_);
1234 reg = PutHWReg32(_Rt_);
1235 LI(reg, 1);
1236 BLT(1);
1237 LI(reg, 0);
1238 }
1239 }
1240}
1241
1242static void recSLTIU() {
1243// Rt = Rs < Im (unsigned)
1244 if (!_Rt_) return;
1245
1246 if (IsConst(_Rs_)) {
1247 MapConst(_Rt_, iRegs[_Rs_].k < _ImmU_);
1248 } else {
1249 int reg;
1250 CMPLWI(GetHWReg32(_Rs_), _Imm_);
1251 reg = PutHWReg32(_Rt_);
1252 LI(reg, 1);
1253 BLT(1);
1254 LI(reg, 0);
1255 }
1256}
1257
1258static void recANDI() {
1259// Rt = Rs And Im
1260 if (!_Rt_) return;
1261
1262 if (IsConst(_Rs_)) {
1263 MapConst(_Rt_, iRegs[_Rs_].k & _ImmU_);
1264 } else {
1265 ANDI_(PutHWReg32(_Rt_), GetHWReg32(_Rs_), _ImmU_);
1266 }
1267}
1268
1269static void recORI() {
1270// Rt = Rs Or Im
1271 if (!_Rt_) return;
1272
1273 if (IsConst(_Rs_)) {
1274 MapConst(_Rt_, iRegs[_Rs_].k | _ImmU_);
1275 } else {
1276 if (_Imm_ == 0) {
1277 MapCopy(_Rt_, _Rs_);
1278 } else {
1279 ORI(PutHWReg32(_Rt_), GetHWReg32(_Rs_), _ImmU_);
1280 }
1281 }
1282}
1283
1284static void recXORI() {
1285// Rt = Rs Xor Im
1286 if (!_Rt_) return;
1287
1288 if (IsConst(_Rs_)) {
1289 MapConst(_Rt_, iRegs[_Rs_].k ^ _ImmU_);
1290 } else {
1291 XORI(PutHWReg32(_Rt_), GetHWReg32(_Rs_), _ImmU_);
1292 }
1293}
1294#endif
1295//end of * Arithmetic with immediate operand
1296
1297/*********************************************************
1298* Load higher 16 bits of the first word in GPR with imm *
1299* Format: OP rt, immediate *
1300*********************************************************/
1301//REC_FUNC(LUI);
1302//#if 0*/
1303static void recLUI() {
1304// Rt = Imm << 16
1305 if (!_Rt_) return;
1306
1307 MapConst(_Rt_, psxRegs.code << 16);
1308}
1309//#endif
1310//End of Load Higher .....
1311
1312#pragma mark - Register arithmetic -
1313/*********************************************************
1314* Register arithmetic *
1315* Format: OP rd, rs, rt *
1316*********************************************************/
1317
1318#if 0
1319/*REC_FUNC(ADD);
1320REC_FUNC(ADDU);
1321REC_FUNC(SUB);
1322REC_FUNC(SUBU);
1323REC_FUNC(AND);
1324REC_FUNC(OR);
1325REC_FUNC(XOR);
1326REC_FUNC(NOR);
1327REC_FUNC(SLT);
1328REC_FUNC(SLTU);*/
1329#else
1330static void recADDU() {
1331// Rd = Rs + Rt
1332 if (!_Rd_) return;
1333
1334 if (IsConst(_Rs_) && IsConst(_Rt_)) {
1335 MapConst(_Rd_, iRegs[_Rs_].k + iRegs[_Rt_].k);
1336 } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
1337 if ((s32)(s16)iRegs[_Rs_].k == (s32)iRegs[_Rs_].k) {
1338 ADDI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), (s16)iRegs[_Rs_].k);
1339 } else if ((iRegs[_Rs_].k & 0xffff) == 0) {
1340 ADDIS(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k>>16);
1341 } else {
1342 ADD(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1343 }
1344 } else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
1345 if ((s32)(s16)iRegs[_Rt_].k == (s32)iRegs[_Rt_].k) {
1346 ADDI(PutHWReg32(_Rd_), GetHWReg32(_Rs_), (s16)iRegs[_Rt_].k);
1347 } else if ((iRegs[_Rt_].k & 0xffff) == 0) {
1348 ADDIS(PutHWReg32(_Rd_), GetHWReg32(_Rs_), iRegs[_Rt_].k>>16);
1349 } else {
1350 ADD(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1351 }
1352 } else {
1353 ADD(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1354 }
1355}
1356
1357static void recADD() {
1358// Rd = Rs + Rt
1359 recADDU();
1360}
1361
1362static void recSUBU() {
1363// Rd = Rs - Rt
1364 if (!_Rd_) return;
1365
1366 if (IsConst(_Rs_) && IsConst(_Rt_)) {
1367 MapConst(_Rd_, iRegs[_Rs_].k - iRegs[_Rt_].k);
1368 } else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
1369 if ((s32)(s16)(-iRegs[_Rt_].k) == (s32)(-iRegs[_Rt_].k)) {
1370 ADDI(PutHWReg32(_Rd_), GetHWReg32(_Rs_), -iRegs[_Rt_].k);
1371 } else if (((-iRegs[_Rt_].k) & 0xffff) == 0) {
1372 ADDIS(PutHWReg32(_Rd_), GetHWReg32(_Rs_), (-iRegs[_Rt_].k)>>16);
1373 } else {
1374 SUB(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1375 }
1376 } else {
1377 SUB(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1378 }
1379}
1380
1381static void recSUB() {
1382// Rd = Rs - Rt
1383 recSUBU();
1384}
1385
1386static void recAND() {
1387// Rd = Rs And Rt
1388 if (!_Rd_) return;
1389
1390 if (IsConst(_Rs_) && IsConst(_Rt_)) {
1391 MapConst(_Rd_, iRegs[_Rs_].k & iRegs[_Rt_].k);
1392 } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
1393 // TODO: implement shifted (ANDIS) versions of these
1394 if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) {
1395 ANDI_(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k);
1396 } else {
1397 AND(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1398 }
1399 } else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
1400 if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) {
1401 ANDI_(PutHWReg32(_Rd_), GetHWReg32(_Rs_), iRegs[_Rt_].k);
1402 } else {
1403 AND(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1404 }
1405 } else {
1406 AND(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1407 }
1408}
1409
1410static void recOR() {
1411// Rd = Rs Or Rt
1412 if (!_Rd_) return;
1413
1414 if (IsConst(_Rs_) && IsConst(_Rt_)) {
1415 MapConst(_Rd_, iRegs[_Rs_].k | iRegs[_Rt_].k);
1416 }
1417 else {
1418 if (_Rs_ == _Rt_) {
1419 MapCopy(_Rd_, _Rs_);
1420 }
1421 else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
1422 if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) {
1423 ORI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k);
1424 } else {
1425 OR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1426 }
1427 }
1428 else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
1429 if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) {
1430 ORI(PutHWReg32(_Rd_), GetHWReg32(_Rs_), iRegs[_Rt_].k);
1431 } else {
1432 OR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1433 }
1434 } else {
1435 OR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1436 }
1437 }
1438}
1439
1440static void recXOR() {
1441// Rd = Rs Xor Rt
1442 if (!_Rd_) return;
1443
1444 if (IsConst(_Rs_) && IsConst(_Rt_)) {
1445 MapConst(_Rd_, iRegs[_Rs_].k ^ iRegs[_Rt_].k);
1446 } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
1447 if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) {
1448 XORI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k);
1449 } else {
1450 XOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1451 }
1452 } else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
1453 if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) {
1454 XORI(PutHWReg32(_Rd_), GetHWReg32(_Rs_), iRegs[_Rt_].k);
1455 } else {
1456 XOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1457 }
1458 } else {
1459 XOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1460 }
1461}
1462
1463static void recNOR() {
1464// Rd = Rs Nor Rt
1465 if (!_Rd_) return;
1466
1467 if (IsConst(_Rs_) && IsConst(_Rt_)) {
1468 MapConst(_Rd_, ~(iRegs[_Rs_].k | iRegs[_Rt_].k));
1469 } /*else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
1470 if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) {
1471 NORI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k);
1472 } else {
1473 NOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1474 }
1475 } else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
1476 if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) {
1477 NORI(PutHWReg32(_Rd_), GetHWReg32(_Rs_), iRegs[_Rt_].k);
1478 } else {
1479 NOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1480 }
1481 } */else {
1482 NOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1483 }
1484}
1485
1486static void recSLT() {
1487// Rd = Rs < Rt (signed)
1488 if (!_Rd_) return;
1489
1490 if (IsConst(_Rs_) && IsConst(_Rt_)) {
1491 MapConst(_Rd_, (s32)iRegs[_Rs_].k < (s32)iRegs[_Rt_].k);
1492 } else { // TODO: add immidiate cases
1493 int reg;
1494 CMPW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1495 reg = PutHWReg32(_Rd_);
1496 LI(reg, 1);
1497 BLT(1);
1498 LI(reg, 0);
1499 }
1500}
1501
1502static void recSLTU() {
1503// Rd = Rs < Rt (unsigned)
1504 if (!_Rd_) return;
1505
1506 if (IsConst(_Rs_) && IsConst(_Rt_)) {
1507 MapConst(_Rd_, iRegs[_Rs_].k < iRegs[_Rt_].k);
1508 } else { // TODO: add immidiate cases
1509 SUBFC(PutHWReg32(_Rd_), GetHWReg32(_Rt_), GetHWReg32(_Rs_));
1510 SUBFE(PutHWReg32(_Rd_), GetHWReg32(_Rd_), GetHWReg32(_Rd_));
1511 NEG(PutHWReg32(_Rd_), GetHWReg32(_Rd_));
1512 }
1513}
1514#endif
1515//End of * Register arithmetic
1516
1517#pragma mark - mult/div & Register trap logic -
1518/*********************************************************
1519* Register mult/div & Register trap logic *
1520* Format: OP rs, rt *
1521*********************************************************/
1522
1523#if 0
1524REC_FUNC(MULT);
1525REC_FUNC(MULTU);
1526REC_FUNC(DIV);
1527REC_FUNC(DIVU);
1528#else
1529
1530int DoShift(u32 k)
1531{
1532 u32 i;
1533 for (i=0; i<30; i++) {
1534 if (k == (1ul << i))
1535 return i;
1536 }
1537 return -1;
1538}
1539
1540//REC_FUNC(MULT);
1541
1542// FIXME: doesn't work in GT - wrong way marker
1543static void recMULT() {
1544// Lo/Hi = Rs * Rt (signed)
1545 s32 k; int r;
1546 int usehi, uselo;
1547
1548 if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) ||
1549 (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) {
1550 MapConst(REG_LO, 0);
1551 MapConst(REG_HI, 0);
1552 return;
1553 }
1554
1555 if (IsConst(_Rs_) && IsConst(_Rt_)) {
1556 u64 res = (s64)((s64)(s32)iRegs[_Rs_].k * (s64)(s32)iRegs[_Rt_].k);
1557 MapConst(REG_LO, (res & 0xffffffff));
1558 MapConst(REG_HI, ((res >> 32) & 0xffffffff));
1559 return;
1560 }
1561
1562 if (IsConst(_Rs_)) {
1563 k = (s32)iRegs[_Rs_].k;
1564 r = _Rt_;
1565 } else if (IsConst(_Rt_)) {
1566 k = (s32)iRegs[_Rt_].k;
1567 r = _Rs_;
1568 } else {
1569 r = -1;
1570 k = 0;
1571 }
1572
1573 // FIXME: this should not be needed!!!
1574// uselo = isPsxRegUsed(pc, REG_LO);
1575// usehi = isPsxRegUsed(pc, REG_HI);
1576 uselo = 1; //isPsxRegUsed(pc, REG_LO);
1577 usehi = 1; //isPsxRegUsed(pc, REG_HI);
1578
1579
1580 if (r != -1) {
1581 int shift = DoShift(k);
1582 if (shift != -1) {
1583 if (uselo) {
1584 SLWI(PutHWReg32(REG_LO), GetHWReg32(r), shift)
1585 }
1586 if (usehi) {
1587 SRAWI(PutHWReg32(REG_HI), GetHWReg32(r), 31-shift);
1588 }
1589 } else {
1590 //if ((s32)(s16)k == k) {
1591 // MULLWI(PutHWReg32(REG_LO), GetHWReg32(r), k);
1592 // MULHWI(PutHWReg32(REG_HI), GetHWReg32(r), k);
1593 //} else
1594 {
1595 if (uselo) {
1596 MULLW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1597 }
1598 if (usehi) {
1599 MULHW(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1600 }
1601 }
1602 }
1603 } else {
1604 if (uselo) {
1605 MULLW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1606 }
1607 if (usehi) {
1608 MULHW(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1609 }
1610 }
1611}
1612
1613static void recMULTU() {
1614// Lo/Hi = Rs * Rt (unsigned)
1615 u32 k; int r;
1616 int usehi, uselo;
1617
1618 if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) ||
1619 (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) {
1620 MapConst(REG_LO, 0);
1621 MapConst(REG_HI, 0);
1622 return;
1623 }
1624
1625 if (IsConst(_Rs_) && IsConst(_Rt_)) {
1626 u64 res = (u64)((u64)(u32)iRegs[_Rs_].k * (u64)(u32)iRegs[_Rt_].k);
1627 MapConst(REG_LO, (res & 0xffffffff));
1628 MapConst(REG_HI, ((res >> 32) & 0xffffffff));
1629 return;
1630 }
1631
1632 if (IsConst(_Rs_)) {
1633 k = (s32)iRegs[_Rs_].k;
1634 r = _Rt_;
1635 } else if (IsConst(_Rt_)) {
1636 k = (s32)iRegs[_Rt_].k;
1637 r = _Rs_;
1638 } else {
1639 r = -1;
1640 k = 0;
1641 }
1642
1643 uselo = isPsxRegUsed(pc, REG_LO);
1644 usehi = isPsxRegUsed(pc, REG_HI);
1645
1646 if (r != -1) {
1647 int shift = DoShift(k);
1648 if (shift != -1) {
1649 if (uselo) {
1650 SLWI(PutHWReg32(REG_LO), GetHWReg32(r), shift);
1651 }
1652 if (usehi) {
1653 SRWI(PutHWReg32(REG_HI), GetHWReg32(r), 31-shift);
1654 }
1655 } else {
1656 {
1657 if (uselo) {
1658 MULLW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1659 }
1660 if (usehi) {
1661 MULHWU(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1662 }
1663 }
1664 }
1665 } else {
1666 if (uselo) {
1667 MULLW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1668 }
1669 if (usehi) {
1670 MULHWU(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1671 }
1672 }
1673}
1674
1675static void recDIV() {
1676// Lo/Hi = Rs / Rt (signed)
1677 int usehi;
1678
1679 if (IsConst(_Rs_) && iRegs[_Rs_].k == 0) {
1680 MapConst(REG_LO, 0);
1681 MapConst(REG_HI, 0);
1682 return;
1683 }
1684 if (IsConst(_Rt_) && IsConst(_Rs_)) {
1685 MapConst(REG_LO, (s32)iRegs[_Rs_].k / (s32)iRegs[_Rt_].k);
1686 MapConst(REG_HI, (s32)iRegs[_Rs_].k % (s32)iRegs[_Rt_].k);
1687 return;
1688 }
1689
1690 usehi = isPsxRegUsed(pc, REG_HI);
1691
1692 if (IsConst(_Rt_)) {
1693 int shift = DoShift(iRegs[_Rt_].k);
1694 if (shift != -1) {
1695 SRAWI(PutHWReg32(REG_LO), GetHWReg32(_Rs_), shift);
1696 ADDZE(PutHWReg32(REG_LO), GetHWReg32(REG_LO));
1697 if (usehi) {
1698 RLWINM(PutHWReg32(REG_HI), GetHWReg32(_Rs_), 0, 31-shift, 31);
1699 }
1700 } else if (iRegs[_Rt_].k == 3) {
1701 // http://the.wall.riscom.net/books/proc/ppc/cwg/code2.html
1702 LIS(PutHWReg32(REG_HI), 0x5555);
1703 ADDI(PutHWReg32(REG_HI), GetHWReg32(REG_HI), 0x5556);
1704 MULHW(PutHWReg32(REG_LO), GetHWReg32(REG_HI), GetHWReg32(_Rs_));
1705 SRWI(PutHWReg32(REG_HI), GetHWReg32(_Rs_), 31);
1706 ADD(PutHWReg32(REG_LO), GetHWReg32(REG_LO), GetHWReg32(REG_HI));
1707 if (usehi) {
1708 MULLI(PutHWReg32(REG_HI), GetHWReg32(REG_LO), 3);
1709 SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI));
1710 }
1711 } else {
1712 DIVW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1713 if (usehi) {
1714 if ((iRegs[_Rt_].k & 0x7fff) == iRegs[_Rt_].k) {
1715 MULLI(PutHWReg32(REG_HI), GetHWReg32(REG_LO), iRegs[_Rt_].k);
1716 } else {
1717 MULLW(PutHWReg32(REG_HI), GetHWReg32(REG_LO), GetHWReg32(_Rt_));
1718 }
1719 SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI));
1720 }
1721 }
1722 } else {
1723 DIVW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1724 if (usehi) {
1725 MULLW(PutHWReg32(REG_HI), GetHWReg32(REG_LO), GetHWReg32(_Rt_));
1726 SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI));
1727 }
1728 }
1729}
1730
1731static void recDIVU() {
1732// Lo/Hi = Rs / Rt (unsigned)
1733 int usehi;
1734
1735 if (IsConst(_Rs_) && iRegs[_Rs_].k == 0) {
1736 MapConst(REG_LO, 0);
1737 MapConst(REG_HI, 0);
1738 return;
1739 }
1740 if (IsConst(_Rt_) && IsConst(_Rs_)) {
1741 MapConst(REG_LO, (u32)iRegs[_Rs_].k / (u32)iRegs[_Rt_].k);
1742 MapConst(REG_HI, (u32)iRegs[_Rs_].k % (u32)iRegs[_Rt_].k);
1743 return;
1744 }
1745
1746 usehi = isPsxRegUsed(pc, REG_HI);
1747
1748 if (IsConst(_Rt_)) {
1749 int shift = DoShift(iRegs[_Rt_].k);
1750 if (shift != -1) {
1751 SRWI(PutHWReg32(REG_LO), GetHWReg32(_Rs_), shift);
1752 if (usehi) {
1753 RLWINM(PutHWReg32(REG_HI), GetHWReg32(_Rs_), 0, 31-shift, 31);
1754 }
1755 } else {
1756 DIVWU(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1757 if (usehi) {
1758 MULLW(PutHWReg32(REG_HI), GetHWReg32(_Rt_), GetHWReg32(REG_LO));
1759 SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI));
1760 }
1761 }
1762 } else {
1763 DIVWU(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1764 if (usehi) {
1765 MULLW(PutHWReg32(REG_HI), GetHWReg32(_Rt_), GetHWReg32(REG_LO));
1766 SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI));
1767 }
1768 }
1769}
1770#endif
1771//End of * Register mult/div & Register trap logic
1772
1773#pragma mark - memory access -
1774
1775#if 0
1776REC_FUNC(LB);
1777REC_FUNC(LBU);
1778REC_FUNC(LH);
1779REC_FUNC(LHU);
1780REC_FUNC(LW);
1781
1782REC_FUNC(SB);
1783REC_FUNC(SH);
1784REC_FUNC(SW);
1785
1786REC_FUNC(LWL);
1787REC_FUNC(LWR);
1788REC_FUNC(SWL);
1789REC_FUNC(SWR);
1790#else
1791static void preMemRead()
1792{
1793 int rs;
1794
1795 ReserveArgs(1);
1796 if (_Rs_ != _Rt_) {
1797 DisposeHWReg(iRegs[_Rt_].reg);
1798 }
1799 rs = GetHWReg32(_Rs_);
1800 if (rs != 3 || _Imm_ != 0) {
1801 ADDI(PutHWRegSpecial(ARG1), rs, _Imm_);
1802 }
1803 if (_Rs_ == _Rt_) {
1804 DisposeHWReg(iRegs[_Rt_].reg);
1805 }
1806 InvalidateCPURegs();
1807 //FlushAllHWReg();
1808}
1809
1810static void preMemWrite(int size)
1811{
1812 int rs;
1813
1814 ReserveArgs(2);
1815 rs = GetHWReg32(_Rs_);
1816 if (rs != 3 || _Imm_ != 0) {
1817 ADDI(PutHWRegSpecial(ARG1), rs, _Imm_);
1818 }
1819 if (size == 1) {
1820 RLWINM(PutHWRegSpecial(ARG2), GetHWReg32(_Rt_), 0, 24, 31);
1821 //ANDI_(PutHWRegSpecial(ARG2), GetHWReg32(_Rt_), 0xff);
1822 } else if (size == 2) {
1823 RLWINM(PutHWRegSpecial(ARG2), GetHWReg32(_Rt_), 0, 16, 31);
1824 //ANDI_(PutHWRegSpecial(ARG2), GetHWReg32(_Rt_), 0xffff);
1825 } else {
1826 MR(PutHWRegSpecial(ARG2), GetHWReg32(_Rt_));
1827 }
1828
1829 InvalidateCPURegs();
1830 //FlushAllHWReg();
1831}
1832
1833static void recLB() {
1834// Rt = mem[Rs + Im] (signed)
1835
1836 /*if (IsConst(_Rs_)) {
1837 u32 addr = iRegs[_Rs_].k + _Imm_;
1838 int t = addr >> 16;
1839
1840 if ((t & 0xfff0) == 0xbfc0) {
1841 if (!_Rt_) return;
1842 // since bios is readonly it won't change
1843 MapConst(_Rt_, psxRs8(addr));
1844 return;
1845 }
1846 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1847 if (!_Rt_) return;
1848
1849 addr = (u32)&psxM[addr & 0x1fffff];
1850 LIW(PutHWReg32(_Rt_), ((addr>>16)<<16)+(addr&0x8000<<1)); // FIXME: is this correct?
1851 LBZ(PutHWReg32(_Rt_), addr&0xffff, GetHWReg32(_Rt_));
1852 EXTSB(PutHWReg32(_Rt_), GetHWReg32(_Rt_));
1853 return;
1854 }
1855 if (t == 0x1f80 && addr < 0x1f801000) {
1856 if (!_Rt_) return;
1857
1858 addr = (u32)&psxH[addr & 0xfff];
1859 LIW(PutHWReg32(_Rt_), ((addr>>16)<<16)+(addr&0x8000<<1)); // FIXME: is this correct?
1860 LBZ(PutHWReg32(_Rt_), addr&0xffff, GetHWReg32(_Rt_));
1861 EXTSB(PutHWReg32(_Rt_), GetHWReg32(_Rt_));
1862 return;
1863 }
1864 // SysPrintf("unhandled r8 %x\n", addr);
1865 }*/
1866
1867 preMemRead();
1868 CALLFunc((u32)psxMemRead8);
1869 if (_Rt_) {
1870 EXTSB(PutHWReg32(_Rt_), GetHWRegSpecial(RETVAL));
1871 DisposeHWReg(GetSpecialIndexFromHWRegs(RETVAL));
1872 }
1873}
1874
1875static void recLBU() {
1876// Rt = mem[Rs + Im] (unsigned)
1877
1878 /*if (IsConst(_Rs_)) {
1879 u32 addr = iRegs[_Rs_].k + _Imm_;
1880 int t = addr >> 16;
1881
1882 if ((t & 0xfff0) == 0xbfc0) {
1883 if (!_Rt_) return;
1884 // since bios is readonly it won't change
1885 MapConst(_Rt_, psxRu8(addr));
1886 return;
1887 }
1888 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1889 if (!_Rt_) return;
1890
1891 addr = (u32)&psxM[addr & 0x1fffff];
1892 LIW(PutHWReg32(_Rt_), ((addr>>16)<<16)+(addr&0x8000<<1)); // FIXME: is this correct?
1893 LBZ(PutHWReg32(_Rt_), addr&0xffff, GetHWReg32(_Rt_));
1894 return;
1895 }
1896 if (t == 0x1f80 && addr < 0x1f801000) {
1897 if (!_Rt_) return;
1898
1899 addr = (u32)&psxH[addr & 0xfff];
1900 LIW(PutHWReg32(_Rt_), ((addr>>16)<<16)+(addr&0x8000<<1)); // FIXME: is this correct?
1901 LBZ(PutHWReg32(_Rt_), addr&0xffff, GetHWReg32(_Rt_));
1902 return;
1903 }
1904 // SysPrintf("unhandled r8 %x\n", addr);
1905 }*/
1906
1907 preMemRead();
1908 CALLFunc((u32)psxMemRead8);
1909
1910 if (_Rt_) {
1911 SetDstCPUReg(3);
1912 PutHWReg32(_Rt_);
1913 }
1914}
1915
1916static void recLH() {
1917// Rt = mem[Rs + Im] (signed)
1918
1919 if (IsConst(_Rs_)) {
1920 u32 addr = iRegs[_Rs_].k + _Imm_;
1921 int t = addr >> 16;
1922
1923 if ((t & 0xfff0) == 0xbfc0) {
1924 if (!_Rt_) return;
1925 // since bios is readonly it won't change
1926 MapConst(_Rt_, psxRs16(addr));
1927 return;
1928 }
1929 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1930 if (!_Rt_) return;
1931
1932 LIW(PutHWReg32(_Rt_), (u32)&psxM[addr & 0x1fffff]);
1933 LHBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
1934 EXTSH(PutHWReg32(_Rt_), GetHWReg32(_Rt_));
1935 return;
1936 }
1937 if (t == 0x1f80 && addr < 0x1f801000) {
1938 if (!_Rt_) return;
1939
1940 LIW(PutHWReg32(_Rt_), (u32)&psxH[addr & 0xfff]);
1941 LHBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
1942 EXTSH(PutHWReg32(_Rt_), GetHWReg32(_Rt_));
1943 return;
1944 }
1945 // SysPrintf("unhandled r16 %x\n", addr);
1946 }
1947
1948 preMemRead();
1949 CALLFunc((u32)psxMemRead16);
1950 if (_Rt_) {
1951 EXTSH(PutHWReg32(_Rt_), GetHWRegSpecial(RETVAL));
1952 DisposeHWReg(GetSpecialIndexFromHWRegs(RETVAL));
1953 }
1954}
1955
1956static void recLHU() {
1957// Rt = mem[Rs + Im] (unsigned)
1958
1959 if (IsConst(_Rs_)) {
1960 u32 addr = iRegs[_Rs_].k + _Imm_;
1961 int t = addr >> 16;
1962
1963 if ((t & 0xfff0) == 0xbfc0) {
1964 if (!_Rt_) return;
1965 // since bios is readonly it won't change
1966 MapConst(_Rt_, psxRu16(addr));
1967 return;
1968 }
1969 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1970 if (!_Rt_) return;
1971
1972 LIW(PutHWReg32(_Rt_), (u32)&psxM[addr & 0x1fffff]);
1973 LHBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
1974 return;
1975 }
1976 if (t == 0x1f80 && addr < 0x1f801000) {
1977 if (!_Rt_) return;
1978
1979 LIW(PutHWReg32(_Rt_), (u32)&psxH[addr & 0xfff]);
1980 LHBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
1981 return;
1982 }
1983 if (t == 0x1f80) {
1984 if (addr >= 0x1f801c00 && addr < 0x1f801e00) {
1985 if (!_Rt_) return;
1986
1987 ReserveArgs(1);
1988 LIW(PutHWRegSpecial(ARG1), addr);
1989 DisposeHWReg(iRegs[_Rt_].reg);
1990 InvalidateCPURegs();
1991 CALLFunc((u32)SPU_readRegister);
1992
1993 SetDstCPUReg(3);
1994 PutHWReg32(_Rt_);
1995 return;
1996 }
1997 switch (addr) {
1998 case 0x1f801100: case 0x1f801110: case 0x1f801120:
1999 if (!_Rt_) return;
2000
2001 ReserveArgs(1);
2002 LIW(PutHWRegSpecial(ARG1), (addr >> 4) & 0x3);
2003 DisposeHWReg(iRegs[_Rt_].reg);
2004 InvalidateCPURegs();
2005 CALLFunc((u32)psxRcntRcount);
2006
2007 SetDstCPUReg(3);
2008 PutHWReg32(_Rt_);
2009 return;
2010
2011 case 0x1f801104: case 0x1f801114: case 0x1f801124:
2012 if (!_Rt_) return;
2013
2014 ReserveArgs(1);
2015 LIW(PutHWRegSpecial(ARG1), (addr >> 4) & 0x3);
2016 DisposeHWReg(iRegs[_Rt_].reg);
2017 InvalidateCPURegs();
2018 CALLFunc((u32)psxRcntRmode);
2019
2020 SetDstCPUReg(3);
2021 PutHWReg32(_Rt_);
2022 return;
2023
2024 case 0x1f801108: case 0x1f801118: case 0x1f801128:
2025 if (!_Rt_) return;
2026
2027 ReserveArgs(1);
2028 LIW(PutHWRegSpecial(ARG1), (addr >> 4) & 0x3);
2029 DisposeHWReg(iRegs[_Rt_].reg);
2030 InvalidateCPURegs();
2031 CALLFunc((u32)psxRcntRtarget);
2032
2033 SetDstCPUReg(3);
2034 PutHWReg32(_Rt_);
2035 return;
2036 }
2037 }
2038 // SysPrintf("unhandled r16u %x\n", addr);
2039 }
2040
2041 preMemRead();
2042 CALLFunc((u32)psxMemRead16);
2043 if (_Rt_) {
2044 SetDstCPUReg(3);
2045 PutHWReg32(_Rt_);
2046 }
2047}
2048
2049static void recLW() {
2050// Rt = mem[Rs + Im] (unsigned)
2051
2052 if (IsConst(_Rs_)) {
2053 u32 addr = iRegs[_Rs_].k + _Imm_;
2054 int t = addr >> 16;
2055
2056 if ((t & 0xfff0) == 0xbfc0) {
2057 if (!_Rt_) return;
2058 // since bios is readonly it won't change
2059 MapConst(_Rt_, psxRu32(addr));
2060 return;
2061 }
2062 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2063 if (!_Rt_) return;
2064
2065 LIW(PutHWReg32(_Rt_), (u32)&psxM[addr & 0x1fffff]);
2066 LWBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
2067 return;
2068 }
2069 if (t == 0x1f80 && addr < 0x1f801000) {
2070 if (!_Rt_) return;
2071
2072 LIW(PutHWReg32(_Rt_), (u32)&psxH[addr & 0xfff]);
2073 LWBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
2074 return;
2075 }
2076 if (t == 0x1f80) {
2077 switch (addr) {
2078 case 0x1f801080: case 0x1f801084: case 0x1f801088:
2079 case 0x1f801090: case 0x1f801094: case 0x1f801098:
2080 case 0x1f8010a0: case 0x1f8010a4: case 0x1f8010a8:
2081 case 0x1f8010b0: case 0x1f8010b4: case 0x1f8010b8:
2082 case 0x1f8010c0: case 0x1f8010c4: case 0x1f8010c8:
2083 case 0x1f8010d0: case 0x1f8010d4: case 0x1f8010d8:
2084 case 0x1f8010e0: case 0x1f8010e4: case 0x1f8010e8:
2085 case 0x1f801070: case 0x1f801074:
2086 case 0x1f8010f0: case 0x1f8010f4:
2087 if (!_Rt_) return;
2088
2089 LIW(PutHWReg32(_Rt_), (u32)&psxH[addr & 0xffff]);
2090 LWBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
2091 return;
2092
2093 case 0x1f801810:
2094 if (!_Rt_) return;
2095
2096 DisposeHWReg(iRegs[_Rt_].reg);
2097 InvalidateCPURegs();
2098 CALLFunc((u32)GPU_readData);
2099
2100 SetDstCPUReg(3);
2101 PutHWReg32(_Rt_);
2102 return;
2103
2104 case 0x1f801814:
2105 if (!_Rt_) return;
2106
2107 DisposeHWReg(iRegs[_Rt_].reg);
2108 InvalidateCPURegs();
2109 CALLFunc((u32)GPU_readStatus);
2110
2111 SetDstCPUReg(3);
2112 PutHWReg32(_Rt_);
2113 return;
2114 }
2115 }
2116// SysPrintf("unhandled r32 %x\n", addr);
2117 }
2118
2119 preMemRead();
2120 CALLFunc((u32)psxMemRead32);
2121 if (_Rt_) {
2122 SetDstCPUReg(3);
2123 PutHWReg32(_Rt_);
2124 }
2125}
2126
2127REC_FUNC(LWL);
2128REC_FUNC(LWR);
2129REC_FUNC(SWL);
2130REC_FUNC(SWR);
2131/*extern u32 LWL_MASK[4];
2132extern u32 LWL_SHIFT[4];
2133
2134void iLWLk(u32 shift) {
2135 if (IsConst(_Rt_)) {
2136 MOV32ItoR(ECX, iRegs[_Rt_].k);
2137 } else {
2138 MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
2139 }
2140 AND32ItoR(ECX, LWL_MASK[shift]);
2141 SHL32ItoR(EAX, LWL_SHIFT[shift]);
2142 OR32RtoR (EAX, ECX);
2143}
2144
2145void recLWL() {
2146// Rt = Rt Merge mem[Rs + Im]
2147
2148 if (IsConst(_Rs_)) {
2149 u32 addr = iRegs[_Rs_].k + _Imm_;
2150 int t = addr >> 16;
2151
2152 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2153 MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
2154 iLWLk(addr & 3);
2155
2156 iRegs[_Rt_].state = ST_UNK;
2157 MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
2158 return;
2159 }
2160 if (t == 0x1f80 && addr < 0x1f801000) {
2161 MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
2162 iLWLk(addr & 3);
2163
2164 iRegs[_Rt_].state = ST_UNK;
2165 MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
2166 return;
2167 }
2168 }
2169
2170 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2171 else {
2172 MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
2173 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2174 }
2175 PUSH32R (EAX);
2176 AND32ItoR(EAX, ~3);
2177 PUSH32R (EAX);
2178 CALLFunc((u32)psxMemRead32);
2179
2180 if (_Rt_) {
2181 ADD32ItoR(ESP, 4);
2182 POP32R (EDX);
2183 AND32ItoR(EDX, 0x3); // shift = addr & 3;
2184
2185 MOV32ItoR(ECX, (u32)LWL_SHIFT);
2186 MOV32RmStoR(ECX, ECX, EDX, 2);
2187 SHL32CLtoR(EAX); // mem(EAX) << LWL_SHIFT[shift]
2188
2189 MOV32ItoR(ECX, (u32)LWL_MASK);
2190 MOV32RmStoR(ECX, ECX, EDX, 2);
2191 if (IsConst(_Rt_)) {
2192 MOV32ItoR(EDX, iRegs[_Rt_].k);
2193 } else {
2194 MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
2195 }
2196 AND32RtoR(EDX, ECX); // _rRt_ & LWL_MASK[shift]
2197
2198 OR32RtoR(EAX, EDX);
2199
2200 iRegs[_Rt_].state = ST_UNK;
2201 MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
2202 } else {
2203// ADD32ItoR(ESP, 8);
2204 resp+= 8;
2205 }
2206}
2207
2208static void recLWBlock(int count) {
2209 u32 *code = PSXM(pc);
2210 int i, respsave;
2211// Rt = mem[Rs + Im] (unsigned)
2212
2213// iFlushRegs(0);
2214
2215 if (IsConst(_Rs_)) {
2216 u32 addr = iRegs[_Rs_].k + _Imm_;
2217 int t = addr >> 16;
2218
2219 if ((t & 0xfff0) == 0xbfc0) {
2220 // since bios is readonly it won't change
2221 for (i=0; i<count; i++, code++, addr+=4) {
2222 if (_fRt_(*code)) {
2223 MapConst(_fRt_(*code), psxRu32(addr));
2224 }
2225 }
2226 return;
2227 }
2228 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2229 for (i=0; i<count; i++, code++, addr+=4) {
2230 if (!_fRt_(*code)) return;
2231 iRegs[_fRt_(*code)].state = ST_UNK;
2232
2233 MOV32MtoR(EAX, (u32)&psxM[addr & 0x1fffff]);
2234 MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX);
2235 }
2236 return;
2237 }
2238 if (t == 0x1f80 && addr < 0x1f801000) {
2239 for (i=0; i<count; i++, code++, addr+=4) {
2240 if (!_fRt_(*code)) return;
2241 iRegs[_fRt_(*code)].state = ST_UNK;
2242
2243 MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]);
2244 MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX);
2245 }
2246 return;
2247 }
2248 }
2249
2250 SysPrintf("recLWBlock %d: %d\n", count, IsConst(_Rs_));
2251 iPushOfB();
2252 CALLFunc((u32)psxMemPointer);
2253// ADD32ItoR(ESP, 4);
2254 resp+= 4;
2255
2256 respsave = resp; resp = 0;
2257 TEST32RtoR(EAX, EAX);
2258 j32Ptr[4] = JZ32(0);
2259 XOR32RtoR(ECX, ECX);
2260 for (i=0; i<count; i++, code++) {
2261 if (_fRt_(*code)) {
2262 iRegs[_fRt_(*code)].state = ST_UNK;
2263
2264 MOV32RmStoR(EDX, EAX, ECX, 2);
2265 MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EDX);
2266 }
2267 if (i != (count-1)) INC32R(ECX);
2268 }
2269 j32Ptr[5] = JMP32(0);
2270 x86SetJ32(j32Ptr[4]);
2271 for (i=0, code = PSXM(pc); i<count; i++, code++) {
2272 psxRegs.code = *code;
2273 recLW();
2274 }
2275 ADD32ItoR(ESP, resp);
2276 x86SetJ32(j32Ptr[5]);
2277 resp = respsave;
2278}
2279
2280extern u32 LWR_MASK[4];
2281extern u32 LWR_SHIFT[4];
2282
2283void iLWRk(u32 shift) {
2284 if (IsConst(_Rt_)) {
2285 MOV32ItoR(ECX, iRegs[_Rt_].k);
2286 } else {
2287 MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
2288 }
2289 AND32ItoR(ECX, LWR_MASK[shift]);
2290 SHR32ItoR(EAX, LWR_SHIFT[shift]);
2291 OR32RtoR (EAX, ECX);
2292}
2293
2294void recLWR() {
2295// Rt = Rt Merge mem[Rs + Im]
2296
2297 if (IsConst(_Rs_)) {
2298 u32 addr = iRegs[_Rs_].k + _Imm_;
2299 int t = addr >> 16;
2300
2301 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2302 MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
2303 iLWRk(addr & 3);
2304
2305 iRegs[_Rt_].state = ST_UNK;
2306 MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
2307 return;
2308 }
2309 if (t == 0x1f80 && addr < 0x1f801000) {
2310 MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
2311 iLWRk(addr & 3);
2312
2313 iRegs[_Rt_].state = ST_UNK;
2314 MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
2315 return;
2316 }
2317 }
2318
2319 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2320 else {
2321 MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
2322 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2323 }
2324 PUSH32R (EAX);
2325 AND32ItoR(EAX, ~3);
2326 PUSH32R (EAX);
2327 CALLFunc((u32)psxMemRead32);
2328
2329 if (_Rt_) {
2330 ADD32ItoR(ESP, 4);
2331 POP32R (EDX);
2332 AND32ItoR(EDX, 0x3); // shift = addr & 3;
2333
2334 MOV32ItoR(ECX, (u32)LWR_SHIFT);
2335 MOV32RmStoR(ECX, ECX, EDX, 2);
2336 SHR32CLtoR(EAX); // mem(EAX) >> LWR_SHIFT[shift]
2337
2338 MOV32ItoR(ECX, (u32)LWR_MASK);
2339 MOV32RmStoR(ECX, ECX, EDX, 2);
2340
2341 if (IsConst(_Rt_)) {
2342 MOV32ItoR(EDX, iRegs[_Rt_].k);
2343 } else {
2344 MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
2345 }
2346 AND32RtoR(EDX, ECX); // _rRt_ & LWR_MASK[shift]
2347
2348 OR32RtoR(EAX, EDX);
2349
2350 iRegs[_Rt_].state = ST_UNK;
2351 MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
2352 } else {
2353// ADD32ItoR(ESP, 8);
2354 resp+= 8;
2355 }
2356}*/
2357
2358static void recSB() {
2359// mem[Rs + Im] = Rt
2360
2361 /*if (IsConst(_Rs_)) {
2362 u32 addr = iRegs[_Rs_].k + _Imm_;
2363 int t = addr >> 16;
2364
2365 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2366 if (IsConst(_Rt_)) {
2367 MOV8ItoM((u32)&psxM[addr & 0x1fffff], (u8)iRegs[_Rt_].k);
2368 } else {
2369 MOV8MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
2370 MOV8RtoM((u32)&psxM[addr & 0x1fffff], EAX);
2371 }
2372 return;
2373 }
2374 if (t == 0x1f80 && addr < 0x1f801000) {
2375 if (IsConst(_Rt_)) {
2376 MOV8ItoM((u32)&psxH[addr & 0xfff], (u8)iRegs[_Rt_].k);
2377 } else {
2378 MOV8MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
2379 MOV8RtoM((u32)&psxH[addr & 0xfff], EAX);
2380 }
2381 return;
2382 }
2383// SysPrintf("unhandled w8 %x\n", addr);
2384 }*/
2385
2386 preMemWrite(1);
2387 CALLFunc((u32)psxMemWrite8);
2388}
2389
2390static void recSH() {
2391// mem[Rs + Im] = Rt
2392
2393 /*if (IsConst(_Rs_)) {
2394 u32 addr = iRegs[_Rs_].k + _Imm_;
2395 int t = addr >> 16;
2396
2397 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2398 if (IsConst(_Rt_)) {
2399 MOV16ItoM((u32)&psxM[addr & 0x1fffff], (u16)iRegs[_Rt_].k);
2400 } else {
2401 MOV16MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
2402 MOV16RtoM((u32)&psxM[addr & 0x1fffff], EAX);
2403 }
2404 return;
2405 }
2406 if (t == 0x1f80 && addr < 0x1f801000) {
2407 if (IsConst(_Rt_)) {
2408 MOV16ItoM((u32)&psxH[addr & 0xfff], (u16)iRegs[_Rt_].k);
2409 } else {
2410 MOV16MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
2411 MOV16RtoM((u32)&psxH[addr & 0xfff], EAX);
2412 }
2413 return;
2414 }
2415 if (t == 0x1f80) {
2416 if (addr >= 0x1f801c00 && addr < 0x1f801e00) {
2417 if (IsConst(_Rt_)) {
2418 PUSH32I(iRegs[_Rt_].k);
2419 } else {
2420 PUSH32M((u32)&psxRegs.GPR.r[_Rt_]);
2421 }
2422 PUSH32I (addr);
2423 CALL32M ((u32)&SPU_writeRegister);
2424#ifndef __WIN32__
2425 resp+= 8;
2426#endif
2427 return;
2428 }
2429 }
2430// SysPrintf("unhandled w16 %x\n", addr);
2431 }*/
2432
2433 preMemWrite(2);
2434 CALLFunc((u32)psxMemWrite16);
2435}
2436
2437static void recSW() {
2438// mem[Rs + Im] = Rt
2439 u32 *b1, *b2;
2440#if 0
2441 if (IsConst(_Rs_)) {
2442 u32 addr = iRegs[_Rs_].k + _Imm_;
2443 int t = addr >> 16;
2444
2445 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2446 LIW(0, addr & 0x1fffff);
2447 STWBRX(GetHWReg32(_Rt_), GetHWRegSpecial(PSXMEM), 0);
2448 return;
2449 }
2450 if (t == 0x1f80 && addr < 0x1f801000) {
2451 LIW(0, (u32)&psxH[addr & 0xfff]);
2452 STWBRX(GetHWReg32(_Rt_), 0, 0);
2453 return;
2454 }
2455 if (t == 0x1f80) {
2456 switch (addr) {
2457 case 0x1f801080: case 0x1f801084:
2458 case 0x1f801090: case 0x1f801094:
2459 case 0x1f8010a0: case 0x1f8010a4:
2460 case 0x1f8010b0: case 0x1f8010b4:
2461 case 0x1f8010c0: case 0x1f8010c4:
2462 case 0x1f8010d0: case 0x1f8010d4:
2463 case 0x1f8010e0: case 0x1f8010e4:
2464 case 0x1f801074:
2465 case 0x1f8010f0:
2466 LIW(0, (u32)&psxH[addr & 0xffff]);
2467 STWBRX(GetHWReg32(_Rt_), 0, 0);
2468 return;
2469
2470/* case 0x1f801810:
2471 if (IsConst(_Rt_)) {
2472 PUSH32I(iRegs[_Rt_].k);
2473 } else {
2474 PUSH32M((u32)&psxRegs.GPR.r[_Rt_]);
2475 }
2476 CALL32M((u32)&GPU_writeData);
2477#ifndef __WIN32__
2478 resp+= 4;
2479#endif
2480 return;
2481
2482 case 0x1f801814:
2483 if (IsConst(_Rt_)) {
2484 PUSH32I(iRegs[_Rt_].k);
2485 } else {
2486 PUSH32M((u32)&psxRegs.GPR.r[_Rt_]);
2487 }
2488 CALL32M((u32)&GPU_writeStatus);
2489#ifndef __WIN32__
2490 resp+= 4;
2491#endif*/
2492 }
2493 }
2494// SysPrintf("unhandled w32 %x\n", addr);
2495 }
2496
2497/* LIS(0, 0x0079 + ((_Imm_ <= 0) ? 1 : 0));
2498 CMPLW(GetHWReg32(_Rs_), 0);
2499 BGE_L(b1);
2500
2501 //SaveContext();
2502 ADDI(0, GetHWReg32(_Rs_), _Imm_);
2503 RLWINM(0, GetHWReg32(_Rs_), 0, 11, 31);
2504 STWBRX(GetHWReg32(_Rt_), GetHWRegSpecial(PSXMEM), 0);
2505 B_L(b2);
2506
2507 B_DST(b1);*/
2508#endif
2509 preMemWrite(4);
2510 CALLFunc((u32)psxMemWrite32);
2511
2512 //B_DST(b2);
2513}
2514
2515/*
2516static void recSWBlock(int count) {
2517 u32 *code;
2518 int i, respsave;
2519// mem[Rs + Im] = Rt
2520
2521// iFlushRegs();
2522
2523 if (IsConst(_Rs_)) {
2524 u32 addr = iRegs[_Rs_].k + _Imm_;
2525 int t = addr >> 16;
2526 code = PSXM(pc);
2527
2528 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2529 for (i=0; i<count; i++, code++, addr+=4) {
2530 if (IsConst(_fRt_(*code))) {
2531 MOV32ItoM((u32)&psxM[addr & 0x1fffff], iRegs[_fRt_(*code)].k);
2532 } else {
2533 MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_fRt_(*code)]);
2534 MOV32RtoM((u32)&psxM[addr & 0x1fffff], EAX);
2535 }
2536 }
2537 return;
2538 }
2539 if (t == 0x1f80 && addr < 0x1f801000) {
2540 for (i=0; i<count; i++, code++, addr+=4) {
2541 if (!_fRt_(*code)) return;
2542 iRegs[_fRt_(*code)].state = ST_UNK;
2543
2544 MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]);
2545 MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX);
2546 }
2547 return;
2548 }
2549 }
2550
2551 SysPrintf("recSWBlock %d: %d\n", count, IsConst(_Rs_));
2552 iPushOfB();
2553 CALLFunc((u32)psxMemPointer);
2554// ADD32ItoR(ESP, 4);
2555 resp+= 4;
2556
2557 respsave = resp; resp = 0;
2558 TEST32RtoR(EAX, EAX);
2559 j32Ptr[4] = JZ32(0);
2560 XOR32RtoR(ECX, ECX);
2561 for (i=0, code = PSXM(pc); i<count; i++, code++) {
2562 if (IsConst(_fRt_(*code))) {
2563 MOV32ItoR(EDX, iRegs[_fRt_(*code)].k);
2564 } else {
2565 MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_fRt_(*code)]);
2566 }
2567 MOV32RtoRmS(EAX, ECX, 2, EDX);
2568 if (i != (count-1)) INC32R(ECX);
2569 }
2570 j32Ptr[5] = JMP32(0);
2571 x86SetJ32(j32Ptr[4]);
2572 for (i=0, code = PSXM(pc); i<count; i++, code++) {
2573 psxRegs.code = *code;
2574 recSW();
2575 }
2576 ADD32ItoR(ESP, resp);
2577 x86SetJ32(j32Ptr[5]);
2578 resp = respsave;
2579}
2580
2581extern u32 SWL_MASK[4];
2582extern u32 SWL_SHIFT[4];
2583
2584void iSWLk(u32 shift) {
2585 if (IsConst(_Rt_)) {
2586 MOV32ItoR(ECX, iRegs[_Rt_].k);
2587 } else {
2588 MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
2589 }
2590 SHR32ItoR(ECX, SWL_SHIFT[shift]);
2591 AND32ItoR(EAX, SWL_MASK[shift]);
2592 OR32RtoR (EAX, ECX);
2593}
2594
2595void recSWL() {
2596// mem[Rs + Im] = Rt Merge mem[Rs + Im]
2597
2598 if (IsConst(_Rs_)) {
2599 u32 addr = iRegs[_Rs_].k + _Imm_;
2600 int t = addr >> 16;
2601
2602 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2603 MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
2604 iSWLk(addr & 3);
2605 MOV32RtoM((u32)&psxM[addr & 0x1ffffc], EAX);
2606 return;
2607 }
2608 if (t == 0x1f80 && addr < 0x1f801000) {
2609 MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
2610 iSWLk(addr & 3);
2611 MOV32RtoM((u32)&psxH[addr & 0xffc], EAX);
2612 return;
2613 }
2614 }
2615
2616 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2617 else {
2618 MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
2619 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2620 }
2621 PUSH32R (EAX);
2622 AND32ItoR(EAX, ~3);
2623 PUSH32R (EAX);
2624
2625 CALLFunc((u32)psxMemRead32);
2626
2627 ADD32ItoR(ESP, 4);
2628 POP32R (EDX);
2629 AND32ItoR(EDX, 0x3); // shift = addr & 3;
2630
2631 MOV32ItoR(ECX, (u32)SWL_MASK);
2632 MOV32RmStoR(ECX, ECX, EDX, 2);
2633 AND32RtoR(EAX, ECX); // mem & SWL_MASK[shift]
2634
2635 MOV32ItoR(ECX, (u32)SWL_SHIFT);
2636 MOV32RmStoR(ECX, ECX, EDX, 2);
2637 if (IsConst(_Rt_)) {
2638 MOV32ItoR(EDX, iRegs[_Rt_].k);
2639 } else {
2640 MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
2641 }
2642 SHR32CLtoR(EDX); // _rRt_ >> SWL_SHIFT[shift]
2643
2644 OR32RtoR (EAX, EDX);
2645 PUSH32R (EAX);
2646
2647 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2648 else {
2649 MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
2650 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2651 }
2652 AND32ItoR(EAX, ~3);
2653 PUSH32R (EAX);
2654
2655 CALLFunc((u32)psxMemWrite32);
2656// ADD32ItoR(ESP, 8);
2657 resp+= 8;
2658}
2659
2660extern u32 SWR_MASK[4];
2661extern u32 SWR_SHIFT[4];
2662
2663void iSWRk(u32 shift) {
2664 if (IsConst(_Rt_)) {
2665 MOV32ItoR(ECX, iRegs[_Rt_].k);
2666 } else {
2667 MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
2668 }
2669 SHL32ItoR(ECX, SWR_SHIFT[shift]);
2670 AND32ItoR(EAX, SWR_MASK[shift]);
2671 OR32RtoR (EAX, ECX);
2672}
2673
2674void recSWR() {
2675// mem[Rs + Im] = Rt Merge mem[Rs + Im]
2676
2677 if (IsConst(_Rs_)) {
2678 u32 addr = iRegs[_Rs_].k + _Imm_;
2679 int t = addr >> 16;
2680
2681 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2682 MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
2683 iSWRk(addr & 3);
2684 MOV32RtoM((u32)&psxM[addr & 0x1ffffc], EAX);
2685 return;
2686 }
2687 if (t == 0x1f80 && addr < 0x1f801000) {
2688 MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
2689 iSWRk(addr & 3);
2690 MOV32RtoM((u32)&psxH[addr & 0xffc], EAX);
2691 return;
2692 }
2693 }
2694
2695 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2696 else {
2697 MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
2698 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2699 }
2700 PUSH32R (EAX);
2701 AND32ItoR(EAX, ~3);
2702 PUSH32R (EAX);
2703
2704 CALLFunc((u32)psxMemRead32);
2705
2706 ADD32ItoR(ESP, 4);
2707 POP32R (EDX);
2708 AND32ItoR(EDX, 0x3); // shift = addr & 3;
2709
2710 MOV32ItoR(ECX, (u32)SWR_MASK);
2711 MOV32RmStoR(ECX, ECX, EDX, 2);
2712 AND32RtoR(EAX, ECX); // mem & SWR_MASK[shift]
2713
2714 MOV32ItoR(ECX, (u32)SWR_SHIFT);
2715 MOV32RmStoR(ECX, ECX, EDX, 2);
2716 if (IsConst(_Rt_)) {
2717 MOV32ItoR(EDX, iRegs[_Rt_].k);
2718 } else {
2719 MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
2720 }
2721 SHL32CLtoR(EDX); // _rRt_ << SWR_SHIFT[shift]
2722
2723 OR32RtoR (EAX, EDX);
2724 PUSH32R (EAX);
2725
2726 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2727 else {
2728 MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
2729 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2730 }
2731 AND32ItoR(EAX, ~3);
2732 PUSH32R (EAX);
2733
2734 CALLFunc((u32)psxMemWrite32);
2735// ADD32ItoR(ESP, 8);
2736 resp+= 8;
2737}*/
2738#endif
2739
2740#if 0
2741/*REC_FUNC(SLL);
2742REC_FUNC(SRL);
2743REC_FUNC(SRA);*/
2744#else
2745static void recSLL() {
2746// Rd = Rt << Sa
2747 if (!_Rd_) return;
2748
2749 if (IsConst(_Rt_)) {
2750 MapConst(_Rd_, iRegs[_Rt_].k << _Sa_);
2751 } else {
2752 SLWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), _Sa_);
2753 }
2754}
2755
2756static void recSRL() {
2757// Rd = Rt >> Sa
2758 if (!_Rd_) return;
2759
2760 if (IsConst(_Rt_)) {
2761 MapConst(_Rd_, iRegs[_Rt_].k >> _Sa_);
2762 } else {
2763 SRWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), _Sa_);
2764 }
2765}
2766
2767static void recSRA() {
2768// Rd = Rt >> Sa
2769 if (!_Rd_) return;
2770
2771 if (IsConst(_Rt_)) {
2772 MapConst(_Rd_, (s32)iRegs[_Rt_].k >> _Sa_);
2773 } else {
2774 SRAWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), _Sa_);
2775 }
2776}
2777#endif
2778
2779#pragma mark - shift ops -
2780#if 0
2781/*REC_FUNC(SLLV);
2782REC_FUNC(SRLV);
2783REC_FUNC(SRAV);*/
2784#else
2785static void recSLLV() {
2786// Rd = Rt << Rs
2787 if (!_Rd_) return;
2788
2789 if (IsConst(_Rt_) && IsConst(_Rs_)) {
2790 MapConst(_Rd_, iRegs[_Rt_].k << iRegs[_Rs_].k);
2791 } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
2792 SLWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k);
2793 } else {
2794 SLW(PutHWReg32(_Rd_), GetHWReg32(_Rt_), GetHWReg32(_Rs_));
2795 }
2796}
2797
2798static void recSRLV() {
2799// Rd = Rt >> Rs
2800 if (!_Rd_) return;
2801
2802 if (IsConst(_Rt_) && IsConst(_Rs_)) {
2803 MapConst(_Rd_, iRegs[_Rt_].k >> iRegs[_Rs_].k);
2804 } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
2805 SRWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k);
2806 } else {
2807 SRW(PutHWReg32(_Rd_), GetHWReg32(_Rt_), GetHWReg32(_Rs_));
2808 }
2809}
2810
2811static void recSRAV() {
2812// Rd = Rt >> Rs
2813 if (!_Rd_) return;
2814
2815 if (IsConst(_Rt_) && IsConst(_Rs_)) {
2816 MapConst(_Rd_, (s32)iRegs[_Rt_].k >> iRegs[_Rs_].k);
2817 } else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
2818 SRAWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), iRegs[_Rs_].k);
2819 } else {
2820 SRAW(PutHWReg32(_Rd_), GetHWReg32(_Rt_), GetHWReg32(_Rs_));
2821 }
2822}
2823#endif
2824
2825//REC_SYS(SYSCALL);
2826//REC_SYS(BREAK);
2827
2828//#if 0*/
2829/*int dump;*/
2830static void recSYSCALL() {
2831// dump=1;
2832 iFlushRegs(0);
2833
2834 ReserveArgs(2);
2835 LIW(PutHWRegSpecial(PSXPC), pc - 4);
2836 LIW(PutHWRegSpecial(ARG1), 0x20);
2837 LIW(PutHWRegSpecial(ARG2), (branch == 1 ? 1 : 0));
2838 FlushAllHWReg();
2839 CALLFunc ((u32)psxException);
2840
2841 branch = 2;
2842 iRet();
2843}
2844
2845static void recBREAK() {
2846}
2847//#endif
2848
2849#if 0
2850/*REC_FUNC(MFHI);
2851REC_FUNC(MTHI);
2852REC_FUNC(MFLO);
2853REC_FUNC(MTLO);*/
2854#else
2855static void recMFHI() {
2856// Rd = Hi
2857 if (!_Rd_) return;
2858
2859 if (IsConst(REG_HI)) {
2860 MapConst(_Rd_, iRegs[REG_HI].k);
2861 } else {
2862 MapCopy(_Rd_, REG_HI);
2863 }
2864}
2865
2866static void recMTHI() {
2867// Hi = Rs
2868
2869 if (IsConst(_Rs_)) {
2870 MapConst(REG_HI, iRegs[_Rs_].k);
2871 } else {
2872 MapCopy(REG_HI, _Rs_);
2873 }
2874}
2875
2876static void recMFLO() {
2877// Rd = Lo
2878 if (!_Rd_) return;
2879
2880 if (IsConst(REG_LO)) {
2881 MapConst(_Rd_, iRegs[REG_LO].k);
2882 } else {
2883 MapCopy(_Rd_, REG_LO);
2884 }
2885}
2886
2887static void recMTLO() {
2888// Lo = Rs
2889
2890 if (IsConst(_Rs_)) {
2891 MapConst(REG_LO, iRegs[_Rs_].k);
2892 } else {
2893 MapCopy(REG_LO, _Rs_);
2894 }
2895}
2896#endif
2897
2898#pragma mark - branch ops -
2899#if 0
2900/*REC_BRANCH(J);
2901REC_BRANCH(JR);
2902REC_BRANCH(JAL);
2903REC_BRANCH(JALR);
2904REC_BRANCH(BLTZ);
2905REC_BRANCH(BGTZ);
2906REC_BRANCH(BLTZAL);
2907REC_BRANCH(BGEZAL);
2908REC_BRANCH(BNE);
2909REC_BRANCH(BEQ);
2910REC_BRANCH(BLEZ);
2911REC_BRANCH(BGEZ);*/
2912#else
2913static void recBLTZ() {
2914// Branch if Rs < 0
2915 u32 bpc = _Imm_ * 4 + pc;
2916 u32 *b;
2917
2918 if (IsConst(_Rs_)) {
2919 if ((s32)iRegs[_Rs_].k < 0) {
2920 iJump(bpc); return;
2921 } else {
2922 iJump(pc+4); return;
2923 }
2924 }
2925
2926 CMPWI(GetHWReg32(_Rs_), 0);
2927 BLT_L(b);
2928
2929 iBranch(pc+4, 1);
2930
2931 B_DST(b);
2932
2933 iBranch(bpc, 0);
2934 pc+=4;
2935}
2936
2937static void recBGTZ() {
2938// Branch if Rs > 0
2939 u32 bpc = _Imm_ * 4 + pc;
2940 u32 *b;
2941
2942 if (IsConst(_Rs_)) {
2943 if ((s32)iRegs[_Rs_].k > 0) {
2944 iJump(bpc); return;
2945 } else {
2946 iJump(pc+4); return;
2947 }
2948 }
2949
2950 CMPWI(GetHWReg32(_Rs_), 0);
2951 BGT_L(b);
2952
2953 iBranch(pc+4, 1);
2954
2955 B_DST(b);
2956
2957 iBranch(bpc, 0);
2958 pc+=4;
2959}
2960
2961static void recBLTZAL() {
2962// Branch if Rs < 0
2963 u32 bpc = _Imm_ * 4 + pc;
2964 u32 *b;
2965
2966 if (IsConst(_Rs_)) {
2967 if ((s32)iRegs[_Rs_].k < 0) {
2968 MapConst(31, pc + 4);
2969
2970 iJump(bpc); return;
2971 } else {
2972 iJump(pc+4); return;
2973 }
2974 }
2975
2976 CMPWI(GetHWReg32(_Rs_), 0);
2977 BLT_L(b);
2978
2979 iBranch(pc+4, 1);
2980
2981 B_DST(b);
2982
2983 MapConst(31, pc + 4);
2984
2985 iBranch(bpc, 0);
2986 pc+=4;
2987}
2988
2989static void recBGEZAL() {
2990// Branch if Rs >= 0
2991 u32 bpc = _Imm_ * 4 + pc;
2992 u32 *b;
2993
2994 if (IsConst(_Rs_)) {
2995 if ((s32)iRegs[_Rs_].k >= 0) {
2996 MapConst(31, pc + 4);
2997
2998 iJump(bpc); return;
2999 } else {
3000 iJump(pc+4); return;
3001 }
3002 }
3003
3004 CMPWI(GetHWReg32(_Rs_), 0);
3005 BGE_L(b);
3006
3007 iBranch(pc+4, 1);
3008
3009 B_DST(b);
3010
3011 MapConst(31, pc + 4);
3012
3013 iBranch(bpc, 0);
3014 pc+=4;
3015}
3016
3017static void recJ() {
3018// j target
3019
3020 iJump(_Target_ * 4 + (pc & 0xf0000000));
3021}
3022
3023static void recJAL() {
3024// jal target
3025 MapConst(31, pc + 4);
3026
3027 iJump(_Target_ * 4 + (pc & 0xf0000000));
3028}
3029
3030static void recJR() {
3031// jr Rs
3032
3033 if (IsConst(_Rs_)) {
3034 iJump(iRegs[_Rs_].k);
3035 //LIW(PutHWRegSpecial(TARGET), iRegs[_Rs_].k);
3036 } else {
3037 MR(PutHWRegSpecial(TARGET), GetHWReg32(_Rs_));
3038 SetBranch();
3039 }
3040}
3041
3042static void recJALR() {
3043// jalr Rs
3044
3045 if (_Rd_) {
3046 MapConst(_Rd_, pc + 4);
3047 }
3048
3049 if (IsConst(_Rs_)) {
3050 iJump(iRegs[_Rs_].k);
3051 //LIW(PutHWRegSpecial(TARGET), iRegs[_Rs_].k);
3052 } else {
3053 MR(PutHWRegSpecial(TARGET), GetHWReg32(_Rs_));
3054 SetBranch();
3055 }
3056}
3057
3058static void recBEQ() {
3059// Branch if Rs == Rt
3060 u32 bpc = _Imm_ * 4 + pc;
3061 u32 *b;
3062
3063 if (_Rs_ == _Rt_) {
3064 iJump(bpc);
3065 }
3066 else {
3067 if (IsConst(_Rs_) && IsConst(_Rt_)) {
3068 if (iRegs[_Rs_].k == iRegs[_Rt_].k) {
3069 iJump(bpc); return;
3070 } else {
3071 iJump(pc+4); return;
3072 }
3073 }
3074 else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
3075 if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) {
3076 CMPLWI(GetHWReg32(_Rt_), iRegs[_Rs_].k);
3077 }
3078 else if ((s32)(s16)iRegs[_Rs_].k == (s32)iRegs[_Rs_].k) {
3079 CMPWI(GetHWReg32(_Rt_), iRegs[_Rs_].k);
3080 }
3081 else {
3082 CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
3083 }
3084 }
3085 else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
3086 if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) {
3087 CMPLWI(GetHWReg32(_Rs_), iRegs[_Rt_].k);
3088 }
3089 else if ((s32)(s16)iRegs[_Rt_].k == (s32)iRegs[_Rt_].k) {
3090 CMPWI(GetHWReg32(_Rs_), iRegs[_Rt_].k);
3091 }
3092 else {
3093 CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
3094 }
3095 }
3096 else {
3097 CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
3098 }
3099
3100 BEQ_L(b);
3101
3102 iBranch(pc+4, 1);
3103
3104 B_DST(b);
3105
3106 iBranch(bpc, 0);
3107 pc+=4;
3108 }
3109}
3110
3111static void recBNE() {
3112// Branch if Rs != Rt
3113 u32 bpc = _Imm_ * 4 + pc;
3114 u32 *b;
3115
3116 if (_Rs_ == _Rt_) {
3117 iJump(pc+4);
3118 }
3119 else {
3120 if (IsConst(_Rs_) && IsConst(_Rt_)) {
3121 if (iRegs[_Rs_].k != iRegs[_Rt_].k) {
3122 iJump(bpc); return;
3123 } else {
3124 iJump(pc+4); return;
3125 }
3126 }
3127 else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
3128 if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) {
3129 CMPLWI(GetHWReg32(_Rt_), iRegs[_Rs_].k);
3130 }
3131 else if ((s32)(s16)iRegs[_Rs_].k == (s32)iRegs[_Rs_].k) {
3132 CMPWI(GetHWReg32(_Rt_), iRegs[_Rs_].k);
3133 }
3134 else {
3135 CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
3136 }
3137 }
3138 else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
3139 if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) {
3140 CMPLWI(GetHWReg32(_Rs_), iRegs[_Rt_].k);
3141 }
3142 else if ((s32)(s16)iRegs[_Rt_].k == (s32)iRegs[_Rt_].k) {
3143 CMPWI(GetHWReg32(_Rs_), iRegs[_Rt_].k);
3144 }
3145 else {
3146 CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
3147 }
3148 }
3149 else {
3150 CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
3151 }
3152
3153 BNE_L(b);
3154
3155 iBranch(pc+4, 1);
3156
3157 B_DST(b);
3158
3159 iBranch(bpc, 0);
3160 pc+=4;
3161 }
3162}
3163
3164static void recBLEZ() {
3165// Branch if Rs <= 0
3166 u32 bpc = _Imm_ * 4 + pc;
3167 u32 *b;
3168
3169 if (IsConst(_Rs_)) {
3170 if ((s32)iRegs[_Rs_].k <= 0) {
3171 iJump(bpc); return;
3172 } else {
3173 iJump(pc+4); return;
3174 }
3175 }
3176
3177 CMPWI(GetHWReg32(_Rs_), 0);
3178 BLE_L(b);
3179
3180 iBranch(pc+4, 1);
3181
3182 B_DST(b);
3183
3184 iBranch(bpc, 0);
3185 pc+=4;
3186}
3187
3188static void recBGEZ() {
3189// Branch if Rs >= 0
3190 u32 bpc = _Imm_ * 4 + pc;
3191 u32 *b;
3192
3193 if (IsConst(_Rs_)) {
3194 if ((s32)iRegs[_Rs_].k >= 0) {
3195 iJump(bpc); return;
3196 } else {
3197 iJump(pc+4); return;
3198 }
3199 }
3200
3201 CMPWI(GetHWReg32(_Rs_), 0);
3202 BGE_L(b);
3203
3204 iBranch(pc+4, 1);
3205
3206 B_DST(b);
3207
3208 iBranch(bpc, 0);
3209 pc+=4;
3210}
3211#endif
3212
3213#if 1
3214//REC_FUNC(MFC0);
3215//REC_SYS(MTC0);
3216//REC_FUNC(CFC0);
3217//REC_SYS(CTC0);
3218REC_FUNC(RFE);
3219//#else
3220static void recMFC0() {
3221// Rt = Cop0->Rd
3222 if (!_Rt_) return;
3223
3224 LWZ(PutHWReg32(_Rt_), OFFSET(&psxRegs, &psxRegs.CP0.r[_Rd_]), GetHWRegSpecial(PSXREGS));
3225}
3226
3227static void recCFC0() {
3228// Rt = Cop0->Rd
3229
3230 recMFC0();
3231}
3232
3233static void recMTC0() {
3234// Cop0->Rd = Rt
3235
3236 /*if (IsConst(_Rt_)) {
3237 switch (_Rd_) {
3238 case 12:
3239 MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k);
3240 break;
3241 case 13:
3242 MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k & ~(0xfc00));
3243 break;
3244 default:
3245 MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k);
3246 break;
3247 }
3248 } else*/ {
3249 switch (_Rd_) {
3250 case 13:
3251 RLWINM(0,GetHWReg32(_Rt_),0,22,15); // & ~(0xfc00)
3252 STW(0, OFFSET(&psxRegs, &psxRegs.CP0.r[_Rd_]), GetHWRegSpecial(PSXREGS));
3253 break;
3254 default:
3255 STW(GetHWReg32(_Rt_), OFFSET(&psxRegs, &psxRegs.CP0.r[_Rd_]), GetHWRegSpecial(PSXREGS));
3256 break;
3257 }
3258 }
3259
3260 if (_Rd_ == 12 || _Rd_ == 13) {
3261 iFlushRegs(0);
3262 LIW(PutHWRegSpecial(PSXPC), (u32)pc);
3263 FlushAllHWReg();
3264 CALLFunc((u32)psxTestSWInts);
3265 if(_Rd_ == 12) {
3266 LWZ(0, OFFSET(&psxRegs, &psxRegs.interrupt), GetHWRegSpecial(PSXREGS));
3267 ORIS(0, 0, 0x8000);
3268 STW(0, OFFSET(&psxRegs, &psxRegs.interrupt), GetHWRegSpecial(PSXREGS));
3269 }
3270 branch = 2;
3271 iRet();
3272 }
3273}
3274
3275static void recCTC0() {
3276// Cop0->Rd = Rt
3277
3278 recMTC0();
3279}
3280#else
3281static void recRFE() {
3282 // TODO: implement multiple temp registers or cop0 registers
3283 RLWINM(t1,Status,0,0,27);
3284 RLWINM(Status,Status,30,28,31);
3285 OR(Status,t1,Status);
3286
3287 MOV32MtoR(EAX, (u32)&psxRegs.CP0.n.Status);
3288 MOV32RtoR(ECX, EAX);
3289 AND32ItoR(EAX, 0xfffffff0);
3290 AND32ItoR(ECX, 0x3c);
3291 SHR32ItoR(ECX, 2);
3292 OR32RtoR (EAX, ECX);
3293 MOV32RtoM((u32)&psxRegs.CP0.n.Status, EAX);
3294 CALLFunc((u32)psxExceptionTest);
3295}
3296#endif
3297
3298#if 0
3299#define CP2_FUNC(f) \
3300void gte##f(); \
3301static void rec##f() { \
3302 iFlushRegs(0); \
3303 LIW(0, (u32)psxRegs.code); \
3304 STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \
3305 FlushAllHWReg(); \
3306 CALLFunc ((u32)gte##f); \
3307}
3308CP2_FUNC(LWC2);
3309CP2_FUNC(SWC2);
3310
3311#else
3312#include "pGte.h"
3313#endif
3314//
3315
3316static void recHLE() {
3317 iFlushRegs(0);
3318 FlushAllHWReg();
3319
3320 if ((psxRegs.code & 0x3ffffff) == (psxRegs.code & 0x7)) {
3321 CALLFunc((u32)psxHLEt[psxRegs.code & 0x7]);
3322 } else {
3323 // somebody else must have written to current opcode for this to happen!!!!
3324 CALLFunc((u32)psxHLEt[0]); // call dummy function
3325 }
3326
3327 count = (idlecyclecount + (pc - pcold) / 4 + 20) * BIAS;
3328 ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
3329 FlushAllHWReg();
3330 CALLFunc((u32)psxBranchTest);
3331 Return();
3332
3333 branch = 2;
3334}
3335
3336//
3337
3338static void (*recBSC[64])() = {
3339 recSPECIAL, recREGIMM, recJ , recJAL , recBEQ , recBNE , recBLEZ, recBGTZ,
3340 recADDI , recADDIU , recSLTI, recSLTIU, recANDI, recORI , recXORI, recLUI ,
3341 recCOP0 , recNULL , recCOP2, recNULL , recNULL, recNULL, recNULL, recNULL,
3342 recNULL , recNULL , recNULL, recNULL , recNULL, recNULL, recNULL, recNULL,
3343 recLB , recLH , recLWL , recLW , recLBU , recLHU , recLWR , recNULL,
3344 recSB , recSH , recSWL , recSW , recNULL, recNULL, recSWR , recNULL,
3345 recNULL , recNULL , recLWC2, recNULL , recNULL, recNULL, recNULL, recNULL,
3346 recNULL , recNULL , recSWC2, recHLE , recNULL, recNULL, recNULL, recNULL
3347};
3348
3349static void (*recSPC[64])() = {
3350 recSLL , recNULL, recSRL , recSRA , recSLLV , recNULL , recSRLV, recSRAV,
3351 recJR , recJALR, recNULL, recNULL, recSYSCALL, recBREAK, recNULL, recNULL,
3352 recMFHI, recMTHI, recMFLO, recMTLO, recNULL , recNULL , recNULL, recNULL,
3353 recMULT, recMULTU, recDIV, recDIVU, recNULL , recNULL , recNULL, recNULL,
3354 recADD , recADDU, recSUB , recSUBU, recAND , recOR , recXOR , recNOR ,
3355 recNULL, recNULL, recSLT , recSLTU, recNULL , recNULL , recNULL, recNULL,
3356 recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL,
3357 recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL
3358};
3359
3360static void (*recREG[32])() = {
3361 recBLTZ , recBGEZ , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
3362 recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
3363 recBLTZAL, recBGEZAL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
3364 recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL
3365};
3366
3367static void (*recCP0[32])() = {
3368 recMFC0, recNULL, recCFC0, recNULL, recMTC0, recNULL, recCTC0, recNULL,
3369 recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
3370 recRFE , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
3371 recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL
3372};
3373
3374static void (*recCP2[64])() = {
3375 recBASIC, recRTPS , recNULL , recNULL, recNULL, recNULL , recNCLIP, recNULL, // 00
3376 recNULL , recNULL , recNULL , recNULL, recOP , recNULL , recNULL , recNULL, // 08
3377 recDPCS , recINTPL, recMVMVA, recNCDS, recCDP , recNULL , recNCDT , recNULL, // 10
3378 recNULL , recNULL , recNULL , recNCCS, recCC , recNULL , recNCS , recNULL, // 18
3379 recNCT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 20
3380 recSQR , recDCPL , recDPCT , recNULL, recNULL, recAVSZ3, recAVSZ4, recNULL, // 28
3381 recRTPT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 30
3382 recNULL , recNULL , recNULL , recNULL, recNULL, recGPF , recGPL , recNCCT // 38
3383};
3384
3385static void (*recCP2BSC[32])() = {
3386 recMFC2, recNULL, recCFC2, recNULL, recMTC2, recNULL, recCTC2, recNULL,
3387 recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
3388 recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
3389 recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL
3390};
3391
3392static void recRecompile() {
3393 //static int recCount = 0;
3394 char *p;
3395 u32 *ptr;
3396 int i;
3397
3398 cop2readypc = 0;
3399 idlecyclecount = 0;
3400
3401 // initialize state variables
3402 UniqueRegAlloc = 1;
3403 HWRegUseCount = 0;
3404 DstCPUReg = -1;
3405 memset(HWRegisters, 0, sizeof(HWRegisters));
3406 for (i=0; i<NUM_HW_REGISTERS; i++)
3407 HWRegisters[i].code = cpuHWRegisters[NUM_HW_REGISTERS-i-1];
3408
3409 // reserve the special psxReg register
3410 HWRegisters[0].usage = HWUSAGE_SPECIAL | HWUSAGE_RESERVED | HWUSAGE_HARDWIRED;
3411 HWRegisters[0].private = PSXREGS;
3412 HWRegisters[0].k = (u32)&psxRegs;
3413
3414 HWRegisters[1].usage = HWUSAGE_SPECIAL | HWUSAGE_RESERVED | HWUSAGE_HARDWIRED;
3415 HWRegisters[1].private = PSXMEM;
3416 HWRegisters[1].k = (u32)&psxM;
3417
3418 // reserve the special psxRegs.cycle register
3419 //HWRegisters[1].usage = HWUSAGE_SPECIAL | HWUSAGE_RESERVED | HWUSAGE_HARDWIRED;
3420 //HWRegisters[1].private = CYCLECOUNT;
3421
3422 //memset(iRegs, 0, sizeof(iRegs));
3423 for (i=0; i<NUM_REGISTERS; i++) {
3424 iRegs[i].state = ST_UNK;
3425 iRegs[i].reg = -1;
3426 }
3427 iRegs[0].k = 0;
3428 iRegs[0].state = ST_CONST;
3429
3430 /* if ppcPtr reached the mem limit reset whole mem */
3431 if (((u32)ppcPtr - (u32)recMem) >= (RECMEM_SIZE - 0x10000))
3432 recReset();
3433
3434 ppcAlign(/*32*/4);
3435 ptr = ppcPtr;
3436
3437 // give us write access
3438 //mprotect(recMem, RECMEM_SIZE, PROT_EXEC|PROT_READ|PROT_WRITE);
3439
3440 // tell the LUT where to find us
3441 PC_REC32(psxRegs.pc) = (u32)ppcPtr;
3442
3443 pcold = pc = psxRegs.pc;
3444
3445 //SysPrintf("RecCount: %i\n", recCount++);
3446
3447 for (count=0; count<500;) {
3448 p = (char *)PSXM(pc);
3449 if (p == NULL) recError();
3450 psxRegs.code = SWAP32(*(u32 *)p);
3451/*
3452 if ((psxRegs.code >> 26) == 0x23) { // LW
3453 int i;
3454 u32 code;
3455
3456 for (i=1;; i++) {
3457 p = (char *)PSXM(pc+i*4);
3458 if (p == NULL) recError();
3459 code = *(u32 *)p;
3460
3461 if ((code >> 26) != 0x23 ||
3462 _fRs_(code) != _Rs_ ||
3463 _fImm_(code) != (_Imm_+i*4))
3464 break;
3465 }
3466 if (i > 1) {
3467 recLWBlock(i);
3468 pc = pc + i*4; continue;
3469 }
3470 }
3471
3472 if ((psxRegs.code >> 26) == 0x2b) { // SW
3473 int i;
3474 u32 code;
3475
3476 for (i=1;; i++) {
3477 p = (char *)PSXM(pc+i*4);
3478 if (p == NULL) recError();
3479 code = *(u32 *)p;
3480
3481 if ((code >> 26) != 0x2b ||
3482 _fRs_(code) != _Rs_ ||
3483 _fImm_(code) != (_Imm_+i*4))
3484 break;
3485 }
3486 if (i > 1) {
3487 recSWBlock(i);
3488 pc = pc + i*4; continue;
3489 }
3490 }*/
3491
3492 pc+=4; count++;
3493// iFlushRegs(0); // test
3494 recBSC[psxRegs.code>>26]();
3495
3496 if (branch) {
3497 branch = 0;
3498 //if (dump) iDumpBlock(ptr);
3499 goto done;
3500 }
3501 }
3502
3503 iFlushRegs(pc);
3504
3505 LIW(PutHWRegSpecial(PSXPC), pc);
3506
3507 iRet();
3508
3509done:;
3510#if 0
3511 MakeDataExecutable(ptr, ((u8*)ppcPtr)-((u8*)ptr));
3512#else
3513 u32 a = (u32)(u8*)ptr;
3514 while(a < (u32)(u8*)ppcPtr) {
3515 __asm__ __volatile__("icbi 0,%0" : : "r" (a));
3516 __asm__ __volatile__("dcbst 0,%0" : : "r" (a));
3517 a += 4;
3518 }
3519 __asm__ __volatile__("sync");
3520 __asm__ __volatile__("isync");
3521#endif
3522
3523#if 1
3524 sprintf((char *)ppcPtr, "PC=%08x", pcold);
3525 ppcPtr += strlen((char *)ppcPtr);
3526#endif
3527
3528 //mprotect(recMem, RECMEM_SIZE, PROT_EXEC|PROT_READ/*|PROT_WRITE*/);
3529}
3530
3531
3532R3000Acpu psxRec = {
3533 recInit,
3534 recReset,
3535 recExecute,
3536 recExecuteBlock,
3537 recClear,
3538 recShutdown
3539};
3540