blob: e50f6c91452bd55260b33368cf2f6acd40e09714 [file] [log] [blame]
armvixl5289c592015-03-02 13:52:04 +00001// Copyright 2015, ARM Limited
armvixlad96eda2013-06-14 11:42:37 +01002// 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_A64_MACRO_ASSEMBLER_A64_H_
28#define VIXL_A64_MACRO_ASSEMBLER_A64_H_
29
armvixlc68cb642014-09-25 18:49:30 +010030#include <algorithm>
31#include <limits>
32
Alexandre Rames1f9074d2016-05-23 15:50:01 +010033#include "globals-vixl.h"
Alexandre Ramesb68bacb2016-05-24 08:56:23 +010034
Alexandre Rames39c32a62016-05-23 15:47:22 +010035#include "a64/assembler-a64.h"
36#include "a64/debugger-a64.h"
37#include "a64/instrument-a64.h"
38#include "a64/simulator-constants-a64.h"
armvixlad96eda2013-06-14 11:42:37 +010039
40
armvixl0f35e362016-05-10 13:57:58 +010041#define LS_MACRO_LIST(V) \
42 V(Ldrb, Register&, rt, LDRB_w) \
43 V(Strb, Register&, rt, STRB_w) \
44 V(Ldrsb, Register&, rt, rt.Is64Bits() ? LDRSB_x : LDRSB_w) \
45 V(Ldrh, Register&, rt, LDRH_w) \
46 V(Strh, Register&, rt, STRH_w) \
47 V(Ldrsh, Register&, rt, rt.Is64Bits() ? LDRSH_x : LDRSH_w) \
48 V(Ldr, CPURegister&, rt, LoadOpFor(rt)) \
49 V(Str, CPURegister&, rt, StoreOpFor(rt)) \
armvixlad96eda2013-06-14 11:42:37 +010050 V(Ldrsw, Register&, rt, LDRSW_x)
51
armvixlc68cb642014-09-25 18:49:30 +010052
armvixl0f35e362016-05-10 13:57:58 +010053#define LSPAIR_MACRO_LIST(V) \
54 V(Ldp, CPURegister&, rt, rt2, LoadPairOpFor(rt, rt2)) \
55 V(Stp, CPURegister&, rt, rt2, StorePairOpFor(rt, rt2)) \
armvixlc68cb642014-09-25 18:49:30 +010056 V(Ldpsw, CPURegister&, rt, rt2, LDPSW_x)
57
armvixlad96eda2013-06-14 11:42:37 +010058namespace vixl {
Pierre Langlois88c46b82016-06-02 18:15:32 +010059namespace aarch64 {
armvixlad96eda2013-06-14 11:42:37 +010060
armvixl5289c592015-03-02 13:52:04 +000061// Forward declaration
62class MacroAssembler;
armvixl6e2c8272015-03-31 11:04:14 +010063class UseScratchRegisterScope;
armvixl5289c592015-03-02 13:52:04 +000064
65class Pool {
armvixlc68cb642014-09-25 18:49:30 +010066 public:
armvixldb644342015-07-21 11:37:10 +010067 explicit Pool(MacroAssembler* masm)
68 : checkpoint_(kNoCheckpointRequired), masm_(masm) {
armvixl5289c592015-03-02 13:52:04 +000069 Reset();
armvixlc68cb642014-09-25 18:49:30 +010070 }
armvixl5289c592015-03-02 13:52:04 +000071
72 void Reset() {
73 checkpoint_ = kNoCheckpointRequired;
74 monitor_ = 0;
75 }
armvixlc68cb642014-09-25 18:49:30 +010076
77 void Block() { monitor_++; }
78 void Release();
79 bool IsBlocked() const { return monitor_ != 0; }
80
armvixl5289c592015-03-02 13:52:04 +000081 static const ptrdiff_t kNoCheckpointRequired = PTRDIFF_MAX;
armvixlc68cb642014-09-25 18:49:30 +010082
armvixl5289c592015-03-02 13:52:04 +000083 void SetNextCheckpoint(ptrdiff_t checkpoint);
Pierre Langlois88c46b82016-06-02 18:15:32 +010084 ptrdiff_t GetCheckpoint() const { return checkpoint_; }
85 VIXL_DEPRECATED("GetCheckpoint", ptrdiff_t checkpoint() const) {
86 return GetCheckpoint();
87 }
armvixlc68cb642014-09-25 18:49:30 +010088
armvixl0f35e362016-05-10 13:57:58 +010089 enum EmitOption { kBranchRequired, kNoBranchRequired };
armvixl5289c592015-03-02 13:52:04 +000090
91 protected:
92 // Next buffer offset at which a check is required for this pool.
93 ptrdiff_t checkpoint_;
94 // Indicates whether the emission of this pool is blocked.
armvixlc68cb642014-09-25 18:49:30 +010095 int monitor_;
armvixl5289c592015-03-02 13:52:04 +000096 // The MacroAssembler using this pool.
97 MacroAssembler* masm_;
armvixlc68cb642014-09-25 18:49:30 +010098};
99
100
armvixl5289c592015-03-02 13:52:04 +0000101class LiteralPool : public Pool {
102 public:
103 explicit LiteralPool(MacroAssembler* masm);
104 ~LiteralPool();
105 void Reset();
106
armvixldb644342015-07-21 11:37:10 +0100107 void AddEntry(RawLiteral* literal);
armvixl5289c592015-03-02 13:52:04 +0000108 bool IsEmpty() const { return entries_.empty(); }
Pierre Langlois88c46b82016-06-02 18:15:32 +0100109 size_t GetSize() const;
110 VIXL_DEPRECATED("GetSize", size_t Size() const) { return GetSize(); }
111
112 size_t GetMaxSize() const;
113 VIXL_DEPRECATED("GetMaxSize", size_t MaxSize() const) { return GetMaxSize(); }
114
115 size_t GetOtherPoolsMaxSize() const;
116 VIXL_DEPRECATED("GetOtherPoolsMaxSize", size_t OtherPoolsMaxSize() const) {
117 return GetOtherPoolsMaxSize();
118 }
armvixl5289c592015-03-02 13:52:04 +0000119
120 void CheckEmitFor(size_t amount, EmitOption option = kBranchRequired);
121 void Emit(EmitOption option = kNoBranchRequired);
122
123 void SetNextRecommendedCheckpoint(ptrdiff_t offset);
Pierre Langlois88c46b82016-06-02 18:15:32 +0100124 ptrdiff_t GetNextRecommendedCheckpoint();
125 VIXL_DEPRECATED("GetNextRecommendedCheckpoint",
126 ptrdiff_t NextRecommendedCheckpoint()) {
127 return GetNextRecommendedCheckpoint();
128 }
armvixl5289c592015-03-02 13:52:04 +0000129
armvixldb644342015-07-21 11:37:10 +0100130 void UpdateFirstUse(ptrdiff_t use_position);
131
132 void DeleteOnDestruction(RawLiteral* literal) {
133 deleted_on_destruction_.push_back(literal);
134 }
135
armvixl5289c592015-03-02 13:52:04 +0000136 // Recommended not exact since the pool can be blocked for short periods.
137 static const ptrdiff_t kRecommendedLiteralPoolRange = 128 * KBytes;
138
139 private:
140 std::vector<RawLiteral*> entries_;
141 size_t size_;
142 ptrdiff_t first_use_;
143 // The parent class `Pool` provides a `checkpoint_`, which is the buffer
144 // offset before which a check *must* occur. This recommended checkpoint
145 // indicates when we would like to start emitting the constant pool. The
146 // MacroAssembler can, but does not have to, check the buffer when the
147 // checkpoint is reached.
148 ptrdiff_t recommended_checkpoint_;
armvixldb644342015-07-21 11:37:10 +0100149
150 std::vector<RawLiteral*> deleted_on_destruction_;
armvixl5289c592015-03-02 13:52:04 +0000151};
152
153
Pierre Langlois88c46b82016-06-02 18:15:32 +0100154inline size_t LiteralPool::GetSize() const {
armvixl5289c592015-03-02 13:52:04 +0000155 // Account for the pool header.
156 return size_ + kInstructionSize;
157}
158
159
Pierre Langlois88c46b82016-06-02 18:15:32 +0100160inline size_t LiteralPool::GetMaxSize() const {
armvixl5289c592015-03-02 13:52:04 +0000161 // Account for the potential branch over the pool.
Pierre Langlois88c46b82016-06-02 18:15:32 +0100162 return GetSize() + kInstructionSize;
armvixl5289c592015-03-02 13:52:04 +0000163}
164
165
Pierre Langlois88c46b82016-06-02 18:15:32 +0100166inline ptrdiff_t LiteralPool::GetNextRecommendedCheckpoint() {
armvixl5289c592015-03-02 13:52:04 +0000167 return first_use_ + kRecommendedLiteralPoolRange;
168}
169
170
171class VeneerPool : public Pool {
172 public:
173 explicit VeneerPool(MacroAssembler* masm) : Pool(masm) {}
174
175 void Reset();
176
177 void Block() { monitor_++; }
178 void Release();
179 bool IsBlocked() const { return monitor_ != 0; }
Pierre Langlois88c46b82016-06-02 18:15:32 +0100180 bool IsEmpty() const { return unresolved_branches_.IsEmpty(); }
armvixl5289c592015-03-02 13:52:04 +0000181
182 class BranchInfo {
183 public:
184 BranchInfo()
armvixl0f35e362016-05-10 13:57:58 +0100185 : max_reachable_pc_(0),
186 pc_offset_(0),
187 label_(NULL),
188 branch_type_(UnknownBranchType) {}
armvixl5289c592015-03-02 13:52:04 +0000189 BranchInfo(ptrdiff_t offset, Label* label, ImmBranchType branch_type)
190 : pc_offset_(offset), label_(label), branch_type_(branch_type) {
191 max_reachable_pc_ =
Pierre Langlois88c46b82016-06-02 18:15:32 +0100192 pc_offset_ + Instruction::GetImmBranchForwardRange(branch_type_);
armvixl5289c592015-03-02 13:52:04 +0000193 }
194
195 static bool IsValidComparison(const BranchInfo& branch_1,
196 const BranchInfo& branch_2) {
197 // BranchInfo are always compared against against other objects with
198 // the same branch type.
199 if (branch_1.branch_type_ != branch_2.branch_type_) {
200 return false;
201 }
202 // Since we should never have two branch infos with the same offsets, it
203 // first looks like we should check that offsets are different. However
204 // the operators may also be used to *search* for a branch info in the
205 // set.
206 bool same_offsets = (branch_1.pc_offset_ == branch_2.pc_offset_);
207 return (!same_offsets ||
208 ((branch_1.label_ == branch_2.label_) &&
209 (branch_1.max_reachable_pc_ == branch_2.max_reachable_pc_)));
210 }
211
212 // We must provide comparison operators to work with InvalSet.
213 bool operator==(const BranchInfo& other) const {
214 VIXL_ASSERT(IsValidComparison(*this, other));
215 return pc_offset_ == other.pc_offset_;
216 }
217 bool operator<(const BranchInfo& other) const {
218 VIXL_ASSERT(IsValidComparison(*this, other));
219 return pc_offset_ < other.pc_offset_;
220 }
221 bool operator<=(const BranchInfo& other) const {
222 VIXL_ASSERT(IsValidComparison(*this, other));
223 return pc_offset_ <= other.pc_offset_;
224 }
225 bool operator>(const BranchInfo& other) const {
226 VIXL_ASSERT(IsValidComparison(*this, other));
227 return pc_offset_ > other.pc_offset_;
228 }
229
230 // Maximum position reachable by the branch using a positive branch offset.
231 ptrdiff_t max_reachable_pc_;
232 // Offset of the branch in the code generation buffer.
233 ptrdiff_t pc_offset_;
234 // The label branched to.
235 Label* label_;
236 ImmBranchType branch_type_;
237 };
238
239 bool BranchTypeUsesVeneers(ImmBranchType type) {
240 return (type != UnknownBranchType) && (type != UncondBranchType);
241 }
242
243 void RegisterUnresolvedBranch(ptrdiff_t branch_pos,
244 Label* label,
245 ImmBranchType branch_type);
246 void DeleteUnresolvedBranchInfoForLabel(Label* label);
247
armvixldb644342015-07-21 11:37:10 +0100248 bool ShouldEmitVeneer(int64_t max_reachable_pc, size_t amount);
armvixl5289c592015-03-02 13:52:04 +0000249 bool ShouldEmitVeneers(size_t amount) {
Pierre Langlois88c46b82016-06-02 18:15:32 +0100250 return ShouldEmitVeneer(unresolved_branches_.GetFirstLimit(), amount);
armvixl5289c592015-03-02 13:52:04 +0000251 }
252
253 void CheckEmitFor(size_t amount, EmitOption option = kBranchRequired);
254 void Emit(EmitOption option, size_t margin);
255
256 // The code size generated for a veneer. Currently one branch instruction.
257 // This is for code size checking purposes, and can be extended in the future
258 // for example if we decide to add nops between the veneers.
259 static const int kVeneerCodeSize = 1 * kInstructionSize;
260 // The maximum size of code other than veneers that can be generated when
261 // emitting a veneer pool. Currently there can be an additional branch to jump
262 // over the pool.
263 static const int kPoolNonVeneerCodeSize = 1 * kInstructionSize;
264
Pierre Langlois88c46b82016-06-02 18:15:32 +0100265 void UpdateNextCheckPoint() { SetNextCheckpoint(GetNextCheckPoint()); }
armvixl5289c592015-03-02 13:52:04 +0000266
Pierre Langlois88c46b82016-06-02 18:15:32 +0100267 int GetNumberOfPotentialVeneers() const {
268 return static_cast<int>(unresolved_branches_.GetSize());
269 }
270 VIXL_DEPRECATED("GetNumberOfPotentialVeneers",
271 int NumberOfPotentialVeneers() const) {
272 return GetNumberOfPotentialVeneers();
armvixl5289c592015-03-02 13:52:04 +0000273 }
274
Pierre Langlois88c46b82016-06-02 18:15:32 +0100275 size_t GetMaxSize() const {
armvixl0f35e362016-05-10 13:57:58 +0100276 return kPoolNonVeneerCodeSize +
Pierre Langlois88c46b82016-06-02 18:15:32 +0100277 unresolved_branches_.GetSize() * kVeneerCodeSize;
armvixl5289c592015-03-02 13:52:04 +0000278 }
Pierre Langlois88c46b82016-06-02 18:15:32 +0100279 VIXL_DEPRECATED("GetMaxSize", size_t MaxSize() const) { return GetMaxSize(); }
armvixl5289c592015-03-02 13:52:04 +0000280
Pierre Langlois88c46b82016-06-02 18:15:32 +0100281 size_t GetOtherPoolsMaxSize() const;
282 VIXL_DEPRECATED("GetOtherPoolsMaxSize", size_t OtherPoolsMaxSize() const) {
283 return GetOtherPoolsMaxSize();
284 }
armvixl5289c592015-03-02 13:52:04 +0000285
286 static const int kNPreallocatedInfos = 4;
287 static const ptrdiff_t kInvalidOffset = PTRDIFF_MAX;
288 static const size_t kReclaimFrom = 128;
289 static const size_t kReclaimFactor = 16;
290
291 private:
292 typedef InvalSet<BranchInfo,
293 kNPreallocatedInfos,
294 ptrdiff_t,
295 kInvalidOffset,
296 kReclaimFrom,
297 kReclaimFactor> BranchInfoTypedSetBase;
298 typedef InvalSetIterator<BranchInfoTypedSetBase> BranchInfoTypedSetIterBase;
299
300 class BranchInfoTypedSet : public BranchInfoTypedSetBase {
301 public:
302 BranchInfoTypedSet() : BranchInfoTypedSetBase() {}
303
Pierre Langlois88c46b82016-06-02 18:15:32 +0100304 ptrdiff_t GetFirstLimit() {
armvixl5289c592015-03-02 13:52:04 +0000305 if (empty()) {
306 return kInvalidOffset;
307 }
armvixl0f35e362016-05-10 13:57:58 +0100308 return GetMinElementKey();
armvixl5289c592015-03-02 13:52:04 +0000309 }
Pierre Langlois88c46b82016-06-02 18:15:32 +0100310 VIXL_DEPRECATED("GetFirstLimit", ptrdiff_t FirstLimit()) {
311 return GetFirstLimit();
312 }
armvixl5289c592015-03-02 13:52:04 +0000313 };
314
315 class BranchInfoTypedSetIterator : public BranchInfoTypedSetIterBase {
316 public:
317 BranchInfoTypedSetIterator() : BranchInfoTypedSetIterBase(NULL) {}
318 explicit BranchInfoTypedSetIterator(BranchInfoTypedSet* typed_set)
319 : BranchInfoTypedSetIterBase(typed_set) {}
armvixl0f35e362016-05-10 13:57:58 +0100320
321 // TODO: Remove these and use the STL-like interface instead.
322 using BranchInfoTypedSetIterBase::Advance;
323 using BranchInfoTypedSetIterBase::Current;
armvixl5289c592015-03-02 13:52:04 +0000324 };
325
326 class BranchInfoSet {
327 public:
328 void insert(BranchInfo branch_info) {
329 ImmBranchType type = branch_info.branch_type_;
330 VIXL_ASSERT(IsValidBranchType(type));
331 typed_set_[BranchIndexFromType(type)].insert(branch_info);
332 }
333
334 void erase(BranchInfo branch_info) {
335 if (IsValidBranchType(branch_info.branch_type_)) {
336 int index =
337 BranchInfoSet::BranchIndexFromType(branch_info.branch_type_);
338 typed_set_[index].erase(branch_info);
339 }
340 }
341
Pierre Langlois88c46b82016-06-02 18:15:32 +0100342 size_t GetSize() const {
armvixl5289c592015-03-02 13:52:04 +0000343 size_t res = 0;
344 for (int i = 0; i < kNumberOfTrackedBranchTypes; i++) {
345 res += typed_set_[i].size();
346 }
347 return res;
348 }
Pierre Langlois88c46b82016-06-02 18:15:32 +0100349 VIXL_DEPRECATED("GetSize", size_t size() const) { return GetSize(); }
armvixl5289c592015-03-02 13:52:04 +0000350
Pierre Langlois88c46b82016-06-02 18:15:32 +0100351 bool IsEmpty() const {
armvixl5289c592015-03-02 13:52:04 +0000352 for (int i = 0; i < kNumberOfTrackedBranchTypes; i++) {
353 if (!typed_set_[i].empty()) {
354 return false;
355 }
356 }
357 return true;
358 }
Pierre Langlois88c46b82016-06-02 18:15:32 +0100359 VIXL_DEPRECATED("IsEmpty", bool empty() const) { return IsEmpty(); }
armvixl5289c592015-03-02 13:52:04 +0000360
Pierre Langlois88c46b82016-06-02 18:15:32 +0100361 ptrdiff_t GetFirstLimit() {
armvixl5289c592015-03-02 13:52:04 +0000362 ptrdiff_t res = kInvalidOffset;
363 for (int i = 0; i < kNumberOfTrackedBranchTypes; i++) {
Pierre Langlois88c46b82016-06-02 18:15:32 +0100364 res = std::min(res, typed_set_[i].GetFirstLimit());
armvixl5289c592015-03-02 13:52:04 +0000365 }
366 return res;
367 }
Pierre Langlois88c46b82016-06-02 18:15:32 +0100368 VIXL_DEPRECATED("GetFirstLimit", ptrdiff_t FirstLimit()) {
369 return GetFirstLimit();
370 }
armvixl5289c592015-03-02 13:52:04 +0000371
372 void Reset() {
373 for (int i = 0; i < kNumberOfTrackedBranchTypes; i++) {
374 typed_set_[i].clear();
375 }
376 }
377
378 static ImmBranchType BranchTypeFromIndex(int index) {
379 switch (index) {
380 case 0:
381 return CondBranchType;
382 case 1:
383 return CompareBranchType;
384 case 2:
385 return TestBranchType;
386 default:
387 VIXL_UNREACHABLE();
388 return UnknownBranchType;
389 }
390 }
391 static int BranchIndexFromType(ImmBranchType branch_type) {
392 switch (branch_type) {
393 case CondBranchType:
394 return 0;
395 case CompareBranchType:
396 return 1;
397 case TestBranchType:
398 return 2;
399 default:
400 VIXL_UNREACHABLE();
401 return 0;
402 }
403 }
404
405 bool IsValidBranchType(ImmBranchType branch_type) {
406 return (branch_type != UnknownBranchType) &&
407 (branch_type != UncondBranchType);
408 }
409
410 private:
411 static const int kNumberOfTrackedBranchTypes = 3;
412 BranchInfoTypedSet typed_set_[kNumberOfTrackedBranchTypes];
413
414 friend class VeneerPool;
415 friend class BranchInfoSetIterator;
416 };
417
418 class BranchInfoSetIterator {
419 public:
420 explicit BranchInfoSetIterator(BranchInfoSet* set) : set_(set) {
421 for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) {
armvixl0f35e362016-05-10 13:57:58 +0100422 new (&sub_iterator_[i])
armvixl5289c592015-03-02 13:52:04 +0000423 BranchInfoTypedSetIterator(&(set_->typed_set_[i]));
424 }
425 }
426
427 VeneerPool::BranchInfo* Current() {
428 for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) {
429 if (!sub_iterator_[i].Done()) {
430 return sub_iterator_[i].Current();
431 }
432 }
433 VIXL_UNREACHABLE();
434 return NULL;
435 }
436
437 void Advance() {
438 VIXL_ASSERT(!Done());
439 for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) {
440 if (!sub_iterator_[i].Done()) {
441 sub_iterator_[i].Advance();
442 return;
443 }
444 }
445 VIXL_UNREACHABLE();
446 }
447
448 bool Done() const {
449 for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) {
450 if (!sub_iterator_[i].Done()) return false;
451 }
452 return true;
453 }
454
455 void AdvanceToNextType() {
456 VIXL_ASSERT(!Done());
457 for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) {
458 if (!sub_iterator_[i].Done()) {
459 sub_iterator_[i].Finish();
460 return;
461 }
462 }
463 VIXL_UNREACHABLE();
464 }
465
466 void DeleteCurrentAndAdvance() {
467 for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) {
468 if (!sub_iterator_[i].Done()) {
469 sub_iterator_[i].DeleteCurrentAndAdvance();
470 return;
471 }
472 }
473 }
474
475 private:
476 BranchInfoSet* set_;
477 BranchInfoTypedSetIterator
478 sub_iterator_[BranchInfoSet::kNumberOfTrackedBranchTypes];
479 };
480
Pierre Langlois88c46b82016-06-02 18:15:32 +0100481 ptrdiff_t GetNextCheckPoint() {
482 if (unresolved_branches_.IsEmpty()) {
armvixl5289c592015-03-02 13:52:04 +0000483 return kNoCheckpointRequired;
484 } else {
Pierre Langlois88c46b82016-06-02 18:15:32 +0100485 return unresolved_branches_.GetFirstLimit();
armvixl5289c592015-03-02 13:52:04 +0000486 }
487 }
Pierre Langlois88c46b82016-06-02 18:15:32 +0100488 VIXL_DEPRECATED("GetNextCheckPoint", ptrdiff_t NextCheckPoint()) {
489 return GetNextCheckPoint();
490 }
armvixl5289c592015-03-02 13:52:04 +0000491
492 // Information about unresolved (forward) branches.
493 BranchInfoSet unresolved_branches_;
494};
495
496
armvixlc68cb642014-09-25 18:49:30 +0100497// This scope has the following purposes:
498// * Acquire/Release the underlying assembler's code buffer.
499// * This is mandatory before emitting.
armvixldb644342015-07-21 11:37:10 +0100500// * Emit the literal or veneer pools if necessary before emitting the
501// macro-instruction.
armvixlc68cb642014-09-25 18:49:30 +0100502// * Ensure there is enough space to emit the macro-instruction.
503class EmissionCheckScope {
504 public:
505 EmissionCheckScope(MacroAssembler* masm, size_t size);
506 ~EmissionCheckScope();
507
508 protected:
armvixlc68cb642014-09-25 18:49:30 +0100509 MacroAssembler* masm_;
armvixldb644342015-07-21 11:37:10 +0100510#ifdef VIXL_DEBUG
armvixlc68cb642014-09-25 18:49:30 +0100511 Label start_;
512 size_t size_;
513#endif
514};
515
516
517// Helper for common Emission checks.
518// The macro-instruction maps to a single instruction.
519class SingleEmissionCheckScope : public EmissionCheckScope {
520 public:
521 explicit SingleEmissionCheckScope(MacroAssembler* masm)
522 : EmissionCheckScope(masm, kInstructionSize) {}
523};
524
525
526// The macro instruction is a "typical" macro-instruction. Typical macro-
527// instruction only emit a few instructions, a few being defined as 8 here.
528class MacroEmissionCheckScope : public EmissionCheckScope {
529 public:
530 explicit MacroEmissionCheckScope(MacroAssembler* masm)
531 : EmissionCheckScope(masm, kTypicalMacroInstructionMaxSize) {}
532
533 private:
534 static const size_t kTypicalMacroInstructionMaxSize = 8 * kInstructionSize;
535};
536
537
armvixlb0c8ae22014-03-21 14:03:59 +0000538enum BranchType {
539 // Copies of architectural conditions.
540 // The associated conditions can be used in place of those, the code will
541 // take care of reinterpreting them with the correct type.
542 integer_eq = eq,
543 integer_ne = ne,
544 integer_hs = hs,
545 integer_lo = lo,
546 integer_mi = mi,
547 integer_pl = pl,
548 integer_vs = vs,
549 integer_vc = vc,
550 integer_hi = hi,
551 integer_ls = ls,
552 integer_ge = ge,
553 integer_lt = lt,
554 integer_gt = gt,
555 integer_le = le,
556 integer_al = al,
557 integer_nv = nv,
558
559 // These two are *different* from the architectural codes al and nv.
560 // 'always' is used to generate unconditional branches.
561 // 'never' is used to not generate a branch (generally as the inverse
562 // branch type of 'always).
armvixl0f35e362016-05-10 13:57:58 +0100563 always,
564 never,
armvixlb0c8ae22014-03-21 14:03:59 +0000565 // cbz and cbnz
armvixl0f35e362016-05-10 13:57:58 +0100566 reg_zero,
567 reg_not_zero,
armvixlb0c8ae22014-03-21 14:03:59 +0000568 // tbz and tbnz
armvixl0f35e362016-05-10 13:57:58 +0100569 reg_bit_clear,
570 reg_bit_set,
armvixlb0c8ae22014-03-21 14:03:59 +0000571
572 // Aliases.
573 kBranchTypeFirstCondition = eq,
574 kBranchTypeLastCondition = nv,
575 kBranchTypeFirstUsingReg = reg_zero,
576 kBranchTypeFirstUsingBit = reg_bit_clear
577};
578
579
armvixlf37fdc02014-02-05 13:22:16 +0000580enum DiscardMoveMode { kDontDiscardForSameWReg, kDiscardForSameWReg };
581
armvixlc68cb642014-09-25 18:49:30 +0100582
armvixlad96eda2013-06-14 11:42:37 +0100583class MacroAssembler : public Assembler {
584 public:
armvixlc68cb642014-09-25 18:49:30 +0100585 MacroAssembler(size_t capacity,
586 PositionIndependentCodeOption pic = PositionIndependentCode);
armvixl0f35e362016-05-10 13:57:58 +0100587 MacroAssembler(byte* buffer,
588 size_t capacity,
armvixlc68cb642014-09-25 18:49:30 +0100589 PositionIndependentCodeOption pic = PositionIndependentCode);
590 ~MacroAssembler();
591
592 // Start generating code from the beginning of the buffer, discarding any code
593 // and data that has already been emitted into the buffer.
594 //
595 // In order to avoid any accidental transfer of state, Reset ASSERTs that the
596 // constant pool is not blocked.
597 void Reset();
598
599 // Finalize a code buffer of generated instructions. This function must be
600 // called before executing or copying code from the buffer.
601 void FinalizeCode();
armvixlad96eda2013-06-14 11:42:37 +0100602
armvixl330dc712014-11-25 10:38:32 +0000603
604 // Constant generation helpers.
605 // These functions return the number of instructions required to move the
606 // immediate into the destination register. Also, if the masm pointer is
607 // non-null, it generates the code to do so.
608 // The two features are implemented using one function to avoid duplication of
609 // the logic.
610 // The function can be used to evaluate the cost of synthesizing an
611 // instruction using 'mov immediate' instructions. A user might prefer loading
612 // a constant using the literal pool instead of using multiple 'mov immediate'
613 // instructions.
614 static int MoveImmediateHelper(MacroAssembler* masm,
armvixl0f35e362016-05-10 13:57:58 +0100615 const Register& rd,
armvixl330dc712014-11-25 10:38:32 +0000616 uint64_t imm);
617 static bool OneInstrMoveImmediateHelper(MacroAssembler* masm,
618 const Register& dst,
619 int64_t imm);
620
621
armvixlad96eda2013-06-14 11:42:37 +0100622 // Logical macros.
armvixl0f35e362016-05-10 13:57:58 +0100623 void And(const Register& rd, const Register& rn, const Operand& operand);
624 void Ands(const Register& rd, const Register& rn, const Operand& operand);
625 void Bic(const Register& rd, const Register& rn, const Operand& operand);
626 void Bics(const Register& rd, const Register& rn, const Operand& operand);
627 void Orr(const Register& rd, const Register& rn, const Operand& operand);
628 void Orn(const Register& rd, const Register& rn, const Operand& operand);
629 void Eor(const Register& rd, const Register& rn, const Operand& operand);
630 void Eon(const Register& rd, const Register& rn, const Operand& operand);
armvixlad96eda2013-06-14 11:42:37 +0100631 void Tst(const Register& rn, const Operand& operand);
632 void LogicalMacro(const Register& rd,
633 const Register& rn,
634 const Operand& operand,
635 LogicalOp op);
636
637 // Add and sub macros.
638 void Add(const Register& rd,
639 const Register& rn,
armvixl6e2c8272015-03-31 11:04:14 +0100640 const Operand& operand,
641 FlagsUpdate S = LeaveFlags);
armvixl0f35e362016-05-10 13:57:58 +0100642 void Adds(const Register& rd, const Register& rn, const Operand& operand);
armvixlad96eda2013-06-14 11:42:37 +0100643 void Sub(const Register& rd,
644 const Register& rn,
armvixl6e2c8272015-03-31 11:04:14 +0100645 const Operand& operand,
646 FlagsUpdate S = LeaveFlags);
armvixl0f35e362016-05-10 13:57:58 +0100647 void Subs(const Register& rd, const Register& rn, const Operand& operand);
armvixlad96eda2013-06-14 11:42:37 +0100648 void Cmn(const Register& rn, const Operand& operand);
649 void Cmp(const Register& rn, const Operand& operand);
armvixl0f35e362016-05-10 13:57:58 +0100650 void Neg(const Register& rd, const Operand& operand);
651 void Negs(const Register& rd, const Operand& operand);
armvixlf37fdc02014-02-05 13:22:16 +0000652
armvixlad96eda2013-06-14 11:42:37 +0100653 void AddSubMacro(const Register& rd,
654 const Register& rn,
655 const Operand& operand,
656 FlagsUpdate S,
657 AddSubOp op);
658
659 // Add/sub with carry macros.
armvixl0f35e362016-05-10 13:57:58 +0100660 void Adc(const Register& rd, const Register& rn, const Operand& operand);
661 void Adcs(const Register& rd, const Register& rn, const Operand& operand);
662 void Sbc(const Register& rd, const Register& rn, const Operand& operand);
663 void Sbcs(const Register& rd, const Register& rn, const Operand& operand);
664 void Ngc(const Register& rd, const Operand& operand);
665 void Ngcs(const Register& rd, const Operand& operand);
armvixlad96eda2013-06-14 11:42:37 +0100666 void AddSubWithCarryMacro(const Register& rd,
667 const Register& rn,
668 const Operand& operand,
669 FlagsUpdate S,
670 AddSubWithCarryOp op);
671
672 // Move macros.
673 void Mov(const Register& rd, uint64_t imm);
armvixlf37fdc02014-02-05 13:22:16 +0000674 void Mov(const Register& rd,
675 const Operand& operand,
676 DiscardMoveMode discard_mode = kDontDiscardForSameWReg);
armvixlad96eda2013-06-14 11:42:37 +0100677 void Mvn(const Register& rd, uint64_t imm) {
Pierre Langlois88c46b82016-06-02 18:15:32 +0100678 Mov(rd, (rd.GetSizeInBits() == kXRegSize) ? ~imm : (~imm & kWRegMask));
armvixl4a102ba2014-07-14 09:02:40 +0100679 }
armvixlad96eda2013-06-14 11:42:37 +0100680 void Mvn(const Register& rd, const Operand& operand);
armvixlad96eda2013-06-14 11:42:37 +0100681
armvixl4a102ba2014-07-14 09:02:40 +0100682 // Try to move an immediate into the destination register in a single
683 // instruction. Returns true for success, and updates the contents of dst.
684 // Returns false, otherwise.
685 bool TryOneInstrMoveImmediate(const Register& dst, int64_t imm);
686
687 // Move an immediate into register dst, and return an Operand object for
688 // use with a subsequent instruction that accepts a shift. The value moved
689 // into dst is not necessarily equal to imm; it may have had a shifting
690 // operation applied to it that will be subsequently undone by the shift
691 // applied in the Operand.
692 Operand MoveImmediateForShiftedOp(const Register& dst, int64_t imm);
693
armvixl5289c592015-03-02 13:52:04 +0000694 // Synthesises the address represented by a MemOperand into a register.
695 void ComputeAddress(const Register& dst, const MemOperand& mem_op);
696
armvixlf37fdc02014-02-05 13:22:16 +0000697 // Conditional macros.
armvixlad96eda2013-06-14 11:42:37 +0100698 void Ccmp(const Register& rn,
699 const Operand& operand,
700 StatusFlags nzcv,
701 Condition cond);
702 void Ccmn(const Register& rn,
703 const Operand& operand,
704 StatusFlags nzcv,
705 Condition cond);
706 void ConditionalCompareMacro(const Register& rn,
707 const Operand& operand,
708 StatusFlags nzcv,
709 Condition cond,
710 ConditionalCompareOp op);
711
armvixl0f35e362016-05-10 13:57:58 +0100712 // On return, the boolean values pointed to will indicate whether `left` and
713 // `right` should be synthesised in a temporary register.
714 static void GetCselSynthesisInformation(const Register& rd,
715 const Operand& left,
716 const Operand& right,
717 bool* should_synthesise_left,
718 bool* should_synthesise_right) {
719 // Note that the helper does not need to look at the condition.
720 CselHelper(NULL,
721 rd,
722 left,
723 right,
724 eq,
725 should_synthesise_left,
726 should_synthesise_right);
727 }
728
729 void Csel(const Register& rd,
730 const Operand& left,
731 const Operand& right,
732 Condition cond) {
733 CselHelper(this, rd, left, right, cond);
734 }
735
736// Load/store macros.
armvixlad96eda2013-06-14 11:42:37 +0100737#define DECLARE_FUNCTION(FN, REGTYPE, REG, OP) \
738 void FN(const REGTYPE REG, const MemOperand& addr);
739 LS_MACRO_LIST(DECLARE_FUNCTION)
740#undef DECLARE_FUNCTION
741
742 void LoadStoreMacro(const CPURegister& rt,
743 const MemOperand& addr,
744 LoadStoreOp op);
745
armvixlc68cb642014-09-25 18:49:30 +0100746#define DECLARE_FUNCTION(FN, REGTYPE, REG, REG2, OP) \
747 void FN(const REGTYPE REG, const REGTYPE REG2, const MemOperand& addr);
748 LSPAIR_MACRO_LIST(DECLARE_FUNCTION)
749#undef DECLARE_FUNCTION
750
751 void LoadStorePairMacro(const CPURegister& rt,
752 const CPURegister& rt2,
753 const MemOperand& addr,
754 LoadStorePairOp op);
755
armvixl330dc712014-11-25 10:38:32 +0000756 void Prfm(PrefetchOperation op, const MemOperand& addr);
757
armvixlad96eda2013-06-14 11:42:37 +0100758 // Push or pop up to 4 registers of the same width to or from the stack,
759 // using the current stack pointer as set by SetStackPointer.
760 //
761 // If an argument register is 'NoReg', all further arguments are also assumed
762 // to be 'NoReg', and are thus not pushed or popped.
763 //
764 // Arguments are ordered such that "Push(a, b);" is functionally equivalent
765 // to "Push(a); Push(b);".
766 //
767 // It is valid to push the same register more than once, and there is no
768 // restriction on the order in which registers are specified.
769 //
770 // It is not valid to pop into the same register more than once in one
771 // operation, not even into the zero register.
772 //
773 // If the current stack pointer (as set by SetStackPointer) is sp, then it
774 // must be aligned to 16 bytes on entry and the total size of the specified
775 // registers must also be a multiple of 16 bytes.
776 //
777 // Even if the current stack pointer is not the system stack pointer (sp),
778 // Push (and derived methods) will still modify the system stack pointer in
779 // order to comply with ABI rules about accessing memory below the system
780 // stack pointer.
781 //
782 // Other than the registers passed into Pop, the stack pointer and (possibly)
783 // the system stack pointer, these methods do not modify any other registers.
armvixl0f35e362016-05-10 13:57:58 +0100784 void Push(const CPURegister& src0,
785 const CPURegister& src1 = NoReg,
786 const CPURegister& src2 = NoReg,
787 const CPURegister& src3 = NoReg);
788 void Pop(const CPURegister& dst0,
789 const CPURegister& dst1 = NoReg,
790 const CPURegister& dst2 = NoReg,
791 const CPURegister& dst3 = NoReg);
armvixlad96eda2013-06-14 11:42:37 +0100792
793 // Alternative forms of Push and Pop, taking a RegList or CPURegList that
794 // specifies the registers that are to be pushed or popped. Higher-numbered
795 // registers are associated with higher memory addresses (as in the A32 push
796 // and pop instructions).
797 //
798 // (Push|Pop)SizeRegList allow you to specify the register size as a
799 // parameter. Only kXRegSize, kWRegSize, kDRegSize and kSRegSize are
800 // supported.
801 //
802 // Otherwise, (Push|Pop)(CPU|X|W|D|S)RegList is preferred.
803 void PushCPURegList(CPURegList registers);
804 void PopCPURegList(CPURegList registers);
805
armvixl0f35e362016-05-10 13:57:58 +0100806 void PushSizeRegList(
807 RegList registers,
808 unsigned reg_size,
armvixlad96eda2013-06-14 11:42:37 +0100809 CPURegister::RegisterType type = CPURegister::kRegister) {
810 PushCPURegList(CPURegList(type, reg_size, registers));
811 }
armvixl0f35e362016-05-10 13:57:58 +0100812 void PopSizeRegList(RegList registers,
813 unsigned reg_size,
814 CPURegister::RegisterType type = CPURegister::kRegister) {
armvixlad96eda2013-06-14 11:42:37 +0100815 PopCPURegList(CPURegList(type, reg_size, registers));
816 }
armvixl0f35e362016-05-10 13:57:58 +0100817 void PushXRegList(RegList regs) { PushSizeRegList(regs, kXRegSize); }
818 void PopXRegList(RegList regs) { PopSizeRegList(regs, kXRegSize); }
819 void PushWRegList(RegList regs) { PushSizeRegList(regs, kWRegSize); }
820 void PopWRegList(RegList regs) { PopSizeRegList(regs, kWRegSize); }
armvixl330dc712014-11-25 10:38:32 +0000821 void PushDRegList(RegList regs) {
armvixl5289c592015-03-02 13:52:04 +0000822 PushSizeRegList(regs, kDRegSize, CPURegister::kVRegister);
armvixlad96eda2013-06-14 11:42:37 +0100823 }
armvixl330dc712014-11-25 10:38:32 +0000824 void PopDRegList(RegList regs) {
armvixl5289c592015-03-02 13:52:04 +0000825 PopSizeRegList(regs, kDRegSize, CPURegister::kVRegister);
armvixlad96eda2013-06-14 11:42:37 +0100826 }
armvixl330dc712014-11-25 10:38:32 +0000827 void PushSRegList(RegList regs) {
armvixl5289c592015-03-02 13:52:04 +0000828 PushSizeRegList(regs, kSRegSize, CPURegister::kVRegister);
armvixlad96eda2013-06-14 11:42:37 +0100829 }
armvixl330dc712014-11-25 10:38:32 +0000830 void PopSRegList(RegList regs) {
armvixl5289c592015-03-02 13:52:04 +0000831 PopSizeRegList(regs, kSRegSize, CPURegister::kVRegister);
armvixlad96eda2013-06-14 11:42:37 +0100832 }
833
834 // Push the specified register 'count' times.
835 void PushMultipleTimes(int count, Register src);
836
837 // Poke 'src' onto the stack. The offset is in bytes.
838 //
839 // If the current stack pointer (as set by SetStackPointer) is sp, then sp
840 // must be aligned to 16 bytes.
841 void Poke(const Register& src, const Operand& offset);
842
843 // Peek at a value on the stack, and put it in 'dst'. The offset is in bytes.
844 //
845 // If the current stack pointer (as set by SetStackPointer) is sp, then sp
846 // must be aligned to 16 bytes.
847 void Peek(const Register& dst, const Operand& offset);
848
armvixlc68cb642014-09-25 18:49:30 +0100849 // Alternative forms of Peek and Poke, taking a RegList or CPURegList that
850 // specifies the registers that are to be pushed or popped. Higher-numbered
851 // registers are associated with higher memory addresses.
852 //
853 // (Peek|Poke)SizeRegList allow you to specify the register size as a
854 // parameter. Only kXRegSize, kWRegSize, kDRegSize and kSRegSize are
855 // supported.
856 //
857 // Otherwise, (Peek|Poke)(CPU|X|W|D|S)RegList is preferred.
armvixl6e2c8272015-03-31 11:04:14 +0100858 void PeekCPURegList(CPURegList registers, int64_t offset) {
859 LoadCPURegList(registers, MemOperand(StackPointer(), offset));
860 }
861 void PokeCPURegList(CPURegList registers, int64_t offset) {
862 StoreCPURegList(registers, MemOperand(StackPointer(), offset));
863 }
armvixlc68cb642014-09-25 18:49:30 +0100864
armvixl0f35e362016-05-10 13:57:58 +0100865 void PeekSizeRegList(
866 RegList registers,
867 int64_t offset,
868 unsigned reg_size,
armvixlc68cb642014-09-25 18:49:30 +0100869 CPURegister::RegisterType type = CPURegister::kRegister) {
870 PeekCPURegList(CPURegList(type, reg_size, registers), offset);
871 }
armvixl0f35e362016-05-10 13:57:58 +0100872 void PokeSizeRegList(
873 RegList registers,
874 int64_t offset,
875 unsigned reg_size,
armvixlc68cb642014-09-25 18:49:30 +0100876 CPURegister::RegisterType type = CPURegister::kRegister) {
877 PokeCPURegList(CPURegList(type, reg_size, registers), offset);
878 }
armvixl6e2c8272015-03-31 11:04:14 +0100879 void PeekXRegList(RegList regs, int64_t offset) {
armvixlc68cb642014-09-25 18:49:30 +0100880 PeekSizeRegList(regs, offset, kXRegSize);
881 }
armvixl6e2c8272015-03-31 11:04:14 +0100882 void PokeXRegList(RegList regs, int64_t offset) {
armvixlc68cb642014-09-25 18:49:30 +0100883 PokeSizeRegList(regs, offset, kXRegSize);
884 }
armvixl6e2c8272015-03-31 11:04:14 +0100885 void PeekWRegList(RegList regs, int64_t offset) {
armvixlc68cb642014-09-25 18:49:30 +0100886 PeekSizeRegList(regs, offset, kWRegSize);
887 }
armvixl6e2c8272015-03-31 11:04:14 +0100888 void PokeWRegList(RegList regs, int64_t offset) {
armvixlc68cb642014-09-25 18:49:30 +0100889 PokeSizeRegList(regs, offset, kWRegSize);
890 }
armvixl6e2c8272015-03-31 11:04:14 +0100891 void PeekDRegList(RegList regs, int64_t offset) {
armvixl5289c592015-03-02 13:52:04 +0000892 PeekSizeRegList(regs, offset, kDRegSize, CPURegister::kVRegister);
armvixlc68cb642014-09-25 18:49:30 +0100893 }
armvixl6e2c8272015-03-31 11:04:14 +0100894 void PokeDRegList(RegList regs, int64_t offset) {
armvixl5289c592015-03-02 13:52:04 +0000895 PokeSizeRegList(regs, offset, kDRegSize, CPURegister::kVRegister);
armvixlc68cb642014-09-25 18:49:30 +0100896 }
armvixl6e2c8272015-03-31 11:04:14 +0100897 void PeekSRegList(RegList regs, int64_t offset) {
armvixl5289c592015-03-02 13:52:04 +0000898 PeekSizeRegList(regs, offset, kSRegSize, CPURegister::kVRegister);
armvixlc68cb642014-09-25 18:49:30 +0100899 }
armvixl6e2c8272015-03-31 11:04:14 +0100900 void PokeSRegList(RegList regs, int64_t offset) {
armvixl5289c592015-03-02 13:52:04 +0000901 PokeSizeRegList(regs, offset, kSRegSize, CPURegister::kVRegister);
armvixlc68cb642014-09-25 18:49:30 +0100902 }
903
904
armvixlad96eda2013-06-14 11:42:37 +0100905 // Claim or drop stack space without actually accessing memory.
906 //
907 // If the current stack pointer (as set by SetStackPointer) is sp, then it
908 // must be aligned to 16 bytes and the size claimed or dropped must be a
909 // multiple of 16 bytes.
910 void Claim(const Operand& size);
911 void Drop(const Operand& size);
912
913 // Preserve the callee-saved registers (as defined by AAPCS64).
914 //
915 // Higher-numbered registers are pushed before lower-numbered registers, and
916 // thus get higher addresses.
917 // Floating-point registers are pushed before general-purpose registers, and
918 // thus get higher addresses.
919 //
920 // This method must not be called unless StackPointer() is sp, and it is
921 // aligned to 16 bytes.
922 void PushCalleeSavedRegisters();
923
924 // Restore the callee-saved registers (as defined by AAPCS64).
925 //
926 // Higher-numbered registers are popped after lower-numbered registers, and
927 // thus come from higher addresses.
928 // Floating-point registers are popped after general-purpose registers, and
929 // thus come from higher addresses.
930 //
931 // This method must not be called unless StackPointer() is sp, and it is
932 // aligned to 16 bytes.
933 void PopCalleeSavedRegisters();
934
armvixl6e2c8272015-03-31 11:04:14 +0100935 void LoadCPURegList(CPURegList registers, const MemOperand& src);
936 void StoreCPURegList(CPURegList registers, const MemOperand& dst);
937
armvixlad96eda2013-06-14 11:42:37 +0100938 // Remaining instructions are simple pass-through calls to the assembler.
939 void Adr(const Register& rd, Label* label) {
armvixlb0c8ae22014-03-21 14:03:59 +0000940 VIXL_ASSERT(allow_macro_instructions_);
941 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100942 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100943 adr(rd, label);
944 }
armvixl4a102ba2014-07-14 09:02:40 +0100945 void Adrp(const Register& rd, Label* label) {
946 VIXL_ASSERT(allow_macro_instructions_);
947 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100948 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +0100949 adrp(rd, label);
950 }
armvixlad96eda2013-06-14 11:42:37 +0100951 void Asr(const Register& rd, const Register& rn, unsigned shift) {
armvixlb0c8ae22014-03-21 14:03:59 +0000952 VIXL_ASSERT(allow_macro_instructions_);
953 VIXL_ASSERT(!rd.IsZero());
954 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100955 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100956 asr(rd, rn, shift);
957 }
958 void Asr(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +0000959 VIXL_ASSERT(allow_macro_instructions_);
960 VIXL_ASSERT(!rd.IsZero());
961 VIXL_ASSERT(!rn.IsZero());
962 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100963 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100964 asrv(rd, rn, rm);
965 }
armvixlb0c8ae22014-03-21 14:03:59 +0000966
967 // Branch type inversion relies on these relations.
armvixl0f35e362016-05-10 13:57:58 +0100968 VIXL_STATIC_ASSERT((reg_zero == (reg_not_zero ^ 1)) &&
armvixlb0c8ae22014-03-21 14:03:59 +0000969 (reg_bit_clear == (reg_bit_set ^ 1)) &&
armvixl0f35e362016-05-10 13:57:58 +0100970 (always == (never ^ 1)));
armvixlb0c8ae22014-03-21 14:03:59 +0000971
972 BranchType InvertBranchType(BranchType type) {
973 if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) {
974 return static_cast<BranchType>(
975 InvertCondition(static_cast<Condition>(type)));
976 } else {
977 return static_cast<BranchType>(type ^ 1);
978 }
979 }
980
981 void B(Label* label, BranchType type, Register reg = NoReg, int bit = -1);
982
armvixl5289c592015-03-02 13:52:04 +0000983 void B(Label* label);
984 void B(Label* label, Condition cond);
armvixl0f35e362016-05-10 13:57:58 +0100985 void B(Condition cond, Label* label) { B(label, cond); }
armvixl5289c592015-03-02 13:52:04 +0000986 void Bfm(const Register& rd,
987 const Register& rn,
988 unsigned immr,
989 unsigned imms) {
990 VIXL_ASSERT(allow_macro_instructions_);
991 VIXL_ASSERT(!rd.IsZero());
992 VIXL_ASSERT(!rn.IsZero());
993 SingleEmissionCheckScope guard(this);
994 bfm(rd, rn, immr, imms);
995 }
armvixlad96eda2013-06-14 11:42:37 +0100996 void Bfi(const Register& rd,
997 const Register& rn,
998 unsigned lsb,
999 unsigned width) {
armvixlb0c8ae22014-03-21 14:03:59 +00001000 VIXL_ASSERT(allow_macro_instructions_);
1001 VIXL_ASSERT(!rd.IsZero());
1002 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001003 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001004 bfi(rd, rn, lsb, width);
1005 }
1006 void Bfxil(const Register& rd,
1007 const Register& rn,
1008 unsigned lsb,
1009 unsigned width) {
armvixlb0c8ae22014-03-21 14:03:59 +00001010 VIXL_ASSERT(allow_macro_instructions_);
1011 VIXL_ASSERT(!rd.IsZero());
1012 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001013 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001014 bfxil(rd, rn, lsb, width);
1015 }
armvixl5289c592015-03-02 13:52:04 +00001016 void Bind(Label* label);
armvixlc68cb642014-09-25 18:49:30 +01001017 // Bind a label to a specified offset from the start of the buffer.
armvixl5289c592015-03-02 13:52:04 +00001018 void BindToOffset(Label* label, ptrdiff_t offset);
armvixlad96eda2013-06-14 11:42:37 +01001019 void Bl(Label* label) {
armvixlb0c8ae22014-03-21 14:03:59 +00001020 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001021 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001022 bl(label);
1023 }
1024 void Blr(const Register& xn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001025 VIXL_ASSERT(allow_macro_instructions_);
1026 VIXL_ASSERT(!xn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001027 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001028 blr(xn);
1029 }
1030 void Br(const Register& xn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001031 VIXL_ASSERT(allow_macro_instructions_);
1032 VIXL_ASSERT(!xn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001033 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001034 br(xn);
1035 }
1036 void Brk(int code = 0) {
armvixlb0c8ae22014-03-21 14:03:59 +00001037 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001038 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001039 brk(code);
1040 }
armvixl5289c592015-03-02 13:52:04 +00001041 void Cbnz(const Register& rt, Label* label);
1042 void Cbz(const Register& rt, Label* label);
armvixlad96eda2013-06-14 11:42:37 +01001043 void Cinc(const Register& rd, const Register& rn, Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +00001044 VIXL_ASSERT(allow_macro_instructions_);
1045 VIXL_ASSERT(!rd.IsZero());
1046 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001047 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001048 cinc(rd, rn, cond);
1049 }
1050 void Cinv(const Register& rd, const Register& rn, Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +00001051 VIXL_ASSERT(allow_macro_instructions_);
1052 VIXL_ASSERT(!rd.IsZero());
1053 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001054 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001055 cinv(rd, rn, cond);
1056 }
armvixl4a102ba2014-07-14 09:02:40 +01001057 void Clrex() {
1058 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001059 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001060 clrex();
1061 }
armvixlad96eda2013-06-14 11:42:37 +01001062 void Cls(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001063 VIXL_ASSERT(allow_macro_instructions_);
1064 VIXL_ASSERT(!rd.IsZero());
1065 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001066 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001067 cls(rd, rn);
1068 }
1069 void Clz(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001070 VIXL_ASSERT(allow_macro_instructions_);
1071 VIXL_ASSERT(!rd.IsZero());
1072 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001073 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001074 clz(rd, rn);
1075 }
1076 void Cneg(const Register& rd, const Register& rn, Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +00001077 VIXL_ASSERT(allow_macro_instructions_);
1078 VIXL_ASSERT(!rd.IsZero());
1079 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001080 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001081 cneg(rd, rn, cond);
1082 }
armvixlad96eda2013-06-14 11:42:37 +01001083 void Cset(const Register& rd, Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +00001084 VIXL_ASSERT(allow_macro_instructions_);
1085 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001086 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001087 cset(rd, cond);
1088 }
1089 void Csetm(const Register& rd, Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +00001090 VIXL_ASSERT(allow_macro_instructions_);
1091 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001092 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001093 csetm(rd, cond);
1094 }
1095 void Csinc(const Register& rd,
1096 const Register& rn,
1097 const Register& rm,
1098 Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +00001099 VIXL_ASSERT(allow_macro_instructions_);
1100 VIXL_ASSERT(!rd.IsZero());
1101 VIXL_ASSERT(!rn.IsZero());
1102 VIXL_ASSERT(!rm.IsZero());
1103 VIXL_ASSERT((cond != al) && (cond != nv));
armvixlc68cb642014-09-25 18:49:30 +01001104 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001105 csinc(rd, rn, rm, cond);
1106 }
1107 void Csinv(const Register& rd,
1108 const Register& rn,
1109 const Register& rm,
1110 Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +00001111 VIXL_ASSERT(allow_macro_instructions_);
1112 VIXL_ASSERT(!rd.IsZero());
1113 VIXL_ASSERT(!rn.IsZero());
1114 VIXL_ASSERT(!rm.IsZero());
1115 VIXL_ASSERT((cond != al) && (cond != nv));
armvixlc68cb642014-09-25 18:49:30 +01001116 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001117 csinv(rd, rn, rm, cond);
1118 }
1119 void Csneg(const Register& rd,
1120 const Register& rn,
1121 const Register& rm,
1122 Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +00001123 VIXL_ASSERT(allow_macro_instructions_);
1124 VIXL_ASSERT(!rd.IsZero());
1125 VIXL_ASSERT(!rn.IsZero());
1126 VIXL_ASSERT(!rm.IsZero());
1127 VIXL_ASSERT((cond != al) && (cond != nv));
armvixlc68cb642014-09-25 18:49:30 +01001128 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001129 csneg(rd, rn, rm, cond);
1130 }
armvixlf37fdc02014-02-05 13:22:16 +00001131 void Dmb(BarrierDomain domain, BarrierType type) {
armvixlb0c8ae22014-03-21 14:03:59 +00001132 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001133 SingleEmissionCheckScope guard(this);
armvixlf37fdc02014-02-05 13:22:16 +00001134 dmb(domain, type);
1135 }
1136 void Dsb(BarrierDomain domain, BarrierType type) {
armvixlb0c8ae22014-03-21 14:03:59 +00001137 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001138 SingleEmissionCheckScope guard(this);
armvixlf37fdc02014-02-05 13:22:16 +00001139 dsb(domain, type);
1140 }
armvixlad96eda2013-06-14 11:42:37 +01001141 void Extr(const Register& rd,
1142 const Register& rn,
1143 const Register& rm,
1144 unsigned lsb) {
armvixlb0c8ae22014-03-21 14:03:59 +00001145 VIXL_ASSERT(allow_macro_instructions_);
1146 VIXL_ASSERT(!rd.IsZero());
1147 VIXL_ASSERT(!rn.IsZero());
1148 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001149 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001150 extr(rd, rn, rm, lsb);
1151 }
armvixl5289c592015-03-02 13:52:04 +00001152 void Fadd(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001153 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001154 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001155 fadd(vd, vn, vm);
armvixlad96eda2013-06-14 11:42:37 +01001156 }
armvixl5289c592015-03-02 13:52:04 +00001157 void Fccmp(const VRegister& vn,
1158 const VRegister& vm,
armvixlad96eda2013-06-14 11:42:37 +01001159 StatusFlags nzcv,
armvixl6e2c8272015-03-31 11:04:14 +01001160 Condition cond,
1161 FPTrapFlags trap = DisableTrap) {
armvixlb0c8ae22014-03-21 14:03:59 +00001162 VIXL_ASSERT(allow_macro_instructions_);
1163 VIXL_ASSERT((cond != al) && (cond != nv));
armvixlc68cb642014-09-25 18:49:30 +01001164 SingleEmissionCheckScope guard(this);
armvixl6e2c8272015-03-31 11:04:14 +01001165 FPCCompareMacro(vn, vm, nzcv, cond, trap);
armvixlad96eda2013-06-14 11:42:37 +01001166 }
armvixl6e2c8272015-03-31 11:04:14 +01001167 void Fccmpe(const VRegister& vn,
1168 const VRegister& vm,
1169 StatusFlags nzcv,
1170 Condition cond) {
1171 Fccmp(vn, vm, nzcv, cond, EnableTrap);
1172 }
armvixl0f35e362016-05-10 13:57:58 +01001173 void Fcmp(const VRegister& vn,
1174 const VRegister& vm,
armvixl6e2c8272015-03-31 11:04:14 +01001175 FPTrapFlags trap = DisableTrap) {
armvixlb0c8ae22014-03-21 14:03:59 +00001176 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001177 SingleEmissionCheckScope guard(this);
armvixl6e2c8272015-03-31 11:04:14 +01001178 FPCompareMacro(vn, vm, trap);
armvixlad96eda2013-06-14 11:42:37 +01001179 }
armvixl0f35e362016-05-10 13:57:58 +01001180 void Fcmp(const VRegister& vn, double value, FPTrapFlags trap = DisableTrap);
armvixl6e2c8272015-03-31 11:04:14 +01001181 void Fcmpe(const VRegister& vn, double value);
1182 void Fcmpe(const VRegister& vn, const VRegister& vm) {
1183 Fcmp(vn, vm, EnableTrap);
1184 }
armvixl5289c592015-03-02 13:52:04 +00001185 void Fcsel(const VRegister& vd,
1186 const VRegister& vn,
1187 const VRegister& vm,
armvixlad96eda2013-06-14 11:42:37 +01001188 Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +00001189 VIXL_ASSERT(allow_macro_instructions_);
1190 VIXL_ASSERT((cond != al) && (cond != nv));
armvixlc68cb642014-09-25 18:49:30 +01001191 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001192 fcsel(vd, vn, vm, cond);
armvixlad96eda2013-06-14 11:42:37 +01001193 }
armvixl5289c592015-03-02 13:52:04 +00001194 void Fcvt(const VRegister& vd, const VRegister& vn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001195 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001196 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001197 fcvt(vd, vn);
armvixl578645f2013-08-15 17:21:42 +01001198 }
armvixl5289c592015-03-02 13:52:04 +00001199 void Fcvtl(const VRegister& vd, const VRegister& vn) {
1200 VIXL_ASSERT(allow_macro_instructions_);
1201 SingleEmissionCheckScope guard(this);
1202 fcvtl(vd, vn);
1203 }
1204 void Fcvtl2(const VRegister& vd, const VRegister& vn) {
1205 VIXL_ASSERT(allow_macro_instructions_);
1206 SingleEmissionCheckScope guard(this);
1207 fcvtl2(vd, vn);
1208 }
1209 void Fcvtn(const VRegister& vd, const VRegister& vn) {
1210 VIXL_ASSERT(allow_macro_instructions_);
1211 SingleEmissionCheckScope guard(this);
1212 fcvtn(vd, vn);
1213 }
1214 void Fcvtn2(const VRegister& vd, const VRegister& vn) {
1215 VIXL_ASSERT(allow_macro_instructions_);
1216 SingleEmissionCheckScope guard(this);
1217 fcvtn2(vd, vn);
1218 }
1219 void Fcvtxn(const VRegister& vd, const VRegister& vn) {
1220 VIXL_ASSERT(allow_macro_instructions_);
1221 SingleEmissionCheckScope guard(this);
1222 fcvtxn(vd, vn);
1223 }
1224 void Fcvtxn2(const VRegister& vd, const VRegister& vn) {
1225 VIXL_ASSERT(allow_macro_instructions_);
1226 SingleEmissionCheckScope guard(this);
1227 fcvtxn2(vd, vn);
1228 }
1229 void Fcvtas(const Register& rd, const VRegister& vn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001230 VIXL_ASSERT(allow_macro_instructions_);
1231 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001232 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001233 fcvtas(rd, vn);
armvixlf37fdc02014-02-05 13:22:16 +00001234 }
armvixl5289c592015-03-02 13:52:04 +00001235 void Fcvtau(const Register& rd, const VRegister& vn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001236 VIXL_ASSERT(allow_macro_instructions_);
1237 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001238 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001239 fcvtau(rd, vn);
armvixlf37fdc02014-02-05 13:22:16 +00001240 }
armvixl5289c592015-03-02 13:52:04 +00001241 void Fcvtms(const Register& rd, const VRegister& vn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001242 VIXL_ASSERT(allow_macro_instructions_);
1243 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001244 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001245 fcvtms(rd, vn);
armvixlad96eda2013-06-14 11:42:37 +01001246 }
armvixl5289c592015-03-02 13:52:04 +00001247 void Fcvtmu(const Register& rd, const VRegister& vn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001248 VIXL_ASSERT(allow_macro_instructions_);
1249 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001250 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001251 fcvtmu(rd, vn);
armvixlad96eda2013-06-14 11:42:37 +01001252 }
armvixl5289c592015-03-02 13:52:04 +00001253 void Fcvtns(const Register& rd, const VRegister& vn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001254 VIXL_ASSERT(allow_macro_instructions_);
1255 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001256 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001257 fcvtns(rd, vn);
armvixlad96eda2013-06-14 11:42:37 +01001258 }
armvixl5289c592015-03-02 13:52:04 +00001259 void Fcvtnu(const Register& rd, const VRegister& vn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001260 VIXL_ASSERT(allow_macro_instructions_);
1261 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001262 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001263 fcvtnu(rd, vn);
armvixlad96eda2013-06-14 11:42:37 +01001264 }
armvixl5289c592015-03-02 13:52:04 +00001265 void Fcvtps(const Register& rd, const VRegister& vn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001266 VIXL_ASSERT(allow_macro_instructions_);
1267 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001268 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001269 fcvtps(rd, vn);
armvixlad96eda2013-06-14 11:42:37 +01001270 }
armvixl5289c592015-03-02 13:52:04 +00001271 void Fcvtpu(const Register& rd, const VRegister& vn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001272 VIXL_ASSERT(allow_macro_instructions_);
1273 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001274 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001275 fcvtpu(rd, vn);
armvixlad96eda2013-06-14 11:42:37 +01001276 }
armvixl5289c592015-03-02 13:52:04 +00001277 void Fcvtzs(const Register& rd, const VRegister& vn, int fbits = 0) {
1278 VIXL_ASSERT(allow_macro_instructions_);
1279 VIXL_ASSERT(!rd.IsZero());
1280 SingleEmissionCheckScope guard(this);
1281 fcvtzs(rd, vn, fbits);
1282 }
1283 void Fcvtzu(const Register& rd, const VRegister& vn, int fbits = 0) {
1284 VIXL_ASSERT(allow_macro_instructions_);
1285 VIXL_ASSERT(!rd.IsZero());
1286 SingleEmissionCheckScope guard(this);
1287 fcvtzu(rd, vn, fbits);
1288 }
1289 void Fdiv(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001290 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001291 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001292 fdiv(vd, vn, vm);
armvixlad96eda2013-06-14 11:42:37 +01001293 }
armvixl5289c592015-03-02 13:52:04 +00001294 void Fmax(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001295 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001296 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001297 fmax(vd, vn, vm);
armvixlad96eda2013-06-14 11:42:37 +01001298 }
armvixl0f35e362016-05-10 13:57:58 +01001299 void Fmaxnm(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001300 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001301 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001302 fmaxnm(vd, vn, vm);
armvixlf37fdc02014-02-05 13:22:16 +00001303 }
armvixl5289c592015-03-02 13:52:04 +00001304 void Fmin(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001305 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001306 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001307 fmin(vd, vn, vm);
armvixlad96eda2013-06-14 11:42:37 +01001308 }
armvixl0f35e362016-05-10 13:57:58 +01001309 void Fminnm(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001310 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001311 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001312 fminnm(vd, vn, vm);
armvixlf37fdc02014-02-05 13:22:16 +00001313 }
armvixl5289c592015-03-02 13:52:04 +00001314 void Fmov(VRegister vd, VRegister vn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001315 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001316 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001317 // Only emit an instruction if vd and vn are different, and they are both D
armvixlad96eda2013-06-14 11:42:37 +01001318 // registers. fmov(s0, s0) is not a no-op because it clears the top word of
1319 // d0. Technically, fmov(d0, d0) is not a no-op either because it clears
armvixl5289c592015-03-02 13:52:04 +00001320 // the top of q0, but VRegister does not currently support Q registers.
1321 if (!vd.Is(vn) || !vd.Is64Bits()) {
1322 fmov(vd, vn);
armvixlad96eda2013-06-14 11:42:37 +01001323 }
1324 }
armvixl5289c592015-03-02 13:52:04 +00001325 void Fmov(VRegister vd, Register rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001326 VIXL_ASSERT(allow_macro_instructions_);
1327 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001328 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001329 fmov(vd, rn);
armvixlad96eda2013-06-14 11:42:37 +01001330 }
armvixl5289c592015-03-02 13:52:04 +00001331 void Fmov(const VRegister& vd, int index, const Register& rn) {
1332 VIXL_ASSERT(allow_macro_instructions_);
1333 SingleEmissionCheckScope guard(this);
1334 fmov(vd, index, rn);
1335 }
1336 void Fmov(const Register& rd, const VRegister& vn, int index) {
1337 VIXL_ASSERT(allow_macro_instructions_);
1338 SingleEmissionCheckScope guard(this);
1339 fmov(rd, vn, index);
1340 }
1341
armvixlb0c8ae22014-03-21 14:03:59 +00001342 // Provide explicit double and float interfaces for FP immediate moves, rather
1343 // than relying on implicit C++ casts. This allows signalling NaNs to be
armvixl5289c592015-03-02 13:52:04 +00001344 // preserved when the immediate matches the format of vd. Most systems convert
armvixlb0c8ae22014-03-21 14:03:59 +00001345 // signalling NaNs to quiet NaNs when converting between float and double.
armvixl5289c592015-03-02 13:52:04 +00001346 void Fmov(VRegister vd, double imm);
1347 void Fmov(VRegister vd, float imm);
armvixlb0c8ae22014-03-21 14:03:59 +00001348 // Provide a template to allow other types to be converted automatically.
armvixl0f35e362016-05-10 13:57:58 +01001349 template <typename T>
armvixl5289c592015-03-02 13:52:04 +00001350 void Fmov(VRegister vd, T imm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001351 VIXL_ASSERT(allow_macro_instructions_);
armvixl5289c592015-03-02 13:52:04 +00001352 Fmov(vd, static_cast<double>(imm));
armvixlad96eda2013-06-14 11:42:37 +01001353 }
armvixl5289c592015-03-02 13:52:04 +00001354 void Fmov(Register rd, VRegister vn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001355 VIXL_ASSERT(allow_macro_instructions_);
1356 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001357 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001358 fmov(rd, vn);
armvixlad96eda2013-06-14 11:42:37 +01001359 }
armvixl5289c592015-03-02 13:52:04 +00001360 void Fmul(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001361 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001362 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001363 fmul(vd, vn, vm);
armvixlad96eda2013-06-14 11:42:37 +01001364 }
armvixl0f35e362016-05-10 13:57:58 +01001365 void Fnmul(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001366 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001367 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001368 fnmul(vd, vn, vm);
armvixlf37fdc02014-02-05 13:22:16 +00001369 }
armvixl5289c592015-03-02 13:52:04 +00001370 void Fmadd(const VRegister& vd,
1371 const VRegister& vn,
1372 const VRegister& vm,
1373 const VRegister& va) {
armvixlb0c8ae22014-03-21 14:03:59 +00001374 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001375 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001376 fmadd(vd, vn, vm, va);
armvixlad96eda2013-06-14 11:42:37 +01001377 }
armvixl5289c592015-03-02 13:52:04 +00001378 void Fmsub(const VRegister& vd,
1379 const VRegister& vn,
1380 const VRegister& vm,
1381 const VRegister& va) {
armvixlb0c8ae22014-03-21 14:03:59 +00001382 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001383 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001384 fmsub(vd, vn, vm, va);
armvixlf37fdc02014-02-05 13:22:16 +00001385 }
armvixl5289c592015-03-02 13:52:04 +00001386 void Fnmadd(const VRegister& vd,
1387 const VRegister& vn,
1388 const VRegister& vm,
1389 const VRegister& va) {
armvixlb0c8ae22014-03-21 14:03:59 +00001390 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001391 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001392 fnmadd(vd, vn, vm, va);
armvixlf37fdc02014-02-05 13:22:16 +00001393 }
armvixl5289c592015-03-02 13:52:04 +00001394 void Fnmsub(const VRegister& vd,
1395 const VRegister& vn,
1396 const VRegister& vm,
1397 const VRegister& va) {
armvixlb0c8ae22014-03-21 14:03:59 +00001398 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001399 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001400 fnmsub(vd, vn, vm, va);
armvixlad96eda2013-06-14 11:42:37 +01001401 }
armvixl5289c592015-03-02 13:52:04 +00001402 void Fsub(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001403 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001404 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001405 fsub(vd, vn, vm);
armvixlad96eda2013-06-14 11:42:37 +01001406 }
1407 void Hint(SystemHint code) {
armvixlb0c8ae22014-03-21 14:03:59 +00001408 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001409 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001410 hint(code);
1411 }
1412 void Hlt(int code) {
armvixlb0c8ae22014-03-21 14:03:59 +00001413 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001414 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001415 hlt(code);
1416 }
armvixlf37fdc02014-02-05 13:22:16 +00001417 void Isb() {
armvixlb0c8ae22014-03-21 14:03:59 +00001418 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001419 SingleEmissionCheckScope guard(this);
armvixlf37fdc02014-02-05 13:22:16 +00001420 isb();
1421 }
armvixl4a102ba2014-07-14 09:02:40 +01001422 void Ldar(const Register& rt, const MemOperand& src) {
1423 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001424 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001425 ldar(rt, src);
1426 }
1427 void Ldarb(const Register& rt, const MemOperand& src) {
1428 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001429 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001430 ldarb(rt, src);
1431 }
1432 void Ldarh(const Register& rt, const MemOperand& src) {
1433 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001434 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001435 ldarh(rt, src);
1436 }
1437 void Ldaxp(const Register& rt, const Register& rt2, const MemOperand& src) {
1438 VIXL_ASSERT(allow_macro_instructions_);
1439 VIXL_ASSERT(!rt.Aliases(rt2));
armvixlc68cb642014-09-25 18:49:30 +01001440 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001441 ldaxp(rt, rt2, src);
1442 }
1443 void Ldaxr(const Register& rt, const MemOperand& src) {
1444 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001445 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001446 ldaxr(rt, src);
1447 }
1448 void Ldaxrb(const Register& rt, const MemOperand& src) {
1449 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001450 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001451 ldaxrb(rt, src);
1452 }
1453 void Ldaxrh(const Register& rt, const MemOperand& src) {
1454 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001455 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001456 ldaxrh(rt, src);
1457 }
armvixlad96eda2013-06-14 11:42:37 +01001458 void Ldnp(const CPURegister& rt,
1459 const CPURegister& rt2,
1460 const MemOperand& src) {
armvixlb0c8ae22014-03-21 14:03:59 +00001461 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001462 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001463 ldnp(rt, rt2, src);
1464 }
armvixlb0c8ae22014-03-21 14:03:59 +00001465 // Provide both double and float interfaces for FP immediate loads, rather
1466 // than relying on implicit C++ casts. This allows signalling NaNs to be
1467 // preserved when the immediate matches the format of fd. Most systems convert
1468 // signalling NaNs to quiet NaNs when converting between float and double.
armvixl5289c592015-03-02 13:52:04 +00001469 void Ldr(const VRegister& vt, double imm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001470 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001471 SingleEmissionCheckScope guard(this);
1472 RawLiteral* literal;
armvixl5289c592015-03-02 13:52:04 +00001473 if (vt.IsD()) {
armvixldb644342015-07-21 11:37:10 +01001474 literal = new Literal<double>(imm,
1475 &literal_pool_,
1476 RawLiteral::kDeletedOnPlacementByPool);
armvixlb0c8ae22014-03-21 14:03:59 +00001477 } else {
armvixldb644342015-07-21 11:37:10 +01001478 literal = new Literal<float>(static_cast<float>(imm),
1479 &literal_pool_,
1480 RawLiteral::kDeletedOnPlacementByPool);
armvixlb0c8ae22014-03-21 14:03:59 +00001481 }
armvixl5289c592015-03-02 13:52:04 +00001482 ldr(vt, literal);
armvixlb0c8ae22014-03-21 14:03:59 +00001483 }
armvixl5289c592015-03-02 13:52:04 +00001484 void Ldr(const VRegister& vt, float imm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001485 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001486 SingleEmissionCheckScope guard(this);
1487 RawLiteral* literal;
armvixl5289c592015-03-02 13:52:04 +00001488 if (vt.IsS()) {
armvixldb644342015-07-21 11:37:10 +01001489 literal = new Literal<float>(imm,
1490 &literal_pool_,
1491 RawLiteral::kDeletedOnPlacementByPool);
armvixlb0c8ae22014-03-21 14:03:59 +00001492 } else {
armvixldb644342015-07-21 11:37:10 +01001493 literal = new Literal<double>(static_cast<double>(imm),
1494 &literal_pool_,
1495 RawLiteral::kDeletedOnPlacementByPool);
armvixlb0c8ae22014-03-21 14:03:59 +00001496 }
armvixl5289c592015-03-02 13:52:04 +00001497 ldr(vt, literal);
1498 }
1499 void Ldr(const VRegister& vt, uint64_t high64, uint64_t low64) {
1500 VIXL_ASSERT(allow_macro_instructions_);
1501 VIXL_ASSERT(vt.IsQ());
1502 SingleEmissionCheckScope guard(this);
armvixl0f35e362016-05-10 13:57:58 +01001503 ldr(vt,
1504 new Literal<uint64_t>(high64,
1505 low64,
1506 &literal_pool_,
1507 RawLiteral::kDeletedOnPlacementByPool));
armvixlad96eda2013-06-14 11:42:37 +01001508 }
1509 void Ldr(const Register& rt, uint64_t imm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001510 VIXL_ASSERT(allow_macro_instructions_);
1511 VIXL_ASSERT(!rt.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001512 SingleEmissionCheckScope guard(this);
1513 RawLiteral* literal;
1514 if (rt.Is64Bits()) {
armvixldb644342015-07-21 11:37:10 +01001515 literal = new Literal<uint64_t>(imm,
1516 &literal_pool_,
1517 RawLiteral::kDeletedOnPlacementByPool);
armvixlc68cb642014-09-25 18:49:30 +01001518 } else {
1519 VIXL_ASSERT(rt.Is32Bits());
Pierre Langlois88c46b82016-06-02 18:15:32 +01001520 VIXL_ASSERT(IsUint32(imm) || IsInt32(imm));
armvixldb644342015-07-21 11:37:10 +01001521 literal = new Literal<uint32_t>(static_cast<uint32_t>(imm),
1522 &literal_pool_,
1523 RawLiteral::kDeletedOnPlacementByPool);
armvixlc68cb642014-09-25 18:49:30 +01001524 }
1525 ldr(rt, literal);
1526 }
1527 void Ldrsw(const Register& rt, uint32_t imm) {
1528 VIXL_ASSERT(allow_macro_instructions_);
1529 VIXL_ASSERT(!rt.IsZero());
1530 SingleEmissionCheckScope guard(this);
armvixldb644342015-07-21 11:37:10 +01001531 ldrsw(rt,
1532 new Literal<uint32_t>(imm,
1533 &literal_pool_,
1534 RawLiteral::kDeletedOnPlacementByPool));
1535 }
1536 void Ldr(const CPURegister& rt, RawLiteral* literal) {
1537 VIXL_ASSERT(allow_macro_instructions_);
1538 SingleEmissionCheckScope guard(this);
1539 ldr(rt, literal);
1540 }
1541 void Ldrsw(const Register& rt, RawLiteral* literal) {
1542 VIXL_ASSERT(allow_macro_instructions_);
1543 SingleEmissionCheckScope guard(this);
armvixlc68cb642014-09-25 18:49:30 +01001544 ldrsw(rt, literal);
armvixlad96eda2013-06-14 11:42:37 +01001545 }
armvixl4a102ba2014-07-14 09:02:40 +01001546 void Ldxp(const Register& rt, const Register& rt2, const MemOperand& src) {
1547 VIXL_ASSERT(allow_macro_instructions_);
1548 VIXL_ASSERT(!rt.Aliases(rt2));
armvixlc68cb642014-09-25 18:49:30 +01001549 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001550 ldxp(rt, rt2, src);
1551 }
1552 void Ldxr(const Register& rt, const MemOperand& src) {
1553 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001554 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001555 ldxr(rt, src);
1556 }
1557 void Ldxrb(const Register& rt, const MemOperand& src) {
1558 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001559 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001560 ldxrb(rt, src);
1561 }
1562 void Ldxrh(const Register& rt, const MemOperand& src) {
1563 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001564 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001565 ldxrh(rt, src);
1566 }
armvixlad96eda2013-06-14 11:42:37 +01001567 void Lsl(const Register& rd, const Register& rn, unsigned shift) {
armvixlb0c8ae22014-03-21 14:03:59 +00001568 VIXL_ASSERT(allow_macro_instructions_);
1569 VIXL_ASSERT(!rd.IsZero());
1570 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001571 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001572 lsl(rd, rn, shift);
1573 }
1574 void Lsl(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001575 VIXL_ASSERT(allow_macro_instructions_);
1576 VIXL_ASSERT(!rd.IsZero());
1577 VIXL_ASSERT(!rn.IsZero());
1578 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001579 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001580 lslv(rd, rn, rm);
1581 }
1582 void Lsr(const Register& rd, const Register& rn, unsigned shift) {
armvixlb0c8ae22014-03-21 14:03:59 +00001583 VIXL_ASSERT(allow_macro_instructions_);
1584 VIXL_ASSERT(!rd.IsZero());
1585 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001586 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001587 lsr(rd, rn, shift);
1588 }
1589 void Lsr(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001590 VIXL_ASSERT(allow_macro_instructions_);
1591 VIXL_ASSERT(!rd.IsZero());
1592 VIXL_ASSERT(!rn.IsZero());
1593 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001594 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001595 lsrv(rd, rn, rm);
1596 }
1597 void Madd(const Register& rd,
1598 const Register& rn,
1599 const Register& rm,
1600 const Register& ra) {
armvixlb0c8ae22014-03-21 14:03:59 +00001601 VIXL_ASSERT(allow_macro_instructions_);
1602 VIXL_ASSERT(!rd.IsZero());
1603 VIXL_ASSERT(!rn.IsZero());
1604 VIXL_ASSERT(!rm.IsZero());
1605 VIXL_ASSERT(!ra.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001606 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001607 madd(rd, rn, rm, ra);
1608 }
1609 void Mneg(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001610 VIXL_ASSERT(allow_macro_instructions_);
1611 VIXL_ASSERT(!rd.IsZero());
1612 VIXL_ASSERT(!rn.IsZero());
1613 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001614 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001615 mneg(rd, rn, rm);
1616 }
1617 void Mov(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001618 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001619 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001620 mov(rd, rn);
1621 }
armvixlf37fdc02014-02-05 13:22:16 +00001622 void Movk(const Register& rd, uint64_t imm, int shift = -1) {
armvixlb0c8ae22014-03-21 14:03:59 +00001623 VIXL_ASSERT(allow_macro_instructions_);
1624 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001625 SingleEmissionCheckScope guard(this);
armvixlf37fdc02014-02-05 13:22:16 +00001626 movk(rd, imm, shift);
1627 }
armvixlad96eda2013-06-14 11:42:37 +01001628 void Mrs(const Register& rt, SystemRegister sysreg) {
armvixlb0c8ae22014-03-21 14:03:59 +00001629 VIXL_ASSERT(allow_macro_instructions_);
1630 VIXL_ASSERT(!rt.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001631 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001632 mrs(rt, sysreg);
1633 }
1634 void Msr(SystemRegister sysreg, const Register& rt) {
armvixlb0c8ae22014-03-21 14:03:59 +00001635 VIXL_ASSERT(allow_macro_instructions_);
1636 VIXL_ASSERT(!rt.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001637 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001638 msr(sysreg, rt);
1639 }
armvixl5289c592015-03-02 13:52:04 +00001640 void Sys(int op1, int crn, int crm, int op2, const Register& rt = xzr) {
1641 VIXL_ASSERT(allow_macro_instructions_);
1642 SingleEmissionCheckScope guard(this);
1643 sys(op1, crn, crm, op2, rt);
1644 }
1645 void Dc(DataCacheOp op, const Register& rt) {
1646 VIXL_ASSERT(allow_macro_instructions_);
1647 SingleEmissionCheckScope guard(this);
1648 dc(op, rt);
1649 }
1650 void Ic(InstructionCacheOp op, const Register& rt) {
1651 VIXL_ASSERT(allow_macro_instructions_);
1652 SingleEmissionCheckScope guard(this);
1653 ic(op, rt);
1654 }
armvixlad96eda2013-06-14 11:42:37 +01001655 void Msub(const Register& rd,
1656 const Register& rn,
1657 const Register& rm,
1658 const Register& ra) {
armvixlb0c8ae22014-03-21 14:03:59 +00001659 VIXL_ASSERT(allow_macro_instructions_);
1660 VIXL_ASSERT(!rd.IsZero());
1661 VIXL_ASSERT(!rn.IsZero());
1662 VIXL_ASSERT(!rm.IsZero());
1663 VIXL_ASSERT(!ra.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001664 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001665 msub(rd, rn, rm, ra);
1666 }
1667 void Mul(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001668 VIXL_ASSERT(allow_macro_instructions_);
1669 VIXL_ASSERT(!rd.IsZero());
1670 VIXL_ASSERT(!rn.IsZero());
1671 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001672 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001673 mul(rd, rn, rm);
1674 }
1675 void Nop() {
armvixlb0c8ae22014-03-21 14:03:59 +00001676 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001677 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001678 nop();
1679 }
1680 void Rbit(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001681 VIXL_ASSERT(allow_macro_instructions_);
1682 VIXL_ASSERT(!rd.IsZero());
1683 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001684 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001685 rbit(rd, rn);
1686 }
1687 void Ret(const Register& xn = lr) {
armvixlb0c8ae22014-03-21 14:03:59 +00001688 VIXL_ASSERT(allow_macro_instructions_);
1689 VIXL_ASSERT(!xn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001690 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001691 ret(xn);
1692 }
1693 void Rev(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001694 VIXL_ASSERT(allow_macro_instructions_);
1695 VIXL_ASSERT(!rd.IsZero());
1696 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001697 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001698 rev(rd, rn);
1699 }
1700 void Rev16(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001701 VIXL_ASSERT(allow_macro_instructions_);
1702 VIXL_ASSERT(!rd.IsZero());
1703 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001704 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001705 rev16(rd, rn);
1706 }
1707 void Rev32(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001708 VIXL_ASSERT(allow_macro_instructions_);
1709 VIXL_ASSERT(!rd.IsZero());
1710 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001711 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001712 rev32(rd, rn);
1713 }
1714 void Ror(const Register& rd, const Register& rs, unsigned shift) {
armvixlb0c8ae22014-03-21 14:03:59 +00001715 VIXL_ASSERT(allow_macro_instructions_);
1716 VIXL_ASSERT(!rd.IsZero());
1717 VIXL_ASSERT(!rs.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001718 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001719 ror(rd, rs, shift);
1720 }
1721 void Ror(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001722 VIXL_ASSERT(allow_macro_instructions_);
1723 VIXL_ASSERT(!rd.IsZero());
1724 VIXL_ASSERT(!rn.IsZero());
1725 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001726 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001727 rorv(rd, rn, rm);
1728 }
1729 void Sbfiz(const Register& rd,
1730 const Register& rn,
1731 unsigned lsb,
1732 unsigned width) {
armvixlb0c8ae22014-03-21 14:03:59 +00001733 VIXL_ASSERT(allow_macro_instructions_);
1734 VIXL_ASSERT(!rd.IsZero());
1735 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001736 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001737 sbfiz(rd, rn, lsb, width);
1738 }
armvixl5289c592015-03-02 13:52:04 +00001739 void Sbfm(const Register& rd,
1740 const Register& rn,
1741 unsigned immr,
1742 unsigned imms) {
1743 VIXL_ASSERT(allow_macro_instructions_);
1744 VIXL_ASSERT(!rd.IsZero());
1745 VIXL_ASSERT(!rn.IsZero());
1746 SingleEmissionCheckScope guard(this);
1747 sbfm(rd, rn, immr, imms);
1748 }
armvixlad96eda2013-06-14 11:42:37 +01001749 void Sbfx(const Register& rd,
1750 const Register& rn,
1751 unsigned lsb,
1752 unsigned width) {
armvixlb0c8ae22014-03-21 14:03:59 +00001753 VIXL_ASSERT(allow_macro_instructions_);
1754 VIXL_ASSERT(!rd.IsZero());
1755 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001756 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001757 sbfx(rd, rn, lsb, width);
1758 }
armvixl5289c592015-03-02 13:52:04 +00001759 void Scvtf(const VRegister& vd, const Register& rn, int fbits = 0) {
armvixlb0c8ae22014-03-21 14:03:59 +00001760 VIXL_ASSERT(allow_macro_instructions_);
1761 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001762 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001763 scvtf(vd, rn, fbits);
armvixlad96eda2013-06-14 11:42:37 +01001764 }
1765 void Sdiv(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001766 VIXL_ASSERT(allow_macro_instructions_);
1767 VIXL_ASSERT(!rd.IsZero());
1768 VIXL_ASSERT(!rn.IsZero());
1769 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001770 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001771 sdiv(rd, rn, rm);
1772 }
1773 void Smaddl(const Register& rd,
1774 const Register& rn,
1775 const Register& rm,
1776 const Register& ra) {
armvixlb0c8ae22014-03-21 14:03:59 +00001777 VIXL_ASSERT(allow_macro_instructions_);
1778 VIXL_ASSERT(!rd.IsZero());
1779 VIXL_ASSERT(!rn.IsZero());
1780 VIXL_ASSERT(!rm.IsZero());
1781 VIXL_ASSERT(!ra.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001782 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001783 smaddl(rd, rn, rm, ra);
1784 }
1785 void Smsubl(const Register& rd,
1786 const Register& rn,
1787 const Register& rm,
1788 const Register& ra) {
armvixlb0c8ae22014-03-21 14:03:59 +00001789 VIXL_ASSERT(allow_macro_instructions_);
1790 VIXL_ASSERT(!rd.IsZero());
1791 VIXL_ASSERT(!rn.IsZero());
1792 VIXL_ASSERT(!rm.IsZero());
1793 VIXL_ASSERT(!ra.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001794 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001795 smsubl(rd, rn, rm, ra);
1796 }
1797 void Smull(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001798 VIXL_ASSERT(allow_macro_instructions_);
1799 VIXL_ASSERT(!rd.IsZero());
1800 VIXL_ASSERT(!rn.IsZero());
1801 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001802 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001803 smull(rd, rn, rm);
1804 }
1805 void Smulh(const Register& xd, const Register& xn, const Register& xm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001806 VIXL_ASSERT(allow_macro_instructions_);
1807 VIXL_ASSERT(!xd.IsZero());
1808 VIXL_ASSERT(!xn.IsZero());
1809 VIXL_ASSERT(!xm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001810 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001811 smulh(xd, xn, xm);
1812 }
armvixl4a102ba2014-07-14 09:02:40 +01001813 void Stlr(const Register& rt, const MemOperand& dst) {
1814 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001815 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001816 stlr(rt, dst);
1817 }
1818 void Stlrb(const Register& rt, const MemOperand& dst) {
1819 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001820 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001821 stlrb(rt, dst);
1822 }
1823 void Stlrh(const Register& rt, const MemOperand& dst) {
1824 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001825 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001826 stlrh(rt, dst);
1827 }
1828 void Stlxp(const Register& rs,
1829 const Register& rt,
1830 const Register& rt2,
1831 const MemOperand& dst) {
1832 VIXL_ASSERT(allow_macro_instructions_);
Pierre Langlois88c46b82016-06-02 18:15:32 +01001833 VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister()));
armvixl4a102ba2014-07-14 09:02:40 +01001834 VIXL_ASSERT(!rs.Aliases(rt));
1835 VIXL_ASSERT(!rs.Aliases(rt2));
armvixlc68cb642014-09-25 18:49:30 +01001836 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001837 stlxp(rs, rt, rt2, dst);
1838 }
1839 void Stlxr(const Register& rs, const Register& rt, const MemOperand& dst) {
1840 VIXL_ASSERT(allow_macro_instructions_);
Pierre Langlois88c46b82016-06-02 18:15:32 +01001841 VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister()));
armvixl4a102ba2014-07-14 09:02:40 +01001842 VIXL_ASSERT(!rs.Aliases(rt));
armvixlc68cb642014-09-25 18:49:30 +01001843 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001844 stlxr(rs, rt, dst);
1845 }
1846 void Stlxrb(const Register& rs, const Register& rt, const MemOperand& dst) {
1847 VIXL_ASSERT(allow_macro_instructions_);
Pierre Langlois88c46b82016-06-02 18:15:32 +01001848 VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister()));
armvixl4a102ba2014-07-14 09:02:40 +01001849 VIXL_ASSERT(!rs.Aliases(rt));
armvixlc68cb642014-09-25 18:49:30 +01001850 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001851 stlxrb(rs, rt, dst);
1852 }
1853 void Stlxrh(const Register& rs, const Register& rt, const MemOperand& dst) {
1854 VIXL_ASSERT(allow_macro_instructions_);
Pierre Langlois88c46b82016-06-02 18:15:32 +01001855 VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister()));
armvixl4a102ba2014-07-14 09:02:40 +01001856 VIXL_ASSERT(!rs.Aliases(rt));
armvixlc68cb642014-09-25 18:49:30 +01001857 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001858 stlxrh(rs, rt, dst);
1859 }
armvixlad96eda2013-06-14 11:42:37 +01001860 void Stnp(const CPURegister& rt,
1861 const CPURegister& rt2,
1862 const MemOperand& dst) {
armvixlb0c8ae22014-03-21 14:03:59 +00001863 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001864 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001865 stnp(rt, rt2, dst);
1866 }
armvixl4a102ba2014-07-14 09:02:40 +01001867 void Stxp(const Register& rs,
1868 const Register& rt,
1869 const Register& rt2,
1870 const MemOperand& dst) {
1871 VIXL_ASSERT(allow_macro_instructions_);
Pierre Langlois88c46b82016-06-02 18:15:32 +01001872 VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister()));
armvixl4a102ba2014-07-14 09:02:40 +01001873 VIXL_ASSERT(!rs.Aliases(rt));
1874 VIXL_ASSERT(!rs.Aliases(rt2));
armvixlc68cb642014-09-25 18:49:30 +01001875 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001876 stxp(rs, rt, rt2, dst);
1877 }
1878 void Stxr(const Register& rs, const Register& rt, const MemOperand& dst) {
1879 VIXL_ASSERT(allow_macro_instructions_);
Pierre Langlois88c46b82016-06-02 18:15:32 +01001880 VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister()));
armvixl4a102ba2014-07-14 09:02:40 +01001881 VIXL_ASSERT(!rs.Aliases(rt));
armvixlc68cb642014-09-25 18:49:30 +01001882 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001883 stxr(rs, rt, dst);
1884 }
1885 void Stxrb(const Register& rs, const Register& rt, const MemOperand& dst) {
1886 VIXL_ASSERT(allow_macro_instructions_);
Pierre Langlois88c46b82016-06-02 18:15:32 +01001887 VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister()));
armvixl4a102ba2014-07-14 09:02:40 +01001888 VIXL_ASSERT(!rs.Aliases(rt));
armvixlc68cb642014-09-25 18:49:30 +01001889 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001890 stxrb(rs, rt, dst);
1891 }
1892 void Stxrh(const Register& rs, const Register& rt, const MemOperand& dst) {
1893 VIXL_ASSERT(allow_macro_instructions_);
Pierre Langlois88c46b82016-06-02 18:15:32 +01001894 VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister()));
armvixl4a102ba2014-07-14 09:02:40 +01001895 VIXL_ASSERT(!rs.Aliases(rt));
armvixlc68cb642014-09-25 18:49:30 +01001896 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001897 stxrh(rs, rt, dst);
1898 }
armvixl5289c592015-03-02 13:52:04 +00001899 void Svc(int code) {
1900 VIXL_ASSERT(allow_macro_instructions_);
1901 SingleEmissionCheckScope guard(this);
1902 svc(code);
1903 }
armvixlad96eda2013-06-14 11:42:37 +01001904 void Sxtb(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001905 VIXL_ASSERT(allow_macro_instructions_);
1906 VIXL_ASSERT(!rd.IsZero());
1907 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001908 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001909 sxtb(rd, rn);
1910 }
1911 void Sxth(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001912 VIXL_ASSERT(allow_macro_instructions_);
1913 VIXL_ASSERT(!rd.IsZero());
1914 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001915 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001916 sxth(rd, rn);
1917 }
1918 void Sxtw(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001919 VIXL_ASSERT(allow_macro_instructions_);
1920 VIXL_ASSERT(!rd.IsZero());
1921 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001922 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001923 sxtw(rd, rn);
1924 }
armvixl0f35e362016-05-10 13:57:58 +01001925 void Tbl(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001926 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001927 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001928 tbl(vd, vn, vm);
armvixlad96eda2013-06-14 11:42:37 +01001929 }
armvixl5289c592015-03-02 13:52:04 +00001930 void Tbl(const VRegister& vd,
1931 const VRegister& vn,
1932 const VRegister& vn2,
1933 const VRegister& vm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001934 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001935 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00001936 tbl(vd, vn, vn2, vm);
armvixlad96eda2013-06-14 11:42:37 +01001937 }
armvixl5289c592015-03-02 13:52:04 +00001938 void Tbl(const VRegister& vd,
1939 const VRegister& vn,
1940 const VRegister& vn2,
1941 const VRegister& vn3,
1942 const VRegister& vm) {
1943 VIXL_ASSERT(allow_macro_instructions_);
1944 SingleEmissionCheckScope guard(this);
1945 tbl(vd, vn, vn2, vn3, vm);
1946 }
1947 void Tbl(const VRegister& vd,
1948 const VRegister& vn,
1949 const VRegister& vn2,
1950 const VRegister& vn3,
1951 const VRegister& vn4,
1952 const VRegister& vm) {
1953 VIXL_ASSERT(allow_macro_instructions_);
1954 SingleEmissionCheckScope guard(this);
1955 tbl(vd, vn, vn2, vn3, vn4, vm);
1956 }
armvixl0f35e362016-05-10 13:57:58 +01001957 void Tbx(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
armvixl5289c592015-03-02 13:52:04 +00001958 VIXL_ASSERT(allow_macro_instructions_);
1959 SingleEmissionCheckScope guard(this);
1960 tbx(vd, vn, vm);
1961 }
1962 void Tbx(const VRegister& vd,
1963 const VRegister& vn,
1964 const VRegister& vn2,
1965 const VRegister& vm) {
1966 VIXL_ASSERT(allow_macro_instructions_);
1967 SingleEmissionCheckScope guard(this);
1968 tbx(vd, vn, vn2, vm);
1969 }
1970 void Tbx(const VRegister& vd,
1971 const VRegister& vn,
1972 const VRegister& vn2,
1973 const VRegister& vn3,
1974 const VRegister& vm) {
1975 VIXL_ASSERT(allow_macro_instructions_);
1976 SingleEmissionCheckScope guard(this);
1977 tbx(vd, vn, vn2, vn3, vm);
1978 }
1979 void Tbx(const VRegister& vd,
1980 const VRegister& vn,
1981 const VRegister& vn2,
1982 const VRegister& vn3,
1983 const VRegister& vn4,
1984 const VRegister& vm) {
1985 VIXL_ASSERT(allow_macro_instructions_);
1986 SingleEmissionCheckScope guard(this);
1987 tbx(vd, vn, vn2, vn3, vn4, vm);
1988 }
1989 void Tbnz(const Register& rt, unsigned bit_pos, Label* label);
1990 void Tbz(const Register& rt, unsigned bit_pos, Label* label);
armvixlad96eda2013-06-14 11:42:37 +01001991 void Ubfiz(const Register& rd,
1992 const Register& rn,
1993 unsigned lsb,
1994 unsigned width) {
armvixlb0c8ae22014-03-21 14:03:59 +00001995 VIXL_ASSERT(allow_macro_instructions_);
1996 VIXL_ASSERT(!rd.IsZero());
1997 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001998 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001999 ubfiz(rd, rn, lsb, width);
2000 }
armvixl5289c592015-03-02 13:52:04 +00002001 void Ubfm(const Register& rd,
2002 const Register& rn,
2003 unsigned immr,
2004 unsigned imms) {
2005 VIXL_ASSERT(allow_macro_instructions_);
2006 VIXL_ASSERT(!rd.IsZero());
2007 VIXL_ASSERT(!rn.IsZero());
2008 SingleEmissionCheckScope guard(this);
2009 ubfm(rd, rn, immr, imms);
2010 }
armvixlad96eda2013-06-14 11:42:37 +01002011 void Ubfx(const Register& rd,
2012 const Register& rn,
2013 unsigned lsb,
2014 unsigned width) {
armvixlb0c8ae22014-03-21 14:03:59 +00002015 VIXL_ASSERT(allow_macro_instructions_);
2016 VIXL_ASSERT(!rd.IsZero());
2017 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01002018 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01002019 ubfx(rd, rn, lsb, width);
2020 }
armvixl5289c592015-03-02 13:52:04 +00002021 void Ucvtf(const VRegister& vd, const Register& rn, int fbits = 0) {
armvixlb0c8ae22014-03-21 14:03:59 +00002022 VIXL_ASSERT(allow_macro_instructions_);
2023 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01002024 SingleEmissionCheckScope guard(this);
armvixl5289c592015-03-02 13:52:04 +00002025 ucvtf(vd, rn, fbits);
armvixlad96eda2013-06-14 11:42:37 +01002026 }
2027 void Udiv(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +00002028 VIXL_ASSERT(allow_macro_instructions_);
2029 VIXL_ASSERT(!rd.IsZero());
2030 VIXL_ASSERT(!rn.IsZero());
2031 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01002032 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01002033 udiv(rd, rn, rm);
2034 }
2035 void Umaddl(const Register& rd,
2036 const Register& rn,
2037 const Register& rm,
2038 const Register& ra) {
armvixlb0c8ae22014-03-21 14:03:59 +00002039 VIXL_ASSERT(allow_macro_instructions_);
2040 VIXL_ASSERT(!rd.IsZero());
2041 VIXL_ASSERT(!rn.IsZero());
2042 VIXL_ASSERT(!rm.IsZero());
2043 VIXL_ASSERT(!ra.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01002044 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01002045 umaddl(rd, rn, rm, ra);
2046 }
armvixl0f35e362016-05-10 13:57:58 +01002047 void Umull(const Register& rd, const Register& rn, const Register& rm) {
armvixl5289c592015-03-02 13:52:04 +00002048 VIXL_ASSERT(allow_macro_instructions_);
2049 VIXL_ASSERT(!rd.IsZero());
2050 VIXL_ASSERT(!rn.IsZero());
2051 VIXL_ASSERT(!rm.IsZero());
2052 SingleEmissionCheckScope guard(this);
2053 umull(rd, rn, rm);
2054 }
armvixl6e2c8272015-03-31 11:04:14 +01002055 void Umulh(const Register& xd, const Register& xn, const Register& xm) {
2056 VIXL_ASSERT(allow_macro_instructions_);
2057 VIXL_ASSERT(!xd.IsZero());
2058 VIXL_ASSERT(!xn.IsZero());
2059 VIXL_ASSERT(!xm.IsZero());
2060 SingleEmissionCheckScope guard(this);
2061 umulh(xd, xn, xm);
2062 }
armvixlad96eda2013-06-14 11:42:37 +01002063 void Umsubl(const Register& rd,
2064 const Register& rn,
2065 const Register& rm,
2066 const Register& ra) {
armvixlb0c8ae22014-03-21 14:03:59 +00002067 VIXL_ASSERT(allow_macro_instructions_);
2068 VIXL_ASSERT(!rd.IsZero());
2069 VIXL_ASSERT(!rn.IsZero());
2070 VIXL_ASSERT(!rm.IsZero());
2071 VIXL_ASSERT(!ra.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01002072 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01002073 umsubl(rd, rn, rm, ra);
2074 }
2075 void Unreachable() {
armvixlb0c8ae22014-03-21 14:03:59 +00002076 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01002077 SingleEmissionCheckScope guard(this);
armvixl684cd2a2015-10-23 13:38:33 +01002078 if (allow_simulator_instructions_) {
2079 hlt(kUnreachableOpcode);
2080 } else {
2081 // Branch to 0 to generate a segfault.
2082 // lr - kInstructionSize is the address of the offending instruction.
2083 blr(xzr);
2084 }
armvixlad96eda2013-06-14 11:42:37 +01002085 }
2086 void Uxtb(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00002087 VIXL_ASSERT(allow_macro_instructions_);
2088 VIXL_ASSERT(!rd.IsZero());
2089 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01002090 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01002091 uxtb(rd, rn);
2092 }
2093 void Uxth(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00002094 VIXL_ASSERT(allow_macro_instructions_);
2095 VIXL_ASSERT(!rd.IsZero());
2096 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01002097 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01002098 uxth(rd, rn);
2099 }
2100 void Uxtw(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00002101 VIXL_ASSERT(allow_macro_instructions_);
2102 VIXL_ASSERT(!rd.IsZero());
2103 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01002104 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01002105 uxtw(rd, rn);
2106 }
2107
armvixl0f35e362016-05-10 13:57:58 +01002108// NEON 3 vector register instructions.
2109#define NEON_3VREG_MACRO_LIST(V) \
2110 V(add, Add) \
2111 V(addhn, Addhn) \
2112 V(addhn2, Addhn2) \
2113 V(addp, Addp) \
2114 V(and_, And) \
2115 V(bic, Bic) \
2116 V(bif, Bif) \
2117 V(bit, Bit) \
2118 V(bsl, Bsl) \
2119 V(cmeq, Cmeq) \
2120 V(cmge, Cmge) \
2121 V(cmgt, Cmgt) \
2122 V(cmhi, Cmhi) \
2123 V(cmhs, Cmhs) \
2124 V(cmtst, Cmtst) \
2125 V(eor, Eor) \
2126 V(fabd, Fabd) \
2127 V(facge, Facge) \
2128 V(facgt, Facgt) \
2129 V(faddp, Faddp) \
2130 V(fcmeq, Fcmeq) \
2131 V(fcmge, Fcmge) \
2132 V(fcmgt, Fcmgt) \
2133 V(fmaxnmp, Fmaxnmp) \
2134 V(fmaxp, Fmaxp) \
2135 V(fminnmp, Fminnmp) \
2136 V(fminp, Fminp) \
2137 V(fmla, Fmla) \
2138 V(fmls, Fmls) \
2139 V(fmulx, Fmulx) \
2140 V(frecps, Frecps) \
2141 V(frsqrts, Frsqrts) \
2142 V(mla, Mla) \
2143 V(mls, Mls) \
2144 V(mul, Mul) \
2145 V(orn, Orn) \
2146 V(orr, Orr) \
2147 V(pmul, Pmul) \
2148 V(pmull, Pmull) \
2149 V(pmull2, Pmull2) \
2150 V(raddhn, Raddhn) \
2151 V(raddhn2, Raddhn2) \
2152 V(rsubhn, Rsubhn) \
2153 V(rsubhn2, Rsubhn2) \
2154 V(saba, Saba) \
2155 V(sabal, Sabal) \
2156 V(sabal2, Sabal2) \
2157 V(sabd, Sabd) \
2158 V(sabdl, Sabdl) \
2159 V(sabdl2, Sabdl2) \
2160 V(saddl, Saddl) \
2161 V(saddl2, Saddl2) \
2162 V(saddw, Saddw) \
2163 V(saddw2, Saddw2) \
2164 V(shadd, Shadd) \
2165 V(shsub, Shsub) \
2166 V(smax, Smax) \
2167 V(smaxp, Smaxp) \
2168 V(smin, Smin) \
2169 V(sminp, Sminp) \
2170 V(smlal, Smlal) \
2171 V(smlal2, Smlal2) \
2172 V(smlsl, Smlsl) \
2173 V(smlsl2, Smlsl2) \
2174 V(smull, Smull) \
2175 V(smull2, Smull2) \
2176 V(sqadd, Sqadd) \
2177 V(sqdmlal, Sqdmlal) \
2178 V(sqdmlal2, Sqdmlal2) \
2179 V(sqdmlsl, Sqdmlsl) \
2180 V(sqdmlsl2, Sqdmlsl2) \
2181 V(sqdmulh, Sqdmulh) \
2182 V(sqdmull, Sqdmull) \
2183 V(sqdmull2, Sqdmull2) \
2184 V(sqrdmulh, Sqrdmulh) \
2185 V(sqrshl, Sqrshl) \
2186 V(sqshl, Sqshl) \
2187 V(sqsub, Sqsub) \
2188 V(srhadd, Srhadd) \
2189 V(srshl, Srshl) \
2190 V(sshl, Sshl) \
2191 V(ssubl, Ssubl) \
2192 V(ssubl2, Ssubl2) \
2193 V(ssubw, Ssubw) \
2194 V(ssubw2, Ssubw2) \
2195 V(sub, Sub) \
2196 V(subhn, Subhn) \
2197 V(subhn2, Subhn2) \
2198 V(trn1, Trn1) \
2199 V(trn2, Trn2) \
2200 V(uaba, Uaba) \
2201 V(uabal, Uabal) \
2202 V(uabal2, Uabal2) \
2203 V(uabd, Uabd) \
2204 V(uabdl, Uabdl) \
2205 V(uabdl2, Uabdl2) \
2206 V(uaddl, Uaddl) \
2207 V(uaddl2, Uaddl2) \
2208 V(uaddw, Uaddw) \
2209 V(uaddw2, Uaddw2) \
2210 V(uhadd, Uhadd) \
2211 V(uhsub, Uhsub) \
2212 V(umax, Umax) \
2213 V(umaxp, Umaxp) \
2214 V(umin, Umin) \
2215 V(uminp, Uminp) \
2216 V(umlal, Umlal) \
2217 V(umlal2, Umlal2) \
2218 V(umlsl, Umlsl) \
2219 V(umlsl2, Umlsl2) \
2220 V(umull, Umull) \
2221 V(umull2, Umull2) \
2222 V(uqadd, Uqadd) \
2223 V(uqrshl, Uqrshl) \
2224 V(uqshl, Uqshl) \
2225 V(uqsub, Uqsub) \
2226 V(urhadd, Urhadd) \
2227 V(urshl, Urshl) \
2228 V(ushl, Ushl) \
2229 V(usubl, Usubl) \
2230 V(usubl2, Usubl2) \
2231 V(usubw, Usubw) \
2232 V(usubw2, Usubw2) \
2233 V(uzp1, Uzp1) \
2234 V(uzp2, Uzp2) \
2235 V(zip1, Zip1) \
2236 V(zip2, Zip2)
armvixl5289c592015-03-02 13:52:04 +00002237
armvixl0f35e362016-05-10 13:57:58 +01002238#define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \
2239 void MASM(const VRegister& vd, const VRegister& vn, const VRegister& vm) { \
2240 VIXL_ASSERT(allow_macro_instructions_); \
2241 SingleEmissionCheckScope guard(this); \
2242 ASM(vd, vn, vm); \
armvixl5289c592015-03-02 13:52:04 +00002243 }
2244 NEON_3VREG_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)
armvixl0f35e362016-05-10 13:57:58 +01002245#undef DEFINE_MACRO_ASM_FUNC
armvixl5289c592015-03-02 13:52:04 +00002246
armvixl0f35e362016-05-10 13:57:58 +01002247// NEON 2 vector register instructions.
2248#define NEON_2VREG_MACRO_LIST(V) \
2249 V(abs, Abs) \
2250 V(addp, Addp) \
2251 V(addv, Addv) \
2252 V(cls, Cls) \
2253 V(clz, Clz) \
2254 V(cnt, Cnt) \
2255 V(fabs, Fabs) \
2256 V(faddp, Faddp) \
2257 V(fcvtas, Fcvtas) \
2258 V(fcvtau, Fcvtau) \
2259 V(fcvtms, Fcvtms) \
2260 V(fcvtmu, Fcvtmu) \
2261 V(fcvtns, Fcvtns) \
2262 V(fcvtnu, Fcvtnu) \
2263 V(fcvtps, Fcvtps) \
2264 V(fcvtpu, Fcvtpu) \
2265 V(fmaxnmp, Fmaxnmp) \
2266 V(fmaxnmv, Fmaxnmv) \
2267 V(fmaxp, Fmaxp) \
2268 V(fmaxv, Fmaxv) \
2269 V(fminnmp, Fminnmp) \
2270 V(fminnmv, Fminnmv) \
2271 V(fminp, Fminp) \
2272 V(fminv, Fminv) \
2273 V(fneg, Fneg) \
2274 V(frecpe, Frecpe) \
2275 V(frecpx, Frecpx) \
2276 V(frinta, Frinta) \
2277 V(frinti, Frinti) \
2278 V(frintm, Frintm) \
2279 V(frintn, Frintn) \
2280 V(frintp, Frintp) \
2281 V(frintx, Frintx) \
2282 V(frintz, Frintz) \
2283 V(frsqrte, Frsqrte) \
2284 V(fsqrt, Fsqrt) \
2285 V(mov, Mov) \
2286 V(mvn, Mvn) \
2287 V(neg, Neg) \
2288 V(not_, Not) \
2289 V(rbit, Rbit) \
2290 V(rev16, Rev16) \
2291 V(rev32, Rev32) \
2292 V(rev64, Rev64) \
2293 V(sadalp, Sadalp) \
2294 V(saddlp, Saddlp) \
2295 V(saddlv, Saddlv) \
2296 V(smaxv, Smaxv) \
2297 V(sminv, Sminv) \
2298 V(sqabs, Sqabs) \
2299 V(sqneg, Sqneg) \
2300 V(sqxtn, Sqxtn) \
2301 V(sqxtn2, Sqxtn2) \
2302 V(sqxtun, Sqxtun) \
2303 V(sqxtun2, Sqxtun2) \
2304 V(suqadd, Suqadd) \
2305 V(sxtl, Sxtl) \
2306 V(sxtl2, Sxtl2) \
2307 V(uadalp, Uadalp) \
2308 V(uaddlp, Uaddlp) \
2309 V(uaddlv, Uaddlv) \
2310 V(umaxv, Umaxv) \
2311 V(uminv, Uminv) \
2312 V(uqxtn, Uqxtn) \
2313 V(uqxtn2, Uqxtn2) \
2314 V(urecpe, Urecpe) \
2315 V(ursqrte, Ursqrte) \
2316 V(usqadd, Usqadd) \
2317 V(uxtl, Uxtl) \
2318 V(uxtl2, Uxtl2) \
2319 V(xtn, Xtn) \
2320 V(xtn2, Xtn2)
armvixl5289c592015-03-02 13:52:04 +00002321
armvixl0f35e362016-05-10 13:57:58 +01002322#define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \
2323 void MASM(const VRegister& vd, const VRegister& vn) { \
2324 VIXL_ASSERT(allow_macro_instructions_); \
2325 SingleEmissionCheckScope guard(this); \
2326 ASM(vd, vn); \
armvixl5289c592015-03-02 13:52:04 +00002327 }
2328 NEON_2VREG_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)
armvixl0f35e362016-05-10 13:57:58 +01002329#undef DEFINE_MACRO_ASM_FUNC
armvixl5289c592015-03-02 13:52:04 +00002330
armvixl0f35e362016-05-10 13:57:58 +01002331// NEON 2 vector register with immediate instructions.
2332#define NEON_2VREG_FPIMM_MACRO_LIST(V) \
2333 V(fcmeq, Fcmeq) \
2334 V(fcmge, Fcmge) \
2335 V(fcmgt, Fcmgt) \
2336 V(fcmle, Fcmle) \
2337 V(fcmlt, Fcmlt)
armvixl5289c592015-03-02 13:52:04 +00002338
armvixl0f35e362016-05-10 13:57:58 +01002339#define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \
2340 void MASM(const VRegister& vd, const VRegister& vn, double imm) { \
2341 VIXL_ASSERT(allow_macro_instructions_); \
2342 SingleEmissionCheckScope guard(this); \
2343 ASM(vd, vn, imm); \
armvixl5289c592015-03-02 13:52:04 +00002344 }
2345 NEON_2VREG_FPIMM_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)
armvixl0f35e362016-05-10 13:57:58 +01002346#undef DEFINE_MACRO_ASM_FUNC
armvixl5289c592015-03-02 13:52:04 +00002347
armvixl0f35e362016-05-10 13:57:58 +01002348// NEON by element instructions.
2349#define NEON_BYELEMENT_MACRO_LIST(V) \
2350 V(fmul, Fmul) \
2351 V(fmla, Fmla) \
2352 V(fmls, Fmls) \
2353 V(fmulx, Fmulx) \
2354 V(mul, Mul) \
2355 V(mla, Mla) \
2356 V(mls, Mls) \
2357 V(sqdmulh, Sqdmulh) \
2358 V(sqrdmulh, Sqrdmulh) \
2359 V(sqdmull, Sqdmull) \
2360 V(sqdmull2, Sqdmull2) \
2361 V(sqdmlal, Sqdmlal) \
2362 V(sqdmlal2, Sqdmlal2) \
2363 V(sqdmlsl, Sqdmlsl) \
2364 V(sqdmlsl2, Sqdmlsl2) \
2365 V(smull, Smull) \
2366 V(smull2, Smull2) \
2367 V(smlal, Smlal) \
2368 V(smlal2, Smlal2) \
2369 V(smlsl, Smlsl) \
2370 V(smlsl2, Smlsl2) \
2371 V(umull, Umull) \
2372 V(umull2, Umull2) \
2373 V(umlal, Umlal) \
2374 V(umlal2, Umlal2) \
2375 V(umlsl, Umlsl) \
2376 V(umlsl2, Umlsl2)
armvixl5289c592015-03-02 13:52:04 +00002377
armvixl0f35e362016-05-10 13:57:58 +01002378#define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \
2379 void MASM(const VRegister& vd, \
2380 const VRegister& vn, \
2381 const VRegister& vm, \
2382 int vm_index) { \
2383 VIXL_ASSERT(allow_macro_instructions_); \
2384 SingleEmissionCheckScope guard(this); \
2385 ASM(vd, vn, vm, vm_index); \
armvixl5289c592015-03-02 13:52:04 +00002386 }
2387 NEON_BYELEMENT_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)
armvixl0f35e362016-05-10 13:57:58 +01002388#undef DEFINE_MACRO_ASM_FUNC
armvixl5289c592015-03-02 13:52:04 +00002389
armvixl0f35e362016-05-10 13:57:58 +01002390#define NEON_2VREG_SHIFT_MACRO_LIST(V) \
2391 V(rshrn, Rshrn) \
2392 V(rshrn2, Rshrn2) \
2393 V(shl, Shl) \
2394 V(shll, Shll) \
2395 V(shll2, Shll2) \
2396 V(shrn, Shrn) \
2397 V(shrn2, Shrn2) \
2398 V(sli, Sli) \
2399 V(sqrshrn, Sqrshrn) \
2400 V(sqrshrn2, Sqrshrn2) \
2401 V(sqrshrun, Sqrshrun) \
2402 V(sqrshrun2, Sqrshrun2) \
2403 V(sqshl, Sqshl) \
2404 V(sqshlu, Sqshlu) \
2405 V(sqshrn, Sqshrn) \
2406 V(sqshrn2, Sqshrn2) \
2407 V(sqshrun, Sqshrun) \
2408 V(sqshrun2, Sqshrun2) \
2409 V(sri, Sri) \
2410 V(srshr, Srshr) \
2411 V(srsra, Srsra) \
2412 V(sshll, Sshll) \
2413 V(sshll2, Sshll2) \
2414 V(sshr, Sshr) \
2415 V(ssra, Ssra) \
2416 V(uqrshrn, Uqrshrn) \
2417 V(uqrshrn2, Uqrshrn2) \
2418 V(uqshl, Uqshl) \
2419 V(uqshrn, Uqshrn) \
2420 V(uqshrn2, Uqshrn2) \
2421 V(urshr, Urshr) \
2422 V(ursra, Ursra) \
2423 V(ushll, Ushll) \
2424 V(ushll2, Ushll2) \
2425 V(ushr, Ushr) \
2426 V(usra, Usra)
armvixl5289c592015-03-02 13:52:04 +00002427
armvixl0f35e362016-05-10 13:57:58 +01002428#define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \
2429 void MASM(const VRegister& vd, const VRegister& vn, int shift) { \
2430 VIXL_ASSERT(allow_macro_instructions_); \
2431 SingleEmissionCheckScope guard(this); \
2432 ASM(vd, vn, shift); \
armvixl5289c592015-03-02 13:52:04 +00002433 }
2434 NEON_2VREG_SHIFT_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)
armvixl0f35e362016-05-10 13:57:58 +01002435#undef DEFINE_MACRO_ASM_FUNC
armvixl5289c592015-03-02 13:52:04 +00002436
armvixl0f35e362016-05-10 13:57:58 +01002437 void Bic(const VRegister& vd, const int imm8, const int left_shift = 0) {
armvixl5289c592015-03-02 13:52:04 +00002438 VIXL_ASSERT(allow_macro_instructions_);
2439 SingleEmissionCheckScope guard(this);
2440 bic(vd, imm8, left_shift);
2441 }
armvixl0f35e362016-05-10 13:57:58 +01002442 void Cmeq(const VRegister& vd, const VRegister& vn, int imm) {
armvixl5289c592015-03-02 13:52:04 +00002443 VIXL_ASSERT(allow_macro_instructions_);
2444 SingleEmissionCheckScope guard(this);
2445 cmeq(vd, vn, imm);
2446 }
armvixl0f35e362016-05-10 13:57:58 +01002447 void Cmge(const VRegister& vd, const VRegister& vn, int imm) {
armvixl5289c592015-03-02 13:52:04 +00002448 VIXL_ASSERT(allow_macro_instructions_);
2449 SingleEmissionCheckScope guard(this);
2450 cmge(vd, vn, imm);
2451 }
armvixl0f35e362016-05-10 13:57:58 +01002452 void Cmgt(const VRegister& vd, const VRegister& vn, int imm) {
armvixl5289c592015-03-02 13:52:04 +00002453 VIXL_ASSERT(allow_macro_instructions_);
2454 SingleEmissionCheckScope guard(this);
2455 cmgt(vd, vn, imm);
2456 }
armvixl0f35e362016-05-10 13:57:58 +01002457 void Cmle(const VRegister& vd, const VRegister& vn, int imm) {
armvixl5289c592015-03-02 13:52:04 +00002458 VIXL_ASSERT(allow_macro_instructions_);
2459 SingleEmissionCheckScope guard(this);
2460 cmle(vd, vn, imm);
2461 }
armvixl0f35e362016-05-10 13:57:58 +01002462 void Cmlt(const VRegister& vd, const VRegister& vn, int imm) {
armvixl5289c592015-03-02 13:52:04 +00002463 VIXL_ASSERT(allow_macro_instructions_);
2464 SingleEmissionCheckScope guard(this);
2465 cmlt(vd, vn, imm);
2466 }
armvixl0f35e362016-05-10 13:57:58 +01002467 void Dup(const VRegister& vd, const VRegister& vn, int index) {
armvixl5289c592015-03-02 13:52:04 +00002468 VIXL_ASSERT(allow_macro_instructions_);
2469 SingleEmissionCheckScope guard(this);
2470 dup(vd, vn, index);
2471 }
armvixl0f35e362016-05-10 13:57:58 +01002472 void Dup(const VRegister& vd, const Register& rn) {
armvixl5289c592015-03-02 13:52:04 +00002473 VIXL_ASSERT(allow_macro_instructions_);
2474 SingleEmissionCheckScope guard(this);
2475 dup(vd, rn);
2476 }
2477 void Ext(const VRegister& vd,
2478 const VRegister& vn,
2479 const VRegister& vm,
2480 int index) {
2481 VIXL_ASSERT(allow_macro_instructions_);
2482 SingleEmissionCheckScope guard(this);
2483 ext(vd, vn, vm, index);
2484 }
2485 void Ins(const VRegister& vd,
2486 int vd_index,
2487 const VRegister& vn,
2488 int vn_index) {
2489 VIXL_ASSERT(allow_macro_instructions_);
2490 SingleEmissionCheckScope guard(this);
2491 ins(vd, vd_index, vn, vn_index);
2492 }
armvixl0f35e362016-05-10 13:57:58 +01002493 void Ins(const VRegister& vd, int vd_index, const Register& rn) {
armvixl5289c592015-03-02 13:52:04 +00002494 VIXL_ASSERT(allow_macro_instructions_);
2495 SingleEmissionCheckScope guard(this);
2496 ins(vd, vd_index, rn);
2497 }
armvixl0f35e362016-05-10 13:57:58 +01002498 void Ld1(const VRegister& vt, const MemOperand& src) {
armvixl5289c592015-03-02 13:52:04 +00002499 VIXL_ASSERT(allow_macro_instructions_);
2500 SingleEmissionCheckScope guard(this);
2501 ld1(vt, src);
2502 }
armvixl0f35e362016-05-10 13:57:58 +01002503 void Ld1(const VRegister& vt, const VRegister& vt2, const MemOperand& src) {
armvixl5289c592015-03-02 13:52:04 +00002504 VIXL_ASSERT(allow_macro_instructions_);
2505 SingleEmissionCheckScope guard(this);
2506 ld1(vt, vt2, src);
2507 }
2508 void Ld1(const VRegister& vt,
2509 const VRegister& vt2,
2510 const VRegister& vt3,
2511 const MemOperand& src) {
2512 VIXL_ASSERT(allow_macro_instructions_);
2513 SingleEmissionCheckScope guard(this);
2514 ld1(vt, vt2, vt3, src);
2515 }
2516 void Ld1(const VRegister& vt,
2517 const VRegister& vt2,
2518 const VRegister& vt3,
2519 const VRegister& vt4,
2520 const MemOperand& src) {
2521 VIXL_ASSERT(allow_macro_instructions_);
2522 SingleEmissionCheckScope guard(this);
2523 ld1(vt, vt2, vt3, vt4, src);
2524 }
armvixl0f35e362016-05-10 13:57:58 +01002525 void Ld1(const VRegister& vt, int lane, const MemOperand& src) {
armvixl5289c592015-03-02 13:52:04 +00002526 VIXL_ASSERT(allow_macro_instructions_);
2527 SingleEmissionCheckScope guard(this);
2528 ld1(vt, lane, src);
2529 }
armvixl0f35e362016-05-10 13:57:58 +01002530 void Ld1r(const VRegister& vt, const MemOperand& src) {
armvixl5289c592015-03-02 13:52:04 +00002531 VIXL_ASSERT(allow_macro_instructions_);
2532 SingleEmissionCheckScope guard(this);
2533 ld1r(vt, src);
2534 }
armvixl0f35e362016-05-10 13:57:58 +01002535 void Ld2(const VRegister& vt, const VRegister& vt2, const MemOperand& src) {
armvixl5289c592015-03-02 13:52:04 +00002536 VIXL_ASSERT(allow_macro_instructions_);
2537 SingleEmissionCheckScope guard(this);
2538 ld2(vt, vt2, src);
2539 }
2540 void Ld2(const VRegister& vt,
2541 const VRegister& vt2,
2542 int lane,
2543 const MemOperand& src) {
2544 VIXL_ASSERT(allow_macro_instructions_);
2545 SingleEmissionCheckScope guard(this);
2546 ld2(vt, vt2, lane, src);
2547 }
armvixl0f35e362016-05-10 13:57:58 +01002548 void Ld2r(const VRegister& vt, const VRegister& vt2, const MemOperand& src) {
armvixl5289c592015-03-02 13:52:04 +00002549 VIXL_ASSERT(allow_macro_instructions_);
2550 SingleEmissionCheckScope guard(this);
2551 ld2r(vt, vt2, src);
2552 }
2553 void Ld3(const VRegister& vt,
2554 const VRegister& vt2,
2555 const VRegister& vt3,
2556 const MemOperand& src) {
2557 VIXL_ASSERT(allow_macro_instructions_);
2558 SingleEmissionCheckScope guard(this);
2559 ld3(vt, vt2, vt3, src);
2560 }
2561 void Ld3(const VRegister& vt,
2562 const VRegister& vt2,
2563 const VRegister& vt3,
2564 int lane,
2565 const MemOperand& src) {
2566 VIXL_ASSERT(allow_macro_instructions_);
2567 SingleEmissionCheckScope guard(this);
2568 ld3(vt, vt2, vt3, lane, src);
2569 }
2570 void Ld3r(const VRegister& vt,
2571 const VRegister& vt2,
2572 const VRegister& vt3,
armvixl0f35e362016-05-10 13:57:58 +01002573 const MemOperand& src) {
armvixl5289c592015-03-02 13:52:04 +00002574 VIXL_ASSERT(allow_macro_instructions_);
2575 SingleEmissionCheckScope guard(this);
2576 ld3r(vt, vt2, vt3, src);
2577 }
2578 void Ld4(const VRegister& vt,
2579 const VRegister& vt2,
2580 const VRegister& vt3,
2581 const VRegister& vt4,
2582 const MemOperand& src) {
2583 VIXL_ASSERT(allow_macro_instructions_);
2584 SingleEmissionCheckScope guard(this);
2585 ld4(vt, vt2, vt3, vt4, src);
2586 }
2587 void Ld4(const VRegister& vt,
2588 const VRegister& vt2,
2589 const VRegister& vt3,
2590 const VRegister& vt4,
2591 int lane,
2592 const MemOperand& src) {
2593 VIXL_ASSERT(allow_macro_instructions_);
2594 SingleEmissionCheckScope guard(this);
2595 ld4(vt, vt2, vt3, vt4, lane, src);
2596 }
2597 void Ld4r(const VRegister& vt,
2598 const VRegister& vt2,
2599 const VRegister& vt3,
2600 const VRegister& vt4,
armvixl0f35e362016-05-10 13:57:58 +01002601 const MemOperand& src) {
armvixl5289c592015-03-02 13:52:04 +00002602 VIXL_ASSERT(allow_macro_instructions_);
2603 SingleEmissionCheckScope guard(this);
2604 ld4r(vt, vt2, vt3, vt4, src);
2605 }
2606 void Mov(const VRegister& vd,
2607 int vd_index,
2608 const VRegister& vn,
2609 int vn_index) {
2610 VIXL_ASSERT(allow_macro_instructions_);
2611 SingleEmissionCheckScope guard(this);
2612 mov(vd, vd_index, vn, vn_index);
2613 }
armvixl0f35e362016-05-10 13:57:58 +01002614 void Mov(const VRegister& vd, const VRegister& vn, int index) {
armvixl5289c592015-03-02 13:52:04 +00002615 VIXL_ASSERT(allow_macro_instructions_);
2616 SingleEmissionCheckScope guard(this);
2617 mov(vd, vn, index);
2618 }
armvixl0f35e362016-05-10 13:57:58 +01002619 void Mov(const VRegister& vd, int vd_index, const Register& rn) {
armvixl5289c592015-03-02 13:52:04 +00002620 VIXL_ASSERT(allow_macro_instructions_);
2621 SingleEmissionCheckScope guard(this);
2622 mov(vd, vd_index, rn);
2623 }
armvixl0f35e362016-05-10 13:57:58 +01002624 void Mov(const Register& rd, const VRegister& vn, int vn_index) {
armvixl5289c592015-03-02 13:52:04 +00002625 VIXL_ASSERT(allow_macro_instructions_);
2626 SingleEmissionCheckScope guard(this);
2627 mov(rd, vn, vn_index);
2628 }
2629 void Movi(const VRegister& vd,
2630 uint64_t imm,
2631 Shift shift = LSL,
2632 int shift_amount = 0);
2633 void Movi(const VRegister& vd, uint64_t hi, uint64_t lo);
2634 void Mvni(const VRegister& vd,
2635 const int imm8,
2636 Shift shift = LSL,
2637 const int shift_amount = 0) {
2638 VIXL_ASSERT(allow_macro_instructions_);
2639 SingleEmissionCheckScope guard(this);
2640 mvni(vd, imm8, shift, shift_amount);
2641 }
armvixl0f35e362016-05-10 13:57:58 +01002642 void Orr(const VRegister& vd, const int imm8, const int left_shift = 0) {
armvixl5289c592015-03-02 13:52:04 +00002643 VIXL_ASSERT(allow_macro_instructions_);
2644 SingleEmissionCheckScope guard(this);
2645 orr(vd, imm8, left_shift);
2646 }
armvixl0f35e362016-05-10 13:57:58 +01002647 void Scvtf(const VRegister& vd, const VRegister& vn, int fbits = 0) {
armvixl5289c592015-03-02 13:52:04 +00002648 VIXL_ASSERT(allow_macro_instructions_);
2649 SingleEmissionCheckScope guard(this);
2650 scvtf(vd, vn, fbits);
2651 }
armvixl0f35e362016-05-10 13:57:58 +01002652 void Ucvtf(const VRegister& vd, const VRegister& vn, int fbits = 0) {
armvixl5289c592015-03-02 13:52:04 +00002653 VIXL_ASSERT(allow_macro_instructions_);
2654 SingleEmissionCheckScope guard(this);
2655 ucvtf(vd, vn, fbits);
2656 }
armvixl0f35e362016-05-10 13:57:58 +01002657 void Fcvtzs(const VRegister& vd, const VRegister& vn, int fbits = 0) {
armvixl5289c592015-03-02 13:52:04 +00002658 VIXL_ASSERT(allow_macro_instructions_);
2659 SingleEmissionCheckScope guard(this);
2660 fcvtzs(vd, vn, fbits);
2661 }
armvixl0f35e362016-05-10 13:57:58 +01002662 void Fcvtzu(const VRegister& vd, const VRegister& vn, int fbits = 0) {
armvixl5289c592015-03-02 13:52:04 +00002663 VIXL_ASSERT(allow_macro_instructions_);
2664 SingleEmissionCheckScope guard(this);
2665 fcvtzu(vd, vn, fbits);
2666 }
armvixl0f35e362016-05-10 13:57:58 +01002667 void St1(const VRegister& vt, const MemOperand& dst) {
armvixl5289c592015-03-02 13:52:04 +00002668 VIXL_ASSERT(allow_macro_instructions_);
2669 SingleEmissionCheckScope guard(this);
2670 st1(vt, dst);
2671 }
armvixl0f35e362016-05-10 13:57:58 +01002672 void St1(const VRegister& vt, const VRegister& vt2, const MemOperand& dst) {
armvixl5289c592015-03-02 13:52:04 +00002673 VIXL_ASSERT(allow_macro_instructions_);
2674 SingleEmissionCheckScope guard(this);
2675 st1(vt, vt2, dst);
2676 }
2677 void St1(const VRegister& vt,
2678 const VRegister& vt2,
2679 const VRegister& vt3,
2680 const MemOperand& dst) {
2681 VIXL_ASSERT(allow_macro_instructions_);
2682 SingleEmissionCheckScope guard(this);
2683 st1(vt, vt2, vt3, dst);
2684 }
2685 void St1(const VRegister& vt,
2686 const VRegister& vt2,
2687 const VRegister& vt3,
2688 const VRegister& vt4,
2689 const MemOperand& dst) {
2690 VIXL_ASSERT(allow_macro_instructions_);
2691 SingleEmissionCheckScope guard(this);
2692 st1(vt, vt2, vt3, vt4, dst);
2693 }
armvixl0f35e362016-05-10 13:57:58 +01002694 void St1(const VRegister& vt, int lane, const MemOperand& dst) {
armvixl5289c592015-03-02 13:52:04 +00002695 VIXL_ASSERT(allow_macro_instructions_);
2696 SingleEmissionCheckScope guard(this);
2697 st1(vt, lane, dst);
2698 }
armvixl0f35e362016-05-10 13:57:58 +01002699 void St2(const VRegister& vt, const VRegister& vt2, const MemOperand& dst) {
armvixl5289c592015-03-02 13:52:04 +00002700 VIXL_ASSERT(allow_macro_instructions_);
2701 SingleEmissionCheckScope guard(this);
2702 st2(vt, vt2, dst);
2703 }
2704 void St3(const VRegister& vt,
2705 const VRegister& vt2,
2706 const VRegister& vt3,
2707 const MemOperand& dst) {
2708 VIXL_ASSERT(allow_macro_instructions_);
2709 SingleEmissionCheckScope guard(this);
2710 st3(vt, vt2, vt3, dst);
2711 }
2712 void St4(const VRegister& vt,
2713 const VRegister& vt2,
2714 const VRegister& vt3,
2715 const VRegister& vt4,
2716 const MemOperand& dst) {
2717 VIXL_ASSERT(allow_macro_instructions_);
2718 SingleEmissionCheckScope guard(this);
2719 st4(vt, vt2, vt3, vt4, dst);
2720 }
2721 void St2(const VRegister& vt,
2722 const VRegister& vt2,
2723 int lane,
2724 const MemOperand& dst) {
2725 VIXL_ASSERT(allow_macro_instructions_);
2726 SingleEmissionCheckScope guard(this);
2727 st2(vt, vt2, lane, dst);
2728 }
2729 void St3(const VRegister& vt,
2730 const VRegister& vt2,
2731 const VRegister& vt3,
2732 int lane,
2733 const MemOperand& dst) {
2734 VIXL_ASSERT(allow_macro_instructions_);
2735 SingleEmissionCheckScope guard(this);
2736 st3(vt, vt2, vt3, lane, dst);
2737 }
2738 void St4(const VRegister& vt,
2739 const VRegister& vt2,
2740 const VRegister& vt3,
2741 const VRegister& vt4,
2742 int lane,
2743 const MemOperand& dst) {
2744 VIXL_ASSERT(allow_macro_instructions_);
2745 SingleEmissionCheckScope guard(this);
2746 st4(vt, vt2, vt3, vt4, lane, dst);
2747 }
armvixl0f35e362016-05-10 13:57:58 +01002748 void Smov(const Register& rd, const VRegister& vn, int vn_index) {
armvixl5289c592015-03-02 13:52:04 +00002749 VIXL_ASSERT(allow_macro_instructions_);
2750 SingleEmissionCheckScope guard(this);
2751 smov(rd, vn, vn_index);
2752 }
armvixl0f35e362016-05-10 13:57:58 +01002753 void Umov(const Register& rd, const VRegister& vn, int vn_index) {
armvixl5289c592015-03-02 13:52:04 +00002754 VIXL_ASSERT(allow_macro_instructions_);
2755 SingleEmissionCheckScope guard(this);
2756 umov(rd, vn, vn_index);
2757 }
armvixl0f35e362016-05-10 13:57:58 +01002758 void Crc32b(const Register& rd, const Register& rn, const Register& rm) {
armvixl5289c592015-03-02 13:52:04 +00002759 VIXL_ASSERT(allow_macro_instructions_);
2760 SingleEmissionCheckScope guard(this);
2761 crc32b(rd, rn, rm);
2762 }
armvixl0f35e362016-05-10 13:57:58 +01002763 void Crc32h(const Register& rd, const Register& rn, const Register& rm) {
armvixl5289c592015-03-02 13:52:04 +00002764 VIXL_ASSERT(allow_macro_instructions_);
2765 SingleEmissionCheckScope guard(this);
2766 crc32h(rd, rn, rm);
2767 }
armvixl0f35e362016-05-10 13:57:58 +01002768 void Crc32w(const Register& rd, const Register& rn, const Register& rm) {
armvixl5289c592015-03-02 13:52:04 +00002769 VIXL_ASSERT(allow_macro_instructions_);
2770 SingleEmissionCheckScope guard(this);
2771 crc32w(rd, rn, rm);
2772 }
armvixl0f35e362016-05-10 13:57:58 +01002773 void Crc32x(const Register& rd, const Register& rn, const Register& rm) {
armvixl5289c592015-03-02 13:52:04 +00002774 VIXL_ASSERT(allow_macro_instructions_);
2775 SingleEmissionCheckScope guard(this);
2776 crc32x(rd, rn, rm);
2777 }
armvixl0f35e362016-05-10 13:57:58 +01002778 void Crc32cb(const Register& rd, const Register& rn, const Register& rm) {
armvixl5289c592015-03-02 13:52:04 +00002779 VIXL_ASSERT(allow_macro_instructions_);
2780 SingleEmissionCheckScope guard(this);
2781 crc32cb(rd, rn, rm);
2782 }
armvixl0f35e362016-05-10 13:57:58 +01002783 void Crc32ch(const Register& rd, const Register& rn, const Register& rm) {
armvixl5289c592015-03-02 13:52:04 +00002784 VIXL_ASSERT(allow_macro_instructions_);
2785 SingleEmissionCheckScope guard(this);
2786 crc32ch(rd, rn, rm);
2787 }
armvixl0f35e362016-05-10 13:57:58 +01002788 void Crc32cw(const Register& rd, const Register& rn, const Register& rm) {
armvixl5289c592015-03-02 13:52:04 +00002789 VIXL_ASSERT(allow_macro_instructions_);
2790 SingleEmissionCheckScope guard(this);
2791 crc32cw(rd, rn, rm);
2792 }
armvixl0f35e362016-05-10 13:57:58 +01002793 void Crc32cx(const Register& rd, const Register& rn, const Register& rm) {
armvixl5289c592015-03-02 13:52:04 +00002794 VIXL_ASSERT(allow_macro_instructions_);
2795 SingleEmissionCheckScope guard(this);
2796 crc32cx(rd, rn, rm);
2797 }
armvixldb644342015-07-21 11:37:10 +01002798
armvixl0f35e362016-05-10 13:57:58 +01002799 template <typename T>
armvixldb644342015-07-21 11:37:10 +01002800 Literal<T>* CreateLiteralDestroyedWithPool(T value) {
2801 return new Literal<T>(value,
2802 &literal_pool_,
2803 RawLiteral::kDeletedOnPoolDestruction);
2804 }
2805
armvixl0f35e362016-05-10 13:57:58 +01002806 template <typename T>
armvixldb644342015-07-21 11:37:10 +01002807 Literal<T>* CreateLiteralDestroyedWithPool(T high64, T low64) {
armvixl0f35e362016-05-10 13:57:58 +01002808 return new Literal<T>(high64,
2809 low64,
armvixldb644342015-07-21 11:37:10 +01002810 &literal_pool_,
2811 RawLiteral::kDeletedOnPoolDestruction);
2812 }
2813
armvixlad96eda2013-06-14 11:42:37 +01002814 // Push the system stack pointer (sp) down to allow the same to be done to
2815 // the current stack pointer (according to StackPointer()). This must be
2816 // called _before_ accessing the memory.
2817 //
2818 // This is necessary when pushing or otherwise adding things to the stack, to
2819 // satisfy the AAPCS64 constraint that the memory below the system stack
2820 // pointer is not accessed.
2821 //
2822 // This method asserts that StackPointer() is not sp, since the call does
2823 // not make sense in that context.
2824 //
2825 // TODO: This method can only accept values of 'space' that can be encoded in
2826 // one instruction. Refer to the implementation for details.
2827 void BumpSystemStackPointer(const Operand& space);
2828
armvixl684cd2a2015-10-23 13:38:33 +01002829#ifdef VIXL_DEBUG
armvixlad96eda2013-06-14 11:42:37 +01002830 void SetAllowMacroInstructions(bool value) {
2831 allow_macro_instructions_ = value;
2832 }
2833
armvixl0f35e362016-05-10 13:57:58 +01002834 bool AllowMacroInstructions() const { return allow_macro_instructions_; }
armvixlad96eda2013-06-14 11:42:37 +01002835#endif
2836
armvixl684cd2a2015-10-23 13:38:33 +01002837 void SetAllowSimulatorInstructions(bool value) {
2838 allow_simulator_instructions_ = value;
2839 }
2840
2841 bool AllowSimulatorInstructions() const {
2842 return allow_simulator_instructions_;
2843 }
2844
armvixlc68cb642014-09-25 18:49:30 +01002845 void BlockLiteralPool() { literal_pool_.Block(); }
2846 void ReleaseLiteralPool() { literal_pool_.Release(); }
2847 bool IsLiteralPoolBlocked() const { return literal_pool_.IsBlocked(); }
armvixl5289c592015-03-02 13:52:04 +00002848 void BlockVeneerPool() { veneer_pool_.Block(); }
2849 void ReleaseVeneerPool() { veneer_pool_.Release(); }
2850 bool IsVeneerPoolBlocked() const { return veneer_pool_.IsBlocked(); }
armvixlc68cb642014-09-25 18:49:30 +01002851
armvixldb644342015-07-21 11:37:10 +01002852 void BlockPools() {
2853 BlockLiteralPool();
2854 BlockVeneerPool();
2855 }
2856
2857 void ReleasePools() {
2858 ReleaseLiteralPool();
2859 ReleaseVeneerPool();
2860 }
2861
Pierre Langlois88c46b82016-06-02 18:15:32 +01002862 size_t GetLiteralPoolSize() const { return literal_pool_.GetSize(); }
2863 VIXL_DEPRECATED("GetLiteralPoolSize", size_t LiteralPoolSize() const) {
2864 return GetLiteralPoolSize();
armvixl5289c592015-03-02 13:52:04 +00002865 }
2866
Pierre Langlois88c46b82016-06-02 18:15:32 +01002867 size_t GetLiteralPoolMaxSize() const { return literal_pool_.GetMaxSize(); }
2868 VIXL_DEPRECATED("GetLiteralPoolMaxSize", size_t LiteralPoolMaxSize() const) {
2869 return GetLiteralPoolMaxSize();
2870 }
2871
2872 size_t GetVeneerPoolMaxSize() const { return veneer_pool_.GetMaxSize(); }
2873 VIXL_DEPRECATED("GetVeneerPoolMaxSize", size_t VeneerPoolMaxSize() const) {
2874 return GetVeneerPoolMaxSize();
2875 }
2876
2877 // The number of unresolved branches that may require a veneer.
2878 int GetNumberOfPotentialVeneers() const {
2879 return veneer_pool_.GetNumberOfPotentialVeneers();
2880 }
2881 VIXL_DEPRECATED("GetNumberOfPotentialVeneers",
2882 int NumberOfPotentialVeneers() const) {
2883 return GetNumberOfPotentialVeneers();
2884 }
2885
2886 ptrdiff_t GetNextCheckPoint() const {
armvixl0f35e362016-05-10 13:57:58 +01002887 ptrdiff_t next_checkpoint_for_pools =
Pierre Langlois88c46b82016-06-02 18:15:32 +01002888 std::min(literal_pool_.GetCheckpoint(), veneer_pool_.GetCheckpoint());
2889 return std::min(next_checkpoint_for_pools, GetBufferEndOffset());
2890 }
2891 VIXL_DEPRECATED("GetNextCheckPoint", ptrdiff_t NextCheckPoint()) {
2892 return GetNextCheckPoint();
armvixlc68cb642014-09-25 18:49:30 +01002893 }
2894
2895 void EmitLiteralPool(LiteralPool::EmitOption option) {
2896 if (!literal_pool_.IsEmpty()) literal_pool_.Emit(option);
2897
Pierre Langlois88c46b82016-06-02 18:15:32 +01002898 checkpoint_ = GetNextCheckPoint();
2899 recommended_checkpoint_ = literal_pool_.GetNextRecommendedCheckpoint();
armvixlc68cb642014-09-25 18:49:30 +01002900 }
2901
armvixl5289c592015-03-02 13:52:04 +00002902 void CheckEmitFor(size_t amount);
armvixlc68cb642014-09-25 18:49:30 +01002903 void EnsureEmitFor(size_t amount) {
2904 ptrdiff_t offset = amount;
Pierre Langlois88c46b82016-06-02 18:15:32 +01002905 ptrdiff_t max_pools_size =
2906 literal_pool_.GetMaxSize() + veneer_pool_.GetMaxSize();
2907 ptrdiff_t cursor = GetCursorOffset();
armvixl5289c592015-03-02 13:52:04 +00002908 if ((cursor >= recommended_checkpoint_) ||
2909 ((cursor + offset + max_pools_size) >= checkpoint_)) {
2910 CheckEmitFor(amount);
armvixlc68cb642014-09-25 18:49:30 +01002911 }
2912 }
2913
armvixlad96eda2013-06-14 11:42:37 +01002914 // Set the current stack pointer, but don't generate any code.
armvixlad96eda2013-06-14 11:42:37 +01002915 void SetStackPointer(const Register& stack_pointer) {
Pierre Langlois88c46b82016-06-02 18:15:32 +01002916 VIXL_ASSERT(!GetScratchRegisterList()->IncludesAliasOf(stack_pointer));
armvixlad96eda2013-06-14 11:42:37 +01002917 sp_ = stack_pointer;
2918 }
2919
2920 // Return the current stack pointer, as set by SetStackPointer.
armvixl0f35e362016-05-10 13:57:58 +01002921 const Register& StackPointer() const { return sp_; }
armvixlad96eda2013-06-14 11:42:37 +01002922
Pierre Langlois88c46b82016-06-02 18:15:32 +01002923 CPURegList* GetScratchRegisterList() { return &tmp_list_; }
2924 VIXL_DEPRECATED("GetScratchRegisterList", CPURegList* TmpList()) {
2925 return GetScratchRegisterList();
2926 }
2927
2928 CPURegList* GetScratchFPRegisterList() { return &fptmp_list_; }
2929 VIXL_DEPRECATED("GetScratchFPRegisterList", CPURegList* FPTmpList()) {
2930 return GetScratchFPRegisterList();
2931 }
armvixlad96eda2013-06-14 11:42:37 +01002932
2933 // Like printf, but print at run-time from generated code.
2934 //
2935 // The caller must ensure that arguments for floating-point placeholders
armvixl5289c592015-03-02 13:52:04 +00002936 // (such as %e, %f or %g) are VRegisters in format 1S or 1D, and that
2937 // arguments for integer placeholders are Registers.
armvixlad96eda2013-06-14 11:42:37 +01002938 //
armvixl5799d6c2014-05-01 11:05:00 +01002939 // At the moment it is only possible to print the value of sp if it is the
2940 // current stack pointer. Otherwise, the MacroAssembler will automatically
2941 // update sp on every push (using BumpSystemStackPointer), so determining its
2942 // value is difficult.
armvixlad96eda2013-06-14 11:42:37 +01002943 //
armvixl5799d6c2014-05-01 11:05:00 +01002944 // Format placeholders that refer to more than one argument, or to a specific
2945 // argument, are not supported. This includes formats like "%1$d" or "%.*d".
armvixlad96eda2013-06-14 11:42:37 +01002946 //
2947 // This function automatically preserves caller-saved registers so that
2948 // calling code can use Printf at any point without having to worry about
2949 // corruption. The preservation mechanism generates a lot of code. If this is
2950 // a problem, preserve the important registers manually and then call
2951 // PrintfNoPreserve. Callee-saved registers are not used by Printf, and are
2952 // implicitly preserved.
armvixl0f35e362016-05-10 13:57:58 +01002953 void Printf(const char* format,
armvixl5799d6c2014-05-01 11:05:00 +01002954 CPURegister arg0 = NoCPUReg,
2955 CPURegister arg1 = NoCPUReg,
2956 CPURegister arg2 = NoCPUReg,
2957 CPURegister arg3 = NoCPUReg);
armvixlad96eda2013-06-14 11:42:37 +01002958
2959 // Like Printf, but don't preserve any caller-saved registers, not even 'lr'.
2960 //
2961 // The return code from the system printf call will be returned in x0.
armvixl0f35e362016-05-10 13:57:58 +01002962 void PrintfNoPreserve(const char* format,
armvixlad96eda2013-06-14 11:42:37 +01002963 const CPURegister& arg0 = NoCPUReg,
2964 const CPURegister& arg1 = NoCPUReg,
2965 const CPURegister& arg2 = NoCPUReg,
2966 const CPURegister& arg3 = NoCPUReg);
2967
2968 // Trace control when running the debug simulator.
2969 //
2970 // For example:
2971 //
2972 // __ Trace(LOG_REGS, TRACE_ENABLE);
2973 // Will add registers to the trace if it wasn't already the case.
2974 //
2975 // __ Trace(LOG_DISASM, TRACE_DISABLE);
2976 // Will stop logging disassembly. It has no effect if the disassembly wasn't
2977 // already being logged.
2978 void Trace(TraceParameters parameters, TraceCommand command);
2979
2980 // Log the requested data independently of what is being traced.
2981 //
2982 // For example:
2983 //
2984 // __ Log(LOG_FLAGS)
2985 // Will output the flags.
armvixl578645f2013-08-15 17:21:42 +01002986 void Log(TraceParameters parameters);
2987
2988 // Enable or disable instrumentation when an Instrument visitor is attached to
2989 // the simulator.
2990 void EnableInstrumentation();
2991 void DisableInstrumentation();
2992
2993 // Add a marker to the instrumentation data produced by an Instrument visitor.
2994 // The name is a two character string that will be attached to the marker in
2995 // the output data.
2996 void AnnotateInstrumentation(const char* marker_name);
armvixlad96eda2013-06-14 11:42:37 +01002997
armvixl0f35e362016-05-10 13:57:58 +01002998 LiteralPool* GetLiteralPool() { return &literal_pool_; }
2999
3000 protected:
3001 // Helper used to query information about code generation and to generate
3002 // code for `csel`.
3003 // Here and for the related helpers below:
3004 // - Code is generated when `masm` is not `NULL`.
3005 // - On return and when set, `should_synthesise_left` and
3006 // `should_synthesise_right` will indicate whether `left` and `right`
3007 // should be synthesized in a temporary register.
3008 static void CselHelper(MacroAssembler* masm,
3009 const Register& rd,
3010 Operand left,
3011 Operand right,
3012 Condition cond,
3013 bool* should_synthesise_left = NULL,
3014 bool* should_synthesise_right = NULL);
3015
3016 // The helper returns `true` if it can handle the specified arguments.
3017 // Also see comments for `CselHelper()`.
3018 static bool CselSubHelperTwoImmediates(MacroAssembler* masm,
3019 const Register& rd,
3020 int64_t left,
3021 int64_t right,
3022 Condition cond,
3023 bool* should_synthesise_left,
3024 bool* should_synthesise_right);
3025
3026 // See comments for `CselHelper()`.
3027 static bool CselSubHelperTwoOrderedImmediates(MacroAssembler* masm,
3028 const Register& rd,
3029 int64_t left,
3030 int64_t right,
3031 Condition cond);
3032
3033 // See comments for `CselHelper()`.
3034 static void CselSubHelperRightSmallImmediate(MacroAssembler* masm,
3035 UseScratchRegisterScope* temps,
3036 const Register& rd,
3037 const Operand& left,
3038 const Operand& right,
3039 Condition cond,
3040 bool* should_synthesise_left);
armvixldb644342015-07-21 11:37:10 +01003041
armvixlad96eda2013-06-14 11:42:37 +01003042 private:
3043 // The actual Push and Pop implementations. These don't generate any code
3044 // other than that required for the push or pop. This allows
3045 // (Push|Pop)CPURegList to bundle together setup code for a large block of
3046 // registers.
3047 //
3048 // Note that size is per register, and is specified in bytes.
armvixl0f35e362016-05-10 13:57:58 +01003049 void PushHelper(int count,
3050 int size,
3051 const CPURegister& src0,
3052 const CPURegister& src1,
3053 const CPURegister& src2,
3054 const CPURegister& src3);
3055 void PopHelper(int count,
3056 int size,
3057 const CPURegister& dst0,
3058 const CPURegister& dst1,
3059 const CPURegister& dst2,
3060 const CPURegister& dst3);
armvixlad96eda2013-06-14 11:42:37 +01003061
armvixl5289c592015-03-02 13:52:04 +00003062 void Movi16bitHelper(const VRegister& vd, uint64_t imm);
3063 void Movi32bitHelper(const VRegister& vd, uint64_t imm);
3064 void Movi64bitHelper(const VRegister& vd, uint64_t imm);
3065
armvixlad96eda2013-06-14 11:42:37 +01003066 // Perform necessary maintenance operations before a push or pop.
3067 //
3068 // Note that size is per register, and is specified in bytes.
3069 void PrepareForPush(int count, int size);
3070 void PrepareForPop(int count, int size);
3071
armvixl6e2c8272015-03-31 11:04:14 +01003072 // The actual implementation of load and store operations for CPURegList.
armvixl0f35e362016-05-10 13:57:58 +01003073 enum LoadStoreCPURegListAction { kLoad, kStore };
armvixl6e2c8272015-03-31 11:04:14 +01003074 void LoadStoreCPURegListHelper(LoadStoreCPURegListAction operation,
3075 CPURegList registers,
3076 const MemOperand& mem);
3077 // Returns a MemOperand suitable for loading or storing a CPURegList at `dst`.
3078 // This helper may allocate registers from `scratch_scope` and generate code
3079 // to compute an intermediate address. The resulting MemOperand is only valid
3080 // as long as `scratch_scope` remains valid.
3081 MemOperand BaseMemOperandForLoadStoreCPURegList(
3082 const CPURegList& registers,
3083 const MemOperand& mem,
3084 UseScratchRegisterScope* scratch_scope);
3085
armvixl5289c592015-03-02 13:52:04 +00003086 bool LabelIsOutOfRange(Label* label, ImmBranchType branch_type) {
3087 return !Instruction::IsValidImmPCOffset(branch_type,
Pierre Langlois88c46b82016-06-02 18:15:32 +01003088 label->GetLocation() -
3089 GetCursorOffset());
armvixl5289c592015-03-02 13:52:04 +00003090 }
3091
armvixl684cd2a2015-10-23 13:38:33 +01003092#ifdef VIXL_DEBUG
armvixlad96eda2013-06-14 11:42:37 +01003093 // Tell whether any of the macro instruction can be used. When false the
3094 // MacroAssembler will assert if a method which can emit a variable number
3095 // of instructions is called.
3096 bool allow_macro_instructions_;
3097#endif
3098
armvixl684cd2a2015-10-23 13:38:33 +01003099 // Tell whether we should generate code that will run on the simulator or not.
3100 bool allow_simulator_instructions_;
3101
armvixlad96eda2013-06-14 11:42:37 +01003102 // The register to use as a stack pointer for stack operations.
3103 Register sp_;
3104
armvixlb0c8ae22014-03-21 14:03:59 +00003105 // Scratch registers available for use by the MacroAssembler.
3106 CPURegList tmp_list_;
3107 CPURegList fptmp_list_;
armvixlc68cb642014-09-25 18:49:30 +01003108
3109 LiteralPool literal_pool_;
armvixl5289c592015-03-02 13:52:04 +00003110 VeneerPool veneer_pool_;
3111
armvixlc68cb642014-09-25 18:49:30 +01003112 ptrdiff_t checkpoint_;
armvixl5289c592015-03-02 13:52:04 +00003113 ptrdiff_t recommended_checkpoint_;
3114
3115 friend class Pool;
3116 friend class LiteralPool;
armvixlad96eda2013-06-14 11:42:37 +01003117};
3118
3119
Pierre Langlois88c46b82016-06-02 18:15:32 +01003120inline size_t VeneerPool::GetOtherPoolsMaxSize() const {
3121 return masm_->GetLiteralPoolMaxSize();
armvixl5289c592015-03-02 13:52:04 +00003122}
3123
3124
Pierre Langlois88c46b82016-06-02 18:15:32 +01003125inline size_t LiteralPool::GetOtherPoolsMaxSize() const {
3126 return masm_->GetVeneerPoolMaxSize();
armvixl5289c592015-03-02 13:52:04 +00003127}
3128
3129
3130inline void LiteralPool::SetNextRecommendedCheckpoint(ptrdiff_t offset) {
3131 masm_->recommended_checkpoint_ =
3132 std::min(masm_->recommended_checkpoint_, offset);
3133 recommended_checkpoint_ = offset;
3134}
3135
armvixlad96eda2013-06-14 11:42:37 +01003136// Use this scope when you need a one-to-one mapping between methods and
3137// instructions. This scope prevents the MacroAssembler from being called and
3138// literal pools from being emitted. It also asserts the number of instructions
3139// emitted is what you specified when creating the scope.
armvixlc68cb642014-09-25 18:49:30 +01003140class InstructionAccurateScope : public CodeBufferCheckScope {
armvixlad96eda2013-06-14 11:42:37 +01003141 public:
armvixlc68cb642014-09-25 18:49:30 +01003142 InstructionAccurateScope(MacroAssembler* masm,
armvixldb644342015-07-21 11:37:10 +01003143 int64_t count,
armvixlc68cb642014-09-25 18:49:30 +01003144 AssertPolicy policy = kExactSize)
armvixl0f35e362016-05-10 13:57:58 +01003145 : CodeBufferCheckScope(masm, (count * kInstructionSize), kCheck, policy) {
armvixlc68cb642014-09-25 18:49:30 +01003146 VIXL_ASSERT(policy != kNoAssert);
armvixl330dc712014-11-25 10:38:32 +00003147#ifdef VIXL_DEBUG
armvixlc68cb642014-09-25 18:49:30 +01003148 old_allow_macro_instructions_ = masm->AllowMacroInstructions();
3149 masm->SetAllowMacroInstructions(false);
armvixl4a102ba2014-07-14 09:02:40 +01003150#endif
armvixlc68cb642014-09-25 18:49:30 +01003151 }
armvixlad96eda2013-06-14 11:42:37 +01003152
3153 ~InstructionAccurateScope() {
armvixl330dc712014-11-25 10:38:32 +00003154#ifdef VIXL_DEBUG
armvixlc68cb642014-09-25 18:49:30 +01003155 MacroAssembler* masm = reinterpret_cast<MacroAssembler*>(assm_);
3156 masm->SetAllowMacroInstructions(old_allow_macro_instructions_);
armvixlad96eda2013-06-14 11:42:37 +01003157#endif
3158 }
3159
3160 private:
armvixl330dc712014-11-25 10:38:32 +00003161#ifdef VIXL_DEBUG
armvixlad96eda2013-06-14 11:42:37 +01003162 bool old_allow_macro_instructions_;
3163#endif
3164};
3165
3166
armvixlc68cb642014-09-25 18:49:30 +01003167class BlockLiteralPoolScope {
3168 public:
3169 explicit BlockLiteralPoolScope(MacroAssembler* masm) : masm_(masm) {
3170 masm_->BlockLiteralPool();
3171 }
3172
armvixl0f35e362016-05-10 13:57:58 +01003173 ~BlockLiteralPoolScope() { masm_->ReleaseLiteralPool(); }
armvixlc68cb642014-09-25 18:49:30 +01003174
3175 private:
3176 MacroAssembler* masm_;
3177};
3178
3179
armvixl5289c592015-03-02 13:52:04 +00003180class BlockVeneerPoolScope {
3181 public:
3182 explicit BlockVeneerPoolScope(MacroAssembler* masm) : masm_(masm) {
3183 masm_->BlockVeneerPool();
3184 }
3185
armvixl0f35e362016-05-10 13:57:58 +01003186 ~BlockVeneerPoolScope() { masm_->ReleaseVeneerPool(); }
armvixl5289c592015-03-02 13:52:04 +00003187
3188 private:
3189 MacroAssembler* masm_;
3190};
3191
3192
3193class BlockPoolsScope {
3194 public:
3195 explicit BlockPoolsScope(MacroAssembler* masm) : masm_(masm) {
armvixldb644342015-07-21 11:37:10 +01003196 masm_->BlockPools();
armvixl5289c592015-03-02 13:52:04 +00003197 }
3198
armvixl0f35e362016-05-10 13:57:58 +01003199 ~BlockPoolsScope() { masm_->ReleasePools(); }
armvixl5289c592015-03-02 13:52:04 +00003200
3201 private:
3202 MacroAssembler* masm_;
3203};
3204
3205
armvixlb0c8ae22014-03-21 14:03:59 +00003206// This scope utility allows scratch registers to be managed safely. The
Pierre Langlois88c46b82016-06-02 18:15:32 +01003207// MacroAssembler's GetScratchRegisterList() (and GetScratchFPRegisterList()) is
3208// used as a pool of scratch registers. These registers can be allocated on
3209// demand, and will be returned at the end of the scope.
armvixlb0c8ae22014-03-21 14:03:59 +00003210//
3211// When the scope ends, the MacroAssembler's lists will be restored to their
3212// original state, even if the lists were modified by some other means.
3213class UseScratchRegisterScope {
3214 public:
armvixl0f35e362016-05-10 13:57:58 +01003215 // This constructor implicitly calls `Open` to initialise the scope (`masm`
3216 // must not be `NULL`), so it is ready to use immediately after it has been
3217 // constructed.
armvixl330dc712014-11-25 10:38:32 +00003218 explicit UseScratchRegisterScope(MacroAssembler* masm);
armvixl0f35e362016-05-10 13:57:58 +01003219 // This constructor does not implicitly initialise the scope. Instead,the user
3220 // is required to explicitly call the `Open` function before using the scope.
armvixl330dc712014-11-25 10:38:32 +00003221 UseScratchRegisterScope();
3222 // This function performs the actual initialisation work.
3223 void Open(MacroAssembler* masm);
armvixlb0c8ae22014-03-21 14:03:59 +00003224
armvixl330dc712014-11-25 10:38:32 +00003225 // The destructor always implicitly calls the `Close` function.
armvixlb0c8ae22014-03-21 14:03:59 +00003226 ~UseScratchRegisterScope();
armvixl330dc712014-11-25 10:38:32 +00003227 // This function performs the cleaning-up work. It must succeed even if the
3228 // scope has not been opened. It is safe to call multiple times.
3229 void Close();
armvixlb0c8ae22014-03-21 14:03:59 +00003230
3231
armvixl5799d6c2014-05-01 11:05:00 +01003232 bool IsAvailable(const CPURegister& reg) const;
3233
3234
armvixlb0c8ae22014-03-21 14:03:59 +00003235 // Take a register from the appropriate temps list. It will be returned
3236 // automatically when the scope ends.
3237 Register AcquireW() { return AcquireNextAvailable(available_).W(); }
3238 Register AcquireX() { return AcquireNextAvailable(available_).X(); }
armvixl5289c592015-03-02 13:52:04 +00003239 VRegister AcquireS() { return AcquireNextAvailable(availablefp_).S(); }
3240 VRegister AcquireD() { return AcquireNextAvailable(availablefp_).D(); }
armvixlb0c8ae22014-03-21 14:03:59 +00003241
3242
3243 Register AcquireSameSizeAs(const Register& reg);
armvixl5289c592015-03-02 13:52:04 +00003244 VRegister AcquireSameSizeAs(const VRegister& reg);
armvixlb0c8ae22014-03-21 14:03:59 +00003245
3246
3247 // Explicitly release an acquired (or excluded) register, putting it back in
3248 // the appropriate temps list.
3249 void Release(const CPURegister& reg);
3250
3251
3252 // Make the specified registers available as scratch registers for the
3253 // duration of this scope.
armvixl5799d6c2014-05-01 11:05:00 +01003254 void Include(const CPURegList& list);
armvixlb0c8ae22014-03-21 14:03:59 +00003255 void Include(const Register& reg1,
3256 const Register& reg2 = NoReg,
3257 const Register& reg3 = NoReg,
3258 const Register& reg4 = NoReg);
armvixl5289c592015-03-02 13:52:04 +00003259 void Include(const VRegister& reg1,
3260 const VRegister& reg2 = NoVReg,
3261 const VRegister& reg3 = NoVReg,
3262 const VRegister& reg4 = NoVReg);
armvixlb0c8ae22014-03-21 14:03:59 +00003263
3264
3265 // Make sure that the specified registers are not available in this scope.
3266 // This can be used to prevent helper functions from using sensitive
3267 // registers, for example.
armvixl5799d6c2014-05-01 11:05:00 +01003268 void Exclude(const CPURegList& list);
armvixlb0c8ae22014-03-21 14:03:59 +00003269 void Exclude(const Register& reg1,
3270 const Register& reg2 = NoReg,
3271 const Register& reg3 = NoReg,
3272 const Register& reg4 = NoReg);
armvixl5289c592015-03-02 13:52:04 +00003273 void Exclude(const VRegister& reg1,
3274 const VRegister& reg2 = NoVReg,
3275 const VRegister& reg3 = NoVReg,
3276 const VRegister& reg4 = NoVReg);
armvixlb0c8ae22014-03-21 14:03:59 +00003277 void Exclude(const CPURegister& reg1,
3278 const CPURegister& reg2 = NoCPUReg,
3279 const CPURegister& reg3 = NoCPUReg,
3280 const CPURegister& reg4 = NoCPUReg);
3281
3282
3283 // Prevent any scratch registers from being used in this scope.
3284 void ExcludeAll();
3285
3286
3287 private:
3288 static CPURegister AcquireNextAvailable(CPURegList* available);
3289
3290 static void ReleaseByCode(CPURegList* available, int code);
3291
armvixl0f35e362016-05-10 13:57:58 +01003292 static void ReleaseByRegList(CPURegList* available, RegList regs);
armvixlb0c8ae22014-03-21 14:03:59 +00003293
armvixl0f35e362016-05-10 13:57:58 +01003294 static void IncludeByRegList(CPURegList* available, RegList exclude);
armvixlb0c8ae22014-03-21 14:03:59 +00003295
armvixl0f35e362016-05-10 13:57:58 +01003296 static void ExcludeByRegList(CPURegList* available, RegList exclude);
armvixlb0c8ae22014-03-21 14:03:59 +00003297
3298 // Available scratch registers.
armvixl0f35e362016-05-10 13:57:58 +01003299 CPURegList* available_; // kRegister
3300 CPURegList* availablefp_; // kVRegister
armvixlb0c8ae22014-03-21 14:03:59 +00003301
3302 // The state of the available lists at the start of this scope.
armvixl0f35e362016-05-10 13:57:58 +01003303 RegList old_available_; // kRegister
3304 RegList old_availablefp_; // kVRegister
armvixl330dc712014-11-25 10:38:32 +00003305#ifdef VIXL_DEBUG
3306 bool initialised_;
3307#endif
3308
3309 // Disallow copy constructor and operator=.
armvixl684cd2a2015-10-23 13:38:33 +01003310 VIXL_DEBUG_NO_RETURN UseScratchRegisterScope(const UseScratchRegisterScope&) {
armvixl330dc712014-11-25 10:38:32 +00003311 VIXL_UNREACHABLE();
3312 }
armvixl684cd2a2015-10-23 13:38:33 +01003313 VIXL_DEBUG_NO_RETURN void operator=(const UseScratchRegisterScope&) {
armvixl330dc712014-11-25 10:38:32 +00003314 VIXL_UNREACHABLE();
3315 }
armvixlb0c8ae22014-03-21 14:03:59 +00003316};
3317
3318
Pierre Langlois88c46b82016-06-02 18:15:32 +01003319} // namespace aarch64
3320
3321// Required InvalSet template specialisations.
3322// TODO: These template specialisations should not live in this file. Move
3323// VeneerPool out of the aarch64 namespace in order to share its implementation
3324// later.
3325template <>
3326inline ptrdiff_t InvalSet<aarch64::VeneerPool::BranchInfo,
3327 aarch64::VeneerPool::kNPreallocatedInfos,
3328 ptrdiff_t,
3329 aarch64::VeneerPool::kInvalidOffset,
3330 aarch64::VeneerPool::kReclaimFrom,
3331 aarch64::VeneerPool::kReclaimFactor>::
3332 GetKey(const aarch64::VeneerPool::BranchInfo& branch_info) {
3333 return branch_info.max_reachable_pc_;
3334}
3335template <>
3336inline void InvalSet<aarch64::VeneerPool::BranchInfo,
3337 aarch64::VeneerPool::kNPreallocatedInfos,
3338 ptrdiff_t,
3339 aarch64::VeneerPool::kInvalidOffset,
3340 aarch64::VeneerPool::kReclaimFrom,
3341 aarch64::VeneerPool::kReclaimFactor>::
3342 SetKey(aarch64::VeneerPool::BranchInfo* branch_info, ptrdiff_t key) {
3343 branch_info->max_reachable_pc_ = key;
3344}
3345
armvixlad96eda2013-06-14 11:42:37 +01003346} // namespace vixl
3347
3348#endif // VIXL_A64_MACRO_ASSEMBLER_A64_H_