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 LBoxFloatingPoint : public LInstructionHelper<2, 1, 1>
14 {
15     MIRType type_;
16 
17   public:
18     LIR_HEADER(BoxFloatingPoint);
19 
LBoxFloatingPoint(const LAllocation & in,const LDefinition & temp,MIRType type)20     LBoxFloatingPoint(const LAllocation& in, const LDefinition& temp, MIRType type)
21       : type_(type)
22     {
23         setOperand(0, in);
24         setTemp(0, temp);
25     }
26 
type()27     MIRType type() const {
28         return type_;
29     }
extraName()30     const char* extraName() const {
31         return StringFromMIRType(type_);
32     }
33 };
34 
35 class LUnbox : public LInstructionHelper<1, 2, 0>
36 {
37   public:
38     LIR_HEADER(Unbox);
39 
mir()40     MUnbox* mir() const {
41         return mir_->toUnbox();
42     }
payload()43     const LAllocation* payload() {
44         return getOperand(0);
45     }
type()46     const LAllocation* type() {
47         return getOperand(1);
48     }
extraName()49     const char* extraName() const {
50         return StringFromMIRType(mir()->type());
51     }
52 };
53 
54 class LUnboxFloatingPoint : public LInstructionHelper<1, 2, 0>
55 {
56     MIRType type_;
57 
58   public:
59     LIR_HEADER(UnboxFloatingPoint);
60 
61     static const size_t Input = 0;
62 
LUnboxFloatingPoint(const LBoxAllocation & input,MIRType type)63     LUnboxFloatingPoint(const LBoxAllocation& input, MIRType type)
64       : type_(type)
65     {
66         setBoxOperand(Input, input);
67     }
68 
mir()69     MUnbox* mir() const {
70         return mir_->toUnbox();
71     }
72 
type()73     MIRType type() const {
74         return type_;
75     }
extraName()76     const char* extraName() const {
77         return StringFromMIRType(type_);
78     }
79 };
80 
81 // Convert a 32-bit unsigned integer to a double.
82 class LWasmUint32ToDouble : public LInstructionHelper<1, 1, 0>
83 {
84   public:
LIR_HEADER(WasmUint32ToDouble)85     LIR_HEADER(WasmUint32ToDouble)
86 
87     LWasmUint32ToDouble(const LAllocation& input) {
88         setOperand(0, input);
89     }
90 };
91 
92 // Convert a 32-bit unsigned integer to a float32.
93 class LWasmUint32ToFloat32 : public LInstructionHelper<1, 1, 0>
94 {
95   public:
LIR_HEADER(WasmUint32ToFloat32)96     LIR_HEADER(WasmUint32ToFloat32)
97 
98     LWasmUint32ToFloat32(const LAllocation& input) {
99         setOperand(0, input);
100     }
101 };
102 
103 class LDivI : public LBinaryMath<1>
104 {
105   public:
106     LIR_HEADER(DivI);
107 
LDivI(const LAllocation & lhs,const LAllocation & rhs,const LDefinition & temp)108     LDivI(const LAllocation& lhs, const LAllocation& rhs,
109           const LDefinition& temp) {
110         setOperand(0, lhs);
111         setOperand(1, rhs);
112         setTemp(0, temp);
113     }
114 
mir()115     MDiv* mir() const {
116         return mir_->toDiv();
117     }
118 };
119 
120 class LDivOrModI64 : public LCallInstructionHelper<INT64_PIECES, INT64_PIECES*2, 0>
121 {
122   public:
123     LIR_HEADER(DivOrModI64)
124 
125     static const size_t Lhs = 0;
126     static const size_t Rhs = INT64_PIECES;
127 
LDivOrModI64(const LInt64Allocation & lhs,const LInt64Allocation & rhs)128     LDivOrModI64(const LInt64Allocation& lhs, const LInt64Allocation& rhs)
129     {
130         setInt64Operand(Lhs, lhs);
131         setInt64Operand(Rhs, rhs);
132     }
133 
mir()134     MBinaryArithInstruction* mir() const {
135         MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
136         return static_cast<MBinaryArithInstruction*>(mir_);
137     }
canBeDivideByZero()138     bool canBeDivideByZero() const {
139         if (mir_->isMod())
140             return mir_->toMod()->canBeDivideByZero();
141         return mir_->toDiv()->canBeDivideByZero();
142     }
canBeNegativeOverflow()143     bool canBeNegativeOverflow() const {
144         if (mir_->isMod())
145             return mir_->toMod()->canBeNegativeDividend();
146         return mir_->toDiv()->canBeNegativeOverflow();
147     }
trapOffset()148     wasm::TrapOffset trapOffset() const {
149         MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
150         if (mir_->isMod())
151             return mir_->toMod()->trapOffset();
152         return mir_->toDiv()->trapOffset();
153     }
154 };
155 
156 class LUDivOrModI64 : public LCallInstructionHelper<INT64_PIECES, INT64_PIECES*2, 0>
157 {
158   public:
159     LIR_HEADER(UDivOrModI64)
160 
161     static const size_t Lhs = 0;
162     static const size_t Rhs = INT64_PIECES;
163 
LUDivOrModI64(const LInt64Allocation & lhs,const LInt64Allocation & rhs)164     LUDivOrModI64(const LInt64Allocation& lhs, const LInt64Allocation& rhs)
165     {
166         setInt64Operand(Lhs, lhs);
167         setInt64Operand(Rhs, rhs);
168     }
169 
mir()170     MBinaryArithInstruction* mir() const {
171         MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
172         return static_cast<MBinaryArithInstruction*>(mir_);
173     }
canBeDivideByZero()174     bool canBeDivideByZero() const {
175         if (mir_->isMod())
176             return mir_->toMod()->canBeDivideByZero();
177         return mir_->toDiv()->canBeDivideByZero();
178     }
canBeNegativeOverflow()179     bool canBeNegativeOverflow() const {
180         if (mir_->isMod())
181             return mir_->toMod()->canBeNegativeDividend();
182         return mir_->toDiv()->canBeNegativeOverflow();
183     }
trapOffset()184     wasm::TrapOffset trapOffset() const {
185         MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
186         if (mir_->isMod())
187             return mir_->toMod()->trapOffset();
188         return mir_->toDiv()->trapOffset();
189     }
190 };
191 
192 // LSoftDivI is a software divide for ARM cores that don't support a hardware
193 // divide instruction.
194 //
195 // It is implemented as a proper C function so it trashes r0, r1, r2 and r3.
196 // The call also trashes lr, and has the ability to trash ip. The function also
197 // takes two arguments (dividend in r0, divisor in r1). The LInstruction gets
198 // encoded such that the divisor and dividend are passed in their apropriate
199 // registers and end their life at the start of the instruction by the use of
200 // useFixedAtStart. The result is returned in r0 and the other three registers
201 // that can be trashed are marked as temps. For the time being, the link
202 // register is not marked as trashed because we never allocate to the link
203 // register. The FP registers are not trashed.
204 class LSoftDivI : public LBinaryMath<3>
205 {
206   public:
207     LIR_HEADER(SoftDivI);
208 
LSoftDivI(const LAllocation & lhs,const LAllocation & rhs,const LDefinition & temp1,const LDefinition & temp2,const LDefinition & temp3)209     LSoftDivI(const LAllocation& lhs, const LAllocation& rhs,
210               const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) {
211         setOperand(0, lhs);
212         setOperand(1, rhs);
213         setTemp(0, temp1);
214         setTemp(1, temp2);
215         setTemp(2, temp3);
216     }
217 
mir()218     MDiv* mir() const {
219         return mir_->toDiv();
220     }
221 };
222 
223 class LDivPowTwoI : public LInstructionHelper<1, 1, 0>
224 {
225     const int32_t shift_;
226 
227   public:
LIR_HEADER(DivPowTwoI)228     LIR_HEADER(DivPowTwoI)
229 
230     LDivPowTwoI(const LAllocation& lhs, int32_t shift)
231       : shift_(shift)
232     {
233         setOperand(0, lhs);
234     }
235 
numerator()236     const LAllocation* numerator() {
237         return getOperand(0);
238     }
239 
shift()240     int32_t shift() {
241         return shift_;
242     }
243 
mir()244     MDiv* mir() const {
245         return mir_->toDiv();
246     }
247 };
248 
249 class LModI : public LBinaryMath<1>
250 {
251   public:
252     LIR_HEADER(ModI);
253 
LModI(const LAllocation & lhs,const LAllocation & rhs,const LDefinition & callTemp)254     LModI(const LAllocation& lhs, const LAllocation& rhs,
255           const LDefinition& callTemp)
256     {
257         setOperand(0, lhs);
258         setOperand(1, rhs);
259         setTemp(0, callTemp);
260     }
261 
callTemp()262     const LDefinition* callTemp() {
263         return getTemp(0);
264     }
265 
mir()266     MMod* mir() const {
267         return mir_->toMod();
268     }
269 };
270 
271 class LSoftModI : public LBinaryMath<4>
272 {
273   public:
274     LIR_HEADER(SoftModI);
275 
LSoftModI(const LAllocation & lhs,const LAllocation & rhs,const LDefinition & temp1,const LDefinition & temp2,const LDefinition & temp3,const LDefinition & callTemp)276     LSoftModI(const LAllocation& lhs, const LAllocation& rhs,
277               const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3,
278               const LDefinition& callTemp)
279     {
280         setOperand(0, lhs);
281         setOperand(1, rhs);
282         setTemp(0, temp1);
283         setTemp(1, temp2);
284         setTemp(2, temp3);
285         setTemp(3, callTemp);
286     }
287 
callTemp()288     const LDefinition* callTemp() {
289         return getTemp(3);
290     }
291 
mir()292     MMod* mir() const {
293         return mir_->toMod();
294     }
295 };
296 
297 class LModPowTwoI : public LInstructionHelper<1, 1, 0>
298 {
299     const int32_t shift_;
300 
301   public:
302     LIR_HEADER(ModPowTwoI);
shift()303     int32_t shift()
304     {
305         return shift_;
306     }
307 
LModPowTwoI(const LAllocation & lhs,int32_t shift)308     LModPowTwoI(const LAllocation& lhs, int32_t shift)
309       : shift_(shift)
310     {
311         setOperand(0, lhs);
312     }
313 
mir()314     MMod* mir() const {
315         return mir_->toMod();
316     }
317 };
318 
319 class LModMaskI : public LInstructionHelper<1, 1, 2>
320 {
321     const int32_t shift_;
322 
323   public:
324     LIR_HEADER(ModMaskI);
325 
LModMaskI(const LAllocation & lhs,const LDefinition & temp1,const LDefinition & temp2,int32_t shift)326     LModMaskI(const LAllocation& lhs, const LDefinition& temp1, const LDefinition& temp2,
327               int32_t shift)
328       : shift_(shift)
329     {
330         setOperand(0, lhs);
331         setTemp(0, temp1);
332         setTemp(1, temp2);
333     }
334 
shift()335     int32_t shift() const {
336         return shift_;
337     }
338 
mir()339     MMod* mir() const {
340         return mir_->toMod();
341     }
342 };
343 
344 // Takes a tableswitch with an integer to decide.
345 class LTableSwitch : public LInstructionHelper<0, 1, 1>
346 {
347   public:
348     LIR_HEADER(TableSwitch);
349 
LTableSwitch(const LAllocation & in,const LDefinition & inputCopy,MTableSwitch * ins)350     LTableSwitch(const LAllocation& in, const LDefinition& inputCopy, MTableSwitch* ins) {
351         setOperand(0, in);
352         setTemp(0, inputCopy);
353         setMir(ins);
354     }
355 
mir()356     MTableSwitch* mir() const {
357         return mir_->toTableSwitch();
358     }
359 
index()360     const LAllocation* index() {
361         return getOperand(0);
362     }
tempInt()363     const LDefinition* tempInt() {
364         return getTemp(0);
365     }
366     // This is added to share the same CodeGenerator prefixes.
tempPointer()367     const LDefinition* tempPointer() {
368         return nullptr;
369     }
370 };
371 
372 // Takes a tableswitch with an integer to decide.
373 class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 2>
374 {
375   public:
376     LIR_HEADER(TableSwitchV);
377 
LTableSwitchV(const LBoxAllocation & input,const LDefinition & inputCopy,const LDefinition & floatCopy,MTableSwitch * ins)378     LTableSwitchV(const LBoxAllocation& input, const LDefinition& inputCopy,
379                   const LDefinition& floatCopy, MTableSwitch* ins)
380     {
381         setBoxOperand(InputValue, input);
382         setTemp(0, inputCopy);
383         setTemp(1, floatCopy);
384         setMir(ins);
385     }
386 
mir()387     MTableSwitch* mir() const {
388         return mir_->toTableSwitch();
389     }
390 
391     static const size_t InputValue = 0;
392 
tempInt()393     const LDefinition* tempInt() {
394         return getTemp(0);
395     }
tempFloat()396     const LDefinition* tempFloat() {
397         return getTemp(1);
398     }
tempPointer()399     const LDefinition* tempPointer() {
400         return nullptr;
401     }
402 };
403 
404 class LGuardShape : public LInstructionHelper<0, 1, 1>
405 {
406   public:
407     LIR_HEADER(GuardShape);
408 
LGuardShape(const LAllocation & in,const LDefinition & temp)409     LGuardShape(const LAllocation& in, const LDefinition& temp) {
410         setOperand(0, in);
411         setTemp(0, temp);
412     }
mir()413     const MGuardShape* mir() const {
414         return mir_->toGuardShape();
415     }
tempInt()416     const LDefinition* tempInt() {
417         return getTemp(0);
418     }
419 };
420 
421 class LGuardObjectGroup : public LInstructionHelper<0, 1, 1>
422 {
423   public:
424     LIR_HEADER(GuardObjectGroup);
425 
LGuardObjectGroup(const LAllocation & in,const LDefinition & temp)426     LGuardObjectGroup(const LAllocation& in, const LDefinition& temp) {
427         setOperand(0, in);
428         setTemp(0, temp);
429     }
mir()430     const MGuardObjectGroup* mir() const {
431         return mir_->toGuardObjectGroup();
432     }
tempInt()433     const LDefinition* tempInt() {
434         return getTemp(0);
435     }
436 };
437 
438 class LMulI : public LBinaryMath<0>
439 {
440   public:
441     LIR_HEADER(MulI);
442 
mir()443     MMul* mir() {
444         return mir_->toMul();
445     }
446 };
447 
448 class LUDiv : public LBinaryMath<0>
449 {
450   public:
451     LIR_HEADER(UDiv);
452 
mir()453     MDiv* mir() {
454         return mir_->toDiv();
455     }
456 };
457 
458 class LUMod : public LBinaryMath<0>
459 {
460   public:
461     LIR_HEADER(UMod);
462 
mir()463     MMod* mir() {
464         return mir_->toMod();
465     }
466 };
467 
468 class LSoftUDivOrMod : public LBinaryMath<3>
469 {
470   public:
471     LIR_HEADER(SoftUDivOrMod);
472 
LSoftUDivOrMod(const LAllocation & lhs,const LAllocation & rhs,const LDefinition & temp1,const LDefinition & temp2,const LDefinition & temp3)473     LSoftUDivOrMod(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp1,
474                    const LDefinition& temp2, const LDefinition& temp3) {
475         setOperand(0, lhs);
476         setOperand(1, rhs);
477         setTemp(0, temp1);
478         setTemp(1, temp2);
479         setTemp(2, temp3);
480     }
481 
mir()482     MInstruction* mir() {
483         return mir_->toInstruction();
484     }
485 };
486 
487 class LAsmJSCompareExchangeCallout : public LCallInstructionHelper<1, 4, 2>
488 {
489   public:
LIR_HEADER(AsmJSCompareExchangeCallout)490     LIR_HEADER(AsmJSCompareExchangeCallout)
491     LAsmJSCompareExchangeCallout(const LAllocation& ptr, const LAllocation& oldval,
492                                  const LAllocation& newval, const LAllocation& tls,
493                                  const LDefinition& temp1, const LDefinition& temp2)
494     {
495         setOperand(0, ptr);
496         setOperand(1, oldval);
497         setOperand(2, newval);
498         setOperand(3, tls);
499         setTemp(0, temp1);
500         setTemp(1, temp2);
501     }
ptr()502     const LAllocation* ptr() {
503         return getOperand(0);
504     }
oldval()505     const LAllocation* oldval() {
506         return getOperand(1);
507     }
newval()508     const LAllocation* newval() {
509         return getOperand(2);
510     }
tls()511     const LAllocation* tls() {
512         return getOperand(3);
513     }
514 
mir()515     const MAsmJSCompareExchangeHeap* mir() const {
516         return mir_->toAsmJSCompareExchangeHeap();
517     }
518 };
519 
520 class LAsmJSAtomicExchangeCallout : public LCallInstructionHelper<1, 3, 2>
521 {
522   public:
LIR_HEADER(AsmJSAtomicExchangeCallout)523     LIR_HEADER(AsmJSAtomicExchangeCallout)
524 
525     LAsmJSAtomicExchangeCallout(const LAllocation& ptr, const LAllocation& value,
526                                 const LAllocation& tls, const LDefinition& temp1,
527                                 const LDefinition& temp2)
528     {
529         setOperand(0, ptr);
530         setOperand(1, value);
531         setOperand(2, tls);
532         setTemp(0, temp1);
533         setTemp(1, temp2);
534     }
ptr()535     const LAllocation* ptr() {
536         return getOperand(0);
537     }
value()538     const LAllocation* value() {
539         return getOperand(1);
540     }
tls()541     const LAllocation* tls() {
542         return getOperand(2);
543     }
544 
mir()545     const MAsmJSAtomicExchangeHeap* mir() const {
546         return mir_->toAsmJSAtomicExchangeHeap();
547     }
548 };
549 
550 class LAsmJSAtomicBinopCallout : public LCallInstructionHelper<1, 3, 2>
551 {
552   public:
LIR_HEADER(AsmJSAtomicBinopCallout)553     LIR_HEADER(AsmJSAtomicBinopCallout)
554     LAsmJSAtomicBinopCallout(const LAllocation& ptr, const LAllocation& value,
555                              const LAllocation& tls, const LDefinition& temp1,
556                              const LDefinition& temp2)
557     {
558         setOperand(0, ptr);
559         setOperand(1, value);
560         setOperand(2, tls);
561         setTemp(0, temp1);
562         setTemp(1, temp2);
563     }
ptr()564     const LAllocation* ptr() {
565         return getOperand(0);
566     }
value()567     const LAllocation* value() {
568         return getOperand(1);
569     }
tls()570     const LAllocation* tls() {
571         return getOperand(2);
572     }
573 
mir()574     const MAsmJSAtomicBinopHeap* mir() const {
575         return mir_->toAsmJSAtomicBinopHeap();
576     }
577 };
578 
579 class LWasmTruncateToInt64 : public LCallInstructionHelper<INT64_PIECES, 1, 0>
580 {
581   public:
582     LIR_HEADER(WasmTruncateToInt64);
583 
LWasmTruncateToInt64(const LAllocation & in)584     LWasmTruncateToInt64(const LAllocation& in)
585     {
586         setOperand(0, in);
587     }
588 
mir()589     MWasmTruncateToInt64* mir() const {
590         return mir_->toWasmTruncateToInt64();
591     }
592 };
593 
594 class LInt64ToFloatingPointCall: public LCallInstructionHelper<1, INT64_PIECES, 0>
595 {
596   public:
597     LIR_HEADER(Int64ToFloatingPointCall);
598 
mir()599     MInt64ToFloatingPoint* mir() const {
600         return mir_->toInt64ToFloatingPoint();
601     }
602 };
603 
604 namespace details {
605 
606 // Base class for the int64 and non-int64 variants.
607 template<size_t NumDefs>
608 class LWasmUnalignedLoadBase : public details::LWasmLoadBase<NumDefs, 4>
609 {
610   public:
611     typedef LWasmLoadBase<NumDefs, 4> Base;
LWasmUnalignedLoadBase(const LAllocation & ptr,const LDefinition & ptrCopy,const LDefinition & temp1,const LDefinition & temp2,const LDefinition & temp3)612     explicit LWasmUnalignedLoadBase(const LAllocation& ptr, const LDefinition& ptrCopy,
613                                     const LDefinition& temp1, const LDefinition& temp2,
614                                     const LDefinition& temp3)
615       : Base(ptr)
616     {
617         Base::setTemp(0, ptrCopy);
618         Base::setTemp(1, temp1);
619         Base::setTemp(2, temp2);
620         Base::setTemp(3, temp3);
621     }
622 
ptrCopy()623     const LDefinition* ptrCopy() {
624         return Base::getTemp(0);
625     }
626 };
627 
628 } // namespace details
629 
630 class LWasmUnalignedLoad : public details::LWasmUnalignedLoadBase<1>
631 {
632   public:
LWasmUnalignedLoad(const LAllocation & ptr,const LDefinition & ptrCopy,const LDefinition & temp1,const LDefinition & temp2,const LDefinition & temp3)633     explicit LWasmUnalignedLoad(const LAllocation& ptr, const LDefinition& ptrCopy,
634                                 const LDefinition& temp1, const LDefinition& temp2,
635                                 const LDefinition& temp3)
636       : LWasmUnalignedLoadBase(ptr, ptrCopy, temp1, temp2, temp3)
637     {}
638     LIR_HEADER(WasmUnalignedLoad);
639 };
640 
641 class LWasmUnalignedLoadI64 : public details::LWasmUnalignedLoadBase<INT64_PIECES>
642 {
643   public:
LWasmUnalignedLoadI64(const LAllocation & ptr,const LDefinition & ptrCopy,const LDefinition & temp1,const LDefinition & temp2,const LDefinition & temp3)644     explicit LWasmUnalignedLoadI64(const LAllocation& ptr, const LDefinition& ptrCopy,
645                                    const LDefinition& temp1, const LDefinition& temp2,
646                                    const LDefinition& temp3)
647       : LWasmUnalignedLoadBase(ptr, ptrCopy, temp1, temp2, temp3)
648     {}
649     LIR_HEADER(WasmUnalignedLoadI64);
650 };
651 
652 namespace details {
653 
654 // Base class for the int64 and non-int64 variants.
655 template<size_t NumOps>
656 class LWasmUnalignedStoreBase : public LInstructionHelper<0, NumOps, 2>
657 {
658   public:
659     typedef LInstructionHelper<0, NumOps, 2> Base;
660 
661     static const uint32_t ValueIndex = 1;
662 
LWasmUnalignedStoreBase(const LAllocation & ptr,const LDefinition & ptrCopy,const LDefinition & valueHelper)663     LWasmUnalignedStoreBase(const LAllocation& ptr, const LDefinition& ptrCopy,
664                             const LDefinition& valueHelper)
665     {
666         Base::setOperand(0, ptr);
667         Base::setTemp(0, ptrCopy);
668         Base::setTemp(1, valueHelper);
669     }
mir()670     MWasmStore* mir() const {
671         return Base::mir_->toWasmStore();
672     }
ptrCopy()673     const LDefinition* ptrCopy() {
674         return Base::getTemp(0);
675     }
valueHelper()676     const LDefinition* valueHelper() {
677         return Base::getTemp(1);
678     }
679 };
680 
681 } // namespace details
682 
683 class LWasmUnalignedStore : public details::LWasmUnalignedStoreBase<2>
684 {
685   public:
686     LIR_HEADER(WasmUnalignedStore);
LWasmUnalignedStore(const LAllocation & ptr,const LAllocation & value,const LDefinition & ptrCopy,const LDefinition & valueHelper)687     LWasmUnalignedStore(const LAllocation& ptr, const LAllocation& value,
688                         const LDefinition& ptrCopy, const LDefinition& valueHelper)
689       : LWasmUnalignedStoreBase(ptr, ptrCopy, valueHelper)
690     {
691         setOperand(1, value);
692     }
693 };
694 
695 class LWasmUnalignedStoreI64 : public details::LWasmUnalignedStoreBase<1 + INT64_PIECES>
696 {
697   public:
698     LIR_HEADER(WasmUnalignedStoreI64);
LWasmUnalignedStoreI64(const LAllocation & ptr,const LInt64Allocation & value,const LDefinition & ptrCopy,const LDefinition & valueHelper)699     LWasmUnalignedStoreI64(const LAllocation& ptr, const LInt64Allocation& value,
700                            const LDefinition& ptrCopy, const LDefinition& valueHelper)
701       : LWasmUnalignedStoreBase(ptr, ptrCopy, valueHelper)
702     {
703         setInt64Operand(1, value);
704     }
705 };
706 
707 } // namespace jit
708 } // namespace js
709 
710 #endif /* jit_arm_LIR_arm_h */
711