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