12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
16bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers
17bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers#include "context_arm.h"
18bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers
193d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier#include "art_method-inl.h"
2041b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko#include "base/bit_utils.h"
217624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko#include "quick/quick_method_frame_info.h"
22bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers
23bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersnamespace art {
24bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersnamespace arm {
25bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers
260bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertzstatic constexpr uint32_t gZero = 0;
276702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier
286702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartiervoid ArmContext::Reset() {
2941b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko  std::fill_n(gprs_, arraysize(gprs_), nullptr);
3041b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko  std::fill_n(fprs_, arraysize(fprs_), nullptr);
316702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier  gprs_[SP] = &sp_;
326702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier  gprs_[PC] = &pc_;
336702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier  // Initialize registers with easy to spot debug values.
346702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier  sp_ = ArmContext::kBadGprBase + SP;
356702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier  pc_ = ArmContext::kBadGprBase + PC;
36bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers}
37bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers
380399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersvoid ArmContext::FillCalleeSaves(const StackVisitor& fr) {
393d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  ArtMethod* method = fr.GetMethod();
407624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko  const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
4141b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko  int spill_pos = 0;
4241b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko
4341b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko  // Core registers come first, from the highest down to the lowest.
4441b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko  uint32_t core_regs = frame_info.CoreSpillMask();
4541b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko  DCHECK_EQ(0u, core_regs & (static_cast<uint32_t>(-1) << kNumberOfCoreRegisters));
4641b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko  for (uint32_t core_reg : HighToLowBits(core_regs)) {
4741b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko    gprs_[core_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
4841b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko    ++spill_pos;
49bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers  }
5041b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko  DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()));
5141b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko
5241b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko  // FP registers come second, from the highest down to the lowest.
5341b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko  for (uint32_t fp_reg : HighToLowBits(frame_info.FpSpillMask())) {
5441b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko    fprs_[fp_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
5541b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko    ++spill_pos;
5615fdb8cfb5b2e3fc882113ec0648d492cebf852cIan Rogers  }
5741b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko  DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) + POPCOUNT(frame_info.FpSpillMask()));
58bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers}
59bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers
6096ba8dc82e7bd859106af837623fe8b2e9e772c3Sebastien Hertzvoid ArmContext::SetGPR(uint32_t reg, uintptr_t value) {
61d74e41b1cce5373aa24fd2fbea735173f6113d5aBrian Carlstrom  DCHECK_LT(reg, static_cast<uint32_t>(kNumberOfCoreRegisters));
6296ba8dc82e7bd859106af837623fe8b2e9e772c3Sebastien Hertz  DCHECK(IsAccessibleGPR(reg));
637934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  DCHECK_NE(gprs_[reg], &gZero);  // Can't overwrite this static value since they are never reset.
6496ba8dc82e7bd859106af837623fe8b2e9e772c3Sebastien Hertz  *gprs_[reg] = value;
650bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz}
660bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz
6796ba8dc82e7bd859106af837623fe8b2e9e772c3Sebastien Hertzvoid ArmContext::SetFPR(uint32_t reg, uintptr_t value) {
680bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  DCHECK_LT(reg, static_cast<uint32_t>(kNumberOfSRegisters));
6996ba8dc82e7bd859106af837623fe8b2e9e772c3Sebastien Hertz  DCHECK(IsAccessibleFPR(reg));
700bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  DCHECK_NE(fprs_[reg], &gZero);  // Can't overwrite this static value since they are never reset.
7196ba8dc82e7bd859106af837623fe8b2e9e772c3Sebastien Hertz  *fprs_[reg] = value;
726702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier}
736702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier
749c750f9b6283f62b3e6a93c0c6b2838abde5000eElliott Hughesvoid ArmContext::SmashCallerSaves() {
756702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier  // This needs to be 0 because we want a null/zero return value.
766702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier  gprs_[R0] = const_cast<uint32_t*>(&gZero);
776702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier  gprs_[R1] = const_cast<uint32_t*>(&gZero);
780bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  gprs_[R2] = nullptr;
790bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  gprs_[R3] = nullptr;
805667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu
815667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu  fprs_[S0] = nullptr;
825667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu  fprs_[S1] = nullptr;
835667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu  fprs_[S2] = nullptr;
845667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu  fprs_[S3] = nullptr;
855667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu  fprs_[S4] = nullptr;
865667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu  fprs_[S5] = nullptr;
875667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu  fprs_[S6] = nullptr;
885667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu  fprs_[S7] = nullptr;
895667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu  fprs_[S8] = nullptr;
905667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu  fprs_[S9] = nullptr;
915667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu  fprs_[S10] = nullptr;
925667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu  fprs_[S11] = nullptr;
935667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu  fprs_[S12] = nullptr;
945667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu  fprs_[S13] = nullptr;
955667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu  fprs_[S14] = nullptr;
965667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu  fprs_[S15] = nullptr;
979c750f9b6283f62b3e6a93c0c6b2838abde5000eElliott Hughes}
989c750f9b6283f62b3e6a93c0c6b2838abde5000eElliott Hughes
99794ad76e8d5b5b9132819d5b08a0570e27615644Andreas Gampeextern "C" NO_RETURN void art_quick_do_long_jump(uint32_t*, uint32_t*);
10057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
101bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersvoid ArmContext::DoLongJump() {
1020bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  uintptr_t gprs[kNumberOfCoreRegisters];
1030bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  uint32_t fprs[kNumberOfSRegisters];
1046702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier  for (size_t i = 0; i < kNumberOfCoreRegisters; ++i) {
1050bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz    gprs[i] = gprs_[i] != nullptr ? *gprs_[i] : ArmContext::kBadGprBase + i;
1066702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier  }
1076702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier  for (size_t i = 0; i < kNumberOfSRegisters; ++i) {
1080bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz    fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : ArmContext::kBadFprBase + i;
1096702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier  }
1106702243ea2332b566d8e8b871cc9db0906d835adMathieu Chartier  DCHECK_EQ(reinterpret_cast<uintptr_t>(Thread::Current()), gprs[TR]);
1118dbb708c7dc05c786329eb5c3fff3194ab6472acLogan Chien  art_quick_do_long_jump(gprs, fprs);
112bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers}
113bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers
114bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers}  // namespace arm
115bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers}  // namespace art
116