1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
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  public:
LIR_HEADER(DivI)15   LIR_HEADER(DivI)
16 
17   LDivI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp)
18       : LBinaryMath(classOpcode) {
19     setOperand(0, lhs);
20     setOperand(1, rhs);
21     setTemp(0, temp);
22   }
23 
extraName()24   const char* extraName() const {
25     if (mir()->isTruncated()) {
26       if (mir()->canBeNegativeZero()) {
27         return mir()->canBeNegativeOverflow()
28                    ? "Truncate_NegativeZero_NegativeOverflow"
29                    : "Truncate_NegativeZero";
30       }
31       return mir()->canBeNegativeOverflow() ? "Truncate_NegativeOverflow"
32                                             : "Truncate";
33     }
34     if (mir()->canBeNegativeZero()) {
35       return mir()->canBeNegativeOverflow() ? "NegativeZero_NegativeOverflow"
36                                             : "NegativeZero";
37     }
38     return mir()->canBeNegativeOverflow() ? "NegativeOverflow" : nullptr;
39   }
40 
remainder()41   const LDefinition* remainder() { return getTemp(0); }
mir()42   MDiv* mir() const { return mir_->toDiv(); }
43 };
44 
45 // Signed division by a power-of-two constant.
46 class LDivPowTwoI : public LBinaryMath<0> {
47   const int32_t shift_;
48   const bool negativeDivisor_;
49 
50  public:
LIR_HEADER(DivPowTwoI)51   LIR_HEADER(DivPowTwoI)
52 
53   LDivPowTwoI(const LAllocation& lhs, const LAllocation& lhsCopy, int32_t shift,
54               bool negativeDivisor)
55       : LBinaryMath(classOpcode),
56         shift_(shift),
57         negativeDivisor_(negativeDivisor) {
58     setOperand(0, lhs);
59     setOperand(1, lhsCopy);
60   }
61 
numerator()62   const LAllocation* numerator() { return getOperand(0); }
numeratorCopy()63   const LAllocation* numeratorCopy() { return getOperand(1); }
shift()64   int32_t shift() const { return shift_; }
negativeDivisor()65   bool negativeDivisor() const { return negativeDivisor_; }
mir()66   MDiv* mir() const { return mir_->toDiv(); }
67 };
68 
69 class LDivOrModConstantI : public LInstructionHelper<1, 1, 1> {
70   const int32_t denominator_;
71 
72  public:
LIR_HEADER(DivOrModConstantI)73   LIR_HEADER(DivOrModConstantI)
74 
75   LDivOrModConstantI(const LAllocation& lhs, int32_t denominator,
76                      const LDefinition& temp)
77       : LInstructionHelper(classOpcode), denominator_(denominator) {
78     setOperand(0, lhs);
79     setTemp(0, temp);
80   }
81 
numerator()82   const LAllocation* numerator() { return getOperand(0); }
denominator()83   int32_t denominator() const { return denominator_; }
mir()84   MBinaryArithInstruction* mir() const {
85     MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
86     return static_cast<MBinaryArithInstruction*>(mir_);
87   }
canBeNegativeDividend()88   bool canBeNegativeDividend() const {
89     if (mir_->isMod()) {
90       return mir_->toMod()->canBeNegativeDividend();
91     }
92     return mir_->toDiv()->canBeNegativeDividend();
93   }
94 };
95 
96 class LModI : public LBinaryMath<1> {
97  public:
LIR_HEADER(ModI)98   LIR_HEADER(ModI)
99 
100   LModI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp)
101       : LBinaryMath(classOpcode) {
102     setOperand(0, lhs);
103     setOperand(1, rhs);
104     setTemp(0, temp);
105   }
106 
extraName()107   const char* extraName() const {
108     return mir()->isTruncated() ? "Truncated" : nullptr;
109   }
110 
remainder()111   const LDefinition* remainder() { return getDef(0); }
mir()112   MMod* mir() const { return mir_->toMod(); }
113 };
114 
115 // This class performs a simple x86 'div', yielding either a quotient or
116 // remainder depending on whether this instruction is defined to output eax
117 // (quotient) or edx (remainder).
118 class LUDivOrMod : public LBinaryMath<1> {
119  public:
120   LIR_HEADER(UDivOrMod);
121 
LUDivOrMod(const LAllocation & lhs,const LAllocation & rhs,const LDefinition & temp)122   LUDivOrMod(const LAllocation& lhs, const LAllocation& rhs,
123              const LDefinition& temp)
124       : LBinaryMath(classOpcode) {
125     setOperand(0, lhs);
126     setOperand(1, rhs);
127     setTemp(0, temp);
128   }
129 
remainder()130   const LDefinition* remainder() { return getTemp(0); }
131 
extraName()132   const char* extraName() const {
133     return mir()->isTruncated() ? "Truncated" : nullptr;
134   }
135 
mir()136   MBinaryArithInstruction* mir() const {
137     MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
138     return static_cast<MBinaryArithInstruction*>(mir_);
139   }
140 
canBeDivideByZero()141   bool canBeDivideByZero() const {
142     if (mir_->isMod()) {
143       return mir_->toMod()->canBeDivideByZero();
144     }
145     return mir_->toDiv()->canBeDivideByZero();
146   }
147 
trapOnError()148   bool trapOnError() const {
149     if (mir_->isMod()) {
150       return mir_->toMod()->trapOnError();
151     }
152     return mir_->toDiv()->trapOnError();
153   }
154 
bytecodeOffset()155   wasm::BytecodeOffset bytecodeOffset() const {
156     if (mir_->isMod()) {
157       return mir_->toMod()->bytecodeOffset();
158     }
159     return mir_->toDiv()->bytecodeOffset();
160   }
161 };
162 
163 class LUDivOrModConstant : public LInstructionHelper<1, 1, 1> {
164   const uint32_t denominator_;
165 
166  public:
LIR_HEADER(UDivOrModConstant)167   LIR_HEADER(UDivOrModConstant)
168 
169   LUDivOrModConstant(const LAllocation& lhs, uint32_t denominator,
170                      const LDefinition& temp)
171       : LInstructionHelper(classOpcode), denominator_(denominator) {
172     setOperand(0, lhs);
173     setTemp(0, temp);
174   }
175 
numerator()176   const LAllocation* numerator() { return getOperand(0); }
denominator()177   uint32_t denominator() const { return denominator_; }
mir()178   MBinaryArithInstruction* mir() const {
179     MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
180     return static_cast<MBinaryArithInstruction*>(mir_);
181   }
canBeNegativeDividend()182   bool canBeNegativeDividend() const {
183     if (mir_->isMod()) {
184       return mir_->toMod()->canBeNegativeDividend();
185     }
186     return mir_->toDiv()->canBeNegativeDividend();
187   }
trapOnError()188   bool trapOnError() const {
189     if (mir_->isMod()) {
190       return mir_->toMod()->trapOnError();
191     }
192     return mir_->toDiv()->trapOnError();
193   }
bytecodeOffset()194   wasm::BytecodeOffset bytecodeOffset() const {
195     if (mir_->isMod()) {
196       return mir_->toMod()->bytecodeOffset();
197     }
198     return mir_->toDiv()->bytecodeOffset();
199   }
200 };
201 
202 class LModPowTwoI : public LInstructionHelper<1, 1, 0> {
203   const int32_t shift_;
204 
205  public:
LIR_HEADER(ModPowTwoI)206   LIR_HEADER(ModPowTwoI)
207 
208   LModPowTwoI(const LAllocation& lhs, int32_t shift)
209       : LInstructionHelper(classOpcode), shift_(shift) {
210     setOperand(0, lhs);
211   }
212 
shift()213   int32_t shift() const { return shift_; }
remainder()214   const LDefinition* remainder() { return getDef(0); }
mir()215   MMod* mir() const { return mir_->toMod(); }
216 };
217 
218 // Takes a tableswitch with an integer to decide
219 class LTableSwitch : public LInstructionHelper<0, 1, 2> {
220  public:
LIR_HEADER(TableSwitch)221   LIR_HEADER(TableSwitch)
222 
223   LTableSwitch(const LAllocation& in, const LDefinition& inputCopy,
224                const LDefinition& jumpTablePointer, MTableSwitch* ins)
225       : LInstructionHelper(classOpcode) {
226     setOperand(0, in);
227     setTemp(0, inputCopy);
228     setTemp(1, jumpTablePointer);
229     setMir(ins);
230   }
231 
mir()232   MTableSwitch* mir() const { return mir_->toTableSwitch(); }
233 
index()234   const LAllocation* index() { return getOperand(0); }
tempInt()235   const LDefinition* tempInt() { return getTemp(0); }
tempPointer()236   const LDefinition* tempPointer() { return getTemp(1); }
237 };
238 
239 // Takes a tableswitch with a value to decide
240 class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 3> {
241  public:
LIR_HEADER(TableSwitchV)242   LIR_HEADER(TableSwitchV)
243 
244   LTableSwitchV(const LBoxAllocation& input, const LDefinition& inputCopy,
245                 const LDefinition& floatCopy,
246                 const LDefinition& jumpTablePointer, MTableSwitch* ins)
247       : LInstructionHelper(classOpcode) {
248     setBoxOperand(InputValue, input);
249     setTemp(0, inputCopy);
250     setTemp(1, floatCopy);
251     setTemp(2, jumpTablePointer);
252     setMir(ins);
253   }
254 
mir()255   MTableSwitch* mir() const { return mir_->toTableSwitch(); }
256 
257   static const size_t InputValue = 0;
258 
tempInt()259   const LDefinition* tempInt() { return getTemp(0); }
tempFloat()260   const LDefinition* tempFloat() { return getTemp(1); }
tempPointer()261   const LDefinition* tempPointer() { return getTemp(2); }
262 };
263 
264 class LMulI : public LBinaryMath<0, 1> {
265  public:
LIR_HEADER(MulI)266   LIR_HEADER(MulI)
267 
268   LMulI(const LAllocation& lhs, const LAllocation& rhs,
269         const LAllocation& lhsCopy)
270       : LBinaryMath(classOpcode) {
271     setOperand(0, lhs);
272     setOperand(1, rhs);
273     setOperand(2, lhsCopy);
274   }
275 
extraName()276   const char* extraName() const {
277     return (mir()->mode() == MMul::Integer)
278                ? "Integer"
279                : (mir()->canBeNegativeZero() ? "CanBeNegativeZero" : nullptr);
280   }
281 
mir()282   MMul* mir() const { return mir_->toMul(); }
lhsCopy()283   const LAllocation* lhsCopy() { return this->getOperand(2); }
284 };
285 
286 class LInt64ToFloatingPoint : public LInstructionHelper<1, INT64_PIECES, 1> {
287  public:
288   LIR_HEADER(Int64ToFloatingPoint);
289 
LInt64ToFloatingPoint(const LInt64Allocation & in,const LDefinition & temp)290   LInt64ToFloatingPoint(const LInt64Allocation& in, const LDefinition& temp)
291       : LInstructionHelper(classOpcode) {
292     setInt64Operand(0, in);
293     setTemp(0, temp);
294   }
295 
mir()296   MInt64ToFloatingPoint* mir() const { return mir_->toInt64ToFloatingPoint(); }
297 
temp()298   const LDefinition* temp() { return getTemp(0); }
299 };
300 
301 }  // namespace jit
302 }  // namespace js
303 
304 #endif /* jit_x86_shared_LIR_x86_shared_h */
305