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