OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 283 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
284 locs->set_out(0, Location::RequiresFpuRegister()); | 284 locs->set_out(0, Location::RequiresFpuRegister()); |
285 locs->set_temp(0, Location::RequiresRegister()); | 285 locs->set_temp(0, Location::RequiresRegister()); |
286 return locs; | 286 return locs; |
287 } | 287 } |
288 | 288 |
289 | 289 |
290 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 290 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
291 // The register allocator drops constant definitions that have no uses. | 291 // The register allocator drops constant definitions that have no uses. |
292 if (!locs()->out(0).IsInvalid()) { | 292 if (!locs()->out(0).IsInvalid()) { |
293 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { | 293 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0) && |
| 294 TargetCPUFeatures::neon_supported()) { |
294 const QRegister dst = locs()->out(0).fpu_reg(); | 295 const QRegister dst = locs()->out(0).fpu_reg(); |
295 __ veorq(dst, dst, dst); | 296 __ veorq(dst, dst, dst); |
296 } else { | 297 } else { |
297 const DRegister dst = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 298 const DRegister dst = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
298 const Register temp = locs()->temp(0).reg(); | 299 const Register temp = locs()->temp(0).reg(); |
299 __ LoadDImmediate(dst, Double::Cast(value()).value(), temp); | 300 __ LoadDImmediate(dst, Double::Cast(value()).value(), temp); |
300 } | 301 } |
301 } | 302 } |
302 } | 303 } |
303 | 304 |
(...skipping 1765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2069 __ TryAllocate(compiler->double_class(), | 2070 __ TryAllocate(compiler->double_class(), |
2070 slow_path->entry_label(), | 2071 slow_path->entry_label(), |
2071 temp, | 2072 temp, |
2072 temp2); | 2073 temp2); |
2073 __ Bind(slow_path->exit_label()); | 2074 __ Bind(slow_path->exit_label()); |
2074 __ MoveRegister(temp2, temp); | 2075 __ MoveRegister(temp2, temp); |
2075 __ StoreIntoObject(instance_reg, | 2076 __ StoreIntoObject(instance_reg, |
2076 FieldAddress(instance_reg, offset_in_bytes_), | 2077 FieldAddress(instance_reg, offset_in_bytes_), |
2077 temp2); | 2078 temp2); |
2078 __ Bind(©_double); | 2079 __ Bind(©_double); |
2079 __ LoadDFromOffset(fpu_temp, | 2080 __ CopyDoubleField(temp, value_reg, TMP, temp2, fpu_temp); |
2080 value_reg, | |
2081 Double::value_offset() - kHeapObjectTag); | |
2082 __ StoreDToOffset(fpu_temp, | |
2083 temp, | |
2084 Double::value_offset() - kHeapObjectTag); | |
2085 __ b(&skip_store); | 2081 __ b(&skip_store); |
2086 } | 2082 } |
2087 | 2083 |
2088 { | 2084 { |
2089 __ Bind(&store_float32x4); | 2085 __ Bind(&store_float32x4); |
2090 Label copy_float32x4; | 2086 Label copy_float32x4; |
2091 StoreInstanceFieldSlowPath* slow_path = | 2087 StoreInstanceFieldSlowPath* slow_path = |
2092 new StoreInstanceFieldSlowPath(this, compiler->float32x4_class()); | 2088 new StoreInstanceFieldSlowPath(this, compiler->float32x4_class()); |
2093 compiler->AddSlowPathCode(slow_path); | 2089 compiler->AddSlowPathCode(slow_path); |
2094 | 2090 |
2095 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes_)); | 2091 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes_)); |
2096 __ CompareImmediate(temp, | 2092 __ CompareImmediate(temp, |
2097 reinterpret_cast<intptr_t>(Object::null())); | 2093 reinterpret_cast<intptr_t>(Object::null())); |
2098 __ b(©_float32x4, NE); | 2094 __ b(©_float32x4, NE); |
2099 | 2095 |
2100 __ TryAllocate(compiler->float32x4_class(), | 2096 __ TryAllocate(compiler->float32x4_class(), |
2101 slow_path->entry_label(), | 2097 slow_path->entry_label(), |
2102 temp, | 2098 temp, |
2103 temp2); | 2099 temp2); |
2104 __ Bind(slow_path->exit_label()); | 2100 __ Bind(slow_path->exit_label()); |
2105 __ MoveRegister(temp2, temp); | 2101 __ MoveRegister(temp2, temp); |
2106 __ StoreIntoObject(instance_reg, | 2102 __ StoreIntoObject(instance_reg, |
2107 FieldAddress(instance_reg, offset_in_bytes_), | 2103 FieldAddress(instance_reg, offset_in_bytes_), |
2108 temp2); | 2104 temp2); |
2109 __ Bind(©_float32x4); | 2105 __ Bind(©_float32x4); |
2110 __ LoadMultipleDFromOffset(fpu_temp, 2, value_reg, | 2106 __ CopyFloat32x4Field(temp, value_reg, TMP, temp2, fpu_temp); |
2111 Float32x4::value_offset() - kHeapObjectTag); | |
2112 __ StoreMultipleDToOffset(fpu_temp, 2, temp, | |
2113 Float32x4::value_offset() - kHeapObjectTag); | |
2114 __ b(&skip_store); | 2107 __ b(&skip_store); |
2115 } | 2108 } |
2116 | 2109 |
2117 { | 2110 { |
2118 __ Bind(&store_float64x2); | 2111 __ Bind(&store_float64x2); |
2119 Label copy_float64x2; | 2112 Label copy_float64x2; |
2120 StoreInstanceFieldSlowPath* slow_path = | 2113 StoreInstanceFieldSlowPath* slow_path = |
2121 new StoreInstanceFieldSlowPath(this, compiler->float64x2_class()); | 2114 new StoreInstanceFieldSlowPath(this, compiler->float64x2_class()); |
2122 compiler->AddSlowPathCode(slow_path); | 2115 compiler->AddSlowPathCode(slow_path); |
2123 | 2116 |
2124 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes_)); | 2117 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes_)); |
2125 __ CompareImmediate(temp, | 2118 __ CompareImmediate(temp, |
2126 reinterpret_cast<intptr_t>(Object::null())); | 2119 reinterpret_cast<intptr_t>(Object::null())); |
2127 __ b(©_float64x2, NE); | 2120 __ b(©_float64x2, NE); |
2128 | 2121 |
2129 __ TryAllocate(compiler->float64x2_class(), | 2122 __ TryAllocate(compiler->float64x2_class(), |
2130 slow_path->entry_label(), | 2123 slow_path->entry_label(), |
2131 temp, | 2124 temp, |
2132 temp2); | 2125 temp2); |
2133 __ Bind(slow_path->exit_label()); | 2126 __ Bind(slow_path->exit_label()); |
2134 __ MoveRegister(temp2, temp); | 2127 __ MoveRegister(temp2, temp); |
2135 __ StoreIntoObject(instance_reg, | 2128 __ StoreIntoObject(instance_reg, |
2136 FieldAddress(instance_reg, offset_in_bytes_), | 2129 FieldAddress(instance_reg, offset_in_bytes_), |
2137 temp2); | 2130 temp2); |
2138 __ Bind(©_float64x2); | 2131 __ Bind(©_float64x2); |
2139 __ LoadMultipleDFromOffset(fpu_temp, 2, value_reg, | 2132 __ CopyFloat64x2Field(temp, value_reg, TMP, temp2, fpu_temp); |
2140 Float64x2::value_offset() - kHeapObjectTag); | |
2141 __ StoreMultipleDToOffset(fpu_temp, 2, temp, | |
2142 Float64x2::value_offset() - kHeapObjectTag); | |
2143 __ b(&skip_store); | 2133 __ b(&skip_store); |
2144 } | 2134 } |
2145 | 2135 |
2146 __ Bind(&store_pointer); | 2136 __ Bind(&store_pointer); |
2147 } | 2137 } |
2148 | 2138 |
2149 if (ShouldEmitStoreBarrier()) { | 2139 if (ShouldEmitStoreBarrier()) { |
2150 Register value_reg = locs()->in(1).reg(); | 2140 Register value_reg = locs()->in(1).reg(); |
2151 __ StoreIntoObject(instance_reg, | 2141 __ StoreIntoObject(instance_reg, |
2152 FieldAddress(instance_reg, offset_in_bytes_), | 2142 FieldAddress(instance_reg, offset_in_bytes_), |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2474 : LocationSummary::kCallOnSlowPath); | 2464 : LocationSummary::kCallOnSlowPath); |
2475 | 2465 |
2476 locs->set_in(0, Location::RequiresRegister()); | 2466 locs->set_in(0, Location::RequiresRegister()); |
2477 | 2467 |
2478 if (IsUnboxedLoad() && opt) { | 2468 if (IsUnboxedLoad() && opt) { |
2479 locs->AddTemp(Location::RequiresRegister()); | 2469 locs->AddTemp(Location::RequiresRegister()); |
2480 } else if (IsPotentialUnboxedLoad()) { | 2470 } else if (IsPotentialUnboxedLoad()) { |
2481 locs->AddTemp(opt ? Location::RequiresFpuRegister() | 2471 locs->AddTemp(opt ? Location::RequiresFpuRegister() |
2482 : Location::FpuRegisterLocation(Q1)); | 2472 : Location::FpuRegisterLocation(Q1)); |
2483 locs->AddTemp(Location::RequiresRegister()); | 2473 locs->AddTemp(Location::RequiresRegister()); |
| 2474 locs->AddTemp(Location::RequiresRegister()); |
2484 } | 2475 } |
2485 locs->set_out(0, Location::RequiresRegister()); | 2476 locs->set_out(0, Location::RequiresRegister()); |
2486 return locs; | 2477 return locs; |
2487 } | 2478 } |
2488 | 2479 |
2489 | 2480 |
2490 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2481 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2491 Register instance_reg = locs()->in(0).reg(); | 2482 const Register instance_reg = locs()->in(0).reg(); |
2492 if (IsUnboxedLoad() && compiler->is_optimizing()) { | 2483 if (IsUnboxedLoad() && compiler->is_optimizing()) { |
2493 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 2484 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
2494 const Register temp = locs()->temp(0).reg(); | 2485 const Register temp = locs()->temp(0).reg(); |
2495 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2486 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
2496 const intptr_t cid = field()->UnboxedFieldCid(); | 2487 const intptr_t cid = field()->UnboxedFieldCid(); |
2497 switch (cid) { | 2488 switch (cid) { |
2498 case kDoubleCid: | 2489 case kDoubleCid: |
2499 __ Comment("UnboxedDoubleLoadFieldInstr"); | 2490 __ Comment("UnboxedDoubleLoadFieldInstr"); |
2500 __ LoadDFromOffset(result, temp, | 2491 __ LoadDFromOffset(result, temp, |
2501 Double::value_offset() - kHeapObjectTag); | 2492 Double::value_offset() - kHeapObjectTag); |
(...skipping 10 matching lines...) Expand all Loading... |
2512 break; | 2503 break; |
2513 default: | 2504 default: |
2514 UNREACHABLE(); | 2505 UNREACHABLE(); |
2515 } | 2506 } |
2516 return; | 2507 return; |
2517 } | 2508 } |
2518 | 2509 |
2519 Label done; | 2510 Label done; |
2520 Register result_reg = locs()->out(0).reg(); | 2511 Register result_reg = locs()->out(0).reg(); |
2521 if (IsPotentialUnboxedLoad()) { | 2512 if (IsPotentialUnboxedLoad()) { |
| 2513 const DRegister value = EvenDRegisterOf(locs()->temp(0).fpu_reg()); |
2522 const Register temp = locs()->temp(1).reg(); | 2514 const Register temp = locs()->temp(1).reg(); |
2523 const DRegister value = EvenDRegisterOf(locs()->temp(0).fpu_reg()); | 2515 const Register temp2 = locs()->temp(2).reg(); |
2524 | 2516 |
2525 Label load_pointer; | 2517 Label load_pointer; |
2526 Label load_double; | 2518 Label load_double; |
2527 Label load_float32x4; | 2519 Label load_float32x4; |
2528 Label load_float64x2; | 2520 Label load_float64x2; |
2529 | 2521 |
2530 __ LoadObject(result_reg, Field::ZoneHandle(field()->raw())); | 2522 __ LoadObject(result_reg, Field::ZoneHandle(field()->raw())); |
2531 | 2523 |
2532 FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset()); | 2524 FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset()); |
2533 FieldAddress field_nullability_operand(result_reg, | 2525 FieldAddress field_nullability_operand(result_reg, |
(...skipping 26 matching lines...) Expand all Loading... |
2560 __ Bind(&load_double); | 2552 __ Bind(&load_double); |
2561 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); | 2553 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); |
2562 compiler->AddSlowPathCode(slow_path); | 2554 compiler->AddSlowPathCode(slow_path); |
2563 | 2555 |
2564 __ TryAllocate(compiler->double_class(), | 2556 __ TryAllocate(compiler->double_class(), |
2565 slow_path->entry_label(), | 2557 slow_path->entry_label(), |
2566 result_reg, | 2558 result_reg, |
2567 temp); | 2559 temp); |
2568 __ Bind(slow_path->exit_label()); | 2560 __ Bind(slow_path->exit_label()); |
2569 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2561 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
2570 __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag); | 2562 __ CopyDoubleField(result_reg, temp, TMP, temp2, value); |
2571 __ StoreDToOffset(value, | |
2572 result_reg, | |
2573 Double::value_offset() - kHeapObjectTag); | |
2574 __ b(&done); | 2563 __ b(&done); |
2575 } | 2564 } |
2576 | 2565 |
2577 { | 2566 { |
2578 __ Bind(&load_float32x4); | 2567 __ Bind(&load_float32x4); |
2579 BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this); | 2568 BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this); |
2580 compiler->AddSlowPathCode(slow_path); | 2569 compiler->AddSlowPathCode(slow_path); |
2581 | 2570 |
2582 __ TryAllocate(compiler->float32x4_class(), | 2571 __ TryAllocate(compiler->float32x4_class(), |
2583 slow_path->entry_label(), | 2572 slow_path->entry_label(), |
2584 result_reg, | 2573 result_reg, |
2585 temp); | 2574 temp); |
2586 __ Bind(slow_path->exit_label()); | 2575 __ Bind(slow_path->exit_label()); |
2587 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2576 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
2588 __ LoadMultipleDFromOffset(value, 2, temp, | 2577 __ CopyFloat32x4Field(result_reg, temp, TMP, temp2, value); |
2589 Float32x4::value_offset() - kHeapObjectTag); | |
2590 __ StoreMultipleDToOffset(value, 2, result_reg, | |
2591 Float32x4::value_offset() - kHeapObjectTag); | |
2592 __ b(&done); | 2578 __ b(&done); |
2593 } | 2579 } |
2594 | 2580 |
2595 { | 2581 { |
2596 __ Bind(&load_float64x2); | 2582 __ Bind(&load_float64x2); |
2597 BoxFloat64x2SlowPath* slow_path = new BoxFloat64x2SlowPath(this); | 2583 BoxFloat64x2SlowPath* slow_path = new BoxFloat64x2SlowPath(this); |
2598 compiler->AddSlowPathCode(slow_path); | 2584 compiler->AddSlowPathCode(slow_path); |
2599 | 2585 |
2600 __ TryAllocate(compiler->float64x2_class(), | 2586 __ TryAllocate(compiler->float64x2_class(), |
2601 slow_path->entry_label(), | 2587 slow_path->entry_label(), |
2602 result_reg, | 2588 result_reg, |
2603 temp); | 2589 temp); |
2604 __ Bind(slow_path->exit_label()); | 2590 __ Bind(slow_path->exit_label()); |
2605 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2591 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
2606 __ LoadMultipleDFromOffset(value, 2, temp, | 2592 __ CopyFloat64x2Field(result_reg, temp, TMP, temp2, value); |
2607 Float64x2::value_offset() - kHeapObjectTag); | |
2608 __ StoreMultipleDToOffset(value, 2, result_reg, | |
2609 Float64x2::value_offset() - kHeapObjectTag); | |
2610 __ b(&done); | 2593 __ b(&done); |
2611 } | 2594 } |
2612 | 2595 |
2613 __ Bind(&load_pointer); | 2596 __ Bind(&load_pointer); |
2614 } | 2597 } |
2615 __ LoadFromOffset(kWord, result_reg, | 2598 __ LoadFromOffset(kWord, result_reg, |
2616 instance_reg, offset_in_bytes() - kHeapObjectTag); | 2599 instance_reg, offset_in_bytes() - kHeapObjectTag); |
2617 __ Bind(&done); | 2600 __ Bind(&done); |
2618 } | 2601 } |
2619 | 2602 |
(...skipping 3662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6282 compiler->GenerateCall(token_pos(), | 6265 compiler->GenerateCall(token_pos(), |
6283 &label, | 6266 &label, |
6284 PcDescriptors::kOther, | 6267 PcDescriptors::kOther, |
6285 locs()); | 6268 locs()); |
6286 __ Drop(ArgumentCount()); // Discard arguments. | 6269 __ Drop(ArgumentCount()); // Discard arguments. |
6287 } | 6270 } |
6288 | 6271 |
6289 } // namespace dart | 6272 } // namespace dart |
6290 | 6273 |
6291 #endif // defined TARGET_ARCH_ARM | 6274 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |