1 // Copyright 2015, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright notice,
8 // this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright notice,
10 // this list of conditions and the following disclaimer in the documentation
11 // and/or other materials provided with the distribution.
12 // * Neither the name of ARM Limited nor the names of its contributors may be
13 // used to endorse or promote products derived from this software without
14 // specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 #ifndef VIXL_AARCH64_ASSEMBLER_AARCH64_H_
28 #define VIXL_AARCH64_ASSEMBLER_AARCH64_H_
29
30 #include "../assembler-base-vixl.h"
31 #include "../code-generation-scopes-vixl.h"
32 #include "../globals-vixl.h"
33 #include "../invalset-vixl.h"
34 #include "../utils-vixl.h"
35
36 #include "operands-aarch64.h"
37
38 namespace vixl {
39 namespace aarch64 {
40
41 class LabelTestHelper; // Forward declaration.
42
43
44 class Label {
45 public:
Label()46 Label() : location_(kLocationUnbound) {}
~Label()47 ~Label() {
48 // All links to a label must have been resolved before it is destructed.
49 VIXL_ASSERT(!IsLinked());
50 }
51
IsBound()52 bool IsBound() const { return location_ >= 0; }
IsLinked()53 bool IsLinked() const { return !links_.empty(); }
54
GetLocation()55 ptrdiff_t GetLocation() const { return location_; }
56 VIXL_DEPRECATED("GetLocation", ptrdiff_t location() const) {
57 return GetLocation();
58 }
59
60 static const int kNPreallocatedLinks = 4;
61 static const ptrdiff_t kInvalidLinkKey = PTRDIFF_MAX;
62 static const size_t kReclaimFrom = 512;
63 static const size_t kReclaimFactor = 2;
64
65 typedef InvalSet<ptrdiff_t,
66 kNPreallocatedLinks,
67 ptrdiff_t,
68 kInvalidLinkKey,
69 kReclaimFrom,
70 kReclaimFactor>
71 LinksSetBase;
72 typedef InvalSetIterator<LinksSetBase> LabelLinksIteratorBase;
73
74 private:
75 class LinksSet : public LinksSetBase {
76 public:
LinksSet()77 LinksSet() : LinksSetBase() {}
78 };
79
80 // Allows iterating over the links of a label. The behaviour is undefined if
81 // the list of links is modified in any way while iterating.
82 class LabelLinksIterator : public LabelLinksIteratorBase {
83 public:
LabelLinksIterator(Label * label)84 explicit LabelLinksIterator(Label* label)
85 : LabelLinksIteratorBase(&label->links_) {}
86
87 // TODO: Remove these and use the STL-like interface instead.
88 using LabelLinksIteratorBase::Advance;
89 using LabelLinksIteratorBase::Current;
90 };
91
Bind(ptrdiff_t location)92 void Bind(ptrdiff_t location) {
93 // Labels can only be bound once.
94 VIXL_ASSERT(!IsBound());
95 location_ = location;
96 }
97
AddLink(ptrdiff_t instruction)98 void AddLink(ptrdiff_t instruction) {
99 // If a label is bound, the assembler already has the information it needs
100 // to write the instruction, so there is no need to add it to links_.
101 VIXL_ASSERT(!IsBound());
102 links_.insert(instruction);
103 }
104
DeleteLink(ptrdiff_t instruction)105 void DeleteLink(ptrdiff_t instruction) { links_.erase(instruction); }
106
ClearAllLinks()107 void ClearAllLinks() { links_.clear(); }
108
109 // TODO: The comment below considers average case complexity for our
110 // usual use-cases. The elements of interest are:
111 // - Branches to a label are emitted in order: branch instructions to a label
112 // are generated at an offset in the code generation buffer greater than any
113 // other branch to that same label already generated. As an example, this can
114 // be broken when an instruction is patched to become a branch. Note that the
115 // code will still work, but the complexity considerations below may locally
116 // not apply any more.
117 // - Veneers are generated in order: for multiple branches of the same type
118 // branching to the same unbound label going out of range, veneers are
119 // generated in growing order of the branch instruction offset from the start
120 // of the buffer.
121 //
122 // When creating a veneer for a branch going out of range, the link for this
123 // branch needs to be removed from this `links_`. Since all branches are
124 // tracked in one underlying InvalSet, the complexity for this deletion is the
125 // same as for finding the element, ie. O(n), where n is the number of links
126 // in the set.
127 // This could be reduced to O(1) by using the same trick as used when tracking
128 // branch information for veneers: split the container to use one set per type
129 // of branch. With that setup, when a veneer is created and the link needs to
130 // be deleted, if the two points above hold, it must be the minimum element of
131 // the set for its type of branch, and that minimum element will be accessible
132 // in O(1).
133
134 // The offsets of the instructions that have linked to this label.
135 LinksSet links_;
136 // The label location.
137 ptrdiff_t location_;
138
139 static const ptrdiff_t kLocationUnbound = -1;
140
141 // It is not safe to copy labels, so disable the copy constructor and operator
142 // by declaring them private (without an implementation).
143 #if __cplusplus >= 201103L
144 Label(const Label&) = delete;
145 void operator=(const Label&) = delete;
146 #else
147 Label(const Label&);
148 void operator=(const Label&);
149 #endif
150
151 // The Assembler class is responsible for binding and linking labels, since
152 // the stored offsets need to be consistent with the Assembler's buffer.
153 friend class Assembler;
154 // The MacroAssembler and VeneerPool handle resolution of branches to distant
155 // targets.
156 friend class MacroAssembler;
157 friend class VeneerPool;
158 };
159
160
161 class Assembler;
162 class LiteralPool;
163
164 // A literal is a 32-bit or 64-bit piece of data stored in the instruction
165 // stream and loaded through a pc relative load. The same literal can be
166 // referred to by multiple instructions but a literal can only reside at one
167 // place in memory. A literal can be used by a load before or after being
168 // placed in memory.
169 //
170 // Internally an offset of 0 is associated with a literal which has been
171 // neither used nor placed. Then two possibilities arise:
172 // 1) the label is placed, the offset (stored as offset + 1) is used to
173 // resolve any subsequent load using the label.
174 // 2) the label is not placed and offset is the offset of the last load using
175 // the literal (stored as -offset -1). If multiple loads refer to this
176 // literal then the last load holds the offset of the preceding load and
177 // all loads form a chain. Once the offset is placed all the loads in the
178 // chain are resolved and future loads fall back to possibility 1.
179 class RawLiteral {
180 public:
181 enum DeletionPolicy {
182 kDeletedOnPlacementByPool,
183 kDeletedOnPoolDestruction,
184 kManuallyDeleted
185 };
186
187 RawLiteral(size_t size,
188 LiteralPool* literal_pool,
189 DeletionPolicy deletion_policy = kManuallyDeleted);
190
191 // The literal pool only sees and deletes `RawLiteral*` pointers, but they are
192 // actually pointing to `Literal<T>` objects.
~RawLiteral()193 virtual ~RawLiteral() {}
194
GetSize()195 size_t GetSize() const {
196 VIXL_STATIC_ASSERT(kDRegSizeInBytes == kXRegSizeInBytes);
197 VIXL_STATIC_ASSERT(kSRegSizeInBytes == kWRegSizeInBytes);
198 VIXL_ASSERT((size_ == kXRegSizeInBytes) || (size_ == kWRegSizeInBytes) ||
199 (size_ == kQRegSizeInBytes));
200 return size_;
201 }
202 VIXL_DEPRECATED("GetSize", size_t size()) { return GetSize(); }
203
GetRawValue128Low64()204 uint64_t GetRawValue128Low64() const {
205 VIXL_ASSERT(size_ == kQRegSizeInBytes);
206 return low64_;
207 }
208 VIXL_DEPRECATED("GetRawValue128Low64", uint64_t raw_value128_low64()) {
209 return GetRawValue128Low64();
210 }
211
GetRawValue128High64()212 uint64_t GetRawValue128High64() const {
213 VIXL_ASSERT(size_ == kQRegSizeInBytes);
214 return high64_;
215 }
216 VIXL_DEPRECATED("GetRawValue128High64", uint64_t raw_value128_high64()) {
217 return GetRawValue128High64();
218 }
219
GetRawValue64()220 uint64_t GetRawValue64() const {
221 VIXL_ASSERT(size_ == kXRegSizeInBytes);
222 VIXL_ASSERT(high64_ == 0);
223 return low64_;
224 }
225 VIXL_DEPRECATED("GetRawValue64", uint64_t raw_value64()) {
226 return GetRawValue64();
227 }
228
GetRawValue32()229 uint32_t GetRawValue32() const {
230 VIXL_ASSERT(size_ == kWRegSizeInBytes);
231 VIXL_ASSERT(high64_ == 0);
232 VIXL_ASSERT(IsUint32(low64_) || IsInt32(low64_));
233 return static_cast<uint32_t>(low64_);
234 }
235 VIXL_DEPRECATED("GetRawValue32", uint32_t raw_value32()) {
236 return GetRawValue32();
237 }
238
IsUsed()239 bool IsUsed() const { return offset_ < 0; }
IsPlaced()240 bool IsPlaced() const { return offset_ > 0; }
241
GetLiteralPool()242 LiteralPool* GetLiteralPool() const { return literal_pool_; }
243
GetOffset()244 ptrdiff_t GetOffset() const {
245 VIXL_ASSERT(IsPlaced());
246 return offset_ - 1;
247 }
248 VIXL_DEPRECATED("GetOffset", ptrdiff_t offset()) { return GetOffset(); }
249
250 protected:
SetOffset(ptrdiff_t offset)251 void SetOffset(ptrdiff_t offset) {
252 VIXL_ASSERT(offset >= 0);
253 VIXL_ASSERT(IsWordAligned(offset));
254 VIXL_ASSERT(!IsPlaced());
255 offset_ = offset + 1;
256 }
set_offset(ptrdiff_t offset)257 VIXL_DEPRECATED("SetOffset", void set_offset(ptrdiff_t offset)) {
258 SetOffset(offset);
259 }
260
GetLastUse()261 ptrdiff_t GetLastUse() const {
262 VIXL_ASSERT(IsUsed());
263 return -offset_ - 1;
264 }
265 VIXL_DEPRECATED("GetLastUse", ptrdiff_t last_use()) { return GetLastUse(); }
266
SetLastUse(ptrdiff_t offset)267 void SetLastUse(ptrdiff_t offset) {
268 VIXL_ASSERT(offset >= 0);
269 VIXL_ASSERT(IsWordAligned(offset));
270 VIXL_ASSERT(!IsPlaced());
271 offset_ = -offset - 1;
272 }
set_last_use(ptrdiff_t offset)273 VIXL_DEPRECATED("SetLastUse", void set_last_use(ptrdiff_t offset)) {
274 SetLastUse(offset);
275 }
276
277 size_t size_;
278 ptrdiff_t offset_;
279 uint64_t low64_;
280 uint64_t high64_;
281
282 private:
283 LiteralPool* literal_pool_;
284 DeletionPolicy deletion_policy_;
285
286 friend class Assembler;
287 friend class LiteralPool;
288 };
289
290
291 template <typename T>
292 class Literal : public RawLiteral {
293 public:
294 explicit Literal(T value,
295 LiteralPool* literal_pool = NULL,
296 RawLiteral::DeletionPolicy ownership = kManuallyDeleted)
RawLiteral(sizeof (value),literal_pool,ownership)297 : RawLiteral(sizeof(value), literal_pool, ownership) {
298 VIXL_STATIC_ASSERT(sizeof(value) <= kXRegSizeInBytes);
299 UpdateValue(value);
300 }
301
302 Literal(T high64,
303 T low64,
304 LiteralPool* literal_pool = NULL,
305 RawLiteral::DeletionPolicy ownership = kManuallyDeleted)
RawLiteral(kQRegSizeInBytes,literal_pool,ownership)306 : RawLiteral(kQRegSizeInBytes, literal_pool, ownership) {
307 VIXL_STATIC_ASSERT(sizeof(low64) == (kQRegSizeInBytes / 2));
308 UpdateValue(high64, low64);
309 }
310
~Literal()311 virtual ~Literal() {}
312
313 // Update the value of this literal, if necessary by rewriting the value in
314 // the pool.
315 // If the literal has already been placed in a literal pool, the address of
316 // the start of the code buffer must be provided, as the literal only knows it
317 // offset from there. This also allows patching the value after the code has
318 // been moved in memory.
319 void UpdateValue(T new_value, uint8_t* code_buffer = NULL) {
320 VIXL_ASSERT(sizeof(new_value) == size_);
321 memcpy(&low64_, &new_value, sizeof(new_value));
322 if (IsPlaced()) {
323 VIXL_ASSERT(code_buffer != NULL);
324 RewriteValueInCode(code_buffer);
325 }
326 }
327
328 void UpdateValue(T high64, T low64, uint8_t* code_buffer = NULL) {
329 VIXL_ASSERT(sizeof(low64) == size_ / 2);
330 memcpy(&low64_, &low64, sizeof(low64));
331 memcpy(&high64_, &high64, sizeof(high64));
332 if (IsPlaced()) {
333 VIXL_ASSERT(code_buffer != NULL);
334 RewriteValueInCode(code_buffer);
335 }
336 }
337
338 void UpdateValue(T new_value, const Assembler* assembler);
339 void UpdateValue(T high64, T low64, const Assembler* assembler);
340
341 private:
RewriteValueInCode(uint8_t * code_buffer)342 void RewriteValueInCode(uint8_t* code_buffer) {
343 VIXL_ASSERT(IsPlaced());
344 VIXL_STATIC_ASSERT(sizeof(T) <= kXRegSizeInBytes);
345 switch (GetSize()) {
346 case kSRegSizeInBytes:
347 *reinterpret_cast<uint32_t*>(code_buffer + GetOffset()) =
348 GetRawValue32();
349 break;
350 case kDRegSizeInBytes:
351 *reinterpret_cast<uint64_t*>(code_buffer + GetOffset()) =
352 GetRawValue64();
353 break;
354 default:
355 VIXL_ASSERT(GetSize() == kQRegSizeInBytes);
356 uint64_t* base_address =
357 reinterpret_cast<uint64_t*>(code_buffer + GetOffset());
358 *base_address = GetRawValue128Low64();
359 *(base_address + 1) = GetRawValue128High64();
360 }
361 }
362 };
363
364
365 // Control whether or not position-independent code should be emitted.
366 enum PositionIndependentCodeOption {
367 // All code generated will be position-independent; all branches and
368 // references to labels generated with the Label class will use PC-relative
369 // addressing.
370 PositionIndependentCode,
371
372 // Allow VIXL to generate code that refers to absolute addresses. With this
373 // option, it will not be possible to copy the code buffer and run it from a
374 // different address; code must be generated in its final location.
375 PositionDependentCode,
376
377 // Allow VIXL to assume that the bottom 12 bits of the address will be
378 // constant, but that the top 48 bits may change. This allows `adrp` to
379 // function in systems which copy code between pages, but otherwise maintain
380 // 4KB page alignment.
381 PageOffsetDependentCode
382 };
383
384
385 // Control how scaled- and unscaled-offset loads and stores are generated.
386 enum LoadStoreScalingOption {
387 // Prefer scaled-immediate-offset instructions, but emit unscaled-offset,
388 // register-offset, pre-index or post-index instructions if necessary.
389 PreferScaledOffset,
390
391 // Prefer unscaled-immediate-offset instructions, but emit scaled-offset,
392 // register-offset, pre-index or post-index instructions if necessary.
393 PreferUnscaledOffset,
394
395 // Require scaled-immediate-offset instructions.
396 RequireScaledOffset,
397
398 // Require unscaled-immediate-offset instructions.
399 RequireUnscaledOffset
400 };
401
402
403 // Assembler.
404 class Assembler : public vixl::internal::AssemblerBase {
405 public:
406 explicit Assembler(
407 PositionIndependentCodeOption pic = PositionIndependentCode)
pic_(pic)408 : pic_(pic) {}
409 explicit Assembler(
410 size_t capacity,
411 PositionIndependentCodeOption pic = PositionIndependentCode)
AssemblerBase(capacity)412 : AssemblerBase(capacity), pic_(pic) {}
413 Assembler(byte* buffer,
414 size_t capacity,
415 PositionIndependentCodeOption pic = PositionIndependentCode)
AssemblerBase(buffer,capacity)416 : AssemblerBase(buffer, capacity), pic_(pic) {}
417
418 // Upon destruction, the code will assert that one of the following is true:
419 // * The Assembler object has not been used.
420 // * Nothing has been emitted since the last Reset() call.
421 // * Nothing has been emitted since the last FinalizeCode() call.
~Assembler()422 ~Assembler() {}
423
424 // System functions.
425
426 // Start generating code from the beginning of the buffer, discarding any code
427 // and data that has already been emitted into the buffer.
428 void Reset();
429
430 // Label.
431 // Bind a label to the current PC.
432 void bind(Label* label);
433
434 // Bind a label to a specified offset from the start of the buffer.
435 void BindToOffset(Label* label, ptrdiff_t offset);
436
437 // Place a literal at the current PC.
438 void place(RawLiteral* literal);
439
440 VIXL_DEPRECATED("GetCursorOffset", ptrdiff_t CursorOffset() const) {
441 return GetCursorOffset();
442 }
443
444 VIXL_DEPRECATED("GetBuffer().GetCapacity()",
445 ptrdiff_t GetBufferEndOffset() const) {
446 return static_cast<ptrdiff_t>(GetBuffer().GetCapacity());
447 }
448 VIXL_DEPRECATED("GetBuffer().GetCapacity()",
449 ptrdiff_t BufferEndOffset() const) {
450 return GetBuffer().GetCapacity();
451 }
452
453 // Return the address of a bound label.
454 template <typename T>
GetLabelAddress(const Label * label)455 T GetLabelAddress(const Label* label) const {
456 VIXL_ASSERT(label->IsBound());
457 VIXL_STATIC_ASSERT(sizeof(T) >= sizeof(uintptr_t));
458 return GetBuffer().GetOffsetAddress<T>(label->GetLocation());
459 }
460
GetInstructionAt(ptrdiff_t instruction_offset)461 Instruction* GetInstructionAt(ptrdiff_t instruction_offset) {
462 return GetBuffer()->GetOffsetAddress<Instruction*>(instruction_offset);
463 }
464 VIXL_DEPRECATED("GetInstructionAt",
465 Instruction* InstructionAt(ptrdiff_t instruction_offset)) {
466 return GetInstructionAt(instruction_offset);
467 }
468
GetInstructionOffset(Instruction * instruction)469 ptrdiff_t GetInstructionOffset(Instruction* instruction) {
470 VIXL_STATIC_ASSERT(sizeof(*instruction) == 1);
471 ptrdiff_t offset =
472 instruction - GetBuffer()->GetStartAddress<Instruction*>();
473 VIXL_ASSERT((0 <= offset) &&
474 (offset < static_cast<ptrdiff_t>(GetBuffer()->GetCapacity())));
475 return offset;
476 }
477 VIXL_DEPRECATED("GetInstructionOffset",
478 ptrdiff_t InstructionOffset(Instruction* instruction)) {
479 return GetInstructionOffset(instruction);
480 }
481
482 // Instruction set functions.
483
484 // Branch / Jump instructions.
485 // Branch to register.
486 void br(const Register& xn);
487
488 // Branch with link to register.
489 void blr(const Register& xn);
490
491 // Branch to register with return hint.
492 void ret(const Register& xn = lr);
493
494 // Unconditional branch to label.
495 void b(Label* label);
496
497 // Conditional branch to label.
498 void b(Label* label, Condition cond);
499
500 // Unconditional branch to PC offset.
501 void b(int64_t imm26);
502
503 // Conditional branch to PC offset.
504 void b(int64_t imm19, Condition cond);
505
506 // Branch with link to label.
507 void bl(Label* label);
508
509 // Branch with link to PC offset.
510 void bl(int64_t imm26);
511
512 // Compare and branch to label if zero.
513 void cbz(const Register& rt, Label* label);
514
515 // Compare and branch to PC offset if zero.
516 void cbz(const Register& rt, int64_t imm19);
517
518 // Compare and branch to label if not zero.
519 void cbnz(const Register& rt, Label* label);
520
521 // Compare and branch to PC offset if not zero.
522 void cbnz(const Register& rt, int64_t imm19);
523
524 // Table lookup from one register.
525 void tbl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
526
527 // Table lookup from two registers.
528 void tbl(const VRegister& vd,
529 const VRegister& vn,
530 const VRegister& vn2,
531 const VRegister& vm);
532
533 // Table lookup from three registers.
534 void tbl(const VRegister& vd,
535 const VRegister& vn,
536 const VRegister& vn2,
537 const VRegister& vn3,
538 const VRegister& vm);
539
540 // Table lookup from four registers.
541 void tbl(const VRegister& vd,
542 const VRegister& vn,
543 const VRegister& vn2,
544 const VRegister& vn3,
545 const VRegister& vn4,
546 const VRegister& vm);
547
548 // Table lookup extension from one register.
549 void tbx(const VRegister& vd, const VRegister& vn, const VRegister& vm);
550
551 // Table lookup extension from two registers.
552 void tbx(const VRegister& vd,
553 const VRegister& vn,
554 const VRegister& vn2,
555 const VRegister& vm);
556
557 // Table lookup extension from three registers.
558 void tbx(const VRegister& vd,
559 const VRegister& vn,
560 const VRegister& vn2,
561 const VRegister& vn3,
562 const VRegister& vm);
563
564 // Table lookup extension from four registers.
565 void tbx(const VRegister& vd,
566 const VRegister& vn,
567 const VRegister& vn2,
568 const VRegister& vn3,
569 const VRegister& vn4,
570 const VRegister& vm);
571
572 // Test bit and branch to label if zero.
573 void tbz(const Register& rt, unsigned bit_pos, Label* label);
574
575 // Test bit and branch to PC offset if zero.
576 void tbz(const Register& rt, unsigned bit_pos, int64_t imm14);
577
578 // Test bit and branch to label if not zero.
579 void tbnz(const Register& rt, unsigned bit_pos, Label* label);
580
581 // Test bit and branch to PC offset if not zero.
582 void tbnz(const Register& rt, unsigned bit_pos, int64_t imm14);
583
584 // Address calculation instructions.
585 // Calculate a PC-relative address. Unlike for branches the offset in adr is
586 // unscaled (i.e. the result can be unaligned).
587
588 // Calculate the address of a label.
589 void adr(const Register& xd, Label* label);
590
591 // Calculate the address of a PC offset.
592 void adr(const Register& xd, int64_t imm21);
593
594 // Calculate the page address of a label.
595 void adrp(const Register& xd, Label* label);
596
597 // Calculate the page address of a PC offset.
598 void adrp(const Register& xd, int64_t imm21);
599
600 // Data Processing instructions.
601 // Add.
602 void add(const Register& rd, const Register& rn, const Operand& operand);
603
604 // Add and update status flags.
605 void adds(const Register& rd, const Register& rn, const Operand& operand);
606
607 // Compare negative.
608 void cmn(const Register& rn, const Operand& operand);
609
610 // Subtract.
611 void sub(const Register& rd, const Register& rn, const Operand& operand);
612
613 // Subtract and update status flags.
614 void subs(const Register& rd, const Register& rn, const Operand& operand);
615
616 // Compare.
617 void cmp(const Register& rn, const Operand& operand);
618
619 // Negate.
620 void neg(const Register& rd, const Operand& operand);
621
622 // Negate and update status flags.
623 void negs(const Register& rd, const Operand& operand);
624
625 // Add with carry bit.
626 void adc(const Register& rd, const Register& rn, const Operand& operand);
627
628 // Add with carry bit and update status flags.
629 void adcs(const Register& rd, const Register& rn, const Operand& operand);
630
631 // Subtract with carry bit.
632 void sbc(const Register& rd, const Register& rn, const Operand& operand);
633
634 // Subtract with carry bit and update status flags.
635 void sbcs(const Register& rd, const Register& rn, const Operand& operand);
636
637 // Negate with carry bit.
638 void ngc(const Register& rd, const Operand& operand);
639
640 // Negate with carry bit and update status flags.
641 void ngcs(const Register& rd, const Operand& operand);
642
643 // Logical instructions.
644 // Bitwise and (A & B).
645 void and_(const Register& rd, const Register& rn, const Operand& operand);
646
647 // Bitwise and (A & B) and update status flags.
648 void ands(const Register& rd, const Register& rn, const Operand& operand);
649
650 // Bit test and set flags.
651 void tst(const Register& rn, const Operand& operand);
652
653 // Bit clear (A & ~B).
654 void bic(const Register& rd, const Register& rn, const Operand& operand);
655
656 // Bit clear (A & ~B) and update status flags.
657 void bics(const Register& rd, const Register& rn, const Operand& operand);
658
659 // Bitwise or (A | B).
660 void orr(const Register& rd, const Register& rn, const Operand& operand);
661
662 // Bitwise nor (A | ~B).
663 void orn(const Register& rd, const Register& rn, const Operand& operand);
664
665 // Bitwise eor/xor (A ^ B).
666 void eor(const Register& rd, const Register& rn, const Operand& operand);
667
668 // Bitwise enor/xnor (A ^ ~B).
669 void eon(const Register& rd, const Register& rn, const Operand& operand);
670
671 // Logical shift left by variable.
672 void lslv(const Register& rd, const Register& rn, const Register& rm);
673
674 // Logical shift right by variable.
675 void lsrv(const Register& rd, const Register& rn, const Register& rm);
676
677 // Arithmetic shift right by variable.
678 void asrv(const Register& rd, const Register& rn, const Register& rm);
679
680 // Rotate right by variable.
681 void rorv(const Register& rd, const Register& rn, const Register& rm);
682
683 // Bitfield instructions.
684 // Bitfield move.
685 void bfm(const Register& rd,
686 const Register& rn,
687 unsigned immr,
688 unsigned imms);
689
690 // Signed bitfield move.
691 void sbfm(const Register& rd,
692 const Register& rn,
693 unsigned immr,
694 unsigned imms);
695
696 // Unsigned bitfield move.
697 void ubfm(const Register& rd,
698 const Register& rn,
699 unsigned immr,
700 unsigned imms);
701
702 // Bfm aliases.
703 // Bitfield insert.
bfi(const Register & rd,const Register & rn,unsigned lsb,unsigned width)704 void bfi(const Register& rd,
705 const Register& rn,
706 unsigned lsb,
707 unsigned width) {
708 VIXL_ASSERT(width >= 1);
709 VIXL_ASSERT(lsb + width <= static_cast<unsigned>(rn.GetSizeInBits()));
710 bfm(rd,
711 rn,
712 (rd.GetSizeInBits() - lsb) & (rd.GetSizeInBits() - 1),
713 width - 1);
714 }
715
716 // Bitfield extract and insert low.
bfxil(const Register & rd,const Register & rn,unsigned lsb,unsigned width)717 void bfxil(const Register& rd,
718 const Register& rn,
719 unsigned lsb,
720 unsigned width) {
721 VIXL_ASSERT(width >= 1);
722 VIXL_ASSERT(lsb + width <= static_cast<unsigned>(rn.GetSizeInBits()));
723 bfm(rd, rn, lsb, lsb + width - 1);
724 }
725
726 // Sbfm aliases.
727 // Arithmetic shift right.
asr(const Register & rd,const Register & rn,unsigned shift)728 void asr(const Register& rd, const Register& rn, unsigned shift) {
729 VIXL_ASSERT(shift < static_cast<unsigned>(rd.GetSizeInBits()));
730 sbfm(rd, rn, shift, rd.GetSizeInBits() - 1);
731 }
732
733 // Signed bitfield insert with zero at right.
sbfiz(const Register & rd,const Register & rn,unsigned lsb,unsigned width)734 void sbfiz(const Register& rd,
735 const Register& rn,
736 unsigned lsb,
737 unsigned width) {
738 VIXL_ASSERT(width >= 1);
739 VIXL_ASSERT(lsb + width <= static_cast<unsigned>(rn.GetSizeInBits()));
740 sbfm(rd,
741 rn,
742 (rd.GetSizeInBits() - lsb) & (rd.GetSizeInBits() - 1),
743 width - 1);
744 }
745
746 // Signed bitfield extract.
sbfx(const Register & rd,const Register & rn,unsigned lsb,unsigned width)747 void sbfx(const Register& rd,
748 const Register& rn,
749 unsigned lsb,
750 unsigned width) {
751 VIXL_ASSERT(width >= 1);
752 VIXL_ASSERT(lsb + width <= static_cast<unsigned>(rn.GetSizeInBits()));
753 sbfm(rd, rn, lsb, lsb + width - 1);
754 }
755
756 // Signed extend byte.
sxtb(const Register & rd,const Register & rn)757 void sxtb(const Register& rd, const Register& rn) { sbfm(rd, rn, 0, 7); }
758
759 // Signed extend halfword.
sxth(const Register & rd,const Register & rn)760 void sxth(const Register& rd, const Register& rn) { sbfm(rd, rn, 0, 15); }
761
762 // Signed extend word.
sxtw(const Register & rd,const Register & rn)763 void sxtw(const Register& rd, const Register& rn) { sbfm(rd, rn, 0, 31); }
764
765 // Ubfm aliases.
766 // Logical shift left.
lsl(const Register & rd,const Register & rn,unsigned shift)767 void lsl(const Register& rd, const Register& rn, unsigned shift) {
768 unsigned reg_size = rd.GetSizeInBits();
769 VIXL_ASSERT(shift < reg_size);
770 ubfm(rd, rn, (reg_size - shift) % reg_size, reg_size - shift - 1);
771 }
772
773 // Logical shift right.
lsr(const Register & rd,const Register & rn,unsigned shift)774 void lsr(const Register& rd, const Register& rn, unsigned shift) {
775 VIXL_ASSERT(shift < static_cast<unsigned>(rd.GetSizeInBits()));
776 ubfm(rd, rn, shift, rd.GetSizeInBits() - 1);
777 }
778
779 // Unsigned bitfield insert with zero at right.
ubfiz(const Register & rd,const Register & rn,unsigned lsb,unsigned width)780 void ubfiz(const Register& rd,
781 const Register& rn,
782 unsigned lsb,
783 unsigned width) {
784 VIXL_ASSERT(width >= 1);
785 VIXL_ASSERT(lsb + width <= static_cast<unsigned>(rn.GetSizeInBits()));
786 ubfm(rd,
787 rn,
788 (rd.GetSizeInBits() - lsb) & (rd.GetSizeInBits() - 1),
789 width - 1);
790 }
791
792 // Unsigned bitfield extract.
ubfx(const Register & rd,const Register & rn,unsigned lsb,unsigned width)793 void ubfx(const Register& rd,
794 const Register& rn,
795 unsigned lsb,
796 unsigned width) {
797 VIXL_ASSERT(width >= 1);
798 VIXL_ASSERT(lsb + width <= static_cast<unsigned>(rn.GetSizeInBits()));
799 ubfm(rd, rn, lsb, lsb + width - 1);
800 }
801
802 // Unsigned extend byte.
uxtb(const Register & rd,const Register & rn)803 void uxtb(const Register& rd, const Register& rn) { ubfm(rd, rn, 0, 7); }
804
805 // Unsigned extend halfword.
uxth(const Register & rd,const Register & rn)806 void uxth(const Register& rd, const Register& rn) { ubfm(rd, rn, 0, 15); }
807
808 // Unsigned extend word.
uxtw(const Register & rd,const Register & rn)809 void uxtw(const Register& rd, const Register& rn) { ubfm(rd, rn, 0, 31); }
810
811 // Extract.
812 void extr(const Register& rd,
813 const Register& rn,
814 const Register& rm,
815 unsigned lsb);
816
817 // Conditional select: rd = cond ? rn : rm.
818 void csel(const Register& rd,
819 const Register& rn,
820 const Register& rm,
821 Condition cond);
822
823 // Conditional select increment: rd = cond ? rn : rm + 1.
824 void csinc(const Register& rd,
825 const Register& rn,
826 const Register& rm,
827 Condition cond);
828
829 // Conditional select inversion: rd = cond ? rn : ~rm.
830 void csinv(const Register& rd,
831 const Register& rn,
832 const Register& rm,
833 Condition cond);
834
835 // Conditional select negation: rd = cond ? rn : -rm.
836 void csneg(const Register& rd,
837 const Register& rn,
838 const Register& rm,
839 Condition cond);
840
841 // Conditional set: rd = cond ? 1 : 0.
842 void cset(const Register& rd, Condition cond);
843
844 // Conditional set mask: rd = cond ? -1 : 0.
845 void csetm(const Register& rd, Condition cond);
846
847 // Conditional increment: rd = cond ? rn + 1 : rn.
848 void cinc(const Register& rd, const Register& rn, Condition cond);
849
850 // Conditional invert: rd = cond ? ~rn : rn.
851 void cinv(const Register& rd, const Register& rn, Condition cond);
852
853 // Conditional negate: rd = cond ? -rn : rn.
854 void cneg(const Register& rd, const Register& rn, Condition cond);
855
856 // Rotate right.
ror(const Register & rd,const Register & rs,unsigned shift)857 void ror(const Register& rd, const Register& rs, unsigned shift) {
858 extr(rd, rs, rs, shift);
859 }
860
861 // Conditional comparison.
862 // Conditional compare negative.
863 void ccmn(const Register& rn,
864 const Operand& operand,
865 StatusFlags nzcv,
866 Condition cond);
867
868 // Conditional compare.
869 void ccmp(const Register& rn,
870 const Operand& operand,
871 StatusFlags nzcv,
872 Condition cond);
873
874 // CRC-32 checksum from byte.
875 void crc32b(const Register& wd, const Register& wn, const Register& wm);
876
877 // CRC-32 checksum from half-word.
878 void crc32h(const Register& wd, const Register& wn, const Register& wm);
879
880 // CRC-32 checksum from word.
881 void crc32w(const Register& wd, const Register& wn, const Register& wm);
882
883 // CRC-32 checksum from double word.
884 void crc32x(const Register& wd, const Register& wn, const Register& xm);
885
886 // CRC-32 C checksum from byte.
887 void crc32cb(const Register& wd, const Register& wn, const Register& wm);
888
889 // CRC-32 C checksum from half-word.
890 void crc32ch(const Register& wd, const Register& wn, const Register& wm);
891
892 // CRC-32 C checksum from word.
893 void crc32cw(const Register& wd, const Register& wn, const Register& wm);
894
895 // CRC-32C checksum from double word.
896 void crc32cx(const Register& wd, const Register& wn, const Register& xm);
897
898 // Multiply.
899 void mul(const Register& rd, const Register& rn, const Register& rm);
900
901 // Negated multiply.
902 void mneg(const Register& rd, const Register& rn, const Register& rm);
903
904 // Signed long multiply: 32 x 32 -> 64-bit.
905 void smull(const Register& xd, const Register& wn, const Register& wm);
906
907 // Signed multiply high: 64 x 64 -> 64-bit <127:64>.
908 void smulh(const Register& xd, const Register& xn, const Register& xm);
909
910 // Multiply and accumulate.
911 void madd(const Register& rd,
912 const Register& rn,
913 const Register& rm,
914 const Register& ra);
915
916 // Multiply and subtract.
917 void msub(const Register& rd,
918 const Register& rn,
919 const Register& rm,
920 const Register& ra);
921
922 // Signed long multiply and accumulate: 32 x 32 + 64 -> 64-bit.
923 void smaddl(const Register& xd,
924 const Register& wn,
925 const Register& wm,
926 const Register& xa);
927
928 // Unsigned long multiply and accumulate: 32 x 32 + 64 -> 64-bit.
929 void umaddl(const Register& xd,
930 const Register& wn,
931 const Register& wm,
932 const Register& xa);
933
934 // Unsigned long multiply: 32 x 32 -> 64-bit.
umull(const Register & xd,const Register & wn,const Register & wm)935 void umull(const Register& xd, const Register& wn, const Register& wm) {
936 umaddl(xd, wn, wm, xzr);
937 }
938
939 // Unsigned multiply high: 64 x 64 -> 64-bit <127:64>.
940 void umulh(const Register& xd, const Register& xn, const Register& xm);
941
942 // Signed long multiply and subtract: 64 - (32 x 32) -> 64-bit.
943 void smsubl(const Register& xd,
944 const Register& wn,
945 const Register& wm,
946 const Register& xa);
947
948 // Unsigned long multiply and subtract: 64 - (32 x 32) -> 64-bit.
949 void umsubl(const Register& xd,
950 const Register& wn,
951 const Register& wm,
952 const Register& xa);
953
954 // Signed integer divide.
955 void sdiv(const Register& rd, const Register& rn, const Register& rm);
956
957 // Unsigned integer divide.
958 void udiv(const Register& rd, const Register& rn, const Register& rm);
959
960 // Bit reverse.
961 void rbit(const Register& rd, const Register& rn);
962
963 // Reverse bytes in 16-bit half words.
964 void rev16(const Register& rd, const Register& rn);
965
966 // Reverse bytes in 32-bit words.
967 void rev32(const Register& xd, const Register& xn);
968
969 // Reverse bytes.
970 void rev(const Register& rd, const Register& rn);
971
972 // Count leading zeroes.
973 void clz(const Register& rd, const Register& rn);
974
975 // Count leading sign bits.
976 void cls(const Register& rd, const Register& rn);
977
978 // Memory instructions.
979 // Load integer or FP register.
980 void ldr(const CPURegister& rt,
981 const MemOperand& src,
982 LoadStoreScalingOption option = PreferScaledOffset);
983
984 // Store integer or FP register.
985 void str(const CPURegister& rt,
986 const MemOperand& dst,
987 LoadStoreScalingOption option = PreferScaledOffset);
988
989 // Load word with sign extension.
990 void ldrsw(const Register& xt,
991 const MemOperand& src,
992 LoadStoreScalingOption option = PreferScaledOffset);
993
994 // Load byte.
995 void ldrb(const Register& rt,
996 const MemOperand& src,
997 LoadStoreScalingOption option = PreferScaledOffset);
998
999 // Store byte.
1000 void strb(const Register& rt,
1001 const MemOperand& dst,
1002 LoadStoreScalingOption option = PreferScaledOffset);
1003
1004 // Load byte with sign extension.
1005 void ldrsb(const Register& rt,
1006 const MemOperand& src,
1007 LoadStoreScalingOption option = PreferScaledOffset);
1008
1009 // Load half-word.
1010 void ldrh(const Register& rt,
1011 const MemOperand& src,
1012 LoadStoreScalingOption option = PreferScaledOffset);
1013
1014 // Store half-word.
1015 void strh(const Register& rt,
1016 const MemOperand& dst,
1017 LoadStoreScalingOption option = PreferScaledOffset);
1018
1019 // Load half-word with sign extension.
1020 void ldrsh(const Register& rt,
1021 const MemOperand& src,
1022 LoadStoreScalingOption option = PreferScaledOffset);
1023
1024 // Load integer or FP register (with unscaled offset).
1025 void ldur(const CPURegister& rt,
1026 const MemOperand& src,
1027 LoadStoreScalingOption option = PreferUnscaledOffset);
1028
1029 // Store integer or FP register (with unscaled offset).
1030 void stur(const CPURegister& rt,
1031 const MemOperand& src,
1032 LoadStoreScalingOption option = PreferUnscaledOffset);
1033
1034 // Load word with sign extension.
1035 void ldursw(const Register& xt,
1036 const MemOperand& src,
1037 LoadStoreScalingOption option = PreferUnscaledOffset);
1038
1039 // Load byte (with unscaled offset).
1040 void ldurb(const Register& rt,
1041 const MemOperand& src,
1042 LoadStoreScalingOption option = PreferUnscaledOffset);
1043
1044 // Store byte (with unscaled offset).
1045 void sturb(const Register& rt,
1046 const MemOperand& dst,
1047 LoadStoreScalingOption option = PreferUnscaledOffset);
1048
1049 // Load byte with sign extension (and unscaled offset).
1050 void ldursb(const Register& rt,
1051 const MemOperand& src,
1052 LoadStoreScalingOption option = PreferUnscaledOffset);
1053
1054 // Load half-word (with unscaled offset).
1055 void ldurh(const Register& rt,
1056 const MemOperand& src,
1057 LoadStoreScalingOption option = PreferUnscaledOffset);
1058
1059 // Store half-word (with unscaled offset).
1060 void sturh(const Register& rt,
1061 const MemOperand& dst,
1062 LoadStoreScalingOption option = PreferUnscaledOffset);
1063
1064 // Load half-word with sign extension (and unscaled offset).
1065 void ldursh(const Register& rt,
1066 const MemOperand& src,
1067 LoadStoreScalingOption option = PreferUnscaledOffset);
1068
1069 // Load integer or FP register pair.
1070 void ldp(const CPURegister& rt,
1071 const CPURegister& rt2,
1072 const MemOperand& src);
1073
1074 // Store integer or FP register pair.
1075 void stp(const CPURegister& rt,
1076 const CPURegister& rt2,
1077 const MemOperand& dst);
1078
1079 // Load word pair with sign extension.
1080 void ldpsw(const Register& xt, const Register& xt2, const MemOperand& src);
1081
1082 // Load integer or FP register pair, non-temporal.
1083 void ldnp(const CPURegister& rt,
1084 const CPURegister& rt2,
1085 const MemOperand& src);
1086
1087 // Store integer or FP register pair, non-temporal.
1088 void stnp(const CPURegister& rt,
1089 const CPURegister& rt2,
1090 const MemOperand& dst);
1091
1092 // Load integer or FP register from literal pool.
1093 void ldr(const CPURegister& rt, RawLiteral* literal);
1094
1095 // Load word with sign extension from literal pool.
1096 void ldrsw(const Register& xt, RawLiteral* literal);
1097
1098 // Load integer or FP register from pc + imm19 << 2.
1099 void ldr(const CPURegister& rt, int64_t imm19);
1100
1101 // Load word with sign extension from pc + imm19 << 2.
1102 void ldrsw(const Register& xt, int64_t imm19);
1103
1104 // Store exclusive byte.
1105 void stxrb(const Register& rs, const Register& rt, const MemOperand& dst);
1106
1107 // Store exclusive half-word.
1108 void stxrh(const Register& rs, const Register& rt, const MemOperand& dst);
1109
1110 // Store exclusive register.
1111 void stxr(const Register& rs, const Register& rt, const MemOperand& dst);
1112
1113 // Load exclusive byte.
1114 void ldxrb(const Register& rt, const MemOperand& src);
1115
1116 // Load exclusive half-word.
1117 void ldxrh(const Register& rt, const MemOperand& src);
1118
1119 // Load exclusive register.
1120 void ldxr(const Register& rt, const MemOperand& src);
1121
1122 // Store exclusive register pair.
1123 void stxp(const Register& rs,
1124 const Register& rt,
1125 const Register& rt2,
1126 const MemOperand& dst);
1127
1128 // Load exclusive register pair.
1129 void ldxp(const Register& rt, const Register& rt2, const MemOperand& src);
1130
1131 // Store-release exclusive byte.
1132 void stlxrb(const Register& rs, const Register& rt, const MemOperand& dst);
1133
1134 // Store-release exclusive half-word.
1135 void stlxrh(const Register& rs, const Register& rt, const MemOperand& dst);
1136
1137 // Store-release exclusive register.
1138 void stlxr(const Register& rs, const Register& rt, const MemOperand& dst);
1139
1140 // Load-acquire exclusive byte.
1141 void ldaxrb(const Register& rt, const MemOperand& src);
1142
1143 // Load-acquire exclusive half-word.
1144 void ldaxrh(const Register& rt, const MemOperand& src);
1145
1146 // Load-acquire exclusive register.
1147 void ldaxr(const Register& rt, const MemOperand& src);
1148
1149 // Store-release exclusive register pair.
1150 void stlxp(const Register& rs,
1151 const Register& rt,
1152 const Register& rt2,
1153 const MemOperand& dst);
1154
1155 // Load-acquire exclusive register pair.
1156 void ldaxp(const Register& rt, const Register& rt2, const MemOperand& src);
1157
1158 // Store-release byte.
1159 void stlrb(const Register& rt, const MemOperand& dst);
1160
1161 // Store-release half-word.
1162 void stlrh(const Register& rt, const MemOperand& dst);
1163
1164 // Store-release register.
1165 void stlr(const Register& rt, const MemOperand& dst);
1166
1167 // Load-acquire byte.
1168 void ldarb(const Register& rt, const MemOperand& src);
1169
1170 // Load-acquire half-word.
1171 void ldarh(const Register& rt, const MemOperand& src);
1172
1173 // Load-acquire register.
1174 void ldar(const Register& rt, const MemOperand& src);
1175
1176 // Prefetch memory.
1177 void prfm(PrefetchOperation op,
1178 const MemOperand& addr,
1179 LoadStoreScalingOption option = PreferScaledOffset);
1180
1181 // Prefetch memory (with unscaled offset).
1182 void prfum(PrefetchOperation op,
1183 const MemOperand& addr,
1184 LoadStoreScalingOption option = PreferUnscaledOffset);
1185
1186 // Prefetch memory in the literal pool.
1187 void prfm(PrefetchOperation op, RawLiteral* literal);
1188
1189 // Prefetch from pc + imm19 << 2.
1190 void prfm(PrefetchOperation op, int64_t imm19);
1191
1192 // Move instructions. The default shift of -1 indicates that the move
1193 // instruction will calculate an appropriate 16-bit immediate and left shift
1194 // that is equal to the 64-bit immediate argument. If an explicit left shift
1195 // is specified (0, 16, 32 or 48), the immediate must be a 16-bit value.
1196 //
1197 // For movk, an explicit shift can be used to indicate which half word should
1198 // be overwritten, eg. movk(x0, 0, 0) will overwrite the least-significant
1199 // half word with zero, whereas movk(x0, 0, 48) will overwrite the
1200 // most-significant.
1201
1202 // Move immediate and keep.
1203 void movk(const Register& rd, uint64_t imm, int shift = -1) {
1204 MoveWide(rd, imm, shift, MOVK);
1205 }
1206
1207 // Move inverted immediate.
1208 void movn(const Register& rd, uint64_t imm, int shift = -1) {
1209 MoveWide(rd, imm, shift, MOVN);
1210 }
1211
1212 // Move immediate.
1213 void movz(const Register& rd, uint64_t imm, int shift = -1) {
1214 MoveWide(rd, imm, shift, MOVZ);
1215 }
1216
1217 // Misc instructions.
1218 // Monitor debug-mode breakpoint.
1219 void brk(int code);
1220
1221 // Halting debug-mode breakpoint.
1222 void hlt(int code);
1223
1224 // Generate exception targeting EL1.
1225 void svc(int code);
1226
1227 // Move register to register.
1228 void mov(const Register& rd, const Register& rn);
1229
1230 // Move inverted operand to register.
1231 void mvn(const Register& rd, const Operand& operand);
1232
1233 // System instructions.
1234 // Move to register from system register.
1235 void mrs(const Register& xt, SystemRegister sysreg);
1236
1237 // Move from register to system register.
1238 void msr(SystemRegister sysreg, const Register& xt);
1239
1240 // System instruction.
1241 void sys(int op1, int crn, int crm, int op2, const Register& xt = xzr);
1242
1243 // System instruction with pre-encoded op (op1:crn:crm:op2).
1244 void sys(int op, const Register& xt = xzr);
1245
1246 // System data cache operation.
1247 void dc(DataCacheOp op, const Register& rt);
1248
1249 // System instruction cache operation.
1250 void ic(InstructionCacheOp op, const Register& rt);
1251
1252 // System hint.
1253 void hint(SystemHint code);
1254
1255 // Clear exclusive monitor.
1256 void clrex(int imm4 = 0xf);
1257
1258 // Data memory barrier.
1259 void dmb(BarrierDomain domain, BarrierType type);
1260
1261 // Data synchronization barrier.
1262 void dsb(BarrierDomain domain, BarrierType type);
1263
1264 // Instruction synchronization barrier.
1265 void isb();
1266
1267 // Alias for system instructions.
1268 // No-op.
nop()1269 void nop() { hint(NOP); }
1270
1271 // FP and NEON instructions.
1272 // Move double precision immediate to FP register.
1273 void fmov(const VRegister& vd, double imm);
1274
1275 // Move single precision immediate to FP register.
1276 void fmov(const VRegister& vd, float imm);
1277
1278 // Move FP register to register.
1279 void fmov(const Register& rd, const VRegister& fn);
1280
1281 // Move register to FP register.
1282 void fmov(const VRegister& vd, const Register& rn);
1283
1284 // Move FP register to FP register.
1285 void fmov(const VRegister& vd, const VRegister& fn);
1286
1287 // Move 64-bit register to top half of 128-bit FP register.
1288 void fmov(const VRegister& vd, int index, const Register& rn);
1289
1290 // Move top half of 128-bit FP register to 64-bit register.
1291 void fmov(const Register& rd, const VRegister& vn, int index);
1292
1293 // FP add.
1294 void fadd(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1295
1296 // FP subtract.
1297 void fsub(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1298
1299 // FP multiply.
1300 void fmul(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1301
1302 // FP fused multiply-add.
1303 void fmadd(const VRegister& vd,
1304 const VRegister& vn,
1305 const VRegister& vm,
1306 const VRegister& va);
1307
1308 // FP fused multiply-subtract.
1309 void fmsub(const VRegister& vd,
1310 const VRegister& vn,
1311 const VRegister& vm,
1312 const VRegister& va);
1313
1314 // FP fused multiply-add and negate.
1315 void fnmadd(const VRegister& vd,
1316 const VRegister& vn,
1317 const VRegister& vm,
1318 const VRegister& va);
1319
1320 // FP fused multiply-subtract and negate.
1321 void fnmsub(const VRegister& vd,
1322 const VRegister& vn,
1323 const VRegister& vm,
1324 const VRegister& va);
1325
1326 // FP multiply-negate scalar.
1327 void fnmul(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1328
1329 // FP reciprocal exponent scalar.
1330 void frecpx(const VRegister& vd, const VRegister& vn);
1331
1332 // FP divide.
1333 void fdiv(const VRegister& vd, const VRegister& fn, const VRegister& vm);
1334
1335 // FP maximum.
1336 void fmax(const VRegister& vd, const VRegister& fn, const VRegister& vm);
1337
1338 // FP minimum.
1339 void fmin(const VRegister& vd, const VRegister& fn, const VRegister& vm);
1340
1341 // FP maximum number.
1342 void fmaxnm(const VRegister& vd, const VRegister& fn, const VRegister& vm);
1343
1344 // FP minimum number.
1345 void fminnm(const VRegister& vd, const VRegister& fn, const VRegister& vm);
1346
1347 // FP absolute.
1348 void fabs(const VRegister& vd, const VRegister& vn);
1349
1350 // FP negate.
1351 void fneg(const VRegister& vd, const VRegister& vn);
1352
1353 // FP square root.
1354 void fsqrt(const VRegister& vd, const VRegister& vn);
1355
1356 // FP round to integer, nearest with ties to away.
1357 void frinta(const VRegister& vd, const VRegister& vn);
1358
1359 // FP round to integer, implicit rounding.
1360 void frinti(const VRegister& vd, const VRegister& vn);
1361
1362 // FP round to integer, toward minus infinity.
1363 void frintm(const VRegister& vd, const VRegister& vn);
1364
1365 // FP round to integer, nearest with ties to even.
1366 void frintn(const VRegister& vd, const VRegister& vn);
1367
1368 // FP round to integer, toward plus infinity.
1369 void frintp(const VRegister& vd, const VRegister& vn);
1370
1371 // FP round to integer, exact, implicit rounding.
1372 void frintx(const VRegister& vd, const VRegister& vn);
1373
1374 // FP round to integer, towards zero.
1375 void frintz(const VRegister& vd, const VRegister& vn);
1376
1377 void FPCompareMacro(const VRegister& vn, double value, FPTrapFlags trap);
1378
1379 void FPCompareMacro(const VRegister& vn,
1380 const VRegister& vm,
1381 FPTrapFlags trap);
1382
1383 // FP compare registers.
1384 void fcmp(const VRegister& vn, const VRegister& vm);
1385
1386 // FP compare immediate.
1387 void fcmp(const VRegister& vn, double value);
1388
1389 void FPCCompareMacro(const VRegister& vn,
1390 const VRegister& vm,
1391 StatusFlags nzcv,
1392 Condition cond,
1393 FPTrapFlags trap);
1394
1395 // FP conditional compare.
1396 void fccmp(const VRegister& vn,
1397 const VRegister& vm,
1398 StatusFlags nzcv,
1399 Condition cond);
1400
1401 // FP signaling compare registers.
1402 void fcmpe(const VRegister& vn, const VRegister& vm);
1403
1404 // FP signaling compare immediate.
1405 void fcmpe(const VRegister& vn, double value);
1406
1407 // FP conditional signaling compare.
1408 void fccmpe(const VRegister& vn,
1409 const VRegister& vm,
1410 StatusFlags nzcv,
1411 Condition cond);
1412
1413 // FP conditional select.
1414 void fcsel(const VRegister& vd,
1415 const VRegister& vn,
1416 const VRegister& vm,
1417 Condition cond);
1418
1419 // Common FP Convert functions.
1420 void NEONFPConvertToInt(const Register& rd, const VRegister& vn, Instr op);
1421 void NEONFPConvertToInt(const VRegister& vd, const VRegister& vn, Instr op);
1422
1423 // FP convert between precisions.
1424 void fcvt(const VRegister& vd, const VRegister& vn);
1425
1426 // FP convert to higher precision.
1427 void fcvtl(const VRegister& vd, const VRegister& vn);
1428
1429 // FP convert to higher precision (second part).
1430 void fcvtl2(const VRegister& vd, const VRegister& vn);
1431
1432 // FP convert to lower precision.
1433 void fcvtn(const VRegister& vd, const VRegister& vn);
1434
1435 // FP convert to lower prevision (second part).
1436 void fcvtn2(const VRegister& vd, const VRegister& vn);
1437
1438 // FP convert to lower precision, rounding to odd.
1439 void fcvtxn(const VRegister& vd, const VRegister& vn);
1440
1441 // FP convert to lower precision, rounding to odd (second part).
1442 void fcvtxn2(const VRegister& vd, const VRegister& vn);
1443
1444 // FP convert to signed integer, nearest with ties to away.
1445 void fcvtas(const Register& rd, const VRegister& vn);
1446
1447 // FP convert to unsigned integer, nearest with ties to away.
1448 void fcvtau(const Register& rd, const VRegister& vn);
1449
1450 // FP convert to signed integer, nearest with ties to away.
1451 void fcvtas(const VRegister& vd, const VRegister& vn);
1452
1453 // FP convert to unsigned integer, nearest with ties to away.
1454 void fcvtau(const VRegister& vd, const VRegister& vn);
1455
1456 // FP convert to signed integer, round towards -infinity.
1457 void fcvtms(const Register& rd, const VRegister& vn);
1458
1459 // FP convert to unsigned integer, round towards -infinity.
1460 void fcvtmu(const Register& rd, const VRegister& vn);
1461
1462 // FP convert to signed integer, round towards -infinity.
1463 void fcvtms(const VRegister& vd, const VRegister& vn);
1464
1465 // FP convert to unsigned integer, round towards -infinity.
1466 void fcvtmu(const VRegister& vd, const VRegister& vn);
1467
1468 // FP convert to signed integer, nearest with ties to even.
1469 void fcvtns(const Register& rd, const VRegister& vn);
1470
1471 // FP convert to unsigned integer, nearest with ties to even.
1472 void fcvtnu(const Register& rd, const VRegister& vn);
1473
1474 // FP convert to signed integer, nearest with ties to even.
1475 void fcvtns(const VRegister& rd, const VRegister& vn);
1476
1477 // FP convert to unsigned integer, nearest with ties to even.
1478 void fcvtnu(const VRegister& rd, const VRegister& vn);
1479
1480 // FP convert to signed integer or fixed-point, round towards zero.
1481 void fcvtzs(const Register& rd, const VRegister& vn, int fbits = 0);
1482
1483 // FP convert to unsigned integer or fixed-point, round towards zero.
1484 void fcvtzu(const Register& rd, const VRegister& vn, int fbits = 0);
1485
1486 // FP convert to signed integer or fixed-point, round towards zero.
1487 void fcvtzs(const VRegister& vd, const VRegister& vn, int fbits = 0);
1488
1489 // FP convert to unsigned integer or fixed-point, round towards zero.
1490 void fcvtzu(const VRegister& vd, const VRegister& vn, int fbits = 0);
1491
1492 // FP convert to signed integer, round towards +infinity.
1493 void fcvtps(const Register& rd, const VRegister& vn);
1494
1495 // FP convert to unsigned integer, round towards +infinity.
1496 void fcvtpu(const Register& rd, const VRegister& vn);
1497
1498 // FP convert to signed integer, round towards +infinity.
1499 void fcvtps(const VRegister& vd, const VRegister& vn);
1500
1501 // FP convert to unsigned integer, round towards +infinity.
1502 void fcvtpu(const VRegister& vd, const VRegister& vn);
1503
1504 // Convert signed integer or fixed point to FP.
1505 void scvtf(const VRegister& fd, const Register& rn, int fbits = 0);
1506
1507 // Convert unsigned integer or fixed point to FP.
1508 void ucvtf(const VRegister& fd, const Register& rn, int fbits = 0);
1509
1510 // Convert signed integer or fixed-point to FP.
1511 void scvtf(const VRegister& fd, const VRegister& vn, int fbits = 0);
1512
1513 // Convert unsigned integer or fixed-point to FP.
1514 void ucvtf(const VRegister& fd, const VRegister& vn, int fbits = 0);
1515
1516 // Unsigned absolute difference.
1517 void uabd(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1518
1519 // Signed absolute difference.
1520 void sabd(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1521
1522 // Unsigned absolute difference and accumulate.
1523 void uaba(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1524
1525 // Signed absolute difference and accumulate.
1526 void saba(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1527
1528 // Add.
1529 void add(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1530
1531 // Subtract.
1532 void sub(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1533
1534 // Unsigned halving add.
1535 void uhadd(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1536
1537 // Signed halving add.
1538 void shadd(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1539
1540 // Unsigned rounding halving add.
1541 void urhadd(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1542
1543 // Signed rounding halving add.
1544 void srhadd(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1545
1546 // Unsigned halving sub.
1547 void uhsub(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1548
1549 // Signed halving sub.
1550 void shsub(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1551
1552 // Unsigned saturating add.
1553 void uqadd(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1554
1555 // Signed saturating add.
1556 void sqadd(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1557
1558 // Unsigned saturating subtract.
1559 void uqsub(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1560
1561 // Signed saturating subtract.
1562 void sqsub(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1563
1564 // Add pairwise.
1565 void addp(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1566
1567 // Add pair of elements scalar.
1568 void addp(const VRegister& vd, const VRegister& vn);
1569
1570 // Multiply-add to accumulator.
1571 void mla(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1572
1573 // Multiply-subtract to accumulator.
1574 void mls(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1575
1576 // Multiply.
1577 void mul(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1578
1579 // Multiply by scalar element.
1580 void mul(const VRegister& vd,
1581 const VRegister& vn,
1582 const VRegister& vm,
1583 int vm_index);
1584
1585 // Multiply-add by scalar element.
1586 void mla(const VRegister& vd,
1587 const VRegister& vn,
1588 const VRegister& vm,
1589 int vm_index);
1590
1591 // Multiply-subtract by scalar element.
1592 void mls(const VRegister& vd,
1593 const VRegister& vn,
1594 const VRegister& vm,
1595 int vm_index);
1596
1597 // Signed long multiply-add by scalar element.
1598 void smlal(const VRegister& vd,
1599 const VRegister& vn,
1600 const VRegister& vm,
1601 int vm_index);
1602
1603 // Signed long multiply-add by scalar element (second part).
1604 void smlal2(const VRegister& vd,
1605 const VRegister& vn,
1606 const VRegister& vm,
1607 int vm_index);
1608
1609 // Unsigned long multiply-add by scalar element.
1610 void umlal(const VRegister& vd,
1611 const VRegister& vn,
1612 const VRegister& vm,
1613 int vm_index);
1614
1615 // Unsigned long multiply-add by scalar element (second part).
1616 void umlal2(const VRegister& vd,
1617 const VRegister& vn,
1618 const VRegister& vm,
1619 int vm_index);
1620
1621 // Signed long multiply-sub by scalar element.
1622 void smlsl(const VRegister& vd,
1623 const VRegister& vn,
1624 const VRegister& vm,
1625 int vm_index);
1626
1627 // Signed long multiply-sub by scalar element (second part).
1628 void smlsl2(const VRegister& vd,
1629 const VRegister& vn,
1630 const VRegister& vm,
1631 int vm_index);
1632
1633 // Unsigned long multiply-sub by scalar element.
1634 void umlsl(const VRegister& vd,
1635 const VRegister& vn,
1636 const VRegister& vm,
1637 int vm_index);
1638
1639 // Unsigned long multiply-sub by scalar element (second part).
1640 void umlsl2(const VRegister& vd,
1641 const VRegister& vn,
1642 const VRegister& vm,
1643 int vm_index);
1644
1645 // Signed long multiply by scalar element.
1646 void smull(const VRegister& vd,
1647 const VRegister& vn,
1648 const VRegister& vm,
1649 int vm_index);
1650
1651 // Signed long multiply by scalar element (second part).
1652 void smull2(const VRegister& vd,
1653 const VRegister& vn,
1654 const VRegister& vm,
1655 int vm_index);
1656
1657 // Unsigned long multiply by scalar element.
1658 void umull(const VRegister& vd,
1659 const VRegister& vn,
1660 const VRegister& vm,
1661 int vm_index);
1662
1663 // Unsigned long multiply by scalar element (second part).
1664 void umull2(const VRegister& vd,
1665 const VRegister& vn,
1666 const VRegister& vm,
1667 int vm_index);
1668
1669 // Signed saturating double long multiply by element.
1670 void sqdmull(const VRegister& vd,
1671 const VRegister& vn,
1672 const VRegister& vm,
1673 int vm_index);
1674
1675 // Signed saturating double long multiply by element (second part).
1676 void sqdmull2(const VRegister& vd,
1677 const VRegister& vn,
1678 const VRegister& vm,
1679 int vm_index);
1680
1681 // Signed saturating doubling long multiply-add by element.
1682 void sqdmlal(const VRegister& vd,
1683 const VRegister& vn,
1684 const VRegister& vm,
1685 int vm_index);
1686
1687 // Signed saturating doubling long multiply-add by element (second part).
1688 void sqdmlal2(const VRegister& vd,
1689 const VRegister& vn,
1690 const VRegister& vm,
1691 int vm_index);
1692
1693 // Signed saturating doubling long multiply-sub by element.
1694 void sqdmlsl(const VRegister& vd,
1695 const VRegister& vn,
1696 const VRegister& vm,
1697 int vm_index);
1698
1699 // Signed saturating doubling long multiply-sub by element (second part).
1700 void sqdmlsl2(const VRegister& vd,
1701 const VRegister& vn,
1702 const VRegister& vm,
1703 int vm_index);
1704
1705 // Compare equal.
1706 void cmeq(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1707
1708 // Compare signed greater than or equal.
1709 void cmge(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1710
1711 // Compare signed greater than.
1712 void cmgt(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1713
1714 // Compare unsigned higher.
1715 void cmhi(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1716
1717 // Compare unsigned higher or same.
1718 void cmhs(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1719
1720 // Compare bitwise test bits nonzero.
1721 void cmtst(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1722
1723 // Compare bitwise to zero.
1724 void cmeq(const VRegister& vd, const VRegister& vn, int value);
1725
1726 // Compare signed greater than or equal to zero.
1727 void cmge(const VRegister& vd, const VRegister& vn, int value);
1728
1729 // Compare signed greater than zero.
1730 void cmgt(const VRegister& vd, const VRegister& vn, int value);
1731
1732 // Compare signed less than or equal to zero.
1733 void cmle(const VRegister& vd, const VRegister& vn, int value);
1734
1735 // Compare signed less than zero.
1736 void cmlt(const VRegister& vd, const VRegister& vn, int value);
1737
1738 // Signed shift left by register.
1739 void sshl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1740
1741 // Unsigned shift left by register.
1742 void ushl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1743
1744 // Signed saturating shift left by register.
1745 void sqshl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1746
1747 // Unsigned saturating shift left by register.
1748 void uqshl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1749
1750 // Signed rounding shift left by register.
1751 void srshl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1752
1753 // Unsigned rounding shift left by register.
1754 void urshl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1755
1756 // Signed saturating rounding shift left by register.
1757 void sqrshl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1758
1759 // Unsigned saturating rounding shift left by register.
1760 void uqrshl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1761
1762 // Bitwise and.
1763 void and_(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1764
1765 // Bitwise or.
1766 void orr(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1767
1768 // Bitwise or immediate.
1769 void orr(const VRegister& vd, const int imm8, const int left_shift = 0);
1770
1771 // Move register to register.
1772 void mov(const VRegister& vd, const VRegister& vn);
1773
1774 // Bitwise orn.
1775 void orn(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1776
1777 // Bitwise eor.
1778 void eor(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1779
1780 // Bit clear immediate.
1781 void bic(const VRegister& vd, const int imm8, const int left_shift = 0);
1782
1783 // Bit clear.
1784 void bic(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1785
1786 // Bitwise insert if false.
1787 void bif(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1788
1789 // Bitwise insert if true.
1790 void bit(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1791
1792 // Bitwise select.
1793 void bsl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1794
1795 // Polynomial multiply.
1796 void pmul(const VRegister& vd, const VRegister& vn, const VRegister& vm);
1797
1798 // Vector move immediate.
1799 void movi(const VRegister& vd,
1800 const uint64_t imm,
1801 Shift shift = LSL,
1802 const int shift_amount = 0);
1803
1804 // Bitwise not.
1805 void mvn(const VRegister& vd, const VRegister& vn);
1806
1807 // Vector move inverted immediate.
1808 void mvni(const VRegister& vd,
1809 const int imm8,
1810 Shift shift = LSL,
1811 const int shift_amount = 0);
1812
1813 // Signed saturating accumulate of unsigned value.
1814 void suqadd(const VRegister& vd, const VRegister& vn);
1815
1816 // Unsigned saturating accumulate of signed value.
1817 void usqadd(const VRegister& vd, const VRegister& vn);
1818
1819 // Absolute value.
1820 void abs(const VRegister& vd, const VRegister& vn);
1821
1822 // Signed saturating absolute value.
1823 void sqabs(const VRegister& vd, const VRegister& vn);
1824
1825 // Negate.
1826 void neg(const VRegister& vd, const VRegister& vn);
1827
1828 // Signed saturating negate.
1829 void sqneg(const VRegister& vd, const VRegister& vn);
1830
1831 // Bitwise not.
1832 void not_(const VRegister& vd, const VRegister& vn);
1833
1834 // Extract narrow.
1835 void xtn(const VRegister& vd, const VRegister& vn);
1836
1837 // Extract narrow (second part).
1838 void xtn2(const VRegister& vd, const VRegister& vn);
1839
1840 // Signed saturating extract narrow.
1841 void sqxtn(const VRegister& vd, const VRegister& vn);
1842
1843 // Signed saturating extract narrow (second part).
1844 void sqxtn2(const VRegister& vd, const VRegister& vn);
1845
1846 // Unsigned saturating extract narrow.
1847 void uqxtn(const VRegister& vd, const VRegister& vn);
1848
1849 // Unsigned saturating extract narrow (second part).
1850 void uqxtn2(const VRegister& vd, const VRegister& vn);
1851
1852 // Signed saturating extract unsigned narrow.
1853 void sqxtun(const VRegister& vd, const VRegister& vn);
1854
1855 // Signed saturating extract unsigned narrow (second part).
1856 void sqxtun2(const VRegister& vd, const VRegister& vn);
1857
1858 // Extract vector from pair of vectors.
1859 void ext(const VRegister& vd,
1860 const VRegister& vn,
1861 const VRegister& vm,
1862 int index);
1863
1864 // Duplicate vector element to vector or scalar.
1865 void dup(const VRegister& vd, const VRegister& vn, int vn_index);
1866
1867 // Move vector element to scalar.
1868 void mov(const VRegister& vd, const VRegister& vn, int vn_index);
1869
1870 // Duplicate general-purpose register to vector.
1871 void dup(const VRegister& vd, const Register& rn);
1872
1873 // Insert vector element from another vector element.
1874 void ins(const VRegister& vd,
1875 int vd_index,
1876 const VRegister& vn,
1877 int vn_index);
1878
1879 // Move vector element to another vector element.
1880 void mov(const VRegister& vd,
1881 int vd_index,
1882 const VRegister& vn,
1883 int vn_index);
1884
1885 // Insert vector element from general-purpose register.
1886 void ins(const VRegister& vd, int vd_index, const Register& rn);
1887
1888 // Move general-purpose register to a vector element.
1889 void mov(const VRegister& vd, int vd_index, const Register& rn);
1890
1891 // Unsigned move vector element to general-purpose register.
1892 void umov(const Register& rd, const VRegister& vn, int vn_index);
1893
1894 // Move vector element to general-purpose register.
1895 void mov(const Register& rd, const VRegister& vn, int vn_index);
1896
1897 // Signed move vector element to general-purpose register.
1898 void smov(const Register& rd, const VRegister& vn, int vn_index);
1899
1900 // One-element structure load to one register.
1901 void ld1(const VRegister& vt, const MemOperand& src);
1902
1903 // One-element structure load to two registers.
1904 void ld1(const VRegister& vt, const VRegister& vt2, const MemOperand& src);
1905
1906 // One-element structure load to three registers.
1907 void ld1(const VRegister& vt,
1908 const VRegister& vt2,
1909 const VRegister& vt3,
1910 const MemOperand& src);
1911
1912 // One-element structure load to four registers.
1913 void ld1(const VRegister& vt,
1914 const VRegister& vt2,
1915 const VRegister& vt3,
1916 const VRegister& vt4,
1917 const MemOperand& src);
1918
1919 // One-element single structure load to one lane.
1920 void ld1(const VRegister& vt, int lane, const MemOperand& src);
1921
1922 // One-element single structure load to all lanes.
1923 void ld1r(const VRegister& vt, const MemOperand& src);
1924
1925 // Two-element structure load.
1926 void ld2(const VRegister& vt, const VRegister& vt2, const MemOperand& src);
1927
1928 // Two-element single structure load to one lane.
1929 void ld2(const VRegister& vt,
1930 const VRegister& vt2,
1931 int lane,
1932 const MemOperand& src);
1933
1934 // Two-element single structure load to all lanes.
1935 void ld2r(const VRegister& vt, const VRegister& vt2, const MemOperand& src);
1936
1937 // Three-element structure load.
1938 void ld3(const VRegister& vt,
1939 const VRegister& vt2,
1940 const VRegister& vt3,
1941 const MemOperand& src);
1942
1943 // Three-element single structure load to one lane.
1944 void ld3(const VRegister& vt,
1945 const VRegister& vt2,
1946 const VRegister& vt3,
1947 int lane,
1948 const MemOperand& src);
1949
1950 // Three-element single structure load to all lanes.
1951 void ld3r(const VRegister& vt,
1952 const VRegister& vt2,
1953 const VRegister& vt3,
1954 const MemOperand& src);
1955
1956 // Four-element structure load.
1957 void ld4(const VRegister& vt,
1958 const VRegister& vt2,
1959 const VRegister& vt3,
1960 const VRegister& vt4,
1961 const MemOperand& src);
1962
1963 // Four-element single structure load to one lane.
1964 void ld4(const VRegister& vt,
1965 const VRegister& vt2,
1966 const VRegister& vt3,
1967 const VRegister& vt4,
1968 int lane,
1969 const MemOperand& src);
1970
1971 // Four-element single structure load to all lanes.
1972 void ld4r(const VRegister& vt,
1973 const VRegister& vt2,
1974 const VRegister& vt3,
1975 const VRegister& vt4,
1976 const MemOperand& src);
1977
1978 // Count leading sign bits.
1979 void cls(const VRegister& vd, const VRegister& vn);
1980
1981 // Count leading zero bits (vector).
1982 void clz(const VRegister& vd, const VRegister& vn);
1983
1984 // Population count per byte.
1985 void cnt(const VRegister& vd, const VRegister& vn);
1986
1987 // Reverse bit order.
1988 void rbit(const VRegister& vd, const VRegister& vn);
1989
1990 // Reverse elements in 16-bit halfwords.
1991 void rev16(const VRegister& vd, const VRegister& vn);
1992
1993 // Reverse elements in 32-bit words.
1994 void rev32(const VRegister& vd, const VRegister& vn);
1995
1996 // Reverse elements in 64-bit doublewords.
1997 void rev64(const VRegister& vd, const VRegister& vn);
1998
1999 // Unsigned reciprocal square root estimate.
2000 void ursqrte(const VRegister& vd, const VRegister& vn);
2001
2002 // Unsigned reciprocal estimate.
2003 void urecpe(const VRegister& vd, const VRegister& vn);
2004
2005 // Signed pairwise long add.
2006 void saddlp(const VRegister& vd, const VRegister& vn);
2007
2008 // Unsigned pairwise long add.
2009 void uaddlp(const VRegister& vd, const VRegister& vn);
2010
2011 // Signed pairwise long add and accumulate.
2012 void sadalp(const VRegister& vd, const VRegister& vn);
2013
2014 // Unsigned pairwise long add and accumulate.
2015 void uadalp(const VRegister& vd, const VRegister& vn);
2016
2017 // Shift left by immediate.
2018 void shl(const VRegister& vd, const VRegister& vn, int shift);
2019
2020 // Signed saturating shift left by immediate.
2021 void sqshl(const VRegister& vd, const VRegister& vn, int shift);
2022
2023 // Signed saturating shift left unsigned by immediate.
2024 void sqshlu(const VRegister& vd, const VRegister& vn, int shift);
2025
2026 // Unsigned saturating shift left by immediate.
2027 void uqshl(const VRegister& vd, const VRegister& vn, int shift);
2028
2029 // Signed shift left long by immediate.
2030 void sshll(const VRegister& vd, const VRegister& vn, int shift);
2031
2032 // Signed shift left long by immediate (second part).
2033 void sshll2(const VRegister& vd, const VRegister& vn, int shift);
2034
2035 // Signed extend long.
2036 void sxtl(const VRegister& vd, const VRegister& vn);
2037
2038 // Signed extend long (second part).
2039 void sxtl2(const VRegister& vd, const VRegister& vn);
2040
2041 // Unsigned shift left long by immediate.
2042 void ushll(const VRegister& vd, const VRegister& vn, int shift);
2043
2044 // Unsigned shift left long by immediate (second part).
2045 void ushll2(const VRegister& vd, const VRegister& vn, int shift);
2046
2047 // Shift left long by element size.
2048 void shll(const VRegister& vd, const VRegister& vn, int shift);
2049
2050 // Shift left long by element size (second part).
2051 void shll2(const VRegister& vd, const VRegister& vn, int shift);
2052
2053 // Unsigned extend long.
2054 void uxtl(const VRegister& vd, const VRegister& vn);
2055
2056 // Unsigned extend long (second part).
2057 void uxtl2(const VRegister& vd, const VRegister& vn);
2058
2059 // Shift left by immediate and insert.
2060 void sli(const VRegister& vd, const VRegister& vn, int shift);
2061
2062 // Shift right by immediate and insert.
2063 void sri(const VRegister& vd, const VRegister& vn, int shift);
2064
2065 // Signed maximum.
2066 void smax(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2067
2068 // Signed pairwise maximum.
2069 void smaxp(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2070
2071 // Add across vector.
2072 void addv(const VRegister& vd, const VRegister& vn);
2073
2074 // Signed add long across vector.
2075 void saddlv(const VRegister& vd, const VRegister& vn);
2076
2077 // Unsigned add long across vector.
2078 void uaddlv(const VRegister& vd, const VRegister& vn);
2079
2080 // FP maximum number across vector.
2081 void fmaxnmv(const VRegister& vd, const VRegister& vn);
2082
2083 // FP maximum across vector.
2084 void fmaxv(const VRegister& vd, const VRegister& vn);
2085
2086 // FP minimum number across vector.
2087 void fminnmv(const VRegister& vd, const VRegister& vn);
2088
2089 // FP minimum across vector.
2090 void fminv(const VRegister& vd, const VRegister& vn);
2091
2092 // Signed maximum across vector.
2093 void smaxv(const VRegister& vd, const VRegister& vn);
2094
2095 // Signed minimum.
2096 void smin(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2097
2098 // Signed minimum pairwise.
2099 void sminp(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2100
2101 // Signed minimum across vector.
2102 void sminv(const VRegister& vd, const VRegister& vn);
2103
2104 // One-element structure store from one register.
2105 void st1(const VRegister& vt, const MemOperand& src);
2106
2107 // One-element structure store from two registers.
2108 void st1(const VRegister& vt, const VRegister& vt2, const MemOperand& src);
2109
2110 // One-element structure store from three registers.
2111 void st1(const VRegister& vt,
2112 const VRegister& vt2,
2113 const VRegister& vt3,
2114 const MemOperand& src);
2115
2116 // One-element structure store from four registers.
2117 void st1(const VRegister& vt,
2118 const VRegister& vt2,
2119 const VRegister& vt3,
2120 const VRegister& vt4,
2121 const MemOperand& src);
2122
2123 // One-element single structure store from one lane.
2124 void st1(const VRegister& vt, int lane, const MemOperand& src);
2125
2126 // Two-element structure store from two registers.
2127 void st2(const VRegister& vt, const VRegister& vt2, const MemOperand& src);
2128
2129 // Two-element single structure store from two lanes.
2130 void st2(const VRegister& vt,
2131 const VRegister& vt2,
2132 int lane,
2133 const MemOperand& src);
2134
2135 // Three-element structure store from three registers.
2136 void st3(const VRegister& vt,
2137 const VRegister& vt2,
2138 const VRegister& vt3,
2139 const MemOperand& src);
2140
2141 // Three-element single structure store from three lanes.
2142 void st3(const VRegister& vt,
2143 const VRegister& vt2,
2144 const VRegister& vt3,
2145 int lane,
2146 const MemOperand& src);
2147
2148 // Four-element structure store from four registers.
2149 void st4(const VRegister& vt,
2150 const VRegister& vt2,
2151 const VRegister& vt3,
2152 const VRegister& vt4,
2153 const MemOperand& src);
2154
2155 // Four-element single structure store from four lanes.
2156 void st4(const VRegister& vt,
2157 const VRegister& vt2,
2158 const VRegister& vt3,
2159 const VRegister& vt4,
2160 int lane,
2161 const MemOperand& src);
2162
2163 // Unsigned add long.
2164 void uaddl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2165
2166 // Unsigned add long (second part).
2167 void uaddl2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2168
2169 // Unsigned add wide.
2170 void uaddw(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2171
2172 // Unsigned add wide (second part).
2173 void uaddw2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2174
2175 // Signed add long.
2176 void saddl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2177
2178 // Signed add long (second part).
2179 void saddl2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2180
2181 // Signed add wide.
2182 void saddw(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2183
2184 // Signed add wide (second part).
2185 void saddw2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2186
2187 // Unsigned subtract long.
2188 void usubl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2189
2190 // Unsigned subtract long (second part).
2191 void usubl2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2192
2193 // Unsigned subtract wide.
2194 void usubw(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2195
2196 // Unsigned subtract wide (second part).
2197 void usubw2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2198
2199 // Signed subtract long.
2200 void ssubl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2201
2202 // Signed subtract long (second part).
2203 void ssubl2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2204
2205 // Signed integer subtract wide.
2206 void ssubw(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2207
2208 // Signed integer subtract wide (second part).
2209 void ssubw2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2210
2211 // Unsigned maximum.
2212 void umax(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2213
2214 // Unsigned pairwise maximum.
2215 void umaxp(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2216
2217 // Unsigned maximum across vector.
2218 void umaxv(const VRegister& vd, const VRegister& vn);
2219
2220 // Unsigned minimum.
2221 void umin(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2222
2223 // Unsigned pairwise minimum.
2224 void uminp(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2225
2226 // Unsigned minimum across vector.
2227 void uminv(const VRegister& vd, const VRegister& vn);
2228
2229 // Transpose vectors (primary).
2230 void trn1(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2231
2232 // Transpose vectors (secondary).
2233 void trn2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2234
2235 // Unzip vectors (primary).
2236 void uzp1(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2237
2238 // Unzip vectors (secondary).
2239 void uzp2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2240
2241 // Zip vectors (primary).
2242 void zip1(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2243
2244 // Zip vectors (secondary).
2245 void zip2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2246
2247 // Signed shift right by immediate.
2248 void sshr(const VRegister& vd, const VRegister& vn, int shift);
2249
2250 // Unsigned shift right by immediate.
2251 void ushr(const VRegister& vd, const VRegister& vn, int shift);
2252
2253 // Signed rounding shift right by immediate.
2254 void srshr(const VRegister& vd, const VRegister& vn, int shift);
2255
2256 // Unsigned rounding shift right by immediate.
2257 void urshr(const VRegister& vd, const VRegister& vn, int shift);
2258
2259 // Signed shift right by immediate and accumulate.
2260 void ssra(const VRegister& vd, const VRegister& vn, int shift);
2261
2262 // Unsigned shift right by immediate and accumulate.
2263 void usra(const VRegister& vd, const VRegister& vn, int shift);
2264
2265 // Signed rounding shift right by immediate and accumulate.
2266 void srsra(const VRegister& vd, const VRegister& vn, int shift);
2267
2268 // Unsigned rounding shift right by immediate and accumulate.
2269 void ursra(const VRegister& vd, const VRegister& vn, int shift);
2270
2271 // Shift right narrow by immediate.
2272 void shrn(const VRegister& vd, const VRegister& vn, int shift);
2273
2274 // Shift right narrow by immediate (second part).
2275 void shrn2(const VRegister& vd, const VRegister& vn, int shift);
2276
2277 // Rounding shift right narrow by immediate.
2278 void rshrn(const VRegister& vd, const VRegister& vn, int shift);
2279
2280 // Rounding shift right narrow by immediate (second part).
2281 void rshrn2(const VRegister& vd, const VRegister& vn, int shift);
2282
2283 // Unsigned saturating shift right narrow by immediate.
2284 void uqshrn(const VRegister& vd, const VRegister& vn, int shift);
2285
2286 // Unsigned saturating shift right narrow by immediate (second part).
2287 void uqshrn2(const VRegister& vd, const VRegister& vn, int shift);
2288
2289 // Unsigned saturating rounding shift right narrow by immediate.
2290 void uqrshrn(const VRegister& vd, const VRegister& vn, int shift);
2291
2292 // Unsigned saturating rounding shift right narrow by immediate (second part).
2293 void uqrshrn2(const VRegister& vd, const VRegister& vn, int shift);
2294
2295 // Signed saturating shift right narrow by immediate.
2296 void sqshrn(const VRegister& vd, const VRegister& vn, int shift);
2297
2298 // Signed saturating shift right narrow by immediate (second part).
2299 void sqshrn2(const VRegister& vd, const VRegister& vn, int shift);
2300
2301 // Signed saturating rounded shift right narrow by immediate.
2302 void sqrshrn(const VRegister& vd, const VRegister& vn, int shift);
2303
2304 // Signed saturating rounded shift right narrow by immediate (second part).
2305 void sqrshrn2(const VRegister& vd, const VRegister& vn, int shift);
2306
2307 // Signed saturating shift right unsigned narrow by immediate.
2308 void sqshrun(const VRegister& vd, const VRegister& vn, int shift);
2309
2310 // Signed saturating shift right unsigned narrow by immediate (second part).
2311 void sqshrun2(const VRegister& vd, const VRegister& vn, int shift);
2312
2313 // Signed sat rounded shift right unsigned narrow by immediate.
2314 void sqrshrun(const VRegister& vd, const VRegister& vn, int shift);
2315
2316 // Signed sat rounded shift right unsigned narrow by immediate (second part).
2317 void sqrshrun2(const VRegister& vd, const VRegister& vn, int shift);
2318
2319 // FP reciprocal step.
2320 void frecps(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2321
2322 // FP reciprocal estimate.
2323 void frecpe(const VRegister& vd, const VRegister& vn);
2324
2325 // FP reciprocal square root estimate.
2326 void frsqrte(const VRegister& vd, const VRegister& vn);
2327
2328 // FP reciprocal square root step.
2329 void frsqrts(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2330
2331 // Signed absolute difference and accumulate long.
2332 void sabal(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2333
2334 // Signed absolute difference and accumulate long (second part).
2335 void sabal2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2336
2337 // Unsigned absolute difference and accumulate long.
2338 void uabal(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2339
2340 // Unsigned absolute difference and accumulate long (second part).
2341 void uabal2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2342
2343 // Signed absolute difference long.
2344 void sabdl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2345
2346 // Signed absolute difference long (second part).
2347 void sabdl2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2348
2349 // Unsigned absolute difference long.
2350 void uabdl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2351
2352 // Unsigned absolute difference long (second part).
2353 void uabdl2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2354
2355 // Polynomial multiply long.
2356 void pmull(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2357
2358 // Polynomial multiply long (second part).
2359 void pmull2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2360
2361 // Signed long multiply-add.
2362 void smlal(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2363
2364 // Signed long multiply-add (second part).
2365 void smlal2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2366
2367 // Unsigned long multiply-add.
2368 void umlal(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2369
2370 // Unsigned long multiply-add (second part).
2371 void umlal2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2372
2373 // Signed long multiply-sub.
2374 void smlsl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2375
2376 // Signed long multiply-sub (second part).
2377 void smlsl2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2378
2379 // Unsigned long multiply-sub.
2380 void umlsl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2381
2382 // Unsigned long multiply-sub (second part).
2383 void umlsl2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2384
2385 // Signed long multiply.
2386 void smull(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2387
2388 // Signed long multiply (second part).
2389 void smull2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2390
2391 // Signed saturating doubling long multiply-add.
2392 void sqdmlal(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2393
2394 // Signed saturating doubling long multiply-add (second part).
2395 void sqdmlal2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2396
2397 // Signed saturating doubling long multiply-subtract.
2398 void sqdmlsl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2399
2400 // Signed saturating doubling long multiply-subtract (second part).
2401 void sqdmlsl2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2402
2403 // Signed saturating doubling long multiply.
2404 void sqdmull(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2405
2406 // Signed saturating doubling long multiply (second part).
2407 void sqdmull2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2408
2409 // Signed saturating doubling multiply returning high half.
2410 void sqdmulh(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2411
2412 // Signed saturating rounding doubling multiply returning high half.
2413 void sqrdmulh(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2414
2415 // Signed saturating doubling multiply element returning high half.
2416 void sqdmulh(const VRegister& vd,
2417 const VRegister& vn,
2418 const VRegister& vm,
2419 int vm_index);
2420
2421 // Signed saturating rounding doubling multiply element returning high half.
2422 void sqrdmulh(const VRegister& vd,
2423 const VRegister& vn,
2424 const VRegister& vm,
2425 int vm_index);
2426
2427 // Unsigned long multiply long.
2428 void umull(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2429
2430 // Unsigned long multiply (second part).
2431 void umull2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2432
2433 // Add narrow returning high half.
2434 void addhn(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2435
2436 // Add narrow returning high half (second part).
2437 void addhn2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2438
2439 // Rounding add narrow returning high half.
2440 void raddhn(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2441
2442 // Rounding add narrow returning high half (second part).
2443 void raddhn2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2444
2445 // Subtract narrow returning high half.
2446 void subhn(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2447
2448 // Subtract narrow returning high half (second part).
2449 void subhn2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2450
2451 // Rounding subtract narrow returning high half.
2452 void rsubhn(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2453
2454 // Rounding subtract narrow returning high half (second part).
2455 void rsubhn2(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2456
2457 // FP vector multiply accumulate.
2458 void fmla(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2459
2460 // FP vector multiply subtract.
2461 void fmls(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2462
2463 // FP vector multiply extended.
2464 void fmulx(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2465
2466 // FP absolute greater than or equal.
2467 void facge(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2468
2469 // FP absolute greater than.
2470 void facgt(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2471
2472 // FP multiply by element.
2473 void fmul(const VRegister& vd,
2474 const VRegister& vn,
2475 const VRegister& vm,
2476 int vm_index);
2477
2478 // FP fused multiply-add to accumulator by element.
2479 void fmla(const VRegister& vd,
2480 const VRegister& vn,
2481 const VRegister& vm,
2482 int vm_index);
2483
2484 // FP fused multiply-sub from accumulator by element.
2485 void fmls(const VRegister& vd,
2486 const VRegister& vn,
2487 const VRegister& vm,
2488 int vm_index);
2489
2490 // FP multiply extended by element.
2491 void fmulx(const VRegister& vd,
2492 const VRegister& vn,
2493 const VRegister& vm,
2494 int vm_index);
2495
2496 // FP compare equal.
2497 void fcmeq(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2498
2499 // FP greater than.
2500 void fcmgt(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2501
2502 // FP greater than or equal.
2503 void fcmge(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2504
2505 // FP compare equal to zero.
2506 void fcmeq(const VRegister& vd, const VRegister& vn, double imm);
2507
2508 // FP greater than zero.
2509 void fcmgt(const VRegister& vd, const VRegister& vn, double imm);
2510
2511 // FP greater than or equal to zero.
2512 void fcmge(const VRegister& vd, const VRegister& vn, double imm);
2513
2514 // FP less than or equal to zero.
2515 void fcmle(const VRegister& vd, const VRegister& vn, double imm);
2516
2517 // FP less than to zero.
2518 void fcmlt(const VRegister& vd, const VRegister& vn, double imm);
2519
2520 // FP absolute difference.
2521 void fabd(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2522
2523 // FP pairwise add vector.
2524 void faddp(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2525
2526 // FP pairwise add scalar.
2527 void faddp(const VRegister& vd, const VRegister& vn);
2528
2529 // FP pairwise maximum vector.
2530 void fmaxp(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2531
2532 // FP pairwise maximum scalar.
2533 void fmaxp(const VRegister& vd, const VRegister& vn);
2534
2535 // FP pairwise minimum vector.
2536 void fminp(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2537
2538 // FP pairwise minimum scalar.
2539 void fminp(const VRegister& vd, const VRegister& vn);
2540
2541 // FP pairwise maximum number vector.
2542 void fmaxnmp(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2543
2544 // FP pairwise maximum number scalar.
2545 void fmaxnmp(const VRegister& vd, const VRegister& vn);
2546
2547 // FP pairwise minimum number vector.
2548 void fminnmp(const VRegister& vd, const VRegister& vn, const VRegister& vm);
2549
2550 // FP pairwise minimum number scalar.
2551 void fminnmp(const VRegister& vd, const VRegister& vn);
2552
2553 // Emit generic instructions.
2554 // Emit raw instructions into the instruction stream.
dci(Instr raw_inst)2555 void dci(Instr raw_inst) { Emit(raw_inst); }
2556
2557 // Emit 32 bits of data into the instruction stream.
dc32(uint32_t data)2558 void dc32(uint32_t data) { dc(data); }
2559
2560 // Emit 64 bits of data into the instruction stream.
dc64(uint64_t data)2561 void dc64(uint64_t data) { dc(data); }
2562
2563 // Emit data in the instruction stream.
2564 template <typename T>
dc(T data)2565 void dc(T data) {
2566 VIXL_ASSERT(AllowAssembler());
2567 GetBuffer()->Emit<T>(data);
2568 }
2569
2570 // Copy a string into the instruction stream, including the terminating NULL
2571 // character. The instruction pointer is then aligned correctly for
2572 // subsequent instructions.
EmitString(const char * string)2573 void EmitString(const char* string) {
2574 VIXL_ASSERT(string != NULL);
2575 VIXL_ASSERT(AllowAssembler());
2576
2577 GetBuffer()->EmitString(string);
2578 GetBuffer()->Align();
2579 }
2580
2581 // Code generation helpers.
2582
2583 // Register encoding.
Rd(CPURegister rd)2584 static Instr Rd(CPURegister rd) {
2585 VIXL_ASSERT(rd.GetCode() != kSPRegInternalCode);
2586 return rd.GetCode() << Rd_offset;
2587 }
2588
Rn(CPURegister rn)2589 static Instr Rn(CPURegister rn) {
2590 VIXL_ASSERT(rn.GetCode() != kSPRegInternalCode);
2591 return rn.GetCode() << Rn_offset;
2592 }
2593
Rm(CPURegister rm)2594 static Instr Rm(CPURegister rm) {
2595 VIXL_ASSERT(rm.GetCode() != kSPRegInternalCode);
2596 return rm.GetCode() << Rm_offset;
2597 }
2598
RmNot31(CPURegister rm)2599 static Instr RmNot31(CPURegister rm) {
2600 VIXL_ASSERT(rm.GetCode() != kSPRegInternalCode);
2601 VIXL_ASSERT(!rm.IsZero());
2602 return Rm(rm);
2603 }
2604
Ra(CPURegister ra)2605 static Instr Ra(CPURegister ra) {
2606 VIXL_ASSERT(ra.GetCode() != kSPRegInternalCode);
2607 return ra.GetCode() << Ra_offset;
2608 }
2609
Rt(CPURegister rt)2610 static Instr Rt(CPURegister rt) {
2611 VIXL_ASSERT(rt.GetCode() != kSPRegInternalCode);
2612 return rt.GetCode() << Rt_offset;
2613 }
2614
Rt2(CPURegister rt2)2615 static Instr Rt2(CPURegister rt2) {
2616 VIXL_ASSERT(rt2.GetCode() != kSPRegInternalCode);
2617 return rt2.GetCode() << Rt2_offset;
2618 }
2619
Rs(CPURegister rs)2620 static Instr Rs(CPURegister rs) {
2621 VIXL_ASSERT(rs.GetCode() != kSPRegInternalCode);
2622 return rs.GetCode() << Rs_offset;
2623 }
2624
2625 // These encoding functions allow the stack pointer to be encoded, and
2626 // disallow the zero register.
RdSP(Register rd)2627 static Instr RdSP(Register rd) {
2628 VIXL_ASSERT(!rd.IsZero());
2629 return (rd.GetCode() & kRegCodeMask) << Rd_offset;
2630 }
2631
RnSP(Register rn)2632 static Instr RnSP(Register rn) {
2633 VIXL_ASSERT(!rn.IsZero());
2634 return (rn.GetCode() & kRegCodeMask) << Rn_offset;
2635 }
2636
2637 // Flags encoding.
Flags(FlagsUpdate S)2638 static Instr Flags(FlagsUpdate S) {
2639 if (S == SetFlags) {
2640 return 1 << FlagsUpdate_offset;
2641 } else if (S == LeaveFlags) {
2642 return 0 << FlagsUpdate_offset;
2643 }
2644 VIXL_UNREACHABLE();
2645 return 0;
2646 }
2647
Cond(Condition cond)2648 static Instr Cond(Condition cond) { return cond << Condition_offset; }
2649
2650 // PC-relative address encoding.
ImmPCRelAddress(int64_t imm21)2651 static Instr ImmPCRelAddress(int64_t imm21) {
2652 VIXL_ASSERT(IsInt21(imm21));
2653 Instr imm = static_cast<Instr>(TruncateToUint21(imm21));
2654 Instr immhi = (imm >> ImmPCRelLo_width) << ImmPCRelHi_offset;
2655 Instr immlo = imm << ImmPCRelLo_offset;
2656 return (immhi & ImmPCRelHi_mask) | (immlo & ImmPCRelLo_mask);
2657 }
2658
2659 // Branch encoding.
ImmUncondBranch(int64_t imm26)2660 static Instr ImmUncondBranch(int64_t imm26) {
2661 VIXL_ASSERT(IsInt26(imm26));
2662 return TruncateToUint26(imm26) << ImmUncondBranch_offset;
2663 }
2664
ImmCondBranch(int64_t imm19)2665 static Instr ImmCondBranch(int64_t imm19) {
2666 VIXL_ASSERT(IsInt19(imm19));
2667 return TruncateToUint19(imm19) << ImmCondBranch_offset;
2668 }
2669
ImmCmpBranch(int64_t imm19)2670 static Instr ImmCmpBranch(int64_t imm19) {
2671 VIXL_ASSERT(IsInt19(imm19));
2672 return TruncateToUint19(imm19) << ImmCmpBranch_offset;
2673 }
2674
ImmTestBranch(int64_t imm14)2675 static Instr ImmTestBranch(int64_t imm14) {
2676 VIXL_ASSERT(IsInt14(imm14));
2677 return TruncateToUint14(imm14) << ImmTestBranch_offset;
2678 }
2679
ImmTestBranchBit(unsigned bit_pos)2680 static Instr ImmTestBranchBit(unsigned bit_pos) {
2681 VIXL_ASSERT(IsUint6(bit_pos));
2682 // Subtract five from the shift offset, as we need bit 5 from bit_pos.
2683 unsigned b5 = bit_pos << (ImmTestBranchBit5_offset - 5);
2684 unsigned b40 = bit_pos << ImmTestBranchBit40_offset;
2685 b5 &= ImmTestBranchBit5_mask;
2686 b40 &= ImmTestBranchBit40_mask;
2687 return b5 | b40;
2688 }
2689
2690 // Data Processing encoding.
SF(Register rd)2691 static Instr SF(Register rd) {
2692 return rd.Is64Bits() ? SixtyFourBits : ThirtyTwoBits;
2693 }
2694
ImmAddSub(int imm)2695 static Instr ImmAddSub(int imm) {
2696 VIXL_ASSERT(IsImmAddSub(imm));
2697 if (IsUint12(imm)) { // No shift required.
2698 imm <<= ImmAddSub_offset;
2699 } else {
2700 imm = ((imm >> 12) << ImmAddSub_offset) | (1 << ShiftAddSub_offset);
2701 }
2702 return imm;
2703 }
2704
ImmS(unsigned imms,unsigned reg_size)2705 static Instr ImmS(unsigned imms, unsigned reg_size) {
2706 VIXL_ASSERT(((reg_size == kXRegSize) && IsUint6(imms)) ||
2707 ((reg_size == kWRegSize) && IsUint5(imms)));
2708 USE(reg_size);
2709 return imms << ImmS_offset;
2710 }
2711
ImmR(unsigned immr,unsigned reg_size)2712 static Instr ImmR(unsigned immr, unsigned reg_size) {
2713 VIXL_ASSERT(((reg_size == kXRegSize) && IsUint6(immr)) ||
2714 ((reg_size == kWRegSize) && IsUint5(immr)));
2715 USE(reg_size);
2716 VIXL_ASSERT(IsUint6(immr));
2717 return immr << ImmR_offset;
2718 }
2719
ImmSetBits(unsigned imms,unsigned reg_size)2720 static Instr ImmSetBits(unsigned imms, unsigned reg_size) {
2721 VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
2722 VIXL_ASSERT(IsUint6(imms));
2723 VIXL_ASSERT((reg_size == kXRegSize) || IsUint6(imms + 3));
2724 USE(reg_size);
2725 return imms << ImmSetBits_offset;
2726 }
2727
ImmRotate(unsigned immr,unsigned reg_size)2728 static Instr ImmRotate(unsigned immr, unsigned reg_size) {
2729 VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
2730 VIXL_ASSERT(((reg_size == kXRegSize) && IsUint6(immr)) ||
2731 ((reg_size == kWRegSize) && IsUint5(immr)));
2732 USE(reg_size);
2733 return immr << ImmRotate_offset;
2734 }
2735
ImmLLiteral(int64_t imm19)2736 static Instr ImmLLiteral(int64_t imm19) {
2737 VIXL_ASSERT(IsInt19(imm19));
2738 return TruncateToUint19(imm19) << ImmLLiteral_offset;
2739 }
2740
BitN(unsigned bitn,unsigned reg_size)2741 static Instr BitN(unsigned bitn, unsigned reg_size) {
2742 VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
2743 VIXL_ASSERT((reg_size == kXRegSize) || (bitn == 0));
2744 USE(reg_size);
2745 return bitn << BitN_offset;
2746 }
2747
ShiftDP(Shift shift)2748 static Instr ShiftDP(Shift shift) {
2749 VIXL_ASSERT(shift == LSL || shift == LSR || shift == ASR || shift == ROR);
2750 return shift << ShiftDP_offset;
2751 }
2752
ImmDPShift(unsigned amount)2753 static Instr ImmDPShift(unsigned amount) {
2754 VIXL_ASSERT(IsUint6(amount));
2755 return amount << ImmDPShift_offset;
2756 }
2757
ExtendMode(Extend extend)2758 static Instr ExtendMode(Extend extend) { return extend << ExtendMode_offset; }
2759
ImmExtendShift(unsigned left_shift)2760 static Instr ImmExtendShift(unsigned left_shift) {
2761 VIXL_ASSERT(left_shift <= 4);
2762 return left_shift << ImmExtendShift_offset;
2763 }
2764
ImmCondCmp(unsigned imm)2765 static Instr ImmCondCmp(unsigned imm) {
2766 VIXL_ASSERT(IsUint5(imm));
2767 return imm << ImmCondCmp_offset;
2768 }
2769
Nzcv(StatusFlags nzcv)2770 static Instr Nzcv(StatusFlags nzcv) {
2771 return ((nzcv >> Flags_offset) & 0xf) << Nzcv_offset;
2772 }
2773
2774 // MemOperand offset encoding.
ImmLSUnsigned(int64_t imm12)2775 static Instr ImmLSUnsigned(int64_t imm12) {
2776 VIXL_ASSERT(IsUint12(imm12));
2777 return TruncateToUint12(imm12) << ImmLSUnsigned_offset;
2778 }
2779
ImmLS(int64_t imm9)2780 static Instr ImmLS(int64_t imm9) {
2781 VIXL_ASSERT(IsInt9(imm9));
2782 return TruncateToUint9(imm9) << ImmLS_offset;
2783 }
2784
ImmLSPair(int64_t imm7,unsigned access_size)2785 static Instr ImmLSPair(int64_t imm7, unsigned access_size) {
2786 VIXL_ASSERT(IsMultiple(imm7, 1 << access_size));
2787 int64_t scaled_imm7 = imm7 / (1 << access_size);
2788 VIXL_ASSERT(IsInt7(scaled_imm7));
2789 return TruncateToUint7(scaled_imm7) << ImmLSPair_offset;
2790 }
2791
ImmShiftLS(unsigned shift_amount)2792 static Instr ImmShiftLS(unsigned shift_amount) {
2793 VIXL_ASSERT(IsUint1(shift_amount));
2794 return shift_amount << ImmShiftLS_offset;
2795 }
2796
ImmPrefetchOperation(int imm5)2797 static Instr ImmPrefetchOperation(int imm5) {
2798 VIXL_ASSERT(IsUint5(imm5));
2799 return imm5 << ImmPrefetchOperation_offset;
2800 }
2801
ImmException(int imm16)2802 static Instr ImmException(int imm16) {
2803 VIXL_ASSERT(IsUint16(imm16));
2804 return imm16 << ImmException_offset;
2805 }
2806
ImmSystemRegister(int imm16)2807 static Instr ImmSystemRegister(int imm16) {
2808 VIXL_ASSERT(IsUint16(imm16));
2809 return imm16 << ImmSystemRegister_offset;
2810 }
2811
ImmHint(int imm7)2812 static Instr ImmHint(int imm7) {
2813 VIXL_ASSERT(IsUint7(imm7));
2814 return imm7 << ImmHint_offset;
2815 }
2816
CRm(int imm4)2817 static Instr CRm(int imm4) {
2818 VIXL_ASSERT(IsUint4(imm4));
2819 return imm4 << CRm_offset;
2820 }
2821
CRn(int imm4)2822 static Instr CRn(int imm4) {
2823 VIXL_ASSERT(IsUint4(imm4));
2824 return imm4 << CRn_offset;
2825 }
2826
SysOp(int imm14)2827 static Instr SysOp(int imm14) {
2828 VIXL_ASSERT(IsUint14(imm14));
2829 return imm14 << SysOp_offset;
2830 }
2831
ImmSysOp1(int imm3)2832 static Instr ImmSysOp1(int imm3) {
2833 VIXL_ASSERT(IsUint3(imm3));
2834 return imm3 << SysOp1_offset;
2835 }
2836
ImmSysOp2(int imm3)2837 static Instr ImmSysOp2(int imm3) {
2838 VIXL_ASSERT(IsUint3(imm3));
2839 return imm3 << SysOp2_offset;
2840 }
2841
ImmBarrierDomain(int imm2)2842 static Instr ImmBarrierDomain(int imm2) {
2843 VIXL_ASSERT(IsUint2(imm2));
2844 return imm2 << ImmBarrierDomain_offset;
2845 }
2846
ImmBarrierType(int imm2)2847 static Instr ImmBarrierType(int imm2) {
2848 VIXL_ASSERT(IsUint2(imm2));
2849 return imm2 << ImmBarrierType_offset;
2850 }
2851
2852 // Move immediates encoding.
ImmMoveWide(uint64_t imm)2853 static Instr ImmMoveWide(uint64_t imm) {
2854 VIXL_ASSERT(IsUint16(imm));
2855 return static_cast<Instr>(imm << ImmMoveWide_offset);
2856 }
2857
ShiftMoveWide(int64_t shift)2858 static Instr ShiftMoveWide(int64_t shift) {
2859 VIXL_ASSERT(IsUint2(shift));
2860 return static_cast<Instr>(shift << ShiftMoveWide_offset);
2861 }
2862
2863 // FP Immediates.
2864 static Instr ImmFP32(float imm);
2865 static Instr ImmFP64(double imm);
2866
2867 // FP register type.
FPType(FPRegister fd)2868 static Instr FPType(FPRegister fd) { return fd.Is64Bits() ? FP64 : FP32; }
2869
FPScale(unsigned scale)2870 static Instr FPScale(unsigned scale) {
2871 VIXL_ASSERT(IsUint6(scale));
2872 return scale << FPScale_offset;
2873 }
2874
2875 // Immediate field checking helpers.
2876 static bool IsImmAddSub(int64_t immediate);
2877 static bool IsImmConditionalCompare(int64_t immediate);
2878 static bool IsImmFP32(float imm);
2879 static bool IsImmFP64(double imm);
2880 static bool IsImmLogical(uint64_t value,
2881 unsigned width,
2882 unsigned* n = NULL,
2883 unsigned* imm_s = NULL,
2884 unsigned* imm_r = NULL);
2885 static bool IsImmLSPair(int64_t offset, unsigned access_size);
2886 static bool IsImmLSScaled(int64_t offset, unsigned access_size);
2887 static bool IsImmLSUnscaled(int64_t offset);
2888 static bool IsImmMovn(uint64_t imm, unsigned reg_size);
2889 static bool IsImmMovz(uint64_t imm, unsigned reg_size);
2890
2891 // Instruction bits for vector format in data processing operations.
VFormat(VRegister vd)2892 static Instr VFormat(VRegister vd) {
2893 if (vd.Is64Bits()) {
2894 switch (vd.GetLanes()) {
2895 case 2:
2896 return NEON_2S;
2897 case 4:
2898 return NEON_4H;
2899 case 8:
2900 return NEON_8B;
2901 default:
2902 return 0xffffffff;
2903 }
2904 } else {
2905 VIXL_ASSERT(vd.Is128Bits());
2906 switch (vd.GetLanes()) {
2907 case 2:
2908 return NEON_2D;
2909 case 4:
2910 return NEON_4S;
2911 case 8:
2912 return NEON_8H;
2913 case 16:
2914 return NEON_16B;
2915 default:
2916 return 0xffffffff;
2917 }
2918 }
2919 }
2920
2921 // Instruction bits for vector format in floating point data processing
2922 // operations.
FPFormat(VRegister vd)2923 static Instr FPFormat(VRegister vd) {
2924 if (vd.GetLanes() == 1) {
2925 // Floating point scalar formats.
2926 VIXL_ASSERT(vd.Is32Bits() || vd.Is64Bits());
2927 return vd.Is64Bits() ? FP64 : FP32;
2928 }
2929
2930 // Two lane floating point vector formats.
2931 if (vd.GetLanes() == 2) {
2932 VIXL_ASSERT(vd.Is64Bits() || vd.Is128Bits());
2933 return vd.Is128Bits() ? NEON_FP_2D : NEON_FP_2S;
2934 }
2935
2936 // Four lane floating point vector format.
2937 VIXL_ASSERT((vd.GetLanes() == 4) && vd.Is128Bits());
2938 return NEON_FP_4S;
2939 }
2940
2941 // Instruction bits for vector format in load and store operations.
LSVFormat(VRegister vd)2942 static Instr LSVFormat(VRegister vd) {
2943 if (vd.Is64Bits()) {
2944 switch (vd.GetLanes()) {
2945 case 1:
2946 return LS_NEON_1D;
2947 case 2:
2948 return LS_NEON_2S;
2949 case 4:
2950 return LS_NEON_4H;
2951 case 8:
2952 return LS_NEON_8B;
2953 default:
2954 return 0xffffffff;
2955 }
2956 } else {
2957 VIXL_ASSERT(vd.Is128Bits());
2958 switch (vd.GetLanes()) {
2959 case 2:
2960 return LS_NEON_2D;
2961 case 4:
2962 return LS_NEON_4S;
2963 case 8:
2964 return LS_NEON_8H;
2965 case 16:
2966 return LS_NEON_16B;
2967 default:
2968 return 0xffffffff;
2969 }
2970 }
2971 }
2972
2973 // Instruction bits for scalar format in data processing operations.
SFormat(VRegister vd)2974 static Instr SFormat(VRegister vd) {
2975 VIXL_ASSERT(vd.GetLanes() == 1);
2976 switch (vd.GetSizeInBytes()) {
2977 case 1:
2978 return NEON_B;
2979 case 2:
2980 return NEON_H;
2981 case 4:
2982 return NEON_S;
2983 case 8:
2984 return NEON_D;
2985 default:
2986 return 0xffffffff;
2987 }
2988 }
2989
ImmNEONHLM(int index,int num_bits)2990 static Instr ImmNEONHLM(int index, int num_bits) {
2991 int h, l, m;
2992 if (num_bits == 3) {
2993 VIXL_ASSERT(IsUint3(index));
2994 h = (index >> 2) & 1;
2995 l = (index >> 1) & 1;
2996 m = (index >> 0) & 1;
2997 } else if (num_bits == 2) {
2998 VIXL_ASSERT(IsUint2(index));
2999 h = (index >> 1) & 1;
3000 l = (index >> 0) & 1;
3001 m = 0;
3002 } else {
3003 VIXL_ASSERT(IsUint1(index) && (num_bits == 1));
3004 h = (index >> 0) & 1;
3005 l = 0;
3006 m = 0;
3007 }
3008 return (h << NEONH_offset) | (l << NEONL_offset) | (m << NEONM_offset);
3009 }
3010
ImmNEONExt(int imm4)3011 static Instr ImmNEONExt(int imm4) {
3012 VIXL_ASSERT(IsUint4(imm4));
3013 return imm4 << ImmNEONExt_offset;
3014 }
3015
ImmNEON5(Instr format,int index)3016 static Instr ImmNEON5(Instr format, int index) {
3017 VIXL_ASSERT(IsUint4(index));
3018 int s = LaneSizeInBytesLog2FromFormat(static_cast<VectorFormat>(format));
3019 int imm5 = (index << (s + 1)) | (1 << s);
3020 return imm5 << ImmNEON5_offset;
3021 }
3022
ImmNEON4(Instr format,int index)3023 static Instr ImmNEON4(Instr format, int index) {
3024 VIXL_ASSERT(IsUint4(index));
3025 int s = LaneSizeInBytesLog2FromFormat(static_cast<VectorFormat>(format));
3026 int imm4 = index << s;
3027 return imm4 << ImmNEON4_offset;
3028 }
3029
ImmNEONabcdefgh(int imm8)3030 static Instr ImmNEONabcdefgh(int imm8) {
3031 VIXL_ASSERT(IsUint8(imm8));
3032 Instr instr;
3033 instr = ((imm8 >> 5) & 7) << ImmNEONabc_offset;
3034 instr |= (imm8 & 0x1f) << ImmNEONdefgh_offset;
3035 return instr;
3036 }
3037
NEONCmode(int cmode)3038 static Instr NEONCmode(int cmode) {
3039 VIXL_ASSERT(IsUint4(cmode));
3040 return cmode << NEONCmode_offset;
3041 }
3042
NEONModImmOp(int op)3043 static Instr NEONModImmOp(int op) {
3044 VIXL_ASSERT(IsUint1(op));
3045 return op << NEONModImmOp_offset;
3046 }
3047
3048 // Size of the code generated since label to the current position.
GetSizeOfCodeGeneratedSince(Label * label)3049 size_t GetSizeOfCodeGeneratedSince(Label* label) const {
3050 VIXL_ASSERT(label->IsBound());
3051 return GetBuffer().GetOffsetFrom(label->GetLocation());
3052 }
3053 VIXL_DEPRECATED("GetSizeOfCodeGeneratedSince",
3054 size_t SizeOfCodeGeneratedSince(Label* label) const) {
3055 return GetSizeOfCodeGeneratedSince(label);
3056 }
3057
3058 VIXL_DEPRECATED("GetBuffer().GetCapacity()",
3059 size_t GetBufferCapacity() const) {
3060 return GetBuffer().GetCapacity();
3061 }
3062 VIXL_DEPRECATED("GetBuffer().GetCapacity()", size_t BufferCapacity() const) {
3063 return GetBuffer().GetCapacity();
3064 }
3065
3066 VIXL_DEPRECATED("GetBuffer().GetRemainingBytes()",
3067 size_t GetRemainingBufferSpace() const) {
3068 return GetBuffer().GetRemainingBytes();
3069 }
3070 VIXL_DEPRECATED("GetBuffer().GetRemainingBytes()",
3071 size_t RemainingBufferSpace() const) {
3072 return GetBuffer().GetRemainingBytes();
3073 }
3074
GetPic()3075 PositionIndependentCodeOption GetPic() const { return pic_; }
3076 VIXL_DEPRECATED("GetPic", PositionIndependentCodeOption pic() const) {
3077 return GetPic();
3078 }
3079
AllowPageOffsetDependentCode()3080 bool AllowPageOffsetDependentCode() const {
3081 return (GetPic() == PageOffsetDependentCode) ||
3082 (GetPic() == PositionDependentCode);
3083 }
3084
AppropriateZeroRegFor(const CPURegister & reg)3085 static Register AppropriateZeroRegFor(const CPURegister& reg) {
3086 return reg.Is64Bits() ? Register(xzr) : Register(wzr);
3087 }
3088
3089 protected:
3090 void LoadStore(const CPURegister& rt,
3091 const MemOperand& addr,
3092 LoadStoreOp op,
3093 LoadStoreScalingOption option = PreferScaledOffset);
3094
3095 void LoadStorePair(const CPURegister& rt,
3096 const CPURegister& rt2,
3097 const MemOperand& addr,
3098 LoadStorePairOp op);
3099 void LoadStoreStruct(const VRegister& vt,
3100 const MemOperand& addr,
3101 NEONLoadStoreMultiStructOp op);
3102 void LoadStoreStruct1(const VRegister& vt,
3103 int reg_count,
3104 const MemOperand& addr);
3105 void LoadStoreStructSingle(const VRegister& vt,
3106 uint32_t lane,
3107 const MemOperand& addr,
3108 NEONLoadStoreSingleStructOp op);
3109 void LoadStoreStructSingleAllLanes(const VRegister& vt,
3110 const MemOperand& addr,
3111 NEONLoadStoreSingleStructOp op);
3112 void LoadStoreStructVerify(const VRegister& vt,
3113 const MemOperand& addr,
3114 Instr op);
3115
3116 void Prefetch(PrefetchOperation op,
3117 const MemOperand& addr,
3118 LoadStoreScalingOption option = PreferScaledOffset);
3119
3120 // TODO(all): The third parameter should be passed by reference but gcc 4.8.2
3121 // reports a bogus uninitialised warning then.
3122 void Logical(const Register& rd,
3123 const Register& rn,
3124 const Operand operand,
3125 LogicalOp op);
3126 void LogicalImmediate(const Register& rd,
3127 const Register& rn,
3128 unsigned n,
3129 unsigned imm_s,
3130 unsigned imm_r,
3131 LogicalOp op);
3132
3133 void ConditionalCompare(const Register& rn,
3134 const Operand& operand,
3135 StatusFlags nzcv,
3136 Condition cond,
3137 ConditionalCompareOp op);
3138
3139 void AddSubWithCarry(const Register& rd,
3140 const Register& rn,
3141 const Operand& operand,
3142 FlagsUpdate S,
3143 AddSubWithCarryOp op);
3144
3145
3146 // Functions for emulating operands not directly supported by the instruction
3147 // set.
3148 void EmitShift(const Register& rd,
3149 const Register& rn,
3150 Shift shift,
3151 unsigned amount);
3152 void EmitExtendShift(const Register& rd,
3153 const Register& rn,
3154 Extend extend,
3155 unsigned left_shift);
3156
3157 void AddSub(const Register& rd,
3158 const Register& rn,
3159 const Operand& operand,
3160 FlagsUpdate S,
3161 AddSubOp op);
3162
3163 void NEONTable(const VRegister& vd,
3164 const VRegister& vn,
3165 const VRegister& vm,
3166 NEONTableOp op);
3167
3168 // Find an appropriate LoadStoreOp or LoadStorePairOp for the specified
3169 // registers. Only simple loads are supported; sign- and zero-extension (such
3170 // as in LDPSW_x or LDRB_w) are not supported.
3171 static LoadStoreOp LoadOpFor(const CPURegister& rt);
3172 static LoadStorePairOp LoadPairOpFor(const CPURegister& rt,
3173 const CPURegister& rt2);
3174 static LoadStoreOp StoreOpFor(const CPURegister& rt);
3175 static LoadStorePairOp StorePairOpFor(const CPURegister& rt,
3176 const CPURegister& rt2);
3177 static LoadStorePairNonTemporalOp LoadPairNonTemporalOpFor(
3178 const CPURegister& rt, const CPURegister& rt2);
3179 static LoadStorePairNonTemporalOp StorePairNonTemporalOpFor(
3180 const CPURegister& rt, const CPURegister& rt2);
3181 static LoadLiteralOp LoadLiteralOpFor(const CPURegister& rt);
3182
3183
3184 private:
3185 static uint32_t FP32ToImm8(float imm);
3186 static uint32_t FP64ToImm8(double imm);
3187
3188 // Instruction helpers.
3189 void MoveWide(const Register& rd,
3190 uint64_t imm,
3191 int shift,
3192 MoveWideImmediateOp mov_op);
3193 void DataProcShiftedRegister(const Register& rd,
3194 const Register& rn,
3195 const Operand& operand,
3196 FlagsUpdate S,
3197 Instr op);
3198 void DataProcExtendedRegister(const Register& rd,
3199 const Register& rn,
3200 const Operand& operand,
3201 FlagsUpdate S,
3202 Instr op);
3203 void LoadStorePairNonTemporal(const CPURegister& rt,
3204 const CPURegister& rt2,
3205 const MemOperand& addr,
3206 LoadStorePairNonTemporalOp op);
3207 void LoadLiteral(const CPURegister& rt, uint64_t imm, LoadLiteralOp op);
3208 void ConditionalSelect(const Register& rd,
3209 const Register& rn,
3210 const Register& rm,
3211 Condition cond,
3212 ConditionalSelectOp op);
3213 void DataProcessing1Source(const Register& rd,
3214 const Register& rn,
3215 DataProcessing1SourceOp op);
3216 void DataProcessing3Source(const Register& rd,
3217 const Register& rn,
3218 const Register& rm,
3219 const Register& ra,
3220 DataProcessing3SourceOp op);
3221 void FPDataProcessing1Source(const VRegister& fd,
3222 const VRegister& fn,
3223 FPDataProcessing1SourceOp op);
3224 void FPDataProcessing3Source(const VRegister& fd,
3225 const VRegister& fn,
3226 const VRegister& fm,
3227 const VRegister& fa,
3228 FPDataProcessing3SourceOp op);
3229 void NEONAcrossLanesL(const VRegister& vd,
3230 const VRegister& vn,
3231 NEONAcrossLanesOp op);
3232 void NEONAcrossLanes(const VRegister& vd,
3233 const VRegister& vn,
3234 NEONAcrossLanesOp op);
3235 void NEONModifiedImmShiftLsl(const VRegister& vd,
3236 const int imm8,
3237 const int left_shift,
3238 NEONModifiedImmediateOp op);
3239 void NEONModifiedImmShiftMsl(const VRegister& vd,
3240 const int imm8,
3241 const int shift_amount,
3242 NEONModifiedImmediateOp op);
3243 void NEONFP2Same(const VRegister& vd, const VRegister& vn, Instr vop);
3244 void NEON3Same(const VRegister& vd,
3245 const VRegister& vn,
3246 const VRegister& vm,
3247 NEON3SameOp vop);
3248 void NEONFP3Same(const VRegister& vd,
3249 const VRegister& vn,
3250 const VRegister& vm,
3251 Instr op);
3252 void NEON3DifferentL(const VRegister& vd,
3253 const VRegister& vn,
3254 const VRegister& vm,
3255 NEON3DifferentOp vop);
3256 void NEON3DifferentW(const VRegister& vd,
3257 const VRegister& vn,
3258 const VRegister& vm,
3259 NEON3DifferentOp vop);
3260 void NEON3DifferentHN(const VRegister& vd,
3261 const VRegister& vn,
3262 const VRegister& vm,
3263 NEON3DifferentOp vop);
3264 void NEONFP2RegMisc(const VRegister& vd,
3265 const VRegister& vn,
3266 NEON2RegMiscOp vop,
3267 double value = 0.0);
3268 void NEON2RegMisc(const VRegister& vd,
3269 const VRegister& vn,
3270 NEON2RegMiscOp vop,
3271 int value = 0);
3272 void NEONFP2RegMisc(const VRegister& vd, const VRegister& vn, Instr op);
3273 void NEONAddlp(const VRegister& vd, const VRegister& vn, NEON2RegMiscOp op);
3274 void NEONPerm(const VRegister& vd,
3275 const VRegister& vn,
3276 const VRegister& vm,
3277 NEONPermOp op);
3278 void NEONFPByElement(const VRegister& vd,
3279 const VRegister& vn,
3280 const VRegister& vm,
3281 int vm_index,
3282 NEONByIndexedElementOp op);
3283 void NEONByElement(const VRegister& vd,
3284 const VRegister& vn,
3285 const VRegister& vm,
3286 int vm_index,
3287 NEONByIndexedElementOp op);
3288 void NEONByElementL(const VRegister& vd,
3289 const VRegister& vn,
3290 const VRegister& vm,
3291 int vm_index,
3292 NEONByIndexedElementOp op);
3293 void NEONShiftImmediate(const VRegister& vd,
3294 const VRegister& vn,
3295 NEONShiftImmediateOp op,
3296 int immh_immb);
3297 void NEONShiftLeftImmediate(const VRegister& vd,
3298 const VRegister& vn,
3299 int shift,
3300 NEONShiftImmediateOp op);
3301 void NEONShiftRightImmediate(const VRegister& vd,
3302 const VRegister& vn,
3303 int shift,
3304 NEONShiftImmediateOp op);
3305 void NEONShiftImmediateL(const VRegister& vd,
3306 const VRegister& vn,
3307 int shift,
3308 NEONShiftImmediateOp op);
3309 void NEONShiftImmediateN(const VRegister& vd,
3310 const VRegister& vn,
3311 int shift,
3312 NEONShiftImmediateOp op);
3313 void NEONXtn(const VRegister& vd, const VRegister& vn, NEON2RegMiscOp vop);
3314
3315 Instr LoadStoreStructAddrModeField(const MemOperand& addr);
3316
3317 // Encode the specified MemOperand for the specified access size and scaling
3318 // preference.
3319 Instr LoadStoreMemOperand(const MemOperand& addr,
3320 unsigned access_size,
3321 LoadStoreScalingOption option);
3322
3323 // Link the current (not-yet-emitted) instruction to the specified label, then
3324 // return an offset to be encoded in the instruction. If the label is not yet
3325 // bound, an offset of 0 is returned.
3326 ptrdiff_t LinkAndGetByteOffsetTo(Label* label);
3327 ptrdiff_t LinkAndGetInstructionOffsetTo(Label* label);
3328 ptrdiff_t LinkAndGetPageOffsetTo(Label* label);
3329
3330 // A common implementation for the LinkAndGet<Type>OffsetTo helpers.
3331 template <int element_shift>
3332 ptrdiff_t LinkAndGetOffsetTo(Label* label);
3333
3334 // Literal load offset are in words (32-bit).
3335 ptrdiff_t LinkAndGetWordOffsetTo(RawLiteral* literal);
3336
3337 // Emit the instruction in buffer_.
Emit(Instr instruction)3338 void Emit(Instr instruction) {
3339 VIXL_STATIC_ASSERT(sizeof(instruction) == kInstructionSize);
3340 VIXL_ASSERT(AllowAssembler());
3341 GetBuffer()->Emit32(instruction);
3342 }
3343
3344 PositionIndependentCodeOption pic_;
3345 };
3346
3347
3348 template <typename T>
UpdateValue(T new_value,const Assembler * assembler)3349 void Literal<T>::UpdateValue(T new_value, const Assembler* assembler) {
3350 return UpdateValue(new_value,
3351 assembler->GetBuffer().GetStartAddress<uint8_t*>());
3352 }
3353
3354
3355 template <typename T>
UpdateValue(T high64,T low64,const Assembler * assembler)3356 void Literal<T>::UpdateValue(T high64, T low64, const Assembler* assembler) {
3357 return UpdateValue(high64,
3358 low64,
3359 assembler->GetBuffer().GetStartAddress<uint8_t*>());
3360 }
3361
3362
3363 } // namespace aarch64
3364
3365 // Required InvalSet template specialisations.
3366 // TODO: These template specialisations should not live in this file. Move
3367 // Label out of the aarch64 namespace in order to share its implementation
3368 // later.
3369 #define INVAL_SET_TEMPLATE_PARAMETERS \
3370 ptrdiff_t, aarch64::Label::kNPreallocatedLinks, ptrdiff_t, \
3371 aarch64::Label::kInvalidLinkKey, aarch64::Label::kReclaimFrom, \
3372 aarch64::Label::kReclaimFactor
3373 template <>
GetKey(const ptrdiff_t & element)3374 inline ptrdiff_t InvalSet<INVAL_SET_TEMPLATE_PARAMETERS>::GetKey(
3375 const ptrdiff_t& element) {
3376 return element;
3377 }
3378 template <>
SetKey(ptrdiff_t * element,ptrdiff_t key)3379 inline void InvalSet<INVAL_SET_TEMPLATE_PARAMETERS>::SetKey(ptrdiff_t* element,
3380 ptrdiff_t key) {
3381 *element = key;
3382 }
3383 #undef INVAL_SET_TEMPLATE_PARAMETERS
3384
3385 } // namespace vixl
3386
3387 #endif // VIXL_AARCH64_ASSEMBLER_AARCH64_H_
3388