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