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_arm_MacroAssembler_arm_h 8 #define jit_arm_MacroAssembler_arm_h 9 10 #include "mozilla/DebugOnly.h" 11 12 #include "jsopcode.h" 13 14 #include "jit/arm/Assembler-arm.h" 15 #include "jit/AtomicOp.h" 16 #include "jit/IonCaches.h" 17 #include "jit/JitFrames.h" 18 #include "jit/MoveResolver.h" 19 20 using mozilla::DebugOnly; 21 22 namespace js { 23 namespace jit { 24 25 static Register CallReg = ip; 26 static const int defaultShift = 3; 27 JS_STATIC_ASSERT(1 << defaultShift == sizeof(JS::Value)); 28 29 // MacroAssemblerARM is inheriting form Assembler defined in 30 // Assembler-arm.{h,cpp} 31 class MacroAssemblerARM : public Assembler 32 { 33 private: 34 // Perform a downcast. Should be removed by Bug 996602. 35 MacroAssembler& asMasm(); 36 const MacroAssembler& asMasm() const; 37 38 protected: 39 // On ARM, some instructions require a second scratch register. This 40 // register defaults to lr, since it's non-allocatable (as it can be 41 // clobbered by some instructions). Allow the baseline compiler to override 42 // this though, since baseline IC stubs rely on lr holding the return 43 // address. 44 Register secondScratchReg_; 45 46 public: 47 // Higher level tag testing code. 48 // TODO: Can probably remove the Operand versions. ToPayload(Operand base)49 Operand ToPayload(Operand base) const { 50 return Operand(Register::FromCode(base.base()), base.disp()); 51 } ToPayload(const Address & base)52 Address ToPayload(const Address& base) const { 53 return base; 54 } 55 56 protected: ToType(Operand base)57 Operand ToType(Operand base) const { 58 return Operand(Register::FromCode(base.base()), base.disp() + sizeof(void*)); 59 } ToType(const Address & base)60 Address ToType(const Address& base) const { 61 return ToType(Operand(base)).toAddress(); 62 } 63 ToPayloadAfterStackPush(const Address & base)64 Address ToPayloadAfterStackPush(const Address& base) const { 65 // If we are based on StackPointer, pass over the type tag just pushed. 66 if (base.base == StackPointer) 67 return Address(base.base, base.offset + sizeof(void *)); 68 return ToPayload(base); 69 } 70 71 public: MacroAssemblerARM()72 MacroAssemblerARM() 73 : secondScratchReg_(lr) 74 { } 75 setSecondScratchReg(Register reg)76 void setSecondScratchReg(Register reg) { 77 MOZ_ASSERT(reg != ScratchRegister); 78 secondScratchReg_ = reg; 79 } 80 81 void convertBoolToInt32(Register source, Register dest); 82 void convertInt32ToDouble(Register src, FloatRegister dest); 83 void convertInt32ToDouble(const Address& src, FloatRegister dest); 84 void convertInt32ToDouble(const BaseIndex& src, FloatRegister dest); 85 void convertUInt32ToFloat32(Register src, FloatRegister dest); 86 void convertUInt32ToDouble(Register src, FloatRegister dest); 87 void convertDoubleToFloat32(FloatRegister src, FloatRegister dest, 88 Condition c = Always); 89 void branchTruncateDouble(FloatRegister src, Register dest, Label* fail); 90 void convertDoubleToInt32(FloatRegister src, Register dest, Label* fail, 91 bool negativeZeroCheck = true); 92 void convertFloat32ToInt32(FloatRegister src, Register dest, Label* fail, 93 bool negativeZeroCheck = true); 94 95 void convertFloat32ToDouble(FloatRegister src, FloatRegister dest); 96 void branchTruncateFloat32(FloatRegister src, Register dest, Label* fail); 97 void convertInt32ToFloat32(Register src, FloatRegister dest); 98 void convertInt32ToFloat32(const Address& src, FloatRegister dest); 99 100 void addDouble(FloatRegister src, FloatRegister dest); 101 void subDouble(FloatRegister src, FloatRegister dest); 102 void mulDouble(FloatRegister src, FloatRegister dest); 103 void divDouble(FloatRegister src, FloatRegister dest); 104 105 void negateDouble(FloatRegister reg); 106 void inc64(AbsoluteAddress dest); 107 108 // Somewhat direct wrappers for the low-level assembler funcitons 109 // bitops. Attempt to encode a virtual alu instruction using two real 110 // instructions. 111 private: 112 bool alu_dbl(Register src1, Imm32 imm, Register dest, ALUOp op, 113 SBit s, Condition c); 114 115 public: 116 void ma_alu(Register src1, Operand2 op2, Register dest, ALUOp op, 117 SBit s = LeaveCC, Condition c = Always); 118 void ma_alu(Register src1, Imm32 imm, Register dest, 119 ALUOp op, 120 SBit s = LeaveCC, Condition c = Always); 121 122 void ma_alu(Register src1, Operand op2, Register dest, ALUOp op, 123 SBit s = LeaveCC, Condition c = Always); 124 void ma_nop(); 125 126 void ma_movPatchable(Imm32 imm, Register dest, Assembler::Condition c, 127 RelocStyle rs); 128 void ma_movPatchable(ImmPtr imm, Register dest, Assembler::Condition c, 129 RelocStyle rs); 130 131 static void ma_mov_patch(Imm32 imm, Register dest, Assembler::Condition c, 132 RelocStyle rs, Instruction* i); 133 static void ma_mov_patch(ImmPtr imm, Register dest, Assembler::Condition c, 134 RelocStyle rs, Instruction* i); 135 136 // These should likely be wrapped up as a set of macros or something like 137 // that. I cannot think of a good reason to explicitly have all of this 138 // code. 139 140 // ALU based ops 141 // mov 142 void ma_mov(Register src, Register dest, 143 SBit s = LeaveCC, Condition c = Always); 144 145 void ma_mov(Imm32 imm, Register dest, 146 SBit s = LeaveCC, Condition c = Always); 147 void ma_mov(ImmWord imm, Register dest, 148 SBit s = LeaveCC, Condition c = Always); 149 150 void ma_mov(ImmGCPtr ptr, Register dest); 151 152 // Shifts (just a move with a shifting op2) 153 void ma_lsl(Imm32 shift, Register src, Register dst); 154 void ma_lsr(Imm32 shift, Register src, Register dst); 155 void ma_asr(Imm32 shift, Register src, Register dst); 156 void ma_ror(Imm32 shift, Register src, Register dst); 157 void ma_rol(Imm32 shift, Register src, Register dst); 158 // Shifts (just a move with a shifting op2) 159 void ma_lsl(Register shift, Register src, Register dst); 160 void ma_lsr(Register shift, Register src, Register dst); 161 void ma_asr(Register shift, Register src, Register dst); 162 void ma_ror(Register shift, Register src, Register dst); 163 void ma_rol(Register shift, Register src, Register dst); 164 165 // Move not (dest <- ~src) 166 void ma_mvn(Imm32 imm, Register dest, 167 SBit s = LeaveCC, Condition c = Always); 168 169 170 void ma_mvn(Register src1, Register dest, 171 SBit s = LeaveCC, Condition c = Always); 172 173 // Negate (dest <- -src) implemented as rsb dest, src, 0 174 void ma_neg(Register src, Register dest, 175 SBit s = LeaveCC, Condition c = Always); 176 177 // And 178 void ma_and(Register src, Register dest, 179 SBit s = LeaveCC, Condition c = Always); 180 181 void ma_and(Register src1, Register src2, Register dest, 182 SBit s = LeaveCC, Condition c = Always); 183 184 void ma_and(Imm32 imm, Register dest, 185 SBit s = LeaveCC, Condition c = Always); 186 187 void ma_and(Imm32 imm, Register src1, Register dest, 188 SBit s = LeaveCC, Condition c = Always); 189 190 191 192 // Bit clear (dest <- dest & ~imm) or (dest <- src1 & ~src2) 193 void ma_bic(Imm32 imm, Register dest, 194 SBit s = LeaveCC, Condition c = Always); 195 196 // Exclusive or 197 void ma_eor(Register src, Register dest, 198 SBit s = LeaveCC, Condition c = Always); 199 200 void ma_eor(Register src1, Register src2, Register dest, 201 SBit s = LeaveCC, Condition c = Always); 202 203 void ma_eor(Imm32 imm, Register dest, 204 SBit s = LeaveCC, Condition c = Always); 205 206 void ma_eor(Imm32 imm, Register src1, Register dest, 207 SBit s = LeaveCC, Condition c = Always); 208 209 210 // Or 211 void ma_orr(Register src, Register dest, 212 SBit s = LeaveCC, Condition c = Always); 213 214 void ma_orr(Register src1, Register src2, Register dest, 215 SBit s = LeaveCC, Condition c = Always); 216 217 void ma_orr(Imm32 imm, Register dest, 218 SBit s = LeaveCC, Condition c = Always); 219 220 void ma_orr(Imm32 imm, Register src1, Register dest, 221 SBit s = LeaveCC, Condition c = Always); 222 223 224 // Arithmetic based ops. 225 // Add with carry: 226 void ma_adc(Imm32 imm, Register dest, SBit s = LeaveCC, Condition c = Always); 227 void ma_adc(Register src, Register dest, SBit s = LeaveCC, Condition c = Always); 228 void ma_adc(Register src1, Register src2, Register dest, SBit s = LeaveCC, Condition c = Always); 229 230 // Add: 231 void ma_add(Imm32 imm, Register dest, SBit s = LeaveCC, Condition c = Always); 232 void ma_add(Register src1, Register dest, SBit s = LeaveCC, Condition c = Always); 233 void ma_add(Register src1, Register src2, Register dest, SBit s = LeaveCC, Condition c = Always); 234 void ma_add(Register src1, Operand op, Register dest, SBit s = LeaveCC, Condition c = Always); 235 void ma_add(Register src1, Imm32 op, Register dest, SBit s = LeaveCC, Condition c = Always); 236 237 // Subtract with carry: 238 void ma_sbc(Imm32 imm, Register dest, SBit s = LeaveCC, Condition c = Always); 239 void ma_sbc(Register src1, Register dest, SBit s = LeaveCC, Condition c = Always); 240 void ma_sbc(Register src1, Register src2, Register dest, SBit s = LeaveCC, Condition c = Always); 241 242 // Subtract: 243 void ma_sub(Imm32 imm, Register dest, SBit s = LeaveCC, Condition c = Always); 244 void ma_sub(Register src1, Register dest, SBit s = LeaveCC, Condition c = Always); 245 void ma_sub(Register src1, Register src2, Register dest, SBit s = LeaveCC, Condition c = Always); 246 void ma_sub(Register src1, Operand op, Register dest, SBit s = LeaveCC, Condition c = Always); 247 void ma_sub(Register src1, Imm32 op, Register dest, SBit s = LeaveCC, Condition c = Always); 248 249 // Reverse subtract: 250 void ma_rsb(Imm32 imm, Register dest, SBit s = LeaveCC, Condition c = Always); 251 void ma_rsb(Register src1, Register dest, SBit s = LeaveCC, Condition c = Always); 252 void ma_rsb(Register src1, Register src2, Register dest, SBit s = LeaveCC, Condition c = Always); 253 void ma_rsb(Register src1, Imm32 op2, Register dest, SBit s = LeaveCC, Condition c = Always); 254 255 // Reverse subtract with carry: 256 void ma_rsc(Imm32 imm, Register dest, SBit s = LeaveCC, Condition c = Always); 257 void ma_rsc(Register src1, Register dest, SBit s = LeaveCC, Condition c = Always); 258 void ma_rsc(Register src1, Register src2, Register dest, SBit s = LeaveCC, Condition c = Always); 259 260 // Compares/tests. 261 // Compare negative (sets condition codes as src1 + src2 would): 262 void ma_cmn(Register src1, Imm32 imm, Condition c = Always); 263 void ma_cmn(Register src1, Register src2, Condition c = Always); 264 void ma_cmn(Register src1, Operand op, Condition c = Always); 265 266 // Compare (src - src2): 267 void ma_cmp(Register src1, Imm32 imm, Condition c = Always); 268 void ma_cmp(Register src1, ImmWord ptr, Condition c = Always); 269 void ma_cmp(Register src1, ImmGCPtr ptr, Condition c = Always); 270 void ma_cmp(Register src1, Operand op, Condition c = Always); 271 void ma_cmp(Register src1, Register src2, Condition c = Always); 272 273 274 // Test for equality, (src1 ^ src2): 275 void ma_teq(Register src1, Imm32 imm, Condition c = Always); 276 void ma_teq(Register src1, Register src2, Condition c = Always); 277 void ma_teq(Register src1, Operand op, Condition c = Always); 278 279 280 // Test (src1 & src2): 281 void ma_tst(Register src1, Imm32 imm, Condition c = Always); 282 void ma_tst(Register src1, Register src2, Condition c = Always); 283 void ma_tst(Register src1, Operand op, Condition c = Always); 284 285 // Multiplies. For now, there are only two that we care about. 286 void ma_mul(Register src1, Register src2, Register dest); 287 void ma_mul(Register src1, Imm32 imm, Register dest); 288 Condition ma_check_mul(Register src1, Register src2, Register dest, Condition cond); 289 Condition ma_check_mul(Register src1, Imm32 imm, Register dest, Condition cond); 290 291 // Fast mod, uses scratch registers, and thus needs to be in the assembler 292 // implicitly assumes that we can overwrite dest at the beginning of the 293 // sequence. 294 void ma_mod_mask(Register src, Register dest, Register hold, Register tmp, 295 int32_t shift); 296 297 // Mod - depends on integer divide instructions being supported. 298 void ma_smod(Register num, Register div, Register dest); 299 void ma_umod(Register num, Register div, Register dest); 300 301 // Division - depends on integer divide instructions being supported. 302 void ma_sdiv(Register num, Register div, Register dest, Condition cond = Always); 303 void ma_udiv(Register num, Register div, Register dest, Condition cond = Always); 304 // Misc operations 305 void ma_clz(Register src, Register dest, Condition cond = Always); 306 // Memory: 307 // Shortcut for when we know we're transferring 32 bits of data. 308 void ma_dtr(LoadStore ls, Register rn, Imm32 offset, Register rt, 309 Index mode = Offset, Condition cc = Always); 310 311 void ma_dtr(LoadStore ls, Register rn, Register rm, Register rt, 312 Index mode = Offset, Condition cc = Always); 313 314 315 void ma_str(Register rt, DTRAddr addr, Index mode = Offset, Condition cc = Always); 316 void ma_str(Register rt, const Address& addr, Index mode = Offset, Condition cc = Always); 317 void ma_dtr(LoadStore ls, Register rt, const Address& addr, Index mode, Condition cc); 318 319 void ma_ldr(DTRAddr addr, Register rt, Index mode = Offset, Condition cc = Always); 320 void ma_ldr(const Address& addr, Register rt, Index mode = Offset, Condition cc = Always); 321 322 void ma_ldrb(DTRAddr addr, Register rt, Index mode = Offset, Condition cc = Always); 323 void ma_ldrh(EDtrAddr addr, Register rt, Index mode = Offset, Condition cc = Always); 324 void ma_ldrsh(EDtrAddr addr, Register rt, Index mode = Offset, Condition cc = Always); 325 void ma_ldrsb(EDtrAddr addr, Register rt, Index mode = Offset, Condition cc = Always); 326 void ma_ldrd(EDtrAddr addr, Register rt, DebugOnly<Register> rt2, Index mode = Offset, Condition cc = Always); 327 void ma_strb(Register rt, DTRAddr addr, Index mode = Offset, Condition cc = Always); 328 void ma_strh(Register rt, EDtrAddr addr, Index mode = Offset, Condition cc = Always); 329 void ma_strd(Register rt, DebugOnly<Register> rt2, EDtrAddr addr, Index mode = Offset, Condition cc = Always); 330 // Specialty for moving N bits of data, where n == 8,16,32,64. 331 BufferOffset ma_dataTransferN(LoadStore ls, int size, bool IsSigned, 332 Register rn, Register rm, Register rt, 333 Index mode = Offset, Condition cc = Always, unsigned scale = TimesOne); 334 335 BufferOffset ma_dataTransferN(LoadStore ls, int size, bool IsSigned, 336 Register rn, Imm32 offset, Register rt, 337 Index mode = Offset, Condition cc = Always); 338 void ma_pop(Register r); 339 void ma_push(Register r); 340 341 void ma_vpop(VFPRegister r); 342 void ma_vpush(VFPRegister r); 343 344 // Barriers. 345 void ma_dmb(BarrierOption option=BarrierSY); 346 void ma_dsb(BarrierOption option=BarrierSY); 347 348 // Branches when done from within arm-specific code. 349 BufferOffset ma_b(Label* dest, Condition c = Always); 350 void ma_b(void* target, Condition c = Always); 351 void ma_bx(Register dest, Condition c = Always); 352 353 // This is almost NEVER necessary, we'll basically never be calling a label 354 // except, possibly in the crazy bailout-table case. 355 void ma_bl(Label* dest, Condition c = Always); 356 357 void ma_blx(Register dest, Condition c = Always); 358 359 // VFP/ALU: 360 void ma_vadd(FloatRegister src1, FloatRegister src2, FloatRegister dst); 361 void ma_vsub(FloatRegister src1, FloatRegister src2, FloatRegister dst); 362 363 void ma_vmul(FloatRegister src1, FloatRegister src2, FloatRegister dst); 364 void ma_vdiv(FloatRegister src1, FloatRegister src2, FloatRegister dst); 365 366 void ma_vneg(FloatRegister src, FloatRegister dest, Condition cc = Always); 367 void ma_vmov(FloatRegister src, FloatRegister dest, Condition cc = Always); 368 void ma_vmov_f32(FloatRegister src, FloatRegister dest, Condition cc = Always); 369 void ma_vabs(FloatRegister src, FloatRegister dest, Condition cc = Always); 370 void ma_vabs_f32(FloatRegister src, FloatRegister dest, Condition cc = Always); 371 372 void ma_vsqrt(FloatRegister src, FloatRegister dest, Condition cc = Always); 373 void ma_vsqrt_f32(FloatRegister src, FloatRegister dest, Condition cc = Always); 374 375 void ma_vimm(double value, FloatRegister dest, Condition cc = Always); 376 void ma_vimm_f32(float value, FloatRegister dest, Condition cc = Always); 377 378 void ma_vcmp(FloatRegister src1, FloatRegister src2, Condition cc = Always); 379 void ma_vcmp_f32(FloatRegister src1, FloatRegister src2, Condition cc = Always); 380 void ma_vcmpz(FloatRegister src1, Condition cc = Always); 381 void ma_vcmpz_f32(FloatRegister src1, Condition cc = Always); 382 383 void ma_vadd_f32(FloatRegister src1, FloatRegister src2, FloatRegister dst); 384 void ma_vsub_f32(FloatRegister src1, FloatRegister src2, FloatRegister dst); 385 386 void ma_vmul_f32(FloatRegister src1, FloatRegister src2, FloatRegister dst); 387 void ma_vdiv_f32(FloatRegister src1, FloatRegister src2, FloatRegister dst); 388 389 void ma_vneg_f32(FloatRegister src, FloatRegister dest, Condition cc = Always); 390 391 // Source is F64, dest is I32: 392 void ma_vcvt_F64_I32(FloatRegister src, FloatRegister dest, Condition cc = Always); 393 void ma_vcvt_F64_U32(FloatRegister src, FloatRegister dest, Condition cc = Always); 394 395 // Source is I32, dest is F64: 396 void ma_vcvt_I32_F64(FloatRegister src, FloatRegister dest, Condition cc = Always); 397 void ma_vcvt_U32_F64(FloatRegister src, FloatRegister dest, Condition cc = Always); 398 399 // Source is F32, dest is I32: 400 void ma_vcvt_F32_I32(FloatRegister src, FloatRegister dest, Condition cc = Always); 401 void ma_vcvt_F32_U32(FloatRegister src, FloatRegister dest, Condition cc = Always); 402 403 // Source is I32, dest is F32: 404 void ma_vcvt_I32_F32(FloatRegister src, FloatRegister dest, Condition cc = Always); 405 void ma_vcvt_U32_F32(FloatRegister src, FloatRegister dest, Condition cc = Always); 406 407 408 // Transfer (do not coerce) a float into a gpr. 409 void ma_vxfer(VFPRegister src, Register dest, Condition cc = Always); 410 // Transfer (do not coerce) a double into a couple of gpr. 411 void ma_vxfer(VFPRegister src, Register dest1, Register dest2, Condition cc = Always); 412 413 // Transfer (do not coerce) a gpr into a float 414 void ma_vxfer(Register src, FloatRegister dest, Condition cc = Always); 415 // Transfer (do not coerce) a couple of gpr into a double 416 void ma_vxfer(Register src1, Register src2, FloatRegister dest, Condition cc = Always); 417 418 BufferOffset ma_vdtr(LoadStore ls, const Address& addr, VFPRegister dest, Condition cc = Always); 419 420 421 BufferOffset ma_vldr(VFPAddr addr, VFPRegister dest, Condition cc = Always); 422 BufferOffset ma_vldr(const Address& addr, VFPRegister dest, Condition cc = Always); 423 BufferOffset ma_vldr(VFPRegister src, Register base, Register index, int32_t shift = defaultShift, Condition cc = Always); 424 425 BufferOffset ma_vstr(VFPRegister src, VFPAddr addr, Condition cc = Always); 426 BufferOffset ma_vstr(VFPRegister src, const Address& addr, Condition cc = Always); 427 428 BufferOffset ma_vstr(VFPRegister src, Register base, Register index, int32_t shift, 429 int32_t offset, Condition cc = Always); 430 431 void ma_call(ImmPtr dest); 432 433 // Float registers can only be loaded/stored in continuous runs when using 434 // vstm/vldm. This function breaks set into continuous runs and loads/stores 435 // them at [rm]. rm will be modified and left in a state logically suitable 436 // for the next load/store. Returns the offset from [dm] for the logical 437 // next load/store. transferMultipleByRuns(FloatRegisterSet set,LoadStore ls,Register rm,DTMMode mode)438 int32_t transferMultipleByRuns(FloatRegisterSet set, LoadStore ls, 439 Register rm, DTMMode mode) 440 { 441 if (mode == IA) { 442 return transferMultipleByRunsImpl 443 <FloatRegisterForwardIterator>(set, ls, rm, mode, 1); 444 } 445 if (mode == DB) { 446 return transferMultipleByRunsImpl 447 <FloatRegisterBackwardIterator>(set, ls, rm, mode, -1); 448 } 449 MOZ_CRASH("Invalid data transfer addressing mode"); 450 } 451 452 private: 453 // Implementation for transferMultipleByRuns so we can use different 454 // iterators for forward/backward traversals. The sign argument should be 1 455 // if we traverse forwards, -1 if we traverse backwards. 456 template<typename RegisterIterator> int32_t transferMultipleByRunsImpl(FloatRegisterSet set,LoadStore ls,Register rm,DTMMode mode,int32_t sign)457 transferMultipleByRunsImpl(FloatRegisterSet set, LoadStore ls, 458 Register rm, DTMMode mode, int32_t sign) 459 { 460 MOZ_ASSERT(sign == 1 || sign == -1); 461 462 int32_t delta = sign * sizeof(float); 463 int32_t offset = 0; 464 // Build up a new set, which is the sum of all of the single and double 465 // registers. This set can have up to 48 registers in it total 466 // s0-s31 and d16-d31 467 FloatRegisterSet mod = set.reduceSetForPush(); 468 469 RegisterIterator iter(mod); 470 while (iter.more()) { 471 startFloatTransferM(ls, rm, mode, WriteBack); 472 int32_t reg = (*iter).code(); 473 do { 474 offset += delta; 475 if ((*iter).isDouble()) 476 offset += delta; 477 transferFloatReg(*iter); 478 } while ((++iter).more() && int32_t((*iter).code()) == (reg += sign)); 479 finishFloatTransfer(); 480 } 481 return offset; 482 } 483 }; 484 485 class MacroAssembler; 486 487 class MacroAssemblerARMCompat : public MacroAssemblerARM 488 { 489 private: 490 // Perform a downcast. Should be removed by Bug 996602. 491 MacroAssembler& asMasm(); 492 const MacroAssembler& asMasm() const; 493 494 public: MacroAssemblerARMCompat()495 MacroAssemblerARMCompat() 496 { } 497 498 public: 499 500 // Jumps + other functions that should be called from non-arm specific 501 // code. Basically, an x86 front end on top of the ARM code. j(Condition code,Label * dest)502 void j(Condition code , Label* dest) 503 { 504 as_b(dest, code); 505 } j(Label * dest)506 void j(Label* dest) 507 { 508 as_b(dest, Always); 509 } 510 mov(Register src,Register dest)511 void mov(Register src, Register dest) { 512 ma_mov(src, dest); 513 } mov(ImmWord imm,Register dest)514 void mov(ImmWord imm, Register dest) { 515 ma_mov(Imm32(imm.value), dest); 516 } mov(ImmPtr imm,Register dest)517 void mov(ImmPtr imm, Register dest) { 518 mov(ImmWord(uintptr_t(imm.value)), dest); 519 } mov(Register src,Address dest)520 void mov(Register src, Address dest) { 521 MOZ_CRASH("NYI-IC"); 522 } mov(Address src,Register dest)523 void mov(Address src, Register dest) { 524 MOZ_CRASH("NYI-IC"); 525 } 526 branch(JitCode * c)527 void branch(JitCode* c) { 528 BufferOffset bo = m_buffer.nextOffset(); 529 addPendingJump(bo, ImmPtr(c->raw()), Relocation::JITCODE); 530 RelocStyle rs; 531 if (HasMOVWT()) 532 rs = L_MOVWT; 533 else 534 rs = L_LDR; 535 536 ScratchRegisterScope scratch(asMasm()); 537 ma_movPatchable(ImmPtr(c->raw()), scratch, Always, rs); 538 ma_bx(scratch); 539 } branch(const Register reg)540 void branch(const Register reg) { 541 ma_bx(reg); 542 } nop()543 void nop() { 544 ma_nop(); 545 } shortJumpSizedNop()546 void shortJumpSizedNop() { 547 ma_nop(); 548 } ret()549 void ret() { 550 ma_pop(pc); 551 } retn(Imm32 n)552 void retn(Imm32 n) { 553 // pc <- [sp]; sp += n 554 ma_dtr(IsLoad, sp, n, pc, PostIndex); 555 } push(Imm32 imm)556 void push(Imm32 imm) { 557 ScratchRegisterScope scratch(asMasm()); 558 ma_mov(imm, scratch); 559 ma_push(scratch); 560 } push(ImmWord imm)561 void push(ImmWord imm) { 562 push(Imm32(imm.value)); 563 } push(ImmGCPtr imm)564 void push(ImmGCPtr imm) { 565 ScratchRegisterScope scratch(asMasm()); 566 ma_mov(imm, scratch); 567 ma_push(scratch); 568 } push(const Address & addr)569 void push(const Address& addr) { 570 ScratchRegisterScope scratch(asMasm()); 571 ma_ldr(addr, scratch); 572 ma_push(scratch); 573 } push(Register reg)574 void push(Register reg) { 575 ma_push(reg); 576 } push(FloatRegister reg)577 void push(FloatRegister reg) { 578 ma_vpush(VFPRegister(reg)); 579 } pushWithPadding(Register reg,const Imm32 extraSpace)580 void pushWithPadding(Register reg, const Imm32 extraSpace) { 581 Imm32 totSpace = Imm32(extraSpace.value + 4); 582 ma_dtr(IsStore, sp, totSpace, reg, PreIndex); 583 } pushWithPadding(Imm32 imm,const Imm32 extraSpace)584 void pushWithPadding(Imm32 imm, const Imm32 extraSpace) { 585 AutoRegisterScope scratch2(asMasm(), secondScratchReg_); 586 Imm32 totSpace = Imm32(extraSpace.value + 4); 587 // ma_dtr may need the scratch register to adjust the stack, so use the 588 // second scratch register. 589 ma_mov(imm, scratch2); 590 ma_dtr(IsStore, sp, totSpace, scratch2, PreIndex); 591 } 592 pop(Register reg)593 void pop(Register reg) { 594 ma_pop(reg); 595 } pop(FloatRegister reg)596 void pop(FloatRegister reg) { 597 ma_vpop(VFPRegister(reg)); 598 } 599 popN(Register reg,Imm32 extraSpace)600 void popN(Register reg, Imm32 extraSpace) { 601 Imm32 totSpace = Imm32(extraSpace.value + 4); 602 ma_dtr(IsLoad, sp, totSpace, reg, PostIndex); 603 } 604 605 CodeOffset toggledJump(Label* label); 606 607 // Emit a BLX or NOP instruction. ToggleCall can be used to patch this 608 // instruction. 609 CodeOffset toggledCall(JitCode* target, bool enabled); 610 pushWithPatch(ImmWord imm)611 CodeOffset pushWithPatch(ImmWord imm) { 612 ScratchRegisterScope scratch(asMasm()); 613 CodeOffset label = movWithPatch(imm, scratch); 614 ma_push(scratch); 615 return label; 616 } 617 movWithPatch(ImmWord imm,Register dest)618 CodeOffset movWithPatch(ImmWord imm, Register dest) { 619 CodeOffset label = CodeOffset(currentOffset()); 620 ma_movPatchable(Imm32(imm.value), dest, Always, HasMOVWT() ? L_MOVWT : L_LDR); 621 return label; 622 } movWithPatch(ImmPtr imm,Register dest)623 CodeOffset movWithPatch(ImmPtr imm, Register dest) { 624 return movWithPatch(ImmWord(uintptr_t(imm.value)), dest); 625 } 626 jump(Label * label)627 void jump(Label* label) { 628 as_b(label); 629 } jump(JitCode * code)630 void jump(JitCode* code) { 631 branch(code); 632 } jump(Register reg)633 void jump(Register reg) { 634 ma_bx(reg); 635 } jump(const Address & addr)636 void jump(const Address& addr) { 637 ScratchRegisterScope scratch(asMasm()); 638 ma_ldr(addr, scratch); 639 ma_bx(scratch); 640 } 641 neg32(Register reg)642 void neg32(Register reg) { 643 ma_neg(reg, reg, SetCC); 644 } negl(Register reg)645 void negl(Register reg) { 646 ma_neg(reg, reg, SetCC); 647 } test32(Register lhs,Register rhs)648 void test32(Register lhs, Register rhs) { 649 ma_tst(lhs, rhs); 650 } test32(Register lhs,Imm32 imm)651 void test32(Register lhs, Imm32 imm) { 652 ma_tst(lhs, imm); 653 } test32(const Address & addr,Imm32 imm)654 void test32(const Address& addr, Imm32 imm) { 655 ScratchRegisterScope scratch(asMasm()); 656 ma_ldr(addr, scratch); 657 ma_tst(scratch, imm); 658 } testPtr(Register lhs,Register rhs)659 void testPtr(Register lhs, Register rhs) { 660 test32(lhs, rhs); 661 } 662 663 // Returns the register containing the type tag. splitTagForTest(const ValueOperand & value)664 Register splitTagForTest(const ValueOperand& value) { 665 return value.typeReg(); 666 } 667 668 // Higher level tag testing code. 669 Condition testInt32(Condition cond, const ValueOperand& value); 670 Condition testBoolean(Condition cond, const ValueOperand& value); 671 Condition testDouble(Condition cond, const ValueOperand& value); 672 Condition testNull(Condition cond, const ValueOperand& value); 673 Condition testUndefined(Condition cond, const ValueOperand& value); 674 Condition testString(Condition cond, const ValueOperand& value); 675 Condition testSymbol(Condition cond, const ValueOperand& value); 676 Condition testObject(Condition cond, const ValueOperand& value); 677 Condition testNumber(Condition cond, const ValueOperand& value); 678 Condition testMagic(Condition cond, const ValueOperand& value); 679 680 Condition testPrimitive(Condition cond, const ValueOperand& value); 681 682 // Register-based tests. 683 Condition testInt32(Condition cond, Register tag); 684 Condition testBoolean(Condition cond, Register tag); 685 Condition testNull(Condition cond, Register tag); 686 Condition testUndefined(Condition cond, Register tag); 687 Condition testString(Condition cond, Register tag); 688 Condition testSymbol(Condition cond, Register tag); 689 Condition testObject(Condition cond, Register tag); 690 Condition testDouble(Condition cond, Register tag); 691 Condition testNumber(Condition cond, Register tag); 692 Condition testMagic(Condition cond, Register tag); 693 Condition testPrimitive(Condition cond, Register tag); 694 695 Condition testGCThing(Condition cond, const Address& address); 696 Condition testMagic(Condition cond, const Address& address); 697 Condition testInt32(Condition cond, const Address& address); 698 Condition testDouble(Condition cond, const Address& address); 699 Condition testBoolean(Condition cond, const Address& address); 700 Condition testNull(Condition cond, const Address& address); 701 Condition testUndefined(Condition cond, const Address& address); 702 Condition testString(Condition cond, const Address& address); 703 Condition testSymbol(Condition cond, const Address& address); 704 Condition testObject(Condition cond, const Address& address); 705 Condition testNumber(Condition cond, const Address& address); 706 707 Condition testUndefined(Condition cond, const BaseIndex& src); 708 Condition testNull(Condition cond, const BaseIndex& src); 709 Condition testBoolean(Condition cond, const BaseIndex& src); 710 Condition testString(Condition cond, const BaseIndex& src); 711 Condition testSymbol(Condition cond, const BaseIndex& src); 712 Condition testInt32(Condition cond, const BaseIndex& src); 713 Condition testObject(Condition cond, const BaseIndex& src); 714 Condition testDouble(Condition cond, const BaseIndex& src); 715 Condition testMagic(Condition cond, const BaseIndex& src); 716 Condition testGCThing(Condition cond, const BaseIndex& src); 717 718 template <typename T> branchTestGCThing(Condition cond,const T & t,Label * label)719 void branchTestGCThing(Condition cond, const T& t, Label* label) { 720 Condition c = testGCThing(cond, t); 721 ma_b(label, c); 722 } 723 template <typename T> branchTestPrimitive(Condition cond,const T & t,Label * label)724 void branchTestPrimitive(Condition cond, const T& t, Label* label) { 725 Condition c = testPrimitive(cond, t); 726 ma_b(label, c); 727 } 728 729 void branchTestValue(Condition cond, const ValueOperand& value, const Value& v, Label* label); 730 void branchTestValue(Condition cond, const Address& valaddr, const ValueOperand& value, 731 Label* label); 732 733 // Unboxing code. 734 void unboxNonDouble(const ValueOperand& operand, Register dest); 735 void unboxNonDouble(const Address& src, Register dest); 736 void unboxNonDouble(const BaseIndex& src, Register dest); unboxInt32(const ValueOperand & src,Register dest)737 void unboxInt32(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); } unboxInt32(const Address & src,Register dest)738 void unboxInt32(const Address& src, Register dest) { unboxNonDouble(src, dest); } unboxBoolean(const ValueOperand & src,Register dest)739 void unboxBoolean(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); } unboxBoolean(const Address & src,Register dest)740 void unboxBoolean(const Address& src, Register dest) { unboxNonDouble(src, dest); } unboxString(const ValueOperand & src,Register dest)741 void unboxString(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); } unboxString(const Address & src,Register dest)742 void unboxString(const Address& src, Register dest) { unboxNonDouble(src, dest); } unboxSymbol(const ValueOperand & src,Register dest)743 void unboxSymbol(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); } unboxSymbol(const Address & src,Register dest)744 void unboxSymbol(const Address& src, Register dest) { unboxNonDouble(src, dest); } unboxObject(const ValueOperand & src,Register dest)745 void unboxObject(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); } unboxObject(const Address & src,Register dest)746 void unboxObject(const Address& src, Register dest) { unboxNonDouble(src, dest); } unboxObject(const BaseIndex & src,Register dest)747 void unboxObject(const BaseIndex& src, Register dest) { unboxNonDouble(src, dest); } 748 void unboxDouble(const ValueOperand& src, FloatRegister dest); 749 void unboxDouble(const Address& src, FloatRegister dest); 750 void unboxValue(const ValueOperand& src, AnyRegister dest); 751 void unboxPrivate(const ValueOperand& src, Register dest); 752 notBoolean(const ValueOperand & val)753 void notBoolean(const ValueOperand& val) { 754 ma_eor(Imm32(1), val.payloadReg()); 755 } 756 757 // Boxing code. 758 void boxDouble(FloatRegister src, const ValueOperand& dest); 759 void boxNonDouble(JSValueType type, Register src, const ValueOperand& dest); 760 761 // Extended unboxing API. If the payload is already in a register, returns 762 // that register. Otherwise, provides a move to the given scratch register, 763 // and returns that. 764 Register extractObject(const Address& address, Register scratch); extractObject(const ValueOperand & value,Register scratch)765 Register extractObject(const ValueOperand& value, Register scratch) { 766 return value.payloadReg(); 767 } extractInt32(const ValueOperand & value,Register scratch)768 Register extractInt32(const ValueOperand& value, Register scratch) { 769 return value.payloadReg(); 770 } extractBoolean(const ValueOperand & value,Register scratch)771 Register extractBoolean(const ValueOperand& value, Register scratch) { 772 return value.payloadReg(); 773 } 774 Register extractTag(const Address& address, Register scratch); 775 Register extractTag(const BaseIndex& address, Register scratch); extractTag(const ValueOperand & value,Register scratch)776 Register extractTag(const ValueOperand& value, Register scratch) { 777 return value.typeReg(); 778 } 779 780 void boolValueToDouble(const ValueOperand& operand, FloatRegister dest); 781 void int32ValueToDouble(const ValueOperand& operand, FloatRegister dest); 782 void loadInt32OrDouble(const Address& src, FloatRegister dest); 783 void loadInt32OrDouble(Register base, Register index, 784 FloatRegister dest, int32_t shift = defaultShift); 785 void loadConstantDouble(double dp, FloatRegister dest); 786 // Treat the value as a boolean, and set condition codes accordingly. 787 Condition testInt32Truthy(bool truthy, const ValueOperand& operand); 788 Condition testBooleanTruthy(bool truthy, const ValueOperand& operand); 789 Condition testDoubleTruthy(bool truthy, FloatRegister reg); 790 Condition testStringTruthy(bool truthy, const ValueOperand& value); 791 792 void boolValueToFloat32(const ValueOperand& operand, FloatRegister dest); 793 void int32ValueToFloat32(const ValueOperand& operand, FloatRegister dest); 794 void loadConstantFloat32(float f, FloatRegister dest); 795 796 template<typename T> branchTestInt32(Condition cond,const T & t,Label * label)797 void branchTestInt32(Condition cond, const T & t, Label* label) { 798 Condition c = testInt32(cond, t); 799 ma_b(label, c); 800 } 801 template<typename T> branchTestBoolean(Condition cond,const T & t,Label * label)802 void branchTestBoolean(Condition cond, const T & t, Label* label) { 803 Condition c = testBoolean(cond, t); 804 ma_b(label, c); 805 } branch32(Condition cond,Register lhs,Register rhs,Label * label)806 void branch32(Condition cond, Register lhs, Register rhs, Label* label) { 807 ma_cmp(lhs, rhs); 808 ma_b(label, cond); 809 } branch32(Condition cond,Register lhs,Imm32 imm,Label * label)810 void branch32(Condition cond, Register lhs, Imm32 imm, Label* label) { 811 ma_cmp(lhs, imm); 812 ma_b(label, cond); 813 } branch32(Condition cond,const Operand & lhs,Register rhs,Label * label)814 void branch32(Condition cond, const Operand& lhs, Register rhs, Label* label) { 815 if (lhs.getTag() == Operand::OP2) { 816 branch32(cond, lhs.toReg(), rhs, label); 817 } else { 818 ScratchRegisterScope scratch(asMasm()); 819 ma_ldr(lhs.toAddress(), scratch); 820 branch32(cond, scratch, rhs, label); 821 } 822 } branch32(Condition cond,const Operand & lhs,Imm32 rhs,Label * label)823 void branch32(Condition cond, const Operand& lhs, Imm32 rhs, Label* label) { 824 if (lhs.getTag() == Operand::OP2) { 825 branch32(cond, lhs.toReg(), rhs, label); 826 } else { 827 // branch32 will use ScratchRegister. 828 AutoRegisterScope scratch(asMasm(), secondScratchReg_); 829 ma_ldr(lhs.toAddress(), scratch); 830 branch32(cond, scratch, rhs, label); 831 } 832 } branch32(Condition cond,const Address & lhs,Register rhs,Label * label)833 void branch32(Condition cond, const Address& lhs, Register rhs, Label* label) { 834 ScratchRegisterScope scratch(asMasm()); 835 load32(lhs, scratch); 836 branch32(cond, scratch, rhs, label); 837 } branch32(Condition cond,const Address & lhs,Imm32 rhs,Label * label)838 void branch32(Condition cond, const Address& lhs, Imm32 rhs, Label* label) { 839 // branch32 will use ScratchRegister. 840 AutoRegisterScope scratch(asMasm(), secondScratchReg_); 841 load32(lhs, scratch); 842 branch32(cond, scratch, rhs, label); 843 } branch32(Condition cond,const BaseIndex & lhs,Imm32 rhs,Label * label)844 void branch32(Condition cond, const BaseIndex& lhs, Imm32 rhs, Label* label) { 845 // branch32 will use ScratchRegister. 846 AutoRegisterScope scratch2(asMasm(), secondScratchReg_); 847 load32(lhs, scratch2); 848 branch32(cond, scratch2, rhs, label); 849 } branchPtr(Condition cond,const Address & lhs,Register rhs,Label * label)850 void branchPtr(Condition cond, const Address& lhs, Register rhs, Label* label) { 851 branch32(cond, lhs, rhs, label); 852 } 853 branchPrivatePtr(Condition cond,const Address & lhs,ImmPtr ptr,Label * label)854 void branchPrivatePtr(Condition cond, const Address& lhs, ImmPtr ptr, Label* label) { 855 branchPtr(cond, lhs, ptr, label); 856 } 857 branchPrivatePtr(Condition cond,const Address & lhs,Register ptr,Label * label)858 void branchPrivatePtr(Condition cond, const Address& lhs, Register ptr, Label* label) { 859 branchPtr(cond, lhs, ptr, label); 860 } 861 branchPrivatePtr(Condition cond,Register lhs,ImmWord ptr,Label * label)862 void branchPrivatePtr(Condition cond, Register lhs, ImmWord ptr, Label* label) { 863 branchPtr(cond, lhs, ptr, label); 864 } 865 866 template<typename T> branchTestDouble(Condition cond,const T & t,Label * label)867 void branchTestDouble(Condition cond, const T & t, Label* label) { 868 Condition c = testDouble(cond, t); 869 ma_b(label, c); 870 } 871 template<typename T> branchTestNull(Condition cond,const T & t,Label * label)872 void branchTestNull(Condition cond, const T & t, Label* label) { 873 Condition c = testNull(cond, t); 874 ma_b(label, c); 875 } 876 template<typename T> branchTestObject(Condition cond,const T & t,Label * label)877 void branchTestObject(Condition cond, const T & t, Label* label) { 878 Condition c = testObject(cond, t); 879 ma_b(label, c); 880 } 881 template<typename T> branchTestString(Condition cond,const T & t,Label * label)882 void branchTestString(Condition cond, const T & t, Label* label) { 883 Condition c = testString(cond, t); 884 ma_b(label, c); 885 } 886 template<typename T> branchTestSymbol(Condition cond,const T & t,Label * label)887 void branchTestSymbol(Condition cond, const T & t, Label* label) { 888 Condition c = testSymbol(cond, t); 889 ma_b(label, c); 890 } 891 template<typename T> branchTestUndefined(Condition cond,const T & t,Label * label)892 void branchTestUndefined(Condition cond, const T & t, Label* label) { 893 Condition c = testUndefined(cond, t); 894 ma_b(label, c); 895 } 896 template <typename T> branchTestNumber(Condition cond,const T & t,Label * label)897 void branchTestNumber(Condition cond, const T& t, Label* label) { 898 cond = testNumber(cond, t); 899 ma_b(label, cond); 900 } 901 template <typename T> branchTestMagic(Condition cond,const T & t,Label * label)902 void branchTestMagic(Condition cond, const T& t, Label* label) { 903 cond = testMagic(cond, t); 904 ma_b(label, cond); 905 } branchTestMagicValue(Condition cond,const ValueOperand & val,JSWhyMagic why,Label * label)906 void branchTestMagicValue(Condition cond, const ValueOperand& val, JSWhyMagic why, 907 Label* label) { 908 MOZ_ASSERT(cond == Equal || cond == NotEqual); 909 branchTestValue(cond, val, MagicValue(why), label); 910 } branchTestInt32Truthy(bool truthy,const ValueOperand & operand,Label * label)911 void branchTestInt32Truthy(bool truthy, const ValueOperand& operand, Label* label) { 912 Condition c = testInt32Truthy(truthy, operand); 913 ma_b(label, c); 914 } branchTestBooleanTruthy(bool truthy,const ValueOperand & operand,Label * label)915 void branchTestBooleanTruthy(bool truthy, const ValueOperand& operand, Label* label) { 916 Condition c = testBooleanTruthy(truthy, operand); 917 ma_b(label, c); 918 } branchTestDoubleTruthy(bool truthy,FloatRegister reg,Label * label)919 void branchTestDoubleTruthy(bool truthy, FloatRegister reg, Label* label) { 920 Condition c = testDoubleTruthy(truthy, reg); 921 ma_b(label, c); 922 } branchTestStringTruthy(bool truthy,const ValueOperand & value,Label * label)923 void branchTestStringTruthy(bool truthy, const ValueOperand& value, Label* label) { 924 Condition c = testStringTruthy(truthy, value); 925 ma_b(label, c); 926 } branchTest32(Condition cond,Register lhs,Register rhs,Label * label)927 void branchTest32(Condition cond, Register lhs, Register rhs, Label* label) { 928 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned); 929 // x86 likes test foo, foo rather than cmp foo, #0. 930 // Convert the former into the latter. 931 if (lhs == rhs && (cond == Zero || cond == NonZero)) 932 ma_cmp(lhs, Imm32(0)); 933 else 934 ma_tst(lhs, rhs); 935 ma_b(label, cond); 936 } branchTest32(Condition cond,Register lhs,Imm32 imm,Label * label)937 void branchTest32(Condition cond, Register lhs, Imm32 imm, Label* label) { 938 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned); 939 ma_tst(lhs, imm); 940 ma_b(label, cond); 941 } branchTest32(Condition cond,const Address & address,Imm32 imm,Label * label)942 void branchTest32(Condition cond, const Address& address, Imm32 imm, Label* label) { 943 // branchTest32 will use ScratchRegister. 944 AutoRegisterScope scratch2(asMasm(), secondScratchReg_); 945 load32(address, scratch2); 946 branchTest32(cond, scratch2, imm, label); 947 } branchTest32(Condition cond,AbsoluteAddress address,Imm32 imm,Label * label)948 void branchTest32(Condition cond, AbsoluteAddress address, Imm32 imm, Label* label) { 949 // branchTest32 will use ScratchRegister. 950 AutoRegisterScope scratch2(asMasm(), secondScratchReg_); 951 load32(address, scratch2); 952 branchTest32(cond, scratch2, imm, label); 953 } branchTestPtr(Condition cond,Register lhs,Register rhs,Label * label)954 void branchTestPtr(Condition cond, Register lhs, Register rhs, Label* label) { 955 branchTest32(cond, lhs, rhs, label); 956 } branchTestPtr(Condition cond,Register lhs,const Imm32 rhs,Label * label)957 void branchTestPtr(Condition cond, Register lhs, const Imm32 rhs, Label* label) { 958 branchTest32(cond, lhs, rhs, label); 959 } branchTestPtr(Condition cond,const Address & lhs,Imm32 imm,Label * label)960 void branchTestPtr(Condition cond, const Address& lhs, Imm32 imm, Label* label) { 961 branchTest32(cond, lhs, imm, label); 962 } branchPtr(Condition cond,Register lhs,Register rhs,Label * label)963 void branchPtr(Condition cond, Register lhs, Register rhs, Label* label) { 964 branch32(cond, lhs, rhs, label); 965 } branchPtr(Condition cond,Register lhs,ImmGCPtr ptr,Label * label)966 void branchPtr(Condition cond, Register lhs, ImmGCPtr ptr, Label* label) { 967 ScratchRegisterScope scratch(asMasm()); 968 movePtr(ptr, scratch); 969 branchPtr(cond, lhs, scratch, label); 970 } branchPtr(Condition cond,Register lhs,ImmWord imm,Label * label)971 void branchPtr(Condition cond, Register lhs, ImmWord imm, Label* label) { 972 branch32(cond, lhs, Imm32(imm.value), label); 973 } branchPtr(Condition cond,Register lhs,ImmPtr imm,Label * label)974 void branchPtr(Condition cond, Register lhs, ImmPtr imm, Label* label) { 975 branchPtr(cond, lhs, ImmWord(uintptr_t(imm.value)), label); 976 } branchPtr(Condition cond,Register lhs,wasm::SymbolicAddress imm,Label * label)977 void branchPtr(Condition cond, Register lhs, wasm::SymbolicAddress imm, Label* label) { 978 ScratchRegisterScope scratch(asMasm()); 979 movePtr(imm, scratch); 980 branchPtr(cond, lhs, scratch, label); 981 } branchPtr(Condition cond,Register lhs,Imm32 imm,Label * label)982 void branchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) { 983 branch32(cond, lhs, imm, label); 984 } decBranchPtr(Condition cond,Register lhs,Imm32 imm,Label * label)985 void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) { 986 subPtr(imm, lhs); 987 branch32(cond, lhs, Imm32(0), label); 988 } 989 void branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp, Label* label); 990 void moveValue(const Value& val, Register type, Register data); 991 992 CodeOffsetJump jumpWithPatch(RepatchLabel* label, Condition cond = Always, 993 Label* documentation = nullptr); backedgeJump(RepatchLabel * label,Label * documentation)994 CodeOffsetJump backedgeJump(RepatchLabel* label, Label* documentation) { 995 return jumpWithPatch(label, Always, documentation); 996 } 997 template <typename T> branchPtrWithPatch(Condition cond,Register reg,T ptr,RepatchLabel * label)998 CodeOffsetJump branchPtrWithPatch(Condition cond, Register reg, T ptr, RepatchLabel* label) { 999 ma_cmp(reg, ptr); 1000 return jumpWithPatch(label, cond); 1001 } 1002 template <typename T> branchPtrWithPatch(Condition cond,Address addr,T ptr,RepatchLabel * label)1003 CodeOffsetJump branchPtrWithPatch(Condition cond, Address addr, T ptr, RepatchLabel* label) { 1004 AutoRegisterScope scratch2(asMasm(), secondScratchReg_); 1005 ma_ldr(addr, scratch2); 1006 ma_cmp(scratch2, ptr); 1007 return jumpWithPatch(label, cond); 1008 } branchPtr(Condition cond,Address addr,ImmGCPtr ptr,Label * label)1009 void branchPtr(Condition cond, Address addr, ImmGCPtr ptr, Label* label) { 1010 AutoRegisterScope scratch2(asMasm(), secondScratchReg_); 1011 ma_ldr(addr, scratch2); 1012 ma_cmp(scratch2, ptr); 1013 ma_b(label, cond); 1014 } branchPtr(Condition cond,Address addr,ImmWord ptr,Label * label)1015 void branchPtr(Condition cond, Address addr, ImmWord ptr, Label* label) { 1016 AutoRegisterScope scratch2(asMasm(), secondScratchReg_); 1017 ma_ldr(addr, scratch2); 1018 ma_cmp(scratch2, ptr); 1019 ma_b(label, cond); 1020 } branchPtr(Condition cond,Address addr,ImmPtr ptr,Label * label)1021 void branchPtr(Condition cond, Address addr, ImmPtr ptr, Label* label) { 1022 branchPtr(cond, addr, ImmWord(uintptr_t(ptr.value)), label); 1023 } branchPtr(Condition cond,AbsoluteAddress addr,Register ptr,Label * label)1024 void branchPtr(Condition cond, AbsoluteAddress addr, Register ptr, Label* label) { 1025 ScratchRegisterScope scratch(asMasm()); 1026 loadPtr(addr, scratch); 1027 ma_cmp(scratch, ptr); 1028 ma_b(label, cond); 1029 } branchPtr(Condition cond,AbsoluteAddress addr,ImmWord ptr,Label * label)1030 void branchPtr(Condition cond, AbsoluteAddress addr, ImmWord ptr, Label* label) { 1031 ScratchRegisterScope scratch(asMasm()); 1032 loadPtr(addr, scratch); 1033 ma_cmp(scratch, ptr); 1034 ma_b(label, cond); 1035 } branchPtr(Condition cond,wasm::SymbolicAddress addr,Register ptr,Label * label)1036 void branchPtr(Condition cond, wasm::SymbolicAddress addr, Register ptr, Label* label) { 1037 ScratchRegisterScope scratch(asMasm()); 1038 loadPtr(addr, scratch); 1039 ma_cmp(scratch, ptr); 1040 ma_b(label, cond); 1041 } branch32(Condition cond,AbsoluteAddress lhs,Imm32 rhs,Label * label)1042 void branch32(Condition cond, AbsoluteAddress lhs, Imm32 rhs, Label* label) { 1043 AutoRegisterScope scratch2(asMasm(), secondScratchReg_); 1044 loadPtr(lhs, scratch2); // ma_cmp will use the scratch register. 1045 ma_cmp(scratch2, rhs); 1046 ma_b(label, cond); 1047 } branch32(Condition cond,AbsoluteAddress lhs,Register rhs,Label * label)1048 void branch32(Condition cond, AbsoluteAddress lhs, Register rhs, Label* label) { 1049 AutoRegisterScope scratch2(asMasm(), secondScratchReg_); 1050 loadPtr(lhs, scratch2); // ma_cmp will use the scratch register. 1051 ma_cmp(scratch2, rhs); 1052 ma_b(label, cond); 1053 } branch32(Condition cond,wasm::SymbolicAddress addr,Imm32 imm,Label * label)1054 void branch32(Condition cond, wasm::SymbolicAddress addr, Imm32 imm, Label* label) { 1055 ScratchRegisterScope scratch(asMasm()); 1056 loadPtr(addr, scratch); 1057 ma_cmp(scratch, imm); 1058 ma_b(label, cond); 1059 } 1060 loadUnboxedValue(Address address,MIRType type,AnyRegister dest)1061 void loadUnboxedValue(Address address, MIRType type, AnyRegister dest) { 1062 if (dest.isFloat()) 1063 loadInt32OrDouble(address, dest.fpu()); 1064 else 1065 ma_ldr(address, dest.gpr()); 1066 } 1067 loadUnboxedValue(BaseIndex address,MIRType type,AnyRegister dest)1068 void loadUnboxedValue(BaseIndex address, MIRType type, AnyRegister dest) { 1069 if (dest.isFloat()) 1070 loadInt32OrDouble(address.base, address.index, dest.fpu(), address.scale); 1071 else 1072 load32(address, dest.gpr()); 1073 } 1074 1075 template <typename T> 1076 void storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const T& dest, 1077 MIRType slotType); 1078 1079 template <typename T> storeUnboxedPayload(ValueOperand value,T address,size_t nbytes)1080 void storeUnboxedPayload(ValueOperand value, T address, size_t nbytes) { 1081 switch (nbytes) { 1082 case 4: 1083 storePtr(value.payloadReg(), address); 1084 return; 1085 case 1: 1086 store8(value.payloadReg(), address); 1087 return; 1088 default: MOZ_CRASH("Bad payload width"); 1089 } 1090 } 1091 1092 void moveValue(const Value& val, const ValueOperand& dest); 1093 moveValue(const ValueOperand & src,const ValueOperand & dest)1094 void moveValue(const ValueOperand& src, const ValueOperand& dest) { 1095 Register s0 = src.typeReg(), d0 = dest.typeReg(), 1096 s1 = src.payloadReg(), d1 = dest.payloadReg(); 1097 1098 // Either one or both of the source registers could be the same as a 1099 // destination register. 1100 if (s1 == d0) { 1101 if (s0 == d1) { 1102 // If both are, this is just a swap of two registers. 1103 ScratchRegisterScope scratch(asMasm()); 1104 MOZ_ASSERT(d1 != scratch); 1105 MOZ_ASSERT(d0 != scratch); 1106 ma_mov(d1, scratch); 1107 ma_mov(d0, d1); 1108 ma_mov(scratch, d0); 1109 return; 1110 } 1111 // If only one is, copy that source first. 1112 mozilla::Swap(s0, s1); 1113 mozilla::Swap(d0, d1); 1114 } 1115 1116 if (s0 != d0) 1117 ma_mov(s0, d0); 1118 if (s1 != d1) 1119 ma_mov(s1, d1); 1120 } 1121 1122 void storeValue(ValueOperand val, const Address& dst); 1123 void storeValue(ValueOperand val, const BaseIndex& dest); storeValue(JSValueType type,Register reg,BaseIndex dest)1124 void storeValue(JSValueType type, Register reg, BaseIndex dest) { 1125 ScratchRegisterScope scratch(asMasm()); 1126 ma_alu(dest.base, lsl(dest.index, dest.scale), scratch, OpAdd); 1127 storeValue(type, reg, Address(scratch, dest.offset)); 1128 } storeValue(JSValueType type,Register reg,Address dest)1129 void storeValue(JSValueType type, Register reg, Address dest) { 1130 ma_str(reg, dest); 1131 AutoRegisterScope scratch2(asMasm(), secondScratchReg_); 1132 ma_mov(ImmTag(JSVAL_TYPE_TO_TAG(type)), scratch2); 1133 ma_str(scratch2, Address(dest.base, dest.offset + 4)); 1134 } storeValue(const Value & val,const Address & dest)1135 void storeValue(const Value& val, const Address& dest) { 1136 AutoRegisterScope scratch2(asMasm(), secondScratchReg_); 1137 jsval_layout jv = JSVAL_TO_IMPL(val); 1138 ma_mov(Imm32(jv.s.tag), scratch2); 1139 ma_str(scratch2, ToType(dest)); 1140 if (val.isMarkable()) 1141 ma_mov(ImmGCPtr(reinterpret_cast<gc::Cell*>(val.toGCThing())), scratch2); 1142 else 1143 ma_mov(Imm32(jv.s.payload.i32), scratch2); 1144 ma_str(scratch2, ToPayload(dest)); 1145 } storeValue(const Value & val,BaseIndex dest)1146 void storeValue(const Value& val, BaseIndex dest) { 1147 ScratchRegisterScope scratch(asMasm()); 1148 ma_alu(dest.base, lsl(dest.index, dest.scale), scratch, OpAdd); 1149 storeValue(val, Address(scratch, dest.offset)); 1150 } 1151 1152 void loadValue(Address src, ValueOperand val); loadValue(Operand dest,ValueOperand val)1153 void loadValue(Operand dest, ValueOperand val) { 1154 loadValue(dest.toAddress(), val); 1155 } 1156 void loadValue(const BaseIndex& addr, ValueOperand val); 1157 void tagValue(JSValueType type, Register payload, ValueOperand dest); 1158 1159 void pushValue(ValueOperand val); 1160 void popValue(ValueOperand val); pushValue(const Value & val)1161 void pushValue(const Value& val) { 1162 jsval_layout jv = JSVAL_TO_IMPL(val); 1163 push(Imm32(jv.s.tag)); 1164 if (val.isMarkable()) 1165 push(ImmGCPtr(reinterpret_cast<gc::Cell*>(val.toGCThing()))); 1166 else 1167 push(Imm32(jv.s.payload.i32)); 1168 } pushValue(JSValueType type,Register reg)1169 void pushValue(JSValueType type, Register reg) { 1170 push(ImmTag(JSVAL_TYPE_TO_TAG(type))); 1171 ma_push(reg); 1172 } 1173 void pushValue(const Address& addr); 1174 1175 void storePayload(const Value& val, const Address& dest); 1176 void storePayload(Register src, const Address& dest); 1177 void storePayload(const Value& val, const BaseIndex& dest); 1178 void storePayload(Register src, const BaseIndex& dest); 1179 void storeTypeTag(ImmTag tag, const Address& dest); 1180 void storeTypeTag(ImmTag tag, const BaseIndex& dest); 1181 1182 void handleFailureWithHandlerTail(void* handler); 1183 1184 ///////////////////////////////////////////////////////////////// 1185 // Common interface. 1186 ///////////////////////////////////////////////////////////////// 1187 public: 1188 void add32(Register src, Register dest); 1189 void add32(Imm32 imm, Register dest); 1190 void add32(Imm32 imm, const Address& dest); 1191 template <typename T> branchAdd32(Condition cond,T src,Register dest,Label * label)1192 void branchAdd32(Condition cond, T src, Register dest, Label* label) { 1193 add32(src, dest); 1194 j(cond, label); 1195 } 1196 template <typename T> branchSub32(Condition cond,T src,Register dest,Label * label)1197 void branchSub32(Condition cond, T src, Register dest, Label* label) { 1198 ma_sub(src, dest, SetCC); 1199 j(cond, label); 1200 } 1201 1202 void addPtr(Register src, Register dest); 1203 void addPtr(const Address& src, Register dest); add64(Imm32 imm,Register64 dest)1204 void add64(Imm32 imm, Register64 dest) { 1205 ma_add(imm, dest.low, SetCC); 1206 ma_adc(Imm32(0), dest.high, LeaveCC); 1207 } 1208 void not32(Register reg); 1209 1210 void move32(Imm32 imm, Register dest); 1211 void move32(Register src, Register dest); 1212 1213 void movePtr(Register src, Register dest); 1214 void movePtr(ImmWord imm, Register dest); 1215 void movePtr(ImmPtr imm, Register dest); 1216 void movePtr(wasm::SymbolicAddress imm, Register dest); 1217 void movePtr(ImmGCPtr imm, Register dest); move64(Register64 src,Register64 dest)1218 void move64(Register64 src, Register64 dest) { 1219 move32(src.low, dest.low); 1220 move32(src.high, dest.high); 1221 } 1222 1223 void load8SignExtend(const Address& address, Register dest); 1224 void load8SignExtend(const BaseIndex& src, Register dest); 1225 1226 void load8ZeroExtend(const Address& address, Register dest); 1227 void load8ZeroExtend(const BaseIndex& src, Register dest); 1228 1229 void load16SignExtend(const Address& address, Register dest); 1230 void load16SignExtend(const BaseIndex& src, Register dest); 1231 1232 void load16ZeroExtend(const Address& address, Register dest); 1233 void load16ZeroExtend(const BaseIndex& src, Register dest); 1234 1235 void load32(const Address& address, Register dest); 1236 void load32(const BaseIndex& address, Register dest); 1237 void load32(AbsoluteAddress address, Register dest); load64(const Address & address,Register64 dest)1238 void load64(const Address& address, Register64 dest) { 1239 load32(address, dest.low); 1240 load32(Address(address.base, address.offset + 4), dest.high); 1241 } 1242 1243 void loadPtr(const Address& address, Register dest); 1244 void loadPtr(const BaseIndex& src, Register dest); 1245 void loadPtr(AbsoluteAddress address, Register dest); 1246 void loadPtr(wasm::SymbolicAddress address, Register dest); 1247 branch64(Condition cond,const Address & lhs,Imm64 val,Label * label)1248 void branch64(Condition cond, const Address& lhs, Imm64 val, Label* label) { 1249 MOZ_ASSERT(cond == Assembler::NotEqual, 1250 "other condition codes not supported"); 1251 1252 branch32(cond, lhs, val.firstHalf(), label); 1253 branch32(cond, Address(lhs.base, lhs.offset + sizeof(uint32_t)), val.secondHalf(), label); 1254 } 1255 branch64(Condition cond,const Address & lhs,const Address & rhs,Register scratch,Label * label)1256 void branch64(Condition cond, const Address& lhs, const Address& rhs, Register scratch, 1257 Label* label) 1258 { 1259 MOZ_ASSERT(cond == Assembler::NotEqual, 1260 "other condition codes not supported"); 1261 MOZ_ASSERT(lhs.base != scratch); 1262 MOZ_ASSERT(rhs.base != scratch); 1263 1264 load32(rhs, scratch); 1265 branch32(cond, lhs, scratch, label); 1266 1267 load32(Address(rhs.base, rhs.offset + sizeof(uint32_t)), scratch); 1268 branch32(cond, Address(lhs.base, lhs.offset + sizeof(uint32_t)), scratch, label); 1269 } 1270 1271 void loadPrivate(const Address& address, Register dest); 1272 loadInt32x1(const Address & addr,FloatRegister dest)1273 void loadInt32x1(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } loadInt32x1(const BaseIndex & addr,FloatRegister dest)1274 void loadInt32x1(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } loadInt32x2(const Address & addr,FloatRegister dest)1275 void loadInt32x2(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } loadInt32x2(const BaseIndex & addr,FloatRegister dest)1276 void loadInt32x2(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } loadInt32x3(const Address & src,FloatRegister dest)1277 void loadInt32x3(const Address& src, FloatRegister dest) { MOZ_CRASH("NYI"); } loadInt32x3(const BaseIndex & src,FloatRegister dest)1278 void loadInt32x3(const BaseIndex& src, FloatRegister dest) { MOZ_CRASH("NYI"); } storeInt32x1(FloatRegister src,const Address & dest)1279 void storeInt32x1(FloatRegister src, const Address& dest) { MOZ_CRASH("NYI"); } storeInt32x1(FloatRegister src,const BaseIndex & dest)1280 void storeInt32x1(FloatRegister src, const BaseIndex& dest) { MOZ_CRASH("NYI"); } storeInt32x2(FloatRegister src,const Address & dest)1281 void storeInt32x2(FloatRegister src, const Address& dest) { MOZ_CRASH("NYI"); } storeInt32x2(FloatRegister src,const BaseIndex & dest)1282 void storeInt32x2(FloatRegister src, const BaseIndex& dest) { MOZ_CRASH("NYI"); } storeInt32x3(FloatRegister src,const Address & dest)1283 void storeInt32x3(FloatRegister src, const Address& dest) { MOZ_CRASH("NYI"); } storeInt32x3(FloatRegister src,const BaseIndex & dest)1284 void storeInt32x3(FloatRegister src, const BaseIndex& dest) { MOZ_CRASH("NYI"); } loadAlignedInt32x4(const Address & addr,FloatRegister dest)1285 void loadAlignedInt32x4(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } storeAlignedInt32x4(FloatRegister src,Address addr)1286 void storeAlignedInt32x4(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); } loadUnalignedInt32x4(const Address & addr,FloatRegister dest)1287 void loadUnalignedInt32x4(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } loadUnalignedInt32x4(const BaseIndex & addr,FloatRegister dest)1288 void loadUnalignedInt32x4(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } storeUnalignedInt32x4(FloatRegister src,Address addr)1289 void storeUnalignedInt32x4(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); } storeUnalignedInt32x4(FloatRegister src,BaseIndex addr)1290 void storeUnalignedInt32x4(FloatRegister src, BaseIndex addr) { MOZ_CRASH("NYI"); } 1291 loadFloat32x3(const Address & src,FloatRegister dest)1292 void loadFloat32x3(const Address& src, FloatRegister dest) { MOZ_CRASH("NYI"); } loadFloat32x3(const BaseIndex & src,FloatRegister dest)1293 void loadFloat32x3(const BaseIndex& src, FloatRegister dest) { MOZ_CRASH("NYI"); } storeFloat32x3(FloatRegister src,const Address & dest)1294 void storeFloat32x3(FloatRegister src, const Address& dest) { MOZ_CRASH("NYI"); } storeFloat32x3(FloatRegister src,const BaseIndex & dest)1295 void storeFloat32x3(FloatRegister src, const BaseIndex& dest) { MOZ_CRASH("NYI"); } loadAlignedFloat32x4(const Address & addr,FloatRegister dest)1296 void loadAlignedFloat32x4(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } storeAlignedFloat32x4(FloatRegister src,Address addr)1297 void storeAlignedFloat32x4(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); } loadUnalignedFloat32x4(const Address & addr,FloatRegister dest)1298 void loadUnalignedFloat32x4(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } loadUnalignedFloat32x4(const BaseIndex & addr,FloatRegister dest)1299 void loadUnalignedFloat32x4(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); } storeUnalignedFloat32x4(FloatRegister src,Address addr)1300 void storeUnalignedFloat32x4(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); } storeUnalignedFloat32x4(FloatRegister src,BaseIndex addr)1301 void storeUnalignedFloat32x4(FloatRegister src, BaseIndex addr) { MOZ_CRASH("NYI"); } 1302 1303 void loadDouble(const Address& addr, FloatRegister dest); 1304 void loadDouble(const BaseIndex& src, FloatRegister dest); 1305 1306 // Load a float value into a register, then expand it to a double. 1307 void loadFloatAsDouble(const Address& addr, FloatRegister dest); 1308 void loadFloatAsDouble(const BaseIndex& src, FloatRegister dest); 1309 1310 void loadFloat32(const Address& addr, FloatRegister dest); 1311 void loadFloat32(const BaseIndex& src, FloatRegister dest); 1312 1313 void store8(Register src, const Address& address); 1314 void store8(Imm32 imm, const Address& address); 1315 void store8(Register src, const BaseIndex& address); 1316 void store8(Imm32 imm, const BaseIndex& address); 1317 1318 void store16(Register src, const Address& address); 1319 void store16(Imm32 imm, const Address& address); 1320 void store16(Register src, const BaseIndex& address); 1321 void store16(Imm32 imm, const BaseIndex& address); 1322 1323 void store32(Register src, AbsoluteAddress address); 1324 void store32(Register src, const Address& address); 1325 void store32(Register src, const BaseIndex& address); 1326 void store32(Imm32 src, const Address& address); 1327 void store32(Imm32 src, const BaseIndex& address); 1328 1329 void store32_NoSecondScratch(Imm32 src, const Address& address); 1330 store64(Register64 src,Address address)1331 void store64(Register64 src, Address address) { 1332 store32(src.low, address); 1333 store32(src.high, Address(address.base, address.offset + 4)); 1334 } 1335 1336 template <typename T> void storePtr(ImmWord imm, T address); 1337 template <typename T> void storePtr(ImmPtr imm, T address); 1338 template <typename T> void storePtr(ImmGCPtr imm, T address); 1339 void storePtr(Register src, const Address& address); 1340 void storePtr(Register src, const BaseIndex& address); 1341 void storePtr(Register src, AbsoluteAddress dest); storeDouble(FloatRegister src,Address addr)1342 void storeDouble(FloatRegister src, Address addr) { 1343 ma_vstr(src, addr); 1344 } storeDouble(FloatRegister src,BaseIndex addr)1345 void storeDouble(FloatRegister src, BaseIndex addr) { 1346 uint32_t scale = Imm32::ShiftOf(addr.scale).value; 1347 ma_vstr(src, addr.base, addr.index, scale, addr.offset); 1348 } moveDouble(FloatRegister src,FloatRegister dest)1349 void moveDouble(FloatRegister src, FloatRegister dest) { 1350 ma_vmov(src, dest); 1351 } 1352 storeFloat32(FloatRegister src,const Address & addr)1353 void storeFloat32(FloatRegister src, const Address& addr) { 1354 ma_vstr(VFPRegister(src).singleOverlay(), addr); 1355 } storeFloat32(FloatRegister src,const BaseIndex & addr)1356 void storeFloat32(FloatRegister src, const BaseIndex& addr) { 1357 uint32_t scale = Imm32::ShiftOf(addr.scale).value; 1358 ma_vstr(VFPRegister(src).singleOverlay(), addr.base, addr.index, scale, addr.offset); 1359 } 1360 1361 private: 1362 template<typename T> 1363 Register computePointer(const T& src, Register r); 1364 1365 template<typename T> 1366 void compareExchangeARMv6(int nbytes, bool signExtend, const T& mem, Register oldval, 1367 Register newval, Register output); 1368 1369 template<typename T> 1370 void compareExchangeARMv7(int nbytes, bool signExtend, const T& mem, Register oldval, 1371 Register newval, Register output); 1372 1373 template<typename T> 1374 void compareExchange(int nbytes, bool signExtend, const T& address, Register oldval, 1375 Register newval, Register output); 1376 1377 template<typename T> 1378 void atomicExchangeARMv6(int nbytes, bool signExtend, const T& mem, Register value, 1379 Register output); 1380 1381 template<typename T> 1382 void atomicExchangeARMv7(int nbytes, bool signExtend, const T& mem, Register value, 1383 Register output); 1384 1385 template<typename T> 1386 void atomicExchange(int nbytes, bool signExtend, const T& address, Register value, 1387 Register output); 1388 1389 template<typename T> 1390 void atomicFetchOpARMv6(int nbytes, bool signExtend, AtomicOp op, const Register& value, 1391 const T& mem, Register flagTemp, Register output); 1392 1393 template<typename T> 1394 void atomicFetchOpARMv7(int nbytes, bool signExtend, AtomicOp op, const Register& value, 1395 const T& mem, Register flagTemp, Register output); 1396 1397 template<typename T> 1398 void atomicFetchOp(int nbytes, bool signExtend, AtomicOp op, const Imm32& value, 1399 const T& address, Register flagTemp, Register output); 1400 1401 template<typename T> 1402 void atomicFetchOp(int nbytes, bool signExtend, AtomicOp op, const Register& value, 1403 const T& address, Register flagTemp, Register output); 1404 1405 template<typename T> 1406 void atomicEffectOpARMv6(int nbytes, AtomicOp op, const Register& value, const T& address, 1407 Register flagTemp); 1408 1409 template<typename T> 1410 void atomicEffectOpARMv7(int nbytes, AtomicOp op, const Register& value, const T& address, 1411 Register flagTemp); 1412 1413 template<typename T> 1414 void atomicEffectOp(int nbytes, AtomicOp op, const Imm32& value, const T& address, 1415 Register flagTemp); 1416 1417 template<typename T> 1418 void atomicEffectOp(int nbytes, AtomicOp op, const Register& value, const T& address, 1419 Register flagTemp); 1420 1421 public: 1422 // T in {Address,BaseIndex} 1423 // S in {Imm32,Register} 1424 1425 template<typename T> compareExchange8SignExtend(const T & mem,Register oldval,Register newval,Register output)1426 void compareExchange8SignExtend(const T& mem, Register oldval, Register newval, Register output) 1427 { 1428 compareExchange(1, true, mem, oldval, newval, output); 1429 } 1430 template<typename T> compareExchange8ZeroExtend(const T & mem,Register oldval,Register newval,Register output)1431 void compareExchange8ZeroExtend(const T& mem, Register oldval, Register newval, Register output) 1432 { 1433 compareExchange(1, false, mem, oldval, newval, output); 1434 } 1435 template<typename T> compareExchange16SignExtend(const T & mem,Register oldval,Register newval,Register output)1436 void compareExchange16SignExtend(const T& mem, Register oldval, Register newval, Register output) 1437 { 1438 compareExchange(2, true, mem, oldval, newval, output); 1439 } 1440 template<typename T> compareExchange16ZeroExtend(const T & mem,Register oldval,Register newval,Register output)1441 void compareExchange16ZeroExtend(const T& mem, Register oldval, Register newval, Register output) 1442 { 1443 compareExchange(2, false, mem, oldval, newval, output); 1444 } 1445 template<typename T> compareExchange32(const T & mem,Register oldval,Register newval,Register output)1446 void compareExchange32(const T& mem, Register oldval, Register newval, Register output) { 1447 compareExchange(4, false, mem, oldval, newval, output); 1448 } 1449 1450 template<typename T> atomicExchange8SignExtend(const T & mem,Register value,Register output)1451 void atomicExchange8SignExtend(const T& mem, Register value, Register output) 1452 { 1453 atomicExchange(1, true, mem, value, output); 1454 } 1455 template<typename T> atomicExchange8ZeroExtend(const T & mem,Register value,Register output)1456 void atomicExchange8ZeroExtend(const T& mem, Register value, Register output) 1457 { 1458 atomicExchange(1, false, mem, value, output); 1459 } 1460 template<typename T> atomicExchange16SignExtend(const T & mem,Register value,Register output)1461 void atomicExchange16SignExtend(const T& mem, Register value, Register output) 1462 { 1463 atomicExchange(2, true, mem, value, output); 1464 } 1465 template<typename T> atomicExchange16ZeroExtend(const T & mem,Register value,Register output)1466 void atomicExchange16ZeroExtend(const T& mem, Register value, Register output) 1467 { 1468 atomicExchange(2, false, mem, value, output); 1469 } 1470 template<typename T> atomicExchange32(const T & mem,Register value,Register output)1471 void atomicExchange32(const T& mem, Register value, Register output) { 1472 atomicExchange(4, false, mem, value, output); 1473 } 1474 1475 template<typename T, typename S> atomicFetchAdd8SignExtend(const S & value,const T & mem,Register temp,Register output)1476 void atomicFetchAdd8SignExtend(const S& value, const T& mem, Register temp, Register output) { 1477 atomicFetchOp(1, true, AtomicFetchAddOp, value, mem, temp, output); 1478 } 1479 template<typename T, typename S> atomicFetchAdd8ZeroExtend(const S & value,const T & mem,Register temp,Register output)1480 void atomicFetchAdd8ZeroExtend(const S& value, const T& mem, Register temp, Register output) { 1481 atomicFetchOp(1, false, AtomicFetchAddOp, value, mem, temp, output); 1482 } 1483 template<typename T, typename S> atomicFetchAdd16SignExtend(const S & value,const T & mem,Register temp,Register output)1484 void atomicFetchAdd16SignExtend(const S& value, const T& mem, Register temp, Register output) { 1485 atomicFetchOp(2, true, AtomicFetchAddOp, value, mem, temp, output); 1486 } 1487 template<typename T, typename S> atomicFetchAdd16ZeroExtend(const S & value,const T & mem,Register temp,Register output)1488 void atomicFetchAdd16ZeroExtend(const S& value, const T& mem, Register temp, Register output) { 1489 atomicFetchOp(2, false, AtomicFetchAddOp, value, mem, temp, output); 1490 } 1491 template<typename T, typename S> atomicFetchAdd32(const S & value,const T & mem,Register temp,Register output)1492 void atomicFetchAdd32(const S& value, const T& mem, Register temp, Register output) { 1493 atomicFetchOp(4, false, AtomicFetchAddOp, value, mem, temp, output); 1494 } 1495 template <typename T, typename S> atomicAdd8(const S & value,const T & mem,Register flagTemp)1496 void atomicAdd8(const S& value, const T& mem, Register flagTemp) { 1497 atomicEffectOp(1, AtomicFetchAddOp, value, mem, flagTemp); 1498 } 1499 template <typename T, typename S> atomicAdd16(const S & value,const T & mem,Register flagTemp)1500 void atomicAdd16(const S& value, const T& mem, Register flagTemp) { 1501 atomicEffectOp(2, AtomicFetchAddOp, value, mem, flagTemp); 1502 } 1503 template <typename T, typename S> atomicAdd32(const S & value,const T & mem,Register flagTemp)1504 void atomicAdd32(const S& value, const T& mem, Register flagTemp) { 1505 atomicEffectOp(4, AtomicFetchAddOp, value, mem, flagTemp); 1506 } 1507 1508 template<typename T, typename S> atomicFetchSub8SignExtend(const S & value,const T & mem,Register temp,Register output)1509 void atomicFetchSub8SignExtend(const S& value, const T& mem, Register temp, Register output) { 1510 atomicFetchOp(1, true, AtomicFetchSubOp, value, mem, temp, output); 1511 } 1512 template<typename T, typename S> atomicFetchSub8ZeroExtend(const S & value,const T & mem,Register temp,Register output)1513 void atomicFetchSub8ZeroExtend(const S& value, const T& mem, Register temp, Register output) { 1514 atomicFetchOp(1, false, AtomicFetchSubOp, value, mem, temp, output); 1515 } 1516 template<typename T, typename S> atomicFetchSub16SignExtend(const S & value,const T & mem,Register temp,Register output)1517 void atomicFetchSub16SignExtend(const S& value, const T& mem, Register temp, Register output) { 1518 atomicFetchOp(2, true, AtomicFetchSubOp, value, mem, temp, output); 1519 } 1520 template<typename T, typename S> atomicFetchSub16ZeroExtend(const S & value,const T & mem,Register temp,Register output)1521 void atomicFetchSub16ZeroExtend(const S& value, const T& mem, Register temp, Register output) { 1522 atomicFetchOp(2, false, AtomicFetchSubOp, value, mem, temp, output); 1523 } 1524 template<typename T, typename S> atomicFetchSub32(const S & value,const T & mem,Register temp,Register output)1525 void atomicFetchSub32(const S& value, const T& mem, Register temp, Register output) { 1526 atomicFetchOp(4, false, AtomicFetchSubOp, value, mem, temp, output); 1527 } 1528 template <typename T, typename S> atomicSub8(const S & value,const T & mem,Register flagTemp)1529 void atomicSub8(const S& value, const T& mem, Register flagTemp) { 1530 atomicEffectOp(1, AtomicFetchSubOp, value, mem, flagTemp); 1531 } 1532 template <typename T, typename S> atomicSub16(const S & value,const T & mem,Register flagTemp)1533 void atomicSub16(const S& value, const T& mem, Register flagTemp) { 1534 atomicEffectOp(2, AtomicFetchSubOp, value, mem, flagTemp); 1535 } 1536 template <typename T, typename S> atomicSub32(const S & value,const T & mem,Register flagTemp)1537 void atomicSub32(const S& value, const T& mem, Register flagTemp) { 1538 atomicEffectOp(4, AtomicFetchSubOp, value, mem, flagTemp); 1539 } 1540 1541 template<typename T, typename S> atomicFetchAnd8SignExtend(const S & value,const T & mem,Register temp,Register output)1542 void atomicFetchAnd8SignExtend(const S& value, const T& mem, Register temp, Register output) { 1543 atomicFetchOp(1, true, AtomicFetchAndOp, value, mem, temp, output); 1544 } 1545 template<typename T, typename S> atomicFetchAnd8ZeroExtend(const S & value,const T & mem,Register temp,Register output)1546 void atomicFetchAnd8ZeroExtend(const S& value, const T& mem, Register temp, Register output) { 1547 atomicFetchOp(1, false, AtomicFetchAndOp, value, mem, temp, output); 1548 } 1549 template<typename T, typename S> atomicFetchAnd16SignExtend(const S & value,const T & mem,Register temp,Register output)1550 void atomicFetchAnd16SignExtend(const S& value, const T& mem, Register temp, Register output) { 1551 atomicFetchOp(2, true, AtomicFetchAndOp, value, mem, temp, output); 1552 } 1553 template<typename T, typename S> atomicFetchAnd16ZeroExtend(const S & value,const T & mem,Register temp,Register output)1554 void atomicFetchAnd16ZeroExtend(const S& value, const T& mem, Register temp, Register output) { 1555 atomicFetchOp(2, false, AtomicFetchAndOp, value, mem, temp, output); 1556 } 1557 template<typename T, typename S> atomicFetchAnd32(const S & value,const T & mem,Register temp,Register output)1558 void atomicFetchAnd32(const S& value, const T& mem, Register temp, Register output) { 1559 atomicFetchOp(4, false, AtomicFetchAndOp, value, mem, temp, output); 1560 } 1561 template <typename T, typename S> atomicAnd8(const S & value,const T & mem,Register flagTemp)1562 void atomicAnd8(const S& value, const T& mem, Register flagTemp) { 1563 atomicEffectOp(1, AtomicFetchAndOp, value, mem, flagTemp); 1564 } 1565 template <typename T, typename S> atomicAnd16(const S & value,const T & mem,Register flagTemp)1566 void atomicAnd16(const S& value, const T& mem, Register flagTemp) { 1567 atomicEffectOp(2, AtomicFetchAndOp, value, mem, flagTemp); 1568 } 1569 template <typename T, typename S> atomicAnd32(const S & value,const T & mem,Register flagTemp)1570 void atomicAnd32(const S& value, const T& mem, Register flagTemp) { 1571 atomicEffectOp(4, AtomicFetchAndOp, value, mem, flagTemp); 1572 } 1573 1574 template<typename T, typename S> atomicFetchOr8SignExtend(const S & value,const T & mem,Register temp,Register output)1575 void atomicFetchOr8SignExtend(const S& value, const T& mem, Register temp, Register output) { 1576 atomicFetchOp(1, true, AtomicFetchOrOp, value, mem, temp, output); 1577 } 1578 template<typename T, typename S> atomicFetchOr8ZeroExtend(const S & value,const T & mem,Register temp,Register output)1579 void atomicFetchOr8ZeroExtend(const S& value, const T& mem, Register temp, Register output) { 1580 atomicFetchOp(1, false, AtomicFetchOrOp, value, mem, temp, output); 1581 } 1582 template<typename T, typename S> atomicFetchOr16SignExtend(const S & value,const T & mem,Register temp,Register output)1583 void atomicFetchOr16SignExtend(const S& value, const T& mem, Register temp, Register output) { 1584 atomicFetchOp(2, true, AtomicFetchOrOp, value, mem, temp, output); 1585 } 1586 template<typename T, typename S> atomicFetchOr16ZeroExtend(const S & value,const T & mem,Register temp,Register output)1587 void atomicFetchOr16ZeroExtend(const S& value, const T& mem, Register temp, Register output) { 1588 atomicFetchOp(2, false, AtomicFetchOrOp, value, mem, temp, output); 1589 } 1590 template<typename T, typename S> atomicFetchOr32(const S & value,const T & mem,Register temp,Register output)1591 void atomicFetchOr32(const S& value, const T& mem, Register temp, Register output) { 1592 atomicFetchOp(4, false, AtomicFetchOrOp, value, mem, temp, output); 1593 } 1594 template <typename T, typename S> atomicOr8(const S & value,const T & mem,Register flagTemp)1595 void atomicOr8(const S& value, const T& mem, Register flagTemp) { 1596 atomicEffectOp(1, AtomicFetchOrOp, value, mem, flagTemp); 1597 } 1598 template <typename T, typename S> atomicOr16(const S & value,const T & mem,Register flagTemp)1599 void atomicOr16(const S& value, const T& mem, Register flagTemp) { 1600 atomicEffectOp(2, AtomicFetchOrOp, value, mem, flagTemp); 1601 } 1602 template <typename T, typename S> atomicOr32(const S & value,const T & mem,Register flagTemp)1603 void atomicOr32(const S& value, const T& mem, Register flagTemp) { 1604 atomicEffectOp(4, AtomicFetchOrOp, value, mem, flagTemp); 1605 } 1606 1607 template<typename T, typename S> atomicFetchXor8SignExtend(const S & value,const T & mem,Register temp,Register output)1608 void atomicFetchXor8SignExtend(const S& value, const T& mem, Register temp, Register output) { 1609 atomicFetchOp(1, true, AtomicFetchXorOp, value, mem, temp, output); 1610 } 1611 template<typename T, typename S> atomicFetchXor8ZeroExtend(const S & value,const T & mem,Register temp,Register output)1612 void atomicFetchXor8ZeroExtend(const S& value, const T& mem, Register temp, Register output) { 1613 atomicFetchOp(1, false, AtomicFetchXorOp, value, mem, temp, output); 1614 } 1615 template<typename T, typename S> atomicFetchXor16SignExtend(const S & value,const T & mem,Register temp,Register output)1616 void atomicFetchXor16SignExtend(const S& value, const T& mem, Register temp, Register output) { 1617 atomicFetchOp(2, true, AtomicFetchXorOp, value, mem, temp, output); 1618 } 1619 template<typename T, typename S> atomicFetchXor16ZeroExtend(const S & value,const T & mem,Register temp,Register output)1620 void atomicFetchXor16ZeroExtend(const S& value, const T& mem, Register temp, Register output) { 1621 atomicFetchOp(2, false, AtomicFetchXorOp, value, mem, temp, output); 1622 } 1623 template<typename T, typename S> atomicFetchXor32(const S & value,const T & mem,Register temp,Register output)1624 void atomicFetchXor32(const S& value, const T& mem, Register temp, Register output) { 1625 atomicFetchOp(4, false, AtomicFetchXorOp, value, mem, temp, output); 1626 } 1627 template <typename T, typename S> atomicXor8(const S & value,const T & mem,Register flagTemp)1628 void atomicXor8(const S& value, const T& mem, Register flagTemp) { 1629 atomicEffectOp(1, AtomicFetchXorOp, value, mem, flagTemp); 1630 } 1631 template <typename T, typename S> atomicXor16(const S & value,const T & mem,Register flagTemp)1632 void atomicXor16(const S& value, const T& mem, Register flagTemp) { 1633 atomicEffectOp(2, AtomicFetchXorOp, value, mem, flagTemp); 1634 } 1635 template <typename T, typename S> atomicXor32(const S & value,const T & mem,Register flagTemp)1636 void atomicXor32(const S& value, const T& mem, Register flagTemp) { 1637 atomicEffectOp(4, AtomicFetchXorOp, value, mem, flagTemp); 1638 } 1639 1640 template<typename T> 1641 void compareExchangeToTypedIntArray(Scalar::Type arrayType, const T& mem, Register oldval, Register newval, 1642 Register temp, AnyRegister output); 1643 1644 template<typename T> 1645 void atomicExchangeToTypedIntArray(Scalar::Type arrayType, const T& mem, Register value, 1646 Register temp, AnyRegister output); 1647 clampIntToUint8(Register reg)1648 void clampIntToUint8(Register reg) { 1649 // Look at (reg >> 8) if it is 0, then reg shouldn't be clamped if it is 1650 // <0, then we want to clamp to 0, otherwise, we wish to clamp to 255 1651 ScratchRegisterScope scratch(asMasm()); 1652 as_mov(scratch, asr(reg, 8), SetCC); 1653 ma_mov(Imm32(0xff), reg, LeaveCC, NotEqual); 1654 ma_mov(Imm32(0), reg, LeaveCC, Signed); 1655 } 1656 incrementInt32Value(const Address & addr)1657 void incrementInt32Value(const Address& addr) { 1658 add32(Imm32(1), ToPayload(addr)); 1659 } 1660 1661 void cmp32(Register lhs, Imm32 rhs); 1662 void cmp32(Register lhs, Register rhs); 1663 void cmp32(const Operand& lhs, Imm32 rhs); 1664 void cmp32(const Operand& lhs, Register rhs); 1665 1666 void cmpPtr(Register lhs, Register rhs); 1667 void cmpPtr(Register lhs, ImmWord rhs); 1668 void cmpPtr(Register lhs, ImmPtr rhs); 1669 void cmpPtr(Register lhs, ImmGCPtr rhs); 1670 void cmpPtr(Register lhs, Imm32 rhs); 1671 void cmpPtr(const Address& lhs, Register rhs); 1672 void cmpPtr(const Address& lhs, ImmWord rhs); 1673 void cmpPtr(const Address& lhs, ImmPtr rhs); 1674 void cmpPtr(const Address& lhs, ImmGCPtr rhs); 1675 void cmpPtr(const Address& lhs, Imm32 rhs); 1676 1677 void subPtr(Imm32 imm, const Register dest); 1678 void subPtr(const Address& addr, const Register dest); 1679 void subPtr(Register src, Register dest); 1680 void subPtr(Register src, const Address& dest); 1681 void addPtr(Imm32 imm, const Register dest); 1682 void addPtr(Imm32 imm, const Address& dest); addPtr(ImmWord imm,const Register dest)1683 void addPtr(ImmWord imm, const Register dest) { 1684 addPtr(Imm32(imm.value), dest); 1685 } addPtr(ImmPtr imm,const Register dest)1686 void addPtr(ImmPtr imm, const Register dest) { 1687 addPtr(ImmWord(uintptr_t(imm.value)), dest); 1688 } mulBy3(const Register & src,const Register & dest)1689 void mulBy3(const Register& src, const Register& dest) { 1690 as_add(dest, src, lsl(src, 1)); 1691 } mul64(Imm64 imm,const Register64 & dest)1692 void mul64(Imm64 imm, const Register64& dest) { 1693 // LOW32 = LOW(LOW(dest) * LOW(imm)); 1694 // HIGH32 = LOW(HIGH(dest) * LOW(imm)) [multiply imm into upper bits] 1695 // + LOW(LOW(dest) * HIGH(imm)) [multiply dest into upper bits] 1696 // + HIGH(LOW(dest) * LOW(imm)) [carry] 1697 1698 // HIGH(dest) = LOW(HIGH(dest) * LOW(imm)); 1699 ma_mov(Imm32(imm.value & 0xFFFFFFFFL), ScratchRegister); 1700 as_mul(dest.high, dest.high, ScratchRegister); 1701 1702 // high:low = LOW(dest) * LOW(imm); 1703 as_umull(secondScratchReg_, ScratchRegister, dest.low, ScratchRegister); 1704 1705 // HIGH(dest) += high; 1706 as_add(dest.high, dest.high, O2Reg(secondScratchReg_)); 1707 1708 // HIGH(dest) += LOW(LOW(dest) * HIGH(imm)); 1709 if (((imm.value >> 32) & 0xFFFFFFFFL) == 5) 1710 as_add(secondScratchReg_, dest.low, lsl(dest.low, 2)); 1711 else 1712 MOZ_CRASH("Not supported imm"); 1713 as_add(dest.high, dest.high, O2Reg(secondScratchReg_)); 1714 1715 // LOW(dest) = low; 1716 ma_mov(ScratchRegister, dest.low); 1717 } 1718 1719 void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest); mulDoublePtr(ImmPtr imm,Register temp,FloatRegister dest)1720 void mulDoublePtr(ImmPtr imm, Register temp, FloatRegister dest) { 1721 movePtr(imm, ScratchRegister); 1722 loadDouble(Address(ScratchRegister, 0), ScratchDoubleReg); 1723 mulDouble(ScratchDoubleReg, dest); 1724 } 1725 1726 void setStackArg(Register reg, uint32_t arg); 1727 1728 void breakpoint(); 1729 // Conditional breakpoint. 1730 void breakpoint(Condition cc); 1731 1732 // Trigger the simulator's interactive read-eval-print loop. 1733 // The message will be printed at the stopping point. 1734 // (On non-simulator builds, does nothing.) 1735 void simulatorStop(const char* msg); 1736 1737 void compareDouble(FloatRegister lhs, FloatRegister rhs); 1738 void branchDouble(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs, 1739 Label* label); 1740 1741 void compareFloat(FloatRegister lhs, FloatRegister rhs); 1742 void branchFloat(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs, 1743 Label* label); 1744 1745 void checkStackAlignment(); 1746 1747 // If source is a double, load it into dest. If source is int32, convert it 1748 // to double. Else, branch to failure. 1749 void ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure); 1750 1751 void emitSet(Assembler::Condition cond,Register dest)1752 emitSet(Assembler::Condition cond, Register dest) 1753 { 1754 ma_mov(Imm32(0), dest); 1755 ma_mov(Imm32(1), dest, LeaveCC, cond); 1756 } 1757 1758 template <typename T1, typename T2> cmpPtrSet(Assembler::Condition cond,T1 lhs,T2 rhs,Register dest)1759 void cmpPtrSet(Assembler::Condition cond, T1 lhs, T2 rhs, Register dest) 1760 { 1761 cmpPtr(lhs, rhs); 1762 emitSet(cond, dest); 1763 } 1764 template <typename T1, typename T2> cmp32Set(Assembler::Condition cond,T1 lhs,T2 rhs,Register dest)1765 void cmp32Set(Assembler::Condition cond, T1 lhs, T2 rhs, Register dest) 1766 { 1767 cmp32(lhs, rhs); 1768 emitSet(cond, dest); 1769 } 1770 testNullSet(Condition cond,const ValueOperand & value,Register dest)1771 void testNullSet(Condition cond, const ValueOperand& value, Register dest) { 1772 cond = testNull(cond, value); 1773 emitSet(cond, dest); 1774 } 1775 testObjectSet(Condition cond,const ValueOperand & value,Register dest)1776 void testObjectSet(Condition cond, const ValueOperand& value, Register dest) { 1777 cond = testObject(cond, value); 1778 emitSet(cond, dest); 1779 } 1780 testUndefinedSet(Condition cond,const ValueOperand & value,Register dest)1781 void testUndefinedSet(Condition cond, const ValueOperand& value, Register dest) { 1782 cond = testUndefined(cond, value); 1783 emitSet(cond, dest); 1784 } 1785 1786 protected: 1787 bool buildOOLFakeExitFrame(void* fakeReturnAddr); 1788 1789 public: labelForPatch()1790 CodeOffset labelForPatch() { 1791 return CodeOffset(nextOffset().getOffset()); 1792 } 1793 computeEffectiveAddress(const Address & address,Register dest)1794 void computeEffectiveAddress(const Address& address, Register dest) { 1795 ma_add(address.base, Imm32(address.offset), dest, LeaveCC); 1796 } computeEffectiveAddress(const BaseIndex & address,Register dest)1797 void computeEffectiveAddress(const BaseIndex& address, Register dest) { 1798 ma_alu(address.base, lsl(address.index, address.scale), dest, OpAdd, LeaveCC); 1799 if (address.offset) 1800 ma_add(dest, Imm32(address.offset), dest, LeaveCC); 1801 } 1802 void floor(FloatRegister input, Register output, Label* handleNotAnInt); 1803 void floorf(FloatRegister input, Register output, Label* handleNotAnInt); 1804 void ceil(FloatRegister input, Register output, Label* handleNotAnInt); 1805 void ceilf(FloatRegister input, Register output, Label* handleNotAnInt); 1806 void round(FloatRegister input, Register output, Label* handleNotAnInt, FloatRegister tmp); 1807 void roundf(FloatRegister input, Register output, Label* handleNotAnInt, FloatRegister tmp); 1808 clampCheck(Register r,Label * handleNotAnInt)1809 void clampCheck(Register r, Label* handleNotAnInt) { 1810 // Check explicitly for r == INT_MIN || r == INT_MAX 1811 // This is the instruction sequence that gcc generated for this 1812 // operation. 1813 ScratchRegisterScope scratch(asMasm()); 1814 ma_sub(r, Imm32(0x80000001), scratch); 1815 ma_cmn(scratch, Imm32(3)); 1816 ma_b(handleNotAnInt, Above); 1817 } 1818 memIntToValue(Address Source,Address Dest)1819 void memIntToValue(Address Source, Address Dest) { 1820 load32(Source, lr); 1821 storeValue(JSVAL_TYPE_INT32, lr, Dest); 1822 } 1823 lea(Operand addr,Register dest)1824 void lea(Operand addr, Register dest) { 1825 ma_add(addr.baseReg(), Imm32(addr.disp()), dest); 1826 } 1827 abiret()1828 void abiret() { 1829 as_bx(lr); 1830 } 1831 ma_storeImm(Imm32 c,const Address & dest)1832 void ma_storeImm(Imm32 c, const Address& dest) { 1833 ma_mov(c, lr); 1834 ma_str(lr, dest); 1835 } ma_BoundsCheck(Register bounded)1836 BufferOffset ma_BoundsCheck(Register bounded) { 1837 return as_cmp(bounded, Imm8(0)); 1838 } 1839 moveFloat32(FloatRegister src,FloatRegister dest)1840 void moveFloat32(FloatRegister src, FloatRegister dest) { 1841 as_vmov(VFPRegister(dest).singleOverlay(), VFPRegister(src).singleOverlay()); 1842 } 1843 1844 void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label* label); 1845 void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, Label* label); 1846 loadAsmJSActivation(Register dest)1847 void loadAsmJSActivation(Register dest) { 1848 loadPtr(Address(GlobalReg, wasm::ActivationGlobalDataOffset - AsmJSGlobalRegBias), dest); 1849 } loadAsmJSHeapRegisterFromGlobalData()1850 void loadAsmJSHeapRegisterFromGlobalData() { 1851 loadPtr(Address(GlobalReg, wasm::HeapGlobalDataOffset - AsmJSGlobalRegBias), HeapReg); 1852 } 1853 // Instrumentation for entering and leaving the profiler. 1854 void profilerEnterFrame(Register framePtr, Register scratch); 1855 void profilerExitFrame(); 1856 }; 1857 1858 typedef MacroAssemblerARMCompat MacroAssemblerSpecific; 1859 1860 } // namespace jit 1861 } // namespace js 1862 1863 #endif /* jit_arm_MacroAssembler_arm_h */ 1864