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