1b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith/*
2b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * Copyright (C) 2014 The Android Open Source Project
3b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *
4b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * Licensed under the Apache License, Version 2.0 (the "License");
5b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * you may not use this file except in compliance with the License.
6b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * You may obtain a copy of the License at
7b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *
8b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *      http://www.apache.org/licenses/LICENSE-2.0
9b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith *
10b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * Unless required by applicable law or agreed to in writing, software
11b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * distributed under the License is distributed on an "AS IS" BASIS,
12b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * See the License for the specific language governing permissions and
14b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith * limitations under the License.
15b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith */
16b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
17b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith#include <stdint.h>
18b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
19b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith#include "context_arm64.h"
20b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
2180afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "base/bit_utils.h"
227624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko#include "quick/quick_method_frame_info.h"
23524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray#include "thread-inl.h"
24b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
25b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithnamespace art {
26b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithnamespace arm64 {
27b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
280bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertzstatic constexpr uint64_t gZero = 0;
29b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
30b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithvoid Arm64Context::Reset() {
3180afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko  std::fill_n(gprs_, arraysize(gprs_), nullptr);
3280afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko  std::fill_n(fprs_, arraysize(fprs_), nullptr);
33b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  gprs_[SP] = &sp_;
34639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe  gprs_[kPC] = &pc_;
35639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe  gprs_[X0] = &arg0_;
36b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  // Initialize registers with easy to spot debug values.
37b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  sp_ = Arm64Context::kBadGprBase + SP;
38639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe  pc_ = Arm64Context::kBadGprBase + kPC;
39639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe  arg0_ = 0;
40b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
41b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
42524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffrayvoid Arm64Context::FillCalleeSaves(uint8_t* frame, const QuickMethodFrameInfo& frame_info) {
4380afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko  int spill_pos = 0;
4480afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko
4580afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko  // Core registers come first, from the highest down to the lowest.
4680afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko  for (uint32_t core_reg : HighToLowBits(frame_info.CoreSpillMask())) {
47524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    gprs_[core_reg] = CalleeSaveAddress(frame, spill_pos, frame_info.FrameSizeInBytes());
4880afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko    ++spill_pos;
49b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  }
5080afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko  DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()));
51b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
5280afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko  // FP registers come second, from the highest down to the lowest.
5380afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko  for (uint32_t fp_reg : HighToLowBits(frame_info.FpSpillMask())) {
54524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    fprs_[fp_reg] = CalleeSaveAddress(frame, spill_pos, frame_info.FrameSizeInBytes());
5580afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko    ++spill_pos;
56b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  }
5780afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko  DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) + POPCOUNT(frame_info.FpSpillMask()));
58b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
59b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
6096ba8dc82e7bd859106af837623fe8b2e9e772c3Sebastien Hertzvoid Arm64Context::SetGPR(uint32_t reg, uintptr_t value) {
61639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe  DCHECK_LT(reg, arraysize(gprs_));
62639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe  // Note: we use kPC == XZR, so do not ensure that reg != XZR.
6396ba8dc82e7bd859106af837623fe8b2e9e772c3Sebastien Hertz  DCHECK(IsAccessibleGPR(reg));
64b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  DCHECK_NE(gprs_[reg], &gZero);  // Can't overwrite this static value since they are never reset.
6596ba8dc82e7bd859106af837623fe8b2e9e772c3Sebastien Hertz  *gprs_[reg] = value;
660bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz}
670bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz
6896ba8dc82e7bd859106af837623fe8b2e9e772c3Sebastien Hertzvoid Arm64Context::SetFPR(uint32_t reg, uintptr_t value) {
690bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  DCHECK_LT(reg, static_cast<uint32_t>(kNumberOfDRegisters));
7096ba8dc82e7bd859106af837623fe8b2e9e772c3Sebastien Hertz  DCHECK(IsAccessibleFPR(reg));
710bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  DCHECK_NE(fprs_[reg], &gZero);  // Can't overwrite this static value since they are never reset.
7296ba8dc82e7bd859106af837623fe8b2e9e772c3Sebastien Hertz  *fprs_[reg] = value;
73b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
74b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
75b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithvoid Arm64Context::SmashCallerSaves() {
76b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  // This needs to be 0 because we want a null/zero return value.
77b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  gprs_[X0] = const_cast<uint64_t*>(&gZero);
780bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  gprs_[X1] = nullptr;
790bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  gprs_[X2] = nullptr;
800bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  gprs_[X3] = nullptr;
810bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  gprs_[X4] = nullptr;
820bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  gprs_[X5] = nullptr;
830bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  gprs_[X6] = nullptr;
840bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  gprs_[X7] = nullptr;
850bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  gprs_[X8] = nullptr;
860bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  gprs_[X9] = nullptr;
870bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  gprs_[X10] = nullptr;
880bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  gprs_[X11] = nullptr;
890bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  gprs_[X12] = nullptr;
900bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  gprs_[X13] = nullptr;
910bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  gprs_[X14] = nullptr;
920bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  gprs_[X15] = nullptr;
939bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu  gprs_[X18] = nullptr;
94b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
956cf80102b5f308f2a5326869343ea0d19109a7fbAndreas Gampe  // d0-d7, d16-d31 are caller-saved; d8-d15 are callee-saved.
966cf80102b5f308f2a5326869343ea0d19109a7fbAndreas Gampe
970bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D0] = nullptr;
980bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D1] = nullptr;
990bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D2] = nullptr;
1000bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D3] = nullptr;
1010bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D4] = nullptr;
1020bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D5] = nullptr;
1030bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D6] = nullptr;
1040bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D7] = nullptr;
1050bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz
1060bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D16] = nullptr;
1070bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D17] = nullptr;
1080bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D18] = nullptr;
1090bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D19] = nullptr;
1100bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D20] = nullptr;
1110bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D21] = nullptr;
1120bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D22] = nullptr;
1130bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D23] = nullptr;
1140bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D24] = nullptr;
1150bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D25] = nullptr;
1160bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D26] = nullptr;
1170bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D27] = nullptr;
1180bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D28] = nullptr;
1190bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D29] = nullptr;
1200bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D30] = nullptr;
1210bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  fprs_[D31] = nullptr;
122b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
123b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
124794ad76e8d5b5b9132819d5b08a0570e27615644Andreas Gampeextern "C" NO_RETURN void art_quick_do_long_jump(uint64_t*, uint64_t*);
125b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
126b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithvoid Arm64Context::DoLongJump() {
127639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe  uint64_t gprs[arraysize(gprs_)];
1280bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz  uint64_t fprs[kNumberOfDRegisters];
129b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
130a304f97c97d38af73afe6b49259ac4faf0902123Alexandre Rames  // The long jump routine called below expects to find the value for SP at index 31.
131a304f97c97d38af73afe6b49259ac4faf0902123Alexandre Rames  DCHECK_EQ(SP, 31);
132a304f97c97d38af73afe6b49259ac4faf0902123Alexandre Rames
133639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe  for (size_t i = 0; i < arraysize(gprs_); ++i) {
1340bcb2902ec21393d71c94e63aa6733cb5311a0ccSebastien Hertz    gprs[i] = gprs_[i] != nullptr ? *gprs_[i] : Arm64Context::kBadGprBase + i;
135b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  }
136b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  for (size_t i = 0; i < kNumberOfDRegisters; ++i) {
1375b09ea0af468d9232cf725ac7f7e73c145892c5cVladimir Marko    fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : Arm64Context::kBadFprBase + i;
138b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  }
139b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  DCHECK_EQ(reinterpret_cast<uintptr_t>(Thread::Current()), gprs[TR]);
140b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  art_quick_do_long_jump(gprs, fprs);
141b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
142b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
143b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}  // namespace arm64
144b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}  // namespace art
145