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 65namespace vixl { 66namespace aarch64 { 67 68class Simulator; 69struct RuntimeCallStructHelper; 70 71class SimStack { 72 public: 73 SimStack() {} 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. 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. 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. 88 void SetUsableSize(size_t size) { usable_size_ = size; } 89 90 // Set the minimum alignment for the stack parameters. 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 112 char* GetBase() const { return base_; } 113 char* GetLimit() const { return limit_; } 114 115 template <typename T> 116 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. 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. 169inline int GetAllocationTagFromAddress(uint64_t address) { 170 return static_cast<int>(ExtractUnsignedBitfield64(59, 56, address)); 171} 172 173template <typename T> 174T 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. 185using InterceptionCallback = std::function<void(uint64_t)>; 186 187class MetaDataDepot { 188 public: 189 class MetaDataMTE { 190 public: 191 explicit MetaDataMTE(int tag) : tag_(tag) {} 192 193 int GetTag() const { return tag_; } 194 void SetTag(int tag) { 195 VIXL_ASSERT(IsUint4(tag)); 196 tag_ = tag; 197 } 198 199 static bool IsActive() { return is_active; } 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> 211 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> 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> 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> 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> 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 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 { 276 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 { 287 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> 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. 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 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. 347class Memory { 348 public: 349 explicit Memory(SimStack::Allocated stack) : stack_(std::move(stack)) { 350 metadata_depot_ = nullptr; 351 } 352 353 const SimStack::Allocated& GetStack() { return stack_; } 354 355 template <typename A> 356 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> 369 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> 386 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> 401 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> 417 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> 433 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 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). 459template <unsigned kMaxSizeInBits> 460class SimRegisterBase { 461 public: 462 static const unsigned kMaxSizeInBytes = kMaxSizeInBits / kBitsPerByte; 463 VIXL_STATIC_ASSERT((kMaxSizeInBytes * kBitsPerByte) == kMaxSizeInBits); 464 465 SimRegisterBase() : size_in_bytes_(kMaxSizeInBytes) { Clear(); } 466 467 unsigned GetSizeInBits() const { return size_in_bytes_ * kBitsPerByte; } 468 unsigned GetSizeInBytes() const { return size_in_bytes_; } 469 470 void SetSizeInBytes(unsigned size_in_bytes) { 471 VIXL_ASSERT(size_in_bytes <= kMaxSizeInBytes); 472 size_in_bytes_ = size_in_bytes; 473 } 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> 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 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> 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> 510 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> 517 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. 529 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. 536 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.) 541 bool WrittenSinceLastLog() const { return written_since_last_log_; } 542 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 553 void NotifyRegisterWrite() { written_since_last_log_ = true; } 554 555 private: 556 template <typename T> 557 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> 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 574 void ReadLane(vixl::internal::SimFloat16* dst, int lane) const { 575 uint16_t rawbits; 576 ReadLane(&rawbits, lane); 577 *dst = RawbitsToFloat16(rawbits); 578 } 579 580 void WriteLane(vixl::internal::SimFloat16 src, int lane) { 581 WriteLane(Float16ToRawbits(src), lane); 582 } 583}; 584 585typedef SimRegisterBase<kXRegSize> SimRegister; // r0-r31 586typedef SimRegisterBase<kPRegMaxSize> SimPRegister; // p0-p15 587// FFR has the same format as a predicate register. 588typedef SimPRegister SimFFRRegister; 589 590// v0-v31 and z0-z31 591class SimVRegister : public SimRegisterBase<kZRegMaxSize> { 592 public: 593 SimVRegister() : SimRegisterBase<kZRegMaxSize>(), accessed_as_z_(false) {} 594 595 void NotifyAccessAsZ() { accessed_as_z_ = true; } 596 597 void NotifyRegisterLogged() { 598 SimRegisterBase<kZRegMaxSize>::NotifyRegisterLogged(); 599 accessed_as_z_ = false; 600 } 601 602 bool AccessedAsZSinceLastLog() const { return accessed_as_z_; } 603 604 private: 605 bool accessed_as_z_; 606}; 607 608// Representation of a SVE predicate register. 609class LogicPRegister { 610 public: 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. 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 630 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. 640 int GetChunkCount() const { 641 VIXL_ASSERT((register_.GetSizeInBytes() % sizeof(ChunkType)) == 0); 642 return register_.GetSizeInBytes() / sizeof(ChunkType); 643 } 644 645 ChunkType GetChunk(int lane) const { return GetActiveMask<ChunkType>(lane); } 646 647 void SetChunk(int lane, ChunkType new_value) { 648 SetActiveMask(lane, new_value); 649 } 650 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> 662 T GetActiveMask(int lane) const { 663 return register_.GetLane<T>(lane); 664 } 665 666 template <typename T> 667 void SetActiveMask(int lane, T new_value) { 668 register_.Insert<T>(lane, new_value); 669 } 670 671 void Clear() { register_.Clear(); } 672 673 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. 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. 708class LogicVRegister { 709 public: 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 721 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 744 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 767 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 774 uint64_t UintLeftJustified(VectorFormat vform, int index) const { 775 return Uint(vform, index) << (64 - LaneSizeInBitsFromFormat(vform)); 776 } 777 778 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 785 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 806 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 813 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 834 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> 842 T Float(int index) const { 843 return register_.GetLane<T>(index); 844 } 845 846 template <typename T> 847 void SetFloat(int index, T value) const { 848 register_.Insert(index, value); 849 } 850 851 template <typename T> 852 void SetFloat(VectorFormat vform, int index, T value) const { 853 if (IsSVEFormat(vform)) register_.NotifyAccessAsZ(); 854 register_.Insert(index, value); 855 } 856 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. 861 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. 885 Saturation GetSignedSaturation(int index) { 886 return static_cast<Saturation>(saturated_[index] & kSignedSatMask); 887 } 888 889 Saturation GetUnsignedSaturation(int index) { 890 return static_cast<Saturation>(saturated_[index] & kUnsignedSatMask); 891 } 892 893 // Setters for saturation state. 894 void ClearSat(int index) { saturated_[index] = kNotSaturated; } 895 896 void SetSignedSat(int index, bool positive) { 897 SetSatFlag(index, positive ? kSignedSatPositive : kSignedSatNegative); 898 } 899 900 void SetUnsignedSat(int index, bool positive) { 901 SetSatFlag(index, positive ? kUnsignedSatPositive : kUnsignedSatNegative); 902 } 903 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. 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 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. 936 bool GetRounding(int index) { return round_[index]; } 937 938 // Setter for rounding state. 939 void SetRounding(int index, bool round) { round_[index] = round; } 940 941 // Round lanes of a vector based on rounding state. 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. 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. 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 984 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. 1012class LogicSVEAddressVector { 1013 public: 1014 // scalar-plus-scalar 1015 // scalar-plus-immediate 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. 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. 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 1057 bool HasMsize() const { 1058 return msize_in_bytes_log2_ != kUnknownMsizeInBytesLog2; 1059 } 1060 1061 int GetMsizeInBytesLog2() const { 1062 VIXL_ASSERT(HasMsize()); 1063 return msize_in_bytes_log2_; 1064 } 1065 int GetMsizeInBitsLog2() const { 1066 return GetMsizeInBytesLog2() + kBitsPerByteLog2; 1067 } 1068 1069 int GetMsizeInBytes() const { return 1 << GetMsizeInBytesLog2(); } 1070 int GetMsizeInBits() const { return 1 << GetMsizeInBitsLog2(); } 1071 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 1078 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. 1083 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); 1112class 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 1171class 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. 1219class SimExclusiveGlobalMonitor { 1220 public: 1221 SimExclusiveGlobalMonitor() : kPassProbability(8), seed_(0x87654321) {} 1222 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 1238class Debugger; 1239 1240 1241class 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 1259 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> 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 { 1288 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...> { 1309 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. 1331 bool IsSimulationFinished() const { return pc_ == kEndOfSimAddress; } 1332 1333 const Instruction* ReadPc() const { return pc_; } 1334 VIXL_DEPRECATED("ReadPc", const Instruction* pc() const) { return ReadPc(); } 1335 1336 enum BranchLogMode { LogBranches, NoBranchLog }; 1337 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 1348 void IncrementPc() { 1349 if (!pc_modified_) { 1350 pc_ = pc_->GetNextInstruction(); 1351 } 1352 } 1353 VIXL_DEPRECATED("IncrementPc", void increment_pc()) { IncrementPc(); } 1354 1355 BType ReadBType() const { return btype_; } 1356 void WriteNextBType(BType btype) { next_btype_ = btype; } 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 1365 bool PcIsInGuardedPage() const { return guard_pages_; } 1366 void SetGuardedPages(bool guard_pages) { guard_pages_ = guard_pages; } 1367 1368 const Instruction* GetLastExecutedInstruction() const { return last_instr_; } 1369 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> 1507 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`. 5295template <size_t... I> 5296struct Simulator::emulated_make_index_sequence_helper<0, I...> 5297 : Simulator::emulated_index_sequence<I...> {}; 5298#endif 5299 5300template <typename R, typename... P> 5301void 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