OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/base/division-by-constant.h" | 8 #include "src/base/division-by-constant.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 2135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2146 // convert it to 0. | 2146 // convert it to 0. |
2147 Fmov(dbl_scratch, 255); | 2147 Fmov(dbl_scratch, 255); |
2148 Fmin(dbl_scratch, dbl_scratch, input); | 2148 Fmin(dbl_scratch, dbl_scratch, input); |
2149 | 2149 |
2150 // Convert double to unsigned integer. Values less than zero become zero. | 2150 // Convert double to unsigned integer. Values less than zero become zero. |
2151 // Values greater than 255 have already been clamped to 255. | 2151 // Values greater than 255 have already been clamped to 255. |
2152 Fcvtnu(output, dbl_scratch); | 2152 Fcvtnu(output, dbl_scratch); |
2153 } | 2153 } |
2154 | 2154 |
2155 | 2155 |
2156 void MacroAssembler::CopyFieldsLoopPairsHelper(Register dst, | |
2157 Register src, | |
2158 unsigned count, | |
2159 Register scratch1, | |
2160 Register scratch2, | |
2161 Register scratch3, | |
2162 Register scratch4, | |
2163 Register scratch5) { | |
2164 // Untag src and dst into scratch registers. | |
2165 // Copy src->dst in a tight loop. | |
2166 DCHECK(!AreAliased(dst, src, | |
2167 scratch1, scratch2, scratch3, scratch4, scratch5)); | |
2168 DCHECK(count >= 2); | |
2169 | |
2170 const Register& remaining = scratch3; | |
2171 Mov(remaining, count / 2); | |
2172 | |
2173 const Register& dst_untagged = scratch1; | |
2174 const Register& src_untagged = scratch2; | |
2175 Sub(dst_untagged, dst, kHeapObjectTag); | |
2176 Sub(src_untagged, src, kHeapObjectTag); | |
2177 | |
2178 // Copy fields in pairs. | |
2179 Label loop; | |
2180 Bind(&loop); | |
2181 Ldp(scratch4, scratch5, | |
2182 MemOperand(src_untagged, kXRegSize* 2, PostIndex)); | |
2183 Stp(scratch4, scratch5, | |
2184 MemOperand(dst_untagged, kXRegSize* 2, PostIndex)); | |
2185 Sub(remaining, remaining, 1); | |
2186 Cbnz(remaining, &loop); | |
2187 | |
2188 // Handle the leftovers. | |
2189 if (count & 1) { | |
2190 Ldr(scratch4, MemOperand(src_untagged)); | |
2191 Str(scratch4, MemOperand(dst_untagged)); | |
2192 } | |
2193 } | |
2194 | |
2195 | |
2196 void MacroAssembler::CopyFieldsUnrolledPairsHelper(Register dst, | |
2197 Register src, | |
2198 unsigned count, | |
2199 Register scratch1, | |
2200 Register scratch2, | |
2201 Register scratch3, | |
2202 Register scratch4) { | |
2203 // Untag src and dst into scratch registers. | |
2204 // Copy src->dst in an unrolled loop. | |
2205 DCHECK(!AreAliased(dst, src, scratch1, scratch2, scratch3, scratch4)); | |
2206 | |
2207 const Register& dst_untagged = scratch1; | |
2208 const Register& src_untagged = scratch2; | |
2209 sub(dst_untagged, dst, kHeapObjectTag); | |
2210 sub(src_untagged, src, kHeapObjectTag); | |
2211 | |
2212 // Copy fields in pairs. | |
2213 for (unsigned i = 0; i < count / 2; i++) { | |
2214 Ldp(scratch3, scratch4, MemOperand(src_untagged, kXRegSize * 2, PostIndex)); | |
2215 Stp(scratch3, scratch4, MemOperand(dst_untagged, kXRegSize * 2, PostIndex)); | |
2216 } | |
2217 | |
2218 // Handle the leftovers. | |
2219 if (count & 1) { | |
2220 Ldr(scratch3, MemOperand(src_untagged)); | |
2221 Str(scratch3, MemOperand(dst_untagged)); | |
2222 } | |
2223 } | |
2224 | |
2225 | |
2226 void MacroAssembler::CopyFieldsUnrolledHelper(Register dst, | |
2227 Register src, | |
2228 unsigned count, | |
2229 Register scratch1, | |
2230 Register scratch2, | |
2231 Register scratch3) { | |
2232 // Untag src and dst into scratch registers. | |
2233 // Copy src->dst in an unrolled loop. | |
2234 DCHECK(!AreAliased(dst, src, scratch1, scratch2, scratch3)); | |
2235 | |
2236 const Register& dst_untagged = scratch1; | |
2237 const Register& src_untagged = scratch2; | |
2238 Sub(dst_untagged, dst, kHeapObjectTag); | |
2239 Sub(src_untagged, src, kHeapObjectTag); | |
2240 | |
2241 // Copy fields one by one. | |
2242 for (unsigned i = 0; i < count; i++) { | |
2243 Ldr(scratch3, MemOperand(src_untagged, kXRegSize, PostIndex)); | |
2244 Str(scratch3, MemOperand(dst_untagged, kXRegSize, PostIndex)); | |
2245 } | |
2246 } | |
2247 | |
2248 | |
2249 void MacroAssembler::CopyFields(Register dst, Register src, CPURegList temps, | |
2250 unsigned count) { | |
2251 // One of two methods is used: | |
2252 // | |
2253 // For high 'count' values where many scratch registers are available: | |
2254 // Untag src and dst into scratch registers. | |
2255 // Copy src->dst in a tight loop. | |
2256 // | |
2257 // For low 'count' values or where few scratch registers are available: | |
2258 // Untag src and dst into scratch registers. | |
2259 // Copy src->dst in an unrolled loop. | |
2260 // | |
2261 // In both cases, fields are copied in pairs if possible, and left-overs are | |
2262 // handled separately. | |
2263 DCHECK(!AreAliased(dst, src)); | |
2264 DCHECK(!temps.IncludesAliasOf(dst)); | |
2265 DCHECK(!temps.IncludesAliasOf(src)); | |
2266 DCHECK(!temps.IncludesAliasOf(xzr)); | |
2267 | |
2268 if (emit_debug_code()) { | |
2269 Cmp(dst, src); | |
2270 Check(ne, kTheSourceAndDestinationAreTheSame); | |
2271 } | |
2272 | |
2273 // The value of 'count' at which a loop will be generated (if there are | |
2274 // enough scratch registers). | |
2275 static const unsigned kLoopThreshold = 8; | |
2276 | |
2277 UseScratchRegisterScope masm_temps(this); | |
2278 if ((temps.Count() >= 3) && (count >= kLoopThreshold)) { | |
2279 CopyFieldsLoopPairsHelper(dst, src, count, | |
2280 Register(temps.PopLowestIndex()), | |
2281 Register(temps.PopLowestIndex()), | |
2282 Register(temps.PopLowestIndex()), | |
2283 masm_temps.AcquireX(), | |
2284 masm_temps.AcquireX()); | |
2285 } else if (temps.Count() >= 2) { | |
2286 CopyFieldsUnrolledPairsHelper(dst, src, count, | |
2287 Register(temps.PopLowestIndex()), | |
2288 Register(temps.PopLowestIndex()), | |
2289 masm_temps.AcquireX(), | |
2290 masm_temps.AcquireX()); | |
2291 } else if (temps.Count() == 1) { | |
2292 CopyFieldsUnrolledHelper(dst, src, count, | |
2293 Register(temps.PopLowestIndex()), | |
2294 masm_temps.AcquireX(), | |
2295 masm_temps.AcquireX()); | |
2296 } else { | |
2297 UNREACHABLE(); | |
2298 } | |
2299 } | |
2300 | |
2301 | |
2302 void MacroAssembler::CopyBytes(Register dst, | 2156 void MacroAssembler::CopyBytes(Register dst, |
2303 Register src, | 2157 Register src, |
2304 Register length, | 2158 Register length, |
2305 Register scratch, | 2159 Register scratch, |
2306 CopyHint hint) { | 2160 CopyHint hint) { |
2307 UseScratchRegisterScope temps(this); | 2161 UseScratchRegisterScope temps(this); |
2308 Register tmp1 = temps.AcquireX(); | 2162 Register tmp1 = temps.AcquireX(); |
2309 Register tmp2 = temps.AcquireX(); | 2163 Register tmp2 = temps.AcquireX(); |
2310 DCHECK(!AreAliased(src, dst, length, scratch, tmp1, tmp2)); | 2164 DCHECK(!AreAliased(src, dst, length, scratch, tmp1, tmp2)); |
2311 DCHECK(!AreAliased(src, dst, csp)); | 2165 DCHECK(!AreAliased(src, dst, csp)); |
(...skipping 2762 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5074 } | 4928 } |
5075 | 4929 |
5076 | 4930 |
5077 #undef __ | 4931 #undef __ |
5078 | 4932 |
5079 | 4933 |
5080 } // namespace internal | 4934 } // namespace internal |
5081 } // namespace v8 | 4935 } // namespace v8 |
5082 | 4936 |
5083 #endif // V8_TARGET_ARCH_ARM64 | 4937 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |