|  | // Copyright 2016 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_OPERANDS_H_ | 
|  | #define V8_INTERPRETER_BYTECODE_OPERANDS_H_ | 
|  |  | 
|  | #include "src/base/bounds.h" | 
|  | #include "src/common/globals.h" | 
|  |  | 
|  | namespace v8 { | 
|  | namespace internal { | 
|  | namespace interpreter { | 
|  |  | 
|  | #define INVALID_OPERAND_TYPE_LIST(V) V(None, OperandTypeInfo::kNone) | 
|  |  | 
|  | #define REGISTER_INPUT_OPERAND_TYPE_LIST(V)        \ | 
|  | V(Reg, OperandTypeInfo::kScalableSignedByte)     \ | 
|  | V(RegList, OperandTypeInfo::kScalableSignedByte) \ | 
|  | V(RegPair, OperandTypeInfo::kScalableSignedByte) | 
|  |  | 
|  | #define REGISTER_OUTPUT_OPERAND_TYPE_LIST(V)          \ | 
|  | V(RegOut, OperandTypeInfo::kScalableSignedByte)     \ | 
|  | V(RegOutList, OperandTypeInfo::kScalableSignedByte) \ | 
|  | V(RegOutPair, OperandTypeInfo::kScalableSignedByte) \ | 
|  | V(RegOutTriple, OperandTypeInfo::kScalableSignedByte) | 
|  |  | 
|  | #define SIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V) \ | 
|  | V(Imm, OperandTypeInfo::kScalableSignedByte) | 
|  |  | 
|  | #define UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V) \ | 
|  | V(Idx, OperandTypeInfo::kScalableUnsignedByte)      \ | 
|  | V(UImm, OperandTypeInfo::kScalableUnsignedByte)     \ | 
|  | V(RegCount, OperandTypeInfo::kScalableUnsignedByte) | 
|  |  | 
|  | #define UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(V)    \ | 
|  | V(Flag8, OperandTypeInfo::kFixedUnsignedByte)       \ | 
|  | V(IntrinsicId, OperandTypeInfo::kFixedUnsignedByte) \ | 
|  | V(RuntimeId, OperandTypeInfo::kFixedUnsignedShort)  \ | 
|  | V(NativeContextIndex, OperandTypeInfo::kFixedUnsignedByte) | 
|  |  | 
|  | // Carefully ordered for operand type range checks below. | 
|  | #define NON_REGISTER_OPERAND_TYPE_LIST(V)       \ | 
|  | INVALID_OPERAND_TYPE_LIST(V)                  \ | 
|  | UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(V)    \ | 
|  | UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V) \ | 
|  | SIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V) | 
|  |  | 
|  | // Carefully ordered for operand type range checks below. | 
|  | #define REGISTER_OPERAND_TYPE_LIST(V) \ | 
|  | REGISTER_INPUT_OPERAND_TYPE_LIST(V) \ | 
|  | REGISTER_OUTPUT_OPERAND_TYPE_LIST(V) | 
|  |  | 
|  | // The list of operand types used by bytecodes. | 
|  | // Carefully ordered for operand type range checks below. | 
|  | #define OPERAND_TYPE_LIST(V)        \ | 
|  | NON_REGISTER_OPERAND_TYPE_LIST(V) \ | 
|  | REGISTER_OPERAND_TYPE_LIST(V) | 
|  |  | 
|  | // Enumeration of scaling factors applicable to scalable operands. Code | 
|  | // relies on being able to cast values to integer scaling values. | 
|  | #define OPERAND_SCALE_LIST(V) \ | 
|  | V(Single, 1)                \ | 
|  | V(Double, 2)                \ | 
|  | V(Quadruple, 4) | 
|  |  | 
|  | enum class OperandScale : uint8_t { | 
|  | #define DECLARE_OPERAND_SCALE(Name, Scale) k##Name = Scale, | 
|  | OPERAND_SCALE_LIST(DECLARE_OPERAND_SCALE) | 
|  | #undef DECLARE_OPERAND_SCALE | 
|  | kLast = kQuadruple | 
|  | }; | 
|  |  | 
|  | // Enumeration of the size classes of operand types used by | 
|  | // bytecodes. Code relies on being able to cast values to integer | 
|  | // types to get the size in bytes. | 
|  | enum class OperandSize : uint8_t { | 
|  | kNone = 0, | 
|  | kByte = 1, | 
|  | kShort = 2, | 
|  | kQuad = 4, | 
|  | kLast = kQuad | 
|  | }; | 
|  |  | 
|  | // Primitive operand info used that summarize properties of operands. | 
|  | // Columns are Name, IsScalable, IsUnsigned, UnscaledSize. | 
|  | #define OPERAND_TYPE_INFO_LIST(V)                         \ | 
|  | V(None, false, false, OperandSize::kNone)               \ | 
|  | V(ScalableSignedByte, true, false, OperandSize::kByte)  \ | 
|  | V(ScalableUnsignedByte, true, true, OperandSize::kByte) \ | 
|  | V(FixedUnsignedByte, false, true, OperandSize::kByte)   \ | 
|  | V(FixedUnsignedShort, false, true, OperandSize::kShort) | 
|  |  | 
|  | enum class OperandTypeInfo : uint8_t { | 
|  | #define DECLARE_OPERAND_TYPE_INFO(Name, ...) k##Name, | 
|  | OPERAND_TYPE_INFO_LIST(DECLARE_OPERAND_TYPE_INFO) | 
|  | #undef DECLARE_OPERAND_TYPE_INFO | 
|  | }; | 
|  |  | 
|  | // Enumeration of operand types used by bytecodes. | 
|  | enum class OperandType : uint8_t { | 
|  | #define DECLARE_OPERAND_TYPE(Name, _) k##Name, | 
|  | OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE) | 
|  | #undef DECLARE_OPERAND_TYPE | 
|  | #define COUNT_OPERAND_TYPES(x, _) +1 | 
|  | // The COUNT_OPERAND macro will turn this into kLast = -1 +1 +1... which will | 
|  | // evaluate to the same value as the last operand. | 
|  | kLast = -1 OPERAND_TYPE_LIST(COUNT_OPERAND_TYPES) | 
|  | #undef COUNT_OPERAND_TYPES | 
|  | }; | 
|  |  | 
|  | enum class AccumulatorUse : uint8_t { | 
|  | kNone = 0, | 
|  | kRead = 1 << 0, | 
|  | kWrite = 1 << 1, | 
|  | kReadWrite = kRead | kWrite | 
|  | }; | 
|  |  | 
|  | constexpr inline AccumulatorUse operator&(AccumulatorUse lhs, | 
|  | AccumulatorUse rhs) { | 
|  | return static_cast<AccumulatorUse>(static_cast<int>(lhs) & | 
|  | static_cast<int>(rhs)); | 
|  | } | 
|  |  | 
|  | constexpr inline AccumulatorUse operator|(AccumulatorUse lhs, | 
|  | AccumulatorUse rhs) { | 
|  | return static_cast<AccumulatorUse>(static_cast<int>(lhs) | | 
|  | static_cast<int>(rhs)); | 
|  | } | 
|  |  | 
|  | V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, | 
|  | const AccumulatorUse& use); | 
|  | V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, | 
|  | const OperandScale& operand_scale); | 
|  | V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, | 
|  | const OperandSize& operand_size); | 
|  | V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, | 
|  | const OperandType& operand_type); | 
|  |  | 
|  | class BytecodeOperands : public AllStatic { | 
|  | public: | 
|  | // The total number of bytecode operand types used. | 
|  | static const int kOperandTypeCount = static_cast<int>(OperandType::kLast) + 1; | 
|  |  | 
|  | // The total number of bytecode operand scales used. | 
|  | #define OPERAND_SCALE_COUNT(...) +1 | 
|  | static const int kOperandScaleCount = | 
|  | 0 OPERAND_SCALE_LIST(OPERAND_SCALE_COUNT); | 
|  | #undef OPERAND_SCALE_COUNT | 
|  |  | 
|  | static constexpr int OperandScaleAsIndex(OperandScale operand_scale) { | 
|  | #if V8_HAS_CXX14_CONSTEXPR | 
|  | #ifdef DEBUG | 
|  | int result = static_cast<int>(operand_scale) >> 1; | 
|  | switch (operand_scale) { | 
|  | case OperandScale::kSingle: | 
|  | DCHECK_EQ(0, result); | 
|  | break; | 
|  | case OperandScale::kDouble: | 
|  | DCHECK_EQ(1, result); | 
|  | break; | 
|  | case OperandScale::kQuadruple: | 
|  | DCHECK_EQ(2, result); | 
|  | break; | 
|  | default: | 
|  | UNREACHABLE(); | 
|  | } | 
|  | #endif | 
|  | #endif | 
|  | return static_cast<int>(operand_scale) >> 1; | 
|  | } | 
|  |  | 
|  | // Returns true if |accumulator_use| reads the accumulator. | 
|  | static constexpr bool ReadsAccumulator(AccumulatorUse accumulator_use) { | 
|  | return (accumulator_use & AccumulatorUse::kRead) == AccumulatorUse::kRead; | 
|  | } | 
|  |  | 
|  | // Returns true if |accumulator_use| writes the accumulator. | 
|  | static constexpr bool WritesAccumulator(AccumulatorUse accumulator_use) { | 
|  | return (accumulator_use & AccumulatorUse::kWrite) == AccumulatorUse::kWrite; | 
|  | } | 
|  |  | 
|  | // Returns true if |operand_type| is a scalable signed byte. | 
|  | static constexpr bool IsScalableSignedByte(OperandType operand_type) { | 
|  | return base::IsInRange(operand_type, OperandType::kImm, | 
|  | OperandType::kRegOutTriple); | 
|  | } | 
|  |  | 
|  | // Returns true if |operand_type| is a scalable unsigned byte. | 
|  | static constexpr bool IsScalableUnsignedByte(OperandType operand_type) { | 
|  | return base::IsInRange(operand_type, OperandType::kIdx, | 
|  | OperandType::kRegCount); | 
|  | } | 
|  | }; | 
|  |  | 
|  | }  // namespace interpreter | 
|  | }  // namespace internal | 
|  | }  // namespace v8 | 
|  |  | 
|  | #endif  // V8_INTERPRETER_BYTECODE_OPERANDS_H_ |