Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: runtime/vm/disassembler_arm.cc

Issue 12301042: Implement ARM disassembler. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/assembler_arm.cc ('k') | runtime/vm/disassembler_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 10
11 namespace dart { 11 namespace dart {
12 12
13 class ARMDecoder : public ValueObject {
14 public:
15 ARMDecoder(char* buffer, size_t buffer_size)
16 : buffer_(buffer),
17 buffer_size_(buffer_size),
18 buffer_pos_(0) {
19 buffer_[buffer_pos_] = '\0';
20 }
21
22 ~ARMDecoder() {}
23
24 // Writes one disassembled instruction into 'buffer' (0-terminated).
25 void InstructionDecode(uword pc);
26
27 private:
28 // Bottleneck functions to print into the out_buffer.
29 void Print(const char* str);
30
31 // Printing of common values.
32 void PrintRegister(int reg);
33 void PrintSRegister(int reg);
34 void PrintDRegister(int reg);
35 void PrintCondition(Instr* instr);
36 void PrintShiftRm(Instr* instr);
37 void PrintShiftImm(Instr* instr);
38 void PrintPU(Instr* instr);
39
40 // Handle formatting of instructions and their options.
41 int FormatRegister(Instr* instr, const char* option);
42 int FormatSRegister(Instr* instr, const char* option);
43 int FormatDRegister(Instr* instr, const char* option);
44 int FormatOption(Instr* instr, const char* option);
45 void Format(Instr* instr, const char* format);
46 void Unknown(Instr* instr);
47
48 // Each of these functions decodes one particular instruction type, a 3-bit
49 // field in the instruction encoding.
50 // Types 0 and 1 are combined as they are largely the same except for the way
51 // they interpret the shifter operand.
52 void DecodeType01(Instr* instr);
53 void DecodeType2(Instr* instr);
54 void DecodeType3(Instr* instr);
55 void DecodeType4(Instr* instr);
56 void DecodeType5(Instr* instr);
57 void DecodeType6(Instr* instr);
58 void DecodeType7(Instr* instr);
59
60 // Convenience functions.
61 char* get_buffer() const { return buffer_; }
62 char* current_position_in_buffer() { return buffer_ + buffer_pos_; }
63 size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; }
64
65 char* buffer_; // Decode instructions into this buffer.
66 size_t buffer_size_; // The size of the character buffer.
67 size_t buffer_pos_; // Current character position in buffer.
68
69 DISALLOW_COPY_AND_ASSIGN(ARMDecoder);
70 };
71
72
73 // Support for assertions in the ARMDecoder formatting functions.
74 #define STRING_STARTS_WITH(string, compare_string) \
75 (strncmp(string, compare_string, strlen(compare_string)) == 0)
76
77
78 // Append the str to the output buffer.
79 void ARMDecoder::Print(const char* str) {
80 char cur = *str++;
81 while (cur != '\0' && (buffer_pos_ < (buffer_size_ - 1))) {
82 buffer_[buffer_pos_++] = cur;
83 cur = *str++;
84 }
85 buffer_[buffer_pos_] = '\0';
86 }
87
88
89 // These condition names are defined in a way to match the native disassembler
90 // formatting. See for example the command "objdump -d <binary file>".
91 static const char* cond_names[kMaxCondition] = {
92 "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
93 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
94 };
95
96
97 // Print the condition guarding the instruction.
98 void ARMDecoder::PrintCondition(Instr* instr) {
99 Print(cond_names[instr->ConditionField()]);
100 }
101
102
103 // These register names are defined in a way to match the native disassembler
104 // formatting. See for example the command "objdump -d <binary file>".
105 static const char* reg_names[kNumberOfCpuRegisters] = {
106 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
107 "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc",
108 };
109
110
111 // Print the register name according to the active name converter.
112 void ARMDecoder::PrintRegister(int reg) {
113 ASSERT(0 <= reg);
114 ASSERT(reg < kNumberOfCpuRegisters);
115 Print(reg_names[reg]);
116 }
117
118
119 void ARMDecoder::PrintSRegister(int reg) {
120 ASSERT(0 <= reg);
121 ASSERT(reg < kNumberOfSRegisters);
122 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
123 remaining_size_in_buffer(),
124 "s%d", reg);
125 }
126
127
128 void ARMDecoder::PrintDRegister(int reg) {
129 ASSERT(0 <= reg);
130 ASSERT(reg < kNumberOfDRegisters);
131 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
132 remaining_size_in_buffer(),
133 "d%d", reg);
134 }
135
136
137 // These shift names are defined in a way to match the native disassembler
138 // formatting. See for example the command "objdump -d <binary file>".
139 static const char* shift_names[kMaxShift] = {
140 "lsl", "lsr", "asr", "ror"
141 };
142
143
144 // Print the register shift operands for the instruction. Generally used for
145 // data processing instructions.
146 void ARMDecoder::PrintShiftRm(Instr* instr) {
147 Shift shift = instr->ShiftField();
148 int shift_amount = instr->ShiftAmountField();
149 int rm = instr->RmField();
150
151 PrintRegister(rm);
152
153 if ((instr->RegShiftField() == 0) && (shift == LSL) && (shift_amount == 0)) {
154 // Special case for using rm only.
155 return;
156 }
157 if (instr->RegShiftField() == 0) {
158 // by immediate
159 if ((shift == ROR) && (shift_amount == 0)) {
160 Print(", RRX");
161 return;
162 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
163 shift_amount = 32;
164 }
165 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
166 remaining_size_in_buffer(),
167 ", %s #%d",
168 shift_names[shift],
169 shift_amount);
170 } else {
171 // by register
172 int rs = instr->RsField();
173 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
174 remaining_size_in_buffer(),
175 ", %s ",
176 shift_names[shift]);
177 PrintRegister(rs);
178 }
179 }
180
181
182 // Print the immediate operand for the instruction. Generally used for data
183 // processing instructions.
184 void ARMDecoder::PrintShiftImm(Instr* instr) {
185 int rotate = instr->RotateField() * 2;
186 int immed8 = instr->Immed8Field();
187 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
188 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
189 remaining_size_in_buffer(),
190 "#%d",
191 imm);
192 }
193
194
195 // Print PU formatting to reduce complexity of FormatOption.
196 void ARMDecoder::PrintPU(Instr* instr) {
197 switch (instr->PUField()) {
198 case 0: {
199 Print("da");
200 break;
201 }
202 case 1: {
203 Print("ia");
204 break;
205 }
206 case 2: {
207 Print("db");
208 break;
209 }
210 case 3: {
211 Print("ib");
212 break;
213 }
214 default: {
215 UNREACHABLE();
216 break;
217 }
218 }
219 }
220
221
222 // Handle all register based formatting in these functions to reduce the
223 // complexity of FormatOption.
224 int ARMDecoder::FormatRegister(Instr* instr, const char* format) {
225 ASSERT(format[0] == 'r');
226 if (format[1] == 'n') { // 'rn: Rn register
227 int reg = instr->RnField();
228 PrintRegister(reg);
229 return 2;
230 } else if (format[1] == 'd') { // 'rd: Rd register
231 int reg = instr->RdField();
232 PrintRegister(reg);
233 if (format[2] == '2') { // 'rd2: possibly Rd, Rd+1 register pair
234 if (instr->HasSign() && !instr->HasL()) {
235 if ((reg % 2) != 0) {
236 Print(" *** unknown (odd register pair) ***");
237 } else {
238 Print(", ");
239 PrintRegister(reg + 1);
240 }
241 }
242 return 3;
243 }
244 return 2;
245 } else if (format[1] == 's') { // 'rs: Rs register
246 int reg = instr->RsField();
247 PrintRegister(reg);
248 return 2;
249 } else if (format[1] == 'm') { // 'rm: Rm register
250 int reg = instr->RmField();
251 PrintRegister(reg);
252 return 2;
253 } else if (format[1] == 'l') {
254 // 'rlist: register list for load and store multiple instructions
255 ASSERT(STRING_STARTS_WITH(format, "rlist"));
256 int rlist = instr->RlistField();
257 int reg = 0;
258 Print("{");
259 // Print register list in ascending order, by scanning the bit mask.
260 while (rlist != 0) {
261 if ((rlist & 1) != 0) {
262 PrintRegister(reg);
263 if ((rlist >> 1) != 0) {
264 Print(", ");
265 }
266 }
267 reg++;
268 rlist >>= 1;
269 }
270 Print("}");
271 return 5;
272 }
273 UNREACHABLE();
274 return -1;
275 }
276
277
278 int ARMDecoder::FormatSRegister(Instr* instr, const char* format) {
279 ASSERT(format[0] == 's');
280 if (format[1] == 'n') { // 'sn: Sn register
281 int reg = instr->SnField();
282 PrintSRegister(reg);
283 return 2;
284 } else if (format[1] == 'd') { // 'sd: Sd register
285 int reg = instr->SdField();
286 PrintSRegister(reg);
287 return 2;
288 } else if (format[1] == 'm') {
289 int reg = instr->SmField();
290 if (format[2] == '1') { // 'sm1: S[m+1] register
291 reg++;
292 ASSERT(reg < kNumberOfSRegisters);
293 PrintSRegister(reg);
294 return 3;
295 } else { // 'sm: Sm register
296 PrintSRegister(reg);
297 return 2;
298 }
299 }
300 UNREACHABLE();
301 return -1;
302 }
303
304
305 int ARMDecoder::FormatDRegister(Instr* instr, const char* format) {
306 ASSERT(format[0] == 'd');
307 if (format[1] == 'n') { // 'dn: Dn register
308 int reg = instr->DnField();
309 PrintDRegister(reg);
310 return 2;
311 } else if (format[1] == 'd') { // 'dd: Dd register
312 int reg = instr->DdField();
313 PrintDRegister(reg);
314 return 2;
315 } else if (format[1] == 'm') { // 'dm: Dm register
316 int reg = instr->DmField();
317 PrintDRegister(reg);
318 return 2;
319 }
320 UNREACHABLE();
321 return -1;
322 }
323
324
325 // FormatOption takes a formatting string and interprets it based on
326 // the current instructions. The format string points to the first
327 // character of the option string (the option escape has already been
328 // consumed by the caller.) FormatOption returns the number of
329 // characters that were consumed from the formatting string.
330 int ARMDecoder::FormatOption(Instr* instr, const char* format) {
331 switch (format[0]) {
332 case 'a': { // 'a: accumulate multiplies
333 if (instr->Bit(21) == 0) {
334 Print("ul");
335 } else {
336 Print("la");
337 }
338 return 1;
339 }
340 case 'b': { // 'b: byte loads or stores
341 if (instr->HasB()) {
342 Print("b");
343 }
344 return 1;
345 }
346 case 'c': { // 'cond: conditional execution
347 ASSERT(STRING_STARTS_WITH(format, "cond"));
348 PrintCondition(instr);
349 return 4;
350 }
351 case 'd': {
352 if (format[1] == 'e') { // 'dest: branch destination
353 ASSERT(STRING_STARTS_WITH(format, "dest"));
354 int off = (instr->SImmed24Field() << 2) + 8;
355 uword destination = reinterpret_cast<uword>(instr) + off;
356 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
357 remaining_size_in_buffer(),
358 "%#"Px"",
359 destination);
360 return 4;
361 } else {
362 return FormatDRegister(instr, format);
363 }
364 }
365 case 'i': { // 'imm12_4, imm4_12, immf, or immd
366 uint16_t immed16;
367 if (format[3] == 'f') {
368 ASSERT(STRING_STARTS_WITH(format, "immf"));
369 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
370 remaining_size_in_buffer(),
371 "%f",
372 instr->ImmFloatField());
373 return 4;
374 } else if (format[3] == 'd') {
375 ASSERT(STRING_STARTS_WITH(format, "immd"));
376 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
377 remaining_size_in_buffer(),
378 "%g",
379 instr->ImmDoubleField());
380 return 4;
381 } else if (format[3] == '1') {
382 ASSERT(STRING_STARTS_WITH(format, "imm12_4"));
383 immed16 = instr->BkptField();
384 } else {
385 ASSERT(STRING_STARTS_WITH(format, "imm4_12"));
386 immed16 = instr->MovwField();
387 }
388 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
389 remaining_size_in_buffer(),
390 "0x%x",
391 immed16);
392 return 7;
393 }
394 case 'l': { // 'l: branch and link
395 if (instr->HasLink()) {
396 Print("l");
397 }
398 return 1;
399 }
400 case 'm': { // 'memop: load/store instructions
401 ASSERT(STRING_STARTS_WITH(format, "memop"));
402 if (instr->HasL() ||
403 // Extra load/store instructions.
404 ((instr->TypeField() == 0) && instr->HasSign() && !instr->HasH())) {
405 Print("ldr");
406 } else {
407 Print("str");
408 }
409 return 5;
410 }
411 case 'o': {
412 if (format[3] == '1') {
413 if (format[4] == '0') {
414 // 'off10: 10-bit offset for VFP load and store instructions
415 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
416 remaining_size_in_buffer(),
417 "%d",
418 instr->Bits(0, 8) << 2);
419 } else {
420 // 'off12: 12-bit offset for load and store instructions
421 ASSERT(STRING_STARTS_WITH(format, "off12"));
422 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
423 remaining_size_in_buffer(),
424 "%d",
425 instr->Offset12Field());
426 }
427 return 5;
428 }
429 // 'off8: 8-bit offset for extra load and store instructions
430 ASSERT(STRING_STARTS_WITH(format, "off8"));
431 int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
432 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
433 remaining_size_in_buffer(),
434 "%d",
435 offs8);
436 return 4;
437 }
438 case 'p': { // 'pu: P and U bits for load and store instructions
439 ASSERT(STRING_STARTS_WITH(format, "pu"));
440 PrintPU(instr);
441 return 2;
442 }
443 case 'r': {
444 return FormatRegister(instr, format);
445 }
446 case 's': {
447 if (format[1] == 'h') { // 'shift_op or 'shift_rm
448 if (format[6] == 'o') { // 'shift_op
449 ASSERT(STRING_STARTS_WITH(format, "shift_op"));
450 if (instr->TypeField() == 0) {
451 PrintShiftRm(instr);
452 } else {
453 ASSERT(instr->TypeField() == 1);
454 PrintShiftImm(instr);
455 }
456 return 8;
457 } else { // 'shift_rm
458 ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
459 PrintShiftRm(instr);
460 return 8;
461 }
462 } else if (format[1] == 'v') { // 'svc
463 ASSERT(STRING_STARTS_WITH(format, "svc"));
464 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
465 remaining_size_in_buffer(),
466 "0x%x",
467 instr->SvcField());
468 return 3;
469 } else if (format[1] == ' ') {
470 // 's: S field of data processing instructions
471 if (instr->HasS()) {
472 Print("s");
473 }
474 return 1;
475 } else {
476 return FormatSRegister(instr, format);
477 }
478 }
479 case 't': { // 'target: target of branch instructions
480 ASSERT(STRING_STARTS_WITH(format, "target"));
481 int off = (instr->SImmed24Field() << 2) + 8;
482 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
483 remaining_size_in_buffer(),
484 "%+d",
485 off);
486 return 6;
487 }
488 case 'u': { // 'u: signed or unsigned multiplies
489 if (instr->Bit(22) == 0) {
490 Print("u");
491 } else {
492 Print("s");
493 }
494 return 1;
495 }
496 case 'w': { // 'w: W field of load and store instructions
497 if (instr->HasW()) {
498 Print("!");
499 }
500 return 1;
501 }
502 case 'x': { // 'x: type of extra load/store instructions
503 if (!instr->HasSign()) {
504 Print("h");
505 } else if (instr->HasL()) {
506 if (instr->HasH()) {
507 Print("sh");
508 } else {
509 Print("sb");
510 }
511 } else {
512 Print("d");
513 }
514 return 1;
515 }
516 default: {
517 UNREACHABLE();
518 break;
519 }
520 }
521 UNREACHABLE();
522 return -1;
523 }
524
525
526 // Format takes a formatting string for a whole instruction and prints it into
527 // the output buffer. All escaped options are handed to FormatOption to be
528 // parsed further.
529 void ARMDecoder::Format(Instr* instr, const char* format) {
530 char cur = *format++;
531 while ((cur != 0) && (buffer_pos_ < (buffer_size_ - 1))) {
532 if (cur == '\'') { // Single quote is used as the formatting escape.
533 format += FormatOption(instr, format);
534 } else {
535 buffer_[buffer_pos_++] = cur;
536 }
537 cur = *format++;
538 }
539 buffer_[buffer_pos_] = '\0';
540 }
541
542
543 // For currently unimplemented decodings the disassembler calls Unknown(instr)
544 // which will just print "unknown" of the instruction bits.
545 void ARMDecoder::Unknown(Instr* instr) {
546 Format(instr, "unknown");
547 }
548
549
550 void ARMDecoder::DecodeType01(Instr* instr) {
551 if (!instr->IsDataProcessing()) {
552 // miscellaneous, multiply, sync primitives, extra loads and stores.
553 if (instr->IsMiscellaneous()) {
554 switch (instr->Bits(4, 3)) {
555 case 1: {
556 if (instr->Bits(21, 2) == 0x3) {
557 Format(instr, "clz'cond 'rd, 'rm");
558 } else {
559 Unknown(instr);
560 }
561 break;
562 }
563 case 3: {
564 if (instr->Bits(21, 2) == 0x1) {
565 Format(instr, "blx'cond 'rm");
566 } else {
567 // Could be inlined constant.
568 Unknown(instr);
569 }
570 break;
571 }
572 case 7: {
573 if (instr->Bits(21, 2) == 0x1) {
574 Format(instr, "bkpt #'imm12_4");
575 } else {
576 // Format(instr, "smc'cond");
577 Unknown(instr); // Not used.
578 }
579 break;
580 }
581 default: {
582 Unknown(instr); // Not used.
583 break;
584 }
585 }
586 } else if (instr->IsMultiplyOrSyncPrimitive()) {
587 if (instr->Bit(24) == 0) {
588 // multiply instructions
589 switch (instr->Bits(21, 3)) {
590 case 0: {
591 // Assembler registers rd, rn, rm are encoded as rn, rm, rs.
592 Format(instr, "mul'cond's 'rn, 'rm, 'rs");
593 break;
594 }
595 case 1: {
596 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
597 Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
598 break;
599 }
600 case 3: {
601 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
602 Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
603 break;
604 }
605 case 4: {
606 // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
607 Format(instr, "umull'cond's 'rd, 'rn, 'rm, 'rs");
608 break;
609 }
610 default: {
611 Unknown(instr); // Not used.
612 break;
613 }
614 }
615 } else {
616 // synchronization primitives
617 switch (instr->Bits(20, 4)) {
618 case 8: {
619 Format(instr, "strex'cond 'rd, 'rm, ['rn]");
620 break;
621 }
622 case 9: {
623 Format(instr, "ldrex'cond 'rd, ['rn]");
624 break;
625 }
626 default: {
627 Unknown(instr); // Not used.
628 break;
629 }
630 }
631 }
632 } else if (instr->Bit(25) == 1) {
633 // 16-bit immediate loads, msr (immediate), and hints
634 switch (instr->Bits(20, 5)) {
635 case 16: {
636 Format(instr, "movw'cond 'rd, #'imm4_12");
637 break;
638 }
639 case 18: {
640 if ((instr->Bits(16, 4) == 0) && (instr->Bits(0, 8) == 0)) {
641 Format(instr, "nop'cond");
642 } else {
643 Unknown(instr); // Not used.
644 }
645 break;
646 }
647 case 20: {
648 Format(instr, "movt'cond 'rd, #'imm4_12");
649 break;
650 }
651 default: {
652 Unknown(instr); // Not used.
653 break;
654 }
655 }
656 } else {
657 // extra load/store instructions
658 switch (instr->PUField()) {
659 case 0: {
660 if (instr->Bit(22) == 0) {
661 Format(instr, "'memop'cond'x 'rd2, ['rn], -'rm");
662 } else {
663 Format(instr, "'memop'cond'x 'rd2, ['rn], #-'off8");
664 }
665 break;
666 }
667 case 1: {
668 if (instr->Bit(22) == 0) {
669 Format(instr, "'memop'cond'x 'rd2, ['rn], +'rm");
670 } else {
671 Format(instr, "'memop'cond'x 'rd2, ['rn], #+'off8");
672 }
673 break;
674 }
675 case 2: {
676 if (instr->Bit(22) == 0) {
677 Format(instr, "'memop'cond'x 'rd2, ['rn, -'rm]'w");
678 } else {
679 Format(instr, "'memop'cond'x 'rd2, ['rn, #-'off8]'w");
680 }
681 break;
682 }
683 case 3: {
684 if (instr->Bit(22) == 0) {
685 Format(instr, "'memop'cond'x 'rd2, ['rn, +'rm]'w");
686 } else {
687 Format(instr, "'memop'cond'x 'rd2, ['rn, #+'off8]'w");
688 }
689 break;
690 }
691 default: {
692 // The PU field is a 2-bit field.
693 UNREACHABLE();
694 break;
695 }
696 }
697 }
698 } else {
699 switch (instr->OpcodeField()) {
700 case AND: {
701 Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
702 break;
703 }
704 case EOR: {
705 Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
706 break;
707 }
708 case SUB: {
709 Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
710 break;
711 }
712 case RSB: {
713 Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
714 break;
715 }
716 case ADD: {
717 Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
718 break;
719 }
720 case ADC: {
721 Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
722 break;
723 }
724 case SBC: {
725 Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
726 break;
727 }
728 case RSC: {
729 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
730 break;
731 }
732 case TST: {
733 if (instr->HasS()) {
734 Format(instr, "tst'cond 'rn, 'shift_op");
735 } else {
736 Unknown(instr); // Not used.
737 }
738 break;
739 }
740 case TEQ: {
741 if (instr->HasS()) {
742 Format(instr, "teq'cond 'rn, 'shift_op");
743 } else {
744 Unknown(instr); // Not used.
745 }
746 break;
747 }
748 case CMP: {
749 if (instr->HasS()) {
750 Format(instr, "cmp'cond 'rn, 'shift_op");
751 } else {
752 Unknown(instr); // Not used.
753 }
754 break;
755 }
756 case CMN: {
757 if (instr->HasS()) {
758 Format(instr, "cmn'cond 'rn, 'shift_op");
759 } else {
760 Unknown(instr); // Not used.
761 }
762 break;
763 }
764 case ORR: {
765 Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
766 break;
767 }
768 case MOV: {
769 Format(instr, "mov'cond's 'rd, 'shift_op");
770 break;
771 }
772 case BIC: {
773 Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
774 break;
775 }
776 case MVN: {
777 Format(instr, "mvn'cond's 'rd, 'shift_op");
778 break;
779 }
780 default: {
781 // The Opcode field is a 4-bit field.
782 UNREACHABLE();
783 break;
784 }
785 }
786 }
787 }
788
789
790 void ARMDecoder::DecodeType2(Instr* instr) {
791 switch (instr->PUField()) {
792 case 0: {
793 if (instr->HasW()) {
794 Unknown(instr); // Not used.
795 } else {
796 Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
797 }
798 break;
799 }
800 case 1: {
801 if (instr->HasW()) {
802 Unknown(instr); // Not used.
803 } else {
804 Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
805 }
806 break;
807 }
808 case 2: {
809 Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
810 break;
811 }
812 case 3: {
813 Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
814 break;
815 }
816 default: {
817 // The PU field is a 2-bit field.
818 UNREACHABLE();
819 break;
820 }
821 }
822 }
823
824
825 void ARMDecoder::DecodeType3(Instr* instr) {
826 switch (instr->PUField()) {
827 case 0: {
828 if (instr->HasW()) {
829 Unknown(instr);
830 } else {
831 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
832 }
833 break;
834 }
835 case 1: {
836 if (instr->HasW()) {
837 Unknown(instr);
838 } else {
839 Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
840 }
841 break;
842 }
843 case 2: {
844 Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
845 break;
846 }
847 case 3: {
848 Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
849 break;
850 }
851 default: {
852 // The PU field is a 2-bit field.
853 UNREACHABLE();
854 break;
855 }
856 }
857 }
858
859
860 void ARMDecoder::DecodeType4(Instr* instr) {
861 if (instr->Bit(22) == 1) {
862 Unknown(instr); // Privileged mode currently not supported.
863 } else if (instr->HasL()) {
864 Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
865 } else {
866 Format(instr, "stm'cond'pu 'rn'w, 'rlist");
867 }
868 }
869
870
871 void ARMDecoder::DecodeType5(Instr* instr) {
872 Format(instr, "b'l'cond 'target ; 'dest");
873 }
874
875
876 void ARMDecoder::DecodeType6(Instr* instr) {
877 if (instr->IsVFPDoubleTransfer()) {
878 if (instr->Bit(8) == 0) {
879 if (instr->Bit(20) == 1) {
880 Format(instr, "vmovrrs'cond 'rd, 'rn, {'sm, 'sm1}");
881 } else {
882 Format(instr, "vmovsrr'cond {'sm, 'sm1}, 'rd, 'rn");
883 }
884 } else {
885 if (instr->Bit(20) == 1) {
886 Format(instr, "vmovrrd'cond 'rd, 'rn, 'dm");
887 } else {
888 Format(instr, "vmovdrr'cond 'dm, 'rd, 'rn");
889 }
890 }
891 } else if (instr-> IsVFPLoadStore()) {
892 if (instr->Bit(8) == 0) {
893 if (instr->Bit(20) == 1) { // vldrs
894 if (instr->Bit(23) == 1) {
895 Format(instr, "vldrs'cond 'sd, ['rn, #+'off10]");
896 } else {
897 Format(instr, "vldrs'cond 'sd, ['rn, #-'off10]");
898 }
899 } else { // vstrs
900 if (instr->Bit(23) == 1) {
901 Format(instr, "vstrs'cond 'sd, ['rn, #+'off10]");
902 } else {
903 Format(instr, "vstrs'cond 'sd, ['rn, #-'off10]");
904 }
905 }
906 } else {
907 if (instr->Bit(20) == 1) { // vldrd
908 if (instr->Bit(23) == 1) {
909 Format(instr, "vldrd'cond 'dd, ['rn, #+'off10]");
910 } else {
911 Format(instr, "vldrd'cond 'dd, ['rn, #-'off10]");
912 }
913 } else { // vstrd
914 if (instr->Bit(23) == 1) {
915 Format(instr, "vstrd'cond 'dd, ['rn, #+'off10]");
916 } else {
917 Format(instr, "vstrd'cond 'dd, ['rn, #-'off10]");
918 }
919 }
920 }
921 } else {
922 Unknown(instr);
923 }
924 }
925
926
927 void ARMDecoder::DecodeType7(Instr* instr) {
928 if (instr->Bit(24) == 1) {
929 Format(instr, "svc'cond #'svc");
930 if (instr->SvcField() == kStopMessageSvcCode) {
931 const char* message = *reinterpret_cast<const char**>(
932 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize);
933 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
934 remaining_size_in_buffer(),
935 " ; \"%s\"",
936 message);
937 }
938 } else if (instr->IsVFPDataProcessingOrSingleTransfer()) {
939 if (instr->Bit(4) == 0) {
940 // VFP Data Processing
941 switch (instr->Bits(20, 4) & 0xb) {
942 case 0: { // vmla, vmls floating-point
943 if (instr->Bit(8) == 0) {
944 if (instr->Bit(6) == 0) {
945 Format(instr, "vmlas'cond 'sd, 'sn, 'sm");
946 } else {
947 Format(instr, "vmlss'cond 'sd, 'sn, 'sm");
948 }
949 } else {
950 if (instr->Bit(6) == 0) {
951 Format(instr, "vmlad'cond 'dd, 'dn, 'dm");
952 } else {
953 Format(instr, "vmlsd'cond 'dd, 'dn, 'dm");
954 }
955 }
956 break;
957 }
958 case 1: // vnmla, vnmls, vnmul
959 default: {
960 Unknown(instr);
961 break;
962 }
963 case 2: { // vmul
964 if (instr->Bit(8) == 0) {
965 Format(instr, "vmuls'cond 'sd, 'sn, 'sm");
966 } else {
967 Format(instr, "vmuld'cond 'dd, 'dn, 'dm");
968 }
969 break;
970 }
971 case 8: { // vdiv
972 if (instr->Bit(8) == 0) {
973 Format(instr, "vdivs'cond 'sd, 'sn, 'sm");
974 } else {
975 Format(instr, "vdivd'cond 'dd, 'dn, 'dm");
976 }
977 break;
978 }
979 case 3: { // vadd, vsub floating-point
980 if (instr->Bit(8) == 0) {
981 if (instr->Bit(6) == 0) {
982 Format(instr, "vadds'cond 'sd, 'sn, 'sm");
983 } else {
984 Format(instr, "vsubs'cond 'sd, 'sn, 'sm");
985 }
986 } else {
987 if (instr->Bit(6) == 0) {
988 Format(instr, "vaddd'cond 'dd, 'dn, 'dm");
989 } else {
990 Format(instr, "vsubd'cond 'dd, 'dn, 'dm");
991 }
992 }
993 break;
994 }
995 case 0xb: { // Other VFP data-processing instructions
996 if (instr->Bit(6) == 0) { // vmov immediate
997 if (instr->Bit(8) == 0) {
998 Format(instr, "vmovs'cond 'sd, #'immf");
999 } else {
1000 Format(instr, "vmovd'cond 'dd, #'immd");
1001 }
1002 break;
1003 }
1004 switch (instr->Bits(16, 4)) {
1005 case 0: { // vmov register, vabs
1006 switch (instr->Bits(6, 2)) {
1007 case 1: { // vmov register
1008 if (instr->Bit(8) == 0) {
1009 Format(instr, "vmovs'cond 'sd, 'sm");
1010 } else {
1011 Format(instr, "vmovd'cond 'dd, 'dm");
1012 }
1013 break;
1014 }
1015 case 3: { // vabs
1016 if (instr->Bit(8) == 0) {
1017 Format(instr, "vabss'cond 'sd, 'sm");
1018 } else {
1019 Format(instr, "vabsd'cond 'dd, 'dm");
1020 }
1021 break;
1022 }
1023 default: {
1024 Unknown(instr);
1025 break;
1026 }
1027 }
1028 break;
1029 }
1030 case 1: { // vneg, vsqrt
1031 switch (instr->Bits(6, 2)) {
1032 case 1: { // vneg
1033 if (instr->Bit(8) == 0) {
1034 Format(instr, "vnegs'cond 'sd, 'sm");
1035 } else {
1036 Format(instr, "vnegd'cond 'dd, 'dm");
1037 }
1038 break;
1039 }
1040 case 3: { // vsqrt
1041 if (instr->Bit(8) == 0) {
1042 Format(instr, "vsqrts'cond 'sd, 'sm");
1043 } else {
1044 Format(instr, "vsqrtd'cond 'dd, 'dm");
1045 }
1046 break;
1047 }
1048 default: {
1049 Unknown(instr);
1050 break;
1051 }
1052 }
1053 break;
1054 }
1055 case 4: // vcmp, vcmpe
1056 case 5: { // vcmp #0.0, vcmpe #0.0
1057 if (instr->Bit(7) == 1) { // vcmpe
1058 Unknown(instr);
1059 } else {
1060 if (instr->Bit(8) == 0) { // vcmps
1061 if (instr->Bit(16) == 0) {
1062 Format(instr, "vcmps'cond 'sd, 'sm");
1063 } else {
1064 Format(instr, "vcmps'cond 'sd, #0.0");
1065 }
1066 } else { // vcmpd
1067 if (instr->Bit(16) == 0) {
1068 Format(instr, "vcmpd'cond 'dd, 'dm");
1069 } else {
1070 Format(instr, "vcmpd'cond 'dd, #0.0");
1071 }
1072 }
1073 }
1074 break;
1075 }
1076 case 7: { // vcvt between double-precision and single-precision
1077 if (instr->Bit(8) == 0) {
1078 Format(instr, "vcvtds'cond 'dd, 'sm");
1079 } else {
1080 Format(instr, "vcvtsd'cond 'sd, 'dm");
1081 }
1082 break;
1083 }
1084 case 8: { // vcvt, vcvtr between floating-point and integer
1085 if (instr->Bit(8) == 0) {
1086 if (instr->Bit(7) == 0) {
1087 Format(instr, "vcvtsu'cond 'sd, 'sm");
1088 } else {
1089 Format(instr, "vcvtsi'cond 'sd, 'sm");
1090 }
1091 } else {
1092 if (instr->Bit(7) == 0) {
1093 Format(instr, "vcvtdu'cond 'dd, 'sm");
1094 } else {
1095 Format(instr, "vcvtdi'cond 'dd, 'sm");
1096 }
1097 }
1098 break;
1099 }
1100 case 12:
1101 case 13: { // vcvt, vcvtr between floating-point and integer
1102 if (instr->Bit(7) == 0) {
1103 // We only support round-to-zero mode
1104 Unknown(instr);
1105 break;
1106 }
1107 if (instr->Bit(8) == 0) {
1108 if (instr->Bit(16) == 0) {
1109 Format(instr, "vcvtus'cond 'sd, 'sm");
1110 } else {
1111 Format(instr, "vcvtis'cond 'sd, 'sm");
1112 }
1113 } else {
1114 if (instr->Bit(16) == 0) {
1115 Format(instr, "vcvtud'cond 'sd, 'dm");
1116 } else {
1117 Format(instr, "vcvtid'cond 'sd, 'dm");
1118 }
1119 }
1120 break;
1121 }
1122 case 2: // vcvtb, vcvtt
1123 case 3: // vcvtb, vcvtt
1124 case 9: // undefined
1125 case 10: // vcvt between floating-point and fixed-point
1126 case 11: // vcvt between floating-point and fixed-point
1127 case 14: // vcvt between floating-point and fixed-point
1128 case 15: // vcvt between floating-point and fixed-point
1129 default: {
1130 Unknown(instr);
1131 break;
1132 }
1133 }
1134 }
1135 break;
1136 }
1137 } else {
1138 // 8, 16, or 32-bit Transfer between ARM Core and VFP
1139 if ((instr->Bits(21, 3) == 0) && (instr->Bit(8) == 0)) {
1140 if (instr->Bit(20) == 0) {
1141 Format(instr, "vmovs'cond 'sn, 'rd");
1142 } else {
1143 Format(instr, "vmovr'cond 'rd, 'sn");
1144 }
1145 } else if ((instr->Bits(20, 4) == 0xf) && (instr->Bit(8) == 0) &&
1146 (instr->Bits(12, 4) == 0xf)) {
1147 Format(instr, "vmstat'cond");
1148 } else {
1149 Unknown(instr);
1150 }
1151 }
1152 } else {
1153 Unknown(instr);
1154 }
1155 }
1156
1157
1158 void ARMDecoder::InstructionDecode(uword pc) {
1159 Instr* instr = Instr::At(pc);
1160 if (instr->ConditionField() == kSpecialCondition) {
1161 if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) {
1162 Format(instr, "clrex");
1163 } else {
1164 Unknown(instr);
1165 }
1166 } else {
1167 switch (instr->TypeField()) {
1168 case 0:
1169 case 1: {
1170 DecodeType01(instr);
1171 break;
1172 }
1173 case 2: {
1174 DecodeType2(instr);
1175 break;
1176 }
1177 case 3: {
1178 DecodeType3(instr);
1179 break;
1180 }
1181 case 4: {
1182 DecodeType4(instr);
1183 break;
1184 }
1185 case 5: {
1186 DecodeType5(instr);
1187 break;
1188 }
1189 case 6: {
1190 DecodeType6(instr);
1191 break;
1192 }
1193 case 7: {
1194 DecodeType7(instr);
1195 break;
1196 }
1197 default: {
1198 // The type field is 3-bits in the ARM encoding.
1199 UNREACHABLE();
1200 break;
1201 }
1202 }
1203 }
1204 }
1205
1206
13 int Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size, 1207 int Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
14 char* human_buffer, intptr_t human_size, 1208 char* human_buffer, intptr_t human_size,
15 uword pc) { 1209 uword pc) {
16 UNIMPLEMENTED(); 1210 ARMDecoder decoder(human_buffer, human_size);
17 return 0; 1211 decoder.InstructionDecode(pc);
18 } 1212 int32_t instruction_bits = Instr::At(pc)->InstructionBits();
19 1213 OS::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits);
20 1214 return Instr::kInstrSize;
1215 }
1216
1217
21 void Disassembler::Disassemble(uword start, 1218 void Disassembler::Disassemble(uword start,
22 uword end, 1219 uword end,
23 DisassemblyFormatter* formatter, 1220 DisassemblyFormatter* formatter,
24 const Code::Comments& comments) { 1221 const Code::Comments& comments) {
25 UNIMPLEMENTED(); 1222 ASSERT(formatter != NULL);
1223 char hex_buffer[kHexadecimalBufferSize]; // Instruction in hexadecimal form.
1224 char human_buffer[kUserReadableBufferSize]; // Human-readable instruction.
1225 uword pc = start;
1226 intptr_t comment_finger = 0;
1227 while (pc < end) {
1228 const intptr_t offset = pc - start;
1229 while (comment_finger < comments.Length() &&
1230 comments.PCOffsetAt(comment_finger) <= offset) {
1231 formatter->Print(
1232 " ;; %s\n",
1233 String::Handle(comments.CommentAt(comment_finger)).ToCString());
1234 comment_finger++;
1235 }
1236 int instruction_length = DecodeInstruction(hex_buffer,
1237 sizeof(hex_buffer),
1238 human_buffer,
1239 sizeof(human_buffer),
1240 pc);
1241 formatter->ConsumeInstruction(hex_buffer,
1242 sizeof(hex_buffer),
1243 human_buffer,
1244 sizeof(human_buffer),
1245 pc);
1246 pc += instruction_length;
1247 }
26 } 1248 }
27 1249
28 } // namespace dart 1250 } // namespace dart
29 1251
30 #endif // defined TARGET_ARCH_ARM 1252 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/assembler_arm.cc ('k') | runtime/vm/disassembler_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698