652 lines
12 KiB
C
652 lines
12 KiB
C
// stop compiling if NORECBUILD build (only for Visual Studio)
|
|
|
|
#ifdef __x86_64__
|
|
|
|
#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD))
|
|
|
|
#include "ix86-64.h"
|
|
|
|
#include <assert.h>
|
|
|
|
/********************/
|
|
/* MMX instructions */
|
|
/********************/
|
|
|
|
// r64 = mm
|
|
|
|
/* movq m64 to r64 */
|
|
void MOVQMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0x6F), true, to, from, 0);
|
|
}
|
|
|
|
/* movq r64 to m64 */
|
|
void MOVQRtoM( uptr to, x86MMXRegType from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0x7F), true, from, to, 0);
|
|
}
|
|
|
|
/* pand r64 to r64 */
|
|
void PANDRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xDB0F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PANDNRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xDF0F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
/* por r64 to r64 */
|
|
void PORRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xEB0F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
/* pxor r64 to r64 */
|
|
void PXORRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xEF0F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
/* psllq r64 to r64 */
|
|
void PSLLQRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xF30F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
/* psllq m64 to r64 */
|
|
void PSLLQMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0xF3), true, to, from, 0);
|
|
}
|
|
|
|
/* psllq imm8 to r64 */
|
|
void PSLLQItoR( x86MMXRegType to, u8 from )
|
|
{
|
|
RexB(0, to);
|
|
write16( 0x730F );
|
|
ModRM( 3, 6, to);
|
|
write8( from );
|
|
}
|
|
|
|
/* psrlq r64 to r64 */
|
|
void PSRLQRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xD30F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
/* psrlq m64 to r64 */
|
|
void PSRLQMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0xD3), true, to, from, 0);
|
|
}
|
|
|
|
/* psrlq imm8 to r64 */
|
|
void PSRLQItoR( x86MMXRegType to, u8 from )
|
|
{
|
|
RexB(0, to);
|
|
write16( 0x730F );
|
|
ModRM( 3, 2, to);
|
|
write8( from );
|
|
}
|
|
|
|
/* paddusb r64 to r64 */
|
|
void PADDUSBRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xDC0F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
/* paddusb m64 to r64 */
|
|
void PADDUSBMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0xDC), true, to, from, 0);
|
|
}
|
|
|
|
/* paddusw r64 to r64 */
|
|
void PADDUSWRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xDD0F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
/* paddusw m64 to r64 */
|
|
void PADDUSWMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0xDD), true, to, from, 0);
|
|
}
|
|
|
|
/* paddb r64 to r64 */
|
|
void PADDBRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xFC0F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
/* paddb m64 to r64 */
|
|
void PADDBMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0xFC), true, to, from, 0);
|
|
}
|
|
|
|
/* paddw r64 to r64 */
|
|
void PADDWRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xFD0F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
/* paddw m64 to r64 */
|
|
void PADDWMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0xFD), true, to, from, 0);
|
|
}
|
|
|
|
/* paddd r64 to r64 */
|
|
void PADDDRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xFE0F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
/* paddd m64 to r64 */
|
|
void PADDDMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0xFE), true, to, from, 0);
|
|
}
|
|
|
|
/* emms */
|
|
void EMMS( void )
|
|
{
|
|
write16( 0x770F );
|
|
}
|
|
|
|
void PADDSBRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xEC0F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PADDSWRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xED0F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
// paddq m64 to r64 (sse2 only?)
|
|
void PADDQMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0xD4), true, to, from, 0);
|
|
}
|
|
|
|
// paddq r64 to r64 (sse2 only?)
|
|
void PADDQRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xD40F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PSUBSBRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xE80F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PSUBSWRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xE90F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
|
|
void PSUBBRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xF80F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PSUBWRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xF90F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PSUBDRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xFA0F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PSUBDMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0xFA), true, to, from, 0);
|
|
}
|
|
|
|
void PSUBUSBRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xD80F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PSUBUSWRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xD90F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
// psubq m64 to r64 (sse2 only?)
|
|
void PSUBQMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0xFB), true, to, from, 0);
|
|
}
|
|
|
|
// psubq r64 to r64 (sse2 only?)
|
|
void PSUBQRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xFB0F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
// pmuludq m64 to r64 (sse2 only?)
|
|
void PMULUDQMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0xF4), true, to, from, 0);
|
|
}
|
|
|
|
// pmuludq r64 to r64 (sse2 only?)
|
|
void PMULUDQRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xF40F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PCMPEQBRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0x740F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PCMPEQWRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0x750F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PCMPEQDRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0x760F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PCMPEQDMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0x76), true, to, from, 0);
|
|
}
|
|
|
|
void PCMPGTBRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0x640F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PCMPGTWRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0x650F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PCMPGTDRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0x660F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PCMPGTDMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0x66), true, to, from, 0);
|
|
}
|
|
|
|
void PSRLWItoR( x86MMXRegType to, u8 from )
|
|
{
|
|
RexB(0, to);
|
|
write16( 0x710F );
|
|
ModRM( 3, 2 , to );
|
|
write8( from );
|
|
}
|
|
|
|
void PSRLDItoR( x86MMXRegType to, u8 from )
|
|
{
|
|
RexB(0, to);
|
|
write16( 0x720F );
|
|
ModRM( 3, 2 , to );
|
|
write8( from );
|
|
}
|
|
|
|
void PSRLDRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xD20F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PSLLWItoR( x86MMXRegType to, u8 from )
|
|
{
|
|
RexB(0, to);
|
|
write16( 0x710F );
|
|
ModRM( 3, 6 , to );
|
|
write8( from );
|
|
}
|
|
|
|
void PSLLDItoR( x86MMXRegType to, u8 from )
|
|
{
|
|
RexB(0, to);
|
|
write16( 0x720F );
|
|
ModRM( 3, 6 , to );
|
|
write8( from );
|
|
}
|
|
|
|
void PSLLDRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xF20F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PSRAWItoR( x86MMXRegType to, u8 from )
|
|
{
|
|
RexB(0, to);
|
|
write16( 0x710F );
|
|
ModRM( 3, 4 , to );
|
|
write8( from );
|
|
}
|
|
|
|
void PSRADItoR( x86MMXRegType to, u8 from )
|
|
{
|
|
RexB(0, to);
|
|
write16( 0x720F );
|
|
ModRM( 3, 4 , to );
|
|
write8( from );
|
|
}
|
|
|
|
void PSRADRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xE20F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
/* por m64 to r64 */
|
|
void PORMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0xEB), true, to, from, 0);
|
|
}
|
|
|
|
/* pxor m64 to r64 */
|
|
void PXORMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0xEF), true, to, from, 0);
|
|
}
|
|
|
|
/* pand m64 to r64 */
|
|
void PANDMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0xDB), true, to, from, 0);
|
|
}
|
|
|
|
void PANDNMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0xDF), true, to, from, 0);
|
|
}
|
|
|
|
void PUNPCKHDQRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0x6A0F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PUNPCKHDQMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0x6A), true, to, from, 0);
|
|
}
|
|
|
|
void PUNPCKLDQRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0x620F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PUNPCKLDQMtoR( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0x62), true, to, from, 0);
|
|
}
|
|
|
|
void MOVQ64ItoR( x86MMXRegType reg, u64 i )
|
|
{
|
|
RexR(0, reg);
|
|
write16(0x6F0F);
|
|
ModRM(0, reg, DISP32);
|
|
write32(2);
|
|
JMP8( 8 );
|
|
write64( i );
|
|
}
|
|
|
|
void MOVQRtoR( x86MMXRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0x6F0F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void MOVQRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0x6F0F );
|
|
|
|
if( offset < 128 ) {
|
|
ModRM( 1, to, from );
|
|
write8(offset);
|
|
}
|
|
else {
|
|
ModRM( 2, to, from );
|
|
write32(offset);
|
|
}
|
|
}
|
|
|
|
void MOVQRtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset )
|
|
{
|
|
RexRB(0, from, to);
|
|
write16( 0x7F0F );
|
|
|
|
if( offset < 128 ) {
|
|
ModRM( 1, from , to );
|
|
write8(offset);
|
|
}
|
|
else {
|
|
ModRM( 2, from, to );
|
|
write32(offset);
|
|
}
|
|
}
|
|
|
|
/* movd m32 to r64 */
|
|
void MOVDMtoMMX( x86MMXRegType to, uptr from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0x6E), true, to, from, 0);
|
|
}
|
|
|
|
/* movd r64 to m32 */
|
|
void MOVDMMXtoM( uptr to, x86MMXRegType from )
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0x7E), true, from, to, 0);
|
|
}
|
|
|
|
void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0x6E0F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void MOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0x6E0F );
|
|
ModRM( 0, to, from );
|
|
}
|
|
|
|
void MOVD32RmOffsettoMMX( x86MMXRegType to, x86IntRegType from, u32 offset )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0x6E0F );
|
|
|
|
if( offset < 128 ) {
|
|
ModRM( 1, to, from );
|
|
write8(offset);
|
|
}
|
|
else {
|
|
ModRM( 2, to, from );
|
|
write32(offset);
|
|
}
|
|
}
|
|
|
|
void MOVD32MMXtoR( x86IntRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, from, to);
|
|
write16( 0x7E0F );
|
|
ModRM( 3, from, to );
|
|
}
|
|
|
|
void MOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from )
|
|
{
|
|
RexRB(0, from, to);
|
|
write16( 0x7E0F );
|
|
ModRM( 0, from, to );
|
|
if( to >= 4 ) {
|
|
// no idea why
|
|
assert( to == ESP );
|
|
write8(0x24);
|
|
}
|
|
|
|
}
|
|
|
|
void MOVD32MMXtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset )
|
|
{
|
|
RexRB(0, from, to);
|
|
write16( 0x7E0F );
|
|
|
|
if( offset < 128 ) {
|
|
ModRM( 1, from, to );
|
|
write8(offset);
|
|
}
|
|
else {
|
|
ModRM( 2, from, to );
|
|
write32(offset);
|
|
}
|
|
}
|
|
|
|
///* movd r32 to r64 */
|
|
//void MOVD32MMXtoMMX( x86MMXRegType to, x86MMXRegType from )
|
|
//{
|
|
// write16( 0x6E0F );
|
|
// ModRM( 3, to, from );
|
|
//}
|
|
//
|
|
///* movq r64 to r32 */
|
|
//void MOVD64MMXtoMMX( x86MMXRegType to, x86MMXRegType from )
|
|
//{
|
|
// write16( 0x7E0F );
|
|
// ModRM( 3, from, to );
|
|
//}
|
|
|
|
// untested
|
|
void PACKSSWBMMXtoMMX(x86MMXRegType to, x86MMXRegType from)
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0x630F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PACKSSDWMMXtoMMX(x86MMXRegType to, x86MMXRegType from)
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0x6B0F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PMOVMSKBMMXtoR(x86IntRegType to, x86MMXRegType from)
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xD70F );
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
void PINSRWRtoMMX( x86MMXRegType to, x86SSERegType from, u8 imm8 )
|
|
{
|
|
RexRB(0, to, from);
|
|
write16( 0xc40f );
|
|
ModRM( 3, to, from );
|
|
write8( imm8 );
|
|
}
|
|
|
|
void PSHUFWRtoR(x86MMXRegType to, x86MMXRegType from, u8 imm8)
|
|
{
|
|
RexRB(0, to, from);
|
|
write16(0x700f);
|
|
ModRM( 3, to, from );
|
|
write8(imm8);
|
|
}
|
|
|
|
void PSHUFWMtoR(x86MMXRegType to, uptr from, u8 imm8)
|
|
{
|
|
MEMADDR_OP(0, VAROP2(0x0F, 0x70), true, to, from, 1 /* XXX was 0? */);
|
|
write8(imm8);
|
|
}
|
|
|
|
void MASKMOVQRtoR(x86MMXRegType to, x86MMXRegType from)
|
|
{
|
|
RexRB(0, to, from);
|
|
write16(0xf70f);
|
|
ModRM( 3, to, from );
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|