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