calling_convention_x86.cc revision 166db04e259ca51838c311891598664deeed85ad
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "calling_convention_x86.h"
18
19#include "base/logging.h"
20#include "utils/x86/managed_register_x86.h"
21#include "utils.h"
22
23namespace art {
24namespace x86 {
25
26// Calling convention
27
28ManagedRegister X86ManagedRuntimeCallingConvention::InterproceduralScratchRegister() {
29  return X86ManagedRegister::FromCpuRegister(ECX);
30}
31
32ManagedRegister X86JniCallingConvention::InterproceduralScratchRegister() {
33  return X86ManagedRegister::FromCpuRegister(ECX);
34}
35
36ManagedRegister X86JniCallingConvention::ReturnScratchRegister() const {
37  return ManagedRegister::NoRegister();  // No free regs, so assembler uses push/pop
38}
39
40static ManagedRegister ReturnRegisterForShorty(const char* shorty, bool jni) {
41  if (shorty[0] == 'F' || shorty[0] == 'D') {
42    if (jni) {
43      return X86ManagedRegister::FromX87Register(ST0);
44    } else {
45      return X86ManagedRegister::FromXmmRegister(XMM0);
46    }
47  } else if (shorty[0] == 'J') {
48    return X86ManagedRegister::FromRegisterPair(EAX_EDX);
49  } else if (shorty[0] == 'V') {
50    return ManagedRegister::NoRegister();
51  } else {
52    return X86ManagedRegister::FromCpuRegister(EAX);
53  }
54}
55
56ManagedRegister X86ManagedRuntimeCallingConvention::ReturnRegister() {
57  return ReturnRegisterForShorty(GetShorty(), false);
58}
59
60ManagedRegister X86JniCallingConvention::ReturnRegister() {
61  return ReturnRegisterForShorty(GetShorty(), true);
62}
63
64ManagedRegister X86JniCallingConvention::IntReturnRegister() {
65  return X86ManagedRegister::FromCpuRegister(EAX);
66}
67
68// Managed runtime calling convention
69
70ManagedRegister X86ManagedRuntimeCallingConvention::MethodRegister() {
71  return X86ManagedRegister::FromCpuRegister(EAX);
72}
73
74bool X86ManagedRuntimeCallingConvention::IsCurrentParamInRegister() {
75  return false;  // Everything is passed by stack
76}
77
78bool X86ManagedRuntimeCallingConvention::IsCurrentParamOnStack() {
79  return true;  // Everything is passed by stack
80}
81
82ManagedRegister X86ManagedRuntimeCallingConvention::CurrentParamRegister() {
83  LOG(FATAL) << "Should not reach here";
84  return ManagedRegister::NoRegister();
85}
86
87FrameOffset X86ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
88  return FrameOffset(displacement_.Int32Value() +   // displacement
89                     kPointerSize +                 // Method*
90                     (itr_slots_ * kPointerSize));  // offset into in args
91}
92
93const std::vector<ManagedRegister>& X86ManagedRuntimeCallingConvention::EntrySpills() {
94  // We spill the argument registers on X86 to free them up for scratch use, we then assume
95  // all arguments are on the stack.
96  if (entry_spills_.size() == 0) {
97    size_t num_spills = NumArgs() + NumLongOrDoubleArgs();
98    if (num_spills > 0) {
99      entry_spills_.push_back(X86ManagedRegister::FromCpuRegister(ECX));
100      if (num_spills > 1) {
101        entry_spills_.push_back(X86ManagedRegister::FromCpuRegister(EDX));
102        if (num_spills > 2) {
103          entry_spills_.push_back(X86ManagedRegister::FromCpuRegister(EBX));
104        }
105      }
106    }
107  }
108  return entry_spills_;
109}
110
111// JNI calling convention
112
113X86JniCallingConvention::X86JniCallingConvention(bool is_static, bool is_synchronized,
114                                                 const char* shorty)
115    : JniCallingConvention(is_static, is_synchronized, shorty) {
116  callee_save_regs_.push_back(X86ManagedRegister::FromCpuRegister(EBP));
117  callee_save_regs_.push_back(X86ManagedRegister::FromCpuRegister(ESI));
118  callee_save_regs_.push_back(X86ManagedRegister::FromCpuRegister(EDI));
119}
120
121uint32_t X86JniCallingConvention::CoreSpillMask() const {
122  return 1 << EBP | 1 << ESI | 1 << EDI | 1 << kNumberOfCpuRegisters;
123}
124
125size_t X86JniCallingConvention::FrameSize() {
126  // Method*, return address and callee save area size, local reference segment state
127  size_t frame_data_size = (3 + CalleeSaveRegisters().size()) * kPointerSize;
128  // References plus 2 words for SIRT header
129  size_t sirt_size = (ReferenceCount() + 2) * kPointerSize;
130  // Plus return value spill area size
131  return RoundUp(frame_data_size + sirt_size + SizeOfReturnValue(), kStackAlignment);
132}
133
134size_t X86JniCallingConvention::OutArgSize() {
135  return RoundUp(NumberOfOutgoingStackArgs() * kPointerSize, kStackAlignment);
136}
137
138bool X86JniCallingConvention::IsCurrentParamInRegister() {
139  return false;  // Everything is passed by stack.
140}
141
142bool X86JniCallingConvention::IsCurrentParamOnStack() {
143  return true;  // Everything is passed by stack.
144}
145
146ManagedRegister X86JniCallingConvention::CurrentParamRegister() {
147  LOG(FATAL) << "Should not reach here";
148  return ManagedRegister::NoRegister();
149}
150
151FrameOffset X86JniCallingConvention::CurrentParamStackOffset() {
152  return FrameOffset(displacement_.Int32Value() - OutArgSize() + (itr_slots_ * kPointerSize));
153}
154
155size_t X86JniCallingConvention::NumberOfOutgoingStackArgs() {
156  size_t static_args = IsStatic() ? 1 : 0;  // count jclass
157  // regular argument parameters and this
158  size_t param_args = NumArgs() + NumLongOrDoubleArgs();
159  // count JNIEnv* and return pc (pushed after Method*)
160  size_t total_args = static_args + param_args + 2;
161  return total_args;
162}
163
164}  // namespace x86
165}  // namespace art
166