diff options
Diffstat (limited to 'runtime/arch/arm64/context_arm64.cc')
-rw-r--r-- | runtime/arch/arm64/context_arm64.cc | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/runtime/arch/arm64/context_arm64.cc b/runtime/arch/arm64/context_arm64.cc new file mode 100644 index 0000000000..3d63c36abe --- /dev/null +++ b/runtime/arch/arm64/context_arm64.cc @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdint.h> + +#include "context_arm64.h" + +#include "mirror/art_method.h" +#include "mirror/object-inl.h" +#include "stack.h" +#include "thread.h" + + +namespace art { +namespace arm64 { + +static const uint64_t gZero = 0; + +void Arm64Context::Reset() { + for (size_t i = 0; i < kNumberOfCoreRegisters; i++) { + gprs_[i] = NULL; + } + for (size_t i = 0; i < kNumberOfDRegisters; i++) { + fprs_[i] = NULL; + } + gprs_[SP] = &sp_; + gprs_[LR] = &pc_; + // Initialize registers with easy to spot debug values. + sp_ = Arm64Context::kBadGprBase + SP; + pc_ = Arm64Context::kBadGprBase + LR; +} + +void Arm64Context::FillCalleeSaves(const StackVisitor& fr) { + mirror::ArtMethod* method = fr.GetMethod(); + uint32_t core_spills = method->GetCoreSpillMask(); + uint32_t fp_core_spills = method->GetFpSpillMask(); + size_t spill_count = __builtin_popcount(core_spills); + size_t fp_spill_count = __builtin_popcount(fp_core_spills); + size_t frame_size = method->GetFrameSizeInBytes(); + + if (spill_count > 0) { + // Lowest number spill is farthest away, walk registers and fill into context. + int j = 1; + for (size_t i = 0; i < kNumberOfCoreRegisters; i++) { + if (((core_spills >> i) & 1) != 0) { + gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_size); + j++; + } + } + } + + if (fp_spill_count > 0) { + // Lowest number spill is farthest away, walk registers and fill into context. + int j = 1; + for (size_t i = 0; i < kNumberOfDRegisters; i++) { + if (((fp_core_spills >> i) & 1) != 0) { + fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j, frame_size); + j++; + } + } + } +} + +void Arm64Context::SetGPR(uint32_t reg, uintptr_t value) { + DCHECK_LT(reg, static_cast<uint32_t>(kNumberOfCoreRegisters)); + DCHECK_NE(gprs_[reg], &gZero); // Can't overwrite this static value since they are never reset. + DCHECK(gprs_[reg] != NULL); + *gprs_[reg] = value; +} + +void Arm64Context::SmashCallerSaves() { + // This needs to be 0 because we want a null/zero return value. + gprs_[X0] = const_cast<uint64_t*>(&gZero); + gprs_[X1] = NULL; + gprs_[X2] = NULL; + gprs_[X3] = NULL; + gprs_[X4] = NULL; + gprs_[X5] = NULL; + gprs_[X6] = NULL; + gprs_[X7] = NULL; + gprs_[X8] = NULL; + gprs_[X9] = NULL; + gprs_[X10] = NULL; + gprs_[X11] = NULL; + gprs_[X12] = NULL; + gprs_[X13] = NULL; + gprs_[X14] = NULL; + gprs_[X15] = NULL; + + fprs_[D8] = NULL; + fprs_[D9] = NULL; + fprs_[D10] = NULL; + fprs_[D11] = NULL; + fprs_[D12] = NULL; + fprs_[D13] = NULL; + fprs_[D14] = NULL; + fprs_[D15] = NULL; +} + +extern "C" void art_quick_do_long_jump(uint64_t*, uint64_t*); + +void Arm64Context::DoLongJump() { + uint64_t gprs[32]; + uint64_t fprs[32]; + + for (size_t i = 0; i < kNumberOfCoreRegisters; ++i) { + gprs[i] = gprs_[i] != NULL ? *gprs_[i] : Arm64Context::kBadGprBase + i; + } + for (size_t i = 0; i < kNumberOfDRegisters; ++i) { + fprs[i] = fprs_[i] != NULL ? *fprs_[i] : Arm64Context::kBadGprBase + i; + } + DCHECK_EQ(reinterpret_cast<uintptr_t>(Thread::Current()), gprs[TR]); + art_quick_do_long_jump(gprs, fprs); +} + +} // namespace arm64 +} // namespace art |