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_x64_LIR_x64_h 8 #define jit_x64_LIR_x64_h 9 10 namespace js { 11 namespace jit { 12 13 // Given an untyped input, guards on whether it's a specific type and returns 14 // the unboxed payload. 15 class LUnboxBase : public LInstructionHelper<1, 1, 0> { 16 public: LUnboxBase(LNode::Opcode op,const LAllocation & input)17 LUnboxBase(LNode::Opcode op, const LAllocation& input) 18 : LInstructionHelper<1, 1, 0>(op) { 19 setOperand(0, input); 20 } 21 22 static const size_t Input = 0; 23 mir()24 MUnbox* mir() const { return mir_->toUnbox(); } 25 }; 26 27 class LUnbox : public LUnboxBase { 28 public: LIR_HEADER(Unbox)29 LIR_HEADER(Unbox) 30 31 explicit LUnbox(const LAllocation& input) : LUnboxBase(classOpcode, input) {} 32 extraName()33 const char* extraName() const { return StringFromMIRType(mir()->type()); } 34 }; 35 36 class LUnboxFloatingPoint : public LUnboxBase { 37 MIRType type_; 38 39 public: LIR_HEADER(UnboxFloatingPoint)40 LIR_HEADER(UnboxFloatingPoint) 41 42 LUnboxFloatingPoint(const LAllocation& input, MIRType type) 43 : LUnboxBase(classOpcode, input), type_(type) {} 44 type()45 MIRType type() const { return type_; } extraName()46 const char* extraName() const { return StringFromMIRType(type_); } 47 }; 48 49 // Convert a 32-bit unsigned integer to a double. 50 class LWasmUint32ToDouble : public LInstructionHelper<1, 1, 0> { 51 public: LIR_HEADER(WasmUint32ToDouble)52 LIR_HEADER(WasmUint32ToDouble) 53 54 explicit LWasmUint32ToDouble(const LAllocation& input) 55 : LInstructionHelper(classOpcode) { 56 setOperand(0, input); 57 } 58 }; 59 60 // Convert a 32-bit unsigned integer to a float32. 61 class LWasmUint32ToFloat32 : public LInstructionHelper<1, 1, 0> { 62 public: LIR_HEADER(WasmUint32ToFloat32)63 LIR_HEADER(WasmUint32ToFloat32) 64 65 explicit LWasmUint32ToFloat32(const LAllocation& input) 66 : LInstructionHelper(classOpcode) { 67 setOperand(0, input); 68 } 69 }; 70 71 class LDivOrModI64 : public LBinaryMath<1> { 72 public: LIR_HEADER(DivOrModI64)73 LIR_HEADER(DivOrModI64) 74 75 LDivOrModI64(const LAllocation& lhs, const LAllocation& rhs, 76 const LDefinition& temp) 77 : LBinaryMath(classOpcode) { 78 setOperand(0, lhs); 79 setOperand(1, rhs); 80 setTemp(0, temp); 81 } 82 remainder()83 const LDefinition* remainder() { return getTemp(0); } 84 mir()85 MBinaryArithInstruction* mir() const { 86 MOZ_ASSERT(mir_->isDiv() || mir_->isMod()); 87 return static_cast<MBinaryArithInstruction*>(mir_); 88 } canBeDivideByZero()89 bool canBeDivideByZero() const { 90 if (mir_->isMod()) { 91 return mir_->toMod()->canBeDivideByZero(); 92 } 93 return mir_->toDiv()->canBeDivideByZero(); 94 } canBeNegativeOverflow()95 bool canBeNegativeOverflow() const { 96 if (mir_->isMod()) { 97 return mir_->toMod()->canBeNegativeDividend(); 98 } 99 return mir_->toDiv()->canBeNegativeOverflow(); 100 } bytecodeOffset()101 wasm::BytecodeOffset bytecodeOffset() const { 102 MOZ_ASSERT(mir_->isDiv() || mir_->isMod()); 103 if (mir_->isMod()) { 104 return mir_->toMod()->bytecodeOffset(); 105 } 106 return mir_->toDiv()->bytecodeOffset(); 107 } 108 }; 109 110 // This class performs a simple x86 'div', yielding either a quotient or 111 // remainder depending on whether this instruction is defined to output 112 // rax (quotient) or rdx (remainder). 113 class LUDivOrModI64 : public LBinaryMath<1> { 114 public: 115 LIR_HEADER(UDivOrModI64); 116 LUDivOrModI64(const LAllocation & lhs,const LAllocation & rhs,const LDefinition & temp)117 LUDivOrModI64(const LAllocation& lhs, const LAllocation& rhs, 118 const LDefinition& temp) 119 : LBinaryMath(classOpcode) { 120 setOperand(0, lhs); 121 setOperand(1, rhs); 122 setTemp(0, temp); 123 } 124 remainder()125 const LDefinition* remainder() { return getTemp(0); } 126 extraName()127 const char* extraName() const { 128 return mir()->isTruncated() ? "Truncated" : nullptr; 129 } 130 mir()131 MBinaryArithInstruction* mir() const { 132 MOZ_ASSERT(mir_->isDiv() || mir_->isMod()); 133 return static_cast<MBinaryArithInstruction*>(mir_); 134 } 135 canBeDivideByZero()136 bool canBeDivideByZero() const { 137 if (mir_->isMod()) { 138 return mir_->toMod()->canBeDivideByZero(); 139 } 140 return mir_->toDiv()->canBeDivideByZero(); 141 } 142 bytecodeOffset()143 wasm::BytecodeOffset bytecodeOffset() const { 144 MOZ_ASSERT(mir_->isDiv() || mir_->isMod()); 145 if (mir_->isMod()) { 146 return mir_->toMod()->bytecodeOffset(); 147 } 148 return mir_->toDiv()->bytecodeOffset(); 149 } 150 }; 151 152 class LWasmTruncateToInt64 : public LInstructionHelper<1, 1, 1> { 153 public: 154 LIR_HEADER(WasmTruncateToInt64); 155 LWasmTruncateToInt64(const LAllocation & in,const LDefinition & temp)156 LWasmTruncateToInt64(const LAllocation& in, const LDefinition& temp) 157 : LInstructionHelper(classOpcode) { 158 setOperand(0, in); 159 setTemp(0, temp); 160 } 161 mir()162 MWasmTruncateToInt64* mir() const { return mir_->toWasmTruncateToInt64(); } 163 temp()164 const LDefinition* temp() { return getTemp(0); } 165 }; 166 167 } // namespace jit 168 } // namespace js 169 170 #endif /* jit_x64_LIR_x64_h */ 171