1// Copyright 2021 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_CODEGEN_ARM_INTERFACE_DESCRIPTORS_ARM_INL_H_
6#define V8_CODEGEN_ARM_INTERFACE_DESCRIPTORS_ARM_INL_H_
7
8#if V8_TARGET_ARCH_ARM
9
10#include "src/codegen/interface-descriptors.h"
11#include "src/execution/frames.h"
12
13namespace v8 {
14namespace internal {
15
16constexpr auto CallInterfaceDescriptor::DefaultRegisterArray() {
17  auto registers = RegisterArray(r0, r1, r2, r3, r4);
18  STATIC_ASSERT(registers.size() == kMaxBuiltinRegisterParams);
19  return registers;
20}
21
22#if DEBUG
23template <typename DerivedDescriptor>
24void StaticCallInterfaceDescriptor<DerivedDescriptor>::
25    VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
26  RegList allocatable_regs = data->allocatable_registers();
27  if (argc >= 1) DCHECK(allocatable_regs.has(r0));
28  if (argc >= 2) DCHECK(allocatable_regs.has(r1));
29  if (argc >= 3) DCHECK(allocatable_regs.has(r2));
30  if (argc >= 4) DCHECK(allocatable_regs.has(r3));
31  if (argc >= 5) DCHECK(allocatable_regs.has(r4));
32  if (argc >= 6) DCHECK(allocatable_regs.has(r5));
33  if (argc >= 7) DCHECK(allocatable_regs.has(r6));
34  if (argc >= 8) DCHECK(allocatable_regs.has(r7));
35  // Additional arguments are passed on the stack.
36}
37#endif  // DEBUG
38
39// static
40constexpr auto WriteBarrierDescriptor::registers() {
41  return RegisterArray(r1, r5, r4, r2, r0, r3, kContextRegister);
42}
43
44// static
45constexpr Register LoadDescriptor::ReceiverRegister() { return r1; }
46// static
47constexpr Register LoadDescriptor::NameRegister() { return r2; }
48// static
49constexpr Register LoadDescriptor::SlotRegister() { return r0; }
50
51// static
52constexpr Register LoadWithVectorDescriptor::VectorRegister() { return r3; }
53
54// static
55constexpr Register KeyedLoadBaselineDescriptor::ReceiverRegister() {
56  return r1;
57}
58// static
59constexpr Register KeyedLoadBaselineDescriptor::NameRegister() {
60  return kInterpreterAccumulatorRegister;
61}
62// static
63constexpr Register KeyedLoadBaselineDescriptor::SlotRegister() { return r2; }
64
65// static
66constexpr Register KeyedLoadWithVectorDescriptor::VectorRegister() {
67  return r3;
68}
69
70// static
71constexpr Register KeyedHasICBaselineDescriptor::ReceiverRegister() {
72  return kInterpreterAccumulatorRegister;
73}
74// static
75constexpr Register KeyedHasICBaselineDescriptor::NameRegister() { return r1; }
76// static
77constexpr Register KeyedHasICBaselineDescriptor::SlotRegister() { return r2; }
78
79// static
80constexpr Register KeyedHasICWithVectorDescriptor::VectorRegister() {
81  return r3;
82}
83
84// static
85constexpr Register
86LoadWithReceiverAndVectorDescriptor::LookupStartObjectRegister() {
87  return r4;
88}
89
90// static
91constexpr Register StoreDescriptor::ReceiverRegister() { return r1; }
92// static
93constexpr Register StoreDescriptor::NameRegister() { return r2; }
94// static
95constexpr Register StoreDescriptor::ValueRegister() { return r0; }
96// static
97constexpr Register StoreDescriptor::SlotRegister() { return r4; }
98
99// static
100constexpr Register StoreWithVectorDescriptor::VectorRegister() { return r3; }
101
102// static
103constexpr Register StoreTransitionDescriptor::MapRegister() { return r5; }
104
105// static
106constexpr Register ApiGetterDescriptor::HolderRegister() { return r0; }
107// static
108constexpr Register ApiGetterDescriptor::CallbackRegister() { return r3; }
109
110// static
111constexpr Register GrowArrayElementsDescriptor::ObjectRegister() { return r0; }
112// static
113constexpr Register GrowArrayElementsDescriptor::KeyRegister() { return r3; }
114
115// static
116constexpr Register BaselineLeaveFrameDescriptor::ParamsSizeRegister() {
117  return r3;
118}
119// static
120constexpr Register BaselineLeaveFrameDescriptor::WeightRegister() { return r4; }
121
122// static
123// static
124constexpr Register TypeConversionDescriptor::ArgumentRegister() { return r0; }
125
126// static
127constexpr auto TypeofDescriptor::registers() { return RegisterArray(r0); }
128
129// static
130constexpr auto CallTrampolineDescriptor::registers() {
131  // r0 : number of arguments
132  // r1 : the target to call
133  return RegisterArray(r1, r0);
134}
135
136// static
137constexpr auto CopyDataPropertiesWithExcludedPropertiesDescriptor::registers() {
138  // r0 : the source
139  // r1 : the excluded property count
140  return RegisterArray(r1, r0);
141}
142
143// static
144constexpr auto
145CopyDataPropertiesWithExcludedPropertiesOnStackDescriptor::registers() {
146  // r0 : the source
147  // r1 : the excluded property count
148  // r2 : the excluded property base
149  return RegisterArray(r1, r0, r2);
150}
151
152// static
153constexpr auto CallVarargsDescriptor::registers() {
154  // r0 : number of arguments (on the stack)
155  // r1 : the target to call
156  // r4 : arguments list length (untagged)
157  // r2 : arguments list (FixedArray)
158  return RegisterArray(r1, r0, r4, r2);
159}
160
161// static
162constexpr auto CallForwardVarargsDescriptor::registers() {
163  // r0 : number of arguments
164  // r2 : start index (to support rest parameters)
165  // r1 : the target to call
166  return RegisterArray(r1, r0, r2);
167}
168
169// static
170constexpr auto CallFunctionTemplateDescriptor::registers() {
171  // r1 : function template info
172  // r2 : number of arguments (on the stack)
173  return RegisterArray(r1, r2);
174}
175
176// static
177constexpr auto CallWithSpreadDescriptor::registers() {
178  // r0 : number of arguments (on the stack)
179  // r1 : the target to call
180  // r2 : the object to spread
181  return RegisterArray(r1, r0, r2);
182}
183
184// static
185constexpr auto CallWithArrayLikeDescriptor::registers() {
186  // r1 : the target to call
187  // r2 : the arguments list
188  return RegisterArray(r1, r2);
189}
190
191// static
192constexpr auto ConstructVarargsDescriptor::registers() {
193  // r0 : number of arguments (on the stack)
194  // r1 : the target to call
195  // r3 : the new target
196  // r4 : arguments list length (untagged)
197  // r2 : arguments list (FixedArray)
198  return RegisterArray(r1, r3, r0, r4, r2);
199}
200
201// static
202constexpr auto ConstructForwardVarargsDescriptor::registers() {
203  // r0 : number of arguments
204  // r3 : the new target
205  // r2 : start index (to support rest parameters)
206  // r1 : the target to call
207  return RegisterArray(r1, r3, r0, r2);
208}
209
210// static
211constexpr auto ConstructWithSpreadDescriptor::registers() {
212  // r0 : number of arguments (on the stack)
213  // r1 : the target to call
214  // r3 : the new target
215  // r2 : the object to spread
216  return RegisterArray(r1, r3, r0, r2);
217}
218
219// static
220constexpr auto ConstructWithArrayLikeDescriptor::registers() {
221  // r1 : the target to call
222  // r3 : the new target
223  // r2 : the arguments list
224  return RegisterArray(r1, r3, r2);
225}
226
227// static
228constexpr auto ConstructStubDescriptor::registers() {
229  // r0 : number of arguments
230  // r1 : the target to call
231  // r3 : the new target
232  // r2 : allocation site or undefined
233  return RegisterArray(r1, r3, r0, r2);
234}
235
236// static
237constexpr auto AbortDescriptor::registers() { return RegisterArray(r1); }
238
239// static
240constexpr auto CompareDescriptor::registers() { return RegisterArray(r1, r0); }
241
242// static
243constexpr auto Compare_BaselineDescriptor::registers() {
244  // r1: left operand
245  // r0: right operand
246  // r2: feedback slot
247  return RegisterArray(r1, r0, r2);
248}
249
250// static
251constexpr auto BinaryOpDescriptor::registers() { return RegisterArray(r1, r0); }
252
253// static
254constexpr auto BinaryOp_BaselineDescriptor::registers() {
255  // r1: left operand
256  // r0: right operand
257  // r2: feedback slot
258  return RegisterArray(r1, r0, r2);
259}
260
261// static
262constexpr auto BinarySmiOp_BaselineDescriptor::registers() {
263  // r0: left operand
264  // r1: right operand
265  // r2: feedback slot
266  return RegisterArray(r0, r1, r2);
267}
268
269// static
270constexpr auto ApiCallbackDescriptor::registers() {
271  return RegisterArray(r1,   // kApiFunctionAddress
272                       r2,   // kArgc
273                       r3,   // kCallData
274                       r0);  // kHolder
275}
276
277// static
278constexpr auto InterpreterDispatchDescriptor::registers() {
279  return RegisterArray(
280      kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
281      kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister);
282}
283
284// static
285constexpr auto InterpreterPushArgsThenCallDescriptor::registers() {
286  return RegisterArray(r0,   // argument count
287                       r2,   // address of first argument
288                       r1);  // the target callable to be call
289}
290
291// static
292constexpr auto InterpreterPushArgsThenConstructDescriptor::registers() {
293  return RegisterArray(
294      r0,   // argument count
295      r4,   // address of the first argument
296      r1,   // constructor to call
297      r3,   // new target
298      r2);  // allocation site feedback if available, undefined otherwise
299}
300
301// static
302constexpr auto ResumeGeneratorDescriptor::registers() {
303  return RegisterArray(r0,   // the value to pass to the generator
304                       r1);  // the JSGeneratorObject to resume
305}
306
307// static
308constexpr auto RunMicrotasksEntryDescriptor::registers() {
309  return RegisterArray(r0, r1);
310}
311
312}  // namespace internal
313}  // namespace v8
314
315#endif  // V8_TARGET_ARCH_ARM
316
317#endif  // V8_CODEGEN_ARM_INTERFACE_DESCRIPTORS_ARM_INL_H_
318