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/base/bounds.h"
9 #include "src/common/globals.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::kFixedUnsignedByte)
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 ImplicitRegisterUse : uint8_t {
113 kNone = 0,
114 kReadAccumulator = 1 << 0,
115 kWriteAccumulator = 1 << 1,
116 kWriteShortStar = 1 << 2,
117 kReadWriteAccumulator = kReadAccumulator | kWriteAccumulator,
118 kReadAccumulatorWriteShortStar = kReadAccumulator | kWriteShortStar
119 };
120
operator &(ImplicitRegisterUse lhs, ImplicitRegisterUse rhs)121 constexpr inline ImplicitRegisterUse operator&(ImplicitRegisterUse lhs,
122 ImplicitRegisterUse rhs) {
123 return static_cast<ImplicitRegisterUse>(static_cast<int>(lhs) &
124 static_cast<int>(rhs));
125 }
126
operator |(ImplicitRegisterUse lhs, ImplicitRegisterUse rhs)127 constexpr inline ImplicitRegisterUse operator|(ImplicitRegisterUse lhs,
128 ImplicitRegisterUse rhs) {
129 return static_cast<ImplicitRegisterUse>(static_cast<int>(lhs) |
130 static_cast<int>(rhs));
131 }
132
133 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
134 const ImplicitRegisterUse& use);
135 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
136 const OperandScale& operand_scale);
137 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
138 const OperandSize& operand_size);
139 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
140 const OperandType& operand_type);
141
142 class BytecodeOperands : public AllStatic {
143 public:
144 // The total number of bytecode operand types used.
145 static const int kOperandTypeCount = static_cast<int>(OperandType::kLast) + 1;
146
147 // The total number of bytecode operand scales used.
148 #define OPERAND_SCALE_COUNT(...) +1
149 static const int kOperandScaleCount =
150 0 OPERAND_SCALE_LIST(OPERAND_SCALE_COUNT);
151 #undef OPERAND_SCALE_COUNT
152
OperandScaleAsIndex(OperandScale operand_scale)153 static constexpr int OperandScaleAsIndex(OperandScale operand_scale) {
154 #ifdef DEBUG
155 int result = static_cast<int>(operand_scale) >> 1;
156 switch (operand_scale) {
157 case OperandScale::kSingle:
158 DCHECK_EQ(0, result);
159 break;
160 case OperandScale::kDouble:
161 DCHECK_EQ(1, result);
162 break;
163 case OperandScale::kQuadruple:
164 DCHECK_EQ(2, result);
165 break;
166 default:
167 UNREACHABLE();
168 }
169 #endif
170 return static_cast<int>(operand_scale) >> 1;
171 }
172
173 // Returns true if |implicit_register_use| reads the
174 // accumulator.
ReadsAccumulator( ImplicitRegisterUse implicit_register_use)175 static constexpr bool ReadsAccumulator(
176 ImplicitRegisterUse implicit_register_use) {
177 return (implicit_register_use & ImplicitRegisterUse::kReadAccumulator) ==
178 ImplicitRegisterUse::kReadAccumulator;
179 }
180
181 // Returns true if |implicit_register_use| writes the
182 // accumulator.
WritesAccumulator( ImplicitRegisterUse implicit_register_use)183 static constexpr bool WritesAccumulator(
184 ImplicitRegisterUse implicit_register_use) {
185 return (implicit_register_use & ImplicitRegisterUse::kWriteAccumulator) ==
186 ImplicitRegisterUse::kWriteAccumulator;
187 }
188
189 // Returns true if |implicit_register_use| writes to a
190 // register not specified by an operand.
WritesImplicitRegister( ImplicitRegisterUse implicit_register_use)191 static constexpr bool WritesImplicitRegister(
192 ImplicitRegisterUse implicit_register_use) {
193 return (implicit_register_use & ImplicitRegisterUse::kWriteShortStar) ==
194 ImplicitRegisterUse::kWriteShortStar;
195 }
196
197 // Returns true if |operand_type| is a scalable signed byte.
IsScalableSignedByte(OperandType operand_type)198 static constexpr bool IsScalableSignedByte(OperandType operand_type) {
199 return base::IsInRange(operand_type, OperandType::kImm,
200 OperandType::kRegOutTriple);
201 }
202
203 // Returns true if |operand_type| is a scalable unsigned byte.
IsScalableUnsignedByte(OperandType operand_type)204 static constexpr bool IsScalableUnsignedByte(OperandType operand_type) {
205 return base::IsInRange(operand_type, OperandType::kIdx,
206 OperandType::kRegCount);
207 }
208 };
209
210 } // namespace interpreter
211 } // namespace internal
212 } // namespace v8
213
214 #endif // V8_INTERPRETER_BYTECODE_OPERANDS_H_
215