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_arm_LIR_arm_h michael@0: #define jit_arm_LIR_arm_h michael@0: michael@0: namespace js { michael@0: namespace jit { michael@0: michael@0: class LBox : public LInstructionHelper<2, 1, 0> michael@0: { michael@0: MIRType type_; michael@0: michael@0: public: michael@0: LIR_HEADER(Box); michael@0: michael@0: LBox(const LAllocation &in_payload, MIRType type) michael@0: : type_(type) michael@0: { michael@0: setOperand(0, in_payload); michael@0: } michael@0: michael@0: MIRType type() const { michael@0: return type_; michael@0: } michael@0: const char *extraName() const { michael@0: return StringFromMIRType(type_); michael@0: } michael@0: }; michael@0: michael@0: class LBoxFloatingPoint : public LInstructionHelper<2, 1, 1> michael@0: { michael@0: MIRType type_; michael@0: michael@0: public: michael@0: LIR_HEADER(BoxFloatingPoint); michael@0: michael@0: LBoxFloatingPoint(const LAllocation &in, const LDefinition &temp, MIRType type) michael@0: : type_(type) michael@0: { michael@0: setOperand(0, in); michael@0: setTemp(0, temp); michael@0: } michael@0: michael@0: MIRType type() const { michael@0: return type_; michael@0: } michael@0: const char *extraName() const { michael@0: return StringFromMIRType(type_); michael@0: } michael@0: }; michael@0: michael@0: class LUnbox : public LInstructionHelper<1, 2, 0> michael@0: { michael@0: public: michael@0: LIR_HEADER(Unbox); michael@0: michael@0: MUnbox *mir() const { michael@0: return mir_->toUnbox(); michael@0: } michael@0: const LAllocation *payload() { michael@0: return getOperand(0); michael@0: } michael@0: const LAllocation *type() { michael@0: return getOperand(1); michael@0: } michael@0: const char *extraName() const { michael@0: return StringFromMIRType(mir()->type()); michael@0: } michael@0: }; michael@0: michael@0: class LUnboxFloatingPoint : public LInstructionHelper<1, 2, 0> michael@0: { michael@0: MIRType type_; michael@0: michael@0: public: michael@0: LIR_HEADER(UnboxFloatingPoint); michael@0: michael@0: static const size_t Input = 0; michael@0: michael@0: LUnboxFloatingPoint(MIRType type) michael@0: : type_(type) michael@0: { } michael@0: michael@0: MUnbox *mir() const { michael@0: return mir_->toUnbox(); michael@0: } michael@0: michael@0: MIRType type() const { michael@0: return type_; michael@0: } michael@0: const char *extraName() const { michael@0: return StringFromMIRType(type_); michael@0: } michael@0: }; michael@0: michael@0: // Convert a 32-bit unsigned integer to a double. michael@0: class LAsmJSUInt32ToDouble : public LInstructionHelper<1, 1, 0> michael@0: { michael@0: public: michael@0: LIR_HEADER(AsmJSUInt32ToDouble) michael@0: michael@0: LAsmJSUInt32ToDouble(const LAllocation &input) { michael@0: setOperand(0, input); michael@0: } michael@0: }; michael@0: michael@0: // Convert a 32-bit unsigned integer to a float32. michael@0: class LAsmJSUInt32ToFloat32 : public LInstructionHelper<1, 1, 0> michael@0: { michael@0: public: michael@0: LIR_HEADER(AsmJSUInt32ToFloat32) michael@0: michael@0: LAsmJSUInt32ToFloat32(const LAllocation &input) { michael@0: setOperand(0, input); michael@0: } michael@0: }; 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, michael@0: const LDefinition &temp) { michael@0: setOperand(0, lhs); michael@0: setOperand(1, rhs); michael@0: setTemp(0, temp); michael@0: } michael@0: michael@0: MDiv *mir() const { michael@0: return mir_->toDiv(); michael@0: } michael@0: }; michael@0: michael@0: // LSoftDivI is a software divide for ARM cores that don't support a hardware michael@0: // divide instruction. michael@0: // michael@0: // It is implemented as a proper C function so it trashes r0, r1, r2 and r3. michael@0: // The call also trashes lr, and has the ability to trash ip. The function also michael@0: // takes two arguments (dividend in r0, divisor in r1). The LInstruction gets michael@0: // encoded such that the divisor and dividend are passed in their apropriate michael@0: // registers and end their life at the start of the instruction by the use of michael@0: // useFixedAtStart. The result is returned in r0 and the other three registers michael@0: // that can be trashed are marked as temps. For the time being, the link michael@0: // register is not marked as trashed because we never allocate to the link michael@0: // register. The FP registers are not trashed. michael@0: class LSoftDivI : public LBinaryMath<3> michael@0: { michael@0: public: michael@0: LIR_HEADER(SoftDivI); michael@0: michael@0: LSoftDivI(const LAllocation &lhs, const LAllocation &rhs, michael@0: const LDefinition &temp1, const LDefinition &temp2, const LDefinition &temp3) { michael@0: setOperand(0, lhs); michael@0: setOperand(1, rhs); michael@0: setTemp(0, temp1); michael@0: setTemp(1, temp2); michael@0: setTemp(2, temp3); michael@0: } michael@0: michael@0: MDiv *mir() const { michael@0: return mir_->toDiv(); michael@0: } michael@0: }; michael@0: michael@0: class LDivPowTwoI : public LInstructionHelper<1, 1, 0> michael@0: { michael@0: const int32_t shift_; michael@0: michael@0: public: michael@0: LIR_HEADER(DivPowTwoI) michael@0: michael@0: LDivPowTwoI(const LAllocation &lhs, int32_t shift) michael@0: : shift_(shift) michael@0: { michael@0: setOperand(0, lhs); michael@0: } michael@0: michael@0: const LAllocation *numerator() { michael@0: return getOperand(0); michael@0: } michael@0: michael@0: int32_t shift() { michael@0: return shift_; michael@0: } michael@0: michael@0: MDiv *mir() const { michael@0: return mir_->toDiv(); 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, michael@0: const LDefinition &callTemp) michael@0: { michael@0: setOperand(0, lhs); michael@0: setOperand(1, rhs); michael@0: setTemp(0, callTemp); michael@0: } michael@0: michael@0: const LDefinition *callTemp() { michael@0: return getTemp(0); michael@0: } michael@0: michael@0: MMod *mir() const { michael@0: return mir_->toMod(); michael@0: } michael@0: }; michael@0: michael@0: class LSoftModI : public LBinaryMath<4> michael@0: { michael@0: public: michael@0: LIR_HEADER(SoftModI); michael@0: michael@0: LSoftModI(const LAllocation &lhs, const LAllocation &rhs, michael@0: const LDefinition &temp1, const LDefinition &temp2, const LDefinition &temp3, michael@0: const LDefinition &callTemp) michael@0: { michael@0: setOperand(0, lhs); michael@0: setOperand(1, rhs); michael@0: setTemp(0, temp1); michael@0: setTemp(1, temp2); michael@0: setTemp(2, temp3); michael@0: setTemp(3, callTemp); michael@0: } michael@0: michael@0: const LDefinition *callTemp() { michael@0: return getTemp(3); michael@0: } michael@0: michael@0: MMod *mir() const { michael@0: return mir_->toMod(); 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: int32_t shift() michael@0: { michael@0: return shift_; michael@0: } 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: MMod *mir() const { michael@0: return mir_->toMod(); michael@0: } michael@0: }; michael@0: michael@0: class LModMaskI : public LInstructionHelper<1, 1, 2> michael@0: { michael@0: const int32_t shift_; michael@0: michael@0: public: michael@0: LIR_HEADER(ModMaskI); michael@0: michael@0: LModMaskI(const LAllocation &lhs, const LDefinition &temp1, const LDefinition &temp2, michael@0: int32_t shift) michael@0: : shift_(shift) michael@0: { michael@0: setOperand(0, lhs); michael@0: setTemp(0, temp1); michael@0: setTemp(1, temp2); michael@0: } michael@0: michael@0: int32_t shift() const { michael@0: return shift_; michael@0: } michael@0: michael@0: MMod *mir() const { michael@0: return mir_->toMod(); michael@0: } michael@0: }; michael@0: 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: }; michael@0: michael@0: // Takes a tableswitch with an integer to decide michael@0: class LTableSwitch : public LInstructionHelper<0, 1, 1> michael@0: { michael@0: public: michael@0: LIR_HEADER(TableSwitch); michael@0: michael@0: LTableSwitch(const LAllocation &in, const LDefinition &inputCopy, MTableSwitch *ins) { michael@0: setOperand(0, in); michael@0: setTemp(0, inputCopy); 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: // This is added to share the same CodeGenerator prefixes. michael@0: const LDefinition *tempPointer() { michael@0: return nullptr; michael@0: } michael@0: }; michael@0: michael@0: // Takes a tableswitch with an integer to decide michael@0: class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 2> michael@0: { michael@0: public: michael@0: LIR_HEADER(TableSwitchV); michael@0: michael@0: LTableSwitchV(const LDefinition &inputCopy, const LDefinition &floatCopy, michael@0: MTableSwitch *ins) michael@0: { michael@0: setTemp(0, inputCopy); michael@0: setTemp(1, floatCopy); 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 nullptr; michael@0: } michael@0: }; michael@0: michael@0: class LGuardShape : public LInstructionHelper<0, 1, 1> michael@0: { michael@0: public: michael@0: LIR_HEADER(GuardShape); michael@0: michael@0: LGuardShape(const LAllocation &in, const LDefinition &temp) { michael@0: setOperand(0, in); michael@0: setTemp(0, temp); michael@0: } michael@0: const MGuardShape *mir() const { michael@0: return mir_->toGuardShape(); michael@0: } michael@0: const LDefinition *tempInt() { michael@0: return getTemp(0); michael@0: } michael@0: }; michael@0: michael@0: class LGuardObjectType : public LInstructionHelper<0, 1, 1> michael@0: { michael@0: public: michael@0: LIR_HEADER(GuardObjectType); michael@0: michael@0: LGuardObjectType(const LAllocation &in, const LDefinition &temp) { michael@0: setOperand(0, in); michael@0: setTemp(0, temp); michael@0: } michael@0: const MGuardObjectType *mir() const { michael@0: return mir_->toGuardObjectType(); michael@0: } michael@0: const LDefinition *tempInt() { michael@0: return getTemp(0); 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> michael@0: { michael@0: public: michael@0: LIR_HEADER(MulI); michael@0: michael@0: MMul *mir() { michael@0: return mir_->toMul(); michael@0: } michael@0: }; michael@0: michael@0: class LUDiv : public LBinaryMath<0> michael@0: { michael@0: public: michael@0: LIR_HEADER(UDiv); michael@0: michael@0: MDiv *mir() { michael@0: return mir_->toDiv(); michael@0: } michael@0: }; michael@0: michael@0: class LUMod : public LBinaryMath<0> michael@0: { michael@0: public: michael@0: LIR_HEADER(UMod); michael@0: michael@0: MMod *mir() { 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 LSoftUDivOrMod : public LBinaryMath<3> michael@0: { michael@0: public: michael@0: LIR_HEADER(SoftUDivOrMod); michael@0: michael@0: LSoftUDivOrMod(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp1, michael@0: const LDefinition &temp2, const LDefinition &temp3) { michael@0: setOperand(0, lhs); michael@0: setOperand(1, rhs); michael@0: setTemp(0, temp1); michael@0: setTemp(1, temp2); michael@0: setTemp(2, temp3); michael@0: } michael@0: }; michael@0: michael@0: class LAsmJSLoadFuncPtr : public LInstructionHelper<1, 1, 1> michael@0: { michael@0: public: michael@0: LIR_HEADER(AsmJSLoadFuncPtr); michael@0: LAsmJSLoadFuncPtr(const LAllocation &index, const LDefinition &temp) { michael@0: setOperand(0, index); michael@0: setTemp(0, temp); michael@0: } michael@0: const MAsmJSLoadFuncPtr *mir() const { michael@0: return mir_->toAsmJSLoadFuncPtr(); michael@0: } michael@0: const LAllocation *index() { michael@0: return getOperand(0); michael@0: } michael@0: const LDefinition *temp() { michael@0: return getTemp(0); michael@0: } michael@0: }; michael@0: michael@0: } // namespace jit michael@0: } // namespace js michael@0: michael@0: #endif /* jit_arm_LIR_arm_h */