xref: /aosp_15_r20/art/libartbase/arch/instruction_set.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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