Line data Source code
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 56372 : 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 34022094 : static int OperandScaleAsIndex(OperandScale operand_scale) {
149 34022094 : switch (operand_scale) {
150 : case OperandScale::kSingle:
151 : return 0;
152 : case OperandScale::kDouble:
153 11318761 : return 1;
154 : case OperandScale::kQuadruple:
155 11318746 : return 2;
156 : default:
157 0 : UNREACHABLE();
158 : }
159 : }
160 :
161 : // Returns true if |accumulator_use| reads the accumulator.
162 54125341 : static constexpr bool ReadsAccumulator(AccumulatorUse accumulator_use) {
163 71569653 : return accumulator_use == AccumulatorUse::kRead ||
164 71569653 : accumulator_use == AccumulatorUse::kReadWrite;
165 : }
166 :
167 : // Returns true if |accumulator_use| writes the accumulator.
168 54125119 : static constexpr bool WritesAccumulator(AccumulatorUse accumulator_use) {
169 71569406 : return accumulator_use == AccumulatorUse::kWrite ||
170 54125120 : accumulator_use == AccumulatorUse::kReadWrite;
171 : }
172 :
173 : // Returns true if |operand_type| is a scalable signed byte.
174 56931568 : static constexpr bool IsScalableSignedByte(OperandType operand_type) {
175 56931568 : return operand_type >= OperandType::kImm &&
176 56931568 : operand_type <= OperandType::kRegOutTriple;
177 : }
178 :
179 : // Returns true if |operand_type| is a scalable unsigned byte.
180 90023918 : static constexpr bool IsScalableUnsignedByte(OperandType operand_type) {
181 90023918 : return operand_type >= OperandType::kIdx &&
182 90023918 : operand_type <= OperandType::kRegCount;
183 : }
184 : };
185 :
186 : } // namespace interpreter
187 : } // namespace internal
188 : } // namespace v8
189 :
190 : #endif // V8_INTERPRETER_BYTECODE_OPERANDS_H_
|