Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / v8 / src / arm64 / macro-assembler-arm64.cc
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 #include "src/v8.h"
6
7 #if V8_TARGET_ARCH_ARM64
8
9 #include "src/base/bits.h"
10 #include "src/base/division-by-constant.h"
11 #include "src/bootstrapper.h"
12 #include "src/codegen.h"
13 #include "src/cpu-profiler.h"
14 #include "src/debug.h"
15 #include "src/isolate-inl.h"
16 #include "src/runtime/runtime.h"
17
18 namespace v8 {
19 namespace internal {
20
21 // Define a fake double underscore to use with the ASM_UNIMPLEMENTED macros.
22 #define __
23
24
25 MacroAssembler::MacroAssembler(Isolate* arg_isolate,
26                                byte * buffer,
27                                unsigned buffer_size)
28     : Assembler(arg_isolate, buffer, buffer_size),
29       generating_stub_(false),
30 #if DEBUG
31       allow_macro_instructions_(true),
32 #endif
33       has_frame_(false),
34       use_real_aborts_(true),
35       sp_(jssp),
36       tmp_list_(DefaultTmpList()),
37       fptmp_list_(DefaultFPTmpList()) {
38   if (isolate() != NULL) {
39     code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
40                                   isolate());
41   }
42 }
43
44
45 CPURegList MacroAssembler::DefaultTmpList() {
46   return CPURegList(ip0, ip1);
47 }
48
49
50 CPURegList MacroAssembler::DefaultFPTmpList() {
51   return CPURegList(fp_scratch1, fp_scratch2);
52 }
53
54
55 void MacroAssembler::LogicalMacro(const Register& rd,
56                                   const Register& rn,
57                                   const Operand& operand,
58                                   LogicalOp op) {
59   UseScratchRegisterScope temps(this);
60
61   if (operand.NeedsRelocation(this)) {
62     Register temp = temps.AcquireX();
63     Ldr(temp, operand.immediate());
64     Logical(rd, rn, temp, op);
65
66   } else if (operand.IsImmediate()) {
67     int64_t immediate = operand.ImmediateValue();
68     unsigned reg_size = rd.SizeInBits();
69
70     // If the operation is NOT, invert the operation and immediate.
71     if ((op & NOT) == NOT) {
72       op = static_cast<LogicalOp>(op & ~NOT);
73       immediate = ~immediate;
74     }
75
76     // Ignore the top 32 bits of an immediate if we're moving to a W register.
77     if (rd.Is32Bits()) {
78       // Check that the top 32 bits are consistent.
79       DCHECK(((immediate >> kWRegSizeInBits) == 0) ||
80              ((immediate >> kWRegSizeInBits) == -1));
81       immediate &= kWRegMask;
82     }
83
84     DCHECK(rd.Is64Bits() || is_uint32(immediate));
85
86     // Special cases for all set or all clear immediates.
87     if (immediate == 0) {
88       switch (op) {
89         case AND:
90           Mov(rd, 0);
91           return;
92         case ORR:  // Fall through.
93         case EOR:
94           Mov(rd, rn);
95           return;
96         case ANDS:  // Fall through.
97         case BICS:
98           break;
99         default:
100           UNREACHABLE();
101       }
102     } else if ((rd.Is64Bits() && (immediate == -1L)) ||
103                (rd.Is32Bits() && (immediate == 0xffffffffL))) {
104       switch (op) {
105         case AND:
106           Mov(rd, rn);
107           return;
108         case ORR:
109           Mov(rd, immediate);
110           return;
111         case EOR:
112           Mvn(rd, rn);
113           return;
114         case ANDS:  // Fall through.
115         case BICS:
116           break;
117         default:
118           UNREACHABLE();
119       }
120     }
121
122     unsigned n, imm_s, imm_r;
123     if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) {
124       // Immediate can be encoded in the instruction.
125       LogicalImmediate(rd, rn, n, imm_s, imm_r, op);
126     } else {
127       // Immediate can't be encoded: synthesize using move immediate.
128       Register temp = temps.AcquireSameSizeAs(rn);
129       Operand imm_operand = MoveImmediateForShiftedOp(temp, immediate);
130       if (rd.Is(csp)) {
131         // If rd is the stack pointer we cannot use it as the destination
132         // register so we use the temp register as an intermediate again.
133         Logical(temp, rn, imm_operand, op);
134         Mov(csp, temp);
135         AssertStackConsistency();
136       } else {
137         Logical(rd, rn, imm_operand, op);
138       }
139     }
140
141   } else if (operand.IsExtendedRegister()) {
142     DCHECK(operand.reg().SizeInBits() <= rd.SizeInBits());
143     // Add/sub extended supports shift <= 4. We want to support exactly the
144     // same modes here.
145     DCHECK(operand.shift_amount() <= 4);
146     DCHECK(operand.reg().Is64Bits() ||
147            ((operand.extend() != UXTX) && (operand.extend() != SXTX)));
148     Register temp = temps.AcquireSameSizeAs(rn);
149     EmitExtendShift(temp, operand.reg(), operand.extend(),
150                     operand.shift_amount());
151     Logical(rd, rn, temp, op);
152
153   } else {
154     // The operand can be encoded in the instruction.
155     DCHECK(operand.IsShiftedRegister());
156     Logical(rd, rn, operand, op);
157   }
158 }
159
160
161 void MacroAssembler::Mov(const Register& rd, uint64_t imm) {
162   DCHECK(allow_macro_instructions_);
163   DCHECK(is_uint32(imm) || is_int32(imm) || rd.Is64Bits());
164   DCHECK(!rd.IsZero());
165
166   // TODO(all) extend to support more immediates.
167   //
168   // Immediates on Aarch64 can be produced using an initial value, and zero to
169   // three move keep operations.
170   //
171   // Initial values can be generated with:
172   //  1. 64-bit move zero (movz).
173   //  2. 32-bit move inverted (movn).
174   //  3. 64-bit move inverted.
175   //  4. 32-bit orr immediate.
176   //  5. 64-bit orr immediate.
177   // Move-keep may then be used to modify each of the 16-bit half-words.
178   //
179   // The code below supports all five initial value generators, and
180   // applying move-keep operations to move-zero and move-inverted initial
181   // values.
182
183   // Try to move the immediate in one instruction, and if that fails, switch to
184   // using multiple instructions.
185   if (!TryOneInstrMoveImmediate(rd, imm)) {
186     unsigned reg_size = rd.SizeInBits();
187
188     // Generic immediate case. Imm will be represented by
189     //   [imm3, imm2, imm1, imm0], where each imm is 16 bits.
190     // A move-zero or move-inverted is generated for the first non-zero or
191     // non-0xffff immX, and a move-keep for subsequent non-zero immX.
192
193     uint64_t ignored_halfword = 0;
194     bool invert_move = false;
195     // If the number of 0xffff halfwords is greater than the number of 0x0000
196     // halfwords, it's more efficient to use move-inverted.
197     if (CountClearHalfWords(~imm, reg_size) >
198         CountClearHalfWords(imm, reg_size)) {
199       ignored_halfword = 0xffffL;
200       invert_move = true;
201     }
202
203     // Mov instructions can't move immediate values into the stack pointer, so
204     // set up a temporary register, if needed.
205     UseScratchRegisterScope temps(this);
206     Register temp = rd.IsSP() ? temps.AcquireSameSizeAs(rd) : rd;
207
208     // Iterate through the halfwords. Use movn/movz for the first non-ignored
209     // halfword, and movk for subsequent halfwords.
210     DCHECK((reg_size % 16) == 0);
211     bool first_mov_done = false;
212     for (unsigned i = 0; i < (rd.SizeInBits() / 16); i++) {
213       uint64_t imm16 = (imm >> (16 * i)) & 0xffffL;
214       if (imm16 != ignored_halfword) {
215         if (!first_mov_done) {
216           if (invert_move) {
217             movn(temp, (~imm16) & 0xffffL, 16 * i);
218           } else {
219             movz(temp, imm16, 16 * i);
220           }
221           first_mov_done = true;
222         } else {
223           // Construct a wider constant.
224           movk(temp, imm16, 16 * i);
225         }
226       }
227     }
228     DCHECK(first_mov_done);
229
230     // Move the temporary if the original destination register was the stack
231     // pointer.
232     if (rd.IsSP()) {
233       mov(rd, temp);
234       AssertStackConsistency();
235     }
236   }
237 }
238
239
240 void MacroAssembler::Mov(const Register& rd,
241                          const Operand& operand,
242                          DiscardMoveMode discard_mode) {
243   DCHECK(allow_macro_instructions_);
244   DCHECK(!rd.IsZero());
245
246   // Provide a swap register for instructions that need to write into the
247   // system stack pointer (and can't do this inherently).
248   UseScratchRegisterScope temps(this);
249   Register dst = (rd.IsSP()) ? temps.AcquireSameSizeAs(rd) : rd;
250
251   if (operand.NeedsRelocation(this)) {
252     Ldr(dst, operand.immediate());
253
254   } else if (operand.IsImmediate()) {
255     // Call the macro assembler for generic immediates.
256     Mov(dst, operand.ImmediateValue());
257
258   } else if (operand.IsShiftedRegister() && (operand.shift_amount() != 0)) {
259     // Emit a shift instruction if moving a shifted register. This operation
260     // could also be achieved using an orr instruction (like orn used by Mvn),
261     // but using a shift instruction makes the disassembly clearer.
262     EmitShift(dst, operand.reg(), operand.shift(), operand.shift_amount());
263
264   } else if (operand.IsExtendedRegister()) {
265     // Emit an extend instruction if moving an extended register. This handles
266     // extend with post-shift operations, too.
267     EmitExtendShift(dst, operand.reg(), operand.extend(),
268                     operand.shift_amount());
269
270   } else {
271     // Otherwise, emit a register move only if the registers are distinct, or
272     // if they are not X registers.
273     //
274     // Note that mov(w0, w0) is not a no-op because it clears the top word of
275     // x0. A flag is provided (kDiscardForSameWReg) if a move between the same W
276     // registers is not required to clear the top word of the X register. In
277     // this case, the instruction is discarded.
278     //
279     // If csp is an operand, add #0 is emitted, otherwise, orr #0.
280     if (!rd.Is(operand.reg()) || (rd.Is32Bits() &&
281                                   (discard_mode == kDontDiscardForSameWReg))) {
282       Assembler::mov(rd, operand.reg());
283     }
284     // This case can handle writes into the system stack pointer directly.
285     dst = rd;
286   }
287
288   // Copy the result to the system stack pointer.
289   if (!dst.Is(rd)) {
290     DCHECK(rd.IsSP());
291     Assembler::mov(rd, dst);
292   }
293 }
294
295
296 void MacroAssembler::Mvn(const Register& rd, const Operand& operand) {
297   DCHECK(allow_macro_instructions_);
298
299   if (operand.NeedsRelocation(this)) {
300     Ldr(rd, operand.immediate());
301     mvn(rd, rd);
302
303   } else if (operand.IsImmediate()) {
304     // Call the macro assembler for generic immediates.
305     Mov(rd, ~operand.ImmediateValue());
306
307   } else if (operand.IsExtendedRegister()) {
308     // Emit two instructions for the extend case. This differs from Mov, as
309     // the extend and invert can't be achieved in one instruction.
310     EmitExtendShift(rd, operand.reg(), operand.extend(),
311                     operand.shift_amount());
312     mvn(rd, rd);
313
314   } else {
315     mvn(rd, operand);
316   }
317 }
318
319
320 unsigned MacroAssembler::CountClearHalfWords(uint64_t imm, unsigned reg_size) {
321   DCHECK((reg_size % 8) == 0);
322   int count = 0;
323   for (unsigned i = 0; i < (reg_size / 16); i++) {
324     if ((imm & 0xffff) == 0) {
325       count++;
326     }
327     imm >>= 16;
328   }
329   return count;
330 }
331
332
333 // The movz instruction can generate immediates containing an arbitrary 16-bit
334 // half-word, with remaining bits clear, eg. 0x00001234, 0x0000123400000000.
335 bool MacroAssembler::IsImmMovz(uint64_t imm, unsigned reg_size) {
336   DCHECK((reg_size == kXRegSizeInBits) || (reg_size == kWRegSizeInBits));
337   return CountClearHalfWords(imm, reg_size) >= ((reg_size / 16) - 1);
338 }
339
340
341 // The movn instruction can generate immediates containing an arbitrary 16-bit
342 // half-word, with remaining bits set, eg. 0xffff1234, 0xffff1234ffffffff.
343 bool MacroAssembler::IsImmMovn(uint64_t imm, unsigned reg_size) {
344   return IsImmMovz(~imm, reg_size);
345 }
346
347
348 void MacroAssembler::ConditionalCompareMacro(const Register& rn,
349                                              const Operand& operand,
350                                              StatusFlags nzcv,
351                                              Condition cond,
352                                              ConditionalCompareOp op) {
353   DCHECK((cond != al) && (cond != nv));
354   if (operand.NeedsRelocation(this)) {
355     UseScratchRegisterScope temps(this);
356     Register temp = temps.AcquireX();
357     Ldr(temp, operand.immediate());
358     ConditionalCompareMacro(rn, temp, nzcv, cond, op);
359
360   } else if ((operand.IsShiftedRegister() && (operand.shift_amount() == 0)) ||
361              (operand.IsImmediate() &&
362               IsImmConditionalCompare(operand.ImmediateValue()))) {
363     // The immediate can be encoded in the instruction, or the operand is an
364     // unshifted register: call the assembler.
365     ConditionalCompare(rn, operand, nzcv, cond, op);
366
367   } else {
368     // The operand isn't directly supported by the instruction: perform the
369     // operation on a temporary register.
370     UseScratchRegisterScope temps(this);
371     Register temp = temps.AcquireSameSizeAs(rn);
372     Mov(temp, operand);
373     ConditionalCompare(rn, temp, nzcv, cond, op);
374   }
375 }
376
377
378 void MacroAssembler::Csel(const Register& rd,
379                           const Register& rn,
380                           const Operand& operand,
381                           Condition cond) {
382   DCHECK(allow_macro_instructions_);
383   DCHECK(!rd.IsZero());
384   DCHECK((cond != al) && (cond != nv));
385   if (operand.IsImmediate()) {
386     // Immediate argument. Handle special cases of 0, 1 and -1 using zero
387     // register.
388     int64_t imm = operand.ImmediateValue();
389     Register zr = AppropriateZeroRegFor(rn);
390     if (imm == 0) {
391       csel(rd, rn, zr, cond);
392     } else if (imm == 1) {
393       csinc(rd, rn, zr, cond);
394     } else if (imm == -1) {
395       csinv(rd, rn, zr, cond);
396     } else {
397       UseScratchRegisterScope temps(this);
398       Register temp = temps.AcquireSameSizeAs(rn);
399       Mov(temp, imm);
400       csel(rd, rn, temp, cond);
401     }
402   } else if (operand.IsShiftedRegister() && (operand.shift_amount() == 0)) {
403     // Unshifted register argument.
404     csel(rd, rn, operand.reg(), cond);
405   } else {
406     // All other arguments.
407     UseScratchRegisterScope temps(this);
408     Register temp = temps.AcquireSameSizeAs(rn);
409     Mov(temp, operand);
410     csel(rd, rn, temp, cond);
411   }
412 }
413
414
415 bool MacroAssembler::TryOneInstrMoveImmediate(const Register& dst,
416                                               int64_t imm) {
417   unsigned n, imm_s, imm_r;
418   int reg_size = dst.SizeInBits();
419   if (IsImmMovz(imm, reg_size) && !dst.IsSP()) {
420     // Immediate can be represented in a move zero instruction. Movz can't write
421     // to the stack pointer.
422     movz(dst, imm);
423     return true;
424   } else if (IsImmMovn(imm, reg_size) && !dst.IsSP()) {
425     // Immediate can be represented in a move not instruction. Movn can't write
426     // to the stack pointer.
427     movn(dst, dst.Is64Bits() ? ~imm : (~imm & kWRegMask));
428     return true;
429   } else if (IsImmLogical(imm, reg_size, &n, &imm_s, &imm_r)) {
430     // Immediate can be represented in a logical orr instruction.
431     LogicalImmediate(dst, AppropriateZeroRegFor(dst), n, imm_s, imm_r, ORR);
432     return true;
433   }
434   return false;
435 }
436
437
438 Operand MacroAssembler::MoveImmediateForShiftedOp(const Register& dst,
439                                                   int64_t imm) {
440   int reg_size = dst.SizeInBits();
441
442   // Encode the immediate in a single move instruction, if possible.
443   if (TryOneInstrMoveImmediate(dst, imm)) {
444     // The move was successful; nothing to do here.
445   } else {
446     // Pre-shift the immediate to the least-significant bits of the register.
447     int shift_low = CountTrailingZeros(imm, reg_size);
448     int64_t imm_low = imm >> shift_low;
449
450     // Pre-shift the immediate to the most-significant bits of the register. We
451     // insert set bits in the least-significant bits, as this creates a
452     // different immediate that may be encodable using movn or orr-immediate.
453     // If this new immediate is encodable, the set bits will be eliminated by
454     // the post shift on the following instruction.
455     int shift_high = CountLeadingZeros(imm, reg_size);
456     int64_t imm_high = (imm << shift_high) | ((1 << shift_high) - 1);
457
458     if (TryOneInstrMoveImmediate(dst, imm_low)) {
459       // The new immediate has been moved into the destination's low bits:
460       // return a new leftward-shifting operand.
461       return Operand(dst, LSL, shift_low);
462     } else if (TryOneInstrMoveImmediate(dst, imm_high)) {
463       // The new immediate has been moved into the destination's high bits:
464       // return a new rightward-shifting operand.
465       return Operand(dst, LSR, shift_high);
466     } else {
467       // Use the generic move operation to set up the immediate.
468       Mov(dst, imm);
469     }
470   }
471   return Operand(dst);
472 }
473
474
475 void MacroAssembler::AddSubMacro(const Register& rd,
476                                  const Register& rn,
477                                  const Operand& operand,
478                                  FlagsUpdate S,
479                                  AddSubOp op) {
480   if (operand.IsZero() && rd.Is(rn) && rd.Is64Bits() && rn.Is64Bits() &&
481       !operand.NeedsRelocation(this) && (S == LeaveFlags)) {
482     // The instruction would be a nop. Avoid generating useless code.
483     return;
484   }
485
486   if (operand.NeedsRelocation(this)) {
487     UseScratchRegisterScope temps(this);
488     Register temp = temps.AcquireX();
489     Ldr(temp, operand.immediate());
490     AddSubMacro(rd, rn, temp, S, op);
491   } else if ((operand.IsImmediate() &&
492               !IsImmAddSub(operand.ImmediateValue()))      ||
493              (rn.IsZero() && !operand.IsShiftedRegister()) ||
494              (operand.IsShiftedRegister() && (operand.shift() == ROR))) {
495     UseScratchRegisterScope temps(this);
496     Register temp = temps.AcquireSameSizeAs(rn);
497     if (operand.IsImmediate()) {
498       Operand imm_operand =
499           MoveImmediateForShiftedOp(temp, operand.ImmediateValue());
500       AddSub(rd, rn, imm_operand, S, op);
501     } else {
502       Mov(temp, operand);
503       AddSub(rd, rn, temp, S, op);
504     }
505   } else {
506     AddSub(rd, rn, operand, S, op);
507   }
508 }
509
510
511 void MacroAssembler::AddSubWithCarryMacro(const Register& rd,
512                                           const Register& rn,
513                                           const Operand& operand,
514                                           FlagsUpdate S,
515                                           AddSubWithCarryOp op) {
516   DCHECK(rd.SizeInBits() == rn.SizeInBits());
517   UseScratchRegisterScope temps(this);
518
519   if (operand.NeedsRelocation(this)) {
520     Register temp = temps.AcquireX();
521     Ldr(temp, operand.immediate());
522     AddSubWithCarryMacro(rd, rn, temp, S, op);
523
524   } else if (operand.IsImmediate() ||
525              (operand.IsShiftedRegister() && (operand.shift() == ROR))) {
526     // Add/sub with carry (immediate or ROR shifted register.)
527     Register temp = temps.AcquireSameSizeAs(rn);
528     Mov(temp, operand);
529     AddSubWithCarry(rd, rn, temp, S, op);
530
531   } else if (operand.IsShiftedRegister() && (operand.shift_amount() != 0)) {
532     // Add/sub with carry (shifted register).
533     DCHECK(operand.reg().SizeInBits() == rd.SizeInBits());
534     DCHECK(operand.shift() != ROR);
535     DCHECK(is_uintn(operand.shift_amount(),
536           rd.SizeInBits() == kXRegSizeInBits ? kXRegSizeInBitsLog2
537                                              : kWRegSizeInBitsLog2));
538     Register temp = temps.AcquireSameSizeAs(rn);
539     EmitShift(temp, operand.reg(), operand.shift(), operand.shift_amount());
540     AddSubWithCarry(rd, rn, temp, S, op);
541
542   } else if (operand.IsExtendedRegister()) {
543     // Add/sub with carry (extended register).
544     DCHECK(operand.reg().SizeInBits() <= rd.SizeInBits());
545     // Add/sub extended supports a shift <= 4. We want to support exactly the
546     // same modes.
547     DCHECK(operand.shift_amount() <= 4);
548     DCHECK(operand.reg().Is64Bits() ||
549            ((operand.extend() != UXTX) && (operand.extend() != SXTX)));
550     Register temp = temps.AcquireSameSizeAs(rn);
551     EmitExtendShift(temp, operand.reg(), operand.extend(),
552                     operand.shift_amount());
553     AddSubWithCarry(rd, rn, temp, S, op);
554
555   } else {
556     // The addressing mode is directly supported by the instruction.
557     AddSubWithCarry(rd, rn, operand, S, op);
558   }
559 }
560
561
562 void MacroAssembler::LoadStoreMacro(const CPURegister& rt,
563                                     const MemOperand& addr,
564                                     LoadStoreOp op) {
565   int64_t offset = addr.offset();
566   LSDataSize size = CalcLSDataSize(op);
567
568   // Check if an immediate offset fits in the immediate field of the
569   // appropriate instruction. If not, emit two instructions to perform
570   // the operation.
571   if (addr.IsImmediateOffset() && !IsImmLSScaled(offset, size) &&
572       !IsImmLSUnscaled(offset)) {
573     // Immediate offset that can't be encoded using unsigned or unscaled
574     // addressing modes.
575     UseScratchRegisterScope temps(this);
576     Register temp = temps.AcquireSameSizeAs(addr.base());
577     Mov(temp, addr.offset());
578     LoadStore(rt, MemOperand(addr.base(), temp), op);
579   } else if (addr.IsPostIndex() && !IsImmLSUnscaled(offset)) {
580     // Post-index beyond unscaled addressing range.
581     LoadStore(rt, MemOperand(addr.base()), op);
582     add(addr.base(), addr.base(), offset);
583   } else if (addr.IsPreIndex() && !IsImmLSUnscaled(offset)) {
584     // Pre-index beyond unscaled addressing range.
585     add(addr.base(), addr.base(), offset);
586     LoadStore(rt, MemOperand(addr.base()), op);
587   } else {
588     // Encodable in one load/store instruction.
589     LoadStore(rt, addr, op);
590   }
591 }
592
593 void MacroAssembler::LoadStorePairMacro(const CPURegister& rt,
594                                         const CPURegister& rt2,
595                                         const MemOperand& addr,
596                                         LoadStorePairOp op) {
597   // TODO(all): Should we support register offset for load-store-pair?
598   DCHECK(!addr.IsRegisterOffset());
599
600   int64_t offset = addr.offset();
601   LSDataSize size = CalcLSPairDataSize(op);
602
603   // Check if the offset fits in the immediate field of the appropriate
604   // instruction. If not, emit two instructions to perform the operation.
605   if (IsImmLSPair(offset, size)) {
606     // Encodable in one load/store pair instruction.
607     LoadStorePair(rt, rt2, addr, op);
608   } else {
609     Register base = addr.base();
610     if (addr.IsImmediateOffset()) {
611       UseScratchRegisterScope temps(this);
612       Register temp = temps.AcquireSameSizeAs(base);
613       Add(temp, base, offset);
614       LoadStorePair(rt, rt2, MemOperand(temp), op);
615     } else if (addr.IsPostIndex()) {
616       LoadStorePair(rt, rt2, MemOperand(base), op);
617       Add(base, base, offset);
618     } else {
619       DCHECK(addr.IsPreIndex());
620       Add(base, base, offset);
621       LoadStorePair(rt, rt2, MemOperand(base), op);
622     }
623   }
624 }
625
626
627 void MacroAssembler::Load(const Register& rt,
628                           const MemOperand& addr,
629                           Representation r) {
630   DCHECK(!r.IsDouble());
631
632   if (r.IsInteger8()) {
633     Ldrsb(rt, addr);
634   } else if (r.IsUInteger8()) {
635     Ldrb(rt, addr);
636   } else if (r.IsInteger16()) {
637     Ldrsh(rt, addr);
638   } else if (r.IsUInteger16()) {
639     Ldrh(rt, addr);
640   } else if (r.IsInteger32()) {
641     Ldr(rt.W(), addr);
642   } else {
643     DCHECK(rt.Is64Bits());
644     Ldr(rt, addr);
645   }
646 }
647
648
649 void MacroAssembler::Store(const Register& rt,
650                            const MemOperand& addr,
651                            Representation r) {
652   DCHECK(!r.IsDouble());
653
654   if (r.IsInteger8() || r.IsUInteger8()) {
655     Strb(rt, addr);
656   } else if (r.IsInteger16() || r.IsUInteger16()) {
657     Strh(rt, addr);
658   } else if (r.IsInteger32()) {
659     Str(rt.W(), addr);
660   } else {
661     DCHECK(rt.Is64Bits());
662     if (r.IsHeapObject()) {
663       AssertNotSmi(rt);
664     } else if (r.IsSmi()) {
665       AssertSmi(rt);
666     }
667     Str(rt, addr);
668   }
669 }
670
671
672 bool MacroAssembler::NeedExtraInstructionsOrRegisterBranch(
673     Label *label, ImmBranchType b_type) {
674   bool need_longer_range = false;
675   // There are two situations in which we care about the offset being out of
676   // range:
677   //  - The label is bound but too far away.
678   //  - The label is not bound but linked, and the previous branch
679   //    instruction in the chain is too far away.
680   if (label->is_bound() || label->is_linked()) {
681     need_longer_range =
682       !Instruction::IsValidImmPCOffset(b_type, label->pos() - pc_offset());
683   }
684   if (!need_longer_range && !label->is_bound()) {
685     int max_reachable_pc = pc_offset() + Instruction::ImmBranchRange(b_type);
686     unresolved_branches_.insert(
687         std::pair<int, FarBranchInfo>(max_reachable_pc,
688                                       FarBranchInfo(pc_offset(), label)));
689     // Also maintain the next pool check.
690     next_veneer_pool_check_ =
691       Min(next_veneer_pool_check_,
692           max_reachable_pc - kVeneerDistanceCheckMargin);
693   }
694   return need_longer_range;
695 }
696
697
698 void MacroAssembler::Adr(const Register& rd, Label* label, AdrHint hint) {
699   DCHECK(allow_macro_instructions_);
700   DCHECK(!rd.IsZero());
701
702   if (hint == kAdrNear) {
703     adr(rd, label);
704     return;
705   }
706
707   DCHECK(hint == kAdrFar);
708   if (label->is_bound()) {
709     int label_offset = label->pos() - pc_offset();
710     if (Instruction::IsValidPCRelOffset(label_offset)) {
711       adr(rd, label);
712     } else {
713       DCHECK(label_offset <= 0);
714       int min_adr_offset = -(1 << (Instruction::ImmPCRelRangeBitwidth - 1));
715       adr(rd, min_adr_offset);
716       Add(rd, rd, label_offset - min_adr_offset);
717     }
718   } else {
719     UseScratchRegisterScope temps(this);
720     Register scratch = temps.AcquireX();
721
722     InstructionAccurateScope scope(
723         this, PatchingAssembler::kAdrFarPatchableNInstrs);
724     adr(rd, label);
725     for (int i = 0; i < PatchingAssembler::kAdrFarPatchableNNops; ++i) {
726       nop(ADR_FAR_NOP);
727     }
728     movz(scratch, 0);
729   }
730 }
731
732
733 void MacroAssembler::B(Label* label, BranchType type, Register reg, int bit) {
734   DCHECK((reg.Is(NoReg) || type >= kBranchTypeFirstUsingReg) &&
735          (bit == -1 || type >= kBranchTypeFirstUsingBit));
736   if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) {
737     B(static_cast<Condition>(type), label);
738   } else {
739     switch (type) {
740       case always:        B(label);              break;
741       case never:         break;
742       case reg_zero:      Cbz(reg, label);       break;
743       case reg_not_zero:  Cbnz(reg, label);      break;
744       case reg_bit_clear: Tbz(reg, bit, label);  break;
745       case reg_bit_set:   Tbnz(reg, bit, label); break;
746       default:
747         UNREACHABLE();
748     }
749   }
750 }
751
752
753 void MacroAssembler::B(Label* label, Condition cond) {
754   DCHECK(allow_macro_instructions_);
755   DCHECK((cond != al) && (cond != nv));
756
757   Label done;
758   bool need_extra_instructions =
759     NeedExtraInstructionsOrRegisterBranch(label, CondBranchType);
760
761   if (need_extra_instructions) {
762     b(&done, NegateCondition(cond));
763     B(label);
764   } else {
765     b(label, cond);
766   }
767   bind(&done);
768 }
769
770
771 void MacroAssembler::Tbnz(const Register& rt, unsigned bit_pos, Label* label) {
772   DCHECK(allow_macro_instructions_);
773
774   Label done;
775   bool need_extra_instructions =
776     NeedExtraInstructionsOrRegisterBranch(label, TestBranchType);
777
778   if (need_extra_instructions) {
779     tbz(rt, bit_pos, &done);
780     B(label);
781   } else {
782     tbnz(rt, bit_pos, label);
783   }
784   bind(&done);
785 }
786
787
788 void MacroAssembler::Tbz(const Register& rt, unsigned bit_pos, Label* label) {
789   DCHECK(allow_macro_instructions_);
790
791   Label done;
792   bool need_extra_instructions =
793     NeedExtraInstructionsOrRegisterBranch(label, TestBranchType);
794
795   if (need_extra_instructions) {
796     tbnz(rt, bit_pos, &done);
797     B(label);
798   } else {
799     tbz(rt, bit_pos, label);
800   }
801   bind(&done);
802 }
803
804
805 void MacroAssembler::Cbnz(const Register& rt, Label* label) {
806   DCHECK(allow_macro_instructions_);
807
808   Label done;
809   bool need_extra_instructions =
810     NeedExtraInstructionsOrRegisterBranch(label, CompareBranchType);
811
812   if (need_extra_instructions) {
813     cbz(rt, &done);
814     B(label);
815   } else {
816     cbnz(rt, label);
817   }
818   bind(&done);
819 }
820
821
822 void MacroAssembler::Cbz(const Register& rt, Label* label) {
823   DCHECK(allow_macro_instructions_);
824
825   Label done;
826   bool need_extra_instructions =
827     NeedExtraInstructionsOrRegisterBranch(label, CompareBranchType);
828
829   if (need_extra_instructions) {
830     cbnz(rt, &done);
831     B(label);
832   } else {
833     cbz(rt, label);
834   }
835   bind(&done);
836 }
837
838
839 // Pseudo-instructions.
840
841
842 void MacroAssembler::Abs(const Register& rd, const Register& rm,
843                          Label* is_not_representable,
844                          Label* is_representable) {
845   DCHECK(allow_macro_instructions_);
846   DCHECK(AreSameSizeAndType(rd, rm));
847
848   Cmp(rm, 1);
849   Cneg(rd, rm, lt);
850
851   // If the comparison sets the v flag, the input was the smallest value
852   // representable by rm, and the mathematical result of abs(rm) is not
853   // representable using two's complement.
854   if ((is_not_representable != NULL) && (is_representable != NULL)) {
855     B(is_not_representable, vs);
856     B(is_representable);
857   } else if (is_not_representable != NULL) {
858     B(is_not_representable, vs);
859   } else if (is_representable != NULL) {
860     B(is_representable, vc);
861   }
862 }
863
864
865 // Abstracted stack operations.
866
867
868 void MacroAssembler::Push(const CPURegister& src0, const CPURegister& src1,
869                           const CPURegister& src2, const CPURegister& src3) {
870   DCHECK(AreSameSizeAndType(src0, src1, src2, src3));
871
872   int count = 1 + src1.IsValid() + src2.IsValid() + src3.IsValid();
873   int size = src0.SizeInBytes();
874
875   PushPreamble(count, size);
876   PushHelper(count, size, src0, src1, src2, src3);
877 }
878
879
880 void MacroAssembler::Push(const CPURegister& src0, const CPURegister& src1,
881                           const CPURegister& src2, const CPURegister& src3,
882                           const CPURegister& src4, const CPURegister& src5,
883                           const CPURegister& src6, const CPURegister& src7) {
884   DCHECK(AreSameSizeAndType(src0, src1, src2, src3, src4, src5, src6, src7));
885
886   int count = 5 + src5.IsValid() + src6.IsValid() + src6.IsValid();
887   int size = src0.SizeInBytes();
888
889   PushPreamble(count, size);
890   PushHelper(4, size, src0, src1, src2, src3);
891   PushHelper(count - 4, size, src4, src5, src6, src7);
892 }
893
894
895 void MacroAssembler::Pop(const CPURegister& dst0, const CPURegister& dst1,
896                          const CPURegister& dst2, const CPURegister& dst3) {
897   // It is not valid to pop into the same register more than once in one
898   // instruction, not even into the zero register.
899   DCHECK(!AreAliased(dst0, dst1, dst2, dst3));
900   DCHECK(AreSameSizeAndType(dst0, dst1, dst2, dst3));
901   DCHECK(dst0.IsValid());
902
903   int count = 1 + dst1.IsValid() + dst2.IsValid() + dst3.IsValid();
904   int size = dst0.SizeInBytes();
905
906   PopHelper(count, size, dst0, dst1, dst2, dst3);
907   PopPostamble(count, size);
908 }
909
910
911 void MacroAssembler::Push(const Register& src0, const FPRegister& src1) {
912   int size = src0.SizeInBytes() + src1.SizeInBytes();
913
914   PushPreamble(size);
915   // Reserve room for src0 and push src1.
916   str(src1, MemOperand(StackPointer(), -size, PreIndex));
917   // Fill the gap with src0.
918   str(src0, MemOperand(StackPointer(), src1.SizeInBytes()));
919 }
920
921
922 void MacroAssembler::PushPopQueue::PushQueued(
923     PreambleDirective preamble_directive) {
924   if (queued_.empty()) return;
925
926   if (preamble_directive == WITH_PREAMBLE) {
927     masm_->PushPreamble(size_);
928   }
929
930   int count = queued_.size();
931   int index = 0;
932   while (index < count) {
933     // PushHelper can only handle registers with the same size and type, and it
934     // can handle only four at a time. Batch them up accordingly.
935     CPURegister batch[4] = {NoReg, NoReg, NoReg, NoReg};
936     int batch_index = 0;
937     do {
938       batch[batch_index++] = queued_[index++];
939     } while ((batch_index < 4) && (index < count) &&
940              batch[0].IsSameSizeAndType(queued_[index]));
941
942     masm_->PushHelper(batch_index, batch[0].SizeInBytes(),
943                       batch[0], batch[1], batch[2], batch[3]);
944   }
945
946   queued_.clear();
947 }
948
949
950 void MacroAssembler::PushPopQueue::PopQueued() {
951   if (queued_.empty()) return;
952
953   int count = queued_.size();
954   int index = 0;
955   while (index < count) {
956     // PopHelper can only handle registers with the same size and type, and it
957     // can handle only four at a time. Batch them up accordingly.
958     CPURegister batch[4] = {NoReg, NoReg, NoReg, NoReg};
959     int batch_index = 0;
960     do {
961       batch[batch_index++] = queued_[index++];
962     } while ((batch_index < 4) && (index < count) &&
963              batch[0].IsSameSizeAndType(queued_[index]));
964
965     masm_->PopHelper(batch_index, batch[0].SizeInBytes(),
966                      batch[0], batch[1], batch[2], batch[3]);
967   }
968
969   masm_->PopPostamble(size_);
970   queued_.clear();
971 }
972
973
974 void MacroAssembler::PushCPURegList(CPURegList registers) {
975   int size = registers.RegisterSizeInBytes();
976
977   PushPreamble(registers.Count(), size);
978   // Push up to four registers at a time because if the current stack pointer is
979   // csp and reg_size is 32, registers must be pushed in blocks of four in order
980   // to maintain the 16-byte alignment for csp.
981   while (!registers.IsEmpty()) {
982     int count_before = registers.Count();
983     const CPURegister& src0 = registers.PopHighestIndex();
984     const CPURegister& src1 = registers.PopHighestIndex();
985     const CPURegister& src2 = registers.PopHighestIndex();
986     const CPURegister& src3 = registers.PopHighestIndex();
987     int count = count_before - registers.Count();
988     PushHelper(count, size, src0, src1, src2, src3);
989   }
990 }
991
992
993 void MacroAssembler::PopCPURegList(CPURegList registers) {
994   int size = registers.RegisterSizeInBytes();
995
996   // Pop up to four registers at a time because if the current stack pointer is
997   // csp and reg_size is 32, registers must be pushed in blocks of four in
998   // order to maintain the 16-byte alignment for csp.
999   while (!registers.IsEmpty()) {
1000     int count_before = registers.Count();
1001     const CPURegister& dst0 = registers.PopLowestIndex();
1002     const CPURegister& dst1 = registers.PopLowestIndex();
1003     const CPURegister& dst2 = registers.PopLowestIndex();
1004     const CPURegister& dst3 = registers.PopLowestIndex();
1005     int count = count_before - registers.Count();
1006     PopHelper(count, size, dst0, dst1, dst2, dst3);
1007   }
1008   PopPostamble(registers.Count(), size);
1009 }
1010
1011
1012 void MacroAssembler::PushMultipleTimes(CPURegister src, int count) {
1013   int size = src.SizeInBytes();
1014
1015   PushPreamble(count, size);
1016
1017   if (FLAG_optimize_for_size && count > 8) {
1018     UseScratchRegisterScope temps(this);
1019     Register temp = temps.AcquireX();
1020
1021     Label loop;
1022     __ Mov(temp, count / 2);
1023     __ Bind(&loop);
1024     PushHelper(2, size, src, src, NoReg, NoReg);
1025     __ Subs(temp, temp, 1);
1026     __ B(ne, &loop);
1027
1028     count %= 2;
1029   }
1030
1031   // Push up to four registers at a time if possible because if the current
1032   // stack pointer is csp and the register size is 32, registers must be pushed
1033   // in blocks of four in order to maintain the 16-byte alignment for csp.
1034   while (count >= 4) {
1035     PushHelper(4, size, src, src, src, src);
1036     count -= 4;
1037   }
1038   if (count >= 2) {
1039     PushHelper(2, size, src, src, NoReg, NoReg);
1040     count -= 2;
1041   }
1042   if (count == 1) {
1043     PushHelper(1, size, src, NoReg, NoReg, NoReg);
1044     count -= 1;
1045   }
1046   DCHECK(count == 0);
1047 }
1048
1049
1050 void MacroAssembler::PushMultipleTimes(CPURegister src, Register count) {
1051   PushPreamble(Operand(count, UXTW, WhichPowerOf2(src.SizeInBytes())));
1052
1053   UseScratchRegisterScope temps(this);
1054   Register temp = temps.AcquireSameSizeAs(count);
1055
1056   if (FLAG_optimize_for_size) {
1057     Label loop, done;
1058
1059     Subs(temp, count, 1);
1060     B(mi, &done);
1061
1062     // Push all registers individually, to save code size.
1063     Bind(&loop);
1064     Subs(temp, temp, 1);
1065     PushHelper(1, src.SizeInBytes(), src, NoReg, NoReg, NoReg);
1066     B(pl, &loop);
1067
1068     Bind(&done);
1069   } else {
1070     Label loop, leftover2, leftover1, done;
1071
1072     Subs(temp, count, 4);
1073     B(mi, &leftover2);
1074
1075     // Push groups of four first.
1076     Bind(&loop);
1077     Subs(temp, temp, 4);
1078     PushHelper(4, src.SizeInBytes(), src, src, src, src);
1079     B(pl, &loop);
1080
1081     // Push groups of two.
1082     Bind(&leftover2);
1083     Tbz(count, 1, &leftover1);
1084     PushHelper(2, src.SizeInBytes(), src, src, NoReg, NoReg);
1085
1086     // Push the last one (if required).
1087     Bind(&leftover1);
1088     Tbz(count, 0, &done);
1089     PushHelper(1, src.SizeInBytes(), src, NoReg, NoReg, NoReg);
1090
1091     Bind(&done);
1092   }
1093 }
1094
1095
1096 void MacroAssembler::PushHelper(int count, int size,
1097                                 const CPURegister& src0,
1098                                 const CPURegister& src1,
1099                                 const CPURegister& src2,
1100                                 const CPURegister& src3) {
1101   // Ensure that we don't unintentially modify scratch or debug registers.
1102   InstructionAccurateScope scope(this);
1103
1104   DCHECK(AreSameSizeAndType(src0, src1, src2, src3));
1105   DCHECK(size == src0.SizeInBytes());
1106
1107   // When pushing multiple registers, the store order is chosen such that
1108   // Push(a, b) is equivalent to Push(a) followed by Push(b).
1109   switch (count) {
1110     case 1:
1111       DCHECK(src1.IsNone() && src2.IsNone() && src3.IsNone());
1112       str(src0, MemOperand(StackPointer(), -1 * size, PreIndex));
1113       break;
1114     case 2:
1115       DCHECK(src2.IsNone() && src3.IsNone());
1116       stp(src1, src0, MemOperand(StackPointer(), -2 * size, PreIndex));
1117       break;
1118     case 3:
1119       DCHECK(src3.IsNone());
1120       stp(src2, src1, MemOperand(StackPointer(), -3 * size, PreIndex));
1121       str(src0, MemOperand(StackPointer(), 2 * size));
1122       break;
1123     case 4:
1124       // Skip over 4 * size, then fill in the gap. This allows four W registers
1125       // to be pushed using csp, whilst maintaining 16-byte alignment for csp
1126       // at all times.
1127       stp(src3, src2, MemOperand(StackPointer(), -4 * size, PreIndex));
1128       stp(src1, src0, MemOperand(StackPointer(), 2 * size));
1129       break;
1130     default:
1131       UNREACHABLE();
1132   }
1133 }
1134
1135
1136 void MacroAssembler::PopHelper(int count, int size,
1137                                const CPURegister& dst0,
1138                                const CPURegister& dst1,
1139                                const CPURegister& dst2,
1140                                const CPURegister& dst3) {
1141   // Ensure that we don't unintentially modify scratch or debug registers.
1142   InstructionAccurateScope scope(this);
1143
1144   DCHECK(AreSameSizeAndType(dst0, dst1, dst2, dst3));
1145   DCHECK(size == dst0.SizeInBytes());
1146
1147   // When popping multiple registers, the load order is chosen such that
1148   // Pop(a, b) is equivalent to Pop(a) followed by Pop(b).
1149   switch (count) {
1150     case 1:
1151       DCHECK(dst1.IsNone() && dst2.IsNone() && dst3.IsNone());
1152       ldr(dst0, MemOperand(StackPointer(), 1 * size, PostIndex));
1153       break;
1154     case 2:
1155       DCHECK(dst2.IsNone() && dst3.IsNone());
1156       ldp(dst0, dst1, MemOperand(StackPointer(), 2 * size, PostIndex));
1157       break;
1158     case 3:
1159       DCHECK(dst3.IsNone());
1160       ldr(dst2, MemOperand(StackPointer(), 2 * size));
1161       ldp(dst0, dst1, MemOperand(StackPointer(), 3 * size, PostIndex));
1162       break;
1163     case 4:
1164       // Load the higher addresses first, then load the lower addresses and
1165       // skip the whole block in the second instruction. This allows four W
1166       // registers to be popped using csp, whilst maintaining 16-byte alignment
1167       // for csp at all times.
1168       ldp(dst2, dst3, MemOperand(StackPointer(), 2 * size));
1169       ldp(dst0, dst1, MemOperand(StackPointer(), 4 * size, PostIndex));
1170       break;
1171     default:
1172       UNREACHABLE();
1173   }
1174 }
1175
1176
1177 void MacroAssembler::PushPreamble(Operand total_size) {
1178   if (csp.Is(StackPointer())) {
1179     // If the current stack pointer is csp, then it must be aligned to 16 bytes
1180     // on entry and the total size of the specified registers must also be a
1181     // multiple of 16 bytes.
1182     if (total_size.IsImmediate()) {
1183       DCHECK((total_size.ImmediateValue() % 16) == 0);
1184     }
1185
1186     // Don't check access size for non-immediate sizes. It's difficult to do
1187     // well, and it will be caught by hardware (or the simulator) anyway.
1188   } else {
1189     // Even if the current stack pointer is not the system stack pointer (csp),
1190     // the system stack pointer will still be modified in order to comply with
1191     // ABI rules about accessing memory below the system stack pointer.
1192     BumpSystemStackPointer(total_size);
1193   }
1194 }
1195
1196
1197 void MacroAssembler::PopPostamble(Operand total_size) {
1198   if (csp.Is(StackPointer())) {
1199     // If the current stack pointer is csp, then it must be aligned to 16 bytes
1200     // on entry and the total size of the specified registers must also be a
1201     // multiple of 16 bytes.
1202     if (total_size.IsImmediate()) {
1203       DCHECK((total_size.ImmediateValue() % 16) == 0);
1204     }
1205
1206     // Don't check access size for non-immediate sizes. It's difficult to do
1207     // well, and it will be caught by hardware (or the simulator) anyway.
1208   } else if (emit_debug_code()) {
1209     // It is safe to leave csp where it is when unwinding the JavaScript stack,
1210     // but if we keep it matching StackPointer, the simulator can detect memory
1211     // accesses in the now-free part of the stack.
1212     SyncSystemStackPointer();
1213   }
1214 }
1215
1216
1217 void MacroAssembler::Poke(const CPURegister& src, const Operand& offset) {
1218   if (offset.IsImmediate()) {
1219     DCHECK(offset.ImmediateValue() >= 0);
1220   } else if (emit_debug_code()) {
1221     Cmp(xzr, offset);
1222     Check(le, kStackAccessBelowStackPointer);
1223   }
1224
1225   Str(src, MemOperand(StackPointer(), offset));
1226 }
1227
1228
1229 void MacroAssembler::Peek(const CPURegister& dst, const Operand& offset) {
1230   if (offset.IsImmediate()) {
1231     DCHECK(offset.ImmediateValue() >= 0);
1232   } else if (emit_debug_code()) {
1233     Cmp(xzr, offset);
1234     Check(le, kStackAccessBelowStackPointer);
1235   }
1236
1237   Ldr(dst, MemOperand(StackPointer(), offset));
1238 }
1239
1240
1241 void MacroAssembler::PokePair(const CPURegister& src1,
1242                               const CPURegister& src2,
1243                               int offset) {
1244   DCHECK(AreSameSizeAndType(src1, src2));
1245   DCHECK((offset >= 0) && ((offset % src1.SizeInBytes()) == 0));
1246   Stp(src1, src2, MemOperand(StackPointer(), offset));
1247 }
1248
1249
1250 void MacroAssembler::PeekPair(const CPURegister& dst1,
1251                               const CPURegister& dst2,
1252                               int offset) {
1253   DCHECK(AreSameSizeAndType(dst1, dst2));
1254   DCHECK((offset >= 0) && ((offset % dst1.SizeInBytes()) == 0));
1255   Ldp(dst1, dst2, MemOperand(StackPointer(), offset));
1256 }
1257
1258
1259 void MacroAssembler::PushCalleeSavedRegisters() {
1260   // Ensure that the macro-assembler doesn't use any scratch registers.
1261   InstructionAccurateScope scope(this);
1262
1263   // This method must not be called unless the current stack pointer is the
1264   // system stack pointer (csp).
1265   DCHECK(csp.Is(StackPointer()));
1266
1267   MemOperand tos(csp, -2 * kXRegSize, PreIndex);
1268
1269   stp(d14, d15, tos);
1270   stp(d12, d13, tos);
1271   stp(d10, d11, tos);
1272   stp(d8, d9, tos);
1273
1274   stp(x29, x30, tos);
1275   stp(x27, x28, tos);    // x28 = jssp
1276   stp(x25, x26, tos);
1277   stp(x23, x24, tos);
1278   stp(x21, x22, tos);
1279   stp(x19, x20, tos);
1280 }
1281
1282
1283 void MacroAssembler::PopCalleeSavedRegisters() {
1284   // Ensure that the macro-assembler doesn't use any scratch registers.
1285   InstructionAccurateScope scope(this);
1286
1287   // This method must not be called unless the current stack pointer is the
1288   // system stack pointer (csp).
1289   DCHECK(csp.Is(StackPointer()));
1290
1291   MemOperand tos(csp, 2 * kXRegSize, PostIndex);
1292
1293   ldp(x19, x20, tos);
1294   ldp(x21, x22, tos);
1295   ldp(x23, x24, tos);
1296   ldp(x25, x26, tos);
1297   ldp(x27, x28, tos);    // x28 = jssp
1298   ldp(x29, x30, tos);
1299
1300   ldp(d8, d9, tos);
1301   ldp(d10, d11, tos);
1302   ldp(d12, d13, tos);
1303   ldp(d14, d15, tos);
1304 }
1305
1306
1307 void MacroAssembler::AssertStackConsistency() {
1308   // Avoid emitting code when !use_real_abort() since non-real aborts cause too
1309   // much code to be generated.
1310   if (emit_debug_code() && use_real_aborts()) {
1311     if (csp.Is(StackPointer()) || CpuFeatures::IsSupported(ALWAYS_ALIGN_CSP)) {
1312       // Always check the alignment of csp if ALWAYS_ALIGN_CSP is true.  We
1313       // can't check the alignment of csp without using a scratch register (or
1314       // clobbering the flags), but the processor (or simulator) will abort if
1315       // it is not properly aligned during a load.
1316       ldr(xzr, MemOperand(csp, 0));
1317     }
1318     if (FLAG_enable_slow_asserts && !csp.Is(StackPointer())) {
1319       Label ok;
1320       // Check that csp <= StackPointer(), preserving all registers and NZCV.
1321       sub(StackPointer(), csp, StackPointer());
1322       cbz(StackPointer(), &ok);                 // Ok if csp == StackPointer().
1323       tbnz(StackPointer(), kXSignBit, &ok);     // Ok if csp < StackPointer().
1324
1325       // Avoid generating AssertStackConsistency checks for the Push in Abort.
1326       { DontEmitDebugCodeScope dont_emit_debug_code_scope(this);
1327         Abort(kTheCurrentStackPointerIsBelowCsp);
1328       }
1329
1330       bind(&ok);
1331       // Restore StackPointer().
1332       sub(StackPointer(), csp, StackPointer());
1333     }
1334   }
1335 }
1336
1337
1338 void MacroAssembler::AssertFPCRState(Register fpcr) {
1339   if (emit_debug_code()) {
1340     Label unexpected_mode, done;
1341     UseScratchRegisterScope temps(this);
1342     if (fpcr.IsNone()) {
1343       fpcr = temps.AcquireX();
1344       Mrs(fpcr, FPCR);
1345     }
1346
1347     // Settings overridden by ConfiugreFPCR():
1348     //   - Assert that default-NaN mode is set.
1349     Tbz(fpcr, DN_offset, &unexpected_mode);
1350
1351     // Settings left to their default values:
1352     //   - Assert that flush-to-zero is not set.
1353     Tbnz(fpcr, FZ_offset, &unexpected_mode);
1354     //   - Assert that the rounding mode is nearest-with-ties-to-even.
1355     STATIC_ASSERT(FPTieEven == 0);
1356     Tst(fpcr, RMode_mask);
1357     B(eq, &done);
1358
1359     Bind(&unexpected_mode);
1360     Abort(kUnexpectedFPCRMode);
1361
1362     Bind(&done);
1363   }
1364 }
1365
1366
1367 void MacroAssembler::ConfigureFPCR() {
1368   UseScratchRegisterScope temps(this);
1369   Register fpcr = temps.AcquireX();
1370   Mrs(fpcr, FPCR);
1371
1372   // If necessary, enable default-NaN mode. The default values of the other FPCR
1373   // options should be suitable, and AssertFPCRState will verify that.
1374   Label no_write_required;
1375   Tbnz(fpcr, DN_offset, &no_write_required);
1376
1377   Orr(fpcr, fpcr, DN_mask);
1378   Msr(FPCR, fpcr);
1379
1380   Bind(&no_write_required);
1381   AssertFPCRState(fpcr);
1382 }
1383
1384
1385 void MacroAssembler::CanonicalizeNaN(const FPRegister& dst,
1386                                      const FPRegister& src) {
1387   AssertFPCRState();
1388
1389   // With DN=1 and RMode=FPTieEven, subtracting 0.0 preserves all inputs except
1390   // for NaNs, which become the default NaN. We use fsub rather than fadd
1391   // because sub preserves -0.0 inputs: -0.0 + 0.0 = 0.0, but -0.0 - 0.0 = -0.0.
1392   Fsub(dst, src, fp_zero);
1393 }
1394
1395
1396 void MacroAssembler::LoadRoot(CPURegister destination,
1397                               Heap::RootListIndex index) {
1398   // TODO(jbramley): Most root values are constants, and can be synthesized
1399   // without a load. Refer to the ARM back end for details.
1400   Ldr(destination, MemOperand(root, index << kPointerSizeLog2));
1401 }
1402
1403
1404 void MacroAssembler::StoreRoot(Register source,
1405                                Heap::RootListIndex index) {
1406   Str(source, MemOperand(root, index << kPointerSizeLog2));
1407 }
1408
1409
1410 void MacroAssembler::LoadTrueFalseRoots(Register true_root,
1411                                         Register false_root) {
1412   STATIC_ASSERT((Heap::kTrueValueRootIndex + 1) == Heap::kFalseValueRootIndex);
1413   Ldp(true_root, false_root,
1414       MemOperand(root, Heap::kTrueValueRootIndex << kPointerSizeLog2));
1415 }
1416
1417
1418 void MacroAssembler::LoadHeapObject(Register result,
1419                                     Handle<HeapObject> object) {
1420   AllowDeferredHandleDereference using_raw_address;
1421   if (isolate()->heap()->InNewSpace(*object)) {
1422     Handle<Cell> cell = isolate()->factory()->NewCell(object);
1423     Mov(result, Operand(cell));
1424     Ldr(result, FieldMemOperand(result, Cell::kValueOffset));
1425   } else {
1426     Mov(result, Operand(object));
1427   }
1428 }
1429
1430
1431 void MacroAssembler::LoadInstanceDescriptors(Register map,
1432                                              Register descriptors) {
1433   Ldr(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset));
1434 }
1435
1436
1437 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
1438   Ldr(dst, FieldMemOperand(map, Map::kBitField3Offset));
1439   DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
1440 }
1441
1442
1443 void MacroAssembler::EnumLengthUntagged(Register dst, Register map) {
1444   STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
1445   Ldrsw(dst, FieldMemOperand(map, Map::kBitField3Offset));
1446   And(dst, dst, Map::EnumLengthBits::kMask);
1447 }
1448
1449
1450 void MacroAssembler::EnumLengthSmi(Register dst, Register map) {
1451   EnumLengthUntagged(dst, map);
1452   SmiTag(dst, dst);
1453 }
1454
1455
1456 void MacroAssembler::CheckEnumCache(Register object,
1457                                     Register null_value,
1458                                     Register scratch0,
1459                                     Register scratch1,
1460                                     Register scratch2,
1461                                     Register scratch3,
1462                                     Label* call_runtime) {
1463   DCHECK(!AreAliased(object, null_value, scratch0, scratch1, scratch2,
1464                      scratch3));
1465
1466   Register empty_fixed_array_value = scratch0;
1467   Register current_object = scratch1;
1468
1469   LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
1470   Label next, start;
1471
1472   Mov(current_object, object);
1473
1474   // Check if the enum length field is properly initialized, indicating that
1475   // there is an enum cache.
1476   Register map = scratch2;
1477   Register enum_length = scratch3;
1478   Ldr(map, FieldMemOperand(current_object, HeapObject::kMapOffset));
1479
1480   EnumLengthUntagged(enum_length, map);
1481   Cmp(enum_length, kInvalidEnumCacheSentinel);
1482   B(eq, call_runtime);
1483
1484   B(&start);
1485
1486   Bind(&next);
1487   Ldr(map, FieldMemOperand(current_object, HeapObject::kMapOffset));
1488
1489   // For all objects but the receiver, check that the cache is empty.
1490   EnumLengthUntagged(enum_length, map);
1491   Cbnz(enum_length, call_runtime);
1492
1493   Bind(&start);
1494
1495   // Check that there are no elements. Register current_object contains the
1496   // current JS object we've reached through the prototype chain.
1497   Label no_elements;
1498   Ldr(current_object, FieldMemOperand(current_object,
1499                                       JSObject::kElementsOffset));
1500   Cmp(current_object, empty_fixed_array_value);
1501   B(eq, &no_elements);
1502
1503   // Second chance, the object may be using the empty slow element dictionary.
1504   CompareRoot(current_object, Heap::kEmptySlowElementDictionaryRootIndex);
1505   B(ne, call_runtime);
1506
1507   Bind(&no_elements);
1508   Ldr(current_object, FieldMemOperand(map, Map::kPrototypeOffset));
1509   Cmp(current_object, null_value);
1510   B(ne, &next);
1511 }
1512
1513
1514 void MacroAssembler::TestJSArrayForAllocationMemento(Register receiver,
1515                                                      Register scratch1,
1516                                                      Register scratch2,
1517                                                      Label* no_memento_found) {
1518   ExternalReference new_space_start =
1519       ExternalReference::new_space_start(isolate());
1520   ExternalReference new_space_allocation_top =
1521       ExternalReference::new_space_allocation_top_address(isolate());
1522
1523   Add(scratch1, receiver,
1524       JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag);
1525   Cmp(scratch1, new_space_start);
1526   B(lt, no_memento_found);
1527
1528   Mov(scratch2, new_space_allocation_top);
1529   Ldr(scratch2, MemOperand(scratch2));
1530   Cmp(scratch1, scratch2);
1531   B(gt, no_memento_found);
1532
1533   Ldr(scratch1, MemOperand(scratch1, -AllocationMemento::kSize));
1534   Cmp(scratch1,
1535       Operand(isolate()->factory()->allocation_memento_map()));
1536 }
1537
1538
1539 void MacroAssembler::JumpToHandlerEntry(Register exception,
1540                                         Register object,
1541                                         Register state,
1542                                         Register scratch1,
1543                                         Register scratch2) {
1544   // Handler expects argument in x0.
1545   DCHECK(exception.Is(x0));
1546
1547   // Compute the handler entry address and jump to it. The handler table is
1548   // a fixed array of (smi-tagged) code offsets.
1549   Ldr(scratch1, FieldMemOperand(object, Code::kHandlerTableOffset));
1550   Add(scratch1, scratch1, FixedArray::kHeaderSize - kHeapObjectTag);
1551   STATIC_ASSERT(StackHandler::kKindWidth < kPointerSizeLog2);
1552   Lsr(scratch2, state, StackHandler::kKindWidth);
1553   Ldr(scratch2, MemOperand(scratch1, scratch2, LSL, kPointerSizeLog2));
1554   Add(scratch1, object, Code::kHeaderSize - kHeapObjectTag);
1555   Add(scratch1, scratch1, Operand::UntagSmi(scratch2));
1556   Br(scratch1);
1557 }
1558
1559
1560 void MacroAssembler::InNewSpace(Register object,
1561                                 Condition cond,
1562                                 Label* branch) {
1563   DCHECK(cond == eq || cond == ne);
1564   UseScratchRegisterScope temps(this);
1565   Register temp = temps.AcquireX();
1566   And(temp, object, ExternalReference::new_space_mask(isolate()));
1567   Cmp(temp, ExternalReference::new_space_start(isolate()));
1568   B(cond, branch);
1569 }
1570
1571
1572 void MacroAssembler::Throw(Register value,
1573                            Register scratch1,
1574                            Register scratch2,
1575                            Register scratch3,
1576                            Register scratch4) {
1577   // Adjust this code if not the case.
1578   STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
1579   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
1580   STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
1581   STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
1582   STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
1583   STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
1584
1585   // The handler expects the exception in x0.
1586   DCHECK(value.Is(x0));
1587
1588   // Drop the stack pointer to the top of the top handler.
1589   DCHECK(jssp.Is(StackPointer()));
1590   Mov(scratch1, Operand(ExternalReference(Isolate::kHandlerAddress,
1591                                           isolate())));
1592   Ldr(jssp, MemOperand(scratch1));
1593   // Restore the next handler.
1594   Pop(scratch2);
1595   Str(scratch2, MemOperand(scratch1));
1596
1597   // Get the code object and state.  Restore the context and frame pointer.
1598   Register object = scratch1;
1599   Register state = scratch2;
1600   Pop(object, state, cp, fp);
1601
1602   // If the handler is a JS frame, restore the context to the frame.
1603   // (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
1604   // or cp.
1605   Label not_js_frame;
1606   Cbz(cp, &not_js_frame);
1607   Str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1608   Bind(&not_js_frame);
1609
1610   JumpToHandlerEntry(value, object, state, scratch3, scratch4);
1611 }
1612
1613
1614 void MacroAssembler::ThrowUncatchable(Register value,
1615                                       Register scratch1,
1616                                       Register scratch2,
1617                                       Register scratch3,
1618                                       Register scratch4) {
1619   // Adjust this code if not the case.
1620   STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
1621   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
1622   STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
1623   STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
1624   STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
1625   STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
1626
1627   // The handler expects the exception in x0.
1628   DCHECK(value.Is(x0));
1629
1630   // Drop the stack pointer to the top of the top stack handler.
1631   DCHECK(jssp.Is(StackPointer()));
1632   Mov(scratch1, Operand(ExternalReference(Isolate::kHandlerAddress,
1633                                           isolate())));
1634   Ldr(jssp, MemOperand(scratch1));
1635
1636   // Unwind the handlers until the ENTRY handler is found.
1637   Label fetch_next, check_kind;
1638   B(&check_kind);
1639   Bind(&fetch_next);
1640   Peek(jssp, StackHandlerConstants::kNextOffset);
1641
1642   Bind(&check_kind);
1643   STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
1644   Peek(scratch2, StackHandlerConstants::kStateOffset);
1645   TestAndBranchIfAnySet(scratch2, StackHandler::KindField::kMask, &fetch_next);
1646
1647   // Set the top handler address to next handler past the top ENTRY handler.
1648   Pop(scratch2);
1649   Str(scratch2, MemOperand(scratch1));
1650
1651   // Get the code object and state.  Clear the context and frame pointer (0 was
1652   // saved in the handler).
1653   Register object = scratch1;
1654   Register state = scratch2;
1655   Pop(object, state, cp, fp);
1656
1657   JumpToHandlerEntry(value, object, state, scratch3, scratch4);
1658 }
1659
1660
1661 void MacroAssembler::AssertSmi(Register object, BailoutReason reason) {
1662   if (emit_debug_code()) {
1663     STATIC_ASSERT(kSmiTag == 0);
1664     Tst(object, kSmiTagMask);
1665     Check(eq, reason);
1666   }
1667 }
1668
1669
1670 void MacroAssembler::AssertNotSmi(Register object, BailoutReason reason) {
1671   if (emit_debug_code()) {
1672     STATIC_ASSERT(kSmiTag == 0);
1673     Tst(object, kSmiTagMask);
1674     Check(ne, reason);
1675   }
1676 }
1677
1678
1679 void MacroAssembler::AssertName(Register object) {
1680   if (emit_debug_code()) {
1681     AssertNotSmi(object, kOperandIsASmiAndNotAName);
1682
1683     UseScratchRegisterScope temps(this);
1684     Register temp = temps.AcquireX();
1685
1686     Ldr(temp, FieldMemOperand(object, HeapObject::kMapOffset));
1687     CompareInstanceType(temp, temp, LAST_NAME_TYPE);
1688     Check(ls, kOperandIsNotAName);
1689   }
1690 }
1691
1692
1693 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object,
1694                                                      Register scratch) {
1695   if (emit_debug_code()) {
1696     Label done_checking;
1697     AssertNotSmi(object);
1698     JumpIfRoot(object, Heap::kUndefinedValueRootIndex, &done_checking);
1699     Ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
1700     CompareRoot(scratch, Heap::kAllocationSiteMapRootIndex);
1701     Assert(eq, kExpectedUndefinedOrCell);
1702     Bind(&done_checking);
1703   }
1704 }
1705
1706
1707 void MacroAssembler::AssertString(Register object) {
1708   if (emit_debug_code()) {
1709     UseScratchRegisterScope temps(this);
1710     Register temp = temps.AcquireX();
1711     STATIC_ASSERT(kSmiTag == 0);
1712     Tst(object, kSmiTagMask);
1713     Check(ne, kOperandIsASmiAndNotAString);
1714     Ldr(temp, FieldMemOperand(object, HeapObject::kMapOffset));
1715     CompareInstanceType(temp, temp, FIRST_NONSTRING_TYPE);
1716     Check(lo, kOperandIsNotAString);
1717   }
1718 }
1719
1720
1721 void MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) {
1722   DCHECK(AllowThisStubCall(stub));  // Stub calls are not allowed in some stubs.
1723   Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id);
1724 }
1725
1726
1727 void MacroAssembler::TailCallStub(CodeStub* stub) {
1728   Jump(stub->GetCode(), RelocInfo::CODE_TARGET);
1729 }
1730
1731
1732 void MacroAssembler::CallRuntime(const Runtime::Function* f,
1733                                  int num_arguments,
1734                                  SaveFPRegsMode save_doubles) {
1735   // All arguments must be on the stack before this function is called.
1736   // x0 holds the return value after the call.
1737
1738   // Check that the number of arguments matches what the function expects.
1739   // If f->nargs is -1, the function can accept a variable number of arguments.
1740   CHECK(f->nargs < 0 || f->nargs == num_arguments);
1741
1742   // Place the necessary arguments.
1743   Mov(x0, num_arguments);
1744   Mov(x1, ExternalReference(f, isolate()));
1745
1746   CEntryStub stub(isolate(), 1, save_doubles);
1747   CallStub(&stub);
1748 }
1749
1750
1751 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
1752   return ref0.address() - ref1.address();
1753 }
1754
1755
1756 void MacroAssembler::CallApiFunctionAndReturn(
1757     Register function_address,
1758     ExternalReference thunk_ref,
1759     int stack_space,
1760     int spill_offset,
1761     MemOperand return_value_operand,
1762     MemOperand* context_restore_operand) {
1763   ASM_LOCATION("CallApiFunctionAndReturn");
1764   ExternalReference next_address =
1765       ExternalReference::handle_scope_next_address(isolate());
1766   const int kNextOffset = 0;
1767   const int kLimitOffset = AddressOffset(
1768       ExternalReference::handle_scope_limit_address(isolate()),
1769       next_address);
1770   const int kLevelOffset = AddressOffset(
1771       ExternalReference::handle_scope_level_address(isolate()),
1772       next_address);
1773
1774   DCHECK(function_address.is(x1) || function_address.is(x2));
1775
1776   Label profiler_disabled;
1777   Label end_profiler_check;
1778   Mov(x10, ExternalReference::is_profiling_address(isolate()));
1779   Ldrb(w10, MemOperand(x10));
1780   Cbz(w10, &profiler_disabled);
1781   Mov(x3, thunk_ref);
1782   B(&end_profiler_check);
1783
1784   Bind(&profiler_disabled);
1785   Mov(x3, function_address);
1786   Bind(&end_profiler_check);
1787
1788   // Save the callee-save registers we are going to use.
1789   // TODO(all): Is this necessary? ARM doesn't do it.
1790   STATIC_ASSERT(kCallApiFunctionSpillSpace == 4);
1791   Poke(x19, (spill_offset + 0) * kXRegSize);
1792   Poke(x20, (spill_offset + 1) * kXRegSize);
1793   Poke(x21, (spill_offset + 2) * kXRegSize);
1794   Poke(x22, (spill_offset + 3) * kXRegSize);
1795
1796   // Allocate HandleScope in callee-save registers.
1797   // We will need to restore the HandleScope after the call to the API function,
1798   // by allocating it in callee-save registers they will be preserved by C code.
1799   Register handle_scope_base = x22;
1800   Register next_address_reg = x19;
1801   Register limit_reg = x20;
1802   Register level_reg = w21;
1803
1804   Mov(handle_scope_base, next_address);
1805   Ldr(next_address_reg, MemOperand(handle_scope_base, kNextOffset));
1806   Ldr(limit_reg, MemOperand(handle_scope_base, kLimitOffset));
1807   Ldr(level_reg, MemOperand(handle_scope_base, kLevelOffset));
1808   Add(level_reg, level_reg, 1);
1809   Str(level_reg, MemOperand(handle_scope_base, kLevelOffset));
1810
1811   if (FLAG_log_timer_events) {
1812     FrameScope frame(this, StackFrame::MANUAL);
1813     PushSafepointRegisters();
1814     Mov(x0, ExternalReference::isolate_address(isolate()));
1815     CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1);
1816     PopSafepointRegisters();
1817   }
1818
1819   // Native call returns to the DirectCEntry stub which redirects to the
1820   // return address pushed on stack (could have moved after GC).
1821   // DirectCEntry stub itself is generated early and never moves.
1822   DirectCEntryStub stub(isolate());
1823   stub.GenerateCall(this, x3);
1824
1825   if (FLAG_log_timer_events) {
1826     FrameScope frame(this, StackFrame::MANUAL);
1827     PushSafepointRegisters();
1828     Mov(x0, ExternalReference::isolate_address(isolate()));
1829     CallCFunction(ExternalReference::log_leave_external_function(isolate()), 1);
1830     PopSafepointRegisters();
1831   }
1832
1833   Label promote_scheduled_exception;
1834   Label exception_handled;
1835   Label delete_allocated_handles;
1836   Label leave_exit_frame;
1837   Label return_value_loaded;
1838
1839   // Load value from ReturnValue.
1840   Ldr(x0, return_value_operand);
1841   Bind(&return_value_loaded);
1842   // No more valid handles (the result handle was the last one). Restore
1843   // previous handle scope.
1844   Str(next_address_reg, MemOperand(handle_scope_base, kNextOffset));
1845   if (emit_debug_code()) {
1846     Ldr(w1, MemOperand(handle_scope_base, kLevelOffset));
1847     Cmp(w1, level_reg);
1848     Check(eq, kUnexpectedLevelAfterReturnFromApiCall);
1849   }
1850   Sub(level_reg, level_reg, 1);
1851   Str(level_reg, MemOperand(handle_scope_base, kLevelOffset));
1852   Ldr(x1, MemOperand(handle_scope_base, kLimitOffset));
1853   Cmp(limit_reg, x1);
1854   B(ne, &delete_allocated_handles);
1855
1856   Bind(&leave_exit_frame);
1857   // Restore callee-saved registers.
1858   Peek(x19, (spill_offset + 0) * kXRegSize);
1859   Peek(x20, (spill_offset + 1) * kXRegSize);
1860   Peek(x21, (spill_offset + 2) * kXRegSize);
1861   Peek(x22, (spill_offset + 3) * kXRegSize);
1862
1863   // Check if the function scheduled an exception.
1864   Mov(x5, ExternalReference::scheduled_exception_address(isolate()));
1865   Ldr(x5, MemOperand(x5));
1866   JumpIfNotRoot(x5, Heap::kTheHoleValueRootIndex, &promote_scheduled_exception);
1867   Bind(&exception_handled);
1868
1869   bool restore_context = context_restore_operand != NULL;
1870   if (restore_context) {
1871     Ldr(cp, *context_restore_operand);
1872   }
1873
1874   LeaveExitFrame(false, x1, !restore_context);
1875   Drop(stack_space);
1876   Ret();
1877
1878   Bind(&promote_scheduled_exception);
1879   {
1880     FrameScope frame(this, StackFrame::INTERNAL);
1881     CallExternalReference(
1882         ExternalReference(
1883             Runtime::kPromoteScheduledException, isolate()), 0);
1884   }
1885   B(&exception_handled);
1886
1887   // HandleScope limit has changed. Delete allocated extensions.
1888   Bind(&delete_allocated_handles);
1889   Str(limit_reg, MemOperand(handle_scope_base, kLimitOffset));
1890   // Save the return value in a callee-save register.
1891   Register saved_result = x19;
1892   Mov(saved_result, x0);
1893   Mov(x0, ExternalReference::isolate_address(isolate()));
1894   CallCFunction(
1895       ExternalReference::delete_handle_scope_extensions(isolate()), 1);
1896   Mov(x0, saved_result);
1897   B(&leave_exit_frame);
1898 }
1899
1900
1901 void MacroAssembler::CallExternalReference(const ExternalReference& ext,
1902                                            int num_arguments) {
1903   Mov(x0, num_arguments);
1904   Mov(x1, ext);
1905
1906   CEntryStub stub(isolate(), 1);
1907   CallStub(&stub);
1908 }
1909
1910
1911 void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin) {
1912   Mov(x1, builtin);
1913   CEntryStub stub(isolate(), 1);
1914   Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
1915 }
1916
1917
1918 void MacroAssembler::GetBuiltinFunction(Register target,
1919                                         Builtins::JavaScript id) {
1920   // Load the builtins object into target register.
1921   Ldr(target, GlobalObjectMemOperand());
1922   Ldr(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset));
1923   // Load the JavaScript builtin function from the builtins object.
1924   Ldr(target, FieldMemOperand(target,
1925                           JSBuiltinsObject::OffsetOfFunctionWithId(id)));
1926 }
1927
1928
1929 void MacroAssembler::GetBuiltinEntry(Register target,
1930                                      Register function,
1931                                      Builtins::JavaScript id) {
1932   DCHECK(!AreAliased(target, function));
1933   GetBuiltinFunction(function, id);
1934   // Load the code entry point from the builtins object.
1935   Ldr(target, FieldMemOperand(function, JSFunction::kCodeEntryOffset));
1936 }
1937
1938
1939 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
1940                                    InvokeFlag flag,
1941                                    const CallWrapper& call_wrapper) {
1942   ASM_LOCATION("MacroAssembler::InvokeBuiltin");
1943   // You can't call a builtin without a valid frame.
1944   DCHECK(flag == JUMP_FUNCTION || has_frame());
1945
1946   // Get the builtin entry in x2 and setup the function object in x1.
1947   GetBuiltinEntry(x2, x1, id);
1948   if (flag == CALL_FUNCTION) {
1949     call_wrapper.BeforeCall(CallSize(x2));
1950     Call(x2);
1951     call_wrapper.AfterCall();
1952   } else {
1953     DCHECK(flag == JUMP_FUNCTION);
1954     Jump(x2);
1955   }
1956 }
1957
1958
1959 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
1960                                                int num_arguments,
1961                                                int result_size) {
1962   // TODO(1236192): Most runtime routines don't need the number of
1963   // arguments passed in because it is constant. At some point we
1964   // should remove this need and make the runtime routine entry code
1965   // smarter.
1966   Mov(x0, num_arguments);
1967   JumpToExternalReference(ext);
1968 }
1969
1970
1971 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
1972                                      int num_arguments,
1973                                      int result_size) {
1974   TailCallExternalReference(ExternalReference(fid, isolate()),
1975                             num_arguments,
1976                             result_size);
1977 }
1978
1979
1980 void MacroAssembler::InitializeNewString(Register string,
1981                                          Register length,
1982                                          Heap::RootListIndex map_index,
1983                                          Register scratch1,
1984                                          Register scratch2) {
1985   DCHECK(!AreAliased(string, length, scratch1, scratch2));
1986   LoadRoot(scratch2, map_index);
1987   SmiTag(scratch1, length);
1988   Str(scratch2, FieldMemOperand(string, HeapObject::kMapOffset));
1989
1990   Mov(scratch2, String::kEmptyHashField);
1991   Str(scratch1, FieldMemOperand(string, String::kLengthOffset));
1992   Str(scratch2, FieldMemOperand(string, String::kHashFieldOffset));
1993 }
1994
1995
1996 int MacroAssembler::ActivationFrameAlignment() {
1997 #if V8_HOST_ARCH_ARM64
1998   // Running on the real platform. Use the alignment as mandated by the local
1999   // environment.
2000   // Note: This will break if we ever start generating snapshots on one ARM
2001   // platform for another ARM platform with a different alignment.
2002   return base::OS::ActivationFrameAlignment();
2003 #else  // V8_HOST_ARCH_ARM64
2004   // If we are using the simulator then we should always align to the expected
2005   // alignment. As the simulator is used to generate snapshots we do not know
2006   // if the target platform will need alignment, so this is controlled from a
2007   // flag.
2008   return FLAG_sim_stack_alignment;
2009 #endif  // V8_HOST_ARCH_ARM64
2010 }
2011
2012
2013 void MacroAssembler::CallCFunction(ExternalReference function,
2014                                    int num_of_reg_args) {
2015   CallCFunction(function, num_of_reg_args, 0);
2016 }
2017
2018
2019 void MacroAssembler::CallCFunction(ExternalReference function,
2020                                    int num_of_reg_args,
2021                                    int num_of_double_args) {
2022   UseScratchRegisterScope temps(this);
2023   Register temp = temps.AcquireX();
2024   Mov(temp, function);
2025   CallCFunction(temp, num_of_reg_args, num_of_double_args);
2026 }
2027
2028
2029 void MacroAssembler::CallCFunction(Register function,
2030                                    int num_of_reg_args,
2031                                    int num_of_double_args) {
2032   DCHECK(has_frame());
2033   // We can pass 8 integer arguments in registers. If we need to pass more than
2034   // that, we'll need to implement support for passing them on the stack.
2035   DCHECK(num_of_reg_args <= 8);
2036
2037   // If we're passing doubles, we're limited to the following prototypes
2038   // (defined by ExternalReference::Type):
2039   //  BUILTIN_COMPARE_CALL:  int f(double, double)
2040   //  BUILTIN_FP_FP_CALL:    double f(double, double)
2041   //  BUILTIN_FP_CALL:       double f(double)
2042   //  BUILTIN_FP_INT_CALL:   double f(double, int)
2043   if (num_of_double_args > 0) {
2044     DCHECK(num_of_reg_args <= 1);
2045     DCHECK((num_of_double_args + num_of_reg_args) <= 2);
2046   }
2047
2048
2049   // If the stack pointer is not csp, we need to derive an aligned csp from the
2050   // current stack pointer.
2051   const Register old_stack_pointer = StackPointer();
2052   if (!csp.Is(old_stack_pointer)) {
2053     AssertStackConsistency();
2054
2055     int sp_alignment = ActivationFrameAlignment();
2056     // The ABI mandates at least 16-byte alignment.
2057     DCHECK(sp_alignment >= 16);
2058     DCHECK(base::bits::IsPowerOfTwo32(sp_alignment));
2059
2060     // The current stack pointer is a callee saved register, and is preserved
2061     // across the call.
2062     DCHECK(kCalleeSaved.IncludesAliasOf(old_stack_pointer));
2063
2064     // Align and synchronize the system stack pointer with jssp.
2065     Bic(csp, old_stack_pointer, sp_alignment - 1);
2066     SetStackPointer(csp);
2067   }
2068
2069   // Call directly. The function called cannot cause a GC, or allow preemption,
2070   // so the return address in the link register stays correct.
2071   Call(function);
2072
2073   if (!csp.Is(old_stack_pointer)) {
2074     if (emit_debug_code()) {
2075       // Because the stack pointer must be aligned on a 16-byte boundary, the
2076       // aligned csp can be up to 12 bytes below the jssp. This is the case
2077       // where we only pushed one W register on top of an aligned jssp.
2078       UseScratchRegisterScope temps(this);
2079       Register temp = temps.AcquireX();
2080       DCHECK(ActivationFrameAlignment() == 16);
2081       Sub(temp, csp, old_stack_pointer);
2082       // We want temp <= 0 && temp >= -12.
2083       Cmp(temp, 0);
2084       Ccmp(temp, -12, NFlag, le);
2085       Check(ge, kTheStackWasCorruptedByMacroAssemblerCall);
2086     }
2087     SetStackPointer(old_stack_pointer);
2088   }
2089 }
2090
2091
2092 void MacroAssembler::Jump(Register target) {
2093   Br(target);
2094 }
2095
2096
2097 void MacroAssembler::Jump(intptr_t target, RelocInfo::Mode rmode) {
2098   UseScratchRegisterScope temps(this);
2099   Register temp = temps.AcquireX();
2100   Mov(temp, Operand(target, rmode));
2101   Br(temp);
2102 }
2103
2104
2105 void MacroAssembler::Jump(Address target, RelocInfo::Mode rmode) {
2106   DCHECK(!RelocInfo::IsCodeTarget(rmode));
2107   Jump(reinterpret_cast<intptr_t>(target), rmode);
2108 }
2109
2110
2111 void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode) {
2112   DCHECK(RelocInfo::IsCodeTarget(rmode));
2113   AllowDeferredHandleDereference embedding_raw_address;
2114   Jump(reinterpret_cast<intptr_t>(code.location()), rmode);
2115 }
2116
2117
2118 void MacroAssembler::Call(Register target) {
2119   BlockPoolsScope scope(this);
2120 #ifdef DEBUG
2121   Label start_call;
2122   Bind(&start_call);
2123 #endif
2124
2125   Blr(target);
2126
2127 #ifdef DEBUG
2128   AssertSizeOfCodeGeneratedSince(&start_call, CallSize(target));
2129 #endif
2130 }
2131
2132
2133 void MacroAssembler::Call(Label* target) {
2134   BlockPoolsScope scope(this);
2135 #ifdef DEBUG
2136   Label start_call;
2137   Bind(&start_call);
2138 #endif
2139
2140   Bl(target);
2141
2142 #ifdef DEBUG
2143   AssertSizeOfCodeGeneratedSince(&start_call, CallSize(target));
2144 #endif
2145 }
2146
2147
2148 // MacroAssembler::CallSize is sensitive to changes in this function, as it
2149 // requires to know how many instructions are used to branch to the target.
2150 void MacroAssembler::Call(Address target, RelocInfo::Mode rmode) {
2151   BlockPoolsScope scope(this);
2152 #ifdef DEBUG
2153   Label start_call;
2154   Bind(&start_call);
2155 #endif
2156   // Statement positions are expected to be recorded when the target
2157   // address is loaded.
2158   positions_recorder()->WriteRecordedPositions();
2159
2160   // Addresses always have 64 bits, so we shouldn't encounter NONE32.
2161   DCHECK(rmode != RelocInfo::NONE32);
2162
2163   UseScratchRegisterScope temps(this);
2164   Register temp = temps.AcquireX();
2165
2166   if (rmode == RelocInfo::NONE64) {
2167     // Addresses are 48 bits so we never need to load the upper 16 bits.
2168     uint64_t imm = reinterpret_cast<uint64_t>(target);
2169     // If we don't use ARM tagged addresses, the 16 higher bits must be 0.
2170     DCHECK(((imm >> 48) & 0xffff) == 0);
2171     movz(temp, (imm >> 0) & 0xffff, 0);
2172     movk(temp, (imm >> 16) & 0xffff, 16);
2173     movk(temp, (imm >> 32) & 0xffff, 32);
2174   } else {
2175     Ldr(temp, Immediate(reinterpret_cast<intptr_t>(target), rmode));
2176   }
2177   Blr(temp);
2178 #ifdef DEBUG
2179   AssertSizeOfCodeGeneratedSince(&start_call, CallSize(target, rmode));
2180 #endif
2181 }
2182
2183
2184 void MacroAssembler::Call(Handle<Code> code,
2185                           RelocInfo::Mode rmode,
2186                           TypeFeedbackId ast_id) {
2187 #ifdef DEBUG
2188   Label start_call;
2189   Bind(&start_call);
2190 #endif
2191
2192   if ((rmode == RelocInfo::CODE_TARGET) && (!ast_id.IsNone())) {
2193     SetRecordedAstId(ast_id);
2194     rmode = RelocInfo::CODE_TARGET_WITH_ID;
2195   }
2196
2197   AllowDeferredHandleDereference embedding_raw_address;
2198   Call(reinterpret_cast<Address>(code.location()), rmode);
2199
2200 #ifdef DEBUG
2201   // Check the size of the code generated.
2202   AssertSizeOfCodeGeneratedSince(&start_call, CallSize(code, rmode, ast_id));
2203 #endif
2204 }
2205
2206
2207 int MacroAssembler::CallSize(Register target) {
2208   USE(target);
2209   return kInstructionSize;
2210 }
2211
2212
2213 int MacroAssembler::CallSize(Label* target) {
2214   USE(target);
2215   return kInstructionSize;
2216 }
2217
2218
2219 int MacroAssembler::CallSize(Address target, RelocInfo::Mode rmode) {
2220   USE(target);
2221
2222   // Addresses always have 64 bits, so we shouldn't encounter NONE32.
2223   DCHECK(rmode != RelocInfo::NONE32);
2224
2225   if (rmode == RelocInfo::NONE64) {
2226     return kCallSizeWithoutRelocation;
2227   } else {
2228     return kCallSizeWithRelocation;
2229   }
2230 }
2231
2232
2233 int MacroAssembler::CallSize(Handle<Code> code,
2234                              RelocInfo::Mode rmode,
2235                              TypeFeedbackId ast_id) {
2236   USE(code);
2237   USE(ast_id);
2238
2239   // Addresses always have 64 bits, so we shouldn't encounter NONE32.
2240   DCHECK(rmode != RelocInfo::NONE32);
2241
2242   if (rmode == RelocInfo::NONE64) {
2243     return kCallSizeWithoutRelocation;
2244   } else {
2245     return kCallSizeWithRelocation;
2246   }
2247 }
2248
2249
2250 void MacroAssembler::JumpIfHeapNumber(Register object, Label* on_heap_number,
2251                                       SmiCheckType smi_check_type) {
2252   Label on_not_heap_number;
2253
2254   if (smi_check_type == DO_SMI_CHECK) {
2255     JumpIfSmi(object, &on_not_heap_number);
2256   }
2257
2258   AssertNotSmi(object);
2259
2260   UseScratchRegisterScope temps(this);
2261   Register temp = temps.AcquireX();
2262   Ldr(temp, FieldMemOperand(object, HeapObject::kMapOffset));
2263   JumpIfRoot(temp, Heap::kHeapNumberMapRootIndex, on_heap_number);
2264
2265   Bind(&on_not_heap_number);
2266 }
2267
2268
2269 void MacroAssembler::JumpIfNotHeapNumber(Register object,
2270                                          Label* on_not_heap_number,
2271                                          SmiCheckType smi_check_type) {
2272   if (smi_check_type == DO_SMI_CHECK) {
2273     JumpIfSmi(object, on_not_heap_number);
2274   }
2275
2276   AssertNotSmi(object);
2277
2278   UseScratchRegisterScope temps(this);
2279   Register temp = temps.AcquireX();
2280   Ldr(temp, FieldMemOperand(object, HeapObject::kMapOffset));
2281   JumpIfNotRoot(temp, Heap::kHeapNumberMapRootIndex, on_not_heap_number);
2282 }
2283
2284
2285 void MacroAssembler::LookupNumberStringCache(Register object,
2286                                              Register result,
2287                                              Register scratch1,
2288                                              Register scratch2,
2289                                              Register scratch3,
2290                                              Label* not_found) {
2291   DCHECK(!AreAliased(object, result, scratch1, scratch2, scratch3));
2292
2293   // Use of registers. Register result is used as a temporary.
2294   Register number_string_cache = result;
2295   Register mask = scratch3;
2296
2297   // Load the number string cache.
2298   LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
2299
2300   // Make the hash mask from the length of the number string cache. It
2301   // contains two elements (number and string) for each cache entry.
2302   Ldrsw(mask, UntagSmiFieldMemOperand(number_string_cache,
2303                                       FixedArray::kLengthOffset));
2304   Asr(mask, mask, 1);  // Divide length by two.
2305   Sub(mask, mask, 1);  // Make mask.
2306
2307   // Calculate the entry in the number string cache. The hash value in the
2308   // number string cache for smis is just the smi value, and the hash for
2309   // doubles is the xor of the upper and lower words. See
2310   // Heap::GetNumberStringCache.
2311   Label is_smi;
2312   Label load_result_from_cache;
2313
2314   JumpIfSmi(object, &is_smi);
2315   JumpIfNotHeapNumber(object, not_found);
2316
2317   STATIC_ASSERT(kDoubleSize == (kWRegSize * 2));
2318   Add(scratch1, object, HeapNumber::kValueOffset - kHeapObjectTag);
2319   Ldp(scratch1.W(), scratch2.W(), MemOperand(scratch1));
2320   Eor(scratch1, scratch1, scratch2);
2321   And(scratch1, scratch1, mask);
2322
2323   // Calculate address of entry in string cache: each entry consists of two
2324   // pointer sized fields.
2325   Add(scratch1, number_string_cache,
2326       Operand(scratch1, LSL, kPointerSizeLog2 + 1));
2327
2328   Register probe = mask;
2329   Ldr(probe, FieldMemOperand(scratch1, FixedArray::kHeaderSize));
2330   JumpIfSmi(probe, not_found);
2331   Ldr(d0, FieldMemOperand(object, HeapNumber::kValueOffset));
2332   Ldr(d1, FieldMemOperand(probe, HeapNumber::kValueOffset));
2333   Fcmp(d0, d1);
2334   B(ne, not_found);
2335   B(&load_result_from_cache);
2336
2337   Bind(&is_smi);
2338   Register scratch = scratch1;
2339   And(scratch, mask, Operand::UntagSmi(object));
2340   // Calculate address of entry in string cache: each entry consists
2341   // of two pointer sized fields.
2342   Add(scratch, number_string_cache,
2343       Operand(scratch, LSL, kPointerSizeLog2 + 1));
2344
2345   // Check if the entry is the smi we are looking for.
2346   Ldr(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize));
2347   Cmp(object, probe);
2348   B(ne, not_found);
2349
2350   // Get the result from the cache.
2351   Bind(&load_result_from_cache);
2352   Ldr(result, FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize));
2353   IncrementCounter(isolate()->counters()->number_to_string_native(), 1,
2354                    scratch1, scratch2);
2355 }
2356
2357
2358 void MacroAssembler::TryRepresentDoubleAsInt(Register as_int,
2359                                              FPRegister value,
2360                                              FPRegister scratch_d,
2361                                              Label* on_successful_conversion,
2362                                              Label* on_failed_conversion) {
2363   // Convert to an int and back again, then compare with the original value.
2364   Fcvtzs(as_int, value);
2365   Scvtf(scratch_d, as_int);
2366   Fcmp(value, scratch_d);
2367
2368   if (on_successful_conversion) {
2369     B(on_successful_conversion, eq);
2370   }
2371   if (on_failed_conversion) {
2372     B(on_failed_conversion, ne);
2373   }
2374 }
2375
2376
2377 void MacroAssembler::TestForMinusZero(DoubleRegister input) {
2378   UseScratchRegisterScope temps(this);
2379   Register temp = temps.AcquireX();
2380   // Floating point -0.0 is kMinInt as an integer, so subtracting 1 (cmp) will
2381   // cause overflow.
2382   Fmov(temp, input);
2383   Cmp(temp, 1);
2384 }
2385
2386
2387 void MacroAssembler::JumpIfMinusZero(DoubleRegister input,
2388                                      Label* on_negative_zero) {
2389   TestForMinusZero(input);
2390   B(vs, on_negative_zero);
2391 }
2392
2393
2394 void MacroAssembler::JumpIfMinusZero(Register input,
2395                                      Label* on_negative_zero) {
2396   DCHECK(input.Is64Bits());
2397   // Floating point value is in an integer register. Detect -0.0 by subtracting
2398   // 1 (cmp), which will cause overflow.
2399   Cmp(input, 1);
2400   B(vs, on_negative_zero);
2401 }
2402
2403
2404 void MacroAssembler::ClampInt32ToUint8(Register output, Register input) {
2405   // Clamp the value to [0..255].
2406   Cmp(input.W(), Operand(input.W(), UXTB));
2407   // If input < input & 0xff, it must be < 0, so saturate to 0.
2408   Csel(output.W(), wzr, input.W(), lt);
2409   // If input <= input & 0xff, it must be <= 255. Otherwise, saturate to 255.
2410   Csel(output.W(), output.W(), 255, le);
2411 }
2412
2413
2414 void MacroAssembler::ClampInt32ToUint8(Register in_out) {
2415   ClampInt32ToUint8(in_out, in_out);
2416 }
2417
2418
2419 void MacroAssembler::ClampDoubleToUint8(Register output,
2420                                         DoubleRegister input,
2421                                         DoubleRegister dbl_scratch) {
2422   // This conversion follows the WebIDL "[Clamp]" rules for PIXEL types:
2423   //   - Inputs lower than 0 (including -infinity) produce 0.
2424   //   - Inputs higher than 255 (including +infinity) produce 255.
2425   // Also, it seems that PIXEL types use round-to-nearest rather than
2426   // round-towards-zero.
2427
2428   // Squash +infinity before the conversion, since Fcvtnu will normally
2429   // convert it to 0.
2430   Fmov(dbl_scratch, 255);
2431   Fmin(dbl_scratch, dbl_scratch, input);
2432
2433   // Convert double to unsigned integer. Values less than zero become zero.
2434   // Values greater than 255 have already been clamped to 255.
2435   Fcvtnu(output, dbl_scratch);
2436 }
2437
2438
2439 void MacroAssembler::CopyFieldsLoopPairsHelper(Register dst,
2440                                                Register src,
2441                                                unsigned count,
2442                                                Register scratch1,
2443                                                Register scratch2,
2444                                                Register scratch3,
2445                                                Register scratch4,
2446                                                Register scratch5) {
2447   // Untag src and dst into scratch registers.
2448   // Copy src->dst in a tight loop.
2449   DCHECK(!AreAliased(dst, src,
2450                      scratch1, scratch2, scratch3, scratch4, scratch5));
2451   DCHECK(count >= 2);
2452
2453   const Register& remaining = scratch3;
2454   Mov(remaining, count / 2);
2455
2456   const Register& dst_untagged = scratch1;
2457   const Register& src_untagged = scratch2;
2458   Sub(dst_untagged, dst, kHeapObjectTag);
2459   Sub(src_untagged, src, kHeapObjectTag);
2460
2461   // Copy fields in pairs.
2462   Label loop;
2463   Bind(&loop);
2464   Ldp(scratch4, scratch5,
2465       MemOperand(src_untagged, kXRegSize* 2, PostIndex));
2466   Stp(scratch4, scratch5,
2467       MemOperand(dst_untagged, kXRegSize* 2, PostIndex));
2468   Sub(remaining, remaining, 1);
2469   Cbnz(remaining, &loop);
2470
2471   // Handle the leftovers.
2472   if (count & 1) {
2473     Ldr(scratch4, MemOperand(src_untagged));
2474     Str(scratch4, MemOperand(dst_untagged));
2475   }
2476 }
2477
2478
2479 void MacroAssembler::CopyFieldsUnrolledPairsHelper(Register dst,
2480                                                    Register src,
2481                                                    unsigned count,
2482                                                    Register scratch1,
2483                                                    Register scratch2,
2484                                                    Register scratch3,
2485                                                    Register scratch4) {
2486   // Untag src and dst into scratch registers.
2487   // Copy src->dst in an unrolled loop.
2488   DCHECK(!AreAliased(dst, src, scratch1, scratch2, scratch3, scratch4));
2489
2490   const Register& dst_untagged = scratch1;
2491   const Register& src_untagged = scratch2;
2492   sub(dst_untagged, dst, kHeapObjectTag);
2493   sub(src_untagged, src, kHeapObjectTag);
2494
2495   // Copy fields in pairs.
2496   for (unsigned i = 0; i < count / 2; i++) {
2497     Ldp(scratch3, scratch4, MemOperand(src_untagged, kXRegSize * 2, PostIndex));
2498     Stp(scratch3, scratch4, MemOperand(dst_untagged, kXRegSize * 2, PostIndex));
2499   }
2500
2501   // Handle the leftovers.
2502   if (count & 1) {
2503     Ldr(scratch3, MemOperand(src_untagged));
2504     Str(scratch3, MemOperand(dst_untagged));
2505   }
2506 }
2507
2508
2509 void MacroAssembler::CopyFieldsUnrolledHelper(Register dst,
2510                                               Register src,
2511                                               unsigned count,
2512                                               Register scratch1,
2513                                               Register scratch2,
2514                                               Register scratch3) {
2515   // Untag src and dst into scratch registers.
2516   // Copy src->dst in an unrolled loop.
2517   DCHECK(!AreAliased(dst, src, scratch1, scratch2, scratch3));
2518
2519   const Register& dst_untagged = scratch1;
2520   const Register& src_untagged = scratch2;
2521   Sub(dst_untagged, dst, kHeapObjectTag);
2522   Sub(src_untagged, src, kHeapObjectTag);
2523
2524   // Copy fields one by one.
2525   for (unsigned i = 0; i < count; i++) {
2526     Ldr(scratch3, MemOperand(src_untagged, kXRegSize, PostIndex));
2527     Str(scratch3, MemOperand(dst_untagged, kXRegSize, PostIndex));
2528   }
2529 }
2530
2531
2532 void MacroAssembler::CopyFields(Register dst, Register src, CPURegList temps,
2533                                 unsigned count) {
2534   // One of two methods is used:
2535   //
2536   // For high 'count' values where many scratch registers are available:
2537   //    Untag src and dst into scratch registers.
2538   //    Copy src->dst in a tight loop.
2539   //
2540   // For low 'count' values or where few scratch registers are available:
2541   //    Untag src and dst into scratch registers.
2542   //    Copy src->dst in an unrolled loop.
2543   //
2544   // In both cases, fields are copied in pairs if possible, and left-overs are
2545   // handled separately.
2546   DCHECK(!AreAliased(dst, src));
2547   DCHECK(!temps.IncludesAliasOf(dst));
2548   DCHECK(!temps.IncludesAliasOf(src));
2549   DCHECK(!temps.IncludesAliasOf(xzr));
2550
2551   if (emit_debug_code()) {
2552     Cmp(dst, src);
2553     Check(ne, kTheSourceAndDestinationAreTheSame);
2554   }
2555
2556   // The value of 'count' at which a loop will be generated (if there are
2557   // enough scratch registers).
2558   static const unsigned kLoopThreshold = 8;
2559
2560   UseScratchRegisterScope masm_temps(this);
2561   if ((temps.Count() >= 3) && (count >= kLoopThreshold)) {
2562     CopyFieldsLoopPairsHelper(dst, src, count,
2563                               Register(temps.PopLowestIndex()),
2564                               Register(temps.PopLowestIndex()),
2565                               Register(temps.PopLowestIndex()),
2566                               masm_temps.AcquireX(),
2567                               masm_temps.AcquireX());
2568   } else if (temps.Count() >= 2) {
2569     CopyFieldsUnrolledPairsHelper(dst, src, count,
2570                                   Register(temps.PopLowestIndex()),
2571                                   Register(temps.PopLowestIndex()),
2572                                   masm_temps.AcquireX(),
2573                                   masm_temps.AcquireX());
2574   } else if (temps.Count() == 1) {
2575     CopyFieldsUnrolledHelper(dst, src, count,
2576                              Register(temps.PopLowestIndex()),
2577                              masm_temps.AcquireX(),
2578                              masm_temps.AcquireX());
2579   } else {
2580     UNREACHABLE();
2581   }
2582 }
2583
2584
2585 void MacroAssembler::CopyBytes(Register dst,
2586                                Register src,
2587                                Register length,
2588                                Register scratch,
2589                                CopyHint hint) {
2590   UseScratchRegisterScope temps(this);
2591   Register tmp1 = temps.AcquireX();
2592   Register tmp2 = temps.AcquireX();
2593   DCHECK(!AreAliased(src, dst, length, scratch, tmp1, tmp2));
2594   DCHECK(!AreAliased(src, dst, csp));
2595
2596   if (emit_debug_code()) {
2597     // Check copy length.
2598     Cmp(length, 0);
2599     Assert(ge, kUnexpectedNegativeValue);
2600
2601     // Check src and dst buffers don't overlap.
2602     Add(scratch, src, length);  // Calculate end of src buffer.
2603     Cmp(scratch, dst);
2604     Add(scratch, dst, length);  // Calculate end of dst buffer.
2605     Ccmp(scratch, src, ZFlag, gt);
2606     Assert(le, kCopyBuffersOverlap);
2607   }
2608
2609   Label short_copy, short_loop, bulk_loop, done;
2610
2611   if ((hint == kCopyLong || hint == kCopyUnknown) && !FLAG_optimize_for_size) {
2612     Register bulk_length = scratch;
2613     int pair_size = 2 * kXRegSize;
2614     int pair_mask = pair_size - 1;
2615
2616     Bic(bulk_length, length, pair_mask);
2617     Cbz(bulk_length, &short_copy);
2618     Bind(&bulk_loop);
2619     Sub(bulk_length, bulk_length, pair_size);
2620     Ldp(tmp1, tmp2, MemOperand(src, pair_size, PostIndex));
2621     Stp(tmp1, tmp2, MemOperand(dst, pair_size, PostIndex));
2622     Cbnz(bulk_length, &bulk_loop);
2623
2624     And(length, length, pair_mask);
2625   }
2626
2627   Bind(&short_copy);
2628   Cbz(length, &done);
2629   Bind(&short_loop);
2630   Sub(length, length, 1);
2631   Ldrb(tmp1, MemOperand(src, 1, PostIndex));
2632   Strb(tmp1, MemOperand(dst, 1, PostIndex));
2633   Cbnz(length, &short_loop);
2634
2635
2636   Bind(&done);
2637 }
2638
2639
2640 void MacroAssembler::FillFields(Register dst,
2641                                 Register field_count,
2642                                 Register filler) {
2643   DCHECK(!dst.Is(csp));
2644   UseScratchRegisterScope temps(this);
2645   Register field_ptr = temps.AcquireX();
2646   Register counter = temps.AcquireX();
2647   Label done;
2648
2649   // Decrement count. If the result < zero, count was zero, and there's nothing
2650   // to do. If count was one, flags are set to fail the gt condition at the end
2651   // of the pairs loop.
2652   Subs(counter, field_count, 1);
2653   B(lt, &done);
2654
2655   // There's at least one field to fill, so do this unconditionally.
2656   Str(filler, MemOperand(dst, kPointerSize, PostIndex));
2657
2658   // If the bottom bit of counter is set, there are an even number of fields to
2659   // fill, so pull the start pointer back by one field, allowing the pairs loop
2660   // to overwrite the field that was stored above.
2661   And(field_ptr, counter, 1);
2662   Sub(field_ptr, dst, Operand(field_ptr, LSL, kPointerSizeLog2));
2663
2664   // Store filler to memory in pairs.
2665   Label entry, loop;
2666   B(&entry);
2667   Bind(&loop);
2668   Stp(filler, filler, MemOperand(field_ptr, 2 * kPointerSize, PostIndex));
2669   Subs(counter, counter, 2);
2670   Bind(&entry);
2671   B(gt, &loop);
2672
2673   Bind(&done);
2674 }
2675
2676
2677 void MacroAssembler::JumpIfEitherIsNotSequentialOneByteStrings(
2678     Register first, Register second, Register scratch1, Register scratch2,
2679     Label* failure, SmiCheckType smi_check) {
2680   if (smi_check == DO_SMI_CHECK) {
2681     JumpIfEitherSmi(first, second, failure);
2682   } else if (emit_debug_code()) {
2683     DCHECK(smi_check == DONT_DO_SMI_CHECK);
2684     Label not_smi;
2685     JumpIfEitherSmi(first, second, NULL, &not_smi);
2686
2687     // At least one input is a smi, but the flags indicated a smi check wasn't
2688     // needed.
2689     Abort(kUnexpectedSmi);
2690
2691     Bind(&not_smi);
2692   }
2693
2694   // Test that both first and second are sequential one-byte strings.
2695   Ldr(scratch1, FieldMemOperand(first, HeapObject::kMapOffset));
2696   Ldr(scratch2, FieldMemOperand(second, HeapObject::kMapOffset));
2697   Ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
2698   Ldrb(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset));
2699
2700   JumpIfEitherInstanceTypeIsNotSequentialOneByte(scratch1, scratch2, scratch1,
2701                                                  scratch2, failure);
2702 }
2703
2704
2705 void MacroAssembler::JumpIfEitherInstanceTypeIsNotSequentialOneByte(
2706     Register first, Register second, Register scratch1, Register scratch2,
2707     Label* failure) {
2708   DCHECK(!AreAliased(scratch1, second));
2709   DCHECK(!AreAliased(scratch1, scratch2));
2710   static const int kFlatOneByteStringMask =
2711       kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
2712   static const int kFlatOneByteStringTag = ONE_BYTE_STRING_TYPE;
2713   And(scratch1, first, kFlatOneByteStringMask);
2714   And(scratch2, second, kFlatOneByteStringMask);
2715   Cmp(scratch1, kFlatOneByteStringTag);
2716   Ccmp(scratch2, kFlatOneByteStringTag, NoFlag, eq);
2717   B(ne, failure);
2718 }
2719
2720
2721 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte(Register type,
2722                                                               Register scratch,
2723                                                               Label* failure) {
2724   const int kFlatOneByteStringMask =
2725       kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
2726   const int kFlatOneByteStringTag =
2727       kStringTag | kOneByteStringTag | kSeqStringTag;
2728   And(scratch, type, kFlatOneByteStringMask);
2729   Cmp(scratch, kFlatOneByteStringTag);
2730   B(ne, failure);
2731 }
2732
2733
2734 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte(
2735     Register first, Register second, Register scratch1, Register scratch2,
2736     Label* failure) {
2737   DCHECK(!AreAliased(first, second, scratch1, scratch2));
2738   const int kFlatOneByteStringMask =
2739       kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
2740   const int kFlatOneByteStringTag =
2741       kStringTag | kOneByteStringTag | kSeqStringTag;
2742   And(scratch1, first, kFlatOneByteStringMask);
2743   And(scratch2, second, kFlatOneByteStringMask);
2744   Cmp(scratch1, kFlatOneByteStringTag);
2745   Ccmp(scratch2, kFlatOneByteStringTag, NoFlag, eq);
2746   B(ne, failure);
2747 }
2748
2749
2750 void MacroAssembler::JumpIfNotUniqueNameInstanceType(Register type,
2751                                                      Label* not_unique_name) {
2752   STATIC_ASSERT((kInternalizedTag == 0) && (kStringTag == 0));
2753   // if ((type is string && type is internalized) || type == SYMBOL_TYPE) {
2754   //   continue
2755   // } else {
2756   //   goto not_unique_name
2757   // }
2758   Tst(type, kIsNotStringMask | kIsNotInternalizedMask);
2759   Ccmp(type, SYMBOL_TYPE, ZFlag, ne);
2760   B(ne, not_unique_name);
2761 }
2762
2763
2764 void MacroAssembler::InvokePrologue(const ParameterCount& expected,
2765                                     const ParameterCount& actual,
2766                                     Handle<Code> code_constant,
2767                                     Register code_reg,
2768                                     Label* done,
2769                                     InvokeFlag flag,
2770                                     bool* definitely_mismatches,
2771                                     const CallWrapper& call_wrapper) {
2772   bool definitely_matches = false;
2773   *definitely_mismatches = false;
2774   Label regular_invoke;
2775
2776   // Check whether the expected and actual arguments count match. If not,
2777   // setup registers according to contract with ArgumentsAdaptorTrampoline:
2778   //  x0: actual arguments count.
2779   //  x1: function (passed through to callee).
2780   //  x2: expected arguments count.
2781
2782   // The code below is made a lot easier because the calling code already sets
2783   // up actual and expected registers according to the contract if values are
2784   // passed in registers.
2785   DCHECK(actual.is_immediate() || actual.reg().is(x0));
2786   DCHECK(expected.is_immediate() || expected.reg().is(x2));
2787   DCHECK((!code_constant.is_null() && code_reg.is(no_reg)) || code_reg.is(x3));
2788
2789   if (expected.is_immediate()) {
2790     DCHECK(actual.is_immediate());
2791     if (expected.immediate() == actual.immediate()) {
2792       definitely_matches = true;
2793
2794     } else {
2795       Mov(x0, actual.immediate());
2796       if (expected.immediate() ==
2797           SharedFunctionInfo::kDontAdaptArgumentsSentinel) {
2798         // Don't worry about adapting arguments for builtins that
2799         // don't want that done. Skip adaption code by making it look
2800         // like we have a match between expected and actual number of
2801         // arguments.
2802         definitely_matches = true;
2803       } else {
2804         *definitely_mismatches = true;
2805         // Set up x2 for the argument adaptor.
2806         Mov(x2, expected.immediate());
2807       }
2808     }
2809
2810   } else {  // expected is a register.
2811     Operand actual_op = actual.is_immediate() ? Operand(actual.immediate())
2812                                               : Operand(actual.reg());
2813     // If actual == expected perform a regular invocation.
2814     Cmp(expected.reg(), actual_op);
2815     B(eq, &regular_invoke);
2816     // Otherwise set up x0 for the argument adaptor.
2817     Mov(x0, actual_op);
2818   }
2819
2820   // If the argument counts may mismatch, generate a call to the argument
2821   // adaptor.
2822   if (!definitely_matches) {
2823     if (!code_constant.is_null()) {
2824       Mov(x3, Operand(code_constant));
2825       Add(x3, x3, Code::kHeaderSize - kHeapObjectTag);
2826     }
2827
2828     Handle<Code> adaptor =
2829         isolate()->builtins()->ArgumentsAdaptorTrampoline();
2830     if (flag == CALL_FUNCTION) {
2831       call_wrapper.BeforeCall(CallSize(adaptor));
2832       Call(adaptor);
2833       call_wrapper.AfterCall();
2834       if (!*definitely_mismatches) {
2835         // If the arg counts don't match, no extra code is emitted by
2836         // MAsm::InvokeCode and we can just fall through.
2837         B(done);
2838       }
2839     } else {
2840       Jump(adaptor, RelocInfo::CODE_TARGET);
2841     }
2842   }
2843   Bind(&regular_invoke);
2844 }
2845
2846
2847 void MacroAssembler::InvokeCode(Register code,
2848                                 const ParameterCount& expected,
2849                                 const ParameterCount& actual,
2850                                 InvokeFlag flag,
2851                                 const CallWrapper& call_wrapper) {
2852   // You can't call a function without a valid frame.
2853   DCHECK(flag == JUMP_FUNCTION || has_frame());
2854
2855   Label done;
2856
2857   bool definitely_mismatches = false;
2858   InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag,
2859                  &definitely_mismatches, call_wrapper);
2860
2861   // If we are certain that actual != expected, then we know InvokePrologue will
2862   // have handled the call through the argument adaptor mechanism.
2863   // The called function expects the call kind in x5.
2864   if (!definitely_mismatches) {
2865     if (flag == CALL_FUNCTION) {
2866       call_wrapper.BeforeCall(CallSize(code));
2867       Call(code);
2868       call_wrapper.AfterCall();
2869     } else {
2870       DCHECK(flag == JUMP_FUNCTION);
2871       Jump(code);
2872     }
2873   }
2874
2875   // Continue here if InvokePrologue does handle the invocation due to
2876   // mismatched parameter counts.
2877   Bind(&done);
2878 }
2879
2880
2881 void MacroAssembler::InvokeFunction(Register function,
2882                                     const ParameterCount& actual,
2883                                     InvokeFlag flag,
2884                                     const CallWrapper& call_wrapper) {
2885   // You can't call a function without a valid frame.
2886   DCHECK(flag == JUMP_FUNCTION || has_frame());
2887
2888   // Contract with called JS functions requires that function is passed in x1.
2889   // (See FullCodeGenerator::Generate().)
2890   DCHECK(function.is(x1));
2891
2892   Register expected_reg = x2;
2893   Register code_reg = x3;
2894
2895   Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset));
2896   // The number of arguments is stored as an int32_t, and -1 is a marker
2897   // (SharedFunctionInfo::kDontAdaptArgumentsSentinel), so we need sign
2898   // extension to correctly handle it.
2899   Ldr(expected_reg, FieldMemOperand(function,
2900                                     JSFunction::kSharedFunctionInfoOffset));
2901   Ldrsw(expected_reg,
2902         FieldMemOperand(expected_reg,
2903                         SharedFunctionInfo::kFormalParameterCountOffset));
2904   Ldr(code_reg,
2905       FieldMemOperand(function, JSFunction::kCodeEntryOffset));
2906
2907   ParameterCount expected(expected_reg);
2908   InvokeCode(code_reg, expected, actual, flag, call_wrapper);
2909 }
2910
2911
2912 void MacroAssembler::InvokeFunction(Register function,
2913                                     const ParameterCount& expected,
2914                                     const ParameterCount& actual,
2915                                     InvokeFlag flag,
2916                                     const CallWrapper& call_wrapper) {
2917   // You can't call a function without a valid frame.
2918   DCHECK(flag == JUMP_FUNCTION || has_frame());
2919
2920   // Contract with called JS functions requires that function is passed in x1.
2921   // (See FullCodeGenerator::Generate().)
2922   DCHECK(function.Is(x1));
2923
2924   Register code_reg = x3;
2925
2926   // Set up the context.
2927   Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset));
2928
2929   // We call indirectly through the code field in the function to
2930   // allow recompilation to take effect without changing any of the
2931   // call sites.
2932   Ldr(code_reg, FieldMemOperand(function, JSFunction::kCodeEntryOffset));
2933   InvokeCode(code_reg, expected, actual, flag, call_wrapper);
2934 }
2935
2936
2937 void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
2938                                     const ParameterCount& expected,
2939                                     const ParameterCount& actual,
2940                                     InvokeFlag flag,
2941                                     const CallWrapper& call_wrapper) {
2942   // Contract with called JS functions requires that function is passed in x1.
2943   // (See FullCodeGenerator::Generate().)
2944   __ LoadObject(x1, function);
2945   InvokeFunction(x1, expected, actual, flag, call_wrapper);
2946 }
2947
2948
2949 void MacroAssembler::TryConvertDoubleToInt64(Register result,
2950                                              DoubleRegister double_input,
2951                                              Label* done) {
2952   // Try to convert with an FPU convert instruction. It's trivial to compute
2953   // the modulo operation on an integer register so we convert to a 64-bit
2954   // integer.
2955   //
2956   // Fcvtzs will saturate to INT64_MIN (0x800...00) or INT64_MAX (0x7ff...ff)
2957   // when the double is out of range. NaNs and infinities will be converted to 0
2958   // (as ECMA-262 requires).
2959   Fcvtzs(result.X(), double_input);
2960
2961   // The values INT64_MIN (0x800...00) or INT64_MAX (0x7ff...ff) are not
2962   // representable using a double, so if the result is one of those then we know
2963   // that saturation occured, and we need to manually handle the conversion.
2964   //
2965   // It is easy to detect INT64_MIN and INT64_MAX because adding or subtracting
2966   // 1 will cause signed overflow.
2967   Cmp(result.X(), 1);
2968   Ccmp(result.X(), -1, VFlag, vc);
2969
2970   B(vc, done);
2971 }
2972
2973
2974 void MacroAssembler::TruncateDoubleToI(Register result,
2975                                        DoubleRegister double_input) {
2976   Label done;
2977
2978   // Try to convert the double to an int64. If successful, the bottom 32 bits
2979   // contain our truncated int32 result.
2980   TryConvertDoubleToInt64(result, double_input, &done);
2981
2982   const Register old_stack_pointer = StackPointer();
2983   if (csp.Is(old_stack_pointer)) {
2984     // This currently only happens during compiler-unittest. If it arises
2985     // during regular code generation the DoubleToI stub should be updated to
2986     // cope with csp and have an extra parameter indicating which stack pointer
2987     // it should use.
2988     Push(jssp, xzr);  // Push xzr to maintain csp required 16-bytes alignment.
2989     Mov(jssp, csp);
2990     SetStackPointer(jssp);
2991   }
2992
2993   // If we fell through then inline version didn't succeed - call stub instead.
2994   Push(lr, double_input);
2995
2996   DoubleToIStub stub(isolate(),
2997                      jssp,
2998                      result,
2999                      0,
3000                      true,   // is_truncating
3001                      true);  // skip_fastpath
3002   CallStub(&stub);  // DoubleToIStub preserves any registers it needs to clobber
3003
3004   DCHECK_EQ(xzr.SizeInBytes(), double_input.SizeInBytes());
3005   Pop(xzr, lr);  // xzr to drop the double input on the stack.
3006
3007   if (csp.Is(old_stack_pointer)) {
3008     Mov(csp, jssp);
3009     SetStackPointer(csp);
3010     AssertStackConsistency();
3011     Pop(xzr, jssp);
3012   }
3013
3014   Bind(&done);
3015 }
3016
3017
3018 void MacroAssembler::TruncateHeapNumberToI(Register result,
3019                                            Register object) {
3020   Label done;
3021   DCHECK(!result.is(object));
3022   DCHECK(jssp.Is(StackPointer()));
3023
3024   Ldr(fp_scratch, FieldMemOperand(object, HeapNumber::kValueOffset));
3025
3026   // Try to convert the double to an int64. If successful, the bottom 32 bits
3027   // contain our truncated int32 result.
3028   TryConvertDoubleToInt64(result, fp_scratch, &done);
3029
3030   // If we fell through then inline version didn't succeed - call stub instead.
3031   Push(lr);
3032   DoubleToIStub stub(isolate(),
3033                      object,
3034                      result,
3035                      HeapNumber::kValueOffset - kHeapObjectTag,
3036                      true,   // is_truncating
3037                      true);  // skip_fastpath
3038   CallStub(&stub);  // DoubleToIStub preserves any registers it needs to clobber
3039   Pop(lr);
3040
3041   Bind(&done);
3042 }
3043
3044
3045 void MacroAssembler::StubPrologue() {
3046   DCHECK(StackPointer().Is(jssp));
3047   UseScratchRegisterScope temps(this);
3048   Register temp = temps.AcquireX();
3049   __ Mov(temp, Smi::FromInt(StackFrame::STUB));
3050   // Compiled stubs don't age, and so they don't need the predictable code
3051   // ageing sequence.
3052   __ Push(lr, fp, cp, temp);
3053   __ Add(fp, jssp, StandardFrameConstants::kFixedFrameSizeFromFp);
3054 }
3055
3056
3057 void MacroAssembler::Prologue(bool code_pre_aging) {
3058   if (code_pre_aging) {
3059     Code* stub = Code::GetPreAgedCodeAgeStub(isolate());
3060     __ EmitCodeAgeSequence(stub);
3061   } else {
3062     __ EmitFrameSetupForCodeAgePatching();
3063   }
3064 }
3065
3066
3067 void MacroAssembler::EnterFrame(StackFrame::Type type,
3068                                 bool load_constant_pool_pointer_reg) {
3069   // Out-of-line constant pool not implemented on arm64.
3070   UNREACHABLE();
3071 }
3072
3073
3074 void MacroAssembler::EnterFrame(StackFrame::Type type) {
3075   DCHECK(jssp.Is(StackPointer()));
3076   UseScratchRegisterScope temps(this);
3077   Register type_reg = temps.AcquireX();
3078   Register code_reg = temps.AcquireX();
3079
3080   Push(lr, fp, cp);
3081   Mov(type_reg, Smi::FromInt(type));
3082   Mov(code_reg, Operand(CodeObject()));
3083   Push(type_reg, code_reg);
3084   // jssp[4] : lr
3085   // jssp[3] : fp
3086   // jssp[2] : cp
3087   // jssp[1] : type
3088   // jssp[0] : code object
3089
3090   // Adjust FP to point to saved FP.
3091   Add(fp, jssp, StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize);
3092 }
3093
3094
3095 void MacroAssembler::LeaveFrame(StackFrame::Type type) {
3096   DCHECK(jssp.Is(StackPointer()));
3097   // Drop the execution stack down to the frame pointer and restore
3098   // the caller frame pointer and return address.
3099   Mov(jssp, fp);
3100   AssertStackConsistency();
3101   Pop(fp, lr);
3102 }
3103
3104
3105 void MacroAssembler::ExitFramePreserveFPRegs() {
3106   PushCPURegList(kCallerSavedFP);
3107 }
3108
3109
3110 void MacroAssembler::ExitFrameRestoreFPRegs() {
3111   // Read the registers from the stack without popping them. The stack pointer
3112   // will be reset as part of the unwinding process.
3113   CPURegList saved_fp_regs = kCallerSavedFP;
3114   DCHECK(saved_fp_regs.Count() % 2 == 0);
3115
3116   int offset = ExitFrameConstants::kLastExitFrameField;
3117   while (!saved_fp_regs.IsEmpty()) {
3118     const CPURegister& dst0 = saved_fp_regs.PopHighestIndex();
3119     const CPURegister& dst1 = saved_fp_regs.PopHighestIndex();
3120     offset -= 2 * kDRegSize;
3121     Ldp(dst1, dst0, MemOperand(fp, offset));
3122   }
3123 }
3124
3125
3126 void MacroAssembler::EnterExitFrame(bool save_doubles,
3127                                     const Register& scratch,
3128                                     int extra_space) {
3129   DCHECK(jssp.Is(StackPointer()));
3130
3131   // Set up the new stack frame.
3132   Mov(scratch, Operand(CodeObject()));
3133   Push(lr, fp);
3134   Mov(fp, StackPointer());
3135   Push(xzr, scratch);
3136   //          fp[8]: CallerPC (lr)
3137   //    fp -> fp[0]: CallerFP (old fp)
3138   //          fp[-8]: Space reserved for SPOffset.
3139   //  jssp -> fp[-16]: CodeObject()
3140   STATIC_ASSERT((2 * kPointerSize) ==
3141                 ExitFrameConstants::kCallerSPDisplacement);
3142   STATIC_ASSERT((1 * kPointerSize) == ExitFrameConstants::kCallerPCOffset);
3143   STATIC_ASSERT((0 * kPointerSize) == ExitFrameConstants::kCallerFPOffset);
3144   STATIC_ASSERT((-1 * kPointerSize) == ExitFrameConstants::kSPOffset);
3145   STATIC_ASSERT((-2 * kPointerSize) == ExitFrameConstants::kCodeOffset);
3146
3147   // Save the frame pointer and context pointer in the top frame.
3148   Mov(scratch, Operand(ExternalReference(Isolate::kCEntryFPAddress,
3149                                          isolate())));
3150   Str(fp, MemOperand(scratch));
3151   Mov(scratch, Operand(ExternalReference(Isolate::kContextAddress,
3152                                          isolate())));
3153   Str(cp, MemOperand(scratch));
3154
3155   STATIC_ASSERT((-2 * kPointerSize) ==
3156                 ExitFrameConstants::kLastExitFrameField);
3157   if (save_doubles) {
3158     ExitFramePreserveFPRegs();
3159   }
3160
3161   // Reserve space for the return address and for user requested memory.
3162   // We do this before aligning to make sure that we end up correctly
3163   // aligned with the minimum of wasted space.
3164   Claim(extra_space + 1, kXRegSize);
3165   //         fp[8]: CallerPC (lr)
3166   //   fp -> fp[0]: CallerFP (old fp)
3167   //         fp[-8]: Space reserved for SPOffset.
3168   //         fp[-16]: CodeObject()
3169   //         fp[-16 - fp_size]: Saved doubles (if save_doubles is true).
3170   //         jssp[8]: Extra space reserved for caller (if extra_space != 0).
3171   // jssp -> jssp[0]: Space reserved for the return address.
3172
3173   // Align and synchronize the system stack pointer with jssp.
3174   AlignAndSetCSPForFrame();
3175   DCHECK(csp.Is(StackPointer()));
3176
3177   //         fp[8]: CallerPC (lr)
3178   //   fp -> fp[0]: CallerFP (old fp)
3179   //         fp[-8]: Space reserved for SPOffset.
3180   //         fp[-16]: CodeObject()
3181   //         fp[-16 - fp_size]: Saved doubles (if save_doubles is true).
3182   //         csp[8]: Memory reserved for the caller if extra_space != 0.
3183   //                 Alignment padding, if necessary.
3184   //  csp -> csp[0]: Space reserved for the return address.
3185
3186   // ExitFrame::GetStateForFramePointer expects to find the return address at
3187   // the memory address immediately below the pointer stored in SPOffset.
3188   // It is not safe to derive much else from SPOffset, because the size of the
3189   // padding can vary.
3190   Add(scratch, csp, kXRegSize);
3191   Str(scratch, MemOperand(fp, ExitFrameConstants::kSPOffset));
3192 }
3193
3194
3195 // Leave the current exit frame.
3196 void MacroAssembler::LeaveExitFrame(bool restore_doubles,
3197                                     const Register& scratch,
3198                                     bool restore_context) {
3199   DCHECK(csp.Is(StackPointer()));
3200
3201   if (restore_doubles) {
3202     ExitFrameRestoreFPRegs();
3203   }
3204
3205   // Restore the context pointer from the top frame.
3206   if (restore_context) {
3207     Mov(scratch, Operand(ExternalReference(Isolate::kContextAddress,
3208                                            isolate())));
3209     Ldr(cp, MemOperand(scratch));
3210   }
3211
3212   if (emit_debug_code()) {
3213     // Also emit debug code to clear the cp in the top frame.
3214     Mov(scratch, Operand(ExternalReference(Isolate::kContextAddress,
3215                                            isolate())));
3216     Str(xzr, MemOperand(scratch));
3217   }
3218   // Clear the frame pointer from the top frame.
3219   Mov(scratch, Operand(ExternalReference(Isolate::kCEntryFPAddress,
3220                                          isolate())));
3221   Str(xzr, MemOperand(scratch));
3222
3223   // Pop the exit frame.
3224   //         fp[8]: CallerPC (lr)
3225   //   fp -> fp[0]: CallerFP (old fp)
3226   //         fp[...]: The rest of the frame.
3227   Mov(jssp, fp);
3228   SetStackPointer(jssp);
3229   AssertStackConsistency();
3230   Pop(fp, lr);
3231 }
3232
3233
3234 void MacroAssembler::SetCounter(StatsCounter* counter, int value,
3235                                 Register scratch1, Register scratch2) {
3236   if (FLAG_native_code_counters && counter->Enabled()) {
3237     Mov(scratch1, value);
3238     Mov(scratch2, ExternalReference(counter));
3239     Str(scratch1, MemOperand(scratch2));
3240   }
3241 }
3242
3243
3244 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value,
3245                                       Register scratch1, Register scratch2) {
3246   DCHECK(value != 0);
3247   if (FLAG_native_code_counters && counter->Enabled()) {
3248     Mov(scratch2, ExternalReference(counter));
3249     Ldr(scratch1, MemOperand(scratch2));
3250     Add(scratch1, scratch1, value);
3251     Str(scratch1, MemOperand(scratch2));
3252   }
3253 }
3254
3255
3256 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
3257                                       Register scratch1, Register scratch2) {
3258   IncrementCounter(counter, -value, scratch1, scratch2);
3259 }
3260
3261
3262 void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
3263   if (context_chain_length > 0) {
3264     // Move up the chain of contexts to the context containing the slot.
3265     Ldr(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX)));
3266     for (int i = 1; i < context_chain_length; i++) {
3267       Ldr(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
3268     }
3269   } else {
3270     // Slot is in the current function context.  Move it into the
3271     // destination register in case we store into it (the write barrier
3272     // cannot be allowed to destroy the context in cp).
3273     Mov(dst, cp);
3274   }
3275 }
3276
3277
3278 void MacroAssembler::DebugBreak() {
3279   Mov(x0, 0);
3280   Mov(x1, ExternalReference(Runtime::kDebugBreak, isolate()));
3281   CEntryStub ces(isolate(), 1);
3282   DCHECK(AllowThisStubCall(&ces));
3283   Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
3284 }
3285
3286
3287 void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
3288                                     int handler_index) {
3289   DCHECK(jssp.Is(StackPointer()));
3290   // Adjust this code if the asserts don't hold.
3291   STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
3292   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
3293   STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
3294   STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
3295   STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
3296   STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
3297
3298   // For the JSEntry handler, we must preserve the live registers x0-x4.
3299   // (See JSEntryStub::GenerateBody().)
3300
3301   unsigned state =
3302       StackHandler::IndexField::encode(handler_index) |
3303       StackHandler::KindField::encode(kind);
3304
3305   // Set up the code object and the state for pushing.
3306   Mov(x10, Operand(CodeObject()));
3307   Mov(x11, state);
3308
3309   // Push the frame pointer, context, state, and code object.
3310   if (kind == StackHandler::JS_ENTRY) {
3311     DCHECK(Smi::FromInt(0) == 0);
3312     Push(xzr, xzr, x11, x10);
3313   } else {
3314     Push(fp, cp, x11, x10);
3315   }
3316
3317   // Link the current handler as the next handler.
3318   Mov(x11, ExternalReference(Isolate::kHandlerAddress, isolate()));
3319   Ldr(x10, MemOperand(x11));
3320   Push(x10);
3321   // Set this new handler as the current one.
3322   Str(jssp, MemOperand(x11));
3323 }
3324
3325
3326 void MacroAssembler::PopTryHandler() {
3327   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
3328   Pop(x10);
3329   Mov(x11, ExternalReference(Isolate::kHandlerAddress, isolate()));
3330   Drop(StackHandlerConstants::kSize - kXRegSize, kByteSizeInBytes);
3331   Str(x10, MemOperand(x11));
3332 }
3333
3334
3335 void MacroAssembler::Allocate(int object_size,
3336                               Register result,
3337                               Register scratch1,
3338                               Register scratch2,
3339                               Label* gc_required,
3340                               AllocationFlags flags) {
3341   DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
3342   if (!FLAG_inline_new) {
3343     if (emit_debug_code()) {
3344       // Trash the registers to simulate an allocation failure.
3345       // We apply salt to the original zap value to easily spot the values.
3346       Mov(result, (kDebugZapValue & ~0xffL) | 0x11L);
3347       Mov(scratch1, (kDebugZapValue & ~0xffL) | 0x21L);
3348       Mov(scratch2, (kDebugZapValue & ~0xffL) | 0x21L);
3349     }
3350     B(gc_required);
3351     return;
3352   }
3353
3354   UseScratchRegisterScope temps(this);
3355   Register scratch3 = temps.AcquireX();
3356
3357   DCHECK(!AreAliased(result, scratch1, scratch2, scratch3));
3358   DCHECK(result.Is64Bits() && scratch1.Is64Bits() && scratch2.Is64Bits());
3359
3360   // Make object size into bytes.
3361   if ((flags & SIZE_IN_WORDS) != 0) {
3362     object_size *= kPointerSize;
3363   }
3364   DCHECK(0 == (object_size & kObjectAlignmentMask));
3365
3366   // Check relative positions of allocation top and limit addresses.
3367   // The values must be adjacent in memory to allow the use of LDP.
3368   ExternalReference heap_allocation_top =
3369       AllocationUtils::GetAllocationTopReference(isolate(), flags);
3370   ExternalReference heap_allocation_limit =
3371       AllocationUtils::GetAllocationLimitReference(isolate(), flags);
3372   intptr_t top = reinterpret_cast<intptr_t>(heap_allocation_top.address());
3373   intptr_t limit = reinterpret_cast<intptr_t>(heap_allocation_limit.address());
3374   DCHECK((limit - top) == kPointerSize);
3375
3376   // Set up allocation top address and object size registers.
3377   Register top_address = scratch1;
3378   Register allocation_limit = scratch2;
3379   Mov(top_address, Operand(heap_allocation_top));
3380
3381   if ((flags & RESULT_CONTAINS_TOP) == 0) {
3382     // Load allocation top into result and the allocation limit.
3383     Ldp(result, allocation_limit, MemOperand(top_address));
3384   } else {
3385     if (emit_debug_code()) {
3386       // Assert that result actually contains top on entry.
3387       Ldr(scratch3, MemOperand(top_address));
3388       Cmp(result, scratch3);
3389       Check(eq, kUnexpectedAllocationTop);
3390     }
3391     // Load the allocation limit. 'result' already contains the allocation top.
3392     Ldr(allocation_limit, MemOperand(top_address, limit - top));
3393   }
3394
3395   // We can ignore DOUBLE_ALIGNMENT flags here because doubles and pointers have
3396   // the same alignment on ARM64.
3397   STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
3398
3399   // Calculate new top and bail out if new space is exhausted.
3400   Adds(scratch3, result, object_size);
3401   Ccmp(scratch3, allocation_limit, CFlag, cc);
3402   B(hi, gc_required);
3403   Str(scratch3, MemOperand(top_address));
3404
3405   // Tag the object if requested.
3406   if ((flags & TAG_OBJECT) != 0) {
3407     ObjectTag(result, result);
3408   }
3409 }
3410
3411
3412 void MacroAssembler::Allocate(Register object_size,
3413                               Register result,
3414                               Register scratch1,
3415                               Register scratch2,
3416                               Label* gc_required,
3417                               AllocationFlags flags) {
3418   if (!FLAG_inline_new) {
3419     if (emit_debug_code()) {
3420       // Trash the registers to simulate an allocation failure.
3421       // We apply salt to the original zap value to easily spot the values.
3422       Mov(result, (kDebugZapValue & ~0xffL) | 0x11L);
3423       Mov(scratch1, (kDebugZapValue & ~0xffL) | 0x21L);
3424       Mov(scratch2, (kDebugZapValue & ~0xffL) | 0x21L);
3425     }
3426     B(gc_required);
3427     return;
3428   }
3429
3430   UseScratchRegisterScope temps(this);
3431   Register scratch3 = temps.AcquireX();
3432
3433   DCHECK(!AreAliased(object_size, result, scratch1, scratch2, scratch3));
3434   DCHECK(object_size.Is64Bits() && result.Is64Bits() &&
3435          scratch1.Is64Bits() && scratch2.Is64Bits());
3436
3437   // Check relative positions of allocation top and limit addresses.
3438   // The values must be adjacent in memory to allow the use of LDP.
3439   ExternalReference heap_allocation_top =
3440       AllocationUtils::GetAllocationTopReference(isolate(), flags);
3441   ExternalReference heap_allocation_limit =
3442       AllocationUtils::GetAllocationLimitReference(isolate(), flags);
3443   intptr_t top = reinterpret_cast<intptr_t>(heap_allocation_top.address());
3444   intptr_t limit = reinterpret_cast<intptr_t>(heap_allocation_limit.address());
3445   DCHECK((limit - top) == kPointerSize);
3446
3447   // Set up allocation top address and object size registers.
3448   Register top_address = scratch1;
3449   Register allocation_limit = scratch2;
3450   Mov(top_address, heap_allocation_top);
3451
3452   if ((flags & RESULT_CONTAINS_TOP) == 0) {
3453     // Load allocation top into result and the allocation limit.
3454     Ldp(result, allocation_limit, MemOperand(top_address));
3455   } else {
3456     if (emit_debug_code()) {
3457       // Assert that result actually contains top on entry.
3458       Ldr(scratch3, MemOperand(top_address));
3459       Cmp(result, scratch3);
3460       Check(eq, kUnexpectedAllocationTop);
3461     }
3462     // Load the allocation limit. 'result' already contains the allocation top.
3463     Ldr(allocation_limit, MemOperand(top_address, limit - top));
3464   }
3465
3466   // We can ignore DOUBLE_ALIGNMENT flags here because doubles and pointers have
3467   // the same alignment on ARM64.
3468   STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
3469
3470   // Calculate new top and bail out if new space is exhausted
3471   if ((flags & SIZE_IN_WORDS) != 0) {
3472     Adds(scratch3, result, Operand(object_size, LSL, kPointerSizeLog2));
3473   } else {
3474     Adds(scratch3, result, object_size);
3475   }
3476
3477   if (emit_debug_code()) {
3478     Tst(scratch3, kObjectAlignmentMask);
3479     Check(eq, kUnalignedAllocationInNewSpace);
3480   }
3481
3482   Ccmp(scratch3, allocation_limit, CFlag, cc);
3483   B(hi, gc_required);
3484   Str(scratch3, MemOperand(top_address));
3485
3486   // Tag the object if requested.
3487   if ((flags & TAG_OBJECT) != 0) {
3488     ObjectTag(result, result);
3489   }
3490 }
3491
3492
3493 void MacroAssembler::UndoAllocationInNewSpace(Register object,
3494                                               Register scratch) {
3495   ExternalReference new_space_allocation_top =
3496       ExternalReference::new_space_allocation_top_address(isolate());
3497
3498   // Make sure the object has no tag before resetting top.
3499   Bic(object, object, kHeapObjectTagMask);
3500 #ifdef DEBUG
3501   // Check that the object un-allocated is below the current top.
3502   Mov(scratch, new_space_allocation_top);
3503   Ldr(scratch, MemOperand(scratch));
3504   Cmp(object, scratch);
3505   Check(lt, kUndoAllocationOfNonAllocatedMemory);
3506 #endif
3507   // Write the address of the object to un-allocate as the current top.
3508   Mov(scratch, new_space_allocation_top);
3509   Str(object, MemOperand(scratch));
3510 }
3511
3512
3513 void MacroAssembler::AllocateTwoByteString(Register result,
3514                                            Register length,
3515                                            Register scratch1,
3516                                            Register scratch2,
3517                                            Register scratch3,
3518                                            Label* gc_required) {
3519   DCHECK(!AreAliased(result, length, scratch1, scratch2, scratch3));
3520   // Calculate the number of bytes needed for the characters in the string while
3521   // observing object alignment.
3522   STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
3523   Add(scratch1, length, length);  // Length in bytes, not chars.
3524   Add(scratch1, scratch1, kObjectAlignmentMask + SeqTwoByteString::kHeaderSize);
3525   Bic(scratch1, scratch1, kObjectAlignmentMask);
3526
3527   // Allocate two-byte string in new space.
3528   Allocate(scratch1,
3529            result,
3530            scratch2,
3531            scratch3,
3532            gc_required,
3533            TAG_OBJECT);
3534
3535   // Set the map, length and hash field.
3536   InitializeNewString(result,
3537                       length,
3538                       Heap::kStringMapRootIndex,
3539                       scratch1,
3540                       scratch2);
3541 }
3542
3543
3544 void MacroAssembler::AllocateOneByteString(Register result, Register length,
3545                                            Register scratch1, Register scratch2,
3546                                            Register scratch3,
3547                                            Label* gc_required) {
3548   DCHECK(!AreAliased(result, length, scratch1, scratch2, scratch3));
3549   // Calculate the number of bytes needed for the characters in the string while
3550   // observing object alignment.
3551   STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
3552   STATIC_ASSERT(kCharSize == 1);
3553   Add(scratch1, length, kObjectAlignmentMask + SeqOneByteString::kHeaderSize);
3554   Bic(scratch1, scratch1, kObjectAlignmentMask);
3555
3556   // Allocate one-byte string in new space.
3557   Allocate(scratch1,
3558            result,
3559            scratch2,
3560            scratch3,
3561            gc_required,
3562            TAG_OBJECT);
3563
3564   // Set the map, length and hash field.
3565   InitializeNewString(result, length, Heap::kOneByteStringMapRootIndex,
3566                       scratch1, scratch2);
3567 }
3568
3569
3570 void MacroAssembler::AllocateTwoByteConsString(Register result,
3571                                                Register length,
3572                                                Register scratch1,
3573                                                Register scratch2,
3574                                                Label* gc_required) {
3575   Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
3576            TAG_OBJECT);
3577
3578   InitializeNewString(result,
3579                       length,
3580                       Heap::kConsStringMapRootIndex,
3581                       scratch1,
3582                       scratch2);
3583 }
3584
3585
3586 void MacroAssembler::AllocateOneByteConsString(Register result, Register length,
3587                                                Register scratch1,
3588                                                Register scratch2,
3589                                                Label* gc_required) {
3590   Allocate(ConsString::kSize,
3591            result,
3592            scratch1,
3593            scratch2,
3594            gc_required,
3595            TAG_OBJECT);
3596
3597   InitializeNewString(result, length, Heap::kConsOneByteStringMapRootIndex,
3598                       scratch1, scratch2);
3599 }
3600
3601
3602 void MacroAssembler::AllocateTwoByteSlicedString(Register result,
3603                                                  Register length,
3604                                                  Register scratch1,
3605                                                  Register scratch2,
3606                                                  Label* gc_required) {
3607   DCHECK(!AreAliased(result, length, scratch1, scratch2));
3608   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
3609            TAG_OBJECT);
3610
3611   InitializeNewString(result,
3612                       length,
3613                       Heap::kSlicedStringMapRootIndex,
3614                       scratch1,
3615                       scratch2);
3616 }
3617
3618
3619 void MacroAssembler::AllocateOneByteSlicedString(Register result,
3620                                                  Register length,
3621                                                  Register scratch1,
3622                                                  Register scratch2,
3623                                                  Label* gc_required) {
3624   DCHECK(!AreAliased(result, length, scratch1, scratch2));
3625   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
3626            TAG_OBJECT);
3627
3628   InitializeNewString(result, length, Heap::kSlicedOneByteStringMapRootIndex,
3629                       scratch1, scratch2);
3630 }
3631
3632
3633 // Allocates a heap number or jumps to the need_gc label if the young space
3634 // is full and a scavenge is needed.
3635 void MacroAssembler::AllocateHeapNumber(Register result,
3636                                         Label* gc_required,
3637                                         Register scratch1,
3638                                         Register scratch2,
3639                                         CPURegister value,
3640                                         CPURegister heap_number_map,
3641                                         MutableMode mode) {
3642   DCHECK(!value.IsValid() || value.Is64Bits());
3643   UseScratchRegisterScope temps(this);
3644
3645   // Allocate an object in the heap for the heap number and tag it as a heap
3646   // object.
3647   Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
3648            NO_ALLOCATION_FLAGS);
3649
3650   Heap::RootListIndex map_index = mode == MUTABLE
3651       ? Heap::kMutableHeapNumberMapRootIndex
3652       : Heap::kHeapNumberMapRootIndex;
3653
3654   // Prepare the heap number map.
3655   if (!heap_number_map.IsValid()) {
3656     // If we have a valid value register, use the same type of register to store
3657     // the map so we can use STP to store both in one instruction.
3658     if (value.IsValid() && value.IsFPRegister()) {
3659       heap_number_map = temps.AcquireD();
3660     } else {
3661       heap_number_map = scratch1;
3662     }
3663     LoadRoot(heap_number_map, map_index);
3664   }
3665   if (emit_debug_code()) {
3666     Register map;
3667     if (heap_number_map.IsFPRegister()) {
3668       map = scratch1;
3669       Fmov(map, DoubleRegister(heap_number_map));
3670     } else {
3671       map = Register(heap_number_map);
3672     }
3673     AssertRegisterIsRoot(map, map_index);
3674   }
3675
3676   // Store the heap number map and the value in the allocated object.
3677   if (value.IsSameSizeAndType(heap_number_map)) {
3678     STATIC_ASSERT(HeapObject::kMapOffset + kPointerSize ==
3679                   HeapNumber::kValueOffset);
3680     Stp(heap_number_map, value, MemOperand(result, HeapObject::kMapOffset));
3681   } else {
3682     Str(heap_number_map, MemOperand(result, HeapObject::kMapOffset));
3683     if (value.IsValid()) {
3684       Str(value, MemOperand(result, HeapNumber::kValueOffset));
3685     }
3686   }
3687   ObjectTag(result, result);
3688 }
3689
3690
3691 void MacroAssembler::JumpIfObjectType(Register object,
3692                                       Register map,
3693                                       Register type_reg,
3694                                       InstanceType type,
3695                                       Label* if_cond_pass,
3696                                       Condition cond) {
3697   CompareObjectType(object, map, type_reg, type);
3698   B(cond, if_cond_pass);
3699 }
3700
3701
3702 void MacroAssembler::JumpIfNotObjectType(Register object,
3703                                          Register map,
3704                                          Register type_reg,
3705                                          InstanceType type,
3706                                          Label* if_not_object) {
3707   JumpIfObjectType(object, map, type_reg, type, if_not_object, ne);
3708 }
3709
3710
3711 // Sets condition flags based on comparison, and returns type in type_reg.
3712 void MacroAssembler::CompareObjectType(Register object,
3713                                        Register map,
3714                                        Register type_reg,
3715                                        InstanceType type) {
3716   Ldr(map, FieldMemOperand(object, HeapObject::kMapOffset));
3717   CompareInstanceType(map, type_reg, type);
3718 }
3719
3720
3721 // Sets condition flags based on comparison, and returns type in type_reg.
3722 void MacroAssembler::CompareInstanceType(Register map,
3723                                          Register type_reg,
3724                                          InstanceType type) {
3725   Ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
3726   Cmp(type_reg, type);
3727 }
3728
3729
3730 void MacroAssembler::CompareObjectMap(Register obj, Heap::RootListIndex index) {
3731   UseScratchRegisterScope temps(this);
3732   Register obj_map = temps.AcquireX();
3733   Ldr(obj_map, FieldMemOperand(obj, HeapObject::kMapOffset));
3734   CompareRoot(obj_map, index);
3735 }
3736
3737
3738 void MacroAssembler::CompareObjectMap(Register obj, Register scratch,
3739                                       Handle<Map> map) {
3740   Ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
3741   CompareMap(scratch, map);
3742 }
3743
3744
3745 void MacroAssembler::CompareMap(Register obj_map,
3746                                 Handle<Map> map) {
3747   Cmp(obj_map, Operand(map));
3748 }
3749
3750
3751 void MacroAssembler::CheckMap(Register obj,
3752                               Register scratch,
3753                               Handle<Map> map,
3754                               Label* fail,
3755                               SmiCheckType smi_check_type) {
3756   if (smi_check_type == DO_SMI_CHECK) {
3757     JumpIfSmi(obj, fail);
3758   }
3759
3760   CompareObjectMap(obj, scratch, map);
3761   B(ne, fail);
3762 }
3763
3764
3765 void MacroAssembler::CheckMap(Register obj,
3766                               Register scratch,
3767                               Heap::RootListIndex index,
3768                               Label* fail,
3769                               SmiCheckType smi_check_type) {
3770   if (smi_check_type == DO_SMI_CHECK) {
3771     JumpIfSmi(obj, fail);
3772   }
3773   Ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
3774   JumpIfNotRoot(scratch, index, fail);
3775 }
3776
3777
3778 void MacroAssembler::CheckMap(Register obj_map,
3779                               Handle<Map> map,
3780                               Label* fail,
3781                               SmiCheckType smi_check_type) {
3782   if (smi_check_type == DO_SMI_CHECK) {
3783     JumpIfSmi(obj_map, fail);
3784   }
3785
3786   CompareMap(obj_map, map);
3787   B(ne, fail);
3788 }
3789
3790
3791 void MacroAssembler::DispatchMap(Register obj,
3792                                  Register scratch,
3793                                  Handle<Map> map,
3794                                  Handle<Code> success,
3795                                  SmiCheckType smi_check_type) {
3796   Label fail;
3797   if (smi_check_type == DO_SMI_CHECK) {
3798     JumpIfSmi(obj, &fail);
3799   }
3800   Ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
3801   Cmp(scratch, Operand(map));
3802   B(ne, &fail);
3803   Jump(success, RelocInfo::CODE_TARGET);
3804   Bind(&fail);
3805 }
3806
3807
3808 void MacroAssembler::TestMapBitfield(Register object, uint64_t mask) {
3809   UseScratchRegisterScope temps(this);
3810   Register temp = temps.AcquireX();
3811   Ldr(temp, FieldMemOperand(object, HeapObject::kMapOffset));
3812   Ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset));
3813   Tst(temp, mask);
3814 }
3815
3816
3817 void MacroAssembler::LoadElementsKindFromMap(Register result, Register map) {
3818   // Load the map's "bit field 2".
3819   __ Ldrb(result, FieldMemOperand(map, Map::kBitField2Offset));
3820   // Retrieve elements_kind from bit field 2.
3821   DecodeField<Map::ElementsKindBits>(result);
3822 }
3823
3824
3825 void MacroAssembler::TryGetFunctionPrototype(Register function,
3826                                              Register result,
3827                                              Register scratch,
3828                                              Label* miss,
3829                                              BoundFunctionAction action) {
3830   DCHECK(!AreAliased(function, result, scratch));
3831
3832   Label non_instance;
3833   if (action == kMissOnBoundFunction) {
3834     // Check that the receiver isn't a smi.
3835     JumpIfSmi(function, miss);
3836
3837     // Check that the function really is a function. Load map into result reg.
3838     JumpIfNotObjectType(function, result, scratch, JS_FUNCTION_TYPE, miss);
3839
3840     Register scratch_w = scratch.W();
3841     Ldr(scratch,
3842         FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
3843     // On 64-bit platforms, compiler hints field is not a smi. See definition of
3844     // kCompilerHintsOffset in src/objects.h.
3845     Ldr(scratch_w,
3846         FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
3847     Tbnz(scratch, SharedFunctionInfo::kBoundFunction, miss);
3848
3849     // Make sure that the function has an instance prototype.
3850     Ldrb(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
3851     Tbnz(scratch, Map::kHasNonInstancePrototype, &non_instance);
3852   }
3853
3854   // Get the prototype or initial map from the function.
3855   Ldr(result,
3856       FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
3857
3858   // If the prototype or initial map is the hole, don't return it and simply
3859   // miss the cache instead. This will allow us to allocate a prototype object
3860   // on-demand in the runtime system.
3861   JumpIfRoot(result, Heap::kTheHoleValueRootIndex, miss);
3862
3863   // If the function does not have an initial map, we're done.
3864   Label done;
3865   JumpIfNotObjectType(result, scratch, scratch, MAP_TYPE, &done);
3866
3867   // Get the prototype from the initial map.
3868   Ldr(result, FieldMemOperand(result, Map::kPrototypeOffset));
3869
3870   if (action == kMissOnBoundFunction) {
3871     B(&done);
3872
3873     // Non-instance prototype: fetch prototype from constructor field in initial
3874     // map.
3875     Bind(&non_instance);
3876     Ldr(result, FieldMemOperand(result, Map::kConstructorOffset));
3877   }
3878
3879   // All done.
3880   Bind(&done);
3881 }
3882
3883
3884 void MacroAssembler::CompareRoot(const Register& obj,
3885                                  Heap::RootListIndex index) {
3886   UseScratchRegisterScope temps(this);
3887   Register temp = temps.AcquireX();
3888   DCHECK(!AreAliased(obj, temp));
3889   LoadRoot(temp, index);
3890   Cmp(obj, temp);
3891 }
3892
3893
3894 void MacroAssembler::JumpIfRoot(const Register& obj,
3895                                 Heap::RootListIndex index,
3896                                 Label* if_equal) {
3897   CompareRoot(obj, index);
3898   B(eq, if_equal);
3899 }
3900
3901
3902 void MacroAssembler::JumpIfNotRoot(const Register& obj,
3903                                    Heap::RootListIndex index,
3904                                    Label* if_not_equal) {
3905   CompareRoot(obj, index);
3906   B(ne, if_not_equal);
3907 }
3908
3909
3910 void MacroAssembler::CompareAndSplit(const Register& lhs,
3911                                      const Operand& rhs,
3912                                      Condition cond,
3913                                      Label* if_true,
3914                                      Label* if_false,
3915                                      Label* fall_through) {
3916   if ((if_true == if_false) && (if_false == fall_through)) {
3917     // Fall through.
3918   } else if (if_true == if_false) {
3919     B(if_true);
3920   } else if (if_false == fall_through) {
3921     CompareAndBranch(lhs, rhs, cond, if_true);
3922   } else if (if_true == fall_through) {
3923     CompareAndBranch(lhs, rhs, NegateCondition(cond), if_false);
3924   } else {
3925     CompareAndBranch(lhs, rhs, cond, if_true);
3926     B(if_false);
3927   }
3928 }
3929
3930
3931 void MacroAssembler::TestAndSplit(const Register& reg,
3932                                   uint64_t bit_pattern,
3933                                   Label* if_all_clear,
3934                                   Label* if_any_set,
3935                                   Label* fall_through) {
3936   if ((if_all_clear == if_any_set) && (if_any_set == fall_through)) {
3937     // Fall through.
3938   } else if (if_all_clear == if_any_set) {
3939     B(if_all_clear);
3940   } else if (if_all_clear == fall_through) {
3941     TestAndBranchIfAnySet(reg, bit_pattern, if_any_set);
3942   } else if (if_any_set == fall_through) {
3943     TestAndBranchIfAllClear(reg, bit_pattern, if_all_clear);
3944   } else {
3945     TestAndBranchIfAnySet(reg, bit_pattern, if_any_set);
3946     B(if_all_clear);
3947   }
3948 }
3949
3950
3951 void MacroAssembler::CheckFastElements(Register map,
3952                                        Register scratch,
3953                                        Label* fail) {
3954   STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
3955   STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
3956   STATIC_ASSERT(FAST_ELEMENTS == 2);
3957   STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
3958   Ldrb(scratch, FieldMemOperand(map, Map::kBitField2Offset));
3959   Cmp(scratch, Map::kMaximumBitField2FastHoleyElementValue);
3960   B(hi, fail);
3961 }
3962
3963
3964 void MacroAssembler::CheckFastObjectElements(Register map,
3965                                              Register scratch,
3966                                              Label* fail) {
3967   STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
3968   STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
3969   STATIC_ASSERT(FAST_ELEMENTS == 2);
3970   STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
3971   Ldrb(scratch, FieldMemOperand(map, Map::kBitField2Offset));
3972   Cmp(scratch, Operand(Map::kMaximumBitField2FastHoleySmiElementValue));
3973   // If cond==ls, set cond=hi, otherwise compare.
3974   Ccmp(scratch,
3975        Operand(Map::kMaximumBitField2FastHoleyElementValue), CFlag, hi);
3976   B(hi, fail);
3977 }
3978
3979
3980 // Note: The ARM version of this clobbers elements_reg, but this version does
3981 // not. Some uses of this in ARM64 assume that elements_reg will be preserved.
3982 void MacroAssembler::StoreNumberToDoubleElements(Register value_reg,
3983                                                  Register key_reg,
3984                                                  Register elements_reg,
3985                                                  Register scratch1,
3986                                                  FPRegister fpscratch1,
3987                                                  Label* fail,
3988                                                  int elements_offset) {
3989   DCHECK(!AreAliased(value_reg, key_reg, elements_reg, scratch1));
3990   Label store_num;
3991
3992   // Speculatively convert the smi to a double - all smis can be exactly
3993   // represented as a double.
3994   SmiUntagToDouble(fpscratch1, value_reg, kSpeculativeUntag);
3995
3996   // If value_reg is a smi, we're done.
3997   JumpIfSmi(value_reg, &store_num);
3998
3999   // Ensure that the object is a heap number.
4000   JumpIfNotHeapNumber(value_reg, fail);
4001
4002   Ldr(fpscratch1, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
4003
4004   // Canonicalize NaNs.
4005   CanonicalizeNaN(fpscratch1);
4006
4007   // Store the result.
4008   Bind(&store_num);
4009   Add(scratch1, elements_reg,
4010       Operand::UntagSmiAndScale(key_reg, kDoubleSizeLog2));
4011   Str(fpscratch1,
4012       FieldMemOperand(scratch1,
4013                       FixedDoubleArray::kHeaderSize - elements_offset));
4014 }
4015
4016
4017 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
4018   return has_frame_ || !stub->SometimesSetsUpAFrame();
4019 }
4020
4021
4022 void MacroAssembler::IndexFromHash(Register hash, Register index) {
4023   // If the hash field contains an array index pick it out. The assert checks
4024   // that the constants for the maximum number of digits for an array index
4025   // cached in the hash field and the number of bits reserved for it does not
4026   // conflict.
4027   DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
4028          (1 << String::kArrayIndexValueBits));
4029   DecodeField<String::ArrayIndexValueBits>(index, hash);
4030   SmiTag(index, index);
4031 }
4032
4033
4034 void MacroAssembler::EmitSeqStringSetCharCheck(
4035     Register string,
4036     Register index,
4037     SeqStringSetCharCheckIndexType index_type,
4038     Register scratch,
4039     uint32_t encoding_mask) {
4040   DCHECK(!AreAliased(string, index, scratch));
4041
4042   if (index_type == kIndexIsSmi) {
4043     AssertSmi(index);
4044   }
4045
4046   // Check that string is an object.
4047   AssertNotSmi(string, kNonObject);
4048
4049   // Check that string has an appropriate map.
4050   Ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset));
4051   Ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
4052
4053   And(scratch, scratch, kStringRepresentationMask | kStringEncodingMask);
4054   Cmp(scratch, encoding_mask);
4055   Check(eq, kUnexpectedStringType);
4056
4057   Ldr(scratch, FieldMemOperand(string, String::kLengthOffset));
4058   Cmp(index, index_type == kIndexIsSmi ? scratch : Operand::UntagSmi(scratch));
4059   Check(lt, kIndexIsTooLarge);
4060
4061   DCHECK_EQ(0, Smi::FromInt(0));
4062   Cmp(index, 0);
4063   Check(ge, kIndexIsNegative);
4064 }
4065
4066
4067 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
4068                                             Register scratch1,
4069                                             Register scratch2,
4070                                             Label* miss) {
4071   DCHECK(!AreAliased(holder_reg, scratch1, scratch2));
4072   Label same_contexts;
4073
4074   // Load current lexical context from the stack frame.
4075   Ldr(scratch1, MemOperand(fp, StandardFrameConstants::kContextOffset));
4076   // In debug mode, make sure the lexical context is set.
4077 #ifdef DEBUG
4078   Cmp(scratch1, 0);
4079   Check(ne, kWeShouldNotHaveAnEmptyLexicalContext);
4080 #endif
4081
4082   // Load the native context of the current context.
4083   int offset =
4084       Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
4085   Ldr(scratch1, FieldMemOperand(scratch1, offset));
4086   Ldr(scratch1, FieldMemOperand(scratch1, GlobalObject::kNativeContextOffset));
4087
4088   // Check the context is a native context.
4089   if (emit_debug_code()) {
4090     // Read the first word and compare to the global_context_map.
4091     Ldr(scratch2, FieldMemOperand(scratch1, HeapObject::kMapOffset));
4092     CompareRoot(scratch2, Heap::kNativeContextMapRootIndex);
4093     Check(eq, kExpectedNativeContext);
4094   }
4095
4096   // Check if both contexts are the same.
4097   Ldr(scratch2, FieldMemOperand(holder_reg,
4098                                 JSGlobalProxy::kNativeContextOffset));
4099   Cmp(scratch1, scratch2);
4100   B(&same_contexts, eq);
4101
4102   // Check the context is a native context.
4103   if (emit_debug_code()) {
4104     // We're short on scratch registers here, so use holder_reg as a scratch.
4105     Push(holder_reg);
4106     Register scratch3 = holder_reg;
4107
4108     CompareRoot(scratch2, Heap::kNullValueRootIndex);
4109     Check(ne, kExpectedNonNullContext);
4110
4111     Ldr(scratch3, FieldMemOperand(scratch2, HeapObject::kMapOffset));
4112     CompareRoot(scratch3, Heap::kNativeContextMapRootIndex);
4113     Check(eq, kExpectedNativeContext);
4114     Pop(holder_reg);
4115   }
4116
4117   // Check that the security token in the calling global object is
4118   // compatible with the security token in the receiving global
4119   // object.
4120   int token_offset = Context::kHeaderSize +
4121                      Context::SECURITY_TOKEN_INDEX * kPointerSize;
4122
4123   Ldr(scratch1, FieldMemOperand(scratch1, token_offset));
4124   Ldr(scratch2, FieldMemOperand(scratch2, token_offset));
4125   Cmp(scratch1, scratch2);
4126   B(miss, ne);
4127
4128   Bind(&same_contexts);
4129 }
4130
4131
4132 // Compute the hash code from the untagged key. This must be kept in sync with
4133 // ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
4134 // code-stub-hydrogen.cc
4135 void MacroAssembler::GetNumberHash(Register key, Register scratch) {
4136   DCHECK(!AreAliased(key, scratch));
4137
4138   // Xor original key with a seed.
4139   LoadRoot(scratch, Heap::kHashSeedRootIndex);
4140   Eor(key, key, Operand::UntagSmi(scratch));
4141
4142   // The algorithm uses 32-bit integer values.
4143   key = key.W();
4144   scratch = scratch.W();
4145
4146   // Compute the hash code from the untagged key.  This must be kept in sync
4147   // with ComputeIntegerHash in utils.h.
4148   //
4149   // hash = ~hash + (hash <<1 15);
4150   Mvn(scratch, key);
4151   Add(key, scratch, Operand(key, LSL, 15));
4152   // hash = hash ^ (hash >> 12);
4153   Eor(key, key, Operand(key, LSR, 12));
4154   // hash = hash + (hash << 2);
4155   Add(key, key, Operand(key, LSL, 2));
4156   // hash = hash ^ (hash >> 4);
4157   Eor(key, key, Operand(key, LSR, 4));
4158   // hash = hash * 2057;
4159   Mov(scratch, Operand(key, LSL, 11));
4160   Add(key, key, Operand(key, LSL, 3));
4161   Add(key, key, scratch);
4162   // hash = hash ^ (hash >> 16);
4163   Eor(key, key, Operand(key, LSR, 16));
4164 }
4165
4166
4167 void MacroAssembler::LoadFromNumberDictionary(Label* miss,
4168                                               Register elements,
4169                                               Register key,
4170                                               Register result,
4171                                               Register scratch0,
4172                                               Register scratch1,
4173                                               Register scratch2,
4174                                               Register scratch3) {
4175   DCHECK(!AreAliased(elements, key, scratch0, scratch1, scratch2, scratch3));
4176
4177   Label done;
4178
4179   SmiUntag(scratch0, key);
4180   GetNumberHash(scratch0, scratch1);
4181
4182   // Compute the capacity mask.
4183   Ldrsw(scratch1,
4184         UntagSmiFieldMemOperand(elements,
4185                                 SeededNumberDictionary::kCapacityOffset));
4186   Sub(scratch1, scratch1, 1);
4187
4188   // Generate an unrolled loop that performs a few probes before giving up.
4189   for (int i = 0; i < kNumberDictionaryProbes; i++) {
4190     // Compute the masked index: (hash + i + i * i) & mask.
4191     if (i > 0) {
4192       Add(scratch2, scratch0, SeededNumberDictionary::GetProbeOffset(i));
4193     } else {
4194       Mov(scratch2, scratch0);
4195     }
4196     And(scratch2, scratch2, scratch1);
4197
4198     // Scale the index by multiplying by the element size.
4199     DCHECK(SeededNumberDictionary::kEntrySize == 3);
4200     Add(scratch2, scratch2, Operand(scratch2, LSL, 1));
4201
4202     // Check if the key is identical to the name.
4203     Add(scratch2, elements, Operand(scratch2, LSL, kPointerSizeLog2));
4204     Ldr(scratch3,
4205         FieldMemOperand(scratch2,
4206                         SeededNumberDictionary::kElementsStartOffset));
4207     Cmp(key, scratch3);
4208     if (i != (kNumberDictionaryProbes - 1)) {
4209       B(eq, &done);
4210     } else {
4211       B(ne, miss);
4212     }
4213   }
4214
4215   Bind(&done);
4216   // Check that the value is a normal property.
4217   const int kDetailsOffset =
4218       SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
4219   Ldrsw(scratch1, UntagSmiFieldMemOperand(scratch2, kDetailsOffset));
4220   TestAndBranchIfAnySet(scratch1, PropertyDetails::TypeField::kMask, miss);
4221
4222   // Get the value at the masked, scaled index and return.
4223   const int kValueOffset =
4224       SeededNumberDictionary::kElementsStartOffset + kPointerSize;
4225   Ldr(result, FieldMemOperand(scratch2, kValueOffset));
4226 }
4227
4228
4229 void MacroAssembler::RememberedSetHelper(Register object,  // For debug tests.
4230                                          Register address,
4231                                          Register scratch1,
4232                                          SaveFPRegsMode fp_mode,
4233                                          RememberedSetFinalAction and_then) {
4234   DCHECK(!AreAliased(object, address, scratch1));
4235   Label done, store_buffer_overflow;
4236   if (emit_debug_code()) {
4237     Label ok;
4238     JumpIfNotInNewSpace(object, &ok);
4239     Abort(kRememberedSetPointerInNewSpace);
4240     bind(&ok);
4241   }
4242   UseScratchRegisterScope temps(this);
4243   Register scratch2 = temps.AcquireX();
4244
4245   // Load store buffer top.
4246   Mov(scratch2, ExternalReference::store_buffer_top(isolate()));
4247   Ldr(scratch1, MemOperand(scratch2));
4248   // Store pointer to buffer and increment buffer top.
4249   Str(address, MemOperand(scratch1, kPointerSize, PostIndex));
4250   // Write back new top of buffer.
4251   Str(scratch1, MemOperand(scratch2));
4252   // Call stub on end of buffer.
4253   // Check for end of buffer.
4254   DCHECK(StoreBuffer::kStoreBufferOverflowBit ==
4255          (1 << (14 + kPointerSizeLog2)));
4256   if (and_then == kFallThroughAtEnd) {
4257     Tbz(scratch1, (14 + kPointerSizeLog2), &done);
4258   } else {
4259     DCHECK(and_then == kReturnAtEnd);
4260     Tbnz(scratch1, (14 + kPointerSizeLog2), &store_buffer_overflow);
4261     Ret();
4262   }
4263
4264   Bind(&store_buffer_overflow);
4265   Push(lr);
4266   StoreBufferOverflowStub store_buffer_overflow_stub(isolate(), fp_mode);
4267   CallStub(&store_buffer_overflow_stub);
4268   Pop(lr);
4269
4270   Bind(&done);
4271   if (and_then == kReturnAtEnd) {
4272     Ret();
4273   }
4274 }
4275
4276
4277 void MacroAssembler::PopSafepointRegisters() {
4278   const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
4279   PopXRegList(kSafepointSavedRegisters);
4280   Drop(num_unsaved);
4281 }
4282
4283
4284 void MacroAssembler::PushSafepointRegisters() {
4285   // Safepoints expect a block of kNumSafepointRegisters values on the stack, so
4286   // adjust the stack for unsaved registers.
4287   const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
4288   DCHECK(num_unsaved >= 0);
4289   Claim(num_unsaved);
4290   PushXRegList(kSafepointSavedRegisters);
4291 }
4292
4293
4294 void MacroAssembler::PushSafepointRegistersAndDoubles() {
4295   PushSafepointRegisters();
4296   PushCPURegList(CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
4297                             FPRegister::kAllocatableFPRegisters));
4298 }
4299
4300
4301 void MacroAssembler::PopSafepointRegistersAndDoubles() {
4302   PopCPURegList(CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
4303                            FPRegister::kAllocatableFPRegisters));
4304   PopSafepointRegisters();
4305 }
4306
4307
4308 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
4309   // Make sure the safepoint registers list is what we expect.
4310   DCHECK(CPURegList::GetSafepointSavedRegisters().list() == 0x6ffcffff);
4311
4312   // Safepoint registers are stored contiguously on the stack, but not all the
4313   // registers are saved. The following registers are excluded:
4314   //  - x16 and x17 (ip0 and ip1) because they shouldn't be preserved outside of
4315   //    the macro assembler.
4316   //  - x28 (jssp) because JS stack pointer doesn't need to be included in
4317   //    safepoint registers.
4318   //  - x31 (csp) because the system stack pointer doesn't need to be included
4319   //    in safepoint registers.
4320   //
4321   // This function implements the mapping of register code to index into the
4322   // safepoint register slots.
4323   if ((reg_code >= 0) && (reg_code <= 15)) {
4324     return reg_code;
4325   } else if ((reg_code >= 18) && (reg_code <= 27)) {
4326     // Skip ip0 and ip1.
4327     return reg_code - 2;
4328   } else if ((reg_code == 29) || (reg_code == 30)) {
4329     // Also skip jssp.
4330     return reg_code - 3;
4331   } else {
4332     // This register has no safepoint register slot.
4333     UNREACHABLE();
4334     return -1;
4335   }
4336 }
4337
4338
4339 void MacroAssembler::CheckPageFlagSet(const Register& object,
4340                                       const Register& scratch,
4341                                       int mask,
4342                                       Label* if_any_set) {
4343   And(scratch, object, ~Page::kPageAlignmentMask);
4344   Ldr(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset));
4345   TestAndBranchIfAnySet(scratch, mask, if_any_set);
4346 }
4347
4348
4349 void MacroAssembler::CheckPageFlagClear(const Register& object,
4350                                         const Register& scratch,
4351                                         int mask,
4352                                         Label* if_all_clear) {
4353   And(scratch, object, ~Page::kPageAlignmentMask);
4354   Ldr(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset));
4355   TestAndBranchIfAllClear(scratch, mask, if_all_clear);
4356 }
4357
4358
4359 void MacroAssembler::RecordWriteField(
4360     Register object,
4361     int offset,
4362     Register value,
4363     Register scratch,
4364     LinkRegisterStatus lr_status,
4365     SaveFPRegsMode save_fp,
4366     RememberedSetAction remembered_set_action,
4367     SmiCheck smi_check,
4368     PointersToHereCheck pointers_to_here_check_for_value) {
4369   // First, check if a write barrier is even needed. The tests below
4370   // catch stores of Smis.
4371   Label done;
4372
4373   // Skip the barrier if writing a smi.
4374   if (smi_check == INLINE_SMI_CHECK) {
4375     JumpIfSmi(value, &done);
4376   }
4377
4378   // Although the object register is tagged, the offset is relative to the start
4379   // of the object, so offset must be a multiple of kPointerSize.
4380   DCHECK(IsAligned(offset, kPointerSize));
4381
4382   Add(scratch, object, offset - kHeapObjectTag);
4383   if (emit_debug_code()) {
4384     Label ok;
4385     Tst(scratch, (1 << kPointerSizeLog2) - 1);
4386     B(eq, &ok);
4387     Abort(kUnalignedCellInWriteBarrier);
4388     Bind(&ok);
4389   }
4390
4391   RecordWrite(object,
4392               scratch,
4393               value,
4394               lr_status,
4395               save_fp,
4396               remembered_set_action,
4397               OMIT_SMI_CHECK,
4398               pointers_to_here_check_for_value);
4399
4400   Bind(&done);
4401
4402   // Clobber clobbered input registers when running with the debug-code flag
4403   // turned on to provoke errors.
4404   if (emit_debug_code()) {
4405     Mov(value, Operand(bit_cast<int64_t>(kZapValue + 4)));
4406     Mov(scratch, Operand(bit_cast<int64_t>(kZapValue + 8)));
4407   }
4408 }
4409
4410
4411 // Will clobber: object, map, dst.
4412 // If lr_status is kLRHasBeenSaved, lr will also be clobbered.
4413 void MacroAssembler::RecordWriteForMap(Register object,
4414                                        Register map,
4415                                        Register dst,
4416                                        LinkRegisterStatus lr_status,
4417                                        SaveFPRegsMode fp_mode) {
4418   ASM_LOCATION("MacroAssembler::RecordWrite");
4419   DCHECK(!AreAliased(object, map));
4420
4421   if (emit_debug_code()) {
4422     UseScratchRegisterScope temps(this);
4423     Register temp = temps.AcquireX();
4424
4425     CompareObjectMap(map, temp, isolate()->factory()->meta_map());
4426     Check(eq, kWrongAddressOrValuePassedToRecordWrite);
4427   }
4428
4429   if (!FLAG_incremental_marking) {
4430     return;
4431   }
4432
4433   if (emit_debug_code()) {
4434     UseScratchRegisterScope temps(this);
4435     Register temp = temps.AcquireX();
4436
4437     Ldr(temp, FieldMemOperand(object, HeapObject::kMapOffset));
4438     Cmp(temp, map);
4439     Check(eq, kWrongAddressOrValuePassedToRecordWrite);
4440   }
4441
4442   // First, check if a write barrier is even needed. The tests below
4443   // catch stores of smis and stores into the young generation.
4444   Label done;
4445
4446   // A single check of the map's pages interesting flag suffices, since it is
4447   // only set during incremental collection, and then it's also guaranteed that
4448   // the from object's page's interesting flag is also set.  This optimization
4449   // relies on the fact that maps can never be in new space.
4450   CheckPageFlagClear(map,
4451                      map,  // Used as scratch.
4452                      MemoryChunk::kPointersToHereAreInterestingMask,
4453                      &done);
4454
4455   // Record the actual write.
4456   if (lr_status == kLRHasNotBeenSaved) {
4457     Push(lr);
4458   }
4459   Add(dst, object, HeapObject::kMapOffset - kHeapObjectTag);
4460   RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET,
4461                        fp_mode);
4462   CallStub(&stub);
4463   if (lr_status == kLRHasNotBeenSaved) {
4464     Pop(lr);
4465   }
4466
4467   Bind(&done);
4468
4469   // Count number of write barriers in generated code.
4470   isolate()->counters()->write_barriers_static()->Increment();
4471   IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1, map,
4472                    dst);
4473
4474   // Clobber clobbered registers when running with the debug-code flag
4475   // turned on to provoke errors.
4476   if (emit_debug_code()) {
4477     Mov(dst, Operand(bit_cast<int64_t>(kZapValue + 12)));
4478     Mov(map, Operand(bit_cast<int64_t>(kZapValue + 16)));
4479   }
4480 }
4481
4482
4483 // Will clobber: object, address, value.
4484 // If lr_status is kLRHasBeenSaved, lr will also be clobbered.
4485 //
4486 // The register 'object' contains a heap object pointer. The heap object tag is
4487 // shifted away.
4488 void MacroAssembler::RecordWrite(
4489     Register object,
4490     Register address,
4491     Register value,
4492     LinkRegisterStatus lr_status,
4493     SaveFPRegsMode fp_mode,
4494     RememberedSetAction remembered_set_action,
4495     SmiCheck smi_check,
4496     PointersToHereCheck pointers_to_here_check_for_value) {
4497   ASM_LOCATION("MacroAssembler::RecordWrite");
4498   DCHECK(!AreAliased(object, value));
4499
4500   if (emit_debug_code()) {
4501     UseScratchRegisterScope temps(this);
4502     Register temp = temps.AcquireX();
4503
4504     Ldr(temp, MemOperand(address));
4505     Cmp(temp, value);
4506     Check(eq, kWrongAddressOrValuePassedToRecordWrite);
4507   }
4508
4509   // First, check if a write barrier is even needed. The tests below
4510   // catch stores of smis and stores into the young generation.
4511   Label done;
4512
4513   if (smi_check == INLINE_SMI_CHECK) {
4514     DCHECK_EQ(0, kSmiTag);
4515     JumpIfSmi(value, &done);
4516   }
4517
4518   if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
4519     CheckPageFlagClear(value,
4520                        value,  // Used as scratch.
4521                        MemoryChunk::kPointersToHereAreInterestingMask,
4522                        &done);
4523   }
4524   CheckPageFlagClear(object,
4525                      value,  // Used as scratch.
4526                      MemoryChunk::kPointersFromHereAreInterestingMask,
4527                      &done);
4528
4529   // Record the actual write.
4530   if (lr_status == kLRHasNotBeenSaved) {
4531     Push(lr);
4532   }
4533   RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
4534                        fp_mode);
4535   CallStub(&stub);
4536   if (lr_status == kLRHasNotBeenSaved) {
4537     Pop(lr);
4538   }
4539
4540   Bind(&done);
4541
4542   // Count number of write barriers in generated code.
4543   isolate()->counters()->write_barriers_static()->Increment();
4544   IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1, address,
4545                    value);
4546
4547   // Clobber clobbered registers when running with the debug-code flag
4548   // turned on to provoke errors.
4549   if (emit_debug_code()) {
4550     Mov(address, Operand(bit_cast<int64_t>(kZapValue + 12)));
4551     Mov(value, Operand(bit_cast<int64_t>(kZapValue + 16)));
4552   }
4553 }
4554
4555
4556 void MacroAssembler::AssertHasValidColor(const Register& reg) {
4557   if (emit_debug_code()) {
4558     // The bit sequence is backward. The first character in the string
4559     // represents the least significant bit.
4560     DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
4561
4562     Label color_is_valid;
4563     Tbnz(reg, 0, &color_is_valid);
4564     Tbz(reg, 1, &color_is_valid);
4565     Abort(kUnexpectedColorFound);
4566     Bind(&color_is_valid);
4567   }
4568 }
4569
4570
4571 void MacroAssembler::GetMarkBits(Register addr_reg,
4572                                  Register bitmap_reg,
4573                                  Register shift_reg) {
4574   DCHECK(!AreAliased(addr_reg, bitmap_reg, shift_reg));
4575   DCHECK(addr_reg.Is64Bits() && bitmap_reg.Is64Bits() && shift_reg.Is64Bits());
4576   // addr_reg is divided into fields:
4577   // |63        page base        20|19    high      8|7   shift   3|2  0|
4578   // 'high' gives the index of the cell holding color bits for the object.
4579   // 'shift' gives the offset in the cell for this object's color.
4580   const int kShiftBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2;
4581   UseScratchRegisterScope temps(this);
4582   Register temp = temps.AcquireX();
4583   Ubfx(temp, addr_reg, kShiftBits, kPageSizeBits - kShiftBits);
4584   Bic(bitmap_reg, addr_reg, Page::kPageAlignmentMask);
4585   Add(bitmap_reg, bitmap_reg, Operand(temp, LSL, Bitmap::kBytesPerCellLog2));
4586   // bitmap_reg:
4587   // |63        page base        20|19 zeros 15|14      high      3|2  0|
4588   Ubfx(shift_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2);
4589 }
4590
4591
4592 void MacroAssembler::HasColor(Register object,
4593                               Register bitmap_scratch,
4594                               Register shift_scratch,
4595                               Label* has_color,
4596                               int first_bit,
4597                               int second_bit) {
4598   // See mark-compact.h for color definitions.
4599   DCHECK(!AreAliased(object, bitmap_scratch, shift_scratch));
4600
4601   GetMarkBits(object, bitmap_scratch, shift_scratch);
4602   Ldr(bitmap_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
4603   // Shift the bitmap down to get the color of the object in bits [1:0].
4604   Lsr(bitmap_scratch, bitmap_scratch, shift_scratch);
4605
4606   AssertHasValidColor(bitmap_scratch);
4607
4608   // These bit sequences are backwards. The first character in the string
4609   // represents the least significant bit.
4610   DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
4611   DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0);
4612   DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0);
4613
4614   // Check for the color.
4615   if (first_bit == 0) {
4616     // Checking for white.
4617     DCHECK(second_bit == 0);
4618     // We only need to test the first bit.
4619     Tbz(bitmap_scratch, 0, has_color);
4620   } else {
4621     Label other_color;
4622     // Checking for grey or black.
4623     Tbz(bitmap_scratch, 0, &other_color);
4624     if (second_bit == 0) {
4625       Tbz(bitmap_scratch, 1, has_color);
4626     } else {
4627       Tbnz(bitmap_scratch, 1, has_color);
4628     }
4629     Bind(&other_color);
4630   }
4631
4632   // Fall through if it does not have the right color.
4633 }
4634
4635
4636 void MacroAssembler::CheckMapDeprecated(Handle<Map> map,
4637                                         Register scratch,
4638                                         Label* if_deprecated) {
4639   if (map->CanBeDeprecated()) {
4640     Mov(scratch, Operand(map));
4641     Ldrsw(scratch, FieldMemOperand(scratch, Map::kBitField3Offset));
4642     TestAndBranchIfAnySet(scratch, Map::Deprecated::kMask, if_deprecated);
4643   }
4644 }
4645
4646
4647 void MacroAssembler::JumpIfBlack(Register object,
4648                                  Register scratch0,
4649                                  Register scratch1,
4650                                  Label* on_black) {
4651   DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0);
4652   HasColor(object, scratch0, scratch1, on_black, 1, 0);  // kBlackBitPattern.
4653 }
4654
4655
4656 void MacroAssembler::JumpIfDictionaryInPrototypeChain(
4657     Register object,
4658     Register scratch0,
4659     Register scratch1,
4660     Label* found) {
4661   DCHECK(!AreAliased(object, scratch0, scratch1));
4662   Factory* factory = isolate()->factory();
4663   Register current = scratch0;
4664   Label loop_again;
4665
4666   // Scratch contains elements pointer.
4667   Mov(current, object);
4668
4669   // Loop based on the map going up the prototype chain.
4670   Bind(&loop_again);
4671   Ldr(current, FieldMemOperand(current, HeapObject::kMapOffset));
4672   Ldrb(scratch1, FieldMemOperand(current, Map::kBitField2Offset));
4673   DecodeField<Map::ElementsKindBits>(scratch1);
4674   CompareAndBranch(scratch1, DICTIONARY_ELEMENTS, eq, found);
4675   Ldr(current, FieldMemOperand(current, Map::kPrototypeOffset));
4676   CompareAndBranch(current, Operand(factory->null_value()), ne, &loop_again);
4677 }
4678
4679
4680 void MacroAssembler::GetRelocatedValueLocation(Register ldr_location,
4681                                                Register result) {
4682   DCHECK(!result.Is(ldr_location));
4683   const uint32_t kLdrLitOffset_lsb = 5;
4684   const uint32_t kLdrLitOffset_width = 19;
4685   Ldr(result, MemOperand(ldr_location));
4686   if (emit_debug_code()) {
4687     And(result, result, LoadLiteralFMask);
4688     Cmp(result, LoadLiteralFixed);
4689     Check(eq, kTheInstructionToPatchShouldBeAnLdrLiteral);
4690     // The instruction was clobbered. Reload it.
4691     Ldr(result, MemOperand(ldr_location));
4692   }
4693   Sbfx(result, result, kLdrLitOffset_lsb, kLdrLitOffset_width);
4694   Add(result, ldr_location, Operand(result, LSL, kWordSizeInBytesLog2));
4695 }
4696
4697
4698 void MacroAssembler::EnsureNotWhite(
4699     Register value,
4700     Register bitmap_scratch,
4701     Register shift_scratch,
4702     Register load_scratch,
4703     Register length_scratch,
4704     Label* value_is_white_and_not_data) {
4705   DCHECK(!AreAliased(
4706       value, bitmap_scratch, shift_scratch, load_scratch, length_scratch));
4707
4708   // These bit sequences are backwards. The first character in the string
4709   // represents the least significant bit.
4710   DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
4711   DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0);
4712   DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0);
4713
4714   GetMarkBits(value, bitmap_scratch, shift_scratch);
4715   Ldr(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
4716   Lsr(load_scratch, load_scratch, shift_scratch);
4717
4718   AssertHasValidColor(load_scratch);
4719
4720   // If the value is black or grey we don't need to do anything.
4721   // Since both black and grey have a 1 in the first position and white does
4722   // not have a 1 there we only need to check one bit.
4723   Label done;
4724   Tbnz(load_scratch, 0, &done);
4725
4726   // Value is white.  We check whether it is data that doesn't need scanning.
4727   Register map = load_scratch;  // Holds map while checking type.
4728   Label is_data_object;
4729
4730   // Check for heap-number.
4731   Ldr(map, FieldMemOperand(value, HeapObject::kMapOffset));
4732   Mov(length_scratch, HeapNumber::kSize);
4733   JumpIfRoot(map, Heap::kHeapNumberMapRootIndex, &is_data_object);
4734
4735   // Check for strings.
4736   DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
4737   DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
4738   // If it's a string and it's not a cons string then it's an object containing
4739   // no GC pointers.
4740   Register instance_type = load_scratch;
4741   Ldrb(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset));
4742   TestAndBranchIfAnySet(instance_type,
4743                         kIsIndirectStringMask | kIsNotStringMask,
4744                         value_is_white_and_not_data);
4745
4746   // It's a non-indirect (non-cons and non-slice) string.
4747   // If it's external, the length is just ExternalString::kSize.
4748   // Otherwise it's String::kHeaderSize + string->length() * (1 or 2).
4749   // External strings are the only ones with the kExternalStringTag bit
4750   // set.
4751   DCHECK_EQ(0, kSeqStringTag & kExternalStringTag);
4752   DCHECK_EQ(0, kConsStringTag & kExternalStringTag);
4753   Mov(length_scratch, ExternalString::kSize);
4754   TestAndBranchIfAnySet(instance_type, kExternalStringTag, &is_data_object);
4755
4756   // Sequential string, either Latin1 or UC16.
4757   // For Latin1 (char-size of 1) we shift the smi tag away to get the length.
4758   // For UC16 (char-size of 2) we just leave the smi tag in place, thereby
4759   // getting the length multiplied by 2.
4760   DCHECK(kOneByteStringTag == 4 && kStringEncodingMask == 4);
4761   Ldrsw(length_scratch, UntagSmiFieldMemOperand(value,
4762                                                 String::kLengthOffset));
4763   Tst(instance_type, kStringEncodingMask);
4764   Cset(load_scratch, eq);
4765   Lsl(length_scratch, length_scratch, load_scratch);
4766   Add(length_scratch,
4767       length_scratch,
4768       SeqString::kHeaderSize + kObjectAlignmentMask);
4769   Bic(length_scratch, length_scratch, kObjectAlignmentMask);
4770
4771   Bind(&is_data_object);
4772   // Value is a data object, and it is white.  Mark it black.  Since we know
4773   // that the object is white we can make it black by flipping one bit.
4774   Register mask = shift_scratch;
4775   Mov(load_scratch, 1);
4776   Lsl(mask, load_scratch, shift_scratch);
4777
4778   Ldr(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
4779   Orr(load_scratch, load_scratch, mask);
4780   Str(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
4781
4782   Bic(bitmap_scratch, bitmap_scratch, Page::kPageAlignmentMask);
4783   Ldr(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
4784   Add(load_scratch, load_scratch, length_scratch);
4785   Str(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
4786
4787   Bind(&done);
4788 }
4789
4790
4791 void MacroAssembler::Assert(Condition cond, BailoutReason reason) {
4792   if (emit_debug_code()) {
4793     Check(cond, reason);
4794   }
4795 }
4796
4797
4798
4799 void MacroAssembler::AssertRegisterIsClear(Register reg, BailoutReason reason) {
4800   if (emit_debug_code()) {
4801     CheckRegisterIsClear(reg, reason);
4802   }
4803 }
4804
4805
4806 void MacroAssembler::AssertRegisterIsRoot(Register reg,
4807                                           Heap::RootListIndex index,
4808                                           BailoutReason reason) {
4809   if (emit_debug_code()) {
4810     CompareRoot(reg, index);
4811     Check(eq, reason);
4812   }
4813 }
4814
4815
4816 void MacroAssembler::AssertFastElements(Register elements) {
4817   if (emit_debug_code()) {
4818     UseScratchRegisterScope temps(this);
4819     Register temp = temps.AcquireX();
4820     Label ok;
4821     Ldr(temp, FieldMemOperand(elements, HeapObject::kMapOffset));
4822     JumpIfRoot(temp, Heap::kFixedArrayMapRootIndex, &ok);
4823     JumpIfRoot(temp, Heap::kFixedDoubleArrayMapRootIndex, &ok);
4824     JumpIfRoot(temp, Heap::kFixedCOWArrayMapRootIndex, &ok);
4825     Abort(kJSObjectWithFastElementsMapHasSlowElements);
4826     Bind(&ok);
4827   }
4828 }
4829
4830
4831 void MacroAssembler::AssertIsString(const Register& object) {
4832   if (emit_debug_code()) {
4833     UseScratchRegisterScope temps(this);
4834     Register temp = temps.AcquireX();
4835     STATIC_ASSERT(kSmiTag == 0);
4836     Tst(object, kSmiTagMask);
4837     Check(ne, kOperandIsNotAString);
4838     Ldr(temp, FieldMemOperand(object, HeapObject::kMapOffset));
4839     CompareInstanceType(temp, temp, FIRST_NONSTRING_TYPE);
4840     Check(lo, kOperandIsNotAString);
4841   }
4842 }
4843
4844
4845 void MacroAssembler::Check(Condition cond, BailoutReason reason) {
4846   Label ok;
4847   B(cond, &ok);
4848   Abort(reason);
4849   // Will not return here.
4850   Bind(&ok);
4851 }
4852
4853
4854 void MacroAssembler::CheckRegisterIsClear(Register reg, BailoutReason reason) {
4855   Label ok;
4856   Cbz(reg, &ok);
4857   Abort(reason);
4858   // Will not return here.
4859   Bind(&ok);
4860 }
4861
4862
4863 void MacroAssembler::Abort(BailoutReason reason) {
4864 #ifdef DEBUG
4865   RecordComment("Abort message: ");
4866   RecordComment(GetBailoutReason(reason));
4867
4868   if (FLAG_trap_on_abort) {
4869     Brk(0);
4870     return;
4871   }
4872 #endif
4873
4874   // Abort is used in some contexts where csp is the stack pointer. In order to
4875   // simplify the CallRuntime code, make sure that jssp is the stack pointer.
4876   // There is no risk of register corruption here because Abort doesn't return.
4877   Register old_stack_pointer = StackPointer();
4878   SetStackPointer(jssp);
4879   Mov(jssp, old_stack_pointer);
4880
4881   // We need some scratch registers for the MacroAssembler, so make sure we have
4882   // some. This is safe here because Abort never returns.
4883   RegList old_tmp_list = TmpList()->list();
4884   TmpList()->Combine(MacroAssembler::DefaultTmpList());
4885
4886   if (use_real_aborts()) {
4887     // Avoid infinite recursion; Push contains some assertions that use Abort.
4888     NoUseRealAbortsScope no_real_aborts(this);
4889
4890     Mov(x0, Smi::FromInt(reason));
4891     Push(x0);
4892
4893     if (!has_frame_) {
4894       // We don't actually want to generate a pile of code for this, so just
4895       // claim there is a stack frame, without generating one.
4896       FrameScope scope(this, StackFrame::NONE);
4897       CallRuntime(Runtime::kAbort, 1);
4898     } else {
4899       CallRuntime(Runtime::kAbort, 1);
4900     }
4901   } else {
4902     // Load the string to pass to Printf.
4903     Label msg_address;
4904     Adr(x0, &msg_address);
4905
4906     // Call Printf directly to report the error.
4907     CallPrintf();
4908
4909     // We need a way to stop execution on both the simulator and real hardware,
4910     // and Unreachable() is the best option.
4911     Unreachable();
4912
4913     // Emit the message string directly in the instruction stream.
4914     {
4915       BlockPoolsScope scope(this);
4916       Bind(&msg_address);
4917       EmitStringData(GetBailoutReason(reason));
4918     }
4919   }
4920
4921   SetStackPointer(old_stack_pointer);
4922   TmpList()->set_list(old_tmp_list);
4923 }
4924
4925
4926 void MacroAssembler::LoadTransitionedArrayMapConditional(
4927     ElementsKind expected_kind,
4928     ElementsKind transitioned_kind,
4929     Register map_in_out,
4930     Register scratch1,
4931     Register scratch2,
4932     Label* no_map_match) {
4933   // Load the global or builtins object from the current context.
4934   Ldr(scratch1, GlobalObjectMemOperand());
4935   Ldr(scratch1, FieldMemOperand(scratch1, GlobalObject::kNativeContextOffset));
4936
4937   // Check that the function's map is the same as the expected cached map.
4938   Ldr(scratch1, ContextMemOperand(scratch1, Context::JS_ARRAY_MAPS_INDEX));
4939   size_t offset = (expected_kind * kPointerSize) + FixedArrayBase::kHeaderSize;
4940   Ldr(scratch2, FieldMemOperand(scratch1, offset));
4941   Cmp(map_in_out, scratch2);
4942   B(ne, no_map_match);
4943
4944   // Use the transitioned cached map.
4945   offset = (transitioned_kind * kPointerSize) + FixedArrayBase::kHeaderSize;
4946   Ldr(map_in_out, FieldMemOperand(scratch1, offset));
4947 }
4948
4949
4950 void MacroAssembler::LoadGlobalFunction(int index, Register function) {
4951   // Load the global or builtins object from the current context.
4952   Ldr(function, GlobalObjectMemOperand());
4953   // Load the native context from the global or builtins object.
4954   Ldr(function, FieldMemOperand(function,
4955                                 GlobalObject::kNativeContextOffset));
4956   // Load the function from the native context.
4957   Ldr(function, ContextMemOperand(function, index));
4958 }
4959
4960
4961 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
4962                                                   Register map,
4963                                                   Register scratch) {
4964   // Load the initial map. The global functions all have initial maps.
4965   Ldr(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
4966   if (emit_debug_code()) {
4967     Label ok, fail;
4968     CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
4969     B(&ok);
4970     Bind(&fail);
4971     Abort(kGlobalFunctionsMustHaveInitialMap);
4972     Bind(&ok);
4973   }
4974 }
4975
4976
4977 // This is the main Printf implementation. All other Printf variants call
4978 // PrintfNoPreserve after setting up one or more PreserveRegisterScopes.
4979 void MacroAssembler::PrintfNoPreserve(const char * format,
4980                                       const CPURegister& arg0,
4981                                       const CPURegister& arg1,
4982                                       const CPURegister& arg2,
4983                                       const CPURegister& arg3) {
4984   // We cannot handle a caller-saved stack pointer. It doesn't make much sense
4985   // in most cases anyway, so this restriction shouldn't be too serious.
4986   DCHECK(!kCallerSaved.IncludesAliasOf(__ StackPointer()));
4987
4988   // The provided arguments, and their proper procedure-call standard registers.
4989   CPURegister args[kPrintfMaxArgCount] = {arg0, arg1, arg2, arg3};
4990   CPURegister pcs[kPrintfMaxArgCount] = {NoReg, NoReg, NoReg, NoReg};
4991
4992   int arg_count = kPrintfMaxArgCount;
4993
4994   // The PCS varargs registers for printf. Note that x0 is used for the printf
4995   // format string.
4996   static const CPURegList kPCSVarargs =
4997       CPURegList(CPURegister::kRegister, kXRegSizeInBits, 1, arg_count);
4998   static const CPURegList kPCSVarargsFP =
4999       CPURegList(CPURegister::kFPRegister, kDRegSizeInBits, 0, arg_count - 1);
5000
5001   // We can use caller-saved registers as scratch values, except for the
5002   // arguments and the PCS registers where they might need to go.
5003   CPURegList tmp_list = kCallerSaved;
5004   tmp_list.Remove(x0);      // Used to pass the format string.
5005   tmp_list.Remove(kPCSVarargs);
5006   tmp_list.Remove(arg0, arg1, arg2, arg3);
5007
5008   CPURegList fp_tmp_list = kCallerSavedFP;
5009   fp_tmp_list.Remove(kPCSVarargsFP);
5010   fp_tmp_list.Remove(arg0, arg1, arg2, arg3);
5011
5012   // Override the MacroAssembler's scratch register list. The lists will be
5013   // reset automatically at the end of the UseScratchRegisterScope.
5014   UseScratchRegisterScope temps(this);
5015   TmpList()->set_list(tmp_list.list());
5016   FPTmpList()->set_list(fp_tmp_list.list());
5017
5018   // Copies of the printf vararg registers that we can pop from.
5019   CPURegList pcs_varargs = kPCSVarargs;
5020   CPURegList pcs_varargs_fp = kPCSVarargsFP;
5021
5022   // Place the arguments. There are lots of clever tricks and optimizations we
5023   // could use here, but Printf is a debug tool so instead we just try to keep
5024   // it simple: Move each input that isn't already in the right place to a
5025   // scratch register, then move everything back.
5026   for (unsigned i = 0; i < kPrintfMaxArgCount; i++) {
5027     // Work out the proper PCS register for this argument.
5028     if (args[i].IsRegister()) {
5029       pcs[i] = pcs_varargs.PopLowestIndex().X();
5030       // We might only need a W register here. We need to know the size of the
5031       // argument so we can properly encode it for the simulator call.
5032       if (args[i].Is32Bits()) pcs[i] = pcs[i].W();
5033     } else if (args[i].IsFPRegister()) {
5034       // In C, floats are always cast to doubles for varargs calls.
5035       pcs[i] = pcs_varargs_fp.PopLowestIndex().D();
5036     } else {
5037       DCHECK(args[i].IsNone());
5038       arg_count = i;
5039       break;
5040     }
5041
5042     // If the argument is already in the right place, leave it where it is.
5043     if (args[i].Aliases(pcs[i])) continue;
5044
5045     // Otherwise, if the argument is in a PCS argument register, allocate an
5046     // appropriate scratch register and then move it out of the way.
5047     if (kPCSVarargs.IncludesAliasOf(args[i]) ||
5048         kPCSVarargsFP.IncludesAliasOf(args[i])) {
5049       if (args[i].IsRegister()) {
5050         Register old_arg = Register(args[i]);
5051         Register new_arg = temps.AcquireSameSizeAs(old_arg);
5052         Mov(new_arg, old_arg);
5053         args[i] = new_arg;
5054       } else {
5055         FPRegister old_arg = FPRegister(args[i]);
5056         FPRegister new_arg = temps.AcquireSameSizeAs(old_arg);
5057         Fmov(new_arg, old_arg);
5058         args[i] = new_arg;
5059       }
5060     }
5061   }
5062
5063   // Do a second pass to move values into their final positions and perform any
5064   // conversions that may be required.
5065   for (int i = 0; i < arg_count; i++) {
5066     DCHECK(pcs[i].type() == args[i].type());
5067     if (pcs[i].IsRegister()) {
5068       Mov(Register(pcs[i]), Register(args[i]), kDiscardForSameWReg);
5069     } else {
5070       DCHECK(pcs[i].IsFPRegister());
5071       if (pcs[i].SizeInBytes() == args[i].SizeInBytes()) {
5072         Fmov(FPRegister(pcs[i]), FPRegister(args[i]));
5073       } else {
5074         Fcvt(FPRegister(pcs[i]), FPRegister(args[i]));
5075       }
5076     }
5077   }
5078
5079   // Load the format string into x0, as per the procedure-call standard.
5080   //
5081   // To make the code as portable as possible, the format string is encoded
5082   // directly in the instruction stream. It might be cleaner to encode it in a
5083   // literal pool, but since Printf is usually used for debugging, it is
5084   // beneficial for it to be minimally dependent on other features.
5085   Label format_address;
5086   Adr(x0, &format_address);
5087
5088   // Emit the format string directly in the instruction stream.
5089   { BlockPoolsScope scope(this);
5090     Label after_data;
5091     B(&after_data);
5092     Bind(&format_address);
5093     EmitStringData(format);
5094     Unreachable();
5095     Bind(&after_data);
5096   }
5097
5098   // We don't pass any arguments on the stack, but we still need to align the C
5099   // stack pointer to a 16-byte boundary for PCS compliance.
5100   if (!csp.Is(StackPointer())) {
5101     Bic(csp, StackPointer(), 0xf);
5102   }
5103
5104   CallPrintf(arg_count, pcs);
5105 }
5106
5107
5108 void MacroAssembler::CallPrintf(int arg_count, const CPURegister * args) {
5109   // A call to printf needs special handling for the simulator, since the system
5110   // printf function will use a different instruction set and the procedure-call
5111   // standard will not be compatible.
5112 #ifdef USE_SIMULATOR
5113   { InstructionAccurateScope scope(this, kPrintfLength / kInstructionSize);
5114     hlt(kImmExceptionIsPrintf);
5115     dc32(arg_count);          // kPrintfArgCountOffset
5116
5117     // Determine the argument pattern.
5118     uint32_t arg_pattern_list = 0;
5119     for (int i = 0; i < arg_count; i++) {
5120       uint32_t arg_pattern;
5121       if (args[i].IsRegister()) {
5122         arg_pattern = args[i].Is32Bits() ? kPrintfArgW : kPrintfArgX;
5123       } else {
5124         DCHECK(args[i].Is64Bits());
5125         arg_pattern = kPrintfArgD;
5126       }
5127       DCHECK(arg_pattern < (1 << kPrintfArgPatternBits));
5128       arg_pattern_list |= (arg_pattern << (kPrintfArgPatternBits * i));
5129     }
5130     dc32(arg_pattern_list);   // kPrintfArgPatternListOffset
5131   }
5132 #else
5133   Call(FUNCTION_ADDR(printf), RelocInfo::EXTERNAL_REFERENCE);
5134 #endif
5135 }
5136
5137
5138 void MacroAssembler::Printf(const char * format,
5139                             CPURegister arg0,
5140                             CPURegister arg1,
5141                             CPURegister arg2,
5142                             CPURegister arg3) {
5143   // We can only print sp if it is the current stack pointer.
5144   if (!csp.Is(StackPointer())) {
5145     DCHECK(!csp.Aliases(arg0));
5146     DCHECK(!csp.Aliases(arg1));
5147     DCHECK(!csp.Aliases(arg2));
5148     DCHECK(!csp.Aliases(arg3));
5149   }
5150
5151   // Printf is expected to preserve all registers, so make sure that none are
5152   // available as scratch registers until we've preserved them.
5153   RegList old_tmp_list = TmpList()->list();
5154   RegList old_fp_tmp_list = FPTmpList()->list();
5155   TmpList()->set_list(0);
5156   FPTmpList()->set_list(0);
5157
5158   // Preserve all caller-saved registers as well as NZCV.
5159   // If csp is the stack pointer, PushCPURegList asserts that the size of each
5160   // list is a multiple of 16 bytes.
5161   PushCPURegList(kCallerSaved);
5162   PushCPURegList(kCallerSavedFP);
5163
5164   // We can use caller-saved registers as scratch values (except for argN).
5165   CPURegList tmp_list = kCallerSaved;
5166   CPURegList fp_tmp_list = kCallerSavedFP;
5167   tmp_list.Remove(arg0, arg1, arg2, arg3);
5168   fp_tmp_list.Remove(arg0, arg1, arg2, arg3);
5169   TmpList()->set_list(tmp_list.list());
5170   FPTmpList()->set_list(fp_tmp_list.list());
5171
5172   { UseScratchRegisterScope temps(this);
5173     // If any of the arguments are the current stack pointer, allocate a new
5174     // register for them, and adjust the value to compensate for pushing the
5175     // caller-saved registers.
5176     bool arg0_sp = StackPointer().Aliases(arg0);
5177     bool arg1_sp = StackPointer().Aliases(arg1);
5178     bool arg2_sp = StackPointer().Aliases(arg2);
5179     bool arg3_sp = StackPointer().Aliases(arg3);
5180     if (arg0_sp || arg1_sp || arg2_sp || arg3_sp) {
5181       // Allocate a register to hold the original stack pointer value, to pass
5182       // to PrintfNoPreserve as an argument.
5183       Register arg_sp = temps.AcquireX();
5184       Add(arg_sp, StackPointer(),
5185           kCallerSaved.TotalSizeInBytes() + kCallerSavedFP.TotalSizeInBytes());
5186       if (arg0_sp) arg0 = Register::Create(arg_sp.code(), arg0.SizeInBits());
5187       if (arg1_sp) arg1 = Register::Create(arg_sp.code(), arg1.SizeInBits());
5188       if (arg2_sp) arg2 = Register::Create(arg_sp.code(), arg2.SizeInBits());
5189       if (arg3_sp) arg3 = Register::Create(arg_sp.code(), arg3.SizeInBits());
5190     }
5191
5192     // Preserve NZCV.
5193     { UseScratchRegisterScope temps(this);
5194       Register tmp = temps.AcquireX();
5195       Mrs(tmp, NZCV);
5196       Push(tmp, xzr);
5197     }
5198
5199     PrintfNoPreserve(format, arg0, arg1, arg2, arg3);
5200
5201     // Restore NZCV.
5202     { UseScratchRegisterScope temps(this);
5203       Register tmp = temps.AcquireX();
5204       Pop(xzr, tmp);
5205       Msr(NZCV, tmp);
5206     }
5207   }
5208
5209   PopCPURegList(kCallerSavedFP);
5210   PopCPURegList(kCallerSaved);
5211
5212   TmpList()->set_list(old_tmp_list);
5213   FPTmpList()->set_list(old_fp_tmp_list);
5214 }
5215
5216
5217 void MacroAssembler::EmitFrameSetupForCodeAgePatching() {
5218   // TODO(jbramley): Other architectures use the internal memcpy to copy the
5219   // sequence. If this is a performance bottleneck, we should consider caching
5220   // the sequence and copying it in the same way.
5221   InstructionAccurateScope scope(this,
5222                                  kNoCodeAgeSequenceLength / kInstructionSize);
5223   DCHECK(jssp.Is(StackPointer()));
5224   EmitFrameSetupForCodeAgePatching(this);
5225 }
5226
5227
5228
5229 void MacroAssembler::EmitCodeAgeSequence(Code* stub) {
5230   InstructionAccurateScope scope(this,
5231                                  kNoCodeAgeSequenceLength / kInstructionSize);
5232   DCHECK(jssp.Is(StackPointer()));
5233   EmitCodeAgeSequence(this, stub);
5234 }
5235
5236
5237 #undef __
5238 #define __ assm->
5239
5240
5241 void MacroAssembler::EmitFrameSetupForCodeAgePatching(Assembler * assm) {
5242   Label start;
5243   __ bind(&start);
5244
5245   // We can do this sequence using four instructions, but the code ageing
5246   // sequence that patches it needs five, so we use the extra space to try to
5247   // simplify some addressing modes and remove some dependencies (compared to
5248   // using two stp instructions with write-back).
5249   __ sub(jssp, jssp, 4 * kXRegSize);
5250   __ sub(csp, csp, 4 * kXRegSize);
5251   __ stp(x1, cp, MemOperand(jssp, 0 * kXRegSize));
5252   __ stp(fp, lr, MemOperand(jssp, 2 * kXRegSize));
5253   __ add(fp, jssp, StandardFrameConstants::kFixedFrameSizeFromFp);
5254
5255   __ AssertSizeOfCodeGeneratedSince(&start, kNoCodeAgeSequenceLength);
5256 }
5257
5258
5259 void MacroAssembler::EmitCodeAgeSequence(Assembler * assm,
5260                                          Code * stub) {
5261   Label start;
5262   __ bind(&start);
5263   // When the stub is called, the sequence is replaced with the young sequence
5264   // (as in EmitFrameSetupForCodeAgePatching). After the code is replaced, the
5265   // stub jumps to &start, stored in x0. The young sequence does not call the
5266   // stub so there is no infinite loop here.
5267   //
5268   // A branch (br) is used rather than a call (blr) because this code replaces
5269   // the frame setup code that would normally preserve lr.
5270   __ ldr_pcrel(ip0, kCodeAgeStubEntryOffset >> kLoadLiteralScaleLog2);
5271   __ adr(x0, &start);
5272   __ br(ip0);
5273   // IsCodeAgeSequence in codegen-arm64.cc assumes that the code generated up
5274   // until now (kCodeAgeStubEntryOffset) is the same for all code age sequences.
5275   __ AssertSizeOfCodeGeneratedSince(&start, kCodeAgeStubEntryOffset);
5276   if (stub) {
5277     __ dc64(reinterpret_cast<uint64_t>(stub->instruction_start()));
5278     __ AssertSizeOfCodeGeneratedSince(&start, kNoCodeAgeSequenceLength);
5279   }
5280 }
5281
5282
5283 bool MacroAssembler::IsYoungSequence(Isolate* isolate, byte* sequence) {
5284   bool is_young = isolate->code_aging_helper()->IsYoung(sequence);
5285   DCHECK(is_young ||
5286          isolate->code_aging_helper()->IsOld(sequence));
5287   return is_young;
5288 }
5289
5290
5291 void MacroAssembler::TruncatingDiv(Register result,
5292                                    Register dividend,
5293                                    int32_t divisor) {
5294   DCHECK(!AreAliased(result, dividend));
5295   DCHECK(result.Is32Bits() && dividend.Is32Bits());
5296   base::MagicNumbersForDivision<uint32_t> mag =
5297       base::SignedDivisionByConstant(static_cast<uint32_t>(divisor));
5298   Mov(result, mag.multiplier);
5299   Smull(result.X(), dividend, result);
5300   Asr(result.X(), result.X(), 32);
5301   bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0;
5302   if (divisor > 0 && neg) Add(result, result, dividend);
5303   if (divisor < 0 && !neg && mag.multiplier > 0) Sub(result, result, dividend);
5304   if (mag.shift > 0) Asr(result, result, mag.shift);
5305   Add(result, result, Operand(dividend, LSR, 31));
5306 }
5307
5308
5309 #undef __
5310
5311
5312 UseScratchRegisterScope::~UseScratchRegisterScope() {
5313   available_->set_list(old_available_);
5314   availablefp_->set_list(old_availablefp_);
5315 }
5316
5317
5318 Register UseScratchRegisterScope::AcquireSameSizeAs(const Register& reg) {
5319   int code = AcquireNextAvailable(available_).code();
5320   return Register::Create(code, reg.SizeInBits());
5321 }
5322
5323
5324 FPRegister UseScratchRegisterScope::AcquireSameSizeAs(const FPRegister& reg) {
5325   int code = AcquireNextAvailable(availablefp_).code();
5326   return FPRegister::Create(code, reg.SizeInBits());
5327 }
5328
5329
5330 CPURegister UseScratchRegisterScope::AcquireNextAvailable(
5331     CPURegList* available) {
5332   CHECK(!available->IsEmpty());
5333   CPURegister result = available->PopLowestIndex();
5334   DCHECK(!AreAliased(result, xzr, csp));
5335   return result;
5336 }
5337
5338
5339 CPURegister UseScratchRegisterScope::UnsafeAcquire(CPURegList* available,
5340                                                    const CPURegister& reg) {
5341   DCHECK(available->IncludesAliasOf(reg));
5342   available->Remove(reg);
5343   return reg;
5344 }
5345
5346
5347 #define __ masm->
5348
5349
5350 void InlineSmiCheckInfo::Emit(MacroAssembler* masm, const Register& reg,
5351                               const Label* smi_check) {
5352   Assembler::BlockPoolsScope scope(masm);
5353   if (reg.IsValid()) {
5354     DCHECK(smi_check->is_bound());
5355     DCHECK(reg.Is64Bits());
5356
5357     // Encode the register (x0-x30) in the lowest 5 bits, then the offset to
5358     // 'check' in the other bits. The possible offset is limited in that we
5359     // use BitField to pack the data, and the underlying data type is a
5360     // uint32_t.
5361     uint32_t delta = __ InstructionsGeneratedSince(smi_check);
5362     __ InlineData(RegisterBits::encode(reg.code()) | DeltaBits::encode(delta));
5363   } else {
5364     DCHECK(!smi_check->is_bound());
5365
5366     // An offset of 0 indicates that there is no patch site.
5367     __ InlineData(0);
5368   }
5369 }
5370
5371
5372 InlineSmiCheckInfo::InlineSmiCheckInfo(Address info)
5373     : reg_(NoReg), smi_check_(NULL) {
5374   InstructionSequence* inline_data = InstructionSequence::At(info);
5375   DCHECK(inline_data->IsInlineData());
5376   if (inline_data->IsInlineData()) {
5377     uint64_t payload = inline_data->InlineData();
5378     // We use BitField to decode the payload, and BitField can only handle
5379     // 32-bit values.
5380     DCHECK(is_uint32(payload));
5381     if (payload != 0) {
5382       int reg_code = RegisterBits::decode(payload);
5383       reg_ = Register::XRegFromCode(reg_code);
5384       uint64_t smi_check_delta = DeltaBits::decode(payload);
5385       DCHECK(smi_check_delta != 0);
5386       smi_check_ = inline_data->preceding(smi_check_delta);
5387     }
5388   }
5389 }
5390
5391
5392 #undef __
5393
5394
5395 } }  // namespace v8::internal
5396
5397 #endif  // V8_TARGET_ARCH_ARM64