1 // Copyright 2016 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_OPERANDS_H_ 6 #define V8_INTERPRETER_BYTECODE_OPERANDS_H_ 7 8 #include "src/globals.h" 9 10 namespace v8 { 11 namespace internal { 12 namespace interpreter { 13 14 #define INVALID_OPERAND_TYPE_LIST(V) V(None, OperandTypeInfo::kNone) 15 16 #define REGISTER_INPUT_OPERAND_TYPE_LIST(V) \ 17 V(Reg, OperandTypeInfo::kScalableSignedByte) \ 18 V(RegList, OperandTypeInfo::kScalableSignedByte) \ 19 V(RegPair, OperandTypeInfo::kScalableSignedByte) 20 21 #define REGISTER_OUTPUT_OPERAND_TYPE_LIST(V) \ 22 V(RegOut, OperandTypeInfo::kScalableSignedByte) \ 23 V(RegOutList, OperandTypeInfo::kScalableSignedByte) \ 24 V(RegOutPair, OperandTypeInfo::kScalableSignedByte) \ 25 V(RegOutTriple, OperandTypeInfo::kScalableSignedByte) 26 27 #define SIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V) \ 28 V(Imm, OperandTypeInfo::kScalableSignedByte) 29 30 #define UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V) \ 31 V(Idx, OperandTypeInfo::kScalableUnsignedByte) \ 32 V(UImm, OperandTypeInfo::kScalableUnsignedByte) \ 33 V(RegCount, OperandTypeInfo::kScalableUnsignedByte) 34 35 #define UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(V) \ 36 V(Flag8, OperandTypeInfo::kFixedUnsignedByte) \ 37 V(IntrinsicId, OperandTypeInfo::kFixedUnsignedByte) \ 38 V(RuntimeId, OperandTypeInfo::kFixedUnsignedShort) \ 39 V(NativeContextIndex, OperandTypeInfo::kScalableUnsignedByte) 40 41 // Carefully ordered for operand type range checks below. 42 #define NON_REGISTER_OPERAND_TYPE_LIST(V) \ 43 INVALID_OPERAND_TYPE_LIST(V) \ 44 UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(V) \ 45 UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V) \ 46 SIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V) 47 48 // Carefully ordered for operand type range checks below. 49 #define REGISTER_OPERAND_TYPE_LIST(V) \ 50 REGISTER_INPUT_OPERAND_TYPE_LIST(V) \ 51 REGISTER_OUTPUT_OPERAND_TYPE_LIST(V) 52 53 // The list of operand types used by bytecodes. 54 // Carefully ordered for operand type range checks below. 55 #define OPERAND_TYPE_LIST(V) \ 56 NON_REGISTER_OPERAND_TYPE_LIST(V) \ 57 REGISTER_OPERAND_TYPE_LIST(V) 58 59 // Enumeration of scaling factors applicable to scalable operands. Code 60 // relies on being able to cast values to integer scaling values. 61 #define OPERAND_SCALE_LIST(V) \ 62 V(Single, 1) \ 63 V(Double, 2) \ 64 V(Quadruple, 4) 65 66 enum class OperandScale : uint8_t { 67 #define DECLARE_OPERAND_SCALE(Name, Scale) k##Name = Scale, 68 OPERAND_SCALE_LIST(DECLARE_OPERAND_SCALE) 69 #undef DECLARE_OPERAND_SCALE 70 kLast = kQuadruple 71 }; 72 73 // Enumeration of the size classes of operand types used by 74 // bytecodes. Code relies on being able to cast values to integer 75 // types to get the size in bytes. 76 enum class OperandSize : uint8_t { 77 kNone = 0, 78 kByte = 1, 79 kShort = 2, 80 kQuad = 4, 81 kLast = kQuad 82 }; 83 84 // Primitive operand info used that summarize properties of operands. 85 // Columns are Name, IsScalable, IsUnsigned, UnscaledSize. 86 #define OPERAND_TYPE_INFO_LIST(V) \ 87 V(None, false, false, OperandSize::kNone) \ 88 V(ScalableSignedByte, true, false, OperandSize::kByte) \ 89 V(ScalableUnsignedByte, true, true, OperandSize::kByte) \ 90 V(FixedUnsignedByte, false, true, OperandSize::kByte) \ 91 V(FixedUnsignedShort, false, true, OperandSize::kShort) 92 93 enum class OperandTypeInfo : uint8_t { 94 #define DECLARE_OPERAND_TYPE_INFO(Name, ...) k##Name, 95 OPERAND_TYPE_INFO_LIST(DECLARE_OPERAND_TYPE_INFO) 96 #undef DECLARE_OPERAND_TYPE_INFO 97 }; 98 99 // Enumeration of operand types used by bytecodes. 100 enum class OperandType : uint8_t { 101 #define DECLARE_OPERAND_TYPE(Name, _) k##Name, 102 OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE) 103 #undef DECLARE_OPERAND_TYPE 104 #define COUNT_OPERAND_TYPES(x, _) +1 105 // The COUNT_OPERAND macro will turn this into kLast = -1 +1 +1... which will 106 // evaluate to the same value as the last operand. 107 kLast = -1 OPERAND_TYPE_LIST(COUNT_OPERAND_TYPES) 108 #undef COUNT_OPERAND_TYPES 109 }; 110 111 enum class AccumulatorUse : uint8_t { 112 kNone = 0, 113 kRead = 1 << 0, 114 kWrite = 1 << 1, 115 kReadWrite = kRead | kWrite 116 }; 117 118 inline AccumulatorUse operator&(AccumulatorUse lhs, AccumulatorUse rhs) { 119 int result = static_cast<int>(lhs) & static_cast<int>(rhs); 120 return static_cast<AccumulatorUse>(result); 121 } 122 123 inline AccumulatorUse operator|(AccumulatorUse lhs, AccumulatorUse rhs) { 124 int result = static_cast<int>(lhs) | static_cast<int>(rhs); 125 return static_cast<AccumulatorUse>(result); 126 } 127 128 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, 129 const AccumulatorUse& use); 130 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, 131 const OperandScale& operand_scale); 132 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, 133 const OperandSize& operand_size); 134 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, 135 const OperandType& operand_type); 136 137 class BytecodeOperands : public AllStatic { 138 public: 139 // The total number of bytecode operand types used. 140 static const int kOperandTypeCount = static_cast<int>(OperandType::kLast) + 1; 141 142 // The total number of bytecode operand scales used. 143 #define OPERAND_SCALE_COUNT(...) +1 144 static const int kOperandScaleCount = 145 0 OPERAND_SCALE_LIST(OPERAND_SCALE_COUNT); 146 #undef OPERAND_SCALE_COUNT 147 148 // Returns true if |accumulator_use| reads the accumulator. ReadsAccumulator(AccumulatorUse accumulator_use)149 static constexpr bool ReadsAccumulator(AccumulatorUse accumulator_use) { 150 return accumulator_use == AccumulatorUse::kRead || 151 accumulator_use == AccumulatorUse::kReadWrite; 152 } 153 154 // Returns true if |accumulator_use| writes the accumulator. WritesAccumulator(AccumulatorUse accumulator_use)155 static constexpr bool WritesAccumulator(AccumulatorUse accumulator_use) { 156 return accumulator_use == AccumulatorUse::kWrite || 157 accumulator_use == AccumulatorUse::kReadWrite; 158 } 159 160 // Returns true if |operand_type| is a scalable signed byte. IsScalableSignedByte(OperandType operand_type)161 static constexpr bool IsScalableSignedByte(OperandType operand_type) { 162 return operand_type >= OperandType::kImm && 163 operand_type <= OperandType::kRegOutTriple; 164 } 165 166 // Returns true if |operand_type| is a scalable unsigned byte. IsScalableUnsignedByte(OperandType operand_type)167 static constexpr bool IsScalableUnsignedByte(OperandType operand_type) { 168 return operand_type >= OperandType::kIdx && 169 operand_type <= OperandType::kRegCount; 170 } 171 }; 172 173 } // namespace interpreter 174 } // namespace internal 175 } // namespace v8 176 177 #endif // V8_INTERPRETER_BYTECODE_OPERANDS_H_ 178