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, ¬Magic);
1916 } else {
1917 branchTestMagic(Assembler::NotEqual, valaddr, label);
1918 }
1919
1920 branch32(cond, ToPayload(valaddr), Imm32(why), label);
1921 bind(¬Magic);
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