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
19namespace v8 {
20namespace internal {
21
22
23MemOperand FieldMemOperand(Register object, int offset) {
24  return MemOperand(object, offset - kHeapObjectTag);
25}
26
27
28MemOperand UntagSmiFieldMemOperand(Register object, int offset) {
29  return UntagSmiMemOperand(object, offset - kHeapObjectTag);
30}
31
32
33MemOperand 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
40Handle<Object> MacroAssembler::CodeObject() {
41  DCHECK(!code_object_.is_null());
42  return code_object_;
43}
44
45
46void 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
55void 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
64void MacroAssembler::Tst(const Register& rn,
65                         const Operand& operand) {
66  DCHECK(allow_macro_instructions_);
67  LogicalMacro(AppropriateZeroRegFor(rn), rn, operand, ANDS);
68}
69
70
71void 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
80void 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
89void 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
98void 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
107void 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
116void 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
125void 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
138void 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
151void 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
163void 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
176void 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
189void 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
202void MacroAssembler::Cmn(const Register& rn, const Operand& operand) {
203  DCHECK(allow_macro_instructions_);
204  Adds(AppropriateZeroRegFor(rn), rn, operand);
205}
206
207
208void MacroAssembler::Cmp(const Register& rn, const Operand& operand) {
209  DCHECK(allow_macro_instructions_);
210  Subs(AppropriateZeroRegFor(rn), rn, operand);
211}
212
213
214void 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
226void MacroAssembler::Negs(const Register& rd,
227                          const Operand& operand) {
228  DCHECK(allow_macro_instructions_);
229  Subs(rd, AppropriateZeroRegFor(rd), operand);
230}
231
232
233void 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
242void 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
251void 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
260void 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
269void 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
278void 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
287void 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)                         \
295void MacroAssembler::FN(const REGTYPE REG, const MemOperand& addr) {  \
296  DCHECK(allow_macro_instructions_);                                  \
297  LoadStoreMacro(REG, addr, OP);                                      \
298}
299LS_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  }
309LSPAIR_MACRO_LIST(DEFINE_FUNCTION)
310#undef DEFINE_FUNCTION
311
312
313void 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
322void 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
331void MacroAssembler::B(Label* label) {
332  b(label);
333  CheckVeneerPool(false, false);
334}
335
336
337void MacroAssembler::B(Condition cond, Label* label) {
338  DCHECK(allow_macro_instructions_);
339  B(label, cond);
340}
341
342
343void 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
353void 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
363void MacroAssembler::Bind(Label* label) {
364  DCHECK(allow_macro_instructions_);
365  bind(label);
366}
367
368
369void MacroAssembler::Bl(Label* label) {
370  DCHECK(allow_macro_instructions_);
371  bl(label);
372}
373
374
375void MacroAssembler::Blr(const Register& xn) {
376  DCHECK(allow_macro_instructions_);
377  DCHECK(!xn.IsZero());
378  blr(xn);
379}
380
381
382void MacroAssembler::Br(const Register& xn) {
383  DCHECK(allow_macro_instructions_);
384  DCHECK(!xn.IsZero());
385  br(xn);
386}
387
388
389void MacroAssembler::Brk(int code) {
390  DCHECK(allow_macro_instructions_);
391  brk(code);
392}
393
394
395void 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
405void 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
415void MacroAssembler::Cls(const Register& rd, const Register& rn) {
416  DCHECK(allow_macro_instructions_);
417  DCHECK(!rd.IsZero());
418  cls(rd, rn);
419}
420
421
422void MacroAssembler::Clz(const Register& rd, const Register& rn) {
423  DCHECK(allow_macro_instructions_);
424  DCHECK(!rd.IsZero());
425  clz(rd, rn);
426}
427
428
429void 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.
441void 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.
452void 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
465void 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
473void 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
481void 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
492void 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
503void 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
514void MacroAssembler::Dmb(BarrierDomain domain, BarrierType type) {
515  DCHECK(allow_macro_instructions_);
516  dmb(domain, type);
517}
518
519
520void MacroAssembler::Dsb(BarrierDomain domain, BarrierType type) {
521  DCHECK(allow_macro_instructions_);
522  dsb(domain, type);
523}
524
525
526void MacroAssembler::Debug(const char* message, uint32_t code, Instr params) {
527  DCHECK(allow_macro_instructions_);
528  debug(message, code, params);
529}
530
531
532void 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
542void MacroAssembler::Fabs(const FPRegister& fd, const FPRegister& fn) {
543  DCHECK(allow_macro_instructions_);
544  fabs(fd, fn);
545}
546
547
548void 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
556void 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
566void MacroAssembler::Fcmp(const FPRegister& fn, const FPRegister& fm) {
567  DCHECK(allow_macro_instructions_);
568  fcmp(fn, fm);
569}
570
571
572void 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
585void 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
595void MacroAssembler::Fcvt(const FPRegister& fd, const FPRegister& fn) {
596  DCHECK(allow_macro_instructions_);
597  fcvt(fd, fn);
598}
599
600
601void MacroAssembler::Fcvtas(const Register& rd, const FPRegister& fn) {
602  DCHECK(allow_macro_instructions_);
603  DCHECK(!rd.IsZero());
604  fcvtas(rd, fn);
605}
606
607
608void MacroAssembler::Fcvtau(const Register& rd, const FPRegister& fn) {
609  DCHECK(allow_macro_instructions_);
610  DCHECK(!rd.IsZero());
611  fcvtau(rd, fn);
612}
613
614
615void MacroAssembler::Fcvtms(const Register& rd, const FPRegister& fn) {
616  DCHECK(allow_macro_instructions_);
617  DCHECK(!rd.IsZero());
618  fcvtms(rd, fn);
619}
620
621
622void MacroAssembler::Fcvtmu(const Register& rd, const FPRegister& fn) {
623  DCHECK(allow_macro_instructions_);
624  DCHECK(!rd.IsZero());
625  fcvtmu(rd, fn);
626}
627
628
629void MacroAssembler::Fcvtns(const Register& rd, const FPRegister& fn) {
630  DCHECK(allow_macro_instructions_);
631  DCHECK(!rd.IsZero());
632  fcvtns(rd, fn);
633}
634
635
636void MacroAssembler::Fcvtnu(const Register& rd, const FPRegister& fn) {
637  DCHECK(allow_macro_instructions_);
638  DCHECK(!rd.IsZero());
639  fcvtnu(rd, fn);
640}
641
642
643void MacroAssembler::Fcvtzs(const Register& rd, const FPRegister& fn) {
644  DCHECK(allow_macro_instructions_);
645  DCHECK(!rd.IsZero());
646  fcvtzs(rd, fn);
647}
648void MacroAssembler::Fcvtzu(const Register& rd, const FPRegister& fn) {
649  DCHECK(allow_macro_instructions_);
650  DCHECK(!rd.IsZero());
651  fcvtzu(rd, fn);
652}
653
654
655void 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
663void 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
672void 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
680void 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
688void 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
696void 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
704void 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
716void MacroAssembler::Fmov(FPRegister fd, Register rn) {
717  DCHECK(allow_macro_instructions_);
718  fmov(fd, rn);
719}
720
721
722void 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
740void 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
762void MacroAssembler::Fmov(Register rd, FPRegister fn) {
763  DCHECK(allow_macro_instructions_);
764  DCHECK(!rd.IsZero());
765  fmov(rd, fn);
766}
767
768
769void 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
778void 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
786void MacroAssembler::Fneg(const FPRegister& fd, const FPRegister& fn) {
787  DCHECK(allow_macro_instructions_);
788  fneg(fd, fn);
789}
790
791
792void 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
801void 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
810void MacroAssembler::Frinta(const FPRegister& fd, const FPRegister& fn) {
811  DCHECK(allow_macro_instructions_);
812  frinta(fd, fn);
813}
814
815
816void MacroAssembler::Frintm(const FPRegister& fd, const FPRegister& fn) {
817  DCHECK(allow_macro_instructions_);
818  frintm(fd, fn);
819}
820
821
822void MacroAssembler::Frintn(const FPRegister& fd, const FPRegister& fn) {
823  DCHECK(allow_macro_instructions_);
824  frintn(fd, fn);
825}
826
827
828void MacroAssembler::Frintz(const FPRegister& fd, const FPRegister& fn) {
829  DCHECK(allow_macro_instructions_);
830  frintz(fd, fn);
831}
832
833
834void MacroAssembler::Fsqrt(const FPRegister& fd, const FPRegister& fn) {
835  DCHECK(allow_macro_instructions_);
836  fsqrt(fd, fn);
837}
838
839
840void MacroAssembler::Fsub(const FPRegister& fd,
841                          const FPRegister& fn,
842                          const FPRegister& fm) {
843  DCHECK(allow_macro_instructions_);
844  fsub(fd, fn, fm);
845}
846
847
848void MacroAssembler::Hint(SystemHint code) {
849  DCHECK(allow_macro_instructions_);
850  hint(code);
851}
852
853
854void MacroAssembler::Hlt(int code) {
855  DCHECK(allow_macro_instructions_);
856  hlt(code);
857}
858
859
860void MacroAssembler::Isb() {
861  DCHECK(allow_macro_instructions_);
862  isb();
863}
864
865
866void MacroAssembler::Ldnp(const CPURegister& rt,
867                          const CPURegister& rt2,
868                          const MemOperand& src) {
869  DCHECK(allow_macro_instructions_);
870  DCHECK(!AreAliased(rt, rt2));
871  ldnp(rt, rt2, src);
872}
873
874
875void MacroAssembler::Ldr(const CPURegister& rt, const Immediate& imm) {
876  DCHECK(allow_macro_instructions_);
877  ldr(rt, imm);
878}
879
880
881void MacroAssembler::Ldr(const CPURegister& rt, double imm) {
882  DCHECK(allow_macro_instructions_);
883  DCHECK(rt.Is64Bits());
884  ldr(rt, Immediate(double_to_rawbits(imm)));
885}
886
887
888void MacroAssembler::Lsl(const Register& rd,
889                         const Register& rn,
890                         unsigned shift) {
891  DCHECK(allow_macro_instructions_);
892  DCHECK(!rd.IsZero());
893  lsl(rd, rn, shift);
894}
895
896
897void MacroAssembler::Lsl(const Register& rd,
898                         const Register& rn,
899                         const Register& rm) {
900  DCHECK(allow_macro_instructions_);
901  DCHECK(!rd.IsZero());
902  lslv(rd, rn, rm);
903}
904
905
906void MacroAssembler::Lsr(const Register& rd,
907                         const Register& rn,
908                         unsigned shift) {
909  DCHECK(allow_macro_instructions_);
910  DCHECK(!rd.IsZero());
911  lsr(rd, rn, shift);
912}
913
914
915void MacroAssembler::Lsr(const Register& rd,
916                         const Register& rn,
917                         const Register& rm) {
918  DCHECK(allow_macro_instructions_);
919  DCHECK(!rd.IsZero());
920  lsrv(rd, rn, rm);
921}
922
923
924void MacroAssembler::Madd(const Register& rd,
925                          const Register& rn,
926                          const Register& rm,
927                          const Register& ra) {
928  DCHECK(allow_macro_instructions_);
929  DCHECK(!rd.IsZero());
930  madd(rd, rn, rm, ra);
931}
932
933
934void MacroAssembler::Mneg(const Register& rd,
935                          const Register& rn,
936                          const Register& rm) {
937  DCHECK(allow_macro_instructions_);
938  DCHECK(!rd.IsZero());
939  mneg(rd, rn, rm);
940}
941
942
943void MacroAssembler::Mov(const Register& rd, const Register& rn) {
944  DCHECK(allow_macro_instructions_);
945  DCHECK(!rd.IsZero());
946  // Emit a register move only if the registers are distinct, or if they are
947  // not X registers. Note that mov(w0, w0) is not a no-op because it clears
948  // the top word of x0.
949  if (!rd.Is(rn) || !rd.Is64Bits()) {
950    Assembler::mov(rd, rn);
951  }
952}
953
954
955void MacroAssembler::Movk(const Register& rd, uint64_t imm, int shift) {
956  DCHECK(allow_macro_instructions_);
957  DCHECK(!rd.IsZero());
958  movk(rd, imm, shift);
959}
960
961
962void MacroAssembler::Mrs(const Register& rt, SystemRegister sysreg) {
963  DCHECK(allow_macro_instructions_);
964  DCHECK(!rt.IsZero());
965  mrs(rt, sysreg);
966}
967
968
969void MacroAssembler::Msr(SystemRegister sysreg, const Register& rt) {
970  DCHECK(allow_macro_instructions_);
971  msr(sysreg, rt);
972}
973
974
975void MacroAssembler::Msub(const Register& rd,
976                          const Register& rn,
977                          const Register& rm,
978                          const Register& ra) {
979  DCHECK(allow_macro_instructions_);
980  DCHECK(!rd.IsZero());
981  msub(rd, rn, rm, ra);
982}
983
984
985void MacroAssembler::Mul(const Register& rd,
986                         const Register& rn,
987                         const Register& rm) {
988  DCHECK(allow_macro_instructions_);
989  DCHECK(!rd.IsZero());
990  mul(rd, rn, rm);
991}
992
993
994void MacroAssembler::Rbit(const Register& rd, const Register& rn) {
995  DCHECK(allow_macro_instructions_);
996  DCHECK(!rd.IsZero());
997  rbit(rd, rn);
998}
999
1000
1001void MacroAssembler::Ret(const Register& xn) {
1002  DCHECK(allow_macro_instructions_);
1003  DCHECK(!xn.IsZero());
1004  ret(xn);
1005  CheckVeneerPool(false, false);
1006}
1007
1008
1009void MacroAssembler::Rev(const Register& rd, const Register& rn) {
1010  DCHECK(allow_macro_instructions_);
1011  DCHECK(!rd.IsZero());
1012  rev(rd, rn);
1013}
1014
1015
1016void MacroAssembler::Rev16(const Register& rd, const Register& rn) {
1017  DCHECK(allow_macro_instructions_);
1018  DCHECK(!rd.IsZero());
1019  rev16(rd, rn);
1020}
1021
1022
1023void MacroAssembler::Rev32(const Register& rd, const Register& rn) {
1024  DCHECK(allow_macro_instructions_);
1025  DCHECK(!rd.IsZero());
1026  rev32(rd, rn);
1027}
1028
1029
1030void MacroAssembler::Ror(const Register& rd,
1031                         const Register& rs,
1032                         unsigned shift) {
1033  DCHECK(allow_macro_instructions_);
1034  DCHECK(!rd.IsZero());
1035  ror(rd, rs, shift);
1036}
1037
1038
1039void MacroAssembler::Ror(const Register& rd,
1040                         const Register& rn,
1041                         const Register& rm) {
1042  DCHECK(allow_macro_instructions_);
1043  DCHECK(!rd.IsZero());
1044  rorv(rd, rn, rm);
1045}
1046
1047
1048void MacroAssembler::Sbfiz(const Register& rd,
1049                           const Register& rn,
1050                           unsigned lsb,
1051                           unsigned width) {
1052  DCHECK(allow_macro_instructions_);
1053  DCHECK(!rd.IsZero());
1054  sbfiz(rd, rn, lsb, width);
1055}
1056
1057
1058void MacroAssembler::Sbfx(const Register& rd,
1059                          const Register& rn,
1060                          unsigned lsb,
1061                          unsigned width) {
1062  DCHECK(allow_macro_instructions_);
1063  DCHECK(!rd.IsZero());
1064  sbfx(rd, rn, lsb, width);
1065}
1066
1067
1068void MacroAssembler::Scvtf(const FPRegister& fd,
1069                           const Register& rn,
1070                           unsigned fbits) {
1071  DCHECK(allow_macro_instructions_);
1072  scvtf(fd, rn, fbits);
1073}
1074
1075
1076void MacroAssembler::Sdiv(const Register& rd,
1077                          const Register& rn,
1078                          const Register& rm) {
1079  DCHECK(allow_macro_instructions_);
1080  DCHECK(!rd.IsZero());
1081  sdiv(rd, rn, rm);
1082}
1083
1084
1085void MacroAssembler::Smaddl(const Register& rd,
1086                            const Register& rn,
1087                            const Register& rm,
1088                            const Register& ra) {
1089  DCHECK(allow_macro_instructions_);
1090  DCHECK(!rd.IsZero());
1091  smaddl(rd, rn, rm, ra);
1092}
1093
1094
1095void MacroAssembler::Smsubl(const Register& rd,
1096                            const Register& rn,
1097                            const Register& rm,
1098                            const Register& ra) {
1099  DCHECK(allow_macro_instructions_);
1100  DCHECK(!rd.IsZero());
1101  smsubl(rd, rn, rm, ra);
1102}
1103
1104
1105void MacroAssembler::Smull(const Register& rd,
1106                           const Register& rn,
1107                           const Register& rm) {
1108  DCHECK(allow_macro_instructions_);
1109  DCHECK(!rd.IsZero());
1110  smull(rd, rn, rm);
1111}
1112
1113
1114void MacroAssembler::Smulh(const Register& rd,
1115                           const Register& rn,
1116                           const Register& rm) {
1117  DCHECK(allow_macro_instructions_);
1118  DCHECK(!rd.IsZero());
1119  smulh(rd, rn, rm);
1120}
1121
1122
1123void MacroAssembler::Stnp(const CPURegister& rt,
1124                          const CPURegister& rt2,
1125                          const MemOperand& dst) {
1126  DCHECK(allow_macro_instructions_);
1127  stnp(rt, rt2, dst);
1128}
1129
1130
1131void MacroAssembler::Sxtb(const Register& rd, const Register& rn) {
1132  DCHECK(allow_macro_instructions_);
1133  DCHECK(!rd.IsZero());
1134  sxtb(rd, rn);
1135}
1136
1137
1138void MacroAssembler::Sxth(const Register& rd, const Register& rn) {
1139  DCHECK(allow_macro_instructions_);
1140  DCHECK(!rd.IsZero());
1141  sxth(rd, rn);
1142}
1143
1144
1145void MacroAssembler::Sxtw(const Register& rd, const Register& rn) {
1146  DCHECK(allow_macro_instructions_);
1147  DCHECK(!rd.IsZero());
1148  sxtw(rd, rn);
1149}
1150
1151
1152void MacroAssembler::Ubfiz(const Register& rd,
1153                           const Register& rn,
1154                           unsigned lsb,
1155                           unsigned width) {
1156  DCHECK(allow_macro_instructions_);
1157  DCHECK(!rd.IsZero());
1158  ubfiz(rd, rn, lsb, width);
1159}
1160
1161
1162void MacroAssembler::Ubfx(const Register& rd,
1163                          const Register& rn,
1164                          unsigned lsb,
1165                          unsigned width) {
1166  DCHECK(allow_macro_instructions_);
1167  DCHECK(!rd.IsZero());
1168  ubfx(rd, rn, lsb, width);
1169}
1170
1171
1172void MacroAssembler::Ucvtf(const FPRegister& fd,
1173                           const Register& rn,
1174                           unsigned fbits) {
1175  DCHECK(allow_macro_instructions_);
1176  ucvtf(fd, rn, fbits);
1177}
1178
1179
1180void MacroAssembler::Udiv(const Register& rd,
1181                          const Register& rn,
1182                          const Register& rm) {
1183  DCHECK(allow_macro_instructions_);
1184  DCHECK(!rd.IsZero());
1185  udiv(rd, rn, rm);
1186}
1187
1188
1189void MacroAssembler::Umaddl(const Register& rd,
1190                            const Register& rn,
1191                            const Register& rm,
1192                            const Register& ra) {
1193  DCHECK(allow_macro_instructions_);
1194  DCHECK(!rd.IsZero());
1195  umaddl(rd, rn, rm, ra);
1196}
1197
1198
1199void MacroAssembler::Umsubl(const Register& rd,
1200                            const Register& rn,
1201                            const Register& rm,
1202                            const Register& ra) {
1203  DCHECK(allow_macro_instructions_);
1204  DCHECK(!rd.IsZero());
1205  umsubl(rd, rn, rm, ra);
1206}
1207
1208
1209void MacroAssembler::Uxtb(const Register& rd, const Register& rn) {
1210  DCHECK(allow_macro_instructions_);
1211  DCHECK(!rd.IsZero());
1212  uxtb(rd, rn);
1213}
1214
1215
1216void MacroAssembler::Uxth(const Register& rd, const Register& rn) {
1217  DCHECK(allow_macro_instructions_);
1218  DCHECK(!rd.IsZero());
1219  uxth(rd, rn);
1220}
1221
1222
1223void MacroAssembler::Uxtw(const Register& rd, const Register& rn) {
1224  DCHECK(allow_macro_instructions_);
1225  DCHECK(!rd.IsZero());
1226  uxtw(rd, rn);
1227}
1228
1229
1230void MacroAssembler::BumpSystemStackPointer(const Operand& space) {
1231  DCHECK(!csp.Is(sp_));
1232  if (!TmpList()->IsEmpty()) {
1233    if (CpuFeatures::IsSupported(ALWAYS_ALIGN_CSP)) {
1234      UseScratchRegisterScope temps(this);
1235      Register temp = temps.AcquireX();
1236      Sub(temp, StackPointer(), space);
1237      Bic(csp, temp, 0xf);
1238    } else {
1239      Sub(csp, StackPointer(), space);
1240    }
1241  } else {
1242    // TODO(jbramley): Several callers rely on this not using scratch
1243    // registers, so we use the assembler directly here. However, this means
1244    // that large immediate values of 'space' cannot be handled cleanly. (Only
1245    // 24-bits immediates or values of 'space' that can be encoded in one
1246    // instruction are accepted.) Once we implement our flexible scratch
1247    // register idea, we could greatly simplify this function.
1248    InstructionAccurateScope scope(this);
1249    DCHECK(space.IsImmediate());
1250    // Align to 16 bytes.
1251    uint64_t imm = RoundUp(space.ImmediateValue(), 0x10);
1252    DCHECK(is_uint24(imm));
1253
1254    Register source = StackPointer();
1255    if (CpuFeatures::IsSupported(ALWAYS_ALIGN_CSP)) {
1256      bic(csp, source, 0xf);
1257      source = csp;
1258    }
1259    if (!is_uint12(imm)) {
1260      int64_t imm_top_12_bits = imm >> 12;
1261      sub(csp, source, imm_top_12_bits << 12);
1262      source = csp;
1263      imm -= imm_top_12_bits << 12;
1264    }
1265    if (imm > 0) {
1266      sub(csp, source, imm);
1267    }
1268  }
1269  AssertStackConsistency();
1270}
1271
1272
1273void MacroAssembler::SyncSystemStackPointer() {
1274  DCHECK(emit_debug_code());
1275  DCHECK(!csp.Is(sp_));
1276  { InstructionAccurateScope scope(this);
1277    if (CpuFeatures::IsSupported(ALWAYS_ALIGN_CSP)) {
1278      bic(csp, StackPointer(), 0xf);
1279    } else {
1280      mov(csp, StackPointer());
1281    }
1282  }
1283  AssertStackConsistency();
1284}
1285
1286
1287void MacroAssembler::InitializeRootRegister() {
1288  ExternalReference roots_array_start =
1289      ExternalReference::roots_array_start(isolate());
1290  Mov(root, Operand(roots_array_start));
1291}
1292
1293
1294void MacroAssembler::SmiTag(Register dst, Register src) {
1295  STATIC_ASSERT(kXRegSizeInBits ==
1296                static_cast<unsigned>(kSmiShift + kSmiValueSize));
1297  DCHECK(dst.Is64Bits() && src.Is64Bits());
1298  Lsl(dst, src, kSmiShift);
1299}
1300
1301
1302void MacroAssembler::SmiTag(Register smi) { SmiTag(smi, smi); }
1303
1304
1305void MacroAssembler::SmiUntag(Register dst, Register src) {
1306  STATIC_ASSERT(kXRegSizeInBits ==
1307                static_cast<unsigned>(kSmiShift + kSmiValueSize));
1308  DCHECK(dst.Is64Bits() && src.Is64Bits());
1309  if (FLAG_enable_slow_asserts) {
1310    AssertSmi(src);
1311  }
1312  Asr(dst, src, kSmiShift);
1313}
1314
1315
1316void MacroAssembler::SmiUntag(Register smi) { SmiUntag(smi, smi); }
1317
1318
1319void MacroAssembler::SmiUntagToDouble(FPRegister dst,
1320                                      Register src,
1321                                      UntagMode mode) {
1322  DCHECK(dst.Is64Bits() && src.Is64Bits());
1323  if (FLAG_enable_slow_asserts && (mode == kNotSpeculativeUntag)) {
1324    AssertSmi(src);
1325  }
1326  Scvtf(dst, src, kSmiShift);
1327}
1328
1329
1330void MacroAssembler::SmiUntagToFloat(FPRegister dst,
1331                                     Register src,
1332                                     UntagMode mode) {
1333  DCHECK(dst.Is32Bits() && src.Is64Bits());
1334  if (FLAG_enable_slow_asserts && (mode == kNotSpeculativeUntag)) {
1335    AssertSmi(src);
1336  }
1337  Scvtf(dst, src, kSmiShift);
1338}
1339
1340
1341void MacroAssembler::SmiTagAndPush(Register src) {
1342  STATIC_ASSERT((static_cast<unsigned>(kSmiShift) == kWRegSizeInBits) &&
1343                (static_cast<unsigned>(kSmiValueSize) == kWRegSizeInBits) &&
1344                (kSmiTag == 0));
1345  Push(src.W(), wzr);
1346}
1347
1348
1349void MacroAssembler::SmiTagAndPush(Register src1, Register src2) {
1350  STATIC_ASSERT((static_cast<unsigned>(kSmiShift) == kWRegSizeInBits) &&
1351                (static_cast<unsigned>(kSmiValueSize) == kWRegSizeInBits) &&
1352                (kSmiTag == 0));
1353  Push(src1.W(), wzr, src2.W(), wzr);
1354}
1355
1356
1357void MacroAssembler::JumpIfSmi(Register value,
1358                               Label* smi_label,
1359                               Label* not_smi_label) {
1360  STATIC_ASSERT((kSmiTagSize == 1) && (kSmiTag == 0));
1361  // Check if the tag bit is set.
1362  if (smi_label) {
1363    Tbz(value, 0, smi_label);
1364    if (not_smi_label) {
1365      B(not_smi_label);
1366    }
1367  } else {
1368    DCHECK(not_smi_label);
1369    Tbnz(value, 0, not_smi_label);
1370  }
1371}
1372
1373
1374void MacroAssembler::JumpIfNotSmi(Register value, Label* not_smi_label) {
1375  JumpIfSmi(value, NULL, not_smi_label);
1376}
1377
1378
1379void MacroAssembler::JumpIfBothSmi(Register value1,
1380                                   Register value2,
1381                                   Label* both_smi_label,
1382                                   Label* not_smi_label) {
1383  STATIC_ASSERT((kSmiTagSize == 1) && (kSmiTag == 0));
1384  UseScratchRegisterScope temps(this);
1385  Register tmp = temps.AcquireX();
1386  // Check if both tag bits are clear.
1387  Orr(tmp, value1, value2);
1388  JumpIfSmi(tmp, both_smi_label, not_smi_label);
1389}
1390
1391
1392void MacroAssembler::JumpIfEitherSmi(Register value1,
1393                                     Register value2,
1394                                     Label* either_smi_label,
1395                                     Label* not_smi_label) {
1396  STATIC_ASSERT((kSmiTagSize == 1) && (kSmiTag == 0));
1397  UseScratchRegisterScope temps(this);
1398  Register tmp = temps.AcquireX();
1399  // Check if either tag bit is clear.
1400  And(tmp, value1, value2);
1401  JumpIfSmi(tmp, either_smi_label, not_smi_label);
1402}
1403
1404
1405void MacroAssembler::JumpIfEitherNotSmi(Register value1,
1406                                        Register value2,
1407                                        Label* not_smi_label) {
1408  JumpIfBothSmi(value1, value2, NULL, not_smi_label);
1409}
1410
1411
1412void MacroAssembler::JumpIfBothNotSmi(Register value1,
1413                                      Register value2,
1414                                      Label* not_smi_label) {
1415  JumpIfEitherSmi(value1, value2, NULL, not_smi_label);
1416}
1417
1418
1419void MacroAssembler::ObjectTag(Register tagged_obj, Register obj) {
1420  STATIC_ASSERT(kHeapObjectTag == 1);
1421  if (emit_debug_code()) {
1422    Label ok;
1423    Tbz(obj, 0, &ok);
1424    Abort(kObjectTagged);
1425    Bind(&ok);
1426  }
1427  Orr(tagged_obj, obj, kHeapObjectTag);
1428}
1429
1430
1431void MacroAssembler::ObjectUntag(Register untagged_obj, Register obj) {
1432  STATIC_ASSERT(kHeapObjectTag == 1);
1433  if (emit_debug_code()) {
1434    Label ok;
1435    Tbnz(obj, 0, &ok);
1436    Abort(kObjectNotTagged);
1437    Bind(&ok);
1438  }
1439  Bic(untagged_obj, obj, kHeapObjectTag);
1440}
1441
1442
1443void MacroAssembler::IsObjectNameType(Register object,
1444                                      Register type,
1445                                      Label* fail) {
1446  CompareObjectType(object, type, type, LAST_NAME_TYPE);
1447  B(hi, fail);
1448}
1449
1450
1451void MacroAssembler::IsObjectJSObjectType(Register heap_object,
1452                                          Register map,
1453                                          Register scratch,
1454                                          Label* fail) {
1455  Ldr(map, FieldMemOperand(heap_object, HeapObject::kMapOffset));
1456  IsInstanceJSObjectType(map, scratch, fail);
1457}
1458
1459
1460void MacroAssembler::IsInstanceJSObjectType(Register map,
1461                                            Register scratch,
1462                                            Label* fail) {
1463  Ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
1464  // If cmp result is lt, the following ccmp will clear all flags.
1465  // Z == 0, N == V implies gt condition.
1466  Cmp(scratch, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
1467  Ccmp(scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE, NoFlag, ge);
1468
1469  // If we didn't get a valid label object just fall through and leave the
1470  // flags updated.
1471  if (fail != NULL) {
1472    B(gt, fail);
1473  }
1474}
1475
1476
1477void MacroAssembler::IsObjectJSStringType(Register object,
1478                                          Register type,
1479                                          Label* not_string,
1480                                          Label* string) {
1481  Ldr(type, FieldMemOperand(object, HeapObject::kMapOffset));
1482  Ldrb(type.W(), FieldMemOperand(type, Map::kInstanceTypeOffset));
1483
1484  STATIC_ASSERT(kStringTag == 0);
1485  DCHECK((string != NULL) || (not_string != NULL));
1486  if (string == NULL) {
1487    TestAndBranchIfAnySet(type.W(), kIsNotStringMask, not_string);
1488  } else if (not_string == NULL) {
1489    TestAndBranchIfAllClear(type.W(), kIsNotStringMask, string);
1490  } else {
1491    TestAndBranchIfAnySet(type.W(), kIsNotStringMask, not_string);
1492    B(string);
1493  }
1494}
1495
1496
1497void MacroAssembler::Push(Handle<Object> handle) {
1498  UseScratchRegisterScope temps(this);
1499  Register tmp = temps.AcquireX();
1500  Mov(tmp, Operand(handle));
1501  Push(tmp);
1502}
1503
1504
1505void MacroAssembler::Claim(uint64_t count, uint64_t unit_size) {
1506  uint64_t size = count * unit_size;
1507
1508  if (size == 0) {
1509    return;
1510  }
1511
1512  if (csp.Is(StackPointer())) {
1513    DCHECK(size % 16 == 0);
1514  } else {
1515    BumpSystemStackPointer(size);
1516  }
1517
1518  Sub(StackPointer(), StackPointer(), size);
1519}
1520
1521
1522void MacroAssembler::Claim(const Register& count, uint64_t unit_size) {
1523  if (unit_size == 0) return;
1524  DCHECK(base::bits::IsPowerOfTwo64(unit_size));
1525
1526  const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits);
1527  const Operand size(count, LSL, shift);
1528
1529  if (size.IsZero()) {
1530    return;
1531  }
1532
1533  if (!csp.Is(StackPointer())) {
1534    BumpSystemStackPointer(size);
1535  }
1536
1537  Sub(StackPointer(), StackPointer(), size);
1538}
1539
1540
1541void MacroAssembler::ClaimBySMI(const Register& count_smi, uint64_t unit_size) {
1542  DCHECK(unit_size == 0 || base::bits::IsPowerOfTwo64(unit_size));
1543  const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits) - kSmiShift;
1544  const Operand size(count_smi,
1545                     (shift >= 0) ? (LSL) : (LSR),
1546                     (shift >= 0) ? (shift) : (-shift));
1547
1548  if (size.IsZero()) {
1549    return;
1550  }
1551
1552  if (!csp.Is(StackPointer())) {
1553    BumpSystemStackPointer(size);
1554  }
1555
1556  Sub(StackPointer(), StackPointer(), size);
1557}
1558
1559
1560void MacroAssembler::Drop(uint64_t count, uint64_t unit_size) {
1561  uint64_t size = count * unit_size;
1562
1563  if (size == 0) {
1564    return;
1565  }
1566
1567  Add(StackPointer(), StackPointer(), size);
1568
1569  if (csp.Is(StackPointer())) {
1570    DCHECK(size % 16 == 0);
1571  } else if (emit_debug_code()) {
1572    // It is safe to leave csp where it is when unwinding the JavaScript stack,
1573    // but if we keep it matching StackPointer, the simulator can detect memory
1574    // accesses in the now-free part of the stack.
1575    SyncSystemStackPointer();
1576  }
1577}
1578
1579
1580void MacroAssembler::Drop(const Register& count, uint64_t unit_size) {
1581  if (unit_size == 0) return;
1582  DCHECK(base::bits::IsPowerOfTwo64(unit_size));
1583
1584  const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits);
1585  const Operand size(count, LSL, shift);
1586
1587  if (size.IsZero()) {
1588    return;
1589  }
1590
1591  Add(StackPointer(), StackPointer(), size);
1592
1593  if (!csp.Is(StackPointer()) && emit_debug_code()) {
1594    // It is safe to leave csp where it is when unwinding the JavaScript stack,
1595    // but if we keep it matching StackPointer, the simulator can detect memory
1596    // accesses in the now-free part of the stack.
1597    SyncSystemStackPointer();
1598  }
1599}
1600
1601
1602void MacroAssembler::DropBySMI(const Register& count_smi, uint64_t unit_size) {
1603  DCHECK(unit_size == 0 || base::bits::IsPowerOfTwo64(unit_size));
1604  const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits) - kSmiShift;
1605  const Operand size(count_smi,
1606                     (shift >= 0) ? (LSL) : (LSR),
1607                     (shift >= 0) ? (shift) : (-shift));
1608
1609  if (size.IsZero()) {
1610    return;
1611  }
1612
1613  Add(StackPointer(), StackPointer(), size);
1614
1615  if (!csp.Is(StackPointer()) && emit_debug_code()) {
1616    // It is safe to leave csp where it is when unwinding the JavaScript stack,
1617    // but if we keep it matching StackPointer, the simulator can detect memory
1618    // accesses in the now-free part of the stack.
1619    SyncSystemStackPointer();
1620  }
1621}
1622
1623
1624void MacroAssembler::CompareAndBranch(const Register& lhs,
1625                                      const Operand& rhs,
1626                                      Condition cond,
1627                                      Label* label) {
1628  if (rhs.IsImmediate() && (rhs.ImmediateValue() == 0) &&
1629      ((cond == eq) || (cond == ne))) {
1630    if (cond == eq) {
1631      Cbz(lhs, label);
1632    } else {
1633      Cbnz(lhs, label);
1634    }
1635  } else {
1636    Cmp(lhs, rhs);
1637    B(cond, label);
1638  }
1639}
1640
1641
1642void MacroAssembler::TestAndBranchIfAnySet(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    Tbnz(reg, MaskToBit(bit_pattern), label);
1649  } else {
1650    Tst(reg, bit_pattern);
1651    B(ne, label);
1652  }
1653}
1654
1655
1656void MacroAssembler::TestAndBranchIfAllClear(const Register& reg,
1657                                             const uint64_t bit_pattern,
1658                                             Label* label) {
1659  int bits = reg.SizeInBits();
1660  DCHECK(CountSetBits(bit_pattern, bits) > 0);
1661  if (CountSetBits(bit_pattern, bits) == 1) {
1662    Tbz(reg, MaskToBit(bit_pattern), label);
1663  } else {
1664    Tst(reg, bit_pattern);
1665    B(eq, label);
1666  }
1667}
1668
1669
1670void MacroAssembler::InlineData(uint64_t data) {
1671  DCHECK(is_uint16(data));
1672  InstructionAccurateScope scope(this, 1);
1673  movz(xzr, data);
1674}
1675
1676
1677void MacroAssembler::EnableInstrumentation() {
1678  InstructionAccurateScope scope(this, 1);
1679  movn(xzr, InstrumentStateEnable);
1680}
1681
1682
1683void MacroAssembler::DisableInstrumentation() {
1684  InstructionAccurateScope scope(this, 1);
1685  movn(xzr, InstrumentStateDisable);
1686}
1687
1688
1689void MacroAssembler::AnnotateInstrumentation(const char* marker_name) {
1690  DCHECK(strlen(marker_name) == 2);
1691
1692  // We allow only printable characters in the marker names. Unprintable
1693  // characters are reserved for controlling features of the instrumentation.
1694  DCHECK(isprint(marker_name[0]) && isprint(marker_name[1]));
1695
1696  InstructionAccurateScope scope(this, 1);
1697  movn(xzr, (marker_name[1] << 8) | marker_name[0]);
1698}
1699
1700} }  // namespace v8::internal
1701
1702#endif  // V8_ARM64_MACRO_ASSEMBLER_ARM64_INL_H_
1703