Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef jit_x86_shared_LIR_x86_shared_h
8 : #define jit_x86_shared_LIR_x86_shared_h
9 :
10 : namespace js {
11 : namespace jit {
12 :
13 : class LDivI : public LBinaryMath<1>
14 : {
15 : public:
16 0 : LIR_HEADER(DivI)
17 :
18 0 : LDivI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp) {
19 0 : setOperand(0, lhs);
20 0 : setOperand(1, rhs);
21 0 : setTemp(0, temp);
22 0 : }
23 :
24 0 : const char* extraName() const {
25 0 : if (mir()->isTruncated()) {
26 0 : if (mir()->canBeNegativeZero()) {
27 0 : return mir()->canBeNegativeOverflow()
28 0 : ? "Truncate_NegativeZero_NegativeOverflow"
29 0 : : "Truncate_NegativeZero";
30 : }
31 0 : return mir()->canBeNegativeOverflow() ? "Truncate_NegativeOverflow" : "Truncate";
32 : }
33 0 : if (mir()->canBeNegativeZero())
34 0 : return mir()->canBeNegativeOverflow() ? "NegativeZero_NegativeOverflow" : "NegativeZero";
35 0 : return mir()->canBeNegativeOverflow() ? "NegativeOverflow" : nullptr;
36 : }
37 :
38 0 : const LDefinition* remainder() {
39 0 : return getTemp(0);
40 : }
41 0 : MDiv* mir() const {
42 0 : return mir_->toDiv();
43 : }
44 : };
45 :
46 : // Signed division by a power-of-two constant.
47 : class LDivPowTwoI : public LBinaryMath<0>
48 : {
49 : const int32_t shift_;
50 : const bool negativeDivisor_;
51 :
52 : public:
53 0 : LIR_HEADER(DivPowTwoI)
54 :
55 0 : LDivPowTwoI(const LAllocation& lhs, const LAllocation& lhsCopy, int32_t shift, bool negativeDivisor)
56 0 : : shift_(shift), negativeDivisor_(negativeDivisor)
57 : {
58 0 : setOperand(0, lhs);
59 0 : setOperand(1, lhsCopy);
60 0 : }
61 :
62 0 : const LAllocation* numerator() {
63 0 : return getOperand(0);
64 : }
65 0 : const LAllocation* numeratorCopy() {
66 0 : return getOperand(1);
67 : }
68 0 : int32_t shift() const {
69 0 : return shift_;
70 : }
71 0 : bool negativeDivisor() const {
72 0 : return negativeDivisor_;
73 : }
74 0 : MDiv* mir() const {
75 0 : return mir_->toDiv();
76 : }
77 : };
78 :
79 : class LDivOrModConstantI : public LInstructionHelper<1, 1, 1>
80 : {
81 : const int32_t denominator_;
82 :
83 : public:
84 0 : LIR_HEADER(DivOrModConstantI)
85 :
86 0 : LDivOrModConstantI(const LAllocation& lhs, int32_t denominator, const LDefinition& temp)
87 0 : : denominator_(denominator)
88 : {
89 0 : setOperand(0, lhs);
90 0 : setTemp(0, temp);
91 0 : }
92 :
93 0 : const LAllocation* numerator() {
94 0 : return getOperand(0);
95 : }
96 0 : int32_t denominator() const {
97 0 : return denominator_;
98 : }
99 0 : MBinaryArithInstruction* mir() const {
100 0 : MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
101 0 : return static_cast<MBinaryArithInstruction*>(mir_);
102 : }
103 0 : bool canBeNegativeDividend() const {
104 0 : if (mir_->isMod())
105 0 : return mir_->toMod()->canBeNegativeDividend();
106 0 : return mir_->toDiv()->canBeNegativeDividend();
107 : }
108 : };
109 :
110 : class LModI : public LBinaryMath<1>
111 : {
112 : public:
113 0 : LIR_HEADER(ModI)
114 :
115 0 : LModI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp) {
116 0 : setOperand(0, lhs);
117 0 : setOperand(1, rhs);
118 0 : setTemp(0, temp);
119 0 : }
120 :
121 0 : const char* extraName() const {
122 0 : return mir()->isTruncated() ? "Truncated" : nullptr;
123 : }
124 :
125 0 : const LDefinition* remainder() {
126 0 : return getDef(0);
127 : }
128 0 : MMod* mir() const {
129 0 : return mir_->toMod();
130 : }
131 : };
132 :
133 : // This class performs a simple x86 'div', yielding either a quotient or remainder depending on
134 : // whether this instruction is defined to output eax (quotient) or edx (remainder).
135 : class LUDivOrMod : public LBinaryMath<1>
136 : {
137 : public:
138 0 : LIR_HEADER(UDivOrMod);
139 :
140 0 : LUDivOrMod(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp) {
141 0 : setOperand(0, lhs);
142 0 : setOperand(1, rhs);
143 0 : setTemp(0, temp);
144 0 : }
145 :
146 0 : const LDefinition* remainder() {
147 0 : return getTemp(0);
148 : }
149 :
150 0 : const char* extraName() const {
151 0 : return mir()->isTruncated() ? "Truncated" : nullptr;
152 : }
153 :
154 0 : MBinaryArithInstruction* mir() const {
155 0 : MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
156 0 : return static_cast<MBinaryArithInstruction*>(mir_);
157 : }
158 :
159 0 : bool canBeDivideByZero() const {
160 0 : if (mir_->isMod())
161 0 : return mir_->toMod()->canBeDivideByZero();
162 0 : return mir_->toDiv()->canBeDivideByZero();
163 : }
164 :
165 0 : bool trapOnError() const {
166 0 : if (mir_->isMod())
167 0 : return mir_->toMod()->trapOnError();
168 0 : return mir_->toDiv()->trapOnError();
169 : }
170 :
171 0 : wasm::BytecodeOffset bytecodeOffset() const {
172 0 : if (mir_->isMod())
173 0 : return mir_->toMod()->bytecodeOffset();
174 0 : return mir_->toDiv()->bytecodeOffset();
175 : }
176 : };
177 :
178 : class LUDivOrModConstant : public LInstructionHelper<1, 1, 1>
179 : {
180 : const uint32_t denominator_;
181 :
182 : public:
183 0 : LIR_HEADER(UDivOrModConstant)
184 :
185 0 : LUDivOrModConstant(const LAllocation &lhs, uint32_t denominator, const LDefinition& temp)
186 0 : : denominator_(denominator)
187 : {
188 0 : setOperand(0, lhs);
189 0 : setTemp(0, temp);
190 0 : }
191 :
192 0 : const LAllocation* numerator() {
193 0 : return getOperand(0);
194 : }
195 0 : uint32_t denominator() const {
196 0 : return denominator_;
197 : }
198 0 : MBinaryArithInstruction *mir() const {
199 0 : MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
200 0 : return static_cast<MBinaryArithInstruction *>(mir_);
201 : }
202 : bool canBeNegativeDividend() const {
203 : if (mir_->isMod())
204 : return mir_->toMod()->canBeNegativeDividend();
205 : return mir_->toDiv()->canBeNegativeDividend();
206 : }
207 0 : bool trapOnError() const {
208 0 : if (mir_->isMod())
209 0 : return mir_->toMod()->trapOnError();
210 0 : return mir_->toDiv()->trapOnError();
211 : }
212 0 : wasm::BytecodeOffset bytecodeOffset() const {
213 0 : if (mir_->isMod())
214 0 : return mir_->toMod()->bytecodeOffset();
215 0 : return mir_->toDiv()->bytecodeOffset();
216 : }
217 : };
218 :
219 : class LModPowTwoI : public LInstructionHelper<1,1,0>
220 : {
221 : const int32_t shift_;
222 :
223 : public:
224 0 : LIR_HEADER(ModPowTwoI)
225 :
226 0 : LModPowTwoI(const LAllocation& lhs, int32_t shift)
227 0 : : shift_(shift)
228 : {
229 0 : setOperand(0, lhs);
230 0 : }
231 :
232 0 : int32_t shift() const {
233 0 : return shift_;
234 : }
235 : const LDefinition* remainder() {
236 : return getDef(0);
237 : }
238 0 : MMod* mir() const {
239 0 : return mir_->toMod();
240 : }
241 : };
242 :
243 : // Takes a tableswitch with an integer to decide
244 : class LTableSwitch : public LInstructionHelper<0, 1, 2>
245 : {
246 : public:
247 0 : LIR_HEADER(TableSwitch)
248 :
249 0 : LTableSwitch(const LAllocation& in, const LDefinition& inputCopy,
250 : const LDefinition& jumpTablePointer, MTableSwitch* ins)
251 0 : {
252 0 : setOperand(0, in);
253 0 : setTemp(0, inputCopy);
254 0 : setTemp(1, jumpTablePointer);
255 0 : setMir(ins);
256 0 : }
257 :
258 0 : MTableSwitch* mir() const {
259 0 : return mir_->toTableSwitch();
260 : }
261 :
262 0 : const LAllocation* index() {
263 0 : return getOperand(0);
264 : }
265 0 : const LDefinition* tempInt() {
266 0 : return getTemp(0);
267 : }
268 0 : const LDefinition* tempPointer() {
269 0 : return getTemp(1);
270 : }
271 : };
272 :
273 : // Takes a tableswitch with a value to decide
274 : class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 3>
275 : {
276 : public:
277 0 : LIR_HEADER(TableSwitchV)
278 :
279 0 : LTableSwitchV(const LBoxAllocation& input, const LDefinition& inputCopy,
280 : const LDefinition& floatCopy, const LDefinition& jumpTablePointer,
281 : MTableSwitch* ins)
282 0 : {
283 0 : setBoxOperand(InputValue, input);
284 0 : setTemp(0, inputCopy);
285 0 : setTemp(1, floatCopy);
286 0 : setTemp(2, jumpTablePointer);
287 0 : setMir(ins);
288 0 : }
289 :
290 0 : MTableSwitch* mir() const {
291 0 : return mir_->toTableSwitch();
292 : }
293 :
294 : static const size_t InputValue = 0;
295 :
296 0 : const LDefinition* tempInt() {
297 0 : return getTemp(0);
298 : }
299 0 : const LDefinition* tempFloat() {
300 0 : return getTemp(1);
301 : }
302 0 : const LDefinition* tempPointer() {
303 0 : return getTemp(2);
304 : }
305 : };
306 :
307 : class LGuardShape : public LInstructionHelper<0, 1, 0>
308 : {
309 : public:
310 660 : LIR_HEADER(GuardShape)
311 :
312 8 : explicit LGuardShape(const LAllocation& in) {
313 8 : setOperand(0, in);
314 8 : }
315 8 : const MGuardShape* mir() const {
316 8 : return mir_->toGuardShape();
317 : }
318 : };
319 :
320 : class LGuardObjectGroup : public LInstructionHelper<0, 1, 0>
321 : {
322 : public:
323 0 : LIR_HEADER(GuardObjectGroup)
324 :
325 0 : explicit LGuardObjectGroup(const LAllocation& in) {
326 0 : setOperand(0, in);
327 0 : }
328 0 : const MGuardObjectGroup* mir() const {
329 0 : return mir_->toGuardObjectGroup();
330 : }
331 : };
332 :
333 : class LMulI : public LBinaryMath<0, 1>
334 : {
335 : public:
336 0 : LIR_HEADER(MulI)
337 :
338 0 : LMulI(const LAllocation& lhs, const LAllocation& rhs, const LAllocation& lhsCopy) {
339 0 : setOperand(0, lhs);
340 0 : setOperand(1, rhs);
341 0 : setOperand(2, lhsCopy);
342 0 : }
343 :
344 0 : const char* extraName() const {
345 0 : return (mir()->mode() == MMul::Integer)
346 0 : ? "Integer"
347 0 : : (mir()->canBeNegativeZero() ? "CanBeNegativeZero" : nullptr);
348 : }
349 :
350 0 : MMul* mir() const {
351 0 : return mir_->toMul();
352 : }
353 0 : const LAllocation* lhsCopy() {
354 0 : return this->getOperand(2);
355 : }
356 : };
357 :
358 : // Constructs an int32x4 SIMD value.
359 : class LSimdValueInt32x4 : public LInstructionHelper<1, 4, 0>
360 : {
361 : public:
362 0 : LIR_HEADER(SimdValueInt32x4)
363 0 : LSimdValueInt32x4(const LAllocation& x, const LAllocation& y,
364 : const LAllocation& z, const LAllocation& w)
365 0 : {
366 0 : setOperand(0, x);
367 0 : setOperand(1, y);
368 0 : setOperand(2, z);
369 0 : setOperand(3, w);
370 0 : }
371 :
372 0 : MSimdValueX4* mir() const {
373 0 : return mir_->toSimdValueX4();
374 : }
375 : };
376 :
377 : // Constructs a float32x4 SIMD value, optimized for x86 family
378 : class LSimdValueFloat32x4 : public LInstructionHelper<1, 4, 1>
379 : {
380 : public:
381 0 : LIR_HEADER(SimdValueFloat32x4)
382 0 : LSimdValueFloat32x4(const LAllocation& x, const LAllocation& y,
383 : const LAllocation& z, const LAllocation& w,
384 : const LDefinition& copyY)
385 0 : {
386 0 : setOperand(0, x);
387 0 : setOperand(1, y);
388 0 : setOperand(2, z);
389 0 : setOperand(3, w);
390 :
391 0 : setTemp(0, copyY);
392 0 : }
393 :
394 0 : MSimdValueX4* mir() const {
395 0 : return mir_->toSimdValueX4();
396 : }
397 : };
398 :
399 : class LInt64ToFloatingPoint : public LInstructionHelper<1, INT64_PIECES, 1>
400 : {
401 : public:
402 0 : LIR_HEADER(Int64ToFloatingPoint);
403 :
404 0 : explicit LInt64ToFloatingPoint(const LInt64Allocation& in, const LDefinition& temp) {
405 0 : setInt64Operand(0, in);
406 0 : setTemp(0, temp);
407 0 : }
408 :
409 0 : MInt64ToFloatingPoint* mir() const {
410 0 : return mir_->toInt64ToFloatingPoint();
411 : }
412 :
413 : const LDefinition* temp() {
414 : return getTemp(0);
415 : }
416 : };
417 :
418 : } // namespace jit
419 : } // namespace js
420 :
421 : #endif /* jit_x86_shared_LIR_x86_shared_h */
|