disasm-arm.cc revision 80d68eab642096c1a48b6474d6ec33064b0ad1f5
1// Copyright 2010 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28// A Disassembler object is used to disassemble a block of code instruction by 29// instruction. The default implementation of the NameConverter object can be 30// overriden to modify register names or to do symbol lookup on addresses. 31// 32// The example below will disassemble a block of code and print it to stdout. 33// 34// NameConverter converter; 35// Disassembler d(converter); 36// for (byte* pc = begin; pc < end;) { 37// v8::internal::EmbeddedVector<char, 256> buffer; 38// byte* prev_pc = pc; 39// pc += d.InstructionDecode(buffer, pc); 40// printf("%p %08x %s\n", 41// prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer); 42// } 43// 44// The Disassembler class also has a convenience method to disassemble a block 45// of code into a FILE*, meaning that the above functionality could also be 46// achieved by just calling Disassembler::Disassemble(stdout, begin, end); 47 48 49#include <assert.h> 50#include <stdio.h> 51#include <stdarg.h> 52#include <string.h> 53#ifndef WIN32 54#include <stdint.h> 55#endif 56 57#include "v8.h" 58 59#if defined(V8_TARGET_ARCH_ARM) 60 61#include "constants-arm.h" 62#include "disasm.h" 63#include "macro-assembler.h" 64#include "platform.h" 65 66 67namespace assembler { 68namespace arm { 69 70namespace v8i = v8::internal; 71 72 73//------------------------------------------------------------------------------ 74 75// Decoder decodes and disassembles instructions into an output buffer. 76// It uses the converter to convert register names and call destinations into 77// more informative description. 78class Decoder { 79 public: 80 Decoder(const disasm::NameConverter& converter, 81 v8::internal::Vector<char> out_buffer) 82 : converter_(converter), 83 out_buffer_(out_buffer), 84 out_buffer_pos_(0) { 85 out_buffer_[out_buffer_pos_] = '\0'; 86 } 87 88 ~Decoder() {} 89 90 // Writes one disassembled instruction into 'buffer' (0-terminated). 91 // Returns the length of the disassembled machine instruction in bytes. 92 int InstructionDecode(byte* instruction); 93 94 private: 95 // Bottleneck functions to print into the out_buffer. 96 void PrintChar(const char ch); 97 void Print(const char* str); 98 99 // Printing of common values. 100 void PrintRegister(int reg); 101 void PrintSRegister(int reg); 102 void PrintDRegister(int reg); 103 int FormatVFPRegister(Instr* instr, const char* format); 104 void PrintMovwMovt(Instr* instr); 105 int FormatVFPinstruction(Instr* instr, const char* format); 106 void PrintCondition(Instr* instr); 107 void PrintShiftRm(Instr* instr); 108 void PrintShiftImm(Instr* instr); 109 void PrintShiftSat(Instr* instr); 110 void PrintPU(Instr* instr); 111 void PrintSoftwareInterrupt(SoftwareInterruptCodes swi); 112 113 // Handle formatting of instructions and their options. 114 int FormatRegister(Instr* instr, const char* option); 115 int FormatOption(Instr* instr, const char* option); 116 void Format(Instr* instr, const char* format); 117 void Unknown(Instr* instr); 118 119 // Each of these functions decodes one particular instruction type, a 3-bit 120 // field in the instruction encoding. 121 // Types 0 and 1 are combined as they are largely the same except for the way 122 // they interpret the shifter operand. 123 void DecodeType01(Instr* instr); 124 void DecodeType2(Instr* instr); 125 void DecodeType3(Instr* instr); 126 void DecodeType4(Instr* instr); 127 void DecodeType5(Instr* instr); 128 void DecodeType6(Instr* instr); 129 void DecodeType7(Instr* instr); 130 void DecodeUnconditional(Instr* instr); 131 // For VFP support. 132 void DecodeTypeVFP(Instr* instr); 133 void DecodeType6CoprocessorIns(Instr* instr); 134 135 void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr); 136 void DecodeVCMP(Instr* instr); 137 void DecodeVCVTBetweenDoubleAndSingle(Instr* instr); 138 void DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr); 139 140 const disasm::NameConverter& converter_; 141 v8::internal::Vector<char> out_buffer_; 142 int out_buffer_pos_; 143 144 DISALLOW_COPY_AND_ASSIGN(Decoder); 145}; 146 147 148// Support for assertions in the Decoder formatting functions. 149#define STRING_STARTS_WITH(string, compare_string) \ 150 (strncmp(string, compare_string, strlen(compare_string)) == 0) 151 152 153// Append the ch to the output buffer. 154void Decoder::PrintChar(const char ch) { 155 out_buffer_[out_buffer_pos_++] = ch; 156} 157 158 159// Append the str to the output buffer. 160void Decoder::Print(const char* str) { 161 char cur = *str++; 162 while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 163 PrintChar(cur); 164 cur = *str++; 165 } 166 out_buffer_[out_buffer_pos_] = 0; 167} 168 169 170// These condition names are defined in a way to match the native disassembler 171// formatting. See for example the command "objdump -d <binary file>". 172static const char* cond_names[max_condition] = { 173 "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" , 174 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid", 175}; 176 177 178// Print the condition guarding the instruction. 179void Decoder::PrintCondition(Instr* instr) { 180 Print(cond_names[instr->ConditionField()]); 181} 182 183 184// Print the register name according to the active name converter. 185void Decoder::PrintRegister(int reg) { 186 Print(converter_.NameOfCPURegister(reg)); 187} 188 189// Print the VFP S register name according to the active name converter. 190void Decoder::PrintSRegister(int reg) { 191 Print(assembler::arm::VFPRegisters::Name(reg, false)); 192} 193 194// Print the VFP D register name according to the active name converter. 195void Decoder::PrintDRegister(int reg) { 196 Print(assembler::arm::VFPRegisters::Name(reg, true)); 197} 198 199 200// These shift names are defined in a way to match the native disassembler 201// formatting. See for example the command "objdump -d <binary file>". 202static const char* shift_names[max_shift] = { 203 "lsl", "lsr", "asr", "ror" 204}; 205 206 207// Print the register shift operands for the instruction. Generally used for 208// data processing instructions. 209void Decoder::PrintShiftRm(Instr* instr) { 210 Shift shift = instr->ShiftField(); 211 int shift_amount = instr->ShiftAmountField(); 212 int rm = instr->RmField(); 213 214 PrintRegister(rm); 215 216 if ((instr->RegShiftField() == 0) && (shift == LSL) && (shift_amount == 0)) { 217 // Special case for using rm only. 218 return; 219 } 220 if (instr->RegShiftField() == 0) { 221 // by immediate 222 if ((shift == ROR) && (shift_amount == 0)) { 223 Print(", RRX"); 224 return; 225 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { 226 shift_amount = 32; 227 } 228 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 229 ", %s #%d", 230 shift_names[shift], shift_amount); 231 } else { 232 // by register 233 int rs = instr->RsField(); 234 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 235 ", %s ", shift_names[shift]); 236 PrintRegister(rs); 237 } 238} 239 240 241// Print the immediate operand for the instruction. Generally used for data 242// processing instructions. 243void Decoder::PrintShiftImm(Instr* instr) { 244 int rotate = instr->RotateField() * 2; 245 int immed8 = instr->Immed8Field(); 246 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate)); 247 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 248 "#%d", imm); 249} 250 251 252// Print the optional shift and immediate used by saturating instructions. 253void Decoder::PrintShiftSat(Instr* instr) { 254 int shift = instr->Bits(11, 7); 255 if (shift > 0) { 256 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 257 ", %s #%d", 258 shift_names[instr->Bit(6) * 2], 259 instr->Bits(11, 7)); 260 } 261} 262 263 264// Print PU formatting to reduce complexity of FormatOption. 265void Decoder::PrintPU(Instr* instr) { 266 switch (instr->PUField()) { 267 case 0: { 268 Print("da"); 269 break; 270 } 271 case 1: { 272 Print("ia"); 273 break; 274 } 275 case 2: { 276 Print("db"); 277 break; 278 } 279 case 3: { 280 Print("ib"); 281 break; 282 } 283 default: { 284 UNREACHABLE(); 285 break; 286 } 287 } 288} 289 290 291// Print SoftwareInterrupt codes. Factoring this out reduces the complexity of 292// the FormatOption method. 293void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes swi) { 294 switch (swi) { 295 case call_rt_redirected: 296 Print("call_rt_redirected"); 297 return; 298 case break_point: 299 Print("break_point"); 300 return; 301 default: 302 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 303 "%d", 304 swi); 305 return; 306 } 307} 308 309 310// Handle all register based formatting in this function to reduce the 311// complexity of FormatOption. 312int Decoder::FormatRegister(Instr* instr, const char* format) { 313 ASSERT(format[0] == 'r'); 314 if (format[1] == 'n') { // 'rn: Rn register 315 int reg = instr->RnField(); 316 PrintRegister(reg); 317 return 2; 318 } else if (format[1] == 'd') { // 'rd: Rd register 319 int reg = instr->RdField(); 320 PrintRegister(reg); 321 return 2; 322 } else if (format[1] == 's') { // 'rs: Rs register 323 int reg = instr->RsField(); 324 PrintRegister(reg); 325 return 2; 326 } else if (format[1] == 'm') { // 'rm: Rm register 327 int reg = instr->RmField(); 328 PrintRegister(reg); 329 return 2; 330 } else if (format[1] == 't') { // 'rt: Rt register 331 int reg = instr->RtField(); 332 PrintRegister(reg); 333 return 2; 334 } else if (format[1] == 'l') { 335 // 'rlist: register list for load and store multiple instructions 336 ASSERT(STRING_STARTS_WITH(format, "rlist")); 337 int rlist = instr->RlistField(); 338 int reg = 0; 339 Print("{"); 340 // Print register list in ascending order, by scanning the bit mask. 341 while (rlist != 0) { 342 if ((rlist & 1) != 0) { 343 PrintRegister(reg); 344 if ((rlist >> 1) != 0) { 345 Print(", "); 346 } 347 } 348 reg++; 349 rlist >>= 1; 350 } 351 Print("}"); 352 return 5; 353 } 354 UNREACHABLE(); 355 return -1; 356} 357 358 359// Handle all VFP register based formatting in this function to reduce the 360// complexity of FormatOption. 361int Decoder::FormatVFPRegister(Instr* instr, const char* format) { 362 ASSERT((format[0] == 'S') || (format[0] == 'D')); 363 364 if (format[1] == 'n') { 365 int reg = instr->VnField(); 366 if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->NField())); 367 if (format[0] == 'D') PrintDRegister(reg); 368 return 2; 369 } else if (format[1] == 'm') { 370 int reg = instr->VmField(); 371 if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->MField())); 372 if (format[0] == 'D') PrintDRegister(reg); 373 return 2; 374 } else if (format[1] == 'd') { 375 int reg = instr->VdField(); 376 if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->DField())); 377 if (format[0] == 'D') PrintDRegister(reg); 378 return 2; 379 } 380 381 UNREACHABLE(); 382 return -1; 383} 384 385 386int Decoder::FormatVFPinstruction(Instr* instr, const char* format) { 387 Print(format); 388 return 0; 389} 390 391 392// Print the movw or movt instruction. 393void Decoder::PrintMovwMovt(Instr* instr) { 394 int imm = instr->ImmedMovwMovtField(); 395 int rd = instr->RdField(); 396 PrintRegister(rd); 397 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 398 ", #%d", imm); 399} 400 401 402// FormatOption takes a formatting string and interprets it based on 403// the current instructions. The format string points to the first 404// character of the option string (the option escape has already been 405// consumed by the caller.) FormatOption returns the number of 406// characters that were consumed from the formatting string. 407int Decoder::FormatOption(Instr* instr, const char* format) { 408 switch (format[0]) { 409 case 'a': { // 'a: accumulate multiplies 410 if (instr->Bit(21) == 0) { 411 Print("ul"); 412 } else { 413 Print("la"); 414 } 415 return 1; 416 } 417 case 'b': { // 'b: byte loads or stores 418 if (instr->HasB()) { 419 Print("b"); 420 } 421 return 1; 422 } 423 case 'c': { // 'cond: conditional execution 424 ASSERT(STRING_STARTS_WITH(format, "cond")); 425 PrintCondition(instr); 426 return 4; 427 } 428 case 'd': { // 'd: vmov double immediate. 429 double d = instr->DoubleImmedVmov(); 430 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 431 "#%g", d); 432 return 1; 433 } 434 case 'f': { // 'f: bitfield instructions - v7 and above. 435 uint32_t lsbit = instr->Bits(11, 7); 436 uint32_t width = instr->Bits(20, 16) + 1; 437 if (instr->Bit(21) == 0) { 438 // BFC/BFI: 439 // Bits 20-16 represent most-significant bit. Covert to width. 440 width -= lsbit; 441 ASSERT(width > 0); 442 } 443 ASSERT((width + lsbit) <= 32); 444 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 445 "#%d, #%d", lsbit, width); 446 return 1; 447 } 448 case 'h': { // 'h: halfword operation for extra loads and stores 449 if (instr->HasH()) { 450 Print("h"); 451 } else { 452 Print("b"); 453 } 454 return 1; 455 } 456 case 'i': { // 'i: immediate value from adjacent bits. 457 // Expects tokens in the form imm%02d@%02d, ie. imm05@07, imm10@16 458 int width = (format[3] - '0') * 10 + (format[4] - '0'); 459 int lsb = (format[6] - '0') * 10 + (format[7] - '0'); 460 461 ASSERT((width >= 1) && (width <= 32)); 462 ASSERT((lsb >= 0) && (lsb <= 31)); 463 ASSERT((width + lsb) <= 32); 464 465 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 466 "%d", 467 instr->Bits(width + lsb - 1, lsb)); 468 return 8; 469 } 470 case 'l': { // 'l: branch and link 471 if (instr->HasLink()) { 472 Print("l"); 473 } 474 return 1; 475 } 476 case 'm': { 477 if (format[1] == 'w') { 478 // 'mw: movt/movw instructions. 479 PrintMovwMovt(instr); 480 return 2; 481 } 482 if (format[1] == 'e') { // 'memop: load/store instructions. 483 ASSERT(STRING_STARTS_WITH(format, "memop")); 484 if (instr->HasL()) { 485 Print("ldr"); 486 } else if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0)) { 487 if (instr->Bits(7, 4) == 0xf) { 488 Print("strd"); 489 } else { 490 Print("ldrd"); 491 } 492 } else { 493 Print("str"); 494 } 495 return 5; 496 } 497 // 'msg: for simulator break instructions 498 ASSERT(STRING_STARTS_WITH(format, "msg")); 499 byte* str = 500 reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff); 501 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 502 "%s", converter_.NameInCode(str)); 503 return 3; 504 } 505 case 'o': { 506 if ((format[3] == '1') && (format[4] == '2')) { 507 // 'off12: 12-bit offset for load and store instructions 508 ASSERT(STRING_STARTS_WITH(format, "off12")); 509 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 510 "%d", instr->Offset12Field()); 511 return 5; 512 } else if (format[3] == '0') { 513 // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0. 514 ASSERT(STRING_STARTS_WITH(format, "off0to3and8to19")); 515 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 516 "%d", 517 (instr->Bits(19, 8) << 4) + 518 instr->Bits(3, 0)); 519 return 15; 520 } 521 // 'off8: 8-bit offset for extra load and store instructions 522 ASSERT(STRING_STARTS_WITH(format, "off8")); 523 int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField(); 524 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 525 "%d", offs8); 526 return 4; 527 } 528 case 'p': { // 'pu: P and U bits for load and store instructions 529 ASSERT(STRING_STARTS_WITH(format, "pu")); 530 PrintPU(instr); 531 return 2; 532 } 533 case 'r': { 534 return FormatRegister(instr, format); 535 } 536 case 's': { 537 if (format[1] == 'h') { // 'shift_op or 'shift_rm or 'shift_sat. 538 if (format[6] == 'o') { // 'shift_op 539 ASSERT(STRING_STARTS_WITH(format, "shift_op")); 540 if (instr->TypeField() == 0) { 541 PrintShiftRm(instr); 542 } else { 543 ASSERT(instr->TypeField() == 1); 544 PrintShiftImm(instr); 545 } 546 return 8; 547 } else if (format[6] == 's') { // 'shift_sat. 548 ASSERT(STRING_STARTS_WITH(format, "shift_sat")); 549 PrintShiftSat(instr); 550 return 9; 551 } else { // 'shift_rm 552 ASSERT(STRING_STARTS_WITH(format, "shift_rm")); 553 PrintShiftRm(instr); 554 return 8; 555 } 556 } else if (format[1] == 'w') { // 'swi 557 ASSERT(STRING_STARTS_WITH(format, "swi")); 558 PrintSoftwareInterrupt(instr->SwiField()); 559 return 3; 560 } else if (format[1] == 'i') { // 'sign: signed extra loads and stores 561 ASSERT(STRING_STARTS_WITH(format, "sign")); 562 if (instr->HasSign()) { 563 Print("s"); 564 } 565 return 4; 566 } 567 // 's: S field of data processing instructions 568 if (instr->HasS()) { 569 Print("s"); 570 } 571 return 1; 572 } 573 case 't': { // 'target: target of branch instructions 574 ASSERT(STRING_STARTS_WITH(format, "target")); 575 int off = (instr->SImmed24Field() << 2) + 8; 576 out_buffer_pos_ += v8i::OS::SNPrintF( 577 out_buffer_ + out_buffer_pos_, 578 "%+d -> %s", 579 off, 580 converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off)); 581 return 6; 582 } 583 case 'u': { // 'u: signed or unsigned multiplies 584 // The manual gets the meaning of bit 22 backwards in the multiply 585 // instruction overview on page A3.16.2. The instructions that 586 // exist in u and s variants are the following: 587 // smull A4.1.87 588 // umull A4.1.129 589 // umlal A4.1.128 590 // smlal A4.1.76 591 // For these 0 means u and 1 means s. As can be seen on their individual 592 // pages. The other 18 mul instructions have the bit set or unset in 593 // arbitrary ways that are unrelated to the signedness of the instruction. 594 // None of these 18 instructions exist in both a 'u' and an 's' variant. 595 596 if (instr->Bit(22) == 0) { 597 Print("u"); 598 } else { 599 Print("s"); 600 } 601 return 1; 602 } 603 case 'v': { 604 return FormatVFPinstruction(instr, format); 605 } 606 case 'S': 607 case 'D': { 608 return FormatVFPRegister(instr, format); 609 } 610 case 'w': { // 'w: W field of load and store instructions 611 if (instr->HasW()) { 612 Print("!"); 613 } 614 return 1; 615 } 616 default: { 617 UNREACHABLE(); 618 break; 619 } 620 } 621 UNREACHABLE(); 622 return -1; 623} 624 625 626// Format takes a formatting string for a whole instruction and prints it into 627// the output buffer. All escaped options are handed to FormatOption to be 628// parsed further. 629void Decoder::Format(Instr* instr, const char* format) { 630 char cur = *format++; 631 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 632 if (cur == '\'') { // Single quote is used as the formatting escape. 633 format += FormatOption(instr, format); 634 } else { 635 out_buffer_[out_buffer_pos_++] = cur; 636 } 637 cur = *format++; 638 } 639 out_buffer_[out_buffer_pos_] = '\0'; 640} 641 642 643// For currently unimplemented decodings the disassembler calls Unknown(instr) 644// which will just print "unknown" of the instruction bits. 645void Decoder::Unknown(Instr* instr) { 646 Format(instr, "unknown"); 647} 648 649 650void Decoder::DecodeType01(Instr* instr) { 651 int type = instr->TypeField(); 652 if ((type == 0) && instr->IsSpecialType0()) { 653 // multiply instruction or extra loads and stores 654 if (instr->Bits(7, 4) == 9) { 655 if (instr->Bit(24) == 0) { 656 // multiply instructions 657 if (instr->Bit(23) == 0) { 658 if (instr->Bit(21) == 0) { 659 // The MUL instruction description (A 4.1.33) refers to Rd as being 660 // the destination for the operation, but it confusingly uses the 661 // Rn field to encode it. 662 Format(instr, "mul'cond's 'rn, 'rm, 'rs"); 663 } else { 664 // The MLA instruction description (A 4.1.28) refers to the order 665 // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the 666 // Rn field to encode the Rd register and the Rd field to encode 667 // the Rn register. 668 Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd"); 669 } 670 } else { 671 // The signed/long multiply instructions use the terms RdHi and RdLo 672 // when referring to the target registers. They are mapped to the Rn 673 // and Rd fields as follows: 674 // RdLo == Rd field 675 // RdHi == Rn field 676 // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs> 677 Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs"); 678 } 679 } else { 680 Unknown(instr); // not used by V8 681 } 682 } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xd) == 0xd)) { 683 // ldrd, strd 684 switch (instr->PUField()) { 685 case 0: { 686 if (instr->Bit(22) == 0) { 687 Format(instr, "'memop'cond's 'rd, ['rn], -'rm"); 688 } else { 689 Format(instr, "'memop'cond's 'rd, ['rn], #-'off8"); 690 } 691 break; 692 } 693 case 1: { 694 if (instr->Bit(22) == 0) { 695 Format(instr, "'memop'cond's 'rd, ['rn], +'rm"); 696 } else { 697 Format(instr, "'memop'cond's 'rd, ['rn], #+'off8"); 698 } 699 break; 700 } 701 case 2: { 702 if (instr->Bit(22) == 0) { 703 Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w"); 704 } else { 705 Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w"); 706 } 707 break; 708 } 709 case 3: { 710 if (instr->Bit(22) == 0) { 711 Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w"); 712 } else { 713 Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w"); 714 } 715 break; 716 } 717 default: { 718 // The PU field is a 2-bit field. 719 UNREACHABLE(); 720 break; 721 } 722 } 723 } else { 724 // extra load/store instructions 725 switch (instr->PUField()) { 726 case 0: { 727 if (instr->Bit(22) == 0) { 728 Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm"); 729 } else { 730 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8"); 731 } 732 break; 733 } 734 case 1: { 735 if (instr->Bit(22) == 0) { 736 Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm"); 737 } else { 738 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8"); 739 } 740 break; 741 } 742 case 2: { 743 if (instr->Bit(22) == 0) { 744 Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w"); 745 } else { 746 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w"); 747 } 748 break; 749 } 750 case 3: { 751 if (instr->Bit(22) == 0) { 752 Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w"); 753 } else { 754 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w"); 755 } 756 break; 757 } 758 default: { 759 // The PU field is a 2-bit field. 760 UNREACHABLE(); 761 break; 762 } 763 } 764 return; 765 } 766 } else if ((type == 0) && instr->IsMiscType0()) { 767 if (instr->Bits(22, 21) == 1) { 768 switch (instr->Bits(7, 4)) { 769 case BX: 770 Format(instr, "bx'cond 'rm"); 771 break; 772 case BLX: 773 Format(instr, "blx'cond 'rm"); 774 break; 775 case BKPT: 776 Format(instr, "bkpt 'off0to3and8to19"); 777 break; 778 default: 779 Unknown(instr); // not used by V8 780 break; 781 } 782 } else if (instr->Bits(22, 21) == 3) { 783 switch (instr->Bits(7, 4)) { 784 case CLZ: 785 Format(instr, "clz'cond 'rd, 'rm"); 786 break; 787 default: 788 Unknown(instr); // not used by V8 789 break; 790 } 791 } else { 792 Unknown(instr); // not used by V8 793 } 794 } else { 795 switch (instr->OpcodeField()) { 796 case AND: { 797 Format(instr, "and'cond's 'rd, 'rn, 'shift_op"); 798 break; 799 } 800 case EOR: { 801 Format(instr, "eor'cond's 'rd, 'rn, 'shift_op"); 802 break; 803 } 804 case SUB: { 805 Format(instr, "sub'cond's 'rd, 'rn, 'shift_op"); 806 break; 807 } 808 case RSB: { 809 Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op"); 810 break; 811 } 812 case ADD: { 813 Format(instr, "add'cond's 'rd, 'rn, 'shift_op"); 814 break; 815 } 816 case ADC: { 817 Format(instr, "adc'cond's 'rd, 'rn, 'shift_op"); 818 break; 819 } 820 case SBC: { 821 Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op"); 822 break; 823 } 824 case RSC: { 825 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op"); 826 break; 827 } 828 case TST: { 829 if (instr->HasS()) { 830 Format(instr, "tst'cond 'rn, 'shift_op"); 831 } else { 832 Format(instr, "movw'cond 'mw"); 833 } 834 break; 835 } 836 case TEQ: { 837 if (instr->HasS()) { 838 Format(instr, "teq'cond 'rn, 'shift_op"); 839 } else { 840 // Other instructions matching this pattern are handled in the 841 // miscellaneous instructions part above. 842 UNREACHABLE(); 843 } 844 break; 845 } 846 case CMP: { 847 if (instr->HasS()) { 848 Format(instr, "cmp'cond 'rn, 'shift_op"); 849 } else { 850 Format(instr, "movt'cond 'mw"); 851 } 852 break; 853 } 854 case CMN: { 855 if (instr->HasS()) { 856 Format(instr, "cmn'cond 'rn, 'shift_op"); 857 } else { 858 // Other instructions matching this pattern are handled in the 859 // miscellaneous instructions part above. 860 UNREACHABLE(); 861 } 862 break; 863 } 864 case ORR: { 865 Format(instr, "orr'cond's 'rd, 'rn, 'shift_op"); 866 break; 867 } 868 case MOV: { 869 Format(instr, "mov'cond's 'rd, 'shift_op"); 870 break; 871 } 872 case BIC: { 873 Format(instr, "bic'cond's 'rd, 'rn, 'shift_op"); 874 break; 875 } 876 case MVN: { 877 Format(instr, "mvn'cond's 'rd, 'shift_op"); 878 break; 879 } 880 default: { 881 // The Opcode field is a 4-bit field. 882 UNREACHABLE(); 883 break; 884 } 885 } 886 } 887} 888 889 890void Decoder::DecodeType2(Instr* instr) { 891 switch (instr->PUField()) { 892 case 0: { 893 if (instr->HasW()) { 894 Unknown(instr); // not used in V8 895 } 896 Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); 897 break; 898 } 899 case 1: { 900 if (instr->HasW()) { 901 Unknown(instr); // not used in V8 902 } 903 Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12"); 904 break; 905 } 906 case 2: { 907 Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w"); 908 break; 909 } 910 case 3: { 911 Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w"); 912 break; 913 } 914 default: { 915 // The PU field is a 2-bit field. 916 UNREACHABLE(); 917 break; 918 } 919 } 920} 921 922 923void Decoder::DecodeType3(Instr* instr) { 924 switch (instr->PUField()) { 925 case 0: { 926 ASSERT(!instr->HasW()); 927 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); 928 break; 929 } 930 case 1: { 931 if (instr->HasW()) { 932 ASSERT(instr->Bits(5, 4) == 0x1); 933 if (instr->Bit(22) == 0x1) { 934 Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat"); 935 } else { 936 UNREACHABLE(); // SSAT. 937 } 938 } else { 939 Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm"); 940 } 941 break; 942 } 943 case 2: { 944 Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w"); 945 break; 946 } 947 case 3: { 948 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) { 949 uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16)); 950 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); 951 uint32_t msbit = widthminus1 + lsbit; 952 if (msbit <= 31) { 953 if (instr->Bit(22)) { 954 Format(instr, "ubfx'cond 'rd, 'rm, 'f"); 955 } else { 956 Format(instr, "sbfx'cond 'rd, 'rm, 'f"); 957 } 958 } else { 959 UNREACHABLE(); 960 } 961 } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) { 962 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); 963 uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16)); 964 if (msbit >= lsbit) { 965 if (instr->RmField() == 15) { 966 Format(instr, "bfc'cond 'rd, 'f"); 967 } else { 968 Format(instr, "bfi'cond 'rd, 'rm, 'f"); 969 } 970 } else { 971 UNREACHABLE(); 972 } 973 } else { 974 Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w"); 975 } 976 break; 977 } 978 default: { 979 // The PU field is a 2-bit field. 980 UNREACHABLE(); 981 break; 982 } 983 } 984} 985 986 987void Decoder::DecodeType4(Instr* instr) { 988 ASSERT(instr->Bit(22) == 0); // Privileged mode currently not supported. 989 if (instr->HasL()) { 990 Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); 991 } else { 992 Format(instr, "stm'cond'pu 'rn'w, 'rlist"); 993 } 994} 995 996 997void Decoder::DecodeType5(Instr* instr) { 998 Format(instr, "b'l'cond 'target"); 999} 1000 1001 1002void Decoder::DecodeType6(Instr* instr) { 1003 DecodeType6CoprocessorIns(instr); 1004} 1005 1006 1007void Decoder::DecodeType7(Instr* instr) { 1008 if (instr->Bit(24) == 1) { 1009 Format(instr, "swi'cond 'swi"); 1010 } else { 1011 DecodeTypeVFP(instr); 1012 } 1013} 1014 1015void Decoder::DecodeUnconditional(Instr* instr) { 1016 if (instr->Bits(7, 4) == 0xB && instr->Bits(27, 25) == 0 && instr->HasL()) { 1017 Format(instr, "'memop'h'pu 'rd, "); 1018 bool immediate = instr->HasB(); 1019 switch (instr->PUField()) { 1020 case 0: { 1021 // Post index, negative. 1022 if (instr->HasW()) { 1023 Unknown(instr); 1024 break; 1025 } 1026 if (immediate) { 1027 Format(instr, "['rn], #-'imm12"); 1028 } else { 1029 Format(instr, "['rn], -'rm"); 1030 } 1031 break; 1032 } 1033 case 1: { 1034 // Post index, positive. 1035 if (instr->HasW()) { 1036 Unknown(instr); 1037 break; 1038 } 1039 if (immediate) { 1040 Format(instr, "['rn], #+'imm12"); 1041 } else { 1042 Format(instr, "['rn], +'rm"); 1043 } 1044 break; 1045 } 1046 case 2: { 1047 // Pre index or offset, negative. 1048 if (immediate) { 1049 Format(instr, "['rn, #-'imm12]'w"); 1050 } else { 1051 Format(instr, "['rn, -'rm]'w"); 1052 } 1053 break; 1054 } 1055 case 3: { 1056 // Pre index or offset, positive. 1057 if (immediate) { 1058 Format(instr, "['rn, #+'imm12]'w"); 1059 } else { 1060 Format(instr, "['rn, +'rm]'w"); 1061 } 1062 break; 1063 } 1064 default: { 1065 // The PU field is a 2-bit field. 1066 UNREACHABLE(); 1067 break; 1068 } 1069 } 1070 return; 1071 } 1072 Format(instr, "break 'msg"); 1073} 1074 1075 1076// void Decoder::DecodeTypeVFP(Instr* instr) 1077// vmov: Sn = Rt 1078// vmov: Rt = Sn 1079// vcvt: Dd = Sm 1080// vcvt: Sd = Dm 1081// Dd = vadd(Dn, Dm) 1082// Dd = vsub(Dn, Dm) 1083// Dd = vmul(Dn, Dm) 1084// Dd = vdiv(Dn, Dm) 1085// vcmp(Dd, Dm) 1086// vmrs 1087// Dd = vsqrt(Dm) 1088void Decoder::DecodeTypeVFP(Instr* instr) { 1089 ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) ); 1090 ASSERT(instr->Bits(11, 9) == 0x5); 1091 1092 if (instr->Bit(4) == 0) { 1093 if (instr->Opc1Field() == 0x7) { 1094 // Other data processing instructions 1095 if ((instr->Opc2Field() == 0x0) && (instr->Opc3Field() == 0x1)) { 1096 // vmov register to register. 1097 if (instr->SzField() == 0x1) { 1098 Format(instr, "vmov.f64'cond 'Dd, 'Dm"); 1099 } else { 1100 Format(instr, "vmov.f32'cond 'Sd, 'Sm"); 1101 } 1102 } else if ((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)) { 1103 DecodeVCVTBetweenDoubleAndSingle(instr); 1104 } else if ((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) { 1105 DecodeVCVTBetweenFloatingPointAndInteger(instr); 1106 } else if (((instr->Opc2Field() >> 1) == 0x6) && 1107 (instr->Opc3Field() & 0x1)) { 1108 DecodeVCVTBetweenFloatingPointAndInteger(instr); 1109 } else if (((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) && 1110 (instr->Opc3Field() & 0x1)) { 1111 DecodeVCMP(instr); 1112 } else if (((instr->Opc2Field() == 0x1)) && (instr->Opc3Field() == 0x3)) { 1113 Format(instr, "vsqrt.f64'cond 'Dd, 'Dm"); 1114 } else if (instr->Opc3Field() == 0x0) { 1115 if (instr->SzField() == 0x1) { 1116 Format(instr, "vmov.f64'cond 'Dd, 'd"); 1117 } else { 1118 Unknown(instr); // Not used by V8. 1119 } 1120 } else { 1121 Unknown(instr); // Not used by V8. 1122 } 1123 } else if (instr->Opc1Field() == 0x3) { 1124 if (instr->SzField() == 0x1) { 1125 if (instr->Opc3Field() & 0x1) { 1126 Format(instr, "vsub.f64'cond 'Dd, 'Dn, 'Dm"); 1127 } else { 1128 Format(instr, "vadd.f64'cond 'Dd, 'Dn, 'Dm"); 1129 } 1130 } else { 1131 Unknown(instr); // Not used by V8. 1132 } 1133 } else if ((instr->Opc1Field() == 0x2) && !(instr->Opc3Field() & 0x1)) { 1134 if (instr->SzField() == 0x1) { 1135 Format(instr, "vmul.f64'cond 'Dd, 'Dn, 'Dm"); 1136 } else { 1137 Unknown(instr); // Not used by V8. 1138 } 1139 } else if ((instr->Opc1Field() == 0x4) && !(instr->Opc3Field() & 0x1)) { 1140 if (instr->SzField() == 0x1) { 1141 Format(instr, "vdiv.f64'cond 'Dd, 'Dn, 'Dm"); 1142 } else { 1143 Unknown(instr); // Not used by V8. 1144 } 1145 } else { 1146 Unknown(instr); // Not used by V8. 1147 } 1148 } else { 1149 if ((instr->VCField() == 0x0) && 1150 (instr->VAField() == 0x0)) { 1151 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); 1152 } else if ((instr->VLField() == 0x1) && 1153 (instr->VCField() == 0x0) && 1154 (instr->VAField() == 0x7) && 1155 (instr->Bits(19, 16) == 0x1)) { 1156 if (instr->Bits(15, 12) == 0xF) 1157 Format(instr, "vmrs'cond APSR, FPSCR"); 1158 else 1159 Unknown(instr); // Not used by V8. 1160 } else { 1161 Unknown(instr); // Not used by V8. 1162 } 1163 } 1164} 1165 1166 1167void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr) { 1168 ASSERT((instr->Bit(4) == 1) && (instr->VCField() == 0x0) && 1169 (instr->VAField() == 0x0)); 1170 1171 bool to_arm_register = (instr->VLField() == 0x1); 1172 1173 if (to_arm_register) { 1174 Format(instr, "vmov'cond 'rt, 'Sn"); 1175 } else { 1176 Format(instr, "vmov'cond 'Sn, 'rt"); 1177 } 1178} 1179 1180 1181void Decoder::DecodeVCMP(Instr* instr) { 1182 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); 1183 ASSERT(((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) && 1184 (instr->Opc3Field() & 0x1)); 1185 1186 // Comparison. 1187 bool dp_operation = (instr->SzField() == 1); 1188 bool raise_exception_for_qnan = (instr->Bit(7) == 0x1); 1189 1190 if (dp_operation && !raise_exception_for_qnan) { 1191 if (instr->Opc2Field() == 0x4) { 1192 Format(instr, "vcmp.f64'cond 'Dd, 'Dm"); 1193 } else if (instr->Opc2Field() == 0x5) { 1194 Format(instr, "vcmp.f64'cond 'Dd, #0.0"); 1195 } else { 1196 Unknown(instr); // invalid 1197 } 1198 } else { 1199 Unknown(instr); // Not used by V8. 1200 } 1201} 1202 1203 1204void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instr* instr) { 1205 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); 1206 ASSERT((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)); 1207 1208 bool double_to_single = (instr->SzField() == 1); 1209 1210 if (double_to_single) { 1211 Format(instr, "vcvt.f32.f64'cond 'Sd, 'Dm"); 1212 } else { 1213 Format(instr, "vcvt.f64.f32'cond 'Dd, 'Sm"); 1214 } 1215} 1216 1217 1218void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr) { 1219 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); 1220 ASSERT(((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) || 1221 (((instr->Opc2Field() >> 1) == 0x6) && (instr->Opc3Field() & 0x1))); 1222 1223 bool to_integer = (instr->Bit(18) == 1); 1224 bool dp_operation = (instr->SzField() == 1); 1225 if (to_integer) { 1226 bool unsigned_integer = (instr->Bit(16) == 0); 1227 1228 if (dp_operation) { 1229 if (unsigned_integer) { 1230 Format(instr, "vcvt.u32.f64'cond 'Sd, 'Dm"); 1231 } else { 1232 Format(instr, "vcvt.s32.f64'cond 'Sd, 'Dm"); 1233 } 1234 } else { 1235 if (unsigned_integer) { 1236 Format(instr, "vcvt.u32.f32'cond 'Sd, 'Sm"); 1237 } else { 1238 Format(instr, "vcvt.s32.f32'cond 'Sd, 'Sm"); 1239 } 1240 } 1241 } else { 1242 bool unsigned_integer = (instr->Bit(7) == 0); 1243 1244 if (dp_operation) { 1245 if (unsigned_integer) { 1246 Format(instr, "vcvt.f64.u32'cond 'Dd, 'Sm"); 1247 } else { 1248 Format(instr, "vcvt.f64.s32'cond 'Dd, 'Sm"); 1249 } 1250 } else { 1251 if (unsigned_integer) { 1252 Format(instr, "vcvt.f32.u32'cond 'Sd, 'Sm"); 1253 } else { 1254 Format(instr, "vcvt.f32.s32'cond 'Sd, 'Sm"); 1255 } 1256 } 1257 } 1258} 1259 1260 1261// Decode Type 6 coprocessor instructions. 1262// Dm = vmov(Rt, Rt2) 1263// <Rt, Rt2> = vmov(Dm) 1264// Ddst = MEM(Rbase + 4*offset). 1265// MEM(Rbase + 4*offset) = Dsrc. 1266void Decoder::DecodeType6CoprocessorIns(Instr* instr) { 1267 ASSERT((instr->TypeField() == 6)); 1268 1269 if (instr->CoprocessorField() == 0xA) { 1270 switch (instr->OpcodeField()) { 1271 case 0x8: 1272 case 0xA: 1273 if (instr->HasL()) { 1274 Format(instr, "vldr'cond 'Sd, ['rn - 4*'imm08@00]"); 1275 } else { 1276 Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]"); 1277 } 1278 break; 1279 case 0xC: 1280 case 0xE: 1281 if (instr->HasL()) { 1282 Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]"); 1283 } else { 1284 Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]"); 1285 } 1286 break; 1287 default: 1288 Unknown(instr); // Not used by V8. 1289 break; 1290 } 1291 } else if (instr->CoprocessorField() == 0xB) { 1292 switch (instr->OpcodeField()) { 1293 case 0x2: 1294 // Load and store double to two GP registers 1295 if (instr->Bits(7, 4) != 0x1) { 1296 Unknown(instr); // Not used by V8. 1297 } else if (instr->HasL()) { 1298 Format(instr, "vmov'cond 'rt, 'rn, 'Dm"); 1299 } else { 1300 Format(instr, "vmov'cond 'Dm, 'rt, 'rn"); 1301 } 1302 break; 1303 case 0x8: 1304 if (instr->HasL()) { 1305 Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]"); 1306 } else { 1307 Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]"); 1308 } 1309 break; 1310 case 0xC: 1311 if (instr->HasL()) { 1312 Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]"); 1313 } else { 1314 Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]"); 1315 } 1316 break; 1317 default: 1318 Unknown(instr); // Not used by V8. 1319 break; 1320 } 1321 } else { 1322 UNIMPLEMENTED(); // Not used by V8. 1323 } 1324} 1325 1326 1327// Disassemble the instruction at *instr_ptr into the output buffer. 1328int Decoder::InstructionDecode(byte* instr_ptr) { 1329 Instr* instr = Instr::At(instr_ptr); 1330 // Print raw instruction bytes. 1331 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 1332 "%08x ", 1333 instr->InstructionBits()); 1334 if (instr->ConditionField() == special_condition) { 1335 DecodeUnconditional(instr); 1336 return Instr::kInstrSize; 1337 } 1338 switch (instr->TypeField()) { 1339 case 0: 1340 case 1: { 1341 DecodeType01(instr); 1342 break; 1343 } 1344 case 2: { 1345 DecodeType2(instr); 1346 break; 1347 } 1348 case 3: { 1349 DecodeType3(instr); 1350 break; 1351 } 1352 case 4: { 1353 DecodeType4(instr); 1354 break; 1355 } 1356 case 5: { 1357 DecodeType5(instr); 1358 break; 1359 } 1360 case 6: { 1361 DecodeType6(instr); 1362 break; 1363 } 1364 case 7: { 1365 DecodeType7(instr); 1366 break; 1367 } 1368 default: { 1369 // The type field is 3-bits in the ARM encoding. 1370 UNREACHABLE(); 1371 break; 1372 } 1373 } 1374 return Instr::kInstrSize; 1375} 1376 1377 1378} } // namespace assembler::arm 1379 1380 1381 1382//------------------------------------------------------------------------------ 1383 1384namespace disasm { 1385 1386namespace v8i = v8::internal; 1387 1388 1389const char* NameConverter::NameOfAddress(byte* addr) const { 1390 static v8::internal::EmbeddedVector<char, 32> tmp_buffer; 1391 v8::internal::OS::SNPrintF(tmp_buffer, "%p", addr); 1392 return tmp_buffer.start(); 1393} 1394 1395 1396const char* NameConverter::NameOfConstant(byte* addr) const { 1397 return NameOfAddress(addr); 1398} 1399 1400 1401const char* NameConverter::NameOfCPURegister(int reg) const { 1402 return assembler::arm::Registers::Name(reg); 1403} 1404 1405 1406const char* NameConverter::NameOfByteCPURegister(int reg) const { 1407 UNREACHABLE(); // ARM does not have the concept of a byte register 1408 return "nobytereg"; 1409} 1410 1411 1412const char* NameConverter::NameOfXMMRegister(int reg) const { 1413 UNREACHABLE(); // ARM does not have any XMM registers 1414 return "noxmmreg"; 1415} 1416 1417 1418const char* NameConverter::NameInCode(byte* addr) const { 1419 // The default name converter is called for unknown code. So we will not try 1420 // to access any memory. 1421 return ""; 1422} 1423 1424 1425//------------------------------------------------------------------------------ 1426 1427Disassembler::Disassembler(const NameConverter& converter) 1428 : converter_(converter) {} 1429 1430 1431Disassembler::~Disassembler() {} 1432 1433 1434int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, 1435 byte* instruction) { 1436 assembler::arm::Decoder d(converter_, buffer); 1437 return d.InstructionDecode(instruction); 1438} 1439 1440 1441int Disassembler::ConstantPoolSizeAt(byte* instruction) { 1442 int instruction_bits = *(reinterpret_cast<int*>(instruction)); 1443 if ((instruction_bits & 0xfff00000) == 0x03000000) { 1444 return instruction_bits & 0x0000ffff; 1445 } else { 1446 return -1; 1447 } 1448} 1449 1450 1451void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { 1452 NameConverter converter; 1453 Disassembler d(converter); 1454 for (byte* pc = begin; pc < end;) { 1455 v8::internal::EmbeddedVector<char, 128> buffer; 1456 buffer[0] = '\0'; 1457 byte* prev_pc = pc; 1458 pc += d.InstructionDecode(buffer, pc); 1459 fprintf(f, "%p %08x %s\n", 1460 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); 1461 } 1462} 1463 1464 1465} // namespace disasm 1466 1467#endif // V8_TARGET_ARCH_ARM 1468