blob: e4138800948f57065be5934f01c930926fff06f0 [file] [log] [blame]
Ian Rogersd582fa42014-11-05 23:46:43 -08001/*
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#ifndef ART_RUNTIME_ARCH_INSTRUCTION_SET_H_
18#define ART_RUNTIME_ARCH_INSTRUCTION_SET_H_
19
20#include <iosfwd>
21#include <string>
22
23#include "base/logging.h" // Logging is required for FATAL in the helper functions.
24
25namespace art {
26
27enum InstructionSet {
28 kNone,
29 kArm,
30 kArm64,
31 kThumb2,
32 kX86,
33 kX86_64,
34 kMips,
35 kMips64
36};
37std::ostream& operator<<(std::ostream& os, const InstructionSet& rhs);
38
39#if defined(__arm__)
40static constexpr InstructionSet kRuntimeISA = kArm;
41#elif defined(__aarch64__)
42static constexpr InstructionSet kRuntimeISA = kArm64;
43#elif defined(__mips__)
44static constexpr InstructionSet kRuntimeISA = kMips;
45#elif defined(__i386__)
46static constexpr InstructionSet kRuntimeISA = kX86;
47#elif defined(__x86_64__)
48static constexpr InstructionSet kRuntimeISA = kX86_64;
49#else
50static constexpr InstructionSet kRuntimeISA = kNone;
51#endif
52
53// Architecture-specific pointer sizes
54static constexpr size_t kArmPointerSize = 4;
55static constexpr size_t kArm64PointerSize = 8;
56static constexpr size_t kMipsPointerSize = 4;
57static constexpr size_t kMips64PointerSize = 8;
58static constexpr size_t kX86PointerSize = 4;
59static constexpr size_t kX86_64PointerSize = 8;
60
61// ARM instruction alignment. ARM processors require code to be 4-byte aligned,
62// but ARM ELF requires 8..
63static constexpr size_t kArmAlignment = 8;
64
65// ARM64 instruction alignment. This is the recommended alignment for maximum performance.
66static constexpr size_t kArm64Alignment = 16;
67
68// MIPS instruction alignment. MIPS processors require code to be 4-byte aligned.
69// TODO: Can this be 4?
70static constexpr size_t kMipsAlignment = 8;
71
72// X86 instruction alignment. This is the recommended alignment for maximum performance.
73static constexpr size_t kX86Alignment = 16;
74
75
76const char* GetInstructionSetString(InstructionSet isa);
77
78// Note: Returns kNone when the string cannot be parsed to a known value.
79InstructionSet GetInstructionSetFromString(const char* instruction_set);
80
81static inline size_t GetInstructionSetPointerSize(InstructionSet isa) {
82 switch (isa) {
83 case kArm:
84 // Fall-through.
85 case kThumb2:
86 return kArmPointerSize;
87 case kArm64:
88 return kArm64PointerSize;
89 case kX86:
90 return kX86PointerSize;
91 case kX86_64:
92 return kX86_64PointerSize;
93 case kMips:
94 return kMipsPointerSize;
95 case kMips64:
96 return kMips64PointerSize;
97 case kNone:
98 LOG(FATAL) << "ISA kNone does not have pointer size.";
99 UNREACHABLE();
100 default:
101 LOG(FATAL) << "Unknown ISA " << isa;
102 UNREACHABLE();
103 }
104}
105
106size_t GetInstructionSetAlignment(InstructionSet isa);
107
108static inline bool Is64BitInstructionSet(InstructionSet isa) {
109 switch (isa) {
110 case kArm:
111 case kThumb2:
112 case kX86:
113 case kMips:
114 return false;
115
116 case kArm64:
117 case kX86_64:
118 case kMips64:
119 return true;
120
121 case kNone:
122 LOG(FATAL) << "ISA kNone does not have bit width.";
123 UNREACHABLE();
124 default:
125 LOG(FATAL) << "Unknown ISA " << isa;
126 UNREACHABLE();
127 }
128}
129
Mathieu Chartier2d721012014-11-10 11:08:06 -0800130static inline size_t InstructionSetPointerSize(InstructionSet isa) {
131 return Is64BitInstructionSet(isa) ? 8U : 4U;
132}
133
Ian Rogersd582fa42014-11-05 23:46:43 -0800134static inline size_t GetBytesPerGprSpillLocation(InstructionSet isa) {
135 switch (isa) {
136 case kArm:
137 // Fall-through.
138 case kThumb2:
139 return 4;
140 case kArm64:
141 return 8;
142 case kX86:
143 return 4;
144 case kX86_64:
145 return 8;
146 case kMips:
147 return 4;
148 case kNone:
149 LOG(FATAL) << "ISA kNone does not have spills.";
150 UNREACHABLE();
151 default:
152 LOG(FATAL) << "Unknown ISA " << isa;
153 UNREACHABLE();
154 }
155}
156
157static inline size_t GetBytesPerFprSpillLocation(InstructionSet isa) {
158 switch (isa) {
159 case kArm:
160 // Fall-through.
161 case kThumb2:
162 return 4;
163 case kArm64:
164 return 8;
165 case kX86:
166 return 8;
167 case kX86_64:
168 return 8;
169 case kMips:
170 return 4;
171 case kNone:
172 LOG(FATAL) << "ISA kNone does not have spills.";
173 UNREACHABLE();
174 default:
175 LOG(FATAL) << "Unknown ISA " << isa;
176 UNREACHABLE();
177 }
178}
179
180size_t GetStackOverflowReservedBytes(InstructionSet isa);
181
182// The following definitions create return types for two word-sized entities that will be passed
183// in registers so that memory operations for the interface trampolines can be avoided. The entities
184// are the resolved method and the pointer to the code to be invoked.
185//
186// On x86, ARM32 and MIPS, this is given for a *scalar* 64bit value. The definition thus *must* be
187// uint64_t or long long int.
188//
189// On x86_64 and ARM64, structs are decomposed for allocation, so we can create a structs of two
190// size_t-sized values.
191//
192// We need two operations:
193//
194// 1) A flag value that signals failure. The assembly stubs expect the lower part to be "0".
195// GetTwoWordFailureValue() will return a value that has lower part == 0.
196//
197// 2) A value that combines two word-sized values.
198// GetTwoWordSuccessValue() constructs this.
199//
200// IMPORTANT: If you use this to transfer object pointers, it is your responsibility to ensure
201// that the object does not move or the value is updated. Simple use of this is NOT SAFE
202// when the garbage collector can move objects concurrently. Ensure that required locks
203// are held when using!
204
205#if defined(__i386__) || defined(__arm__) || defined(__mips__)
206typedef uint64_t TwoWordReturn;
207
208// Encodes method_ptr==nullptr and code_ptr==nullptr
209static inline constexpr TwoWordReturn GetTwoWordFailureValue() {
210 return 0;
211}
212
213// Use the lower 32b for the method pointer and the upper 32b for the code pointer.
214static inline TwoWordReturn GetTwoWordSuccessValue(uintptr_t hi, uintptr_t lo) {
215 static_assert(sizeof(uint32_t) == sizeof(uintptr_t), "Unexpected size difference");
216 uint32_t lo32 = lo;
217 uint64_t hi64 = static_cast<uint64_t>(hi);
218 return ((hi64 << 32) | lo32);
219}
220
221#elif defined(__x86_64__) || defined(__aarch64__)
222struct TwoWordReturn {
223 uintptr_t lo;
224 uintptr_t hi;
225};
226
227// Encodes method_ptr==nullptr. Leaves random value in code pointer.
228static inline TwoWordReturn GetTwoWordFailureValue() {
229 TwoWordReturn ret;
230 ret.lo = 0;
231 return ret;
232}
233
234// Write values into their respective members.
235static inline TwoWordReturn GetTwoWordSuccessValue(uintptr_t hi, uintptr_t lo) {
236 TwoWordReturn ret;
237 ret.lo = lo;
238 ret.hi = hi;
239 return ret;
240}
241#else
242#error "Unsupported architecture"
243#endif
244
245} // namespace art
246
247#endif // ART_RUNTIME_ARCH_INSTRUCTION_SET_H_