x64Emitter: Support FLD/FSTP with 80 bits operands
This commit is contained in:
parent
f99f302c91
commit
cc0b048c0b
|
@ -1660,25 +1660,27 @@ void XEmitter::FWAIT()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: make this more generic
|
// 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;
|
int mf = 0;
|
||||||
|
_assert_msg_(DYNA_REC, !(bits == 80 && op_80b == floatINVALID), "WriteFloatLoadStore: 80 bits not supported for this instruction");
|
||||||
switch (bits)
|
switch (bits)
|
||||||
{
|
{
|
||||||
case 32: mf = 0; break;
|
case 32: mf = 0; break;
|
||||||
case 64: mf = 2; break;
|
case 64: mf = 4; break;
|
||||||
default: _assert_msg_(DYNA_REC, 0, "WriteFloatLoadStore: bits is not 32 or 64");
|
case 80: mf = 2; break;
|
||||||
|
default: _assert_msg_(DYNA_REC, 0, "WriteFloatLoadStore: invalid bits (should be 32/64/80)");
|
||||||
}
|
}
|
||||||
|
Write8(0xd9 | mf);
|
||||||
Write8(0xd9 | (mf << 1));
|
|
||||||
// x87 instructions use the reg field of the ModR/M byte as opcode:
|
// 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);
|
arg.WriteRest(this, 0, (X64Reg) op);
|
||||||
}
|
}
|
||||||
|
|
||||||
void XEmitter::FLD(int bits, OpArg src) {WriteFloatLoadStore(bits, floatLD, src);}
|
void XEmitter::FLD(int bits, OpArg src) {WriteFloatLoadStore(bits, floatLD, floatLD80, src);}
|
||||||
void XEmitter::FST(int bits, OpArg dest) {WriteFloatLoadStore(bits, floatST, dest);}
|
void XEmitter::FST(int bits, OpArg dest) {WriteFloatLoadStore(bits, floatST, floatINVALID, dest);}
|
||||||
void XEmitter::FSTP(int bits, OpArg dest) {WriteFloatLoadStore(bits, floatSTP, dest);}
|
void XEmitter::FSTP(int bits, OpArg dest) {WriteFloatLoadStore(bits, floatSTP, floatSTP80, dest);}
|
||||||
void XEmitter::FNSTSW_AX() { Write8(0xDF); Write8(0xE0); }
|
void XEmitter::FNSTSW_AX() { Write8(0xDF); Write8(0xE0); }
|
||||||
|
|
||||||
void XEmitter::RDTSC() { Write8(0x0F); Write8(0x31); }
|
void XEmitter::RDTSC() { Write8(0x0F); Write8(0x31); }
|
||||||
|
|
|
@ -105,6 +105,10 @@ enum FloatOp {
|
||||||
floatLD = 0,
|
floatLD = 0,
|
||||||
floatST = 2,
|
floatST = 2,
|
||||||
floatSTP = 3,
|
floatSTP = 3,
|
||||||
|
floatLD80 = 5,
|
||||||
|
floatSTP80 = 7,
|
||||||
|
|
||||||
|
floatINVALID = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
class XEmitter;
|
class XEmitter;
|
||||||
|
@ -271,7 +275,7 @@ private:
|
||||||
void WriteSSE41Op(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 regOp, OpArg arg, int extrabytes = 0);
|
||||||
void WriteAVXOp(int size, u16 sseOp, bool packed, X64Reg regOp1, X64Reg regOp2, 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);
|
void WriteNormalOp(XEmitter *emit, int bits, NormalOp op, const OpArg &a1, const OpArg &a2);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
Loading…
Reference in New Issue