1 // Copyright 2015, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 //   * Redistributions of source code must retain the above copyright notice,
8 //     this list of conditions and the following disclaimer.
9 //   * Redistributions in binary form must reproduce the above copyright notice,
10 //     this list of conditions and the following disclaimer in the documentation
11 //     and/or other materials provided with the distribution.
12 //   * Neither the name of ARM Limited nor the names of its contributors may be
13 //     used to endorse or promote products derived from this software without
14 //     specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 #ifndef VIXL_AARCH64_SIMULATOR_AARCH64_H_
28 #define VIXL_AARCH64_SIMULATOR_AARCH64_H_
29 
30 #include <memory>
31 #include <unordered_map>
32 #include <vector>
33 
34 #include "../globals-vixl.h"
35 #include "../utils-vixl.h"
36 #include "cpu-features.h"
37 
38 #include "abi-aarch64.h"
39 #include "cpu-features-auditor-aarch64.h"
40 #include "debugger-aarch64.h"
41 #include "disasm-aarch64.h"
42 #include "instructions-aarch64.h"
43 #include "simulator-constants-aarch64.h"
44 
45 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
46 
47 // These are only used for the ABI feature, and depend on checks performed for
48 // it.
49 #ifdef VIXL_HAS_ABI_SUPPORT
50 #include <tuple>
51 #if __cplusplus >= 201402L
52 // Required for `std::index_sequence`
53 #include <utility>
54 #endif
55 #endif
56 
57 // The hosts that Simulator running on may not have these flags defined.
58 #ifndef PROT_BTI
59 #define PROT_BTI 0x10
60 #endif
61 #ifndef PROT_MTE
62 #define PROT_MTE 0x20
63 #endif
64 
65 namespace vixl {
66 namespace aarch64 {
67 
68 class Simulator;
69 struct RuntimeCallStructHelper;
70 
71 class SimStack {
72  public:
SimStack()73   SimStack() {}
SimStack(size_t size)74   explicit SimStack(size_t size) : usable_size_(size) {}
75 
76   // Guard against accesses above the stack base. This could occur, for example,
77   // if the first simulated function tries to read stack arguments that haven't
78   // been properly initialised in the Simulator's stack.
SetBaseGuardSize(size_t size)79   void SetBaseGuardSize(size_t size) { base_guard_size_ = size; }
80 
81   // Guard against stack overflows. The size should be large enough to detect
82   // the largest stride made (by `MacroAssembler::Claim()` or equivalent) whilst
83   // initialising stack objects.
SetLimitGuardSize(size_t size)84   void SetLimitGuardSize(size_t size) { limit_guard_size_ = size; }
85 
86   // The minimum usable size of the stack.
87   // Equal to "stack base" - "stack limit", in AAPCS64 terminology.
SetUsableSize(size_t size)88   void SetUsableSize(size_t size) { usable_size_ = size; }
89 
90   // Set the minimum alignment for the stack parameters.
AlignToBytesLog2(int align_log2)91   void AlignToBytesLog2(int align_log2) { align_log2_ = align_log2; }
92 
93   class Allocated {
94    public:
95     // Using AAPCS64 terminology, highest addresses at the top:
96     //
97     //  data_.get() + alloc_size ->
98     //                              |
99     //                              | Base guard
100     //                 GetBase() -> |                  |
101     //                                |                |
102     //                                |                | AAPCS64-legal
103     //                                | Usable stack   | values of 'sp'.
104     //                                |                |
105     //                                |                |
106     //                GetLimit() -> |
107     //                              | Limit guard
108     //               data_.get() -> |
109     //
110     // The Simulator detects (and forbids) accesses to either guard region.
111 
GetBase() const112     char* GetBase() const { return base_; }
GetLimit() const113     char* GetLimit() const { return limit_; }
114 
115     template <typename T>
IsAccessInGuardRegion(const T* base, size_t size) const116     bool IsAccessInGuardRegion(const T* base, size_t size) const {
117       VIXL_ASSERT(size > 0);
118       // Inclusive bounds.
119       const char* start = reinterpret_cast<const char*>(base);
120       const char* end = start + size - 1;
121       const char* data_start = data_.get();
122       const char* data_end = data_start + alloc_size_ - 1;
123       bool in_base_guard = (start <= data_end) && (end >= base_);
124       bool in_limit_guard = (start <= limit_) && (end >= data_start);
125       return in_base_guard || in_limit_guard;
126     }
127 
128    private:
129     std::unique_ptr<char[]> data_;
130     char* limit_;
131     char* base_;
132     size_t alloc_size_;
133 
134     friend class SimStack;
135   };
136 
137   // Allocate the stack, locking the parameters.
Allocate()138   Allocated Allocate() {
139     size_t align_to = 1 << align_log2_;
140     size_t l = AlignUp(limit_guard_size_, align_to);
141     size_t u = AlignUp(usable_size_, align_to);
142     size_t b = AlignUp(base_guard_size_, align_to);
143     size_t size = l + u + b;
144 
145     Allocated a;
146     size_t alloc_size = (align_to - 1) + size;
147     a.data_ = std::make_unique<char[]>(alloc_size);
148     void* data = a.data_.get();
149     auto data_aligned =
150         reinterpret_cast<char*>(std::align(align_to, size, data, alloc_size));
151     a.limit_ = data_aligned + l - 1;
152     a.base_ = data_aligned + l + u;
153     a.alloc_size_ = alloc_size;
154     return a;
155   }
156 
157  private:
158   size_t base_guard_size_ = 256;
159   size_t limit_guard_size_ = 4 * 1024;
160   size_t usable_size_ = 8 * 1024;
161   size_t align_log2_ = 4;
162 
163   static const size_t kDefaultBaseGuardSize = 256;
164   static const size_t kDefaultLimitGuardSize = 4 * 1024;
165   static const size_t kDefaultUsableSize = 8 * 1024;
166 };
167 
168 // Armv8.5 MTE helpers.
GetAllocationTagFromAddress(uint64_t address)169 inline int GetAllocationTagFromAddress(uint64_t address) {
170   return static_cast<int>(ExtractUnsignedBitfield64(59, 56, address));
171 }
172 
173 template <typename T>
AddressUntag(T address)174 T AddressUntag(T address) {
175   // Cast the address using a C-style cast. A reinterpret_cast would be
176   // appropriate, but it can't cast one integral type to another.
177   uint64_t bits = (uint64_t)address;
178   return (T)(bits & ~kAddressTagMask);
179 }
180 
181 // A callback function, called when a function has been intercepted if a
182 // BranchInterception entry exists in branch_interceptions. The address of
183 // the intercepted function is passed to the callback. For usage see
184 // BranchInterception.
185 using InterceptionCallback = std::function<void(uint64_t)>;
186 
187 class MetaDataDepot {
188  public:
189   class MetaDataMTE {
190    public:
MetaDataMTE(int tag)191     explicit MetaDataMTE(int tag) : tag_(tag) {}
192 
GetTag() const193     int GetTag() const { return tag_; }
SetTag(int tag)194     void SetTag(int tag) {
195       VIXL_ASSERT(IsUint4(tag));
196       tag_ = tag;
197     }
198 
IsActive()199     static bool IsActive() { return is_active; }
SetActive(bool value)200     static void SetActive(bool value) { is_active = value; }
201 
202    private:
203     static bool is_active;
204     int16_t tag_;
205 
206     friend class MetaDataDepot;
207   };
208 
209   // Generate a key for metadata recording from a untagged address.
210   template <typename T>
GenerateMTEkey(T address) const211   uint64_t GenerateMTEkey(T address) const {
212     // Cast the address using a C-style cast. A reinterpret_cast would be
213     // appropriate, but it can't cast one integral type to another.
214     return (uint64_t)(AddressUntag(address)) >> kMTETagGranuleInBytesLog2;
215   }
216 
217   template <typename R, typename T>
GetAttribute(T map, uint64_t key)218   R GetAttribute(T map, uint64_t key) {
219     auto pair = map->find(key);
220     R value = (pair == map->end()) ? nullptr : &pair->second;
221     return value;
222   }
223 
224   template <typename T>
GetMTETag(T address, Instruction const* pc = nullptr)225   int GetMTETag(T address, Instruction const* pc = nullptr) {
226     uint64_t key = GenerateMTEkey(address);
227     MetaDataMTE* m = GetAttribute<MetaDataMTE*>(&metadata_mte_, key);
228 
229     if (!m) {
230       std::stringstream sstream;
231       sstream << std::hex << "MTE ERROR : instruction at 0x"
232               << reinterpret_cast<uint64_t>(pc)
233               << " touched a unallocated memory location 0x"
234               << (uint64_t)(address) << ".\n";
235       VIXL_ABORT_WITH_MSG(sstream.str().c_str());
236     }
237 
238     return m->GetTag();
239   }
240 
241   template <typename T>
SetMTETag(T address, int tag, Instruction const* pc = nullptr)242   void SetMTETag(T address, int tag, Instruction const* pc = nullptr) {
243     VIXL_ASSERT(IsAligned((uintptr_t)address, kMTETagGranuleInBytes));
244     uint64_t key = GenerateMTEkey(address);
245     MetaDataMTE* m = GetAttribute<MetaDataMTE*>(&metadata_mte_, key);
246 
247     if (!m) {
248       metadata_mte_.insert({key, MetaDataMTE(tag)});
249     } else {
250       // Overwrite
251       if (m->GetTag() == tag) {
252         std::stringstream sstream;
253         sstream << std::hex << "MTE WARNING : instruction at 0x"
254                 << reinterpret_cast<uint64_t>(pc)
255                 << ", the same tag is assigned to the address 0x"
256                 << (uint64_t)(address) << ".\n";
257         VIXL_WARNING(sstream.str().c_str());
258       }
259       m->SetTag(tag);
260     }
261   }
262 
263   template <typename T>
CleanMTETag(T address)264   size_t CleanMTETag(T address) {
265     VIXL_ASSERT(
266         IsAligned(reinterpret_cast<uintptr_t>(address), kMTETagGranuleInBytes));
267     uint64_t key = GenerateMTEkey(address);
268     return metadata_mte_.erase(key);
269   }
270 
GetTotalCountMTE()271   size_t GetTotalCountMTE() { return metadata_mte_.size(); }
272 
273   // A pure virtual struct that allows the templated BranchInterception struct
274   // to be stored. For more information see BranchInterception.
275   struct BranchInterceptionAbstract {
~BranchInterceptionAbstractvixl::aarch64::MetaDataDepot::BranchInterceptionAbstract276     virtual ~BranchInterceptionAbstract() {}
277     // Call the callback_ if one exists, otherwise do a RuntimeCall.
278     virtual void operator()(Simulator* simulator) const = 0;
279   };
280 
281   // An entry denoting a function to intercept when branched to during
282   // simulator execution. When a function is intercepted the callback will be
283   // called if one exists otherwise the function will be passed to
284   // RuntimeCall.
285   template <typename R, typename... P>
286   struct BranchInterception : public BranchInterceptionAbstract {
BranchInterceptionvixl::aarch64::MetaDataDepot::BranchInterception287     BranchInterception(R (*function)(P...),
288                        InterceptionCallback callback = nullptr)
289         : function_(function), callback_(callback) {}
290 
291     void operator()(Simulator* simulator) const VIXL_OVERRIDE;
292 
293    private:
294     // Pointer to the function that will be intercepted.
295     R (*function_)(P...);
296 
297     // Function to be called instead of function_
298     InterceptionCallback callback_;
299   };
300 
301   // Register a new BranchInterception object. If 'function' is branched to
302   // (e.g: "blr function") in the future; instead, if provided, 'callback' will
303   // be called otherwise a runtime call will be performed on 'function'.
304   //
305   // For example: this can be used to always perform runtime calls on
306   // non-AArch64 functions without using the macroassembler.
307   //
308   // Note: only unconditional branches to registers are currently supported to
309   // be intercepted, e.g: "br"/"blr".
310   //
311   // TODO: support intercepting other branch types.
312   template <typename R, typename... P>
RegisterBranchInterception(R (function)P...), InterceptionCallback callback = nullptr)313   void RegisterBranchInterception(R (*function)(P...),
314                                   InterceptionCallback callback = nullptr) {
315     uintptr_t addr = reinterpret_cast<uintptr_t>(function);
316     std::unique_ptr<BranchInterceptionAbstract> intercept =
317         std::make_unique<BranchInterception<R, P...>>(function, callback);
318     branch_interceptions_.insert(std::make_pair(addr, std::move(intercept)));
319   }
320 
321   // Search for branch interceptions to the branch_target address; If one is
322   // found return it otherwise return nullptr.
FindBranchInterception(uint64_t branch_target)323   BranchInterceptionAbstract* FindBranchInterception(uint64_t branch_target) {
324     // Check for interceptions to the target address, if one is found, call it.
325     auto search = branch_interceptions_.find(branch_target);
326     if (search != branch_interceptions_.end()) {
327       return search->second.get();
328     } else {
329       return nullptr;
330     }
331   }
332 
ResetState()333   void ResetState() { branch_interceptions_.clear(); }
334 
335  private:
336   // Tag recording of each allocated memory in the tag-granule.
337   std::unordered_map<uint64_t, class MetaDataMTE> metadata_mte_;
338 
339   // Store a map of addresses to be intercepted and their corresponding branch
340   // interception object, see 'BranchInterception'.
341   std::unordered_map<uintptr_t, std::unique_ptr<BranchInterceptionAbstract>>
342       branch_interceptions_;
343 };
344 
345 
346 // Representation of memory, with typed getters and setters for access.
347 class Memory {
348  public:
Memory(SimStack::Allocated stack)349   explicit Memory(SimStack::Allocated stack) : stack_(std::move(stack)) {
350     metadata_depot_ = nullptr;
351   }
352 
GetStack()353   const SimStack::Allocated& GetStack() { return stack_; }
354 
355   template <typename A>
IsMTETagsMatched(A address, Instruction const* pc = nullptr) const356   bool IsMTETagsMatched(A address, Instruction const* pc = nullptr) const {
357     if (MetaDataDepot::MetaDataMTE::IsActive()) {
358       // Cast the address using a C-style cast. A reinterpret_cast would be
359       // appropriate, but it can't cast one integral type to another.
360       uint64_t addr = (uint64_t)address;
361       int pointer_tag = GetAllocationTagFromAddress(addr);
362       int memory_tag = metadata_depot_->GetMTETag(AddressUntag(addr), pc);
363       return pointer_tag == memory_tag;
364     }
365     return true;
366   }
367 
368   template <typename T, typename A>
Read(A address, Instruction const* pc = nullptr) const369   T Read(A address, Instruction const* pc = nullptr) const {
370     T value;
371     VIXL_STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
372                        (sizeof(value) == 4) || (sizeof(value) == 8) ||
373                        (sizeof(value) == 16));
374     auto base = reinterpret_cast<const char*>(AddressUntag(address));
375     if (stack_.IsAccessInGuardRegion(base, sizeof(value))) {
376       VIXL_ABORT_WITH_MSG("Attempt to read from stack guard region");
377     }
378     if (!IsMTETagsMatched(address, pc)) {
379       VIXL_ABORT_WITH_MSG("Tag mismatch.");
380     }
381     memcpy(&value, base, sizeof(value));
382     return value;
383   }
384 
385   template <typename T, typename A>
Write(A address, T value, Instruction const* pc = nullptr) const386   void Write(A address, T value, Instruction const* pc = nullptr) const {
387     VIXL_STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
388                        (sizeof(value) == 4) || (sizeof(value) == 8) ||
389                        (sizeof(value) == 16));
390     auto base = reinterpret_cast<char*>(AddressUntag(address));
391     if (stack_.IsAccessInGuardRegion(base, sizeof(value))) {
392       VIXL_ABORT_WITH_MSG("Attempt to write to stack guard region");
393     }
394     if (!IsMTETagsMatched(address, pc)) {
395       VIXL_ABORT_WITH_MSG("Tag mismatch.");
396     }
397     memcpy(base, &value, sizeof(value));
398   }
399 
400   template <typename A>
ReadUint(int size_in_bytes, A address) const401   uint64_t ReadUint(int size_in_bytes, A address) const {
402     switch (size_in_bytes) {
403       case 1:
404         return Read<uint8_t>(address);
405       case 2:
406         return Read<uint16_t>(address);
407       case 4:
408         return Read<uint32_t>(address);
409       case 8:
410         return Read<uint64_t>(address);
411     }
412     VIXL_UNREACHABLE();
413     return 0;
414   }
415 
416   template <typename A>
ReadInt(int size_in_bytes, A address) const417   int64_t ReadInt(int size_in_bytes, A address) const {
418     switch (size_in_bytes) {
419       case 1:
420         return Read<int8_t>(address);
421       case 2:
422         return Read<int16_t>(address);
423       case 4:
424         return Read<int32_t>(address);
425       case 8:
426         return Read<int64_t>(address);
427     }
428     VIXL_UNREACHABLE();
429     return 0;
430   }
431 
432   template <typename A>
Write(int size_in_bytes, A address, uint64_t value) const433   void Write(int size_in_bytes, A address, uint64_t value) const {
434     switch (size_in_bytes) {
435       case 1:
436         return Write(address, static_cast<uint8_t>(value));
437       case 2:
438         return Write(address, static_cast<uint16_t>(value));
439       case 4:
440         return Write(address, static_cast<uint32_t>(value));
441       case 8:
442         return Write(address, value);
443     }
444     VIXL_UNREACHABLE();
445   }
446 
AppendMetaData(MetaDataDepot* metadata_depot)447   void AppendMetaData(MetaDataDepot* metadata_depot) {
448     VIXL_ASSERT(metadata_depot != nullptr);
449     VIXL_ASSERT(metadata_depot_ == nullptr);
450     metadata_depot_ = metadata_depot;
451   }
452 
453  private:
454   SimStack::Allocated stack_;
455   MetaDataDepot* metadata_depot_;
456 };
457 
458 // Represent a register (r0-r31, v0-v31, z0-z31, p0-p15).
459 template <unsigned kMaxSizeInBits>
460 class SimRegisterBase {
461  public:
462   static const unsigned kMaxSizeInBytes = kMaxSizeInBits / kBitsPerByte;
463   VIXL_STATIC_ASSERT((kMaxSizeInBytes * kBitsPerByte) == kMaxSizeInBits);
464 
SimRegisterBase()465   SimRegisterBase() : size_in_bytes_(kMaxSizeInBytes) { Clear(); }
466 
GetSizeInBits() const467   unsigned GetSizeInBits() const { return size_in_bytes_ * kBitsPerByte; }
GetSizeInBytes() const468   unsigned GetSizeInBytes() const { return size_in_bytes_; }
469 
SetSizeInBytes(unsigned size_in_bytes)470   void SetSizeInBytes(unsigned size_in_bytes) {
471     VIXL_ASSERT(size_in_bytes <= kMaxSizeInBytes);
472     size_in_bytes_ = size_in_bytes;
473   }
SetSizeInBits(unsigned size_in_bits)474   void SetSizeInBits(unsigned size_in_bits) {
475     VIXL_ASSERT(size_in_bits <= kMaxSizeInBits);
476     VIXL_ASSERT((size_in_bits % kBitsPerByte) == 0);
477     SetSizeInBytes(size_in_bits / kBitsPerByte);
478   }
479 
480   // Write the specified value. The value is zero-extended if necessary.
481   template <typename T>
Write(T new_value)482   void Write(T new_value) {
483     // All AArch64 registers are zero-extending.
484     if (sizeof(new_value) < GetSizeInBytes()) Clear();
485     WriteLane(new_value, 0);
486     NotifyRegisterWrite();
487   }
488   template <typename T>
489   VIXL_DEPRECATED("Write", void Set(T new_value)) {
490     Write(new_value);
491   }
492 
Clear()493   void Clear() {
494     memset(value_, 0, kMaxSizeInBytes);
495     NotifyRegisterWrite();
496   }
497 
498   // Insert a typed value into a register, leaving the rest of the register
499   // unchanged. The lane parameter indicates where in the register the value
500   // should be inserted, in the range [ 0, sizeof(value_) / sizeof(T) ), where
501   // 0 represents the least significant bits.
502   template <typename T>
Insert(int lane, T new_value)503   void Insert(int lane, T new_value) {
504     WriteLane(new_value, lane);
505     NotifyRegisterWrite();
506   }
507 
508   // Get the value as the specified type. The value is truncated if necessary.
509   template <typename T>
Get() const510   T Get() const {
511     return GetLane<T>(0);
512   }
513 
514   // Get the lane value as the specified type. The value is truncated if
515   // necessary.
516   template <typename T>
GetLane(int lane) const517   T GetLane(int lane) const {
518     T result;
519     ReadLane(&result, lane);
520     return result;
521   }
522   template <typename T>
523   VIXL_DEPRECATED("GetLane", T Get(int lane) const) {
524     return GetLane(lane);
525   }
526 
527   // Get the value of a specific bit, indexed from the least-significant bit of
528   // lane 0.
GetBit(int bit) const529   bool GetBit(int bit) const {
530     int bit_in_byte = bit % (sizeof(value_[0]) * kBitsPerByte);
531     int byte = bit / (sizeof(value_[0]) * kBitsPerByte);
532     return ((value_[byte] >> bit_in_byte) & 1) != 0;
533   }
534 
535   // Return a pointer to the raw, underlying byte array.
GetBytes() const536   const uint8_t* GetBytes() const { return value_; }
537 
538   // TODO: Make this return a map of updated bytes, so that we can highlight
539   // updated lanes for load-and-insert. (That never happens for scalar code, but
540   // NEON has some instructions that can update individual lanes.)
WrittenSinceLastLog() const541   bool WrittenSinceLastLog() const { return written_since_last_log_; }
542 
NotifyRegisterLogged()543   void NotifyRegisterLogged() { written_since_last_log_ = false; }
544 
545  protected:
546   uint8_t value_[kMaxSizeInBytes];
547 
548   unsigned size_in_bytes_;
549 
550   // Helpers to aid with register tracing.
551   bool written_since_last_log_;
552 
NotifyRegisterWrite()553   void NotifyRegisterWrite() { written_since_last_log_ = true; }
554 
555  private:
556   template <typename T>
ReadLane(T* dst, int lane) const557   void ReadLane(T* dst, int lane) const {
558     VIXL_ASSERT(lane >= 0);
559     VIXL_ASSERT((sizeof(*dst) + (lane * sizeof(*dst))) <= GetSizeInBytes());
560     memcpy(dst, &value_[lane * sizeof(*dst)], sizeof(*dst));
561   }
562 
563   template <typename T>
WriteLane(T src, int lane)564   void WriteLane(T src, int lane) {
565     VIXL_ASSERT(lane >= 0);
566     VIXL_ASSERT((sizeof(src) + (lane * sizeof(src))) <= GetSizeInBytes());
567     memcpy(&value_[lane * sizeof(src)], &src, sizeof(src));
568   }
569 
570   // The default ReadLane and WriteLane methods assume what we are copying is
571   // "trivially copyable" by using memcpy. We have to provide alternative
572   // implementations for SimFloat16 which cannot be copied this way.
573 
ReadLane(vixl::internal::SimFloat16* dst, int lane) const574   void ReadLane(vixl::internal::SimFloat16* dst, int lane) const {
575     uint16_t rawbits;
576     ReadLane(&rawbits, lane);
577     *dst = RawbitsToFloat16(rawbits);
578   }
579 
WriteLane(vixl::internal::SimFloat16 src, int lane)580   void WriteLane(vixl::internal::SimFloat16 src, int lane) {
581     WriteLane(Float16ToRawbits(src), lane);
582   }
583 };
584 
585 typedef SimRegisterBase<kXRegSize> SimRegister;      // r0-r31
586 typedef SimRegisterBase<kPRegMaxSize> SimPRegister;  // p0-p15
587 // FFR has the same format as a predicate register.
588 typedef SimPRegister SimFFRRegister;
589 
590 // v0-v31 and z0-z31
591 class SimVRegister : public SimRegisterBase<kZRegMaxSize> {
592  public:
SimVRegister()593   SimVRegister() : SimRegisterBase<kZRegMaxSize>(), accessed_as_z_(false) {}
594 
NotifyAccessAsZ()595   void NotifyAccessAsZ() { accessed_as_z_ = true; }
596 
NotifyRegisterLogged()597   void NotifyRegisterLogged() {
598     SimRegisterBase<kZRegMaxSize>::NotifyRegisterLogged();
599     accessed_as_z_ = false;
600   }
601 
AccessedAsZSinceLastLog() const602   bool AccessedAsZSinceLastLog() const { return accessed_as_z_; }
603 
604  private:
605   bool accessed_as_z_;
606 };
607 
608 // Representation of a SVE predicate register.
609 class LogicPRegister {
610  public:
LogicPRegister( SimPRegister& other)611   inline LogicPRegister(
612       SimPRegister& other)  // NOLINT(runtime/references)(runtime/explicit)
613       : register_(other) {}
614 
615   // Set a conveniently-sized block to 16 bits as the minimum predicate length
616   // is 16 bits and allow to be increased to multiples of 16 bits.
617   typedef uint16_t ChunkType;
618 
619   // Assign a bit into the end positon of the specified lane.
620   // The bit is zero-extended if necessary.
SetActive(VectorFormat vform, int lane_index, bool value)621   void SetActive(VectorFormat vform, int lane_index, bool value) {
622     int psize = LaneSizeInBytesFromFormat(vform);
623     int bit_index = lane_index * psize;
624     int byte_index = bit_index / kBitsPerByte;
625     int bit_offset = bit_index % kBitsPerByte;
626     uint8_t byte = register_.GetLane<uint8_t>(byte_index);
627     register_.Insert(byte_index, ZeroExtend(byte, bit_offset, psize, value));
628   }
629 
IsActive(VectorFormat vform, int lane_index) const630   bool IsActive(VectorFormat vform, int lane_index) const {
631     int psize = LaneSizeInBytesFromFormat(vform);
632     int bit_index = lane_index * psize;
633     int byte_index = bit_index / kBitsPerByte;
634     int bit_offset = bit_index % kBitsPerByte;
635     uint8_t byte = register_.GetLane<uint8_t>(byte_index);
636     return ExtractBit(byte, bit_offset);
637   }
638 
639   // The accessors for bulk processing.
GetChunkCount() const640   int GetChunkCount() const {
641     VIXL_ASSERT((register_.GetSizeInBytes() % sizeof(ChunkType)) == 0);
642     return register_.GetSizeInBytes() / sizeof(ChunkType);
643   }
644 
GetChunk(int lane) const645   ChunkType GetChunk(int lane) const { return GetActiveMask<ChunkType>(lane); }
646 
SetChunk(int lane, ChunkType new_value)647   void SetChunk(int lane, ChunkType new_value) {
648     SetActiveMask(lane, new_value);
649   }
650 
SetAllBits()651   void SetAllBits() {
652     int chunk_size = sizeof(ChunkType) * kBitsPerByte;
653     ChunkType bits = GetUintMask(chunk_size);
654     for (int lane = 0;
655          lane < (static_cast<int>(register_.GetSizeInBits() / chunk_size));
656          lane++) {
657       SetChunk(lane, bits);
658     }
659   }
660 
661   template <typename T>
GetActiveMask(int lane) const662   T GetActiveMask(int lane) const {
663     return register_.GetLane<T>(lane);
664   }
665 
666   template <typename T>
SetActiveMask(int lane, T new_value)667   void SetActiveMask(int lane, T new_value) {
668     register_.Insert<T>(lane, new_value);
669   }
670 
Clear()671   void Clear() { register_.Clear(); }
672 
Aliases(const LogicPRegister& other) const673   bool Aliases(const LogicPRegister& other) const {
674     return &register_ == &other.register_;
675   }
676 
677  private:
678   // The bit assignment is zero-extended to fill the size of predicate element.
ZeroExtend(uint8_t byte, int index, int psize, bool value)679   uint8_t ZeroExtend(uint8_t byte, int index, int psize, bool value) {
680     VIXL_ASSERT(index >= 0);
681     VIXL_ASSERT(index + psize <= kBitsPerByte);
682     int bits = value ? 1 : 0;
683     switch (psize) {
684       case 1:
685         AssignBit(byte, index, bits);
686         break;
687       case 2:
688         AssignBits(byte, index, 0x03, bits);
689         break;
690       case 4:
691         AssignBits(byte, index, 0x0f, bits);
692         break;
693       case 8:
694         AssignBits(byte, index, 0xff, bits);
695         break;
696       default:
697         VIXL_UNREACHABLE();
698         return 0;
699     }
700     return byte;
701   }
702 
703   SimPRegister& register_;
704 };
705 
706 // Representation of a vector register, with typed getters and setters for lanes
707 // and additional information to represent lane state.
708 class LogicVRegister {
709  public:
LogicVRegister( SimVRegister& other)710   inline LogicVRegister(
711       SimVRegister& other)  // NOLINT(runtime/references)(runtime/explicit)
712       : register_(other) {
713     for (size_t i = 0; i < ArrayLength(saturated_); i++) {
714       saturated_[i] = kNotSaturated;
715     }
716     for (size_t i = 0; i < ArrayLength(round_); i++) {
717       round_[i] = 0;
718     }
719   }
720 
Int(VectorFormat vform, int index) const721   int64_t Int(VectorFormat vform, int index) const {
722     if (IsSVEFormat(vform)) register_.NotifyAccessAsZ();
723     int64_t element;
724     switch (LaneSizeInBitsFromFormat(vform)) {
725       case 8:
726         element = register_.GetLane<int8_t>(index);
727         break;
728       case 16:
729         element = register_.GetLane<int16_t>(index);
730         break;
731       case 32:
732         element = register_.GetLane<int32_t>(index);
733         break;
734       case 64:
735         element = register_.GetLane<int64_t>(index);
736         break;
737       default:
738         VIXL_UNREACHABLE();
739         return 0;
740     }
741     return element;
742   }
743 
Uint(VectorFormat vform, int index) const744   uint64_t Uint(VectorFormat vform, int index) const {
745     if (IsSVEFormat(vform)) register_.NotifyAccessAsZ();
746     uint64_t element;
747     switch (LaneSizeInBitsFromFormat(vform)) {
748       case 8:
749         element = register_.GetLane<uint8_t>(index);
750         break;
751       case 16:
752         element = register_.GetLane<uint16_t>(index);
753         break;
754       case 32:
755         element = register_.GetLane<uint32_t>(index);
756         break;
757       case 64:
758         element = register_.GetLane<uint64_t>(index);
759         break;
760       default:
761         VIXL_UNREACHABLE();
762         return 0;
763     }
764     return element;
765   }
766 
UintArray(VectorFormat vform, uint64_t* dst) const767   int UintArray(VectorFormat vform, uint64_t* dst) const {
768     for (int i = 0; i < LaneCountFromFormat(vform); i++) {
769       dst[i] = Uint(vform, i);
770     }
771     return LaneCountFromFormat(vform);
772   }
773 
UintLeftJustified(VectorFormat vform, int index) const774   uint64_t UintLeftJustified(VectorFormat vform, int index) const {
775     return Uint(vform, index) << (64 - LaneSizeInBitsFromFormat(vform));
776   }
777 
IntLeftJustified(VectorFormat vform, int index) const778   int64_t IntLeftJustified(VectorFormat vform, int index) const {
779     uint64_t value = UintLeftJustified(vform, index);
780     int64_t result;
781     memcpy(&result, &value, sizeof(result));
782     return result;
783   }
784 
SetInt(VectorFormat vform, int index, int64_t value) const785   void SetInt(VectorFormat vform, int index, int64_t value) const {
786     if (IsSVEFormat(vform)) register_.NotifyAccessAsZ();
787     switch (LaneSizeInBitsFromFormat(vform)) {
788       case 8:
789         register_.Insert(index, static_cast<int8_t>(value));
790         break;
791       case 16:
792         register_.Insert(index, static_cast<int16_t>(value));
793         break;
794       case 32:
795         register_.Insert(index, static_cast<int32_t>(value));
796         break;
797       case 64:
798         register_.Insert(index, static_cast<int64_t>(value));
799         break;
800       default:
801         VIXL_UNREACHABLE();
802         return;
803     }
804   }
805 
SetIntArray(VectorFormat vform, const int64_t* src) const806   void SetIntArray(VectorFormat vform, const int64_t* src) const {
807     ClearForWrite(vform);
808     for (int i = 0; i < LaneCountFromFormat(vform); i++) {
809       SetInt(vform, i, src[i]);
810     }
811   }
812 
SetUint(VectorFormat vform, int index, uint64_t value) const813   void SetUint(VectorFormat vform, int index, uint64_t value) const {
814     if (IsSVEFormat(vform)) register_.NotifyAccessAsZ();
815     switch (LaneSizeInBitsFromFormat(vform)) {
816       case 8:
817         register_.Insert(index, static_cast<uint8_t>(value));
818         break;
819       case 16:
820         register_.Insert(index, static_cast<uint16_t>(value));
821         break;
822       case 32:
823         register_.Insert(index, static_cast<uint32_t>(value));
824         break;
825       case 64:
826         register_.Insert(index, static_cast<uint64_t>(value));
827         break;
828       default:
829         VIXL_UNREACHABLE();
830         return;
831     }
832   }
833 
SetUintArray(VectorFormat vform, const uint64_t* src) const834   void SetUintArray(VectorFormat vform, const uint64_t* src) const {
835     ClearForWrite(vform);
836     for (int i = 0; i < LaneCountFromFormat(vform); i++) {
837       SetUint(vform, i, src[i]);
838     }
839   }
840 
841   template <typename T>
Float(int index) const842   T Float(int index) const {
843     return register_.GetLane<T>(index);
844   }
845 
846   template <typename T>
SetFloat(int index, T value) const847   void SetFloat(int index, T value) const {
848     register_.Insert(index, value);
849   }
850 
851   template <typename T>
SetFloat(VectorFormat vform, int index, T value) const852   void SetFloat(VectorFormat vform, int index, T value) const {
853     if (IsSVEFormat(vform)) register_.NotifyAccessAsZ();
854     register_.Insert(index, value);
855   }
856 
Clear()857   void Clear() { register_.Clear(); }
858 
859   // When setting a result in a register larger than the result itself, the top
860   // bits of the register must be cleared.
ClearForWrite(VectorFormat vform) const861   void ClearForWrite(VectorFormat vform) const {
862     // SVE destinations write whole registers, so we have nothing to clear.
863     if (IsSVEFormat(vform)) return;
864 
865     unsigned size = RegisterSizeInBytesFromFormat(vform);
866     for (unsigned i = size; i < register_.GetSizeInBytes(); i++) {
867       SetUint(kFormat16B, i, 0);
868     }
869   }
870 
871   // Saturation state for each lane of a vector.
872   enum Saturation {
873     kNotSaturated = 0,
874     kSignedSatPositive = 1 << 0,
875     kSignedSatNegative = 1 << 1,
876     kSignedSatMask = kSignedSatPositive | kSignedSatNegative,
877     kSignedSatUndefined = kSignedSatMask,
878     kUnsignedSatPositive = 1 << 2,
879     kUnsignedSatNegative = 1 << 3,
880     kUnsignedSatMask = kUnsignedSatPositive | kUnsignedSatNegative,
881     kUnsignedSatUndefined = kUnsignedSatMask
882   };
883 
884   // Getters for saturation state.
GetSignedSaturation(int index)885   Saturation GetSignedSaturation(int index) {
886     return static_cast<Saturation>(saturated_[index] & kSignedSatMask);
887   }
888 
GetUnsignedSaturation(int index)889   Saturation GetUnsignedSaturation(int index) {
890     return static_cast<Saturation>(saturated_[index] & kUnsignedSatMask);
891   }
892 
893   // Setters for saturation state.
ClearSat(int index)894   void ClearSat(int index) { saturated_[index] = kNotSaturated; }
895 
SetSignedSat(int index, bool positive)896   void SetSignedSat(int index, bool positive) {
897     SetSatFlag(index, positive ? kSignedSatPositive : kSignedSatNegative);
898   }
899 
SetUnsignedSat(int index, bool positive)900   void SetUnsignedSat(int index, bool positive) {
901     SetSatFlag(index, positive ? kUnsignedSatPositive : kUnsignedSatNegative);
902   }
903 
SetSatFlag(int index, Saturation sat)904   void SetSatFlag(int index, Saturation sat) {
905     saturated_[index] = static_cast<Saturation>(saturated_[index] | sat);
906     VIXL_ASSERT((sat & kUnsignedSatMask) != kUnsignedSatUndefined);
907     VIXL_ASSERT((sat & kSignedSatMask) != kSignedSatUndefined);
908   }
909 
910   // Saturate lanes of a vector based on saturation state.
SignedSaturate(VectorFormat vform)911   LogicVRegister& SignedSaturate(VectorFormat vform) {
912     for (int i = 0; i < LaneCountFromFormat(vform); i++) {
913       Saturation sat = GetSignedSaturation(i);
914       if (sat == kSignedSatPositive) {
915         SetInt(vform, i, MaxIntFromFormat(vform));
916       } else if (sat == kSignedSatNegative) {
917         SetInt(vform, i, MinIntFromFormat(vform));
918       }
919     }
920     return *this;
921   }
922 
UnsignedSaturate(VectorFormat vform)923   LogicVRegister& UnsignedSaturate(VectorFormat vform) {
924     for (int i = 0; i < LaneCountFromFormat(vform); i++) {
925       Saturation sat = GetUnsignedSaturation(i);
926       if (sat == kUnsignedSatPositive) {
927         SetUint(vform, i, MaxUintFromFormat(vform));
928       } else if (sat == kUnsignedSatNegative) {
929         SetUint(vform, i, 0);
930       }
931     }
932     return *this;
933   }
934 
935   // Getter for rounding state.
GetRounding(int index)936   bool GetRounding(int index) { return round_[index]; }
937 
938   // Setter for rounding state.
SetRounding(int index, bool round)939   void SetRounding(int index, bool round) { round_[index] = round; }
940 
941   // Round lanes of a vector based on rounding state.
Round(VectorFormat vform)942   LogicVRegister& Round(VectorFormat vform) {
943     for (int i = 0; i < LaneCountFromFormat(vform); i++) {
944       SetUint(vform, i, Uint(vform, i) + (GetRounding(i) ? 1 : 0));
945     }
946     return *this;
947   }
948 
949   // Unsigned halve lanes of a vector, and use the saturation state to set the
950   // top bit.
Uhalve(VectorFormat vform)951   LogicVRegister& Uhalve(VectorFormat vform) {
952     for (int i = 0; i < LaneCountFromFormat(vform); i++) {
953       uint64_t val = Uint(vform, i);
954       SetRounding(i, (val & 1) == 1);
955       val >>= 1;
956       if (GetUnsignedSaturation(i) != kNotSaturated) {
957         // If the operation causes unsigned saturation, the bit shifted into the
958         // most significant bit must be set.
959         val |= (MaxUintFromFormat(vform) >> 1) + 1;
960       }
961       SetInt(vform, i, val);
962     }
963     return *this;
964   }
965 
966   // Signed halve lanes of a vector, and use the carry state to set the top bit.
Halve(VectorFormat vform)967   LogicVRegister& Halve(VectorFormat vform) {
968     for (int i = 0; i < LaneCountFromFormat(vform); i++) {
969       int64_t val = Int(vform, i);
970       SetRounding(i, (val & 1) == 1);
971       val = ExtractSignedBitfield64(63, 1, val);  // >>= 1
972       if (GetSignedSaturation(i) == kNotSaturated) {
973         SetInt(vform, i, val);
974       } else {
975         // If the operation causes signed saturation, the sign bit must be
976         // inverted.
977         uint64_t uval = static_cast<uint64_t>(val);
978         SetUint(vform, i, uval ^ ((MaxUintFromFormat(vform) >> 1) + 1));
979       }
980     }
981     return *this;
982   }
983 
LaneCountFromFormat(VectorFormat vform) const984   int LaneCountFromFormat(VectorFormat vform) const {
985     if (IsSVEFormat(vform)) {
986       return register_.GetSizeInBits() / LaneSizeInBitsFromFormat(vform);
987     } else {
988       return vixl::aarch64::LaneCountFromFormat(vform);
989     }
990   }
991 
992  private:
993   SimVRegister& register_;
994 
995   // Allocate one saturation state entry per lane; largest register is type Q,
996   // and lanes can be a minimum of one byte wide.
997   Saturation saturated_[kZRegMaxSizeInBytes];
998 
999   // Allocate one rounding state entry per lane.
1000   bool round_[kZRegMaxSizeInBytes];
1001 };
1002 
1003 // Represent an SVE addressing mode and abstract per-lane address generation to
1004 // make iteration easy.
1005 //
1006 // Contiguous accesses are described with a simple base address, the memory
1007 // occupied by each lane (`SetMsizeInBytesLog2()`) and the number of elements in
1008 // each struct (`SetRegCount()`).
1009 //
1010 // Scatter-gather accesses also require a SimVRegister and information about how
1011 // to extract lanes from it.
1012 class LogicSVEAddressVector {
1013  public:
1014   // scalar-plus-scalar
1015   // scalar-plus-immediate
LogicSVEAddressVector(uint64_t base)1016   explicit LogicSVEAddressVector(uint64_t base)
1017       : base_(base),
1018         msize_in_bytes_log2_(kUnknownMsizeInBytesLog2),
1019         reg_count_(1),
1020         vector_(NULL),
1021         vector_form_(kFormatUndefined),
1022         vector_mod_(NO_SVE_OFFSET_MODIFIER),
1023         vector_shift_(0) {}
1024 
1025   // scalar-plus-vector
1026   // vector-plus-immediate
1027   //    `base` should be the constant used for each element. That is, the value
1028   //    of `xn`, or `#<imm>`.
1029   //    `vector` should be the SimVRegister with offsets for each element. The
1030   //    vector format must be specified; SVE scatter/gather accesses typically
1031   //    support both 32-bit and 64-bit addressing.
1032   //
1033   //    `mod` and `shift` correspond to the modifiers applied to each element in
1034   //    scalar-plus-vector forms, such as those used for unpacking and
1035   //    sign-extension. They are not used for vector-plus-immediate.
LogicSVEAddressVector(uint64_t base, const SimVRegister* vector, VectorFormat vform, SVEOffsetModifier mod = NO_SVE_OFFSET_MODIFIER, int shift = 0)1036   LogicSVEAddressVector(uint64_t base,
1037                         const SimVRegister* vector,
1038                         VectorFormat vform,
1039                         SVEOffsetModifier mod = NO_SVE_OFFSET_MODIFIER,
1040                         int shift = 0)
1041       : base_(base),
1042         msize_in_bytes_log2_(kUnknownMsizeInBytesLog2),
1043         reg_count_(1),
1044         vector_(vector),
1045         vector_form_(vform),
1046         vector_mod_(mod),
1047         vector_shift_(shift) {}
1048 
1049   // Set `msize` -- the memory occupied by each lane -- for address
1050   // calculations.
SetMsizeInBytesLog2(int msize_in_bytes_log2)1051   void SetMsizeInBytesLog2(int msize_in_bytes_log2) {
1052     VIXL_ASSERT(msize_in_bytes_log2 >= static_cast<int>(kBRegSizeInBytesLog2));
1053     VIXL_ASSERT(msize_in_bytes_log2 <= static_cast<int>(kDRegSizeInBytesLog2));
1054     msize_in_bytes_log2_ = msize_in_bytes_log2;
1055   }
1056 
HasMsize() const1057   bool HasMsize() const {
1058     return msize_in_bytes_log2_ != kUnknownMsizeInBytesLog2;
1059   }
1060 
GetMsizeInBytesLog2() const1061   int GetMsizeInBytesLog2() const {
1062     VIXL_ASSERT(HasMsize());
1063     return msize_in_bytes_log2_;
1064   }
GetMsizeInBitsLog2() const1065   int GetMsizeInBitsLog2() const {
1066     return GetMsizeInBytesLog2() + kBitsPerByteLog2;
1067   }
1068 
GetMsizeInBytes() const1069   int GetMsizeInBytes() const { return 1 << GetMsizeInBytesLog2(); }
GetMsizeInBits() const1070   int GetMsizeInBits() const { return 1 << GetMsizeInBitsLog2(); }
1071 
SetRegCount(int reg_count)1072   void SetRegCount(int reg_count) {
1073     VIXL_ASSERT(reg_count >= 1);  // E.g. ld1/st1
1074     VIXL_ASSERT(reg_count <= 4);  // E.g. ld4/st4
1075     reg_count_ = reg_count;
1076   }
1077 
GetRegCount() const1078   int GetRegCount() const { return reg_count_; }
1079 
1080   // Full per-element address calculation for structured accesses.
1081   //
1082   // Note that the register number argument (`reg`) is zero-based.
GetElementAddress(int lane, int reg) const1083   uint64_t GetElementAddress(int lane, int reg) const {
1084     VIXL_ASSERT(reg < GetRegCount());
1085     // Individual structures are always contiguous in memory, so this
1086     // implementation works for both contiguous and scatter-gather addressing.
1087     return GetStructAddress(lane) + (reg * GetMsizeInBytes());
1088   }
1089 
1090   // Full per-struct address calculation for structured accesses.
1091   uint64_t GetStructAddress(int lane) const;
1092 
1093   bool IsContiguous() const { return vector_ == NULL; }
1094   bool IsScatterGather() const { return !IsContiguous(); }
1095 
1096  private:
1097   uint64_t base_;
1098   int msize_in_bytes_log2_;
1099   int reg_count_;
1100 
1101   const SimVRegister* vector_;
1102   VectorFormat vector_form_;
1103   SVEOffsetModifier vector_mod_;
1104   int vector_shift_;
1105 
1106   static const int kUnknownMsizeInBytesLog2 = -1;
1107 };
1108 
1109 // The proper way to initialize a simulated system register (such as NZCV) is as
1110 // follows:
1111 //  SimSystemRegister nzcv = SimSystemRegister::DefaultValueFor(NZCV);
1112 class SimSystemRegister {
1113  public:
1114   // The default constructor represents a register which has no writable bits.
1115   // It is not possible to set its value to anything other than 0.
1116   SimSystemRegister() : value_(0), write_ignore_mask_(0xffffffff) {}
1117 
1118   uint32_t GetRawValue() const { return value_; }
1119   VIXL_DEPRECATED("GetRawValue", uint32_t RawValue() const) {
1120     return GetRawValue();
1121   }
1122 
1123   void SetRawValue(uint32_t new_value) {
1124     value_ = (value_ & write_ignore_mask_) | (new_value & ~write_ignore_mask_);
1125   }
1126 
1127   uint32_t ExtractBits(int msb, int lsb) const {
1128     return ExtractUnsignedBitfield32(msb, lsb, value_);
1129   }
1130   VIXL_DEPRECATED("ExtractBits", uint32_t Bits(int msb, int lsb) const) {
1131     return ExtractBits(msb, lsb);
1132   }
1133 
1134   int32_t ExtractSignedBits(int msb, int lsb) const {
1135     return ExtractSignedBitfield32(msb, lsb, value_);
1136   }
1137   VIXL_DEPRECATED("ExtractSignedBits",
1138                   int32_t SignedBits(int msb, int lsb) const) {
1139     return ExtractSignedBits(msb, lsb);
1140   }
1141 
1142   void SetBits(int msb, int lsb, uint32_t bits);
1143 
1144   // Default system register values.
1145   static SimSystemRegister DefaultValueFor(SystemRegister id);
1146 
1147 #define DEFINE_GETTER(Name, HighBit, LowBit, Func)                            \
1148   uint32_t Get##Name() const { return this->Func(HighBit, LowBit); }          \
1149   VIXL_DEPRECATED("Get" #Name, uint32_t Name() const) { return Get##Name(); } \
1150   void Set##Name(uint32_t bits) { SetBits(HighBit, LowBit, bits); }
1151 #define DEFINE_WRITE_IGNORE_MASK(Name, Mask) \
1152   static const uint32_t Name##WriteIgnoreMask = ~static_cast<uint32_t>(Mask);
1153 
1154   SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER, DEFINE_WRITE_IGNORE_MASK)
1155 
1156 #undef DEFINE_ZERO_BITS
1157 #undef DEFINE_GETTER
1158 
1159  protected:
1160   // Most system registers only implement a few of the bits in the word. Other
1161   // bits are "read-as-zero, write-ignored". The write_ignore_mask argument
1162   // describes the bits which are not modifiable.
1163   SimSystemRegister(uint32_t value, uint32_t write_ignore_mask)
1164       : value_(value), write_ignore_mask_(write_ignore_mask) {}
1165 
1166   uint32_t value_;
1167   uint32_t write_ignore_mask_;
1168 };
1169 
1170 
1171 class SimExclusiveLocalMonitor {
1172  public:
1173   SimExclusiveLocalMonitor() : kSkipClearProbability(8), seed_(0x87654321) {
1174     Clear();
1175   }
1176 
1177   // Clear the exclusive monitor (like clrex).
1178   void Clear() {
1179     address_ = 0;
1180     size_ = 0;
1181   }
1182 
1183   // Clear the exclusive monitor most of the time.
1184   void MaybeClear() {
1185     if ((seed_ % kSkipClearProbability) != 0) {
1186       Clear();
1187     }
1188 
1189     // Advance seed_ using a simple linear congruential generator.
1190     seed_ = (seed_ * 48271) % 2147483647;
1191   }
1192 
1193   // Mark the address range for exclusive access (like load-exclusive).
1194   void MarkExclusive(uint64_t address, size_t size) {
1195     address_ = address;
1196     size_ = size;
1197   }
1198 
1199   // Return true if the address range is marked (like store-exclusive).
1200   // This helper doesn't implicitly clear the monitor.
1201   bool IsExclusive(uint64_t address, size_t size) {
1202     VIXL_ASSERT(size > 0);
1203     // Be pedantic: Require both the address and the size to match.
1204     return (size == size_) && (address == address_);
1205   }
1206 
1207  private:
1208   uint64_t address_;
1209   size_t size_;
1210 
1211   const int kSkipClearProbability;
1212   uint32_t seed_;
1213 };
1214 
1215 
1216 // We can't accurate simulate the global monitor since it depends on external
1217 // influences. Instead, this implementation occasionally causes accesses to
1218 // fail, according to kPassProbability.
1219 class SimExclusiveGlobalMonitor {
1220  public:
SimExclusiveGlobalMonitor()1221   SimExclusiveGlobalMonitor() : kPassProbability(8), seed_(0x87654321) {}
1222 
IsExclusive(uint64_t address, size_t size)1223   bool IsExclusive(uint64_t address, size_t size) {
1224     USE(address, size);
1225 
1226     bool pass = (seed_ % kPassProbability) != 0;
1227     // Advance seed_ using a simple linear congruential generator.
1228     seed_ = (seed_ * 48271) % 2147483647;
1229     return pass;
1230   }
1231 
1232  private:
1233   const int kPassProbability;
1234   uint32_t seed_;
1235 };
1236 
1237 
1238 class Debugger;
1239 
1240 
1241 class Simulator : public DecoderVisitor {
1242  public:
1243 #ifndef PANDA_BUILD
1244   explicit Simulator(Decoder* decoder,
1245                      FILE* stream = stdout,
1246                      SimStack::Allocated stack = SimStack().Allocate());
1247 #else
1248   explicit Simulator(Decoder* decoder,
1249                      FILE* stream = stdout,
1250                      SimStack::Allocated stack = SimStack().Allocate()) = delete;
1251   Simulator(PandaAllocator* allocator,
1252             Decoder* decoder,
1253             SimStack::Allocated stack,
1254             FILE* stream = stdout);
1255 #endif
1256   ~Simulator();
1257 
1258 #ifdef PANDA_BUILD
GetAllocator() const1259   AllocatorWrapper GetAllocator() const {
1260     return allocator_;
1261   }
1262 #endif
1263 
1264   void ResetState();
1265 
1266   // Run the simulator.
1267   virtual void Run();
1268   void RunFrom(const Instruction* first);
1269 
1270 
1271 #if defined(VIXL_HAS_ABI_SUPPORT) && __cplusplus >= 201103L && \
1272     (defined(__clang__) || GCC_VERSION_OR_NEWER(4, 9, 1))
1273   // Templated `RunFrom` version taking care of passing arguments and returning
1274   // the result value.
1275   // This allows code like:
1276   //    int32_t res = simulator.RunFrom<int32_t, int32_t>(GenerateCode(),
1277   //                                                      0x123);
1278   // It requires VIXL's ABI features, and C++11 or greater.
1279   // Also, the initialisation of tuples is incorrect in GCC before 4.9.1:
1280   // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51253
1281   template <typename R, typename... P>
RunFrom(const Instruction* code, P... arguments)1282   R RunFrom(const Instruction* code, P... arguments) {
1283     return RunFromStructHelper<R, P...>::Wrapper(this, code, arguments...);
1284   }
1285 
1286   template <typename R, typename... P>
1287   struct RunFromStructHelper {
Wrappervixl::aarch64::Simulator::RunFromStructHelper1288     static R Wrapper(Simulator* simulator,
1289                      const Instruction* code,
1290                      P... arguments) {
1291       ABI abi;
1292       std::tuple<P...> unused_tuple{
1293           // TODO: We currently do not support arguments passed on the stack. We
1294           // could do so by using `WriteGenericOperand()` here, but may need to
1295           // add features to handle situations where the stack is or is not set
1296           // up.
1297           (simulator->WriteCPURegister(abi.GetNextParameterGenericOperand<P>()
1298                                            .GetCPURegister(),
1299                                        arguments),
1300            arguments)...};
1301       simulator->RunFrom(code);
1302       return simulator->ReadGenericOperand<R>(abi.GetReturnGenericOperand<R>());
1303     }
1304   };
1305 
1306   // Partial specialization when the return type is `void`.
1307   template <typename... P>
1308   struct RunFromStructHelper<void, P...> {
Wrappervixl::aarch64::Simulator::RunFromStructHelper1309     static void Wrapper(Simulator* simulator,
1310                         const Instruction* code,
1311                         P... arguments) {
1312       ABI abi;
1313       std::tuple<P...> unused_tuple{
1314           // TODO: We currently do not support arguments passed on the stack. We
1315           // could do so by using `WriteGenericOperand()` here, but may need to
1316           // add features to handle situations where the stack is or is not set
1317           // up.
1318           (simulator->WriteCPURegister(abi.GetNextParameterGenericOperand<P>()
1319                                            .GetCPURegister(),
1320                                        arguments),
1321            arguments)...};
1322       simulator->RunFrom(code);
1323     }
1324   };
1325 #endif
1326 
1327   // Execution ends when the PC hits this address.
1328   static const Instruction* kEndOfSimAddress;
1329 
1330   // Simulation helpers.
IsSimulationFinished() const1331   bool IsSimulationFinished() const { return pc_ == kEndOfSimAddress; }
1332 
ReadPc() const1333   const Instruction* ReadPc() const { return pc_; }
1334   VIXL_DEPRECATED("ReadPc", const Instruction* pc() const) { return ReadPc(); }
1335 
1336   enum BranchLogMode { LogBranches, NoBranchLog };
1337 
WritePc(const Instruction* new_pc, BranchLogMode log_mode = LogBranches)1338   void WritePc(const Instruction* new_pc,
1339                BranchLogMode log_mode = LogBranches) {
1340     if (log_mode == LogBranches) LogTakenBranch(new_pc);
1341     pc_ = AddressUntag(new_pc);
1342     pc_modified_ = true;
1343   }
1344   VIXL_DEPRECATED("WritePc", void set_pc(const Instruction* new_pc)) {
1345     return WritePc(new_pc);
1346   }
1347 
IncrementPc()1348   void IncrementPc() {
1349     if (!pc_modified_) {
1350       pc_ = pc_->GetNextInstruction();
1351     }
1352   }
1353   VIXL_DEPRECATED("IncrementPc", void increment_pc()) { IncrementPc(); }
1354 
ReadBType() const1355   BType ReadBType() const { return btype_; }
WriteNextBType(BType btype)1356   void WriteNextBType(BType btype) { next_btype_ = btype; }
UpdateBType()1357   void UpdateBType() {
1358     btype_ = next_btype_;
1359     next_btype_ = DefaultBType;
1360   }
1361 
1362   // Helper function to determine BType for branches.
1363   BType GetBTypeFromInstruction(const Instruction* instr) const;
1364 
PcIsInGuardedPage() const1365   bool PcIsInGuardedPage() const { return guard_pages_; }
SetGuardedPages(bool guard_pages)1366   void SetGuardedPages(bool guard_pages) { guard_pages_ = guard_pages; }
1367 
GetLastExecutedInstruction() const1368   const Instruction* GetLastExecutedInstruction() const { return last_instr_; }
1369 
ExecuteInstruction()1370   void ExecuteInstruction() {
1371     // The program counter should always be aligned.
1372     VIXL_ASSERT(IsWordAligned(pc_));
1373     pc_modified_ = false;
1374 
1375     // On guarded pages, if BType is not zero, take an exception on any
1376     // instruction other than BTI, PACI[AB]SP, HLT or BRK.
1377     if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
1378       if (pc_->IsPAuth()) {
1379         Instr i = pc_->Mask(SystemPAuthMask);
1380         if ((i != PACIASP) && (i != PACIBSP)) {
1381           VIXL_ABORT_WITH_MSG(
1382               "Executing non-BTI instruction with wrong BType.");
1383         }
1384       } else if (!pc_->IsBti() && !pc_->IsException()) {
1385         VIXL_ABORT_WITH_MSG("Executing non-BTI instruction with wrong BType.");
1386       }
1387     }
1388 
1389     bool last_instr_was_movprfx =
1390         (form_hash_ == "movprfx_z_z"_h) || (form_hash_ == "movprfx_z_p_z"_h);
1391 
1392     // decoder_->Decode(...) triggers at least the following visitors:
1393     //  1. The CPUFeaturesAuditor (`cpu_features_auditor_`).
1394     //  2. The PrintDisassembler (`print_disasm_`), if enabled.
1395     //  3. The Simulator (`this`).
1396     // User can add additional visitors at any point, but the Simulator requires
1397     // that the ordering above is preserved.
1398     decoder_->Decode(pc_);
1399 
1400     if (last_instr_was_movprfx) {
1401       VIXL_ASSERT(last_instr_ != NULL);
1402       VIXL_CHECK(pc_->CanTakeSVEMovprfx(form_hash_, last_instr_));
1403     }
1404 
1405     last_instr_ = ReadPc();
1406     IncrementPc();
1407     LogAllWrittenRegisters();
1408     UpdateBType();
1409 
1410     VIXL_CHECK(cpu_features_auditor_.InstructionIsAvailable());
1411   }
1412 
1413   virtual void Visit(Metadata* metadata,
1414                      const Instruction* instr) VIXL_OVERRIDE;
1415 
1416 #define DECLARE(A) virtual void Visit##A(const Instruction* instr);
1417   VISITOR_LIST_THAT_RETURN(DECLARE)
1418 #undef DECLARE
1419 #define DECLARE(A) \
1420   VIXL_NO_RETURN virtual void Visit##A(const Instruction* instr);
1421   VISITOR_LIST_THAT_DONT_RETURN(DECLARE)
1422 #undef DECLARE
1423 
1424   void Simulate_PdT_PgZ_ZnT_ZmT(const Instruction* instr);
1425   void Simulate_PdT_Xn_Xm(const Instruction* instr);
1426   void Simulate_ZdB_Zn1B_Zn2B_imm(const Instruction* instr);
1427   void Simulate_ZdB_ZnB_ZmB(const Instruction* instr);
1428   void Simulate_ZdD_ZnD_ZmD_imm(const Instruction* instr);
1429   void Simulate_ZdH_PgM_ZnS(const Instruction* instr);
1430   void Simulate_ZdH_ZnH_ZmH_imm(const Instruction* instr);
1431   void Simulate_ZdS_PgM_ZnD(const Instruction* instr);
1432   void Simulate_ZdS_PgM_ZnS(const Instruction* instr);
1433   void Simulate_ZdS_ZnS_ZmS_imm(const Instruction* instr);
1434   void Simulate_ZdT_PgM_ZnT(const Instruction* instr);
1435   void Simulate_ZdT_PgZ_ZnT_ZmT(const Instruction* instr);
1436   void Simulate_ZdT_ZnT_ZmT(const Instruction* instr);
1437   void Simulate_ZdT_ZnT_ZmTb(const Instruction* instr);
1438   void Simulate_ZdT_ZnT_const(const Instruction* instr);
1439   void Simulate_ZdaD_ZnS_ZmS_imm(const Instruction* instr);
1440   void Simulate_ZdaH_ZnH_ZmH_imm_const(const Instruction* instr);
1441   void Simulate_ZdaS_ZnH_ZmH(const Instruction* instr);
1442   void Simulate_ZdaS_ZnH_ZmH_imm(const Instruction* instr);
1443   void Simulate_ZdaS_ZnS_ZmS_imm_const(const Instruction* instr);
1444   void Simulate_ZdaT_PgM_ZnTb(const Instruction* instr);
1445   void Simulate_ZdaT_ZnT_ZmT(const Instruction* instr);
1446   void Simulate_ZdaT_ZnT_const(const Instruction* instr);
1447   void Simulate_ZdaT_ZnTb_ZmTb(const Instruction* instr);
1448   void Simulate_ZdnT_PgM_ZdnT_ZmT(const Instruction* instr);
1449   void Simulate_ZdnT_PgM_ZdnT_const(const Instruction* instr);
1450   void Simulate_ZdnT_ZdnT_ZmT_const(const Instruction* instr);
1451   void Simulate_ZtD_PgZ_ZnD_Xm(const Instruction* instr);
1452   void Simulate_ZtD_Pg_ZnD_Xm(const Instruction* instr);
1453   void Simulate_ZtS_PgZ_ZnS_Xm(const Instruction* instr);
1454   void Simulate_ZtS_Pg_ZnS_Xm(const Instruction* instr);
1455 
1456   void SimulateSVEHalvingAddSub(const Instruction* instr);
1457   void SimulateSVESaturatingArithmetic(const Instruction* instr);
1458   void SimulateSVEIntArithPair(const Instruction* instr);
1459   void SimulateSVENarrow(const Instruction* instr);
1460   void SimulateSVEInterleavedArithLong(const Instruction* instr);
1461   void SimulateSVEShiftLeftImm(const Instruction* instr);
1462   void SimulateSVEAddSubCarry(const Instruction* instr);
1463   void SimulateSVEAddSubHigh(const Instruction* instr);
1464   void SimulateSVEIntMulLongVec(const Instruction* instr);
1465   void SimulateSVESaturatingIntMulLongIdx(const Instruction* instr);
1466   void SimulateSVEExclusiveOrRotate(const Instruction* instr);
1467   void SimulateSVEBitwiseTernary(const Instruction* instr);
1468   void SimulateSVEComplexDotProduct(const Instruction* instr);
1469   void SimulateSVEMulIndex(const Instruction* instr);
1470   void SimulateSVEMlaMlsIndex(const Instruction* instr);
1471   void SimulateSVEComplexIntMulAdd(const Instruction* instr);
1472   void SimulateSVESaturatingMulAddHigh(const Instruction* instr);
1473   void SimulateSVESaturatingMulHighIndex(const Instruction* instr);
1474   void SimulateSVEFPConvertLong(const Instruction* instr);
1475   void SimulateMatrixMul(const Instruction* instr);
1476   void SimulateSVEFPMatrixMul(const Instruction* instr);
1477   void SimulateNEONMulByElementLong(const Instruction* instr);
1478   void SimulateNEONFPMulByElement(const Instruction* instr);
1479   void SimulateNEONFPMulByElementLong(const Instruction* instr);
1480   void SimulateNEONComplexMulByElement(const Instruction* instr);
1481   void SimulateNEONDotProdByElement(const Instruction* instr);
1482   void SimulateMTEAddSubTag(const Instruction* instr);
1483   void SimulateMTETagMaskInsert(const Instruction* instr);
1484   void SimulateMTESubPointer(const Instruction* instr);
1485   void SimulateMTELoadTag(const Instruction* instr);
1486   void SimulateMTEStoreTag(const Instruction* instr);
1487   void SimulateMTEStoreTagPair(const Instruction* instr);
1488   void Simulate_XdSP_XnSP_Xm(const Instruction* instr);
1489   void SimulateCpy(const Instruction* instr);
1490   void SimulateCpyFP(const Instruction* instr);
1491   void SimulateCpyP(const Instruction* instr);
1492   void SimulateCpyM(const Instruction* instr);
1493   void SimulateCpyE(const Instruction* instr);
1494   void SimulateSetP(const Instruction* instr);
1495   void SimulateSetM(const Instruction* instr);
1496   void SimulateSetE(const Instruction* instr);
1497   void SimulateSetGP(const Instruction* instr);
1498   void SimulateSetGM(const Instruction* instr);
1499   void SimulateSignedMinMax(const Instruction* instr);
1500   void SimulateUnsignedMinMax(const Instruction* instr);
1501 
1502 
1503   // Integer register accessors.
1504 
1505   // Basic accessor: Read the register as the specified type.
1506   template <typename T>
ReadRegister(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const1507   T ReadRegister(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
1508     VIXL_ASSERT(
1509         code < kNumberOfRegisters ||
1510         ((r31mode == Reg31IsZeroRegister) && (code == kSPRegInternalCode)));
1511     if ((code == 31) && (r31mode == Reg31IsZeroRegister)) {
1512       T result;
1513       memset(&result, 0, sizeof(result));
1514       return result;
1515     }
1516     if ((r31mode == Reg31IsZeroRegister) && (code == kSPRegInternalCode)) {
1517       code = 31;
1518     }
1519     return registers_[code].Get<T>();
1520   }
1521   template <typename T>
1522   VIXL_DEPRECATED("ReadRegister",
1523                   T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister)
1524                       const) {
1525     return ReadRegister<T>(code, r31mode);
1526   }
1527 
1528   // Common specialized accessors for the ReadRegister() template.
1529   int32_t ReadWRegister(unsigned code,
1530                         Reg31Mode r31mode = Reg31IsZeroRegister) const {
1531     return ReadRegister<int32_t>(code, r31mode);
1532   }
1533   VIXL_DEPRECATED("ReadWRegister",
1534                   int32_t wreg(unsigned code,
1535                                Reg31Mode r31mode = Reg31IsZeroRegister) const) {
1536     return ReadWRegister(code, r31mode);
1537   }
1538 
1539   int64_t ReadXRegister(unsigned code,
1540                         Reg31Mode r31mode = Reg31IsZeroRegister) const {
1541     return ReadRegister<int64_t>(code, r31mode);
1542   }
1543   VIXL_DEPRECATED("ReadXRegister",
1544                   int64_t xreg(unsigned code,
1545                                Reg31Mode r31mode = Reg31IsZeroRegister) const) {
1546     return ReadXRegister(code, r31mode);
1547   }
1548 
1549   SimPRegister& ReadPRegister(unsigned code) {
1550     VIXL_ASSERT(code < kNumberOfPRegisters);
1551     return pregisters_[code];
1552   }
1553 
1554   SimFFRRegister& ReadFFR() { return ffr_register_; }
1555 
1556   // As above, with parameterized size and return type. The value is
1557   // either zero-extended or truncated to fit, as required.
1558   template <typename T>
1559   T ReadRegister(unsigned size,
1560                  unsigned code,
1561                  Reg31Mode r31mode = Reg31IsZeroRegister) const {
1562     uint64_t raw;
1563     switch (size) {
1564       case kWRegSize:
1565         raw = ReadRegister<uint32_t>(code, r31mode);
1566         break;
1567       case kXRegSize:
1568         raw = ReadRegister<uint64_t>(code, r31mode);
1569         break;
1570       default:
1571         VIXL_UNREACHABLE();
1572         return 0;
1573     }
1574 
1575     T result;
1576     VIXL_STATIC_ASSERT(sizeof(result) <= sizeof(raw));
1577     // Copy the result and truncate to fit. This assumes a little-endian host.
1578     memcpy(&result, &raw, sizeof(result));
1579     return result;
1580   }
1581   template <typename T>
1582   VIXL_DEPRECATED("ReadRegister",
1583                   T reg(unsigned size,
1584                         unsigned code,
1585                         Reg31Mode r31mode = Reg31IsZeroRegister) const) {
1586     return ReadRegister<T>(size, code, r31mode);
1587   }
1588 
1589   // Use int64_t by default if T is not specified.
1590   int64_t ReadRegister(unsigned size,
1591                        unsigned code,
1592                        Reg31Mode r31mode = Reg31IsZeroRegister) const {
1593     return ReadRegister<int64_t>(size, code, r31mode);
1594   }
1595   VIXL_DEPRECATED("ReadRegister",
1596                   int64_t reg(unsigned size,
1597                               unsigned code,
1598                               Reg31Mode r31mode = Reg31IsZeroRegister) const) {
1599     return ReadRegister(size, code, r31mode);
1600   }
1601 
1602   enum RegLogMode { LogRegWrites, NoRegLog };
1603 
1604   // Write 'value' into an integer register. The value is zero-extended. This
1605   // behaviour matches AArch64 register writes.
1606   //
1607   // SP may be specified in one of two ways:
1608   //  - (code == kSPRegInternalCode) && (r31mode == Reg31IsZeroRegister)
1609   //  - (code == 31) && (r31mode == Reg31IsStackPointer)
1610   template <typename T>
1611   void WriteRegister(unsigned code,
1612                      T value,
1613                      RegLogMode log_mode = LogRegWrites,
1614                      Reg31Mode r31mode = Reg31IsZeroRegister) {
1615     if (sizeof(T) < kWRegSizeInBytes) {
1616       // We use a C-style cast on purpose here.
1617       // Since we do not have access to 'constepxr if', the casts in this `if`
1618       // must be valid even if we know the code will never be executed, in
1619       // particular when `T` is a pointer type.
1620       int64_t tmp_64bit = (int64_t)value;
1621       int32_t tmp_32bit = static_cast<int32_t>(tmp_64bit);
1622       WriteRegister<int32_t>(code, tmp_32bit, log_mode, r31mode);
1623       return;
1624     }
1625 
1626     VIXL_ASSERT((sizeof(T) == kWRegSizeInBytes) ||
1627                 (sizeof(T) == kXRegSizeInBytes));
1628     VIXL_ASSERT(
1629         (code < kNumberOfRegisters) ||
1630         ((r31mode == Reg31IsZeroRegister) && (code == kSPRegInternalCode)));
1631 
1632     if (code == 31) {
1633       if (r31mode == Reg31IsZeroRegister) {
1634         // Discard writes to the zero register.
1635         return;
1636       } else {
1637         code = kSPRegInternalCode;
1638       }
1639     }
1640 
1641     // registers_[31] is the stack pointer.
1642     VIXL_STATIC_ASSERT((kSPRegInternalCode % kNumberOfRegisters) == 31);
1643     registers_[code % kNumberOfRegisters].Write(value);
1644 
1645     if (log_mode == LogRegWrites) {
1646       LogRegister(code, GetPrintRegisterFormatForSize(sizeof(T)));
1647     }
1648   }
1649   template <typename T>
1650   VIXL_DEPRECATED("WriteRegister",
1651                   void set_reg(unsigned code,
1652                                T value,
1653                                RegLogMode log_mode = LogRegWrites,
1654                                Reg31Mode r31mode = Reg31IsZeroRegister)) {
1655     WriteRegister<T>(code, value, log_mode, r31mode);
1656   }
1657 
1658   // Common specialized accessors for the set_reg() template.
1659   void WriteWRegister(unsigned code,
1660                       int32_t value,
1661                       RegLogMode log_mode = LogRegWrites,
1662                       Reg31Mode r31mode = Reg31IsZeroRegister) {
1663     WriteRegister(code, value, log_mode, r31mode);
1664   }
1665   VIXL_DEPRECATED("WriteWRegister",
1666                   void set_wreg(unsigned code,
1667                                 int32_t value,
1668                                 RegLogMode log_mode = LogRegWrites,
1669                                 Reg31Mode r31mode = Reg31IsZeroRegister)) {
1670     WriteWRegister(code, value, log_mode, r31mode);
1671   }
1672 
1673   void WriteXRegister(unsigned code,
1674                       int64_t value,
1675                       RegLogMode log_mode = LogRegWrites,
1676                       Reg31Mode r31mode = Reg31IsZeroRegister) {
1677     WriteRegister(code, value, log_mode, r31mode);
1678   }
1679   VIXL_DEPRECATED("WriteXRegister",
1680                   void set_xreg(unsigned code,
1681                                 int64_t value,
1682                                 RegLogMode log_mode = LogRegWrites,
1683                                 Reg31Mode r31mode = Reg31IsZeroRegister)) {
1684     WriteXRegister(code, value, log_mode, r31mode);
1685   }
1686 
1687   // As above, with parameterized size and type. The value is either
1688   // zero-extended or truncated to fit, as required.
1689   template <typename T>
1690   void WriteRegister(unsigned size,
1691                      unsigned code,
1692                      T value,
1693                      RegLogMode log_mode = LogRegWrites,
1694                      Reg31Mode r31mode = Reg31IsZeroRegister) {
1695     // Zero-extend the input.
1696     uint64_t raw = 0;
1697     VIXL_STATIC_ASSERT(sizeof(value) <= sizeof(raw));
1698     memcpy(&raw, &value, sizeof(value));
1699 
1700     // Write (and possibly truncate) the value.
1701     switch (size) {
1702       case kWRegSize:
1703         WriteRegister(code, static_cast<uint32_t>(raw), log_mode, r31mode);
1704         break;
1705       case kXRegSize:
1706         WriteRegister(code, raw, log_mode, r31mode);
1707         break;
1708       default:
1709         VIXL_UNREACHABLE();
1710         return;
1711     }
1712   }
1713   template <typename T>
1714   VIXL_DEPRECATED("WriteRegister",
1715                   void set_reg(unsigned size,
1716                                unsigned code,
1717                                T value,
1718                                RegLogMode log_mode = LogRegWrites,
1719                                Reg31Mode r31mode = Reg31IsZeroRegister)) {
1720     WriteRegister(size, code, value, log_mode, r31mode);
1721   }
1722 
1723   // Common specialized accessors for the set_reg() template.
1724 
1725   // Commonly-used special cases.
1726   template <typename T>
1727   void WriteLr(T value) {
1728     WriteRegister(kLinkRegCode, value);
1729   }
1730   template <typename T>
1731   VIXL_DEPRECATED("WriteLr", void set_lr(T value)) {
1732     WriteLr(value);
1733   }
1734 
1735   template <typename T>
1736   void WriteSp(T value) {
1737     WriteRegister(31, value, LogRegWrites, Reg31IsStackPointer);
1738   }
1739   template <typename T>
1740   VIXL_DEPRECATED("WriteSp", void set_sp(T value)) {
1741     WriteSp(value);
1742   }
1743 
1744   // Vector register accessors.
1745   // These are equivalent to the integer register accessors, but for vector
1746   // registers.
1747 
1748   // A structure for representing a 128-bit Q register.
1749   struct qreg_t {
1750     uint8_t val[kQRegSizeInBytes];
1751   };
1752 
1753   // A structure for representing a SVE Z register.
1754   struct zreg_t {
1755     uint8_t val[kZRegMaxSizeInBytes];
1756   };
1757 
1758   // Basic accessor: read the register as the specified type.
1759   template <typename T>
1760   T ReadVRegister(unsigned code) const {
1761     VIXL_STATIC_ASSERT(
1762         (sizeof(T) == kBRegSizeInBytes) || (sizeof(T) == kHRegSizeInBytes) ||
1763         (sizeof(T) == kSRegSizeInBytes) || (sizeof(T) == kDRegSizeInBytes) ||
1764         (sizeof(T) == kQRegSizeInBytes));
1765     VIXL_ASSERT(code < kNumberOfVRegisters);
1766 
1767     return vregisters_[code].Get<T>();
1768   }
1769   template <typename T>
1770   VIXL_DEPRECATED("ReadVRegister", T vreg(unsigned code) const) {
1771     return ReadVRegister<T>(code);
1772   }
1773 
1774   // Common specialized accessors for the vreg() template.
1775   int8_t ReadBRegister(unsigned code) const {
1776     return ReadVRegister<int8_t>(code);
1777   }
1778   VIXL_DEPRECATED("ReadBRegister", int8_t breg(unsigned code) const) {
1779     return ReadBRegister(code);
1780   }
1781 
1782   vixl::internal::SimFloat16 ReadHRegister(unsigned code) const {
1783     return RawbitsToFloat16(ReadHRegisterBits(code));
1784   }
1785   VIXL_DEPRECATED("ReadHRegister", int16_t hreg(unsigned code) const) {
1786     return Float16ToRawbits(ReadHRegister(code));
1787   }
1788 
1789   uint16_t ReadHRegisterBits(unsigned code) const {
1790     return ReadVRegister<uint16_t>(code);
1791   }
1792 
1793   float ReadSRegister(unsigned code) const {
1794     return ReadVRegister<float>(code);
1795   }
1796   VIXL_DEPRECATED("ReadSRegister", float sreg(unsigned code) const) {
1797     return ReadSRegister(code);
1798   }
1799 
1800   uint32_t ReadSRegisterBits(unsigned code) const {
1801     return ReadVRegister<uint32_t>(code);
1802   }
1803   VIXL_DEPRECATED("ReadSRegisterBits",
1804                   uint32_t sreg_bits(unsigned code) const) {
1805     return ReadSRegisterBits(code);
1806   }
1807 
1808   double ReadDRegister(unsigned code) const {
1809     return ReadVRegister<double>(code);
1810   }
1811   VIXL_DEPRECATED("ReadDRegister", double dreg(unsigned code) const) {
1812     return ReadDRegister(code);
1813   }
1814 
1815   uint64_t ReadDRegisterBits(unsigned code) const {
1816     return ReadVRegister<uint64_t>(code);
1817   }
1818   VIXL_DEPRECATED("ReadDRegisterBits",
1819                   uint64_t dreg_bits(unsigned code) const) {
1820     return ReadDRegisterBits(code);
1821   }
1822 
1823   qreg_t ReadQRegister(unsigned code) const {
1824     return ReadVRegister<qreg_t>(code);
1825   }
1826   VIXL_DEPRECATED("ReadQRegister", qreg_t qreg(unsigned code) const) {
1827     return ReadQRegister(code);
1828   }
1829 
1830   // As above, with parameterized size and return type. The value is
1831   // either zero-extended or truncated to fit, as required.
1832   template <typename T>
1833   T ReadVRegister(unsigned size, unsigned code) const {
1834     uint64_t raw = 0;
1835     T result;
1836 
1837     switch (size) {
1838       case kSRegSize:
1839         raw = ReadVRegister<uint32_t>(code);
1840         break;
1841       case kDRegSize:
1842         raw = ReadVRegister<uint64_t>(code);
1843         break;
1844       default:
1845         VIXL_UNREACHABLE();
1846         break;
1847     }
1848 
1849     VIXL_STATIC_ASSERT(sizeof(result) <= sizeof(raw));
1850     // Copy the result and truncate to fit. This assumes a little-endian host.
1851     memcpy(&result, &raw, sizeof(result));
1852     return result;
1853   }
1854   template <typename T>
1855   VIXL_DEPRECATED("ReadVRegister", T vreg(unsigned size, unsigned code) const) {
1856     return ReadVRegister<T>(size, code);
1857   }
1858 
1859   SimVRegister& ReadVRegister(unsigned code) { return vregisters_[code]; }
1860   VIXL_DEPRECATED("ReadVRegister", SimVRegister& vreg(unsigned code)) {
1861     return ReadVRegister(code);
1862   }
1863 
1864   // Basic accessor: Write the specified value.
1865   template <typename T>
1866   void WriteVRegister(unsigned code,
1867                       T value,
1868                       RegLogMode log_mode = LogRegWrites) {
1869     VIXL_STATIC_ASSERT((sizeof(value) == kBRegSizeInBytes) ||
1870                        (sizeof(value) == kHRegSizeInBytes) ||
1871                        (sizeof(value) == kSRegSizeInBytes) ||
1872                        (sizeof(value) == kDRegSizeInBytes) ||
1873                        (sizeof(value) == kQRegSizeInBytes) ||
1874                        (sizeof(value) == kZRegMaxSizeInBytes));
1875     VIXL_ASSERT(code < kNumberOfVRegisters);
1876     vregisters_[code].Write(value);
1877 
1878     if (log_mode == LogRegWrites) {
1879       LogVRegister(code, GetPrintRegisterFormat(value));
1880     }
1881   }
1882   template <typename T>
1883   VIXL_DEPRECATED("WriteVRegister",
1884                   void set_vreg(unsigned code,
1885                                 T value,
1886                                 RegLogMode log_mode = LogRegWrites)) {
1887     WriteVRegister(code, value, log_mode);
1888   }
1889 
1890   // Common specialized accessors for the WriteVRegister() template.
1891   void WriteBRegister(unsigned code,
1892                       int8_t value,
1893                       RegLogMode log_mode = LogRegWrites) {
1894     WriteVRegister(code, value, log_mode);
1895   }
1896   VIXL_DEPRECATED("WriteBRegister",
1897                   void set_breg(unsigned code,
1898                                 int8_t value,
1899                                 RegLogMode log_mode = LogRegWrites)) {
1900     return WriteBRegister(code, value, log_mode);
1901   }
1902 
1903   void WriteHRegister(unsigned code,
1904                       vixl::internal::SimFloat16 value,
1905                       RegLogMode log_mode = LogRegWrites) {
1906     WriteVRegister(code, Float16ToRawbits(value), log_mode);
1907   }
1908 
1909   void WriteHRegister(unsigned code,
1910                       int16_t value,
1911                       RegLogMode log_mode = LogRegWrites) {
1912     WriteVRegister(code, value, log_mode);
1913   }
1914   VIXL_DEPRECATED("WriteHRegister",
1915                   void set_hreg(unsigned code,
1916                                 int16_t value,
1917                                 RegLogMode log_mode = LogRegWrites)) {
1918     return WriteHRegister(code, value, log_mode);
1919   }
1920 
1921   void WriteSRegister(unsigned code,
1922                       float value,
1923                       RegLogMode log_mode = LogRegWrites) {
1924     WriteVRegister(code, value, log_mode);
1925   }
1926   VIXL_DEPRECATED("WriteSRegister",
1927                   void set_sreg(unsigned code,
1928                                 float value,
1929                                 RegLogMode log_mode = LogRegWrites)) {
1930     WriteSRegister(code, value, log_mode);
1931   }
1932 
1933   void WriteSRegisterBits(unsigned code,
1934                           uint32_t value,
1935                           RegLogMode log_mode = LogRegWrites) {
1936     WriteVRegister(code, value, log_mode);
1937   }
1938   VIXL_DEPRECATED("WriteSRegisterBits",
1939                   void set_sreg_bits(unsigned code,
1940                                      uint32_t value,
1941                                      RegLogMode log_mode = LogRegWrites)) {
1942     WriteSRegisterBits(code, value, log_mode);
1943   }
1944 
1945   void WriteDRegister(unsigned code,
1946                       double value,
1947                       RegLogMode log_mode = LogRegWrites) {
1948     WriteVRegister(code, value, log_mode);
1949   }
1950   VIXL_DEPRECATED("WriteDRegister",
1951                   void set_dreg(unsigned code,
1952                                 double value,
1953                                 RegLogMode log_mode = LogRegWrites)) {
1954     WriteDRegister(code, value, log_mode);
1955   }
1956 
1957   void WriteDRegisterBits(unsigned code,
1958                           uint64_t value,
1959                           RegLogMode log_mode = LogRegWrites) {
1960     WriteVRegister(code, value, log_mode);
1961   }
1962   VIXL_DEPRECATED("WriteDRegisterBits",
1963                   void set_dreg_bits(unsigned code,
1964                                      uint64_t value,
1965                                      RegLogMode log_mode = LogRegWrites)) {
1966     WriteDRegisterBits(code, value, log_mode);
1967   }
1968 
1969   void WriteQRegister(unsigned code,
1970                       qreg_t value,
1971                       RegLogMode log_mode = LogRegWrites) {
1972     WriteVRegister(code, value, log_mode);
1973   }
1974   VIXL_DEPRECATED("WriteQRegister",
1975                   void set_qreg(unsigned code,
1976                                 qreg_t value,
1977                                 RegLogMode log_mode = LogRegWrites)) {
1978     WriteQRegister(code, value, log_mode);
1979   }
1980 
1981   void WriteZRegister(unsigned code,
1982                       zreg_t value,
1983                       RegLogMode log_mode = LogRegWrites) {
1984     WriteVRegister(code, value, log_mode);
1985   }
1986 
1987   template <typename T>
1988   T ReadRegister(Register reg) const {
1989     return ReadRegister<T>(reg.GetCode(), Reg31IsZeroRegister);
1990   }
1991 
1992   template <typename T>
1993   void WriteRegister(Register reg,
1994                      T value,
1995                      RegLogMode log_mode = LogRegWrites) {
1996     WriteRegister<T>(reg.GetCode(), value, log_mode, Reg31IsZeroRegister);
1997   }
1998 
1999   template <typename T>
2000   T ReadVRegister(VRegister vreg) const {
2001     return ReadVRegister<T>(vreg.GetCode());
2002   }
2003 
2004   template <typename T>
2005   void WriteVRegister(VRegister vreg,
2006                       T value,
2007                       RegLogMode log_mode = LogRegWrites) {
2008     WriteVRegister<T>(vreg.GetCode(), value, log_mode);
2009   }
2010 
2011   template <typename T>
2012   T ReadCPURegister(CPURegister reg) const {
2013     if (reg.IsVRegister()) {
2014       return ReadVRegister<T>(VRegister(reg));
2015     } else {
2016       return ReadRegister<T>(Register(reg));
2017     }
2018   }
2019 
2020   template <typename T>
2021   void WriteCPURegister(CPURegister reg,
2022                         T value,
2023                         RegLogMode log_mode = LogRegWrites) {
2024     if (reg.IsVRegister()) {
2025       WriteVRegister<T>(VRegister(reg), value, log_mode);
2026     } else {
2027       WriteRegister<T>(Register(reg), value, log_mode);
2028     }
2029   }
2030 
2031   template <typename T, typename A>
2032   T MemRead(A address) const {
2033     Instruction const* pc = ReadPc();
2034     return memory_.Read<T>(address, pc);
2035   }
2036 
2037   template <typename T, typename A>
2038   void MemWrite(A address, T value) const {
2039     Instruction const* pc = ReadPc();
2040     return memory_.Write(address, value, pc);
2041   }
2042 
2043   template <typename A>
2044   uint64_t MemReadUint(int size_in_bytes, A address) const {
2045     return memory_.ReadUint(size_in_bytes, address);
2046   }
2047 
2048   template <typename A>
2049   int64_t MemReadInt(int size_in_bytes, A address) const {
2050     return memory_.ReadInt(size_in_bytes, address);
2051   }
2052 
2053   template <typename A>
2054   void MemWrite(int size_in_bytes, A address, uint64_t value) const {
2055     return memory_.Write(size_in_bytes, address, value);
2056   }
2057 
2058   void LoadLane(LogicVRegister dst,
2059                 VectorFormat vform,
2060                 int index,
2061                 uint64_t addr) const {
2062     unsigned msize_in_bytes = LaneSizeInBytesFromFormat(vform);
2063     LoadUintToLane(dst, vform, msize_in_bytes, index, addr);
2064   }
2065 
2066   void LoadUintToLane(LogicVRegister dst,
2067                       VectorFormat vform,
2068                       unsigned msize_in_bytes,
2069                       int index,
2070                       uint64_t addr) const {
2071     dst.SetUint(vform, index, MemReadUint(msize_in_bytes, addr));
2072   }
2073 
2074   void LoadIntToLane(LogicVRegister dst,
2075                      VectorFormat vform,
2076                      unsigned msize_in_bytes,
2077                      int index,
2078                      uint64_t addr) const {
2079     dst.SetInt(vform, index, MemReadInt(msize_in_bytes, addr));
2080   }
2081 
2082   void StoreLane(const LogicVRegister& src,
2083                  VectorFormat vform,
2084                  int index,
2085                  uint64_t addr) const {
2086     unsigned msize_in_bytes = LaneSizeInBytesFromFormat(vform);
2087     MemWrite(msize_in_bytes, addr, src.Uint(vform, index));
2088   }
2089 
2090   uint64_t ComputeMemOperandAddress(const MemOperand& mem_op) const;
2091 
2092   template <typename T>
2093   T ReadGenericOperand(GenericOperand operand) const {
2094     if (operand.IsCPURegister()) {
2095       return ReadCPURegister<T>(operand.GetCPURegister());
2096     } else {
2097       VIXL_ASSERT(operand.IsMemOperand());
2098       return MemRead<T>(ComputeMemOperandAddress(operand.GetMemOperand()));
2099     }
2100   }
2101 
2102   template <typename T>
2103   void WriteGenericOperand(GenericOperand operand,
2104                            T value,
2105                            RegLogMode log_mode = LogRegWrites) {
2106     if (operand.IsCPURegister()) {
2107       // Outside SIMD, registers are 64-bit or a subset of a 64-bit register. If
2108       // the width of the value to write is smaller than 64 bits, the unused
2109       // bits may contain unrelated values that the code following this write
2110       // needs to handle gracefully.
2111       // Here we fill the unused bits with a predefined pattern to catch issues
2112       // early.
2113       VIXL_ASSERT(operand.GetCPURegister().GetSizeInBits() <= 64);
2114       uint64_t raw = 0xdeadda1adeadda1a;
2115       memcpy(&raw, &value, sizeof(value));
2116       WriteCPURegister(operand.GetCPURegister(), raw, log_mode);
2117     } else {
2118       VIXL_ASSERT(operand.IsMemOperand());
2119       MemWrite(ComputeMemOperandAddress(operand.GetMemOperand()), value);
2120     }
2121   }
2122 
2123   bool ReadN() const { return nzcv_.GetN() != 0; }
2124   VIXL_DEPRECATED("ReadN", bool N() const) { return ReadN(); }
2125 
2126   bool ReadZ() const { return nzcv_.GetZ() != 0; }
2127   VIXL_DEPRECATED("ReadZ", bool Z() const) { return ReadZ(); }
2128 
2129   bool ReadC() const { return nzcv_.GetC() != 0; }
2130   VIXL_DEPRECATED("ReadC", bool C() const) { return ReadC(); }
2131 
2132   bool ReadV() const { return nzcv_.GetV() != 0; }
2133   VIXL_DEPRECATED("ReadV", bool V() const) { return ReadV(); }
2134 
2135   SimSystemRegister& ReadNzcv() { return nzcv_; }
2136   VIXL_DEPRECATED("ReadNzcv", SimSystemRegister& nzcv()) { return ReadNzcv(); }
2137 
2138   // TODO: Find a way to make the fpcr_ members return the proper types, so
2139   // these accessors are not necessary.
2140   FPRounding ReadRMode() const {
2141     return static_cast<FPRounding>(fpcr_.GetRMode());
2142   }
2143   VIXL_DEPRECATED("ReadRMode", FPRounding RMode()) { return ReadRMode(); }
2144 
2145   UseDefaultNaN ReadDN() const {
2146     return fpcr_.GetDN() != 0 ? kUseDefaultNaN : kIgnoreDefaultNaN;
2147   }
2148 
2149   VIXL_DEPRECATED("ReadDN", bool DN()) {
2150     return ReadDN() == kUseDefaultNaN ? true : false;
2151   }
2152 
2153   SimSystemRegister& ReadFpcr() { return fpcr_; }
2154   VIXL_DEPRECATED("ReadFpcr", SimSystemRegister& fpcr()) { return ReadFpcr(); }
2155 
2156   // Specify relevant register formats for Print(V)Register and related helpers.
2157   enum PrintRegisterFormat {
2158     // The lane size.
2159     kPrintRegLaneSizeB = 0 << 0,
2160     kPrintRegLaneSizeH = 1 << 0,
2161     kPrintRegLaneSizeS = 2 << 0,
2162     kPrintRegLaneSizeW = kPrintRegLaneSizeS,
2163     kPrintRegLaneSizeD = 3 << 0,
2164     kPrintRegLaneSizeX = kPrintRegLaneSizeD,
2165     kPrintRegLaneSizeQ = 4 << 0,
2166     kPrintRegLaneSizeUnknown = 5 << 0,
2167 
2168     kPrintRegLaneSizeOffset = 0,
2169     kPrintRegLaneSizeMask = 7 << 0,
2170 
2171     // The overall register size.
2172     kPrintRegAsScalar = 0,
2173     kPrintRegAsDVector = 1 << 3,
2174     kPrintRegAsQVector = 2 << 3,
2175     kPrintRegAsSVEVector = 3 << 3,
2176 
2177     kPrintRegAsVectorMask = 3 << 3,
2178 
2179     // Indicate floating-point format lanes. (This flag is only supported for
2180     // S-, H-, and D-sized lanes.)
2181     kPrintRegAsFP = 1 << 5,
2182 
2183     // With this flag, print helpers won't check that the upper bits are zero.
2184     // This also forces the register name to be printed with the `reg<msb:0>`
2185     // format.
2186     //
2187     // The flag is supported with any PrintRegisterFormat other than those with
2188     // kPrintRegAsSVEVector.
2189     kPrintRegPartial = 1 << 6,
2190 
2191 // Supported combinations.
2192 // These exist so that they can be referred to by name, but also because C++
2193 // does not allow enum types to hold values that aren't explicitly
2194 // enumerated, and we want to be able to combine the above flags.
2195 
2196 // Scalar formats.
2197 #define VIXL_DECL_PRINT_REG_SCALAR(size)                           \
2198   kPrint##size##Reg = kPrintRegLaneSize##size | kPrintRegAsScalar, \
2199   kPrint##size##RegPartial = kPrintRegLaneSize##size | kPrintRegPartial
2200 #define VIXL_DECL_PRINT_REG_SCALAR_FP(size)                  \
2201   VIXL_DECL_PRINT_REG_SCALAR(size)                           \
2202   , kPrint##size##RegFP = kPrint##size##Reg | kPrintRegAsFP, \
2203     kPrint##size##RegPartialFP = kPrint##size##RegPartial | kPrintRegAsFP
2204     VIXL_DECL_PRINT_REG_SCALAR(W),
2205     VIXL_DECL_PRINT_REG_SCALAR(X),
2206     VIXL_DECL_PRINT_REG_SCALAR_FP(H),
2207     VIXL_DECL_PRINT_REG_SCALAR_FP(S),
2208     VIXL_DECL_PRINT_REG_SCALAR_FP(D),
2209     VIXL_DECL_PRINT_REG_SCALAR(Q),
2210 #undef VIXL_DECL_PRINT_REG_SCALAR
2211 #undef VIXL_DECL_PRINT_REG_SCALAR_FP
2212 
2213 #define VIXL_DECL_PRINT_REG_NEON(count, type, size)                     \
2214   kPrintReg##count##type = kPrintRegLaneSize##type | kPrintRegAs##size, \
2215   kPrintReg##count##type##Partial = kPrintReg##count##type | kPrintRegPartial
2216 #define VIXL_DECL_PRINT_REG_NEON_FP(count, type, size)                   \
2217   VIXL_DECL_PRINT_REG_NEON(count, type, size)                            \
2218   , kPrintReg##count##type##FP = kPrintReg##count##type | kPrintRegAsFP, \
2219     kPrintReg##count##type##PartialFP =                                  \
2220         kPrintReg##count##type##Partial | kPrintRegAsFP
2221     VIXL_DECL_PRINT_REG_NEON(1, B, Scalar),
2222     VIXL_DECL_PRINT_REG_NEON(8, B, DVector),
2223     VIXL_DECL_PRINT_REG_NEON(16, B, QVector),
2224     VIXL_DECL_PRINT_REG_NEON_FP(1, H, Scalar),
2225     VIXL_DECL_PRINT_REG_NEON_FP(4, H, DVector),
2226     VIXL_DECL_PRINT_REG_NEON_FP(8, H, QVector),
2227     VIXL_DECL_PRINT_REG_NEON_FP(1, S, Scalar),
2228     VIXL_DECL_PRINT_REG_NEON_FP(2, S, DVector),
2229     VIXL_DECL_PRINT_REG_NEON_FP(4, S, QVector),
2230     VIXL_DECL_PRINT_REG_NEON_FP(1, D, Scalar),
2231     VIXL_DECL_PRINT_REG_NEON_FP(2, D, QVector),
2232     VIXL_DECL_PRINT_REG_NEON(1, Q, Scalar),
2233 #undef VIXL_DECL_PRINT_REG_NEON
2234 #undef VIXL_DECL_PRINT_REG_NEON_FP
2235 
2236 #define VIXL_DECL_PRINT_REG_SVE(type)                                 \
2237   kPrintRegVn##type = kPrintRegLaneSize##type | kPrintRegAsSVEVector, \
2238   kPrintRegVn##type##Partial = kPrintRegVn##type | kPrintRegPartial
2239 #define VIXL_DECL_PRINT_REG_SVE_FP(type)                       \
2240   VIXL_DECL_PRINT_REG_SVE(type)                                \
2241   , kPrintRegVn##type##FP = kPrintRegVn##type | kPrintRegAsFP, \
2242     kPrintRegVn##type##PartialFP = kPrintRegVn##type##Partial | kPrintRegAsFP
2243     VIXL_DECL_PRINT_REG_SVE(B),
2244     VIXL_DECL_PRINT_REG_SVE_FP(H),
2245     VIXL_DECL_PRINT_REG_SVE_FP(S),
2246     VIXL_DECL_PRINT_REG_SVE_FP(D),
2247     VIXL_DECL_PRINT_REG_SVE(Q)
2248 #undef VIXL_DECL_PRINT_REG_SVE
2249 #undef VIXL_DECL_PRINT_REG_SVE_FP
2250   };
2251 
2252   // Return `format` with the kPrintRegPartial flag set.
2253   PrintRegisterFormat GetPrintRegPartial(PrintRegisterFormat format) {
2254     // Every PrintRegisterFormat has a kPrintRegPartial counterpart, so the
2255     // result of this cast will always be well-defined.
2256     return static_cast<PrintRegisterFormat>(format | kPrintRegPartial);
2257   }
2258 
2259   // For SVE formats, return the format of a Q register part of it.
2260   PrintRegisterFormat GetPrintRegAsQChunkOfSVE(PrintRegisterFormat format) {
2261     VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
2262     // Keep the FP and lane size fields.
2263     int q_format = format & (kPrintRegLaneSizeMask | kPrintRegAsFP);
2264     // The resulting format must always be partial, because we're not formatting
2265     // the whole Z register.
2266     q_format |= (kPrintRegAsQVector | kPrintRegPartial);
2267 
2268     // This cast is always safe because NEON QVector formats support every
2269     // combination of FP and lane size that SVE formats do.
2270     return static_cast<PrintRegisterFormat>(q_format);
2271   }
2272 
2273   unsigned GetPrintRegLaneSizeInBytesLog2(PrintRegisterFormat format) {
2274     VIXL_ASSERT((format & kPrintRegLaneSizeMask) != kPrintRegLaneSizeUnknown);
2275     return (format & kPrintRegLaneSizeMask) >> kPrintRegLaneSizeOffset;
2276   }
2277 
2278   unsigned GetPrintRegLaneSizeInBytes(PrintRegisterFormat format) {
2279     return 1 << GetPrintRegLaneSizeInBytesLog2(format);
2280   }
2281 
2282   unsigned GetPrintRegSizeInBytesLog2(PrintRegisterFormat format) {
2283     switch (format & kPrintRegAsVectorMask) {
2284       case kPrintRegAsScalar:
2285         return GetPrintRegLaneSizeInBytesLog2(format);
2286       case kPrintRegAsDVector:
2287         return kDRegSizeInBytesLog2;
2288       case kPrintRegAsQVector:
2289         return kQRegSizeInBytesLog2;
2290       default:
2291       case kPrintRegAsSVEVector:
2292         // We print SVE vectors in Q-sized chunks. These need special handling,
2293         // and it's probably an error to call this function in that case.
2294         VIXL_UNREACHABLE();
2295         return kQRegSizeInBytesLog2;
2296     }
2297   }
2298 
2299   unsigned GetPrintRegSizeInBytes(PrintRegisterFormat format) {
2300     return 1 << GetPrintRegSizeInBytesLog2(format);
2301   }
2302 
2303   unsigned GetPrintRegSizeInBitsLog2(PrintRegisterFormat format) {
2304     return GetPrintRegSizeInBytesLog2(format) + kBitsPerByteLog2;
2305   }
2306 
2307   unsigned GetPrintRegSizeInBits(PrintRegisterFormat format) {
2308     return 1 << GetPrintRegSizeInBitsLog2(format);
2309   }
2310 
2311   const char* GetPartialRegSuffix(PrintRegisterFormat format) {
2312     switch (GetPrintRegSizeInBitsLog2(format)) {
2313       case kBRegSizeLog2:
2314         return "<7:0>";
2315       case kHRegSizeLog2:
2316         return "<15:0>";
2317       case kSRegSizeLog2:
2318         return "<31:0>";
2319       case kDRegSizeLog2:
2320         return "<63:0>";
2321       case kQRegSizeLog2:
2322         return "<127:0>";
2323     }
2324     VIXL_UNREACHABLE();
2325     return "<UNKNOWN>";
2326   }
2327 
2328   unsigned GetPrintRegLaneCount(PrintRegisterFormat format) {
2329     unsigned reg_size_log2 = GetPrintRegSizeInBytesLog2(format);
2330     unsigned lane_size_log2 = GetPrintRegLaneSizeInBytesLog2(format);
2331     VIXL_ASSERT(reg_size_log2 >= lane_size_log2);
2332     return 1 << (reg_size_log2 - lane_size_log2);
2333   }
2334 
2335   uint16_t GetPrintRegLaneMask(PrintRegisterFormat format) {
2336     int print_as = format & kPrintRegAsVectorMask;
2337     if (print_as == kPrintRegAsScalar) return 1;
2338 
2339     // Vector formats, including SVE formats printed in Q-sized chunks.
2340     static const uint16_t masks[] = {0xffff, 0x5555, 0x1111, 0x0101, 0x0001};
2341     unsigned size_in_bytes_log2 = GetPrintRegLaneSizeInBytesLog2(format);
2342     VIXL_ASSERT(size_in_bytes_log2 < ArrayLength(masks));
2343     uint16_t mask = masks[size_in_bytes_log2];
2344 
2345     // Exclude lanes that aren't visible in D vectors.
2346     if (print_as == kPrintRegAsDVector) mask &= 0x00ff;
2347     return mask;
2348   }
2349 
2350   PrintRegisterFormat GetPrintRegisterFormatForSize(unsigned reg_size,
2351                                                     unsigned lane_size);
2352 
2353   PrintRegisterFormat GetPrintRegisterFormatForSize(unsigned size) {
2354     return GetPrintRegisterFormatForSize(size, size);
2355   }
2356 
2357   PrintRegisterFormat GetPrintRegisterFormatForSizeFP(unsigned size) {
2358     switch (size) {
2359       default:
2360         VIXL_UNREACHABLE();
2361         return kPrintDReg;
2362       case kDRegSizeInBytes:
2363         return kPrintDReg;
2364       case kSRegSizeInBytes:
2365         return kPrintSReg;
2366       case kHRegSizeInBytes:
2367         return kPrintHReg;
2368     }
2369   }
2370 
2371   PrintRegisterFormat GetPrintRegisterFormatTryFP(PrintRegisterFormat format) {
2372     if ((GetPrintRegLaneSizeInBytes(format) == kHRegSizeInBytes) ||
2373         (GetPrintRegLaneSizeInBytes(format) == kSRegSizeInBytes) ||
2374         (GetPrintRegLaneSizeInBytes(format) == kDRegSizeInBytes)) {
2375       return static_cast<PrintRegisterFormat>(format | kPrintRegAsFP);
2376     }
2377     return format;
2378   }
2379 
2380   PrintRegisterFormat GetPrintRegisterFormatForSizeTryFP(unsigned size) {
2381     return GetPrintRegisterFormatTryFP(GetPrintRegisterFormatForSize(size));
2382   }
2383 
2384   template <typename T>
2385   PrintRegisterFormat GetPrintRegisterFormat(T value) {
2386     return GetPrintRegisterFormatForSize(sizeof(value));
2387   }
2388 
2389   PrintRegisterFormat GetPrintRegisterFormat(double value) {
2390     VIXL_STATIC_ASSERT(sizeof(value) == kDRegSizeInBytes);
2391     return GetPrintRegisterFormatForSizeFP(sizeof(value));
2392   }
2393 
2394   PrintRegisterFormat GetPrintRegisterFormat(float value) {
2395     VIXL_STATIC_ASSERT(sizeof(value) == kSRegSizeInBytes);
2396     return GetPrintRegisterFormatForSizeFP(sizeof(value));
2397   }
2398 
2399   PrintRegisterFormat GetPrintRegisterFormat(Float16 value) {
2400     VIXL_STATIC_ASSERT(sizeof(Float16ToRawbits(value)) == kHRegSizeInBytes);
2401     return GetPrintRegisterFormatForSizeFP(sizeof(Float16ToRawbits(value)));
2402   }
2403 
2404   PrintRegisterFormat GetPrintRegisterFormat(VectorFormat vform);
2405   PrintRegisterFormat GetPrintRegisterFormatFP(VectorFormat vform);
2406 
2407   // Print all registers of the specified types.
2408   void PrintRegisters();
2409   void PrintVRegisters();
2410   void PrintZRegisters();
2411   void PrintSystemRegisters();
2412 
2413   // As above, but only print the registers that have been updated.
2414   void PrintWrittenRegisters();
2415   void PrintWrittenVRegisters();
2416   void PrintWrittenPRegisters();
2417 
2418   // As above, but respect LOG_REG and LOG_VREG.
2419   void LogWrittenRegisters() {
2420     if (ShouldTraceRegs()) PrintWrittenRegisters();
2421   }
2422   void LogWrittenVRegisters() {
2423     if (ShouldTraceVRegs()) PrintWrittenVRegisters();
2424   }
2425   void LogWrittenPRegisters() {
2426     if (ShouldTraceVRegs()) PrintWrittenPRegisters();
2427   }
2428   void LogAllWrittenRegisters() {
2429     LogWrittenRegisters();
2430     LogWrittenVRegisters();
2431     LogWrittenPRegisters();
2432   }
2433 
2434   // The amount of space to leave for a register name. This is used to keep the
2435   // values vertically aligned. The longest register name has the form
2436   // "z31<2047:1920>". The total overall value indentation must also take into
2437   // account the fixed formatting: "# {name}: 0x{value}".
2438   static const int kPrintRegisterNameFieldWidth = 14;
2439 
2440   // Print whole, individual register values.
2441   // - The format can be used to restrict how much of the register is printed,
2442   //   but such formats indicate that the unprinted high-order bits are zero and
2443   //   these helpers will assert that.
2444   // - If the format includes the kPrintRegAsFP flag then human-friendly FP
2445   //   value annotations will be printed.
2446   // - The suffix can be used to add annotations (such as memory access
2447   //   details), or to suppress the newline.
2448   void PrintRegister(int code,
2449                      PrintRegisterFormat format = kPrintXReg,
2450                      const char* suffix = "\n");
2451   void PrintVRegister(int code,
2452                       PrintRegisterFormat format = kPrintReg1Q,
2453                       const char* suffix = "\n");
2454   // PrintZRegister and PrintPRegister print over several lines, so they cannot
2455   // allow the suffix to be overridden.
2456   void PrintZRegister(int code, PrintRegisterFormat format = kPrintRegVnQ);
2457   void PrintPRegister(int code, PrintRegisterFormat format = kPrintRegVnQ);
2458   void PrintFFR(PrintRegisterFormat format = kPrintRegVnQ);
2459   // Print a single Q-sized part of a Z register, or the corresponding two-byte
2460   // part of a P register. These print single lines, and therefore allow the
2461   // suffix to be overridden. The format must include the kPrintRegPartial flag.
2462   void PrintPartialZRegister(int code,
2463                              int q_index,
2464                              PrintRegisterFormat format = kPrintRegVnQ,
2465                              const char* suffix = "\n");
2466   void PrintPartialPRegister(int code,
2467                              int q_index,
2468                              PrintRegisterFormat format = kPrintRegVnQ,
2469                              const char* suffix = "\n");
2470   void PrintPartialPRegister(const char* name,
2471                              const SimPRegister& reg,
2472                              int q_index,
2473                              PrintRegisterFormat format = kPrintRegVnQ,
2474                              const char* suffix = "\n");
2475 
2476   // Like Print*Register (above), but respect trace parameters.
2477   void LogRegister(unsigned code, PrintRegisterFormat format) {
2478     if (ShouldTraceRegs()) PrintRegister(code, format);
2479   }
2480   void LogVRegister(unsigned code, PrintRegisterFormat format) {
2481     if (ShouldTraceVRegs()) PrintVRegister(code, format);
2482   }
2483   void LogZRegister(unsigned code, PrintRegisterFormat format) {
2484     if (ShouldTraceVRegs()) PrintZRegister(code, format);
2485   }
2486   void LogPRegister(unsigned code, PrintRegisterFormat format) {
2487     if (ShouldTraceVRegs()) PrintPRegister(code, format);
2488   }
2489   void LogFFR(PrintRegisterFormat format) {
2490     if (ShouldTraceVRegs()) PrintFFR(format);
2491   }
2492 
2493   // Other state updates, including system registers.
2494   void PrintSystemRegister(SystemRegister id);
2495   void PrintTakenBranch(const Instruction* target);
2496   void LogSystemRegister(SystemRegister id) {
2497     if (ShouldTraceSysRegs()) PrintSystemRegister(id);
2498   }
2499   void LogTakenBranch(const Instruction* target) {
2500     if (ShouldTraceBranches()) PrintTakenBranch(target);
2501   }
2502 
2503   // Trace memory accesses.
2504 
2505   // Common, contiguous register accesses (such as for scalars).
2506   // The *Write variants automatically set kPrintRegPartial on the format.
2507   void PrintRead(int rt_code, PrintRegisterFormat format, uintptr_t address);
2508   void PrintExtendingRead(int rt_code,
2509                           PrintRegisterFormat format,
2510                           int access_size_in_bytes,
2511                           uintptr_t address);
2512   void PrintWrite(int rt_code, PrintRegisterFormat format, uintptr_t address);
2513   void PrintVRead(int rt_code, PrintRegisterFormat format, uintptr_t address);
2514   void PrintVWrite(int rt_code, PrintRegisterFormat format, uintptr_t address);
2515   // Simple, unpredicated SVE accesses always access the whole vector, and never
2516   // know the lane type, so there's no need to accept a `format`.
2517   void PrintZRead(int rt_code, uintptr_t address) {
2518     vregisters_[rt_code].NotifyRegisterLogged();
2519     PrintZAccess(rt_code, "<-", address);
2520   }
2521   void PrintZWrite(int rt_code, uintptr_t address) {
2522     PrintZAccess(rt_code, "->", address);
2523   }
2524   void PrintPRead(int rt_code, uintptr_t address) {
2525     pregisters_[rt_code].NotifyRegisterLogged();
2526     PrintPAccess(rt_code, "<-", address);
2527   }
2528   void PrintPWrite(int rt_code, uintptr_t address) {
2529     PrintPAccess(rt_code, "->", address);
2530   }
2531 
2532   // Like Print* (above), but respect GetTraceParameters().
2533   void LogRead(int rt_code, PrintRegisterFormat format, uintptr_t address) {
2534     if (ShouldTraceRegs()) PrintRead(rt_code, format, address);
2535   }
2536   void LogExtendingRead(int rt_code,
2537                         PrintRegisterFormat format,
2538                         int access_size_in_bytes,
2539                         uintptr_t address) {
2540     if (ShouldTraceRegs()) {
2541       PrintExtendingRead(rt_code, format, access_size_in_bytes, address);
2542     }
2543   }
2544   void LogWrite(int rt_code, PrintRegisterFormat format, uintptr_t address) {
2545     if (ShouldTraceWrites()) PrintWrite(rt_code, format, address);
2546   }
2547   void LogVRead(int rt_code, PrintRegisterFormat format, uintptr_t address) {
2548     if (ShouldTraceVRegs()) PrintVRead(rt_code, format, address);
2549   }
2550   void LogVWrite(int rt_code, PrintRegisterFormat format, uintptr_t address) {
2551     if (ShouldTraceWrites()) PrintVWrite(rt_code, format, address);
2552   }
2553   void LogZRead(int rt_code, uintptr_t address) {
2554     if (ShouldTraceVRegs()) PrintZRead(rt_code, address);
2555   }
2556   void LogZWrite(int rt_code, uintptr_t address) {
2557     if (ShouldTraceWrites()) PrintZWrite(rt_code, address);
2558   }
2559   void LogPRead(int rt_code, uintptr_t address) {
2560     if (ShouldTraceVRegs()) PrintPRead(rt_code, address);
2561   }
2562   void LogPWrite(int rt_code, uintptr_t address) {
2563     if (ShouldTraceWrites()) PrintPWrite(rt_code, address);
2564   }
2565   void LogMemTransfer(uintptr_t dst, uintptr_t src, uint8_t value) {
2566     if (ShouldTraceWrites()) PrintMemTransfer(dst, src, value);
2567   }
2568   // Helpers for the above, where the access operation is parameterised.
2569   // - For loads, set op = "<-".
2570   // - For stores, set op = "->".
2571   void PrintAccess(int rt_code,
2572                    PrintRegisterFormat format,
2573                    const char* op,
2574                    uintptr_t address);
2575   void PrintVAccess(int rt_code,
2576                     PrintRegisterFormat format,
2577                     const char* op,
2578                     uintptr_t address);
2579   void PrintMemTransfer(uintptr_t dst, uintptr_t src, uint8_t value);
2580   // Simple, unpredicated SVE accesses always access the whole vector, and never
2581   // know the lane type, so these don't accept a `format`.
2582   void PrintZAccess(int rt_code, const char* op, uintptr_t address);
2583   void PrintPAccess(int rt_code, const char* op, uintptr_t address);
2584 
2585   // Multiple-structure accesses.
2586   void PrintVStructAccess(int rt_code,
2587                           int reg_count,
2588                           PrintRegisterFormat format,
2589                           const char* op,
2590                           uintptr_t address);
2591   // Single-structure (single-lane) accesses.
2592   void PrintVSingleStructAccess(int rt_code,
2593                                 int reg_count,
2594                                 int lane,
2595                                 PrintRegisterFormat format,
2596                                 const char* op,
2597                                 uintptr_t address);
2598   // Replicating accesses.
2599   void PrintVReplicatingStructAccess(int rt_code,
2600                                      int reg_count,
2601                                      PrintRegisterFormat format,
2602                                      const char* op,
2603                                      uintptr_t address);
2604 
2605   // Multiple-structure accesses.
2606   void PrintZStructAccess(int rt_code,
2607                           int reg_count,
2608                           const LogicPRegister& pg,
2609                           PrintRegisterFormat format,
2610                           int msize_in_bytes,
2611                           const char* op,
2612                           const LogicSVEAddressVector& addr);
2613 
2614   // Register-printing helper for all structured accessors.
2615   //
2616   // All lanes (according to `format`) are printed, but lanes indicated by
2617   // `focus_mask` are of particular interest. Each bit corresponds to a byte in
2618   // the printed register, in a manner similar to SVE's predicates. Currently,
2619   // this is used to determine when to print human-readable FP annotations.
2620   void PrintVRegistersForStructuredAccess(int rt_code,
2621                                           int reg_count,
2622                                           uint16_t focus_mask,
2623                                           PrintRegisterFormat format);
2624 
2625   // As for the VRegister variant, but print partial Z register names.
2626   void PrintZRegistersForStructuredAccess(int rt_code,
2627                                           int q_index,
2628                                           int reg_count,
2629                                           uint16_t focus_mask,
2630                                           PrintRegisterFormat format);
2631 
2632   // Print part of a memory access. This should be used for annotating
2633   // non-trivial accesses, such as structured or sign-extending loads. Call
2634   // Print*Register (or Print*RegistersForStructuredAccess), then
2635   // PrintPartialAccess for each contiguous access that makes up the
2636   // instruction.
2637   //
2638   //  access_mask:
2639   //      The lanes to be printed. Each bit corresponds to a byte in the printed
2640   //      register, in a manner similar to SVE's predicates, except that the
2641   //      lane size is not respected when interpreting lane_mask: unaligned bits
2642   //      must be zeroed.
2643   //
2644   //      This function asserts that this mask is non-zero.
2645   //
2646   //  future_access_mask:
2647   //      The lanes to be printed by a future invocation. This must be specified
2648   //      because vertical lines are drawn for partial accesses that haven't yet
2649   //      been printed. The format is the same as for accessed_mask.
2650   //
2651   //      If a lane is active in both `access_mask` and `future_access_mask`,
2652   //      `access_mask` takes precedence.
2653   //
2654   //  struct_element_count:
2655   //      The number of elements in each structure. For non-structured accesses,
2656   //      set this to one. Along with lane_size_in_bytes, this is used determine
2657   //      the size of each access, and to format the accessed value.
2658   //
2659   //  op:
2660   //      For stores, use "->". For loads, use "<-".
2661   //
2662   //  address:
2663   //      The address of this partial access. (Not the base address of the whole
2664   //      instruction.) The traced value is read from this address (according to
2665   //      part_count and lane_size_in_bytes) so it must be accessible, and when
2666   //      tracing stores, the store must have been executed before this function
2667   //      is called.
2668   //
2669   //  reg_size_in_bytes:
2670   //      The size of the register being accessed. This helper is usually used
2671   //      for V registers or Q-sized chunks of Z registers, so that is the
2672   //      default, but it is possible to use this to annotate X register
2673   //      accesses by specifying kXRegSizeInBytes.
2674   //
2675   // The return value is a future_access_mask suitable for the next iteration,
2676   // so that it is possible to execute this in a loop, until the mask is zero.
2677   // Note that accessed_mask must still be updated by the caller for each call.
2678   uint16_t PrintPartialAccess(uint16_t access_mask,
2679                               uint16_t future_access_mask,
2680                               int struct_element_count,
2681                               int lane_size_in_bytes,
2682                               const char* op,
2683                               uintptr_t address,
2684                               int reg_size_in_bytes = kQRegSizeInBytes);
2685 
2686   // Print an abstract register value. This works for all register types, and
2687   // can print parts of registers. This exists to ensure consistent formatting
2688   // of values.
2689   void PrintRegisterValue(const uint8_t* value,
2690                           int value_size,
2691                           PrintRegisterFormat format);
2692   template <typename T>
2693   void PrintRegisterValue(const T& sim_register, PrintRegisterFormat format) {
2694     PrintRegisterValue(sim_register.GetBytes(),
2695                        std::min(sim_register.GetSizeInBytes(),
2696                                 kQRegSizeInBytes),
2697                        format);
2698   }
2699 
2700   // As above, but format as an SVE predicate value, using binary notation with
2701   // spaces between each bit so that they align with the Z register bytes that
2702   // they predicate.
2703   void PrintPRegisterValue(uint16_t value);
2704 
2705   void PrintRegisterValueFPAnnotations(const uint8_t* value,
2706                                        uint16_t lane_mask,
2707                                        PrintRegisterFormat format);
2708   template <typename T>
2709   void PrintRegisterValueFPAnnotations(const T& sim_register,
2710                                        uint16_t lane_mask,
2711                                        PrintRegisterFormat format) {
2712     PrintRegisterValueFPAnnotations(sim_register.GetBytes(), lane_mask, format);
2713   }
2714   template <typename T>
2715   void PrintRegisterValueFPAnnotations(const T& sim_register,
2716                                        PrintRegisterFormat format) {
2717     PrintRegisterValueFPAnnotations(sim_register.GetBytes(),
2718                                     GetPrintRegLaneMask(format),
2719                                     format);
2720   }
2721 
2722   VIXL_NO_RETURN void DoUnreachable(const Instruction* instr);
2723   void DoTrace(const Instruction* instr);
2724   void DoLog(const Instruction* instr);
2725 
2726   static const char* WRegNameForCode(unsigned code,
2727                                      Reg31Mode mode = Reg31IsZeroRegister);
2728   static const char* XRegNameForCode(unsigned code,
2729                                      Reg31Mode mode = Reg31IsZeroRegister);
2730   static const char* BRegNameForCode(unsigned code);
2731   static const char* HRegNameForCode(unsigned code);
2732   static const char* SRegNameForCode(unsigned code);
2733   static const char* DRegNameForCode(unsigned code);
2734   static const char* VRegNameForCode(unsigned code);
2735   static const char* ZRegNameForCode(unsigned code);
2736   static const char* PRegNameForCode(unsigned code);
2737 
2738   bool IsColouredTrace() const { return coloured_trace_; }
2739   VIXL_DEPRECATED("IsColouredTrace", bool coloured_trace() const) {
2740     return IsColouredTrace();
2741   }
2742 
2743   void SetColouredTrace(bool value);
2744   VIXL_DEPRECATED("SetColouredTrace", void set_coloured_trace(bool value)) {
2745     SetColouredTrace(value);
2746   }
2747 
2748   // Values for traces parameters defined in simulator-constants-aarch64.h in
2749   // enum TraceParameters.
2750   int GetTraceParameters() const { return trace_parameters_; }
2751   VIXL_DEPRECATED("GetTraceParameters", int trace_parameters() const) {
2752     return GetTraceParameters();
2753   }
2754 
2755   bool ShouldTraceWrites() const {
2756     return (GetTraceParameters() & LOG_WRITE) != 0;
2757   }
2758   bool ShouldTraceRegs() const {
2759     return (GetTraceParameters() & LOG_REGS) != 0;
2760   }
2761   bool ShouldTraceVRegs() const {
2762     return (GetTraceParameters() & LOG_VREGS) != 0;
2763   }
2764   bool ShouldTraceSysRegs() const {
2765     return (GetTraceParameters() & LOG_SYSREGS) != 0;
2766   }
2767   bool ShouldTraceBranches() const {
2768     return (GetTraceParameters() & LOG_BRANCH) != 0;
2769   }
2770 
2771   void SetTraceParameters(int parameters);
2772   VIXL_DEPRECATED("SetTraceParameters",
2773                   void set_trace_parameters(int parameters)) {
2774     SetTraceParameters(parameters);
2775   }
2776 
2777   // Clear the simulated local monitor to force the next store-exclusive
2778   // instruction to fail.
2779   void ClearLocalMonitor() { local_monitor_.Clear(); }
2780 
2781   void SilenceExclusiveAccessWarning() {
2782     print_exclusive_access_warning_ = false;
2783   }
2784 
2785   void CheckIsValidUnalignedAtomicAccess(int rn,
2786                                          uint64_t address,
2787                                          unsigned access_size) {
2788     // Verify that the address is available to the host.
2789     VIXL_ASSERT(address == static_cast<uintptr_t>(address));
2790 
2791     if (GetCPUFeatures()->Has(CPUFeatures::kUSCAT)) {
2792       // Check that the access falls entirely within one atomic access granule.
2793       if (AlignDown(address, kAtomicAccessGranule) !=
2794           AlignDown(address + access_size - 1, kAtomicAccessGranule)) {
2795         VIXL_ALIGNMENT_EXCEPTION();
2796       }
2797     } else {
2798       // Check that the access is aligned.
2799       if (AlignDown(address, access_size) != address) {
2800         VIXL_ALIGNMENT_EXCEPTION();
2801       }
2802     }
2803 
2804     // The sp must be aligned to 16 bytes when it is accessed.
2805     if ((rn == kSpRegCode) && (AlignDown(address, 16) != address)) {
2806       VIXL_ALIGNMENT_EXCEPTION();
2807     }
2808   }
2809 
2810   enum PointerType { kDataPointer, kInstructionPointer };
2811 
2812   struct PACKey {
2813     uint64_t high;
2814     uint64_t low;
2815     int number;
2816   };
2817 
2818   // Current implementation is that all pointers are tagged.
2819   bool HasTBI(uint64_t ptr, PointerType type) {
2820     USE(ptr, type);
2821     return true;
2822   }
2823 
2824   // Current implementation uses 48-bit virtual addresses.
2825   int GetBottomPACBit(uint64_t ptr, int ttbr) {
2826     USE(ptr, ttbr);
2827     VIXL_ASSERT((ttbr == 0) || (ttbr == 1));
2828     return 48;
2829   }
2830 
2831   // The top PAC bit is 55 for the purposes of relative bit fields with TBI,
2832   // however bit 55 is the TTBR bit regardless of TBI so isn't part of the PAC
2833   // codes in pointers.
2834   int GetTopPACBit(uint64_t ptr, PointerType type) {
2835     return HasTBI(ptr, type) ? 55 : 63;
2836   }
2837 
2838   // Armv8.3 Pointer authentication helpers.
2839   uint64_t CalculatePACMask(uint64_t ptr, PointerType type, int ext_bit);
2840   uint64_t ComputePAC(uint64_t data, uint64_t context, PACKey key);
2841   uint64_t AuthPAC(uint64_t ptr,
2842                    uint64_t context,
2843                    PACKey key,
2844                    PointerType type);
2845   uint64_t AddPAC(uint64_t ptr, uint64_t context, PACKey key, PointerType type);
2846   uint64_t StripPAC(uint64_t ptr, PointerType type);
2847   void PACHelper(int dst,
2848                  int src,
2849                  PACKey key,
2850                  decltype(&Simulator::AddPAC) pac_fn);
2851 
2852   // Armv8.5 MTE helpers.
2853   uint64_t ChooseNonExcludedTag(uint64_t tag,
2854                                 uint64_t offset,
2855                                 uint64_t exclude = 0) {
2856     VIXL_ASSERT(IsUint4(tag) && IsUint4(offset) && IsUint16(exclude));
2857 
2858     if (exclude == 0xffff) {
2859       return 0;
2860     }
2861 
2862     if (offset == 0) {
2863       while ((exclude & (1 << tag)) != 0) {
2864         tag = (tag + 1) % 16;
2865       }
2866     }
2867 
2868     while (offset > 0) {
2869       offset--;
2870       tag = (tag + 1) % 16;
2871       while ((exclude & (1 << tag)) != 0) {
2872         tag = (tag + 1) % 16;
2873       }
2874     }
2875     return tag;
2876   }
2877 
2878   uint64_t GetAddressWithAllocationTag(uint64_t addr, uint64_t tag) {
2879     VIXL_ASSERT(IsUint4(tag));
2880     return (addr & ~(UINT64_C(0xf) << 56)) | (tag << 56);
2881   }
2882 
2883   // Create or remove a mapping with memory protection. Memory attributes such
2884   // as MTE and BTI are represented by metadata in Simulator.
2885   void* Mmap(
2886       void* address, size_t length, int prot, int flags, int fd, off_t offset);
2887 
2888   int Munmap(void* address, size_t length, int prot);
2889 
2890   // The common CPUFeatures interface with the set of available features.
2891 
2892   CPUFeatures* GetCPUFeatures() {
2893     return cpu_features_auditor_.GetCPUFeatures();
2894   }
2895 
2896   void SetCPUFeatures(const CPUFeatures& cpu_features) {
2897     cpu_features_auditor_.SetCPUFeatures(cpu_features);
2898   }
2899 
2900   // The set of features that the simulator has encountered.
2901   const CPUFeatures& GetSeenFeatures() {
2902     return cpu_features_auditor_.GetSeenFeatures();
2903   }
2904   void ResetSeenFeatures() { cpu_features_auditor_.ResetSeenFeatures(); }
2905 
2906 // Runtime call emulation support.
2907 // It requires VIXL's ABI features, and C++11 or greater.
2908 // Also, the initialisation of the tuples in RuntimeCall(Non)Void is incorrect
2909 // in GCC before 4.9.1: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51253
2910 #if defined(VIXL_HAS_ABI_SUPPORT) && __cplusplus >= 201103L && \
2911     (defined(__clang__) || GCC_VERSION_OR_NEWER(4, 9, 1))
2912 
2913 #define VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
2914 
2915 // The implementation of the runtime call helpers require the functionality
2916 // provided by `std::index_sequence`. It is only available from C++14, but
2917 // we want runtime call simulation to work from C++11, so we emulate if
2918 // necessary.
2919 #if __cplusplus >= 201402L
2920   template <std::size_t... I>
2921   using local_index_sequence = std::index_sequence<I...>;
2922   template <typename... P>
2923   using __local_index_sequence_for = std::index_sequence_for<P...>;
2924 #else
2925   // Emulate the behaviour of `std::index_sequence` and
2926   // `std::index_sequence_for`.
2927   // Naming follow the `std` names, prefixed with `emulated_`.
2928   template <size_t... I>
2929   struct emulated_index_sequence {};
2930 
2931   // A recursive template to create a sequence of indexes.
2932   // The base case (for `N == 0`) is declared outside of the class scope, as
2933   // required by C++.
2934   template <std::size_t N, size_t... I>
2935   struct emulated_make_index_sequence_helper
2936       : emulated_make_index_sequence_helper<N - 1, N - 1, I...> {};
2937 
2938   template <std::size_t N>
2939   struct emulated_make_index_sequence : emulated_make_index_sequence_helper<N> {
2940   };
2941 
2942   template <typename... P>
2943   struct emulated_index_sequence_for
2944       : emulated_make_index_sequence<sizeof...(P)> {};
2945 
2946   template <std::size_t... I>
2947   using local_index_sequence = emulated_index_sequence<I...>;
2948   template <typename... P>
2949   using __local_index_sequence_for = emulated_index_sequence_for<P...>;
2950 #endif
2951 
2952   // Expand the argument tuple and perform the call.
2953   template <typename R, typename... P, std::size_t... I>
2954   R DoRuntimeCall(R (*function)(P...),
2955                   std::tuple<P...> arguments,
2956                   local_index_sequence<I...>) {
2957     USE(arguments);
2958     return function(std::get<I>(arguments)...);
2959   }
2960 
2961   template <typename R, typename... P>
2962   void RuntimeCallNonVoid(R (*function)(P...)) {
2963     ABI abi;
2964     std::tuple<P...> argument_operands{
2965         ReadGenericOperand<P>(abi.GetNextParameterGenericOperand<P>())...};
2966     R return_value = DoRuntimeCall(function,
2967                                    argument_operands,
2968                                    __local_index_sequence_for<P...>{});
2969     WriteGenericOperand(abi.GetReturnGenericOperand<R>(), return_value);
2970   }
2971 
2972   template <typename R, typename... P>
2973   void RuntimeCallVoid(R (*function)(P...)) {
2974     ABI abi;
2975     std::tuple<P...> argument_operands{
2976         ReadGenericOperand<P>(abi.GetNextParameterGenericOperand<P>())...};
2977     DoRuntimeCall(function,
2978                   argument_operands,
2979                   __local_index_sequence_for<P...>{});
2980   }
2981 
2982   // We use `struct` for `void` return type specialisation.
2983   template <typename R, typename... P>
2984   struct RuntimeCallStructHelper {
2985     static void Wrapper(Simulator* simulator, uintptr_t function_pointer) {
2986       R (*function)(P...) = reinterpret_cast<R (*)(P...)>(function_pointer);
2987       simulator->RuntimeCallNonVoid(function);
2988     }
2989   };
2990 
2991   // Partial specialization when the return type is `void`.
2992   template <typename... P>
2993   struct RuntimeCallStructHelper<void, P...> {
2994     static void Wrapper(Simulator* simulator, uintptr_t function_pointer) {
2995       void (*function)(P...) =
2996           reinterpret_cast<void (*)(P...)>(function_pointer);
2997       simulator->RuntimeCallVoid(function);
2998     }
2999   };
3000 #endif
3001 
3002   // Configure the simulated value of 'VL', which is the size of a Z register.
3003   // Because this cannot occur during a program's lifetime, this function also
3004   // resets the SVE registers.
3005   void SetVectorLengthInBits(unsigned vector_length);
3006 
3007   unsigned GetVectorLengthInBits() const { return vector_length_; }
3008   unsigned GetVectorLengthInBytes() const {
3009     VIXL_ASSERT((vector_length_ % kBitsPerByte) == 0);
3010     return vector_length_ / kBitsPerByte;
3011   }
3012   unsigned GetPredicateLengthInBits() const {
3013     VIXL_ASSERT((GetVectorLengthInBits() % kZRegBitsPerPRegBit) == 0);
3014     return GetVectorLengthInBits() / kZRegBitsPerPRegBit;
3015   }
3016   unsigned GetPredicateLengthInBytes() const {
3017     VIXL_ASSERT((GetVectorLengthInBytes() % kZRegBitsPerPRegBit) == 0);
3018     return GetVectorLengthInBytes() / kZRegBitsPerPRegBit;
3019   }
3020 
3021   unsigned RegisterSizeInBitsFromFormat(VectorFormat vform) const {
3022     if (IsSVEFormat(vform)) {
3023       return GetVectorLengthInBits();
3024     } else {
3025       return vixl::aarch64::RegisterSizeInBitsFromFormat(vform);
3026     }
3027   }
3028 
3029   unsigned RegisterSizeInBytesFromFormat(VectorFormat vform) const {
3030     unsigned size_in_bits = RegisterSizeInBitsFromFormat(vform);
3031     VIXL_ASSERT((size_in_bits % kBitsPerByte) == 0);
3032     return size_in_bits / kBitsPerByte;
3033   }
3034 
3035   int LaneCountFromFormat(VectorFormat vform) const {
3036     if (IsSVEFormat(vform)) {
3037       return GetVectorLengthInBits() / LaneSizeInBitsFromFormat(vform);
3038     } else {
3039       return vixl::aarch64::LaneCountFromFormat(vform);
3040     }
3041   }
3042 
3043   bool IsFirstActive(VectorFormat vform,
3044                      const LogicPRegister& mask,
3045                      const LogicPRegister& bits) {
3046     for (int i = 0; i < LaneCountFromFormat(vform); i++) {
3047       if (mask.IsActive(vform, i)) {
3048         return bits.IsActive(vform, i);
3049       }
3050     }
3051     return false;
3052   }
3053 
3054   bool AreNoneActive(VectorFormat vform,
3055                      const LogicPRegister& mask,
3056                      const LogicPRegister& bits) {
3057     for (int i = 0; i < LaneCountFromFormat(vform); i++) {
3058       if (mask.IsActive(vform, i) && bits.IsActive(vform, i)) {
3059         return false;
3060       }
3061     }
3062     return true;
3063   }
3064 
3065   bool IsLastActive(VectorFormat vform,
3066                     const LogicPRegister& mask,
3067                     const LogicPRegister& bits) {
3068     for (int i = LaneCountFromFormat(vform) - 1; i >= 0; i--) {
3069       if (mask.IsActive(vform, i)) {
3070         return bits.IsActive(vform, i);
3071       }
3072     }
3073     return false;
3074   }
3075 
3076   void PredTest(VectorFormat vform,
3077                 const LogicPRegister& mask,
3078                 const LogicPRegister& bits) {
3079     ReadNzcv().SetN(IsFirstActive(vform, mask, bits));
3080     ReadNzcv().SetZ(AreNoneActive(vform, mask, bits));
3081     ReadNzcv().SetC(!IsLastActive(vform, mask, bits));
3082     ReadNzcv().SetV(0);
3083     LogSystemRegister(NZCV);
3084   }
3085 
3086   SimPRegister& GetPTrue() { return pregister_all_true_; }
3087 
3088   template <typename T>
3089   size_t CleanGranuleTag(T address, size_t length = kMTETagGranuleInBytes) {
3090     size_t count = 0;
3091     for (size_t offset = 0; offset < length; offset += kMTETagGranuleInBytes) {
3092       count +=
3093           meta_data_.CleanMTETag(reinterpret_cast<uintptr_t>(address) + offset);
3094     }
3095     size_t expected =
3096         length / kMTETagGranuleInBytes + (length % kMTETagGranuleInBytes != 0);
3097 
3098     // Give a warning when the memory region that is being unmapped isn't all
3099     // either MTE protected or not.
3100     if (count != expected) {
3101       std::stringstream sstream;
3102       sstream << std::hex
3103               << "MTE WARNING : the memory region being unmapped "
3104                  "starting at address 0x"
3105               << reinterpret_cast<uint64_t>(address)
3106               << "is not fully MTE protected.\n";
3107       VIXL_WARNING(sstream.str().c_str());
3108     }
3109     return count;
3110   }
3111 
3112   template <typename T>
3113   void SetGranuleTag(T address,
3114                      int tag,
3115                      size_t length = kMTETagGranuleInBytes) {
3116     for (size_t offset = 0; offset < length; offset += kMTETagGranuleInBytes) {
3117       meta_data_.SetMTETag((uintptr_t)(address) + offset, tag);
3118     }
3119   }
3120 
3121   template <typename T>
3122   int GetGranuleTag(T address) {
3123     return meta_data_.GetMTETag(address);
3124   }
3125 
3126   // Generate a random address tag, and any tags specified in the input are
3127   // excluded from the selection.
3128   uint64_t GenerateRandomTag(uint16_t exclude = 0);
3129 
3130   // Register a new BranchInterception object. If 'function' is branched to
3131   // (e.g: "bl function") in the future; instead, if provided, 'callback' will
3132   // be called otherwise a runtime call will be performed on 'function'.
3133   //
3134   // For example: this can be used to always perform runtime calls on
3135   // non-AArch64 functions without using the macroassembler.
3136   template <typename R, typename... P>
3137   void RegisterBranchInterception(R (*function)(P...),
3138                                   InterceptionCallback callback = nullptr) {
3139     meta_data_.RegisterBranchInterception(*function, callback);
3140   }
3141 
3142   // Return the current output stream in use by the simulator.
3143   FILE* GetOutputStream() const { return stream_; }
3144 
3145   bool IsDebuggerEnabled() const { return debugger_enabled_; }
3146 
3147   void SetDebuggerEnabled(bool enabled) { debugger_enabled_ = enabled; }
3148 
3149   Debugger* GetDebugger() const {
3150 #ifndef PANDA_BUILD
3151     return debugger_.get();
3152 #else
3153     return debugger_;
3154 #endif
3155   }
3156 
3157  protected:
3158   const char* clr_normal;
3159   const char* clr_flag_name;
3160   const char* clr_flag_value;
3161   const char* clr_reg_name;
3162   const char* clr_reg_value;
3163   const char* clr_vreg_name;
3164   const char* clr_vreg_value;
3165   const char* clr_preg_name;
3166   const char* clr_preg_value;
3167   const char* clr_memory_address;
3168   const char* clr_warning;
3169   const char* clr_warning_message;
3170   const char* clr_printf;
3171   const char* clr_branch_marker;
3172 
3173   // Simulation helpers ------------------------------------
3174 
3175   void ResetSystemRegisters();
3176   void ResetRegisters();
3177   void ResetVRegisters();
3178   void ResetPRegisters();
3179   void ResetFFR();
3180 
3181   bool ConditionPassed(Condition cond) {
3182     switch (cond) {
3183       case eq:
3184         return ReadZ();
3185       case ne:
3186         return !ReadZ();
3187       case hs:
3188         return ReadC();
3189       case lo:
3190         return !ReadC();
3191       case mi:
3192         return ReadN();
3193       case pl:
3194         return !ReadN();
3195       case vs:
3196         return ReadV();
3197       case vc:
3198         return !ReadV();
3199       case hi:
3200         return ReadC() && !ReadZ();
3201       case ls:
3202         return !(ReadC() && !ReadZ());
3203       case ge:
3204         return ReadN() == ReadV();
3205       case lt:
3206         return ReadN() != ReadV();
3207       case gt:
3208         return !ReadZ() && (ReadN() == ReadV());
3209       case le:
3210         return !(!ReadZ() && (ReadN() == ReadV()));
3211       case nv:
3212         VIXL_FALLTHROUGH();
3213       case al:
3214         return true;
3215       default:
3216         VIXL_UNREACHABLE();
3217         return false;
3218     }
3219   }
3220 
3221   bool ConditionPassed(Instr cond) {
3222     return ConditionPassed(static_cast<Condition>(cond));
3223   }
3224 
3225   bool ConditionFailed(Condition cond) { return !ConditionPassed(cond); }
3226 
3227   void AddSubHelper(const Instruction* instr, int64_t op2);
3228   uint64_t AddWithCarry(unsigned reg_size,
3229                         bool set_flags,
3230                         uint64_t left,
3231                         uint64_t right,
3232                         int carry_in = 0);
3233   std::pair<uint64_t, uint8_t> AddWithCarry(unsigned reg_size,
3234                                             uint64_t left,
3235                                             uint64_t right,
3236                                             int carry_in);
3237   using vixl_uint128_t = std::pair<uint64_t, uint64_t>;
3238   vixl_uint128_t Add128(vixl_uint128_t x, vixl_uint128_t y);
3239   vixl_uint128_t Mul64(uint64_t x, uint64_t y);
3240   vixl_uint128_t Neg128(vixl_uint128_t x);
3241   void LogicalHelper(const Instruction* instr, int64_t op2);
3242   void ConditionalCompareHelper(const Instruction* instr, int64_t op2);
3243   void LoadStoreHelper(const Instruction* instr,
3244                        int64_t offset,
3245                        AddrMode addrmode);
3246   void LoadStorePairHelper(const Instruction* instr, AddrMode addrmode);
3247   template <typename T>
3248   void CompareAndSwapHelper(const Instruction* instr);
3249   template <typename T>
3250   void CompareAndSwapPairHelper(const Instruction* instr);
3251   template <typename T>
3252   void AtomicMemorySimpleHelper(const Instruction* instr);
3253   template <typename T>
3254   void AtomicMemorySwapHelper(const Instruction* instr);
3255   template <typename T>
3256   void LoadAcquireRCpcHelper(const Instruction* instr);
3257   template <typename T1, typename T2>
3258   void LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr);
3259   template <typename T>
3260   void StoreReleaseUnscaledOffsetHelper(const Instruction* instr);
3261   uintptr_t AddressModeHelper(unsigned addr_reg,
3262                               int64_t offset,
3263                               AddrMode addrmode);
3264   void NEONLoadStoreMultiStructHelper(const Instruction* instr,
3265                                       AddrMode addr_mode);
3266   void NEONLoadStoreSingleStructHelper(const Instruction* instr,
3267                                        AddrMode addr_mode);
3268   template <uint32_t mops_type>
3269   void MOPSPHelper(const Instruction* instr) {
3270     VIXL_ASSERT(instr->IsConsistentMOPSTriplet<mops_type>());
3271 
3272     int d = instr->GetRd();
3273     int n = instr->GetRn();
3274     int s = instr->GetRs();
3275 
3276     // Aliased registers and xzr are disallowed for Xd and Xn.
3277     if ((d == n) || (d == s) || (n == s) || (d == 31) || (n == 31)) {
3278       VisitUnallocated(instr);
3279     }
3280 
3281     // Additionally, Xs may not be xzr for cpy.
3282     if ((mops_type == "cpy"_h) && (s == 31)) {
3283       VisitUnallocated(instr);
3284     }
3285 
3286     // Bits 31 and 30 must be zero.
3287     if (instr->ExtractBits(31, 30) != 0) {
3288       VisitUnallocated(instr);
3289     }
3290 
3291     // Saturate copy count.
3292     uint64_t xn = ReadXRegister(n);
3293     int saturation_bits = (mops_type == "cpy"_h) ? 55 : 63;
3294     if ((xn >> saturation_bits) != 0) {
3295       xn = (UINT64_C(1) << saturation_bits) - 1;
3296       if (mops_type == "setg"_h) {
3297         // Align saturated value to granule.
3298         xn &= ~UINT64_C(kMTETagGranuleInBytes - 1);
3299       }
3300       WriteXRegister(n, xn);
3301     }
3302 
3303     ReadNzcv().SetN(0);
3304     ReadNzcv().SetZ(0);
3305     ReadNzcv().SetC(1);  // Indicates "option B" implementation.
3306     ReadNzcv().SetV(0);
3307   }
3308 
3309   int64_t ShiftOperand(unsigned reg_size,
3310                        uint64_t value,
3311                        Shift shift_type,
3312                        unsigned amount) const;
3313   int64_t ExtendValue(unsigned reg_width,
3314                       int64_t value,
3315                       Extend extend_type,
3316                       unsigned left_shift = 0) const;
3317   uint64_t PolynomialMult(uint64_t op1,
3318                           uint64_t op2,
3319                           int lane_size_in_bits) const;
3320 
3321   void ld1(VectorFormat vform, LogicVRegister dst, uint64_t addr);
3322   void ld1(VectorFormat vform, LogicVRegister dst, int index, uint64_t addr);
3323   void ld1r(VectorFormat vform, LogicVRegister dst, uint64_t addr);
3324   void ld1r(VectorFormat vform,
3325             VectorFormat unpack_vform,
3326             LogicVRegister dst,
3327             uint64_t addr,
3328             bool is_signed = false);
3329   void ld2(VectorFormat vform,
3330            LogicVRegister dst1,
3331            LogicVRegister dst2,
3332            uint64_t addr);
3333   void ld2(VectorFormat vform,
3334            LogicVRegister dst1,
3335            LogicVRegister dst2,
3336            int index,
3337            uint64_t addr);
3338   void ld2r(VectorFormat vform,
3339             LogicVRegister dst1,
3340             LogicVRegister dst2,
3341             uint64_t addr);
3342   void ld3(VectorFormat vform,
3343            LogicVRegister dst1,
3344            LogicVRegister dst2,
3345            LogicVRegister dst3,
3346            uint64_t addr);
3347   void ld3(VectorFormat vform,
3348            LogicVRegister dst1,
3349            LogicVRegister dst2,
3350            LogicVRegister dst3,
3351            int index,
3352            uint64_t addr);
3353   void ld3r(VectorFormat vform,
3354             LogicVRegister dst1,
3355             LogicVRegister dst2,
3356             LogicVRegister dst3,
3357             uint64_t addr);
3358   void ld4(VectorFormat vform,
3359            LogicVRegister dst1,
3360            LogicVRegister dst2,
3361            LogicVRegister dst3,
3362            LogicVRegister dst4,
3363            uint64_t addr);
3364   void ld4(VectorFormat vform,
3365            LogicVRegister dst1,
3366            LogicVRegister dst2,
3367            LogicVRegister dst3,
3368            LogicVRegister dst4,
3369            int index,
3370            uint64_t addr);
3371   void ld4r(VectorFormat vform,
3372             LogicVRegister dst1,
3373             LogicVRegister dst2,
3374             LogicVRegister dst3,
3375             LogicVRegister dst4,
3376             uint64_t addr);
3377   void st1(VectorFormat vform, LogicVRegister src, uint64_t addr);
3378   void st1(VectorFormat vform, LogicVRegister src, int index, uint64_t addr);
3379   void st2(VectorFormat vform,
3380            LogicVRegister src,
3381            LogicVRegister src2,
3382            uint64_t addr);
3383   void st2(VectorFormat vform,
3384            LogicVRegister src,
3385            LogicVRegister src2,
3386            int index,
3387            uint64_t addr);
3388   void st3(VectorFormat vform,
3389            LogicVRegister src,
3390            LogicVRegister src2,
3391            LogicVRegister src3,
3392            uint64_t addr);
3393   void st3(VectorFormat vform,
3394            LogicVRegister src,
3395            LogicVRegister src2,
3396            LogicVRegister src3,
3397            int index,
3398            uint64_t addr);
3399   void st4(VectorFormat vform,
3400            LogicVRegister src,
3401            LogicVRegister src2,
3402            LogicVRegister src3,
3403            LogicVRegister src4,
3404            uint64_t addr);
3405   void st4(VectorFormat vform,
3406            LogicVRegister src,
3407            LogicVRegister src2,
3408            LogicVRegister src3,
3409            LogicVRegister src4,
3410            int index,
3411            uint64_t addr);
3412   LogicVRegister cmp(VectorFormat vform,
3413                      LogicVRegister dst,
3414                      const LogicVRegister& src1,
3415                      const LogicVRegister& src2,
3416                      Condition cond);
3417   LogicVRegister cmp(VectorFormat vform,
3418                      LogicVRegister dst,
3419                      const LogicVRegister& src1,
3420                      int imm,
3421                      Condition cond);
3422   LogicVRegister cmptst(VectorFormat vform,
3423                         LogicVRegister dst,
3424                         const LogicVRegister& src1,
3425                         const LogicVRegister& src2);
3426   LogicVRegister add(VectorFormat vform,
3427                      LogicVRegister dst,
3428                      const LogicVRegister& src1,
3429                      const LogicVRegister& src2);
3430   // Add `value` to each lane of `src1`, treating `value` as unsigned for the
3431   // purposes of setting the saturation flags.
3432   LogicVRegister add_uint(VectorFormat vform,
3433                           LogicVRegister dst,
3434                           const LogicVRegister& src1,
3435                           uint64_t value);
3436   LogicVRegister addp(VectorFormat vform,
3437                       LogicVRegister dst,
3438                       const LogicVRegister& src1,
3439                       const LogicVRegister& src2);
3440   LogicPRegister brka(LogicPRegister pd,
3441                       const LogicPRegister& pg,
3442                       const LogicPRegister& pn);
3443   LogicPRegister brkb(LogicPRegister pd,
3444                       const LogicPRegister& pg,
3445                       const LogicPRegister& pn);
3446   LogicPRegister brkn(LogicPRegister pdm,
3447                       const LogicPRegister& pg,
3448                       const LogicPRegister& pn);
3449   LogicPRegister brkpa(LogicPRegister pd,
3450                        const LogicPRegister& pg,
3451                        const LogicPRegister& pn,
3452                        const LogicPRegister& pm);
3453   LogicPRegister brkpb(LogicPRegister pd,
3454                        const LogicPRegister& pg,
3455                        const LogicPRegister& pn,
3456                        const LogicPRegister& pm);
3457   // dst = srca + src1 * src2
3458   LogicVRegister mla(VectorFormat vform,
3459                      LogicVRegister dst,
3460                      const LogicVRegister& srca,
3461                      const LogicVRegister& src1,
3462                      const LogicVRegister& src2);
3463   // dst = srca - src1 * src2
3464   LogicVRegister mls(VectorFormat vform,
3465                      LogicVRegister dst,
3466                      const LogicVRegister& srca,
3467                      const LogicVRegister& src1,
3468                      const LogicVRegister& src2);
3469   LogicVRegister mul(VectorFormat vform,
3470                      LogicVRegister dst,
3471                      const LogicVRegister& src1,
3472                      const LogicVRegister& src2);
3473   LogicVRegister mul(VectorFormat vform,
3474                      LogicVRegister dst,
3475                      const LogicVRegister& src1,
3476                      const LogicVRegister& src2,
3477                      int index);
3478   LogicVRegister mla(VectorFormat vform,
3479                      LogicVRegister dst,
3480                      const LogicVRegister& src1,
3481                      const LogicVRegister& src2,
3482                      int index);
3483   LogicVRegister mls(VectorFormat vform,
3484                      LogicVRegister dst,
3485                      const LogicVRegister& src1,
3486                      const LogicVRegister& src2,
3487                      int index);
3488   LogicVRegister pmul(VectorFormat vform,
3489                       LogicVRegister dst,
3490                       const LogicVRegister& src1,
3491                       const LogicVRegister& src2);
3492   LogicVRegister sdiv(VectorFormat vform,
3493                       LogicVRegister dst,
3494                       const LogicVRegister& src1,
3495                       const LogicVRegister& src2);
3496   LogicVRegister udiv(VectorFormat vform,
3497                       LogicVRegister dst,
3498                       const LogicVRegister& src1,
3499                       const LogicVRegister& src2);
3500 
3501   typedef LogicVRegister (Simulator::*ByElementOp)(VectorFormat vform,
3502                                                    LogicVRegister dst,
3503                                                    const LogicVRegister& src1,
3504                                                    const LogicVRegister& src2,
3505                                                    int index);
3506   LogicVRegister fmul(VectorFormat vform,
3507                       LogicVRegister dst,
3508                       const LogicVRegister& src1,
3509                       const LogicVRegister& src2,
3510                       int index);
3511   LogicVRegister fmla(VectorFormat vform,
3512                       LogicVRegister dst,
3513                       const LogicVRegister& src1,
3514                       const LogicVRegister& src2,
3515                       int index);
3516   LogicVRegister fmlal(VectorFormat vform,
3517                        LogicVRegister dst,
3518                        const LogicVRegister& src1,
3519                        const LogicVRegister& src2,
3520                        int index);
3521   LogicVRegister fmlal2(VectorFormat vform,
3522                         LogicVRegister dst,
3523                         const LogicVRegister& src1,
3524                         const LogicVRegister& src2,
3525                         int index);
3526   LogicVRegister fmls(VectorFormat vform,
3527                       LogicVRegister dst,
3528                       const LogicVRegister& src1,
3529                       const LogicVRegister& src2,
3530                       int index);
3531   LogicVRegister fmlsl(VectorFormat vform,
3532                        LogicVRegister dst,
3533                        const LogicVRegister& src1,
3534                        const LogicVRegister& src2,
3535                        int index);
3536   LogicVRegister fmlsl2(VectorFormat vform,
3537                         LogicVRegister dst,
3538                         const LogicVRegister& src1,
3539                         const LogicVRegister& src2,
3540                         int index);
3541   LogicVRegister fmulx(VectorFormat vform,
3542                        LogicVRegister dst,
3543                        const LogicVRegister& src1,
3544                        const LogicVRegister& src2,
3545                        int index);
3546   LogicVRegister smulh(VectorFormat vform,
3547                        LogicVRegister dst,
3548                        const LogicVRegister& src1,
3549                        const LogicVRegister& src2);
3550   LogicVRegister umulh(VectorFormat vform,
3551                        LogicVRegister dst,
3552                        const LogicVRegister& src1,
3553                        const LogicVRegister& src2);
3554   LogicVRegister sqdmull(VectorFormat vform,
3555                          LogicVRegister dst,
3556                          const LogicVRegister& src1,
3557                          const LogicVRegister& src2,
3558                          int index);
3559   LogicVRegister sqdmlal(VectorFormat vform,
3560                          LogicVRegister dst,
3561                          const LogicVRegister& src1,
3562                          const LogicVRegister& src2,
3563                          int index);
3564   LogicVRegister sqdmlsl(VectorFormat vform,
3565                          LogicVRegister dst,
3566                          const LogicVRegister& src1,
3567                          const LogicVRegister& src2,
3568                          int index);
3569   LogicVRegister sqdmulh(VectorFormat vform,
3570                          LogicVRegister dst,
3571                          const LogicVRegister& src1,
3572                          const LogicVRegister& src2,
3573                          int index);
3574   LogicVRegister sqrdmulh(VectorFormat vform,
3575                           LogicVRegister dst,
3576                           const LogicVRegister& src1,
3577                           const LogicVRegister& src2,
3578                           int index);
3579   LogicVRegister sqrdmlah(VectorFormat vform,
3580                           LogicVRegister dst,
3581                           const LogicVRegister& src1,
3582                           const LogicVRegister& src2,
3583                           int index);
3584   LogicVRegister sqrdmlsh(VectorFormat vform,
3585                           LogicVRegister dst,
3586                           const LogicVRegister& src1,
3587                           const LogicVRegister& src2,
3588                           int index);
3589   LogicVRegister sub(VectorFormat vform,
3590                      LogicVRegister dst,
3591                      const LogicVRegister& src1,
3592                      const LogicVRegister& src2);
3593   // Subtract `value` from each lane of `src1`, treating `value` as unsigned for
3594   // the purposes of setting the saturation flags.
3595   LogicVRegister sub_uint(VectorFormat vform,
3596                           LogicVRegister dst,
3597                           const LogicVRegister& src1,
3598                           uint64_t value);
3599   LogicVRegister and_(VectorFormat vform,
3600                       LogicVRegister dst,
3601                       const LogicVRegister& src1,
3602                       const LogicVRegister& src2);
3603   LogicVRegister orr(VectorFormat vform,
3604                      LogicVRegister dst,
3605                      const LogicVRegister& src1,
3606                      const LogicVRegister& src2);
3607   LogicVRegister orn(VectorFormat vform,
3608                      LogicVRegister dst,
3609                      const LogicVRegister& src1,
3610                      const LogicVRegister& src2);
3611   LogicVRegister eor(VectorFormat vform,
3612                      LogicVRegister dst,
3613                      const LogicVRegister& src1,
3614                      const LogicVRegister& src2);
3615   LogicVRegister bic(VectorFormat vform,
3616                      LogicVRegister dst,
3617                      const LogicVRegister& src1,
3618                      const LogicVRegister& src2);
3619   LogicVRegister bic(VectorFormat vform,
3620                      LogicVRegister dst,
3621                      const LogicVRegister& src,
3622                      uint64_t imm);
3623   LogicVRegister bif(VectorFormat vform,
3624                      LogicVRegister dst,
3625                      const LogicVRegister& src1,
3626                      const LogicVRegister& src2);
3627   LogicVRegister bit(VectorFormat vform,
3628                      LogicVRegister dst,
3629                      const LogicVRegister& src1,
3630                      const LogicVRegister& src2);
3631   LogicVRegister bsl(VectorFormat vform,
3632                      LogicVRegister dst,
3633                      const LogicVRegister& src_mask,
3634                      const LogicVRegister& src1,
3635                      const LogicVRegister& src2);
3636   LogicVRegister cls(VectorFormat vform,
3637                      LogicVRegister dst,
3638                      const LogicVRegister& src);
3639   LogicVRegister clz(VectorFormat vform,
3640                      LogicVRegister dst,
3641                      const LogicVRegister& src);
3642   LogicVRegister cnot(VectorFormat vform,
3643                       LogicVRegister dst,
3644                       const LogicVRegister& src);
3645   LogicVRegister cnt(VectorFormat vform,
3646                      LogicVRegister dst,
3647                      const LogicVRegister& src);
3648   LogicVRegister not_(VectorFormat vform,
3649                       LogicVRegister dst,
3650                       const LogicVRegister& src);
3651   LogicVRegister rbit(VectorFormat vform,
3652                       LogicVRegister dst,
3653                       const LogicVRegister& src);
3654   LogicVRegister rev(VectorFormat vform,
3655                      LogicVRegister dst,
3656                      const LogicVRegister& src);
3657   LogicVRegister rev_byte(VectorFormat vform,
3658                           LogicVRegister dst,
3659                           const LogicVRegister& src,
3660                           int rev_size);
3661   LogicVRegister rev16(VectorFormat vform,
3662                        LogicVRegister dst,
3663                        const LogicVRegister& src);
3664   LogicVRegister rev32(VectorFormat vform,
3665                        LogicVRegister dst,
3666                        const LogicVRegister& src);
3667   LogicVRegister rev64(VectorFormat vform,
3668                        LogicVRegister dst,
3669                        const LogicVRegister& src);
3670   LogicVRegister addlp(VectorFormat vform,
3671                        LogicVRegister dst,
3672                        const LogicVRegister& src,
3673                        bool is_signed,
3674                        bool do_accumulate);
3675   LogicVRegister saddlp(VectorFormat vform,
3676                         LogicVRegister dst,
3677                         const LogicVRegister& src);
3678   LogicVRegister uaddlp(VectorFormat vform,
3679                         LogicVRegister dst,
3680                         const LogicVRegister& src);
3681   LogicVRegister sadalp(VectorFormat vform,
3682                         LogicVRegister dst,
3683                         const LogicVRegister& src);
3684   LogicVRegister uadalp(VectorFormat vform,
3685                         LogicVRegister dst,
3686                         const LogicVRegister& src);
3687   LogicVRegister ror(VectorFormat vform,
3688                      LogicVRegister dst,
3689                      const LogicVRegister& src,
3690                      int rotation);
3691   LogicVRegister ext(VectorFormat vform,
3692                      LogicVRegister dst,
3693                      const LogicVRegister& src1,
3694                      const LogicVRegister& src2,
3695                      int index);
3696   LogicVRegister rotate_elements_right(VectorFormat vform,
3697                                        LogicVRegister dst,
3698                                        const LogicVRegister& src,
3699                                        int index);
3700   template <typename T>
3701   LogicVRegister fcadd(VectorFormat vform,
3702                        LogicVRegister dst,
3703                        const LogicVRegister& src1,
3704                        const LogicVRegister& src2,
3705                        int rot);
3706   LogicVRegister fcadd(VectorFormat vform,
3707                        LogicVRegister dst,
3708                        const LogicVRegister& src1,
3709                        const LogicVRegister& src2,
3710                        int rot);
3711   template <typename T>
3712   LogicVRegister fcmla(VectorFormat vform,
3713                        LogicVRegister dst,
3714                        const LogicVRegister& src1,
3715                        const LogicVRegister& src2,
3716                        const LogicVRegister& acc,
3717                        int index,
3718                        int rot);
3719   LogicVRegister fcmla(VectorFormat vform,
3720                        LogicVRegister dst,
3721                        const LogicVRegister& src1,
3722                        const LogicVRegister& src2,
3723                        int index,
3724                        int rot);
3725   LogicVRegister fcmla(VectorFormat vform,
3726                        LogicVRegister dst,
3727                        const LogicVRegister& src1,
3728                        const LogicVRegister& src2,
3729                        const LogicVRegister& acc,
3730                        int rot);
3731   template <typename T>
3732   LogicVRegister fadda(VectorFormat vform,
3733                        LogicVRegister acc,
3734                        const LogicPRegister& pg,
3735                        const LogicVRegister& src);
3736   LogicVRegister fadda(VectorFormat vform,
3737                        LogicVRegister acc,
3738                        const LogicPRegister& pg,
3739                        const LogicVRegister& src);
3740   LogicVRegister cadd(VectorFormat vform,
3741                       LogicVRegister dst,
3742                       const LogicVRegister& src1,
3743                       const LogicVRegister& src2,
3744                       int rot,
3745                       bool saturate = false);
3746   LogicVRegister cmla(VectorFormat vform,
3747                       LogicVRegister dst,
3748                       const LogicVRegister& srca,
3749                       const LogicVRegister& src1,
3750                       const LogicVRegister& src2,
3751                       int rot);
3752   LogicVRegister cmla(VectorFormat vform,
3753                       LogicVRegister dst,
3754                       const LogicVRegister& srca,
3755                       const LogicVRegister& src1,
3756                       const LogicVRegister& src2,
3757                       int index,
3758                       int rot);
3759   LogicVRegister bgrp(VectorFormat vform,
3760                       LogicVRegister dst,
3761                       const LogicVRegister& src1,
3762                       const LogicVRegister& src2,
3763                       bool do_bext = false);
3764   LogicVRegister bdep(VectorFormat vform,
3765                       LogicVRegister dst,
3766                       const LogicVRegister& src1,
3767                       const LogicVRegister& src2);
3768   LogicVRegister histogram(VectorFormat vform,
3769                            LogicVRegister dst,
3770                            const LogicPRegister& pg,
3771                            const LogicVRegister& src1,
3772                            const LogicVRegister& src2,
3773                            bool do_segmented = false);
3774   LogicVRegister index(VectorFormat vform,
3775                        LogicVRegister dst,
3776                        uint64_t start,
3777                        uint64_t step);
3778   LogicVRegister ins_element(VectorFormat vform,
3779                              LogicVRegister dst,
3780                              int dst_index,
3781                              const LogicVRegister& src,
3782                              int src_index);
3783   LogicVRegister ins_immediate(VectorFormat vform,
3784                                LogicVRegister dst,
3785                                int dst_index,
3786                                uint64_t imm);
3787   LogicVRegister insr(VectorFormat vform, LogicVRegister dst, uint64_t imm);
3788   LogicVRegister dup_element(VectorFormat vform,
3789                              LogicVRegister dst,
3790                              const LogicVRegister& src,
3791                              int src_index);
3792   LogicVRegister dup_elements_to_segments(VectorFormat vform,
3793                                           LogicVRegister dst,
3794                                           const LogicVRegister& src,
3795                                           int src_index);
3796   LogicVRegister dup_elements_to_segments(
3797       VectorFormat vform,
3798       LogicVRegister dst,
3799       const std::pair<int, int>& src_and_index);
3800   LogicVRegister dup_immediate(VectorFormat vform,
3801                                LogicVRegister dst,
3802                                uint64_t imm);
3803   LogicVRegister mov(VectorFormat vform,
3804                      LogicVRegister dst,
3805                      const LogicVRegister& src);
3806   LogicPRegister mov(LogicPRegister dst, const LogicPRegister& src);
3807   LogicVRegister mov_merging(VectorFormat vform,
3808                              LogicVRegister dst,
3809                              const SimPRegister& pg,
3810                              const LogicVRegister& src);
3811   LogicVRegister mov_zeroing(VectorFormat vform,
3812                              LogicVRegister dst,
3813                              const SimPRegister& pg,
3814                              const LogicVRegister& src);
3815   LogicVRegister mov_alternating(VectorFormat vform,
3816                                  LogicVRegister dst,
3817                                  const LogicVRegister& src,
3818                                  int start_at);
3819   LogicPRegister mov_merging(LogicPRegister dst,
3820                              const LogicPRegister& pg,
3821                              const LogicPRegister& src);
3822   LogicPRegister mov_zeroing(LogicPRegister dst,
3823                              const LogicPRegister& pg,
3824                              const LogicPRegister& src);
3825   LogicVRegister movi(VectorFormat vform, LogicVRegister dst, uint64_t imm);
3826   LogicVRegister mvni(VectorFormat vform, LogicVRegister dst, uint64_t imm);
3827   LogicVRegister orr(VectorFormat vform,
3828                      LogicVRegister dst,
3829                      const LogicVRegister& src,
3830                      uint64_t imm);
3831   LogicVRegister sshl(VectorFormat vform,
3832                       LogicVRegister dst,
3833                       const LogicVRegister& src1,
3834                       const LogicVRegister& src2,
3835                       bool shift_is_8bit = true);
3836   LogicVRegister ushl(VectorFormat vform,
3837                       LogicVRegister dst,
3838                       const LogicVRegister& src1,
3839                       const LogicVRegister& src2,
3840                       bool shift_is_8bit = true);
3841   LogicVRegister sshr(VectorFormat vform,
3842                       LogicVRegister dst,
3843                       const LogicVRegister& src1,
3844                       const LogicVRegister& src2);
3845   LogicVRegister ushr(VectorFormat vform,
3846                       LogicVRegister dst,
3847                       const LogicVRegister& src1,
3848                       const LogicVRegister& src2);
3849   // Perform a "conditional last" operation. The first part of the pair is true
3850   // if any predicate lane is active, false otherwise. The second part takes the
3851   // value of the last active (plus offset) lane, or last (plus offset) lane if
3852   // none active.
3853   std::pair<bool, uint64_t> clast(VectorFormat vform,
3854                                   const LogicPRegister& pg,
3855                                   const LogicVRegister& src2,
3856                                   int offset_from_last_active);
3857   LogicPRegister match(VectorFormat vform,
3858                        LogicPRegister dst,
3859                        const LogicVRegister& haystack,
3860                        const LogicVRegister& needles,
3861                        bool negate_match);
3862   LogicVRegister compact(VectorFormat vform,
3863                          LogicVRegister dst,
3864                          const LogicPRegister& pg,
3865                          const LogicVRegister& src);
3866   LogicVRegister splice(VectorFormat vform,
3867                         LogicVRegister dst,
3868                         const LogicPRegister& pg,
3869                         const LogicVRegister& src1,
3870                         const LogicVRegister& src2);
3871   LogicVRegister sel(VectorFormat vform,
3872                      LogicVRegister dst,
3873                      const SimPRegister& pg,
3874                      const LogicVRegister& src1,
3875                      const LogicVRegister& src2);
3876   LogicPRegister sel(LogicPRegister dst,
3877                      const LogicPRegister& pg,
3878                      const LogicPRegister& src1,
3879                      const LogicPRegister& src2);
3880   LogicVRegister sminmax(VectorFormat vform,
3881                          LogicVRegister dst,
3882                          const LogicVRegister& src1,
3883                          const LogicVRegister& src2,
3884                          bool max);
3885   LogicVRegister smax(VectorFormat vform,
3886                       LogicVRegister dst,
3887                       const LogicVRegister& src1,
3888                       const LogicVRegister& src2);
3889   LogicVRegister smin(VectorFormat vform,
3890                       LogicVRegister dst,
3891                       const LogicVRegister& src1,
3892                       const LogicVRegister& src2);
3893   LogicVRegister sminmaxp(VectorFormat vform,
3894                           LogicVRegister dst,
3895                           const LogicVRegister& src1,
3896                           const LogicVRegister& src2,
3897                           bool max);
3898   LogicVRegister smaxp(VectorFormat vform,
3899                        LogicVRegister dst,
3900                        const LogicVRegister& src1,
3901                        const LogicVRegister& src2);
3902   LogicVRegister sminp(VectorFormat vform,
3903                        LogicVRegister dst,
3904                        const LogicVRegister& src1,
3905                        const LogicVRegister& src2);
3906   LogicVRegister addp(VectorFormat vform,
3907                       LogicVRegister dst,
3908                       const LogicVRegister& src);
3909   LogicVRegister addv(VectorFormat vform,
3910                       LogicVRegister dst,
3911                       const LogicVRegister& src);
3912   LogicVRegister uaddlv(VectorFormat vform,
3913                         LogicVRegister dst,
3914                         const LogicVRegister& src);
3915   LogicVRegister saddlv(VectorFormat vform,
3916                         LogicVRegister dst,
3917                         const LogicVRegister& src);
3918   LogicVRegister sminmaxv(VectorFormat vform,
3919                           LogicVRegister dst,
3920                           const LogicPRegister& pg,
3921                           const LogicVRegister& src,
3922                           bool max);
3923   LogicVRegister smaxv(VectorFormat vform,
3924                        LogicVRegister dst,
3925                        const LogicVRegister& src);
3926   LogicVRegister sminv(VectorFormat vform,
3927                        LogicVRegister dst,
3928                        const LogicVRegister& src);
3929   LogicVRegister uxtl(VectorFormat vform,
3930                       LogicVRegister dst,
3931                       const LogicVRegister& src,
3932                       bool is_2 = false);
3933   LogicVRegister uxtl2(VectorFormat vform,
3934                        LogicVRegister dst,
3935                        const LogicVRegister& src);
3936   LogicVRegister sxtl(VectorFormat vform,
3937                       LogicVRegister dst,
3938                       const LogicVRegister& src,
3939                       bool is_2 = false);
3940   LogicVRegister sxtl2(VectorFormat vform,
3941                        LogicVRegister dst,
3942                        const LogicVRegister& src);
3943   LogicVRegister uxt(VectorFormat vform,
3944                      LogicVRegister dst,
3945                      const LogicVRegister& src,
3946                      unsigned from_size_in_bits);
3947   LogicVRegister sxt(VectorFormat vform,
3948                      LogicVRegister dst,
3949                      const LogicVRegister& src,
3950                      unsigned from_size_in_bits);
3951   LogicVRegister tbl(VectorFormat vform,
3952                      LogicVRegister dst,
3953                      const LogicVRegister& tab,
3954                      const LogicVRegister& ind);
3955   LogicVRegister tbl(VectorFormat vform,
3956                      LogicVRegister dst,
3957                      const LogicVRegister& tab,
3958                      const LogicVRegister& tab2,
3959                      const LogicVRegister& ind);
3960   LogicVRegister tbl(VectorFormat vform,
3961                      LogicVRegister dst,
3962                      const LogicVRegister& tab,
3963                      const LogicVRegister& tab2,
3964                      const LogicVRegister& tab3,
3965                      const LogicVRegister& ind);
3966   LogicVRegister tbl(VectorFormat vform,
3967                      LogicVRegister dst,
3968                      const LogicVRegister& tab,
3969                      const LogicVRegister& tab2,
3970                      const LogicVRegister& tab3,
3971                      const LogicVRegister& tab4,
3972                      const LogicVRegister& ind);
3973   LogicVRegister Table(VectorFormat vform,
3974                        LogicVRegister dst,
3975                        const LogicVRegister& ind,
3976                        bool zero_out_of_bounds,
3977                        const LogicVRegister* tab1,
3978                        const LogicVRegister* tab2 = NULL,
3979                        const LogicVRegister* tab3 = NULL,
3980                        const LogicVRegister* tab4 = NULL);
3981   LogicVRegister tbx(VectorFormat vform,
3982                      LogicVRegister dst,
3983                      const LogicVRegister& tab,
3984                      const LogicVRegister& ind);
3985   LogicVRegister tbx(VectorFormat vform,
3986                      LogicVRegister dst,
3987                      const LogicVRegister& tab,
3988                      const LogicVRegister& tab2,
3989                      const LogicVRegister& ind);
3990   LogicVRegister tbx(VectorFormat vform,
3991                      LogicVRegister dst,
3992                      const LogicVRegister& tab,
3993                      const LogicVRegister& tab2,
3994                      const LogicVRegister& tab3,
3995                      const LogicVRegister& ind);
3996   LogicVRegister tbx(VectorFormat vform,
3997                      LogicVRegister dst,
3998                      const LogicVRegister& tab,
3999                      const LogicVRegister& tab2,
4000                      const LogicVRegister& tab3,
4001                      const LogicVRegister& tab4,
4002                      const LogicVRegister& ind);
4003   LogicVRegister uaddl(VectorFormat vform,
4004                        LogicVRegister dst,
4005                        const LogicVRegister& src1,
4006                        const LogicVRegister& src2);
4007   LogicVRegister uaddl2(VectorFormat vform,
4008                         LogicVRegister dst,
4009                         const LogicVRegister& src1,
4010                         const LogicVRegister& src2);
4011   LogicVRegister uaddw(VectorFormat vform,
4012                        LogicVRegister dst,
4013                        const LogicVRegister& src1,
4014                        const LogicVRegister& src2);
4015   LogicVRegister uaddw2(VectorFormat vform,
4016                         LogicVRegister dst,
4017                         const LogicVRegister& src1,
4018                         const LogicVRegister& src2);
4019   LogicVRegister saddl(VectorFormat vform,
4020                        LogicVRegister dst,
4021                        const LogicVRegister& src1,
4022                        const LogicVRegister& src2);
4023   LogicVRegister saddl2(VectorFormat vform,
4024                         LogicVRegister dst,
4025                         const LogicVRegister& src1,
4026                         const LogicVRegister& src2);
4027   LogicVRegister saddw(VectorFormat vform,
4028                        LogicVRegister dst,
4029                        const LogicVRegister& src1,
4030                        const LogicVRegister& src2);
4031   LogicVRegister saddw2(VectorFormat vform,
4032                         LogicVRegister dst,
4033                         const LogicVRegister& src1,
4034                         const LogicVRegister& src2);
4035   LogicVRegister usubl(VectorFormat vform,
4036                        LogicVRegister dst,
4037                        const LogicVRegister& src1,
4038                        const LogicVRegister& src2);
4039   LogicVRegister usubl2(VectorFormat vform,
4040                         LogicVRegister dst,
4041                         const LogicVRegister& src1,
4042                         const LogicVRegister& src2);
4043   LogicVRegister usubw(VectorFormat vform,
4044                        LogicVRegister dst,
4045                        const LogicVRegister& src1,
4046                        const LogicVRegister& src2);
4047   LogicVRegister usubw2(VectorFormat vform,
4048                         LogicVRegister dst,
4049                         const LogicVRegister& src1,
4050                         const LogicVRegister& src2);
4051   LogicVRegister ssubl(VectorFormat vform,
4052                        LogicVRegister dst,
4053                        const LogicVRegister& src1,
4054                        const LogicVRegister& src2);
4055   LogicVRegister ssubl2(VectorFormat vform,
4056                         LogicVRegister dst,
4057                         const LogicVRegister& src1,
4058                         const LogicVRegister& src2);
4059   LogicVRegister ssubw(VectorFormat vform,
4060                        LogicVRegister dst,
4061                        const LogicVRegister& src1,
4062                        const LogicVRegister& src2);
4063   LogicVRegister ssubw2(VectorFormat vform,
4064                         LogicVRegister dst,
4065                         const LogicVRegister& src1,
4066                         const LogicVRegister& src2);
4067   LogicVRegister uminmax(VectorFormat vform,
4068                          LogicVRegister dst,
4069                          const LogicVRegister& src1,
4070                          const LogicVRegister& src2,
4071                          bool max);
4072   LogicVRegister umax(VectorFormat vform,
4073                       LogicVRegister dst,
4074                       const LogicVRegister& src1,
4075                       const LogicVRegister& src2);
4076   LogicVRegister umin(VectorFormat vform,
4077                       LogicVRegister dst,
4078                       const LogicVRegister& src1,
4079                       const LogicVRegister& src2);
4080   LogicVRegister uminmaxp(VectorFormat vform,
4081                           LogicVRegister dst,
4082                           const LogicVRegister& src1,
4083                           const LogicVRegister& src2,
4084                           bool max);
4085   LogicVRegister umaxp(VectorFormat vform,
4086                        LogicVRegister dst,
4087                        const LogicVRegister& src1,
4088                        const LogicVRegister& src2);
4089   LogicVRegister uminp(VectorFormat vform,
4090                        LogicVRegister dst,
4091                        const LogicVRegister& src1,
4092                        const LogicVRegister& src2);
4093   LogicVRegister uminmaxv(VectorFormat vform,
4094                           LogicVRegister dst,
4095                           const LogicPRegister& pg,
4096                           const LogicVRegister& src,
4097                           bool max);
4098   LogicVRegister umaxv(VectorFormat vform,
4099                        LogicVRegister dst,
4100                        const LogicVRegister& src);
4101   LogicVRegister uminv(VectorFormat vform,
4102                        LogicVRegister dst,
4103                        const LogicVRegister& src);
4104   LogicVRegister trn1(VectorFormat vform,
4105                       LogicVRegister dst,
4106                       const LogicVRegister& src1,
4107                       const LogicVRegister& src2);
4108   LogicVRegister trn2(VectorFormat vform,
4109                       LogicVRegister dst,
4110                       const LogicVRegister& src1,
4111                       const LogicVRegister& src2);
4112   LogicVRegister zip1(VectorFormat vform,
4113                       LogicVRegister dst,
4114                       const LogicVRegister& src1,
4115                       const LogicVRegister& src2);
4116   LogicVRegister zip2(VectorFormat vform,
4117                       LogicVRegister dst,
4118                       const LogicVRegister& src1,
4119                       const LogicVRegister& src2);
4120   LogicVRegister uzp1(VectorFormat vform,
4121                       LogicVRegister dst,
4122                       const LogicVRegister& src1,
4123                       const LogicVRegister& src2);
4124   LogicVRegister uzp2(VectorFormat vform,
4125                       LogicVRegister dst,
4126                       const LogicVRegister& src1,
4127                       const LogicVRegister& src2);
4128   LogicVRegister shl(VectorFormat vform,
4129                      LogicVRegister dst,
4130                      const LogicVRegister& src,
4131                      int shift);
4132   LogicVRegister scvtf(VectorFormat vform,
4133                        unsigned dst_data_size_in_bits,
4134                        unsigned src_data_size_in_bits,
4135                        LogicVRegister dst,
4136                        const LogicPRegister& pg,
4137                        const LogicVRegister& src,
4138                        FPRounding round,
4139                        int fbits = 0);
4140   LogicVRegister scvtf(VectorFormat vform,
4141                        LogicVRegister dst,
4142                        const LogicVRegister& src,
4143                        int fbits,
4144                        FPRounding rounding_mode);
4145   LogicVRegister ucvtf(VectorFormat vform,
4146                        unsigned dst_data_size,
4147                        unsigned src_data_size,
4148                        LogicVRegister dst,
4149                        const LogicPRegister& pg,
4150                        const LogicVRegister& src,
4151                        FPRounding round,
4152                        int fbits = 0);
4153   LogicVRegister ucvtf(VectorFormat vform,
4154                        LogicVRegister dst,
4155                        const LogicVRegister& src,
4156                        int fbits,
4157                        FPRounding rounding_mode);
4158   LogicVRegister sshll(VectorFormat vform,
4159                        LogicVRegister dst,
4160                        const LogicVRegister& src,
4161                        int shift);
4162   LogicVRegister sshll2(VectorFormat vform,
4163                         LogicVRegister dst,
4164                         const LogicVRegister& src,
4165                         int shift);
4166   LogicVRegister shll(VectorFormat vform,
4167                       LogicVRegister dst,
4168                       const LogicVRegister& src);
4169   LogicVRegister shll2(VectorFormat vform,
4170                        LogicVRegister dst,
4171                        const LogicVRegister& src);
4172   LogicVRegister ushll(VectorFormat vform,
4173                        LogicVRegister dst,
4174                        const LogicVRegister& src,
4175                        int shift);
4176   LogicVRegister ushll2(VectorFormat vform,
4177                         LogicVRegister dst,
4178                         const LogicVRegister& src,
4179                         int shift);
4180   LogicVRegister sli(VectorFormat vform,
4181                      LogicVRegister dst,
4182                      const LogicVRegister& src,
4183                      int shift);
4184   LogicVRegister sri(VectorFormat vform,
4185                      LogicVRegister dst,
4186                      const LogicVRegister& src,
4187                      int shift);
4188   LogicVRegister sshr(VectorFormat vform,
4189                       LogicVRegister dst,
4190                       const LogicVRegister& src,
4191                       int shift);
4192   LogicVRegister ushr(VectorFormat vform,
4193                       LogicVRegister dst,
4194                       const LogicVRegister& src,
4195                       int shift);
4196   LogicVRegister ssra(VectorFormat vform,
4197                       LogicVRegister dst,
4198                       const LogicVRegister& src,
4199                       int shift);
4200   LogicVRegister usra(VectorFormat vform,
4201                       LogicVRegister dst,
4202                       const LogicVRegister& src,
4203                       int shift);
4204   LogicVRegister srsra(VectorFormat vform,
4205                        LogicVRegister dst,
4206                        const LogicVRegister& src,
4207                        int shift);
4208   LogicVRegister ursra(VectorFormat vform,
4209                        LogicVRegister dst,
4210                        const LogicVRegister& src,
4211                        int shift);
4212   LogicVRegister suqadd(VectorFormat vform,
4213                         LogicVRegister dst,
4214                         const LogicVRegister& src1,
4215                         const LogicVRegister& src2);
4216   LogicVRegister usqadd(VectorFormat vform,
4217                         LogicVRegister dst,
4218                         const LogicVRegister& src1,
4219                         const LogicVRegister& src2);
4220   LogicVRegister sqshl(VectorFormat vform,
4221                        LogicVRegister dst,
4222                        const LogicVRegister& src,
4223                        int shift);
4224   LogicVRegister uqshl(VectorFormat vform,
4225                        LogicVRegister dst,
4226                        const LogicVRegister& src,
4227                        int shift);
4228   LogicVRegister sqshlu(VectorFormat vform,
4229                         LogicVRegister dst,
4230                         const LogicVRegister& src,
4231                         int shift);
4232   LogicVRegister abs(VectorFormat vform,
4233                      LogicVRegister dst,
4234                      const LogicVRegister& src);
4235   LogicVRegister neg(VectorFormat vform,
4236                      LogicVRegister dst,
4237                      const LogicVRegister& src);
4238   LogicVRegister extractnarrow(VectorFormat vform,
4239                                LogicVRegister dst,
4240                                bool dst_is_signed,
4241                                const LogicVRegister& src,
4242                                bool src_is_signed);
4243   LogicVRegister xtn(VectorFormat vform,
4244                      LogicVRegister dst,
4245                      const LogicVRegister& src);
4246   LogicVRegister sqxtn(VectorFormat vform,
4247                        LogicVRegister dst,
4248                        const LogicVRegister& src);
4249   LogicVRegister uqxtn(VectorFormat vform,
4250                        LogicVRegister dst,
4251                        const LogicVRegister& src);
4252   LogicVRegister sqxtun(VectorFormat vform,
4253                         LogicVRegister dst,
4254                         const LogicVRegister& src);
4255   LogicVRegister absdiff(VectorFormat vform,
4256                          LogicVRegister dst,
4257                          const LogicVRegister& src1,
4258                          const LogicVRegister& src2,
4259                          bool is_signed);
4260   LogicVRegister saba(VectorFormat vform,
4261                       LogicVRegister dst,
4262                       const LogicVRegister& src1,
4263                       const LogicVRegister& src2);
4264   LogicVRegister uaba(VectorFormat vform,
4265                       LogicVRegister dst,
4266                       const LogicVRegister& src1,
4267                       const LogicVRegister& src2);
4268   LogicVRegister shrn(VectorFormat vform,
4269                       LogicVRegister dst,
4270                       const LogicVRegister& src,
4271                       int shift);
4272   LogicVRegister shrn2(VectorFormat vform,
4273                        LogicVRegister dst,
4274                        const LogicVRegister& src,
4275                        int shift);
4276   LogicVRegister rshrn(VectorFormat vform,
4277                        LogicVRegister dst,
4278                        const LogicVRegister& src,
4279                        int shift);
4280   LogicVRegister rshrn2(VectorFormat vform,
4281                         LogicVRegister dst,
4282                         const LogicVRegister& src,
4283                         int shift);
4284   LogicVRegister uqshrn(VectorFormat vform,
4285                         LogicVRegister dst,
4286                         const LogicVRegister& src,
4287                         int shift);
4288   LogicVRegister uqshrn2(VectorFormat vform,
4289                          LogicVRegister dst,
4290                          const LogicVRegister& src,
4291                          int shift);
4292   LogicVRegister uqrshrn(VectorFormat vform,
4293                          LogicVRegister dst,
4294                          const LogicVRegister& src,
4295                          int shift);
4296   LogicVRegister uqrshrn2(VectorFormat vform,
4297                           LogicVRegister dst,
4298                           const LogicVRegister& src,
4299                           int shift);
4300   LogicVRegister sqshrn(VectorFormat vform,
4301                         LogicVRegister dst,
4302                         const LogicVRegister& src,
4303                         int shift);
4304   LogicVRegister sqshrn2(VectorFormat vform,
4305                          LogicVRegister dst,
4306                          const LogicVRegister& src,
4307                          int shift);
4308   LogicVRegister sqrshrn(VectorFormat vform,
4309                          LogicVRegister dst,
4310                          const LogicVRegister& src,
4311                          int shift);
4312   LogicVRegister sqrshrn2(VectorFormat vform,
4313                           LogicVRegister dst,
4314                           const LogicVRegister& src,
4315                           int shift);
4316   LogicVRegister sqshrun(VectorFormat vform,
4317                          LogicVRegister dst,
4318                          const LogicVRegister& src,
4319                          int shift);
4320   LogicVRegister sqshrun2(VectorFormat vform,
4321                           LogicVRegister dst,
4322                           const LogicVRegister& src,
4323                           int shift);
4324   LogicVRegister sqrshrun(VectorFormat vform,
4325                           LogicVRegister dst,
4326                           const LogicVRegister& src,
4327                           int shift);
4328   LogicVRegister sqrshrun2(VectorFormat vform,
4329                            LogicVRegister dst,
4330                            const LogicVRegister& src,
4331                            int shift);
4332   LogicVRegister sqrdmulh(VectorFormat vform,
4333                           LogicVRegister dst,
4334                           const LogicVRegister& src1,
4335                           const LogicVRegister& src2,
4336                           bool round = true);
4337   LogicVRegister dot(VectorFormat vform,
4338                      LogicVRegister dst,
4339                      const LogicVRegister& src1,
4340                      const LogicVRegister& src2,
4341                      bool is_src1_signed,
4342                      bool is_src2_signed);
4343   LogicVRegister sdot(VectorFormat vform,
4344                       LogicVRegister dst,
4345                       const LogicVRegister& src1,
4346                       const LogicVRegister& src2);
4347   LogicVRegister udot(VectorFormat vform,
4348                       LogicVRegister dst,
4349                       const LogicVRegister& src1,
4350                       const LogicVRegister& src2);
4351   LogicVRegister usdot(VectorFormat vform,
4352                        LogicVRegister dst,
4353                        const LogicVRegister& src1,
4354                        const LogicVRegister& src2);
4355   LogicVRegister cdot(VectorFormat vform,
4356                       LogicVRegister dst,
4357                       const LogicVRegister& acc,
4358                       const LogicVRegister& src1,
4359                       const LogicVRegister& src2,
4360                       int rot);
4361   LogicVRegister sqrdcmlah(VectorFormat vform,
4362                            LogicVRegister dst,
4363                            const LogicVRegister& srca,
4364                            const LogicVRegister& src1,
4365                            const LogicVRegister& src2,
4366                            int rot);
4367   LogicVRegister sqrdcmlah(VectorFormat vform,
4368                            LogicVRegister dst,
4369                            const LogicVRegister& srca,
4370                            const LogicVRegister& src1,
4371                            const LogicVRegister& src2,
4372                            int index,
4373                            int rot);
4374   LogicVRegister sqrdmlash(VectorFormat vform,
4375                            LogicVRegister dst,
4376                            const LogicVRegister& src1,
4377                            const LogicVRegister& src2,
4378                            bool round = true,
4379                            bool sub_op = false);
4380   LogicVRegister sqrdmlash_d(VectorFormat vform,
4381                              LogicVRegister dst,
4382                              const LogicVRegister& src1,
4383                              const LogicVRegister& src2,
4384                              bool round = true,
4385                              bool sub_op = false);
4386   LogicVRegister sqrdmlah(VectorFormat vform,
4387                           LogicVRegister dst,
4388                           const LogicVRegister& src1,
4389                           const LogicVRegister& src2,
4390                           bool round = true);
4391   LogicVRegister sqrdmlsh(VectorFormat vform,
4392                           LogicVRegister dst,
4393                           const LogicVRegister& src1,
4394                           const LogicVRegister& src2,
4395                           bool round = true);
4396   LogicVRegister sqdmulh(VectorFormat vform,
4397                          LogicVRegister dst,
4398                          const LogicVRegister& src1,
4399                          const LogicVRegister& src2);
4400   LogicVRegister matmul(VectorFormat vform_dst,
4401                         LogicVRegister dst,
4402                         const LogicVRegister& src1,
4403                         const LogicVRegister& src2,
4404                         bool src1_signed,
4405                         bool src2_signed);
4406   template <typename T>
4407   LogicVRegister fmatmul(VectorFormat vform,
4408                          LogicVRegister srcdst,
4409                          const LogicVRegister& src1,
4410                          const LogicVRegister& src2);
4411   LogicVRegister fmatmul(VectorFormat vform,
4412                          LogicVRegister srcdst,
4413                          const LogicVRegister& src1,
4414                          const LogicVRegister& src2);
4415 #define NEON_3VREG_LOGIC_LIST(V) \
4416   V(addhn)                       \
4417   V(addhn2)                      \
4418   V(raddhn)                      \
4419   V(raddhn2)                     \
4420   V(subhn)                       \
4421   V(subhn2)                      \
4422   V(rsubhn)                      \
4423   V(rsubhn2)                     \
4424   V(pmull)                       \
4425   V(pmull2)                      \
4426   V(sabal)                       \
4427   V(sabal2)                      \
4428   V(uabal)                       \
4429   V(uabal2)                      \
4430   V(sabdl)                       \
4431   V(sabdl2)                      \
4432   V(uabdl)                       \
4433   V(uabdl2)                      \
4434   V(smull2)                      \
4435   V(umull2)                      \
4436   V(smlal2)                      \
4437   V(umlal2)                      \
4438   V(smlsl2)                      \
4439   V(umlsl2)                      \
4440   V(sqdmlal2)                    \
4441   V(sqdmlsl2)                    \
4442   V(sqdmull2)
4443 
4444 #define DEFINE_LOGIC_FUNC(FXN)                   \
4445   LogicVRegister FXN(VectorFormat vform,         \
4446                      LogicVRegister dst,         \
4447                      const LogicVRegister& src1, \
4448                      const LogicVRegister& src2);
4449   NEON_3VREG_LOGIC_LIST(DEFINE_LOGIC_FUNC)
4450 #undef DEFINE_LOGIC_FUNC
4451 
4452 #define NEON_MULL_LIST(V) \
4453   V(smull)                \
4454   V(umull)                \
4455   V(smlal)                \
4456   V(umlal)                \
4457   V(smlsl)                \
4458   V(umlsl)                \
4459   V(sqdmlal)              \
4460   V(sqdmlsl)              \
4461   V(sqdmull)
4462 
4463 #define DECLARE_NEON_MULL_OP(FN)                \
4464   LogicVRegister FN(VectorFormat vform,         \
4465                     LogicVRegister dst,         \
4466                     const LogicVRegister& src1, \
4467                     const LogicVRegister& src2, \
4468                     bool is_2 = false);
4469   NEON_MULL_LIST(DECLARE_NEON_MULL_OP)
4470 #undef DECLARE_NEON_MULL_OP
4471 
4472 #define NEON_FP3SAME_LIST(V) \
4473   V(fadd, FPAdd, false)      \
4474   V(fsub, FPSub, true)       \
4475   V(fmul, FPMul, true)       \
4476   V(fmulx, FPMulx, true)     \
4477   V(fdiv, FPDiv, true)       \
4478   V(fmax, FPMax, false)      \
4479   V(fmin, FPMin, false)      \
4480   V(fmaxnm, FPMaxNM, false)  \
4481   V(fminnm, FPMinNM, false)
4482 
4483 #define DECLARE_NEON_FP_VECTOR_OP(FN, OP, PROCNAN) \
4484   template <typename T>                            \
4485   LogicVRegister FN(VectorFormat vform,            \
4486                     LogicVRegister dst,            \
4487                     const LogicVRegister& src1,    \
4488                     const LogicVRegister& src2);   \
4489   LogicVRegister FN(VectorFormat vform,            \
4490                     LogicVRegister dst,            \
4491                     const LogicVRegister& src1,    \
4492                     const LogicVRegister& src2);
4493   NEON_FP3SAME_LIST(DECLARE_NEON_FP_VECTOR_OP)
4494 #undef DECLARE_NEON_FP_VECTOR_OP
4495 
4496 #define NEON_FPPAIRWISE_LIST(V) \
4497   V(faddp, fadd, FPAdd)         \
4498   V(fmaxp, fmax, FPMax)         \
4499   V(fmaxnmp, fmaxnm, FPMaxNM)   \
4500   V(fminp, fmin, FPMin)         \
4501   V(fminnmp, fminnm, FPMinNM)
4502 
4503 #define DECLARE_NEON_FP_PAIR_OP(FNP, FN, OP)      \
4504   LogicVRegister FNP(VectorFormat vform,          \
4505                      LogicVRegister dst,          \
4506                      const LogicVRegister& src1,  \
4507                      const LogicVRegister& src2); \
4508   LogicVRegister FNP(VectorFormat vform,          \
4509                      LogicVRegister dst,          \
4510                      const LogicVRegister& src);
4511   NEON_FPPAIRWISE_LIST(DECLARE_NEON_FP_PAIR_OP)
4512 #undef DECLARE_NEON_FP_PAIR_OP
4513 
4514   enum FrintMode {
4515     kFrintToInteger = 0,
4516     kFrintToInt32 = 32,
4517     kFrintToInt64 = 64
4518   };
4519 
4520   template <typename T>
4521   LogicVRegister frecps(VectorFormat vform,
4522                         LogicVRegister dst,
4523                         const LogicVRegister& src1,
4524                         const LogicVRegister& src2);
4525   LogicVRegister frecps(VectorFormat vform,
4526                         LogicVRegister dst,
4527                         const LogicVRegister& src1,
4528                         const LogicVRegister& src2);
4529   template <typename T>
4530   LogicVRegister frsqrts(VectorFormat vform,
4531                          LogicVRegister dst,
4532                          const LogicVRegister& src1,
4533                          const LogicVRegister& src2);
4534   LogicVRegister frsqrts(VectorFormat vform,
4535                          LogicVRegister dst,
4536                          const LogicVRegister& src1,
4537                          const LogicVRegister& src2);
4538   template <typename T>
4539   LogicVRegister fmla(VectorFormat vform,
4540                       LogicVRegister dst,
4541                       const LogicVRegister& srca,
4542                       const LogicVRegister& src1,
4543                       const LogicVRegister& src2);
4544   LogicVRegister fmla(VectorFormat vform,
4545                       LogicVRegister dst,
4546                       const LogicVRegister& srca,
4547                       const LogicVRegister& src1,
4548                       const LogicVRegister& src2);
4549   template <typename T>
4550   LogicVRegister fmls(VectorFormat vform,
4551                       LogicVRegister dst,
4552                       const LogicVRegister& srca,
4553                       const LogicVRegister& src1,
4554                       const LogicVRegister& src2);
4555   LogicVRegister fmls(VectorFormat vform,
4556                       LogicVRegister dst,
4557                       const LogicVRegister& srca,
4558                       const LogicVRegister& src1,
4559                       const LogicVRegister& src2);
4560   LogicVRegister fnmul(VectorFormat vform,
4561                        LogicVRegister dst,
4562                        const LogicVRegister& src1,
4563                        const LogicVRegister& src2);
4564 
4565   LogicVRegister fmlal(VectorFormat vform,
4566                        LogicVRegister dst,
4567                        const LogicVRegister& src1,
4568                        const LogicVRegister& src2);
4569   LogicVRegister fmlal2(VectorFormat vform,
4570                         LogicVRegister dst,
4571                         const LogicVRegister& src1,
4572                         const LogicVRegister& src2);
4573   LogicVRegister fmlsl(VectorFormat vform,
4574                        LogicVRegister dst,
4575                        const LogicVRegister& src1,
4576                        const LogicVRegister& src2);
4577   LogicVRegister fmlsl2(VectorFormat vform,
4578                         LogicVRegister dst,
4579                         const LogicVRegister& src1,
4580                         const LogicVRegister& src2);
4581 
4582   template <typename T>
4583   LogicVRegister fcmp(VectorFormat vform,
4584                       LogicVRegister dst,
4585                       const LogicVRegister& src1,
4586                       const LogicVRegister& src2,
4587                       Condition cond);
4588   LogicVRegister fcmp(VectorFormat vform,
4589                       LogicVRegister dst,
4590                       const LogicVRegister& src1,
4591                       const LogicVRegister& src2,
4592                       Condition cond);
4593   LogicVRegister fabscmp(VectorFormat vform,
4594                          LogicVRegister dst,
4595                          const LogicVRegister& src1,
4596                          const LogicVRegister& src2,
4597                          Condition cond);
4598   LogicVRegister fcmp_zero(VectorFormat vform,
4599                            LogicVRegister dst,
4600                            const LogicVRegister& src,
4601                            Condition cond);
4602 
4603   template <typename T>
4604   LogicVRegister fneg(VectorFormat vform,
4605                       LogicVRegister dst,
4606                       const LogicVRegister& src);
4607   LogicVRegister fneg(VectorFormat vform,
4608                       LogicVRegister dst,
4609                       const LogicVRegister& src);
4610   template <typename T>
4611   LogicVRegister frecpx(VectorFormat vform,
4612                         LogicVRegister dst,
4613                         const LogicVRegister& src);
4614   LogicVRegister frecpx(VectorFormat vform,
4615                         LogicVRegister dst,
4616                         const LogicVRegister& src);
4617   LogicVRegister ftsmul(VectorFormat vform,
4618                         LogicVRegister dst,
4619                         const LogicVRegister& src1,
4620                         const LogicVRegister& src2);
4621   LogicVRegister ftssel(VectorFormat vform,
4622                         LogicVRegister dst,
4623                         const LogicVRegister& src1,
4624                         const LogicVRegister& src2);
4625   LogicVRegister ftmad(VectorFormat vform,
4626                        LogicVRegister dst,
4627                        const LogicVRegister& src1,
4628                        const LogicVRegister& src2,
4629                        unsigned index);
4630   LogicVRegister fexpa(VectorFormat vform,
4631                        LogicVRegister dst,
4632                        const LogicVRegister& src);
4633   LogicVRegister flogb(VectorFormat vform,
4634                        LogicVRegister dst,
4635                        const LogicVRegister& src);
4636   template <typename T>
4637   LogicVRegister fscale(VectorFormat vform,
4638                         LogicVRegister dst,
4639                         const LogicVRegister& src1,
4640                         const LogicVRegister& src2);
4641   LogicVRegister fscale(VectorFormat vform,
4642                         LogicVRegister dst,
4643                         const LogicVRegister& src1,
4644                         const LogicVRegister& src2);
4645   template <typename T>
4646   LogicVRegister fabs_(VectorFormat vform,
4647                        LogicVRegister dst,
4648                        const LogicVRegister& src);
4649   LogicVRegister fabs_(VectorFormat vform,
4650                        LogicVRegister dst,
4651                        const LogicVRegister& src);
4652   LogicVRegister fabd(VectorFormat vform,
4653                       LogicVRegister dst,
4654                       const LogicVRegister& src1,
4655                       const LogicVRegister& src2);
4656   LogicVRegister frint(VectorFormat vform,
4657                        LogicVRegister dst,
4658                        const LogicVRegister& src,
4659                        FPRounding rounding_mode,
4660                        bool inexact_exception = false,
4661                        FrintMode frint_mode = kFrintToInteger);
4662   LogicVRegister fcvt(VectorFormat dst_vform,
4663                       VectorFormat src_vform,
4664                       LogicVRegister dst,
4665                       const LogicPRegister& pg,
4666                       const LogicVRegister& src);
4667   LogicVRegister fcvts(VectorFormat vform,
4668                        unsigned dst_data_size_in_bits,
4669                        unsigned src_data_size_in_bits,
4670                        LogicVRegister dst,
4671                        const LogicPRegister& pg,
4672                        const LogicVRegister& src,
4673                        FPRounding round,
4674                        int fbits = 0);
4675   LogicVRegister fcvts(VectorFormat vform,
4676                        LogicVRegister dst,
4677                        const LogicVRegister& src,
4678                        FPRounding rounding_mode,
4679                        int fbits = 0);
4680   LogicVRegister fcvtu(VectorFormat vform,
4681                        unsigned dst_data_size_in_bits,
4682                        unsigned src_data_size_in_bits,
4683                        LogicVRegister dst,
4684                        const LogicPRegister& pg,
4685                        const LogicVRegister& src,
4686                        FPRounding round,
4687                        int fbits = 0);
4688   LogicVRegister fcvtu(VectorFormat vform,
4689                        LogicVRegister dst,
4690                        const LogicVRegister& src,
4691                        FPRounding rounding_mode,
4692                        int fbits = 0);
4693   LogicVRegister fcvtl(VectorFormat vform,
4694                        LogicVRegister dst,
4695                        const LogicVRegister& src);
4696   LogicVRegister fcvtl2(VectorFormat vform,
4697                         LogicVRegister dst,
4698                         const LogicVRegister& src);
4699   LogicVRegister fcvtn(VectorFormat vform,
4700                        LogicVRegister dst,
4701                        const LogicVRegister& src);
4702   LogicVRegister fcvtn2(VectorFormat vform,
4703                         LogicVRegister dst,
4704                         const LogicVRegister& src);
4705   LogicVRegister fcvtxn(VectorFormat vform,
4706                         LogicVRegister dst,
4707                         const LogicVRegister& src);
4708   LogicVRegister fcvtxn2(VectorFormat vform,
4709                          LogicVRegister dst,
4710                          const LogicVRegister& src);
4711   LogicVRegister fsqrt(VectorFormat vform,
4712                        LogicVRegister dst,
4713                        const LogicVRegister& src);
4714   LogicVRegister frsqrte(VectorFormat vform,
4715                          LogicVRegister dst,
4716                          const LogicVRegister& src);
4717   LogicVRegister frecpe(VectorFormat vform,
4718                         LogicVRegister dst,
4719                         const LogicVRegister& src,
4720                         FPRounding rounding);
4721   LogicVRegister ursqrte(VectorFormat vform,
4722                          LogicVRegister dst,
4723                          const LogicVRegister& src);
4724   LogicVRegister urecpe(VectorFormat vform,
4725                         LogicVRegister dst,
4726                         const LogicVRegister& src);
4727 
4728   LogicPRegister pfalse(LogicPRegister dst);
4729   LogicPRegister pfirst(LogicPRegister dst,
4730                         const LogicPRegister& pg,
4731                         const LogicPRegister& src);
4732   LogicPRegister ptrue(VectorFormat vform, LogicPRegister dst, int pattern);
4733   LogicPRegister pnext(VectorFormat vform,
4734                        LogicPRegister dst,
4735                        const LogicPRegister& pg,
4736                        const LogicPRegister& src);
4737 
4738   LogicVRegister asrd(VectorFormat vform,
4739                       LogicVRegister dst,
4740                       const LogicVRegister& src1,
4741                       int shift);
4742 
4743   LogicVRegister andv(VectorFormat vform,
4744                       LogicVRegister dst,
4745                       const LogicPRegister& pg,
4746                       const LogicVRegister& src);
4747   LogicVRegister eorv(VectorFormat vform,
4748                       LogicVRegister dst,
4749                       const LogicPRegister& pg,
4750                       const LogicVRegister& src);
4751   LogicVRegister orv(VectorFormat vform,
4752                      LogicVRegister dst,
4753                      const LogicPRegister& pg,
4754                      const LogicVRegister& src);
4755   LogicVRegister saddv(VectorFormat vform,
4756                        LogicVRegister dst,
4757                        const LogicPRegister& pg,
4758                        const LogicVRegister& src);
4759   LogicVRegister sminv(VectorFormat vform,
4760                        LogicVRegister dst,
4761                        const LogicPRegister& pg,
4762                        const LogicVRegister& src);
4763   LogicVRegister smaxv(VectorFormat vform,
4764                        LogicVRegister dst,
4765                        const LogicPRegister& pg,
4766                        const LogicVRegister& src);
4767   LogicVRegister uaddv(VectorFormat vform,
4768                        LogicVRegister dst,
4769                        const LogicPRegister& pg,
4770                        const LogicVRegister& src);
4771   LogicVRegister uminv(VectorFormat vform,
4772                        LogicVRegister dst,
4773                        const LogicPRegister& pg,
4774                        const LogicVRegister& src);
4775   LogicVRegister umaxv(VectorFormat vform,
4776                        LogicVRegister dst,
4777                        const LogicPRegister& pg,
4778                        const LogicVRegister& src);
4779 
4780   LogicVRegister interleave_top_bottom(VectorFormat vform,
4781                                        LogicVRegister dst,
4782                                        const LogicVRegister& src);
4783 
4784   template <typename T>
4785   struct TFPPairOp {
4786     typedef T (Simulator::*type)(T a, T b);
4787   };
4788 
4789   template <typename T>
4790   LogicVRegister FPPairedAcrossHelper(VectorFormat vform,
4791                                       LogicVRegister dst,
4792                                       const LogicVRegister& src,
4793                                       typename TFPPairOp<T>::type fn,
4794                                       uint64_t inactive_value);
4795 
4796   LogicVRegister FPPairedAcrossHelper(
4797       VectorFormat vform,
4798       LogicVRegister dst,
4799       const LogicVRegister& src,
4800       typename TFPPairOp<vixl::internal::SimFloat16>::type fn16,
4801       typename TFPPairOp<float>::type fn32,
4802       typename TFPPairOp<double>::type fn64,
4803       uint64_t inactive_value);
4804 
4805   LogicVRegister fminv(VectorFormat vform,
4806                        LogicVRegister dst,
4807                        const LogicVRegister& src);
4808   LogicVRegister fmaxv(VectorFormat vform,
4809                        LogicVRegister dst,
4810                        const LogicVRegister& src);
4811   LogicVRegister fminnmv(VectorFormat vform,
4812                          LogicVRegister dst,
4813                          const LogicVRegister& src);
4814   LogicVRegister fmaxnmv(VectorFormat vform,
4815                          LogicVRegister dst,
4816                          const LogicVRegister& src);
4817   LogicVRegister faddv(VectorFormat vform,
4818                        LogicVRegister dst,
4819                        const LogicVRegister& src);
4820 
4821   static const uint32_t CRC32_POLY = 0x04C11DB7;
4822   static const uint32_t CRC32C_POLY = 0x1EDC6F41;
4823   uint32_t Poly32Mod2(unsigned n, uint64_t data, uint32_t poly);
4824   template <typename T>
4825   uint32_t Crc32Checksum(uint32_t acc, T val, uint32_t poly);
4826   uint32_t Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly);
4827 
4828   void SysOp_W(int op, int64_t val);
4829 
4830   template <typename T>
4831   T FPRecipSqrtEstimate(T op);
4832   template <typename T>
4833   T FPRecipEstimate(T op, FPRounding rounding);
4834   template <typename T, typename R>
4835   R FPToFixed(T op, int fbits, bool is_signed, FPRounding rounding);
4836 
4837   void FPCompare(double val0, double val1, FPTrapFlags trap);
4838   double FPRoundInt(double value, FPRounding round_mode);
4839   double FPRoundInt(double value, FPRounding round_mode, FrintMode frint_mode);
4840   double FPRoundIntCommon(double value, FPRounding round_mode);
4841   double recip_sqrt_estimate(double a);
4842   double recip_estimate(double a);
4843   double FPRecipSqrtEstimate(double a);
4844   double FPRecipEstimate(double a);
4845   double FixedToDouble(int64_t src, int fbits, FPRounding round_mode);
4846   double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode);
4847   float FixedToFloat(int64_t src, int fbits, FPRounding round_mode);
4848   float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode);
4849   ::vixl::internal::SimFloat16 FixedToFloat16(int64_t src,
4850                                               int fbits,
4851                                               FPRounding round_mode);
4852   ::vixl::internal::SimFloat16 UFixedToFloat16(uint64_t src,
4853                                                int fbits,
4854                                                FPRounding round_mode);
4855   int16_t FPToInt16(double value, FPRounding rmode);
4856   int32_t FPToInt32(double value, FPRounding rmode);
4857   int64_t FPToInt64(double value, FPRounding rmode);
4858   uint16_t FPToUInt16(double value, FPRounding rmode);
4859   uint32_t FPToUInt32(double value, FPRounding rmode);
4860   uint64_t FPToUInt64(double value, FPRounding rmode);
4861   int32_t FPToFixedJS(double value);
4862 
4863   template <typename T>
4864   T FPAdd(T op1, T op2);
4865 
4866   template <typename T>
4867   T FPNeg(T op);
4868 
4869   template <typename T>
4870   T FPDiv(T op1, T op2);
4871 
4872   template <typename T>
4873   T FPMax(T a, T b);
4874 
4875   template <typename T>
4876   T FPMaxNM(T a, T b);
4877 
4878   template <typename T>
4879   T FPMin(T a, T b);
4880 
4881   template <typename T>
4882   T FPMinNM(T a, T b);
4883 
4884   template <typename T>
4885   T FPMulNaNs(T op1, T op2);
4886 
4887   template <typename T>
4888   T FPMul(T op1, T op2);
4889 
4890   template <typename T>
4891   T FPMulx(T op1, T op2);
4892 
4893   template <typename T>
4894   T FPMulAdd(T a, T op1, T op2);
4895 
4896   template <typename T>
4897   T FPSqrt(T op);
4898 
4899   template <typename T>
4900   T FPSub(T op1, T op2);
4901 
4902   template <typename T>
4903   T FPRecipStepFused(T op1, T op2);
4904 
4905   template <typename T>
4906   T FPRSqrtStepFused(T op1, T op2);
4907 
4908   // This doesn't do anything at the moment. We'll need it if we want support
4909   // for cumulative exception bits or floating-point exceptions.
4910   void FPProcessException() {}
4911 
4912   bool FPProcessNaNs(const Instruction* instr);
4913 
4914   // Pseudo Printf instruction
4915   void DoPrintf(const Instruction* instr);
4916 
4917   // Pseudo-instructions to configure CPU features dynamically.
4918   void DoConfigureCPUFeatures(const Instruction* instr);
4919 
4920   void DoSaveCPUFeatures(const Instruction* instr);
4921   void DoRestoreCPUFeatures(const Instruction* instr);
4922 
4923   // General arithmetic helpers ----------------------------
4924 
4925   // Add `delta` to the accumulator (`acc`), optionally saturate, then zero- or
4926   // sign-extend. Initial `acc` bits outside `n` are ignored, but the delta must
4927   // be a valid int<n>_t.
4928   uint64_t IncDecN(uint64_t acc,
4929                    int64_t delta,
4930                    unsigned n,
4931                    bool is_saturating = false,
4932                    bool is_signed = false);
4933 
4934   // SVE helpers -------------------------------------------
4935   LogicVRegister SVEBitwiseLogicalUnpredicatedHelper(LogicalOp op,
4936                                                      VectorFormat vform,
4937                                                      LogicVRegister zd,
4938                                                      const LogicVRegister& zn,
4939                                                      const LogicVRegister& zm);
4940 
4941   LogicPRegister SVEPredicateLogicalHelper(SVEPredicateLogicalOp op,
4942                                            LogicPRegister Pd,
4943                                            const LogicPRegister& pn,
4944                                            const LogicPRegister& pm);
4945 
4946   LogicVRegister SVEBitwiseImmHelper(SVEBitwiseLogicalWithImm_UnpredicatedOp op,
4947                                      VectorFormat vform,
4948                                      LogicVRegister zd,
4949                                      uint64_t imm);
4950   enum UnpackType { kHiHalf, kLoHalf };
4951   enum ExtendType { kSignedExtend, kUnsignedExtend };
4952   LogicVRegister unpk(VectorFormat vform,
4953                       LogicVRegister zd,
4954                       const LogicVRegister& zn,
4955                       UnpackType unpack_type,
4956                       ExtendType extend_type);
4957 
4958   LogicPRegister SVEIntCompareVectorsHelper(Condition cc,
4959                                             VectorFormat vform,
4960                                             LogicPRegister dst,
4961                                             const LogicPRegister& mask,
4962                                             const LogicVRegister& src1,
4963                                             const LogicVRegister& src2,
4964                                             bool is_wide_elements = false,
4965                                             FlagsUpdate flags = SetFlags);
4966 
4967   void SVEGatherLoadScalarPlusVectorHelper(const Instruction* instr,
4968                                            VectorFormat vform,
4969                                            SVEOffsetModifier mod);
4970 
4971   // Store each active zt<i>[lane] to `addr.GetElementAddress(lane, ...)`.
4972   //
4973   // `zt_code` specifies the code of the first register (zt). Each additional
4974   // register (up to `reg_count`) is `(zt_code + i) % 32`.
4975   //
4976   // This helper calls LogZWrite in the proper way, according to `addr`.
4977   void SVEStructuredStoreHelper(VectorFormat vform,
4978                                 const LogicPRegister& pg,
4979                                 unsigned zt_code,
4980                                 const LogicSVEAddressVector& addr);
4981   // Load each active zt<i>[lane] from `addr.GetElementAddress(lane, ...)`.
4982   void SVEStructuredLoadHelper(VectorFormat vform,
4983                                const LogicPRegister& pg,
4984                                unsigned zt_code,
4985                                const LogicSVEAddressVector& addr,
4986                                bool is_signed = false);
4987 
4988   enum SVEFaultTolerantLoadType {
4989     // - Elements active in both FFR and pg are accessed as usual. If the access
4990     //   fails, the corresponding lane and all subsequent lanes are filled with
4991     //   an unpredictable value, and made inactive in FFR.
4992     //
4993     // - Elements active in FFR but not pg are set to zero.
4994     //
4995     // - Elements that are not active in FFR are filled with an unpredictable
4996     //   value, regardless of pg.
4997     kSVENonFaultLoad,
4998 
4999     // If type == kSVEFirstFaultLoad, the behaviour is the same, except that the
5000     // first active element is always accessed, regardless of FFR, and will
5001     // generate a real fault if it is inaccessible. If the lane is not active in
5002     // FFR, the actual value loaded into the result is still unpredictable.
5003     kSVEFirstFaultLoad
5004   };
5005 
5006   // Load with first-faulting or non-faulting load semantics, respecting and
5007   // updating FFR.
5008   void SVEFaultTolerantLoadHelper(VectorFormat vform,
5009                                   const LogicPRegister& pg,
5010                                   unsigned zt_code,
5011                                   const LogicSVEAddressVector& addr,
5012                                   SVEFaultTolerantLoadType type,
5013                                   bool is_signed);
5014 
5015   LogicVRegister SVEBitwiseShiftHelper(Shift shift_op,
5016                                        VectorFormat vform,
5017                                        LogicVRegister dst,
5018                                        const LogicVRegister& src1,
5019                                        const LogicVRegister& src2,
5020                                        bool is_wide_elements);
5021 
5022   // Pack all even- or odd-numbered elements of source vector side by side and
5023   // place in elements of lower half the destination vector, and leave the upper
5024   // half all zero.
5025   //    [...| H | G | F | E | D | C | B | A ]
5026   // => [...................| G | E | C | A ]
5027   LogicVRegister pack_even_elements(VectorFormat vform,
5028                                     LogicVRegister dst,
5029                                     const LogicVRegister& src);
5030 
5031   //    [...| H | G | F | E | D | C | B | A ]
5032   // => [...................| H | F | D | B ]
5033   LogicVRegister pack_odd_elements(VectorFormat vform,
5034                                    LogicVRegister dst,
5035                                    const LogicVRegister& src);
5036 
5037   LogicVRegister adcl(VectorFormat vform,
5038                       LogicVRegister dst,
5039                       const LogicVRegister& src1,
5040                       const LogicVRegister& src2,
5041                       bool top);
5042 
5043   template <typename T>
5044   LogicVRegister FTMaddHelper(VectorFormat vform,
5045                               LogicVRegister dst,
5046                               const LogicVRegister& src1,
5047                               const LogicVRegister& src2,
5048                               uint64_t coeff_pos,
5049                               uint64_t coeff_neg);
5050 
5051   // Return the first or last active lane, or -1 if none are active.
5052   int GetFirstActive(VectorFormat vform, const LogicPRegister& pg) const;
5053   int GetLastActive(VectorFormat vform, const LogicPRegister& pg) const;
5054 
5055   int CountActiveLanes(VectorFormat vform, const LogicPRegister& pg) const;
5056 
5057   // Count active and true lanes in `pn`.
5058   int CountActiveAndTrueLanes(VectorFormat vform,
5059                               const LogicPRegister& pg,
5060                               const LogicPRegister& pn) const;
5061 
5062   // Count the number of lanes referred to by `pattern`, given the vector
5063   // length. If `pattern` is not a recognised SVEPredicateConstraint, this
5064   // returns zero.
5065   int GetPredicateConstraintLaneCount(VectorFormat vform, int pattern) const;
5066 
5067   // Simulate a runtime call.
5068   void DoRuntimeCall(const Instruction* instr);
5069 
5070   // Processor state ---------------------------------------
5071 
5072   // Simulated monitors for exclusive access instructions.
5073   SimExclusiveLocalMonitor local_monitor_;
5074   SimExclusiveGlobalMonitor global_monitor_;
5075 
5076   // Output stream.
5077   FILE* stream_;
5078   PrintDisassembler* print_disasm_;
5079 
5080   // General purpose registers. Register 31 is the stack pointer.
5081   SimRegister registers_[kNumberOfRegisters];
5082 
5083   // Vector registers
5084   SimVRegister vregisters_[kNumberOfVRegisters];
5085 
5086   // SVE predicate registers.
5087   SimPRegister pregisters_[kNumberOfPRegisters];
5088 
5089   // SVE first-fault register.
5090   SimFFRRegister ffr_register_;
5091 
5092   // A pseudo SVE predicate register with all bits set to true.
5093   SimPRegister pregister_all_true_;
5094 
5095   // Program Status Register.
5096   // bits[31, 27]: Condition flags N, Z, C, and V.
5097   //               (Negative, Zero, Carry, Overflow)
5098   SimSystemRegister nzcv_;
5099 
5100   // Floating-Point Control Register
5101   SimSystemRegister fpcr_;
5102 
5103   // Only a subset of FPCR features are supported by the simulator. This helper
5104   // checks that the FPCR settings are supported.
5105   //
5106   // This is checked when floating-point instructions are executed, not when
5107   // FPCR is set. This allows generated code to modify FPCR for external
5108   // functions, or to save and restore it when entering and leaving generated
5109   // code.
5110   void AssertSupportedFPCR() {
5111     // No flush-to-zero support.
5112     VIXL_ASSERT(ReadFpcr().GetFZ() == 0);
5113     // Ties-to-even rounding only.
5114     VIXL_ASSERT(ReadFpcr().GetRMode() == FPTieEven);
5115     // No alternative half-precision support.
5116     VIXL_ASSERT(ReadFpcr().GetAHP() == 0);
5117   }
5118 
5119   static int CalcNFlag(uint64_t result, unsigned reg_size) {
5120     return (result >> (reg_size - 1)) & 1;
5121   }
5122 
5123   static int CalcZFlag(uint64_t result) { return (result == 0) ? 1 : 0; }
5124 
5125   static const uint32_t kConditionFlagsMask = 0xf0000000;
5126 
5127   Memory memory_;
5128 
5129   static const size_t kDefaultStackGuardStartSize = 0;
5130   static const size_t kDefaultStackGuardEndSize = 4 * 1024;
5131   static const size_t kDefaultStackUsableSize = 8 * 1024;
5132 
5133   Decoder* decoder_;
5134   // Indicates if the pc has been modified by the instruction and should not be
5135   // automatically incremented.
5136   bool pc_modified_;
5137   const Instruction* pc_;
5138 
5139   // Pointer to the last simulated instruction, used for checking the validity
5140   // of the current instruction with the previous instruction, such as movprfx.
5141   Instruction const* last_instr_;
5142 
5143   // Branch type register, used for branch target identification.
5144   BType btype_;
5145 
5146   // Next value of branch type register after the current instruction has been
5147   // decoded.
5148   BType next_btype_;
5149 
5150   // Global flag for enabling guarded pages.
5151   // TODO: implement guarding at page granularity, rather than globally.
5152   bool guard_pages_;
5153 
5154   static const char* xreg_names[];
5155   static const char* wreg_names[];
5156   static const char* breg_names[];
5157   static const char* hreg_names[];
5158   static const char* sreg_names[];
5159   static const char* dreg_names[];
5160   static const char* vreg_names[];
5161   static const char* zreg_names[];
5162   static const char* preg_names[];
5163 
5164  private:
5165   using FormToVisitorFnMap = FormToVisitorFnMapT<Simulator>;
5166 
5167   static const FormToVisitorFnMap FORM_TO_VISITOR;
5168 
5169   static const FormToVisitorFnMap* GetFormToVisitorFnMap();
5170 
5171   uint32_t form_hash_;
5172 
5173   static const PACKey kPACKeyIA;
5174   static const PACKey kPACKeyIB;
5175   static const PACKey kPACKeyDA;
5176   static const PACKey kPACKeyDB;
5177   static const PACKey kPACKeyGA;
5178 
5179   bool CanReadMemory(uintptr_t address, size_t size);
5180 
5181   // CanReadMemory needs placeholder file descriptors, so we use a pipe. We can
5182   // save some system call overhead by opening them on construction, rather than
5183   // on every call to CanReadMemory.
5184   int placeholder_pipe_fd_[2];
5185 
5186   template <typename T>
5187   static T FPDefaultNaN();
5188 
5189   // Standard NaN processing.
5190   template <typename T>
5191   T FPProcessNaN(T op) {
5192     VIXL_ASSERT(IsNaN(op));
5193     if (IsSignallingNaN(op)) {
5194       FPProcessException();
5195     }
5196     return (ReadDN() == kUseDefaultNaN) ? FPDefaultNaN<T>() : ToQuietNaN(op);
5197   }
5198 
5199   template <typename T>
5200   T FPProcessNaNs(T op1, T op2) {
5201     if (IsSignallingNaN(op1)) {
5202       return FPProcessNaN(op1);
5203     } else if (IsSignallingNaN(op2)) {
5204       return FPProcessNaN(op2);
5205     } else if (IsNaN(op1)) {
5206       VIXL_ASSERT(IsQuietNaN(op1));
5207       return FPProcessNaN(op1);
5208     } else if (IsNaN(op2)) {
5209       VIXL_ASSERT(IsQuietNaN(op2));
5210       return FPProcessNaN(op2);
5211     } else {
5212       return 0.0;
5213     }
5214   }
5215 
5216   template <typename T>
5217   T FPProcessNaNs3(T op1, T op2, T op3) {
5218     if (IsSignallingNaN(op1)) {
5219       return FPProcessNaN(op1);
5220     } else if (IsSignallingNaN(op2)) {
5221       return FPProcessNaN(op2);
5222     } else if (IsSignallingNaN(op3)) {
5223       return FPProcessNaN(op3);
5224     } else if (IsNaN(op1)) {
5225       VIXL_ASSERT(IsQuietNaN(op1));
5226       return FPProcessNaN(op1);
5227     } else if (IsNaN(op2)) {
5228       VIXL_ASSERT(IsQuietNaN(op2));
5229       return FPProcessNaN(op2);
5230     } else if (IsNaN(op3)) {
5231       VIXL_ASSERT(IsQuietNaN(op3));
5232       return FPProcessNaN(op3);
5233     } else {
5234       return 0.0;
5235     }
5236   }
5237 
5238   // Construct a SimVRegister from a SimPRegister, where each byte-sized lane of
5239   // the destination is set to all true (0xff) when the corresponding
5240   // predicate flag is set, and false (0x00) otherwise.
5241   SimVRegister ExpandToSimVRegister(const SimPRegister& preg);
5242 
5243   // Set each predicate flag in pd where the corresponding assigned-sized lane
5244   // in vreg is non-zero. Clear the flag, otherwise. This is almost the opposite
5245   // operation to ExpandToSimVRegister(), except that any non-zero lane is
5246   // interpreted as true.
5247   void ExtractFromSimVRegister(VectorFormat vform,
5248                                SimPRegister& pd,  // NOLINT(runtime/references)
5249                                SimVRegister vreg);
5250   AllocatorWrapper allocator_;
5251 
5252   bool coloured_trace_;
5253 
5254   // A set of TraceParameters flags.
5255   int trace_parameters_;
5256 
5257   // Indicates whether the exclusive-access warning has been printed.
5258   bool print_exclusive_access_warning_;
5259   void PrintExclusiveAccessWarning();
5260 
5261   CPUFeaturesAuditor cpu_features_auditor_;
5262 #ifndef PANDA_BUILD
5263   std::vector<CPUFeatures> saved_cpu_features_;
5264 #else
5265   Vector<CPUFeatures>saved_cpu_features_;
5266 #endif
5267 
5268   // State for *rand48 functions, used to simulate randomness with repeatable
5269   // behaviour (so that tests are deterministic). This is used to simulate RNDR
5270   // and RNDRRS, as well as to simulate a source of entropy for architecturally
5271   // undefined behaviour.
5272   uint16_t rand_state_[3];
5273 
5274   // A configurable size of SVE vector registers.
5275   unsigned vector_length_;
5276 
5277   // Representation of memory attributes such as MTE tagging and BTI page
5278   // protection in addition to branch interceptions.
5279   MetaDataDepot meta_data_;
5280 
5281   // True if the debugger is enabled and might get entered.
5282   bool debugger_enabled_;
5283 
5284   // Debugger for the simulator.
5285 #ifndef PANDA_BUILD
5286   std::unique_ptr<Debugger> debugger_;
5287 #else
5288   Debugger* debugger_{nullptr};
5289 #endif
5290 };
5291 
5292 #if defined(VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT) && __cplusplus < 201402L
5293 // Base case of the recursive template used to emulate C++14
5294 // `std::index_sequence`.
5295 template <size_t... I>
5296 struct Simulator::emulated_make_index_sequence_helper<0, I...>
5297     : Simulator::emulated_index_sequence<I...> {};
5298 #endif
5299 
5300 template <typename R, typename... P>
5301 void MetaDataDepot::BranchInterception<R, P...>::operator()(
5302     Simulator* simulator) const {
5303   if (callback_ == nullptr) {
5304     Simulator::RuntimeCallStructHelper<R, P...>::
5305         Wrapper(simulator, reinterpret_cast<uint64_t>(function_));
5306   } else {
5307     callback_(reinterpret_cast<uint64_t>(function_));
5308   }
5309 }
5310 
5311 }  // namespace aarch64
5312 }  // namespace vixl
5313 
5314 #endif  // VIXL_INCLUDE_SIMULATOR_AARCH64
5315 
5316 #endif  // VIXL_AARCH64_SIMULATOR_AARCH64_H_
5317