[presubmit] Enable readability/namespace linter checking.
[platform/upstream/v8.git] / src / arm64 / macro-assembler-arm64-inl.h
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_ARM64_MACRO_ASSEMBLER_ARM64_INL_H_
6 #define V8_ARM64_MACRO_ASSEMBLER_ARM64_INL_H_
7
8 #include <ctype.h>
9
10 #include "src/globals.h"
11
12 #include "src/arm64/assembler-arm64-inl.h"
13 #include "src/arm64/assembler-arm64.h"
14 #include "src/arm64/instrument-arm64.h"
15 #include "src/arm64/macro-assembler-arm64.h"
16 #include "src/base/bits.h"
17
18
19 namespace v8 {
20 namespace internal {
21
22
23 MemOperand FieldMemOperand(Register object, int offset) {
24   return MemOperand(object, offset - kHeapObjectTag);
25 }
26
27
28 MemOperand UntagSmiFieldMemOperand(Register object, int offset) {
29   return UntagSmiMemOperand(object, offset - kHeapObjectTag);
30 }
31
32
33 MemOperand UntagSmiMemOperand(Register object, int offset) {
34   // Assumes that Smis are shifted by 32 bits and little endianness.
35   STATIC_ASSERT(kSmiShift == 32);
36   return MemOperand(object, offset + (kSmiShift / kBitsPerByte));
37 }
38
39
40 Handle<Object> MacroAssembler::CodeObject() {
41   DCHECK(!code_object_.is_null());
42   return code_object_;
43 }
44
45
46 void MacroAssembler::And(const Register& rd,
47                          const Register& rn,
48                          const Operand& operand) {
49   DCHECK(allow_macro_instructions_);
50   DCHECK(!rd.IsZero());
51   LogicalMacro(rd, rn, operand, AND);
52 }
53
54
55 void MacroAssembler::Ands(const Register& rd,
56                           const Register& rn,
57                           const Operand& operand) {
58   DCHECK(allow_macro_instructions_);
59   DCHECK(!rd.IsZero());
60   LogicalMacro(rd, rn, operand, ANDS);
61 }
62
63
64 void MacroAssembler::Tst(const Register& rn,
65                          const Operand& operand) {
66   DCHECK(allow_macro_instructions_);
67   LogicalMacro(AppropriateZeroRegFor(rn), rn, operand, ANDS);
68 }
69
70
71 void MacroAssembler::Bic(const Register& rd,
72                          const Register& rn,
73                          const Operand& operand) {
74   DCHECK(allow_macro_instructions_);
75   DCHECK(!rd.IsZero());
76   LogicalMacro(rd, rn, operand, BIC);
77 }
78
79
80 void MacroAssembler::Bics(const Register& rd,
81                           const Register& rn,
82                           const Operand& operand) {
83   DCHECK(allow_macro_instructions_);
84   DCHECK(!rd.IsZero());
85   LogicalMacro(rd, rn, operand, BICS);
86 }
87
88
89 void MacroAssembler::Orr(const Register& rd,
90                          const Register& rn,
91                          const Operand& operand) {
92   DCHECK(allow_macro_instructions_);
93   DCHECK(!rd.IsZero());
94   LogicalMacro(rd, rn, operand, ORR);
95 }
96
97
98 void MacroAssembler::Orn(const Register& rd,
99                          const Register& rn,
100                          const Operand& operand) {
101   DCHECK(allow_macro_instructions_);
102   DCHECK(!rd.IsZero());
103   LogicalMacro(rd, rn, operand, ORN);
104 }
105
106
107 void MacroAssembler::Eor(const Register& rd,
108                          const Register& rn,
109                          const Operand& operand) {
110   DCHECK(allow_macro_instructions_);
111   DCHECK(!rd.IsZero());
112   LogicalMacro(rd, rn, operand, EOR);
113 }
114
115
116 void MacroAssembler::Eon(const Register& rd,
117                          const Register& rn,
118                          const Operand& operand) {
119   DCHECK(allow_macro_instructions_);
120   DCHECK(!rd.IsZero());
121   LogicalMacro(rd, rn, operand, EON);
122 }
123
124
125 void MacroAssembler::Ccmp(const Register& rn,
126                           const Operand& operand,
127                           StatusFlags nzcv,
128                           Condition cond) {
129   DCHECK(allow_macro_instructions_);
130   if (operand.IsImmediate() && (operand.ImmediateValue() < 0)) {
131     ConditionalCompareMacro(rn, -operand.ImmediateValue(), nzcv, cond, CCMN);
132   } else {
133     ConditionalCompareMacro(rn, operand, nzcv, cond, CCMP);
134   }
135 }
136
137
138 void MacroAssembler::Ccmn(const Register& rn,
139                           const Operand& operand,
140                           StatusFlags nzcv,
141                           Condition cond) {
142   DCHECK(allow_macro_instructions_);
143   if (operand.IsImmediate() && (operand.ImmediateValue() < 0)) {
144     ConditionalCompareMacro(rn, -operand.ImmediateValue(), nzcv, cond, CCMP);
145   } else {
146     ConditionalCompareMacro(rn, operand, nzcv, cond, CCMN);
147   }
148 }
149
150
151 void MacroAssembler::Add(const Register& rd,
152                          const Register& rn,
153                          const Operand& operand) {
154   DCHECK(allow_macro_instructions_);
155   if (operand.IsImmediate() && (operand.ImmediateValue() < 0) &&
156       IsImmAddSub(-operand.ImmediateValue())) {
157     AddSubMacro(rd, rn, -operand.ImmediateValue(), LeaveFlags, SUB);
158   } else {
159     AddSubMacro(rd, rn, operand, LeaveFlags, ADD);
160   }
161 }
162
163 void MacroAssembler::Adds(const Register& rd,
164                           const Register& rn,
165                           const Operand& operand) {
166   DCHECK(allow_macro_instructions_);
167   if (operand.IsImmediate() && (operand.ImmediateValue() < 0) &&
168       IsImmAddSub(-operand.ImmediateValue())) {
169     AddSubMacro(rd, rn, -operand.ImmediateValue(), SetFlags, SUB);
170   } else {
171     AddSubMacro(rd, rn, operand, SetFlags, ADD);
172   }
173 }
174
175
176 void MacroAssembler::Sub(const Register& rd,
177                          const Register& rn,
178                          const Operand& operand) {
179   DCHECK(allow_macro_instructions_);
180   if (operand.IsImmediate() && (operand.ImmediateValue() < 0) &&
181       IsImmAddSub(-operand.ImmediateValue())) {
182     AddSubMacro(rd, rn, -operand.ImmediateValue(), LeaveFlags, ADD);
183   } else {
184     AddSubMacro(rd, rn, operand, LeaveFlags, SUB);
185   }
186 }
187
188
189 void MacroAssembler::Subs(const Register& rd,
190                           const Register& rn,
191                           const Operand& operand) {
192   DCHECK(allow_macro_instructions_);
193   if (operand.IsImmediate() && (operand.ImmediateValue() < 0) &&
194       IsImmAddSub(-operand.ImmediateValue())) {
195     AddSubMacro(rd, rn, -operand.ImmediateValue(), SetFlags, ADD);
196   } else {
197     AddSubMacro(rd, rn, operand, SetFlags, SUB);
198   }
199 }
200
201
202 void MacroAssembler::Cmn(const Register& rn, const Operand& operand) {
203   DCHECK(allow_macro_instructions_);
204   Adds(AppropriateZeroRegFor(rn), rn, operand);
205 }
206
207
208 void MacroAssembler::Cmp(const Register& rn, const Operand& operand) {
209   DCHECK(allow_macro_instructions_);
210   Subs(AppropriateZeroRegFor(rn), rn, operand);
211 }
212
213
214 void MacroAssembler::Neg(const Register& rd,
215                          const Operand& operand) {
216   DCHECK(allow_macro_instructions_);
217   DCHECK(!rd.IsZero());
218   if (operand.IsImmediate()) {
219     Mov(rd, -operand.ImmediateValue());
220   } else {
221     Sub(rd, AppropriateZeroRegFor(rd), operand);
222   }
223 }
224
225
226 void MacroAssembler::Negs(const Register& rd,
227                           const Operand& operand) {
228   DCHECK(allow_macro_instructions_);
229   Subs(rd, AppropriateZeroRegFor(rd), operand);
230 }
231
232
233 void MacroAssembler::Adc(const Register& rd,
234                          const Register& rn,
235                          const Operand& operand) {
236   DCHECK(allow_macro_instructions_);
237   DCHECK(!rd.IsZero());
238   AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, ADC);
239 }
240
241
242 void MacroAssembler::Adcs(const Register& rd,
243                           const Register& rn,
244                           const Operand& operand) {
245   DCHECK(allow_macro_instructions_);
246   DCHECK(!rd.IsZero());
247   AddSubWithCarryMacro(rd, rn, operand, SetFlags, ADC);
248 }
249
250
251 void MacroAssembler::Sbc(const Register& rd,
252                          const Register& rn,
253                          const Operand& operand) {
254   DCHECK(allow_macro_instructions_);
255   DCHECK(!rd.IsZero());
256   AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, SBC);
257 }
258
259
260 void MacroAssembler::Sbcs(const Register& rd,
261                           const Register& rn,
262                           const Operand& operand) {
263   DCHECK(allow_macro_instructions_);
264   DCHECK(!rd.IsZero());
265   AddSubWithCarryMacro(rd, rn, operand, SetFlags, SBC);
266 }
267
268
269 void MacroAssembler::Ngc(const Register& rd,
270                          const Operand& operand) {
271   DCHECK(allow_macro_instructions_);
272   DCHECK(!rd.IsZero());
273   Register zr = AppropriateZeroRegFor(rd);
274   Sbc(rd, zr, operand);
275 }
276
277
278 void MacroAssembler::Ngcs(const Register& rd,
279                           const Operand& operand) {
280   DCHECK(allow_macro_instructions_);
281   DCHECK(!rd.IsZero());
282   Register zr = AppropriateZeroRegFor(rd);
283   Sbcs(rd, zr, operand);
284 }
285
286
287 void MacroAssembler::Mvn(const Register& rd, uint64_t imm) {
288   DCHECK(allow_macro_instructions_);
289   DCHECK(!rd.IsZero());
290   Mov(rd, ~imm);
291 }
292
293
294 #define DEFINE_FUNCTION(FN, REGTYPE, REG, OP)                         \
295 void MacroAssembler::FN(const REGTYPE REG, const MemOperand& addr) {  \
296   DCHECK(allow_macro_instructions_);                                  \
297   LoadStoreMacro(REG, addr, OP);                                      \
298 }
299 LS_MACRO_LIST(DEFINE_FUNCTION)
300 #undef DEFINE_FUNCTION
301
302
303 #define DEFINE_FUNCTION(FN, REGTYPE, REG, REG2, OP)              \
304   void MacroAssembler::FN(const REGTYPE REG, const REGTYPE REG2, \
305                           const MemOperand& addr) {              \
306     DCHECK(allow_macro_instructions_);                           \
307     LoadStorePairMacro(REG, REG2, addr, OP);                     \
308   }
309 LSPAIR_MACRO_LIST(DEFINE_FUNCTION)
310 #undef DEFINE_FUNCTION
311
312
313 void MacroAssembler::Asr(const Register& rd,
314                          const Register& rn,
315                          unsigned shift) {
316   DCHECK(allow_macro_instructions_);
317   DCHECK(!rd.IsZero());
318   asr(rd, rn, shift);
319 }
320
321
322 void MacroAssembler::Asr(const Register& rd,
323                          const Register& rn,
324                          const Register& rm) {
325   DCHECK(allow_macro_instructions_);
326   DCHECK(!rd.IsZero());
327   asrv(rd, rn, rm);
328 }
329
330
331 void MacroAssembler::B(Label* label) {
332   b(label);
333   CheckVeneerPool(false, false);
334 }
335
336
337 void MacroAssembler::B(Condition cond, Label* label) {
338   DCHECK(allow_macro_instructions_);
339   B(label, cond);
340 }
341
342
343 void MacroAssembler::Bfi(const Register& rd,
344                          const Register& rn,
345                          unsigned lsb,
346                          unsigned width) {
347   DCHECK(allow_macro_instructions_);
348   DCHECK(!rd.IsZero());
349   bfi(rd, rn, lsb, width);
350 }
351
352
353 void MacroAssembler::Bfxil(const Register& rd,
354                            const Register& rn,
355                            unsigned lsb,
356                            unsigned width) {
357   DCHECK(allow_macro_instructions_);
358   DCHECK(!rd.IsZero());
359   bfxil(rd, rn, lsb, width);
360 }
361
362
363 void MacroAssembler::Bind(Label* label) {
364   DCHECK(allow_macro_instructions_);
365   bind(label);
366 }
367
368
369 void MacroAssembler::Bl(Label* label) {
370   DCHECK(allow_macro_instructions_);
371   bl(label);
372 }
373
374
375 void MacroAssembler::Blr(const Register& xn) {
376   DCHECK(allow_macro_instructions_);
377   DCHECK(!xn.IsZero());
378   blr(xn);
379 }
380
381
382 void MacroAssembler::Br(const Register& xn) {
383   DCHECK(allow_macro_instructions_);
384   DCHECK(!xn.IsZero());
385   br(xn);
386 }
387
388
389 void MacroAssembler::Brk(int code) {
390   DCHECK(allow_macro_instructions_);
391   brk(code);
392 }
393
394
395 void MacroAssembler::Cinc(const Register& rd,
396                           const Register& rn,
397                           Condition cond) {
398   DCHECK(allow_macro_instructions_);
399   DCHECK(!rd.IsZero());
400   DCHECK((cond != al) && (cond != nv));
401   cinc(rd, rn, cond);
402 }
403
404
405 void MacroAssembler::Cinv(const Register& rd,
406                           const Register& rn,
407                           Condition cond) {
408   DCHECK(allow_macro_instructions_);
409   DCHECK(!rd.IsZero());
410   DCHECK((cond != al) && (cond != nv));
411   cinv(rd, rn, cond);
412 }
413
414
415 void MacroAssembler::Cls(const Register& rd, const Register& rn) {
416   DCHECK(allow_macro_instructions_);
417   DCHECK(!rd.IsZero());
418   cls(rd, rn);
419 }
420
421
422 void MacroAssembler::Clz(const Register& rd, const Register& rn) {
423   DCHECK(allow_macro_instructions_);
424   DCHECK(!rd.IsZero());
425   clz(rd, rn);
426 }
427
428
429 void MacroAssembler::Cneg(const Register& rd,
430                           const Register& rn,
431                           Condition cond) {
432   DCHECK(allow_macro_instructions_);
433   DCHECK(!rd.IsZero());
434   DCHECK((cond != al) && (cond != nv));
435   cneg(rd, rn, cond);
436 }
437
438
439 // Conditionally zero the destination register. Only X registers are supported
440 // due to the truncation side-effect when used on W registers.
441 void MacroAssembler::CzeroX(const Register& rd,
442                             Condition cond) {
443   DCHECK(allow_macro_instructions_);
444   DCHECK(!rd.IsSP() && rd.Is64Bits());
445   DCHECK((cond != al) && (cond != nv));
446   csel(rd, xzr, rd, cond);
447 }
448
449
450 // Conditionally move a value into the destination register. Only X registers
451 // are supported due to the truncation side-effect when used on W registers.
452 void MacroAssembler::CmovX(const Register& rd,
453                            const Register& rn,
454                            Condition cond) {
455   DCHECK(allow_macro_instructions_);
456   DCHECK(!rd.IsSP());
457   DCHECK(rd.Is64Bits() && rn.Is64Bits());
458   DCHECK((cond != al) && (cond != nv));
459   if (!rd.is(rn)) {
460     csel(rd, rn, rd, cond);
461   }
462 }
463
464
465 void MacroAssembler::Cset(const Register& rd, Condition cond) {
466   DCHECK(allow_macro_instructions_);
467   DCHECK(!rd.IsZero());
468   DCHECK((cond != al) && (cond != nv));
469   cset(rd, cond);
470 }
471
472
473 void MacroAssembler::Csetm(const Register& rd, Condition cond) {
474   DCHECK(allow_macro_instructions_);
475   DCHECK(!rd.IsZero());
476   DCHECK((cond != al) && (cond != nv));
477   csetm(rd, cond);
478 }
479
480
481 void MacroAssembler::Csinc(const Register& rd,
482                            const Register& rn,
483                            const Register& rm,
484                            Condition cond) {
485   DCHECK(allow_macro_instructions_);
486   DCHECK(!rd.IsZero());
487   DCHECK((cond != al) && (cond != nv));
488   csinc(rd, rn, rm, cond);
489 }
490
491
492 void MacroAssembler::Csinv(const Register& rd,
493                            const Register& rn,
494                            const Register& rm,
495                            Condition cond) {
496   DCHECK(allow_macro_instructions_);
497   DCHECK(!rd.IsZero());
498   DCHECK((cond != al) && (cond != nv));
499   csinv(rd, rn, rm, cond);
500 }
501
502
503 void MacroAssembler::Csneg(const Register& rd,
504                            const Register& rn,
505                            const Register& rm,
506                            Condition cond) {
507   DCHECK(allow_macro_instructions_);
508   DCHECK(!rd.IsZero());
509   DCHECK((cond != al) && (cond != nv));
510   csneg(rd, rn, rm, cond);
511 }
512
513
514 void MacroAssembler::Dmb(BarrierDomain domain, BarrierType type) {
515   DCHECK(allow_macro_instructions_);
516   dmb(domain, type);
517 }
518
519
520 void MacroAssembler::Dsb(BarrierDomain domain, BarrierType type) {
521   DCHECK(allow_macro_instructions_);
522   dsb(domain, type);
523 }
524
525
526 void MacroAssembler::Debug(const char* message, uint32_t code, Instr params) {
527   DCHECK(allow_macro_instructions_);
528   debug(message, code, params);
529 }
530
531
532 void MacroAssembler::Extr(const Register& rd,
533                           const Register& rn,
534                           const Register& rm,
535                           unsigned lsb) {
536   DCHECK(allow_macro_instructions_);
537   DCHECK(!rd.IsZero());
538   extr(rd, rn, rm, lsb);
539 }
540
541
542 void MacroAssembler::Fabs(const FPRegister& fd, const FPRegister& fn) {
543   DCHECK(allow_macro_instructions_);
544   fabs(fd, fn);
545 }
546
547
548 void MacroAssembler::Fadd(const FPRegister& fd,
549                           const FPRegister& fn,
550                           const FPRegister& fm) {
551   DCHECK(allow_macro_instructions_);
552   fadd(fd, fn, fm);
553 }
554
555
556 void MacroAssembler::Fccmp(const FPRegister& fn,
557                            const FPRegister& fm,
558                            StatusFlags nzcv,
559                            Condition cond) {
560   DCHECK(allow_macro_instructions_);
561   DCHECK((cond != al) && (cond != nv));
562   fccmp(fn, fm, nzcv, cond);
563 }
564
565
566 void MacroAssembler::Fcmp(const FPRegister& fn, const FPRegister& fm) {
567   DCHECK(allow_macro_instructions_);
568   fcmp(fn, fm);
569 }
570
571
572 void MacroAssembler::Fcmp(const FPRegister& fn, double value) {
573   DCHECK(allow_macro_instructions_);
574   if (value != 0.0) {
575     UseScratchRegisterScope temps(this);
576     FPRegister tmp = temps.AcquireSameSizeAs(fn);
577     Fmov(tmp, value);
578     fcmp(fn, tmp);
579   } else {
580     fcmp(fn, value);
581   }
582 }
583
584
585 void MacroAssembler::Fcsel(const FPRegister& fd,
586                            const FPRegister& fn,
587                            const FPRegister& fm,
588                            Condition cond) {
589   DCHECK(allow_macro_instructions_);
590   DCHECK((cond != al) && (cond != nv));
591   fcsel(fd, fn, fm, cond);
592 }
593
594
595 void MacroAssembler::Fcvt(const FPRegister& fd, const FPRegister& fn) {
596   DCHECK(allow_macro_instructions_);
597   fcvt(fd, fn);
598 }
599
600
601 void MacroAssembler::Fcvtas(const Register& rd, const FPRegister& fn) {
602   DCHECK(allow_macro_instructions_);
603   DCHECK(!rd.IsZero());
604   fcvtas(rd, fn);
605 }
606
607
608 void MacroAssembler::Fcvtau(const Register& rd, const FPRegister& fn) {
609   DCHECK(allow_macro_instructions_);
610   DCHECK(!rd.IsZero());
611   fcvtau(rd, fn);
612 }
613
614
615 void MacroAssembler::Fcvtms(const Register& rd, const FPRegister& fn) {
616   DCHECK(allow_macro_instructions_);
617   DCHECK(!rd.IsZero());
618   fcvtms(rd, fn);
619 }
620
621
622 void MacroAssembler::Fcvtmu(const Register& rd, const FPRegister& fn) {
623   DCHECK(allow_macro_instructions_);
624   DCHECK(!rd.IsZero());
625   fcvtmu(rd, fn);
626 }
627
628
629 void MacroAssembler::Fcvtns(const Register& rd, const FPRegister& fn) {
630   DCHECK(allow_macro_instructions_);
631   DCHECK(!rd.IsZero());
632   fcvtns(rd, fn);
633 }
634
635
636 void MacroAssembler::Fcvtnu(const Register& rd, const FPRegister& fn) {
637   DCHECK(allow_macro_instructions_);
638   DCHECK(!rd.IsZero());
639   fcvtnu(rd, fn);
640 }
641
642
643 void MacroAssembler::Fcvtzs(const Register& rd, const FPRegister& fn) {
644   DCHECK(allow_macro_instructions_);
645   DCHECK(!rd.IsZero());
646   fcvtzs(rd, fn);
647 }
648 void MacroAssembler::Fcvtzu(const Register& rd, const FPRegister& fn) {
649   DCHECK(allow_macro_instructions_);
650   DCHECK(!rd.IsZero());
651   fcvtzu(rd, fn);
652 }
653
654
655 void MacroAssembler::Fdiv(const FPRegister& fd,
656                           const FPRegister& fn,
657                           const FPRegister& fm) {
658   DCHECK(allow_macro_instructions_);
659   fdiv(fd, fn, fm);
660 }
661
662
663 void MacroAssembler::Fmadd(const FPRegister& fd,
664                            const FPRegister& fn,
665                            const FPRegister& fm,
666                            const FPRegister& fa) {
667   DCHECK(allow_macro_instructions_);
668   fmadd(fd, fn, fm, fa);
669 }
670
671
672 void MacroAssembler::Fmax(const FPRegister& fd,
673                           const FPRegister& fn,
674                           const FPRegister& fm) {
675   DCHECK(allow_macro_instructions_);
676   fmax(fd, fn, fm);
677 }
678
679
680 void MacroAssembler::Fmaxnm(const FPRegister& fd,
681                             const FPRegister& fn,
682                             const FPRegister& fm) {
683   DCHECK(allow_macro_instructions_);
684   fmaxnm(fd, fn, fm);
685 }
686
687
688 void MacroAssembler::Fmin(const FPRegister& fd,
689                           const FPRegister& fn,
690                           const FPRegister& fm) {
691   DCHECK(allow_macro_instructions_);
692   fmin(fd, fn, fm);
693 }
694
695
696 void MacroAssembler::Fminnm(const FPRegister& fd,
697                             const FPRegister& fn,
698                             const FPRegister& fm) {
699   DCHECK(allow_macro_instructions_);
700   fminnm(fd, fn, fm);
701 }
702
703
704 void MacroAssembler::Fmov(FPRegister fd, FPRegister fn) {
705   DCHECK(allow_macro_instructions_);
706   // Only emit an instruction if fd and fn are different, and they are both D
707   // registers. fmov(s0, s0) is not a no-op because it clears the top word of
708   // d0. Technically, fmov(d0, d0) is not a no-op either because it clears the
709   // top of q0, but FPRegister does not currently support Q registers.
710   if (!fd.Is(fn) || !fd.Is64Bits()) {
711     fmov(fd, fn);
712   }
713 }
714
715
716 void MacroAssembler::Fmov(FPRegister fd, Register rn) {
717   DCHECK(allow_macro_instructions_);
718   fmov(fd, rn);
719 }
720
721
722 void MacroAssembler::Fmov(FPRegister fd, double imm) {
723   DCHECK(allow_macro_instructions_);
724   if (fd.Is32Bits()) {
725     Fmov(fd, static_cast<float>(imm));
726     return;
727   }
728
729   DCHECK(fd.Is64Bits());
730   if (IsImmFP64(imm)) {
731     fmov(fd, imm);
732   } else if ((imm == 0.0) && (copysign(1.0, imm) == 1.0)) {
733     fmov(fd, xzr);
734   } else {
735     Ldr(fd, imm);
736   }
737 }
738
739
740 void MacroAssembler::Fmov(FPRegister fd, float imm) {
741   DCHECK(allow_macro_instructions_);
742   if (fd.Is64Bits()) {
743     Fmov(fd, static_cast<double>(imm));
744     return;
745   }
746
747   DCHECK(fd.Is32Bits());
748   if (IsImmFP32(imm)) {
749     fmov(fd, imm);
750   } else if ((imm == 0.0) && (copysign(1.0, imm) == 1.0)) {
751     fmov(fd, wzr);
752   } else {
753     UseScratchRegisterScope temps(this);
754     Register tmp = temps.AcquireW();
755     // TODO(all): Use Assembler::ldr(const FPRegister& ft, float imm).
756     Mov(tmp, float_to_rawbits(imm));
757     Fmov(fd, tmp);
758   }
759 }
760
761
762 void MacroAssembler::Fmov(Register rd, FPRegister fn) {
763   DCHECK(allow_macro_instructions_);
764   DCHECK(!rd.IsZero());
765   fmov(rd, fn);
766 }
767
768
769 void MacroAssembler::Fmsub(const FPRegister& fd,
770                            const FPRegister& fn,
771                            const FPRegister& fm,
772                            const FPRegister& fa) {
773   DCHECK(allow_macro_instructions_);
774   fmsub(fd, fn, fm, fa);
775 }
776
777
778 void MacroAssembler::Fmul(const FPRegister& fd,
779                           const FPRegister& fn,
780                           const FPRegister& fm) {
781   DCHECK(allow_macro_instructions_);
782   fmul(fd, fn, fm);
783 }
784
785
786 void MacroAssembler::Fneg(const FPRegister& fd, const FPRegister& fn) {
787   DCHECK(allow_macro_instructions_);
788   fneg(fd, fn);
789 }
790
791
792 void MacroAssembler::Fnmadd(const FPRegister& fd,
793                             const FPRegister& fn,
794                             const FPRegister& fm,
795                             const FPRegister& fa) {
796   DCHECK(allow_macro_instructions_);
797   fnmadd(fd, fn, fm, fa);
798 }
799
800
801 void MacroAssembler::Fnmsub(const FPRegister& fd,
802                             const FPRegister& fn,
803                             const FPRegister& fm,
804                             const FPRegister& fa) {
805   DCHECK(allow_macro_instructions_);
806   fnmsub(fd, fn, fm, fa);
807 }
808
809
810 void MacroAssembler::Frinta(const FPRegister& fd, const FPRegister& fn) {
811   DCHECK(allow_macro_instructions_);
812   frinta(fd, fn);
813 }
814
815
816 void MacroAssembler::Frintm(const FPRegister& fd, const FPRegister& fn) {
817   DCHECK(allow_macro_instructions_);
818   frintm(fd, fn);
819 }
820
821
822 void MacroAssembler::Frintn(const FPRegister& fd, const FPRegister& fn) {
823   DCHECK(allow_macro_instructions_);
824   frintn(fd, fn);
825 }
826
827
828 void MacroAssembler::Frintp(const FPRegister& fd, const FPRegister& fn) {
829   DCHECK(allow_macro_instructions_);
830   frintp(fd, fn);
831 }
832
833
834 void MacroAssembler::Frintz(const FPRegister& fd, const FPRegister& fn) {
835   DCHECK(allow_macro_instructions_);
836   frintz(fd, fn);
837 }
838
839
840 void MacroAssembler::Fsqrt(const FPRegister& fd, const FPRegister& fn) {
841   DCHECK(allow_macro_instructions_);
842   fsqrt(fd, fn);
843 }
844
845
846 void MacroAssembler::Fsub(const FPRegister& fd,
847                           const FPRegister& fn,
848                           const FPRegister& fm) {
849   DCHECK(allow_macro_instructions_);
850   fsub(fd, fn, fm);
851 }
852
853
854 void MacroAssembler::Hint(SystemHint code) {
855   DCHECK(allow_macro_instructions_);
856   hint(code);
857 }
858
859
860 void MacroAssembler::Hlt(int code) {
861   DCHECK(allow_macro_instructions_);
862   hlt(code);
863 }
864
865
866 void MacroAssembler::Isb() {
867   DCHECK(allow_macro_instructions_);
868   isb();
869 }
870
871
872 void MacroAssembler::Ldr(const CPURegister& rt, const Immediate& imm) {
873   DCHECK(allow_macro_instructions_);
874   ldr(rt, imm);
875 }
876
877
878 void MacroAssembler::Ldr(const CPURegister& rt, double imm) {
879   DCHECK(allow_macro_instructions_);
880   DCHECK(rt.Is64Bits());
881   ldr(rt, Immediate(double_to_rawbits(imm)));
882 }
883
884
885 void MacroAssembler::Lsl(const Register& rd,
886                          const Register& rn,
887                          unsigned shift) {
888   DCHECK(allow_macro_instructions_);
889   DCHECK(!rd.IsZero());
890   lsl(rd, rn, shift);
891 }
892
893
894 void MacroAssembler::Lsl(const Register& rd,
895                          const Register& rn,
896                          const Register& rm) {
897   DCHECK(allow_macro_instructions_);
898   DCHECK(!rd.IsZero());
899   lslv(rd, rn, rm);
900 }
901
902
903 void MacroAssembler::Lsr(const Register& rd,
904                          const Register& rn,
905                          unsigned shift) {
906   DCHECK(allow_macro_instructions_);
907   DCHECK(!rd.IsZero());
908   lsr(rd, rn, shift);
909 }
910
911
912 void MacroAssembler::Lsr(const Register& rd,
913                          const Register& rn,
914                          const Register& rm) {
915   DCHECK(allow_macro_instructions_);
916   DCHECK(!rd.IsZero());
917   lsrv(rd, rn, rm);
918 }
919
920
921 void MacroAssembler::Madd(const Register& rd,
922                           const Register& rn,
923                           const Register& rm,
924                           const Register& ra) {
925   DCHECK(allow_macro_instructions_);
926   DCHECK(!rd.IsZero());
927   madd(rd, rn, rm, ra);
928 }
929
930
931 void MacroAssembler::Mneg(const Register& rd,
932                           const Register& rn,
933                           const Register& rm) {
934   DCHECK(allow_macro_instructions_);
935   DCHECK(!rd.IsZero());
936   mneg(rd, rn, rm);
937 }
938
939
940 void MacroAssembler::Mov(const Register& rd, const Register& rn) {
941   DCHECK(allow_macro_instructions_);
942   DCHECK(!rd.IsZero());
943   // Emit a register move only if the registers are distinct, or if they are
944   // not X registers. Note that mov(w0, w0) is not a no-op because it clears
945   // the top word of x0.
946   if (!rd.Is(rn) || !rd.Is64Bits()) {
947     Assembler::mov(rd, rn);
948   }
949 }
950
951
952 void MacroAssembler::Movk(const Register& rd, uint64_t imm, int shift) {
953   DCHECK(allow_macro_instructions_);
954   DCHECK(!rd.IsZero());
955   movk(rd, imm, shift);
956 }
957
958
959 void MacroAssembler::Mrs(const Register& rt, SystemRegister sysreg) {
960   DCHECK(allow_macro_instructions_);
961   DCHECK(!rt.IsZero());
962   mrs(rt, sysreg);
963 }
964
965
966 void MacroAssembler::Msr(SystemRegister sysreg, const Register& rt) {
967   DCHECK(allow_macro_instructions_);
968   msr(sysreg, rt);
969 }
970
971
972 void MacroAssembler::Msub(const Register& rd,
973                           const Register& rn,
974                           const Register& rm,
975                           const Register& ra) {
976   DCHECK(allow_macro_instructions_);
977   DCHECK(!rd.IsZero());
978   msub(rd, rn, rm, ra);
979 }
980
981
982 void MacroAssembler::Mul(const Register& rd,
983                          const Register& rn,
984                          const Register& rm) {
985   DCHECK(allow_macro_instructions_);
986   DCHECK(!rd.IsZero());
987   mul(rd, rn, rm);
988 }
989
990
991 void MacroAssembler::Rbit(const Register& rd, const Register& rn) {
992   DCHECK(allow_macro_instructions_);
993   DCHECK(!rd.IsZero());
994   rbit(rd, rn);
995 }
996
997
998 void MacroAssembler::Ret(const Register& xn) {
999   DCHECK(allow_macro_instructions_);
1000   DCHECK(!xn.IsZero());
1001   ret(xn);
1002   CheckVeneerPool(false, false);
1003 }
1004
1005
1006 void MacroAssembler::Rev(const Register& rd, const Register& rn) {
1007   DCHECK(allow_macro_instructions_);
1008   DCHECK(!rd.IsZero());
1009   rev(rd, rn);
1010 }
1011
1012
1013 void MacroAssembler::Rev16(const Register& rd, const Register& rn) {
1014   DCHECK(allow_macro_instructions_);
1015   DCHECK(!rd.IsZero());
1016   rev16(rd, rn);
1017 }
1018
1019
1020 void MacroAssembler::Rev32(const Register& rd, const Register& rn) {
1021   DCHECK(allow_macro_instructions_);
1022   DCHECK(!rd.IsZero());
1023   rev32(rd, rn);
1024 }
1025
1026
1027 void MacroAssembler::Ror(const Register& rd,
1028                          const Register& rs,
1029                          unsigned shift) {
1030   DCHECK(allow_macro_instructions_);
1031   DCHECK(!rd.IsZero());
1032   ror(rd, rs, shift);
1033 }
1034
1035
1036 void MacroAssembler::Ror(const Register& rd,
1037                          const Register& rn,
1038                          const Register& rm) {
1039   DCHECK(allow_macro_instructions_);
1040   DCHECK(!rd.IsZero());
1041   rorv(rd, rn, rm);
1042 }
1043
1044
1045 void MacroAssembler::Sbfiz(const Register& rd,
1046                            const Register& rn,
1047                            unsigned lsb,
1048                            unsigned width) {
1049   DCHECK(allow_macro_instructions_);
1050   DCHECK(!rd.IsZero());
1051   sbfiz(rd, rn, lsb, width);
1052 }
1053
1054
1055 void MacroAssembler::Sbfx(const Register& rd,
1056                           const Register& rn,
1057                           unsigned lsb,
1058                           unsigned width) {
1059   DCHECK(allow_macro_instructions_);
1060   DCHECK(!rd.IsZero());
1061   sbfx(rd, rn, lsb, width);
1062 }
1063
1064
1065 void MacroAssembler::Scvtf(const FPRegister& fd,
1066                            const Register& rn,
1067                            unsigned fbits) {
1068   DCHECK(allow_macro_instructions_);
1069   scvtf(fd, rn, fbits);
1070 }
1071
1072
1073 void MacroAssembler::Sdiv(const Register& rd,
1074                           const Register& rn,
1075                           const Register& rm) {
1076   DCHECK(allow_macro_instructions_);
1077   DCHECK(!rd.IsZero());
1078   sdiv(rd, rn, rm);
1079 }
1080
1081
1082 void MacroAssembler::Smaddl(const Register& rd,
1083                             const Register& rn,
1084                             const Register& rm,
1085                             const Register& ra) {
1086   DCHECK(allow_macro_instructions_);
1087   DCHECK(!rd.IsZero());
1088   smaddl(rd, rn, rm, ra);
1089 }
1090
1091
1092 void MacroAssembler::Smsubl(const Register& rd,
1093                             const Register& rn,
1094                             const Register& rm,
1095                             const Register& ra) {
1096   DCHECK(allow_macro_instructions_);
1097   DCHECK(!rd.IsZero());
1098   smsubl(rd, rn, rm, ra);
1099 }
1100
1101
1102 void MacroAssembler::Smull(const Register& rd,
1103                            const Register& rn,
1104                            const Register& rm) {
1105   DCHECK(allow_macro_instructions_);
1106   DCHECK(!rd.IsZero());
1107   smull(rd, rn, rm);
1108 }
1109
1110
1111 void MacroAssembler::Smulh(const Register& rd,
1112                            const Register& rn,
1113                            const Register& rm) {
1114   DCHECK(allow_macro_instructions_);
1115   DCHECK(!rd.IsZero());
1116   smulh(rd, rn, rm);
1117 }
1118
1119
1120 void MacroAssembler::Umull(const Register& rd, const Register& rn,
1121                            const Register& rm) {
1122   DCHECK(allow_macro_instructions_);
1123   DCHECK(!rd.IsZero());
1124   umaddl(rd, rn, rm, xzr);
1125 }
1126
1127
1128 void MacroAssembler::Sxtb(const Register& rd, const Register& rn) {
1129   DCHECK(allow_macro_instructions_);
1130   DCHECK(!rd.IsZero());
1131   sxtb(rd, rn);
1132 }
1133
1134
1135 void MacroAssembler::Sxth(const Register& rd, const Register& rn) {
1136   DCHECK(allow_macro_instructions_);
1137   DCHECK(!rd.IsZero());
1138   sxth(rd, rn);
1139 }
1140
1141
1142 void MacroAssembler::Sxtw(const Register& rd, const Register& rn) {
1143   DCHECK(allow_macro_instructions_);
1144   DCHECK(!rd.IsZero());
1145   sxtw(rd, rn);
1146 }
1147
1148
1149 void MacroAssembler::Ubfiz(const Register& rd,
1150                            const Register& rn,
1151                            unsigned lsb,
1152                            unsigned width) {
1153   DCHECK(allow_macro_instructions_);
1154   DCHECK(!rd.IsZero());
1155   ubfiz(rd, rn, lsb, width);
1156 }
1157
1158
1159 void MacroAssembler::Ubfx(const Register& rd,
1160                           const Register& rn,
1161                           unsigned lsb,
1162                           unsigned width) {
1163   DCHECK(allow_macro_instructions_);
1164   DCHECK(!rd.IsZero());
1165   ubfx(rd, rn, lsb, width);
1166 }
1167
1168
1169 void MacroAssembler::Ucvtf(const FPRegister& fd,
1170                            const Register& rn,
1171                            unsigned fbits) {
1172   DCHECK(allow_macro_instructions_);
1173   ucvtf(fd, rn, fbits);
1174 }
1175
1176
1177 void MacroAssembler::Udiv(const Register& rd,
1178                           const Register& rn,
1179                           const Register& rm) {
1180   DCHECK(allow_macro_instructions_);
1181   DCHECK(!rd.IsZero());
1182   udiv(rd, rn, rm);
1183 }
1184
1185
1186 void MacroAssembler::Umaddl(const Register& rd,
1187                             const Register& rn,
1188                             const Register& rm,
1189                             const Register& ra) {
1190   DCHECK(allow_macro_instructions_);
1191   DCHECK(!rd.IsZero());
1192   umaddl(rd, rn, rm, ra);
1193 }
1194
1195
1196 void MacroAssembler::Umsubl(const Register& rd,
1197                             const Register& rn,
1198                             const Register& rm,
1199                             const Register& ra) {
1200   DCHECK(allow_macro_instructions_);
1201   DCHECK(!rd.IsZero());
1202   umsubl(rd, rn, rm, ra);
1203 }
1204
1205
1206 void MacroAssembler::Uxtb(const Register& rd, const Register& rn) {
1207   DCHECK(allow_macro_instructions_);
1208   DCHECK(!rd.IsZero());
1209   uxtb(rd, rn);
1210 }
1211
1212
1213 void MacroAssembler::Uxth(const Register& rd, const Register& rn) {
1214   DCHECK(allow_macro_instructions_);
1215   DCHECK(!rd.IsZero());
1216   uxth(rd, rn);
1217 }
1218
1219
1220 void MacroAssembler::Uxtw(const Register& rd, const Register& rn) {
1221   DCHECK(allow_macro_instructions_);
1222   DCHECK(!rd.IsZero());
1223   uxtw(rd, rn);
1224 }
1225
1226
1227 void MacroAssembler::BumpSystemStackPointer(const Operand& space) {
1228   DCHECK(!csp.Is(sp_));
1229   if (!TmpList()->IsEmpty()) {
1230     Sub(csp, StackPointer(), space);
1231   } else {
1232     // TODO(jbramley): Several callers rely on this not using scratch
1233     // registers, so we use the assembler directly here. However, this means
1234     // that large immediate values of 'space' cannot be handled cleanly. (Only
1235     // 24-bits immediates or values of 'space' that can be encoded in one
1236     // instruction are accepted.) Once we implement our flexible scratch
1237     // register idea, we could greatly simplify this function.
1238     InstructionAccurateScope scope(this);
1239     DCHECK(space.IsImmediate());
1240     // Align to 16 bytes.
1241     uint64_t imm = RoundUp(space.ImmediateValue(), 0x10);
1242     DCHECK(is_uint24(imm));
1243
1244     Register source = StackPointer();
1245     if (CpuFeatures::IsSupported(ALWAYS_ALIGN_CSP)) {
1246       bic(csp, source, 0xf);
1247       source = csp;
1248     }
1249     if (!is_uint12(imm)) {
1250       int64_t imm_top_12_bits = imm >> 12;
1251       sub(csp, source, imm_top_12_bits << 12);
1252       source = csp;
1253       imm -= imm_top_12_bits << 12;
1254     }
1255     if (imm > 0) {
1256       sub(csp, source, imm);
1257     }
1258   }
1259   AssertStackConsistency();
1260 }
1261
1262
1263 void MacroAssembler::SyncSystemStackPointer() {
1264   DCHECK(emit_debug_code());
1265   DCHECK(!csp.Is(sp_));
1266   { InstructionAccurateScope scope(this);
1267     mov(csp, StackPointer());
1268   }
1269   AssertStackConsistency();
1270 }
1271
1272
1273 void MacroAssembler::InitializeRootRegister() {
1274   ExternalReference roots_array_start =
1275       ExternalReference::roots_array_start(isolate());
1276   Mov(root, Operand(roots_array_start));
1277 }
1278
1279
1280 void MacroAssembler::SmiTag(Register dst, Register src) {
1281   STATIC_ASSERT(kXRegSizeInBits ==
1282                 static_cast<unsigned>(kSmiShift + kSmiValueSize));
1283   DCHECK(dst.Is64Bits() && src.Is64Bits());
1284   Lsl(dst, src, kSmiShift);
1285 }
1286
1287
1288 void MacroAssembler::SmiTag(Register smi) { SmiTag(smi, smi); }
1289
1290
1291 void MacroAssembler::SmiUntag(Register dst, Register src) {
1292   STATIC_ASSERT(kXRegSizeInBits ==
1293                 static_cast<unsigned>(kSmiShift + kSmiValueSize));
1294   DCHECK(dst.Is64Bits() && src.Is64Bits());
1295   if (FLAG_enable_slow_asserts) {
1296     AssertSmi(src);
1297   }
1298   Asr(dst, src, kSmiShift);
1299 }
1300
1301
1302 void MacroAssembler::SmiUntag(Register smi) { SmiUntag(smi, smi); }
1303
1304
1305 void MacroAssembler::SmiUntagToDouble(FPRegister dst,
1306                                       Register src,
1307                                       UntagMode mode) {
1308   DCHECK(dst.Is64Bits() && src.Is64Bits());
1309   if (FLAG_enable_slow_asserts && (mode == kNotSpeculativeUntag)) {
1310     AssertSmi(src);
1311   }
1312   Scvtf(dst, src, kSmiShift);
1313 }
1314
1315
1316 void MacroAssembler::SmiUntagToFloat(FPRegister dst,
1317                                      Register src,
1318                                      UntagMode mode) {
1319   DCHECK(dst.Is32Bits() && src.Is64Bits());
1320   if (FLAG_enable_slow_asserts && (mode == kNotSpeculativeUntag)) {
1321     AssertSmi(src);
1322   }
1323   Scvtf(dst, src, kSmiShift);
1324 }
1325
1326
1327 void MacroAssembler::SmiTagAndPush(Register src) {
1328   STATIC_ASSERT((static_cast<unsigned>(kSmiShift) == kWRegSizeInBits) &&
1329                 (static_cast<unsigned>(kSmiValueSize) == kWRegSizeInBits) &&
1330                 (kSmiTag == 0));
1331   Push(src.W(), wzr);
1332 }
1333
1334
1335 void MacroAssembler::SmiTagAndPush(Register src1, Register src2) {
1336   STATIC_ASSERT((static_cast<unsigned>(kSmiShift) == kWRegSizeInBits) &&
1337                 (static_cast<unsigned>(kSmiValueSize) == kWRegSizeInBits) &&
1338                 (kSmiTag == 0));
1339   Push(src1.W(), wzr, src2.W(), wzr);
1340 }
1341
1342
1343 void MacroAssembler::JumpIfSmi(Register value,
1344                                Label* smi_label,
1345                                Label* not_smi_label) {
1346   STATIC_ASSERT((kSmiTagSize == 1) && (kSmiTag == 0));
1347   // Check if the tag bit is set.
1348   if (smi_label) {
1349     Tbz(value, 0, smi_label);
1350     if (not_smi_label) {
1351       B(not_smi_label);
1352     }
1353   } else {
1354     DCHECK(not_smi_label);
1355     Tbnz(value, 0, not_smi_label);
1356   }
1357 }
1358
1359
1360 void MacroAssembler::JumpIfNotSmi(Register value, Label* not_smi_label) {
1361   JumpIfSmi(value, NULL, not_smi_label);
1362 }
1363
1364
1365 void MacroAssembler::JumpIfBothSmi(Register value1,
1366                                    Register value2,
1367                                    Label* both_smi_label,
1368                                    Label* not_smi_label) {
1369   STATIC_ASSERT((kSmiTagSize == 1) && (kSmiTag == 0));
1370   UseScratchRegisterScope temps(this);
1371   Register tmp = temps.AcquireX();
1372   // Check if both tag bits are clear.
1373   Orr(tmp, value1, value2);
1374   JumpIfSmi(tmp, both_smi_label, not_smi_label);
1375 }
1376
1377
1378 void MacroAssembler::JumpIfEitherSmi(Register value1,
1379                                      Register value2,
1380                                      Label* either_smi_label,
1381                                      Label* not_smi_label) {
1382   STATIC_ASSERT((kSmiTagSize == 1) && (kSmiTag == 0));
1383   UseScratchRegisterScope temps(this);
1384   Register tmp = temps.AcquireX();
1385   // Check if either tag bit is clear.
1386   And(tmp, value1, value2);
1387   JumpIfSmi(tmp, either_smi_label, not_smi_label);
1388 }
1389
1390
1391 void MacroAssembler::JumpIfEitherNotSmi(Register value1,
1392                                         Register value2,
1393                                         Label* not_smi_label) {
1394   JumpIfBothSmi(value1, value2, NULL, not_smi_label);
1395 }
1396
1397
1398 void MacroAssembler::JumpIfBothNotSmi(Register value1,
1399                                       Register value2,
1400                                       Label* not_smi_label) {
1401   JumpIfEitherSmi(value1, value2, NULL, not_smi_label);
1402 }
1403
1404
1405 void MacroAssembler::ObjectTag(Register tagged_obj, Register obj) {
1406   STATIC_ASSERT(kHeapObjectTag == 1);
1407   if (emit_debug_code()) {
1408     Label ok;
1409     Tbz(obj, 0, &ok);
1410     Abort(kObjectTagged);
1411     Bind(&ok);
1412   }
1413   Orr(tagged_obj, obj, kHeapObjectTag);
1414 }
1415
1416
1417 void MacroAssembler::ObjectUntag(Register untagged_obj, Register obj) {
1418   STATIC_ASSERT(kHeapObjectTag == 1);
1419   if (emit_debug_code()) {
1420     Label ok;
1421     Tbnz(obj, 0, &ok);
1422     Abort(kObjectNotTagged);
1423     Bind(&ok);
1424   }
1425   Bic(untagged_obj, obj, kHeapObjectTag);
1426 }
1427
1428
1429 void MacroAssembler::IsObjectNameType(Register object,
1430                                       Register type,
1431                                       Label* fail) {
1432   CompareObjectType(object, type, type, LAST_NAME_TYPE);
1433   B(hi, fail);
1434 }
1435
1436
1437 void MacroAssembler::IsObjectJSObjectType(Register heap_object,
1438                                           Register map,
1439                                           Register scratch,
1440                                           Label* fail) {
1441   Ldr(map, FieldMemOperand(heap_object, HeapObject::kMapOffset));
1442   IsInstanceJSObjectType(map, scratch, fail);
1443 }
1444
1445
1446 void MacroAssembler::IsInstanceJSObjectType(Register map,
1447                                             Register scratch,
1448                                             Label* fail) {
1449   Ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
1450   // If cmp result is lt, the following ccmp will clear all flags.
1451   // Z == 0, N == V implies gt condition.
1452   Cmp(scratch, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
1453   Ccmp(scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE, NoFlag, ge);
1454
1455   // If we didn't get a valid label object just fall through and leave the
1456   // flags updated.
1457   if (fail != NULL) {
1458     B(gt, fail);
1459   }
1460 }
1461
1462
1463 void MacroAssembler::IsObjectJSStringType(Register object,
1464                                           Register type,
1465                                           Label* not_string,
1466                                           Label* string) {
1467   Ldr(type, FieldMemOperand(object, HeapObject::kMapOffset));
1468   Ldrb(type.W(), FieldMemOperand(type, Map::kInstanceTypeOffset));
1469
1470   STATIC_ASSERT(kStringTag == 0);
1471   DCHECK((string != NULL) || (not_string != NULL));
1472   if (string == NULL) {
1473     TestAndBranchIfAnySet(type.W(), kIsNotStringMask, not_string);
1474   } else if (not_string == NULL) {
1475     TestAndBranchIfAllClear(type.W(), kIsNotStringMask, string);
1476   } else {
1477     TestAndBranchIfAnySet(type.W(), kIsNotStringMask, not_string);
1478     B(string);
1479   }
1480 }
1481
1482
1483 void MacroAssembler::Push(Handle<Object> handle) {
1484   UseScratchRegisterScope temps(this);
1485   Register tmp = temps.AcquireX();
1486   Mov(tmp, Operand(handle));
1487   Push(tmp);
1488 }
1489
1490
1491 void MacroAssembler::Claim(uint64_t count, uint64_t unit_size) {
1492   uint64_t size = count * unit_size;
1493
1494   if (size == 0) {
1495     return;
1496   }
1497
1498   if (csp.Is(StackPointer())) {
1499     DCHECK(size % 16 == 0);
1500   } else {
1501     BumpSystemStackPointer(size);
1502   }
1503
1504   Sub(StackPointer(), StackPointer(), size);
1505 }
1506
1507
1508 void MacroAssembler::Claim(const Register& count, uint64_t unit_size) {
1509   if (unit_size == 0) return;
1510   DCHECK(base::bits::IsPowerOfTwo64(unit_size));
1511
1512   const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits);
1513   const Operand size(count, LSL, shift);
1514
1515   if (size.IsZero()) {
1516     return;
1517   }
1518
1519   if (!csp.Is(StackPointer())) {
1520     BumpSystemStackPointer(size);
1521   }
1522
1523   Sub(StackPointer(), StackPointer(), size);
1524 }
1525
1526
1527 void MacroAssembler::ClaimBySMI(const Register& count_smi, uint64_t unit_size) {
1528   DCHECK(unit_size == 0 || base::bits::IsPowerOfTwo64(unit_size));
1529   const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits) - kSmiShift;
1530   const Operand size(count_smi,
1531                      (shift >= 0) ? (LSL) : (LSR),
1532                      (shift >= 0) ? (shift) : (-shift));
1533
1534   if (size.IsZero()) {
1535     return;
1536   }
1537
1538   if (!csp.Is(StackPointer())) {
1539     BumpSystemStackPointer(size);
1540   }
1541
1542   Sub(StackPointer(), StackPointer(), size);
1543 }
1544
1545
1546 void MacroAssembler::Drop(uint64_t count, uint64_t unit_size) {
1547   uint64_t size = count * unit_size;
1548
1549   if (size == 0) {
1550     return;
1551   }
1552
1553   Add(StackPointer(), StackPointer(), size);
1554
1555   if (csp.Is(StackPointer())) {
1556     DCHECK(size % 16 == 0);
1557   } else if (emit_debug_code()) {
1558     // It is safe to leave csp where it is when unwinding the JavaScript stack,
1559     // but if we keep it matching StackPointer, the simulator can detect memory
1560     // accesses in the now-free part of the stack.
1561     SyncSystemStackPointer();
1562   }
1563 }
1564
1565
1566 void MacroAssembler::Drop(const Register& count, uint64_t unit_size) {
1567   if (unit_size == 0) return;
1568   DCHECK(base::bits::IsPowerOfTwo64(unit_size));
1569
1570   const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits);
1571   const Operand size(count, LSL, shift);
1572
1573   if (size.IsZero()) {
1574     return;
1575   }
1576
1577   Add(StackPointer(), StackPointer(), size);
1578
1579   if (!csp.Is(StackPointer()) && emit_debug_code()) {
1580     // It is safe to leave csp where it is when unwinding the JavaScript stack,
1581     // but if we keep it matching StackPointer, the simulator can detect memory
1582     // accesses in the now-free part of the stack.
1583     SyncSystemStackPointer();
1584   }
1585 }
1586
1587
1588 void MacroAssembler::DropBySMI(const Register& count_smi, uint64_t unit_size) {
1589   DCHECK(unit_size == 0 || base::bits::IsPowerOfTwo64(unit_size));
1590   const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits) - kSmiShift;
1591   const Operand size(count_smi,
1592                      (shift >= 0) ? (LSL) : (LSR),
1593                      (shift >= 0) ? (shift) : (-shift));
1594
1595   if (size.IsZero()) {
1596     return;
1597   }
1598
1599   Add(StackPointer(), StackPointer(), size);
1600
1601   if (!csp.Is(StackPointer()) && emit_debug_code()) {
1602     // It is safe to leave csp where it is when unwinding the JavaScript stack,
1603     // but if we keep it matching StackPointer, the simulator can detect memory
1604     // accesses in the now-free part of the stack.
1605     SyncSystemStackPointer();
1606   }
1607 }
1608
1609
1610 void MacroAssembler::CompareAndBranch(const Register& lhs,
1611                                       const Operand& rhs,
1612                                       Condition cond,
1613                                       Label* label) {
1614   if (rhs.IsImmediate() && (rhs.ImmediateValue() == 0) &&
1615       ((cond == eq) || (cond == ne))) {
1616     if (cond == eq) {
1617       Cbz(lhs, label);
1618     } else {
1619       Cbnz(lhs, label);
1620     }
1621   } else {
1622     Cmp(lhs, rhs);
1623     B(cond, label);
1624   }
1625 }
1626
1627
1628 void MacroAssembler::TestAndBranchIfAnySet(const Register& reg,
1629                                            const uint64_t bit_pattern,
1630                                            Label* label) {
1631   int bits = reg.SizeInBits();
1632   DCHECK(CountSetBits(bit_pattern, bits) > 0);
1633   if (CountSetBits(bit_pattern, bits) == 1) {
1634     Tbnz(reg, MaskToBit(bit_pattern), label);
1635   } else {
1636     Tst(reg, bit_pattern);
1637     B(ne, label);
1638   }
1639 }
1640
1641
1642 void MacroAssembler::TestAndBranchIfAllClear(const Register& reg,
1643                                              const uint64_t bit_pattern,
1644                                              Label* label) {
1645   int bits = reg.SizeInBits();
1646   DCHECK(CountSetBits(bit_pattern, bits) > 0);
1647   if (CountSetBits(bit_pattern, bits) == 1) {
1648     Tbz(reg, MaskToBit(bit_pattern), label);
1649   } else {
1650     Tst(reg, bit_pattern);
1651     B(eq, label);
1652   }
1653 }
1654
1655
1656 void MacroAssembler::InlineData(uint64_t data) {
1657   DCHECK(is_uint16(data));
1658   InstructionAccurateScope scope(this, 1);
1659   movz(xzr, data);
1660 }
1661
1662
1663 void MacroAssembler::EnableInstrumentation() {
1664   InstructionAccurateScope scope(this, 1);
1665   movn(xzr, InstrumentStateEnable);
1666 }
1667
1668
1669 void MacroAssembler::DisableInstrumentation() {
1670   InstructionAccurateScope scope(this, 1);
1671   movn(xzr, InstrumentStateDisable);
1672 }
1673
1674
1675 void MacroAssembler::AnnotateInstrumentation(const char* marker_name) {
1676   DCHECK(strlen(marker_name) == 2);
1677
1678   // We allow only printable characters in the marker names. Unprintable
1679   // characters are reserved for controlling features of the instrumentation.
1680   DCHECK(isprint(marker_name[0]) && isprint(marker_name[1]));
1681
1682   InstructionAccurateScope scope(this, 1);
1683   movn(xzr, (marker_name[1] << 8) | marker_name[0]);
1684 }
1685
1686 }  // namespace internal
1687 }  // namespace v8
1688
1689 #endif  // V8_ARM64_MACRO_ASSEMBLER_ARM64_INL_H_