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 "base/logging.h"
18b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith#include "calling_convention_arm64.h"
193e0acf673ce1fbb3932d288d7b52a6dc551a920fMathieu Chartier#include "handle_scope-inl.h"
20b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith#include "utils/arm64/managed_register_arm64.h"
21b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
22b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithnamespace art {
23b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithnamespace arm64 {
24b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
2537c92df53979f9f6ab83155ab9521d554d717161Alexandre Ramesstatic const XRegister kXArgumentRegisters[] = {
2675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  X0, X1, X2, X3, X4, X5, X6, X7
2775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu};
2875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu
2975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescustatic const WRegister kWArgumentRegisters[] = {
3075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  W0, W1, W2, W3, W4, W5, W6, W7
3175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu};
3275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu
3375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescustatic const DRegister kDArgumentRegisters[] = {
3475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  D0, D1, D2, D3, D4, D5, D6, D7
3575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu};
3675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu
3775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescustatic const SRegister kSArgumentRegisters[] = {
3875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  S0, S1, S2, S3, S4, S5, S6, S7
3975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu};
40b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
417cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertzstatic const DRegister kDCalleeSaveRegisters[] = {
427cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz  D8, D9, D10, D11, D12, D13, D14, D15
437cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz};
447cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz
4575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu// Calling convention
46b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithManagedRegister Arm64ManagedRuntimeCallingConvention::InterproceduralScratchRegister() {
4737c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames  return Arm64ManagedRegister::FromXRegister(X20);  // saved on entry restored on exit
48b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
49b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
50b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithManagedRegister Arm64JniCallingConvention::InterproceduralScratchRegister() {
5137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames  return Arm64ManagedRegister::FromXRegister(X20);  // saved on entry restored on exit
52b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
53b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
54b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithstatic ManagedRegister ReturnRegisterForShorty(const char* shorty) {
55b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  if (shorty[0] == 'F') {
56b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    return Arm64ManagedRegister::FromSRegister(S0);
57b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  } else if (shorty[0] == 'D') {
58b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    return Arm64ManagedRegister::FromDRegister(D0);
59b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  } else if (shorty[0] == 'J') {
6037c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames    return Arm64ManagedRegister::FromXRegister(X0);
61b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  } else if (shorty[0] == 'V') {
62b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    return Arm64ManagedRegister::NoRegister();
63b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  } else {
64b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    return Arm64ManagedRegister::FromWRegister(W0);
65b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  }
66b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
67b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
68b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithManagedRegister Arm64ManagedRuntimeCallingConvention::ReturnRegister() {
69b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  return ReturnRegisterForShorty(GetShorty());
70b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
71b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
72b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithManagedRegister Arm64JniCallingConvention::ReturnRegister() {
73b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  return ReturnRegisterForShorty(GetShorty());
74b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
75b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
76b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithManagedRegister Arm64JniCallingConvention::IntReturnRegister() {
77b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  return Arm64ManagedRegister::FromWRegister(W0);
78b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
79b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
80b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith// Managed runtime calling convention
81b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
82b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithManagedRegister Arm64ManagedRuntimeCallingConvention::MethodRegister() {
8337c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames  return Arm64ManagedRegister::FromXRegister(X0);
84b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
85b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
86b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithbool Arm64ManagedRuntimeCallingConvention::IsCurrentParamInRegister() {
87b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  return false;  // Everything moved to stack on entry.
88b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
89b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
90b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithbool Arm64ManagedRuntimeCallingConvention::IsCurrentParamOnStack() {
91b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  return true;
92b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
93b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
94b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithManagedRegister Arm64ManagedRuntimeCallingConvention::CurrentParamRegister() {
95b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  LOG(FATAL) << "Should not reach here";
96b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  return ManagedRegister::NoRegister();
97b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
98b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
99b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithFrameOffset Arm64ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
100b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  CHECK(IsCurrentParamOnStack());
101b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  FrameOffset result =
102e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier      FrameOffset(displacement_.Int32Value() +  // displacement
103e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                  kFramePointerSize +  // Method ref
10475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu                  (itr_slots_ * sizeof(uint32_t)));  // offset into in args
105b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  return result;
106b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
107b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
108fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenkoconst ManagedRegisterEntrySpills& Arm64ManagedRuntimeCallingConvention::EntrySpills() {
109b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  // We spill the argument registers on ARM64 to free them up for scratch use, we then assume
110b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  // all arguments are on the stack.
11175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  if ((entry_spills_.size() == 0) && (NumArgs() > 0)) {
11275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    int gp_reg_index = 1;   // we start from X1/W1, X0 holds ArtMethod*.
11375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    int fp_reg_index = 0;   // D0/S0.
11475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu
11575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    // We need to choose the correct register (D/S or X/W) since the managed
11675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    // stack uses 32bit stack slots.
11775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    ResetIterator(FrameOffset(0));
11875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    while (HasNext()) {
11975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu      if (IsCurrentParamAFloatOrDouble()) {  // FP regs.
12075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu          if (fp_reg_index < 8) {
12175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu            if (!IsCurrentParamADouble()) {
12275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu              entry_spills_.push_back(Arm64ManagedRegister::FromSRegister(kSArgumentRegisters[fp_reg_index]));
12375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu            } else {
12475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu              entry_spills_.push_back(Arm64ManagedRegister::FromDRegister(kDArgumentRegisters[fp_reg_index]));
12575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu            }
12675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu            fp_reg_index++;
12775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu          } else {  // just increase the stack offset.
12875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu            if (!IsCurrentParamADouble()) {
12975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu              entry_spills_.push_back(ManagedRegister::NoRegister(), 4);
13075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu            } else {
13175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu              entry_spills_.push_back(ManagedRegister::NoRegister(), 8);
132b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith            }
133b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith          }
13475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu      } else {  // GP regs.
13575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu        if (gp_reg_index < 8) {
13675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu          if (IsCurrentParamALong() && (!IsCurrentParamAReference())) {
13737c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames            entry_spills_.push_back(Arm64ManagedRegister::FromXRegister(kXArgumentRegisters[gp_reg_index]));
13875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu          } else {
13975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu            entry_spills_.push_back(Arm64ManagedRegister::FromWRegister(kWArgumentRegisters[gp_reg_index]));
14075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu          }
14175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu          gp_reg_index++;
14275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu        } else {  // just increase the stack offset.
14375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu          if (IsCurrentParamALong() && (!IsCurrentParamAReference())) {
14475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu              entry_spills_.push_back(ManagedRegister::NoRegister(), 8);
14575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu          } else {
14675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu              entry_spills_.push_back(ManagedRegister::NoRegister(), 4);
14775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu          }
148b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith        }
149b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith      }
15075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu      Next();
151b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith    }
152b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  }
153b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  return entry_spills_;
154b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
155b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
15675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu// JNI calling convention
157b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithArm64JniCallingConvention::Arm64JniCallingConvention(bool is_static, bool is_synchronized,
158790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers                                                     const char* shorty)
159790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers    : JniCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {
16069a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu  uint32_t core_spill_mask = CoreSpillMask();
16180afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko  DCHECK_EQ(XZR, kNumberOfXRegisters - 1);  // Exclude XZR from the loop (avoid 1 << 32).
16280afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko  for (int x_reg = 0; x_reg < kNumberOfXRegisters - 1; ++x_reg) {
16369a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu    if (((1 << x_reg) & core_spill_mask) != 0) {
16469a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu      callee_save_regs_.push_back(
16569a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu          Arm64ManagedRegister::FromXRegister(static_cast<XRegister>(x_reg)));
16669a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu    }
16769a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu  }
1687cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz
16969a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu  uint32_t fp_spill_mask = FpSpillMask();
17069a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu  for (int d_reg = 0; d_reg < kNumberOfDRegisters; ++d_reg) {
17169a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu    if (((1 << d_reg) & fp_spill_mask) != 0) {
17269a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu      callee_save_regs_.push_back(
17369a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu          Arm64ManagedRegister::FromDRegister(static_cast<DRegister>(d_reg)));
17469a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu    }
1757cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz  }
176b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
177b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
178b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithuint32_t Arm64JniCallingConvention::CoreSpillMask() const {
17969a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu  // Compute spill mask to agree with callee saves initialized in the constructor.
180b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu  // Note: The native jni function may call to some VM runtime functions which may suspend
181b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu  // or trigger GC. And the jni method frame will become top quick frame in those cases.
182b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu  // So we need to satisfy GC to save LR and callee-save registers which is similar to
183b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu  // CalleeSaveMethod(RefOnly) frame.
184b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu  // Jni function is the native function which the java code wants to call.
185b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu  // Jni method is the method that compiled by jni compiler.
186b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu  // Call chain: managed code(java) --> jni method --> jni function.
1879bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu  // Thread register(X19) is saved on stack.
18869a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu  return 1 << X19 | 1 << X20 | 1 << X21 | 1 << X22 | 1 << X23 | 1 << X24 |
18969a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu         1 << X25 | 1 << X26 | 1 << X27 | 1 << X28 | 1 << X29 | 1 << LR;
19075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu}
19175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu
19275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescuuint32_t Arm64JniCallingConvention::FpSpillMask() const {
19369a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu  // Considering the case, java_method_1 --> jni method --> jni function --> java_method_2, we may
19469a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu  // break on java_method_2 and we still need to find out the values of DEX registers in
19569a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu  // java_method_1. So all callee-saves(in managed code) need to be saved.
1967cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz  uint32_t result = 0;
1977cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz  for (size_t i = 0; i < arraysize(kDCalleeSaveRegisters); ++i) {
1987cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz    result |= (1 << kDCalleeSaveRegisters[i]);
1997cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz  }
2007cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz  return result;
201b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
202b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
203b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithManagedRegister Arm64JniCallingConvention::ReturnScratchRegister() const {
20475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  return ManagedRegister::NoRegister();
205b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
206b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
207b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithsize_t Arm64JniCallingConvention::FrameSize() {
20875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  // Method*, callee save area size, local reference segment state
209e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  size_t frame_data_size = kFramePointerSize +
210cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe      CalleeSaveRegisters().size() * kFramePointerSize + sizeof(uint32_t);
211eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  // References plus 2 words for HandleScope header
212cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe  size_t handle_scope_size = HandleScope::SizeOf(kFramePointerSize, ReferenceCount());
213b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  // Plus return value spill area size
214eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  return RoundUp(frame_data_size + handle_scope_size + SizeOfReturnValue(), kStackAlignment);
215b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
216b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
217b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithsize_t Arm64JniCallingConvention::OutArgSize() {
21875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  return RoundUp(NumberOfOutgoingStackArgs() * kFramePointerSize, kStackAlignment);
219b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
220b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
221b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithbool Arm64JniCallingConvention::IsCurrentParamInRegister() {
22275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  if (IsCurrentParamAFloatOrDouble()) {
22375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    return (itr_float_and_doubles_ < 8);
22475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  } else {
22575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    return ((itr_args_ - itr_float_and_doubles_) < 8);
22675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  }
227b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
228b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
229b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithbool Arm64JniCallingConvention::IsCurrentParamOnStack() {
230b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  return !IsCurrentParamInRegister();
231b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
232b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
233b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithManagedRegister Arm64JniCallingConvention::CurrentParamRegister() {
23475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  CHECK(IsCurrentParamInRegister());
23575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  if (IsCurrentParamAFloatOrDouble()) {
23675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    CHECK_LT(itr_float_and_doubles_, 8u);
23775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    if (IsCurrentParamADouble()) {
23875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu      return Arm64ManagedRegister::FromDRegister(kDArgumentRegisters[itr_float_and_doubles_]);
23975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    } else {
24075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu      return Arm64ManagedRegister::FromSRegister(kSArgumentRegisters[itr_float_and_doubles_]);
24175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    }
242b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  } else {
24375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    int gp_reg = itr_args_ - itr_float_and_doubles_;
24475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    CHECK_LT(static_cast<unsigned int>(gp_reg), 8u);
24575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    if (IsCurrentParamALong() || IsCurrentParamAReference() || IsCurrentParamJniEnv())  {
24637c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames      return Arm64ManagedRegister::FromXRegister(kXArgumentRegisters[gp_reg]);
24775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    } else {
24875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu      return Arm64ManagedRegister::FromWRegister(kWArgumentRegisters[gp_reg]);
24975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu    }
250b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  }
251b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
252b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
253b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart MonteithFrameOffset Arm64JniCallingConvention::CurrentParamStackOffset() {
25475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  CHECK(IsCurrentParamOnStack());
25575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  size_t args_on_stack = itr_args_
25675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu                  - std::min(8u, itr_float_and_doubles_)
25775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu                  - std::min(8u, (itr_args_ - itr_float_and_doubles_));
25875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  size_t offset = displacement_.Int32Value() - OutArgSize() + (args_on_stack * kFramePointerSize);
259b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  CHECK_LT(offset, OutArgSize());
260b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith  return FrameOffset(offset);
261b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
262b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
263b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithsize_t Arm64JniCallingConvention::NumberOfOutgoingStackArgs() {
26475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  // all arguments including JNI args
26575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  size_t all_args = NumArgs() + NumberOfExtraArgumentsForJni();
26675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu
26775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  size_t all_stack_args = all_args -
26875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu            std::min(8u, static_cast<unsigned int>(NumFloatOrDoubleArgs())) -
26975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu            std::min(8u, static_cast<unsigned int>((all_args - NumFloatOrDoubleArgs())));
27075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu
27175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  return all_stack_args;
272b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}
273b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith
274b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}  // namespace arm64
275b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith}  // namespace art
276