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