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 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 } | 113 } |
114 | 114 |
115 | 115 |
116 // This function defines the list of registers which are associated with a | 116 // This function defines the list of registers which are associated with a |
117 // safepoint slot. Safepoint register slots are saved contiguously on the stack. | 117 // safepoint slot. Safepoint register slots are saved contiguously on the stack. |
118 // MacroAssembler::SafepointRegisterStackIndex handles mapping from register | 118 // MacroAssembler::SafepointRegisterStackIndex handles mapping from register |
119 // code to index in the safepoint register slots. Any change here can affect | 119 // code to index in the safepoint register slots. Any change here can affect |
120 // this mapping. | 120 // this mapping. |
121 CPURegList CPURegList::GetSafepointSavedRegisters() { | 121 CPURegList CPURegList::GetSafepointSavedRegisters() { |
122 CPURegList list = CPURegList::GetCalleeSaved(); | 122 CPURegList list = CPURegList::GetCalleeSaved(); |
123 list.Combine(CPURegList(CPURegister::kRegister, kXRegSize, kJSCallerSaved)); | 123 list.Combine( |
| 124 CPURegList(CPURegister::kRegister, kXRegSizeInBits, kJSCallerSaved)); |
124 | 125 |
125 // Note that unfortunately we can't use symbolic names for registers and have | 126 // Note that unfortunately we can't use symbolic names for registers and have |
126 // to directly use register codes. This is because this function is used to | 127 // to directly use register codes. This is because this function is used to |
127 // initialize some static variables and we can't rely on register variables | 128 // initialize some static variables and we can't rely on register variables |
128 // to be initialized due to static initialization order issues in C++. | 129 // to be initialized due to static initialization order issues in C++. |
129 | 130 |
130 // Drop ip0 and ip1 (i.e. x16 and x17), as they should not be expected to be | 131 // Drop ip0 and ip1 (i.e. x16 and x17), as they should not be expected to be |
131 // preserved outside of the macro assembler. | 132 // preserved outside of the macro assembler. |
132 list.Remove(16); | 133 list.Remove(16); |
133 list.Remove(17); | 134 list.Remove(17); |
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 Label* label) { | 742 Label* label) { |
742 positions_recorder()->WriteRecordedPositions(); | 743 positions_recorder()->WriteRecordedPositions(); |
743 cbnz(rt, LinkAndGetInstructionOffsetTo(label)); | 744 cbnz(rt, LinkAndGetInstructionOffsetTo(label)); |
744 } | 745 } |
745 | 746 |
746 | 747 |
747 void Assembler::tbz(const Register& rt, | 748 void Assembler::tbz(const Register& rt, |
748 unsigned bit_pos, | 749 unsigned bit_pos, |
749 int imm14) { | 750 int imm14) { |
750 positions_recorder()->WriteRecordedPositions(); | 751 positions_recorder()->WriteRecordedPositions(); |
751 ASSERT(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSize))); | 752 ASSERT(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSizeInBits))); |
752 Emit(TBZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt)); | 753 Emit(TBZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt)); |
753 } | 754 } |
754 | 755 |
755 | 756 |
756 void Assembler::tbz(const Register& rt, | 757 void Assembler::tbz(const Register& rt, |
757 unsigned bit_pos, | 758 unsigned bit_pos, |
758 Label* label) { | 759 Label* label) { |
759 positions_recorder()->WriteRecordedPositions(); | 760 positions_recorder()->WriteRecordedPositions(); |
760 tbz(rt, bit_pos, LinkAndGetInstructionOffsetTo(label)); | 761 tbz(rt, bit_pos, LinkAndGetInstructionOffsetTo(label)); |
761 } | 762 } |
762 | 763 |
763 | 764 |
764 void Assembler::tbnz(const Register& rt, | 765 void Assembler::tbnz(const Register& rt, |
765 unsigned bit_pos, | 766 unsigned bit_pos, |
766 int imm14) { | 767 int imm14) { |
767 positions_recorder()->WriteRecordedPositions(); | 768 positions_recorder()->WriteRecordedPositions(); |
768 ASSERT(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSize))); | 769 ASSERT(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSizeInBits))); |
769 Emit(TBNZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt)); | 770 Emit(TBNZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt)); |
770 } | 771 } |
771 | 772 |
772 | 773 |
773 void Assembler::tbnz(const Register& rt, | 774 void Assembler::tbnz(const Register& rt, |
774 unsigned bit_pos, | 775 unsigned bit_pos, |
775 Label* label) { | 776 Label* label) { |
776 positions_recorder()->WriteRecordedPositions(); | 777 positions_recorder()->WriteRecordedPositions(); |
777 tbnz(rt, bit_pos, LinkAndGetInstructionOffsetTo(label)); | 778 tbnz(rt, bit_pos, LinkAndGetInstructionOffsetTo(label)); |
778 } | 779 } |
(...skipping 1299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2078 if ((non_shift_bits > high_bit) || (non_shift_bits == 0)) { | 2079 if ((non_shift_bits > high_bit) || (non_shift_bits == 0)) { |
2079 switch (extend) { | 2080 switch (extend) { |
2080 case UXTB: | 2081 case UXTB: |
2081 case UXTH: | 2082 case UXTH: |
2082 case UXTW: ubfm(rd, rn_, non_shift_bits, high_bit); break; | 2083 case UXTW: ubfm(rd, rn_, non_shift_bits, high_bit); break; |
2083 case SXTB: | 2084 case SXTB: |
2084 case SXTH: | 2085 case SXTH: |
2085 case SXTW: sbfm(rd, rn_, non_shift_bits, high_bit); break; | 2086 case SXTW: sbfm(rd, rn_, non_shift_bits, high_bit); break; |
2086 case UXTX: | 2087 case UXTX: |
2087 case SXTX: { | 2088 case SXTX: { |
2088 ASSERT(rn.SizeInBits() == kXRegSize); | 2089 ASSERT(rn.SizeInBits() == kXRegSizeInBits); |
2089 // Nothing to extend. Just shift. | 2090 // Nothing to extend. Just shift. |
2090 lsl(rd, rn_, left_shift); | 2091 lsl(rd, rn_, left_shift); |
2091 break; | 2092 break; |
2092 } | 2093 } |
2093 default: UNREACHABLE(); | 2094 default: UNREACHABLE(); |
2094 } | 2095 } |
2095 } else { | 2096 } else { |
2096 // No need to extend as the extended bits would be shifted away. | 2097 // No need to extend as the extended bits would be shifted away. |
2097 lsl(rd, rn_, left_shift); | 2098 lsl(rd, rn_, left_shift); |
2098 } | 2099 } |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2223 // imm_s and imm_r are updated with immediates encoded in the format required | 2224 // imm_s and imm_r are updated with immediates encoded in the format required |
2224 // by the corresponding fields in the logical instruction. | 2225 // by the corresponding fields in the logical instruction. |
2225 // If it can not be encoded, the function returns false, and the values pointed | 2226 // If it can not be encoded, the function returns false, and the values pointed |
2226 // to by n, imm_s and imm_r are undefined. | 2227 // to by n, imm_s and imm_r are undefined. |
2227 bool Assembler::IsImmLogical(uint64_t value, | 2228 bool Assembler::IsImmLogical(uint64_t value, |
2228 unsigned width, | 2229 unsigned width, |
2229 unsigned* n, | 2230 unsigned* n, |
2230 unsigned* imm_s, | 2231 unsigned* imm_s, |
2231 unsigned* imm_r) { | 2232 unsigned* imm_r) { |
2232 ASSERT((n != NULL) && (imm_s != NULL) && (imm_r != NULL)); | 2233 ASSERT((n != NULL) && (imm_s != NULL) && (imm_r != NULL)); |
2233 ASSERT((width == kWRegSize) || (width == kXRegSize)); | 2234 ASSERT((width == kWRegSizeInBits) || (width == kXRegSizeInBits)); |
2234 | 2235 |
2235 // Logical immediates are encoded using parameters n, imm_s and imm_r using | 2236 // Logical immediates are encoded using parameters n, imm_s and imm_r using |
2236 // the following table: | 2237 // the following table: |
2237 // | 2238 // |
2238 // N imms immr size S R | 2239 // N imms immr size S R |
2239 // 1 ssssss rrrrrr 64 UInt(ssssss) UInt(rrrrrr) | 2240 // 1 ssssss rrrrrr 64 UInt(ssssss) UInt(rrrrrr) |
2240 // 0 0sssss xrrrrr 32 UInt(sssss) UInt(rrrrr) | 2241 // 0 0sssss xrrrrr 32 UInt(sssss) UInt(rrrrr) |
2241 // 0 10ssss xxrrrr 16 UInt(ssss) UInt(rrrr) | 2242 // 0 10ssss xxrrrr 16 UInt(ssss) UInt(rrrr) |
2242 // 0 110sss xxxrrr 8 UInt(sss) UInt(rrr) | 2243 // 0 110sss xxxrrr 8 UInt(sss) UInt(rrr) |
2243 // 0 1110ss xxxxrr 4 UInt(ss) UInt(rr) | 2244 // 0 1110ss xxxxrr 4 UInt(ss) UInt(rr) |
2244 // 0 11110s xxxxxr 2 UInt(s) UInt(r) | 2245 // 0 11110s xxxxxr 2 UInt(s) UInt(r) |
2245 // (s bits must not be all set) | 2246 // (s bits must not be all set) |
2246 // | 2247 // |
2247 // A pattern is constructed of size bits, where the least significant S+1 | 2248 // A pattern is constructed of size bits, where the least significant S+1 |
2248 // bits are set. The pattern is rotated right by R, and repeated across a | 2249 // bits are set. The pattern is rotated right by R, and repeated across a |
2249 // 32 or 64-bit value, depending on destination register width. | 2250 // 32 or 64-bit value, depending on destination register width. |
2250 // | 2251 // |
2251 // To test if an arbitary immediate can be encoded using this scheme, an | 2252 // To test if an arbitary immediate can be encoded using this scheme, an |
2252 // iterative algorithm is used. | 2253 // iterative algorithm is used. |
2253 // | 2254 // |
2254 // TODO(mcapewel) This code does not consider using X/W register overlap to | 2255 // TODO(mcapewel) This code does not consider using X/W register overlap to |
2255 // support 64-bit immediates where the top 32-bits are zero, and the bottom | 2256 // support 64-bit immediates where the top 32-bits are zero, and the bottom |
2256 // 32-bits are an encodable logical immediate. | 2257 // 32-bits are an encodable logical immediate. |
2257 | 2258 |
2258 // 1. If the value has all set or all clear bits, it can't be encoded. | 2259 // 1. If the value has all set or all clear bits, it can't be encoded. |
2259 if ((value == 0) || (value == 0xffffffffffffffffUL) || | 2260 if ((value == 0) || (value == 0xffffffffffffffffUL) || |
2260 ((width == kWRegSize) && (value == 0xffffffff))) { | 2261 ((width == kWRegSizeInBits) && (value == 0xffffffff))) { |
2261 return false; | 2262 return false; |
2262 } | 2263 } |
2263 | 2264 |
2264 unsigned lead_zero = CountLeadingZeros(value, width); | 2265 unsigned lead_zero = CountLeadingZeros(value, width); |
2265 unsigned lead_one = CountLeadingZeros(~value, width); | 2266 unsigned lead_one = CountLeadingZeros(~value, width); |
2266 unsigned trail_zero = CountTrailingZeros(value, width); | 2267 unsigned trail_zero = CountTrailingZeros(value, width); |
2267 unsigned trail_one = CountTrailingZeros(~value, width); | 2268 unsigned trail_one = CountTrailingZeros(~value, width); |
2268 unsigned set_bits = CountSetBits(value, width); | 2269 unsigned set_bits = CountSetBits(value, width); |
2269 | 2270 |
2270 // The fixed bits in the immediate s field. | 2271 // The fixed bits in the immediate s field. |
2271 // If width == 64 (X reg), start at 0xFFFFFF80. | 2272 // If width == 64 (X reg), start at 0xFFFFFF80. |
2272 // If width == 32 (W reg), start at 0xFFFFFFC0, as the iteration for 64-bit | 2273 // If width == 32 (W reg), start at 0xFFFFFFC0, as the iteration for 64-bit |
2273 // widths won't be executed. | 2274 // widths won't be executed. |
2274 int imm_s_fixed = (width == kXRegSize) ? -128 : -64; | 2275 int imm_s_fixed = (width == kXRegSizeInBits) ? -128 : -64; |
2275 int imm_s_mask = 0x3F; | 2276 int imm_s_mask = 0x3F; |
2276 | 2277 |
2277 for (;;) { | 2278 for (;;) { |
2278 // 2. If the value is two bits wide, it can be encoded. | 2279 // 2. If the value is two bits wide, it can be encoded. |
2279 if (width == 2) { | 2280 if (width == 2) { |
2280 *n = 0; | 2281 *n = 0; |
2281 *imm_s = 0x3C; | 2282 *imm_s = 0x3C; |
2282 *imm_r = (value & 3) - 1; | 2283 *imm_r = (value & 3) - 1; |
2283 return true; | 2284 return true; |
2284 } | 2285 } |
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2739 // code. | 2740 // code. |
2740 #ifdef ENABLE_DEBUGGER_SUPPORT | 2741 #ifdef ENABLE_DEBUGGER_SUPPORT |
2741 RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size)); | 2742 RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size)); |
2742 #endif | 2743 #endif |
2743 } | 2744 } |
2744 | 2745 |
2745 | 2746 |
2746 } } // namespace v8::internal | 2747 } } // namespace v8::internal |
2747 | 2748 |
2748 #endif // V8_TARGET_ARCH_A64 | 2749 #endif // V8_TARGET_ARCH_A64 |
OLD | NEW |