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