blob: da76e177c7c40c3a94118b54aa72376c2523c771 [file] [log] [blame]
Ian Rogersb033c752011-07-20 12:22:35 -07001// Copyright 2011 Google Inc. All Rights Reserved.
Ian Rogersb033c752011-07-20 12:22:35 -07002
Ian Rogers2c8f6532011-09-02 17:16:34 -07003#include "calling_convention_x86.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07004#include "logging.h"
Ian Rogers2c8f6532011-09-02 17:16:34 -07005#include "managed_register_x86.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07006#include "utils.h"
Ian Rogersb033c752011-07-20 12:22:35 -07007
8namespace art {
Ian Rogers2c8f6532011-09-02 17:16:34 -07009namespace x86 {
Ian Rogersb033c752011-07-20 12:22:35 -070010
Ian Rogers2c8f6532011-09-02 17:16:34 -070011// Calling convention
12
13ManagedRegister X86ManagedRuntimeCallingConvention::InterproceduralScratchRegister() {
14 return X86ManagedRegister::FromCpuRegister(ECX);
Ian Rogersb033c752011-07-20 12:22:35 -070015}
16
Ian Rogers2c8f6532011-09-02 17:16:34 -070017ManagedRegister X86JniCallingConvention::InterproceduralScratchRegister() {
18 return X86ManagedRegister::FromCpuRegister(ECX);
Ian Rogersb033c752011-07-20 12:22:35 -070019}
20
Ian Rogersdc51b792011-09-22 20:41:37 -070021ManagedRegister X86JniCallingConvention::ReturnScratchRegister() const {
22 return ManagedRegister::NoRegister(); // No free regs, so assembler uses push/pop
23}
24
Brian Carlstrom3320cf42011-10-04 14:58:28 -070025static ManagedRegister ReturnRegisterForMethod(const Method* method) {
Ian Rogers45a76cb2011-07-21 22:00:15 -070026 if (method->IsReturnAFloatOrDouble()) {
Ian Rogers2c8f6532011-09-02 17:16:34 -070027 return X86ManagedRegister::FromX87Register(ST0);
Ian Rogers45a76cb2011-07-21 22:00:15 -070028 } else if (method->IsReturnALong()) {
Ian Rogers2c8f6532011-09-02 17:16:34 -070029 return X86ManagedRegister::FromRegisterPair(EAX_EDX);
Ian Rogers45a76cb2011-07-21 22:00:15 -070030 } else if (method->IsReturnVoid()) {
31 return ManagedRegister::NoRegister();
Ian Rogersb033c752011-07-20 12:22:35 -070032 } else {
Ian Rogers2c8f6532011-09-02 17:16:34 -070033 return X86ManagedRegister::FromCpuRegister(EAX);
Ian Rogersb033c752011-07-20 12:22:35 -070034 }
35}
36
Ian Rogers2c8f6532011-09-02 17:16:34 -070037ManagedRegister X86ManagedRuntimeCallingConvention::ReturnRegister() {
38 return ReturnRegisterForMethod(GetMethod());
39}
40
41ManagedRegister X86JniCallingConvention::ReturnRegister() {
42 return ReturnRegisterForMethod(GetMethod());
43}
44
Ian Rogersb033c752011-07-20 12:22:35 -070045// Managed runtime calling convention
46
Ian Rogers2c8f6532011-09-02 17:16:34 -070047ManagedRegister X86ManagedRuntimeCallingConvention::MethodRegister() {
Ian Rogers67375ac2011-09-14 00:55:44 -070048 return X86ManagedRegister::FromCpuRegister(EAX);
Ian Rogers2c8f6532011-09-02 17:16:34 -070049}
50
51bool X86ManagedRuntimeCallingConvention::IsCurrentParamInRegister() {
Ian Rogersb033c752011-07-20 12:22:35 -070052 return false; // Everything is passed by stack
53}
54
Ian Rogers2c8f6532011-09-02 17:16:34 -070055bool X86ManagedRuntimeCallingConvention::IsCurrentParamOnStack() {
Ian Rogersb033c752011-07-20 12:22:35 -070056 return true; // Everything is passed by stack
57}
58
Ian Rogers2c8f6532011-09-02 17:16:34 -070059ManagedRegister X86ManagedRuntimeCallingConvention::CurrentParamRegister() {
Ian Rogersb033c752011-07-20 12:22:35 -070060 LOG(FATAL) << "Should not reach here";
61 return ManagedRegister::NoRegister();
62}
63
Ian Rogers2c8f6532011-09-02 17:16:34 -070064FrameOffset X86ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070065 return FrameOffset(displacement_.Int32Value() + // displacement
66 kPointerSize + // Method*
67 (itr_slots_ * kPointerSize)); // offset into in args
Ian Rogersb033c752011-07-20 12:22:35 -070068}
69
70// JNI calling convention
71
Ian Rogersbdb03912011-09-14 00:55:44 -070072std::vector<ManagedRegister> X86JniCallingConvention::callee_save_regs_;
73
Ian Rogers2c8f6532011-09-02 17:16:34 -070074size_t X86JniCallingConvention::FrameSize() {
Ian Rogersdc51b792011-09-22 20:41:37 -070075 // Return address, Method* and local reference segment state
76 size_t frame_data_size = 3 * kPointerSize;
Ian Rogers408f79a2011-08-23 18:22:33 -070077 // References plus 2 words for SIRT header
78 size_t sirt_size = (ReferenceCount() + 2) * kPointerSize;
Ian Rogers0d666d82011-08-14 16:03:46 -070079 // Plus return value spill area size
Ian Rogersdc51b792011-09-22 20:41:37 -070080 return RoundUp(frame_data_size + sirt_size + SizeOfReturnValue(), kStackAlignment);
Ian Rogers0d666d82011-08-14 16:03:46 -070081}
82
Ian Rogers2c8f6532011-09-02 17:16:34 -070083size_t X86JniCallingConvention::OutArgSize() {
Ian Rogers7a99c112011-09-07 12:48:27 -070084 return RoundUp(NumberOfOutgoingStackArgs() * kPointerSize, kStackAlignment);
85}
86
Ian Rogers2c8f6532011-09-02 17:16:34 -070087size_t X86JniCallingConvention::ReturnPcOffset() {
Ian Rogers762400c2011-08-23 12:14:16 -070088 // Return PC is pushed at the top of the frame by the call into the method
89 return FrameSize() - kPointerSize;
90}
91
Ian Rogersad42e132011-09-17 20:23:33 -070092bool X86JniCallingConvention::IsMethodRegisterClobberedPreCall() {
Ian Rogers67375ac2011-09-14 00:55:44 -070093 return GetMethod()->IsSynchronized(); // Monitor enter crushes the method register
Carl Shapiroe2d373e2011-07-25 15:20:06 -070094}
95
Ian Rogers2c8f6532011-09-02 17:16:34 -070096bool X86JniCallingConvention::IsCurrentParamInRegister() {
Ian Rogersb033c752011-07-20 12:22:35 -070097 return false; // Everything is passed by stack
98}
99
Ian Rogers2c8f6532011-09-02 17:16:34 -0700100bool X86JniCallingConvention::IsCurrentParamOnStack() {
Ian Rogersb033c752011-07-20 12:22:35 -0700101 return true; // Everything is passed by stack
102}
103
Ian Rogers2c8f6532011-09-02 17:16:34 -0700104ManagedRegister X86JniCallingConvention::CurrentParamRegister() {
Ian Rogersb033c752011-07-20 12:22:35 -0700105 LOG(FATAL) << "Should not reach here";
106 return ManagedRegister::NoRegister();
107}
108
Ian Rogers2c8f6532011-09-02 17:16:34 -0700109FrameOffset X86JniCallingConvention::CurrentParamStackOffset() {
Ian Rogersb033c752011-07-20 12:22:35 -0700110 return FrameOffset(displacement_.Int32Value() - OutArgSize() +
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700111 (itr_slots_ * kPointerSize));
Ian Rogersb033c752011-07-20 12:22:35 -0700112}
113
Ian Rogers2c8f6532011-09-02 17:16:34 -0700114size_t X86JniCallingConvention::NumberOfOutgoingStackArgs() {
Ian Rogers7a99c112011-09-07 12:48:27 -0700115 size_t static_args = GetMethod()->IsStatic() ? 1 : 0; // count jclass
116 // regular argument parameters and this
117 size_t param_args = GetMethod()->NumArgs() +
118 GetMethod()->NumLongOrDoubleArgs();
Ian Rogersbdb03912011-09-14 00:55:44 -0700119 return static_args + param_args + 2; // count JNIEnv* and return pc (pushed after Method*)
Ian Rogersb033c752011-07-20 12:22:35 -0700120}
121
Ian Rogers2c8f6532011-09-02 17:16:34 -0700122} // namespace x86
Ian Rogersb033c752011-07-20 12:22:35 -0700123} // namespace art