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