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