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 3 // found in the LICENSE file. 4 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 7 // overriden to modify register names or to do symbol lookup on addresses. 8 // 9 // The example below will disassemble a block of code and print it to stdout. 10 // 11 // NameConverter converter; 12 // Disassembler d(converter); 13 // for (byte* pc = begin; pc < end;) { 14 // v8::internal::EmbeddedVector<char, 256> buffer; 15 // byte* prev_pc = pc; 16 // pc += d.InstructionDecode(buffer, pc); 17 // printf("%p %08x %s\n", 18 // prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer); 19 // } 20 // 21 // The Disassembler class also has a convenience method to disassemble a block 22 // of code into a FILE*, meaning that the above functionality could also be 23 // achieved by just calling Disassembler::Disassemble(stdout, begin, end); 24 25 26 #include <assert.h> 27 #include <stdarg.h> 28 #include <stdio.h> 29 #include <string.h> 30 31 #if V8_TARGET_ARCH_ARM 32 33 #include "src/arm/constants-arm.h" 34 #include "src/base/bits.h" 35 #include "src/base/platform/platform.h" 36 #include "src/disasm.h" 37 #include "src/macro-assembler.h" 38 39 40 namespace v8 { 41 namespace internal { 42 43 44 //------------------------------------------------------------------------------ 45 46 // Decoder decodes and disassembles instructions into an output buffer. 47 // It uses the converter to convert register names and call destinations into 48 // more informative description. 49 class Decoder { 50 public: 51 Decoder(const disasm::NameConverter& converter, 52 Vector<char> out_buffer) 53 : converter_(converter), 54 out_buffer_(out_buffer), 55 out_buffer_pos_(0) { 56 out_buffer_[out_buffer_pos_] = '\0'; 57 } 58 59 ~Decoder() {} 60 61 // Writes one disassembled instruction into 'buffer' (0-terminated). 62 // Returns the length of the disassembled machine instruction in bytes. 63 int InstructionDecode(byte* instruction); 64 65 static bool IsConstantPoolAt(byte* instr_ptr); 66 static int ConstantPoolSizeAt(byte* instr_ptr); 67 68 private: 69 // Bottleneck functions to print into the out_buffer. 70 void PrintChar(const char ch); 71 void Print(const char* str); 72 73 // Printing of common values. 74 void PrintRegister(int reg); 75 void PrintSRegister(int reg); 76 void PrintDRegister(int reg); 77 int FormatVFPRegister(Instruction* instr, const char* format); 78 void PrintMovwMovt(Instruction* instr); 79 int FormatVFPinstruction(Instruction* instr, const char* format); 80 void PrintCondition(Instruction* instr); 81 void PrintShiftRm(Instruction* instr); 82 void PrintShiftImm(Instruction* instr); 83 void PrintShiftSat(Instruction* instr); 84 void PrintPU(Instruction* instr); 85 void PrintSoftwareInterrupt(SoftwareInterruptCodes svc); 86 87 // Handle formatting of instructions and their options. 88 int FormatRegister(Instruction* instr, const char* option); 89 void FormatNeonList(int Vd, int type); 90 void FormatNeonMemory(int Rn, int align, int Rm); 91 int FormatOption(Instruction* instr, const char* option); 92 void Format(Instruction* instr, const char* format); 93 void Unknown(Instruction* instr); 94 95 // Each of these functions decodes one particular instruction type, a 3-bit 96 // field in the instruction encoding. 97 // Types 0 and 1 are combined as they are largely the same except for the way 98 // they interpret the shifter operand. 99 void DecodeType01(Instruction* instr); 100 void DecodeType2(Instruction* instr); 101 void DecodeType3(Instruction* instr); 102 void DecodeType4(Instruction* instr); 103 void DecodeType5(Instruction* instr); 104 void DecodeType6(Instruction* instr); 105 // Type 7 includes special Debugger instructions. 106 int DecodeType7(Instruction* instr); 107 // For VFP support. 108 void DecodeTypeVFP(Instruction* instr); 109 void DecodeType6CoprocessorIns(Instruction* instr); 110 111 void DecodeSpecialCondition(Instruction* instr); 112 113 void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr); 114 void DecodeVCMP(Instruction* instr); 115 void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr); 116 void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr); 117 118 const disasm::NameConverter& converter_; 119 Vector<char> out_buffer_; 120 int out_buffer_pos_; 121 122 DISALLOW_COPY_AND_ASSIGN(Decoder); 123 }; 124 125 126 // Support for assertions in the Decoder formatting functions. 127 #define STRING_STARTS_WITH(string, compare_string) \ 128 (strncmp(string, compare_string, strlen(compare_string)) == 0) 129 130 131 // Append the ch to the output buffer. 132 void Decoder::PrintChar(const char ch) { 133 out_buffer_[out_buffer_pos_++] = ch; 134 } 135 136 137 // Append the str to the output buffer. 138 void Decoder::Print(const char* str) { 139 char cur = *str++; 140 while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 141 PrintChar(cur); 142 cur = *str++; 143 } 144 out_buffer_[out_buffer_pos_] = 0; 145 } 146 147 148 // These condition names are defined in a way to match the native disassembler 149 // formatting. See for example the command "objdump -d <binary file>". 150 static const char* const cond_names[kNumberOfConditions] = { 151 "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" , 152 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid", 153 }; 154 155 156 // Print the condition guarding the instruction. 157 void Decoder::PrintCondition(Instruction* instr) { 158 Print(cond_names[instr->ConditionValue()]); 159 } 160 161 162 // Print the register name according to the active name converter. 163 void Decoder::PrintRegister(int reg) { 164 Print(converter_.NameOfCPURegister(reg)); 165 } 166 167 168 // Print the VFP S register name according to the active name converter. 169 void Decoder::PrintSRegister(int reg) { 170 Print(VFPRegisters::Name(reg, false)); 171 } 172 173 174 // Print the VFP D register name according to the active name converter. 175 void Decoder::PrintDRegister(int reg) { 176 Print(VFPRegisters::Name(reg, true)); 177 } 178 179 180 // These shift names are defined in a way to match the native disassembler 181 // formatting. See for example the command "objdump -d <binary file>". 182 static const char* const shift_names[kNumberOfShifts] = { 183 "lsl", "lsr", "asr", "ror" 184 }; 185 186 187 // Print the register shift operands for the instruction. Generally used for 188 // data processing instructions. 189 void Decoder::PrintShiftRm(Instruction* instr) { 190 ShiftOp shift = instr->ShiftField(); 191 int shift_index = instr->ShiftValue(); 192 int shift_amount = instr->ShiftAmountValue(); 193 int rm = instr->RmValue(); 194 195 PrintRegister(rm); 196 197 if ((instr->RegShiftValue() == 0) && (shift == LSL) && (shift_amount == 0)) { 198 // Special case for using rm only. 199 return; 200 } 201 if (instr->RegShiftValue() == 0) { 202 // by immediate 203 if ((shift == ROR) && (shift_amount == 0)) { 204 Print(", RRX"); 205 return; 206 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { 207 shift_amount = 32; 208 } 209 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 210 ", %s #%d", 211 shift_names[shift_index], 212 shift_amount); 213 } else { 214 // by register 215 int rs = instr->RsValue(); 216 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 217 ", %s ", shift_names[shift_index]); 218 PrintRegister(rs); 219 } 220 } 221 222 223 // Print the immediate operand for the instruction. Generally used for data 224 // processing instructions. 225 void Decoder::PrintShiftImm(Instruction* instr) { 226 int rotate = instr->RotateValue() * 2; 227 int immed8 = instr->Immed8Value(); 228 int imm = base::bits::RotateRight32(immed8, rotate); 229 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%d", imm); 230 } 231 232 233 // Print the optional shift and immediate used by saturating instructions. 234 void Decoder::PrintShiftSat(Instruction* instr) { 235 int shift = instr->Bits(11, 7); 236 if (shift > 0) { 237 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 238 ", %s #%d", 239 shift_names[instr->Bit(6) * 2], 240 instr->Bits(11, 7)); 241 } 242 } 243 244 245 // Print PU formatting to reduce complexity of FormatOption. 246 void Decoder::PrintPU(Instruction* instr) { 247 switch (instr->PUField()) { 248 case da_x: { 249 Print("da"); 250 break; 251 } 252 case ia_x: { 253 Print("ia"); 254 break; 255 } 256 case db_x: { 257 Print("db"); 258 break; 259 } 260 case ib_x: { 261 Print("ib"); 262 break; 263 } 264 default: { 265 UNREACHABLE(); 266 break; 267 } 268 } 269 } 270 271 272 // Print SoftwareInterrupt codes. Factoring this out reduces the complexity of 273 // the FormatOption method. 274 void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) { 275 switch (svc) { 276 case kCallRtRedirected: 277 Print("call rt redirected"); 278 return; 279 case kBreakpoint: 280 Print("breakpoint"); 281 return; 282 default: 283 if (svc >= kStopCode) { 284 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 285 "%d - 0x%x", 286 svc & kStopCodeMask, 287 svc & kStopCodeMask); 288 } else { 289 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 290 "%d", 291 svc); 292 } 293 return; 294 } 295 } 296 297 298 // Handle all register based formatting in this function to reduce the 299 // complexity of FormatOption. 300 int Decoder::FormatRegister(Instruction* instr, const char* format) { 301 DCHECK(format[0] == 'r'); 302 if (format[1] == 'n') { // 'rn: Rn register 303 int reg = instr->RnValue(); 304 PrintRegister(reg); 305 return 2; 306 } else if (format[1] == 'd') { // 'rd: Rd register 307 int reg = instr->RdValue(); 308 PrintRegister(reg); 309 return 2; 310 } else if (format[1] == 's') { // 'rs: Rs register 311 int reg = instr->RsValue(); 312 PrintRegister(reg); 313 return 2; 314 } else if (format[1] == 'm') { // 'rm: Rm register 315 int reg = instr->RmValue(); 316 PrintRegister(reg); 317 return 2; 318 } else if (format[1] == 't') { // 'rt: Rt register 319 int reg = instr->RtValue(); 320 PrintRegister(reg); 321 return 2; 322 } else if (format[1] == 'l') { 323 // 'rlist: register list for load and store multiple instructions 324 DCHECK(STRING_STARTS_WITH(format, "rlist")); 325 int rlist = instr->RlistValue(); 326 int reg = 0; 327 Print("{"); 328 // Print register list in ascending order, by scanning the bit mask. 329 while (rlist != 0) { 330 if ((rlist & 1) != 0) { 331 PrintRegister(reg); 332 if ((rlist >> 1) != 0) { 333 Print(", "); 334 } 335 } 336 reg++; 337 rlist >>= 1; 338 } 339 Print("}"); 340 return 5; 341 } 342 UNREACHABLE(); 343 return -1; 344 } 345 346 347 // Handle all VFP register based formatting in this function to reduce the 348 // complexity of FormatOption. 349 int Decoder::FormatVFPRegister(Instruction* instr, const char* format) { 350 DCHECK((format[0] == 'S') || (format[0] == 'D')); 351 352 VFPRegPrecision precision = 353 format[0] == 'D' ? kDoublePrecision : kSinglePrecision; 354 355 int retval = 2; 356 int reg = -1; 357 if (format[1] == 'n') { 358 reg = instr->VFPNRegValue(precision); 359 } else if (format[1] == 'm') { 360 reg = instr->VFPMRegValue(precision); 361 } else if (format[1] == 'd') { 362 if ((instr->TypeValue() == 7) && 363 (instr->Bit(24) == 0x0) && 364 (instr->Bits(11, 9) == 0x5) && 365 (instr->Bit(4) == 0x1)) { 366 // vmov.32 has Vd in a different place. 367 reg = instr->Bits(19, 16) | (instr->Bit(7) << 4); 368 } else { 369 reg = instr->VFPDRegValue(precision); 370 } 371 372 if (format[2] == '+') { 373 int immed8 = instr->Immed8Value(); 374 if (format[0] == 'S') reg += immed8 - 1; 375 if (format[0] == 'D') reg += (immed8 / 2 - 1); 376 } 377 if (format[2] == '+') retval = 3; 378 } else { 379 UNREACHABLE(); 380 } 381 382 if (precision == kSinglePrecision) { 383 PrintSRegister(reg); 384 } else { 385 PrintDRegister(reg); 386 } 387 388 return retval; 389 } 390 391 392 int Decoder::FormatVFPinstruction(Instruction* instr, const char* format) { 393 Print(format); 394 return 0; 395 } 396 397 398 void Decoder::FormatNeonList(int Vd, int type) { 399 if (type == nlt_1) { 400 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 401 "{d%d}", Vd); 402 } else if (type == nlt_2) { 403 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 404 "{d%d, d%d}", Vd, Vd + 1); 405 } else if (type == nlt_3) { 406 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 407 "{d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2); 408 } else if (type == nlt_4) { 409 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 410 "{d%d, d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2, Vd + 3); 411 } 412 } 413 414 415 void Decoder::FormatNeonMemory(int Rn, int align, int Rm) { 416 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 417 "[r%d", Rn); 418 if (align != 0) { 419 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 420 ":%d", (1 << align) << 6); 421 } 422 if (Rm == 15) { 423 Print("]"); 424 } else if (Rm == 13) { 425 Print("]!"); 426 } else { 427 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 428 "], r%d", Rm); 429 } 430 } 431 432 433 // Print the movw or movt instruction. 434 void Decoder::PrintMovwMovt(Instruction* instr) { 435 int imm = instr->ImmedMovwMovtValue(); 436 int rd = instr->RdValue(); 437 PrintRegister(rd); 438 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, ", #%d", imm); 439 } 440 441 442 // FormatOption takes a formatting string and interprets it based on 443 // the current instructions. The format string points to the first 444 // character of the option string (the option escape has already been 445 // consumed by the caller.) FormatOption returns the number of 446 // characters that were consumed from the formatting string. 447 int Decoder::FormatOption(Instruction* instr, const char* format) { 448 switch (format[0]) { 449 case 'a': { // 'a: accumulate multiplies 450 if (instr->Bit(21) == 0) { 451 Print("ul"); 452 } else { 453 Print("la"); 454 } 455 return 1; 456 } 457 case 'b': { // 'b: byte loads or stores 458 if (instr->HasB()) { 459 Print("b"); 460 } 461 return 1; 462 } 463 case 'c': { // 'cond: conditional execution 464 DCHECK(STRING_STARTS_WITH(format, "cond")); 465 PrintCondition(instr); 466 return 4; 467 } 468 case 'd': { // 'd: vmov double immediate. 469 double d = instr->DoubleImmedVmov(); 470 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%g", d); 471 return 1; 472 } 473 case 'f': { // 'f: bitfield instructions - v7 and above. 474 uint32_t lsbit = instr->Bits(11, 7); 475 uint32_t width = instr->Bits(20, 16) + 1; 476 if (instr->Bit(21) == 0) { 477 // BFC/BFI: 478 // Bits 20-16 represent most-significant bit. Covert to width. 479 width -= lsbit; 480 DCHECK(width > 0); 481 } 482 DCHECK((width + lsbit) <= 32); 483 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 484 "#%d, #%d", lsbit, width); 485 return 1; 486 } 487 case 'h': { // 'h: halfword operation for extra loads and stores 488 if (instr->HasH()) { 489 Print("h"); 490 } else { 491 Print("b"); 492 } 493 return 1; 494 } 495 case 'i': { // 'i: immediate value from adjacent bits. 496 // Expects tokens in the form imm%02d@%02d, i.e. imm05@07, imm10@16 497 int width = (format[3] - '0') * 10 + (format[4] - '0'); 498 int lsb = (format[6] - '0') * 10 + (format[7] - '0'); 499 500 DCHECK((width >= 1) && (width <= 32)); 501 DCHECK((lsb >= 0) && (lsb <= 31)); 502 DCHECK((width + lsb) <= 32); 503 504 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 505 "%d", 506 instr->Bits(width + lsb - 1, lsb)); 507 return 8; 508 } 509 case 'l': { // 'l: branch and link 510 if (instr->HasLink()) { 511 Print("l"); 512 } 513 return 1; 514 } 515 case 'm': { 516 if (format[1] == 'w') { 517 // 'mw: movt/movw instructions. 518 PrintMovwMovt(instr); 519 return 2; 520 } 521 if (format[1] == 'e') { // 'memop: load/store instructions. 522 DCHECK(STRING_STARTS_WITH(format, "memop")); 523 if (instr->HasL()) { 524 Print("ldr"); 525 } else { 526 if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0) && 527 (instr->Bits(7, 6) == 3) && (instr->Bit(4) == 1)) { 528 if (instr->Bit(5) == 1) { 529 Print("strd"); 530 } else { 531 Print("ldrd"); 532 } 533 return 5; 534 } 535 Print("str"); 536 } 537 return 5; 538 } 539 // 'msg: for simulator break instructions 540 DCHECK(STRING_STARTS_WITH(format, "msg")); 541 byte* str = 542 reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff); 543 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 544 "%s", converter_.NameInCode(str)); 545 return 3; 546 } 547 case 'o': { 548 if ((format[3] == '1') && (format[4] == '2')) { 549 // 'off12: 12-bit offset for load and store instructions 550 DCHECK(STRING_STARTS_WITH(format, "off12")); 551 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 552 "%d", instr->Offset12Value()); 553 return 5; 554 } else if (format[3] == '0') { 555 // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0. 556 DCHECK(STRING_STARTS_WITH(format, "off0to3and8to19")); 557 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 558 "%d", 559 (instr->Bits(19, 8) << 4) + 560 instr->Bits(3, 0)); 561 return 15; 562 } 563 // 'off8: 8-bit offset for extra load and store instructions 564 DCHECK(STRING_STARTS_WITH(format, "off8")); 565 int offs8 = (instr->ImmedHValue() << 4) | instr->ImmedLValue(); 566 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", offs8); 567 return 4; 568 } 569 case 'p': { // 'pu: P and U bits for load and store instructions 570 DCHECK(STRING_STARTS_WITH(format, "pu")); 571 PrintPU(instr); 572 return 2; 573 } 574 case 'r': { 575 return FormatRegister(instr, format); 576 } 577 case 's': { 578 if (format[1] == 'h') { // 'shift_op or 'shift_rm or 'shift_sat. 579 if (format[6] == 'o') { // 'shift_op 580 DCHECK(STRING_STARTS_WITH(format, "shift_op")); 581 if (instr->TypeValue() == 0) { 582 PrintShiftRm(instr); 583 } else { 584 DCHECK(instr->TypeValue() == 1); 585 PrintShiftImm(instr); 586 } 587 return 8; 588 } else if (format[6] == 's') { // 'shift_sat. 589 DCHECK(STRING_STARTS_WITH(format, "shift_sat")); 590 PrintShiftSat(instr); 591 return 9; 592 } else { // 'shift_rm 593 DCHECK(STRING_STARTS_WITH(format, "shift_rm")); 594 PrintShiftRm(instr); 595 return 8; 596 } 597 } else if (format[1] == 'v') { // 'svc 598 DCHECK(STRING_STARTS_WITH(format, "svc")); 599 PrintSoftwareInterrupt(instr->SvcValue()); 600 return 3; 601 } else if (format[1] == 'i') { // 'sign: signed extra loads and stores 602 DCHECK(STRING_STARTS_WITH(format, "sign")); 603 if (instr->HasSign()) { 604 Print("s"); 605 } 606 return 4; 607 } 608 // 's: S field of data processing instructions 609 if (instr->HasS()) { 610 Print("s"); 611 } 612 return 1; 613 } 614 case 't': { // 'target: target of branch instructions 615 DCHECK(STRING_STARTS_WITH(format, "target")); 616 int off = (instr->SImmed24Value() << 2) + 8; 617 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 618 "%+d -> %s", 619 off, 620 converter_.NameOfAddress( 621 reinterpret_cast<byte*>(instr) + off)); 622 return 6; 623 } 624 case 'u': { // 'u: signed or unsigned multiplies 625 // The manual gets the meaning of bit 22 backwards in the multiply 626 // instruction overview on page A3.16.2. The instructions that 627 // exist in u and s variants are the following: 628 // smull A4.1.87 629 // umull A4.1.129 630 // umlal A4.1.128 631 // smlal A4.1.76 632 // For these 0 means u and 1 means s. As can be seen on their individual 633 // pages. The other 18 mul instructions have the bit set or unset in 634 // arbitrary ways that are unrelated to the signedness of the instruction. 635 // None of these 18 instructions exist in both a 'u' and an 's' variant. 636 637 if (instr->Bit(22) == 0) { 638 Print("u"); 639 } else { 640 Print("s"); 641 } 642 return 1; 643 } 644 case 'v': { 645 return FormatVFPinstruction(instr, format); 646 } 647 case 'S': 648 case 'D': { 649 return FormatVFPRegister(instr, format); 650 } 651 case 'w': { // 'w: W field of load and store instructions 652 if (instr->HasW()) { 653 Print("!"); 654 } 655 return 1; 656 } 657 default: { 658 UNREACHABLE(); 659 break; 660 } 661 } 662 UNREACHABLE(); 663 return -1; 664 } 665 666 667 // Format takes a formatting string for a whole instruction and prints it into 668 // the output buffer. All escaped options are handed to FormatOption to be 669 // parsed further. 670 void Decoder::Format(Instruction* instr, const char* format) { 671 char cur = *format++; 672 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 673 if (cur == '\'') { // Single quote is used as the formatting escape. 674 format += FormatOption(instr, format); 675 } else { 676 out_buffer_[out_buffer_pos_++] = cur; 677 } 678 cur = *format++; 679 } 680 out_buffer_[out_buffer_pos_] = '\0'; 681 } 682 683 684 // The disassembler may end up decoding data inlined in the code. We do not want 685 // it to crash if the data does not ressemble any known instruction. 686 #define VERIFY(condition) \ 687 if(!(condition)) { \ 688 Unknown(instr); \ 689 return; \ 690 } 691 692 693 // For currently unimplemented decodings the disassembler calls Unknown(instr) 694 // which will just print "unknown" of the instruction bits. 695 void Decoder::Unknown(Instruction* instr) { 696 Format(instr, "unknown"); 697 } 698 699 700 void Decoder::DecodeType01(Instruction* instr) { 701 int type = instr->TypeValue(); 702 if ((type == 0) && instr->IsSpecialType0()) { 703 // multiply instruction or extra loads and stores 704 if (instr->Bits(7, 4) == 9) { 705 if (instr->Bit(24) == 0) { 706 // multiply instructions 707 if (instr->Bit(23) == 0) { 708 if (instr->Bit(21) == 0) { 709 // The MUL instruction description (A 4.1.33) refers to Rd as being 710 // the destination for the operation, but it confusingly uses the 711 // Rn field to encode it. 712 Format(instr, "mul'cond's 'rn, 'rm, 'rs"); 713 } else { 714 if (instr->Bit(22) == 0) { 715 // The MLA instruction description (A 4.1.28) refers to the order 716 // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the 717 // Rn field to encode the Rd register and the Rd field to encode 718 // the Rn register. 719 Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd"); 720 } else { 721 // The MLS instruction description (A 4.1.29) refers to the order 722 // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the 723 // Rn field to encode the Rd register and the Rd field to encode 724 // the Rn register. 725 Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd"); 726 } 727 } 728 } else { 729 // The signed/long multiply instructions use the terms RdHi and RdLo 730 // when referring to the target registers. They are mapped to the Rn 731 // and Rd fields as follows: 732 // RdLo == Rd field 733 // RdHi == Rn field 734 // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs> 735 Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs"); 736 } 737 } else { 738 Unknown(instr); // not used by V8 739 } 740 } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xd) == 0xd)) { 741 // ldrd, strd 742 switch (instr->PUField()) { 743 case da_x: { 744 if (instr->Bit(22) == 0) { 745 Format(instr, "'memop'cond's 'rd, ['rn], -'rm"); 746 } else { 747 Format(instr, "'memop'cond's 'rd, ['rn], #-'off8"); 748 } 749 break; 750 } 751 case ia_x: { 752 if (instr->Bit(22) == 0) { 753 Format(instr, "'memop'cond's 'rd, ['rn], +'rm"); 754 } else { 755 Format(instr, "'memop'cond's 'rd, ['rn], #+'off8"); 756 } 757 break; 758 } 759 case db_x: { 760 if (instr->Bit(22) == 0) { 761 Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w"); 762 } else { 763 Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w"); 764 } 765 break; 766 } 767 case ib_x: { 768 if (instr->Bit(22) == 0) { 769 Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w"); 770 } else { 771 Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w"); 772 } 773 break; 774 } 775 default: { 776 // The PU field is a 2-bit field. 777 UNREACHABLE(); 778 break; 779 } 780 } 781 } else { 782 // extra load/store instructions 783 switch (instr->PUField()) { 784 case da_x: { 785 if (instr->Bit(22) == 0) { 786 Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm"); 787 } else { 788 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8"); 789 } 790 break; 791 } 792 case ia_x: { 793 if (instr->Bit(22) == 0) { 794 Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm"); 795 } else { 796 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8"); 797 } 798 break; 799 } 800 case db_x: { 801 if (instr->Bit(22) == 0) { 802 Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w"); 803 } else { 804 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w"); 805 } 806 break; 807 } 808 case ib_x: { 809 if (instr->Bit(22) == 0) { 810 Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w"); 811 } else { 812 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w"); 813 } 814 break; 815 } 816 default: { 817 // The PU field is a 2-bit field. 818 UNREACHABLE(); 819 break; 820 } 821 } 822 return; 823 } 824 } else if ((type == 0) && instr->IsMiscType0()) { 825 if (instr->Bits(22, 21) == 1) { 826 switch (instr->BitField(7, 4)) { 827 case BX: 828 Format(instr, "bx'cond 'rm"); 829 break; 830 case BLX: 831 Format(instr, "blx'cond 'rm"); 832 break; 833 case BKPT: 834 Format(instr, "bkpt 'off0to3and8to19"); 835 break; 836 default: 837 Unknown(instr); // not used by V8 838 break; 839 } 840 } else if (instr->Bits(22, 21) == 3) { 841 switch (instr->BitField(7, 4)) { 842 case CLZ: 843 Format(instr, "clz'cond 'rd, 'rm"); 844 break; 845 default: 846 Unknown(instr); // not used by V8 847 break; 848 } 849 } else { 850 Unknown(instr); // not used by V8 851 } 852 } else if ((type == 1) && instr->IsNopType1()) { 853 Format(instr, "nop'cond"); 854 } else { 855 switch (instr->OpcodeField()) { 856 case AND: { 857 Format(instr, "and'cond's 'rd, 'rn, 'shift_op"); 858 break; 859 } 860 case EOR: { 861 Format(instr, "eor'cond's 'rd, 'rn, 'shift_op"); 862 break; 863 } 864 case SUB: { 865 Format(instr, "sub'cond's 'rd, 'rn, 'shift_op"); 866 break; 867 } 868 case RSB: { 869 Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op"); 870 break; 871 } 872 case ADD: { 873 Format(instr, "add'cond's 'rd, 'rn, 'shift_op"); 874 break; 875 } 876 case ADC: { 877 Format(instr, "adc'cond's 'rd, 'rn, 'shift_op"); 878 break; 879 } 880 case SBC: { 881 Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op"); 882 break; 883 } 884 case RSC: { 885 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op"); 886 break; 887 } 888 case TST: { 889 if (instr->HasS()) { 890 Format(instr, "tst'cond 'rn, 'shift_op"); 891 } else { 892 Format(instr, "movw'cond 'mw"); 893 } 894 break; 895 } 896 case TEQ: { 897 if (instr->HasS()) { 898 Format(instr, "teq'cond 'rn, 'shift_op"); 899 } else { 900 // Other instructions matching this pattern are handled in the 901 // miscellaneous instructions part above. 902 UNREACHABLE(); 903 } 904 break; 905 } 906 case CMP: { 907 if (instr->HasS()) { 908 Format(instr, "cmp'cond 'rn, 'shift_op"); 909 } else { 910 Format(instr, "movt'cond 'mw"); 911 } 912 break; 913 } 914 case CMN: { 915 if (instr->HasS()) { 916 Format(instr, "cmn'cond 'rn, 'shift_op"); 917 } else { 918 // Other instructions matching this pattern are handled in the 919 // miscellaneous instructions part above. 920 UNREACHABLE(); 921 } 922 break; 923 } 924 case ORR: { 925 Format(instr, "orr'cond's 'rd, 'rn, 'shift_op"); 926 break; 927 } 928 case MOV: { 929 Format(instr, "mov'cond's 'rd, 'shift_op"); 930 break; 931 } 932 case BIC: { 933 Format(instr, "bic'cond's 'rd, 'rn, 'shift_op"); 934 break; 935 } 936 case MVN: { 937 Format(instr, "mvn'cond's 'rd, 'shift_op"); 938 break; 939 } 940 default: { 941 // The Opcode field is a 4-bit field. 942 UNREACHABLE(); 943 break; 944 } 945 } 946 } 947 } 948 949 950 void Decoder::DecodeType2(Instruction* instr) { 951 switch (instr->PUField()) { 952 case da_x: { 953 if (instr->HasW()) { 954 Unknown(instr); // not used in V8 955 return; 956 } 957 Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); 958 break; 959 } 960 case ia_x: { 961 if (instr->HasW()) { 962 Unknown(instr); // not used in V8 963 return; 964 } 965 Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12"); 966 break; 967 } 968 case db_x: { 969 Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w"); 970 break; 971 } 972 case ib_x: { 973 Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w"); 974 break; 975 } 976 default: { 977 // The PU field is a 2-bit field. 978 UNREACHABLE(); 979 break; 980 } 981 } 982 } 983 984 985 void Decoder::DecodeType3(Instruction* instr) { 986 switch (instr->PUField()) { 987 case da_x: { 988 VERIFY(!instr->HasW()); 989 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); 990 break; 991 } 992 case ia_x: { 993 if (instr->Bit(4) == 0) { 994 Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm"); 995 } else { 996 if (instr->Bit(5) == 0) { 997 switch (instr->Bits(22, 21)) { 998 case 0: 999 if (instr->Bit(20) == 0) { 1000 if (instr->Bit(6) == 0) { 1001 Format(instr, "pkhbt'cond 'rd, 'rn, 'rm, lsl #'imm05@07"); 1002 } else { 1003 if (instr->Bits(11, 7) == 0) { 1004 Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #32"); 1005 } else { 1006 Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #'imm05@07"); 1007 } 1008 } 1009 } else { 1010 UNREACHABLE(); 1011 } 1012 break; 1013 case 1: 1014 UNREACHABLE(); 1015 break; 1016 case 2: 1017 UNREACHABLE(); 1018 break; 1019 case 3: 1020 Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat"); 1021 break; 1022 } 1023 } else { 1024 switch (instr->Bits(22, 21)) { 1025 case 0: 1026 UNREACHABLE(); 1027 break; 1028 case 1: 1029 if (instr->Bits(9, 6) == 1) { 1030 if (instr->Bit(20) == 0) { 1031 if (instr->Bits(19, 16) == 0xF) { 1032 switch (instr->Bits(11, 10)) { 1033 case 0: 1034 Format(instr, "sxtb'cond 'rd, 'rm"); 1035 break; 1036 case 1: 1037 Format(instr, "sxtb'cond 'rd, 'rm, ror #8"); 1038 break; 1039 case 2: 1040 Format(instr, "sxtb'cond 'rd, 'rm, ror #16"); 1041 break; 1042 case 3: 1043 Format(instr, "sxtb'cond 'rd, 'rm, ror #24"); 1044 break; 1045 } 1046 } else { 1047 switch (instr->Bits(11, 10)) { 1048 case 0: 1049 Format(instr, "sxtab'cond 'rd, 'rn, 'rm"); 1050 break; 1051 case 1: 1052 Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #8"); 1053 break; 1054 case 2: 1055 Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #16"); 1056 break; 1057 case 3: 1058 Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #24"); 1059 break; 1060 } 1061 } 1062 } else { 1063 if (instr->Bits(19, 16) == 0xF) { 1064 switch (instr->Bits(11, 10)) { 1065 case 0: 1066 Format(instr, "sxth'cond 'rd, 'rm"); 1067 break; 1068 case 1: 1069 Format(instr, "sxth'cond 'rd, 'rm, ror #8"); 1070 break; 1071 case 2: 1072 Format(instr, "sxth'cond 'rd, 'rm, ror #16"); 1073 break; 1074 case 3: 1075 Format(instr, "sxth'cond 'rd, 'rm, ror #24"); 1076 break; 1077 } 1078 } else { 1079 switch (instr->Bits(11, 10)) { 1080 case 0: 1081 Format(instr, "sxtah'cond 'rd, 'rn, 'rm"); 1082 break; 1083 case 1: 1084 Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #8"); 1085 break; 1086 case 2: 1087 Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #16"); 1088 break; 1089 case 3: 1090 Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #24"); 1091 break; 1092 } 1093 } 1094 } 1095 } else { 1096 UNREACHABLE(); 1097 } 1098 break; 1099 case 2: 1100 if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) { 1101 if (instr->Bits(19, 16) == 0xF) { 1102 switch (instr->Bits(11, 10)) { 1103 case 0: 1104 Format(instr, "uxtb16'cond 'rd, 'rm"); 1105 break; 1106 case 1: 1107 Format(instr, "uxtb16'cond 'rd, 'rm, ror #8"); 1108 break; 1109 case 2: 1110 Format(instr, "uxtb16'cond 'rd, 'rm, ror #16"); 1111 break; 1112 case 3: 1113 Format(instr, "uxtb16'cond 'rd, 'rm, ror #24"); 1114 break; 1115 } 1116 } else { 1117 UNREACHABLE(); 1118 } 1119 } else { 1120 UNREACHABLE(); 1121 } 1122 break; 1123 case 3: 1124 if ((instr->Bits(9, 6) == 1)) { 1125 if ((instr->Bit(20) == 0)) { 1126 if (instr->Bits(19, 16) == 0xF) { 1127 switch (instr->Bits(11, 10)) { 1128 case 0: 1129 Format(instr, "uxtb'cond 'rd, 'rm"); 1130 break; 1131 case 1: 1132 Format(instr, "uxtb'cond 'rd, 'rm, ror #8"); 1133 break; 1134 case 2: 1135 Format(instr, "uxtb'cond 'rd, 'rm, ror #16"); 1136 break; 1137 case 3: 1138 Format(instr, "uxtb'cond 'rd, 'rm, ror #24"); 1139 break; 1140 } 1141 } else { 1142 switch (instr->Bits(11, 10)) { 1143 case 0: 1144 Format(instr, "uxtab'cond 'rd, 'rn, 'rm"); 1145 break; 1146 case 1: 1147 Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #8"); 1148 break; 1149 case 2: 1150 Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #16"); 1151 break; 1152 case 3: 1153 Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #24"); 1154 break; 1155 } 1156 } 1157 } else { 1158 if (instr->Bits(19, 16) == 0xF) { 1159 switch (instr->Bits(11, 10)) { 1160 case 0: 1161 Format(instr, "uxth'cond 'rd, 'rm"); 1162 break; 1163 case 1: 1164 Format(instr, "uxth'cond 'rd, 'rm, ror #8"); 1165 break; 1166 case 2: 1167 Format(instr, "uxth'cond 'rd, 'rm, ror #16"); 1168 break; 1169 case 3: 1170 Format(instr, "uxth'cond 'rd, 'rm, ror #24"); 1171 break; 1172 } 1173 } else { 1174 switch (instr->Bits(11, 10)) { 1175 case 0: 1176 Format(instr, "uxtah'cond 'rd, 'rn, 'rm"); 1177 break; 1178 case 1: 1179 Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #8"); 1180 break; 1181 case 2: 1182 Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #16"); 1183 break; 1184 case 3: 1185 Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #24"); 1186 break; 1187 } 1188 } 1189 } 1190 } else { 1191 UNREACHABLE(); 1192 } 1193 break; 1194 } 1195 } 1196 } 1197 break; 1198 } 1199 case db_x: { 1200 if (instr->Bits(22, 20) == 0x5) { 1201 if (instr->Bits(7, 4) == 0x1) { 1202 if (instr->Bits(15, 12) == 0xF) { 1203 Format(instr, "smmul'cond 'rn, 'rm, 'rs"); 1204 } else { 1205 // SMMLA (in V8 notation matching ARM ISA format) 1206 Format(instr, "smmla'cond 'rn, 'rm, 'rs, 'rd"); 1207 } 1208 break; 1209 } 1210 } 1211 if (FLAG_enable_sudiv) { 1212 if (instr->Bits(5, 4) == 0x1) { 1213 if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) { 1214 if (instr->Bit(21) == 0x1) { 1215 // UDIV (in V8 notation matching ARM ISA format) rn = rm/rs 1216 Format(instr, "udiv'cond'b 'rn, 'rm, 'rs"); 1217 } else { 1218 // SDIV (in V8 notation matching ARM ISA format) rn = rm/rs 1219 Format(instr, "sdiv'cond'b 'rn, 'rm, 'rs"); 1220 } 1221 break; 1222 } 1223 } 1224 } 1225 Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w"); 1226 break; 1227 } 1228 case ib_x: { 1229 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) { 1230 uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16)); 1231 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); 1232 uint32_t msbit = widthminus1 + lsbit; 1233 if (msbit <= 31) { 1234 if (instr->Bit(22)) { 1235 Format(instr, "ubfx'cond 'rd, 'rm, 'f"); 1236 } else { 1237 Format(instr, "sbfx'cond 'rd, 'rm, 'f"); 1238 } 1239 } else { 1240 UNREACHABLE(); 1241 } 1242 } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) { 1243 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); 1244 uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16)); 1245 if (msbit >= lsbit) { 1246 if (instr->RmValue() == 15) { 1247 Format(instr, "bfc'cond 'rd, 'f"); 1248 } else { 1249 Format(instr, "bfi'cond 'rd, 'rm, 'f"); 1250 } 1251 } else { 1252 UNREACHABLE(); 1253 } 1254 } else { 1255 Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w"); 1256 } 1257 break; 1258 } 1259 default: { 1260 // The PU field is a 2-bit field. 1261 UNREACHABLE(); 1262 break; 1263 } 1264 } 1265 } 1266 1267 1268 void Decoder::DecodeType4(Instruction* instr) { 1269 if (instr->Bit(22) != 0) { 1270 // Privileged mode currently not supported. 1271 Unknown(instr); 1272 } else { 1273 if (instr->HasL()) { 1274 Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); 1275 } else { 1276 Format(instr, "stm'cond'pu 'rn'w, 'rlist"); 1277 } 1278 } 1279 } 1280 1281 1282 void Decoder::DecodeType5(Instruction* instr) { 1283 Format(instr, "b'l'cond 'target"); 1284 } 1285 1286 1287 void Decoder::DecodeType6(Instruction* instr) { 1288 DecodeType6CoprocessorIns(instr); 1289 } 1290 1291 1292 int Decoder::DecodeType7(Instruction* instr) { 1293 if (instr->Bit(24) == 1) { 1294 if (instr->SvcValue() >= kStopCode) { 1295 Format(instr, "stop'cond 'svc"); 1296 // Also print the stop message. Its address is encoded 1297 // in the following 4 bytes. 1298 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1299 "\n %p %08x stop message: %s", 1300 reinterpret_cast<void*>(instr 1301 + Instruction::kInstrSize), 1302 *reinterpret_cast<uint32_t*>(instr 1303 + Instruction::kInstrSize), 1304 *reinterpret_cast<char**>(instr 1305 + Instruction::kInstrSize)); 1306 // We have decoded 2 * Instruction::kInstrSize bytes. 1307 return 2 * Instruction::kInstrSize; 1308 } else { 1309 Format(instr, "svc'cond 'svc"); 1310 } 1311 } else { 1312 DecodeTypeVFP(instr); 1313 } 1314 return Instruction::kInstrSize; 1315 } 1316 1317 1318 // void Decoder::DecodeTypeVFP(Instruction* instr) 1319 // vmov: Sn = Rt 1320 // vmov: Rt = Sn 1321 // vcvt: Dd = Sm 1322 // vcvt: Sd = Dm 1323 // vcvt.f64.s32 Dd, Dd, #<fbits> 1324 // Dd = vabs(Dm) 1325 // Sd = vabs(Sm) 1326 // Dd = vneg(Dm) 1327 // Sd = vneg(Sm) 1328 // Dd = vadd(Dn, Dm) 1329 // Sd = vadd(Sn, Sm) 1330 // Dd = vsub(Dn, Dm) 1331 // Sd = vsub(Sn, Sm) 1332 // Dd = vmul(Dn, Dm) 1333 // Sd = vmul(Sn, Sm) 1334 // Dd = vmla(Dn, Dm) 1335 // Sd = vmla(Sn, Sm) 1336 // Dd = vmls(Dn, Dm) 1337 // Sd = vmls(Sn, Sm) 1338 // Dd = vdiv(Dn, Dm) 1339 // Sd = vdiv(Sn, Sm) 1340 // vcmp(Dd, Dm) 1341 // vcmp(Sd, Sm) 1342 // Dd = vsqrt(Dm) 1343 // Sd = vsqrt(Sm) 1344 // vmrs 1345 // vmsr 1346 void Decoder::DecodeTypeVFP(Instruction* instr) { 1347 VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) ); 1348 VERIFY(instr->Bits(11, 9) == 0x5); 1349 1350 if (instr->Bit(4) == 0) { 1351 if (instr->Opc1Value() == 0x7) { 1352 // Other data processing instructions 1353 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) { 1354 // vmov register to register. 1355 if (instr->SzValue() == 0x1) { 1356 Format(instr, "vmov'cond.f64 'Dd, 'Dm"); 1357 } else { 1358 Format(instr, "vmov'cond.f32 'Sd, 'Sm"); 1359 } 1360 } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) { 1361 // vabs 1362 if (instr->SzValue() == 0x1) { 1363 Format(instr, "vabs'cond.f64 'Dd, 'Dm"); 1364 } else { 1365 Format(instr, "vabs'cond.f32 'Sd, 'Sm"); 1366 } 1367 } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) { 1368 // vneg 1369 if (instr->SzValue() == 0x1) { 1370 Format(instr, "vneg'cond.f64 'Dd, 'Dm"); 1371 } else { 1372 Format(instr, "vneg'cond.f32 'Sd, 'Sm"); 1373 } 1374 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { 1375 DecodeVCVTBetweenDoubleAndSingle(instr); 1376 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { 1377 DecodeVCVTBetweenFloatingPointAndInteger(instr); 1378 } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) && 1379 (instr->Bit(8) == 1)) { 1380 // vcvt.f64.s32 Dd, Dd, #<fbits> 1381 int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5)); 1382 Format(instr, "vcvt'cond.f64.s32 'Dd, 'Dd"); 1383 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1384 ", #%d", fraction_bits); 1385 } else if (((instr->Opc2Value() >> 1) == 0x6) && 1386 (instr->Opc3Value() & 0x1)) { 1387 DecodeVCVTBetweenFloatingPointAndInteger(instr); 1388 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && 1389 (instr->Opc3Value() & 0x1)) { 1390 DecodeVCMP(instr); 1391 } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) { 1392 if (instr->SzValue() == 0x1) { 1393 Format(instr, "vsqrt'cond.f64 'Dd, 'Dm"); 1394 } else { 1395 Format(instr, "vsqrt'cond.f32 'Sd, 'Sm"); 1396 } 1397 } else if (instr->Opc3Value() == 0x0) { 1398 if (instr->SzValue() == 0x1) { 1399 Format(instr, "vmov'cond.f64 'Dd, 'd"); 1400 } else { 1401 Unknown(instr); // Not used by V8. 1402 } 1403 } else if (((instr->Opc2Value() == 0x6)) && instr->Opc3Value() == 0x3) { 1404 // vrintz - round towards zero (truncate) 1405 if (instr->SzValue() == 0x1) { 1406 Format(instr, "vrintz'cond.f64.f64 'Dd, 'Dm"); 1407 } else { 1408 Format(instr, "vrintz'cond.f32.f32 'Sd, 'Sm"); 1409 } 1410 } else { 1411 Unknown(instr); // Not used by V8. 1412 } 1413 } else if (instr->Opc1Value() == 0x3) { 1414 if (instr->SzValue() == 0x1) { 1415 if (instr->Opc3Value() & 0x1) { 1416 Format(instr, "vsub'cond.f64 'Dd, 'Dn, 'Dm"); 1417 } else { 1418 Format(instr, "vadd'cond.f64 'Dd, 'Dn, 'Dm"); 1419 } 1420 } else { 1421 if (instr->Opc3Value() & 0x1) { 1422 Format(instr, "vsub'cond.f32 'Sd, 'Sn, 'Sm"); 1423 } else { 1424 Format(instr, "vadd'cond.f32 'Sd, 'Sn, 'Sm"); 1425 } 1426 } 1427 } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) { 1428 if (instr->SzValue() == 0x1) { 1429 Format(instr, "vmul'cond.f64 'Dd, 'Dn, 'Dm"); 1430 } else { 1431 Format(instr, "vmul'cond.f32 'Sd, 'Sn, 'Sm"); 1432 } 1433 } else if ((instr->Opc1Value() == 0x0) && !(instr->Opc3Value() & 0x1)) { 1434 if (instr->SzValue() == 0x1) { 1435 Format(instr, "vmla'cond.f64 'Dd, 'Dn, 'Dm"); 1436 } else { 1437 Format(instr, "vmla'cond.f32 'Sd, 'Sn, 'Sm"); 1438 } 1439 } else if ((instr->Opc1Value() == 0x0) && (instr->Opc3Value() & 0x1)) { 1440 if (instr->SzValue() == 0x1) { 1441 Format(instr, "vmls'cond.f64 'Dd, 'Dn, 'Dm"); 1442 } else { 1443 Format(instr, "vmls'cond.f32 'Sd, 'Sn, 'Sm"); 1444 } 1445 } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) { 1446 if (instr->SzValue() == 0x1) { 1447 Format(instr, "vdiv'cond.f64 'Dd, 'Dn, 'Dm"); 1448 } else { 1449 Format(instr, "vdiv'cond.f32 'Sd, 'Sn, 'Sm"); 1450 } 1451 } else { 1452 Unknown(instr); // Not used by V8. 1453 } 1454 } else { 1455 if ((instr->VCValue() == 0x0) && 1456 (instr->VAValue() == 0x0)) { 1457 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); 1458 } else if ((instr->VLValue() == 0x0) && 1459 (instr->VCValue() == 0x1) && 1460 (instr->Bit(23) == 0x0)) { 1461 if (instr->Bit(21) == 0x0) { 1462 Format(instr, "vmov'cond.32 'Dd[0], 'rt"); 1463 } else { 1464 Format(instr, "vmov'cond.32 'Dd[1], 'rt"); 1465 } 1466 } else if ((instr->VLValue() == 0x1) && 1467 (instr->VCValue() == 0x1) && 1468 (instr->Bit(23) == 0x0)) { 1469 if (instr->Bit(21) == 0x0) { 1470 Format(instr, "vmov'cond.32 'rt, 'Dd[0]"); 1471 } else { 1472 Format(instr, "vmov'cond.32 'rt, 'Dd[1]"); 1473 } 1474 } else if ((instr->VCValue() == 0x0) && 1475 (instr->VAValue() == 0x7) && 1476 (instr->Bits(19, 16) == 0x1)) { 1477 if (instr->VLValue() == 0) { 1478 if (instr->Bits(15, 12) == 0xF) { 1479 Format(instr, "vmsr'cond FPSCR, APSR"); 1480 } else { 1481 Format(instr, "vmsr'cond FPSCR, 'rt"); 1482 } 1483 } else { 1484 if (instr->Bits(15, 12) == 0xF) { 1485 Format(instr, "vmrs'cond APSR, FPSCR"); 1486 } else { 1487 Format(instr, "vmrs'cond 'rt, FPSCR"); 1488 } 1489 } 1490 } 1491 } 1492 } 1493 1494 1495 void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters( 1496 Instruction* instr) { 1497 VERIFY((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) && 1498 (instr->VAValue() == 0x0)); 1499 1500 bool to_arm_register = (instr->VLValue() == 0x1); 1501 1502 if (to_arm_register) { 1503 Format(instr, "vmov'cond 'rt, 'Sn"); 1504 } else { 1505 Format(instr, "vmov'cond 'Sn, 'rt"); 1506 } 1507 } 1508 1509 1510 void Decoder::DecodeVCMP(Instruction* instr) { 1511 VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 1512 VERIFY(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && 1513 (instr->Opc3Value() & 0x1)); 1514 1515 // Comparison. 1516 bool dp_operation = (instr->SzValue() == 1); 1517 bool raise_exception_for_qnan = (instr->Bit(7) == 0x1); 1518 1519 if (dp_operation && !raise_exception_for_qnan) { 1520 if (instr->Opc2Value() == 0x4) { 1521 Format(instr, "vcmp'cond.f64 'Dd, 'Dm"); 1522 } else if (instr->Opc2Value() == 0x5) { 1523 Format(instr, "vcmp'cond.f64 'Dd, #0.0"); 1524 } else { 1525 Unknown(instr); // invalid 1526 } 1527 } else if (!raise_exception_for_qnan) { 1528 if (instr->Opc2Value() == 0x4) { 1529 Format(instr, "vcmp'cond.f32 'Sd, 'Sm"); 1530 } else if (instr->Opc2Value() == 0x5) { 1531 Format(instr, "vcmp'cond.f32 'Sd, #0.0"); 1532 } else { 1533 Unknown(instr); // invalid 1534 } 1535 } else { 1536 Unknown(instr); // Not used by V8. 1537 } 1538 } 1539 1540 1541 void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) { 1542 VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 1543 VERIFY((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)); 1544 1545 bool double_to_single = (instr->SzValue() == 1); 1546 1547 if (double_to_single) { 1548 Format(instr, "vcvt'cond.f32.f64 'Sd, 'Dm"); 1549 } else { 1550 Format(instr, "vcvt'cond.f64.f32 'Dd, 'Sm"); 1551 } 1552 } 1553 1554 1555 void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) { 1556 VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 1557 VERIFY(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) || 1558 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1))); 1559 1560 bool to_integer = (instr->Bit(18) == 1); 1561 bool dp_operation = (instr->SzValue() == 1); 1562 if (to_integer) { 1563 bool unsigned_integer = (instr->Bit(16) == 0); 1564 1565 if (dp_operation) { 1566 if (unsigned_integer) { 1567 Format(instr, "vcvt'cond.u32.f64 'Sd, 'Dm"); 1568 } else { 1569 Format(instr, "vcvt'cond.s32.f64 'Sd, 'Dm"); 1570 } 1571 } else { 1572 if (unsigned_integer) { 1573 Format(instr, "vcvt'cond.u32.f32 'Sd, 'Sm"); 1574 } else { 1575 Format(instr, "vcvt'cond.s32.f32 'Sd, 'Sm"); 1576 } 1577 } 1578 } else { 1579 bool unsigned_integer = (instr->Bit(7) == 0); 1580 1581 if (dp_operation) { 1582 if (unsigned_integer) { 1583 Format(instr, "vcvt'cond.f64.u32 'Dd, 'Sm"); 1584 } else { 1585 Format(instr, "vcvt'cond.f64.s32 'Dd, 'Sm"); 1586 } 1587 } else { 1588 if (unsigned_integer) { 1589 Format(instr, "vcvt'cond.f32.u32 'Sd, 'Sm"); 1590 } else { 1591 Format(instr, "vcvt'cond.f32.s32 'Sd, 'Sm"); 1592 } 1593 } 1594 } 1595 } 1596 1597 1598 // Decode Type 6 coprocessor instructions. 1599 // Dm = vmov(Rt, Rt2) 1600 // <Rt, Rt2> = vmov(Dm) 1601 // Ddst = MEM(Rbase + 4*offset). 1602 // MEM(Rbase + 4*offset) = Dsrc. 1603 void Decoder::DecodeType6CoprocessorIns(Instruction* instr) { 1604 VERIFY(instr->TypeValue() == 6); 1605 1606 if (instr->CoprocessorValue() == 0xA) { 1607 switch (instr->OpcodeValue()) { 1608 case 0x8: 1609 case 0xA: 1610 if (instr->HasL()) { 1611 Format(instr, "vldr'cond 'Sd, ['rn - 4*'imm08@00]"); 1612 } else { 1613 Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]"); 1614 } 1615 break; 1616 case 0xC: 1617 case 0xE: 1618 if (instr->HasL()) { 1619 Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]"); 1620 } else { 1621 Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]"); 1622 } 1623 break; 1624 case 0x4: 1625 case 0x5: 1626 case 0x6: 1627 case 0x7: 1628 case 0x9: 1629 case 0xB: { 1630 bool to_vfp_register = (instr->VLValue() == 0x1); 1631 if (to_vfp_register) { 1632 Format(instr, "vldm'cond'pu 'rn'w, {'Sd-'Sd+}"); 1633 } else { 1634 Format(instr, "vstm'cond'pu 'rn'w, {'Sd-'Sd+}"); 1635 } 1636 break; 1637 } 1638 default: 1639 Unknown(instr); // Not used by V8. 1640 } 1641 } else if (instr->CoprocessorValue() == 0xB) { 1642 switch (instr->OpcodeValue()) { 1643 case 0x2: 1644 // Load and store double to two GP registers 1645 if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) { 1646 Unknown(instr); // Not used by V8. 1647 } else if (instr->HasL()) { 1648 Format(instr, "vmov'cond 'rt, 'rn, 'Dm"); 1649 } else { 1650 Format(instr, "vmov'cond 'Dm, 'rt, 'rn"); 1651 } 1652 break; 1653 case 0x8: 1654 case 0xA: 1655 if (instr->HasL()) { 1656 Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]"); 1657 } else { 1658 Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]"); 1659 } 1660 break; 1661 case 0xC: 1662 case 0xE: 1663 if (instr->HasL()) { 1664 Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]"); 1665 } else { 1666 Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]"); 1667 } 1668 break; 1669 case 0x4: 1670 case 0x5: 1671 case 0x6: 1672 case 0x7: 1673 case 0x9: 1674 case 0xB: { 1675 bool to_vfp_register = (instr->VLValue() == 0x1); 1676 if (to_vfp_register) { 1677 Format(instr, "vldm'cond'pu 'rn'w, {'Dd-'Dd+}"); 1678 } else { 1679 Format(instr, "vstm'cond'pu 'rn'w, {'Dd-'Dd+}"); 1680 } 1681 break; 1682 } 1683 default: 1684 Unknown(instr); // Not used by V8. 1685 } 1686 } else { 1687 Unknown(instr); // Not used by V8. 1688 } 1689 } 1690 1691 1692 void Decoder::DecodeSpecialCondition(Instruction* instr) { 1693 switch (instr->SpecialValue()) { 1694 case 5: 1695 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && 1696 (instr->Bit(4) == 1)) { 1697 // vmovl signed 1698 if ((instr->VdValue() & 1) != 0) Unknown(instr); 1699 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1); 1700 int Vm = (instr->Bit(5) << 4) | instr->VmValue(); 1701 int imm3 = instr->Bits(21, 19); 1702 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1703 "vmovl.s%d q%d, d%d", imm3*8, Vd, Vm); 1704 } else { 1705 Unknown(instr); 1706 } 1707 break; 1708 case 7: 1709 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && 1710 (instr->Bit(4) == 1)) { 1711 // vmovl unsigned 1712 if ((instr->VdValue() & 1) != 0) Unknown(instr); 1713 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1); 1714 int Vm = (instr->Bit(5) << 4) | instr->VmValue(); 1715 int imm3 = instr->Bits(21, 19); 1716 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1717 "vmovl.u%d q%d, d%d", imm3*8, Vd, Vm); 1718 } else { 1719 Unknown(instr); 1720 } 1721 break; 1722 case 8: 1723 if (instr->Bits(21, 20) == 0) { 1724 // vst1 1725 int Vd = (instr->Bit(22) << 4) | instr->VdValue(); 1726 int Rn = instr->VnValue(); 1727 int type = instr->Bits(11, 8); 1728 int size = instr->Bits(7, 6); 1729 int align = instr->Bits(5, 4); 1730 int Rm = instr->VmValue(); 1731 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1732 "vst1.%d ", (1 << size) << 3); 1733 FormatNeonList(Vd, type); 1734 Print(", "); 1735 FormatNeonMemory(Rn, align, Rm); 1736 } else if (instr->Bits(21, 20) == 2) { 1737 // vld1 1738 int Vd = (instr->Bit(22) << 4) | instr->VdValue(); 1739 int Rn = instr->VnValue(); 1740 int type = instr->Bits(11, 8); 1741 int size = instr->Bits(7, 6); 1742 int align = instr->Bits(5, 4); 1743 int Rm = instr->VmValue(); 1744 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1745 "vld1.%d ", (1 << size) << 3); 1746 FormatNeonList(Vd, type); 1747 Print(", "); 1748 FormatNeonMemory(Rn, align, Rm); 1749 } else { 1750 Unknown(instr); 1751 } 1752 break; 1753 case 0xA: 1754 case 0xB: 1755 if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) { 1756 int Rn = instr->Bits(19, 16); 1757 int offset = instr->Bits(11, 0); 1758 if (offset == 0) { 1759 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1760 "pld [r%d]", Rn); 1761 } else if (instr->Bit(23) == 0) { 1762 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1763 "pld [r%d, #-%d]", Rn, offset); 1764 } else { 1765 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1766 "pld [r%d, #+%d]", Rn, offset); 1767 } 1768 } else { 1769 Unknown(instr); 1770 } 1771 break; 1772 case 0x1D: 1773 if (instr->Opc1Value() == 0x7 && instr->Bits(19, 18) == 0x2 && 1774 instr->Bits(11, 9) == 0x5 && instr->Bits(7, 6) == 0x1 && 1775 instr->Bit(4) == 0x0) { 1776 // VRINTA, VRINTN, VRINTP, VRINTM (floating-point) 1777 bool dp_operation = (instr->SzValue() == 1); 1778 int rounding_mode = instr->Bits(17, 16); 1779 switch (rounding_mode) { 1780 case 0x0: 1781 if (dp_operation) { 1782 Format(instr, "vrinta.f64.f64 'Dd, 'Dm"); 1783 } else { 1784 Format(instr, "vrinta.f32.f32 'Sd, 'Sm"); 1785 } 1786 break; 1787 case 0x1: 1788 if (dp_operation) { 1789 Format(instr, "vrintn.f64.f64 'Dd, 'Dm"); 1790 } else { 1791 Format(instr, "vrintn.f32.f32 'Sd, 'Sm"); 1792 } 1793 break; 1794 case 0x2: 1795 if (dp_operation) { 1796 Format(instr, "vrintp.f64.f64 'Dd, 'Dm"); 1797 } else { 1798 Format(instr, "vrintp.f32.f32 'Sd, 'Sm"); 1799 } 1800 break; 1801 case 0x3: 1802 if (dp_operation) { 1803 Format(instr, "vrintm.f64.f64 'Dd, 'Dm"); 1804 } else { 1805 Format(instr, "vrintm.f32.f32 'Sd, 'Sm"); 1806 } 1807 break; 1808 default: 1809 UNREACHABLE(); // Case analysis is exhaustive. 1810 break; 1811 } 1812 } else { 1813 Unknown(instr); 1814 } 1815 break; 1816 default: 1817 Unknown(instr); 1818 break; 1819 } 1820 } 1821 1822 #undef VERIFIY 1823 1824 bool Decoder::IsConstantPoolAt(byte* instr_ptr) { 1825 int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); 1826 return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker; 1827 } 1828 1829 1830 int Decoder::ConstantPoolSizeAt(byte* instr_ptr) { 1831 if (IsConstantPoolAt(instr_ptr)) { 1832 int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); 1833 return DecodeConstantPoolLength(instruction_bits); 1834 } else { 1835 return -1; 1836 } 1837 } 1838 1839 1840 // Disassemble the instruction at *instr_ptr into the output buffer. 1841 int Decoder::InstructionDecode(byte* instr_ptr) { 1842 Instruction* instr = Instruction::At(instr_ptr); 1843 // Print raw instruction bytes. 1844 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1845 "%08x ", 1846 instr->InstructionBits()); 1847 if (instr->ConditionField() == kSpecialCondition) { 1848 DecodeSpecialCondition(instr); 1849 return Instruction::kInstrSize; 1850 } 1851 int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); 1852 if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) { 1853 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1854 "constant pool begin (length %d)", 1855 DecodeConstantPoolLength(instruction_bits)); 1856 return Instruction::kInstrSize; 1857 } else if (instruction_bits == kCodeAgeJumpInstruction) { 1858 // The code age prologue has a constant immediatly following the jump 1859 // instruction. 1860 Instruction* target = Instruction::At(instr_ptr + Instruction::kInstrSize); 1861 DecodeType2(instr); 1862 SNPrintF(out_buffer_ + out_buffer_pos_, 1863 " (0x%08x)", target->InstructionBits()); 1864 return 2 * Instruction::kInstrSize; 1865 } 1866 switch (instr->TypeValue()) { 1867 case 0: 1868 case 1: { 1869 DecodeType01(instr); 1870 break; 1871 } 1872 case 2: { 1873 DecodeType2(instr); 1874 break; 1875 } 1876 case 3: { 1877 DecodeType3(instr); 1878 break; 1879 } 1880 case 4: { 1881 DecodeType4(instr); 1882 break; 1883 } 1884 case 5: { 1885 DecodeType5(instr); 1886 break; 1887 } 1888 case 6: { 1889 DecodeType6(instr); 1890 break; 1891 } 1892 case 7: { 1893 return DecodeType7(instr); 1894 } 1895 default: { 1896 // The type field is 3-bits in the ARM encoding. 1897 UNREACHABLE(); 1898 break; 1899 } 1900 } 1901 return Instruction::kInstrSize; 1902 } 1903 1904 1905 } // namespace internal 1906 } // namespace v8 1907 1908 1909 //------------------------------------------------------------------------------ 1910 1911 namespace disasm { 1912 1913 1914 const char* NameConverter::NameOfAddress(byte* addr) const { 1915 v8::internal::SNPrintF(tmp_buffer_, "%p", addr); 1916 return tmp_buffer_.start(); 1917 } 1918 1919 1920 const char* NameConverter::NameOfConstant(byte* addr) const { 1921 return NameOfAddress(addr); 1922 } 1923 1924 1925 const char* NameConverter::NameOfCPURegister(int reg) const { 1926 return v8::internal::Register::from_code(reg).ToString(); 1927 } 1928 1929 1930 const char* NameConverter::NameOfByteCPURegister(int reg) const { 1931 UNREACHABLE(); // ARM does not have the concept of a byte register 1932 return "nobytereg"; 1933 } 1934 1935 1936 const char* NameConverter::NameOfXMMRegister(int reg) const { 1937 UNREACHABLE(); // ARM does not have any XMM registers 1938 return "noxmmreg"; 1939 } 1940 1941 1942 const char* NameConverter::NameInCode(byte* addr) const { 1943 // The default name converter is called for unknown code. So we will not try 1944 // to access any memory. 1945 return ""; 1946 } 1947 1948 1949 //------------------------------------------------------------------------------ 1950 1951 Disassembler::Disassembler(const NameConverter& converter) 1952 : converter_(converter) {} 1953 1954 1955 Disassembler::~Disassembler() {} 1956 1957 1958 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, 1959 byte* instruction) { 1960 v8::internal::Decoder d(converter_, buffer); 1961 return d.InstructionDecode(instruction); 1962 } 1963 1964 1965 int Disassembler::ConstantPoolSizeAt(byte* instruction) { 1966 return v8::internal::Decoder::ConstantPoolSizeAt(instruction); 1967 } 1968 1969 1970 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { 1971 NameConverter converter; 1972 Disassembler d(converter); 1973 for (byte* pc = begin; pc < end;) { 1974 v8::internal::EmbeddedVector<char, 128> buffer; 1975 buffer[0] = '\0'; 1976 byte* prev_pc = pc; 1977 pc += d.InstructionDecode(buffer, pc); 1978 v8::internal::PrintF( 1979 f, "%p %08x %s\n", 1980 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); 1981 } 1982 } 1983 1984 1985 } // namespace disasm 1986 1987 #endif // V8_TARGET_ARCH_ARM 1988