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