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 |