1 // Copyright 2013 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <assert.h> 6 #include <stdarg.h> 7 #include <stdio.h> 8 #include <string.h> 9 10 #if V8_TARGET_ARCH_ARM64 11 12 #include "src/arm64/decoder-arm64-inl.h" 13 #include "src/arm64/disasm-arm64.h" 14 #include "src/base/platform/platform.h" 15 #include "src/disasm.h" 16 #include "src/macro-assembler.h" 17 18 namespace v8 { 19 namespace internal { 20 21 22 DisassemblingDecoder::DisassemblingDecoder() { 23 buffer_size_ = 256; 24 buffer_ = reinterpret_cast<char*>(malloc(buffer_size_)); 25 buffer_pos_ = 0; 26 own_buffer_ = true; 27 } 28 29 30 DisassemblingDecoder::DisassemblingDecoder(char* text_buffer, int buffer_size) { 31 buffer_size_ = buffer_size; 32 buffer_ = text_buffer; 33 buffer_pos_ = 0; 34 own_buffer_ = false; 35 } 36 37 38 DisassemblingDecoder::~DisassemblingDecoder() { 39 if (own_buffer_) { 40 free(buffer_); 41 } 42 } 43 44 45 char* DisassemblingDecoder::GetOutput() { return buffer_; } 46 47 48 void DisassemblingDecoder::VisitAddSubImmediate(Instruction* instr) { 49 bool rd_is_zr = RdIsZROrSP(instr); 50 bool stack_op = (rd_is_zr || RnIsZROrSP(instr)) && 51 (instr->ImmAddSub() == 0) ? true : false; 52 const char *mnemonic = ""; 53 const char *form = "'Rds, 'Rns, 'IAddSub"; 54 const char *form_cmp = "'Rns, 'IAddSub"; 55 const char *form_mov = "'Rds, 'Rns"; 56 57 switch (instr->Mask(AddSubImmediateMask)) { 58 case ADD_w_imm: 59 case ADD_x_imm: { 60 mnemonic = "add"; 61 if (stack_op) { 62 mnemonic = "mov"; 63 form = form_mov; 64 } 65 break; 66 } 67 case ADDS_w_imm: 68 case ADDS_x_imm: { 69 mnemonic = "adds"; 70 if (rd_is_zr) { 71 mnemonic = "cmn"; 72 form = form_cmp; 73 } 74 break; 75 } 76 case SUB_w_imm: 77 case SUB_x_imm: mnemonic = "sub"; break; 78 case SUBS_w_imm: 79 case SUBS_x_imm: { 80 mnemonic = "subs"; 81 if (rd_is_zr) { 82 mnemonic = "cmp"; 83 form = form_cmp; 84 } 85 break; 86 } 87 default: UNREACHABLE(); 88 } 89 Format(instr, mnemonic, form); 90 } 91 92 93 void DisassemblingDecoder::VisitAddSubShifted(Instruction* instr) { 94 bool rd_is_zr = RdIsZROrSP(instr); 95 bool rn_is_zr = RnIsZROrSP(instr); 96 const char *mnemonic = ""; 97 const char *form = "'Rd, 'Rn, 'Rm'HDP"; 98 const char *form_cmp = "'Rn, 'Rm'HDP"; 99 const char *form_neg = "'Rd, 'Rm'HDP"; 100 101 switch (instr->Mask(AddSubShiftedMask)) { 102 case ADD_w_shift: 103 case ADD_x_shift: mnemonic = "add"; break; 104 case ADDS_w_shift: 105 case ADDS_x_shift: { 106 mnemonic = "adds"; 107 if (rd_is_zr) { 108 mnemonic = "cmn"; 109 form = form_cmp; 110 } 111 break; 112 } 113 case SUB_w_shift: 114 case SUB_x_shift: { 115 mnemonic = "sub"; 116 if (rn_is_zr) { 117 mnemonic = "neg"; 118 form = form_neg; 119 } 120 break; 121 } 122 case SUBS_w_shift: 123 case SUBS_x_shift: { 124 mnemonic = "subs"; 125 if (rd_is_zr) { 126 mnemonic = "cmp"; 127 form = form_cmp; 128 } else if (rn_is_zr) { 129 mnemonic = "negs"; 130 form = form_neg; 131 } 132 break; 133 } 134 default: UNREACHABLE(); 135 } 136 Format(instr, mnemonic, form); 137 } 138 139 140 void DisassemblingDecoder::VisitAddSubExtended(Instruction* instr) { 141 bool rd_is_zr = RdIsZROrSP(instr); 142 const char *mnemonic = ""; 143 Extend mode = static_cast<Extend>(instr->ExtendMode()); 144 const char *form = ((mode == UXTX) || (mode == SXTX)) ? 145 "'Rds, 'Rns, 'Xm'Ext" : "'Rds, 'Rns, 'Wm'Ext"; 146 const char *form_cmp = ((mode == UXTX) || (mode == SXTX)) ? 147 "'Rns, 'Xm'Ext" : "'Rns, 'Wm'Ext"; 148 149 switch (instr->Mask(AddSubExtendedMask)) { 150 case ADD_w_ext: 151 case ADD_x_ext: mnemonic = "add"; break; 152 case ADDS_w_ext: 153 case ADDS_x_ext: { 154 mnemonic = "adds"; 155 if (rd_is_zr) { 156 mnemonic = "cmn"; 157 form = form_cmp; 158 } 159 break; 160 } 161 case SUB_w_ext: 162 case SUB_x_ext: mnemonic = "sub"; break; 163 case SUBS_w_ext: 164 case SUBS_x_ext: { 165 mnemonic = "subs"; 166 if (rd_is_zr) { 167 mnemonic = "cmp"; 168 form = form_cmp; 169 } 170 break; 171 } 172 default: UNREACHABLE(); 173 } 174 Format(instr, mnemonic, form); 175 } 176 177 178 void DisassemblingDecoder::VisitAddSubWithCarry(Instruction* instr) { 179 bool rn_is_zr = RnIsZROrSP(instr); 180 const char *mnemonic = ""; 181 const char *form = "'Rd, 'Rn, 'Rm"; 182 const char *form_neg = "'Rd, 'Rm"; 183 184 switch (instr->Mask(AddSubWithCarryMask)) { 185 case ADC_w: 186 case ADC_x: mnemonic = "adc"; break; 187 case ADCS_w: 188 case ADCS_x: mnemonic = "adcs"; break; 189 case SBC_w: 190 case SBC_x: { 191 mnemonic = "sbc"; 192 if (rn_is_zr) { 193 mnemonic = "ngc"; 194 form = form_neg; 195 } 196 break; 197 } 198 case SBCS_w: 199 case SBCS_x: { 200 mnemonic = "sbcs"; 201 if (rn_is_zr) { 202 mnemonic = "ngcs"; 203 form = form_neg; 204 } 205 break; 206 } 207 default: UNREACHABLE(); 208 } 209 Format(instr, mnemonic, form); 210 } 211 212 213 void DisassemblingDecoder::VisitLogicalImmediate(Instruction* instr) { 214 bool rd_is_zr = RdIsZROrSP(instr); 215 bool rn_is_zr = RnIsZROrSP(instr); 216 const char *mnemonic = ""; 217 const char *form = "'Rds, 'Rn, 'ITri"; 218 219 if (instr->ImmLogical() == 0) { 220 // The immediate encoded in the instruction is not in the expected format. 221 Format(instr, "unallocated", "(LogicalImmediate)"); 222 return; 223 } 224 225 switch (instr->Mask(LogicalImmediateMask)) { 226 case AND_w_imm: 227 case AND_x_imm: mnemonic = "and"; break; 228 case ORR_w_imm: 229 case ORR_x_imm: { 230 mnemonic = "orr"; 231 unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSizeInBits 232 : kWRegSizeInBits; 233 if (rn_is_zr && !IsMovzMovnImm(reg_size, instr->ImmLogical())) { 234 mnemonic = "mov"; 235 form = "'Rds, 'ITri"; 236 } 237 break; 238 } 239 case EOR_w_imm: 240 case EOR_x_imm: mnemonic = "eor"; break; 241 case ANDS_w_imm: 242 case ANDS_x_imm: { 243 mnemonic = "ands"; 244 if (rd_is_zr) { 245 mnemonic = "tst"; 246 form = "'Rn, 'ITri"; 247 } 248 break; 249 } 250 default: UNREACHABLE(); 251 } 252 Format(instr, mnemonic, form); 253 } 254 255 256 bool DisassemblingDecoder::IsMovzMovnImm(unsigned reg_size, uint64_t value) { 257 DCHECK((reg_size == kXRegSizeInBits) || 258 ((reg_size == kWRegSizeInBits) && (value <= 0xffffffff))); 259 260 // Test for movz: 16-bits set at positions 0, 16, 32 or 48. 261 if (((value & 0xffffffffffff0000UL) == 0UL) || 262 ((value & 0xffffffff0000ffffUL) == 0UL) || 263 ((value & 0xffff0000ffffffffUL) == 0UL) || 264 ((value & 0x0000ffffffffffffUL) == 0UL)) { 265 return true; 266 } 267 268 // Test for movn: NOT(16-bits set at positions 0, 16, 32 or 48). 269 if ((reg_size == kXRegSizeInBits) && 270 (((value & 0xffffffffffff0000UL) == 0xffffffffffff0000UL) || 271 ((value & 0xffffffff0000ffffUL) == 0xffffffff0000ffffUL) || 272 ((value & 0xffff0000ffffffffUL) == 0xffff0000ffffffffUL) || 273 ((value & 0x0000ffffffffffffUL) == 0x0000ffffffffffffUL))) { 274 return true; 275 } 276 if ((reg_size == kWRegSizeInBits) && 277 (((value & 0xffff0000) == 0xffff0000) || 278 ((value & 0x0000ffff) == 0x0000ffff))) { 279 return true; 280 } 281 return false; 282 } 283 284 285 void DisassemblingDecoder::VisitLogicalShifted(Instruction* instr) { 286 bool rd_is_zr = RdIsZROrSP(instr); 287 bool rn_is_zr = RnIsZROrSP(instr); 288 const char *mnemonic = ""; 289 const char *form = "'Rd, 'Rn, 'Rm'HLo"; 290 291 switch (instr->Mask(LogicalShiftedMask)) { 292 case AND_w: 293 case AND_x: mnemonic = "and"; break; 294 case BIC_w: 295 case BIC_x: mnemonic = "bic"; break; 296 case EOR_w: 297 case EOR_x: mnemonic = "eor"; break; 298 case EON_w: 299 case EON_x: mnemonic = "eon"; break; 300 case BICS_w: 301 case BICS_x: mnemonic = "bics"; break; 302 case ANDS_w: 303 case ANDS_x: { 304 mnemonic = "ands"; 305 if (rd_is_zr) { 306 mnemonic = "tst"; 307 form = "'Rn, 'Rm'HLo"; 308 } 309 break; 310 } 311 case ORR_w: 312 case ORR_x: { 313 mnemonic = "orr"; 314 if (rn_is_zr && (instr->ImmDPShift() == 0) && (instr->ShiftDP() == LSL)) { 315 mnemonic = "mov"; 316 form = "'Rd, 'Rm"; 317 } 318 break; 319 } 320 case ORN_w: 321 case ORN_x: { 322 mnemonic = "orn"; 323 if (rn_is_zr) { 324 mnemonic = "mvn"; 325 form = "'Rd, 'Rm'HLo"; 326 } 327 break; 328 } 329 default: UNREACHABLE(); 330 } 331 332 Format(instr, mnemonic, form); 333 } 334 335 336 void DisassemblingDecoder::VisitConditionalCompareRegister(Instruction* instr) { 337 const char *mnemonic = ""; 338 const char *form = "'Rn, 'Rm, 'INzcv, 'Cond"; 339 340 switch (instr->Mask(ConditionalCompareRegisterMask)) { 341 case CCMN_w: 342 case CCMN_x: mnemonic = "ccmn"; break; 343 case CCMP_w: 344 case CCMP_x: mnemonic = "ccmp"; break; 345 default: UNREACHABLE(); 346 } 347 Format(instr, mnemonic, form); 348 } 349 350 351 void DisassemblingDecoder::VisitConditionalCompareImmediate( 352 Instruction* instr) { 353 const char *mnemonic = ""; 354 const char *form = "'Rn, 'IP, 'INzcv, 'Cond"; 355 356 switch (instr->Mask(ConditionalCompareImmediateMask)) { 357 case CCMN_w_imm: 358 case CCMN_x_imm: mnemonic = "ccmn"; break; 359 case CCMP_w_imm: 360 case CCMP_x_imm: mnemonic = "ccmp"; break; 361 default: UNREACHABLE(); 362 } 363 Format(instr, mnemonic, form); 364 } 365 366 367 void DisassemblingDecoder::VisitConditionalSelect(Instruction* instr) { 368 bool rnm_is_zr = (RnIsZROrSP(instr) && RmIsZROrSP(instr)); 369 bool rn_is_rm = (instr->Rn() == instr->Rm()); 370 const char *mnemonic = ""; 371 const char *form = "'Rd, 'Rn, 'Rm, 'Cond"; 372 const char *form_test = "'Rd, 'CInv"; 373 const char *form_update = "'Rd, 'Rn, 'CInv"; 374 375 Condition cond = static_cast<Condition>(instr->Condition()); 376 bool invertible_cond = (cond != al) && (cond != nv); 377 378 switch (instr->Mask(ConditionalSelectMask)) { 379 case CSEL_w: 380 case CSEL_x: mnemonic = "csel"; break; 381 case CSINC_w: 382 case CSINC_x: { 383 mnemonic = "csinc"; 384 if (rnm_is_zr && invertible_cond) { 385 mnemonic = "cset"; 386 form = form_test; 387 } else if (rn_is_rm && invertible_cond) { 388 mnemonic = "cinc"; 389 form = form_update; 390 } 391 break; 392 } 393 case CSINV_w: 394 case CSINV_x: { 395 mnemonic = "csinv"; 396 if (rnm_is_zr && invertible_cond) { 397 mnemonic = "csetm"; 398 form = form_test; 399 } else if (rn_is_rm && invertible_cond) { 400 mnemonic = "cinv"; 401 form = form_update; 402 } 403 break; 404 } 405 case CSNEG_w: 406 case CSNEG_x: { 407 mnemonic = "csneg"; 408 if (rn_is_rm && invertible_cond) { 409 mnemonic = "cneg"; 410 form = form_update; 411 } 412 break; 413 } 414 default: UNREACHABLE(); 415 } 416 Format(instr, mnemonic, form); 417 } 418 419 420 void DisassemblingDecoder::VisitBitfield(Instruction* instr) { 421 unsigned s = instr->ImmS(); 422 unsigned r = instr->ImmR(); 423 unsigned rd_size_minus_1 = 424 ((instr->SixtyFourBits() == 1) ? kXRegSizeInBits : kWRegSizeInBits) - 1; 425 const char *mnemonic = ""; 426 const char *form = ""; 427 const char *form_shift_right = "'Rd, 'Rn, 'IBr"; 428 const char *form_extend = "'Rd, 'Wn"; 429 const char *form_bfiz = "'Rd, 'Rn, 'IBZ-r, 'IBs+1"; 430 const char *form_bfx = "'Rd, 'Rn, 'IBr, 'IBs-r+1"; 431 const char *form_lsl = "'Rd, 'Rn, 'IBZ-r"; 432 433 switch (instr->Mask(BitfieldMask)) { 434 case SBFM_w: 435 case SBFM_x: { 436 mnemonic = "sbfx"; 437 form = form_bfx; 438 if (r == 0) { 439 form = form_extend; 440 if (s == 7) { 441 mnemonic = "sxtb"; 442 } else if (s == 15) { 443 mnemonic = "sxth"; 444 } else if ((s == 31) && (instr->SixtyFourBits() == 1)) { 445 mnemonic = "sxtw"; 446 } else { 447 form = form_bfx; 448 } 449 } else if (s == rd_size_minus_1) { 450 mnemonic = "asr"; 451 form = form_shift_right; 452 } else if (s < r) { 453 mnemonic = "sbfiz"; 454 form = form_bfiz; 455 } 456 break; 457 } 458 case UBFM_w: 459 case UBFM_x: { 460 mnemonic = "ubfx"; 461 form = form_bfx; 462 if (r == 0) { 463 form = form_extend; 464 if (s == 7) { 465 mnemonic = "uxtb"; 466 } else if (s == 15) { 467 mnemonic = "uxth"; 468 } else { 469 form = form_bfx; 470 } 471 } 472 if (s == rd_size_minus_1) { 473 mnemonic = "lsr"; 474 form = form_shift_right; 475 } else if (r == s + 1) { 476 mnemonic = "lsl"; 477 form = form_lsl; 478 } else if (s < r) { 479 mnemonic = "ubfiz"; 480 form = form_bfiz; 481 } 482 break; 483 } 484 case BFM_w: 485 case BFM_x: { 486 mnemonic = "bfxil"; 487 form = form_bfx; 488 if (s < r) { 489 mnemonic = "bfi"; 490 form = form_bfiz; 491 } 492 } 493 } 494 Format(instr, mnemonic, form); 495 } 496 497 498 void DisassemblingDecoder::VisitExtract(Instruction* instr) { 499 const char *mnemonic = ""; 500 const char *form = "'Rd, 'Rn, 'Rm, 'IExtract"; 501 502 switch (instr->Mask(ExtractMask)) { 503 case EXTR_w: 504 case EXTR_x: { 505 if (instr->Rn() == instr->Rm()) { 506 mnemonic = "ror"; 507 form = "'Rd, 'Rn, 'IExtract"; 508 } else { 509 mnemonic = "extr"; 510 } 511 break; 512 } 513 default: UNREACHABLE(); 514 } 515 Format(instr, mnemonic, form); 516 } 517 518 519 void DisassemblingDecoder::VisitPCRelAddressing(Instruction* instr) { 520 switch (instr->Mask(PCRelAddressingMask)) { 521 case ADR: Format(instr, "adr", "'Xd, 'AddrPCRelByte"); break; 522 // ADRP is not implemented. 523 default: Format(instr, "unimplemented", "(PCRelAddressing)"); 524 } 525 } 526 527 528 void DisassemblingDecoder::VisitConditionalBranch(Instruction* instr) { 529 switch (instr->Mask(ConditionalBranchMask)) { 530 case B_cond: Format(instr, "b.'CBrn", "'BImmCond"); break; 531 default: UNREACHABLE(); 532 } 533 } 534 535 536 void DisassemblingDecoder::VisitUnconditionalBranchToRegister( 537 Instruction* instr) { 538 const char *mnemonic = "unimplemented"; 539 const char *form = "'Xn"; 540 541 switch (instr->Mask(UnconditionalBranchToRegisterMask)) { 542 case BR: mnemonic = "br"; break; 543 case BLR: mnemonic = "blr"; break; 544 case RET: { 545 mnemonic = "ret"; 546 if (instr->Rn() == kLinkRegCode) { 547 form = NULL; 548 } 549 break; 550 } 551 default: form = "(UnconditionalBranchToRegister)"; 552 } 553 Format(instr, mnemonic, form); 554 } 555 556 557 void DisassemblingDecoder::VisitUnconditionalBranch(Instruction* instr) { 558 const char *mnemonic = ""; 559 const char *form = "'BImmUncn"; 560 561 switch (instr->Mask(UnconditionalBranchMask)) { 562 case B: mnemonic = "b"; break; 563 case BL: mnemonic = "bl"; break; 564 default: UNREACHABLE(); 565 } 566 Format(instr, mnemonic, form); 567 } 568 569 570 void DisassemblingDecoder::VisitDataProcessing1Source(Instruction* instr) { 571 const char *mnemonic = ""; 572 const char *form = "'Rd, 'Rn"; 573 574 switch (instr->Mask(DataProcessing1SourceMask)) { 575 #define FORMAT(A, B) \ 576 case A##_w: \ 577 case A##_x: mnemonic = B; break; 578 FORMAT(RBIT, "rbit"); 579 FORMAT(REV16, "rev16"); 580 FORMAT(REV, "rev"); 581 FORMAT(CLZ, "clz"); 582 FORMAT(CLS, "cls"); 583 #undef FORMAT 584 case REV32_x: mnemonic = "rev32"; break; 585 default: UNREACHABLE(); 586 } 587 Format(instr, mnemonic, form); 588 } 589 590 591 void DisassemblingDecoder::VisitDataProcessing2Source(Instruction* instr) { 592 const char *mnemonic = "unimplemented"; 593 const char *form = "'Rd, 'Rn, 'Rm"; 594 595 switch (instr->Mask(DataProcessing2SourceMask)) { 596 #define FORMAT(A, B) \ 597 case A##_w: \ 598 case A##_x: mnemonic = B; break; 599 FORMAT(UDIV, "udiv"); 600 FORMAT(SDIV, "sdiv"); 601 FORMAT(LSLV, "lsl"); 602 FORMAT(LSRV, "lsr"); 603 FORMAT(ASRV, "asr"); 604 FORMAT(RORV, "ror"); 605 #undef FORMAT 606 default: form = "(DataProcessing2Source)"; 607 } 608 Format(instr, mnemonic, form); 609 } 610 611 612 void DisassemblingDecoder::VisitDataProcessing3Source(Instruction* instr) { 613 bool ra_is_zr = RaIsZROrSP(instr); 614 const char *mnemonic = ""; 615 const char *form = "'Xd, 'Wn, 'Wm, 'Xa"; 616 const char *form_rrr = "'Rd, 'Rn, 'Rm"; 617 const char *form_rrrr = "'Rd, 'Rn, 'Rm, 'Ra"; 618 const char *form_xww = "'Xd, 'Wn, 'Wm"; 619 const char *form_xxx = "'Xd, 'Xn, 'Xm"; 620 621 switch (instr->Mask(DataProcessing3SourceMask)) { 622 case MADD_w: 623 case MADD_x: { 624 mnemonic = "madd"; 625 form = form_rrrr; 626 if (ra_is_zr) { 627 mnemonic = "mul"; 628 form = form_rrr; 629 } 630 break; 631 } 632 case MSUB_w: 633 case MSUB_x: { 634 mnemonic = "msub"; 635 form = form_rrrr; 636 if (ra_is_zr) { 637 mnemonic = "mneg"; 638 form = form_rrr; 639 } 640 break; 641 } 642 case SMADDL_x: { 643 mnemonic = "smaddl"; 644 if (ra_is_zr) { 645 mnemonic = "smull"; 646 form = form_xww; 647 } 648 break; 649 } 650 case SMSUBL_x: { 651 mnemonic = "smsubl"; 652 if (ra_is_zr) { 653 mnemonic = "smnegl"; 654 form = form_xww; 655 } 656 break; 657 } 658 case UMADDL_x: { 659 mnemonic = "umaddl"; 660 if (ra_is_zr) { 661 mnemonic = "umull"; 662 form = form_xww; 663 } 664 break; 665 } 666 case UMSUBL_x: { 667 mnemonic = "umsubl"; 668 if (ra_is_zr) { 669 mnemonic = "umnegl"; 670 form = form_xww; 671 } 672 break; 673 } 674 case SMULH_x: { 675 mnemonic = "smulh"; 676 form = form_xxx; 677 break; 678 } 679 case UMULH_x: { 680 mnemonic = "umulh"; 681 form = form_xxx; 682 break; 683 } 684 default: UNREACHABLE(); 685 } 686 Format(instr, mnemonic, form); 687 } 688 689 690 void DisassemblingDecoder::VisitCompareBranch(Instruction* instr) { 691 const char *mnemonic = ""; 692 const char *form = "'Rt, 'BImmCmpa"; 693 694 switch (instr->Mask(CompareBranchMask)) { 695 case CBZ_w: 696 case CBZ_x: mnemonic = "cbz"; break; 697 case CBNZ_w: 698 case CBNZ_x: mnemonic = "cbnz"; break; 699 default: UNREACHABLE(); 700 } 701 Format(instr, mnemonic, form); 702 } 703 704 705 void DisassemblingDecoder::VisitTestBranch(Instruction* instr) { 706 const char *mnemonic = ""; 707 // If the top bit of the immediate is clear, the tested register is 708 // disassembled as Wt, otherwise Xt. As the top bit of the immediate is 709 // encoded in bit 31 of the instruction, we can reuse the Rt form, which 710 // uses bit 31 (normally "sf") to choose the register size. 711 const char *form = "'Rt, 'IS, 'BImmTest"; 712 713 switch (instr->Mask(TestBranchMask)) { 714 case TBZ: mnemonic = "tbz"; break; 715 case TBNZ: mnemonic = "tbnz"; break; 716 default: UNREACHABLE(); 717 } 718 Format(instr, mnemonic, form); 719 } 720 721 722 void DisassemblingDecoder::VisitMoveWideImmediate(Instruction* instr) { 723 const char *mnemonic = ""; 724 const char *form = "'Rd, 'IMoveImm"; 725 726 // Print the shift separately for movk, to make it clear which half word will 727 // be overwritten. Movn and movz print the computed immediate, which includes 728 // shift calculation. 729 switch (instr->Mask(MoveWideImmediateMask)) { 730 case MOVN_w: 731 case MOVN_x: mnemonic = "movn"; break; 732 case MOVZ_w: 733 case MOVZ_x: mnemonic = "movz"; break; 734 case MOVK_w: 735 case MOVK_x: mnemonic = "movk"; form = "'Rd, 'IMoveLSL"; break; 736 default: UNREACHABLE(); 737 } 738 Format(instr, mnemonic, form); 739 } 740 741 742 #define LOAD_STORE_LIST(V) \ 743 V(STRB_w, "strb", "'Wt") \ 744 V(STRH_w, "strh", "'Wt") \ 745 V(STR_w, "str", "'Wt") \ 746 V(STR_x, "str", "'Xt") \ 747 V(LDRB_w, "ldrb", "'Wt") \ 748 V(LDRH_w, "ldrh", "'Wt") \ 749 V(LDR_w, "ldr", "'Wt") \ 750 V(LDR_x, "ldr", "'Xt") \ 751 V(LDRSB_x, "ldrsb", "'Xt") \ 752 V(LDRSH_x, "ldrsh", "'Xt") \ 753 V(LDRSW_x, "ldrsw", "'Xt") \ 754 V(LDRSB_w, "ldrsb", "'Wt") \ 755 V(LDRSH_w, "ldrsh", "'Wt") \ 756 V(STR_s, "str", "'St") \ 757 V(STR_d, "str", "'Dt") \ 758 V(LDR_s, "ldr", "'St") \ 759 V(LDR_d, "ldr", "'Dt") 760 761 void DisassemblingDecoder::VisitLoadStorePreIndex(Instruction* instr) { 762 const char *mnemonic = "unimplemented"; 763 const char *form = "(LoadStorePreIndex)"; 764 765 switch (instr->Mask(LoadStorePreIndexMask)) { 766 #define LS_PREINDEX(A, B, C) \ 767 case A##_pre: mnemonic = B; form = C ", ['Xns'ILS]!"; break; 768 LOAD_STORE_LIST(LS_PREINDEX) 769 #undef LS_PREINDEX 770 } 771 Format(instr, mnemonic, form); 772 } 773 774 775 void DisassemblingDecoder::VisitLoadStorePostIndex(Instruction* instr) { 776 const char *mnemonic = "unimplemented"; 777 const char *form = "(LoadStorePostIndex)"; 778 779 switch (instr->Mask(LoadStorePostIndexMask)) { 780 #define LS_POSTINDEX(A, B, C) \ 781 case A##_post: mnemonic = B; form = C ", ['Xns]'ILS"; break; 782 LOAD_STORE_LIST(LS_POSTINDEX) 783 #undef LS_POSTINDEX 784 } 785 Format(instr, mnemonic, form); 786 } 787 788 789 void DisassemblingDecoder::VisitLoadStoreUnsignedOffset(Instruction* instr) { 790 const char *mnemonic = "unimplemented"; 791 const char *form = "(LoadStoreUnsignedOffset)"; 792 793 switch (instr->Mask(LoadStoreUnsignedOffsetMask)) { 794 #define LS_UNSIGNEDOFFSET(A, B, C) \ 795 case A##_unsigned: mnemonic = B; form = C ", ['Xns'ILU]"; break; 796 LOAD_STORE_LIST(LS_UNSIGNEDOFFSET) 797 #undef LS_UNSIGNEDOFFSET 798 case PRFM_unsigned: mnemonic = "prfm"; form = "'PrefOp, ['Xn'ILU]"; 799 } 800 Format(instr, mnemonic, form); 801 } 802 803 804 void DisassemblingDecoder::VisitLoadStoreRegisterOffset(Instruction* instr) { 805 const char *mnemonic = "unimplemented"; 806 const char *form = "(LoadStoreRegisterOffset)"; 807 808 switch (instr->Mask(LoadStoreRegisterOffsetMask)) { 809 #define LS_REGISTEROFFSET(A, B, C) \ 810 case A##_reg: mnemonic = B; form = C ", ['Xns, 'Offsetreg]"; break; 811 LOAD_STORE_LIST(LS_REGISTEROFFSET) 812 #undef LS_REGISTEROFFSET 813 case PRFM_reg: mnemonic = "prfm"; form = "'PrefOp, ['Xns, 'Offsetreg]"; 814 } 815 Format(instr, mnemonic, form); 816 } 817 818 819 void DisassemblingDecoder::VisitLoadStoreUnscaledOffset(Instruction* instr) { 820 const char *mnemonic = "unimplemented"; 821 const char *form = "'Wt, ['Xns'ILS]"; 822 const char *form_x = "'Xt, ['Xns'ILS]"; 823 const char *form_s = "'St, ['Xns'ILS]"; 824 const char *form_d = "'Dt, ['Xns'ILS]"; 825 826 switch (instr->Mask(LoadStoreUnscaledOffsetMask)) { 827 case STURB_w: mnemonic = "sturb"; break; 828 case STURH_w: mnemonic = "sturh"; break; 829 case STUR_w: mnemonic = "stur"; break; 830 case STUR_x: mnemonic = "stur"; form = form_x; break; 831 case STUR_s: mnemonic = "stur"; form = form_s; break; 832 case STUR_d: mnemonic = "stur"; form = form_d; break; 833 case LDURB_w: mnemonic = "ldurb"; break; 834 case LDURH_w: mnemonic = "ldurh"; break; 835 case LDUR_w: mnemonic = "ldur"; break; 836 case LDUR_x: mnemonic = "ldur"; form = form_x; break; 837 case LDUR_s: mnemonic = "ldur"; form = form_s; break; 838 case LDUR_d: mnemonic = "ldur"; form = form_d; break; 839 case LDURSB_x: form = form_x; // Fall through. 840 case LDURSB_w: mnemonic = "ldursb"; break; 841 case LDURSH_x: form = form_x; // Fall through. 842 case LDURSH_w: mnemonic = "ldursh"; break; 843 case LDURSW_x: mnemonic = "ldursw"; form = form_x; break; 844 default: form = "(LoadStoreUnscaledOffset)"; 845 } 846 Format(instr, mnemonic, form); 847 } 848 849 850 void DisassemblingDecoder::VisitLoadLiteral(Instruction* instr) { 851 const char *mnemonic = "ldr"; 852 const char *form = "(LoadLiteral)"; 853 854 switch (instr->Mask(LoadLiteralMask)) { 855 case LDR_w_lit: form = "'Wt, 'ILLiteral 'LValue"; break; 856 case LDR_x_lit: form = "'Xt, 'ILLiteral 'LValue"; break; 857 case LDR_s_lit: form = "'St, 'ILLiteral 'LValue"; break; 858 case LDR_d_lit: form = "'Dt, 'ILLiteral 'LValue"; break; 859 default: mnemonic = "unimplemented"; 860 } 861 Format(instr, mnemonic, form); 862 } 863 864 865 #define LOAD_STORE_PAIR_LIST(V) \ 866 V(STP_w, "stp", "'Wt, 'Wt2", "4") \ 867 V(LDP_w, "ldp", "'Wt, 'Wt2", "4") \ 868 V(LDPSW_x, "ldpsw", "'Xt, 'Xt2", "4") \ 869 V(STP_x, "stp", "'Xt, 'Xt2", "8") \ 870 V(LDP_x, "ldp", "'Xt, 'Xt2", "8") \ 871 V(STP_s, "stp", "'St, 'St2", "4") \ 872 V(LDP_s, "ldp", "'St, 'St2", "4") \ 873 V(STP_d, "stp", "'Dt, 'Dt2", "8") \ 874 V(LDP_d, "ldp", "'Dt, 'Dt2", "8") 875 876 void DisassemblingDecoder::VisitLoadStorePairPostIndex(Instruction* instr) { 877 const char *mnemonic = "unimplemented"; 878 const char *form = "(LoadStorePairPostIndex)"; 879 880 switch (instr->Mask(LoadStorePairPostIndexMask)) { 881 #define LSP_POSTINDEX(A, B, C, D) \ 882 case A##_post: mnemonic = B; form = C ", ['Xns]'ILP" D; break; 883 LOAD_STORE_PAIR_LIST(LSP_POSTINDEX) 884 #undef LSP_POSTINDEX 885 } 886 Format(instr, mnemonic, form); 887 } 888 889 890 void DisassemblingDecoder::VisitLoadStorePairPreIndex(Instruction* instr) { 891 const char *mnemonic = "unimplemented"; 892 const char *form = "(LoadStorePairPreIndex)"; 893 894 switch (instr->Mask(LoadStorePairPreIndexMask)) { 895 #define LSP_PREINDEX(A, B, C, D) \ 896 case A##_pre: mnemonic = B; form = C ", ['Xns'ILP" D "]!"; break; 897 LOAD_STORE_PAIR_LIST(LSP_PREINDEX) 898 #undef LSP_PREINDEX 899 } 900 Format(instr, mnemonic, form); 901 } 902 903 904 void DisassemblingDecoder::VisitLoadStorePairOffset(Instruction* instr) { 905 const char *mnemonic = "unimplemented"; 906 const char *form = "(LoadStorePairOffset)"; 907 908 switch (instr->Mask(LoadStorePairOffsetMask)) { 909 #define LSP_OFFSET(A, B, C, D) \ 910 case A##_off: mnemonic = B; form = C ", ['Xns'ILP" D "]"; break; 911 LOAD_STORE_PAIR_LIST(LSP_OFFSET) 912 #undef LSP_OFFSET 913 } 914 Format(instr, mnemonic, form); 915 } 916 917 void DisassemblingDecoder::VisitLoadStoreAcquireRelease(Instruction *instr) { 918 const char *mnemonic = "unimplemented"; 919 const char *form = "'Wt, ['Xn]"; 920 const char *form_x = "'Xt, ['Xn]"; 921 const char *form_stlx = "'Ws, 'Wt, ['Xn]"; 922 const char *form_stlx_x = "'Ws, 'Xt, ['Xn]"; 923 924 switch (instr->Mask(LoadStoreAcquireReleaseMask)) { 925 case LDAXR_b: mnemonic = "ldaxrb"; break; 926 case STLR_b: mnemonic = "stlrb"; break; 927 case LDAR_b: mnemonic = "ldarb"; break; 928 case LDAXR_h: mnemonic = "ldaxrh"; break; 929 case STLR_h: mnemonic = "stlrh"; break; 930 case LDAR_h: mnemonic = "ldarh"; break; 931 case LDAXR_w: mnemonic = "ldaxr"; break; 932 case STLR_w: mnemonic = "stlr"; break; 933 case LDAR_w: mnemonic = "ldar"; break; 934 case LDAXR_x: mnemonic = "ldaxr"; form = form_x; break; 935 case STLR_x: mnemonic = "stlr"; form = form_x; break; 936 case LDAR_x: mnemonic = "ldar"; form = form_x; break; 937 case STLXR_h: mnemonic = "stlxrh"; form = form_stlx; break; 938 case STLXR_b: mnemonic = "stlxrb"; form = form_stlx; break; 939 case STLXR_w: mnemonic = "stlxr"; form = form_stlx; break; 940 case STLXR_x: mnemonic = "stlxr"; form = form_stlx_x; break; 941 default: form = "(LoadStoreAcquireReleaseMask)"; 942 } 943 Format(instr, mnemonic, form); 944 } 945 946 void DisassemblingDecoder::VisitFPCompare(Instruction* instr) { 947 const char *mnemonic = "unimplemented"; 948 const char *form = "'Fn, 'Fm"; 949 const char *form_zero = "'Fn, #0.0"; 950 951 switch (instr->Mask(FPCompareMask)) { 952 case FCMP_s_zero: 953 case FCMP_d_zero: form = form_zero; // Fall through. 954 case FCMP_s: 955 case FCMP_d: mnemonic = "fcmp"; break; 956 default: form = "(FPCompare)"; 957 } 958 Format(instr, mnemonic, form); 959 } 960 961 962 void DisassemblingDecoder::VisitFPConditionalCompare(Instruction* instr) { 963 const char *mnemonic = "unimplemented"; 964 const char *form = "'Fn, 'Fm, 'INzcv, 'Cond"; 965 966 switch (instr->Mask(FPConditionalCompareMask)) { 967 case FCCMP_s: 968 case FCCMP_d: mnemonic = "fccmp"; break; 969 case FCCMPE_s: 970 case FCCMPE_d: mnemonic = "fccmpe"; break; 971 default: form = "(FPConditionalCompare)"; 972 } 973 Format(instr, mnemonic, form); 974 } 975 976 977 void DisassemblingDecoder::VisitFPConditionalSelect(Instruction* instr) { 978 const char *mnemonic = ""; 979 const char *form = "'Fd, 'Fn, 'Fm, 'Cond"; 980 981 switch (instr->Mask(FPConditionalSelectMask)) { 982 case FCSEL_s: 983 case FCSEL_d: mnemonic = "fcsel"; break; 984 default: UNREACHABLE(); 985 } 986 Format(instr, mnemonic, form); 987 } 988 989 990 void DisassemblingDecoder::VisitFPDataProcessing1Source(Instruction* instr) { 991 const char *mnemonic = "unimplemented"; 992 const char *form = "'Fd, 'Fn"; 993 994 switch (instr->Mask(FPDataProcessing1SourceMask)) { 995 #define FORMAT(A, B) \ 996 case A##_s: \ 997 case A##_d: mnemonic = B; break; 998 FORMAT(FMOV, "fmov"); 999 FORMAT(FABS, "fabs"); 1000 FORMAT(FNEG, "fneg"); 1001 FORMAT(FSQRT, "fsqrt"); 1002 FORMAT(FRINTN, "frintn"); 1003 FORMAT(FRINTP, "frintp"); 1004 FORMAT(FRINTM, "frintm"); 1005 FORMAT(FRINTZ, "frintz"); 1006 FORMAT(FRINTA, "frinta"); 1007 FORMAT(FRINTX, "frintx"); 1008 FORMAT(FRINTI, "frinti"); 1009 #undef FORMAT 1010 case FCVT_ds: mnemonic = "fcvt"; form = "'Dd, 'Sn"; break; 1011 case FCVT_sd: mnemonic = "fcvt"; form = "'Sd, 'Dn"; break; 1012 default: form = "(FPDataProcessing1Source)"; 1013 } 1014 Format(instr, mnemonic, form); 1015 } 1016 1017 1018 void DisassemblingDecoder::VisitFPDataProcessing2Source(Instruction* instr) { 1019 const char *mnemonic = ""; 1020 const char *form = "'Fd, 'Fn, 'Fm"; 1021 1022 switch (instr->Mask(FPDataProcessing2SourceMask)) { 1023 #define FORMAT(A, B) \ 1024 case A##_s: \ 1025 case A##_d: mnemonic = B; break; 1026 FORMAT(FMUL, "fmul"); 1027 FORMAT(FDIV, "fdiv"); 1028 FORMAT(FADD, "fadd"); 1029 FORMAT(FSUB, "fsub"); 1030 FORMAT(FMAX, "fmax"); 1031 FORMAT(FMIN, "fmin"); 1032 FORMAT(FMAXNM, "fmaxnm"); 1033 FORMAT(FMINNM, "fminnm"); 1034 FORMAT(FNMUL, "fnmul"); 1035 #undef FORMAT 1036 default: UNREACHABLE(); 1037 } 1038 Format(instr, mnemonic, form); 1039 } 1040 1041 1042 void DisassemblingDecoder::VisitFPDataProcessing3Source(Instruction* instr) { 1043 const char *mnemonic = ""; 1044 const char *form = "'Fd, 'Fn, 'Fm, 'Fa"; 1045 1046 switch (instr->Mask(FPDataProcessing3SourceMask)) { 1047 #define FORMAT(A, B) \ 1048 case A##_s: \ 1049 case A##_d: mnemonic = B; break; 1050 FORMAT(FMADD, "fmadd"); 1051 FORMAT(FMSUB, "fmsub"); 1052 FORMAT(FNMADD, "fnmadd"); 1053 FORMAT(FNMSUB, "fnmsub"); 1054 #undef FORMAT 1055 default: UNREACHABLE(); 1056 } 1057 Format(instr, mnemonic, form); 1058 } 1059 1060 1061 void DisassemblingDecoder::VisitFPImmediate(Instruction* instr) { 1062 const char *mnemonic = ""; 1063 const char *form = "(FPImmediate)"; 1064 1065 switch (instr->Mask(FPImmediateMask)) { 1066 case FMOV_s_imm: mnemonic = "fmov"; form = "'Sd, 'IFPSingle"; break; 1067 case FMOV_d_imm: mnemonic = "fmov"; form = "'Dd, 'IFPDouble"; break; 1068 default: UNREACHABLE(); 1069 } 1070 Format(instr, mnemonic, form); 1071 } 1072 1073 1074 void DisassemblingDecoder::VisitFPIntegerConvert(Instruction* instr) { 1075 const char *mnemonic = "unimplemented"; 1076 const char *form = "(FPIntegerConvert)"; 1077 const char *form_rf = "'Rd, 'Fn"; 1078 const char *form_fr = "'Fd, 'Rn"; 1079 1080 switch (instr->Mask(FPIntegerConvertMask)) { 1081 case FMOV_ws: 1082 case FMOV_xd: mnemonic = "fmov"; form = form_rf; break; 1083 case FMOV_sw: 1084 case FMOV_dx: mnemonic = "fmov"; form = form_fr; break; 1085 case FCVTAS_ws: 1086 case FCVTAS_xs: 1087 case FCVTAS_wd: 1088 case FCVTAS_xd: mnemonic = "fcvtas"; form = form_rf; break; 1089 case FCVTAU_ws: 1090 case FCVTAU_xs: 1091 case FCVTAU_wd: 1092 case FCVTAU_xd: mnemonic = "fcvtau"; form = form_rf; break; 1093 case FCVTMS_ws: 1094 case FCVTMS_xs: 1095 case FCVTMS_wd: 1096 case FCVTMS_xd: mnemonic = "fcvtms"; form = form_rf; break; 1097 case FCVTMU_ws: 1098 case FCVTMU_xs: 1099 case FCVTMU_wd: 1100 case FCVTMU_xd: mnemonic = "fcvtmu"; form = form_rf; break; 1101 case FCVTNS_ws: 1102 case FCVTNS_xs: 1103 case FCVTNS_wd: 1104 case FCVTNS_xd: mnemonic = "fcvtns"; form = form_rf; break; 1105 case FCVTNU_ws: 1106 case FCVTNU_xs: 1107 case FCVTNU_wd: 1108 case FCVTNU_xd: mnemonic = "fcvtnu"; form = form_rf; break; 1109 case FCVTZU_xd: 1110 case FCVTZU_ws: 1111 case FCVTZU_wd: 1112 case FCVTZU_xs: mnemonic = "fcvtzu"; form = form_rf; break; 1113 case FCVTZS_xd: 1114 case FCVTZS_wd: 1115 case FCVTZS_xs: 1116 case FCVTZS_ws: mnemonic = "fcvtzs"; form = form_rf; break; 1117 case SCVTF_sw: 1118 case SCVTF_sx: 1119 case SCVTF_dw: 1120 case SCVTF_dx: mnemonic = "scvtf"; form = form_fr; break; 1121 case UCVTF_sw: 1122 case UCVTF_sx: 1123 case UCVTF_dw: 1124 case UCVTF_dx: mnemonic = "ucvtf"; form = form_fr; break; 1125 } 1126 Format(instr, mnemonic, form); 1127 } 1128 1129 1130 void DisassemblingDecoder::VisitFPFixedPointConvert(Instruction* instr) { 1131 const char *mnemonic = ""; 1132 const char *form = "'Rd, 'Fn, 'IFPFBits"; 1133 const char *form_fr = "'Fd, 'Rn, 'IFPFBits"; 1134 1135 switch (instr->Mask(FPFixedPointConvertMask)) { 1136 case FCVTZS_ws_fixed: 1137 case FCVTZS_xs_fixed: 1138 case FCVTZS_wd_fixed: 1139 case FCVTZS_xd_fixed: mnemonic = "fcvtzs"; break; 1140 case FCVTZU_ws_fixed: 1141 case FCVTZU_xs_fixed: 1142 case FCVTZU_wd_fixed: 1143 case FCVTZU_xd_fixed: mnemonic = "fcvtzu"; break; 1144 case SCVTF_sw_fixed: 1145 case SCVTF_sx_fixed: 1146 case SCVTF_dw_fixed: 1147 case SCVTF_dx_fixed: mnemonic = "scvtf"; form = form_fr; break; 1148 case UCVTF_sw_fixed: 1149 case UCVTF_sx_fixed: 1150 case UCVTF_dw_fixed: 1151 case UCVTF_dx_fixed: mnemonic = "ucvtf"; form = form_fr; break; 1152 } 1153 Format(instr, mnemonic, form); 1154 } 1155 1156 1157 void DisassemblingDecoder::VisitSystem(Instruction* instr) { 1158 // Some system instructions hijack their Op and Cp fields to represent a 1159 // range of immediates instead of indicating a different instruction. This 1160 // makes the decoding tricky. 1161 const char *mnemonic = "unimplemented"; 1162 const char *form = "(System)"; 1163 1164 if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) { 1165 switch (instr->Mask(SystemSysRegMask)) { 1166 case MRS: { 1167 mnemonic = "mrs"; 1168 switch (instr->ImmSystemRegister()) { 1169 case NZCV: form = "'Xt, nzcv"; break; 1170 case FPCR: form = "'Xt, fpcr"; break; 1171 default: form = "'Xt, (unknown)"; break; 1172 } 1173 break; 1174 } 1175 case MSR: { 1176 mnemonic = "msr"; 1177 switch (instr->ImmSystemRegister()) { 1178 case NZCV: form = "nzcv, 'Xt"; break; 1179 case FPCR: form = "fpcr, 'Xt"; break; 1180 default: form = "(unknown), 'Xt"; break; 1181 } 1182 break; 1183 } 1184 } 1185 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) { 1186 DCHECK(instr->Mask(SystemHintMask) == HINT); 1187 switch (instr->ImmHint()) { 1188 case NOP: { 1189 mnemonic = "nop"; 1190 form = NULL; 1191 break; 1192 } 1193 } 1194 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) { 1195 switch (instr->Mask(MemBarrierMask)) { 1196 case DMB: { 1197 mnemonic = "dmb"; 1198 form = "'M"; 1199 break; 1200 } 1201 case DSB: { 1202 mnemonic = "dsb"; 1203 form = "'M"; 1204 break; 1205 } 1206 case ISB: { 1207 mnemonic = "isb"; 1208 form = NULL; 1209 break; 1210 } 1211 } 1212 } 1213 1214 Format(instr, mnemonic, form); 1215 } 1216 1217 1218 void DisassemblingDecoder::VisitException(Instruction* instr) { 1219 const char *mnemonic = "unimplemented"; 1220 const char *form = "'IDebug"; 1221 1222 switch (instr->Mask(ExceptionMask)) { 1223 case HLT: mnemonic = "hlt"; break; 1224 case BRK: mnemonic = "brk"; break; 1225 case SVC: mnemonic = "svc"; break; 1226 case HVC: mnemonic = "hvc"; break; 1227 case SMC: mnemonic = "smc"; break; 1228 case DCPS1: mnemonic = "dcps1"; form = "{'IDebug}"; break; 1229 case DCPS2: mnemonic = "dcps2"; form = "{'IDebug}"; break; 1230 case DCPS3: mnemonic = "dcps3"; form = "{'IDebug}"; break; 1231 default: form = "(Exception)"; 1232 } 1233 Format(instr, mnemonic, form); 1234 } 1235 1236 1237 void DisassemblingDecoder::VisitUnimplemented(Instruction* instr) { 1238 Format(instr, "unimplemented", "(Unimplemented)"); 1239 } 1240 1241 1242 void DisassemblingDecoder::VisitUnallocated(Instruction* instr) { 1243 Format(instr, "unallocated", "(Unallocated)"); 1244 } 1245 1246 1247 void DisassemblingDecoder::ProcessOutput(Instruction* /*instr*/) { 1248 // The base disasm does nothing more than disassembling into a buffer. 1249 } 1250 1251 1252 void DisassemblingDecoder::Format(Instruction* instr, const char* mnemonic, 1253 const char* format) { 1254 // TODO(mcapewel) don't think I can use the instr address here - there needs 1255 // to be a base address too 1256 DCHECK(mnemonic != NULL); 1257 ResetOutput(); 1258 Substitute(instr, mnemonic); 1259 if (format != NULL) { 1260 buffer_[buffer_pos_++] = ' '; 1261 Substitute(instr, format); 1262 } 1263 buffer_[buffer_pos_] = 0; 1264 ProcessOutput(instr); 1265 } 1266 1267 1268 void DisassemblingDecoder::Substitute(Instruction* instr, const char* string) { 1269 char chr = *string++; 1270 while (chr != '\0') { 1271 if (chr == '\'') { 1272 string += SubstituteField(instr, string); 1273 } else { 1274 buffer_[buffer_pos_++] = chr; 1275 } 1276 chr = *string++; 1277 } 1278 } 1279 1280 1281 int DisassemblingDecoder::SubstituteField(Instruction* instr, 1282 const char* format) { 1283 switch (format[0]) { 1284 case 'R': // Register. X or W, selected by sf bit. 1285 case 'F': // FP Register. S or D, selected by type field. 1286 case 'W': 1287 case 'X': 1288 case 'S': 1289 case 'D': return SubstituteRegisterField(instr, format); 1290 case 'I': return SubstituteImmediateField(instr, format); 1291 case 'L': return SubstituteLiteralField(instr, format); 1292 case 'H': return SubstituteShiftField(instr, format); 1293 case 'P': return SubstitutePrefetchField(instr, format); 1294 case 'C': return SubstituteConditionField(instr, format); 1295 case 'E': return SubstituteExtendField(instr, format); 1296 case 'A': return SubstitutePCRelAddressField(instr, format); 1297 case 'B': return SubstituteBranchTargetField(instr, format); 1298 case 'O': return SubstituteLSRegOffsetField(instr, format); 1299 case 'M': return SubstituteBarrierField(instr, format); 1300 default: { 1301 UNREACHABLE(); 1302 return 1; 1303 } 1304 } 1305 } 1306 1307 1308 int DisassemblingDecoder::SubstituteRegisterField(Instruction* instr, 1309 const char* format) { 1310 unsigned reg_num = 0; 1311 unsigned field_len = 2; 1312 switch (format[1]) { 1313 case 'd': reg_num = instr->Rd(); break; 1314 case 'n': reg_num = instr->Rn(); break; 1315 case 'm': reg_num = instr->Rm(); break; 1316 case 'a': reg_num = instr->Ra(); break; 1317 case 't': { 1318 if (format[2] == '2') { 1319 reg_num = instr->Rt2(); 1320 field_len = 3; 1321 } else { 1322 reg_num = instr->Rt(); 1323 } 1324 break; 1325 } 1326 case 's': 1327 reg_num = instr->Rs(); 1328 break; 1329 default: UNREACHABLE(); 1330 } 1331 1332 // Increase field length for registers tagged as stack. 1333 if (format[2] == 's') { 1334 field_len = 3; 1335 } 1336 1337 char reg_type; 1338 if (format[0] == 'R') { 1339 // Register type is R: use sf bit to choose X and W. 1340 reg_type = instr->SixtyFourBits() ? 'x' : 'w'; 1341 } else if (format[0] == 'F') { 1342 // Floating-point register: use type field to choose S or D. 1343 reg_type = ((instr->FPType() & 1) == 0) ? 's' : 'd'; 1344 } else { 1345 // Register type is specified. Make it lower case. 1346 reg_type = format[0] + 0x20; 1347 } 1348 1349 if ((reg_num != kZeroRegCode) || (reg_type == 's') || (reg_type == 'd')) { 1350 // A normal register: w0 - w30, x0 - x30, s0 - s31, d0 - d31. 1351 1352 // Filter special registers 1353 if ((reg_type == 'x') && (reg_num == 27)) { 1354 AppendToOutput("cp"); 1355 } else if ((reg_type == 'x') && (reg_num == 28)) { 1356 AppendToOutput("jssp"); 1357 } else if ((reg_type == 'x') && (reg_num == 29)) { 1358 AppendToOutput("fp"); 1359 } else if ((reg_type == 'x') && (reg_num == 30)) { 1360 AppendToOutput("lr"); 1361 } else { 1362 AppendToOutput("%c%d", reg_type, reg_num); 1363 } 1364 } else if (format[2] == 's') { 1365 // Disassemble w31/x31 as stack pointer wcsp/csp. 1366 AppendToOutput("%s", (reg_type == 'w') ? "wcsp" : "csp"); 1367 } else { 1368 // Disassemble w31/x31 as zero register wzr/xzr. 1369 AppendToOutput("%czr", reg_type); 1370 } 1371 1372 return field_len; 1373 } 1374 1375 1376 int DisassemblingDecoder::SubstituteImmediateField(Instruction* instr, 1377 const char* format) { 1378 DCHECK(format[0] == 'I'); 1379 1380 switch (format[1]) { 1381 case 'M': { // IMoveImm or IMoveLSL. 1382 if (format[5] == 'I') { 1383 uint64_t imm = static_cast<uint64_t>(instr->ImmMoveWide()) 1384 << (16 * instr->ShiftMoveWide()); 1385 AppendToOutput("#0x%" PRIx64, imm); 1386 } else { 1387 DCHECK(format[5] == 'L'); 1388 AppendToOutput("#0x%" PRIx32, instr->ImmMoveWide()); 1389 if (instr->ShiftMoveWide() > 0) { 1390 AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide()); 1391 } 1392 } 1393 return 8; 1394 } 1395 case 'L': { 1396 switch (format[2]) { 1397 case 'L': { // ILLiteral - Immediate Load Literal. 1398 AppendToOutput("pc%+" PRId32, instr->ImmLLiteral() 1399 << kLoadLiteralScaleLog2); 1400 return 9; 1401 } 1402 case 'S': { // ILS - Immediate Load/Store. 1403 if (instr->ImmLS() != 0) { 1404 AppendToOutput(", #%" PRId32, instr->ImmLS()); 1405 } 1406 return 3; 1407 } 1408 case 'P': { // ILPx - Immediate Load/Store Pair, x = access size. 1409 if (instr->ImmLSPair() != 0) { 1410 // format[3] is the scale value. Convert to a number. 1411 int scale = format[3] - 0x30; 1412 AppendToOutput(", #%" PRId32, instr->ImmLSPair() * scale); 1413 } 1414 return 4; 1415 } 1416 case 'U': { // ILU - Immediate Load/Store Unsigned. 1417 if (instr->ImmLSUnsigned() != 0) { 1418 AppendToOutput(", #%" PRId32, instr->ImmLSUnsigned() 1419 << instr->SizeLS()); 1420 } 1421 return 3; 1422 } 1423 } 1424 } 1425 case 'C': { // ICondB - Immediate Conditional Branch. 1426 int64_t offset = instr->ImmCondBranch() << 2; 1427 char sign = (offset >= 0) ? '+' : '-'; 1428 AppendToOutput("#%c0x%" PRIx64, sign, offset); 1429 return 6; 1430 } 1431 case 'A': { // IAddSub. 1432 DCHECK(instr->ShiftAddSub() <= 1); 1433 int64_t imm = instr->ImmAddSub() << (12 * instr->ShiftAddSub()); 1434 AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm); 1435 return 7; 1436 } 1437 case 'F': { // IFPSingle, IFPDouble or IFPFBits. 1438 if (format[3] == 'F') { // IFPFBits. 1439 AppendToOutput("#%d", 64 - instr->FPScale()); 1440 return 8; 1441 } else { 1442 AppendToOutput("#0x%" PRIx32 " (%.4f)", instr->ImmFP(), 1443 format[3] == 'S' ? instr->ImmFP32() : instr->ImmFP64()); 1444 return 9; 1445 } 1446 } 1447 case 'T': { // ITri - Immediate Triangular Encoded. 1448 AppendToOutput("#0x%" PRIx64, instr->ImmLogical()); 1449 return 4; 1450 } 1451 case 'N': { // INzcv. 1452 int nzcv = (instr->Nzcv() << Flags_offset); 1453 AppendToOutput("#%c%c%c%c", ((nzcv & NFlag) == 0) ? 'n' : 'N', 1454 ((nzcv & ZFlag) == 0) ? 'z' : 'Z', 1455 ((nzcv & CFlag) == 0) ? 'c' : 'C', 1456 ((nzcv & VFlag) == 0) ? 'v' : 'V'); 1457 return 5; 1458 } 1459 case 'P': { // IP - Conditional compare. 1460 AppendToOutput("#%d", instr->ImmCondCmp()); 1461 return 2; 1462 } 1463 case 'B': { // Bitfields. 1464 return SubstituteBitfieldImmediateField(instr, format); 1465 } 1466 case 'E': { // IExtract. 1467 AppendToOutput("#%d", instr->ImmS()); 1468 return 8; 1469 } 1470 case 'S': { // IS - Test and branch bit. 1471 AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) | 1472 instr->ImmTestBranchBit40()); 1473 return 2; 1474 } 1475 case 'D': { // IDebug - HLT and BRK instructions. 1476 AppendToOutput("#0x%x", instr->ImmException()); 1477 return 6; 1478 } 1479 default: { 1480 UNREACHABLE(); 1481 return 0; 1482 } 1483 } 1484 } 1485 1486 1487 int DisassemblingDecoder::SubstituteBitfieldImmediateField(Instruction* instr, 1488 const char* format) { 1489 DCHECK((format[0] == 'I') && (format[1] == 'B')); 1490 unsigned r = instr->ImmR(); 1491 unsigned s = instr->ImmS(); 1492 1493 switch (format[2]) { 1494 case 'r': { // IBr. 1495 AppendToOutput("#%d", r); 1496 return 3; 1497 } 1498 case 's': { // IBs+1 or IBs-r+1. 1499 if (format[3] == '+') { 1500 AppendToOutput("#%d", s + 1); 1501 return 5; 1502 } else { 1503 DCHECK(format[3] == '-'); 1504 AppendToOutput("#%d", s - r + 1); 1505 return 7; 1506 } 1507 } 1508 case 'Z': { // IBZ-r. 1509 DCHECK((format[3] == '-') && (format[4] == 'r')); 1510 unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSizeInBits 1511 : kWRegSizeInBits; 1512 AppendToOutput("#%d", reg_size - r); 1513 return 5; 1514 } 1515 default: { 1516 UNREACHABLE(); 1517 return 0; 1518 } 1519 } 1520 } 1521 1522 1523 int DisassemblingDecoder::SubstituteLiteralField(Instruction* instr, 1524 const char* format) { 1525 DCHECK(strncmp(format, "LValue", 6) == 0); 1526 USE(format); 1527 1528 switch (instr->Mask(LoadLiteralMask)) { 1529 case LDR_w_lit: 1530 case LDR_x_lit: 1531 case LDR_s_lit: 1532 case LDR_d_lit: 1533 AppendToOutput("(addr 0x%016" PRIxPTR ")", instr->LiteralAddress()); 1534 break; 1535 default: UNREACHABLE(); 1536 } 1537 1538 return 6; 1539 } 1540 1541 1542 int DisassemblingDecoder::SubstituteShiftField(Instruction* instr, 1543 const char* format) { 1544 DCHECK(format[0] == 'H'); 1545 DCHECK(instr->ShiftDP() <= 0x3); 1546 1547 switch (format[1]) { 1548 case 'D': { // HDP. 1549 DCHECK(instr->ShiftDP() != ROR); 1550 } // Fall through. 1551 case 'L': { // HLo. 1552 if (instr->ImmDPShift() != 0) { 1553 const char* shift_type[] = {"lsl", "lsr", "asr", "ror"}; 1554 AppendToOutput(", %s #%" PRId32, shift_type[instr->ShiftDP()], 1555 instr->ImmDPShift()); 1556 } 1557 return 3; 1558 } 1559 default: 1560 UNREACHABLE(); 1561 return 0; 1562 } 1563 } 1564 1565 1566 int DisassemblingDecoder::SubstituteConditionField(Instruction* instr, 1567 const char* format) { 1568 DCHECK(format[0] == 'C'); 1569 const char* condition_code[] = { "eq", "ne", "hs", "lo", 1570 "mi", "pl", "vs", "vc", 1571 "hi", "ls", "ge", "lt", 1572 "gt", "le", "al", "nv" }; 1573 int cond; 1574 switch (format[1]) { 1575 case 'B': cond = instr->ConditionBranch(); break; 1576 case 'I': { 1577 cond = NegateCondition(static_cast<Condition>(instr->Condition())); 1578 break; 1579 } 1580 default: cond = instr->Condition(); 1581 } 1582 AppendToOutput("%s", condition_code[cond]); 1583 return 4; 1584 } 1585 1586 1587 int DisassemblingDecoder::SubstitutePCRelAddressField(Instruction* instr, 1588 const char* format) { 1589 USE(format); 1590 DCHECK(strncmp(format, "AddrPCRel", 9) == 0); 1591 1592 int offset = instr->ImmPCRel(); 1593 1594 // Only ADR (AddrPCRelByte) is supported. 1595 DCHECK(strcmp(format, "AddrPCRelByte") == 0); 1596 1597 char sign = '+'; 1598 if (offset < 0) { 1599 offset = -offset; 1600 sign = '-'; 1601 } 1602 AppendToOutput("#%c0x%x (addr %p)", sign, offset, 1603 instr->InstructionAtOffset(offset, Instruction::NO_CHECK)); 1604 return 13; 1605 } 1606 1607 1608 int DisassemblingDecoder::SubstituteBranchTargetField(Instruction* instr, 1609 const char* format) { 1610 DCHECK(strncmp(format, "BImm", 4) == 0); 1611 1612 int64_t offset = 0; 1613 switch (format[5]) { 1614 // BImmUncn - unconditional branch immediate. 1615 case 'n': offset = instr->ImmUncondBranch(); break; 1616 // BImmCond - conditional branch immediate. 1617 case 'o': offset = instr->ImmCondBranch(); break; 1618 // BImmCmpa - compare and branch immediate. 1619 case 'm': offset = instr->ImmCmpBranch(); break; 1620 // BImmTest - test and branch immediate. 1621 case 'e': offset = instr->ImmTestBranch(); break; 1622 default: UNREACHABLE(); 1623 } 1624 offset <<= kInstructionSizeLog2; 1625 char sign = '+'; 1626 if (offset < 0) { 1627 sign = '-'; 1628 } 1629 AppendToOutput("#%c0x%" PRIx64 " (addr %p)", sign, Abs(offset), 1630 instr->InstructionAtOffset(offset), Instruction::NO_CHECK); 1631 return 8; 1632 } 1633 1634 1635 int DisassemblingDecoder::SubstituteExtendField(Instruction* instr, 1636 const char* format) { 1637 DCHECK(strncmp(format, "Ext", 3) == 0); 1638 DCHECK(instr->ExtendMode() <= 7); 1639 USE(format); 1640 1641 const char* extend_mode[] = { "uxtb", "uxth", "uxtw", "uxtx", 1642 "sxtb", "sxth", "sxtw", "sxtx" }; 1643 1644 // If rd or rn is SP, uxtw on 32-bit registers and uxtx on 64-bit 1645 // registers becomes lsl. 1646 if (((instr->Rd() == kZeroRegCode) || (instr->Rn() == kZeroRegCode)) && 1647 (((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) || 1648 (instr->ExtendMode() == UXTX))) { 1649 if (instr->ImmExtendShift() > 0) { 1650 AppendToOutput(", lsl #%d", instr->ImmExtendShift()); 1651 } 1652 } else { 1653 AppendToOutput(", %s", extend_mode[instr->ExtendMode()]); 1654 if (instr->ImmExtendShift() > 0) { 1655 AppendToOutput(" #%d", instr->ImmExtendShift()); 1656 } 1657 } 1658 return 3; 1659 } 1660 1661 1662 int DisassemblingDecoder::SubstituteLSRegOffsetField(Instruction* instr, 1663 const char* format) { 1664 DCHECK(strncmp(format, "Offsetreg", 9) == 0); 1665 const char* extend_mode[] = { "undefined", "undefined", "uxtw", "lsl", 1666 "undefined", "undefined", "sxtw", "sxtx" }; 1667 USE(format); 1668 1669 unsigned shift = instr->ImmShiftLS(); 1670 Extend ext = static_cast<Extend>(instr->ExtendMode()); 1671 char reg_type = ((ext == UXTW) || (ext == SXTW)) ? 'w' : 'x'; 1672 1673 unsigned rm = instr->Rm(); 1674 if (rm == kZeroRegCode) { 1675 AppendToOutput("%czr", reg_type); 1676 } else { 1677 AppendToOutput("%c%d", reg_type, rm); 1678 } 1679 1680 // Extend mode UXTX is an alias for shift mode LSL here. 1681 if (!((ext == UXTX) && (shift == 0))) { 1682 AppendToOutput(", %s", extend_mode[ext]); 1683 if (shift != 0) { 1684 AppendToOutput(" #%d", instr->SizeLS()); 1685 } 1686 } 1687 return 9; 1688 } 1689 1690 1691 int DisassemblingDecoder::SubstitutePrefetchField(Instruction* instr, 1692 const char* format) { 1693 DCHECK(format[0] == 'P'); 1694 USE(format); 1695 1696 int prefetch_mode = instr->PrefetchMode(); 1697 1698 const char* ls = (prefetch_mode & 0x10) ? "st" : "ld"; 1699 int level = (prefetch_mode >> 1) + 1; 1700 const char* ks = (prefetch_mode & 1) ? "strm" : "keep"; 1701 1702 AppendToOutput("p%sl%d%s", ls, level, ks); 1703 return 6; 1704 } 1705 1706 int DisassemblingDecoder::SubstituteBarrierField(Instruction* instr, 1707 const char* format) { 1708 DCHECK(format[0] == 'M'); 1709 USE(format); 1710 1711 static const char* const options[4][4] = { 1712 { "sy (0b0000)", "oshld", "oshst", "osh" }, 1713 { "sy (0b0100)", "nshld", "nshst", "nsh" }, 1714 { "sy (0b1000)", "ishld", "ishst", "ish" }, 1715 { "sy (0b1100)", "ld", "st", "sy" } 1716 }; 1717 int domain = instr->ImmBarrierDomain(); 1718 int type = instr->ImmBarrierType(); 1719 1720 AppendToOutput("%s", options[domain][type]); 1721 return 1; 1722 } 1723 1724 1725 void DisassemblingDecoder::ResetOutput() { 1726 buffer_pos_ = 0; 1727 buffer_[buffer_pos_] = 0; 1728 } 1729 1730 1731 void DisassemblingDecoder::AppendToOutput(const char* format, ...) { 1732 va_list args; 1733 va_start(args, format); 1734 buffer_pos_ += vsnprintf(&buffer_[buffer_pos_], buffer_size_, format, args); 1735 va_end(args); 1736 } 1737 1738 1739 void PrintDisassembler::ProcessOutput(Instruction* instr) { 1740 fprintf(stream_, "0x%016" PRIx64 " %08" PRIx32 "\t\t%s\n", 1741 reinterpret_cast<uint64_t>(instr), instr->InstructionBits(), 1742 GetOutput()); 1743 } 1744 1745 } // namespace internal 1746 } // namespace v8 1747 1748 1749 namespace disasm { 1750 1751 1752 const char* NameConverter::NameOfAddress(byte* addr) const { 1753 v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void *>(addr)); 1754 return tmp_buffer_.start(); 1755 } 1756 1757 1758 const char* NameConverter::NameOfConstant(byte* addr) const { 1759 return NameOfAddress(addr); 1760 } 1761 1762 1763 const char* NameConverter::NameOfCPURegister(int reg) const { 1764 unsigned ureg = reg; // Avoid warnings about signed/unsigned comparisons. 1765 if (ureg >= v8::internal::kNumberOfRegisters) { 1766 return "noreg"; 1767 } 1768 if (ureg == v8::internal::kZeroRegCode) { 1769 return "xzr"; 1770 } 1771 v8::internal::SNPrintF(tmp_buffer_, "x%u", ureg); 1772 return tmp_buffer_.start(); 1773 } 1774 1775 1776 const char* NameConverter::NameOfByteCPURegister(int reg) const { 1777 UNREACHABLE(); // ARM64 does not have the concept of a byte register 1778 return "nobytereg"; 1779 } 1780 1781 1782 const char* NameConverter::NameOfXMMRegister(int reg) const { 1783 UNREACHABLE(); // ARM64 does not have any XMM registers 1784 return "noxmmreg"; 1785 } 1786 1787 1788 const char* NameConverter::NameInCode(byte* addr) const { 1789 // The default name converter is called for unknown code, so we will not try 1790 // to access any memory. 1791 return ""; 1792 } 1793 1794 1795 //------------------------------------------------------------------------------ 1796 1797 class BufferDisassembler : public v8::internal::DisassemblingDecoder { 1798 public: 1799 explicit BufferDisassembler(v8::internal::Vector<char> out_buffer) 1800 : out_buffer_(out_buffer) { } 1801 1802 ~BufferDisassembler() { } 1803 1804 virtual void ProcessOutput(v8::internal::Instruction* instr) { 1805 v8::internal::SNPrintF(out_buffer_, "%08" PRIx32 " %s", 1806 instr->InstructionBits(), GetOutput()); 1807 } 1808 1809 private: 1810 v8::internal::Vector<char> out_buffer_; 1811 }; 1812 1813 Disassembler::Disassembler(const NameConverter& converter) 1814 : converter_(converter) {} 1815 1816 1817 Disassembler::~Disassembler() { USE(converter_); } 1818 1819 1820 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, 1821 byte* instr) { 1822 v8::internal::Decoder<v8::internal::DispatchingDecoderVisitor> decoder; 1823 BufferDisassembler disasm(buffer); 1824 decoder.AppendVisitor(&disasm); 1825 1826 decoder.Decode(reinterpret_cast<v8::internal::Instruction*>(instr)); 1827 return v8::internal::kInstructionSize; 1828 } 1829 1830 1831 int Disassembler::ConstantPoolSizeAt(byte* instr) { 1832 return v8::internal::Assembler::ConstantPoolSizeAt( 1833 reinterpret_cast<v8::internal::Instruction*>(instr)); 1834 } 1835 1836 1837 void Disassembler::Disassemble(FILE* file, byte* start, byte* end) { 1838 v8::internal::Decoder<v8::internal::DispatchingDecoderVisitor> decoder; 1839 v8::internal::PrintDisassembler disasm(file); 1840 decoder.AppendVisitor(&disasm); 1841 1842 for (byte* pc = start; pc < end; pc += v8::internal::kInstructionSize) { 1843 decoder.Decode(reinterpret_cast<v8::internal::Instruction*>(pc)); 1844 } 1845 } 1846 1847 } // namespace disasm 1848 1849 #endif // V8_TARGET_ARCH_ARM64 1850