mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-11 08:39:13 +01:00
4c3230bcde
It isn't easily accessible with sigaction or Mach exceptions (well, requires an additional system call in the latter), and isn't necessary. (and get rid of the enum, because it's only used once, and the comments are more expressive than enum names)
215 lines
3.8 KiB
C++
215 lines
3.8 KiB
C++
// Copyright 2013 Dolphin Emulator Project
|
|
// Licensed under GPLv2
|
|
// Refer to the license.txt file included.
|
|
|
|
#include "x64Analyzer.h"
|
|
|
|
bool DisassembleMov(const unsigned char *codePtr, InstructionInfo *info)
|
|
{
|
|
unsigned const char *startCodePtr = codePtr;
|
|
u8 rex = 0;
|
|
u8 codeByte = 0;
|
|
u8 codeByte2 = 0;
|
|
|
|
//Check for regular prefix
|
|
info->operandSize = 4;
|
|
info->zeroExtend = false;
|
|
info->signExtend = false;
|
|
info->hasImmediate = false;
|
|
info->isMemoryWrite = false;
|
|
|
|
u8 modRMbyte = 0;
|
|
u8 sibByte = 0;
|
|
bool hasModRM = false;
|
|
|
|
int displacementSize = 0;
|
|
|
|
if (*codePtr == 0x66)
|
|
{
|
|
info->operandSize = 2;
|
|
codePtr++;
|
|
}
|
|
else if (*codePtr == 0x67)
|
|
{
|
|
codePtr++;
|
|
}
|
|
|
|
//Check for REX prefix
|
|
if ((*codePtr & 0xF0) == 0x40)
|
|
{
|
|
rex = *codePtr;
|
|
if (rex & 8) //REX.W
|
|
{
|
|
info->operandSize = 8;
|
|
}
|
|
codePtr++;
|
|
}
|
|
|
|
codeByte = *codePtr++;
|
|
|
|
// Skip two-byte opcode byte
|
|
bool twoByte = false;
|
|
if(codeByte == 0x0F)
|
|
{
|
|
twoByte = true;
|
|
codeByte2 = *codePtr++;
|
|
}
|
|
|
|
if (!twoByte)
|
|
{
|
|
if ((codeByte & 0xF0) == 0x80 ||
|
|
((codeByte & 0xF8) == 0xC0 && (codeByte & 0x0E) != 0x02))
|
|
{
|
|
modRMbyte = *codePtr++;
|
|
hasModRM = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
if (hasModRM)
|
|
{
|
|
ModRM mrm(modRMbyte, rex);
|
|
info->regOperandReg = mrm.reg;
|
|
if (mrm.mod < 3)
|
|
{
|
|
if (mrm.rm == 4)
|
|
{
|
|
//SIB byte
|
|
sibByte = *codePtr++;
|
|
info->scaledReg = (sibByte >> 3) & 7;
|
|
info->otherReg = (sibByte & 7);
|
|
if (rex & 2) info->scaledReg += 8;
|
|
if (rex & 1) info->otherReg += 8;
|
|
}
|
|
else
|
|
{
|
|
//info->scaledReg =
|
|
}
|
|
}
|
|
if (mrm.mod == 1 || mrm.mod == 2)
|
|
{
|
|
if (mrm.mod == 1)
|
|
displacementSize = 1;
|
|
else
|
|
displacementSize = 4;
|
|
}
|
|
}
|
|
|
|
if (displacementSize == 1)
|
|
info->displacement = (s32)(s8)*codePtr;
|
|
else
|
|
info->displacement = *((s32 *)codePtr);
|
|
codePtr += displacementSize;
|
|
|
|
|
|
switch (codeByte)
|
|
{
|
|
// writes
|
|
case 0xC6: // mem <- imm8
|
|
{
|
|
info->isMemoryWrite = true;
|
|
info->hasImmediate = true;
|
|
info->immediate = *codePtr;
|
|
codePtr++; //move past immediate
|
|
}
|
|
break;
|
|
|
|
case 0xC7: // mem <- imm16/32
|
|
{
|
|
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 0x89: // mem <- r16/32/64
|
|
{
|
|
info->isMemoryWrite = true;
|
|
break;
|
|
}
|
|
|
|
case 0x0F: // two-byte escape
|
|
{
|
|
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;
|
|
}
|
|
|
|
case 0x8A: // r8 <- mem
|
|
{
|
|
info->isMemoryWrite = false;
|
|
if (info->operandSize == 4)
|
|
{
|
|
info->operandSize = 1;
|
|
break;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
case 0x8B: // r16/32/64 <- mem
|
|
{
|
|
info->isMemoryWrite = false;
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
info->instructionSize = (int)(codePtr - startCodePtr);
|
|
return true;
|
|
}
|