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