// 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_); }
// if not mmx, then xmm int eeProcessHILO(int reg, int mode, int mmx) { // Fixme: MMX problem int usemmx = 0/*mmx && _hasFreeMMXreg()*/; if( (usemmx || _hasFreeXMMreg()) || !(g_pCurInstInfo->regs[reg]&EEINST_LASTUSE) ) { //if( usemmx ) return _allocMMXreg(-1, MMX_GPR+reg, mode); return _allocGPRtoXMMreg(-1, reg, mode); } return -1; }
// 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_); }
// EE XMM allocation code int eeRecompileCodeXMM(int xmminfo) { int info = PROCESS_EE_XMM; // flush consts if( xmminfo & XMMINFO_READT ) { if( GPR_IS_CONST1( _Rt_ ) && !(g_cpuFlushedConstReg&(1<<_Rt_)) ) { MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); g_cpuFlushedConstReg |= (1<<_Rt_); } } if( xmminfo & XMMINFO_READS) { if( GPR_IS_CONST1( _Rs_ ) && !(g_cpuFlushedConstReg&(1<<_Rs_)) ) { MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); g_cpuFlushedConstReg |= (1<<_Rs_); } } if( xmminfo & XMMINFO_WRITED ) { GPR_DEL_CONST(_Rd_); } // add needed if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { _addNeededGPRtoXMMreg(XMMGPR_LO); } if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { _addNeededGPRtoXMMreg(XMMGPR_HI); } if( xmminfo & XMMINFO_READS) _addNeededGPRtoXMMreg(_Rs_); if( xmminfo & XMMINFO_READT) _addNeededGPRtoXMMreg(_Rt_); if( xmminfo & XMMINFO_WRITED ) _addNeededGPRtoXMMreg(_Rd_); // allocate if( xmminfo & XMMINFO_READS) { int reg = _allocGPRtoXMMreg(-1, _Rs_, MODE_READ); info |= PROCESS_EE_SET_S(reg)|PROCESS_EE_SETMODES(reg); } if( xmminfo & XMMINFO_READT) { int reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ); info |= PROCESS_EE_SET_T(reg)|PROCESS_EE_SETMODET(reg); } if( xmminfo & XMMINFO_WRITED ) { int readd = MODE_WRITE|((xmminfo&XMMINFO_READD)?((xmminfo&XMMINFO_READD_LO)?(MODE_READ|MODE_READHALF):MODE_READ):0); int regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, readd); if( regd < 0 ) { if( !(xmminfo&XMMINFO_READD) && (xmminfo & XMMINFO_READT) && (_Rt_ == 0 || (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_)) ) { _freeXMMreg(EEREC_T); _deleteMMXreg(MMX_GPR+_Rd_, 2); xmmregs[EEREC_T].inuse = 1; xmmregs[EEREC_T].reg = _Rd_; xmmregs[EEREC_T].mode = readd; regd = EEREC_T; } else if( !(xmminfo&XMMINFO_READD) && (xmminfo & XMMINFO_READS) && (_Rs_ == 0 || (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_)) ) { _freeXMMreg(EEREC_S); _deleteMMXreg(MMX_GPR+_Rd_, 2); xmmregs[EEREC_S].inuse = 1; xmmregs[EEREC_S].reg = _Rd_; xmmregs[EEREC_S].mode = readd; regd = EEREC_S; } else regd = _allocGPRtoXMMreg(-1, _Rd_, readd); } info |= PROCESS_EE_SET_D(regd); } if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { info |= PROCESS_EE_SET_LO(_allocGPRtoXMMreg(-1, XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0))); info |= PROCESS_EE_LO; } if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { info |= PROCESS_EE_SET_HI(_allocGPRtoXMMreg(-1, XMMGPR_HI, ((xmminfo&XMMINFO_READHI)?MODE_READ:0)|((xmminfo&XMMINFO_WRITEHI)?MODE_WRITE:0))); info |= PROCESS_EE_HI; } return info; }
int _allocCheckGPRtoXMM(EEINST* pinst, int gprreg, int mode) { if( pinst->regs[gprreg] & EEINST_XMM ) return _allocGPRtoXMMreg(-1, gprreg, mode); return _checkXMMreg(XMMTYPE_GPRREG, gprreg, mode); }