| 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 12 matching lines...) Expand all Loading... |
| 23 | 23 |
| 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); | 33 void PrintRegister(int reg, R31Type r31t); |
| 34 void PrintShiftExtendRm(Instr* instr); | 34 void PrintShiftExtendRm(Instr* instr); |
| 35 void PrintS(Instr* instr); | 35 void PrintS(Instr* instr); |
| 36 | 36 |
| 37 // Handle formatting of instructions and their options. | 37 // Handle formatting of instructions and their options. |
| 38 int FormatRegister(Instr* instr, const char* option); | 38 int FormatRegister(Instr* instr, const char* option); |
| 39 int FormatOption(Instr* instr, const char* format); | 39 int FormatOption(Instr* instr, const char* format); |
| 40 void Format(Instr* instr, const char* format); | 40 void Format(Instr* instr, const char* format); |
| 41 void Unknown(Instr* instr); | 41 void Unknown(Instr* instr); |
| 42 | 42 |
| 43 // Decode instructions. | 43 // Decode instructions. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 // See for example the command "objdump -d <binary file>". | 82 // See for example the command "objdump -d <binary file>". |
| 83 static const char* reg_names[kNumberOfCpuRegisters] = { | 83 static const char* reg_names[kNumberOfCpuRegisters] = { |
| 84 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", | 84 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", |
| 85 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", | 85 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", |
| 86 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", | 86 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", |
| 87 "r24", "ip0", "ip1", "pp", "ctx", "fp", "lr", "r31", | 87 "r24", "ip0", "ip1", "pp", "ctx", "fp", "lr", "r31", |
| 88 }; | 88 }; |
| 89 | 89 |
| 90 | 90 |
| 91 // Print the register name according to the active name converter. | 91 // Print the register name according to the active name converter. |
| 92 void ARM64Decoder::PrintRegister(int reg) { | 92 void ARM64Decoder::PrintRegister(int reg, R31Type r31t) { |
| 93 ASSERT(0 <= reg); | 93 ASSERT(0 <= reg); |
| 94 ASSERT(reg < kNumberOfCpuRegisters); | 94 ASSERT(reg < kNumberOfCpuRegisters); |
| 95 Print(reg_names[reg]); | 95 if ((reg == 31)) { |
| 96 const char* rstr = (r31t == R31IsZR) ? "zr" : "sp"; |
| 97 Print(rstr); |
| 98 } else { |
| 99 Print(reg_names[reg]); |
| 100 } |
| 96 } | 101 } |
| 97 | 102 |
| 98 | 103 |
| 99 // These shift names are defined in a way to match the native disassembler | 104 // These shift names are defined in a way to match the native disassembler |
| 100 // formatting. See for example the command "objdump -d <binary file>". | 105 // formatting. See for example the command "objdump -d <binary file>". |
| 101 static const char* shift_names[kMaxShift] = { | 106 static const char* shift_names[kMaxShift] = { |
| 102 "lsl", "lsr", "asr", "ror" | 107 "lsl", "lsr", "asr", "ror" |
| 103 }; | 108 }; |
| 104 | 109 |
| 105 | 110 |
| 106 static const char* extend_names[kMaxExtend] = { | 111 static const char* extend_names[kMaxExtend] = { |
| 107 "uxtb", "uxth", "uxtw", "uxtx", | 112 "uxtb", "uxth", "uxtw", "uxtx", |
| 108 "sxtb", "sxth", "sxtw", "sxtx", | 113 "sxtb", "sxth", "sxtw", "sxtx", |
| 109 }; | 114 }; |
| 110 | 115 |
| 111 | 116 |
| 112 // Print the register shift operands for the instruction. Generally used for | 117 // Print the register shift operands for the instruction. Generally used for |
| 113 // data processing instructions. | 118 // data processing instructions. |
| 114 void ARM64Decoder::PrintShiftExtendRm(Instr* instr) { | 119 void ARM64Decoder::PrintShiftExtendRm(Instr* instr) { |
| 115 int rm = instr->RmField(); | 120 int rm = instr->RmField(); |
| 116 Shift shift = instr->ShiftTypeField(); | 121 Shift shift = instr->ShiftTypeField(); |
| 117 int shift_amount = instr->ShiftAmountField(); | 122 int shift_amount = instr->ShiftAmountField(); |
| 118 Extend extend = instr->ExtendTypeField(); | 123 Extend extend = instr->ExtendTypeField(); |
| 119 int extend_shift_amount = instr->ExtShiftAmountField(); | 124 int extend_shift_amount = instr->ExtShiftAmountField(); |
| 120 | 125 |
| 121 PrintRegister(rm); | 126 PrintRegister(rm, R31IsZR); |
| 122 | 127 |
| 123 if (instr->IsShift() && (shift == LSL) && (shift_amount == 0)) { | 128 if (instr->IsShift() && (shift == LSL) && (shift_amount == 0)) { |
| 124 // Special case for using rm only. | 129 // Special case for using rm only. |
| 125 return; | 130 return; |
| 126 } | 131 } |
| 127 if (instr->IsShift()) { | 132 if (instr->IsShift()) { |
| 128 // by immediate | 133 // by immediate |
| 129 if ((shift == ROR) && (shift_amount == 0)) { | 134 if ((shift == ROR) && (shift_amount == 0)) { |
| 130 Print(", RRX"); | 135 Print(" RRX"); |
| 131 return; | 136 return; |
| 132 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { | 137 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { |
| 133 shift_amount = 32; | 138 shift_amount = 32; |
| 134 } | 139 } |
| 135 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 140 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 136 remaining_size_in_buffer(), | 141 remaining_size_in_buffer(), |
| 137 ", %s #%d", | 142 " %s #%d", |
| 138 shift_names[shift], | 143 shift_names[shift], |
| 139 shift_amount); | 144 shift_amount); |
| 140 } else { | 145 } else { |
| 141 ASSERT(instr->IsExtend()); | 146 ASSERT(instr->IsExtend()); |
| 142 // by register | 147 // by register |
| 143 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 148 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 144 remaining_size_in_buffer(), | 149 remaining_size_in_buffer(), |
| 145 ", %s", | 150 " %s", |
| 146 extend_names[extend]); | 151 extend_names[extend]); |
| 147 if (((instr->SFField() == 1) && (extend == UXTX)) || | 152 if (((instr->SFField() == 1) && (extend == UXTX)) || |
| 148 ((instr->SFField() == 0) && (extend == UXTW))) { | 153 ((instr->SFField() == 0) && (extend == UXTW))) { |
| 149 // Shift amount. | 154 // Shift amount. |
| 150 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 155 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 151 remaining_size_in_buffer(), | 156 remaining_size_in_buffer(), |
| 152 " %d", | 157 " %d", |
| 153 extend_shift_amount); | 158 extend_shift_amount); |
| 154 } | 159 } |
| 155 } | 160 } |
| 156 } | 161 } |
| 157 | 162 |
| 158 | 163 |
| 159 // Handle all register based formatting in these functions to reduce the | 164 // Handle all register based formatting in these functions to reduce the |
| 160 // complexity of FormatOption. | 165 // complexity of FormatOption. |
| 161 int ARM64Decoder::FormatRegister(Instr* instr, const char* format) { | 166 int ARM64Decoder::FormatRegister(Instr* instr, const char* format) { |
| 162 ASSERT(format[0] == 'r'); | 167 ASSERT(format[0] == 'r'); |
| 163 if (format[1] == 'n') { // 'rn: Rn register | 168 if (format[1] == 'n') { // 'rn: Rn register |
| 164 int reg = instr->RnField(); | 169 int reg = instr->RnField(); |
| 165 PrintRegister(reg); | 170 PrintRegister(reg, instr->RnMode()); |
| 166 return 2; | 171 return 2; |
| 167 } else if (format[1] == 'd') { // 'rd: Rd register | 172 } else if (format[1] == 'd') { // 'rd: Rd register |
| 168 int reg = instr->RdField(); | 173 int reg = instr->RdField(); |
| 169 PrintRegister(reg); | 174 PrintRegister(reg, instr->RdMode()); |
| 170 return 2; | 175 return 2; |
| 171 } else if (format[1] == 'm') { // 'rm: Rm register | 176 } else if (format[1] == 'm') { // 'rm: Rm register |
| 172 int reg = instr->RmField(); | 177 int reg = instr->RmField(); |
| 173 PrintRegister(reg); | 178 PrintRegister(reg, R31IsZR); |
| 174 return 2; | 179 return 2; |
| 175 } | 180 } |
| 176 UNREACHABLE(); | 181 UNREACHABLE(); |
| 177 return -1; | 182 return -1; |
| 178 } | 183 } |
| 179 | 184 |
| 180 | 185 |
| 181 // FormatOption takes a formatting string and interprets it based on | 186 // FormatOption takes a formatting string and interprets it based on |
| 182 // the current instructions. The format string points to the first | 187 // the current instructions. The format string points to the first |
| 183 // character of the option string (the option escape has already been | 188 // character of the option string (the option escape has already been |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 Print("s"); | 235 Print("s"); |
| 231 } | 236 } |
| 232 return 1; | 237 return 1; |
| 233 } else { | 238 } else { |
| 234 UNREACHABLE(); | 239 UNREACHABLE(); |
| 235 } | 240 } |
| 236 } | 241 } |
| 237 case 'r': { | 242 case 'r': { |
| 238 return FormatRegister(instr, format); | 243 return FormatRegister(instr, format); |
| 239 } | 244 } |
| 245 case 'h': { |
| 246 ASSERT(STRING_STARTS_WITH(format, "hw")); |
| 247 const int shift = instr->HWField() << 4; |
| 248 if (shift != 0) { |
| 249 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 250 remaining_size_in_buffer(), |
| 251 "lsl %d", |
| 252 shift); |
| 253 } |
| 254 return 2; |
| 255 } |
| 240 default: { | 256 default: { |
| 241 UNREACHABLE(); | 257 UNREACHABLE(); |
| 242 break; | 258 break; |
| 243 } | 259 } |
| 244 } | 260 } |
| 245 UNREACHABLE(); | 261 UNREACHABLE(); |
| 246 return -1; | 262 return -1; |
| 247 } | 263 } |
| 248 | 264 |
| 249 | 265 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 267 // For currently unimplemented decodings the disassembler calls Unknown(instr) | 283 // For currently unimplemented decodings the disassembler calls Unknown(instr) |
| 268 // which will just print "unknown" of the instruction bits. | 284 // which will just print "unknown" of the instruction bits. |
| 269 void ARM64Decoder::Unknown(Instr* instr) { | 285 void ARM64Decoder::Unknown(Instr* instr) { |
| 270 Format(instr, "unknown"); | 286 Format(instr, "unknown"); |
| 271 } | 287 } |
| 272 | 288 |
| 273 | 289 |
| 274 void ARM64Decoder::DecodeMoveWide(Instr* instr) { | 290 void ARM64Decoder::DecodeMoveWide(Instr* instr) { |
| 275 switch (instr->Bits(29, 2)) { | 291 switch (instr->Bits(29, 2)) { |
| 276 case 0: | 292 case 0: |
| 277 Format(instr, "movn'sf 'rd, 'imm16"); | 293 Format(instr, "movn'sf 'rd, 'imm16 'hw"); |
| 278 break; | 294 break; |
| 279 case 2: | 295 case 2: |
| 280 Format(instr, "movz'sf 'rd, 'imm16"); | 296 Format(instr, "movz'sf 'rd, 'imm16 'hw"); |
| 281 break; | 297 break; |
| 282 case 3: | 298 case 3: |
| 283 Format(instr, "movk'sf 'rd, 'imm16"); | 299 Format(instr, "movk'sf 'rd, 'imm16 'hw"); |
| 284 break; | 300 break; |
| 285 default: | 301 default: |
| 286 Unknown(instr); | 302 Unknown(instr); |
| 287 break; | 303 break; |
| 288 } | 304 } |
| 289 } | 305 } |
| 290 | 306 |
| 291 | 307 |
| 292 void ARM64Decoder::DecodeAddSubImm(Instr* instr) { | 308 void ARM64Decoder::DecodeAddSubImm(Instr* instr) { |
| 293 switch (instr->Bit(30)) { | 309 switch (instr->Bit(30)) { |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 human_buffer, | 493 human_buffer, |
| 478 sizeof(human_buffer), | 494 sizeof(human_buffer), |
| 479 pc); | 495 pc); |
| 480 pc += instruction_length; | 496 pc += instruction_length; |
| 481 } | 497 } |
| 482 } | 498 } |
| 483 | 499 |
| 484 } // namespace dart | 500 } // namespace dart |
| 485 | 501 |
| 486 #endif // defined TARGET_ARCH_ARM | 502 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |