2015-10-01 17:22:58 +00:00
|
|
|
// Copyright 2015 the V8 project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
#ifndef V8_INTERPRETER_BYTECODE_TRAITS_H_
|
|
|
|
#define V8_INTERPRETER_BYTECODE_TRAITS_H_
|
|
|
|
|
|
|
|
#include "src/interpreter/bytecodes.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
namespace interpreter {
|
|
|
|
|
2016-03-21 17:08:21 +00:00
|
|
|
template <OperandTypeInfo>
|
|
|
|
struct OperandTypeInfoTraits {
|
|
|
|
static const bool kIsScalable = false;
|
|
|
|
static const bool kIsUnsigned = false;
|
|
|
|
static const OperandSize kUnscaledSize = OperandSize::kNone;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define DECLARE_OPERAND_TYPE_INFO(Name, Scalable, Unsigned, BaseSize) \
|
|
|
|
template <> \
|
|
|
|
struct OperandTypeInfoTraits<OperandTypeInfo::k##Name> { \
|
|
|
|
static const bool kIsScalable = Scalable; \
|
|
|
|
static const bool kIsUnsigned = Unsigned; \
|
|
|
|
static const OperandSize kUnscaledSize = BaseSize; \
|
|
|
|
};
|
|
|
|
OPERAND_TYPE_INFO_LIST(DECLARE_OPERAND_TYPE_INFO)
|
|
|
|
#undef DECLARE_OPERAND_TYPE_INFO
|
|
|
|
|
2015-10-01 17:22:58 +00:00
|
|
|
template <OperandType>
|
2016-03-21 17:08:21 +00:00
|
|
|
struct OperandTraits {
|
2016-06-10 10:34:50 +00:00
|
|
|
typedef OperandTypeInfoTraits<OperandTypeInfo::kNone> TypeInfoTraits;
|
|
|
|
static const OperandTypeInfo kOperandTypeInfo = OperandTypeInfo::kNone;
|
2016-03-21 17:08:21 +00:00
|
|
|
};
|
2015-10-01 17:22:58 +00:00
|
|
|
|
2016-06-10 10:34:50 +00:00
|
|
|
#define DECLARE_OPERAND_TYPE_TRAITS(Name, InfoType) \
|
|
|
|
template <> \
|
|
|
|
struct OperandTraits<OperandType::k##Name> { \
|
|
|
|
typedef OperandTypeInfoTraits<InfoType> TypeInfoTraits; \
|
|
|
|
static const OperandTypeInfo kOperandTypeInfo = InfoType; \
|
2015-10-01 17:22:58 +00:00
|
|
|
};
|
2016-03-21 17:08:21 +00:00
|
|
|
OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE_TRAITS)
|
|
|
|
#undef DECLARE_OPERAND_TYPE_TRAITS
|
2015-10-01 17:22:58 +00:00
|
|
|
|
2016-05-12 19:18:07 +00:00
|
|
|
template <OperandType operand_type, OperandScale operand_scale>
|
|
|
|
struct OperandScaler {
|
|
|
|
template <bool, OperandSize, OperandScale>
|
|
|
|
struct Helper {
|
|
|
|
static const int kSize = 0;
|
|
|
|
};
|
|
|
|
template <OperandSize size, OperandScale scale>
|
|
|
|
struct Helper<false, size, scale> {
|
|
|
|
static const int kSize = static_cast<int>(size);
|
|
|
|
};
|
|
|
|
template <OperandSize size, OperandScale scale>
|
|
|
|
struct Helper<true, size, scale> {
|
|
|
|
static const int kSize = static_cast<int>(size) * static_cast<int>(scale);
|
|
|
|
};
|
|
|
|
|
|
|
|
static const int kSize =
|
2016-06-10 10:34:50 +00:00
|
|
|
Helper<OperandTraits<operand_type>::TypeInfoTraits::kIsScalable,
|
|
|
|
OperandTraits<operand_type>::TypeInfoTraits::kUnscaledSize,
|
2016-05-12 19:18:07 +00:00
|
|
|
operand_scale>::kSize;
|
|
|
|
static const OperandSize kOperandSize = static_cast<OperandSize>(kSize);
|
|
|
|
};
|
|
|
|
|
2016-01-26 13:55:28 +00:00
|
|
|
template <OperandType>
|
|
|
|
struct RegisterOperandTraits {
|
|
|
|
static const int kIsRegisterOperand = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define DECLARE_REGISTER_OPERAND(Name, _) \
|
|
|
|
template <> \
|
|
|
|
struct RegisterOperandTraits<OperandType::k##Name> { \
|
|
|
|
static const int kIsRegisterOperand = 1; \
|
|
|
|
};
|
|
|
|
REGISTER_OPERAND_TYPE_LIST(DECLARE_REGISTER_OPERAND)
|
|
|
|
#undef DECLARE_REGISTER_OPERAND
|
2015-10-01 17:22:58 +00:00
|
|
|
|
2016-04-06 07:57:35 +00:00
|
|
|
template <AccumulatorUse, OperandType...>
|
2015-10-01 17:22:58 +00:00
|
|
|
struct BytecodeTraits {};
|
|
|
|
|
2016-04-06 07:57:35 +00:00
|
|
|
template <AccumulatorUse accumulator_use, OperandType operand_0,
|
|
|
|
OperandType operand_1, OperandType operand_2, OperandType operand_3>
|
|
|
|
struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2,
|
|
|
|
operand_3> {
|
2016-05-12 19:18:07 +00:00
|
|
|
static const OperandType* GetOperandTypes() {
|
|
|
|
static const OperandType operand_types[] = {operand_0, operand_1, operand_2,
|
|
|
|
operand_3, OperandType::kNone};
|
|
|
|
return operand_types;
|
|
|
|
}
|
|
|
|
|
2016-06-10 10:34:50 +00:00
|
|
|
static const OperandTypeInfo* GetOperandTypeInfos() {
|
|
|
|
static const OperandTypeInfo operand_type_infos[] = {
|
|
|
|
OperandTraits<operand_0>::kOperandTypeInfo,
|
|
|
|
OperandTraits<operand_1>::kOperandTypeInfo,
|
|
|
|
OperandTraits<operand_2>::kOperandTypeInfo,
|
|
|
|
OperandTraits<operand_3>::kOperandTypeInfo, OperandTypeInfo::kNone};
|
|
|
|
return operand_type_infos;
|
|
|
|
}
|
|
|
|
|
2016-01-26 13:55:28 +00:00
|
|
|
template <OperandType ot>
|
|
|
|
static inline bool HasAnyOperandsOfType() {
|
|
|
|
return operand_0 == ot || operand_1 == ot || operand_2 == ot ||
|
|
|
|
operand_3 == ot;
|
|
|
|
}
|
|
|
|
|
2016-03-21 17:08:21 +00:00
|
|
|
static inline bool IsScalable() {
|
2016-06-10 10:34:50 +00:00
|
|
|
return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
|
|
|
|
OperandTraits<operand_1>::TypeInfoTraits::kIsScalable |
|
|
|
|
OperandTraits<operand_2>::TypeInfoTraits::kIsScalable |
|
|
|
|
OperandTraits<operand_3>::TypeInfoTraits::kIsScalable);
|
2016-03-21 17:08:21 +00:00
|
|
|
}
|
|
|
|
|
2016-04-06 07:57:35 +00:00
|
|
|
static const AccumulatorUse kAccumulatorUse = accumulator_use;
|
2015-10-01 17:22:58 +00:00
|
|
|
static const int kOperandCount = 4;
|
2016-01-26 13:55:28 +00:00
|
|
|
static const int kRegisterOperandCount =
|
|
|
|
RegisterOperandTraits<operand_0>::kIsRegisterOperand +
|
|
|
|
RegisterOperandTraits<operand_1>::kIsRegisterOperand +
|
|
|
|
RegisterOperandTraits<operand_2>::kIsRegisterOperand +
|
|
|
|
RegisterOperandTraits<operand_3>::kIsRegisterOperand;
|
2015-10-01 17:22:58 +00:00
|
|
|
};
|
|
|
|
|
2016-04-06 07:57:35 +00:00
|
|
|
template <AccumulatorUse accumulator_use, OperandType operand_0,
|
|
|
|
OperandType operand_1, OperandType operand_2>
|
|
|
|
struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2> {
|
2016-05-12 19:18:07 +00:00
|
|
|
static const OperandType* GetOperandTypes() {
|
|
|
|
static const OperandType operand_types[] = {operand_0, operand_1, operand_2,
|
|
|
|
OperandType::kNone};
|
|
|
|
return operand_types;
|
|
|
|
}
|
|
|
|
|
2016-06-10 10:34:50 +00:00
|
|
|
static const OperandTypeInfo* GetOperandTypeInfos() {
|
|
|
|
static const OperandTypeInfo operand_type_infos[] = {
|
|
|
|
OperandTraits<operand_0>::kOperandTypeInfo,
|
|
|
|
OperandTraits<operand_1>::kOperandTypeInfo,
|
|
|
|
OperandTraits<operand_2>::kOperandTypeInfo, OperandTypeInfo::kNone};
|
|
|
|
return operand_type_infos;
|
|
|
|
}
|
|
|
|
|
2016-01-26 13:55:28 +00:00
|
|
|
template <OperandType ot>
|
|
|
|
static inline bool HasAnyOperandsOfType() {
|
|
|
|
return operand_0 == ot || operand_1 == ot || operand_2 == ot;
|
|
|
|
}
|
|
|
|
|
2016-03-21 17:08:21 +00:00
|
|
|
static inline bool IsScalable() {
|
2016-06-10 10:34:50 +00:00
|
|
|
return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
|
|
|
|
OperandTraits<operand_1>::TypeInfoTraits::kIsScalable |
|
|
|
|
OperandTraits<operand_2>::TypeInfoTraits::kIsScalable);
|
2016-03-21 17:08:21 +00:00
|
|
|
}
|
|
|
|
|
2016-04-06 07:57:35 +00:00
|
|
|
static const AccumulatorUse kAccumulatorUse = accumulator_use;
|
2015-10-01 17:22:58 +00:00
|
|
|
static const int kOperandCount = 3;
|
2016-01-26 13:55:28 +00:00
|
|
|
static const int kRegisterOperandCount =
|
|
|
|
RegisterOperandTraits<operand_0>::kIsRegisterOperand +
|
|
|
|
RegisterOperandTraits<operand_1>::kIsRegisterOperand +
|
|
|
|
RegisterOperandTraits<operand_2>::kIsRegisterOperand;
|
2015-10-01 17:22:58 +00:00
|
|
|
};
|
|
|
|
|
2016-04-06 07:57:35 +00:00
|
|
|
template <AccumulatorUse accumulator_use, OperandType operand_0,
|
|
|
|
OperandType operand_1>
|
|
|
|
struct BytecodeTraits<accumulator_use, operand_0, operand_1> {
|
2016-05-12 19:18:07 +00:00
|
|
|
static const OperandType* GetOperandTypes() {
|
|
|
|
static const OperandType operand_types[] = {operand_0, operand_1,
|
|
|
|
OperandType::kNone};
|
|
|
|
return operand_types;
|
|
|
|
}
|
|
|
|
|
2016-06-10 10:34:50 +00:00
|
|
|
static const OperandTypeInfo* GetOperandTypeInfos() {
|
|
|
|
static const OperandTypeInfo operand_type_infos[] = {
|
|
|
|
OperandTraits<operand_0>::kOperandTypeInfo,
|
|
|
|
OperandTraits<operand_1>::kOperandTypeInfo, OperandTypeInfo::kNone};
|
|
|
|
return operand_type_infos;
|
|
|
|
}
|
|
|
|
|
2016-01-26 13:55:28 +00:00
|
|
|
template <OperandType ot>
|
|
|
|
static inline bool HasAnyOperandsOfType() {
|
|
|
|
return operand_0 == ot || operand_1 == ot;
|
|
|
|
}
|
|
|
|
|
2016-03-21 17:08:21 +00:00
|
|
|
static inline bool IsScalable() {
|
2016-06-10 10:34:50 +00:00
|
|
|
return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
|
|
|
|
OperandTraits<operand_1>::TypeInfoTraits::kIsScalable);
|
2016-03-21 17:08:21 +00:00
|
|
|
}
|
|
|
|
|
2016-04-06 07:57:35 +00:00
|
|
|
static const AccumulatorUse kAccumulatorUse = accumulator_use;
|
2015-10-01 17:22:58 +00:00
|
|
|
static const int kOperandCount = 2;
|
2016-01-26 13:55:28 +00:00
|
|
|
static const int kRegisterOperandCount =
|
|
|
|
RegisterOperandTraits<operand_0>::kIsRegisterOperand +
|
|
|
|
RegisterOperandTraits<operand_1>::kIsRegisterOperand;
|
2015-10-01 17:22:58 +00:00
|
|
|
};
|
|
|
|
|
2016-04-06 07:57:35 +00:00
|
|
|
template <AccumulatorUse accumulator_use, OperandType operand_0>
|
|
|
|
struct BytecodeTraits<accumulator_use, operand_0> {
|
2016-05-12 19:18:07 +00:00
|
|
|
static const OperandType* GetOperandTypes() {
|
|
|
|
static const OperandType operand_types[] = {operand_0, OperandType::kNone};
|
|
|
|
return operand_types;
|
|
|
|
}
|
|
|
|
|
2016-06-10 10:34:50 +00:00
|
|
|
static const OperandTypeInfo* GetOperandTypeInfos() {
|
|
|
|
static const OperandTypeInfo operand_type_infos[] = {
|
|
|
|
OperandTraits<operand_0>::kOperandTypeInfo, OperandTypeInfo::kNone};
|
|
|
|
return operand_type_infos;
|
|
|
|
}
|
|
|
|
|
2016-01-26 13:55:28 +00:00
|
|
|
template <OperandType ot>
|
|
|
|
static inline bool HasAnyOperandsOfType() {
|
|
|
|
return operand_0 == ot;
|
|
|
|
}
|
|
|
|
|
2016-03-21 17:08:21 +00:00
|
|
|
static inline bool IsScalable() {
|
2016-06-10 10:34:50 +00:00
|
|
|
return OperandTraits<operand_0>::TypeInfoTraits::kIsScalable;
|
2016-03-21 17:08:21 +00:00
|
|
|
}
|
|
|
|
|
2016-04-06 07:57:35 +00:00
|
|
|
static const AccumulatorUse kAccumulatorUse = accumulator_use;
|
2015-10-01 17:22:58 +00:00
|
|
|
static const int kOperandCount = 1;
|
2016-01-26 13:55:28 +00:00
|
|
|
static const int kRegisterOperandCount =
|
|
|
|
RegisterOperandTraits<operand_0>::kIsRegisterOperand;
|
2015-10-01 17:22:58 +00:00
|
|
|
};
|
|
|
|
|
2016-04-06 07:57:35 +00:00
|
|
|
template <AccumulatorUse accumulator_use>
|
|
|
|
struct BytecodeTraits<accumulator_use> {
|
2016-05-12 19:18:07 +00:00
|
|
|
static const OperandType* GetOperandTypes() {
|
|
|
|
static const OperandType operand_types[] = {OperandType::kNone};
|
|
|
|
return operand_types;
|
|
|
|
}
|
|
|
|
|
2016-06-10 10:34:50 +00:00
|
|
|
static const OperandTypeInfo* GetOperandTypeInfos() {
|
|
|
|
static const OperandTypeInfo operand_type_infos[] = {
|
|
|
|
OperandTypeInfo::kNone};
|
|
|
|
return operand_type_infos;
|
|
|
|
}
|
|
|
|
|
2016-01-26 13:55:28 +00:00
|
|
|
template <OperandType ot>
|
|
|
|
static inline bool HasAnyOperandsOfType() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-03-21 17:08:21 +00:00
|
|
|
static inline bool IsScalable() { return false; }
|
|
|
|
|
2016-04-06 07:57:35 +00:00
|
|
|
static const AccumulatorUse kAccumulatorUse = accumulator_use;
|
2015-10-01 17:22:58 +00:00
|
|
|
static const int kOperandCount = 0;
|
2016-01-26 13:55:28 +00:00
|
|
|
static const int kRegisterOperandCount = 0;
|
2015-10-01 17:22:58 +00:00
|
|
|
};
|
|
|
|
|
2016-03-21 17:08:21 +00:00
|
|
|
static OperandSize ScaledOperandSize(OperandType operand_type,
|
|
|
|
OperandScale operand_scale) {
|
2016-05-12 19:18:07 +00:00
|
|
|
STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 &&
|
|
|
|
OperandScale::kLast == OperandScale::kQuadruple);
|
|
|
|
int index = static_cast<int>(operand_scale) >> 1;
|
2016-03-21 17:08:21 +00:00
|
|
|
switch (operand_type) {
|
2016-05-12 19:18:07 +00:00
|
|
|
#define CASE(Name, TypeInfo) \
|
|
|
|
case OperandType::k##Name: { \
|
|
|
|
static const OperandSize kOperandSizes[] = { \
|
|
|
|
OperandScaler<OperandType::k##Name, \
|
|
|
|
OperandScale::kSingle>::kOperandSize, \
|
|
|
|
OperandScaler<OperandType::k##Name, \
|
|
|
|
OperandScale::kDouble>::kOperandSize, \
|
|
|
|
OperandScaler<OperandType::k##Name, \
|
|
|
|
OperandScale::kQuadruple>::kOperandSize}; \
|
|
|
|
return kOperandSizes[index]; \
|
2016-03-21 17:08:21 +00:00
|
|
|
}
|
|
|
|
OPERAND_TYPE_LIST(CASE)
|
|
|
|
#undef CASE
|
|
|
|
}
|
|
|
|
UNREACHABLE();
|
|
|
|
return OperandSize::kNone;
|
|
|
|
}
|
|
|
|
|
2015-10-01 17:22:58 +00:00
|
|
|
} // namespace interpreter
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|
|
|
|
|
|
|
|
#endif // V8_INTERPRETER_BYTECODE_TRAITS_H_
|