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