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