blob: f93dc9b96f58c10f68de43973eeb4e10d0bab9b8 [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() {
35 return itr_position_ < 3;
36}
37
38bool ManagedRuntimeCallingConvention::IsCurrentParamOnStack() {
39 return itr_position_ >= 3;
40}
41
42static const Register kManagedArgumentRegisters[] = {
43 R1, R2, R3
44};
45ManagedRegister ManagedRuntimeCallingConvention::CurrentParamRegister() {
46 CHECK_LT(itr_position_, 3u);
Carl Shapiroe2d373e2011-07-25 15:20:06 -070047 const Method* method = GetMethod();
48 if (method->IsParamALongOrDouble(itr_position_)) {
49 // TODO: handle a long/double split between registers and the stack, also
50 // itr_position_ 0
51 if (itr_position_ != 1u) {
52 LOG(WARNING) << "Unimplemented";
53 }
54 return ManagedRegister::FromRegisterPair(R2_R3);
55 } else {
56 return
57 ManagedRegister::FromCoreRegister(kManagedArgumentRegisters[itr_position_]);
58 }
Ian Rogersb033c752011-07-20 12:22:35 -070059}
60
61FrameOffset ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
62 CHECK_GE(itr_position_, 3u);
63 return FrameOffset(displacement_.Int32Value() +
64 ((itr_position_ + itr_longs_and_doubles_ - 3) * kPointerSize));
65}
66
67// JNI calling convention
68
Carl Shapiroe2d373e2011-07-25 15:20:06 -070069// Will reg be crushed by an outgoing argument?
70bool JniCallingConvention::IsOutArgRegister(ManagedRegister) {
71 // R0 holds the method register and will be crushed by the JNIEnv*
72 return true;
73}
74
Ian Rogersb033c752011-07-20 12:22:35 -070075bool JniCallingConvention::IsCurrentParamInRegister() {
Carl Shapiroe2d373e2011-07-25 15:20:06 -070076 return (itr_position_ + itr_longs_and_doubles_) < 4;
Ian Rogersb033c752011-07-20 12:22:35 -070077}
78
79bool JniCallingConvention::IsCurrentParamOnStack() {
Carl Shapiroe2d373e2011-07-25 15:20:06 -070080 return (itr_position_ + itr_longs_and_doubles_) >= 4;
Ian Rogersb033c752011-07-20 12:22:35 -070081}
82
83static const Register kJniArgumentRegisters[] = {
84 R0, R1, R2, R3
85};
86ManagedRegister JniCallingConvention::CurrentParamRegister() {
Carl Shapiroe2d373e2011-07-25 15:20:06 -070087 CHECK_LT(itr_position_ + itr_longs_and_doubles_, 4u);
88 const Method* method = GetMethod();
89 int arg_pos = itr_position_ - (method->IsStatic() ? 2 : 1);
90 if ((itr_position_ >= 2) && method->IsParamALongOrDouble(arg_pos)) {
91 // TODO: handle a long/double split between registers and the stack
92 if (itr_position_ != 2u) {
93 LOG(WARNING) << "Unimplemented";
94 }
95 return ManagedRegister::FromRegisterPair(R2_R3);
96 } else {
97 return
98 ManagedRegister::FromCoreRegister(kJniArgumentRegisters[itr_position_]);
99 }
Ian Rogersb033c752011-07-20 12:22:35 -0700100}
101
102FrameOffset JniCallingConvention::CurrentParamStackOffset() {
Carl Shapiroe2d373e2011-07-25 15:20:06 -0700103 CHECK_GE(itr_position_ + itr_longs_and_doubles_, 4u);
Ian Rogersb033c752011-07-20 12:22:35 -0700104 return FrameOffset(displacement_.Int32Value() - OutArgSize()
105 + ((itr_position_ + itr_longs_and_doubles_ - 4) * kPointerSize));
106}
107
108size_t JniCallingConvention::NumberOfOutgoingStackArgs() {
109 return GetMethod()->NumArgs() + GetMethod()->NumLongOrDoubleArgs() - 2;
110}
111
112} // namespace art