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