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