/* Pcsx - Pc Psx Emulator * Copyright (C) 1999-2003 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA */ int psxCP2time[64] = { 2, 16 , 1 , 1, 1, 1 , 8, 1, // 00 1 , 1 , 1 , 1, 6 , 1 , 1 , 1, // 08 8 , 8, 8, 19, 13 , 1 , 44 , 1, // 10 1 , 1 , 1 , 17, 11 , 1 , 14 , 1, // 18 30 , 1 , 1 , 1, 1, 1 , 1 , 1, // 20 5 , 8 , 17 , 1, 1, 5, 6, 1, // 28 23 , 1 , 1 , 1, 1, 1 , 1 , 1, // 30 1 , 1 , 1 , 1, 1, 6 , 5 , 39 // 38 }; #define CP2_FUNC(f) \ void gte##f(); \ static void rec##f() { \ if (pc < cop2readypc) idlecyclecount += (cop2readypc - pc)>>2; \ iFlushRegs(0); \ LIW(0, (u32)psxRegs.code); \ STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \ FlushAllHWReg(); \ CALLFunc ((u32)gte##f); \ cop2readypc = pc + psxCP2time[_fFunct_(psxRegs.code)]<<2; \ } #define CP2_FUNCNC(f) \ void gte##f(); \ static void rec##f() { \ if (pc < cop2readypc) idlecyclecount += (cop2readypc - pc)>>2; \ iFlushRegs(0); \ CALLFunc ((u32)gte##f); \ /* branch = 2; */\ cop2readypc = pc + psxCP2time[_fFunct_(psxRegs.code)]; \ } CP2_FUNC(MFC2); CP2_FUNC(MTC2); CP2_FUNC(CFC2); CP2_FUNC(CTC2); CP2_FUNC(LWC2); CP2_FUNC(SWC2); #if 0 void gteMFC2(); static void recMFC2() { // Rt = Cop2D->Rd if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; switch (_Rd_) { case 29: MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); CALLFunc ((u32)gteMFC2); break; default: MOV32MtoR(EAX, (u32)&psxRegs.CP2D.r[_Rd_]); MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); break; } } void gteMTC2(); static void recMTC2() { // Cop2D->Rd = Rt int fixt = 0; // iFlushRegs(); switch (_Rd_) { case 8: case 9: case 10: case 11: fixt = 1; break; case 16: case 17: case 18: case 19: fixt = 2; break; case 15: case 28: case 30: MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); CALLFunc ((u32)gteMTC2); break; } if (IsConst(_Rt_)) { if (fixt == 1) MOV32ItoM((u32)&psxRegs.CP2D.r[_Rd_], (s16)iRegs[_Rt_].k); else if (fixt == 2) MOV32ItoM((u32)&psxRegs.CP2D.r[_Rd_], iRegs[_Rt_].k & 0xffff); else MOV32ItoM((u32)&psxRegs.CP2D.r[_Rd_], iRegs[_Rt_].k); } else { MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); if (fixt == 1) MOVSX32R16toR(EAX, EAX); else if (fixt == 2) AND32ItoR(EAX, 0xffff); MOV32RtoM((u32)&psxRegs.CP2D.r[_Rd_], EAX); } } void gteLWC2(); static void recLWC2() { // Cop2D->Rt = mem[Rs + Im] (unsigned) int fixt = 0; switch (_Rt_) { case 8: case 9: case 10: case 11: fixt = 1; break; case 16: case 17: case 18: case 19: fixt = 2; break; case 15: case 28: case 30: iFlushRegs(); MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); CALLFunc ((u32)gteLWC2); return; } if (IsConst(_Rs_)) { u32 addr = iRegs[_Rs_].k + _Imm_; int t = addr >> 16; if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { MOV32MtoR(EAX, (u32)&psxM[addr & 0x1fffff]); if (fixt == 1) MOVSX32R16toR(EAX, EAX); else if (fixt == 2) AND32ItoR(EAX, 0xffff); MOV32RtoM((u32)&psxRegs.CP2D.r[_Rt_], EAX); return; } if (t == 0x1f80 && addr < 0x1f801000) { MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]); if (fixt == 1) MOVSX32R16toR(EAX, EAX); else if (fixt == 2) AND32ItoR(EAX, 0xffff); MOV32RtoM((u32)&psxRegs.CP2D.r[_Rt_], EAX); return; } } iPushOfB(); CALLFunc((u32)psxMemRead32); if (fixt == 1) MOVSX32R16toR(EAX, EAX); else if (fixt == 2) AND32ItoR(EAX, 0xffff); MOV32RtoM((u32)&psxRegs.CP2D.r[_Rt_], EAX); // ADD32ItoR(ESP, 4); resp+= 4; } void gteSWC2(); static void recSWC2() { // mem[Rs + Im] = Rt switch (_Rt_) { case 29: iFlushRegs(); MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); CALLFunc ((u32)gteSWC2); return; } if (IsConst(_Rs_)) { u32 addr = iRegs[_Rs_].k + _Imm_; int t = addr >> 16; if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { MOV32MtoR(EAX, (u32)&psxRegs.CP2D.r[_Rt_]); MOV32RtoM((u32)&psxM[addr & 0x1fffff], EAX); return; } if (t == 0x1f80 && addr < 0x1f801000) { MOV32MtoR(EAX, (u32)&psxRegs.CP2D.r[_Rt_]); MOV32RtoM((u32)&psxH[addr & 0xfff], EAX); return; } } PUSH32M ((u32)&psxRegs.CP2D.r[_Rt_]); iPushOfB(); CALLFunc((u32)psxMemWrite32); // ADD32ItoR(ESP, 8); resp+= 8; } static void recCFC2() { // Rt = Cop2C->Rd if (!_Rt_) return; iRegs[_Rt_].state = ST_UNK; MOV32MtoR(EAX, (u32)&psxRegs.CP2C.r[_Rd_]); MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); } static void recCTC2() { // Cop2C->Rd = Rt if (IsConst(_Rt_)) { MOV32ItoM((u32)&psxRegs.CP2C.r[_Rd_], iRegs[_Rt_].k); } else { MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); MOV32RtoM((u32)&psxRegs.CP2C.r[_Rd_], EAX); } } #endif CP2_FUNCNC(RTPS); CP2_FUNC(OP); CP2_FUNCNC(NCLIP); CP2_FUNCNC(DPCS); CP2_FUNCNC(INTPL); CP2_FUNC(MVMVA); CP2_FUNCNC(NCDS); CP2_FUNCNC(NCDT); CP2_FUNCNC(CDP); CP2_FUNCNC(NCCS); CP2_FUNCNC(CC); CP2_FUNCNC(NCS); CP2_FUNCNC(NCT); CP2_FUNC(SQR); CP2_FUNCNC(DCPL); CP2_FUNCNC(DPCT); CP2_FUNCNC(AVSZ3); CP2_FUNCNC(AVSZ4); CP2_FUNCNC(RTPT); CP2_FUNC(GPF); CP2_FUNC(GPL); CP2_FUNCNC(NCCT); #if 0 #define gteVX0 ((s16*)psxRegs.CP2D.r)[0] #define gteVY0 ((s16*)psxRegs.CP2D.r)[1] #define gteVZ0 ((s16*)psxRegs.CP2D.r)[2] #define gteVX1 ((s16*)psxRegs.CP2D.r)[4] #define gteVY1 ((s16*)psxRegs.CP2D.r)[5] #define gteVZ1 ((s16*)psxRegs.CP2D.r)[6] #define gteVX2 ((s16*)psxRegs.CP2D.r)[8] #define gteVY2 ((s16*)psxRegs.CP2D.r)[9] #define gteVZ2 ((s16*)psxRegs.CP2D.r)[10] #define gteRGB psxRegs.CP2D.r[6] #define gteOTZ ((s16*)psxRegs.CP2D.r)[7*2] #define gteIR0 ((s32*)psxRegs.CP2D.r)[8] #define gteIR1 ((s32*)psxRegs.CP2D.r)[9] #define gteIR2 ((s32*)psxRegs.CP2D.r)[10] #define gteIR3 ((s32*)psxRegs.CP2D.r)[11] #define gteSX0 ((s16*)psxRegs.CP2D.r)[12*2] #define gteSY0 ((s16*)psxRegs.CP2D.r)[12*2+1] #define gteSX1 ((s16*)psxRegs.CP2D.r)[13*2] #define gteSY1 ((s16*)psxRegs.CP2D.r)[13*2+1] #define gteSX2 ((s16*)psxRegs.CP2D.r)[14*2] #define gteSY2 ((s16*)psxRegs.CP2D.r)[14*2+1] #define gteSXP ((s16*)psxRegs.CP2D.r)[15*2] #define gteSYP ((s16*)psxRegs.CP2D.r)[15*2+1] #define gteSZx ((u16*)psxRegs.CP2D.r)[16*2] #define gteSZ0 ((u16*)psxRegs.CP2D.r)[17*2] #define gteSZ1 ((u16*)psxRegs.CP2D.r)[18*2] #define gteSZ2 ((u16*)psxRegs.CP2D.r)[19*2] #define gteRGB0 psxRegs.CP2D.r[20] #define gteRGB1 psxRegs.CP2D.r[21] #define gteRGB2 psxRegs.CP2D.r[22] #define gteMAC0 psxRegs.CP2D.r[24] #define gteMAC1 ((s32*)psxRegs.CP2D.r)[25] #define gteMAC2 ((s32*)psxRegs.CP2D.r)[26] #define gteMAC3 ((s32*)psxRegs.CP2D.r)[27] #define gteIRGB psxRegs.CP2D.r[28] #define gteORGB psxRegs.CP2D.r[29] #define gteLZCS psxRegs.CP2D.r[30] #define gteLZCR psxRegs.CP2D.r[31] #define gteR ((u8 *)psxRegs.CP2D.r)[6*4] #define gteG ((u8 *)psxRegs.CP2D.r)[6*4+1] #define gteB ((u8 *)psxRegs.CP2D.r)[6*4+2] #define gteCODE ((u8 *)psxRegs.CP2D.r)[6*4+3] #define gteC gteCODE #define gteR0 ((u8 *)psxRegs.CP2D.r)[20*4] #define gteG0 ((u8 *)psxRegs.CP2D.r)[20*4+1] #define gteB0 ((u8 *)psxRegs.CP2D.r)[20*4+2] #define gteCODE0 ((u8 *)psxRegs.CP2D.r)[20*4+3] #define gteC0 gteCODE0 #define gteR1 ((u8 *)psxRegs.CP2D.r)[21*4] #define gteG1 ((u8 *)psxRegs.CP2D.r)[21*4+1] #define gteB1 ((u8 *)psxRegs.CP2D.r)[21*4+2] #define gteCODE1 ((u8 *)psxRegs.CP2D.r)[21*4+3] #define gteC1 gteCODE1 #define gteR2 ((u8 *)psxRegs.CP2D.r)[22*4] #define gteG2 ((u8 *)psxRegs.CP2D.r)[22*4+1] #define gteB2 ((u8 *)psxRegs.CP2D.r)[22*4+2] #define gteCODE2 ((u8 *)psxRegs.CP2D.r)[22*4+3] #define gteC2 gteCODE2 #define gteR11 ((s16*)psxRegs.CP2C.r)[0] #define gteR12 ((s16*)psxRegs.CP2C.r)[1] #define gteR13 ((s16*)psxRegs.CP2C.r)[2] #define gteR21 ((s16*)psxRegs.CP2C.r)[3] #define gteR22 ((s16*)psxRegs.CP2C.r)[4] #define gteR23 ((s16*)psxRegs.CP2C.r)[5] #define gteR31 ((s16*)psxRegs.CP2C.r)[6] #define gteR32 ((s16*)psxRegs.CP2C.r)[7] #define gteR33 ((s16*)psxRegs.CP2C.r)[8] #define gteTRX ((s32*)psxRegs.CP2C.r)[5] #define gteTRY ((s32*)psxRegs.CP2C.r)[6] #define gteTRZ ((s32*)psxRegs.CP2C.r)[7] #define gteL11 ((s16*)psxRegs.CP2C.r)[16] #define gteL12 ((s16*)psxRegs.CP2C.r)[17] #define gteL13 ((s16*)psxRegs.CP2C.r)[18] #define gteL21 ((s16*)psxRegs.CP2C.r)[19] #define gteL22 ((s16*)psxRegs.CP2C.r)[20] #define gteL23 ((s16*)psxRegs.CP2C.r)[21] #define gteL31 ((s16*)psxRegs.CP2C.r)[22] #define gteL32 ((s16*)psxRegs.CP2C.r)[23] #define gteL33 ((s16*)psxRegs.CP2C.r)[24] #define gteRBK ((s32*)psxRegs.CP2C.r)[13] #define gteGBK ((s32*)psxRegs.CP2C.r)[14] #define gteBBK ((s32*)psxRegs.CP2C.r)[15] #define gteLR1 ((s16*)psxRegs.CP2C.r)[32] #define gteLR2 ((s16*)psxRegs.CP2C.r)[33] #define gteLR3 ((s16*)psxRegs.CP2C.r)[34] #define gteLG1 ((s16*)psxRegs.CP2C.r)[35] #define gteLG2 ((s16*)psxRegs.CP2C.r)[36] #define gteLG3 ((s16*)psxRegs.CP2C.r)[37] #define gteLB1 ((s16*)psxRegs.CP2C.r)[38] #define gteLB2 ((s16*)psxRegs.CP2C.r)[39] #define gteLB3 ((s16*)psxRegs.CP2C.r)[40] #define gteRFC ((s32*)psxRegs.CP2C.r)[21] #define gteGFC ((s32*)psxRegs.CP2C.r)[22] #define gteBFC ((s32*)psxRegs.CP2C.r)[23] #define gteOFX ((s32*)psxRegs.CP2C.r)[24] #define gteOFY ((s32*)psxRegs.CP2C.r)[25] #define gteH ((u16*)psxRegs.CP2C.r)[52] #define gteDQA ((s16*)psxRegs.CP2C.r)[54] #define gteDQB ((s32*)psxRegs.CP2C.r)[28] #define gteZSF3 ((s16*)psxRegs.CP2C.r)[58] #define gteZSF4 ((s16*)psxRegs.CP2C.r)[60] #define gteFLAG psxRegs.CP2C.r[31] //#define SUM_FLAG if(gteFLAG & 0x7F87E000) gteFLAG |= 0x80000000; #define SUM_FLAG() { \ TEST32ItoM((u32)>eFLAG, 0x7F87E000); \ j8Ptr[0] = JZ8(0); \ OR32ItoM((u32)>eFLAG, 0x80000000); \ \ x86SetJ8(j8Ptr[0]); \ } #define LIM32X8(reg, gteout, negv, posv, flagb) { \ CMP32ItoR(reg, negv); \ j8Ptr[0] = JL8(0); \ CMP32ItoR(reg, posv); \ j8Ptr[1] = JG8(0); \ \ MOV8RtoM((u32)>eout, reg); \ j8Ptr[2] = JMP8(0); \ \ x86SetJ8(j8Ptr[0]); \ MOV8ItoM((u32)>eout, negv); \ j8Ptr[3] = JMP8(0); \ \ x86SetJ8(j8Ptr[1]); \ MOV8ItoM((u32)>eout, posv); \ \ x86SetJ8(j8Ptr[3]); \ OR32ItoM((u32)>eFLAG, 1<