| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/disassembler.h" | 5 #include "vm/disassembler.h" |
| 6 | 6 |
| 7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 8 #if defined(TARGET_ARCH_IA32) | 8 #if defined(TARGET_ARCH_IA32) |
| 9 #include "platform/utils.h" | 9 #include "platform/utils.h" |
| 10 #include "vm/allocation.h" | 10 #include "vm/allocation.h" |
| 11 #include "vm/heap.h" | 11 #include "vm/heap.h" |
| 12 #include "vm/os.h" | 12 #include "vm/os.h" |
| 13 #include "vm/stack_frame.h" | 13 #include "vm/stack_frame.h" |
| 14 #include "vm/stub_code.h" | 14 #include "vm/stub_code.h" |
| 15 | 15 |
| 16 namespace dart { | 16 namespace dart { |
| 17 | 17 |
| 18 #ifndef PRODUCT | 18 #ifndef PRODUCT |
| 19 | 19 |
| 20 // Tables used for decoding of x86 instructions. | 20 // Tables used for decoding of x86 instructions. |
| 21 enum OperandOrder { UNSET_OP_ORDER = 0, REG_OPER_OP_ORDER, OPER_REG_OP_ORDER }; | 21 enum OperandOrder { UNSET_OP_ORDER = 0, REG_OPER_OP_ORDER, OPER_REG_OP_ORDER }; |
| 22 | 22 |
| 23 | |
| 24 struct ByteMnemonic { | 23 struct ByteMnemonic { |
| 25 int b; // -1 terminates, otherwise must be in range (0..255) | 24 int b; // -1 terminates, otherwise must be in range (0..255) |
| 26 const char* mnem; | 25 const char* mnem; |
| 27 OperandOrder op_order_; | 26 OperandOrder op_order_; |
| 28 }; | 27 }; |
| 29 | 28 |
| 30 | |
| 31 static ByteMnemonic two_operands_instr[] = { | 29 static ByteMnemonic two_operands_instr[] = { |
| 32 {0x01, "add", OPER_REG_OP_ORDER}, {0x03, "add", REG_OPER_OP_ORDER}, | 30 {0x01, "add", OPER_REG_OP_ORDER}, {0x03, "add", REG_OPER_OP_ORDER}, |
| 33 {0x09, "or", OPER_REG_OP_ORDER}, {0x0B, "or", REG_OPER_OP_ORDER}, | 31 {0x09, "or", OPER_REG_OP_ORDER}, {0x0B, "or", REG_OPER_OP_ORDER}, |
| 34 {0x11, "adc", OPER_REG_OP_ORDER}, {0x13, "adc", REG_OPER_OP_ORDER}, | 32 {0x11, "adc", OPER_REG_OP_ORDER}, {0x13, "adc", REG_OPER_OP_ORDER}, |
| 35 {0x19, "sbb", OPER_REG_OP_ORDER}, {0x1B, "sbb", REG_OPER_OP_ORDER}, | 33 {0x19, "sbb", OPER_REG_OP_ORDER}, {0x1B, "sbb", REG_OPER_OP_ORDER}, |
| 36 {0x21, "and", OPER_REG_OP_ORDER}, {0x23, "and", REG_OPER_OP_ORDER}, | 34 {0x21, "and", OPER_REG_OP_ORDER}, {0x23, "and", REG_OPER_OP_ORDER}, |
| 37 {0x29, "sub", OPER_REG_OP_ORDER}, {0x2B, "sub", REG_OPER_OP_ORDER}, | 35 {0x29, "sub", OPER_REG_OP_ORDER}, {0x2B, "sub", REG_OPER_OP_ORDER}, |
| 38 {0x31, "xor", OPER_REG_OP_ORDER}, {0x33, "xor", REG_OPER_OP_ORDER}, | 36 {0x31, "xor", OPER_REG_OP_ORDER}, {0x33, "xor", REG_OPER_OP_ORDER}, |
| 39 {0x39, "cmp", OPER_REG_OP_ORDER}, {0x3B, "cmp", REG_OPER_OP_ORDER}, | 37 {0x39, "cmp", OPER_REG_OP_ORDER}, {0x3B, "cmp", REG_OPER_OP_ORDER}, |
| 40 {0x85, "test", REG_OPER_OP_ORDER}, {0x87, "xchg", REG_OPER_OP_ORDER}, | 38 {0x85, "test", REG_OPER_OP_ORDER}, {0x87, "xchg", REG_OPER_OP_ORDER}, |
| 41 {0x8A, "mov_b", REG_OPER_OP_ORDER}, {0x8B, "mov", REG_OPER_OP_ORDER}, | 39 {0x8A, "mov_b", REG_OPER_OP_ORDER}, {0x8B, "mov", REG_OPER_OP_ORDER}, |
| 42 {0x8D, "lea", REG_OPER_OP_ORDER}, {-1, "", UNSET_OP_ORDER}}; | 40 {0x8D, "lea", REG_OPER_OP_ORDER}, {-1, "", UNSET_OP_ORDER}}; |
| 43 | 41 |
| 44 | |
| 45 static ByteMnemonic zero_operands_instr[] = { | 42 static ByteMnemonic zero_operands_instr[] = { |
| 46 {0xC3, "ret", UNSET_OP_ORDER}, {0xC9, "leave", UNSET_OP_ORDER}, | 43 {0xC3, "ret", UNSET_OP_ORDER}, {0xC9, "leave", UNSET_OP_ORDER}, |
| 47 {0x90, "nop", UNSET_OP_ORDER}, {0xF4, "hlt", UNSET_OP_ORDER}, | 44 {0x90, "nop", UNSET_OP_ORDER}, {0xF4, "hlt", UNSET_OP_ORDER}, |
| 48 {0xCC, "int3", UNSET_OP_ORDER}, {0x60, "pushad", UNSET_OP_ORDER}, | 45 {0xCC, "int3", UNSET_OP_ORDER}, {0x60, "pushad", UNSET_OP_ORDER}, |
| 49 {0x61, "popad", UNSET_OP_ORDER}, {0x9C, "pushfd", UNSET_OP_ORDER}, | 46 {0x61, "popad", UNSET_OP_ORDER}, {0x9C, "pushfd", UNSET_OP_ORDER}, |
| 50 {0x9D, "popfd", UNSET_OP_ORDER}, {0x9E, "sahf", UNSET_OP_ORDER}, | 47 {0x9D, "popfd", UNSET_OP_ORDER}, {0x9E, "sahf", UNSET_OP_ORDER}, |
| 51 {0x99, "cdq", UNSET_OP_ORDER}, {0x9B, "fwait", UNSET_OP_ORDER}, | 48 {0x99, "cdq", UNSET_OP_ORDER}, {0x9B, "fwait", UNSET_OP_ORDER}, |
| 52 {-1, "", UNSET_OP_ORDER}}; | 49 {-1, "", UNSET_OP_ORDER}}; |
| 53 | 50 |
| 54 | |
| 55 static ByteMnemonic call_jump_instr[] = {{0xE8, "call", UNSET_OP_ORDER}, | 51 static ByteMnemonic call_jump_instr[] = {{0xE8, "call", UNSET_OP_ORDER}, |
| 56 {0xE9, "jmp", UNSET_OP_ORDER}, | 52 {0xE9, "jmp", UNSET_OP_ORDER}, |
| 57 {-1, "", UNSET_OP_ORDER}}; | 53 {-1, "", UNSET_OP_ORDER}}; |
| 58 | 54 |
| 59 | |
| 60 static ByteMnemonic short_immediate_instr[] = { | 55 static ByteMnemonic short_immediate_instr[] = { |
| 61 {0x05, "add", UNSET_OP_ORDER}, {0x0D, "or", UNSET_OP_ORDER}, | 56 {0x05, "add", UNSET_OP_ORDER}, {0x0D, "or", UNSET_OP_ORDER}, |
| 62 {0x15, "adc", UNSET_OP_ORDER}, {0x25, "and", UNSET_OP_ORDER}, | 57 {0x15, "adc", UNSET_OP_ORDER}, {0x25, "and", UNSET_OP_ORDER}, |
| 63 {0x2D, "sub", UNSET_OP_ORDER}, {0x35, "xor", UNSET_OP_ORDER}, | 58 {0x2D, "sub", UNSET_OP_ORDER}, {0x35, "xor", UNSET_OP_ORDER}, |
| 64 {0x3D, "cmp", UNSET_OP_ORDER}, {-1, "", UNSET_OP_ORDER}}; | 59 {0x3D, "cmp", UNSET_OP_ORDER}, {-1, "", UNSET_OP_ORDER}}; |
| 65 | 60 |
| 66 | |
| 67 static const char* jump_conditional_mnem[] = { | 61 static const char* jump_conditional_mnem[] = { |
| 68 /*0*/ "jo", "jno", "jc", "jnc", | 62 /*0*/ "jo", "jno", "jc", "jnc", |
| 69 /*4*/ "jz", "jnz", "jna", "ja", | 63 /*4*/ "jz", "jnz", "jna", "ja", |
| 70 /*8*/ "js", "jns", "jpe", "jpo", | 64 /*8*/ "js", "jns", "jpe", "jpo", |
| 71 /*12*/ "jl", "jnl", "jng", "jg"}; | 65 /*12*/ "jl", "jnl", "jng", "jg"}; |
| 72 | 66 |
| 73 | |
| 74 static const char* set_conditional_mnem[] = { | 67 static const char* set_conditional_mnem[] = { |
| 75 /*0*/ "seto", "setno", "setc", "setnc", | 68 /*0*/ "seto", "setno", "setc", "setnc", |
| 76 /*4*/ "setz", "setnz", "setna", "seta", | 69 /*4*/ "setz", "setnz", "setna", "seta", |
| 77 /*8*/ "sets", "setns", "setpe", "setpo", | 70 /*8*/ "sets", "setns", "setpe", "setpo", |
| 78 /*12*/ "setl", "setnl", "setng", "setg"}; | 71 /*12*/ "setl", "setnl", "setng", "setg"}; |
| 79 | 72 |
| 80 | |
| 81 static const char* conditional_move_mnem[] = { | 73 static const char* conditional_move_mnem[] = { |
| 82 /*0*/ "cmovo", "cmovno", "cmovc", "cmovnc", | 74 /*0*/ "cmovo", "cmovno", "cmovc", "cmovnc", |
| 83 /*4*/ "cmovz", "cmovnz", "cmovna", "cmova", | 75 /*4*/ "cmovz", "cmovnz", "cmovna", "cmova", |
| 84 /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo", | 76 /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo", |
| 85 /*12*/ "cmovl", "cmovnl", "cmovng", "cmovg"}; | 77 /*12*/ "cmovl", "cmovnl", "cmovng", "cmovg"}; |
| 86 | 78 |
| 87 | |
| 88 enum InstructionType { | 79 enum InstructionType { |
| 89 NO_INSTR, | 80 NO_INSTR, |
| 90 ZERO_OPERANDS_INSTR, | 81 ZERO_OPERANDS_INSTR, |
| 91 TWO_OPERANDS_INSTR, | 82 TWO_OPERANDS_INSTR, |
| 92 JUMP_CONDITIONAL_SHORT_INSTR, | 83 JUMP_CONDITIONAL_SHORT_INSTR, |
| 93 REGISTER_INSTR, | 84 REGISTER_INSTR, |
| 94 MOVE_REG_INSTR, | 85 MOVE_REG_INSTR, |
| 95 CALL_JUMP_INSTR, | 86 CALL_JUMP_INSTR, |
| 96 SHORT_IMMEDIATE_INSTR | 87 SHORT_IMMEDIATE_INSTR |
| 97 }; | 88 }; |
| 98 | 89 |
| 99 | |
| 100 struct InstructionDesc { | 90 struct InstructionDesc { |
| 101 const char* mnem; | 91 const char* mnem; |
| 102 InstructionType type; | 92 InstructionType type; |
| 103 OperandOrder op_order_; | 93 OperandOrder op_order_; |
| 104 }; | 94 }; |
| 105 | 95 |
| 106 | |
| 107 class InstructionTable : public ValueObject { | 96 class InstructionTable : public ValueObject { |
| 108 public: | 97 public: |
| 109 InstructionTable(); | 98 InstructionTable(); |
| 110 const InstructionDesc& Get(uint8_t x) const { return instructions_[x]; } | 99 const InstructionDesc& Get(uint8_t x) const { return instructions_[x]; } |
| 111 | 100 |
| 112 private: | 101 private: |
| 113 InstructionDesc instructions_[256]; | 102 InstructionDesc instructions_[256]; |
| 114 void Clear(); | 103 void Clear(); |
| 115 void Init(); | 104 void Init(); |
| 116 void CopyTable(ByteMnemonic bm[], InstructionType type); | 105 void CopyTable(ByteMnemonic bm[], InstructionType type); |
| 117 void SetTableRange(InstructionType type, | 106 void SetTableRange(InstructionType type, |
| 118 uint8_t start, | 107 uint8_t start, |
| 119 uint8_t end, | 108 uint8_t end, |
| 120 const char* mnem); | 109 const char* mnem); |
| 121 void AddJumpConditionalShort(); | 110 void AddJumpConditionalShort(); |
| 122 | 111 |
| 123 DISALLOW_COPY_AND_ASSIGN(InstructionTable); | 112 DISALLOW_COPY_AND_ASSIGN(InstructionTable); |
| 124 }; | 113 }; |
| 125 | 114 |
| 126 | |
| 127 InstructionTable::InstructionTable() { | 115 InstructionTable::InstructionTable() { |
| 128 Clear(); | 116 Clear(); |
| 129 Init(); | 117 Init(); |
| 130 } | 118 } |
| 131 | 119 |
| 132 | |
| 133 void InstructionTable::Clear() { | 120 void InstructionTable::Clear() { |
| 134 for (int i = 0; i < 256; i++) { | 121 for (int i = 0; i < 256; i++) { |
| 135 instructions_[i].mnem = ""; | 122 instructions_[i].mnem = ""; |
| 136 instructions_[i].type = NO_INSTR; | 123 instructions_[i].type = NO_INSTR; |
| 137 instructions_[i].op_order_ = UNSET_OP_ORDER; | 124 instructions_[i].op_order_ = UNSET_OP_ORDER; |
| 138 } | 125 } |
| 139 } | 126 } |
| 140 | 127 |
| 141 | |
| 142 void InstructionTable::Init() { | 128 void InstructionTable::Init() { |
| 143 CopyTable(two_operands_instr, TWO_OPERANDS_INSTR); | 129 CopyTable(two_operands_instr, TWO_OPERANDS_INSTR); |
| 144 CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR); | 130 CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR); |
| 145 CopyTable(call_jump_instr, CALL_JUMP_INSTR); | 131 CopyTable(call_jump_instr, CALL_JUMP_INSTR); |
| 146 CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR); | 132 CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR); |
| 147 AddJumpConditionalShort(); | 133 AddJumpConditionalShort(); |
| 148 SetTableRange(REGISTER_INSTR, 0x40, 0x47, "inc"); | 134 SetTableRange(REGISTER_INSTR, 0x40, 0x47, "inc"); |
| 149 SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec"); | 135 SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec"); |
| 150 SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push"); | 136 SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push"); |
| 151 SetTableRange(REGISTER_INSTR, 0x58, 0x5F, "pop"); | 137 SetTableRange(REGISTER_INSTR, 0x58, 0x5F, "pop"); |
| 152 SetTableRange(REGISTER_INSTR, 0x91, 0x97, "xchg eax,"); // 0x90 is nop. | 138 SetTableRange(REGISTER_INSTR, 0x91, 0x97, "xchg eax,"); // 0x90 is nop. |
| 153 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov"); | 139 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov"); |
| 154 } | 140 } |
| 155 | 141 |
| 156 | |
| 157 void InstructionTable::CopyTable(ByteMnemonic bm[], InstructionType type) { | 142 void InstructionTable::CopyTable(ByteMnemonic bm[], InstructionType type) { |
| 158 for (int i = 0; bm[i].b >= 0; i++) { | 143 for (int i = 0; bm[i].b >= 0; i++) { |
| 159 InstructionDesc* id = &instructions_[bm[i].b]; | 144 InstructionDesc* id = &instructions_[bm[i].b]; |
| 160 id->mnem = bm[i].mnem; | 145 id->mnem = bm[i].mnem; |
| 161 id->op_order_ = bm[i].op_order_; | 146 id->op_order_ = bm[i].op_order_; |
| 162 ASSERT(id->type == NO_INSTR); // Information already entered | 147 ASSERT(id->type == NO_INSTR); // Information already entered |
| 163 id->type = type; | 148 id->type = type; |
| 164 } | 149 } |
| 165 } | 150 } |
| 166 | 151 |
| 167 | |
| 168 void InstructionTable::SetTableRange(InstructionType type, | 152 void InstructionTable::SetTableRange(InstructionType type, |
| 169 uint8_t start, | 153 uint8_t start, |
| 170 uint8_t end, | 154 uint8_t end, |
| 171 const char* mnem) { | 155 const char* mnem) { |
| 172 for (uint8_t b = start; b <= end; b++) { | 156 for (uint8_t b = start; b <= end; b++) { |
| 173 InstructionDesc* id = &instructions_[b]; | 157 InstructionDesc* id = &instructions_[b]; |
| 174 ASSERT(id->type == NO_INSTR); // Information already entered | 158 ASSERT(id->type == NO_INSTR); // Information already entered |
| 175 id->mnem = mnem; | 159 id->mnem = mnem; |
| 176 id->type = type; | 160 id->type = type; |
| 177 } | 161 } |
| 178 } | 162 } |
| 179 | 163 |
| 180 | |
| 181 void InstructionTable::AddJumpConditionalShort() { | 164 void InstructionTable::AddJumpConditionalShort() { |
| 182 for (uint8_t b = 0x70; b <= 0x7F; b++) { | 165 for (uint8_t b = 0x70; b <= 0x7F; b++) { |
| 183 InstructionDesc* id = &instructions_[b]; | 166 InstructionDesc* id = &instructions_[b]; |
| 184 ASSERT(id->type == NO_INSTR); // Information already entered | 167 ASSERT(id->type == NO_INSTR); // Information already entered |
| 185 id->mnem = jump_conditional_mnem[b & 0x0F]; | 168 id->mnem = jump_conditional_mnem[b & 0x0F]; |
| 186 id->type = JUMP_CONDITIONAL_SHORT_INSTR; | 169 id->type = JUMP_CONDITIONAL_SHORT_INSTR; |
| 187 } | 170 } |
| 188 } | 171 } |
| 189 | 172 |
| 190 | |
| 191 static InstructionTable instruction_table; | 173 static InstructionTable instruction_table; |
| 192 | 174 |
| 193 | |
| 194 // Mnemonics for instructions 0xF0 byte. | 175 // Mnemonics for instructions 0xF0 byte. |
| 195 // Returns NULL if the instruction is not handled here. | 176 // Returns NULL if the instruction is not handled here. |
| 196 static const char* F0Mnem(uint8_t f0byte) { | 177 static const char* F0Mnem(uint8_t f0byte) { |
| 197 switch (f0byte) { | 178 switch (f0byte) { |
| 198 case 0x12: | 179 case 0x12: |
| 199 return "movhlps"; | 180 return "movhlps"; |
| 200 case 0x14: | 181 case 0x14: |
| 201 return "unpcklps"; | 182 return "unpcklps"; |
| 202 case 0x15: | 183 case 0x15: |
| 203 return "unpckhps"; | 184 return "unpckhps"; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 if (data == 0x59) mnemonic = "mulpd "; | 261 if (data == 0x59) mnemonic = "mulpd "; |
| 281 if (data == 0x5E) mnemonic = "divpd "; | 262 if (data == 0x5E) mnemonic = "divpd "; |
| 282 if (data == 0x5D) mnemonic = "minpd "; | 263 if (data == 0x5D) mnemonic = "minpd "; |
| 283 if (data == 0x5F) mnemonic = "maxpd "; | 264 if (data == 0x5F) mnemonic = "maxpd "; |
| 284 if (data == 0x51) mnemonic = "sqrtpd "; | 265 if (data == 0x51) mnemonic = "sqrtpd "; |
| 285 if (data == 0x5A) mnemonic = "cvtpd2ps "; | 266 if (data == 0x5A) mnemonic = "cvtpd2ps "; |
| 286 ASSERT(mnemonic != NULL); | 267 ASSERT(mnemonic != NULL); |
| 287 return mnemonic; | 268 return mnemonic; |
| 288 } | 269 } |
| 289 | 270 |
| 290 | |
| 291 static bool IsTwoXmmRegInstruction(uint8_t f0byte) { | 271 static bool IsTwoXmmRegInstruction(uint8_t f0byte) { |
| 292 return f0byte == 0x28 || f0byte == 0x11 || f0byte == 0x12 || f0byte == 0x14 || | 272 return f0byte == 0x28 || f0byte == 0x11 || f0byte == 0x12 || f0byte == 0x14 || |
| 293 f0byte == 0x15 || f0byte == 0x16 || f0byte == 0x51 || f0byte == 0x52 || | 273 f0byte == 0x15 || f0byte == 0x16 || f0byte == 0x51 || f0byte == 0x52 || |
| 294 f0byte == 0x53 || f0byte == 0x54 || f0byte == 0x56 || f0byte == 0x58 || | 274 f0byte == 0x53 || f0byte == 0x54 || f0byte == 0x56 || f0byte == 0x58 || |
| 295 f0byte == 0x59 || f0byte == 0x5C || f0byte == 0x5D || f0byte == 0x5E || | 275 f0byte == 0x59 || f0byte == 0x5C || f0byte == 0x5D || f0byte == 0x5E || |
| 296 f0byte == 0x5F || f0byte == 0x5A; | 276 f0byte == 0x5F || f0byte == 0x5A; |
| 297 } | 277 } |
| 298 | 278 |
| 299 | |
| 300 // The implementation of x86 decoding based on the above tables. | 279 // The implementation of x86 decoding based on the above tables. |
| 301 class X86Decoder : public ValueObject { | 280 class X86Decoder : public ValueObject { |
| 302 public: | 281 public: |
| 303 X86Decoder(char* buffer, intptr_t buffer_size) | 282 X86Decoder(char* buffer, intptr_t buffer_size) |
| 304 : buffer_(buffer), buffer_size_(buffer_size), buffer_pos_(0) { | 283 : buffer_(buffer), buffer_size_(buffer_size), buffer_pos_(0) { |
| 305 buffer_[buffer_pos_] = '\0'; | 284 buffer_[buffer_pos_] = '\0'; |
| 306 } | 285 } |
| 307 | 286 |
| 308 ~X86Decoder() {} | 287 ~X86Decoder() {} |
| 309 | 288 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 *regop = (data & 0x38) >> 3; | 351 *regop = (data & 0x38) >> 3; |
| 373 *rm = data & 7; | 352 *rm = data & 7; |
| 374 } | 353 } |
| 375 | 354 |
| 376 static void GetSib(uint8_t data, int* scale, int* index, int* base) { | 355 static void GetSib(uint8_t data, int* scale, int* index, int* base) { |
| 377 *scale = (data >> 6) & 3; | 356 *scale = (data >> 6) & 3; |
| 378 *index = (data >> 3) & 7; | 357 *index = (data >> 3) & 7; |
| 379 *base = data & 7; | 358 *base = data & 7; |
| 380 } | 359 } |
| 381 | 360 |
| 382 | |
| 383 // Convenience functions. | 361 // Convenience functions. |
| 384 char* get_buffer() const { return buffer_; } | 362 char* get_buffer() const { return buffer_; } |
| 385 char* current_position_in_buffer() { return buffer_ + buffer_pos_; } | 363 char* current_position_in_buffer() { return buffer_ + buffer_pos_; } |
| 386 intptr_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; } | 364 intptr_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; } |
| 387 | 365 |
| 388 char* buffer_; // Decode instructions into this buffer. | 366 char* buffer_; // Decode instructions into this buffer. |
| 389 intptr_t buffer_size_; // The size of the buffer_. | 367 intptr_t buffer_size_; // The size of the buffer_. |
| 390 intptr_t buffer_pos_; // Current character position in the buffer_. | 368 intptr_t buffer_pos_; // Current character position in the buffer_. |
| 391 | 369 |
| 392 DISALLOW_COPY_AND_ASSIGN(X86Decoder); | 370 DISALLOW_COPY_AND_ASSIGN(X86Decoder); |
| 393 }; | 371 }; |
| 394 | 372 |
| 395 | |
| 396 void X86Decoder::PrintInt(int value) { | 373 void X86Decoder::PrintInt(int value) { |
| 397 char int_buffer[16]; | 374 char int_buffer[16]; |
| 398 OS::SNPrint(int_buffer, sizeof(int_buffer), "%#x", value); | 375 OS::SNPrint(int_buffer, sizeof(int_buffer), "%#x", value); |
| 399 Print(int_buffer); | 376 Print(int_buffer); |
| 400 } | 377 } |
| 401 | 378 |
| 402 | |
| 403 // Append the int value (printed in hex) to the output buffer. | 379 // Append the int value (printed in hex) to the output buffer. |
| 404 void X86Decoder::PrintHex(int value, bool signed_value) { | 380 void X86Decoder::PrintHex(int value, bool signed_value) { |
| 405 char hex_buffer[16]; | 381 char hex_buffer[16]; |
| 406 if (signed_value && value < 0) { | 382 if (signed_value && value < 0) { |
| 407 OS::SNPrint(hex_buffer, sizeof(hex_buffer), "-%#x", -value); | 383 OS::SNPrint(hex_buffer, sizeof(hex_buffer), "-%#x", -value); |
| 408 } else { | 384 } else { |
| 409 OS::SNPrint(hex_buffer, sizeof(hex_buffer), "%#x", value); | 385 OS::SNPrint(hex_buffer, sizeof(hex_buffer), "%#x", value); |
| 410 } | 386 } |
| 411 Print(hex_buffer); | 387 Print(hex_buffer); |
| 412 } | 388 } |
| 413 | 389 |
| 414 | |
| 415 // Append the str to the output buffer. | 390 // Append the str to the output buffer. |
| 416 void X86Decoder::Print(const char* str) { | 391 void X86Decoder::Print(const char* str) { |
| 417 char cur = *str++; | 392 char cur = *str++; |
| 418 while (cur != '\0' && (buffer_pos_ < (buffer_size_ - 1))) { | 393 while (cur != '\0' && (buffer_pos_ < (buffer_size_ - 1))) { |
| 419 buffer_[buffer_pos_++] = cur; | 394 buffer_[buffer_pos_++] = cur; |
| 420 cur = *str++; | 395 cur = *str++; |
| 421 } | 396 } |
| 422 buffer_[buffer_pos_] = '\0'; | 397 buffer_[buffer_pos_] = '\0'; |
| 423 } | 398 } |
| 424 | 399 |
| 425 | |
| 426 static const int kMaxCPURegisters = 8; | 400 static const int kMaxCPURegisters = 8; |
| 427 static const char* cpu_regs[kMaxCPURegisters] = {"eax", "ecx", "edx", "ebx", | 401 static const char* cpu_regs[kMaxCPURegisters] = {"eax", "ecx", "edx", "ebx", |
| 428 "esp", "ebp", "esi", "edi"}; | 402 "esp", "ebp", "esi", "edi"}; |
| 429 | 403 |
| 430 static const int kMaxByteCPURegisters = 8; | 404 static const int kMaxByteCPURegisters = 8; |
| 431 static const char* byte_cpu_regs[kMaxByteCPURegisters] = { | 405 static const char* byte_cpu_regs[kMaxByteCPURegisters] = { |
| 432 "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"}; | 406 "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"}; |
| 433 | 407 |
| 434 static const int kMaxXmmRegisters = 8; | 408 static const int kMaxXmmRegisters = 8; |
| 435 static const char* xmm_regs[kMaxXmmRegisters] = { | 409 static const char* xmm_regs[kMaxXmmRegisters] = { |
| 436 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"}; | 410 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"}; |
| 437 | 411 |
| 438 void X86Decoder::PrintCPURegister(int reg) { | 412 void X86Decoder::PrintCPURegister(int reg) { |
| 439 ASSERT(0 <= reg); | 413 ASSERT(0 <= reg); |
| 440 ASSERT(reg < kMaxCPURegisters); | 414 ASSERT(reg < kMaxCPURegisters); |
| 441 Print(cpu_regs[reg]); | 415 Print(cpu_regs[reg]); |
| 442 } | 416 } |
| 443 | 417 |
| 444 | |
| 445 void X86Decoder::PrintCPUByteRegister(int reg) { | 418 void X86Decoder::PrintCPUByteRegister(int reg) { |
| 446 ASSERT(0 <= reg); | 419 ASSERT(0 <= reg); |
| 447 ASSERT(reg < kMaxByteCPURegisters); | 420 ASSERT(reg < kMaxByteCPURegisters); |
| 448 Print(byte_cpu_regs[reg]); | 421 Print(byte_cpu_regs[reg]); |
| 449 } | 422 } |
| 450 | 423 |
| 451 | |
| 452 void X86Decoder::PrintXmmRegister(int reg) { | 424 void X86Decoder::PrintXmmRegister(int reg) { |
| 453 ASSERT(0 <= reg); | 425 ASSERT(0 <= reg); |
| 454 ASSERT(reg < kMaxXmmRegisters); | 426 ASSERT(reg < kMaxXmmRegisters); |
| 455 Print(xmm_regs[reg]); | 427 Print(xmm_regs[reg]); |
| 456 } | 428 } |
| 457 | 429 |
| 458 void X86Decoder::PrintXmmComparison(int comparison) { | 430 void X86Decoder::PrintXmmComparison(int comparison) { |
| 459 ASSERT(0 <= comparison); | 431 ASSERT(0 <= comparison); |
| 460 ASSERT(comparison < 8); | 432 ASSERT(comparison < 8); |
| 461 static const char* comparisons[8] = { | 433 static const char* comparisons[8] = { |
| 462 "eq", "lt", "le", "unordered", "not eq", "not lt", "not le", "ordered"}; | 434 "eq", "lt", "le", "unordered", "not eq", "not lt", "not le", "ordered"}; |
| 463 Print(comparisons[comparison]); | 435 Print(comparisons[comparison]); |
| 464 } | 436 } |
| 465 | 437 |
| 466 | |
| 467 void X86Decoder::PrintAddress(uword addr) { | 438 void X86Decoder::PrintAddress(uword addr) { |
| 468 char addr_buffer[32]; | 439 char addr_buffer[32]; |
| 469 OS::SNPrint(addr_buffer, sizeof(addr_buffer), "%#" Px "", addr); | 440 OS::SNPrint(addr_buffer, sizeof(addr_buffer), "%#" Px "", addr); |
| 470 Print(addr_buffer); | 441 Print(addr_buffer); |
| 471 | 442 |
| 472 // Try to print as stub name. | 443 // Try to print as stub name. |
| 473 const char* name_of_stub = StubCode::NameOfStub(addr); | 444 const char* name_of_stub = StubCode::NameOfStub(addr); |
| 474 if (name_of_stub != NULL) { | 445 if (name_of_stub != NULL) { |
| 475 Print(" [stub: "); | 446 Print(" [stub: "); |
| 476 Print(name_of_stub); | 447 Print(name_of_stub); |
| 477 Print("]"); | 448 Print("]"); |
| 478 } | 449 } |
| 479 } | 450 } |
| 480 | 451 |
| 481 | |
| 482 int X86Decoder::PrintRightOperandHelper(uint8_t* modrmp, | 452 int X86Decoder::PrintRightOperandHelper(uint8_t* modrmp, |
| 483 RegisterNamePrinter register_printer) { | 453 RegisterNamePrinter register_printer) { |
| 484 int mod, regop, rm; | 454 int mod, regop, rm; |
| 485 GetModRm(*modrmp, &mod, ®op, &rm); | 455 GetModRm(*modrmp, &mod, ®op, &rm); |
| 486 switch (mod) { | 456 switch (mod) { |
| 487 case 0: | 457 case 0: |
| 488 if (rm == ebp) { | 458 if (rm == ebp) { |
| 489 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1); | 459 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1); |
| 490 Print("["); | 460 Print("["); |
| 491 PrintHex(disp); | 461 PrintHex(disp); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 case 3: | 562 case 3: |
| 593 (this->*register_printer)(rm); | 563 (this->*register_printer)(rm); |
| 594 return 1; | 564 return 1; |
| 595 default: | 565 default: |
| 596 UNIMPLEMENTED(); | 566 UNIMPLEMENTED(); |
| 597 return 1; | 567 return 1; |
| 598 } | 568 } |
| 599 UNREACHABLE(); | 569 UNREACHABLE(); |
| 600 } | 570 } |
| 601 | 571 |
| 602 | |
| 603 int X86Decoder::PrintRightOperand(uint8_t* modrmp) { | 572 int X86Decoder::PrintRightOperand(uint8_t* modrmp) { |
| 604 return PrintRightOperandHelper(modrmp, &X86Decoder::PrintCPURegister); | 573 return PrintRightOperandHelper(modrmp, &X86Decoder::PrintCPURegister); |
| 605 } | 574 } |
| 606 | 575 |
| 607 | |
| 608 int X86Decoder::PrintRightXmmOperand(uint8_t* modrmp) { | 576 int X86Decoder::PrintRightXmmOperand(uint8_t* modrmp) { |
| 609 return PrintRightOperandHelper(modrmp, &X86Decoder::PrintXmmRegister); | 577 return PrintRightOperandHelper(modrmp, &X86Decoder::PrintXmmRegister); |
| 610 } | 578 } |
| 611 | 579 |
| 612 | |
| 613 int X86Decoder::PrintRightByteOperand(uint8_t* modrmp) { | 580 int X86Decoder::PrintRightByteOperand(uint8_t* modrmp) { |
| 614 return PrintRightOperandHelper(modrmp, &X86Decoder::PrintCPUByteRegister); | 581 return PrintRightOperandHelper(modrmp, &X86Decoder::PrintCPUByteRegister); |
| 615 } | 582 } |
| 616 | 583 |
| 617 | |
| 618 int X86Decoder::PrintOperands(const char* mnem, | 584 int X86Decoder::PrintOperands(const char* mnem, |
| 619 OperandOrder op_order, | 585 OperandOrder op_order, |
| 620 uint8_t* data) { | 586 uint8_t* data) { |
| 621 uint8_t modrm = *data; | 587 uint8_t modrm = *data; |
| 622 int mod, regop, rm; | 588 int mod, regop, rm; |
| 623 GetModRm(modrm, &mod, ®op, &rm); | 589 GetModRm(modrm, &mod, ®op, &rm); |
| 624 int advance = 0; | 590 int advance = 0; |
| 625 switch (op_order) { | 591 switch (op_order) { |
| 626 case REG_OPER_OP_ORDER: { | 592 case REG_OPER_OP_ORDER: { |
| 627 Print(mnem); | 593 Print(mnem); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 639 PrintCPURegister(regop); | 605 PrintCPURegister(regop); |
| 640 break; | 606 break; |
| 641 } | 607 } |
| 642 default: | 608 default: |
| 643 UNREACHABLE(); | 609 UNREACHABLE(); |
| 644 break; | 610 break; |
| 645 } | 611 } |
| 646 return advance; | 612 return advance; |
| 647 } | 613 } |
| 648 | 614 |
| 649 | |
| 650 int X86Decoder::PrintImmediateOp(uint8_t* data, bool size_override) { | 615 int X86Decoder::PrintImmediateOp(uint8_t* data, bool size_override) { |
| 651 bool sign_extension_bit = (*data & 0x02) != 0; | 616 bool sign_extension_bit = (*data & 0x02) != 0; |
| 652 uint8_t modrm = *(data + 1); | 617 uint8_t modrm = *(data + 1); |
| 653 int mod, regop, rm; | 618 int mod, regop, rm; |
| 654 GetModRm(modrm, &mod, ®op, &rm); | 619 GetModRm(modrm, &mod, ®op, &rm); |
| 655 const char* mnem = "Imm???"; | 620 const char* mnem = "Imm???"; |
| 656 switch (regop) { | 621 switch (regop) { |
| 657 case 0: | 622 case 0: |
| 658 mnem = "add"; | 623 mnem = "add"; |
| 659 break; | 624 break; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 690 return 1 + count + 2 /*int16_t*/; | 655 return 1 + count + 2 /*int16_t*/; |
| 691 } else if (sign_extension_bit) { | 656 } else if (sign_extension_bit) { |
| 692 PrintHex(*reinterpret_cast<int8_t*>(data + 1 + count), sign_extension_bit); | 657 PrintHex(*reinterpret_cast<int8_t*>(data + 1 + count), sign_extension_bit); |
| 693 return 1 + count + 1 /*int8_t*/; | 658 return 1 + count + 1 /*int8_t*/; |
| 694 } else { | 659 } else { |
| 695 PrintHex(*reinterpret_cast<int32_t*>(data + 1 + count)); | 660 PrintHex(*reinterpret_cast<int32_t*>(data + 1 + count)); |
| 696 return 1 + count + 4 /*int32_t*/; | 661 return 1 + count + 4 /*int32_t*/; |
| 697 } | 662 } |
| 698 } | 663 } |
| 699 | 664 |
| 700 | |
| 701 int X86Decoder::DecodeEnter(uint8_t* data) { | 665 int X86Decoder::DecodeEnter(uint8_t* data) { |
| 702 uint16_t size = *reinterpret_cast<uint16_t*>(data + 1); | 666 uint16_t size = *reinterpret_cast<uint16_t*>(data + 1); |
| 703 uint8_t level = *reinterpret_cast<uint8_t*>(data + 3); | 667 uint8_t level = *reinterpret_cast<uint8_t*>(data + 3); |
| 704 Print("enter "); | 668 Print("enter "); |
| 705 PrintInt(size); | 669 PrintInt(size); |
| 706 Print(", "); | 670 Print(", "); |
| 707 PrintInt(level); | 671 PrintInt(level); |
| 708 return 4; | 672 return 4; |
| 709 } | 673 } |
| 710 | 674 |
| 711 | |
| 712 // Returns number of bytes used, including *data. | 675 // Returns number of bytes used, including *data. |
| 713 int X86Decoder::JumpShort(uint8_t* data) { | 676 int X86Decoder::JumpShort(uint8_t* data) { |
| 714 ASSERT(*data == 0xEB); | 677 ASSERT(*data == 0xEB); |
| 715 uint8_t b = *(data + 1); | 678 uint8_t b = *(data + 1); |
| 716 uword dest = reinterpret_cast<uword>(data) + static_cast<int8_t>(b) + 2; | 679 uword dest = reinterpret_cast<uword>(data) + static_cast<int8_t>(b) + 2; |
| 717 Print("jmp "); | 680 Print("jmp "); |
| 718 PrintAddress(dest); | 681 PrintAddress(dest); |
| 719 return 2; | 682 return 2; |
| 720 } | 683 } |
| 721 | 684 |
| 722 | |
| 723 // Returns number of bytes used, including *data. | 685 // Returns number of bytes used, including *data. |
| 724 int X86Decoder::JumpConditional(uint8_t* data, const char* comment) { | 686 int X86Decoder::JumpConditional(uint8_t* data, const char* comment) { |
| 725 ASSERT(*data == 0x0F); | 687 ASSERT(*data == 0x0F); |
| 726 uint8_t cond = *(data + 1) & 0x0F; | 688 uint8_t cond = *(data + 1) & 0x0F; |
| 727 uword dest = | 689 uword dest = |
| 728 reinterpret_cast<uword>(data) + *reinterpret_cast<int32_t*>(data + 2) + 6; | 690 reinterpret_cast<uword>(data) + *reinterpret_cast<int32_t*>(data + 2) + 6; |
| 729 const char* mnem = jump_conditional_mnem[cond]; | 691 const char* mnem = jump_conditional_mnem[cond]; |
| 730 Print(mnem); | 692 Print(mnem); |
| 731 Print(" "); | 693 Print(" "); |
| 732 PrintAddress(dest); | 694 PrintAddress(dest); |
| 733 if (comment != NULL) { | 695 if (comment != NULL) { |
| 734 Print(", "); | 696 Print(", "); |
| 735 Print(comment); | 697 Print(comment); |
| 736 } | 698 } |
| 737 return 6; // includes 0x0F | 699 return 6; // includes 0x0F |
| 738 } | 700 } |
| 739 | 701 |
| 740 | |
| 741 // Returns number of bytes used, including *data. | 702 // Returns number of bytes used, including *data. |
| 742 int X86Decoder::JumpConditionalShort(uint8_t* data, const char* comment) { | 703 int X86Decoder::JumpConditionalShort(uint8_t* data, const char* comment) { |
| 743 uint8_t cond = *data & 0x0F; | 704 uint8_t cond = *data & 0x0F; |
| 744 uint8_t b = *(data + 1); | 705 uint8_t b = *(data + 1); |
| 745 uword dest = reinterpret_cast<uword>(data) + static_cast<int8_t>(b) + 2; | 706 uword dest = reinterpret_cast<uword>(data) + static_cast<int8_t>(b) + 2; |
| 746 const char* mnem = jump_conditional_mnem[cond]; | 707 const char* mnem = jump_conditional_mnem[cond]; |
| 747 Print(mnem); | 708 Print(mnem); |
| 748 Print(" "); | 709 Print(" "); |
| 749 PrintAddress(dest); | 710 PrintAddress(dest); |
| 750 if (comment != NULL) { | 711 if (comment != NULL) { |
| 751 Print(", "); | 712 Print(", "); |
| 752 Print(comment); | 713 Print(comment); |
| 753 } | 714 } |
| 754 return 2; | 715 return 2; |
| 755 } | 716 } |
| 756 | 717 |
| 757 | |
| 758 // Returns number of bytes used, including *data. | 718 // Returns number of bytes used, including *data. |
| 759 int X86Decoder::SetCC(uint8_t* data) { | 719 int X86Decoder::SetCC(uint8_t* data) { |
| 760 ASSERT(*data == 0x0F); | 720 ASSERT(*data == 0x0F); |
| 761 uint8_t cond = *(data + 1) & 0x0F; | 721 uint8_t cond = *(data + 1) & 0x0F; |
| 762 const char* mnem = set_conditional_mnem[cond]; | 722 const char* mnem = set_conditional_mnem[cond]; |
| 763 Print(mnem); | 723 Print(mnem); |
| 764 Print(" "); | 724 Print(" "); |
| 765 PrintRightByteOperand(data + 2); | 725 PrintRightByteOperand(data + 2); |
| 766 return 3; // includes 0x0F | 726 return 3; // includes 0x0F |
| 767 } | 727 } |
| 768 | 728 |
| 769 | |
| 770 // Returns number of bytes used, including *data. | 729 // Returns number of bytes used, including *data. |
| 771 int X86Decoder::CMov(uint8_t* data) { | 730 int X86Decoder::CMov(uint8_t* data) { |
| 772 ASSERT(*data == 0x0F); | 731 ASSERT(*data == 0x0F); |
| 773 uint8_t cond = *(data + 1) & 0x0F; | 732 uint8_t cond = *(data + 1) & 0x0F; |
| 774 const char* mnem = conditional_move_mnem[cond]; | 733 const char* mnem = conditional_move_mnem[cond]; |
| 775 int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2); | 734 int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2); |
| 776 return 2 + op_size; // includes 0x0F | 735 return 2 + op_size; // includes 0x0F |
| 777 } | 736 } |
| 778 | 737 |
| 779 | |
| 780 int X86Decoder::D1D3C1Instruction(uint8_t* data) { | 738 int X86Decoder::D1D3C1Instruction(uint8_t* data) { |
| 781 uint8_t op = *data; | 739 uint8_t op = *data; |
| 782 ASSERT(op == 0xD1 || op == 0xD3 || op == 0xC1); | 740 ASSERT(op == 0xD1 || op == 0xD3 || op == 0xC1); |
| 783 int mod, regop, rm; | 741 int mod, regop, rm; |
| 784 GetModRm(*(data + 1), &mod, ®op, &rm); | 742 GetModRm(*(data + 1), &mod, ®op, &rm); |
| 785 int num_bytes = 1; | 743 int num_bytes = 1; |
| 786 const char* mnem = NULL; | 744 const char* mnem = NULL; |
| 787 switch (regop) { | 745 switch (regop) { |
| 788 case 2: | 746 case 2: |
| 789 mnem = "rcl"; | 747 mnem = "rcl"; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 813 PrintInt(*(data + 2)); | 771 PrintInt(*(data + 2)); |
| 814 num_bytes++; | 772 num_bytes++; |
| 815 } else { | 773 } else { |
| 816 ASSERT(op == 0xD3); | 774 ASSERT(op == 0xD3); |
| 817 num_bytes += PrintRightOperand(data + 1); | 775 num_bytes += PrintRightOperand(data + 1); |
| 818 Print(", cl"); | 776 Print(", cl"); |
| 819 } | 777 } |
| 820 return num_bytes; | 778 return num_bytes; |
| 821 } | 779 } |
| 822 | 780 |
| 823 | |
| 824 uint8_t* X86Decoder::F3Instruction(uint8_t* data) { | 781 uint8_t* X86Decoder::F3Instruction(uint8_t* data) { |
| 825 if (*(data + 1) == 0x0F) { | 782 if (*(data + 1) == 0x0F) { |
| 826 uint8_t b2 = *(data + 2); | 783 uint8_t b2 = *(data + 2); |
| 827 switch (b2) { | 784 switch (b2) { |
| 828 case 0x2C: { | 785 case 0x2C: { |
| 829 data += 3; | 786 data += 3; |
| 830 data += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, data); | 787 data += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, data); |
| 831 break; | 788 break; |
| 832 } | 789 } |
| 833 case 0x2A: { | 790 case 0x2A: { |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 930 } | 887 } |
| 931 } else if (*(data + 1) == 0xA4) { | 888 } else if (*(data + 1) == 0xA4) { |
| 932 Print("rep_movsb"); | 889 Print("rep_movsb"); |
| 933 data += 2; | 890 data += 2; |
| 934 } else { | 891 } else { |
| 935 UNIMPLEMENTED(); | 892 UNIMPLEMENTED(); |
| 936 } | 893 } |
| 937 return data; | 894 return data; |
| 938 } | 895 } |
| 939 | 896 |
| 940 | |
| 941 // Returns number of bytes used, including *data. | 897 // Returns number of bytes used, including *data. |
| 942 int X86Decoder::F7Instruction(uint8_t* data) { | 898 int X86Decoder::F7Instruction(uint8_t* data) { |
| 943 ASSERT(*data == 0xF7); | 899 ASSERT(*data == 0xF7); |
| 944 uint8_t modrm = *(data + 1); | 900 uint8_t modrm = *(data + 1); |
| 945 int mod, regop, rm; | 901 int mod, regop, rm; |
| 946 GetModRm(modrm, &mod, ®op, &rm); | 902 GetModRm(modrm, &mod, ®op, &rm); |
| 947 if (mod == 3 && regop != 0) { | 903 if (mod == 3 && regop != 0) { |
| 948 const char* mnem = NULL; | 904 const char* mnem = NULL; |
| 949 switch (regop) { | 905 switch (regop) { |
| 950 case 2: | 906 case 2: |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1174 return 2; | 1130 return 2; |
| 1175 } else if (b1 == 0xDA && b2 == 0xE9) { | 1131 } else if (b1 == 0xDA && b2 == 0xE9) { |
| 1176 const char* mnem = "fucompp"; | 1132 const char* mnem = "fucompp"; |
| 1177 Print(mnem); | 1133 Print(mnem); |
| 1178 return 2; | 1134 return 2; |
| 1179 } | 1135 } |
| 1180 Print("Unknown FP instruction"); | 1136 Print("Unknown FP instruction"); |
| 1181 return 2; | 1137 return 2; |
| 1182 } | 1138 } |
| 1183 | 1139 |
| 1184 | |
| 1185 uint8_t* X86Decoder::SSEInstruction(uint8_t prefix, | 1140 uint8_t* X86Decoder::SSEInstruction(uint8_t prefix, |
| 1186 uint8_t primary, | 1141 uint8_t primary, |
| 1187 uint8_t* data) { | 1142 uint8_t* data) { |
| 1188 ASSERT(prefix == 0x0F); | 1143 ASSERT(prefix == 0x0F); |
| 1189 int mod, regop, rm; | 1144 int mod, regop, rm; |
| 1190 if (primary == 0x10) { | 1145 if (primary == 0x10) { |
| 1191 GetModRm(*data, &mod, ®op, &rm); | 1146 GetModRm(*data, &mod, ®op, &rm); |
| 1192 Print("movups "); | 1147 Print("movups "); |
| 1193 PrintXmmRegister(regop); | 1148 PrintXmmRegister(regop); |
| 1194 Print(","); | 1149 Print(","); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1206 GetModRm(*data, &mod, ®op, &rm); | 1161 GetModRm(*data, &mod, ®op, &rm); |
| 1207 Print(f0mnem); | 1162 Print(f0mnem); |
| 1208 Print(" "); | 1163 Print(" "); |
| 1209 PrintXmmRegister(regop); | 1164 PrintXmmRegister(regop); |
| 1210 Print(","); | 1165 Print(","); |
| 1211 data += PrintRightXmmOperand(data); | 1166 data += PrintRightXmmOperand(data); |
| 1212 } | 1167 } |
| 1213 return data; | 1168 return data; |
| 1214 } | 1169 } |
| 1215 | 1170 |
| 1216 | |
| 1217 int X86Decoder::BitwisePDInstruction(uint8_t* data) { | 1171 int X86Decoder::BitwisePDInstruction(uint8_t* data) { |
| 1218 const char* mnem = | 1172 const char* mnem = |
| 1219 (*data == 0x57) ? "xorpd" : (*data == 0x56) ? "orpd" : "andpd"; | 1173 (*data == 0x57) ? "xorpd" : (*data == 0x56) ? "orpd" : "andpd"; |
| 1220 int mod, regop, rm; | 1174 int mod, regop, rm; |
| 1221 GetModRm(*(data + 1), &mod, ®op, &rm); | 1175 GetModRm(*(data + 1), &mod, ®op, &rm); |
| 1222 Print(mnem); | 1176 Print(mnem); |
| 1223 Print(" "); | 1177 Print(" "); |
| 1224 PrintXmmRegister(regop); | 1178 PrintXmmRegister(regop); |
| 1225 Print(","); | 1179 Print(","); |
| 1226 return 1 + PrintRightXmmOperand(data + 1); | 1180 return 1 + PrintRightXmmOperand(data + 1); |
| 1227 } | 1181 } |
| 1228 | 1182 |
| 1229 | |
| 1230 int X86Decoder::Packed660F38Instruction(uint8_t* data) { | 1183 int X86Decoder::Packed660F38Instruction(uint8_t* data) { |
| 1231 if (*(data + 1) == 0x25) { | 1184 if (*(data + 1) == 0x25) { |
| 1232 Print("pmovsxdq "); | 1185 Print("pmovsxdq "); |
| 1233 int mod, regop, rm; | 1186 int mod, regop, rm; |
| 1234 GetModRm(*(data + 2), &mod, ®op, &rm); | 1187 GetModRm(*(data + 2), &mod, ®op, &rm); |
| 1235 PrintXmmRegister(regop); | 1188 PrintXmmRegister(regop); |
| 1236 Print(","); | 1189 Print(","); |
| 1237 return 2 + PrintRightXmmOperand(data + 2); | 1190 return 2 + PrintRightXmmOperand(data + 2); |
| 1238 } else if (*(data + 1) == 0x29) { | 1191 } else if (*(data + 1) == 0x29) { |
| 1239 Print("pcmpeqq "); | 1192 Print("pcmpeqq "); |
| 1240 int mod, regop, rm; | 1193 int mod, regop, rm; |
| 1241 GetModRm(*(data + 2), &mod, ®op, &rm); | 1194 GetModRm(*(data + 2), &mod, ®op, &rm); |
| 1242 PrintXmmRegister(regop); | 1195 PrintXmmRegister(regop); |
| 1243 Print(","); | 1196 Print(","); |
| 1244 return 2 + PrintRightXmmOperand(data + 2); | 1197 return 2 + PrintRightXmmOperand(data + 2); |
| 1245 } | 1198 } |
| 1246 UNREACHABLE(); | 1199 UNREACHABLE(); |
| 1247 return 1; | 1200 return 1; |
| 1248 } | 1201 } |
| 1249 | 1202 |
| 1250 | |
| 1251 // Called when disassembling test eax, 0xXXXXX. | 1203 // Called when disassembling test eax, 0xXXXXX. |
| 1252 void X86Decoder::CheckPrintStop(uint8_t* data) { | 1204 void X86Decoder::CheckPrintStop(uint8_t* data) { |
| 1253 // Recognize stop pattern. | 1205 // Recognize stop pattern. |
| 1254 if (*reinterpret_cast<uint8_t*>(data + 5) == 0xCC) { | 1206 if (*reinterpret_cast<uint8_t*>(data + 5) == 0xCC) { |
| 1255 Print(" STOP:'"); | 1207 Print(" STOP:'"); |
| 1256 const char* text = *reinterpret_cast<const char**>(data + 1); | 1208 const char* text = *reinterpret_cast<const char**>(data + 1); |
| 1257 Print(text); | 1209 Print(text); |
| 1258 Print("'"); | 1210 Print("'"); |
| 1259 } | 1211 } |
| 1260 } | 1212 } |
| 1261 | 1213 |
| 1262 const char* X86Decoder::GetBranchPrefix(uint8_t** data) { | 1214 const char* X86Decoder::GetBranchPrefix(uint8_t** data) { |
| 1263 // We use these two prefixes only with branch prediction | 1215 // We use these two prefixes only with branch prediction |
| 1264 switch (**data) { | 1216 switch (**data) { |
| 1265 case 0x3E: // ds | 1217 case 0x3E: // ds |
| 1266 (*data)++; | 1218 (*data)++; |
| 1267 return "predicted taken"; | 1219 return "predicted taken"; |
| 1268 case 0x2E: // cs | 1220 case 0x2E: // cs |
| 1269 (*data)++; | 1221 (*data)++; |
| 1270 return "predicted not taken"; | 1222 return "predicted not taken"; |
| 1271 case 0xF0: // lock | 1223 case 0xF0: // lock |
| 1272 Print("lock "); | 1224 Print("lock "); |
| 1273 (*data)++; | 1225 (*data)++; |
| 1274 return NULL; | 1226 return NULL; |
| 1275 default: // Ignore all other instructions. | 1227 default: // Ignore all other instructions. |
| 1276 return NULL; | 1228 return NULL; |
| 1277 } | 1229 } |
| 1278 } | 1230 } |
| 1279 | 1231 |
| 1280 | |
| 1281 bool X86Decoder::DecodeInstructionType(const InstructionDesc& idesc, | 1232 bool X86Decoder::DecodeInstructionType(const InstructionDesc& idesc, |
| 1282 const char* branch_hint, | 1233 const char* branch_hint, |
| 1283 uint8_t** data) { | 1234 uint8_t** data) { |
| 1284 switch (idesc.type) { | 1235 switch (idesc.type) { |
| 1285 case ZERO_OPERANDS_INSTR: | 1236 case ZERO_OPERANDS_INSTR: |
| 1286 Print(idesc.mnem); | 1237 Print(idesc.mnem); |
| 1287 (*data)++; | 1238 (*data)++; |
| 1288 return true; | 1239 return true; |
| 1289 | 1240 |
| 1290 case TWO_OPERANDS_INSTR: | 1241 case TWO_OPERANDS_INSTR: |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1333 | 1284 |
| 1334 case NO_INSTR: | 1285 case NO_INSTR: |
| 1335 return false; | 1286 return false; |
| 1336 | 1287 |
| 1337 default: | 1288 default: |
| 1338 UNIMPLEMENTED(); // This type is not implemented. | 1289 UNIMPLEMENTED(); // This type is not implemented. |
| 1339 return false; | 1290 return false; |
| 1340 } | 1291 } |
| 1341 } | 1292 } |
| 1342 | 1293 |
| 1343 | |
| 1344 int X86Decoder::InstructionDecode(uword pc) { | 1294 int X86Decoder::InstructionDecode(uword pc) { |
| 1345 uint8_t* data = reinterpret_cast<uint8_t*>(pc); | 1295 uint8_t* data = reinterpret_cast<uint8_t*>(pc); |
| 1346 // Check for hints. | 1296 // Check for hints. |
| 1347 const char* branch_hint = GetBranchPrefix(&data); | 1297 const char* branch_hint = GetBranchPrefix(&data); |
| 1348 const InstructionDesc& idesc = instruction_table.Get(*data); | 1298 const InstructionDesc& idesc = instruction_table.Get(*data); |
| 1349 // Will be set to false if the current instruction | 1299 // Will be set to false if the current instruction |
| 1350 // is not in 'instructions' table. | 1300 // is not in 'instructions' table. |
| 1351 bool processed = DecodeInstructionType(idesc, branch_hint, &data); | 1301 bool processed = DecodeInstructionType(idesc, branch_hint, &data); |
| 1352 //---------------------------- | 1302 //---------------------------- |
| 1353 if (!processed) { | 1303 if (!processed) { |
| (...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1905 UNIMPLEMENTED(); | 1855 UNIMPLEMENTED(); |
| 1906 } | 1856 } |
| 1907 } | 1857 } |
| 1908 | 1858 |
| 1909 int instr_len = data - reinterpret_cast<uint8_t*>(pc); | 1859 int instr_len = data - reinterpret_cast<uint8_t*>(pc); |
| 1910 ASSERT(instr_len > 0); // Ensure progress. | 1860 ASSERT(instr_len > 0); // Ensure progress. |
| 1911 | 1861 |
| 1912 return instr_len; | 1862 return instr_len; |
| 1913 } // NOLINT | 1863 } // NOLINT |
| 1914 | 1864 |
| 1915 | |
| 1916 void Disassembler::DecodeInstruction(char* hex_buffer, | 1865 void Disassembler::DecodeInstruction(char* hex_buffer, |
| 1917 intptr_t hex_size, | 1866 intptr_t hex_size, |
| 1918 char* human_buffer, | 1867 char* human_buffer, |
| 1919 intptr_t human_size, | 1868 intptr_t human_size, |
| 1920 int* out_instr_len, | 1869 int* out_instr_len, |
| 1921 const Code& code, | 1870 const Code& code, |
| 1922 Object** object, | 1871 Object** object, |
| 1923 uword pc) { | 1872 uword pc) { |
| 1924 ASSERT(hex_size > 0); | 1873 ASSERT(hex_size > 0); |
| 1925 ASSERT(human_size > 0); | 1874 ASSERT(human_size > 0); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1949 } | 1898 } |
| 1950 } | 1899 } |
| 1951 } | 1900 } |
| 1952 } | 1901 } |
| 1953 | 1902 |
| 1954 #endif // !PRODUCT | 1903 #endif // !PRODUCT |
| 1955 | 1904 |
| 1956 } // namespace dart | 1905 } // namespace dart |
| 1957 | 1906 |
| 1958 #endif // defined TARGET_ARCH_IA32 | 1907 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |