| 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 |