| Index: runtime/vm/disassembler_x64.cc
|
| diff --git a/runtime/vm/disassembler_x64.cc b/runtime/vm/disassembler_x64.cc
|
| index 26735dfd65e3897257a5f64ce2428bafed45bc05..657fbc07fb07fbac75a73265d40c780b59aa97ee 100644
|
| --- a/runtime/vm/disassembler_x64.cc
|
| +++ b/runtime/vm/disassembler_x64.cc
|
| @@ -38,7 +38,6 @@ struct ByteMnemonic {
|
| const char* mnem;
|
| };
|
|
|
| -
|
| static const ByteMnemonic two_operands_instr[] = {
|
| {0x00, BYTE_OPER_REG_OP_ORDER, "add"},
|
| {0x01, OPER_REG_OP_ORDER, "add"},
|
| @@ -84,7 +83,6 @@ static const ByteMnemonic two_operands_instr[] = {
|
| {0x8D, REG_OPER_OP_ORDER, "lea"},
|
| {-1, UNSET_OP_ORDER, ""}};
|
|
|
| -
|
| static const ByteMnemonic zero_operands_instr[] = {
|
| {0xC3, UNSET_OP_ORDER, "ret"}, {0xC9, UNSET_OP_ORDER, "leave"},
|
| {0xF4, UNSET_OP_ORDER, "hlt"}, {0xFC, UNSET_OP_ORDER, "cld"},
|
| @@ -96,12 +94,10 @@ static const ByteMnemonic zero_operands_instr[] = {
|
| {0xA6, UNSET_OP_ORDER, "cmps"}, {0xA7, UNSET_OP_ORDER, "cmps"},
|
| {-1, UNSET_OP_ORDER, ""}};
|
|
|
| -
|
| static const ByteMnemonic call_jump_instr[] = {{0xE8, UNSET_OP_ORDER, "call"},
|
| {0xE9, UNSET_OP_ORDER, "jmp"},
|
| {-1, UNSET_OP_ORDER, ""}};
|
|
|
| -
|
| static const ByteMnemonic short_immediate_instr[] = {
|
| {0x05, UNSET_OP_ORDER, "add"}, {0x0D, UNSET_OP_ORDER, "or"},
|
| {0x15, UNSET_OP_ORDER, "adc"}, {0x1D, UNSET_OP_ORDER, "sbb"},
|
| @@ -109,12 +105,10 @@ static const ByteMnemonic short_immediate_instr[] = {
|
| {0x35, UNSET_OP_ORDER, "xor"}, {0x3D, UNSET_OP_ORDER, "cmp"},
|
| {-1, UNSET_OP_ORDER, ""}};
|
|
|
| -
|
| static const char* const conditional_code_suffix[] = {
|
| "o", "no", "c", "nc", "z", "nz", "na", "a",
|
| "s", "ns", "pe", "po", "l", "ge", "le", "g"};
|
|
|
| -
|
| enum InstructionType {
|
| NO_INSTR,
|
| ZERO_OPERANDS_INSTR,
|
| @@ -127,7 +121,6 @@ enum InstructionType {
|
| SHORT_IMMEDIATE_INSTR
|
| };
|
|
|
| -
|
| enum Prefixes {
|
| ESCAPE_PREFIX = 0x0F,
|
| OPERAND_SIZE_OVERRIDE_PREFIX = 0x66,
|
| @@ -137,7 +130,6 @@ enum Prefixes {
|
| REPEQ_PREFIX = REP_PREFIX
|
| };
|
|
|
| -
|
| struct InstructionDesc {
|
| const char* mnem;
|
| InstructionType type;
|
| @@ -145,7 +137,6 @@ struct InstructionDesc {
|
| bool byte_size_operation; // Fixed 8-bit operation.
|
| };
|
|
|
| -
|
| class InstructionTable : public ValueObject {
|
| public:
|
| InstructionTable();
|
| @@ -166,13 +157,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 = "(bad)";
|
| @@ -182,7 +171,6 @@ void InstructionTable::Clear() {
|
| }
|
| }
|
|
|
| -
|
| void InstructionTable::Init() {
|
| CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
|
| CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
|
| @@ -194,7 +182,6 @@ void InstructionTable::Init() {
|
| SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, false, "mov");
|
| }
|
|
|
| -
|
| void InstructionTable::CopyTable(const ByteMnemonic bm[],
|
| InstructionType type) {
|
| for (int i = 0; bm[i].b >= 0; i++) {
|
| @@ -209,7 +196,6 @@ void InstructionTable::CopyTable(const ByteMnemonic bm[],
|
| }
|
| }
|
|
|
| -
|
| void InstructionTable::SetTableRange(InstructionType type,
|
| uint8_t start,
|
| uint8_t end,
|
| @@ -224,7 +210,6 @@ void InstructionTable::SetTableRange(InstructionType type,
|
| }
|
| }
|
|
|
| -
|
| void InstructionTable::AddJumpConditionalShort() {
|
| for (uint8_t b = 0x70; b <= 0x7F; b++) {
|
| InstructionDesc* id = &instructions_[b];
|
| @@ -234,10 +219,8 @@ void InstructionTable::AddJumpConditionalShort() {
|
| }
|
| }
|
|
|
| -
|
| static InstructionTable instruction_table;
|
|
|
| -
|
| static InstructionDesc cmov_instructions[16] = {
|
| {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| @@ -256,11 +239,9 @@ static InstructionDesc cmov_instructions[16] = {
|
| {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}};
|
|
|
| -
|
| //-------------------------------------------------
|
| // DisassemblerX64 implementation.
|
|
|
| -
|
| static const int kMaxXmmRegisters = 16;
|
| static const char* xmm_regs[kMaxXmmRegisters] = {
|
| "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
|
| @@ -392,7 +373,6 @@ class DisassemblerX64 : public ValueObject {
|
| DISALLOW_COPY_AND_ASSIGN(DisassemblerX64);
|
| };
|
|
|
| -
|
| // Append the str to the output buffer.
|
| void DisassemblerX64::Print(const char* format, ...) {
|
| intptr_t available = buffer_size_ - buffer_pos_;
|
| @@ -410,7 +390,6 @@ void DisassemblerX64::Print(const char* format, ...) {
|
| ASSERT(buffer_pos_ < buffer_size_);
|
| }
|
|
|
| -
|
| int DisassemblerX64::PrintRightOperandHelper(
|
| uint8_t* modrmp,
|
| RegisterNameMapping direct_register_name) {
|
| @@ -491,7 +470,6 @@ int DisassemblerX64::PrintRightOperandHelper(
|
| UNREACHABLE();
|
| }
|
|
|
| -
|
| int DisassemblerX64::PrintImmediate(uint8_t* data,
|
| OperandSize size,
|
| bool sign_extend) {
|
| @@ -553,7 +531,6 @@ void DisassemblerX64::PrintDisp(int disp, const char* after) {
|
| if (after != NULL) Print("%s", after);
|
| }
|
|
|
| -
|
| // Returns number of bytes used by machine instruction, including *data byte.
|
| // Writes immediate instructions to 'tmp_buffer_'.
|
| int DisassemblerX64::PrintImmediateOp(uint8_t* data) {
|
| @@ -599,7 +576,6 @@ int DisassemblerX64::PrintImmediateOp(uint8_t* data) {
|
| return 1 + count;
|
| }
|
|
|
| -
|
| // Returns number of bytes used, including *data.
|
| int DisassemblerX64::F6F7Instruction(uint8_t* data) {
|
| ASSERT(*data == 0xF7 || *data == 0xF6);
|
| @@ -641,7 +617,6 @@ int DisassemblerX64::F6F7Instruction(uint8_t* data) {
|
| }
|
| }
|
|
|
| -
|
| int DisassemblerX64::ShiftInstruction(uint8_t* data) {
|
| uint8_t op = *data & (~1);
|
| if (op != 0xD0 && op != 0xD2 && op != 0xC0) {
|
| @@ -702,23 +677,19 @@ int DisassemblerX64::ShiftInstruction(uint8_t* data) {
|
| return num_bytes;
|
| }
|
|
|
| -
|
| int DisassemblerX64::PrintRightOperand(uint8_t* modrmp) {
|
| return PrintRightOperandHelper(modrmp, &DisassemblerX64::NameOfCPURegister);
|
| }
|
|
|
| -
|
| int DisassemblerX64::PrintRightByteOperand(uint8_t* modrmp) {
|
| return PrintRightOperandHelper(modrmp,
|
| &DisassemblerX64::NameOfByteCPURegister);
|
| }
|
|
|
| -
|
| int DisassemblerX64::PrintRightXMMOperand(uint8_t* modrmp) {
|
| return PrintRightOperandHelper(modrmp, &DisassemblerX64::NameOfXMMRegister);
|
| }
|
|
|
| -
|
| // Returns number of bytes used including the current *data.
|
| // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
|
| int DisassemblerX64::PrintOperands(const char* mnem,
|
| @@ -751,13 +722,11 @@ int DisassemblerX64::PrintOperands(const char* mnem,
|
| return advance;
|
| }
|
|
|
| -
|
| void DisassemblerX64::PrintAddress(uint8_t* addr_byte_ptr) {
|
| uword addr = reinterpret_cast<uword>(addr_byte_ptr);
|
| Print("%#" Px "", addr);
|
| }
|
|
|
| -
|
| // Returns number of bytes used, including *data.
|
| int DisassemblerX64::JumpShort(uint8_t* data) {
|
| ASSERT(0xEB == *data);
|
| @@ -768,7 +737,6 @@ int DisassemblerX64::JumpShort(uint8_t* data) {
|
| return 2;
|
| }
|
|
|
| -
|
| // Returns number of bytes used, including *data.
|
| int DisassemblerX64::JumpConditional(uint8_t* data) {
|
| ASSERT(0x0F == *data);
|
| @@ -780,7 +748,6 @@ int DisassemblerX64::JumpConditional(uint8_t* data) {
|
| return 6; // includes 0x0F
|
| }
|
|
|
| -
|
| // Returns number of bytes used, including *data.
|
| int DisassemblerX64::JumpConditionalShort(uint8_t* data) {
|
| uint8_t cond = *data & 0x0F;
|
| @@ -792,7 +759,6 @@ int DisassemblerX64::JumpConditionalShort(uint8_t* data) {
|
| return 2;
|
| }
|
|
|
| -
|
| // Returns number of bytes used, including *data.
|
| int DisassemblerX64::SetCC(uint8_t* data) {
|
| ASSERT(0x0F == *data);
|
| @@ -803,7 +769,6 @@ int DisassemblerX64::SetCC(uint8_t* data) {
|
| return 3; // includes 0x0F
|
| }
|
|
|
| -
|
| // Returns number of bytes used, including *data.
|
| int DisassemblerX64::FPUInstruction(uint8_t* data) {
|
| uint8_t escape_opcode = *data;
|
| @@ -817,7 +782,6 @@ int DisassemblerX64::FPUInstruction(uint8_t* data) {
|
| }
|
| }
|
|
|
| -
|
| int DisassemblerX64::MemoryFPUInstruction(int escape_opcode,
|
| int modrm_byte,
|
| uint8_t* modrm_start) {
|
| @@ -1070,7 +1034,6 @@ int DisassemblerX64::RegisterFPUInstruction(int escape_opcode,
|
| return 2;
|
| }
|
|
|
| -
|
| // TODO(srdjan): Should we add a branch hint argument?
|
| bool DisassemblerX64::DecodeInstructionType(uint8_t** data) {
|
| uint8_t current;
|
| @@ -1185,7 +1148,6 @@ bool DisassemblerX64::DecodeInstructionType(uint8_t** data) {
|
| return true;
|
| }
|
|
|
| -
|
| // Handle all two-byte opcodes, which start with 0x0F.
|
| // These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix.
|
| // We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A.
|
| @@ -1568,7 +1530,6 @@ int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) {
|
| return static_cast<int>(current - data);
|
| }
|
|
|
| -
|
| // Mnemonics for two-byte opcode instructions starting with 0x0F.
|
| // The argument is the second byte of the two-byte opcode.
|
| // Returns NULL if the instruction is not handled here.
|
| @@ -1626,7 +1587,6 @@ const char* DisassemblerX64::TwoByteMnemonic(uint8_t opcode) {
|
| }
|
| }
|
|
|
| -
|
| int DisassemblerX64::InstructionDecode(uword pc) {
|
| uint8_t* data = reinterpret_cast<uint8_t*>(pc);
|
|
|
| @@ -1943,7 +1903,6 @@ int DisassemblerX64::InstructionDecode(uword pc) {
|
| return instr_len;
|
| }
|
|
|
| -
|
| void Disassembler::DecodeInstruction(char* hex_buffer,
|
| intptr_t hex_size,
|
| char* human_buffer,
|
|
|