blob: e7d14325037a44ce8757fc9ed07be47d85a8f00f [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 {
33 typedef OperandTypeInfoTraits<OperandTypeInfo::kNone> TypeInfo;
34};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035
Ben Murdochda12d292016-06-02 14:46:10 +010036#define DECLARE_OPERAND_TYPE_TRAITS(Name, InfoType) \
37 template <> \
38 struct OperandTraits<OperandType::k##Name> { \
39 typedef OperandTypeInfoTraits<InfoType> TypeInfo; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040 };
Ben Murdochda12d292016-06-02 14:46:10 +010041OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE_TRAITS)
42#undef DECLARE_OPERAND_TYPE_TRAITS
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043
Ben Murdochc5610432016-08-08 18:44:38 +010044template <OperandType operand_type, OperandScale operand_scale>
45struct OperandScaler {
46 template <bool, OperandSize, OperandScale>
47 struct Helper {
48 static const int kSize = 0;
49 };
50 template <OperandSize size, OperandScale scale>
51 struct Helper<false, size, scale> {
52 static const int kSize = static_cast<int>(size);
53 };
54 template <OperandSize size, OperandScale scale>
55 struct Helper<true, size, scale> {
56 static const int kSize = static_cast<int>(size) * static_cast<int>(scale);
57 };
58
59 static const int kSize =
60 Helper<OperandTraits<operand_type>::TypeInfo::kIsScalable,
61 OperandTraits<operand_type>::TypeInfo::kUnscaledSize,
62 operand_scale>::kSize;
63 static const OperandSize kOperandSize = static_cast<OperandSize>(kSize);
64};
65
Ben Murdoch097c5b22016-05-18 11:27:45 +010066template <OperandType>
67struct RegisterOperandTraits {
68 static const int kIsRegisterOperand = 0;
69};
70
71#define DECLARE_REGISTER_OPERAND(Name, _) \
72 template <> \
73 struct RegisterOperandTraits<OperandType::k##Name> { \
74 static const int kIsRegisterOperand = 1; \
75 };
76REGISTER_OPERAND_TYPE_LIST(DECLARE_REGISTER_OPERAND)
77#undef DECLARE_REGISTER_OPERAND
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078
Ben Murdochda12d292016-06-02 14:46:10 +010079template <AccumulatorUse, OperandType...>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000080struct BytecodeTraits {};
81
Ben Murdochda12d292016-06-02 14:46:10 +010082template <AccumulatorUse accumulator_use, OperandType operand_0,
83 OperandType operand_1, OperandType operand_2, OperandType operand_3>
84struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2,
85 operand_3> {
Ben Murdochc5610432016-08-08 18:44:38 +010086 static const OperandType* GetOperandTypes() {
87 static const OperandType operand_types[] = {operand_0, operand_1, operand_2,
88 operand_3, OperandType::kNone};
89 return operand_types;
90 }
91
92 static OperandSize GetOperandSize(int i, OperandScale operand_scale) {
93 switch (operand_scale) {
94#define CASE(Name, _) \
95 case OperandScale::k##Name: { \
96 static const OperandSize kOperandSizes[] = { \
97 OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \
98 OperandScaler<operand_1, OperandScale::k##Name>::kOperandSize, \
99 OperandScaler<operand_2, OperandScale::k##Name>::kOperandSize, \
100 OperandScaler<operand_3, OperandScale::k##Name>::kOperandSize, \
101 }; \
102 DCHECK_LT(static_cast<size_t>(i), arraysize(kOperandSizes)); \
103 return kOperandSizes[i]; \
104 }
105 OPERAND_SCALE_LIST(CASE)
106#undef CASE
107 }
108 UNREACHABLE();
109 return OperandSize::kNone;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000110 }
111
Ben Murdoch097c5b22016-05-18 11:27:45 +0100112 template <OperandType ot>
113 static inline bool HasAnyOperandsOfType() {
114 return operand_0 == ot || operand_1 == ot || operand_2 == ot ||
115 operand_3 == ot;
116 }
117
Ben Murdochda12d292016-06-02 14:46:10 +0100118 static inline bool IsScalable() {
119 return (OperandTraits<operand_0>::TypeInfo::kIsScalable |
120 OperandTraits<operand_1>::TypeInfo::kIsScalable |
121 OperandTraits<operand_2>::TypeInfo::kIsScalable |
122 OperandTraits<operand_3>::TypeInfo::kIsScalable);
123 }
124
125 static const AccumulatorUse kAccumulatorUse = accumulator_use;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 static const int kOperandCount = 4;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100127 static const int kRegisterOperandCount =
128 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
129 RegisterOperandTraits<operand_1>::kIsRegisterOperand +
130 RegisterOperandTraits<operand_2>::kIsRegisterOperand +
131 RegisterOperandTraits<operand_3>::kIsRegisterOperand;
132 static const int kRegisterOperandBitmap =
133 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
134 (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1) +
135 (RegisterOperandTraits<operand_2>::kIsRegisterOperand << 2) +
136 (RegisterOperandTraits<operand_3>::kIsRegisterOperand << 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000137};
138
Ben Murdochda12d292016-06-02 14:46:10 +0100139template <AccumulatorUse accumulator_use, OperandType operand_0,
140 OperandType operand_1, OperandType operand_2>
141struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2> {
Ben Murdochc5610432016-08-08 18:44:38 +0100142 static const OperandType* GetOperandTypes() {
143 static const OperandType operand_types[] = {operand_0, operand_1, operand_2,
144 OperandType::kNone};
145 return operand_types;
146 }
147
148 static OperandSize GetOperandSize(int i, OperandScale operand_scale) {
149 switch (operand_scale) {
150#define CASE(Name, _) \
151 case OperandScale::k##Name: { \
152 static const OperandSize kOperandSizes[] = { \
153 OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \
154 OperandScaler<operand_1, OperandScale::k##Name>::kOperandSize, \
155 OperandScaler<operand_2, OperandScale::k##Name>::kOperandSize, \
156 }; \
157 DCHECK_LT(static_cast<size_t>(i), arraysize(kOperandSizes)); \
158 return kOperandSizes[i]; \
159 }
160 OPERAND_SCALE_LIST(CASE)
161#undef CASE
162 }
163 UNREACHABLE();
164 return OperandSize::kNone;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000165 }
166
Ben Murdoch097c5b22016-05-18 11:27:45 +0100167 template <OperandType ot>
168 static inline bool HasAnyOperandsOfType() {
169 return operand_0 == ot || operand_1 == ot || operand_2 == ot;
170 }
171
Ben Murdochda12d292016-06-02 14:46:10 +0100172 static inline bool IsScalable() {
173 return (OperandTraits<operand_0>::TypeInfo::kIsScalable |
174 OperandTraits<operand_1>::TypeInfo::kIsScalable |
175 OperandTraits<operand_2>::TypeInfo::kIsScalable);
176 }
177
178 static const AccumulatorUse kAccumulatorUse = accumulator_use;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000179 static const int kOperandCount = 3;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100180 static const int kRegisterOperandCount =
181 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
182 RegisterOperandTraits<operand_1>::kIsRegisterOperand +
183 RegisterOperandTraits<operand_2>::kIsRegisterOperand;
184 static const int kRegisterOperandBitmap =
185 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
186 (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1) +
187 (RegisterOperandTraits<operand_2>::kIsRegisterOperand << 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000188};
189
Ben Murdochda12d292016-06-02 14:46:10 +0100190template <AccumulatorUse accumulator_use, OperandType operand_0,
191 OperandType operand_1>
192struct BytecodeTraits<accumulator_use, operand_0, operand_1> {
Ben Murdochc5610432016-08-08 18:44:38 +0100193 static const OperandType* GetOperandTypes() {
194 static const OperandType operand_types[] = {operand_0, operand_1,
195 OperandType::kNone};
196 return operand_types;
197 }
198
199 static OperandSize GetOperandSize(int i, OperandScale operand_scale) {
200 switch (operand_scale) {
201#define CASE(Name, _) \
202 case OperandScale::k##Name: { \
203 static const OperandSize kOperandSizes[] = { \
204 OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \
205 OperandScaler<operand_1, OperandScale::k##Name>::kOperandSize, \
206 }; \
207 DCHECK_LT(static_cast<size_t>(i), arraysize(kOperandSizes)); \
208 return kOperandSizes[i]; \
209 }
210 OPERAND_SCALE_LIST(CASE)
211#undef CASE
212 }
213 UNREACHABLE();
214 return OperandSize::kNone;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000215 }
216
Ben Murdoch097c5b22016-05-18 11:27:45 +0100217 template <OperandType ot>
218 static inline bool HasAnyOperandsOfType() {
219 return operand_0 == ot || operand_1 == ot;
220 }
221
Ben Murdochda12d292016-06-02 14:46:10 +0100222 static inline bool IsScalable() {
223 return (OperandTraits<operand_0>::TypeInfo::kIsScalable |
224 OperandTraits<operand_1>::TypeInfo::kIsScalable);
225 }
226
227 static const AccumulatorUse kAccumulatorUse = accumulator_use;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000228 static const int kOperandCount = 2;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100229 static const int kRegisterOperandCount =
230 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
231 RegisterOperandTraits<operand_1>::kIsRegisterOperand;
232 static const int kRegisterOperandBitmap =
233 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
234 (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000235};
236
Ben Murdochda12d292016-06-02 14:46:10 +0100237template <AccumulatorUse accumulator_use, OperandType operand_0>
238struct BytecodeTraits<accumulator_use, operand_0> {
Ben Murdochc5610432016-08-08 18:44:38 +0100239 static const OperandType* GetOperandTypes() {
240 static const OperandType operand_types[] = {operand_0, OperandType::kNone};
241 return operand_types;
242 }
243
244 static OperandSize GetOperandSize(int i, OperandScale operand_scale) {
245 switch (operand_scale) {
246#define CASE(Name, _) \
247 case OperandScale::k##Name: { \
248 static const OperandSize kOperandSizes[] = { \
249 OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \
250 }; \
251 DCHECK_LT(static_cast<size_t>(i), arraysize(kOperandSizes)); \
252 return kOperandSizes[i]; \
253 }
254 OPERAND_SCALE_LIST(CASE)
255#undef CASE
256 }
257 UNREACHABLE();
258 return OperandSize::kNone;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000259 }
260
Ben Murdoch097c5b22016-05-18 11:27:45 +0100261 template <OperandType ot>
262 static inline bool HasAnyOperandsOfType() {
263 return operand_0 == ot;
264 }
265
Ben Murdochda12d292016-06-02 14:46:10 +0100266 static inline bool IsScalable() {
267 return OperandTraits<operand_0>::TypeInfo::kIsScalable;
268 }
269
270 static const AccumulatorUse kAccumulatorUse = accumulator_use;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000271 static const int kOperandCount = 1;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100272 static const int kRegisterOperandCount =
273 RegisterOperandTraits<operand_0>::kIsRegisterOperand;
274 static const int kRegisterOperandBitmap =
275 RegisterOperandTraits<operand_0>::kIsRegisterOperand;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000276};
277
Ben Murdochda12d292016-06-02 14:46:10 +0100278template <AccumulatorUse accumulator_use>
279struct BytecodeTraits<accumulator_use> {
Ben Murdochc5610432016-08-08 18:44:38 +0100280 static const OperandType* GetOperandTypes() {
281 static const OperandType operand_types[] = {OperandType::kNone};
282 return operand_types;
283 }
284
285 static OperandSize GetOperandSize(int i, OperandScale operand_scale) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000286 UNREACHABLE();
Ben Murdochc5610432016-08-08 18:44:38 +0100287 return OperandSize::kNone;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000288 }
289
Ben Murdoch097c5b22016-05-18 11:27:45 +0100290 template <OperandType ot>
291 static inline bool HasAnyOperandsOfType() {
292 return false;
293 }
294
Ben Murdochda12d292016-06-02 14:46:10 +0100295 static inline bool IsScalable() { return false; }
296
297 static const AccumulatorUse kAccumulatorUse = accumulator_use;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000298 static const int kOperandCount = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100299 static const int kRegisterOperandCount = 0;
300 static const int kRegisterOperandBitmap = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301};
302
Ben Murdochda12d292016-06-02 14:46:10 +0100303static OperandSize ScaledOperandSize(OperandType operand_type,
304 OperandScale operand_scale) {
Ben Murdochc5610432016-08-08 18:44:38 +0100305 STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 &&
306 OperandScale::kLast == OperandScale::kQuadruple);
307 int index = static_cast<int>(operand_scale) >> 1;
Ben Murdochda12d292016-06-02 14:46:10 +0100308 switch (operand_type) {
Ben Murdochc5610432016-08-08 18:44:38 +0100309#define CASE(Name, TypeInfo) \
310 case OperandType::k##Name: { \
311 static const OperandSize kOperandSizes[] = { \
312 OperandScaler<OperandType::k##Name, \
313 OperandScale::kSingle>::kOperandSize, \
314 OperandScaler<OperandType::k##Name, \
315 OperandScale::kDouble>::kOperandSize, \
316 OperandScaler<OperandType::k##Name, \
317 OperandScale::kQuadruple>::kOperandSize}; \
318 return kOperandSizes[index]; \
Ben Murdochda12d292016-06-02 14:46:10 +0100319 }
320 OPERAND_TYPE_LIST(CASE)
321#undef CASE
322 }
323 UNREACHABLE();
324 return OperandSize::kNone;
325}
326
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327} // namespace interpreter
328} // namespace internal
329} // namespace v8
330
331#endif // V8_INTERPRETER_BYTECODE_TRAITS_H_