|
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_arm_LIR_arm_h |
|
8 #define jit_arm_LIR_arm_h |
|
9 |
|
10 namespace js { |
|
11 namespace jit { |
|
12 |
|
13 class LBox : public LInstructionHelper<2, 1, 0> |
|
14 { |
|
15 MIRType type_; |
|
16 |
|
17 public: |
|
18 LIR_HEADER(Box); |
|
19 |
|
20 LBox(const LAllocation &in_payload, MIRType type) |
|
21 : type_(type) |
|
22 { |
|
23 setOperand(0, in_payload); |
|
24 } |
|
25 |
|
26 MIRType type() const { |
|
27 return type_; |
|
28 } |
|
29 const char *extraName() const { |
|
30 return StringFromMIRType(type_); |
|
31 } |
|
32 }; |
|
33 |
|
34 class LBoxFloatingPoint : public LInstructionHelper<2, 1, 1> |
|
35 { |
|
36 MIRType type_; |
|
37 |
|
38 public: |
|
39 LIR_HEADER(BoxFloatingPoint); |
|
40 |
|
41 LBoxFloatingPoint(const LAllocation &in, const LDefinition &temp, MIRType type) |
|
42 : type_(type) |
|
43 { |
|
44 setOperand(0, in); |
|
45 setTemp(0, temp); |
|
46 } |
|
47 |
|
48 MIRType type() const { |
|
49 return type_; |
|
50 } |
|
51 const char *extraName() const { |
|
52 return StringFromMIRType(type_); |
|
53 } |
|
54 }; |
|
55 |
|
56 class LUnbox : public LInstructionHelper<1, 2, 0> |
|
57 { |
|
58 public: |
|
59 LIR_HEADER(Unbox); |
|
60 |
|
61 MUnbox *mir() const { |
|
62 return mir_->toUnbox(); |
|
63 } |
|
64 const LAllocation *payload() { |
|
65 return getOperand(0); |
|
66 } |
|
67 const LAllocation *type() { |
|
68 return getOperand(1); |
|
69 } |
|
70 const char *extraName() const { |
|
71 return StringFromMIRType(mir()->type()); |
|
72 } |
|
73 }; |
|
74 |
|
75 class LUnboxFloatingPoint : public LInstructionHelper<1, 2, 0> |
|
76 { |
|
77 MIRType type_; |
|
78 |
|
79 public: |
|
80 LIR_HEADER(UnboxFloatingPoint); |
|
81 |
|
82 static const size_t Input = 0; |
|
83 |
|
84 LUnboxFloatingPoint(MIRType type) |
|
85 : type_(type) |
|
86 { } |
|
87 |
|
88 MUnbox *mir() const { |
|
89 return mir_->toUnbox(); |
|
90 } |
|
91 |
|
92 MIRType type() const { |
|
93 return type_; |
|
94 } |
|
95 const char *extraName() const { |
|
96 return StringFromMIRType(type_); |
|
97 } |
|
98 }; |
|
99 |
|
100 // Convert a 32-bit unsigned integer to a double. |
|
101 class LAsmJSUInt32ToDouble : public LInstructionHelper<1, 1, 0> |
|
102 { |
|
103 public: |
|
104 LIR_HEADER(AsmJSUInt32ToDouble) |
|
105 |
|
106 LAsmJSUInt32ToDouble(const LAllocation &input) { |
|
107 setOperand(0, input); |
|
108 } |
|
109 }; |
|
110 |
|
111 // Convert a 32-bit unsigned integer to a float32. |
|
112 class LAsmJSUInt32ToFloat32 : public LInstructionHelper<1, 1, 0> |
|
113 { |
|
114 public: |
|
115 LIR_HEADER(AsmJSUInt32ToFloat32) |
|
116 |
|
117 LAsmJSUInt32ToFloat32(const LAllocation &input) { |
|
118 setOperand(0, input); |
|
119 } |
|
120 }; |
|
121 |
|
122 class LDivI : public LBinaryMath<1> |
|
123 { |
|
124 public: |
|
125 LIR_HEADER(DivI); |
|
126 |
|
127 LDivI(const LAllocation &lhs, const LAllocation &rhs, |
|
128 const LDefinition &temp) { |
|
129 setOperand(0, lhs); |
|
130 setOperand(1, rhs); |
|
131 setTemp(0, temp); |
|
132 } |
|
133 |
|
134 MDiv *mir() const { |
|
135 return mir_->toDiv(); |
|
136 } |
|
137 }; |
|
138 |
|
139 // LSoftDivI is a software divide for ARM cores that don't support a hardware |
|
140 // divide instruction. |
|
141 // |
|
142 // It is implemented as a proper C function so it trashes r0, r1, r2 and r3. |
|
143 // The call also trashes lr, and has the ability to trash ip. The function also |
|
144 // takes two arguments (dividend in r0, divisor in r1). The LInstruction gets |
|
145 // encoded such that the divisor and dividend are passed in their apropriate |
|
146 // registers and end their life at the start of the instruction by the use of |
|
147 // useFixedAtStart. The result is returned in r0 and the other three registers |
|
148 // that can be trashed are marked as temps. For the time being, the link |
|
149 // register is not marked as trashed because we never allocate to the link |
|
150 // register. The FP registers are not trashed. |
|
151 class LSoftDivI : public LBinaryMath<3> |
|
152 { |
|
153 public: |
|
154 LIR_HEADER(SoftDivI); |
|
155 |
|
156 LSoftDivI(const LAllocation &lhs, const LAllocation &rhs, |
|
157 const LDefinition &temp1, const LDefinition &temp2, const LDefinition &temp3) { |
|
158 setOperand(0, lhs); |
|
159 setOperand(1, rhs); |
|
160 setTemp(0, temp1); |
|
161 setTemp(1, temp2); |
|
162 setTemp(2, temp3); |
|
163 } |
|
164 |
|
165 MDiv *mir() const { |
|
166 return mir_->toDiv(); |
|
167 } |
|
168 }; |
|
169 |
|
170 class LDivPowTwoI : public LInstructionHelper<1, 1, 0> |
|
171 { |
|
172 const int32_t shift_; |
|
173 |
|
174 public: |
|
175 LIR_HEADER(DivPowTwoI) |
|
176 |
|
177 LDivPowTwoI(const LAllocation &lhs, int32_t shift) |
|
178 : shift_(shift) |
|
179 { |
|
180 setOperand(0, lhs); |
|
181 } |
|
182 |
|
183 const LAllocation *numerator() { |
|
184 return getOperand(0); |
|
185 } |
|
186 |
|
187 int32_t shift() { |
|
188 return shift_; |
|
189 } |
|
190 |
|
191 MDiv *mir() const { |
|
192 return mir_->toDiv(); |
|
193 } |
|
194 }; |
|
195 |
|
196 class LModI : public LBinaryMath<1> |
|
197 { |
|
198 public: |
|
199 LIR_HEADER(ModI); |
|
200 |
|
201 LModI(const LAllocation &lhs, const LAllocation &rhs, |
|
202 const LDefinition &callTemp) |
|
203 { |
|
204 setOperand(0, lhs); |
|
205 setOperand(1, rhs); |
|
206 setTemp(0, callTemp); |
|
207 } |
|
208 |
|
209 const LDefinition *callTemp() { |
|
210 return getTemp(0); |
|
211 } |
|
212 |
|
213 MMod *mir() const { |
|
214 return mir_->toMod(); |
|
215 } |
|
216 }; |
|
217 |
|
218 class LSoftModI : public LBinaryMath<4> |
|
219 { |
|
220 public: |
|
221 LIR_HEADER(SoftModI); |
|
222 |
|
223 LSoftModI(const LAllocation &lhs, const LAllocation &rhs, |
|
224 const LDefinition &temp1, const LDefinition &temp2, const LDefinition &temp3, |
|
225 const LDefinition &callTemp) |
|
226 { |
|
227 setOperand(0, lhs); |
|
228 setOperand(1, rhs); |
|
229 setTemp(0, temp1); |
|
230 setTemp(1, temp2); |
|
231 setTemp(2, temp3); |
|
232 setTemp(3, callTemp); |
|
233 } |
|
234 |
|
235 const LDefinition *callTemp() { |
|
236 return getTemp(3); |
|
237 } |
|
238 |
|
239 MMod *mir() const { |
|
240 return mir_->toMod(); |
|
241 } |
|
242 }; |
|
243 |
|
244 class LModPowTwoI : public LInstructionHelper<1, 1, 0> |
|
245 { |
|
246 const int32_t shift_; |
|
247 |
|
248 public: |
|
249 LIR_HEADER(ModPowTwoI); |
|
250 int32_t shift() |
|
251 { |
|
252 return shift_; |
|
253 } |
|
254 |
|
255 LModPowTwoI(const LAllocation &lhs, int32_t shift) |
|
256 : shift_(shift) |
|
257 { |
|
258 setOperand(0, lhs); |
|
259 } |
|
260 |
|
261 MMod *mir() const { |
|
262 return mir_->toMod(); |
|
263 } |
|
264 }; |
|
265 |
|
266 class LModMaskI : public LInstructionHelper<1, 1, 2> |
|
267 { |
|
268 const int32_t shift_; |
|
269 |
|
270 public: |
|
271 LIR_HEADER(ModMaskI); |
|
272 |
|
273 LModMaskI(const LAllocation &lhs, const LDefinition &temp1, const LDefinition &temp2, |
|
274 int32_t shift) |
|
275 : shift_(shift) |
|
276 { |
|
277 setOperand(0, lhs); |
|
278 setTemp(0, temp1); |
|
279 setTemp(1, temp2); |
|
280 } |
|
281 |
|
282 int32_t shift() const { |
|
283 return shift_; |
|
284 } |
|
285 |
|
286 MMod *mir() const { |
|
287 return mir_->toMod(); |
|
288 } |
|
289 }; |
|
290 |
|
291 class LPowHalfD : public LInstructionHelper<1, 1, 0> |
|
292 { |
|
293 public: |
|
294 LIR_HEADER(PowHalfD); |
|
295 LPowHalfD(const LAllocation &input) { |
|
296 setOperand(0, input); |
|
297 } |
|
298 |
|
299 const LAllocation *input() { |
|
300 return getOperand(0); |
|
301 } |
|
302 const LDefinition *output() { |
|
303 return getDef(0); |
|
304 } |
|
305 }; |
|
306 |
|
307 // Takes a tableswitch with an integer to decide |
|
308 class LTableSwitch : public LInstructionHelper<0, 1, 1> |
|
309 { |
|
310 public: |
|
311 LIR_HEADER(TableSwitch); |
|
312 |
|
313 LTableSwitch(const LAllocation &in, const LDefinition &inputCopy, MTableSwitch *ins) { |
|
314 setOperand(0, in); |
|
315 setTemp(0, inputCopy); |
|
316 setMir(ins); |
|
317 } |
|
318 |
|
319 MTableSwitch *mir() const { |
|
320 return mir_->toTableSwitch(); |
|
321 } |
|
322 |
|
323 const LAllocation *index() { |
|
324 return getOperand(0); |
|
325 } |
|
326 const LDefinition *tempInt() { |
|
327 return getTemp(0); |
|
328 } |
|
329 // This is added to share the same CodeGenerator prefixes. |
|
330 const LDefinition *tempPointer() { |
|
331 return nullptr; |
|
332 } |
|
333 }; |
|
334 |
|
335 // Takes a tableswitch with an integer to decide |
|
336 class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 2> |
|
337 { |
|
338 public: |
|
339 LIR_HEADER(TableSwitchV); |
|
340 |
|
341 LTableSwitchV(const LDefinition &inputCopy, const LDefinition &floatCopy, |
|
342 MTableSwitch *ins) |
|
343 { |
|
344 setTemp(0, inputCopy); |
|
345 setTemp(1, floatCopy); |
|
346 setMir(ins); |
|
347 } |
|
348 |
|
349 MTableSwitch *mir() const { |
|
350 return mir_->toTableSwitch(); |
|
351 } |
|
352 |
|
353 static const size_t InputValue = 0; |
|
354 |
|
355 const LDefinition *tempInt() { |
|
356 return getTemp(0); |
|
357 } |
|
358 const LDefinition *tempFloat() { |
|
359 return getTemp(1); |
|
360 } |
|
361 const LDefinition *tempPointer() { |
|
362 return nullptr; |
|
363 } |
|
364 }; |
|
365 |
|
366 class LGuardShape : public LInstructionHelper<0, 1, 1> |
|
367 { |
|
368 public: |
|
369 LIR_HEADER(GuardShape); |
|
370 |
|
371 LGuardShape(const LAllocation &in, const LDefinition &temp) { |
|
372 setOperand(0, in); |
|
373 setTemp(0, temp); |
|
374 } |
|
375 const MGuardShape *mir() const { |
|
376 return mir_->toGuardShape(); |
|
377 } |
|
378 const LDefinition *tempInt() { |
|
379 return getTemp(0); |
|
380 } |
|
381 }; |
|
382 |
|
383 class LGuardObjectType : public LInstructionHelper<0, 1, 1> |
|
384 { |
|
385 public: |
|
386 LIR_HEADER(GuardObjectType); |
|
387 |
|
388 LGuardObjectType(const LAllocation &in, const LDefinition &temp) { |
|
389 setOperand(0, in); |
|
390 setTemp(0, temp); |
|
391 } |
|
392 const MGuardObjectType *mir() const { |
|
393 return mir_->toGuardObjectType(); |
|
394 } |
|
395 const LDefinition *tempInt() { |
|
396 return getTemp(0); |
|
397 } |
|
398 }; |
|
399 |
|
400 class LInterruptCheck : public LInstructionHelper<0, 0, 0> |
|
401 { |
|
402 public: |
|
403 LIR_HEADER(InterruptCheck); |
|
404 }; |
|
405 |
|
406 class LMulI : public LBinaryMath<0> |
|
407 { |
|
408 public: |
|
409 LIR_HEADER(MulI); |
|
410 |
|
411 MMul *mir() { |
|
412 return mir_->toMul(); |
|
413 } |
|
414 }; |
|
415 |
|
416 class LUDiv : public LBinaryMath<0> |
|
417 { |
|
418 public: |
|
419 LIR_HEADER(UDiv); |
|
420 |
|
421 MDiv *mir() { |
|
422 return mir_->toDiv(); |
|
423 } |
|
424 }; |
|
425 |
|
426 class LUMod : public LBinaryMath<0> |
|
427 { |
|
428 public: |
|
429 LIR_HEADER(UMod); |
|
430 |
|
431 MMod *mir() { |
|
432 return mir_->toMod(); |
|
433 } |
|
434 }; |
|
435 |
|
436 // This class performs a simple x86 'div', yielding either a quotient or remainder depending on |
|
437 // whether this instruction is defined to output eax (quotient) or edx (remainder). |
|
438 class LSoftUDivOrMod : public LBinaryMath<3> |
|
439 { |
|
440 public: |
|
441 LIR_HEADER(SoftUDivOrMod); |
|
442 |
|
443 LSoftUDivOrMod(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp1, |
|
444 const LDefinition &temp2, const LDefinition &temp3) { |
|
445 setOperand(0, lhs); |
|
446 setOperand(1, rhs); |
|
447 setTemp(0, temp1); |
|
448 setTemp(1, temp2); |
|
449 setTemp(2, temp3); |
|
450 } |
|
451 }; |
|
452 |
|
453 class LAsmJSLoadFuncPtr : public LInstructionHelper<1, 1, 1> |
|
454 { |
|
455 public: |
|
456 LIR_HEADER(AsmJSLoadFuncPtr); |
|
457 LAsmJSLoadFuncPtr(const LAllocation &index, const LDefinition &temp) { |
|
458 setOperand(0, index); |
|
459 setTemp(0, temp); |
|
460 } |
|
461 const MAsmJSLoadFuncPtr *mir() const { |
|
462 return mir_->toAsmJSLoadFuncPtr(); |
|
463 } |
|
464 const LAllocation *index() { |
|
465 return getOperand(0); |
|
466 } |
|
467 const LDefinition *temp() { |
|
468 return getTemp(0); |
|
469 } |
|
470 }; |
|
471 |
|
472 } // namespace jit |
|
473 } // namespace js |
|
474 |
|
475 #endif /* jit_arm_LIR_arm_h */ |