#include #include "MA_EE.h" #include "MIPS.h" #include "CodeGen.h" #include "PS2OS.h" #include "offsetof_def.h" #include "MemoryUtils.h" using namespace std; using namespace std::tr1; CMA_EE::CMA_EE() : CMA_MIPSIV(MIPS_REGSIZE_64) { m_pOpGeneral[0x1E] = bind(&CMA_EE::LQ, this); m_pOpGeneral[0x1F] = bind(&CMA_EE::SQ, this); //OS special instructions m_pOpSpecial[0x1D] = bind(&CMA_EE::REEXCPT, this); m_pOpRegImm[0x18] = bind(&CMA_EE::MTSAB, this); m_pOpRegImm[0x19] = bind(&CMA_EE::MTSAH, this); m_pOpSpecial2[0x00] = bind(&CMA_EE::MADD, this); m_pOpSpecial2[0x04] = bind(&CMA_EE::PLZCW, this); m_pOpSpecial2[0x08] = bind(&CMA_EE::MMI0, this); m_pOpSpecial2[0x09] = bind(&CMA_EE::MMI2, this); m_pOpSpecial2[0x10] = bind(&CMA_EE::MFHI1, this); m_pOpSpecial2[0x11] = bind(&CMA_EE::MTHI1, this); m_pOpSpecial2[0x12] = bind(&CMA_EE::MFLO1, this); m_pOpSpecial2[0x13] = bind(&CMA_EE::MTLO1, this); m_pOpSpecial2[0x18] = bind(&CMA_EE::MULT1, this); m_pOpSpecial2[0x19] = bind(&CMA_EE::MULTU1, this); m_pOpSpecial2[0x1A] = bind(&CMA_EE::DIV1, this); m_pOpSpecial2[0x1B] = bind(&CMA_EE::DIVU1, this); m_pOpSpecial2[0x28] = bind(&CMA_EE::MMI1, this); m_pOpSpecial2[0x29] = bind(&CMA_EE::MMI3, this); m_pOpSpecial2[0x34] = bind(&CMA_EE::PSLLH, this); m_pOpSpecial2[0x36] = bind(&CMA_EE::PSRLH, this); m_pOpSpecial2[0x37] = bind(&CMA_EE::PSRAH, this); m_pOpSpecial2[0x3F] = bind(&CMA_EE::PSRAW, this); SetupReflectionTables(); } CMA_EE::~CMA_EE() { } void CMA_EE::PushVector(unsigned int nReg) { m_codeGen->MD_PushRel(offsetof(CMIPS, m_State.nGPR[nReg])); } void CMA_EE::PullVector(unsigned int nReg) { m_codeGen->MD_PullRel(offsetof(CMIPS, m_State.nGPR[nReg])); } ////////////////////////////////////////////////// //General Opcodes ////////////////////////////////////////////////// //1E void CMA_EE::LQ() { ComputeMemAccessAddr(); for(unsigned int i = 0; i < 4; i++) { m_codeGen->PushRef(m_pCtx); m_codeGen->PushIdx(1); m_codeGen->Call(reinterpret_cast(&CMemoryUtils::GetWordProxy), 2, true); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[i])); if(i != 3) { m_codeGen->PushCst(4); m_codeGen->Add(); } } m_codeGen->PullTop(); } //1F void CMA_EE::SQ() { ComputeMemAccessAddr(); for(unsigned int i = 0; i < 4; i++) { m_codeGen->PushRef(m_pCtx); m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[i])); m_codeGen->PushIdx(2); m_codeGen->Call(reinterpret_cast(&CMemoryUtils::SetWordProxy), 3, false); if(i != 3) { m_codeGen->PushCst(4); m_codeGen->Add(); } } m_codeGen->PullTop(); } ////////////////////////////////////////////////// //RegImm Opcodes ////////////////////////////////////////////////// //18 void CMA_EE::MTSAB() { m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0])); m_codeGen->PushCst(0x0F); m_codeGen->And(); m_codeGen->PushCst(m_nImmediate & 0x0F); m_codeGen->Xor(); m_codeGen->Shl(0x03); m_codeGen->PullRel(offsetof(CMIPS, m_State.nSA)); } //19 void CMA_EE::MTSAH() { m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0])); m_codeGen->PushCst(0x07); m_codeGen->And(); m_codeGen->PushCst(m_nImmediate & 0x07); m_codeGen->Xor(); m_codeGen->Shl(0x04); m_codeGen->PullRel(offsetof(CMIPS, m_State.nSA)); } ////////////////////////////////////////////////// //Special Opcodes ////////////////////////////////////////////////// void CMA_EE::REEXCPT() { // m_pB->Call(CPS2OS::ExceptionReentry, 0, false); } ////////////////////////////////////////////////// //MMI Opcodes ////////////////////////////////////////////////// //00 void CMA_EE::MADD() { //prod = (HI || LO) + (RS * RT) //LO = sex(prod[0]) //HI = sex(prod[1]) //RD = LO size_t lo[2]; size_t hi[2]; unsigned int unit = 0; switch(unit) { case 0: lo[0] = offsetof(CMIPS, m_State.nLO[0]); lo[1] = offsetof(CMIPS, m_State.nLO[1]); hi[0] = offsetof(CMIPS, m_State.nHI[0]); hi[1] = offsetof(CMIPS, m_State.nHI[1]); break; case 1: lo[0] = offsetof(CMIPS, m_State.nLO1[0]); lo[1] = offsetof(CMIPS, m_State.nLO1[1]); hi[0] = offsetof(CMIPS, m_State.nHI1[0]); hi[1] = offsetof(CMIPS, m_State.nHI1[1]); break; default: throw runtime_error("Invalid unit number."); break; } m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0])); m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0])); m_codeGen->MultS(); //gives Stack(0) = LO, Stack(1) = HI m_codeGen->Swap(); m_codeGen->PushRel(lo[0]); m_codeGen->PushRel(hi[0]); m_codeGen->Add64(); m_codeGen->SeX(); m_codeGen->PullRel(hi[1]); m_codeGen->PullRel(hi[0]); m_codeGen->SeX(); m_codeGen->PullRel(lo[1]); m_codeGen->PullRel(lo[0]); if(m_nRD != 0) { m_codeGen->PushRel(lo[0]); m_codeGen->PushRel(lo[1]); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0])); } } //04 void CMA_EE::PLZCW() { for(unsigned int i = 0; i < 2; i++) { m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[i])); m_codeGen->Lzc(); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[i])); } } //08 void CMA_EE::MMI0() { ((this)->*(m_pOpMmi0[(m_nOpcode >> 6) & 0x1F]))(); } //09 void CMA_EE::MMI2() { ((this)->*(m_pOpMmi2[(m_nOpcode >> 6) & 0x1F]))(); } //10 void CMA_EE::MFHI1() { m_codeGen->PushRel(offsetof(CMIPS, m_State.nHI1[0])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0])); m_codeGen->PushRel(offsetof(CMIPS, m_State.nHI1[1])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1])); } //11 void CMA_EE::MTHI1() { m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nHI1[0])); m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nHI1[1])); } //12 void CMA_EE::MFLO1() { m_codeGen->PushRel(offsetof(CMIPS, m_State.nLO1[0])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0])); m_codeGen->PushRel(offsetof(CMIPS, m_State.nLO1[1])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1])); } //13 void CMA_EE::MTLO1() { m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nLO1[0])); m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nLO1[1])); } //18 void CMA_EE::MULT1() { Template_Mult32(bind(&CCodeGen::MultS, m_codeGen), 1); } //19 void CMA_EE::MULTU1() { Template_Mult32(bind(&CCodeGen::Mult, m_codeGen), 1); } //1A void CMA_EE::DIV1() { Template_Div32(bind(&CCodeGen::DivS, m_codeGen), 1); } //1B void CMA_EE::DIVU1() { Template_Div32(bind(&CCodeGen::Div, m_codeGen), 1); } //28 void CMA_EE::MMI1() { ((this)->*(m_pOpMmi1[(m_nOpcode >> 6) & 0x1F]))(); } //29 void CMA_EE::MMI3() { ((this)->*(m_pOpMmi3[(m_nOpcode >> 6) & 0x1F]))(); } //34 void CMA_EE::PSLLH() { PushVector(m_nRT); m_codeGen->MD_SllH(m_nSA); PullVector(m_nRD); } //36 void CMA_EE::PSRLH() { PushVector(m_nRT); m_codeGen->MD_SrlH(m_nSA); PullVector(m_nRD); } //37 void CMA_EE::PSRAH() { PushVector(m_nRT); m_codeGen->MD_SraH(m_nSA); PullVector(m_nRD); } //3F void CMA_EE::PSRAW() { PushVector(m_nRT); m_codeGen->MD_SraW(m_nSA); PullVector(m_nRD); } ////////////////////////////////////////////////// //MMI0 Opcodes ////////////////////////////////////////////////// //01 void CMA_EE::PSUBW() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_SubW(); PullVector(m_nRD); } //04 void CMA_EE::PADDH() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_AddH(); PullVector(m_nRD); } //06 void CMA_EE::PCGTH() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_CmpGtH(); PullVector(m_nRD); } //07 void CMA_EE::PMAXH() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_MaxH(); PullVector(m_nRD); } //09 void CMA_EE::PSUBB() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_SubB(); PullVector(m_nRD); } //10 void CMA_EE::PADDSW() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_AddWSS(); PullVector(m_nRD); } //12 void CMA_EE::PEXTLW() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_UnpackLowerWD(); PullVector(m_nRD); } //16 void CMA_EE::PEXTLH() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_UnpackLowerHW(); PullVector(m_nRD); } //17 void CMA_EE::PPACH() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_PackWH(); PullVector(m_nRD); } //1A void CMA_EE::PEXTLB() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_UnpackLowerBH(); PullVector(m_nRD); } //1B void CMA_EE::PPACB() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_PackHB(); PullVector(m_nRD); } //1E void CMA_EE::PEXT5() { for(unsigned int i = 0; i < 4; i++) { m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[i])); m_codeGen->PushCst(0x001F); m_codeGen->And(); m_codeGen->Shl(3); m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[i])); m_codeGen->PushCst(0x03E0); m_codeGen->And(); m_codeGen->Shl(6); m_codeGen->Or(); m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[i])); m_codeGen->PushCst(0x7C00); m_codeGen->And(); m_codeGen->Shl(9); m_codeGen->Or(); m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[i])); m_codeGen->PushCst(0x8000); m_codeGen->And(); m_codeGen->Shl(16); m_codeGen->Or(); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[i])); } } ////////////////////////////////////////////////// //MMI1 Opcodes ////////////////////////////////////////////////// //02 void CMA_EE::PCEQW() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_CmpEqW(); PullVector(m_nRD); } //07 void CMA_EE::PMINH() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_MinH(); PullVector(m_nRD); } //10 void CMA_EE::PADDUW() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_AddWUS(); PullVector(m_nRD); } //12 void CMA_EE::PEXTUW() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_UnpackUpperWD(); PullVector(m_nRD); } //1A void CMA_EE::PEXTUB() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_UnpackUpperBH(); PullVector(m_nRD); } //1B void CMA_EE::QFSRV() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->PushRel(offsetof(CMIPS, m_State.nSA)); m_codeGen->MD_Srl256(); PullVector(m_nRD); } ////////////////////////////////////////////////// //MMI2 Opcodes ////////////////////////////////////////////////// //0E void CMA_EE::PCPYLD() { //A0 m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0])); m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[3])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[2])); //B0 m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0])); m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0])); } //12 void CMA_EE::PAND() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_And(); PullVector(m_nRD); } //13 void CMA_EE::PXOR() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_Xor(); PullVector(m_nRD); } //1F void CMA_EE::PROT3W() { //3 m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[3])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[3])); //2 m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[2])); //1 m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[2])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1])); //0 m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0])); } ////////////////////////////////////////////////// //MMI3 Opcodes ////////////////////////////////////////////////// //0E void CMA_EE::PCPYUD() { //A m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[2])); m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[3])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0])); //B m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[2])); m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[3])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[3])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[2])); } //12 void CMA_EE::POR() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_Or(); PullVector(m_nRD); } //13 void CMA_EE::PNOR() { PushVector(m_nRS); PushVector(m_nRT); m_codeGen->MD_Or(); m_codeGen->MD_Not(); PullVector(m_nRD); } //1B void CMA_EE::PCPYH() { for(unsigned int i = 0; i < 4; i += 2) { m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[i])); m_codeGen->PushCst(0xFFFF); m_codeGen->And(); m_codeGen->PushTop(); m_codeGen->Shl(16); m_codeGen->Or(); m_codeGen->PushTop(); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[i + 0])); m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[i + 1])); } } ////////////////////////////////////////////////// //Opcode Tables ////////////////////////////////////////////////// CMA_EE::InstructionFuncConstant CMA_EE::m_pOpMmi0[0x20] = { //0x00 &Illegal, &PSUBW, &Illegal, &Illegal, &PADDH, &Illegal, &PCGTH, &PMAXH, //0x08 &Illegal, &PSUBB, &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, //0x10 &PADDSW, &Illegal, &PEXTLW, &Illegal, &Illegal, &Illegal, &PEXTLH, &PPACH, //0x18 &Illegal, &Illegal, &PEXTLB, &PPACB, &Illegal, &Illegal, &PEXT5, &Illegal, }; CMA_EE::InstructionFuncConstant CMA_EE::m_pOpMmi1[0x20] = { //0x00 &Illegal, &Illegal, &PCEQW, &Illegal, &Illegal, &Illegal, &Illegal, &PMINH, //0x08 &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, //0x10 &PADDUW, &Illegal, &PEXTUW, &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, //0x18 &Illegal, &Illegal, &PEXTUB, &QFSRV, &Illegal, &Illegal, &Illegal, &Illegal, }; CMA_EE::InstructionFuncConstant CMA_EE::m_pOpMmi2[0x20] = { //0x00 &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, //0x08 &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, &PCPYLD, &Illegal, //0x10 &Illegal, &Illegal, &PAND, &PXOR, &Illegal, &Illegal, &Illegal, &Illegal, //0x18 &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, &PROT3W, }; CMA_EE::InstructionFuncConstant CMA_EE::m_pOpMmi3[0x20] = { //0x00 &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, //0x08 &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, &Illegal, &PCPYUD, &Illegal, //0x10 &Illegal, &Illegal, &POR, &PNOR, &Illegal, &Illegal, &Illegal, &Illegal, //0x18 &Illegal, &Illegal, &Illegal, &PCPYH, &Illegal, &Illegal, &Illegal, &Illegal, };