disasm-arm.cc revision 3b9bc31999c9787eb726ecdbfd5796bfdec32a18
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 40namespace v8 { 41namespace 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. 49class 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. 132void Decoder::PrintChar(const char ch) { 133 out_buffer_[out_buffer_pos_++] = ch; 134} 135 136 137// Append the str to the output buffer. 138void 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>". 150static 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. 157void Decoder::PrintCondition(Instruction* instr) { 158 Print(cond_names[instr->ConditionValue()]); 159} 160 161 162// Print the register name according to the active name converter. 163void 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. 169void 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. 175void 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>". 182static 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. 189void 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. 225void 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. 234void 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. 246void 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. 274void 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. 300int 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. 349int 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 392int Decoder::FormatVFPinstruction(Instruction* instr, const char* format) { 393 Print(format); 394 return 0; 395} 396 397 398void 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 415void 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. 434void 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. 447int 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 } else if (format[1] == 'p') { 608 if (format[8] == '_') { // 'spec_reg_fields 609 DCHECK(STRING_STARTS_WITH(format, "spec_reg_fields")); 610 Print("_"); 611 int mask = instr->Bits(19, 16); 612 if (mask == 0) Print("(none)"); 613 if ((mask & 0x8) != 0) Print("f"); 614 if ((mask & 0x4) != 0) Print("s"); 615 if ((mask & 0x2) != 0) Print("x"); 616 if ((mask & 0x1) != 0) Print("c"); 617 return 15; 618 } else { // 'spec_reg 619 DCHECK(STRING_STARTS_WITH(format, "spec_reg")); 620 if (instr->Bit(22) == 0) { 621 Print("CPSR"); 622 } else { 623 Print("SPSR"); 624 } 625 return 8; 626 } 627 } 628 // 's: S field of data processing instructions 629 if (instr->HasS()) { 630 Print("s"); 631 } 632 return 1; 633 } 634 case 't': { // 'target: target of branch instructions 635 DCHECK(STRING_STARTS_WITH(format, "target")); 636 int off = (instr->SImmed24Value() << 2) + 8; 637 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 638 "%+d -> %s", 639 off, 640 converter_.NameOfAddress( 641 reinterpret_cast<byte*>(instr) + off)); 642 return 6; 643 } 644 case 'u': { // 'u: signed or unsigned multiplies 645 // The manual gets the meaning of bit 22 backwards in the multiply 646 // instruction overview on page A3.16.2. The instructions that 647 // exist in u and s variants are the following: 648 // smull A4.1.87 649 // umull A4.1.129 650 // umlal A4.1.128 651 // smlal A4.1.76 652 // For these 0 means u and 1 means s. As can be seen on their individual 653 // pages. The other 18 mul instructions have the bit set or unset in 654 // arbitrary ways that are unrelated to the signedness of the instruction. 655 // None of these 18 instructions exist in both a 'u' and an 's' variant. 656 657 if (instr->Bit(22) == 0) { 658 Print("u"); 659 } else { 660 Print("s"); 661 } 662 return 1; 663 } 664 case 'v': { 665 return FormatVFPinstruction(instr, format); 666 } 667 case 'S': 668 case 'D': { 669 return FormatVFPRegister(instr, format); 670 } 671 case 'w': { // 'w: W field of load and store instructions 672 if (instr->HasW()) { 673 Print("!"); 674 } 675 return 1; 676 } 677 default: { 678 UNREACHABLE(); 679 break; 680 } 681 } 682 UNREACHABLE(); 683 return -1; 684} 685 686 687// Format takes a formatting string for a whole instruction and prints it into 688// the output buffer. All escaped options are handed to FormatOption to be 689// parsed further. 690void Decoder::Format(Instruction* instr, const char* format) { 691 char cur = *format++; 692 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 693 if (cur == '\'') { // Single quote is used as the formatting escape. 694 format += FormatOption(instr, format); 695 } else { 696 out_buffer_[out_buffer_pos_++] = cur; 697 } 698 cur = *format++; 699 } 700 out_buffer_[out_buffer_pos_] = '\0'; 701} 702 703 704// The disassembler may end up decoding data inlined in the code. We do not want 705// it to crash if the data does not ressemble any known instruction. 706#define VERIFY(condition) \ 707if(!(condition)) { \ 708 Unknown(instr); \ 709 return; \ 710} 711 712 713// For currently unimplemented decodings the disassembler calls Unknown(instr) 714// which will just print "unknown" of the instruction bits. 715void Decoder::Unknown(Instruction* instr) { 716 Format(instr, "unknown"); 717} 718 719 720void Decoder::DecodeType01(Instruction* instr) { 721 int type = instr->TypeValue(); 722 if ((type == 0) && instr->IsSpecialType0()) { 723 // multiply instruction or extra loads and stores 724 if (instr->Bits(7, 4) == 9) { 725 if (instr->Bit(24) == 0) { 726 // multiply instructions 727 if (instr->Bit(23) == 0) { 728 if (instr->Bit(21) == 0) { 729 // The MUL instruction description (A 4.1.33) refers to Rd as being 730 // the destination for the operation, but it confusingly uses the 731 // Rn field to encode it. 732 Format(instr, "mul'cond's 'rn, 'rm, 'rs"); 733 } else { 734 if (instr->Bit(22) == 0) { 735 // The MLA instruction description (A 4.1.28) refers to the order 736 // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the 737 // Rn field to encode the Rd register and the Rd field to encode 738 // the Rn register. 739 Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd"); 740 } else { 741 // The MLS instruction description (A 4.1.29) refers to the order 742 // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the 743 // Rn field to encode the Rd register and the Rd field to encode 744 // the Rn register. 745 Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd"); 746 } 747 } 748 } else { 749 // The signed/long multiply instructions use the terms RdHi and RdLo 750 // when referring to the target registers. They are mapped to the Rn 751 // and Rd fields as follows: 752 // RdLo == Rd field 753 // RdHi == Rn field 754 // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs> 755 Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs"); 756 } 757 } else { 758 Unknown(instr); // not used by V8 759 } 760 } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xd) == 0xd)) { 761 // ldrd, strd 762 switch (instr->PUField()) { 763 case da_x: { 764 if (instr->Bit(22) == 0) { 765 Format(instr, "'memop'cond's 'rd, ['rn], -'rm"); 766 } else { 767 Format(instr, "'memop'cond's 'rd, ['rn], #-'off8"); 768 } 769 break; 770 } 771 case ia_x: { 772 if (instr->Bit(22) == 0) { 773 Format(instr, "'memop'cond's 'rd, ['rn], +'rm"); 774 } else { 775 Format(instr, "'memop'cond's 'rd, ['rn], #+'off8"); 776 } 777 break; 778 } 779 case db_x: { 780 if (instr->Bit(22) == 0) { 781 Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w"); 782 } else { 783 Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w"); 784 } 785 break; 786 } 787 case ib_x: { 788 if (instr->Bit(22) == 0) { 789 Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w"); 790 } else { 791 Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w"); 792 } 793 break; 794 } 795 default: { 796 // The PU field is a 2-bit field. 797 UNREACHABLE(); 798 break; 799 } 800 } 801 } else { 802 // extra load/store instructions 803 switch (instr->PUField()) { 804 case da_x: { 805 if (instr->Bit(22) == 0) { 806 Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm"); 807 } else { 808 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8"); 809 } 810 break; 811 } 812 case ia_x: { 813 if (instr->Bit(22) == 0) { 814 Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm"); 815 } else { 816 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8"); 817 } 818 break; 819 } 820 case db_x: { 821 if (instr->Bit(22) == 0) { 822 Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w"); 823 } else { 824 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w"); 825 } 826 break; 827 } 828 case ib_x: { 829 if (instr->Bit(22) == 0) { 830 Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w"); 831 } else { 832 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w"); 833 } 834 break; 835 } 836 default: { 837 // The PU field is a 2-bit field. 838 UNREACHABLE(); 839 break; 840 } 841 } 842 return; 843 } 844 } else if ((type == 0) && instr->IsMiscType0()) { 845 if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 2) && 846 (instr->Bits(15, 4) == 0xf00)) { 847 Format(instr, "msr'cond 'spec_reg'spec_reg_fields, 'rm"); 848 } else if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 0) && 849 (instr->Bits(11, 0) == 0)) { 850 Format(instr, "mrs'cond 'rd, 'spec_reg"); 851 } else if (instr->Bits(22, 21) == 1) { 852 switch (instr->BitField(7, 4)) { 853 case BX: 854 Format(instr, "bx'cond 'rm"); 855 break; 856 case BLX: 857 Format(instr, "blx'cond 'rm"); 858 break; 859 case BKPT: 860 Format(instr, "bkpt 'off0to3and8to19"); 861 break; 862 default: 863 Unknown(instr); // not used by V8 864 break; 865 } 866 } else if (instr->Bits(22, 21) == 3) { 867 switch (instr->BitField(7, 4)) { 868 case CLZ: 869 Format(instr, "clz'cond 'rd, 'rm"); 870 break; 871 default: 872 Unknown(instr); // not used by V8 873 break; 874 } 875 } else { 876 Unknown(instr); // not used by V8 877 } 878 } else if ((type == 1) && instr->IsNopType1()) { 879 Format(instr, "nop'cond"); 880 } else { 881 switch (instr->OpcodeField()) { 882 case AND: { 883 Format(instr, "and'cond's 'rd, 'rn, 'shift_op"); 884 break; 885 } 886 case EOR: { 887 Format(instr, "eor'cond's 'rd, 'rn, 'shift_op"); 888 break; 889 } 890 case SUB: { 891 Format(instr, "sub'cond's 'rd, 'rn, 'shift_op"); 892 break; 893 } 894 case RSB: { 895 Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op"); 896 break; 897 } 898 case ADD: { 899 Format(instr, "add'cond's 'rd, 'rn, 'shift_op"); 900 break; 901 } 902 case ADC: { 903 Format(instr, "adc'cond's 'rd, 'rn, 'shift_op"); 904 break; 905 } 906 case SBC: { 907 Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op"); 908 break; 909 } 910 case RSC: { 911 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op"); 912 break; 913 } 914 case TST: { 915 if (instr->HasS()) { 916 Format(instr, "tst'cond 'rn, 'shift_op"); 917 } else { 918 Format(instr, "movw'cond 'mw"); 919 } 920 break; 921 } 922 case TEQ: { 923 if (instr->HasS()) { 924 Format(instr, "teq'cond 'rn, 'shift_op"); 925 } else { 926 // Other instructions matching this pattern are handled in the 927 // miscellaneous instructions part above. 928 UNREACHABLE(); 929 } 930 break; 931 } 932 case CMP: { 933 if (instr->HasS()) { 934 Format(instr, "cmp'cond 'rn, 'shift_op"); 935 } else { 936 Format(instr, "movt'cond 'mw"); 937 } 938 break; 939 } 940 case CMN: { 941 if (instr->HasS()) { 942 Format(instr, "cmn'cond 'rn, 'shift_op"); 943 } else { 944 // Other instructions matching this pattern are handled in the 945 // miscellaneous instructions part above. 946 UNREACHABLE(); 947 } 948 break; 949 } 950 case ORR: { 951 Format(instr, "orr'cond's 'rd, 'rn, 'shift_op"); 952 break; 953 } 954 case MOV: { 955 Format(instr, "mov'cond's 'rd, 'shift_op"); 956 break; 957 } 958 case BIC: { 959 Format(instr, "bic'cond's 'rd, 'rn, 'shift_op"); 960 break; 961 } 962 case MVN: { 963 Format(instr, "mvn'cond's 'rd, 'shift_op"); 964 break; 965 } 966 default: { 967 // The Opcode field is a 4-bit field. 968 UNREACHABLE(); 969 break; 970 } 971 } 972 } 973} 974 975 976void Decoder::DecodeType2(Instruction* instr) { 977 switch (instr->PUField()) { 978 case da_x: { 979 if (instr->HasW()) { 980 Unknown(instr); // not used in V8 981 return; 982 } 983 Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); 984 break; 985 } 986 case ia_x: { 987 if (instr->HasW()) { 988 Unknown(instr); // not used in V8 989 return; 990 } 991 Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12"); 992 break; 993 } 994 case db_x: { 995 Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w"); 996 break; 997 } 998 case ib_x: { 999 Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w"); 1000 break; 1001 } 1002 default: { 1003 // The PU field is a 2-bit field. 1004 UNREACHABLE(); 1005 break; 1006 } 1007 } 1008} 1009 1010 1011void Decoder::DecodeType3(Instruction* instr) { 1012 switch (instr->PUField()) { 1013 case da_x: { 1014 VERIFY(!instr->HasW()); 1015 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); 1016 break; 1017 } 1018 case ia_x: { 1019 if (instr->Bit(4) == 0) { 1020 Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm"); 1021 } else { 1022 if (instr->Bit(5) == 0) { 1023 switch (instr->Bits(22, 21)) { 1024 case 0: 1025 if (instr->Bit(20) == 0) { 1026 if (instr->Bit(6) == 0) { 1027 Format(instr, "pkhbt'cond 'rd, 'rn, 'rm, lsl #'imm05@07"); 1028 } else { 1029 if (instr->Bits(11, 7) == 0) { 1030 Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #32"); 1031 } else { 1032 Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #'imm05@07"); 1033 } 1034 } 1035 } else { 1036 UNREACHABLE(); 1037 } 1038 break; 1039 case 1: 1040 UNREACHABLE(); 1041 break; 1042 case 2: 1043 UNREACHABLE(); 1044 break; 1045 case 3: 1046 Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat"); 1047 break; 1048 } 1049 } else { 1050 switch (instr->Bits(22, 21)) { 1051 case 0: 1052 UNREACHABLE(); 1053 break; 1054 case 1: 1055 if (instr->Bits(9, 6) == 1) { 1056 if (instr->Bit(20) == 0) { 1057 if (instr->Bits(19, 16) == 0xF) { 1058 switch (instr->Bits(11, 10)) { 1059 case 0: 1060 Format(instr, "sxtb'cond 'rd, 'rm"); 1061 break; 1062 case 1: 1063 Format(instr, "sxtb'cond 'rd, 'rm, ror #8"); 1064 break; 1065 case 2: 1066 Format(instr, "sxtb'cond 'rd, 'rm, ror #16"); 1067 break; 1068 case 3: 1069 Format(instr, "sxtb'cond 'rd, 'rm, ror #24"); 1070 break; 1071 } 1072 } else { 1073 switch (instr->Bits(11, 10)) { 1074 case 0: 1075 Format(instr, "sxtab'cond 'rd, 'rn, 'rm"); 1076 break; 1077 case 1: 1078 Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #8"); 1079 break; 1080 case 2: 1081 Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #16"); 1082 break; 1083 case 3: 1084 Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #24"); 1085 break; 1086 } 1087 } 1088 } else { 1089 if (instr->Bits(19, 16) == 0xF) { 1090 switch (instr->Bits(11, 10)) { 1091 case 0: 1092 Format(instr, "sxth'cond 'rd, 'rm"); 1093 break; 1094 case 1: 1095 Format(instr, "sxth'cond 'rd, 'rm, ror #8"); 1096 break; 1097 case 2: 1098 Format(instr, "sxth'cond 'rd, 'rm, ror #16"); 1099 break; 1100 case 3: 1101 Format(instr, "sxth'cond 'rd, 'rm, ror #24"); 1102 break; 1103 } 1104 } else { 1105 switch (instr->Bits(11, 10)) { 1106 case 0: 1107 Format(instr, "sxtah'cond 'rd, 'rn, 'rm"); 1108 break; 1109 case 1: 1110 Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #8"); 1111 break; 1112 case 2: 1113 Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #16"); 1114 break; 1115 case 3: 1116 Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #24"); 1117 break; 1118 } 1119 } 1120 } 1121 } else { 1122 UNREACHABLE(); 1123 } 1124 break; 1125 case 2: 1126 if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) { 1127 if (instr->Bits(19, 16) == 0xF) { 1128 switch (instr->Bits(11, 10)) { 1129 case 0: 1130 Format(instr, "uxtb16'cond 'rd, 'rm"); 1131 break; 1132 case 1: 1133 Format(instr, "uxtb16'cond 'rd, 'rm, ror #8"); 1134 break; 1135 case 2: 1136 Format(instr, "uxtb16'cond 'rd, 'rm, ror #16"); 1137 break; 1138 case 3: 1139 Format(instr, "uxtb16'cond 'rd, 'rm, ror #24"); 1140 break; 1141 } 1142 } else { 1143 UNREACHABLE(); 1144 } 1145 } else { 1146 UNREACHABLE(); 1147 } 1148 break; 1149 case 3: 1150 if ((instr->Bits(9, 6) == 1)) { 1151 if ((instr->Bit(20) == 0)) { 1152 if (instr->Bits(19, 16) == 0xF) { 1153 switch (instr->Bits(11, 10)) { 1154 case 0: 1155 Format(instr, "uxtb'cond 'rd, 'rm"); 1156 break; 1157 case 1: 1158 Format(instr, "uxtb'cond 'rd, 'rm, ror #8"); 1159 break; 1160 case 2: 1161 Format(instr, "uxtb'cond 'rd, 'rm, ror #16"); 1162 break; 1163 case 3: 1164 Format(instr, "uxtb'cond 'rd, 'rm, ror #24"); 1165 break; 1166 } 1167 } else { 1168 switch (instr->Bits(11, 10)) { 1169 case 0: 1170 Format(instr, "uxtab'cond 'rd, 'rn, 'rm"); 1171 break; 1172 case 1: 1173 Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #8"); 1174 break; 1175 case 2: 1176 Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #16"); 1177 break; 1178 case 3: 1179 Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #24"); 1180 break; 1181 } 1182 } 1183 } else { 1184 if (instr->Bits(19, 16) == 0xF) { 1185 switch (instr->Bits(11, 10)) { 1186 case 0: 1187 Format(instr, "uxth'cond 'rd, 'rm"); 1188 break; 1189 case 1: 1190 Format(instr, "uxth'cond 'rd, 'rm, ror #8"); 1191 break; 1192 case 2: 1193 Format(instr, "uxth'cond 'rd, 'rm, ror #16"); 1194 break; 1195 case 3: 1196 Format(instr, "uxth'cond 'rd, 'rm, ror #24"); 1197 break; 1198 } 1199 } else { 1200 switch (instr->Bits(11, 10)) { 1201 case 0: 1202 Format(instr, "uxtah'cond 'rd, 'rn, 'rm"); 1203 break; 1204 case 1: 1205 Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #8"); 1206 break; 1207 case 2: 1208 Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #16"); 1209 break; 1210 case 3: 1211 Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #24"); 1212 break; 1213 } 1214 } 1215 } 1216 } else { 1217 // PU == 0b01, BW == 0b11, Bits(9, 6) != 0b0001 1218 if ((instr->Bits(20, 16) == 0x1f) && 1219 (instr->Bits(11, 4) == 0xf3)) { 1220 Format(instr, "rbit'cond 'rd, 'rm"); 1221 } else { 1222 UNREACHABLE(); 1223 } 1224 } 1225 break; 1226 } 1227 } 1228 } 1229 break; 1230 } 1231 case db_x: { 1232 if (instr->Bits(22, 20) == 0x5) { 1233 if (instr->Bits(7, 4) == 0x1) { 1234 if (instr->Bits(15, 12) == 0xF) { 1235 Format(instr, "smmul'cond 'rn, 'rm, 'rs"); 1236 } else { 1237 // SMMLA (in V8 notation matching ARM ISA format) 1238 Format(instr, "smmla'cond 'rn, 'rm, 'rs, 'rd"); 1239 } 1240 break; 1241 } 1242 } 1243 if (FLAG_enable_sudiv) { 1244 if (instr->Bits(5, 4) == 0x1) { 1245 if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) { 1246 if (instr->Bit(21) == 0x1) { 1247 // UDIV (in V8 notation matching ARM ISA format) rn = rm/rs 1248 Format(instr, "udiv'cond'b 'rn, 'rm, 'rs"); 1249 } else { 1250 // SDIV (in V8 notation matching ARM ISA format) rn = rm/rs 1251 Format(instr, "sdiv'cond'b 'rn, 'rm, 'rs"); 1252 } 1253 break; 1254 } 1255 } 1256 } 1257 Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w"); 1258 break; 1259 } 1260 case ib_x: { 1261 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) { 1262 uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16)); 1263 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); 1264 uint32_t msbit = widthminus1 + lsbit; 1265 if (msbit <= 31) { 1266 if (instr->Bit(22)) { 1267 Format(instr, "ubfx'cond 'rd, 'rm, 'f"); 1268 } else { 1269 Format(instr, "sbfx'cond 'rd, 'rm, 'f"); 1270 } 1271 } else { 1272 UNREACHABLE(); 1273 } 1274 } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) { 1275 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); 1276 uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16)); 1277 if (msbit >= lsbit) { 1278 if (instr->RmValue() == 15) { 1279 Format(instr, "bfc'cond 'rd, 'f"); 1280 } else { 1281 Format(instr, "bfi'cond 'rd, 'rm, 'f"); 1282 } 1283 } else { 1284 UNREACHABLE(); 1285 } 1286 } else { 1287 Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w"); 1288 } 1289 break; 1290 } 1291 default: { 1292 // The PU field is a 2-bit field. 1293 UNREACHABLE(); 1294 break; 1295 } 1296 } 1297} 1298 1299 1300void Decoder::DecodeType4(Instruction* instr) { 1301 if (instr->Bit(22) != 0) { 1302 // Privileged mode currently not supported. 1303 Unknown(instr); 1304 } else { 1305 if (instr->HasL()) { 1306 Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); 1307 } else { 1308 Format(instr, "stm'cond'pu 'rn'w, 'rlist"); 1309 } 1310 } 1311} 1312 1313 1314void Decoder::DecodeType5(Instruction* instr) { 1315 Format(instr, "b'l'cond 'target"); 1316} 1317 1318 1319void Decoder::DecodeType6(Instruction* instr) { 1320 DecodeType6CoprocessorIns(instr); 1321} 1322 1323 1324int Decoder::DecodeType7(Instruction* instr) { 1325 if (instr->Bit(24) == 1) { 1326 if (instr->SvcValue() >= kStopCode) { 1327 Format(instr, "stop'cond 'svc"); 1328 // Also print the stop message. Its address is encoded 1329 // in the following 4 bytes. 1330 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1331 "\n %p %08x stop message: %s", 1332 reinterpret_cast<void*>(instr 1333 + Instruction::kInstrSize), 1334 *reinterpret_cast<uint32_t*>(instr 1335 + Instruction::kInstrSize), 1336 *reinterpret_cast<char**>(instr 1337 + Instruction::kInstrSize)); 1338 // We have decoded 2 * Instruction::kInstrSize bytes. 1339 return 2 * Instruction::kInstrSize; 1340 } else { 1341 Format(instr, "svc'cond 'svc"); 1342 } 1343 } else { 1344 DecodeTypeVFP(instr); 1345 } 1346 return Instruction::kInstrSize; 1347} 1348 1349 1350// void Decoder::DecodeTypeVFP(Instruction* instr) 1351// vmov: Sn = Rt 1352// vmov: Rt = Sn 1353// vcvt: Dd = Sm 1354// vcvt: Sd = Dm 1355// vcvt.f64.s32 Dd, Dd, #<fbits> 1356// Dd = vabs(Dm) 1357// Sd = vabs(Sm) 1358// Dd = vneg(Dm) 1359// Sd = vneg(Sm) 1360// Dd = vadd(Dn, Dm) 1361// Sd = vadd(Sn, Sm) 1362// Dd = vsub(Dn, Dm) 1363// Sd = vsub(Sn, Sm) 1364// Dd = vmul(Dn, Dm) 1365// Sd = vmul(Sn, Sm) 1366// Dd = vmla(Dn, Dm) 1367// Sd = vmla(Sn, Sm) 1368// Dd = vmls(Dn, Dm) 1369// Sd = vmls(Sn, Sm) 1370// Dd = vdiv(Dn, Dm) 1371// Sd = vdiv(Sn, Sm) 1372// vcmp(Dd, Dm) 1373// vcmp(Sd, Sm) 1374// Dd = vsqrt(Dm) 1375// Sd = vsqrt(Sm) 1376// vmrs 1377// vmsr 1378void Decoder::DecodeTypeVFP(Instruction* instr) { 1379 VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) ); 1380 VERIFY(instr->Bits(11, 9) == 0x5); 1381 1382 if (instr->Bit(4) == 0) { 1383 if (instr->Opc1Value() == 0x7) { 1384 // Other data processing instructions 1385 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) { 1386 // vmov register to register. 1387 if (instr->SzValue() == 0x1) { 1388 Format(instr, "vmov'cond.f64 'Dd, 'Dm"); 1389 } else { 1390 Format(instr, "vmov'cond.f32 'Sd, 'Sm"); 1391 } 1392 } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) { 1393 // vabs 1394 if (instr->SzValue() == 0x1) { 1395 Format(instr, "vabs'cond.f64 'Dd, 'Dm"); 1396 } else { 1397 Format(instr, "vabs'cond.f32 'Sd, 'Sm"); 1398 } 1399 } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) { 1400 // vneg 1401 if (instr->SzValue() == 0x1) { 1402 Format(instr, "vneg'cond.f64 'Dd, 'Dm"); 1403 } else { 1404 Format(instr, "vneg'cond.f32 'Sd, 'Sm"); 1405 } 1406 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { 1407 DecodeVCVTBetweenDoubleAndSingle(instr); 1408 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { 1409 DecodeVCVTBetweenFloatingPointAndInteger(instr); 1410 } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) && 1411 (instr->Bit(8) == 1)) { 1412 // vcvt.f64.s32 Dd, Dd, #<fbits> 1413 int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5)); 1414 Format(instr, "vcvt'cond.f64.s32 'Dd, 'Dd"); 1415 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1416 ", #%d", fraction_bits); 1417 } else if (((instr->Opc2Value() >> 1) == 0x6) && 1418 (instr->Opc3Value() & 0x1)) { 1419 DecodeVCVTBetweenFloatingPointAndInteger(instr); 1420 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && 1421 (instr->Opc3Value() & 0x1)) { 1422 DecodeVCMP(instr); 1423 } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) { 1424 if (instr->SzValue() == 0x1) { 1425 Format(instr, "vsqrt'cond.f64 'Dd, 'Dm"); 1426 } else { 1427 Format(instr, "vsqrt'cond.f32 'Sd, 'Sm"); 1428 } 1429 } else if (instr->Opc3Value() == 0x0) { 1430 if (instr->SzValue() == 0x1) { 1431 Format(instr, "vmov'cond.f64 'Dd, 'd"); 1432 } else { 1433 Format(instr, "vmov'cond.f32 'Sd, 'd"); 1434 } 1435 } else if (((instr->Opc2Value() == 0x6)) && instr->Opc3Value() == 0x3) { 1436 // vrintz - round towards zero (truncate) 1437 if (instr->SzValue() == 0x1) { 1438 Format(instr, "vrintz'cond.f64.f64 'Dd, 'Dm"); 1439 } else { 1440 Format(instr, "vrintz'cond.f32.f32 'Sd, 'Sm"); 1441 } 1442 } else { 1443 Unknown(instr); // Not used by V8. 1444 } 1445 } else if (instr->Opc1Value() == 0x3) { 1446 if (instr->SzValue() == 0x1) { 1447 if (instr->Opc3Value() & 0x1) { 1448 Format(instr, "vsub'cond.f64 'Dd, 'Dn, 'Dm"); 1449 } else { 1450 Format(instr, "vadd'cond.f64 'Dd, 'Dn, 'Dm"); 1451 } 1452 } else { 1453 if (instr->Opc3Value() & 0x1) { 1454 Format(instr, "vsub'cond.f32 'Sd, 'Sn, 'Sm"); 1455 } else { 1456 Format(instr, "vadd'cond.f32 'Sd, 'Sn, 'Sm"); 1457 } 1458 } 1459 } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) { 1460 if (instr->SzValue() == 0x1) { 1461 Format(instr, "vmul'cond.f64 'Dd, 'Dn, 'Dm"); 1462 } else { 1463 Format(instr, "vmul'cond.f32 'Sd, 'Sn, 'Sm"); 1464 } 1465 } else if ((instr->Opc1Value() == 0x0) && !(instr->Opc3Value() & 0x1)) { 1466 if (instr->SzValue() == 0x1) { 1467 Format(instr, "vmla'cond.f64 'Dd, 'Dn, 'Dm"); 1468 } else { 1469 Format(instr, "vmla'cond.f32 'Sd, 'Sn, 'Sm"); 1470 } 1471 } else if ((instr->Opc1Value() == 0x0) && (instr->Opc3Value() & 0x1)) { 1472 if (instr->SzValue() == 0x1) { 1473 Format(instr, "vmls'cond.f64 'Dd, 'Dn, 'Dm"); 1474 } else { 1475 Format(instr, "vmls'cond.f32 'Sd, 'Sn, 'Sm"); 1476 } 1477 } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) { 1478 if (instr->SzValue() == 0x1) { 1479 Format(instr, "vdiv'cond.f64 'Dd, 'Dn, 'Dm"); 1480 } else { 1481 Format(instr, "vdiv'cond.f32 'Sd, 'Sn, 'Sm"); 1482 } 1483 } else { 1484 Unknown(instr); // Not used by V8. 1485 } 1486 } else { 1487 if ((instr->VCValue() == 0x0) && 1488 (instr->VAValue() == 0x0)) { 1489 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); 1490 } else if ((instr->VLValue() == 0x0) && 1491 (instr->VCValue() == 0x1) && 1492 (instr->Bit(23) == 0x0)) { 1493 if (instr->Bit(21) == 0x0) { 1494 Format(instr, "vmov'cond.32 'Dd[0], 'rt"); 1495 } else { 1496 Format(instr, "vmov'cond.32 'Dd[1], 'rt"); 1497 } 1498 } else if ((instr->VLValue() == 0x1) && 1499 (instr->VCValue() == 0x1) && 1500 (instr->Bit(23) == 0x0)) { 1501 if (instr->Bit(21) == 0x0) { 1502 Format(instr, "vmov'cond.32 'rt, 'Dd[0]"); 1503 } else { 1504 Format(instr, "vmov'cond.32 'rt, 'Dd[1]"); 1505 } 1506 } else if ((instr->VCValue() == 0x0) && 1507 (instr->VAValue() == 0x7) && 1508 (instr->Bits(19, 16) == 0x1)) { 1509 if (instr->VLValue() == 0) { 1510 if (instr->Bits(15, 12) == 0xF) { 1511 Format(instr, "vmsr'cond FPSCR, APSR"); 1512 } else { 1513 Format(instr, "vmsr'cond FPSCR, 'rt"); 1514 } 1515 } else { 1516 if (instr->Bits(15, 12) == 0xF) { 1517 Format(instr, "vmrs'cond APSR, FPSCR"); 1518 } else { 1519 Format(instr, "vmrs'cond 'rt, FPSCR"); 1520 } 1521 } 1522 } 1523 } 1524} 1525 1526 1527void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters( 1528 Instruction* instr) { 1529 VERIFY((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) && 1530 (instr->VAValue() == 0x0)); 1531 1532 bool to_arm_register = (instr->VLValue() == 0x1); 1533 1534 if (to_arm_register) { 1535 Format(instr, "vmov'cond 'rt, 'Sn"); 1536 } else { 1537 Format(instr, "vmov'cond 'Sn, 'rt"); 1538 } 1539} 1540 1541 1542void Decoder::DecodeVCMP(Instruction* instr) { 1543 VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 1544 VERIFY(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && 1545 (instr->Opc3Value() & 0x1)); 1546 1547 // Comparison. 1548 bool dp_operation = (instr->SzValue() == 1); 1549 bool raise_exception_for_qnan = (instr->Bit(7) == 0x1); 1550 1551 if (dp_operation && !raise_exception_for_qnan) { 1552 if (instr->Opc2Value() == 0x4) { 1553 Format(instr, "vcmp'cond.f64 'Dd, 'Dm"); 1554 } else if (instr->Opc2Value() == 0x5) { 1555 Format(instr, "vcmp'cond.f64 'Dd, #0.0"); 1556 } else { 1557 Unknown(instr); // invalid 1558 } 1559 } else if (!raise_exception_for_qnan) { 1560 if (instr->Opc2Value() == 0x4) { 1561 Format(instr, "vcmp'cond.f32 'Sd, 'Sm"); 1562 } else if (instr->Opc2Value() == 0x5) { 1563 Format(instr, "vcmp'cond.f32 'Sd, #0.0"); 1564 } else { 1565 Unknown(instr); // invalid 1566 } 1567 } else { 1568 Unknown(instr); // Not used by V8. 1569 } 1570} 1571 1572 1573void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) { 1574 VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 1575 VERIFY((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)); 1576 1577 bool double_to_single = (instr->SzValue() == 1); 1578 1579 if (double_to_single) { 1580 Format(instr, "vcvt'cond.f32.f64 'Sd, 'Dm"); 1581 } else { 1582 Format(instr, "vcvt'cond.f64.f32 'Dd, 'Sm"); 1583 } 1584} 1585 1586 1587void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) { 1588 VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 1589 VERIFY(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) || 1590 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1))); 1591 1592 bool to_integer = (instr->Bit(18) == 1); 1593 bool dp_operation = (instr->SzValue() == 1); 1594 if (to_integer) { 1595 bool unsigned_integer = (instr->Bit(16) == 0); 1596 1597 if (dp_operation) { 1598 if (unsigned_integer) { 1599 Format(instr, "vcvt'cond.u32.f64 'Sd, 'Dm"); 1600 } else { 1601 Format(instr, "vcvt'cond.s32.f64 'Sd, 'Dm"); 1602 } 1603 } else { 1604 if (unsigned_integer) { 1605 Format(instr, "vcvt'cond.u32.f32 'Sd, 'Sm"); 1606 } else { 1607 Format(instr, "vcvt'cond.s32.f32 'Sd, 'Sm"); 1608 } 1609 } 1610 } else { 1611 bool unsigned_integer = (instr->Bit(7) == 0); 1612 1613 if (dp_operation) { 1614 if (unsigned_integer) { 1615 Format(instr, "vcvt'cond.f64.u32 'Dd, 'Sm"); 1616 } else { 1617 Format(instr, "vcvt'cond.f64.s32 'Dd, 'Sm"); 1618 } 1619 } else { 1620 if (unsigned_integer) { 1621 Format(instr, "vcvt'cond.f32.u32 'Sd, 'Sm"); 1622 } else { 1623 Format(instr, "vcvt'cond.f32.s32 'Sd, 'Sm"); 1624 } 1625 } 1626 } 1627} 1628 1629 1630// Decode Type 6 coprocessor instructions. 1631// Dm = vmov(Rt, Rt2) 1632// <Rt, Rt2> = vmov(Dm) 1633// Ddst = MEM(Rbase + 4*offset). 1634// MEM(Rbase + 4*offset) = Dsrc. 1635void Decoder::DecodeType6CoprocessorIns(Instruction* instr) { 1636 VERIFY(instr->TypeValue() == 6); 1637 1638 if (instr->CoprocessorValue() == 0xA) { 1639 switch (instr->OpcodeValue()) { 1640 case 0x8: 1641 case 0xA: 1642 if (instr->HasL()) { 1643 Format(instr, "vldr'cond 'Sd, ['rn - 4*'imm08@00]"); 1644 } else { 1645 Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]"); 1646 } 1647 break; 1648 case 0xC: 1649 case 0xE: 1650 if (instr->HasL()) { 1651 Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]"); 1652 } else { 1653 Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]"); 1654 } 1655 break; 1656 case 0x4: 1657 case 0x5: 1658 case 0x6: 1659 case 0x7: 1660 case 0x9: 1661 case 0xB: { 1662 bool to_vfp_register = (instr->VLValue() == 0x1); 1663 if (to_vfp_register) { 1664 Format(instr, "vldm'cond'pu 'rn'w, {'Sd-'Sd+}"); 1665 } else { 1666 Format(instr, "vstm'cond'pu 'rn'w, {'Sd-'Sd+}"); 1667 } 1668 break; 1669 } 1670 default: 1671 Unknown(instr); // Not used by V8. 1672 } 1673 } else if (instr->CoprocessorValue() == 0xB) { 1674 switch (instr->OpcodeValue()) { 1675 case 0x2: 1676 // Load and store double to two GP registers 1677 if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) { 1678 Unknown(instr); // Not used by V8. 1679 } else if (instr->HasL()) { 1680 Format(instr, "vmov'cond 'rt, 'rn, 'Dm"); 1681 } else { 1682 Format(instr, "vmov'cond 'Dm, 'rt, 'rn"); 1683 } 1684 break; 1685 case 0x8: 1686 case 0xA: 1687 if (instr->HasL()) { 1688 Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]"); 1689 } else { 1690 Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]"); 1691 } 1692 break; 1693 case 0xC: 1694 case 0xE: 1695 if (instr->HasL()) { 1696 Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]"); 1697 } else { 1698 Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]"); 1699 } 1700 break; 1701 case 0x4: 1702 case 0x5: 1703 case 0x6: 1704 case 0x7: 1705 case 0x9: 1706 case 0xB: { 1707 bool to_vfp_register = (instr->VLValue() == 0x1); 1708 if (to_vfp_register) { 1709 Format(instr, "vldm'cond'pu 'rn'w, {'Dd-'Dd+}"); 1710 } else { 1711 Format(instr, "vstm'cond'pu 'rn'w, {'Dd-'Dd+}"); 1712 } 1713 break; 1714 } 1715 default: 1716 Unknown(instr); // Not used by V8. 1717 } 1718 } else { 1719 Unknown(instr); // Not used by V8. 1720 } 1721} 1722 1723 1724static const char* const barrier_option_names[] = { 1725 "invalid", "oshld", "oshst", "osh", "invalid", "nshld", "nshst", "nsh", 1726 "invalid", "ishld", "ishst", "ish", "invalid", "ld", "st", "sy", 1727}; 1728 1729 1730void Decoder::DecodeSpecialCondition(Instruction* instr) { 1731 switch (instr->SpecialValue()) { 1732 case 5: 1733 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && 1734 (instr->Bit(4) == 1)) { 1735 // vmovl signed 1736 if ((instr->VdValue() & 1) != 0) Unknown(instr); 1737 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1); 1738 int Vm = (instr->Bit(5) << 4) | instr->VmValue(); 1739 int imm3 = instr->Bits(21, 19); 1740 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1741 "vmovl.s%d q%d, d%d", imm3*8, Vd, Vm); 1742 } else { 1743 Unknown(instr); 1744 } 1745 break; 1746 case 7: 1747 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && 1748 (instr->Bit(4) == 1)) { 1749 // vmovl unsigned 1750 if ((instr->VdValue() & 1) != 0) Unknown(instr); 1751 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1); 1752 int Vm = (instr->Bit(5) << 4) | instr->VmValue(); 1753 int imm3 = instr->Bits(21, 19); 1754 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1755 "vmovl.u%d q%d, d%d", imm3*8, Vd, Vm); 1756 } else { 1757 Unknown(instr); 1758 } 1759 break; 1760 case 8: 1761 if (instr->Bits(21, 20) == 0) { 1762 // vst1 1763 int Vd = (instr->Bit(22) << 4) | instr->VdValue(); 1764 int Rn = instr->VnValue(); 1765 int type = instr->Bits(11, 8); 1766 int size = instr->Bits(7, 6); 1767 int align = instr->Bits(5, 4); 1768 int Rm = instr->VmValue(); 1769 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1770 "vst1.%d ", (1 << size) << 3); 1771 FormatNeonList(Vd, type); 1772 Print(", "); 1773 FormatNeonMemory(Rn, align, Rm); 1774 } else if (instr->Bits(21, 20) == 2) { 1775 // vld1 1776 int Vd = (instr->Bit(22) << 4) | instr->VdValue(); 1777 int Rn = instr->VnValue(); 1778 int type = instr->Bits(11, 8); 1779 int size = instr->Bits(7, 6); 1780 int align = instr->Bits(5, 4); 1781 int Rm = instr->VmValue(); 1782 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1783 "vld1.%d ", (1 << size) << 3); 1784 FormatNeonList(Vd, type); 1785 Print(", "); 1786 FormatNeonMemory(Rn, align, Rm); 1787 } else { 1788 Unknown(instr); 1789 } 1790 break; 1791 case 0xA: 1792 case 0xB: 1793 if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) { 1794 int Rn = instr->Bits(19, 16); 1795 int offset = instr->Bits(11, 0); 1796 if (offset == 0) { 1797 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1798 "pld [r%d]", Rn); 1799 } else if (instr->Bit(23) == 0) { 1800 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1801 "pld [r%d, #-%d]", Rn, offset); 1802 } else { 1803 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1804 "pld [r%d, #+%d]", Rn, offset); 1805 } 1806 } else if (instr->SpecialValue() == 0xA && instr->Bits(22, 20) == 7) { 1807 int option = instr->Bits(3, 0); 1808 switch (instr->Bits(7, 4)) { 1809 case 4: 1810 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1811 "dsb %s", barrier_option_names[option]); 1812 break; 1813 case 5: 1814 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1815 "dmb %s", barrier_option_names[option]); 1816 break; 1817 case 6: 1818 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1819 "isb %s", barrier_option_names[option]); 1820 break; 1821 default: 1822 Unknown(instr); 1823 } 1824 } else { 1825 Unknown(instr); 1826 } 1827 break; 1828 case 0x1D: 1829 if (instr->Opc1Value() == 0x7 && instr->Bits(19, 18) == 0x2 && 1830 instr->Bits(11, 9) == 0x5 && instr->Bits(7, 6) == 0x1 && 1831 instr->Bit(4) == 0x0) { 1832 // VRINTA, VRINTN, VRINTP, VRINTM (floating-point) 1833 bool dp_operation = (instr->SzValue() == 1); 1834 int rounding_mode = instr->Bits(17, 16); 1835 switch (rounding_mode) { 1836 case 0x0: 1837 if (dp_operation) { 1838 Format(instr, "vrinta.f64.f64 'Dd, 'Dm"); 1839 } else { 1840 Format(instr, "vrinta.f32.f32 'Sd, 'Sm"); 1841 } 1842 break; 1843 case 0x1: 1844 if (dp_operation) { 1845 Format(instr, "vrintn.f64.f64 'Dd, 'Dm"); 1846 } else { 1847 Format(instr, "vrintn.f32.f32 'Sd, 'Sm"); 1848 } 1849 break; 1850 case 0x2: 1851 if (dp_operation) { 1852 Format(instr, "vrintp.f64.f64 'Dd, 'Dm"); 1853 } else { 1854 Format(instr, "vrintp.f32.f32 'Sd, 'Sm"); 1855 } 1856 break; 1857 case 0x3: 1858 if (dp_operation) { 1859 Format(instr, "vrintm.f64.f64 'Dd, 'Dm"); 1860 } else { 1861 Format(instr, "vrintm.f32.f32 'Sd, 'Sm"); 1862 } 1863 break; 1864 default: 1865 UNREACHABLE(); // Case analysis is exhaustive. 1866 break; 1867 } 1868 } else { 1869 Unknown(instr); 1870 } 1871 break; 1872 default: 1873 Unknown(instr); 1874 break; 1875 } 1876} 1877 1878#undef VERIFIY 1879 1880bool Decoder::IsConstantPoolAt(byte* instr_ptr) { 1881 int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); 1882 return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker; 1883} 1884 1885 1886int Decoder::ConstantPoolSizeAt(byte* instr_ptr) { 1887 if (IsConstantPoolAt(instr_ptr)) { 1888 int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); 1889 return DecodeConstantPoolLength(instruction_bits); 1890 } else { 1891 return -1; 1892 } 1893} 1894 1895 1896// Disassemble the instruction at *instr_ptr into the output buffer. 1897int Decoder::InstructionDecode(byte* instr_ptr) { 1898 Instruction* instr = Instruction::At(instr_ptr); 1899 // Print raw instruction bytes. 1900 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1901 "%08x ", 1902 instr->InstructionBits()); 1903 if (instr->ConditionField() == kSpecialCondition) { 1904 DecodeSpecialCondition(instr); 1905 return Instruction::kInstrSize; 1906 } 1907 int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); 1908 if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) { 1909 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1910 "constant pool begin (length %d)", 1911 DecodeConstantPoolLength(instruction_bits)); 1912 return Instruction::kInstrSize; 1913 } else if (instruction_bits == kCodeAgeJumpInstruction) { 1914 // The code age prologue has a constant immediatly following the jump 1915 // instruction. 1916 Instruction* target = Instruction::At(instr_ptr + Instruction::kInstrSize); 1917 DecodeType2(instr); 1918 SNPrintF(out_buffer_ + out_buffer_pos_, 1919 " (0x%08x)", target->InstructionBits()); 1920 return 2 * Instruction::kInstrSize; 1921 } 1922 switch (instr->TypeValue()) { 1923 case 0: 1924 case 1: { 1925 DecodeType01(instr); 1926 break; 1927 } 1928 case 2: { 1929 DecodeType2(instr); 1930 break; 1931 } 1932 case 3: { 1933 DecodeType3(instr); 1934 break; 1935 } 1936 case 4: { 1937 DecodeType4(instr); 1938 break; 1939 } 1940 case 5: { 1941 DecodeType5(instr); 1942 break; 1943 } 1944 case 6: { 1945 DecodeType6(instr); 1946 break; 1947 } 1948 case 7: { 1949 return DecodeType7(instr); 1950 } 1951 default: { 1952 // The type field is 3-bits in the ARM encoding. 1953 UNREACHABLE(); 1954 break; 1955 } 1956 } 1957 return Instruction::kInstrSize; 1958} 1959 1960 1961} // namespace internal 1962} // namespace v8 1963 1964 1965//------------------------------------------------------------------------------ 1966 1967namespace disasm { 1968 1969 1970const char* NameConverter::NameOfAddress(byte* addr) const { 1971 v8::internal::SNPrintF(tmp_buffer_, "%p", addr); 1972 return tmp_buffer_.start(); 1973} 1974 1975 1976const char* NameConverter::NameOfConstant(byte* addr) const { 1977 return NameOfAddress(addr); 1978} 1979 1980 1981const char* NameConverter::NameOfCPURegister(int reg) const { 1982 return v8::internal::Register::from_code(reg).ToString(); 1983} 1984 1985 1986const char* NameConverter::NameOfByteCPURegister(int reg) const { 1987 UNREACHABLE(); // ARM does not have the concept of a byte register 1988 return "nobytereg"; 1989} 1990 1991 1992const char* NameConverter::NameOfXMMRegister(int reg) const { 1993 UNREACHABLE(); // ARM does not have any XMM registers 1994 return "noxmmreg"; 1995} 1996 1997 1998const char* NameConverter::NameInCode(byte* addr) const { 1999 // The default name converter is called for unknown code. So we will not try 2000 // to access any memory. 2001 return ""; 2002} 2003 2004 2005//------------------------------------------------------------------------------ 2006 2007Disassembler::Disassembler(const NameConverter& converter) 2008 : converter_(converter) {} 2009 2010 2011Disassembler::~Disassembler() {} 2012 2013 2014int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, 2015 byte* instruction) { 2016 v8::internal::Decoder d(converter_, buffer); 2017 return d.InstructionDecode(instruction); 2018} 2019 2020 2021int Disassembler::ConstantPoolSizeAt(byte* instruction) { 2022 return v8::internal::Decoder::ConstantPoolSizeAt(instruction); 2023} 2024 2025 2026void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { 2027 NameConverter converter; 2028 Disassembler d(converter); 2029 for (byte* pc = begin; pc < end;) { 2030 v8::internal::EmbeddedVector<char, 128> buffer; 2031 buffer[0] = '\0'; 2032 byte* prev_pc = pc; 2033 pc += d.InstructionDecode(buffer, pc); 2034 v8::internal::PrintF( 2035 f, "%p %08x %s\n", 2036 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); 2037 } 2038} 2039 2040 2041} // namespace disasm 2042 2043#endif // V8_TARGET_ARCH_ARM 2044