mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-22 22:00:39 -06:00
Add remaining possible uses of MOVBE
Also fixes a missing 'break' statement in DisassembleMov().
This commit is contained in:
@ -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 2:
|
||||
info->hasImmediate = true;
|
||||
info->immediate = *(u16*)codePtr;
|
||||
codePtr += 2;
|
||||
break;
|
||||
|
||||
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 0x88: // mem <- r8
|
||||
info->isMemoryWrite = true;
|
||||
if (info->operandSize != 4)
|
||||
{
|
||||
info->isMemoryWrite = true;
|
||||
if (info->operandSize == 4)
|
||||
{
|
||||
info->operandSize = 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
info->operandSize = 1;
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
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:
|
||||
|
@ -17,6 +17,7 @@ struct InstructionInfo
|
||||
bool signExtend;
|
||||
bool hasImmediate;
|
||||
bool isMemoryWrite;
|
||||
bool byteSwap;
|
||||
u64 immediate;
|
||||
s32 displacement;
|
||||
};
|
||||
|
Reference in New Issue
Block a user