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_mips_shared_LIR_mips_shared_h
8 #define jit_mips_shared_LIR_mips_shared_h
9 
10 namespace js {
11 namespace jit {
12 
13 // Convert a 32-bit unsigned integer to a double.
14 class LWasmUint32ToDouble : public LInstructionHelper<1, 1, 0> {
15  public:
LIR_HEADER(WasmUint32ToDouble)16   LIR_HEADER(WasmUint32ToDouble)
17 
18   LWasmUint32ToDouble(const LAllocation& input) { setOperand(0, input); }
19 };
20 
21 // Convert a 32-bit unsigned integer to a float32.
22 class LWasmUint32ToFloat32 : public LInstructionHelper<1, 1, 0> {
23  public:
LIR_HEADER(WasmUint32ToFloat32)24   LIR_HEADER(WasmUint32ToFloat32)
25 
26   LWasmUint32ToFloat32(const LAllocation& input) { setOperand(0, input); }
27 };
28 
29 class LDivI : public LBinaryMath<1> {
30  public:
31   LIR_HEADER(DivI);
32 
LDivI(const LAllocation & lhs,const LAllocation & rhs,const LDefinition & temp)33   LDivI(const LAllocation& lhs, const LAllocation& rhs,
34         const LDefinition& temp) {
35     setOperand(0, lhs);
36     setOperand(1, rhs);
37     setTemp(0, temp);
38   }
39 
mir()40   MDiv* mir() const { return mir_->toDiv(); }
41 };
42 
43 class LDivPowTwoI : public LInstructionHelper<1, 1, 1> {
44   const int32_t shift_;
45 
46  public:
LIR_HEADER(DivPowTwoI)47   LIR_HEADER(DivPowTwoI)
48 
49   LDivPowTwoI(const LAllocation& lhs, int32_t shift, const LDefinition& temp)
50       : shift_(shift) {
51     setOperand(0, lhs);
52     setTemp(0, temp);
53   }
54 
numerator()55   const LAllocation* numerator() { return getOperand(0); }
56 
shift()57   int32_t shift() { return shift_; }
58 
mir()59   MDiv* mir() const { return mir_->toDiv(); }
60 };
61 
62 class LModI : public LBinaryMath<1> {
63  public:
64   LIR_HEADER(ModI);
65 
LModI(const LAllocation & lhs,const LAllocation & rhs,const LDefinition & callTemp)66   LModI(const LAllocation& lhs, const LAllocation& rhs,
67         const LDefinition& callTemp) {
68     setOperand(0, lhs);
69     setOperand(1, rhs);
70     setTemp(0, callTemp);
71   }
72 
callTemp()73   const LDefinition* callTemp() { return getTemp(0); }
74 
mir()75   MMod* mir() const { return mir_->toMod(); }
76 };
77 
78 class LModPowTwoI : public LInstructionHelper<1, 1, 0> {
79   const int32_t shift_;
80 
81  public:
82   LIR_HEADER(ModPowTwoI);
shift()83   int32_t shift() { return shift_; }
84 
LModPowTwoI(const LAllocation & lhs,int32_t shift)85   LModPowTwoI(const LAllocation& lhs, int32_t shift) : shift_(shift) {
86     setOperand(0, lhs);
87   }
88 
mir()89   MMod* mir() const { return mir_->toMod(); }
90 };
91 
92 class LModMaskI : public LInstructionHelper<1, 1, 2> {
93   const int32_t shift_;
94 
95  public:
96   LIR_HEADER(ModMaskI);
97 
LModMaskI(const LAllocation & lhs,const LDefinition & temp0,const LDefinition & temp1,int32_t shift)98   LModMaskI(const LAllocation& lhs, const LDefinition& temp0,
99             const LDefinition& temp1, int32_t shift)
100       : shift_(shift) {
101     setOperand(0, lhs);
102     setTemp(0, temp0);
103     setTemp(1, temp1);
104   }
105 
shift()106   int32_t shift() const { return shift_; }
107 
mir()108   MMod* mir() const { return mir_->toMod(); }
109 };
110 
111 // Takes a tableswitch with an integer to decide
112 class LTableSwitch : public LInstructionHelper<0, 1, 2> {
113  public:
114   LIR_HEADER(TableSwitch);
115 
LTableSwitch(const LAllocation & in,const LDefinition & inputCopy,const LDefinition & jumpTablePointer,MTableSwitch * ins)116   LTableSwitch(const LAllocation& in, const LDefinition& inputCopy,
117                const LDefinition& jumpTablePointer, MTableSwitch* ins) {
118     setOperand(0, in);
119     setTemp(0, inputCopy);
120     setTemp(1, jumpTablePointer);
121     setMir(ins);
122   }
123 
mir()124   MTableSwitch* mir() const { return mir_->toTableSwitch(); }
125 
index()126   const LAllocation* index() { return getOperand(0); }
tempInt()127   const LDefinition* tempInt() { return getTemp(0); }
128   // This is added to share the same CodeGenerator prefixes.
tempPointer()129   const LDefinition* tempPointer() { return getTemp(1); }
130 };
131 
132 // Takes a tableswitch with an integer to decide
133 class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 3> {
134  public:
135   LIR_HEADER(TableSwitchV);
136 
LTableSwitchV(const LBoxAllocation & input,const LDefinition & inputCopy,const LDefinition & floatCopy,const LDefinition & jumpTablePointer,MTableSwitch * ins)137   LTableSwitchV(const LBoxAllocation& input, const LDefinition& inputCopy,
138                 const LDefinition& floatCopy,
139                 const LDefinition& jumpTablePointer, MTableSwitch* ins) {
140     setBoxOperand(InputValue, input);
141     setTemp(0, inputCopy);
142     setTemp(1, floatCopy);
143     setTemp(2, jumpTablePointer);
144     setMir(ins);
145   }
146 
mir()147   MTableSwitch* mir() const { return mir_->toTableSwitch(); }
148 
149   static const size_t InputValue = 0;
150 
tempInt()151   const LDefinition* tempInt() { return getTemp(0); }
tempFloat()152   const LDefinition* tempFloat() { return getTemp(1); }
tempPointer()153   const LDefinition* tempPointer() { return getTemp(2); }
154 };
155 
156 class LMulI : public LBinaryMath<0> {
157  public:
158   LIR_HEADER(MulI);
159 
mir()160   MMul* mir() { return mir_->toMul(); }
161 };
162 
163 class LUDivOrMod : public LBinaryMath<0> {
164  public:
165   LIR_HEADER(UDivOrMod);
166 
mir()167   MBinaryArithInstruction* mir() const {
168     MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
169     return static_cast<MBinaryArithInstruction*>(mir_);
170   }
171 
canBeDivideByZero()172   bool canBeDivideByZero() const {
173     if (mir_->isMod()) return mir_->toMod()->canBeDivideByZero();
174     return mir_->toDiv()->canBeDivideByZero();
175   }
176 
trapOnError()177   bool trapOnError() const {
178     if (mir_->isMod()) return mir_->toMod()->trapOnError();
179     return mir_->toDiv()->trapOnError();
180   }
181 
bytecodeOffset()182   wasm::BytecodeOffset bytecodeOffset() const {
183     MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
184     if (mir_->isMod()) return mir_->toMod()->bytecodeOffset();
185     return mir_->toDiv()->bytecodeOffset();
186   }
187 };
188 
189 namespace details {
190 
191 // Base class for the int64 and non-int64 variants.
192 template <size_t NumDefs>
193 class LWasmUnalignedLoadBase : public details::LWasmLoadBase<NumDefs, 2> {
194  public:
195   typedef LWasmLoadBase<NumDefs, 2> Base;
196 
LWasmUnalignedLoadBase(const LAllocation & ptr,const LDefinition & valueHelper)197   explicit LWasmUnalignedLoadBase(const LAllocation& ptr,
198                                   const LDefinition& valueHelper)
199       : Base(ptr, LAllocation()) {
200     Base::setTemp(0, LDefinition::BogusTemp());
201     Base::setTemp(1, valueHelper);
202   }
ptr()203   const LAllocation* ptr() { return Base::getOperand(0); }
ptrCopy()204   const LDefinition* ptrCopy() { return Base::getTemp(0); }
205 };
206 
207 }  // namespace details
208 
209 class LWasmUnalignedLoad : public details::LWasmUnalignedLoadBase<1> {
210  public:
LWasmUnalignedLoad(const LAllocation & ptr,const LDefinition & valueHelper)211   explicit LWasmUnalignedLoad(const LAllocation& ptr,
212                               const LDefinition& valueHelper)
213       : LWasmUnalignedLoadBase(ptr, valueHelper) {}
214   LIR_HEADER(WasmUnalignedLoad);
215 };
216 
217 class LWasmUnalignedLoadI64
218     : public details::LWasmUnalignedLoadBase<INT64_PIECES> {
219  public:
LWasmUnalignedLoadI64(const LAllocation & ptr,const LDefinition & valueHelper)220   explicit LWasmUnalignedLoadI64(const LAllocation& ptr,
221                                  const LDefinition& valueHelper)
222       : LWasmUnalignedLoadBase(ptr, valueHelper) {}
223   LIR_HEADER(WasmUnalignedLoadI64);
224 };
225 
226 namespace details {
227 
228 // Base class for the int64 and non-int64 variants.
229 template <size_t NumOps>
230 class LWasmUnalignedStoreBase : public LInstructionHelper<0, NumOps, 2> {
231  public:
232   typedef LInstructionHelper<0, NumOps, 2> Base;
233 
234   static const size_t PtrIndex = 0;
235   static const size_t ValueIndex = 1;
236 
LWasmUnalignedStoreBase(const LAllocation & ptr,const LDefinition & valueHelper)237   LWasmUnalignedStoreBase(const LAllocation& ptr,
238                           const LDefinition& valueHelper) {
239     Base::setOperand(0, ptr);
240     Base::setTemp(0, LDefinition::BogusTemp());
241     Base::setTemp(1, valueHelper);
242   }
mir()243   MWasmStore* mir() const { return Base::mir_->toWasmStore(); }
ptr()244   const LAllocation* ptr() { return Base::getOperand(PtrIndex); }
ptrCopy()245   const LDefinition* ptrCopy() { return Base::getTemp(0); }
246 };
247 
248 }  // namespace details
249 
250 class LWasmUnalignedStore : public details::LWasmUnalignedStoreBase<2> {
251  public:
252   LIR_HEADER(WasmUnalignedStore);
LWasmUnalignedStore(const LAllocation & ptr,const LAllocation & value,const LDefinition & valueHelper)253   LWasmUnalignedStore(const LAllocation& ptr, const LAllocation& value,
254                       const LDefinition& valueHelper)
255       : LWasmUnalignedStoreBase(ptr, valueHelper) {
256     setOperand(1, value);
257   }
value()258   const LAllocation* value() { return Base::getOperand(ValueIndex); }
259 };
260 
261 class LWasmUnalignedStoreI64
262     : public details::LWasmUnalignedStoreBase<1 + INT64_PIECES> {
263  public:
264   LIR_HEADER(WasmUnalignedStoreI64);
LWasmUnalignedStoreI64(const LAllocation & ptr,const LInt64Allocation & value,const LDefinition & valueHelper)265   LWasmUnalignedStoreI64(const LAllocation& ptr, const LInt64Allocation& value,
266                          const LDefinition& valueHelper)
267       : LWasmUnalignedStoreBase(ptr, valueHelper) {
268     setInt64Operand(1, value);
269   }
value()270   const LInt64Allocation value() { return getInt64Operand(ValueIndex); }
271 };
272 
273 class LWasmCompareExchangeI64
274     : public LInstructionHelper<INT64_PIECES, 1 + INT64_PIECES + INT64_PIECES,
275                                 0> {
276  public:
277   LIR_HEADER(WasmCompareExchangeI64);
278 
LWasmCompareExchangeI64(const LAllocation & ptr,const LInt64Allocation & oldValue,const LInt64Allocation & newValue)279   LWasmCompareExchangeI64(const LAllocation& ptr,
280                           const LInt64Allocation& oldValue,
281                           const LInt64Allocation& newValue) {
282     setOperand(0, ptr);
283     setInt64Operand(1, oldValue);
284     setInt64Operand(1 + INT64_PIECES, newValue);
285   }
286 
ptr()287   const LAllocation* ptr() { return getOperand(0); }
oldValue()288   const LInt64Allocation oldValue() { return getInt64Operand(1); }
newValue()289   const LInt64Allocation newValue() {
290     return getInt64Operand(1 + INT64_PIECES);
291   }
mir()292   const MWasmCompareExchangeHeap* mir() const {
293     return mir_->toWasmCompareExchangeHeap();
294   }
295 };
296 
297 class LWasmAtomicExchangeI64
298     : public LInstructionHelper<INT64_PIECES, 1 + INT64_PIECES, 0> {
299  public:
300   LIR_HEADER(WasmAtomicExchangeI64);
301 
LWasmAtomicExchangeI64(const LAllocation & ptr,const LInt64Allocation & value)302   LWasmAtomicExchangeI64(const LAllocation& ptr,
303                          const LInt64Allocation& value) {
304     setOperand(0, ptr);
305     setInt64Operand(1, value);
306   }
307 
ptr()308   const LAllocation* ptr() { return getOperand(0); }
value()309   const LInt64Allocation value() { return getInt64Operand(1); }
mir()310   const MWasmAtomicExchangeHeap* mir() const {
311     return mir_->toWasmAtomicExchangeHeap();
312   }
313 };
314 
315 class LWasmAtomicBinopI64
316     : public LInstructionHelper<INT64_PIECES, 1 + INT64_PIECES, 2> {
317  public:
318   LIR_HEADER(WasmAtomicBinopI64);
319 
LWasmAtomicBinopI64(const LAllocation & ptr,const LInt64Allocation & value)320   LWasmAtomicBinopI64(const LAllocation& ptr, const LInt64Allocation& value) {
321     setOperand(0, ptr);
322     setInt64Operand(1, value);
323   }
324 
ptr()325   const LAllocation* ptr() { return getOperand(0); }
value()326   const LInt64Allocation value() { return getInt64Operand(1); }
327 
mir()328   const MWasmAtomicBinopHeap* mir() const {
329     return mir_->toWasmAtomicBinopHeap();
330   }
331 };
332 
333 }  // namespace jit
334 }  // namespace js
335 
336 #endif /* jit_mips_shared_LIR_mips_shared_h */
337