| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // | 2 // |
| 3 // Redistribution and use in source and binary forms, with or without | 3 // Redistribution and use in source and binary forms, with or without |
| 4 // modification, are permitted provided that the following conditions are | 4 // modification, are permitted provided that the following conditions are |
| 5 // met: | 5 // met: |
| 6 // | 6 // |
| 7 // * Redistributions of source code must retain the above copyright | 7 // * Redistributions of source code must retain the above copyright |
| 8 // notice, this list of conditions and the following disclaimer. | 8 // notice, this list of conditions and the following disclaimer. |
| 9 // * Redistributions in binary form must reproduce the above | 9 // * Redistributions in binary form must reproduce the above |
| 10 // copyright notice, this list of conditions and the following | 10 // copyright notice, this list of conditions and the following |
| (...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 reloc_info_writer.Finish(); | 573 reloc_info_writer.Finish(); |
| 574 // Emit constant pool if necessary. | 574 // Emit constant pool if necessary. |
| 575 CheckConstPool(true, false); | 575 CheckConstPool(true, false); |
| 576 DCHECK(constpool_.IsEmpty()); | 576 DCHECK(constpool_.IsEmpty()); |
| 577 | 577 |
| 578 // Set up code descriptor. | 578 // Set up code descriptor. |
| 579 if (desc) { | 579 if (desc) { |
| 580 desc->buffer = reinterpret_cast<byte*>(buffer_); | 580 desc->buffer = reinterpret_cast<byte*>(buffer_); |
| 581 desc->buffer_size = buffer_size_; | 581 desc->buffer_size = buffer_size_; |
| 582 desc->instr_size = pc_offset(); | 582 desc->instr_size = pc_offset(); |
| 583 desc->reloc_size = (reinterpret_cast<byte*>(buffer_) + buffer_size_) - | 583 desc->reloc_size = |
| 584 reloc_info_writer.pos(); | 584 static_cast<int>((reinterpret_cast<byte*>(buffer_) + buffer_size_) - |
| 585 reloc_info_writer.pos()); |
| 585 desc->origin = this; | 586 desc->origin = this; |
| 586 } | 587 } |
| 587 } | 588 } |
| 588 | 589 |
| 589 | 590 |
| 590 void Assembler::Align(int m) { | 591 void Assembler::Align(int m) { |
| 591 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m)); | 592 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m)); |
| 592 while ((pc_offset() & (m - 1)) != 0) { | 593 while ((pc_offset() & (m - 1)) != 0) { |
| 593 nop(); | 594 nop(); |
| 594 } | 595 } |
| 595 } | 596 } |
| 596 | 597 |
| 597 | 598 |
| 598 void Assembler::CheckLabelLinkChain(Label const * label) { | 599 void Assembler::CheckLabelLinkChain(Label const * label) { |
| 599 #ifdef DEBUG | 600 #ifdef DEBUG |
| 600 if (label->is_linked()) { | 601 if (label->is_linked()) { |
| 601 static const int kMaxLinksToCheck = 64; // Avoid O(n2) behaviour. | 602 static const int kMaxLinksToCheck = 64; // Avoid O(n2) behaviour. |
| 602 int links_checked = 0; | 603 int links_checked = 0; |
| 603 int linkoffset = label->pos(); | 604 int64_t linkoffset = label->pos(); |
| 604 bool end_of_chain = false; | 605 bool end_of_chain = false; |
| 605 while (!end_of_chain) { | 606 while (!end_of_chain) { |
| 606 if (++links_checked > kMaxLinksToCheck) break; | 607 if (++links_checked > kMaxLinksToCheck) break; |
| 607 Instruction * link = InstructionAt(linkoffset); | 608 Instruction * link = InstructionAt(linkoffset); |
| 608 int linkpcoffset = link->ImmPCOffset(); | 609 int64_t linkpcoffset = link->ImmPCOffset(); |
| 609 int prevlinkoffset = linkoffset + linkpcoffset; | 610 int64_t prevlinkoffset = linkoffset + linkpcoffset; |
| 610 | 611 |
| 611 end_of_chain = (linkoffset == prevlinkoffset); | 612 end_of_chain = (linkoffset == prevlinkoffset); |
| 612 linkoffset = linkoffset + linkpcoffset; | 613 linkoffset = linkoffset + linkpcoffset; |
| 613 } | 614 } |
| 614 } | 615 } |
| 615 #endif | 616 #endif |
| 616 } | 617 } |
| 617 | 618 |
| 618 | 619 |
| 619 void Assembler::RemoveBranchFromLabelLinkChain(Instruction* branch, | 620 void Assembler::RemoveBranchFromLabelLinkChain(Instruction* branch, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 638 DCHECK(branch == link); | 639 DCHECK(branch == link); |
| 639 next_link = branch->ImmPCOffsetTarget(); | 640 next_link = branch->ImmPCOffsetTarget(); |
| 640 | 641 |
| 641 if (branch == prev_link) { | 642 if (branch == prev_link) { |
| 642 // The branch is the first instruction in the chain. | 643 // The branch is the first instruction in the chain. |
| 643 if (branch == next_link) { | 644 if (branch == next_link) { |
| 644 // It is also the last instruction in the chain, so it is the only branch | 645 // It is also the last instruction in the chain, so it is the only branch |
| 645 // currently referring to this label. | 646 // currently referring to this label. |
| 646 label->Unuse(); | 647 label->Unuse(); |
| 647 } else { | 648 } else { |
| 648 label->link_to(reinterpret_cast<byte*>(next_link) - buffer_); | 649 label->link_to( |
| 650 static_cast<int>(reinterpret_cast<byte*>(next_link) - buffer_)); |
| 649 } | 651 } |
| 650 | 652 |
| 651 } else if (branch == next_link) { | 653 } else if (branch == next_link) { |
| 652 // The branch is the last (but not also the first) instruction in the chain. | 654 // The branch is the last (but not also the first) instruction in the chain. |
| 653 prev_link->SetImmPCOffsetTarget(prev_link); | 655 prev_link->SetImmPCOffsetTarget(prev_link); |
| 654 | 656 |
| 655 } else { | 657 } else { |
| 656 // The branch is in the middle of the chain. | 658 // The branch is in the middle of the chain. |
| 657 if (prev_link->IsTargetInImmPCOffsetRange(next_link)) { | 659 if (prev_link->IsTargetInImmPCOffsetRange(next_link)) { |
| 658 prev_link->SetImmPCOffsetTarget(next_link); | 660 prev_link->SetImmPCOffsetTarget(next_link); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 714 // |<------| link->ImmPCOffset() | 716 // |<------| link->ImmPCOffset() |
| 715 // |------>| prevlinkoffset = linkoffset + link->ImmPCOffset() | 717 // |------>| prevlinkoffset = linkoffset + link->ImmPCOffset() |
| 716 // | 718 // |
| 717 // On each iteration, the last link is updated and then removed from the | 719 // On each iteration, the last link is updated and then removed from the |
| 718 // chain until only one remains. At that point, the label is bound. | 720 // chain until only one remains. At that point, the label is bound. |
| 719 // | 721 // |
| 720 // If the label is not linked, no preparation is required before binding. | 722 // If the label is not linked, no preparation is required before binding. |
| 721 while (label->is_linked()) { | 723 while (label->is_linked()) { |
| 722 int linkoffset = label->pos(); | 724 int linkoffset = label->pos(); |
| 723 Instruction* link = InstructionAt(linkoffset); | 725 Instruction* link = InstructionAt(linkoffset); |
| 724 int prevlinkoffset = linkoffset + link->ImmPCOffset(); | 726 int prevlinkoffset = linkoffset + static_cast<int>(link->ImmPCOffset()); |
| 725 | 727 |
| 726 CheckLabelLinkChain(label); | 728 CheckLabelLinkChain(label); |
| 727 | 729 |
| 728 DCHECK(linkoffset >= 0); | 730 DCHECK(linkoffset >= 0); |
| 729 DCHECK(linkoffset < pc_offset()); | 731 DCHECK(linkoffset < pc_offset()); |
| 730 DCHECK((linkoffset > prevlinkoffset) || | 732 DCHECK((linkoffset > prevlinkoffset) || |
| 731 (linkoffset - prevlinkoffset == kStartOfLabelLinkChain)); | 733 (linkoffset - prevlinkoffset == kStartOfLabelLinkChain)); |
| 732 DCHECK(prevlinkoffset >= 0); | 734 DCHECK(prevlinkoffset >= 0); |
| 733 | 735 |
| 734 // Update the link to point to the label. | 736 // Update the link to point to the label. |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 804 void Assembler::DeleteUnresolvedBranchInfoForLabelTraverse(Label* label) { | 806 void Assembler::DeleteUnresolvedBranchInfoForLabelTraverse(Label* label) { |
| 805 DCHECK(label->is_linked()); | 807 DCHECK(label->is_linked()); |
| 806 CheckLabelLinkChain(label); | 808 CheckLabelLinkChain(label); |
| 807 | 809 |
| 808 int link_offset = label->pos(); | 810 int link_offset = label->pos(); |
| 809 int link_pcoffset; | 811 int link_pcoffset; |
| 810 bool end_of_chain = false; | 812 bool end_of_chain = false; |
| 811 | 813 |
| 812 while (!end_of_chain) { | 814 while (!end_of_chain) { |
| 813 Instruction * link = InstructionAt(link_offset); | 815 Instruction * link = InstructionAt(link_offset); |
| 814 link_pcoffset = link->ImmPCOffset(); | 816 link_pcoffset = static_cast<int>(link->ImmPCOffset()); |
| 815 | 817 |
| 816 // ADR instructions are not handled by veneers. | 818 // ADR instructions are not handled by veneers. |
| 817 if (link->IsImmBranch()) { | 819 if (link->IsImmBranch()) { |
| 818 int max_reachable_pc = InstructionOffset(link) + | 820 int max_reachable_pc = |
| 819 Instruction::ImmBranchRange(link->BranchType()); | 821 static_cast<int>(InstructionOffset(link) + |
| 822 Instruction::ImmBranchRange(link->BranchType())); |
| 820 typedef std::multimap<int, FarBranchInfo>::iterator unresolved_info_it; | 823 typedef std::multimap<int, FarBranchInfo>::iterator unresolved_info_it; |
| 821 std::pair<unresolved_info_it, unresolved_info_it> range; | 824 std::pair<unresolved_info_it, unresolved_info_it> range; |
| 822 range = unresolved_branches_.equal_range(max_reachable_pc); | 825 range = unresolved_branches_.equal_range(max_reachable_pc); |
| 823 unresolved_info_it it; | 826 unresolved_info_it it; |
| 824 for (it = range.first; it != range.second; ++it) { | 827 for (it = range.first; it != range.second; ++it) { |
| 825 if (it->second.pc_offset_ == link_offset) { | 828 if (it->second.pc_offset_ == link_offset) { |
| 826 unresolved_branches_.erase(it); | 829 unresolved_branches_.erase(it); |
| 827 break; | 830 break; |
| 828 } | 831 } |
| 829 } | 832 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 902 int Assembler::ConstantPoolSizeAt(Instruction* instr) { | 905 int Assembler::ConstantPoolSizeAt(Instruction* instr) { |
| 903 #ifdef USE_SIMULATOR | 906 #ifdef USE_SIMULATOR |
| 904 // Assembler::debug() embeds constants directly into the instruction stream. | 907 // Assembler::debug() embeds constants directly into the instruction stream. |
| 905 // Although this is not a genuine constant pool, treat it like one to avoid | 908 // Although this is not a genuine constant pool, treat it like one to avoid |
| 906 // disassembling the constants. | 909 // disassembling the constants. |
| 907 if ((instr->Mask(ExceptionMask) == HLT) && | 910 if ((instr->Mask(ExceptionMask) == HLT) && |
| 908 (instr->ImmException() == kImmExceptionIsDebug)) { | 911 (instr->ImmException() == kImmExceptionIsDebug)) { |
| 909 const char* message = | 912 const char* message = |
| 910 reinterpret_cast<const char*>( | 913 reinterpret_cast<const char*>( |
| 911 instr->InstructionAtOffset(kDebugMessageOffset)); | 914 instr->InstructionAtOffset(kDebugMessageOffset)); |
| 912 int size = kDebugMessageOffset + strlen(message) + 1; | 915 int size = static_cast<int>(kDebugMessageOffset + strlen(message) + 1); |
| 913 return RoundUp(size, kInstructionSize) / kInstructionSize; | 916 return RoundUp(size, kInstructionSize) / kInstructionSize; |
| 914 } | 917 } |
| 915 // Same for printf support, see MacroAssembler::CallPrintf(). | 918 // Same for printf support, see MacroAssembler::CallPrintf(). |
| 916 if ((instr->Mask(ExceptionMask) == HLT) && | 919 if ((instr->Mask(ExceptionMask) == HLT) && |
| 917 (instr->ImmException() == kImmExceptionIsPrintf)) { | 920 (instr->ImmException() == kImmExceptionIsPrintf)) { |
| 918 return kPrintfLength / kInstructionSize; | 921 return kPrintfLength / kInstructionSize; |
| 919 } | 922 } |
| 920 #endif | 923 #endif |
| 921 if (IsConstantPoolAt(instr)) { | 924 if (IsConstantPoolAt(instr)) { |
| 922 return instr->ImmLLiteral(); | 925 return instr->ImmLLiteral(); |
| (...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1592 } | 1595 } |
| 1593 | 1596 |
| 1594 | 1597 |
| 1595 void Assembler::LoadStorePair(const CPURegister& rt, | 1598 void Assembler::LoadStorePair(const CPURegister& rt, |
| 1596 const CPURegister& rt2, | 1599 const CPURegister& rt2, |
| 1597 const MemOperand& addr, | 1600 const MemOperand& addr, |
| 1598 LoadStorePairOp op) { | 1601 LoadStorePairOp op) { |
| 1599 // 'rt' and 'rt2' can only be aliased for stores. | 1602 // 'rt' and 'rt2' can only be aliased for stores. |
| 1600 DCHECK(((op & LoadStorePairLBit) == 0) || !rt.Is(rt2)); | 1603 DCHECK(((op & LoadStorePairLBit) == 0) || !rt.Is(rt2)); |
| 1601 DCHECK(AreSameSizeAndType(rt, rt2)); | 1604 DCHECK(AreSameSizeAndType(rt, rt2)); |
| 1605 DCHECK(IsImmLSPair(addr.offset(), CalcLSPairDataSize(op))); |
| 1606 int offset = static_cast<int>(addr.offset()); |
| 1602 | 1607 |
| 1603 Instr memop = op | Rt(rt) | Rt2(rt2) | RnSP(addr.base()) | | 1608 Instr memop = op | Rt(rt) | Rt2(rt2) | RnSP(addr.base()) | |
| 1604 ImmLSPair(addr.offset(), CalcLSPairDataSize(op)); | 1609 ImmLSPair(offset, CalcLSPairDataSize(op)); |
| 1605 | 1610 |
| 1606 Instr addrmodeop; | 1611 Instr addrmodeop; |
| 1607 if (addr.IsImmediateOffset()) { | 1612 if (addr.IsImmediateOffset()) { |
| 1608 addrmodeop = LoadStorePairOffsetFixed; | 1613 addrmodeop = LoadStorePairOffsetFixed; |
| 1609 } else { | 1614 } else { |
| 1610 // Pre-index and post-index modes. | 1615 // Pre-index and post-index modes. |
| 1611 DCHECK(!rt.Is(addr.base())); | 1616 DCHECK(!rt.Is(addr.base())); |
| 1612 DCHECK(!rt2.Is(addr.base())); | 1617 DCHECK(!rt2.Is(addr.base())); |
| 1613 DCHECK(addr.offset() != 0); | 1618 DCHECK(addr.offset() != 0); |
| 1614 if (addr.IsPreIndex()) { | 1619 if (addr.IsPreIndex()) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1638 } | 1643 } |
| 1639 | 1644 |
| 1640 | 1645 |
| 1641 void Assembler::LoadStorePairNonTemporal(const CPURegister& rt, | 1646 void Assembler::LoadStorePairNonTemporal(const CPURegister& rt, |
| 1642 const CPURegister& rt2, | 1647 const CPURegister& rt2, |
| 1643 const MemOperand& addr, | 1648 const MemOperand& addr, |
| 1644 LoadStorePairNonTemporalOp op) { | 1649 LoadStorePairNonTemporalOp op) { |
| 1645 DCHECK(!rt.Is(rt2)); | 1650 DCHECK(!rt.Is(rt2)); |
| 1646 DCHECK(AreSameSizeAndType(rt, rt2)); | 1651 DCHECK(AreSameSizeAndType(rt, rt2)); |
| 1647 DCHECK(addr.IsImmediateOffset()); | 1652 DCHECK(addr.IsImmediateOffset()); |
| 1648 | |
| 1649 LSDataSize size = CalcLSPairDataSize( | 1653 LSDataSize size = CalcLSPairDataSize( |
| 1650 static_cast<LoadStorePairOp>(op & LoadStorePairMask)); | 1654 static_cast<LoadStorePairOp>(op & LoadStorePairMask)); |
| 1651 Emit(op | Rt(rt) | Rt2(rt2) | RnSP(addr.base()) | | 1655 DCHECK(IsImmLSPair(addr.offset(), size)); |
| 1652 ImmLSPair(addr.offset(), size)); | 1656 int offset = static_cast<int>(addr.offset()); |
| 1657 Emit(op | Rt(rt) | Rt2(rt2) | RnSP(addr.base()) | ImmLSPair(offset, size)); |
| 1653 } | 1658 } |
| 1654 | 1659 |
| 1655 | 1660 |
| 1656 // Memory instructions. | 1661 // Memory instructions. |
| 1657 void Assembler::ldrb(const Register& rt, const MemOperand& src) { | 1662 void Assembler::ldrb(const Register& rt, const MemOperand& src) { |
| 1658 LoadStore(rt, src, LDRB_w); | 1663 LoadStore(rt, src, LDRB_w); |
| 1659 } | 1664 } |
| 1660 | 1665 |
| 1661 | 1666 |
| 1662 void Assembler::strb(const Register& rt, const MemOperand& dst) { | 1667 void Assembler::strb(const Register& rt, const MemOperand& dst) { |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2130 return (bit7 | bit6 | bit5_to_0) << ImmFP_offset; | 2135 return (bit7 | bit6 | bit5_to_0) << ImmFP_offset; |
| 2131 } | 2136 } |
| 2132 | 2137 |
| 2133 | 2138 |
| 2134 Instr Assembler::ImmFP64(double imm) { | 2139 Instr Assembler::ImmFP64(double imm) { |
| 2135 DCHECK(IsImmFP64(imm)); | 2140 DCHECK(IsImmFP64(imm)); |
| 2136 // bits: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 | 2141 // bits: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 |
| 2137 // 0000.0000.0000.0000.0000.0000.0000.0000 | 2142 // 0000.0000.0000.0000.0000.0000.0000.0000 |
| 2138 uint64_t bits = double_to_rawbits(imm); | 2143 uint64_t bits = double_to_rawbits(imm); |
| 2139 // bit7: a000.0000 | 2144 // bit7: a000.0000 |
| 2140 uint32_t bit7 = ((bits >> 63) & 0x1) << 7; | 2145 uint64_t bit7 = ((bits >> 63) & 0x1) << 7; |
| 2141 // bit6: 0b00.0000 | 2146 // bit6: 0b00.0000 |
| 2142 uint32_t bit6 = ((bits >> 61) & 0x1) << 6; | 2147 uint64_t bit6 = ((bits >> 61) & 0x1) << 6; |
| 2143 // bit5_to_0: 00cd.efgh | 2148 // bit5_to_0: 00cd.efgh |
| 2144 uint32_t bit5_to_0 = (bits >> 48) & 0x3f; | 2149 uint64_t bit5_to_0 = (bits >> 48) & 0x3f; |
| 2145 | 2150 |
| 2146 return (bit7 | bit6 | bit5_to_0) << ImmFP_offset; | 2151 return static_cast<Instr>((bit7 | bit6 | bit5_to_0) << ImmFP_offset); |
| 2147 } | 2152 } |
| 2148 | 2153 |
| 2149 | 2154 |
| 2150 // Code generation helpers. | 2155 // Code generation helpers. |
| 2151 void Assembler::MoveWide(const Register& rd, | 2156 void Assembler::MoveWide(const Register& rd, |
| 2152 uint64_t imm, | 2157 uint64_t imm, |
| 2153 int shift, | 2158 int shift, |
| 2154 MoveWideImmediateOp mov_op) { | 2159 MoveWideImmediateOp mov_op) { |
| 2155 // Ignore the top 32 bits of an immediate if we're moving to a W register. | 2160 // Ignore the top 32 bits of an immediate if we're moving to a W register. |
| 2156 if (rd.Is32Bits()) { | 2161 if (rd.Is32Bits()) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2181 shift = 2; | 2186 shift = 2; |
| 2182 } else if ((imm & ~(0xffffUL << 48)) == 0) { | 2187 } else if ((imm & ~(0xffffUL << 48)) == 0) { |
| 2183 DCHECK(rd.Is64Bits()); | 2188 DCHECK(rd.Is64Bits()); |
| 2184 imm >>= 48; | 2189 imm >>= 48; |
| 2185 shift = 3; | 2190 shift = 3; |
| 2186 } | 2191 } |
| 2187 } | 2192 } |
| 2188 | 2193 |
| 2189 DCHECK(is_uint16(imm)); | 2194 DCHECK(is_uint16(imm)); |
| 2190 | 2195 |
| 2191 Emit(SF(rd) | MoveWideImmediateFixed | mov_op | | 2196 Emit(SF(rd) | MoveWideImmediateFixed | mov_op | Rd(rd) | |
| 2192 Rd(rd) | ImmMoveWide(imm) | ShiftMoveWide(shift)); | 2197 ImmMoveWide(static_cast<int>(imm)) | ShiftMoveWide(shift)); |
| 2193 } | 2198 } |
| 2194 | 2199 |
| 2195 | 2200 |
| 2196 void Assembler::AddSub(const Register& rd, | 2201 void Assembler::AddSub(const Register& rd, |
| 2197 const Register& rn, | 2202 const Register& rn, |
| 2198 const Operand& operand, | 2203 const Operand& operand, |
| 2199 FlagsUpdate S, | 2204 FlagsUpdate S, |
| 2200 AddSubOp op) { | 2205 AddSubOp op) { |
| 2201 DCHECK(rd.SizeInBits() == rn.SizeInBits()); | 2206 DCHECK(rd.SizeInBits() == rn.SizeInBits()); |
| 2202 DCHECK(!operand.NeedsRelocation(this)); | 2207 DCHECK(!operand.NeedsRelocation(this)); |
| 2203 if (operand.IsImmediate()) { | 2208 if (operand.IsImmediate()) { |
| 2204 int64_t immediate = operand.ImmediateValue(); | 2209 int64_t immediate = operand.ImmediateValue(); |
| 2205 DCHECK(IsImmAddSub(immediate)); | 2210 DCHECK(IsImmAddSub(immediate)); |
| 2206 Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd); | 2211 Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd); |
| 2207 Emit(SF(rd) | AddSubImmediateFixed | op | Flags(S) | | 2212 Emit(SF(rd) | AddSubImmediateFixed | op | Flags(S) | |
| 2208 ImmAddSub(immediate) | dest_reg | RnSP(rn)); | 2213 ImmAddSub(static_cast<int>(immediate)) | dest_reg | RnSP(rn)); |
| 2209 } else if (operand.IsShiftedRegister()) { | 2214 } else if (operand.IsShiftedRegister()) { |
| 2210 DCHECK(operand.reg().SizeInBits() == rd.SizeInBits()); | 2215 DCHECK(operand.reg().SizeInBits() == rd.SizeInBits()); |
| 2211 DCHECK(operand.shift() != ROR); | 2216 DCHECK(operand.shift() != ROR); |
| 2212 | 2217 |
| 2213 // For instructions of the form: | 2218 // For instructions of the form: |
| 2214 // add/sub wsp, <Wn>, <Wm> [, LSL #0-3 ] | 2219 // add/sub wsp, <Wn>, <Wm> [, LSL #0-3 ] |
| 2215 // add/sub <Wd>, wsp, <Wm> [, LSL #0-3 ] | 2220 // add/sub <Wd>, wsp, <Wm> [, LSL #0-3 ] |
| 2216 // add/sub wsp, wsp, <Wm> [, LSL #0-3 ] | 2221 // add/sub wsp, wsp, <Wm> [, LSL #0-3 ] |
| 2217 // adds/subs <Wd>, wsp, <Wm> [, LSL #0-3 ] | 2222 // adds/subs <Wd>, wsp, <Wm> [, LSL #0-3 ] |
| 2218 // or their 64-bit register equivalents, convert the operand from shifted to | 2223 // or their 64-bit register equivalents, convert the operand from shifted to |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2252 | 2257 |
| 2253 void Assembler::brk(int code) { | 2258 void Assembler::brk(int code) { |
| 2254 DCHECK(is_uint16(code)); | 2259 DCHECK(is_uint16(code)); |
| 2255 Emit(BRK | ImmException(code)); | 2260 Emit(BRK | ImmException(code)); |
| 2256 } | 2261 } |
| 2257 | 2262 |
| 2258 | 2263 |
| 2259 void Assembler::EmitStringData(const char* string) { | 2264 void Assembler::EmitStringData(const char* string) { |
| 2260 size_t len = strlen(string) + 1; | 2265 size_t len = strlen(string) + 1; |
| 2261 DCHECK(RoundUp(len, kInstructionSize) <= static_cast<size_t>(kGap)); | 2266 DCHECK(RoundUp(len, kInstructionSize) <= static_cast<size_t>(kGap)); |
| 2262 EmitData(string, len); | 2267 EmitData(string, static_cast<int>(len)); |
| 2263 // Pad with NULL characters until pc_ is aligned. | 2268 // Pad with NULL characters until pc_ is aligned. |
| 2264 const char pad[] = {'\0', '\0', '\0', '\0'}; | 2269 const char pad[] = {'\0', '\0', '\0', '\0'}; |
| 2265 STATIC_ASSERT(sizeof(pad) == kInstructionSize); | 2270 STATIC_ASSERT(sizeof(pad) == kInstructionSize); |
| 2266 EmitData(pad, RoundUp(pc_offset(), kInstructionSize) - pc_offset()); | 2271 EmitData(pad, RoundUp(pc_offset(), kInstructionSize) - pc_offset()); |
| 2267 } | 2272 } |
| 2268 | 2273 |
| 2269 | 2274 |
| 2270 void Assembler::debug(const char* message, uint32_t code, Instr params) { | 2275 void Assembler::debug(const char* message, uint32_t code, Instr params) { |
| 2271 #ifdef USE_SIMULATOR | 2276 #ifdef USE_SIMULATOR |
| 2272 // Don't generate simulator specific code if we are building a snapshot, which | 2277 // Don't generate simulator specific code if we are building a snapshot, which |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2355 void Assembler::ConditionalCompare(const Register& rn, | 2360 void Assembler::ConditionalCompare(const Register& rn, |
| 2356 const Operand& operand, | 2361 const Operand& operand, |
| 2357 StatusFlags nzcv, | 2362 StatusFlags nzcv, |
| 2358 Condition cond, | 2363 Condition cond, |
| 2359 ConditionalCompareOp op) { | 2364 ConditionalCompareOp op) { |
| 2360 Instr ccmpop; | 2365 Instr ccmpop; |
| 2361 DCHECK(!operand.NeedsRelocation(this)); | 2366 DCHECK(!operand.NeedsRelocation(this)); |
| 2362 if (operand.IsImmediate()) { | 2367 if (operand.IsImmediate()) { |
| 2363 int64_t immediate = operand.ImmediateValue(); | 2368 int64_t immediate = operand.ImmediateValue(); |
| 2364 DCHECK(IsImmConditionalCompare(immediate)); | 2369 DCHECK(IsImmConditionalCompare(immediate)); |
| 2365 ccmpop = ConditionalCompareImmediateFixed | op | ImmCondCmp(immediate); | 2370 ccmpop = ConditionalCompareImmediateFixed | op | |
| 2371 ImmCondCmp(static_cast<unsigned>(immediate)); |
| 2366 } else { | 2372 } else { |
| 2367 DCHECK(operand.IsShiftedRegister() && (operand.shift_amount() == 0)); | 2373 DCHECK(operand.IsShiftedRegister() && (operand.shift_amount() == 0)); |
| 2368 ccmpop = ConditionalCompareRegisterFixed | op | Rm(operand.reg()); | 2374 ccmpop = ConditionalCompareRegisterFixed | op | Rm(operand.reg()); |
| 2369 } | 2375 } |
| 2370 Emit(SF(rn) | ccmpop | Cond(cond) | Rn(rn) | Nzcv(nzcv)); | 2376 Emit(SF(rn) | ccmpop | Cond(cond) | Rn(rn) | Nzcv(nzcv)); |
| 2371 } | 2377 } |
| 2372 | 2378 |
| 2373 | 2379 |
| 2374 void Assembler::DataProcessing1Source(const Register& rd, | 2380 void Assembler::DataProcessing1Source(const Register& rd, |
| 2375 const Register& rn, | 2381 const Register& rn, |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2495 | 2501 |
| 2496 bool Assembler::IsImmAddSub(int64_t immediate) { | 2502 bool Assembler::IsImmAddSub(int64_t immediate) { |
| 2497 return is_uint12(immediate) || | 2503 return is_uint12(immediate) || |
| 2498 (is_uint12(immediate >> 12) && ((immediate & 0xfff) == 0)); | 2504 (is_uint12(immediate >> 12) && ((immediate & 0xfff) == 0)); |
| 2499 } | 2505 } |
| 2500 | 2506 |
| 2501 void Assembler::LoadStore(const CPURegister& rt, | 2507 void Assembler::LoadStore(const CPURegister& rt, |
| 2502 const MemOperand& addr, | 2508 const MemOperand& addr, |
| 2503 LoadStoreOp op) { | 2509 LoadStoreOp op) { |
| 2504 Instr memop = op | Rt(rt) | RnSP(addr.base()); | 2510 Instr memop = op | Rt(rt) | RnSP(addr.base()); |
| 2505 int64_t offset = addr.offset(); | |
| 2506 | 2511 |
| 2507 if (addr.IsImmediateOffset()) { | 2512 if (addr.IsImmediateOffset()) { |
| 2508 LSDataSize size = CalcLSDataSize(op); | 2513 LSDataSize size = CalcLSDataSize(op); |
| 2509 if (IsImmLSScaled(offset, size)) { | 2514 if (IsImmLSScaled(addr.offset(), size)) { |
| 2515 int offset = static_cast<int>(addr.offset()); |
| 2510 // Use the scaled addressing mode. | 2516 // Use the scaled addressing mode. |
| 2511 Emit(LoadStoreUnsignedOffsetFixed | memop | | 2517 Emit(LoadStoreUnsignedOffsetFixed | memop | |
| 2512 ImmLSUnsigned(offset >> size)); | 2518 ImmLSUnsigned(offset >> size)); |
| 2513 } else if (IsImmLSUnscaled(offset)) { | 2519 } else if (IsImmLSUnscaled(addr.offset())) { |
| 2520 int offset = static_cast<int>(addr.offset()); |
| 2514 // Use the unscaled addressing mode. | 2521 // Use the unscaled addressing mode. |
| 2515 Emit(LoadStoreUnscaledOffsetFixed | memop | ImmLS(offset)); | 2522 Emit(LoadStoreUnscaledOffsetFixed | memop | ImmLS(offset)); |
| 2516 } else { | 2523 } else { |
| 2517 // This case is handled in the macro assembler. | 2524 // This case is handled in the macro assembler. |
| 2518 UNREACHABLE(); | 2525 UNREACHABLE(); |
| 2519 } | 2526 } |
| 2520 } else if (addr.IsRegisterOffset()) { | 2527 } else if (addr.IsRegisterOffset()) { |
| 2521 Extend ext = addr.extend(); | 2528 Extend ext = addr.extend(); |
| 2522 Shift shift = addr.shift(); | 2529 Shift shift = addr.shift(); |
| 2523 unsigned shift_amount = addr.shift_amount(); | 2530 unsigned shift_amount = addr.shift_amount(); |
| 2524 | 2531 |
| 2525 // LSL is encoded in the option field as UXTX. | 2532 // LSL is encoded in the option field as UXTX. |
| 2526 if (shift == LSL) { | 2533 if (shift == LSL) { |
| 2527 ext = UXTX; | 2534 ext = UXTX; |
| 2528 } | 2535 } |
| 2529 | 2536 |
| 2530 // Shifts are encoded in one bit, indicating a left shift by the memory | 2537 // Shifts are encoded in one bit, indicating a left shift by the memory |
| 2531 // access size. | 2538 // access size. |
| 2532 DCHECK((shift_amount == 0) || | 2539 DCHECK((shift_amount == 0) || |
| 2533 (shift_amount == static_cast<unsigned>(CalcLSDataSize(op)))); | 2540 (shift_amount == static_cast<unsigned>(CalcLSDataSize(op)))); |
| 2534 Emit(LoadStoreRegisterOffsetFixed | memop | Rm(addr.regoffset()) | | 2541 Emit(LoadStoreRegisterOffsetFixed | memop | Rm(addr.regoffset()) | |
| 2535 ExtendMode(ext) | ImmShiftLS((shift_amount > 0) ? 1 : 0)); | 2542 ExtendMode(ext) | ImmShiftLS((shift_amount > 0) ? 1 : 0)); |
| 2536 } else { | 2543 } else { |
| 2537 // Pre-index and post-index modes. | 2544 // Pre-index and post-index modes. |
| 2538 DCHECK(!rt.Is(addr.base())); | 2545 DCHECK(!rt.Is(addr.base())); |
| 2539 if (IsImmLSUnscaled(offset)) { | 2546 if (IsImmLSUnscaled(addr.offset())) { |
| 2547 int offset = static_cast<int>(addr.offset()); |
| 2540 if (addr.IsPreIndex()) { | 2548 if (addr.IsPreIndex()) { |
| 2541 Emit(LoadStorePreIndexFixed | memop | ImmLS(offset)); | 2549 Emit(LoadStorePreIndexFixed | memop | ImmLS(offset)); |
| 2542 } else { | 2550 } else { |
| 2543 DCHECK(addr.IsPostIndex()); | 2551 DCHECK(addr.IsPostIndex()); |
| 2544 Emit(LoadStorePostIndexFixed | memop | ImmLS(offset)); | 2552 Emit(LoadStorePostIndexFixed | memop | ImmLS(offset)); |
| 2545 } | 2553 } |
| 2546 } else { | 2554 } else { |
| 2547 // This case is handled in the macro assembler. | 2555 // This case is handled in the macro assembler. |
| 2548 UNREACHABLE(); | 2556 UNREACHABLE(); |
| 2549 } | 2557 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2561 return offset_is_size_multiple && is_uint12(offset >> size); | 2569 return offset_is_size_multiple && is_uint12(offset >> size); |
| 2562 } | 2570 } |
| 2563 | 2571 |
| 2564 | 2572 |
| 2565 bool Assembler::IsImmLSPair(int64_t offset, LSDataSize size) { | 2573 bool Assembler::IsImmLSPair(int64_t offset, LSDataSize size) { |
| 2566 bool offset_is_size_multiple = (((offset >> size) << size) == offset); | 2574 bool offset_is_size_multiple = (((offset >> size) << size) == offset); |
| 2567 return offset_is_size_multiple && is_int7(offset >> size); | 2575 return offset_is_size_multiple && is_int7(offset >> size); |
| 2568 } | 2576 } |
| 2569 | 2577 |
| 2570 | 2578 |
| 2579 bool Assembler::IsImmLLiteral(int64_t offset) { |
| 2580 int inst_size = static_cast<int>(kInstructionSizeLog2); |
| 2581 bool offset_is_inst_multiple = |
| 2582 (((offset >> inst_size) << inst_size) == offset); |
| 2583 return offset_is_inst_multiple && is_intn(offset, ImmLLiteral_width); |
| 2584 } |
| 2585 |
| 2586 |
| 2571 // Test if a given value can be encoded in the immediate field of a logical | 2587 // Test if a given value can be encoded in the immediate field of a logical |
| 2572 // instruction. | 2588 // instruction. |
| 2573 // If it can be encoded, the function returns true, and values pointed to by n, | 2589 // If it can be encoded, the function returns true, and values pointed to by n, |
| 2574 // imm_s and imm_r are updated with immediates encoded in the format required | 2590 // imm_s and imm_r are updated with immediates encoded in the format required |
| 2575 // by the corresponding fields in the logical instruction. | 2591 // by the corresponding fields in the logical instruction. |
| 2576 // If it can not be encoded, the function returns false, and the values pointed | 2592 // If it can not be encoded, the function returns false, and the values pointed |
| 2577 // to by n, imm_s and imm_r are undefined. | 2593 // to by n, imm_s and imm_r are undefined. |
| 2578 bool Assembler::IsImmLogical(uint64_t value, | 2594 bool Assembler::IsImmLogical(uint64_t value, |
| 2579 unsigned width, | 2595 unsigned width, |
| 2580 unsigned* n, | 2596 unsigned* n, |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2842 desc.buffer_size = buffer_size_ + 1 * MB; | 2858 desc.buffer_size = buffer_size_ + 1 * MB; |
| 2843 } | 2859 } |
| 2844 CHECK_GT(desc.buffer_size, 0); // No overflow. | 2860 CHECK_GT(desc.buffer_size, 0); // No overflow. |
| 2845 | 2861 |
| 2846 byte* buffer = reinterpret_cast<byte*>(buffer_); | 2862 byte* buffer = reinterpret_cast<byte*>(buffer_); |
| 2847 | 2863 |
| 2848 // Set up new buffer. | 2864 // Set up new buffer. |
| 2849 desc.buffer = NewArray<byte>(desc.buffer_size); | 2865 desc.buffer = NewArray<byte>(desc.buffer_size); |
| 2850 | 2866 |
| 2851 desc.instr_size = pc_offset(); | 2867 desc.instr_size = pc_offset(); |
| 2852 desc.reloc_size = (buffer + buffer_size_) - reloc_info_writer.pos(); | 2868 desc.reloc_size = |
| 2869 static_cast<int>((buffer + buffer_size_) - reloc_info_writer.pos()); |
| 2853 | 2870 |
| 2854 // Copy the data. | 2871 // Copy the data. |
| 2855 intptr_t pc_delta = desc.buffer - buffer; | 2872 intptr_t pc_delta = desc.buffer - buffer; |
| 2856 intptr_t rc_delta = (desc.buffer + desc.buffer_size) - | 2873 intptr_t rc_delta = (desc.buffer + desc.buffer_size) - |
| 2857 (buffer + buffer_size_); | 2874 (buffer + buffer_size_); |
| 2858 memmove(desc.buffer, buffer, desc.instr_size); | 2875 memmove(desc.buffer, buffer, desc.instr_size); |
| 2859 memmove(reloc_info_writer.pos() + rc_delta, | 2876 memmove(reloc_info_writer.pos() + rc_delta, |
| 2860 reloc_info_writer.pos(), desc.reloc_size); | 2877 reloc_info_writer.pos(), desc.reloc_size); |
| 2861 | 2878 |
| 2862 // Switch buffers. | 2879 // Switch buffers. |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3058 #endif | 3075 #endif |
| 3059 | 3076 |
| 3060 it_to_delete = it++; | 3077 it_to_delete = it++; |
| 3061 unresolved_branches_.erase(it_to_delete); | 3078 unresolved_branches_.erase(it_to_delete); |
| 3062 } else { | 3079 } else { |
| 3063 ++it; | 3080 ++it; |
| 3064 } | 3081 } |
| 3065 } | 3082 } |
| 3066 | 3083 |
| 3067 // Record the veneer pool size. | 3084 // Record the veneer pool size. |
| 3068 int pool_size = SizeOfCodeGeneratedSince(&size_check); | 3085 int pool_size = static_cast<int>(SizeOfCodeGeneratedSince(&size_check)); |
| 3069 RecordVeneerPool(veneer_pool_relocinfo_loc, pool_size); | 3086 RecordVeneerPool(veneer_pool_relocinfo_loc, pool_size); |
| 3070 | 3087 |
| 3071 if (unresolved_branches_.empty()) { | 3088 if (unresolved_branches_.empty()) { |
| 3072 next_veneer_pool_check_ = kMaxInt; | 3089 next_veneer_pool_check_ = kMaxInt; |
| 3073 } else { | 3090 } else { |
| 3074 next_veneer_pool_check_ = | 3091 next_veneer_pool_check_ = |
| 3075 unresolved_branches_first_limit() - kVeneerDistanceCheckMargin; | 3092 unresolved_branches_first_limit() - kVeneerDistanceCheckMargin; |
| 3076 } | 3093 } |
| 3077 | 3094 |
| 3078 bind(&end); | 3095 bind(&end); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3106 if (force_emit || ShouldEmitVeneers(margin)) { | 3123 if (force_emit || ShouldEmitVeneers(margin)) { |
| 3107 EmitVeneers(force_emit, require_jump, margin); | 3124 EmitVeneers(force_emit, require_jump, margin); |
| 3108 } else { | 3125 } else { |
| 3109 next_veneer_pool_check_ = | 3126 next_veneer_pool_check_ = |
| 3110 unresolved_branches_first_limit() - kVeneerDistanceCheckMargin; | 3127 unresolved_branches_first_limit() - kVeneerDistanceCheckMargin; |
| 3111 } | 3128 } |
| 3112 } | 3129 } |
| 3113 | 3130 |
| 3114 | 3131 |
| 3115 int Assembler::buffer_space() const { | 3132 int Assembler::buffer_space() const { |
| 3116 return reloc_info_writer.pos() - reinterpret_cast<byte*>(pc_); | 3133 return static_cast<int>(reloc_info_writer.pos() - |
| 3134 reinterpret_cast<byte*>(pc_)); |
| 3117 } | 3135 } |
| 3118 | 3136 |
| 3119 | 3137 |
| 3120 void Assembler::RecordConstPool(int size) { | 3138 void Assembler::RecordConstPool(int size) { |
| 3121 // We only need this for debugger support, to correctly compute offsets in the | 3139 // We only need this for debugger support, to correctly compute offsets in the |
| 3122 // code. | 3140 // code. |
| 3123 RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size)); | 3141 RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size)); |
| 3124 } | 3142 } |
| 3125 | 3143 |
| 3126 | 3144 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3167 movz(scratch, (target_offset >> 16) & 0xFFFF, 16); | 3185 movz(scratch, (target_offset >> 16) & 0xFFFF, 16); |
| 3168 movk(scratch, (target_offset >> 32) & 0xFFFF, 32); | 3186 movk(scratch, (target_offset >> 32) & 0xFFFF, 32); |
| 3169 DCHECK((target_offset >> 48) == 0); | 3187 DCHECK((target_offset >> 48) == 0); |
| 3170 add(rd, rd, scratch); | 3188 add(rd, rd, scratch); |
| 3171 } | 3189 } |
| 3172 | 3190 |
| 3173 | 3191 |
| 3174 } } // namespace v8::internal | 3192 } } // namespace v8::internal |
| 3175 | 3193 |
| 3176 #endif // V8_TARGET_ARCH_ARM64 | 3194 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |