1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 * vim: set ts=8 sts=4 et sw=4 tw=99: 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_mips32_MacroAssembler_mips32_h 8 #define jit_mips32_MacroAssembler_mips32_h 9 10 #include "jsopcode.h" 11 12 #include "jit/AtomicOp.h" 13 #include "jit/IonCaches.h" 14 #include "jit/JitFrames.h" 15 #include "jit/mips-shared/MacroAssembler-mips-shared.h" 16 #include "jit/MoveResolver.h" 17 18 namespace js { 19 namespace jit { 20 21 struct ImmTag : public Imm32 22 { ImmTagImmTag23 ImmTag(JSValueTag mask) 24 : Imm32(int32_t(mask)) 25 { } 26 }; 27 28 struct ImmType : public ImmTag 29 { ImmTypeImmType30 ImmType(JSValueType type) 31 : ImmTag(JSVAL_TYPE_TO_TAG(type)) 32 { } 33 }; 34 35 static const ValueOperand JSReturnOperand = ValueOperand(JSReturnReg_Type, JSReturnReg_Data); 36 static const ValueOperand softfpReturnOperand = ValueOperand(v1, v0); 37 38 static const int defaultShift = 3; 39 static_assert(1 << defaultShift == sizeof(JS::Value), "The defaultShift is wrong"); 40 41 static const uint32_t LOW_32_MASK = (1LL << 32) - 1; 42 static const int32_t LOW_32_OFFSET = 0; 43 static const int32_t HIGH_32_OFFSET = 4; 44 45 class MacroAssemblerMIPS : public MacroAssemblerMIPSShared 46 { 47 public: 48 using MacroAssemblerMIPSShared::ma_b; 49 using MacroAssemblerMIPSShared::ma_li; 50 using MacroAssemblerMIPSShared::ma_ss; 51 using MacroAssemblerMIPSShared::ma_sd; 52 using MacroAssemblerMIPSShared::ma_load; 53 using MacroAssemblerMIPSShared::ma_store; 54 using MacroAssemblerMIPSShared::ma_cmp_set; 55 using MacroAssemblerMIPSShared::ma_subTestOverflow; 56 57 void ma_li(Register dest, CodeOffset* label); 58 59 void ma_liPatchable(Register dest, Imm32 imm); 60 void ma_li(Register dest, ImmWord imm); 61 void ma_liPatchable(Register dest, ImmPtr imm); 62 void ma_liPatchable(Register dest, ImmWord imm); 63 64 // load 65 void ma_load(Register dest, Address address, LoadStoreSize size = SizeWord, 66 LoadStoreExtension extension = SignExtend); 67 68 // store 69 void ma_store(Register data, Address address, LoadStoreSize size = SizeWord, 70 LoadStoreExtension extension = SignExtend); 71 72 // arithmetic based ops 73 // add 74 void ma_addTestOverflow(Register rd, Register rs, Register rt, Label* overflow); 75 void ma_addTestOverflow(Register rd, Register rs, Imm32 imm, Label* overflow); 76 77 // subtract 78 void ma_subTestOverflow(Register rd, Register rs, Register rt, Label* overflow); 79 80 // memory 81 // shortcut for when we know we're transferring 32 bits of data 82 void ma_lw(Register data, Address address); 83 84 void ma_sw(Register data, Address address); 85 void ma_sw(Imm32 imm, Address address); 86 void ma_sw(Register data, BaseIndex& address); 87 88 void ma_pop(Register r); 89 void ma_push(Register r); 90 91 void branchWithCode(InstImm code, Label* label, JumpKind jumpKind); 92 // branches when done from within mips-specific code 93 void ma_b(Register lhs, ImmWord imm, Label* l, Condition c, JumpKind jumpKind = LongJump) 94 { 95 ma_b(lhs, Imm32(uint32_t(imm.value)), l, c, jumpKind); 96 } 97 void ma_b(Address addr, ImmWord imm, Label* l, Condition c, JumpKind jumpKind = LongJump) 98 { 99 ma_b(addr, Imm32(uint32_t(imm.value)), l, c, jumpKind); 100 } 101 102 void ma_b(Register lhs, Address addr, Label* l, Condition c, JumpKind jumpKind = LongJump); 103 void ma_b(Address addr, Imm32 imm, Label* l, Condition c, JumpKind jumpKind = LongJump); 104 void ma_b(Address addr, ImmGCPtr imm, Label* l, Condition c, JumpKind jumpKind = LongJump); 105 void ma_b(Address addr, Register rhs, Label* l, Condition c, JumpKind jumpKind = LongJump) { 106 MOZ_ASSERT(rhs != ScratchRegister); 107 ma_load(ScratchRegister, addr, SizeWord); 108 ma_b(ScratchRegister, rhs, l, c, jumpKind); 109 } 110 111 void ma_bal(Label* l, DelaySlotFill delaySlotFill = FillDelaySlot); 112 113 // fp instructions 114 void ma_lid(FloatRegister dest, double value); 115 116 void ma_mv(FloatRegister src, ValueOperand dest); 117 void ma_mv(ValueOperand src, FloatRegister dest); 118 119 void ma_ls(FloatRegister fd, Address address); 120 void ma_ld(FloatRegister fd, Address address); 121 void ma_sd(FloatRegister fd, Address address); 122 void ma_ss(FloatRegister fd, Address address); 123 124 void ma_pop(FloatRegister fs); 125 void ma_push(FloatRegister fs); 126 ma_cmp_set(Register dst,Register lhs,ImmPtr imm,Condition c)127 void ma_cmp_set(Register dst, Register lhs, ImmPtr imm, Condition c) { 128 ma_cmp_set(dst, lhs, Imm32(uint32_t(imm.value)), c); 129 } 130 void ma_cmp_set(Register rd, Register rs, Address addr, Condition c); 131 void ma_cmp_set(Register dst, Address lhs, Register rhs, Condition c); ma_cmp_set(Register dst,Address lhs,ImmPtr imm,Condition c)132 void ma_cmp_set(Register dst, Address lhs, ImmPtr imm, Condition c) { 133 ma_lw(ScratchRegister, lhs); 134 ma_li(SecondScratchReg, Imm32(uint32_t(imm.value))); 135 ma_cmp_set(dst, ScratchRegister, SecondScratchReg, c); 136 } 137 138 // These fuctions abstract the access to high part of the double precision 139 // float register. It is intended to work on both 32 bit and 64 bit 140 // floating point coprocessor. 141 // :TODO: (Bug 985881) Modify this for N32 ABI to use mthc1 and mfhc1 moveToDoubleHi(Register src,FloatRegister dest)142 void moveToDoubleHi(Register src, FloatRegister dest) { 143 as_mtc1(src, getOddPair(dest)); 144 } moveFromDoubleHi(FloatRegister src,Register dest)145 void moveFromDoubleHi(FloatRegister src, Register dest) { 146 as_mfc1(dest, getOddPair(src)); 147 } 148 }; 149 150 class MacroAssembler; 151 152 class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS 153 { 154 public: 155 using MacroAssemblerMIPS::call; 156 MacroAssemblerMIPSCompat()157 MacroAssemblerMIPSCompat() 158 { } 159 160 void convertBoolToInt32(Register source, Register dest); 161 void convertInt32ToDouble(Register src, FloatRegister dest); 162 void convertInt32ToDouble(const Address& src, FloatRegister dest); 163 void convertInt32ToDouble(const BaseIndex& src, FloatRegister dest); 164 void convertUInt32ToDouble(Register src, FloatRegister dest); 165 void convertUInt32ToFloat32(Register src, FloatRegister dest); 166 void convertDoubleToFloat32(FloatRegister src, FloatRegister dest); 167 void branchTruncateDouble(FloatRegister src, Register dest, Label* fail); 168 void convertDoubleToInt32(FloatRegister src, Register dest, Label* fail, 169 bool negativeZeroCheck = true); 170 void convertFloat32ToInt32(FloatRegister src, Register dest, Label* fail, 171 bool negativeZeroCheck = true); 172 173 void convertFloat32ToDouble(FloatRegister src, FloatRegister dest); 174 void branchTruncateFloat32(FloatRegister src, Register dest, Label* fail); 175 void convertInt32ToFloat32(Register src, FloatRegister dest); 176 void convertInt32ToFloat32(const Address& src, FloatRegister dest); 177 178 void addDouble(FloatRegister src, FloatRegister dest); 179 void subDouble(FloatRegister src, FloatRegister dest); 180 void mulDouble(FloatRegister src, FloatRegister dest); 181 void divDouble(FloatRegister src, FloatRegister dest); 182 183 void negateDouble(FloatRegister reg); 184 void inc64(AbsoluteAddress dest); 185 186 void computeScaledAddress(const BaseIndex& address, Register dest); 187 computeEffectiveAddress(const Address & address,Register dest)188 void computeEffectiveAddress(const Address& address, Register dest) { 189 ma_addu(dest, address.base, Imm32(address.offset)); 190 } 191 computeEffectiveAddress(const BaseIndex & address,Register dest)192 void computeEffectiveAddress(const BaseIndex& address, Register dest) { 193 computeScaledAddress(address, dest); 194 if (address.offset) { 195 addPtr(Imm32(address.offset), dest); 196 } 197 } 198 j(Label * dest)199 void j(Label* dest) { 200 ma_b(dest); 201 } 202 mov(Register src,Register dest)203 void mov(Register src, Register dest) { 204 as_ori(dest, src, 0); 205 } mov(ImmWord imm,Register dest)206 void mov(ImmWord imm, Register dest) { 207 ma_li(dest, imm); 208 } mov(ImmPtr imm,Register dest)209 void mov(ImmPtr imm, Register dest) { 210 mov(ImmWord(uintptr_t(imm.value)), dest); 211 } mov(Register src,Address dest)212 void mov(Register src, Address dest) { 213 MOZ_CRASH("NYI-IC"); 214 } mov(Address src,Register dest)215 void mov(Address src, Register dest) { 216 MOZ_CRASH("NYI-IC"); 217 } 218 branch(JitCode * c)219 void branch(JitCode* c) { 220 BufferOffset bo = m_buffer.nextOffset(); 221 addPendingJump(bo, ImmPtr(c->raw()), Relocation::JITCODE); 222 ma_liPatchable(ScratchRegister, ImmPtr(c->raw())); 223 as_jr(ScratchRegister); 224 as_nop(); 225 } branch(const Register reg)226 void branch(const Register reg) { 227 as_jr(reg); 228 as_nop(); 229 } nop()230 void nop() { 231 as_nop(); 232 } ret()233 void ret() { 234 ma_pop(ra); 235 as_jr(ra); 236 as_nop(); 237 } retn(Imm32 n)238 void retn(Imm32 n) { 239 // pc <- [sp]; sp += n 240 loadPtr(Address(StackPointer, 0), ra); 241 addPtr(n, StackPointer); 242 as_jr(ra); 243 as_nop(); 244 } push(Imm32 imm)245 void push(Imm32 imm) { 246 ma_li(ScratchRegister, imm); 247 ma_push(ScratchRegister); 248 } push(ImmWord imm)249 void push(ImmWord imm) { 250 ma_li(ScratchRegister, imm); 251 ma_push(ScratchRegister); 252 } push(ImmGCPtr imm)253 void push(ImmGCPtr imm) { 254 ma_li(ScratchRegister, imm); 255 ma_push(ScratchRegister); 256 } push(const Address & address)257 void push(const Address& address) { 258 loadPtr(address, ScratchRegister); 259 ma_push(ScratchRegister); 260 } push(Register reg)261 void push(Register reg) { 262 ma_push(reg); 263 } push(FloatRegister reg)264 void push(FloatRegister reg) { 265 ma_push(reg); 266 } pop(Register reg)267 void pop(Register reg) { 268 ma_pop(reg); 269 } pop(FloatRegister reg)270 void pop(FloatRegister reg) { 271 ma_pop(reg); 272 } 273 274 // Emit a branch that can be toggled to a non-operation. On MIPS we use 275 // "andi" instruction to toggle the branch. 276 // See ToggleToJmp(), ToggleToCmp(). 277 CodeOffset toggledJump(Label* label); 278 279 // Emit a "jalr" or "nop" instruction. ToggleCall can be used to patch 280 // this instruction. 281 CodeOffset toggledCall(JitCode* target, bool enabled); 282 ToggledCallSize(uint8_t * code)283 static size_t ToggledCallSize(uint8_t* code) { 284 // Four instructions used in: MacroAssemblerMIPSCompat::toggledCall 285 return 4 * sizeof(uint32_t); 286 } 287 pushWithPatch(ImmWord imm)288 CodeOffset pushWithPatch(ImmWord imm) { 289 CodeOffset label = movWithPatch(imm, ScratchRegister); 290 ma_push(ScratchRegister); 291 return label; 292 } 293 movWithPatch(ImmWord imm,Register dest)294 CodeOffset movWithPatch(ImmWord imm, Register dest) { 295 CodeOffset label = CodeOffset(currentOffset()); 296 ma_liPatchable(dest, imm); 297 return label; 298 } movWithPatch(ImmPtr imm,Register dest)299 CodeOffset movWithPatch(ImmPtr imm, Register dest) { 300 return movWithPatch(ImmWord(uintptr_t(imm.value)), dest); 301 } 302 jump(Label * label)303 void jump(Label* label) { 304 ma_b(label); 305 } jump(Register reg)306 void jump(Register reg) { 307 as_jr(reg); 308 as_nop(); 309 } jump(const Address & address)310 void jump(const Address& address) { 311 loadPtr(address, ScratchRegister); 312 as_jr(ScratchRegister); 313 as_nop(); 314 } 315 jump(JitCode * code)316 void jump(JitCode* code) { 317 branch(code); 318 } 319 neg32(Register reg)320 void neg32(Register reg) { 321 ma_negu(reg, reg); 322 } negl(Register reg)323 void negl(Register reg) { 324 ma_negu(reg, reg); 325 } 326 327 // Returns the register containing the type tag. splitTagForTest(const ValueOperand & value)328 Register splitTagForTest(const ValueOperand& value) { 329 return value.typeReg(); 330 } 331 332 void branchTestGCThing(Condition cond, const Address& address, Label* label); 333 void branchTestGCThing(Condition cond, const BaseIndex& src, Label* label); 334 335 void branchTestPrimitive(Condition cond, const ValueOperand& value, Label* label); 336 void branchTestPrimitive(Condition cond, Register tag, Label* label); 337 338 void branchTestValue(Condition cond, const ValueOperand& value, const Value& v, Label* label); 339 void branchTestValue(Condition cond, const Address& valaddr, const ValueOperand& value, 340 Label* label); 341 342 // unboxing code 343 void unboxNonDouble(const ValueOperand& operand, Register dest); 344 void unboxNonDouble(const Address& src, Register dest); 345 void unboxNonDouble(const BaseIndex& src, Register dest); 346 void unboxInt32(const ValueOperand& operand, Register dest); 347 void unboxInt32(const Address& src, Register dest); 348 void unboxBoolean(const ValueOperand& operand, Register dest); 349 void unboxBoolean(const Address& src, Register dest); 350 void unboxDouble(const ValueOperand& operand, FloatRegister dest); 351 void unboxDouble(const Address& src, FloatRegister dest); 352 void unboxString(const ValueOperand& operand, Register dest); 353 void unboxString(const Address& src, Register dest); 354 void unboxObject(const ValueOperand& src, Register dest); 355 void unboxObject(const Address& src, Register dest); unboxObject(const BaseIndex & src,Register dest)356 void unboxObject(const BaseIndex& src, Register dest) { unboxNonDouble(src, dest); } 357 void unboxValue(const ValueOperand& src, AnyRegister dest); 358 void unboxPrivate(const ValueOperand& src, Register dest); 359 notBoolean(const ValueOperand & val)360 void notBoolean(const ValueOperand& val) { 361 as_xori(val.payloadReg(), val.payloadReg(), 1); 362 } 363 364 // boxing code 365 void boxDouble(FloatRegister src, const ValueOperand& dest); 366 void boxNonDouble(JSValueType type, Register src, const ValueOperand& dest); 367 368 // Extended unboxing API. If the payload is already in a register, returns 369 // that register. Otherwise, provides a move to the given scratch register, 370 // and returns that. 371 Register extractObject(const Address& address, Register scratch); extractObject(const ValueOperand & value,Register scratch)372 Register extractObject(const ValueOperand& value, Register scratch) { 373 return value.payloadReg(); 374 } extractInt32(const ValueOperand & value,Register scratch)375 Register extractInt32(const ValueOperand& value, Register scratch) { 376 return value.payloadReg(); 377 } extractBoolean(const ValueOperand & value,Register scratch)378 Register extractBoolean(const ValueOperand& value, Register scratch) { 379 return value.payloadReg(); 380 } 381 Register extractTag(const Address& address, Register scratch); 382 Register extractTag(const BaseIndex& address, Register scratch); extractTag(const ValueOperand & value,Register scratch)383 Register extractTag(const ValueOperand& value, Register scratch) { 384 return value.typeReg(); 385 } 386 387 void boolValueToDouble(const ValueOperand& operand, FloatRegister dest); 388 void int32ValueToDouble(const ValueOperand& operand, FloatRegister dest); 389 void loadInt32OrDouble(const Address& address, FloatRegister dest); 390 void loadInt32OrDouble(Register base, Register index, 391 FloatRegister dest, int32_t shift = defaultShift); 392 void loadConstantDouble(double dp, FloatRegister dest); 393 394 void boolValueToFloat32(const ValueOperand& operand, FloatRegister dest); 395 void int32ValueToFloat32(const ValueOperand& operand, FloatRegister dest); 396 void loadConstantFloat32(float f, FloatRegister dest); 397 398 void branchTestInt32(Condition cond, const ValueOperand& value, Label* label); 399 void branchTestInt32(Condition cond, Register tag, Label* label); 400 void branchTestInt32(Condition cond, const Address& address, Label* label); 401 void branchTestInt32(Condition cond, const BaseIndex& src, Label* label); 402 403 void branchTestBoolean(Condition cond, const ValueOperand& value, Label* label); 404 void branchTestBoolean(Condition cond, Register tag, Label* label); 405 void branchTestBoolean(Condition cond, const Address& address, Label* label); 406 void branchTestBoolean(Condition cond, const BaseIndex& src, Label* label); 407 branch32(Condition cond,Register lhs,Register rhs,Label * label)408 void branch32(Condition cond, Register lhs, Register rhs, Label* label) { 409 ma_b(lhs, rhs, label, cond); 410 } branch32(Condition cond,Register lhs,Imm32 imm,Label * label)411 void branch32(Condition cond, Register lhs, Imm32 imm, Label* label) { 412 ma_b(lhs, imm, label, cond); 413 } branch32(Condition cond,const Operand & lhs,Register rhs,Label * label)414 void branch32(Condition cond, const Operand& lhs, Register rhs, Label* label) { 415 if (lhs.getTag() == Operand::REG) { 416 ma_b(lhs.toReg(), rhs, label, cond); 417 } else { 418 branch32(cond, lhs.toAddress(), rhs, label); 419 } 420 } branch32(Condition cond,const Operand & lhs,Imm32 rhs,Label * label)421 void branch32(Condition cond, const Operand& lhs, Imm32 rhs, Label* label) { 422 if (lhs.getTag() == Operand::REG) { 423 ma_b(lhs.toReg(), rhs, label, cond); 424 } else { 425 branch32(cond, lhs.toAddress(), rhs, label); 426 } 427 } branch32(Condition cond,const Address & lhs,Register rhs,Label * label)428 void branch32(Condition cond, const Address& lhs, Register rhs, Label* label) { 429 load32(lhs, SecondScratchReg); 430 ma_b(SecondScratchReg, rhs, label, cond); 431 } branch32(Condition cond,const Address & lhs,Imm32 rhs,Label * label)432 void branch32(Condition cond, const Address& lhs, Imm32 rhs, Label* label) { 433 load32(lhs, SecondScratchReg); 434 ma_b(SecondScratchReg, rhs, label, cond); 435 } branch32(Condition cond,const BaseIndex & lhs,Imm32 rhs,Label * label)436 void branch32(Condition cond, const BaseIndex& lhs, Imm32 rhs, Label* label) { 437 load32(lhs, SecondScratchReg); 438 ma_b(SecondScratchReg, rhs, label, cond); 439 } branchPtr(Condition cond,const Address & lhs,Register rhs,Label * label)440 void branchPtr(Condition cond, const Address& lhs, Register rhs, Label* label) { 441 loadPtr(lhs, SecondScratchReg); 442 ma_b(SecondScratchReg, rhs, label, cond); 443 } 444 branchPrivatePtr(Condition cond,const Address & lhs,ImmPtr ptr,Label * label)445 void branchPrivatePtr(Condition cond, const Address& lhs, ImmPtr ptr, Label* label) { 446 branchPtr(cond, lhs, ptr, label); 447 } 448 branchPrivatePtr(Condition cond,const Address & lhs,Register ptr,Label * label)449 void branchPrivatePtr(Condition cond, const Address& lhs, Register ptr, Label* label) { 450 branchPtr(cond, lhs, ptr, label); 451 } 452 branchPrivatePtr(Condition cond,Register lhs,ImmWord ptr,Label * label)453 void branchPrivatePtr(Condition cond, Register lhs, ImmWord ptr, Label* label) { 454 branchPtr(cond, lhs, ptr, label); 455 } 456 457 void branchTestDouble(Condition cond, const ValueOperand& value, Label* label); 458 void branchTestDouble(Condition cond, Register tag, Label* label); 459 void branchTestDouble(Condition cond, const Address& address, Label* label); 460 void branchTestDouble(Condition cond, const BaseIndex& src, Label* label); 461 462 void branchTestNull(Condition cond, const ValueOperand& value, Label* label); 463 void branchTestNull(Condition cond, Register tag, Label* label); 464 void branchTestNull(Condition cond, const BaseIndex& src, Label* label); 465 void branchTestNull(Condition cond, const Address& address, Label* label); 466 void testNullSet(Condition cond, const ValueOperand& value, Register dest); 467 468 void branchTestObject(Condition cond, const ValueOperand& value, Label* label); 469 void branchTestObject(Condition cond, Register tag, Label* label); 470 void branchTestObject(Condition cond, const BaseIndex& src, Label* label); 471 void branchTestObject(Condition cond, const Address& src, Label* label); 472 void testObjectSet(Condition cond, const ValueOperand& value, Register dest); 473 474 void branchTestString(Condition cond, const ValueOperand& value, Label* label); 475 void branchTestString(Condition cond, Register tag, Label* label); 476 void branchTestString(Condition cond, const BaseIndex& src, Label* label); 477 478 void branchTestSymbol(Condition cond, const ValueOperand& value, Label* label); 479 void branchTestSymbol(Condition cond, const Register& tag, Label* label); 480 void branchTestSymbol(Condition cond, const BaseIndex& src, Label* label); 481 482 void branchTestUndefined(Condition cond, const ValueOperand& value, Label* label); 483 void branchTestUndefined(Condition cond, Register tag, Label* label); 484 void branchTestUndefined(Condition cond, const BaseIndex& src, Label* label); 485 void branchTestUndefined(Condition cond, const Address& address, Label* label); 486 void testUndefinedSet(Condition cond, const ValueOperand& value, Register dest); 487 488 void branchTestNumber(Condition cond, const ValueOperand& value, Label* label); 489 void branchTestNumber(Condition cond, Register tag, Label* label); 490 491 void branchTestMagic(Condition cond, const ValueOperand& value, Label* label); 492 void branchTestMagic(Condition cond, Register tag, Label* label); 493 void branchTestMagic(Condition cond, const Address& address, Label* label); 494 void branchTestMagic(Condition cond, const BaseIndex& src, Label* label); 495 branchTestMagicValue(Condition cond,const ValueOperand & val,JSWhyMagic why,Label * label)496 void branchTestMagicValue(Condition cond, const ValueOperand& val, JSWhyMagic why, 497 Label* label) { 498 MOZ_ASSERT(cond == Equal || cond == NotEqual); 499 branchTestValue(cond, val, MagicValue(why), label); 500 } 501 502 void branchTestInt32Truthy(bool b, const ValueOperand& value, Label* label); 503 504 void branchTestStringTruthy(bool b, const ValueOperand& value, Label* label); 505 506 void branchTestDoubleTruthy(bool b, FloatRegister value, Label* label); 507 508 void branchTestBooleanTruthy(bool b, const ValueOperand& operand, Label* label); 509 branchTest32(Condition cond,Register lhs,Register rhs,Label * label)510 void branchTest32(Condition cond, Register lhs, Register rhs, Label* label) { 511 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned); 512 if (lhs == rhs) { 513 ma_b(lhs, rhs, label, cond); 514 } else { 515 as_and(ScratchRegister, lhs, rhs); 516 ma_b(ScratchRegister, ScratchRegister, label, cond); 517 } 518 } branchTest32(Condition cond,Register lhs,Imm32 imm,Label * label)519 void branchTest32(Condition cond, Register lhs, Imm32 imm, Label* label) { 520 ma_li(ScratchRegister, imm); 521 branchTest32(cond, lhs, ScratchRegister, label); 522 } branchTest32(Condition cond,const Address & address,Imm32 imm,Label * label)523 void branchTest32(Condition cond, const Address& address, Imm32 imm, Label* label) { 524 load32(address, SecondScratchReg); 525 branchTest32(cond, SecondScratchReg, imm, label); 526 } branchTest32(Condition cond,AbsoluteAddress address,Imm32 imm,Label * label)527 void branchTest32(Condition cond, AbsoluteAddress address, Imm32 imm, Label* label) { 528 load32(address, ScratchRegister); 529 branchTest32(cond, ScratchRegister, imm, label); 530 } branchTestPtr(Condition cond,Register lhs,Register rhs,Label * label)531 void branchTestPtr(Condition cond, Register lhs, Register rhs, Label* label) { 532 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned); 533 if (lhs == rhs) { 534 ma_b(lhs, rhs, label, cond); 535 } else { 536 as_and(ScratchRegister, lhs, rhs); 537 ma_b(ScratchRegister, ScratchRegister, label, cond); 538 } 539 } branchTestPtr(Condition cond,Register lhs,const Imm32 rhs,Label * label)540 void branchTestPtr(Condition cond, Register lhs, const Imm32 rhs, Label* label) { 541 ma_li(ScratchRegister, rhs); 542 branchTestPtr(cond, lhs, ScratchRegister, label); 543 } branchTestPtr(Condition cond,const Address & lhs,Imm32 imm,Label * label)544 void branchTestPtr(Condition cond, const Address& lhs, Imm32 imm, Label* label) { 545 loadPtr(lhs, SecondScratchReg); 546 branchTestPtr(cond, SecondScratchReg, imm, label); 547 } 548 void branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp, 549 Label* label); branchPtr(Condition cond,Register lhs,Register rhs,Label * label)550 void branchPtr(Condition cond, Register lhs, Register rhs, Label* label) { 551 ma_b(lhs, rhs, label, cond); 552 } branchPtr(Condition cond,Register lhs,ImmGCPtr ptr,Label * label)553 void branchPtr(Condition cond, Register lhs, ImmGCPtr ptr, Label* label) { 554 ma_b(lhs, ptr, label, cond); 555 } branchPtr(Condition cond,Register lhs,ImmWord imm,Label * label)556 void branchPtr(Condition cond, Register lhs, ImmWord imm, Label* label) { 557 ma_b(lhs, imm, label, cond); 558 } branchPtr(Condition cond,Register lhs,ImmPtr imm,Label * label)559 void branchPtr(Condition cond, Register lhs, ImmPtr imm, Label* label) { 560 ma_b(lhs, imm, label, cond); 561 } branchPtr(Condition cond,Register lhs,wasm::SymbolicAddress imm,Label * label)562 void branchPtr(Condition cond, Register lhs, wasm::SymbolicAddress imm, Label* label) { 563 movePtr(imm, SecondScratchReg); 564 ma_b(lhs, SecondScratchReg, label, cond); 565 } branchPtr(Condition cond,Register lhs,Imm32 imm,Label * label)566 void branchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) { 567 ma_b(lhs, imm, label, cond); 568 } decBranchPtr(Condition cond,Register lhs,Imm32 imm,Label * label)569 void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) { 570 subPtr(imm, lhs); 571 branchPtr(cond, lhs, Imm32(0), label); 572 } 573 574 // higher level tag testing code 575 Operand ToPayload(Operand base); ToPayload(Address base)576 Address ToPayload(Address base) { 577 return ToPayload(Operand(base)).toAddress(); 578 } 579 580 protected: 581 Operand ToType(Operand base); ToType(Address base)582 Address ToType(Address base) { 583 return ToType(Operand(base)).toAddress(); 584 } 585 586 uint32_t getType(const Value& val); 587 void moveData(const Value& val, Register data); 588 public: 589 void moveValue(const Value& val, Register type, Register data); 590 591 CodeOffsetJump backedgeJump(RepatchLabel* label, Label* documentation = nullptr); 592 CodeOffsetJump jumpWithPatch(RepatchLabel* label, Label* documentation = nullptr); 593 594 template <typename T> branchPtrWithPatch(Condition cond,Register reg,T ptr,RepatchLabel * label)595 CodeOffsetJump branchPtrWithPatch(Condition cond, Register reg, T ptr, RepatchLabel* label) { 596 movePtr(ptr, ScratchRegister); 597 Label skipJump; 598 ma_b(reg, ScratchRegister, &skipJump, InvertCondition(cond), ShortJump); 599 CodeOffsetJump off = jumpWithPatch(label); 600 bind(&skipJump); 601 return off; 602 } 603 604 template <typename T> branchPtrWithPatch(Condition cond,Address addr,T ptr,RepatchLabel * label)605 CodeOffsetJump branchPtrWithPatch(Condition cond, Address addr, T ptr, RepatchLabel* label) { 606 loadPtr(addr, SecondScratchReg); 607 movePtr(ptr, ScratchRegister); 608 Label skipJump; 609 ma_b(SecondScratchReg, ScratchRegister, &skipJump, InvertCondition(cond), ShortJump); 610 CodeOffsetJump off = jumpWithPatch(label); 611 bind(&skipJump); 612 return off; 613 } branchPtr(Condition cond,Address addr,ImmGCPtr ptr,Label * label)614 void branchPtr(Condition cond, Address addr, ImmGCPtr ptr, Label* label) { 615 loadPtr(addr, SecondScratchReg); 616 ma_b(SecondScratchReg, ptr, label, cond); 617 } 618 branchPtr(Condition cond,Address addr,ImmWord ptr,Label * label)619 void branchPtr(Condition cond, Address addr, ImmWord ptr, Label* label) { 620 loadPtr(addr, SecondScratchReg); 621 ma_b(SecondScratchReg, ptr, label, cond); 622 } branchPtr(Condition cond,Address addr,ImmPtr ptr,Label * label)623 void branchPtr(Condition cond, Address addr, ImmPtr ptr, Label* label) { 624 loadPtr(addr, SecondScratchReg); 625 ma_b(SecondScratchReg, ptr, label, cond); 626 } branchPtr(Condition cond,AbsoluteAddress addr,Register ptr,Label * label)627 void branchPtr(Condition cond, AbsoluteAddress addr, Register ptr, Label* label) { 628 loadPtr(addr, SecondScratchReg); 629 ma_b(SecondScratchReg, ptr, label, cond); 630 } branchPtr(Condition cond,AbsoluteAddress addr,ImmWord ptr,Label * label)631 void branchPtr(Condition cond, AbsoluteAddress addr, ImmWord ptr, Label* label) { 632 loadPtr(addr, SecondScratchReg); 633 ma_b(SecondScratchReg, ptr, label, cond); 634 } branchPtr(Condition cond,wasm::SymbolicAddress addr,Register ptr,Label * label)635 void branchPtr(Condition cond, wasm::SymbolicAddress addr, Register ptr, Label* label) { 636 loadPtr(addr, SecondScratchReg); 637 ma_b(SecondScratchReg, ptr, label, cond); 638 } branch32(Condition cond,AbsoluteAddress lhs,Imm32 rhs,Label * label)639 void branch32(Condition cond, AbsoluteAddress lhs, Imm32 rhs, Label* label) { 640 load32(lhs, SecondScratchReg); 641 ma_b(SecondScratchReg, rhs, label, cond); 642 } branch32(Condition cond,AbsoluteAddress lhs,Register rhs,Label * label)643 void branch32(Condition cond, AbsoluteAddress lhs, Register rhs, Label* label) { 644 load32(lhs, SecondScratchReg); 645 ma_b(SecondScratchReg, rhs, label, cond); 646 } branch32(Condition cond,wasm::SymbolicAddress addr,Imm32 imm,Label * label)647 void branch32(Condition cond, wasm::SymbolicAddress addr, Imm32 imm, Label* label) { 648 load32(addr, SecondScratchReg); 649 ma_b(SecondScratchReg, imm, label, cond); 650 } 651 loadUnboxedValue(Address address,MIRType type,AnyRegister dest)652 void loadUnboxedValue(Address address, MIRType type, AnyRegister dest) { 653 if (dest.isFloat()) 654 loadInt32OrDouble(address, dest.fpu()); 655 else 656 ma_lw(dest.gpr(), address); 657 } 658 loadUnboxedValue(BaseIndex address,MIRType type,AnyRegister dest)659 void loadUnboxedValue(BaseIndex address, MIRType type, AnyRegister dest) { 660 if (dest.isFloat()) 661 loadInt32OrDouble(address.base, address.index, dest.fpu(), address.scale); 662 else 663 load32(address, dest.gpr()); 664 } 665 666 template <typename T> 667 void storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const T& dest, 668 MIRType slotType); 669 670 template <typename T> storeUnboxedPayload(ValueOperand value,T address,size_t nbytes)671 void storeUnboxedPayload(ValueOperand value, T address, size_t nbytes) { 672 switch (nbytes) { 673 case 4: 674 store32(value.payloadReg(), address); 675 return; 676 case 1: 677 store8(value.payloadReg(), address); 678 return; 679 default: MOZ_CRASH("Bad payload width"); 680 } 681 } 682 683 void moveValue(const Value& val, const ValueOperand& dest); 684 moveValue(const ValueOperand & src,const ValueOperand & dest)685 void moveValue(const ValueOperand& src, const ValueOperand& dest) { 686 Register s0 = src.typeReg(), d0 = dest.typeReg(), 687 s1 = src.payloadReg(), d1 = dest.payloadReg(); 688 689 // Either one or both of the source registers could be the same as a 690 // destination register. 691 if (s1 == d0) { 692 if (s0 == d1) { 693 // If both are, this is just a swap of two registers. 694 MOZ_ASSERT(d1 != ScratchRegister); 695 MOZ_ASSERT(d0 != ScratchRegister); 696 move32(d1, ScratchRegister); 697 move32(d0, d1); 698 move32(ScratchRegister, d0); 699 return; 700 } 701 // If only one is, copy that source first. 702 mozilla::Swap(s0, s1); 703 mozilla::Swap(d0, d1); 704 } 705 706 if (s0 != d0) 707 move32(s0, d0); 708 if (s1 != d1) 709 move32(s1, d1); 710 } 711 712 void storeValue(ValueOperand val, Operand dst); 713 void storeValue(ValueOperand val, const BaseIndex& dest); 714 void storeValue(JSValueType type, Register reg, BaseIndex dest); 715 void storeValue(ValueOperand val, const Address& dest); 716 void storeValue(JSValueType type, Register reg, Address dest); 717 void storeValue(const Value& val, Address dest); 718 void storeValue(const Value& val, BaseIndex dest); 719 720 void loadValue(Address src, ValueOperand val); loadValue(Operand dest,ValueOperand val)721 void loadValue(Operand dest, ValueOperand val) { 722 loadValue(dest.toAddress(), val); 723 } 724 void loadValue(const BaseIndex& addr, ValueOperand val); 725 void tagValue(JSValueType type, Register payload, ValueOperand dest); 726 727 void pushValue(ValueOperand val); 728 void popValue(ValueOperand val); pushValue(const Value & val)729 void pushValue(const Value& val) { 730 jsval_layout jv = JSVAL_TO_IMPL(val); 731 push(Imm32(jv.s.tag)); 732 if (val.isMarkable()) 733 push(ImmGCPtr(reinterpret_cast<gc::Cell*>(val.toGCThing()))); 734 else 735 push(Imm32(jv.s.payload.i32)); 736 } pushValue(JSValueType type,Register reg)737 void pushValue(JSValueType type, Register reg) { 738 push(ImmTag(JSVAL_TYPE_TO_TAG(type))); 739 ma_push(reg); 740 } 741 void pushValue(const Address& addr); 742 743 void storePayload(const Value& val, Address dest); 744 void storePayload(Register src, Address dest); 745 void storePayload(const Value& val, const BaseIndex& dest); 746 void storePayload(Register src, const BaseIndex& dest); 747 void storeTypeTag(ImmTag tag, Address dest); 748 void storeTypeTag(ImmTag tag, const BaseIndex& dest); 749 750 void handleFailureWithHandlerTail(void* handler); 751 752 ///////////////////////////////////////////////////////////////// 753 // Common interface. 754 ///////////////////////////////////////////////////////////////// 755 public: 756 // The following functions are exposed for use in platform-shared code. 757 758 template<typename T> compareExchange8SignExtend(const T & mem,Register oldval,Register newval,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)759 void compareExchange8SignExtend(const T& mem, Register oldval, Register newval, Register valueTemp, 760 Register offsetTemp, Register maskTemp, Register output) 761 { 762 compareExchange(1, true, mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output); 763 } 764 template<typename T> compareExchange8ZeroExtend(const T & mem,Register oldval,Register newval,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)765 void compareExchange8ZeroExtend(const T& mem, Register oldval, Register newval, Register valueTemp, 766 Register offsetTemp, Register maskTemp, Register output) 767 { 768 compareExchange(1, false, mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output); 769 } 770 template<typename T> compareExchange16SignExtend(const T & mem,Register oldval,Register newval,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)771 void compareExchange16SignExtend(const T& mem, Register oldval, Register newval, Register valueTemp, 772 Register offsetTemp, Register maskTemp, Register output) 773 { 774 compareExchange(2, true, mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output); 775 } 776 template<typename T> compareExchange16ZeroExtend(const T & mem,Register oldval,Register newval,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)777 void compareExchange16ZeroExtend(const T& mem, Register oldval, Register newval, Register valueTemp, 778 Register offsetTemp, Register maskTemp, Register output) 779 { 780 compareExchange(2, false, mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output); 781 } 782 template<typename T> compareExchange32(const T & mem,Register oldval,Register newval,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)783 void compareExchange32(const T& mem, Register oldval, Register newval, Register valueTemp, 784 Register offsetTemp, Register maskTemp, Register output) 785 { 786 compareExchange(4, false, mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output); 787 } 788 789 template<typename T> atomicExchange8SignExtend(const T & mem,Register value,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)790 void atomicExchange8SignExtend(const T& mem, Register value, Register valueTemp, 791 Register offsetTemp, Register maskTemp, Register output) 792 { 793 atomicExchange(1, true, mem, value, valueTemp, offsetTemp, maskTemp, output); 794 } 795 template<typename T> atomicExchange8ZeroExtend(const T & mem,Register value,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)796 void atomicExchange8ZeroExtend(const T& mem, Register value, Register valueTemp, 797 Register offsetTemp, Register maskTemp, Register output) 798 { 799 atomicExchange(1, false, mem, value, valueTemp, offsetTemp, maskTemp, output); 800 } 801 template<typename T> atomicExchange16SignExtend(const T & mem,Register value,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)802 void atomicExchange16SignExtend(const T& mem, Register value, Register valueTemp, 803 Register offsetTemp, Register maskTemp, Register output) 804 { 805 atomicExchange(2, true, mem, value, valueTemp, offsetTemp, maskTemp, output); 806 } 807 template<typename T> atomicExchange16ZeroExtend(const T & mem,Register value,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)808 void atomicExchange16ZeroExtend(const T& mem, Register value, Register valueTemp, 809 Register offsetTemp, Register maskTemp, Register output) 810 { 811 atomicExchange(2, false, mem, value, valueTemp, offsetTemp, maskTemp, output); 812 } 813 template<typename T> atomicExchange32(const T & mem,Register value,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)814 void atomicExchange32(const T& mem, Register value, Register valueTemp, 815 Register offsetTemp, Register maskTemp, Register output) 816 { 817 atomicExchange(4, false, mem, value, valueTemp, offsetTemp, maskTemp, output); 818 } 819 820 template<typename T, typename S> atomicFetchAdd8SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)821 void atomicFetchAdd8SignExtend(const S& value, const T& mem, Register flagTemp, 822 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 823 { 824 atomicFetchOp(1, true, AtomicFetchAddOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 825 } 826 template<typename T, typename S> atomicFetchAdd8ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)827 void atomicFetchAdd8ZeroExtend(const S& value, const T& mem, Register flagTemp, 828 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 829 { 830 atomicFetchOp(1, false, AtomicFetchAddOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 831 } 832 template<typename T, typename S> atomicFetchAdd16SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)833 void atomicFetchAdd16SignExtend(const S& value, const T& mem, Register flagTemp, 834 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 835 { 836 atomicFetchOp(2, true, AtomicFetchAddOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 837 } 838 template<typename T, typename S> atomicFetchAdd16ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)839 void atomicFetchAdd16ZeroExtend(const S& value, const T& mem, Register flagTemp, 840 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 841 { 842 atomicFetchOp(2, false, AtomicFetchAddOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 843 } 844 template<typename T, typename S> atomicFetchAdd32(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)845 void atomicFetchAdd32(const S& value, const T& mem, Register flagTemp, 846 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 847 { 848 atomicFetchOp(4, false, AtomicFetchAddOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 849 } 850 template <typename T, typename S> atomicAdd8(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)851 void atomicAdd8(const T& value, const S& mem, Register flagTemp, 852 Register valueTemp, Register offsetTemp, Register maskTemp) 853 { 854 atomicEffectOp(1, AtomicFetchAddOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp); 855 } 856 template <typename T, typename S> atomicAdd16(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)857 void atomicAdd16(const T& value, const S& mem, Register flagTemp, 858 Register valueTemp, Register offsetTemp, Register maskTemp) 859 { 860 atomicEffectOp(2, AtomicFetchAddOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp); 861 } 862 template <typename T, typename S> atomicAdd32(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)863 void atomicAdd32(const T& value, const S& mem, Register flagTemp, 864 Register valueTemp, Register offsetTemp, Register maskTemp) 865 { 866 atomicEffectOp(4, AtomicFetchAddOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp); 867 } 868 869 template<typename T, typename S> atomicFetchSub8SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)870 void atomicFetchSub8SignExtend(const S& value, const T& mem, Register flagTemp, 871 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 872 { 873 atomicFetchOp(1, true, AtomicFetchSubOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 874 } 875 template<typename T, typename S> atomicFetchSub8ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)876 void atomicFetchSub8ZeroExtend(const S& value, const T& mem, Register flagTemp, 877 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 878 { 879 atomicFetchOp(1, false, AtomicFetchSubOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 880 } 881 template<typename T, typename S> atomicFetchSub16SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)882 void atomicFetchSub16SignExtend(const S& value, const T& mem, Register flagTemp, 883 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 884 { 885 atomicFetchOp(2, true, AtomicFetchSubOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 886 } 887 template<typename T, typename S> atomicFetchSub16ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)888 void atomicFetchSub16ZeroExtend(const S& value, const T& mem, Register flagTemp, 889 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 890 { 891 atomicFetchOp(2, false, AtomicFetchSubOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 892 } 893 template<typename T, typename S> atomicFetchSub32(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)894 void atomicFetchSub32(const S& value, const T& mem, Register flagTemp, 895 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 896 { 897 atomicFetchOp(4, false, AtomicFetchSubOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 898 } 899 template <typename T, typename S> atomicSub8(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)900 void atomicSub8(const T& value, const S& mem, Register flagTemp, 901 Register valueTemp, Register offsetTemp, Register maskTemp) 902 { 903 atomicEffectOp(1, AtomicFetchSubOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp); 904 } 905 template <typename T, typename S> atomicSub16(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)906 void atomicSub16(const T& value, const S& mem, Register flagTemp, 907 Register valueTemp, Register offsetTemp, Register maskTemp) 908 { 909 atomicEffectOp(2, AtomicFetchSubOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp); 910 } 911 template <typename T, typename S> atomicSub32(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)912 void atomicSub32(const T& value, const S& mem, Register flagTemp, 913 Register valueTemp, Register offsetTemp, Register maskTemp) 914 { 915 atomicEffectOp(4, AtomicFetchSubOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp); 916 } 917 918 template<typename T, typename S> atomicFetchAnd8SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)919 void atomicFetchAnd8SignExtend(const S& value, const T& mem, Register flagTemp, 920 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 921 { 922 atomicFetchOp(1, true, AtomicFetchAndOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 923 } 924 template<typename T, typename S> atomicFetchAnd8ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)925 void atomicFetchAnd8ZeroExtend(const S& value, const T& mem, Register flagTemp, 926 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 927 { 928 atomicFetchOp(1, false, AtomicFetchAndOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 929 } 930 template<typename T, typename S> atomicFetchAnd16SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)931 void atomicFetchAnd16SignExtend(const S& value, const T& mem, Register flagTemp, 932 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 933 { 934 atomicFetchOp(2, true, AtomicFetchAndOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 935 } 936 template<typename T, typename S> atomicFetchAnd16ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)937 void atomicFetchAnd16ZeroExtend(const S& value, const T& mem, Register flagTemp, 938 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 939 { 940 atomicFetchOp(2, false, AtomicFetchAndOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 941 } 942 template<typename T, typename S> atomicFetchAnd32(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)943 void atomicFetchAnd32(const S& value, const T& mem, Register flagTemp, 944 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 945 { 946 atomicFetchOp(4, false, AtomicFetchAndOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 947 } 948 template <typename T, typename S> atomicAnd8(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)949 void atomicAnd8(const T& value, const S& mem, Register flagTemp, 950 Register valueTemp, Register offsetTemp, Register maskTemp) 951 { 952 atomicEffectOp(1, AtomicFetchAndOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp); 953 } 954 template <typename T, typename S> atomicAnd16(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)955 void atomicAnd16(const T& value, const S& mem, Register flagTemp, 956 Register valueTemp, Register offsetTemp, Register maskTemp) 957 { 958 atomicEffectOp(2, AtomicFetchAndOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp); 959 } 960 template <typename T, typename S> atomicAnd32(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)961 void atomicAnd32(const T& value, const S& mem, Register flagTemp, 962 Register valueTemp, Register offsetTemp, Register maskTemp) 963 { 964 atomicEffectOp(4, AtomicFetchAndOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp); 965 } 966 967 template<typename T, typename S> atomicFetchOr8SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)968 void atomicFetchOr8SignExtend(const S& value, const T& mem, Register flagTemp, 969 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 970 { 971 atomicFetchOp(1, true, AtomicFetchOrOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 972 } 973 template<typename T, typename S> atomicFetchOr8ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)974 void atomicFetchOr8ZeroExtend(const S& value, const T& mem, Register flagTemp, 975 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 976 { 977 atomicFetchOp(1, false, AtomicFetchOrOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 978 } 979 template<typename T, typename S> atomicFetchOr16SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)980 void atomicFetchOr16SignExtend(const S& value, const T& mem, Register flagTemp, 981 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 982 { 983 atomicFetchOp(2, true, AtomicFetchOrOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 984 } 985 template<typename T, typename S> atomicFetchOr16ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)986 void atomicFetchOr16ZeroExtend(const S& value, const T& mem, Register flagTemp, 987 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 988 { 989 atomicFetchOp(2, false, AtomicFetchOrOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 990 } 991 template<typename T, typename S> atomicFetchOr32(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)992 void atomicFetchOr32(const S& value, const T& mem, Register flagTemp, 993 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 994 { 995 atomicFetchOp(4, false, AtomicFetchOrOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 996 } 997 template <typename T, typename S> atomicOr8(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)998 void atomicOr8(const T& value, const S& mem, Register flagTemp, 999 Register valueTemp, Register offsetTemp, Register maskTemp) 1000 { 1001 atomicEffectOp(1, AtomicFetchOrOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp); 1002 } 1003 template <typename T, typename S> atomicOr16(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)1004 void atomicOr16(const T& value, const S& mem, Register flagTemp, 1005 Register valueTemp, Register offsetTemp, Register maskTemp) 1006 { 1007 atomicEffectOp(2, AtomicFetchOrOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp); 1008 } 1009 template <typename T, typename S> atomicOr32(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)1010 void atomicOr32(const T& value, const S& mem, Register flagTemp, 1011 Register valueTemp, Register offsetTemp, Register maskTemp) 1012 { 1013 atomicEffectOp(4, AtomicFetchOrOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp); 1014 } 1015 1016 template<typename T, typename S> atomicFetchXor8SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)1017 void atomicFetchXor8SignExtend(const S& value, const T& mem, Register flagTemp, 1018 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 1019 { 1020 atomicFetchOp(1, true, AtomicFetchXorOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 1021 } 1022 template<typename T, typename S> atomicFetchXor8ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)1023 void atomicFetchXor8ZeroExtend(const S& value, const T& mem, Register flagTemp, 1024 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 1025 { 1026 atomicFetchOp(1, false, AtomicFetchXorOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 1027 } 1028 template<typename T, typename S> atomicFetchXor16SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)1029 void atomicFetchXor16SignExtend(const S& value, const T& mem, Register flagTemp, 1030 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 1031 { 1032 atomicFetchOp(2, true, AtomicFetchXorOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 1033 } 1034 template<typename T, typename S> atomicFetchXor16ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)1035 void atomicFetchXor16ZeroExtend(const S& value, const T& mem, Register flagTemp, 1036 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 1037 { 1038 atomicFetchOp(2, false, AtomicFetchXorOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 1039 } 1040 template<typename T, typename S> atomicFetchXor32(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)1041 void atomicFetchXor32(const S& value, const T& mem, Register flagTemp, 1042 Register valueTemp, Register offsetTemp, Register maskTemp, Register output) 1043 { 1044 atomicFetchOp(4, false, AtomicFetchXorOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output); 1045 } 1046 template <typename T, typename S> atomicXor8(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)1047 void atomicXor8(const T& value, const S& mem, Register flagTemp, 1048 Register valueTemp, Register offsetTemp, Register maskTemp) 1049 { 1050 atomicEffectOp(1, AtomicFetchXorOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp); 1051 } 1052 template <typename T, typename S> atomicXor16(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)1053 void atomicXor16(const T& value, const S& mem, Register flagTemp, 1054 Register valueTemp, Register offsetTemp, Register maskTemp) 1055 { 1056 atomicEffectOp(2, AtomicFetchXorOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp); 1057 } 1058 template <typename T, typename S> atomicXor32(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)1059 void atomicXor32(const T& value, const S& mem, Register flagTemp, 1060 Register valueTemp, Register offsetTemp, Register maskTemp) 1061 { 1062 atomicEffectOp(4, AtomicFetchXorOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp); 1063 } 1064 1065 template<typename T> 1066 void compareExchangeToTypedIntArray(Scalar::Type arrayType, const T& mem, Register oldval, Register newval, 1067 Register temp, Register valueTemp, Register offsetTemp, Register maskTemp, 1068 AnyRegister output); 1069 1070 template<typename T> 1071 void atomicExchangeToTypedIntArray(Scalar::Type arrayType, const T& mem, Register value, 1072 Register temp, Register valueTemp, Register offsetTemp, Register maskTemp, 1073 AnyRegister output); 1074 1075 void add32(Register src, Register dest); 1076 void add32(Imm32 imm, Register dest); 1077 void add32(Imm32 imm, const Address& dest); add64(Imm32 imm,Register64 dest)1078 void add64(Imm32 imm, Register64 dest) { 1079 as_addiu(dest.low, dest.low, imm.value); 1080 as_sltiu(ScratchRegister, dest.low, imm.value); 1081 as_addu(dest.high, dest.high, ScratchRegister); 1082 } 1083 incrementInt32Value(const Address & addr)1084 void incrementInt32Value(const Address& addr) { 1085 add32(Imm32(1), ToPayload(addr)); 1086 } 1087 1088 template <typename T> branchAdd32(Condition cond,T src,Register dest,Label * overflow)1089 void branchAdd32(Condition cond, T src, Register dest, Label* overflow) { 1090 switch (cond) { 1091 case Overflow: 1092 ma_addTestOverflow(dest, dest, src, overflow); 1093 break; 1094 default: 1095 MOZ_CRASH("NYI"); 1096 } 1097 } 1098 template <typename T> branchSub32(Condition cond,T src,Register dest,Label * overflow)1099 void branchSub32(Condition cond, T src, Register dest, Label* overflow) { 1100 switch (cond) { 1101 case Overflow: 1102 ma_subTestOverflow(dest, dest, src, overflow); 1103 break; 1104 case NonZero: 1105 case Zero: 1106 ma_subu(dest, src); 1107 ma_b(dest, dest, overflow, cond); 1108 break; 1109 default: 1110 MOZ_CRASH("NYI"); 1111 } 1112 } 1113 1114 void addPtr(Register src, Register dest); 1115 void subPtr(Register src, Register dest); 1116 void addPtr(const Address& src, Register dest); 1117 1118 void move32(Imm32 imm, Register dest); 1119 void move32(Register src, Register dest); move64(Register64 src,Register64 dest)1120 void move64(Register64 src, Register64 dest) { 1121 move32(src.low, dest.low); 1122 move32(src.high, dest.high); 1123 } 1124 1125 void movePtr(Register src, Register dest); 1126 void movePtr(ImmWord imm, Register dest); 1127 void movePtr(ImmPtr imm, Register dest); 1128 void movePtr(wasm::SymbolicAddress imm, Register dest); 1129 void movePtr(ImmGCPtr imm, Register dest); 1130 1131 void load8SignExtend(const Address& address, Register dest); 1132 void load8SignExtend(const BaseIndex& src, Register dest); 1133 1134 void load8ZeroExtend(const Address& address, Register dest); 1135 void load8ZeroExtend(const BaseIndex& src, Register dest); 1136 1137 void load16SignExtend(const Address& address, Register dest); 1138 void load16SignExtend(const BaseIndex& src, Register dest); 1139 1140 void load16ZeroExtend(const Address& address, Register dest); 1141 void load16ZeroExtend(const BaseIndex& src, Register dest); 1142 1143 void load32(const Address& address, Register dest); 1144 void load32(const BaseIndex& address, Register dest); 1145 void load32(AbsoluteAddress address, Register dest); 1146 void load32(wasm::SymbolicAddress address, Register dest); load64(const Address & address,Register64 dest)1147 void load64(const Address& address, Register64 dest) { 1148 load32(Address(address.base, address.offset + LOW_32_OFFSET), dest.low); 1149 load32(Address(address.base, address.offset + HIGH_32_OFFSET), dest.high); 1150 } 1151 branch64(Condition cond,const Address & lhs,Imm64 val,Label * label)1152 void branch64(Condition cond, const Address& lhs, Imm64 val, Label* label) { 1153 MOZ_ASSERT(cond == Assembler::NotEqual, 1154 "other condition codes not supported"); 1155 1156 branch32(cond, lhs, val.firstHalf(), label); 1157 branch32(cond, Address(lhs.base, lhs.offset + sizeof(uint32_t)), val.secondHalf(), label); 1158 } 1159 branch64(Condition cond,const Address & lhs,const Address & rhs,Register scratch,Label * label)1160 void branch64(Condition cond, const Address& lhs, const Address& rhs, Register scratch, 1161 Label* label) 1162 { 1163 MOZ_ASSERT(cond == Assembler::NotEqual, 1164 "other condition codes not supported"); 1165 MOZ_ASSERT(lhs.base != scratch); 1166 MOZ_ASSERT(rhs.base != scratch); 1167 1168 load32(rhs, scratch); 1169 branch32(cond, lhs, scratch, label); 1170 1171 load32(Address(rhs.base, rhs.offset + sizeof(uint32_t)), scratch); 1172 branch32(cond, Address(lhs.base, lhs.offset + sizeof(uint32_t)), scratch, label); 1173 } 1174 1175 void loadPtr(const Address& address, Register dest); 1176 void loadPtr(const BaseIndex& src, Register dest); 1177 void loadPtr(AbsoluteAddress address, Register dest); 1178 void loadPtr(wasm::SymbolicAddress address, Register dest); 1179 1180 void loadPrivate(const Address& address, Register dest); 1181 loadInt32x1(const Address & addr,FloatRegister dest)1182 void loadInt32x1(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } loadInt32x1(const BaseIndex & addr,FloatRegister dest)1183 void loadInt32x1(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } loadInt32x2(const Address & addr,FloatRegister dest)1184 void loadInt32x2(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } loadInt32x2(const BaseIndex & addr,FloatRegister dest)1185 void loadInt32x2(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } loadInt32x3(const Address & src,FloatRegister dest)1186 void loadInt32x3(const Address& src, FloatRegister dest) { MOZ_CRASH("NYI"); } loadInt32x3(const BaseIndex & src,FloatRegister dest)1187 void loadInt32x3(const BaseIndex& src, FloatRegister dest) { MOZ_CRASH("NYI"); } storeInt32x1(FloatRegister src,const Address & dest)1188 void storeInt32x1(FloatRegister src, const Address& dest) { MOZ_CRASH("NYI"); } storeInt32x1(FloatRegister src,const BaseIndex & dest)1189 void storeInt32x1(FloatRegister src, const BaseIndex& dest) { MOZ_CRASH("NYI"); } storeInt32x2(FloatRegister src,const Address & dest)1190 void storeInt32x2(FloatRegister src, const Address& dest) { MOZ_CRASH("NYI"); } storeInt32x2(FloatRegister src,const BaseIndex & dest)1191 void storeInt32x2(FloatRegister src, const BaseIndex& dest) { MOZ_CRASH("NYI"); } storeInt32x3(FloatRegister src,const Address & dest)1192 void storeInt32x3(FloatRegister src, const Address& dest) { MOZ_CRASH("NYI"); } storeInt32x3(FloatRegister src,const BaseIndex & dest)1193 void storeInt32x3(FloatRegister src, const BaseIndex& dest) { MOZ_CRASH("NYI"); } loadAlignedInt32x4(const Address & addr,FloatRegister dest)1194 void loadAlignedInt32x4(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } storeAlignedInt32x4(FloatRegister src,Address addr)1195 void storeAlignedInt32x4(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); } loadUnalignedInt32x4(const Address & addr,FloatRegister dest)1196 void loadUnalignedInt32x4(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } loadUnalignedInt32x4(const BaseIndex & addr,FloatRegister dest)1197 void loadUnalignedInt32x4(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } storeUnalignedInt32x4(FloatRegister src,Address addr)1198 void storeUnalignedInt32x4(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); } storeUnalignedInt32x4(FloatRegister src,BaseIndex addr)1199 void storeUnalignedInt32x4(FloatRegister src, BaseIndex addr) { MOZ_CRASH("NYI"); } 1200 loadFloat32x3(const Address & src,FloatRegister dest)1201 void loadFloat32x3(const Address& src, FloatRegister dest) { MOZ_CRASH("NYI"); } loadFloat32x3(const BaseIndex & src,FloatRegister dest)1202 void loadFloat32x3(const BaseIndex& src, FloatRegister dest) { MOZ_CRASH("NYI"); } storeFloat32x3(FloatRegister src,const Address & dest)1203 void storeFloat32x3(FloatRegister src, const Address& dest) { MOZ_CRASH("NYI"); } storeFloat32x3(FloatRegister src,const BaseIndex & dest)1204 void storeFloat32x3(FloatRegister src, const BaseIndex& dest) { MOZ_CRASH("NYI"); } loadAlignedFloat32x4(const Address & addr,FloatRegister dest)1205 void loadAlignedFloat32x4(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } storeAlignedFloat32x4(FloatRegister src,Address addr)1206 void storeAlignedFloat32x4(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); } loadUnalignedFloat32x4(const Address & addr,FloatRegister dest)1207 void loadUnalignedFloat32x4(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } loadUnalignedFloat32x4(const BaseIndex & addr,FloatRegister dest)1208 void loadUnalignedFloat32x4(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } storeUnalignedFloat32x4(FloatRegister src,Address addr)1209 void storeUnalignedFloat32x4(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); } storeUnalignedFloat32x4(FloatRegister src,BaseIndex addr)1210 void storeUnalignedFloat32x4(FloatRegister src, BaseIndex addr) { MOZ_CRASH("NYI"); } 1211 1212 void loadDouble(const Address& addr, FloatRegister dest); 1213 void loadDouble(const BaseIndex& src, FloatRegister dest); 1214 1215 // Load a float value into a register, then expand it to a double. 1216 void loadFloatAsDouble(const Address& addr, FloatRegister dest); 1217 void loadFloatAsDouble(const BaseIndex& src, FloatRegister dest); 1218 1219 void loadFloat32(const Address& addr, FloatRegister dest); 1220 void loadFloat32(const BaseIndex& src, FloatRegister dest); 1221 1222 void store8(Register src, const Address& address); 1223 void store8(Imm32 imm, const Address& address); 1224 void store8(Register src, const BaseIndex& address); 1225 void store8(Imm32 imm, const BaseIndex& address); 1226 1227 void store16(Register src, const Address& address); 1228 void store16(Imm32 imm, const Address& address); 1229 void store16(Register src, const BaseIndex& address); 1230 void store16(Imm32 imm, const BaseIndex& address); 1231 1232 void store32(Register src, AbsoluteAddress address); 1233 void store32(Register src, const Address& address); 1234 void store32(Register src, const BaseIndex& address); 1235 void store32(Imm32 src, const Address& address); 1236 void store32(Imm32 src, const BaseIndex& address); 1237 1238 // NOTE: This will use second scratch on MIPS. Only ARM needs the 1239 // implementation without second scratch. store32_NoSecondScratch(Imm32 src,const Address & address)1240 void store32_NoSecondScratch(Imm32 src, const Address& address) { 1241 store32(src, address); 1242 } 1243 store64(Register64 src,Address address)1244 void store64(Register64 src, Address address) { 1245 store32(src.low, Address(address.base, address.offset + LOW_32_OFFSET)); 1246 store32(src.high, Address(address.base, address.offset + HIGH_32_OFFSET)); 1247 } 1248 1249 template <typename T> void storePtr(ImmWord imm, T address); 1250 template <typename T> void storePtr(ImmPtr imm, T address); 1251 template <typename T> void storePtr(ImmGCPtr imm, T address); 1252 void storePtr(Register src, const Address& address); 1253 void storePtr(Register src, const BaseIndex& address); 1254 void storePtr(Register src, AbsoluteAddress dest); storeDouble(FloatRegister src,Address addr)1255 void storeDouble(FloatRegister src, Address addr) { 1256 ma_sd(src, addr); 1257 } storeDouble(FloatRegister src,BaseIndex addr)1258 void storeDouble(FloatRegister src, BaseIndex addr) { 1259 MOZ_ASSERT(addr.offset == 0); 1260 ma_sd(src, addr); 1261 } moveDouble(FloatRegister src,FloatRegister dest)1262 void moveDouble(FloatRegister src, FloatRegister dest) { 1263 as_movd(dest, src); 1264 } 1265 storeFloat32(FloatRegister src,Address addr)1266 void storeFloat32(FloatRegister src, Address addr) { 1267 ma_ss(src, addr); 1268 } storeFloat32(FloatRegister src,BaseIndex addr)1269 void storeFloat32(FloatRegister src, BaseIndex addr) { 1270 MOZ_ASSERT(addr.offset == 0); 1271 ma_ss(src, addr); 1272 } 1273 zeroDouble(FloatRegister reg)1274 void zeroDouble(FloatRegister reg) { 1275 moveToDoubleLo(zero, reg); 1276 moveToDoubleHi(zero, reg); 1277 } 1278 1279 void clampIntToUint8(Register reg); 1280 1281 void subPtr(Imm32 imm, const Register dest); 1282 void subPtr(const Address& addr, const Register dest); 1283 void subPtr(Register src, const Address& dest); 1284 void addPtr(Imm32 imm, const Register dest); 1285 void addPtr(Imm32 imm, const Address& dest); addPtr(ImmWord imm,const Register dest)1286 void addPtr(ImmWord imm, const Register dest) { 1287 addPtr(Imm32(imm.value), dest); 1288 } addPtr(ImmPtr imm,const Register dest)1289 void addPtr(ImmPtr imm, const Register dest) { 1290 addPtr(ImmWord(uintptr_t(imm.value)), dest); 1291 } mulBy3(const Register & src,const Register & dest)1292 void mulBy3(const Register& src, const Register& dest) { 1293 as_addu(dest, src, src); 1294 as_addu(dest, dest, src); 1295 } 1296 1297 void mul64(Imm64 imm, const Register64& dest); 1298 1299 void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest); mulDoublePtr(ImmPtr imm,Register temp,FloatRegister dest)1300 void mulDoublePtr(ImmPtr imm, Register temp, FloatRegister dest) { 1301 movePtr(imm, ScratchRegister); 1302 loadDouble(Address(ScratchRegister, 0), ScratchDoubleReg); 1303 mulDouble(ScratchDoubleReg, dest); 1304 } 1305 1306 void breakpoint(); 1307 1308 void branchDouble(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs, 1309 Label* label); 1310 1311 void branchFloat(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs, 1312 Label* label); 1313 1314 void checkStackAlignment(); 1315 1316 void alignStackPointer(); 1317 void restoreStackPointer(); 1318 static void calculateAlignedStackPointer(void** stackPointer); 1319 1320 // If source is a double, load it into dest. If source is int32, 1321 // convert it to double. Else, branch to failure. 1322 void ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure); 1323 1324 template <typename T1, typename T2> cmpPtrSet(Assembler::Condition cond,T1 lhs,T2 rhs,Register dest)1325 void cmpPtrSet(Assembler::Condition cond, T1 lhs, T2 rhs, Register dest) 1326 { 1327 ma_cmp_set(dest, lhs, rhs, cond); 1328 } 1329 1330 template <typename T1, typename T2> cmp32Set(Assembler::Condition cond,T1 lhs,T2 rhs,Register dest)1331 void cmp32Set(Assembler::Condition cond, T1 lhs, T2 rhs, Register dest) 1332 { 1333 ma_cmp_set(dest, lhs, rhs, cond); 1334 } 1335 1336 protected: 1337 bool buildOOLFakeExitFrame(void* fakeReturnAddr); 1338 1339 public: labelForPatch()1340 CodeOffset labelForPatch() { 1341 return CodeOffset(nextOffset().getOffset()); 1342 } 1343 memIntToValue(Address Source,Address Dest)1344 void memIntToValue(Address Source, Address Dest) { 1345 load32(Source, ScratchRegister); 1346 storeValue(JSVAL_TYPE_INT32, ScratchRegister, Dest); 1347 } 1348 lea(Operand addr,Register dest)1349 void lea(Operand addr, Register dest) { 1350 ma_addu(dest, addr.baseReg(), Imm32(addr.disp())); 1351 } 1352 abiret()1353 void abiret() { 1354 as_jr(ra); 1355 as_nop(); 1356 } 1357 ma_storeImm(Imm32 imm,const Address & addr)1358 void ma_storeImm(Imm32 imm, const Address& addr) { 1359 ma_sw(imm, addr); 1360 } 1361 ma_BoundsCheck(Register bounded)1362 BufferOffset ma_BoundsCheck(Register bounded) { 1363 BufferOffset bo = m_buffer.nextOffset(); 1364 ma_liPatchable(bounded, ImmWord(0)); 1365 return bo; 1366 } 1367 moveFloat32(FloatRegister src,FloatRegister dest)1368 void moveFloat32(FloatRegister src, FloatRegister dest) { 1369 as_movs(dest, src); 1370 } 1371 1372 void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label* label); 1373 void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, 1374 Label* label); 1375 loadAsmJSActivation(Register dest)1376 void loadAsmJSActivation(Register dest) { 1377 loadPtr(Address(GlobalReg, wasm::ActivationGlobalDataOffset - AsmJSGlobalRegBias), dest); 1378 } loadAsmJSHeapRegisterFromGlobalData()1379 void loadAsmJSHeapRegisterFromGlobalData() { 1380 MOZ_ASSERT(Imm16::IsInSignedRange(wasm::HeapGlobalDataOffset - AsmJSGlobalRegBias)); 1381 loadPtr(Address(GlobalReg, wasm::HeapGlobalDataOffset - AsmJSGlobalRegBias), HeapReg); 1382 } 1383 1384 // Instrumentation for entering and leaving the profiler. 1385 void profilerEnterFrame(Register framePtr, Register scratch); 1386 void profilerExitFrame(); 1387 }; 1388 1389 typedef MacroAssemblerMIPSCompat MacroAssemblerSpecific; 1390 1391 } // namespace jit 1392 } // namespace js 1393 1394 #endif /* jit_mips32_MacroAssembler_mips32_h */ 1395