1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2011 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_LIBARTBASE_ARCH_INSTRUCTION_SET_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_LIBARTBASE_ARCH_INSTRUCTION_SET_H_
19*795d594fSAndroid Build Coastguard Worker
20*795d594fSAndroid Build Coastguard Worker #include <iosfwd>
21*795d594fSAndroid Build Coastguard Worker #include <string>
22*795d594fSAndroid Build Coastguard Worker #include <vector>
23*795d594fSAndroid Build Coastguard Worker
24*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
25*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
26*795d594fSAndroid Build Coastguard Worker
27*795d594fSAndroid Build Coastguard Worker namespace art {
28*795d594fSAndroid Build Coastguard Worker
29*795d594fSAndroid Build Coastguard Worker enum class InstructionSet {
30*795d594fSAndroid Build Coastguard Worker kNone,
31*795d594fSAndroid Build Coastguard Worker kArm,
32*795d594fSAndroid Build Coastguard Worker kArm64,
33*795d594fSAndroid Build Coastguard Worker kThumb2,
34*795d594fSAndroid Build Coastguard Worker kRiscv64,
35*795d594fSAndroid Build Coastguard Worker kX86,
36*795d594fSAndroid Build Coastguard Worker kX86_64,
37*795d594fSAndroid Build Coastguard Worker kLast = kX86_64
38*795d594fSAndroid Build Coastguard Worker };
39*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, InstructionSet rhs);
40*795d594fSAndroid Build Coastguard Worker
41*795d594fSAndroid Build Coastguard Worker // kRuntimeISA must match the ISA of the machine that ART will be run on. This ISA will be used for
42*795d594fSAndroid Build Coastguard Worker // the native context, native stack frame and native ABI.
43*795d594fSAndroid Build Coastguard Worker #if defined(__arm__)
44*795d594fSAndroid Build Coastguard Worker static constexpr InstructionSet kRuntimeISA = InstructionSet::kArm;
45*795d594fSAndroid Build Coastguard Worker #elif defined(__aarch64__)
46*795d594fSAndroid Build Coastguard Worker static constexpr InstructionSet kRuntimeISA = InstructionSet::kArm64;
47*795d594fSAndroid Build Coastguard Worker #elif defined (__riscv)
48*795d594fSAndroid Build Coastguard Worker static constexpr InstructionSet kRuntimeISA = InstructionSet::kRiscv64;
49*795d594fSAndroid Build Coastguard Worker #elif defined(__i386__)
50*795d594fSAndroid Build Coastguard Worker static constexpr InstructionSet kRuntimeISA = InstructionSet::kX86;
51*795d594fSAndroid Build Coastguard Worker #elif defined(__x86_64__)
52*795d594fSAndroid Build Coastguard Worker static constexpr InstructionSet kRuntimeISA = InstructionSet::kX86_64;
53*795d594fSAndroid Build Coastguard Worker #else
54*795d594fSAndroid Build Coastguard Worker static constexpr InstructionSet kRuntimeISA = InstructionSet::kNone;
55*795d594fSAndroid Build Coastguard Worker #endif
56*795d594fSAndroid Build Coastguard Worker
57*795d594fSAndroid Build Coastguard Worker // The ISA that ART will generate quick code for, i.e.: that java code will be compiled to. This
58*795d594fSAndroid Build Coastguard Worker // ISA will be used for the quick context, quick stack frame and quick ABI. This may differ from
59*795d594fSAndroid Build Coastguard Worker // kRuntimeISA if the simulator is in use where, for example, the native runtime is x86-64 but the
60*795d594fSAndroid Build Coastguard Worker // quick code generated by the compiler is Arm64.
61*795d594fSAndroid Build Coastguard Worker static constexpr InstructionSet kRuntimeQuickCodeISA = kRuntimeISA;
62*795d594fSAndroid Build Coastguard Worker
63*795d594fSAndroid Build Coastguard Worker // Architecture-specific pointer sizes
64*795d594fSAndroid Build Coastguard Worker static constexpr PointerSize kArmPointerSize = PointerSize::k32;
65*795d594fSAndroid Build Coastguard Worker static constexpr PointerSize kArm64PointerSize = PointerSize::k64;
66*795d594fSAndroid Build Coastguard Worker static constexpr PointerSize kRiscv64PointerSize = PointerSize::k64;
67*795d594fSAndroid Build Coastguard Worker static constexpr PointerSize kX86PointerSize = PointerSize::k32;
68*795d594fSAndroid Build Coastguard Worker static constexpr PointerSize kX86_64PointerSize = PointerSize::k64;
69*795d594fSAndroid Build Coastguard Worker
70*795d594fSAndroid Build Coastguard Worker // ARM64 default SVE vector length.
71*795d594fSAndroid Build Coastguard Worker static constexpr size_t kArm64DefaultSVEVectorLength = 256;
72*795d594fSAndroid Build Coastguard Worker
73*795d594fSAndroid Build Coastguard Worker // Code alignment (used for the first instruction of a subroutine, such as an entrypoint).
74*795d594fSAndroid Build Coastguard Worker // This is the recommended alignment for maximum performance.
75*795d594fSAndroid Build Coastguard Worker // ARM processors require code to be 4-byte aligned, but ARM ELF requires 8.
76*795d594fSAndroid Build Coastguard Worker static constexpr size_t kArmCodeAlignment = 8;
77*795d594fSAndroid Build Coastguard Worker static constexpr size_t kArm64CodeAlignment = 16;
78*795d594fSAndroid Build Coastguard Worker static constexpr size_t kRiscv64CodeAlignment = 16;
79*795d594fSAndroid Build Coastguard Worker static constexpr size_t kX86CodeAlignment = 16;
80*795d594fSAndroid Build Coastguard Worker
81*795d594fSAndroid Build Coastguard Worker // Instruction alignment (every instruction must be aligned at this boundary). This differs from
82*795d594fSAndroid Build Coastguard Worker // code alignment, which applies only to the first instruction of a subroutine.
83*795d594fSAndroid Build Coastguard Worker // Android requires the RISC-V compressed instruction extension, and that allows
84*795d594fSAndroid Build Coastguard Worker // *all* instructions (not just compressed ones) to be 2-byte aligned rather
85*795d594fSAndroid Build Coastguard Worker // than the usual 4-byte alignment requirement.
86*795d594fSAndroid Build Coastguard Worker static constexpr size_t kThumb2InstructionAlignment = 2;
87*795d594fSAndroid Build Coastguard Worker static constexpr size_t kArm64InstructionAlignment = 4;
88*795d594fSAndroid Build Coastguard Worker static constexpr size_t kRiscv64InstructionAlignment = 2;
89*795d594fSAndroid Build Coastguard Worker static constexpr size_t kX86InstructionAlignment = 1;
90*795d594fSAndroid Build Coastguard Worker static constexpr size_t kX86_64InstructionAlignment = 1;
91*795d594fSAndroid Build Coastguard Worker
92*795d594fSAndroid Build Coastguard Worker const char* GetInstructionSetString(InstructionSet isa);
93*795d594fSAndroid Build Coastguard Worker
94*795d594fSAndroid Build Coastguard Worker // Note: Returns kNone when the string cannot be parsed to a known value.
95*795d594fSAndroid Build Coastguard Worker InstructionSet GetInstructionSetFromString(const char* instruction_set);
96*795d594fSAndroid Build Coastguard Worker
97*795d594fSAndroid Build Coastguard Worker // Fatal logging out of line to keep the header clean of logging.h.
98*795d594fSAndroid Build Coastguard Worker NO_RETURN void InstructionSetAbort(InstructionSet isa);
99*795d594fSAndroid Build Coastguard Worker
GetInstructionSetPointerSize(InstructionSet isa)100*795d594fSAndroid Build Coastguard Worker constexpr PointerSize GetInstructionSetPointerSize(InstructionSet isa) {
101*795d594fSAndroid Build Coastguard Worker switch (isa) {
102*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm:
103*795d594fSAndroid Build Coastguard Worker case InstructionSet::kThumb2:
104*795d594fSAndroid Build Coastguard Worker return kArmPointerSize;
105*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm64:
106*795d594fSAndroid Build Coastguard Worker return kArm64PointerSize;
107*795d594fSAndroid Build Coastguard Worker case InstructionSet::kRiscv64:
108*795d594fSAndroid Build Coastguard Worker return kRiscv64PointerSize;
109*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86:
110*795d594fSAndroid Build Coastguard Worker return kX86PointerSize;
111*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86_64:
112*795d594fSAndroid Build Coastguard Worker return kX86_64PointerSize;
113*795d594fSAndroid Build Coastguard Worker case InstructionSet::kNone:
114*795d594fSAndroid Build Coastguard Worker InstructionSetAbort(isa);
115*795d594fSAndroid Build Coastguard Worker }
116*795d594fSAndroid Build Coastguard Worker }
117*795d594fSAndroid Build Coastguard Worker
IsValidInstructionSet(InstructionSet isa)118*795d594fSAndroid Build Coastguard Worker constexpr bool IsValidInstructionSet(InstructionSet isa) {
119*795d594fSAndroid Build Coastguard Worker switch (isa) {
120*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm:
121*795d594fSAndroid Build Coastguard Worker case InstructionSet::kThumb2:
122*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm64:
123*795d594fSAndroid Build Coastguard Worker case InstructionSet::kRiscv64:
124*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86:
125*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86_64:
126*795d594fSAndroid Build Coastguard Worker return true;
127*795d594fSAndroid Build Coastguard Worker case InstructionSet::kNone:
128*795d594fSAndroid Build Coastguard Worker return false;
129*795d594fSAndroid Build Coastguard Worker }
130*795d594fSAndroid Build Coastguard Worker }
131*795d594fSAndroid Build Coastguard Worker
GetInstructionSetInstructionAlignment(InstructionSet isa)132*795d594fSAndroid Build Coastguard Worker constexpr size_t GetInstructionSetInstructionAlignment(InstructionSet isa) {
133*795d594fSAndroid Build Coastguard Worker switch (isa) {
134*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm:
135*795d594fSAndroid Build Coastguard Worker case InstructionSet::kThumb2:
136*795d594fSAndroid Build Coastguard Worker return kThumb2InstructionAlignment;
137*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm64:
138*795d594fSAndroid Build Coastguard Worker return kArm64InstructionAlignment;
139*795d594fSAndroid Build Coastguard Worker case InstructionSet::kRiscv64:
140*795d594fSAndroid Build Coastguard Worker return kRiscv64InstructionAlignment;
141*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86:
142*795d594fSAndroid Build Coastguard Worker return kX86InstructionAlignment;
143*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86_64:
144*795d594fSAndroid Build Coastguard Worker return kX86_64InstructionAlignment;
145*795d594fSAndroid Build Coastguard Worker case InstructionSet::kNone:
146*795d594fSAndroid Build Coastguard Worker InstructionSetAbort(isa);
147*795d594fSAndroid Build Coastguard Worker }
148*795d594fSAndroid Build Coastguard Worker }
149*795d594fSAndroid Build Coastguard Worker
GetInstructionSetCodeAlignment(InstructionSet isa)150*795d594fSAndroid Build Coastguard Worker constexpr size_t GetInstructionSetCodeAlignment(InstructionSet isa) {
151*795d594fSAndroid Build Coastguard Worker switch (isa) {
152*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm:
153*795d594fSAndroid Build Coastguard Worker case InstructionSet::kThumb2:
154*795d594fSAndroid Build Coastguard Worker return kArmCodeAlignment;
155*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm64:
156*795d594fSAndroid Build Coastguard Worker return kArm64CodeAlignment;
157*795d594fSAndroid Build Coastguard Worker case InstructionSet::kRiscv64:
158*795d594fSAndroid Build Coastguard Worker return kRiscv64CodeAlignment;
159*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86:
160*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86_64:
161*795d594fSAndroid Build Coastguard Worker return kX86CodeAlignment;
162*795d594fSAndroid Build Coastguard Worker case InstructionSet::kNone:
163*795d594fSAndroid Build Coastguard Worker InstructionSetAbort(isa);
164*795d594fSAndroid Build Coastguard Worker }
165*795d594fSAndroid Build Coastguard Worker }
166*795d594fSAndroid Build Coastguard Worker
167*795d594fSAndroid Build Coastguard Worker // Returns the difference between the code address and a usable PC.
168*795d594fSAndroid Build Coastguard Worker // Mainly to cope with `kThumb2` where the lower bit must be set.
GetInstructionSetEntryPointAdjustment(InstructionSet isa)169*795d594fSAndroid Build Coastguard Worker constexpr size_t GetInstructionSetEntryPointAdjustment(InstructionSet isa) {
170*795d594fSAndroid Build Coastguard Worker switch (isa) {
171*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm:
172*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm64:
173*795d594fSAndroid Build Coastguard Worker case InstructionSet::kRiscv64:
174*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86:
175*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86_64:
176*795d594fSAndroid Build Coastguard Worker return 0;
177*795d594fSAndroid Build Coastguard Worker case InstructionSet::kThumb2:
178*795d594fSAndroid Build Coastguard Worker // +1 to set the low-order bit so a BLX will switch to Thumb mode
179*795d594fSAndroid Build Coastguard Worker return 1;
180*795d594fSAndroid Build Coastguard Worker case InstructionSet::kNone:
181*795d594fSAndroid Build Coastguard Worker InstructionSetAbort(isa);
182*795d594fSAndroid Build Coastguard Worker }
183*795d594fSAndroid Build Coastguard Worker }
184*795d594fSAndroid Build Coastguard Worker
Is64BitInstructionSet(InstructionSet isa)185*795d594fSAndroid Build Coastguard Worker constexpr bool Is64BitInstructionSet(InstructionSet isa) {
186*795d594fSAndroid Build Coastguard Worker switch (isa) {
187*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm:
188*795d594fSAndroid Build Coastguard Worker case InstructionSet::kThumb2:
189*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86:
190*795d594fSAndroid Build Coastguard Worker return false;
191*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm64:
192*795d594fSAndroid Build Coastguard Worker case InstructionSet::kRiscv64:
193*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86_64:
194*795d594fSAndroid Build Coastguard Worker return true;
195*795d594fSAndroid Build Coastguard Worker case InstructionSet::kNone:
196*795d594fSAndroid Build Coastguard Worker InstructionSetAbort(isa);
197*795d594fSAndroid Build Coastguard Worker }
198*795d594fSAndroid Build Coastguard Worker }
199*795d594fSAndroid Build Coastguard Worker
InstructionSetPointerSize(InstructionSet isa)200*795d594fSAndroid Build Coastguard Worker constexpr PointerSize InstructionSetPointerSize(InstructionSet isa) {
201*795d594fSAndroid Build Coastguard Worker return Is64BitInstructionSet(isa) ? PointerSize::k64 : PointerSize::k32;
202*795d594fSAndroid Build Coastguard Worker }
203*795d594fSAndroid Build Coastguard Worker
GetBytesPerGprSpillLocation(InstructionSet isa)204*795d594fSAndroid Build Coastguard Worker constexpr size_t GetBytesPerGprSpillLocation(InstructionSet isa) {
205*795d594fSAndroid Build Coastguard Worker switch (isa) {
206*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm:
207*795d594fSAndroid Build Coastguard Worker case InstructionSet::kThumb2:
208*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86:
209*795d594fSAndroid Build Coastguard Worker return 4;
210*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm64:
211*795d594fSAndroid Build Coastguard Worker case InstructionSet::kRiscv64:
212*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86_64:
213*795d594fSAndroid Build Coastguard Worker return 8;
214*795d594fSAndroid Build Coastguard Worker case InstructionSet::kNone:
215*795d594fSAndroid Build Coastguard Worker InstructionSetAbort(isa);
216*795d594fSAndroid Build Coastguard Worker }
217*795d594fSAndroid Build Coastguard Worker }
218*795d594fSAndroid Build Coastguard Worker
GetBytesPerFprSpillLocation(InstructionSet isa)219*795d594fSAndroid Build Coastguard Worker constexpr size_t GetBytesPerFprSpillLocation(InstructionSet isa) {
220*795d594fSAndroid Build Coastguard Worker switch (isa) {
221*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm:
222*795d594fSAndroid Build Coastguard Worker case InstructionSet::kThumb2:
223*795d594fSAndroid Build Coastguard Worker return 4;
224*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm64:
225*795d594fSAndroid Build Coastguard Worker case InstructionSet::kRiscv64:
226*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86:
227*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86_64:
228*795d594fSAndroid Build Coastguard Worker return 8;
229*795d594fSAndroid Build Coastguard Worker case InstructionSet::kNone:
230*795d594fSAndroid Build Coastguard Worker InstructionSetAbort(isa);
231*795d594fSAndroid Build Coastguard Worker }
232*795d594fSAndroid Build Coastguard Worker }
233*795d594fSAndroid Build Coastguard Worker
234*795d594fSAndroid Build Coastguard Worker // Returns the instruction sets supported by the device, or an empty list on failure.
235*795d594fSAndroid Build Coastguard Worker std::vector<InstructionSet> GetSupportedInstructionSets(std::string* error_msg);
236*795d594fSAndroid Build Coastguard Worker
237*795d594fSAndroid Build Coastguard Worker namespace instruction_set_details {
238*795d594fSAndroid Build Coastguard Worker
239*795d594fSAndroid Build Coastguard Worker #if !defined(ART_STACK_OVERFLOW_GAP_arm) || !defined(ART_STACK_OVERFLOW_GAP_arm64) || \
240*795d594fSAndroid Build Coastguard Worker !defined(ART_STACK_OVERFLOW_GAP_riscv64) || \
241*795d594fSAndroid Build Coastguard Worker !defined(ART_STACK_OVERFLOW_GAP_x86) || !defined(ART_STACK_OVERFLOW_GAP_x86_64)
242*795d594fSAndroid Build Coastguard Worker #error "Missing defines for stack overflow gap"
243*795d594fSAndroid Build Coastguard Worker #endif
244*795d594fSAndroid Build Coastguard Worker
245*795d594fSAndroid Build Coastguard Worker static constexpr size_t kArmStackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_arm;
246*795d594fSAndroid Build Coastguard Worker static constexpr size_t kArm64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_arm64;
247*795d594fSAndroid Build Coastguard Worker static constexpr size_t kRiscv64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_riscv64;
248*795d594fSAndroid Build Coastguard Worker static constexpr size_t kX86StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_x86;
249*795d594fSAndroid Build Coastguard Worker static constexpr size_t kX86_64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_x86_64;
250*795d594fSAndroid Build Coastguard Worker
251*795d594fSAndroid Build Coastguard Worker NO_RETURN void GetStackOverflowReservedBytesFailure(const char* error_msg);
252*795d594fSAndroid Build Coastguard Worker
253*795d594fSAndroid Build Coastguard Worker } // namespace instruction_set_details
254*795d594fSAndroid Build Coastguard Worker
255*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE
GetStackOverflowReservedBytes(InstructionSet isa)256*795d594fSAndroid Build Coastguard Worker constexpr size_t GetStackOverflowReservedBytes(InstructionSet isa) {
257*795d594fSAndroid Build Coastguard Worker switch (isa) {
258*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm: // Intentional fall-through.
259*795d594fSAndroid Build Coastguard Worker case InstructionSet::kThumb2:
260*795d594fSAndroid Build Coastguard Worker return instruction_set_details::kArmStackOverflowReservedBytes;
261*795d594fSAndroid Build Coastguard Worker
262*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm64:
263*795d594fSAndroid Build Coastguard Worker return instruction_set_details::kArm64StackOverflowReservedBytes;
264*795d594fSAndroid Build Coastguard Worker
265*795d594fSAndroid Build Coastguard Worker case InstructionSet::kRiscv64:
266*795d594fSAndroid Build Coastguard Worker return instruction_set_details::kRiscv64StackOverflowReservedBytes;
267*795d594fSAndroid Build Coastguard Worker
268*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86:
269*795d594fSAndroid Build Coastguard Worker return instruction_set_details::kX86StackOverflowReservedBytes;
270*795d594fSAndroid Build Coastguard Worker
271*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86_64:
272*795d594fSAndroid Build Coastguard Worker return instruction_set_details::kX86_64StackOverflowReservedBytes;
273*795d594fSAndroid Build Coastguard Worker
274*795d594fSAndroid Build Coastguard Worker case InstructionSet::kNone:
275*795d594fSAndroid Build Coastguard Worker instruction_set_details::GetStackOverflowReservedBytesFailure(
276*795d594fSAndroid Build Coastguard Worker "kNone has no stack overflow size");
277*795d594fSAndroid Build Coastguard Worker }
278*795d594fSAndroid Build Coastguard Worker }
279*795d594fSAndroid Build Coastguard Worker
280*795d594fSAndroid Build Coastguard Worker // The following definitions create return types for two word-sized entities that will be passed
281*795d594fSAndroid Build Coastguard Worker // in registers so that memory operations for the interface trampolines can be avoided. The entities
282*795d594fSAndroid Build Coastguard Worker // are the resolved method and the pointer to the code to be invoked.
283*795d594fSAndroid Build Coastguard Worker //
284*795d594fSAndroid Build Coastguard Worker // On x86 and ARM32, this is given for a *scalar* 64bit value. The definition thus *must* be
285*795d594fSAndroid Build Coastguard Worker // uint64_t or long long int.
286*795d594fSAndroid Build Coastguard Worker //
287*795d594fSAndroid Build Coastguard Worker // On x86_64 and ARM64, structs are decomposed for allocation, so we can create a structs of
288*795d594fSAndroid Build Coastguard Worker // two size_t-sized values.
289*795d594fSAndroid Build Coastguard Worker //
290*795d594fSAndroid Build Coastguard Worker // We need two operations:
291*795d594fSAndroid Build Coastguard Worker //
292*795d594fSAndroid Build Coastguard Worker // 1) A flag value that signals failure. The assembly stubs expect the lower part to be "0".
293*795d594fSAndroid Build Coastguard Worker // GetTwoWordFailureValue() will return a value that has lower part == 0.
294*795d594fSAndroid Build Coastguard Worker //
295*795d594fSAndroid Build Coastguard Worker // 2) A value that combines two word-sized values.
296*795d594fSAndroid Build Coastguard Worker // GetTwoWordSuccessValue() constructs this.
297*795d594fSAndroid Build Coastguard Worker //
298*795d594fSAndroid Build Coastguard Worker // IMPORTANT: If you use this to transfer object pointers, it is your responsibility to ensure
299*795d594fSAndroid Build Coastguard Worker // that the object does not move or the value is updated. Simple use of this is NOT SAFE
300*795d594fSAndroid Build Coastguard Worker // when the garbage collector can move objects concurrently. Ensure that required locks
301*795d594fSAndroid Build Coastguard Worker // are held when using!
302*795d594fSAndroid Build Coastguard Worker
303*795d594fSAndroid Build Coastguard Worker #if defined(__i386__) || defined(__arm__)
304*795d594fSAndroid Build Coastguard Worker using TwoWordReturn = uint64_t;
305*795d594fSAndroid Build Coastguard Worker
306*795d594fSAndroid Build Coastguard Worker // Encodes method_ptr==nullptr and code_ptr==nullptr
GetTwoWordFailureValue()307*795d594fSAndroid Build Coastguard Worker static inline constexpr TwoWordReturn GetTwoWordFailureValue() {
308*795d594fSAndroid Build Coastguard Worker return 0;
309*795d594fSAndroid Build Coastguard Worker }
310*795d594fSAndroid Build Coastguard Worker
311*795d594fSAndroid Build Coastguard Worker // Use the lower 32b for the method pointer and the upper 32b for the code pointer.
GetTwoWordSuccessValue(uintptr_t hi,uintptr_t lo)312*795d594fSAndroid Build Coastguard Worker static inline constexpr TwoWordReturn GetTwoWordSuccessValue(uintptr_t hi, uintptr_t lo) {
313*795d594fSAndroid Build Coastguard Worker static_assert(sizeof(uint32_t) == sizeof(uintptr_t), "Unexpected size difference");
314*795d594fSAndroid Build Coastguard Worker uint32_t lo32 = lo;
315*795d594fSAndroid Build Coastguard Worker uint64_t hi64 = static_cast<uint64_t>(hi);
316*795d594fSAndroid Build Coastguard Worker return ((hi64 << 32) | lo32);
317*795d594fSAndroid Build Coastguard Worker }
318*795d594fSAndroid Build Coastguard Worker
319*795d594fSAndroid Build Coastguard Worker #elif defined(__x86_64__) || defined(__aarch64__) || defined(__riscv)
320*795d594fSAndroid Build Coastguard Worker
321*795d594fSAndroid Build Coastguard Worker // Note: TwoWordReturn can't be constexpr for 64-bit targets. We'd need a constexpr constructor,
322*795d594fSAndroid Build Coastguard Worker // which would violate C-linkage in the entrypoint functions.
323*795d594fSAndroid Build Coastguard Worker
324*795d594fSAndroid Build Coastguard Worker struct TwoWordReturn {
325*795d594fSAndroid Build Coastguard Worker uintptr_t lo;
326*795d594fSAndroid Build Coastguard Worker uintptr_t hi;
327*795d594fSAndroid Build Coastguard Worker };
328*795d594fSAndroid Build Coastguard Worker
329*795d594fSAndroid Build Coastguard Worker // Encodes method_ptr==nullptr. Leaves random value in code pointer.
GetTwoWordFailureValue()330*795d594fSAndroid Build Coastguard Worker static inline TwoWordReturn GetTwoWordFailureValue() {
331*795d594fSAndroid Build Coastguard Worker TwoWordReturn ret;
332*795d594fSAndroid Build Coastguard Worker ret.lo = 0;
333*795d594fSAndroid Build Coastguard Worker return ret;
334*795d594fSAndroid Build Coastguard Worker }
335*795d594fSAndroid Build Coastguard Worker
336*795d594fSAndroid Build Coastguard Worker // Write values into their respective members.
GetTwoWordSuccessValue(uintptr_t hi,uintptr_t lo)337*795d594fSAndroid Build Coastguard Worker static inline TwoWordReturn GetTwoWordSuccessValue(uintptr_t hi, uintptr_t lo) {
338*795d594fSAndroid Build Coastguard Worker TwoWordReturn ret;
339*795d594fSAndroid Build Coastguard Worker ret.lo = lo;
340*795d594fSAndroid Build Coastguard Worker ret.hi = hi;
341*795d594fSAndroid Build Coastguard Worker return ret;
342*795d594fSAndroid Build Coastguard Worker }
343*795d594fSAndroid Build Coastguard Worker #else
344*795d594fSAndroid Build Coastguard Worker #error "Unsupported architecture"
345*795d594fSAndroid Build Coastguard Worker #endif
346*795d594fSAndroid Build Coastguard Worker
347*795d594fSAndroid Build Coastguard Worker } // namespace art
348*795d594fSAndroid Build Coastguard Worker
349*795d594fSAndroid Build Coastguard Worker #endif // ART_LIBARTBASE_ARCH_INSTRUCTION_SET_H_
350