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 |