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