Chromium Code Reviews| 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" // NOLINT | 5 #include "vm/globals.h" // NOLINT |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
| 10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
| (...skipping 1569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1580 if (object.IsSmi()) { | 1580 if (object.IsSmi()) { |
| 1581 LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()), cond); | 1581 LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()), cond); |
| 1582 } else if (object.InVMHeap() || !allow_constant_pool()) { | 1582 } else if (object.InVMHeap() || !allow_constant_pool()) { |
| 1583 // Make sure that class CallPattern is able to decode this load immediate. | 1583 // Make sure that class CallPattern is able to decode this load immediate. |
| 1584 const int32_t object_raw = reinterpret_cast<int32_t>(object.raw()); | 1584 const int32_t object_raw = reinterpret_cast<int32_t>(object.raw()); |
| 1585 LoadImmediate(rd, object_raw, cond); | 1585 LoadImmediate(rd, object_raw, cond); |
| 1586 } else { | 1586 } else { |
| 1587 // Make sure that class CallPattern is able to decode this load from the | 1587 // Make sure that class CallPattern is able to decode this load from the |
| 1588 // object pool. | 1588 // object pool. |
| 1589 const int32_t offset = | 1589 const int32_t offset = |
| 1590 Array::data_offset() + 4*AddObject(object) - kHeapObjectTag; | 1590 Array::element_offset(object_pool_.FindObject(object, kNotPatchable)); |
| 1591 LoadWordFromPoolOffset(rd, offset, cond); | 1591 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, cond); |
| 1592 } | 1592 } |
| 1593 } | 1593 } |
| 1594 | 1594 |
| 1595 | 1595 |
| 1596 void Assembler::PushObject(const Object& object) { | 1596 void Assembler::PushObject(const Object& object) { |
| 1597 LoadObject(IP, object); | 1597 LoadObject(IP, object); |
| 1598 Push(IP); | 1598 Push(IP); |
| 1599 } | 1599 } |
| 1600 | 1600 |
| 1601 | 1601 |
| (...skipping 1064 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2666 blx(LR); // Use blx instruction so that the return branch prediction works. | 2666 blx(LR); // Use blx instruction so that the return branch prediction works. |
| 2667 } | 2667 } |
| 2668 | 2668 |
| 2669 | 2669 |
| 2670 void Assembler::BranchLinkPatchable(const ExternalLabel* label) { | 2670 void Assembler::BranchLinkPatchable(const ExternalLabel* label) { |
| 2671 // Make sure that class CallPattern is able to patch the label referred | 2671 // Make sure that class CallPattern is able to patch the label referred |
| 2672 // to by this code sequence. | 2672 // to by this code sequence. |
| 2673 // For added code robustness, use 'blx lr' in a patchable sequence and | 2673 // For added code robustness, use 'blx lr' in a patchable sequence and |
| 2674 // use 'blx ip' in a non-patchable sequence (see other BranchLink flavors). | 2674 // use 'blx ip' in a non-patchable sequence (see other BranchLink flavors). |
| 2675 const int32_t offset = | 2675 const int32_t offset = |
| 2676 Array::data_offset() + 4*AddExternalLabel(label) - kHeapObjectTag; | 2676 Array::element_offset(object_pool_.FindExternalLabel(label, kPatchable)); |
| 2677 LoadWordFromPoolOffset(LR, offset); | 2677 LoadWordFromPoolOffset(LR, offset - kHeapObjectTag); |
| 2678 blx(LR); // Use blx instruction so that the return branch prediction works. | 2678 blx(LR); // Use blx instruction so that the return branch prediction works. |
| 2679 } | 2679 } |
| 2680 | 2680 |
| 2681 | 2681 |
| 2682 void Assembler::BranchLinkOffset(Register base, int32_t offset) { | 2682 void Assembler::BranchLinkOffset(Register base, int32_t offset) { |
| 2683 ASSERT(base != PC); | 2683 ASSERT(base != PC); |
| 2684 ASSERT(base != IP); | 2684 ASSERT(base != IP); |
| 2685 LoadFromOffset(kWord, IP, base, offset); | 2685 LoadFromOffset(kWord, IP, base, offset); |
| 2686 blx(IP); // Use blx instruction so that the return branch prediction works. | 2686 blx(IP); // Use blx instruction so that the return branch prediction works. |
| 2687 } | 2687 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 2703 } else { | 2703 } else { |
| 2704 ASSERT(version == ARMv7); | 2704 ASSERT(version == ARMv7); |
| 2705 const uint16_t value_low = Utils::Low16Bits(value); | 2705 const uint16_t value_low = Utils::Low16Bits(value); |
| 2706 const uint16_t value_high = Utils::High16Bits(value); | 2706 const uint16_t value_high = Utils::High16Bits(value); |
| 2707 movw(rd, value_low, cond); | 2707 movw(rd, value_low, cond); |
| 2708 movt(rd, value_high, cond); | 2708 movt(rd, value_high, cond); |
| 2709 } | 2709 } |
| 2710 } | 2710 } |
| 2711 | 2711 |
| 2712 | 2712 |
| 2713 void Assembler::LoadDecodableImmediate( | |
| 2714 Register rd, int32_t value, Condition cond) { | |
| 2715 const ARMVersion version = TargetCPUFeatures::arm_version(); | |
| 2716 if ((version == ARMv5TE) || (version == ARMv6)) { | |
| 2717 LoadPatchableImmediate(rd, value, cond); | |
| 2718 } else { | |
| 2719 ASSERT(version == ARMv7); | |
| 2720 movw(rd, Utils::Low16Bits(value), cond); | |
| 2721 const uint16_t value_high = Utils::High16Bits(value); | |
| 2722 if (value_high != 0) { | |
| 2723 movt(rd, value_high, cond); | |
| 2724 } | |
| 2725 } | |
| 2726 } | |
| 2727 | |
| 2728 | |
| 2729 void Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) { | 2713 void Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) { |
| 2730 Operand o; | 2714 Operand o; |
| 2731 if (Operand::CanHold(value, &o)) { | 2715 if (Operand::CanHold(value, &o)) { |
| 2732 mov(rd, o, cond); | 2716 mov(rd, o, cond); |
| 2733 } else if (Operand::CanHold(~value, &o)) { | 2717 } else if (Operand::CanHold(~value, &o)) { |
| 2734 mvn(rd, o, cond); | 2718 mvn(rd, o, cond); |
| 2735 } else { | 2719 } else { |
| 2736 LoadDecodableImmediate(rd, value, cond); | 2720 LoadPatchableImmediate(rd, value, cond); |
|
zra
2015/02/09 15:30:30
What is the reason for this change? Does this imme
Florian Schneider
2015/02/09 15:49:41
No, I missed the case for <16 bit values. I'll und
| |
| 2737 } | 2721 } |
| 2738 } | 2722 } |
| 2739 | 2723 |
| 2740 | 2724 |
| 2741 void Assembler::LoadSImmediate(SRegister sd, float value, Condition cond) { | 2725 void Assembler::LoadSImmediate(SRegister sd, float value, Condition cond) { |
| 2742 if (!vmovs(sd, value, cond)) { | 2726 if (!vmovs(sd, value, cond)) { |
| 2743 const DRegister dd = static_cast<DRegister>(sd >> 1); | 2727 const DRegister dd = static_cast<DRegister>(sd >> 1); |
| 2744 const int index = sd & 1; | 2728 const int index = sd & 1; |
| 2745 LoadImmediate(IP, bit_cast<int32_t, float>(value), cond); | 2729 LoadImmediate(IP, bit_cast<int32_t, float>(value), cond); |
| 2746 vmovdr(dd, index, IP, cond); | 2730 vmovdr(dd, index, IP, cond); |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3012 sub(rd, rn, o, cond); | 2996 sub(rd, rn, o, cond); |
| 3013 } else { | 2997 } else { |
| 3014 ASSERT(rn != IP); | 2998 ASSERT(rn != IP); |
| 3015 if (Operand::CanHold(~value, &o)) { | 2999 if (Operand::CanHold(~value, &o)) { |
| 3016 mvn(IP, o, cond); | 3000 mvn(IP, o, cond); |
| 3017 add(rd, rn, Operand(IP), cond); | 3001 add(rd, rn, Operand(IP), cond); |
| 3018 } else if (Operand::CanHold(~(-value), &o)) { | 3002 } else if (Operand::CanHold(~(-value), &o)) { |
| 3019 mvn(IP, o, cond); | 3003 mvn(IP, o, cond); |
| 3020 sub(rd, rn, Operand(IP), cond); | 3004 sub(rd, rn, Operand(IP), cond); |
| 3021 } else { | 3005 } else { |
| 3022 LoadDecodableImmediate(IP, value, cond); | 3006 LoadPatchableImmediate(IP, value, cond); |
| 3023 add(rd, rn, Operand(IP), cond); | 3007 add(rd, rn, Operand(IP), cond); |
| 3024 } | 3008 } |
| 3025 } | 3009 } |
| 3026 } | 3010 } |
| 3027 | 3011 |
| 3028 | 3012 |
| 3029 void Assembler::AddImmediateSetFlags(Register rd, Register rn, int32_t value, | 3013 void Assembler::AddImmediateSetFlags(Register rd, Register rn, int32_t value, |
| 3030 Condition cond) { | 3014 Condition cond) { |
| 3031 Operand o; | 3015 Operand o; |
| 3032 if (Operand::CanHold(value, &o)) { | 3016 if (Operand::CanHold(value, &o)) { |
| 3033 // Handles value == kMinInt32. | 3017 // Handles value == kMinInt32. |
| 3034 adds(rd, rn, o, cond); | 3018 adds(rd, rn, o, cond); |
| 3035 } else if (Operand::CanHold(-value, &o)) { | 3019 } else if (Operand::CanHold(-value, &o)) { |
| 3036 ASSERT(value != kMinInt32); // Would cause erroneous overflow detection. | 3020 ASSERT(value != kMinInt32); // Would cause erroneous overflow detection. |
| 3037 subs(rd, rn, o, cond); | 3021 subs(rd, rn, o, cond); |
| 3038 } else { | 3022 } else { |
| 3039 ASSERT(rn != IP); | 3023 ASSERT(rn != IP); |
| 3040 if (Operand::CanHold(~value, &o)) { | 3024 if (Operand::CanHold(~value, &o)) { |
| 3041 mvn(IP, o, cond); | 3025 mvn(IP, o, cond); |
| 3042 adds(rd, rn, Operand(IP), cond); | 3026 adds(rd, rn, Operand(IP), cond); |
| 3043 } else if (Operand::CanHold(~(-value), &o)) { | 3027 } else if (Operand::CanHold(~(-value), &o)) { |
| 3044 ASSERT(value != kMinInt32); // Would cause erroneous overflow detection. | 3028 ASSERT(value != kMinInt32); // Would cause erroneous overflow detection. |
| 3045 mvn(IP, o, cond); | 3029 mvn(IP, o, cond); |
| 3046 subs(rd, rn, Operand(IP), cond); | 3030 subs(rd, rn, Operand(IP), cond); |
| 3047 } else { | 3031 } else { |
| 3048 LoadDecodableImmediate(IP, value, cond); | 3032 LoadPatchableImmediate(IP, value, cond); |
| 3049 adds(rd, rn, Operand(IP), cond); | 3033 adds(rd, rn, Operand(IP), cond); |
| 3050 } | 3034 } |
| 3051 } | 3035 } |
| 3052 } | 3036 } |
| 3053 | 3037 |
| 3054 | 3038 |
| 3055 void Assembler::SubImmediateSetFlags(Register rd, Register rn, int32_t value, | 3039 void Assembler::SubImmediateSetFlags(Register rd, Register rn, int32_t value, |
| 3056 Condition cond) { | 3040 Condition cond) { |
| 3057 Operand o; | 3041 Operand o; |
| 3058 if (Operand::CanHold(value, &o)) { | 3042 if (Operand::CanHold(value, &o)) { |
| 3059 // Handles value == kMinInt32. | 3043 // Handles value == kMinInt32. |
| 3060 subs(rd, rn, o, cond); | 3044 subs(rd, rn, o, cond); |
| 3061 } else if (Operand::CanHold(-value, &o)) { | 3045 } else if (Operand::CanHold(-value, &o)) { |
| 3062 ASSERT(value != kMinInt32); // Would cause erroneous overflow detection. | 3046 ASSERT(value != kMinInt32); // Would cause erroneous overflow detection. |
| 3063 adds(rd, rn, o, cond); | 3047 adds(rd, rn, o, cond); |
| 3064 } else { | 3048 } else { |
| 3065 ASSERT(rn != IP); | 3049 ASSERT(rn != IP); |
| 3066 if (Operand::CanHold(~value, &o)) { | 3050 if (Operand::CanHold(~value, &o)) { |
| 3067 mvn(IP, o, cond); | 3051 mvn(IP, o, cond); |
| 3068 subs(rd, rn, Operand(IP), cond); | 3052 subs(rd, rn, Operand(IP), cond); |
| 3069 } else if (Operand::CanHold(~(-value), &o)) { | 3053 } else if (Operand::CanHold(~(-value), &o)) { |
| 3070 ASSERT(value != kMinInt32); // Would cause erroneous overflow detection. | 3054 ASSERT(value != kMinInt32); // Would cause erroneous overflow detection. |
| 3071 mvn(IP, o, cond); | 3055 mvn(IP, o, cond); |
| 3072 adds(rd, rn, Operand(IP), cond); | 3056 adds(rd, rn, Operand(IP), cond); |
| 3073 } else { | 3057 } else { |
| 3074 LoadDecodableImmediate(IP, value, cond); | 3058 LoadPatchableImmediate(IP, value, cond); |
| 3075 subs(rd, rn, Operand(IP), cond); | 3059 subs(rd, rn, Operand(IP), cond); |
| 3076 } | 3060 } |
| 3077 } | 3061 } |
| 3078 } | 3062 } |
| 3079 | 3063 |
| 3080 | 3064 |
| 3081 void Assembler::AndImmediate(Register rd, Register rs, int32_t imm, | 3065 void Assembler::AndImmediate(Register rd, Register rs, int32_t imm, |
| 3082 Condition cond) { | 3066 Condition cond) { |
| 3083 Operand o; | 3067 Operand o; |
| 3084 if (Operand::CanHold(imm, &o)) { | 3068 if (Operand::CanHold(imm, &o)) { |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3536 // 'unstop' and continue execution in the simulator or jump to the next | 3520 // 'unstop' and continue execution in the simulator or jump to the next |
| 3537 // instruction in gdb. | 3521 // instruction in gdb. |
| 3538 Label stop; | 3522 Label stop; |
| 3539 b(&stop); | 3523 b(&stop); |
| 3540 Emit(reinterpret_cast<int32_t>(message)); | 3524 Emit(reinterpret_cast<int32_t>(message)); |
| 3541 Bind(&stop); | 3525 Bind(&stop); |
| 3542 svc(kStopMessageSvcCode); | 3526 svc(kStopMessageSvcCode); |
| 3543 } | 3527 } |
| 3544 | 3528 |
| 3545 | 3529 |
| 3546 int32_t Assembler::AddObject(const Object& obj) { | |
| 3547 ASSERT(obj.IsNotTemporaryScopedHandle()); | |
| 3548 ASSERT(obj.IsOld()); | |
| 3549 if (object_pool_.IsNull()) { | |
| 3550 // The object pool cannot be used in the vm isolate. | |
| 3551 ASSERT(Isolate::Current() != Dart::vm_isolate()); | |
| 3552 object_pool_ = GrowableObjectArray::New(Heap::kOld); | |
| 3553 } | |
| 3554 | |
| 3555 intptr_t index = object_pool_index_table_.Lookup(&obj); | |
| 3556 if (index != ObjIndexPair::kNoIndex) { | |
| 3557 return index; | |
| 3558 } | |
| 3559 | |
| 3560 object_pool_.Add(obj, Heap::kOld); | |
| 3561 object_pool_index_table_.Insert( | |
| 3562 ObjIndexPair(&obj, object_pool_.Length() - 1)); | |
| 3563 return object_pool_.Length() - 1; | |
| 3564 } | |
| 3565 | |
| 3566 | |
| 3567 int32_t Assembler::AddExternalLabel(const ExternalLabel* label) { | |
| 3568 if (object_pool_.IsNull()) { | |
| 3569 // The object pool cannot be used in the vm isolate. | |
| 3570 ASSERT(Isolate::Current() != Dart::vm_isolate()); | |
| 3571 object_pool_ = GrowableObjectArray::New(Heap::kOld); | |
| 3572 } | |
| 3573 const word address = label->address(); | |
| 3574 ASSERT(Utils::IsAligned(address, 4)); | |
| 3575 // The address is stored in the object array as a RawSmi. | |
| 3576 const Smi& smi = Smi::Handle(Smi::New(address >> kSmiTagShift)); | |
| 3577 // Do not reuse an existing entry, since each reference may be patched | |
| 3578 // independently. | |
| 3579 object_pool_.Add(smi, Heap::kOld); | |
| 3580 return object_pool_.Length() - 1; | |
| 3581 } | |
| 3582 | |
| 3583 | |
| 3584 Address Assembler::ElementAddressForIntIndex(bool is_load, | 3530 Address Assembler::ElementAddressForIntIndex(bool is_load, |
| 3585 bool is_external, | 3531 bool is_external, |
| 3586 intptr_t cid, | 3532 intptr_t cid, |
| 3587 intptr_t index_scale, | 3533 intptr_t index_scale, |
| 3588 Register array, | 3534 Register array, |
| 3589 intptr_t index, | 3535 intptr_t index, |
| 3590 Register temp) { | 3536 Register temp) { |
| 3591 const int64_t offset_base = | 3537 const int64_t offset_base = |
| 3592 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); | 3538 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); |
| 3593 const int64_t offset = offset_base + | 3539 const int64_t offset = offset_base + |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3669 | 3615 |
| 3670 | 3616 |
| 3671 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 3617 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
| 3672 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); | 3618 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); |
| 3673 return fpu_reg_names[reg]; | 3619 return fpu_reg_names[reg]; |
| 3674 } | 3620 } |
| 3675 | 3621 |
| 3676 } // namespace dart | 3622 } // namespace dart |
| 3677 | 3623 |
| 3678 #endif // defined TARGET_ARCH_ARM | 3624 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |