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