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_arm64_MacroAssembler_arm64_inl_h
8 #define jit_arm64_MacroAssembler_arm64_inl_h
9 
10 #include "jit/arm64/MacroAssembler-arm64.h"
11 
12 namespace js {
13 namespace jit {
14 
15 //{{{ check_macroassembler_style
16 
17 void
move64(Register64 src,Register64 dest)18 MacroAssembler::move64(Register64 src, Register64 dest)
19 {
20     movePtr(src.reg, dest.reg);
21 }
22 
23 void
move64(Imm64 imm,Register64 dest)24 MacroAssembler::move64(Imm64 imm, Register64 dest)
25 {
26     movePtr(ImmWord(imm.value), dest.reg);
27 }
28 
29 void
moveFloat32ToGPR(FloatRegister src,Register dest)30 MacroAssembler::moveFloat32ToGPR(FloatRegister src, Register dest)
31 {
32     MOZ_CRASH("NYI: moveFloat32ToGPR");
33 }
34 
35 void
moveGPRToFloat32(Register src,FloatRegister dest)36 MacroAssembler::moveGPRToFloat32(Register src, FloatRegister dest)
37 {
38     MOZ_CRASH("NYI: moveGPRToFloat32");
39 }
40 
41 void
move8SignExtend(Register src,Register dest)42 MacroAssembler::move8SignExtend(Register src, Register dest)
43 {
44     MOZ_CRASH("NYI: move8SignExtend");
45 }
46 
47 void
move16SignExtend(Register src,Register dest)48 MacroAssembler::move16SignExtend(Register src, Register dest)
49 {
50     MOZ_CRASH("NYI: move16SignExtend");
51 }
52 
53 // ===============================================================
54 // Logical instructions
55 
56 void
not32(Register reg)57 MacroAssembler::not32(Register reg)
58 {
59     Orn(ARMRegister(reg, 32), vixl::wzr, ARMRegister(reg, 32));
60 }
61 
62 void
and32(Register src,Register dest)63 MacroAssembler::and32(Register src, Register dest)
64 {
65     And(ARMRegister(dest, 32), ARMRegister(dest, 32), Operand(ARMRegister(src, 32)));
66 }
67 
68 void
and32(Imm32 imm,Register dest)69 MacroAssembler::and32(Imm32 imm, Register dest)
70 {
71     And(ARMRegister(dest, 32), ARMRegister(dest, 32), Operand(imm.value));
72 }
73 
74 void
and32(Imm32 imm,Register src,Register dest)75 MacroAssembler::and32(Imm32 imm, Register src, Register dest)
76 {
77     And(ARMRegister(dest, 32), ARMRegister(src, 32), Operand(imm.value));
78 }
79 
80 void
and32(Imm32 imm,const Address & dest)81 MacroAssembler::and32(Imm32 imm, const Address& dest)
82 {
83     vixl::UseScratchRegisterScope temps(this);
84     const ARMRegister scratch32 = temps.AcquireW();
85     MOZ_ASSERT(scratch32.asUnsized() != dest.base);
86     load32(dest, scratch32.asUnsized());
87     And(scratch32, scratch32, Operand(imm.value));
88     store32(scratch32.asUnsized(), dest);
89 }
90 
91 void
and32(const Address & src,Register dest)92 MacroAssembler::and32(const Address& src, Register dest)
93 {
94     vixl::UseScratchRegisterScope temps(this);
95     const ARMRegister scratch32 = temps.AcquireW();
96     MOZ_ASSERT(scratch32.asUnsized() != src.base);
97     load32(src, scratch32.asUnsized());
98     And(ARMRegister(dest, 32), ARMRegister(dest, 32), Operand(scratch32));
99 }
100 
101 void
andPtr(Register src,Register dest)102 MacroAssembler::andPtr(Register src, Register dest)
103 {
104     And(ARMRegister(dest, 64), ARMRegister(dest, 64), Operand(ARMRegister(src, 64)));
105 }
106 
107 void
andPtr(Imm32 imm,Register dest)108 MacroAssembler::andPtr(Imm32 imm, Register dest)
109 {
110     And(ARMRegister(dest, 64), ARMRegister(dest, 64), Operand(imm.value));
111 }
112 
113 void
and64(Imm64 imm,Register64 dest)114 MacroAssembler::and64(Imm64 imm, Register64 dest)
115 {
116     vixl::UseScratchRegisterScope temps(this);
117     const Register scratch = temps.AcquireX().asUnsized();
118     mov(ImmWord(imm.value), scratch);
119     andPtr(scratch, dest.reg);
120 }
121 
122 void
and64(Register64 src,Register64 dest)123 MacroAssembler::and64(Register64 src, Register64 dest)
124 {
125     MOZ_CRASH("NYI: and64");
126 }
127 
128 void
or64(Imm64 imm,Register64 dest)129 MacroAssembler::or64(Imm64 imm, Register64 dest)
130 {
131     vixl::UseScratchRegisterScope temps(this);
132     const Register scratch = temps.AcquireX().asUnsized();
133     mov(ImmWord(imm.value), scratch);
134     orPtr(scratch, dest.reg);
135 }
136 
137 void
xor64(Imm64 imm,Register64 dest)138 MacroAssembler::xor64(Imm64 imm, Register64 dest)
139 {
140     vixl::UseScratchRegisterScope temps(this);
141     const Register scratch = temps.AcquireX().asUnsized();
142     mov(ImmWord(imm.value), scratch);
143     xorPtr(scratch, dest.reg);
144 }
145 
146 void
or32(Imm32 imm,Register dest)147 MacroAssembler::or32(Imm32 imm, Register dest)
148 {
149     Orr(ARMRegister(dest, 32), ARMRegister(dest, 32), Operand(imm.value));
150 }
151 
152 void
or32(Register src,Register dest)153 MacroAssembler::or32(Register src, Register dest)
154 {
155     Orr(ARMRegister(dest, 32), ARMRegister(dest, 32), Operand(ARMRegister(src, 32)));
156 }
157 
158 void
or32(Imm32 imm,const Address & dest)159 MacroAssembler::or32(Imm32 imm, const Address& dest)
160 {
161     vixl::UseScratchRegisterScope temps(this);
162     const ARMRegister scratch32 = temps.AcquireW();
163     MOZ_ASSERT(scratch32.asUnsized() != dest.base);
164     load32(dest, scratch32.asUnsized());
165     Orr(scratch32, scratch32, Operand(imm.value));
166     store32(scratch32.asUnsized(), dest);
167 }
168 
169 void
orPtr(Register src,Register dest)170 MacroAssembler::orPtr(Register src, Register dest)
171 {
172     Orr(ARMRegister(dest, 64), ARMRegister(dest, 64), Operand(ARMRegister(src, 64)));
173 }
174 
175 void
orPtr(Imm32 imm,Register dest)176 MacroAssembler::orPtr(Imm32 imm, Register dest)
177 {
178     Orr(ARMRegister(dest, 64), ARMRegister(dest, 64), Operand(imm.value));
179 }
180 
181 void
or64(Register64 src,Register64 dest)182 MacroAssembler::or64(Register64 src, Register64 dest)
183 {
184     orPtr(src.reg, dest.reg);
185 }
186 
187 void
xor64(Register64 src,Register64 dest)188 MacroAssembler::xor64(Register64 src, Register64 dest)
189 {
190     xorPtr(src.reg, dest.reg);
191 }
192 
193 void
xor32(Register src,Register dest)194 MacroAssembler::xor32(Register src, Register dest)
195 {
196     Eor(ARMRegister(dest, 32), ARMRegister(dest, 32), Operand(ARMRegister(src, 32)));
197 }
198 
199 void
xor32(Imm32 imm,Register dest)200 MacroAssembler::xor32(Imm32 imm, Register dest)
201 {
202     Eor(ARMRegister(dest, 32), ARMRegister(dest, 32), Operand(imm.value));
203 }
204 
205 void
xorPtr(Register src,Register dest)206 MacroAssembler::xorPtr(Register src, Register dest)
207 {
208     Eor(ARMRegister(dest, 64), ARMRegister(dest, 64), Operand(ARMRegister(src, 64)));
209 }
210 
211 void
xorPtr(Imm32 imm,Register dest)212 MacroAssembler::xorPtr(Imm32 imm, Register dest)
213 {
214     Eor(ARMRegister(dest, 64), ARMRegister(dest, 64), Operand(imm.value));
215 }
216 
217 // ===============================================================
218 // Arithmetic functions
219 
220 void
add32(Register src,Register dest)221 MacroAssembler::add32(Register src, Register dest)
222 {
223     Add(ARMRegister(dest, 32), ARMRegister(dest, 32), Operand(ARMRegister(src, 32)));
224 }
225 
226 void
add32(Imm32 imm,Register dest)227 MacroAssembler::add32(Imm32 imm, Register dest)
228 {
229     Add(ARMRegister(dest, 32), ARMRegister(dest, 32), Operand(imm.value));
230 }
231 
232 void
add32(Imm32 imm,const Address & dest)233 MacroAssembler::add32(Imm32 imm, const Address& dest)
234 {
235     vixl::UseScratchRegisterScope temps(this);
236     const ARMRegister scratch32 = temps.AcquireW();
237     MOZ_ASSERT(scratch32.asUnsized() != dest.base);
238 
239     Ldr(scratch32, MemOperand(ARMRegister(dest.base, 64), dest.offset));
240     Add(scratch32, scratch32, Operand(imm.value));
241     Str(scratch32, MemOperand(ARMRegister(dest.base, 64), dest.offset));
242 }
243 
244 void
addPtr(Register src,Register dest)245 MacroAssembler::addPtr(Register src, Register dest)
246 {
247     addPtr(src, dest, dest);
248 }
249 
250 void
addPtr(Register src1,Register src2,Register dest)251 MacroAssembler::addPtr(Register src1, Register src2, Register dest)
252 {
253     Add(ARMRegister(dest, 64), ARMRegister(src1, 64), Operand(ARMRegister(src2, 64)));
254 }
255 
256 void
addPtr(Imm32 imm,Register dest)257 MacroAssembler::addPtr(Imm32 imm, Register dest)
258 {
259     addPtr(imm, dest, dest);
260 }
261 
262 void
addPtr(Imm32 imm,Register src,Register dest)263 MacroAssembler::addPtr(Imm32 imm, Register src, Register dest)
264 {
265     Add(ARMRegister(dest, 64), ARMRegister(src, 64), Operand(imm.value));
266 }
267 
268 void
addPtr(ImmWord imm,Register dest)269 MacroAssembler::addPtr(ImmWord imm, Register dest)
270 {
271     Add(ARMRegister(dest, 64), ARMRegister(dest, 64), Operand(imm.value));
272 }
273 
274 void
addPtr(Imm32 imm,const Address & dest)275 MacroAssembler::addPtr(Imm32 imm, const Address& dest)
276 {
277     vixl::UseScratchRegisterScope temps(this);
278     const ARMRegister scratch64 = temps.AcquireX();
279     MOZ_ASSERT(scratch64.asUnsized() != dest.base);
280 
281     Ldr(scratch64, MemOperand(ARMRegister(dest.base, 64), dest.offset));
282     Add(scratch64, scratch64, Operand(imm.value));
283     Str(scratch64, MemOperand(ARMRegister(dest.base, 64), dest.offset));
284 }
285 
286 void
addPtr(const Address & src,Register dest)287 MacroAssembler::addPtr(const Address& src, Register dest)
288 {
289     vixl::UseScratchRegisterScope temps(this);
290     const ARMRegister scratch64 = temps.AcquireX();
291     MOZ_ASSERT(scratch64.asUnsized() != src.base);
292 
293     Ldr(scratch64, MemOperand(ARMRegister(src.base, 64), src.offset));
294     Add(ARMRegister(dest, 64), ARMRegister(dest, 64), Operand(scratch64));
295 }
296 
297 void
add64(Register64 src,Register64 dest)298 MacroAssembler::add64(Register64 src, Register64 dest)
299 {
300     addPtr(src.reg, dest.reg);
301 }
302 
303 void
add64(Imm32 imm,Register64 dest)304 MacroAssembler::add64(Imm32 imm, Register64 dest)
305 {
306     Add(ARMRegister(dest.reg, 64), ARMRegister(dest.reg, 64), Operand(imm.value));
307 }
308 
309 void
addDouble(FloatRegister src,FloatRegister dest)310 MacroAssembler::addDouble(FloatRegister src, FloatRegister dest)
311 {
312     fadd(ARMFPRegister(dest, 64), ARMFPRegister(dest, 64), ARMFPRegister(src, 64));
313 }
314 
315 void
addFloat32(FloatRegister src,FloatRegister dest)316 MacroAssembler::addFloat32(FloatRegister src, FloatRegister dest)
317 {
318     fadd(ARMFPRegister(dest, 32), ARMFPRegister(dest, 32), ARMFPRegister(src, 32));
319 }
320 
321 void
sub32(Imm32 imm,Register dest)322 MacroAssembler::sub32(Imm32 imm, Register dest)
323 {
324     Sub(ARMRegister(dest, 32), ARMRegister(dest, 32), Operand(imm.value));
325 }
326 
327 void
sub32(Register src,Register dest)328 MacroAssembler::sub32(Register src, Register dest)
329 {
330     Sub(ARMRegister(dest, 32), ARMRegister(dest, 32), Operand(ARMRegister(src, 32)));
331 }
332 
333 void
sub32(const Address & src,Register dest)334 MacroAssembler::sub32(const Address& src, Register dest)
335 {
336     vixl::UseScratchRegisterScope temps(this);
337     const ARMRegister scratch32 = temps.AcquireW();
338     MOZ_ASSERT(scratch32.asUnsized() != src.base);
339     load32(src, scratch32.asUnsized());
340     Sub(ARMRegister(dest, 32), ARMRegister(dest, 32), Operand(scratch32));
341 }
342 
343 void
subPtr(Register src,Register dest)344 MacroAssembler::subPtr(Register src, Register dest)
345 {
346     Sub(ARMRegister(dest, 64), ARMRegister(dest, 64), Operand(ARMRegister(src, 64)));
347 }
348 
349 void
subPtr(Register src,const Address & dest)350 MacroAssembler::subPtr(Register src, const Address& dest)
351 {
352     vixl::UseScratchRegisterScope temps(this);
353     const ARMRegister scratch64 = temps.AcquireX();
354     MOZ_ASSERT(scratch64.asUnsized() != dest.base);
355 
356     Ldr(scratch64, MemOperand(ARMRegister(dest.base, 64), dest.offset));
357     Sub(scratch64, scratch64, Operand(ARMRegister(src, 64)));
358     Str(scratch64, MemOperand(ARMRegister(dest.base, 64), dest.offset));
359 }
360 
361 void
subPtr(Imm32 imm,Register dest)362 MacroAssembler::subPtr(Imm32 imm, Register dest)
363 {
364     Sub(ARMRegister(dest, 64), ARMRegister(dest, 64), Operand(imm.value));
365 }
366 
367 void
subPtr(const Address & addr,Register dest)368 MacroAssembler::subPtr(const Address& addr, Register dest)
369 {
370     vixl::UseScratchRegisterScope temps(this);
371     const ARMRegister scratch64 = temps.AcquireX();
372     MOZ_ASSERT(scratch64.asUnsized() != addr.base);
373 
374     Ldr(scratch64, MemOperand(ARMRegister(addr.base, 64), addr.offset));
375     Sub(ARMRegister(dest, 64), ARMRegister(dest, 64), Operand(scratch64));
376 }
377 
378 void
sub64(Register64 src,Register64 dest)379 MacroAssembler::sub64(Register64 src, Register64 dest)
380 {
381     MOZ_CRASH("NYI: sub64");
382 }
383 
384 void
subDouble(FloatRegister src,FloatRegister dest)385 MacroAssembler::subDouble(FloatRegister src, FloatRegister dest)
386 {
387     fsub(ARMFPRegister(dest, 64), ARMFPRegister(dest, 64), ARMFPRegister(src, 64));
388 }
389 
390 void
subFloat32(FloatRegister src,FloatRegister dest)391 MacroAssembler::subFloat32(FloatRegister src, FloatRegister dest)
392 {
393     fsub(ARMFPRegister(dest, 32), ARMFPRegister(dest, 32), ARMFPRegister(src, 32));
394 }
395 
396 void
mul32(Register rhs,Register srcDest)397 MacroAssembler::mul32(Register rhs, Register srcDest)
398 {
399     MOZ_CRASH("NYI - mul32");
400 }
401 
402 void
mul32(Register src1,Register src2,Register dest,Label * onOver,Label * onZero)403 MacroAssembler::mul32(Register src1, Register src2, Register dest, Label* onOver, Label* onZero)
404 {
405     Smull(ARMRegister(dest, 64), ARMRegister(src1, 32), ARMRegister(src2, 32));
406     if (onOver) {
407         Cmp(ARMRegister(dest, 64), Operand(ARMRegister(dest, 32), vixl::SXTW));
408         B(onOver, NotEqual);
409     }
410     if (onZero)
411         Cbz(ARMRegister(dest, 32), onZero);
412 
413     // Clear upper 32 bits.
414     Mov(ARMRegister(dest, 32), ARMRegister(dest, 32));
415 }
416 
417 void
mul64(Imm64 imm,const Register64 & dest)418 MacroAssembler::mul64(Imm64 imm, const Register64& dest)
419 {
420     vixl::UseScratchRegisterScope temps(this);
421     const ARMRegister scratch64 = temps.AcquireX();
422     MOZ_ASSERT(dest.reg != scratch64.asUnsized());
423     mov(ImmWord(imm.value), scratch64.asUnsized());
424     Mul(ARMRegister(dest.reg, 64), ARMRegister(dest.reg, 64), scratch64);
425 }
426 
427 void
mul64(const Register64 & src,const Register64 & dest,const Register temp)428 MacroAssembler::mul64(const Register64& src, const Register64& dest, const Register temp)
429 {
430     MOZ_CRASH("NYI: mul64");
431 }
432 
433 void
mulBy3(Register src,Register dest)434 MacroAssembler::mulBy3(Register src, Register dest)
435 {
436     ARMRegister xdest(dest, 64);
437     ARMRegister xsrc(src, 64);
438     Add(xdest, xsrc, Operand(xsrc, vixl::LSL, 1));
439 }
440 
441 void
mulFloat32(FloatRegister src,FloatRegister dest)442 MacroAssembler::mulFloat32(FloatRegister src, FloatRegister dest)
443 {
444     fmul(ARMFPRegister(dest, 32), ARMFPRegister(dest, 32), ARMFPRegister(src, 32));
445 }
446 
447 void
mulDouble(FloatRegister src,FloatRegister dest)448 MacroAssembler::mulDouble(FloatRegister src, FloatRegister dest)
449 {
450     fmul(ARMFPRegister(dest, 64), ARMFPRegister(dest, 64), ARMFPRegister(src, 64));
451 }
452 
453 void
mulDoublePtr(ImmPtr imm,Register temp,FloatRegister dest)454 MacroAssembler::mulDoublePtr(ImmPtr imm, Register temp, FloatRegister dest)
455 {
456     vixl::UseScratchRegisterScope temps(this);
457     const Register scratch = temps.AcquireX().asUnsized();
458     MOZ_ASSERT(temp != scratch);
459     movePtr(imm, scratch);
460     const ARMFPRegister scratchDouble = temps.AcquireD();
461     Ldr(scratchDouble, MemOperand(Address(scratch, 0)));
462     fmul(ARMFPRegister(dest, 64), ARMFPRegister(dest, 64), scratchDouble);
463 }
464 
465 void
quotient32(Register rhs,Register srcDest,bool isUnsigned)466 MacroAssembler::quotient32(Register rhs, Register srcDest, bool isUnsigned)
467 {
468     MOZ_CRASH("NYI - quotient32");
469 }
470 
471 void
remainder32(Register rhs,Register srcDest,bool isUnsigned)472 MacroAssembler::remainder32(Register rhs, Register srcDest, bool isUnsigned)
473 {
474     MOZ_CRASH("NYI - remainder32");
475 }
476 
477 void
divFloat32(FloatRegister src,FloatRegister dest)478 MacroAssembler::divFloat32(FloatRegister src, FloatRegister dest)
479 {
480     fdiv(ARMFPRegister(dest, 32), ARMFPRegister(dest, 32), ARMFPRegister(src, 32));
481 }
482 
483 void
divDouble(FloatRegister src,FloatRegister dest)484 MacroAssembler::divDouble(FloatRegister src, FloatRegister dest)
485 {
486     fdiv(ARMFPRegister(dest, 64), ARMFPRegister(dest, 64), ARMFPRegister(src, 64));
487 }
488 
489 void
inc64(AbsoluteAddress dest)490 MacroAssembler::inc64(AbsoluteAddress dest)
491 {
492     vixl::UseScratchRegisterScope temps(this);
493     const ARMRegister scratchAddr64 = temps.AcquireX();
494     const ARMRegister scratch64 = temps.AcquireX();
495 
496     Mov(scratchAddr64, uint64_t(dest.addr));
497     Ldr(scratch64, MemOperand(scratchAddr64, 0));
498     Add(scratch64, scratch64, Operand(1));
499     Str(scratch64, MemOperand(scratchAddr64, 0));
500 }
501 
502 void
neg32(Register reg)503 MacroAssembler::neg32(Register reg)
504 {
505     Negs(ARMRegister(reg, 32), Operand(ARMRegister(reg, 32)));
506 }
507 
508 void
negateFloat(FloatRegister reg)509 MacroAssembler::negateFloat(FloatRegister reg)
510 {
511     fneg(ARMFPRegister(reg, 32), ARMFPRegister(reg, 32));
512 }
513 
514 void
negateDouble(FloatRegister reg)515 MacroAssembler::negateDouble(FloatRegister reg)
516 {
517     fneg(ARMFPRegister(reg, 64), ARMFPRegister(reg, 64));
518 }
519 
520 void
absFloat32(FloatRegister src,FloatRegister dest)521 MacroAssembler::absFloat32(FloatRegister src, FloatRegister dest)
522 {
523     MOZ_CRASH("NYI - absFloat32");
524 }
525 
526 void
absDouble(FloatRegister src,FloatRegister dest)527 MacroAssembler::absDouble(FloatRegister src, FloatRegister dest)
528 {
529     MOZ_CRASH("NYI - absDouble");
530 }
531 
532 void
sqrtFloat32(FloatRegister src,FloatRegister dest)533 MacroAssembler::sqrtFloat32(FloatRegister src, FloatRegister dest)
534 {
535     MOZ_CRASH("NYI - sqrtFloat32");
536 }
537 
538 void
sqrtDouble(FloatRegister src,FloatRegister dest)539 MacroAssembler::sqrtDouble(FloatRegister src, FloatRegister dest)
540 {
541     MOZ_CRASH("NYI - sqrtDouble");
542 }
543 
544 void
minFloat32(FloatRegister other,FloatRegister srcDest,bool handleNaN)545 MacroAssembler::minFloat32(FloatRegister other, FloatRegister srcDest, bool handleNaN)
546 {
547     MOZ_CRASH("NYI - minFloat32");
548 }
549 
550 void
minDouble(FloatRegister other,FloatRegister srcDest,bool handleNaN)551 MacroAssembler::minDouble(FloatRegister other, FloatRegister srcDest, bool handleNaN)
552 {
553     MOZ_CRASH("NYI - minDouble");
554 }
555 
556 void
maxFloat32(FloatRegister other,FloatRegister srcDest,bool handleNaN)557 MacroAssembler::maxFloat32(FloatRegister other, FloatRegister srcDest, bool handleNaN)
558 {
559     MOZ_CRASH("NYI - maxFloat32");
560 }
561 
562 void
maxDouble(FloatRegister other,FloatRegister srcDest,bool handleNaN)563 MacroAssembler::maxDouble(FloatRegister other, FloatRegister srcDest, bool handleNaN)
564 {
565     MOZ_CRASH("NYI - maxDouble");
566 }
567 
568 // ===============================================================
569 // Shift functions
570 
571 void
lshiftPtr(Imm32 imm,Register dest)572 MacroAssembler::lshiftPtr(Imm32 imm, Register dest)
573 {
574     MOZ_ASSERT(0 <= imm.value && imm.value < 64);
575     Lsl(ARMRegister(dest, 64), ARMRegister(dest, 64), imm.value);
576 }
577 
578 void
lshift64(Imm32 imm,Register64 dest)579 MacroAssembler::lshift64(Imm32 imm, Register64 dest)
580 {
581     MOZ_ASSERT(0 <= imm.value && imm.value < 64);
582     lshiftPtr(imm, dest.reg);
583 }
584 
585 void
lshift64(Register shift,Register64 srcDest)586 MacroAssembler::lshift64(Register shift, Register64 srcDest)
587 {
588     MOZ_CRASH("NYI: lshift64");
589 }
590 
591 void
lshift32(Register shift,Register dest)592 MacroAssembler::lshift32(Register shift, Register dest)
593 {
594     Lsl(ARMRegister(dest, 32), ARMRegister(dest, 32), ARMRegister(shift, 32));
595 }
596 
597 void
lshift32(Imm32 imm,Register dest)598 MacroAssembler::lshift32(Imm32 imm, Register dest)
599 {
600     MOZ_ASSERT(0 <= imm.value && imm.value < 32);
601     Lsl(ARMRegister(dest, 32), ARMRegister(dest, 32), imm.value);
602 }
603 
604 void
rshiftPtr(Imm32 imm,Register dest)605 MacroAssembler::rshiftPtr(Imm32 imm, Register dest)
606 {
607     MOZ_ASSERT(0 <= imm.value && imm.value < 64);
608     Lsr(ARMRegister(dest, 64), ARMRegister(dest, 64), imm.value);
609 }
610 
611 void
rshiftPtr(Imm32 imm,Register src,Register dest)612 MacroAssembler::rshiftPtr(Imm32 imm, Register src, Register dest)
613 {
614     MOZ_ASSERT(0 <= imm.value && imm.value < 64);
615     Lsr(ARMRegister(dest, 64), ARMRegister(src, 64), imm.value);
616 }
617 
618 void
rshift32(Register shift,Register dest)619 MacroAssembler::rshift32(Register shift, Register dest)
620 {
621     Lsr(ARMRegister(dest, 32), ARMRegister(dest, 32), ARMRegister(shift, 32));
622 }
623 
624 void
rshift32(Imm32 imm,Register dest)625 MacroAssembler::rshift32(Imm32 imm, Register dest)
626 {
627     MOZ_ASSERT(0 <= imm.value && imm.value < 32);
628     Lsr(ARMRegister(dest, 32), ARMRegister(dest, 32), imm.value);
629 }
630 
631 void
rshiftPtrArithmetic(Imm32 imm,Register dest)632 MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register dest)
633 {
634     MOZ_ASSERT(0 <= imm.value && imm.value < 64);
635     Asr(ARMRegister(dest, 64), ARMRegister(dest, 64), imm.value);
636 }
637 
638 void
rshift32Arithmetic(Register shift,Register dest)639 MacroAssembler::rshift32Arithmetic(Register shift, Register dest)
640 {
641     Asr(ARMRegister(dest, 32), ARMRegister(dest, 32), ARMRegister(shift, 32));
642 }
643 
644 void
rshift32Arithmetic(Imm32 imm,Register dest)645 MacroAssembler::rshift32Arithmetic(Imm32 imm, Register dest)
646 {
647     MOZ_ASSERT(0 <= imm.value && imm.value < 32);
648     Asr(ARMRegister(dest, 32), ARMRegister(dest, 32), imm.value);
649 }
650 
651 void
rshift64(Imm32 imm,Register64 dest)652 MacroAssembler::rshift64(Imm32 imm, Register64 dest)
653 {
654     MOZ_ASSERT(0 <= imm.value && imm.value < 64);
655     rshiftPtr(imm, dest.reg);
656 }
657 
658 void
rshift64(Register shift,Register64 srcDest)659 MacroAssembler::rshift64(Register shift, Register64 srcDest)
660 {
661     MOZ_CRASH("NYI: rshift64");
662 }
663 
664 void
rshift64Arithmetic(Imm32 imm,Register64 dest)665 MacroAssembler::rshift64Arithmetic(Imm32 imm, Register64 dest)
666 {
667     MOZ_CRASH("NYI: rshift64Arithmetic");
668 }
669 
670 void
rshift64Arithmetic(Register shift,Register64 srcDest)671 MacroAssembler::rshift64Arithmetic(Register shift, Register64 srcDest)
672 {
673     MOZ_CRASH("NYI: rshift64Arithmetic");
674 }
675 
676 // ===============================================================
677 // Condition functions
678 
679 template <typename T1, typename T2>
680 void
cmp32Set(Condition cond,T1 lhs,T2 rhs,Register dest)681 MacroAssembler::cmp32Set(Condition cond, T1 lhs, T2 rhs, Register dest)
682 {
683     cmp32(lhs, rhs);
684     emitSet(cond, dest);
685 }
686 
687 template <typename T1, typename T2>
688 void
cmpPtrSet(Condition cond,T1 lhs,T2 rhs,Register dest)689 MacroAssembler::cmpPtrSet(Condition cond, T1 lhs, T2 rhs, Register dest)
690 {
691     cmpPtr(lhs, rhs);
692     emitSet(cond, dest);
693 }
694 
695 // ===============================================================
696 // Rotation functions
697 
698 void
rotateLeft(Imm32 count,Register input,Register dest)699 MacroAssembler::rotateLeft(Imm32 count, Register input, Register dest)
700 {
701     MOZ_CRASH("NYI: rotateLeft by immediate");
702 }
703 
704 void
rotateLeft(Register count,Register input,Register dest)705 MacroAssembler::rotateLeft(Register count, Register input, Register dest)
706 {
707     MOZ_CRASH("NYI: rotateLeft by register");
708 }
709 
710 void
rotateRight(Imm32 count,Register input,Register dest)711 MacroAssembler::rotateRight(Imm32 count, Register input, Register dest)
712 {
713     MOZ_CRASH("NYI: rotateRight by immediate");
714 }
715 
716 void
rotateRight(Register count,Register input,Register dest)717 MacroAssembler::rotateRight(Register count, Register input, Register dest)
718 {
719     MOZ_CRASH("NYI: rotateRight by register");
720 }
721 
722 void
rotateLeft64(Register count,Register64 input,Register64 dest,Register temp)723 MacroAssembler::rotateLeft64(Register count, Register64 input, Register64 dest, Register temp)
724 {
725     MOZ_CRASH("NYI: rotateLeft64");
726 }
727 
728 void
rotateRight64(Register count,Register64 input,Register64 dest,Register temp)729 MacroAssembler::rotateRight64(Register count, Register64 input, Register64 dest, Register temp)
730 {
731     MOZ_CRASH("NYI: rotateRight64");
732 }
733 
734 // ===============================================================
735 // Bit counting functions
736 
737 void
clz32(Register src,Register dest,bool knownNotZero)738 MacroAssembler::clz32(Register src, Register dest, bool knownNotZero)
739 {
740     MOZ_CRASH("NYI: clz32");
741 }
742 
743 void
ctz32(Register src,Register dest,bool knownNotZero)744 MacroAssembler::ctz32(Register src, Register dest, bool knownNotZero)
745 {
746     MOZ_CRASH("NYI: ctz32");
747 }
748 
749 void
clz64(Register64 src,Register dest)750 MacroAssembler::clz64(Register64 src, Register dest)
751 {
752     MOZ_CRASH("NYI: clz64");
753 }
754 
755 void
ctz64(Register64 src,Register dest)756 MacroAssembler::ctz64(Register64 src, Register dest)
757 {
758     MOZ_CRASH("NYI: ctz64");
759 }
760 
761 void
popcnt32(Register src,Register dest,Register temp)762 MacroAssembler::popcnt32(Register src, Register dest, Register temp)
763 {
764     MOZ_CRASH("NYI: popcnt32");
765 }
766 
767 void
popcnt64(Register64 src,Register64 dest,Register temp)768 MacroAssembler::popcnt64(Register64 src, Register64 dest, Register temp)
769 {
770     MOZ_CRASH("NYI: popcnt64");
771 }
772 
773 // ===============================================================
774 // Branch functions
775 
776 template <class L>
777 void
branch32(Condition cond,Register lhs,Register rhs,L label)778 MacroAssembler::branch32(Condition cond, Register lhs, Register rhs, L label)
779 {
780     cmp32(lhs, rhs);
781     B(label, cond);
782 }
783 
784 template <class L>
785 void
branch32(Condition cond,Register lhs,Imm32 imm,L label)786 MacroAssembler::branch32(Condition cond, Register lhs, Imm32 imm, L label)
787 {
788     cmp32(lhs, imm);
789     B(label, cond);
790 }
791 
792 void
branch32(Condition cond,const Address & lhs,Register rhs,Label * label)793 MacroAssembler::branch32(Condition cond, const Address& lhs, Register rhs, Label* label)
794 {
795     vixl::UseScratchRegisterScope temps(this);
796     const Register scratch = temps.AcquireX().asUnsized();
797     MOZ_ASSERT(scratch != lhs.base);
798     MOZ_ASSERT(scratch != rhs);
799     load32(lhs, scratch);
800     branch32(cond, scratch, rhs, label);
801 }
802 
803 void
branch32(Condition cond,const Address & lhs,Imm32 imm,Label * label)804 MacroAssembler::branch32(Condition cond, const Address& lhs, Imm32 imm, Label* label)
805 {
806     vixl::UseScratchRegisterScope temps(this);
807     const Register scratch = temps.AcquireX().asUnsized();
808     MOZ_ASSERT(scratch != lhs.base);
809     load32(lhs, scratch);
810     branch32(cond, scratch, imm, label);
811 }
812 
813 void
branch32(Condition cond,const AbsoluteAddress & lhs,Register rhs,Label * label)814 MacroAssembler::branch32(Condition cond, const AbsoluteAddress& lhs, Register rhs, Label* label)
815 {
816     vixl::UseScratchRegisterScope temps(this);
817     const Register scratch = temps.AcquireX().asUnsized();
818     movePtr(ImmPtr(lhs.addr), scratch);
819     branch32(cond, Address(scratch, 0), rhs, label);
820 }
821 
822 void
branch32(Condition cond,const AbsoluteAddress & lhs,Imm32 rhs,Label * label)823 MacroAssembler::branch32(Condition cond, const AbsoluteAddress& lhs, Imm32 rhs, Label* label)
824 {
825     vixl::UseScratchRegisterScope temps(this);
826     const Register scratch = temps.AcquireX().asUnsized();
827     movePtr(ImmPtr(lhs.addr), scratch);
828     branch32(cond, Address(scratch, 0), rhs, label);
829 }
830 
831 void
branch32(Condition cond,const BaseIndex & lhs,Imm32 rhs,Label * label)832 MacroAssembler::branch32(Condition cond, const BaseIndex& lhs, Imm32 rhs, Label* label)
833 {
834     vixl::UseScratchRegisterScope temps(this);
835     const ARMRegister scratch32 = temps.AcquireW();
836     MOZ_ASSERT(scratch32.asUnsized() != lhs.base);
837     MOZ_ASSERT(scratch32.asUnsized() != lhs.index);
838     doBaseIndex(scratch32, lhs, vixl::LDR_w);
839     branch32(cond, scratch32.asUnsized(), rhs, label);
840 }
841 
842 void
branch32(Condition cond,wasm::SymbolicAddress lhs,Imm32 rhs,Label * label)843 MacroAssembler::branch32(Condition cond, wasm::SymbolicAddress lhs, Imm32 rhs, Label* label)
844 {
845     vixl::UseScratchRegisterScope temps(this);
846     const Register scratch = temps.AcquireX().asUnsized();
847     movePtr(lhs, scratch);
848     branch32(cond, Address(scratch, 0), rhs, label);
849 }
850 
851 void
branch64(Condition cond,Register64 lhs,Imm64 val,Label * success,Label * fail)852 MacroAssembler::branch64(Condition cond, Register64 lhs, Imm64 val, Label* success, Label* fail)
853 {
854     MOZ_CRASH("NYI: branch64 reg-imm");
855 }
856 
857 void
branch64(Condition cond,const Address & lhs,Imm64 val,Label * label)858 MacroAssembler::branch64(Condition cond, const Address& lhs, Imm64 val, Label* label)
859 {
860     MOZ_ASSERT(cond == Assembler::NotEqual,
861                "other condition codes not supported");
862 
863     branchPtr(cond, lhs, ImmWord(val.value), label);
864 }
865 
866 void
branch64(Condition cond,const Address & lhs,const Address & rhs,Register scratch,Label * label)867 MacroAssembler::branch64(Condition cond, const Address& lhs, const Address& rhs, Register scratch,
868                          Label* label)
869 {
870     MOZ_ASSERT(cond == Assembler::NotEqual,
871                "other condition codes not supported");
872     MOZ_ASSERT(lhs.base != scratch);
873     MOZ_ASSERT(rhs.base != scratch);
874 
875     loadPtr(rhs, scratch);
876     branchPtr(cond, lhs, scratch, label);
877 }
878 
879 template <class L>
880 void
branchPtr(Condition cond,Register lhs,Register rhs,L label)881 MacroAssembler::branchPtr(Condition cond, Register lhs, Register rhs, L label)
882 {
883     Cmp(ARMRegister(lhs, 64), ARMRegister(rhs, 64));
884     B(label, cond);
885 }
886 
887 void
branchPtr(Condition cond,Register lhs,Imm32 rhs,Label * label)888 MacroAssembler::branchPtr(Condition cond, Register lhs, Imm32 rhs, Label* label)
889 {
890     cmpPtr(lhs, rhs);
891     B(label, cond);
892 }
893 
894 void
branchPtr(Condition cond,Register lhs,ImmPtr rhs,Label * label)895 MacroAssembler::branchPtr(Condition cond, Register lhs, ImmPtr rhs, Label* label)
896 {
897     cmpPtr(lhs, rhs);
898     B(label, cond);
899 }
900 
901 void
branchPtr(Condition cond,Register lhs,ImmGCPtr rhs,Label * label)902 MacroAssembler::branchPtr(Condition cond, Register lhs, ImmGCPtr rhs, Label* label)
903 {
904     vixl::UseScratchRegisterScope temps(this);
905     const Register scratch = temps.AcquireX().asUnsized();
906     MOZ_ASSERT(scratch != lhs);
907     movePtr(rhs, scratch);
908     branchPtr(cond, lhs, scratch, label);
909 }
910 
911 void
branchPtr(Condition cond,Register lhs,ImmWord rhs,Label * label)912 MacroAssembler::branchPtr(Condition cond, Register lhs, ImmWord rhs, Label* label)
913 {
914     cmpPtr(lhs, rhs);
915     B(label, cond);
916 }
917 
918 template <class L>
919 void
branchPtr(Condition cond,const Address & lhs,Register rhs,L label)920 MacroAssembler::branchPtr(Condition cond, const Address& lhs, Register rhs, L label)
921 {
922     vixl::UseScratchRegisterScope temps(this);
923     const Register scratch = temps.AcquireX().asUnsized();
924     MOZ_ASSERT(scratch != lhs.base);
925     MOZ_ASSERT(scratch != rhs);
926     loadPtr(lhs, scratch);
927     branchPtr(cond, scratch, rhs, label);
928 }
929 
930 void
branchPtr(Condition cond,const Address & lhs,ImmPtr rhs,Label * label)931 MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmPtr rhs, Label* label)
932 {
933     vixl::UseScratchRegisterScope temps(this);
934     const Register scratch = temps.AcquireX().asUnsized();
935     MOZ_ASSERT(scratch != lhs.base);
936     loadPtr(lhs, scratch);
937     branchPtr(cond, scratch, rhs, label);
938 }
939 
940 void
branchPtr(Condition cond,const Address & lhs,ImmGCPtr rhs,Label * label)941 MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmGCPtr rhs, Label* label)
942 {
943     vixl::UseScratchRegisterScope temps(this);
944     const ARMRegister scratch1_64 = temps.AcquireX();
945     const ARMRegister scratch2_64 = temps.AcquireX();
946     MOZ_ASSERT(scratch1_64.asUnsized() != lhs.base);
947     MOZ_ASSERT(scratch2_64.asUnsized() != lhs.base);
948 
949     movePtr(rhs, scratch1_64.asUnsized());
950     loadPtr(lhs, scratch2_64.asUnsized());
951     branchPtr(cond, scratch2_64.asUnsized(), scratch1_64.asUnsized(), label);
952 }
953 
954 void
branchPtr(Condition cond,const Address & lhs,ImmWord rhs,Label * label)955 MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmWord rhs, Label* label)
956 {
957     vixl::UseScratchRegisterScope temps(this);
958     const Register scratch = temps.AcquireX().asUnsized();
959     MOZ_ASSERT(scratch != lhs.base);
960     loadPtr(lhs, scratch);
961     branchPtr(cond, scratch, rhs, label);
962 }
963 
964 void
branchPtr(Condition cond,const AbsoluteAddress & lhs,Register rhs,Label * label)965 MacroAssembler::branchPtr(Condition cond, const AbsoluteAddress& lhs, Register rhs, Label* label)
966 {
967     vixl::UseScratchRegisterScope temps(this);
968     const Register scratch = temps.AcquireX().asUnsized();
969     MOZ_ASSERT(scratch != rhs);
970     loadPtr(lhs, scratch);
971     branchPtr(cond, scratch, rhs, label);
972 }
973 
974 void
branchPtr(Condition cond,const AbsoluteAddress & lhs,ImmWord rhs,Label * label)975 MacroAssembler::branchPtr(Condition cond, const AbsoluteAddress& lhs, ImmWord rhs, Label* label)
976 {
977     vixl::UseScratchRegisterScope temps(this);
978     const Register scratch = temps.AcquireX().asUnsized();
979     loadPtr(lhs, scratch);
980     branchPtr(cond, scratch, rhs, label);
981 }
982 
983 void
branchPtr(Condition cond,wasm::SymbolicAddress lhs,Register rhs,Label * label)984 MacroAssembler::branchPtr(Condition cond, wasm::SymbolicAddress lhs, Register rhs, Label* label)
985 {
986     vixl::UseScratchRegisterScope temps(this);
987     const Register scratch = temps.AcquireX().asUnsized();
988     MOZ_ASSERT(scratch != rhs);
989     loadPtr(lhs, scratch);
990     branchPtr(cond, scratch, rhs, label);
991 }
992 
993 template <typename T>
994 CodeOffsetJump
branchPtrWithPatch(Condition cond,Register lhs,T rhs,RepatchLabel * label)995 MacroAssembler::branchPtrWithPatch(Condition cond, Register lhs, T rhs, RepatchLabel* label)
996 {
997     cmpPtr(lhs, rhs);
998     return jumpWithPatch(label, cond);
999 }
1000 
1001 template <typename T>
1002 CodeOffsetJump
branchPtrWithPatch(Condition cond,Address lhs,T rhs,RepatchLabel * label)1003 MacroAssembler::branchPtrWithPatch(Condition cond, Address lhs, T rhs, RepatchLabel* label)
1004 {
1005     // The scratch register is unused after the condition codes are set.
1006     {
1007         vixl::UseScratchRegisterScope temps(this);
1008         const Register scratch = temps.AcquireX().asUnsized();
1009         MOZ_ASSERT(scratch != lhs.base);
1010         loadPtr(lhs, scratch);
1011         cmpPtr(scratch, rhs);
1012     }
1013     return jumpWithPatch(label, cond);
1014 }
1015 
1016 void
branchPrivatePtr(Condition cond,const Address & lhs,Register rhs,Label * label)1017 MacroAssembler::branchPrivatePtr(Condition cond, const Address& lhs, Register rhs, Label* label)
1018 {
1019     vixl::UseScratchRegisterScope temps(this);
1020     const Register scratch = temps.AcquireX().asUnsized();
1021     if (rhs != scratch)
1022         movePtr(rhs, scratch);
1023     // Instead of unboxing lhs, box rhs and do direct comparison with lhs.
1024     rshiftPtr(Imm32(1), scratch);
1025     branchPtr(cond, lhs, scratch, label);
1026 }
1027 
1028 void
branchFloat(DoubleCondition cond,FloatRegister lhs,FloatRegister rhs,Label * label)1029 MacroAssembler::branchFloat(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs,
1030                             Label* label)
1031 {
1032     compareFloat(cond, lhs, rhs);
1033     switch (cond) {
1034       case DoubleNotEqual: {
1035         Label unordered;
1036         // not equal *and* ordered
1037         branch(Overflow, &unordered);
1038         branch(NotEqual, label);
1039         bind(&unordered);
1040         break;
1041       }
1042       case DoubleEqualOrUnordered:
1043         branch(Overflow, label);
1044         branch(Equal, label);
1045         break;
1046       default:
1047         branch(Condition(cond), label);
1048     }
1049 }
1050 
1051 void
branchTruncateFloat32MaybeModUint32(FloatRegister src,Register dest,Label * fail)1052 MacroAssembler::branchTruncateFloat32MaybeModUint32(FloatRegister src, Register dest, Label* fail)
1053 {
1054     vixl::UseScratchRegisterScope temps(this);
1055     const ARMRegister scratch64 = temps.AcquireX();
1056 
1057     ARMFPRegister src32(src, 32);
1058     ARMRegister dest64(dest, 64);
1059 
1060     MOZ_ASSERT(!scratch64.Is(dest64));
1061 
1062     Fcvtzs(dest64, src32);
1063     Add(scratch64, dest64, Operand(0x7fffffffffffffff));
1064     Cmn(scratch64, 3);
1065     B(fail, Assembler::Above);
1066     And(dest64, dest64, Operand(0xffffffff));
1067 }
1068 
1069 void
branchTruncateFloat32ToInt32(FloatRegister src,Register dest,Label * fail)1070 MacroAssembler::branchTruncateFloat32ToInt32(FloatRegister src, Register dest, Label* fail)
1071 {
1072     convertFloat32ToInt32(src, dest, fail);
1073 }
1074 
1075 void
branchDouble(DoubleCondition cond,FloatRegister lhs,FloatRegister rhs,Label * label)1076 MacroAssembler::branchDouble(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs,
1077                              Label* label)
1078 {
1079     compareDouble(cond, lhs, rhs);
1080     switch (cond) {
1081       case DoubleNotEqual: {
1082         Label unordered;
1083         // not equal *and* ordered
1084         branch(Overflow, &unordered);
1085         branch(NotEqual, label);
1086         bind(&unordered);
1087         break;
1088       }
1089       case DoubleEqualOrUnordered:
1090         branch(Overflow, label);
1091         branch(Equal, label);
1092         break;
1093       default:
1094         branch(Condition(cond), label);
1095     }
1096 }
1097 
1098 void
branchTruncateDoubleMaybeModUint32(FloatRegister src,Register dest,Label * fail)1099 MacroAssembler::branchTruncateDoubleMaybeModUint32(FloatRegister src, Register dest, Label* fail)
1100 {
1101     vixl::UseScratchRegisterScope temps(this);
1102     const ARMRegister scratch64 = temps.AcquireX();
1103 
1104     // An out of range integer will be saturated to the destination size.
1105     ARMFPRegister src64(src, 64);
1106     ARMRegister dest64(dest, 64);
1107 
1108     MOZ_ASSERT(!scratch64.Is(dest64));
1109 
1110     Fcvtzs(dest64, src64);
1111     Add(scratch64, dest64, Operand(0x7fffffffffffffff));
1112     Cmn(scratch64, 3);
1113     B(fail, Assembler::Above);
1114     And(dest64, dest64, Operand(0xffffffff));
1115 }
1116 
1117 void
branchTruncateDoubleToInt32(FloatRegister src,Register dest,Label * fail)1118 MacroAssembler::branchTruncateDoubleToInt32(FloatRegister src, Register dest, Label* fail)
1119 {
1120     convertDoubleToInt32(src, dest, fail);
1121 }
1122 
1123 template <typename T, typename L>
1124 void
branchAdd32(Condition cond,T src,Register dest,L label)1125 MacroAssembler::branchAdd32(Condition cond, T src, Register dest, L label)
1126 {
1127     adds32(src, dest);
1128     B(label, cond);
1129 }
1130 
1131 template <typename T>
1132 void
branchSub32(Condition cond,T src,Register dest,Label * label)1133 MacroAssembler::branchSub32(Condition cond, T src, Register dest, Label* label)
1134 {
1135     subs32(src, dest);
1136     branch(cond, label);
1137 }
1138 
1139 void
decBranchPtr(Condition cond,Register lhs,Imm32 rhs,Label * label)1140 MacroAssembler::decBranchPtr(Condition cond, Register lhs, Imm32 rhs, Label* label)
1141 {
1142     Subs(ARMRegister(lhs, 64), ARMRegister(lhs, 64), Operand(rhs.value));
1143     B(cond, label);
1144 }
1145 
1146 template <class L>
1147 void
branchTest32(Condition cond,Register lhs,Register rhs,L label)1148 MacroAssembler::branchTest32(Condition cond, Register lhs, Register rhs, L label)
1149 {
1150     MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
1151     // x86 prefers |test foo, foo| to |cmp foo, #0|.
1152     // Convert the former to the latter for ARM.
1153     if (lhs == rhs && (cond == Zero || cond == NonZero))
1154         cmp32(lhs, Imm32(0));
1155     else
1156         test32(lhs, rhs);
1157     B(label, cond);
1158 }
1159 
1160 template <class L>
1161 void
branchTest32(Condition cond,Register lhs,Imm32 rhs,L label)1162 MacroAssembler::branchTest32(Condition cond, Register lhs, Imm32 rhs, L label)
1163 {
1164     MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
1165     test32(lhs, rhs);
1166     B(label, cond);
1167 }
1168 
1169 void
branchTest32(Condition cond,const Address & lhs,Imm32 rhs,Label * label)1170 MacroAssembler::branchTest32(Condition cond, const Address& lhs, Imm32 rhs, Label* label)
1171 {
1172     vixl::UseScratchRegisterScope temps(this);
1173     const Register scratch = temps.AcquireX().asUnsized();
1174     MOZ_ASSERT(scratch != lhs.base);
1175     load32(lhs, scratch);
1176     branchTest32(cond, scratch, rhs, label);
1177 }
1178 
1179 void
branchTest32(Condition cond,const AbsoluteAddress & lhs,Imm32 rhs,Label * label)1180 MacroAssembler::branchTest32(Condition cond, const AbsoluteAddress& lhs, Imm32 rhs, Label* label)
1181 {
1182     vixl::UseScratchRegisterScope temps(this);
1183     const Register scratch = temps.AcquireX().asUnsized();
1184     load32(lhs, scratch);
1185     branchTest32(cond, scratch, rhs, label);
1186 }
1187 
1188 template <class L>
1189 void
branchTestPtr(Condition cond,Register lhs,Register rhs,L label)1190 MacroAssembler::branchTestPtr(Condition cond, Register lhs, Register rhs, L label)
1191 {
1192     Tst(ARMRegister(lhs, 64), Operand(ARMRegister(rhs, 64)));
1193     B(label, cond);
1194 }
1195 
1196 void
branchTestPtr(Condition cond,Register lhs,Imm32 rhs,Label * label)1197 MacroAssembler::branchTestPtr(Condition cond, Register lhs, Imm32 rhs, Label* label)
1198 {
1199     Tst(ARMRegister(lhs, 64), Operand(rhs.value));
1200     B(label, cond);
1201 }
1202 
1203 void
branchTestPtr(Condition cond,const Address & lhs,Imm32 rhs,Label * label)1204 MacroAssembler::branchTestPtr(Condition cond, const Address& lhs, Imm32 rhs, Label* label)
1205 {
1206     vixl::UseScratchRegisterScope temps(this);
1207     const Register scratch = temps.AcquireX().asUnsized();
1208     MOZ_ASSERT(scratch != lhs.base);
1209     loadPtr(lhs, scratch);
1210     branchTestPtr(cond, scratch, rhs, label);
1211 }
1212 
1213 template <class L>
1214 void
branchTest64(Condition cond,Register64 lhs,Register64 rhs,Register temp,L label)1215 MacroAssembler::branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp,
1216                              L label)
1217 {
1218     branchTestPtr(cond, lhs.reg, rhs.reg, label);
1219 }
1220 
1221 void
branchTestUndefined(Condition cond,Register tag,Label * label)1222 MacroAssembler::branchTestUndefined(Condition cond, Register tag, Label* label)
1223 {
1224     branchTestUndefinedImpl(cond, tag, label);
1225 }
1226 
1227 void
branchTestUndefined(Condition cond,const Address & address,Label * label)1228 MacroAssembler::branchTestUndefined(Condition cond, const Address& address, Label* label)
1229 {
1230     branchTestUndefinedImpl(cond, address, label);
1231 }
1232 
1233 void
branchTestUndefined(Condition cond,const BaseIndex & address,Label * label)1234 MacroAssembler::branchTestUndefined(Condition cond, const BaseIndex& address, Label* label)
1235 {
1236     branchTestUndefinedImpl(cond, address, label);
1237 }
1238 
1239 void
branchTestUndefined(Condition cond,const ValueOperand & value,Label * label)1240 MacroAssembler::branchTestUndefined(Condition cond, const ValueOperand& value, Label* label)
1241 {
1242     branchTestUndefinedImpl(cond, value, label);
1243 }
1244 
1245 template <typename T>
1246 void
branchTestUndefinedImpl(Condition cond,const T & t,Label * label)1247 MacroAssembler::branchTestUndefinedImpl(Condition cond, const T& t, Label* label)
1248 {
1249     Condition c = testUndefined(cond, t);
1250     B(label, c);
1251 }
1252 
1253 void
branchTestInt32(Condition cond,Register tag,Label * label)1254 MacroAssembler::branchTestInt32(Condition cond, Register tag, Label* label)
1255 {
1256     branchTestInt32Impl(cond, tag, label);
1257 }
1258 
1259 void
branchTestInt32(Condition cond,const Address & address,Label * label)1260 MacroAssembler::branchTestInt32(Condition cond, const Address& address, Label* label)
1261 {
1262     branchTestInt32Impl(cond, address, label);
1263 }
1264 
1265 void
branchTestInt32(Condition cond,const BaseIndex & address,Label * label)1266 MacroAssembler::branchTestInt32(Condition cond, const BaseIndex& address, Label* label)
1267 {
1268     branchTestInt32Impl(cond, address, label);
1269 }
1270 
1271 void
branchTestInt32(Condition cond,const ValueOperand & value,Label * label)1272 MacroAssembler::branchTestInt32(Condition cond, const ValueOperand& value, Label* label)
1273 {
1274     branchTestInt32Impl(cond, value, label);
1275 }
1276 
1277 template <typename T>
1278 void
branchTestInt32Impl(Condition cond,const T & t,Label * label)1279 MacroAssembler::branchTestInt32Impl(Condition cond, const T& t, Label* label)
1280 {
1281     Condition c = testInt32(cond, t);
1282     B(label, c);
1283 }
1284 
1285 void
branchTestInt32Truthy(bool truthy,const ValueOperand & value,Label * label)1286 MacroAssembler::branchTestInt32Truthy(bool truthy, const ValueOperand& value, Label* label)
1287 {
1288     Condition c = testInt32Truthy(truthy, value);
1289     B(label, c);
1290 }
1291 
1292 void
branchTestDouble(Condition cond,Register tag,Label * label)1293 MacroAssembler::branchTestDouble(Condition cond, Register tag, Label* label)
1294 {
1295     branchTestDoubleImpl(cond, tag, label);
1296 }
1297 
1298 void
branchTestDouble(Condition cond,const Address & address,Label * label)1299 MacroAssembler::branchTestDouble(Condition cond, const Address& address, Label* label)
1300 {
1301     branchTestDoubleImpl(cond, address, label);
1302 }
1303 
1304 void
branchTestDouble(Condition cond,const BaseIndex & address,Label * label)1305 MacroAssembler::branchTestDouble(Condition cond, const BaseIndex& address, Label* label)
1306 {
1307     branchTestDoubleImpl(cond, address, label);
1308 }
1309 
1310 void
branchTestDouble(Condition cond,const ValueOperand & value,Label * label)1311 MacroAssembler::branchTestDouble(Condition cond, const ValueOperand& value, Label* label)
1312 {
1313     branchTestDoubleImpl(cond, value, label);
1314 }
1315 
1316 template <typename T>
1317 void
branchTestDoubleImpl(Condition cond,const T & t,Label * label)1318 MacroAssembler::branchTestDoubleImpl(Condition cond, const T& t, Label* label)
1319 {
1320     Condition c = testDouble(cond, t);
1321     B(label, c);
1322 }
1323 
1324 void
branchTestDoubleTruthy(bool truthy,FloatRegister reg,Label * label)1325 MacroAssembler::branchTestDoubleTruthy(bool truthy, FloatRegister reg, Label* label)
1326 {
1327     Fcmp(ARMFPRegister(reg, 64), 0.0);
1328     if (!truthy) {
1329         // falsy values are zero, and NaN.
1330         branch(Zero, label);
1331         branch(Overflow, label);
1332     } else {
1333         // truthy values are non-zero and not nan.
1334         // If it is overflow
1335         Label onFalse;
1336         branch(Zero, &onFalse);
1337         branch(Overflow, &onFalse);
1338         B(label);
1339         bind(&onFalse);
1340     }
1341 }
1342 
1343 void
branchTestNumber(Condition cond,Register tag,Label * label)1344 MacroAssembler::branchTestNumber(Condition cond, Register tag, Label* label)
1345 {
1346     branchTestNumberImpl(cond, tag, label);
1347 }
1348 
1349 void
branchTestNumber(Condition cond,const ValueOperand & value,Label * label)1350 MacroAssembler::branchTestNumber(Condition cond, const ValueOperand& value, Label* label)
1351 {
1352     branchTestNumberImpl(cond, value, label);
1353 }
1354 
1355 template <typename T>
1356 void
branchTestNumberImpl(Condition cond,const T & t,Label * label)1357 MacroAssembler::branchTestNumberImpl(Condition cond, const T& t, Label* label)
1358 {
1359     Condition c = testNumber(cond, t);
1360     B(label, c);
1361 }
1362 
1363 void
branchTestBoolean(Condition cond,Register tag,Label * label)1364 MacroAssembler::branchTestBoolean(Condition cond, Register tag, Label* label)
1365 {
1366     branchTestBooleanImpl(cond, tag, label);
1367 }
1368 
1369 void
branchTestBoolean(Condition cond,const Address & address,Label * label)1370 MacroAssembler::branchTestBoolean(Condition cond, const Address& address, Label* label)
1371 {
1372     branchTestBooleanImpl(cond, address, label);
1373 }
1374 
1375 void
branchTestBoolean(Condition cond,const BaseIndex & address,Label * label)1376 MacroAssembler::branchTestBoolean(Condition cond, const BaseIndex& address, Label* label)
1377 {
1378     branchTestBooleanImpl(cond, address, label);
1379 }
1380 
1381 void
branchTestBoolean(Condition cond,const ValueOperand & value,Label * label)1382 MacroAssembler::branchTestBoolean(Condition cond, const ValueOperand& value, Label* label)
1383 {
1384     branchTestBooleanImpl(cond, value, label);
1385 }
1386 
1387 template <typename T>
1388 void
branchTestBooleanImpl(Condition cond,const T & tag,Label * label)1389 MacroAssembler::branchTestBooleanImpl(Condition cond, const T& tag, Label* label)
1390 {
1391     Condition c = testBoolean(cond, tag);
1392     B(label, c);
1393 }
1394 
1395 void
branchTestBooleanTruthy(bool truthy,const ValueOperand & value,Label * label)1396 MacroAssembler::branchTestBooleanTruthy(bool truthy, const ValueOperand& value, Label* label)
1397 {
1398     Condition c = testBooleanTruthy(truthy, value);
1399     B(label, c);
1400 }
1401 
1402 void
branchTestString(Condition cond,Register tag,Label * label)1403 MacroAssembler::branchTestString(Condition cond, Register tag, Label* label)
1404 {
1405     branchTestStringImpl(cond, tag, label);
1406 }
1407 
1408 void
branchTestString(Condition cond,const BaseIndex & address,Label * label)1409 MacroAssembler::branchTestString(Condition cond, const BaseIndex& address, Label* label)
1410 {
1411     branchTestStringImpl(cond, address, label);
1412 }
1413 
1414 void
branchTestString(Condition cond,const ValueOperand & value,Label * label)1415 MacroAssembler::branchTestString(Condition cond, const ValueOperand& value, Label* label)
1416 {
1417     branchTestStringImpl(cond, value, label);
1418 }
1419 
1420 template <typename T>
1421 void
branchTestStringImpl(Condition cond,const T & t,Label * label)1422 MacroAssembler::branchTestStringImpl(Condition cond, const T& t, Label* label)
1423 {
1424     Condition c = testString(cond, t);
1425     B(label, c);
1426 }
1427 
1428 void
branchTestStringTruthy(bool truthy,const ValueOperand & value,Label * label)1429 MacroAssembler::branchTestStringTruthy(bool truthy, const ValueOperand& value, Label* label)
1430 {
1431     Condition c = testStringTruthy(truthy, value);
1432     B(label, c);
1433 }
1434 
1435 void
branchTestSymbol(Condition cond,Register tag,Label * label)1436 MacroAssembler::branchTestSymbol(Condition cond, Register tag, Label* label)
1437 {
1438     branchTestSymbolImpl(cond, tag, label);
1439 }
1440 
1441 void
branchTestSymbol(Condition cond,const BaseIndex & address,Label * label)1442 MacroAssembler::branchTestSymbol(Condition cond, const BaseIndex& address, Label* label)
1443 {
1444     branchTestSymbolImpl(cond, address, label);
1445 }
1446 
1447 void
branchTestSymbol(Condition cond,const ValueOperand & value,Label * label)1448 MacroAssembler::branchTestSymbol(Condition cond, const ValueOperand& value, Label* label)
1449 {
1450     branchTestSymbolImpl(cond, value, label);
1451 }
1452 
1453 template <typename T>
1454 void
branchTestSymbolImpl(Condition cond,const T & t,Label * label)1455 MacroAssembler::branchTestSymbolImpl(Condition cond, const T& t, Label* label)
1456 {
1457     Condition c = testSymbol(cond, t);
1458     B(label, c);
1459 }
1460 
1461 void
branchTestNull(Condition cond,Register tag,Label * label)1462 MacroAssembler::branchTestNull(Condition cond, Register tag, Label* label)
1463 {
1464     branchTestNullImpl(cond, tag, label);
1465 }
1466 
1467 void
branchTestNull(Condition cond,const Address & address,Label * label)1468 MacroAssembler::branchTestNull(Condition cond, const Address& address, Label* label)
1469 {
1470     branchTestNullImpl(cond, address, label);
1471 }
1472 
1473 void
branchTestNull(Condition cond,const BaseIndex & address,Label * label)1474 MacroAssembler::branchTestNull(Condition cond, const BaseIndex& address, Label* label)
1475 {
1476     branchTestNullImpl(cond, address, label);
1477 }
1478 
1479 void
branchTestNull(Condition cond,const ValueOperand & value,Label * label)1480 MacroAssembler::branchTestNull(Condition cond, const ValueOperand& value, Label* label)
1481 {
1482     branchTestNullImpl(cond, value, label);
1483 }
1484 
1485 template <typename T>
1486 void
branchTestNullImpl(Condition cond,const T & t,Label * label)1487 MacroAssembler::branchTestNullImpl(Condition cond, const T& t, Label* label)
1488 {
1489     Condition c = testNull(cond, t);
1490     B(label, c);
1491 }
1492 
1493 void
branchTestObject(Condition cond,Register tag,Label * label)1494 MacroAssembler::branchTestObject(Condition cond, Register tag, Label* label)
1495 {
1496     branchTestObjectImpl(cond, tag, label);
1497 }
1498 
1499 void
branchTestObject(Condition cond,const Address & address,Label * label)1500 MacroAssembler::branchTestObject(Condition cond, const Address& address, Label* label)
1501 {
1502     branchTestObjectImpl(cond, address, label);
1503 }
1504 
1505 void
branchTestObject(Condition cond,const BaseIndex & address,Label * label)1506 MacroAssembler::branchTestObject(Condition cond, const BaseIndex& address, Label* label)
1507 {
1508     branchTestObjectImpl(cond, address, label);
1509 }
1510 
1511 void
branchTestObject(Condition cond,const ValueOperand & value,Label * label)1512 MacroAssembler::branchTestObject(Condition cond, const ValueOperand& value, Label* label)
1513 {
1514     branchTestObjectImpl(cond, value, label);
1515 }
1516 
1517 template <typename T>
1518 void
branchTestObjectImpl(Condition cond,const T & t,Label * label)1519 MacroAssembler::branchTestObjectImpl(Condition cond, const T& t, Label* label)
1520 {
1521     Condition c = testObject(cond, t);
1522     B(label, c);
1523 }
1524 
1525 void
branchTestGCThing(Condition cond,const Address & address,Label * label)1526 MacroAssembler::branchTestGCThing(Condition cond, const Address& address, Label* label)
1527 {
1528     branchTestGCThingImpl(cond, address, label);
1529 }
1530 
1531 void
branchTestGCThing(Condition cond,const BaseIndex & address,Label * label)1532 MacroAssembler::branchTestGCThing(Condition cond, const BaseIndex& address, Label* label)
1533 {
1534     branchTestGCThingImpl(cond, address, label);
1535 }
1536 
1537 template <typename T>
1538 void
branchTestGCThingImpl(Condition cond,const T & src,Label * label)1539 MacroAssembler::branchTestGCThingImpl(Condition cond, const T& src, Label* label)
1540 {
1541     Condition c = testGCThing(cond, src);
1542     B(label, c);
1543 }
1544 
1545 void
branchTestPrimitive(Condition cond,Register tag,Label * label)1546 MacroAssembler::branchTestPrimitive(Condition cond, Register tag, Label* label)
1547 {
1548     branchTestPrimitiveImpl(cond, tag, label);
1549 }
1550 
1551 void
branchTestPrimitive(Condition cond,const ValueOperand & value,Label * label)1552 MacroAssembler::branchTestPrimitive(Condition cond, const ValueOperand& value, Label* label)
1553 {
1554     branchTestPrimitiveImpl(cond, value, label);
1555 }
1556 
1557 template <typename T>
1558 void
branchTestPrimitiveImpl(Condition cond,const T & t,Label * label)1559 MacroAssembler::branchTestPrimitiveImpl(Condition cond, const T& t, Label* label)
1560 {
1561     Condition c = testPrimitive(cond, t);
1562     B(label, c);
1563 }
1564 
1565 void
branchTestMagic(Condition cond,Register tag,Label * label)1566 MacroAssembler::branchTestMagic(Condition cond, Register tag, Label* label)
1567 {
1568     branchTestMagicImpl(cond, tag, label);
1569 }
1570 
1571 void
branchTestMagic(Condition cond,const Address & address,Label * label)1572 MacroAssembler::branchTestMagic(Condition cond, const Address& address, Label* label)
1573 {
1574     branchTestMagicImpl(cond, address, label);
1575 }
1576 
1577 void
branchTestMagic(Condition cond,const BaseIndex & address,Label * label)1578 MacroAssembler::branchTestMagic(Condition cond, const BaseIndex& address, Label* label)
1579 {
1580     branchTestMagicImpl(cond, address, label);
1581 }
1582 
1583 template <class L>
1584 void
branchTestMagic(Condition cond,const ValueOperand & value,L label)1585 MacroAssembler::branchTestMagic(Condition cond, const ValueOperand& value, L label)
1586 {
1587     branchTestMagicImpl(cond, value, label);
1588 }
1589 
1590 template <typename T, class L>
1591 void
branchTestMagicImpl(Condition cond,const T & t,L label)1592 MacroAssembler::branchTestMagicImpl(Condition cond, const T& t, L label)
1593 {
1594     Condition c = testMagic(cond, t);
1595     B(label, c);
1596 }
1597 
1598 void
branchTestMagic(Condition cond,const Address & valaddr,JSWhyMagic why,Label * label)1599 MacroAssembler::branchTestMagic(Condition cond, const Address& valaddr, JSWhyMagic why, Label* label)
1600 {
1601     uint64_t magic = MagicValue(why).asRawBits();
1602     cmpPtr(valaddr, ImmWord(magic));
1603     B(label, cond);
1604 }
1605 
1606 // ========================================================================
1607 // Memory access primitives.
1608 void
storeUncanonicalizedDouble(FloatRegister src,const Address & dest)1609 MacroAssembler::storeUncanonicalizedDouble(FloatRegister src, const Address& dest)
1610 {
1611     Str(ARMFPRegister(src, 64), MemOperand(ARMRegister(dest.base, 64), dest.offset));
1612 }
1613 void
storeUncanonicalizedDouble(FloatRegister src,const BaseIndex & dest)1614 MacroAssembler::storeUncanonicalizedDouble(FloatRegister src, const BaseIndex& dest)
1615 {
1616     doBaseIndex(ARMFPRegister(src, 64), dest, vixl::STR_d);
1617 }
1618 
1619 void
storeUncanonicalizedFloat32(FloatRegister src,const Address & addr)1620 MacroAssembler::storeUncanonicalizedFloat32(FloatRegister src, const Address& addr)
1621 {
1622     Str(ARMFPRegister(src, 32), MemOperand(ARMRegister(addr.base, 64), addr.offset));
1623 }
1624 void
storeUncanonicalizedFloat32(FloatRegister src,const BaseIndex & addr)1625 MacroAssembler::storeUncanonicalizedFloat32(FloatRegister src, const BaseIndex& addr)
1626 {
1627     doBaseIndex(ARMFPRegister(src, 32), addr, vixl::STR_s);
1628 }
1629 
1630 void
storeFloat32x3(FloatRegister src,const Address & dest)1631 MacroAssembler::storeFloat32x3(FloatRegister src, const Address& dest)
1632 {
1633     MOZ_CRASH("NYI");
1634 }
1635 void
storeFloat32x3(FloatRegister src,const BaseIndex & dest)1636 MacroAssembler::storeFloat32x3(FloatRegister src, const BaseIndex& dest)
1637 {
1638     MOZ_CRASH("NYI");
1639 }
1640 
1641 void
memoryBarrier(MemoryBarrierBits barrier)1642 MacroAssembler::memoryBarrier(MemoryBarrierBits barrier)
1643 {
1644     MOZ_CRASH("NYI");
1645 }
1646 
1647 // ===============================================================
1648 // Clamping functions.
1649 
1650 void
clampIntToUint8(Register reg)1651 MacroAssembler::clampIntToUint8(Register reg)
1652 {
1653     vixl::UseScratchRegisterScope temps(this);
1654     const ARMRegister scratch32 = temps.AcquireW();
1655     const ARMRegister reg32(reg, 32);
1656     MOZ_ASSERT(!scratch32.Is(reg32));
1657 
1658     Cmp(reg32, Operand(reg32, vixl::UXTB));
1659     Csel(reg32, reg32, vixl::wzr, Assembler::GreaterThanOrEqual);
1660     Mov(scratch32, Operand(0xff));
1661     Csel(reg32, reg32, scratch32, Assembler::LessThanOrEqual);
1662 }
1663 
1664 // ========================================================================
1665 // wasm support
1666 
1667 template <class L>
1668 void
wasmBoundsCheck(Condition cond,Register index,L label)1669 MacroAssembler::wasmBoundsCheck(Condition cond, Register index, L label)
1670 {
1671     MOZ_CRASH("NYI");
1672 }
1673 
1674 void
wasmPatchBoundsCheck(uint8_t * patchAt,uint32_t limit)1675 MacroAssembler::wasmPatchBoundsCheck(uint8_t* patchAt, uint32_t limit)
1676 {
1677     MOZ_CRASH("NYI");
1678 }
1679 
1680 //}}} check_macroassembler_style
1681 // ===============================================================
1682 
1683 template <typename T>
1684 void
addToStackPtr(T t)1685 MacroAssemblerCompat::addToStackPtr(T t)
1686 {
1687     asMasm().addPtr(t, getStackPointer());
1688 }
1689 
1690 template <typename T>
1691 void
addStackPtrTo(T t)1692 MacroAssemblerCompat::addStackPtrTo(T t)
1693 {
1694     asMasm().addPtr(getStackPointer(), t);
1695 }
1696 
1697 template <typename T>
1698 void
subFromStackPtr(T t)1699 MacroAssemblerCompat::subFromStackPtr(T t)
1700 {
1701     asMasm().subPtr(t, getStackPointer()); syncStackPtr();
1702 }
1703 
1704 template <typename T>
1705 void
subStackPtrFrom(T t)1706 MacroAssemblerCompat::subStackPtrFrom(T t)
1707 {
1708     asMasm().subPtr(getStackPointer(), t);
1709 }
1710 
1711 template <typename T>
1712 void
andToStackPtr(T t)1713 MacroAssemblerCompat::andToStackPtr(T t)
1714 {
1715     asMasm().andPtr(t, getStackPointer());
1716     syncStackPtr();
1717 }
1718 
1719 template <typename T>
1720 void
andStackPtrTo(T t)1721 MacroAssemblerCompat::andStackPtrTo(T t)
1722 {
1723     asMasm().andPtr(getStackPointer(), t);
1724 }
1725 
1726 template <typename T>
1727 void
branchStackPtr(Condition cond,T rhs,Label * label)1728 MacroAssemblerCompat::branchStackPtr(Condition cond, T rhs, Label* label)
1729 {
1730     asMasm().branchPtr(cond, getStackPointer(), rhs, label);
1731 }
1732 
1733 template <typename T>
1734 void
branchStackPtrRhs(Condition cond,T lhs,Label * label)1735 MacroAssemblerCompat::branchStackPtrRhs(Condition cond, T lhs, Label* label)
1736 {
1737     asMasm().branchPtr(cond, lhs, getStackPointer(), label);
1738 }
1739 
1740 template <typename T>
1741 void
branchTestStackPtr(Condition cond,T t,Label * label)1742 MacroAssemblerCompat::branchTestStackPtr(Condition cond, T t, Label* label)
1743 {
1744     asMasm().branchTestPtr(cond, getStackPointer(), t, label);
1745 }
1746 
1747 // If source is a double, load into dest.
1748 // If source is int32, convert to double and store in dest.
1749 // Else, branch to failure.
1750 void
ensureDouble(const ValueOperand & source,FloatRegister dest,Label * failure)1751 MacroAssemblerCompat::ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure)
1752 {
1753     Label isDouble, done;
1754 
1755     // TODO: splitTagForTest really should not leak a scratch register.
1756     Register tag = splitTagForTest(source);
1757     {
1758         vixl::UseScratchRegisterScope temps(this);
1759         temps.Exclude(ARMRegister(tag, 64));
1760 
1761         asMasm().branchTestDouble(Assembler::Equal, tag, &isDouble);
1762         asMasm().branchTestInt32(Assembler::NotEqual, tag, failure);
1763     }
1764 
1765     convertInt32ToDouble(source.valueReg(), dest);
1766     jump(&done);
1767 
1768     bind(&isDouble);
1769     unboxDouble(source, dest);
1770 
1771     bind(&done);
1772 }
1773 
1774 void
unboxValue(const ValueOperand & src,AnyRegister dest)1775 MacroAssemblerCompat::unboxValue(const ValueOperand& src, AnyRegister dest)
1776 {
1777     if (dest.isFloat()) {
1778         Label notInt32, end;
1779         asMasm().branchTestInt32(Assembler::NotEqual, src, &notInt32);
1780         convertInt32ToDouble(src.valueReg(), dest.fpu());
1781         jump(&end);
1782         bind(&notInt32);
1783         unboxDouble(src, dest.fpu());
1784         bind(&end);
1785     } else {
1786         unboxNonDouble(src, dest.gpr());
1787     }
1788 }
1789 
1790 } // namespace jit
1791 } // namespace js
1792 
1793 #endif /* jit_arm64_MacroAssembler_arm64_inl_h */
1794