// rd = rt op sa void eeRecompileCode2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) { int mmreg1, mmreg2; if ( ! _Rd_ ) return; if( GPR_IS_CONST1(_Rt_) ) { _deleteMMXreg(MMX_GPR+_Rd_, 2); _deleteGPRtoXMMreg(_Rd_, 2); GPR_SET_CONST(_Rd_); constcode(); return; } // test if should write xmm, mirror to mmx code if( g_pCurInstInfo->info & EEINST_XMM ) { // no const regs mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_READ); if( mmreg1 >= 0 ) { int info = PROCESS_EE_XMM|PROCESS_EE_SETMODET(mmreg1); // check for last used, if so don't alloc a new XMM reg _addNeededGPRtoXMMreg(_Rd_); mmreg2 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE); if( mmreg2 < 0 ) { if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVE64(_Rt_) ) { _freeXMMreg(mmreg1); info &= ~PROCESS_EE_MODEWRITET; _deleteMMXreg(MMX_GPR+_Rd_, 2); xmmregs[mmreg1].inuse = 1; xmmregs[mmreg1].reg = _Rd_; xmmregs[mmreg1].mode = MODE_WRITE|MODE_READ; mmreg2 = mmreg1; } else mmreg2 = _allocGPRtoXMMreg(-1, _Rd_, MODE_WRITE); } noconstcode(info|PROCESS_EE_SET_T(mmreg1)|PROCESS_EE_SET_D(mmreg2)); _clearNeededXMMregs(); GPR_DEL_CONST(_Rd_); return; } _clearNeededXMMregs(); } // regular x86 _deleteGPRtoXMMreg(_Rt_, 1); _deleteGPRtoXMMreg(_Rd_, 2); _deleteMMXreg(MMX_GPR+_Rt_, 1); _deleteMMXreg(MMX_GPR+_Rd_, 2); noconstcode(0); GPR_DEL_CONST(_Rd_); }
else SSE_MOVLPS_M64_to_XMM(reglo, (uptr)ptr); } else { MOV32ItoM(loaddr, res & 0xffffffff); MOV32ItoM(loaddr+4, (res&0x80000000)?0xffffffff:0); } } } if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) { if( !upper && (reghi = _allocCheckGPRtoMMX(g_pCurInstInfo, XMMGPR_HI, MODE_WRITE)) >= 0 ) { MOVQMtoR(reghi, (uptr)recGetImm64(res >> 63 ? -1 : 0, res >> 32)); } else { reghi = _allocCheckGPRtoXMM(g_pCurInstInfo, XMMGPR_HI, MODE_WRITE|MODE_READ); if( reghi >= 0 ) { u32* ptr = recGetImm64(res >> 63 ? -1 : 0, res >> 32); if( upper ) SSE_MOVHPS_M64_to_XMM(reghi, (u32)ptr); else SSE_MOVLPS_M64_to_XMM(reghi, (u32)ptr); } else { _deleteEEreg(XMMGPR_HI, 0); MOV32ItoM(hiaddr, res >> 32); MOV32ItoM(hiaddr+4, (res>>63)?0xffffffff:0); } } } if (!writed || !_Rd_) return;
// ignores XMMINFO_READS, XMMINFO_READT, and XMMINFO_READD_LO from xmminfo // core of reg caching void eeRecompileCode0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode, int xmminfo) { int mmreg1, mmreg2, mmreg3, mmtemp, moded; if ( ! _Rd_ && (xmminfo&XMMINFO_WRITED) ) return; if( GPR_IS_CONST2(_Rs_, _Rt_) ) { if( xmminfo & XMMINFO_WRITED ) { _deleteMMXreg(MMX_GPR+_Rd_, 2); _deleteGPRtoXMMreg(_Rd_, 2); } if( xmminfo&XMMINFO_WRITED ) GPR_SET_CONST(_Rd_); constcode(); return; } moded = MODE_WRITE|((xmminfo&XMMINFO_READD)?MODE_READ:0); // test if should write xmm, mirror to mmx code if( g_pCurInstInfo->info & EEINST_XMM ) { if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) _addNeededGPRtoXMMreg(XMMGPR_LO); if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) _addNeededGPRtoXMMreg(XMMGPR_HI); _addNeededGPRtoXMMreg(_Rs_); _addNeededGPRtoXMMreg(_Rt_); if( GPR_IS_CONST1(_Rs_) || GPR_IS_CONST1(_Rt_) ) { int creg = GPR_IS_CONST1(_Rs_) ? _Rs_ : _Rt_; int vreg = creg == _Rs_ ? _Rt_ : _Rs_; // if(g_pCurInstInfo->regs[vreg]&EEINST_XMM) { // mmreg1 = _allocGPRtoXMMreg(-1, vreg, MODE_READ); // _addNeededGPRtoXMMreg(vreg); // } mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, vreg, MODE_READ); if( mmreg1 >= 0 ) { int info = PROCESS_EE_XMM; if( GPR_IS_CONST1(_Rs_) ) info |= PROCESS_EE_SETMODET(mmreg1); else info |= PROCESS_EE_SETMODES(mmreg1); if( xmminfo & XMMINFO_WRITED ) { _addNeededGPRtoXMMreg(_Rd_); mmreg3 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE); if( !(xmminfo&XMMINFO_READD) && mmreg3 < 0 && ((g_pCurInstInfo->regs[vreg] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(vreg)) ) { _freeXMMreg(mmreg1); if( GPR_IS_CONST1(_Rs_) ) info &= ~PROCESS_EE_MODEWRITET; else info &= ~PROCESS_EE_MODEWRITES; _deleteMMXreg(MMX_GPR+_Rd_, 2); xmmregs[mmreg1].inuse = 1; xmmregs[mmreg1].reg = _Rd_; xmmregs[mmreg1].mode = moded; mmreg3 = mmreg1; } else if( mmreg3 < 0 ) mmreg3 = _allocGPRtoXMMreg(-1, _Rd_, moded); info |= PROCESS_EE_SET_D(mmreg3); } if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { mmtemp = eeProcessHILO(XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); } if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { mmtemp = eeProcessHILO(XMMGPR_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); } if( creg == _Rs_ ) constscode(info|PROCESS_EE_SET_T(mmreg1)); else consttcode(info|PROCESS_EE_SET_S(mmreg1)); _clearNeededXMMregs(); if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); return; } } else { // no const regs mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rs_, MODE_READ); mmreg2 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_READ); if( mmreg1 >= 0 || mmreg2 >= 0 ) { int info = PROCESS_EE_XMM; // do it all in xmm if( mmreg1 < 0 ) mmreg1 = _allocGPRtoXMMreg(-1, _Rs_, MODE_READ); if( mmreg2 < 0 ) mmreg2 = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ); info |= PROCESS_EE_SETMODES(mmreg1)|PROCESS_EE_SETMODET(mmreg2); if( xmminfo & XMMINFO_WRITED ) { // check for last used, if so don't alloc a new XMM reg _addNeededGPRtoXMMreg(_Rd_); mmreg3 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, moded); if( mmreg3 < 0 ) { if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_)) ) { _freeXMMreg(mmreg2); info &= ~PROCESS_EE_MODEWRITET; _deleteMMXreg(MMX_GPR+_Rd_, 2); xmmregs[mmreg2].inuse = 1; xmmregs[mmreg2].reg = _Rd_; xmmregs[mmreg2].mode = moded; mmreg3 = mmreg2; } else if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_)) ) { _freeXMMreg(mmreg1); info &= ~PROCESS_EE_MODEWRITES; _deleteMMXreg(MMX_GPR+_Rd_, 2); xmmregs[mmreg1].inuse = 1; xmmregs[mmreg1].reg = _Rd_; xmmregs[mmreg1].mode = moded; mmreg3 = mmreg1; } else mmreg3 = _allocGPRtoXMMreg(-1, _Rd_, moded); } info |= PROCESS_EE_SET_D(mmreg3); } if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { mmtemp = eeProcessHILO(XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); } if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { mmtemp = eeProcessHILO(XMMGPR_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); } noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); _clearNeededXMMregs(); if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); return; } } _clearNeededXMMregs(); } // regular x86 _deleteGPRtoXMMreg(_Rs_, 1); _deleteGPRtoXMMreg(_Rt_, 1); if( xmminfo&XMMINFO_WRITED ) _deleteGPRtoXMMreg(_Rd_, (xmminfo&XMMINFO_READD)?0:2); _deleteMMXreg(MMX_GPR+_Rs_, 1); _deleteMMXreg(MMX_GPR+_Rt_, 1); if( xmminfo&XMMINFO_WRITED ) _deleteMMXreg(MMX_GPR+_Rd_, (xmminfo&XMMINFO_READD)?0:2); // don't delete, fn will take care of them // if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { // _deleteGPRtoXMMreg(XMMGPR_LO, (xmminfo&XMMINFO_READLO)?1:0); // _deleteMMXreg(MMX_GPR+MMX_LO, (xmminfo&XMMINFO_READLO)?1:0); // } // if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { // _deleteGPRtoXMMreg(XMMGPR_HI, (xmminfo&XMMINFO_READHI)?1:0); // _deleteMMXreg(MMX_GPR+MMX_HI, (xmminfo&XMMINFO_READHI)?1:0); // } if( GPR_IS_CONST1(_Rs_) ) { constscode(0); if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); return; } if( GPR_IS_CONST1(_Rt_) ) { consttcode(0); if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); return; } noconstcode(0); if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); }