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