summaryrefslogtreecommitdiff
path: root/Source/Core/Common/x64Emitter.cpp
diff options
context:
space:
mode:
authorFiora <fioraaeterna@gmail.com>2014-09-10 23:54:06 -0700
committerFiora <fioraaeterna@gmail.com>2014-09-11 11:40:30 -0700
commit18d83a310e4e1d985ea70f0e5848a6ec830d3565 (patch)
tree31042af1b3f1f3e83f1f00e28af9bbb1cf81962f /Source/Core/Common/x64Emitter.cpp
parent67f7e7e28b0de7b1f4060900b6158cf9733d9a90 (diff)
X64Emitter: support shorter mov reg, imm opcodes
Also refactor WriteNormalOp a little bit and add comments.
Diffstat (limited to 'Source/Core/Common/x64Emitter.cpp')
-rw-r--r--Source/Core/Common/x64Emitter.cpp54
1 files changed, 39 insertions, 15 deletions
diff --git a/Source/Core/Common/x64Emitter.cpp b/Source/Core/Common/x64Emitter.cpp
index 9d9b2551c1..77cb1f9f72 100644
--- a/Source/Core/Common/x64Emitter.cpp
+++ b/Source/Core/Common/x64Emitter.cpp
@@ -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
{
- if (!scale && offsetOrBaseReg == EAX && normalops[op].eaximm32 != 0xCC)
+ // mov reg, imm
+ if (!scale && op == nrmMOV && bits != 64)
{
- emit->Write8(normalops[op].eaximm32);
- skip_rest = true;
+ emit->Write8(0xB8 + (offsetOrBaseReg & 7));
+ if (bits == 16)
+ emit->Write16((u16)operand.offset);
+ else
+ emit->Write32((u32)operand.offset);
+ return;
}
- else
+ // op eax, imm
+ if (!scale && offsetOrBaseReg == EAX && normalops[op].eaximm32 != 0xCC)
{
- emit->Write8(normalops[op].imm32);
+ emit->Write8(normalops[op].eaximm32);
+ 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: