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

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

Issue 2974233002: VM: Re-format to use at most one newline between functions (Closed)
Patch Set: Rebase and merge Created 3 years, 5 months 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_test.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 20 matching lines...) Expand all
31 31
32 //------------------------------------------------------------------ 32 //------------------------------------------------------------------
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
42 static const ByteMnemonic two_operands_instr[] = { 41 static const ByteMnemonic two_operands_instr[] = {
43 {0x00, BYTE_OPER_REG_OP_ORDER, "add"}, 42 {0x00, BYTE_OPER_REG_OP_ORDER, "add"},
44 {0x01, OPER_REG_OP_ORDER, "add"}, 43 {0x01, OPER_REG_OP_ORDER, "add"},
45 {0x02, BYTE_REG_OPER_OP_ORDER, "add"}, 44 {0x02, BYTE_REG_OPER_OP_ORDER, "add"},
46 {0x03, REG_OPER_OP_ORDER, "add"}, 45 {0x03, REG_OPER_OP_ORDER, "add"},
47 {0x08, BYTE_OPER_REG_OP_ORDER, "or"}, 46 {0x08, BYTE_OPER_REG_OP_ORDER, "or"},
48 {0x09, OPER_REG_OP_ORDER, "or"}, 47 {0x09, OPER_REG_OP_ORDER, "or"},
49 {0x0A, BYTE_REG_OPER_OP_ORDER, "or"}, 48 {0x0A, BYTE_REG_OPER_OP_ORDER, "or"},
50 {0x0B, REG_OPER_OP_ORDER, "or"}, 49 {0x0B, REG_OPER_OP_ORDER, "or"},
51 {0x10, BYTE_OPER_REG_OP_ORDER, "adc"}, 50 {0x10, BYTE_OPER_REG_OP_ORDER, "adc"},
(...skipping 25 matching lines...) Expand all
77 {0x85, REG_OPER_OP_ORDER, "test"}, 76 {0x85, REG_OPER_OP_ORDER, "test"},
78 {0x86, BYTE_REG_OPER_OP_ORDER, "xchg"}, 77 {0x86, BYTE_REG_OPER_OP_ORDER, "xchg"},
79 {0x87, REG_OPER_OP_ORDER, "xchg"}, 78 {0x87, REG_OPER_OP_ORDER, "xchg"},
80 {0x88, BYTE_OPER_REG_OP_ORDER, "mov"}, 79 {0x88, BYTE_OPER_REG_OP_ORDER, "mov"},
81 {0x89, OPER_REG_OP_ORDER, "mov"}, 80 {0x89, OPER_REG_OP_ORDER, "mov"},
82 {0x8A, BYTE_REG_OPER_OP_ORDER, "mov"}, 81 {0x8A, BYTE_REG_OPER_OP_ORDER, "mov"},
83 {0x8B, REG_OPER_OP_ORDER, "mov"}, 82 {0x8B, REG_OPER_OP_ORDER, "mov"},
84 {0x8D, REG_OPER_OP_ORDER, "lea"}, 83 {0x8D, REG_OPER_OP_ORDER, "lea"},
85 {-1, UNSET_OP_ORDER, ""}}; 84 {-1, UNSET_OP_ORDER, ""}};
86 85
87
88 static const ByteMnemonic zero_operands_instr[] = { 86 static const ByteMnemonic zero_operands_instr[] = {
89 {0xC3, UNSET_OP_ORDER, "ret"}, {0xC9, UNSET_OP_ORDER, "leave"}, 87 {0xC3, UNSET_OP_ORDER, "ret"}, {0xC9, UNSET_OP_ORDER, "leave"},
90 {0xF4, UNSET_OP_ORDER, "hlt"}, {0xFC, UNSET_OP_ORDER, "cld"}, 88 {0xF4, UNSET_OP_ORDER, "hlt"}, {0xFC, UNSET_OP_ORDER, "cld"},
91 {0xCC, UNSET_OP_ORDER, "int3"}, {0x60, UNSET_OP_ORDER, "pushad"}, 89 {0xCC, UNSET_OP_ORDER, "int3"}, {0x60, UNSET_OP_ORDER, "pushad"},
92 {0x61, UNSET_OP_ORDER, "popad"}, {0x9C, UNSET_OP_ORDER, "pushfd"}, 90 {0x61, UNSET_OP_ORDER, "popad"}, {0x9C, UNSET_OP_ORDER, "pushfd"},
93 {0x9D, UNSET_OP_ORDER, "popfd"}, {0x9E, UNSET_OP_ORDER, "sahf"}, 91 {0x9D, UNSET_OP_ORDER, "popfd"}, {0x9E, UNSET_OP_ORDER, "sahf"},
94 {0x99, UNSET_OP_ORDER, "cdq"}, {0x9B, UNSET_OP_ORDER, "fwait"}, 92 {0x99, UNSET_OP_ORDER, "cdq"}, {0x9B, UNSET_OP_ORDER, "fwait"},
95 {0xA4, UNSET_OP_ORDER, "movs"}, {0xA5, UNSET_OP_ORDER, "movs"}, 93 {0xA4, UNSET_OP_ORDER, "movs"}, {0xA5, UNSET_OP_ORDER, "movs"},
96 {0xA6, UNSET_OP_ORDER, "cmps"}, {0xA7, UNSET_OP_ORDER, "cmps"}, 94 {0xA6, UNSET_OP_ORDER, "cmps"}, {0xA7, UNSET_OP_ORDER, "cmps"},
97 {-1, UNSET_OP_ORDER, ""}}; 95 {-1, UNSET_OP_ORDER, ""}};
98 96
99
100 static const ByteMnemonic call_jump_instr[] = {{0xE8, UNSET_OP_ORDER, "call"}, 97 static const ByteMnemonic call_jump_instr[] = {{0xE8, UNSET_OP_ORDER, "call"},
101 {0xE9, UNSET_OP_ORDER, "jmp"}, 98 {0xE9, UNSET_OP_ORDER, "jmp"},
102 {-1, UNSET_OP_ORDER, ""}}; 99 {-1, UNSET_OP_ORDER, ""}};
103 100
104
105 static const ByteMnemonic short_immediate_instr[] = { 101 static const ByteMnemonic short_immediate_instr[] = {
106 {0x05, UNSET_OP_ORDER, "add"}, {0x0D, UNSET_OP_ORDER, "or"}, 102 {0x05, UNSET_OP_ORDER, "add"}, {0x0D, UNSET_OP_ORDER, "or"},
107 {0x15, UNSET_OP_ORDER, "adc"}, {0x1D, UNSET_OP_ORDER, "sbb"}, 103 {0x15, UNSET_OP_ORDER, "adc"}, {0x1D, UNSET_OP_ORDER, "sbb"},
108 {0x25, UNSET_OP_ORDER, "and"}, {0x2D, UNSET_OP_ORDER, "sub"}, 104 {0x25, UNSET_OP_ORDER, "and"}, {0x2D, UNSET_OP_ORDER, "sub"},
109 {0x35, UNSET_OP_ORDER, "xor"}, {0x3D, UNSET_OP_ORDER, "cmp"}, 105 {0x35, UNSET_OP_ORDER, "xor"}, {0x3D, UNSET_OP_ORDER, "cmp"},
110 {-1, UNSET_OP_ORDER, ""}}; 106 {-1, UNSET_OP_ORDER, ""}};
111 107
112
113 static const char* const conditional_code_suffix[] = { 108 static const char* const conditional_code_suffix[] = {
114 "o", "no", "c", "nc", "z", "nz", "na", "a", 109 "o", "no", "c", "nc", "z", "nz", "na", "a",
115 "s", "ns", "pe", "po", "l", "ge", "le", "g"}; 110 "s", "ns", "pe", "po", "l", "ge", "le", "g"};
116 111
117
118 enum InstructionType { 112 enum InstructionType {
119 NO_INSTR, 113 NO_INSTR,
120 ZERO_OPERANDS_INSTR, 114 ZERO_OPERANDS_INSTR,
121 TWO_OPERANDS_INSTR, 115 TWO_OPERANDS_INSTR,
122 JUMP_CONDITIONAL_SHORT_INSTR, 116 JUMP_CONDITIONAL_SHORT_INSTR,
123 REGISTER_INSTR, 117 REGISTER_INSTR,
124 PUSHPOP_INSTR, // Has implicit 64-bit operand size. 118 PUSHPOP_INSTR, // Has implicit 64-bit operand size.
125 MOVE_REG_INSTR, 119 MOVE_REG_INSTR,
126 CALL_JUMP_INSTR, 120 CALL_JUMP_INSTR,
127 SHORT_IMMEDIATE_INSTR 121 SHORT_IMMEDIATE_INSTR
128 }; 122 };
129 123
130
131 enum Prefixes { 124 enum Prefixes {
132 ESCAPE_PREFIX = 0x0F, 125 ESCAPE_PREFIX = 0x0F,
133 OPERAND_SIZE_OVERRIDE_PREFIX = 0x66, 126 OPERAND_SIZE_OVERRIDE_PREFIX = 0x66,
134 ADDRESS_SIZE_OVERRIDE_PREFIX = 0x67, 127 ADDRESS_SIZE_OVERRIDE_PREFIX = 0x67,
135 REPNE_PREFIX = 0xF2, 128 REPNE_PREFIX = 0xF2,
136 REP_PREFIX = 0xF3, 129 REP_PREFIX = 0xF3,
137 REPEQ_PREFIX = REP_PREFIX 130 REPEQ_PREFIX = REP_PREFIX
138 }; 131 };
139 132
140
141 struct InstructionDesc { 133 struct InstructionDesc {
142 const char* mnem; 134 const char* mnem;
143 InstructionType type; 135 InstructionType type;
144 OperandType op_order_; 136 OperandType op_order_;
145 bool byte_size_operation; // Fixed 8-bit operation. 137 bool byte_size_operation; // Fixed 8-bit operation.
146 }; 138 };
147 139
148
149 class InstructionTable : public ValueObject { 140 class InstructionTable : public ValueObject {
150 public: 141 public:
151 InstructionTable(); 142 InstructionTable();
152 const InstructionDesc& Get(uint8_t x) const { return instructions_[x]; } 143 const InstructionDesc& Get(uint8_t x) const { return instructions_[x]; }
153 144
154 private: 145 private:
155 InstructionDesc instructions_[256]; 146 InstructionDesc instructions_[256];
156 void Clear(); 147 void Clear();
157 void Init(); 148 void Init();
158 void CopyTable(const ByteMnemonic bm[], InstructionType type); 149 void CopyTable(const ByteMnemonic bm[], InstructionType type);
159 void SetTableRange(InstructionType type, 150 void SetTableRange(InstructionType type,
160 uint8_t start, 151 uint8_t start,
161 uint8_t end, 152 uint8_t end,
162 bool byte_size, 153 bool byte_size,
163 const char* mnem); 154 const char* mnem);
164 void AddJumpConditionalShort(); 155 void AddJumpConditionalShort();
165 156
166 DISALLOW_COPY_AND_ASSIGN(InstructionTable); 157 DISALLOW_COPY_AND_ASSIGN(InstructionTable);
167 }; 158 };
168 159
169
170 InstructionTable::InstructionTable() { 160 InstructionTable::InstructionTable() {
171 Clear(); 161 Clear();
172 Init(); 162 Init();
173 } 163 }
174 164
175
176 void InstructionTable::Clear() { 165 void InstructionTable::Clear() {
177 for (int i = 0; i < 256; i++) { 166 for (int i = 0; i < 256; i++) {
178 instructions_[i].mnem = "(bad)"; 167 instructions_[i].mnem = "(bad)";
179 instructions_[i].type = NO_INSTR; 168 instructions_[i].type = NO_INSTR;
180 instructions_[i].op_order_ = UNSET_OP_ORDER; 169 instructions_[i].op_order_ = UNSET_OP_ORDER;
181 instructions_[i].byte_size_operation = false; 170 instructions_[i].byte_size_operation = false;
182 } 171 }
183 } 172 }
184 173
185
186 void InstructionTable::Init() { 174 void InstructionTable::Init() {
187 CopyTable(two_operands_instr, TWO_OPERANDS_INSTR); 175 CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
188 CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR); 176 CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
189 CopyTable(call_jump_instr, CALL_JUMP_INSTR); 177 CopyTable(call_jump_instr, CALL_JUMP_INSTR);
190 CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR); 178 CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
191 AddJumpConditionalShort(); 179 AddJumpConditionalShort();
192 SetTableRange(PUSHPOP_INSTR, 0x50, 0x57, false, "push"); 180 SetTableRange(PUSHPOP_INSTR, 0x50, 0x57, false, "push");
193 SetTableRange(PUSHPOP_INSTR, 0x58, 0x5F, false, "pop"); 181 SetTableRange(PUSHPOP_INSTR, 0x58, 0x5F, false, "pop");
194 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, false, "mov"); 182 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, false, "mov");
195 } 183 }
196 184
197
198 void InstructionTable::CopyTable(const ByteMnemonic bm[], 185 void InstructionTable::CopyTable(const ByteMnemonic bm[],
199 InstructionType type) { 186 InstructionType type) {
200 for (int i = 0; bm[i].b >= 0; i++) { 187 for (int i = 0; bm[i].b >= 0; i++) {
201 InstructionDesc* id = &instructions_[bm[i].b]; 188 InstructionDesc* id = &instructions_[bm[i].b];
202 id->mnem = bm[i].mnem; 189 id->mnem = bm[i].mnem;
203 OperandType op_order = bm[i].op_order_; 190 OperandType op_order = bm[i].op_order_;
204 id->op_order_ = 191 id->op_order_ =
205 static_cast<OperandType>(op_order & ~BYTE_SIZE_OPERAND_FLAG); 192 static_cast<OperandType>(op_order & ~BYTE_SIZE_OPERAND_FLAG);
206 ASSERT(NO_INSTR == id->type); // Information not already entered 193 ASSERT(NO_INSTR == id->type); // Information not already entered
207 id->type = type; 194 id->type = type;
208 id->byte_size_operation = ((op_order & BYTE_SIZE_OPERAND_FLAG) != 0); 195 id->byte_size_operation = ((op_order & BYTE_SIZE_OPERAND_FLAG) != 0);
209 } 196 }
210 } 197 }
211 198
212
213 void InstructionTable::SetTableRange(InstructionType type, 199 void InstructionTable::SetTableRange(InstructionType type,
214 uint8_t start, 200 uint8_t start,
215 uint8_t end, 201 uint8_t end,
216 bool byte_size, 202 bool byte_size,
217 const char* mnem) { 203 const char* mnem) {
218 for (uint8_t b = start; b <= end; b++) { 204 for (uint8_t b = start; b <= end; b++) {
219 InstructionDesc* id = &instructions_[b]; 205 InstructionDesc* id = &instructions_[b];
220 ASSERT(NO_INSTR == id->type); // Information not already entered 206 ASSERT(NO_INSTR == id->type); // Information not already entered
221 id->mnem = mnem; 207 id->mnem = mnem;
222 id->type = type; 208 id->type = type;
223 id->byte_size_operation = byte_size; 209 id->byte_size_operation = byte_size;
224 } 210 }
225 } 211 }
226 212
227
228 void InstructionTable::AddJumpConditionalShort() { 213 void InstructionTable::AddJumpConditionalShort() {
229 for (uint8_t b = 0x70; b <= 0x7F; b++) { 214 for (uint8_t b = 0x70; b <= 0x7F; b++) {
230 InstructionDesc* id = &instructions_[b]; 215 InstructionDesc* id = &instructions_[b];
231 ASSERT(NO_INSTR == id->type); // Information not already entered 216 ASSERT(NO_INSTR == id->type); // Information not already entered
232 id->mnem = NULL; // Computed depending on condition code. 217 id->mnem = NULL; // Computed depending on condition code.
233 id->type = JUMP_CONDITIONAL_SHORT_INSTR; 218 id->type = JUMP_CONDITIONAL_SHORT_INSTR;
234 } 219 }
235 } 220 }
236 221
237
238 static InstructionTable instruction_table; 222 static InstructionTable instruction_table;
239 223
240
241 static InstructionDesc cmov_instructions[16] = { 224 static InstructionDesc cmov_instructions[16] = {
242 {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 225 {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
243 {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 226 {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
244 {"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 227 {"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
245 {"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 228 {"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
246 {"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 229 {"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
247 {"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 230 {"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
248 {"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 231 {"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
249 {"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 232 {"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
250 {"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 233 {"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
251 {"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 234 {"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
252 {"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 235 {"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
253 {"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 236 {"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
254 {"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 237 {"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
255 {"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 238 {"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
256 {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 239 {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
257 {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}}; 240 {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}};
258 241
259
260 //------------------------------------------------- 242 //-------------------------------------------------
261 // DisassemblerX64 implementation. 243 // DisassemblerX64 implementation.
262 244
263
264 static const int kMaxXmmRegisters = 16; 245 static const int kMaxXmmRegisters = 16;
265 static const char* xmm_regs[kMaxXmmRegisters] = { 246 static const char* xmm_regs[kMaxXmmRegisters] = {
266 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", 247 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
267 "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"}; 248 "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"};
268 249
269 class DisassemblerX64 : public ValueObject { 250 class DisassemblerX64 : public ValueObject {
270 public: 251 public:
271 DisassemblerX64(char* buffer, intptr_t buffer_size) 252 DisassemblerX64(char* buffer, intptr_t buffer_size)
272 : buffer_(buffer), 253 : buffer_(buffer),
273 buffer_size_(buffer_size), 254 buffer_size_(buffer_size),
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 uint8_t rex_; 366 uint8_t rex_;
386 uint8_t operand_size_; // 0x66 or (if no group 3 prefix is present) 0x0. 367 uint8_t operand_size_; // 0x66 or (if no group 3 prefix is present) 0x0.
387 // 0xF2, 0xF3, or (if no group 1 prefix is present) 0. 368 // 0xF2, 0xF3, or (if no group 1 prefix is present) 0.
388 uint8_t group_1_prefix_; 369 uint8_t group_1_prefix_;
389 // Byte size operand override. 370 // Byte size operand override.
390 bool byte_size_operand_; 371 bool byte_size_operand_;
391 372
392 DISALLOW_COPY_AND_ASSIGN(DisassemblerX64); 373 DISALLOW_COPY_AND_ASSIGN(DisassemblerX64);
393 }; 374 };
394 375
395
396 // Append the str to the output buffer. 376 // Append the str to the output buffer.
397 void DisassemblerX64::Print(const char* format, ...) { 377 void DisassemblerX64::Print(const char* format, ...) {
398 intptr_t available = buffer_size_ - buffer_pos_; 378 intptr_t available = buffer_size_ - buffer_pos_;
399 if (available <= 1) { 379 if (available <= 1) {
400 ASSERT(buffer_[buffer_pos_] == '\0'); 380 ASSERT(buffer_[buffer_pos_] == '\0');
401 return; 381 return;
402 } 382 }
403 char* buf = buffer_ + buffer_pos_; 383 char* buf = buffer_ + buffer_pos_;
404 va_list args; 384 va_list args;
405 va_start(args, format); 385 va_start(args, format);
406 int length = OS::VSNPrint(buf, available, format, args); 386 int length = OS::VSNPrint(buf, available, format, args);
407 va_end(args); 387 va_end(args);
408 buffer_pos_ = 388 buffer_pos_ =
409 (length >= available) ? (buffer_size_ - 1) : (buffer_pos_ + length); 389 (length >= available) ? (buffer_size_ - 1) : (buffer_pos_ + length);
410 ASSERT(buffer_pos_ < buffer_size_); 390 ASSERT(buffer_pos_ < buffer_size_);
411 } 391 }
412 392
413
414 int DisassemblerX64::PrintRightOperandHelper( 393 int DisassemblerX64::PrintRightOperandHelper(
415 uint8_t* modrmp, 394 uint8_t* modrmp,
416 RegisterNameMapping direct_register_name) { 395 RegisterNameMapping direct_register_name) {
417 int mod, regop, rm; 396 int mod, regop, rm;
418 get_modrm(*modrmp, &mod, &regop, &rm); 397 get_modrm(*modrmp, &mod, &regop, &rm);
419 RegisterNameMapping register_name = 398 RegisterNameMapping register_name =
420 (mod == 3) ? direct_register_name : &DisassemblerX64::NameOfCPURegister; 399 (mod == 3) ? direct_register_name : &DisassemblerX64::NameOfCPURegister;
421 switch (mod) { 400 switch (mod) {
422 case 0: 401 case 0:
423 if ((rm & 7) == 5) { 402 if ((rm & 7) == 5) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 case 3: 463 case 3:
485 Print("%s", (this->*register_name)(rm)); 464 Print("%s", (this->*register_name)(rm));
486 return 1; 465 return 1;
487 default: 466 default:
488 UnimplementedInstruction(); 467 UnimplementedInstruction();
489 return 1; 468 return 1;
490 } 469 }
491 UNREACHABLE(); 470 UNREACHABLE();
492 } 471 }
493 472
494
495 int DisassemblerX64::PrintImmediate(uint8_t* data, 473 int DisassemblerX64::PrintImmediate(uint8_t* data,
496 OperandSize size, 474 OperandSize size,
497 bool sign_extend) { 475 bool sign_extend) {
498 int64_t value; 476 int64_t value;
499 int count; 477 int count;
500 switch (size) { 478 switch (size) {
501 case BYTE_SIZE: 479 case BYTE_SIZE:
502 if (sign_extend) { 480 if (sign_extend) {
503 value = *reinterpret_cast<int8_t*>(data); 481 value = *reinterpret_cast<int8_t*>(data);
504 } else { 482 } else {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 524
547 void DisassemblerX64::PrintDisp(int disp, const char* after) { 525 void DisassemblerX64::PrintDisp(int disp, const char* after) {
548 if (-disp > 0) { 526 if (-disp > 0) {
549 Print("-%#x", -disp); 527 Print("-%#x", -disp);
550 } else { 528 } else {
551 Print("+%#x", disp); 529 Print("+%#x", disp);
552 } 530 }
553 if (after != NULL) Print("%s", after); 531 if (after != NULL) Print("%s", after);
554 } 532 }
555 533
556
557 // Returns number of bytes used by machine instruction, including *data byte. 534 // Returns number of bytes used by machine instruction, including *data byte.
558 // Writes immediate instructions to 'tmp_buffer_'. 535 // Writes immediate instructions to 'tmp_buffer_'.
559 int DisassemblerX64::PrintImmediateOp(uint8_t* data) { 536 int DisassemblerX64::PrintImmediateOp(uint8_t* data) {
560 bool byte_size_immediate = (*data & 0x02) != 0; 537 bool byte_size_immediate = (*data & 0x02) != 0;
561 uint8_t modrm = *(data + 1); 538 uint8_t modrm = *(data + 1);
562 int mod, regop, rm; 539 int mod, regop, rm;
563 get_modrm(modrm, &mod, &regop, &rm); 540 get_modrm(modrm, &mod, &regop, &rm);
564 const char* mnem = "Imm???"; 541 const char* mnem = "Imm???";
565 switch (regop) { 542 switch (regop) {
566 case 0: 543 case 0:
(...skipping 25 matching lines...) Expand all
592 } 569 }
593 Print("%s%c ", mnem, operand_size_code()); 570 Print("%s%c ", mnem, operand_size_code());
594 int count = PrintRightOperand(data + 1); 571 int count = PrintRightOperand(data + 1);
595 Print(","); 572 Print(",");
596 OperandSize immediate_size = byte_size_immediate ? BYTE_SIZE : operand_size(); 573 OperandSize immediate_size = byte_size_immediate ? BYTE_SIZE : operand_size();
597 count += 574 count +=
598 PrintImmediate(data + 1 + count, immediate_size, byte_size_immediate); 575 PrintImmediate(data + 1 + count, immediate_size, byte_size_immediate);
599 return 1 + count; 576 return 1 + count;
600 } 577 }
601 578
602
603 // Returns number of bytes used, including *data. 579 // Returns number of bytes used, including *data.
604 int DisassemblerX64::F6F7Instruction(uint8_t* data) { 580 int DisassemblerX64::F6F7Instruction(uint8_t* data) {
605 ASSERT(*data == 0xF7 || *data == 0xF6); 581 ASSERT(*data == 0xF7 || *data == 0xF6);
606 uint8_t modrm = *(data + 1); 582 uint8_t modrm = *(data + 1);
607 int mod, regop, rm; 583 int mod, regop, rm;
608 get_modrm(modrm, &mod, &regop, &rm); 584 get_modrm(modrm, &mod, &regop, &rm);
609 if (mod == 3 && regop != 0) { 585 if (mod == 3 && regop != 0) {
610 const char* mnem = NULL; 586 const char* mnem = NULL;
611 switch (regop) { 587 switch (regop) {
612 case 2: 588 case 2:
(...skipping 21 matching lines...) Expand all
634 int count = PrintRightOperand(data + 1); // Use name of 64-bit register. 610 int count = PrintRightOperand(data + 1); // Use name of 64-bit register.
635 Print(","); 611 Print(",");
636 count += PrintImmediate(data + 1 + count, operand_size()); 612 count += PrintImmediate(data + 1 + count, operand_size());
637 return 1 + count; 613 return 1 + count;
638 } else { 614 } else {
639 UnimplementedInstruction(); 615 UnimplementedInstruction();
640 return 2; 616 return 2;
641 } 617 }
642 } 618 }
643 619
644
645 int DisassemblerX64::ShiftInstruction(uint8_t* data) { 620 int DisassemblerX64::ShiftInstruction(uint8_t* data) {
646 uint8_t op = *data & (~1); 621 uint8_t op = *data & (~1);
647 if (op != 0xD0 && op != 0xD2 && op != 0xC0) { 622 if (op != 0xD0 && op != 0xD2 && op != 0xC0) {
648 UnimplementedInstruction(); 623 UnimplementedInstruction();
649 return 1; 624 return 1;
650 } 625 }
651 uint8_t modrm = *(data + 1); 626 uint8_t modrm = *(data + 1);
652 int mod, regop, rm; 627 int mod, regop, rm;
653 get_modrm(modrm, &mod, &regop, &rm); 628 get_modrm(modrm, &mod, &regop, &rm);
654 regop &= 0x7; // The REX.R bit does not affect the operation. 629 regop &= 0x7; // The REX.R bit does not affect the operation.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
695 Print("%s%c %s,", mnem, operand_size_code(), 670 Print("%s%c %s,", mnem, operand_size_code(),
696 byte_size_operand_ ? NameOfByteCPURegister(rm) : NameOfCPURegister(rm)); 671 byte_size_operand_ ? NameOfByteCPURegister(rm) : NameOfCPURegister(rm));
697 if (op == 0xD2) { 672 if (op == 0xD2) {
698 Print("cl"); 673 Print("cl");
699 } else { 674 } else {
700 Print("%d", imm8); 675 Print("%d", imm8);
701 } 676 }
702 return num_bytes; 677 return num_bytes;
703 } 678 }
704 679
705
706 int DisassemblerX64::PrintRightOperand(uint8_t* modrmp) { 680 int DisassemblerX64::PrintRightOperand(uint8_t* modrmp) {
707 return PrintRightOperandHelper(modrmp, &DisassemblerX64::NameOfCPURegister); 681 return PrintRightOperandHelper(modrmp, &DisassemblerX64::NameOfCPURegister);
708 } 682 }
709 683
710
711 int DisassemblerX64::PrintRightByteOperand(uint8_t* modrmp) { 684 int DisassemblerX64::PrintRightByteOperand(uint8_t* modrmp) {
712 return PrintRightOperandHelper(modrmp, 685 return PrintRightOperandHelper(modrmp,
713 &DisassemblerX64::NameOfByteCPURegister); 686 &DisassemblerX64::NameOfByteCPURegister);
714 } 687 }
715 688
716
717 int DisassemblerX64::PrintRightXMMOperand(uint8_t* modrmp) { 689 int DisassemblerX64::PrintRightXMMOperand(uint8_t* modrmp) {
718 return PrintRightOperandHelper(modrmp, &DisassemblerX64::NameOfXMMRegister); 690 return PrintRightOperandHelper(modrmp, &DisassemblerX64::NameOfXMMRegister);
719 } 691 }
720 692
721
722 // Returns number of bytes used including the current *data. 693 // Returns number of bytes used including the current *data.
723 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'. 694 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
724 int DisassemblerX64::PrintOperands(const char* mnem, 695 int DisassemblerX64::PrintOperands(const char* mnem,
725 OperandType op_order, 696 OperandType op_order,
726 uint8_t* data) { 697 uint8_t* data) {
727 uint8_t modrm = *data; 698 uint8_t modrm = *data;
728 int mod, regop, rm; 699 int mod, regop, rm;
729 get_modrm(modrm, &mod, &regop, &rm); 700 get_modrm(modrm, &mod, &regop, &rm);
730 int advance = 0; 701 int advance = 0;
731 const char* register_name = byte_size_operand_ ? NameOfByteCPURegister(regop) 702 const char* register_name = byte_size_operand_ ? NameOfByteCPURegister(regop)
(...skipping 12 matching lines...) Expand all
744 Print(",%s", register_name); 715 Print(",%s", register_name);
745 break; 716 break;
746 } 717 }
747 default: 718 default:
748 UNREACHABLE(); 719 UNREACHABLE();
749 break; 720 break;
750 } 721 }
751 return advance; 722 return advance;
752 } 723 }
753 724
754
755 void DisassemblerX64::PrintAddress(uint8_t* addr_byte_ptr) { 725 void DisassemblerX64::PrintAddress(uint8_t* addr_byte_ptr) {
756 uword addr = reinterpret_cast<uword>(addr_byte_ptr); 726 uword addr = reinterpret_cast<uword>(addr_byte_ptr);
757 Print("%#" Px "", addr); 727 Print("%#" Px "", addr);
758 } 728 }
759 729
760
761 // Returns number of bytes used, including *data. 730 // Returns number of bytes used, including *data.
762 int DisassemblerX64::JumpShort(uint8_t* data) { 731 int DisassemblerX64::JumpShort(uint8_t* data) {
763 ASSERT(0xEB == *data); 732 ASSERT(0xEB == *data);
764 uint8_t b = *(data + 1); 733 uint8_t b = *(data + 1);
765 uint8_t* dest = data + static_cast<int8_t>(b) + 2; 734 uint8_t* dest = data + static_cast<int8_t>(b) + 2;
766 Print("jmp "); 735 Print("jmp ");
767 PrintAddress(dest); 736 PrintAddress(dest);
768 return 2; 737 return 2;
769 } 738 }
770 739
771
772 // Returns number of bytes used, including *data. 740 // Returns number of bytes used, including *data.
773 int DisassemblerX64::JumpConditional(uint8_t* data) { 741 int DisassemblerX64::JumpConditional(uint8_t* data) {
774 ASSERT(0x0F == *data); 742 ASSERT(0x0F == *data);
775 uint8_t cond = *(data + 1) & 0x0F; 743 uint8_t cond = *(data + 1) & 0x0F;
776 uint8_t* dest = data + *reinterpret_cast<int32_t*>(data + 2) + 6; 744 uint8_t* dest = data + *reinterpret_cast<int32_t*>(data + 2) + 6;
777 const char* mnem = conditional_code_suffix[cond]; 745 const char* mnem = conditional_code_suffix[cond];
778 Print("j%s ", mnem); 746 Print("j%s ", mnem);
779 PrintAddress(dest); 747 PrintAddress(dest);
780 return 6; // includes 0x0F 748 return 6; // includes 0x0F
781 } 749 }
782 750
783
784 // Returns number of bytes used, including *data. 751 // Returns number of bytes used, including *data.
785 int DisassemblerX64::JumpConditionalShort(uint8_t* data) { 752 int DisassemblerX64::JumpConditionalShort(uint8_t* data) {
786 uint8_t cond = *data & 0x0F; 753 uint8_t cond = *data & 0x0F;
787 uint8_t b = *(data + 1); 754 uint8_t b = *(data + 1);
788 uint8_t* dest = data + static_cast<int8_t>(b) + 2; 755 uint8_t* dest = data + static_cast<int8_t>(b) + 2;
789 const char* mnem = conditional_code_suffix[cond]; 756 const char* mnem = conditional_code_suffix[cond];
790 Print("j%s ", mnem); 757 Print("j%s ", mnem);
791 PrintAddress(dest); 758 PrintAddress(dest);
792 return 2; 759 return 2;
793 } 760 }
794 761
795
796 // Returns number of bytes used, including *data. 762 // Returns number of bytes used, including *data.
797 int DisassemblerX64::SetCC(uint8_t* data) { 763 int DisassemblerX64::SetCC(uint8_t* data) {
798 ASSERT(0x0F == *data); 764 ASSERT(0x0F == *data);
799 uint8_t cond = *(data + 1) & 0x0F; 765 uint8_t cond = *(data + 1) & 0x0F;
800 const char* mnem = conditional_code_suffix[cond]; 766 const char* mnem = conditional_code_suffix[cond];
801 Print("set%s%c ", mnem, operand_size_code()); 767 Print("set%s%c ", mnem, operand_size_code());
802 PrintRightByteOperand(data + 2); 768 PrintRightByteOperand(data + 2);
803 return 3; // includes 0x0F 769 return 3; // includes 0x0F
804 } 770 }
805 771
806
807 // Returns number of bytes used, including *data. 772 // Returns number of bytes used, including *data.
808 int DisassemblerX64::FPUInstruction(uint8_t* data) { 773 int DisassemblerX64::FPUInstruction(uint8_t* data) {
809 uint8_t escape_opcode = *data; 774 uint8_t escape_opcode = *data;
810 ASSERT(0xD8 == (escape_opcode & 0xF8)); 775 ASSERT(0xD8 == (escape_opcode & 0xF8));
811 uint8_t modrm_byte = *(data + 1); 776 uint8_t modrm_byte = *(data + 1);
812 777
813 if (modrm_byte >= 0xC0) { 778 if (modrm_byte >= 0xC0) {
814 return RegisterFPUInstruction(escape_opcode, modrm_byte); 779 return RegisterFPUInstruction(escape_opcode, modrm_byte);
815 } else { 780 } else {
816 return MemoryFPUInstruction(escape_opcode, modrm_byte, data + 1); 781 return MemoryFPUInstruction(escape_opcode, modrm_byte, data + 1);
817 } 782 }
818 } 783 }
819 784
820
821 int DisassemblerX64::MemoryFPUInstruction(int escape_opcode, 785 int DisassemblerX64::MemoryFPUInstruction(int escape_opcode,
822 int modrm_byte, 786 int modrm_byte,
823 uint8_t* modrm_start) { 787 uint8_t* modrm_start) {
824 const char* mnem = "?"; 788 const char* mnem = "?";
825 int regop = (modrm_byte >> 3) & 0x7; // reg/op field of modrm byte. 789 int regop = (modrm_byte >> 3) & 0x7; // reg/op field of modrm byte.
826 switch (escape_opcode) { 790 switch (escape_opcode) {
827 case 0xD9: 791 case 0xD9:
828 switch (regop) { 792 switch (regop) {
829 case 0: 793 case 0:
830 mnem = "fld_s"; 794 mnem = "fld_s";
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
1063 } 1027 }
1064 1028
1065 if (has_register) { 1029 if (has_register) {
1066 Print("%s st%d", mnem, modrm_byte & 0x7); 1030 Print("%s st%d", mnem, modrm_byte & 0x7);
1067 } else { 1031 } else {
1068 Print("%s", mnem); 1032 Print("%s", mnem);
1069 } 1033 }
1070 return 2; 1034 return 2;
1071 } 1035 }
1072 1036
1073
1074 // TODO(srdjan): Should we add a branch hint argument? 1037 // TODO(srdjan): Should we add a branch hint argument?
1075 bool DisassemblerX64::DecodeInstructionType(uint8_t** data) { 1038 bool DisassemblerX64::DecodeInstructionType(uint8_t** data) {
1076 uint8_t current; 1039 uint8_t current;
1077 1040
1078 // Scan for prefixes. 1041 // Scan for prefixes.
1079 while (true) { 1042 while (true) {
1080 current = **data; 1043 current = **data;
1081 if (current == OPERAND_SIZE_OVERRIDE_PREFIX) { // Group 3 prefix. 1044 if (current == OPERAND_SIZE_OVERRIDE_PREFIX) { // Group 3 prefix.
1082 operand_size_ = current; 1045 operand_size_ = current;
1083 } else if ((current & 0xF0) == 0x40) { // REX prefix. 1046 } else if ((current & 0xF0) == 0x40) { // REX prefix.
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1178 1141
1179 case NO_INSTR: 1142 case NO_INSTR:
1180 return false; 1143 return false;
1181 1144
1182 default: 1145 default:
1183 UNIMPLEMENTED(); // This type is not implemented. 1146 UNIMPLEMENTED(); // This type is not implemented.
1184 } 1147 }
1185 return true; 1148 return true;
1186 } 1149 }
1187 1150
1188
1189 // Handle all two-byte opcodes, which start with 0x0F. 1151 // Handle all two-byte opcodes, which start with 0x0F.
1190 // These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix. 1152 // These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix.
1191 // We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A. 1153 // We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A.
1192 int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) { 1154 int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) {
1193 uint8_t opcode = *(data + 1); 1155 uint8_t opcode = *(data + 1);
1194 uint8_t* current = data + 2; 1156 uint8_t* current = data + 2;
1195 // At return, "current" points to the start of the next instruction. 1157 // At return, "current" points to the start of the next instruction.
1196 const char* mnemonic = TwoByteMnemonic(opcode); 1158 const char* mnemonic = TwoByteMnemonic(opcode);
1197 if (operand_size_ == 0x66) { 1159 if (operand_size_ == 0x66) {
1198 // 0x66 0x0F prefix. 1160 // 0x66 0x0F prefix.
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
1561 } else { 1523 } else {
1562 Print(","); 1524 Print(",");
1563 current += PrintImmediate(current, BYTE_SIZE); 1525 current += PrintImmediate(current, BYTE_SIZE);
1564 } 1526 }
1565 } else { 1527 } else {
1566 UnimplementedInstruction(); 1528 UnimplementedInstruction();
1567 } 1529 }
1568 return static_cast<int>(current - data); 1530 return static_cast<int>(current - data);
1569 } 1531 }
1570 1532
1571
1572 // Mnemonics for two-byte opcode instructions starting with 0x0F. 1533 // Mnemonics for two-byte opcode instructions starting with 0x0F.
1573 // The argument is the second byte of the two-byte opcode. 1534 // The argument is the second byte of the two-byte opcode.
1574 // Returns NULL if the instruction is not handled here. 1535 // Returns NULL if the instruction is not handled here.
1575 const char* DisassemblerX64::TwoByteMnemonic(uint8_t opcode) { 1536 const char* DisassemblerX64::TwoByteMnemonic(uint8_t opcode) {
1576 switch (opcode) { 1537 switch (opcode) {
1577 case 0x1F: 1538 case 0x1F:
1578 return "nop"; 1539 return "nop";
1579 case 0x2A: // F2/F3 prefix. 1540 case 0x2A: // F2/F3 prefix.
1580 return "cvtsi2s"; 1541 return "cvtsi2s";
1581 case 0x31: 1542 case 0x31:
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1619 return "movsxw"; 1580 return "movsxw";
1620 case 0x12: 1581 case 0x12:
1621 return "movhlps"; 1582 return "movhlps";
1622 case 0x16: 1583 case 0x16:
1623 return "movlhps"; 1584 return "movlhps";
1624 default: 1585 default:
1625 return NULL; 1586 return NULL;
1626 } 1587 }
1627 } 1588 }
1628 1589
1629
1630 int DisassemblerX64::InstructionDecode(uword pc) { 1590 int DisassemblerX64::InstructionDecode(uword pc) {
1631 uint8_t* data = reinterpret_cast<uint8_t*>(pc); 1591 uint8_t* data = reinterpret_cast<uint8_t*>(pc);
1632 1592
1633 const bool processed = DecodeInstructionType(&data); 1593 const bool processed = DecodeInstructionType(&data);
1634 1594
1635 if (!processed) { 1595 if (!processed) {
1636 switch (*data) { 1596 switch (*data) {
1637 case 0xC2: 1597 case 0xC2:
1638 Print("ret "); 1598 Print("ret ");
1639 PrintImmediateValue(*reinterpret_cast<uint16_t*>(data + 1)); 1599 PrintImmediateValue(*reinterpret_cast<uint16_t*>(data + 1));
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
1936 } // !processed 1896 } // !processed
1937 1897
1938 ASSERT(buffer_[buffer_pos_] == '\0'); 1898 ASSERT(buffer_[buffer_pos_] == '\0');
1939 1899
1940 int instr_len = data - reinterpret_cast<uint8_t*>(pc); 1900 int instr_len = data - reinterpret_cast<uint8_t*>(pc);
1941 ASSERT(instr_len > 0); // Ensure progress. 1901 ASSERT(instr_len > 0); // Ensure progress.
1942 1902
1943 return instr_len; 1903 return instr_len;
1944 } 1904 }
1945 1905
1946
1947 void Disassembler::DecodeInstruction(char* hex_buffer, 1906 void Disassembler::DecodeInstruction(char* hex_buffer,
1948 intptr_t hex_size, 1907 intptr_t hex_size,
1949 char* human_buffer, 1908 char* human_buffer,
1950 intptr_t human_size, 1909 intptr_t human_size,
1951 int* out_instr_len, 1910 int* out_instr_len,
1952 const Code& code, 1911 const Code& code,
1953 Object** object, 1912 Object** object,
1954 uword pc) { 1913 uword pc) {
1955 ASSERT(hex_size > 0); 1914 ASSERT(hex_size > 0);
1956 ASSERT(human_size > 0); 1915 ASSERT(human_size > 0);
(...skipping 19 matching lines...) Expand all
1976 *object = NULL; 1935 *object = NULL;
1977 } 1936 }
1978 } 1937 }
1979 } 1938 }
1980 1939
1981 #endif // !PRODUCT 1940 #endif // !PRODUCT
1982 1941
1983 } // namespace dart 1942 } // namespace dart
1984 1943
1985 #endif // defined TARGET_ARCH_X64 1944 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/disassembler_test.cc ('k') | runtime/vm/double_conversion.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698