blob: ea3d5d4e441078350761bb3c98a0ae5f4e9abb05 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2015 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_INTERPRETER_BYTECODE_TRAITS_H_
6#define V8_INTERPRETER_BYTECODE_TRAITS_H_
7
8#include "src/interpreter/bytecodes.h"
9
10namespace v8 {
11namespace internal {
12namespace interpreter {
13
Ben Murdochda12d292016-06-02 14:46:10 +010014template <OperandTypeInfo>
15struct OperandTypeInfoTraits {
16 static const bool kIsScalable = false;
17 static const bool kIsUnsigned = false;
18 static const OperandSize kUnscaledSize = OperandSize::kNone;
19};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020
Ben Murdochda12d292016-06-02 14:46:10 +010021#define DECLARE_OPERAND_TYPE_INFO(Name, Scalable, Unsigned, BaseSize) \
22 template <> \
23 struct OperandTypeInfoTraits<OperandTypeInfo::k##Name> { \
24 static const bool kIsScalable = Scalable; \
25 static const bool kIsUnsigned = Unsigned; \
26 static const OperandSize kUnscaledSize = BaseSize; \
27 };
28OPERAND_TYPE_INFO_LIST(DECLARE_OPERAND_TYPE_INFO)
29#undef DECLARE_OPERAND_TYPE_INFO
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030
31template <OperandType>
Ben Murdochda12d292016-06-02 14:46:10 +010032struct OperandTraits {
Ben Murdoch61f157c2016-09-16 13:49:30 +010033 typedef OperandTypeInfoTraits<OperandTypeInfo::kNone> TypeInfoTraits;
34 static const OperandTypeInfo kOperandTypeInfo = OperandTypeInfo::kNone;
Ben Murdochda12d292016-06-02 14:46:10 +010035};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000036
Ben Murdoch61f157c2016-09-16 13:49:30 +010037#define DECLARE_OPERAND_TYPE_TRAITS(Name, InfoType) \
38 template <> \
39 struct OperandTraits<OperandType::k##Name> { \
40 typedef OperandTypeInfoTraits<InfoType> TypeInfoTraits; \
41 static const OperandTypeInfo kOperandTypeInfo = InfoType; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000042 };
Ben Murdochda12d292016-06-02 14:46:10 +010043OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE_TRAITS)
44#undef DECLARE_OPERAND_TYPE_TRAITS
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000045
Ben Murdochc5610432016-08-08 18:44:38 +010046template <OperandType operand_type, OperandScale operand_scale>
47struct OperandScaler {
48 template <bool, OperandSize, OperandScale>
49 struct Helper {
50 static const int kSize = 0;
51 };
52 template <OperandSize size, OperandScale scale>
53 struct Helper<false, size, scale> {
54 static const int kSize = static_cast<int>(size);
55 };
56 template <OperandSize size, OperandScale scale>
57 struct Helper<true, size, scale> {
58 static const int kSize = static_cast<int>(size) * static_cast<int>(scale);
59 };
60
61 static const int kSize =
Ben Murdoch61f157c2016-09-16 13:49:30 +010062 Helper<OperandTraits<operand_type>::TypeInfoTraits::kIsScalable,
63 OperandTraits<operand_type>::TypeInfoTraits::kUnscaledSize,
Ben Murdochc5610432016-08-08 18:44:38 +010064 operand_scale>::kSize;
65 static const OperandSize kOperandSize = static_cast<OperandSize>(kSize);
66};
67
Ben Murdoch097c5b22016-05-18 11:27:45 +010068template <OperandType>
69struct RegisterOperandTraits {
70 static const int kIsRegisterOperand = 0;
71};
72
73#define DECLARE_REGISTER_OPERAND(Name, _) \
74 template <> \
75 struct RegisterOperandTraits<OperandType::k##Name> { \
76 static const int kIsRegisterOperand = 1; \
77 };
78REGISTER_OPERAND_TYPE_LIST(DECLARE_REGISTER_OPERAND)
79#undef DECLARE_REGISTER_OPERAND
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000080
Ben Murdochda12d292016-06-02 14:46:10 +010081template <AccumulatorUse, OperandType...>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082struct BytecodeTraits {};
83
Ben Murdochda12d292016-06-02 14:46:10 +010084template <AccumulatorUse accumulator_use, OperandType operand_0,
85 OperandType operand_1, OperandType operand_2, OperandType operand_3>
86struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2,
87 operand_3> {
Ben Murdochc5610432016-08-08 18:44:38 +010088 static const OperandType* GetOperandTypes() {
89 static const OperandType operand_types[] = {operand_0, operand_1, operand_2,
90 operand_3, OperandType::kNone};
91 return operand_types;
92 }
93
Ben Murdoch61f157c2016-09-16 13:49:30 +010094 static const OperandTypeInfo* GetOperandTypeInfos() {
95 static const OperandTypeInfo operand_type_infos[] = {
96 OperandTraits<operand_0>::kOperandTypeInfo,
97 OperandTraits<operand_1>::kOperandTypeInfo,
98 OperandTraits<operand_2>::kOperandTypeInfo,
99 OperandTraits<operand_3>::kOperandTypeInfo, OperandTypeInfo::kNone};
100 return operand_type_infos;
101 }
102
103 static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
Ben Murdochc5610432016-08-08 18:44:38 +0100104 switch (operand_scale) {
105#define CASE(Name, _) \
106 case OperandScale::k##Name: { \
107 static const OperandSize kOperandSizes[] = { \
108 OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \
109 OperandScaler<operand_1, OperandScale::k##Name>::kOperandSize, \
110 OperandScaler<operand_2, OperandScale::k##Name>::kOperandSize, \
111 OperandScaler<operand_3, OperandScale::k##Name>::kOperandSize, \
112 }; \
Ben Murdoch61f157c2016-09-16 13:49:30 +0100113 return kOperandSizes; \
Ben Murdochc5610432016-08-08 18:44:38 +0100114 }
115 OPERAND_SCALE_LIST(CASE)
116#undef CASE
117 }
118 UNREACHABLE();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100119 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000120 }
121
Ben Murdoch097c5b22016-05-18 11:27:45 +0100122 template <OperandType ot>
123 static inline bool HasAnyOperandsOfType() {
124 return operand_0 == ot || operand_1 == ot || operand_2 == ot ||
125 operand_3 == ot;
126 }
127
Ben Murdochda12d292016-06-02 14:46:10 +0100128 static inline bool IsScalable() {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100129 return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
130 OperandTraits<operand_1>::TypeInfoTraits::kIsScalable |
131 OperandTraits<operand_2>::TypeInfoTraits::kIsScalable |
132 OperandTraits<operand_3>::TypeInfoTraits::kIsScalable);
Ben Murdochda12d292016-06-02 14:46:10 +0100133 }
134
135 static const AccumulatorUse kAccumulatorUse = accumulator_use;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000136 static const int kOperandCount = 4;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100137 static const int kRegisterOperandCount =
138 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
139 RegisterOperandTraits<operand_1>::kIsRegisterOperand +
140 RegisterOperandTraits<operand_2>::kIsRegisterOperand +
141 RegisterOperandTraits<operand_3>::kIsRegisterOperand;
142 static const int kRegisterOperandBitmap =
143 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
144 (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1) +
145 (RegisterOperandTraits<operand_2>::kIsRegisterOperand << 2) +
146 (RegisterOperandTraits<operand_3>::kIsRegisterOperand << 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147};
148
Ben Murdochda12d292016-06-02 14:46:10 +0100149template <AccumulatorUse accumulator_use, OperandType operand_0,
150 OperandType operand_1, OperandType operand_2>
151struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2> {
Ben Murdochc5610432016-08-08 18:44:38 +0100152 static const OperandType* GetOperandTypes() {
153 static const OperandType operand_types[] = {operand_0, operand_1, operand_2,
154 OperandType::kNone};
155 return operand_types;
156 }
157
Ben Murdoch61f157c2016-09-16 13:49:30 +0100158 static const OperandTypeInfo* GetOperandTypeInfos() {
159 static const OperandTypeInfo operand_type_infos[] = {
160 OperandTraits<operand_0>::kOperandTypeInfo,
161 OperandTraits<operand_1>::kOperandTypeInfo,
162 OperandTraits<operand_2>::kOperandTypeInfo, OperandTypeInfo::kNone};
163 return operand_type_infos;
164 }
165
166 static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
Ben Murdochc5610432016-08-08 18:44:38 +0100167 switch (operand_scale) {
168#define CASE(Name, _) \
169 case OperandScale::k##Name: { \
170 static const OperandSize kOperandSizes[] = { \
171 OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \
172 OperandScaler<operand_1, OperandScale::k##Name>::kOperandSize, \
173 OperandScaler<operand_2, OperandScale::k##Name>::kOperandSize, \
174 }; \
Ben Murdoch61f157c2016-09-16 13:49:30 +0100175 return kOperandSizes; \
Ben Murdochc5610432016-08-08 18:44:38 +0100176 }
177 OPERAND_SCALE_LIST(CASE)
178#undef CASE
179 }
180 UNREACHABLE();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100181 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182 }
183
Ben Murdoch097c5b22016-05-18 11:27:45 +0100184 template <OperandType ot>
185 static inline bool HasAnyOperandsOfType() {
186 return operand_0 == ot || operand_1 == ot || operand_2 == ot;
187 }
188
Ben Murdochda12d292016-06-02 14:46:10 +0100189 static inline bool IsScalable() {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100190 return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
191 OperandTraits<operand_1>::TypeInfoTraits::kIsScalable |
192 OperandTraits<operand_2>::TypeInfoTraits::kIsScalable);
Ben Murdochda12d292016-06-02 14:46:10 +0100193 }
194
195 static const AccumulatorUse kAccumulatorUse = accumulator_use;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000196 static const int kOperandCount = 3;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100197 static const int kRegisterOperandCount =
198 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
199 RegisterOperandTraits<operand_1>::kIsRegisterOperand +
200 RegisterOperandTraits<operand_2>::kIsRegisterOperand;
201 static const int kRegisterOperandBitmap =
202 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
203 (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1) +
204 (RegisterOperandTraits<operand_2>::kIsRegisterOperand << 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000205};
206
Ben Murdochda12d292016-06-02 14:46:10 +0100207template <AccumulatorUse accumulator_use, OperandType operand_0,
208 OperandType operand_1>
209struct BytecodeTraits<accumulator_use, operand_0, operand_1> {
Ben Murdochc5610432016-08-08 18:44:38 +0100210 static const OperandType* GetOperandTypes() {
211 static const OperandType operand_types[] = {operand_0, operand_1,
212 OperandType::kNone};
213 return operand_types;
214 }
215
Ben Murdoch61f157c2016-09-16 13:49:30 +0100216 static const OperandTypeInfo* GetOperandTypeInfos() {
217 static const OperandTypeInfo operand_type_infos[] = {
218 OperandTraits<operand_0>::kOperandTypeInfo,
219 OperandTraits<operand_1>::kOperandTypeInfo, OperandTypeInfo::kNone};
220 return operand_type_infos;
221 }
222
223 static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
Ben Murdochc5610432016-08-08 18:44:38 +0100224 switch (operand_scale) {
225#define CASE(Name, _) \
226 case OperandScale::k##Name: { \
227 static const OperandSize kOperandSizes[] = { \
228 OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \
229 OperandScaler<operand_1, OperandScale::k##Name>::kOperandSize, \
230 }; \
Ben Murdoch61f157c2016-09-16 13:49:30 +0100231 return kOperandSizes; \
Ben Murdochc5610432016-08-08 18:44:38 +0100232 }
233 OPERAND_SCALE_LIST(CASE)
234#undef CASE
235 }
236 UNREACHABLE();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100237 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000238 }
239
Ben Murdoch097c5b22016-05-18 11:27:45 +0100240 template <OperandType ot>
241 static inline bool HasAnyOperandsOfType() {
242 return operand_0 == ot || operand_1 == ot;
243 }
244
Ben Murdochda12d292016-06-02 14:46:10 +0100245 static inline bool IsScalable() {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100246 return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
247 OperandTraits<operand_1>::TypeInfoTraits::kIsScalable);
Ben Murdochda12d292016-06-02 14:46:10 +0100248 }
249
250 static const AccumulatorUse kAccumulatorUse = accumulator_use;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000251 static const int kOperandCount = 2;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100252 static const int kRegisterOperandCount =
253 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
254 RegisterOperandTraits<operand_1>::kIsRegisterOperand;
255 static const int kRegisterOperandBitmap =
256 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
257 (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000258};
259
Ben Murdochda12d292016-06-02 14:46:10 +0100260template <AccumulatorUse accumulator_use, OperandType operand_0>
261struct BytecodeTraits<accumulator_use, operand_0> {
Ben Murdochc5610432016-08-08 18:44:38 +0100262 static const OperandType* GetOperandTypes() {
263 static const OperandType operand_types[] = {operand_0, OperandType::kNone};
264 return operand_types;
265 }
266
Ben Murdoch61f157c2016-09-16 13:49:30 +0100267 static const OperandTypeInfo* GetOperandTypeInfos() {
268 static const OperandTypeInfo operand_type_infos[] = {
269 OperandTraits<operand_0>::kOperandTypeInfo, OperandTypeInfo::kNone};
270 return operand_type_infos;
271 }
272
273 static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
Ben Murdochc5610432016-08-08 18:44:38 +0100274 switch (operand_scale) {
275#define CASE(Name, _) \
276 case OperandScale::k##Name: { \
277 static const OperandSize kOperandSizes[] = { \
278 OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \
279 }; \
Ben Murdoch61f157c2016-09-16 13:49:30 +0100280 return kOperandSizes; \
Ben Murdochc5610432016-08-08 18:44:38 +0100281 }
282 OPERAND_SCALE_LIST(CASE)
283#undef CASE
284 }
285 UNREACHABLE();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100286 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000287 }
288
Ben Murdoch097c5b22016-05-18 11:27:45 +0100289 template <OperandType ot>
290 static inline bool HasAnyOperandsOfType() {
291 return operand_0 == ot;
292 }
293
Ben Murdochda12d292016-06-02 14:46:10 +0100294 static inline bool IsScalable() {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100295 return OperandTraits<operand_0>::TypeInfoTraits::kIsScalable;
Ben Murdochda12d292016-06-02 14:46:10 +0100296 }
297
298 static const AccumulatorUse kAccumulatorUse = accumulator_use;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000299 static const int kOperandCount = 1;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100300 static const int kRegisterOperandCount =
301 RegisterOperandTraits<operand_0>::kIsRegisterOperand;
302 static const int kRegisterOperandBitmap =
303 RegisterOperandTraits<operand_0>::kIsRegisterOperand;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000304};
305
Ben Murdochda12d292016-06-02 14:46:10 +0100306template <AccumulatorUse accumulator_use>
307struct BytecodeTraits<accumulator_use> {
Ben Murdochc5610432016-08-08 18:44:38 +0100308 static const OperandType* GetOperandTypes() {
309 static const OperandType operand_types[] = {OperandType::kNone};
310 return operand_types;
311 }
312
Ben Murdoch61f157c2016-09-16 13:49:30 +0100313 static const OperandTypeInfo* GetOperandTypeInfos() {
314 static const OperandTypeInfo operand_type_infos[] = {
315 OperandTypeInfo::kNone};
316 return operand_type_infos;
317 }
318
319 static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
320 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000321 }
322
Ben Murdoch097c5b22016-05-18 11:27:45 +0100323 template <OperandType ot>
324 static inline bool HasAnyOperandsOfType() {
325 return false;
326 }
327
Ben Murdochda12d292016-06-02 14:46:10 +0100328 static inline bool IsScalable() { return false; }
329
330 static const AccumulatorUse kAccumulatorUse = accumulator_use;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000331 static const int kOperandCount = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100332 static const int kRegisterOperandCount = 0;
333 static const int kRegisterOperandBitmap = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000334};
335
Ben Murdochda12d292016-06-02 14:46:10 +0100336static OperandSize ScaledOperandSize(OperandType operand_type,
337 OperandScale operand_scale) {
Ben Murdochc5610432016-08-08 18:44:38 +0100338 STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 &&
339 OperandScale::kLast == OperandScale::kQuadruple);
340 int index = static_cast<int>(operand_scale) >> 1;
Ben Murdochda12d292016-06-02 14:46:10 +0100341 switch (operand_type) {
Ben Murdochc5610432016-08-08 18:44:38 +0100342#define CASE(Name, TypeInfo) \
343 case OperandType::k##Name: { \
344 static const OperandSize kOperandSizes[] = { \
345 OperandScaler<OperandType::k##Name, \
346 OperandScale::kSingle>::kOperandSize, \
347 OperandScaler<OperandType::k##Name, \
348 OperandScale::kDouble>::kOperandSize, \
349 OperandScaler<OperandType::k##Name, \
350 OperandScale::kQuadruple>::kOperandSize}; \
351 return kOperandSizes[index]; \
Ben Murdochda12d292016-06-02 14:46:10 +0100352 }
353 OPERAND_TYPE_LIST(CASE)
354#undef CASE
355 }
356 UNREACHABLE();
357 return OperandSize::kNone;
358}
359
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360} // namespace interpreter
361} // namespace internal
362} // namespace v8
363
364#endif // V8_INTERPRETER_BYTECODE_TRAITS_H_