| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // A Disassembler object is used to disassemble a block of code instruction by | 5 // A Disassembler object is used to disassemble a block of code instruction by |
| 6 // instruction. The default implementation of the NameConverter object can be | 6 // instruction. The default implementation of the NameConverter object can be |
| 7 // overriden to modify register names or to do symbol lookup on addresses. | 7 // overriden to modify register names or to do symbol lookup on addresses. |
| 8 // | 8 // |
| 9 // The example below will disassemble a block of code and print it to stdout. | 9 // The example below will disassemble a block of code and print it to stdout. |
| 10 // | 10 // |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 return; | 200 return; |
| 201 } | 201 } |
| 202 if (instr->RegShiftValue() == 0) { | 202 if (instr->RegShiftValue() == 0) { |
| 203 // by immediate | 203 // by immediate |
| 204 if ((shift == ROR) && (shift_amount == 0)) { | 204 if ((shift == ROR) && (shift_amount == 0)) { |
| 205 Print(", RRX"); | 205 Print(", RRX"); |
| 206 return; | 206 return; |
| 207 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { | 207 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { |
| 208 shift_amount = 32; | 208 shift_amount = 32; |
| 209 } | 209 } |
| 210 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 210 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 211 ", %s #%d", | 211 ", %s #%d", |
| 212 shift_names[shift_index], | 212 shift_names[shift_index], |
| 213 shift_amount); | 213 shift_amount); |
| 214 } else { | 214 } else { |
| 215 // by register | 215 // by register |
| 216 int rs = instr->RsValue(); | 216 int rs = instr->RsValue(); |
| 217 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 217 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 218 ", %s ", shift_names[shift_index]); | 218 ", %s ", shift_names[shift_index]); |
| 219 PrintRegister(rs); | 219 PrintRegister(rs); |
| 220 } | 220 } |
| 221 } | 221 } |
| 222 | 222 |
| 223 | 223 |
| 224 // Print the immediate operand for the instruction. Generally used for data | 224 // Print the immediate operand for the instruction. Generally used for data |
| 225 // processing instructions. | 225 // processing instructions. |
| 226 void Decoder::PrintShiftImm(Instruction* instr) { | 226 void Decoder::PrintShiftImm(Instruction* instr) { |
| 227 int rotate = instr->RotateValue() * 2; | 227 int rotate = instr->RotateValue() * 2; |
| 228 int immed8 = instr->Immed8Value(); | 228 int immed8 = instr->Immed8Value(); |
| 229 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate)); | 229 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate)); |
| 230 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 230 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%d", imm); |
| 231 "#%d", imm); | |
| 232 } | 231 } |
| 233 | 232 |
| 234 | 233 |
| 235 // Print the optional shift and immediate used by saturating instructions. | 234 // Print the optional shift and immediate used by saturating instructions. |
| 236 void Decoder::PrintShiftSat(Instruction* instr) { | 235 void Decoder::PrintShiftSat(Instruction* instr) { |
| 237 int shift = instr->Bits(11, 7); | 236 int shift = instr->Bits(11, 7); |
| 238 if (shift > 0) { | 237 if (shift > 0) { |
| 239 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 238 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 240 ", %s #%d", | 239 ", %s #%d", |
| 241 shift_names[instr->Bit(6) * 2], | 240 shift_names[instr->Bit(6) * 2], |
| 242 instr->Bits(11, 7)); | 241 instr->Bits(11, 7)); |
| 243 } | 242 } |
| 244 } | 243 } |
| 245 | 244 |
| 246 | 245 |
| 247 // Print PU formatting to reduce complexity of FormatOption. | 246 // Print PU formatting to reduce complexity of FormatOption. |
| 248 void Decoder::PrintPU(Instruction* instr) { | 247 void Decoder::PrintPU(Instruction* instr) { |
| 249 switch (instr->PUField()) { | 248 switch (instr->PUField()) { |
| 250 case da_x: { | 249 case da_x: { |
| 251 Print("da"); | 250 Print("da"); |
| 252 break; | 251 break; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 276 void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) { | 275 void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) { |
| 277 switch (svc) { | 276 switch (svc) { |
| 278 case kCallRtRedirected: | 277 case kCallRtRedirected: |
| 279 Print("call rt redirected"); | 278 Print("call rt redirected"); |
| 280 return; | 279 return; |
| 281 case kBreakpoint: | 280 case kBreakpoint: |
| 282 Print("breakpoint"); | 281 Print("breakpoint"); |
| 283 return; | 282 return; |
| 284 default: | 283 default: |
| 285 if (svc >= kStopCode) { | 284 if (svc >= kStopCode) { |
| 286 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 285 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 287 "%d - 0x%x", | 286 "%d - 0x%x", |
| 288 svc & kStopCodeMask, | 287 svc & kStopCodeMask, |
| 289 svc & kStopCodeMask); | 288 svc & kStopCodeMask); |
| 290 } else { | 289 } else { |
| 291 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 290 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 292 "%d", | 291 "%d", |
| 293 svc); | 292 svc); |
| 294 } | 293 } |
| 295 return; | 294 return; |
| 296 } | 295 } |
| 297 } | 296 } |
| 298 | 297 |
| 299 | 298 |
| 300 // Handle all register based formatting in this function to reduce the | 299 // Handle all register based formatting in this function to reduce the |
| 301 // complexity of FormatOption. | 300 // complexity of FormatOption. |
| 302 int Decoder::FormatRegister(Instruction* instr, const char* format) { | 301 int Decoder::FormatRegister(Instruction* instr, const char* format) { |
| 303 ASSERT(format[0] == 'r'); | 302 ASSERT(format[0] == 'r'); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 | 391 |
| 393 | 392 |
| 394 int Decoder::FormatVFPinstruction(Instruction* instr, const char* format) { | 393 int Decoder::FormatVFPinstruction(Instruction* instr, const char* format) { |
| 395 Print(format); | 394 Print(format); |
| 396 return 0; | 395 return 0; |
| 397 } | 396 } |
| 398 | 397 |
| 399 | 398 |
| 400 void Decoder::FormatNeonList(int Vd, int type) { | 399 void Decoder::FormatNeonList(int Vd, int type) { |
| 401 if (type == nlt_1) { | 400 if (type == nlt_1) { |
| 402 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 401 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 403 "{d%d}", Vd); | 402 "{d%d}", Vd); |
| 404 } else if (type == nlt_2) { | 403 } else if (type == nlt_2) { |
| 405 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 404 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 406 "{d%d, d%d}", Vd, Vd + 1); | 405 "{d%d, d%d}", Vd, Vd + 1); |
| 407 } else if (type == nlt_3) { | 406 } else if (type == nlt_3) { |
| 408 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 407 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 409 "{d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2); | 408 "{d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2); |
| 410 } else if (type == nlt_4) { | 409 } else if (type == nlt_4) { |
| 411 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 410 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 412 "{d%d, d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2, Vd + 3); | 411 "{d%d, d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2, Vd + 3); |
| 413 } | 412 } |
| 414 } | 413 } |
| 415 | 414 |
| 416 | 415 |
| 417 void Decoder::FormatNeonMemory(int Rn, int align, int Rm) { | 416 void Decoder::FormatNeonMemory(int Rn, int align, int Rm) { |
| 418 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 417 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 419 "[r%d", Rn); | 418 "[r%d", Rn); |
| 420 if (align != 0) { | 419 if (align != 0) { |
| 421 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 420 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 422 ":%d", (1 << align) << 6); | 421 ":%d", (1 << align) << 6); |
| 423 } | 422 } |
| 424 if (Rm == 15) { | 423 if (Rm == 15) { |
| 425 Print("]"); | 424 Print("]"); |
| 426 } else if (Rm == 13) { | 425 } else if (Rm == 13) { |
| 427 Print("]!"); | 426 Print("]!"); |
| 428 } else { | 427 } else { |
| 429 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 428 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 430 "], r%d", Rm); | 429 "], r%d", Rm); |
| 431 } | 430 } |
| 432 } | 431 } |
| 433 | 432 |
| 434 | 433 |
| 435 // Print the movw or movt instruction. | 434 // Print the movw or movt instruction. |
| 436 void Decoder::PrintMovwMovt(Instruction* instr) { | 435 void Decoder::PrintMovwMovt(Instruction* instr) { |
| 437 int imm = instr->ImmedMovwMovtValue(); | 436 int imm = instr->ImmedMovwMovtValue(); |
| 438 int rd = instr->RdValue(); | 437 int rd = instr->RdValue(); |
| 439 PrintRegister(rd); | 438 PrintRegister(rd); |
| 440 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 439 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, ", #%d", imm); |
| 441 ", #%d", imm); | |
| 442 } | 440 } |
| 443 | 441 |
| 444 | 442 |
| 445 // FormatOption takes a formatting string and interprets it based on | 443 // FormatOption takes a formatting string and interprets it based on |
| 446 // the current instructions. The format string points to the first | 444 // the current instructions. The format string points to the first |
| 447 // character of the option string (the option escape has already been | 445 // character of the option string (the option escape has already been |
| 448 // consumed by the caller.) FormatOption returns the number of | 446 // consumed by the caller.) FormatOption returns the number of |
| 449 // characters that were consumed from the formatting string. | 447 // characters that were consumed from the formatting string. |
| 450 int Decoder::FormatOption(Instruction* instr, const char* format) { | 448 int Decoder::FormatOption(Instruction* instr, const char* format) { |
| 451 switch (format[0]) { | 449 switch (format[0]) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 463 } | 461 } |
| 464 return 1; | 462 return 1; |
| 465 } | 463 } |
| 466 case 'c': { // 'cond: conditional execution | 464 case 'c': { // 'cond: conditional execution |
| 467 ASSERT(STRING_STARTS_WITH(format, "cond")); | 465 ASSERT(STRING_STARTS_WITH(format, "cond")); |
| 468 PrintCondition(instr); | 466 PrintCondition(instr); |
| 469 return 4; | 467 return 4; |
| 470 } | 468 } |
| 471 case 'd': { // 'd: vmov double immediate. | 469 case 'd': { // 'd: vmov double immediate. |
| 472 double d = instr->DoubleImmedVmov(); | 470 double d = instr->DoubleImmedVmov(); |
| 473 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 471 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%g", d); |
| 474 "#%g", d); | |
| 475 return 1; | 472 return 1; |
| 476 } | 473 } |
| 477 case 'f': { // 'f: bitfield instructions - v7 and above. | 474 case 'f': { // 'f: bitfield instructions - v7 and above. |
| 478 uint32_t lsbit = instr->Bits(11, 7); | 475 uint32_t lsbit = instr->Bits(11, 7); |
| 479 uint32_t width = instr->Bits(20, 16) + 1; | 476 uint32_t width = instr->Bits(20, 16) + 1; |
| 480 if (instr->Bit(21) == 0) { | 477 if (instr->Bit(21) == 0) { |
| 481 // BFC/BFI: | 478 // BFC/BFI: |
| 482 // Bits 20-16 represent most-significant bit. Covert to width. | 479 // Bits 20-16 represent most-significant bit. Covert to width. |
| 483 width -= lsbit; | 480 width -= lsbit; |
| 484 ASSERT(width > 0); | 481 ASSERT(width > 0); |
| 485 } | 482 } |
| 486 ASSERT((width + lsbit) <= 32); | 483 ASSERT((width + lsbit) <= 32); |
| 487 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 484 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 488 "#%d, #%d", lsbit, width); | 485 "#%d, #%d", lsbit, width); |
| 489 return 1; | 486 return 1; |
| 490 } | 487 } |
| 491 case 'h': { // 'h: halfword operation for extra loads and stores | 488 case 'h': { // 'h: halfword operation for extra loads and stores |
| 492 if (instr->HasH()) { | 489 if (instr->HasH()) { |
| 493 Print("h"); | 490 Print("h"); |
| 494 } else { | 491 } else { |
| 495 Print("b"); | 492 Print("b"); |
| 496 } | 493 } |
| 497 return 1; | 494 return 1; |
| 498 } | 495 } |
| 499 case 'i': { // 'i: immediate value from adjacent bits. | 496 case 'i': { // 'i: immediate value from adjacent bits. |
| 500 // Expects tokens in the form imm%02d@%02d, i.e. imm05@07, imm10@16 | 497 // Expects tokens in the form imm%02d@%02d, i.e. imm05@07, imm10@16 |
| 501 int width = (format[3] - '0') * 10 + (format[4] - '0'); | 498 int width = (format[3] - '0') * 10 + (format[4] - '0'); |
| 502 int lsb = (format[6] - '0') * 10 + (format[7] - '0'); | 499 int lsb = (format[6] - '0') * 10 + (format[7] - '0'); |
| 503 | 500 |
| 504 ASSERT((width >= 1) && (width <= 32)); | 501 ASSERT((width >= 1) && (width <= 32)); |
| 505 ASSERT((lsb >= 0) && (lsb <= 31)); | 502 ASSERT((lsb >= 0) && (lsb <= 31)); |
| 506 ASSERT((width + lsb) <= 32); | 503 ASSERT((width + lsb) <= 32); |
| 507 | 504 |
| 508 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 505 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 509 "%d", | 506 "%d", |
| 510 instr->Bits(width + lsb - 1, lsb)); | 507 instr->Bits(width + lsb - 1, lsb)); |
| 511 return 8; | 508 return 8; |
| 512 } | 509 } |
| 513 case 'l': { // 'l: branch and link | 510 case 'l': { // 'l: branch and link |
| 514 if (instr->HasLink()) { | 511 if (instr->HasLink()) { |
| 515 Print("l"); | 512 Print("l"); |
| 516 } | 513 } |
| 517 return 1; | 514 return 1; |
| 518 } | 515 } |
| 519 case 'm': { | 516 case 'm': { |
| 520 if (format[1] == 'w') { | 517 if (format[1] == 'w') { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 537 return 5; | 534 return 5; |
| 538 } | 535 } |
| 539 Print("str"); | 536 Print("str"); |
| 540 } | 537 } |
| 541 return 5; | 538 return 5; |
| 542 } | 539 } |
| 543 // 'msg: for simulator break instructions | 540 // 'msg: for simulator break instructions |
| 544 ASSERT(STRING_STARTS_WITH(format, "msg")); | 541 ASSERT(STRING_STARTS_WITH(format, "msg")); |
| 545 byte* str = | 542 byte* str = |
| 546 reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff); | 543 reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff); |
| 547 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 544 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 548 "%s", converter_.NameInCode(str)); | 545 "%s", converter_.NameInCode(str)); |
| 549 return 3; | 546 return 3; |
| 550 } | 547 } |
| 551 case 'o': { | 548 case 'o': { |
| 552 if ((format[3] == '1') && (format[4] == '2')) { | 549 if ((format[3] == '1') && (format[4] == '2')) { |
| 553 // 'off12: 12-bit offset for load and store instructions | 550 // 'off12: 12-bit offset for load and store instructions |
| 554 ASSERT(STRING_STARTS_WITH(format, "off12")); | 551 ASSERT(STRING_STARTS_WITH(format, "off12")); |
| 555 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 552 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 556 "%d", instr->Offset12Value()); | 553 "%d", instr->Offset12Value()); |
| 557 return 5; | 554 return 5; |
| 558 } else if (format[3] == '0') { | 555 } else if (format[3] == '0') { |
| 559 // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0. | 556 // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0. |
| 560 ASSERT(STRING_STARTS_WITH(format, "off0to3and8to19")); | 557 ASSERT(STRING_STARTS_WITH(format, "off0to3and8to19")); |
| 561 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 558 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 562 "%d", | 559 "%d", |
| 563 (instr->Bits(19, 8) << 4) + | 560 (instr->Bits(19, 8) << 4) + |
| 564 instr->Bits(3, 0)); | 561 instr->Bits(3, 0)); |
| 565 return 15; | 562 return 15; |
| 566 } | 563 } |
| 567 // 'off8: 8-bit offset for extra load and store instructions | 564 // 'off8: 8-bit offset for extra load and store instructions |
| 568 ASSERT(STRING_STARTS_WITH(format, "off8")); | 565 ASSERT(STRING_STARTS_WITH(format, "off8")); |
| 569 int offs8 = (instr->ImmedHValue() << 4) | instr->ImmedLValue(); | 566 int offs8 = (instr->ImmedHValue() << 4) | instr->ImmedLValue(); |
| 570 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 567 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", offs8); |
| 571 "%d", offs8); | |
| 572 return 4; | 568 return 4; |
| 573 } | 569 } |
| 574 case 'p': { // 'pu: P and U bits for load and store instructions | 570 case 'p': { // 'pu: P and U bits for load and store instructions |
| 575 ASSERT(STRING_STARTS_WITH(format, "pu")); | 571 ASSERT(STRING_STARTS_WITH(format, "pu")); |
| 576 PrintPU(instr); | 572 PrintPU(instr); |
| 577 return 2; | 573 return 2; |
| 578 } | 574 } |
| 579 case 'r': { | 575 case 'r': { |
| 580 return FormatRegister(instr, format); | 576 return FormatRegister(instr, format); |
| 581 } | 577 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 612 } | 608 } |
| 613 // 's: S field of data processing instructions | 609 // 's: S field of data processing instructions |
| 614 if (instr->HasS()) { | 610 if (instr->HasS()) { |
| 615 Print("s"); | 611 Print("s"); |
| 616 } | 612 } |
| 617 return 1; | 613 return 1; |
| 618 } | 614 } |
| 619 case 't': { // 'target: target of branch instructions | 615 case 't': { // 'target: target of branch instructions |
| 620 ASSERT(STRING_STARTS_WITH(format, "target")); | 616 ASSERT(STRING_STARTS_WITH(format, "target")); |
| 621 int off = (instr->SImmed24Value() << 2) + 8; | 617 int off = (instr->SImmed24Value() << 2) + 8; |
| 622 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 618 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 623 "%+d -> %s", | 619 "%+d -> %s", |
| 624 off, | 620 off, |
| 625 converter_.NameOfAddress( | 621 converter_.NameOfAddress( |
| 626 reinterpret_cast<byte*>(instr) + off)); | 622 reinterpret_cast<byte*>(instr) + off)); |
| 627 return 6; | 623 return 6; |
| 628 } | 624 } |
| 629 case 'u': { // 'u: signed or unsigned multiplies | 625 case 'u': { // 'u: signed or unsigned multiplies |
| 630 // The manual gets the meaning of bit 22 backwards in the multiply | 626 // The manual gets the meaning of bit 22 backwards in the multiply |
| 631 // instruction overview on page A3.16.2. The instructions that | 627 // instruction overview on page A3.16.2. The instructions that |
| 632 // exist in u and s variants are the following: | 628 // exist in u and s variants are the following: |
| 633 // smull A4.1.87 | 629 // smull A4.1.87 |
| 634 // umull A4.1.129 | 630 // umull A4.1.129 |
| 635 // umlal A4.1.128 | 631 // umlal A4.1.128 |
| 636 // smlal A4.1.76 | 632 // smlal A4.1.76 |
| (...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1177 DecodeType6CoprocessorIns(instr); | 1173 DecodeType6CoprocessorIns(instr); |
| 1178 } | 1174 } |
| 1179 | 1175 |
| 1180 | 1176 |
| 1181 int Decoder::DecodeType7(Instruction* instr) { | 1177 int Decoder::DecodeType7(Instruction* instr) { |
| 1182 if (instr->Bit(24) == 1) { | 1178 if (instr->Bit(24) == 1) { |
| 1183 if (instr->SvcValue() >= kStopCode) { | 1179 if (instr->SvcValue() >= kStopCode) { |
| 1184 Format(instr, "stop'cond 'svc"); | 1180 Format(instr, "stop'cond 'svc"); |
| 1185 // Also print the stop message. Its address is encoded | 1181 // Also print the stop message. Its address is encoded |
| 1186 // in the following 4 bytes. | 1182 // in the following 4 bytes. |
| 1187 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 1183 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 1188 "\n %p %08x stop message: %s", | 1184 "\n %p %08x stop message: %s", |
| 1189 reinterpret_cast<int32_t*>(instr | 1185 reinterpret_cast<void*>(instr |
| 1190 + Instruction::kInstrSize), | 1186 + Instruction::kInstrSize), |
| 1191 *reinterpret_cast<char**>(instr | 1187 *reinterpret_cast<uint32_t*>(instr |
| 1192 + Instruction::kInstrSize), | 1188 + Instruction::kInstrSize), |
| 1193 *reinterpret_cast<char**>(instr | 1189 *reinterpret_cast<char**>(instr |
| 1194 + Instruction::kInstrSize)); | 1190 + Instruction::kInstrSize)); |
| 1195 // We have decoded 2 * Instruction::kInstrSize bytes. | 1191 // We have decoded 2 * Instruction::kInstrSize bytes. |
| 1196 return 2 * Instruction::kInstrSize; | 1192 return 2 * Instruction::kInstrSize; |
| 1197 } else { | 1193 } else { |
| 1198 Format(instr, "svc'cond 'svc"); | 1194 Format(instr, "svc'cond 'svc"); |
| 1199 } | 1195 } |
| 1200 } else { | 1196 } else { |
| 1201 DecodeTypeVFP(instr); | 1197 DecodeTypeVFP(instr); |
| 1202 } | 1198 } |
| 1203 return Instruction::kInstrSize; | 1199 return Instruction::kInstrSize; |
| 1204 } | 1200 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1244 Format(instr, "vneg'cond.f64 'Dd, 'Dm"); | 1240 Format(instr, "vneg'cond.f64 'Dd, 'Dm"); |
| 1245 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { | 1241 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { |
| 1246 DecodeVCVTBetweenDoubleAndSingle(instr); | 1242 DecodeVCVTBetweenDoubleAndSingle(instr); |
| 1247 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { | 1243 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { |
| 1248 DecodeVCVTBetweenFloatingPointAndInteger(instr); | 1244 DecodeVCVTBetweenFloatingPointAndInteger(instr); |
| 1249 } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) && | 1245 } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) && |
| 1250 (instr->Bit(8) == 1)) { | 1246 (instr->Bit(8) == 1)) { |
| 1251 // vcvt.f64.s32 Dd, Dd, #<fbits> | 1247 // vcvt.f64.s32 Dd, Dd, #<fbits> |
| 1252 int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5)); | 1248 int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5)); |
| 1253 Format(instr, "vcvt'cond.f64.s32 'Dd, 'Dd"); | 1249 Format(instr, "vcvt'cond.f64.s32 'Dd, 'Dd"); |
| 1254 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 1250 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 1255 ", #%d", fraction_bits); | 1251 ", #%d", fraction_bits); |
| 1256 } else if (((instr->Opc2Value() >> 1) == 0x6) && | 1252 } else if (((instr->Opc2Value() >> 1) == 0x6) && |
| 1257 (instr->Opc3Value() & 0x1)) { | 1253 (instr->Opc3Value() & 0x1)) { |
| 1258 DecodeVCVTBetweenFloatingPointAndInteger(instr); | 1254 DecodeVCVTBetweenFloatingPointAndInteger(instr); |
| 1259 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && | 1255 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && |
| 1260 (instr->Opc3Value() & 0x1)) { | 1256 (instr->Opc3Value() & 0x1)) { |
| 1261 DecodeVCMP(instr); | 1257 DecodeVCMP(instr); |
| 1262 } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) { | 1258 } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) { |
| 1263 Format(instr, "vsqrt'cond.f64 'Dd, 'Dm"); | 1259 Format(instr, "vsqrt'cond.f64 'Dd, 'Dm"); |
| 1264 } else if (instr->Opc3Value() == 0x0) { | 1260 } else if (instr->Opc3Value() == 0x0) { |
| 1265 if (instr->SzValue() == 0x1) { | 1261 if (instr->SzValue() == 0x1) { |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1540 void Decoder::DecodeSpecialCondition(Instruction* instr) { | 1536 void Decoder::DecodeSpecialCondition(Instruction* instr) { |
| 1541 switch (instr->SpecialValue()) { | 1537 switch (instr->SpecialValue()) { |
| 1542 case 5: | 1538 case 5: |
| 1543 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && | 1539 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && |
| 1544 (instr->Bit(4) == 1)) { | 1540 (instr->Bit(4) == 1)) { |
| 1545 // vmovl signed | 1541 // vmovl signed |
| 1546 if ((instr->VdValue() & 1) != 0) Unknown(instr); | 1542 if ((instr->VdValue() & 1) != 0) Unknown(instr); |
| 1547 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1); | 1543 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1); |
| 1548 int Vm = (instr->Bit(5) << 4) | instr->VmValue(); | 1544 int Vm = (instr->Bit(5) << 4) | instr->VmValue(); |
| 1549 int imm3 = instr->Bits(21, 19); | 1545 int imm3 = instr->Bits(21, 19); |
| 1550 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 1546 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 1551 "vmovl.s%d q%d, d%d", imm3*8, Vd, Vm); | 1547 "vmovl.s%d q%d, d%d", imm3*8, Vd, Vm); |
| 1552 } else { | 1548 } else { |
| 1553 Unknown(instr); | 1549 Unknown(instr); |
| 1554 } | 1550 } |
| 1555 break; | 1551 break; |
| 1556 case 7: | 1552 case 7: |
| 1557 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && | 1553 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && |
| 1558 (instr->Bit(4) == 1)) { | 1554 (instr->Bit(4) == 1)) { |
| 1559 // vmovl unsigned | 1555 // vmovl unsigned |
| 1560 if ((instr->VdValue() & 1) != 0) Unknown(instr); | 1556 if ((instr->VdValue() & 1) != 0) Unknown(instr); |
| 1561 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1); | 1557 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1); |
| 1562 int Vm = (instr->Bit(5) << 4) | instr->VmValue(); | 1558 int Vm = (instr->Bit(5) << 4) | instr->VmValue(); |
| 1563 int imm3 = instr->Bits(21, 19); | 1559 int imm3 = instr->Bits(21, 19); |
| 1564 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 1560 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 1565 "vmovl.u%d q%d, d%d", imm3*8, Vd, Vm); | 1561 "vmovl.u%d q%d, d%d", imm3*8, Vd, Vm); |
| 1566 } else { | 1562 } else { |
| 1567 Unknown(instr); | 1563 Unknown(instr); |
| 1568 } | 1564 } |
| 1569 break; | 1565 break; |
| 1570 case 8: | 1566 case 8: |
| 1571 if (instr->Bits(21, 20) == 0) { | 1567 if (instr->Bits(21, 20) == 0) { |
| 1572 // vst1 | 1568 // vst1 |
| 1573 int Vd = (instr->Bit(22) << 4) | instr->VdValue(); | 1569 int Vd = (instr->Bit(22) << 4) | instr->VdValue(); |
| 1574 int Rn = instr->VnValue(); | 1570 int Rn = instr->VnValue(); |
| 1575 int type = instr->Bits(11, 8); | 1571 int type = instr->Bits(11, 8); |
| 1576 int size = instr->Bits(7, 6); | 1572 int size = instr->Bits(7, 6); |
| 1577 int align = instr->Bits(5, 4); | 1573 int align = instr->Bits(5, 4); |
| 1578 int Rm = instr->VmValue(); | 1574 int Rm = instr->VmValue(); |
| 1579 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 1575 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 1580 "vst1.%d ", (1 << size) << 3); | 1576 "vst1.%d ", (1 << size) << 3); |
| 1581 FormatNeonList(Vd, type); | 1577 FormatNeonList(Vd, type); |
| 1582 Print(", "); | 1578 Print(", "); |
| 1583 FormatNeonMemory(Rn, align, Rm); | 1579 FormatNeonMemory(Rn, align, Rm); |
| 1584 } else if (instr->Bits(21, 20) == 2) { | 1580 } else if (instr->Bits(21, 20) == 2) { |
| 1585 // vld1 | 1581 // vld1 |
| 1586 int Vd = (instr->Bit(22) << 4) | instr->VdValue(); | 1582 int Vd = (instr->Bit(22) << 4) | instr->VdValue(); |
| 1587 int Rn = instr->VnValue(); | 1583 int Rn = instr->VnValue(); |
| 1588 int type = instr->Bits(11, 8); | 1584 int type = instr->Bits(11, 8); |
| 1589 int size = instr->Bits(7, 6); | 1585 int size = instr->Bits(7, 6); |
| 1590 int align = instr->Bits(5, 4); | 1586 int align = instr->Bits(5, 4); |
| 1591 int Rm = instr->VmValue(); | 1587 int Rm = instr->VmValue(); |
| 1592 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 1588 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 1593 "vld1.%d ", (1 << size) << 3); | 1589 "vld1.%d ", (1 << size) << 3); |
| 1594 FormatNeonList(Vd, type); | 1590 FormatNeonList(Vd, type); |
| 1595 Print(", "); | 1591 Print(", "); |
| 1596 FormatNeonMemory(Rn, align, Rm); | 1592 FormatNeonMemory(Rn, align, Rm); |
| 1597 } else { | 1593 } else { |
| 1598 Unknown(instr); | 1594 Unknown(instr); |
| 1599 } | 1595 } |
| 1600 break; | 1596 break; |
| 1601 case 0xA: | 1597 case 0xA: |
| 1602 case 0xB: | 1598 case 0xB: |
| 1603 if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) { | 1599 if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) { |
| 1604 int Rn = instr->Bits(19, 16); | 1600 int Rn = instr->Bits(19, 16); |
| 1605 int offset = instr->Bits(11, 0); | 1601 int offset = instr->Bits(11, 0); |
| 1606 if (offset == 0) { | 1602 if (offset == 0) { |
| 1607 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 1603 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 1608 "pld [r%d]", Rn); | 1604 "pld [r%d]", Rn); |
| 1609 } else if (instr->Bit(23) == 0) { | 1605 } else if (instr->Bit(23) == 0) { |
| 1610 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 1606 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 1611 "pld [r%d, #-%d]", Rn, offset); | 1607 "pld [r%d, #-%d]", Rn, offset); |
| 1612 } else { | 1608 } else { |
| 1613 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 1609 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 1614 "pld [r%d, #+%d]", Rn, offset); | 1610 "pld [r%d, #+%d]", Rn, offset); |
| 1615 } | 1611 } |
| 1616 } else { | 1612 } else { |
| 1617 Unknown(instr); | 1613 Unknown(instr); |
| 1618 } | 1614 } |
| 1619 break; | 1615 break; |
| 1620 default: | 1616 default: |
| 1621 Unknown(instr); | 1617 Unknown(instr); |
| 1622 break; | 1618 break; |
| 1623 } | 1619 } |
| 1624 } | 1620 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1638 } else { | 1634 } else { |
| 1639 return -1; | 1635 return -1; |
| 1640 } | 1636 } |
| 1641 } | 1637 } |
| 1642 | 1638 |
| 1643 | 1639 |
| 1644 // Disassemble the instruction at *instr_ptr into the output buffer. | 1640 // Disassemble the instruction at *instr_ptr into the output buffer. |
| 1645 int Decoder::InstructionDecode(byte* instr_ptr) { | 1641 int Decoder::InstructionDecode(byte* instr_ptr) { |
| 1646 Instruction* instr = Instruction::At(instr_ptr); | 1642 Instruction* instr = Instruction::At(instr_ptr); |
| 1647 // Print raw instruction bytes. | 1643 // Print raw instruction bytes. |
| 1648 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 1644 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 1649 "%08x ", | 1645 "%08x ", |
| 1650 instr->InstructionBits()); | 1646 instr->InstructionBits()); |
| 1651 if (instr->ConditionField() == kSpecialCondition) { | 1647 if (instr->ConditionField() == kSpecialCondition) { |
| 1652 DecodeSpecialCondition(instr); | 1648 DecodeSpecialCondition(instr); |
| 1653 return Instruction::kInstrSize; | 1649 return Instruction::kInstrSize; |
| 1654 } | 1650 } |
| 1655 int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); | 1651 int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); |
| 1656 if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) { | 1652 if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) { |
| 1657 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 1653 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 1658 "constant pool begin (length %d)", | 1654 "constant pool begin (length %d)", |
| 1659 DecodeConstantPoolLength(instruction_bits)); | 1655 DecodeConstantPoolLength(instruction_bits)); |
| 1660 return Instruction::kInstrSize; | 1656 return Instruction::kInstrSize; |
| 1661 } else if (instruction_bits == kCodeAgeJumpInstruction) { | 1657 } else if (instruction_bits == kCodeAgeJumpInstruction) { |
| 1662 // The code age prologue has a constant immediatly following the jump | 1658 // The code age prologue has a constant immediatly following the jump |
| 1663 // instruction. | 1659 // instruction. |
| 1664 Instruction* target = Instruction::At(instr_ptr + Instruction::kInstrSize); | 1660 Instruction* target = Instruction::At(instr_ptr + Instruction::kInstrSize); |
| 1665 DecodeType2(instr); | 1661 DecodeType2(instr); |
| 1666 OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 1662 SNPrintF(out_buffer_ + out_buffer_pos_, |
| 1667 " (0x%08x)", target->InstructionBits()); | 1663 " (0x%08x)", target->InstructionBits()); |
| 1668 return 2 * Instruction::kInstrSize; | 1664 return 2 * Instruction::kInstrSize; |
| 1669 } | 1665 } |
| 1670 switch (instr->TypeValue()) { | 1666 switch (instr->TypeValue()) { |
| 1671 case 0: | 1667 case 0: |
| 1672 case 1: { | 1668 case 1: { |
| 1673 DecodeType01(instr); | 1669 DecodeType01(instr); |
| 1674 break; | 1670 break; |
| 1675 } | 1671 } |
| 1676 case 2: { | 1672 case 2: { |
| 1677 DecodeType2(instr); | 1673 DecodeType2(instr); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1709 } } // namespace v8::internal | 1705 } } // namespace v8::internal |
| 1710 | 1706 |
| 1711 | 1707 |
| 1712 | 1708 |
| 1713 //------------------------------------------------------------------------------ | 1709 //------------------------------------------------------------------------------ |
| 1714 | 1710 |
| 1715 namespace disasm { | 1711 namespace disasm { |
| 1716 | 1712 |
| 1717 | 1713 |
| 1718 const char* NameConverter::NameOfAddress(byte* addr) const { | 1714 const char* NameConverter::NameOfAddress(byte* addr) const { |
| 1719 v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr); | 1715 v8::internal::SNPrintF(tmp_buffer_, "%p", addr); |
| 1720 return tmp_buffer_.start(); | 1716 return tmp_buffer_.start(); |
| 1721 } | 1717 } |
| 1722 | 1718 |
| 1723 | 1719 |
| 1724 const char* NameConverter::NameOfConstant(byte* addr) const { | 1720 const char* NameConverter::NameOfConstant(byte* addr) const { |
| 1725 return NameOfAddress(addr); | 1721 return NameOfAddress(addr); |
| 1726 } | 1722 } |
| 1727 | 1723 |
| 1728 | 1724 |
| 1729 const char* NameConverter::NameOfCPURegister(int reg) const { | 1725 const char* NameConverter::NameOfCPURegister(int reg) const { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1782 v8::internal::PrintF( | 1778 v8::internal::PrintF( |
| 1783 f, "%p %08x %s\n", | 1779 f, "%p %08x %s\n", |
| 1784 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1780 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
| 1785 } | 1781 } |
| 1786 } | 1782 } |
| 1787 | 1783 |
| 1788 | 1784 |
| 1789 } // namespace disasm | 1785 } // namespace disasm |
| 1790 | 1786 |
| 1791 #endif // V8_TARGET_ARCH_ARM | 1787 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |