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