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