1// Copyright 2012 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#include "src/arm/interface-descriptors-arm.h"
6
7#if V8_TARGET_ARCH_ARM
8
9#include "src/interface-descriptors.h"
10
11namespace v8 {
12namespace internal {
13
14const Register CallInterfaceDescriptor::ContextRegister() { return cp; }
15
16void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
17    CallInterfaceDescriptorData* data, int register_parameter_count) {
18  const Register default_stub_registers[] = {r0, r1, r2, r3, r4};
19  CHECK_LE(static_cast<size_t>(register_parameter_count),
20           arraysize(default_stub_registers));
21  data->InitializePlatformSpecific(register_parameter_count,
22                                   default_stub_registers);
23}
24
25const Register FastNewFunctionContextDescriptor::FunctionRegister() {
26  return r1;
27}
28const Register FastNewFunctionContextDescriptor::SlotsRegister() { return r0; }
29
30const Register LoadDescriptor::ReceiverRegister() { return r1; }
31const Register LoadDescriptor::NameRegister() { return r2; }
32const Register LoadDescriptor::SlotRegister() { return r0; }
33
34const Register LoadWithVectorDescriptor::VectorRegister() { return r3; }
35
36const Register LoadICProtoArrayDescriptor::HandlerRegister() { return r4; }
37
38const Register StoreDescriptor::ReceiverRegister() { return r1; }
39const Register StoreDescriptor::NameRegister() { return r2; }
40const Register StoreDescriptor::ValueRegister() { return r0; }
41const Register StoreDescriptor::SlotRegister() { return r4; }
42
43const Register StoreWithVectorDescriptor::VectorRegister() { return r3; }
44
45const Register StoreTransitionDescriptor::SlotRegister() { return r4; }
46const Register StoreTransitionDescriptor::VectorRegister() { return r3; }
47const Register StoreTransitionDescriptor::MapRegister() { return r5; }
48
49const Register StringCompareDescriptor::LeftRegister() { return r1; }
50const Register StringCompareDescriptor::RightRegister() { return r0; }
51
52const Register ApiGetterDescriptor::HolderRegister() { return r0; }
53const Register ApiGetterDescriptor::CallbackRegister() { return r3; }
54
55const Register MathPowTaggedDescriptor::exponent() { return r2; }
56
57
58const Register MathPowIntegerDescriptor::exponent() {
59  return MathPowTaggedDescriptor::exponent();
60}
61
62
63const Register GrowArrayElementsDescriptor::ObjectRegister() { return r0; }
64const Register GrowArrayElementsDescriptor::KeyRegister() { return r3; }
65
66
67void FastNewClosureDescriptor::InitializePlatformSpecific(
68    CallInterfaceDescriptorData* data) {
69  Register registers[] = {r1, r2, r3};
70  data->InitializePlatformSpecific(arraysize(registers), registers);
71}
72
73// static
74const Register TypeConversionDescriptor::ArgumentRegister() { return r0; }
75
76void TypeofDescriptor::InitializePlatformSpecific(
77    CallInterfaceDescriptorData* data) {
78  Register registers[] = {r3};
79  data->InitializePlatformSpecific(arraysize(registers), registers);
80}
81
82
83void FastCloneRegExpDescriptor::InitializePlatformSpecific(
84    CallInterfaceDescriptorData* data) {
85  Register registers[] = {r3, r2, r1, r0};
86  data->InitializePlatformSpecific(arraysize(registers), registers);
87}
88
89
90void FastCloneShallowArrayDescriptor::InitializePlatformSpecific(
91    CallInterfaceDescriptorData* data) {
92  Register registers[] = {r3, r2, r1};
93  data->InitializePlatformSpecific(arraysize(registers), registers);
94}
95
96
97void FastCloneShallowObjectDescriptor::InitializePlatformSpecific(
98    CallInterfaceDescriptorData* data) {
99  Register registers[] = {r3, r2, r1, r0};
100  data->InitializePlatformSpecific(arraysize(registers), registers);
101}
102
103
104void CreateAllocationSiteDescriptor::InitializePlatformSpecific(
105    CallInterfaceDescriptorData* data) {
106  Register registers[] = {r2, r3};
107  data->InitializePlatformSpecific(arraysize(registers), registers);
108}
109
110
111void CreateWeakCellDescriptor::InitializePlatformSpecific(
112    CallInterfaceDescriptorData* data) {
113  Register registers[] = {r2, r3, r1};
114  data->InitializePlatformSpecific(arraysize(registers), registers);
115}
116
117
118void CallFunctionDescriptor::InitializePlatformSpecific(
119    CallInterfaceDescriptorData* data) {
120  Register registers[] = {r1};
121  data->InitializePlatformSpecific(arraysize(registers), registers);
122}
123
124void CallICTrampolineDescriptor::InitializePlatformSpecific(
125    CallInterfaceDescriptorData* data) {
126  Register registers[] = {r1, r0, r3};
127  data->InitializePlatformSpecific(arraysize(registers), registers);
128}
129
130void CallICDescriptor::InitializePlatformSpecific(
131    CallInterfaceDescriptorData* data) {
132  Register registers[] = {r1, r0, r3, r2};
133  data->InitializePlatformSpecific(arraysize(registers), registers);
134}
135
136
137void CallConstructDescriptor::InitializePlatformSpecific(
138    CallInterfaceDescriptorData* data) {
139  // r0 : number of arguments
140  // r1 : the function to call
141  // r2 : feedback vector
142  // r3 : slot in feedback vector (Smi, for RecordCallTarget)
143  // r4 : new target (for IsSuperConstructorCall)
144  // TODO(turbofan): So far we don't gather type feedback and hence skip the
145  // slot parameter, but ArrayConstructStub needs the vector to be undefined.
146  Register registers[] = {r0, r1, r4, r2};
147  data->InitializePlatformSpecific(arraysize(registers), registers);
148}
149
150
151void CallTrampolineDescriptor::InitializePlatformSpecific(
152    CallInterfaceDescriptorData* data) {
153  // r0 : number of arguments
154  // r1 : the target to call
155  Register registers[] = {r1, r0};
156  data->InitializePlatformSpecific(arraysize(registers), registers);
157}
158
159void CallForwardVarargsDescriptor::InitializePlatformSpecific(
160    CallInterfaceDescriptorData* data) {
161  // r2 : start index (to support rest parameters)
162  // r1 : the target to call
163  Register registers[] = {r1, r2};
164  data->InitializePlatformSpecific(arraysize(registers), registers);
165}
166
167void ConstructStubDescriptor::InitializePlatformSpecific(
168    CallInterfaceDescriptorData* data) {
169  // r0 : number of arguments
170  // r1 : the target to call
171  // r3 : the new target
172  // r2 : allocation site or undefined
173  Register registers[] = {r1, r3, r0, r2};
174  data->InitializePlatformSpecific(arraysize(registers), registers);
175}
176
177
178void ConstructTrampolineDescriptor::InitializePlatformSpecific(
179    CallInterfaceDescriptorData* data) {
180  // r0 : number of arguments
181  // r1 : the target to call
182  // r3 : the new target
183  Register registers[] = {r1, r3, r0};
184  data->InitializePlatformSpecific(arraysize(registers), registers);
185}
186
187
188void TransitionElementsKindDescriptor::InitializePlatformSpecific(
189    CallInterfaceDescriptorData* data) {
190  Register registers[] = {r0, r1};
191  data->InitializePlatformSpecific(arraysize(registers), registers);
192}
193
194
195void AllocateHeapNumberDescriptor::InitializePlatformSpecific(
196    CallInterfaceDescriptorData* data) {
197  data->InitializePlatformSpecific(0, nullptr, nullptr);
198}
199
200void ArrayConstructorDescriptor::InitializePlatformSpecific(
201    CallInterfaceDescriptorData* data) {
202  // kTarget, kNewTarget, kActualArgumentsCount, kAllocationSite
203  Register registers[] = {r1, r3, r0, r2};
204  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
205}
206
207void ArrayNoArgumentConstructorDescriptor::InitializePlatformSpecific(
208    CallInterfaceDescriptorData* data) {
209  // register state
210  // r0 -- number of arguments
211  // r1 -- function
212  // r2 -- allocation site with elements kind
213  Register registers[] = {r1, r2, r0};
214  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
215}
216
217void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific(
218    CallInterfaceDescriptorData* data) {
219  // register state
220  // r0 -- number of arguments
221  // r1 -- function
222  // r2 -- allocation site with elements kind
223  Register registers[] = {r1, r2, r0};
224  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
225}
226
227void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
228    CallInterfaceDescriptorData* data) {
229  // stack param count needs (constructor pointer, and single argument)
230  Register registers[] = {r1, r2, r0};
231  data->InitializePlatformSpecific(arraysize(registers), registers);
232}
233
234
235void VarArgFunctionDescriptor::InitializePlatformSpecific(
236    CallInterfaceDescriptorData* data) {
237  // stack param count needs (arg count)
238  Register registers[] = {r0};
239  data->InitializePlatformSpecific(arraysize(registers), registers);
240}
241
242void CompareDescriptor::InitializePlatformSpecific(
243    CallInterfaceDescriptorData* data) {
244  Register registers[] = {r1, r0};
245  data->InitializePlatformSpecific(arraysize(registers), registers);
246}
247
248
249void BinaryOpDescriptor::InitializePlatformSpecific(
250    CallInterfaceDescriptorData* data) {
251  Register registers[] = {r1, r0};
252  data->InitializePlatformSpecific(arraysize(registers), registers);
253}
254
255
256void BinaryOpWithAllocationSiteDescriptor::InitializePlatformSpecific(
257    CallInterfaceDescriptorData* data) {
258  Register registers[] = {r2, r1, r0};
259  data->InitializePlatformSpecific(arraysize(registers), registers);
260}
261
262void BinaryOpWithVectorDescriptor::InitializePlatformSpecific(
263    CallInterfaceDescriptorData* data) {
264  // register state
265  // r1 -- lhs
266  // r0 -- rhs
267  // r4 -- slot id
268  // r3 -- vector
269  Register registers[] = {r1, r0, r4, r3};
270  data->InitializePlatformSpecific(arraysize(registers), registers);
271}
272
273void CountOpDescriptor::InitializePlatformSpecific(
274    CallInterfaceDescriptorData* data) {
275  Register registers[] = {r1};
276  data->InitializePlatformSpecific(arraysize(registers), registers);
277}
278
279void StringAddDescriptor::InitializePlatformSpecific(
280    CallInterfaceDescriptorData* data) {
281  Register registers[] = {r1, r0};
282  data->InitializePlatformSpecific(arraysize(registers), registers);
283}
284
285
286void KeyedDescriptor::InitializePlatformSpecific(
287    CallInterfaceDescriptorData* data) {
288  static PlatformInterfaceDescriptor noInlineDescriptor =
289      PlatformInterfaceDescriptor(NEVER_INLINE_TARGET_ADDRESS);
290
291  Register registers[] = {
292      r2,  // key
293  };
294  data->InitializePlatformSpecific(arraysize(registers), registers,
295                                   &noInlineDescriptor);
296}
297
298
299void NamedDescriptor::InitializePlatformSpecific(
300    CallInterfaceDescriptorData* data) {
301  static PlatformInterfaceDescriptor noInlineDescriptor =
302      PlatformInterfaceDescriptor(NEVER_INLINE_TARGET_ADDRESS);
303
304  Register registers[] = {
305      r2,  // name
306  };
307  data->InitializePlatformSpecific(arraysize(registers), registers,
308                                   &noInlineDescriptor);
309}
310
311
312void CallHandlerDescriptor::InitializePlatformSpecific(
313    CallInterfaceDescriptorData* data) {
314  static PlatformInterfaceDescriptor default_descriptor =
315      PlatformInterfaceDescriptor(CAN_INLINE_TARGET_ADDRESS);
316
317  Register registers[] = {
318      r0,  // receiver
319  };
320  data->InitializePlatformSpecific(arraysize(registers), registers,
321                                   &default_descriptor);
322}
323
324
325void ArgumentAdaptorDescriptor::InitializePlatformSpecific(
326    CallInterfaceDescriptorData* data) {
327  static PlatformInterfaceDescriptor default_descriptor =
328      PlatformInterfaceDescriptor(CAN_INLINE_TARGET_ADDRESS);
329
330  Register registers[] = {
331      r1,  // JSFunction
332      r3,  // the new target
333      r0,  // actual number of arguments
334      r2,  // expected number of arguments
335  };
336  data->InitializePlatformSpecific(arraysize(registers), registers,
337                                   &default_descriptor);
338}
339
340void ApiCallbackDescriptor::InitializePlatformSpecific(
341    CallInterfaceDescriptorData* data) {
342  static PlatformInterfaceDescriptor default_descriptor =
343      PlatformInterfaceDescriptor(CAN_INLINE_TARGET_ADDRESS);
344
345  Register registers[] = {
346      r0,  // callee
347      r4,  // call_data
348      r2,  // holder
349      r1,  // api_function_address
350  };
351  data->InitializePlatformSpecific(arraysize(registers), registers,
352                                   &default_descriptor);
353}
354
355void InterpreterDispatchDescriptor::InitializePlatformSpecific(
356    CallInterfaceDescriptorData* data) {
357  Register registers[] = {
358      kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
359      kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
360  data->InitializePlatformSpecific(arraysize(registers), registers);
361}
362
363void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
364    CallInterfaceDescriptorData* data) {
365  Register registers[] = {
366      r0,  // argument count (not including receiver)
367      r2,  // address of first argument
368      r1   // the target callable to be call
369  };
370  data->InitializePlatformSpecific(arraysize(registers), registers);
371}
372
373void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
374    CallInterfaceDescriptorData* data) {
375  Register registers[] = {
376      r0,  // argument count (not including receiver)
377      r3,  // new target
378      r1,  // constructor to call
379      r2,  // allocation site feedback if available, undefined otherwise
380      r4   // address of the first argument
381  };
382  data->InitializePlatformSpecific(arraysize(registers), registers);
383}
384
385void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific(
386    CallInterfaceDescriptorData* data) {
387  Register registers[] = {
388      r0,  // argument count (not including receiver)
389      r1,  // target to call checked to be Array function
390      r2,  // allocation site feedback if available, undefined otherwise
391      r3   // address of the first argument
392  };
393  data->InitializePlatformSpecific(arraysize(registers), registers);
394}
395
396void InterpreterCEntryDescriptor::InitializePlatformSpecific(
397    CallInterfaceDescriptorData* data) {
398  Register registers[] = {
399      r0,  // argument count (argc)
400      r2,  // address of first argument (argv)
401      r1   // the runtime function to call
402  };
403  data->InitializePlatformSpecific(arraysize(registers), registers);
404}
405
406void ResumeGeneratorDescriptor::InitializePlatformSpecific(
407    CallInterfaceDescriptorData* data) {
408  Register registers[] = {
409      r0,  // the value to pass to the generator
410      r1,  // the JSGeneratorObject to resume
411      r2   // the resume mode (tagged)
412  };
413  data->InitializePlatformSpecific(arraysize(registers), registers);
414}
415
416void FrameDropperTrampolineDescriptor::InitializePlatformSpecific(
417    CallInterfaceDescriptorData* data) {
418  Register registers[] = {
419      r1,  // loaded new FP
420  };
421  data->InitializePlatformSpecific(arraysize(registers), registers);
422}
423
424}  // namespace internal
425}  // namespace v8
426
427#endif  // V8_TARGET_ARCH_ARM
428