1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef jit_arm_MacroAssembler_arm_inl_h
8 #define jit_arm_MacroAssembler_arm_inl_h
9 
10 #include "jit/arm/MacroAssembler-arm.h"
11 
12 namespace js {
13 namespace jit {
14 
15 //{{{ check_macroassembler_style
16 
move64(Register64 src,Register64 dest)17 void MacroAssembler::move64(Register64 src, Register64 dest) {
18   move32(src.low, dest.low);
19   move32(src.high, dest.high);
20 }
21 
move64(Imm64 imm,Register64 dest)22 void MacroAssembler::move64(Imm64 imm, Register64 dest) {
23   move32(Imm32(imm.value & 0xFFFFFFFFL), dest.low);
24   move32(Imm32((imm.value >> 32) & 0xFFFFFFFFL), dest.high);
25 }
26 
moveFloat32ToGPR(FloatRegister src,Register dest)27 void MacroAssembler::moveFloat32ToGPR(FloatRegister src, Register dest) {
28   ma_vxfer(src, dest);
29 }
30 
moveGPRToFloat32(Register src,FloatRegister dest)31 void MacroAssembler::moveGPRToFloat32(Register src, FloatRegister dest) {
32   ma_vxfer(src, dest);
33 }
34 
move8SignExtend(Register src,Register dest)35 void MacroAssembler::move8SignExtend(Register src, Register dest) {
36   as_sxtb(dest, src, 0);
37 }
38 
move16SignExtend(Register src,Register dest)39 void MacroAssembler::move16SignExtend(Register src, Register dest) {
40   as_sxth(dest, src, 0);
41 }
42 
moveDoubleToGPR64(FloatRegister src,Register64 dest)43 void MacroAssembler::moveDoubleToGPR64(FloatRegister src, Register64 dest) {
44   ma_vxfer(src, dest.low, dest.high);
45 }
46 
moveGPR64ToDouble(Register64 src,FloatRegister dest)47 void MacroAssembler::moveGPR64ToDouble(Register64 src, FloatRegister dest) {
48   ma_vxfer(src.low, src.high, dest);
49 }
50 
move64To32(Register64 src,Register dest)51 void MacroAssembler::move64To32(Register64 src, Register dest) {
52   if (src.low != dest) {
53     move32(src.low, dest);
54   }
55 }
56 
move32To64ZeroExtend(Register src,Register64 dest)57 void MacroAssembler::move32To64ZeroExtend(Register src, Register64 dest) {
58   if (src != dest.low) {
59     move32(src, dest.low);
60   }
61   move32(Imm32(0), dest.high);
62 }
63 
move8To64SignExtend(Register src,Register64 dest)64 void MacroAssembler::move8To64SignExtend(Register src, Register64 dest) {
65   as_sxtb(dest.low, src, 0);
66   ma_asr(Imm32(31), dest.low, dest.high);
67 }
68 
move16To64SignExtend(Register src,Register64 dest)69 void MacroAssembler::move16To64SignExtend(Register src, Register64 dest) {
70   as_sxth(dest.low, src, 0);
71   ma_asr(Imm32(31), dest.low, dest.high);
72 }
73 
move32To64SignExtend(Register src,Register64 dest)74 void MacroAssembler::move32To64SignExtend(Register src, Register64 dest) {
75   if (src != dest.low) {
76     move32(src, dest.low);
77   }
78   ma_asr(Imm32(31), dest.low, dest.high);
79 }
80 
move32ZeroExtendToPtr(Register src,Register dest)81 void MacroAssembler::move32ZeroExtendToPtr(Register src, Register dest) {
82   move32(src, dest);
83 }
84 
85 // ===============================================================
86 // Load instructions
87 
load32SignExtendToPtr(const Address & src,Register dest)88 void MacroAssembler::load32SignExtendToPtr(const Address& src, Register dest) {
89   load32(src, dest);
90 }
91 
loadAbiReturnAddress(Register dest)92 void MacroAssembler::loadAbiReturnAddress(Register dest) { movePtr(lr, dest); }
93 
94 // ===============================================================
95 // Logical instructions
96 
not32(Register reg)97 void MacroAssembler::not32(Register reg) { ma_mvn(reg, reg); }
98 
and32(Register src,Register dest)99 void MacroAssembler::and32(Register src, Register dest) {
100   ma_and(src, dest, SetCC);
101 }
102 
and32(Imm32 imm,Register dest)103 void MacroAssembler::and32(Imm32 imm, Register dest) {
104   ScratchRegisterScope scratch(*this);
105   ma_and(imm, dest, scratch, SetCC);
106 }
107 
and32(Imm32 imm,const Address & dest)108 void MacroAssembler::and32(Imm32 imm, const Address& dest) {
109   ScratchRegisterScope scratch(*this);
110   SecondScratchRegisterScope scratch2(*this);
111 
112   ma_ldr(dest, scratch, scratch2);
113   ma_and(imm, scratch, scratch2);
114   ma_str(scratch, dest, scratch2);
115 }
116 
and32(const Address & src,Register dest)117 void MacroAssembler::and32(const Address& src, Register dest) {
118   ScratchRegisterScope scratch(*this);
119   SecondScratchRegisterScope scratch2(*this);
120 
121   ma_ldr(src, scratch, scratch2);
122   ma_and(scratch, dest, SetCC);
123 }
124 
andPtr(Register src,Register dest)125 void MacroAssembler::andPtr(Register src, Register dest) { ma_and(src, dest); }
126 
andPtr(Imm32 imm,Register dest)127 void MacroAssembler::andPtr(Imm32 imm, Register dest) {
128   ScratchRegisterScope scratch(*this);
129   ma_and(imm, dest, scratch);
130 }
131 
and64(Imm64 imm,Register64 dest)132 void MacroAssembler::and64(Imm64 imm, Register64 dest) {
133   if (imm.low().value != int32_t(0xFFFFFFFF)) {
134     and32(imm.low(), dest.low);
135   }
136   if (imm.hi().value != int32_t(0xFFFFFFFF)) {
137     and32(imm.hi(), dest.high);
138   }
139 }
140 
or64(Imm64 imm,Register64 dest)141 void MacroAssembler::or64(Imm64 imm, Register64 dest) {
142   if (imm.low().value) {
143     or32(imm.low(), dest.low);
144   }
145   if (imm.hi().value) {
146     or32(imm.hi(), dest.high);
147   }
148 }
149 
xor64(Imm64 imm,Register64 dest)150 void MacroAssembler::xor64(Imm64 imm, Register64 dest) {
151   if (imm.low().value) {
152     xor32(imm.low(), dest.low);
153   }
154   if (imm.hi().value) {
155     xor32(imm.hi(), dest.high);
156   }
157 }
158 
or32(Register src,Register dest)159 void MacroAssembler::or32(Register src, Register dest) { ma_orr(src, dest); }
160 
or32(Imm32 imm,Register dest)161 void MacroAssembler::or32(Imm32 imm, Register dest) {
162   ScratchRegisterScope scratch(*this);
163   ma_orr(imm, dest, scratch);
164 }
165 
or32(Imm32 imm,const Address & dest)166 void MacroAssembler::or32(Imm32 imm, const Address& dest) {
167   ScratchRegisterScope scratch(*this);
168   SecondScratchRegisterScope scratch2(*this);
169 
170   ma_ldr(dest, scratch, scratch2);
171   ma_orr(imm, scratch, scratch2);
172   ma_str(scratch, dest, scratch2);
173 }
174 
orPtr(Register src,Register dest)175 void MacroAssembler::orPtr(Register src, Register dest) { ma_orr(src, dest); }
176 
orPtr(Imm32 imm,Register dest)177 void MacroAssembler::orPtr(Imm32 imm, Register dest) {
178   ScratchRegisterScope scratch(*this);
179   ma_orr(imm, dest, scratch);
180 }
181 
and64(Register64 src,Register64 dest)182 void MacroAssembler::and64(Register64 src, Register64 dest) {
183   and32(src.low, dest.low);
184   and32(src.high, dest.high);
185 }
186 
or64(Register64 src,Register64 dest)187 void MacroAssembler::or64(Register64 src, Register64 dest) {
188   or32(src.low, dest.low);
189   or32(src.high, dest.high);
190 }
191 
xor64(Register64 src,Register64 dest)192 void MacroAssembler::xor64(Register64 src, Register64 dest) {
193   ma_eor(src.low, dest.low);
194   ma_eor(src.high, dest.high);
195 }
196 
xor32(Register src,Register dest)197 void MacroAssembler::xor32(Register src, Register dest) {
198   ma_eor(src, dest, SetCC);
199 }
200 
xor32(Imm32 imm,Register dest)201 void MacroAssembler::xor32(Imm32 imm, Register dest) {
202   ScratchRegisterScope scratch(*this);
203   ma_eor(imm, dest, scratch, SetCC);
204 }
205 
xorPtr(Register src,Register dest)206 void MacroAssembler::xorPtr(Register src, Register dest) { ma_eor(src, dest); }
207 
xorPtr(Imm32 imm,Register dest)208 void MacroAssembler::xorPtr(Imm32 imm, Register dest) {
209   ScratchRegisterScope scratch(*this);
210   ma_eor(imm, dest, scratch);
211 }
212 
213 // ===============================================================
214 // Swap instructions
215 
byteSwap16SignExtend(Register reg)216 void MacroAssembler::byteSwap16SignExtend(Register reg) { as_revsh(reg, reg); }
217 
byteSwap16ZeroExtend(Register reg)218 void MacroAssembler::byteSwap16ZeroExtend(Register reg) {
219   as_rev16(reg, reg);
220   as_uxth(reg, reg, 0);
221 }
222 
byteSwap32(Register reg)223 void MacroAssembler::byteSwap32(Register reg) { as_rev(reg, reg); }
224 
byteSwap64(Register64 reg)225 void MacroAssembler::byteSwap64(Register64 reg) {
226   as_rev(reg.high, reg.high);
227   as_rev(reg.low, reg.low);
228 
229   ScratchRegisterScope scratch(*this);
230   ma_mov(reg.high, scratch);
231   ma_mov(reg.low, reg.high);
232   ma_mov(scratch, reg.low);
233 }
234 
235 // ===============================================================
236 // Arithmetic functions
237 
add32(Register src,Register dest)238 void MacroAssembler::add32(Register src, Register dest) {
239   ma_add(src, dest, SetCC);
240 }
241 
add32(Imm32 imm,Register dest)242 void MacroAssembler::add32(Imm32 imm, Register dest) {
243   ScratchRegisterScope scratch(*this);
244   ma_add(imm, dest, scratch, SetCC);
245 }
246 
add32(Imm32 imm,const Address & dest)247 void MacroAssembler::add32(Imm32 imm, const Address& dest) {
248   ScratchRegisterScope scratch(*this);
249   SecondScratchRegisterScope scratch2(*this);
250 
251   ma_ldr(dest, scratch, scratch2);
252   ma_add(imm, scratch, scratch2, SetCC);
253   ma_str(scratch, dest, scratch2);
254 }
255 
addPtr(Register src,Register dest)256 void MacroAssembler::addPtr(Register src, Register dest) { ma_add(src, dest); }
257 
addPtr(Imm32 imm,Register dest)258 void MacroAssembler::addPtr(Imm32 imm, Register dest) {
259   ScratchRegisterScope scratch(*this);
260   ma_add(imm, dest, scratch);
261 }
262 
addPtr(ImmWord imm,Register dest)263 void MacroAssembler::addPtr(ImmWord imm, Register dest) {
264   addPtr(Imm32(imm.value), dest);
265 }
266 
addPtr(Imm32 imm,const Address & dest)267 void MacroAssembler::addPtr(Imm32 imm, const Address& dest) {
268   ScratchRegisterScope scratch(*this);
269   SecondScratchRegisterScope scratch2(*this);
270 
271   ma_ldr(dest, scratch, scratch2);
272   ma_add(imm, scratch, scratch2);
273   ma_str(scratch, dest, scratch2);
274 }
275 
addPtr(const Address & src,Register dest)276 void MacroAssembler::addPtr(const Address& src, Register dest) {
277   ScratchRegisterScope scratch(*this);
278   SecondScratchRegisterScope scratch2(*this);
279 
280   ma_ldr(src, scratch, scratch2);
281   ma_add(scratch, dest, SetCC);
282 }
283 
add64(Register64 src,Register64 dest)284 void MacroAssembler::add64(Register64 src, Register64 dest) {
285   ma_add(src.low, dest.low, SetCC);
286   ma_adc(src.high, dest.high);
287 }
288 
add64(Imm32 imm,Register64 dest)289 void MacroAssembler::add64(Imm32 imm, Register64 dest) {
290   ScratchRegisterScope scratch(*this);
291   ma_add(imm, dest.low, scratch, SetCC);
292   as_adc(dest.high, dest.high, Imm8(0), LeaveCC);
293 }
294 
add64(Imm64 imm,Register64 dest)295 void MacroAssembler::add64(Imm64 imm, Register64 dest) {
296   ScratchRegisterScope scratch(*this);
297   ma_add(imm.low(), dest.low, scratch, SetCC);
298   ma_adc(imm.hi(), dest.high, scratch, LeaveCC);
299 }
300 
sub32FromStackPtrWithPatch(Register dest)301 CodeOffset MacroAssembler::sub32FromStackPtrWithPatch(Register dest) {
302   ScratchRegisterScope scratch(*this);
303   CodeOffset offs = CodeOffset(currentOffset());
304   ma_movPatchable(Imm32(0), scratch, Always);
305   ma_sub(getStackPointer(), scratch, dest);
306   return offs;
307 }
308 
patchSub32FromStackPtr(CodeOffset offset,Imm32 imm)309 void MacroAssembler::patchSub32FromStackPtr(CodeOffset offset, Imm32 imm) {
310   ScratchRegisterScope scratch(*this);
311   BufferInstructionIterator iter(BufferOffset(offset.offset()), &m_buffer);
312   iter.maybeSkipAutomaticInstructions();
313   ma_mov_patch(imm, scratch, Always, HasMOVWT() ? L_MOVWT : L_LDR, iter);
314 }
315 
addDouble(FloatRegister src,FloatRegister dest)316 void MacroAssembler::addDouble(FloatRegister src, FloatRegister dest) {
317   ma_vadd(dest, src, dest);
318 }
319 
addFloat32(FloatRegister src,FloatRegister dest)320 void MacroAssembler::addFloat32(FloatRegister src, FloatRegister dest) {
321   ma_vadd_f32(dest, src, dest);
322 }
323 
sub32(Register src,Register dest)324 void MacroAssembler::sub32(Register src, Register dest) {
325   ma_sub(src, dest, SetCC);
326 }
327 
sub32(Imm32 imm,Register dest)328 void MacroAssembler::sub32(Imm32 imm, Register dest) {
329   ScratchRegisterScope scratch(*this);
330   ma_sub(imm, dest, scratch, SetCC);
331 }
332 
sub32(const Address & src,Register dest)333 void MacroAssembler::sub32(const Address& src, Register dest) {
334   ScratchRegisterScope scratch(*this);
335   SecondScratchRegisterScope scratch2(*this);
336 
337   ma_ldr(src, scratch, scratch2);
338   ma_sub(scratch, dest, SetCC);
339 }
340 
subPtr(Register src,Register dest)341 void MacroAssembler::subPtr(Register src, Register dest) { ma_sub(src, dest); }
342 
subPtr(Register src,const Address & dest)343 void MacroAssembler::subPtr(Register src, const Address& dest) {
344   ScratchRegisterScope scratch(*this);
345   SecondScratchRegisterScope scratch2(*this);
346 
347   ma_ldr(dest, scratch, scratch2);
348   ma_sub(src, scratch);
349   ma_str(scratch, dest, scratch2);
350 }
351 
subPtr(Imm32 imm,Register dest)352 void MacroAssembler::subPtr(Imm32 imm, Register dest) {
353   ScratchRegisterScope scratch(*this);
354   ma_sub(imm, dest, scratch);
355 }
356 
subPtr(const Address & addr,Register dest)357 void MacroAssembler::subPtr(const Address& addr, Register dest) {
358   ScratchRegisterScope scratch(*this);
359   SecondScratchRegisterScope scratch2(*this);
360 
361   ma_ldr(addr, scratch, scratch2);
362   ma_sub(scratch, dest);
363 }
364 
sub64(Register64 src,Register64 dest)365 void MacroAssembler::sub64(Register64 src, Register64 dest) {
366   ma_sub(src.low, dest.low, SetCC);
367   ma_sbc(src.high, dest.high, LeaveCC);
368 }
369 
sub64(Imm64 imm,Register64 dest)370 void MacroAssembler::sub64(Imm64 imm, Register64 dest) {
371   ScratchRegisterScope scratch(*this);
372   ma_sub(imm.low(), dest.low, scratch, SetCC);
373   ma_sbc(imm.hi(), dest.high, scratch, LeaveCC);
374 }
375 
subDouble(FloatRegister src,FloatRegister dest)376 void MacroAssembler::subDouble(FloatRegister src, FloatRegister dest) {
377   ma_vsub(dest, src, dest);
378 }
379 
subFloat32(FloatRegister src,FloatRegister dest)380 void MacroAssembler::subFloat32(FloatRegister src, FloatRegister dest) {
381   ma_vsub_f32(dest, src, dest);
382 }
383 
mul32(Register rhs,Register srcDest)384 void MacroAssembler::mul32(Register rhs, Register srcDest) {
385   as_mul(srcDest, srcDest, rhs);
386 }
387 
mul64(Imm64 imm,const Register64 & dest)388 void MacroAssembler::mul64(Imm64 imm, const Register64& dest) {
389   // LOW32  = LOW(LOW(dest) * LOW(imm));
390   // HIGH32 = LOW(HIGH(dest) * LOW(imm)) [multiply imm into upper bits]
391   //        + LOW(LOW(dest) * HIGH(imm)) [multiply dest into upper bits]
392   //        + HIGH(LOW(dest) * LOW(imm)) [carry]
393 
394   ScratchRegisterScope scratch(*this);
395   SecondScratchRegisterScope scratch2(*this);
396 
397   // HIGH(dest) = LOW(HIGH(dest) * LOW(imm));
398   ma_mov(Imm32(imm.value & 0xFFFFFFFFL), scratch);
399   as_mul(dest.high, dest.high, scratch);
400 
401   // high:low = LOW(dest) * LOW(imm);
402   as_umull(scratch2, scratch, dest.low, scratch);
403 
404   // HIGH(dest) += high;
405   as_add(dest.high, dest.high, O2Reg(scratch2));
406 
407   // HIGH(dest) += LOW(LOW(dest) * HIGH(imm));
408   if (((imm.value >> 32) & 0xFFFFFFFFL) == 5) {
409     as_add(scratch2, dest.low, lsl(dest.low, 2));
410   } else {
411     MOZ_CRASH("Not supported imm");
412   }
413   as_add(dest.high, dest.high, O2Reg(scratch2));
414 
415   // LOW(dest) = low;
416   ma_mov(scratch, dest.low);
417 }
418 
mul64(Imm64 imm,const Register64 & dest,const Register temp)419 void MacroAssembler::mul64(Imm64 imm, const Register64& dest,
420                            const Register temp) {
421   // LOW32  = LOW(LOW(dest) * LOW(src));                                  (1)
422   // HIGH32 = LOW(HIGH(dest) * LOW(src)) [multiply src into upper bits]   (2)
423   //        + LOW(LOW(dest) * HIGH(src)) [multiply dest into upper bits]  (3)
424   //        + HIGH(LOW(dest) * LOW(src)) [carry]                          (4)
425 
426   MOZ_ASSERT(temp != dest.high && temp != dest.low);
427 
428   // Compute mul64
429   ScratchRegisterScope scratch(*this);
430   ma_mul(dest.high, imm.low(), dest.high, scratch);  // (2)
431   ma_mul(dest.low, imm.hi(), temp, scratch);         // (3)
432   ma_add(dest.high, temp, temp);
433   ma_umull(dest.low, imm.low(), dest.high, dest.low, scratch);  // (4) + (1)
434   ma_add(temp, dest.high, dest.high);
435 }
436 
mul64(const Register64 & src,const Register64 & dest,const Register temp)437 void MacroAssembler::mul64(const Register64& src, const Register64& dest,
438                            const Register temp) {
439   // LOW32  = LOW(LOW(dest) * LOW(src));                                  (1)
440   // HIGH32 = LOW(HIGH(dest) * LOW(src)) [multiply src into upper bits]   (2)
441   //        + LOW(LOW(dest) * HIGH(src)) [multiply dest into upper bits]  (3)
442   //        + HIGH(LOW(dest) * LOW(src)) [carry]                          (4)
443 
444   MOZ_ASSERT(dest != src);
445   MOZ_ASSERT(dest.low != src.high && dest.high != src.low);
446 
447   // Compute mul64
448   ma_mul(dest.high, src.low, dest.high);  // (2)
449   ma_mul(src.high, dest.low, temp);       // (3)
450   ma_add(dest.high, temp, temp);
451   ma_umull(dest.low, src.low, dest.high, dest.low);  // (4) + (1)
452   ma_add(temp, dest.high, dest.high);
453 }
454 
mulBy3(Register src,Register dest)455 void MacroAssembler::mulBy3(Register src, Register dest) {
456   as_add(dest, src, lsl(src, 1));
457 }
458 
mulFloat32(FloatRegister src,FloatRegister dest)459 void MacroAssembler::mulFloat32(FloatRegister src, FloatRegister dest) {
460   ma_vmul_f32(dest, src, dest);
461 }
462 
mulDouble(FloatRegister src,FloatRegister dest)463 void MacroAssembler::mulDouble(FloatRegister src, FloatRegister dest) {
464   ma_vmul(dest, src, dest);
465 }
466 
mulDoublePtr(ImmPtr imm,Register temp,FloatRegister dest)467 void MacroAssembler::mulDoublePtr(ImmPtr imm, Register temp,
468                                   FloatRegister dest) {
469   ScratchRegisterScope scratch(*this);
470   ScratchDoubleScope scratchDouble(*this);
471 
472   movePtr(imm, scratch);
473   ma_vldr(Operand(Address(scratch, 0)).toVFPAddr(), scratchDouble);
474   mulDouble(scratchDouble, dest);
475 }
476 
quotient32(Register rhs,Register srcDest,bool isUnsigned)477 void MacroAssembler::quotient32(Register rhs, Register srcDest,
478                                 bool isUnsigned) {
479   MOZ_ASSERT(HasIDIV());
480   if (isUnsigned) {
481     ma_udiv(srcDest, rhs, srcDest);
482   } else {
483     ma_sdiv(srcDest, rhs, srcDest);
484   }
485 }
486 
remainder32(Register rhs,Register srcDest,bool isUnsigned)487 void MacroAssembler::remainder32(Register rhs, Register srcDest,
488                                  bool isUnsigned) {
489   MOZ_ASSERT(HasIDIV());
490 
491   ScratchRegisterScope scratch(*this);
492   if (isUnsigned) {
493     ma_umod(srcDest, rhs, srcDest, scratch);
494   } else {
495     ma_smod(srcDest, rhs, srcDest, scratch);
496   }
497 }
498 
divFloat32(FloatRegister src,FloatRegister dest)499 void MacroAssembler::divFloat32(FloatRegister src, FloatRegister dest) {
500   ma_vdiv_f32(dest, src, dest);
501 }
502 
divDouble(FloatRegister src,FloatRegister dest)503 void MacroAssembler::divDouble(FloatRegister src, FloatRegister dest) {
504   ma_vdiv(dest, src, dest);
505 }
506 
inc64(AbsoluteAddress dest)507 void MacroAssembler::inc64(AbsoluteAddress dest) {
508   ScratchRegisterScope scratch(*this);
509 
510   ma_strd(r0, r1, EDtrAddr(sp, EDtrOffImm(-8)), PreIndex);
511 
512   ma_mov(Imm32((int32_t)dest.addr), scratch);
513   ma_ldrd(EDtrAddr(scratch, EDtrOffImm(0)), r0, r1);
514 
515   as_add(r0, r0, Imm8(1), SetCC);
516   as_adc(r1, r1, Imm8(0), LeaveCC);
517 
518   ma_strd(r0, r1, EDtrAddr(scratch, EDtrOffImm(0)));
519   ma_ldrd(EDtrAddr(sp, EDtrOffImm(8)), r0, r1, PostIndex);
520 }
521 
neg32(Register reg)522 void MacroAssembler::neg32(Register reg) { ma_neg(reg, reg, SetCC); }
523 
neg64(Register64 reg)524 void MacroAssembler::neg64(Register64 reg) {
525   as_rsb(reg.low, reg.low, Imm8(0), SetCC);
526   as_rsc(reg.high, reg.high, Imm8(0));
527 }
528 
negPtr(Register reg)529 void MacroAssembler::negPtr(Register reg) { neg32(reg); }
530 
negateDouble(FloatRegister reg)531 void MacroAssembler::negateDouble(FloatRegister reg) { ma_vneg(reg, reg); }
532 
negateFloat(FloatRegister reg)533 void MacroAssembler::negateFloat(FloatRegister reg) { ma_vneg_f32(reg, reg); }
534 
absFloat32(FloatRegister src,FloatRegister dest)535 void MacroAssembler::absFloat32(FloatRegister src, FloatRegister dest) {
536   if (src != dest) {
537     ma_vmov_f32(src, dest);
538   }
539   ma_vabs_f32(dest, dest);
540 }
541 
absDouble(FloatRegister src,FloatRegister dest)542 void MacroAssembler::absDouble(FloatRegister src, FloatRegister dest) {
543   if (src != dest) {
544     ma_vmov(src, dest);
545   }
546   ma_vabs(dest, dest);
547 }
548 
sqrtFloat32(FloatRegister src,FloatRegister dest)549 void MacroAssembler::sqrtFloat32(FloatRegister src, FloatRegister dest) {
550   ma_vsqrt_f32(src, dest);
551 }
552 
sqrtDouble(FloatRegister src,FloatRegister dest)553 void MacroAssembler::sqrtDouble(FloatRegister src, FloatRegister dest) {
554   ma_vsqrt(src, dest);
555 }
556 
minFloat32(FloatRegister other,FloatRegister srcDest,bool handleNaN)557 void MacroAssembler::minFloat32(FloatRegister other, FloatRegister srcDest,
558                                 bool handleNaN) {
559   minMaxFloat32(srcDest, other, handleNaN, false);
560 }
561 
minDouble(FloatRegister other,FloatRegister srcDest,bool handleNaN)562 void MacroAssembler::minDouble(FloatRegister other, FloatRegister srcDest,
563                                bool handleNaN) {
564   minMaxDouble(srcDest, other, handleNaN, false);
565 }
566 
maxFloat32(FloatRegister other,FloatRegister srcDest,bool handleNaN)567 void MacroAssembler::maxFloat32(FloatRegister other, FloatRegister srcDest,
568                                 bool handleNaN) {
569   minMaxFloat32(srcDest, other, handleNaN, true);
570 }
571 
maxDouble(FloatRegister other,FloatRegister srcDest,bool handleNaN)572 void MacroAssembler::maxDouble(FloatRegister other, FloatRegister srcDest,
573                                bool handleNaN) {
574   minMaxDouble(srcDest, other, handleNaN, true);
575 }
576 
577 // ===============================================================
578 // Shift functions
579 
lshiftPtr(Imm32 imm,Register dest)580 void MacroAssembler::lshiftPtr(Imm32 imm, Register dest) {
581   MOZ_ASSERT(0 <= imm.value && imm.value < 32);
582   ma_lsl(imm, dest, dest);
583 }
584 
lshift64(Imm32 imm,Register64 dest)585 void MacroAssembler::lshift64(Imm32 imm, Register64 dest) {
586   MOZ_ASSERT(0 <= imm.value && imm.value < 64);
587   if (imm.value == 0) {
588     return;
589   }
590 
591   if (imm.value < 32) {
592     as_mov(dest.high, lsl(dest.high, imm.value));
593     as_orr(dest.high, dest.high, lsr(dest.low, 32 - imm.value));
594     as_mov(dest.low, lsl(dest.low, imm.value));
595   } else {
596     as_mov(dest.high, lsl(dest.low, imm.value - 32));
597     ma_mov(Imm32(0), dest.low);
598   }
599 }
600 
lshift64(Register unmaskedShift,Register64 dest)601 void MacroAssembler::lshift64(Register unmaskedShift, Register64 dest) {
602   // dest.high = dest.high << shift | dest.low << shift - 32 | dest.low >> 32 -
603   // shift Note: one of the two dest.low shift will always yield zero due to
604   // negative shift.
605 
606   ScratchRegisterScope shift(*this);
607   as_and(shift, unmaskedShift, Imm8(0x3f));
608   as_mov(dest.high, lsl(dest.high, shift));
609   as_sub(shift, shift, Imm8(32));
610   as_orr(dest.high, dest.high, lsl(dest.low, shift));
611   ma_neg(shift, shift);
612   as_orr(dest.high, dest.high, lsr(dest.low, shift));
613   as_and(shift, unmaskedShift, Imm8(0x3f));
614   as_mov(dest.low, lsl(dest.low, shift));
615 }
616 
lshift32(Register src,Register dest)617 void MacroAssembler::lshift32(Register src, Register dest) {
618   ma_lsl(src, dest, dest);
619 }
620 
flexibleLshift32(Register src,Register dest)621 void MacroAssembler::flexibleLshift32(Register src, Register dest) {
622   lshift32(src, dest);
623 }
624 
lshift32(Imm32 imm,Register dest)625 void MacroAssembler::lshift32(Imm32 imm, Register dest) {
626   MOZ_ASSERT(0 <= imm.value && imm.value < 32);
627   lshiftPtr(imm, dest);
628 }
629 
rshiftPtr(Imm32 imm,Register dest)630 void MacroAssembler::rshiftPtr(Imm32 imm, Register dest) {
631   MOZ_ASSERT(0 <= imm.value && imm.value < 32);
632   if (imm.value) {
633     ma_lsr(imm, dest, dest);
634   }
635 }
636 
rshift32(Register src,Register dest)637 void MacroAssembler::rshift32(Register src, Register dest) {
638   ma_lsr(src, dest, dest);
639 }
640 
flexibleRshift32(Register src,Register dest)641 void MacroAssembler::flexibleRshift32(Register src, Register dest) {
642   rshift32(src, dest);
643 }
644 
rshift32(Imm32 imm,Register dest)645 void MacroAssembler::rshift32(Imm32 imm, Register dest) {
646   MOZ_ASSERT(0 <= imm.value && imm.value < 32);
647   rshiftPtr(imm, dest);
648 }
649 
rshiftPtrArithmetic(Imm32 imm,Register dest)650 void MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register dest) {
651   MOZ_ASSERT(0 <= imm.value && imm.value < 32);
652   if (imm.value) {
653     ma_asr(imm, dest, dest);
654   }
655 }
656 
rshift64Arithmetic(Imm32 imm,Register64 dest)657 void MacroAssembler::rshift64Arithmetic(Imm32 imm, Register64 dest) {
658   MOZ_ASSERT(0 <= imm.value && imm.value < 64);
659   if (!imm.value) {
660     return;
661   }
662 
663   if (imm.value < 32) {
664     as_mov(dest.low, lsr(dest.low, imm.value));
665     as_orr(dest.low, dest.low, lsl(dest.high, 32 - imm.value));
666     as_mov(dest.high, asr(dest.high, imm.value));
667   } else if (imm.value == 32) {
668     as_mov(dest.low, O2Reg(dest.high));
669     as_mov(dest.high, asr(dest.high, 31));
670   } else {
671     as_mov(dest.low, asr(dest.high, imm.value - 32));
672     as_mov(dest.high, asr(dest.high, 31));
673   }
674 }
675 
rshift64Arithmetic(Register unmaskedShift,Register64 dest)676 void MacroAssembler::rshift64Arithmetic(Register unmaskedShift,
677                                         Register64 dest) {
678   Label proceed;
679 
680   // dest.low = dest.low >>> shift | dest.high <<< 32 - shift
681   // if (shift - 32 >= 0)
682   //   dest.low |= dest.high >>> shift - 32
683   // Note: Negative shifts yield a zero as result, except for the signed
684   //       right shift. Therefore we need to test for it and only do it if
685   //       it isn't negative.
686   ScratchRegisterScope shift(*this);
687 
688   as_and(shift, unmaskedShift, Imm8(0x3f));
689   as_mov(dest.low, lsr(dest.low, shift));
690   as_rsb(shift, shift, Imm8(32));
691   as_orr(dest.low, dest.low, lsl(dest.high, shift));
692   ma_neg(shift, shift, SetCC);
693   ma_b(&proceed, Signed);
694 
695   as_orr(dest.low, dest.low, asr(dest.high, shift));
696 
697   bind(&proceed);
698   as_and(shift, unmaskedShift, Imm8(0x3f));
699   as_mov(dest.high, asr(dest.high, shift));
700 }
701 
rshift32Arithmetic(Register src,Register dest)702 void MacroAssembler::rshift32Arithmetic(Register src, Register dest) {
703   ma_asr(src, dest, dest);
704 }
705 
rshift32Arithmetic(Imm32 imm,Register dest)706 void MacroAssembler::rshift32Arithmetic(Imm32 imm, Register dest) {
707   MOZ_ASSERT(0 <= imm.value && imm.value < 32);
708   rshiftPtrArithmetic(imm, dest);
709 }
710 
flexibleRshift32Arithmetic(Register src,Register dest)711 void MacroAssembler::flexibleRshift32Arithmetic(Register src, Register dest) {
712   rshift32Arithmetic(src, dest);
713 }
714 
rshift64(Imm32 imm,Register64 dest)715 void MacroAssembler::rshift64(Imm32 imm, Register64 dest) {
716   MOZ_ASSERT(0 <= imm.value && imm.value < 64);
717   MOZ_ASSERT(0 <= imm.value && imm.value < 64);
718   if (!imm.value) {
719     return;
720   }
721 
722   if (imm.value < 32) {
723     as_mov(dest.low, lsr(dest.low, imm.value));
724     as_orr(dest.low, dest.low, lsl(dest.high, 32 - imm.value));
725     as_mov(dest.high, lsr(dest.high, imm.value));
726   } else if (imm.value == 32) {
727     ma_mov(dest.high, dest.low);
728     ma_mov(Imm32(0), dest.high);
729   } else {
730     ma_lsr(Imm32(imm.value - 32), dest.high, dest.low);
731     ma_mov(Imm32(0), dest.high);
732   }
733 }
734 
rshift64(Register unmaskedShift,Register64 dest)735 void MacroAssembler::rshift64(Register unmaskedShift, Register64 dest) {
736   // dest.low = dest.low >> shift | dest.high >> shift - 32 | dest.high << 32 -
737   // shift Note: one of the two dest.high shifts will always yield zero due to
738   // negative shift.
739 
740   ScratchRegisterScope shift(*this);
741   as_and(shift, unmaskedShift, Imm8(0x3f));
742   as_mov(dest.low, lsr(dest.low, shift));
743   as_sub(shift, shift, Imm8(32));
744   as_orr(dest.low, dest.low, lsr(dest.high, shift));
745   ma_neg(shift, shift);
746   as_orr(dest.low, dest.low, lsl(dest.high, shift));
747   as_and(shift, unmaskedShift, Imm8(0x3f));
748   as_mov(dest.high, lsr(dest.high, shift));
749 }
750 
751 // ===============================================================
752 // Rotate functions
rotateLeft(Imm32 count,Register input,Register dest)753 void MacroAssembler::rotateLeft(Imm32 count, Register input, Register dest) {
754   if (count.value) {
755     ma_rol(count, input, dest);
756   } else {
757     ma_mov(input, dest);
758   }
759 }
760 
rotateLeft(Register count,Register input,Register dest)761 void MacroAssembler::rotateLeft(Register count, Register input, Register dest) {
762   ScratchRegisterScope scratch(*this);
763   ma_rol(count, input, dest, scratch);
764 }
765 
rotateLeft64(Imm32 count,Register64 input,Register64 dest,Register temp)766 void MacroAssembler::rotateLeft64(Imm32 count, Register64 input,
767                                   Register64 dest, Register temp) {
768   MOZ_ASSERT(temp == InvalidReg);
769   MOZ_ASSERT(input.low != dest.high && input.high != dest.low);
770 
771   int32_t amount = count.value & 0x3f;
772   if (amount > 32) {
773     rotateRight64(Imm32(64 - amount), input, dest, temp);
774   } else {
775     ScratchRegisterScope scratch(*this);
776     if (amount == 0) {
777       ma_mov(input.low, dest.low);
778       ma_mov(input.high, dest.high);
779     } else if (amount == 32) {
780       ma_mov(input.low, scratch);
781       ma_mov(input.high, dest.low);
782       ma_mov(scratch, dest.high);
783     } else {
784       MOZ_ASSERT(0 < amount && amount < 32);
785       ma_mov(dest.high, scratch);
786       as_mov(dest.high, lsl(dest.high, amount));
787       as_orr(dest.high, dest.high, lsr(dest.low, 32 - amount));
788       as_mov(dest.low, lsl(dest.low, amount));
789       as_orr(dest.low, dest.low, lsr(scratch, 32 - amount));
790     }
791   }
792 }
793 
rotateLeft64(Register shift,Register64 src,Register64 dest,Register temp)794 void MacroAssembler::rotateLeft64(Register shift, Register64 src,
795                                   Register64 dest, Register temp) {
796   MOZ_ASSERT(shift != temp);
797   MOZ_ASSERT(src == dest);
798   MOZ_ASSERT(temp != src.low && temp != src.high);
799   MOZ_ASSERT(shift != src.low && shift != src.high);
800   MOZ_ASSERT(temp != InvalidReg);
801 
802   ScratchRegisterScope shift_value(*this);
803   Label high, done;
804 
805   ma_mov(src.high, temp);
806   as_and(shift_value, shift, Imm8(0x3f));
807   as_cmp(shift_value, Imm8(32));
808   ma_b(&high, GreaterThanOrEqual);
809 
810   // high = high << shift | low >> 32 - shift
811   // low = low << shift | high >> 32 - shift
812   as_mov(dest.high, lsl(src.high, shift_value));
813   as_rsb(shift_value, shift_value, Imm8(32));
814   as_orr(dest.high, dest.high, lsr(src.low, shift_value));
815 
816   as_rsb(shift_value, shift_value, Imm8(32));
817   as_mov(dest.low, lsl(src.low, shift_value));
818   as_rsb(shift_value, shift_value, Imm8(32));
819   as_orr(dest.low, dest.low, lsr(temp, shift_value));
820 
821   ma_b(&done);
822 
823   // A 32 - 64 shift is a 0 - 32 shift in the other direction.
824   bind(&high);
825   as_rsb(shift_value, shift_value, Imm8(64));
826 
827   as_mov(dest.high, lsr(src.high, shift_value));
828   as_rsb(shift_value, shift_value, Imm8(32));
829   as_orr(dest.high, dest.high, lsl(src.low, shift_value));
830 
831   as_rsb(shift_value, shift_value, Imm8(32));
832   as_mov(dest.low, lsr(src.low, shift_value));
833   as_rsb(shift_value, shift_value, Imm8(32));
834   as_orr(dest.low, dest.low, lsl(temp, shift_value));
835 
836   bind(&done);
837 }
838 
rotateRight(Imm32 count,Register input,Register dest)839 void MacroAssembler::rotateRight(Imm32 count, Register input, Register dest) {
840   if (count.value) {
841     ma_ror(count, input, dest);
842   } else {
843     ma_mov(input, dest);
844   }
845 }
846 
rotateRight(Register count,Register input,Register dest)847 void MacroAssembler::rotateRight(Register count, Register input,
848                                  Register dest) {
849   ma_ror(count, input, dest);
850 }
851 
rotateRight64(Imm32 count,Register64 input,Register64 dest,Register temp)852 void MacroAssembler::rotateRight64(Imm32 count, Register64 input,
853                                    Register64 dest, Register temp) {
854   MOZ_ASSERT(temp == InvalidReg);
855   MOZ_ASSERT(input.low != dest.high && input.high != dest.low);
856 
857   int32_t amount = count.value & 0x3f;
858   if (amount > 32) {
859     rotateLeft64(Imm32(64 - amount), input, dest, temp);
860   } else {
861     ScratchRegisterScope scratch(*this);
862     if (amount == 0) {
863       ma_mov(input.low, dest.low);
864       ma_mov(input.high, dest.high);
865     } else if (amount == 32) {
866       ma_mov(input.low, scratch);
867       ma_mov(input.high, dest.low);
868       ma_mov(scratch, dest.high);
869     } else {
870       MOZ_ASSERT(0 < amount && amount < 32);
871       ma_mov(dest.high, scratch);
872       as_mov(dest.high, lsr(dest.high, amount));
873       as_orr(dest.high, dest.high, lsl(dest.low, 32 - amount));
874       as_mov(dest.low, lsr(dest.low, amount));
875       as_orr(dest.low, dest.low, lsl(scratch, 32 - amount));
876     }
877   }
878 }
879 
rotateRight64(Register shift,Register64 src,Register64 dest,Register temp)880 void MacroAssembler::rotateRight64(Register shift, Register64 src,
881                                    Register64 dest, Register temp) {
882   MOZ_ASSERT(shift != temp);
883   MOZ_ASSERT(src == dest);
884   MOZ_ASSERT(temp != src.low && temp != src.high);
885   MOZ_ASSERT(shift != src.low && shift != src.high);
886   MOZ_ASSERT(temp != InvalidReg);
887 
888   ScratchRegisterScope shift_value(*this);
889   Label high, done;
890 
891   ma_mov(src.high, temp);
892   as_and(shift_value, shift, Imm8(0x3f));
893   as_cmp(shift_value, Imm8(32));
894   ma_b(&high, GreaterThanOrEqual);
895 
896   // high = high >> shift | low << 32 - shift
897   // low = low >> shift | high << 32 - shift
898   as_mov(dest.high, lsr(src.high, shift_value));
899   as_rsb(shift_value, shift_value, Imm8(32));
900   as_orr(dest.high, dest.high, lsl(src.low, shift_value));
901 
902   as_rsb(shift_value, shift_value, Imm8(32));
903   as_mov(dest.low, lsr(src.low, shift_value));
904   as_rsb(shift_value, shift_value, Imm8(32));
905   as_orr(dest.low, dest.low, lsl(temp, shift_value));
906 
907   ma_b(&done);
908 
909   // A 32 - 64 shift is a 0 - 32 shift in the other direction.
910   bind(&high);
911   as_rsb(shift_value, shift_value, Imm8(64));
912 
913   as_mov(dest.high, lsl(src.high, shift_value));
914   as_rsb(shift_value, shift_value, Imm8(32));
915   as_orr(dest.high, dest.high, lsr(src.low, shift_value));
916 
917   as_rsb(shift_value, shift_value, Imm8(32));
918   as_mov(dest.low, lsl(src.low, shift_value));
919   as_rsb(shift_value, shift_value, Imm8(32));
920   as_orr(dest.low, dest.low, lsr(temp, shift_value));
921 
922   bind(&done);
923 }
924 
925 // ===============================================================
926 // Condition functions
927 
928 template <typename T1, typename T2>
cmp32Set(Condition cond,T1 lhs,T2 rhs,Register dest)929 void MacroAssembler::cmp32Set(Condition cond, T1 lhs, T2 rhs, Register dest) {
930   cmp32(lhs, rhs);
931   emitSet(cond, dest);
932 }
933 
934 template <typename T1, typename T2>
cmpPtrSet(Condition cond,T1 lhs,T2 rhs,Register dest)935 void MacroAssembler::cmpPtrSet(Condition cond, T1 lhs, T2 rhs, Register dest) {
936   cmpPtr(lhs, rhs);
937   emitSet(cond, dest);
938 }
939 
940 // ===============================================================
941 // Bit counting functions
942 
clz32(Register src,Register dest,bool knownNotZero)943 void MacroAssembler::clz32(Register src, Register dest, bool knownNotZero) {
944   ma_clz(src, dest);
945 }
946 
clz64(Register64 src,Register dest)947 void MacroAssembler::clz64(Register64 src, Register dest) {
948   ScratchRegisterScope scratch(*this);
949 
950   ma_clz(src.high, scratch);
951   as_cmp(scratch, Imm8(32));
952   ma_mov(scratch, dest, LeaveCC, NotEqual);
953   ma_clz(src.low, dest, Equal);
954   as_add(dest, dest, Imm8(32), LeaveCC, Equal);
955 }
956 
ctz32(Register src,Register dest,bool knownNotZero)957 void MacroAssembler::ctz32(Register src, Register dest, bool knownNotZero) {
958   ScratchRegisterScope scratch(*this);
959   ma_ctz(src, dest, scratch);
960 }
961 
ctz64(Register64 src,Register dest)962 void MacroAssembler::ctz64(Register64 src, Register dest) {
963   Label done, high;
964   as_cmp(src.low, Imm8(0));
965   ma_b(&high, Equal);
966 
967   ctz32(src.low, dest, /* knownNotZero = */ true);
968   ma_b(&done);
969 
970   bind(&high);
971   ctz32(src.high, dest, /* knownNotZero = */ false);
972   as_add(dest, dest, Imm8(32));
973 
974   bind(&done);
975 }
976 
popcnt32(Register input,Register output,Register tmp)977 void MacroAssembler::popcnt32(Register input, Register output, Register tmp) {
978   // Equivalent to GCC output of mozilla::CountPopulation32()
979 
980   ScratchRegisterScope scratch(*this);
981 
982   if (input != output) {
983     ma_mov(input, output);
984   }
985   as_mov(tmp, asr(output, 1));
986   ma_and(Imm32(0x55555555), tmp, scratch);
987   ma_sub(output, tmp, output);
988   as_mov(tmp, asr(output, 2));
989   ma_mov(Imm32(0x33333333), scratch);
990   ma_and(scratch, output);
991   ma_and(scratch, tmp);
992   ma_add(output, tmp, output);
993   as_add(output, output, lsr(output, 4));
994   ma_and(Imm32(0xF0F0F0F), output, scratch);
995   as_add(output, output, lsl(output, 8));
996   as_add(output, output, lsl(output, 16));
997   as_mov(output, asr(output, 24));
998 }
999 
popcnt64(Register64 src,Register64 dest,Register tmp)1000 void MacroAssembler::popcnt64(Register64 src, Register64 dest, Register tmp) {
1001   MOZ_ASSERT(dest.low != tmp);
1002   MOZ_ASSERT(dest.high != tmp);
1003   MOZ_ASSERT(dest.low != dest.high);
1004   // The source and destination can overlap. Therefore make sure we don't
1005   // clobber the source before we have the data.
1006   if (dest.low != src.high) {
1007     popcnt32(src.low, dest.low, tmp);
1008     popcnt32(src.high, dest.high, tmp);
1009   } else {
1010     MOZ_ASSERT(dest.high != src.high);
1011     popcnt32(src.low, dest.high, tmp);
1012     popcnt32(src.high, dest.low, tmp);
1013   }
1014   ma_add(dest.high, dest.low);
1015   ma_mov(Imm32(0), dest.high);
1016 }
1017 
1018 // ===============================================================
1019 // Branch functions
1020 
1021 template <class L>
branch32(Condition cond,Register lhs,Register rhs,L label)1022 void MacroAssembler::branch32(Condition cond, Register lhs, Register rhs,
1023                               L label) {
1024   ma_cmp(lhs, rhs);
1025   ma_b(label, cond);
1026 }
1027 
1028 template <class L>
branch32(Condition cond,Register lhs,Imm32 rhs,L label)1029 void MacroAssembler::branch32(Condition cond, Register lhs, Imm32 rhs,
1030                               L label) {
1031   ScratchRegisterScope scratch(*this);
1032 
1033   ma_cmp(lhs, rhs, scratch);
1034   ma_b(label, cond);
1035 }
1036 
branch32(Condition cond,const Address & lhs,Register rhs,Label * label)1037 void MacroAssembler::branch32(Condition cond, const Address& lhs, Register rhs,
1038                               Label* label) {
1039   ScratchRegisterScope scratch(*this);
1040   SecondScratchRegisterScope scratch2(*this);
1041 
1042   ma_ldr(lhs, scratch, scratch2);
1043   ma_cmp(scratch, rhs);
1044   ma_b(label, cond);
1045 }
1046 
branch32(Condition cond,const Address & lhs,Imm32 rhs,Label * label)1047 void MacroAssembler::branch32(Condition cond, const Address& lhs, Imm32 rhs,
1048                               Label* label) {
1049   ScratchRegisterScope scratch(*this);
1050   SecondScratchRegisterScope scratch2(*this);
1051 
1052   ma_ldr(lhs, scratch, scratch2);
1053   ma_cmp(scratch, rhs, scratch2);
1054   ma_b(label, cond);
1055 }
1056 
branch32(Condition cond,const AbsoluteAddress & lhs,Register rhs,Label * label)1057 void MacroAssembler::branch32(Condition cond, const AbsoluteAddress& lhs,
1058                               Register rhs, Label* label) {
1059   ScratchRegisterScope scratch(*this);
1060 
1061   // Load into scratch.
1062   movePtr(ImmWord(uintptr_t(lhs.addr)), scratch);
1063   ma_ldr(DTRAddr(scratch, DtrOffImm(0)), scratch);
1064 
1065   ma_cmp(scratch, rhs);
1066   ma_b(label, cond);
1067 }
1068 
branch32(Condition cond,const AbsoluteAddress & lhs,Imm32 rhs,Label * label)1069 void MacroAssembler::branch32(Condition cond, const AbsoluteAddress& lhs,
1070                               Imm32 rhs, Label* label) {
1071   ScratchRegisterScope scratch(*this);
1072   SecondScratchRegisterScope scratch2(*this);
1073 
1074   // Load into scratch.
1075   movePtr(ImmWord(uintptr_t(lhs.addr)), scratch);
1076   ma_ldr(DTRAddr(scratch, DtrOffImm(0)), scratch);
1077 
1078   ma_cmp(scratch, rhs, scratch2);
1079   ma_b(label, cond);
1080 }
1081 
branch32(Condition cond,const BaseIndex & lhs,Imm32 rhs,Label * label)1082 void MacroAssembler::branch32(Condition cond, const BaseIndex& lhs, Imm32 rhs,
1083                               Label* label) {
1084   SecondScratchRegisterScope scratch2(*this);
1085   {
1086     ScratchRegisterScope scratch(*this);
1087 
1088     Register base = lhs.base;
1089     uint32_t scale = Imm32::ShiftOf(lhs.scale).value;
1090 
1091     // Load lhs into scratch2.
1092     if (lhs.offset != 0) {
1093       ma_add(base, Imm32(lhs.offset), scratch, scratch2);
1094       ma_ldr(DTRAddr(scratch, DtrRegImmShift(lhs.index, LSL, scale)), scratch2);
1095     } else {
1096       ma_ldr(DTRAddr(base, DtrRegImmShift(lhs.index, LSL, scale)), scratch2);
1097     }
1098   }
1099   branch32(cond, scratch2, rhs, label);
1100 }
1101 
branch32(Condition cond,wasm::SymbolicAddress lhs,Imm32 rhs,Label * label)1102 void MacroAssembler::branch32(Condition cond, wasm::SymbolicAddress lhs,
1103                               Imm32 rhs, Label* label) {
1104   ScratchRegisterScope scratch(*this);
1105   SecondScratchRegisterScope scratch2(*this);
1106 
1107   movePtr(lhs, scratch);
1108   ma_ldr(DTRAddr(scratch, DtrOffImm(0)), scratch);
1109 
1110   ma_cmp(scratch, rhs, scratch2);
1111   ma_b(label, cond);
1112 }
1113 
branch64(Condition cond,const Address & lhs,Imm64 val,Label * label)1114 void MacroAssembler::branch64(Condition cond, const Address& lhs, Imm64 val,
1115                               Label* label) {
1116   MOZ_ASSERT(cond == Assembler::NotEqual,
1117              "other condition codes not supported");
1118 
1119   branch32(cond, lhs, val.firstHalf(), label);
1120   branch32(cond, Address(lhs.base, lhs.offset + sizeof(uint32_t)),
1121            val.secondHalf(), label);
1122 }
1123 
branch64(Condition cond,const Address & lhs,const Address & rhs,Register scratch,Label * label)1124 void MacroAssembler::branch64(Condition cond, const Address& lhs,
1125                               const Address& rhs, Register scratch,
1126                               Label* label) {
1127   MOZ_ASSERT(cond == Assembler::NotEqual,
1128              "other condition codes not supported");
1129   MOZ_ASSERT(lhs.base != scratch);
1130   MOZ_ASSERT(rhs.base != scratch);
1131 
1132   load32(rhs, scratch);
1133   branch32(cond, lhs, scratch, label);
1134 
1135   load32(Address(rhs.base, rhs.offset + sizeof(uint32_t)), scratch);
1136   branch32(cond, Address(lhs.base, lhs.offset + sizeof(uint32_t)), scratch,
1137            label);
1138 }
1139 
branch64(Condition cond,Register64 lhs,Imm64 val,Label * success,Label * fail)1140 void MacroAssembler::branch64(Condition cond, Register64 lhs, Imm64 val,
1141                               Label* success, Label* fail) {
1142   bool fallthrough = false;
1143   Label fallthroughLabel;
1144 
1145   if (!fail) {
1146     fail = &fallthroughLabel;
1147     fallthrough = true;
1148   }
1149 
1150   switch (cond) {
1151     case Assembler::Equal:
1152       branch32(Assembler::NotEqual, lhs.low, val.low(), fail);
1153       branch32(Assembler::Equal, lhs.high, val.hi(), success);
1154       if (!fallthrough) {
1155         jump(fail);
1156       }
1157       break;
1158     case Assembler::NotEqual:
1159       branch32(Assembler::NotEqual, lhs.low, val.low(), success);
1160       branch32(Assembler::NotEqual, lhs.high, val.hi(), success);
1161       if (!fallthrough) {
1162         jump(fail);
1163       }
1164       break;
1165     case Assembler::LessThan:
1166     case Assembler::LessThanOrEqual:
1167     case Assembler::GreaterThan:
1168     case Assembler::GreaterThanOrEqual:
1169     case Assembler::Below:
1170     case Assembler::BelowOrEqual:
1171     case Assembler::Above:
1172     case Assembler::AboveOrEqual: {
1173       Assembler::Condition cond1 = Assembler::ConditionWithoutEqual(cond);
1174       Assembler::Condition cond2 =
1175           Assembler::ConditionWithoutEqual(Assembler::InvertCondition(cond));
1176       Assembler::Condition cond3 = Assembler::UnsignedCondition(cond);
1177 
1178       cmp32(lhs.high, val.hi());
1179       ma_b(success, cond1);
1180       ma_b(fail, cond2);
1181       cmp32(lhs.low, val.low());
1182       ma_b(success, cond3);
1183       if (!fallthrough) {
1184         jump(fail);
1185       }
1186       break;
1187     }
1188     default:
1189       MOZ_CRASH("Condition code not supported");
1190       break;
1191   }
1192 
1193   if (fallthrough) {
1194     bind(fail);
1195   }
1196 }
1197 
branch64(Condition cond,Register64 lhs,Register64 rhs,Label * success,Label * fail)1198 void MacroAssembler::branch64(Condition cond, Register64 lhs, Register64 rhs,
1199                               Label* success, Label* fail) {
1200   bool fallthrough = false;
1201   Label fallthroughLabel;
1202 
1203   if (!fail) {
1204     fail = &fallthroughLabel;
1205     fallthrough = true;
1206   }
1207 
1208   switch (cond) {
1209     case Assembler::Equal:
1210       branch32(Assembler::NotEqual, lhs.low, rhs.low, fail);
1211       branch32(Assembler::Equal, lhs.high, rhs.high, success);
1212       if (!fallthrough) {
1213         jump(fail);
1214       }
1215       break;
1216     case Assembler::NotEqual:
1217       branch32(Assembler::NotEqual, lhs.low, rhs.low, success);
1218       branch32(Assembler::NotEqual, lhs.high, rhs.high, success);
1219       if (!fallthrough) {
1220         jump(fail);
1221       }
1222       break;
1223     case Assembler::LessThan:
1224     case Assembler::LessThanOrEqual:
1225     case Assembler::GreaterThan:
1226     case Assembler::GreaterThanOrEqual:
1227     case Assembler::Below:
1228     case Assembler::BelowOrEqual:
1229     case Assembler::Above:
1230     case Assembler::AboveOrEqual: {
1231       Assembler::Condition cond1 = Assembler::ConditionWithoutEqual(cond);
1232       Assembler::Condition cond2 =
1233           Assembler::ConditionWithoutEqual(Assembler::InvertCondition(cond));
1234       Assembler::Condition cond3 = Assembler::UnsignedCondition(cond);
1235 
1236       cmp32(lhs.high, rhs.high);
1237       ma_b(success, cond1);
1238       ma_b(fail, cond2);
1239       cmp32(lhs.low, rhs.low);
1240       ma_b(success, cond3);
1241       if (!fallthrough) {
1242         jump(fail);
1243       }
1244       break;
1245     }
1246     default:
1247       MOZ_CRASH("Condition code not supported");
1248       break;
1249   }
1250 
1251   if (fallthrough) {
1252     bind(fail);
1253   }
1254 }
1255 
1256 template <class L>
branchPtr(Condition cond,Register lhs,Register rhs,L label)1257 void MacroAssembler::branchPtr(Condition cond, Register lhs, Register rhs,
1258                                L label) {
1259   branch32(cond, lhs, rhs, label);
1260 }
1261 
branchPtr(Condition cond,Register lhs,Imm32 rhs,Label * label)1262 void MacroAssembler::branchPtr(Condition cond, Register lhs, Imm32 rhs,
1263                                Label* label) {
1264   branch32(cond, lhs, rhs, label);
1265 }
1266 
branchPtr(Condition cond,Register lhs,ImmPtr rhs,Label * label)1267 void MacroAssembler::branchPtr(Condition cond, Register lhs, ImmPtr rhs,
1268                                Label* label) {
1269   branchPtr(cond, lhs, ImmWord(uintptr_t(rhs.value)), label);
1270 }
1271 
branchPtr(Condition cond,Register lhs,ImmGCPtr rhs,Label * label)1272 void MacroAssembler::branchPtr(Condition cond, Register lhs, ImmGCPtr rhs,
1273                                Label* label) {
1274   ScratchRegisterScope scratch(*this);
1275   movePtr(rhs, scratch);
1276   branchPtr(cond, lhs, scratch, label);
1277 }
1278 
branchPtr(Condition cond,Register lhs,ImmWord rhs,Label * label)1279 void MacroAssembler::branchPtr(Condition cond, Register lhs, ImmWord rhs,
1280                                Label* label) {
1281   branch32(cond, lhs, Imm32(rhs.value), label);
1282 }
1283 
1284 template <class L>
branchPtr(Condition cond,const Address & lhs,Register rhs,L label)1285 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, Register rhs,
1286                                L label) {
1287   branch32(cond, lhs, rhs, label);
1288 }
1289 
branchPtr(Condition cond,const Address & lhs,ImmPtr rhs,Label * label)1290 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmPtr rhs,
1291                                Label* label) {
1292   branchPtr(cond, lhs, ImmWord(uintptr_t(rhs.value)), label);
1293 }
1294 
branchPtr(Condition cond,const Address & lhs,ImmGCPtr rhs,Label * label)1295 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmGCPtr rhs,
1296                                Label* label) {
1297   SecondScratchRegisterScope scratch2(*this);
1298   loadPtr(lhs, scratch2);
1299   branchPtr(cond, scratch2, rhs, label);
1300 }
1301 
branchPtr(Condition cond,const Address & lhs,ImmWord rhs,Label * label)1302 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmWord rhs,
1303                                Label* label) {
1304   SecondScratchRegisterScope scratch2(*this);
1305   loadPtr(lhs, scratch2);
1306   branchPtr(cond, scratch2, rhs, label);
1307 }
1308 
branchPtr(Condition cond,const AbsoluteAddress & lhs,Register rhs,Label * label)1309 void MacroAssembler::branchPtr(Condition cond, const AbsoluteAddress& lhs,
1310                                Register rhs, Label* label) {
1311   SecondScratchRegisterScope scratch2(*this);
1312   loadPtr(lhs, scratch2);
1313   branchPtr(cond, scratch2, rhs, label);
1314 }
1315 
branchPtr(Condition cond,const AbsoluteAddress & lhs,ImmWord rhs,Label * label)1316 void MacroAssembler::branchPtr(Condition cond, const AbsoluteAddress& lhs,
1317                                ImmWord rhs, Label* label) {
1318   SecondScratchRegisterScope scratch2(*this);
1319   loadPtr(lhs, scratch2);
1320   branchPtr(cond, scratch2, rhs, label);
1321 }
1322 
branchPtr(Condition cond,wasm::SymbolicAddress lhs,Register rhs,Label * label)1323 void MacroAssembler::branchPtr(Condition cond, wasm::SymbolicAddress lhs,
1324                                Register rhs, Label* label) {
1325   SecondScratchRegisterScope scratch2(*this);
1326   loadPtr(lhs, scratch2);
1327   branchPtr(cond, scratch2, rhs, label);
1328 }
1329 
branchPtr(Condition cond,const BaseIndex & lhs,ImmWord rhs,Label * label)1330 void MacroAssembler::branchPtr(Condition cond, const BaseIndex& lhs,
1331                                ImmWord rhs, Label* label) {
1332   branch32(cond, lhs, Imm32(rhs.value), label);
1333 }
1334 
branchPrivatePtr(Condition cond,const Address & lhs,Register rhs,Label * label)1335 void MacroAssembler::branchPrivatePtr(Condition cond, const Address& lhs,
1336                                       Register rhs, Label* label) {
1337   branchPtr(cond, lhs, rhs, label);
1338 }
1339 
branchFloat(DoubleCondition cond,FloatRegister lhs,FloatRegister rhs,Label * label)1340 void MacroAssembler::branchFloat(DoubleCondition cond, FloatRegister lhs,
1341                                  FloatRegister rhs, Label* label) {
1342   compareFloat(lhs, rhs);
1343 
1344   if (cond == DoubleNotEqual) {
1345     // Force the unordered cases not to jump.
1346     Label unordered;
1347     ma_b(&unordered, VFP_Unordered);
1348     ma_b(label, VFP_NotEqualOrUnordered);
1349     bind(&unordered);
1350     return;
1351   }
1352 
1353   if (cond == DoubleEqualOrUnordered) {
1354     ma_b(label, VFP_Unordered);
1355     ma_b(label, VFP_Equal);
1356     return;
1357   }
1358 
1359   ma_b(label, ConditionFromDoubleCondition(cond));
1360 }
1361 
branchTruncateFloat32MaybeModUint32(FloatRegister src,Register dest,Label * fail)1362 void MacroAssembler::branchTruncateFloat32MaybeModUint32(FloatRegister src,
1363                                                          Register dest,
1364                                                          Label* fail) {
1365   branchTruncateFloat32ToInt32(src, dest, fail);
1366 }
1367 
branchTruncateFloat32ToInt32(FloatRegister src,Register dest,Label * fail)1368 void MacroAssembler::branchTruncateFloat32ToInt32(FloatRegister src,
1369                                                   Register dest, Label* fail) {
1370   ScratchFloat32Scope scratchFloat32(*this);
1371   ScratchRegisterScope scratch(*this);
1372 
1373   ma_vcvt_F32_I32(src, scratchFloat32.sintOverlay());
1374   ma_vxfer(scratchFloat32, dest);
1375   ma_cmp(dest, Imm32(0x7fffffff), scratch);
1376   ma_cmp(dest, Imm32(0x80000000), scratch, Assembler::NotEqual);
1377   ma_b(fail, Assembler::Equal);
1378 }
1379 
branchDouble(DoubleCondition cond,FloatRegister lhs,FloatRegister rhs,Label * label)1380 void MacroAssembler::branchDouble(DoubleCondition cond, FloatRegister lhs,
1381                                   FloatRegister rhs, Label* label) {
1382   compareDouble(lhs, rhs);
1383 
1384   if (cond == DoubleNotEqual) {
1385     // Force the unordered cases not to jump.
1386     Label unordered;
1387     ma_b(&unordered, VFP_Unordered);
1388     ma_b(label, VFP_NotEqualOrUnordered);
1389     bind(&unordered);
1390     return;
1391   }
1392 
1393   if (cond == DoubleEqualOrUnordered) {
1394     ma_b(label, VFP_Unordered);
1395     ma_b(label, VFP_Equal);
1396     return;
1397   }
1398 
1399   ma_b(label, ConditionFromDoubleCondition(cond));
1400 }
1401 
branchTruncateDoubleMaybeModUint32(FloatRegister src,Register dest,Label * fail)1402 void MacroAssembler::branchTruncateDoubleMaybeModUint32(FloatRegister src,
1403                                                         Register dest,
1404                                                         Label* fail) {
1405   branchTruncateDoubleToInt32(src, dest, fail);
1406 }
1407 
1408 // There are two options for implementing branchTruncateDoubleToInt32:
1409 //
1410 // 1. Convert the floating point value to an integer, if it did not fit, then it
1411 // was clamped to INT_MIN/INT_MAX, and we can test it. NOTE: if the value
1412 // really was supposed to be INT_MAX / INT_MIN then it will be wrong.
1413 //
1414 // 2. Convert the floating point value to an integer, if it did not fit, then it
1415 // set one or two bits in the fpcsr. Check those.
branchTruncateDoubleToInt32(FloatRegister src,Register dest,Label * fail)1416 void MacroAssembler::branchTruncateDoubleToInt32(FloatRegister src,
1417                                                  Register dest, Label* fail) {
1418   ScratchDoubleScope scratchDouble(*this);
1419   FloatRegister scratchSIntReg = scratchDouble.sintOverlay();
1420   ScratchRegisterScope scratch(*this);
1421 
1422   ma_vcvt_F64_I32(src, scratchSIntReg);
1423   ma_vxfer(scratchSIntReg, dest);
1424   ma_cmp(dest, Imm32(0x7fffffff), scratch);
1425   ma_cmp(dest, Imm32(0x80000000), scratch, Assembler::NotEqual);
1426   ma_b(fail, Assembler::Equal);
1427 }
1428 
1429 template <typename T>
branchAdd32(Condition cond,T src,Register dest,Label * label)1430 void MacroAssembler::branchAdd32(Condition cond, T src, Register dest,
1431                                  Label* label) {
1432   add32(src, dest);
1433   as_b(label, cond);
1434 }
1435 
1436 template <typename T>
branchSub32(Condition cond,T src,Register dest,Label * label)1437 void MacroAssembler::branchSub32(Condition cond, T src, Register dest,
1438                                  Label* label) {
1439   sub32(src, dest);
1440   j(cond, label);
1441 }
1442 
1443 template <typename T>
branchMul32(Condition cond,T src,Register dest,Label * label)1444 void MacroAssembler::branchMul32(Condition cond, T src, Register dest,
1445                                  Label* label) {
1446   MOZ_ASSERT(cond == Assembler::Overflow);
1447   ScratchRegisterScope scratch(*this);
1448   Assembler::Condition overflow_cond =
1449       ma_check_mul(src, dest, dest, scratch, cond);
1450   j(overflow_cond, label);
1451 }
1452 
1453 template <typename T>
branchRshift32(Condition cond,T src,Register dest,Label * label)1454 void MacroAssembler::branchRshift32(Condition cond, T src, Register dest,
1455                                     Label* label) {
1456   MOZ_ASSERT(cond == Zero || cond == NonZero);
1457   rshift32(src, dest);
1458   branch32(cond == Zero ? Equal : NotEqual, dest, Imm32(0), label);
1459 }
1460 
branchNeg32(Condition cond,Register reg,Label * label)1461 void MacroAssembler::branchNeg32(Condition cond, Register reg, Label* label) {
1462   MOZ_ASSERT(cond == Overflow);
1463   neg32(reg);
1464   j(cond, label);
1465 }
1466 
decBranchPtr(Condition cond,Register lhs,Imm32 rhs,Label * label)1467 void MacroAssembler::decBranchPtr(Condition cond, Register lhs, Imm32 rhs,
1468                                   Label* label) {
1469   ScratchRegisterScope scratch(*this);
1470   ma_sub(rhs, lhs, scratch, SetCC);
1471   as_b(label, cond);
1472 }
1473 
1474 template <class L>
branchTest32(Condition cond,Register lhs,Register rhs,L label)1475 void MacroAssembler::branchTest32(Condition cond, Register lhs, Register rhs,
1476                                   L label) {
1477   MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed ||
1478              cond == NotSigned);
1479   // x86 likes test foo, foo rather than cmp foo, #0.
1480   // Convert the former into the latter.
1481   if (lhs == rhs && (cond == Zero || cond == NonZero)) {
1482     as_cmp(lhs, Imm8(0));
1483   } else {
1484     ma_tst(lhs, rhs);
1485   }
1486   ma_b(label, cond);
1487 }
1488 
1489 template <class L>
branchTest32(Condition cond,Register lhs,Imm32 rhs,L label)1490 void MacroAssembler::branchTest32(Condition cond, Register lhs, Imm32 rhs,
1491                                   L label) {
1492   MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed ||
1493              cond == NotSigned);
1494   ScratchRegisterScope scratch(*this);
1495   ma_tst(lhs, rhs, scratch);
1496   ma_b(label, cond);
1497 }
1498 
branchTest32(Condition cond,const Address & lhs,Imm32 rhs,Label * label)1499 void MacroAssembler::branchTest32(Condition cond, const Address& lhs, Imm32 rhs,
1500                                   Label* label) {
1501   SecondScratchRegisterScope scratch2(*this);
1502   load32(lhs, scratch2);
1503   branchTest32(cond, scratch2, rhs, label);
1504 }
1505 
branchTest32(Condition cond,const AbsoluteAddress & lhs,Imm32 rhs,Label * label)1506 void MacroAssembler::branchTest32(Condition cond, const AbsoluteAddress& lhs,
1507                                   Imm32 rhs, Label* label) {
1508   SecondScratchRegisterScope scratch2(*this);
1509   load32(lhs, scratch2);
1510   branchTest32(cond, scratch2, rhs, label);
1511 }
1512 
1513 template <class L>
branchTestPtr(Condition cond,Register lhs,Register rhs,L label)1514 void MacroAssembler::branchTestPtr(Condition cond, Register lhs, Register rhs,
1515                                    L label) {
1516   branchTest32(cond, lhs, rhs, label);
1517 }
1518 
branchTestPtr(Condition cond,Register lhs,Imm32 rhs,Label * label)1519 void MacroAssembler::branchTestPtr(Condition cond, Register lhs, Imm32 rhs,
1520                                    Label* label) {
1521   branchTest32(cond, lhs, rhs, label);
1522 }
1523 
branchTestPtr(Condition cond,const Address & lhs,Imm32 rhs,Label * label)1524 void MacroAssembler::branchTestPtr(Condition cond, const Address& lhs,
1525                                    Imm32 rhs, Label* label) {
1526   branchTest32(cond, lhs, rhs, label);
1527 }
1528 
1529 template <class L>
branchTest64(Condition cond,Register64 lhs,Register64 rhs,Register temp,L label)1530 void MacroAssembler::branchTest64(Condition cond, Register64 lhs,
1531                                   Register64 rhs, Register temp, L label) {
1532   ScratchRegisterScope scratch(*this);
1533 
1534   if (cond == Assembler::Zero || cond == Assembler::NonZero) {
1535     MOZ_ASSERT(lhs.low == rhs.low);
1536     MOZ_ASSERT(lhs.high == rhs.high);
1537     ma_orr(lhs.low, lhs.high, scratch);
1538     branchTestPtr(cond, scratch, scratch, label);
1539   } else {
1540     MOZ_CRASH("Unsupported condition");
1541   }
1542 }
1543 
branchTestUndefined(Condition cond,Register tag,Label * label)1544 void MacroAssembler::branchTestUndefined(Condition cond, Register tag,
1545                                          Label* label) {
1546   branchTestUndefinedImpl(cond, tag, label);
1547 }
1548 
branchTestUndefined(Condition cond,const Address & address,Label * label)1549 void MacroAssembler::branchTestUndefined(Condition cond, const Address& address,
1550                                          Label* label) {
1551   branchTestUndefinedImpl(cond, address, label);
1552 }
1553 
branchTestUndefined(Condition cond,const BaseIndex & address,Label * label)1554 void MacroAssembler::branchTestUndefined(Condition cond,
1555                                          const BaseIndex& address,
1556                                          Label* label) {
1557   branchTestUndefinedImpl(cond, address, label);
1558 }
1559 
branchTestUndefined(Condition cond,const ValueOperand & value,Label * label)1560 void MacroAssembler::branchTestUndefined(Condition cond,
1561                                          const ValueOperand& value,
1562                                          Label* label) {
1563   branchTestUndefinedImpl(cond, value, label);
1564 }
1565 
1566 template <typename T>
branchTestUndefinedImpl(Condition cond,const T & t,Label * label)1567 void MacroAssembler::branchTestUndefinedImpl(Condition cond, const T& t,
1568                                              Label* label) {
1569   Condition c = testUndefined(cond, t);
1570   ma_b(label, c);
1571 }
1572 
branchTestInt32(Condition cond,Register tag,Label * label)1573 void MacroAssembler::branchTestInt32(Condition cond, Register tag,
1574                                      Label* label) {
1575   branchTestInt32Impl(cond, tag, label);
1576 }
1577 
branchTestInt32(Condition cond,const Address & address,Label * label)1578 void MacroAssembler::branchTestInt32(Condition cond, const Address& address,
1579                                      Label* label) {
1580   branchTestInt32Impl(cond, address, label);
1581 }
1582 
branchTestInt32(Condition cond,const BaseIndex & address,Label * label)1583 void MacroAssembler::branchTestInt32(Condition cond, const BaseIndex& address,
1584                                      Label* label) {
1585   branchTestInt32Impl(cond, address, label);
1586 }
1587 
branchTestInt32(Condition cond,const ValueOperand & value,Label * label)1588 void MacroAssembler::branchTestInt32(Condition cond, const ValueOperand& value,
1589                                      Label* label) {
1590   branchTestInt32Impl(cond, value, label);
1591 }
1592 
1593 template <typename T>
branchTestInt32Impl(Condition cond,const T & t,Label * label)1594 void MacroAssembler::branchTestInt32Impl(Condition cond, const T& t,
1595                                          Label* label) {
1596   Condition c = testInt32(cond, t);
1597   ma_b(label, c);
1598 }
1599 
branchTestInt32Truthy(bool truthy,const ValueOperand & value,Label * label)1600 void MacroAssembler::branchTestInt32Truthy(bool truthy,
1601                                            const ValueOperand& value,
1602                                            Label* label) {
1603   Condition c = testInt32Truthy(truthy, value);
1604   ma_b(label, c);
1605 }
1606 
branchTestDouble(Condition cond,Register tag,Label * label)1607 void MacroAssembler::branchTestDouble(Condition cond, Register tag,
1608                                       Label* label) {
1609   branchTestDoubleImpl(cond, tag, label);
1610 }
1611 
branchTestDouble(Condition cond,const Address & address,Label * label)1612 void MacroAssembler::branchTestDouble(Condition cond, const Address& address,
1613                                       Label* label) {
1614   branchTestDoubleImpl(cond, address, label);
1615 }
1616 
branchTestDouble(Condition cond,const BaseIndex & address,Label * label)1617 void MacroAssembler::branchTestDouble(Condition cond, const BaseIndex& address,
1618                                       Label* label) {
1619   branchTestDoubleImpl(cond, address, label);
1620 }
1621 
branchTestDouble(Condition cond,const ValueOperand & value,Label * label)1622 void MacroAssembler::branchTestDouble(Condition cond, const ValueOperand& value,
1623                                       Label* label) {
1624   branchTestDoubleImpl(cond, value, label);
1625 }
1626 
1627 template <typename T>
branchTestDoubleImpl(Condition cond,const T & t,Label * label)1628 void MacroAssembler::branchTestDoubleImpl(Condition cond, const T& t,
1629                                           Label* label) {
1630   Condition c = testDouble(cond, t);
1631   ma_b(label, c);
1632 }
1633 
branchTestDoubleTruthy(bool truthy,FloatRegister reg,Label * label)1634 void MacroAssembler::branchTestDoubleTruthy(bool truthy, FloatRegister reg,
1635                                             Label* label) {
1636   Condition c = testDoubleTruthy(truthy, reg);
1637   ma_b(label, c);
1638 }
1639 
branchTestNumber(Condition cond,Register tag,Label * label)1640 void MacroAssembler::branchTestNumber(Condition cond, Register tag,
1641                                       Label* label) {
1642   branchTestNumberImpl(cond, tag, label);
1643 }
1644 
branchTestNumber(Condition cond,const ValueOperand & value,Label * label)1645 void MacroAssembler::branchTestNumber(Condition cond, const ValueOperand& value,
1646                                       Label* label) {
1647   branchTestNumberImpl(cond, value, label);
1648 }
1649 
1650 template <typename T>
branchTestNumberImpl(Condition cond,const T & t,Label * label)1651 void MacroAssembler::branchTestNumberImpl(Condition cond, const T& t,
1652                                           Label* label) {
1653   cond = testNumber(cond, t);
1654   ma_b(label, cond);
1655 }
1656 
branchTestBoolean(Condition cond,Register tag,Label * label)1657 void MacroAssembler::branchTestBoolean(Condition cond, Register tag,
1658                                        Label* label) {
1659   branchTestBooleanImpl(cond, tag, label);
1660 }
1661 
branchTestBoolean(Condition cond,const Address & address,Label * label)1662 void MacroAssembler::branchTestBoolean(Condition cond, const Address& address,
1663                                        Label* label) {
1664   branchTestBooleanImpl(cond, address, label);
1665 }
1666 
branchTestBoolean(Condition cond,const BaseIndex & address,Label * label)1667 void MacroAssembler::branchTestBoolean(Condition cond, const BaseIndex& address,
1668                                        Label* label) {
1669   branchTestBooleanImpl(cond, address, label);
1670 }
1671 
branchTestBoolean(Condition cond,const ValueOperand & value,Label * label)1672 void MacroAssembler::branchTestBoolean(Condition cond,
1673                                        const ValueOperand& value,
1674                                        Label* label) {
1675   branchTestBooleanImpl(cond, value, label);
1676 }
1677 
1678 template <typename T>
branchTestBooleanImpl(Condition cond,const T & t,Label * label)1679 void MacroAssembler::branchTestBooleanImpl(Condition cond, const T& t,
1680                                            Label* label) {
1681   Condition c = testBoolean(cond, t);
1682   ma_b(label, c);
1683 }
1684 
branchTestBooleanTruthy(bool truthy,const ValueOperand & value,Label * label)1685 void MacroAssembler::branchTestBooleanTruthy(bool truthy,
1686                                              const ValueOperand& value,
1687                                              Label* label) {
1688   Condition c = testBooleanTruthy(truthy, value);
1689   ma_b(label, c);
1690 }
1691 
branchTestString(Condition cond,Register tag,Label * label)1692 void MacroAssembler::branchTestString(Condition cond, Register tag,
1693                                       Label* label) {
1694   branchTestStringImpl(cond, tag, label);
1695 }
1696 
branchTestString(Condition cond,const Address & address,Label * label)1697 void MacroAssembler::branchTestString(Condition cond, const Address& address,
1698                                       Label* label) {
1699   branchTestStringImpl(cond, address, label);
1700 }
1701 
branchTestString(Condition cond,const BaseIndex & address,Label * label)1702 void MacroAssembler::branchTestString(Condition cond, const BaseIndex& address,
1703                                       Label* label) {
1704   branchTestStringImpl(cond, address, label);
1705 }
1706 
branchTestString(Condition cond,const ValueOperand & value,Label * label)1707 void MacroAssembler::branchTestString(Condition cond, const ValueOperand& value,
1708                                       Label* label) {
1709   branchTestStringImpl(cond, value, label);
1710 }
1711 
1712 template <typename T>
branchTestStringImpl(Condition cond,const T & t,Label * label)1713 void MacroAssembler::branchTestStringImpl(Condition cond, const T& t,
1714                                           Label* label) {
1715   Condition c = testString(cond, t);
1716   ma_b(label, c);
1717 }
1718 
branchTestStringTruthy(bool truthy,const ValueOperand & value,Label * label)1719 void MacroAssembler::branchTestStringTruthy(bool truthy,
1720                                             const ValueOperand& value,
1721                                             Label* label) {
1722   Condition c = testStringTruthy(truthy, value);
1723   ma_b(label, c);
1724 }
1725 
branchTestSymbol(Condition cond,Register tag,Label * label)1726 void MacroAssembler::branchTestSymbol(Condition cond, Register tag,
1727                                       Label* label) {
1728   branchTestSymbolImpl(cond, tag, label);
1729 }
1730 
branchTestSymbol(Condition cond,const Address & address,Label * label)1731 void MacroAssembler::branchTestSymbol(Condition cond, const Address& address,
1732                                       Label* label) {
1733   branchTestSymbolImpl(cond, address, label);
1734 }
1735 
branchTestSymbol(Condition cond,const BaseIndex & address,Label * label)1736 void MacroAssembler::branchTestSymbol(Condition cond, const BaseIndex& address,
1737                                       Label* label) {
1738   branchTestSymbolImpl(cond, address, label);
1739 }
1740 
branchTestSymbol(Condition cond,const ValueOperand & value,Label * label)1741 void MacroAssembler::branchTestSymbol(Condition cond, const ValueOperand& value,
1742                                       Label* label) {
1743   branchTestSymbolImpl(cond, value, label);
1744 }
1745 
1746 template <typename T>
branchTestSymbolImpl(Condition cond,const T & t,Label * label)1747 void MacroAssembler::branchTestSymbolImpl(Condition cond, const T& t,
1748                                           Label* label) {
1749   Condition c = testSymbol(cond, t);
1750   ma_b(label, c);
1751 }
1752 
branchTestBigInt(Condition cond,Register tag,Label * label)1753 void MacroAssembler::branchTestBigInt(Condition cond, Register tag,
1754                                       Label* label) {
1755   branchTestBigIntImpl(cond, tag, label);
1756 }
1757 
branchTestBigInt(Condition cond,const Address & address,Label * label)1758 void MacroAssembler::branchTestBigInt(Condition cond, const Address& address,
1759                                       Label* label) {
1760   branchTestBigIntImpl(cond, address, label);
1761 }
1762 
branchTestBigInt(Condition cond,const BaseIndex & address,Label * label)1763 void MacroAssembler::branchTestBigInt(Condition cond, const BaseIndex& address,
1764                                       Label* label) {
1765   branchTestBigIntImpl(cond, address, label);
1766 }
1767 
branchTestBigInt(Condition cond,const ValueOperand & value,Label * label)1768 void MacroAssembler::branchTestBigInt(Condition cond, const ValueOperand& value,
1769                                       Label* label) {
1770   branchTestBigIntImpl(cond, value, label);
1771 }
1772 
1773 template <typename T>
branchTestBigIntImpl(Condition cond,const T & t,Label * label)1774 void MacroAssembler::branchTestBigIntImpl(Condition cond, const T& t,
1775                                           Label* label) {
1776   Condition c = testBigInt(cond, t);
1777   ma_b(label, c);
1778 }
1779 
branchTestBigIntTruthy(bool truthy,const ValueOperand & value,Label * label)1780 void MacroAssembler::branchTestBigIntTruthy(bool truthy,
1781                                             const ValueOperand& value,
1782                                             Label* label) {
1783   Condition c = testBigIntTruthy(truthy, value);
1784   ma_b(label, c);
1785 }
1786 
branchTestNull(Condition cond,Register tag,Label * label)1787 void MacroAssembler::branchTestNull(Condition cond, Register tag,
1788                                     Label* label) {
1789   branchTestNullImpl(cond, tag, label);
1790 }
1791 
branchTestNull(Condition cond,const Address & address,Label * label)1792 void MacroAssembler::branchTestNull(Condition cond, const Address& address,
1793                                     Label* label) {
1794   branchTestNullImpl(cond, address, label);
1795 }
1796 
branchTestNull(Condition cond,const BaseIndex & address,Label * label)1797 void MacroAssembler::branchTestNull(Condition cond, const BaseIndex& address,
1798                                     Label* label) {
1799   branchTestNullImpl(cond, address, label);
1800 }
1801 
branchTestNull(Condition cond,const ValueOperand & value,Label * label)1802 void MacroAssembler::branchTestNull(Condition cond, const ValueOperand& value,
1803                                     Label* label) {
1804   branchTestNullImpl(cond, value, label);
1805 }
1806 
1807 template <typename T>
branchTestNullImpl(Condition cond,const T & t,Label * label)1808 void MacroAssembler::branchTestNullImpl(Condition cond, const T& t,
1809                                         Label* label) {
1810   Condition c = testNull(cond, t);
1811   ma_b(label, c);
1812 }
1813 
branchTestObject(Condition cond,Register tag,Label * label)1814 void MacroAssembler::branchTestObject(Condition cond, Register tag,
1815                                       Label* label) {
1816   branchTestObjectImpl(cond, tag, label);
1817 }
1818 
branchTestObject(Condition cond,const Address & address,Label * label)1819 void MacroAssembler::branchTestObject(Condition cond, const Address& address,
1820                                       Label* label) {
1821   branchTestObjectImpl(cond, address, label);
1822 }
1823 
branchTestObject(Condition cond,const BaseIndex & address,Label * label)1824 void MacroAssembler::branchTestObject(Condition cond, const BaseIndex& address,
1825                                       Label* label) {
1826   branchTestObjectImpl(cond, address, label);
1827 }
1828 
branchTestObject(Condition cond,const ValueOperand & value,Label * label)1829 void MacroAssembler::branchTestObject(Condition cond, const ValueOperand& value,
1830                                       Label* label) {
1831   branchTestObjectImpl(cond, value, label);
1832 }
1833 
1834 template <typename T>
branchTestObjectImpl(Condition cond,const T & t,Label * label)1835 void MacroAssembler::branchTestObjectImpl(Condition cond, const T& t,
1836                                           Label* label) {
1837   Condition c = testObject(cond, t);
1838   ma_b(label, c);
1839 }
1840 
branchTestGCThing(Condition cond,const Address & address,Label * label)1841 void MacroAssembler::branchTestGCThing(Condition cond, const Address& address,
1842                                        Label* label) {
1843   branchTestGCThingImpl(cond, address, label);
1844 }
1845 
branchTestGCThing(Condition cond,const BaseIndex & address,Label * label)1846 void MacroAssembler::branchTestGCThing(Condition cond, const BaseIndex& address,
1847                                        Label* label) {
1848   branchTestGCThingImpl(cond, address, label);
1849 }
1850 
branchTestGCThing(Condition cond,const ValueOperand & value,Label * label)1851 void MacroAssembler::branchTestGCThing(Condition cond,
1852                                        const ValueOperand& value,
1853                                        Label* label) {
1854   branchTestGCThingImpl(cond, value, label);
1855 }
1856 
1857 template <typename T>
branchTestGCThingImpl(Condition cond,const T & t,Label * label)1858 void MacroAssembler::branchTestGCThingImpl(Condition cond, const T& t,
1859                                            Label* label) {
1860   Condition c = testGCThing(cond, t);
1861   ma_b(label, c);
1862 }
1863 
branchTestPrimitive(Condition cond,Register tag,Label * label)1864 void MacroAssembler::branchTestPrimitive(Condition cond, Register tag,
1865                                          Label* label) {
1866   branchTestPrimitiveImpl(cond, tag, label);
1867 }
1868 
branchTestPrimitive(Condition cond,const ValueOperand & value,Label * label)1869 void MacroAssembler::branchTestPrimitive(Condition cond,
1870                                          const ValueOperand& value,
1871                                          Label* label) {
1872   branchTestPrimitiveImpl(cond, value, label);
1873 }
1874 
1875 template <typename T>
branchTestPrimitiveImpl(Condition cond,const T & t,Label * label)1876 void MacroAssembler::branchTestPrimitiveImpl(Condition cond, const T& t,
1877                                              Label* label) {
1878   Condition c = testPrimitive(cond, t);
1879   ma_b(label, c);
1880 }
1881 
branchTestMagic(Condition cond,Register tag,Label * label)1882 void MacroAssembler::branchTestMagic(Condition cond, Register tag,
1883                                      Label* label) {
1884   branchTestMagicImpl(cond, tag, label);
1885 }
1886 
branchTestMagic(Condition cond,const Address & address,Label * label)1887 void MacroAssembler::branchTestMagic(Condition cond, const Address& address,
1888                                      Label* label) {
1889   branchTestMagicImpl(cond, address, label);
1890 }
1891 
branchTestMagic(Condition cond,const BaseIndex & address,Label * label)1892 void MacroAssembler::branchTestMagic(Condition cond, const BaseIndex& address,
1893                                      Label* label) {
1894   branchTestMagicImpl(cond, address, label);
1895 }
1896 
1897 template <class L>
branchTestMagic(Condition cond,const ValueOperand & value,L label)1898 void MacroAssembler::branchTestMagic(Condition cond, const ValueOperand& value,
1899                                      L label) {
1900   branchTestMagicImpl(cond, value, label);
1901 }
1902 
1903 template <typename T, class L>
branchTestMagicImpl(Condition cond,const T & t,L label)1904 void MacroAssembler::branchTestMagicImpl(Condition cond, const T& t, L label) {
1905   cond = testMagic(cond, t);
1906   ma_b(label, cond);
1907 }
1908 
branchTestMagic(Condition cond,const Address & valaddr,JSWhyMagic why,Label * label)1909 void MacroAssembler::branchTestMagic(Condition cond, const Address& valaddr,
1910                                      JSWhyMagic why, Label* label) {
1911   MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
1912 
1913   Label notMagic;
1914   if (cond == Assembler::Equal) {
1915     branchTestMagic(Assembler::NotEqual, valaddr, &notMagic);
1916   } else {
1917     branchTestMagic(Assembler::NotEqual, valaddr, label);
1918   }
1919 
1920   branch32(cond, ToPayload(valaddr), Imm32(why), label);
1921   bind(&notMagic);
1922 }
1923 
branchToComputedAddress(const BaseIndex & addr)1924 void MacroAssembler::branchToComputedAddress(const BaseIndex& addr) {
1925   MOZ_ASSERT(
1926       addr.offset == 0,
1927       "NYI: offsets from pc should be shifted by the number of instructions.");
1928 
1929   Register base = addr.base;
1930   uint32_t scale = Imm32::ShiftOf(addr.scale).value;
1931 
1932   ma_ldr(DTRAddr(base, DtrRegImmShift(addr.index, LSL, scale)), pc);
1933 
1934   if (base == pc) {
1935     // When loading from pc, the pc is shifted to the next instruction, we
1936     // add one extra instruction to accomodate for this shifted offset.
1937     breakpoint();
1938   }
1939 }
1940 
cmp32Move32(Condition cond,Register lhs,Register rhs,Register src,Register dest)1941 void MacroAssembler::cmp32Move32(Condition cond, Register lhs, Register rhs,
1942                                  Register src, Register dest) {
1943   cmp32(lhs, rhs);
1944   ma_mov(src, dest, LeaveCC, cond);
1945 }
1946 
cmp32MovePtr(Condition cond,Register lhs,Imm32 rhs,Register src,Register dest)1947 void MacroAssembler::cmp32MovePtr(Condition cond, Register lhs, Imm32 rhs,
1948                                   Register src, Register dest) {
1949   cmp32(lhs, rhs);
1950   ma_mov(src, dest, LeaveCC, cond);
1951 }
1952 
cmp32Move32(Condition cond,Register lhs,const Address & rhs,Register src,Register dest)1953 void MacroAssembler::cmp32Move32(Condition cond, Register lhs,
1954                                  const Address& rhs, Register src,
1955                                  Register dest) {
1956   ScratchRegisterScope scratch(*this);
1957   SecondScratchRegisterScope scratch2(*this);
1958   ma_ldr(rhs, scratch, scratch2);
1959   cmp32Move32(cond, lhs, scratch, src, dest);
1960 }
1961 
cmp32Load32(Condition cond,Register lhs,const Address & rhs,const Address & src,Register dest)1962 void MacroAssembler::cmp32Load32(Condition cond, Register lhs,
1963                                  const Address& rhs, const Address& src,
1964                                  Register dest) {
1965   // This is never used, but must be present to facilitate linking on arm.
1966   MOZ_CRASH("No known use cases");
1967 }
1968 
cmp32Load32(Condition cond,Register lhs,Register rhs,const Address & src,Register dest)1969 void MacroAssembler::cmp32Load32(Condition cond, Register lhs, Register rhs,
1970                                  const Address& src, Register dest) {
1971   // This is never used, but must be present to facilitate linking on arm.
1972   MOZ_CRASH("No known use cases");
1973 }
1974 
cmp32LoadPtr(Condition cond,const Address & lhs,Imm32 rhs,const Address & src,Register dest)1975 void MacroAssembler::cmp32LoadPtr(Condition cond, const Address& lhs, Imm32 rhs,
1976                                   const Address& src, Register dest) {
1977   cmp32(lhs, rhs);
1978   ScratchRegisterScope scratch(*this);
1979   ma_ldr(src, dest, scratch, Offset, cond);
1980 }
1981 
test32LoadPtr(Condition cond,const Address & addr,Imm32 mask,const Address & src,Register dest)1982 void MacroAssembler::test32LoadPtr(Condition cond, const Address& addr,
1983                                    Imm32 mask, const Address& src,
1984                                    Register dest) {
1985   MOZ_ASSERT(cond == Assembler::Zero || cond == Assembler::NonZero);
1986   test32(addr, mask);
1987   ScratchRegisterScope scratch(*this);
1988   ma_ldr(src, dest, scratch, Offset, cond);
1989 }
1990 
test32MovePtr(Condition cond,const Address & addr,Imm32 mask,Register src,Register dest)1991 void MacroAssembler::test32MovePtr(Condition cond, const Address& addr,
1992                                    Imm32 mask, Register src, Register dest) {
1993   MOZ_ASSERT(cond == Assembler::Zero || cond == Assembler::NonZero);
1994   test32(addr, mask);
1995   ma_mov(src, dest, LeaveCC, cond);
1996 }
1997 
spectreMovePtr(Condition cond,Register src,Register dest)1998 void MacroAssembler::spectreMovePtr(Condition cond, Register src,
1999                                     Register dest) {
2000   ma_mov(src, dest, LeaveCC, cond);
2001 }
2002 
spectreZeroRegister(Condition cond,Register,Register dest)2003 void MacroAssembler::spectreZeroRegister(Condition cond, Register,
2004                                          Register dest) {
2005   ma_mov(Imm32(0), dest, cond);
2006 }
2007 
spectreBoundsCheck32(Register index,Register length,Register maybeScratch,Label * failure)2008 void MacroAssembler::spectreBoundsCheck32(Register index, Register length,
2009                                           Register maybeScratch,
2010                                           Label* failure) {
2011   MOZ_ASSERT(length != maybeScratch);
2012   MOZ_ASSERT(index != maybeScratch);
2013 
2014   branch32(Assembler::BelowOrEqual, length, index, failure);
2015 
2016   if (JitOptions.spectreIndexMasking) {
2017     ma_mov(Imm32(0), index, Assembler::BelowOrEqual);
2018   }
2019 }
2020 
spectreBoundsCheck32(Register index,const Address & length,Register maybeScratch,Label * failure)2021 void MacroAssembler::spectreBoundsCheck32(Register index, const Address& length,
2022                                           Register maybeScratch,
2023                                           Label* failure) {
2024   MOZ_ASSERT(index != length.base);
2025   MOZ_ASSERT(length.base != maybeScratch);
2026   MOZ_ASSERT(index != maybeScratch);
2027 
2028   branch32(Assembler::BelowOrEqual, length, index, failure);
2029 
2030   if (JitOptions.spectreIndexMasking) {
2031     ma_mov(Imm32(0), index, Assembler::BelowOrEqual);
2032   }
2033 }
2034 
2035 // ========================================================================
2036 // Memory access primitives.
storeUncanonicalizedDouble(FloatRegister src,const Address & addr)2037 void MacroAssembler::storeUncanonicalizedDouble(FloatRegister src,
2038                                                 const Address& addr) {
2039   ScratchRegisterScope scratch(*this);
2040   ma_vstr(src, addr, scratch);
2041 }
storeUncanonicalizedDouble(FloatRegister src,const BaseIndex & addr)2042 void MacroAssembler::storeUncanonicalizedDouble(FloatRegister src,
2043                                                 const BaseIndex& addr) {
2044   ScratchRegisterScope scratch(*this);
2045   SecondScratchRegisterScope scratch2(*this);
2046   uint32_t scale = Imm32::ShiftOf(addr.scale).value;
2047   ma_vstr(src, addr.base, addr.index, scratch, scratch2, scale, addr.offset);
2048 }
2049 
storeUncanonicalizedFloat32(FloatRegister src,const Address & addr)2050 void MacroAssembler::storeUncanonicalizedFloat32(FloatRegister src,
2051                                                  const Address& addr) {
2052   ScratchRegisterScope scratch(*this);
2053   ma_vstr(src.asSingle(), addr, scratch);
2054 }
storeUncanonicalizedFloat32(FloatRegister src,const BaseIndex & addr)2055 void MacroAssembler::storeUncanonicalizedFloat32(FloatRegister src,
2056                                                  const BaseIndex& addr) {
2057   ScratchRegisterScope scratch(*this);
2058   SecondScratchRegisterScope scratch2(*this);
2059   uint32_t scale = Imm32::ShiftOf(addr.scale).value;
2060   ma_vstr(src.asSingle(), addr.base, addr.index, scratch, scratch2, scale,
2061           addr.offset);
2062 }
2063 
storeFloat32x3(FloatRegister src,const Address & dest)2064 void MacroAssembler::storeFloat32x3(FloatRegister src, const Address& dest) {
2065   MOZ_CRASH("NYI");
2066 }
storeFloat32x3(FloatRegister src,const BaseIndex & dest)2067 void MacroAssembler::storeFloat32x3(FloatRegister src, const BaseIndex& dest) {
2068   MOZ_CRASH("NYI");
2069 }
2070 
memoryBarrier(MemoryBarrierBits barrier)2071 void MacroAssembler::memoryBarrier(MemoryBarrierBits barrier) {
2072   // On ARMv6 the optional argument (BarrierST, etc) is ignored.
2073   if (barrier == (MembarStoreStore | MembarSynchronizing)) {
2074     ma_dsb(BarrierST);
2075   } else if (barrier & MembarSynchronizing) {
2076     ma_dsb();
2077   } else if (barrier == MembarStoreStore) {
2078     ma_dmb(BarrierST);
2079   } else if (barrier) {
2080     ma_dmb();
2081   }
2082 }
2083 
2084 // ===============================================================
2085 // Clamping functions.
2086 
clampIntToUint8(Register reg)2087 void MacroAssembler::clampIntToUint8(Register reg) {
2088   // Look at (reg >> 8) if it is 0, then reg shouldn't be clamped if it is
2089   // <0, then we want to clamp to 0, otherwise, we wish to clamp to 255
2090   ScratchRegisterScope scratch(*this);
2091   as_mov(scratch, asr(reg, 8), SetCC);
2092   ma_mov(Imm32(0xff), reg, NotEqual);
2093   ma_mov(Imm32(0), reg, Signed);
2094 }
2095 
2096 template <typename T>
fallibleUnboxPtrImpl(const T & src,Register dest,JSValueType type,Label * fail)2097 void MacroAssemblerARMCompat::fallibleUnboxPtrImpl(const T& src, Register dest,
2098                                                    JSValueType type,
2099                                                    Label* fail) {
2100   switch (type) {
2101     case JSVAL_TYPE_OBJECT:
2102       asMasm().branchTestObject(Assembler::NotEqual, src, fail);
2103       break;
2104     case JSVAL_TYPE_STRING:
2105       asMasm().branchTestString(Assembler::NotEqual, src, fail);
2106       break;
2107     case JSVAL_TYPE_SYMBOL:
2108       asMasm().branchTestSymbol(Assembler::NotEqual, src, fail);
2109       break;
2110     case JSVAL_TYPE_BIGINT:
2111       asMasm().branchTestBigInt(Assembler::NotEqual, src, fail);
2112       break;
2113     default:
2114       MOZ_CRASH("Unexpected type");
2115   }
2116   unboxNonDouble(src, dest, type);
2117 }
2118 
fallibleUnboxPtr(const ValueOperand & src,Register dest,JSValueType type,Label * fail)2119 void MacroAssembler::fallibleUnboxPtr(const ValueOperand& src, Register dest,
2120                                       JSValueType type, Label* fail) {
2121   fallibleUnboxPtrImpl(src, dest, type, fail);
2122 }
2123 
fallibleUnboxPtr(const Address & src,Register dest,JSValueType type,Label * fail)2124 void MacroAssembler::fallibleUnboxPtr(const Address& src, Register dest,
2125                                       JSValueType type, Label* fail) {
2126   fallibleUnboxPtrImpl(src, dest, type, fail);
2127 }
2128 
fallibleUnboxPtr(const BaseIndex & src,Register dest,JSValueType type,Label * fail)2129 void MacroAssembler::fallibleUnboxPtr(const BaseIndex& src, Register dest,
2130                                       JSValueType type, Label* fail) {
2131   fallibleUnboxPtrImpl(src, dest, type, fail);
2132 }
2133 
2134 //}}} check_macroassembler_style
2135 // ===============================================================
2136 
incrementInt32Value(const Address & addr)2137 void MacroAssemblerARMCompat::incrementInt32Value(const Address& addr) {
2138   asMasm().add32(Imm32(1), ToPayload(addr));
2139 }
2140 
2141 }  // namespace jit
2142 }  // namespace js
2143 
2144 #endif /* jit_arm_MacroAssembler_arm_inl_h */
2145