summaryrefslogtreecommitdiff
path: root/Source/Core/Common/x64Analyzer.cpp
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2014-04-24 17:23:34 +0200
committerPierre Bourdon <delroth@gmail.com>2014-04-24 17:23:34 +0200
commit47373af9d9fc8b1da23547cc5190834025cd0399 (patch)
tree8f6f0db970852326036bcb1ec4b0101986adca50 /Source/Core/Common/x64Analyzer.cpp
parent13b1ff5160c5489efd5d6dbfb79475755a3ae3ee (diff)
parent1f2e551c8c8bc96285288af5c65465aa40286f1b (diff)
Merge pull request #303 from Tilka/movbe
Add remaining possible uses of MOVBE
Diffstat (limited to 'Source/Core/Common/x64Analyzer.cpp')
-rw-r--r--Source/Core/Common/x64Analyzer.cpp222
1 files changed, 109 insertions, 113 deletions
diff --git a/Source/Core/Common/x64Analyzer.cpp b/Source/Core/Common/x64Analyzer.cpp
index 72ff1105a5..4878f9dea8 100644
--- a/Source/Core/Common/x64Analyzer.cpp
+++ b/Source/Core/Common/x64Analyzer.cpp
@@ -8,8 +8,8 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo *info)
{
unsigned const char *startCodePtr = codePtr;
u8 rex = 0;
- u8 codeByte = 0;
- u8 codeByte2 = 0;
+ u32 opcode;
+ int opcode_length;
//Check for regular prefix
info->operandSize = 4;
@@ -17,6 +17,7 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo *info)
info->signExtend = false;
info->hasImmediate = false;
info->isMemoryWrite = false;
+ info->byteSwap = false;
u8 modRMbyte = 0;
u8 sibByte = 0;
@@ -45,41 +46,53 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo *info)
codePtr++;
}
- codeByte = *codePtr++;
-
- // Skip two-byte opcode byte
- bool twoByte = false;
- if (codeByte == 0x0F)
+ opcode = *codePtr++;
+ opcode_length = 1;
+ if (opcode == 0x0F)
{
- twoByte = true;
- codeByte2 = *codePtr++;
- }
-
- if (!twoByte)
- {
- if ((codeByte & 0xF0) == 0x80 ||
- ((codeByte & 0xF8) == 0xC0 && (codeByte & 0x0E) != 0x02))
+ opcode = (opcode << 8) | *codePtr++;
+ opcode_length = 2;
+ if ((opcode & 0xFB) == 0x38)
{
- modRMbyte = *codePtr++;
- hasModRM = true;
+ opcode = (opcode << 8) | *codePtr++;
+ opcode_length = 3;
}
}
- else
+
+ switch (opcode_length)
{
- if (((codeByte2 & 0xF0) == 0x00 && (codeByte2 & 0x0F) >= 0x04 && (codeByte2 & 0x0D) != 0x0D) ||
- (codeByte2 & 0xF0) == 0x30 ||
- codeByte2 == 0x77 ||
- (codeByte2 & 0xF0) == 0x80 ||
- ((codeByte2 & 0xF0) == 0xA0 && (codeByte2 & 0x07) <= 0x02) ||
- (codeByte2 & 0xF8) == 0xC8)
- {
- // No mod R/M byte
- }
- else
- {
- modRMbyte = *codePtr++;
- hasModRM = true;
- }
+ case 1:
+ if ((opcode & 0xF0) == 0x80 ||
+ ((opcode & 0xF8) == 0xC0 && (opcode & 0x0E) != 0x02))
+ {
+ modRMbyte = *codePtr++;
+ hasModRM = true;
+ }
+ break;
+ case 2:
+ if (((opcode & 0xF0) == 0x00 && (opcode & 0x0F) >= 0x04 && (opcode & 0x0D) != 0x0D) ||
+ ((opcode & 0xF0) == 0xA0 && (opcode & 0x07) <= 0x02) ||
+ (opcode & 0xF0) == 0x30 ||
+ (opcode & 0xFF) == 0x77 ||
+ (opcode & 0xF0) == 0x80 ||
+ (opcode & 0xF8) == 0xC8)
+ {
+ // No mod R/M byte
+ }
+ else
+ {
+ modRMbyte = *codePtr++;
+ hasModRM = true;
+ }
+ break;
+ case 3:
+ // TODO: support more 3-byte opcode instructions
+ if ((opcode & 0xFE) == 0xF0)
+ {
+ modRMbyte = *codePtr++;
+ hasModRM = true;
+ }
+ break;
}
if (hasModRM)
@@ -114,109 +127,92 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo *info)
if (displacementSize == 1)
info->displacement = (s32)(s8)*codePtr;
else
- info->displacement = *((s32 *)codePtr);
+ info->displacement = *((s32*)codePtr);
codePtr += displacementSize;
-
- switch (codeByte)
+ switch (opcode)
{
- // writes
case 0xC6: // mem <- imm8
- {
- info->isMemoryWrite = true;
- info->hasImmediate = true;
- info->immediate = *codePtr;
- codePtr++; //move past immediate
- }
+ info->isMemoryWrite = true;
+ info->hasImmediate = true;
+ info->immediate = *codePtr;
+ codePtr++;
break;
case 0xC7: // mem <- imm16/32
+ info->isMemoryWrite = true;
+ switch (info->operandSize)
{
- info->isMemoryWrite = true;
- if (info->operandSize == 2)
- {
- info->hasImmediate = true;
- info->immediate = *(u16*)codePtr;
- codePtr += 2;
- }
- else if (info->operandSize == 4)
- {
- info->hasImmediate = true;
- info->immediate = *(u32*)codePtr;
- codePtr += 4;
- }
- else if (info->operandSize == 8)
- {
- info->zeroExtend = true;
- info->immediate = *(u32*)codePtr;
- codePtr += 4;
- }
- }
-
- case 0x88: // mem <- r8
- {
- info->isMemoryWrite = true;
- if (info->operandSize == 4)
- {
- info->operandSize = 1;
- break;
- }
- else
- return false;
+ case 2:
+ info->hasImmediate = true;
+ info->immediate = *(u16*)codePtr;
+ codePtr += 2;
break;
- }
- case 0x89: // mem <- r16/32/64
- {
- info->isMemoryWrite = true;
+ case 4:
+ info->hasImmediate = true;
+ info->immediate = *(u32*)codePtr;
+ codePtr += 4;
+ break;
+ case 8:
+ info->zeroExtend = true;
+ info->immediate = *(u32*)codePtr;
+ codePtr += 4;
break;
}
+ break;
- case 0x0F: // two-byte escape
+ case 0x88: // mem <- r8
+ info->isMemoryWrite = true;
+ if (info->operandSize != 4)
{
- info->isMemoryWrite = false;
- switch (codeByte2)
- {
- case 0xB6: // movzx on byte
- info->zeroExtend = true;
- info->operandSize = 1;
- break;
- case 0xB7: // movzx on short
- info->zeroExtend = true;
- info->operandSize = 2;
- break;
- case 0xBE: // movsx on byte
- info->signExtend = true;
- info->operandSize = 1;
- break;
- case 0xBF: // movsx on short
- info->signExtend = true;
- info->operandSize = 2;
- break;
- default:
- return false;
- }
- break;
+ return false;
}
+ info->operandSize = 1;
+ break;
+
+ case 0x89: // mem <- r16/32/64
+ info->isMemoryWrite = true;
+ break;
case 0x8A: // r8 <- mem
+ if (info->operandSize != 4)
{
- info->isMemoryWrite = false;
- if (info->operandSize == 4)
- {
- info->operandSize = 1;
- break;
- }
- else
- return false;
+ return false;
}
+ info->operandSize = 1;
+ break;
case 0x8B: // r16/32/64 <- mem
- {
- info->isMemoryWrite = false;
- break;
- }
+ break;
+
+ case 0x0FB6: // movzx on byte
+ info->zeroExtend = true;
+ info->operandSize = 1;
+ break;
+
+ case 0x0FB7: // movzx on short
+ info->zeroExtend = true;
+ info->operandSize = 2;
+ break;
+
+ case 0x0FBE: // movsx on byte
+ info->signExtend = true;
+ info->operandSize = 1;
+ break;
+
+ case 0x0FBF: // movsx on short
+ info->signExtend = true;
+ info->operandSize = 2;
+ break;
+
+ case 0x0F38F0: // movbe read
+ info->byteSwap = true;
+ break;
+ case 0x0F38F1: // movbe write
+ info->byteSwap = true;
+ info->isMemoryWrite = true;
break;
default: