OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_ARM. | 7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
8 #if defined(TARGET_ARCH_ARM) | 8 #if defined(TARGET_ARCH_ARM) |
9 #include "platform/assert.h" | 9 #include "platform/assert.h" |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; } | 70 size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; } |
71 | 71 |
72 char* buffer_; // Decode instructions into this buffer. | 72 char* buffer_; // Decode instructions into this buffer. |
73 size_t buffer_size_; // The size of the character buffer. | 73 size_t buffer_size_; // The size of the character buffer. |
74 size_t buffer_pos_; // Current character position in buffer. | 74 size_t buffer_pos_; // Current character position in buffer. |
75 | 75 |
76 DISALLOW_ALLOCATION(); | 76 DISALLOW_ALLOCATION(); |
77 DISALLOW_COPY_AND_ASSIGN(ARMDecoder); | 77 DISALLOW_COPY_AND_ASSIGN(ARMDecoder); |
78 }; | 78 }; |
79 | 79 |
80 | |
81 // Support for assertions in the ARMDecoder formatting functions. | 80 // Support for assertions in the ARMDecoder formatting functions. |
82 #define STRING_STARTS_WITH(string, compare_string) \ | 81 #define STRING_STARTS_WITH(string, compare_string) \ |
83 (strncmp(string, compare_string, strlen(compare_string)) == 0) | 82 (strncmp(string, compare_string, strlen(compare_string)) == 0) |
84 | 83 |
85 | |
86 // Append the str to the output buffer. | 84 // Append the str to the output buffer. |
87 void ARMDecoder::Print(const char* str) { | 85 void ARMDecoder::Print(const char* str) { |
88 char cur = *str++; | 86 char cur = *str++; |
89 while (cur != '\0' && (buffer_pos_ < (buffer_size_ - 1))) { | 87 while (cur != '\0' && (buffer_pos_ < (buffer_size_ - 1))) { |
90 buffer_[buffer_pos_++] = cur; | 88 buffer_[buffer_pos_++] = cur; |
91 cur = *str++; | 89 cur = *str++; |
92 } | 90 } |
93 buffer_[buffer_pos_] = '\0'; | 91 buffer_[buffer_pos_] = '\0'; |
94 } | 92 } |
95 | 93 |
96 | |
97 // These condition names are defined in a way to match the native disassembler | 94 // These condition names are defined in a way to match the native disassembler |
98 // formatting. See for example the command "objdump -d <binary file>". | 95 // formatting. See for example the command "objdump -d <binary file>". |
99 static const char* cond_names[kNumberOfConditions] = { | 96 static const char* cond_names[kNumberOfConditions] = { |
100 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", | 97 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", |
101 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid", | 98 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid", |
102 }; | 99 }; |
103 | 100 |
104 | |
105 // Print the condition guarding the instruction. | 101 // Print the condition guarding the instruction. |
106 void ARMDecoder::PrintCondition(Instr* instr) { | 102 void ARMDecoder::PrintCondition(Instr* instr) { |
107 Print(cond_names[instr->ConditionField()]); | 103 Print(cond_names[instr->ConditionField()]); |
108 } | 104 } |
109 | 105 |
110 | |
111 // These register names are defined in a way to match the native disassembler | 106 // These register names are defined in a way to match the native disassembler |
112 // formatting, except for register alias pp (r5). | 107 // formatting, except for register alias pp (r5). |
113 // See for example the command "objdump -d <binary file>". | 108 // See for example the command "objdump -d <binary file>". |
114 static const char* reg_names[kNumberOfCpuRegisters] = { | 109 static const char* reg_names[kNumberOfCpuRegisters] = { |
115 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS) | 110 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS) |
116 "r0", "r1", "r2", "r3", "r4", "pp", "r6", "fp", | 111 "r0", "r1", "r2", "r3", "r4", "pp", "r6", "fp", |
117 "r8", "r9", "thr", "r11", "ip", "sp", "lr", "pc", | 112 "r8", "r9", "thr", "r11", "ip", "sp", "lr", "pc", |
118 #else | 113 #else |
119 "r0", "r1", "r2", "r3", "r4", "pp", "r6", "r7", | 114 "r0", "r1", "r2", "r3", "r4", "pp", "r6", "r7", |
120 "r8", "r9", "thr", "fp", "ip", "sp", "lr", "pc", | 115 "r8", "r9", "thr", "fp", "ip", "sp", "lr", "pc", |
121 #endif | 116 #endif |
122 }; | 117 }; |
123 | 118 |
124 | |
125 // Print the register name according to the active name converter. | 119 // Print the register name according to the active name converter. |
126 void ARMDecoder::PrintRegister(int reg) { | 120 void ARMDecoder::PrintRegister(int reg) { |
127 ASSERT(0 <= reg); | 121 ASSERT(0 <= reg); |
128 ASSERT(reg < kNumberOfCpuRegisters); | 122 ASSERT(reg < kNumberOfCpuRegisters); |
129 Print(reg_names[reg]); | 123 Print(reg_names[reg]); |
130 } | 124 } |
131 | 125 |
132 | |
133 void ARMDecoder::PrintSRegister(int reg) { | 126 void ARMDecoder::PrintSRegister(int reg) { |
134 ASSERT(0 <= reg); | 127 ASSERT(0 <= reg); |
135 ASSERT(reg < kNumberOfSRegisters); | 128 ASSERT(reg < kNumberOfSRegisters); |
136 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 129 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
137 remaining_size_in_buffer(), "s%d", reg); | 130 remaining_size_in_buffer(), "s%d", reg); |
138 } | 131 } |
139 | 132 |
140 | |
141 void ARMDecoder::PrintDRegister(int reg) { | 133 void ARMDecoder::PrintDRegister(int reg) { |
142 ASSERT(0 <= reg); | 134 ASSERT(0 <= reg); |
143 ASSERT(reg < kNumberOfDRegisters); | 135 ASSERT(reg < kNumberOfDRegisters); |
144 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 136 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
145 remaining_size_in_buffer(), "d%d", reg); | 137 remaining_size_in_buffer(), "d%d", reg); |
146 } | 138 } |
147 | 139 |
148 | |
149 void ARMDecoder::PrintQRegister(int reg) { | 140 void ARMDecoder::PrintQRegister(int reg) { |
150 ASSERT(0 <= reg); | 141 ASSERT(0 <= reg); |
151 ASSERT(reg < kNumberOfQRegisters); | 142 ASSERT(reg < kNumberOfQRegisters); |
152 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 143 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
153 remaining_size_in_buffer(), "q%d", reg); | 144 remaining_size_in_buffer(), "q%d", reg); |
154 } | 145 } |
155 | 146 |
156 | |
157 // These shift names are defined in a way to match the native disassembler | 147 // These shift names are defined in a way to match the native disassembler |
158 // formatting. See for example the command "objdump -d <binary file>". | 148 // formatting. See for example the command "objdump -d <binary file>". |
159 static const char* shift_names[kMaxShift] = {"lsl", "lsr", "asr", "ror"}; | 149 static const char* shift_names[kMaxShift] = {"lsl", "lsr", "asr", "ror"}; |
160 | 150 |
161 | |
162 // Print the register shift operands for the instruction. Generally used for | 151 // Print the register shift operands for the instruction. Generally used for |
163 // data processing instructions. | 152 // data processing instructions. |
164 void ARMDecoder::PrintShiftRm(Instr* instr) { | 153 void ARMDecoder::PrintShiftRm(Instr* instr) { |
165 Shift shift = instr->ShiftField(); | 154 Shift shift = instr->ShiftField(); |
166 int shift_amount = instr->ShiftAmountField(); | 155 int shift_amount = instr->ShiftAmountField(); |
167 int rm = instr->RmField(); | 156 int rm = instr->RmField(); |
168 | 157 |
169 PrintRegister(rm); | 158 PrintRegister(rm); |
170 | 159 |
171 if ((instr->RegShiftField() == 0) && (shift == LSL) && (shift_amount == 0)) { | 160 if ((instr->RegShiftField() == 0) && (shift == LSL) && (shift_amount == 0)) { |
(...skipping 14 matching lines...) Expand all Loading... |
186 } else { | 175 } else { |
187 // by register | 176 // by register |
188 int rs = instr->RsField(); | 177 int rs = instr->RsField(); |
189 buffer_pos_ += | 178 buffer_pos_ += |
190 OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(), | 179 OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(), |
191 ", %s ", shift_names[shift]); | 180 ", %s ", shift_names[shift]); |
192 PrintRegister(rs); | 181 PrintRegister(rs); |
193 } | 182 } |
194 } | 183 } |
195 | 184 |
196 | |
197 // Print the immediate operand for the instruction. Generally used for data | 185 // Print the immediate operand for the instruction. Generally used for data |
198 // processing instructions. | 186 // processing instructions. |
199 void ARMDecoder::PrintShiftImm(Instr* instr) { | 187 void ARMDecoder::PrintShiftImm(Instr* instr) { |
200 int rotate = instr->RotateField() * 2; | 188 int rotate = instr->RotateField() * 2; |
201 int immed8 = instr->Immed8Field(); | 189 int immed8 = instr->Immed8Field(); |
202 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate)); | 190 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate)); |
203 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 191 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
204 remaining_size_in_buffer(), "#%d", imm); | 192 remaining_size_in_buffer(), "#%d", imm); |
205 } | 193 } |
206 | 194 |
207 | |
208 // Print PU formatting to reduce complexity of FormatOption. | 195 // Print PU formatting to reduce complexity of FormatOption. |
209 void ARMDecoder::PrintPU(Instr* instr) { | 196 void ARMDecoder::PrintPU(Instr* instr) { |
210 switch (instr->PUField()) { | 197 switch (instr->PUField()) { |
211 case 0: { | 198 case 0: { |
212 Print("da"); | 199 Print("da"); |
213 break; | 200 break; |
214 } | 201 } |
215 case 1: { | 202 case 1: { |
216 Print("ia"); | 203 Print("ia"); |
217 break; | 204 break; |
218 } | 205 } |
219 case 2: { | 206 case 2: { |
220 Print("db"); | 207 Print("db"); |
221 break; | 208 break; |
222 } | 209 } |
223 case 3: { | 210 case 3: { |
224 Print("ib"); | 211 Print("ib"); |
225 break; | 212 break; |
226 } | 213 } |
227 default: { | 214 default: { |
228 UNREACHABLE(); | 215 UNREACHABLE(); |
229 break; | 216 break; |
230 } | 217 } |
231 } | 218 } |
232 } | 219 } |
233 | 220 |
234 | |
235 // Handle all register based formatting in these functions to reduce the | 221 // Handle all register based formatting in these functions to reduce the |
236 // complexity of FormatOption. | 222 // complexity of FormatOption. |
237 int ARMDecoder::FormatRegister(Instr* instr, const char* format) { | 223 int ARMDecoder::FormatRegister(Instr* instr, const char* format) { |
238 ASSERT(format[0] == 'r'); | 224 ASSERT(format[0] == 'r'); |
239 if (format[1] == 'n') { // 'rn: Rn register | 225 if (format[1] == 'n') { // 'rn: Rn register |
240 int reg = instr->RnField(); | 226 int reg = instr->RnField(); |
241 PrintRegister(reg); | 227 PrintRegister(reg); |
242 return 2; | 228 return 2; |
243 } else if (format[1] == 'd') { // 'rd: Rd register | 229 } else if (format[1] == 'd') { // 'rd: Rd register |
244 int reg = instr->RdField(); | 230 int reg = instr->RdField(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 reg++; | 266 reg++; |
281 rlist >>= 1; | 267 rlist >>= 1; |
282 } | 268 } |
283 Print("}"); | 269 Print("}"); |
284 return 5; | 270 return 5; |
285 } | 271 } |
286 UNREACHABLE(); | 272 UNREACHABLE(); |
287 return -1; | 273 return -1; |
288 } | 274 } |
289 | 275 |
290 | |
291 int ARMDecoder::FormatSRegister(Instr* instr, const char* format) { | 276 int ARMDecoder::FormatSRegister(Instr* instr, const char* format) { |
292 ASSERT(format[0] == 's'); | 277 ASSERT(format[0] == 's'); |
293 if (format[1] == 'n') { // 'sn: Sn register | 278 if (format[1] == 'n') { // 'sn: Sn register |
294 int reg = instr->SnField(); | 279 int reg = instr->SnField(); |
295 PrintSRegister(reg); | 280 PrintSRegister(reg); |
296 return 2; | 281 return 2; |
297 } else if (format[1] == 'd') { // 'sd: Sd register | 282 } else if (format[1] == 'd') { // 'sd: Sd register |
298 int reg = instr->SdField(); | 283 int reg = instr->SdField(); |
299 PrintSRegister(reg); | 284 PrintSRegister(reg); |
300 return 2; | 285 return 2; |
(...skipping 19 matching lines...) Expand all Loading... |
320 Print(", "); | 305 Print(", "); |
321 } | 306 } |
322 } | 307 } |
323 Print("}"); | 308 Print("}"); |
324 return 5; | 309 return 5; |
325 } | 310 } |
326 UNREACHABLE(); | 311 UNREACHABLE(); |
327 return -1; | 312 return -1; |
328 } | 313 } |
329 | 314 |
330 | |
331 void ARMDecoder::PrintDRegisterList(int start, int reg_count) { | 315 void ARMDecoder::PrintDRegisterList(int start, int reg_count) { |
332 Print("{"); | 316 Print("{"); |
333 for (int i = start; i < start + reg_count; i++) { | 317 for (int i = start; i < start + reg_count; i++) { |
334 PrintDRegister(i); | 318 PrintDRegister(i); |
335 if (i != start + reg_count - 1) { | 319 if (i != start + reg_count - 1) { |
336 Print(", "); | 320 Print(", "); |
337 } | 321 } |
338 } | 322 } |
339 Print("}"); | 323 Print("}"); |
340 } | 324 } |
341 | 325 |
342 | |
343 int ARMDecoder::FormatDRegister(Instr* instr, const char* format) { | 326 int ARMDecoder::FormatDRegister(Instr* instr, const char* format) { |
344 ASSERT(format[0] == 'd'); | 327 ASSERT(format[0] == 'd'); |
345 if (format[1] == 'n') { // 'dn: Dn register | 328 if (format[1] == 'n') { // 'dn: Dn register |
346 int reg = instr->DnField(); | 329 int reg = instr->DnField(); |
347 PrintDRegister(reg); | 330 PrintDRegister(reg); |
348 return 2; | 331 return 2; |
349 } else if (format[1] == 'd') { // 'dd: Dd register | 332 } else if (format[1] == 'd') { // 'dd: Dd register |
350 int reg = instr->DdField(); | 333 int reg = instr->DdField(); |
351 PrintDRegister(reg); | 334 PrintDRegister(reg); |
352 return 2; | 335 return 2; |
(...skipping 11 matching lines...) Expand all Loading... |
364 ASSERT(STRING_STARTS_WITH(format, "dtbllist")); | 347 ASSERT(STRING_STARTS_WITH(format, "dtbllist")); |
365 int reg_count = instr->Bits(8, 2) + 1; | 348 int reg_count = instr->Bits(8, 2) + 1; |
366 int start = (instr->Bit(7) << 4) | instr->Bits(16, 4); | 349 int start = (instr->Bit(7) << 4) | instr->Bits(16, 4); |
367 PrintDRegisterList(start, reg_count); | 350 PrintDRegisterList(start, reg_count); |
368 return 8; | 351 return 8; |
369 } | 352 } |
370 UNREACHABLE(); | 353 UNREACHABLE(); |
371 return -1; | 354 return -1; |
372 } | 355 } |
373 | 356 |
374 | |
375 int ARMDecoder::FormatQRegister(Instr* instr, const char* format) { | 357 int ARMDecoder::FormatQRegister(Instr* instr, const char* format) { |
376 ASSERT(format[0] == 'q'); | 358 ASSERT(format[0] == 'q'); |
377 if (format[1] == 'n') { // 'qn: Qn register | 359 if (format[1] == 'n') { // 'qn: Qn register |
378 int reg = instr->QnField(); | 360 int reg = instr->QnField(); |
379 PrintQRegister(reg); | 361 PrintQRegister(reg); |
380 return 2; | 362 return 2; |
381 } else if (format[1] == 'd') { // 'qd: Qd register | 363 } else if (format[1] == 'd') { // 'qd: Qd register |
382 int reg = instr->QdField(); | 364 int reg = instr->QdField(); |
383 PrintQRegister(reg); | 365 PrintQRegister(reg); |
384 return 2; | 366 return 2; |
385 } else if (format[1] == 'm') { // 'qm: Qm register | 367 } else if (format[1] == 'm') { // 'qm: Qm register |
386 int reg = instr->QmField(); | 368 int reg = instr->QmField(); |
387 PrintQRegister(reg); | 369 PrintQRegister(reg); |
388 return 2; | 370 return 2; |
389 } | 371 } |
390 UNREACHABLE(); | 372 UNREACHABLE(); |
391 return -1; | 373 return -1; |
392 } | 374 } |
393 | 375 |
394 | |
395 // FormatOption takes a formatting string and interprets it based on | 376 // FormatOption takes a formatting string and interprets it based on |
396 // the current instructions. The format string points to the first | 377 // the current instructions. The format string points to the first |
397 // character of the option string (the option escape has already been | 378 // character of the option string (the option escape has already been |
398 // consumed by the caller.) FormatOption returns the number of | 379 // consumed by the caller.) FormatOption returns the number of |
399 // characters that were consumed from the formatting string. | 380 // characters that were consumed from the formatting string. |
400 int ARMDecoder::FormatOption(Instr* instr, const char* format) { | 381 int ARMDecoder::FormatOption(Instr* instr, const char* format) { |
401 switch (format[0]) { | 382 switch (format[0]) { |
402 case 'a': { // 'a: accumulate multiplies | 383 case 'a': { // 'a: accumulate multiplies |
403 if (instr->Bit(21) == 0) { | 384 if (instr->Bit(21) == 0) { |
404 Print("ul"); | 385 Print("ul"); |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 } | 597 } |
617 default: { | 598 default: { |
618 UNREACHABLE(); | 599 UNREACHABLE(); |
619 break; | 600 break; |
620 } | 601 } |
621 } | 602 } |
622 UNREACHABLE(); | 603 UNREACHABLE(); |
623 return -1; | 604 return -1; |
624 } | 605 } |
625 | 606 |
626 | |
627 // Format takes a formatting string for a whole instruction and prints it into | 607 // Format takes a formatting string for a whole instruction and prints it into |
628 // the output buffer. All escaped options are handed to FormatOption to be | 608 // the output buffer. All escaped options are handed to FormatOption to be |
629 // parsed further. | 609 // parsed further. |
630 void ARMDecoder::Format(Instr* instr, const char* format) { | 610 void ARMDecoder::Format(Instr* instr, const char* format) { |
631 char cur = *format++; | 611 char cur = *format++; |
632 while ((cur != 0) && (buffer_pos_ < (buffer_size_ - 1))) { | 612 while ((cur != 0) && (buffer_pos_ < (buffer_size_ - 1))) { |
633 if (cur == '\'') { // Single quote is used as the formatting escape. | 613 if (cur == '\'') { // Single quote is used as the formatting escape. |
634 format += FormatOption(instr, format); | 614 format += FormatOption(instr, format); |
635 } else { | 615 } else { |
636 buffer_[buffer_pos_++] = cur; | 616 buffer_[buffer_pos_++] = cur; |
637 } | 617 } |
638 cur = *format++; | 618 cur = *format++; |
639 } | 619 } |
640 buffer_[buffer_pos_] = '\0'; | 620 buffer_[buffer_pos_] = '\0'; |
641 } | 621 } |
642 | 622 |
643 | |
644 // For currently unimplemented decodings the disassembler calls Unknown(instr) | 623 // For currently unimplemented decodings the disassembler calls Unknown(instr) |
645 // which will just print "unknown" of the instruction bits. | 624 // which will just print "unknown" of the instruction bits. |
646 void ARMDecoder::Unknown(Instr* instr) { | 625 void ARMDecoder::Unknown(Instr* instr) { |
647 Format(instr, "unknown"); | 626 Format(instr, "unknown"); |
648 } | 627 } |
649 | 628 |
650 | |
651 void ARMDecoder::DecodeType01(Instr* instr) { | 629 void ARMDecoder::DecodeType01(Instr* instr) { |
652 if (!instr->IsDataProcessing()) { | 630 if (!instr->IsDataProcessing()) { |
653 // miscellaneous, multiply, sync primitives, extra loads and stores. | 631 // miscellaneous, multiply, sync primitives, extra loads and stores. |
654 if (instr->IsMiscellaneous()) { | 632 if (instr->IsMiscellaneous()) { |
655 switch (instr->Bits(4, 3)) { | 633 switch (instr->Bits(4, 3)) { |
656 case 1: { | 634 case 1: { |
657 if (instr->Bits(21, 2) == 0x3) { | 635 if (instr->Bits(21, 2) == 0x3) { |
658 Format(instr, "clz'cond 'rd, 'rm"); | 636 Format(instr, "clz'cond 'rd, 'rm"); |
659 } else if (instr->Bits(21, 2) == 0x1) { | 637 } else if (instr->Bits(21, 2) == 0x1) { |
660 Format(instr, "bx'cond 'rm"); | 638 Format(instr, "bx'cond 'rm"); |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
925 } | 903 } |
926 default: { | 904 default: { |
927 // The Opcode field is a 4-bit field. | 905 // The Opcode field is a 4-bit field. |
928 UNREACHABLE(); | 906 UNREACHABLE(); |
929 break; | 907 break; |
930 } | 908 } |
931 } | 909 } |
932 } | 910 } |
933 } | 911 } |
934 | 912 |
935 | |
936 void ARMDecoder::DecodeType2(Instr* instr) { | 913 void ARMDecoder::DecodeType2(Instr* instr) { |
937 switch (instr->PUField()) { | 914 switch (instr->PUField()) { |
938 case 0: { | 915 case 0: { |
939 if (instr->HasW()) { | 916 if (instr->HasW()) { |
940 Unknown(instr); // Not used. | 917 Unknown(instr); // Not used. |
941 } else { | 918 } else { |
942 Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); | 919 Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); |
943 } | 920 } |
944 break; | 921 break; |
945 } | 922 } |
(...skipping 14 matching lines...) Expand all Loading... |
960 break; | 937 break; |
961 } | 938 } |
962 default: { | 939 default: { |
963 // The PU field is a 2-bit field. | 940 // The PU field is a 2-bit field. |
964 UNREACHABLE(); | 941 UNREACHABLE(); |
965 break; | 942 break; |
966 } | 943 } |
967 } | 944 } |
968 } | 945 } |
969 | 946 |
970 | |
971 void ARMDecoder::DecodeType3(Instr* instr) { | 947 void ARMDecoder::DecodeType3(Instr* instr) { |
972 if (instr->IsDivision()) { | 948 if (instr->IsDivision()) { |
973 if (!TargetCPUFeatures::integer_division_supported()) { | 949 if (!TargetCPUFeatures::integer_division_supported()) { |
974 Unknown(instr); | 950 Unknown(instr); |
975 return; | 951 return; |
976 } | 952 } |
977 if (instr->Bit(21)) { | 953 if (instr->Bit(21)) { |
978 Format(instr, "udiv'cond 'rn, 'rs, 'rm"); | 954 Format(instr, "udiv'cond 'rn, 'rs, 'rm"); |
979 } else { | 955 } else { |
980 Format(instr, "sdiv'cond 'rn, 'rs, 'rm"); | 956 Format(instr, "sdiv'cond 'rn, 'rs, 'rm"); |
(...skipping 26 matching lines...) Expand all Loading... |
1007 break; | 983 break; |
1008 } | 984 } |
1009 default: { | 985 default: { |
1010 // The PU field is a 2-bit field. | 986 // The PU field is a 2-bit field. |
1011 UNREACHABLE(); | 987 UNREACHABLE(); |
1012 break; | 988 break; |
1013 } | 989 } |
1014 } | 990 } |
1015 } | 991 } |
1016 | 992 |
1017 | |
1018 void ARMDecoder::DecodeType4(Instr* instr) { | 993 void ARMDecoder::DecodeType4(Instr* instr) { |
1019 if (instr->Bit(22) == 1) { | 994 if (instr->Bit(22) == 1) { |
1020 Unknown(instr); // Privileged mode currently not supported. | 995 Unknown(instr); // Privileged mode currently not supported. |
1021 } else if (instr->HasL()) { | 996 } else if (instr->HasL()) { |
1022 Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); | 997 Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); |
1023 } else { | 998 } else { |
1024 Format(instr, "stm'cond'pu 'rn'w, 'rlist"); | 999 Format(instr, "stm'cond'pu 'rn'w, 'rlist"); |
1025 } | 1000 } |
1026 } | 1001 } |
1027 | 1002 |
1028 | |
1029 void ARMDecoder::DecodeType5(Instr* instr) { | 1003 void ARMDecoder::DecodeType5(Instr* instr) { |
1030 Format(instr, "b'l'cond 'target ; 'dest"); | 1004 Format(instr, "b'l'cond 'target ; 'dest"); |
1031 } | 1005 } |
1032 | 1006 |
1033 | |
1034 void ARMDecoder::DecodeType6(Instr* instr) { | 1007 void ARMDecoder::DecodeType6(Instr* instr) { |
1035 if (instr->IsVFPDoubleTransfer()) { | 1008 if (instr->IsVFPDoubleTransfer()) { |
1036 if (instr->Bit(8) == 0) { | 1009 if (instr->Bit(8) == 0) { |
1037 if (instr->Bit(20) == 1) { | 1010 if (instr->Bit(20) == 1) { |
1038 Format(instr, "vmovrrs'cond 'rd, 'rn, {'sm, 'sm1}"); | 1011 Format(instr, "vmovrrs'cond 'rd, 'rn, {'sm, 'sm1}"); |
1039 } else { | 1012 } else { |
1040 Format(instr, "vmovsrr'cond {'sm, 'sm1}, 'rd, 'rn"); | 1013 Format(instr, "vmovsrr'cond {'sm, 'sm1}, 'rd, 'rn"); |
1041 } | 1014 } |
1042 } else { | 1015 } else { |
1043 if (instr->Bit(20) == 1) { | 1016 if (instr->Bit(20) == 1) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1088 Format(instr, "vstmd'cond'pu 'rn'w, 'dlist"); | 1061 Format(instr, "vstmd'cond'pu 'rn'w, 'dlist"); |
1089 } else { // vstms | 1062 } else { // vstms |
1090 Format(instr, "vstms'cond'pu 'rn'w, 'slist"); | 1063 Format(instr, "vstms'cond'pu 'rn'w, 'slist"); |
1091 } | 1064 } |
1092 } | 1065 } |
1093 } else { | 1066 } else { |
1094 Unknown(instr); | 1067 Unknown(instr); |
1095 } | 1068 } |
1096 } | 1069 } |
1097 | 1070 |
1098 | |
1099 void ARMDecoder::DecodeType7(Instr* instr) { | 1071 void ARMDecoder::DecodeType7(Instr* instr) { |
1100 if (instr->Bit(24) == 1) { | 1072 if (instr->Bit(24) == 1) { |
1101 Format(instr, "svc'cond #'svc"); | 1073 Format(instr, "svc'cond #'svc"); |
1102 } else if (instr->IsVFPDataProcessingOrSingleTransfer()) { | 1074 } else if (instr->IsVFPDataProcessingOrSingleTransfer()) { |
1103 if (instr->Bit(4) == 0) { | 1075 if (instr->Bit(4) == 0) { |
1104 // VFP Data Processing | 1076 // VFP Data Processing |
1105 switch (instr->Bits(20, 4) & 0xb) { | 1077 switch (instr->Bits(20, 4) & 0xb) { |
1106 case 0: { // vmla, vmls floating-point | 1078 case 0: { // vmla, vmls floating-point |
1107 if (instr->Bit(8) == 0) { | 1079 if (instr->Bit(8) == 0) { |
1108 if (instr->Bit(6) == 0) { | 1080 if (instr->Bit(6) == 0) { |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1320 } | 1292 } |
1321 } else { | 1293 } else { |
1322 Unknown(instr); | 1294 Unknown(instr); |
1323 } | 1295 } |
1324 } | 1296 } |
1325 } else { | 1297 } else { |
1326 Unknown(instr); | 1298 Unknown(instr); |
1327 } | 1299 } |
1328 } | 1300 } |
1329 | 1301 |
1330 | |
1331 void ARMDecoder::DecodeSIMDDataProcessing(Instr* instr) { | 1302 void ARMDecoder::DecodeSIMDDataProcessing(Instr* instr) { |
1332 ASSERT(instr->ConditionField() == kSpecialCondition); | 1303 ASSERT(instr->ConditionField() == kSpecialCondition); |
1333 if (instr->Bit(6) == 1) { | 1304 if (instr->Bit(6) == 1) { |
1334 if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 0) && | 1305 if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 0) && |
1335 (instr->Bits(23, 2) == 0)) { | 1306 (instr->Bits(23, 2) == 0)) { |
1336 Format(instr, "vaddq'sz 'qd, 'qn, 'qm"); | 1307 Format(instr, "vaddq'sz 'qd, 'qn, 'qm"); |
1337 } else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 0) && | 1308 } else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 0) && |
1338 (instr->Bits(23, 2) == 0) && (instr->Bit(21) == 0)) { | 1309 (instr->Bits(23, 2) == 0) && (instr->Bit(21) == 0)) { |
1339 Format(instr, "vaddqs 'qd, 'qn, 'qm"); | 1310 Format(instr, "vaddqs 'qd, 'qn, 'qm"); |
1340 } else if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 0) && | 1311 } else if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 0) && |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1450 } else { | 1421 } else { |
1451 if ((instr->Bits(23, 2) == 3) && (instr->Bits(20, 2) == 3) && | 1422 if ((instr->Bits(23, 2) == 3) && (instr->Bits(20, 2) == 3) && |
1452 (instr->Bits(10, 2) == 2) && (instr->Bit(4) == 0)) { | 1423 (instr->Bits(10, 2) == 2) && (instr->Bit(4) == 0)) { |
1453 Format(instr, "vtbl 'dd, 'dtbllist, 'dm"); | 1424 Format(instr, "vtbl 'dd, 'dtbllist, 'dm"); |
1454 } else { | 1425 } else { |
1455 Unknown(instr); | 1426 Unknown(instr); |
1456 } | 1427 } |
1457 } | 1428 } |
1458 } | 1429 } |
1459 | 1430 |
1460 | |
1461 void ARMDecoder::InstructionDecode(uword pc) { | 1431 void ARMDecoder::InstructionDecode(uword pc) { |
1462 Instr* instr = Instr::At(pc); | 1432 Instr* instr = Instr::At(pc); |
1463 | 1433 |
1464 if (instr->ConditionField() == kSpecialCondition) { | 1434 if (instr->ConditionField() == kSpecialCondition) { |
1465 if ((instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) && | 1435 if ((instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) && |
1466 (TargetCPUFeatures::arm_version() != ARMv5TE)) { | 1436 (TargetCPUFeatures::arm_version() != ARMv5TE)) { |
1467 Format(instr, "clrex"); | 1437 Format(instr, "clrex"); |
1468 } else { | 1438 } else { |
1469 if (instr->IsSIMDDataProcessing()) { | 1439 if (instr->IsSIMDDataProcessing()) { |
1470 DecodeSIMDDataProcessing(instr); | 1440 DecodeSIMDDataProcessing(instr); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1505 } | 1475 } |
1506 default: { | 1476 default: { |
1507 // The type field is 3-bits in the ARM encoding. | 1477 // The type field is 3-bits in the ARM encoding. |
1508 UNREACHABLE(); | 1478 UNREACHABLE(); |
1509 break; | 1479 break; |
1510 } | 1480 } |
1511 } | 1481 } |
1512 } | 1482 } |
1513 } | 1483 } |
1514 | 1484 |
1515 | |
1516 void Disassembler::DecodeInstruction(char* hex_buffer, | 1485 void Disassembler::DecodeInstruction(char* hex_buffer, |
1517 intptr_t hex_size, | 1486 intptr_t hex_size, |
1518 char* human_buffer, | 1487 char* human_buffer, |
1519 intptr_t human_size, | 1488 intptr_t human_size, |
1520 int* out_instr_size, | 1489 int* out_instr_size, |
1521 const Code& code, | 1490 const Code& code, |
1522 Object** object, | 1491 Object** object, |
1523 uword pc) { | 1492 uword pc) { |
1524 ARMDecoder decoder(human_buffer, human_size); | 1493 ARMDecoder decoder(human_buffer, human_size); |
1525 decoder.InstructionDecode(pc); | 1494 decoder.InstructionDecode(pc); |
(...skipping 10 matching lines...) Expand all Loading... |
1536 *object = NULL; | 1505 *object = NULL; |
1537 } | 1506 } |
1538 } | 1507 } |
1539 } | 1508 } |
1540 | 1509 |
1541 #endif // !PRODUCT | 1510 #endif // !PRODUCT |
1542 | 1511 |
1543 } // namespace dart | 1512 } // namespace dart |
1544 | 1513 |
1545 #endif // defined TARGET_ARCH_ARM | 1514 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |