Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(382)

Side by Side Diff: runtime/vm/disassembler_x64.cc

Issue 2481873005: clang-format runtime/vm (Closed)
Patch Set: Merge Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/disassembler_mips.cc ('k') | runtime/vm/double_conversion.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_X64) 8 #if defined(TARGET_ARCH_X64)
9 #include "platform/utils.h" 9 #include "platform/utils.h"
10 #include "vm/allocation.h" 10 #include "vm/allocation.h"
(...skipping 22 matching lines...) Expand all
33 // Tables 33 // Tables
34 //------------------------------------------------------------------ 34 //------------------------------------------------------------------
35 struct ByteMnemonic { 35 struct ByteMnemonic {
36 int b; // -1 terminates, otherwise must be in range (0..255) 36 int b; // -1 terminates, otherwise must be in range (0..255)
37 OperandType op_order_; 37 OperandType op_order_;
38 const char* mnem; 38 const char* mnem;
39 }; 39 };
40 40
41 41
42 static const ByteMnemonic two_operands_instr[] = { 42 static const ByteMnemonic two_operands_instr[] = {
43 { 0x00, BYTE_OPER_REG_OP_ORDER, "add" }, 43 {0x00, BYTE_OPER_REG_OP_ORDER, "add"},
44 { 0x01, OPER_REG_OP_ORDER, "add" }, 44 {0x01, OPER_REG_OP_ORDER, "add"},
45 { 0x02, BYTE_REG_OPER_OP_ORDER, "add" }, 45 {0x02, BYTE_REG_OPER_OP_ORDER, "add"},
46 { 0x03, REG_OPER_OP_ORDER, "add" }, 46 {0x03, REG_OPER_OP_ORDER, "add"},
47 { 0x08, BYTE_OPER_REG_OP_ORDER, "or" }, 47 {0x08, BYTE_OPER_REG_OP_ORDER, "or"},
48 { 0x09, OPER_REG_OP_ORDER, "or" }, 48 {0x09, OPER_REG_OP_ORDER, "or"},
49 { 0x0A, BYTE_REG_OPER_OP_ORDER, "or" }, 49 {0x0A, BYTE_REG_OPER_OP_ORDER, "or"},
50 { 0x0B, REG_OPER_OP_ORDER, "or" }, 50 {0x0B, REG_OPER_OP_ORDER, "or"},
51 { 0x10, BYTE_OPER_REG_OP_ORDER, "adc" }, 51 {0x10, BYTE_OPER_REG_OP_ORDER, "adc"},
52 { 0x11, OPER_REG_OP_ORDER, "adc" }, 52 {0x11, OPER_REG_OP_ORDER, "adc"},
53 { 0x12, BYTE_REG_OPER_OP_ORDER, "adc" }, 53 {0x12, BYTE_REG_OPER_OP_ORDER, "adc"},
54 { 0x13, REG_OPER_OP_ORDER, "adc" }, 54 {0x13, REG_OPER_OP_ORDER, "adc"},
55 { 0x18, BYTE_OPER_REG_OP_ORDER, "sbb" }, 55 {0x18, BYTE_OPER_REG_OP_ORDER, "sbb"},
56 { 0x19, OPER_REG_OP_ORDER, "sbb" }, 56 {0x19, OPER_REG_OP_ORDER, "sbb"},
57 { 0x1A, BYTE_REG_OPER_OP_ORDER, "sbb" }, 57 {0x1A, BYTE_REG_OPER_OP_ORDER, "sbb"},
58 { 0x1B, REG_OPER_OP_ORDER, "sbb" }, 58 {0x1B, REG_OPER_OP_ORDER, "sbb"},
59 { 0x20, BYTE_OPER_REG_OP_ORDER, "and" }, 59 {0x20, BYTE_OPER_REG_OP_ORDER, "and"},
60 { 0x21, OPER_REG_OP_ORDER, "and" }, 60 {0x21, OPER_REG_OP_ORDER, "and"},
61 { 0x22, BYTE_REG_OPER_OP_ORDER, "and" }, 61 {0x22, BYTE_REG_OPER_OP_ORDER, "and"},
62 { 0x23, REG_OPER_OP_ORDER, "and" }, 62 {0x23, REG_OPER_OP_ORDER, "and"},
63 { 0x28, BYTE_OPER_REG_OP_ORDER, "sub" }, 63 {0x28, BYTE_OPER_REG_OP_ORDER, "sub"},
64 { 0x29, OPER_REG_OP_ORDER, "sub" }, 64 {0x29, OPER_REG_OP_ORDER, "sub"},
65 { 0x2A, BYTE_REG_OPER_OP_ORDER, "sub" }, 65 {0x2A, BYTE_REG_OPER_OP_ORDER, "sub"},
66 { 0x2B, REG_OPER_OP_ORDER, "sub" }, 66 {0x2B, REG_OPER_OP_ORDER, "sub"},
67 { 0x30, BYTE_OPER_REG_OP_ORDER, "xor" }, 67 {0x30, BYTE_OPER_REG_OP_ORDER, "xor"},
68 { 0x31, OPER_REG_OP_ORDER, "xor" }, 68 {0x31, OPER_REG_OP_ORDER, "xor"},
69 { 0x32, BYTE_REG_OPER_OP_ORDER, "xor" }, 69 {0x32, BYTE_REG_OPER_OP_ORDER, "xor"},
70 { 0x33, REG_OPER_OP_ORDER, "xor" }, 70 {0x33, REG_OPER_OP_ORDER, "xor"},
71 { 0x38, BYTE_OPER_REG_OP_ORDER, "cmp" }, 71 {0x38, BYTE_OPER_REG_OP_ORDER, "cmp"},
72 { 0x39, OPER_REG_OP_ORDER, "cmp" }, 72 {0x39, OPER_REG_OP_ORDER, "cmp"},
73 { 0x3A, BYTE_REG_OPER_OP_ORDER, "cmp" }, 73 {0x3A, BYTE_REG_OPER_OP_ORDER, "cmp"},
74 { 0x3B, REG_OPER_OP_ORDER, "cmp" }, 74 {0x3B, REG_OPER_OP_ORDER, "cmp"},
75 { 0x63, REG_OPER_OP_ORDER, "movsxd" }, 75 {0x63, REG_OPER_OP_ORDER, "movsxd"},
76 { 0x84, BYTE_REG_OPER_OP_ORDER, "test" }, 76 {0x84, BYTE_REG_OPER_OP_ORDER, "test"},
77 { 0x85, REG_OPER_OP_ORDER, "test" }, 77 {0x85, REG_OPER_OP_ORDER, "test"},
78 { 0x86, BYTE_REG_OPER_OP_ORDER, "xchg" }, 78 {0x86, BYTE_REG_OPER_OP_ORDER, "xchg"},
79 { 0x87, REG_OPER_OP_ORDER, "xchg" }, 79 {0x87, REG_OPER_OP_ORDER, "xchg"},
80 { 0x88, BYTE_OPER_REG_OP_ORDER, "mov" }, 80 {0x88, BYTE_OPER_REG_OP_ORDER, "mov"},
81 { 0x89, OPER_REG_OP_ORDER, "mov" }, 81 {0x89, OPER_REG_OP_ORDER, "mov"},
82 { 0x8A, BYTE_REG_OPER_OP_ORDER, "mov" }, 82 {0x8A, BYTE_REG_OPER_OP_ORDER, "mov"},
83 { 0x8B, REG_OPER_OP_ORDER, "mov" }, 83 {0x8B, REG_OPER_OP_ORDER, "mov"},
84 { 0x8D, REG_OPER_OP_ORDER, "lea" }, 84 {0x8D, REG_OPER_OP_ORDER, "lea"},
85 { -1, UNSET_OP_ORDER, "" } 85 {-1, UNSET_OP_ORDER, ""}};
86 };
87 86
88 87
89 static const ByteMnemonic zero_operands_instr[] = { 88 static const ByteMnemonic zero_operands_instr[] = {
90 { 0xC3, UNSET_OP_ORDER, "ret" }, 89 {0xC3, UNSET_OP_ORDER, "ret"}, {0xC9, UNSET_OP_ORDER, "leave"},
91 { 0xC9, UNSET_OP_ORDER, "leave" }, 90 {0xF4, UNSET_OP_ORDER, "hlt"}, {0xFC, UNSET_OP_ORDER, "cld"},
92 { 0xF4, UNSET_OP_ORDER, "hlt" }, 91 {0xCC, UNSET_OP_ORDER, "int3"}, {0x60, UNSET_OP_ORDER, "pushad"},
93 { 0xFC, UNSET_OP_ORDER, "cld" }, 92 {0x61, UNSET_OP_ORDER, "popad"}, {0x9C, UNSET_OP_ORDER, "pushfd"},
94 { 0xCC, UNSET_OP_ORDER, "int3" }, 93 {0x9D, UNSET_OP_ORDER, "popfd"}, {0x9E, UNSET_OP_ORDER, "sahf"},
95 { 0x60, UNSET_OP_ORDER, "pushad" }, 94 {0x99, UNSET_OP_ORDER, "cdq"}, {0x9B, UNSET_OP_ORDER, "fwait"},
96 { 0x61, UNSET_OP_ORDER, "popad" }, 95 {0xA4, UNSET_OP_ORDER, "movs"}, {0xA5, UNSET_OP_ORDER, "movs"},
97 { 0x9C, UNSET_OP_ORDER, "pushfd" }, 96 {0xA6, UNSET_OP_ORDER, "cmps"}, {0xA7, UNSET_OP_ORDER, "cmps"},
98 { 0x9D, UNSET_OP_ORDER, "popfd" }, 97 {-1, UNSET_OP_ORDER, ""}};
99 { 0x9E, UNSET_OP_ORDER, "sahf" },
100 { 0x99, UNSET_OP_ORDER, "cdq" },
101 { 0x9B, UNSET_OP_ORDER, "fwait" },
102 { 0xA4, UNSET_OP_ORDER, "movs" },
103 { 0xA5, UNSET_OP_ORDER, "movs" },
104 { 0xA6, UNSET_OP_ORDER, "cmps" },
105 { 0xA7, UNSET_OP_ORDER, "cmps" },
106 { -1, UNSET_OP_ORDER, "" }
107 };
108 98
109 99
110 static const ByteMnemonic call_jump_instr[] = { 100 static const ByteMnemonic call_jump_instr[] = {{0xE8, UNSET_OP_ORDER, "call"},
111 { 0xE8, UNSET_OP_ORDER, "call" }, 101 {0xE9, UNSET_OP_ORDER, "jmp"},
112 { 0xE9, UNSET_OP_ORDER, "jmp" }, 102 {-1, UNSET_OP_ORDER, ""}};
113 { -1, UNSET_OP_ORDER, "" }
114 };
115 103
116 104
117 static const ByteMnemonic short_immediate_instr[] = { 105 static const ByteMnemonic short_immediate_instr[] = {
118 { 0x05, UNSET_OP_ORDER, "add" }, 106 {0x05, UNSET_OP_ORDER, "add"}, {0x0D, UNSET_OP_ORDER, "or"},
119 { 0x0D, UNSET_OP_ORDER, "or" }, 107 {0x15, UNSET_OP_ORDER, "adc"}, {0x1D, UNSET_OP_ORDER, "sbb"},
120 { 0x15, UNSET_OP_ORDER, "adc" }, 108 {0x25, UNSET_OP_ORDER, "and"}, {0x2D, UNSET_OP_ORDER, "sub"},
121 { 0x1D, UNSET_OP_ORDER, "sbb" }, 109 {0x35, UNSET_OP_ORDER, "xor"}, {0x3D, UNSET_OP_ORDER, "cmp"},
122 { 0x25, UNSET_OP_ORDER, "and" }, 110 {-1, UNSET_OP_ORDER, ""}};
123 { 0x2D, UNSET_OP_ORDER, "sub" },
124 { 0x35, UNSET_OP_ORDER, "xor" },
125 { 0x3D, UNSET_OP_ORDER, "cmp" },
126 { -1, UNSET_OP_ORDER, "" }
127 };
128 111
129 112
130 static const char* const conditional_code_suffix[] = { 113 static const char* const conditional_code_suffix[] = {
131 "o", "no", "c", "nc", "z", "nz", "na", "a", 114 "o", "no", "c", "nc", "z", "nz", "na", "a",
132 "s", "ns", "pe", "po", "l", "ge", "le", "g" 115 "s", "ns", "pe", "po", "l", "ge", "le", "g"};
133 };
134 116
135 117
136 enum InstructionType { 118 enum InstructionType {
137 NO_INSTR, 119 NO_INSTR,
138 ZERO_OPERANDS_INSTR, 120 ZERO_OPERANDS_INSTR,
139 TWO_OPERANDS_INSTR, 121 TWO_OPERANDS_INSTR,
140 JUMP_CONDITIONAL_SHORT_INSTR, 122 JUMP_CONDITIONAL_SHORT_INSTR,
141 REGISTER_INSTR, 123 REGISTER_INSTR,
142 PUSHPOP_INSTR, // Has implicit 64-bit operand size. 124 PUSHPOP_INSTR, // Has implicit 64-bit operand size.
143 MOVE_REG_INSTR, 125 MOVE_REG_INSTR,
(...skipping 16 matching lines...) Expand all
160 const char* mnem; 142 const char* mnem;
161 InstructionType type; 143 InstructionType type;
162 OperandType op_order_; 144 OperandType op_order_;
163 bool byte_size_operation; // Fixed 8-bit operation. 145 bool byte_size_operation; // Fixed 8-bit operation.
164 }; 146 };
165 147
166 148
167 class InstructionTable : public ValueObject { 149 class InstructionTable : public ValueObject {
168 public: 150 public:
169 InstructionTable(); 151 InstructionTable();
170 const InstructionDesc& Get(uint8_t x) const { 152 const InstructionDesc& Get(uint8_t x) const { return instructions_[x]; }
171 return instructions_[x];
172 }
173 153
174 private: 154 private:
175 InstructionDesc instructions_[256]; 155 InstructionDesc instructions_[256];
176 void Clear(); 156 void Clear();
177 void Init(); 157 void Init();
178 void CopyTable(const ByteMnemonic bm[], InstructionType type); 158 void CopyTable(const ByteMnemonic bm[], InstructionType type);
179 void SetTableRange(InstructionType type, 159 void SetTableRange(InstructionType type,
180 uint8_t start, 160 uint8_t start,
181 uint8_t end, 161 uint8_t end,
182 bool byte_size, 162 bool byte_size,
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 id->type = type; 222 id->type = type;
243 id->byte_size_operation = byte_size; 223 id->byte_size_operation = byte_size;
244 } 224 }
245 } 225 }
246 226
247 227
248 void InstructionTable::AddJumpConditionalShort() { 228 void InstructionTable::AddJumpConditionalShort() {
249 for (uint8_t b = 0x70; b <= 0x7F; b++) { 229 for (uint8_t b = 0x70; b <= 0x7F; b++) {
250 InstructionDesc* id = &instructions_[b]; 230 InstructionDesc* id = &instructions_[b];
251 ASSERT(NO_INSTR == id->type); // Information not already entered 231 ASSERT(NO_INSTR == id->type); // Information not already entered
252 id->mnem = NULL; // Computed depending on condition code. 232 id->mnem = NULL; // Computed depending on condition code.
253 id->type = JUMP_CONDITIONAL_SHORT_INSTR; 233 id->type = JUMP_CONDITIONAL_SHORT_INSTR;
254 } 234 }
255 } 235 }
256 236
257 237
258 static InstructionTable instruction_table; 238 static InstructionTable instruction_table;
259 239
260 240
261 static InstructionDesc cmov_instructions[16] = { 241 static InstructionDesc cmov_instructions[16] = {
262 {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 242 {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
263 {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 243 {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
264 {"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 244 {"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
265 {"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 245 {"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
266 {"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 246 {"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
267 {"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 247 {"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
268 {"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 248 {"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
269 {"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 249 {"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
270 {"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 250 {"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
271 {"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 251 {"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
272 {"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 252 {"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
273 {"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 253 {"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
274 {"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 254 {"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
275 {"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 255 {"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
276 {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 256 {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
277 {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false} 257 {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}};
278 };
279 258
280 259
281 //------------------------------------------------- 260 //-------------------------------------------------
282 // DisassemblerX64 implementation. 261 // DisassemblerX64 implementation.
283 262
284 263
285 static const int kMaxXmmRegisters = 16; 264 static const int kMaxXmmRegisters = 16;
286 static const char* xmm_regs[kMaxXmmRegisters] = { 265 static const char* xmm_regs[kMaxXmmRegisters] = {
287 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", 266 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
288 "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" 267 "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"};
289 };
290 268
291 class DisassemblerX64 : public ValueObject { 269 class DisassemblerX64 : public ValueObject {
292 public: 270 public:
293 DisassemblerX64(char* buffer, intptr_t buffer_size) 271 DisassemblerX64(char* buffer, intptr_t buffer_size)
294 : buffer_(buffer), 272 : buffer_(buffer),
295 buffer_size_(buffer_size), 273 buffer_size_(buffer_size),
296 buffer_pos_(0), 274 buffer_pos_(0),
297 rex_(0), 275 rex_(0),
298 operand_size_(0), 276 operand_size_(0),
299 group_1_prefix_(0), 277 group_1_prefix_(0),
300 byte_size_operand_(false) { 278 byte_size_operand_(false) {
301 buffer_[buffer_pos_] = '\0'; 279 buffer_[buffer_pos_] = '\0';
302 } 280 }
303 281
304 virtual ~DisassemblerX64() { 282 virtual ~DisassemblerX64() {}
305 }
306 283
307 int InstructionDecode(uword pc); 284 int InstructionDecode(uword pc);
308 285
309 private: 286 private:
310 enum OperandSize { 287 enum OperandSize {
311 BYTE_SIZE = 0, 288 BYTE_SIZE = 0,
312 WORD_SIZE = 1, 289 WORD_SIZE = 1,
313 DOUBLEWORD_SIZE = 2, 290 DOUBLEWORD_SIZE = 2,
314 QUADWORD_SIZE = 3 291 QUADWORD_SIZE = 3
315 }; 292 };
(...skipping 16 matching lines...) Expand all
332 309
333 bool rex_w() { return (rex_ & 0x08) != 0; } 310 bool rex_w() { return (rex_ & 0x08) != 0; }
334 311
335 OperandSize operand_size() { 312 OperandSize operand_size() {
336 if (byte_size_operand_) return BYTE_SIZE; 313 if (byte_size_operand_) return BYTE_SIZE;
337 if (rex_w()) return QUADWORD_SIZE; 314 if (rex_w()) return QUADWORD_SIZE;
338 if (operand_size_ != 0) return WORD_SIZE; 315 if (operand_size_ != 0) return WORD_SIZE;
339 return DOUBLEWORD_SIZE; 316 return DOUBLEWORD_SIZE;
340 } 317 }
341 318
342 char operand_size_code() { 319 char operand_size_code() { return "bwlq"[operand_size()]; }
343 return "bwlq"[operand_size()];
344 }
345 320
346 // Disassembler helper functions. 321 // Disassembler helper functions.
347 void get_modrm(uint8_t data, 322 void get_modrm(uint8_t data, int* mod, int* regop, int* rm) {
348 int* mod,
349 int* regop,
350 int* rm) {
351 *mod = (data >> 6) & 3; 323 *mod = (data >> 6) & 3;
352 *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0); 324 *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0);
353 *rm = (data & 7) | (rex_b() ? 8 : 0); 325 *rm = (data & 7) | (rex_b() ? 8 : 0);
354 } 326 }
355 327
356 void get_sib(uint8_t data, 328 void get_sib(uint8_t data, int* scale, int* index, int* base) {
357 int* scale,
358 int* index,
359 int* base) {
360 *scale = (data >> 6) & 3; 329 *scale = (data >> 6) & 3;
361 *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0); 330 *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0);
362 *base = (data & 7) | (rex_b() ? 8 : 0); 331 *base = (data & 7) | (rex_b() ? 8 : 0);
363 } 332 }
364 333
365 const char* NameOfCPURegister(int reg) const { 334 const char* NameOfCPURegister(int reg) const {
366 return Assembler::RegisterName(static_cast<Register>(reg)); 335 return Assembler::RegisterName(static_cast<Register>(reg));
367 } 336 }
368 337
369 const char* NameOfByteCPURegister(int reg) const { 338 const char* NameOfByteCPURegister(int reg) const {
370 return NameOfCPURegister(reg); 339 return NameOfCPURegister(reg);
371 } 340 }
372 341
373 const char* NameOfXMMRegister(int reg) const { 342 const char* NameOfXMMRegister(int reg) const {
374 ASSERT((0 <= reg) && (reg < kMaxXmmRegisters)); 343 ASSERT((0 <= reg) && (reg < kMaxXmmRegisters));
375 return xmm_regs[reg]; 344 return xmm_regs[reg];
376 } 345 }
377 346
378 void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); 347 void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
379 void PrintAddress(uint8_t* addr); 348 void PrintAddress(uint8_t* addr);
380 349
381 int PrintOperands(const char* mnem, 350 int PrintOperands(const char* mnem, OperandType op_order, uint8_t* data);
382 OperandType op_order,
383 uint8_t* data);
384 351
385 typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const; 352 typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const;
386 353
387 int PrintRightOperandHelper(uint8_t* modrmp, 354 int PrintRightOperandHelper(uint8_t* modrmp,
388 RegisterNameMapping register_name); 355 RegisterNameMapping register_name);
389 int PrintRightOperand(uint8_t* modrmp); 356 int PrintRightOperand(uint8_t* modrmp);
390 int PrintRightByteOperand(uint8_t* modrmp); 357 int PrintRightByteOperand(uint8_t* modrmp);
391 int PrintRightXMMOperand(uint8_t* modrmp); 358 int PrintRightXMMOperand(uint8_t* modrmp);
392 void PrintDisp(int disp, const char* after); 359 void PrintDisp(int disp, const char* after);
393 int PrintImmediate(uint8_t* data, OperandSize size); 360 int PrintImmediate(uint8_t* data, OperandSize size);
394 void PrintImmediateValue(int64_t value); 361 void PrintImmediateValue(int64_t value);
395 int PrintImmediateOp(uint8_t* data); 362 int PrintImmediateOp(uint8_t* data);
396 const char* TwoByteMnemonic(uint8_t opcode); 363 const char* TwoByteMnemonic(uint8_t opcode);
397 int TwoByteOpcodeInstruction(uint8_t* data); 364 int TwoByteOpcodeInstruction(uint8_t* data);
398 365
399 int F6F7Instruction(uint8_t* data); 366 int F6F7Instruction(uint8_t* data);
400 int ShiftInstruction(uint8_t* data); 367 int ShiftInstruction(uint8_t* data);
401 int JumpShort(uint8_t* data); 368 int JumpShort(uint8_t* data);
402 int JumpConditional(uint8_t* data); 369 int JumpConditional(uint8_t* data);
403 int JumpConditionalShort(uint8_t* data); 370 int JumpConditionalShort(uint8_t* data);
404 int SetCC(uint8_t* data); 371 int SetCC(uint8_t* data);
405 int FPUInstruction(uint8_t* data); 372 int FPUInstruction(uint8_t* data);
406 int MemoryFPUInstruction(int escape_opcode, int regop, uint8_t* modrm_start); 373 int MemoryFPUInstruction(int escape_opcode, int regop, uint8_t* modrm_start);
407 int RegisterFPUInstruction(int escape_opcode, uint8_t modrm_byte); 374 int RegisterFPUInstruction(int escape_opcode, uint8_t modrm_byte);
408 375
409 bool DecodeInstructionType(uint8_t** data); 376 bool DecodeInstructionType(uint8_t** data);
410 377
411 void UnimplementedInstruction() { 378 void UnimplementedInstruction() { Print("'Unimplemented Instruction'"); }
412 Print("'Unimplemented Instruction'");
413 }
414 379
415 char* buffer_; // Decode instructions into this buffer. 380 char* buffer_; // Decode instructions into this buffer.
416 intptr_t buffer_size_; // The size of the buffer_. 381 intptr_t buffer_size_; // The size of the buffer_.
417 intptr_t buffer_pos_; // Current character position in the buffer_. 382 intptr_t buffer_pos_; // Current character position in the buffer_.
418 383
419 // Prefixes parsed 384 // Prefixes parsed
420 uint8_t rex_; 385 uint8_t rex_;
421 uint8_t operand_size_; // 0x66 or (if no group 3 prefix is present) 0x0. 386 uint8_t operand_size_; // 0x66 or (if no group 3 prefix is present) 0x0.
422 // 0xF2, 0xF3, or (if no group 1 prefix is present) 0. 387 // 0xF2, 0xF3, or (if no group 1 prefix is present) 0.
423 uint8_t group_1_prefix_; 388 uint8_t group_1_prefix_;
424 // Byte size operand override. 389 // Byte size operand override.
425 bool byte_size_operand_; 390 bool byte_size_operand_;
426 391
427 DISALLOW_COPY_AND_ASSIGN(DisassemblerX64); 392 DISALLOW_COPY_AND_ASSIGN(DisassemblerX64);
(...skipping 16 matching lines...) Expand all
444 (length >= available) ? (buffer_size_ - 1) : (buffer_pos_ + length); 409 (length >= available) ? (buffer_size_ - 1) : (buffer_pos_ + length);
445 ASSERT(buffer_pos_ < buffer_size_); 410 ASSERT(buffer_pos_ < buffer_size_);
446 } 411 }
447 412
448 413
449 int DisassemblerX64::PrintRightOperandHelper( 414 int DisassemblerX64::PrintRightOperandHelper(
450 uint8_t* modrmp, 415 uint8_t* modrmp,
451 RegisterNameMapping direct_register_name) { 416 RegisterNameMapping direct_register_name) {
452 int mod, regop, rm; 417 int mod, regop, rm;
453 get_modrm(*modrmp, &mod, &regop, &rm); 418 get_modrm(*modrmp, &mod, &regop, &rm);
454 RegisterNameMapping register_name = (mod == 3) ? direct_register_name : 419 RegisterNameMapping register_name =
455 &DisassemblerX64::NameOfCPURegister; 420 (mod == 3) ? direct_register_name : &DisassemblerX64::NameOfCPURegister;
456 switch (mod) { 421 switch (mod) {
457 case 0: 422 case 0:
458 if ((rm & 7) == 5) { 423 if ((rm & 7) == 5) {
459 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1); 424 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1);
460 Print("[rip"); 425 Print("[rip");
461 PrintDisp(disp, "]"); 426 PrintDisp(disp, "]");
462 return 5; 427 return 5;
463 } else if ((rm & 7) == 4) { 428 } else if ((rm & 7) == 4) {
464 // Codes for SIB byte. 429 // Codes for SIB byte.
465 uint8_t sib = *(modrmp + 1); 430 uint8_t sib = *(modrmp + 1);
466 int scale, index, base; 431 int scale, index, base;
467 get_sib(sib, &scale, &index, &base); 432 get_sib(sib, &scale, &index, &base);
468 if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) { 433 if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
469 // index == rsp means no index. Only use sib byte with no index for 434 // index == rsp means no index. Only use sib byte with no index for
470 // rsp and r12 base. 435 // rsp and r12 base.
471 Print("[%s]", NameOfCPURegister(base)); 436 Print("[%s]", NameOfCPURegister(base));
472 return 2; 437 return 2;
473 } else if (base == 5) { 438 } else if (base == 5) {
474 // base == rbp means no base register (when mod == 0). 439 // base == rbp means no base register (when mod == 0).
475 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2); 440 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
476 Print("[%s*%d", NameOfCPURegister(index), 1 << scale); 441 Print("[%s*%d", NameOfCPURegister(index), 1 << scale);
477 PrintDisp(disp, "]"); 442 PrintDisp(disp, "]");
478 return 6; 443 return 6;
479 } else if (index != 4 && base != 5) { 444 } else if (index != 4 && base != 5) {
480 // [base+index*scale] 445 // [base+index*scale]
481 Print("[%s+%s*%d]", 446 Print("[%s+%s*%d]", NameOfCPURegister(base), NameOfCPURegister(index),
482 NameOfCPURegister(base),
483 NameOfCPURegister(index),
484 1 << scale); 447 1 << scale);
485 return 2; 448 return 2;
486 } else { 449 } else {
487 UnimplementedInstruction(); 450 UnimplementedInstruction();
488 return 1; 451 return 1;
489 } 452 }
490 } else { 453 } else {
491 Print("[%s]", NameOfCPURegister(rm)); 454 Print("[%s]", NameOfCPURegister(rm));
492 return 1; 455 return 1;
493 } 456 }
494 break; 457 break;
495 case 1: // fall through 458 case 1: // fall through
496 case 2: 459 case 2:
497 if ((rm & 7) == 4) { 460 if ((rm & 7) == 4) {
498 uint8_t sib = *(modrmp + 1); 461 uint8_t sib = *(modrmp + 1);
499 int scale, index, base; 462 int scale, index, base;
500 get_sib(sib, &scale, &index, &base); 463 get_sib(sib, &scale, &index, &base);
501 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2) 464 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2)
502 : *reinterpret_cast<char*>(modrmp + 2); 465 : *reinterpret_cast<char*>(modrmp + 2);
503 if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) { 466 if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
504 Print("[%s", NameOfCPURegister(base)); 467 Print("[%s", NameOfCPURegister(base));
505 PrintDisp(disp, "]"); 468 PrintDisp(disp, "]");
506 } else { 469 } else {
507 Print("[%s+%s*%d", 470 Print("[%s+%s*%d", NameOfCPURegister(base), NameOfCPURegister(index),
508 NameOfCPURegister(base),
509 NameOfCPURegister(index),
510 1 << scale); 471 1 << scale);
511 PrintDisp(disp, "]"); 472 PrintDisp(disp, "]");
512 } 473 }
513 return mod == 2 ? 6 : 3; 474 return mod == 2 ? 6 : 3;
514 } else { 475 } else {
515 // No sib. 476 // No sib.
516 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1) 477 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1)
517 : *reinterpret_cast<char*>(modrmp + 1); 478 : *reinterpret_cast<char*>(modrmp + 1);
518 Print("[%s", NameOfCPURegister(rm)); 479 Print("[%s", NameOfCPURegister(rm));
519 PrintDisp(disp, "]"); 480 PrintDisp(disp, "]");
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 void DisassemblerX64::PrintDisp(int disp, const char* after) { 532 void DisassemblerX64::PrintDisp(int disp, const char* after) {
572 if (-disp > 0) { 533 if (-disp > 0) {
573 Print("-%#x", -disp); 534 Print("-%#x", -disp);
574 } else { 535 } else {
575 Print("+%#x", disp); 536 Print("+%#x", disp);
576 } 537 }
577 if (after != NULL) Print("%s", after); 538 if (after != NULL) Print("%s", after);
578 } 539 }
579 540
580 541
581
582
583 // Returns number of bytes used by machine instruction, including *data byte. 542 // Returns number of bytes used by machine instruction, including *data byte.
584 // Writes immediate instructions to 'tmp_buffer_'. 543 // Writes immediate instructions to 'tmp_buffer_'.
585 int DisassemblerX64::PrintImmediateOp(uint8_t* data) { 544 int DisassemblerX64::PrintImmediateOp(uint8_t* data) {
586 bool byte_size_immediate = (*data & 0x02) != 0; 545 bool byte_size_immediate = (*data & 0x02) != 0;
587 uint8_t modrm = *(data + 1); 546 uint8_t modrm = *(data + 1);
588 int mod, regop, rm; 547 int mod, regop, rm;
589 get_modrm(modrm, &mod, &regop, &rm); 548 get_modrm(modrm, &mod, &regop, &rm);
590 const char* mnem = "Imm???"; 549 const char* mnem = "Imm???";
591 switch (regop) { 550 switch (regop) {
592 case 0: 551 case 0:
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 break; 604 break;
646 case 6: 605 case 6:
647 mnem = "div"; 606 mnem = "div";
648 break; 607 break;
649 case 7: 608 case 7:
650 mnem = "idiv"; 609 mnem = "idiv";
651 break; 610 break;
652 default: 611 default:
653 UnimplementedInstruction(); 612 UnimplementedInstruction();
654 } 613 }
655 Print("%s%c %s", 614 Print("%s%c %s", mnem, operand_size_code(), NameOfCPURegister(rm));
656 mnem,
657 operand_size_code(),
658 NameOfCPURegister(rm));
659 return 2; 615 return 2;
660 } else if (regop == 0) { 616 } else if (regop == 0) {
661 Print("test%c ", operand_size_code()); 617 Print("test%c ", operand_size_code());
662 int count = PrintRightOperand(data + 1); // Use name of 64-bit register. 618 int count = PrintRightOperand(data + 1); // Use name of 64-bit register.
663 Print(","); 619 Print(",");
664 count += PrintImmediate(data + 1 + count, operand_size()); 620 count += PrintImmediate(data + 1 + count, operand_size());
665 return 1 + count; 621 return 1 + count;
666 } else { 622 } else {
667 UnimplementedInstruction(); 623 UnimplementedInstruction();
668 return 2; 624 return 2;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
713 UnimplementedInstruction(); 669 UnimplementedInstruction();
714 return num_bytes; 670 return num_bytes;
715 } 671 }
716 ASSERT(NULL != mnem); 672 ASSERT(NULL != mnem);
717 if (op == 0xD0) { 673 if (op == 0xD0) {
718 imm8 = 1; 674 imm8 = 1;
719 } else if (op == 0xC0) { 675 } else if (op == 0xC0) {
720 imm8 = *(data + 2); 676 imm8 = *(data + 2);
721 num_bytes = 3; 677 num_bytes = 3;
722 } 678 }
723 Print("%s%c %s,", 679 Print("%s%c %s,", mnem, operand_size_code(),
724 mnem, 680 byte_size_operand_ ? NameOfByteCPURegister(rm) : NameOfCPURegister(rm));
725 operand_size_code(),
726 byte_size_operand_ ? NameOfByteCPURegister(rm)
727 : NameOfCPURegister(rm));
728 if (op == 0xD2) { 681 if (op == 0xD2) {
729 Print("cl"); 682 Print("cl");
730 } else { 683 } else {
731 Print("%d", imm8); 684 Print("%d", imm8);
732 } 685 }
733 return num_bytes; 686 return num_bytes;
734 } 687 }
735 688
736 689
737 int DisassemblerX64::PrintRightOperand(uint8_t* modrmp) { 690 int DisassemblerX64::PrintRightOperand(uint8_t* modrmp) {
738 return PrintRightOperandHelper(modrmp, 691 return PrintRightOperandHelper(modrmp, &DisassemblerX64::NameOfCPURegister);
739 &DisassemblerX64::NameOfCPURegister);
740 } 692 }
741 693
742 694
743 int DisassemblerX64::PrintRightByteOperand(uint8_t* modrmp) { 695 int DisassemblerX64::PrintRightByteOperand(uint8_t* modrmp) {
744 return PrintRightOperandHelper(modrmp, 696 return PrintRightOperandHelper(modrmp,
745 &DisassemblerX64::NameOfByteCPURegister); 697 &DisassemblerX64::NameOfByteCPURegister);
746 } 698 }
747 699
748 700
749 int DisassemblerX64::PrintRightXMMOperand(uint8_t* modrmp) { 701 int DisassemblerX64::PrintRightXMMOperand(uint8_t* modrmp) {
750 return PrintRightOperandHelper(modrmp, 702 return PrintRightOperandHelper(modrmp, &DisassemblerX64::NameOfXMMRegister);
751 &DisassemblerX64::NameOfXMMRegister);
752 } 703 }
753 704
754 705
755 // Returns number of bytes used including the current *data. 706 // Returns number of bytes used including the current *data.
756 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'. 707 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
757 int DisassemblerX64::PrintOperands(const char* mnem, 708 int DisassemblerX64::PrintOperands(const char* mnem,
758 OperandType op_order, 709 OperandType op_order,
759 uint8_t* data) { 710 uint8_t* data) {
760 uint8_t modrm = *data; 711 uint8_t modrm = *data;
761 int mod, regop, rm; 712 int mod, regop, rm;
762 get_modrm(modrm, &mod, &regop, &rm); 713 get_modrm(modrm, &mod, &regop, &rm);
763 int advance = 0; 714 int advance = 0;
764 const char* register_name = 715 const char* register_name = byte_size_operand_ ? NameOfByteCPURegister(regop)
765 byte_size_operand_ ? NameOfByteCPURegister(regop) 716 : NameOfCPURegister(regop);
766 : NameOfCPURegister(regop);
767 switch (op_order) { 717 switch (op_order) {
768 case REG_OPER_OP_ORDER: { 718 case REG_OPER_OP_ORDER: {
769 Print("%s%c %s,", mnem, operand_size_code(), register_name); 719 Print("%s%c %s,", mnem, operand_size_code(), register_name);
770 advance = byte_size_operand_ ? PrintRightByteOperand(data) 720 advance = byte_size_operand_ ? PrintRightByteOperand(data)
771 : PrintRightOperand(data); 721 : PrintRightOperand(data);
772 break; 722 break;
773 } 723 }
774 case OPER_REG_OP_ORDER: { 724 case OPER_REG_OP_ORDER: {
775 Print("%s%c ", mnem, operand_size_code()); 725 Print("%s%c ", mnem, operand_size_code());
776 advance = byte_size_operand_ ? PrintRightByteOperand(data) 726 advance = byte_size_operand_ ? PrintRightByteOperand(data)
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
835 Print("set%s%c ", mnem, operand_size_code()); 785 Print("set%s%c ", mnem, operand_size_code());
836 PrintRightByteOperand(data + 2); 786 PrintRightByteOperand(data + 2);
837 return 3; // includes 0x0F 787 return 3; // includes 0x0F
838 } 788 }
839 789
840 790
841 // Returns number of bytes used, including *data. 791 // Returns number of bytes used, including *data.
842 int DisassemblerX64::FPUInstruction(uint8_t* data) { 792 int DisassemblerX64::FPUInstruction(uint8_t* data) {
843 uint8_t escape_opcode = *data; 793 uint8_t escape_opcode = *data;
844 ASSERT(0xD8 == (escape_opcode & 0xF8)); 794 ASSERT(0xD8 == (escape_opcode & 0xF8));
845 uint8_t modrm_byte = *(data+1); 795 uint8_t modrm_byte = *(data + 1);
846 796
847 if (modrm_byte >= 0xC0) { 797 if (modrm_byte >= 0xC0) {
848 return RegisterFPUInstruction(escape_opcode, modrm_byte); 798 return RegisterFPUInstruction(escape_opcode, modrm_byte);
849 } else { 799 } else {
850 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1); 800 return MemoryFPUInstruction(escape_opcode, modrm_byte, data + 1);
851 } 801 }
852 } 802 }
853 803
854 804
855 int DisassemblerX64::MemoryFPUInstruction(int escape_opcode, 805 int DisassemblerX64::MemoryFPUInstruction(int escape_opcode,
856 int modrm_byte, 806 int modrm_byte,
857 uint8_t* modrm_start) { 807 uint8_t* modrm_start) {
858 const char* mnem = "?"; 808 const char* mnem = "?";
859 int regop = (modrm_byte >> 3) & 0x7; // reg/op field of modrm byte. 809 int regop = (modrm_byte >> 3) & 0x7; // reg/op field of modrm byte.
860 switch (escape_opcode) { 810 switch (escape_opcode) {
861 case 0xD9: switch (regop) { 811 case 0xD9:
862 case 0: mnem = "fld_s"; break; 812 switch (regop) {
863 case 3: mnem = "fstp_s"; break; 813 case 0:
864 case 7: mnem = "fstcw"; break; 814 mnem = "fld_s";
865 default: UnimplementedInstruction(); 815 break;
816 case 3:
817 mnem = "fstp_s";
818 break;
819 case 7:
820 mnem = "fstcw";
821 break;
822 default:
823 UnimplementedInstruction();
866 } 824 }
867 break; 825 break;
868 826
869 case 0xDB: switch (regop) { 827 case 0xDB:
870 case 0: mnem = "fild_s"; break; 828 switch (regop) {
871 case 1: mnem = "fisttp_s"; break; 829 case 0:
872 case 2: mnem = "fist_s"; break; 830 mnem = "fild_s";
873 case 3: mnem = "fistp_s"; break; 831 break;
874 default: UnimplementedInstruction(); 832 case 1:
833 mnem = "fisttp_s";
834 break;
835 case 2:
836 mnem = "fist_s";
837 break;
838 case 3:
839 mnem = "fistp_s";
840 break;
841 default:
842 UnimplementedInstruction();
875 } 843 }
876 break; 844 break;
877 845
878 case 0xDD: switch (regop) { 846 case 0xDD:
879 case 0: mnem = "fld_d"; break; 847 switch (regop) {
880 case 3: mnem = "fstp_d"; break; 848 case 0:
881 default: UnimplementedInstruction(); 849 mnem = "fld_d";
850 break;
851 case 3:
852 mnem = "fstp_d";
853 break;
854 default:
855 UnimplementedInstruction();
882 } 856 }
883 break; 857 break;
884 858
885 case 0xDF: switch (regop) { 859 case 0xDF:
886 case 5: mnem = "fild_d"; break; 860 switch (regop) {
887 case 7: mnem = "fistp_d"; break; 861 case 5:
888 default: UnimplementedInstruction(); 862 mnem = "fild_d";
863 break;
864 case 7:
865 mnem = "fistp_d";
866 break;
867 default:
868 UnimplementedInstruction();
889 } 869 }
890 break; 870 break;
891 871
892 default: UnimplementedInstruction(); 872 default:
873 UnimplementedInstruction();
893 } 874 }
894 Print("%s ", mnem); 875 Print("%s ", mnem);
895 int count = PrintRightOperand(modrm_start); 876 int count = PrintRightOperand(modrm_start);
896 return count + 1; 877 return count + 1;
897 } 878 }
898 879
899 int DisassemblerX64::RegisterFPUInstruction(int escape_opcode, 880 int DisassemblerX64::RegisterFPUInstruction(int escape_opcode,
900 uint8_t modrm_byte) { 881 uint8_t modrm_byte) {
901 bool has_register = false; // Is the FPU register encoded in modrm_byte? 882 bool has_register = false; // Is the FPU register encoded in modrm_byte?
902 const char* mnem = "?"; 883 const char* mnem = "?";
903 884
904 switch (escape_opcode) { 885 switch (escape_opcode) {
905 case 0xD8: 886 case 0xD8:
906 UnimplementedInstruction(); 887 UnimplementedInstruction();
907 break; 888 break;
908 889
909 case 0xD9: 890 case 0xD9:
910 switch (modrm_byte & 0xF8) { 891 switch (modrm_byte & 0xF8) {
911 case 0xC0: 892 case 0xC0:
912 mnem = "fld"; 893 mnem = "fld";
913 has_register = true; 894 has_register = true;
914 break; 895 break;
915 case 0xC8: 896 case 0xC8:
916 mnem = "fxch"; 897 mnem = "fxch";
917 has_register = true; 898 has_register = true;
918 break; 899 break;
919 default: 900 default:
920 switch (modrm_byte) { 901 switch (modrm_byte) {
921 case 0xE0: mnem = "fchs"; break; 902 case 0xE0:
922 case 0xE1: mnem = "fabs"; break; 903 mnem = "fchs";
923 case 0xE3: mnem = "fninit"; break; 904 break;
924 case 0xE4: mnem = "ftst"; break; 905 case 0xE1:
925 case 0xE8: mnem = "fld1"; break; 906 mnem = "fabs";
926 case 0xEB: mnem = "fldpi"; break; 907 break;
927 case 0xED: mnem = "fldln2"; break; 908 case 0xE3:
928 case 0xEE: mnem = "fldz"; break; 909 mnem = "fninit";
929 case 0xF0: mnem = "f2xm1"; break; 910 break;
930 case 0xF1: mnem = "fyl2x"; break; 911 case 0xE4:
931 case 0xF2: mnem = "fptan"; break; 912 mnem = "ftst";
932 case 0xF5: mnem = "fprem1"; break; 913 break;
933 case 0xF7: mnem = "fincstp"; break; 914 case 0xE8:
934 case 0xF8: mnem = "fprem"; break; 915 mnem = "fld1";
935 case 0xFD: mnem = "fscale"; break; 916 break;
936 case 0xFE: mnem = "fsin"; break; 917 case 0xEB:
937 case 0xFF: mnem = "fcos"; break; 918 mnem = "fldpi";
938 default: UnimplementedInstruction(); 919 break;
920 case 0xED:
921 mnem = "fldln2";
922 break;
923 case 0xEE:
924 mnem = "fldz";
925 break;
926 case 0xF0:
927 mnem = "f2xm1";
928 break;
929 case 0xF1:
930 mnem = "fyl2x";
931 break;
932 case 0xF2:
933 mnem = "fptan";
934 break;
935 case 0xF5:
936 mnem = "fprem1";
937 break;
938 case 0xF7:
939 mnem = "fincstp";
940 break;
941 case 0xF8:
942 mnem = "fprem";
943 break;
944 case 0xFD:
945 mnem = "fscale";
946 break;
947 case 0xFE:
948 mnem = "fsin";
949 break;
950 case 0xFF:
951 mnem = "fcos";
952 break;
953 default:
954 UnimplementedInstruction();
939 } 955 }
940 } 956 }
941 break; 957 break;
942 958
943 case 0xDA: 959 case 0xDA:
944 if (modrm_byte == 0xE9) { 960 if (modrm_byte == 0xE9) {
945 mnem = "fucompp"; 961 mnem = "fucompp";
946 } else { 962 } else {
947 UnimplementedInstruction(); 963 UnimplementedInstruction();
948 } 964 }
949 break; 965 break;
950 966
951 case 0xDB: 967 case 0xDB:
952 if ((modrm_byte & 0xF8) == 0xE8) { 968 if ((modrm_byte & 0xF8) == 0xE8) {
953 mnem = "fucomi"; 969 mnem = "fucomi";
954 has_register = true; 970 has_register = true;
955 } else if (modrm_byte == 0xE2) { 971 } else if (modrm_byte == 0xE2) {
956 mnem = "fclex"; 972 mnem = "fclex";
957 } else { 973 } else {
958 UnimplementedInstruction(); 974 UnimplementedInstruction();
959 } 975 }
960 break; 976 break;
961 977
962 case 0xDC: 978 case 0xDC:
963 has_register = true; 979 has_register = true;
964 switch (modrm_byte & 0xF8) { 980 switch (modrm_byte & 0xF8) {
965 case 0xC0: mnem = "fadd"; break; 981 case 0xC0:
966 case 0xE8: mnem = "fsub"; break; 982 mnem = "fadd";
967 case 0xC8: mnem = "fmul"; break; 983 break;
968 case 0xF8: mnem = "fdiv"; break; 984 case 0xE8:
969 default: UnimplementedInstruction(); 985 mnem = "fsub";
986 break;
987 case 0xC8:
988 mnem = "fmul";
989 break;
990 case 0xF8:
991 mnem = "fdiv";
992 break;
993 default:
994 UnimplementedInstruction();
970 } 995 }
971 break; 996 break;
972 997
973 case 0xDD: 998 case 0xDD:
974 has_register = true; 999 has_register = true;
975 switch (modrm_byte & 0xF8) { 1000 switch (modrm_byte & 0xF8) {
976 case 0xC0: mnem = "ffree"; break; 1001 case 0xC0:
977 case 0xD8: mnem = "fstp"; break; 1002 mnem = "ffree";
978 default: UnimplementedInstruction(); 1003 break;
1004 case 0xD8:
1005 mnem = "fstp";
1006 break;
1007 default:
1008 UnimplementedInstruction();
979 } 1009 }
980 break; 1010 break;
981 1011
982 case 0xDE: 1012 case 0xDE:
983 if (modrm_byte == 0xD9) { 1013 if (modrm_byte == 0xD9) {
984 mnem = "fcompp"; 1014 mnem = "fcompp";
985 } else { 1015 } else {
986 has_register = true; 1016 has_register = true;
987 switch (modrm_byte & 0xF8) { 1017 switch (modrm_byte & 0xF8) {
988 case 0xC0: mnem = "faddp"; break; 1018 case 0xC0:
989 case 0xE8: mnem = "fsubp"; break; 1019 mnem = "faddp";
990 case 0xC8: mnem = "fmulp"; break; 1020 break;
991 case 0xF8: mnem = "fdivp"; break; 1021 case 0xE8:
992 default: UnimplementedInstruction(); 1022 mnem = "fsubp";
1023 break;
1024 case 0xC8:
1025 mnem = "fmulp";
1026 break;
1027 case 0xF8:
1028 mnem = "fdivp";
1029 break;
1030 default:
1031 UnimplementedInstruction();
993 } 1032 }
994 } 1033 }
995 break; 1034 break;
996 1035
997 case 0xDF: 1036 case 0xDF:
998 if (modrm_byte == 0xE0) { 1037 if (modrm_byte == 0xE0) {
999 mnem = "fnstsw_ax"; 1038 mnem = "fnstsw_ax";
1000 } else if ((modrm_byte & 0xF8) == 0xE8) { 1039 } else if ((modrm_byte & 0xF8) == 0xE8) {
1001 mnem = "fucomip"; 1040 mnem = "fucomip";
1002 has_register = true; 1041 has_register = true;
1003 } 1042 }
1004 break; 1043 break;
1005 1044
1006 default: UnimplementedInstruction(); 1045 default:
1046 UnimplementedInstruction();
1007 } 1047 }
1008 1048
1009 if (has_register) { 1049 if (has_register) {
1010 Print("%s st%d", mnem, modrm_byte & 0x7); 1050 Print("%s st%d", mnem, modrm_byte & 0x7);
1011 } else { 1051 } else {
1012 Print("%s", mnem); 1052 Print("%s", mnem);
1013 } 1053 }
1014 return 2; 1054 return 2;
1015 } 1055 }
1016 1056
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1061 case TWO_OPERANDS_INSTR: 1101 case TWO_OPERANDS_INSTR:
1062 (*data)++; 1102 (*data)++;
1063 (*data) += PrintOperands(idesc.mnem, idesc.op_order_, *data); 1103 (*data) += PrintOperands(idesc.mnem, idesc.op_order_, *data);
1064 break; 1104 break;
1065 1105
1066 case JUMP_CONDITIONAL_SHORT_INSTR: 1106 case JUMP_CONDITIONAL_SHORT_INSTR:
1067 (*data) += JumpConditionalShort(*data); 1107 (*data) += JumpConditionalShort(*data);
1068 break; 1108 break;
1069 1109
1070 case REGISTER_INSTR: 1110 case REGISTER_INSTR:
1071 Print("%s%c %s", 1111 Print("%s%c %s", idesc.mnem, operand_size_code(),
1072 idesc.mnem,
1073 operand_size_code(),
1074 NameOfCPURegister(base_reg(current & 0x07))); 1112 NameOfCPURegister(base_reg(current & 0x07)));
1075 (*data)++; 1113 (*data)++;
1076 break; 1114 break;
1077 case PUSHPOP_INSTR: 1115 case PUSHPOP_INSTR:
1078 Print("%s %s", 1116 Print("%s %s", idesc.mnem, NameOfCPURegister(base_reg(current & 0x07)));
1079 idesc.mnem,
1080 NameOfCPURegister(base_reg(current & 0x07)));
1081 (*data)++; 1117 (*data)++;
1082 break; 1118 break;
1083 case MOVE_REG_INSTR: { 1119 case MOVE_REG_INSTR: {
1084 uint8_t* addr = NULL; 1120 uint8_t* addr = NULL;
1085 switch (operand_size()) { 1121 switch (operand_size()) {
1086 case WORD_SIZE: 1122 case WORD_SIZE:
1087 addr = reinterpret_cast<uint8_t*>( 1123 addr = reinterpret_cast<uint8_t*>(
1088 *reinterpret_cast<int16_t*>(*data + 1)); 1124 *reinterpret_cast<int16_t*>(*data + 1));
1089 (*data) += 3; 1125 (*data) += 3;
1090 break; 1126 break;
1091 case DOUBLEWORD_SIZE: 1127 case DOUBLEWORD_SIZE:
1092 addr = reinterpret_cast<uint8_t*>( 1128 addr = reinterpret_cast<uint8_t*>(
1093 *reinterpret_cast<int32_t*>(*data + 1)); 1129 *reinterpret_cast<int32_t*>(*data + 1));
1094 (*data) += 5; 1130 (*data) += 5;
1095 break; 1131 break;
1096 case QUADWORD_SIZE: 1132 case QUADWORD_SIZE:
1097 addr = reinterpret_cast<uint8_t*>( 1133 addr = reinterpret_cast<uint8_t*>(
1098 *reinterpret_cast<int64_t*>(*data + 1)); 1134 *reinterpret_cast<int64_t*>(*data + 1));
1099 (*data) += 9; 1135 (*data) += 9;
1100 break; 1136 break;
1101 default: 1137 default:
1102 UNREACHABLE(); 1138 UNREACHABLE();
1103 } 1139 }
1104 Print("mov%c %s,", 1140 Print("mov%c %s,", operand_size_code(),
1105 operand_size_code(),
1106 NameOfCPURegister(base_reg(current & 0x07))); 1141 NameOfCPURegister(base_reg(current & 0x07)));
1107 PrintAddress(addr); 1142 PrintAddress(addr);
1108 break; 1143 break;
1109 } 1144 }
1110 1145
1111 case CALL_JUMP_INSTR: { 1146 case CALL_JUMP_INSTR: {
1112 uint8_t* addr = *data + *reinterpret_cast<int32_t*>(*data + 1) + 5; 1147 uint8_t* addr = *data + *reinterpret_cast<int32_t*>(*data + 1) + 5;
1113 Print("%s ", idesc.mnem); 1148 Print("%s ", idesc.mnem);
1114 PrintAddress(addr); 1149 PrintAddress(addr);
1115 (*data) += 5; 1150 (*data) += 5;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1157 uint8_t third_byte = *current; 1192 uint8_t third_byte = *current;
1158 current = data + 3; 1193 current = data + 3;
1159 if (third_byte == 0x17) { 1194 if (third_byte == 0x17) {
1160 get_modrm(*current, &mod, &regop, &rm); 1195 get_modrm(*current, &mod, &regop, &rm);
1161 Print("extractps "); // reg/m32, xmm, imm8 1196 Print("extractps "); // reg/m32, xmm, imm8
1162 current += PrintRightOperand(current); 1197 current += PrintRightOperand(current);
1163 Print(", %s, %d", NameOfCPURegister(regop), (*current) & 3); 1198 Print(", %s, %d", NameOfCPURegister(regop), (*current) & 3);
1164 current += 1; 1199 current += 1;
1165 } else if (third_byte == 0x0b) { 1200 } else if (third_byte == 0x0b) {
1166 get_modrm(*current, &mod, &regop, &rm); 1201 get_modrm(*current, &mod, &regop, &rm);
1167 // roundsd xmm, xmm/m64, imm8 1202 // roundsd xmm, xmm/m64, imm8
1168 Print("roundsd %s, ", NameOfCPURegister(regop)); 1203 Print("roundsd %s, ", NameOfCPURegister(regop));
1169 current += PrintRightOperand(current); 1204 current += PrintRightOperand(current);
1170 Print(", %d", (*current) & 3); 1205 Print(", %d", (*current) & 3);
1171 current += 1; 1206 current += 1;
1172 } else { 1207 } else {
1173 UnimplementedInstruction(); 1208 UnimplementedInstruction();
1174 } 1209 }
1175 } else { 1210 } else {
1176 get_modrm(*current, &mod, &regop, &rm); 1211 get_modrm(*current, &mod, &regop, &rm);
1177 if (opcode == 0x1f) { 1212 if (opcode == 0x1f) {
1178 current++; 1213 current++;
1179 if (rm == 4) { // SIB byte present. 1214 if (rm == 4) { // SIB byte present.
1180 current++; 1215 current++;
1181 } 1216 }
1182 if (mod == 1) { // Byte displacement. 1217 if (mod == 1) { // Byte displacement.
1183 current += 1; 1218 current += 1;
1184 } else if (mod == 2) { // 32-bit displacement. 1219 } else if (mod == 2) { // 32-bit displacement.
1185 current += 4; 1220 current += 4;
1186 } // else no immediate displacement. 1221 } // else no immediate displacement.
1187 Print("nop"); 1222 Print("nop");
1188 } else if (opcode == 0x28) { 1223 } else if (opcode == 0x28) {
1189 Print("movapd %s, ", NameOfXMMRegister(regop)); 1224 Print("movapd %s, ", NameOfXMMRegister(regop));
1190 current += PrintRightXMMOperand(current); 1225 current += PrintRightXMMOperand(current);
1191 } else if (opcode == 0x29) { 1226 } else if (opcode == 0x29) {
1192 Print("movapd "); 1227 Print("movapd ");
1193 current += PrintRightXMMOperand(current); 1228 current += PrintRightXMMOperand(current);
1194 Print(", %s", NameOfXMMRegister(regop)); 1229 Print(", %s", NameOfXMMRegister(regop));
1195 } else if (opcode == 0x6E) { 1230 } else if (opcode == 0x6E) {
1196 Print("mov%c %s,", 1231 Print("mov%c %s,", rex_w() ? 'q' : 'd', NameOfXMMRegister(regop));
1197 rex_w() ? 'q' : 'd',
1198 NameOfXMMRegister(regop));
1199 current += PrintRightOperand(current); 1232 current += PrintRightOperand(current);
1200 } else if (opcode == 0x6F) { 1233 } else if (opcode == 0x6F) {
1201 Print("movdqa %s,", 1234 Print("movdqa %s,", NameOfXMMRegister(regop));
1202 NameOfXMMRegister(regop));
1203 current += PrintRightXMMOperand(current); 1235 current += PrintRightXMMOperand(current);
1204 } else if (opcode == 0x7E) { 1236 } else if (opcode == 0x7E) {
1205 Print("mov%c ", 1237 Print("mov%c ", rex_w() ? 'q' : 'd');
1206 rex_w() ? 'q' : 'd');
1207 current += PrintRightOperand(current); 1238 current += PrintRightOperand(current);
1208 Print(", %s", NameOfXMMRegister(regop)); 1239 Print(", %s", NameOfXMMRegister(regop));
1209 } else if (opcode == 0x7F) { 1240 } else if (opcode == 0x7F) {
1210 Print("movdqa "); 1241 Print("movdqa ");
1211 current += PrintRightXMMOperand(current); 1242 current += PrintRightXMMOperand(current);
1212 Print(", %s", NameOfXMMRegister(regop)); 1243 Print(", %s", NameOfXMMRegister(regop));
1213 } else if (opcode == 0xD6) { 1244 } else if (opcode == 0xD6) {
1214 Print("movq "); 1245 Print("movq ");
1215 current += PrintRightXMMOperand(current); 1246 current += PrintRightXMMOperand(current);
1216 Print(", %s", NameOfXMMRegister(regop)); 1247 Print(", %s", NameOfXMMRegister(regop));
1217 } else if (opcode == 0x50) { 1248 } else if (opcode == 0x50) {
1218 Print("movmskpd %s,", NameOfCPURegister(regop)); 1249 Print("movmskpd %s,", NameOfCPURegister(regop));
1219 current += PrintRightXMMOperand(current); 1250 current += PrintRightXMMOperand(current);
1220 } else { 1251 } else {
1221 const char* mnemonic = "?"; 1252 const char* mnemonic = "?";
1222 if (opcode == 0x14) { 1253 if (opcode == 0x14) {
1223 mnemonic = "unpcklpd"; 1254 mnemonic = "unpcklpd";
1224 } else if (opcode == 0x15) { 1255 } else if (opcode == 0x15) {
1225 mnemonic = "unpckhpd"; 1256 mnemonic = "unpckhpd";
1226 } else if (opcode == 0x54) { 1257 } else if (opcode == 0x54) {
1227 mnemonic = "andpd"; 1258 mnemonic = "andpd";
1228 } else if (opcode == 0x56) { 1259 } else if (opcode == 0x56) {
1229 mnemonic = "orpd"; 1260 mnemonic = "orpd";
1230 } else if (opcode == 0x57) { 1261 } else if (opcode == 0x57) {
1231 mnemonic = "xorpd"; 1262 mnemonic = "xorpd";
1232 } else if (opcode == 0x2E) { 1263 } else if (opcode == 0x2E) {
1233 mnemonic = "ucomisd"; 1264 mnemonic = "ucomisd";
1234 } else if (opcode == 0x2F) { 1265 } else if (opcode == 0x2F) {
1235 mnemonic = "comisd"; 1266 mnemonic = "comisd";
1236 } else if (opcode == 0xFE) { 1267 } else if (opcode == 0xFE) {
1237 mnemonic = "paddd"; 1268 mnemonic = "paddd";
1238 } else if (opcode == 0xFA) { 1269 } else if (opcode == 0xFA) {
1239 mnemonic = "psubd"; 1270 mnemonic = "psubd";
1240 } else if (opcode == 0x58) { 1271 } else if (opcode == 0x58) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1279 // CVTSI2SD: integer to XMM double conversion. 1310 // CVTSI2SD: integer to XMM double conversion.
1280 int mod, regop, rm; 1311 int mod, regop, rm;
1281 get_modrm(*current, &mod, &regop, &rm); 1312 get_modrm(*current, &mod, &regop, &rm);
1282 Print("%sd %s,", mnemonic, NameOfXMMRegister(regop)); 1313 Print("%sd %s,", mnemonic, NameOfXMMRegister(regop));
1283 current += PrintRightOperand(current); 1314 current += PrintRightOperand(current);
1284 } else if (opcode == 0x2C) { 1315 } else if (opcode == 0x2C) {
1285 // CVTTSD2SI: 1316 // CVTTSD2SI:
1286 // Convert with truncation scalar double-precision FP to integer. 1317 // Convert with truncation scalar double-precision FP to integer.
1287 int mod, regop, rm; 1318 int mod, regop, rm;
1288 get_modrm(*current, &mod, &regop, &rm); 1319 get_modrm(*current, &mod, &regop, &rm);
1289 Print("cvttsd2si%c %s,", 1320 Print("cvttsd2si%c %s,", operand_size_code(), NameOfCPURegister(regop));
1290 operand_size_code(), NameOfCPURegister(regop));
1291 current += PrintRightXMMOperand(current); 1321 current += PrintRightXMMOperand(current);
1292 } else if (opcode == 0x2D) { 1322 } else if (opcode == 0x2D) {
1293 // CVTSD2SI: Convert scalar double-precision FP to integer. 1323 // CVTSD2SI: Convert scalar double-precision FP to integer.
1294 int mod, regop, rm; 1324 int mod, regop, rm;
1295 get_modrm(*current, &mod, &regop, &rm); 1325 get_modrm(*current, &mod, &regop, &rm);
1296 Print("cvtsd2si%c %s,", 1326 Print("cvtsd2si%c %s,", operand_size_code(), NameOfCPURegister(regop));
1297 operand_size_code(), NameOfCPURegister(regop));
1298 current += PrintRightXMMOperand(current); 1327 current += PrintRightXMMOperand(current);
1299 } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) { 1328 } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
1300 // XMM arithmetic. Mnemonic was retrieved at the start of this function. 1329 // XMM arithmetic. Mnemonic was retrieved at the start of this function.
1301 int mod, regop, rm; 1330 int mod, regop, rm;
1302 get_modrm(*current, &mod, &regop, &rm); 1331 get_modrm(*current, &mod, &regop, &rm);
1303 Print("%s %s,", mnemonic, NameOfXMMRegister(regop)); 1332 Print("%s %s,", mnemonic, NameOfXMMRegister(regop));
1304 current += PrintRightXMMOperand(current); 1333 current += PrintRightXMMOperand(current);
1305 } else { 1334 } else {
1306 UnimplementedInstruction(); 1335 UnimplementedInstruction();
1307 } 1336 }
(...skipping 15 matching lines...) Expand all
1323 // CVTSI2SS: integer to XMM single conversion. 1352 // CVTSI2SS: integer to XMM single conversion.
1324 int mod, regop, rm; 1353 int mod, regop, rm;
1325 get_modrm(*current, &mod, &regop, &rm); 1354 get_modrm(*current, &mod, &regop, &rm);
1326 Print("%ss %s,", mnemonic, NameOfXMMRegister(regop)); 1355 Print("%ss %s,", mnemonic, NameOfXMMRegister(regop));
1327 current += PrintRightOperand(current); 1356 current += PrintRightOperand(current);
1328 } else if (opcode == 0x2C) { 1357 } else if (opcode == 0x2C) {
1329 // CVTTSS2SI: 1358 // CVTTSS2SI:
1330 // Convert with truncation scalar single-precision FP to dword integer. 1359 // Convert with truncation scalar single-precision FP to dword integer.
1331 int mod, regop, rm; 1360 int mod, regop, rm;
1332 get_modrm(*current, &mod, &regop, &rm); 1361 get_modrm(*current, &mod, &regop, &rm);
1333 Print("cvttss2si%c %s,", 1362 Print("cvttss2si%c %s,", operand_size_code(), NameOfCPURegister(regop));
1334 operand_size_code(), NameOfCPURegister(regop));
1335 current += PrintRightXMMOperand(current); 1363 current += PrintRightXMMOperand(current);
1336 } else if (opcode == 0x5A) { 1364 } else if (opcode == 0x5A) {
1337 // CVTSS2SD: 1365 // CVTSS2SD:
1338 // Convert scalar single-precision FP to scalar double-precision FP. 1366 // Convert scalar single-precision FP to scalar double-precision FP.
1339 int mod, regop, rm; 1367 int mod, regop, rm;
1340 get_modrm(*current, &mod, &regop, &rm); 1368 get_modrm(*current, &mod, &regop, &rm);
1341 Print("cvtss2sd %s,", NameOfXMMRegister(regop)); 1369 Print("cvtss2sd %s,", NameOfXMMRegister(regop));
1342 current += PrintRightXMMOperand(current); 1370 current += PrintRightXMMOperand(current);
1343 } else if (opcode == 0x7E) { 1371 } else if (opcode == 0x7E) {
1344 int mod, regop, rm; 1372 int mod, regop, rm;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1411 current += PrintOperands(idesc.mnem, idesc.op_order_, current); 1439 current += PrintOperands(idesc.mnem, idesc.op_order_, current);
1412 1440
1413 } else if (opcode == 0x12 || opcode == 0x14 || opcode == 0x15 || 1441 } else if (opcode == 0x12 || opcode == 0x14 || opcode == 0x15 ||
1414 opcode == 0x16 || opcode == 0x51 || opcode == 0x52 || 1442 opcode == 0x16 || opcode == 0x51 || opcode == 0x52 ||
1415 opcode == 0x53 || opcode == 0x54 || opcode == 0x56 || 1443 opcode == 0x53 || opcode == 0x54 || opcode == 0x56 ||
1416 opcode == 0x57 || opcode == 0x58 || opcode == 0x59 || 1444 opcode == 0x57 || opcode == 0x58 || opcode == 0x59 ||
1417 opcode == 0x5A || opcode == 0x5C || opcode == 0x5D || 1445 opcode == 0x5A || opcode == 0x5C || opcode == 0x5D ||
1418 opcode == 0x5E || opcode == 0x5F) { 1446 opcode == 0x5E || opcode == 0x5F) {
1419 const char* mnemonic = NULL; 1447 const char* mnemonic = NULL;
1420 switch (opcode) { 1448 switch (opcode) {
1421 case 0x12: mnemonic = "movhlps"; break; 1449 case 0x12:
1422 case 0x14: mnemonic = "unpcklps"; break; 1450 mnemonic = "movhlps";
1423 case 0x15: mnemonic = "unpckhps"; break; 1451 break;
1424 case 0x16: mnemonic = "movlhps"; break; 1452 case 0x14:
1425 case 0x51: mnemonic = "sqrtps"; break; 1453 mnemonic = "unpcklps";
1426 case 0x52: mnemonic = "rsqrtps"; break; 1454 break;
1427 case 0x53: mnemonic = "rcpps"; break; 1455 case 0x15:
1428 case 0x54: mnemonic = "andps"; break; 1456 mnemonic = "unpckhps";
1429 case 0x56: mnemonic = "orps"; break; 1457 break;
1430 case 0x57: mnemonic = "xorps"; break; 1458 case 0x16:
1431 case 0x58: mnemonic = "addps"; break; 1459 mnemonic = "movlhps";
1432 case 0x59: mnemonic = "mulps"; break; 1460 break;
1433 case 0x5A: mnemonic = "cvtsd2ss"; break; 1461 case 0x51:
1434 case 0x5C: mnemonic = "subps"; break; 1462 mnemonic = "sqrtps";
1435 case 0x5D: mnemonic = "minps"; break; 1463 break;
1436 case 0x5E: mnemonic = "divps"; break; 1464 case 0x52:
1437 case 0x5F: mnemonic = "maxps"; break; 1465 mnemonic = "rsqrtps";
1438 default: UNREACHABLE(); 1466 break;
1467 case 0x53:
1468 mnemonic = "rcpps";
1469 break;
1470 case 0x54:
1471 mnemonic = "andps";
1472 break;
1473 case 0x56:
1474 mnemonic = "orps";
1475 break;
1476 case 0x57:
1477 mnemonic = "xorps";
1478 break;
1479 case 0x58:
1480 mnemonic = "addps";
1481 break;
1482 case 0x59:
1483 mnemonic = "mulps";
1484 break;
1485 case 0x5A:
1486 mnemonic = "cvtsd2ss";
1487 break;
1488 case 0x5C:
1489 mnemonic = "subps";
1490 break;
1491 case 0x5D:
1492 mnemonic = "minps";
1493 break;
1494 case 0x5E:
1495 mnemonic = "divps";
1496 break;
1497 case 0x5F:
1498 mnemonic = "maxps";
1499 break;
1500 default:
1501 UNREACHABLE();
1439 } 1502 }
1440 int mod, regop, rm; 1503 int mod, regop, rm;
1441 get_modrm(*current, &mod, &regop, &rm); 1504 get_modrm(*current, &mod, &regop, &rm);
1442 Print("%s %s, ", mnemonic, NameOfXMMRegister(regop)); 1505 Print("%s %s, ", mnemonic, NameOfXMMRegister(regop));
1443 current += PrintRightXMMOperand(current); 1506 current += PrintRightXMMOperand(current);
1444 } else if (opcode == 0xC2 || opcode == 0xC6) { 1507 } else if (opcode == 0xC2 || opcode == 0xC6) {
1445 int mod, regop, rm; 1508 int mod, regop, rm;
1446 get_modrm(*current, &mod, &regop, &rm); 1509 get_modrm(*current, &mod, &regop, &rm);
1447 if (opcode == 0xC2) { 1510 if (opcode == 0xC2) {
1448 Print("cmpps %s, ", NameOfXMMRegister(regop)); 1511 Print("cmpps %s, ", NameOfXMMRegister(regop));
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1555 1618
1556 if (!processed) { 1619 if (!processed) {
1557 switch (*data) { 1620 switch (*data) {
1558 case 0xC2: 1621 case 0xC2:
1559 Print("ret "); 1622 Print("ret ");
1560 PrintImmediateValue(*reinterpret_cast<uint16_t*>(data + 1)); 1623 PrintImmediateValue(*reinterpret_cast<uint16_t*>(data + 1));
1561 data += 3; 1624 data += 3;
1562 break; 1625 break;
1563 1626
1564 case 0xC8: 1627 case 0xC8:
1565 Print("enter %d, %d", 1628 Print("enter %d, %d", *reinterpret_cast<uint16_t*>(data + 1), data[3]);
1566 *reinterpret_cast<uint16_t*>(data + 1),
1567 data[3]);
1568 data += 4; 1629 data += 4;
1569 break; 1630 break;
1570 1631
1571 case 0x69: // fall through 1632 case 0x69: // fall through
1572 case 0x6B: { 1633 case 0x6B: {
1573 int mod, regop, rm; 1634 int mod, regop, rm;
1574 get_modrm(*(data + 1), &mod, &regop, &rm); 1635 get_modrm(*(data + 1), &mod, &regop, &rm);
1575 int32_t imm = *data == 0x6B ? *(data + 2) 1636 int32_t imm =
1576 : *reinterpret_cast<int32_t*>(data + 2); 1637 *data == 0x6B ? *(data + 2) : *reinterpret_cast<int32_t*>(data + 2);
1577 Print("imul%c %s,%s,", 1638 Print("imul%c %s,%s,", operand_size_code(), NameOfCPURegister(regop),
1578 operand_size_code(),
1579 NameOfCPURegister(regop),
1580 NameOfCPURegister(rm)); 1639 NameOfCPURegister(rm));
1581 PrintImmediateValue(imm); 1640 PrintImmediateValue(imm);
1582 data += 2 + (*data == 0x6B ? 1 : 4); 1641 data += 2 + (*data == 0x6B ? 1 : 4);
1583 break; 1642 break;
1584 } 1643 }
1585 1644
1586 case 0x81: // fall through 1645 case 0x81: // fall through
1587 case 0x83: // 0x81 with sign extension bit set 1646 case 0x83: // 0x81 with sign extension bit set
1588 data += PrintImmediateOp(data); 1647 data += PrintImmediateOp(data);
1589 break; 1648 break;
1590 1649
1591 case 0x0F: 1650 case 0x0F:
1592 data += TwoByteOpcodeInstruction(data); 1651 data += TwoByteOpcodeInstruction(data);
1593 break; 1652 break;
1594 1653
1595 case 0x8F: { 1654 case 0x8F: {
1596 data++; 1655 data++;
1597 int mod, regop, rm; 1656 int mod, regop, rm;
1598 get_modrm(*data, &mod, &regop, &rm); 1657 get_modrm(*data, &mod, &regop, &rm);
1599 if (regop == 0) { 1658 if (regop == 0) {
1600 Print("pop "); 1659 Print("pop ");
1601 data += PrintRightOperand(data); 1660 data += PrintRightOperand(data);
1602 } 1661 }
1603 } 1662 } break;
1604 break;
1605 1663
1606 case 0xFF: { 1664 case 0xFF: {
1607 data++; 1665 data++;
1608 int mod, regop, rm; 1666 int mod, regop, rm;
1609 get_modrm(*data, &mod, &regop, &rm); 1667 get_modrm(*data, &mod, &regop, &rm);
1610 const char* mnem = NULL; 1668 const char* mnem = NULL;
1611 switch (regop) { 1669 switch (regop) {
1612 case 0: 1670 case 0:
1613 mnem = "inc"; 1671 mnem = "inc";
1614 break; 1672 break;
(...skipping 11 matching lines...) Expand all
1626 break; 1684 break;
1627 default: 1685 default:
1628 mnem = "???"; 1686 mnem = "???";
1629 } 1687 }
1630 if (regop <= 1) { 1688 if (regop <= 1) {
1631 Print("%s%c ", mnem, operand_size_code()); 1689 Print("%s%c ", mnem, operand_size_code());
1632 } else { 1690 } else {
1633 Print("%s ", mnem); 1691 Print("%s ", mnem);
1634 } 1692 }
1635 data += PrintRightOperand(data); 1693 data += PrintRightOperand(data);
1636 } 1694 } break;
1637 break;
1638 1695
1639 case 0xC7: // imm32, fall through 1696 case 0xC7: // imm32, fall through
1640 case 0xC6: // imm8 1697 case 0xC6: // imm8
1641 { 1698 {
1642 bool is_byte = *data == 0xC6; 1699 bool is_byte = *data == 0xC6;
1643 data++; 1700 data++;
1644 if (is_byte) { 1701 if (is_byte) {
1645 Print("movb "); 1702 Print("movb ");
1646 data += PrintRightByteOperand(data); 1703 data += PrintRightByteOperand(data);
1647 int32_t imm = *data; 1704 int32_t imm = *data;
1648 Print(","); 1705 Print(",");
1649 PrintImmediateValue(imm); 1706 PrintImmediateValue(imm);
1650 data++; 1707 data++;
1651 } else { 1708 } else {
1652 Print("mov%c ", operand_size_code()); 1709 Print("mov%c ", operand_size_code());
1653 data += PrintRightOperand(data); 1710 data += PrintRightOperand(data);
1654 int32_t imm = *reinterpret_cast<int32_t*>(data); 1711 int32_t imm = *reinterpret_cast<int32_t*>(data);
1655 Print(","); 1712 Print(",");
1656 PrintImmediateValue(imm); 1713 PrintImmediateValue(imm);
1657 data += 4; 1714 data += 4;
1658 } 1715 }
1659 } 1716 } break;
1660 break;
1661 1717
1662 case 0x80: { 1718 case 0x80: {
1663 data++; 1719 data++;
1664 Print("cmpb "); 1720 Print("cmpb ");
1665 data += PrintRightByteOperand(data); 1721 data += PrintRightByteOperand(data);
1666 int32_t imm = *data; 1722 int32_t imm = *data;
1667 Print(","); 1723 Print(",");
1668 PrintImmediateValue(imm); 1724 PrintImmediateValue(imm);
1669 data++; 1725 data++;
1670 } 1726 } break;
1671 break;
1672 1727
1673 case 0x88: // 8bit, fall through 1728 case 0x88: // 8bit, fall through
1674 case 0x89: // 32bit 1729 case 0x89: // 32bit
1675 { 1730 {
1676 bool is_byte = *data == 0x88; 1731 bool is_byte = *data == 0x88;
1677 int mod, regop, rm; 1732 int mod, regop, rm;
1678 data++; 1733 data++;
1679 get_modrm(*data, &mod, &regop, &rm); 1734 get_modrm(*data, &mod, &regop, &rm);
1680 if (is_byte) { 1735 if (is_byte) {
1681 Print("movb "); 1736 Print("movb ");
1682 data += PrintRightByteOperand(data); 1737 data += PrintRightByteOperand(data);
1683 Print(",%s", NameOfByteCPURegister(regop)); 1738 Print(",%s", NameOfByteCPURegister(regop));
1684 } else { 1739 } else {
1685 Print("mov%c ", operand_size_code()); 1740 Print("mov%c ", operand_size_code());
1686 data += PrintRightOperand(data); 1741 data += PrintRightOperand(data);
1687 Print(",%s", NameOfCPURegister(regop)); 1742 Print(",%s", NameOfCPURegister(regop));
1688 } 1743 }
1689 } 1744 } break;
1690 break;
1691 1745
1692 case 0x90: 1746 case 0x90:
1693 case 0x91: 1747 case 0x91:
1694 case 0x92: 1748 case 0x92:
1695 case 0x93: 1749 case 0x93:
1696 case 0x94: 1750 case 0x94:
1697 case 0x95: 1751 case 0x95:
1698 case 0x96: 1752 case 0x96:
1699 case 0x97: { 1753 case 0x97: {
1700 int reg = (*data & 0x7) | (rex_b() ? 8 : 0); 1754 int reg = (*data & 0x7) | (rex_b() ? 8 : 0);
1701 if (reg == 0) { 1755 if (reg == 0) {
1702 Print("nop"); // Common name for xchg rax,rax. 1756 Print("nop"); // Common name for xchg rax,rax.
1703 } else { 1757 } else {
1704 Print("xchg%c rax, %s", operand_size_code(), NameOfCPURegister(reg)); 1758 Print("xchg%c rax, %s", operand_size_code(), NameOfCPURegister(reg));
1705 } 1759 }
1706 data++; 1760 data++;
1707 } 1761 } break;
1708 break;
1709 case 0xB0: 1762 case 0xB0:
1710 case 0xB1: 1763 case 0xB1:
1711 case 0xB2: 1764 case 0xB2:
1712 case 0xB3: 1765 case 0xB3:
1713 case 0xB4: 1766 case 0xB4:
1714 case 0xB5: 1767 case 0xB5:
1715 case 0xB6: 1768 case 0xB6:
1716 case 0xB7: 1769 case 0xB7:
1717 case 0xB8: 1770 case 0xB8:
1718 case 0xB9: 1771 case 0xB9:
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1757 case 0x6A: 1810 case 0x6A:
1758 Print("push "); 1811 Print("push ");
1759 PrintImmediateValue(*reinterpret_cast<int8_t*>(data + 1)); 1812 PrintImmediateValue(*reinterpret_cast<int8_t*>(data + 1));
1760 data += 2; 1813 data += 2;
1761 break; 1814 break;
1762 1815
1763 case 0xA1: // Fall through. 1816 case 0xA1: // Fall through.
1764 case 0xA3: 1817 case 0xA3:
1765 switch (operand_size()) { 1818 switch (operand_size()) {
1766 case DOUBLEWORD_SIZE: { 1819 case DOUBLEWORD_SIZE: {
1767 PrintAddress( 1820 PrintAddress(reinterpret_cast<uint8_t*>(
1768 reinterpret_cast<uint8_t*>( 1821 *reinterpret_cast<int32_t*>(data + 1)));
1769 *reinterpret_cast<int32_t*>(data + 1)));
1770 if (*data == 0xA1) { // Opcode 0xA1 1822 if (*data == 0xA1) { // Opcode 0xA1
1771 Print("movzxlq rax,("); 1823 Print("movzxlq rax,(");
1772 PrintAddress( 1824 PrintAddress(reinterpret_cast<uint8_t*>(
1773 reinterpret_cast<uint8_t*>( 1825 *reinterpret_cast<int32_t*>(data + 1)));
1774 *reinterpret_cast<int32_t*>(data + 1)));
1775 Print(")"); 1826 Print(")");
1776 } else { // Opcode 0xA3 1827 } else { // Opcode 0xA3
1777 Print("movzxlq ("); 1828 Print("movzxlq (");
1778 PrintAddress( 1829 PrintAddress(reinterpret_cast<uint8_t*>(
1779 reinterpret_cast<uint8_t*>( 1830 *reinterpret_cast<int32_t*>(data + 1)));
1780 *reinterpret_cast<int32_t*>(data + 1)));
1781 Print("),rax"); 1831 Print("),rax");
1782 } 1832 }
1783 data += 5; 1833 data += 5;
1784 break; 1834 break;
1785 } 1835 }
1786 case QUADWORD_SIZE: { 1836 case QUADWORD_SIZE: {
1787 // New x64 instruction mov rax,(imm_64). 1837 // New x64 instruction mov rax,(imm_64).
1788 if (*data == 0xA1) { // Opcode 0xA1 1838 if (*data == 0xA1) { // Opcode 0xA1
1789 Print("movq rax,("); 1839 Print("movq rax,(");
1790 PrintAddress(*reinterpret_cast<uint8_t**>(data + 1)); 1840 PrintAddress(*reinterpret_cast<uint8_t**>(data + 1));
1791 Print(")"); 1841 Print(")");
1792 } else { // Opcode 0xA3 1842 } else { // Opcode 0xA3
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1871 1921
1872 ASSERT(buffer_[buffer_pos_] == '\0'); 1922 ASSERT(buffer_[buffer_pos_] == '\0');
1873 1923
1874 int instr_len = data - reinterpret_cast<uint8_t*>(pc); 1924 int instr_len = data - reinterpret_cast<uint8_t*>(pc);
1875 ASSERT(instr_len > 0); // Ensure progress. 1925 ASSERT(instr_len > 0); // Ensure progress.
1876 1926
1877 return instr_len; 1927 return instr_len;
1878 } 1928 }
1879 1929
1880 1930
1881 void Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size, 1931 void Disassembler::DecodeInstruction(char* hex_buffer,
1882 char* human_buffer, intptr_t human_size, 1932 intptr_t hex_size,
1883 int* out_instr_len, const Code& code, 1933 char* human_buffer,
1884 Object** object, uword pc) { 1934 intptr_t human_size,
1935 int* out_instr_len,
1936 const Code& code,
1937 Object** object,
1938 uword pc) {
1885 ASSERT(hex_size > 0); 1939 ASSERT(hex_size > 0);
1886 ASSERT(human_size > 0); 1940 ASSERT(human_size > 0);
1887 DisassemblerX64 decoder(human_buffer, human_size); 1941 DisassemblerX64 decoder(human_buffer, human_size);
1888 int instruction_length = decoder.InstructionDecode(pc); 1942 int instruction_length = decoder.InstructionDecode(pc);
1889 uint8_t* pc_ptr = reinterpret_cast<uint8_t*>(pc); 1943 uint8_t* pc_ptr = reinterpret_cast<uint8_t*>(pc);
1890 int hex_index = 0; 1944 int hex_index = 0;
1891 int remaining_size = hex_size - hex_index; 1945 int remaining_size = hex_size - hex_index;
1892 for (int i = 0; (i < instruction_length) && (remaining_size > 2); ++i) { 1946 for (int i = 0; (i < instruction_length) && (remaining_size > 2); ++i) {
1893 OS::SNPrint(&hex_buffer[hex_index], remaining_size, "%02x", pc_ptr[i]); 1947 OS::SNPrint(&hex_buffer[hex_index], remaining_size, "%02x", pc_ptr[i]);
1894 hex_index += 2; 1948 hex_index += 2;
(...skipping 11 matching lines...) Expand all
1906 *object = NULL; 1960 *object = NULL;
1907 } 1961 }
1908 } 1962 }
1909 } 1963 }
1910 1964
1911 #endif // !PRODUCT 1965 #endif // !PRODUCT
1912 1966
1913 } // namespace dart 1967 } // namespace dart
1914 1968
1915 #endif // defined TARGET_ARCH_X64 1969 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/disassembler_mips.cc ('k') | runtime/vm/double_conversion.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698