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

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

Issue 235363005: Adds comparisons, labels, branches to arm64 (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 8 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
OLDNEW
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 16 matching lines...) Expand all
27 27
28 private: 28 private:
29 // Bottleneck functions to print into the out_buffer. 29 // Bottleneck functions to print into the out_buffer.
30 void Print(const char* str); 30 void Print(const char* str);
31 31
32 // Printing of common values. 32 // Printing of common values.
33 void PrintRegister(int reg, R31Type r31t); 33 void PrintRegister(int reg, R31Type r31t);
34 void PrintShiftExtendRm(Instr* instr); 34 void PrintShiftExtendRm(Instr* instr);
35 void PrintMemOperand(Instr* instr); 35 void PrintMemOperand(Instr* instr);
36 void PrintS(Instr* instr); 36 void PrintS(Instr* instr);
37 void PrintCondition(Instr* instr);
37 38
38 // Handle formatting of instructions and their options. 39 // Handle formatting of instructions and their options.
39 int FormatRegister(Instr* instr, const char* option); 40 int FormatRegister(Instr* instr, const char* option);
40 int FormatOption(Instr* instr, const char* format); 41 int FormatOption(Instr* instr, const char* format);
41 void Format(Instr* instr, const char* format); 42 void Format(Instr* instr, const char* format);
42 void Unknown(Instr* instr); 43 void Unknown(Instr* instr);
43 44
44 // Decode instructions. 45 // Decode instructions.
45 #define DECODE_OP(op) \ 46 #define DECODE_OP(op) \
46 void Decode##op(Instr* instr); 47 void Decode##op(Instr* instr);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 "lsl", "lsr", "asr", "ror" 109 "lsl", "lsr", "asr", "ror"
109 }; 110 };
110 111
111 112
112 static const char* extend_names[kMaxExtend] = { 113 static const char* extend_names[kMaxExtend] = {
113 "uxtb", "uxth", "uxtw", "uxtx", 114 "uxtb", "uxth", "uxtw", "uxtx",
114 "sxtb", "sxth", "sxtw", "sxtx", 115 "sxtb", "sxth", "sxtw", "sxtx",
115 }; 116 };
116 117
117 118
119 // These condition names are defined in a way to match the native disassembler
120 // formatting. See for example the command "objdump -d <binary file>".
121 static const char* cond_names[kMaxCondition] = {
122 "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
123 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
124 };
125
126
127 // Print the condition guarding the instruction.
128 void ARM64Decoder::PrintCondition(Instr* instr) {
129 Print(cond_names[instr->ConditionField()]);
130 }
131
132
118 // Print the register shift operands for the instruction. Generally used for 133 // Print the register shift operands for the instruction. Generally used for
119 // data processing instructions. 134 // data processing instructions.
120 void ARM64Decoder::PrintShiftExtendRm(Instr* instr) { 135 void ARM64Decoder::PrintShiftExtendRm(Instr* instr) {
121 int rm = instr->RmField(); 136 int rm = instr->RmField();
122 Shift shift = instr->ShiftTypeField(); 137 Shift shift = instr->ShiftTypeField();
123 int shift_amount = instr->ShiftAmountField(); 138 int shift_amount = instr->ShiftAmountField();
124 Extend extend = instr->ExtendTypeField(); 139 Extend extend = instr->ExtendTypeField();
125 int extend_shift_amount = instr->ExtShiftAmountField(); 140 int extend_shift_amount = instr->ExtShiftAmountField();
126 141
127 PrintRegister(rm, R31IsZR); 142 PrintRegister(rm, R31IsZR);
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 } 271 }
257 272
258 273
259 // FormatOption takes a formatting string and interprets it based on 274 // FormatOption takes a formatting string and interprets it based on
260 // the current instructions. The format string points to the first 275 // the current instructions. The format string points to the first
261 // character of the option string (the option escape has already been 276 // character of the option string (the option escape has already been
262 // consumed by the caller.) FormatOption returns the number of 277 // consumed by the caller.) FormatOption returns the number of
263 // characters that were consumed from the formatting string. 278 // characters that were consumed from the formatting string.
264 int ARM64Decoder::FormatOption(Instr* instr, const char* format) { 279 int ARM64Decoder::FormatOption(Instr* instr, const char* format) {
265 switch (format[0]) { 280 switch (format[0]) {
281 case 'b': {
282 if (format[3] == 'i') {
283 ASSERT(STRING_STARTS_WITH(format, "bitimm"));
284 const uint64_t imm = instr->ImmLogical();
285 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
286 remaining_size_in_buffer(),
287 "0x%"Px64,
288 imm);
289 return 6;
290 } else {
291 ASSERT(STRING_STARTS_WITH(format, "bitpos"));
292 int bitpos = instr->Bits(19, 4) | (instr->Bit(31) << 5);
293 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
294 remaining_size_in_buffer(),
295 "#%d",
296 bitpos);
297 return 6;
298 }
299 }
300 case 'c': {
301 ASSERT(STRING_STARTS_WITH(format, "cond"));
302 PrintCondition(instr);
303 return 4;
304 }
305 case 'd': {
306 if (format[4] == '2') {
307 ASSERT(STRING_STARTS_WITH(format, "dest26"));
308 int64_t off = instr->SImm26Field() << 2;
309 uword destination = reinterpret_cast<uword>(instr) + off;
310 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
311 remaining_size_in_buffer(),
312 "%#" Px "",
313 destination);
314 } else {
315 if (format[5] == '4') {
316 ASSERT(STRING_STARTS_WITH(format, "dest14"));
317 int64_t off = instr->SImm14Field() << 2;
318 uword destination = reinterpret_cast<uword>(instr) + off;
319 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
320 remaining_size_in_buffer(),
321 "%#" Px "",
322 destination);
323 } else {
324 ASSERT(STRING_STARTS_WITH(format, "dest19"));
325 int64_t off = instr->SImm19Field() << 2;
326 uword destination = reinterpret_cast<uword>(instr) + off;
327 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
328 remaining_size_in_buffer(),
329 "%#" Px "",
330 destination);
331 }
332 }
333 return 6;
334 }
335 case 'h': {
336 ASSERT(STRING_STARTS_WITH(format, "hw"));
337 const int shift = instr->HWField() << 4;
338 if (shift != 0) {
339 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
340 remaining_size_in_buffer(),
341 "lsl %d",
342 shift);
343 }
344 return 2;
345 }
266 case 'i': { // 'imm12, imm16 346 case 'i': { // 'imm12, imm16
267 uint64_t imm; 347 uint64_t imm;
268 int ret = 5; 348 int ret = 5;
269 if (format[4] == '2') { 349 if (format[4] == '2') {
270 ASSERT(STRING_STARTS_WITH(format, "imm12")); 350 ASSERT(STRING_STARTS_WITH(format, "imm12"));
271 imm = instr->Imm12Field(); 351 imm = instr->Imm12Field();
272 if (format[5] == 's') { 352 if (format[5] == 's') {
273 // shifted immediate. 353 // shifted immediate.
274 if (instr->Imm12ShiftField() == 1) { 354 if (instr->Imm12ShiftField() == 1) {
275 imm = imm << 12; 355 imm = imm << 12;
276 } else if ((instr->Imm12ShiftField() & 0x2) != 0) { 356 } else if ((instr->Imm12ShiftField() & 0x2) != 0) {
277 Print("Unknown Shift"); 357 Print("Unknown Shift");
278 } 358 }
279 ret = 6; 359 ret = 6;
280 } 360 }
281 } else { 361 } else {
282 ASSERT(STRING_STARTS_WITH(format, "imm16")); 362 ASSERT(STRING_STARTS_WITH(format, "imm16"));
283 imm = instr->Imm16Field(); 363 imm = instr->Imm16Field();
284 } 364 }
285 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), 365 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
286 remaining_size_in_buffer(), 366 remaining_size_in_buffer(),
287 "0x%"Px64, 367 "0x%"Px64,
288 imm); 368 imm);
289 return ret; 369 return ret;
290 } 370 }
371 case 'm': {
372 ASSERT(STRING_STARTS_WITH(format, "memop"));
373 PrintMemOperand(instr);
374 return 5;
375 }
376 case 'p': {
377 ASSERT(STRING_STARTS_WITH(format, "pcrel"));
378 const int64_t immhi = instr->SImm19Field();
379 const int64_t immlo = instr->Bits(29, 2);
380 const int64_t off = (immhi << 2) | immlo;
381 const int64_t pc = reinterpret_cast<int64_t>(instr);
382 const int64_t dest = pc + off;
383 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
384 remaining_size_in_buffer(),
385 "0x%"Px64,
386 dest);
387 return 5;
388 }
389 case 'r': {
390 return FormatRegister(instr, format);
391 }
291 case 's': { // 's: S flag. 392 case 's': { // 's: S flag.
292 if (format[1] == 'h') { 393 if (format[1] == 'h') {
293 ASSERT(STRING_STARTS_WITH(format, "shift_op")); 394 ASSERT(STRING_STARTS_WITH(format, "shift_op"));
294 PrintShiftExtendRm(instr); 395 PrintShiftExtendRm(instr);
295 return 8; 396 return 8;
296 } else if (format[1] == 'f') { 397 } else if (format[1] == 'f') {
297 ASSERT(STRING_STARTS_WITH(format, "sf")); 398 ASSERT(STRING_STARTS_WITH(format, "sf"));
298 if (instr->SFField() == 1) { 399 if (instr->SFField() == 1) {
299 // TODO(zra): If we don't use the w form much, we can omit printing 400 // TODO(zra): If we don't use the w form much, we can omit printing
300 // this x. 401 // this x.
(...skipping 20 matching lines...) Expand all
321 return 2; 422 return 2;
322 } else if (format[1] == ' ') { 423 } else if (format[1] == ' ') {
323 if (instr->HasS()) { 424 if (instr->HasS()) {
324 Print("s"); 425 Print("s");
325 } 426 }
326 return 1; 427 return 1;
327 } else { 428 } else {
328 UNREACHABLE(); 429 UNREACHABLE();
329 } 430 }
330 } 431 }
331 case 'r': {
332 return FormatRegister(instr, format);
333 }
334 case 'h': {
335 ASSERT(STRING_STARTS_WITH(format, "hw"));
336 const int shift = instr->HWField() << 4;
337 if (shift != 0) {
338 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
339 remaining_size_in_buffer(),
340 "lsl %d",
341 shift);
342 }
343 return 2;
344 }
345 case 'm': {
346 ASSERT(STRING_STARTS_WITH(format, "memop"));
347 PrintMemOperand(instr);
348 return 5;
349 }
350 case 'b': {
351 ASSERT(STRING_STARTS_WITH(format, "bitimm"));
352 const uint64_t imm = instr->ImmLogical();
353 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
354 remaining_size_in_buffer(),
355 "0x%"Px64,
356 imm);
357 return 6;
358 }
359 default: { 432 default: {
360 UNREACHABLE(); 433 UNREACHABLE();
361 break; 434 break;
362 } 435 }
363 } 436 }
364 UNREACHABLE(); 437 UNREACHABLE();
365 return -1; 438 return -1;
366 } 439 }
367 440
368 441
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 case 3: 534 case 3:
462 Format(instr, "andi'sfs 'rd, 'rn, 'bitimm"); 535 Format(instr, "andi'sfs 'rd, 'rn, 'bitimm");
463 break; 536 break;
464 default: 537 default:
465 Unknown(instr); 538 Unknown(instr);
466 break; 539 break;
467 } 540 }
468 } 541 }
469 542
470 543
544 void ARM64Decoder::DecodePCRel(Instr* instr) {
545 const int op = instr->Bit(31);
546 if (op == 0) {
547 Format(instr, "adr 'rd, 'pcrel");
548 } else {
549 Unknown(instr);
550 }
551 }
552
553
471 void ARM64Decoder::DecodeDPImmediate(Instr* instr) { 554 void ARM64Decoder::DecodeDPImmediate(Instr* instr) {
472 if (instr->IsMoveWideOp()) { 555 if (instr->IsMoveWideOp()) {
473 DecodeMoveWide(instr); 556 DecodeMoveWide(instr);
474 } else if (instr->IsAddSubImmOp()) { 557 } else if (instr->IsAddSubImmOp()) {
475 DecodeAddSubImm(instr); 558 DecodeAddSubImm(instr);
476 } else if (instr->IsLogicalImmOp()) { 559 } else if (instr->IsLogicalImmOp()) {
477 DecodeLogicalImm(instr); 560 DecodeLogicalImm(instr);
561 } else if (instr->IsPCRelOp()) {
562 DecodePCRel(instr);
478 } else { 563 } else {
479 Unknown(instr); 564 Unknown(instr);
480 } 565 }
481 } 566 }
482 567
483 568
484 void ARM64Decoder::DecodeExceptionGen(Instr* instr) { 569 void ARM64Decoder::DecodeExceptionGen(Instr* instr) {
485 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) && 570 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) &&
486 (instr->Bits(21, 3) == 0)) { 571 (instr->Bits(21, 3) == 0)) {
487 Format(instr, "svc 'imm16"); 572 Format(instr, "svc 'imm16");
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 Format(instr, "ret 'rn"); 609 Format(instr, "ret 'rn");
525 break; 610 break;
526 default: 611 default:
527 Unknown(instr); 612 Unknown(instr);
528 break; 613 break;
529 } 614 }
530 } 615 }
531 } 616 }
532 617
533 618
619 void ARM64Decoder::DecodeCompareAndBranch(Instr* instr) {
620 const int op = instr->Bit(24);
621 if (op == 0) {
622 Format(instr, "cbz'sf 'rt, 'dest19");
623 } else {
624 Format(instr, "cbnz'sf 'rt, 'dest19");
625 }
626 }
627
628
629 void ARM64Decoder::DecodeConditionalBranch(Instr* instr) {
630 if ((instr->Bit(24) != 0) || (instr->Bit(4) != 0)) {
631 Unknown(instr);
632 return;
633 }
634 Format(instr, "b'cond 'dest19");
635 }
636
637
638 void ARM64Decoder::DecodeTestAndBranch(Instr* instr) {
639 const int op = instr->Bit(24);
640 if (op == 0) {
641 Format(instr, "tbz'sf 'rt, 'bitpos, 'dest14");
642 } else {
643 Format(instr, "tbnz'sf 'rt, 'bitpos, 'dest14");
644 }
645 }
646
647
648 void ARM64Decoder::DecodeUnconditionalBranch(Instr* instr) {
649 const int op = instr->Bit(31);
650 if (op == 0) {
651 Format(instr, "b 'dest26");
652 } else {
653 Format(instr, "bl 'dest26");
654 }
655 }
656
534 void ARM64Decoder::DecodeCompareBranch(Instr* instr) { 657 void ARM64Decoder::DecodeCompareBranch(Instr* instr) {
535 if (instr->IsExceptionGenOp()) { 658 if (instr->IsExceptionGenOp()) {
536 DecodeExceptionGen(instr); 659 DecodeExceptionGen(instr);
537 } else if (instr->IsSystemOp()) { 660 } else if (instr->IsSystemOp()) {
538 DecodeSystem(instr); 661 DecodeSystem(instr);
539 } else if (instr->IsUnconditionalBranchRegOp()) { 662 } else if (instr->IsUnconditionalBranchRegOp()) {
540 DecodeUnconditionalBranchReg(instr); 663 DecodeUnconditionalBranchReg(instr);
664 } else if (instr->IsCompareAndBranchOp()) {
665 DecodeCompareAndBranch(instr);
666 } else if (instr->IsConditionalBranchOp()) {
667 DecodeConditionalBranch(instr);
668 } else if (instr->IsTestAndBranchOp()) {
669 DecodeTestAndBranch(instr);
670 } else if (instr->IsUnconditionalBranchOp()) {
671 DecodeUnconditionalBranch(instr);
541 } else { 672 } else {
542 Unknown(instr); 673 Unknown(instr);
543 } 674 }
544 } 675 }
545 676
546 677
547 void ARM64Decoder::DecodeLoadStore(Instr* instr) { 678 void ARM64Decoder::DecodeLoadStore(Instr* instr) {
548 if (instr->IsLoadStoreRegOp()) { 679 if (instr->IsLoadStoreRegOp()) {
549 DecodeLoadStoreReg(instr); 680 DecodeLoadStoreReg(instr);
550 } else { 681 } else {
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 human_buffer, 825 human_buffer,
695 sizeof(human_buffer), 826 sizeof(human_buffer),
696 pc); 827 pc);
697 pc += instruction_length; 828 pc += instruction_length;
698 } 829 }
699 } 830 }
700 831
701 } // namespace dart 832 } // namespace dart
702 833
703 #endif // defined TARGET_ARCH_ARM 834 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698