michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef jit_shared_LIR_x86_shared_h michael@0: #define jit_shared_LIR_x86_shared_h michael@0: michael@0: namespace js { michael@0: namespace jit { michael@0: michael@0: class LDivI : public LBinaryMath<1> michael@0: { michael@0: public: michael@0: LIR_HEADER(DivI) michael@0: michael@0: LDivI(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp) { michael@0: setOperand(0, lhs); michael@0: setOperand(1, rhs); michael@0: setTemp(0, temp); michael@0: } michael@0: michael@0: const char *extraName() const { michael@0: if (mir()->isTruncated()) { michael@0: if (mir()->canBeNegativeZero()) { michael@0: return mir()->canBeNegativeOverflow() michael@0: ? "Truncate_NegativeZero_NegativeOverflow" michael@0: : "Truncate_NegativeZero"; michael@0: } michael@0: return mir()->canBeNegativeOverflow() ? "Truncate_NegativeOverflow" : "Truncate"; michael@0: } michael@0: if (mir()->canBeNegativeZero()) michael@0: return mir()->canBeNegativeOverflow() ? "NegativeZero_NegativeOverflow" : "NegativeZero"; michael@0: return mir()->canBeNegativeOverflow() ? "NegativeOverflow" : nullptr; michael@0: } michael@0: michael@0: const LDefinition *remainder() { michael@0: return getTemp(0); michael@0: } michael@0: MDiv *mir() const { michael@0: return mir_->toDiv(); michael@0: } michael@0: }; michael@0: michael@0: // Signed division by a power-of-two constant. michael@0: class LDivPowTwoI : public LBinaryMath<0> michael@0: { michael@0: const int32_t shift_; michael@0: const bool negativeDivisor_; michael@0: michael@0: public: michael@0: LIR_HEADER(DivPowTwoI) michael@0: michael@0: LDivPowTwoI(const LAllocation &lhs, const LAllocation &lhsCopy, int32_t shift, bool negativeDivisor) michael@0: : shift_(shift), negativeDivisor_(negativeDivisor) michael@0: { michael@0: setOperand(0, lhs); michael@0: setOperand(1, lhsCopy); michael@0: } michael@0: michael@0: const LAllocation *numerator() { michael@0: return getOperand(0); michael@0: } michael@0: const LAllocation *numeratorCopy() { michael@0: return getOperand(1); michael@0: } michael@0: int32_t shift() const { michael@0: return shift_; michael@0: } michael@0: bool negativeDivisor() const { michael@0: return negativeDivisor_; michael@0: } michael@0: MDiv *mir() const { michael@0: return mir_->toDiv(); michael@0: } michael@0: }; michael@0: michael@0: class LDivOrModConstantI : public LInstructionHelper<1, 1, 1> michael@0: { michael@0: const int32_t denominator_; michael@0: michael@0: public: michael@0: LIR_HEADER(DivOrModConstantI) michael@0: michael@0: LDivOrModConstantI(const LAllocation &lhs, int32_t denominator, const LDefinition& temp) michael@0: : denominator_(denominator) michael@0: { michael@0: setOperand(0, lhs); michael@0: setTemp(0, temp); michael@0: } michael@0: michael@0: const LAllocation *numerator() { michael@0: return getOperand(0); michael@0: } michael@0: int32_t denominator() const { michael@0: return denominator_; michael@0: } michael@0: MBinaryArithInstruction *mir() const { michael@0: JS_ASSERT(mir_->isDiv() || mir_->isMod()); michael@0: return static_cast(mir_); michael@0: } michael@0: bool canBeNegativeDividend() const { michael@0: if (mir_->isMod()) michael@0: return mir_->toMod()->canBeNegativeDividend(); michael@0: return mir_->toDiv()->canBeNegativeDividend(); michael@0: } michael@0: }; michael@0: michael@0: class LModI : public LBinaryMath<1> michael@0: { michael@0: public: michael@0: LIR_HEADER(ModI) michael@0: michael@0: LModI(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp) { michael@0: setOperand(0, lhs); michael@0: setOperand(1, rhs); michael@0: setTemp(0, temp); michael@0: } michael@0: michael@0: const char *extraName() const { michael@0: return mir()->isTruncated() ? "Truncated" : nullptr; michael@0: } michael@0: michael@0: const LDefinition *remainder() { michael@0: return getDef(0); michael@0: } michael@0: MMod *mir() const { michael@0: return mir_->toMod(); michael@0: } michael@0: }; michael@0: michael@0: // This class performs a simple x86 'div', yielding either a quotient or remainder depending on michael@0: // whether this instruction is defined to output eax (quotient) or edx (remainder). michael@0: class LUDivOrMod : public LBinaryMath<1> michael@0: { michael@0: public: michael@0: LIR_HEADER(UDivOrMod); michael@0: michael@0: LUDivOrMod(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp) { michael@0: setOperand(0, lhs); michael@0: setOperand(1, rhs); michael@0: setTemp(0, temp); michael@0: } michael@0: michael@0: const LDefinition *remainder() { michael@0: return getTemp(0); michael@0: } michael@0: michael@0: const char *extraName() const { michael@0: return mir()->isTruncated() ? "Truncated" : nullptr; michael@0: } michael@0: michael@0: MBinaryArithInstruction *mir() const { michael@0: JS_ASSERT(mir_->isDiv() || mir_->isMod()); michael@0: return static_cast(mir_); michael@0: } michael@0: michael@0: bool canBeDivideByZero() const { michael@0: if (mir_->isMod()) michael@0: return mir_->toMod()->canBeDivideByZero(); michael@0: return mir_->toDiv()->canBeDivideByZero(); michael@0: } michael@0: }; michael@0: michael@0: class LModPowTwoI : public LInstructionHelper<1,1,0> michael@0: { michael@0: const int32_t shift_; michael@0: michael@0: public: michael@0: LIR_HEADER(ModPowTwoI) michael@0: michael@0: LModPowTwoI(const LAllocation &lhs, int32_t shift) michael@0: : shift_(shift) michael@0: { michael@0: setOperand(0, lhs); michael@0: } michael@0: michael@0: int32_t shift() const { michael@0: return shift_; michael@0: } michael@0: const LDefinition *remainder() { michael@0: return getDef(0); michael@0: } michael@0: MMod *mir() const { michael@0: return mir_->toMod(); michael@0: } michael@0: }; michael@0: michael@0: // Double raised to a half power. michael@0: class LPowHalfD : public LInstructionHelper<1, 1, 0> michael@0: { michael@0: public: michael@0: LIR_HEADER(PowHalfD) michael@0: LPowHalfD(const LAllocation &input) { michael@0: setOperand(0, input); michael@0: } michael@0: michael@0: const LAllocation *input() { michael@0: return getOperand(0); michael@0: } michael@0: const LDefinition *output() { michael@0: return getDef(0); michael@0: } michael@0: MPowHalf *mir() const { michael@0: return mir_->toPowHalf(); michael@0: } michael@0: }; michael@0: michael@0: // Takes a tableswitch with an integer to decide michael@0: class LTableSwitch : public LInstructionHelper<0, 1, 2> michael@0: { michael@0: public: michael@0: LIR_HEADER(TableSwitch) michael@0: michael@0: LTableSwitch(const LAllocation &in, const LDefinition &inputCopy, michael@0: const LDefinition &jumpTablePointer, MTableSwitch *ins) michael@0: { michael@0: setOperand(0, in); michael@0: setTemp(0, inputCopy); michael@0: setTemp(1, jumpTablePointer); michael@0: setMir(ins); michael@0: } michael@0: michael@0: MTableSwitch *mir() const { michael@0: return mir_->toTableSwitch(); michael@0: } michael@0: michael@0: const LAllocation *index() { michael@0: return getOperand(0); michael@0: } michael@0: const LDefinition *tempInt() { michael@0: return getTemp(0); michael@0: } michael@0: const LDefinition *tempPointer() { michael@0: return getTemp(1); michael@0: } michael@0: }; michael@0: michael@0: // Takes a tableswitch with a value to decide michael@0: class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 3> michael@0: { michael@0: public: michael@0: LIR_HEADER(TableSwitchV) michael@0: michael@0: LTableSwitchV(const LDefinition &inputCopy, const LDefinition &floatCopy, michael@0: const LDefinition &jumpTablePointer, MTableSwitch *ins) michael@0: { michael@0: setTemp(0, inputCopy); michael@0: setTemp(1, floatCopy); michael@0: setTemp(2, jumpTablePointer); michael@0: setMir(ins); michael@0: } michael@0: michael@0: MTableSwitch *mir() const { michael@0: return mir_->toTableSwitch(); michael@0: } michael@0: michael@0: static const size_t InputValue = 0; michael@0: michael@0: const LDefinition *tempInt() { michael@0: return getTemp(0); michael@0: } michael@0: const LDefinition *tempFloat() { michael@0: return getTemp(1); michael@0: } michael@0: const LDefinition *tempPointer() { michael@0: return getTemp(2); michael@0: } michael@0: }; michael@0: michael@0: class LGuardShape : public LInstructionHelper<0, 1, 0> michael@0: { michael@0: public: michael@0: LIR_HEADER(GuardShape) michael@0: michael@0: LGuardShape(const LAllocation &in) { michael@0: setOperand(0, in); michael@0: } michael@0: const MGuardShape *mir() const { michael@0: return mir_->toGuardShape(); michael@0: } michael@0: }; michael@0: michael@0: class LGuardObjectType : public LInstructionHelper<0, 1, 0> michael@0: { michael@0: public: michael@0: LIR_HEADER(GuardObjectType) michael@0: michael@0: LGuardObjectType(const LAllocation &in) { michael@0: setOperand(0, in); michael@0: } michael@0: const MGuardObjectType *mir() const { michael@0: return mir_->toGuardObjectType(); michael@0: } michael@0: }; michael@0: michael@0: class LInterruptCheck : public LInstructionHelper<0, 0, 0> michael@0: { michael@0: public: michael@0: LIR_HEADER(InterruptCheck) michael@0: }; michael@0: michael@0: class LMulI : public LBinaryMath<0, 1> michael@0: { michael@0: public: michael@0: LIR_HEADER(MulI) michael@0: michael@0: LMulI(const LAllocation &lhs, const LAllocation &rhs, const LAllocation &lhsCopy) { michael@0: setOperand(0, lhs); michael@0: setOperand(1, rhs); michael@0: setOperand(2, lhsCopy); michael@0: } michael@0: michael@0: const char *extraName() const { michael@0: return (mir()->mode() == MMul::Integer) michael@0: ? "Integer" michael@0: : (mir()->canBeNegativeZero() ? "CanBeNegativeZero" : nullptr); michael@0: } michael@0: michael@0: MMul *mir() const { michael@0: return mir_->toMul(); michael@0: } michael@0: const LAllocation *lhsCopy() { michael@0: return this->getOperand(2); michael@0: } michael@0: }; michael@0: michael@0: } // namespace jit michael@0: } // namespace js michael@0: michael@0: #endif /* jit_shared_LIR_x86_shared_h */