blob: a7a080e99c8af553dd5fdfee70e26c20dc3344ca [file] [log] [blame]
Ian Rogersb033c752011-07-20 12:22:35 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2// Author: irogers@google.com (Ian Rogers)
3
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07004#include "calling_convention.h"
5#include "logging.h"
Ian Rogersb033c752011-07-20 12:22:35 -07006
7namespace art {
8
9ManagedRegister CallingConvention::MethodRegister() {
10 return ManagedRegister::FromCoreRegister(R0);
11}
12
13ManagedRegister CallingConvention::InterproceduralScratchRegister() {
14 return ManagedRegister::FromCoreRegister(R12);
15}
16
17ManagedRegister CallingConvention::ReturnRegister() {
Ian Rogers45a76cb2011-07-21 22:00:15 -070018 const Method *method = GetMethod();
Ian Rogersb033c752011-07-20 12:22:35 -070019 if (GetMethod()->IsReturnAFloat()) {
Carl Shapiroe2d373e2011-07-25 15:20:06 -070020 return ManagedRegister::FromCoreRegister(R0);
Ian Rogers45a76cb2011-07-21 22:00:15 -070021 } else if (GetMethod()->IsReturnADouble()) {
Carl Shapiroe2d373e2011-07-25 15:20:06 -070022 return ManagedRegister::FromRegisterPair(R0_R1);
Ian Rogers45a76cb2011-07-21 22:00:15 -070023 } else if (method->IsReturnALong()) {
Ian Rogersb033c752011-07-20 12:22:35 -070024 return ManagedRegister::FromRegisterPair(R0_R1);
Ian Rogers45a76cb2011-07-21 22:00:15 -070025 } else if (method->IsReturnVoid()) {
26 return ManagedRegister::NoRegister();
Ian Rogersb033c752011-07-20 12:22:35 -070027 } else {
28 return ManagedRegister::FromCoreRegister(R0);
29 }
30}
31
32// Managed runtime calling convention
33
34bool ManagedRuntimeCallingConvention::IsCurrentParamInRegister() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070035 if (itr_slots_ < 3) {
36 return true;
37 }
38 return false; // everything else on the stack
Ian Rogersb033c752011-07-20 12:22:35 -070039}
40
41bool ManagedRuntimeCallingConvention::IsCurrentParamOnStack() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070042 return !IsCurrentParamInRegister();
Ian Rogersb033c752011-07-20 12:22:35 -070043}
44
45static const Register kManagedArgumentRegisters[] = {
46 R1, R2, R3
47};
48ManagedRegister ManagedRuntimeCallingConvention::CurrentParamRegister() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070049 CHECK_LT(itr_slots_, 3u); // Otherwise, should have gone through stack
Carl Shapiroe2d373e2011-07-25 15:20:06 -070050 const Method* method = GetMethod();
Shih-wei Liao5381cf92011-07-27 00:28:04 -070051 if (method->IsParamALongOrDouble(itr_args_)) {
52 if (itr_slots_ == 0) {
53 // return R1 to denote R1_R2
54 return ManagedRegister::FromCoreRegister(kManagedArgumentRegisters
55 [itr_slots_]);
56 } else if (itr_slots_ == 1) {
57 return ManagedRegister::FromRegisterPair(R2_R3);
58 } else {
59 // This is a long/double split between registers and the stack
60 return ManagedRegister::FromCoreRegister(
61 kManagedArgumentRegisters[itr_slots_]);
Carl Shapiroe2d373e2011-07-25 15:20:06 -070062 }
Carl Shapiroe2d373e2011-07-25 15:20:06 -070063 } else {
64 return
Shih-wei Liao5381cf92011-07-27 00:28:04 -070065 ManagedRegister::FromCoreRegister(kManagedArgumentRegisters[itr_slots_]);
Carl Shapiroe2d373e2011-07-25 15:20:06 -070066 }
Ian Rogersb033c752011-07-20 12:22:35 -070067}
68
69FrameOffset ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070070 CHECK_GE(itr_slots_, 3u);
Ian Rogersb033c752011-07-20 12:22:35 -070071 return FrameOffset(displacement_.Int32Value() +
Shih-wei Liao5381cf92011-07-27 00:28:04 -070072 ((itr_slots_ - 3) * kPointerSize));
Ian Rogersb033c752011-07-20 12:22:35 -070073}
74
75// JNI calling convention
76
Carl Shapiroe2d373e2011-07-25 15:20:06 -070077// Will reg be crushed by an outgoing argument?
78bool JniCallingConvention::IsOutArgRegister(ManagedRegister) {
79 // R0 holds the method register and will be crushed by the JNIEnv*
80 return true;
81}
82
Shih-wei Liao5381cf92011-07-27 00:28:04 -070083// JniCallingConvention ABI follows AAPCS
84//
85// In processing each parameter, we know that IsCurrentParamInRegister()
86// or IsCurrentParamOnStack() will be called first.
87// Both functions will ensure that we conform to AAPCS.
88//
Ian Rogersb033c752011-07-20 12:22:35 -070089bool JniCallingConvention::IsCurrentParamInRegister() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070090 // AAPCS processing
91 const Method* method = GetMethod();
92 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(method);
93 if ((itr_args_ >= 2) && method->IsParamALongOrDouble(arg_pos)) {
94 // itr_slots_ needs to be an even number, according to AAPCS.
95 if (itr_slots_ & 0x1u) {
96 itr_slots_++;
97 }
98 }
99
100 return itr_slots_ < 4;
Ian Rogersb033c752011-07-20 12:22:35 -0700101}
102
103bool JniCallingConvention::IsCurrentParamOnStack() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700104 return !IsCurrentParamInRegister();
Ian Rogersb033c752011-07-20 12:22:35 -0700105}
106
107static const Register kJniArgumentRegisters[] = {
108 R0, R1, R2, R3
109};
110ManagedRegister JniCallingConvention::CurrentParamRegister() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700111 CHECK_LT(itr_slots_, 4u);
Carl Shapiroe2d373e2011-07-25 15:20:06 -0700112 const Method* method = GetMethod();
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700113 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(method);
114 if ((itr_args_ >= 2) && method->IsParamALongOrDouble(arg_pos)) {
115 CHECK_EQ(itr_slots_, 2u);
Carl Shapiroe2d373e2011-07-25 15:20:06 -0700116 return ManagedRegister::FromRegisterPair(R2_R3);
117 } else {
118 return
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700119 ManagedRegister::FromCoreRegister(kJniArgumentRegisters[itr_slots_]);
Carl Shapiroe2d373e2011-07-25 15:20:06 -0700120 }
Ian Rogersb033c752011-07-20 12:22:35 -0700121}
122
123FrameOffset JniCallingConvention::CurrentParamStackOffset() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700124 CHECK_GE(itr_slots_, 4u);
Ian Rogersb033c752011-07-20 12:22:35 -0700125 return FrameOffset(displacement_.Int32Value() - OutArgSize()
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700126 + ((itr_slots_ - 4) * kPointerSize));
Ian Rogersb033c752011-07-20 12:22:35 -0700127}
128
129size_t JniCallingConvention::NumberOfOutgoingStackArgs() {
130 return GetMethod()->NumArgs() + GetMethod()->NumLongOrDoubleArgs() - 2;
131}
132
133} // namespace art