calling_convention_x86.cc revision 166db04e259ca51838c311891598664deeed85ad
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 */ 16b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 172c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers#include "calling_convention_x86.h" 1857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers 1907ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h" 20166db04e259ca51838c311891598664deeed85adIan Rogers#include "utils/x86/managed_register_x86.h" 21578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "utils.h" 22b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 23b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersnamespace art { 242c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogersnamespace x86 { 25b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 262c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers// Calling convention 272c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 282c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersManagedRegister X86ManagedRuntimeCallingConvention::InterproceduralScratchRegister() { 292c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers return X86ManagedRegister::FromCpuRegister(ECX); 30b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} 31b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 322c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersManagedRegister X86JniCallingConvention::InterproceduralScratchRegister() { 332c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers return X86ManagedRegister::FromCpuRegister(ECX); 34b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} 35b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 36dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian RogersManagedRegister X86JniCallingConvention::ReturnScratchRegister() const { 37dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers return ManagedRegister::NoRegister(); // No free regs, so assembler uses push/pop 38dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers} 39dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers 40b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogersstatic ManagedRegister ReturnRegisterForShorty(const char* shorty, bool jni) { 41169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers if (shorty[0] == 'F' || shorty[0] == 'D') { 42b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers if (jni) { 43b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers return X86ManagedRegister::FromX87Register(ST0); 44b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } else { 45b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers return X86ManagedRegister::FromXmmRegister(XMM0); 46b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 47169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } else if (shorty[0] == 'J') { 482c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers return X86ManagedRegister::FromRegisterPair(EAX_EDX); 49169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } else if (shorty[0] == 'V') { 5045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers return ManagedRegister::NoRegister(); 51b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } else { 522c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers return X86ManagedRegister::FromCpuRegister(EAX); 53b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 54b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} 55b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 562c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersManagedRegister X86ManagedRuntimeCallingConvention::ReturnRegister() { 57b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers return ReturnRegisterForShorty(GetShorty(), false); 582c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers} 592c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 602c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersManagedRegister X86JniCallingConvention::ReturnRegister() { 61b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers return ReturnRegisterForShorty(GetShorty(), true); 622c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers} 632c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 6400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan RogersManagedRegister X86JniCallingConvention::IntReturnRegister() { 6500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return X86ManagedRegister::FromCpuRegister(EAX); 6600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers} 6700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 68b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Managed runtime calling convention 69b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 702c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersManagedRegister X86ManagedRuntimeCallingConvention::MethodRegister() { 7167375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers return X86ManagedRegister::FromCpuRegister(EAX); 722c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers} 732c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 742c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogersbool X86ManagedRuntimeCallingConvention::IsCurrentParamInRegister() { 75b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers return false; // Everything is passed by stack 76b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} 77b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 782c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogersbool X86ManagedRuntimeCallingConvention::IsCurrentParamOnStack() { 79b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers return true; // Everything is passed by stack 80b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} 81b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 822c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersManagedRegister X86ManagedRuntimeCallingConvention::CurrentParamRegister() { 83b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers LOG(FATAL) << "Should not reach here"; 84b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers return ManagedRegister::NoRegister(); 85b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} 86b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 872c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersFrameOffset X86ManagedRuntimeCallingConvention::CurrentParamStackOffset() { 88cdd1d2d3fee0711b8b11db99f2dfb80113520100Ian Rogers return FrameOffset(displacement_.Int32Value() + // displacement 89cdd1d2d3fee0711b8b11db99f2dfb80113520100Ian Rogers kPointerSize + // Method* 90cdd1d2d3fee0711b8b11db99f2dfb80113520100Ian Rogers (itr_slots_ * kPointerSize)); // offset into in args 91b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} 92b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 93b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogersconst std::vector<ManagedRegister>& X86ManagedRuntimeCallingConvention::EntrySpills() { 94b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers // We spill the argument registers on X86 to free them up for scratch use, we then assume 95b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers // all arguments are on the stack. 96b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers if (entry_spills_.size() == 0) { 97b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers size_t num_spills = NumArgs() + NumLongOrDoubleArgs(); 98b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers if (num_spills > 0) { 99b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers entry_spills_.push_back(X86ManagedRegister::FromCpuRegister(ECX)); 100b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers if (num_spills > 1) { 101b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers entry_spills_.push_back(X86ManagedRegister::FromCpuRegister(EDX)); 102b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers if (num_spills > 2) { 103b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers entry_spills_.push_back(X86ManagedRegister::FromCpuRegister(EBX)); 104b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers } 105b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 106b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 107b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers } 108b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers return entry_spills_; 109b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers} 110b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers 111b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// JNI calling convention 112b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 113703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhaoX86JniCallingConvention::X86JniCallingConvention(bool is_static, bool is_synchronized, 114703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao const char* shorty) 115703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao : JniCallingConvention(is_static, is_synchronized, shorty) { 116703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao callee_save_regs_.push_back(X86ManagedRegister::FromCpuRegister(EBP)); 117703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao callee_save_regs_.push_back(X86ManagedRegister::FromCpuRegister(ESI)); 118703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao callee_save_regs_.push_back(X86ManagedRegister::FromCpuRegister(EDI)); 119703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao} 120703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao 121703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhaouint32_t X86JniCallingConvention::CoreSpillMask() const { 122703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao return 1 << EBP | 1 << ESI | 1 << EDI | 1 << kNumberOfCpuRegisters; 123703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao} 124bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 1252c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogerssize_t X86JniCallingConvention::FrameSize() { 126703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao // Method*, return address and callee save area size, local reference segment state 127703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao size_t frame_data_size = (3 + CalleeSaveRegisters().size()) * kPointerSize; 128408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // References plus 2 words for SIRT header 129408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers size_t sirt_size = (ReferenceCount() + 2) * kPointerSize; 1300d666d8769714dcbc2acc4dd5b06f0deffa6e0a1Ian Rogers // Plus return value spill area size 131dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers return RoundUp(frame_data_size + sirt_size + SizeOfReturnValue(), kStackAlignment); 1320d666d8769714dcbc2acc4dd5b06f0deffa6e0a1Ian Rogers} 1330d666d8769714dcbc2acc4dd5b06f0deffa6e0a1Ian Rogers 1342c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogerssize_t X86JniCallingConvention::OutArgSize() { 1357a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers return RoundUp(NumberOfOutgoingStackArgs() * kPointerSize, kStackAlignment); 1367a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers} 1377a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers 1382c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogersbool X86JniCallingConvention::IsCurrentParamInRegister() { 139b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers return false; // Everything is passed by stack. 140b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} 141b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 1422c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogersbool X86JniCallingConvention::IsCurrentParamOnStack() { 143b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers return true; // Everything is passed by stack. 144b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} 145b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 1462c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersManagedRegister X86JniCallingConvention::CurrentParamRegister() { 147b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers LOG(FATAL) << "Should not reach here"; 148b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers return ManagedRegister::NoRegister(); 149b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} 150b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 1512c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersFrameOffset X86JniCallingConvention::CurrentParamStackOffset() { 15200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return FrameOffset(displacement_.Int32Value() - OutArgSize() + (itr_slots_ * kPointerSize)); 153b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} 154b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 1552c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogerssize_t X86JniCallingConvention::NumberOfOutgoingStackArgs() { 156169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t static_args = IsStatic() ? 1 : 0; // count jclass 1577a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers // regular argument parameters and this 158169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t param_args = NumArgs() + NumLongOrDoubleArgs(); 15900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // count JNIEnv* and return pc (pushed after Method*) 16000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers size_t total_args = static_args + param_args + 2; 16100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return total_args; 162b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} 163b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 1642c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers} // namespace x86 165b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} // namespace art 166