int _getFreeXMMreg() { int i, tempi; u32 bestcount = 0x10000; for (i=0; (uint)i<iREGCNT_XMM; i++) { if (xmmregs[(i+s_xmmchecknext)%iREGCNT_XMM].inuse == 0) { int ret = (s_xmmchecknext+i)%iREGCNT_XMM; s_xmmchecknext = (s_xmmchecknext+i+1)%iREGCNT_XMM; return ret; } } // check for dead regs for (i=0; (uint)i<iREGCNT_XMM; i++) { if (xmmregs[i].needed) continue; if (xmmregs[i].type == XMMTYPE_GPRREG ) { if (!(EEINST_ISLIVEXMM(xmmregs[i].reg))) { _freeXMMreg(i); return i; } } } // check for future xmm usage for (i=0; (uint)i<iREGCNT_XMM; i++) { if (xmmregs[i].needed) continue; if (xmmregs[i].type == XMMTYPE_GPRREG ) { if( !(g_pCurInstInfo->regs[xmmregs[i].reg] & EEINST_XMM) ) { _freeXMMreg(i); return i; } } } tempi = -1; bestcount = 0xffff; for (i=0; (uint)i<iREGCNT_XMM; i++) { if (xmmregs[i].needed) continue; if (xmmregs[i].type != XMMTYPE_TEMP) { if( xmmregs[i].counter < bestcount ) { tempi = i; bestcount = xmmregs[i].counter; } continue; } _freeXMMreg(i); return i; } if( tempi != -1 ) { _freeXMMreg(tempi); return tempi; } Console.Error("*PCSX2*: XMM Reg Allocation Error in _getFreeXMMreg()!"); return -1; }
void _deleteFPtoXMMreg(int reg, int flush) { int i; for (i=0; (uint)i<iREGCNT_XMM; i++) { if (xmmregs[i].inuse && xmmregs[i].type == XMMTYPE_FPREG && xmmregs[i].reg == reg ) { switch(flush) { case 0: _freeXMMreg(i); return; case 1: if (xmmregs[i].mode & MODE_WRITE) { SSE_MOVSS_XMM_to_M32((uptr)&fpuRegs.fpr[reg].UL, i); // get rid of MODE_WRITE since don't want to flush again xmmregs[i].mode &= ~MODE_WRITE; xmmregs[i].mode |= MODE_READ; } return; case 2: xmmregs[i].inuse = 0; return; } } } }
// when flush is 1 or 2, only commits the reg to mem (still leave its xmm entry) void _deleteGPRtoXMMreg(int reg, int flush) { int i; for (i=0; (uint)i<iREGCNT_XMM; i++) { if (xmmregs[i].inuse && xmmregs[i].type == XMMTYPE_GPRREG && xmmregs[i].reg == reg ) { switch(flush) { case 0: _freeXMMreg(i); break; case 1: case 2: if( xmmregs[i].mode & MODE_WRITE ) { pxAssert( reg != 0 ); //pxAssert( g_xmmtypes[i] == XMMT_INT ); SSEX_MOVDQA_XMM_to_M128((uptr)&cpuRegs.GPR.r[reg].UL[0], i); // get rid of MODE_WRITE since don't want to flush again xmmregs[i].mode &= ~MODE_WRITE; xmmregs[i].mode |= MODE_READ; } if( flush == 2 ) xmmregs[i].inuse = 0; break; } return; } } }
void _deleteACCtoXMMreg(int vu, int flush) { int i; VURegs *VU = vu ? &VU1 : &VU0; for (i=0; (uint)i<iREGCNT_XMM; i++) { if (xmmregs[i].inuse && (xmmregs[i].type == XMMTYPE_ACC) && (xmmregs[i].VU == vu)) { switch(flush) { case 0: _freeXMMreg(i); break; case 1: case 2: if( xmmregs[i].mode & MODE_WRITE ) { if( xmmregs[i].mode & MODE_VUXYZ ) { if( xmmregs[i].mode & MODE_VUZ ) { // xyz, don't destroy w uint t0reg; for(t0reg = 0; t0reg < iREGCNT_XMM; ++t0reg ) { if( !xmmregs[t0reg].inuse ) break; } if( t0reg < iREGCNT_XMM ) { SSE_MOVHLPS_XMM_to_XMM(t0reg, i); SSE_MOVLPS_XMM_to_M64(VU_ACCx_ADDR, i); SSE_MOVSS_XMM_to_M32(VU_ACCx_ADDR+8, t0reg); } else { // no free reg SSE_MOVLPS_XMM_to_M64(VU_ACCx_ADDR, i); SSE_SHUFPS_XMM_to_XMM(i, i, 0xc6); //SSE_MOVHLPS_XMM_to_XMM(i, i); SSE_MOVSS_XMM_to_M32(VU_ACCx_ADDR+8, i); SSE_SHUFPS_XMM_to_XMM(i, i, 0xc6); } } else { // xy SSE_MOVLPS_XMM_to_M64(VU_ACCx_ADDR, i); } } else SSE_MOVAPS_XMM_to_M128(VU_ACCx_ADDR, i); // get rid of MODE_WRITE since don't want to flush again xmmregs[i].mode &= ~MODE_WRITE; xmmregs[i].mode |= MODE_READ; } if( flush == 2 ) xmmregs[i].inuse = 0; break; } return; } } }
// 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_); }
int _allocACCtoXMMreg(VURegs *VU, int xmmreg, int mode) { int i; int readfromreg = -1; for (i=0; (uint)i<iREGCNT_XMM; i++) { if (xmmregs[i].inuse == 0) continue; if (xmmregs[i].type != XMMTYPE_ACC) continue; if (xmmregs[i].VU != XMM_CONV_VU(VU) ) continue; if( xmmreg >= 0 ) { // requested specific reg, so return that instead if( i != xmmreg ) { if( xmmregs[i].mode & MODE_READ ) readfromreg = i; //if( xmmregs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; mode |= xmmregs[i].mode&MODE_WRITE; xmmregs[i].inuse = 0; break; } } if( !(xmmregs[i].mode & MODE_READ) && (mode&MODE_READ)) { SSE_MOVAPS_M128_to_XMM(i, VU_ACCx_ADDR); xmmregs[i].mode |= MODE_READ; } g_xmmtypes[i] = XMMT_FPS; xmmregs[i].counter = g_xmmAllocCounter++; // update counter xmmregs[i].needed = 1; xmmregs[i].mode|= mode; return i; } if (xmmreg == -1) xmmreg = _getFreeXMMreg(); else _freeXMMreg(xmmreg); g_xmmtypes[xmmreg] = XMMT_FPS; xmmregs[xmmreg].inuse = 1; xmmregs[xmmreg].type = XMMTYPE_ACC; xmmregs[xmmreg].mode = mode; xmmregs[xmmreg].needed = 1; xmmregs[xmmreg].VU = XMM_CONV_VU(VU); xmmregs[xmmreg].counter = g_xmmAllocCounter++; xmmregs[xmmreg].reg = 0; if (mode & MODE_READ) { if( readfromreg >= 0 ) SSE_MOVAPS_XMM_to_XMM(xmmreg, readfromreg); else SSE_MOVAPS_M128_to_XMM(xmmreg, VU_ACCx_ADDR); } return xmmreg; }
void _freeXMMregs() { int i; for (i=0; (uint)i<iREGCNT_XMM; i++) { if (xmmregs[i].inuse == 0) continue; pxAssert( xmmregs[i].type != XMMTYPE_TEMP ); //pxAssert( xmmregs[i].mode & (MODE_READ|MODE_WRITE) ); _freeXMMreg(i); } }
int _allocTempXMMreg(XMMSSEType type, int xmmreg) { if (xmmreg == -1) xmmreg = _getFreeXMMreg(); else _freeXMMreg(xmmreg); xmmregs[xmmreg].inuse = 1; xmmregs[xmmreg].type = XMMTYPE_TEMP; xmmregs[xmmreg].needed = 1; xmmregs[xmmreg].counter = g_xmmAllocCounter++; g_xmmtypes[xmmreg] = type; return xmmreg; }
void _moveXMMreg(int xmmreg) { int i; if( !xmmregs[xmmreg].inuse ) return; for (i=0; (uint)i<iREGCNT_XMM; i++) { if (xmmregs[i].inuse) continue; break; } if( i == iREGCNT_XMM ) { _freeXMMreg(xmmreg); return; } // move xmmregs[i] = xmmregs[xmmreg]; xmmregs[xmmreg].inuse = 0; SSEX_MOVDQA_XMM_to_XMM(i, xmmreg); }
// 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_); }
// 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(); }
// 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; }