Index: runtime/vm/disassembler_ia32.cc |
diff --git a/runtime/vm/disassembler_ia32.cc b/runtime/vm/disassembler_ia32.cc |
index 90957ce1886a1134b0b78b2b108765bef69d7148..35414588d6fbc79a1d1bd504fca12c265373ffa7 100644 |
--- a/runtime/vm/disassembler_ia32.cc |
+++ b/runtime/vm/disassembler_ia32.cc |
@@ -20,14 +20,12 @@ namespace dart { |
// Tables used for decoding of x86 instructions. |
enum OperandOrder { UNSET_OP_ORDER = 0, REG_OPER_OP_ORDER, OPER_REG_OP_ORDER }; |
- |
struct ByteMnemonic { |
int b; // -1 terminates, otherwise must be in range (0..255) |
const char* mnem; |
OperandOrder op_order_; |
}; |
- |
static ByteMnemonic two_operands_instr[] = { |
{0x01, "add", OPER_REG_OP_ORDER}, {0x03, "add", REG_OPER_OP_ORDER}, |
{0x09, "or", OPER_REG_OP_ORDER}, {0x0B, "or", REG_OPER_OP_ORDER}, |
@@ -41,7 +39,6 @@ static ByteMnemonic two_operands_instr[] = { |
{0x8A, "mov_b", REG_OPER_OP_ORDER}, {0x8B, "mov", REG_OPER_OP_ORDER}, |
{0x8D, "lea", REG_OPER_OP_ORDER}, {-1, "", UNSET_OP_ORDER}}; |
- |
static ByteMnemonic zero_operands_instr[] = { |
{0xC3, "ret", UNSET_OP_ORDER}, {0xC9, "leave", UNSET_OP_ORDER}, |
{0x90, "nop", UNSET_OP_ORDER}, {0xF4, "hlt", UNSET_OP_ORDER}, |
@@ -51,40 +48,34 @@ static ByteMnemonic zero_operands_instr[] = { |
{0x99, "cdq", UNSET_OP_ORDER}, {0x9B, "fwait", UNSET_OP_ORDER}, |
{-1, "", UNSET_OP_ORDER}}; |
- |
static ByteMnemonic call_jump_instr[] = {{0xE8, "call", UNSET_OP_ORDER}, |
{0xE9, "jmp", UNSET_OP_ORDER}, |
{-1, "", UNSET_OP_ORDER}}; |
- |
static ByteMnemonic short_immediate_instr[] = { |
{0x05, "add", UNSET_OP_ORDER}, {0x0D, "or", UNSET_OP_ORDER}, |
{0x15, "adc", UNSET_OP_ORDER}, {0x25, "and", UNSET_OP_ORDER}, |
{0x2D, "sub", UNSET_OP_ORDER}, {0x35, "xor", UNSET_OP_ORDER}, |
{0x3D, "cmp", UNSET_OP_ORDER}, {-1, "", UNSET_OP_ORDER}}; |
- |
static const char* jump_conditional_mnem[] = { |
/*0*/ "jo", "jno", "jc", "jnc", |
/*4*/ "jz", "jnz", "jna", "ja", |
/*8*/ "js", "jns", "jpe", "jpo", |
/*12*/ "jl", "jnl", "jng", "jg"}; |
- |
static const char* set_conditional_mnem[] = { |
/*0*/ "seto", "setno", "setc", "setnc", |
/*4*/ "setz", "setnz", "setna", "seta", |
/*8*/ "sets", "setns", "setpe", "setpo", |
/*12*/ "setl", "setnl", "setng", "setg"}; |
- |
static const char* conditional_move_mnem[] = { |
/*0*/ "cmovo", "cmovno", "cmovc", "cmovnc", |
/*4*/ "cmovz", "cmovnz", "cmovna", "cmova", |
/*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo", |
/*12*/ "cmovl", "cmovnl", "cmovng", "cmovg"}; |
- |
enum InstructionType { |
NO_INSTR, |
ZERO_OPERANDS_INSTR, |
@@ -96,14 +87,12 @@ enum InstructionType { |
SHORT_IMMEDIATE_INSTR |
}; |
- |
struct InstructionDesc { |
const char* mnem; |
InstructionType type; |
OperandOrder op_order_; |
}; |
- |
class InstructionTable : public ValueObject { |
public: |
InstructionTable(); |
@@ -123,13 +112,11 @@ class InstructionTable : public ValueObject { |
DISALLOW_COPY_AND_ASSIGN(InstructionTable); |
}; |
- |
InstructionTable::InstructionTable() { |
Clear(); |
Init(); |
} |
- |
void InstructionTable::Clear() { |
for (int i = 0; i < 256; i++) { |
instructions_[i].mnem = ""; |
@@ -138,7 +125,6 @@ void InstructionTable::Clear() { |
} |
} |
- |
void InstructionTable::Init() { |
CopyTable(two_operands_instr, TWO_OPERANDS_INSTR); |
CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR); |
@@ -153,7 +139,6 @@ void InstructionTable::Init() { |
SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov"); |
} |
- |
void InstructionTable::CopyTable(ByteMnemonic bm[], InstructionType type) { |
for (int i = 0; bm[i].b >= 0; i++) { |
InstructionDesc* id = &instructions_[bm[i].b]; |
@@ -164,7 +149,6 @@ void InstructionTable::CopyTable(ByteMnemonic bm[], InstructionType type) { |
} |
} |
- |
void InstructionTable::SetTableRange(InstructionType type, |
uint8_t start, |
uint8_t end, |
@@ -177,7 +161,6 @@ void InstructionTable::SetTableRange(InstructionType type, |
} |
} |
- |
void InstructionTable::AddJumpConditionalShort() { |
for (uint8_t b = 0x70; b <= 0x7F; b++) { |
InstructionDesc* id = &instructions_[b]; |
@@ -187,10 +170,8 @@ void InstructionTable::AddJumpConditionalShort() { |
} |
} |
- |
static InstructionTable instruction_table; |
- |
// Mnemonics for instructions 0xF0 byte. |
// Returns NULL if the instruction is not handled here. |
static const char* F0Mnem(uint8_t f0byte) { |
@@ -287,7 +268,6 @@ static const char* PackedDoubleMnemonic(uint8_t data) { |
return mnemonic; |
} |
- |
static bool IsTwoXmmRegInstruction(uint8_t f0byte) { |
return f0byte == 0x28 || f0byte == 0x11 || f0byte == 0x12 || f0byte == 0x14 || |
f0byte == 0x15 || f0byte == 0x16 || f0byte == 0x51 || f0byte == 0x52 || |
@@ -296,7 +276,6 @@ static bool IsTwoXmmRegInstruction(uint8_t f0byte) { |
f0byte == 0x5F || f0byte == 0x5A; |
} |
- |
// The implementation of x86 decoding based on the above tables. |
class X86Decoder : public ValueObject { |
public: |
@@ -379,7 +358,6 @@ class X86Decoder : public ValueObject { |
*base = data & 7; |
} |
- |
// Convenience functions. |
char* get_buffer() const { return buffer_; } |
char* current_position_in_buffer() { return buffer_ + buffer_pos_; } |
@@ -392,14 +370,12 @@ class X86Decoder : public ValueObject { |
DISALLOW_COPY_AND_ASSIGN(X86Decoder); |
}; |
- |
void X86Decoder::PrintInt(int value) { |
char int_buffer[16]; |
OS::SNPrint(int_buffer, sizeof(int_buffer), "%#x", value); |
Print(int_buffer); |
} |
- |
// Append the int value (printed in hex) to the output buffer. |
void X86Decoder::PrintHex(int value, bool signed_value) { |
char hex_buffer[16]; |
@@ -411,7 +387,6 @@ void X86Decoder::PrintHex(int value, bool signed_value) { |
Print(hex_buffer); |
} |
- |
// Append the str to the output buffer. |
void X86Decoder::Print(const char* str) { |
char cur = *str++; |
@@ -422,7 +397,6 @@ void X86Decoder::Print(const char* str) { |
buffer_[buffer_pos_] = '\0'; |
} |
- |
static const int kMaxCPURegisters = 8; |
static const char* cpu_regs[kMaxCPURegisters] = {"eax", "ecx", "edx", "ebx", |
"esp", "ebp", "esi", "edi"}; |
@@ -441,14 +415,12 @@ void X86Decoder::PrintCPURegister(int reg) { |
Print(cpu_regs[reg]); |
} |
- |
void X86Decoder::PrintCPUByteRegister(int reg) { |
ASSERT(0 <= reg); |
ASSERT(reg < kMaxByteCPURegisters); |
Print(byte_cpu_regs[reg]); |
} |
- |
void X86Decoder::PrintXmmRegister(int reg) { |
ASSERT(0 <= reg); |
ASSERT(reg < kMaxXmmRegisters); |
@@ -463,7 +435,6 @@ void X86Decoder::PrintXmmComparison(int comparison) { |
Print(comparisons[comparison]); |
} |
- |
void X86Decoder::PrintAddress(uword addr) { |
char addr_buffer[32]; |
OS::SNPrint(addr_buffer, sizeof(addr_buffer), "%#" Px "", addr); |
@@ -478,7 +449,6 @@ void X86Decoder::PrintAddress(uword addr) { |
} |
} |
- |
int X86Decoder::PrintRightOperandHelper(uint8_t* modrmp, |
RegisterNamePrinter register_printer) { |
int mod, regop, rm; |
@@ -599,22 +569,18 @@ int X86Decoder::PrintRightOperandHelper(uint8_t* modrmp, |
UNREACHABLE(); |
} |
- |
int X86Decoder::PrintRightOperand(uint8_t* modrmp) { |
return PrintRightOperandHelper(modrmp, &X86Decoder::PrintCPURegister); |
} |
- |
int X86Decoder::PrintRightXmmOperand(uint8_t* modrmp) { |
return PrintRightOperandHelper(modrmp, &X86Decoder::PrintXmmRegister); |
} |
- |
int X86Decoder::PrintRightByteOperand(uint8_t* modrmp) { |
return PrintRightOperandHelper(modrmp, &X86Decoder::PrintCPUByteRegister); |
} |
- |
int X86Decoder::PrintOperands(const char* mnem, |
OperandOrder op_order, |
uint8_t* data) { |
@@ -646,7 +612,6 @@ int X86Decoder::PrintOperands(const char* mnem, |
return advance; |
} |
- |
int X86Decoder::PrintImmediateOp(uint8_t* data, bool size_override) { |
bool sign_extension_bit = (*data & 0x02) != 0; |
uint8_t modrm = *(data + 1); |
@@ -697,7 +662,6 @@ int X86Decoder::PrintImmediateOp(uint8_t* data, bool size_override) { |
} |
} |
- |
int X86Decoder::DecodeEnter(uint8_t* data) { |
uint16_t size = *reinterpret_cast<uint16_t*>(data + 1); |
uint8_t level = *reinterpret_cast<uint8_t*>(data + 3); |
@@ -708,7 +672,6 @@ int X86Decoder::DecodeEnter(uint8_t* data) { |
return 4; |
} |
- |
// Returns number of bytes used, including *data. |
int X86Decoder::JumpShort(uint8_t* data) { |
ASSERT(*data == 0xEB); |
@@ -719,7 +682,6 @@ int X86Decoder::JumpShort(uint8_t* data) { |
return 2; |
} |
- |
// Returns number of bytes used, including *data. |
int X86Decoder::JumpConditional(uint8_t* data, const char* comment) { |
ASSERT(*data == 0x0F); |
@@ -737,7 +699,6 @@ int X86Decoder::JumpConditional(uint8_t* data, const char* comment) { |
return 6; // includes 0x0F |
} |
- |
// Returns number of bytes used, including *data. |
int X86Decoder::JumpConditionalShort(uint8_t* data, const char* comment) { |
uint8_t cond = *data & 0x0F; |
@@ -754,7 +715,6 @@ int X86Decoder::JumpConditionalShort(uint8_t* data, const char* comment) { |
return 2; |
} |
- |
// Returns number of bytes used, including *data. |
int X86Decoder::SetCC(uint8_t* data) { |
ASSERT(*data == 0x0F); |
@@ -766,7 +726,6 @@ int X86Decoder::SetCC(uint8_t* data) { |
return 3; // includes 0x0F |
} |
- |
// Returns number of bytes used, including *data. |
int X86Decoder::CMov(uint8_t* data) { |
ASSERT(*data == 0x0F); |
@@ -776,7 +735,6 @@ int X86Decoder::CMov(uint8_t* data) { |
return 2 + op_size; // includes 0x0F |
} |
- |
int X86Decoder::D1D3C1Instruction(uint8_t* data) { |
uint8_t op = *data; |
ASSERT(op == 0xD1 || op == 0xD3 || op == 0xC1); |
@@ -820,7 +778,6 @@ int X86Decoder::D1D3C1Instruction(uint8_t* data) { |
return num_bytes; |
} |
- |
uint8_t* X86Decoder::F3Instruction(uint8_t* data) { |
if (*(data + 1) == 0x0F) { |
uint8_t b2 = *(data + 2); |
@@ -937,7 +894,6 @@ uint8_t* X86Decoder::F3Instruction(uint8_t* data) { |
return data; |
} |
- |
// Returns number of bytes used, including *data. |
int X86Decoder::F7Instruction(uint8_t* data) { |
ASSERT(*data == 0xF7); |
@@ -1181,7 +1137,6 @@ int X86Decoder::FPUInstruction(uint8_t* data) { |
return 2; |
} |
- |
uint8_t* X86Decoder::SSEInstruction(uint8_t prefix, |
uint8_t primary, |
uint8_t* data) { |
@@ -1213,7 +1168,6 @@ uint8_t* X86Decoder::SSEInstruction(uint8_t prefix, |
return data; |
} |
- |
int X86Decoder::BitwisePDInstruction(uint8_t* data) { |
const char* mnem = |
(*data == 0x57) ? "xorpd" : (*data == 0x56) ? "orpd" : "andpd"; |
@@ -1226,7 +1180,6 @@ int X86Decoder::BitwisePDInstruction(uint8_t* data) { |
return 1 + PrintRightXmmOperand(data + 1); |
} |
- |
int X86Decoder::Packed660F38Instruction(uint8_t* data) { |
if (*(data + 1) == 0x25) { |
Print("pmovsxdq "); |
@@ -1247,7 +1200,6 @@ int X86Decoder::Packed660F38Instruction(uint8_t* data) { |
return 1; |
} |
- |
// Called when disassembling test eax, 0xXXXXX. |
void X86Decoder::CheckPrintStop(uint8_t* data) { |
// Recognize stop pattern. |
@@ -1277,7 +1229,6 @@ const char* X86Decoder::GetBranchPrefix(uint8_t** data) { |
} |
} |
- |
bool X86Decoder::DecodeInstructionType(const InstructionDesc& idesc, |
const char* branch_hint, |
uint8_t** data) { |
@@ -1340,7 +1291,6 @@ bool X86Decoder::DecodeInstructionType(const InstructionDesc& idesc, |
} |
} |
- |
int X86Decoder::InstructionDecode(uword pc) { |
uint8_t* data = reinterpret_cast<uint8_t*>(pc); |
// Check for hints. |
@@ -1912,7 +1862,6 @@ int X86Decoder::InstructionDecode(uword pc) { |
return instr_len; |
} // NOLINT |
- |
void Disassembler::DecodeInstruction(char* hex_buffer, |
intptr_t hex_size, |
char* human_buffer, |