mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Merge pull request #940 from delroth/x64emittertest
Add unit tests for the x64Emitter
This commit is contained in:
@@ -666,7 +666,7 @@ void XEmitter::POP(int /*bits*/, const OpArg ®)
|
||||
if (reg.IsSimpleReg())
|
||||
POP(reg.GetSimpleReg());
|
||||
else
|
||||
INT3();
|
||||
_assert_msg_(DYNA_REC, 0, "POP - Unsupported encoding");
|
||||
}
|
||||
|
||||
void XEmitter::BSWAP(int bits, X64Reg reg)
|
||||
@@ -720,6 +720,8 @@ void XEmitter::SETcc(CCFlags flag, OpArg dest)
|
||||
void XEmitter::CMOVcc(int bits, X64Reg dest, OpArg src, CCFlags flag)
|
||||
{
|
||||
if (src.IsImm()) _assert_msg_(DYNA_REC, 0, "CMOVcc - Imm argument");
|
||||
if (bits == 8) _assert_msg_(DYNA_REC, 0, "CMOVcc - 8 bits unsupported");
|
||||
if (bits == 16) Write8(0x66);
|
||||
src.operandReg = dest;
|
||||
src.WriteRex(this, bits, bits);
|
||||
Write8(0x0F);
|
||||
@@ -732,7 +734,7 @@ void XEmitter::WriteMulDivType(int bits, OpArg src, int ext)
|
||||
if (src.IsImm()) _assert_msg_(DYNA_REC, 0, "WriteMulDivType - Imm argument");
|
||||
src.operandReg = ext;
|
||||
if (bits == 16) Write8(0x66);
|
||||
src.WriteRex(this, bits, bits);
|
||||
src.WriteRex(this, bits, bits, 0);
|
||||
if (bits == 8)
|
||||
{
|
||||
Write8(0xF6);
|
||||
@@ -831,7 +833,7 @@ void XEmitter::MOVZX(int dbits, int sbits, X64Reg dest, OpArg src)
|
||||
}
|
||||
else
|
||||
{
|
||||
Crash();
|
||||
_assert_msg_(DYNA_REC, 0, "MOVZX - Invalid size");
|
||||
}
|
||||
src.WriteRest(this);
|
||||
}
|
||||
@@ -1172,10 +1174,8 @@ void XEmitter::OR (int bits, const OpArg &a1, const OpArg &a2) {WriteNormalOp(t
|
||||
void XEmitter::XOR (int bits, const OpArg &a1, const OpArg &a2) {WriteNormalOp(this, bits, nrmXOR, a1, a2);}
|
||||
void XEmitter::MOV (int bits, const OpArg &a1, const OpArg &a2)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
_assert_msg_(DYNA_REC, !a1.IsSimpleReg() || !a2.IsSimpleReg() || a1.GetSimpleReg() != a2.GetSimpleReg(), "Redundant MOV @ %p - bug in JIT?",
|
||||
code);
|
||||
#endif
|
||||
if (a1.IsSimpleReg() && a2.IsSimpleReg() && a1.GetSimpleReg() == a2.GetSimpleReg())
|
||||
ERROR_LOG(DYNA_REC, "Redundant MOV @ %p - bug in JIT?", code);
|
||||
WriteNormalOp(this, bits, nrmMOV, a1, a2);
|
||||
}
|
||||
void XEmitter::TEST(int bits, const OpArg &a1, const OpArg &a2) {WriteNormalOp(this, bits, nrmTEST, a1, a2);}
|
||||
@@ -1658,28 +1658,30 @@ void XEmitter::FWAIT()
|
||||
}
|
||||
|
||||
// TODO: make this more generic
|
||||
void XEmitter::WriteFloatLoadStore(int bits, FloatOp op, OpArg arg)
|
||||
void XEmitter::WriteFloatLoadStore(int bits, FloatOp op, FloatOp op_80b, OpArg arg)
|
||||
{
|
||||
int mf = 0;
|
||||
|
||||
_assert_msg_(DYNA_REC, !(bits == 80 && op_80b == floatINVALID), "WriteFloatLoadStore: 80 bits not supported for this instruction");
|
||||
switch (bits)
|
||||
{
|
||||
case 32: mf = 0; break;
|
||||
case 64: mf = 2; break;
|
||||
default: _assert_msg_(DYNA_REC, 0, "WriteFloatLoadStore: bits is not 32 or 64");
|
||||
case 64: mf = 4; break;
|
||||
case 80: mf = 2; break;
|
||||
default: _assert_msg_(DYNA_REC, 0, "WriteFloatLoadStore: invalid bits (should be 32/64/80)");
|
||||
}
|
||||
|
||||
Write8(0xd9 | (mf << 1));
|
||||
Write8(0xd9 | mf);
|
||||
// x87 instructions use the reg field of the ModR/M byte as opcode:
|
||||
if (bits == 80)
|
||||
op = op_80b;
|
||||
arg.WriteRest(this, 0, (X64Reg) op);
|
||||
}
|
||||
|
||||
void XEmitter::FLD(int bits, OpArg src) {WriteFloatLoadStore(bits, floatLD, src);}
|
||||
void XEmitter::FST(int bits, OpArg dest) {WriteFloatLoadStore(bits, floatST, dest);}
|
||||
void XEmitter::FSTP(int bits, OpArg dest) {WriteFloatLoadStore(bits, floatSTP, dest);}
|
||||
void XEmitter::FLD(int bits, OpArg src) {WriteFloatLoadStore(bits, floatLD, floatLD80, src);}
|
||||
void XEmitter::FST(int bits, OpArg dest) {WriteFloatLoadStore(bits, floatST, floatINVALID, dest);}
|
||||
void XEmitter::FSTP(int bits, OpArg dest) {WriteFloatLoadStore(bits, floatSTP, floatSTP80, dest);}
|
||||
void XEmitter::FNSTSW_AX() { Write8(0xDF); Write8(0xE0); }
|
||||
|
||||
void XEmitter::RTDSC() { Write8(0x0F); Write8(0x31); }
|
||||
void XEmitter::RDTSC() { Write8(0x0F); Write8(0x31); }
|
||||
|
||||
// helper routines for setting pointers
|
||||
void XEmitter::CallCdeclFunction3(void* fnptr, u32 arg0, u32 arg1, u32 arg2)
|
||||
|
||||
@@ -105,6 +105,10 @@ enum FloatOp {
|
||||
floatLD = 0,
|
||||
floatST = 2,
|
||||
floatSTP = 3,
|
||||
floatLD80 = 5,
|
||||
floatSTP80 = 7,
|
||||
|
||||
floatINVALID = -1,
|
||||
};
|
||||
|
||||
class XEmitter;
|
||||
@@ -271,7 +275,7 @@ private:
|
||||
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 WriteFloatLoadStore(int bits, FloatOp op, FloatOp op_80b, OpArg arg);
|
||||
void WriteNormalOp(XEmitter *emit, int bits, NormalOp op, const OpArg &a1, const OpArg &a2);
|
||||
|
||||
protected:
|
||||
@@ -336,7 +340,6 @@ public:
|
||||
FixupBranch J(bool force5bytes = false);
|
||||
|
||||
void JMP(const u8 * addr, bool force5Bytes = false);
|
||||
void JMP(OpArg arg);
|
||||
void JMPptr(const OpArg &arg);
|
||||
void JMPself(); //infinite loop!
|
||||
#ifdef CALL
|
||||
@@ -536,11 +539,8 @@ public:
|
||||
// SSE/SSE2: Useful alternative to shuffle in some cases.
|
||||
void MOVDDUP(X64Reg regOp, OpArg arg);
|
||||
|
||||
// THESE TWO ARE NEW AND UNTESTED
|
||||
void UNPCKLPS(X64Reg dest, OpArg src);
|
||||
void UNPCKHPS(X64Reg dest, OpArg src);
|
||||
|
||||
// These are OK.
|
||||
void UNPCKLPD(X64Reg dest, OpArg src);
|
||||
void UNPCKHPD(X64Reg dest, OpArg src);
|
||||
|
||||
@@ -588,21 +588,23 @@ public:
|
||||
void CVTPS2PD(X64Reg dest, OpArg src);
|
||||
void CVTPD2PS(X64Reg dest, OpArg src);
|
||||
void CVTSS2SD(X64Reg dest, OpArg src);
|
||||
void CVTSS2SI(X64Reg dest, OpArg src);
|
||||
void CVTSI2SS(X64Reg dest, OpArg src);
|
||||
void CVTSD2SS(X64Reg dest, OpArg src);
|
||||
void CVTSD2SI(X64Reg dest, OpArg src);
|
||||
void CVTSI2SD(X64Reg dest, OpArg src);
|
||||
void CVTDQ2PD(X64Reg regOp, OpArg arg);
|
||||
void CVTPD2DQ(X64Reg regOp, OpArg arg);
|
||||
void CVTDQ2PS(X64Reg regOp, OpArg arg);
|
||||
void CVTPS2DQ(X64Reg regOp, OpArg arg);
|
||||
|
||||
void CVTTSS2SI(X64Reg regOp, OpArg arg);
|
||||
void CVTTSD2SI(X64Reg regOp, OpArg arg);
|
||||
void CVTTPS2DQ(X64Reg regOp, OpArg arg);
|
||||
void CVTTPD2DQ(X64Reg regOp, OpArg arg);
|
||||
|
||||
// Destinations are X64 regs (rax, rbx, ...) for these instructions.
|
||||
void CVTSS2SI(X64Reg xregdest, OpArg src);
|
||||
void CVTSD2SI(X64Reg xregdest, OpArg src);
|
||||
void CVTTSS2SI(X64Reg xregdest, OpArg arg);
|
||||
void CVTTSD2SI(X64Reg xregdest, OpArg arg);
|
||||
|
||||
// SSE2: Packed integer instructions
|
||||
void PACKSSDW(X64Reg dest, OpArg arg);
|
||||
void PACKSSWB(X64Reg dest, OpArg arg);
|
||||
@@ -706,7 +708,7 @@ public:
|
||||
void VPAND(X64Reg regOp1, X64Reg regOp2, OpArg arg);
|
||||
void VPANDN(X64Reg regOp1, X64Reg regOp2, OpArg arg);
|
||||
|
||||
void RTDSC();
|
||||
void RDTSC();
|
||||
|
||||
// Utility functions
|
||||
// The difference between this and CALL is that this aligns the stack
|
||||
|
||||
@@ -5,3 +5,4 @@ add_dolphin_test(FifoQueueTest FifoQueueTest.cpp)
|
||||
add_dolphin_test(FixedSizeQueueTest FixedSizeQueueTest.cpp)
|
||||
add_dolphin_test(FlagTest FlagTest.cpp)
|
||||
add_dolphin_test(MathUtilTest MathUtilTest.cpp)
|
||||
add_dolphin_test(x64EmitterTest x64EmitterTest.cpp)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user