/*************************************************************************** * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ /* * i386 assembly functions for R3000A core. */ #ifdef __x86_64__ #include "ix86-64.h" #include "../r3000a.h" #include "../psxhle.h" #include "../pgxp_cpu.h" #include "../pgxp_gte.h" #include "../pgxp_debug.h" #include #ifndef MAP_ANONYMOUS #define MAP_ANONYMOUS MAP_ANON #endif uptr* psxRecLUT; #define PTRMULT (sizeof(uptr) / sizeof(u32)) #undef PC_REC #undef PC_REC8 #undef PC_REC16 #undef PC_REC32 #define PC_REC(x) (psxRecLUT[(x) >> 16] + PTRMULT * ((x) & 0xffff)) #define PC_RECP(x) (*(uptr *)PC_REC(x)) #define RECMEM_SIZE (PTRMULT * 8 * 1024 * 1024) static char *recMem; /* the recompiled blocks will be here */ static char *recRAM; /* and the ptr to the blocks here */ static char *recROM; /* and here */ static u32 pc; /* recompiler pc */ static u32 pcold; /* recompiler oldpc */ static int count; /* recompiler intruction count */ static int branch; /* set for branch */ static u32 target; /* branch target */ static u32 resp; typedef struct { int state; u32 k; int reg; } iRegisters; static iRegisters iRegs[32]; static iRegisters iRegsS[32]; static psxRegisters psxRegsS; #define ST_UNK 0 #define ST_CONST 1 #define ST_MAPPED 2 #define IsConst(reg) (iRegs[reg].state == ST_CONST) #define IsMapped(reg) (iRegs[reg].state == ST_MAPPED) static void (*recBSC[64])(); static void (*recSPC[64])(); static void (*recREG[32])(); static void (*recCP0[32])(); static void (*recCP2[64])(); static void (*recCP2BSC[32])(); /// PGXP function tables static void(*pgxpRecBSC[64])(); static void(*pgxpRecSPC[64])(); static void(*pgxpRecCP0[32])(); static void(*pgxpRecCP2BSC[32])(); static void(*pgxpRecBSCMem[64])(); /// static void(**pRecBSC)() = recBSC; static void(**pRecSPC)() = recSPC; static void(**pRecREG)() = recREG; static void(**pRecCP0)() = recCP0; static void(**pRecCP2)() = recCP2; static void(**pRecCP2BSC)() = recCP2BSC; static void recReset(); static void recSetPGXPMode(u32 pgxpMode) { switch (pgxpMode) { case 0: //PGXP_MODE_DISABLED: pRecBSC = recBSC; pRecSPC = recSPC; pRecREG = recREG; pRecCP0 = recCP0; pRecCP2 = recCP2; pRecCP2BSC = recCP2BSC; break; case 1: //PGXP_MODE_MEM: pRecBSC = pgxpRecBSCMem; pRecSPC = recSPC; pRecREG = recREG; pRecCP0 = pgxpRecCP0; pRecCP2 = recCP2; pRecCP2BSC = pgxpRecCP2BSC; break; case 2: //PGXP_MODE_FULL: pRecBSC = pgxpRecBSC; pRecSPC = pgxpRecSPC; pRecREG = recREG; pRecCP0 = pgxpRecCP0; pRecCP2 = recCP2; pRecCP2BSC = pgxpRecCP2BSC; break; } // set interpreter mode too psxInt.SetPGXPMode(pgxpMode); // reset to ensure new func tables are used recReset(); } #define STACKSIZE 0x18 static void StackRes() { #ifdef __x86_64__ ADD64ItoR(RSP, STACKSIZE); #else if (resp) ADD32ItoR(ESP, resp); #endif } int dump = FALSE; static void MapConst(int reg, u32 _const) { iRegs[reg].k = _const; iRegs[reg].state = ST_CONST; } static void iFlushReg(int reg) { if (IsConst(reg)) { MOV32ItoM((uptr)&psxRegs.GPR.r[reg], iRegs[reg].k); } iRegs[reg].state = ST_UNK; } static inline void iDump(const iRegisters* iRegsParam) { #ifdef PSXCPU_LOG int i; for (i=0; i<32; i++) { psxRegsS.GPR.r[i] = psxRegs.GPR.r[i]; if (iRegsParam[i].state != ST_UNK) psxRegs.GPR.r[i] = iRegsParam[i].k; } PSXCPU_LOG("%s\n", disR3000AF(PSXMu32(pc), pc)); // PSXCPU_LOG("%s (%x %x)\n", disR3000AF(PSXMu32(pc), pc), iRegsParam[_Rt_].k, psxRegs.GPR.r[_Rt_]); for (i=0; i<32; i++) { psxRegs.GPR.r[i] = psxRegsS.GPR.r[i]; } #endif } static void iFlushRegs() { int i; for (i=1; i<32; i++) { iFlushReg(i); } } static void iStoreCycle() { count = ((pc - pcold) / 4) * BIAS; ADD32ItoM((uptr)&psxRegs.cycle, count); } static void iRet() { iStoreCycle(); StackRes(); RET(); } static int iLoadTest() { u32 tmp; // check for load delay tmp = psxRegs.code >> 26; switch (tmp) { case 0x10: // COP0 switch (_Rs_) { case 0x00: // MFC0 case 0x02: // CFC0 return 1; } break; case 0x12: // COP2 switch (_Funct_) { case 0x00: switch (_Rs_) { case 0x00: // MFC2 case 0x02: // CFC2 return 1; } break; } break; case 0x32: // LWC2 return 1; default: if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR return 1; } break; } return 0; } /* set a pending branch */ static void SetBranch() { branch = 1; psxRegs.code = PSXMu32(pc); #ifdef PSXCPU_LOG if (dump) iDump(iRegsS); #endif pc+=4; if (iLoadTest() == 1) { iFlushRegs(); MOV32ItoM((uptr)&psxRegs.code, psxRegs.code); /* store cycle */ count = ((pc - pcold) / 4) * BIAS; ADD32ItoM((uptr)&psxRegs.cycle, count); //PUSH64M((uptr)&target); MOV32MtoR(X86ARG2, (uptr)&target); //PUSHI(_Rt_); MOV64ItoR(X86ARG1, _Rt_); CALLFunc((uptr)psxDelayTest); StackRes(); RET(); return; } switch( psxRegs.code >> 26 ) { // Lode Runner (jr - beq) // bltz - bgez - bltzal - bgezal / beq - bne - blez - bgtz case 0x01: case 0x04: case 0x05: case 0x06: case 0x07: break; default: pRecBSC[psxRegs.code>>26](); break; } iFlushRegs(); iStoreCycle(); MOV32MtoR(EAX, (uptr)&target); MOV32RtoM((uptr)&psxRegs.pc, EAX); CALLFunc((uptr)psxBranchTest); CALLFunc((uptr)psxJumpTest); StackRes(); RET(); } static void iJump(u32 branchPC) { branch = 1; psxRegs.code = PSXMu32(pc); #ifdef PSXCPU_LOG if (dump) iDump(iRegsS); #endif pc+=4; if (iLoadTest() == 1) { iFlushRegs(); MOV32ItoM((uptr)&psxRegs.code, psxRegs.code); /* store cycle */ count = ((pc - pcold) / 4) * BIAS; ADD32ItoM((uptr)&psxRegs.cycle, count); //PUSHI(branchPC); MOV64ItoR(X86ARG2, branchPC); //PUSHI(_Rt_); MOV64ItoR(X86ARG1, _Rt_); CALLFunc((uptr)psxDelayTest); //ADD32ItoR(ESP, 2*8); StackRes(); RET(); return; } pRecBSC[psxRegs.code>>26](); iFlushRegs(); iStoreCycle(); MOV32ItoM((uptr)&psxRegs.pc, branchPC); CALLFunc((uptr)psxBranchTest); CALLFunc((uptr)psxJumpTest); StackRes(); RET(); //* XXX? // maybe just happened an interruption, check so CMP32ItoM((uptr)&psxRegs.pc, branchPC); j8Ptr[0] = JE8(0); RET(); x86SetJ8(j8Ptr[0]); MOV64MtoR(RAX, PC_REC(branchPC)); TEST64RtoR(RAX,RAX); j8Ptr[1] = JNE8(0); RET(); x86SetJ8(j8Ptr[1]); RET(); //JMP32R(EAX); JMPR(EAX); //*/ } static void iBranch(u32 branchPC, int savectx) { u32 respold=0; if (savectx) { respold = resp; memcpy(iRegsS, iRegs, sizeof(iRegs)); } branch = 1; psxRegs.code = PSXMu32(pc); #ifdef PSXCPU_LOG if (dump && savectx) iDump(iRegsS); #endif // the delay test is only made when the branch is taken // savectx == 0 will mean that :) if (savectx == 0 && iLoadTest() == 1) { iFlushRegs(); MOV32ItoM((uptr)&psxRegs.code, psxRegs.code); /* store cycle */ count = (((pc+4) - pcold) / 4) * BIAS; ADD32ItoM((uptr)&psxRegs.cycle, count); //if (resp) ADD32ItoR(ESP, resp); //PUSHI(branchPC); MOV64ItoR(X86ARG2, branchPC); //PUSHI(_Rt_); MOV64ItoR(X86ARG1,_Rt_); CALLFunc((uptr)psxDelayTest); StackRes(); RET(); return; } pc+= 4; pRecBSC[psxRegs.code>>26](); iFlushRegs(); iStoreCycle(); MOV32ItoM((uptr)&psxRegs.pc, branchPC); CALLFunc((uptr)psxBranchTest); CALLFunc((uptr)psxJumpTest); StackRes(); // maybe just happened an interruption, check so CMP32ItoM((uptr)&psxRegs.pc, branchPC); j8Ptr[1] = JE8(0); RET(); x86SetJ8(j8Ptr[1]); MOV64MtoR(RAX, PC_REC(branchPC)); TEST64RtoR(RAX, RAX); j8Ptr[2] = JNE8(0); RET(); x86SetJ8(j8Ptr[2]); //JMP32R(EAX); JMPR(EAX); pc-= 4; if (savectx) { resp = respold; memcpy(iRegs, iRegsS, sizeof(iRegs)); } } char *txt0 = "EAX = %x : ECX = %x : EDX = %x\n"; char *txt1 = "EAX = %x\n"; char *txt2 = "M32 = %x\n"; /* void iLogX86() { PUSHA32(); PUSH32R (EDX); PUSH32R (ECX); PUSH32R (EAX); PUSH32M ((uptr)&txt0); CALLFunc((uptr)SysPrintf); ADD32ItoR(ESP, 4*4); POPA32(); } */ void iLogEAX() { PUSH64R (EAX); PUSH64M ((uptr)&txt1); CALLFunc((uptr)SysPrintf); ADD32ItoR(ESP, 8*2); } void iLogM32(u32 mem) { PUSH64M (mem); PUSH64M ((uptr)&txt2); CALLFunc((uptr)SysPrintf); ADD32ItoR(ESP, 8*2); } #if 0 static void iDumpRegs() { int i, j; printf("%x %x\n", psxRegs.pc, psxRegs.cycle); for (i = 0; i < 4; i++) { for (j = 0; j < 8; j++) printf("%x ", psxRegs.GPR.r[j*i]); printf("\n"); } } #endif void iDumpBlock(char *ptr) { #ifdef PSXCPU_LOG u32 i; for (i = psxRegs.pc; i < pc; i+=4) PSXCPU_LOG("%s\n", disR3000AF(PSXMu32(i), i)); #endif #ifdef PSXCPUDUMP_LOG FILE *f; f = fopen("dump1", "w"); fwrite(ptr, 1, (uptr)x86Ptr - (uptr)ptr, f); fclose(f); //system("ndisasm -b64 dump1"); #endif } #define REC_FUNC(f) \ void psx##f(); \ static void rec##f() { \ iFlushRegs(); \ MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); \ MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); \ CALLFunc((uptr)psx##f); \ /* branch = 2; */\ } #define REC_SYS(f) \ void psx##f(); \ static void rec##f() { \ iFlushRegs(); \ MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); \ MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); \ CALLFunc((uptr)psx##f); \ branch = 2; \ iRet(); \ } #define REC_BRANCH(f) \ void psx##f(); \ static void rec##f() { \ iFlushRegs(); \ MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); \ MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); \ CALLFunc((uptr)psx##f); \ branch = 2; \ iRet(); \ } static void recRecompile(); static int recInit() { int i; psxRecLUT = (uptr*) malloc(0x010000 * sizeof(uptr)); recMem = mmap(0, RECMEM_SIZE + PTRMULT*0x1000, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); recRAM = mmap(0, 0x280000*PTRMULT, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); recROM = &recRAM[0x200000*PTRMULT]; if (recRAM == NULL || recROM == NULL || recMem == NULL || psxRecLUT == NULL) { SysMessage("Error allocating memory"); return -1; } memset(recMem, 0, RECMEM_SIZE); memset(recRAM, 0, 0x200000 * PTRMULT); memset(recROM, 0, 0x080000 * PTRMULT); for (i=0; i<0x80; i++) psxRecLUT[i + 0x0000] = (uptr)&recRAM[PTRMULT*((i & 0x1f) << 16)]; memcpy(psxRecLUT + 0x8000, psxRecLUT, 0x80 * sizeof(uptr)); memcpy(psxRecLUT + 0xa000, psxRecLUT, 0x80 * sizeof(uptr)); for (i=0; i<0x08; i++) psxRecLUT[i + 0xbfc0] = (uptr)&recROM[PTRMULT*(i << 16)]; //x86Init(); cpudetectInit(); return 0; } static void recReset() { memset(recRAM, 0, 0x200000 * PTRMULT); memset(recROM, 0, 0x080000 * PTRMULT); x86SetPtr(recMem); branch = 0; memset(iRegs, 0, sizeof(iRegs)); iRegs[0].state = ST_CONST; iRegs[0].k = 0; } static void recShutdown() { if (recMem == NULL) return; free(psxRecLUT); munmap(recMem, RECMEM_SIZE + PTRMULT*0x1000); munmap(recRAM, 0x280000*PTRMULT); x86Shutdown(); } static void recError() { SysReset(); ClosePlugins(); SysMessage("Unrecoverable error while running recompiler\n"); SysRunGui(); } /*__inline*/ static void execute() { void (*recFunc)(); uptr *p; p = (uptr *)PC_REC(psxRegs.pc); // if (!p) { recError(); return; } if (*p == 0) { recRecompile(); } else if (psxRegs.ICache_valid == FALSE) { // Xenogears: fixes memory card access with original BIOS (0a_44_FlushCache issue) //psxCpu->Clear(0x0, 0x20000); memset(recRAM, 0, 0x10000 * PTRMULT); recRecompile(); p = (uptr *)PC_REC(psxRegs.pc); psxRegs.ICache_valid = TRUE; } if (*p < (uptr)recMem || *p >= (uptr)recMem + RECMEM_SIZE) { recError(); return; } recFunc = (void (*)())*p; (*recFunc)(); } static void recExecute() { for (;;) execute(); } static void recExecuteBlock() { execute(); } static void recClear(u32 Addr, u32 Size) { memset((void *)PC_REC(Addr), 0, Size * sizeof(uptr)); } static void recNULL() { // SysMessage("recUNK: %8.8x\n", psxRegs.code); } /********************************************************* * goes to opcodes tables... * * Format: table[something....] * *********************************************************/ //REC_SYS(SPECIAL); #if 1 static void recSPECIAL() { pRecSPC[_Funct_](); } #endif static void recREGIMM() { pRecREG[_Rt_](); } static void recCOP0() { pRecCP0[_Rs_](); } //REC_SYS(COP2); #if 1 static void recCOP2() { MOV32MtoR(EAX, (uptr)&psxRegs.CP0.n.Status); AND32ItoR(EAX, 0x40000000); j32Ptr[31] = JZ32(0); pRecCP2[_Funct_](); x86SetJ32(j32Ptr[31]); } #endif static void recBASIC() { pRecCP2BSC[_Rs_](); } //end of Tables opcodes... /********************************************************* * Arithmetic with immediate operand * * Format: OP rt, rs, immediate * *********************************************************/ #if 0 REC_FUNC(ADDI); REC_FUNC(ADDIU); REC_FUNC(ANDI); REC_FUNC(ORI); REC_FUNC(XORI); REC_FUNC(SLTI); REC_FUNC(SLTIU); #endif #if 1 static void recADDIU() { // Rt = Rs + Im if (!_Rt_) return; // iFlushRegs(); if (_Rs_ == _Rt_) { if (IsConst(_Rt_)) { iRegs[_Rt_].k+= _Imm_; } else { if (_Imm_ == 1) { INC32M((uptr)&psxRegs.GPR.r[_Rt_]); } else if (_Imm_ == -1) { DEC32M((uptr)&psxRegs.GPR.r[_Rt_]); } else if (_Imm_) { ADD32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _Imm_); } } } else { if (IsConst(_Rs_)) { MapConst(_Rt_, iRegs[_Rs_].k + _Imm_); } else { iRegs[_Rt_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); if (_Imm_ == 1) { INC32R(EAX); } else if (_Imm_ == -1) { DEC32R(EAX); } else if (_Imm_) { ADD32ItoR(EAX, _Imm_); } MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); } } } static void recADDI() { // Rt = Rs + Im recADDIU(); } static void recSLTI() { // Rt = Rs < Im (signed) if (!_Rt_) return; // iFlushRegs(); if (IsConst(_Rs_)) { MapConst(_Rt_, (s32)iRegs[_Rs_].k < _Imm_); } else { iRegs[_Rt_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); CMP32ItoR(EAX, _Imm_); SETL8R (EAX); AND32ItoR(EAX, 0xff); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); } } static void recSLTIU() { // Rt = Rs < Im (unsigned) if (!_Rt_) return; // iFlushRegs(); if (IsConst(_Rs_)) { MapConst(_Rt_, iRegs[_Rs_].k < _ImmU_); } else { iRegs[_Rt_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); CMP32ItoR(EAX, _Imm_); SETB8R (EAX); AND32ItoR(EAX, 0xff); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); } } static void recANDI() { // Rt = Rs And Im if (!_Rt_) return; // iFlushRegs(); if (_Rs_ == _Rt_) { if (IsConst(_Rt_)) { iRegs[_Rt_].k&= _ImmU_; } else { AND32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _ImmU_); } } else { if (IsConst(_Rs_)) { MapConst(_Rt_, iRegs[_Rs_].k & _ImmU_); } else { iRegs[_Rt_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); AND32ItoR(EAX, _ImmU_); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); } } } static void recORI() { // Rt = Rs Or Im if (!_Rt_) return; // iFlushRegs(); if (_Rs_ == _Rt_) { if (IsConst(_Rt_)) { iRegs[_Rt_].k|= _ImmU_; } else { OR32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _ImmU_); } } else { if (IsConst(_Rs_)) { MapConst(_Rt_, iRegs[_Rs_].k | _ImmU_); } else { iRegs[_Rt_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); if (_ImmU_) OR32ItoR (EAX, _ImmU_); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); } } } static void recXORI() { // Rt = Rs Xor Im if (!_Rt_) return; // iFlushRegs(); if (_Rs_ == _Rt_) { if (IsConst(_Rt_)) { iRegs[_Rt_].k^= _ImmU_; } else { XOR32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _ImmU_); } } else { if (IsConst(_Rs_)) { MapConst(_Rt_, iRegs[_Rs_].k ^ _ImmU_); } else { iRegs[_Rt_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); XOR32ItoR(EAX, _ImmU_); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); } } } #endif //end of * Arithmetic with immediate operand /********************************************************* * Load higher 16 bits of the first word in GPR with imm * * Format: OP rt, immediate * *********************************************************/ //REC_FUNC(LUI); #if 1 static void recLUI() { // Rt = Imm << 16 if (!_Rt_) return; //iFlushReg(_Rt_); MapConst(_Rt_, _ImmLU_); } #endif //End of Load Higher ..... /********************************************************* * Register arithmetic * * Format: OP rd, rs, rt * *********************************************************/ #if 0 REC_FUNC(ADD); REC_FUNC(ADDU); REC_FUNC(SUB); REC_FUNC(SUBU); REC_FUNC(AND); REC_FUNC(OR); REC_FUNC(XOR); REC_FUNC(NOR); REC_FUNC(SLT); REC_FUNC(SLTU); #endif #if 1 static void recADDU() { // Rd = Rs + Rt if (!_Rd_) return; // iFlushRegs(); if (IsConst(_Rs_) && IsConst(_Rt_)) { MapConst(_Rd_, iRegs[_Rs_].k + iRegs[_Rt_].k); } else if (IsConst(_Rs_)) { iRegs[_Rd_].state = ST_UNK; if (_Rt_ == _Rd_) { if (iRegs[_Rs_].k == 1) { INC32M((uptr)&psxRegs.GPR.r[_Rd_]); } else if (iRegs[_Rs_].k == -1) { DEC32M((uptr)&psxRegs.GPR.r[_Rd_]); } else if (iRegs[_Rs_].k) { ADD32ItoM((uptr)&psxRegs.GPR.r[_Rd_], iRegs[_Rs_].k); } } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); if (iRegs[_Rs_].k == 1) { INC32R(EAX); } else if (iRegs[_Rs_].k == 0xffffffff) { DEC32R(EAX); } else if (iRegs[_Rs_].k) { ADD32ItoR(EAX, iRegs[_Rs_].k); } MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } else if (IsConst(_Rt_)) { iRegs[_Rd_].state = ST_UNK; if (_Rs_ == _Rd_) { if (iRegs[_Rt_].k == 1) { INC32M((uptr)&psxRegs.GPR.r[_Rd_]); } else if (iRegs[_Rt_].k == -1) { DEC32M((uptr)&psxRegs.GPR.r[_Rd_]); } else if (iRegs[_Rt_].k) { ADD32ItoM((uptr)&psxRegs.GPR.r[_Rd_], iRegs[_Rt_].k); } } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); if (iRegs[_Rt_].k == 1) { INC32R(EAX); } else if (iRegs[_Rt_].k == 0xffffffff) { DEC32R(EAX); } else if (iRegs[_Rt_].k) { ADD32ItoR(EAX, iRegs[_Rt_].k); } MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } else { iRegs[_Rd_].state = ST_UNK; if (_Rs_ == _Rd_) { // Rd+= Rt MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); ADD32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else if (_Rt_ == _Rd_) { // Rd+= Rs MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); ADD32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else { // Rd = Rs + Rt MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); ADD32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } } static void recADD() { // Rd = Rs + Rt recADDU(); } static void recSUBU() { // Rd = Rs - Rt if (!_Rd_) return; // iFlushRegs(); if (IsConst(_Rs_) && IsConst(_Rt_)) { MapConst(_Rd_, iRegs[_Rs_].k - iRegs[_Rt_].k); } else if (IsConst(_Rs_)) { iRegs[_Rd_].state = ST_UNK; MOV32ItoR(EAX, iRegs[_Rs_].k); SUB32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else if (IsConst(_Rt_)) { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); SUB32ItoR(EAX, iRegs[_Rt_].k); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); SUB32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } static void recSUB() { // Rd = Rs - Rt recSUBU(); } static void recAND() { // Rd = Rs And Rt if (!_Rd_) return; // iFlushRegs(); if (IsConst(_Rs_) && IsConst(_Rt_)) { MapConst(_Rd_, iRegs[_Rs_].k & iRegs[_Rt_].k); } else if (IsConst(_Rs_)) { iRegs[_Rd_].state = ST_UNK; if (_Rd_ == _Rt_) { // Rd&= Rs AND32ItoM((uptr)&psxRegs.GPR.r[_Rd_], iRegs[_Rs_].k); } else { MOV32ItoR(EAX, iRegs[_Rs_].k); AND32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } else if (IsConst(_Rt_)) { iRegs[_Rd_].state = ST_UNK; if (_Rd_ == _Rs_) { // Rd&= kRt AND32ItoM((uptr)&psxRegs.GPR.r[_Rd_], iRegs[_Rt_].k); } else { // Rd = Rs & kRt MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); AND32ItoR(EAX, iRegs[_Rt_].k); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } else { iRegs[_Rd_].state = ST_UNK; if (_Rs_ == _Rd_) { // Rd&= Rt MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); AND32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else if (_Rt_ == _Rd_) { // Rd&= Rs MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); AND32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else { // Rd = Rs & Rt MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); AND32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } } static void recOR() { // Rd = Rs Or Rt if (!_Rd_) return; // iFlushRegs(); if (IsConst(_Rs_) && IsConst(_Rt_)) { MapConst(_Rd_, iRegs[_Rs_].k | iRegs[_Rt_].k); } else if (IsConst(_Rs_)) { iRegs[_Rd_].state = ST_UNK; MOV32ItoR(EAX, iRegs[_Rs_].k); OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else if (IsConst(_Rt_)) { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); OR32ItoR (EAX, iRegs[_Rt_].k); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } static void recXOR() { // Rd = Rs Xor Rt if (!_Rd_) return; // iFlushRegs(); if (IsConst(_Rs_) && IsConst(_Rt_)) { MapConst(_Rd_, iRegs[_Rs_].k ^ iRegs[_Rt_].k); } else if (IsConst(_Rs_)) { iRegs[_Rd_].state = ST_UNK; MOV32ItoR(EAX, iRegs[_Rs_].k); XOR32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else if (IsConst(_Rt_)) { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); XOR32ItoR(EAX, iRegs[_Rt_].k); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); XOR32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } static void recNOR() { // Rd = Rs Nor Rt if (!_Rd_) return; // iFlushRegs(); if (IsConst(_Rs_) && IsConst(_Rt_)) { MapConst(_Rd_, ~(iRegs[_Rs_].k | iRegs[_Rt_].k)); } else if (IsConst(_Rs_)) { iRegs[_Rd_].state = ST_UNK; MOV32ItoR(EAX, iRegs[_Rs_].k); OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]); NOT32R (EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else if (IsConst(_Rt_)) { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); OR32ItoR (EAX, iRegs[_Rt_].k); NOT32R (EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]); NOT32R (EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } static void recSLT() { // Rd = Rs < Rt (signed) if (!_Rd_) return; // iFlushRegs(); if (IsConst(_Rs_) && IsConst(_Rt_)) { MapConst(_Rd_, (s32)iRegs[_Rs_].k < (s32)iRegs[_Rt_].k); } else if (IsConst(_Rs_)) { iRegs[_Rd_].state = ST_UNK; MOV32ItoR(EAX, iRegs[_Rs_].k); CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); SETL8R (EAX); AND32ItoR(EAX, 0xff); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else if (IsConst(_Rt_)) { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); CMP32ItoR(EAX, iRegs[_Rt_].k); SETL8R (EAX); AND32ItoR(EAX, 0xff); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); SETL8R (EAX); AND32ItoR(EAX, 0xff); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } static void recSLTU() { // Rd = Rs < Rt (unsigned) if (!_Rd_) return; // iFlushRegs(); if (IsConst(_Rs_) && IsConst(_Rt_)) { MapConst(_Rd_, iRegs[_Rs_].k < iRegs[_Rt_].k); } else if (IsConst(_Rs_)) { iRegs[_Rd_].state = ST_UNK; MOV32ItoR(EAX, iRegs[_Rs_].k); CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); SBB32RtoR(EAX, EAX); NEG32R (EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else if (IsConst(_Rt_)) { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); CMP32ItoR(EAX, iRegs[_Rt_].k); SBB32RtoR(EAX, EAX); NEG32R (EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); SBB32RtoR(EAX, EAX); NEG32R (EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } #endif //End of * Register arithmetic /********************************************************* * Register mult/div & Register trap logic * * Format: OP rs, rt * *********************************************************/ #if 0 REC_FUNC(MULT); REC_FUNC(MULTU); REC_FUNC(DIV); REC_FUNC(DIVU); #endif #if 1 static void recMULT() { // Lo/Hi = Rs * Rt (signed) // iFlushRegs(); if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) || (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) { XOR32RtoR(EAX, EAX); MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); return; } if (IsConst(_Rs_)) { MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("multrsk %x\n", iRegs[_Rs_].k); } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); } if (IsConst(_Rt_)) { MOV32ItoR(EDX, iRegs[_Rt_].k);// printf("multrtk %x\n", iRegs[_Rt_].k); IMUL32R (EDX); } else { IMUL32M ((uptr)&psxRegs.GPR.r[_Rt_]); } MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); } static void recMULTU() { // Lo/Hi = Rs * Rt (unsigned) // iFlushRegs(); if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) || (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) { XOR32RtoR(EAX, EAX); MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); return; } if (IsConst(_Rs_)) { MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("multursk %x\n", iRegs[_Rs_].k); } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); } if (IsConst(_Rt_)) { MOV32ItoR(EDX, iRegs[_Rt_].k);// printf("multurtk %x\n", iRegs[_Rt_].k); MUL32R (EDX); } else { MUL32M ((uptr)&psxRegs.GPR.r[_Rt_]); } MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); } static void recDIV() { // Lo/Hi = Rs / Rt (signed) // iFlushRegs(); if (IsConst(_Rt_)) { if (iRegs[_Rt_].k == 0) { MOV32ItoM((uptr)&psxRegs.GPR.n.lo, 0xffffffff); if (IsConst(_Rs_)) { MOV32ItoM((uptr)&psxRegs.GPR.n.hi, iRegs[_Rs_].k); } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); } return; } MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divrtk %x\n", iRegs[_Rt_].k); } else { MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); CMP32ItoR(ECX, 0); j8Ptr[0] = JE8(0); } if (IsConst(_Rs_)) { MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("divrsk %x\n", iRegs[_Rs_].k); } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); } CDQ(); IDIV32R (ECX); MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); if (!IsConst(_Rt_)) { j8Ptr[1] = JMP8(1); x86SetJ8(j8Ptr[0]); MOV32ItoM((uptr)&psxRegs.GPR.n.lo, 0xffffffff); if (IsConst(_Rs_)) { MOV32ItoM((uptr)&psxRegs.GPR.n.hi, iRegs[_Rs_].k); } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); } x86SetJ8(j8Ptr[1]); } } static void recDIVU() { // Lo/Hi = Rs / Rt (unsigned) // iFlushRegs(); if (IsConst(_Rt_)) { if (iRegs[_Rt_].k == 0) { MOV32ItoM((uptr)&psxRegs.GPR.n.lo, 0xffffffff); if (IsConst(_Rs_)) { MOV32ItoM((uptr)&psxRegs.GPR.n.hi, iRegs[_Rs_].k); } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); } return; } MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divurtk %x\n", iRegs[_Rt_].k); } else { MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); CMP32ItoR(ECX, 0); j8Ptr[0] = JE8(0); } if (IsConst(_Rs_)) { MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("divursk %x\n", iRegs[_Rs_].k); } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); } XOR32RtoR(EDX, EDX); DIV32R (ECX); MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); if (!IsConst(_Rt_)) { j8Ptr[1] = JMP8(1); x86SetJ8(j8Ptr[0]); MOV32ItoM((uptr)&psxRegs.GPR.n.lo, 0xffffffff); if (IsConst(_Rs_)) { MOV32ItoM((uptr)&psxRegs.GPR.n.hi, iRegs[_Rs_].k); } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); } x86SetJ8(j8Ptr[1]); } } #endif //End of * Register mult/div & Register trap logic #if 0 REC_FUNC(LB); REC_FUNC(LBU); REC_FUNC(LH); REC_FUNC(LHU); REC_FUNC(LW); REC_FUNC(SB); REC_FUNC(SH); REC_FUNC(SW); REC_FUNC(LWL); REC_FUNC(LWR); REC_FUNC(SWL); REC_FUNC(SWR); #endif static void SetArg_OfB(x86IntRegType arg) { if (IsConst(_Rs_)) #ifdef __x86_64__ MOV64ItoR(arg, iRegs[_Rs_].k + _Imm_); #else PUSH32I (iRegs[_Rs_].k + _Imm_); #endif else { #ifdef __x86_64__ MOV32MtoR(arg, (uptr)&psxRegs.GPR.r[_Rs_]); if (_Imm_) ADD32ItoR(arg, _Imm_); #else if (_Imm_) { MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); ADD32ItoR(EAX, _Imm_); PUSH32R (EAX); } else { PUSH32M ((u32)&psxRegs.GPR.r[_Rs_]); } #endif } #ifndef __x86_64__ resp += 4; #endif } #if 1 static void recLB() { // Rt = mem[Rs + Im] (signed) // iFlushRegs(); if (IsConst(_Rs_)) { u32 addr = iRegs[_Rs_].k + _Imm_; int t = addr >> 16; if ((t & 0xfff0) == 0xbfc0) { if (!_Rt_) return; // since bios is readonly it won't change MapConst(_Rt_, psxRs8(addr)); return; } if ((t & 0x1fe0) == 0) { if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; MOVSX32M8toR(EAX, (uptr)&psxM[addr & 0x1fffff]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); return; } if (t == 0x1f80 && addr < 0x1f801000) { if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; MOVSX32M8toR(EAX, (uptr)&psxH[addr & 0xfff]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); return; } // SysPrintf("unhandled r8 %x\n", addr); } SetArg_OfB(X86ARG1); CALLFunc((uptr)psxMemRead8); if (_Rt_) { iRegs[_Rt_].state = ST_UNK; MOVSX32R8toR(EAX, EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); } // ADD32ItoR(ESP, 4); } static void recLBU() { // Rt = mem[Rs + Im] (unsigned) // iFlushRegs(); if (IsConst(_Rs_)) { u32 addr = iRegs[_Rs_].k + _Imm_; int t = addr >> 16; if ((t & 0xfff0) == 0xbfc0) { if (!_Rt_) return; // since bios is readonly it won't change MapConst(_Rt_, psxRu8(addr)); return; } if ((t & 0x1fe0) == 0) { if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; MOVZX32M8toR(EAX, (uptr)&psxM[addr & 0x1fffff]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); return; } if (t == 0x1f80 && addr < 0x1f801000) { if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; MOVZX32M8toR(EAX, (uptr)&psxH[addr & 0xfff]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); return; } // SysPrintf("unhandled r8u %x\n", addr); } SetArg_OfB(X86ARG1); CALLFunc((uptr)psxMemRead8); if (_Rt_) { iRegs[_Rt_].state = ST_UNK; MOVZX32R8toR(EAX, EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); } // ADD32ItoR(ESP, 4); } static void recLH() { // Rt = mem[Rs + Im] (signed) // iFlushRegs(); if (IsConst(_Rs_)) { u32 addr = iRegs[_Rs_].k + _Imm_; int t = addr >> 16; if ((t & 0xfff0) == 0xbfc0) { if (!_Rt_) return; // since bios is readonly it won't change MapConst(_Rt_, psxRs16(addr)); return; } if ((t & 0x1fe0) == 0) { if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; MOVSX32M16toR(EAX, (uptr)&psxM[addr & 0x1fffff]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); return; } if (t == 0x1f80 && addr < 0x1f801000) { if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; MOVSX32M16toR(EAX, (uptr)&psxH[addr & 0xfff]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); return; } // SysPrintf("unhandled r16 %x\n", addr); } SetArg_OfB(X86ARG1); CALLFunc((uptr)psxMemRead16); if (_Rt_) { iRegs[_Rt_].state = ST_UNK; MOVSX32R16toR(EAX, EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); } // ADD32ItoR(ESP, 4); } static void recLHU() { // Rt = mem[Rs + Im] (unsigned) // iFlushRegs(); if (IsConst(_Rs_)) { u32 addr = iRegs[_Rs_].k + _Imm_; int t = addr >> 16; if ((t & 0xfff0) == 0xbfc0) { if (!_Rt_) return; // since bios is readonly it won't change MapConst(_Rt_, psxRu16(addr)); return; } if ((t & 0x1fe0) == 0) { if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; MOVZX32M16toR(EAX, (uptr)&psxM[addr & 0x1fffff]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); return; } if (t == 0x1f80 && addr < 0x1f801000) { if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; MOVZX32M16toR(EAX, (uptr)&psxH[addr & 0xfff]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); return; } if (t == 0x1f80) { if (addr >= 0x1f801c00 && addr < 0x1f801e00) { if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; //PUSHI (addr); MOV64ItoR(X86ARG1, addr); //CALLFunc ((uptr)SPU_readRegister); MOV64ItoR(RAX, (uptr)SPU_readRegister); CALL64R(RAX); MOVZX32R16toR(EAX, EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); #ifndef __WIN32__ resp+= 4; #endif return; } switch (addr) { case 0x1f801100: case 0x1f801110: case 0x1f801120: if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; //PUSHI((addr >> 4) & 0x3); MOV64ItoR(X86ARG1, (addr >> 4) & 0x3); CALLFunc((uptr)psxRcntRcount); MOVZX32R16toR(EAX, EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); resp+= 4; return; case 0x1f801104: case 0x1f801114: case 0x1f801124: if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; MOV64ItoR(X86ARG1, (addr >> 4) & 0x3); CALLFunc((uptr)psxRcntRmode); MOVZX32R16toR(EAX, EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); resp+= 4; return; case 0x1f801108: case 0x1f801118: case 0x1f801128: if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; MOV64ItoR(X86ARG1, (addr >> 4) & 0x3); CALLFunc((uptr)psxRcntRtarget); MOVZX32R16toR(EAX, EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); resp+= 4; return; } } // SysPrintf("unhandled r16u %x\n", addr); } SetArg_OfB(X86ARG1); CALLFunc((uptr)psxMemRead16); if (_Rt_) { iRegs[_Rt_].state = ST_UNK; MOVZX32R16toR(EAX, EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); } // ADD32ItoR(ESP, 4); } static void recLW() { // Rt = mem[Rs + Im] (unsigned) // iFlushRegs(); if (IsConst(_Rs_)) { u32 addr = iRegs[_Rs_].k + _Imm_; int t = addr >> 16; if ((t & 0xfff0) == 0xbfc0) { if (!_Rt_) return; // since bios is readonly it won't change MapConst(_Rt_, psxRu32(addr)); return; } if ((t & 0x1fe0) == 0) { if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1fffff]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); return; } if (t == 0x1f80 && addr < 0x1f801000) { if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxH[addr & 0xfff]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); return; } if (t == 0x1f80) { switch (addr) { case 0x1f801080: case 0x1f801084: case 0x1f801088: case 0x1f801090: case 0x1f801094: case 0x1f801098: case 0x1f8010a0: case 0x1f8010a4: case 0x1f8010a8: case 0x1f8010b0: case 0x1f8010b4: case 0x1f8010b8: case 0x1f8010c0: case 0x1f8010c4: case 0x1f8010c8: case 0x1f8010d0: case 0x1f8010d4: case 0x1f8010d8: case 0x1f8010e0: case 0x1f8010e4: case 0x1f8010e8: case 0x1f801070: case 0x1f801074: case 0x1f8010f0: case 0x1f8010f4: if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffff]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); return; case 0x1f801810: if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; CALLFunc((uptr)GPU_readData); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); return; case 0x1f801814: if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; CALLFunc((uptr)GPU_readStatus); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); return; } } // SysPrintf("unhandled r32 %x\n", addr); } SetArg_OfB(X86ARG1); CALLFunc((uptr)psxMemRead32); if (_Rt_) { iRegs[_Rt_].state = ST_UNK; MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); } // ADD32ItoR(ESP, 4); // Delay is memread delay + 1 cycle. // Seems to work nicely with games that require cycle accuracy like CART World Series. // TODO: this could be needed with other L ops such as LB. if (Config.HackFix)INC32M((uptr)&psxRegs.cycle); } extern u32 LWL_MASK[4]; extern u32 LWL_SHIFT[4]; void iLWLk(u32 shift) { if (IsConst(_Rt_)) { MOV32ItoR(ECX, iRegs[_Rt_].k); } else { MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); } AND32ItoR(ECX, LWL_MASK[shift]); SHL32ItoR(EAX, LWL_SHIFT[shift]); OR32RtoR (EAX, ECX); } void recLWL() { // Rt = Rt Merge mem[Rs + Im] if (IsConst(_Rs_)) { u32 addr = iRegs[_Rs_].k + _Imm_; int t = addr >> 16; if ((t & 0x1fe0) == 0) { MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]); iLWLk(addr & 3); iRegs[_Rt_].state = ST_UNK; MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); return; } if (t == 0x1f80 && addr < 0x1f801000) { MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]); iLWLk(addr & 3); iRegs[_Rt_].state = ST_UNK; MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); return; } } if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); if (_Imm_) ADD32ItoR(EAX, _Imm_); } //PUSH64R (EAX); AND32ItoR(EAX, ~3); //PUSH64R (EAX); MOV32RtoR(X86ARG1, EAX); CALLFunc((uptr)psxMemRead32); if (_Rt_) { //ADD32ItoR(ESP, 4); //POP64R (EDX); if (IsConst(_Rs_)) MOV32ItoR(EDX, iRegs[_Rs_].k + _Imm_); else { MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rs_]); if (_Imm_) ADD32ItoR(EDX, _Imm_); } AND32ItoR(EDX, 0x3); // shift = addr & 3; MOV64ItoR(ECX, (uptr)LWL_SHIFT); MOV32RmStoR(ECX, ECX, EDX, 2); SHL32CLtoR(EAX); // mem(EAX) << LWL_SHIFT[shift] MOV64ItoR(ECX, (uptr)LWL_MASK); MOV32RmStoR(ECX, ECX, EDX, 2); if (IsConst(_Rt_)) { MOV32ItoR(EDX, iRegs[_Rt_].k); } else { MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]); } AND32RtoR(EDX, ECX); // _rRt_ & LWL_MASK[shift] OR32RtoR(EAX, EDX); iRegs[_Rt_].state = ST_UNK; MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); //} else { //ADD64ItoR(RSP, 8); //resp+= 8; } } /* static void recLWBlock(int count) { u32 *code = PSXM(pc); int i, respsave; // Rt = mem[Rs + Im] (unsigned) // iFlushRegs(); if (IsConst(_Rs_)) { u32 addr = iRegs[_Rs_].k + _Imm_; int t = addr >> 16; if ((t & 0xfff0) == 0xbfc0) { // since bios is readonly it won't change for (i=0; i> 16; if ((t & 0x1fe0) == 0) { MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]); iLWRk(addr & 3); iRegs[_Rt_].state = ST_UNK; MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); return; } if (t == 0x1f80 && addr < 0x1f801000) { MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]); iLWRk(addr & 3); iRegs[_Rt_].state = ST_UNK; MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); return; } } if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); if (_Imm_) ADD32ItoR(EAX, _Imm_); } PUSHR(EAX); AND32ItoR(EAX, ~3); MOV32RtoR(X86ARG1, EAX); CALLFunc((uptr)psxMemRead32); POPR (EDX); if (_Rt_) { AND32ItoR(EDX, 0x3); // shift = addr & 3; MOV64ItoR(ECX, (uptr)LWR_SHIFT); MOV32RmStoR(ECX, ECX, EDX, 2); SHR32CLtoR(EAX); // mem(EAX) >> LWR_SHIFT[shift] MOV64ItoR(ECX, (uptr)LWR_MASK); MOV32RmStoR(ECX, ECX, EDX, 2); if (IsConst(_Rt_)) { MOV32ItoR(EDX, iRegs[_Rt_].k); } else { MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]); } AND32RtoR(EDX, ECX); // _rRt_ & LWR_MASK[shift] OR32RtoR(EAX, EDX); iRegs[_Rt_].state = ST_UNK; MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); //} else { //resp+= 8; } } static void recSB() { // mem[Rs + Im] = Rt // iFlushRegs(); if (IsConst(_Rs_)) { u32 addr = iRegs[_Rs_].k + _Imm_; int t = addr >> 16; if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { if (IsConst(_Rt_)) { MOV8ItoM((uptr)&psxM[addr & 0x1fffff], (u8)iRegs[_Rt_].k); } else { MOV8MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV8RtoM((uptr)&psxM[addr & 0x1fffff], EAX); } MOV32ItoR(X86ARG2, 1); MOV32ItoR(X86ARG1, addr & ~3); CALLFunc((uptr)&recClear); return; } if (t == 0x1f80 && addr < 0x1f801000) { if (IsConst(_Rt_)) { MOV8ItoM((uptr)&psxH[addr & 0xfff], (u8)iRegs[_Rt_].k); } else { MOV8MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV8RtoM((uptr)&psxH[addr & 0xfff], EAX); } return; } // SysPrintf("unhandled w8 %x\n", addr); } if (IsConst(_Rt_)) { MOV64ItoR(X86ARG2, iRegs[_Rt_].k); } else { MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]); } SetArg_OfB(X86ARG1); CALLFunc((uptr)psxMemWrite8); // ADD32ItoR(ESP, 8); } static void recSH() { // mem[Rs + Im] = Rt // iFlushRegs(); if (IsConst(_Rs_)) { u32 addr = iRegs[_Rs_].k + _Imm_; int t = addr >> 16; if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { if (IsConst(_Rt_)) { MOV16ItoM((uptr)&psxM[addr & 0x1fffff], (u16)iRegs[_Rt_].k); } else { MOV16MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV16RtoM((uptr)&psxM[addr & 0x1fffff], EAX); } MOV32ItoR(X86ARG2, 1); MOV32ItoR(X86ARG1, addr & ~3); CALLFunc((uptr)&recClear); return; } if (t == 0x1f80 && addr < 0x1f801000) { if (IsConst(_Rt_)) { MOV16ItoM((uptr)&psxH[addr & 0xfff], (u16)iRegs[_Rt_].k); } else { MOV16MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV16RtoM((uptr)&psxH[addr & 0xfff], EAX); } return; } if (t == 0x1f80) { if (addr >= 0x1f801c00 && addr < 0x1f801e00) { if (IsConst(_Rt_)) { MOV64ItoR(X86ARG2, iRegs[_Rt_].k); } else { MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]); } MOV64ItoR(X86ARG1, addr); CALLFunc ((uptr)SPU_writeRegister); #ifndef __WIN32__ //resp+= 8; #endif return; } } // SysPrintf("unhandled w16 %x\n", addr); } if (IsConst(_Rt_)) { MOV64ItoR(X86ARG2, iRegs[_Rt_].k); } else { MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]); } SetArg_OfB(X86ARG1); CALLFunc((uptr)psxMemWrite16); // ADD32ItoR(ESP, 8); } static void recSW() { // mem[Rs + Im] = Rt // iFlushRegs(); if (IsConst(_Rs_)) { u32 addr = iRegs[_Rs_].k + _Imm_; int t = addr >> 16; if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { if (IsConst(_Rt_)) { MOV32ItoM((uptr)&psxM[addr & 0x1fffff], iRegs[_Rt_].k); } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32RtoM((uptr)&psxM[addr & 0x1fffff], EAX); } MOV32ItoR(X86ARG2, 1); MOV32ItoR(X86ARG1, addr); CALLFunc((uptr)&recClear); return; } if (t == 0x1f80 && addr < 0x1f801000) { if (IsConst(_Rt_)) { MOV32ItoM((uptr)&psxH[addr & 0xfff], iRegs[_Rt_].k); } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32RtoM((uptr)&psxH[addr & 0xfff], EAX); } return; } if (t == 0x1f80) { switch (addr) { case 0x1f801080: case 0x1f801084: case 0x1f801090: case 0x1f801094: case 0x1f8010a0: case 0x1f8010a4: case 0x1f8010b0: case 0x1f8010b4: case 0x1f8010c0: case 0x1f8010c4: case 0x1f8010d0: case 0x1f8010d4: case 0x1f8010e0: case 0x1f8010e4: case 0x1f801074: case 0x1f8010f0: if (IsConst(_Rt_)) { MOV32ItoM((uptr)&psxH[addr & 0xffff], iRegs[_Rt_].k); } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32RtoM((uptr)&psxH[addr & 0xffff], EAX); } return; case 0x1f801810: if (IsConst(_Rt_)) { MOV64ItoR(X86ARG1, iRegs[_Rt_].k); } else { MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rt_]); } CALLFunc((uptr)GPU_writeData); #ifndef __WIN32__ //resp+= 4; #endif return; case 0x1f801814: if (IsConst(_Rt_)) { MOV64ItoR(X86ARG1, iRegs[_Rt_].k); } else { MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rt_]); } CALLFunc((uptr)GPU_writeStatus); #ifndef __WIN32__ //resp+= 4; #endif } } // SysPrintf("unhandled w32 %x\n", addr); } if (IsConst(_Rt_)) { MOV64ItoR(X86ARG2, iRegs[_Rt_].k); } else { MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]); } SetArg_OfB(X86ARG1); CALLFunc((uptr)psxMemWrite32); // ADD32ItoR(ESP, 8); //resp+= 8; } /* static void recSWBlock(int count) { u32 *code; int i, respsave; // mem[Rs + Im] = Rt // iFlushRegs(); if (IsConst(_Rs_)) { u32 addr = iRegs[_Rs_].k + _Imm_; int t = addr >> 16; code = PSXM(pc); if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { for (i=0; i> 16; if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]); iSWLk(addr & 3); MOV32RtoM((uptr)&psxM[addr & 0x1ffffc], EAX); return; } if (t == 0x1f80 && addr < 0x1f801000) { MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]); iSWLk(addr & 3); MOV32RtoM((uptr)&psxH[addr & 0xffc], EAX); return; } } if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); if (_Imm_) ADD32ItoR(EAX, _Imm_); } PUSHR (EAX); AND32ItoR(EAX, ~3); MOV32RtoR(X86ARG1, EAX); CALLFunc((uptr)psxMemRead32); POPR (EDX); AND32ItoR(EDX, 0x3); // shift = addr & 3; MOV64ItoR(ECX, (uptr)SWL_MASK); MOV32RmStoR(ECX, ECX, EDX, 2); AND32RtoR(EAX, ECX); // mem & SWL_MASK[shift] MOV64ItoR(ECX, (uptr)SWL_SHIFT); MOV32RmStoR(ECX, ECX, EDX, 2); if (IsConst(_Rt_)) { MOV32ItoR(EDX, iRegs[_Rt_].k); } else { MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]); } SHR32CLtoR(EDX); // _rRt_ >> SWL_SHIFT[shift] OR32RtoR (EAX, EDX); MOV32RtoR(X86ARG2, EAX); if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); if (_Imm_) ADD32ItoR(EAX, _Imm_); } AND32ItoR(EAX, ~3); MOV32RtoR(X86ARG1, EAX); CALLFunc((uptr)psxMemWrite32); // ADD32ItoR(ESP, 8); //resp+= 8; } extern u32 SWR_MASK[4]; extern u32 SWR_SHIFT[4]; void iSWRk(u32 shift) { if (IsConst(_Rt_)) { MOV32ItoR(ECX, iRegs[_Rt_].k); } else { MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); } SHL32ItoR(ECX, SWR_SHIFT[shift]); AND32ItoR(EAX, SWR_MASK[shift]); OR32RtoR (EAX, ECX); } void recSWR() { // mem[Rs + Im] = Rt Merge mem[Rs + Im] if (IsConst(_Rs_)) { u32 addr = iRegs[_Rs_].k + _Imm_; int t = addr >> 16; if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]); iSWRk(addr & 3); MOV32RtoM((uptr)&psxM[addr & 0x1ffffc], EAX); return; } if (t == 0x1f80 && addr < 0x1f801000) { MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]); iSWRk(addr & 3); MOV32RtoM((uptr)&psxH[addr & 0xffc], EAX); return; } } if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); if (_Imm_) ADD32ItoR(EAX, _Imm_); } PUSHR (EAX); AND32ItoR(EAX, ~3); MOV32RtoR(X86ARG1, EAX); CALLFunc((uptr)psxMemRead32); POPR (EDX); AND32ItoR(EDX, 0x3); // shift = addr & 3; MOV64ItoR(ECX, (uptr)SWR_MASK); MOV32RmStoR(ECX, ECX, EDX, 2); AND32RtoR(EAX, ECX); // mem & SWR_MASK[shift] MOV64ItoR(ECX, (uptr)SWR_SHIFT); MOV32RmStoR(ECX, ECX, EDX, 2); if (IsConst(_Rt_)) { MOV32ItoR(EDX, iRegs[_Rt_].k); } else { MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]); } SHL32CLtoR(EDX); // _rRt_ << SWR_SHIFT[shift] OR32RtoR (EAX, EDX); MOV32RtoR(X86ARG2, EAX); if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_); else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); if (_Imm_) ADD32ItoR(EAX, _Imm_); } AND32ItoR(EAX, ~3); MOV32RtoR(X86ARG1, EAX); CALLFunc((uptr)psxMemWrite32); // ADD32ItoR(ESP, 8); //resp+= 8; } #endif #if 0 REC_FUNC(SLL); REC_FUNC(SRL); REC_FUNC(SRA); #endif #if 1 static void recSLL() { // Rd = Rt << Sa if (!_Rd_) return; // iFlushRegs(); if (IsConst(_Rt_)) { MapConst(_Rd_, iRegs[_Rt_].k << _Sa_); } else { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); if (_Sa_) SHL32ItoR(EAX, _Sa_); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } static void recSRL() { // Rd = Rt >> Sa if (!_Rd_) return; // iFlushRegs(); if (IsConst(_Rt_)) { MapConst(_Rd_, iRegs[_Rt_].k >> _Sa_); } else { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); if (_Sa_) SHR32ItoR(EAX, _Sa_); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } static void recSRA() { // Rd = Rt >> Sa if (!_Rd_) return; // iFlushRegs(); if (IsConst(_Rt_)) { MapConst(_Rd_, (s32)iRegs[_Rt_].k >> _Sa_); } else { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); if (_Sa_) SAR32ItoR(EAX, _Sa_); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } #endif #if 0 REC_FUNC(SLLV); REC_FUNC(SRLV); REC_FUNC(SRAV); #endif #if 1 static void recSLLV() { // Rd = Rt << Rs if (!_Rd_) return; // iFlushRegs(); if (IsConst(_Rt_) && IsConst(_Rs_)) { MapConst(_Rd_, iRegs[_Rt_].k << iRegs[_Rs_].k); } else if (IsConst(_Rs_)) { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32ItoR(ECX, iRegs[_Rs_].k); SHL32CLtoR(EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else if (IsConst(_Rt_)) { iRegs[_Rd_].state = ST_UNK; MOV32ItoR(EAX, iRegs[_Rt_].k); MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); SHL32CLtoR(EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); SHL32CLtoR(EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } static void recSRLV() { // Rd = Rt >> Rs if (!_Rd_) return; // iFlushRegs(); if (IsConst(_Rt_) && IsConst(_Rs_)) { MapConst(_Rd_, iRegs[_Rt_].k >> iRegs[_Rs_].k); } else if (IsConst(_Rs_)) { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32ItoR(ECX, iRegs[_Rs_].k); SHR32CLtoR(EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else if (IsConst(_Rt_)) { iRegs[_Rd_].state = ST_UNK; MOV32ItoR(EAX, iRegs[_Rt_].k); MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); SHR32CLtoR(EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); SHR32CLtoR(EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } static void recSRAV() { // Rd = Rt >> Rs if (!_Rd_) return; // iFlushRegs(); if (IsConst(_Rt_) && IsConst(_Rs_)) { MapConst(_Rd_, (s32)iRegs[_Rt_].k >> iRegs[_Rs_].k); } else if (IsConst(_Rs_)) { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32ItoR(ECX, iRegs[_Rs_].k); SAR32CLtoR(EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else if (IsConst(_Rt_)) { iRegs[_Rd_].state = ST_UNK; MOV32ItoR(EAX, iRegs[_Rt_].k); MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); SAR32CLtoR(EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } else { iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); SAR32CLtoR(EAX); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } } #endif #if 0 REC_SYS(SYSCALL); REC_SYS(BREAK); #endif #if 1 static void recSYSCALL() { // dump=1; iFlushRegs(); MOV32ItoR(EAX, pc - 4); MOV32RtoM((uptr)&psxRegs.pc, EAX); MOV64ItoR(X86ARG2, branch == 1 ? 1 : 0); MOV64ItoR(X86ARG1, 0x20); CALLFunc((uptr)psxException); //ADD32ItoR(ESP, 8); branch = 2; iRet(); } static void recBREAK() { } #endif #if 0 REC_FUNC(MFHI); REC_FUNC(MTHI); REC_FUNC(MFLO); REC_FUNC(MTLO); #endif #if 1 static void recMFHI() { // Rd = Hi if (!_Rd_) return; iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.hi); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } static void recMTHI() { // Hi = Rs if (IsConst(_Rs_)) { MOV32ItoM((uptr)&psxRegs.GPR.n.hi, iRegs[_Rs_].k); } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); } } static void recMFLO() { // Rd = Lo if (!_Rd_) return; iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.lo); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); } static void recMTLO() { // Lo = Rs if (IsConst(_Rs_)) { MOV32ItoM((uptr)&psxRegs.GPR.n.lo, iRegs[_Rs_].k); } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); } } #endif #if 0 REC_BRANCH(J); REC_BRANCH(JR); REC_BRANCH(JAL); REC_BRANCH(JALR); REC_BRANCH(BLTZ); REC_BRANCH(BGTZ); REC_BRANCH(BLTZAL); REC_BRANCH(BGEZAL); REC_BRANCH(BNE); REC_BRANCH(BEQ); REC_BRANCH(BLEZ); REC_BRANCH(BGEZ); #endif #if 1 static void recBLTZ() { // Branch if Rs < 0 u32 bpc = _Imm_ * 4 + pc; // iFlushRegs(); if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { return; } if (IsConst(_Rs_)) { if ((s32)iRegs[_Rs_].k < 0) { iJump(bpc); return; } else { iJump(pc+4); return; } } CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); j32Ptr[4] = JL32(0); iBranch(pc+4, 1); x86SetJ32(j32Ptr[4]); iBranch(bpc, 0); pc+=4; } static void recBGTZ() { // Branch if Rs > 0 u32 bpc = _Imm_ * 4 + pc; // iFlushRegs(); if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { return; } if (IsConst(_Rs_)) { if ((s32)iRegs[_Rs_].k > 0) { iJump(bpc); return; } else { iJump(pc+4); return; } } CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); j32Ptr[4] = JG32(0); iBranch(pc+4, 1); x86SetJ32(j32Ptr[4]); iBranch(bpc, 0); pc+=4; } static void recBLTZAL() { // Branch if Rs < 0 u32 bpc = _Imm_ * 4 + pc; // iFlushRegs(); if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { return; } if (IsConst(_Rs_)) { if ((s32)iRegs[_Rs_].k < 0) { MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4); iJump(bpc); return; } else { iJump(pc+4); return; } } CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); j32Ptr[4] = JL32(0); iBranch(pc+4, 1); x86SetJ32(j32Ptr[4]); MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4); iBranch(bpc, 0); pc+=4; } static void recBGEZAL() { // Branch if Rs >= 0 u32 bpc = _Imm_ * 4 + pc; // iFlushRegs(); if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { return; } if (IsConst(_Rs_)) { if ((s32)iRegs[_Rs_].k >= 0) { MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4); iJump(bpc); return; } else { iJump(pc+4); return; } } CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); j32Ptr[4] = JGE32(0); iBranch(pc+4, 1); x86SetJ32(j32Ptr[4]); MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4); iBranch(bpc, 0); pc+=4; } static void recJ() { // j target iJump(_Target_ * 4 + (pc & 0xf0000000)); } static void recJAL() { // jal target MapConst(31, pc + 4); iJump(_Target_ * 4 + (pc & 0xf0000000)); } static void recJR() { // jr Rs if (IsConst(_Rs_)) { MOV32ItoM((uptr)&target, iRegs[_Rs_].k); } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); MOV32RtoM((uptr)&target, EAX); } SetBranch(); } static void recJALR() { // jalr Rs if (IsConst(_Rs_)) { MOV32ItoM((uptr)&target, iRegs[_Rs_].k); } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); MOV32RtoM((uptr)&target, EAX); } if (_Rd_) { MapConst(_Rd_, pc + 4); } SetBranch(); } static void recBEQ() { // Branch if Rs == Rt u32 bpc = _Imm_ * 4 + pc; // iFlushRegs(); if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { return; } if (_Rs_ == _Rt_) { iJump(bpc); } else { if (IsConst(_Rs_) && IsConst(_Rt_)) { if (iRegs[_Rs_].k == iRegs[_Rt_].k) { iJump(bpc); return; } else { iJump(pc+4); return; } } else if (IsConst(_Rs_)) { CMP32ItoM((uptr)&psxRegs.GPR.r[_Rt_], iRegs[_Rs_].k); } else if (IsConst(_Rt_)) { CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], iRegs[_Rt_].k); } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); } j32Ptr[4] = JE32(0); iBranch(pc+4, 1); x86SetJ32(j32Ptr[4]); iBranch(bpc, 0); pc+=4; } } static void recBNE() { // Branch if Rs != Rt u32 bpc = _Imm_ * 4 + pc; // iFlushRegs(); if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { return; } if (IsConst(_Rs_) && IsConst(_Rt_)) { if (iRegs[_Rs_].k != iRegs[_Rt_].k) { iJump(bpc); return; } else { iJump(pc+4); return; } } else if (IsConst(_Rs_)) { CMP32ItoM((uptr)&psxRegs.GPR.r[_Rt_], iRegs[_Rs_].k); } else if (IsConst(_Rt_)) { CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], iRegs[_Rt_].k); } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); } j32Ptr[4] = JNE32(0); iBranch(pc+4, 1); x86SetJ32(j32Ptr[4]); iBranch(bpc, 0); pc+=4; } static void recBLEZ() { // Branch if Rs <= 0 u32 bpc = _Imm_ * 4 + pc; // iFlushRegs(); if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { return; } if (IsConst(_Rs_)) { if ((s32)iRegs[_Rs_].k <= 0) { iJump(bpc); return; } else { iJump(pc+4); return; } } CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); j32Ptr[4] = JLE32(0); iBranch(pc+4, 1); x86SetJ32(j32Ptr[4]); iBranch(bpc, 0); pc+=4; } static void recBGEZ() { // Branch if Rs >= 0 u32 bpc = _Imm_ * 4 + pc; // iFlushRegs(); if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) { return; } if (IsConst(_Rs_)) { if ((s32)iRegs[_Rs_].k >= 0) { iJump(bpc); return; } else { iJump(pc+4); return; } } CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); j32Ptr[4] = JGE32(0); iBranch(pc+4, 1); x86SetJ32(j32Ptr[4]); iBranch(bpc, 0); pc+=4; } #endif #if 0 REC_FUNC(MFC0); REC_SYS(MTC0); REC_FUNC(CFC0); REC_SYS(CTC0); REC_FUNC(RFE); #endif //REC_SYS(MTC0); #if 1 static void recMFC0() { // Rt = Cop0->Rd if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; MOV32MtoR(EAX, (uptr)&psxRegs.CP0.r[_Rd_]); MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); } static void recCFC0() { // Rt = Cop0->Rd recMFC0(); } //* void psxMTC0(); static void recMTC0() { // Cop0->Rd = Rt if (IsConst(_Rt_)) { switch (_Rd_) { case 12: MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k); break; case 13: MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k & ~(0xfc00)); break; default: MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k); break; } } else { MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); switch (_Rd_) { case 13: AND32ItoR(EAX, ~(0xfc00)); break; } MOV32RtoM((uptr)&psxRegs.CP0.r[_Rd_], EAX); } if (_Rd_ == 12 || _Rd_ == 13) { iFlushRegs(); MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); CALLFunc((uptr)psxTestSWInts); if (branch == 0) { branch = 2; iRet(); } } }//*/ static void recCTC0() { // Cop0->Rd = Rt recMTC0(); } static void recRFE() { MOV32MtoR(EAX, (uptr)&psxRegs.CP0.n.Status); MOV32RtoR(ECX, EAX); AND32ItoR(EAX, 0xfffffff0); AND32ItoR(ECX, 0x3c); SHR32ItoR(ECX, 2); OR32RtoR (EAX, ECX); MOV32RtoM((uptr)&psxRegs.CP0.n.Status, EAX); iFlushRegs(); MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); CALLFunc((uptr)psxTestSWInts); if (branch == 0) { branch = 2; iRet(); } } #endif #include "iGte.h" // static void recHLE() { iFlushRegs(); CALLFunc((uptr)psxHLEt[psxRegs.code & 0xffff]); branch = 2; iRet(); } // #include "iPGXP-64.h" static void (*recBSC[64])() = { recSPECIAL, recREGIMM, recJ , recJAL , recBEQ , recBNE , recBLEZ, recBGTZ, recADDI , recADDIU , recSLTI, recSLTIU, recANDI, recORI , recXORI, recLUI , recCOP0 , recNULL , recCOP2, recNULL , recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL , recNULL, recNULL, recNULL, recNULL, recLB , recLH , recLWL , recLW , recLBU , recLHU , recLWR , recNULL, recSB , recSH , recSWL , recSW , recNULL, recNULL, recSWR , recNULL, recNULL , recNULL , recLWC2, recNULL , recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recSWC2, recHLE , recNULL, recNULL, recNULL, recNULL }; static void (*recSPC[64])() = { recSLL , recNULL, recSRL , recSRA , recSLLV , recNULL , recSRLV, recSRAV, recJR , recJALR, recNULL, recNULL, recSYSCALL, recBREAK, recNULL, recNULL, recMFHI, recMTHI, recMFLO, recMTLO, recNULL , recNULL , recNULL, recNULL, recMULT, recMULTU, recDIV, recDIVU, recNULL , recNULL , recNULL, recNULL, recADD , recADDU, recSUB , recSUBU, recAND , recOR , recXOR , recNOR , recNULL, recNULL, recSLT , recSLTU, recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL }; static void (*recREG[32])() = { recBLTZ , recBGEZ , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recBLTZAL, recBGEZAL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL }; static void (*recCP0[32])() = { recMFC0, recNULL, recCFC0, recNULL, recMTC0, recNULL, recCTC0, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recRFE , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL }; static void (*recCP2[64])() = { recBASIC, recRTPS , recNULL , recNULL, recNULL, recNULL , recNCLIP, recNULL, // 00 recNULL , recNULL , recNULL , recNULL, recOP , recNULL , recNULL , recNULL, // 08 recDPCS , recINTPL, recMVMVA, recNCDS, recCDP , recNULL , recNCDT , recNULL, // 10 recNULL , recNULL , recNULL , recNCCS, recCC , recNULL , recNCS , recNULL, // 18 recNCT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 20 recSQR , recDCPL , recDPCT , recNULL, recNULL, recAVSZ3, recAVSZ4, recNULL, // 28 recRTPT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 30 recNULL , recNULL , recNULL , recNULL, recNULL, recGPF , recGPL , recNCCT // 38 }; static void (*recCP2BSC[32])() = { recMFC2, recNULL, recCFC2, recNULL, recMTC2, recNULL, recCTC2, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL }; // Trace all functions using PGXP static void(*pgxpRecBSC[64])() = { recSPECIAL, recREGIMM, recJ , recJAL , recBEQ , recBNE , recBLEZ, recBGTZ, pgxpRecADDI , pgxpRecADDIU , pgxpRecSLTI, pgxpRecSLTIU, pgxpRecANDI, pgxpRecORI , pgxpRecXORI, pgxpRecLUI , recCOP0 , recNULL , recCOP2, recNULL , recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL , recNULL, recNULL, recNULL, recNULL, pgxpRecLB , pgxpRecLH , pgxpRecLWL , pgxpRecLW , pgxpRecLBU , pgxpRecLHU , pgxpRecLWR , pgxpRecNULL, pgxpRecSB , pgxpRecSH , pgxpRecSWL , pgxpRecSW , pgxpRecNULL, pgxpRecNULL, pgxpRecSWR , pgxpRecNULL, recNULL , recNULL , pgxpRecLWC2, recNULL , recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , pgxpRecSWC2, recHLE , recNULL, recNULL, recNULL, recNULL }; static void(*pgxpRecSPC[64])() = { pgxpRecSLL , pgxpRecNULL, pgxpRecSRL , pgxpRecSRA , pgxpRecSLLV , pgxpRecNULL , pgxpRecSRLV, pgxpRecSRAV, recJR , recJALR, recNULL, recNULL, recSYSCALL, recBREAK, recNULL, recNULL, pgxpRecMFHI, pgxpRecMTHI, pgxpRecMFLO, pgxpRecMTLO, pgxpRecNULL , pgxpRecNULL , pgxpRecNULL, pgxpRecNULL, pgxpRecMULT, pgxpRecMULTU, pgxpRecDIV, pgxpRecDIVU, pgxpRecNULL , pgxpRecNULL , pgxpRecNULL, pgxpRecNULL, pgxpRecADD , pgxpRecADDU, pgxpRecSUB , pgxpRecSUBU, pgxpRecAND , pgxpRecOR , pgxpRecXOR , pgxpRecNOR , pgxpRecNULL, pgxpRecNULL, pgxpRecSLT , pgxpRecSLTU, pgxpRecNULL , pgxpRecNULL , pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL , pgxpRecNULL , pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL , pgxpRecNULL , pgxpRecNULL, pgxpRecNULL }; static void(*pgxpRecCP0[32])() = { pgxpRecMFC0, pgxpRecNULL, pgxpRecCFC0, pgxpRecNULL, pgxpRecMTC0, pgxpRecNULL, pgxpRecCTC0, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecRFE , pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL }; static void(*pgxpRecCP2BSC[32])() = { pgxpRecMFC2, pgxpRecNULL, pgxpRecCFC2, pgxpRecNULL, pgxpRecMTC2, pgxpRecNULL, pgxpRecCTC2, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL }; // Trace memory functions only static void(*pgxpRecBSCMem[64])() = { recSPECIAL, recREGIMM, recJ , recJAL , recBEQ , recBNE , recBLEZ, recBGTZ, recADDI , recADDIU , recSLTI, recSLTIU, recANDI, recORI , recXORI, recLUI , recCOP0 , recNULL , recCOP2, recNULL , recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL , recNULL, recNULL, recNULL, recNULL, pgxpRecLB , pgxpRecLH , pgxpRecLWL , pgxpRecLW , pgxpRecLBU , pgxpRecLHU , pgxpRecLWR , pgxpRecNULL, pgxpRecSB , pgxpRecSH , pgxpRecSWL , pgxpRecSW , pgxpRecNULL, pgxpRecNULL, pgxpRecSWR , pgxpRecNULL, recNULL , recNULL , pgxpRecLWC2, recNULL , recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , pgxpRecSWC2, recHLE , recNULL, recNULL, recNULL, recNULL }; static void recRecompile() { char *p; char *ptr; resp = 0; /* if x86Ptr reached the mem limit reset whole mem */ if (((uptr)x86Ptr - (uptr)recMem) >= (RECMEM_SIZE - PTRMULT*0x10000)) recReset(); x86Align(32); ptr = x86Ptr; PC_RECP(psxRegs.pc) = (uptr)x86Ptr; pc = psxRegs.pc; pcold = pc; //Make some stack space for function arguments spill (x86-64 calling conventions) // 0x38 = 7 args, should be plenty... SUB64ItoR(RSP, STACKSIZE); for (count=0; count<500;) { p = (char *)PSXM(pc); if (p == NULL) recError(); psxRegs.code = *(u32 *)p; /* if ((psxRegs.code >> 26) == 0x23) { // LW int i; u32 code; for (i=1;; i++) { p = (char *)PSXM(pc+i*4); if (p == NULL) recError(); code = *(u32 *)p; if ((code >> 26) != 0x23 || _fRs_(code) != _Rs_ || _fImm_(code) != (_Imm_+i*4)) break; } if (i > 1) { recLWBlock(i); pc = pc + i*4; continue; } } if ((psxRegs.code >> 26) == 0x2b) { // SW int i; u32 code; for (i=1;; i++) { p = (char *)PSXM(pc+i*4); if (p == NULL) recError(); code = *(u32 *)p; if ((code >> 26) != 0x2b || _fRs_(code) != _Rs_ || _fImm_(code) != (_Imm_+i*4)) break; } if (i > 1) { recSWBlock(i); pc = pc + i*4; continue; } }*/ #ifdef PSXCPU_LOG if (Config.PsxOut) { dump = TRUE; } iDump(iRegs); #endif pc+=4; count++; pRecBSC[psxRegs.code>>26](); #ifdef PSXCPU_LOG dump = FALSE; #endif if (branch) { branch = 0; #ifdef PSXCPU_LOG if (dump) iDumpBlock(ptr); #endif return; } } iFlushRegs(); MOV32ItoM((uptr)&psxRegs.pc, pc); iRet(); } R3000Acpu psxRec = { recInit, recReset, recExecute, recExecuteBlock, recClear, recShutdown, recSetPGXPMode }; #endif