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