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_x86_shared_LIR_x86_shared_h 8 #define jit_x86_shared_LIR_x86_shared_h 9 10 namespace js { 11 namespace jit { 12 13 class LDivI : public LBinaryMath<1> { 14 public: LIR_HEADER(DivI)15 LIR_HEADER(DivI) 16 17 LDivI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp) 18 : LBinaryMath(classOpcode) { 19 setOperand(0, lhs); 20 setOperand(1, rhs); 21 setTemp(0, temp); 22 } 23 extraName()24 const char* extraName() const { 25 if (mir()->isTruncated()) { 26 if (mir()->canBeNegativeZero()) { 27 return mir()->canBeNegativeOverflow() 28 ? "Truncate_NegativeZero_NegativeOverflow" 29 : "Truncate_NegativeZero"; 30 } 31 return mir()->canBeNegativeOverflow() ? "Truncate_NegativeOverflow" 32 : "Truncate"; 33 } 34 if (mir()->canBeNegativeZero()) { 35 return mir()->canBeNegativeOverflow() ? "NegativeZero_NegativeOverflow" 36 : "NegativeZero"; 37 } 38 return mir()->canBeNegativeOverflow() ? "NegativeOverflow" : nullptr; 39 } 40 remainder()41 const LDefinition* remainder() { return getTemp(0); } mir()42 MDiv* mir() const { return mir_->toDiv(); } 43 }; 44 45 // Signed division by a power-of-two constant. 46 class LDivPowTwoI : public LBinaryMath<0> { 47 const int32_t shift_; 48 const bool negativeDivisor_; 49 50 public: LIR_HEADER(DivPowTwoI)51 LIR_HEADER(DivPowTwoI) 52 53 LDivPowTwoI(const LAllocation& lhs, const LAllocation& lhsCopy, int32_t shift, 54 bool negativeDivisor) 55 : LBinaryMath(classOpcode), 56 shift_(shift), 57 negativeDivisor_(negativeDivisor) { 58 setOperand(0, lhs); 59 setOperand(1, lhsCopy); 60 } 61 numerator()62 const LAllocation* numerator() { return getOperand(0); } numeratorCopy()63 const LAllocation* numeratorCopy() { return getOperand(1); } shift()64 int32_t shift() const { return shift_; } negativeDivisor()65 bool negativeDivisor() const { return negativeDivisor_; } mir()66 MDiv* mir() const { return mir_->toDiv(); } 67 }; 68 69 class LDivOrModConstantI : public LInstructionHelper<1, 1, 1> { 70 const int32_t denominator_; 71 72 public: LIR_HEADER(DivOrModConstantI)73 LIR_HEADER(DivOrModConstantI) 74 75 LDivOrModConstantI(const LAllocation& lhs, int32_t denominator, 76 const LDefinition& temp) 77 : LInstructionHelper(classOpcode), denominator_(denominator) { 78 setOperand(0, lhs); 79 setTemp(0, temp); 80 } 81 numerator()82 const LAllocation* numerator() { return getOperand(0); } denominator()83 int32_t denominator() const { return denominator_; } mir()84 MBinaryArithInstruction* mir() const { 85 MOZ_ASSERT(mir_->isDiv() || mir_->isMod()); 86 return static_cast<MBinaryArithInstruction*>(mir_); 87 } canBeNegativeDividend()88 bool canBeNegativeDividend() const { 89 if (mir_->isMod()) { 90 return mir_->toMod()->canBeNegativeDividend(); 91 } 92 return mir_->toDiv()->canBeNegativeDividend(); 93 } 94 }; 95 96 class LModI : public LBinaryMath<1> { 97 public: LIR_HEADER(ModI)98 LIR_HEADER(ModI) 99 100 LModI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp) 101 : LBinaryMath(classOpcode) { 102 setOperand(0, lhs); 103 setOperand(1, rhs); 104 setTemp(0, temp); 105 } 106 extraName()107 const char* extraName() const { 108 return mir()->isTruncated() ? "Truncated" : nullptr; 109 } 110 remainder()111 const LDefinition* remainder() { return getDef(0); } mir()112 MMod* mir() const { return mir_->toMod(); } 113 }; 114 115 // This class performs a simple x86 'div', yielding either a quotient or 116 // remainder depending on whether this instruction is defined to output eax 117 // (quotient) or edx (remainder). 118 class LUDivOrMod : public LBinaryMath<1> { 119 public: 120 LIR_HEADER(UDivOrMod); 121 LUDivOrMod(const LAllocation & lhs,const LAllocation & rhs,const LDefinition & temp)122 LUDivOrMod(const LAllocation& lhs, const LAllocation& rhs, 123 const LDefinition& temp) 124 : LBinaryMath(classOpcode) { 125 setOperand(0, lhs); 126 setOperand(1, rhs); 127 setTemp(0, temp); 128 } 129 remainder()130 const LDefinition* remainder() { return getTemp(0); } 131 extraName()132 const char* extraName() const { 133 return mir()->isTruncated() ? "Truncated" : nullptr; 134 } 135 mir()136 MBinaryArithInstruction* mir() const { 137 MOZ_ASSERT(mir_->isDiv() || mir_->isMod()); 138 return static_cast<MBinaryArithInstruction*>(mir_); 139 } 140 canBeDivideByZero()141 bool canBeDivideByZero() const { 142 if (mir_->isMod()) { 143 return mir_->toMod()->canBeDivideByZero(); 144 } 145 return mir_->toDiv()->canBeDivideByZero(); 146 } 147 trapOnError()148 bool trapOnError() const { 149 if (mir_->isMod()) { 150 return mir_->toMod()->trapOnError(); 151 } 152 return mir_->toDiv()->trapOnError(); 153 } 154 bytecodeOffset()155 wasm::BytecodeOffset bytecodeOffset() const { 156 if (mir_->isMod()) { 157 return mir_->toMod()->bytecodeOffset(); 158 } 159 return mir_->toDiv()->bytecodeOffset(); 160 } 161 }; 162 163 class LUDivOrModConstant : public LInstructionHelper<1, 1, 1> { 164 const uint32_t denominator_; 165 166 public: LIR_HEADER(UDivOrModConstant)167 LIR_HEADER(UDivOrModConstant) 168 169 LUDivOrModConstant(const LAllocation& lhs, uint32_t denominator, 170 const LDefinition& temp) 171 : LInstructionHelper(classOpcode), denominator_(denominator) { 172 setOperand(0, lhs); 173 setTemp(0, temp); 174 } 175 numerator()176 const LAllocation* numerator() { return getOperand(0); } denominator()177 uint32_t denominator() const { return denominator_; } mir()178 MBinaryArithInstruction* mir() const { 179 MOZ_ASSERT(mir_->isDiv() || mir_->isMod()); 180 return static_cast<MBinaryArithInstruction*>(mir_); 181 } canBeNegativeDividend()182 bool canBeNegativeDividend() const { 183 if (mir_->isMod()) { 184 return mir_->toMod()->canBeNegativeDividend(); 185 } 186 return mir_->toDiv()->canBeNegativeDividend(); 187 } trapOnError()188 bool trapOnError() const { 189 if (mir_->isMod()) { 190 return mir_->toMod()->trapOnError(); 191 } 192 return mir_->toDiv()->trapOnError(); 193 } bytecodeOffset()194 wasm::BytecodeOffset bytecodeOffset() const { 195 if (mir_->isMod()) { 196 return mir_->toMod()->bytecodeOffset(); 197 } 198 return mir_->toDiv()->bytecodeOffset(); 199 } 200 }; 201 202 class LModPowTwoI : public LInstructionHelper<1, 1, 0> { 203 const int32_t shift_; 204 205 public: LIR_HEADER(ModPowTwoI)206 LIR_HEADER(ModPowTwoI) 207 208 LModPowTwoI(const LAllocation& lhs, int32_t shift) 209 : LInstructionHelper(classOpcode), shift_(shift) { 210 setOperand(0, lhs); 211 } 212 shift()213 int32_t shift() const { return shift_; } remainder()214 const LDefinition* remainder() { return getDef(0); } mir()215 MMod* mir() const { return mir_->toMod(); } 216 }; 217 218 // Takes a tableswitch with an integer to decide 219 class LTableSwitch : public LInstructionHelper<0, 1, 2> { 220 public: LIR_HEADER(TableSwitch)221 LIR_HEADER(TableSwitch) 222 223 LTableSwitch(const LAllocation& in, const LDefinition& inputCopy, 224 const LDefinition& jumpTablePointer, MTableSwitch* ins) 225 : LInstructionHelper(classOpcode) { 226 setOperand(0, in); 227 setTemp(0, inputCopy); 228 setTemp(1, jumpTablePointer); 229 setMir(ins); 230 } 231 mir()232 MTableSwitch* mir() const { return mir_->toTableSwitch(); } 233 index()234 const LAllocation* index() { return getOperand(0); } tempInt()235 const LDefinition* tempInt() { return getTemp(0); } tempPointer()236 const LDefinition* tempPointer() { return getTemp(1); } 237 }; 238 239 // Takes a tableswitch with a value to decide 240 class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 3> { 241 public: LIR_HEADER(TableSwitchV)242 LIR_HEADER(TableSwitchV) 243 244 LTableSwitchV(const LBoxAllocation& input, const LDefinition& inputCopy, 245 const LDefinition& floatCopy, 246 const LDefinition& jumpTablePointer, MTableSwitch* ins) 247 : LInstructionHelper(classOpcode) { 248 setBoxOperand(InputValue, input); 249 setTemp(0, inputCopy); 250 setTemp(1, floatCopy); 251 setTemp(2, jumpTablePointer); 252 setMir(ins); 253 } 254 mir()255 MTableSwitch* mir() const { return mir_->toTableSwitch(); } 256 257 static const size_t InputValue = 0; 258 tempInt()259 const LDefinition* tempInt() { return getTemp(0); } tempFloat()260 const LDefinition* tempFloat() { return getTemp(1); } tempPointer()261 const LDefinition* tempPointer() { return getTemp(2); } 262 }; 263 264 class LMulI : public LBinaryMath<0, 1> { 265 public: LIR_HEADER(MulI)266 LIR_HEADER(MulI) 267 268 LMulI(const LAllocation& lhs, const LAllocation& rhs, 269 const LAllocation& lhsCopy) 270 : LBinaryMath(classOpcode) { 271 setOperand(0, lhs); 272 setOperand(1, rhs); 273 setOperand(2, lhsCopy); 274 } 275 extraName()276 const char* extraName() const { 277 return (mir()->mode() == MMul::Integer) 278 ? "Integer" 279 : (mir()->canBeNegativeZero() ? "CanBeNegativeZero" : nullptr); 280 } 281 mir()282 MMul* mir() const { return mir_->toMul(); } lhsCopy()283 const LAllocation* lhsCopy() { return this->getOperand(2); } 284 }; 285 286 class LInt64ToFloatingPoint : public LInstructionHelper<1, INT64_PIECES, 1> { 287 public: 288 LIR_HEADER(Int64ToFloatingPoint); 289 LInt64ToFloatingPoint(const LInt64Allocation & in,const LDefinition & temp)290 LInt64ToFloatingPoint(const LInt64Allocation& in, const LDefinition& temp) 291 : LInstructionHelper(classOpcode) { 292 setInt64Operand(0, in); 293 setTemp(0, temp); 294 } 295 mir()296 MInt64ToFloatingPoint* mir() const { return mir_->toInt64ToFloatingPoint(); } 297 temp()298 const LDefinition* temp() { return getTemp(0); } 299 }; 300 301 } // namespace jit 302 } // namespace js 303 304 #endif /* jit_x86_shared_LIR_x86_shared_h */ 305