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 |