| Index: runtime/vm/disassembler_x64.cc
|
| diff --git a/runtime/vm/disassembler_x64.cc b/runtime/vm/disassembler_x64.cc
|
| index f389415c533f4369c31885ec680b4d18a83be722..fe384dc62a68eb7b64efed73e4225a1a40394f3d 100644
|
| --- a/runtime/vm/disassembler_x64.cc
|
| +++ b/runtime/vm/disassembler_x64.cc
|
| @@ -40,97 +40,79 @@ struct ByteMnemonic {
|
|
|
|
|
| static const ByteMnemonic two_operands_instr[] = {
|
| - { 0x00, BYTE_OPER_REG_OP_ORDER, "add" },
|
| - { 0x01, OPER_REG_OP_ORDER, "add" },
|
| - { 0x02, BYTE_REG_OPER_OP_ORDER, "add" },
|
| - { 0x03, REG_OPER_OP_ORDER, "add" },
|
| - { 0x08, BYTE_OPER_REG_OP_ORDER, "or" },
|
| - { 0x09, OPER_REG_OP_ORDER, "or" },
|
| - { 0x0A, BYTE_REG_OPER_OP_ORDER, "or" },
|
| - { 0x0B, REG_OPER_OP_ORDER, "or" },
|
| - { 0x10, BYTE_OPER_REG_OP_ORDER, "adc" },
|
| - { 0x11, OPER_REG_OP_ORDER, "adc" },
|
| - { 0x12, BYTE_REG_OPER_OP_ORDER, "adc" },
|
| - { 0x13, REG_OPER_OP_ORDER, "adc" },
|
| - { 0x18, BYTE_OPER_REG_OP_ORDER, "sbb" },
|
| - { 0x19, OPER_REG_OP_ORDER, "sbb" },
|
| - { 0x1A, BYTE_REG_OPER_OP_ORDER, "sbb" },
|
| - { 0x1B, REG_OPER_OP_ORDER, "sbb" },
|
| - { 0x20, BYTE_OPER_REG_OP_ORDER, "and" },
|
| - { 0x21, OPER_REG_OP_ORDER, "and" },
|
| - { 0x22, BYTE_REG_OPER_OP_ORDER, "and" },
|
| - { 0x23, REG_OPER_OP_ORDER, "and" },
|
| - { 0x28, BYTE_OPER_REG_OP_ORDER, "sub" },
|
| - { 0x29, OPER_REG_OP_ORDER, "sub" },
|
| - { 0x2A, BYTE_REG_OPER_OP_ORDER, "sub" },
|
| - { 0x2B, REG_OPER_OP_ORDER, "sub" },
|
| - { 0x30, BYTE_OPER_REG_OP_ORDER, "xor" },
|
| - { 0x31, OPER_REG_OP_ORDER, "xor" },
|
| - { 0x32, BYTE_REG_OPER_OP_ORDER, "xor" },
|
| - { 0x33, REG_OPER_OP_ORDER, "xor" },
|
| - { 0x38, BYTE_OPER_REG_OP_ORDER, "cmp" },
|
| - { 0x39, OPER_REG_OP_ORDER, "cmp" },
|
| - { 0x3A, BYTE_REG_OPER_OP_ORDER, "cmp" },
|
| - { 0x3B, REG_OPER_OP_ORDER, "cmp" },
|
| - { 0x63, REG_OPER_OP_ORDER, "movsxd" },
|
| - { 0x84, BYTE_REG_OPER_OP_ORDER, "test" },
|
| - { 0x85, REG_OPER_OP_ORDER, "test" },
|
| - { 0x86, BYTE_REG_OPER_OP_ORDER, "xchg" },
|
| - { 0x87, REG_OPER_OP_ORDER, "xchg" },
|
| - { 0x88, BYTE_OPER_REG_OP_ORDER, "mov" },
|
| - { 0x89, OPER_REG_OP_ORDER, "mov" },
|
| - { 0x8A, BYTE_REG_OPER_OP_ORDER, "mov" },
|
| - { 0x8B, REG_OPER_OP_ORDER, "mov" },
|
| - { 0x8D, REG_OPER_OP_ORDER, "lea" },
|
| - { -1, UNSET_OP_ORDER, "" }
|
| -};
|
| + {0x00, BYTE_OPER_REG_OP_ORDER, "add"},
|
| + {0x01, OPER_REG_OP_ORDER, "add"},
|
| + {0x02, BYTE_REG_OPER_OP_ORDER, "add"},
|
| + {0x03, REG_OPER_OP_ORDER, "add"},
|
| + {0x08, BYTE_OPER_REG_OP_ORDER, "or"},
|
| + {0x09, OPER_REG_OP_ORDER, "or"},
|
| + {0x0A, BYTE_REG_OPER_OP_ORDER, "or"},
|
| + {0x0B, REG_OPER_OP_ORDER, "or"},
|
| + {0x10, BYTE_OPER_REG_OP_ORDER, "adc"},
|
| + {0x11, OPER_REG_OP_ORDER, "adc"},
|
| + {0x12, BYTE_REG_OPER_OP_ORDER, "adc"},
|
| + {0x13, REG_OPER_OP_ORDER, "adc"},
|
| + {0x18, BYTE_OPER_REG_OP_ORDER, "sbb"},
|
| + {0x19, OPER_REG_OP_ORDER, "sbb"},
|
| + {0x1A, BYTE_REG_OPER_OP_ORDER, "sbb"},
|
| + {0x1B, REG_OPER_OP_ORDER, "sbb"},
|
| + {0x20, BYTE_OPER_REG_OP_ORDER, "and"},
|
| + {0x21, OPER_REG_OP_ORDER, "and"},
|
| + {0x22, BYTE_REG_OPER_OP_ORDER, "and"},
|
| + {0x23, REG_OPER_OP_ORDER, "and"},
|
| + {0x28, BYTE_OPER_REG_OP_ORDER, "sub"},
|
| + {0x29, OPER_REG_OP_ORDER, "sub"},
|
| + {0x2A, BYTE_REG_OPER_OP_ORDER, "sub"},
|
| + {0x2B, REG_OPER_OP_ORDER, "sub"},
|
| + {0x30, BYTE_OPER_REG_OP_ORDER, "xor"},
|
| + {0x31, OPER_REG_OP_ORDER, "xor"},
|
| + {0x32, BYTE_REG_OPER_OP_ORDER, "xor"},
|
| + {0x33, REG_OPER_OP_ORDER, "xor"},
|
| + {0x38, BYTE_OPER_REG_OP_ORDER, "cmp"},
|
| + {0x39, OPER_REG_OP_ORDER, "cmp"},
|
| + {0x3A, BYTE_REG_OPER_OP_ORDER, "cmp"},
|
| + {0x3B, REG_OPER_OP_ORDER, "cmp"},
|
| + {0x63, REG_OPER_OP_ORDER, "movsxd"},
|
| + {0x84, BYTE_REG_OPER_OP_ORDER, "test"},
|
| + {0x85, REG_OPER_OP_ORDER, "test"},
|
| + {0x86, BYTE_REG_OPER_OP_ORDER, "xchg"},
|
| + {0x87, REG_OPER_OP_ORDER, "xchg"},
|
| + {0x88, BYTE_OPER_REG_OP_ORDER, "mov"},
|
| + {0x89, OPER_REG_OP_ORDER, "mov"},
|
| + {0x8A, BYTE_REG_OPER_OP_ORDER, "mov"},
|
| + {0x8B, REG_OPER_OP_ORDER, "mov"},
|
| + {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" },
|
| - { 0xCC, UNSET_OP_ORDER, "int3" },
|
| - { 0x60, UNSET_OP_ORDER, "pushad" },
|
| - { 0x61, UNSET_OP_ORDER, "popad" },
|
| - { 0x9C, UNSET_OP_ORDER, "pushfd" },
|
| - { 0x9D, UNSET_OP_ORDER, "popfd" },
|
| - { 0x9E, UNSET_OP_ORDER, "sahf" },
|
| - { 0x99, UNSET_OP_ORDER, "cdq" },
|
| - { 0x9B, UNSET_OP_ORDER, "fwait" },
|
| - { 0xA4, UNSET_OP_ORDER, "movs" },
|
| - { 0xA5, UNSET_OP_ORDER, "movs" },
|
| - { 0xA6, UNSET_OP_ORDER, "cmps" },
|
| - { 0xA7, UNSET_OP_ORDER, "cmps" },
|
| - { -1, UNSET_OP_ORDER, "" }
|
| -};
|
| + {0xC3, UNSET_OP_ORDER, "ret"}, {0xC9, UNSET_OP_ORDER, "leave"},
|
| + {0xF4, UNSET_OP_ORDER, "hlt"}, {0xFC, UNSET_OP_ORDER, "cld"},
|
| + {0xCC, UNSET_OP_ORDER, "int3"}, {0x60, UNSET_OP_ORDER, "pushad"},
|
| + {0x61, UNSET_OP_ORDER, "popad"}, {0x9C, UNSET_OP_ORDER, "pushfd"},
|
| + {0x9D, UNSET_OP_ORDER, "popfd"}, {0x9E, UNSET_OP_ORDER, "sahf"},
|
| + {0x99, UNSET_OP_ORDER, "cdq"}, {0x9B, UNSET_OP_ORDER, "fwait"},
|
| + {0xA4, UNSET_OP_ORDER, "movs"}, {0xA5, UNSET_OP_ORDER, "movs"},
|
| + {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 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" },
|
| - { 0x25, UNSET_OP_ORDER, "and" },
|
| - { 0x2D, UNSET_OP_ORDER, "sub" },
|
| - { 0x35, UNSET_OP_ORDER, "xor" },
|
| - { 0x3D, UNSET_OP_ORDER, "cmp" },
|
| - { -1, UNSET_OP_ORDER, "" }
|
| -};
|
| + {0x05, UNSET_OP_ORDER, "add"}, {0x0D, UNSET_OP_ORDER, "or"},
|
| + {0x15, UNSET_OP_ORDER, "adc"}, {0x1D, UNSET_OP_ORDER, "sbb"},
|
| + {0x25, UNSET_OP_ORDER, "and"}, {0x2D, UNSET_OP_ORDER, "sub"},
|
| + {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"
|
| -};
|
| + "o", "no", "c", "nc", "z", "nz", "na", "a",
|
| + "s", "ns", "pe", "po", "l", "ge", "le", "g"};
|
|
|
|
|
| enum InstructionType {
|
| @@ -167,9 +149,7 @@ struct InstructionDesc {
|
| class InstructionTable : public ValueObject {
|
| public:
|
| InstructionTable();
|
| - const InstructionDesc& Get(uint8_t x) const {
|
| - return instructions_[x];
|
| - }
|
| + const InstructionDesc& Get(uint8_t x) const { return instructions_[x]; }
|
|
|
| private:
|
| InstructionDesc instructions_[256];
|
| @@ -249,7 +229,7 @@ void InstructionTable::AddJumpConditionalShort() {
|
| for (uint8_t b = 0x70; b <= 0x7F; b++) {
|
| InstructionDesc* id = &instructions_[b];
|
| ASSERT(NO_INSTR == id->type); // Information not already entered
|
| - id->mnem = NULL; // Computed depending on condition code.
|
| + id->mnem = NULL; // Computed depending on condition code.
|
| id->type = JUMP_CONDITIONAL_SHORT_INSTR;
|
| }
|
| }
|
| @@ -259,23 +239,22 @@ 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},
|
| - {"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| - {"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| - {"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| - {"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| - {"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| - {"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| - {"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| - {"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| - {"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| - {"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| - {"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| - {"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| - {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| - {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}
|
| -};
|
| + {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| + {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| + {"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| + {"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| + {"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| + {"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| + {"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| + {"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| + {"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| + {"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| + {"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| + {"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| + {"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| + {"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| + {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
|
| + {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}};
|
|
|
|
|
| //-------------------------------------------------
|
| @@ -284,9 +263,8 @@ static InstructionDesc cmov_instructions[16] = {
|
|
|
| static const int kMaxXmmRegisters = 16;
|
| static const char* xmm_regs[kMaxXmmRegisters] = {
|
| - "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
|
| - "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
|
| -};
|
| + "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
|
| + "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"};
|
|
|
| class DisassemblerX64 : public ValueObject {
|
| public:
|
| @@ -301,8 +279,7 @@ class DisassemblerX64 : public ValueObject {
|
| buffer_[buffer_pos_] = '\0';
|
| }
|
|
|
| - virtual ~DisassemblerX64() {
|
| - }
|
| + virtual ~DisassemblerX64() {}
|
|
|
| int InstructionDecode(uword pc);
|
|
|
| @@ -339,24 +316,16 @@ class DisassemblerX64 : public ValueObject {
|
| return DOUBLEWORD_SIZE;
|
| }
|
|
|
| - char operand_size_code() {
|
| - return "bwlq"[operand_size()];
|
| - }
|
| + char operand_size_code() { return "bwlq"[operand_size()]; }
|
|
|
| // Disassembler helper functions.
|
| - void get_modrm(uint8_t data,
|
| - int* mod,
|
| - int* regop,
|
| - int* rm) {
|
| + void get_modrm(uint8_t data, int* mod, int* regop, int* rm) {
|
| *mod = (data >> 6) & 3;
|
| *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0);
|
| *rm = (data & 7) | (rex_b() ? 8 : 0);
|
| }
|
|
|
| - void get_sib(uint8_t data,
|
| - int* scale,
|
| - int* index,
|
| - int* base) {
|
| + void get_sib(uint8_t data, int* scale, int* index, int* base) {
|
| *scale = (data >> 6) & 3;
|
| *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0);
|
| *base = (data & 7) | (rex_b() ? 8 : 0);
|
| @@ -378,9 +347,7 @@ class DisassemblerX64 : public ValueObject {
|
| void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
|
| void PrintAddress(uint8_t* addr);
|
|
|
| - int PrintOperands(const char* mnem,
|
| - OperandType op_order,
|
| - uint8_t* data);
|
| + int PrintOperands(const char* mnem, OperandType op_order, uint8_t* data);
|
|
|
| typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const;
|
|
|
| @@ -408,13 +375,11 @@ class DisassemblerX64 : public ValueObject {
|
|
|
| bool DecodeInstructionType(uint8_t** data);
|
|
|
| - void UnimplementedInstruction() {
|
| - Print("'Unimplemented Instruction'");
|
| - }
|
| + void UnimplementedInstruction() { Print("'Unimplemented Instruction'"); }
|
|
|
| - char* buffer_; // Decode instructions into this buffer.
|
| + char* buffer_; // Decode instructions into this buffer.
|
| intptr_t buffer_size_; // The size of the buffer_.
|
| - intptr_t buffer_pos_; // Current character position in the buffer_.
|
| + intptr_t buffer_pos_; // Current character position in the buffer_.
|
|
|
| // Prefixes parsed
|
| uint8_t rex_;
|
| @@ -451,8 +416,8 @@ int DisassemblerX64::PrintRightOperandHelper(
|
| RegisterNameMapping direct_register_name) {
|
| int mod, regop, rm;
|
| get_modrm(*modrmp, &mod, ®op, &rm);
|
| - RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
|
| - &DisassemblerX64::NameOfCPURegister;
|
| + RegisterNameMapping register_name =
|
| + (mod == 3) ? direct_register_name : &DisassemblerX64::NameOfCPURegister;
|
| switch (mod) {
|
| case 0:
|
| if ((rm & 7) == 5) {
|
| @@ -478,9 +443,7 @@ int DisassemblerX64::PrintRightOperandHelper(
|
| return 6;
|
| } else if (index != 4 && base != 5) {
|
| // [base+index*scale]
|
| - Print("[%s+%s*%d]",
|
| - NameOfCPURegister(base),
|
| - NameOfCPURegister(index),
|
| + Print("[%s+%s*%d]", NameOfCPURegister(base), NameOfCPURegister(index),
|
| 1 << scale);
|
| return 2;
|
| } else {
|
| @@ -504,9 +467,7 @@ int DisassemblerX64::PrintRightOperandHelper(
|
| Print("[%s", NameOfCPURegister(base));
|
| PrintDisp(disp, "]");
|
| } else {
|
| - Print("[%s+%s*%d",
|
| - NameOfCPURegister(base),
|
| - NameOfCPURegister(index),
|
| + Print("[%s+%s*%d", NameOfCPURegister(base), NameOfCPURegister(index),
|
| 1 << scale);
|
| PrintDisp(disp, "]");
|
| }
|
| @@ -578,8 +539,6 @@ void DisassemblerX64::PrintDisp(int disp, const char* after) {
|
| }
|
|
|
|
|
| -
|
| -
|
| // Returns number of bytes used by machine instruction, including *data byte.
|
| // Writes immediate instructions to 'tmp_buffer_'.
|
| int DisassemblerX64::PrintImmediateOp(uint8_t* data) {
|
| @@ -652,10 +611,7 @@ int DisassemblerX64::F6F7Instruction(uint8_t* data) {
|
| default:
|
| UnimplementedInstruction();
|
| }
|
| - Print("%s%c %s",
|
| - mnem,
|
| - operand_size_code(),
|
| - NameOfCPURegister(rm));
|
| + Print("%s%c %s", mnem, operand_size_code(), NameOfCPURegister(rm));
|
| return 2;
|
| } else if (regop == 0) {
|
| Print("test%c ", operand_size_code());
|
| @@ -720,11 +676,8 @@ int DisassemblerX64::ShiftInstruction(uint8_t* data) {
|
| imm8 = *(data + 2);
|
| num_bytes = 3;
|
| }
|
| - Print("%s%c %s,",
|
| - mnem,
|
| - operand_size_code(),
|
| - byte_size_operand_ ? NameOfByteCPURegister(rm)
|
| - : NameOfCPURegister(rm));
|
| + Print("%s%c %s,", mnem, operand_size_code(),
|
| + byte_size_operand_ ? NameOfByteCPURegister(rm) : NameOfCPURegister(rm));
|
| if (op == 0xD2) {
|
| Print("cl");
|
| } else {
|
| @@ -735,8 +688,7 @@ int DisassemblerX64::ShiftInstruction(uint8_t* data) {
|
|
|
|
|
| int DisassemblerX64::PrintRightOperand(uint8_t* modrmp) {
|
| - return PrintRightOperandHelper(modrmp,
|
| - &DisassemblerX64::NameOfCPURegister);
|
| + return PrintRightOperandHelper(modrmp, &DisassemblerX64::NameOfCPURegister);
|
| }
|
|
|
|
|
| @@ -747,8 +699,7 @@ int DisassemblerX64::PrintRightByteOperand(uint8_t* modrmp) {
|
|
|
|
|
| int DisassemblerX64::PrintRightXMMOperand(uint8_t* modrmp) {
|
| - return PrintRightOperandHelper(modrmp,
|
| - &DisassemblerX64::NameOfXMMRegister);
|
| + return PrintRightOperandHelper(modrmp, &DisassemblerX64::NameOfXMMRegister);
|
| }
|
|
|
|
|
| @@ -761,9 +712,8 @@ int DisassemblerX64::PrintOperands(const char* mnem,
|
| int mod, regop, rm;
|
| get_modrm(modrm, &mod, ®op, &rm);
|
| int advance = 0;
|
| - const char* register_name =
|
| - byte_size_operand_ ? NameOfByteCPURegister(regop)
|
| - : NameOfCPURegister(regop);
|
| + const char* register_name = byte_size_operand_ ? NameOfByteCPURegister(regop)
|
| + : NameOfCPURegister(regop);
|
| switch (op_order) {
|
| case REG_OPER_OP_ORDER: {
|
| Print("%s%c %s,", mnem, operand_size_code(), register_name);
|
| @@ -842,12 +792,12 @@ int DisassemblerX64::SetCC(uint8_t* data) {
|
| int DisassemblerX64::FPUInstruction(uint8_t* data) {
|
| uint8_t escape_opcode = *data;
|
| ASSERT(0xD8 == (escape_opcode & 0xF8));
|
| - uint8_t modrm_byte = *(data+1);
|
| + uint8_t modrm_byte = *(data + 1);
|
|
|
| if (modrm_byte >= 0xC0) {
|
| return RegisterFPUInstruction(escape_opcode, modrm_byte);
|
| } else {
|
| - return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
|
| + return MemoryFPUInstruction(escape_opcode, modrm_byte, data + 1);
|
| }
|
| }
|
|
|
| @@ -858,38 +808,69 @@ int DisassemblerX64::MemoryFPUInstruction(int escape_opcode,
|
| const char* mnem = "?";
|
| int regop = (modrm_byte >> 3) & 0x7; // reg/op field of modrm byte.
|
| switch (escape_opcode) {
|
| - case 0xD9: switch (regop) {
|
| - case 0: mnem = "fld_s"; break;
|
| - case 3: mnem = "fstp_s"; break;
|
| - case 7: mnem = "fstcw"; break;
|
| - default: UnimplementedInstruction();
|
| + case 0xD9:
|
| + switch (regop) {
|
| + case 0:
|
| + mnem = "fld_s";
|
| + break;
|
| + case 3:
|
| + mnem = "fstp_s";
|
| + break;
|
| + case 7:
|
| + mnem = "fstcw";
|
| + break;
|
| + default:
|
| + UnimplementedInstruction();
|
| }
|
| break;
|
|
|
| - case 0xDB: switch (regop) {
|
| - case 0: mnem = "fild_s"; break;
|
| - case 1: mnem = "fisttp_s"; break;
|
| - case 2: mnem = "fist_s"; break;
|
| - case 3: mnem = "fistp_s"; break;
|
| - default: UnimplementedInstruction();
|
| + case 0xDB:
|
| + switch (regop) {
|
| + case 0:
|
| + mnem = "fild_s";
|
| + break;
|
| + case 1:
|
| + mnem = "fisttp_s";
|
| + break;
|
| + case 2:
|
| + mnem = "fist_s";
|
| + break;
|
| + case 3:
|
| + mnem = "fistp_s";
|
| + break;
|
| + default:
|
| + UnimplementedInstruction();
|
| }
|
| break;
|
|
|
| - case 0xDD: switch (regop) {
|
| - case 0: mnem = "fld_d"; break;
|
| - case 3: mnem = "fstp_d"; break;
|
| - default: UnimplementedInstruction();
|
| + case 0xDD:
|
| + switch (regop) {
|
| + case 0:
|
| + mnem = "fld_d";
|
| + break;
|
| + case 3:
|
| + mnem = "fstp_d";
|
| + break;
|
| + default:
|
| + UnimplementedInstruction();
|
| }
|
| break;
|
|
|
| - case 0xDF: switch (regop) {
|
| - case 5: mnem = "fild_d"; break;
|
| - case 7: mnem = "fistp_d"; break;
|
| - default: UnimplementedInstruction();
|
| + case 0xDF:
|
| + switch (regop) {
|
| + case 5:
|
| + mnem = "fild_d";
|
| + break;
|
| + case 7:
|
| + mnem = "fistp_d";
|
| + break;
|
| + default:
|
| + UnimplementedInstruction();
|
| }
|
| break;
|
|
|
| - default: UnimplementedInstruction();
|
| + default:
|
| + UnimplementedInstruction();
|
| }
|
| Print("%s ", mnem);
|
| int count = PrintRightOperand(modrm_start);
|
| @@ -918,24 +899,59 @@ int DisassemblerX64::RegisterFPUInstruction(int escape_opcode,
|
| break;
|
| default:
|
| switch (modrm_byte) {
|
| - case 0xE0: mnem = "fchs"; break;
|
| - case 0xE1: mnem = "fabs"; break;
|
| - case 0xE3: mnem = "fninit"; break;
|
| - case 0xE4: mnem = "ftst"; break;
|
| - case 0xE8: mnem = "fld1"; break;
|
| - case 0xEB: mnem = "fldpi"; break;
|
| - case 0xED: mnem = "fldln2"; break;
|
| - case 0xEE: mnem = "fldz"; break;
|
| - case 0xF0: mnem = "f2xm1"; break;
|
| - case 0xF1: mnem = "fyl2x"; break;
|
| - case 0xF2: mnem = "fptan"; break;
|
| - case 0xF5: mnem = "fprem1"; break;
|
| - case 0xF7: mnem = "fincstp"; break;
|
| - case 0xF8: mnem = "fprem"; break;
|
| - case 0xFD: mnem = "fscale"; break;
|
| - case 0xFE: mnem = "fsin"; break;
|
| - case 0xFF: mnem = "fcos"; break;
|
| - default: UnimplementedInstruction();
|
| + case 0xE0:
|
| + mnem = "fchs";
|
| + break;
|
| + case 0xE1:
|
| + mnem = "fabs";
|
| + break;
|
| + case 0xE3:
|
| + mnem = "fninit";
|
| + break;
|
| + case 0xE4:
|
| + mnem = "ftst";
|
| + break;
|
| + case 0xE8:
|
| + mnem = "fld1";
|
| + break;
|
| + case 0xEB:
|
| + mnem = "fldpi";
|
| + break;
|
| + case 0xED:
|
| + mnem = "fldln2";
|
| + break;
|
| + case 0xEE:
|
| + mnem = "fldz";
|
| + break;
|
| + case 0xF0:
|
| + mnem = "f2xm1";
|
| + break;
|
| + case 0xF1:
|
| + mnem = "fyl2x";
|
| + break;
|
| + case 0xF2:
|
| + mnem = "fptan";
|
| + break;
|
| + case 0xF5:
|
| + mnem = "fprem1";
|
| + break;
|
| + case 0xF7:
|
| + mnem = "fincstp";
|
| + break;
|
| + case 0xF8:
|
| + mnem = "fprem";
|
| + break;
|
| + case 0xFD:
|
| + mnem = "fscale";
|
| + break;
|
| + case 0xFE:
|
| + mnem = "fsin";
|
| + break;
|
| + case 0xFF:
|
| + mnem = "fcos";
|
| + break;
|
| + default:
|
| + UnimplementedInstruction();
|
| }
|
| }
|
| break;
|
| @@ -952,7 +968,7 @@ int DisassemblerX64::RegisterFPUInstruction(int escape_opcode,
|
| if ((modrm_byte & 0xF8) == 0xE8) {
|
| mnem = "fucomi";
|
| has_register = true;
|
| - } else if (modrm_byte == 0xE2) {
|
| + } else if (modrm_byte == 0xE2) {
|
| mnem = "fclex";
|
| } else {
|
| UnimplementedInstruction();
|
| @@ -962,34 +978,57 @@ int DisassemblerX64::RegisterFPUInstruction(int escape_opcode,
|
| case 0xDC:
|
| has_register = true;
|
| switch (modrm_byte & 0xF8) {
|
| - case 0xC0: mnem = "fadd"; break;
|
| - case 0xE8: mnem = "fsub"; break;
|
| - case 0xC8: mnem = "fmul"; break;
|
| - case 0xF8: mnem = "fdiv"; break;
|
| - default: UnimplementedInstruction();
|
| + case 0xC0:
|
| + mnem = "fadd";
|
| + break;
|
| + case 0xE8:
|
| + mnem = "fsub";
|
| + break;
|
| + case 0xC8:
|
| + mnem = "fmul";
|
| + break;
|
| + case 0xF8:
|
| + mnem = "fdiv";
|
| + break;
|
| + default:
|
| + UnimplementedInstruction();
|
| }
|
| break;
|
|
|
| case 0xDD:
|
| has_register = true;
|
| switch (modrm_byte & 0xF8) {
|
| - case 0xC0: mnem = "ffree"; break;
|
| - case 0xD8: mnem = "fstp"; break;
|
| - default: UnimplementedInstruction();
|
| + case 0xC0:
|
| + mnem = "ffree";
|
| + break;
|
| + case 0xD8:
|
| + mnem = "fstp";
|
| + break;
|
| + default:
|
| + UnimplementedInstruction();
|
| }
|
| break;
|
|
|
| case 0xDE:
|
| - if (modrm_byte == 0xD9) {
|
| + if (modrm_byte == 0xD9) {
|
| mnem = "fcompp";
|
| } else {
|
| has_register = true;
|
| switch (modrm_byte & 0xF8) {
|
| - case 0xC0: mnem = "faddp"; break;
|
| - case 0xE8: mnem = "fsubp"; break;
|
| - case 0xC8: mnem = "fmulp"; break;
|
| - case 0xF8: mnem = "fdivp"; break;
|
| - default: UnimplementedInstruction();
|
| + case 0xC0:
|
| + mnem = "faddp";
|
| + break;
|
| + case 0xE8:
|
| + mnem = "fsubp";
|
| + break;
|
| + case 0xC8:
|
| + mnem = "fmulp";
|
| + break;
|
| + case 0xF8:
|
| + mnem = "fdivp";
|
| + break;
|
| + default:
|
| + UnimplementedInstruction();
|
| }
|
| }
|
| break;
|
| @@ -1003,7 +1042,8 @@ int DisassemblerX64::RegisterFPUInstruction(int escape_opcode,
|
| }
|
| break;
|
|
|
| - default: UnimplementedInstruction();
|
| + default:
|
| + UnimplementedInstruction();
|
| }
|
|
|
| if (has_register) {
|
| @@ -1068,16 +1108,12 @@ bool DisassemblerX64::DecodeInstructionType(uint8_t** data) {
|
| break;
|
|
|
| case REGISTER_INSTR:
|
| - Print("%s%c %s",
|
| - idesc.mnem,
|
| - operand_size_code(),
|
| + Print("%s%c %s", idesc.mnem, operand_size_code(),
|
| NameOfCPURegister(base_reg(current & 0x07)));
|
| (*data)++;
|
| break;
|
| case PUSHPOP_INSTR:
|
| - Print("%s %s",
|
| - idesc.mnem,
|
| - NameOfCPURegister(base_reg(current & 0x07)));
|
| + Print("%s %s", idesc.mnem, NameOfCPURegister(base_reg(current & 0x07)));
|
| (*data)++;
|
| break;
|
| case MOVE_REG_INSTR: {
|
| @@ -1101,8 +1137,7 @@ bool DisassemblerX64::DecodeInstructionType(uint8_t** data) {
|
| default:
|
| UNREACHABLE();
|
| }
|
| - Print("mov%c %s,",
|
| - operand_size_code(),
|
| + Print("mov%c %s,", operand_size_code(),
|
| NameOfCPURegister(base_reg(current & 0x07)));
|
| PrintAddress(addr);
|
| break;
|
| @@ -1164,7 +1199,7 @@ int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) {
|
| current += 1;
|
| } else if (third_byte == 0x0b) {
|
| get_modrm(*current, &mod, ®op, &rm);
|
| - // roundsd xmm, xmm/m64, imm8
|
| + // roundsd xmm, xmm/m64, imm8
|
| Print("roundsd %s, ", NameOfCPURegister(regop));
|
| current += PrintRightOperand(current);
|
| Print(", %d", (*current) & 3);
|
| @@ -1193,17 +1228,13 @@ int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) {
|
| current += PrintRightXMMOperand(current);
|
| Print(", %s", NameOfXMMRegister(regop));
|
| } else if (opcode == 0x6E) {
|
| - Print("mov%c %s,",
|
| - rex_w() ? 'q' : 'd',
|
| - NameOfXMMRegister(regop));
|
| + Print("mov%c %s,", rex_w() ? 'q' : 'd', NameOfXMMRegister(regop));
|
| current += PrintRightOperand(current);
|
| } else if (opcode == 0x6F) {
|
| - Print("movdqa %s,",
|
| - NameOfXMMRegister(regop));
|
| + Print("movdqa %s,", NameOfXMMRegister(regop));
|
| current += PrintRightXMMOperand(current);
|
| } else if (opcode == 0x7E) {
|
| - Print("mov%c ",
|
| - rex_w() ? 'q' : 'd');
|
| + Print("mov%c ", rex_w() ? 'q' : 'd');
|
| current += PrintRightOperand(current);
|
| Print(", %s", NameOfXMMRegister(regop));
|
| } else if (opcode == 0x7F) {
|
| @@ -1225,9 +1256,9 @@ int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) {
|
| mnemonic = "unpckhpd";
|
| } else if (opcode == 0x54) {
|
| mnemonic = "andpd";
|
| - } else if (opcode == 0x56) {
|
| + } else if (opcode == 0x56) {
|
| mnemonic = "orpd";
|
| - } else if (opcode == 0x57) {
|
| + } else if (opcode == 0x57) {
|
| mnemonic = "xorpd";
|
| } else if (opcode == 0x2E) {
|
| mnemonic = "ucomisd";
|
| @@ -1286,15 +1317,13 @@ int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) {
|
| // Convert with truncation scalar double-precision FP to integer.
|
| int mod, regop, rm;
|
| get_modrm(*current, &mod, ®op, &rm);
|
| - Print("cvttsd2si%c %s,",
|
| - operand_size_code(), NameOfCPURegister(regop));
|
| + Print("cvttsd2si%c %s,", operand_size_code(), NameOfCPURegister(regop));
|
| current += PrintRightXMMOperand(current);
|
| } else if (opcode == 0x2D) {
|
| // CVTSD2SI: Convert scalar double-precision FP to integer.
|
| int mod, regop, rm;
|
| get_modrm(*current, &mod, ®op, &rm);
|
| - Print("cvtsd2si%c %s,",
|
| - operand_size_code(), NameOfCPURegister(regop));
|
| + Print("cvtsd2si%c %s,", operand_size_code(), NameOfCPURegister(regop));
|
| current += PrintRightXMMOperand(current);
|
| } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
|
| // XMM arithmetic. Mnemonic was retrieved at the start of this function.
|
| @@ -1330,8 +1359,7 @@ int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) {
|
| // Convert with truncation scalar single-precision FP to dword integer.
|
| int mod, regop, rm;
|
| get_modrm(*current, &mod, ®op, &rm);
|
| - Print("cvttss2si%c %s,",
|
| - operand_size_code(), NameOfCPURegister(regop));
|
| + Print("cvttss2si%c %s,", operand_size_code(), NameOfCPURegister(regop));
|
| current += PrintRightXMMOperand(current);
|
| } else if (opcode == 0x5A) {
|
| // CVTSS2SD:
|
| @@ -1418,24 +1446,59 @@ int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) {
|
| opcode == 0x5E || opcode == 0x5F) {
|
| const char* mnemonic = NULL;
|
| switch (opcode) {
|
| - case 0x12: mnemonic = "movhlps"; break;
|
| - case 0x14: mnemonic = "unpcklps"; break;
|
| - case 0x15: mnemonic = "unpckhps"; break;
|
| - case 0x16: mnemonic = "movlhps"; break;
|
| - case 0x51: mnemonic = "sqrtps"; break;
|
| - case 0x52: mnemonic = "rsqrtps"; break;
|
| - case 0x53: mnemonic = "rcpps"; break;
|
| - case 0x54: mnemonic = "andps"; break;
|
| - case 0x56: mnemonic = "orps"; break;
|
| - case 0x57: mnemonic = "xorps"; break;
|
| - case 0x58: mnemonic = "addps"; break;
|
| - case 0x59: mnemonic = "mulps"; break;
|
| - case 0x5A: mnemonic = "cvtsd2ss"; break;
|
| - case 0x5C: mnemonic = "subps"; break;
|
| - case 0x5D: mnemonic = "minps"; break;
|
| - case 0x5E: mnemonic = "divps"; break;
|
| - case 0x5F: mnemonic = "maxps"; break;
|
| - default: UNREACHABLE();
|
| + case 0x12:
|
| + mnemonic = "movhlps";
|
| + break;
|
| + case 0x14:
|
| + mnemonic = "unpcklps";
|
| + break;
|
| + case 0x15:
|
| + mnemonic = "unpckhps";
|
| + break;
|
| + case 0x16:
|
| + mnemonic = "movlhps";
|
| + break;
|
| + case 0x51:
|
| + mnemonic = "sqrtps";
|
| + break;
|
| + case 0x52:
|
| + mnemonic = "rsqrtps";
|
| + break;
|
| + case 0x53:
|
| + mnemonic = "rcpps";
|
| + break;
|
| + case 0x54:
|
| + mnemonic = "andps";
|
| + break;
|
| + case 0x56:
|
| + mnemonic = "orps";
|
| + break;
|
| + case 0x57:
|
| + mnemonic = "xorps";
|
| + break;
|
| + case 0x58:
|
| + mnemonic = "addps";
|
| + break;
|
| + case 0x59:
|
| + mnemonic = "mulps";
|
| + break;
|
| + case 0x5A:
|
| + mnemonic = "cvtsd2ss";
|
| + break;
|
| + case 0x5C:
|
| + mnemonic = "subps";
|
| + break;
|
| + case 0x5D:
|
| + mnemonic = "minps";
|
| + break;
|
| + case 0x5E:
|
| + mnemonic = "divps";
|
| + break;
|
| + case 0x5F:
|
| + mnemonic = "maxps";
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| }
|
| int mod, regop, rm;
|
| get_modrm(*current, &mod, ®op, &rm);
|
| @@ -1562,9 +1625,7 @@ int DisassemblerX64::InstructionDecode(uword pc) {
|
| break;
|
|
|
| case 0xC8:
|
| - Print("enter %d, %d",
|
| - *reinterpret_cast<uint16_t*>(data + 1),
|
| - data[3]);
|
| + Print("enter %d, %d", *reinterpret_cast<uint16_t*>(data + 1), data[3]);
|
| data += 4;
|
| break;
|
|
|
| @@ -1572,11 +1633,9 @@ int DisassemblerX64::InstructionDecode(uword pc) {
|
| case 0x6B: {
|
| int mod, regop, rm;
|
| get_modrm(*(data + 1), &mod, ®op, &rm);
|
| - int32_t imm = *data == 0x6B ? *(data + 2)
|
| - : *reinterpret_cast<int32_t*>(data + 2);
|
| - Print("imul%c %s,%s,",
|
| - operand_size_code(),
|
| - NameOfCPURegister(regop),
|
| + int32_t imm =
|
| + *data == 0x6B ? *(data + 2) : *reinterpret_cast<int32_t*>(data + 2);
|
| + Print("imul%c %s,%s,", operand_size_code(), NameOfCPURegister(regop),
|
| NameOfCPURegister(rm));
|
| PrintImmediateValue(imm);
|
| data += 2 + (*data == 0x6B ? 1 : 4);
|
| @@ -1600,8 +1659,7 @@ int DisassemblerX64::InstructionDecode(uword pc) {
|
| Print("pop ");
|
| data += PrintRightOperand(data);
|
| }
|
| - }
|
| - break;
|
| + } break;
|
|
|
| case 0xFF: {
|
| data++;
|
| @@ -1633,8 +1691,7 @@ int DisassemblerX64::InstructionDecode(uword pc) {
|
| Print("%s ", mnem);
|
| }
|
| data += PrintRightOperand(data);
|
| - }
|
| - break;
|
| + } break;
|
|
|
| case 0xC7: // imm32, fall through
|
| case 0xC6: // imm8
|
| @@ -1656,8 +1713,7 @@ int DisassemblerX64::InstructionDecode(uword pc) {
|
| PrintImmediateValue(imm);
|
| data += 4;
|
| }
|
| - }
|
| - break;
|
| + } break;
|
|
|
| case 0x80: {
|
| data++;
|
| @@ -1667,8 +1723,7 @@ int DisassemblerX64::InstructionDecode(uword pc) {
|
| Print(",");
|
| PrintImmediateValue(imm);
|
| data++;
|
| - }
|
| - break;
|
| + } break;
|
|
|
| case 0x88: // 8bit, fall through
|
| case 0x89: // 32bit
|
| @@ -1686,8 +1741,7 @@ int DisassemblerX64::InstructionDecode(uword pc) {
|
| data += PrintRightOperand(data);
|
| Print(",%s", NameOfCPURegister(regop));
|
| }
|
| - }
|
| - break;
|
| + } break;
|
|
|
| case 0x90:
|
| case 0x91:
|
| @@ -1704,8 +1758,7 @@ int DisassemblerX64::InstructionDecode(uword pc) {
|
| Print("xchg%c rax, %s", operand_size_code(), NameOfCPURegister(reg));
|
| }
|
| data++;
|
| - }
|
| - break;
|
| + } break;
|
| case 0xB0:
|
| case 0xB1:
|
| case 0xB2:
|
| @@ -1764,22 +1817,19 @@ int DisassemblerX64::InstructionDecode(uword pc) {
|
| case 0xA3:
|
| switch (operand_size()) {
|
| case DOUBLEWORD_SIZE: {
|
| - PrintAddress(
|
| - reinterpret_cast<uint8_t*>(
|
| - *reinterpret_cast<int32_t*>(data + 1)));
|
| + PrintAddress(reinterpret_cast<uint8_t*>(
|
| + *reinterpret_cast<int32_t*>(data + 1)));
|
| if (*data == 0xA1) { // Opcode 0xA1
|
| Print("movzxlq rax,(");
|
| - PrintAddress(
|
| - reinterpret_cast<uint8_t*>(
|
| - *reinterpret_cast<int32_t*>(data + 1)));
|
| + PrintAddress(reinterpret_cast<uint8_t*>(
|
| + *reinterpret_cast<int32_t*>(data + 1)));
|
| Print(")");
|
| } else { // Opcode 0xA3
|
| Print("movzxlq (");
|
| - PrintAddress(
|
| - reinterpret_cast<uint8_t*>(
|
| - *reinterpret_cast<int32_t*>(data + 1)));
|
| + PrintAddress(reinterpret_cast<uint8_t*>(
|
| + *reinterpret_cast<int32_t*>(data + 1)));
|
| Print("),rax");
|
| - }
|
| + }
|
| data += 5;
|
| break;
|
| }
|
| @@ -1878,10 +1928,14 @@ int DisassemblerX64::InstructionDecode(uword pc) {
|
| }
|
|
|
|
|
| -void Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
|
| - char* human_buffer, intptr_t human_size,
|
| - int* out_instr_len, const Code& code,
|
| - Object** object, uword pc) {
|
| +void Disassembler::DecodeInstruction(char* hex_buffer,
|
| + intptr_t hex_size,
|
| + char* human_buffer,
|
| + intptr_t human_size,
|
| + int* out_instr_len,
|
| + const Code& code,
|
| + Object** object,
|
| + uword pc) {
|
| ASSERT(hex_size > 0);
|
| ASSERT(human_size > 0);
|
| DisassemblerX64 decoder(human_buffer, human_size);
|
|
|