MacroAssembler-mips-shared.h (10268B)
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_MacroAssembler_mips_shared_h 8 #define jit_mips_shared_MacroAssembler_mips_shared_h 9 10 #include "jit/AtomicOp.h" 11 #include "jit/mips64/Assembler-mips64.h" 12 13 namespace js { 14 namespace jit { 15 16 enum LoadStoreSize { 17 SizeByte = 8, 18 SizeHalfWord = 16, 19 SizeWord = 32, 20 SizeDouble = 64 21 }; 22 23 enum LoadStoreExtension { ZeroExtend = 0, SignExtend = 1 }; 24 25 enum JumpKind { LongJump = 0, ShortJump = 1 }; 26 27 enum DelaySlotFill { DontFillDelaySlot = 0, FillDelaySlot = 1 }; 28 29 static constexpr Register CallReg = t9; 30 31 class MacroAssemblerMIPSShared : public Assembler { 32 protected: 33 // Perform a downcast. Should be removed by Bug 996602. 34 MacroAssembler& asMasm(); 35 const MacroAssembler& asMasm() const; 36 37 Condition ma_cmp(Register rd, Register lhs, Register rhs, Condition c); 38 Condition ma_cmp(Register rd, Register lhs, Imm32 imm, Condition c); 39 40 void compareFloatingPoint(FloatFormat fmt, FloatRegister lhs, 41 FloatRegister rhs, DoubleCondition c, 42 FloatTestKind* testKind, FPConditionBit fcc = FCC0); 43 44 public: 45 void ma_move(Register rd, Register rs); 46 47 void ma_li(Register dest, ImmGCPtr ptr); 48 49 void ma_li(Register dest, Imm32 imm); 50 void ma_liPatchable(Register dest, Imm32 imm); 51 52 // Shift operations 53 void ma_sll(Register rd, Register rt, Imm32 shift); 54 void ma_srl(Register rd, Register rt, Imm32 shift); 55 void ma_sra(Register rd, Register rt, Imm32 shift); 56 void ma_ror(Register rd, Register rt, Imm32 shift); 57 void ma_rol(Register rd, Register rt, Imm32 shift); 58 59 void ma_sll(Register rd, Register rt, Register shift); 60 void ma_srl(Register rd, Register rt, Register shift); 61 void ma_sra(Register rd, Register rt, Register shift); 62 void ma_ror(Register rd, Register rt, Register shift); 63 void ma_rol(Register rd, Register rt, Register shift); 64 65 // Negate 66 void ma_negu(Register rd, Register rs); 67 68 void ma_not(Register rd, Register rs); 69 70 // Bit extract/insert 71 void ma_ext(Register rt, Register rs, uint16_t pos, uint16_t size); 72 void ma_ins(Register rt, Register rs, uint16_t pos, uint16_t size); 73 74 // Sign extend 75 void ma_seb(Register rd, Register rt); 76 void ma_seh(Register rd, Register rt); 77 78 // and 79 void ma_and(Register rd, Register rs); 80 void ma_and(Register rd, Imm32 imm); 81 void ma_and(Register rd, Register rs, Imm32 imm); 82 83 // or 84 void ma_or(Register rd, Register rs); 85 void ma_or(Register rd, Imm32 imm); 86 void ma_or(Register rd, Register rs, Imm32 imm); 87 88 // xor 89 void ma_xor(Register rd, Register rs); 90 void ma_xor(Register rd, Imm32 imm); 91 void ma_xor(Register rd, Register rs, Imm32 imm); 92 93 // word swap byte within halfwords 94 void ma_wsbh(Register rd, Register rt); 95 96 void ma_ctz(Register rd, Register rs); 97 98 // load 99 FaultingCodeOffset ma_load(Register dest, const BaseIndex& src, 100 LoadStoreSize size = SizeWord, 101 LoadStoreExtension extension = SignExtend); 102 void ma_load_unaligned(Register dest, const BaseIndex& src, 103 LoadStoreSize size = SizeWord, 104 LoadStoreExtension extension = SignExtend); 105 void ma_load_unaligned(Register dest, const Address& address, 106 LoadStoreSize size = SizeWord, 107 LoadStoreExtension extension = SignExtend); 108 void ma_load_unaligned(const wasm::MemoryAccessDesc& access, Register dest, 109 const BaseIndex& src, Register temp, 110 LoadStoreSize size, LoadStoreExtension extension); 111 112 // store 113 FaultingCodeOffset ma_store(Register data, const BaseIndex& dest, 114 LoadStoreSize size = SizeWord, 115 LoadStoreExtension extension = SignExtend); 116 void ma_store(Imm32 imm, const BaseIndex& dest, LoadStoreSize size = SizeWord, 117 LoadStoreExtension extension = SignExtend); 118 void ma_store_unaligned(Register data, const Address& dest, 119 LoadStoreSize size = SizeWord); 120 void ma_store_unaligned(Register data, const BaseIndex& dest, 121 LoadStoreSize size = SizeWord); 122 void ma_store_unaligned(const wasm::MemoryAccessDesc& access, Register data, 123 const BaseIndex& dest, Register temp, 124 LoadStoreSize size, LoadStoreExtension extension); 125 126 // arithmetic based ops 127 // add 128 void ma_addu(Register rd, Register rs, Imm32 imm); 129 void ma_addu(Register rd, Register rs); 130 void ma_addu(Register rd, Imm32 imm); 131 void ma_add32TestCarry(Condition cond, Register rd, Register rs, Register rt, 132 Label* overflow); 133 void ma_add32TestCarry(Condition cond, Register rd, Register rs, Imm32 imm, 134 Label* overflow); 135 136 // subtract 137 void ma_subu(Register rd, Register rs, Imm32 imm); 138 void ma_subu(Register rd, Register rs); 139 void ma_subu(Register rd, Imm32 imm); 140 void ma_sub32TestOverflow(Register rd, Register rs, Imm32 imm, 141 Label* overflow); 142 143 // multiplies. For now, there are only few that we care about. 144 void ma_mul(Register rd, Register rs, Imm32 imm); 145 void ma_mul32TestOverflow(Register rd, Register rs, Register rt, 146 Label* overflow); 147 void ma_mul32TestOverflow(Register rd, Register rs, Imm32 imm, 148 Label* overflow); 149 150 // fast mod, uses scratch registers, and thus needs to be in the assembler 151 // implicitly assumes that we can overwrite dest at the beginning of the 152 // sequence 153 void ma_mod_mask(Register src, Register dest, Register hold, Register remain, 154 int32_t shift, Label* negZero = nullptr); 155 156 // branches when done from within mips-specific code 157 void ma_b(Register lhs, Register rhs, Label* l, Condition c, 158 JumpKind jumpKind = LongJump); 159 void ma_b(Register lhs, Imm32 imm, Label* l, Condition c, 160 JumpKind jumpKind = LongJump); 161 void ma_b(Register lhs, ImmPtr imm, Label* l, Condition c, 162 JumpKind jumpKind = LongJump); 163 void ma_b(Register lhs, ImmGCPtr imm, Label* l, Condition c, 164 JumpKind jumpKind = LongJump) { 165 UseScratchRegisterScope temps(*this); 166 Register scratch = temps.Acquire(); 167 MOZ_ASSERT(lhs != scratch); 168 ma_li(scratch, imm); 169 ma_b(lhs, scratch, l, c, jumpKind); 170 } 171 172 void ma_b(Label* l, JumpKind jumpKind = LongJump); 173 174 // fp instructions 175 void ma_lis(FloatRegister dest, float value); 176 177 FaultingCodeOffset ma_sd(FloatRegister src, BaseIndex address); 178 FaultingCodeOffset ma_ss(FloatRegister src, BaseIndex address); 179 180 FaultingCodeOffset ma_ld(FloatRegister dest, const BaseIndex& src); 181 FaultingCodeOffset ma_ls(FloatRegister dest, const BaseIndex& src); 182 183 // FP branches 184 void ma_bc1s(FloatRegister lhs, FloatRegister rhs, Label* label, 185 DoubleCondition c, JumpKind jumpKind = LongJump, 186 FPConditionBit fcc = FCC0); 187 void ma_bc1d(FloatRegister lhs, FloatRegister rhs, Label* label, 188 DoubleCondition c, JumpKind jumpKind = LongJump, 189 FPConditionBit fcc = FCC0); 190 191 void ma_call(ImmPtr dest); 192 193 void ma_jump(ImmPtr dest); 194 195 void ma_cmp_set(Register dst, Register lhs, Register rhs, Condition c); 196 void ma_cmp_set(Register dst, Register lhs, Imm32 imm, Condition c); 197 // void ma_cmp_set(Register dst, Address address, Imm32 imm, Condition c); 198 void ma_cmp_set_double(Register dst, FloatRegister lhs, FloatRegister rhs, 199 DoubleCondition c); 200 void ma_cmp_set_float32(Register dst, FloatRegister lhs, FloatRegister rhs, 201 DoubleCondition c); 202 203 void moveToFloat32(Register src, FloatRegister dest) { as_mtc1(src, dest); } 204 void moveFromFloat32(FloatRegister src, Register dest) { as_mfc1(dest, src); } 205 206 void minMax32(Register lhs, Register rhs, Register dest, bool isMax); 207 void minMax32(Register lhs, Imm32 rhs, Register dest, bool isMax); 208 209 void minMaxPtr(Register lhs, Register rhs, Register dest, bool isMax); 210 void minMaxPtr(Register lhs, ImmWord rhs, Register dest, bool isMax); 211 212 // Evaluate srcDest = minmax<isMax>{Float32,Double}(srcDest, other). 213 // Handle NaN specially if handleNaN is true. 214 void minMaxDouble(FloatRegister srcDest, FloatRegister other, bool handleNaN, 215 bool isMax); 216 void minMaxFloat32(FloatRegister srcDest, FloatRegister other, bool handleNaN, 217 bool isMax); 218 219 FaultingCodeOffset loadDouble(const Address& addr, FloatRegister dest); 220 FaultingCodeOffset loadDouble(const BaseIndex& src, FloatRegister dest); 221 222 FaultingCodeOffset loadFloat32(const Address& addr, FloatRegister dest); 223 FaultingCodeOffset loadFloat32(const BaseIndex& src, FloatRegister dest); 224 225 FaultingCodeOffset loadFloat16(const Address& addr, FloatRegister dest, 226 Register) { 227 MOZ_CRASH("Not supported for this target"); 228 } 229 FaultingCodeOffset loadFloat16(const BaseIndex& src, FloatRegister dest, 230 Register) { 231 MOZ_CRASH("Not supported for this target"); 232 } 233 234 void outOfLineWasmTruncateToInt32Check( 235 FloatRegister input, Register output, MIRType fromType, TruncFlags flags, 236 Label* rejoin, const wasm::TrapSiteDesc& trapSiteDesc); 237 void outOfLineWasmTruncateToInt64Check( 238 FloatRegister input, Register64 output, MIRType fromType, 239 TruncFlags flags, Label* rejoin, const wasm::TrapSiteDesc& trapSiteDesc); 240 241 protected: 242 void wasmLoadImpl(const wasm::MemoryAccessDesc& access, Register memoryBase, 243 Register ptr, Register ptrScratch, AnyRegister output, 244 Register tmp); 245 void wasmStoreImpl(const wasm::MemoryAccessDesc& access, AnyRegister value, 246 Register memoryBase, Register ptr, Register ptrScratch, 247 Register tmp); 248 }; 249 250 } // namespace jit 251 } // namespace js 252 253 #endif /* jit_mips_shared_MacroAssembler_mips_shared_h */