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