x64Emitter: refactor to support longer opcodes
Also add some new SSE4 opcodes.
This commit is contained in:
parent
66a30d0fc6
commit
802b28daf9
|
@ -60,6 +60,10 @@ enum NormalSSEOps
|
|||
sseMOVAPtoRM = 0x29, //MOVAP to RM
|
||||
sseMOVUPfromRM = 0x10, //MOVUP from RM
|
||||
sseMOVUPtoRM = 0x11, //MOVUP to RM
|
||||
sseMOVLPDfromRM= 0x12,
|
||||
sseMOVLPDtoRM = 0x13,
|
||||
sseMOVHPDfromRM= 0x16,
|
||||
sseMOVHPDtoRM = 0x17,
|
||||
sseMASKMOVDQU = 0xF7,
|
||||
sseLDDQU = 0xF0,
|
||||
sseSHUF = 0xC6,
|
||||
|
@ -1237,7 +1241,7 @@ void XEmitter::IMUL(int bits, X64Reg regOp, OpArg a)
|
|||
}
|
||||
|
||||
|
||||
void XEmitter::WriteSSEOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes)
|
||||
void XEmitter::WriteSSEOp(int size, u16 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes)
|
||||
{
|
||||
if (size == 64 && packed)
|
||||
Write8(0x66); //this time, override goes upwards
|
||||
|
@ -1246,19 +1250,33 @@ void XEmitter::WriteSSEOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg a
|
|||
arg.operandReg = regOp;
|
||||
arg.WriteRex(this, 0, 0);
|
||||
Write8(0x0F);
|
||||
Write8(sseOp);
|
||||
if (sseOp > 0xFF)
|
||||
{
|
||||
// Currently, only 0x38 and 0x3A are used as secondary escape byte.
|
||||
_assert_msg_(DYNA_REC, ((sseOp >> 8) & 0xFD) == 0x38, "Invalid SSE opcode: 0F%04X", sseOp);
|
||||
Write8((sseOp >> 8) & 0xFF);
|
||||
}
|
||||
Write8(sseOp & 0xFF);
|
||||
arg.WriteRest(this, extrabytes);
|
||||
}
|
||||
|
||||
void XEmitter::WriteAVXOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes)
|
||||
void XEmitter::WriteAVXOp(int size, u16 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes)
|
||||
{
|
||||
WriteAVXOp(size, sseOp, packed, regOp, X64Reg::INVALID_REG, arg, extrabytes);
|
||||
}
|
||||
|
||||
void XEmitter::WriteAVXOp(int size, u8 sseOp, bool packed, X64Reg regOp1, X64Reg regOp2, OpArg arg, int extrabytes)
|
||||
void XEmitter::WriteAVXOp(int size, u16 sseOp, bool packed, X64Reg regOp1, X64Reg regOp2, OpArg arg, int extrabytes)
|
||||
{
|
||||
if (!cpu_info.bAVX)
|
||||
PanicAlert("Trying to use AVX on a system that doesn't support it. Bad programmer.");
|
||||
arg.WriteVex(this, size, packed, regOp1, regOp2);
|
||||
Write8(sseOp);
|
||||
if (sseOp > 0xFF)
|
||||
{
|
||||
// Currently, only 0x38 and 0x3A are used as secondary escape byte.
|
||||
_assert_msg_(DYNA_REC, ((sseOp >> 8) & 0xFD) == 0x38, "Invalid SSE opcode: 0F%04X", sseOp);
|
||||
Write8((sseOp >> 8) & 0xFF);
|
||||
}
|
||||
Write8(sseOp & 0xFF);
|
||||
arg.WriteRest(this, extrabytes, regOp1);
|
||||
}
|
||||
|
||||
|
@ -1382,6 +1400,11 @@ void XEmitter::MOVSD(X64Reg regOp, OpArg arg) {WriteSSEOp(64, sseMOVUPfromRM,
|
|||
void XEmitter::MOVSS(OpArg arg, X64Reg regOp) {WriteSSEOp(32, sseMOVUPtoRM, false, regOp, arg);}
|
||||
void XEmitter::MOVSD(OpArg arg, X64Reg regOp) {WriteSSEOp(64, sseMOVUPtoRM, false, regOp, arg);}
|
||||
|
||||
void XEmitter::MOVLPD(X64Reg regOp, OpArg arg) {WriteSSEOp(64, sseMOVLPDfromRM, false, regOp, arg);}
|
||||
void XEmitter::MOVHPD(X64Reg regOp, OpArg arg) {WriteSSEOp(64, sseMOVHPDfromRM, false, regOp, arg);}
|
||||
void XEmitter::MOVLPD(OpArg arg, X64Reg regOp) {WriteSSEOp(64, sseMOVLPDtoRM, false, regOp, arg);}
|
||||
void XEmitter::MOVHPD(OpArg arg, X64Reg regOp) {WriteSSEOp(64, sseMOVHPDtoRM, false, regOp, arg);}
|
||||
|
||||
void XEmitter::CVTPS2PD(X64Reg regOp, OpArg arg) {WriteSSEOp(32, 0x5A, true, regOp, arg);}
|
||||
void XEmitter::CVTPD2PS(X64Reg regOp, OpArg arg) {WriteSSEOp(64, 0x5A, true, regOp, arg);}
|
||||
|
||||
|
@ -1432,7 +1455,6 @@ void XEmitter::MOVDDUP(X64Reg regOp, OpArg arg)
|
|||
// Also some integer instructions are missing
|
||||
void XEmitter::PACKSSDW(X64Reg dest, OpArg arg) {WriteSSEOp(64, 0x6B, true, dest, arg);}
|
||||
void XEmitter::PACKSSWB(X64Reg dest, OpArg arg) {WriteSSEOp(64, 0x63, true, dest, arg);}
|
||||
//void PACKUSDW(X64Reg dest, OpArg arg) {WriteSSEOp(64, 0x66, true, dest, arg);} // WRONG
|
||||
void XEmitter::PACKUSWB(X64Reg dest, OpArg arg) {WriteSSEOp(64, 0x67, true, dest, arg);}
|
||||
|
||||
void XEmitter::PUNPCKLBW(X64Reg dest, const OpArg &arg) {WriteSSEOp(64, 0x60, true, dest, arg);}
|
||||
|
@ -1496,31 +1518,41 @@ void XEmitter::PSRAD(X64Reg reg, int shift) {
|
|||
Write8(shift);
|
||||
}
|
||||
|
||||
void XEmitter::PSHUFB(X64Reg dest, OpArg arg) {
|
||||
if (!cpu_info.bSSSE3) {
|
||||
PanicAlert("Trying to use PSHUFB on a system that doesn't support it. Bad programmer.");
|
||||
}
|
||||
Write8(0x66);
|
||||
arg.operandReg = dest;
|
||||
arg.WriteRex(this, 0, 0);
|
||||
Write8(0x0f);
|
||||
Write8(0x38);
|
||||
Write8(0x00);
|
||||
arg.WriteRest(this);
|
||||
void XEmitter::WriteSSSE3Op(int size, u16 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes)
|
||||
{
|
||||
if (!cpu_info.bSSSE3)
|
||||
PanicAlert("Trying to use SSSE3 on a system that doesn't support it. Bad programmer.");
|
||||
WriteSSEOp(size, sseOp, packed, regOp, arg, extrabytes);
|
||||
}
|
||||
|
||||
void XEmitter::PTEST(X64Reg dest, OpArg arg) {
|
||||
if (!cpu_info.bSSE4_1) {
|
||||
PanicAlert("Trying to use PTEST on a system that doesn't support it. Nobody hears your screams.");
|
||||
}
|
||||
Write8(0x66);
|
||||
Write8(0x0f);
|
||||
Write8(0x38);
|
||||
Write8(0x17);
|
||||
arg.operandReg = dest;
|
||||
arg.WriteRest(this);
|
||||
void XEmitter::WriteSSE41Op(int size, u16 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes)
|
||||
{
|
||||
if (!cpu_info.bSSE4_1)
|
||||
PanicAlert("Trying to use SSE4.1 on a system that doesn't support it. Bad programmer.");
|
||||
WriteSSEOp(size, sseOp, packed, regOp, arg, extrabytes);
|
||||
}
|
||||
|
||||
void XEmitter::PSHUFB(X64Reg dest, OpArg arg) {WriteSSSE3Op(64, 0x3800, true, dest, arg);}
|
||||
void XEmitter::PTEST(X64Reg dest, OpArg arg) {WriteSSE41Op(64, 0x3817, true, dest, arg);}
|
||||
void XEmitter::PACKUSDW(X64Reg dest, OpArg arg) {WriteSSE41Op(64, 0x382b, true, dest, arg);}
|
||||
|
||||
void XEmitter::PMOVSXBW(X64Reg dest, OpArg arg) {WriteSSE41Op(64, 0x3820, true, dest, arg);}
|
||||
void XEmitter::PMOVSXBD(X64Reg dest, OpArg arg) {WriteSSE41Op(64, 0x3821, true, dest, arg);}
|
||||
void XEmitter::PMOVSXBQ(X64Reg dest, OpArg arg) {WriteSSE41Op(64, 0x3822, true, dest, arg);}
|
||||
void XEmitter::PMOVSXWD(X64Reg dest, OpArg arg) {WriteSSE41Op(64, 0x3823, true, dest, arg);}
|
||||
void XEmitter::PMOVSXWQ(X64Reg dest, OpArg arg) {WriteSSE41Op(64, 0x3824, true, dest, arg);}
|
||||
void XEmitter::PMOVSXDQ(X64Reg dest, OpArg arg) {WriteSSE41Op(64, 0x3825, true, dest, arg);}
|
||||
void XEmitter::PMOVZXBW(X64Reg dest, OpArg arg) {WriteSSE41Op(64, 0x3830, true, dest, arg);}
|
||||
void XEmitter::PMOVZXBD(X64Reg dest, OpArg arg) {WriteSSE41Op(64, 0x3831, true, dest, arg);}
|
||||
void XEmitter::PMOVZXBQ(X64Reg dest, OpArg arg) {WriteSSE41Op(64, 0x3832, true, dest, arg);}
|
||||
void XEmitter::PMOVZXWD(X64Reg dest, OpArg arg) {WriteSSE41Op(64, 0x3833, true, dest, arg);}
|
||||
void XEmitter::PMOVZXWQ(X64Reg dest, OpArg arg) {WriteSSE41Op(64, 0x3834, true, dest, arg);}
|
||||
void XEmitter::PMOVZXDQ(X64Reg dest, OpArg arg) {WriteSSE41Op(64, 0x3835, true, dest, arg);}
|
||||
|
||||
void XEmitter::PBLENDVB(X64Reg dest, OpArg arg) {WriteSSE41Op(64, 0x3810, true, dest, arg);}
|
||||
void XEmitter::BLENDVPS(X64Reg dest, OpArg arg) {WriteSSE41Op(64, 0x3814, true, dest, arg);}
|
||||
void XEmitter::BLENDVPD(X64Reg dest, OpArg arg) {WriteSSE41Op(64, 0x3815, true, dest, arg);}
|
||||
|
||||
void XEmitter::PAND(X64Reg dest, OpArg arg) {WriteSSEOp(64, 0xDB, true, dest, arg);}
|
||||
void XEmitter::PANDN(X64Reg dest, OpArg arg) {WriteSSEOp(64, 0xDF, true, dest, arg);}
|
||||
void XEmitter::PXOR(X64Reg dest, OpArg arg) {WriteSSEOp(64, 0xEF, true, dest, arg);}
|
||||
|
|
|
@ -252,9 +252,11 @@ private:
|
|||
void WriteShift(int bits, OpArg dest, OpArg &shift, int ext);
|
||||
void WriteBitTest(int bits, OpArg &dest, OpArg &index, int ext);
|
||||
void WriteMXCSR(OpArg arg, int ext);
|
||||
void WriteSSEOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes = 0);
|
||||
void WriteAVXOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes = 0);
|
||||
void WriteAVXOp(int size, u8 sseOp, bool packed, X64Reg regOp1, X64Reg regOp2, OpArg arg, int extrabytes = 0);
|
||||
void WriteSSEOp(int size, u16 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes = 0);
|
||||
void WriteSSSE3Op(int size, u16 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes = 0);
|
||||
void WriteSSE41Op(int size, u16 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes = 0);
|
||||
void WriteAVXOp(int size, u16 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes = 0);
|
||||
void WriteAVXOp(int size, u16 sseOp, bool packed, X64Reg regOp1, X64Reg regOp2, OpArg arg, int extrabytes = 0);
|
||||
void WriteFloatLoadStore(int bits, FloatOp op, OpArg arg);
|
||||
void WriteNormalOp(XEmitter *emit, int bits, NormalOp op, const OpArg &a1, const OpArg &a2);
|
||||
|
||||
|
@ -550,6 +552,11 @@ public:
|
|||
void MOVSS(OpArg arg, X64Reg regOp);
|
||||
void MOVSD(OpArg arg, X64Reg regOp);
|
||||
|
||||
void MOVLPD(X64Reg regOp, OpArg arg);
|
||||
void MOVHPD(X64Reg regOp, OpArg arg);
|
||||
void MOVLPD(OpArg arg, X64Reg regOp);
|
||||
void MOVHPD(OpArg arg, X64Reg regOp);
|
||||
|
||||
void MOVD_xmm(X64Reg dest, const OpArg &arg);
|
||||
void MOVQ_xmm(X64Reg dest, OpArg arg);
|
||||
void MOVD_xmm(const OpArg &arg, X64Reg src);
|
||||
|
@ -581,7 +588,7 @@ public:
|
|||
// SSE2: Packed integer instructions
|
||||
void PACKSSDW(X64Reg dest, OpArg arg);
|
||||
void PACKSSWB(X64Reg dest, OpArg arg);
|
||||
//void PACKUSDW(X64Reg dest, OpArg arg);
|
||||
void PACKUSDW(X64Reg dest, OpArg arg);
|
||||
void PACKUSWB(X64Reg dest, OpArg arg);
|
||||
|
||||
void PUNPCKLBW(X64Reg dest, const OpArg &arg);
|
||||
|
@ -653,6 +660,25 @@ public:
|
|||
void PSRAW(X64Reg reg, int shift);
|
||||
void PSRAD(X64Reg reg, int shift);
|
||||
|
||||
// SSE4: data type conversions
|
||||
void PMOVSXBW(X64Reg dest, OpArg arg);
|
||||
void PMOVSXBD(X64Reg dest, OpArg arg);
|
||||
void PMOVSXBQ(X64Reg dest, OpArg arg);
|
||||
void PMOVSXWD(X64Reg dest, OpArg arg);
|
||||
void PMOVSXWQ(X64Reg dest, OpArg arg);
|
||||
void PMOVSXDQ(X64Reg dest, OpArg arg);
|
||||
void PMOVZXBW(X64Reg dest, OpArg arg);
|
||||
void PMOVZXBD(X64Reg dest, OpArg arg);
|
||||
void PMOVZXBQ(X64Reg dest, OpArg arg);
|
||||
void PMOVZXWD(X64Reg dest, OpArg arg);
|
||||
void PMOVZXWQ(X64Reg dest, OpArg arg);
|
||||
void PMOVZXDQ(X64Reg dest, OpArg arg);
|
||||
|
||||
// SSE4: variable blend instructions (xmm0 implicit argument)
|
||||
void PBLENDVB(X64Reg dest, OpArg arg);
|
||||
void BLENDVPS(X64Reg dest, OpArg arg);
|
||||
void BLENDVPD(X64Reg dest, OpArg arg);
|
||||
|
||||
// AVX
|
||||
void VADDSD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
|
||||
void VSUBSD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
|
||||
|
|
Loading…
Reference in New Issue