diff options
| author | Pierre Bourdon <delroth@gmail.com> | 2014-04-24 17:23:34 +0200 |
|---|---|---|
| committer | Pierre Bourdon <delroth@gmail.com> | 2014-04-24 17:23:34 +0200 |
| commit | 47373af9d9fc8b1da23547cc5190834025cd0399 (patch) | |
| tree | 8f6f0db970852326036bcb1ec4b0101986adca50 /Source/Core/Common/x64Analyzer.cpp | |
| parent | 13b1ff5160c5489efd5d6dbfb79475755a3ae3ee (diff) | |
| parent | 1f2e551c8c8bc96285288af5c65465aa40286f1b (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.cpp | 222 |
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: |
