OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // A Disassembler object is used to disassemble a block of code instruction by | 5 // A Disassembler object is used to disassemble a block of code instruction by |
6 // instruction. The default implementation of the NameConverter object can be | 6 // instruction. The default implementation of the NameConverter object can be |
7 // overriden to modify register names or to do symbol lookup on addresses. | 7 // overriden to modify register names or to do symbol lookup on addresses. |
8 // | 8 // |
9 // The example below will disassemble a block of code and print it to stdout. | 9 // The example below will disassemble a block of code and print it to stdout. |
10 // | 10 // |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 svc); | 292 svc); |
293 } | 293 } |
294 return; | 294 return; |
295 } | 295 } |
296 } | 296 } |
297 | 297 |
298 | 298 |
299 // Handle all register based formatting in this function to reduce the | 299 // Handle all register based formatting in this function to reduce the |
300 // complexity of FormatOption. | 300 // complexity of FormatOption. |
301 int Decoder::FormatRegister(Instruction* instr, const char* format) { | 301 int Decoder::FormatRegister(Instruction* instr, const char* format) { |
302 ASSERT(format[0] == 'r'); | 302 DCHECK(format[0] == 'r'); |
303 if (format[1] == 'n') { // 'rn: Rn register | 303 if (format[1] == 'n') { // 'rn: Rn register |
304 int reg = instr->RnValue(); | 304 int reg = instr->RnValue(); |
305 PrintRegister(reg); | 305 PrintRegister(reg); |
306 return 2; | 306 return 2; |
307 } else if (format[1] == 'd') { // 'rd: Rd register | 307 } else if (format[1] == 'd') { // 'rd: Rd register |
308 int reg = instr->RdValue(); | 308 int reg = instr->RdValue(); |
309 PrintRegister(reg); | 309 PrintRegister(reg); |
310 return 2; | 310 return 2; |
311 } else if (format[1] == 's') { // 'rs: Rs register | 311 } else if (format[1] == 's') { // 'rs: Rs register |
312 int reg = instr->RsValue(); | 312 int reg = instr->RsValue(); |
313 PrintRegister(reg); | 313 PrintRegister(reg); |
314 return 2; | 314 return 2; |
315 } else if (format[1] == 'm') { // 'rm: Rm register | 315 } else if (format[1] == 'm') { // 'rm: Rm register |
316 int reg = instr->RmValue(); | 316 int reg = instr->RmValue(); |
317 PrintRegister(reg); | 317 PrintRegister(reg); |
318 return 2; | 318 return 2; |
319 } else if (format[1] == 't') { // 'rt: Rt register | 319 } else if (format[1] == 't') { // 'rt: Rt register |
320 int reg = instr->RtValue(); | 320 int reg = instr->RtValue(); |
321 PrintRegister(reg); | 321 PrintRegister(reg); |
322 return 2; | 322 return 2; |
323 } else if (format[1] == 'l') { | 323 } else if (format[1] == 'l') { |
324 // 'rlist: register list for load and store multiple instructions | 324 // 'rlist: register list for load and store multiple instructions |
325 ASSERT(STRING_STARTS_WITH(format, "rlist")); | 325 DCHECK(STRING_STARTS_WITH(format, "rlist")); |
326 int rlist = instr->RlistValue(); | 326 int rlist = instr->RlistValue(); |
327 int reg = 0; | 327 int reg = 0; |
328 Print("{"); | 328 Print("{"); |
329 // Print register list in ascending order, by scanning the bit mask. | 329 // Print register list in ascending order, by scanning the bit mask. |
330 while (rlist != 0) { | 330 while (rlist != 0) { |
331 if ((rlist & 1) != 0) { | 331 if ((rlist & 1) != 0) { |
332 PrintRegister(reg); | 332 PrintRegister(reg); |
333 if ((rlist >> 1) != 0) { | 333 if ((rlist >> 1) != 0) { |
334 Print(", "); | 334 Print(", "); |
335 } | 335 } |
336 } | 336 } |
337 reg++; | 337 reg++; |
338 rlist >>= 1; | 338 rlist >>= 1; |
339 } | 339 } |
340 Print("}"); | 340 Print("}"); |
341 return 5; | 341 return 5; |
342 } | 342 } |
343 UNREACHABLE(); | 343 UNREACHABLE(); |
344 return -1; | 344 return -1; |
345 } | 345 } |
346 | 346 |
347 | 347 |
348 // Handle all VFP register based formatting in this function to reduce the | 348 // Handle all VFP register based formatting in this function to reduce the |
349 // complexity of FormatOption. | 349 // complexity of FormatOption. |
350 int Decoder::FormatVFPRegister(Instruction* instr, const char* format) { | 350 int Decoder::FormatVFPRegister(Instruction* instr, const char* format) { |
351 ASSERT((format[0] == 'S') || (format[0] == 'D')); | 351 DCHECK((format[0] == 'S') || (format[0] == 'D')); |
352 | 352 |
353 VFPRegPrecision precision = | 353 VFPRegPrecision precision = |
354 format[0] == 'D' ? kDoublePrecision : kSinglePrecision; | 354 format[0] == 'D' ? kDoublePrecision : kSinglePrecision; |
355 | 355 |
356 int retval = 2; | 356 int retval = 2; |
357 int reg = -1; | 357 int reg = -1; |
358 if (format[1] == 'n') { | 358 if (format[1] == 'n') { |
359 reg = instr->VFPNRegValue(precision); | 359 reg = instr->VFPNRegValue(precision); |
360 } else if (format[1] == 'm') { | 360 } else if (format[1] == 'm') { |
361 reg = instr->VFPMRegValue(precision); | 361 reg = instr->VFPMRegValue(precision); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 } | 455 } |
456 return 1; | 456 return 1; |
457 } | 457 } |
458 case 'b': { // 'b: byte loads or stores | 458 case 'b': { // 'b: byte loads or stores |
459 if (instr->HasB()) { | 459 if (instr->HasB()) { |
460 Print("b"); | 460 Print("b"); |
461 } | 461 } |
462 return 1; | 462 return 1; |
463 } | 463 } |
464 case 'c': { // 'cond: conditional execution | 464 case 'c': { // 'cond: conditional execution |
465 ASSERT(STRING_STARTS_WITH(format, "cond")); | 465 DCHECK(STRING_STARTS_WITH(format, "cond")); |
466 PrintCondition(instr); | 466 PrintCondition(instr); |
467 return 4; | 467 return 4; |
468 } | 468 } |
469 case 'd': { // 'd: vmov double immediate. | 469 case 'd': { // 'd: vmov double immediate. |
470 double d = instr->DoubleImmedVmov(); | 470 double d = instr->DoubleImmedVmov(); |
471 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%g", d); | 471 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%g", d); |
472 return 1; | 472 return 1; |
473 } | 473 } |
474 case 'f': { // 'f: bitfield instructions - v7 and above. | 474 case 'f': { // 'f: bitfield instructions - v7 and above. |
475 uint32_t lsbit = instr->Bits(11, 7); | 475 uint32_t lsbit = instr->Bits(11, 7); |
476 uint32_t width = instr->Bits(20, 16) + 1; | 476 uint32_t width = instr->Bits(20, 16) + 1; |
477 if (instr->Bit(21) == 0) { | 477 if (instr->Bit(21) == 0) { |
478 // BFC/BFI: | 478 // BFC/BFI: |
479 // Bits 20-16 represent most-significant bit. Covert to width. | 479 // Bits 20-16 represent most-significant bit. Covert to width. |
480 width -= lsbit; | 480 width -= lsbit; |
481 ASSERT(width > 0); | 481 DCHECK(width > 0); |
482 } | 482 } |
483 ASSERT((width + lsbit) <= 32); | 483 DCHECK((width + lsbit) <= 32); |
484 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, | 484 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
485 "#%d, #%d", lsbit, width); | 485 "#%d, #%d", lsbit, width); |
486 return 1; | 486 return 1; |
487 } | 487 } |
488 case 'h': { // 'h: halfword operation for extra loads and stores | 488 case 'h': { // 'h: halfword operation for extra loads and stores |
489 if (instr->HasH()) { | 489 if (instr->HasH()) { |
490 Print("h"); | 490 Print("h"); |
491 } else { | 491 } else { |
492 Print("b"); | 492 Print("b"); |
493 } | 493 } |
494 return 1; | 494 return 1; |
495 } | 495 } |
496 case 'i': { // 'i: immediate value from adjacent bits. | 496 case 'i': { // 'i: immediate value from adjacent bits. |
497 // Expects tokens in the form imm%02d@%02d, i.e. imm05@07, imm10@16 | 497 // Expects tokens in the form imm%02d@%02d, i.e. imm05@07, imm10@16 |
498 int width = (format[3] - '0') * 10 + (format[4] - '0'); | 498 int width = (format[3] - '0') * 10 + (format[4] - '0'); |
499 int lsb = (format[6] - '0') * 10 + (format[7] - '0'); | 499 int lsb = (format[6] - '0') * 10 + (format[7] - '0'); |
500 | 500 |
501 ASSERT((width >= 1) && (width <= 32)); | 501 DCHECK((width >= 1) && (width <= 32)); |
502 ASSERT((lsb >= 0) && (lsb <= 31)); | 502 DCHECK((lsb >= 0) && (lsb <= 31)); |
503 ASSERT((width + lsb) <= 32); | 503 DCHECK((width + lsb) <= 32); |
504 | 504 |
505 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, | 505 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
506 "%d", | 506 "%d", |
507 instr->Bits(width + lsb - 1, lsb)); | 507 instr->Bits(width + lsb - 1, lsb)); |
508 return 8; | 508 return 8; |
509 } | 509 } |
510 case 'l': { // 'l: branch and link | 510 case 'l': { // 'l: branch and link |
511 if (instr->HasLink()) { | 511 if (instr->HasLink()) { |
512 Print("l"); | 512 Print("l"); |
513 } | 513 } |
514 return 1; | 514 return 1; |
515 } | 515 } |
516 case 'm': { | 516 case 'm': { |
517 if (format[1] == 'w') { | 517 if (format[1] == 'w') { |
518 // 'mw: movt/movw instructions. | 518 // 'mw: movt/movw instructions. |
519 PrintMovwMovt(instr); | 519 PrintMovwMovt(instr); |
520 return 2; | 520 return 2; |
521 } | 521 } |
522 if (format[1] == 'e') { // 'memop: load/store instructions. | 522 if (format[1] == 'e') { // 'memop: load/store instructions. |
523 ASSERT(STRING_STARTS_WITH(format, "memop")); | 523 DCHECK(STRING_STARTS_WITH(format, "memop")); |
524 if (instr->HasL()) { | 524 if (instr->HasL()) { |
525 Print("ldr"); | 525 Print("ldr"); |
526 } else { | 526 } else { |
527 if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0) && | 527 if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0) && |
528 (instr->Bits(7, 6) == 3) && (instr->Bit(4) == 1)) { | 528 (instr->Bits(7, 6) == 3) && (instr->Bit(4) == 1)) { |
529 if (instr->Bit(5) == 1) { | 529 if (instr->Bit(5) == 1) { |
530 Print("strd"); | 530 Print("strd"); |
531 } else { | 531 } else { |
532 Print("ldrd"); | 532 Print("ldrd"); |
533 } | 533 } |
534 return 5; | 534 return 5; |
535 } | 535 } |
536 Print("str"); | 536 Print("str"); |
537 } | 537 } |
538 return 5; | 538 return 5; |
539 } | 539 } |
540 // 'msg: for simulator break instructions | 540 // 'msg: for simulator break instructions |
541 ASSERT(STRING_STARTS_WITH(format, "msg")); | 541 DCHECK(STRING_STARTS_WITH(format, "msg")); |
542 byte* str = | 542 byte* str = |
543 reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff); | 543 reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff); |
544 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, | 544 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
545 "%s", converter_.NameInCode(str)); | 545 "%s", converter_.NameInCode(str)); |
546 return 3; | 546 return 3; |
547 } | 547 } |
548 case 'o': { | 548 case 'o': { |
549 if ((format[3] == '1') && (format[4] == '2')) { | 549 if ((format[3] == '1') && (format[4] == '2')) { |
550 // 'off12: 12-bit offset for load and store instructions | 550 // 'off12: 12-bit offset for load and store instructions |
551 ASSERT(STRING_STARTS_WITH(format, "off12")); | 551 DCHECK(STRING_STARTS_WITH(format, "off12")); |
552 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, | 552 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
553 "%d", instr->Offset12Value()); | 553 "%d", instr->Offset12Value()); |
554 return 5; | 554 return 5; |
555 } else if (format[3] == '0') { | 555 } else if (format[3] == '0') { |
556 // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0. | 556 // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0. |
557 ASSERT(STRING_STARTS_WITH(format, "off0to3and8to19")); | 557 DCHECK(STRING_STARTS_WITH(format, "off0to3and8to19")); |
558 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, | 558 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
559 "%d", | 559 "%d", |
560 (instr->Bits(19, 8) << 4) + | 560 (instr->Bits(19, 8) << 4) + |
561 instr->Bits(3, 0)); | 561 instr->Bits(3, 0)); |
562 return 15; | 562 return 15; |
563 } | 563 } |
564 // 'off8: 8-bit offset for extra load and store instructions | 564 // 'off8: 8-bit offset for extra load and store instructions |
565 ASSERT(STRING_STARTS_WITH(format, "off8")); | 565 DCHECK(STRING_STARTS_WITH(format, "off8")); |
566 int offs8 = (instr->ImmedHValue() << 4) | instr->ImmedLValue(); | 566 int offs8 = (instr->ImmedHValue() << 4) | instr->ImmedLValue(); |
567 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", offs8); | 567 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", offs8); |
568 return 4; | 568 return 4; |
569 } | 569 } |
570 case 'p': { // 'pu: P and U bits for load and store instructions | 570 case 'p': { // 'pu: P and U bits for load and store instructions |
571 ASSERT(STRING_STARTS_WITH(format, "pu")); | 571 DCHECK(STRING_STARTS_WITH(format, "pu")); |
572 PrintPU(instr); | 572 PrintPU(instr); |
573 return 2; | 573 return 2; |
574 } | 574 } |
575 case 'r': { | 575 case 'r': { |
576 return FormatRegister(instr, format); | 576 return FormatRegister(instr, format); |
577 } | 577 } |
578 case 's': { | 578 case 's': { |
579 if (format[1] == 'h') { // 'shift_op or 'shift_rm or 'shift_sat. | 579 if (format[1] == 'h') { // 'shift_op or 'shift_rm or 'shift_sat. |
580 if (format[6] == 'o') { // 'shift_op | 580 if (format[6] == 'o') { // 'shift_op |
581 ASSERT(STRING_STARTS_WITH(format, "shift_op")); | 581 DCHECK(STRING_STARTS_WITH(format, "shift_op")); |
582 if (instr->TypeValue() == 0) { | 582 if (instr->TypeValue() == 0) { |
583 PrintShiftRm(instr); | 583 PrintShiftRm(instr); |
584 } else { | 584 } else { |
585 ASSERT(instr->TypeValue() == 1); | 585 DCHECK(instr->TypeValue() == 1); |
586 PrintShiftImm(instr); | 586 PrintShiftImm(instr); |
587 } | 587 } |
588 return 8; | 588 return 8; |
589 } else if (format[6] == 's') { // 'shift_sat. | 589 } else if (format[6] == 's') { // 'shift_sat. |
590 ASSERT(STRING_STARTS_WITH(format, "shift_sat")); | 590 DCHECK(STRING_STARTS_WITH(format, "shift_sat")); |
591 PrintShiftSat(instr); | 591 PrintShiftSat(instr); |
592 return 9; | 592 return 9; |
593 } else { // 'shift_rm | 593 } else { // 'shift_rm |
594 ASSERT(STRING_STARTS_WITH(format, "shift_rm")); | 594 DCHECK(STRING_STARTS_WITH(format, "shift_rm")); |
595 PrintShiftRm(instr); | 595 PrintShiftRm(instr); |
596 return 8; | 596 return 8; |
597 } | 597 } |
598 } else if (format[1] == 'v') { // 'svc | 598 } else if (format[1] == 'v') { // 'svc |
599 ASSERT(STRING_STARTS_WITH(format, "svc")); | 599 DCHECK(STRING_STARTS_WITH(format, "svc")); |
600 PrintSoftwareInterrupt(instr->SvcValue()); | 600 PrintSoftwareInterrupt(instr->SvcValue()); |
601 return 3; | 601 return 3; |
602 } else if (format[1] == 'i') { // 'sign: signed extra loads and stores | 602 } else if (format[1] == 'i') { // 'sign: signed extra loads and stores |
603 ASSERT(STRING_STARTS_WITH(format, "sign")); | 603 DCHECK(STRING_STARTS_WITH(format, "sign")); |
604 if (instr->HasSign()) { | 604 if (instr->HasSign()) { |
605 Print("s"); | 605 Print("s"); |
606 } | 606 } |
607 return 4; | 607 return 4; |
608 } | 608 } |
609 // 's: S field of data processing instructions | 609 // 's: S field of data processing instructions |
610 if (instr->HasS()) { | 610 if (instr->HasS()) { |
611 Print("s"); | 611 Print("s"); |
612 } | 612 } |
613 return 1; | 613 return 1; |
614 } | 614 } |
615 case 't': { // 'target: target of branch instructions | 615 case 't': { // 'target: target of branch instructions |
616 ASSERT(STRING_STARTS_WITH(format, "target")); | 616 DCHECK(STRING_STARTS_WITH(format, "target")); |
617 int off = (instr->SImmed24Value() << 2) + 8; | 617 int off = (instr->SImmed24Value() << 2) + 8; |
618 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, | 618 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
619 "%+d -> %s", | 619 "%+d -> %s", |
620 off, | 620 off, |
621 converter_.NameOfAddress( | 621 converter_.NameOfAddress( |
622 reinterpret_cast<byte*>(instr) + off)); | 622 reinterpret_cast<byte*>(instr) + off)); |
623 return 6; | 623 return 6; |
624 } | 624 } |
625 case 'u': { // 'u: signed or unsigned multiplies | 625 case 'u': { // 'u: signed or unsigned multiplies |
626 // The manual gets the meaning of bit 22 backwards in the multiply | 626 // The manual gets the meaning of bit 22 backwards in the multiply |
(...skipping 1154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1781 v8::internal::PrintF( | 1781 v8::internal::PrintF( |
1782 f, "%p %08x %s\n", | 1782 f, "%p %08x %s\n", |
1783 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1783 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
1784 } | 1784 } |
1785 } | 1785 } |
1786 | 1786 |
1787 | 1787 |
1788 } // namespace disasm | 1788 } // namespace disasm |
1789 | 1789 |
1790 #endif // V8_TARGET_ARCH_ARM | 1790 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |