blob: 67e7100873779fe74fb2da856ab0283b90ae8461 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -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 */
Ian Rogersb033c752011-07-20 12:22:35 -070016
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_INSTRUCTION_SET_H_
18#define ART_RUNTIME_INSTRUCTION_SET_H_
Ian Rogersb033c752011-07-20 12:22:35 -070019
Ian Rogersc8b306f2012-02-17 21:34:44 -080020#include <iosfwd>
Dave Allison70202782013-10-22 17:52:19 -070021#include <string>
22
Alexei Zavjalov41c507a2014-05-15 16:02:46 +070023#include "base/logging.h" // Logging is required for FATAL in the helper functions.
Dave Allison70202782013-10-22 17:52:19 -070024#include "base/macros.h"
Ian Rogersc8b306f2012-02-17 21:34:44 -080025
buzbeec143c552011-08-20 17:38:58 -070026namespace art {
27
28enum InstructionSet {
29 kNone,
30 kArm,
Serban Constantinescued8dd492014-02-11 14:15:10 +000031 kArm64,
buzbeec143c552011-08-20 17:38:58 -070032 kThumb2,
Shih-wei Liao6edfde42012-03-01 15:49:12 -080033 kX86,
Ian Rogersef7d42f2014-01-06 12:55:46 -080034 kX86_64,
Shih-wei Liao6edfde42012-03-01 15:49:12 -080035 kMips
buzbeec143c552011-08-20 17:38:58 -070036};
Ian Rogers8afeb852014-04-02 14:55:49 -070037std::ostream& operator<<(std::ostream& os, const InstructionSet& rhs);
buzbeec143c552011-08-20 17:38:58 -070038
Alexei Zavjalov41c507a2014-05-15 16:02:46 +070039// Architecture-specific pointer sizes
40static constexpr size_t kArmPointerSize = 4;
41static constexpr size_t kArm64PointerSize = 8;
42static constexpr size_t kMipsPointerSize = 4;
43static constexpr size_t kX86PointerSize = 4;
44static constexpr size_t kX86_64PointerSize = 8;
45
46// ARM instruction alignment. ARM processors require code to be 4-byte aligned,
47// but ARM ELF requires 8..
48static constexpr size_t kArmAlignment = 8;
49
50// ARM64 instruction alignment. This is the recommended alignment for maximum performance.
51static constexpr size_t kArm64Alignment = 16;
52
53// MIPS instruction alignment. MIPS processors require code to be 4-byte aligned.
54// TODO: Can this be 4?
55static constexpr size_t kMipsAlignment = 8;
56
57// X86 instruction alignment. This is the recommended alignment for maximum performance.
58static constexpr size_t kX86Alignment = 16;
59
60
Brian Carlstrom2afe4942014-05-19 10:25:33 -070061const char* GetInstructionSetString(InstructionSet isa);
Narayan Kamath11d9f062014-04-23 20:24:57 +010062InstructionSet GetInstructionSetFromString(const char* instruction_set);
63
Alexei Zavjalov41c507a2014-05-15 16:02:46 +070064static inline size_t GetInstructionSetPointerSize(InstructionSet isa) {
65 switch (isa) {
66 case kArm:
67 // Fall-through.
68 case kThumb2:
69 return kArmPointerSize;
70 case kArm64:
71 return kArm64PointerSize;
72 case kX86:
73 return kX86PointerSize;
74 case kX86_64:
75 return kX86_64PointerSize;
76 case kMips:
77 return kMipsPointerSize;
78 case kNone:
79 LOG(FATAL) << "ISA kNone does not have pointer size.";
80 return 0;
81 default:
82 LOG(FATAL) << "Unknown ISA " << isa;
83 return 0;
84 }
85}
86
Andreas Gampeaf13ad92014-04-11 12:07:48 -070087size_t GetInstructionSetAlignment(InstructionSet isa);
Alexei Zavjalov41c507a2014-05-15 16:02:46 +070088
89static inline bool Is64BitInstructionSet(InstructionSet isa) {
90 switch (isa) {
91 case kArm:
92 case kThumb2:
93 case kX86:
94 case kMips:
95 return false;
96
97 case kArm64:
98 case kX86_64:
99 return true;
100
101 case kNone:
102 LOG(FATAL) << "ISA kNone does not have bit width.";
103 return 0;
104 default:
105 LOG(FATAL) << "Unknown ISA " << isa;
106 return 0;
107 }
108}
109
110static inline size_t GetBytesPerGprSpillLocation(InstructionSet isa) {
111 switch (isa) {
112 case kArm:
113 // Fall-through.
114 case kThumb2:
115 return 4;
116 case kArm64:
117 return 8;
118 case kX86:
119 return 4;
120 case kX86_64:
121 return 8;
122 case kMips:
123 return 4;
124 case kNone:
125 LOG(FATAL) << "ISA kNone does not have spills.";
126 return 0;
127 default:
128 LOG(FATAL) << "Unknown ISA " << isa;
129 return 0;
130 }
131}
132
133static inline size_t GetBytesPerFprSpillLocation(InstructionSet isa) {
134 switch (isa) {
135 case kArm:
136 // Fall-through.
137 case kThumb2:
138 return 4;
139 case kArm64:
140 return 8;
141 case kX86:
142 return 8;
143 case kX86_64:
144 return 8;
145 case kMips:
146 return 4;
147 case kNone:
148 LOG(FATAL) << "ISA kNone does not have spills.";
149 return 0;
150 default:
151 LOG(FATAL) << "Unknown ISA " << isa;
152 return 0;
153 }
154}
Andreas Gampeaf13ad92014-04-11 12:07:48 -0700155
Andreas Gampe91268c12014-04-03 17:50:24 -0700156#if defined(__arm__)
157static constexpr InstructionSet kRuntimeISA = kArm;
158#elif defined(__aarch64__)
159static constexpr InstructionSet kRuntimeISA = kArm64;
160#elif defined(__mips__)
161static constexpr InstructionSet kRuntimeISA = kMips;
162#elif defined(__i386__)
163static constexpr InstructionSet kRuntimeISA = kX86;
164#elif defined(__x86_64__)
165static constexpr InstructionSet kRuntimeISA = kX86_64;
166#else
167static constexpr InstructionSet kRuntimeISA = kNone;
168#endif
169
Dave Allison70202782013-10-22 17:52:19 -0700170enum InstructionFeatures {
Vladimir Marko674744e2014-04-24 15:18:26 +0100171 kHwDiv = 0x1, // Supports hardware divide.
172 kHwLpae = 0x2, // Supports Large Physical Address Extension.
Dave Allison70202782013-10-22 17:52:19 -0700173};
174
175// This is a bitmask of supported features per architecture.
176class PACKED(4) InstructionSetFeatures {
177 public:
178 InstructionSetFeatures() : mask_(0) {}
179 explicit InstructionSetFeatures(uint32_t mask) : mask_(mask) {}
180
Ian Rogers8afeb852014-04-02 14:55:49 -0700181 static InstructionSetFeatures GuessInstructionSetFeatures();
182
Dave Allison70202782013-10-22 17:52:19 -0700183 bool HasDivideInstruction() const {
184 return (mask_ & kHwDiv) != 0;
185 }
186
187 void SetHasDivideInstruction(bool v) {
188 mask_ = (mask_ & ~kHwDiv) | (v ? kHwDiv : 0);
189 }
190
Vladimir Marko674744e2014-04-24 15:18:26 +0100191 bool HasLpae() const {
192 return (mask_ & kHwLpae) != 0;
193 }
194
195 void SetHasLpae(bool v) {
196 mask_ = (mask_ & ~kHwLpae) | (v ? kHwLpae : 0);
197 }
198
Ian Rogers8afeb852014-04-02 14:55:49 -0700199 std::string GetFeatureString() const;
Dave Allison70202782013-10-22 17:52:19 -0700200
201 // Other features in here.
202
203 bool operator==(const InstructionSetFeatures &peer) const {
204 return mask_ == peer.mask_;
205 }
206
207 bool operator!=(const InstructionSetFeatures &peer) const {
208 return mask_ != peer.mask_;
209 }
210
Serban Constantinescu75b91132014-04-09 18:39:10 +0100211 bool operator<=(const InstructionSetFeatures &peer) const {
212 return (mask_ & peer.mask_) == mask_;
213 }
214
Dave Allison70202782013-10-22 17:52:19 -0700215 private:
216 uint32_t mask_;
217};
218
Andreas Gamped58342c2014-06-05 14:18:08 -0700219// The following definitions create return types for two word-sized entities that will be passed
220// in registers so that memory operations for the interface trampolines can be avoided. The entities
221// are the resolved method and the pointer to the code to be invoked.
222//
223// On x86, ARM32 and MIPS, this is given for a *scalar* 64bit value. The definition thus *must* be
224// uint64_t or long long int.
225//
226// On x86_64 and ARM64, structs are decomposed for allocation, so we can create a structs of two
227// size_t-sized values.
228//
229// We need two operations:
230//
231// 1) A flag value that signals failure. The assembly stubs expect the lower part to be "0".
232// GetTwoWordFailureValue() will return a value that has lower part == 0.
233//
234// 2) A value that combines two word-sized values.
235// GetTwoWordSuccessValue() constructs this.
236//
237// IMPORTANT: If you use this to transfer object pointers, it is your responsibility to ensure
238// that the object does not move or the value is updated. Simple use of this is NOT SAFE
239// when the garbage collector can move objects concurrently. Ensure that required locks
240// are held when using!
241
242#if defined(__i386__) || defined(__arm__) || defined(__mips__)
243typedef uint64_t TwoWordReturn;
244
245// Encodes method_ptr==nullptr and code_ptr==nullptr
246static inline constexpr TwoWordReturn GetTwoWordFailureValue() {
247 return 0;
248}
249
250// Use the lower 32b for the method pointer and the upper 32b for the code pointer.
251static inline TwoWordReturn GetTwoWordSuccessValue(uintptr_t hi, uintptr_t lo) {
252 uint32_t lo32 = static_cast<uint32_t>(lo);
253 uint64_t hi64 = static_cast<uint64_t>(hi);
254 return ((hi64 << 32) | lo32);
255}
256
257#elif defined(__x86_64__) || defined(__aarch64__)
258struct TwoWordReturn {
259 uintptr_t lo;
260 uintptr_t hi;
261};
262
263// Encodes method_ptr==nullptr. Leaves random value in code pointer.
264static inline TwoWordReturn GetTwoWordFailureValue() {
265 TwoWordReturn ret;
266 ret.lo = 0;
267 return ret;
268}
269
270// Write values into their respective members.
271static inline TwoWordReturn GetTwoWordSuccessValue(uintptr_t hi, uintptr_t lo) {
272 TwoWordReturn ret;
273 ret.lo = lo;
274 ret.hi = hi;
275 return ret;
276}
277#else
278#error "Unsupported architecture"
279#endif
280
buzbeec143c552011-08-20 17:38:58 -0700281} // namespace art
282
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700283#endif // ART_RUNTIME_INSTRUCTION_SET_H_