• 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 <vector>
31 
32 #include "../globals-vixl.h"
33 #include "../utils-vixl.h"
34 
35 #include "cpu-features.h"
36 #include "abi-aarch64.h"
37 #include "cpu-features-auditor-aarch64.h"
38 #include "disasm-aarch64.h"
39 #include "instructions-aarch64.h"
40 #include "instrument-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 // Representation of memory, with typed getters and setters for access.
59 class Memory {
60  public:
61   template <typename T>
AddressUntag(T address)62   static T AddressUntag(T address) {
63     // Cast the address using a C-style cast. A reinterpret_cast would be
64     // appropriate, but it can't cast one integral type to another.
65     uint64_t bits = (uint64_t)address;
66     return (T)(bits & ~kAddressTagMask);
67   }
68 
69   template <typename T, typename A>
Read(A address)70   static T Read(A address) {
71     T value;
72     address = AddressUntag(address);
73     VIXL_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
74                 (sizeof(value) == 4) || (sizeof(value) == 8) ||
75                 (sizeof(value) == 16));
76     memcpy(&value, reinterpret_cast<const char*>(address), sizeof(value));
77     return value;
78   }
79 
80   template <typename T, typename A>
Write(A address,T value)81   static void Write(A address, T value) {
82     address = AddressUntag(address);
83     VIXL_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
84                 (sizeof(value) == 4) || (sizeof(value) == 8) ||
85                 (sizeof(value) == 16));
86     memcpy(reinterpret_cast<char*>(address), &value, sizeof(value));
87   }
88 };
89 
90 // Represent a register (r0-r31, v0-v31).
91 template <int kSizeInBytes>
92 class SimRegisterBase {
93  public:
SimRegisterBase()94   SimRegisterBase() : written_since_last_log_(false) {}
95 
96   // Write the specified value. The value is zero-extended if necessary.
97   template <typename T>
Write(T new_value)98   void Write(T new_value) {
99     if (sizeof(new_value) < kSizeInBytes) {
100       // All AArch64 registers are zero-extending.
101       memset(value_ + sizeof(new_value), 0, kSizeInBytes - sizeof(new_value));
102     }
103     WriteLane(new_value, 0);
104     NotifyRegisterWrite();
105   }
106   template <typename T>
Set(T new_value)107   VIXL_DEPRECATED("Write", void Set(T new_value)) {
108     Write(new_value);
109   }
110 
111   // Insert a typed value into a register, leaving the rest of the register
112   // unchanged. The lane parameter indicates where in the register the value
113   // should be inserted, in the range [ 0, sizeof(value_) / sizeof(T) ), where
114   // 0 represents the least significant bits.
115   template <typename T>
Insert(int lane,T new_value)116   void Insert(int lane, T new_value) {
117     WriteLane(new_value, lane);
118     NotifyRegisterWrite();
119   }
120 
121   // Get the value as the specified type. The value is truncated if necessary.
122   template <typename T>
Get()123   T Get() const {
124     return GetLane<T>(0);
125   }
126 
127   // Get the lane value as the specified type. The value is truncated if
128   // necessary.
129   template <typename T>
GetLane(int lane)130   T GetLane(int lane) const {
131     T result;
132     ReadLane(&result, lane);
133     return result;
134   }
135   template <typename T>
136   VIXL_DEPRECATED("GetLane", T Get(int lane) const) {
137     return GetLane(lane);
138   }
139 
140   // TODO: Make this return a map of updated bytes, so that we can highlight
141   // updated lanes for load-and-insert. (That never happens for scalar code, but
142   // NEON has some instructions that can update individual lanes.)
WrittenSinceLastLog()143   bool WrittenSinceLastLog() const { return written_since_last_log_; }
144 
NotifyRegisterLogged()145   void NotifyRegisterLogged() { written_since_last_log_ = false; }
146 
147  protected:
148   uint8_t value_[kSizeInBytes];
149 
150   // Helpers to aid with register tracing.
151   bool written_since_last_log_;
152 
NotifyRegisterWrite()153   void NotifyRegisterWrite() { written_since_last_log_ = true; }
154 
155  private:
156   template <typename T>
ReadLane(T * dst,int lane)157   void ReadLane(T* dst, int lane) const {
158     VIXL_ASSERT(lane >= 0);
159     VIXL_ASSERT((sizeof(*dst) + (lane * sizeof(*dst))) <= kSizeInBytes);
160     memcpy(dst, &value_[lane * sizeof(*dst)], sizeof(*dst));
161   }
162 
163   template <typename T>
WriteLane(T src,int lane)164   void WriteLane(T src, int lane) {
165     VIXL_ASSERT(lane >= 0);
166     VIXL_ASSERT((sizeof(src) + (lane * sizeof(src))) <= kSizeInBytes);
167     memcpy(&value_[lane * sizeof(src)], &src, sizeof(src));
168   }
169 };
170 typedef SimRegisterBase<kXRegSizeInBytes> SimRegister;   // r0-r31
171 typedef SimRegisterBase<kQRegSizeInBytes> SimVRegister;  // v0-v31
172 
173 // The default ReadLane and WriteLane methods assume what we are copying is
174 // "trivially copyable" by using memcpy. We have to provide alternative
175 // implementations for SimFloat16 which cannot be copied this way.
176 
177 template <>
178 template <>
ReadLane(vixl::internal::SimFloat16 * dst,int lane)179 inline void SimVRegister::ReadLane(vixl::internal::SimFloat16* dst,
180                                    int lane) const {
181   uint16_t rawbits;
182   ReadLane(&rawbits, lane);
183   *dst = RawbitsToFloat16(rawbits);
184 }
185 
186 template <>
187 template <>
WriteLane(vixl::internal::SimFloat16 src,int lane)188 inline void SimVRegister::WriteLane(vixl::internal::SimFloat16 src, int lane) {
189   WriteLane(Float16ToRawbits(src), lane);
190 }
191 
192 // Representation of a vector register, with typed getters and setters for lanes
193 // and additional information to represent lane state.
194 class LogicVRegister {
195  public:
LogicVRegister(SimVRegister & other)196   inline LogicVRegister(
197       SimVRegister& other)  // NOLINT(runtime/references)(runtime/explicit)
198       : register_(other) {
199     for (size_t i = 0; i < ArrayLength(saturated_); i++) {
200       saturated_[i] = kNotSaturated;
201     }
202     for (size_t i = 0; i < ArrayLength(round_); i++) {
203       round_[i] = 0;
204     }
205   }
206 
Int(VectorFormat vform,int index)207   int64_t Int(VectorFormat vform, int index) const {
208     int64_t element;
209     switch (LaneSizeInBitsFromFormat(vform)) {
210       case 8:
211         element = register_.GetLane<int8_t>(index);
212         break;
213       case 16:
214         element = register_.GetLane<int16_t>(index);
215         break;
216       case 32:
217         element = register_.GetLane<int32_t>(index);
218         break;
219       case 64:
220         element = register_.GetLane<int64_t>(index);
221         break;
222       default:
223         VIXL_UNREACHABLE();
224         return 0;
225     }
226     return element;
227   }
228 
Uint(VectorFormat vform,int index)229   uint64_t Uint(VectorFormat vform, int index) const {
230     uint64_t element;
231     switch (LaneSizeInBitsFromFormat(vform)) {
232       case 8:
233         element = register_.GetLane<uint8_t>(index);
234         break;
235       case 16:
236         element = register_.GetLane<uint16_t>(index);
237         break;
238       case 32:
239         element = register_.GetLane<uint32_t>(index);
240         break;
241       case 64:
242         element = register_.GetLane<uint64_t>(index);
243         break;
244       default:
245         VIXL_UNREACHABLE();
246         return 0;
247     }
248     return element;
249   }
250 
UintLeftJustified(VectorFormat vform,int index)251   uint64_t UintLeftJustified(VectorFormat vform, int index) const {
252     return Uint(vform, index) << (64 - LaneSizeInBitsFromFormat(vform));
253   }
254 
IntLeftJustified(VectorFormat vform,int index)255   int64_t IntLeftJustified(VectorFormat vform, int index) const {
256     uint64_t value = UintLeftJustified(vform, index);
257     int64_t result;
258     memcpy(&result, &value, sizeof(result));
259     return result;
260   }
261 
SetInt(VectorFormat vform,int index,int64_t value)262   void SetInt(VectorFormat vform, int index, int64_t value) const {
263     switch (LaneSizeInBitsFromFormat(vform)) {
264       case 8:
265         register_.Insert(index, static_cast<int8_t>(value));
266         break;
267       case 16:
268         register_.Insert(index, static_cast<int16_t>(value));
269         break;
270       case 32:
271         register_.Insert(index, static_cast<int32_t>(value));
272         break;
273       case 64:
274         register_.Insert(index, static_cast<int64_t>(value));
275         break;
276       default:
277         VIXL_UNREACHABLE();
278         return;
279     }
280   }
281 
SetIntArray(VectorFormat vform,const int64_t * src)282   void SetIntArray(VectorFormat vform, const int64_t* src) const {
283     ClearForWrite(vform);
284     for (int i = 0; i < LaneCountFromFormat(vform); i++) {
285       SetInt(vform, i, src[i]);
286     }
287   }
288 
SetUint(VectorFormat vform,int index,uint64_t value)289   void SetUint(VectorFormat vform, int index, uint64_t value) const {
290     switch (LaneSizeInBitsFromFormat(vform)) {
291       case 8:
292         register_.Insert(index, static_cast<uint8_t>(value));
293         break;
294       case 16:
295         register_.Insert(index, static_cast<uint16_t>(value));
296         break;
297       case 32:
298         register_.Insert(index, static_cast<uint32_t>(value));
299         break;
300       case 64:
301         register_.Insert(index, static_cast<uint64_t>(value));
302         break;
303       default:
304         VIXL_UNREACHABLE();
305         return;
306     }
307   }
308 
SetUintArray(VectorFormat vform,const uint64_t * src)309   void SetUintArray(VectorFormat vform, const uint64_t* src) const {
310     ClearForWrite(vform);
311     for (int i = 0; i < LaneCountFromFormat(vform); i++) {
312       SetUint(vform, i, src[i]);
313     }
314   }
315 
ReadUintFromMem(VectorFormat vform,int index,uint64_t addr)316   void ReadUintFromMem(VectorFormat vform, int index, uint64_t addr) const {
317     switch (LaneSizeInBitsFromFormat(vform)) {
318       case 8:
319         register_.Insert(index, Memory::Read<uint8_t>(addr));
320         break;
321       case 16:
322         register_.Insert(index, Memory::Read<uint16_t>(addr));
323         break;
324       case 32:
325         register_.Insert(index, Memory::Read<uint32_t>(addr));
326         break;
327       case 64:
328         register_.Insert(index, Memory::Read<uint64_t>(addr));
329         break;
330       default:
331         VIXL_UNREACHABLE();
332         return;
333     }
334   }
335 
WriteUintToMem(VectorFormat vform,int index,uint64_t addr)336   void WriteUintToMem(VectorFormat vform, int index, uint64_t addr) const {
337     uint64_t value = Uint(vform, index);
338     switch (LaneSizeInBitsFromFormat(vform)) {
339       case 8:
340         Memory::Write(addr, static_cast<uint8_t>(value));
341         break;
342       case 16:
343         Memory::Write(addr, static_cast<uint16_t>(value));
344         break;
345       case 32:
346         Memory::Write(addr, static_cast<uint32_t>(value));
347         break;
348       case 64:
349         Memory::Write(addr, value);
350         break;
351     }
352   }
353 
354   template <typename T>
Float(int index)355   T Float(int index) const {
356     return register_.GetLane<T>(index);
357   }
358 
359   template <typename T>
SetFloat(int index,T value)360   void SetFloat(int index, T value) const {
361     register_.Insert(index, value);
362   }
363 
364   // When setting a result in a register of size less than Q, the top bits of
365   // the Q register must be cleared.
ClearForWrite(VectorFormat vform)366   void ClearForWrite(VectorFormat vform) const {
367     unsigned size = RegisterSizeInBytesFromFormat(vform);
368     for (unsigned i = size; i < kQRegSizeInBytes; i++) {
369       SetUint(kFormat16B, i, 0);
370     }
371   }
372 
373   // Saturation state for each lane of a vector.
374   enum Saturation {
375     kNotSaturated = 0,
376     kSignedSatPositive = 1 << 0,
377     kSignedSatNegative = 1 << 1,
378     kSignedSatMask = kSignedSatPositive | kSignedSatNegative,
379     kSignedSatUndefined = kSignedSatMask,
380     kUnsignedSatPositive = 1 << 2,
381     kUnsignedSatNegative = 1 << 3,
382     kUnsignedSatMask = kUnsignedSatPositive | kUnsignedSatNegative,
383     kUnsignedSatUndefined = kUnsignedSatMask
384   };
385 
386   // Getters for saturation state.
GetSignedSaturation(int index)387   Saturation GetSignedSaturation(int index) {
388     return static_cast<Saturation>(saturated_[index] & kSignedSatMask);
389   }
390 
GetUnsignedSaturation(int index)391   Saturation GetUnsignedSaturation(int index) {
392     return static_cast<Saturation>(saturated_[index] & kUnsignedSatMask);
393   }
394 
395   // Setters for saturation state.
ClearSat(int index)396   void ClearSat(int index) { saturated_[index] = kNotSaturated; }
397 
SetSignedSat(int index,bool positive)398   void SetSignedSat(int index, bool positive) {
399     SetSatFlag(index, positive ? kSignedSatPositive : kSignedSatNegative);
400   }
401 
SetUnsignedSat(int index,bool positive)402   void SetUnsignedSat(int index, bool positive) {
403     SetSatFlag(index, positive ? kUnsignedSatPositive : kUnsignedSatNegative);
404   }
405 
SetSatFlag(int index,Saturation sat)406   void SetSatFlag(int index, Saturation sat) {
407     saturated_[index] = static_cast<Saturation>(saturated_[index] | sat);
408     VIXL_ASSERT((sat & kUnsignedSatMask) != kUnsignedSatUndefined);
409     VIXL_ASSERT((sat & kSignedSatMask) != kSignedSatUndefined);
410   }
411 
412   // Saturate lanes of a vector based on saturation state.
SignedSaturate(VectorFormat vform)413   LogicVRegister& SignedSaturate(VectorFormat vform) {
414     for (int i = 0; i < LaneCountFromFormat(vform); i++) {
415       Saturation sat = GetSignedSaturation(i);
416       if (sat == kSignedSatPositive) {
417         SetInt(vform, i, MaxIntFromFormat(vform));
418       } else if (sat == kSignedSatNegative) {
419         SetInt(vform, i, MinIntFromFormat(vform));
420       }
421     }
422     return *this;
423   }
424 
UnsignedSaturate(VectorFormat vform)425   LogicVRegister& UnsignedSaturate(VectorFormat vform) {
426     for (int i = 0; i < LaneCountFromFormat(vform); i++) {
427       Saturation sat = GetUnsignedSaturation(i);
428       if (sat == kUnsignedSatPositive) {
429         SetUint(vform, i, MaxUintFromFormat(vform));
430       } else if (sat == kUnsignedSatNegative) {
431         SetUint(vform, i, 0);
432       }
433     }
434     return *this;
435   }
436 
437   // Getter for rounding state.
GetRounding(int index)438   bool GetRounding(int index) { return round_[index]; }
439 
440   // Setter for rounding state.
SetRounding(int index,bool round)441   void SetRounding(int index, bool round) { round_[index] = round; }
442 
443   // Round lanes of a vector based on rounding state.
Round(VectorFormat vform)444   LogicVRegister& Round(VectorFormat vform) {
445     for (int i = 0; i < LaneCountFromFormat(vform); i++) {
446       SetUint(vform, i, Uint(vform, i) + (GetRounding(i) ? 1 : 0));
447     }
448     return *this;
449   }
450 
451   // Unsigned halve lanes of a vector, and use the saturation state to set the
452   // top bit.
Uhalve(VectorFormat vform)453   LogicVRegister& Uhalve(VectorFormat vform) {
454     for (int i = 0; i < LaneCountFromFormat(vform); i++) {
455       uint64_t val = Uint(vform, i);
456       SetRounding(i, (val & 1) == 1);
457       val >>= 1;
458       if (GetUnsignedSaturation(i) != kNotSaturated) {
459         // If the operation causes unsigned saturation, the bit shifted into the
460         // most significant bit must be set.
461         val |= (MaxUintFromFormat(vform) >> 1) + 1;
462       }
463       SetInt(vform, i, val);
464     }
465     return *this;
466   }
467 
468   // Signed halve lanes of a vector, and use the carry state to set the top bit.
Halve(VectorFormat vform)469   LogicVRegister& Halve(VectorFormat vform) {
470     for (int i = 0; i < LaneCountFromFormat(vform); i++) {
471       int64_t val = Int(vform, i);
472       SetRounding(i, (val & 1) == 1);
473       val >>= 1;
474       if (GetSignedSaturation(i) != kNotSaturated) {
475         // If the operation causes signed saturation, the sign bit must be
476         // inverted.
477         val ^= (MaxUintFromFormat(vform) >> 1) + 1;
478       }
479       SetInt(vform, i, val);
480     }
481     return *this;
482   }
483 
484  private:
485   SimVRegister& register_;
486 
487   // Allocate one saturation state entry per lane; largest register is type Q,
488   // and lanes can be a minimum of one byte wide.
489   Saturation saturated_[kQRegSizeInBytes];
490 
491   // Allocate one rounding state entry per lane.
492   bool round_[kQRegSizeInBytes];
493 };
494 
495 // The proper way to initialize a simulated system register (such as NZCV) is as
496 // follows:
497 //  SimSystemRegister nzcv = SimSystemRegister::DefaultValueFor(NZCV);
498 class SimSystemRegister {
499  public:
500   // The default constructor represents a register which has no writable bits.
501   // It is not possible to set its value to anything other than 0.
SimSystemRegister()502   SimSystemRegister() : value_(0), write_ignore_mask_(0xffffffff) {}
503 
GetRawValue()504   uint32_t GetRawValue() const { return value_; }
505   VIXL_DEPRECATED("GetRawValue", uint32_t RawValue() const) {
506     return GetRawValue();
507   }
508 
SetRawValue(uint32_t new_value)509   void SetRawValue(uint32_t new_value) {
510     value_ = (value_ & write_ignore_mask_) | (new_value & ~write_ignore_mask_);
511   }
512 
ExtractBits(int msb,int lsb)513   uint32_t ExtractBits(int msb, int lsb) const {
514     return ExtractUnsignedBitfield32(msb, lsb, value_);
515   }
516   VIXL_DEPRECATED("ExtractBits", uint32_t Bits(int msb, int lsb) const) {
517     return ExtractBits(msb, lsb);
518   }
519 
ExtractSignedBits(int msb,int lsb)520   int32_t ExtractSignedBits(int msb, int lsb) const {
521     return ExtractSignedBitfield32(msb, lsb, value_);
522   }
523   VIXL_DEPRECATED("ExtractSignedBits",
524                   int32_t SignedBits(int msb, int lsb) const) {
525     return ExtractSignedBits(msb, lsb);
526   }
527 
528   void SetBits(int msb, int lsb, uint32_t bits);
529 
530   // Default system register values.
531   static SimSystemRegister DefaultValueFor(SystemRegister id);
532 
533 #define DEFINE_GETTER(Name, HighBit, LowBit, Func)                            \
534   uint32_t Get##Name() const { return this->Func(HighBit, LowBit); }          \
535   VIXL_DEPRECATED("Get" #Name, uint32_t Name() const) { return Get##Name(); } \
536   void Set##Name(uint32_t bits) { SetBits(HighBit, LowBit, bits); }
537 #define DEFINE_WRITE_IGNORE_MASK(Name, Mask) \
538   static const uint32_t Name##WriteIgnoreMask = ~static_cast<uint32_t>(Mask);
539 
SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER,DEFINE_WRITE_IGNORE_MASK)540   SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER, DEFINE_WRITE_IGNORE_MASK)
541 
542 #undef DEFINE_ZERO_BITS
543 #undef DEFINE_GETTER
544 
545  protected:
546   // Most system registers only implement a few of the bits in the word. Other
547   // bits are "read-as-zero, write-ignored". The write_ignore_mask argument
548   // describes the bits which are not modifiable.
549   SimSystemRegister(uint32_t value, uint32_t write_ignore_mask)
550       : value_(value), write_ignore_mask_(write_ignore_mask) {}
551 
552   uint32_t value_;
553   uint32_t write_ignore_mask_;
554 };
555 
556 
557 class SimExclusiveLocalMonitor {
558  public:
SimExclusiveLocalMonitor()559   SimExclusiveLocalMonitor() : kSkipClearProbability(8), seed_(0x87654321) {
560     Clear();
561   }
562 
563   // Clear the exclusive monitor (like clrex).
Clear()564   void Clear() {
565     address_ = 0;
566     size_ = 0;
567   }
568 
569   // Clear the exclusive monitor most of the time.
MaybeClear()570   void MaybeClear() {
571     if ((seed_ % kSkipClearProbability) != 0) {
572       Clear();
573     }
574 
575     // Advance seed_ using a simple linear congruential generator.
576     seed_ = (seed_ * 48271) % 2147483647;
577   }
578 
579   // Mark the address range for exclusive access (like load-exclusive).
MarkExclusive(uint64_t address,size_t size)580   void MarkExclusive(uint64_t address, size_t size) {
581     address_ = address;
582     size_ = size;
583   }
584 
585   // Return true if the address range is marked (like store-exclusive).
586   // This helper doesn't implicitly clear the monitor.
IsExclusive(uint64_t address,size_t size)587   bool IsExclusive(uint64_t address, size_t size) {
588     VIXL_ASSERT(size > 0);
589     // Be pedantic: Require both the address and the size to match.
590     return (size == size_) && (address == address_);
591   }
592 
593  private:
594   uint64_t address_;
595   size_t size_;
596 
597   const int kSkipClearProbability;
598   uint32_t seed_;
599 };
600 
601 
602 // We can't accurate simulate the global monitor since it depends on external
603 // influences. Instead, this implementation occasionally causes accesses to
604 // fail, according to kPassProbability.
605 class SimExclusiveGlobalMonitor {
606  public:
SimExclusiveGlobalMonitor()607   SimExclusiveGlobalMonitor() : kPassProbability(8), seed_(0x87654321) {}
608 
IsExclusive(uint64_t address,size_t size)609   bool IsExclusive(uint64_t address, size_t size) {
610     USE(address, size);
611 
612     bool pass = (seed_ % kPassProbability) != 0;
613     // Advance seed_ using a simple linear congruential generator.
614     seed_ = (seed_ * 48271) % 2147483647;
615     return pass;
616   }
617 
618  private:
619   const int kPassProbability;
620   uint32_t seed_;
621 };
622 
623 
624 class Simulator : public DecoderVisitor {
625  public:
626   explicit Simulator(Decoder* decoder, FILE* stream = stdout);
627   ~Simulator();
628 
629   void ResetState();
630 
631   // Run the simulator.
632   virtual void Run();
633   void RunFrom(const Instruction* first);
634 
635 
636 #if defined(VIXL_HAS_ABI_SUPPORT) && __cplusplus >= 201103L && \
637     (defined(__clang__) || GCC_VERSION_OR_NEWER(4, 9, 1))
638   // Templated `RunFrom` version taking care of passing arguments and returning
639   // the result value.
640   // This allows code like:
641   //    int32_t res = simulator.RunFrom<int32_t, int32_t>(GenerateCode(),
642   //                                                      0x123);
643   // It requires VIXL's ABI features, and C++11 or greater.
644   // Also, the initialisation of tuples is incorrect in GCC before 4.9.1:
645   // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51253
646   template <typename R, typename... P>
RunFrom(const Instruction * code,P...arguments)647   R RunFrom(const Instruction* code, P... arguments) {
648     return RunFromStructHelper<R, P...>::Wrapper(this, code, arguments...);
649   }
650 
651   template <typename R, typename... P>
652   struct RunFromStructHelper {
WrapperRunFromStructHelper653     static R Wrapper(Simulator* simulator,
654                      const Instruction* code,
655                      P... arguments) {
656       ABI abi;
657       std::tuple<P...> unused_tuple{
658           // TODO: We currently do not support arguments passed on the stack. We
659           // could do so by using `WriteGenericOperand()` here, but may need to
660           // add features to handle situations where the stack is or is not set
661           // up.
662           (simulator->WriteCPURegister(abi.GetNextParameterGenericOperand<P>()
663                                            .GetCPURegister(),
664                                        arguments),
665            arguments)...};
666       simulator->RunFrom(code);
667       return simulator->ReadGenericOperand<R>(abi.GetReturnGenericOperand<R>());
668     }
669   };
670 
671   // Partial specialization when the return type is `void`.
672   template <typename... P>
673   struct RunFromStructHelper<void, P...> {
674     static void Wrapper(Simulator* simulator,
675                         const Instruction* code,
676                         P... arguments) {
677       ABI abi;
678       std::tuple<P...> unused_tuple{
679           // TODO: We currently do not support arguments passed on the stack. We
680           // could do so by using `WriteGenericOperand()` here, but may need to
681           // add features to handle situations where the stack is or is not set
682           // up.
683           (simulator->WriteCPURegister(abi.GetNextParameterGenericOperand<P>()
684                                            .GetCPURegister(),
685                                        arguments),
686            arguments)...};
687       simulator->RunFrom(code);
688     }
689   };
690 #endif
691 
692   // Execution ends when the PC hits this address.
693   static const Instruction* kEndOfSimAddress;
694 
695   // Simulation helpers.
696   const Instruction* ReadPc() const { return pc_; }
697   VIXL_DEPRECATED("ReadPc", const Instruction* pc() const) { return ReadPc(); }
698 
699   enum BranchLogMode { LogBranches, NoBranchLog };
700 
701   void WritePc(const Instruction* new_pc,
702                BranchLogMode log_mode = LogBranches) {
703     if (log_mode == LogBranches) LogTakenBranch(new_pc);
704     pc_ = Memory::AddressUntag(new_pc);
705     pc_modified_ = true;
706   }
707   VIXL_DEPRECATED("WritePc", void set_pc(const Instruction* new_pc)) {
708     return WritePc(new_pc);
709   }
710 
711   void IncrementPc() {
712     if (!pc_modified_) {
713       pc_ = pc_->GetNextInstruction();
714     }
715   }
716   VIXL_DEPRECATED("IncrementPc", void increment_pc()) { IncrementPc(); }
717 
718   BType ReadBType() const { return btype_; }
719   void WriteNextBType(BType btype) { next_btype_ = btype; }
720   void UpdateBType() {
721     btype_ = next_btype_;
722     next_btype_ = DefaultBType;
723   }
724 
725   // Helper function to determine BType for branches.
726   BType GetBTypeFromInstruction(const Instruction* instr) const;
727 
728   bool PcIsInGuardedPage() const { return guard_pages_; }
729   void SetGuardedPages(bool guard_pages) { guard_pages_ = guard_pages; }
730 
731   void ExecuteInstruction() {
732     // The program counter should always be aligned.
733     VIXL_ASSERT(IsWordAligned(pc_));
734     pc_modified_ = false;
735 
736     // On guarded pages, if BType is not zero, take an exception on any
737     // instruction other than BTI, PACI[AB]SP, HLT or BRK.
738     if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
739       if (pc_->IsPAuth()) {
740         Instr i = pc_->Mask(SystemPAuthMask);
741         if ((i != PACIASP) && (i != PACIBSP)) {
742           VIXL_ABORT_WITH_MSG(
743               "Executing non-BTI instruction with wrong BType.");
744         }
745       } else if (!pc_->IsBti() && !pc_->IsException()) {
746         VIXL_ABORT_WITH_MSG("Executing non-BTI instruction with wrong BType.");
747       }
748     }
749 
750     // decoder_->Decode(...) triggers at least the following visitors:
751     //  1. The CPUFeaturesAuditor (`cpu_features_auditor_`).
752     //  2. The PrintDisassembler (`print_disasm_`), if enabled.
753     //  3. The Simulator (`this`).
754     // User can add additional visitors at any point, but the Simulator requires
755     // that the ordering above is preserved.
756     decoder_->Decode(pc_);
757     IncrementPc();
758     LogAllWrittenRegisters();
759     UpdateBType();
760 
761     VIXL_CHECK(cpu_features_auditor_.InstructionIsAvailable());
762   }
763 
764 // Declare all Visitor functions.
765 #define DECLARE(A) \
766   virtual void Visit##A(const Instruction* instr) VIXL_OVERRIDE;
767   VISITOR_LIST_THAT_RETURN(DECLARE)
768 #undef DECLARE
769 
770 
771 #define DECLARE(A) \
772   VIXL_NO_RETURN virtual void Visit##A(const Instruction* instr) VIXL_OVERRIDE;
773   VISITOR_LIST_THAT_DONT_RETURN(DECLARE)
774 #undef DECLARE
775 
776 
777 #define DECLARE(A)                                                             \
778   VIXL_NO_RETURN_IN_DEBUG_MODE virtual void Visit##A(const Instruction* instr) \
779       VIXL_OVERRIDE;
780   VISITOR_LIST_THAT_DONT_RETURN_IN_DEBUG_MODE(DECLARE)
781 #undef DECLARE
782 
783 
784   // Integer register accessors.
785 
786   // Basic accessor: Read the register as the specified type.
787   template <typename T>
788   T ReadRegister(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
789     VIXL_ASSERT(
790         code < kNumberOfRegisters ||
791         ((r31mode == Reg31IsZeroRegister) && (code == kSPRegInternalCode)));
792     if ((code == 31) && (r31mode == Reg31IsZeroRegister)) {
793       T result;
794       memset(&result, 0, sizeof(result));
795       return result;
796     }
797     if ((r31mode == Reg31IsZeroRegister) && (code == kSPRegInternalCode)) {
798       code = 31;
799     }
800     return registers_[code].Get<T>();
801   }
802   template <typename T>
803   VIXL_DEPRECATED("ReadRegister",
804                   T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister)
805                       const) {
806     return ReadRegister<T>(code, r31mode);
807   }
808 
809   // Common specialized accessors for the ReadRegister() template.
810   int32_t ReadWRegister(unsigned code,
811                         Reg31Mode r31mode = Reg31IsZeroRegister) const {
812     return ReadRegister<int32_t>(code, r31mode);
813   }
814   VIXL_DEPRECATED("ReadWRegister",
815                   int32_t wreg(unsigned code,
816                                Reg31Mode r31mode = Reg31IsZeroRegister) const) {
817     return ReadWRegister(code, r31mode);
818   }
819 
820   int64_t ReadXRegister(unsigned code,
821                         Reg31Mode r31mode = Reg31IsZeroRegister) const {
822     return ReadRegister<int64_t>(code, r31mode);
823   }
824   VIXL_DEPRECATED("ReadXRegister",
825                   int64_t xreg(unsigned code,
826                                Reg31Mode r31mode = Reg31IsZeroRegister) const) {
827     return ReadXRegister(code, r31mode);
828   }
829 
830   // As above, with parameterized size and return type. The value is
831   // either zero-extended or truncated to fit, as required.
832   template <typename T>
833   T ReadRegister(unsigned size,
834                  unsigned code,
835                  Reg31Mode r31mode = Reg31IsZeroRegister) const {
836     uint64_t raw;
837     switch (size) {
838       case kWRegSize:
839         raw = ReadRegister<uint32_t>(code, r31mode);
840         break;
841       case kXRegSize:
842         raw = ReadRegister<uint64_t>(code, r31mode);
843         break;
844       default:
845         VIXL_UNREACHABLE();
846         return 0;
847     }
848 
849     T result;
850     VIXL_STATIC_ASSERT(sizeof(result) <= sizeof(raw));
851     // Copy the result and truncate to fit. This assumes a little-endian host.
852     memcpy(&result, &raw, sizeof(result));
853     return result;
854   }
855   template <typename T>
856   VIXL_DEPRECATED("ReadRegister",
857                   T reg(unsigned size,
858                         unsigned code,
859                         Reg31Mode r31mode = Reg31IsZeroRegister) const) {
860     return ReadRegister<T>(size, code, r31mode);
861   }
862 
863   // Use int64_t by default if T is not specified.
864   int64_t ReadRegister(unsigned size,
865                        unsigned code,
866                        Reg31Mode r31mode = Reg31IsZeroRegister) const {
867     return ReadRegister<int64_t>(size, code, r31mode);
868   }
869   VIXL_DEPRECATED("ReadRegister",
870                   int64_t reg(unsigned size,
871                               unsigned code,
872                               Reg31Mode r31mode = Reg31IsZeroRegister) const) {
873     return ReadRegister(size, code, r31mode);
874   }
875 
876   enum RegLogMode { LogRegWrites, NoRegLog };
877 
878   // Write 'value' into an integer register. The value is zero-extended. This
879   // behaviour matches AArch64 register writes.
880   template <typename T>
881   void WriteRegister(unsigned code,
882                      T value,
883                      RegLogMode log_mode = LogRegWrites,
884                      Reg31Mode r31mode = Reg31IsZeroRegister) {
885     if (sizeof(T) < kWRegSizeInBytes) {
886       // We use a C-style cast on purpose here.
887       // Since we do not have access to 'constepxr if', the casts in this `if`
888       // must be valid even if we know the code will never be executed, in
889       // particular when `T` is a pointer type.
890       int64_t tmp_64bit = (int64_t)value;
891       int32_t tmp_32bit = static_cast<int32_t>(tmp_64bit);
892       WriteRegister<int32_t>(code, tmp_32bit, log_mode, r31mode);
893       return;
894     }
895 
896     VIXL_ASSERT((sizeof(T) == kWRegSizeInBytes) ||
897                 (sizeof(T) == kXRegSizeInBytes));
898     VIXL_ASSERT(
899         code < kNumberOfRegisters ||
900         ((r31mode == Reg31IsZeroRegister) && (code == kSPRegInternalCode)));
901 
902     if ((code == 31) && (r31mode == Reg31IsZeroRegister)) {
903       return;
904     }
905 
906     if ((r31mode == Reg31IsZeroRegister) && (code == kSPRegInternalCode)) {
907       code = 31;
908     }
909 
910     registers_[code].Write(value);
911 
912     if (log_mode == LogRegWrites) LogRegister(code, r31mode);
913   }
914   template <typename T>
915   VIXL_DEPRECATED("WriteRegister",
916                   void set_reg(unsigned code,
917                                T value,
918                                RegLogMode log_mode = LogRegWrites,
919                                Reg31Mode r31mode = Reg31IsZeroRegister)) {
920     WriteRegister<T>(code, value, log_mode, r31mode);
921   }
922 
923   // Common specialized accessors for the set_reg() template.
924   void WriteWRegister(unsigned code,
925                       int32_t value,
926                       RegLogMode log_mode = LogRegWrites,
927                       Reg31Mode r31mode = Reg31IsZeroRegister) {
928     WriteRegister(code, value, log_mode, r31mode);
929   }
930   VIXL_DEPRECATED("WriteWRegister",
931                   void set_wreg(unsigned code,
932                                 int32_t value,
933                                 RegLogMode log_mode = LogRegWrites,
934                                 Reg31Mode r31mode = Reg31IsZeroRegister)) {
935     WriteWRegister(code, value, log_mode, r31mode);
936   }
937 
938   void WriteXRegister(unsigned code,
939                       int64_t value,
940                       RegLogMode log_mode = LogRegWrites,
941                       Reg31Mode r31mode = Reg31IsZeroRegister) {
942     WriteRegister(code, value, log_mode, r31mode);
943   }
944   VIXL_DEPRECATED("WriteXRegister",
945                   void set_xreg(unsigned code,
946                                 int64_t value,
947                                 RegLogMode log_mode = LogRegWrites,
948                                 Reg31Mode r31mode = Reg31IsZeroRegister)) {
949     WriteXRegister(code, value, log_mode, r31mode);
950   }
951 
952   // As above, with parameterized size and type. The value is either
953   // zero-extended or truncated to fit, as required.
954   template <typename T>
955   void WriteRegister(unsigned size,
956                      unsigned code,
957                      T value,
958                      RegLogMode log_mode = LogRegWrites,
959                      Reg31Mode r31mode = Reg31IsZeroRegister) {
960     // Zero-extend the input.
961     uint64_t raw = 0;
962     VIXL_STATIC_ASSERT(sizeof(value) <= sizeof(raw));
963     memcpy(&raw, &value, sizeof(value));
964 
965     // Write (and possibly truncate) the value.
966     switch (size) {
967       case kWRegSize:
968         WriteRegister(code, static_cast<uint32_t>(raw), log_mode, r31mode);
969         break;
970       case kXRegSize:
971         WriteRegister(code, raw, log_mode, r31mode);
972         break;
973       default:
974         VIXL_UNREACHABLE();
975         return;
976     }
977   }
978   template <typename T>
979   VIXL_DEPRECATED("WriteRegister",
980                   void set_reg(unsigned size,
981                                unsigned code,
982                                T value,
983                                RegLogMode log_mode = LogRegWrites,
984                                Reg31Mode r31mode = Reg31IsZeroRegister)) {
985     WriteRegister(size, code, value, log_mode, r31mode);
986   }
987 
988   // Common specialized accessors for the set_reg() template.
989 
990   // Commonly-used special cases.
991   template <typename T>
992   void WriteLr(T value) {
993     WriteRegister(kLinkRegCode, value);
994   }
995   template <typename T>
996   VIXL_DEPRECATED("WriteLr", void set_lr(T value)) {
997     WriteLr(value);
998   }
999 
1000   template <typename T>
1001   void WriteSp(T value) {
1002     WriteRegister(31, value, LogRegWrites, Reg31IsStackPointer);
1003   }
1004   template <typename T>
1005   VIXL_DEPRECATED("WriteSp", void set_sp(T value)) {
1006     WriteSp(value);
1007   }
1008 
1009   // Vector register accessors.
1010   // These are equivalent to the integer register accessors, but for vector
1011   // registers.
1012 
1013   // A structure for representing a 128-bit Q register.
1014   struct qreg_t {
1015     uint8_t val[kQRegSizeInBytes];
1016   };
1017 
1018   // Basic accessor: read the register as the specified type.
1019   template <typename T>
1020   T ReadVRegister(unsigned code) const {
1021     VIXL_STATIC_ASSERT(
1022         (sizeof(T) == kBRegSizeInBytes) || (sizeof(T) == kHRegSizeInBytes) ||
1023         (sizeof(T) == kSRegSizeInBytes) || (sizeof(T) == kDRegSizeInBytes) ||
1024         (sizeof(T) == kQRegSizeInBytes));
1025     VIXL_ASSERT(code < kNumberOfVRegisters);
1026 
1027     return vregisters_[code].Get<T>();
1028   }
1029   template <typename T>
1030   VIXL_DEPRECATED("ReadVRegister", T vreg(unsigned code) const) {
1031     return ReadVRegister<T>(code);
1032   }
1033 
1034   // Common specialized accessors for the vreg() template.
1035   int8_t ReadBRegister(unsigned code) const {
1036     return ReadVRegister<int8_t>(code);
1037   }
1038   VIXL_DEPRECATED("ReadBRegister", int8_t breg(unsigned code) const) {
1039     return ReadBRegister(code);
1040   }
1041 
1042   vixl::internal::SimFloat16 ReadHRegister(unsigned code) const {
1043     return RawbitsToFloat16(ReadHRegisterBits(code));
1044   }
1045   VIXL_DEPRECATED("ReadHRegister", int16_t hreg(unsigned code) const) {
1046     return Float16ToRawbits(ReadHRegister(code));
1047   }
1048 
1049   uint16_t ReadHRegisterBits(unsigned code) const {
1050     return ReadVRegister<uint16_t>(code);
1051   }
1052 
1053   float ReadSRegister(unsigned code) const {
1054     return ReadVRegister<float>(code);
1055   }
1056   VIXL_DEPRECATED("ReadSRegister", float sreg(unsigned code) const) {
1057     return ReadSRegister(code);
1058   }
1059 
1060   uint32_t ReadSRegisterBits(unsigned code) const {
1061     return ReadVRegister<uint32_t>(code);
1062   }
1063   VIXL_DEPRECATED("ReadSRegisterBits",
1064                   uint32_t sreg_bits(unsigned code) const) {
1065     return ReadSRegisterBits(code);
1066   }
1067 
1068   double ReadDRegister(unsigned code) const {
1069     return ReadVRegister<double>(code);
1070   }
1071   VIXL_DEPRECATED("ReadDRegister", double dreg(unsigned code) const) {
1072     return ReadDRegister(code);
1073   }
1074 
1075   uint64_t ReadDRegisterBits(unsigned code) const {
1076     return ReadVRegister<uint64_t>(code);
1077   }
1078   VIXL_DEPRECATED("ReadDRegisterBits",
1079                   uint64_t dreg_bits(unsigned code) const) {
1080     return ReadDRegisterBits(code);
1081   }
1082 
1083   qreg_t ReadQRegister(unsigned code) const {
1084     return ReadVRegister<qreg_t>(code);
1085   }
1086   VIXL_DEPRECATED("ReadQRegister", qreg_t qreg(unsigned code) const) {
1087     return ReadQRegister(code);
1088   }
1089 
1090   // As above, with parameterized size and return type. The value is
1091   // either zero-extended or truncated to fit, as required.
1092   template <typename T>
1093   T ReadVRegister(unsigned size, unsigned code) const {
1094     uint64_t raw = 0;
1095     T result;
1096 
1097     switch (size) {
1098       case kSRegSize:
1099         raw = ReadVRegister<uint32_t>(code);
1100         break;
1101       case kDRegSize:
1102         raw = ReadVRegister<uint64_t>(code);
1103         break;
1104       default:
1105         VIXL_UNREACHABLE();
1106         break;
1107     }
1108 
1109     VIXL_STATIC_ASSERT(sizeof(result) <= sizeof(raw));
1110     // Copy the result and truncate to fit. This assumes a little-endian host.
1111     memcpy(&result, &raw, sizeof(result));
1112     return result;
1113   }
1114   template <typename T>
1115   VIXL_DEPRECATED("ReadVRegister", T vreg(unsigned size, unsigned code) const) {
1116     return ReadVRegister<T>(size, code);
1117   }
1118 
1119   SimVRegister& ReadVRegister(unsigned code) { return vregisters_[code]; }
1120   VIXL_DEPRECATED("ReadVRegister", SimVRegister& vreg(unsigned code)) {
1121     return ReadVRegister(code);
1122   }
1123 
1124   // Basic accessor: Write the specified value.
1125   template <typename T>
1126   void WriteVRegister(unsigned code,
1127                       T value,
1128                       RegLogMode log_mode = LogRegWrites) {
1129     VIXL_STATIC_ASSERT((sizeof(value) == kBRegSizeInBytes) ||
1130                        (sizeof(value) == kHRegSizeInBytes) ||
1131                        (sizeof(value) == kSRegSizeInBytes) ||
1132                        (sizeof(value) == kDRegSizeInBytes) ||
1133                        (sizeof(value) == kQRegSizeInBytes));
1134     VIXL_ASSERT(code < kNumberOfVRegisters);
1135     vregisters_[code].Write(value);
1136 
1137     if (log_mode == LogRegWrites) {
1138       LogVRegister(code, GetPrintRegisterFormat(value));
1139     }
1140   }
1141   template <typename T>
1142   VIXL_DEPRECATED("WriteVRegister",
1143                   void set_vreg(unsigned code,
1144                                 T value,
1145                                 RegLogMode log_mode = LogRegWrites)) {
1146     WriteVRegister(code, value, log_mode);
1147   }
1148 
1149   // Common specialized accessors for the WriteVRegister() template.
1150   void WriteBRegister(unsigned code,
1151                       int8_t value,
1152                       RegLogMode log_mode = LogRegWrites) {
1153     WriteVRegister(code, value, log_mode);
1154   }
1155   VIXL_DEPRECATED("WriteBRegister",
1156                   void set_breg(unsigned code,
1157                                 int8_t value,
1158                                 RegLogMode log_mode = LogRegWrites)) {
1159     return WriteBRegister(code, value, log_mode);
1160   }
1161 
1162   void WriteHRegister(unsigned code,
1163                       vixl::internal::SimFloat16 value,
1164                       RegLogMode log_mode = LogRegWrites) {
1165     WriteVRegister(code, Float16ToRawbits(value), log_mode);
1166   }
1167 
1168   void WriteHRegister(unsigned code,
1169                       int16_t value,
1170                       RegLogMode log_mode = LogRegWrites) {
1171     WriteVRegister(code, value, log_mode);
1172   }
1173   VIXL_DEPRECATED("WriteHRegister",
1174                   void set_hreg(unsigned code,
1175                                 int16_t value,
1176                                 RegLogMode log_mode = LogRegWrites)) {
1177     return WriteHRegister(code, value, log_mode);
1178   }
1179 
1180   void WriteSRegister(unsigned code,
1181                       float value,
1182                       RegLogMode log_mode = LogRegWrites) {
1183     WriteVRegister(code, value, log_mode);
1184   }
1185   VIXL_DEPRECATED("WriteSRegister",
1186                   void set_sreg(unsigned code,
1187                                 float value,
1188                                 RegLogMode log_mode = LogRegWrites)) {
1189     WriteSRegister(code, value, log_mode);
1190   }
1191 
1192   void WriteSRegisterBits(unsigned code,
1193                           uint32_t value,
1194                           RegLogMode log_mode = LogRegWrites) {
1195     WriteVRegister(code, value, log_mode);
1196   }
1197   VIXL_DEPRECATED("WriteSRegisterBits",
1198                   void set_sreg_bits(unsigned code,
1199                                      uint32_t value,
1200                                      RegLogMode log_mode = LogRegWrites)) {
1201     WriteSRegisterBits(code, value, log_mode);
1202   }
1203 
1204   void WriteDRegister(unsigned code,
1205                       double value,
1206                       RegLogMode log_mode = LogRegWrites) {
1207     WriteVRegister(code, value, log_mode);
1208   }
1209   VIXL_DEPRECATED("WriteDRegister",
1210                   void set_dreg(unsigned code,
1211                                 double value,
1212                                 RegLogMode log_mode = LogRegWrites)) {
1213     WriteDRegister(code, value, log_mode);
1214   }
1215 
1216   void WriteDRegisterBits(unsigned code,
1217                           uint64_t value,
1218                           RegLogMode log_mode = LogRegWrites) {
1219     WriteVRegister(code, value, log_mode);
1220   }
1221   VIXL_DEPRECATED("WriteDRegisterBits",
1222                   void set_dreg_bits(unsigned code,
1223                                      uint64_t value,
1224                                      RegLogMode log_mode = LogRegWrites)) {
1225     WriteDRegisterBits(code, value, log_mode);
1226   }
1227 
1228   void WriteQRegister(unsigned code,
1229                       qreg_t value,
1230                       RegLogMode log_mode = LogRegWrites) {
1231     WriteVRegister(code, value, log_mode);
1232   }
1233   VIXL_DEPRECATED("WriteQRegister",
1234                   void set_qreg(unsigned code,
1235                                 qreg_t value,
1236                                 RegLogMode log_mode = LogRegWrites)) {
1237     WriteQRegister(code, value, log_mode);
1238   }
1239 
1240   template <typename T>
1241   T ReadRegister(Register reg) const {
1242     return ReadRegister<T>(reg.GetCode(), Reg31IsZeroRegister);
1243   }
1244 
1245   template <typename T>
1246   void WriteRegister(Register reg,
1247                      T value,
1248                      RegLogMode log_mode = LogRegWrites) {
1249     WriteRegister<T>(reg.GetCode(), value, log_mode, Reg31IsZeroRegister);
1250   }
1251 
1252   template <typename T>
1253   T ReadVRegister(VRegister vreg) const {
1254     return ReadVRegister<T>(vreg.GetCode());
1255   }
1256 
1257   template <typename T>
1258   void WriteVRegister(VRegister vreg,
1259                       T value,
1260                       RegLogMode log_mode = LogRegWrites) {
1261     WriteVRegister<T>(vreg.GetCode(), value, log_mode);
1262   }
1263 
1264   template <typename T>
1265   T ReadCPURegister(CPURegister reg) const {
1266     if (reg.IsVRegister()) {
1267       return ReadVRegister<T>(VRegister(reg));
1268     } else {
1269       return ReadRegister<T>(Register(reg));
1270     }
1271   }
1272 
1273   template <typename T>
1274   void WriteCPURegister(CPURegister reg,
1275                         T value,
1276                         RegLogMode log_mode = LogRegWrites) {
1277     if (reg.IsVRegister()) {
1278       WriteVRegister<T>(VRegister(reg), value, log_mode);
1279     } else {
1280       WriteRegister<T>(Register(reg), value, log_mode);
1281     }
1282   }
1283 
1284   uint64_t ComputeMemOperandAddress(const MemOperand& mem_op) const;
1285 
1286   template <typename T>
1287   T ReadGenericOperand(GenericOperand operand) const {
1288     if (operand.IsCPURegister()) {
1289       return ReadCPURegister<T>(operand.GetCPURegister());
1290     } else {
1291       VIXL_ASSERT(operand.IsMemOperand());
1292       return Memory::Read<T>(ComputeMemOperandAddress(operand.GetMemOperand()));
1293     }
1294   }
1295 
1296   template <typename T>
1297   void WriteGenericOperand(GenericOperand operand,
1298                            T value,
1299                            RegLogMode log_mode = LogRegWrites) {
1300     if (operand.IsCPURegister()) {
1301       // Outside SIMD, registers are 64-bit or a subset of a 64-bit register. If
1302       // the width of the value to write is smaller than 64 bits, the unused
1303       // bits may contain unrelated values that the code following this write
1304       // needs to handle gracefully.
1305       // Here we fill the unused bits with a predefined pattern to catch issues
1306       // early.
1307       VIXL_ASSERT(operand.GetCPURegister().GetSizeInBits() <= 64);
1308       uint64_t raw = 0xdeadda1adeadda1a;
1309       memcpy(&raw, &value, sizeof(value));
1310       WriteCPURegister(operand.GetCPURegister(), raw, log_mode);
1311     } else {
1312       VIXL_ASSERT(operand.IsMemOperand());
1313       Memory::Write(ComputeMemOperandAddress(operand.GetMemOperand()), value);
1314     }
1315   }
1316 
1317   bool ReadN() const { return nzcv_.GetN() != 0; }
1318   VIXL_DEPRECATED("ReadN", bool N() const) { return ReadN(); }
1319 
1320   bool ReadZ() const { return nzcv_.GetZ() != 0; }
1321   VIXL_DEPRECATED("ReadZ", bool Z() const) { return ReadZ(); }
1322 
1323   bool ReadC() const { return nzcv_.GetC() != 0; }
1324   VIXL_DEPRECATED("ReadC", bool C() const) { return ReadC(); }
1325 
1326   bool ReadV() const { return nzcv_.GetV() != 0; }
1327   VIXL_DEPRECATED("ReadV", bool V() const) { return ReadV(); }
1328 
1329   SimSystemRegister& ReadNzcv() { return nzcv_; }
1330   VIXL_DEPRECATED("ReadNzcv", SimSystemRegister& nzcv()) { return ReadNzcv(); }
1331 
1332   // TODO: Find a way to make the fpcr_ members return the proper types, so
1333   // these accessors are not necessary.
1334   FPRounding ReadRMode() const {
1335     return static_cast<FPRounding>(fpcr_.GetRMode());
1336   }
1337   VIXL_DEPRECATED("ReadRMode", FPRounding RMode()) { return ReadRMode(); }
1338 
1339   UseDefaultNaN ReadDN() const {
1340     return fpcr_.GetDN() != 0 ? kUseDefaultNaN : kIgnoreDefaultNaN;
1341   }
1342 
1343   VIXL_DEPRECATED("ReadDN", bool DN()) {
1344     return ReadDN() == kUseDefaultNaN ? true : false;
1345   }
1346 
1347   SimSystemRegister& ReadFpcr() { return fpcr_; }
1348   VIXL_DEPRECATED("ReadFpcr", SimSystemRegister& fpcr()) { return ReadFpcr(); }
1349 
1350   // Specify relevant register formats for Print(V)Register and related helpers.
1351   enum PrintRegisterFormat {
1352     // The lane size.
1353     kPrintRegLaneSizeB = 0 << 0,
1354     kPrintRegLaneSizeH = 1 << 0,
1355     kPrintRegLaneSizeS = 2 << 0,
1356     kPrintRegLaneSizeW = kPrintRegLaneSizeS,
1357     kPrintRegLaneSizeD = 3 << 0,
1358     kPrintRegLaneSizeX = kPrintRegLaneSizeD,
1359     kPrintRegLaneSizeQ = 4 << 0,
1360 
1361     kPrintRegLaneSizeOffset = 0,
1362     kPrintRegLaneSizeMask = 7 << 0,
1363 
1364     // The lane count.
1365     kPrintRegAsScalar = 0,
1366     kPrintRegAsDVector = 1 << 3,
1367     kPrintRegAsQVector = 2 << 3,
1368 
1369     kPrintRegAsVectorMask = 3 << 3,
1370 
1371     // Indicate floating-point format lanes. (This flag is only supported for
1372     // S-, H-, and D-sized lanes.)
1373     kPrintRegAsFP = 1 << 5,
1374 
1375     // Supported combinations.
1376 
1377     kPrintXReg = kPrintRegLaneSizeX | kPrintRegAsScalar,
1378     kPrintWReg = kPrintRegLaneSizeW | kPrintRegAsScalar,
1379     kPrintHReg = kPrintRegLaneSizeH | kPrintRegAsScalar | kPrintRegAsFP,
1380     kPrintSReg = kPrintRegLaneSizeS | kPrintRegAsScalar | kPrintRegAsFP,
1381     kPrintDReg = kPrintRegLaneSizeD | kPrintRegAsScalar | kPrintRegAsFP,
1382 
1383     kPrintReg1B = kPrintRegLaneSizeB | kPrintRegAsScalar,
1384     kPrintReg8B = kPrintRegLaneSizeB | kPrintRegAsDVector,
1385     kPrintReg16B = kPrintRegLaneSizeB | kPrintRegAsQVector,
1386     kPrintReg1H = kPrintRegLaneSizeH | kPrintRegAsScalar,
1387     kPrintReg4H = kPrintRegLaneSizeH | kPrintRegAsDVector,
1388     kPrintReg8H = kPrintRegLaneSizeH | kPrintRegAsQVector,
1389     kPrintReg1S = kPrintRegLaneSizeS | kPrintRegAsScalar,
1390     kPrintReg2S = kPrintRegLaneSizeS | kPrintRegAsDVector,
1391     kPrintReg4S = kPrintRegLaneSizeS | kPrintRegAsQVector,
1392     kPrintReg1HFP = kPrintRegLaneSizeH | kPrintRegAsScalar | kPrintRegAsFP,
1393     kPrintReg4HFP = kPrintRegLaneSizeH | kPrintRegAsDVector | kPrintRegAsFP,
1394     kPrintReg8HFP = kPrintRegLaneSizeH | kPrintRegAsQVector | kPrintRegAsFP,
1395     kPrintReg1SFP = kPrintRegLaneSizeS | kPrintRegAsScalar | kPrintRegAsFP,
1396     kPrintReg2SFP = kPrintRegLaneSizeS | kPrintRegAsDVector | kPrintRegAsFP,
1397     kPrintReg4SFP = kPrintRegLaneSizeS | kPrintRegAsQVector | kPrintRegAsFP,
1398     kPrintReg1D = kPrintRegLaneSizeD | kPrintRegAsScalar,
1399     kPrintReg2D = kPrintRegLaneSizeD | kPrintRegAsQVector,
1400     kPrintReg1DFP = kPrintRegLaneSizeD | kPrintRegAsScalar | kPrintRegAsFP,
1401     kPrintReg2DFP = kPrintRegLaneSizeD | kPrintRegAsQVector | kPrintRegAsFP,
1402     kPrintReg1Q = kPrintRegLaneSizeQ | kPrintRegAsScalar
1403   };
1404 
1405   unsigned GetPrintRegLaneSizeInBytesLog2(PrintRegisterFormat format) {
1406     return (format & kPrintRegLaneSizeMask) >> kPrintRegLaneSizeOffset;
1407   }
1408 
1409   unsigned GetPrintRegLaneSizeInBytes(PrintRegisterFormat format) {
1410     return 1 << GetPrintRegLaneSizeInBytesLog2(format);
1411   }
1412 
1413   unsigned GetPrintRegSizeInBytesLog2(PrintRegisterFormat format) {
1414     if (format & kPrintRegAsDVector) return kDRegSizeInBytesLog2;
1415     if (format & kPrintRegAsQVector) return kQRegSizeInBytesLog2;
1416 
1417     // Scalar types.
1418     return GetPrintRegLaneSizeInBytesLog2(format);
1419   }
1420 
1421   unsigned GetPrintRegSizeInBytes(PrintRegisterFormat format) {
1422     return 1 << GetPrintRegSizeInBytesLog2(format);
1423   }
1424 
1425   unsigned GetPrintRegLaneCount(PrintRegisterFormat format) {
1426     unsigned reg_size_log2 = GetPrintRegSizeInBytesLog2(format);
1427     unsigned lane_size_log2 = GetPrintRegLaneSizeInBytesLog2(format);
1428     VIXL_ASSERT(reg_size_log2 >= lane_size_log2);
1429     return 1 << (reg_size_log2 - lane_size_log2);
1430   }
1431 
1432   PrintRegisterFormat GetPrintRegisterFormatForSize(unsigned reg_size,
1433                                                     unsigned lane_size);
1434 
1435   PrintRegisterFormat GetPrintRegisterFormatForSize(unsigned size) {
1436     return GetPrintRegisterFormatForSize(size, size);
1437   }
1438 
1439   PrintRegisterFormat GetPrintRegisterFormatForSizeFP(unsigned size) {
1440     switch (size) {
1441       default:
1442         VIXL_UNREACHABLE();
1443         return kPrintDReg;
1444       case kDRegSizeInBytes:
1445         return kPrintDReg;
1446       case kSRegSizeInBytes:
1447         return kPrintSReg;
1448       case kHRegSizeInBytes:
1449         return kPrintHReg;
1450     }
1451   }
1452 
1453   PrintRegisterFormat GetPrintRegisterFormatTryFP(PrintRegisterFormat format) {
1454     if ((GetPrintRegLaneSizeInBytes(format) == kHRegSizeInBytes) ||
1455         (GetPrintRegLaneSizeInBytes(format) == kSRegSizeInBytes) ||
1456         (GetPrintRegLaneSizeInBytes(format) == kDRegSizeInBytes)) {
1457       return static_cast<PrintRegisterFormat>(format | kPrintRegAsFP);
1458     }
1459     return format;
1460   }
1461 
1462   template <typename T>
1463   PrintRegisterFormat GetPrintRegisterFormat(T value) {
1464     return GetPrintRegisterFormatForSize(sizeof(value));
1465   }
1466 
1467   PrintRegisterFormat GetPrintRegisterFormat(double value) {
1468     VIXL_STATIC_ASSERT(sizeof(value) == kDRegSizeInBytes);
1469     return GetPrintRegisterFormatForSizeFP(sizeof(value));
1470   }
1471 
1472   PrintRegisterFormat GetPrintRegisterFormat(float value) {
1473     VIXL_STATIC_ASSERT(sizeof(value) == kSRegSizeInBytes);
1474     return GetPrintRegisterFormatForSizeFP(sizeof(value));
1475   }
1476 
1477   PrintRegisterFormat GetPrintRegisterFormat(Float16 value) {
1478     VIXL_STATIC_ASSERT(sizeof(Float16ToRawbits(value)) == kHRegSizeInBytes);
1479     return GetPrintRegisterFormatForSizeFP(sizeof(Float16ToRawbits(value)));
1480   }
1481 
1482   PrintRegisterFormat GetPrintRegisterFormat(VectorFormat vform);
1483   PrintRegisterFormat GetPrintRegisterFormatFP(VectorFormat vform);
1484 
1485   // Print all registers of the specified types.
1486   void PrintRegisters();
1487   void PrintVRegisters();
1488   void PrintSystemRegisters();
1489 
1490   // As above, but only print the registers that have been updated.
1491   void PrintWrittenRegisters();
1492   void PrintWrittenVRegisters();
1493 
1494   // As above, but respect LOG_REG and LOG_VREG.
1495   void LogWrittenRegisters() {
1496     if (GetTraceParameters() & LOG_REGS) PrintWrittenRegisters();
1497   }
1498   void LogWrittenVRegisters() {
1499     if (GetTraceParameters() & LOG_VREGS) PrintWrittenVRegisters();
1500   }
1501   void LogAllWrittenRegisters() {
1502     LogWrittenRegisters();
1503     LogWrittenVRegisters();
1504   }
1505 
1506   // Print individual register values (after update).
1507   void PrintRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer);
1508   void PrintVRegister(unsigned code, PrintRegisterFormat format);
1509   void PrintSystemRegister(SystemRegister id);
1510   void PrintTakenBranch(const Instruction* target);
1511 
1512   // Like Print* (above), but respect GetTraceParameters().
1513   void LogRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer) {
1514     if (GetTraceParameters() & LOG_REGS) PrintRegister(code, r31mode);
1515   }
1516   void LogVRegister(unsigned code, PrintRegisterFormat format) {
1517     if (GetTraceParameters() & LOG_VREGS) PrintVRegister(code, format);
1518   }
1519   void LogSystemRegister(SystemRegister id) {
1520     if (GetTraceParameters() & LOG_SYSREGS) PrintSystemRegister(id);
1521   }
1522   void LogTakenBranch(const Instruction* target) {
1523     if (GetTraceParameters() & LOG_BRANCH) PrintTakenBranch(target);
1524   }
1525 
1526   // Print memory accesses.
1527   void PrintRead(uintptr_t address,
1528                  unsigned reg_code,
1529                  PrintRegisterFormat format);
1530   void PrintWrite(uintptr_t address,
1531                   unsigned reg_code,
1532                   PrintRegisterFormat format);
1533   void PrintVRead(uintptr_t address,
1534                   unsigned reg_code,
1535                   PrintRegisterFormat format,
1536                   unsigned lane);
1537   void PrintVWrite(uintptr_t address,
1538                    unsigned reg_code,
1539                    PrintRegisterFormat format,
1540                    unsigned lane);
1541 
1542   // Like Print* (above), but respect GetTraceParameters().
1543   void LogRead(uintptr_t address,
1544                unsigned reg_code,
1545                PrintRegisterFormat format) {
1546     if (GetTraceParameters() & LOG_REGS) PrintRead(address, reg_code, format);
1547   }
1548   void LogWrite(uintptr_t address,
1549                 unsigned reg_code,
1550                 PrintRegisterFormat format) {
1551     if (GetTraceParameters() & LOG_WRITE) PrintWrite(address, reg_code, format);
1552   }
1553   void LogVRead(uintptr_t address,
1554                 unsigned reg_code,
1555                 PrintRegisterFormat format,
1556                 unsigned lane = 0) {
1557     if (GetTraceParameters() & LOG_VREGS) {
1558       PrintVRead(address, reg_code, format, lane);
1559     }
1560   }
1561   void LogVWrite(uintptr_t address,
1562                  unsigned reg_code,
1563                  PrintRegisterFormat format,
1564                  unsigned lane = 0) {
1565     if (GetTraceParameters() & LOG_WRITE) {
1566       PrintVWrite(address, reg_code, format, lane);
1567     }
1568   }
1569 
1570   // Helper functions for register tracing.
1571   void PrintRegisterRawHelper(unsigned code,
1572                               Reg31Mode r31mode,
1573                               int size_in_bytes = kXRegSizeInBytes);
1574   void PrintVRegisterRawHelper(unsigned code,
1575                                int bytes = kQRegSizeInBytes,
1576                                int lsb = 0);
1577   void PrintVRegisterFPHelper(unsigned code,
1578                               unsigned lane_size_in_bytes,
1579                               int lane_count = 1,
1580                               int rightmost_lane = 0);
1581 
1582   VIXL_NO_RETURN void DoUnreachable(const Instruction* instr);
1583   void DoTrace(const Instruction* instr);
1584   void DoLog(const Instruction* instr);
1585 
1586   static const char* WRegNameForCode(unsigned code,
1587                                      Reg31Mode mode = Reg31IsZeroRegister);
1588   static const char* XRegNameForCode(unsigned code,
1589                                      Reg31Mode mode = Reg31IsZeroRegister);
1590   static const char* HRegNameForCode(unsigned code);
1591   static const char* SRegNameForCode(unsigned code);
1592   static const char* DRegNameForCode(unsigned code);
1593   static const char* VRegNameForCode(unsigned code);
1594 
1595   bool IsColouredTrace() const { return coloured_trace_; }
1596   VIXL_DEPRECATED("IsColouredTrace", bool coloured_trace() const) {
1597     return IsColouredTrace();
1598   }
1599 
1600   void SetColouredTrace(bool value);
1601   VIXL_DEPRECATED("SetColouredTrace", void set_coloured_trace(bool value)) {
1602     SetColouredTrace(value);
1603   }
1604 
1605   // Values for traces parameters defined in simulator-constants-aarch64.h in
1606   // enum TraceParameters.
1607   int GetTraceParameters() const { return trace_parameters_; }
1608   VIXL_DEPRECATED("GetTraceParameters", int trace_parameters() const) {
1609     return GetTraceParameters();
1610   }
1611 
1612   void SetTraceParameters(int parameters);
1613   VIXL_DEPRECATED("SetTraceParameters",
1614                   void set_trace_parameters(int parameters)) {
1615     SetTraceParameters(parameters);
1616   }
1617 
1618   void SetInstructionStats(bool value);
1619   VIXL_DEPRECATED("SetInstructionStats",
1620                   void set_instruction_stats(bool value)) {
1621     SetInstructionStats(value);
1622   }
1623 
1624   // Clear the simulated local monitor to force the next store-exclusive
1625   // instruction to fail.
1626   void ClearLocalMonitor() { local_monitor_.Clear(); }
1627 
1628   void SilenceExclusiveAccessWarning() {
1629     print_exclusive_access_warning_ = false;
1630   }
1631 
1632   void CheckIsValidUnalignedAtomicAccess(int rn,
1633                                          uint64_t address,
1634                                          unsigned access_size) {
1635     // Verify that the address is available to the host.
1636     VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1637 
1638     if (GetCPUFeatures()->Has(CPUFeatures::kUSCAT)) {
1639       // Check that the access falls entirely within one atomic access granule.
1640       if (AlignDown(address, kAtomicAccessGranule) !=
1641           AlignDown(address + access_size - 1, kAtomicAccessGranule)) {
1642         VIXL_ALIGNMENT_EXCEPTION();
1643       }
1644     } else {
1645       // Check that the access is aligned.
1646       if (AlignDown(address, access_size) != address) {
1647         VIXL_ALIGNMENT_EXCEPTION();
1648       }
1649     }
1650 
1651     // The sp must be aligned to 16 bytes when it is accessed.
1652     if ((rn == kSpRegCode) && (AlignDown(address, 16) != address)) {
1653       VIXL_ALIGNMENT_EXCEPTION();
1654     }
1655   }
1656 
1657   enum PointerType { kDataPointer, kInstructionPointer };
1658 
1659   struct PACKey {
1660     uint64_t high;
1661     uint64_t low;
1662     int number;
1663   };
1664 
1665   // Current implementation is that all pointers are tagged.
1666   bool HasTBI(uint64_t ptr, PointerType type) {
1667     USE(ptr, type);
1668     return true;
1669   }
1670 
1671   // Current implementation uses 48-bit virtual addresses.
1672   int GetBottomPACBit(uint64_t ptr, int ttbr) {
1673     USE(ptr, ttbr);
1674     VIXL_ASSERT((ttbr == 0) || (ttbr == 1));
1675     return 48;
1676   }
1677 
1678   // The top PAC bit is 55 for the purposes of relative bit fields with TBI,
1679   // however bit 55 is the TTBR bit regardless of TBI so isn't part of the PAC
1680   // codes in pointers.
1681   int GetTopPACBit(uint64_t ptr, PointerType type) {
1682     return HasTBI(ptr, type) ? 55 : 63;
1683   }
1684 
1685   // Armv8.3 Pointer authentication helpers.
1686   uint64_t CalculatePACMask(uint64_t ptr, PointerType type, int ext_bit);
1687   uint64_t ComputePAC(uint64_t data, uint64_t context, PACKey key);
1688   uint64_t AuthPAC(uint64_t ptr,
1689                    uint64_t context,
1690                    PACKey key,
1691                    PointerType type);
1692   uint64_t AddPAC(uint64_t ptr, uint64_t context, PACKey key, PointerType type);
1693   uint64_t StripPAC(uint64_t ptr, PointerType type);
1694 
1695   // The common CPUFeatures interface with the set of available features.
1696 
1697   CPUFeatures* GetCPUFeatures() {
1698     return cpu_features_auditor_.GetCPUFeatures();
1699   }
1700 
1701   void SetCPUFeatures(const CPUFeatures& cpu_features) {
1702     cpu_features_auditor_.SetCPUFeatures(cpu_features);
1703   }
1704 
1705   // The set of features that the simulator has encountered.
1706   const CPUFeatures& GetSeenFeatures() {
1707     return cpu_features_auditor_.GetSeenFeatures();
1708   }
1709   void ResetSeenFeatures() { cpu_features_auditor_.ResetSeenFeatures(); }
1710 
1711 // Runtime call emulation support.
1712 // It requires VIXL's ABI features, and C++11 or greater.
1713 // Also, the initialisation of the tuples in RuntimeCall(Non)Void is incorrect
1714 // in GCC before 4.9.1: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51253
1715 #if defined(VIXL_HAS_ABI_SUPPORT) && __cplusplus >= 201103L && \
1716     (defined(__clang__) || GCC_VERSION_OR_NEWER(4, 9, 1))
1717 
1718 #define VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
1719 
1720 // The implementation of the runtime call helpers require the functionality
1721 // provided by `std::index_sequence`. It is only available from C++14, but
1722 // we want runtime call simulation to work from C++11, so we emulate if
1723 // necessary.
1724 #if __cplusplus >= 201402L
1725   template <std::size_t... I>
1726   using local_index_sequence = std::index_sequence<I...>;
1727   template <typename... P>
1728   using __local_index_sequence_for = std::index_sequence_for<P...>;
1729 #else
1730   // Emulate the behaviour of `std::index_sequence` and
1731   // `std::index_sequence_for`.
1732   // Naming follow the `std` names, prefixed with `emulated_`.
1733   template <size_t... I>
1734   struct emulated_index_sequence {};
1735 
1736   // A recursive template to create a sequence of indexes.
1737   // The base case (for `N == 0`) is declared outside of the class scope, as
1738   // required by C++.
1739   template <std::size_t N, size_t... I>
1740   struct emulated_make_index_sequence_helper
1741       : emulated_make_index_sequence_helper<N - 1, N - 1, I...> {};
1742 
1743   template <std::size_t N>
1744   struct emulated_make_index_sequence : emulated_make_index_sequence_helper<N> {
1745   };
1746 
1747   template <typename... P>
1748   struct emulated_index_sequence_for
1749       : emulated_make_index_sequence<sizeof...(P)> {};
1750 
1751   template <std::size_t... I>
1752   using local_index_sequence = emulated_index_sequence<I...>;
1753   template <typename... P>
1754   using __local_index_sequence_for = emulated_index_sequence_for<P...>;
1755 #endif
1756 
1757   // Expand the argument tuple and perform the call.
1758   template <typename R, typename... P, std::size_t... I>
1759   R DoRuntimeCall(R (*function)(P...),
1760                   std::tuple<P...> arguments,
1761                   local_index_sequence<I...>) {
1762     return function(std::get<I>(arguments)...);
1763   }
1764 
1765   template <typename R, typename... P>
1766   void RuntimeCallNonVoid(R (*function)(P...)) {
1767     ABI abi;
1768     std::tuple<P...> argument_operands{
1769         ReadGenericOperand<P>(abi.GetNextParameterGenericOperand<P>())...};
1770     R return_value = DoRuntimeCall(function,
1771                                    argument_operands,
1772                                    __local_index_sequence_for<P...>{});
1773     WriteGenericOperand(abi.GetReturnGenericOperand<R>(), return_value);
1774   }
1775 
1776   template <typename R, typename... P>
1777   void RuntimeCallVoid(R (*function)(P...)) {
1778     ABI abi;
1779     std::tuple<P...> argument_operands{
1780         ReadGenericOperand<P>(abi.GetNextParameterGenericOperand<P>())...};
1781     DoRuntimeCall(function,
1782                   argument_operands,
1783                   __local_index_sequence_for<P...>{});
1784   }
1785 
1786   // We use `struct` for `void` return type specialisation.
1787   template <typename R, typename... P>
1788   struct RuntimeCallStructHelper {
1789     static void Wrapper(Simulator* simulator, uintptr_t function_pointer) {
1790       R (*function)(P...) = reinterpret_cast<R (*)(P...)>(function_pointer);
1791       simulator->RuntimeCallNonVoid(function);
1792     }
1793   };
1794 
1795   // Partial specialization when the return type is `void`.
1796   template <typename... P>
1797   struct RuntimeCallStructHelper<void, P...> {
1798     static void Wrapper(Simulator* simulator, uintptr_t function_pointer) {
1799       void (*function)(P...) =
1800           reinterpret_cast<void (*)(P...)>(function_pointer);
1801       simulator->RuntimeCallVoid(function);
1802     }
1803   };
1804 #endif
1805 
1806  protected:
1807   const char* clr_normal;
1808   const char* clr_flag_name;
1809   const char* clr_flag_value;
1810   const char* clr_reg_name;
1811   const char* clr_reg_value;
1812   const char* clr_vreg_name;
1813   const char* clr_vreg_value;
1814   const char* clr_memory_address;
1815   const char* clr_warning;
1816   const char* clr_warning_message;
1817   const char* clr_printf;
1818   const char* clr_branch_marker;
1819 
1820   // Simulation helpers ------------------------------------
1821   bool ConditionPassed(Condition cond) {
1822     switch (cond) {
1823       case eq:
1824         return ReadZ();
1825       case ne:
1826         return !ReadZ();
1827       case hs:
1828         return ReadC();
1829       case lo:
1830         return !ReadC();
1831       case mi:
1832         return ReadN();
1833       case pl:
1834         return !ReadN();
1835       case vs:
1836         return ReadV();
1837       case vc:
1838         return !ReadV();
1839       case hi:
1840         return ReadC() && !ReadZ();
1841       case ls:
1842         return !(ReadC() && !ReadZ());
1843       case ge:
1844         return ReadN() == ReadV();
1845       case lt:
1846         return ReadN() != ReadV();
1847       case gt:
1848         return !ReadZ() && (ReadN() == ReadV());
1849       case le:
1850         return !(!ReadZ() && (ReadN() == ReadV()));
1851       case nv:
1852         VIXL_FALLTHROUGH();
1853       case al:
1854         return true;
1855       default:
1856         VIXL_UNREACHABLE();
1857         return false;
1858     }
1859   }
1860 
1861   bool ConditionPassed(Instr cond) {
1862     return ConditionPassed(static_cast<Condition>(cond));
1863   }
1864 
1865   bool ConditionFailed(Condition cond) { return !ConditionPassed(cond); }
1866 
1867   void AddSubHelper(const Instruction* instr, int64_t op2);
1868   uint64_t AddWithCarry(unsigned reg_size,
1869                         bool set_flags,
1870                         uint64_t left,
1871                         uint64_t right,
1872                         int carry_in = 0);
1873   void LogicalHelper(const Instruction* instr, int64_t op2);
1874   void ConditionalCompareHelper(const Instruction* instr, int64_t op2);
1875   void LoadStoreHelper(const Instruction* instr,
1876                        int64_t offset,
1877                        AddrMode addrmode);
1878   void LoadStorePairHelper(const Instruction* instr, AddrMode addrmode);
1879   template <typename T>
1880   void CompareAndSwapHelper(const Instruction* instr);
1881   template <typename T>
1882   void CompareAndSwapPairHelper(const Instruction* instr);
1883   template <typename T>
1884   void AtomicMemorySimpleHelper(const Instruction* instr);
1885   template <typename T>
1886   void AtomicMemorySwapHelper(const Instruction* instr);
1887   template <typename T>
1888   void LoadAcquireRCpcHelper(const Instruction* instr);
1889   template <typename T1, typename T2>
1890   void LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr);
1891   template <typename T>
1892   void StoreReleaseUnscaledOffsetHelper(const Instruction* instr);
1893   uintptr_t AddressModeHelper(unsigned addr_reg,
1894                               int64_t offset,
1895                               AddrMode addrmode);
1896   void NEONLoadStoreMultiStructHelper(const Instruction* instr,
1897                                       AddrMode addr_mode);
1898   void NEONLoadStoreSingleStructHelper(const Instruction* instr,
1899                                        AddrMode addr_mode);
1900 
1901   uint64_t AddressUntag(uint64_t address) { return address & ~kAddressTagMask; }
1902 
1903   template <typename T>
1904   T* AddressUntag(T* address) {
1905     uintptr_t address_raw = reinterpret_cast<uintptr_t>(address);
1906     return reinterpret_cast<T*>(AddressUntag(address_raw));
1907   }
1908 
1909   int64_t ShiftOperand(unsigned reg_size,
1910                        int64_t value,
1911                        Shift shift_type,
1912                        unsigned amount) const;
1913   int64_t ExtendValue(unsigned reg_width,
1914                       int64_t value,
1915                       Extend extend_type,
1916                       unsigned left_shift = 0) const;
1917   uint16_t PolynomialMult(uint8_t op1, uint8_t op2) const;
1918 
1919   void ld1(VectorFormat vform, LogicVRegister dst, uint64_t addr);
1920   void ld1(VectorFormat vform, LogicVRegister dst, int index, uint64_t addr);
1921   void ld1r(VectorFormat vform, LogicVRegister dst, uint64_t addr);
1922   void ld2(VectorFormat vform,
1923            LogicVRegister dst1,
1924            LogicVRegister dst2,
1925            uint64_t addr);
1926   void ld2(VectorFormat vform,
1927            LogicVRegister dst1,
1928            LogicVRegister dst2,
1929            int index,
1930            uint64_t addr);
1931   void ld2r(VectorFormat vform,
1932             LogicVRegister dst1,
1933             LogicVRegister dst2,
1934             uint64_t addr);
1935   void ld3(VectorFormat vform,
1936            LogicVRegister dst1,
1937            LogicVRegister dst2,
1938            LogicVRegister dst3,
1939            uint64_t addr);
1940   void ld3(VectorFormat vform,
1941            LogicVRegister dst1,
1942            LogicVRegister dst2,
1943            LogicVRegister dst3,
1944            int index,
1945            uint64_t addr);
1946   void ld3r(VectorFormat vform,
1947             LogicVRegister dst1,
1948             LogicVRegister dst2,
1949             LogicVRegister dst3,
1950             uint64_t addr);
1951   void ld4(VectorFormat vform,
1952            LogicVRegister dst1,
1953            LogicVRegister dst2,
1954            LogicVRegister dst3,
1955            LogicVRegister dst4,
1956            uint64_t addr);
1957   void ld4(VectorFormat vform,
1958            LogicVRegister dst1,
1959            LogicVRegister dst2,
1960            LogicVRegister dst3,
1961            LogicVRegister dst4,
1962            int index,
1963            uint64_t addr);
1964   void ld4r(VectorFormat vform,
1965             LogicVRegister dst1,
1966             LogicVRegister dst2,
1967             LogicVRegister dst3,
1968             LogicVRegister dst4,
1969             uint64_t addr);
1970   void st1(VectorFormat vform, LogicVRegister src, uint64_t addr);
1971   void st1(VectorFormat vform, LogicVRegister src, int index, uint64_t addr);
1972   void st2(VectorFormat vform,
1973            LogicVRegister src,
1974            LogicVRegister src2,
1975            uint64_t addr);
1976   void st2(VectorFormat vform,
1977            LogicVRegister src,
1978            LogicVRegister src2,
1979            int index,
1980            uint64_t addr);
1981   void st3(VectorFormat vform,
1982            LogicVRegister src,
1983            LogicVRegister src2,
1984            LogicVRegister src3,
1985            uint64_t addr);
1986   void st3(VectorFormat vform,
1987            LogicVRegister src,
1988            LogicVRegister src2,
1989            LogicVRegister src3,
1990            int index,
1991            uint64_t addr);
1992   void st4(VectorFormat vform,
1993            LogicVRegister src,
1994            LogicVRegister src2,
1995            LogicVRegister src3,
1996            LogicVRegister src4,
1997            uint64_t addr);
1998   void st4(VectorFormat vform,
1999            LogicVRegister src,
2000            LogicVRegister src2,
2001            LogicVRegister src3,
2002            LogicVRegister src4,
2003            int index,
2004            uint64_t addr);
2005   LogicVRegister cmp(VectorFormat vform,
2006                      LogicVRegister dst,
2007                      const LogicVRegister& src1,
2008                      const LogicVRegister& src2,
2009                      Condition cond);
2010   LogicVRegister cmp(VectorFormat vform,
2011                      LogicVRegister dst,
2012                      const LogicVRegister& src1,
2013                      int imm,
2014                      Condition cond);
2015   LogicVRegister cmptst(VectorFormat vform,
2016                         LogicVRegister dst,
2017                         const LogicVRegister& src1,
2018                         const LogicVRegister& src2);
2019   LogicVRegister add(VectorFormat vform,
2020                      LogicVRegister dst,
2021                      const LogicVRegister& src1,
2022                      const LogicVRegister& src2);
2023   LogicVRegister addp(VectorFormat vform,
2024                       LogicVRegister dst,
2025                       const LogicVRegister& src1,
2026                       const LogicVRegister& src2);
2027   LogicVRegister mla(VectorFormat vform,
2028                      LogicVRegister dst,
2029                      const LogicVRegister& src1,
2030                      const LogicVRegister& src2);
2031   LogicVRegister mls(VectorFormat vform,
2032                      LogicVRegister dst,
2033                      const LogicVRegister& src1,
2034                      const LogicVRegister& src2);
2035   LogicVRegister mul(VectorFormat vform,
2036                      LogicVRegister dst,
2037                      const LogicVRegister& src1,
2038                      const LogicVRegister& src2);
2039   LogicVRegister mul(VectorFormat vform,
2040                      LogicVRegister dst,
2041                      const LogicVRegister& src1,
2042                      const LogicVRegister& src2,
2043                      int index);
2044   LogicVRegister mla(VectorFormat vform,
2045                      LogicVRegister dst,
2046                      const LogicVRegister& src1,
2047                      const LogicVRegister& src2,
2048                      int index);
2049   LogicVRegister mls(VectorFormat vform,
2050                      LogicVRegister dst,
2051                      const LogicVRegister& src1,
2052                      const LogicVRegister& src2,
2053                      int index);
2054   LogicVRegister pmul(VectorFormat vform,
2055                       LogicVRegister dst,
2056                       const LogicVRegister& src1,
2057                       const LogicVRegister& src2);
2058 
2059   typedef LogicVRegister (Simulator::*ByElementOp)(VectorFormat vform,
2060                                                    LogicVRegister dst,
2061                                                    const LogicVRegister& src1,
2062                                                    const LogicVRegister& src2,
2063                                                    int index);
2064   LogicVRegister fmul(VectorFormat vform,
2065                       LogicVRegister dst,
2066                       const LogicVRegister& src1,
2067                       const LogicVRegister& src2,
2068                       int index);
2069   LogicVRegister fmla(VectorFormat vform,
2070                       LogicVRegister dst,
2071                       const LogicVRegister& src1,
2072                       const LogicVRegister& src2,
2073                       int index);
2074   LogicVRegister fmlal(VectorFormat vform,
2075                        LogicVRegister dst,
2076                        const LogicVRegister& src1,
2077                        const LogicVRegister& src2,
2078                        int index);
2079   LogicVRegister fmlal2(VectorFormat vform,
2080                         LogicVRegister dst,
2081                         const LogicVRegister& src1,
2082                         const LogicVRegister& src2,
2083                         int index);
2084   LogicVRegister fmls(VectorFormat vform,
2085                       LogicVRegister dst,
2086                       const LogicVRegister& src1,
2087                       const LogicVRegister& src2,
2088                       int index);
2089   LogicVRegister fmlsl(VectorFormat vform,
2090                        LogicVRegister dst,
2091                        const LogicVRegister& src1,
2092                        const LogicVRegister& src2,
2093                        int index);
2094   LogicVRegister fmlsl2(VectorFormat vform,
2095                         LogicVRegister dst,
2096                         const LogicVRegister& src1,
2097                         const LogicVRegister& src2,
2098                         int index);
2099   LogicVRegister fmulx(VectorFormat vform,
2100                        LogicVRegister dst,
2101                        const LogicVRegister& src1,
2102                        const LogicVRegister& src2,
2103                        int index);
2104   LogicVRegister smull(VectorFormat vform,
2105                        LogicVRegister dst,
2106                        const LogicVRegister& src1,
2107                        const LogicVRegister& src2,
2108                        int index);
2109   LogicVRegister smull2(VectorFormat vform,
2110                         LogicVRegister dst,
2111                         const LogicVRegister& src1,
2112                         const LogicVRegister& src2,
2113                         int index);
2114   LogicVRegister umull(VectorFormat vform,
2115                        LogicVRegister dst,
2116                        const LogicVRegister& src1,
2117                        const LogicVRegister& src2,
2118                        int index);
2119   LogicVRegister umull2(VectorFormat vform,
2120                         LogicVRegister dst,
2121                         const LogicVRegister& src1,
2122                         const LogicVRegister& src2,
2123                         int index);
2124   LogicVRegister smlal(VectorFormat vform,
2125                        LogicVRegister dst,
2126                        const LogicVRegister& src1,
2127                        const LogicVRegister& src2,
2128                        int index);
2129   LogicVRegister smlal2(VectorFormat vform,
2130                         LogicVRegister dst,
2131                         const LogicVRegister& src1,
2132                         const LogicVRegister& src2,
2133                         int index);
2134   LogicVRegister umlal(VectorFormat vform,
2135                        LogicVRegister dst,
2136                        const LogicVRegister& src1,
2137                        const LogicVRegister& src2,
2138                        int index);
2139   LogicVRegister umlal2(VectorFormat vform,
2140                         LogicVRegister dst,
2141                         const LogicVRegister& src1,
2142                         const LogicVRegister& src2,
2143                         int index);
2144   LogicVRegister smlsl(VectorFormat vform,
2145                        LogicVRegister dst,
2146                        const LogicVRegister& src1,
2147                        const LogicVRegister& src2,
2148                        int index);
2149   LogicVRegister smlsl2(VectorFormat vform,
2150                         LogicVRegister dst,
2151                         const LogicVRegister& src1,
2152                         const LogicVRegister& src2,
2153                         int index);
2154   LogicVRegister umlsl(VectorFormat vform,
2155                        LogicVRegister dst,
2156                        const LogicVRegister& src1,
2157                        const LogicVRegister& src2,
2158                        int index);
2159   LogicVRegister umlsl2(VectorFormat vform,
2160                         LogicVRegister dst,
2161                         const LogicVRegister& src1,
2162                         const LogicVRegister& src2,
2163                         int index);
2164   LogicVRegister sqdmull(VectorFormat vform,
2165                          LogicVRegister dst,
2166                          const LogicVRegister& src1,
2167                          const LogicVRegister& src2,
2168                          int index);
2169   LogicVRegister sqdmull2(VectorFormat vform,
2170                           LogicVRegister dst,
2171                           const LogicVRegister& src1,
2172                           const LogicVRegister& src2,
2173                           int index);
2174   LogicVRegister sqdmlal(VectorFormat vform,
2175                          LogicVRegister dst,
2176                          const LogicVRegister& src1,
2177                          const LogicVRegister& src2,
2178                          int index);
2179   LogicVRegister sqdmlal2(VectorFormat vform,
2180                           LogicVRegister dst,
2181                           const LogicVRegister& src1,
2182                           const LogicVRegister& src2,
2183                           int index);
2184   LogicVRegister sqdmlsl(VectorFormat vform,
2185                          LogicVRegister dst,
2186                          const LogicVRegister& src1,
2187                          const LogicVRegister& src2,
2188                          int index);
2189   LogicVRegister sqdmlsl2(VectorFormat vform,
2190                           LogicVRegister dst,
2191                           const LogicVRegister& src1,
2192                           const LogicVRegister& src2,
2193                           int index);
2194   LogicVRegister sqdmulh(VectorFormat vform,
2195                          LogicVRegister dst,
2196                          const LogicVRegister& src1,
2197                          const LogicVRegister& src2,
2198                          int index);
2199   LogicVRegister sqrdmulh(VectorFormat vform,
2200                           LogicVRegister dst,
2201                           const LogicVRegister& src1,
2202                           const LogicVRegister& src2,
2203                           int index);
2204   LogicVRegister sdot(VectorFormat vform,
2205                       LogicVRegister dst,
2206                       const LogicVRegister& src1,
2207                       const LogicVRegister& src2,
2208                       int index);
2209   LogicVRegister sqrdmlah(VectorFormat vform,
2210                           LogicVRegister dst,
2211                           const LogicVRegister& src1,
2212                           const LogicVRegister& src2,
2213                           int index);
2214   LogicVRegister udot(VectorFormat vform,
2215                       LogicVRegister dst,
2216                       const LogicVRegister& src1,
2217                       const LogicVRegister& src2,
2218                       int index);
2219   LogicVRegister sqrdmlsh(VectorFormat vform,
2220                           LogicVRegister dst,
2221                           const LogicVRegister& src1,
2222                           const LogicVRegister& src2,
2223                           int index);
2224   LogicVRegister sub(VectorFormat vform,
2225                      LogicVRegister dst,
2226                      const LogicVRegister& src1,
2227                      const LogicVRegister& src2);
2228   LogicVRegister and_(VectorFormat vform,
2229                       LogicVRegister dst,
2230                       const LogicVRegister& src1,
2231                       const LogicVRegister& src2);
2232   LogicVRegister orr(VectorFormat vform,
2233                      LogicVRegister dst,
2234                      const LogicVRegister& src1,
2235                      const LogicVRegister& src2);
2236   LogicVRegister orn(VectorFormat vform,
2237                      LogicVRegister dst,
2238                      const LogicVRegister& src1,
2239                      const LogicVRegister& src2);
2240   LogicVRegister eor(VectorFormat vform,
2241                      LogicVRegister dst,
2242                      const LogicVRegister& src1,
2243                      const LogicVRegister& src2);
2244   LogicVRegister bic(VectorFormat vform,
2245                      LogicVRegister dst,
2246                      const LogicVRegister& src1,
2247                      const LogicVRegister& src2);
2248   LogicVRegister bic(VectorFormat vform,
2249                      LogicVRegister dst,
2250                      const LogicVRegister& src,
2251                      uint64_t imm);
2252   LogicVRegister bif(VectorFormat vform,
2253                      LogicVRegister dst,
2254                      const LogicVRegister& src1,
2255                      const LogicVRegister& src2);
2256   LogicVRegister bit(VectorFormat vform,
2257                      LogicVRegister dst,
2258                      const LogicVRegister& src1,
2259                      const LogicVRegister& src2);
2260   LogicVRegister bsl(VectorFormat vform,
2261                      LogicVRegister dst,
2262                      const LogicVRegister& src1,
2263                      const LogicVRegister& src2);
2264   LogicVRegister cls(VectorFormat vform,
2265                      LogicVRegister dst,
2266                      const LogicVRegister& src);
2267   LogicVRegister clz(VectorFormat vform,
2268                      LogicVRegister dst,
2269                      const LogicVRegister& src);
2270   LogicVRegister cnt(VectorFormat vform,
2271                      LogicVRegister dst,
2272                      const LogicVRegister& src);
2273   LogicVRegister not_(VectorFormat vform,
2274                       LogicVRegister dst,
2275                       const LogicVRegister& src);
2276   LogicVRegister rbit(VectorFormat vform,
2277                       LogicVRegister dst,
2278                       const LogicVRegister& src);
2279   LogicVRegister rev(VectorFormat vform,
2280                      LogicVRegister dst,
2281                      const LogicVRegister& src,
2282                      int revSize);
2283   LogicVRegister rev16(VectorFormat vform,
2284                        LogicVRegister dst,
2285                        const LogicVRegister& src);
2286   LogicVRegister rev32(VectorFormat vform,
2287                        LogicVRegister dst,
2288                        const LogicVRegister& src);
2289   LogicVRegister rev64(VectorFormat vform,
2290                        LogicVRegister dst,
2291                        const LogicVRegister& src);
2292   LogicVRegister addlp(VectorFormat vform,
2293                        LogicVRegister dst,
2294                        const LogicVRegister& src,
2295                        bool is_signed,
2296                        bool do_accumulate);
2297   LogicVRegister saddlp(VectorFormat vform,
2298                         LogicVRegister dst,
2299                         const LogicVRegister& src);
2300   LogicVRegister uaddlp(VectorFormat vform,
2301                         LogicVRegister dst,
2302                         const LogicVRegister& src);
2303   LogicVRegister sadalp(VectorFormat vform,
2304                         LogicVRegister dst,
2305                         const LogicVRegister& src);
2306   LogicVRegister uadalp(VectorFormat vform,
2307                         LogicVRegister dst,
2308                         const LogicVRegister& src);
2309   LogicVRegister ext(VectorFormat vform,
2310                      LogicVRegister dst,
2311                      const LogicVRegister& src1,
2312                      const LogicVRegister& src2,
2313                      int index);
2314   template <typename T>
2315   LogicVRegister fcadd(VectorFormat vform,
2316                        LogicVRegister dst,
2317                        const LogicVRegister& src1,
2318                        const LogicVRegister& src2,
2319                        int rot);
2320   LogicVRegister fcadd(VectorFormat vform,
2321                        LogicVRegister dst,
2322                        const LogicVRegister& src1,
2323                        const LogicVRegister& src2,
2324                        int rot);
2325   template <typename T>
2326   LogicVRegister fcmla(VectorFormat vform,
2327                        LogicVRegister dst,
2328                        const LogicVRegister& src1,
2329                        const LogicVRegister& src2,
2330                        int index,
2331                        int rot);
2332   LogicVRegister fcmla(VectorFormat vform,
2333                        LogicVRegister dst,
2334                        const LogicVRegister& src1,
2335                        const LogicVRegister& src2,
2336                        int index,
2337                        int rot);
2338   template <typename T>
2339   LogicVRegister fcmla(VectorFormat vform,
2340                        LogicVRegister dst,
2341                        const LogicVRegister& src1,
2342                        const LogicVRegister& src2,
2343                        int rot);
2344   LogicVRegister fcmla(VectorFormat vform,
2345                        LogicVRegister dst,
2346                        const LogicVRegister& src1,
2347                        const LogicVRegister& src2,
2348                        int rot);
2349   LogicVRegister ins_element(VectorFormat vform,
2350                              LogicVRegister dst,
2351                              int dst_index,
2352                              const LogicVRegister& src,
2353                              int src_index);
2354   LogicVRegister ins_immediate(VectorFormat vform,
2355                                LogicVRegister dst,
2356                                int dst_index,
2357                                uint64_t imm);
2358   LogicVRegister dup_element(VectorFormat vform,
2359                              LogicVRegister dst,
2360                              const LogicVRegister& src,
2361                              int src_index);
2362   LogicVRegister dup_immediate(VectorFormat vform,
2363                                LogicVRegister dst,
2364                                uint64_t imm);
2365   LogicVRegister movi(VectorFormat vform, LogicVRegister dst, uint64_t imm);
2366   LogicVRegister mvni(VectorFormat vform, LogicVRegister dst, uint64_t imm);
2367   LogicVRegister orr(VectorFormat vform,
2368                      LogicVRegister dst,
2369                      const LogicVRegister& src,
2370                      uint64_t imm);
2371   LogicVRegister sshl(VectorFormat vform,
2372                       LogicVRegister dst,
2373                       const LogicVRegister& src1,
2374                       const LogicVRegister& src2);
2375   LogicVRegister ushl(VectorFormat vform,
2376                       LogicVRegister dst,
2377                       const LogicVRegister& src1,
2378                       const LogicVRegister& src2);
2379   LogicVRegister sminmax(VectorFormat vform,
2380                          LogicVRegister dst,
2381                          const LogicVRegister& src1,
2382                          const LogicVRegister& src2,
2383                          bool max);
2384   LogicVRegister smax(VectorFormat vform,
2385                       LogicVRegister dst,
2386                       const LogicVRegister& src1,
2387                       const LogicVRegister& src2);
2388   LogicVRegister smin(VectorFormat vform,
2389                       LogicVRegister dst,
2390                       const LogicVRegister& src1,
2391                       const LogicVRegister& src2);
2392   LogicVRegister sminmaxp(VectorFormat vform,
2393                           LogicVRegister dst,
2394                           const LogicVRegister& src1,
2395                           const LogicVRegister& src2,
2396                           bool max);
2397   LogicVRegister smaxp(VectorFormat vform,
2398                        LogicVRegister dst,
2399                        const LogicVRegister& src1,
2400                        const LogicVRegister& src2);
2401   LogicVRegister sminp(VectorFormat vform,
2402                        LogicVRegister dst,
2403                        const LogicVRegister& src1,
2404                        const LogicVRegister& src2);
2405   LogicVRegister addp(VectorFormat vform,
2406                       LogicVRegister dst,
2407                       const LogicVRegister& src);
2408   LogicVRegister addv(VectorFormat vform,
2409                       LogicVRegister dst,
2410                       const LogicVRegister& src);
2411   LogicVRegister uaddlv(VectorFormat vform,
2412                         LogicVRegister dst,
2413                         const LogicVRegister& src);
2414   LogicVRegister saddlv(VectorFormat vform,
2415                         LogicVRegister dst,
2416                         const LogicVRegister& src);
2417   LogicVRegister sminmaxv(VectorFormat vform,
2418                           LogicVRegister dst,
2419                           const LogicVRegister& src,
2420                           bool max);
2421   LogicVRegister smaxv(VectorFormat vform,
2422                        LogicVRegister dst,
2423                        const LogicVRegister& src);
2424   LogicVRegister sminv(VectorFormat vform,
2425                        LogicVRegister dst,
2426                        const LogicVRegister& src);
2427   LogicVRegister uxtl(VectorFormat vform,
2428                       LogicVRegister dst,
2429                       const LogicVRegister& src);
2430   LogicVRegister uxtl2(VectorFormat vform,
2431                        LogicVRegister dst,
2432                        const LogicVRegister& src);
2433   LogicVRegister sxtl(VectorFormat vform,
2434                       LogicVRegister dst,
2435                       const LogicVRegister& src);
2436   LogicVRegister sxtl2(VectorFormat vform,
2437                        LogicVRegister dst,
2438                        const LogicVRegister& src);
2439   LogicVRegister tbl(VectorFormat vform,
2440                      LogicVRegister dst,
2441                      const LogicVRegister& tab,
2442                      const LogicVRegister& ind);
2443   LogicVRegister tbl(VectorFormat vform,
2444                      LogicVRegister dst,
2445                      const LogicVRegister& tab,
2446                      const LogicVRegister& tab2,
2447                      const LogicVRegister& ind);
2448   LogicVRegister tbl(VectorFormat vform,
2449                      LogicVRegister dst,
2450                      const LogicVRegister& tab,
2451                      const LogicVRegister& tab2,
2452                      const LogicVRegister& tab3,
2453                      const LogicVRegister& ind);
2454   LogicVRegister tbl(VectorFormat vform,
2455                      LogicVRegister dst,
2456                      const LogicVRegister& tab,
2457                      const LogicVRegister& tab2,
2458                      const LogicVRegister& tab3,
2459                      const LogicVRegister& tab4,
2460                      const LogicVRegister& ind);
2461   LogicVRegister Table(VectorFormat vform,
2462                        LogicVRegister dst,
2463                        const LogicVRegister& ind,
2464                        bool zero_out_of_bounds,
2465                        const LogicVRegister* tab1,
2466                        const LogicVRegister* tab2 = NULL,
2467                        const LogicVRegister* tab3 = NULL,
2468                        const LogicVRegister* tab4 = NULL);
2469   LogicVRegister tbx(VectorFormat vform,
2470                      LogicVRegister dst,
2471                      const LogicVRegister& tab,
2472                      const LogicVRegister& ind);
2473   LogicVRegister tbx(VectorFormat vform,
2474                      LogicVRegister dst,
2475                      const LogicVRegister& tab,
2476                      const LogicVRegister& tab2,
2477                      const LogicVRegister& ind);
2478   LogicVRegister tbx(VectorFormat vform,
2479                      LogicVRegister dst,
2480                      const LogicVRegister& tab,
2481                      const LogicVRegister& tab2,
2482                      const LogicVRegister& tab3,
2483                      const LogicVRegister& ind);
2484   LogicVRegister tbx(VectorFormat vform,
2485                      LogicVRegister dst,
2486                      const LogicVRegister& tab,
2487                      const LogicVRegister& tab2,
2488                      const LogicVRegister& tab3,
2489                      const LogicVRegister& tab4,
2490                      const LogicVRegister& ind);
2491   LogicVRegister uaddl(VectorFormat vform,
2492                        LogicVRegister dst,
2493                        const LogicVRegister& src1,
2494                        const LogicVRegister& src2);
2495   LogicVRegister uaddl2(VectorFormat vform,
2496                         LogicVRegister dst,
2497                         const LogicVRegister& src1,
2498                         const LogicVRegister& src2);
2499   LogicVRegister uaddw(VectorFormat vform,
2500                        LogicVRegister dst,
2501                        const LogicVRegister& src1,
2502                        const LogicVRegister& src2);
2503   LogicVRegister uaddw2(VectorFormat vform,
2504                         LogicVRegister dst,
2505                         const LogicVRegister& src1,
2506                         const LogicVRegister& src2);
2507   LogicVRegister saddl(VectorFormat vform,
2508                        LogicVRegister dst,
2509                        const LogicVRegister& src1,
2510                        const LogicVRegister& src2);
2511   LogicVRegister saddl2(VectorFormat vform,
2512                         LogicVRegister dst,
2513                         const LogicVRegister& src1,
2514                         const LogicVRegister& src2);
2515   LogicVRegister saddw(VectorFormat vform,
2516                        LogicVRegister dst,
2517                        const LogicVRegister& src1,
2518                        const LogicVRegister& src2);
2519   LogicVRegister saddw2(VectorFormat vform,
2520                         LogicVRegister dst,
2521                         const LogicVRegister& src1,
2522                         const LogicVRegister& src2);
2523   LogicVRegister usubl(VectorFormat vform,
2524                        LogicVRegister dst,
2525                        const LogicVRegister& src1,
2526                        const LogicVRegister& src2);
2527   LogicVRegister usubl2(VectorFormat vform,
2528                         LogicVRegister dst,
2529                         const LogicVRegister& src1,
2530                         const LogicVRegister& src2);
2531   LogicVRegister usubw(VectorFormat vform,
2532                        LogicVRegister dst,
2533                        const LogicVRegister& src1,
2534                        const LogicVRegister& src2);
2535   LogicVRegister usubw2(VectorFormat vform,
2536                         LogicVRegister dst,
2537                         const LogicVRegister& src1,
2538                         const LogicVRegister& src2);
2539   LogicVRegister ssubl(VectorFormat vform,
2540                        LogicVRegister dst,
2541                        const LogicVRegister& src1,
2542                        const LogicVRegister& src2);
2543   LogicVRegister ssubl2(VectorFormat vform,
2544                         LogicVRegister dst,
2545                         const LogicVRegister& src1,
2546                         const LogicVRegister& src2);
2547   LogicVRegister ssubw(VectorFormat vform,
2548                        LogicVRegister dst,
2549                        const LogicVRegister& src1,
2550                        const LogicVRegister& src2);
2551   LogicVRegister ssubw2(VectorFormat vform,
2552                         LogicVRegister dst,
2553                         const LogicVRegister& src1,
2554                         const LogicVRegister& src2);
2555   LogicVRegister uminmax(VectorFormat vform,
2556                          LogicVRegister dst,
2557                          const LogicVRegister& src1,
2558                          const LogicVRegister& src2,
2559                          bool max);
2560   LogicVRegister umax(VectorFormat vform,
2561                       LogicVRegister dst,
2562                       const LogicVRegister& src1,
2563                       const LogicVRegister& src2);
2564   LogicVRegister umin(VectorFormat vform,
2565                       LogicVRegister dst,
2566                       const LogicVRegister& src1,
2567                       const LogicVRegister& src2);
2568   LogicVRegister uminmaxp(VectorFormat vform,
2569                           LogicVRegister dst,
2570                           const LogicVRegister& src1,
2571                           const LogicVRegister& src2,
2572                           bool max);
2573   LogicVRegister umaxp(VectorFormat vform,
2574                        LogicVRegister dst,
2575                        const LogicVRegister& src1,
2576                        const LogicVRegister& src2);
2577   LogicVRegister uminp(VectorFormat vform,
2578                        LogicVRegister dst,
2579                        const LogicVRegister& src1,
2580                        const LogicVRegister& src2);
2581   LogicVRegister uminmaxv(VectorFormat vform,
2582                           LogicVRegister dst,
2583                           const LogicVRegister& src,
2584                           bool max);
2585   LogicVRegister umaxv(VectorFormat vform,
2586                        LogicVRegister dst,
2587                        const LogicVRegister& src);
2588   LogicVRegister uminv(VectorFormat vform,
2589                        LogicVRegister dst,
2590                        const LogicVRegister& src);
2591   LogicVRegister trn1(VectorFormat vform,
2592                       LogicVRegister dst,
2593                       const LogicVRegister& src1,
2594                       const LogicVRegister& src2);
2595   LogicVRegister trn2(VectorFormat vform,
2596                       LogicVRegister dst,
2597                       const LogicVRegister& src1,
2598                       const LogicVRegister& src2);
2599   LogicVRegister zip1(VectorFormat vform,
2600                       LogicVRegister dst,
2601                       const LogicVRegister& src1,
2602                       const LogicVRegister& src2);
2603   LogicVRegister zip2(VectorFormat vform,
2604                       LogicVRegister dst,
2605                       const LogicVRegister& src1,
2606                       const LogicVRegister& src2);
2607   LogicVRegister uzp1(VectorFormat vform,
2608                       LogicVRegister dst,
2609                       const LogicVRegister& src1,
2610                       const LogicVRegister& src2);
2611   LogicVRegister uzp2(VectorFormat vform,
2612                       LogicVRegister dst,
2613                       const LogicVRegister& src1,
2614                       const LogicVRegister& src2);
2615   LogicVRegister shl(VectorFormat vform,
2616                      LogicVRegister dst,
2617                      const LogicVRegister& src,
2618                      int shift);
2619   LogicVRegister scvtf(VectorFormat vform,
2620                        LogicVRegister dst,
2621                        const LogicVRegister& src,
2622                        int fbits,
2623                        FPRounding rounding_mode);
2624   LogicVRegister ucvtf(VectorFormat vform,
2625                        LogicVRegister dst,
2626                        const LogicVRegister& src,
2627                        int fbits,
2628                        FPRounding rounding_mode);
2629   LogicVRegister sshll(VectorFormat vform,
2630                        LogicVRegister dst,
2631                        const LogicVRegister& src,
2632                        int shift);
2633   LogicVRegister sshll2(VectorFormat vform,
2634                         LogicVRegister dst,
2635                         const LogicVRegister& src,
2636                         int shift);
2637   LogicVRegister shll(VectorFormat vform,
2638                       LogicVRegister dst,
2639                       const LogicVRegister& src);
2640   LogicVRegister shll2(VectorFormat vform,
2641                        LogicVRegister dst,
2642                        const LogicVRegister& src);
2643   LogicVRegister ushll(VectorFormat vform,
2644                        LogicVRegister dst,
2645                        const LogicVRegister& src,
2646                        int shift);
2647   LogicVRegister ushll2(VectorFormat vform,
2648                         LogicVRegister dst,
2649                         const LogicVRegister& src,
2650                         int shift);
2651   LogicVRegister sli(VectorFormat vform,
2652                      LogicVRegister dst,
2653                      const LogicVRegister& src,
2654                      int shift);
2655   LogicVRegister sri(VectorFormat vform,
2656                      LogicVRegister dst,
2657                      const LogicVRegister& src,
2658                      int shift);
2659   LogicVRegister sshr(VectorFormat vform,
2660                       LogicVRegister dst,
2661                       const LogicVRegister& src,
2662                       int shift);
2663   LogicVRegister ushr(VectorFormat vform,
2664                       LogicVRegister dst,
2665                       const LogicVRegister& src,
2666                       int shift);
2667   LogicVRegister ssra(VectorFormat vform,
2668                       LogicVRegister dst,
2669                       const LogicVRegister& src,
2670                       int shift);
2671   LogicVRegister usra(VectorFormat vform,
2672                       LogicVRegister dst,
2673                       const LogicVRegister& src,
2674                       int shift);
2675   LogicVRegister srsra(VectorFormat vform,
2676                        LogicVRegister dst,
2677                        const LogicVRegister& src,
2678                        int shift);
2679   LogicVRegister ursra(VectorFormat vform,
2680                        LogicVRegister dst,
2681                        const LogicVRegister& src,
2682                        int shift);
2683   LogicVRegister suqadd(VectorFormat vform,
2684                         LogicVRegister dst,
2685                         const LogicVRegister& src);
2686   LogicVRegister usqadd(VectorFormat vform,
2687                         LogicVRegister dst,
2688                         const LogicVRegister& src);
2689   LogicVRegister sqshl(VectorFormat vform,
2690                        LogicVRegister dst,
2691                        const LogicVRegister& src,
2692                        int shift);
2693   LogicVRegister uqshl(VectorFormat vform,
2694                        LogicVRegister dst,
2695                        const LogicVRegister& src,
2696                        int shift);
2697   LogicVRegister sqshlu(VectorFormat vform,
2698                         LogicVRegister dst,
2699                         const LogicVRegister& src,
2700                         int shift);
2701   LogicVRegister abs(VectorFormat vform,
2702                      LogicVRegister dst,
2703                      const LogicVRegister& src);
2704   LogicVRegister neg(VectorFormat vform,
2705                      LogicVRegister dst,
2706                      const LogicVRegister& src);
2707   LogicVRegister extractnarrow(VectorFormat vform,
2708                                LogicVRegister dst,
2709                                bool dstIsSigned,
2710                                const LogicVRegister& src,
2711                                bool srcIsSigned);
2712   LogicVRegister xtn(VectorFormat vform,
2713                      LogicVRegister dst,
2714                      const LogicVRegister& src);
2715   LogicVRegister sqxtn(VectorFormat vform,
2716                        LogicVRegister dst,
2717                        const LogicVRegister& src);
2718   LogicVRegister uqxtn(VectorFormat vform,
2719                        LogicVRegister dst,
2720                        const LogicVRegister& src);
2721   LogicVRegister sqxtun(VectorFormat vform,
2722                         LogicVRegister dst,
2723                         const LogicVRegister& src);
2724   LogicVRegister absdiff(VectorFormat vform,
2725                          LogicVRegister dst,
2726                          const LogicVRegister& src1,
2727                          const LogicVRegister& src2,
2728                          bool issigned);
2729   LogicVRegister saba(VectorFormat vform,
2730                       LogicVRegister dst,
2731                       const LogicVRegister& src1,
2732                       const LogicVRegister& src2);
2733   LogicVRegister uaba(VectorFormat vform,
2734                       LogicVRegister dst,
2735                       const LogicVRegister& src1,
2736                       const LogicVRegister& src2);
2737   LogicVRegister shrn(VectorFormat vform,
2738                       LogicVRegister dst,
2739                       const LogicVRegister& src,
2740                       int shift);
2741   LogicVRegister shrn2(VectorFormat vform,
2742                        LogicVRegister dst,
2743                        const LogicVRegister& src,
2744                        int shift);
2745   LogicVRegister rshrn(VectorFormat vform,
2746                        LogicVRegister dst,
2747                        const LogicVRegister& src,
2748                        int shift);
2749   LogicVRegister rshrn2(VectorFormat vform,
2750                         LogicVRegister dst,
2751                         const LogicVRegister& src,
2752                         int shift);
2753   LogicVRegister uqshrn(VectorFormat vform,
2754                         LogicVRegister dst,
2755                         const LogicVRegister& src,
2756                         int shift);
2757   LogicVRegister uqshrn2(VectorFormat vform,
2758                          LogicVRegister dst,
2759                          const LogicVRegister& src,
2760                          int shift);
2761   LogicVRegister uqrshrn(VectorFormat vform,
2762                          LogicVRegister dst,
2763                          const LogicVRegister& src,
2764                          int shift);
2765   LogicVRegister uqrshrn2(VectorFormat vform,
2766                           LogicVRegister dst,
2767                           const LogicVRegister& src,
2768                           int shift);
2769   LogicVRegister sqshrn(VectorFormat vform,
2770                         LogicVRegister dst,
2771                         const LogicVRegister& src,
2772                         int shift);
2773   LogicVRegister sqshrn2(VectorFormat vform,
2774                          LogicVRegister dst,
2775                          const LogicVRegister& src,
2776                          int shift);
2777   LogicVRegister sqrshrn(VectorFormat vform,
2778                          LogicVRegister dst,
2779                          const LogicVRegister& src,
2780                          int shift);
2781   LogicVRegister sqrshrn2(VectorFormat vform,
2782                           LogicVRegister dst,
2783                           const LogicVRegister& src,
2784                           int shift);
2785   LogicVRegister sqshrun(VectorFormat vform,
2786                          LogicVRegister dst,
2787                          const LogicVRegister& src,
2788                          int shift);
2789   LogicVRegister sqshrun2(VectorFormat vform,
2790                           LogicVRegister dst,
2791                           const LogicVRegister& src,
2792                           int shift);
2793   LogicVRegister sqrshrun(VectorFormat vform,
2794                           LogicVRegister dst,
2795                           const LogicVRegister& src,
2796                           int shift);
2797   LogicVRegister sqrshrun2(VectorFormat vform,
2798                            LogicVRegister dst,
2799                            const LogicVRegister& src,
2800                            int shift);
2801   LogicVRegister sqrdmulh(VectorFormat vform,
2802                           LogicVRegister dst,
2803                           const LogicVRegister& src1,
2804                           const LogicVRegister& src2,
2805                           bool round = true);
2806   LogicVRegister dot(VectorFormat vform,
2807                      LogicVRegister dst,
2808                      const LogicVRegister& src1,
2809                      const LogicVRegister& src2,
2810                      bool is_signed);
2811   LogicVRegister sdot(VectorFormat vform,
2812                       LogicVRegister dst,
2813                       const LogicVRegister& src1,
2814                       const LogicVRegister& src2);
2815   LogicVRegister udot(VectorFormat vform,
2816                       LogicVRegister dst,
2817                       const LogicVRegister& src1,
2818                       const LogicVRegister& src2);
2819   LogicVRegister sqrdmlash(VectorFormat vform,
2820                            LogicVRegister dst,
2821                            const LogicVRegister& src1,
2822                            const LogicVRegister& src2,
2823                            bool round = true,
2824                            bool sub_op = false);
2825   LogicVRegister sqrdmlah(VectorFormat vform,
2826                           LogicVRegister dst,
2827                           const LogicVRegister& src1,
2828                           const LogicVRegister& src2,
2829                           bool round = true);
2830   LogicVRegister sqrdmlsh(VectorFormat vform,
2831                           LogicVRegister dst,
2832                           const LogicVRegister& src1,
2833                           const LogicVRegister& src2,
2834                           bool round = true);
2835   LogicVRegister sqdmulh(VectorFormat vform,
2836                          LogicVRegister dst,
2837                          const LogicVRegister& src1,
2838                          const LogicVRegister& src2);
2839 #define NEON_3VREG_LOGIC_LIST(V) \
2840   V(addhn)                       \
2841   V(addhn2)                      \
2842   V(raddhn)                      \
2843   V(raddhn2)                     \
2844   V(subhn)                       \
2845   V(subhn2)                      \
2846   V(rsubhn)                      \
2847   V(rsubhn2)                     \
2848   V(pmull)                       \
2849   V(pmull2)                      \
2850   V(sabal)                       \
2851   V(sabal2)                      \
2852   V(uabal)                       \
2853   V(uabal2)                      \
2854   V(sabdl)                       \
2855   V(sabdl2)                      \
2856   V(uabdl)                       \
2857   V(uabdl2)                      \
2858   V(smull)                       \
2859   V(smull2)                      \
2860   V(umull)                       \
2861   V(umull2)                      \
2862   V(smlal)                       \
2863   V(smlal2)                      \
2864   V(umlal)                       \
2865   V(umlal2)                      \
2866   V(smlsl)                       \
2867   V(smlsl2)                      \
2868   V(umlsl)                       \
2869   V(umlsl2)                      \
2870   V(sqdmlal)                     \
2871   V(sqdmlal2)                    \
2872   V(sqdmlsl)                     \
2873   V(sqdmlsl2)                    \
2874   V(sqdmull)                     \
2875   V(sqdmull2)
2876 
2877 #define DEFINE_LOGIC_FUNC(FXN)                   \
2878   LogicVRegister FXN(VectorFormat vform,         \
2879                      LogicVRegister dst,         \
2880                      const LogicVRegister& src1, \
2881                      const LogicVRegister& src2);
2882   NEON_3VREG_LOGIC_LIST(DEFINE_LOGIC_FUNC)
2883 #undef DEFINE_LOGIC_FUNC
2884 
2885 #define NEON_FP3SAME_LIST(V) \
2886   V(fadd, FPAdd, false)      \
2887   V(fsub, FPSub, true)       \
2888   V(fmul, FPMul, true)       \
2889   V(fmulx, FPMulx, true)     \
2890   V(fdiv, FPDiv, true)       \
2891   V(fmax, FPMax, false)      \
2892   V(fmin, FPMin, false)      \
2893   V(fmaxnm, FPMaxNM, false)  \
2894   V(fminnm, FPMinNM, false)
2895 
2896 #define DECLARE_NEON_FP_VECTOR_OP(FN, OP, PROCNAN) \
2897   template <typename T>                            \
2898   LogicVRegister FN(VectorFormat vform,            \
2899                     LogicVRegister dst,            \
2900                     const LogicVRegister& src1,    \
2901                     const LogicVRegister& src2);   \
2902   LogicVRegister FN(VectorFormat vform,            \
2903                     LogicVRegister dst,            \
2904                     const LogicVRegister& src1,    \
2905                     const LogicVRegister& src2);
2906   NEON_FP3SAME_LIST(DECLARE_NEON_FP_VECTOR_OP)
2907 #undef DECLARE_NEON_FP_VECTOR_OP
2908 
2909 #define NEON_FPPAIRWISE_LIST(V) \
2910   V(faddp, fadd, FPAdd)         \
2911   V(fmaxp, fmax, FPMax)         \
2912   V(fmaxnmp, fmaxnm, FPMaxNM)   \
2913   V(fminp, fmin, FPMin)         \
2914   V(fminnmp, fminnm, FPMinNM)
2915 
2916 #define DECLARE_NEON_FP_PAIR_OP(FNP, FN, OP)      \
2917   LogicVRegister FNP(VectorFormat vform,          \
2918                      LogicVRegister dst,          \
2919                      const LogicVRegister& src1,  \
2920                      const LogicVRegister& src2); \
2921   LogicVRegister FNP(VectorFormat vform,          \
2922                      LogicVRegister dst,          \
2923                      const LogicVRegister& src);
2924   NEON_FPPAIRWISE_LIST(DECLARE_NEON_FP_PAIR_OP)
2925 #undef DECLARE_NEON_FP_PAIR_OP
2926 
2927   enum FrintMode {
2928     kFrintToInteger = 0,
2929     kFrintToInt32 = 32,
2930     kFrintToInt64 = 64
2931   };
2932 
2933   template <typename T>
2934   LogicVRegister frecps(VectorFormat vform,
2935                         LogicVRegister dst,
2936                         const LogicVRegister& src1,
2937                         const LogicVRegister& src2);
2938   LogicVRegister frecps(VectorFormat vform,
2939                         LogicVRegister dst,
2940                         const LogicVRegister& src1,
2941                         const LogicVRegister& src2);
2942   template <typename T>
2943   LogicVRegister frsqrts(VectorFormat vform,
2944                          LogicVRegister dst,
2945                          const LogicVRegister& src1,
2946                          const LogicVRegister& src2);
2947   LogicVRegister frsqrts(VectorFormat vform,
2948                          LogicVRegister dst,
2949                          const LogicVRegister& src1,
2950                          const LogicVRegister& src2);
2951   template <typename T>
2952   LogicVRegister fmla(VectorFormat vform,
2953                       LogicVRegister dst,
2954                       const LogicVRegister& src1,
2955                       const LogicVRegister& src2);
2956   LogicVRegister fmla(VectorFormat vform,
2957                       LogicVRegister dst,
2958                       const LogicVRegister& src1,
2959                       const LogicVRegister& src2);
2960   template <typename T>
2961   LogicVRegister fmls(VectorFormat vform,
2962                       LogicVRegister dst,
2963                       const LogicVRegister& src1,
2964                       const LogicVRegister& src2);
2965   LogicVRegister fmls(VectorFormat vform,
2966                       LogicVRegister dst,
2967                       const LogicVRegister& src1,
2968                       const LogicVRegister& src2);
2969   LogicVRegister fnmul(VectorFormat vform,
2970                        LogicVRegister dst,
2971                        const LogicVRegister& src1,
2972                        const LogicVRegister& src2);
2973 
2974   LogicVRegister fmlal(VectorFormat vform,
2975                        LogicVRegister dst,
2976                        const LogicVRegister& src1,
2977                        const LogicVRegister& src2);
2978   LogicVRegister fmlal2(VectorFormat vform,
2979                         LogicVRegister dst,
2980                         const LogicVRegister& src1,
2981                         const LogicVRegister& src2);
2982   LogicVRegister fmlsl(VectorFormat vform,
2983                        LogicVRegister dst,
2984                        const LogicVRegister& src1,
2985                        const LogicVRegister& src2);
2986   LogicVRegister fmlsl2(VectorFormat vform,
2987                         LogicVRegister dst,
2988                         const LogicVRegister& src1,
2989                         const LogicVRegister& src2);
2990 
2991   template <typename T>
2992   LogicVRegister fcmp(VectorFormat vform,
2993                       LogicVRegister dst,
2994                       const LogicVRegister& src1,
2995                       const LogicVRegister& src2,
2996                       Condition cond);
2997   LogicVRegister fcmp(VectorFormat vform,
2998                       LogicVRegister dst,
2999                       const LogicVRegister& src1,
3000                       const LogicVRegister& src2,
3001                       Condition cond);
3002   LogicVRegister fabscmp(VectorFormat vform,
3003                          LogicVRegister dst,
3004                          const LogicVRegister& src1,
3005                          const LogicVRegister& src2,
3006                          Condition cond);
3007   LogicVRegister fcmp_zero(VectorFormat vform,
3008                            LogicVRegister dst,
3009                            const LogicVRegister& src,
3010                            Condition cond);
3011 
3012   template <typename T>
3013   LogicVRegister fneg(VectorFormat vform,
3014                       LogicVRegister dst,
3015                       const LogicVRegister& src);
3016   LogicVRegister fneg(VectorFormat vform,
3017                       LogicVRegister dst,
3018                       const LogicVRegister& src);
3019   template <typename T>
3020   LogicVRegister frecpx(VectorFormat vform,
3021                         LogicVRegister dst,
3022                         const LogicVRegister& src);
3023   LogicVRegister frecpx(VectorFormat vform,
3024                         LogicVRegister dst,
3025                         const LogicVRegister& src);
3026   template <typename T>
3027   LogicVRegister fabs_(VectorFormat vform,
3028                        LogicVRegister dst,
3029                        const LogicVRegister& src);
3030   LogicVRegister fabs_(VectorFormat vform,
3031                        LogicVRegister dst,
3032                        const LogicVRegister& src);
3033   LogicVRegister fabd(VectorFormat vform,
3034                       LogicVRegister dst,
3035                       const LogicVRegister& src1,
3036                       const LogicVRegister& src2);
3037 
3038   LogicVRegister frint(VectorFormat vform,
3039                        LogicVRegister dst,
3040                        const LogicVRegister& src,
3041                        FPRounding rounding_mode,
3042                        bool inexact_exception = false,
3043                        FrintMode frint_mode = kFrintToInteger);
3044   LogicVRegister fcvts(VectorFormat vform,
3045                        LogicVRegister dst,
3046                        const LogicVRegister& src,
3047                        FPRounding rounding_mode,
3048                        int fbits = 0);
3049   LogicVRegister fcvtu(VectorFormat vform,
3050                        LogicVRegister dst,
3051                        const LogicVRegister& src,
3052                        FPRounding rounding_mode,
3053                        int fbits = 0);
3054   LogicVRegister fcvtl(VectorFormat vform,
3055                        LogicVRegister dst,
3056                        const LogicVRegister& src);
3057   LogicVRegister fcvtl2(VectorFormat vform,
3058                         LogicVRegister dst,
3059                         const LogicVRegister& src);
3060   LogicVRegister fcvtn(VectorFormat vform,
3061                        LogicVRegister dst,
3062                        const LogicVRegister& src);
3063   LogicVRegister fcvtn2(VectorFormat vform,
3064                         LogicVRegister dst,
3065                         const LogicVRegister& src);
3066   LogicVRegister fcvtxn(VectorFormat vform,
3067                         LogicVRegister dst,
3068                         const LogicVRegister& src);
3069   LogicVRegister fcvtxn2(VectorFormat vform,
3070                          LogicVRegister dst,
3071                          const LogicVRegister& src);
3072   LogicVRegister fsqrt(VectorFormat vform,
3073                        LogicVRegister dst,
3074                        const LogicVRegister& src);
3075   LogicVRegister frsqrte(VectorFormat vform,
3076                          LogicVRegister dst,
3077                          const LogicVRegister& src);
3078   LogicVRegister frecpe(VectorFormat vform,
3079                         LogicVRegister dst,
3080                         const LogicVRegister& src,
3081                         FPRounding rounding);
3082   LogicVRegister ursqrte(VectorFormat vform,
3083                          LogicVRegister dst,
3084                          const LogicVRegister& src);
3085   LogicVRegister urecpe(VectorFormat vform,
3086                         LogicVRegister dst,
3087                         const LogicVRegister& src);
3088 
3089   template <typename T>
3090   struct TFPMinMaxOp {
3091     typedef T (Simulator::*type)(T a, T b);
3092   };
3093 
3094   template <typename T>
3095   LogicVRegister fminmaxv(VectorFormat vform,
3096                           LogicVRegister dst,
3097                           const LogicVRegister& src,
3098                           typename TFPMinMaxOp<T>::type Op);
3099 
3100   LogicVRegister fminv(VectorFormat vform,
3101                        LogicVRegister dst,
3102                        const LogicVRegister& src);
3103   LogicVRegister fmaxv(VectorFormat vform,
3104                        LogicVRegister dst,
3105                        const LogicVRegister& src);
3106   LogicVRegister fminnmv(VectorFormat vform,
3107                          LogicVRegister dst,
3108                          const LogicVRegister& src);
3109   LogicVRegister fmaxnmv(VectorFormat vform,
3110                          LogicVRegister dst,
3111                          const LogicVRegister& src);
3112 
3113   static const uint32_t CRC32_POLY = 0x04C11DB7;
3114   static const uint32_t CRC32C_POLY = 0x1EDC6F41;
3115   uint32_t Poly32Mod2(unsigned n, uint64_t data, uint32_t poly);
3116   template <typename T>
3117   uint32_t Crc32Checksum(uint32_t acc, T val, uint32_t poly);
3118   uint32_t Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly);
3119 
3120   void SysOp_W(int op, int64_t val);
3121 
3122   template <typename T>
3123   T FPRecipSqrtEstimate(T op);
3124   template <typename T>
3125   T FPRecipEstimate(T op, FPRounding rounding);
3126   template <typename T, typename R>
3127   R FPToFixed(T op, int fbits, bool is_signed, FPRounding rounding);
3128 
3129   void FPCompare(double val0, double val1, FPTrapFlags trap);
3130   double FPRoundInt(double value, FPRounding round_mode);
3131   double FPRoundInt(double value, FPRounding round_mode, FrintMode frint_mode);
3132   double FPRoundIntCommon(double value, FPRounding round_mode);
3133   double recip_sqrt_estimate(double a);
3134   double recip_estimate(double a);
3135   double FPRecipSqrtEstimate(double a);
3136   double FPRecipEstimate(double a);
3137   double FixedToDouble(int64_t src, int fbits, FPRounding round_mode);
3138   double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode);
3139   float FixedToFloat(int64_t src, int fbits, FPRounding round_mode);
3140   float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode);
3141   ::vixl::internal::SimFloat16 FixedToFloat16(int64_t src,
3142                                               int fbits,
3143                                               FPRounding round_mode);
3144   ::vixl::internal::SimFloat16 UFixedToFloat16(uint64_t src,
3145                                                int fbits,
3146                                                FPRounding round_mode);
3147   int16_t FPToInt16(double value, FPRounding rmode);
3148   int32_t FPToInt32(double value, FPRounding rmode);
3149   int64_t FPToInt64(double value, FPRounding rmode);
3150   uint16_t FPToUInt16(double value, FPRounding rmode);
3151   uint32_t FPToUInt32(double value, FPRounding rmode);
3152   uint64_t FPToUInt64(double value, FPRounding rmode);
3153   int32_t FPToFixedJS(double value);
3154 
3155   template <typename T>
3156   T FPAdd(T op1, T op2);
3157 
3158   template <typename T>
3159   T FPNeg(T op);
3160 
3161   template <typename T>
3162   T FPDiv(T op1, T op2);
3163 
3164   template <typename T>
3165   T FPMax(T a, T b);
3166 
3167   template <typename T>
3168   T FPMaxNM(T a, T b);
3169 
3170   template <typename T>
3171   T FPMin(T a, T b);
3172 
3173   template <typename T>
3174   T FPMinNM(T a, T b);
3175 
3176   template <typename T>
3177   T FPMul(T op1, T op2);
3178 
3179   template <typename T>
3180   T FPMulx(T op1, T op2);
3181 
3182   template <typename T>
3183   T FPMulAdd(T a, T op1, T op2);
3184 
3185   template <typename T>
3186   T FPSqrt(T op);
3187 
3188   template <typename T>
3189   T FPSub(T op1, T op2);
3190 
3191   template <typename T>
3192   T FPRecipStepFused(T op1, T op2);
3193 
3194   template <typename T>
3195   T FPRSqrtStepFused(T op1, T op2);
3196 
3197   // This doesn't do anything at the moment. We'll need it if we want support
3198   // for cumulative exception bits or floating-point exceptions.
3199   void FPProcessException() {}
3200 
3201   bool FPProcessNaNs(const Instruction* instr);
3202 
3203   // Pseudo Printf instruction
3204   void DoPrintf(const Instruction* instr);
3205 
3206   // Pseudo-instructions to configure CPU features dynamically.
3207   void DoConfigureCPUFeatures(const Instruction* instr);
3208 
3209   void DoSaveCPUFeatures(const Instruction* instr);
3210   void DoRestoreCPUFeatures(const Instruction* instr);
3211 
3212   // Simulate a runtime call.
3213   void DoRuntimeCall(const Instruction* instr);
3214 
3215   // Processor state ---------------------------------------
3216 
3217   // Simulated monitors for exclusive access instructions.
3218   SimExclusiveLocalMonitor local_monitor_;
3219   SimExclusiveGlobalMonitor global_monitor_;
3220 
3221   // Output stream.
3222   FILE* stream_;
3223   PrintDisassembler* print_disasm_;
3224 
3225   // Instruction statistics instrumentation.
3226   Instrument* instrumentation_;
3227 
3228   // General purpose registers. Register 31 is the stack pointer.
3229   SimRegister registers_[kNumberOfRegisters];
3230 
3231   // Vector registers
3232   SimVRegister vregisters_[kNumberOfVRegisters];
3233 
3234   // Program Status Register.
3235   // bits[31, 27]: Condition flags N, Z, C, and V.
3236   //               (Negative, Zero, Carry, Overflow)
3237   SimSystemRegister nzcv_;
3238 
3239   // Floating-Point Control Register
3240   SimSystemRegister fpcr_;
3241 
3242   // Only a subset of FPCR features are supported by the simulator. This helper
3243   // checks that the FPCR settings are supported.
3244   //
3245   // This is checked when floating-point instructions are executed, not when
3246   // FPCR is set. This allows generated code to modify FPCR for external
3247   // functions, or to save and restore it when entering and leaving generated
3248   // code.
3249   void AssertSupportedFPCR() {
3250     // No flush-to-zero support.
3251     VIXL_ASSERT(ReadFpcr().GetFZ() == 0);
3252     // Ties-to-even rounding only.
3253     VIXL_ASSERT(ReadFpcr().GetRMode() == FPTieEven);
3254     // No alternative half-precision support.
3255     VIXL_ASSERT(ReadFpcr().GetAHP() == 0);
3256   }
3257 
3258   static int CalcNFlag(uint64_t result, unsigned reg_size) {
3259     return (result >> (reg_size - 1)) & 1;
3260   }
3261 
3262   static int CalcZFlag(uint64_t result) { return (result == 0) ? 1 : 0; }
3263 
3264   static const uint32_t kConditionFlagsMask = 0xf0000000;
3265 
3266   // Stack
3267   byte* stack_;
3268   static const int stack_protection_size_ = 256;
3269   // 2 KB stack.
3270   static const int stack_size_ = 2 * 1024 + 2 * stack_protection_size_;
3271   byte* stack_limit_;
3272 
3273   Decoder* decoder_;
3274   // Indicates if the pc has been modified by the instruction and should not be
3275   // automatically incremented.
3276   bool pc_modified_;
3277   const Instruction* pc_;
3278 
3279   // Branch type register, used for branch target identification.
3280   BType btype_;
3281 
3282   // Next value of branch type register after the current instruction has been
3283   // decoded.
3284   BType next_btype_;
3285 
3286   // Global flag for enabling guarded pages.
3287   // TODO: implement guarding at page granularity, rather than globally.
3288   bool guard_pages_;
3289 
3290   static const char* xreg_names[];
3291   static const char* wreg_names[];
3292   static const char* hreg_names[];
3293   static const char* sreg_names[];
3294   static const char* dreg_names[];
3295   static const char* vreg_names[];
3296 
3297  private:
3298   static const PACKey kPACKeyIA;
3299   static const PACKey kPACKeyIB;
3300   static const PACKey kPACKeyDA;
3301   static const PACKey kPACKeyDB;
3302   static const PACKey kPACKeyGA;
3303 
3304   template <typename T>
3305   static T FPDefaultNaN();
3306 
3307   // Standard NaN processing.
3308   template <typename T>
3309   T FPProcessNaN(T op) {
3310     VIXL_ASSERT(IsNaN(op));
3311     if (IsSignallingNaN(op)) {
3312       FPProcessException();
3313     }
3314     return (ReadDN() == kUseDefaultNaN) ? FPDefaultNaN<T>() : ToQuietNaN(op);
3315   }
3316 
3317   template <typename T>
3318   T FPProcessNaNs(T op1, T op2) {
3319     if (IsSignallingNaN(op1)) {
3320       return FPProcessNaN(op1);
3321     } else if (IsSignallingNaN(op2)) {
3322       return FPProcessNaN(op2);
3323     } else if (IsNaN(op1)) {
3324       VIXL_ASSERT(IsQuietNaN(op1));
3325       return FPProcessNaN(op1);
3326     } else if (IsNaN(op2)) {
3327       VIXL_ASSERT(IsQuietNaN(op2));
3328       return FPProcessNaN(op2);
3329     } else {
3330       return 0.0;
3331     }
3332   }
3333 
3334   template <typename T>
3335   T FPProcessNaNs3(T op1, T op2, T op3) {
3336     if (IsSignallingNaN(op1)) {
3337       return FPProcessNaN(op1);
3338     } else if (IsSignallingNaN(op2)) {
3339       return FPProcessNaN(op2);
3340     } else if (IsSignallingNaN(op3)) {
3341       return FPProcessNaN(op3);
3342     } else if (IsNaN(op1)) {
3343       VIXL_ASSERT(IsQuietNaN(op1));
3344       return FPProcessNaN(op1);
3345     } else if (IsNaN(op2)) {
3346       VIXL_ASSERT(IsQuietNaN(op2));
3347       return FPProcessNaN(op2);
3348     } else if (IsNaN(op3)) {
3349       VIXL_ASSERT(IsQuietNaN(op3));
3350       return FPProcessNaN(op3);
3351     } else {
3352       return 0.0;
3353     }
3354   }
3355 
3356   bool coloured_trace_;
3357 
3358   // A set of TraceParameters flags.
3359   int trace_parameters_;
3360 
3361   // Indicates whether the instruction instrumentation is active.
3362   bool instruction_stats_;
3363 
3364   // Indicates whether the exclusive-access warning has been printed.
3365   bool print_exclusive_access_warning_;
3366   void PrintExclusiveAccessWarning();
3367 
3368   CPUFeaturesAuditor cpu_features_auditor_;
3369   std::vector<CPUFeatures> saved_cpu_features_;
3370 
3371   // The simulated state of RNDR and RNDRRS for generating a random number.
3372   uint16_t rndr_state_[3];
3373 };
3374 
3375 #if defined(VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT) && __cplusplus < 201402L
3376 // Base case of the recursive template used to emulate C++14
3377 // `std::index_sequence`.
3378 template <size_t... I>
3379 struct Simulator::emulated_make_index_sequence_helper<0, I...>
3380     : Simulator::emulated_index_sequence<I...> {};
3381 #endif
3382 
3383 }  // namespace aarch64
3384 }  // namespace vixl
3385 
3386 #endif  // VIXL_INCLUDE_SIMULATOR_AARCH64
3387 
3388 #endif  // VIXL_AARCH64_SIMULATOR_AARCH64_H_
3389