mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 05:47:56 -07:00
Merge pull request #1055 from FioraAeterna/smallermov
X64Emitter: support shorter mov reg, imm opcodes
This commit is contained in:
commit
439068acae
2
Externals/Bochs_disasm/opcodes.inc
vendored
2
Externals/Bochs_disasm/opcodes.inc
vendored
@ -36,7 +36,7 @@ Ia_adcl_Ed_sIb = { "adc", "adcl", Ed, sIbd, XX, XX, 0 },
|
||||
Ia_adcl_Gd_Ed = { "adc", "adcl", Gd, Ed, XX, XX, 0 },
|
||||
Ia_adcq_Eq_Gq = { "adc", "adcq", Eq, Gq, XX, XX, 0 },
|
||||
Ia_adcq_Eq_sIb = { "adc", "adcq", Eq, sIbq, XX, XX, 0 },
|
||||
Ia_adcq_Eq_sId = { "adc", "adcq", Eq, Iq, XX, XX, 0 },
|
||||
Ia_adcq_Eq_sId = { "adc", "adcq", Eq, sIdq, XX, XX, 0 },
|
||||
Ia_adcq_Gq_Eq = { "adc", "adcq", Gq, Eq, XX, XX, 0 },
|
||||
Ia_adcq_RAX_sId = { "adc", "adcq", RAX_Reg, sIdq, XX, XX, 0 },
|
||||
Ia_adcw_AX_Iw = { "adc", "adcw", AX_Reg, Iw, XX, XX, 0 },
|
||||
|
@ -1053,7 +1053,6 @@ void OpArg::WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg &o
|
||||
emit->Write8(0x66);
|
||||
|
||||
int immToWrite = 0;
|
||||
bool skip_rest = false;
|
||||
|
||||
if (operand.IsImm())
|
||||
{
|
||||
@ -1066,15 +1065,22 @@ void OpArg::WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg &o
|
||||
|
||||
if (operand.scale == SCALE_IMM8 && bits == 8)
|
||||
{
|
||||
// op al, imm8
|
||||
if (!scale && offsetOrBaseReg == AL && normalops[op].eaximm8 != 0xCC)
|
||||
{
|
||||
emit->Write8(normalops[op].eaximm8);
|
||||
skip_rest = true;
|
||||
emit->Write8((u8)operand.offset);
|
||||
return;
|
||||
}
|
||||
else
|
||||
// mov reg, imm8
|
||||
if (!scale && op == nrmMOV)
|
||||
{
|
||||
emit->Write8(normalops[op].imm8);
|
||||
emit->Write8(0xB0 + (offsetOrBaseReg & 7));
|
||||
emit->Write8((u8)operand.offset);
|
||||
return;
|
||||
}
|
||||
// op r/m8, imm8
|
||||
emit->Write8(normalops[op].imm8);
|
||||
immToWrite = 8;
|
||||
}
|
||||
else if ((operand.scale == SCALE_IMM16 && bits == 16) ||
|
||||
@ -1083,6 +1089,7 @@ void OpArg::WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg &o
|
||||
{
|
||||
// Try to save immediate size if we can, but first check to see
|
||||
// if the instruction supports simm8.
|
||||
// op r/m, imm8
|
||||
if (normalops[op].simm8 != 0xCC &&
|
||||
((operand.scale == SCALE_IMM16 && (s16)operand.offset == (s8)operand.offset) ||
|
||||
(operand.scale == SCALE_IMM32 && (s32)operand.offset == (s8)operand.offset)))
|
||||
@ -1092,15 +1099,28 @@ void OpArg::WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg &o
|
||||
}
|
||||
else
|
||||
{
|
||||
// mov reg, imm
|
||||
if (!scale && op == nrmMOV && bits != 64)
|
||||
{
|
||||
emit->Write8(0xB8 + (offsetOrBaseReg & 7));
|
||||
if (bits == 16)
|
||||
emit->Write16((u16)operand.offset);
|
||||
else
|
||||
emit->Write32((u32)operand.offset);
|
||||
return;
|
||||
}
|
||||
// op eax, imm
|
||||
if (!scale && offsetOrBaseReg == EAX && normalops[op].eaximm32 != 0xCC)
|
||||
{
|
||||
emit->Write8(normalops[op].eaximm32);
|
||||
skip_rest = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
emit->Write8(normalops[op].imm32);
|
||||
if (bits == 16)
|
||||
emit->Write16((u16)operand.offset);
|
||||
else
|
||||
emit->Write32((u32)operand.offset);
|
||||
return;
|
||||
}
|
||||
// op r/m, imm
|
||||
emit->Write8(normalops[op].imm32);
|
||||
immToWrite = bits == 16 ? 16 : 32;
|
||||
}
|
||||
}
|
||||
@ -1108,12 +1128,18 @@ void OpArg::WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg &o
|
||||
(operand.scale == SCALE_IMM8 && bits == 32) ||
|
||||
(operand.scale == SCALE_IMM8 && bits == 64))
|
||||
{
|
||||
// op r/m, imm8
|
||||
emit->Write8(normalops[op].simm8);
|
||||
immToWrite = 8;
|
||||
}
|
||||
else if (operand.scale == SCALE_IMM64 && bits == 64)
|
||||
{
|
||||
if (op == nrmMOV)
|
||||
if (scale)
|
||||
{
|
||||
_assert_msg_(DYNA_REC, 0, "WriteNormalOp - MOV with 64-bit imm requres register destination");
|
||||
}
|
||||
// mov reg64, imm64
|
||||
else if (op == nrmMOV)
|
||||
{
|
||||
emit->Write8(0xB8 + (offsetOrBaseReg & 7));
|
||||
emit->Write64((u64)operand.offset);
|
||||
@ -1131,20 +1157,18 @@ void OpArg::WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg &o
|
||||
{
|
||||
_operandReg = (X64Reg)operand.offsetOrBaseReg;
|
||||
WriteRex(emit, bits, bits, _operandReg);
|
||||
// mem/reg or reg/reg op
|
||||
// op r/m, reg
|
||||
if (toRM)
|
||||
{
|
||||
emit->Write8(bits == 8 ? normalops[op].toRm8 : normalops[op].toRm32);
|
||||
// _assert_msg_(DYNA_REC, code[-1] != 0xCC, "ARGH4");
|
||||
}
|
||||
// op reg, r/m
|
||||
else
|
||||
{
|
||||
emit->Write8(bits == 8 ? normalops[op].fromRm8 : normalops[op].fromRm32);
|
||||
// _assert_msg_(DYNA_REC, code[-1] != 0xCC, "ARGH5");
|
||||
}
|
||||
}
|
||||
if (!skip_rest)
|
||||
WriteRest(emit, immToWrite>>3, _operandReg);
|
||||
WriteRest(emit, immToWrite >> 3, _operandReg);
|
||||
switch (immToWrite)
|
||||
{
|
||||
case 0:
|
||||
|
@ -471,7 +471,7 @@ SHIFT_TEST(SAR)
|
||||
}; \
|
||||
for (const auto& regset : regsets) \
|
||||
for (const auto& r : regset.regs) \
|
||||
{ \
|
||||
{ \
|
||||
emitter->Name(regset.bits, R(r.reg), R(RAX)); \
|
||||
emitter->Name(regset.bits, R(RAX), R(r.reg)); \
|
||||
emitter->Name(regset.bits, R(r.reg), Imm8(0x42)); \
|
||||
@ -480,7 +480,7 @@ SHIFT_TEST(SAR)
|
||||
#Name " " + regset.out_name + ", " + r.name + " " \
|
||||
#Name " " + r.name + ", 0x42 " \
|
||||
#Name " " + regset.size + " ptr ds:[r12], " + r.name); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
BT_TEST(BT)
|
||||
@ -506,14 +506,14 @@ BT_TEST(BTC)
|
||||
}; \
|
||||
for (const auto& regset : regsets) \
|
||||
for (const auto& r : regset.regs) \
|
||||
{ \
|
||||
{ \
|
||||
emitter->Name(regset.bits, R(r.reg)); \
|
||||
emitter->Name(regset.bits, MatR(RAX)); \
|
||||
emitter->Name(regset.bits, MatR(R12)); \
|
||||
ExpectDisassembly(#Name " " + r.name + " " \
|
||||
#Name " " + regset.size + " ptr ds:[rax] " \
|
||||
#Name " " + regset.size + " ptr ds:[r12]"); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
ONE_OP_ARITH_TEST(NOT)
|
||||
@ -527,12 +527,14 @@ ONE_OP_ARITH_TEST(NEG)
|
||||
std::vector<NamedReg> regs; \
|
||||
std::string size; \
|
||||
std::string rax_name; \
|
||||
Gen::OpArg imm; \
|
||||
std::string immname; \
|
||||
} regsets[] = { \
|
||||
{ 8, reg8names, "byte", "al" }, \
|
||||
{ 8, reg8hnames, "byte", "al" }, \
|
||||
{ 16, reg16names, "word", "ax" }, \
|
||||
{ 32, reg32names, "dword", "eax" }, \
|
||||
{ 64, reg64names, "qword", "rax" }, \
|
||||
{ 8, reg8names, "byte", "al", Imm8(0xEF), "0xef" }, \
|
||||
{ 8, reg8hnames, "byte", "al", Imm8(0xEF), "0xef" }, \
|
||||
{ 16, reg16names, "word", "ax", Imm16(0xBEEF), "0xbeef" }, \
|
||||
{ 32, reg32names, "dword", "eax", Imm32(0xDEADBEEF), "0xdeadbeef" }, \
|
||||
{ 64, reg64names, "qword", "rax", Imm32(0xDEADBEEF), "0xffffffffdeadbeef" }, \
|
||||
}; \
|
||||
for (const auto& regset : regsets) \
|
||||
for (const auto& r : regset.regs) \
|
||||
@ -541,10 +543,12 @@ ONE_OP_ARITH_TEST(NEG)
|
||||
emitter->Name(regset.bits, R(RAX), R(r.reg)); \
|
||||
emitter->Name(regset.bits, R(r.reg), MatR(RAX)); \
|
||||
emitter->Name(regset.bits, MatR(RAX), R(r.reg)); \
|
||||
emitter->Name(regset.bits, R(r.reg), regset.imm); \
|
||||
ExpectDisassembly(#Name " " + r.name + ", " + regset.rax_name + " " \
|
||||
#Name " " + regset.rax_name + ", " + r.name + " " \
|
||||
#Name " " + r.name + ", " + regset.size + " ptr ds:[rax] " \
|
||||
#Name " " + regset.size + " ptr ds:[rax], " + r.name); \
|
||||
#Name " " + regset.size + " ptr ds:[rax], " + r.name + " " \
|
||||
#Name " " + r.name + ", " + regset.immname ); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user