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 |