Emitter renovations of a large scale sort (only up to phase 1). Intel's 'group 1' instructions now use a completely new ModRM/SIB encoder, along with a nicely object-oriented interface. I created some macros to retain backward compat for now, and will continue implementing the rest of the instructions later as I have time.

Also: Removed x86/64 instructions from the emitter.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@917 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-04-07 08:42:25 +00:00
parent 60e7428671
commit 2588dc0309
17 changed files with 905 additions and 1298 deletions

View File

@ -2982,6 +2982,10 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\x86\ix86\ix86_group1.inl"
>
</File>
<File
RelativePath="..\..\x86\ix86\ix86_macros.h"
>

View File

@ -1982,8 +1982,8 @@ void recQFSRV()
MOV32MtoR(EAX, (uptr)&cpuRegs.sa);
SHL32ItoR(EAX, 4); // Multiply SA bytes by 16 bytes (the amount of bytes in QFSRVhelper() macros)
AND32I8toR(EAX, 0xf0); // This can possibly be removed but keeping it incase theres garbage in SA (cottonvibes)
ADD32ItoEAX((uptr)x86Ptr[0] + 7); // ADD32 = 5 bytes, JMPR = 2 bytes
AND32ItoR(EAX, 0xf0); // This can possibly be removed but keeping it incase theres garbage in SA (cottonvibes)
ADD32ItoR(EAX, (uptr)x86Ptr[0] + 7); // ADD32 = 5 bytes, JMPR = 2 bytes
JMPR(EAX); // Jumps to a QFSRVhelper() case below (a total of 16 different cases)
// Case 0:

View File

@ -316,7 +316,7 @@ void _psxMoveGPRtoM(u32 to, int fromgpr)
void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr)
{
if( PSX_IS_CONST1(fromgpr) )
MOV32ItoRmOffset( to, g_psxConstRegs[fromgpr], 0 );
MOV32ItoRm( to, g_psxConstRegs[fromgpr] );
else {
// check x86
MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[ fromgpr ] );

View File

@ -609,31 +609,31 @@ void _loadEAX(VURegs *VU, int x86reg, uptr offset, int info)
if( x86reg >= 0 ) {
switch(_X_Y_Z_W) {
case 3: // ZW
SSE_MOVHPS_RmOffset_to_XMM(EEREC_T, x86reg, offset+8);
SSE_MOVHPS_Rm_to_XMM(EEREC_T, x86reg, offset+8);
break;
case 6: // YZ
SSE_SHUFPS_RmOffset_to_XMM(EEREC_T, x86reg, offset, 0x9c);
SSE_SHUFPS_Rm_to_XMM(EEREC_T, x86reg, offset, 0x9c);
SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0x78);
break;
case 8: // X
SSE_MOVSS_RmOffset_to_XMM(EEREC_TEMP, x86reg, offset);
SSE_MOVSS_Rm_to_XMM(EEREC_TEMP, x86reg, offset);
SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP);
break;
case 9: // XW
SSE_SHUFPS_RmOffset_to_XMM(EEREC_T, x86reg, offset, 0xc9);
SSE_SHUFPS_Rm_to_XMM(EEREC_T, x86reg, offset, 0xc9);
SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xd2);
break;
case 12: // XY
SSE_MOVLPS_RmOffset_to_XMM(EEREC_T, x86reg, offset);
SSE_MOVLPS_Rm_to_XMM(EEREC_T, x86reg, offset);
break;
case 15:
if( VU == &VU1 ) SSE_MOVAPSRmtoROffset(EEREC_T, x86reg, offset);
else SSE_MOVUPSRmtoROffset(EEREC_T, x86reg, offset);
if( VU == &VU1 ) SSE_MOVAPSRmtoR(EEREC_T, x86reg, offset);
else SSE_MOVUPSRmtoR(EEREC_T, x86reg, offset);
break;
default:
if( VU == &VU1 ) SSE_MOVAPSRmtoROffset(EEREC_TEMP, x86reg, offset);
else SSE_MOVUPSRmtoROffset(EEREC_TEMP, x86reg, offset);
if( VU == &VU1 ) SSE_MOVAPSRmtoR(EEREC_TEMP, x86reg, offset);
else SSE_MOVUPSRmtoR(EEREC_TEMP, x86reg, offset);
VU_MERGE_REGS(EEREC_T, EEREC_TEMP);
break;
@ -795,15 +795,15 @@ void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info)
if ( _Fs_ == 0 ) {
if ( _XYZW_SS ) {
u32 c = _W ? 0x3f800000 : 0;
if ( x86reg >= 0 ) MOV32ItoRmOffset(x86reg, c, offset+(_W?12:(_Z?8:(_Y?4:0))));
if ( x86reg >= 0 ) MOV32ItoRm(x86reg, c, offset+(_W?12:(_Z?8:(_Y?4:0))));
else MOV32ItoM(offset+(_W?12:(_Z?8:(_Y?4:0))), c);
}
else {
if ( x86reg >= 0 ) {
if ( _X ) MOV32ItoRmOffset(x86reg, 0x00000000, offset);
if ( _Y ) MOV32ItoRmOffset(x86reg, 0x00000000, offset+4);
if ( _Z ) MOV32ItoRmOffset(x86reg, 0x00000000, offset+8);
if ( _W ) MOV32ItoRmOffset(x86reg, 0x3f800000, offset+12);
if ( _X ) MOV32ItoRm(x86reg, 0x00000000, offset);
if ( _Y ) MOV32ItoRm(x86reg, 0x00000000, offset+4);
if ( _Z ) MOV32ItoRm(x86reg, 0x00000000, offset+8);
if ( _W ) MOV32ItoRm(x86reg, 0x3f800000, offset+12);
}
else {
if ( _X ) MOV32ItoM(offset, 0x00000000);
@ -818,29 +818,29 @@ void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info)
switch ( _X_Y_Z_W ) {
case 1: // W
SSE2_PSHUFD_XMM_to_XMM(EEREC_TEMP, EEREC_S, 0x27);
if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+12);
if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+12);
else SSE_MOVSS_XMM_to_M32(offset+12, EEREC_TEMP);
break;
case 2: // Z
SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S);
if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+8);
if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+8);
else SSE_MOVSS_XMM_to_M32(offset+8, EEREC_TEMP);
break;
case 3: // ZW
if ( x86reg >= 0 ) SSE_MOVHPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+8);
if ( x86reg >= 0 ) SSE_MOVHPS_XMM_to_Rm(x86reg, EEREC_S, offset+8);
else SSE_MOVHPS_XMM_to_M64(offset+8, EEREC_S);
break;
case 4: // Y
SSE2_PSHUFLW_XMM_to_XMM(EEREC_TEMP, EEREC_S, 0x4e);
if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+4);
if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+4);
else SSE_MOVSS_XMM_to_M32(offset+4, EEREC_TEMP);
break;
case 5: // YW
SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xB1);
SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S);
if ( x86reg >= 0 ) {
SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset+4);
SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+12);
SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_S, offset+4);
SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+12);
}
else {
SSE_MOVSS_XMM_to_M32(offset+4, EEREC_S);
@ -850,14 +850,14 @@ void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info)
break;
case 6: // YZ
SSE2_PSHUFD_XMM_to_XMM(EEREC_TEMP, EEREC_S, 0xc9);
if ( x86reg >= 0 ) SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+4);
if ( x86reg >= 0 ) SSE_MOVLPS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+4);
else SSE_MOVLPS_XMM_to_M64(offset+4, EEREC_TEMP);
break;
case 7: // YZW
SSE2_PSHUFD_XMM_to_XMM(EEREC_TEMP, EEREC_S, 0x93); //ZYXW
if ( x86reg >= 0 ) {
SSE_MOVHPS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+4);
SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+12);
SSE_MOVHPS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+4);
SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+12);
}
else {
SSE_MOVHPS_XMM_to_M64(offset+4, EEREC_TEMP);
@ -865,26 +865,26 @@ void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info)
}
break;
case 8: // X
if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset);
if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_S, offset);
else SSE_MOVSS_XMM_to_M32(offset, EEREC_S);
break;
case 9: // XW
SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S);
if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset);
if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_S, offset);
else SSE_MOVSS_XMM_to_M32(offset, EEREC_S);
if ( cpucaps.hasStreamingSIMD3Extensions ) SSE3_MOVSLDUP_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP);
else SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x55);
if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+12);
if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+12);
else SSE_MOVSS_XMM_to_M32(offset+12, EEREC_TEMP);
break;
case 10: //XZ
SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S);
if ( x86reg >= 0 ) {
SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset);
SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+8);
SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_S, offset);
SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+8);
}
else {
SSE_MOVSS_XMM_to_M32(offset, EEREC_S);
@ -893,8 +893,8 @@ void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info)
break;
case 11: //XZW
if ( x86reg >= 0 ) {
SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset);
SSE_MOVHPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+8);
SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_S, offset);
SSE_MOVHPS_XMM_to_Rm(x86reg, EEREC_S, offset+8);
}
else {
SSE_MOVSS_XMM_to_M32(offset, EEREC_S);
@ -902,14 +902,14 @@ void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info)
}
break;
case 12: // XY
if ( x86reg >= 0 ) SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+0);
if ( x86reg >= 0 ) SSE_MOVLPS_XMM_to_Rm(x86reg, EEREC_S, offset+0);
else SSE_MOVLPS_XMM_to_M64(offset, EEREC_S);
break;
case 13: // XYW
SSE2_PSHUFD_XMM_to_XMM(EEREC_TEMP, EEREC_S, 0x4b); //YXZW
if ( x86reg >= 0 ) {
SSE_MOVHPS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+0);
SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+12);
SSE_MOVHPS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+0);
SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+12);
}
else {
SSE_MOVHPS_XMM_to_M64(offset, EEREC_TEMP);
@ -919,8 +919,8 @@ void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info)
case 14: // XYZ
SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S);
if ( x86reg >= 0 ) {
SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+0);
SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+8);
SSE_MOVLPS_XMM_to_Rm(x86reg, EEREC_S, offset+0);
SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+8);
}
else {
SSE_MOVLPS_XMM_to_M64(offset, EEREC_S);
@ -929,11 +929,11 @@ void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info)
break;
case 15: // XYZW
if ( VU == &VU1 ) {
if( x86reg >= 0 ) SSE_MOVAPSRtoRmOffset(x86reg, EEREC_S, offset+0);
if( x86reg >= 0 ) SSE_MOVAPSRtoRm(x86reg, EEREC_S, offset+0);
else SSE_MOVAPS_XMM_to_M128(offset, EEREC_S);
}
else {
if( x86reg >= 0 ) SSE_MOVUPSRtoRmOffset(x86reg, EEREC_S, offset+0);
if( x86reg >= 0 ) SSE_MOVUPSRtoRm(x86reg, EEREC_S, offset+0);
else {
if( offset & 15 ) SSE_MOVUPS_XMM_to_M128(offset, EEREC_S);
else SSE_MOVAPS_XMM_to_M128(offset, EEREC_S);
@ -1018,7 +1018,7 @@ void recVUMI_ILW(VURegs *VU, int info)
}
else {
int fsreg = ALLOCVI(_Fs_, MODE_READ);
MOV32RmtoROffset(ftreg, recVUTransformAddr(fsreg, VU, _Fs_, imm), (uptr)VU->Mem + off);
MOV32RmtoR(ftreg, recVUTransformAddr(fsreg, VU, _Fs_, imm), (uptr)VU->Mem + off);
}
}
//------------------------------------------------------------------
@ -1051,10 +1051,10 @@ void recVUMI_ISW( VURegs *VU, int info )
x86reg = recVUTransformAddr(fsreg, VU, _Fs_, imm);
if (_X) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem);
if (_Y) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+4);
if (_Z) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+8);
if (_W) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+12);
if (_X) MOV32RtoRm(x86reg, ftreg, (uptr)VU->Mem);
if (_Y) MOV32RtoRm(x86reg, ftreg, (uptr)VU->Mem+4);
if (_Z) MOV32RtoRm(x86reg, ftreg, (uptr)VU->Mem+8);
if (_W) MOV32RtoRm(x86reg, ftreg, (uptr)VU->Mem+12);
}
}
//------------------------------------------------------------------
@ -1082,7 +1082,7 @@ void recVUMI_ILWR( VURegs *VU, int info )
}
else {
int fsreg = ALLOCVI(_Fs_, MODE_READ);
MOVZX32Rm16toROffset(ftreg, recVUTransformAddr(fsreg, VU, _Fs_, 0), (uptr)VU->Mem + off);
MOVZX32Rm16toR(ftreg, recVUTransformAddr(fsreg, VU, _Fs_, 0), (uptr)VU->Mem + off);
}
}
//------------------------------------------------------------------
@ -1109,10 +1109,10 @@ void recVUMI_ISWR( VURegs *VU, int info )
int fsreg = ALLOCVI(_Fs_, MODE_READ);
x86reg = recVUTransformAddr(fsreg, VU, _Fs_, 0);
if (_X) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem);
if (_Y) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+4);
if (_Z) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+8);
if (_W) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+12);
if (_X) MOV32RtoRm(x86reg, ftreg, (uptr)VU->Mem);
if (_Y) MOV32RtoRm(x86reg, ftreg, (uptr)VU->Mem+4);
if (_Z) MOV32RtoRm(x86reg, ftreg, (uptr)VU->Mem+8);
if (_W) MOV32RtoRm(x86reg, ftreg, (uptr)VU->Mem+12);
}
}
//------------------------------------------------------------------

View File

@ -1050,12 +1050,12 @@ void _recMove128MtoM(u32 to, u32 from)
// fixme - see above function!
void _recMove128RmOffsettoM(u32 to, u32 offset)
{
MOV32RmtoROffset(EAX, ECX, offset);
MOV32RmtoROffset(EDX, ECX, offset+4);
MOV32RmtoR(EAX, ECX, offset);
MOV32RmtoR(EDX, ECX, offset+4);
MOV32RtoM(to, EAX);
MOV32RtoM(to+4, EDX);
MOV32RmtoROffset(EAX, ECX, offset+8);
MOV32RmtoROffset(EDX, ECX, offset+12);
MOV32RmtoR(EAX, ECX, offset+8);
MOV32RmtoR(EDX, ECX, offset+12);
MOV32RtoM(to+8, EAX);
MOV32RtoM(to+12, EDX);
}
@ -1065,12 +1065,12 @@ void _recMove128MtoRmOffset(u32 offset, u32 from)
{
MOV32MtoR(EAX, from);
MOV32MtoR(EDX, from+4);
MOV32RtoRmOffset(ECX, EAX, offset);
MOV32RtoRmOffset(ECX, EDX, offset+4);
MOV32RtoRm(ECX, EAX, offset);
MOV32RtoRm(ECX, EDX, offset+4);
MOV32MtoR(EAX, from+8);
MOV32MtoR(EDX, from+12);
MOV32RtoRmOffset(ECX, EAX, offset+8);
MOV32RtoRmOffset(ECX, EDX, offset+12);
MOV32RtoRm(ECX, EAX, offset+8);
MOV32RtoRm(ECX, EDX, offset+12);
}
static PCSX2_ALIGNED16(u32 s_ones[2]) = {0xffffffff, 0xffffffff};

View File

@ -367,7 +367,7 @@ void _eeMoveGPRtoM(u32 to, int fromgpr)
void _eeMoveGPRtoRm(x86IntRegType to, int fromgpr)
{
if( GPR_IS_CONST1(fromgpr) )
MOV32ItoRmOffset( to, g_cpuConstRegs[fromgpr].UL[0], 0 );
MOV32ItoRm( to, g_cpuConstRegs[fromgpr].UL[0] );
else {
int mmreg;
@ -380,7 +380,7 @@ void _eeMoveGPRtoRm(x86IntRegType to, int fromgpr)
}
else {
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] );
MOV32RtoRm(to, EAX );
MOV32RtoRm( to, EAX );
}
}
}

View File

@ -2101,7 +2101,7 @@ void recLoad64( u32 bits, bool sign )
if ( _Imm_ != 0 )
ADD32ItoR( ECX, _Imm_ );
if( bits == 128 ) // force 16 byte alignment on 128 bit reads
AND32I8toR(ECX,0xF0);
AND32ItoR(ECX,~0x0F); // emitter automatically encodes this as an 8-bit sign-extended imm8
_eeOnLoadWrite(_Rt_);
EEINST_RESETSIGNEXT(_Rt_); // remove the sign extension
@ -2198,7 +2198,7 @@ void recStore(u32 sz, bool edxAlreadyAssigned=false)
if ( _Imm_ != 0 )
ADD32ItoR(ECX, _Imm_);
if (sz==128)
AND32I8toR(ECX,0xF0);
AND32ItoR(ECX,~0x0F);
vtlb_DynGenWrite(sz);
}

View File

@ -33,12 +33,12 @@ void MOV128_MtoM( x86IntRegType destRm, x86IntRegType srcRm )
{
MOV32RmtoR(EAX,srcRm);
MOV32RtoRm(destRm,EAX);
MOV32RmtoROffset(EAX,srcRm,4);
MOV32RtoRmOffset(destRm,EAX,4);
MOV32RmtoROffset(EAX,srcRm,8);
MOV32RtoRmOffset(destRm,EAX,8);
MOV32RmtoROffset(EAX,srcRm,12);
MOV32RtoRmOffset(destRm,EAX,12);
MOV32RmtoR(EAX,srcRm,4);
MOV32RtoRm(destRm,EAX,4);
MOV32RmtoR(EAX,srcRm,8);
MOV32RtoRm(destRm,EAX,8);
MOV32RmtoR(EAX,srcRm,12);
MOV32RtoRm(destRm,EAX,12);
}
/*
@ -121,8 +121,8 @@ static void _vtlb_DynGen_DirectRead( u32 bits, bool sign )
if( _hasFreeMMXreg() )
{
const int freereg = _allocMMXreg(-1, MMX_TEMP, 0);
MOVQRmtoROffset(freereg,ECX,0);
MOVQRtoRmOffset(EDX,freereg,0);
MOVQRmtoR(freereg,ECX);
MOVQRtoRm(EDX,freereg);
_freeMMXreg(freereg);
}
else
@ -130,8 +130,8 @@ static void _vtlb_DynGen_DirectRead( u32 bits, bool sign )
MOV32RmtoR(EAX,ECX);
MOV32RtoRm(EDX,EAX);
MOV32RmtoROffset(EAX,ECX,4);
MOV32RtoRmOffset(EDX,EAX,4);
MOV32RmtoR(EAX,ECX,4);
MOV32RtoRm(EDX,EAX,4);
}
break;
@ -139,8 +139,8 @@ static void _vtlb_DynGen_DirectRead( u32 bits, bool sign )
if( _hasFreeXMMreg() )
{
const int freereg = _allocTempXMMreg( XMMT_INT, -1 );
SSE2_MOVDQARmtoROffset(freereg,ECX,0);
SSE2_MOVDQARtoRmOffset(EDX,freereg,0);
SSE2_MOVDQARmtoR(freereg,ECX);
SSE2_MOVDQARtoRm(EDX,freereg);
_freeXMMreg(freereg);
}
else
@ -255,7 +255,7 @@ void vtlb_DynGenRead64_Const( u32 bits, u32 addr_const )
{
const int freereg = _allocMMXreg(-1, MMX_TEMP, 0);
MOVQMtoR(freereg,ppf);
MOVQRtoRmOffset(EDX,freereg,0);
MOVQRtoRm(EDX,freereg);
_freeMMXreg(freereg);
}
else
@ -264,7 +264,7 @@ void vtlb_DynGenRead64_Const( u32 bits, u32 addr_const )
MOV32RtoRm(EDX,EAX);
MOV32MtoR(EAX,ppf+4);
MOV32RtoRmOffset(EDX,EAX,4);
MOV32RtoRm(EDX,EAX,4);
}
break;
@ -273,7 +273,7 @@ void vtlb_DynGenRead64_Const( u32 bits, u32 addr_const )
{
const int freereg = _allocTempXMMreg( XMMT_INT, -1 );
SSE2_MOVDQA_M128_to_XMM( freereg, ppf );
SSE2_MOVDQARtoRmOffset(EDX,freereg,0);
SSE2_MOVDQARtoRm(EDX,freereg);
_freeXMMreg(freereg);
}
else
@ -406,8 +406,8 @@ static void _vtlb_DynGen_DirectWrite( u32 bits )
if( _hasFreeMMXreg() )
{
const int freereg = _allocMMXreg(-1, MMX_TEMP, 0);
MOVQRmtoROffset(freereg,EDX,0);
MOVQRtoRmOffset(ECX,freereg,0);
MOVQRmtoR(freereg,EDX);
MOVQRtoRm(ECX,freereg);
_freeMMXreg( freereg );
}
else
@ -415,8 +415,8 @@ static void _vtlb_DynGen_DirectWrite( u32 bits )
MOV32RmtoR(EAX,EDX);
MOV32RtoRm(ECX,EAX);
MOV32RmtoROffset(EAX,EDX,4);
MOV32RtoRmOffset(ECX,EAX,4);
MOV32RmtoR(EAX,EDX,4);
MOV32RtoRm(ECX,EAX,4);
}
break;
@ -424,8 +424,8 @@ static void _vtlb_DynGen_DirectWrite( u32 bits )
if( _hasFreeXMMreg() )
{
const int freereg = _allocTempXMMreg( XMMT_INT, -1 );
SSE2_MOVDQARmtoROffset(freereg,EDX,0);
SSE2_MOVDQARtoRmOffset(ECX,freereg,0);
SSE2_MOVDQARmtoR(freereg,EDX);
SSE2_MOVDQARtoRm(ECX,freereg);
_freeXMMreg( freereg );
}
else
@ -502,7 +502,7 @@ void vtlb_DynGenWrite_Const( u32 bits, u32 addr_const )
if( _hasFreeMMXreg() )
{
const int freereg = _allocMMXreg(-1, MMX_TEMP, 0);
MOVQRmtoROffset(freereg,EDX,0);
MOVQRmtoR(freereg,EDX);
MOVQRtoM(ppf,freereg);
_freeMMXreg( freereg );
}
@ -511,7 +511,7 @@ void vtlb_DynGenWrite_Const( u32 bits, u32 addr_const )
MOV32RmtoR(EAX,EDX);
MOV32RtoM(ppf,EAX);
MOV32RmtoROffset(EAX,EDX,4);
MOV32RmtoR(EAX,EDX,4);
MOV32RtoM(ppf+4,EAX);
}
break;
@ -520,7 +520,7 @@ void vtlb_DynGenWrite_Const( u32 bits, u32 addr_const )
if( _hasFreeXMMreg() )
{
const int freereg = _allocTempXMMreg( XMMT_INT, -1 );
SSE2_MOVDQARmtoROffset(freereg,EDX,0);
SSE2_MOVDQARmtoR(freereg,EDX);
SSE2_MOVDQA_XMM_to_M128(ppf,freereg);
_freeXMMreg( freereg );
}

View File

@ -39,3 +39,199 @@ PCSX2_ALIGNED16(u32 p2[4]);
PCSX2_ALIGNED16(float f[4]);
XMMSSEType g_xmmtypes[XMMREGS] = { XMMT_INT };
namespace x86Emitter
{
const x86IndexerType ptr;
//////////////////////////////////////////////////////////////////////////////////////////
//
const x86Register x86Register::Empty( -1 );
const x86Register eax( 0 );
const x86Register ebx( 3 );
const x86Register ecx( 1 );
const x86Register edx( 2 );
const x86Register esi( 6 );
const x86Register edi( 7 );
const x86Register ebp( 5 );
const x86Register esp( 4 );
const x86Register16 ax( 0 );
const x86Register16 bx( 3 );
const x86Register16 cx( 1 );
const x86Register16 dx( 2 );
const x86Register16 si( 6 );
const x86Register16 di( 7 );
const x86Register16 bp( 5 );
const x86Register16 sp( 4 );
const x86Register8 al( 0 );
const x86Register8 cl( 1 );
const x86Register8 dl( 2 );
const x86Register8 bl( 3 );
const x86Register8 ah( 4 );
const x86Register8 ch( 5 );
const x86Register8 dh( 6 );
const x86Register8 bh( 7 );
//////////////////////////////////////////////////////////////////////////////////////////
// x86Register Method Implementations
//
x86ModRm x86Register::operator+( const x86Register& right ) const
{
return x86ModRm( *this, right );
}
x86ModRm x86Register::operator+( const x86ModRm& right ) const
{
return right + *this;
}
//////////////////////////////////////////////////////////////////////////////////////////
// ModSib Method Implementations
//
x86ModRm x86ModRm::FromIndexReg( x86Register index, int scale, int displacement )
{
return x86ModRm( x86Register::Empty, index, scale, displacement );
}
x86Register x86ModRm::GetEitherReg() const
{
return Base.IsEmpty() ? Base : Index;
}
x86ModRm& x86ModRm::Add( const x86Register& src )
{
if( src == Index )
{
Factor++;
}
else if( src == Base )
{
// Compound the existing register reference into the Index/Scale pair.
Base = x86Register::Empty;
if( src == Index )
Factor++;
else
{
jASSUME( Index.IsEmpty() ); // or die if we already have an index!
Index = src;
Factor = 2;
}
}
else if( Base.IsEmpty() )
Base = src;
else if( Index.IsEmpty() )
Index = src;
else
assert( false ); // oops, only 2 regs allowed per ModRm!
return *this;
}
x86ModRm& x86ModRm::Add( const x86ModRm& src )
{
Add( src.Base );
Add( src.Displacement );
// If the factor is 1, we can just treat index like a base register also.
if( src.Factor == 1 )
{
Add( src.Index );
}
else if( Index.IsEmpty() )
{
Index = src.Index;
Factor = 1;
}
else if( Index == src.Index )
Factor++;
else
assert( false ); // oops, only 2 regs allowed!
return *this;
}
x86ModRm x86ptr( x86Register base ) { return x86ModRm( base ); }
// ------------------------------------------------------------------------
// Generates a 'reduced' ModSib form, which has valid Base, Index, and Scale values.
// Necessary because by default ModSib compounds registers into Index when possible.
//
void ModSib::Reduce()
{
// If no index reg, then nothing for us to do...
if( Index.IsEmpty() || Scale == 0 ) return;
// The Scale has a series of valid forms, all shown here:
switch( Scale )
{
case 1: Scale = 0; break;
case 2: Scale = 1; break;
case 3: // becomes [reg*2+reg]
jASSUME( Base.IsEmpty() );
Base = Index;
Scale = 1;
break;
case 4: Scale = 2; break;
case 5: // becomes [reg*4+reg]
jASSUME( Base.IsEmpty() );
Base = Index;
Scale = 2;
break;
case 6: // invalid!
assert( false );
break;
case 7: // so invalid!
assert( false );
break;
case 8: Scale = 3; break;
case 9: // becomes [reg*8+reg]
jASSUME( Base.IsEmpty() );
Base = Index;
Scale = 3;
break;
}
}
ModSib::ModSib( const x86ModRm& src ) :
Base( src.Base ),
Index( src.Index ),
Scale( src.Factor ),
Displacement( src.Displacement )
{
Reduce();
}
ModSib::ModSib( x86Register base, x86Register index, int scale, s32 displacement ) :
Base( base ),
Index( index ),
Scale( scale ),
Displacement( displacement )
{
Reduce();
}
ModSib::ModSib( s32 displacement ) :
Base(),
Index(),
Scale(0),
Displacement( displacement )
{
}
x86Register ModSib::GetEitherReg() const
{
return Base.IsEmpty() ? Base : Index;
}
}

View File

@ -42,6 +42,11 @@
#define RexRB(w, reg, base) assert( !(w || (reg) >= 8 || (base)>=8) )
#define RexRXB(w, reg, index, base) assert( !(w || (reg) >= 8 || (index) >= 8 || (base) >= 8) )
// We use int param for offsets and then test them for validity in the recompiler.
// This helps catch programmer errors better than using an auto-truncated s8 parameter.
#define assertOffset8(ofs) assert( ofs < 128 && ofs >= -128 )
//------------------------------------------------------------------
// write functions
//------------------------------------------------------------------
@ -49,23 +54,27 @@ extern u8 *x86Ptr[EmitterId_Count];
extern u8 *j8Ptr[32];
extern u32 *j32Ptr[32];
emitterT void write8( u8 val ) {
*x86Ptr[I] = (u8)val;
emitterT void write8( u8 val )
{
*x86Ptr[I] = (u8)val;
x86Ptr[I]++;
}
}
emitterT void write16( u16 val ) {
*(u16*)x86Ptr[I] = (u16)val;
emitterT void write16( u16 val )
{
*(u16*)x86Ptr[I] = val;
x86Ptr[I] += 2;
}
emitterT void write24( u32 val ) {
emitterT void write24( u32 val )
{
*x86Ptr[I]++ = (u8)(val & 0xff);
*x86Ptr[I]++ = (u8)((val >> 8) & 0xff);
*x86Ptr[I]++ = (u8)((val >> 16) & 0xff);
}
emitterT void write32( u32 val ) {
emitterT void write32( u32 val )
{
*(u32*)x86Ptr[I] = val;
x86Ptr[I] += 4;
}
@ -93,7 +102,6 @@ emitterT void ex86AlignExecutable( int align );
//------------------------------------------------------------------
// General Emitter Helper functions
//------------------------------------------------------------------
emitterT void WriteRmOffset(x86IntRegType to, int offset);
emitterT void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset);
emitterT void ModRM( int mod, int reg, int rm );
emitterT void SibSB( int ss, int index, int base );
@ -112,15 +120,12 @@ emitterT void eCALL32( u32 to );
emitterT void eLEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset);
emitterT void eLEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale);
emitterT void eNOP( void );
emitterT void eAND32I8toR( x86IntRegType to, u8 from );
emitterT void eAND32ItoM( uptr to, u32 from );
emitterT void eLEA32RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1);
emitterT void eAND32I8toM( uptr to, u8 from );
emitterT void eLEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale);
#define MMXONLY(code) code
#define _MM_MK_INSERTPS_NDX(srcField, dstField, zeroMask) (((srcField)<<6) | ((dstField)<<4) | (zeroMask))

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,258 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#pragma once
//------------------------------------------------------------------
// x86 Group 1 Instructions
//------------------------------------------------------------------
// Group 1 instructions all adhere to the same encoding scheme, and so they all
// share the same emitter which has been coded here.
//
// Group 1 Table: [column value is the Reg field of the ModRM byte]
//
// 0 1 2 3 4 5 6 7
// ADD OR ADC SBB AND SUB XOR CMP
//
namespace x86Emitter {
static const int ModRm_UseSib = 4; // same index value as ESP (used in RM field)
static const int ModRm_UseDisp32 = 5; // same index value as EBP (used in Mod field)
// ------------------------------------------------------------------------
// returns TRUE if this instruction requires SIB to be encoded, or FALSE if the
// instruction ca be encoded as ModRm alone.
emitterT bool NeedsSibMagic( const ModSib& info )
{
// no registers? no sibs!
if( info.Base.IsEmpty() && info.Index.IsEmpty() ) return false;
// A scaled register needs a SIB
if( info.Scale != 0 && !info.Index.IsEmpty() ) return true;
// two registers needs a SIB
if( !info.Base.IsEmpty() && !info.Index.IsEmpty() ) return true;
// If register is ESP, then we need a SIB:
if( info.Base == esp || info.Index == esp ) return true;
return false;
}
// ------------------------------------------------------------------------
// Conditionally generates Sib encoding information!
//
// regfield - register field to be written to the ModRm. This is either a register specifier
// or an opcode extension. In either case, the instruction determines the value for us.
//
emitterT void EmitSibMagic( int regfield, const ModSib& info )
{
int displacement_size = (info.Displacement == 0) ? 0 :
( ( info.IsByteSizeDisp() ) ? 1 : 2 );
if( !NeedsSibMagic<I>( info ) )
{
// Use ModRm-only encoding, with the rm field holding an index/base register, if
// one has been specified. If neither register is specified then use Disp32 form,
// which is encoded as "EBP w/o displacement" (which is why EBP must always be
// encoded *with* a displacement of 0, if it would otherwise not have one).
x86Register basereg = info.GetEitherReg();
if( basereg.IsEmpty() )
ModRM<I>( 0, regfield, ModRm_UseDisp32 );
else
{
if( basereg == ebp && displacement_size == 0 )
displacement_size = 1; // forces [ebp] to be encoded as [ebp+0]!
ModRM<I>( displacement_size, regfield, basereg.Id );
}
}
else
{
ModRM<I>( displacement_size, regfield, ModRm_UseSib );
SibSB<I>( info.Index.Id, info.Scale, info.Base.Id );
}
switch( displacement_size )
{
case 0: break;
case 1: write8<I>( info.Displacement ); break;
case 2: write32<I>( info.Displacement ); break;
jNO_DEFAULT
}
}
// ------------------------------------------------------------------------
// Conditionally generates Sib encoding information!
//
// regfield - register field to be written to the ModRm. This is either a register specifier
// or an opcode extension. In either case, the instruction determines the value for us.
//
emitterT void EmitSibMagic( x86Register regfield, const ModSib& info )
{
EmitSibMagic<I>( regfield.Id, info );
}
enum Group1InstructionType
{
G1Type_ADD=0,
G1Type_OR,
G1Type_ADC,
G1Type_SBB,
G1Type_AND,
G1Type_SUB,
G1Type_XOR,
G1Type_CMP
};
emitterT void Group1_32( Group1InstructionType inst, x86Register to, x86Register from )
{
write8<I>( 0x01 | (inst<<3) );
ModRM<I>( 3, from.Id, to.Id );
}
emitterT void Group1_32( Group1InstructionType inst, x86Register to, u32 imm )
{
if( is_s8( imm ) )
{
write8<I>( 0x83 );
ModRM<I>( 3, inst, to.Id );
write8<I>( (s8)imm );
}
else
{
if( to == eax )
write8<I>( 0x05 | (inst<<3) );
else
{
write8<I>( 0x81 );
ModRM<I>( 3, inst, to.Id );
}
write32<I>( imm );
}
}
emitterT void Group1_32( Group1InstructionType inst, const ModSib& sibdest, u32 imm )
{
write8<I>( is_s8( imm ) ? 0x83 : 0x81 );
EmitSibMagic<I>( inst, sibdest );
if( is_s8( imm ) )
write8<I>( (s8)imm );
else
write32<I>( imm );
}
emitterT void Group1_32( Group1InstructionType inst, const ModSib& sibdest, x86Register from )
{
write8<I>( 0x01 | (inst<<3) );
EmitSibMagic<I>( from, sibdest );
}
/* add m32 to r32 */
emitterT void Group1_32( Group1InstructionType inst, x86Register to, const ModSib& sibsrc )
{
write8<I>( 0x03 | (inst<<3) );
EmitSibMagic<I>( to, sibsrc );
}
emitterT void Group1_8( Group1InstructionType inst, x86Register to, s8 imm )
{
if( to == eax )
{
write8<I>( 0x04 | (inst<<3) );
write8<I>( imm );
}
else
{
write8<I>( 0x80 );
ModRM<I>( 3, inst, to.Id );
write8<I>( imm );
}
}
//////////////////////////////////////////////////////////////////////////////////////////
//
#define DEFINE_GROUP1_OPCODE( lwr, cod ) \
emitterT void lwr##32( x86Register to, x86Register from ) { Group1_32<I>( G1Type_##cod, to, from ); } \
emitterT void lwr##32( x86Register to, u32 imm ) { Group1_32<I>( G1Type_##cod, to, imm ); } \
emitterT void lwr##32( x86Register to, void* from ) { Group1_32<I>( G1Type_##cod, to, ptr[from] ); } \
emitterT void lwr##32( void* to, x86Register from ) { Group1_32<I>( G1Type_##cod, ptr[to], from ); } \
emitterT void lwr##32( void* to, u32 imm ) { Group1_32<I>( G1Type_##cod, ptr[to], imm ); } \
emitterT void lwr##32( x86Register to, const x86ModRm& from ) { Group1_32<I>( G1Type_##cod, to, ptr[from] ); } \
emitterT void lwr##32( const x86ModRm& to, x86Register from ) { Group1_32<I>( G1Type_##cod, ptr[to], from ); } \
emitterT void lwr##32( const x86ModRm& to, u32 imm ) { Group1_32<I>( G1Type_##cod, ptr[to], imm ); }
DEFINE_GROUP1_OPCODE( add, ADD );
DEFINE_GROUP1_OPCODE( cmp, CMP );
DEFINE_GROUP1_OPCODE( or, OR );
DEFINE_GROUP1_OPCODE( adc, ADC );
DEFINE_GROUP1_OPCODE( sbb, SBB );
DEFINE_GROUP1_OPCODE( and, AND );
DEFINE_GROUP1_OPCODE( sub, SUB );
DEFINE_GROUP1_OPCODE( xor, XOR );
} // end namespace x86Emitter
static __forceinline x86Emitter::x86Register _reghlp( x86IntRegType src )
{
return x86Emitter::x86Register( src );
}
static __forceinline x86Emitter::x86ModRm _mrmhlp( x86IntRegType src )
{
return x86Emitter::x86ModRm( _reghlp(src) );
}
//////////////////////////////////////////////////////////////////////////////////////////
//
#define DEFINE_GROUP1_OPCODE_LEGACY( lwr, cod ) \
emitterT void e##cod##32RtoR( x86IntRegType to, x86IntRegType from ) { x86Emitter::lwr##32<I>( _reghlp(to), _reghlp(from) ); } \
emitterT void e##cod##32ItoR( x86IntRegType to, u32 imm ) { x86Emitter::lwr##32<I>( _reghlp(to), imm ); } \
emitterT void e##cod##32MtoR( x86IntRegType to, uptr from ) { x86Emitter::lwr##32<I>( _reghlp(to), (void*)from ); } \
emitterT void e##cod##32RtoM( uptr to, x86IntRegType from ) { x86Emitter::lwr##32<I>( (void*)to, _reghlp(from) ); } \
emitterT void e##cod##32ItoM( uptr to, u32 imm ) { x86Emitter::lwr##32<I>( (void*)to, imm ); } \
emitterT void e##cod##32ItoRm( x86IntRegType to, u32 imm, int offset=0 ){ x86Emitter::lwr##32<I>( _mrmhlp(to) + offset, imm ); } \
emitterT void e##cod##32RmtoR( x86IntRegType to, x86IntRegType from, int offset=0 ) { x86Emitter::lwr##32<I>( _reghlp(to), _mrmhlp(from) + offset ); } \
emitterT void e##cod##32RtoRm( x86IntRegType to, x86IntRegType from, int offset=0 ) { x86Emitter::lwr##32<I>( _mrmhlp(to) + offset, _reghlp(from) ); }
DEFINE_GROUP1_OPCODE_LEGACY( add, ADD );
DEFINE_GROUP1_OPCODE_LEGACY( cmp, CMP );
DEFINE_GROUP1_OPCODE_LEGACY( or, OR );
DEFINE_GROUP1_OPCODE_LEGACY( adc, ADC );
DEFINE_GROUP1_OPCODE_LEGACY( sbb, SBB );
DEFINE_GROUP1_OPCODE_LEGACY( and, AND );
DEFINE_GROUP1_OPCODE_LEGACY( sub, SUB );
DEFINE_GROUP1_OPCODE_LEGACY( xor, XOR );
emitterT void eAND32I8toR( x86IntRegType to, s8 from )
{
x86Emitter::and32<I>( _reghlp(to), from );
}
emitterT void eAND32I8toM( uptr to, s8 from )
{
x86Emitter::and32<I>( (void*)to, from );
}

View File

@ -51,66 +51,51 @@
//------------------------------------------------------------------
// mov instructions
//------------------------------------------------------------------
#define MOV64RtoR eMOV64RtoR<_EmitterId_>
#define MOV64RtoM eMOV64RtoM<_EmitterId_>
#define MOV64MtoR eMOV64MtoR<_EmitterId_>
#define MOV64I32toM eMOV64I32toM<_EmitterId_>
#define MOV64I32toR eMOV64I32toR<_EmitterId_>
#define MOV64ItoR eMOV64ItoR<_EmitterId_>
#define MOV64ItoRmOffset eMOV64ItoRmOffset<_EmitterId_>
#define MOV64RmOffsettoR eMOV64RmOffsettoR<_EmitterId_>
#define MOV64RmStoR eMOV64RmStoR<_EmitterId_>
#define MOV64RtoRmOffset eMOV64RtoRmOffset<_EmitterId_>
#define MOV64RtoRmS eMOV64RtoRmS<_EmitterId_>
#define MOV32RtoR eMOV32RtoR<_EmitterId_>
#define MOV32RtoM eMOV32RtoM<_EmitterId_>
#define MOV32MtoR eMOV32MtoR<_EmitterId_>
#define MOV32RmtoR eMOV32RmtoR<_EmitterId_>
#define MOV32RmtoROffset eMOV32RmtoROffset<_EmitterId_>
#define MOV32RmtoR eMOV32RmtoR<_EmitterId_>
#define MOV32RmStoR eMOV32RmStoR<_EmitterId_>
#define MOV32RmSOffsettoR eMOV32RmSOffsettoR<_EmitterId_>
#define MOV32RtoRm eMOV32RtoRm<_EmitterId_>
#define MOV32RtoRmS eMOV32RtoRmS<_EmitterId_>
#define MOV32ItoR eMOV32ItoR<_EmitterId_>
#define MOV32ItoM eMOV32ItoM<_EmitterId_>
#define MOV32ItoRmOffset eMOV32ItoRmOffset<_EmitterId_>
#define MOV32RtoRmOffset eMOV32RtoRmOffset<_EmitterId_>
#define MOV32ItoRm eMOV32ItoRm<_EmitterId_>
#define MOV32RtoRm eMOV32RtoRm<_EmitterId_>
#define MOV16RtoM eMOV16RtoM<_EmitterId_>
#define MOV16MtoR eMOV16MtoR<_EmitterId_>
#define MOV16RmtoR eMOV16RmtoR<_EmitterId_>
#define MOV16RmtoROffset eMOV16RmtoROffset<_EmitterId_>
#define MOV16RmtoR eMOV16RmtoR<_EmitterId_>
#define MOV16RmSOffsettoR eMOV16RmSOffsettoR<_EmitterId_>
#define MOV16RtoRm eMOV16RtoRm<_EmitterId_>
#define MOV16ItoM eMOV16ItoM<_EmitterId_>
#define MOV16RtoRmS eMOV16RtoRmS<_EmitterId_>
#define MOV16ItoR eMOV16ItoR<_EmitterId_>
#define MOV16ItoRmOffset eMOV16ItoRmOffset<_EmitterId_>
#define MOV16RtoRmOffset eMOV16RtoRmOffset<_EmitterId_>
#define MOV16ItoRm eMOV16ItoRm<_EmitterId_>
#define MOV16RtoRm eMOV16RtoRm<_EmitterId_>
#define MOV8RtoM eMOV8RtoM<_EmitterId_>
#define MOV8MtoR eMOV8MtoR<_EmitterId_>
#define MOV8RmtoR eMOV8RmtoR<_EmitterId_>
#define MOV8RmtoROffset eMOV8RmtoROffset<_EmitterId_>
#define MOV8RmtoR eMOV8RmtoR<_EmitterId_>
#define MOV8RmSOffsettoR eMOV8RmSOffsettoR<_EmitterId_>
#define MOV8RtoRm eMOV8RtoRm<_EmitterId_>
#define MOV8ItoM eMOV8ItoM<_EmitterId_>
#define MOV8ItoR eMOV8ItoR<_EmitterId_>
#define MOV8ItoRmOffset eMOV8ItoRmOffset<_EmitterId_>
#define MOV8RtoRmOffset eMOV8RtoRmOffset<_EmitterId_>
#define MOV8ItoRm eMOV8ItoRm<_EmitterId_>
#define MOV8RtoRm eMOV8RtoRm<_EmitterId_>
#define MOVSX32R8toR eMOVSX32R8toR<_EmitterId_>
#define MOVSX32Rm8toR eMOVSX32Rm8toR<_EmitterId_>
#define MOVSX32Rm8toROffset eMOVSX32Rm8toROffset<_EmitterId_>
#define MOVSX32M8toR eMOVSX32M8toR<_EmitterId_>
#define MOVSX32R16toR eMOVSX32R16toR<_EmitterId_>
#define MOVSX32Rm16toR eMOVSX32Rm16toR<_EmitterId_>
#define MOVSX32Rm16toROffset eMOVSX32Rm16toROffset<_EmitterId_>
#define MOVSX32M16toR eMOVSX32M16toR<_EmitterId_>
#define MOVZX32R8toR eMOVZX32R8toR<_EmitterId_>
#define MOVZX32Rm8toR eMOVZX32Rm8toR<_EmitterId_>
#define MOVZX32Rm8toROffset eMOVZX32Rm8toROffset<_EmitterId_>
#define MOVZX32M8toR eMOVZX32M8toR<_EmitterId_>
#define MOVZX32R16toR eMOVZX32R16toR<_EmitterId_>
#define MOVZX32Rm16toR eMOVZX32Rm16toR<_EmitterId_>
#define MOVZX32Rm16toROffset eMOVZX32Rm16toROffset<_EmitterId_>
#define MOVZX32M16toR eMOVZX32M16toR<_EmitterId_>
#define CMOVBE32RtoR eCMOVBE32RtoR<_EmitterId_>
#define CMOVBE32MtoR eCMOVBE32MtoR<_EmitterId_>
@ -147,12 +132,10 @@
//------------------------------------------------------------------
// arithmetic instructions
//------------------------------------------------------------------
#define ADD64ItoR eADD64ItoR<_EmitterId_>
#define ADD64MtoR eADD64MtoR<_EmitterId_>
#define ADD32ItoEAX eADD32ItoEAX<_EmitterId_>
#define ADD32ItoR eADD32ItoR<_EmitterId_>
#define ADD32ItoM eADD32ItoM<_EmitterId_>
#define ADD32ItoRmOffset eADD32ItoRmOffset<_EmitterId_>
#define ADD32ItoRm eADD32ItoRm<_EmitterId_>
#define ADD32RtoR eADD32RtoR<_EmitterId_>
#define ADD32RtoM eADD32RtoM<_EmitterId_>
#define ADD32MtoR eADD32MtoR<_EmitterId_>
@ -171,7 +154,6 @@
#define INC32M eINC32M<_EmitterId_>
#define INC16R eINC16R<_EmitterId_>
#define INC16M eINC16M<_EmitterId_>
#define SUB64MtoR eSUB64MtoR<_EmitterId_>
#define SUB32ItoR eSUB32ItoR<_EmitterId_>
#define SUB32ItoM eSUB32ItoM<_EmitterId_>
#define SUB32RtoR eSUB32RtoR<_EmitterId_>
@ -181,7 +163,6 @@
#define SUB16ItoR eSUB16ItoR<_EmitterId_>
#define SUB16ItoM eSUB16ItoM<_EmitterId_>
#define SUB16MtoR eSUB16MtoR<_EmitterId_>
#define SBB64RtoR eSBB64RtoR<_EmitterId_>
#define SBB32ItoR eSBB32ItoR<_EmitterId_>
#define SBB32ItoM eSBB32ItoM<_EmitterId_>
#define SBB32RtoR eSBB32RtoR<_EmitterId_>
@ -203,12 +184,6 @@
//------------------------------------------------------------------
// shifting instructions
//------------------------------------------------------------------
#define SHL64ItoR eSHL64ItoR<_EmitterId_>
#define SHL64CLtoR eSHL64CLtoR<_EmitterId_>
#define SHR64ItoR eSHR64ItoR<_EmitterId_>
#define SHR64CLtoR eSHR64CLtoR<_EmitterId_>
#define SAR64ItoR eSAR64ItoR<_EmitterId_>
#define SAR64CLtoR eSAR64CLtoR<_EmitterId_>
#define SHL32ItoR eSHL32ItoR<_EmitterId_>
#define SHL32ItoM eSHL32ItoM<_EmitterId_>
#define SHL32CLtoR eSHL32CLtoR<_EmitterId_>
@ -231,10 +206,6 @@
//------------------------------------------------------------------
// logical instructions
//------------------------------------------------------------------
#define OR64ItoR eOR64ItoR<_EmitterId_>
#define OR64MtoR eOR64MtoR<_EmitterId_>
#define OR64RtoR eOR64RtoR<_EmitterId_>
#define OR64RtoM eOR64RtoM<_EmitterId_>
#define OR32ItoR eOR32ItoR<_EmitterId_>
#define OR32ItoM eOR32ItoM<_EmitterId_>
#define OR32RtoR eOR32RtoR<_EmitterId_>
@ -249,11 +220,6 @@
#define OR8RtoM eOR8RtoM<_EmitterId_>
#define OR8ItoM eOR8ItoM<_EmitterId_>
#define OR8MtoR eOR8MtoR<_EmitterId_>
#define XOR64ItoR eXOR64ItoR<_EmitterId_>
#define XOR64RtoR eXOR64RtoR<_EmitterId_>
#define XOR64MtoR eXOR64MtoR<_EmitterId_>
#define XOR64RtoR eXOR64RtoR<_EmitterId_>
#define XOR64RtoM eXOR64RtoM<_EmitterId_>
#define XOR32ItoR eXOR32ItoR<_EmitterId_>
#define XOR32ItoM eXOR32ItoM<_EmitterId_>
#define XOR32RtoR eXOR32RtoR<_EmitterId_>
@ -262,11 +228,6 @@
#define XOR32MtoR eXOR32MtoR<_EmitterId_>
#define XOR16RtoM eXOR16RtoM<_EmitterId_>
#define XOR16ItoR eXOR16ItoR<_EmitterId_>
#define AND64I32toR eAND64I32toR<_EmitterId_>
#define AND64MtoR eAND64MtoR<_EmitterId_>
#define AND64RtoM eAND64RtoM<_EmitterId_>
#define AND64RtoR eAND64RtoR<_EmitterId_>
#define AND64I32toM eAND64I32toM<_EmitterId_>
#define AND32ItoR eAND32ItoR<_EmitterId_>
#define AND32I8toR eAND32I8toR<_EmitterId_>
#define AND32ItoM eAND32ItoM<_EmitterId_>
@ -275,7 +236,7 @@
#define AND32RtoM eAND32RtoM<_EmitterId_>
#define AND32MtoR eAND32MtoR<_EmitterId_>
#define AND32RmtoR eAND32RmtoR<_EmitterId_>
#define AND32RmtoROffset eAND32RmtoROffset<_EmitterId_>
#define AND32RmtoR eAND32RmtoR<_EmitterId_>
#define AND16RtoR eAND16RtoR<_EmitterId_>
#define AND16ItoR eAND16ItoR<_EmitterId_>
#define AND16ItoM eAND16ItoM<_EmitterId_>
@ -286,10 +247,8 @@
#define AND8RtoM eAND8RtoM<_EmitterId_>
#define AND8MtoR eAND8MtoR<_EmitterId_>
#define AND8RtoR eAND8RtoR<_EmitterId_>
#define NOT64R eNOT64R<_EmitterId_>
#define NOT32R eNOT32R<_EmitterId_>
#define NOT32M eNOT32M<_EmitterId_>
#define NEG64R eNEG64R<_EmitterId_>
#define NEG32R eNEG32R<_EmitterId_>
#define NEG32M eNEG32M<_EmitterId_>
#define NEG16R eNEG16R<_EmitterId_>
@ -349,15 +308,13 @@
//------------------------------------------------------------------
// misc instructions
//------------------------------------------------------------------
#define CMP64I32toR eCMP64I32toR<_EmitterId_>
#define CMP64MtoR eCMP64MtoR<_EmitterId_>
#define CMP64RtoR eCMP64RtoR<_EmitterId_>
#define CMP32ItoR eCMP32ItoR<_EmitterId_>
#define CMP32ItoM eCMP32ItoM<_EmitterId_>
#define CMP32RtoR eCMP32RtoR<_EmitterId_>
#define CMP32MtoR eCMP32MtoR<_EmitterId_>
#define CMP32ItoRm eCMP32ItoRm<_EmitterId_>
#define CMP8I8toRm eCMP8I8toRm<_EmitterId_>
#define CMP32I8toRm eCMP32I8toRm<_EmitterId_>
#define CMP32I8toRmOffset8 eCMP32I8toRmOffset8<_EmitterId_>
#define CMP32I8toM eCMP32I8toM<_EmitterId_>
#define CMP16ItoR eCMP16ItoR<_EmitterId_>
#define CMP16ItoM eCMP16ItoM<_EmitterId_>
@ -539,16 +496,16 @@
#define PUNPCKHDQMtoR ePUNPCKHDQMtoR<_EmitterId_>
#define MOVQ64ItoR eMOVQ64ItoR<_EmitterId_>
#define MOVQRtoR eMOVQRtoR<_EmitterId_>
#define MOVQRmtoROffset eMOVQRmtoROffset<_EmitterId_>
#define MOVQRtoRmOffset eMOVQRtoRmOffset<_EmitterId_>
#define MOVQRmtoR eMOVQRmtoR<_EmitterId_>
#define MOVQRtoRm eMOVQRtoRm<_EmitterId_>
#define MOVDMtoMMX eMOVDMtoMMX<_EmitterId_>
#define MOVDMMXtoM eMOVDMMXtoM<_EmitterId_>
#define MOVD32RtoMMX eMOVD32RtoMMX<_EmitterId_>
#define MOVD32RmtoMMX eMOVD32RmtoMMX<_EmitterId_>
#define MOVD32RmOffsettoMMX eMOVD32RmOffsettoMMX<_EmitterId_>
#define MOVD32RmtoMMX eMOVD32RmtoMMX<_EmitterId_>
#define MOVD32MMXtoR eMOVD32MMXtoR<_EmitterId_>
#define MOVD32MMXtoRm eMOVD32MMXtoRm<_EmitterId_>
#define MOVD32MMXtoRmOffset eMOVD32MMXtoRmOffset<_EmitterId_>
#define MOVD32MMXtoRm eMOVD32MMXtoRm<_EmitterId_>
#define PINSRWRtoMMX ePINSRWRtoMMX<_EmitterId_>
#define PSHUFWRtoR ePSHUFWRtoR<_EmitterId_>
#define PSHUFWMtoR ePSHUFWMtoR<_EmitterId_>
@ -575,33 +532,31 @@
#define SSE_MOVSS_XMM_to_M32 eSSE_MOVSS_XMM_to_M32<_EmitterId_>
#define SSE_MOVSS_XMM_to_Rm eSSE_MOVSS_XMM_to_Rm<_EmitterId_>
#define SSE_MOVSS_XMM_to_XMM eSSE_MOVSS_XMM_to_XMM<_EmitterId_>
#define SSE_MOVSS_RmOffset_to_XMM eSSE_MOVSS_RmOffset_to_XMM<_EmitterId_>
#define SSE_MOVSS_XMM_to_RmOffset eSSE_MOVSS_XMM_to_RmOffset<_EmitterId_>
#define SSE_MOVSS_Rm_to_XMM eSSE_MOVSS_Rm_to_XMM<_EmitterId_>
#define SSE_MOVSS_XMM_to_Rm eSSE_MOVSS_XMM_to_Rm<_EmitterId_>
#define SSE_MASKMOVDQU_XMM_to_XMM eSSE_MASKMOVDQU_XMM_to_XMM<_EmitterId_>
#define SSE_MOVLPS_M64_to_XMM eSSE_MOVLPS_M64_to_XMM<_EmitterId_>
#define SSE_MOVLPS_XMM_to_M64 eSSE_MOVLPS_XMM_to_M64<_EmitterId_>
#define SSE_MOVLPS_RmOffset_to_XMM eSSE_MOVLPS_RmOffset_to_XMM<_EmitterId_>
#define SSE_MOVLPS_XMM_to_RmOffset eSSE_MOVLPS_XMM_to_RmOffset<_EmitterId_>
#define SSE_MOVLPS_Rm_to_XMM eSSE_MOVLPS_Rm_to_XMM<_EmitterId_>
#define SSE_MOVLPS_XMM_to_Rm eSSE_MOVLPS_XMM_to_Rm<_EmitterId_>
#define SSE_MOVHPS_M64_to_XMM eSSE_MOVHPS_M64_to_XMM<_EmitterId_>
#define SSE_MOVHPS_XMM_to_M64 eSSE_MOVHPS_XMM_to_M64<_EmitterId_>
#define SSE_MOVHPS_RmOffset_to_XMM eSSE_MOVHPS_RmOffset_to_XMM<_EmitterId_>
#define SSE_MOVHPS_XMM_to_RmOffset eSSE_MOVHPS_XMM_to_RmOffset<_EmitterId_>
#define SSE_MOVHPS_Rm_to_XMM eSSE_MOVHPS_Rm_to_XMM<_EmitterId_>
#define SSE_MOVHPS_XMM_to_Rm eSSE_MOVHPS_XMM_to_Rm<_EmitterId_>
#define SSE_MOVLHPS_XMM_to_XMM eSSE_MOVLHPS_XMM_to_XMM<_EmitterId_>
#define SSE_MOVHLPS_XMM_to_XMM eSSE_MOVHLPS_XMM_to_XMM<_EmitterId_>
#define SSE_MOVLPSRmtoR eSSE_MOVLPSRmtoR<_EmitterId_>
#define SSE_MOVLPSRmtoROffset eSSE_MOVLPSRmtoROffset<_EmitterId_>
#define SSE_MOVLPSRtoRm eSSE_MOVLPSRtoRm<_EmitterId_>
#define SSE_MOVLPSRtoRmOffset eSSE_MOVLPSRtoRmOffset<_EmitterId_>
#define SSE_MOVAPSRmStoR eSSE_MOVAPSRmStoR<_EmitterId_>
#define SSE_MOVAPSRtoRmS eSSE_MOVAPSRtoRmS<_EmitterId_>
#define SSE_MOVAPSRtoRmOffset eSSE_MOVAPSRtoRmOffset<_EmitterId_>
#define SSE_MOVAPSRmtoROffset eSSE_MOVAPSRmtoROffset<_EmitterId_>
#define SSE_MOVAPSRtoRm eSSE_MOVAPSRtoRm<_EmitterId_>
#define SSE_MOVAPSRmtoR eSSE_MOVAPSRmtoR<_EmitterId_>
#define SSE_MOVUPSRmStoR eSSE_MOVUPSRmStoR<_EmitterId_>
#define SSE_MOVUPSRtoRmS eSSE_MOVUPSRtoRmS<_EmitterId_>
#define SSE_MOVUPSRtoRm eSSE_MOVUPSRtoRm<_EmitterId_>
#define SSE_MOVUPSRmtoR eSSE_MOVUPSRmtoR<_EmitterId_>
#define SSE_MOVUPSRmtoROffset eSSE_MOVUPSRmtoROffset<_EmitterId_>
#define SSE_MOVUPSRtoRmOffset eSSE_MOVUPSRtoRmOffset<_EmitterId_>
#define SSE_MOVUPSRmtoR eSSE_MOVUPSRmtoR<_EmitterId_>
#define SSE_MOVUPSRtoRm eSSE_MOVUPSRtoRm<_EmitterId_>
#define SSE_RCPPS_XMM_to_XMM eSSE_RCPPS_XMM_to_XMM<_EmitterId_>
#define SSE_RCPPS_M128_to_XMM eSSE_RCPPS_M128_to_XMM<_EmitterId_>
#define SSE_RCPSS_XMM_to_XMM eSSE_RCPSS_XMM_to_XMM<_EmitterId_>
@ -676,7 +631,7 @@
#define SSE_UNPCKHPS_XMM_to_XMM eSSE_UNPCKHPS_XMM_to_XMM<_EmitterId_>
#define SSE_SHUFPS_XMM_to_XMM eSSE_SHUFPS_XMM_to_XMM<_EmitterId_>
#define SSE_SHUFPS_M128_to_XMM eSSE_SHUFPS_M128_to_XMM<_EmitterId_>
#define SSE_SHUFPS_RmOffset_to_XMM eSSE_SHUFPS_RmOffset_to_XMM<_EmitterId_>
#define SSE_SHUFPS_Rm_to_XMM eSSE_SHUFPS_Rm_to_XMM<_EmitterId_>
#define SSE_CMPEQPS_M128_to_XMM eSSE_CMPEQPS_M128_to_XMM<_EmitterId_>
#define SSE_CMPEQPS_XMM_to_XMM eSSE_CMPEQPS_XMM_to_XMM<_EmitterId_>
#define SSE_CMPLTPS_M128_to_XMM eSSE_CMPLTPS_M128_to_XMM<_EmitterId_>
@ -780,8 +735,8 @@
#define SSE2_MOVQ_XMM_to_M64 eSSE2_MOVQ_XMM_to_M64<_EmitterId_>
#define SSE2_MOVDQ2Q_XMM_to_MM eSSE2_MOVDQ2Q_XMM_to_MM<_EmitterId_>
#define SSE2_MOVQ2DQ_MM_to_XMM eSSE2_MOVQ2DQ_MM_to_XMM<_EmitterId_>
#define SSE2_MOVDQARtoRmOffset eSSE2_MOVDQARtoRmOffset<_EmitterId_>
#define SSE2_MOVDQARmtoROffset eSSE2_MOVDQARmtoROffset<_EmitterId_>
#define SSE2_MOVDQARtoRm eSSE2_MOVDQARtoRm<_EmitterId_>
#define SSE2_MOVDQARmtoR eSSE2_MOVDQARmtoR<_EmitterId_>
#define SSE2_CVTDQ2PS_M128_to_XMM eSSE2_CVTDQ2PS_M128_to_XMM<_EmitterId_>
#define SSE2_CVTDQ2PS_XMM_to_XMM eSSE2_CVTDQ2PS_XMM_to_XMM<_EmitterId_>
#define SSE2_CVTPS2DQ_M128_to_XMM eSSE2_CVTPS2DQ_M128_to_XMM<_EmitterId_>
@ -920,11 +875,11 @@
#define SSE2_MOVD_M32_to_XMM eSSE2_MOVD_M32_to_XMM<_EmitterId_>
#define SSE2_MOVD_R_to_XMM eSSE2_MOVD_R_to_XMM<_EmitterId_>
#define SSE2_MOVD_Rm_to_XMM eSSE2_MOVD_Rm_to_XMM<_EmitterId_>
#define SSE2_MOVD_RmOffset_to_XMM eSSE2_MOVD_RmOffset_to_XMM<_EmitterId_>
#define SSE2_MOVD_Rm_to_XMM eSSE2_MOVD_Rm_to_XMM<_EmitterId_>
#define SSE2_MOVD_XMM_to_M32 eSSE2_MOVD_XMM_to_M32<_EmitterId_>
#define SSE2_MOVD_XMM_to_R eSSE2_MOVD_XMM_to_R<_EmitterId_>
#define SSE2_MOVD_XMM_to_Rm eSSE2_MOVD_XMM_to_Rm<_EmitterId_>
#define SSE2_MOVD_XMM_to_RmOffset eSSE2_MOVD_XMM_to_RmOffset<_EmitterId_>
#define SSE2_MOVD_XMM_to_Rm eSSE2_MOVD_XMM_to_Rm<_EmitterId_>
#define SSE2_MOVQ_XMM_to_R eSSE2_MOVQ_XMM_to_R<_EmitterId_>
#define SSE2_MOVQ_R_to_XMM eSSE2_MOVQ_R_to_XMM<_EmitterId_>
//------------------------------------------------------------------

View File

@ -482,11 +482,11 @@ emitterT void eMOVQRtoR( x86MMXRegType to, x86MMXRegType from )
ModRM<I>( 3, to, from );
}
emitterT void eMOVQRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset )
emitterT void eMOVQRmtoR( x86MMXRegType to, x86IntRegType from, int offset=0 )
{
write16<I>( 0x6F0F );
if( offset < 128 ) {
if( offset < 128 && offset >= -128) {
ModRM<I>( 1, to, from );
write8<I>(offset);
}
@ -496,11 +496,11 @@ emitterT void eMOVQRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset
}
}
emitterT void eMOVQRtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset )
emitterT void eMOVQRtoRm( x86IntRegType to, x86MMXRegType from, int offset=0 )
{
write16<I>( 0x7F0F );
if( offset < 128 ) {
if( offset < 128 && offset >= -128) {
ModRM<I>( 1, from , to );
write8<I>(offset);
}

View File

@ -18,18 +18,22 @@
#pragma once
//------------------------------------------------------------------
// SSE instructions
//------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////////////////////
// AlwaysUseMovaps [const]
//
// This tells the recompiler's emitter to always use movaps instead of movdqa. Both instructions
// do the exact same thing, but movaps is 1 byte shorter, and thus results in a cleaner L1 cache
// and some marginal speed gains as a result. (it's possible someday in the future the per-
// formance of the two instructions could change, so this constant is provided to restore MOVDQA
// use easily at a later time, if needed).
//
static const bool AlwaysUseMovaps = true;
//------------------------------------------------------------------
// SSE instructions
//------------------------------------------------------------------
#define SSEMtoR( code, overb ) \
assert( to < XMMREGS ), \
RexR(0, to), \
@ -140,7 +144,7 @@ static const bool AlwaysUseMovaps = true;
write8<I>( op )
/* movups [r32][r32*scale] to xmm1 */
emitterT void eSSE_MOVUPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale )
emitterT void eSSE_MOVUPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale=0 )
{
RexRXB(0, to, from2, from);
write16<I>( 0x100f );
@ -149,7 +153,7 @@ emitterT void eSSE_MOVUPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntReg
}
/* movups xmm1 to [r32][r32*scale] */
emitterT void eSSE_MOVUPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale )
emitterT void eSSE_MOVUPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale=0 )
{
RexRXB(1, to, from2, from);
write16<I>( 0x110f );
@ -181,7 +185,7 @@ emitterT void eSSE_MOVLPSRmtoR( x86SSERegType to, x86IntRegType from )
ModRM<I>( 0, to, from );
}
emitterT void eSSE_MOVLPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset )
emitterT void eSSE_MOVLPSRmtoR( x86SSERegType to, x86IntRegType from, int offset=0 )
{
RexRB(0, to, from);
write16<I>( 0x120f );
@ -196,7 +200,7 @@ emitterT void eSSE_MOVLPSRtoRm( x86IntRegType to, x86IntRegType from )
ModRM<I>( 0, from, to );
}
emitterT void eSSE_MOVLPSRtoRmOffset( x86SSERegType to, x86IntRegType from, int offset )
emitterT void eSSE_MOVLPSRtoRm( x86SSERegType to, x86IntRegType from, int offset=0 )
{
RexRB(0, from, to);
write16<I>( 0x130f );
@ -204,7 +208,7 @@ emitterT void eSSE_MOVLPSRtoRmOffset( x86SSERegType to, x86IntRegType from, int
}
/* movaps [r32][r32*scale] to xmm1 */
emitterT void eSSE_MOVAPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale )
emitterT void eSSE_MOVAPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale=0 )
{
assert( from != EBP );
RexRXB(0, to, from2, from);
@ -214,7 +218,7 @@ emitterT void eSSE_MOVAPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntReg
}
/* movaps xmm1 to [r32][r32*scale] */
emitterT void eSSE_MOVAPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale )
emitterT void eSSE_MOVAPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale=0 )
{
assert( from != EBP );
RexRXB(0, to, from2, from);
@ -224,7 +228,7 @@ emitterT void eSSE_MOVAPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntReg
}
// movaps [r32+offset] to r32
emitterT void eSSE_MOVAPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset )
emitterT void eSSE_MOVAPSRmtoR( x86SSERegType to, x86IntRegType from, int offset=0 )
{
RexRB(0, to, from);
write16<I>( 0x280f );
@ -232,7 +236,7 @@ emitterT void eSSE_MOVAPSRmtoROffset( x86SSERegType to, x86IntRegType from, int
}
// movaps r32 to [r32+offset]
emitterT void eSSE_MOVAPSRtoRmOffset( x86IntRegType to, x86SSERegType from, int offset )
emitterT void eSSE_MOVAPSRtoRm( x86IntRegType to, x86SSERegType from, int offset=0 )
{
RexRB(0, from, to);
write16<I>( 0x290f );
@ -240,10 +244,10 @@ emitterT void eSSE_MOVAPSRtoRmOffset( x86IntRegType to, x86SSERegType from, int
}
// movdqa [r32+offset] to r32
emitterT void eSSE2_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, int offset )
emitterT void eSSE2_MOVDQARmtoR( x86SSERegType to, x86IntRegType from, int offset=0 )
{
if( AlwaysUseMovaps )
eSSE_MOVAPSRmtoROffset<I>( to, from, offset );
eSSE_MOVAPSRmtoR<I>( to, from, offset );
else
{
write8<I>(0x66);
@ -254,10 +258,10 @@ emitterT void eSSE2_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, int
}
// movdqa r32 to [r32+offset]
emitterT void eSSE2_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, int offset )
emitterT void eSSE2_MOVDQARtoRm( x86IntRegType to, x86SSERegType from, int offset=0 )
{
if( AlwaysUseMovaps )
eSSE_MOVAPSRtoRmOffset<I>( to, from, offset );
eSSE_MOVAPSRtoRm<I>( to, from, offset );
else
{
write8<I>(0x66);
@ -268,7 +272,7 @@ emitterT void eSSE2_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, int
}
// movups [r32+offset] to r32
emitterT void eSSE_MOVUPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset )
emitterT void eSSE_MOVUPSRmtoR( x86SSERegType to, x86IntRegType from, int offset=0 )
{
RexRB(0, to, from);
write16<I>( 0x100f );
@ -276,7 +280,7 @@ emitterT void eSSE_MOVUPSRmtoROffset( x86SSERegType to, x86IntRegType from, int
}
// movups r32 to [r32+offset]
emitterT void eSSE_MOVUPSRtoRmOffset( x86IntRegType to, x86SSERegType from, int offset )
emitterT void eSSE_MOVUPSRtoRm( x86IntRegType to, x86SSERegType from, int offset=0 )
{
RexRB(0, from, to);
write16<I>( 0x110f );
@ -328,17 +332,10 @@ emitterT void eSSE2_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from)
//**********************************************************************************
emitterT void eSSE_MOVSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x100f, 0 ); }
emitterT void eSSE_MOVSS_XMM_to_M32( u32 to, x86SSERegType from ) { SSE_SS_RtoM( 0x110f, 0 ); }
emitterT void eSSE_MOVSS_XMM_to_Rm( x86IntRegType to, x86SSERegType from )
{
write8<I>(0xf3);
RexRB(0, from, to);
write16<I>(0x110f);
ModRM<I>(0, from, to);
}
emitterT void eSSE_MOVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { if (to != from) { SSE_SS_RtoR( 0x100f ); } }
emitterT void eSSE_MOVSS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset )
emitterT void eSSE_MOVSS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset=0 )
{
write8<I>(0xf3);
RexRB(0, to, from);
@ -346,7 +343,7 @@ emitterT void eSSE_MOVSS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from,
WriteRmOffsetFrom<I>(to, from, offset);
}
emitterT void eSSE_MOVSS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset )
emitterT void eSSE_MOVSS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset=0 )
{
write8<I>(0xf3);
RexRB(0, from, to);
@ -361,14 +358,14 @@ emitterT void eSSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from )
emitterT void eSSE_MOVLPS_M64_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x120f, 0 ); }
emitterT void eSSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from ) { SSERtoM( 0x130f, 0 ); }
emitterT void eSSE_MOVLPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset )
emitterT void eSSE_MOVLPS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset=0 )
{
RexRB(0, to, from);
write16<I>( 0x120f );
WriteRmOffsetFrom<I>(to, from, offset);
}
emitterT void eSSE_MOVLPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset )
emitterT void eSSE_MOVLPS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset=0 )
{
RexRB(0, from, to);
write16<I>(0x130f);
@ -382,14 +379,14 @@ emitterT void eSSE_MOVLPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from,
emitterT void eSSE_MOVHPS_M64_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x160f, 0 ); }
emitterT void eSSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from ) { SSERtoM( 0x170f, 0 ); }
emitterT void eSSE_MOVHPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset )
emitterT void eSSE_MOVHPS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset=0 )
{
RexRB(0, to, from);
write16<I>( 0x160f );
WriteRmOffsetFrom<I>(to, from, offset);
}
emitterT void eSSE_MOVHPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset )
emitterT void eSSE_MOVHPS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset=0 )
{
RexRB(0, from, to);
write16<I>(0x170f);
@ -756,7 +753,7 @@ emitterT void eSSE_PMINSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ){ SSER
emitterT void eSSE_SHUFPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { SSERtoR( 0xC60F ); write8<I>( imm8 ); }
emitterT void eSSE_SHUFPS_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { SSEMtoR( 0xC60F, 1 ); write8<I>( imm8 ); }
emitterT void eSSE_SHUFPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset, u8 imm8 )
emitterT void eSSE_SHUFPS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset, u8 imm8 )
{
RexRB(0, to, from);
write16<I>(0xc60f);
@ -903,7 +900,7 @@ emitterT void eSSE2_MOVD_Rm_to_XMM( x86SSERegType to, x86IntRegType from )
ModRM<I>( 0, to, from);
}
emitterT void eSSE2_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset )
emitterT void eSSE2_MOVD_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset=0 )
{
write8<I>(0x66);
RexRB(0, to, from);
@ -914,15 +911,7 @@ emitterT void eSSE2_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from,
emitterT void eSSE2_MOVD_XMM_to_M32( u32 to, x86SSERegType from ) { SSERtoM66(0x7E0F); }
emitterT void eSSE2_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ) { _SSERtoR66(0x7E0F); }
emitterT void eSSE2_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from )
{
write8<I>(0x66);
RexRB(0, from, to);
write16<I>( 0x7e0f );
ModRM<I>( 0, from, to );
}
emitterT void eSSE2_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset )
emitterT void eSSE2_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset=0 )
{
write8<I>(0x66);
RexRB(0, from, to);

View File

@ -47,16 +47,16 @@ static __forceinline void SSEX_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegTyp
else SSE_MOVAPS_XMM_to_XMM(to, from);
}
static __forceinline void SSEX_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, int offset )
static __forceinline void SSEX_MOVDQARmtoR( x86SSERegType to, x86IntRegType from, int offset=0 )
{
if( !AlwaysUseMovaps && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQARmtoROffset(to, from, offset);
else SSE_MOVAPSRmtoROffset(to, from, offset);
if( !AlwaysUseMovaps && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQARmtoR(to, from, offset);
else SSE_MOVAPSRmtoR(to, from, offset);
}
static __forceinline void SSEX_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, int offset )
static __forceinline void SSEX_MOVDQARtoRm( x86IntRegType to, x86SSERegType from, int offset=0 )
{
if( !AlwaysUseMovaps && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQARtoRmOffset(to, from, offset);
else SSE_MOVAPSRtoRmOffset(to, from, offset);
if( !AlwaysUseMovaps && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQARtoRm(to, from, offset);
else SSE_MOVAPSRtoRm(to, from, offset);
}
static __forceinline void SSEX_MOVDQU_M128_to_XMM( x86SSERegType to, uptr from )
@ -83,22 +83,16 @@ static __forceinline void SSEX_MOVD_XMM_to_M32( u32 to, x86SSERegType from )
else SSE_MOVSS_XMM_to_M32(to, from);
}
static __forceinline void SSEX_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from )
static __forceinline void SSEX_MOVD_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset=0 )
{
if( g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_Rm(to, from);
else SSE_MOVSS_XMM_to_Rm(to, from);
if( g_xmmtypes[to] == XMMT_INT ) SSE2_MOVD_Rm_to_XMM(to, from, offset);
else SSE_MOVSS_Rm_to_XMM(to, from, offset);
}
static __forceinline void SSEX_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset )
static __forceinline void SSEX_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset=0 )
{
if( g_xmmtypes[to] == XMMT_INT ) SSE2_MOVD_RmOffset_to_XMM(to, from, offset);
else SSE_MOVSS_RmOffset_to_XMM(to, from, offset);
}
static __forceinline void SSEX_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset )
{
if( g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_RmOffset(to, from, offset);
else SSE_MOVSS_XMM_to_RmOffset(to, from, offset);
if( g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_Rm(to, from, offset);
else SSE_MOVSS_XMM_to_Rm(to, from, offset);
}
static __forceinline void SSEX_POR_M128_to_XMM( x86SSERegType to, uptr from )

View File

@ -29,6 +29,7 @@
// general types
typedef int x86IntRegType;
#define EAX 0
#define EBX 3
#define ECX 1
@ -149,3 +150,211 @@ struct CPUINFO{
extern CPUINFO cpuinfo;
//------------------------------------------------------------------
static __forceinline bool is_s8( u32 imm ) { return (s8)imm == (s32)imm; }
namespace x86Emitter
{
class x86ModRm;
//////////////////////////////////////////////////////////////////////////////////////////
//
struct x86Register
{
static const x86Register Empty; // defined as an empty/unused value (-1)
int Id;
x86Register( const x86Register& src ) : Id( src.Id ) {}
x86Register() : Id( -1 ) {}
explicit x86Register( int regId ) : Id( regId ) { }
bool IsEmpty() const { return Id == -1; }
bool operator==( const x86Register& src ) const { return Id == src.Id; }
bool operator!=( const x86Register& src ) const { return Id != src.Id; }
x86ModRm operator+( const x86Register& right ) const;
x86ModRm operator+( const x86ModRm& right ) const;
x86Register& operator=( const x86Register& src )
{
Id = src.Id;
return *this;
}
};
//////////////////////////////////////////////////////////////////////////////////////////
// Similar to x86Register, but without the ability to add/combine them with ModSib.
//
class x86Register16
{
public:
static const x86Register16 Empty;
int Id;
x86Register16( const x86Register16& src ) : Id( src.Id ) {}
x86Register16() : Id( -1 ) {}
explicit x86Register16( int regId ) : Id( regId ) { }
bool IsEmpty() const { return Id == -1; }
bool operator==( const x86Register16& src ) const { return Id == src.Id; }
bool operator!=( const x86Register16& src ) const { return Id != src.Id; }
x86Register16& operator=( const x86Register16& src )
{
Id = src.Id;
return *this;
}
};
//////////////////////////////////////////////////////////////////////////////////////////
// Similar to x86Register, but without the ability to add/combine them with ModSib.
//
class x86Register8
{
public:
static const x86Register8 Empty;
int Id;
x86Register8( const x86Register16& src ) : Id( src.Id ) {}
x86Register8() : Id( -1 ) {}
explicit x86Register8( int regId ) : Id( regId ) { }
bool IsEmpty() const { return Id == -1; }
bool operator==( const x86Register8& src ) const { return Id == src.Id; }
bool operator!=( const x86Register8& src ) const { return Id != src.Id; }
x86Register8& operator=( const x86Register8& src )
{
Id = src.Id;
return *this;
}
};
//////////////////////////////////////////////////////////////////////////////////////////
//
class x86ModRm
{
public:
x86Register Base; // base register (no scale)
x86Register Index; // index reg gets multiplied by the scale
int Factor; // scale applied to the index register, in factor form (not a shift!)
s32 Displacement; // address displacement
public:
x86ModRm( x86Register base, x86Register index, int factor=1, s32 displacement=0 ) :
Base( base ),
Index( index ),
Factor( factor ),
Displacement( displacement )
{
}
explicit x86ModRm( x86Register base, int displacement=0 ) :
Base( base ),
Index(),
Factor(0),
Displacement( displacement )
{
}
explicit x86ModRm( s32 displacement ) :
Base(),
Index(),
Factor(0),
Displacement( displacement )
{
}
static x86ModRm FromIndexReg( x86Register index, int scale=0, s32 displacement=0 );
public:
bool IsByteSizeDisp() const { return is_s8( Displacement ); }
x86Register GetEitherReg() const;
x86ModRm& Add( s32 imm )
{
Displacement += imm;
return *this;
}
x86ModRm& Add( const x86Register& src );
x86ModRm& Add( const x86ModRm& src );
x86ModRm operator+( const x86Register& right ) const { return x86ModRm( *this ).Add( right ); }
x86ModRm operator+( const x86ModRm& right ) const { return x86ModRm( *this ).Add( right ); }
x86ModRm operator+( const s32 imm ) const { return x86ModRm( *this ).Add( imm ); }
x86ModRm operator-( const s32 imm ) const { return x86ModRm( *this ).Add( -imm ); }
};
//////////////////////////////////////////////////////////////////////////////////////////
// ModSib - Internal low-level representation of the ModRM/SIB information.
//
// This class serves two purposes: It houses 'reduced' ModRM/SIB info only, which means that
// the Base, Index, Scale, and Displacement values are all valid, and it serves as a type-
// safe layer between the x86Register's operators (which generate x86ModRm types) and the
// emitter's ModSib instruction forms. Without this, the x86Register would pass as a
// ModSib type implicitly, and that would cause ambiguity on a number of instructions.
//
class ModSib
{
public:
x86Register Base; // base register (no scale)
x86Register Index; // index reg gets multiplied by the scale
int Scale; // scale applied to the index register, in scale/shift form
s32 Displacement; // offset applied to the Base/Index registers.
ModSib( const x86ModRm& src );
ModSib( x86Register base, x86Register index, int scale=0, s32 displacement=0 );
ModSib( s32 disp );
x86Register GetEitherReg() const;
bool IsByteSizeDisp() const { return is_s8( Displacement ); }
protected:
void Reduce();
};
//////////////////////////////////////////////////////////////////////////////////////////
// x86IndexerType - This is a static class which provisions our ptr[] syntax.
//
struct x86IndexerType
{
ModSib operator[]( x86Register src ) const
{
return ModSib( src, x86Register::Empty );
}
ModSib operator[]( const x86ModRm& src ) const
{
return ModSib( src );
}
ModSib operator[]( uptr src ) const
{
return ModSib( src );
}
ModSib operator[]( void* src ) const
{
return ModSib( (uptr)src );
}
};
// ------------------------------------------------------------------------
extern const x86Register eax;
extern const x86Register ebx;
extern const x86Register ecx;
extern const x86Register edx;
extern const x86Register esi;
extern const x86Register edi;
extern const x86Register ebp;
extern const x86Register esp;
extern const x86IndexerType ptr;
}