pcsx2/ix86-32/iR5900Shift.c
2007-04-02 01:06:17 +00:00

1349 lines
31 KiB
C

/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2003 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "Common.h"
#include "InterTables.h"
#include "ix86/ix86.h"
#include "iR5900.h"
#ifdef __WIN32__
#pragma warning(disable:4244)
#pragma warning(disable:4761)
#endif
/*********************************************************
* Shift arithmetic with constant shift *
* Format: OP rd, rt, sa *
*********************************************************/
#ifndef SHIFT_RECOMPILE
REC_FUNC(SLL);
REC_FUNC(SRL);
REC_FUNC(SRA);
REC_FUNC(DSLL);
REC_FUNC(DSRL);
REC_FUNC(DSRA);
REC_FUNC(DSLL32);
REC_FUNC(DSRL32);
REC_FUNC(DSRA32);
REC_FUNC(SLLV);
REC_FUNC(SRLV);
REC_FUNC(SRAV);
REC_FUNC(DSLLV);
REC_FUNC(DSRLV);
REC_FUNC(DSRAV);
#elif defined(EE_CONST_PROP)
//// SLL
void recSLL_const()
{
g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] << _Sa_);
}
void recSLLs_(int info, int sa)
{
int rtreg, rdreg, t0reg;
assert( !(info & PROCESS_EE_XMM) );
if( info & PROCESS_EE_MMX ) {
rtreg = EEREC_T;
rdreg = EEREC_D;
}
else if( g_pCurInstInfo->regs[_Rd_]&EEINST_MMX ) {
_addNeededMMXreg(MMX_GPR+_Rd_);
rtreg = rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
SetMMXstate();
MOVDMtoMMX(rtreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]);
}
else {
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
if ( sa != 0 )
{
SHL32ItoR( EAX, sa );
}
if( EEINST_ISLIVE1(_Rd_) ) {
CDQ( );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
else {
EEINST_RESETHASLIVE1(_Rd_);
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
}
return;
}
if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg);
if( !EEINST_ISLIVE1(_Rd_) ) {
EEINST_RESETHASLIVE1(_Rd_);
PSLLDItoR(rdreg, sa);
return;
}
if ( sa != 0 ) {
t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
// it is a signed shift
PSLLDItoR(rdreg, sa);
MOVQRtoR(t0reg, rdreg);
PSRADItoR(t0reg, 31);
// take lower dword of rdreg and lower dword of t0reg
PUNPCKLDQRtoR(rdreg, t0reg);
_freeMMXreg(t0reg);
}
else {
if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(rdreg, _Rd_, 0);
else EEINST_RESETHASLIVE1(_Rd_);
}
}
void recSLL_(int info)
{
recSLLs_(info, _Sa_);
EEINST_SETSIGNEXT(_Rd_);
}
EERECOMPILE_CODEX(eeRecompileCode2, SLL);
//// SRL
void recSRL_const()
{
g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] >> _Sa_);
}
void recSRLs_(int info, int sa)
{
int rtreg, rdreg;
assert( !(info & PROCESS_EE_XMM) );
if( info & PROCESS_EE_MMX ) {
rtreg = EEREC_T;
rdreg = EEREC_D;
}
else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) {
_addNeededMMXreg(MMX_GPR+_Rd_);
rtreg = rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
SetMMXstate();
MOVDMtoMMX(rtreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]);
}
else {
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
if ( sa != 0 ) SHR32ItoR( EAX, sa);
if( EEINST_ISLIVE1(_Rd_) ) {
CDQ( );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
else {
EEINST_RESETHASLIVE1(_Rd_);
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
}
return;
}
if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg);
if( !EEINST_ISLIVE1(_Rd_) ) {
EEINST_RESETHASLIVE1(_Rd_);
PSRLDItoR(rdreg, sa);
return;
}
if ( sa != 0 ) {
// rdreg already sign extended
PSLLQItoR(rdreg, 32);
PSRLQItoR(rdreg, 32+sa);
// t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
//
// // it is a signed shift
// PSRLDItoR(rdreg, sa);
// MOVQRtoR(t0reg, rdreg);
// PSRADItoR(t0reg, 31);
//
// take lower dword of rdreg and lower dword of t0reg
// PUNPCKLDQRtoR(rdreg, t0reg);
// _freeMMXreg(t0reg);
}
}
void recSRL_(int info)
{
recSRLs_(info, _Sa_);
EEINST_SETSIGNEXT(_Rd_);
}
EERECOMPILE_CODEX(eeRecompileCode2, SRL);
//// SRA
void recSRA_const()
{
g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].SL[0] >> _Sa_);
}
void recSRAs_(int info, int sa)
{
int rtreg, rdreg, t0reg;
assert( !(info & PROCESS_EE_XMM) );
if( info & PROCESS_EE_MMX ) {
rtreg = EEREC_T;
rdreg = EEREC_D;
}
else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) {
_addNeededMMXreg(MMX_GPR+_Rd_);
rtreg = rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
SetMMXstate();
MOVDMtoMMX(rtreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]);
}
else {
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
if ( sa != 0 ) SAR32ItoR( EAX, sa);
if( EEINST_ISLIVE1(_Rd_) ) {
CDQ();
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
else {
EEINST_RESETHASLIVE1(_Rd_);
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
}
return;
}
if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg);
if( EEINST_ISSIGNEXT(_Rt_) && EEINST_HASLIVE1(_Rt_) ) {
PSRADItoR(rdreg, sa);
return;
}
if( !EEINST_ISLIVE1(_Rd_) ) {
EEINST_RESETHASLIVE1(_Rd_);
PSRADItoR(rdreg, sa);
return;
}
if ( sa != 0 ) {
t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
// it is a signed shift
PSRADItoR(rdreg, sa);
MOVQRtoR(t0reg, rdreg);
PSRADItoR(rdreg, 31);
// take lower dword of rdreg and lower dword of t0reg
PUNPCKLDQRtoR(t0reg, rdreg);
// swap regs
mmxregs[t0reg] = mmxregs[rdreg];
mmxregs[rdreg].inuse = 0;
}
}
void recSRA_(int info)
{
recSRAs_(info, _Sa_);
EEINST_SETSIGNEXT(_Rd_);
}
EERECOMPILE_CODEX(eeRecompileCode2, SRA);
////////////////////////////////////////////////////
void recDSLL_const()
{
g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] << _Sa_);
}
void recDSLLs_(int info, int sa)
{
int rtreg, rdreg;
assert( !(info & PROCESS_EE_XMM) );
if( info & PROCESS_EE_MMX ) {
rtreg = EEREC_T;
rdreg = EEREC_D;
}
else {
_addNeededMMXreg(MMX_GPR+_Rt_);
_addNeededMMXreg(MMX_GPR+_Rd_);
rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ);
rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
SetMMXstate();
}
if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg);
PSLLQItoR(rdreg, sa);
}
void recDSLL_(int info)
{
recDSLLs_(info, _Sa_);
}
EERECOMPILE_CODEX(eeRecompileCode2, DSLL);
////////////////////////////////////////////////////
void recDSRL_const()
{
g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] >> _Sa_);
}
void recDSRLs_(int info, int sa)
{
int rtreg, rdreg;
assert( !(info & PROCESS_EE_XMM) );
if( info & PROCESS_EE_MMX ) {
rtreg = EEREC_T;
rdreg = EEREC_D;
}
else {
_addNeededMMXreg(MMX_GPR+_Rt_);
_addNeededMMXreg(MMX_GPR+_Rd_);
rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ);
rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
SetMMXstate();
}
if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg);
PSRLQItoR(rdreg, sa);
}
void recDSRL_(int info)
{
recDSRLs_(info, _Sa_);
}
EERECOMPILE_CODEX(eeRecompileCode2, DSRL);
//// DSRA
void recDSRA_const()
{
g_cpuConstRegs[_Rd_].SD[0] = (u64)(g_cpuConstRegs[_Rt_].SD[0] >> _Sa_);
}
void recDSRAs_(int info, int sa)
{
int rtreg, rdreg, t0reg;
assert( !(info & PROCESS_EE_XMM) );
if( info & PROCESS_EE_MMX ) {
rtreg = EEREC_T;
rdreg = EEREC_D;
}
else {
_addNeededMMXreg(MMX_GPR+_Rt_);
_addNeededMMXreg(MMX_GPR+_Rd_);
rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ);
rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
SetMMXstate();
}
if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg);
if( EEINST_ISSIGNEXT(_Rt_) && EEINST_HASLIVE1(_Rt_) ) {
PSRADItoR(rdreg, sa);
return;
}
if( !EEINST_ISLIVE1(_Rd_) ) {
EEINST_RESETHASLIVE1(_Rd_);
PSRLQItoR(rdreg, sa);
return;
}
if ( sa != 0 ) {
t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
MOVQRtoR(t0reg, rtreg);
// it is a signed shift
PSRADItoR(t0reg, sa);
PSRLQItoR(rdreg, sa);
PUNPCKHDQRtoR(t0reg, t0reg); // shift to lower
// take lower dword of rdreg and lower dword of t0reg
PUNPCKLDQRtoR(rdreg, t0reg);
_freeMMXreg(t0reg);
}
}
void recDSRA_(int info)
{
recDSRAs_(info, _Sa_);
}
EERECOMPILE_CODEX(eeRecompileCode2, DSRA);
///// DSLL32
void recDSLL32_const()
{
g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] << (_Sa_+32));
}
void recDSLL32s_(int info, int sa)
{
int rtreg, rdreg;
assert( !(info & PROCESS_EE_XMM) );
if( info & PROCESS_EE_MMX ) {
rtreg = EEREC_T;
rdreg = EEREC_D;
}
else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) {
_addNeededMMXreg(MMX_GPR+_Rt_);
_addNeededMMXreg(MMX_GPR+_Rd_);
rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ);
rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
SetMMXstate();
}
else {
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
if ( sa != 0 )
{
SHL32ItoR( EAX, sa );
}
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0 );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX );
return;
}
if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg);
PSLLQItoR(rdreg, sa+32);
}
void recDSLL32_(int info)
{
recDSLL32s_(info, _Sa_);
}
EERECOMPILE_CODEX(eeRecompileCode2, DSLL32);
//// DSRL32
void recDSRL32_const()
{
g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] >> (_Sa_+32));
}
void recDSRL32s_(int info, int sa)
{
int rtreg, rdreg;
assert( !(info & PROCESS_EE_XMM) );
if( info & PROCESS_EE_MMX ) {
rtreg = EEREC_T;
rdreg = EEREC_D;
}
else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) {
_addNeededMMXreg(MMX_GPR+_Rt_);
_addNeededMMXreg(MMX_GPR+_Rd_);
rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ);
rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
SetMMXstate();
}
else {
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] );
if ( sa != 0 ) SHR32ItoR( EAX, sa );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 );
else EEINST_RESETHASLIVE1(_Rd_);
return;
}
if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg);
PSRLQItoR(rdreg, sa+32);
}
void recDSRL32_(int info)
{
recDSRL32s_(info, _Sa_);
}
EERECOMPILE_CODEX(eeRecompileCode2, DSRL32);
//// DSRA32
void recDSRA32_const()
{
g_cpuConstRegs[_Rd_].SD[0] = (u64)(g_cpuConstRegs[_Rt_].SD[0] >> (_Sa_+32));
}
void recDSRA32s_(int info, int sa)
{
int rtreg, rdreg, t0reg;
assert( !(info & PROCESS_EE_XMM) );
if( info & PROCESS_EE_MMX ) {
rtreg = EEREC_T;
rdreg = EEREC_D;
}
else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) {
_addNeededMMXreg(MMX_GPR+_Rt_);
_addNeededMMXreg(MMX_GPR+_Rd_);
rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ);
rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
SetMMXstate();
}
else {
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] );
CDQ( );
if ( sa != 0 ) SAR32ItoR( EAX, sa );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
if( EEINST_ISLIVE1(_Rd_) ) MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
else EEINST_RESETHASLIVE1(_Rd_);
return;
}
if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg);
if( EEINST_ISSIGNEXT(_Rt_) && EEINST_HASLIVE1(_Rt_) ) {
PSRADItoR(rdreg, 31);
return;
}
if( !EEINST_ISLIVE1(_Rd_) ) {
EEINST_RESETHASLIVE1(_Rd_);
if( sa ) PSRADItoR(rdreg, sa);
PUNPCKHDQRtoR(rdreg, rdreg);
return;
}
t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
MOVQRtoR(t0reg, rtreg);
// it is a signed shift
if( sa ) {
PSRADItoR(rdreg, sa);
PSRADItoR(t0reg, 31);
// take higher dword of rdreg and lower dword of t0reg
PUNPCKHDQRtoR(rdreg, t0reg);
_freeMMXreg(t0reg);
}
else {
// better timing
PSRADItoR(rdreg, 31);
// take higher dword of rdreg and lower dword of t0reg
PUNPCKHDQRtoR(t0reg, rdreg);
// swap
mmxregs[t0reg] = mmxregs[rdreg];
mmxregs[rdreg].inuse = 0;
}
}
void recDSRA32_(int info)
{
recDSRA32s_(info, _Sa_);
}
EERECOMPILE_CODEX(eeRecompileCode2, DSRA32);
/*********************************************************
* Shift arithmetic with variant register shift *
* Format: OP rd, rt, rs *
*********************************************************/
__declspec(align(16)) u32 s_sa[4] = {0x1f, 0, 0x3f, 0};
int recSetShiftV(int info, int* rsreg, int* rtreg, int* rdreg, int* rstemp, int forcemmx, int shift64)
{
assert( !(info & PROCESS_EE_XMM) );
if( info & PROCESS_EE_MMX ) {
*rtreg = EEREC_T;
*rdreg = EEREC_D;
*rsreg = EEREC_S;
// make sure to take only low 5 bits of *rsreg
if( !(g_pCurInstInfo->regs[_Rs_]&EEINST_LASTUSE) && EEINST_ISLIVEMMX(_Rs_)) {
*rstemp = _allocMMXreg(-1, MMX_TEMP, 0);
MOVQRtoR(*rstemp, *rsreg);
*rsreg = *rstemp;
}
else {
if( *rsreg != *rdreg ) {
_freeMMXreg(*rsreg);
mmxregs[*rsreg].inuse = 0;
}
}
PANDMtoR(*rsreg, (u32)&s_sa[shift64?2:0]);
if( EEREC_D == EEREC_S ) {
// need to be separate
int mmreg = _allocMMXreg(-1, MMX_TEMP, 0);
*rdreg = mmreg;
mmxregs[mmreg] = mmxregs[EEREC_S];
mmxregs[EEREC_S].inuse = 0;
}
}
else if( forcemmx || (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) {
_addNeededMMXreg(MMX_GPR+_Rt_);
_addNeededMMXreg(MMX_GPR+_Rd_);
*rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ);
*rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
SetMMXstate();
*rstemp = _allocMMXreg(-1, MMX_TEMP, 0);
MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]);
AND32ItoR(EAX, shift64?0x3f:0x1f);
MOVD32RtoMMX(*rstemp, EAX);
*rsreg = *rstemp;
}
else {
return 0;
}
if( *rtreg != *rdreg ) MOVQRtoR(*rdreg, *rtreg);
return 1;
}
void recSetConstShiftV(int info, int* rsreg, int* rdreg, int* rstemp, int shift64)
{
if( info & PROCESS_EE_MMX ) {
*rdreg = EEREC_D;
*rsreg = EEREC_S;
// make sure to take only low 5 bits of *rsreg
if( !(g_pCurInstInfo->regs[_Rs_]&EEINST_LASTUSE) && EEINST_ISLIVEMMX(_Rs_) ) {
*rstemp = _allocMMXreg(-1, MMX_TEMP, 0);
MOVQRtoR(*rstemp, *rsreg);
*rsreg = *rstemp;
}
else {
if( *rsreg != *rdreg ) {
_freeMMXreg(*rsreg);
mmxregs[*rsreg].inuse = 0;
}
}
PANDMtoR(*rsreg, (u32)&s_sa[shift64?2:0]);
if( EEREC_D == EEREC_S ) {
// need to be separate
int mmreg = _allocMMXreg(-1, MMX_TEMP, 0);
*rdreg = mmreg;
mmxregs[mmreg] = mmxregs[EEREC_S];
mmxregs[EEREC_S].inuse = 0;
}
}
else {
_addNeededMMXreg(MMX_GPR+_Rd_);
*rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
SetMMXstate();
*rstemp = _allocMMXreg(-1, MMX_TEMP, 0);
MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]);
AND32ItoR(EAX, shift64?0x3f:0x1f);
MOVD32RtoMMX(*rstemp, EAX);
*rsreg = *rstemp;
}
_flushConstReg(_Rt_);
}
void recMoveSignToRd(int info)
{
if( EEINST_ISLIVE1(_Rd_) ) {
CDQ();
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
else {
EEINST_RESETHASLIVE1(_Rd_);
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
}
if( info & PROCESS_EE_MMX ) {
mmxregs[EEREC_D].inuse = 0;
}
}
//// SLLV
void recSLLV_const()
{
g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] << (g_cpuConstRegs[_Rs_].UL[0] &0x1f));
}
void recSLLV_consts(int info)
{
recSLLs_(info, g_cpuConstRegs[_Rs_].UL[0]&0x1f);
EEINST_SETSIGNEXT(_Rd_);
}
void recSLLV_constt(int info)
{
if( (info & PROCESS_EE_MMX) && (info & PROCESS_EE_MODEWRITES) ) MOVD32MMXtoR(ECX, EEREC_S);
else MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] );
AND32ItoR( ECX, 0x1f );
SHL32CLtoR( EAX );
recMoveSignToRd(info);
EEINST_SETSIGNEXT(_Rd_);
}
void recSLLV_(int info)
{
int rsreg, rtreg, rdreg, rstemp = -1, t0reg;
EEINST_SETSIGNEXT(_Rd_);
if( recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 0, 0) == 0 ) {
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
if ( _Rs_ != 0 )
{
MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
AND32ItoR( ECX, 0x1f );
SHL32CLtoR( EAX );
}
CDQ();
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
return;
}
if( !EEINST_ISLIVE1(_Rd_) ) {
EEINST_RESETHASLIVE1(_Rd_);
PSLLDRtoR(rdreg, rsreg);
if( rstemp != -1 ) _freeMMXreg(rstemp);
return;
}
t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
// it is a signed shift
PSLLDRtoR(rdreg, rsreg);
MOVQRtoR(t0reg, rdreg);
PSRADItoR(t0reg, 31);
// take lower dword of rdreg and lower dword of t0reg
PUNPCKLDQRtoR(rdreg, t0reg);
_freeMMXreg(t0reg);
if( rstemp != -1 ) _freeMMXreg(rstemp);
}
EERECOMPILE_CODE0(SLLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
//// SRLV
void recSRLV_const()
{
g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x1f));
}
void recSRLV_consts(int info)
{
recSRLs_(info, g_cpuConstRegs[_Rs_].UL[0]&0x1f);
EEINST_SETSIGNEXT(_Rd_);
}
void recSRLV_constt(int info)
{
if( (info & PROCESS_EE_MMX) && (info&PROCESS_EE_MODEWRITES) ) MOVD32MMXtoR(ECX, EEREC_S);
else MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] );
AND32ItoR( ECX, 0x1f );
SHR32CLtoR( EAX );
recMoveSignToRd(info);
EEINST_SETSIGNEXT(_Rd_);
}
void recSRLV_(int info)
{
int rsreg, rtreg, rdreg, rstemp = -1, t0reg;
EEINST_SETSIGNEXT(_Rd_);
if( recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 0, 0) == 0 ) {
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
if ( _Rs_ != 0 )
{
MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
AND32ItoR( ECX, 0x1f );
SHR32CLtoR( EAX );
}
CDQ( );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
return;
}
if( !EEINST_ISLIVE1(_Rd_) ) {
EEINST_RESETHASLIVE1(_Rd_);
PSRLDRtoR(rdreg, rsreg);
if( rstemp != -1 ) _freeMMXreg(rstemp);
return;
}
t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
// it is a signed shift
PSRLDRtoR(rdreg, rsreg);
MOVQRtoR(t0reg, rdreg);
PSRADItoR(t0reg, 31);
// take lower dword of rdreg and lower dword of t0reg
PUNPCKLDQRtoR(rdreg, t0reg);
_freeMMXreg(t0reg);
if( rstemp != -1 ) _freeMMXreg(rstemp);
}
EERECOMPILE_CODE0(SRLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
//// SRAV
void recSRAV_const()
{
g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].SL[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x1f));
}
void recSRAV_consts(int info)
{
recSRAs_(info, g_cpuConstRegs[_Rs_].UL[0]&0x1f);
EEINST_SETSIGNEXT(_Rd_);
}
void recSRAV_constt(int info)
{
if( (info & PROCESS_EE_MMX) && (info&PROCESS_EE_MODEWRITES) ) MOVD32MMXtoR(ECX, EEREC_S);
else MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] );
AND32ItoR( ECX, 0x1f );
SAR32CLtoR( EAX );
recMoveSignToRd(info);
EEINST_SETSIGNEXT(_Rd_);
}
void recSRAV_(int info)
{
int rsreg, rtreg, rdreg, rstemp = -1, t0reg;
EEINST_SETSIGNEXT(_Rd_);
if( recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 0, 0) == 0 ) {
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
if ( _Rs_ != 0 )
{
MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
AND32ItoR( ECX, 0x1f );
SAR32CLtoR( EAX );
}
CDQ( );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
return;
}
if( !EEINST_ISLIVE1(_Rd_) ) {
EEINST_RESETHASLIVE1(_Rd_);
PSRADRtoR(rdreg, rsreg);
if( rstemp != -1 ) _freeMMXreg(rstemp);
return;
}
t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
// it is a signed shift
PSRADRtoR(rdreg, rsreg);
MOVQRtoR(t0reg, rdreg);
PSRADItoR(t0reg, 31);
// take lower dword of rdreg and lower dword of t0reg
PUNPCKLDQRtoR(rdreg, t0reg);
_freeMMXreg(t0reg);
if( rstemp != -1 ) _freeMMXreg(rstemp);
}
EERECOMPILE_CODE0(SRAV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
//// DSLLV
void recDSLLV_const()
{
g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] << (g_cpuConstRegs[_Rs_].UL[0] &0x3f));
}
void recDSLLV_consts(int info)
{
int sa = g_cpuConstRegs[_Rs_].UL[0]&0x3f;
if( sa < 32 ) recDSLLs_(info, sa);
else recDSLL32s_(info, sa-32);
}
void recDSLLV_constt(int info)
{
int rsreg, rdreg, rstemp = -1;
recSetConstShiftV(info, &rsreg, &rdreg, &rstemp, 1);
MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[_Rt_]);
PSLLQRtoR(rdreg, rsreg);
if( rstemp != -1 ) _freeMMXreg(rstemp);
}
void recDSLLV_(int info)
{
int rsreg, rtreg, rdreg, rstemp = -1;
recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 1, 1);
PSLLQRtoR(rdreg, rsreg);
if( rstemp != -1 ) _freeMMXreg(rstemp);
}
EERECOMPILE_CODE0(DSLLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
//// DSRLV
void recDSRLV_const()
{
g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x3f));
}
void recDSRLV_consts(int info)
{
int sa = g_cpuConstRegs[_Rs_].UL[0]&0x3f;
if( sa < 32 ) recDSRLs_(info, sa);
else recDSRL32s_(info, sa-32);
}
void recDSRLV_constt(int info)
{
int rsreg, rdreg, rstemp = -1;
recSetConstShiftV(info, &rsreg, &rdreg, &rstemp, 1);
MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[_Rt_]);
PSRLQRtoR(rdreg, rsreg);
if( rstemp != -1 ) _freeMMXreg(rstemp);
}
void recDSRLV_(int info)
{
int rsreg, rtreg, rdreg, rstemp = -1;
recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 1, 1);
PSRLQRtoR(rdreg, rsreg);
if( rstemp != -1 ) _freeMMXreg(rstemp);
}
EERECOMPILE_CODE0(DSRLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
//// DSRAV
void recDSRAV_const()
{
g_cpuConstRegs[_Rd_].SD[0] = (s64)(g_cpuConstRegs[_Rt_].SD[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x3f));
}
void recDSRAV_consts(int info)
{
int sa = g_cpuConstRegs[_Rs_].UL[0]&0x3f;
if( sa < 32 ) recDSRAs_(info, sa);
else recDSRA32s_(info, sa-32);
}
void recDSRAV_constt(int info)
{
int rsreg, rdreg, rstemp = -1, t0reg, t1reg;
t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
t1reg = _allocMMXreg(-1, MMX_TEMP, 0);
recSetConstShiftV(info, &rsreg, &rdreg, &rstemp, 1);
MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[_Rt_]);
PXORRtoR(t0reg, t0reg);
// calc high bit
MOVQRtoR(t1reg, rdreg);
PCMPGTDRtoR(t0reg, rdreg);
PUNPCKHDQRtoR(t0reg, t0reg); // shift to lower
// shift highest bit, 64 - eax
MOV32ItoR(EAX, 64);
MOVD32RtoMMX(t1reg, EAX);
PSUBDRtoR(t1reg, rsreg);
// right logical shift
PSRLQRtoR(rdreg, rsreg);
PSLLQRtoR(t0reg, t1reg); // highest bits
PORRtoR(rdreg, t0reg);
_freeMMXreg(t0reg);
_freeMMXreg(t1reg);
if( rstemp != -1 ) _freeMMXreg(rstemp);
}
void recDSRAV_(int info)
{
int rsreg, rtreg, rdreg, rstemp = -1, t0reg, t1reg;
t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
t1reg = _allocMMXreg(-1, MMX_TEMP, 0);
recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 1, 1);
PXORRtoR(t0reg, t0reg);
// calc high bit
MOVQRtoR(t1reg, rdreg);
PCMPGTDRtoR(t0reg, rdreg);
PUNPCKHDQRtoR(t0reg, t0reg); // shift to lower
// shift highest bit, 64 - eax
MOV32ItoR(EAX, 64);
MOVD32RtoMMX(t1reg, EAX);
PSUBDRtoR(t1reg, rsreg);
// right logical shift
PSRLQRtoR(rdreg, rsreg);
PSLLQRtoR(t0reg, t1reg); // highest bits
PORRtoR(rdreg, t0reg);
_freeMMXreg(t0reg);
_freeMMXreg(t1reg);
if( rstemp != -1 ) _freeMMXreg(rstemp);
}
EERECOMPILE_CODE0(DSRAV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
#else
////////////////////////////////////////////////////
void recDSRA( void )
{
if( !_Rd_ ) return; //?
if ( _Sa_ != 0 ) {
// it is a signed shift
MOVQMtoR(MM0, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
MOVQRtoR(MM1, MM0);
PSRADItoR(MM0, _Sa_);
PSRLQItoR(MM1, _Sa_);
PUNPCKHDQRtoR(MM0, MM0); // shift to lower
// take lower dword of MM1 and lower dword of MM0
PUNPCKLDQRtoR(MM1, MM0);
MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM1);
}
else {
MOVQMtoR(MM0, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM0);
}
SetMMXstate();
}
////////////////////////////////////////////////////
void recDSRA32(void)
{
if( !_Rd_ ) return; //?
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] );
CDQ();
if ( _Sa_ != 0 )
{
SAR32ItoR( EAX, _Sa_ );
}
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX);
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX);
}
////////////////////////////////////////////////////
void recSLL( void )
{
if ( ! _Rd_ )
return;
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
if ( _Sa_ != 0 )
{
SHL32ItoR( EAX, _Sa_ );
}
CDQ( );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
////////////////////////////////////////////////////
void recSRL( void )
{
if ( ! _Rd_ )
{
return;
}
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
if ( _Sa_ != 0 )
{
SHR32ItoR( EAX, _Sa_);
}
CDQ( );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
////////////////////////////////////////////////////
void recSRA( void )
{
if ( ! _Rd_ )
{
return;
}
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
if ( _Sa_ != 0 )
{
SAR32ItoR( EAX, _Sa_);
}
CDQ();
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
////////////////////////////////////////////////////
void recDSLL( void )
{
if ( ! _Rd_ )
{
return;
}
MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] );
if ( _Sa_ != 0 )
{
PSLLQItoR( MM0, _Sa_ );
}
MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 );
SetMMXstate();
}
////////////////////////////////////////////////////
void recDSRL( void )
{
if ( ! _Rd_ )
{
return;
}
MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] );
if ( _Sa_ != 0 )
{
PSRLQItoR( MM0, _Sa_ );
}
MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 );
SetMMXstate();
}
////////////////////////////////////////////////////
void recDSLL32( void )
{
if ( ! _Rd_ )
{
return;
}
if ( _Sa_ == 0 )
{
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0 );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX );
return;
}
MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] );
PSLLQItoR( MM0, _Sa_ + 32 );
MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 );
SetMMXstate();
}
////////////////////////////////////////////////////
void recDSRL32( void )
{
if ( ! _Rd_ )
{
return;
}
if ( _Sa_ == 0 )
{
MOV32MtoR( EAX,(int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] );
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
return;
}
MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] );
PSRLQItoR( MM0, _Sa_ + 32 );
MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 );
SetMMXstate();
}
/*********************************************************
* Shift arithmetic with variant register shift *
* Format: OP rd, rt, rs *
*********************************************************/
////////////////////////////////////////////////////
////////////////////////////////////////////////////
void recSLLV( void )
{
if ( ! _Rd_ ) return;
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
if ( _Rs_ != 0 )
{
MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
AND32ItoR( ECX, 0x1f );
SHL32CLtoR( EAX );
}
CDQ();
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
////////////////////////////////////////////////////
void recSRLV( void )
{
if ( ! _Rd_ ) return;
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
if ( _Rs_ != 0 )
{
MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
AND32ItoR( ECX, 0x1f );
SHR32CLtoR( EAX );
}
CDQ( );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
////////////////////////////////////////////////////
void recSRAV( void )
{
if ( ! _Rd_ ) return;
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
if ( _Rs_ != 0 )
{
MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
AND32ItoR( ECX, 0x1f );
SAR32CLtoR( EAX );
}
CDQ( );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
////////////////////////////////////////////////////
static u64 _sa = 0;
void recDSLLV( void )
{
if ( ! _Rd_ ) return;
MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] );
if ( _Rs_ != 0 )
{
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ] );
AND32ItoR( EAX, 0x3f);
MOV32RtoM( (int)&_sa, EAX );
PSLLQMtoR( MM0, (int)&_sa );
}
MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 );
SetMMXstate();
}
////////////////////////////////////////////////////
void recDSRLV( void )
{
if ( ! _Rd_ ) return;
MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] );
if ( _Rs_ != 0 )
{
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ] );
AND32ItoR( EAX, 0x3f);
MOV32RtoM( (int)&_sa, EAX );
PSRLQMtoR( MM0, (int)&_sa );
}
MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 );
SetMMXstate();
}
////////////////////////////////////////////////////////////////
void recDSRAV( void )
{
MOVQMtoR(MM0, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
if ( _Rs_ != 0 ) {
PXORRtoR(MM1, MM1);
// calc high bit
MOVQRtoR(MM2, MM0);
PUNPCKHDQRtoR(MM2, MM2); // shift to lower
PCMPGTDRtoR(MM1, MM2);
// it is a signed shift
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ] );
AND32ItoR( EAX, 0x3f);
MOVD32RtoMMX(MM2, EAX); // amount to shift
NOT32R(EAX);
ADD32ItoR(EAX, 65);
// right logical shift
PSRLQRtoR(MM0, MM2);
// shift highest bit, 64 - eax
MOVD32RtoMMX(MM2, EAX);
PSLLQRtoR(MM1, MM2); // highest bits
PORRtoR(MM0, MM1);
MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM0);
}
else {
MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM0);
}
SetMMXstate();
}
#endif