Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
| 2 // All Rights Reserved. | 2 // All Rights Reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
| 9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
| 10 // | 10 // |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 290 desc->buffer = buffer_; | 290 desc->buffer = buffer_; |
| 291 desc->buffer_size = buffer_size_; | 291 desc->buffer_size = buffer_size_; |
| 292 desc->instr_size = pc_offset(); | 292 desc->instr_size = pc_offset(); |
| 293 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); | 293 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); |
| 294 desc->origin = this; | 294 desc->origin = this; |
| 295 } | 295 } |
| 296 | 296 |
| 297 | 297 |
| 298 void Assembler::Align(int m) { | 298 void Assembler::Align(int m) { |
| 299 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m)); | 299 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m)); |
| 300 if (IsPrevInstrCompactBranch()) { | |
| 301 nop(); | |
| 302 ClearCompactBranchState(); | |
| 303 } | |
| 300 while ((pc_offset() & (m - 1)) != 0) { | 304 while ((pc_offset() & (m - 1)) != 0) { |
| 301 nop(); | 305 nop(); |
| 302 } | 306 } |
| 303 } | 307 } |
| 304 | 308 |
| 305 | 309 |
| 306 void Assembler::CodeTargetAlign() { | 310 void Assembler::CodeTargetAlign() { |
| 307 // No advantage to aligning branch/call targets to more than | 311 // No advantage to aligning branch/call targets to more than |
| 308 // single instruction, that I am aware of. | 312 // single instruction, that I am aware of. |
| 309 Align(4); | 313 Align(4); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 446 const int kEndOfChain = -4; | 450 const int kEndOfChain = -4; |
| 447 // Determines the end of the Jump chain (a subset of the label link chain). | 451 // Determines the end of the Jump chain (a subset of the label link chain). |
| 448 const int kEndOfJumpChain = 0; | 452 const int kEndOfJumpChain = 0; |
| 449 | 453 |
| 450 | 454 |
| 451 bool Assembler::IsBranch(Instr instr) { | 455 bool Assembler::IsBranch(Instr instr) { |
| 452 uint32_t opcode = GetOpcodeField(instr); | 456 uint32_t opcode = GetOpcodeField(instr); |
| 453 uint32_t rt_field = GetRtField(instr); | 457 uint32_t rt_field = GetRtField(instr); |
| 454 uint32_t rs_field = GetRsField(instr); | 458 uint32_t rs_field = GetRsField(instr); |
| 455 // Checks if the instruction is a branch. | 459 // Checks if the instruction is a branch. |
| 456 return opcode == BEQ || | 460 bool isBranch = |
| 457 opcode == BNE || | 461 opcode == BEQ || opcode == BNE || opcode == BLEZ || opcode == BGTZ || |
| 458 opcode == BLEZ || | 462 opcode == BEQL || opcode == BNEL || opcode == BLEZL || opcode == BGTZL || |
| 459 opcode == BGTZ || | |
| 460 opcode == BEQL || | |
| 461 opcode == BNEL || | |
| 462 opcode == BLEZL || | |
| 463 opcode == BGTZL || | |
| 464 (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ || | 463 (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ || |
| 465 rt_field == BLTZAL || rt_field == BGEZAL)) || | 464 rt_field == BLTZAL || rt_field == BGEZAL)) || |
| 466 (opcode == COP1 && rs_field == BC1) || // Coprocessor branch. | 465 (opcode == COP1 && rs_field == BC1) || // Coprocessor branch. |
| 467 (opcode == COP1 && rs_field == BC1EQZ) || | 466 (opcode == COP1 && rs_field == BC1EQZ) || |
| 468 (opcode == COP1 && rs_field == BC1NEZ); | 467 (opcode == COP1 && rs_field == BC1NEZ); |
| 468 if (!isBranch && IsMipsArchVariant(kMips32r6)) { | |
| 469 // All the 3 variants of POP10 (BOVC, BEQC, BEQZALC) and | |
| 470 // POP30 (BNVC, BNEC, BNEZALC) are branch ops. | |
| 471 isBranch |= opcode == POP10 || opcode == POP30 || opcode == BC || | |
| 472 opcode == BALC || | |
| 473 (opcode == POP66 && rs_field != 0) || // BEQZC | |
| 474 (opcode == POP76 && rs_field != 0); // BNEZC | |
| 475 } | |
| 476 return isBranch; | |
| 469 } | 477 } |
| 470 | 478 |
| 471 | 479 |
| 480 bool Assembler::IsBc(Instr instr) { | |
| 481 uint32_t opcode = GetOpcodeField(instr); | |
| 482 // Checks if the instruction is a BC or BALC. | |
| 483 return opcode == BC || opcode == BALC; | |
| 484 } | |
| 485 | |
| 486 | |
| 487 bool Assembler::IsBzc(Instr instr) { | |
| 488 uint32_t opcode = GetOpcodeField(instr); | |
| 489 // Checks if the instruction is BEQZC or BNEZC. | |
| 490 return (opcode == POP66 && GetRsField(instr) != 0) || | |
| 491 (opcode == POP76 && GetRsField(instr) != 0); | |
| 492 } | |
| 493 | |
| 494 | |
| 472 bool Assembler::IsEmittedConstant(Instr instr) { | 495 bool Assembler::IsEmittedConstant(Instr instr) { |
| 473 uint32_t label_constant = GetLabelConst(instr); | 496 uint32_t label_constant = GetLabelConst(instr); |
| 474 return label_constant == 0; // Emitted label const in reg-exp engine. | 497 return label_constant == 0; // Emitted label const in reg-exp engine. |
| 475 } | 498 } |
| 476 | 499 |
| 477 | 500 |
| 478 bool Assembler::IsBeq(Instr instr) { | 501 bool Assembler::IsBeq(Instr instr) { |
| 479 return GetOpcodeField(instr) == BEQ; | 502 return GetOpcodeField(instr) == BEQ; |
| 480 } | 503 } |
| 481 | 504 |
| 482 | 505 |
| 483 bool Assembler::IsBne(Instr instr) { | 506 bool Assembler::IsBne(Instr instr) { |
| 484 return GetOpcodeField(instr) == BNE; | 507 return GetOpcodeField(instr) == BNE; |
| 485 } | 508 } |
| 486 | 509 |
| 487 | 510 |
| 511 bool Assembler::IsBeqzc(Instr instr) { | |
| 512 uint32_t opcode = GetOpcodeField(instr); | |
| 513 return opcode == POP66 && GetRsField(instr) != 0; | |
| 514 } | |
| 515 | |
| 516 | |
| 517 bool Assembler::IsBnezc(Instr instr) { | |
| 518 uint32_t opcode = GetOpcodeField(instr); | |
| 519 return opcode == POP76 && GetRsField(instr) != 0; | |
| 520 } | |
| 521 | |
| 522 | |
| 523 bool Assembler::IsBeqc(Instr instr) { | |
| 524 uint32_t opcode = GetOpcodeField(instr); | |
| 525 uint32_t rs = GetRsField(instr); | |
| 526 uint32_t rt = GetRtField(instr); | |
| 527 return opcode == POP10 && rs != 0 && rs < rt; // && rt != 0 | |
| 528 } | |
| 529 | |
| 530 | |
| 531 bool Assembler::IsBnec(Instr instr) { | |
| 532 uint32_t opcode = GetOpcodeField(instr); | |
| 533 uint32_t rs = GetRsField(instr); | |
| 534 uint32_t rt = GetRtField(instr); | |
| 535 return opcode == POP30 && rs != 0 && rs < rt; // && rt != 0 | |
| 536 } | |
| 537 | |
| 538 | |
| 488 bool Assembler::IsJump(Instr instr) { | 539 bool Assembler::IsJump(Instr instr) { |
| 489 uint32_t opcode = GetOpcodeField(instr); | 540 uint32_t opcode = GetOpcodeField(instr); |
| 490 uint32_t rt_field = GetRtField(instr); | 541 uint32_t rt_field = GetRtField(instr); |
| 491 uint32_t rd_field = GetRdField(instr); | 542 uint32_t rd_field = GetRdField(instr); |
| 492 uint32_t function_field = GetFunctionField(instr); | 543 uint32_t function_field = GetFunctionField(instr); |
| 493 // Checks if the instruction is a jump. | 544 // Checks if the instruction is a jump. |
| 494 return opcode == J || opcode == JAL || | 545 return opcode == J || opcode == JAL || |
| 495 (opcode == SPECIAL && rt_field == 0 && | 546 (opcode == SPECIAL && rt_field == 0 && |
| 496 ((function_field == JALR) || (rd_field == 0 && (function_field == JR)))); | 547 ((function_field == JALR) || (rd_field == 0 && (function_field == JR)))); |
| 497 } | 548 } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 563 } | 614 } |
| 564 | 615 |
| 565 | 616 |
| 566 int32_t Assembler::GetBranchOffset(Instr instr) { | 617 int32_t Assembler::GetBranchOffset(Instr instr) { |
| 567 DCHECK(IsBranch(instr)); | 618 DCHECK(IsBranch(instr)); |
| 568 return (static_cast<int16_t>(instr & kImm16Mask)) << 2; | 619 return (static_cast<int16_t>(instr & kImm16Mask)) << 2; |
| 569 } | 620 } |
| 570 | 621 |
| 571 | 622 |
| 572 bool Assembler::IsLw(Instr instr) { | 623 bool Assembler::IsLw(Instr instr) { |
| 573 return ((instr & kOpcodeMask) == LW); | 624 return (static_cast<uint32_t>(instr & kOpcodeMask) == LW); |
| 574 } | 625 } |
| 575 | 626 |
| 576 | 627 |
| 577 int16_t Assembler::GetLwOffset(Instr instr) { | 628 int16_t Assembler::GetLwOffset(Instr instr) { |
| 578 DCHECK(IsLw(instr)); | 629 DCHECK(IsLw(instr)); |
| 579 return ((instr & kImm16Mask)); | 630 return ((instr & kImm16Mask)); |
| 580 } | 631 } |
| 581 | 632 |
| 582 | 633 |
| 583 Instr Assembler::SetLwOffset(Instr instr, int16_t offset) { | 634 Instr Assembler::SetLwOffset(Instr instr, int16_t offset) { |
| 584 DCHECK(IsLw(instr)); | 635 DCHECK(IsLw(instr)); |
| 585 | 636 |
| 586 // We actually create a new lw instruction based on the original one. | 637 // We actually create a new lw instruction based on the original one. |
| 587 Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask) | 638 Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask) |
| 588 | (offset & kImm16Mask); | 639 | (offset & kImm16Mask); |
| 589 | 640 |
| 590 return temp_instr; | 641 return temp_instr; |
| 591 } | 642 } |
| 592 | 643 |
| 593 | 644 |
| 594 bool Assembler::IsSw(Instr instr) { | 645 bool Assembler::IsSw(Instr instr) { |
| 595 return ((instr & kOpcodeMask) == SW); | 646 return (static_cast<uint32_t>(instr & kOpcodeMask) == SW); |
| 596 } | 647 } |
| 597 | 648 |
| 598 | 649 |
| 599 Instr Assembler::SetSwOffset(Instr instr, int16_t offset) { | 650 Instr Assembler::SetSwOffset(Instr instr, int16_t offset) { |
| 600 DCHECK(IsSw(instr)); | 651 DCHECK(IsSw(instr)); |
| 601 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); | 652 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); |
| 602 } | 653 } |
| 603 | 654 |
| 604 | 655 |
| 605 bool Assembler::IsAddImmediate(Instr instr) { | 656 bool Assembler::IsAddImmediate(Instr instr) { |
| 606 return ((instr & kOpcodeMask) == ADDIU); | 657 return ((instr & kOpcodeMask) == ADDIU); |
| 607 } | 658 } |
| 608 | 659 |
| 609 | 660 |
| 610 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) { | 661 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) { |
| 611 DCHECK(IsAddImmediate(instr)); | 662 DCHECK(IsAddImmediate(instr)); |
| 612 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); | 663 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); |
| 613 } | 664 } |
| 614 | 665 |
| 615 | 666 |
| 616 bool Assembler::IsAndImmediate(Instr instr) { | 667 bool Assembler::IsAndImmediate(Instr instr) { |
| 617 return GetOpcodeField(instr) == ANDI; | 668 return GetOpcodeField(instr) == ANDI; |
| 618 } | 669 } |
| 619 | 670 |
| 620 | 671 |
| 672 static int32_t OffsetSizeInBits(Instr instr) { | |
| 673 if (IsMipsArchVariant(kMips32r6)) { | |
| 674 if (Assembler::IsBc(instr)) { | |
| 675 return 26; | |
|
ivica.bogosavljevic
2015/10/15 11:49:08
Use contstants instead of number
balazs.kilvady
2015/10/30 21:11:14
Done.
| |
| 676 } else if (Assembler::IsBzc(instr)) { | |
| 677 return 21; | |
| 678 } | |
| 679 } | |
| 680 return 16; | |
| 681 } | |
| 682 | |
| 683 | |
| 684 static inline int32_t AddBranchOffset(int pos, Instr instr) { | |
| 685 int32_t bits = OffsetSizeInBits(instr); | |
| 686 const int32_t mask = (1 << bits) - 1; | |
| 687 bits = 32 - bits; | |
| 688 | |
| 689 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming | |
| 690 // the compiler uses arithmetic shifts for signed integers. | |
| 691 int32_t imm = ((instr & mask) << bits) >> (bits - 2); | |
| 692 | |
| 693 if (imm == kEndOfChain) { | |
| 694 // EndOfChain sentinel is returned directly, not relative to pc or pos. | |
| 695 return kEndOfChain; | |
| 696 } else { | |
| 697 return pos + Assembler::kBranchPCOffset + imm; | |
| 698 } | |
| 699 } | |
| 700 | |
| 701 | |
| 621 int Assembler::target_at(int pos, bool is_internal) { | 702 int Assembler::target_at(int pos, bool is_internal) { |
| 622 Instr instr = instr_at(pos); | 703 Instr instr = instr_at(pos); |
| 623 if (is_internal) { | 704 if (is_internal) { |
| 624 if (instr == 0) { | 705 if (instr == 0) { |
| 625 return kEndOfChain; | 706 return kEndOfChain; |
| 626 } else { | 707 } else { |
| 627 int32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); | 708 int32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); |
| 628 int delta = static_cast<int>(instr_address - instr); | 709 int delta = static_cast<int>(instr_address - instr); |
| 629 DCHECK(pos > delta); | 710 DCHECK(pos > delta); |
| 630 return pos - delta; | 711 return pos - delta; |
| 631 } | 712 } |
| 632 } | 713 } |
| 633 if ((instr & ~kImm16Mask) == 0) { | 714 if ((instr & ~kImm16Mask) == 0) { |
| 634 // Emitted label constant, not part of a branch. | 715 // Emitted label constant, not part of a branch. |
| 635 if (instr == 0) { | 716 if (instr == 0) { |
| 636 return kEndOfChain; | 717 return kEndOfChain; |
| 637 } else { | 718 } else { |
| 638 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; | 719 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; |
| 639 return (imm18 + pos); | 720 return (imm18 + pos); |
| 640 } | 721 } |
| 641 } | 722 } |
| 642 // Check we have a branch or jump instruction. | 723 // Check we have a branch or jump instruction. |
| 643 DCHECK(IsBranch(instr) || IsLui(instr)); | 724 DCHECK(IsBranch(instr) || IsLui(instr)); |
| 644 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming | |
| 645 // the compiler uses arithmetic shifts for signed integers. | |
| 646 if (IsBranch(instr)) { | 725 if (IsBranch(instr)) { |
| 647 int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; | 726 return AddBranchOffset(pos, instr); |
| 648 | 727 } else { |
| 649 if (imm18 == kEndOfChain) { | |
| 650 // EndOfChain sentinel is returned directly, not relative to pc or pos. | |
| 651 return kEndOfChain; | |
| 652 } else { | |
| 653 return pos + kBranchPCOffset + imm18; | |
| 654 } | |
| 655 } else if (IsLui(instr)) { | |
| 656 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); | 728 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); |
| 657 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); | 729 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); |
| 658 DCHECK(IsOri(instr_ori)); | 730 DCHECK(IsOri(instr_ori)); |
|
ivica.bogosavljevic
2015/10/15 11:49:08
Since isLui is not part of else if, then we should
balazs.kilvady
2015/10/30 21:11:14
That check is covered at line 724
| |
| 659 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; | 731 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; |
| 660 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); | 732 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); |
| 661 | 733 |
| 662 if (imm == kEndOfJumpChain) { | 734 if (imm == kEndOfJumpChain) { |
| 663 // EndOfChain sentinel is returned directly, not relative to pc or pos. | 735 // EndOfChain sentinel is returned directly, not relative to pc or pos. |
| 664 return kEndOfChain; | 736 return kEndOfChain; |
| 665 } else { | 737 } else { |
| 666 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); | 738 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); |
| 667 int32_t delta = instr_address - imm; | 739 int32_t delta = instr_address - imm; |
| 668 DCHECK(pos > delta); | 740 DCHECK(pos > delta); |
| 669 return pos - delta; | 741 return pos - delta; |
| 670 } | 742 } |
| 671 } else { | |
| 672 UNREACHABLE(); | |
| 673 return 0; | |
| 674 } | 743 } |
| 744 return 0; | |
| 675 } | 745 } |
| 676 | 746 |
| 677 | 747 |
| 748 static inline Instr SetBranchOffset(int32_t pos, int32_t target_pos, | |
| 749 Instr instr) { | |
| 750 int32_t bits = OffsetSizeInBits(instr); | |
| 751 int32_t imm = target_pos - (pos + Assembler::kBranchPCOffset); | |
| 752 DCHECK((imm & 3) == 0); | |
| 753 imm >>= 2; | |
| 754 | |
| 755 const int32_t mask = (1 << bits) - 1; | |
| 756 instr &= ~mask; | |
| 757 DCHECK(is_intn(imm, bits)); | |
| 758 | |
| 759 return instr | (imm & mask); | |
| 760 } | |
| 761 | |
| 762 | |
| 678 void Assembler::target_at_put(int32_t pos, int32_t target_pos, | 763 void Assembler::target_at_put(int32_t pos, int32_t target_pos, |
| 679 bool is_internal) { | 764 bool is_internal) { |
| 680 Instr instr = instr_at(pos); | 765 Instr instr = instr_at(pos); |
| 681 | 766 |
| 682 if (is_internal) { | 767 if (is_internal) { |
| 683 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; | 768 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; |
| 684 instr_at_put(pos, imm); | 769 instr_at_put(pos, imm); |
| 685 return; | 770 return; |
| 686 } | 771 } |
| 687 if ((instr & ~kImm16Mask) == 0) { | 772 if ((instr & ~kImm16Mask) == 0) { |
| 688 DCHECK(target_pos == kEndOfChain || target_pos >= 0); | 773 DCHECK(target_pos == kEndOfChain || target_pos >= 0); |
| 689 // Emitted label constant, not part of a branch. | 774 // Emitted label constant, not part of a branch. |
| 690 // Make label relative to Code* of generated Code object. | 775 // Make label relative to Code* of generated Code object. |
| 691 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); | 776 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); |
| 692 return; | 777 return; |
| 693 } | 778 } |
| 694 | 779 |
| 695 DCHECK(IsBranch(instr) || IsLui(instr)); | 780 DCHECK(IsBranch(instr) || IsLui(instr)); |
| 696 if (IsBranch(instr)) { | 781 if (IsBranch(instr)) { |
| 697 int32_t imm18 = target_pos - (pos + kBranchPCOffset); | 782 instr = SetBranchOffset(pos, target_pos, instr); |
| 698 DCHECK((imm18 & 3) == 0); | 783 instr_at_put(pos, instr); |
| 699 | 784 } else { |
| 700 instr &= ~kImm16Mask; | |
| 701 int32_t imm16 = imm18 >> 2; | |
| 702 DCHECK(is_int16(imm16)); | |
| 703 | |
| 704 instr_at_put(pos, instr | (imm16 & kImm16Mask)); | |
| 705 } else if (IsLui(instr)) { | |
| 706 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); | 785 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); |
| 707 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); | 786 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); |
| 708 DCHECK(IsOri(instr_ori)); | 787 DCHECK(IsOri(instr_ori)); |
|
ivica.bogosavljevic
2015/10/15 11:49:08
Since isLui is not part of else if, then we should
balazs.kilvady
2015/10/30 21:11:14
Check covered at line 780
| |
| 709 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; | 788 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; |
| 710 DCHECK((imm & 3) == 0); | 789 DCHECK((imm & 3) == 0); |
| 711 | 790 |
| 712 instr_lui &= ~kImm16Mask; | 791 instr_lui &= ~kImm16Mask; |
| 713 instr_ori &= ~kImm16Mask; | 792 instr_ori &= ~kImm16Mask; |
| 714 | 793 |
| 715 instr_at_put(pos + 0 * Assembler::kInstrSize, | 794 instr_at_put(pos + 0 * Assembler::kInstrSize, |
| 716 instr_lui | ((imm & kHiMask) >> kLuiShift)); | 795 instr_lui | ((imm & kHiMask) >> kLuiShift)); |
| 717 instr_at_put(pos + 1 * Assembler::kInstrSize, | 796 instr_at_put(pos + 1 * Assembler::kInstrSize, |
| 718 instr_ori | (imm & kImm16Mask)); | 797 instr_ori | (imm & kImm16Mask)); |
| 719 } else { | |
| 720 UNREACHABLE(); | |
| 721 } | 798 } |
| 722 } | 799 } |
| 723 | 800 |
| 724 | 801 |
| 725 void Assembler::print(Label* L) { | 802 void Assembler::print(Label* L) { |
| 726 if (L->is_unused()) { | 803 if (L->is_unused()) { |
| 727 PrintF("unused label\n"); | 804 PrintF("unused label\n"); |
| 728 } else if (L->is_bound()) { | 805 } else if (L->is_bound()) { |
| 729 PrintF("bound label to %d\n", L->pos()); | 806 PrintF("bound label to %d\n", L->pos()); |
| 730 } else if (L->is_linked()) { | 807 } else if (L->is_linked()) { |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 759 while (L->is_linked()) { | 836 while (L->is_linked()) { |
| 760 int32_t fixup_pos = L->pos(); | 837 int32_t fixup_pos = L->pos(); |
| 761 int32_t dist = pos - fixup_pos; | 838 int32_t dist = pos - fixup_pos; |
| 762 is_internal = internal_reference_positions_.find(fixup_pos) != | 839 is_internal = internal_reference_positions_.find(fixup_pos) != |
| 763 internal_reference_positions_.end(); | 840 internal_reference_positions_.end(); |
| 764 next(L, is_internal); // Call next before overwriting link with target at | 841 next(L, is_internal); // Call next before overwriting link with target at |
| 765 // fixup_pos. | 842 // fixup_pos. |
| 766 Instr instr = instr_at(fixup_pos); | 843 Instr instr = instr_at(fixup_pos); |
| 767 if (is_internal) { | 844 if (is_internal) { |
| 768 target_at_put(fixup_pos, pos, is_internal); | 845 target_at_put(fixup_pos, pos, is_internal); |
| 769 } else if (!is_internal && IsBranch(instr)) { | 846 } else { |
| 770 if (dist > kMaxBranchOffset) { | 847 if (IsBranch(instr)) { |
| 771 if (trampoline_pos == kInvalidSlotPos) { | 848 if (dist > kMaxBranchOffset) { |
| 772 trampoline_pos = get_trampoline_entry(fixup_pos); | 849 if (trampoline_pos == kInvalidSlotPos) { |
| 773 CHECK(trampoline_pos != kInvalidSlotPos); | 850 trampoline_pos = get_trampoline_entry(fixup_pos); |
| 851 CHECK(trampoline_pos != kInvalidSlotPos); | |
| 852 } | |
| 853 CHECK((trampoline_pos - fixup_pos) <= kMaxBranchOffset); | |
| 854 target_at_put(fixup_pos, trampoline_pos, false); | |
| 855 fixup_pos = trampoline_pos; | |
| 856 dist = pos - fixup_pos; | |
| 774 } | 857 } |
| 775 CHECK((trampoline_pos - fixup_pos) <= kMaxBranchOffset); | 858 target_at_put(fixup_pos, pos, false); |
| 776 target_at_put(fixup_pos, trampoline_pos, false); | 859 } else { |
| 777 fixup_pos = trampoline_pos; | 860 target_at_put(fixup_pos, pos, false); |
| 778 dist = pos - fixup_pos; | |
| 779 } | 861 } |
| 780 target_at_put(fixup_pos, pos, false); | |
| 781 } else { | |
| 782 target_at_put(fixup_pos, pos, false); | |
| 783 } | 862 } |
| 784 } | 863 } |
| 785 L->bind_to(pos); | 864 L->bind_to(pos); |
| 786 | 865 |
| 787 // Keep track of the last bound label so we don't eliminate any instructions | 866 // Keep track of the last bound label so we don't eliminate any instructions |
| 788 // before a bound label. | 867 // before a bound label. |
| 789 if (pos > last_bound_pos_) | 868 if (pos > last_bound_pos_) |
| 790 last_bound_pos_ = pos; | 869 last_bound_pos_ = pos; |
| 791 } | 870 } |
| 792 | 871 |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 992 } | 1071 } |
| 993 } | 1072 } |
| 994 | 1073 |
| 995 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; | 1074 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; |
| 996 DCHECK((imm & 3) == 0); | 1075 DCHECK((imm & 3) == 0); |
| 997 | 1076 |
| 998 return imm; | 1077 return imm; |
| 999 } | 1078 } |
| 1000 | 1079 |
| 1001 | 1080 |
| 1002 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { | 1081 int32_t Assembler::branch_offset_helper(Label* L, bool jump_elimination_allowed, |
|
ivica.bogosavljevic
2015/10/15 11:49:08
Bravo for removing all these functions!
| |
| 1082 int bits) { | |
| 1003 int32_t target_pos; | 1083 int32_t target_pos; |
| 1084 int32_t pad = IsPrevInstrCompactBranch() ? kInstrSize : 0; | |
| 1004 | 1085 |
| 1005 if (L->is_bound()) { | 1086 if (L->is_bound()) { |
| 1006 target_pos = L->pos(); | 1087 target_pos = L->pos(); |
| 1007 } else { | 1088 } else { |
| 1008 if (L->is_linked()) { | 1089 if (L->is_linked()) { |
| 1009 target_pos = L->pos(); | 1090 target_pos = L->pos(); |
| 1010 L->link_to(pc_offset()); | 1091 L->link_to(pc_offset() + pad); |
| 1011 } else { | 1092 } else { |
| 1012 L->link_to(pc_offset()); | 1093 L->link_to(pc_offset() + pad); |
| 1013 if (!trampoline_emitted_) { | 1094 if (!trampoline_emitted_) { |
| 1014 unbound_labels_count_++; | 1095 unbound_labels_count_++; |
| 1015 next_buffer_check_ -= kTrampolineSlotsSize; | 1096 next_buffer_check_ -= kTrampolineSlotsSize; |
| 1016 } | |
| 1017 return kEndOfChain; | |
| 1018 } | |
| 1019 } | |
| 1020 | |
| 1021 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset); | |
| 1022 DCHECK((offset & 3) == 0); | |
| 1023 DCHECK(is_int16(offset >> 2)); | |
| 1024 | |
| 1025 return offset; | |
| 1026 } | |
| 1027 | |
| 1028 | |
| 1029 int32_t Assembler::branch_offset_compact(Label* L, | |
| 1030 bool jump_elimination_allowed) { | |
| 1031 int32_t target_pos; | |
| 1032 if (L->is_bound()) { | |
| 1033 target_pos = L->pos(); | |
| 1034 } else { | |
| 1035 if (L->is_linked()) { | |
| 1036 target_pos = L->pos(); | |
| 1037 L->link_to(pc_offset()); | |
| 1038 } else { | |
| 1039 L->link_to(pc_offset()); | |
| 1040 if (!trampoline_emitted_) { | |
| 1041 unbound_labels_count_++; | |
| 1042 next_buffer_check_ -= kTrampolineSlotsSize; | |
| 1043 } | |
| 1044 return kEndOfChain; | |
| 1045 } | |
| 1046 } | |
| 1047 | |
| 1048 int32_t offset = target_pos - pc_offset(); | |
| 1049 DCHECK((offset & 3) == 0); | |
| 1050 DCHECK(is_int16(offset >> 2)); | |
| 1051 | |
| 1052 return offset; | |
| 1053 } | |
| 1054 | |
| 1055 | |
| 1056 int32_t Assembler::branch_offset21(Label* L, bool jump_elimination_allowed) { | |
| 1057 int32_t target_pos; | |
| 1058 | |
| 1059 if (L->is_bound()) { | |
| 1060 target_pos = L->pos(); | |
| 1061 } else { | |
| 1062 if (L->is_linked()) { | |
| 1063 target_pos = L->pos(); | |
| 1064 L->link_to(pc_offset()); | |
| 1065 } else { | |
| 1066 L->link_to(pc_offset()); | |
| 1067 if (!trampoline_emitted_) { | |
| 1068 unbound_labels_count_++; | |
| 1069 next_buffer_check_ -= kTrampolineSlotsSize; | |
| 1070 } | 1097 } |
| 1071 return kEndOfChain; | 1098 return kEndOfChain; |
| 1072 } | 1099 } |
| 1073 } | 1100 } |
| 1074 | 1101 |
| 1075 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset); | 1102 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset + pad); |
| 1103 DCHECK(is_intn(offset, bits + 2)); | |
| 1076 DCHECK((offset & 3) == 0); | 1104 DCHECK((offset & 3) == 0); |
| 1077 DCHECK(((offset >> 2) & 0xFFE00000) == 0); // Offset is 21bit width. | |
| 1078 | 1105 |
| 1079 return offset; | 1106 return offset; |
| 1080 } | 1107 } |
| 1081 | |
| 1082 | |
| 1083 int32_t Assembler::branch_offset21_compact(Label* L, | |
| 1084 bool jump_elimination_allowed) { | |
| 1085 int32_t target_pos; | |
| 1086 | |
| 1087 if (L->is_bound()) { | |
| 1088 target_pos = L->pos(); | |
| 1089 } else { | |
| 1090 if (L->is_linked()) { | |
| 1091 target_pos = L->pos(); | |
| 1092 L->link_to(pc_offset()); | |
| 1093 } else { | |
| 1094 L->link_to(pc_offset()); | |
| 1095 if (!trampoline_emitted_) { | |
| 1096 unbound_labels_count_++; | |
| 1097 next_buffer_check_ -= kTrampolineSlotsSize; | |
| 1098 } | |
| 1099 return kEndOfChain; | |
| 1100 } | |
| 1101 } | |
| 1102 | |
| 1103 int32_t offset = target_pos - pc_offset(); | |
| 1104 DCHECK((offset & 3) == 0); | |
| 1105 DCHECK(((offset >> 2) & 0xFFe00000) == 0); // Offset is 21bit width. | |
| 1106 | |
| 1107 return offset; | |
| 1108 } | |
| 1109 | 1108 |
| 1110 | 1109 |
| 1111 void Assembler::label_at_put(Label* L, int at_offset) { | 1110 void Assembler::label_at_put(Label* L, int at_offset) { |
| 1112 int target_pos; | 1111 int target_pos; |
| 1113 if (L->is_bound()) { | 1112 if (L->is_bound()) { |
| 1114 target_pos = L->pos(); | 1113 target_pos = L->pos(); |
| 1115 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); | 1114 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); |
| 1116 } else { | 1115 } else { |
| 1117 if (L->is_linked()) { | 1116 if (L->is_linked()) { |
| 1118 target_pos = L->pos(); // L's link. | 1117 target_pos = L->pos(); // L's link. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1135 | 1134 |
| 1136 | 1135 |
| 1137 //------- Branch and jump instructions -------- | 1136 //------- Branch and jump instructions -------- |
| 1138 | 1137 |
| 1139 void Assembler::b(int16_t offset) { | 1138 void Assembler::b(int16_t offset) { |
| 1140 beq(zero_reg, zero_reg, offset); | 1139 beq(zero_reg, zero_reg, offset); |
| 1141 } | 1140 } |
| 1142 | 1141 |
| 1143 | 1142 |
| 1144 void Assembler::bal(int16_t offset) { | 1143 void Assembler::bal(int16_t offset) { |
| 1145 positions_recorder()->WriteRecordedPositions(); | |
| 1146 bgezal(zero_reg, offset); | 1144 bgezal(zero_reg, offset); |
| 1147 } | 1145 } |
| 1148 | 1146 |
| 1149 | 1147 |
| 1150 void Assembler::bc(int32_t offset) { | 1148 void Assembler::bc(int32_t offset) { |
| 1151 DCHECK(IsMipsArchVariant(kMips32r6)); | 1149 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1152 GenInstrImmediate(BC, offset); | 1150 GenInstrImmediate(BC, offset); |
| 1151 EmittedCompactBranchInstruction(); | |
| 1153 } | 1152 } |
| 1154 | 1153 |
| 1155 | 1154 |
| 1156 void Assembler::balc(int32_t offset) { | 1155 void Assembler::balc(int32_t offset) { |
| 1157 DCHECK(IsMipsArchVariant(kMips32r6)); | 1156 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1158 positions_recorder()->WriteRecordedPositions(); | |
| 1159 GenInstrImmediate(BALC, offset); | 1157 GenInstrImmediate(BALC, offset); |
| 1158 EmittedCompactBranchInstruction(); | |
| 1160 } | 1159 } |
| 1161 | 1160 |
| 1162 | 1161 |
| 1163 void Assembler::beq(Register rs, Register rt, int16_t offset) { | 1162 void Assembler::beq(Register rs, Register rt, int16_t offset) { |
| 1164 BlockTrampolinePoolScope block_trampoline_pool(this); | 1163 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 1165 GenInstrImmediate(BEQ, rs, rt, offset); | 1164 GenInstrImmediate(BEQ, rs, rt, offset); |
| 1166 BlockTrampolinePoolFor(1); // For associated delay slot. | 1165 BlockTrampolinePoolFor(1); // For associated delay slot. |
| 1167 } | 1166 } |
| 1168 | 1167 |
| 1169 | 1168 |
| 1170 void Assembler::bgez(Register rs, int16_t offset) { | 1169 void Assembler::bgez(Register rs, int16_t offset) { |
| 1171 BlockTrampolinePoolScope block_trampoline_pool(this); | 1170 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 1172 GenInstrImmediate(REGIMM, rs, BGEZ, offset); | 1171 GenInstrImmediate(REGIMM, rs, BGEZ, offset); |
| 1173 BlockTrampolinePoolFor(1); // For associated delay slot. | 1172 BlockTrampolinePoolFor(1); // For associated delay slot. |
| 1174 } | 1173 } |
| 1175 | 1174 |
| 1176 | 1175 |
| 1177 void Assembler::bgezc(Register rt, int16_t offset) { | 1176 void Assembler::bgezc(Register rt, int16_t offset) { |
| 1178 DCHECK(IsMipsArchVariant(kMips32r6)); | 1177 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1179 DCHECK(!(rt.is(zero_reg))); | 1178 DCHECK(!(rt.is(zero_reg))); |
| 1180 GenInstrImmediate(BLEZL, rt, rt, offset); | 1179 GenInstrImmediate(BLEZL, rt, rt, offset); |
| 1180 EmittedCompactBranchInstruction(); | |
| 1181 } | 1181 } |
| 1182 | 1182 |
| 1183 | 1183 |
| 1184 void Assembler::bgeuc(Register rs, Register rt, int16_t offset) { | 1184 void Assembler::bgeuc(Register rs, Register rt, int16_t offset) { |
| 1185 DCHECK(IsMipsArchVariant(kMips32r6)); | 1185 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1186 DCHECK(!(rs.is(zero_reg))); | 1186 DCHECK(!(rs.is(zero_reg))); |
| 1187 DCHECK(!(rt.is(zero_reg))); | 1187 DCHECK(!(rt.is(zero_reg))); |
| 1188 DCHECK(rs.code() != rt.code()); | 1188 DCHECK(rs.code() != rt.code()); |
| 1189 GenInstrImmediate(BLEZ, rs, rt, offset); | 1189 GenInstrImmediate(BLEZ, rs, rt, offset); |
| 1190 EmittedCompactBranchInstruction(); | |
| 1190 } | 1191 } |
| 1191 | 1192 |
| 1192 | 1193 |
| 1193 void Assembler::bgec(Register rs, Register rt, int16_t offset) { | 1194 void Assembler::bgec(Register rs, Register rt, int16_t offset) { |
| 1194 DCHECK(IsMipsArchVariant(kMips32r6)); | 1195 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1195 DCHECK(!(rs.is(zero_reg))); | 1196 DCHECK(!(rs.is(zero_reg))); |
| 1196 DCHECK(!(rt.is(zero_reg))); | 1197 DCHECK(!(rt.is(zero_reg))); |
| 1197 DCHECK(rs.code() != rt.code()); | 1198 DCHECK(rs.code() != rt.code()); |
| 1198 GenInstrImmediate(BLEZL, rs, rt, offset); | 1199 GenInstrImmediate(BLEZL, rs, rt, offset); |
| 1200 EmittedCompactBranchInstruction(); | |
| 1199 } | 1201 } |
| 1200 | 1202 |
| 1201 | 1203 |
| 1202 void Assembler::bgezal(Register rs, int16_t offset) { | 1204 void Assembler::bgezal(Register rs, int16_t offset) { |
| 1203 DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg)); | 1205 DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg)); |
| 1204 BlockTrampolinePoolScope block_trampoline_pool(this); | 1206 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 1205 positions_recorder()->WriteRecordedPositions(); | |
| 1206 GenInstrImmediate(REGIMM, rs, BGEZAL, offset); | 1207 GenInstrImmediate(REGIMM, rs, BGEZAL, offset); |
| 1207 BlockTrampolinePoolFor(1); // For associated delay slot. | 1208 BlockTrampolinePoolFor(1); // For associated delay slot. |
| 1208 } | 1209 } |
| 1209 | 1210 |
| 1210 | 1211 |
| 1211 void Assembler::bgtz(Register rs, int16_t offset) { | 1212 void Assembler::bgtz(Register rs, int16_t offset) { |
| 1212 BlockTrampolinePoolScope block_trampoline_pool(this); | 1213 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 1213 GenInstrImmediate(BGTZ, rs, zero_reg, offset); | 1214 GenInstrImmediate(BGTZ, rs, zero_reg, offset); |
| 1214 BlockTrampolinePoolFor(1); // For associated delay slot. | 1215 BlockTrampolinePoolFor(1); // For associated delay slot. |
| 1215 } | 1216 } |
| 1216 | 1217 |
| 1217 | 1218 |
| 1218 void Assembler::bgtzc(Register rt, int16_t offset) { | 1219 void Assembler::bgtzc(Register rt, int16_t offset) { |
| 1219 DCHECK(IsMipsArchVariant(kMips32r6)); | 1220 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1220 DCHECK(!(rt.is(zero_reg))); | 1221 DCHECK(!(rt.is(zero_reg))); |
| 1221 GenInstrImmediate(BGTZL, zero_reg, rt, offset); | 1222 GenInstrImmediate(BGTZL, zero_reg, rt, offset); |
| 1223 EmittedCompactBranchInstruction(); | |
| 1222 } | 1224 } |
| 1223 | 1225 |
| 1224 | 1226 |
| 1225 void Assembler::blez(Register rs, int16_t offset) { | 1227 void Assembler::blez(Register rs, int16_t offset) { |
| 1226 BlockTrampolinePoolScope block_trampoline_pool(this); | 1228 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 1227 GenInstrImmediate(BLEZ, rs, zero_reg, offset); | 1229 GenInstrImmediate(BLEZ, rs, zero_reg, offset); |
| 1228 BlockTrampolinePoolFor(1); // For associated delay slot. | 1230 BlockTrampolinePoolFor(1); // For associated delay slot. |
| 1229 } | 1231 } |
| 1230 | 1232 |
| 1231 | 1233 |
| 1232 void Assembler::blezc(Register rt, int16_t offset) { | 1234 void Assembler::blezc(Register rt, int16_t offset) { |
| 1233 DCHECK(IsMipsArchVariant(kMips32r6)); | 1235 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1234 DCHECK(!(rt.is(zero_reg))); | 1236 DCHECK(!(rt.is(zero_reg))); |
| 1235 GenInstrImmediate(BLEZL, zero_reg, rt, offset); | 1237 GenInstrImmediate(BLEZL, zero_reg, rt, offset); |
| 1238 EmittedCompactBranchInstruction(); | |
| 1236 } | 1239 } |
| 1237 | 1240 |
| 1238 | 1241 |
| 1239 void Assembler::bltzc(Register rt, int16_t offset) { | 1242 void Assembler::bltzc(Register rt, int16_t offset) { |
| 1240 DCHECK(IsMipsArchVariant(kMips32r6)); | 1243 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1241 DCHECK(!(rt.is(zero_reg))); | 1244 DCHECK(!rt.is(zero_reg)); |
| 1242 GenInstrImmediate(BGTZL, rt, rt, offset); | 1245 GenInstrImmediate(BGTZL, rt, rt, offset); |
| 1246 EmittedCompactBranchInstruction(); | |
| 1243 } | 1247 } |
| 1244 | 1248 |
| 1245 | 1249 |
| 1246 void Assembler::bltuc(Register rs, Register rt, int16_t offset) { | 1250 void Assembler::bltuc(Register rs, Register rt, int16_t offset) { |
| 1247 DCHECK(IsMipsArchVariant(kMips32r6)); | 1251 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1248 DCHECK(!(rs.is(zero_reg))); | 1252 DCHECK(!(rs.is(zero_reg))); |
| 1249 DCHECK(!(rt.is(zero_reg))); | 1253 DCHECK(!(rt.is(zero_reg))); |
| 1250 DCHECK(rs.code() != rt.code()); | 1254 DCHECK(rs.code() != rt.code()); |
| 1251 GenInstrImmediate(BGTZ, rs, rt, offset); | 1255 GenInstrImmediate(BGTZ, rs, rt, offset); |
| 1256 EmittedCompactBranchInstruction(); | |
| 1252 } | 1257 } |
| 1253 | 1258 |
| 1254 | 1259 |
| 1255 void Assembler::bltc(Register rs, Register rt, int16_t offset) { | 1260 void Assembler::bltc(Register rs, Register rt, int16_t offset) { |
| 1256 DCHECK(IsMipsArchVariant(kMips32r6)); | 1261 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1257 DCHECK(!(rs.is(zero_reg))); | 1262 DCHECK(!rs.is(zero_reg)); |
| 1258 DCHECK(!(rt.is(zero_reg))); | 1263 DCHECK(!rt.is(zero_reg)); |
| 1259 DCHECK(rs.code() != rt.code()); | 1264 DCHECK(rs.code() != rt.code()); |
| 1260 GenInstrImmediate(BGTZL, rs, rt, offset); | 1265 GenInstrImmediate(BGTZL, rs, rt, offset); |
| 1266 EmittedCompactBranchInstruction(); | |
| 1261 } | 1267 } |
| 1262 | 1268 |
| 1263 | 1269 |
| 1264 void Assembler::bltz(Register rs, int16_t offset) { | 1270 void Assembler::bltz(Register rs, int16_t offset) { |
| 1265 BlockTrampolinePoolScope block_trampoline_pool(this); | 1271 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 1266 GenInstrImmediate(REGIMM, rs, BLTZ, offset); | 1272 GenInstrImmediate(REGIMM, rs, BLTZ, offset); |
| 1267 BlockTrampolinePoolFor(1); // For associated delay slot. | 1273 BlockTrampolinePoolFor(1); // For associated delay slot. |
| 1268 } | 1274 } |
| 1269 | 1275 |
| 1270 | 1276 |
| 1271 void Assembler::bltzal(Register rs, int16_t offset) { | 1277 void Assembler::bltzal(Register rs, int16_t offset) { |
| 1272 DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg)); | 1278 DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg)); |
| 1273 BlockTrampolinePoolScope block_trampoline_pool(this); | 1279 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 1274 positions_recorder()->WriteRecordedPositions(); | |
| 1275 GenInstrImmediate(REGIMM, rs, BLTZAL, offset); | 1280 GenInstrImmediate(REGIMM, rs, BLTZAL, offset); |
| 1276 BlockTrampolinePoolFor(1); // For associated delay slot. | 1281 BlockTrampolinePoolFor(1); // For associated delay slot. |
| 1277 } | 1282 } |
| 1278 | 1283 |
| 1279 | 1284 |
| 1280 void Assembler::bne(Register rs, Register rt, int16_t offset) { | 1285 void Assembler::bne(Register rs, Register rt, int16_t offset) { |
| 1281 BlockTrampolinePoolScope block_trampoline_pool(this); | 1286 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 1282 GenInstrImmediate(BNE, rs, rt, offset); | 1287 GenInstrImmediate(BNE, rs, rt, offset); |
| 1283 BlockTrampolinePoolFor(1); // For associated delay slot. | 1288 BlockTrampolinePoolFor(1); // For associated delay slot. |
| 1284 } | 1289 } |
| 1285 | 1290 |
| 1286 | 1291 |
| 1287 void Assembler::bovc(Register rs, Register rt, int16_t offset) { | 1292 void Assembler::bovc(Register rs, Register rt, int16_t offset) { |
| 1288 DCHECK(IsMipsArchVariant(kMips32r6)); | 1293 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1289 DCHECK(!(rs.is(zero_reg))); | 1294 DCHECK(!(rs.is(zero_reg))); |
| 1290 DCHECK(rs.code() >= rt.code()); | 1295 DCHECK(rs.code() >= rt.code()); |
| 1291 GenInstrImmediate(ADDI, rs, rt, offset); | 1296 GenInstrImmediate(ADDI, rs, rt, offset); |
| 1297 EmittedCompactBranchInstruction(); | |
| 1292 } | 1298 } |
| 1293 | 1299 |
| 1294 | 1300 |
| 1295 void Assembler::bnvc(Register rs, Register rt, int16_t offset) { | 1301 void Assembler::bnvc(Register rs, Register rt, int16_t offset) { |
| 1296 DCHECK(IsMipsArchVariant(kMips32r6)); | 1302 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1297 DCHECK(!(rs.is(zero_reg))); | 1303 DCHECK(!(rs.is(zero_reg))); |
| 1298 DCHECK(rs.code() >= rt.code()); | 1304 DCHECK(rs.code() >= rt.code()); |
| 1299 GenInstrImmediate(DADDI, rs, rt, offset); | 1305 GenInstrImmediate(DADDI, rs, rt, offset); |
| 1306 EmittedCompactBranchInstruction(); | |
| 1300 } | 1307 } |
| 1301 | 1308 |
| 1302 | 1309 |
| 1303 void Assembler::blezalc(Register rt, int16_t offset) { | 1310 void Assembler::blezalc(Register rt, int16_t offset) { |
| 1304 DCHECK(IsMipsArchVariant(kMips32r6)); | 1311 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1305 DCHECK(!(rt.is(zero_reg))); | 1312 DCHECK(!(rt.is(zero_reg))); |
| 1306 GenInstrImmediate(BLEZ, zero_reg, rt, offset); | 1313 GenInstrImmediate(BLEZ, zero_reg, rt, offset); |
| 1314 EmittedCompactBranchInstruction(); | |
| 1307 } | 1315 } |
| 1308 | 1316 |
| 1309 | 1317 |
| 1310 void Assembler::bgezalc(Register rt, int16_t offset) { | 1318 void Assembler::bgezalc(Register rt, int16_t offset) { |
| 1311 DCHECK(IsMipsArchVariant(kMips32r6)); | 1319 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1312 DCHECK(!(rt.is(zero_reg))); | 1320 DCHECK(!(rt.is(zero_reg))); |
| 1313 GenInstrImmediate(BLEZ, rt, rt, offset); | 1321 GenInstrImmediate(BLEZ, rt, rt, offset); |
| 1322 EmittedCompactBranchInstruction(); | |
| 1314 } | 1323 } |
| 1315 | 1324 |
| 1316 | 1325 |
| 1317 void Assembler::bgezall(Register rs, int16_t offset) { | 1326 void Assembler::bgezall(Register rs, int16_t offset) { |
| 1318 DCHECK(IsMipsArchVariant(kMips32r6)); | 1327 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1319 DCHECK(!(rs.is(zero_reg))); | 1328 DCHECK(!(rs.is(zero_reg))); |
| 1320 GenInstrImmediate(REGIMM, rs, BGEZALL, offset); | 1329 GenInstrImmediate(REGIMM, rs, BGEZALL, offset); |
| 1321 } | 1330 } |
| 1322 | 1331 |
| 1323 | 1332 |
| 1324 void Assembler::bltzalc(Register rt, int16_t offset) { | 1333 void Assembler::bltzalc(Register rt, int16_t offset) { |
| 1325 DCHECK(IsMipsArchVariant(kMips32r6)); | 1334 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1326 DCHECK(!(rt.is(zero_reg))); | 1335 DCHECK(!(rt.is(zero_reg))); |
| 1327 GenInstrImmediate(BGTZ, rt, rt, offset); | 1336 GenInstrImmediate(BGTZ, rt, rt, offset); |
| 1337 EmittedCompactBranchInstruction(); | |
| 1328 } | 1338 } |
| 1329 | 1339 |
| 1330 | 1340 |
| 1331 void Assembler::bgtzalc(Register rt, int16_t offset) { | 1341 void Assembler::bgtzalc(Register rt, int16_t offset) { |
| 1332 DCHECK(IsMipsArchVariant(kMips32r6)); | 1342 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1333 DCHECK(!(rt.is(zero_reg))); | 1343 DCHECK(!(rt.is(zero_reg))); |
| 1334 GenInstrImmediate(BGTZ, zero_reg, rt, offset); | 1344 GenInstrImmediate(BGTZ, zero_reg, rt, offset); |
| 1345 EmittedCompactBranchInstruction(); | |
| 1335 } | 1346 } |
| 1336 | 1347 |
| 1337 | 1348 |
| 1338 void Assembler::beqzalc(Register rt, int16_t offset) { | 1349 void Assembler::beqzalc(Register rt, int16_t offset) { |
| 1339 DCHECK(IsMipsArchVariant(kMips32r6)); | 1350 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1340 DCHECK(!(rt.is(zero_reg))); | 1351 DCHECK(!(rt.is(zero_reg))); |
| 1341 GenInstrImmediate(ADDI, zero_reg, rt, offset); | 1352 GenInstrImmediate(ADDI, zero_reg, rt, offset); |
| 1353 EmittedCompactBranchInstruction(); | |
| 1342 } | 1354 } |
| 1343 | 1355 |
| 1344 | 1356 |
| 1345 void Assembler::bnezalc(Register rt, int16_t offset) { | 1357 void Assembler::bnezalc(Register rt, int16_t offset) { |
| 1346 DCHECK(IsMipsArchVariant(kMips32r6)); | 1358 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1347 DCHECK(!(rt.is(zero_reg))); | 1359 DCHECK(!(rt.is(zero_reg))); |
| 1348 GenInstrImmediate(DADDI, zero_reg, rt, offset); | 1360 GenInstrImmediate(DADDI, zero_reg, rt, offset); |
| 1361 EmittedCompactBranchInstruction(); | |
| 1349 } | 1362 } |
| 1350 | 1363 |
| 1351 | 1364 |
| 1352 void Assembler::beqc(Register rs, Register rt, int16_t offset) { | 1365 void Assembler::beqc(Register rs, Register rt, int16_t offset) { |
| 1353 DCHECK(IsMipsArchVariant(kMips32r6)); | 1366 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1354 DCHECK(rs.code() < rt.code()); | 1367 DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0); |
| 1355 GenInstrImmediate(ADDI, rs, rt, offset); | 1368 if (rs.code() < rt.code()) { |
| 1369 GenInstrImmediate(ADDI, rs, rt, offset); | |
| 1370 } else { | |
| 1371 GenInstrImmediate(ADDI, rt, rs, offset); | |
| 1372 } | |
| 1373 EmittedCompactBranchInstruction(); | |
| 1356 } | 1374 } |
| 1357 | 1375 |
| 1358 | 1376 |
| 1359 void Assembler::beqzc(Register rs, int32_t offset) { | 1377 void Assembler::beqzc(Register rs, int32_t offset) { |
| 1360 DCHECK(IsMipsArchVariant(kMips32r6)); | 1378 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1361 DCHECK(!(rs.is(zero_reg))); | 1379 DCHECK(!(rs.is(zero_reg))); |
| 1362 Instr instr = POP66 | (rs.code() << kRsShift) | (offset & kImm21Mask); | 1380 Instr instr = POP66 | (rs.code() << kRsShift) | (offset & kImm21Mask); |
| 1363 emit(instr); | 1381 emit(instr); |
| 1382 EmittedCompactBranchInstruction(); | |
| 1364 } | 1383 } |
| 1365 | 1384 |
| 1366 | 1385 |
| 1367 void Assembler::bnec(Register rs, Register rt, int16_t offset) { | 1386 void Assembler::bnec(Register rs, Register rt, int16_t offset) { |
| 1368 DCHECK(IsMipsArchVariant(kMips32r6)); | 1387 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1369 DCHECK(rs.code() < rt.code()); | 1388 DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0); |
| 1370 GenInstrImmediate(DADDI, rs, rt, offset); | 1389 if (rs.code() < rt.code()) { |
| 1390 GenInstrImmediate(DADDI, rs, rt, offset); | |
| 1391 } else { | |
| 1392 GenInstrImmediate(DADDI, rt, rs, offset); | |
| 1393 } | |
| 1394 EmittedCompactBranchInstruction(); | |
| 1371 } | 1395 } |
| 1372 | 1396 |
| 1373 | 1397 |
| 1374 void Assembler::bnezc(Register rs, int32_t offset) { | 1398 void Assembler::bnezc(Register rs, int32_t offset) { |
| 1375 DCHECK(IsMipsArchVariant(kMips32r6)); | 1399 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1376 DCHECK(!(rs.is(zero_reg))); | 1400 DCHECK(!(rs.is(zero_reg))); |
| 1377 Instr instr = POP76 | (rs.code() << kRsShift) | offset; | 1401 Instr instr = POP76 | (rs.code() << kRsShift) | (offset & kImm21Mask); |
| 1378 emit(instr); | 1402 emit(instr); |
| 1403 EmittedCompactBranchInstruction(); | |
| 1379 } | 1404 } |
| 1380 | 1405 |
| 1381 | 1406 |
| 1382 void Assembler::j(int32_t target) { | 1407 void Assembler::j(int32_t target) { |
| 1383 #if DEBUG | 1408 #if DEBUG |
| 1384 // Get pc of delay slot. | 1409 // Get pc of delay slot. |
| 1385 uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize); | 1410 uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize); |
| 1386 bool in_range = ((ipc ^ static_cast<uint32_t>(target)) >> | 1411 bool in_range = ((ipc ^ static_cast<uint32_t>(target)) >> |
| 1387 (kImm26Bits + kImmFieldShift)) == 0; | 1412 (kImm26Bits + kImmFieldShift)) == 0; |
| 1388 DCHECK(in_range && ((target & 3) == 0)); | 1413 DCHECK(in_range && ((target & 3) == 0)); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1425 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR); | 1450 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR); |
| 1426 BlockTrampolinePoolFor(1); // For associated delay slot. | 1451 BlockTrampolinePoolFor(1); // For associated delay slot. |
| 1427 } | 1452 } |
| 1428 | 1453 |
| 1429 | 1454 |
| 1430 void Assembler::jic(Register rt, int16_t offset) { | 1455 void Assembler::jic(Register rt, int16_t offset) { |
| 1431 DCHECK(IsMipsArchVariant(kMips32r6)); | 1456 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1432 Instr instr = POP66 | (JIC << kRsShift) | (rt.code() << kRtShift) | | 1457 Instr instr = POP66 | (JIC << kRsShift) | (rt.code() << kRtShift) | |
| 1433 (offset & kImm16Mask); | 1458 (offset & kImm16Mask); |
| 1434 emit(instr); | 1459 emit(instr); |
| 1460 EmittedCompactBranchInstruction(); | |
| 1435 } | 1461 } |
| 1436 | 1462 |
| 1437 | 1463 |
| 1438 void Assembler::jialc(Register rt, int16_t offset) { | 1464 void Assembler::jialc(Register rt, int16_t offset) { |
| 1439 DCHECK(IsMipsArchVariant(kMips32r6)); | 1465 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 1440 positions_recorder()->WriteRecordedPositions(); | |
| 1441 GenInstrImmediate(POP76, zero_reg, rt, offset); | 1466 GenInstrImmediate(POP76, zero_reg, rt, offset); |
| 1467 EmittedCompactBranchInstruction(); | |
| 1442 } | 1468 } |
| 1443 | 1469 |
| 1444 | 1470 |
| 1445 // -------Data-processing-instructions--------- | 1471 // -------Data-processing-instructions--------- |
| 1446 | 1472 |
| 1447 // Arithmetic. | 1473 // Arithmetic. |
| 1448 | 1474 |
| 1449 void Assembler::addu(Register rd, Register rs, Register rt) { | 1475 void Assembler::addu(Register rd, Register rs, Register rt) { |
| 1450 GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU); | 1476 GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU); |
| 1451 } | 1477 } |
| (...skipping 1212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2664 } | 2690 } |
| 2665 | 2691 |
| 2666 | 2692 |
| 2667 void Assembler::bc1t(int16_t offset, uint16_t cc) { | 2693 void Assembler::bc1t(int16_t offset, uint16_t cc) { |
| 2668 DCHECK(is_uint3(cc)); | 2694 DCHECK(is_uint3(cc)); |
| 2669 Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask); | 2695 Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask); |
| 2670 emit(instr); | 2696 emit(instr); |
| 2671 } | 2697 } |
| 2672 | 2698 |
| 2673 | 2699 |
| 2674 // Debugging. | |
| 2675 int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc, | 2700 int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc, |
| 2676 intptr_t pc_delta) { | 2701 intptr_t pc_delta) { |
| 2677 Instr instr = instr_at(pc); | 2702 Instr instr = instr_at(pc); |
| 2678 | 2703 |
| 2679 if (RelocInfo::IsInternalReference(rmode)) { | 2704 if (RelocInfo::IsInternalReference(rmode)) { |
| 2680 int32_t* p = reinterpret_cast<int32_t*>(pc); | 2705 int32_t* p = reinterpret_cast<int32_t*>(pc); |
| 2681 if (*p == 0) { | 2706 if (*p == 0) { |
| 2682 return 0; // Number of instructions patched. | 2707 return 0; // Number of instructions patched. |
| 2683 } | 2708 } |
| 2684 *p += pc_delta; | 2709 *p += pc_delta; |
| (...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3074 if (patched) { | 3099 if (patched) { |
| 3075 CpuFeatures::FlushICache(pc + 2, sizeof(Address)); | 3100 CpuFeatures::FlushICache(pc + 2, sizeof(Address)); |
| 3076 } | 3101 } |
| 3077 } | 3102 } |
| 3078 | 3103 |
| 3079 | 3104 |
| 3080 } // namespace internal | 3105 } // namespace internal |
| 3081 } // namespace v8 | 3106 } // namespace v8 |
| 3082 | 3107 |
| 3083 #endif // V8_TARGET_ARCH_MIPS | 3108 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |