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/base/bits.h"
16 #include "src/macro-assembler.h"
17 
18 namespace v8 {
19 namespace internal {
20 
21 
FieldMemOperand(Register object,int offset)22 MemOperand FieldMemOperand(Register object, int offset) {
23   return MemOperand(object, offset - kHeapObjectTag);
24 }
25 
26 
And(const Register & rd,const Register & rn,const Operand & operand)27 void TurboAssembler::And(const Register& rd, const Register& rn,
28                          const Operand& operand) {
29   DCHECK(allow_macro_instructions());
30   DCHECK(!rd.IsZero());
31   LogicalMacro(rd, rn, operand, AND);
32 }
33 
Ands(const Register & rd,const Register & rn,const Operand & operand)34 void TurboAssembler::Ands(const Register& rd, const Register& rn,
35                           const Operand& operand) {
36   DCHECK(allow_macro_instructions());
37   DCHECK(!rd.IsZero());
38   LogicalMacro(rd, rn, operand, ANDS);
39 }
40 
Tst(const Register & rn,const Operand & operand)41 void TurboAssembler::Tst(const Register& rn, const Operand& operand) {
42   DCHECK(allow_macro_instructions());
43   LogicalMacro(AppropriateZeroRegFor(rn), rn, operand, ANDS);
44 }
45 
Bic(const Register & rd,const Register & rn,const Operand & operand)46 void TurboAssembler::Bic(const Register& rd, const Register& rn,
47                          const Operand& operand) {
48   DCHECK(allow_macro_instructions());
49   DCHECK(!rd.IsZero());
50   LogicalMacro(rd, rn, operand, BIC);
51 }
52 
53 
Bics(const Register & rd,const Register & rn,const Operand & operand)54 void MacroAssembler::Bics(const Register& rd,
55                           const Register& rn,
56                           const Operand& operand) {
57   DCHECK(allow_macro_instructions());
58   DCHECK(!rd.IsZero());
59   LogicalMacro(rd, rn, operand, BICS);
60 }
61 
Orr(const Register & rd,const Register & rn,const Operand & operand)62 void TurboAssembler::Orr(const Register& rd, const Register& rn,
63                          const Operand& operand) {
64   DCHECK(allow_macro_instructions());
65   DCHECK(!rd.IsZero());
66   LogicalMacro(rd, rn, operand, ORR);
67 }
68 
Orn(const Register & rd,const Register & rn,const Operand & operand)69 void TurboAssembler::Orn(const Register& rd, const Register& rn,
70                          const Operand& operand) {
71   DCHECK(allow_macro_instructions());
72   DCHECK(!rd.IsZero());
73   LogicalMacro(rd, rn, operand, ORN);
74 }
75 
Eor(const Register & rd,const Register & rn,const Operand & operand)76 void TurboAssembler::Eor(const Register& rd, const Register& rn,
77                          const Operand& operand) {
78   DCHECK(allow_macro_instructions());
79   DCHECK(!rd.IsZero());
80   LogicalMacro(rd, rn, operand, EOR);
81 }
82 
Eon(const Register & rd,const Register & rn,const Operand & operand)83 void TurboAssembler::Eon(const Register& rd, const Register& rn,
84                          const Operand& operand) {
85   DCHECK(allow_macro_instructions());
86   DCHECK(!rd.IsZero());
87   LogicalMacro(rd, rn, operand, EON);
88 }
89 
Ccmp(const Register & rn,const Operand & operand,StatusFlags nzcv,Condition cond)90 void TurboAssembler::Ccmp(const Register& rn, const Operand& operand,
91                           StatusFlags nzcv, Condition cond) {
92   DCHECK(allow_macro_instructions());
93   if (operand.IsImmediate() && (operand.ImmediateValue() < 0)) {
94     ConditionalCompareMacro(rn, -operand.ImmediateValue(), nzcv, cond, CCMN);
95   } else {
96     ConditionalCompareMacro(rn, operand, nzcv, cond, CCMP);
97   }
98 }
99 
100 
Ccmn(const Register & rn,const Operand & operand,StatusFlags nzcv,Condition cond)101 void MacroAssembler::Ccmn(const Register& rn,
102                           const Operand& operand,
103                           StatusFlags nzcv,
104                           Condition cond) {
105   DCHECK(allow_macro_instructions());
106   if (operand.IsImmediate() && (operand.ImmediateValue() < 0)) {
107     ConditionalCompareMacro(rn, -operand.ImmediateValue(), nzcv, cond, CCMP);
108   } else {
109     ConditionalCompareMacro(rn, operand, nzcv, cond, CCMN);
110   }
111 }
112 
Add(const Register & rd,const Register & rn,const Operand & operand)113 void TurboAssembler::Add(const Register& rd, const Register& rn,
114                          const Operand& operand) {
115   DCHECK(allow_macro_instructions());
116   if (operand.IsImmediate() && (operand.ImmediateValue() < 0) &&
117       IsImmAddSub(-operand.ImmediateValue())) {
118     AddSubMacro(rd, rn, -operand.ImmediateValue(), LeaveFlags, SUB);
119   } else {
120     AddSubMacro(rd, rn, operand, LeaveFlags, ADD);
121   }
122 }
123 
Adds(const Register & rd,const Register & rn,const Operand & operand)124 void TurboAssembler::Adds(const Register& rd, const Register& rn,
125                           const Operand& operand) {
126   DCHECK(allow_macro_instructions());
127   if (operand.IsImmediate() && (operand.ImmediateValue() < 0) &&
128       IsImmAddSub(-operand.ImmediateValue())) {
129     AddSubMacro(rd, rn, -operand.ImmediateValue(), SetFlags, SUB);
130   } else {
131     AddSubMacro(rd, rn, operand, SetFlags, ADD);
132   }
133 }
134 
Sub(const Register & rd,const Register & rn,const Operand & operand)135 void TurboAssembler::Sub(const Register& rd, const Register& rn,
136                          const Operand& operand) {
137   DCHECK(allow_macro_instructions());
138   if (operand.IsImmediate() && (operand.ImmediateValue() < 0) &&
139       IsImmAddSub(-operand.ImmediateValue())) {
140     AddSubMacro(rd, rn, -operand.ImmediateValue(), LeaveFlags, ADD);
141   } else {
142     AddSubMacro(rd, rn, operand, LeaveFlags, SUB);
143   }
144 }
145 
Subs(const Register & rd,const Register & rn,const Operand & operand)146 void TurboAssembler::Subs(const Register& rd, const Register& rn,
147                           const Operand& operand) {
148   DCHECK(allow_macro_instructions());
149   if (operand.IsImmediate() && (operand.ImmediateValue() < 0) &&
150       IsImmAddSub(-operand.ImmediateValue())) {
151     AddSubMacro(rd, rn, -operand.ImmediateValue(), SetFlags, ADD);
152   } else {
153     AddSubMacro(rd, rn, operand, SetFlags, SUB);
154   }
155 }
156 
Cmn(const Register & rn,const Operand & operand)157 void TurboAssembler::Cmn(const Register& rn, const Operand& operand) {
158   DCHECK(allow_macro_instructions());
159   Adds(AppropriateZeroRegFor(rn), rn, operand);
160 }
161 
Cmp(const Register & rn,const Operand & operand)162 void TurboAssembler::Cmp(const Register& rn, const Operand& operand) {
163   DCHECK(allow_macro_instructions());
164   Subs(AppropriateZeroRegFor(rn), rn, operand);
165 }
166 
Neg(const Register & rd,const Operand & operand)167 void TurboAssembler::Neg(const Register& rd, const Operand& operand) {
168   DCHECK(allow_macro_instructions());
169   DCHECK(!rd.IsZero());
170   if (operand.IsImmediate()) {
171     Mov(rd, -operand.ImmediateValue());
172   } else {
173     Sub(rd, AppropriateZeroRegFor(rd), operand);
174   }
175 }
176 
Negs(const Register & rd,const Operand & operand)177 void TurboAssembler::Negs(const Register& rd, const Operand& operand) {
178   DCHECK(allow_macro_instructions());
179   Subs(rd, AppropriateZeroRegFor(rd), operand);
180 }
181 
Adc(const Register & rd,const Register & rn,const Operand & operand)182 void TurboAssembler::Adc(const Register& rd, const Register& rn,
183                          const Operand& operand) {
184   DCHECK(allow_macro_instructions());
185   DCHECK(!rd.IsZero());
186   AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, ADC);
187 }
188 
189 
Adcs(const Register & rd,const Register & rn,const Operand & operand)190 void MacroAssembler::Adcs(const Register& rd,
191                           const Register& rn,
192                           const Operand& operand) {
193   DCHECK(allow_macro_instructions());
194   DCHECK(!rd.IsZero());
195   AddSubWithCarryMacro(rd, rn, operand, SetFlags, ADC);
196 }
197 
198 
Sbc(const Register & rd,const Register & rn,const Operand & operand)199 void MacroAssembler::Sbc(const Register& rd,
200                          const Register& rn,
201                          const Operand& operand) {
202   DCHECK(allow_macro_instructions());
203   DCHECK(!rd.IsZero());
204   AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, SBC);
205 }
206 
207 
Sbcs(const Register & rd,const Register & rn,const Operand & operand)208 void MacroAssembler::Sbcs(const Register& rd,
209                           const Register& rn,
210                           const Operand& operand) {
211   DCHECK(allow_macro_instructions());
212   DCHECK(!rd.IsZero());
213   AddSubWithCarryMacro(rd, rn, operand, SetFlags, SBC);
214 }
215 
216 
Ngc(const Register & rd,const Operand & operand)217 void MacroAssembler::Ngc(const Register& rd,
218                          const Operand& operand) {
219   DCHECK(allow_macro_instructions());
220   DCHECK(!rd.IsZero());
221   Register zr = AppropriateZeroRegFor(rd);
222   Sbc(rd, zr, operand);
223 }
224 
225 
Ngcs(const Register & rd,const Operand & operand)226 void MacroAssembler::Ngcs(const Register& rd,
227                           const Operand& operand) {
228   DCHECK(allow_macro_instructions());
229   DCHECK(!rd.IsZero());
230   Register zr = AppropriateZeroRegFor(rd);
231   Sbcs(rd, zr, operand);
232 }
233 
Mvn(const Register & rd,uint64_t imm)234 void TurboAssembler::Mvn(const Register& rd, uint64_t imm) {
235   DCHECK(allow_macro_instructions());
236   DCHECK(!rd.IsZero());
237   Mov(rd, ~imm);
238 }
239 
240 #define DEFINE_FUNCTION(FN, REGTYPE, REG, OP)                          \
241   void TurboAssembler::FN(const REGTYPE REG, const MemOperand& addr) { \
242     DCHECK(allow_macro_instructions());                                \
243     LoadStoreMacro(REG, addr, OP);                                     \
244   }
245 LS_MACRO_LIST(DEFINE_FUNCTION)
246 #undef DEFINE_FUNCTION
247 
248 #define DEFINE_FUNCTION(FN, REGTYPE, REG, REG2, OP)              \
249   void TurboAssembler::FN(const REGTYPE REG, const REGTYPE REG2, \
250                           const MemOperand& addr) {              \
251     DCHECK(allow_macro_instructions());                          \
252     LoadStorePairMacro(REG, REG2, addr, OP);                     \
253   }
LSPAIR_MACRO_LIST(DEFINE_FUNCTION)254 LSPAIR_MACRO_LIST(DEFINE_FUNCTION)
255 #undef DEFINE_FUNCTION
256 
257 #define DECLARE_FUNCTION(FN, OP)                                    \
258   void TurboAssembler::FN(const Register& rt, const Register& rn) { \
259     DCHECK(allow_macro_instructions());                             \
260     OP(rt, rn);                                                     \
261   }
262 LDA_STL_MACRO_LIST(DECLARE_FUNCTION)
263 #undef DECLARE_FUNCTION
264 
265 #define DECLARE_FUNCTION(FN, OP)                                  \
266   void MacroAssembler::FN(const Register& rs, const Register& rt, \
267                           const Register& rn) {                   \
268     DCHECK(allow_macro_instructions());                           \
269     OP(rs, rt, rn);                                               \
270   }
271 STLX_MACRO_LIST(DECLARE_FUNCTION)
272 #undef DECLARE_FUNCTION
273 
274 void TurboAssembler::Asr(const Register& rd, const Register& rn,
275                          unsigned shift) {
276   DCHECK(allow_macro_instructions());
277   DCHECK(!rd.IsZero());
278   asr(rd, rn, shift);
279 }
280 
Asr(const Register & rd,const Register & rn,const Register & rm)281 void TurboAssembler::Asr(const Register& rd, const Register& rn,
282                          const Register& rm) {
283   DCHECK(allow_macro_instructions());
284   DCHECK(!rd.IsZero());
285   asrv(rd, rn, rm);
286 }
287 
B(Label * label)288 void TurboAssembler::B(Label* label) {
289   DCHECK(allow_macro_instructions());
290   b(label);
291   CheckVeneerPool(false, false);
292 }
293 
B(Condition cond,Label * label)294 void TurboAssembler::B(Condition cond, Label* label) {
295   DCHECK(allow_macro_instructions());
296   B(label, cond);
297 }
298 
Bfi(const Register & rd,const Register & rn,unsigned lsb,unsigned width)299 void TurboAssembler::Bfi(const Register& rd, const Register& rn, unsigned lsb,
300                          unsigned width) {
301   DCHECK(allow_macro_instructions());
302   DCHECK(!rd.IsZero());
303   bfi(rd, rn, lsb, width);
304 }
305 
306 
Bfxil(const Register & rd,const Register & rn,unsigned lsb,unsigned width)307 void MacroAssembler::Bfxil(const Register& rd,
308                            const Register& rn,
309                            unsigned lsb,
310                            unsigned width) {
311   DCHECK(allow_macro_instructions());
312   DCHECK(!rd.IsZero());
313   bfxil(rd, rn, lsb, width);
314 }
315 
Bind(Label * label)316 void TurboAssembler::Bind(Label* label) {
317   DCHECK(allow_macro_instructions());
318   bind(label);
319 }
320 
Bl(Label * label)321 void TurboAssembler::Bl(Label* label) {
322   DCHECK(allow_macro_instructions());
323   bl(label);
324 }
325 
Blr(const Register & xn)326 void TurboAssembler::Blr(const Register& xn) {
327   DCHECK(allow_macro_instructions());
328   DCHECK(!xn.IsZero());
329   blr(xn);
330 }
331 
Br(const Register & xn)332 void TurboAssembler::Br(const Register& xn) {
333   DCHECK(allow_macro_instructions());
334   DCHECK(!xn.IsZero());
335   br(xn);
336 }
337 
Brk(int code)338 void TurboAssembler::Brk(int code) {
339   DCHECK(allow_macro_instructions());
340   brk(code);
341 }
342 
343 
Cinc(const Register & rd,const Register & rn,Condition cond)344 void MacroAssembler::Cinc(const Register& rd,
345                           const Register& rn,
346                           Condition cond) {
347   DCHECK(allow_macro_instructions());
348   DCHECK(!rd.IsZero());
349   DCHECK((cond != al) && (cond != nv));
350   cinc(rd, rn, cond);
351 }
352 
353 
Cinv(const Register & rd,const Register & rn,Condition cond)354 void MacroAssembler::Cinv(const Register& rd,
355                           const Register& rn,
356                           Condition cond) {
357   DCHECK(allow_macro_instructions());
358   DCHECK(!rd.IsZero());
359   DCHECK((cond != al) && (cond != nv));
360   cinv(rd, rn, cond);
361 }
362 
Cls(const Register & rd,const Register & rn)363 void TurboAssembler::Cls(const Register& rd, const Register& rn) {
364   DCHECK(allow_macro_instructions());
365   DCHECK(!rd.IsZero());
366   cls(rd, rn);
367 }
368 
Clz(const Register & rd,const Register & rn)369 void TurboAssembler::Clz(const Register& rd, const Register& rn) {
370   DCHECK(allow_macro_instructions());
371   DCHECK(!rd.IsZero());
372   clz(rd, rn);
373 }
374 
Cneg(const Register & rd,const Register & rn,Condition cond)375 void TurboAssembler::Cneg(const Register& rd, const Register& rn,
376                           Condition cond) {
377   DCHECK(allow_macro_instructions());
378   DCHECK(!rd.IsZero());
379   DCHECK((cond != al) && (cond != nv));
380   cneg(rd, rn, cond);
381 }
382 
383 
384 // Conditionally zero the destination register. Only X registers are supported
385 // due to the truncation side-effect when used on W registers.
CzeroX(const Register & rd,Condition cond)386 void MacroAssembler::CzeroX(const Register& rd,
387                             Condition cond) {
388   DCHECK(allow_macro_instructions());
389   DCHECK(!rd.IsSP() && rd.Is64Bits());
390   DCHECK((cond != al) && (cond != nv));
391   csel(rd, xzr, rd, cond);
392 }
393 
394 
395 // Conditionally move a value into the destination register. Only X registers
396 // are supported due to the truncation side-effect when used on W registers.
CmovX(const Register & rd,const Register & rn,Condition cond)397 void TurboAssembler::CmovX(const Register& rd, const Register& rn,
398                            Condition cond) {
399   DCHECK(allow_macro_instructions());
400   DCHECK(!rd.IsSP());
401   DCHECK(rd.Is64Bits() && rn.Is64Bits());
402   DCHECK((cond != al) && (cond != nv));
403   if (!rd.is(rn)) {
404     csel(rd, rn, rd, cond);
405   }
406 }
407 
Csdb()408 void TurboAssembler::Csdb() {
409   DCHECK(allow_macro_instructions());
410   csdb();
411 }
412 
Cset(const Register & rd,Condition cond)413 void TurboAssembler::Cset(const Register& rd, Condition cond) {
414   DCHECK(allow_macro_instructions());
415   DCHECK(!rd.IsZero());
416   DCHECK((cond != al) && (cond != nv));
417   cset(rd, cond);
418 }
419 
Csetm(const Register & rd,Condition cond)420 void TurboAssembler::Csetm(const Register& rd, Condition cond) {
421   DCHECK(allow_macro_instructions());
422   DCHECK(!rd.IsZero());
423   DCHECK((cond != al) && (cond != nv));
424   csetm(rd, cond);
425 }
426 
Csinc(const Register & rd,const Register & rn,const Register & rm,Condition cond)427 void TurboAssembler::Csinc(const Register& rd, const Register& rn,
428                            const Register& rm, Condition cond) {
429   DCHECK(allow_macro_instructions());
430   DCHECK(!rd.IsZero());
431   DCHECK((cond != al) && (cond != nv));
432   csinc(rd, rn, rm, cond);
433 }
434 
435 
Csinv(const Register & rd,const Register & rn,const Register & rm,Condition cond)436 void MacroAssembler::Csinv(const Register& rd,
437                            const Register& rn,
438                            const Register& rm,
439                            Condition cond) {
440   DCHECK(allow_macro_instructions());
441   DCHECK(!rd.IsZero());
442   DCHECK((cond != al) && (cond != nv));
443   csinv(rd, rn, rm, cond);
444 }
445 
446 
Csneg(const Register & rd,const Register & rn,const Register & rm,Condition cond)447 void MacroAssembler::Csneg(const Register& rd,
448                            const Register& rn,
449                            const Register& rm,
450                            Condition cond) {
451   DCHECK(allow_macro_instructions());
452   DCHECK(!rd.IsZero());
453   DCHECK((cond != al) && (cond != nv));
454   csneg(rd, rn, rm, cond);
455 }
456 
Dmb(BarrierDomain domain,BarrierType type)457 void TurboAssembler::Dmb(BarrierDomain domain, BarrierType type) {
458   DCHECK(allow_macro_instructions());
459   dmb(domain, type);
460 }
461 
Dsb(BarrierDomain domain,BarrierType type)462 void TurboAssembler::Dsb(BarrierDomain domain, BarrierType type) {
463   DCHECK(allow_macro_instructions());
464   dsb(domain, type);
465 }
466 
Debug(const char * message,uint32_t code,Instr params)467 void TurboAssembler::Debug(const char* message, uint32_t code, Instr params) {
468   DCHECK(allow_macro_instructions());
469   debug(message, code, params);
470 }
471 
472 
Extr(const Register & rd,const Register & rn,const Register & rm,unsigned lsb)473 void MacroAssembler::Extr(const Register& rd,
474                           const Register& rn,
475                           const Register& rm,
476                           unsigned lsb) {
477   DCHECK(allow_macro_instructions());
478   DCHECK(!rd.IsZero());
479   extr(rd, rn, rm, lsb);
480 }
481 
Fabs(const VRegister & fd,const VRegister & fn)482 void TurboAssembler::Fabs(const VRegister& fd, const VRegister& fn) {
483   DCHECK(allow_macro_instructions());
484   fabs(fd, fn);
485 }
486 
Fadd(const VRegister & fd,const VRegister & fn,const VRegister & fm)487 void TurboAssembler::Fadd(const VRegister& fd, const VRegister& fn,
488                           const VRegister& fm) {
489   DCHECK(allow_macro_instructions());
490   fadd(fd, fn, fm);
491 }
492 
Fccmp(const VRegister & fn,const VRegister & fm,StatusFlags nzcv,Condition cond)493 void TurboAssembler::Fccmp(const VRegister& fn, const VRegister& fm,
494                            StatusFlags nzcv, Condition cond) {
495   DCHECK(allow_macro_instructions());
496   DCHECK((cond != al) && (cond != nv));
497   fccmp(fn, fm, nzcv, cond);
498 }
499 
Fcmp(const VRegister & fn,const VRegister & fm)500 void TurboAssembler::Fcmp(const VRegister& fn, const VRegister& fm) {
501   DCHECK(allow_macro_instructions());
502   fcmp(fn, fm);
503 }
504 
Fcmp(const VRegister & fn,double value)505 void TurboAssembler::Fcmp(const VRegister& fn, double value) {
506   DCHECK(allow_macro_instructions());
507   if (value != 0.0) {
508     UseScratchRegisterScope temps(this);
509     VRegister tmp = temps.AcquireSameSizeAs(fn);
510     Fmov(tmp, value);
511     fcmp(fn, tmp);
512   } else {
513     fcmp(fn, value);
514   }
515 }
516 
Fcsel(const VRegister & fd,const VRegister & fn,const VRegister & fm,Condition cond)517 void MacroAssembler::Fcsel(const VRegister& fd, const VRegister& fn,
518                            const VRegister& fm, Condition cond) {
519   DCHECK(allow_macro_instructions());
520   DCHECK((cond != al) && (cond != nv));
521   fcsel(fd, fn, fm, cond);
522 }
523 
Fcvt(const VRegister & fd,const VRegister & fn)524 void TurboAssembler::Fcvt(const VRegister& fd, const VRegister& fn) {
525   DCHECK(allow_macro_instructions());
526   fcvt(fd, fn);
527 }
528 
Fcvtas(const Register & rd,const VRegister & fn)529 void TurboAssembler::Fcvtas(const Register& rd, const VRegister& fn) {
530   DCHECK(allow_macro_instructions());
531   DCHECK(!rd.IsZero());
532   fcvtas(rd, fn);
533 }
534 
Fcvtau(const Register & rd,const VRegister & fn)535 void TurboAssembler::Fcvtau(const Register& rd, const VRegister& fn) {
536   DCHECK(allow_macro_instructions());
537   DCHECK(!rd.IsZero());
538   fcvtau(rd, fn);
539 }
540 
Fcvtms(const Register & rd,const VRegister & fn)541 void TurboAssembler::Fcvtms(const Register& rd, const VRegister& fn) {
542   DCHECK(allow_macro_instructions());
543   DCHECK(!rd.IsZero());
544   fcvtms(rd, fn);
545 }
546 
Fcvtmu(const Register & rd,const VRegister & fn)547 void TurboAssembler::Fcvtmu(const Register& rd, const VRegister& fn) {
548   DCHECK(allow_macro_instructions());
549   DCHECK(!rd.IsZero());
550   fcvtmu(rd, fn);
551 }
552 
Fcvtns(const Register & rd,const VRegister & fn)553 void TurboAssembler::Fcvtns(const Register& rd, const VRegister& fn) {
554   DCHECK(allow_macro_instructions());
555   DCHECK(!rd.IsZero());
556   fcvtns(rd, fn);
557 }
558 
Fcvtnu(const Register & rd,const VRegister & fn)559 void TurboAssembler::Fcvtnu(const Register& rd, const VRegister& fn) {
560   DCHECK(allow_macro_instructions());
561   DCHECK(!rd.IsZero());
562   fcvtnu(rd, fn);
563 }
564 
Fcvtzs(const Register & rd,const VRegister & fn)565 void TurboAssembler::Fcvtzs(const Register& rd, const VRegister& fn) {
566   DCHECK(allow_macro_instructions());
567   DCHECK(!rd.IsZero());
568   fcvtzs(rd, fn);
569 }
Fcvtzu(const Register & rd,const VRegister & fn)570 void TurboAssembler::Fcvtzu(const Register& rd, const VRegister& fn) {
571   DCHECK(allow_macro_instructions());
572   DCHECK(!rd.IsZero());
573   fcvtzu(rd, fn);
574 }
575 
Fdiv(const VRegister & fd,const VRegister & fn,const VRegister & fm)576 void TurboAssembler::Fdiv(const VRegister& fd, const VRegister& fn,
577                           const VRegister& fm) {
578   DCHECK(allow_macro_instructions());
579   fdiv(fd, fn, fm);
580 }
581 
Fmadd(const VRegister & fd,const VRegister & fn,const VRegister & fm,const VRegister & fa)582 void MacroAssembler::Fmadd(const VRegister& fd, const VRegister& fn,
583                            const VRegister& fm, const VRegister& fa) {
584   DCHECK(allow_macro_instructions());
585   fmadd(fd, fn, fm, fa);
586 }
587 
Fmax(const VRegister & fd,const VRegister & fn,const VRegister & fm)588 void TurboAssembler::Fmax(const VRegister& fd, const VRegister& fn,
589                           const VRegister& fm) {
590   DCHECK(allow_macro_instructions());
591   fmax(fd, fn, fm);
592 }
593 
Fmaxnm(const VRegister & fd,const VRegister & fn,const VRegister & fm)594 void MacroAssembler::Fmaxnm(const VRegister& fd, const VRegister& fn,
595                             const VRegister& fm) {
596   DCHECK(allow_macro_instructions());
597   fmaxnm(fd, fn, fm);
598 }
599 
Fmin(const VRegister & fd,const VRegister & fn,const VRegister & fm)600 void TurboAssembler::Fmin(const VRegister& fd, const VRegister& fn,
601                           const VRegister& fm) {
602   DCHECK(allow_macro_instructions());
603   fmin(fd, fn, fm);
604 }
605 
Fminnm(const VRegister & fd,const VRegister & fn,const VRegister & fm)606 void MacroAssembler::Fminnm(const VRegister& fd, const VRegister& fn,
607                             const VRegister& fm) {
608   DCHECK(allow_macro_instructions());
609   fminnm(fd, fn, fm);
610 }
611 
Fmov(VRegister fd,VRegister fn)612 void TurboAssembler::Fmov(VRegister fd, VRegister fn) {
613   DCHECK(allow_macro_instructions());
614   // Only emit an instruction if fd and fn are different, and they are both D
615   // registers. fmov(s0, s0) is not a no-op because it clears the top word of
616   // d0. Technically, fmov(d0, d0) is not a no-op either because it clears the
617   // top of q0, but VRegister does not currently support Q registers.
618   if (!fd.Is(fn) || !fd.Is64Bits()) {
619     fmov(fd, fn);
620   }
621 }
622 
Fmov(VRegister fd,Register rn)623 void TurboAssembler::Fmov(VRegister fd, Register rn) {
624   DCHECK(allow_macro_instructions());
625   fmov(fd, rn);
626 }
627 
Fmov(VRegister vd,double imm)628 void TurboAssembler::Fmov(VRegister vd, double imm) {
629   DCHECK(allow_macro_instructions());
630 
631   if (vd.Is1S() || vd.Is2S() || vd.Is4S()) {
632     Fmov(vd, static_cast<float>(imm));
633     return;
634   }
635 
636   DCHECK(vd.Is1D() || vd.Is2D());
637   if (IsImmFP64(imm)) {
638     fmov(vd, imm);
639   } else {
640     uint64_t bits = bit_cast<uint64_t>(imm);
641     if (vd.IsScalar()) {
642       if (bits == 0) {
643         fmov(vd, xzr);
644       } else {
645         UseScratchRegisterScope temps(this);
646         Register tmp = temps.AcquireX();
647         Mov(tmp, bits);
648         fmov(vd, tmp);
649       }
650     } else {
651       Movi(vd, bits);
652     }
653   }
654 }
655 
Fmov(VRegister vd,float imm)656 void TurboAssembler::Fmov(VRegister vd, float imm) {
657   DCHECK(allow_macro_instructions());
658   if (vd.Is1D() || vd.Is2D()) {
659     Fmov(vd, static_cast<double>(imm));
660     return;
661   }
662 
663   DCHECK(vd.Is1S() || vd.Is2S() || vd.Is4S());
664   if (IsImmFP32(imm)) {
665     fmov(vd, imm);
666   } else {
667     uint32_t bits = bit_cast<uint32_t>(imm);
668     if (vd.IsScalar()) {
669       if (bits == 0) {
670         fmov(vd, wzr);
671       } else {
672         UseScratchRegisterScope temps(this);
673         Register tmp = temps.AcquireW();
674         Mov(tmp, bit_cast<uint32_t>(imm));
675         Fmov(vd, tmp);
676       }
677     } else {
678       Movi(vd, bits);
679     }
680   }
681 }
682 
Fmov(Register rd,VRegister fn)683 void TurboAssembler::Fmov(Register rd, VRegister fn) {
684   DCHECK(allow_macro_instructions());
685   DCHECK(!rd.IsZero());
686   fmov(rd, fn);
687 }
688 
Fmsub(const VRegister & fd,const VRegister & fn,const VRegister & fm,const VRegister & fa)689 void MacroAssembler::Fmsub(const VRegister& fd, const VRegister& fn,
690                            const VRegister& fm, const VRegister& fa) {
691   DCHECK(allow_macro_instructions());
692   fmsub(fd, fn, fm, fa);
693 }
694 
Fmul(const VRegister & fd,const VRegister & fn,const VRegister & fm)695 void TurboAssembler::Fmul(const VRegister& fd, const VRegister& fn,
696                           const VRegister& fm) {
697   DCHECK(allow_macro_instructions());
698   fmul(fd, fn, fm);
699 }
700 
Fnmadd(const VRegister & fd,const VRegister & fn,const VRegister & fm,const VRegister & fa)701 void MacroAssembler::Fnmadd(const VRegister& fd, const VRegister& fn,
702                             const VRegister& fm, const VRegister& fa) {
703   DCHECK(allow_macro_instructions());
704   fnmadd(fd, fn, fm, fa);
705 }
706 
Fnmsub(const VRegister & fd,const VRegister & fn,const VRegister & fm,const VRegister & fa)707 void MacroAssembler::Fnmsub(const VRegister& fd, const VRegister& fn,
708                             const VRegister& fm, const VRegister& fa) {
709   DCHECK(allow_macro_instructions());
710   fnmsub(fd, fn, fm, fa);
711 }
712 
Fsub(const VRegister & fd,const VRegister & fn,const VRegister & fm)713 void TurboAssembler::Fsub(const VRegister& fd, const VRegister& fn,
714                           const VRegister& fm) {
715   DCHECK(allow_macro_instructions());
716   fsub(fd, fn, fm);
717 }
718 
719 
Hint(SystemHint code)720 void MacroAssembler::Hint(SystemHint code) {
721   DCHECK(allow_macro_instructions());
722   hint(code);
723 }
724 
725 
Hlt(int code)726 void MacroAssembler::Hlt(int code) {
727   DCHECK(allow_macro_instructions());
728   hlt(code);
729 }
730 
Isb()731 void TurboAssembler::Isb() {
732   DCHECK(allow_macro_instructions());
733   isb();
734 }
735 
Ldr(const CPURegister & rt,const Operand & operand)736 void TurboAssembler::Ldr(const CPURegister& rt, const Operand& operand) {
737   DCHECK(allow_macro_instructions());
738   ldr(rt, operand);
739 }
740 
Lsl(const Register & rd,const Register & rn,unsigned shift)741 void TurboAssembler::Lsl(const Register& rd, const Register& rn,
742                          unsigned shift) {
743   DCHECK(allow_macro_instructions());
744   DCHECK(!rd.IsZero());
745   lsl(rd, rn, shift);
746 }
747 
Lsl(const Register & rd,const Register & rn,const Register & rm)748 void TurboAssembler::Lsl(const Register& rd, const Register& rn,
749                          const Register& rm) {
750   DCHECK(allow_macro_instructions());
751   DCHECK(!rd.IsZero());
752   lslv(rd, rn, rm);
753 }
754 
Lsr(const Register & rd,const Register & rn,unsigned shift)755 void TurboAssembler::Lsr(const Register& rd, const Register& rn,
756                          unsigned shift) {
757   DCHECK(allow_macro_instructions());
758   DCHECK(!rd.IsZero());
759   lsr(rd, rn, shift);
760 }
761 
Lsr(const Register & rd,const Register & rn,const Register & rm)762 void TurboAssembler::Lsr(const Register& rd, const Register& rn,
763                          const Register& rm) {
764   DCHECK(allow_macro_instructions());
765   DCHECK(!rd.IsZero());
766   lsrv(rd, rn, rm);
767 }
768 
Madd(const Register & rd,const Register & rn,const Register & rm,const Register & ra)769 void TurboAssembler::Madd(const Register& rd, const Register& rn,
770                           const Register& rm, const Register& ra) {
771   DCHECK(allow_macro_instructions());
772   DCHECK(!rd.IsZero());
773   madd(rd, rn, rm, ra);
774 }
775 
Mneg(const Register & rd,const Register & rn,const Register & rm)776 void TurboAssembler::Mneg(const Register& rd, const Register& rn,
777                           const Register& rm) {
778   DCHECK(allow_macro_instructions());
779   DCHECK(!rd.IsZero());
780   mneg(rd, rn, rm);
781 }
782 
Movk(const Register & rd,uint64_t imm,int shift)783 void MacroAssembler::Movk(const Register& rd, uint64_t imm, int shift) {
784   DCHECK(allow_macro_instructions());
785   DCHECK(!rd.IsZero());
786   movk(rd, imm, shift);
787 }
788 
Mrs(const Register & rt,SystemRegister sysreg)789 void TurboAssembler::Mrs(const Register& rt, SystemRegister sysreg) {
790   DCHECK(allow_macro_instructions());
791   DCHECK(!rt.IsZero());
792   mrs(rt, sysreg);
793 }
794 
795 
Msr(SystemRegister sysreg,const Register & rt)796 void MacroAssembler::Msr(SystemRegister sysreg, const Register& rt) {
797   DCHECK(allow_macro_instructions());
798   msr(sysreg, rt);
799 }
800 
Msub(const Register & rd,const Register & rn,const Register & rm,const Register & ra)801 void TurboAssembler::Msub(const Register& rd, const Register& rn,
802                           const Register& rm, const Register& ra) {
803   DCHECK(allow_macro_instructions());
804   DCHECK(!rd.IsZero());
805   msub(rd, rn, rm, ra);
806 }
807 
Mul(const Register & rd,const Register & rn,const Register & rm)808 void TurboAssembler::Mul(const Register& rd, const Register& rn,
809                          const Register& rm) {
810   DCHECK(allow_macro_instructions());
811   DCHECK(!rd.IsZero());
812   mul(rd, rn, rm);
813 }
814 
Rbit(const Register & rd,const Register & rn)815 void TurboAssembler::Rbit(const Register& rd, const Register& rn) {
816   DCHECK(allow_macro_instructions());
817   DCHECK(!rd.IsZero());
818   rbit(rd, rn);
819 }
820 
Rev(const Register & rd,const Register & rn)821 void TurboAssembler::Rev(const Register& rd, const Register& rn) {
822   DCHECK(allow_macro_instructions());
823   DCHECK(!rd.IsZero());
824   rev(rd, rn);
825 }
826 
Ret(const Register & xn)827 void TurboAssembler::Ret(const Register& xn) {
828   DCHECK(allow_macro_instructions());
829   DCHECK(!xn.IsZero());
830   ret(xn);
831   CheckVeneerPool(false, false);
832 }
833 
834 
Rev(const Register & rd,const Register & rn)835 void MacroAssembler::Rev(const Register& rd, const Register& rn) {
836   DCHECK(allow_macro_instructions());
837   DCHECK(!rd.IsZero());
838   rev(rd, rn);
839 }
840 
Rev16(const Register & rd,const Register & rn)841 void TurboAssembler::Rev16(const Register& rd, const Register& rn) {
842   DCHECK(allow_macro_instructions());
843   DCHECK(!rd.IsZero());
844   rev16(rd, rn);
845 }
846 
Rev32(const Register & rd,const Register & rn)847 void TurboAssembler::Rev32(const Register& rd, const Register& rn) {
848   DCHECK(allow_macro_instructions());
849   DCHECK(!rd.IsZero());
850   rev32(rd, rn);
851 }
852 
Ror(const Register & rd,const Register & rs,unsigned shift)853 void TurboAssembler::Ror(const Register& rd, const Register& rs,
854                          unsigned shift) {
855   DCHECK(allow_macro_instructions());
856   DCHECK(!rd.IsZero());
857   ror(rd, rs, shift);
858 }
859 
Ror(const Register & rd,const Register & rn,const Register & rm)860 void TurboAssembler::Ror(const Register& rd, const Register& rn,
861                          const Register& rm) {
862   DCHECK(allow_macro_instructions());
863   DCHECK(!rd.IsZero());
864   rorv(rd, rn, rm);
865 }
866 
867 
Sbfiz(const Register & rd,const Register & rn,unsigned lsb,unsigned width)868 void MacroAssembler::Sbfiz(const Register& rd,
869                            const Register& rn,
870                            unsigned lsb,
871                            unsigned width) {
872   DCHECK(allow_macro_instructions());
873   DCHECK(!rd.IsZero());
874   sbfiz(rd, rn, lsb, width);
875 }
876 
Sbfx(const Register & rd,const Register & rn,unsigned lsb,unsigned width)877 void TurboAssembler::Sbfx(const Register& rd, const Register& rn, unsigned lsb,
878                           unsigned width) {
879   DCHECK(allow_macro_instructions());
880   DCHECK(!rd.IsZero());
881   sbfx(rd, rn, lsb, width);
882 }
883 
Scvtf(const VRegister & fd,const Register & rn,unsigned fbits)884 void TurboAssembler::Scvtf(const VRegister& fd, const Register& rn,
885                            unsigned fbits) {
886   DCHECK(allow_macro_instructions());
887   scvtf(fd, rn, fbits);
888 }
889 
Sdiv(const Register & rd,const Register & rn,const Register & rm)890 void TurboAssembler::Sdiv(const Register& rd, const Register& rn,
891                           const Register& rm) {
892   DCHECK(allow_macro_instructions());
893   DCHECK(!rd.IsZero());
894   sdiv(rd, rn, rm);
895 }
896 
897 
Smaddl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)898 void MacroAssembler::Smaddl(const Register& rd,
899                             const Register& rn,
900                             const Register& rm,
901                             const Register& ra) {
902   DCHECK(allow_macro_instructions());
903   DCHECK(!rd.IsZero());
904   smaddl(rd, rn, rm, ra);
905 }
906 
907 
Smsubl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)908 void MacroAssembler::Smsubl(const Register& rd,
909                             const Register& rn,
910                             const Register& rm,
911                             const Register& ra) {
912   DCHECK(allow_macro_instructions());
913   DCHECK(!rd.IsZero());
914   smsubl(rd, rn, rm, ra);
915 }
916 
Smull(const Register & rd,const Register & rn,const Register & rm)917 void TurboAssembler::Smull(const Register& rd, const Register& rn,
918                            const Register& rm) {
919   DCHECK(allow_macro_instructions());
920   DCHECK(!rd.IsZero());
921   smull(rd, rn, rm);
922 }
923 
924 
Smulh(const Register & rd,const Register & rn,const Register & rm)925 void MacroAssembler::Smulh(const Register& rd,
926                            const Register& rn,
927                            const Register& rm) {
928   DCHECK(allow_macro_instructions());
929   DCHECK(!rd.IsZero());
930   smulh(rd, rn, rm);
931 }
932 
Umull(const Register & rd,const Register & rn,const Register & rm)933 void TurboAssembler::Umull(const Register& rd, const Register& rn,
934                            const Register& rm) {
935   DCHECK(allow_macro_instructions());
936   DCHECK(!rd.IsZero());
937   umaddl(rd, rn, rm, xzr);
938 }
939 
Sxtb(const Register & rd,const Register & rn)940 void TurboAssembler::Sxtb(const Register& rd, const Register& rn) {
941   DCHECK(allow_macro_instructions());
942   DCHECK(!rd.IsZero());
943   sxtb(rd, rn);
944 }
945 
Sxth(const Register & rd,const Register & rn)946 void TurboAssembler::Sxth(const Register& rd, const Register& rn) {
947   DCHECK(allow_macro_instructions());
948   DCHECK(!rd.IsZero());
949   sxth(rd, rn);
950 }
951 
Sxtw(const Register & rd,const Register & rn)952 void TurboAssembler::Sxtw(const Register& rd, const Register& rn) {
953   DCHECK(allow_macro_instructions());
954   DCHECK(!rd.IsZero());
955   sxtw(rd, rn);
956 }
957 
Ubfiz(const Register & rd,const Register & rn,unsigned lsb,unsigned width)958 void TurboAssembler::Ubfiz(const Register& rd, const Register& rn, unsigned lsb,
959                            unsigned width) {
960   DCHECK(allow_macro_instructions());
961   DCHECK(!rd.IsZero());
962   ubfiz(rd, rn, lsb, width);
963 }
964 
Ubfx(const Register & rd,const Register & rn,unsigned lsb,unsigned width)965 void TurboAssembler::Ubfx(const Register& rd, const Register& rn, unsigned lsb,
966                           unsigned width) {
967   DCHECK(allow_macro_instructions());
968   DCHECK(!rd.IsZero());
969   ubfx(rd, rn, lsb, width);
970 }
971 
Ucvtf(const VRegister & fd,const Register & rn,unsigned fbits)972 void TurboAssembler::Ucvtf(const VRegister& fd, const Register& rn,
973                            unsigned fbits) {
974   DCHECK(allow_macro_instructions());
975   ucvtf(fd, rn, fbits);
976 }
977 
Udiv(const Register & rd,const Register & rn,const Register & rm)978 void TurboAssembler::Udiv(const Register& rd, const Register& rn,
979                           const Register& rm) {
980   DCHECK(allow_macro_instructions());
981   DCHECK(!rd.IsZero());
982   udiv(rd, rn, rm);
983 }
984 
985 
Umaddl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)986 void MacroAssembler::Umaddl(const Register& rd,
987                             const Register& rn,
988                             const Register& rm,
989                             const Register& ra) {
990   DCHECK(allow_macro_instructions());
991   DCHECK(!rd.IsZero());
992   umaddl(rd, rn, rm, ra);
993 }
994 
995 
Umsubl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)996 void MacroAssembler::Umsubl(const Register& rd,
997                             const Register& rn,
998                             const Register& rm,
999                             const Register& ra) {
1000   DCHECK(allow_macro_instructions());
1001   DCHECK(!rd.IsZero());
1002   umsubl(rd, rn, rm, ra);
1003 }
1004 
Uxtb(const Register & rd,const Register & rn)1005 void TurboAssembler::Uxtb(const Register& rd, const Register& rn) {
1006   DCHECK(allow_macro_instructions());
1007   DCHECK(!rd.IsZero());
1008   uxtb(rd, rn);
1009 }
1010 
Uxth(const Register & rd,const Register & rn)1011 void TurboAssembler::Uxth(const Register& rd, const Register& rn) {
1012   DCHECK(allow_macro_instructions());
1013   DCHECK(!rd.IsZero());
1014   uxth(rd, rn);
1015 }
1016 
Uxtw(const Register & rd,const Register & rn)1017 void TurboAssembler::Uxtw(const Register& rd, const Register& rn) {
1018   DCHECK(allow_macro_instructions());
1019   DCHECK(!rd.IsZero());
1020   uxtw(rd, rn);
1021 }
1022 
InitializeRootRegister()1023 void TurboAssembler::InitializeRootRegister() {
1024   ExternalReference roots_array_start =
1025       ExternalReference::roots_array_start(isolate());
1026   Mov(kRootRegister, Operand(roots_array_start));
1027   Add(kRootRegister, kRootRegister, kRootRegisterBias);
1028 }
1029 
1030 
SmiTag(Register dst,Register src)1031 void MacroAssembler::SmiTag(Register dst, Register src) {
1032   DCHECK(dst.Is64Bits() && src.Is64Bits());
1033   DCHECK(SmiValuesAre32Bits() || SmiValuesAre31Bits());
1034   Lsl(dst, src, kSmiShift);
1035 }
1036 
SmiTag(Register smi)1037 void MacroAssembler::SmiTag(Register smi) { SmiTag(smi, smi); }
1038 
SmiUntag(Register dst,Register src)1039 void TurboAssembler::SmiUntag(Register dst, Register src) {
1040   DCHECK(dst.Is64Bits() && src.Is64Bits());
1041   if (FLAG_enable_slow_asserts) {
1042     AssertSmi(src);
1043   }
1044   DCHECK(SmiValuesAre32Bits() || SmiValuesAre31Bits());
1045   Asr(dst, src, kSmiShift);
1046 }
1047 
SmiUntag(Register dst,const MemOperand & src)1048 void TurboAssembler::SmiUntag(Register dst, const MemOperand& src) {
1049   DCHECK(dst.Is64Bits());
1050   if (SmiValuesAre32Bits()) {
1051     if (src.IsImmediateOffset() && src.shift_amount() == 0) {
1052       // Load value directly from the upper half-word.
1053       // Assumes that Smis are shifted by 32 bits and little endianness.
1054       DCHECK_EQ(kSmiShift, 32);
1055       Ldrsw(dst,
1056             MemOperand(src.base(), src.offset() + (kSmiShift / kBitsPerByte),
1057                        src.addrmode()));
1058 
1059     } else {
1060       Ldr(dst, src);
1061       SmiUntag(dst);
1062     }
1063   } else {
1064     DCHECK(SmiValuesAre31Bits());
1065     Ldr(dst, src);
1066     SmiUntag(dst);
1067   }
1068 }
1069 
SmiUntag(Register smi)1070 void TurboAssembler::SmiUntag(Register smi) { SmiUntag(smi, smi); }
1071 
JumpIfSmi(Register value,Label * smi_label,Label * not_smi_label)1072 void TurboAssembler::JumpIfSmi(Register value, Label* smi_label,
1073                                Label* not_smi_label) {
1074   STATIC_ASSERT((kSmiTagSize == 1) && (kSmiTag == 0));
1075   // Check if the tag bit is set.
1076   if (smi_label) {
1077     Tbz(value, 0, smi_label);
1078     if (not_smi_label) {
1079       B(not_smi_label);
1080     }
1081   } else {
1082     DCHECK(not_smi_label);
1083     Tbnz(value, 0, not_smi_label);
1084   }
1085 }
1086 
JumpIfEqual(Register x,int32_t y,Label * dest)1087 void TurboAssembler::JumpIfEqual(Register x, int32_t y, Label* dest) {
1088   Cmp(x, y);
1089   B(eq, dest);
1090 }
1091 
JumpIfLessThan(Register x,int32_t y,Label * dest)1092 void TurboAssembler::JumpIfLessThan(Register x, int32_t y, Label* dest) {
1093   Cmp(x, y);
1094   B(lt, dest);
1095 }
1096 
JumpIfNotSmi(Register value,Label * not_smi_label)1097 void MacroAssembler::JumpIfNotSmi(Register value, Label* not_smi_label) {
1098   JumpIfSmi(value, nullptr, not_smi_label);
1099 }
1100 
1101 
JumpIfBothSmi(Register value1,Register value2,Label * both_smi_label,Label * not_smi_label)1102 void MacroAssembler::JumpIfBothSmi(Register value1,
1103                                    Register value2,
1104                                    Label* both_smi_label,
1105                                    Label* not_smi_label) {
1106   STATIC_ASSERT((kSmiTagSize == 1) && (kSmiTag == 0));
1107   UseScratchRegisterScope temps(this);
1108   Register tmp = temps.AcquireX();
1109   // Check if both tag bits are clear.
1110   Orr(tmp, value1, value2);
1111   JumpIfSmi(tmp, both_smi_label, not_smi_label);
1112 }
1113 
1114 
JumpIfEitherSmi(Register value1,Register value2,Label * either_smi_label,Label * not_smi_label)1115 void MacroAssembler::JumpIfEitherSmi(Register value1,
1116                                      Register value2,
1117                                      Label* either_smi_label,
1118                                      Label* not_smi_label) {
1119   STATIC_ASSERT((kSmiTagSize == 1) && (kSmiTag == 0));
1120   UseScratchRegisterScope temps(this);
1121   Register tmp = temps.AcquireX();
1122   // Check if either tag bit is clear.
1123   And(tmp, value1, value2);
1124   JumpIfSmi(tmp, either_smi_label, not_smi_label);
1125 }
1126 
1127 
JumpIfEitherNotSmi(Register value1,Register value2,Label * not_smi_label)1128 void MacroAssembler::JumpIfEitherNotSmi(Register value1,
1129                                         Register value2,
1130                                         Label* not_smi_label) {
1131   JumpIfBothSmi(value1, value2, nullptr, not_smi_label);
1132 }
1133 
1134 
JumpIfBothNotSmi(Register value1,Register value2,Label * not_smi_label)1135 void MacroAssembler::JumpIfBothNotSmi(Register value1,
1136                                       Register value2,
1137                                       Label* not_smi_label) {
1138   JumpIfEitherSmi(value1, value2, nullptr, not_smi_label);
1139 }
1140 
1141 
ObjectTag(Register tagged_obj,Register obj)1142 void MacroAssembler::ObjectTag(Register tagged_obj, Register obj) {
1143   STATIC_ASSERT(kHeapObjectTag == 1);
1144   if (emit_debug_code()) {
1145     Label ok;
1146     Tbz(obj, 0, &ok);
1147     Abort(AbortReason::kObjectTagged);
1148     Bind(&ok);
1149   }
1150   Orr(tagged_obj, obj, kHeapObjectTag);
1151 }
1152 
1153 
ObjectUntag(Register untagged_obj,Register obj)1154 void MacroAssembler::ObjectUntag(Register untagged_obj, Register obj) {
1155   STATIC_ASSERT(kHeapObjectTag == 1);
1156   if (emit_debug_code()) {
1157     Label ok;
1158     Tbnz(obj, 0, &ok);
1159     Abort(AbortReason::kObjectNotTagged);
1160     Bind(&ok);
1161   }
1162   Bic(untagged_obj, obj, kHeapObjectTag);
1163 }
1164 
jmp(Label * L)1165 void TurboAssembler::jmp(Label* L) { B(L); }
1166 
Push(Handle<HeapObject> handle)1167 void TurboAssembler::Push(Handle<HeapObject> handle) {
1168   UseScratchRegisterScope temps(this);
1169   Register tmp = temps.AcquireX();
1170   Mov(tmp, Operand(handle));
1171   // This is only used in test-heap.cc, for generating code that is not
1172   // executed. Push a padding slot together with the handle here, to
1173   // satisfy the alignment requirement.
1174   Push(padreg, tmp);
1175 }
1176 
Push(Smi * smi)1177 void TurboAssembler::Push(Smi* smi) {
1178   UseScratchRegisterScope temps(this);
1179   Register tmp = temps.AcquireX();
1180   Mov(tmp, Operand(smi));
1181   Push(tmp);
1182 }
1183 
Claim(int64_t count,uint64_t unit_size)1184 void TurboAssembler::Claim(int64_t count, uint64_t unit_size) {
1185   DCHECK_GE(count, 0);
1186   uint64_t size = count * unit_size;
1187 
1188   if (size == 0) {
1189     return;
1190   }
1191   DCHECK_EQ(size % 16, 0);
1192 
1193   Sub(sp, sp, size);
1194 }
1195 
Claim(const Register & count,uint64_t unit_size)1196 void TurboAssembler::Claim(const Register& count, uint64_t unit_size) {
1197   if (unit_size == 0) return;
1198   DCHECK(base::bits::IsPowerOfTwo(unit_size));
1199 
1200   const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits);
1201   const Operand size(count, LSL, shift);
1202 
1203   if (size.IsZero()) {
1204     return;
1205   }
1206   AssertPositiveOrZero(count);
1207 
1208   Sub(sp, sp, size);
1209 }
1210 
1211 
ClaimBySMI(const Register & count_smi,uint64_t unit_size)1212 void MacroAssembler::ClaimBySMI(const Register& count_smi, uint64_t unit_size) {
1213   DCHECK(unit_size == 0 || base::bits::IsPowerOfTwo(unit_size));
1214   const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits) - kSmiShift;
1215   const Operand size(count_smi,
1216                      (shift >= 0) ? (LSL) : (LSR),
1217                      (shift >= 0) ? (shift) : (-shift));
1218 
1219   if (size.IsZero()) {
1220     return;
1221   }
1222 
1223   Sub(sp, sp, size);
1224 }
1225 
Drop(int64_t count,uint64_t unit_size)1226 void TurboAssembler::Drop(int64_t count, uint64_t unit_size) {
1227   DCHECK_GE(count, 0);
1228   uint64_t size = count * unit_size;
1229 
1230   if (size == 0) {
1231     return;
1232   }
1233 
1234   Add(sp, sp, size);
1235   DCHECK_EQ(size % 16, 0);
1236 }
1237 
Drop(const Register & count,uint64_t unit_size)1238 void TurboAssembler::Drop(const Register& count, uint64_t unit_size) {
1239   if (unit_size == 0) return;
1240   DCHECK(base::bits::IsPowerOfTwo(unit_size));
1241 
1242   const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits);
1243   const Operand size(count, LSL, shift);
1244 
1245   if (size.IsZero()) {
1246     return;
1247   }
1248 
1249   AssertPositiveOrZero(count);
1250   Add(sp, sp, size);
1251 }
1252 
DropArguments(const Register & count,ArgumentsCountMode mode)1253 void TurboAssembler::DropArguments(const Register& count,
1254                                    ArgumentsCountMode mode) {
1255   int extra_slots = 1;  // Padding slot.
1256   if (mode == kCountExcludesReceiver) {
1257     // Add a slot for the receiver.
1258     ++extra_slots;
1259   }
1260   UseScratchRegisterScope temps(this);
1261   Register tmp = temps.AcquireX();
1262   Add(tmp, count, extra_slots);
1263   Bic(tmp, tmp, 1);
1264   Drop(tmp, kXRegSize);
1265 }
1266 
DropArguments(int64_t count,ArgumentsCountMode mode)1267 void TurboAssembler::DropArguments(int64_t count, ArgumentsCountMode mode) {
1268   if (mode == kCountExcludesReceiver) {
1269     // Add a slot for the receiver.
1270     ++count;
1271   }
1272   Drop(RoundUp(count, 2), kXRegSize);
1273 }
1274 
DropSlots(int64_t count)1275 void TurboAssembler::DropSlots(int64_t count) {
1276   Drop(RoundUp(count, 2), kXRegSize);
1277 }
1278 
PushArgument(const Register & arg)1279 void TurboAssembler::PushArgument(const Register& arg) { Push(padreg, arg); }
1280 
DropBySMI(const Register & count_smi,uint64_t unit_size)1281 void MacroAssembler::DropBySMI(const Register& count_smi, uint64_t unit_size) {
1282   DCHECK(unit_size == 0 || base::bits::IsPowerOfTwo(unit_size));
1283   const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits) - kSmiShift;
1284   const Operand size(count_smi,
1285                      (shift >= 0) ? (LSL) : (LSR),
1286                      (shift >= 0) ? (shift) : (-shift));
1287 
1288   if (size.IsZero()) {
1289     return;
1290   }
1291 
1292   Add(sp, sp, size);
1293 }
1294 
1295 
CompareAndBranch(const Register & lhs,const Operand & rhs,Condition cond,Label * label)1296 void MacroAssembler::CompareAndBranch(const Register& lhs,
1297                                       const Operand& rhs,
1298                                       Condition cond,
1299                                       Label* label) {
1300   if (rhs.IsImmediate() && (rhs.ImmediateValue() == 0) &&
1301       ((cond == eq) || (cond == ne))) {
1302     if (cond == eq) {
1303       Cbz(lhs, label);
1304     } else {
1305       Cbnz(lhs, label);
1306     }
1307   } else {
1308     Cmp(lhs, rhs);
1309     B(cond, label);
1310   }
1311 }
1312 
TestAndBranchIfAnySet(const Register & reg,const uint64_t bit_pattern,Label * label)1313 void TurboAssembler::TestAndBranchIfAnySet(const Register& reg,
1314                                            const uint64_t bit_pattern,
1315                                            Label* label) {
1316   int bits = reg.SizeInBits();
1317   DCHECK_GT(CountSetBits(bit_pattern, bits), 0);
1318   if (CountSetBits(bit_pattern, bits) == 1) {
1319     Tbnz(reg, MaskToBit(bit_pattern), label);
1320   } else {
1321     Tst(reg, bit_pattern);
1322     B(ne, label);
1323   }
1324 }
1325 
TestAndBranchIfAllClear(const Register & reg,const uint64_t bit_pattern,Label * label)1326 void TurboAssembler::TestAndBranchIfAllClear(const Register& reg,
1327                                              const uint64_t bit_pattern,
1328                                              Label* label) {
1329   int bits = reg.SizeInBits();
1330   DCHECK_GT(CountSetBits(bit_pattern, bits), 0);
1331   if (CountSetBits(bit_pattern, bits) == 1) {
1332     Tbz(reg, MaskToBit(bit_pattern), label);
1333   } else {
1334     Tst(reg, bit_pattern);
1335     B(eq, label);
1336   }
1337 }
1338 
1339 
InlineData(uint64_t data)1340 void MacroAssembler::InlineData(uint64_t data) {
1341   DCHECK(is_uint16(data));
1342   InstructionAccurateScope scope(this, 1);
1343   movz(xzr, data);
1344 }
1345 
1346 
EnableInstrumentation()1347 void MacroAssembler::EnableInstrumentation() {
1348   InstructionAccurateScope scope(this, 1);
1349   movn(xzr, InstrumentStateEnable);
1350 }
1351 
1352 
DisableInstrumentation()1353 void MacroAssembler::DisableInstrumentation() {
1354   InstructionAccurateScope scope(this, 1);
1355   movn(xzr, InstrumentStateDisable);
1356 }
1357 
1358 
AnnotateInstrumentation(const char * marker_name)1359 void MacroAssembler::AnnotateInstrumentation(const char* marker_name) {
1360   DCHECK_EQ(strlen(marker_name), 2);
1361 
1362   // We allow only printable characters in the marker names. Unprintable
1363   // characters are reserved for controlling features of the instrumentation.
1364   DCHECK(isprint(marker_name[0]) && isprint(marker_name[1]));
1365 
1366   InstructionAccurateScope scope(this, 1);
1367   movn(xzr, (marker_name[1] << 8) | marker_name[0]);
1368 }
1369 
1370 }  // namespace internal
1371 }  // namespace v8
1372 
1373 #endif  // V8_ARM64_MACRO_ASSEMBLER_ARM64_INL_H_
1374