From cc0b048c0bf1a80039374fbe606c97bd79e71ebc Mon Sep 17 00:00:00 2001 From: Pierre Bourdon Date: Tue, 2 Sep 2014 08:55:38 +0200 Subject: [PATCH] x64Emitter: Support FLD/FSTP with 80 bits operands --- Source/Core/Common/x64Emitter.cpp | 20 +++++++++++--------- Source/Core/Common/x64Emitter.h | 6 +++++- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/Source/Core/Common/x64Emitter.cpp b/Source/Core/Common/x64Emitter.cpp index 0a9a10487c..036e085d41 100644 --- a/Source/Core/Common/x64Emitter.cpp +++ b/Source/Core/Common/x64Emitter.cpp @@ -1660,25 +1660,27 @@ 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::RDTSC() { Write8(0x0F); Write8(0x31); } diff --git a/Source/Core/Common/x64Emitter.h b/Source/Core/Common/x64Emitter.h index 4c93e10978..4eb7635c5e 100644 --- a/Source/Core/Common/x64Emitter.h +++ b/Source/Core/Common/x64Emitter.h @@ -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: