// rd = rs op rt void eeFPURecompileCode(R5900FNPTR_INFO xmmcode, R5900FNPTR fpucode, int xmminfo) { int mmregs=-1, mmregt=-1, mmregd=-1, mmregacc=-1; int info = PROCESS_EE_XMM; if( xmminfo & XMMINFO_READS ) _addNeededFPtoXMMreg(_Fs_); if( xmminfo & XMMINFO_READT ) _addNeededFPtoXMMreg(_Ft_); if( xmminfo & (XMMINFO_WRITED|XMMINFO_READD) ) _addNeededFPtoXMMreg(_Fd_); if( xmminfo & (XMMINFO_WRITEACC|XMMINFO_READACC) ) _addNeededFPACCtoXMMreg(); if( xmminfo & XMMINFO_READT ) { if( g_pCurInstInfo->fpuregs[_Ft_] & EEINST_LASTUSE ) mmregt = _checkXMMreg(XMMTYPE_FPREG, _Ft_, MODE_READ); else mmregt = _allocFPtoXMMreg(-1, _Ft_, MODE_READ); } if( xmminfo & XMMINFO_READS ) { if( ( !(xmminfo & XMMINFO_READT) || (mmregt >= 0) ) && (g_pCurInstInfo->fpuregs[_Fs_] & EEINST_LASTUSE) ) { mmregs = _checkXMMreg(XMMTYPE_FPREG, _Fs_, MODE_READ); } else mmregs = _allocFPtoXMMreg(-1, _Fs_, MODE_READ); } if( mmregs >= 0 ) info |= PROCESS_EE_SETMODES_XMM(mmregs); if( mmregt >= 0 ) info |= PROCESS_EE_SETMODET_XMM(mmregt); if( xmminfo & XMMINFO_READD ) { pxAssert( xmminfo & XMMINFO_WRITED ); mmregd = _allocFPtoXMMreg(-1, _Fd_, MODE_READ); } if( xmminfo & XMMINFO_READACC ) { if( !(xmminfo&XMMINFO_WRITEACC) && (g_pCurInstInfo->fpuregs[_Ft_] & EEINST_LASTUSE) ) mmregacc = _checkXMMreg(XMMTYPE_FPACC, 0, MODE_READ); else mmregacc = _allocFPACCtoXMMreg(-1, MODE_READ); } if( xmminfo & XMMINFO_WRITEACC ) { // check for last used, if so don't alloc a new XMM reg int readacc = MODE_WRITE|((xmminfo&XMMINFO_READACC)?MODE_READ:0); mmregacc = _checkXMMreg(XMMTYPE_FPACC, 0, readacc); if( mmregacc < 0 ) { if( (xmminfo&XMMINFO_READT) && mmregt >= 0 && (FPUINST_LASTUSE(_Ft_) || !FPUINST_ISLIVE(_Ft_)) ) { if( FPUINST_ISLIVE(_Ft_) ) { _freeXMMreg(mmregt); info &= ~PROCESS_EE_MODEWRITET; } _deleteMMXreg(MMX_FPU+XMMFPU_ACC, 2); xmmregs[mmregt].inuse = 1; xmmregs[mmregt].reg = 0; xmmregs[mmregt].mode = readacc; xmmregs[mmregt].type = XMMTYPE_FPACC; mmregacc = mmregt; } else if( (xmminfo&XMMINFO_READS) && mmregs >= 0 && (FPUINST_LASTUSE(_Fs_) || !FPUINST_ISLIVE(_Fs_)) ) { if( FPUINST_ISLIVE(_Fs_) ) { _freeXMMreg(mmregs); info &= ~PROCESS_EE_MODEWRITES; } _deleteMMXreg(MMX_FPU+XMMFPU_ACC, 2); xmmregs[mmregs].inuse = 1; xmmregs[mmregs].reg = 0; xmmregs[mmregs].mode = readacc; xmmregs[mmregs].type = XMMTYPE_FPACC; mmregacc = mmregs; } else mmregacc = _allocFPACCtoXMMreg(-1, readacc); } xmmregs[mmregacc].mode |= MODE_WRITE; } else if( xmminfo & XMMINFO_WRITED ) { // check for last used, if so don't alloc a new XMM reg int readd = MODE_WRITE|((xmminfo&XMMINFO_READD)?MODE_READ:0); if( xmminfo&XMMINFO_READD ) mmregd = _allocFPtoXMMreg(-1, _Fd_, readd); else mmregd = _checkXMMreg(XMMTYPE_FPREG, _Fd_, readd); if( mmregd < 0 ) { if( (xmminfo&XMMINFO_READT) && mmregt >= 0 && (FPUINST_LASTUSE(_Ft_) || !FPUINST_ISLIVE(_Ft_)) ) { if( FPUINST_ISLIVE(_Ft_) ) { _freeXMMreg(mmregt); info &= ~PROCESS_EE_MODEWRITET; } _deleteMMXreg(MMX_FPU+_Fd_, 2); xmmregs[mmregt].inuse = 1; xmmregs[mmregt].reg = _Fd_; xmmregs[mmregt].mode = readd; mmregd = mmregt; } else if( (xmminfo&XMMINFO_READS) && mmregs >= 0 && (FPUINST_LASTUSE(_Fs_) || !FPUINST_ISLIVE(_Fs_)) ) { if( FPUINST_ISLIVE(_Fs_) ) { _freeXMMreg(mmregs); info &= ~PROCESS_EE_MODEWRITES; } _deleteMMXreg(MMX_FPU+_Fd_, 2); xmmregs[mmregs].inuse = 1; xmmregs[mmregs].reg = _Fd_; xmmregs[mmregs].mode = readd; mmregd = mmregs; } else if( (xmminfo&XMMINFO_READACC) && mmregacc >= 0 && (FPUINST_LASTUSE(XMMFPU_ACC) || !FPUINST_ISLIVE(XMMFPU_ACC)) ) { if( FPUINST_ISLIVE(XMMFPU_ACC) ) _freeXMMreg(mmregacc); _deleteMMXreg(MMX_FPU+_Fd_, 2); xmmregs[mmregacc].inuse = 1; xmmregs[mmregacc].reg = _Fd_; xmmregs[mmregacc].mode = readd; xmmregs[mmregacc].type = XMMTYPE_FPREG; mmregd = mmregacc; } else mmregd = _allocFPtoXMMreg(-1, _Fd_, readd); } } pxAssert( mmregs >= 0 || mmregt >= 0 || mmregd >= 0 || mmregacc >= 0 ); if( xmminfo & XMMINFO_WRITED ) { pxAssert( mmregd >= 0 ); info |= PROCESS_EE_SET_D(mmregd); } if( xmminfo & (XMMINFO_WRITEACC|XMMINFO_READACC) ) { if( mmregacc >= 0 ) info |= PROCESS_EE_SET_ACC(mmregacc)|PROCESS_EE_ACC; else pxAssert( !(xmminfo&XMMINFO_WRITEACC)); } if( xmminfo & XMMINFO_READS ) { if( mmregs >= 0 ) info |= PROCESS_EE_SET_S(mmregs)|PROCESS_EE_S; } if( xmminfo & XMMINFO_READT ) { if( mmregt >= 0 ) info |= PROCESS_EE_SET_T(mmregt)|PROCESS_EE_T; } // at least one must be in xmm if( (xmminfo & (XMMINFO_READS|XMMINFO_READT)) == (XMMINFO_READS|XMMINFO_READT) ) { pxAssert( mmregs >= 0 || mmregt >= 0 ); } xmmcode(info); _clearNeededXMMregs(); }
int _allocCheckFPUtoXMM(EEINST* pinst, int fpureg, int mode) { if( pinst->fpuregs[fpureg] & EEINST_XMM ) return _allocFPtoXMMreg(-1, fpureg, mode); return _checkXMMreg(XMMTYPE_FPREG, fpureg, mode); }