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