|
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_shared_LIR_x86_shared_h |
|
8 #define jit_shared_LIR_x86_shared_h |
|
9 |
|
10 namespace js { |
|
11 namespace jit { |
|
12 |
|
13 class LDivI : public LBinaryMath<1> |
|
14 { |
|
15 public: |
|
16 LIR_HEADER(DivI) |
|
17 |
|
18 LDivI(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp) { |
|
19 setOperand(0, lhs); |
|
20 setOperand(1, rhs); |
|
21 setTemp(0, temp); |
|
22 } |
|
23 |
|
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" : "Truncate"; |
|
32 } |
|
33 if (mir()->canBeNegativeZero()) |
|
34 return mir()->canBeNegativeOverflow() ? "NegativeZero_NegativeOverflow" : "NegativeZero"; |
|
35 return mir()->canBeNegativeOverflow() ? "NegativeOverflow" : nullptr; |
|
36 } |
|
37 |
|
38 const LDefinition *remainder() { |
|
39 return getTemp(0); |
|
40 } |
|
41 MDiv *mir() const { |
|
42 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 LIR_HEADER(DivPowTwoI) |
|
54 |
|
55 LDivPowTwoI(const LAllocation &lhs, const LAllocation &lhsCopy, int32_t shift, bool negativeDivisor) |
|
56 : shift_(shift), negativeDivisor_(negativeDivisor) |
|
57 { |
|
58 setOperand(0, lhs); |
|
59 setOperand(1, lhsCopy); |
|
60 } |
|
61 |
|
62 const LAllocation *numerator() { |
|
63 return getOperand(0); |
|
64 } |
|
65 const LAllocation *numeratorCopy() { |
|
66 return getOperand(1); |
|
67 } |
|
68 int32_t shift() const { |
|
69 return shift_; |
|
70 } |
|
71 bool negativeDivisor() const { |
|
72 return negativeDivisor_; |
|
73 } |
|
74 MDiv *mir() const { |
|
75 return mir_->toDiv(); |
|
76 } |
|
77 }; |
|
78 |
|
79 class LDivOrModConstantI : public LInstructionHelper<1, 1, 1> |
|
80 { |
|
81 const int32_t denominator_; |
|
82 |
|
83 public: |
|
84 LIR_HEADER(DivOrModConstantI) |
|
85 |
|
86 LDivOrModConstantI(const LAllocation &lhs, int32_t denominator, const LDefinition& temp) |
|
87 : denominator_(denominator) |
|
88 { |
|
89 setOperand(0, lhs); |
|
90 setTemp(0, temp); |
|
91 } |
|
92 |
|
93 const LAllocation *numerator() { |
|
94 return getOperand(0); |
|
95 } |
|
96 int32_t denominator() const { |
|
97 return denominator_; |
|
98 } |
|
99 MBinaryArithInstruction *mir() const { |
|
100 JS_ASSERT(mir_->isDiv() || mir_->isMod()); |
|
101 return static_cast<MBinaryArithInstruction *>(mir_); |
|
102 } |
|
103 bool canBeNegativeDividend() const { |
|
104 if (mir_->isMod()) |
|
105 return mir_->toMod()->canBeNegativeDividend(); |
|
106 return mir_->toDiv()->canBeNegativeDividend(); |
|
107 } |
|
108 }; |
|
109 |
|
110 class LModI : public LBinaryMath<1> |
|
111 { |
|
112 public: |
|
113 LIR_HEADER(ModI) |
|
114 |
|
115 LModI(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp) { |
|
116 setOperand(0, lhs); |
|
117 setOperand(1, rhs); |
|
118 setTemp(0, temp); |
|
119 } |
|
120 |
|
121 const char *extraName() const { |
|
122 return mir()->isTruncated() ? "Truncated" : nullptr; |
|
123 } |
|
124 |
|
125 const LDefinition *remainder() { |
|
126 return getDef(0); |
|
127 } |
|
128 MMod *mir() const { |
|
129 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 LIR_HEADER(UDivOrMod); |
|
139 |
|
140 LUDivOrMod(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp) { |
|
141 setOperand(0, lhs); |
|
142 setOperand(1, rhs); |
|
143 setTemp(0, temp); |
|
144 } |
|
145 |
|
146 const LDefinition *remainder() { |
|
147 return getTemp(0); |
|
148 } |
|
149 |
|
150 const char *extraName() const { |
|
151 return mir()->isTruncated() ? "Truncated" : nullptr; |
|
152 } |
|
153 |
|
154 MBinaryArithInstruction *mir() const { |
|
155 JS_ASSERT(mir_->isDiv() || mir_->isMod()); |
|
156 return static_cast<MBinaryArithInstruction *>(mir_); |
|
157 } |
|
158 |
|
159 bool canBeDivideByZero() const { |
|
160 if (mir_->isMod()) |
|
161 return mir_->toMod()->canBeDivideByZero(); |
|
162 return mir_->toDiv()->canBeDivideByZero(); |
|
163 } |
|
164 }; |
|
165 |
|
166 class LModPowTwoI : public LInstructionHelper<1,1,0> |
|
167 { |
|
168 const int32_t shift_; |
|
169 |
|
170 public: |
|
171 LIR_HEADER(ModPowTwoI) |
|
172 |
|
173 LModPowTwoI(const LAllocation &lhs, int32_t shift) |
|
174 : shift_(shift) |
|
175 { |
|
176 setOperand(0, lhs); |
|
177 } |
|
178 |
|
179 int32_t shift() const { |
|
180 return shift_; |
|
181 } |
|
182 const LDefinition *remainder() { |
|
183 return getDef(0); |
|
184 } |
|
185 MMod *mir() const { |
|
186 return mir_->toMod(); |
|
187 } |
|
188 }; |
|
189 |
|
190 // Double raised to a half power. |
|
191 class LPowHalfD : public LInstructionHelper<1, 1, 0> |
|
192 { |
|
193 public: |
|
194 LIR_HEADER(PowHalfD) |
|
195 LPowHalfD(const LAllocation &input) { |
|
196 setOperand(0, input); |
|
197 } |
|
198 |
|
199 const LAllocation *input() { |
|
200 return getOperand(0); |
|
201 } |
|
202 const LDefinition *output() { |
|
203 return getDef(0); |
|
204 } |
|
205 MPowHalf *mir() const { |
|
206 return mir_->toPowHalf(); |
|
207 } |
|
208 }; |
|
209 |
|
210 // Takes a tableswitch with an integer to decide |
|
211 class LTableSwitch : public LInstructionHelper<0, 1, 2> |
|
212 { |
|
213 public: |
|
214 LIR_HEADER(TableSwitch) |
|
215 |
|
216 LTableSwitch(const LAllocation &in, const LDefinition &inputCopy, |
|
217 const LDefinition &jumpTablePointer, MTableSwitch *ins) |
|
218 { |
|
219 setOperand(0, in); |
|
220 setTemp(0, inputCopy); |
|
221 setTemp(1, jumpTablePointer); |
|
222 setMir(ins); |
|
223 } |
|
224 |
|
225 MTableSwitch *mir() const { |
|
226 return mir_->toTableSwitch(); |
|
227 } |
|
228 |
|
229 const LAllocation *index() { |
|
230 return getOperand(0); |
|
231 } |
|
232 const LDefinition *tempInt() { |
|
233 return getTemp(0); |
|
234 } |
|
235 const LDefinition *tempPointer() { |
|
236 return getTemp(1); |
|
237 } |
|
238 }; |
|
239 |
|
240 // Takes a tableswitch with a value to decide |
|
241 class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 3> |
|
242 { |
|
243 public: |
|
244 LIR_HEADER(TableSwitchV) |
|
245 |
|
246 LTableSwitchV(const LDefinition &inputCopy, const LDefinition &floatCopy, |
|
247 const LDefinition &jumpTablePointer, MTableSwitch *ins) |
|
248 { |
|
249 setTemp(0, inputCopy); |
|
250 setTemp(1, floatCopy); |
|
251 setTemp(2, jumpTablePointer); |
|
252 setMir(ins); |
|
253 } |
|
254 |
|
255 MTableSwitch *mir() const { |
|
256 return mir_->toTableSwitch(); |
|
257 } |
|
258 |
|
259 static const size_t InputValue = 0; |
|
260 |
|
261 const LDefinition *tempInt() { |
|
262 return getTemp(0); |
|
263 } |
|
264 const LDefinition *tempFloat() { |
|
265 return getTemp(1); |
|
266 } |
|
267 const LDefinition *tempPointer() { |
|
268 return getTemp(2); |
|
269 } |
|
270 }; |
|
271 |
|
272 class LGuardShape : public LInstructionHelper<0, 1, 0> |
|
273 { |
|
274 public: |
|
275 LIR_HEADER(GuardShape) |
|
276 |
|
277 LGuardShape(const LAllocation &in) { |
|
278 setOperand(0, in); |
|
279 } |
|
280 const MGuardShape *mir() const { |
|
281 return mir_->toGuardShape(); |
|
282 } |
|
283 }; |
|
284 |
|
285 class LGuardObjectType : public LInstructionHelper<0, 1, 0> |
|
286 { |
|
287 public: |
|
288 LIR_HEADER(GuardObjectType) |
|
289 |
|
290 LGuardObjectType(const LAllocation &in) { |
|
291 setOperand(0, in); |
|
292 } |
|
293 const MGuardObjectType *mir() const { |
|
294 return mir_->toGuardObjectType(); |
|
295 } |
|
296 }; |
|
297 |
|
298 class LInterruptCheck : public LInstructionHelper<0, 0, 0> |
|
299 { |
|
300 public: |
|
301 LIR_HEADER(InterruptCheck) |
|
302 }; |
|
303 |
|
304 class LMulI : public LBinaryMath<0, 1> |
|
305 { |
|
306 public: |
|
307 LIR_HEADER(MulI) |
|
308 |
|
309 LMulI(const LAllocation &lhs, const LAllocation &rhs, const LAllocation &lhsCopy) { |
|
310 setOperand(0, lhs); |
|
311 setOperand(1, rhs); |
|
312 setOperand(2, lhsCopy); |
|
313 } |
|
314 |
|
315 const char *extraName() const { |
|
316 return (mir()->mode() == MMul::Integer) |
|
317 ? "Integer" |
|
318 : (mir()->canBeNegativeZero() ? "CanBeNegativeZero" : nullptr); |
|
319 } |
|
320 |
|
321 MMul *mir() const { |
|
322 return mir_->toMul(); |
|
323 } |
|
324 const LAllocation *lhsCopy() { |
|
325 return this->getOperand(2); |
|
326 } |
|
327 }; |
|
328 |
|
329 } // namespace jit |
|
330 } // namespace js |
|
331 |
|
332 #endif /* jit_shared_LIR_x86_shared_h */ |