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