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 #include "vm/instructions.h" | 10 #include "vm/instructions.h" |
11 | 11 |
12 namespace dart { | 12 namespace dart { |
13 | 13 |
14 #ifndef PRODUCT | 14 #ifndef PRODUCT |
15 | 15 |
16 class ARM64Decoder : public ValueObject { | 16 class ARM64Decoder : public ValueObject { |
17 public: | 17 public: |
18 ARM64Decoder(char* buffer, size_t buffer_size) | 18 ARM64Decoder(char* buffer, size_t buffer_size) |
19 : buffer_(buffer), | 19 : buffer_(buffer), buffer_size_(buffer_size), buffer_pos_(0) { |
20 buffer_size_(buffer_size), | |
21 buffer_pos_(0) { | |
22 buffer_[buffer_pos_] = '\0'; | 20 buffer_[buffer_pos_] = '\0'; |
23 } | 21 } |
24 | 22 |
25 ~ARM64Decoder() {} | 23 ~ARM64Decoder() {} |
26 | 24 |
27 // Writes one disassembled instruction into 'buffer' (0-terminated). | 25 // Writes one disassembled instruction into 'buffer' (0-terminated). |
28 // Returns true if the instruction was successfully decoded, false otherwise. | 26 // Returns true if the instruction was successfully decoded, false otherwise. |
29 void InstructionDecode(uword pc); | 27 void InstructionDecode(uword pc); |
30 | 28 |
31 private: | 29 private: |
32 // Bottleneck functions to print into the out_buffer. | 30 // Bottleneck functions to print into the out_buffer. |
33 void Print(const char* str); | 31 void Print(const char* str); |
34 | 32 |
35 // Printing of common values. | 33 // Printing of common values. |
36 void PrintRegister(int reg, R31Type r31t); | 34 void PrintRegister(int reg, R31Type r31t); |
37 void PrintVRegister(int reg); | 35 void PrintVRegister(int reg); |
38 void PrintShiftExtendRm(Instr* instr); | 36 void PrintShiftExtendRm(Instr* instr); |
39 void PrintMemOperand(Instr* instr); | 37 void PrintMemOperand(Instr* instr); |
40 void PrintPairMemOperand(Instr* instr); | 38 void PrintPairMemOperand(Instr* instr); |
41 void PrintS(Instr* instr); | 39 void PrintS(Instr* instr); |
42 void PrintCondition(Instr* instr); | 40 void PrintCondition(Instr* instr); |
43 | 41 |
44 // Handle formatting of instructions and their options. | 42 // Handle formatting of instructions and their options. |
45 int FormatRegister(Instr* instr, const char* option); | 43 int FormatRegister(Instr* instr, const char* option); |
46 int FormatVRegister(Instr*instr, const char* option); | 44 int FormatVRegister(Instr* instr, const char* option); |
47 int FormatOption(Instr* instr, const char* format); | 45 int FormatOption(Instr* instr, const char* format); |
48 void Format(Instr* instr, const char* format); | 46 void Format(Instr* instr, const char* format); |
49 void Unknown(Instr* instr); | 47 void Unknown(Instr* instr); |
50 | 48 |
51 // Decode instructions. | 49 // Decode instructions. |
52 #define DECODE_OP(op) \ | 50 #define DECODE_OP(op) void Decode##op(Instr* instr); |
53 void Decode##op(Instr* instr); | |
54 APPLY_OP_LIST(DECODE_OP) | 51 APPLY_OP_LIST(DECODE_OP) |
55 #undef DECODE_OP | 52 #undef DECODE_OP |
56 | 53 |
57 | 54 |
58 // Convenience functions. | 55 // Convenience functions. |
59 char* get_buffer() const { return buffer_; } | 56 char* get_buffer() const { return buffer_; } |
60 char* current_position_in_buffer() { return buffer_ + buffer_pos_; } | 57 char* current_position_in_buffer() { return buffer_ + buffer_pos_; } |
61 size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; } | 58 size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; } |
62 | 59 |
63 char* buffer_; // Decode instructions into this buffer. | 60 char* buffer_; // Decode instructions into this buffer. |
64 size_t buffer_size_; // The size of the character buffer. | 61 size_t buffer_size_; // The size of the character buffer. |
65 size_t buffer_pos_; // Current character position in buffer. | 62 size_t buffer_pos_; // Current character position in buffer. |
66 | 63 |
67 DISALLOW_ALLOCATION(); | 64 DISALLOW_ALLOCATION(); |
68 DISALLOW_COPY_AND_ASSIGN(ARM64Decoder); | 65 DISALLOW_COPY_AND_ASSIGN(ARM64Decoder); |
69 }; | 66 }; |
70 | 67 |
71 | 68 |
72 // Support for assertions in the ARM64Decoder formatting functions. | 69 // Support for assertions in the ARM64Decoder formatting functions. |
73 #define STRING_STARTS_WITH(string, compare_string) \ | 70 #define STRING_STARTS_WITH(string, compare_string) \ |
74 (strncmp(string, compare_string, strlen(compare_string)) == 0) | 71 (strncmp(string, compare_string, strlen(compare_string)) == 0) |
75 | 72 |
76 | 73 |
77 // Append the str to the output buffer. | 74 // Append the str to the output buffer. |
78 void ARM64Decoder::Print(const char* str) { | 75 void ARM64Decoder::Print(const char* str) { |
79 char cur = *str++; | 76 char cur = *str++; |
80 while (cur != '\0' && (buffer_pos_ < (buffer_size_ - 1))) { | 77 while (cur != '\0' && (buffer_pos_ < (buffer_size_ - 1))) { |
81 buffer_[buffer_pos_++] = cur; | 78 buffer_[buffer_pos_++] = cur; |
82 cur = *str++; | 79 cur = *str++; |
83 } | 80 } |
84 buffer_[buffer_pos_] = '\0'; | 81 buffer_[buffer_pos_] = '\0'; |
85 } | 82 } |
86 | 83 |
87 | 84 |
88 // These register names are defined in a way to match the native disassembler | 85 // These register names are defined in a way to match the native disassembler |
89 // formatting, except for register aliases ctx (r9), pp (r10) and sp (r19). | 86 // formatting, except for register aliases ctx (r9), pp (r10) and sp (r19). |
90 // See for example the command "objdump -d <binary file>". | 87 // See for example the command "objdump -d <binary file>". |
91 static const char* reg_names[kNumberOfCpuRegisters] = { | 88 static const char* reg_names[kNumberOfCpuRegisters] = { |
92 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", | 89 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", |
93 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", | 90 "r11", "r12", "r13", "r14", "r15", "ip0", "ip1", "r18", "sp", "r20", "r21", |
94 "ip0", "ip1", "r18", "sp", "r20", "r21", "r22", "r23", | 91 "r22", "r23", "r24", "r25", "thr", "pp", "ctx", "fp", "lr", "r31", |
95 "r24", "r25", "thr", "pp", "ctx", "fp", "lr", "r31", | |
96 }; | 92 }; |
97 | 93 |
98 | 94 |
99 // Print the register name according to the active name converter. | 95 // Print the register name according to the active name converter. |
100 void ARM64Decoder::PrintRegister(int reg, R31Type r31t) { | 96 void ARM64Decoder::PrintRegister(int reg, R31Type r31t) { |
101 ASSERT(0 <= reg); | 97 ASSERT(0 <= reg); |
102 ASSERT(reg < kNumberOfCpuRegisters); | 98 ASSERT(reg < kNumberOfCpuRegisters); |
103 if (reg == 31) { | 99 if (reg == 31) { |
104 const char* rstr = (r31t == R31IsZR) ? "zr" : "csp"; | 100 const char* rstr = (r31t == R31IsZR) ? "zr" : "csp"; |
105 Print(rstr); | 101 Print(rstr); |
106 } else { | 102 } else { |
107 Print(reg_names[reg]); | 103 Print(reg_names[reg]); |
108 } | 104 } |
109 } | 105 } |
110 | 106 |
111 | 107 |
112 void ARM64Decoder::PrintVRegister(int reg) { | 108 void ARM64Decoder::PrintVRegister(int reg) { |
113 ASSERT(0 <= reg); | 109 ASSERT(0 <= reg); |
114 ASSERT(reg < kNumberOfVRegisters); | 110 ASSERT(reg < kNumberOfVRegisters); |
115 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 111 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
116 remaining_size_in_buffer(), | 112 remaining_size_in_buffer(), "v%d", reg); |
117 "v%d", reg); | |
118 } | 113 } |
119 | 114 |
120 | 115 |
121 // These shift names are defined in a way to match the native disassembler | 116 // These shift names are defined in a way to match the native disassembler |
122 // formatting. See for example the command "objdump -d <binary file>". | 117 // formatting. See for example the command "objdump -d <binary file>". |
123 static const char* shift_names[kMaxShift] = { | 118 static const char* shift_names[kMaxShift] = {"lsl", "lsr", "asr", "ror"}; |
124 "lsl", "lsr", "asr", "ror" | |
125 }; | |
126 | 119 |
127 | 120 |
128 static const char* extend_names[kMaxExtend] = { | 121 static const char* extend_names[kMaxExtend] = { |
129 "uxtb", "uxth", "uxtw", "uxtx", | 122 "uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx", |
130 "sxtb", "sxth", "sxtw", "sxtx", | |
131 }; | 123 }; |
132 | 124 |
133 | 125 |
134 // These condition names are defined in a way to match the native disassembler | 126 // These condition names are defined in a way to match the native disassembler |
135 // formatting. See for example the command "objdump -d <binary file>". | 127 // formatting. See for example the command "objdump -d <binary file>". |
136 static const char* cond_names[kMaxCondition] = { | 128 static const char* cond_names[kMaxCondition] = { |
137 "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" , | 129 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", |
138 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid", | 130 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid", |
139 }; | 131 }; |
140 | 132 |
141 | 133 |
142 // Print the condition guarding the instruction. | 134 // Print the condition guarding the instruction. |
143 void ARM64Decoder::PrintCondition(Instr* instr) { | 135 void ARM64Decoder::PrintCondition(Instr* instr) { |
144 if (instr->IsConditionalSelectOp()) { | 136 if (instr->IsConditionalSelectOp()) { |
145 Print(cond_names[instr->SelectConditionField()]); | 137 Print(cond_names[instr->SelectConditionField()]); |
146 } else { | 138 } else { |
147 Print(cond_names[instr->ConditionField()]); | 139 Print(cond_names[instr->ConditionField()]); |
148 } | 140 } |
(...skipping 16 matching lines...) Expand all Loading... |
165 return; | 157 return; |
166 } | 158 } |
167 if (instr->IsShift()) { | 159 if (instr->IsShift()) { |
168 // by immediate | 160 // by immediate |
169 if ((shift == ROR) && (shift_amount == 0)) { | 161 if ((shift == ROR) && (shift_amount == 0)) { |
170 Print(" RRX"); | 162 Print(" RRX"); |
171 return; | 163 return; |
172 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { | 164 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { |
173 shift_amount = 32; | 165 shift_amount = 32; |
174 } | 166 } |
175 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 167 buffer_pos_ += |
176 remaining_size_in_buffer(), | 168 OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(), |
177 " %s #%d", | 169 " %s #%d", shift_names[shift], shift_amount); |
178 shift_names[shift], | |
179 shift_amount); | |
180 } else { | 170 } else { |
181 ASSERT(instr->IsExtend()); | 171 ASSERT(instr->IsExtend()); |
182 // by register | 172 // by register |
183 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 173 buffer_pos_ += |
184 remaining_size_in_buffer(), | 174 OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(), |
185 " %s", | 175 " %s", extend_names[extend]); |
186 extend_names[extend]); | |
187 if (((instr->SFField() == 1) && (extend == UXTX)) || | 176 if (((instr->SFField() == 1) && (extend == UXTX)) || |
188 ((instr->SFField() == 0) && (extend == UXTW))) { | 177 ((instr->SFField() == 0) && (extend == UXTW))) { |
189 // Shift amount. | 178 // Shift amount. |
190 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 179 buffer_pos_ += |
191 remaining_size_in_buffer(), | 180 OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(), |
192 " %d", | 181 " %d", extend_shift_amount); |
193 extend_shift_amount); | |
194 } | 182 } |
195 } | 183 } |
196 } | 184 } |
197 | 185 |
198 | 186 |
199 void ARM64Decoder::PrintMemOperand(Instr* instr) { | 187 void ARM64Decoder::PrintMemOperand(Instr* instr) { |
200 const Register rn = instr->RnField(); | 188 const Register rn = instr->RnField(); |
201 if (instr->Bit(24) == 1) { | 189 if (instr->Bit(24) == 1) { |
202 // rn + scaled unsigned 12-bit immediate offset. | 190 // rn + scaled unsigned 12-bit immediate offset. |
203 const uint32_t scale = instr->SzField(); | 191 const uint32_t scale = instr->SzField(); |
204 const uint32_t imm12 = instr->Imm12Field(); | 192 const uint32_t imm12 = instr->Imm12Field(); |
205 const uint32_t off = imm12 << scale; | 193 const uint32_t off = imm12 << scale; |
206 Print("["); | 194 Print("["); |
207 PrintRegister(rn, R31IsSP); | 195 PrintRegister(rn, R31IsSP); |
208 if (off != 0) { | 196 if (off != 0) { |
209 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 197 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
210 remaining_size_in_buffer(), | 198 remaining_size_in_buffer(), ", #%d", off); |
211 ", #%d", | |
212 off); | |
213 } | 199 } |
214 Print("]"); | 200 Print("]"); |
215 } else { | 201 } else { |
216 switch (instr->Bits(10, 2)) { | 202 switch (instr->Bits(10, 2)) { |
217 case 0: { | 203 case 0: { |
218 // rn + signed 9-bit immediate, pre-index, no writeback. | 204 // rn + signed 9-bit immediate, pre-index, no writeback. |
219 const int32_t imm9 = instr->SImm9Field(); | 205 const int32_t imm9 = instr->SImm9Field(); |
220 Print("["); | 206 Print("["); |
221 PrintRegister(rn, R31IsSP); | 207 PrintRegister(rn, R31IsSP); |
222 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 208 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
223 remaining_size_in_buffer(), | 209 remaining_size_in_buffer(), ", #%d", imm9); |
224 ", #%d", | |
225 imm9); | |
226 Print("]"); | 210 Print("]"); |
227 break; | 211 break; |
228 } | 212 } |
229 case 1: { | 213 case 1: { |
230 const int32_t imm9 = instr->SImm9Field(); | 214 const int32_t imm9 = instr->SImm9Field(); |
231 // rn + signed 9-bit immediate, post-index, writeback. | 215 // rn + signed 9-bit immediate, post-index, writeback. |
232 Print("["); | 216 Print("["); |
233 PrintRegister(rn, R31IsSP); | 217 PrintRegister(rn, R31IsSP); |
234 Print("]"); | 218 Print("]"); |
235 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 219 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
236 remaining_size_in_buffer(), | 220 remaining_size_in_buffer(), ", #%d !", imm9); |
237 ", #%d !", | |
238 imm9); | |
239 break; | 221 break; |
240 } | 222 } |
241 case 2: { | 223 case 2: { |
242 const Register rm = instr->RmField(); | 224 const Register rm = instr->RmField(); |
243 const Extend ext = instr->ExtendTypeField(); | 225 const Extend ext = instr->ExtendTypeField(); |
244 const int s = instr->Bit(12); | 226 const int s = instr->Bit(12); |
245 Print("["); | 227 Print("["); |
246 PrintRegister(rn, R31IsSP); | 228 PrintRegister(rn, R31IsSP); |
247 Print(", "); | 229 Print(", "); |
248 PrintRegister(rm, R31IsZR); | 230 PrintRegister(rm, R31IsZR); |
249 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 231 buffer_pos_ += |
250 remaining_size_in_buffer(), | 232 OS::SNPrint(current_position_in_buffer(), |
251 " %s", | 233 remaining_size_in_buffer(), " %s", extend_names[ext]); |
252 extend_names[ext]); | |
253 if (s == 1) { | 234 if (s == 1) { |
254 Print(" scaled"); | 235 Print(" scaled"); |
255 } | 236 } |
256 Print("]"); | 237 Print("]"); |
257 break; | 238 break; |
258 } | 239 } |
259 case 3: { | 240 case 3: { |
260 const int32_t imm9 = instr->SImm9Field(); | 241 const int32_t imm9 = instr->SImm9Field(); |
261 // rn + signed 9-bit immediate, pre-index, writeback. | 242 // rn + signed 9-bit immediate, pre-index, writeback. |
262 Print("["); | 243 Print("["); |
263 PrintRegister(rn, R31IsSP); | 244 PrintRegister(rn, R31IsSP); |
264 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 245 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
265 remaining_size_in_buffer(), | 246 remaining_size_in_buffer(), ", #%d", imm9); |
266 ", #%d", | |
267 imm9); | |
268 Print("] !"); | 247 Print("] !"); |
269 break; | 248 break; |
270 } | 249 } |
271 default: { | 250 default: { Print("???"); } |
272 Print("???"); | |
273 } | |
274 } | 251 } |
275 } | 252 } |
276 } | 253 } |
277 | 254 |
278 | 255 |
279 void ARM64Decoder::PrintPairMemOperand(Instr* instr) { | 256 void ARM64Decoder::PrintPairMemOperand(Instr* instr) { |
280 const Register rn = instr->RnField(); | 257 const Register rn = instr->RnField(); |
281 const int32_t simm7 = instr->SImm7Field(); | 258 const int32_t simm7 = instr->SImm7Field(); |
282 const int32_t offset = simm7 << (2 + instr->Bit(31)); | 259 const int32_t offset = simm7 << (2 + instr->Bit(31)); |
283 Print("["); | 260 Print("["); |
284 PrintRegister(rn, R31IsSP); | 261 PrintRegister(rn, R31IsSP); |
285 switch (instr->Bits(23, 3)) { | 262 switch (instr->Bits(23, 3)) { |
286 case 1: | 263 case 1: |
287 // rn + (imm7 << (2 + B31)), post-index, writeback. | 264 // rn + (imm7 << (2 + B31)), post-index, writeback. |
288 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 265 buffer_pos_ += |
289 remaining_size_in_buffer(), | 266 OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(), |
290 "], #%d !", | 267 "], #%d !", offset); |
291 offset); | |
292 break; | 268 break; |
293 case 2: | 269 case 2: |
294 // rn + (imm7 << (2 + B31)), pre-index, no writeback. | 270 // rn + (imm7 << (2 + B31)), pre-index, no writeback. |
295 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 271 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
296 remaining_size_in_buffer(), | 272 remaining_size_in_buffer(), ", #%d ]", offset); |
297 ", #%d ]", | |
298 offset); | |
299 break; | 273 break; |
300 case 3: | 274 case 3: |
301 // rn + (imm7 << (2 + B31)), pre-index, writeback. | 275 // rn + (imm7 << (2 + B31)), pre-index, writeback. |
302 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 276 buffer_pos_ += |
303 remaining_size_in_buffer(), | 277 OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(), |
304 ", #%d ]!", | 278 ", #%d ]!", offset); |
305 offset); | |
306 break; | 279 break; |
307 default: | 280 default: |
308 Print(", ???]"); | 281 Print(", ???]"); |
309 break; | 282 break; |
310 } | 283 } |
311 } | 284 } |
312 | 285 |
313 | 286 |
314 // Handle all register based formatting in these functions to reduce the | 287 // Handle all register based formatting in these functions to reduce the |
315 // complexity of FormatOption. | 288 // complexity of FormatOption. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 // character of the option string (the option escape has already been | 347 // character of the option string (the option escape has already been |
375 // consumed by the caller.) FormatOption returns the number of | 348 // consumed by the caller.) FormatOption returns the number of |
376 // characters that were consumed from the formatting string. | 349 // characters that were consumed from the formatting string. |
377 int ARM64Decoder::FormatOption(Instr* instr, const char* format) { | 350 int ARM64Decoder::FormatOption(Instr* instr, const char* format) { |
378 switch (format[0]) { | 351 switch (format[0]) { |
379 case 'b': { | 352 case 'b': { |
380 if (format[3] == 'i') { | 353 if (format[3] == 'i') { |
381 ASSERT(STRING_STARTS_WITH(format, "bitimm")); | 354 ASSERT(STRING_STARTS_WITH(format, "bitimm")); |
382 const uint64_t imm = instr->ImmLogical(); | 355 const uint64_t imm = instr->ImmLogical(); |
383 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 356 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
384 remaining_size_in_buffer(), | 357 remaining_size_in_buffer(), "0x%" Px64, imm); |
385 "0x%" Px64, | |
386 imm); | |
387 return 6; | 358 return 6; |
388 } else { | 359 } else { |
389 ASSERT(STRING_STARTS_WITH(format, "bitpos")); | 360 ASSERT(STRING_STARTS_WITH(format, "bitpos")); |
390 int bitpos = instr->Bits(19, 4) | (instr->Bit(31) << 5); | 361 int bitpos = instr->Bits(19, 4) | (instr->Bit(31) << 5); |
391 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 362 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
392 remaining_size_in_buffer(), | 363 remaining_size_in_buffer(), "#%d", bitpos); |
393 "#%d", | |
394 bitpos); | |
395 return 6; | 364 return 6; |
396 } | 365 } |
397 } | 366 } |
398 case 'c': { | 367 case 'c': { |
399 if (format[1] == 's') { | 368 if (format[1] == 's') { |
400 ASSERT(STRING_STARTS_WITH(format, "csz")); | 369 ASSERT(STRING_STARTS_WITH(format, "csz")); |
401 const int32_t imm5 = instr->Bits(16, 5); | 370 const int32_t imm5 = instr->Bits(16, 5); |
402 char const* typ = "??"; | 371 char const* typ = "??"; |
403 if (imm5 & 0x1) { | 372 if (imm5 & 0x1) { |
404 typ = "b"; | 373 typ = "b"; |
405 } else if (imm5 & 0x2) { | 374 } else if (imm5 & 0x2) { |
406 typ = "h"; | 375 typ = "h"; |
407 } else if (imm5 & 0x4) { | 376 } else if (imm5 & 0x4) { |
408 typ = "s"; | 377 typ = "s"; |
409 } else if (imm5 & 0x8) { | 378 } else if (imm5 & 0x8) { |
410 typ = "d"; | 379 typ = "d"; |
411 } | 380 } |
412 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 381 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
413 remaining_size_in_buffer(), | 382 remaining_size_in_buffer(), "%s", typ); |
414 "%s", | |
415 typ); | |
416 return 3; | 383 return 3; |
417 } else { | 384 } else { |
418 ASSERT(STRING_STARTS_WITH(format, "cond")); | 385 ASSERT(STRING_STARTS_WITH(format, "cond")); |
419 PrintCondition(instr); | 386 PrintCondition(instr); |
420 return 4; | 387 return 4; |
421 } | 388 } |
422 } | 389 } |
423 case 'd': { | 390 case 'd': { |
424 if (format[4] == '2') { | 391 if (format[4] == '2') { |
425 ASSERT(STRING_STARTS_WITH(format, "dest26")); | 392 ASSERT(STRING_STARTS_WITH(format, "dest26")); |
426 int64_t off = instr->SImm26Field() << 2; | 393 int64_t off = instr->SImm26Field() << 2; |
427 uword destination = reinterpret_cast<uword>(instr) + off; | 394 uword destination = reinterpret_cast<uword>(instr) + off; |
428 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 395 buffer_pos_ += |
429 remaining_size_in_buffer(), | 396 OS::SNPrint(current_position_in_buffer(), |
430 "%#" Px "", | 397 remaining_size_in_buffer(), "%#" Px "", destination); |
431 destination); | |
432 } else { | 398 } else { |
433 if (format[5] == '4') { | 399 if (format[5] == '4') { |
434 ASSERT(STRING_STARTS_WITH(format, "dest14")); | 400 ASSERT(STRING_STARTS_WITH(format, "dest14")); |
435 int64_t off = instr->SImm14Field() << 2; | 401 int64_t off = instr->SImm14Field() << 2; |
436 uword destination = reinterpret_cast<uword>(instr) + off; | 402 uword destination = reinterpret_cast<uword>(instr) + off; |
437 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 403 buffer_pos_ += |
438 remaining_size_in_buffer(), | 404 OS::SNPrint(current_position_in_buffer(), |
439 "%#" Px "", | 405 remaining_size_in_buffer(), "%#" Px "", destination); |
440 destination); | |
441 } else { | 406 } else { |
442 ASSERT(STRING_STARTS_WITH(format, "dest19")); | 407 ASSERT(STRING_STARTS_WITH(format, "dest19")); |
443 int64_t off = instr->SImm19Field() << 2; | 408 int64_t off = instr->SImm19Field() << 2; |
444 uword destination = reinterpret_cast<uword>(instr) + off; | 409 uword destination = reinterpret_cast<uword>(instr) + off; |
445 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 410 buffer_pos_ += |
446 remaining_size_in_buffer(), | 411 OS::SNPrint(current_position_in_buffer(), |
447 "%#" Px "", | 412 remaining_size_in_buffer(), "%#" Px "", destination); |
448 destination); | |
449 } | 413 } |
450 } | 414 } |
451 return 6; | 415 return 6; |
452 } | 416 } |
453 case 'f': { | 417 case 'f': { |
454 ASSERT(STRING_STARTS_WITH(format, "fsz")); | 418 ASSERT(STRING_STARTS_WITH(format, "fsz")); |
455 const int sz = instr->SzField(); | 419 const int sz = instr->SzField(); |
456 char const* sz_str; | 420 char const* sz_str; |
457 switch (sz) { | 421 switch (sz) { |
458 case 0: | 422 case 0: |
459 if (instr->Bit(23) == 1) { | 423 if (instr->Bit(23) == 1) { |
460 sz_str = "q"; | 424 sz_str = "q"; |
461 } else { | 425 } else { |
462 sz_str = "b"; | 426 sz_str = "b"; |
463 } | 427 } |
464 break; | 428 break; |
465 case 1: sz_str = "h"; break; | 429 case 1: |
466 case 2: sz_str = "s"; break; | 430 sz_str = "h"; |
467 case 3: sz_str = "d"; break; | 431 break; |
468 default: sz_str = "?"; break; | 432 case 2: |
469 } | 433 sz_str = "s"; |
470 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 434 break; |
471 remaining_size_in_buffer(), | 435 case 3: |
472 "%s", | 436 sz_str = "d"; |
473 sz_str); | 437 break; |
| 438 default: |
| 439 sz_str = "?"; |
| 440 break; |
| 441 } |
| 442 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 443 remaining_size_in_buffer(), "%s", sz_str); |
474 return 3; | 444 return 3; |
475 } | 445 } |
476 case 'h': { | 446 case 'h': { |
477 ASSERT(STRING_STARTS_WITH(format, "hw")); | 447 ASSERT(STRING_STARTS_WITH(format, "hw")); |
478 const int shift = instr->HWField() << 4; | 448 const int shift = instr->HWField() << 4; |
479 if (shift != 0) { | 449 if (shift != 0) { |
480 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 450 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
481 remaining_size_in_buffer(), | 451 remaining_size_in_buffer(), "lsl %d", shift); |
482 "lsl %d", | |
483 shift); | |
484 } | 452 } |
485 return 2; | 453 return 2; |
486 } | 454 } |
487 case 'i': { // 'imm12, 'imm16, 'immd | 455 case 'i': { // 'imm12, 'imm16, 'immd |
488 if (format[1] == 'd') { | 456 if (format[1] == 'd') { |
489 // Element index for a SIMD copy instruction. | 457 // Element index for a SIMD copy instruction. |
490 ASSERT(STRING_STARTS_WITH(format, "idx")); | 458 ASSERT(STRING_STARTS_WITH(format, "idx")); |
491 const int32_t imm4 = instr->Bits(11, 4); | 459 const int32_t imm4 = instr->Bits(11, 4); |
492 const int32_t imm5 = instr->Bits(16, 5); | 460 const int32_t imm5 = instr->Bits(16, 5); |
493 int32_t shift = 0; | 461 int32_t shift = 0; |
494 int32_t imm = -1; | 462 int32_t imm = -1; |
495 if (format[3] == '4') { | 463 if (format[3] == '4') { |
496 imm = imm4; | 464 imm = imm4; |
497 } else if (format[3] == '5') { | 465 } else if (format[3] == '5') { |
498 imm = imm5; | 466 imm = imm5; |
499 shift = 1; | 467 shift = 1; |
500 } | 468 } |
501 int32_t idx = -1; | 469 int32_t idx = -1; |
502 if (imm5 & 0x1) { | 470 if (imm5 & 0x1) { |
503 idx = imm >> shift; | 471 idx = imm >> shift; |
504 } else if (imm5 & 0x2) { | 472 } else if (imm5 & 0x2) { |
505 idx = imm >> (shift + 1); | 473 idx = imm >> (shift + 1); |
506 } else if (imm5 & 0x4) { | 474 } else if (imm5 & 0x4) { |
507 idx = imm >> (shift + 2); | 475 idx = imm >> (shift + 2); |
508 } else if (imm5 & 0x8) { | 476 } else if (imm5 & 0x8) { |
509 idx = imm >> (shift + 3); | 477 idx = imm >> (shift + 3); |
510 } | 478 } |
511 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 479 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
512 remaining_size_in_buffer(), | 480 remaining_size_in_buffer(), "[%d]", idx); |
513 "[%d]", | |
514 idx); | |
515 return 4; | 481 return 4; |
516 } else if (format[3] == '1') { | 482 } else if (format[3] == '1') { |
517 uint64_t imm; | 483 uint64_t imm; |
518 int ret = 5; | 484 int ret = 5; |
519 if (format[4] == '2') { | 485 if (format[4] == '2') { |
520 ASSERT(STRING_STARTS_WITH(format, "imm12")); | 486 ASSERT(STRING_STARTS_WITH(format, "imm12")); |
521 imm = instr->Imm12Field(); | 487 imm = instr->Imm12Field(); |
522 if (format[5] == 's') { | 488 if (format[5] == 's') { |
523 // shifted immediate. | 489 // shifted immediate. |
524 if (instr->Imm12ShiftField() == 1) { | 490 if (instr->Imm12ShiftField() == 1) { |
525 imm = imm << 12; | 491 imm = imm << 12; |
526 } else if ((instr->Imm12ShiftField() & 0x2) != 0) { | 492 } else if ((instr->Imm12ShiftField() & 0x2) != 0) { |
527 Print("Unknown Shift"); | 493 Print("Unknown Shift"); |
528 } | 494 } |
529 ret = 6; | 495 ret = 6; |
530 } | 496 } |
531 } else { | 497 } else { |
532 ASSERT(STRING_STARTS_WITH(format, "imm16")); | 498 ASSERT(STRING_STARTS_WITH(format, "imm16")); |
533 imm = instr->Imm16Field(); | 499 imm = instr->Imm16Field(); |
534 } | 500 } |
535 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 501 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
536 remaining_size_in_buffer(), | 502 remaining_size_in_buffer(), "0x%" Px64, imm); |
537 "0x%" Px64, | |
538 imm); | |
539 return ret; | 503 return ret; |
540 } else { | 504 } else { |
541 ASSERT(STRING_STARTS_WITH(format, "immd")); | 505 ASSERT(STRING_STARTS_WITH(format, "immd")); |
542 double dimm = bit_cast<double, int64_t>( | 506 double dimm = |
543 Instr::VFPExpandImm(instr->Imm8Field())); | 507 bit_cast<double, int64_t>(Instr::VFPExpandImm(instr->Imm8Field())); |
544 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 508 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
545 remaining_size_in_buffer(), | 509 remaining_size_in_buffer(), "%f", dimm); |
546 "%f", | |
547 dimm); | |
548 return 4; | 510 return 4; |
549 } | 511 } |
550 } | 512 } |
551 case 'm': { | 513 case 'm': { |
552 ASSERT(STRING_STARTS_WITH(format, "memop")); | 514 ASSERT(STRING_STARTS_WITH(format, "memop")); |
553 PrintMemOperand(instr); | 515 PrintMemOperand(instr); |
554 return 5; | 516 return 5; |
555 } | 517 } |
556 case 'p': { | 518 case 'p': { |
557 if (format[1] == 'c') { | 519 if (format[1] == 'c') { |
558 if (format[2] == 'a') { | 520 if (format[2] == 'a') { |
559 ASSERT(STRING_STARTS_WITH(format, "pcadr")); | 521 ASSERT(STRING_STARTS_WITH(format, "pcadr")); |
560 const int64_t immhi = instr->SImm19Field(); | 522 const int64_t immhi = instr->SImm19Field(); |
561 const int64_t immlo = instr->Bits(29, 2); | 523 const int64_t immlo = instr->Bits(29, 2); |
562 const int64_t off = (immhi << 2) | immlo; | 524 const int64_t off = (immhi << 2) | immlo; |
563 const int64_t pc = reinterpret_cast<int64_t>(instr); | 525 const int64_t pc = reinterpret_cast<int64_t>(instr); |
564 const int64_t dest = pc + off; | 526 const int64_t dest = pc + off; |
565 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 527 buffer_pos_ += |
566 remaining_size_in_buffer(), | 528 OS::SNPrint(current_position_in_buffer(), |
567 "0x%" Px64, | 529 remaining_size_in_buffer(), "0x%" Px64, dest); |
568 dest); | |
569 } else { | 530 } else { |
570 ASSERT(STRING_STARTS_WITH(format, "pcldr")); | 531 ASSERT(STRING_STARTS_WITH(format, "pcldr")); |
571 const int64_t off = instr->SImm19Field() << 2; | 532 const int64_t off = instr->SImm19Field() << 2; |
572 const int64_t pc = reinterpret_cast<int64_t>(instr); | 533 const int64_t pc = reinterpret_cast<int64_t>(instr); |
573 const int64_t dest = pc + off; | 534 const int64_t dest = pc + off; |
574 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 535 buffer_pos_ += |
575 remaining_size_in_buffer(), | 536 OS::SNPrint(current_position_in_buffer(), |
576 "0x%" Px64, | 537 remaining_size_in_buffer(), "0x%" Px64, dest); |
577 dest); | |
578 } | 538 } |
579 return 5; | 539 return 5; |
580 } else { | 540 } else { |
581 ASSERT(STRING_STARTS_WITH(format, "pmemop")); | 541 ASSERT(STRING_STARTS_WITH(format, "pmemop")); |
582 PrintPairMemOperand(instr); | 542 PrintPairMemOperand(instr); |
583 return 6; | 543 return 6; |
584 } | 544 } |
585 } | 545 } |
586 case 'r': { | 546 case 'r': { |
587 return FormatRegister(instr, format); | 547 return FormatRegister(instr, format); |
588 } | 548 } |
589 case 'v': { | 549 case 'v': { |
590 if (format[1] == 's') { | 550 if (format[1] == 's') { |
591 ASSERT(STRING_STARTS_WITH(format, "vsz")); | 551 ASSERT(STRING_STARTS_WITH(format, "vsz")); |
592 char const* sz_str = NULL; | 552 char const* sz_str = NULL; |
593 if (instr->Bits(14, 2) == 3) { | 553 if (instr->Bits(14, 2) == 3) { |
594 switch (instr->Bit(22)) { | 554 switch (instr->Bit(22)) { |
595 case 0: sz_str = "s"; break; | 555 case 0: |
596 case 1: sz_str = "d"; break; | 556 sz_str = "s"; |
597 default: UNREACHABLE(); break; | 557 break; |
| 558 case 1: |
| 559 sz_str = "d"; |
| 560 break; |
| 561 default: |
| 562 UNREACHABLE(); |
| 563 break; |
598 } | 564 } |
599 } else { | 565 } else { |
600 switch (instr->Bit(22)) { | 566 switch (instr->Bit(22)) { |
601 case 0: sz_str = "w"; break; | 567 case 0: |
602 case 1: sz_str = "x"; break; | 568 sz_str = "w"; |
603 default: UNREACHABLE(); break; | 569 break; |
| 570 case 1: |
| 571 sz_str = "x"; |
| 572 break; |
| 573 default: |
| 574 UNREACHABLE(); |
| 575 break; |
604 } | 576 } |
605 } | 577 } |
606 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 578 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
607 remaining_size_in_buffer(), | 579 remaining_size_in_buffer(), "%s", sz_str); |
608 "%s", | |
609 sz_str); | |
610 return 3; | 580 return 3; |
611 } else { | 581 } else { |
612 return FormatVRegister(instr, format); | 582 return FormatVRegister(instr, format); |
613 } | 583 } |
614 } | 584 } |
615 case 's': { // 's: S flag. | 585 case 's': { // 's: S flag. |
616 if (format[1] == 'h') { | 586 if (format[1] == 'h') { |
617 ASSERT(STRING_STARTS_WITH(format, "shift_op")); | 587 ASSERT(STRING_STARTS_WITH(format, "shift_op")); |
618 PrintShiftExtendRm(instr); | 588 PrintShiftExtendRm(instr); |
619 return 8; | 589 return 8; |
620 } else if (format[1] == 'f') { | 590 } else if (format[1] == 'f') { |
621 ASSERT(STRING_STARTS_WITH(format, "sf")); | 591 ASSERT(STRING_STARTS_WITH(format, "sf")); |
622 if (instr->SFField() == 1) { | 592 if (instr->SFField() == 1) { |
623 // TODO(zra): If we don't use the w form much, we can omit printing | 593 // TODO(zra): If we don't use the w form much, we can omit printing |
624 // this x. | 594 // this x. |
625 Print("x"); | 595 Print("x"); |
626 } else { | 596 } else { |
627 Print("w"); | 597 Print("w"); |
628 } | 598 } |
629 return 2; | 599 return 2; |
630 } else if (format[1] == 'z') { | 600 } else if (format[1] == 'z') { |
631 ASSERT(STRING_STARTS_WITH(format, "sz")); | 601 ASSERT(STRING_STARTS_WITH(format, "sz")); |
632 const int sz = instr->SzField(); | 602 const int sz = instr->SzField(); |
633 char const* sz_str; | 603 char const* sz_str; |
634 switch (sz) { | 604 switch (sz) { |
635 case 0: sz_str = "b"; break; | 605 case 0: |
636 case 1: sz_str = "h"; break; | 606 sz_str = "b"; |
637 case 2: sz_str = "w"; break; | 607 break; |
638 case 3: sz_str = "x"; break; | 608 case 1: |
639 default: sz_str = "?"; break; | 609 sz_str = "h"; |
| 610 break; |
| 611 case 2: |
| 612 sz_str = "w"; |
| 613 break; |
| 614 case 3: |
| 615 sz_str = "x"; |
| 616 break; |
| 617 default: |
| 618 sz_str = "?"; |
| 619 break; |
640 } | 620 } |
641 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 621 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
642 remaining_size_in_buffer(), | 622 remaining_size_in_buffer(), "%s", sz_str); |
643 "%s", | |
644 sz_str); | |
645 return 2; | 623 return 2; |
646 } else if (format[1] == ' ') { | 624 } else if (format[1] == ' ') { |
647 if (instr->HasS()) { | 625 if (instr->HasS()) { |
648 Print("s"); | 626 Print("s"); |
649 } | 627 } |
650 return 1; | 628 return 1; |
651 } else { | 629 } else { |
652 UNREACHABLE(); | 630 UNREACHABLE(); |
653 } | 631 } |
654 } | 632 } |
(...skipping 13 matching lines...) Expand all Loading... |
668 void ARM64Decoder::Format(Instr* instr, const char* format) { | 646 void ARM64Decoder::Format(Instr* instr, const char* format) { |
669 char cur = *format++; | 647 char cur = *format++; |
670 while ((cur != 0) && (buffer_pos_ < (buffer_size_ - 1))) { | 648 while ((cur != 0) && (buffer_pos_ < (buffer_size_ - 1))) { |
671 if (cur == '\'') { // Single quote is used as the formatting escape. | 649 if (cur == '\'') { // Single quote is used as the formatting escape. |
672 format += FormatOption(instr, format); | 650 format += FormatOption(instr, format); |
673 } else { | 651 } else { |
674 buffer_[buffer_pos_++] = cur; | 652 buffer_[buffer_pos_++] = cur; |
675 } | 653 } |
676 cur = *format++; | 654 cur = *format++; |
677 } | 655 } |
678 buffer_[buffer_pos_] = '\0'; | 656 buffer_[buffer_pos_] = '\0'; |
679 } | 657 } |
680 | 658 |
681 | 659 |
682 // For currently unimplemented decodings the disassembler calls Unknown(instr) | 660 // For currently unimplemented decodings the disassembler calls Unknown(instr) |
683 // which will just print "unknown" of the instruction bits. | 661 // which will just print "unknown" of the instruction bits. |
684 void ARM64Decoder::Unknown(Instr* instr) { | 662 void ARM64Decoder::Unknown(Instr* instr) { |
685 Format(instr, "unknown"); | 663 Format(instr, "unknown"); |
686 } | 664 } |
687 | 665 |
688 | 666 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 } | 719 } |
742 if (instr->Bit(30)) { | 720 if (instr->Bit(30)) { |
743 Format(instr, "ldrx 'rt, 'pcldr"); | 721 Format(instr, "ldrx 'rt, 'pcldr"); |
744 } else { | 722 } else { |
745 Format(instr, "ldrw 'rt, 'pcldr"); | 723 Format(instr, "ldrw 'rt, 'pcldr"); |
746 } | 724 } |
747 } | 725 } |
748 | 726 |
749 | 727 |
750 void ARM64Decoder::DecodeLoadStoreExclusive(Instr* instr) { | 728 void ARM64Decoder::DecodeLoadStoreExclusive(Instr* instr) { |
751 if ((instr->Bit(23) != 0) || | 729 if ((instr->Bit(23) != 0) || (instr->Bit(21) != 0) || (instr->Bit(15) != 0)) { |
752 (instr->Bit(21) != 0) || | |
753 (instr->Bit(15) != 0)) { | |
754 Unknown(instr); | 730 Unknown(instr); |
755 } | 731 } |
756 const int32_t size = instr->Bits(30, 2); | 732 const int32_t size = instr->Bits(30, 2); |
757 if (size != 3) { | 733 if (size != 3) { |
758 Unknown(instr); | 734 Unknown(instr); |
759 } | 735 } |
760 | 736 |
761 const bool is_load = instr->Bit(22) == 1; | 737 const bool is_load = instr->Bit(22) == 1; |
762 if (is_load) { | 738 if (is_load) { |
763 Format(instr, "ldxr 'rt, 'rn"); | 739 Format(instr, "ldxr 'rt, 'rn"); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
852 void ARM64Decoder::DecodeExceptionGen(Instr* instr) { | 828 void ARM64Decoder::DecodeExceptionGen(Instr* instr) { |
853 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) && | 829 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) && |
854 (instr->Bits(21, 3) == 0)) { | 830 (instr->Bits(21, 3) == 0)) { |
855 Format(instr, "svc 'imm16"); | 831 Format(instr, "svc 'imm16"); |
856 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && | 832 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && |
857 (instr->Bits(21, 3) == 1)) { | 833 (instr->Bits(21, 3) == 1)) { |
858 Format(instr, "brk 'imm16"); | 834 Format(instr, "brk 'imm16"); |
859 if (instr->Imm16Field() == Instr::kStopMessageCode) { | 835 if (instr->Imm16Field() == Instr::kStopMessageCode) { |
860 const char* message = *reinterpret_cast<const char**>( | 836 const char* message = *reinterpret_cast<const char**>( |
861 reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize); | 837 reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize); |
862 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 838 buffer_pos_ += |
863 remaining_size_in_buffer(), | 839 OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(), |
864 " ; \"%s\"", | 840 " ; \"%s\"", message); |
865 message); | |
866 } | 841 } |
867 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && | 842 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && |
868 (instr->Bits(21, 3) == 2)) { | 843 (instr->Bits(21, 3) == 2)) { |
869 Format(instr, "hlt 'imm16"); | 844 Format(instr, "hlt 'imm16"); |
870 } else { | 845 } else { |
871 Unknown(instr); | 846 Unknown(instr); |
872 } | 847 } |
873 } | 848 } |
874 | 849 |
875 | 850 |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1180 const int32_t Q = instr->Bit(30); | 1155 const int32_t Q = instr->Bit(30); |
1181 const int32_t op = instr->Bit(29); | 1156 const int32_t op = instr->Bit(29); |
1182 const int32_t imm4 = instr->Bits(11, 4); | 1157 const int32_t imm4 = instr->Bits(11, 4); |
1183 | 1158 |
1184 if ((op == 0) && (imm4 == 7)) { | 1159 if ((op == 0) && (imm4 == 7)) { |
1185 if (Q == 0) { | 1160 if (Q == 0) { |
1186 Format(instr, "vmovrs 'rd, 'vn'idx5"); | 1161 Format(instr, "vmovrs 'rd, 'vn'idx5"); |
1187 } else { | 1162 } else { |
1188 Format(instr, "vmovrd 'rd, 'vn'idx5"); | 1163 Format(instr, "vmovrd 'rd, 'vn'idx5"); |
1189 } | 1164 } |
1190 } else if ((Q == 1) && (op == 0) && (imm4 == 0)) { | 1165 } else if ((Q == 1) && (op == 0) && (imm4 == 0)) { |
1191 Format(instr, "vdup'csz 'vd, 'vn'idx5"); | 1166 Format(instr, "vdup'csz 'vd, 'vn'idx5"); |
1192 } else if ((Q == 1) && (op == 0) && (imm4 == 3)) { | 1167 } else if ((Q == 1) && (op == 0) && (imm4 == 3)) { |
1193 Format(instr, "vins'csz 'vd'idx5, 'rn"); | 1168 Format(instr, "vins'csz 'vd'idx5, 'rn"); |
1194 } else if ((Q == 1) && (op == 0) && (imm4 == 1)) { | 1169 } else if ((Q == 1) && (op == 0) && (imm4 == 1)) { |
1195 Format(instr, "vdup'csz 'vd, 'rn"); | 1170 Format(instr, "vdup'csz 'vd, 'rn"); |
1196 } else if ((Q == 1) && (op == 1)) { | 1171 } else if ((Q == 1) && (op == 1)) { |
1197 Format(instr, "vins'csz 'vd'idx5, 'vn'idx4"); | 1172 Format(instr, "vins'csz 'vd'idx5, 'vn'idx4"); |
1198 } else { | 1173 } else { |
1199 Unknown(instr); | 1174 Unknown(instr); |
1200 } | 1175 } |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1480 } else if (instr->IsDPSimd1Op()) { | 1455 } else if (instr->IsDPSimd1Op()) { |
1481 DecodeDPSimd1(instr); | 1456 DecodeDPSimd1(instr); |
1482 } else if (instr->IsDPSimd2Op()) { | 1457 } else if (instr->IsDPSimd2Op()) { |
1483 DecodeDPSimd2(instr); | 1458 DecodeDPSimd2(instr); |
1484 } else { | 1459 } else { |
1485 Unknown(instr); | 1460 Unknown(instr); |
1486 } | 1461 } |
1487 } | 1462 } |
1488 | 1463 |
1489 | 1464 |
1490 void Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size, | 1465 void Disassembler::DecodeInstruction(char* hex_buffer, |
1491 char* human_buffer, intptr_t human_size, | 1466 intptr_t hex_size, |
1492 int* out_instr_size, const Code& code, | 1467 char* human_buffer, |
1493 Object** object, uword pc) { | 1468 intptr_t human_size, |
| 1469 int* out_instr_size, |
| 1470 const Code& code, |
| 1471 Object** object, |
| 1472 uword pc) { |
1494 ARM64Decoder decoder(human_buffer, human_size); | 1473 ARM64Decoder decoder(human_buffer, human_size); |
1495 decoder.InstructionDecode(pc); | 1474 decoder.InstructionDecode(pc); |
1496 int32_t instruction_bits = Instr::At(pc)->InstructionBits(); | 1475 int32_t instruction_bits = Instr::At(pc)->InstructionBits(); |
1497 OS::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits); | 1476 OS::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits); |
1498 if (out_instr_size) { | 1477 if (out_instr_size) { |
1499 *out_instr_size = Instr::kInstrSize; | 1478 *out_instr_size = Instr::kInstrSize; |
1500 } | 1479 } |
1501 | 1480 |
1502 *object = NULL; | 1481 *object = NULL; |
1503 if (!code.IsNull()) { | 1482 if (!code.IsNull()) { |
1504 *object = &Object::Handle(); | 1483 *object = &Object::Handle(); |
1505 if (!DecodeLoadObjectFromPoolOrThread(pc, code, *object)) { | 1484 if (!DecodeLoadObjectFromPoolOrThread(pc, code, *object)) { |
1506 *object = NULL; | 1485 *object = NULL; |
1507 } | 1486 } |
1508 } | 1487 } |
1509 } | 1488 } |
1510 | 1489 |
1511 #endif // !PRODUCT | 1490 #endif // !PRODUCT |
1512 | 1491 |
1513 } // namespace dart | 1492 } // namespace dart |
1514 | 1493 |
1515 #endif // defined TARGET_ARCH_ARM | 1494 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |