1 /* Pcsx - Pc Psx Emulator
2 * Copyright (C) 1999-2003 Pcsx Team
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.
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.
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
20 #pragma warning(disable:4244)
21 #pragma warning(disable:4761)
26 #include <sys/types.h>
30 #define MAP_ANONYMOUS MAP_ANON
33 #include "../psxcommon.h"
36 #include "../r3000a.h"
37 #include "../psxhle.h"
44 #define _Op_ _fOp_(psxRegs.code)
46 #define _Funct_ _fFunct_(psxRegs.code)
48 #define _Rd_ _fRd_(psxRegs.code)
50 #define _Rt_ _fRt_(psxRegs.code)
52 #define _Rs_ _fRs_(psxRegs.code)
54 #define _Sa_ _fSa_(psxRegs.code)
56 #define _Im_ _fIm_(psxRegs.code)
58 #define _Target_ _fTarget_(psxRegs.code)
61 #define _Imm_ _fImm_(psxRegs.code)
63 #define _ImmU_ _fImmU_(psxRegs.code)
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))
74 #define OFFSET(X,Y) ((u32)(Y)-(u32)(X))
76 #define RECMEM_SIZE (12*1024*1024)
78 static char *recMem; /* the recompiled blocks will be here */
79 static char *recRAM; /* and the ptr to the blocks here */
80 static char *recROM; /* and here */
82 static u32 pc; /* recompiler pc */
83 static u32 pcold; /* recompiler oldpc */
84 static int count; /* recompiler intruction count */
85 static int branch; /* set for branch */
86 static u32 target; /* branch target */
90 u32 idlecyclecount = 0;
92 #define NUM_REGISTERS 34
99 static iRegisters iRegs[34];
102 #define ST_CONST 0x01
103 #define ST_MAPPED 0x02
106 #define IsConst(reg) 0
108 #define IsConst(reg) (iRegs[reg].state & ST_CONST)
110 #define IsMapped(reg) (iRegs[reg].state & ST_MAPPED)
112 static void (*recBSC[64])();
113 static void (*recSPC[64])();
114 static void (*recREG[32])();
115 static void (*recCP0[32])();
116 static void (*recCP2[64])();
117 static void (*recCP2BSC[32])();
122 // Hardware register usage
123 #define HWUSAGE_NONE 0x00
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 */
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
136 // Remember to invalidate the special registers if they are modified by compiler
158 void (*flush)(int hwreg);
161 static HWRegister HWRegisters[NUM_HW_REGISTERS];
162 static int HWRegUseCount;
163 static int DstCPUReg;
164 static int UniqueRegAlloc;
166 static int GetFreeHWReg();
167 static void InvalidateCPURegs();
168 static void DisposeHWReg(int index);
169 static void FlushHWReg(int index);
170 static void FlushAllHWReg();
171 static void MapPsxReg32(int reg);
172 static void FlushPsxReg32(int hwreg);
173 static int UpdateHWRegUsage(int hwreg, int usage);
174 static int GetHWReg32(int reg);
175 static int PutHWReg32(int reg);
176 static int GetSpecialIndexFromHWRegs(int which);
177 static int GetHWRegFromCPUReg(int cpureg);
178 static int MapRegSpecial(int which);
179 static void FlushRegSpecial(int hwreg);
180 static int GetHWRegSpecial(int which);
181 static int PutHWRegSpecial(int which);
182 static void recRecompile();
183 static void recError();
185 #pragma mark --- Generic register mapping ---
187 static int GetFreeHWReg()
191 if (DstCPUReg != -1) {
192 index = GetHWRegFromCPUReg(DstCPUReg);
195 // LRU algorith with a twist ;)
196 for (i=0; i<NUM_HW_REGISTERS; i++) {
197 if (!(HWRegisters[i].usage & HWUSAGE_RESERVED)) {
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) {
209 else if (HWRegisters[i].lastUsed < least) {
210 least = HWRegisters[i].lastUsed;
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;
232 /* if (HWRegisters[index].code < 13 && HWRegisters[index].code > 3) {
233 SysPrintf("Allocating volatile register %i\n", HWRegisters[index].code);
235 if (HWRegisters[index].usage != HWUSAGE_NONE) {
236 SysPrintf("RegUse too big. Flushing %i\n", HWRegisters[index].code);
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);
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);
249 if (HWRegisters[index].lastUsed != 0) {
253 // Make sure the register is really flushed!
255 HWRegisters[index].usage = HWUSAGE_NONE;
256 HWRegisters[index].flush = NULL;
261 static void FlushHWReg(int index)
263 if (index < 0) return;
264 if (HWRegisters[index].usage == HWUSAGE_NONE) return;
266 if (HWRegisters[index].flush) {
267 HWRegisters[index].usage |= HWUSAGE_RESERVED;
268 HWRegisters[index].flush(index);
269 HWRegisters[index].flush = NULL;
272 if (HWRegisters[index].usage & HWUSAGE_HARDWIRED) {
273 HWRegisters[index].usage &= ~(HWUSAGE_READ | HWUSAGE_WRITE);
275 HWRegisters[index].usage = HWUSAGE_NONE;
279 // get rid of a mapped register without flushing the contents to the memory
280 static void DisposeHWReg(int index)
282 if (index < 0) return;
283 if (HWRegisters[index].usage == HWUSAGE_NONE) return;
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);
293 // operated on cpu registers
294 __inline static void FlushCPURegRange(int start, int end)
298 if (end <= 0) end = 31;
299 if (start <= 0) start = 0;
301 for (i=0; i<NUM_HW_REGISTERS; i++) {
302 if (HWRegisters[i].code >= start && HWRegisters[i].code <= end)
303 if (HWRegisters[i].flush)
307 for (i=0; i<NUM_HW_REGISTERS; i++) {
308 if (HWRegisters[i].code >= start && HWRegisters[i].code <= end)
313 static void FlushAllHWReg()
315 FlushCPURegRange(0,31);
318 static void InvalidateCPURegs()
320 FlushCPURegRange(0,12);
323 #pragma mark --- Mapping utility functions ---
325 static void MoveHWRegToCPUReg(int cpureg, int hwreg)
329 if (HWRegisters[hwreg].code == cpureg)
332 dstreg = GetHWRegFromCPUReg(cpureg);
334 HWRegisters[dstreg].usage &= ~(HWUSAGE_HARDWIRED | HWUSAGE_ARG);
335 if (HWRegisters[hwreg].usage & (HWUSAGE_READ | HWUSAGE_WRITE)) {
337 MR(HWRegisters[dstreg].code, HWRegisters[hwreg].code);
339 if (HWRegisters[dstreg].usage & (HWUSAGE_READ | HWUSAGE_WRITE)) {
340 MR(HWRegisters[hwreg].code, HWRegisters[dstreg].code);
342 else if (HWRegisters[dstreg].usage != HWUSAGE_NONE) {
347 HWRegisters[dstreg].code = HWRegisters[hwreg].code;
348 HWRegisters[hwreg].code = cpureg;
351 static int UpdateHWRegUsage(int hwreg, int usage)
353 HWRegisters[hwreg].lastUsed = ++HWRegUseCount;
354 if (usage & HWUSAGE_WRITE) {
355 HWRegisters[hwreg].usage &= ~HWUSAGE_CONST;
357 if (!(usage & HWUSAGE_INITED)) {
358 HWRegisters[hwreg].usage &= ~HWUSAGE_INITED;
360 HWRegisters[hwreg].usage |= usage;
362 return HWRegisters[hwreg].code;
365 static int GetHWRegFromCPUReg(int cpureg)
368 for (i=0; i<NUM_HW_REGISTERS; i++) {
369 if (HWRegisters[i].code == cpureg) {
374 SysPrintf("Error! Register location failure (r%i)", cpureg);
378 // this function operates on cpu registers
379 void SetDstCPUReg(int cpureg)
384 static void ReserveArgs(int args)
388 for (i=0; i<args; i++) {
389 index = GetHWRegFromCPUReg(3+i);
390 HWRegisters[index].usage |= HWUSAGE_RESERVED | HWUSAGE_HARDWIRED | HWUSAGE_ARG;
394 static void ReleaseArgs()
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);
408 #pragma mark --- Psx register mapping ---
410 static void MapPsxReg32(int reg)
412 int hwreg = GetFreeHWReg();
413 HWRegisters[hwreg].flush = FlushPsxReg32;
414 HWRegisters[hwreg].private = reg;
416 if (iRegs[reg].reg != -1) {
417 SysPrintf("error: double mapped psx register");
420 iRegs[reg].reg = hwreg;
421 iRegs[reg].state |= ST_MAPPED;
424 static void FlushPsxReg32(int hwreg)
426 int reg = HWRegisters[hwreg].private;
428 if (iRegs[reg].reg == -1) {
429 SysPrintf("error: flushing unmapped psx register");
432 if (HWRegisters[hwreg].usage & HWUSAGE_WRITE) {
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));
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));
447 iRegs[reg].state = ST_UNK;
450 static int GetHWReg32(int reg)
452 int usage = HWUSAGE_PSXREG | HWUSAGE_READ;
455 return GetHWRegSpecial(REG_RZERO);
457 if (!IsMapped(reg)) {
458 usage |= HWUSAGE_INITED;
461 HWRegisters[iRegs[reg].reg].usage |= HWUSAGE_RESERVED;
463 LIW(HWRegisters[iRegs[reg].reg].code, iRegs[reg].k);
464 usage |= HWUSAGE_WRITE | HWUSAGE_CONST;
465 //iRegs[reg].state &= ~ST_CONST;
468 LWZ(HWRegisters[iRegs[reg].reg].code, OFFSET(&psxRegs, &psxRegs.GPR.r[reg]), GetHWRegSpecial(PSXREGS));
470 HWRegisters[iRegs[reg].reg].usage &= ~HWUSAGE_RESERVED;
472 else if (DstCPUReg != -1) {
476 if (HWRegisters[iRegs[reg].reg].code < 13) {
477 MoveHWRegToCPUReg(dst, iRegs[reg].reg);
479 MR(DstCPUReg, HWRegisters[iRegs[reg].reg].code);
485 return UpdateHWRegUsage(iRegs[reg].reg, usage);
488 static int PutHWReg32(int reg)
490 int usage = HWUSAGE_PSXREG | HWUSAGE_WRITE;
492 return PutHWRegSpecial(REG_WZERO);
495 if (DstCPUReg != -1 && IsMapped(reg)) {
496 if (HWRegisters[iRegs[reg].reg].code != DstCPUReg) {
499 DisposeHWReg(iRegs[reg].reg);
503 if (!IsMapped(reg)) {
504 usage |= HWUSAGE_INITED;
509 iRegs[reg].state &= ~ST_CONST;
511 return UpdateHWRegUsage(iRegs[reg].reg, usage);
514 #pragma mark --- Special register mapping ---
516 static int GetSpecialIndexFromHWRegs(int which)
519 for (i=0; i<NUM_HW_REGISTERS; i++) {
520 if (HWRegisters[i].usage & HWUSAGE_SPECIAL) {
521 if (HWRegisters[i].private == which) {
529 static int MapRegSpecial(int which)
531 int hwreg = GetFreeHWReg();
532 HWRegisters[hwreg].flush = FlushRegSpecial;
533 HWRegisters[hwreg].private = which;
538 static void FlushRegSpecial(int hwreg)
540 int which = HWRegisters[hwreg].private;
542 if (!(HWRegisters[hwreg].usage & HWUSAGE_WRITE))
547 STW(HWRegisters[hwreg].code, OFFSET(&psxRegs, &psxRegs.cycle), GetHWRegSpecial(PSXREGS));
550 STW(HWRegisters[hwreg].code, OFFSET(&psxRegs, &psxRegs.pc), GetHWRegSpecial(PSXREGS));
553 STW(HWRegisters[hwreg].code, 0, GetHWRegSpecial(TARGETPTR));
558 static int GetHWRegSpecial(int which)
560 int index = GetSpecialIndexFromHWRegs(which);
561 int usage = HWUSAGE_READ | HWUSAGE_SPECIAL;
564 usage |= HWUSAGE_INITED;
565 index = MapRegSpecial(which);
567 HWRegisters[index].usage |= HWUSAGE_RESERVED;
571 SysPrintf("error! shouldn't be here!\n");
572 //HWRegisters[index].flush = NULL;
573 //LIW(HWRegisters[index].code, (u32)&psxRegs);
576 HWRegisters[index].flush = NULL;
577 LIW(HWRegisters[index].code, (u32)&target);
580 HWRegisters[index].flush = NULL;
581 LIW(HWRegisters[index].code, 0);
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;
590 usage |= HWUSAGE_RESERVED;
594 LWZ(HWRegisters[index].code, OFFSET(&psxRegs, &psxRegs.cycle), GetHWRegSpecial(PSXREGS));
597 LWZ(HWRegisters[index].code, OFFSET(&psxRegs, &psxRegs.pc), GetHWRegSpecial(PSXREGS));
600 LWZ(HWRegisters[index].code, 0, GetHWRegSpecial(TARGETPTR));
603 SysPrintf("Error: Unknown special register in GetHWRegSpecial()\n");
606 HWRegisters[index].usage &= ~HWUSAGE_RESERVED;
608 else if (DstCPUReg != -1) {
612 MoveHWRegToCPUReg(dst, index);
615 return UpdateHWRegUsage(index, usage);
618 static int PutHWRegSpecial(int which)
620 int index = GetSpecialIndexFromHWRegs(which);
621 int usage = HWUSAGE_WRITE | HWUSAGE_SPECIAL;
623 if (DstCPUReg != -1 && index != -1) {
624 if (HWRegisters[index].code != DstCPUReg) {
634 SysPrintf("Error: Read-only special register in PutHWRegSpecial()\n");
637 if (HWRegisters[index].usage & HWUSAGE_WRITE)
640 index = MapRegSpecial(which);
641 HWRegisters[index].flush = NULL;
645 usage |= HWUSAGE_INITED;
646 index = MapRegSpecial(which);
648 HWRegisters[index].usage |= HWUSAGE_RESERVED;
653 MoveHWRegToCPUReg(3+(which-ARG1), index);
654 /*reg = GetHWRegFromCPUReg(3+(which-ARG1));
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);
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;
670 usage |= HWUSAGE_RESERVED | HWUSAGE_HARDWIRED | HWUSAGE_ARG;
674 HWRegisters[index].usage &= ~HWUSAGE_RESERVED;
680 return UpdateHWRegUsage(index, usage);
685 static void MapConst(int reg, u32 _const) {
688 if (IsConst(reg) && iRegs[reg].k == _const)
691 DisposeHWReg(iRegs[reg].reg);
692 iRegs[reg].k = _const;
693 iRegs[reg].state = ST_CONST;
696 static void MapCopy(int dst, int src)
698 // do it the lazy way for now
699 MR(PutHWReg32(dst), GetHWReg32(src));
702 static void iFlushReg(u32 nextpc, int reg) {
703 if (!IsMapped(reg) && IsConst(reg)) {
708 int use = nextPsxRegUse(nextpc, reg);
709 if ((use & REGUSE_RW) == REGUSE_WRITE) {
710 DisposeHWReg(iRegs[reg].reg);
712 FlushHWReg(iRegs[reg].reg);
715 FlushHWReg(iRegs[reg].reg);
720 static void iFlushRegs(u32 nextpc) {
723 for (i=1; i<NUM_REGISTERS; i++) {
724 iFlushReg(nextpc, i);
732 if (((u32)returnPC & 0x1fffffc) == (u32)returnPC) {
736 LIW(0, (u32)returnPC);
744 count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
745 ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
749 static int iLoadTest() {
752 // check for load delay
753 tmp = psxRegs.code >> 26;
776 if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
784 /* set a pending branch */
785 static void SetBranch() {
788 psxRegs.code = PSXMu32(pc);
791 if (iLoadTest() == 1) {
793 LIW(0, psxRegs.code);
794 STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS));
796 count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
797 ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
799 treg = GetHWRegSpecial(TARGET);
800 MR(PutHWRegSpecial(ARG2), treg);
801 DisposeHWReg(GetHWRegFromCPUReg(treg));
802 LIW(PutHWRegSpecial(ARG1), _Rt_);
803 LIW(GetHWRegSpecial(PSXPC), pc);
805 CALLFunc((u32)psxDelayTest);
811 recBSC[psxRegs.code>>26]();
814 treg = GetHWRegSpecial(TARGET);
815 MR(PutHWRegSpecial(PSXPC), GetHWRegSpecial(TARGET)); // FIXME: this line should not be needed
816 DisposeHWReg(GetHWRegFromCPUReg(treg));
819 count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
820 ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
822 CALLFunc((u32)psxBranchTest);
824 // TODO: don't return if target is compiled
828 static void iJump(u32 branchPC) {
831 psxRegs.code = PSXMu32(pc);
834 if (iLoadTest() == 1) {
836 LIW(0, psxRegs.code);
837 STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS));
839 count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
840 ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
842 LIW(PutHWRegSpecial(ARG2), branchPC);
843 LIW(PutHWRegSpecial(ARG1), _Rt_);
844 LIW(GetHWRegSpecial(PSXPC), pc);
846 CALLFunc((u32)psxDelayTest);
852 recBSC[psxRegs.code>>26]();
854 iFlushRegs(branchPC);
855 LIW(PutHWRegSpecial(PSXPC), branchPC);
858 count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
859 //if (/*psxRegs.code == 0 &&*/ count == 2 && branchPC == pcold) {
860 // LIW(PutHWRegSpecial(CYCLECOUNT), 0);
862 ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
865 CALLFunc((u32)psxBranchTest);
867 if (!Config.HLE && Config.PsxOut &&
868 ((branchPC & 0x1fffff) == 0xa0 ||
869 (branchPC & 0x1fffff) == 0xb0 ||
870 (branchPC & 0x1fffff) == 0xc0))
871 CALLFunc((u32)psxJumpTest);
873 // always return for now...
876 // maybe just happened an interruption, check so
878 CMPLW(GetHWRegSpecial(PSXPC), 0);
881 LIW(3, PC_REC(branchPC));
889 // next bit is already compiled - jump right to it
895 static void iBranch(u32 branchPC, int savectx) {
896 HWRegister HWRegistersS[NUM_HW_REGISTERS];
897 iRegisters iRegsS[NUM_REGISTERS];
898 int HWRegUseCountS = 0;
904 memcpy(iRegsS, iRegs, sizeof(iRegs));
905 memcpy(HWRegistersS, HWRegisters, sizeof(HWRegisters));
906 HWRegUseCountS = HWRegUseCount;
910 psxRegs.code = PSXMu32(pc);
912 // the delay test is only made when the branch is taken
913 // savectx == 0 will mean that :)
914 if (savectx == 0 && iLoadTest() == 1) {
916 LIW(0, psxRegs.code);
917 STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS));
919 count = (idlecyclecount + ((pc+4) - pcold) / 4) * BIAS;
920 ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
922 LIW(PutHWRegSpecial(ARG2), branchPC);
923 LIW(PutHWRegSpecial(ARG1), _Rt_);
924 LIW(GetHWRegSpecial(PSXPC), pc);
926 CALLFunc((u32)psxDelayTest);
933 recBSC[psxRegs.code>>26]();
935 iFlushRegs(branchPC);
936 LIW(PutHWRegSpecial(PSXPC), branchPC);
940 count = (idlecyclecount + (pc - pcold) / 4) * BIAS;
941 //if (/*psxRegs.code == 0 &&*/ count == 2 && branchPC == pcold) {
942 // LIW(PutHWRegSpecial(CYCLECOUNT), 0);
944 ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
947 CALLFunc((u32)psxBranchTest);
949 // always return for now...
953 CMPLW(GetHWRegSpecial(PSXPC), 0);
956 LIW(3, PC_REC(branchPC));
968 // maybe just happened an interruption, check so
969 /* CMP32ItoM((u32)&psxRegs.pc, branchPC);
974 MOV32MtoR(EAX, PC_REC(branchPC));
975 TEST32RtoR(EAX, EAX);
985 memcpy(iRegs, iRegsS, sizeof(iRegs));
986 memcpy(HWRegisters, HWRegistersS, sizeof(HWRegisters));
987 HWRegUseCount = HWRegUseCountS;
992 static void iDumpRegs() {
995 printf("%lx %lx\n", psxRegs.pc, psxRegs.cycle);
996 for (i=0; i<4; i++) {
998 printf("%lx ", psxRegs.GPR.r[j*i]);
1003 void iDumpBlock(char *ptr) {
1007 SysPrintf("dump1 %x:%x, %x\n", psxRegs.pc, pc, psxCurrentCycle);
1009 for (i = psxRegs.pc; i < pc; i+=4)
1010 SysPrintf("%s\n", disR3000AF(PSXMu32(i), i));
1013 f = fopen("dump1", "w");
1014 fwrite(ptr, 1, (u32)x86Ptr - (u32)ptr, f);
1016 system("ndisasmw -u dump1");
1020 #define REC_FUNC(f) \
1022 static void rec##f() { \
1024 LIW(PutHWRegSpecial(ARG1), (u32)psxRegs.code); \
1025 STW(GetHWRegSpecial(ARG1), OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \
1026 LIW(PutHWRegSpecial(PSXPC), (u32)pc); \
1028 CALLFunc((u32)psx##f); \
1032 #define REC_SYS(f) \
1034 static void rec##f() { \
1036 LIW(PutHWRegSpecial(ARG1), (u32)psxRegs.code); \
1037 STW(GetHWRegSpecial(ARG1), OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \
1038 LIW(PutHWRegSpecial(PSXPC), (u32)pc); \
1040 CALLFunc((u32)psx##f); \
1045 #define REC_BRANCH(f) \
1047 static void rec##f() { \
1049 LIW(PutHWRegSpecial(ARG1), (u32)psxRegs.code); \
1050 STW(GetHWRegSpecial(ARG1), OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \
1051 LIW(PutHWRegSpecial(PSXPC), (u32)pc); \
1053 CALLFunc((u32)psx##f); \
1058 static void freeMem(int all)
1060 if (recMem) free(recMem);
1061 if (recRAM) free(recRAM);
1062 if (recROM) free(recROM);
1063 recMem = recRAM = recROM = 0;
1065 if (all && psxRecLUT) {
1066 free(psxRecLUT); psxRecLUT = NULL;
1070 static int allocMem() {
1075 if (psxRecLUT==NULL)
1076 psxRecLUT = (u32*) malloc(0x010000 * 4);
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) {
1084 SysMessage("Error allocating memory"); return -1;
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);
1091 for (i=0; i<0x08; i++) psxRecLUT[i + 0xbfc0] = (u32)&recROM[i << 16];
1096 static int recInit() {
1100 static void recReset() {
1101 memset(recRAM, 0, 0x200000);
1102 memset(recROM, 0, 0x080000);
1105 ppcSetPtr((u32 *)recMem);
1108 memset(iRegs, 0, sizeof(iRegs));
1109 iRegs[0].state = ST_CONST;
1113 static void recShutdown() {
1118 static void recError() {
1121 SysMessage("Unrecoverable error while running recompiler\n");
1125 __inline static void execute() {
1129 p = (char*)PC_REC(psxRegs.pc);
1130 /*if (p != NULL)*/ recFunc = (void (**)()) (u32)p;
1131 /*else { recError(); return; }*/
1133 if (*recFunc == 0) {
1136 recRun(*recFunc, (u32)&psxRegs, (u32)&psxM);
1139 static void recExecute() {
1143 static void recExecuteBlock() {
1147 static void recClear(u32 Addr, u32 Size) {
1148 memset((void*)PC_REC(Addr), 0, Size * 4);
1151 static void recNULL() {
1152 // SysMessage("recUNK: %8.8x\n", psxRegs.code);
1155 /*********************************************************
1156 * goes to opcodes tables... *
1157 * Format: table[something....] *
1158 *********************************************************/
1161 static void recSPECIAL() {
1165 static void recREGIMM() {
1169 static void recCOP0() {
1174 static void recCOP2() {
1178 static void recBASIC() {
1182 //end of Tables opcodes...
1184 #pragma mark - Arithmetic with immediate operand -
1185 /*********************************************************
1186 * Arithmetic with immediate operand *
1187 * Format: OP rt, rs, immediate *
1188 *********************************************************/
1199 static void recADDIU() {
1203 if (IsConst(_Rs_)) {
1204 MapConst(_Rt_, iRegs[_Rs_].k + _Imm_);
1207 MapCopy(_Rt_, _Rs_);
1209 ADDI(PutHWReg32(_Rt_), GetHWReg32(_Rs_), _Imm_);
1214 static void recADDI() {
1221 //CR0: SIGN | POSITIVE | ZERO | SOVERFLOW | SOVERFLOW | OVERFLOW | CARRY
1222 static void recSLTI() {
1223 // Rt = Rs < Im (signed)
1226 if (IsConst(_Rs_)) {
1227 MapConst(_Rt_, (s32)iRegs[_Rs_].k < _Imm_);
1230 SRWI(PutHWReg32(_Rt_), GetHWReg32(_Rs_), 31);
1233 CMPWI(GetHWReg32(_Rs_), _Imm_);
1234 reg = PutHWReg32(_Rt_);
1242 static void recSLTIU() {
1243 // Rt = Rs < Im (unsigned)
1246 if (IsConst(_Rs_)) {
1247 MapConst(_Rt_, iRegs[_Rs_].k < _ImmU_);
1250 CMPLWI(GetHWReg32(_Rs_), _Imm_);
1251 reg = PutHWReg32(_Rt_);
1258 static void recANDI() {
1262 if (IsConst(_Rs_)) {
1263 MapConst(_Rt_, iRegs[_Rs_].k & _ImmU_);
1265 ANDI_(PutHWReg32(_Rt_), GetHWReg32(_Rs_), _ImmU_);
1269 static void recORI() {
1273 if (IsConst(_Rs_)) {
1274 MapConst(_Rt_, iRegs[_Rs_].k | _ImmU_);
1277 MapCopy(_Rt_, _Rs_);
1279 ORI(PutHWReg32(_Rt_), GetHWReg32(_Rs_), _ImmU_);
1284 static void recXORI() {
1288 if (IsConst(_Rs_)) {
1289 MapConst(_Rt_, iRegs[_Rs_].k ^ _ImmU_);
1291 XORI(PutHWReg32(_Rt_), GetHWReg32(_Rs_), _ImmU_);
1295 //end of * Arithmetic with immediate operand
1297 /*********************************************************
1298 * Load higher 16 bits of the first word in GPR with imm *
1299 * Format: OP rt, immediate *
1300 *********************************************************/
1303 static void recLUI() {
1307 MapConst(_Rt_, psxRegs.code << 16);
1310 //End of Load Higher .....
1312 #pragma mark - Register arithmetic -
1313 /*********************************************************
1314 * Register arithmetic *
1315 * Format: OP rd, rs, rt *
1316 *********************************************************/
1330 static void recADDU() {
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);
1342 ADD(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
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);
1350 ADD(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1353 ADD(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1357 static void recADD() {
1362 static void recSUBU() {
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);
1374 SUB(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1377 SUB(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1381 static void recSUB() {
1386 static void recAND() {
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);
1397 AND(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
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);
1403 AND(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1406 AND(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1410 static void recOR() {
1414 if (IsConst(_Rs_) && IsConst(_Rt_)) {
1415 MapConst(_Rd_, iRegs[_Rs_].k | iRegs[_Rt_].k);
1419 MapCopy(_Rd_, _Rs_);
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);
1425 OR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
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);
1432 OR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1435 OR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1440 static void recXOR() {
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);
1450 XOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
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);
1456 XOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1459 XOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1463 static void recNOR() {
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);
1473 NOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
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);
1479 NOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1482 NOR(PutHWReg32(_Rd_), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1486 static void recSLT() {
1487 // Rd = Rs < Rt (signed)
1490 if (IsConst(_Rs_) && IsConst(_Rt_)) {
1491 MapConst(_Rd_, (s32)iRegs[_Rs_].k < (s32)iRegs[_Rt_].k);
1492 } else { // TODO: add immidiate cases
1494 CMPW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1495 reg = PutHWReg32(_Rd_);
1502 static void recSLTU() {
1503 // Rd = Rs < Rt (unsigned)
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_));
1515 //End of * Register arithmetic
1517 #pragma mark - mult/div & Register trap logic -
1518 /*********************************************************
1519 * Register mult/div & Register trap logic *
1520 * Format: OP rs, rt *
1521 *********************************************************/
1533 for (i=0; i<30; i++) {
1534 if (k == (1ul << i))
1542 // FIXME: doesn't work in GT - wrong way marker
1543 static void recMULT() {
1544 // Lo/Hi = Rs * Rt (signed)
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);
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));
1562 if (IsConst(_Rs_)) {
1563 k = (s32)iRegs[_Rs_].k;
1565 } else if (IsConst(_Rt_)) {
1566 k = (s32)iRegs[_Rt_].k;
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);
1581 int shift = DoShift(k);
1584 SLWI(PutHWReg32(REG_LO), GetHWReg32(r), shift)
1587 SRAWI(PutHWReg32(REG_HI), GetHWReg32(r), 31-shift);
1590 //if ((s32)(s16)k == k) {
1591 // MULLWI(PutHWReg32(REG_LO), GetHWReg32(r), k);
1592 // MULHWI(PutHWReg32(REG_HI), GetHWReg32(r), k);
1596 MULLW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1599 MULHW(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1605 MULLW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1608 MULHW(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1613 static void recMULTU() {
1614 // Lo/Hi = Rs * Rt (unsigned)
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);
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));
1632 if (IsConst(_Rs_)) {
1633 k = (s32)iRegs[_Rs_].k;
1635 } else if (IsConst(_Rt_)) {
1636 k = (s32)iRegs[_Rt_].k;
1643 uselo = isPsxRegUsed(pc, REG_LO);
1644 usehi = isPsxRegUsed(pc, REG_HI);
1647 int shift = DoShift(k);
1650 SLWI(PutHWReg32(REG_LO), GetHWReg32(r), shift);
1653 SRWI(PutHWReg32(REG_HI), GetHWReg32(r), 31-shift);
1658 MULLW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1661 MULHWU(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1667 MULLW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1670 MULHWU(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1675 static void recDIV() {
1676 // Lo/Hi = Rs / Rt (signed)
1679 if (IsConst(_Rs_) && iRegs[_Rs_].k == 0) {
1680 MapConst(REG_LO, 0);
1681 MapConst(REG_HI, 0);
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);
1690 usehi = isPsxRegUsed(pc, REG_HI);
1692 if (IsConst(_Rt_)) {
1693 int shift = DoShift(iRegs[_Rt_].k);
1695 SRAWI(PutHWReg32(REG_LO), GetHWReg32(_Rs_), shift);
1696 ADDZE(PutHWReg32(REG_LO), GetHWReg32(REG_LO));
1698 RLWINM(PutHWReg32(REG_HI), GetHWReg32(_Rs_), 0, 31-shift, 31);
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));
1708 MULLI(PutHWReg32(REG_HI), GetHWReg32(REG_LO), 3);
1709 SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI));
1712 DIVW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1714 if ((iRegs[_Rt_].k & 0x7fff) == iRegs[_Rt_].k) {
1715 MULLI(PutHWReg32(REG_HI), GetHWReg32(REG_LO), iRegs[_Rt_].k);
1717 MULLW(PutHWReg32(REG_HI), GetHWReg32(REG_LO), GetHWReg32(_Rt_));
1719 SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI));
1723 DIVW(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1725 MULLW(PutHWReg32(REG_HI), GetHWReg32(REG_LO), GetHWReg32(_Rt_));
1726 SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI));
1731 static void recDIVU() {
1732 // Lo/Hi = Rs / Rt (unsigned)
1735 if (IsConst(_Rs_) && iRegs[_Rs_].k == 0) {
1736 MapConst(REG_LO, 0);
1737 MapConst(REG_HI, 0);
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);
1746 usehi = isPsxRegUsed(pc, REG_HI);
1748 if (IsConst(_Rt_)) {
1749 int shift = DoShift(iRegs[_Rt_].k);
1751 SRWI(PutHWReg32(REG_LO), GetHWReg32(_Rs_), shift);
1753 RLWINM(PutHWReg32(REG_HI), GetHWReg32(_Rs_), 0, 31-shift, 31);
1756 DIVWU(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1758 MULLW(PutHWReg32(REG_HI), GetHWReg32(_Rt_), GetHWReg32(REG_LO));
1759 SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI));
1763 DIVWU(PutHWReg32(REG_LO), GetHWReg32(_Rs_), GetHWReg32(_Rt_));
1765 MULLW(PutHWReg32(REG_HI), GetHWReg32(_Rt_), GetHWReg32(REG_LO));
1766 SUB(PutHWReg32(REG_HI), GetHWReg32(_Rs_), GetHWReg32(REG_HI));
1771 //End of * Register mult/div & Register trap logic
1773 #pragma mark - memory access -
1791 static void preMemRead()
1797 DisposeHWReg(iRegs[_Rt_].reg);
1799 rs = GetHWReg32(_Rs_);
1800 if (rs != 3 || _Imm_ != 0) {
1801 ADDI(PutHWRegSpecial(ARG1), rs, _Imm_);
1804 DisposeHWReg(iRegs[_Rt_].reg);
1806 InvalidateCPURegs();
1810 static void preMemWrite(int size)
1815 rs = GetHWReg32(_Rs_);
1816 if (rs != 3 || _Imm_ != 0) {
1817 ADDI(PutHWRegSpecial(ARG1), rs, _Imm_);
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);
1826 MR(PutHWRegSpecial(ARG2), GetHWReg32(_Rt_));
1829 InvalidateCPURegs();
1833 static void recLB() {
1834 // Rt = mem[Rs + Im] (signed)
1836 /*if (IsConst(_Rs_)) {
1837 u32 addr = iRegs[_Rs_].k + _Imm_;
1840 if ((t & 0xfff0) == 0xbfc0) {
1842 // since bios is readonly it won't change
1843 MapConst(_Rt_, psxRs8(addr));
1846 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
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_));
1855 if (t == 0x1f80 && addr < 0x1f801000) {
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_));
1864 // SysPrintf("unhandled r8 %x\n", addr);
1868 CALLFunc((u32)psxMemRead8);
1870 EXTSB(PutHWReg32(_Rt_), GetHWRegSpecial(RETVAL));
1871 DisposeHWReg(GetSpecialIndexFromHWRegs(RETVAL));
1875 static void recLBU() {
1876 // Rt = mem[Rs + Im] (unsigned)
1878 /*if (IsConst(_Rs_)) {
1879 u32 addr = iRegs[_Rs_].k + _Imm_;
1882 if ((t & 0xfff0) == 0xbfc0) {
1884 // since bios is readonly it won't change
1885 MapConst(_Rt_, psxRu8(addr));
1888 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
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_));
1896 if (t == 0x1f80 && addr < 0x1f801000) {
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_));
1904 // SysPrintf("unhandled r8 %x\n", addr);
1908 CALLFunc((u32)psxMemRead8);
1916 static void recLH() {
1917 // Rt = mem[Rs + Im] (signed)
1919 if (IsConst(_Rs_)) {
1920 u32 addr = iRegs[_Rs_].k + _Imm_;
1923 if ((t & 0xfff0) == 0xbfc0) {
1925 // since bios is readonly it won't change
1926 MapConst(_Rt_, psxRs16(addr));
1929 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1932 LIW(PutHWReg32(_Rt_), (u32)&psxM[addr & 0x1fffff]);
1933 LHBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
1934 EXTSH(PutHWReg32(_Rt_), GetHWReg32(_Rt_));
1937 if (t == 0x1f80 && addr < 0x1f801000) {
1940 LIW(PutHWReg32(_Rt_), (u32)&psxH[addr & 0xfff]);
1941 LHBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
1942 EXTSH(PutHWReg32(_Rt_), GetHWReg32(_Rt_));
1945 // SysPrintf("unhandled r16 %x\n", addr);
1949 CALLFunc((u32)psxMemRead16);
1951 EXTSH(PutHWReg32(_Rt_), GetHWRegSpecial(RETVAL));
1952 DisposeHWReg(GetSpecialIndexFromHWRegs(RETVAL));
1956 static void recLHU() {
1957 // Rt = mem[Rs + Im] (unsigned)
1959 if (IsConst(_Rs_)) {
1960 u32 addr = iRegs[_Rs_].k + _Imm_;
1963 if ((t & 0xfff0) == 0xbfc0) {
1965 // since bios is readonly it won't change
1966 MapConst(_Rt_, psxRu16(addr));
1969 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1972 LIW(PutHWReg32(_Rt_), (u32)&psxM[addr & 0x1fffff]);
1973 LHBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
1976 if (t == 0x1f80 && addr < 0x1f801000) {
1979 LIW(PutHWReg32(_Rt_), (u32)&psxH[addr & 0xfff]);
1980 LHBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
1984 if (addr >= 0x1f801c00 && addr < 0x1f801e00) {
1988 LIW(PutHWRegSpecial(ARG1), addr);
1989 DisposeHWReg(iRegs[_Rt_].reg);
1990 InvalidateCPURegs();
1991 CALLFunc((u32)SPU_readRegister);
1998 case 0x1f801100: case 0x1f801110: case 0x1f801120:
2002 LIW(PutHWRegSpecial(ARG1), (addr >> 4) & 0x3);
2003 DisposeHWReg(iRegs[_Rt_].reg);
2004 InvalidateCPURegs();
2005 CALLFunc((u32)psxRcntRcount);
2011 case 0x1f801104: case 0x1f801114: case 0x1f801124:
2015 LIW(PutHWRegSpecial(ARG1), (addr >> 4) & 0x3);
2016 DisposeHWReg(iRegs[_Rt_].reg);
2017 InvalidateCPURegs();
2018 CALLFunc((u32)psxRcntRmode);
2024 case 0x1f801108: case 0x1f801118: case 0x1f801128:
2028 LIW(PutHWRegSpecial(ARG1), (addr >> 4) & 0x3);
2029 DisposeHWReg(iRegs[_Rt_].reg);
2030 InvalidateCPURegs();
2031 CALLFunc((u32)psxRcntRtarget);
2038 // SysPrintf("unhandled r16u %x\n", addr);
2042 CALLFunc((u32)psxMemRead16);
2049 static void recLW() {
2050 // Rt = mem[Rs + Im] (unsigned)
2052 if (IsConst(_Rs_)) {
2053 u32 addr = iRegs[_Rs_].k + _Imm_;
2056 if ((t & 0xfff0) == 0xbfc0) {
2058 // since bios is readonly it won't change
2059 MapConst(_Rt_, psxRu32(addr));
2062 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2065 LIW(PutHWReg32(_Rt_), (u32)&psxM[addr & 0x1fffff]);
2066 LWBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
2069 if (t == 0x1f80 && addr < 0x1f801000) {
2072 LIW(PutHWReg32(_Rt_), (u32)&psxH[addr & 0xfff]);
2073 LWBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
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:
2089 LIW(PutHWReg32(_Rt_), (u32)&psxH[addr & 0xffff]);
2090 LWBRX(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_));
2096 DisposeHWReg(iRegs[_Rt_].reg);
2097 InvalidateCPURegs();
2098 CALLFunc((u32)GPU_readData);
2107 DisposeHWReg(iRegs[_Rt_].reg);
2108 InvalidateCPURegs();
2109 CALLFunc((u32)GPU_readStatus);
2116 // SysPrintf("unhandled r32 %x\n", addr);
2120 CALLFunc((u32)psxMemRead32);
2131 /*extern u32 LWL_MASK[4];
2132 extern u32 LWL_SHIFT[4];
2134 void iLWLk(u32 shift) {
2135 if (IsConst(_Rt_)) {
2136 MOV32ItoR(ECX, iRegs[_Rt_].k);
2138 MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
2140 AND32ItoR(ECX, LWL_MASK[shift]);
2141 SHL32ItoR(EAX, LWL_SHIFT[shift]);
2142 OR32RtoR (EAX, ECX);
2146 // Rt = Rt Merge mem[Rs + Im]
2148 if (IsConst(_Rs_)) {
2149 u32 addr = iRegs[_Rs_].k + _Imm_;
2152 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2153 MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
2156 iRegs[_Rt_].state = ST_UNK;
2157 MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
2160 if (t == 0x1f80 && addr < 0x1f801000) {
2161 MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
2164 iRegs[_Rt_].state = ST_UNK;
2165 MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
2170 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2172 MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
2173 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2178 CALLFunc((u32)psxMemRead32);
2183 AND32ItoR(EDX, 0x3); // shift = addr & 3;
2185 MOV32ItoR(ECX, (u32)LWL_SHIFT);
2186 MOV32RmStoR(ECX, ECX, EDX, 2);
2187 SHL32CLtoR(EAX); // mem(EAX) << LWL_SHIFT[shift]
2189 MOV32ItoR(ECX, (u32)LWL_MASK);
2190 MOV32RmStoR(ECX, ECX, EDX, 2);
2191 if (IsConst(_Rt_)) {
2192 MOV32ItoR(EDX, iRegs[_Rt_].k);
2194 MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
2196 AND32RtoR(EDX, ECX); // _rRt_ & LWL_MASK[shift]
2200 iRegs[_Rt_].state = ST_UNK;
2201 MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
2203 // ADD32ItoR(ESP, 8);
2208 static void recLWBlock(int count) {
2209 u32 *code = PSXM(pc);
2211 // Rt = mem[Rs + Im] (unsigned)
2215 if (IsConst(_Rs_)) {
2216 u32 addr = iRegs[_Rs_].k + _Imm_;
2219 if ((t & 0xfff0) == 0xbfc0) {
2220 // since bios is readonly it won't change
2221 for (i=0; i<count; i++, code++, addr+=4) {
2223 MapConst(_fRt_(*code), psxRu32(addr));
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;
2233 MOV32MtoR(EAX, (u32)&psxM[addr & 0x1fffff]);
2234 MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX);
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;
2243 MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]);
2244 MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX);
2250 SysPrintf("recLWBlock %d: %d\n", count, IsConst(_Rs_));
2252 CALLFunc((u32)psxMemPointer);
2253 // ADD32ItoR(ESP, 4);
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++) {
2262 iRegs[_fRt_(*code)].state = ST_UNK;
2264 MOV32RmStoR(EDX, EAX, ECX, 2);
2265 MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EDX);
2267 if (i != (count-1)) INC32R(ECX);
2269 j32Ptr[5] = JMP32(0);
2270 x86SetJ32(j32Ptr[4]);
2271 for (i=0, code = PSXM(pc); i<count; i++, code++) {
2272 psxRegs.code = *code;
2275 ADD32ItoR(ESP, resp);
2276 x86SetJ32(j32Ptr[5]);
2280 extern u32 LWR_MASK[4];
2281 extern u32 LWR_SHIFT[4];
2283 void iLWRk(u32 shift) {
2284 if (IsConst(_Rt_)) {
2285 MOV32ItoR(ECX, iRegs[_Rt_].k);
2287 MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
2289 AND32ItoR(ECX, LWR_MASK[shift]);
2290 SHR32ItoR(EAX, LWR_SHIFT[shift]);
2291 OR32RtoR (EAX, ECX);
2295 // Rt = Rt Merge mem[Rs + Im]
2297 if (IsConst(_Rs_)) {
2298 u32 addr = iRegs[_Rs_].k + _Imm_;
2301 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2302 MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
2305 iRegs[_Rt_].state = ST_UNK;
2306 MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
2309 if (t == 0x1f80 && addr < 0x1f801000) {
2310 MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
2313 iRegs[_Rt_].state = ST_UNK;
2314 MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
2319 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2321 MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
2322 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2327 CALLFunc((u32)psxMemRead32);
2332 AND32ItoR(EDX, 0x3); // shift = addr & 3;
2334 MOV32ItoR(ECX, (u32)LWR_SHIFT);
2335 MOV32RmStoR(ECX, ECX, EDX, 2);
2336 SHR32CLtoR(EAX); // mem(EAX) >> LWR_SHIFT[shift]
2338 MOV32ItoR(ECX, (u32)LWR_MASK);
2339 MOV32RmStoR(ECX, ECX, EDX, 2);
2341 if (IsConst(_Rt_)) {
2342 MOV32ItoR(EDX, iRegs[_Rt_].k);
2344 MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
2346 AND32RtoR(EDX, ECX); // _rRt_ & LWR_MASK[shift]
2350 iRegs[_Rt_].state = ST_UNK;
2351 MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
2353 // ADD32ItoR(ESP, 8);
2358 static void recSB() {
2359 // mem[Rs + Im] = Rt
2361 /*if (IsConst(_Rs_)) {
2362 u32 addr = iRegs[_Rs_].k + _Imm_;
2365 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2366 if (IsConst(_Rt_)) {
2367 MOV8ItoM((u32)&psxM[addr & 0x1fffff], (u8)iRegs[_Rt_].k);
2369 MOV8MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
2370 MOV8RtoM((u32)&psxM[addr & 0x1fffff], EAX);
2374 if (t == 0x1f80 && addr < 0x1f801000) {
2375 if (IsConst(_Rt_)) {
2376 MOV8ItoM((u32)&psxH[addr & 0xfff], (u8)iRegs[_Rt_].k);
2378 MOV8MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
2379 MOV8RtoM((u32)&psxH[addr & 0xfff], EAX);
2383 // SysPrintf("unhandled w8 %x\n", addr);
2387 CALLFunc((u32)psxMemWrite8);
2390 static void recSH() {
2391 // mem[Rs + Im] = Rt
2393 /*if (IsConst(_Rs_)) {
2394 u32 addr = iRegs[_Rs_].k + _Imm_;
2397 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2398 if (IsConst(_Rt_)) {
2399 MOV16ItoM((u32)&psxM[addr & 0x1fffff], (u16)iRegs[_Rt_].k);
2401 MOV16MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
2402 MOV16RtoM((u32)&psxM[addr & 0x1fffff], EAX);
2406 if (t == 0x1f80 && addr < 0x1f801000) {
2407 if (IsConst(_Rt_)) {
2408 MOV16ItoM((u32)&psxH[addr & 0xfff], (u16)iRegs[_Rt_].k);
2410 MOV16MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
2411 MOV16RtoM((u32)&psxH[addr & 0xfff], EAX);
2416 if (addr >= 0x1f801c00 && addr < 0x1f801e00) {
2417 if (IsConst(_Rt_)) {
2418 PUSH32I(iRegs[_Rt_].k);
2420 PUSH32M((u32)&psxRegs.GPR.r[_Rt_]);
2423 CALL32M ((u32)&SPU_writeRegister);
2430 // SysPrintf("unhandled w16 %x\n", addr);
2434 CALLFunc((u32)psxMemWrite16);
2437 static void recSW() {
2438 // mem[Rs + Im] = Rt
2441 if (IsConst(_Rs_)) {
2442 u32 addr = iRegs[_Rs_].k + _Imm_;
2445 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2446 LIW(0, addr & 0x1fffff);
2447 STWBRX(GetHWReg32(_Rt_), GetHWRegSpecial(PSXMEM), 0);
2450 if (t == 0x1f80 && addr < 0x1f801000) {
2451 LIW(0, (u32)&psxH[addr & 0xfff]);
2452 STWBRX(GetHWReg32(_Rt_), 0, 0);
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:
2466 LIW(0, (u32)&psxH[addr & 0xffff]);
2467 STWBRX(GetHWReg32(_Rt_), 0, 0);
2471 if (IsConst(_Rt_)) {
2472 PUSH32I(iRegs[_Rt_].k);
2474 PUSH32M((u32)&psxRegs.GPR.r[_Rt_]);
2476 CALL32M((u32)&GPU_writeData);
2483 if (IsConst(_Rt_)) {
2484 PUSH32I(iRegs[_Rt_].k);
2486 PUSH32M((u32)&psxRegs.GPR.r[_Rt_]);
2488 CALL32M((u32)&GPU_writeStatus);
2494 // SysPrintf("unhandled w32 %x\n", addr);
2497 /* LIS(0, 0x0079 + ((_Imm_ <= 0) ? 1 : 0));
2498 CMPLW(GetHWReg32(_Rs_), 0);
2502 ADDI(0, GetHWReg32(_Rs_), _Imm_);
2503 RLWINM(0, GetHWReg32(_Rs_), 0, 11, 31);
2504 STWBRX(GetHWReg32(_Rt_), GetHWRegSpecial(PSXMEM), 0);
2510 CALLFunc((u32)psxMemWrite32);
2516 static void recSWBlock(int count) {
2519 // mem[Rs + Im] = Rt
2523 if (IsConst(_Rs_)) {
2524 u32 addr = iRegs[_Rs_].k + _Imm_;
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);
2533 MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_fRt_(*code)]);
2534 MOV32RtoM((u32)&psxM[addr & 0x1fffff], EAX);
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;
2544 MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]);
2545 MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX);
2551 SysPrintf("recSWBlock %d: %d\n", count, IsConst(_Rs_));
2553 CALLFunc((u32)psxMemPointer);
2554 // ADD32ItoR(ESP, 4);
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);
2565 MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_fRt_(*code)]);
2567 MOV32RtoRmS(EAX, ECX, 2, EDX);
2568 if (i != (count-1)) INC32R(ECX);
2570 j32Ptr[5] = JMP32(0);
2571 x86SetJ32(j32Ptr[4]);
2572 for (i=0, code = PSXM(pc); i<count; i++, code++) {
2573 psxRegs.code = *code;
2576 ADD32ItoR(ESP, resp);
2577 x86SetJ32(j32Ptr[5]);
2581 extern u32 SWL_MASK[4];
2582 extern u32 SWL_SHIFT[4];
2584 void iSWLk(u32 shift) {
2585 if (IsConst(_Rt_)) {
2586 MOV32ItoR(ECX, iRegs[_Rt_].k);
2588 MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
2590 SHR32ItoR(ECX, SWL_SHIFT[shift]);
2591 AND32ItoR(EAX, SWL_MASK[shift]);
2592 OR32RtoR (EAX, ECX);
2596 // mem[Rs + Im] = Rt Merge mem[Rs + Im]
2598 if (IsConst(_Rs_)) {
2599 u32 addr = iRegs[_Rs_].k + _Imm_;
2602 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2603 MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
2605 MOV32RtoM((u32)&psxM[addr & 0x1ffffc], EAX);
2608 if (t == 0x1f80 && addr < 0x1f801000) {
2609 MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
2611 MOV32RtoM((u32)&psxH[addr & 0xffc], EAX);
2616 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2618 MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
2619 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2625 CALLFunc((u32)psxMemRead32);
2629 AND32ItoR(EDX, 0x3); // shift = addr & 3;
2631 MOV32ItoR(ECX, (u32)SWL_MASK);
2632 MOV32RmStoR(ECX, ECX, EDX, 2);
2633 AND32RtoR(EAX, ECX); // mem & SWL_MASK[shift]
2635 MOV32ItoR(ECX, (u32)SWL_SHIFT);
2636 MOV32RmStoR(ECX, ECX, EDX, 2);
2637 if (IsConst(_Rt_)) {
2638 MOV32ItoR(EDX, iRegs[_Rt_].k);
2640 MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
2642 SHR32CLtoR(EDX); // _rRt_ >> SWL_SHIFT[shift]
2644 OR32RtoR (EAX, EDX);
2647 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2649 MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
2650 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2655 CALLFunc((u32)psxMemWrite32);
2656 // ADD32ItoR(ESP, 8);
2660 extern u32 SWR_MASK[4];
2661 extern u32 SWR_SHIFT[4];
2663 void iSWRk(u32 shift) {
2664 if (IsConst(_Rt_)) {
2665 MOV32ItoR(ECX, iRegs[_Rt_].k);
2667 MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
2669 SHL32ItoR(ECX, SWR_SHIFT[shift]);
2670 AND32ItoR(EAX, SWR_MASK[shift]);
2671 OR32RtoR (EAX, ECX);
2675 // mem[Rs + Im] = Rt Merge mem[Rs + Im]
2677 if (IsConst(_Rs_)) {
2678 u32 addr = iRegs[_Rs_].k + _Imm_;
2681 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2682 MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
2684 MOV32RtoM((u32)&psxM[addr & 0x1ffffc], EAX);
2687 if (t == 0x1f80 && addr < 0x1f801000) {
2688 MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
2690 MOV32RtoM((u32)&psxH[addr & 0xffc], EAX);
2695 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2697 MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
2698 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2704 CALLFunc((u32)psxMemRead32);
2708 AND32ItoR(EDX, 0x3); // shift = addr & 3;
2710 MOV32ItoR(ECX, (u32)SWR_MASK);
2711 MOV32RmStoR(ECX, ECX, EDX, 2);
2712 AND32RtoR(EAX, ECX); // mem & SWR_MASK[shift]
2714 MOV32ItoR(ECX, (u32)SWR_SHIFT);
2715 MOV32RmStoR(ECX, ECX, EDX, 2);
2716 if (IsConst(_Rt_)) {
2717 MOV32ItoR(EDX, iRegs[_Rt_].k);
2719 MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
2721 SHL32CLtoR(EDX); // _rRt_ << SWR_SHIFT[shift]
2723 OR32RtoR (EAX, EDX);
2726 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2728 MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
2729 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2734 CALLFunc((u32)psxMemWrite32);
2735 // ADD32ItoR(ESP, 8);
2745 static void recSLL() {
2749 if (IsConst(_Rt_)) {
2750 MapConst(_Rd_, iRegs[_Rt_].k << _Sa_);
2752 SLWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), _Sa_);
2756 static void recSRL() {
2760 if (IsConst(_Rt_)) {
2761 MapConst(_Rd_, iRegs[_Rt_].k >> _Sa_);
2763 SRWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), _Sa_);
2767 static void recSRA() {
2771 if (IsConst(_Rt_)) {
2772 MapConst(_Rd_, (s32)iRegs[_Rt_].k >> _Sa_);
2774 SRAWI(PutHWReg32(_Rd_), GetHWReg32(_Rt_), _Sa_);
2779 #pragma mark - shift ops -
2785 static void recSLLV() {
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);
2794 SLW(PutHWReg32(_Rd_), GetHWReg32(_Rt_), GetHWReg32(_Rs_));
2798 static void recSRLV() {
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);
2807 SRW(PutHWReg32(_Rd_), GetHWReg32(_Rt_), GetHWReg32(_Rs_));
2811 static void recSRAV() {
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);
2820 SRAW(PutHWReg32(_Rd_), GetHWReg32(_Rt_), GetHWReg32(_Rs_));
2830 static void recSYSCALL() {
2835 LIW(PutHWRegSpecial(PSXPC), pc - 4);
2836 LIW(PutHWRegSpecial(ARG1), 0x20);
2837 LIW(PutHWRegSpecial(ARG2), (branch == 1 ? 1 : 0));
2839 CALLFunc ((u32)psxException);
2845 static void recBREAK() {
2855 static void recMFHI() {
2859 if (IsConst(REG_HI)) {
2860 MapConst(_Rd_, iRegs[REG_HI].k);
2862 MapCopy(_Rd_, REG_HI);
2866 static void recMTHI() {
2869 if (IsConst(_Rs_)) {
2870 MapConst(REG_HI, iRegs[_Rs_].k);
2872 MapCopy(REG_HI, _Rs_);
2876 static void recMFLO() {
2880 if (IsConst(REG_LO)) {
2881 MapConst(_Rd_, iRegs[REG_LO].k);
2883 MapCopy(_Rd_, REG_LO);
2887 static void recMTLO() {
2890 if (IsConst(_Rs_)) {
2891 MapConst(REG_LO, iRegs[_Rs_].k);
2893 MapCopy(REG_LO, _Rs_);
2898 #pragma mark - branch ops -
2913 static void recBLTZ() {
2915 u32 bpc = _Imm_ * 4 + pc;
2918 if (IsConst(_Rs_)) {
2919 if ((s32)iRegs[_Rs_].k < 0) {
2922 iJump(pc+4); return;
2926 CMPWI(GetHWReg32(_Rs_), 0);
2937 static void recBGTZ() {
2939 u32 bpc = _Imm_ * 4 + pc;
2942 if (IsConst(_Rs_)) {
2943 if ((s32)iRegs[_Rs_].k > 0) {
2946 iJump(pc+4); return;
2950 CMPWI(GetHWReg32(_Rs_), 0);
2961 static void recBLTZAL() {
2963 u32 bpc = _Imm_ * 4 + pc;
2966 if (IsConst(_Rs_)) {
2967 if ((s32)iRegs[_Rs_].k < 0) {
2968 MapConst(31, pc + 4);
2972 iJump(pc+4); return;
2976 CMPWI(GetHWReg32(_Rs_), 0);
2983 MapConst(31, pc + 4);
2989 static void recBGEZAL() {
2990 // Branch if Rs >= 0
2991 u32 bpc = _Imm_ * 4 + pc;
2994 if (IsConst(_Rs_)) {
2995 if ((s32)iRegs[_Rs_].k >= 0) {
2996 MapConst(31, pc + 4);
3000 iJump(pc+4); return;
3004 CMPWI(GetHWReg32(_Rs_), 0);
3011 MapConst(31, pc + 4);
3017 static void recJ() {
3020 iJump(_Target_ * 4 + (pc & 0xf0000000));
3023 static void recJAL() {
3025 MapConst(31, pc + 4);
3027 iJump(_Target_ * 4 + (pc & 0xf0000000));
3030 static void recJR() {
3033 if (IsConst(_Rs_)) {
3034 iJump(iRegs[_Rs_].k);
3035 //LIW(PutHWRegSpecial(TARGET), iRegs[_Rs_].k);
3037 MR(PutHWRegSpecial(TARGET), GetHWReg32(_Rs_));
3042 static void recJALR() {
3046 MapConst(_Rd_, pc + 4);
3049 if (IsConst(_Rs_)) {
3050 iJump(iRegs[_Rs_].k);
3051 //LIW(PutHWRegSpecial(TARGET), iRegs[_Rs_].k);
3053 MR(PutHWRegSpecial(TARGET), GetHWReg32(_Rs_));
3058 static void recBEQ() {
3059 // Branch if Rs == Rt
3060 u32 bpc = _Imm_ * 4 + pc;
3067 if (IsConst(_Rs_) && IsConst(_Rt_)) {
3068 if (iRegs[_Rs_].k == iRegs[_Rt_].k) {
3071 iJump(pc+4); return;
3074 else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
3075 if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) {
3076 CMPLWI(GetHWReg32(_Rt_), iRegs[_Rs_].k);
3078 else if ((s32)(s16)iRegs[_Rs_].k == (s32)iRegs[_Rs_].k) {
3079 CMPWI(GetHWReg32(_Rt_), iRegs[_Rs_].k);
3082 CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
3085 else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
3086 if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) {
3087 CMPLWI(GetHWReg32(_Rs_), iRegs[_Rt_].k);
3089 else if ((s32)(s16)iRegs[_Rt_].k == (s32)iRegs[_Rt_].k) {
3090 CMPWI(GetHWReg32(_Rs_), iRegs[_Rt_].k);
3093 CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
3097 CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
3111 static void recBNE() {
3112 // Branch if Rs != Rt
3113 u32 bpc = _Imm_ * 4 + pc;
3120 if (IsConst(_Rs_) && IsConst(_Rt_)) {
3121 if (iRegs[_Rs_].k != iRegs[_Rt_].k) {
3124 iJump(pc+4); return;
3127 else if (IsConst(_Rs_) && !IsMapped(_Rs_)) {
3128 if ((iRegs[_Rs_].k & 0xffff) == iRegs[_Rs_].k) {
3129 CMPLWI(GetHWReg32(_Rt_), iRegs[_Rs_].k);
3131 else if ((s32)(s16)iRegs[_Rs_].k == (s32)iRegs[_Rs_].k) {
3132 CMPWI(GetHWReg32(_Rt_), iRegs[_Rs_].k);
3135 CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
3138 else if (IsConst(_Rt_) && !IsMapped(_Rt_)) {
3139 if ((iRegs[_Rt_].k & 0xffff) == iRegs[_Rt_].k) {
3140 CMPLWI(GetHWReg32(_Rs_), iRegs[_Rt_].k);
3142 else if ((s32)(s16)iRegs[_Rt_].k == (s32)iRegs[_Rt_].k) {
3143 CMPWI(GetHWReg32(_Rs_), iRegs[_Rt_].k);
3146 CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
3150 CMPLW(GetHWReg32(_Rs_), GetHWReg32(_Rt_));
3164 static void recBLEZ() {
3165 // Branch if Rs <= 0
3166 u32 bpc = _Imm_ * 4 + pc;
3169 if (IsConst(_Rs_)) {
3170 if ((s32)iRegs[_Rs_].k <= 0) {
3173 iJump(pc+4); return;
3177 CMPWI(GetHWReg32(_Rs_), 0);
3188 static void recBGEZ() {
3189 // Branch if Rs >= 0
3190 u32 bpc = _Imm_ * 4 + pc;
3193 if (IsConst(_Rs_)) {
3194 if ((s32)iRegs[_Rs_].k >= 0) {
3197 iJump(pc+4); return;
3201 CMPWI(GetHWReg32(_Rs_), 0);
3220 static void recMFC0() {
3224 LWZ(PutHWReg32(_Rt_), OFFSET(&psxRegs, &psxRegs.CP0.r[_Rd_]), GetHWRegSpecial(PSXREGS));
3227 static void recCFC0() {
3233 static void recMTC0() {
3236 /*if (IsConst(_Rt_)) {
3239 MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k);
3242 MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k & ~(0xfc00));
3245 MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k);
3251 RLWINM(0,GetHWReg32(_Rt_),0,22,15); // & ~(0xfc00)
3252 STW(0, OFFSET(&psxRegs, &psxRegs.CP0.r[_Rd_]), GetHWRegSpecial(PSXREGS));
3255 STW(GetHWReg32(_Rt_), OFFSET(&psxRegs, &psxRegs.CP0.r[_Rd_]), GetHWRegSpecial(PSXREGS));
3260 if (_Rd_ == 12 || _Rd_ == 13) {
3262 LIW(PutHWRegSpecial(PSXPC), (u32)pc);
3264 CALLFunc((u32)psxTestSWInts);
3266 LWZ(0, OFFSET(&psxRegs, &psxRegs.interrupt), GetHWRegSpecial(PSXREGS));
3268 STW(0, OFFSET(&psxRegs, &psxRegs.interrupt), GetHWRegSpecial(PSXREGS));
3275 static void recCTC0() {
3281 static 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);
3287 MOV32MtoR(EAX, (u32)&psxRegs.CP0.n.Status);
3288 MOV32RtoR(ECX, EAX);
3289 AND32ItoR(EAX, 0xfffffff0);
3290 AND32ItoR(ECX, 0x3c);
3292 OR32RtoR (EAX, ECX);
3293 MOV32RtoM((u32)&psxRegs.CP0.n.Status, EAX);
3294 CALLFunc((u32)psxExceptionTest);
3299 #define CP2_FUNC(f) \
3301 static void rec##f() { \
3303 LIW(0, (u32)psxRegs.code); \
3304 STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \
3306 CALLFunc ((u32)gte##f); \
3316 static void recHLE() {
3320 if ((psxRegs.code & 0x3ffffff) == (psxRegs.code & 0x7)) {
3321 CALLFunc((u32)psxHLEt[psxRegs.code & 0x7]);
3323 // somebody else must have written to current opcode for this to happen!!!!
3324 CALLFunc((u32)psxHLEt[0]); // call dummy function
3327 count = (idlecyclecount + (pc - pcold) / 4 + 20) * BIAS;
3328 ADDI(PutHWRegSpecial(CYCLECOUNT), GetHWRegSpecial(CYCLECOUNT), count);
3330 CALLFunc((u32)psxBranchTest);
3338 static 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
3349 static 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
3360 static 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
3367 static 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
3374 static 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
3385 static 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
3392 static void recRecompile() {
3393 //static int recCount = 0;
3401 // initialize state variables
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];
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;
3414 HWRegisters[1].usage = HWUSAGE_SPECIAL | HWUSAGE_RESERVED | HWUSAGE_HARDWIRED;
3415 HWRegisters[1].private = PSXMEM;
3416 HWRegisters[1].k = (u32)&psxM;
3418 // reserve the special psxRegs.cycle register
3419 //HWRegisters[1].usage = HWUSAGE_SPECIAL | HWUSAGE_RESERVED | HWUSAGE_HARDWIRED;
3420 //HWRegisters[1].private = CYCLECOUNT;
3422 //memset(iRegs, 0, sizeof(iRegs));
3423 for (i=0; i<NUM_REGISTERS; i++) {
3424 iRegs[i].state = ST_UNK;
3428 iRegs[0].state = ST_CONST;
3430 /* if ppcPtr reached the mem limit reset whole mem */
3431 if (((u32)ppcPtr - (u32)recMem) >= (RECMEM_SIZE - 0x10000))
3437 // give us write access
3438 //mprotect(recMem, RECMEM_SIZE, PROT_EXEC|PROT_READ|PROT_WRITE);
3440 // tell the LUT where to find us
3441 PC_REC32(psxRegs.pc) = (u32)ppcPtr;
3443 pcold = pc = psxRegs.pc;
3445 //SysPrintf("RecCount: %i\n", recCount++);
3447 for (count=0; count<500;) {
3448 p = (char *)PSXM(pc);
3449 if (p == NULL) recError();
3450 psxRegs.code = SWAP32(*(u32 *)p);
3452 if ((psxRegs.code >> 26) == 0x23) { // LW
3457 p = (char *)PSXM(pc+i*4);
3458 if (p == NULL) recError();
3461 if ((code >> 26) != 0x23 ||
3462 _fRs_(code) != _Rs_ ||
3463 _fImm_(code) != (_Imm_+i*4))
3468 pc = pc + i*4; continue;
3472 if ((psxRegs.code >> 26) == 0x2b) { // SW
3477 p = (char *)PSXM(pc+i*4);
3478 if (p == NULL) recError();
3481 if ((code >> 26) != 0x2b ||
3482 _fRs_(code) != _Rs_ ||
3483 _fImm_(code) != (_Imm_+i*4))
3488 pc = pc + i*4; continue;
3493 // iFlushRegs(0); // test
3494 recBSC[psxRegs.code>>26]();
3498 //if (dump) iDumpBlock(ptr);
3505 LIW(PutHWRegSpecial(PSXPC), pc);
3511 MakeDataExecutable(ptr, ((u8*)ppcPtr)-((u8*)ptr));
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));
3519 __asm__ __volatile__("sync");
3520 __asm__ __volatile__("isync");
3524 sprintf((char *)ppcPtr, "PC=%08x", pcold);
3525 ppcPtr += strlen((char *)ppcPtr);
3528 //mprotect(recMem, RECMEM_SIZE, PROT_EXEC|PROT_READ/*|PROT_WRITE*/);
3532 R3000Acpu psxRec = {