blob: 6434005ddaea288357a385f951a5a218d1af113e [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
Andreas Gampe542451c2016-07-26 09:02:02 -070023#include "base/enums.h"
Andreas Gampebda1d602016-08-29 17:43:45 -070024#include "base/macros.h"
Ian Rogersd582fa42014-11-05 23:46:43 -080025
26namespace art {
27
Vladimir Marko33bff252017-11-01 14:35:42 +000028enum class InstructionSet {
Ian Rogersd582fa42014-11-05 23:46:43 -080029 kNone,
30 kArm,
31 kArm64,
32 kThumb2,
33 kX86,
34 kX86_64,
35 kMips,
Vladimir Marko33bff252017-11-01 14:35:42 +000036 kMips64,
37 kLast = kMips64
Ian Rogersd582fa42014-11-05 23:46:43 -080038};
39std::ostream& operator<<(std::ostream& os, const InstructionSet& rhs);
40
41#if defined(__arm__)
Vladimir Marko33bff252017-11-01 14:35:42 +000042static constexpr InstructionSet kRuntimeISA = InstructionSet::kArm;
Ian Rogersd582fa42014-11-05 23:46:43 -080043#elif defined(__aarch64__)
Vladimir Marko33bff252017-11-01 14:35:42 +000044static constexpr InstructionSet kRuntimeISA = InstructionSet::kArm64;
Andreas Gampe57b34292015-01-14 15:45:59 -080045#elif defined(__mips__) && !defined(__LP64__)
Vladimir Marko33bff252017-11-01 14:35:42 +000046static constexpr InstructionSet kRuntimeISA = InstructionSet::kMips;
Andreas Gampe57b34292015-01-14 15:45:59 -080047#elif defined(__mips__) && defined(__LP64__)
Vladimir Marko33bff252017-11-01 14:35:42 +000048static constexpr InstructionSet kRuntimeISA = InstructionSet::kMips64;
Ian Rogersd582fa42014-11-05 23:46:43 -080049#elif defined(__i386__)
Vladimir Marko33bff252017-11-01 14:35:42 +000050static constexpr InstructionSet kRuntimeISA = InstructionSet::kX86;
Ian Rogersd582fa42014-11-05 23:46:43 -080051#elif defined(__x86_64__)
Vladimir Marko33bff252017-11-01 14:35:42 +000052static constexpr InstructionSet kRuntimeISA = InstructionSet::kX86_64;
Ian Rogersd582fa42014-11-05 23:46:43 -080053#else
Vladimir Marko33bff252017-11-01 14:35:42 +000054static constexpr InstructionSet kRuntimeISA = InstructionSet::kNone;
Ian Rogersd582fa42014-11-05 23:46:43 -080055#endif
56
57// Architecture-specific pointer sizes
Andreas Gampe542451c2016-07-26 09:02:02 -070058static constexpr PointerSize kArmPointerSize = PointerSize::k32;
59static constexpr PointerSize kArm64PointerSize = PointerSize::k64;
60static constexpr PointerSize kMipsPointerSize = PointerSize::k32;
61static constexpr PointerSize kMips64PointerSize = PointerSize::k64;
62static constexpr PointerSize kX86PointerSize = PointerSize::k32;
63static constexpr PointerSize kX86_64PointerSize = PointerSize::k64;
Ian Rogersd582fa42014-11-05 23:46:43 -080064
65// ARM instruction alignment. ARM processors require code to be 4-byte aligned,
66// but ARM ELF requires 8..
67static constexpr size_t kArmAlignment = 8;
68
69// ARM64 instruction alignment. This is the recommended alignment for maximum performance.
70static constexpr size_t kArm64Alignment = 16;
71
Alexey Frunze85885fe2017-02-01 16:25:37 -080072// MIPS instruction alignment. MIPS processors require code to be 4-byte aligned,
73// but 64-bit literals must be 8-byte aligned.
Ian Rogersd582fa42014-11-05 23:46:43 -080074static constexpr size_t kMipsAlignment = 8;
75
76// X86 instruction alignment. This is the recommended alignment for maximum performance.
77static constexpr size_t kX86Alignment = 16;
78
Mathieu Chartiera2f526f2017-01-19 14:48:48 -080079// Different than code alignment since code alignment is only first instruction of method.
80static constexpr size_t kThumb2InstructionAlignment = 2;
81static constexpr size_t kArm64InstructionAlignment = 4;
82static constexpr size_t kX86InstructionAlignment = 1;
83static constexpr size_t kX86_64InstructionAlignment = 1;
Alexey Frunze85885fe2017-02-01 16:25:37 -080084static constexpr size_t kMipsInstructionAlignment = 4;
85static constexpr size_t kMips64InstructionAlignment = 4;
Mathieu Chartiera2f526f2017-01-19 14:48:48 -080086
Ian Rogersd582fa42014-11-05 23:46:43 -080087const char* GetInstructionSetString(InstructionSet isa);
88
89// Note: Returns kNone when the string cannot be parsed to a known value.
90InstructionSet GetInstructionSetFromString(const char* instruction_set);
91
Andreas Gampe6f611412015-01-21 22:25:24 -080092InstructionSet GetInstructionSetFromELF(uint16_t e_machine, uint32_t e_flags);
93
Andreas Gampebda1d602016-08-29 17:43:45 -070094// Fatal logging out of line to keep the header clean of logging.h.
95NO_RETURN void InstructionSetAbort(InstructionSet isa);
96
Andreas Gampe705543e2017-05-24 13:20:49 -070097constexpr PointerSize GetInstructionSetPointerSize(InstructionSet isa) {
Ian Rogersd582fa42014-11-05 23:46:43 -080098 switch (isa) {
Vladimir Marko33bff252017-11-01 14:35:42 +000099 case InstructionSet::kArm:
Ian Rogersd582fa42014-11-05 23:46:43 -0800100 // Fall-through.
Vladimir Marko33bff252017-11-01 14:35:42 +0000101 case InstructionSet::kThumb2:
Ian Rogersd582fa42014-11-05 23:46:43 -0800102 return kArmPointerSize;
Vladimir Marko33bff252017-11-01 14:35:42 +0000103 case InstructionSet::kArm64:
Ian Rogersd582fa42014-11-05 23:46:43 -0800104 return kArm64PointerSize;
Vladimir Marko33bff252017-11-01 14:35:42 +0000105 case InstructionSet::kX86:
Ian Rogersd582fa42014-11-05 23:46:43 -0800106 return kX86PointerSize;
Vladimir Marko33bff252017-11-01 14:35:42 +0000107 case InstructionSet::kX86_64:
Ian Rogersd582fa42014-11-05 23:46:43 -0800108 return kX86_64PointerSize;
Vladimir Marko33bff252017-11-01 14:35:42 +0000109 case InstructionSet::kMips:
Ian Rogersd582fa42014-11-05 23:46:43 -0800110 return kMipsPointerSize;
Vladimir Marko33bff252017-11-01 14:35:42 +0000111 case InstructionSet::kMips64:
Ian Rogersd582fa42014-11-05 23:46:43 -0800112 return kMips64PointerSize;
Andreas Gampe705543e2017-05-24 13:20:49 -0700113
Vladimir Marko33bff252017-11-01 14:35:42 +0000114 case InstructionSet::kNone:
Andreas Gampe705543e2017-05-24 13:20:49 -0700115 break;
Ian Rogersd582fa42014-11-05 23:46:43 -0800116 }
Andreas Gampe705543e2017-05-24 13:20:49 -0700117 InstructionSetAbort(isa);
Ian Rogersd582fa42014-11-05 23:46:43 -0800118}
119
Andreas Gampe705543e2017-05-24 13:20:49 -0700120constexpr size_t GetInstructionSetInstructionAlignment(InstructionSet isa) {
121 switch (isa) {
Vladimir Marko33bff252017-11-01 14:35:42 +0000122 case InstructionSet::kArm:
Andreas Gampe705543e2017-05-24 13:20:49 -0700123 // Fall-through.
Vladimir Marko33bff252017-11-01 14:35:42 +0000124 case InstructionSet::kThumb2:
Andreas Gampe705543e2017-05-24 13:20:49 -0700125 return kThumb2InstructionAlignment;
Vladimir Marko33bff252017-11-01 14:35:42 +0000126 case InstructionSet::kArm64:
Andreas Gampe705543e2017-05-24 13:20:49 -0700127 return kArm64InstructionAlignment;
Vladimir Marko33bff252017-11-01 14:35:42 +0000128 case InstructionSet::kX86:
Andreas Gampe705543e2017-05-24 13:20:49 -0700129 return kX86InstructionAlignment;
Vladimir Marko33bff252017-11-01 14:35:42 +0000130 case InstructionSet::kX86_64:
Andreas Gampe705543e2017-05-24 13:20:49 -0700131 return kX86_64InstructionAlignment;
Vladimir Marko33bff252017-11-01 14:35:42 +0000132 case InstructionSet::kMips:
Andreas Gampe705543e2017-05-24 13:20:49 -0700133 return kMipsInstructionAlignment;
Vladimir Marko33bff252017-11-01 14:35:42 +0000134 case InstructionSet::kMips64:
Andreas Gampe705543e2017-05-24 13:20:49 -0700135 return kMips64InstructionAlignment;
136
Vladimir Marko33bff252017-11-01 14:35:42 +0000137 case InstructionSet::kNone:
Andreas Gampe705543e2017-05-24 13:20:49 -0700138 break;
139 }
140 InstructionSetAbort(isa);
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800141}
142
Andreas Gampe705543e2017-05-24 13:20:49 -0700143constexpr bool IsValidInstructionSet(InstructionSet isa) {
Vladimir Marko09d09432015-09-08 13:47:48 +0100144 switch (isa) {
Vladimir Marko33bff252017-11-01 14:35:42 +0000145 case InstructionSet::kArm:
146 case InstructionSet::kThumb2:
147 case InstructionSet::kArm64:
148 case InstructionSet::kX86:
149 case InstructionSet::kX86_64:
150 case InstructionSet::kMips:
151 case InstructionSet::kMips64:
Vladimir Marko09d09432015-09-08 13:47:48 +0100152 return true;
Andreas Gampe705543e2017-05-24 13:20:49 -0700153
Vladimir Marko33bff252017-11-01 14:35:42 +0000154 case InstructionSet::kNone:
Vladimir Marko09d09432015-09-08 13:47:48 +0100155 return false;
156 }
Andreas Gampe705543e2017-05-24 13:20:49 -0700157 return false;
Vladimir Marko09d09432015-09-08 13:47:48 +0100158}
159
Ian Rogersd582fa42014-11-05 23:46:43 -0800160size_t GetInstructionSetAlignment(InstructionSet isa);
161
Andreas Gampe705543e2017-05-24 13:20:49 -0700162constexpr bool Is64BitInstructionSet(InstructionSet isa) {
Ian Rogersd582fa42014-11-05 23:46:43 -0800163 switch (isa) {
Vladimir Marko33bff252017-11-01 14:35:42 +0000164 case InstructionSet::kArm:
165 case InstructionSet::kThumb2:
166 case InstructionSet::kX86:
167 case InstructionSet::kMips:
Ian Rogersd582fa42014-11-05 23:46:43 -0800168 return false;
169
Vladimir Marko33bff252017-11-01 14:35:42 +0000170 case InstructionSet::kArm64:
171 case InstructionSet::kX86_64:
172 case InstructionSet::kMips64:
Ian Rogersd582fa42014-11-05 23:46:43 -0800173 return true;
174
Vladimir Marko33bff252017-11-01 14:35:42 +0000175 case InstructionSet::kNone:
Andreas Gampe705543e2017-05-24 13:20:49 -0700176 break;
Ian Rogersd582fa42014-11-05 23:46:43 -0800177 }
Andreas Gampe705543e2017-05-24 13:20:49 -0700178 InstructionSetAbort(isa);
Ian Rogersd582fa42014-11-05 23:46:43 -0800179}
180
Andreas Gampe705543e2017-05-24 13:20:49 -0700181constexpr PointerSize InstructionSetPointerSize(InstructionSet isa) {
Andreas Gampe542451c2016-07-26 09:02:02 -0700182 return Is64BitInstructionSet(isa) ? PointerSize::k64 : PointerSize::k32;
Mathieu Chartier2d721012014-11-10 11:08:06 -0800183}
184
Andreas Gampe705543e2017-05-24 13:20:49 -0700185constexpr size_t GetBytesPerGprSpillLocation(InstructionSet isa) {
Ian Rogersd582fa42014-11-05 23:46:43 -0800186 switch (isa) {
Vladimir Marko33bff252017-11-01 14:35:42 +0000187 case InstructionSet::kArm:
Ian Rogersd582fa42014-11-05 23:46:43 -0800188 // Fall-through.
Vladimir Marko33bff252017-11-01 14:35:42 +0000189 case InstructionSet::kThumb2:
Ian Rogersd582fa42014-11-05 23:46:43 -0800190 return 4;
Vladimir Marko33bff252017-11-01 14:35:42 +0000191 case InstructionSet::kArm64:
Ian Rogersd582fa42014-11-05 23:46:43 -0800192 return 8;
Vladimir Marko33bff252017-11-01 14:35:42 +0000193 case InstructionSet::kX86:
Ian Rogersd582fa42014-11-05 23:46:43 -0800194 return 4;
Vladimir Marko33bff252017-11-01 14:35:42 +0000195 case InstructionSet::kX86_64:
Ian Rogersd582fa42014-11-05 23:46:43 -0800196 return 8;
Vladimir Marko33bff252017-11-01 14:35:42 +0000197 case InstructionSet::kMips:
Ian Rogersd582fa42014-11-05 23:46:43 -0800198 return 4;
Vladimir Marko33bff252017-11-01 14:35:42 +0000199 case InstructionSet::kMips64:
Andreas Gampe57b34292015-01-14 15:45:59 -0800200 return 8;
Andreas Gampebda1d602016-08-29 17:43:45 -0700201
Vladimir Marko33bff252017-11-01 14:35:42 +0000202 case InstructionSet::kNone:
Andreas Gampe705543e2017-05-24 13:20:49 -0700203 break;
Ian Rogersd582fa42014-11-05 23:46:43 -0800204 }
Andreas Gampe705543e2017-05-24 13:20:49 -0700205 InstructionSetAbort(isa);
Ian Rogersd582fa42014-11-05 23:46:43 -0800206}
207
Andreas Gampe705543e2017-05-24 13:20:49 -0700208constexpr size_t GetBytesPerFprSpillLocation(InstructionSet isa) {
Ian Rogersd582fa42014-11-05 23:46:43 -0800209 switch (isa) {
Vladimir Marko33bff252017-11-01 14:35:42 +0000210 case InstructionSet::kArm:
Ian Rogersd582fa42014-11-05 23:46:43 -0800211 // Fall-through.
Vladimir Marko33bff252017-11-01 14:35:42 +0000212 case InstructionSet::kThumb2:
Ian Rogersd582fa42014-11-05 23:46:43 -0800213 return 4;
Vladimir Marko33bff252017-11-01 14:35:42 +0000214 case InstructionSet::kArm64:
Ian Rogersd582fa42014-11-05 23:46:43 -0800215 return 8;
Vladimir Marko33bff252017-11-01 14:35:42 +0000216 case InstructionSet::kX86:
Ian Rogersd582fa42014-11-05 23:46:43 -0800217 return 8;
Vladimir Marko33bff252017-11-01 14:35:42 +0000218 case InstructionSet::kX86_64:
Ian Rogersd582fa42014-11-05 23:46:43 -0800219 return 8;
Vladimir Marko33bff252017-11-01 14:35:42 +0000220 case InstructionSet::kMips:
Ian Rogersd582fa42014-11-05 23:46:43 -0800221 return 4;
Vladimir Marko33bff252017-11-01 14:35:42 +0000222 case InstructionSet::kMips64:
Andreas Gampe57b34292015-01-14 15:45:59 -0800223 return 8;
Andreas Gampebda1d602016-08-29 17:43:45 -0700224
Vladimir Marko33bff252017-11-01 14:35:42 +0000225 case InstructionSet::kNone:
Andreas Gampe705543e2017-05-24 13:20:49 -0700226 break;
Ian Rogersd582fa42014-11-05 23:46:43 -0800227 }
Andreas Gampe705543e2017-05-24 13:20:49 -0700228 InstructionSetAbort(isa);
Ian Rogersd582fa42014-11-05 23:46:43 -0800229}
230
231size_t GetStackOverflowReservedBytes(InstructionSet isa);
232
233// The following definitions create return types for two word-sized entities that will be passed
234// in registers so that memory operations for the interface trampolines can be avoided. The entities
235// are the resolved method and the pointer to the code to be invoked.
236//
237// On x86, ARM32 and MIPS, this is given for a *scalar* 64bit value. The definition thus *must* be
238// uint64_t or long long int.
239//
Andreas Gampe57b34292015-01-14 15:45:59 -0800240// On x86_64, ARM64 and MIPS64, structs are decomposed for allocation, so we can create a structs of
241// two size_t-sized values.
Ian Rogersd582fa42014-11-05 23:46:43 -0800242//
243// We need two operations:
244//
245// 1) A flag value that signals failure. The assembly stubs expect the lower part to be "0".
246// GetTwoWordFailureValue() will return a value that has lower part == 0.
247//
248// 2) A value that combines two word-sized values.
249// GetTwoWordSuccessValue() constructs this.
250//
251// IMPORTANT: If you use this to transfer object pointers, it is your responsibility to ensure
252// that the object does not move or the value is updated. Simple use of this is NOT SAFE
253// when the garbage collector can move objects concurrently. Ensure that required locks
254// are held when using!
255
Andreas Gampe57b34292015-01-14 15:45:59 -0800256#if defined(__i386__) || defined(__arm__) || (defined(__mips__) && !defined(__LP64__))
Ian Rogersd582fa42014-11-05 23:46:43 -0800257typedef uint64_t TwoWordReturn;
258
259// Encodes method_ptr==nullptr and code_ptr==nullptr
260static inline constexpr TwoWordReturn GetTwoWordFailureValue() {
261 return 0;
262}
263
264// Use the lower 32b for the method pointer and the upper 32b for the code pointer.
Andreas Gampe705543e2017-05-24 13:20:49 -0700265static inline constexpr TwoWordReturn GetTwoWordSuccessValue(uintptr_t hi, uintptr_t lo) {
Ian Rogersd582fa42014-11-05 23:46:43 -0800266 static_assert(sizeof(uint32_t) == sizeof(uintptr_t), "Unexpected size difference");
267 uint32_t lo32 = lo;
268 uint64_t hi64 = static_cast<uint64_t>(hi);
269 return ((hi64 << 32) | lo32);
270}
271
Andreas Gampe57b34292015-01-14 15:45:59 -0800272#elif defined(__x86_64__) || defined(__aarch64__) || (defined(__mips__) && defined(__LP64__))
Andreas Gampe705543e2017-05-24 13:20:49 -0700273
274// Note: TwoWordReturn can't be constexpr for 64-bit targets. We'd need a constexpr constructor,
275// which would violate C-linkage in the entrypoint functions.
276
Ian Rogersd582fa42014-11-05 23:46:43 -0800277struct TwoWordReturn {
278 uintptr_t lo;
279 uintptr_t hi;
280};
281
282// Encodes method_ptr==nullptr. Leaves random value in code pointer.
283static inline TwoWordReturn GetTwoWordFailureValue() {
284 TwoWordReturn ret;
285 ret.lo = 0;
286 return ret;
287}
288
289// Write values into their respective members.
290static inline TwoWordReturn GetTwoWordSuccessValue(uintptr_t hi, uintptr_t lo) {
291 TwoWordReturn ret;
292 ret.lo = lo;
293 ret.hi = hi;
294 return ret;
295}
296#else
297#error "Unsupported architecture"
298#endif
299
300} // namespace art
301
302#endif // ART_RUNTIME_ARCH_INSTRUCTION_SET_H_