mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
60e7428671
commit
2588dc0309
|
@ -2982,6 +2982,10 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\ix86\ix86_group1.inl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\ix86\ix86_macros.h"
|
||||
>
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 ] );
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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 );
|
||||
}
|
|
@ -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_>
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue