OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64. | 7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
8 #if defined(TARGET_ARCH_ARM64) | 8 #if defined(TARGET_ARCH_ARM64) |
9 #include "platform/assert.h" | 9 #include "platform/assert.h" |
10 | 10 |
(...skipping 13 matching lines...) Expand all Loading... |
24 // Writes one disassembled instruction into 'buffer' (0-terminated). | 24 // Writes one disassembled instruction into 'buffer' (0-terminated). |
25 // Returns true if the instruction was successfully decoded, false otherwise. | 25 // Returns true if the instruction was successfully decoded, false otherwise. |
26 void InstructionDecode(uword pc); | 26 void InstructionDecode(uword pc); |
27 | 27 |
28 private: | 28 private: |
29 // Bottleneck functions to print into the out_buffer. | 29 // Bottleneck functions to print into the out_buffer. |
30 void Print(const char* str); | 30 void Print(const char* str); |
31 | 31 |
32 // Printing of common values. | 32 // Printing of common values. |
33 void PrintRegister(int reg, R31Type r31t); | 33 void PrintRegister(int reg, R31Type r31t); |
| 34 void PrintVRegister(int reg); |
34 void PrintShiftExtendRm(Instr* instr); | 35 void PrintShiftExtendRm(Instr* instr); |
35 void PrintMemOperand(Instr* instr); | 36 void PrintMemOperand(Instr* instr); |
36 void PrintS(Instr* instr); | 37 void PrintS(Instr* instr); |
37 void PrintCondition(Instr* instr); | 38 void PrintCondition(Instr* instr); |
38 | 39 |
39 // Handle formatting of instructions and their options. | 40 // Handle formatting of instructions and their options. |
40 int FormatRegister(Instr* instr, const char* option); | 41 int FormatRegister(Instr* instr, const char* option); |
| 42 int FormatVRegister(Instr*instr, const char* option); |
41 int FormatOption(Instr* instr, const char* format); | 43 int FormatOption(Instr* instr, const char* format); |
42 void Format(Instr* instr, const char* format); | 44 void Format(Instr* instr, const char* format); |
43 void Unknown(Instr* instr); | 45 void Unknown(Instr* instr); |
44 | 46 |
45 // Decode instructions. | 47 // Decode instructions. |
46 #define DECODE_OP(op) \ | 48 #define DECODE_OP(op) \ |
47 void Decode##op(Instr* instr); | 49 void Decode##op(Instr* instr); |
48 APPLY_OP_LIST(DECODE_OP) | 50 APPLY_OP_LIST(DECODE_OP) |
49 #undef DECODE_OP | 51 #undef DECODE_OP |
50 | 52 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 ASSERT(reg < kNumberOfCpuRegisters); | 98 ASSERT(reg < kNumberOfCpuRegisters); |
97 if (reg == 31) { | 99 if (reg == 31) { |
98 const char* rstr = (r31t == R31IsZR) ? "zr" : "sp"; | 100 const char* rstr = (r31t == R31IsZR) ? "zr" : "sp"; |
99 Print(rstr); | 101 Print(rstr); |
100 } else { | 102 } else { |
101 Print(reg_names[reg]); | 103 Print(reg_names[reg]); |
102 } | 104 } |
103 } | 105 } |
104 | 106 |
105 | 107 |
| 108 void ARM64Decoder::PrintVRegister(int reg) { |
| 109 ASSERT(0 <= reg); |
| 110 ASSERT(reg < kNumberOfVRegisters); |
| 111 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 112 remaining_size_in_buffer(), |
| 113 "v%d", reg); |
| 114 } |
| 115 |
| 116 |
106 // These shift names are defined in a way to match the native disassembler | 117 // These shift names are defined in a way to match the native disassembler |
107 // formatting. See for example the command "objdump -d <binary file>". | 118 // formatting. See for example the command "objdump -d <binary file>". |
108 static const char* shift_names[kMaxShift] = { | 119 static const char* shift_names[kMaxShift] = { |
109 "lsl", "lsr", "asr", "ror" | 120 "lsl", "lsr", "asr", "ror" |
110 }; | 121 }; |
111 | 122 |
112 | 123 |
113 static const char* extend_names[kMaxExtend] = { | 124 static const char* extend_names[kMaxExtend] = { |
114 "uxtb", "uxth", "uxtw", "uxtx", | 125 "uxtb", "uxth", "uxtw", "uxtx", |
115 "sxtb", "sxth", "sxtw", "sxtx", | 126 "sxtb", "sxth", "sxtw", "sxtx", |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 } else if (format[1] == 'a') { // 'ra: Ra register | 295 } else if (format[1] == 'a') { // 'ra: Ra register |
285 int reg = instr->RaField(); | 296 int reg = instr->RaField(); |
286 PrintRegister(reg, R31IsZR); | 297 PrintRegister(reg, R31IsZR); |
287 return 2; | 298 return 2; |
288 } | 299 } |
289 UNREACHABLE(); | 300 UNREACHABLE(); |
290 return -1; | 301 return -1; |
291 } | 302 } |
292 | 303 |
293 | 304 |
| 305 int ARM64Decoder::FormatVRegister(Instr* instr, const char* format) { |
| 306 ASSERT(format[0] == 'v'); |
| 307 if (format[1] == 'd') { |
| 308 int reg = instr->VdField(); |
| 309 PrintVRegister(reg); |
| 310 return 2; |
| 311 } else if (format[1] == 'n') { |
| 312 int reg = instr->VnField(); |
| 313 PrintVRegister(reg); |
| 314 return 2; |
| 315 } |
| 316 UNREACHABLE(); |
| 317 return -1; |
| 318 } |
| 319 |
| 320 |
294 // FormatOption takes a formatting string and interprets it based on | 321 // FormatOption takes a formatting string and interprets it based on |
295 // the current instructions. The format string points to the first | 322 // the current instructions. The format string points to the first |
296 // character of the option string (the option escape has already been | 323 // character of the option string (the option escape has already been |
297 // consumed by the caller.) FormatOption returns the number of | 324 // consumed by the caller.) FormatOption returns the number of |
298 // characters that were consumed from the formatting string. | 325 // characters that were consumed from the formatting string. |
299 int ARM64Decoder::FormatOption(Instr* instr, const char* format) { | 326 int ARM64Decoder::FormatOption(Instr* instr, const char* format) { |
300 switch (format[0]) { | 327 switch (format[0]) { |
301 case 'b': { | 328 case 'b': { |
302 if (format[3] == 'i') { | 329 if (format[3] == 'i') { |
303 ASSERT(STRING_STARTS_WITH(format, "bitimm")); | 330 ASSERT(STRING_STARTS_WITH(format, "bitimm")); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 ASSERT(STRING_STARTS_WITH(format, "hw")); | 383 ASSERT(STRING_STARTS_WITH(format, "hw")); |
357 const int shift = instr->HWField() << 4; | 384 const int shift = instr->HWField() << 4; |
358 if (shift != 0) { | 385 if (shift != 0) { |
359 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 386 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
360 remaining_size_in_buffer(), | 387 remaining_size_in_buffer(), |
361 "lsl %d", | 388 "lsl %d", |
362 shift); | 389 shift); |
363 } | 390 } |
364 return 2; | 391 return 2; |
365 } | 392 } |
366 case 'i': { // 'imm12, imm16 | 393 case 'i': { // 'imm12, 'imm16, 'immd |
367 uint64_t imm; | 394 if (format[3] == '1') { |
368 int ret = 5; | 395 uint64_t imm; |
369 if (format[4] == '2') { | 396 int ret = 5; |
370 ASSERT(STRING_STARTS_WITH(format, "imm12")); | 397 if (format[4] == '2') { |
371 imm = instr->Imm12Field(); | 398 ASSERT(STRING_STARTS_WITH(format, "imm12")); |
372 if (format[5] == 's') { | 399 imm = instr->Imm12Field(); |
373 // shifted immediate. | 400 if (format[5] == 's') { |
374 if (instr->Imm12ShiftField() == 1) { | 401 // shifted immediate. |
375 imm = imm << 12; | 402 if (instr->Imm12ShiftField() == 1) { |
376 } else if ((instr->Imm12ShiftField() & 0x2) != 0) { | 403 imm = imm << 12; |
377 Print("Unknown Shift"); | 404 } else if ((instr->Imm12ShiftField() & 0x2) != 0) { |
| 405 Print("Unknown Shift"); |
| 406 } |
| 407 ret = 6; |
378 } | 408 } |
379 ret = 6; | 409 } else { |
| 410 ASSERT(STRING_STARTS_WITH(format, "imm16")); |
| 411 imm = instr->Imm16Field(); |
380 } | 412 } |
| 413 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 414 remaining_size_in_buffer(), |
| 415 "0x%"Px64, |
| 416 imm); |
| 417 return ret; |
381 } else { | 418 } else { |
382 ASSERT(STRING_STARTS_WITH(format, "imm16")); | 419 ASSERT(STRING_STARTS_WITH(format, "immd")); |
383 imm = instr->Imm16Field(); | 420 double dimm = bit_cast<double, int64_t>( |
| 421 Instr::VFPExpandImm(instr->Imm8Field())); |
| 422 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 423 remaining_size_in_buffer(), |
| 424 "%f", |
| 425 dimm); |
| 426 return 4; |
384 } | 427 } |
385 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | |
386 remaining_size_in_buffer(), | |
387 "0x%"Px64, | |
388 imm); | |
389 return ret; | |
390 } | 428 } |
391 case 'm': { | 429 case 'm': { |
392 ASSERT(STRING_STARTS_WITH(format, "memop")); | 430 ASSERT(STRING_STARTS_WITH(format, "memop")); |
393 PrintMemOperand(instr); | 431 PrintMemOperand(instr); |
394 return 5; | 432 return 5; |
395 } | 433 } |
396 case 'p': { | 434 case 'p': { |
397 if (format[2] == 'a') { | 435 if (format[2] == 'a') { |
398 ASSERT(STRING_STARTS_WITH(format, "pcadr")); | 436 ASSERT(STRING_STARTS_WITH(format, "pcadr")); |
399 const int64_t immhi = instr->SImm19Field(); | 437 const int64_t immhi = instr->SImm19Field(); |
(...skipping 13 matching lines...) Expand all Loading... |
413 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 451 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
414 remaining_size_in_buffer(), | 452 remaining_size_in_buffer(), |
415 "0x%"Px64, | 453 "0x%"Px64, |
416 dest); | 454 dest); |
417 } | 455 } |
418 return 5; | 456 return 5; |
419 } | 457 } |
420 case 'r': { | 458 case 'r': { |
421 return FormatRegister(instr, format); | 459 return FormatRegister(instr, format); |
422 } | 460 } |
| 461 case 'v': { |
| 462 return FormatVRegister(instr, format); |
| 463 } |
423 case 's': { // 's: S flag. | 464 case 's': { // 's: S flag. |
424 if (format[1] == 'h') { | 465 if (format[1] == 'h') { |
425 ASSERT(STRING_STARTS_WITH(format, "shift_op")); | 466 ASSERT(STRING_STARTS_WITH(format, "shift_op")); |
426 PrintShiftExtendRm(instr); | 467 PrintShiftExtendRm(instr); |
427 return 8; | 468 return 8; |
428 } else if (format[1] == 'f') { | 469 } else if (format[1] == 'f') { |
429 ASSERT(STRING_STARTS_WITH(format, "sf")); | 470 ASSERT(STRING_STARTS_WITH(format, "sf")); |
430 if (instr->SFField() == 1) { | 471 if (instr->SFField() == 1) { |
431 // TODO(zra): If we don't use the w form much, we can omit printing | 472 // TODO(zra): If we don't use the w form much, we can omit printing |
432 // this x. | 473 // this x. |
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
872 Unknown(instr); | 913 Unknown(instr); |
873 } | 914 } |
874 } | 915 } |
875 | 916 |
876 | 917 |
877 void ARM64Decoder::DecodeDPSimd1(Instr* instr) { | 918 void ARM64Decoder::DecodeDPSimd1(Instr* instr) { |
878 Unknown(instr); | 919 Unknown(instr); |
879 } | 920 } |
880 | 921 |
881 | 922 |
| 923 void ARM64Decoder::DecodeFPImm(Instr* instr) { |
| 924 if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) || (instr->Bit(23) != 0) || |
| 925 (instr->Bits(5, 5) != 0)) { |
| 926 Unknown(instr); |
| 927 return; |
| 928 } |
| 929 if (instr->Bit(22) == 1) { |
| 930 // Double. |
| 931 Format(instr, "fmovd 'vd, 'immd"); |
| 932 } else { |
| 933 // Single. |
| 934 Unknown(instr); |
| 935 } |
| 936 } |
| 937 |
| 938 |
| 939 void ARM64Decoder::DecodeFPIntCvt(Instr* instr) { |
| 940 if ((instr->SFField() != 1) || (instr->Bit(29) != 0) || |
| 941 (instr->Bits(22, 2) != 1)) { |
| 942 Unknown(instr); |
| 943 return; |
| 944 } |
| 945 if (instr->Bits(16, 3) == 6) { |
| 946 Format(instr, "fmovrd 'rd, 'vn"); |
| 947 } else if (instr->Bits(16, 3) == 7) { |
| 948 Format(instr, "fmovdr 'vd, 'rn"); |
| 949 } else { |
| 950 Unknown(instr); |
| 951 } |
| 952 } |
| 953 |
| 954 |
| 955 void ARM64Decoder::DecodeFP(Instr* instr) { |
| 956 if (instr->IsFPImmOp()) { |
| 957 DecodeFPImm(instr); |
| 958 } else if (instr->IsFPIntCvtOp()) { |
| 959 DecodeFPIntCvt(instr); |
| 960 } else { |
| 961 Unknown(instr); |
| 962 } |
| 963 } |
| 964 |
| 965 |
882 void ARM64Decoder::DecodeDPSimd2(Instr* instr) { | 966 void ARM64Decoder::DecodeDPSimd2(Instr* instr) { |
883 Unknown(instr); | 967 if (instr->IsFPOp()) { |
| 968 DecodeFP(instr); |
| 969 } else { |
| 970 Unknown(instr); |
| 971 } |
884 } | 972 } |
885 | 973 |
886 | 974 |
887 void ARM64Decoder::InstructionDecode(uword pc) { | 975 void ARM64Decoder::InstructionDecode(uword pc) { |
888 Instr* instr = Instr::At(pc); | 976 Instr* instr = Instr::At(pc); |
889 | 977 |
890 if (instr->IsDPImmediateOp()) { | 978 if (instr->IsDPImmediateOp()) { |
891 DecodeDPImmediate(instr); | 979 DecodeDPImmediate(instr); |
892 } else if (instr->IsCompareBranchOp()) { | 980 } else if (instr->IsCompareBranchOp()) { |
893 DecodeCompareBranch(instr); | 981 DecodeCompareBranch(instr); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
946 human_buffer, | 1034 human_buffer, |
947 sizeof(human_buffer), | 1035 sizeof(human_buffer), |
948 pc); | 1036 pc); |
949 pc += instruction_length; | 1037 pc += instruction_length; |
950 } | 1038 } |
951 } | 1039 } |
952 | 1040 |
953 } // namespace dart | 1041 } // namespace dart |
954 | 1042 |
955 #endif // defined TARGET_ARCH_ARM | 1043 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |