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 <vector>
31
32 #include "../globals-vixl.h"
33 #include "../utils-vixl.h"
34
35 #include "cpu-features.h"
36 #include "abi-aarch64.h"
37 #include "cpu-features-auditor-aarch64.h"
38 #include "disasm-aarch64.h"
39 #include "instructions-aarch64.h"
40 #include "instrument-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 // Representation of memory, with typed getters and setters for access.
59 class Memory {
60 public:
61 template <typename T>
AddressUntag(T address)62 static T AddressUntag(T address) {
63 // Cast the address using a C-style cast. A reinterpret_cast would be
64 // appropriate, but it can't cast one integral type to another.
65 uint64_t bits = (uint64_t)address;
66 return (T)(bits & ~kAddressTagMask);
67 }
68
69 template <typename T, typename A>
Read(A address)70 static T Read(A address) {
71 T value;
72 address = AddressUntag(address);
73 VIXL_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
74 (sizeof(value) == 4) || (sizeof(value) == 8) ||
75 (sizeof(value) == 16));
76 memcpy(&value, reinterpret_cast<const char*>(address), sizeof(value));
77 return value;
78 }
79
80 template <typename T, typename A>
Write(A address,T value)81 static void Write(A address, T value) {
82 address = AddressUntag(address);
83 VIXL_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
84 (sizeof(value) == 4) || (sizeof(value) == 8) ||
85 (sizeof(value) == 16));
86 memcpy(reinterpret_cast<char*>(address), &value, sizeof(value));
87 }
88 };
89
90 // Represent a register (r0-r31, v0-v31).
91 template <int kSizeInBytes>
92 class SimRegisterBase {
93 public:
SimRegisterBase()94 SimRegisterBase() : written_since_last_log_(false) {}
95
96 // Write the specified value. The value is zero-extended if necessary.
97 template <typename T>
Write(T new_value)98 void Write(T new_value) {
99 if (sizeof(new_value) < kSizeInBytes) {
100 // All AArch64 registers are zero-extending.
101 memset(value_ + sizeof(new_value), 0, kSizeInBytes - sizeof(new_value));
102 }
103 WriteLane(new_value, 0);
104 NotifyRegisterWrite();
105 }
106 template <typename T>
Set(T new_value)107 VIXL_DEPRECATED("Write", void Set(T new_value)) {
108 Write(new_value);
109 }
110
111 // Insert a typed value into a register, leaving the rest of the register
112 // unchanged. The lane parameter indicates where in the register the value
113 // should be inserted, in the range [ 0, sizeof(value_) / sizeof(T) ), where
114 // 0 represents the least significant bits.
115 template <typename T>
Insert(int lane,T new_value)116 void Insert(int lane, T new_value) {
117 WriteLane(new_value, lane);
118 NotifyRegisterWrite();
119 }
120
121 // Get the value as the specified type. The value is truncated if necessary.
122 template <typename T>
Get()123 T Get() const {
124 return GetLane<T>(0);
125 }
126
127 // Get the lane value as the specified type. The value is truncated if
128 // necessary.
129 template <typename T>
GetLane(int lane)130 T GetLane(int lane) const {
131 T result;
132 ReadLane(&result, lane);
133 return result;
134 }
135 template <typename T>
136 VIXL_DEPRECATED("GetLane", T Get(int lane) const) {
137 return GetLane(lane);
138 }
139
140 // TODO: Make this return a map of updated bytes, so that we can highlight
141 // updated lanes for load-and-insert. (That never happens for scalar code, but
142 // NEON has some instructions that can update individual lanes.)
WrittenSinceLastLog()143 bool WrittenSinceLastLog() const { return written_since_last_log_; }
144
NotifyRegisterLogged()145 void NotifyRegisterLogged() { written_since_last_log_ = false; }
146
147 protected:
148 uint8_t value_[kSizeInBytes];
149
150 // Helpers to aid with register tracing.
151 bool written_since_last_log_;
152
NotifyRegisterWrite()153 void NotifyRegisterWrite() { written_since_last_log_ = true; }
154
155 private:
156 template <typename T>
ReadLane(T * dst,int lane)157 void ReadLane(T* dst, int lane) const {
158 VIXL_ASSERT(lane >= 0);
159 VIXL_ASSERT((sizeof(*dst) + (lane * sizeof(*dst))) <= kSizeInBytes);
160 memcpy(dst, &value_[lane * sizeof(*dst)], sizeof(*dst));
161 }
162
163 template <typename T>
WriteLane(T src,int lane)164 void WriteLane(T src, int lane) {
165 VIXL_ASSERT(lane >= 0);
166 VIXL_ASSERT((sizeof(src) + (lane * sizeof(src))) <= kSizeInBytes);
167 memcpy(&value_[lane * sizeof(src)], &src, sizeof(src));
168 }
169 };
170 typedef SimRegisterBase<kXRegSizeInBytes> SimRegister; // r0-r31
171 typedef SimRegisterBase<kQRegSizeInBytes> SimVRegister; // v0-v31
172
173 // The default ReadLane and WriteLane methods assume what we are copying is
174 // "trivially copyable" by using memcpy. We have to provide alternative
175 // implementations for SimFloat16 which cannot be copied this way.
176
177 template <>
178 template <>
ReadLane(vixl::internal::SimFloat16 * dst,int lane)179 inline void SimVRegister::ReadLane(vixl::internal::SimFloat16* dst,
180 int lane) const {
181 uint16_t rawbits;
182 ReadLane(&rawbits, lane);
183 *dst = RawbitsToFloat16(rawbits);
184 }
185
186 template <>
187 template <>
WriteLane(vixl::internal::SimFloat16 src,int lane)188 inline void SimVRegister::WriteLane(vixl::internal::SimFloat16 src, int lane) {
189 WriteLane(Float16ToRawbits(src), lane);
190 }
191
192 // Representation of a vector register, with typed getters and setters for lanes
193 // and additional information to represent lane state.
194 class LogicVRegister {
195 public:
LogicVRegister(SimVRegister & other)196 inline LogicVRegister(
197 SimVRegister& other) // NOLINT(runtime/references)(runtime/explicit)
198 : register_(other) {
199 for (size_t i = 0; i < ArrayLength(saturated_); i++) {
200 saturated_[i] = kNotSaturated;
201 }
202 for (size_t i = 0; i < ArrayLength(round_); i++) {
203 round_[i] = 0;
204 }
205 }
206
Int(VectorFormat vform,int index)207 int64_t Int(VectorFormat vform, int index) const {
208 int64_t element;
209 switch (LaneSizeInBitsFromFormat(vform)) {
210 case 8:
211 element = register_.GetLane<int8_t>(index);
212 break;
213 case 16:
214 element = register_.GetLane<int16_t>(index);
215 break;
216 case 32:
217 element = register_.GetLane<int32_t>(index);
218 break;
219 case 64:
220 element = register_.GetLane<int64_t>(index);
221 break;
222 default:
223 VIXL_UNREACHABLE();
224 return 0;
225 }
226 return element;
227 }
228
Uint(VectorFormat vform,int index)229 uint64_t Uint(VectorFormat vform, int index) const {
230 uint64_t element;
231 switch (LaneSizeInBitsFromFormat(vform)) {
232 case 8:
233 element = register_.GetLane<uint8_t>(index);
234 break;
235 case 16:
236 element = register_.GetLane<uint16_t>(index);
237 break;
238 case 32:
239 element = register_.GetLane<uint32_t>(index);
240 break;
241 case 64:
242 element = register_.GetLane<uint64_t>(index);
243 break;
244 default:
245 VIXL_UNREACHABLE();
246 return 0;
247 }
248 return element;
249 }
250
UintLeftJustified(VectorFormat vform,int index)251 uint64_t UintLeftJustified(VectorFormat vform, int index) const {
252 return Uint(vform, index) << (64 - LaneSizeInBitsFromFormat(vform));
253 }
254
IntLeftJustified(VectorFormat vform,int index)255 int64_t IntLeftJustified(VectorFormat vform, int index) const {
256 uint64_t value = UintLeftJustified(vform, index);
257 int64_t result;
258 memcpy(&result, &value, sizeof(result));
259 return result;
260 }
261
SetInt(VectorFormat vform,int index,int64_t value)262 void SetInt(VectorFormat vform, int index, int64_t value) const {
263 switch (LaneSizeInBitsFromFormat(vform)) {
264 case 8:
265 register_.Insert(index, static_cast<int8_t>(value));
266 break;
267 case 16:
268 register_.Insert(index, static_cast<int16_t>(value));
269 break;
270 case 32:
271 register_.Insert(index, static_cast<int32_t>(value));
272 break;
273 case 64:
274 register_.Insert(index, static_cast<int64_t>(value));
275 break;
276 default:
277 VIXL_UNREACHABLE();
278 return;
279 }
280 }
281
SetIntArray(VectorFormat vform,const int64_t * src)282 void SetIntArray(VectorFormat vform, const int64_t* src) const {
283 ClearForWrite(vform);
284 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
285 SetInt(vform, i, src[i]);
286 }
287 }
288
SetUint(VectorFormat vform,int index,uint64_t value)289 void SetUint(VectorFormat vform, int index, uint64_t value) const {
290 switch (LaneSizeInBitsFromFormat(vform)) {
291 case 8:
292 register_.Insert(index, static_cast<uint8_t>(value));
293 break;
294 case 16:
295 register_.Insert(index, static_cast<uint16_t>(value));
296 break;
297 case 32:
298 register_.Insert(index, static_cast<uint32_t>(value));
299 break;
300 case 64:
301 register_.Insert(index, static_cast<uint64_t>(value));
302 break;
303 default:
304 VIXL_UNREACHABLE();
305 return;
306 }
307 }
308
SetUintArray(VectorFormat vform,const uint64_t * src)309 void SetUintArray(VectorFormat vform, const uint64_t* src) const {
310 ClearForWrite(vform);
311 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
312 SetUint(vform, i, src[i]);
313 }
314 }
315
ReadUintFromMem(VectorFormat vform,int index,uint64_t addr)316 void ReadUintFromMem(VectorFormat vform, int index, uint64_t addr) const {
317 switch (LaneSizeInBitsFromFormat(vform)) {
318 case 8:
319 register_.Insert(index, Memory::Read<uint8_t>(addr));
320 break;
321 case 16:
322 register_.Insert(index, Memory::Read<uint16_t>(addr));
323 break;
324 case 32:
325 register_.Insert(index, Memory::Read<uint32_t>(addr));
326 break;
327 case 64:
328 register_.Insert(index, Memory::Read<uint64_t>(addr));
329 break;
330 default:
331 VIXL_UNREACHABLE();
332 return;
333 }
334 }
335
WriteUintToMem(VectorFormat vform,int index,uint64_t addr)336 void WriteUintToMem(VectorFormat vform, int index, uint64_t addr) const {
337 uint64_t value = Uint(vform, index);
338 switch (LaneSizeInBitsFromFormat(vform)) {
339 case 8:
340 Memory::Write(addr, static_cast<uint8_t>(value));
341 break;
342 case 16:
343 Memory::Write(addr, static_cast<uint16_t>(value));
344 break;
345 case 32:
346 Memory::Write(addr, static_cast<uint32_t>(value));
347 break;
348 case 64:
349 Memory::Write(addr, value);
350 break;
351 }
352 }
353
354 template <typename T>
Float(int index)355 T Float(int index) const {
356 return register_.GetLane<T>(index);
357 }
358
359 template <typename T>
SetFloat(int index,T value)360 void SetFloat(int index, T value) const {
361 register_.Insert(index, value);
362 }
363
364 // When setting a result in a register of size less than Q, the top bits of
365 // the Q register must be cleared.
ClearForWrite(VectorFormat vform)366 void ClearForWrite(VectorFormat vform) const {
367 unsigned size = RegisterSizeInBytesFromFormat(vform);
368 for (unsigned i = size; i < kQRegSizeInBytes; i++) {
369 SetUint(kFormat16B, i, 0);
370 }
371 }
372
373 // Saturation state for each lane of a vector.
374 enum Saturation {
375 kNotSaturated = 0,
376 kSignedSatPositive = 1 << 0,
377 kSignedSatNegative = 1 << 1,
378 kSignedSatMask = kSignedSatPositive | kSignedSatNegative,
379 kSignedSatUndefined = kSignedSatMask,
380 kUnsignedSatPositive = 1 << 2,
381 kUnsignedSatNegative = 1 << 3,
382 kUnsignedSatMask = kUnsignedSatPositive | kUnsignedSatNegative,
383 kUnsignedSatUndefined = kUnsignedSatMask
384 };
385
386 // Getters for saturation state.
GetSignedSaturation(int index)387 Saturation GetSignedSaturation(int index) {
388 return static_cast<Saturation>(saturated_[index] & kSignedSatMask);
389 }
390
GetUnsignedSaturation(int index)391 Saturation GetUnsignedSaturation(int index) {
392 return static_cast<Saturation>(saturated_[index] & kUnsignedSatMask);
393 }
394
395 // Setters for saturation state.
ClearSat(int index)396 void ClearSat(int index) { saturated_[index] = kNotSaturated; }
397
SetSignedSat(int index,bool positive)398 void SetSignedSat(int index, bool positive) {
399 SetSatFlag(index, positive ? kSignedSatPositive : kSignedSatNegative);
400 }
401
SetUnsignedSat(int index,bool positive)402 void SetUnsignedSat(int index, bool positive) {
403 SetSatFlag(index, positive ? kUnsignedSatPositive : kUnsignedSatNegative);
404 }
405
SetSatFlag(int index,Saturation sat)406 void SetSatFlag(int index, Saturation sat) {
407 saturated_[index] = static_cast<Saturation>(saturated_[index] | sat);
408 VIXL_ASSERT((sat & kUnsignedSatMask) != kUnsignedSatUndefined);
409 VIXL_ASSERT((sat & kSignedSatMask) != kSignedSatUndefined);
410 }
411
412 // Saturate lanes of a vector based on saturation state.
SignedSaturate(VectorFormat vform)413 LogicVRegister& SignedSaturate(VectorFormat vform) {
414 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
415 Saturation sat = GetSignedSaturation(i);
416 if (sat == kSignedSatPositive) {
417 SetInt(vform, i, MaxIntFromFormat(vform));
418 } else if (sat == kSignedSatNegative) {
419 SetInt(vform, i, MinIntFromFormat(vform));
420 }
421 }
422 return *this;
423 }
424
UnsignedSaturate(VectorFormat vform)425 LogicVRegister& UnsignedSaturate(VectorFormat vform) {
426 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
427 Saturation sat = GetUnsignedSaturation(i);
428 if (sat == kUnsignedSatPositive) {
429 SetUint(vform, i, MaxUintFromFormat(vform));
430 } else if (sat == kUnsignedSatNegative) {
431 SetUint(vform, i, 0);
432 }
433 }
434 return *this;
435 }
436
437 // Getter for rounding state.
GetRounding(int index)438 bool GetRounding(int index) { return round_[index]; }
439
440 // Setter for rounding state.
SetRounding(int index,bool round)441 void SetRounding(int index, bool round) { round_[index] = round; }
442
443 // Round lanes of a vector based on rounding state.
Round(VectorFormat vform)444 LogicVRegister& Round(VectorFormat vform) {
445 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
446 SetUint(vform, i, Uint(vform, i) + (GetRounding(i) ? 1 : 0));
447 }
448 return *this;
449 }
450
451 // Unsigned halve lanes of a vector, and use the saturation state to set the
452 // top bit.
Uhalve(VectorFormat vform)453 LogicVRegister& Uhalve(VectorFormat vform) {
454 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
455 uint64_t val = Uint(vform, i);
456 SetRounding(i, (val & 1) == 1);
457 val >>= 1;
458 if (GetUnsignedSaturation(i) != kNotSaturated) {
459 // If the operation causes unsigned saturation, the bit shifted into the
460 // most significant bit must be set.
461 val |= (MaxUintFromFormat(vform) >> 1) + 1;
462 }
463 SetInt(vform, i, val);
464 }
465 return *this;
466 }
467
468 // Signed halve lanes of a vector, and use the carry state to set the top bit.
Halve(VectorFormat vform)469 LogicVRegister& Halve(VectorFormat vform) {
470 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
471 int64_t val = Int(vform, i);
472 SetRounding(i, (val & 1) == 1);
473 val >>= 1;
474 if (GetSignedSaturation(i) != kNotSaturated) {
475 // If the operation causes signed saturation, the sign bit must be
476 // inverted.
477 val ^= (MaxUintFromFormat(vform) >> 1) + 1;
478 }
479 SetInt(vform, i, val);
480 }
481 return *this;
482 }
483
484 private:
485 SimVRegister& register_;
486
487 // Allocate one saturation state entry per lane; largest register is type Q,
488 // and lanes can be a minimum of one byte wide.
489 Saturation saturated_[kQRegSizeInBytes];
490
491 // Allocate one rounding state entry per lane.
492 bool round_[kQRegSizeInBytes];
493 };
494
495 // The proper way to initialize a simulated system register (such as NZCV) is as
496 // follows:
497 // SimSystemRegister nzcv = SimSystemRegister::DefaultValueFor(NZCV);
498 class SimSystemRegister {
499 public:
500 // The default constructor represents a register which has no writable bits.
501 // It is not possible to set its value to anything other than 0.
SimSystemRegister()502 SimSystemRegister() : value_(0), write_ignore_mask_(0xffffffff) {}
503
GetRawValue()504 uint32_t GetRawValue() const { return value_; }
505 VIXL_DEPRECATED("GetRawValue", uint32_t RawValue() const) {
506 return GetRawValue();
507 }
508
SetRawValue(uint32_t new_value)509 void SetRawValue(uint32_t new_value) {
510 value_ = (value_ & write_ignore_mask_) | (new_value & ~write_ignore_mask_);
511 }
512
ExtractBits(int msb,int lsb)513 uint32_t ExtractBits(int msb, int lsb) const {
514 return ExtractUnsignedBitfield32(msb, lsb, value_);
515 }
516 VIXL_DEPRECATED("ExtractBits", uint32_t Bits(int msb, int lsb) const) {
517 return ExtractBits(msb, lsb);
518 }
519
ExtractSignedBits(int msb,int lsb)520 int32_t ExtractSignedBits(int msb, int lsb) const {
521 return ExtractSignedBitfield32(msb, lsb, value_);
522 }
523 VIXL_DEPRECATED("ExtractSignedBits",
524 int32_t SignedBits(int msb, int lsb) const) {
525 return ExtractSignedBits(msb, lsb);
526 }
527
528 void SetBits(int msb, int lsb, uint32_t bits);
529
530 // Default system register values.
531 static SimSystemRegister DefaultValueFor(SystemRegister id);
532
533 #define DEFINE_GETTER(Name, HighBit, LowBit, Func) \
534 uint32_t Get##Name() const { return this->Func(HighBit, LowBit); } \
535 VIXL_DEPRECATED("Get" #Name, uint32_t Name() const) { return Get##Name(); } \
536 void Set##Name(uint32_t bits) { SetBits(HighBit, LowBit, bits); }
537 #define DEFINE_WRITE_IGNORE_MASK(Name, Mask) \
538 static const uint32_t Name##WriteIgnoreMask = ~static_cast<uint32_t>(Mask);
539
SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER,DEFINE_WRITE_IGNORE_MASK)540 SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER, DEFINE_WRITE_IGNORE_MASK)
541
542 #undef DEFINE_ZERO_BITS
543 #undef DEFINE_GETTER
544
545 protected:
546 // Most system registers only implement a few of the bits in the word. Other
547 // bits are "read-as-zero, write-ignored". The write_ignore_mask argument
548 // describes the bits which are not modifiable.
549 SimSystemRegister(uint32_t value, uint32_t write_ignore_mask)
550 : value_(value), write_ignore_mask_(write_ignore_mask) {}
551
552 uint32_t value_;
553 uint32_t write_ignore_mask_;
554 };
555
556
557 class SimExclusiveLocalMonitor {
558 public:
SimExclusiveLocalMonitor()559 SimExclusiveLocalMonitor() : kSkipClearProbability(8), seed_(0x87654321) {
560 Clear();
561 }
562
563 // Clear the exclusive monitor (like clrex).
Clear()564 void Clear() {
565 address_ = 0;
566 size_ = 0;
567 }
568
569 // Clear the exclusive monitor most of the time.
MaybeClear()570 void MaybeClear() {
571 if ((seed_ % kSkipClearProbability) != 0) {
572 Clear();
573 }
574
575 // Advance seed_ using a simple linear congruential generator.
576 seed_ = (seed_ * 48271) % 2147483647;
577 }
578
579 // Mark the address range for exclusive access (like load-exclusive).
MarkExclusive(uint64_t address,size_t size)580 void MarkExclusive(uint64_t address, size_t size) {
581 address_ = address;
582 size_ = size;
583 }
584
585 // Return true if the address range is marked (like store-exclusive).
586 // This helper doesn't implicitly clear the monitor.
IsExclusive(uint64_t address,size_t size)587 bool IsExclusive(uint64_t address, size_t size) {
588 VIXL_ASSERT(size > 0);
589 // Be pedantic: Require both the address and the size to match.
590 return (size == size_) && (address == address_);
591 }
592
593 private:
594 uint64_t address_;
595 size_t size_;
596
597 const int kSkipClearProbability;
598 uint32_t seed_;
599 };
600
601
602 // We can't accurate simulate the global monitor since it depends on external
603 // influences. Instead, this implementation occasionally causes accesses to
604 // fail, according to kPassProbability.
605 class SimExclusiveGlobalMonitor {
606 public:
SimExclusiveGlobalMonitor()607 SimExclusiveGlobalMonitor() : kPassProbability(8), seed_(0x87654321) {}
608
IsExclusive(uint64_t address,size_t size)609 bool IsExclusive(uint64_t address, size_t size) {
610 USE(address, size);
611
612 bool pass = (seed_ % kPassProbability) != 0;
613 // Advance seed_ using a simple linear congruential generator.
614 seed_ = (seed_ * 48271) % 2147483647;
615 return pass;
616 }
617
618 private:
619 const int kPassProbability;
620 uint32_t seed_;
621 };
622
623
624 class Simulator : public DecoderVisitor {
625 public:
626 explicit Simulator(Decoder* decoder, FILE* stream = stdout);
627 ~Simulator();
628
629 void ResetState();
630
631 // Run the simulator.
632 virtual void Run();
633 void RunFrom(const Instruction* first);
634
635
636 #if defined(VIXL_HAS_ABI_SUPPORT) && __cplusplus >= 201103L && \
637 (defined(__clang__) || GCC_VERSION_OR_NEWER(4, 9, 1))
638 // Templated `RunFrom` version taking care of passing arguments and returning
639 // the result value.
640 // This allows code like:
641 // int32_t res = simulator.RunFrom<int32_t, int32_t>(GenerateCode(),
642 // 0x123);
643 // It requires VIXL's ABI features, and C++11 or greater.
644 // Also, the initialisation of tuples is incorrect in GCC before 4.9.1:
645 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51253
646 template <typename R, typename... P>
RunFrom(const Instruction * code,P...arguments)647 R RunFrom(const Instruction* code, P... arguments) {
648 return RunFromStructHelper<R, P...>::Wrapper(this, code, arguments...);
649 }
650
651 template <typename R, typename... P>
652 struct RunFromStructHelper {
WrapperRunFromStructHelper653 static R Wrapper(Simulator* simulator,
654 const Instruction* code,
655 P... arguments) {
656 ABI abi;
657 std::tuple<P...> unused_tuple{
658 // TODO: We currently do not support arguments passed on the stack. We
659 // could do so by using `WriteGenericOperand()` here, but may need to
660 // add features to handle situations where the stack is or is not set
661 // up.
662 (simulator->WriteCPURegister(abi.GetNextParameterGenericOperand<P>()
663 .GetCPURegister(),
664 arguments),
665 arguments)...};
666 simulator->RunFrom(code);
667 return simulator->ReadGenericOperand<R>(abi.GetReturnGenericOperand<R>());
668 }
669 };
670
671 // Partial specialization when the return type is `void`.
672 template <typename... P>
673 struct RunFromStructHelper<void, P...> {
674 static void Wrapper(Simulator* simulator,
675 const Instruction* code,
676 P... arguments) {
677 ABI abi;
678 std::tuple<P...> unused_tuple{
679 // TODO: We currently do not support arguments passed on the stack. We
680 // could do so by using `WriteGenericOperand()` here, but may need to
681 // add features to handle situations where the stack is or is not set
682 // up.
683 (simulator->WriteCPURegister(abi.GetNextParameterGenericOperand<P>()
684 .GetCPURegister(),
685 arguments),
686 arguments)...};
687 simulator->RunFrom(code);
688 }
689 };
690 #endif
691
692 // Execution ends when the PC hits this address.
693 static const Instruction* kEndOfSimAddress;
694
695 // Simulation helpers.
696 const Instruction* ReadPc() const { return pc_; }
697 VIXL_DEPRECATED("ReadPc", const Instruction* pc() const) { return ReadPc(); }
698
699 enum BranchLogMode { LogBranches, NoBranchLog };
700
701 void WritePc(const Instruction* new_pc,
702 BranchLogMode log_mode = LogBranches) {
703 if (log_mode == LogBranches) LogTakenBranch(new_pc);
704 pc_ = Memory::AddressUntag(new_pc);
705 pc_modified_ = true;
706 }
707 VIXL_DEPRECATED("WritePc", void set_pc(const Instruction* new_pc)) {
708 return WritePc(new_pc);
709 }
710
711 void IncrementPc() {
712 if (!pc_modified_) {
713 pc_ = pc_->GetNextInstruction();
714 }
715 }
716 VIXL_DEPRECATED("IncrementPc", void increment_pc()) { IncrementPc(); }
717
718 BType ReadBType() const { return btype_; }
719 void WriteNextBType(BType btype) { next_btype_ = btype; }
720 void UpdateBType() {
721 btype_ = next_btype_;
722 next_btype_ = DefaultBType;
723 }
724
725 // Helper function to determine BType for branches.
726 BType GetBTypeFromInstruction(const Instruction* instr) const;
727
728 bool PcIsInGuardedPage() const { return guard_pages_; }
729 void SetGuardedPages(bool guard_pages) { guard_pages_ = guard_pages; }
730
731 void ExecuteInstruction() {
732 // The program counter should always be aligned.
733 VIXL_ASSERT(IsWordAligned(pc_));
734 pc_modified_ = false;
735
736 // On guarded pages, if BType is not zero, take an exception on any
737 // instruction other than BTI, PACI[AB]SP, HLT or BRK.
738 if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
739 if (pc_->IsPAuth()) {
740 Instr i = pc_->Mask(SystemPAuthMask);
741 if ((i != PACIASP) && (i != PACIBSP)) {
742 VIXL_ABORT_WITH_MSG(
743 "Executing non-BTI instruction with wrong BType.");
744 }
745 } else if (!pc_->IsBti() && !pc_->IsException()) {
746 VIXL_ABORT_WITH_MSG("Executing non-BTI instruction with wrong BType.");
747 }
748 }
749
750 // decoder_->Decode(...) triggers at least the following visitors:
751 // 1. The CPUFeaturesAuditor (`cpu_features_auditor_`).
752 // 2. The PrintDisassembler (`print_disasm_`), if enabled.
753 // 3. The Simulator (`this`).
754 // User can add additional visitors at any point, but the Simulator requires
755 // that the ordering above is preserved.
756 decoder_->Decode(pc_);
757 IncrementPc();
758 LogAllWrittenRegisters();
759 UpdateBType();
760
761 VIXL_CHECK(cpu_features_auditor_.InstructionIsAvailable());
762 }
763
764 // Declare all Visitor functions.
765 #define DECLARE(A) \
766 virtual void Visit##A(const Instruction* instr) VIXL_OVERRIDE;
767 VISITOR_LIST_THAT_RETURN(DECLARE)
768 #undef DECLARE
769
770
771 #define DECLARE(A) \
772 VIXL_NO_RETURN virtual void Visit##A(const Instruction* instr) VIXL_OVERRIDE;
773 VISITOR_LIST_THAT_DONT_RETURN(DECLARE)
774 #undef DECLARE
775
776
777 #define DECLARE(A) \
778 VIXL_NO_RETURN_IN_DEBUG_MODE virtual void Visit##A(const Instruction* instr) \
779 VIXL_OVERRIDE;
780 VISITOR_LIST_THAT_DONT_RETURN_IN_DEBUG_MODE(DECLARE)
781 #undef DECLARE
782
783
784 // Integer register accessors.
785
786 // Basic accessor: Read the register as the specified type.
787 template <typename T>
788 T ReadRegister(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
789 VIXL_ASSERT(
790 code < kNumberOfRegisters ||
791 ((r31mode == Reg31IsZeroRegister) && (code == kSPRegInternalCode)));
792 if ((code == 31) && (r31mode == Reg31IsZeroRegister)) {
793 T result;
794 memset(&result, 0, sizeof(result));
795 return result;
796 }
797 if ((r31mode == Reg31IsZeroRegister) && (code == kSPRegInternalCode)) {
798 code = 31;
799 }
800 return registers_[code].Get<T>();
801 }
802 template <typename T>
803 VIXL_DEPRECATED("ReadRegister",
804 T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister)
805 const) {
806 return ReadRegister<T>(code, r31mode);
807 }
808
809 // Common specialized accessors for the ReadRegister() template.
810 int32_t ReadWRegister(unsigned code,
811 Reg31Mode r31mode = Reg31IsZeroRegister) const {
812 return ReadRegister<int32_t>(code, r31mode);
813 }
814 VIXL_DEPRECATED("ReadWRegister",
815 int32_t wreg(unsigned code,
816 Reg31Mode r31mode = Reg31IsZeroRegister) const) {
817 return ReadWRegister(code, r31mode);
818 }
819
820 int64_t ReadXRegister(unsigned code,
821 Reg31Mode r31mode = Reg31IsZeroRegister) const {
822 return ReadRegister<int64_t>(code, r31mode);
823 }
824 VIXL_DEPRECATED("ReadXRegister",
825 int64_t xreg(unsigned code,
826 Reg31Mode r31mode = Reg31IsZeroRegister) const) {
827 return ReadXRegister(code, r31mode);
828 }
829
830 // As above, with parameterized size and return type. The value is
831 // either zero-extended or truncated to fit, as required.
832 template <typename T>
833 T ReadRegister(unsigned size,
834 unsigned code,
835 Reg31Mode r31mode = Reg31IsZeroRegister) const {
836 uint64_t raw;
837 switch (size) {
838 case kWRegSize:
839 raw = ReadRegister<uint32_t>(code, r31mode);
840 break;
841 case kXRegSize:
842 raw = ReadRegister<uint64_t>(code, r31mode);
843 break;
844 default:
845 VIXL_UNREACHABLE();
846 return 0;
847 }
848
849 T result;
850 VIXL_STATIC_ASSERT(sizeof(result) <= sizeof(raw));
851 // Copy the result and truncate to fit. This assumes a little-endian host.
852 memcpy(&result, &raw, sizeof(result));
853 return result;
854 }
855 template <typename T>
856 VIXL_DEPRECATED("ReadRegister",
857 T reg(unsigned size,
858 unsigned code,
859 Reg31Mode r31mode = Reg31IsZeroRegister) const) {
860 return ReadRegister<T>(size, code, r31mode);
861 }
862
863 // Use int64_t by default if T is not specified.
864 int64_t ReadRegister(unsigned size,
865 unsigned code,
866 Reg31Mode r31mode = Reg31IsZeroRegister) const {
867 return ReadRegister<int64_t>(size, code, r31mode);
868 }
869 VIXL_DEPRECATED("ReadRegister",
870 int64_t reg(unsigned size,
871 unsigned code,
872 Reg31Mode r31mode = Reg31IsZeroRegister) const) {
873 return ReadRegister(size, code, r31mode);
874 }
875
876 enum RegLogMode { LogRegWrites, NoRegLog };
877
878 // Write 'value' into an integer register. The value is zero-extended. This
879 // behaviour matches AArch64 register writes.
880 template <typename T>
881 void WriteRegister(unsigned code,
882 T value,
883 RegLogMode log_mode = LogRegWrites,
884 Reg31Mode r31mode = Reg31IsZeroRegister) {
885 if (sizeof(T) < kWRegSizeInBytes) {
886 // We use a C-style cast on purpose here.
887 // Since we do not have access to 'constepxr if', the casts in this `if`
888 // must be valid even if we know the code will never be executed, in
889 // particular when `T` is a pointer type.
890 int64_t tmp_64bit = (int64_t)value;
891 int32_t tmp_32bit = static_cast<int32_t>(tmp_64bit);
892 WriteRegister<int32_t>(code, tmp_32bit, log_mode, r31mode);
893 return;
894 }
895
896 VIXL_ASSERT((sizeof(T) == kWRegSizeInBytes) ||
897 (sizeof(T) == kXRegSizeInBytes));
898 VIXL_ASSERT(
899 code < kNumberOfRegisters ||
900 ((r31mode == Reg31IsZeroRegister) && (code == kSPRegInternalCode)));
901
902 if ((code == 31) && (r31mode == Reg31IsZeroRegister)) {
903 return;
904 }
905
906 if ((r31mode == Reg31IsZeroRegister) && (code == kSPRegInternalCode)) {
907 code = 31;
908 }
909
910 registers_[code].Write(value);
911
912 if (log_mode == LogRegWrites) LogRegister(code, r31mode);
913 }
914 template <typename T>
915 VIXL_DEPRECATED("WriteRegister",
916 void set_reg(unsigned code,
917 T value,
918 RegLogMode log_mode = LogRegWrites,
919 Reg31Mode r31mode = Reg31IsZeroRegister)) {
920 WriteRegister<T>(code, value, log_mode, r31mode);
921 }
922
923 // Common specialized accessors for the set_reg() template.
924 void WriteWRegister(unsigned code,
925 int32_t value,
926 RegLogMode log_mode = LogRegWrites,
927 Reg31Mode r31mode = Reg31IsZeroRegister) {
928 WriteRegister(code, value, log_mode, r31mode);
929 }
930 VIXL_DEPRECATED("WriteWRegister",
931 void set_wreg(unsigned code,
932 int32_t value,
933 RegLogMode log_mode = LogRegWrites,
934 Reg31Mode r31mode = Reg31IsZeroRegister)) {
935 WriteWRegister(code, value, log_mode, r31mode);
936 }
937
938 void WriteXRegister(unsigned code,
939 int64_t value,
940 RegLogMode log_mode = LogRegWrites,
941 Reg31Mode r31mode = Reg31IsZeroRegister) {
942 WriteRegister(code, value, log_mode, r31mode);
943 }
944 VIXL_DEPRECATED("WriteXRegister",
945 void set_xreg(unsigned code,
946 int64_t value,
947 RegLogMode log_mode = LogRegWrites,
948 Reg31Mode r31mode = Reg31IsZeroRegister)) {
949 WriteXRegister(code, value, log_mode, r31mode);
950 }
951
952 // As above, with parameterized size and type. The value is either
953 // zero-extended or truncated to fit, as required.
954 template <typename T>
955 void WriteRegister(unsigned size,
956 unsigned code,
957 T value,
958 RegLogMode log_mode = LogRegWrites,
959 Reg31Mode r31mode = Reg31IsZeroRegister) {
960 // Zero-extend the input.
961 uint64_t raw = 0;
962 VIXL_STATIC_ASSERT(sizeof(value) <= sizeof(raw));
963 memcpy(&raw, &value, sizeof(value));
964
965 // Write (and possibly truncate) the value.
966 switch (size) {
967 case kWRegSize:
968 WriteRegister(code, static_cast<uint32_t>(raw), log_mode, r31mode);
969 break;
970 case kXRegSize:
971 WriteRegister(code, raw, log_mode, r31mode);
972 break;
973 default:
974 VIXL_UNREACHABLE();
975 return;
976 }
977 }
978 template <typename T>
979 VIXL_DEPRECATED("WriteRegister",
980 void set_reg(unsigned size,
981 unsigned code,
982 T value,
983 RegLogMode log_mode = LogRegWrites,
984 Reg31Mode r31mode = Reg31IsZeroRegister)) {
985 WriteRegister(size, code, value, log_mode, r31mode);
986 }
987
988 // Common specialized accessors for the set_reg() template.
989
990 // Commonly-used special cases.
991 template <typename T>
992 void WriteLr(T value) {
993 WriteRegister(kLinkRegCode, value);
994 }
995 template <typename T>
996 VIXL_DEPRECATED("WriteLr", void set_lr(T value)) {
997 WriteLr(value);
998 }
999
1000 template <typename T>
1001 void WriteSp(T value) {
1002 WriteRegister(31, value, LogRegWrites, Reg31IsStackPointer);
1003 }
1004 template <typename T>
1005 VIXL_DEPRECATED("WriteSp", void set_sp(T value)) {
1006 WriteSp(value);
1007 }
1008
1009 // Vector register accessors.
1010 // These are equivalent to the integer register accessors, but for vector
1011 // registers.
1012
1013 // A structure for representing a 128-bit Q register.
1014 struct qreg_t {
1015 uint8_t val[kQRegSizeInBytes];
1016 };
1017
1018 // Basic accessor: read the register as the specified type.
1019 template <typename T>
1020 T ReadVRegister(unsigned code) const {
1021 VIXL_STATIC_ASSERT(
1022 (sizeof(T) == kBRegSizeInBytes) || (sizeof(T) == kHRegSizeInBytes) ||
1023 (sizeof(T) == kSRegSizeInBytes) || (sizeof(T) == kDRegSizeInBytes) ||
1024 (sizeof(T) == kQRegSizeInBytes));
1025 VIXL_ASSERT(code < kNumberOfVRegisters);
1026
1027 return vregisters_[code].Get<T>();
1028 }
1029 template <typename T>
1030 VIXL_DEPRECATED("ReadVRegister", T vreg(unsigned code) const) {
1031 return ReadVRegister<T>(code);
1032 }
1033
1034 // Common specialized accessors for the vreg() template.
1035 int8_t ReadBRegister(unsigned code) const {
1036 return ReadVRegister<int8_t>(code);
1037 }
1038 VIXL_DEPRECATED("ReadBRegister", int8_t breg(unsigned code) const) {
1039 return ReadBRegister(code);
1040 }
1041
1042 vixl::internal::SimFloat16 ReadHRegister(unsigned code) const {
1043 return RawbitsToFloat16(ReadHRegisterBits(code));
1044 }
1045 VIXL_DEPRECATED("ReadHRegister", int16_t hreg(unsigned code) const) {
1046 return Float16ToRawbits(ReadHRegister(code));
1047 }
1048
1049 uint16_t ReadHRegisterBits(unsigned code) const {
1050 return ReadVRegister<uint16_t>(code);
1051 }
1052
1053 float ReadSRegister(unsigned code) const {
1054 return ReadVRegister<float>(code);
1055 }
1056 VIXL_DEPRECATED("ReadSRegister", float sreg(unsigned code) const) {
1057 return ReadSRegister(code);
1058 }
1059
1060 uint32_t ReadSRegisterBits(unsigned code) const {
1061 return ReadVRegister<uint32_t>(code);
1062 }
1063 VIXL_DEPRECATED("ReadSRegisterBits",
1064 uint32_t sreg_bits(unsigned code) const) {
1065 return ReadSRegisterBits(code);
1066 }
1067
1068 double ReadDRegister(unsigned code) const {
1069 return ReadVRegister<double>(code);
1070 }
1071 VIXL_DEPRECATED("ReadDRegister", double dreg(unsigned code) const) {
1072 return ReadDRegister(code);
1073 }
1074
1075 uint64_t ReadDRegisterBits(unsigned code) const {
1076 return ReadVRegister<uint64_t>(code);
1077 }
1078 VIXL_DEPRECATED("ReadDRegisterBits",
1079 uint64_t dreg_bits(unsigned code) const) {
1080 return ReadDRegisterBits(code);
1081 }
1082
1083 qreg_t ReadQRegister(unsigned code) const {
1084 return ReadVRegister<qreg_t>(code);
1085 }
1086 VIXL_DEPRECATED("ReadQRegister", qreg_t qreg(unsigned code) const) {
1087 return ReadQRegister(code);
1088 }
1089
1090 // As above, with parameterized size and return type. The value is
1091 // either zero-extended or truncated to fit, as required.
1092 template <typename T>
1093 T ReadVRegister(unsigned size, unsigned code) const {
1094 uint64_t raw = 0;
1095 T result;
1096
1097 switch (size) {
1098 case kSRegSize:
1099 raw = ReadVRegister<uint32_t>(code);
1100 break;
1101 case kDRegSize:
1102 raw = ReadVRegister<uint64_t>(code);
1103 break;
1104 default:
1105 VIXL_UNREACHABLE();
1106 break;
1107 }
1108
1109 VIXL_STATIC_ASSERT(sizeof(result) <= sizeof(raw));
1110 // Copy the result and truncate to fit. This assumes a little-endian host.
1111 memcpy(&result, &raw, sizeof(result));
1112 return result;
1113 }
1114 template <typename T>
1115 VIXL_DEPRECATED("ReadVRegister", T vreg(unsigned size, unsigned code) const) {
1116 return ReadVRegister<T>(size, code);
1117 }
1118
1119 SimVRegister& ReadVRegister(unsigned code) { return vregisters_[code]; }
1120 VIXL_DEPRECATED("ReadVRegister", SimVRegister& vreg(unsigned code)) {
1121 return ReadVRegister(code);
1122 }
1123
1124 // Basic accessor: Write the specified value.
1125 template <typename T>
1126 void WriteVRegister(unsigned code,
1127 T value,
1128 RegLogMode log_mode = LogRegWrites) {
1129 VIXL_STATIC_ASSERT((sizeof(value) == kBRegSizeInBytes) ||
1130 (sizeof(value) == kHRegSizeInBytes) ||
1131 (sizeof(value) == kSRegSizeInBytes) ||
1132 (sizeof(value) == kDRegSizeInBytes) ||
1133 (sizeof(value) == kQRegSizeInBytes));
1134 VIXL_ASSERT(code < kNumberOfVRegisters);
1135 vregisters_[code].Write(value);
1136
1137 if (log_mode == LogRegWrites) {
1138 LogVRegister(code, GetPrintRegisterFormat(value));
1139 }
1140 }
1141 template <typename T>
1142 VIXL_DEPRECATED("WriteVRegister",
1143 void set_vreg(unsigned code,
1144 T value,
1145 RegLogMode log_mode = LogRegWrites)) {
1146 WriteVRegister(code, value, log_mode);
1147 }
1148
1149 // Common specialized accessors for the WriteVRegister() template.
1150 void WriteBRegister(unsigned code,
1151 int8_t value,
1152 RegLogMode log_mode = LogRegWrites) {
1153 WriteVRegister(code, value, log_mode);
1154 }
1155 VIXL_DEPRECATED("WriteBRegister",
1156 void set_breg(unsigned code,
1157 int8_t value,
1158 RegLogMode log_mode = LogRegWrites)) {
1159 return WriteBRegister(code, value, log_mode);
1160 }
1161
1162 void WriteHRegister(unsigned code,
1163 vixl::internal::SimFloat16 value,
1164 RegLogMode log_mode = LogRegWrites) {
1165 WriteVRegister(code, Float16ToRawbits(value), log_mode);
1166 }
1167
1168 void WriteHRegister(unsigned code,
1169 int16_t value,
1170 RegLogMode log_mode = LogRegWrites) {
1171 WriteVRegister(code, value, log_mode);
1172 }
1173 VIXL_DEPRECATED("WriteHRegister",
1174 void set_hreg(unsigned code,
1175 int16_t value,
1176 RegLogMode log_mode = LogRegWrites)) {
1177 return WriteHRegister(code, value, log_mode);
1178 }
1179
1180 void WriteSRegister(unsigned code,
1181 float value,
1182 RegLogMode log_mode = LogRegWrites) {
1183 WriteVRegister(code, value, log_mode);
1184 }
1185 VIXL_DEPRECATED("WriteSRegister",
1186 void set_sreg(unsigned code,
1187 float value,
1188 RegLogMode log_mode = LogRegWrites)) {
1189 WriteSRegister(code, value, log_mode);
1190 }
1191
1192 void WriteSRegisterBits(unsigned code,
1193 uint32_t value,
1194 RegLogMode log_mode = LogRegWrites) {
1195 WriteVRegister(code, value, log_mode);
1196 }
1197 VIXL_DEPRECATED("WriteSRegisterBits",
1198 void set_sreg_bits(unsigned code,
1199 uint32_t value,
1200 RegLogMode log_mode = LogRegWrites)) {
1201 WriteSRegisterBits(code, value, log_mode);
1202 }
1203
1204 void WriteDRegister(unsigned code,
1205 double value,
1206 RegLogMode log_mode = LogRegWrites) {
1207 WriteVRegister(code, value, log_mode);
1208 }
1209 VIXL_DEPRECATED("WriteDRegister",
1210 void set_dreg(unsigned code,
1211 double value,
1212 RegLogMode log_mode = LogRegWrites)) {
1213 WriteDRegister(code, value, log_mode);
1214 }
1215
1216 void WriteDRegisterBits(unsigned code,
1217 uint64_t value,
1218 RegLogMode log_mode = LogRegWrites) {
1219 WriteVRegister(code, value, log_mode);
1220 }
1221 VIXL_DEPRECATED("WriteDRegisterBits",
1222 void set_dreg_bits(unsigned code,
1223 uint64_t value,
1224 RegLogMode log_mode = LogRegWrites)) {
1225 WriteDRegisterBits(code, value, log_mode);
1226 }
1227
1228 void WriteQRegister(unsigned code,
1229 qreg_t value,
1230 RegLogMode log_mode = LogRegWrites) {
1231 WriteVRegister(code, value, log_mode);
1232 }
1233 VIXL_DEPRECATED("WriteQRegister",
1234 void set_qreg(unsigned code,
1235 qreg_t value,
1236 RegLogMode log_mode = LogRegWrites)) {
1237 WriteQRegister(code, value, log_mode);
1238 }
1239
1240 template <typename T>
1241 T ReadRegister(Register reg) const {
1242 return ReadRegister<T>(reg.GetCode(), Reg31IsZeroRegister);
1243 }
1244
1245 template <typename T>
1246 void WriteRegister(Register reg,
1247 T value,
1248 RegLogMode log_mode = LogRegWrites) {
1249 WriteRegister<T>(reg.GetCode(), value, log_mode, Reg31IsZeroRegister);
1250 }
1251
1252 template <typename T>
1253 T ReadVRegister(VRegister vreg) const {
1254 return ReadVRegister<T>(vreg.GetCode());
1255 }
1256
1257 template <typename T>
1258 void WriteVRegister(VRegister vreg,
1259 T value,
1260 RegLogMode log_mode = LogRegWrites) {
1261 WriteVRegister<T>(vreg.GetCode(), value, log_mode);
1262 }
1263
1264 template <typename T>
1265 T ReadCPURegister(CPURegister reg) const {
1266 if (reg.IsVRegister()) {
1267 return ReadVRegister<T>(VRegister(reg));
1268 } else {
1269 return ReadRegister<T>(Register(reg));
1270 }
1271 }
1272
1273 template <typename T>
1274 void WriteCPURegister(CPURegister reg,
1275 T value,
1276 RegLogMode log_mode = LogRegWrites) {
1277 if (reg.IsVRegister()) {
1278 WriteVRegister<T>(VRegister(reg), value, log_mode);
1279 } else {
1280 WriteRegister<T>(Register(reg), value, log_mode);
1281 }
1282 }
1283
1284 uint64_t ComputeMemOperandAddress(const MemOperand& mem_op) const;
1285
1286 template <typename T>
1287 T ReadGenericOperand(GenericOperand operand) const {
1288 if (operand.IsCPURegister()) {
1289 return ReadCPURegister<T>(operand.GetCPURegister());
1290 } else {
1291 VIXL_ASSERT(operand.IsMemOperand());
1292 return Memory::Read<T>(ComputeMemOperandAddress(operand.GetMemOperand()));
1293 }
1294 }
1295
1296 template <typename T>
1297 void WriteGenericOperand(GenericOperand operand,
1298 T value,
1299 RegLogMode log_mode = LogRegWrites) {
1300 if (operand.IsCPURegister()) {
1301 // Outside SIMD, registers are 64-bit or a subset of a 64-bit register. If
1302 // the width of the value to write is smaller than 64 bits, the unused
1303 // bits may contain unrelated values that the code following this write
1304 // needs to handle gracefully.
1305 // Here we fill the unused bits with a predefined pattern to catch issues
1306 // early.
1307 VIXL_ASSERT(operand.GetCPURegister().GetSizeInBits() <= 64);
1308 uint64_t raw = 0xdeadda1adeadda1a;
1309 memcpy(&raw, &value, sizeof(value));
1310 WriteCPURegister(operand.GetCPURegister(), raw, log_mode);
1311 } else {
1312 VIXL_ASSERT(operand.IsMemOperand());
1313 Memory::Write(ComputeMemOperandAddress(operand.GetMemOperand()), value);
1314 }
1315 }
1316
1317 bool ReadN() const { return nzcv_.GetN() != 0; }
1318 VIXL_DEPRECATED("ReadN", bool N() const) { return ReadN(); }
1319
1320 bool ReadZ() const { return nzcv_.GetZ() != 0; }
1321 VIXL_DEPRECATED("ReadZ", bool Z() const) { return ReadZ(); }
1322
1323 bool ReadC() const { return nzcv_.GetC() != 0; }
1324 VIXL_DEPRECATED("ReadC", bool C() const) { return ReadC(); }
1325
1326 bool ReadV() const { return nzcv_.GetV() != 0; }
1327 VIXL_DEPRECATED("ReadV", bool V() const) { return ReadV(); }
1328
1329 SimSystemRegister& ReadNzcv() { return nzcv_; }
1330 VIXL_DEPRECATED("ReadNzcv", SimSystemRegister& nzcv()) { return ReadNzcv(); }
1331
1332 // TODO: Find a way to make the fpcr_ members return the proper types, so
1333 // these accessors are not necessary.
1334 FPRounding ReadRMode() const {
1335 return static_cast<FPRounding>(fpcr_.GetRMode());
1336 }
1337 VIXL_DEPRECATED("ReadRMode", FPRounding RMode()) { return ReadRMode(); }
1338
1339 UseDefaultNaN ReadDN() const {
1340 return fpcr_.GetDN() != 0 ? kUseDefaultNaN : kIgnoreDefaultNaN;
1341 }
1342
1343 VIXL_DEPRECATED("ReadDN", bool DN()) {
1344 return ReadDN() == kUseDefaultNaN ? true : false;
1345 }
1346
1347 SimSystemRegister& ReadFpcr() { return fpcr_; }
1348 VIXL_DEPRECATED("ReadFpcr", SimSystemRegister& fpcr()) { return ReadFpcr(); }
1349
1350 // Specify relevant register formats for Print(V)Register and related helpers.
1351 enum PrintRegisterFormat {
1352 // The lane size.
1353 kPrintRegLaneSizeB = 0 << 0,
1354 kPrintRegLaneSizeH = 1 << 0,
1355 kPrintRegLaneSizeS = 2 << 0,
1356 kPrintRegLaneSizeW = kPrintRegLaneSizeS,
1357 kPrintRegLaneSizeD = 3 << 0,
1358 kPrintRegLaneSizeX = kPrintRegLaneSizeD,
1359 kPrintRegLaneSizeQ = 4 << 0,
1360
1361 kPrintRegLaneSizeOffset = 0,
1362 kPrintRegLaneSizeMask = 7 << 0,
1363
1364 // The lane count.
1365 kPrintRegAsScalar = 0,
1366 kPrintRegAsDVector = 1 << 3,
1367 kPrintRegAsQVector = 2 << 3,
1368
1369 kPrintRegAsVectorMask = 3 << 3,
1370
1371 // Indicate floating-point format lanes. (This flag is only supported for
1372 // S-, H-, and D-sized lanes.)
1373 kPrintRegAsFP = 1 << 5,
1374
1375 // Supported combinations.
1376
1377 kPrintXReg = kPrintRegLaneSizeX | kPrintRegAsScalar,
1378 kPrintWReg = kPrintRegLaneSizeW | kPrintRegAsScalar,
1379 kPrintHReg = kPrintRegLaneSizeH | kPrintRegAsScalar | kPrintRegAsFP,
1380 kPrintSReg = kPrintRegLaneSizeS | kPrintRegAsScalar | kPrintRegAsFP,
1381 kPrintDReg = kPrintRegLaneSizeD | kPrintRegAsScalar | kPrintRegAsFP,
1382
1383 kPrintReg1B = kPrintRegLaneSizeB | kPrintRegAsScalar,
1384 kPrintReg8B = kPrintRegLaneSizeB | kPrintRegAsDVector,
1385 kPrintReg16B = kPrintRegLaneSizeB | kPrintRegAsQVector,
1386 kPrintReg1H = kPrintRegLaneSizeH | kPrintRegAsScalar,
1387 kPrintReg4H = kPrintRegLaneSizeH | kPrintRegAsDVector,
1388 kPrintReg8H = kPrintRegLaneSizeH | kPrintRegAsQVector,
1389 kPrintReg1S = kPrintRegLaneSizeS | kPrintRegAsScalar,
1390 kPrintReg2S = kPrintRegLaneSizeS | kPrintRegAsDVector,
1391 kPrintReg4S = kPrintRegLaneSizeS | kPrintRegAsQVector,
1392 kPrintReg1HFP = kPrintRegLaneSizeH | kPrintRegAsScalar | kPrintRegAsFP,
1393 kPrintReg4HFP = kPrintRegLaneSizeH | kPrintRegAsDVector | kPrintRegAsFP,
1394 kPrintReg8HFP = kPrintRegLaneSizeH | kPrintRegAsQVector | kPrintRegAsFP,
1395 kPrintReg1SFP = kPrintRegLaneSizeS | kPrintRegAsScalar | kPrintRegAsFP,
1396 kPrintReg2SFP = kPrintRegLaneSizeS | kPrintRegAsDVector | kPrintRegAsFP,
1397 kPrintReg4SFP = kPrintRegLaneSizeS | kPrintRegAsQVector | kPrintRegAsFP,
1398 kPrintReg1D = kPrintRegLaneSizeD | kPrintRegAsScalar,
1399 kPrintReg2D = kPrintRegLaneSizeD | kPrintRegAsQVector,
1400 kPrintReg1DFP = kPrintRegLaneSizeD | kPrintRegAsScalar | kPrintRegAsFP,
1401 kPrintReg2DFP = kPrintRegLaneSizeD | kPrintRegAsQVector | kPrintRegAsFP,
1402 kPrintReg1Q = kPrintRegLaneSizeQ | kPrintRegAsScalar
1403 };
1404
1405 unsigned GetPrintRegLaneSizeInBytesLog2(PrintRegisterFormat format) {
1406 return (format & kPrintRegLaneSizeMask) >> kPrintRegLaneSizeOffset;
1407 }
1408
1409 unsigned GetPrintRegLaneSizeInBytes(PrintRegisterFormat format) {
1410 return 1 << GetPrintRegLaneSizeInBytesLog2(format);
1411 }
1412
1413 unsigned GetPrintRegSizeInBytesLog2(PrintRegisterFormat format) {
1414 if (format & kPrintRegAsDVector) return kDRegSizeInBytesLog2;
1415 if (format & kPrintRegAsQVector) return kQRegSizeInBytesLog2;
1416
1417 // Scalar types.
1418 return GetPrintRegLaneSizeInBytesLog2(format);
1419 }
1420
1421 unsigned GetPrintRegSizeInBytes(PrintRegisterFormat format) {
1422 return 1 << GetPrintRegSizeInBytesLog2(format);
1423 }
1424
1425 unsigned GetPrintRegLaneCount(PrintRegisterFormat format) {
1426 unsigned reg_size_log2 = GetPrintRegSizeInBytesLog2(format);
1427 unsigned lane_size_log2 = GetPrintRegLaneSizeInBytesLog2(format);
1428 VIXL_ASSERT(reg_size_log2 >= lane_size_log2);
1429 return 1 << (reg_size_log2 - lane_size_log2);
1430 }
1431
1432 PrintRegisterFormat GetPrintRegisterFormatForSize(unsigned reg_size,
1433 unsigned lane_size);
1434
1435 PrintRegisterFormat GetPrintRegisterFormatForSize(unsigned size) {
1436 return GetPrintRegisterFormatForSize(size, size);
1437 }
1438
1439 PrintRegisterFormat GetPrintRegisterFormatForSizeFP(unsigned size) {
1440 switch (size) {
1441 default:
1442 VIXL_UNREACHABLE();
1443 return kPrintDReg;
1444 case kDRegSizeInBytes:
1445 return kPrintDReg;
1446 case kSRegSizeInBytes:
1447 return kPrintSReg;
1448 case kHRegSizeInBytes:
1449 return kPrintHReg;
1450 }
1451 }
1452
1453 PrintRegisterFormat GetPrintRegisterFormatTryFP(PrintRegisterFormat format) {
1454 if ((GetPrintRegLaneSizeInBytes(format) == kHRegSizeInBytes) ||
1455 (GetPrintRegLaneSizeInBytes(format) == kSRegSizeInBytes) ||
1456 (GetPrintRegLaneSizeInBytes(format) == kDRegSizeInBytes)) {
1457 return static_cast<PrintRegisterFormat>(format | kPrintRegAsFP);
1458 }
1459 return format;
1460 }
1461
1462 template <typename T>
1463 PrintRegisterFormat GetPrintRegisterFormat(T value) {
1464 return GetPrintRegisterFormatForSize(sizeof(value));
1465 }
1466
1467 PrintRegisterFormat GetPrintRegisterFormat(double value) {
1468 VIXL_STATIC_ASSERT(sizeof(value) == kDRegSizeInBytes);
1469 return GetPrintRegisterFormatForSizeFP(sizeof(value));
1470 }
1471
1472 PrintRegisterFormat GetPrintRegisterFormat(float value) {
1473 VIXL_STATIC_ASSERT(sizeof(value) == kSRegSizeInBytes);
1474 return GetPrintRegisterFormatForSizeFP(sizeof(value));
1475 }
1476
1477 PrintRegisterFormat GetPrintRegisterFormat(Float16 value) {
1478 VIXL_STATIC_ASSERT(sizeof(Float16ToRawbits(value)) == kHRegSizeInBytes);
1479 return GetPrintRegisterFormatForSizeFP(sizeof(Float16ToRawbits(value)));
1480 }
1481
1482 PrintRegisterFormat GetPrintRegisterFormat(VectorFormat vform);
1483 PrintRegisterFormat GetPrintRegisterFormatFP(VectorFormat vform);
1484
1485 // Print all registers of the specified types.
1486 void PrintRegisters();
1487 void PrintVRegisters();
1488 void PrintSystemRegisters();
1489
1490 // As above, but only print the registers that have been updated.
1491 void PrintWrittenRegisters();
1492 void PrintWrittenVRegisters();
1493
1494 // As above, but respect LOG_REG and LOG_VREG.
1495 void LogWrittenRegisters() {
1496 if (GetTraceParameters() & LOG_REGS) PrintWrittenRegisters();
1497 }
1498 void LogWrittenVRegisters() {
1499 if (GetTraceParameters() & LOG_VREGS) PrintWrittenVRegisters();
1500 }
1501 void LogAllWrittenRegisters() {
1502 LogWrittenRegisters();
1503 LogWrittenVRegisters();
1504 }
1505
1506 // Print individual register values (after update).
1507 void PrintRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer);
1508 void PrintVRegister(unsigned code, PrintRegisterFormat format);
1509 void PrintSystemRegister(SystemRegister id);
1510 void PrintTakenBranch(const Instruction* target);
1511
1512 // Like Print* (above), but respect GetTraceParameters().
1513 void LogRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer) {
1514 if (GetTraceParameters() & LOG_REGS) PrintRegister(code, r31mode);
1515 }
1516 void LogVRegister(unsigned code, PrintRegisterFormat format) {
1517 if (GetTraceParameters() & LOG_VREGS) PrintVRegister(code, format);
1518 }
1519 void LogSystemRegister(SystemRegister id) {
1520 if (GetTraceParameters() & LOG_SYSREGS) PrintSystemRegister(id);
1521 }
1522 void LogTakenBranch(const Instruction* target) {
1523 if (GetTraceParameters() & LOG_BRANCH) PrintTakenBranch(target);
1524 }
1525
1526 // Print memory accesses.
1527 void PrintRead(uintptr_t address,
1528 unsigned reg_code,
1529 PrintRegisterFormat format);
1530 void PrintWrite(uintptr_t address,
1531 unsigned reg_code,
1532 PrintRegisterFormat format);
1533 void PrintVRead(uintptr_t address,
1534 unsigned reg_code,
1535 PrintRegisterFormat format,
1536 unsigned lane);
1537 void PrintVWrite(uintptr_t address,
1538 unsigned reg_code,
1539 PrintRegisterFormat format,
1540 unsigned lane);
1541
1542 // Like Print* (above), but respect GetTraceParameters().
1543 void LogRead(uintptr_t address,
1544 unsigned reg_code,
1545 PrintRegisterFormat format) {
1546 if (GetTraceParameters() & LOG_REGS) PrintRead(address, reg_code, format);
1547 }
1548 void LogWrite(uintptr_t address,
1549 unsigned reg_code,
1550 PrintRegisterFormat format) {
1551 if (GetTraceParameters() & LOG_WRITE) PrintWrite(address, reg_code, format);
1552 }
1553 void LogVRead(uintptr_t address,
1554 unsigned reg_code,
1555 PrintRegisterFormat format,
1556 unsigned lane = 0) {
1557 if (GetTraceParameters() & LOG_VREGS) {
1558 PrintVRead(address, reg_code, format, lane);
1559 }
1560 }
1561 void LogVWrite(uintptr_t address,
1562 unsigned reg_code,
1563 PrintRegisterFormat format,
1564 unsigned lane = 0) {
1565 if (GetTraceParameters() & LOG_WRITE) {
1566 PrintVWrite(address, reg_code, format, lane);
1567 }
1568 }
1569
1570 // Helper functions for register tracing.
1571 void PrintRegisterRawHelper(unsigned code,
1572 Reg31Mode r31mode,
1573 int size_in_bytes = kXRegSizeInBytes);
1574 void PrintVRegisterRawHelper(unsigned code,
1575 int bytes = kQRegSizeInBytes,
1576 int lsb = 0);
1577 void PrintVRegisterFPHelper(unsigned code,
1578 unsigned lane_size_in_bytes,
1579 int lane_count = 1,
1580 int rightmost_lane = 0);
1581
1582 VIXL_NO_RETURN void DoUnreachable(const Instruction* instr);
1583 void DoTrace(const Instruction* instr);
1584 void DoLog(const Instruction* instr);
1585
1586 static const char* WRegNameForCode(unsigned code,
1587 Reg31Mode mode = Reg31IsZeroRegister);
1588 static const char* XRegNameForCode(unsigned code,
1589 Reg31Mode mode = Reg31IsZeroRegister);
1590 static const char* HRegNameForCode(unsigned code);
1591 static const char* SRegNameForCode(unsigned code);
1592 static const char* DRegNameForCode(unsigned code);
1593 static const char* VRegNameForCode(unsigned code);
1594
1595 bool IsColouredTrace() const { return coloured_trace_; }
1596 VIXL_DEPRECATED("IsColouredTrace", bool coloured_trace() const) {
1597 return IsColouredTrace();
1598 }
1599
1600 void SetColouredTrace(bool value);
1601 VIXL_DEPRECATED("SetColouredTrace", void set_coloured_trace(bool value)) {
1602 SetColouredTrace(value);
1603 }
1604
1605 // Values for traces parameters defined in simulator-constants-aarch64.h in
1606 // enum TraceParameters.
1607 int GetTraceParameters() const { return trace_parameters_; }
1608 VIXL_DEPRECATED("GetTraceParameters", int trace_parameters() const) {
1609 return GetTraceParameters();
1610 }
1611
1612 void SetTraceParameters(int parameters);
1613 VIXL_DEPRECATED("SetTraceParameters",
1614 void set_trace_parameters(int parameters)) {
1615 SetTraceParameters(parameters);
1616 }
1617
1618 void SetInstructionStats(bool value);
1619 VIXL_DEPRECATED("SetInstructionStats",
1620 void set_instruction_stats(bool value)) {
1621 SetInstructionStats(value);
1622 }
1623
1624 // Clear the simulated local monitor to force the next store-exclusive
1625 // instruction to fail.
1626 void ClearLocalMonitor() { local_monitor_.Clear(); }
1627
1628 void SilenceExclusiveAccessWarning() {
1629 print_exclusive_access_warning_ = false;
1630 }
1631
1632 void CheckIsValidUnalignedAtomicAccess(int rn,
1633 uint64_t address,
1634 unsigned access_size) {
1635 // Verify that the address is available to the host.
1636 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1637
1638 if (GetCPUFeatures()->Has(CPUFeatures::kUSCAT)) {
1639 // Check that the access falls entirely within one atomic access granule.
1640 if (AlignDown(address, kAtomicAccessGranule) !=
1641 AlignDown(address + access_size - 1, kAtomicAccessGranule)) {
1642 VIXL_ALIGNMENT_EXCEPTION();
1643 }
1644 } else {
1645 // Check that the access is aligned.
1646 if (AlignDown(address, access_size) != address) {
1647 VIXL_ALIGNMENT_EXCEPTION();
1648 }
1649 }
1650
1651 // The sp must be aligned to 16 bytes when it is accessed.
1652 if ((rn == kSpRegCode) && (AlignDown(address, 16) != address)) {
1653 VIXL_ALIGNMENT_EXCEPTION();
1654 }
1655 }
1656
1657 enum PointerType { kDataPointer, kInstructionPointer };
1658
1659 struct PACKey {
1660 uint64_t high;
1661 uint64_t low;
1662 int number;
1663 };
1664
1665 // Current implementation is that all pointers are tagged.
1666 bool HasTBI(uint64_t ptr, PointerType type) {
1667 USE(ptr, type);
1668 return true;
1669 }
1670
1671 // Current implementation uses 48-bit virtual addresses.
1672 int GetBottomPACBit(uint64_t ptr, int ttbr) {
1673 USE(ptr, ttbr);
1674 VIXL_ASSERT((ttbr == 0) || (ttbr == 1));
1675 return 48;
1676 }
1677
1678 // The top PAC bit is 55 for the purposes of relative bit fields with TBI,
1679 // however bit 55 is the TTBR bit regardless of TBI so isn't part of the PAC
1680 // codes in pointers.
1681 int GetTopPACBit(uint64_t ptr, PointerType type) {
1682 return HasTBI(ptr, type) ? 55 : 63;
1683 }
1684
1685 // Armv8.3 Pointer authentication helpers.
1686 uint64_t CalculatePACMask(uint64_t ptr, PointerType type, int ext_bit);
1687 uint64_t ComputePAC(uint64_t data, uint64_t context, PACKey key);
1688 uint64_t AuthPAC(uint64_t ptr,
1689 uint64_t context,
1690 PACKey key,
1691 PointerType type);
1692 uint64_t AddPAC(uint64_t ptr, uint64_t context, PACKey key, PointerType type);
1693 uint64_t StripPAC(uint64_t ptr, PointerType type);
1694
1695 // The common CPUFeatures interface with the set of available features.
1696
1697 CPUFeatures* GetCPUFeatures() {
1698 return cpu_features_auditor_.GetCPUFeatures();
1699 }
1700
1701 void SetCPUFeatures(const CPUFeatures& cpu_features) {
1702 cpu_features_auditor_.SetCPUFeatures(cpu_features);
1703 }
1704
1705 // The set of features that the simulator has encountered.
1706 const CPUFeatures& GetSeenFeatures() {
1707 return cpu_features_auditor_.GetSeenFeatures();
1708 }
1709 void ResetSeenFeatures() { cpu_features_auditor_.ResetSeenFeatures(); }
1710
1711 // Runtime call emulation support.
1712 // It requires VIXL's ABI features, and C++11 or greater.
1713 // Also, the initialisation of the tuples in RuntimeCall(Non)Void is incorrect
1714 // in GCC before 4.9.1: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51253
1715 #if defined(VIXL_HAS_ABI_SUPPORT) && __cplusplus >= 201103L && \
1716 (defined(__clang__) || GCC_VERSION_OR_NEWER(4, 9, 1))
1717
1718 #define VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
1719
1720 // The implementation of the runtime call helpers require the functionality
1721 // provided by `std::index_sequence`. It is only available from C++14, but
1722 // we want runtime call simulation to work from C++11, so we emulate if
1723 // necessary.
1724 #if __cplusplus >= 201402L
1725 template <std::size_t... I>
1726 using local_index_sequence = std::index_sequence<I...>;
1727 template <typename... P>
1728 using __local_index_sequence_for = std::index_sequence_for<P...>;
1729 #else
1730 // Emulate the behaviour of `std::index_sequence` and
1731 // `std::index_sequence_for`.
1732 // Naming follow the `std` names, prefixed with `emulated_`.
1733 template <size_t... I>
1734 struct emulated_index_sequence {};
1735
1736 // A recursive template to create a sequence of indexes.
1737 // The base case (for `N == 0`) is declared outside of the class scope, as
1738 // required by C++.
1739 template <std::size_t N, size_t... I>
1740 struct emulated_make_index_sequence_helper
1741 : emulated_make_index_sequence_helper<N - 1, N - 1, I...> {};
1742
1743 template <std::size_t N>
1744 struct emulated_make_index_sequence : emulated_make_index_sequence_helper<N> {
1745 };
1746
1747 template <typename... P>
1748 struct emulated_index_sequence_for
1749 : emulated_make_index_sequence<sizeof...(P)> {};
1750
1751 template <std::size_t... I>
1752 using local_index_sequence = emulated_index_sequence<I...>;
1753 template <typename... P>
1754 using __local_index_sequence_for = emulated_index_sequence_for<P...>;
1755 #endif
1756
1757 // Expand the argument tuple and perform the call.
1758 template <typename R, typename... P, std::size_t... I>
1759 R DoRuntimeCall(R (*function)(P...),
1760 std::tuple<P...> arguments,
1761 local_index_sequence<I...>) {
1762 return function(std::get<I>(arguments)...);
1763 }
1764
1765 template <typename R, typename... P>
1766 void RuntimeCallNonVoid(R (*function)(P...)) {
1767 ABI abi;
1768 std::tuple<P...> argument_operands{
1769 ReadGenericOperand<P>(abi.GetNextParameterGenericOperand<P>())...};
1770 R return_value = DoRuntimeCall(function,
1771 argument_operands,
1772 __local_index_sequence_for<P...>{});
1773 WriteGenericOperand(abi.GetReturnGenericOperand<R>(), return_value);
1774 }
1775
1776 template <typename R, typename... P>
1777 void RuntimeCallVoid(R (*function)(P...)) {
1778 ABI abi;
1779 std::tuple<P...> argument_operands{
1780 ReadGenericOperand<P>(abi.GetNextParameterGenericOperand<P>())...};
1781 DoRuntimeCall(function,
1782 argument_operands,
1783 __local_index_sequence_for<P...>{});
1784 }
1785
1786 // We use `struct` for `void` return type specialisation.
1787 template <typename R, typename... P>
1788 struct RuntimeCallStructHelper {
1789 static void Wrapper(Simulator* simulator, uintptr_t function_pointer) {
1790 R (*function)(P...) = reinterpret_cast<R (*)(P...)>(function_pointer);
1791 simulator->RuntimeCallNonVoid(function);
1792 }
1793 };
1794
1795 // Partial specialization when the return type is `void`.
1796 template <typename... P>
1797 struct RuntimeCallStructHelper<void, P...> {
1798 static void Wrapper(Simulator* simulator, uintptr_t function_pointer) {
1799 void (*function)(P...) =
1800 reinterpret_cast<void (*)(P...)>(function_pointer);
1801 simulator->RuntimeCallVoid(function);
1802 }
1803 };
1804 #endif
1805
1806 protected:
1807 const char* clr_normal;
1808 const char* clr_flag_name;
1809 const char* clr_flag_value;
1810 const char* clr_reg_name;
1811 const char* clr_reg_value;
1812 const char* clr_vreg_name;
1813 const char* clr_vreg_value;
1814 const char* clr_memory_address;
1815 const char* clr_warning;
1816 const char* clr_warning_message;
1817 const char* clr_printf;
1818 const char* clr_branch_marker;
1819
1820 // Simulation helpers ------------------------------------
1821 bool ConditionPassed(Condition cond) {
1822 switch (cond) {
1823 case eq:
1824 return ReadZ();
1825 case ne:
1826 return !ReadZ();
1827 case hs:
1828 return ReadC();
1829 case lo:
1830 return !ReadC();
1831 case mi:
1832 return ReadN();
1833 case pl:
1834 return !ReadN();
1835 case vs:
1836 return ReadV();
1837 case vc:
1838 return !ReadV();
1839 case hi:
1840 return ReadC() && !ReadZ();
1841 case ls:
1842 return !(ReadC() && !ReadZ());
1843 case ge:
1844 return ReadN() == ReadV();
1845 case lt:
1846 return ReadN() != ReadV();
1847 case gt:
1848 return !ReadZ() && (ReadN() == ReadV());
1849 case le:
1850 return !(!ReadZ() && (ReadN() == ReadV()));
1851 case nv:
1852 VIXL_FALLTHROUGH();
1853 case al:
1854 return true;
1855 default:
1856 VIXL_UNREACHABLE();
1857 return false;
1858 }
1859 }
1860
1861 bool ConditionPassed(Instr cond) {
1862 return ConditionPassed(static_cast<Condition>(cond));
1863 }
1864
1865 bool ConditionFailed(Condition cond) { return !ConditionPassed(cond); }
1866
1867 void AddSubHelper(const Instruction* instr, int64_t op2);
1868 uint64_t AddWithCarry(unsigned reg_size,
1869 bool set_flags,
1870 uint64_t left,
1871 uint64_t right,
1872 int carry_in = 0);
1873 void LogicalHelper(const Instruction* instr, int64_t op2);
1874 void ConditionalCompareHelper(const Instruction* instr, int64_t op2);
1875 void LoadStoreHelper(const Instruction* instr,
1876 int64_t offset,
1877 AddrMode addrmode);
1878 void LoadStorePairHelper(const Instruction* instr, AddrMode addrmode);
1879 template <typename T>
1880 void CompareAndSwapHelper(const Instruction* instr);
1881 template <typename T>
1882 void CompareAndSwapPairHelper(const Instruction* instr);
1883 template <typename T>
1884 void AtomicMemorySimpleHelper(const Instruction* instr);
1885 template <typename T>
1886 void AtomicMemorySwapHelper(const Instruction* instr);
1887 template <typename T>
1888 void LoadAcquireRCpcHelper(const Instruction* instr);
1889 template <typename T1, typename T2>
1890 void LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr);
1891 template <typename T>
1892 void StoreReleaseUnscaledOffsetHelper(const Instruction* instr);
1893 uintptr_t AddressModeHelper(unsigned addr_reg,
1894 int64_t offset,
1895 AddrMode addrmode);
1896 void NEONLoadStoreMultiStructHelper(const Instruction* instr,
1897 AddrMode addr_mode);
1898 void NEONLoadStoreSingleStructHelper(const Instruction* instr,
1899 AddrMode addr_mode);
1900
1901 uint64_t AddressUntag(uint64_t address) { return address & ~kAddressTagMask; }
1902
1903 template <typename T>
1904 T* AddressUntag(T* address) {
1905 uintptr_t address_raw = reinterpret_cast<uintptr_t>(address);
1906 return reinterpret_cast<T*>(AddressUntag(address_raw));
1907 }
1908
1909 int64_t ShiftOperand(unsigned reg_size,
1910 int64_t value,
1911 Shift shift_type,
1912 unsigned amount) const;
1913 int64_t ExtendValue(unsigned reg_width,
1914 int64_t value,
1915 Extend extend_type,
1916 unsigned left_shift = 0) const;
1917 uint16_t PolynomialMult(uint8_t op1, uint8_t op2) const;
1918
1919 void ld1(VectorFormat vform, LogicVRegister dst, uint64_t addr);
1920 void ld1(VectorFormat vform, LogicVRegister dst, int index, uint64_t addr);
1921 void ld1r(VectorFormat vform, LogicVRegister dst, uint64_t addr);
1922 void ld2(VectorFormat vform,
1923 LogicVRegister dst1,
1924 LogicVRegister dst2,
1925 uint64_t addr);
1926 void ld2(VectorFormat vform,
1927 LogicVRegister dst1,
1928 LogicVRegister dst2,
1929 int index,
1930 uint64_t addr);
1931 void ld2r(VectorFormat vform,
1932 LogicVRegister dst1,
1933 LogicVRegister dst2,
1934 uint64_t addr);
1935 void ld3(VectorFormat vform,
1936 LogicVRegister dst1,
1937 LogicVRegister dst2,
1938 LogicVRegister dst3,
1939 uint64_t addr);
1940 void ld3(VectorFormat vform,
1941 LogicVRegister dst1,
1942 LogicVRegister dst2,
1943 LogicVRegister dst3,
1944 int index,
1945 uint64_t addr);
1946 void ld3r(VectorFormat vform,
1947 LogicVRegister dst1,
1948 LogicVRegister dst2,
1949 LogicVRegister dst3,
1950 uint64_t addr);
1951 void ld4(VectorFormat vform,
1952 LogicVRegister dst1,
1953 LogicVRegister dst2,
1954 LogicVRegister dst3,
1955 LogicVRegister dst4,
1956 uint64_t addr);
1957 void ld4(VectorFormat vform,
1958 LogicVRegister dst1,
1959 LogicVRegister dst2,
1960 LogicVRegister dst3,
1961 LogicVRegister dst4,
1962 int index,
1963 uint64_t addr);
1964 void ld4r(VectorFormat vform,
1965 LogicVRegister dst1,
1966 LogicVRegister dst2,
1967 LogicVRegister dst3,
1968 LogicVRegister dst4,
1969 uint64_t addr);
1970 void st1(VectorFormat vform, LogicVRegister src, uint64_t addr);
1971 void st1(VectorFormat vform, LogicVRegister src, int index, uint64_t addr);
1972 void st2(VectorFormat vform,
1973 LogicVRegister src,
1974 LogicVRegister src2,
1975 uint64_t addr);
1976 void st2(VectorFormat vform,
1977 LogicVRegister src,
1978 LogicVRegister src2,
1979 int index,
1980 uint64_t addr);
1981 void st3(VectorFormat vform,
1982 LogicVRegister src,
1983 LogicVRegister src2,
1984 LogicVRegister src3,
1985 uint64_t addr);
1986 void st3(VectorFormat vform,
1987 LogicVRegister src,
1988 LogicVRegister src2,
1989 LogicVRegister src3,
1990 int index,
1991 uint64_t addr);
1992 void st4(VectorFormat vform,
1993 LogicVRegister src,
1994 LogicVRegister src2,
1995 LogicVRegister src3,
1996 LogicVRegister src4,
1997 uint64_t addr);
1998 void st4(VectorFormat vform,
1999 LogicVRegister src,
2000 LogicVRegister src2,
2001 LogicVRegister src3,
2002 LogicVRegister src4,
2003 int index,
2004 uint64_t addr);
2005 LogicVRegister cmp(VectorFormat vform,
2006 LogicVRegister dst,
2007 const LogicVRegister& src1,
2008 const LogicVRegister& src2,
2009 Condition cond);
2010 LogicVRegister cmp(VectorFormat vform,
2011 LogicVRegister dst,
2012 const LogicVRegister& src1,
2013 int imm,
2014 Condition cond);
2015 LogicVRegister cmptst(VectorFormat vform,
2016 LogicVRegister dst,
2017 const LogicVRegister& src1,
2018 const LogicVRegister& src2);
2019 LogicVRegister add(VectorFormat vform,
2020 LogicVRegister dst,
2021 const LogicVRegister& src1,
2022 const LogicVRegister& src2);
2023 LogicVRegister addp(VectorFormat vform,
2024 LogicVRegister dst,
2025 const LogicVRegister& src1,
2026 const LogicVRegister& src2);
2027 LogicVRegister mla(VectorFormat vform,
2028 LogicVRegister dst,
2029 const LogicVRegister& src1,
2030 const LogicVRegister& src2);
2031 LogicVRegister mls(VectorFormat vform,
2032 LogicVRegister dst,
2033 const LogicVRegister& src1,
2034 const LogicVRegister& src2);
2035 LogicVRegister mul(VectorFormat vform,
2036 LogicVRegister dst,
2037 const LogicVRegister& src1,
2038 const LogicVRegister& src2);
2039 LogicVRegister mul(VectorFormat vform,
2040 LogicVRegister dst,
2041 const LogicVRegister& src1,
2042 const LogicVRegister& src2,
2043 int index);
2044 LogicVRegister mla(VectorFormat vform,
2045 LogicVRegister dst,
2046 const LogicVRegister& src1,
2047 const LogicVRegister& src2,
2048 int index);
2049 LogicVRegister mls(VectorFormat vform,
2050 LogicVRegister dst,
2051 const LogicVRegister& src1,
2052 const LogicVRegister& src2,
2053 int index);
2054 LogicVRegister pmul(VectorFormat vform,
2055 LogicVRegister dst,
2056 const LogicVRegister& src1,
2057 const LogicVRegister& src2);
2058
2059 typedef LogicVRegister (Simulator::*ByElementOp)(VectorFormat vform,
2060 LogicVRegister dst,
2061 const LogicVRegister& src1,
2062 const LogicVRegister& src2,
2063 int index);
2064 LogicVRegister fmul(VectorFormat vform,
2065 LogicVRegister dst,
2066 const LogicVRegister& src1,
2067 const LogicVRegister& src2,
2068 int index);
2069 LogicVRegister fmla(VectorFormat vform,
2070 LogicVRegister dst,
2071 const LogicVRegister& src1,
2072 const LogicVRegister& src2,
2073 int index);
2074 LogicVRegister fmlal(VectorFormat vform,
2075 LogicVRegister dst,
2076 const LogicVRegister& src1,
2077 const LogicVRegister& src2,
2078 int index);
2079 LogicVRegister fmlal2(VectorFormat vform,
2080 LogicVRegister dst,
2081 const LogicVRegister& src1,
2082 const LogicVRegister& src2,
2083 int index);
2084 LogicVRegister fmls(VectorFormat vform,
2085 LogicVRegister dst,
2086 const LogicVRegister& src1,
2087 const LogicVRegister& src2,
2088 int index);
2089 LogicVRegister fmlsl(VectorFormat vform,
2090 LogicVRegister dst,
2091 const LogicVRegister& src1,
2092 const LogicVRegister& src2,
2093 int index);
2094 LogicVRegister fmlsl2(VectorFormat vform,
2095 LogicVRegister dst,
2096 const LogicVRegister& src1,
2097 const LogicVRegister& src2,
2098 int index);
2099 LogicVRegister fmulx(VectorFormat vform,
2100 LogicVRegister dst,
2101 const LogicVRegister& src1,
2102 const LogicVRegister& src2,
2103 int index);
2104 LogicVRegister smull(VectorFormat vform,
2105 LogicVRegister dst,
2106 const LogicVRegister& src1,
2107 const LogicVRegister& src2,
2108 int index);
2109 LogicVRegister smull2(VectorFormat vform,
2110 LogicVRegister dst,
2111 const LogicVRegister& src1,
2112 const LogicVRegister& src2,
2113 int index);
2114 LogicVRegister umull(VectorFormat vform,
2115 LogicVRegister dst,
2116 const LogicVRegister& src1,
2117 const LogicVRegister& src2,
2118 int index);
2119 LogicVRegister umull2(VectorFormat vform,
2120 LogicVRegister dst,
2121 const LogicVRegister& src1,
2122 const LogicVRegister& src2,
2123 int index);
2124 LogicVRegister smlal(VectorFormat vform,
2125 LogicVRegister dst,
2126 const LogicVRegister& src1,
2127 const LogicVRegister& src2,
2128 int index);
2129 LogicVRegister smlal2(VectorFormat vform,
2130 LogicVRegister dst,
2131 const LogicVRegister& src1,
2132 const LogicVRegister& src2,
2133 int index);
2134 LogicVRegister umlal(VectorFormat vform,
2135 LogicVRegister dst,
2136 const LogicVRegister& src1,
2137 const LogicVRegister& src2,
2138 int index);
2139 LogicVRegister umlal2(VectorFormat vform,
2140 LogicVRegister dst,
2141 const LogicVRegister& src1,
2142 const LogicVRegister& src2,
2143 int index);
2144 LogicVRegister smlsl(VectorFormat vform,
2145 LogicVRegister dst,
2146 const LogicVRegister& src1,
2147 const LogicVRegister& src2,
2148 int index);
2149 LogicVRegister smlsl2(VectorFormat vform,
2150 LogicVRegister dst,
2151 const LogicVRegister& src1,
2152 const LogicVRegister& src2,
2153 int index);
2154 LogicVRegister umlsl(VectorFormat vform,
2155 LogicVRegister dst,
2156 const LogicVRegister& src1,
2157 const LogicVRegister& src2,
2158 int index);
2159 LogicVRegister umlsl2(VectorFormat vform,
2160 LogicVRegister dst,
2161 const LogicVRegister& src1,
2162 const LogicVRegister& src2,
2163 int index);
2164 LogicVRegister sqdmull(VectorFormat vform,
2165 LogicVRegister dst,
2166 const LogicVRegister& src1,
2167 const LogicVRegister& src2,
2168 int index);
2169 LogicVRegister sqdmull2(VectorFormat vform,
2170 LogicVRegister dst,
2171 const LogicVRegister& src1,
2172 const LogicVRegister& src2,
2173 int index);
2174 LogicVRegister sqdmlal(VectorFormat vform,
2175 LogicVRegister dst,
2176 const LogicVRegister& src1,
2177 const LogicVRegister& src2,
2178 int index);
2179 LogicVRegister sqdmlal2(VectorFormat vform,
2180 LogicVRegister dst,
2181 const LogicVRegister& src1,
2182 const LogicVRegister& src2,
2183 int index);
2184 LogicVRegister sqdmlsl(VectorFormat vform,
2185 LogicVRegister dst,
2186 const LogicVRegister& src1,
2187 const LogicVRegister& src2,
2188 int index);
2189 LogicVRegister sqdmlsl2(VectorFormat vform,
2190 LogicVRegister dst,
2191 const LogicVRegister& src1,
2192 const LogicVRegister& src2,
2193 int index);
2194 LogicVRegister sqdmulh(VectorFormat vform,
2195 LogicVRegister dst,
2196 const LogicVRegister& src1,
2197 const LogicVRegister& src2,
2198 int index);
2199 LogicVRegister sqrdmulh(VectorFormat vform,
2200 LogicVRegister dst,
2201 const LogicVRegister& src1,
2202 const LogicVRegister& src2,
2203 int index);
2204 LogicVRegister sdot(VectorFormat vform,
2205 LogicVRegister dst,
2206 const LogicVRegister& src1,
2207 const LogicVRegister& src2,
2208 int index);
2209 LogicVRegister sqrdmlah(VectorFormat vform,
2210 LogicVRegister dst,
2211 const LogicVRegister& src1,
2212 const LogicVRegister& src2,
2213 int index);
2214 LogicVRegister udot(VectorFormat vform,
2215 LogicVRegister dst,
2216 const LogicVRegister& src1,
2217 const LogicVRegister& src2,
2218 int index);
2219 LogicVRegister sqrdmlsh(VectorFormat vform,
2220 LogicVRegister dst,
2221 const LogicVRegister& src1,
2222 const LogicVRegister& src2,
2223 int index);
2224 LogicVRegister sub(VectorFormat vform,
2225 LogicVRegister dst,
2226 const LogicVRegister& src1,
2227 const LogicVRegister& src2);
2228 LogicVRegister and_(VectorFormat vform,
2229 LogicVRegister dst,
2230 const LogicVRegister& src1,
2231 const LogicVRegister& src2);
2232 LogicVRegister orr(VectorFormat vform,
2233 LogicVRegister dst,
2234 const LogicVRegister& src1,
2235 const LogicVRegister& src2);
2236 LogicVRegister orn(VectorFormat vform,
2237 LogicVRegister dst,
2238 const LogicVRegister& src1,
2239 const LogicVRegister& src2);
2240 LogicVRegister eor(VectorFormat vform,
2241 LogicVRegister dst,
2242 const LogicVRegister& src1,
2243 const LogicVRegister& src2);
2244 LogicVRegister bic(VectorFormat vform,
2245 LogicVRegister dst,
2246 const LogicVRegister& src1,
2247 const LogicVRegister& src2);
2248 LogicVRegister bic(VectorFormat vform,
2249 LogicVRegister dst,
2250 const LogicVRegister& src,
2251 uint64_t imm);
2252 LogicVRegister bif(VectorFormat vform,
2253 LogicVRegister dst,
2254 const LogicVRegister& src1,
2255 const LogicVRegister& src2);
2256 LogicVRegister bit(VectorFormat vform,
2257 LogicVRegister dst,
2258 const LogicVRegister& src1,
2259 const LogicVRegister& src2);
2260 LogicVRegister bsl(VectorFormat vform,
2261 LogicVRegister dst,
2262 const LogicVRegister& src1,
2263 const LogicVRegister& src2);
2264 LogicVRegister cls(VectorFormat vform,
2265 LogicVRegister dst,
2266 const LogicVRegister& src);
2267 LogicVRegister clz(VectorFormat vform,
2268 LogicVRegister dst,
2269 const LogicVRegister& src);
2270 LogicVRegister cnt(VectorFormat vform,
2271 LogicVRegister dst,
2272 const LogicVRegister& src);
2273 LogicVRegister not_(VectorFormat vform,
2274 LogicVRegister dst,
2275 const LogicVRegister& src);
2276 LogicVRegister rbit(VectorFormat vform,
2277 LogicVRegister dst,
2278 const LogicVRegister& src);
2279 LogicVRegister rev(VectorFormat vform,
2280 LogicVRegister dst,
2281 const LogicVRegister& src,
2282 int revSize);
2283 LogicVRegister rev16(VectorFormat vform,
2284 LogicVRegister dst,
2285 const LogicVRegister& src);
2286 LogicVRegister rev32(VectorFormat vform,
2287 LogicVRegister dst,
2288 const LogicVRegister& src);
2289 LogicVRegister rev64(VectorFormat vform,
2290 LogicVRegister dst,
2291 const LogicVRegister& src);
2292 LogicVRegister addlp(VectorFormat vform,
2293 LogicVRegister dst,
2294 const LogicVRegister& src,
2295 bool is_signed,
2296 bool do_accumulate);
2297 LogicVRegister saddlp(VectorFormat vform,
2298 LogicVRegister dst,
2299 const LogicVRegister& src);
2300 LogicVRegister uaddlp(VectorFormat vform,
2301 LogicVRegister dst,
2302 const LogicVRegister& src);
2303 LogicVRegister sadalp(VectorFormat vform,
2304 LogicVRegister dst,
2305 const LogicVRegister& src);
2306 LogicVRegister uadalp(VectorFormat vform,
2307 LogicVRegister dst,
2308 const LogicVRegister& src);
2309 LogicVRegister ext(VectorFormat vform,
2310 LogicVRegister dst,
2311 const LogicVRegister& src1,
2312 const LogicVRegister& src2,
2313 int index);
2314 template <typename T>
2315 LogicVRegister fcadd(VectorFormat vform,
2316 LogicVRegister dst,
2317 const LogicVRegister& src1,
2318 const LogicVRegister& src2,
2319 int rot);
2320 LogicVRegister fcadd(VectorFormat vform,
2321 LogicVRegister dst,
2322 const LogicVRegister& src1,
2323 const LogicVRegister& src2,
2324 int rot);
2325 template <typename T>
2326 LogicVRegister fcmla(VectorFormat vform,
2327 LogicVRegister dst,
2328 const LogicVRegister& src1,
2329 const LogicVRegister& src2,
2330 int index,
2331 int rot);
2332 LogicVRegister fcmla(VectorFormat vform,
2333 LogicVRegister dst,
2334 const LogicVRegister& src1,
2335 const LogicVRegister& src2,
2336 int index,
2337 int rot);
2338 template <typename T>
2339 LogicVRegister fcmla(VectorFormat vform,
2340 LogicVRegister dst,
2341 const LogicVRegister& src1,
2342 const LogicVRegister& src2,
2343 int rot);
2344 LogicVRegister fcmla(VectorFormat vform,
2345 LogicVRegister dst,
2346 const LogicVRegister& src1,
2347 const LogicVRegister& src2,
2348 int rot);
2349 LogicVRegister ins_element(VectorFormat vform,
2350 LogicVRegister dst,
2351 int dst_index,
2352 const LogicVRegister& src,
2353 int src_index);
2354 LogicVRegister ins_immediate(VectorFormat vform,
2355 LogicVRegister dst,
2356 int dst_index,
2357 uint64_t imm);
2358 LogicVRegister dup_element(VectorFormat vform,
2359 LogicVRegister dst,
2360 const LogicVRegister& src,
2361 int src_index);
2362 LogicVRegister dup_immediate(VectorFormat vform,
2363 LogicVRegister dst,
2364 uint64_t imm);
2365 LogicVRegister movi(VectorFormat vform, LogicVRegister dst, uint64_t imm);
2366 LogicVRegister mvni(VectorFormat vform, LogicVRegister dst, uint64_t imm);
2367 LogicVRegister orr(VectorFormat vform,
2368 LogicVRegister dst,
2369 const LogicVRegister& src,
2370 uint64_t imm);
2371 LogicVRegister sshl(VectorFormat vform,
2372 LogicVRegister dst,
2373 const LogicVRegister& src1,
2374 const LogicVRegister& src2);
2375 LogicVRegister ushl(VectorFormat vform,
2376 LogicVRegister dst,
2377 const LogicVRegister& src1,
2378 const LogicVRegister& src2);
2379 LogicVRegister sminmax(VectorFormat vform,
2380 LogicVRegister dst,
2381 const LogicVRegister& src1,
2382 const LogicVRegister& src2,
2383 bool max);
2384 LogicVRegister smax(VectorFormat vform,
2385 LogicVRegister dst,
2386 const LogicVRegister& src1,
2387 const LogicVRegister& src2);
2388 LogicVRegister smin(VectorFormat vform,
2389 LogicVRegister dst,
2390 const LogicVRegister& src1,
2391 const LogicVRegister& src2);
2392 LogicVRegister sminmaxp(VectorFormat vform,
2393 LogicVRegister dst,
2394 const LogicVRegister& src1,
2395 const LogicVRegister& src2,
2396 bool max);
2397 LogicVRegister smaxp(VectorFormat vform,
2398 LogicVRegister dst,
2399 const LogicVRegister& src1,
2400 const LogicVRegister& src2);
2401 LogicVRegister sminp(VectorFormat vform,
2402 LogicVRegister dst,
2403 const LogicVRegister& src1,
2404 const LogicVRegister& src2);
2405 LogicVRegister addp(VectorFormat vform,
2406 LogicVRegister dst,
2407 const LogicVRegister& src);
2408 LogicVRegister addv(VectorFormat vform,
2409 LogicVRegister dst,
2410 const LogicVRegister& src);
2411 LogicVRegister uaddlv(VectorFormat vform,
2412 LogicVRegister dst,
2413 const LogicVRegister& src);
2414 LogicVRegister saddlv(VectorFormat vform,
2415 LogicVRegister dst,
2416 const LogicVRegister& src);
2417 LogicVRegister sminmaxv(VectorFormat vform,
2418 LogicVRegister dst,
2419 const LogicVRegister& src,
2420 bool max);
2421 LogicVRegister smaxv(VectorFormat vform,
2422 LogicVRegister dst,
2423 const LogicVRegister& src);
2424 LogicVRegister sminv(VectorFormat vform,
2425 LogicVRegister dst,
2426 const LogicVRegister& src);
2427 LogicVRegister uxtl(VectorFormat vform,
2428 LogicVRegister dst,
2429 const LogicVRegister& src);
2430 LogicVRegister uxtl2(VectorFormat vform,
2431 LogicVRegister dst,
2432 const LogicVRegister& src);
2433 LogicVRegister sxtl(VectorFormat vform,
2434 LogicVRegister dst,
2435 const LogicVRegister& src);
2436 LogicVRegister sxtl2(VectorFormat vform,
2437 LogicVRegister dst,
2438 const LogicVRegister& src);
2439 LogicVRegister tbl(VectorFormat vform,
2440 LogicVRegister dst,
2441 const LogicVRegister& tab,
2442 const LogicVRegister& ind);
2443 LogicVRegister tbl(VectorFormat vform,
2444 LogicVRegister dst,
2445 const LogicVRegister& tab,
2446 const LogicVRegister& tab2,
2447 const LogicVRegister& ind);
2448 LogicVRegister tbl(VectorFormat vform,
2449 LogicVRegister dst,
2450 const LogicVRegister& tab,
2451 const LogicVRegister& tab2,
2452 const LogicVRegister& tab3,
2453 const LogicVRegister& ind);
2454 LogicVRegister tbl(VectorFormat vform,
2455 LogicVRegister dst,
2456 const LogicVRegister& tab,
2457 const LogicVRegister& tab2,
2458 const LogicVRegister& tab3,
2459 const LogicVRegister& tab4,
2460 const LogicVRegister& ind);
2461 LogicVRegister Table(VectorFormat vform,
2462 LogicVRegister dst,
2463 const LogicVRegister& ind,
2464 bool zero_out_of_bounds,
2465 const LogicVRegister* tab1,
2466 const LogicVRegister* tab2 = NULL,
2467 const LogicVRegister* tab3 = NULL,
2468 const LogicVRegister* tab4 = NULL);
2469 LogicVRegister tbx(VectorFormat vform,
2470 LogicVRegister dst,
2471 const LogicVRegister& tab,
2472 const LogicVRegister& ind);
2473 LogicVRegister tbx(VectorFormat vform,
2474 LogicVRegister dst,
2475 const LogicVRegister& tab,
2476 const LogicVRegister& tab2,
2477 const LogicVRegister& ind);
2478 LogicVRegister tbx(VectorFormat vform,
2479 LogicVRegister dst,
2480 const LogicVRegister& tab,
2481 const LogicVRegister& tab2,
2482 const LogicVRegister& tab3,
2483 const LogicVRegister& ind);
2484 LogicVRegister tbx(VectorFormat vform,
2485 LogicVRegister dst,
2486 const LogicVRegister& tab,
2487 const LogicVRegister& tab2,
2488 const LogicVRegister& tab3,
2489 const LogicVRegister& tab4,
2490 const LogicVRegister& ind);
2491 LogicVRegister uaddl(VectorFormat vform,
2492 LogicVRegister dst,
2493 const LogicVRegister& src1,
2494 const LogicVRegister& src2);
2495 LogicVRegister uaddl2(VectorFormat vform,
2496 LogicVRegister dst,
2497 const LogicVRegister& src1,
2498 const LogicVRegister& src2);
2499 LogicVRegister uaddw(VectorFormat vform,
2500 LogicVRegister dst,
2501 const LogicVRegister& src1,
2502 const LogicVRegister& src2);
2503 LogicVRegister uaddw2(VectorFormat vform,
2504 LogicVRegister dst,
2505 const LogicVRegister& src1,
2506 const LogicVRegister& src2);
2507 LogicVRegister saddl(VectorFormat vform,
2508 LogicVRegister dst,
2509 const LogicVRegister& src1,
2510 const LogicVRegister& src2);
2511 LogicVRegister saddl2(VectorFormat vform,
2512 LogicVRegister dst,
2513 const LogicVRegister& src1,
2514 const LogicVRegister& src2);
2515 LogicVRegister saddw(VectorFormat vform,
2516 LogicVRegister dst,
2517 const LogicVRegister& src1,
2518 const LogicVRegister& src2);
2519 LogicVRegister saddw2(VectorFormat vform,
2520 LogicVRegister dst,
2521 const LogicVRegister& src1,
2522 const LogicVRegister& src2);
2523 LogicVRegister usubl(VectorFormat vform,
2524 LogicVRegister dst,
2525 const LogicVRegister& src1,
2526 const LogicVRegister& src2);
2527 LogicVRegister usubl2(VectorFormat vform,
2528 LogicVRegister dst,
2529 const LogicVRegister& src1,
2530 const LogicVRegister& src2);
2531 LogicVRegister usubw(VectorFormat vform,
2532 LogicVRegister dst,
2533 const LogicVRegister& src1,
2534 const LogicVRegister& src2);
2535 LogicVRegister usubw2(VectorFormat vform,
2536 LogicVRegister dst,
2537 const LogicVRegister& src1,
2538 const LogicVRegister& src2);
2539 LogicVRegister ssubl(VectorFormat vform,
2540 LogicVRegister dst,
2541 const LogicVRegister& src1,
2542 const LogicVRegister& src2);
2543 LogicVRegister ssubl2(VectorFormat vform,
2544 LogicVRegister dst,
2545 const LogicVRegister& src1,
2546 const LogicVRegister& src2);
2547 LogicVRegister ssubw(VectorFormat vform,
2548 LogicVRegister dst,
2549 const LogicVRegister& src1,
2550 const LogicVRegister& src2);
2551 LogicVRegister ssubw2(VectorFormat vform,
2552 LogicVRegister dst,
2553 const LogicVRegister& src1,
2554 const LogicVRegister& src2);
2555 LogicVRegister uminmax(VectorFormat vform,
2556 LogicVRegister dst,
2557 const LogicVRegister& src1,
2558 const LogicVRegister& src2,
2559 bool max);
2560 LogicVRegister umax(VectorFormat vform,
2561 LogicVRegister dst,
2562 const LogicVRegister& src1,
2563 const LogicVRegister& src2);
2564 LogicVRegister umin(VectorFormat vform,
2565 LogicVRegister dst,
2566 const LogicVRegister& src1,
2567 const LogicVRegister& src2);
2568 LogicVRegister uminmaxp(VectorFormat vform,
2569 LogicVRegister dst,
2570 const LogicVRegister& src1,
2571 const LogicVRegister& src2,
2572 bool max);
2573 LogicVRegister umaxp(VectorFormat vform,
2574 LogicVRegister dst,
2575 const LogicVRegister& src1,
2576 const LogicVRegister& src2);
2577 LogicVRegister uminp(VectorFormat vform,
2578 LogicVRegister dst,
2579 const LogicVRegister& src1,
2580 const LogicVRegister& src2);
2581 LogicVRegister uminmaxv(VectorFormat vform,
2582 LogicVRegister dst,
2583 const LogicVRegister& src,
2584 bool max);
2585 LogicVRegister umaxv(VectorFormat vform,
2586 LogicVRegister dst,
2587 const LogicVRegister& src);
2588 LogicVRegister uminv(VectorFormat vform,
2589 LogicVRegister dst,
2590 const LogicVRegister& src);
2591 LogicVRegister trn1(VectorFormat vform,
2592 LogicVRegister dst,
2593 const LogicVRegister& src1,
2594 const LogicVRegister& src2);
2595 LogicVRegister trn2(VectorFormat vform,
2596 LogicVRegister dst,
2597 const LogicVRegister& src1,
2598 const LogicVRegister& src2);
2599 LogicVRegister zip1(VectorFormat vform,
2600 LogicVRegister dst,
2601 const LogicVRegister& src1,
2602 const LogicVRegister& src2);
2603 LogicVRegister zip2(VectorFormat vform,
2604 LogicVRegister dst,
2605 const LogicVRegister& src1,
2606 const LogicVRegister& src2);
2607 LogicVRegister uzp1(VectorFormat vform,
2608 LogicVRegister dst,
2609 const LogicVRegister& src1,
2610 const LogicVRegister& src2);
2611 LogicVRegister uzp2(VectorFormat vform,
2612 LogicVRegister dst,
2613 const LogicVRegister& src1,
2614 const LogicVRegister& src2);
2615 LogicVRegister shl(VectorFormat vform,
2616 LogicVRegister dst,
2617 const LogicVRegister& src,
2618 int shift);
2619 LogicVRegister scvtf(VectorFormat vform,
2620 LogicVRegister dst,
2621 const LogicVRegister& src,
2622 int fbits,
2623 FPRounding rounding_mode);
2624 LogicVRegister ucvtf(VectorFormat vform,
2625 LogicVRegister dst,
2626 const LogicVRegister& src,
2627 int fbits,
2628 FPRounding rounding_mode);
2629 LogicVRegister sshll(VectorFormat vform,
2630 LogicVRegister dst,
2631 const LogicVRegister& src,
2632 int shift);
2633 LogicVRegister sshll2(VectorFormat vform,
2634 LogicVRegister dst,
2635 const LogicVRegister& src,
2636 int shift);
2637 LogicVRegister shll(VectorFormat vform,
2638 LogicVRegister dst,
2639 const LogicVRegister& src);
2640 LogicVRegister shll2(VectorFormat vform,
2641 LogicVRegister dst,
2642 const LogicVRegister& src);
2643 LogicVRegister ushll(VectorFormat vform,
2644 LogicVRegister dst,
2645 const LogicVRegister& src,
2646 int shift);
2647 LogicVRegister ushll2(VectorFormat vform,
2648 LogicVRegister dst,
2649 const LogicVRegister& src,
2650 int shift);
2651 LogicVRegister sli(VectorFormat vform,
2652 LogicVRegister dst,
2653 const LogicVRegister& src,
2654 int shift);
2655 LogicVRegister sri(VectorFormat vform,
2656 LogicVRegister dst,
2657 const LogicVRegister& src,
2658 int shift);
2659 LogicVRegister sshr(VectorFormat vform,
2660 LogicVRegister dst,
2661 const LogicVRegister& src,
2662 int shift);
2663 LogicVRegister ushr(VectorFormat vform,
2664 LogicVRegister dst,
2665 const LogicVRegister& src,
2666 int shift);
2667 LogicVRegister ssra(VectorFormat vform,
2668 LogicVRegister dst,
2669 const LogicVRegister& src,
2670 int shift);
2671 LogicVRegister usra(VectorFormat vform,
2672 LogicVRegister dst,
2673 const LogicVRegister& src,
2674 int shift);
2675 LogicVRegister srsra(VectorFormat vform,
2676 LogicVRegister dst,
2677 const LogicVRegister& src,
2678 int shift);
2679 LogicVRegister ursra(VectorFormat vform,
2680 LogicVRegister dst,
2681 const LogicVRegister& src,
2682 int shift);
2683 LogicVRegister suqadd(VectorFormat vform,
2684 LogicVRegister dst,
2685 const LogicVRegister& src);
2686 LogicVRegister usqadd(VectorFormat vform,
2687 LogicVRegister dst,
2688 const LogicVRegister& src);
2689 LogicVRegister sqshl(VectorFormat vform,
2690 LogicVRegister dst,
2691 const LogicVRegister& src,
2692 int shift);
2693 LogicVRegister uqshl(VectorFormat vform,
2694 LogicVRegister dst,
2695 const LogicVRegister& src,
2696 int shift);
2697 LogicVRegister sqshlu(VectorFormat vform,
2698 LogicVRegister dst,
2699 const LogicVRegister& src,
2700 int shift);
2701 LogicVRegister abs(VectorFormat vform,
2702 LogicVRegister dst,
2703 const LogicVRegister& src);
2704 LogicVRegister neg(VectorFormat vform,
2705 LogicVRegister dst,
2706 const LogicVRegister& src);
2707 LogicVRegister extractnarrow(VectorFormat vform,
2708 LogicVRegister dst,
2709 bool dstIsSigned,
2710 const LogicVRegister& src,
2711 bool srcIsSigned);
2712 LogicVRegister xtn(VectorFormat vform,
2713 LogicVRegister dst,
2714 const LogicVRegister& src);
2715 LogicVRegister sqxtn(VectorFormat vform,
2716 LogicVRegister dst,
2717 const LogicVRegister& src);
2718 LogicVRegister uqxtn(VectorFormat vform,
2719 LogicVRegister dst,
2720 const LogicVRegister& src);
2721 LogicVRegister sqxtun(VectorFormat vform,
2722 LogicVRegister dst,
2723 const LogicVRegister& src);
2724 LogicVRegister absdiff(VectorFormat vform,
2725 LogicVRegister dst,
2726 const LogicVRegister& src1,
2727 const LogicVRegister& src2,
2728 bool issigned);
2729 LogicVRegister saba(VectorFormat vform,
2730 LogicVRegister dst,
2731 const LogicVRegister& src1,
2732 const LogicVRegister& src2);
2733 LogicVRegister uaba(VectorFormat vform,
2734 LogicVRegister dst,
2735 const LogicVRegister& src1,
2736 const LogicVRegister& src2);
2737 LogicVRegister shrn(VectorFormat vform,
2738 LogicVRegister dst,
2739 const LogicVRegister& src,
2740 int shift);
2741 LogicVRegister shrn2(VectorFormat vform,
2742 LogicVRegister dst,
2743 const LogicVRegister& src,
2744 int shift);
2745 LogicVRegister rshrn(VectorFormat vform,
2746 LogicVRegister dst,
2747 const LogicVRegister& src,
2748 int shift);
2749 LogicVRegister rshrn2(VectorFormat vform,
2750 LogicVRegister dst,
2751 const LogicVRegister& src,
2752 int shift);
2753 LogicVRegister uqshrn(VectorFormat vform,
2754 LogicVRegister dst,
2755 const LogicVRegister& src,
2756 int shift);
2757 LogicVRegister uqshrn2(VectorFormat vform,
2758 LogicVRegister dst,
2759 const LogicVRegister& src,
2760 int shift);
2761 LogicVRegister uqrshrn(VectorFormat vform,
2762 LogicVRegister dst,
2763 const LogicVRegister& src,
2764 int shift);
2765 LogicVRegister uqrshrn2(VectorFormat vform,
2766 LogicVRegister dst,
2767 const LogicVRegister& src,
2768 int shift);
2769 LogicVRegister sqshrn(VectorFormat vform,
2770 LogicVRegister dst,
2771 const LogicVRegister& src,
2772 int shift);
2773 LogicVRegister sqshrn2(VectorFormat vform,
2774 LogicVRegister dst,
2775 const LogicVRegister& src,
2776 int shift);
2777 LogicVRegister sqrshrn(VectorFormat vform,
2778 LogicVRegister dst,
2779 const LogicVRegister& src,
2780 int shift);
2781 LogicVRegister sqrshrn2(VectorFormat vform,
2782 LogicVRegister dst,
2783 const LogicVRegister& src,
2784 int shift);
2785 LogicVRegister sqshrun(VectorFormat vform,
2786 LogicVRegister dst,
2787 const LogicVRegister& src,
2788 int shift);
2789 LogicVRegister sqshrun2(VectorFormat vform,
2790 LogicVRegister dst,
2791 const LogicVRegister& src,
2792 int shift);
2793 LogicVRegister sqrshrun(VectorFormat vform,
2794 LogicVRegister dst,
2795 const LogicVRegister& src,
2796 int shift);
2797 LogicVRegister sqrshrun2(VectorFormat vform,
2798 LogicVRegister dst,
2799 const LogicVRegister& src,
2800 int shift);
2801 LogicVRegister sqrdmulh(VectorFormat vform,
2802 LogicVRegister dst,
2803 const LogicVRegister& src1,
2804 const LogicVRegister& src2,
2805 bool round = true);
2806 LogicVRegister dot(VectorFormat vform,
2807 LogicVRegister dst,
2808 const LogicVRegister& src1,
2809 const LogicVRegister& src2,
2810 bool is_signed);
2811 LogicVRegister sdot(VectorFormat vform,
2812 LogicVRegister dst,
2813 const LogicVRegister& src1,
2814 const LogicVRegister& src2);
2815 LogicVRegister udot(VectorFormat vform,
2816 LogicVRegister dst,
2817 const LogicVRegister& src1,
2818 const LogicVRegister& src2);
2819 LogicVRegister sqrdmlash(VectorFormat vform,
2820 LogicVRegister dst,
2821 const LogicVRegister& src1,
2822 const LogicVRegister& src2,
2823 bool round = true,
2824 bool sub_op = false);
2825 LogicVRegister sqrdmlah(VectorFormat vform,
2826 LogicVRegister dst,
2827 const LogicVRegister& src1,
2828 const LogicVRegister& src2,
2829 bool round = true);
2830 LogicVRegister sqrdmlsh(VectorFormat vform,
2831 LogicVRegister dst,
2832 const LogicVRegister& src1,
2833 const LogicVRegister& src2,
2834 bool round = true);
2835 LogicVRegister sqdmulh(VectorFormat vform,
2836 LogicVRegister dst,
2837 const LogicVRegister& src1,
2838 const LogicVRegister& src2);
2839 #define NEON_3VREG_LOGIC_LIST(V) \
2840 V(addhn) \
2841 V(addhn2) \
2842 V(raddhn) \
2843 V(raddhn2) \
2844 V(subhn) \
2845 V(subhn2) \
2846 V(rsubhn) \
2847 V(rsubhn2) \
2848 V(pmull) \
2849 V(pmull2) \
2850 V(sabal) \
2851 V(sabal2) \
2852 V(uabal) \
2853 V(uabal2) \
2854 V(sabdl) \
2855 V(sabdl2) \
2856 V(uabdl) \
2857 V(uabdl2) \
2858 V(smull) \
2859 V(smull2) \
2860 V(umull) \
2861 V(umull2) \
2862 V(smlal) \
2863 V(smlal2) \
2864 V(umlal) \
2865 V(umlal2) \
2866 V(smlsl) \
2867 V(smlsl2) \
2868 V(umlsl) \
2869 V(umlsl2) \
2870 V(sqdmlal) \
2871 V(sqdmlal2) \
2872 V(sqdmlsl) \
2873 V(sqdmlsl2) \
2874 V(sqdmull) \
2875 V(sqdmull2)
2876
2877 #define DEFINE_LOGIC_FUNC(FXN) \
2878 LogicVRegister FXN(VectorFormat vform, \
2879 LogicVRegister dst, \
2880 const LogicVRegister& src1, \
2881 const LogicVRegister& src2);
2882 NEON_3VREG_LOGIC_LIST(DEFINE_LOGIC_FUNC)
2883 #undef DEFINE_LOGIC_FUNC
2884
2885 #define NEON_FP3SAME_LIST(V) \
2886 V(fadd, FPAdd, false) \
2887 V(fsub, FPSub, true) \
2888 V(fmul, FPMul, true) \
2889 V(fmulx, FPMulx, true) \
2890 V(fdiv, FPDiv, true) \
2891 V(fmax, FPMax, false) \
2892 V(fmin, FPMin, false) \
2893 V(fmaxnm, FPMaxNM, false) \
2894 V(fminnm, FPMinNM, false)
2895
2896 #define DECLARE_NEON_FP_VECTOR_OP(FN, OP, PROCNAN) \
2897 template <typename T> \
2898 LogicVRegister FN(VectorFormat vform, \
2899 LogicVRegister dst, \
2900 const LogicVRegister& src1, \
2901 const LogicVRegister& src2); \
2902 LogicVRegister FN(VectorFormat vform, \
2903 LogicVRegister dst, \
2904 const LogicVRegister& src1, \
2905 const LogicVRegister& src2);
2906 NEON_FP3SAME_LIST(DECLARE_NEON_FP_VECTOR_OP)
2907 #undef DECLARE_NEON_FP_VECTOR_OP
2908
2909 #define NEON_FPPAIRWISE_LIST(V) \
2910 V(faddp, fadd, FPAdd) \
2911 V(fmaxp, fmax, FPMax) \
2912 V(fmaxnmp, fmaxnm, FPMaxNM) \
2913 V(fminp, fmin, FPMin) \
2914 V(fminnmp, fminnm, FPMinNM)
2915
2916 #define DECLARE_NEON_FP_PAIR_OP(FNP, FN, OP) \
2917 LogicVRegister FNP(VectorFormat vform, \
2918 LogicVRegister dst, \
2919 const LogicVRegister& src1, \
2920 const LogicVRegister& src2); \
2921 LogicVRegister FNP(VectorFormat vform, \
2922 LogicVRegister dst, \
2923 const LogicVRegister& src);
2924 NEON_FPPAIRWISE_LIST(DECLARE_NEON_FP_PAIR_OP)
2925 #undef DECLARE_NEON_FP_PAIR_OP
2926
2927 enum FrintMode {
2928 kFrintToInteger = 0,
2929 kFrintToInt32 = 32,
2930 kFrintToInt64 = 64
2931 };
2932
2933 template <typename T>
2934 LogicVRegister frecps(VectorFormat vform,
2935 LogicVRegister dst,
2936 const LogicVRegister& src1,
2937 const LogicVRegister& src2);
2938 LogicVRegister frecps(VectorFormat vform,
2939 LogicVRegister dst,
2940 const LogicVRegister& src1,
2941 const LogicVRegister& src2);
2942 template <typename T>
2943 LogicVRegister frsqrts(VectorFormat vform,
2944 LogicVRegister dst,
2945 const LogicVRegister& src1,
2946 const LogicVRegister& src2);
2947 LogicVRegister frsqrts(VectorFormat vform,
2948 LogicVRegister dst,
2949 const LogicVRegister& src1,
2950 const LogicVRegister& src2);
2951 template <typename T>
2952 LogicVRegister fmla(VectorFormat vform,
2953 LogicVRegister dst,
2954 const LogicVRegister& src1,
2955 const LogicVRegister& src2);
2956 LogicVRegister fmla(VectorFormat vform,
2957 LogicVRegister dst,
2958 const LogicVRegister& src1,
2959 const LogicVRegister& src2);
2960 template <typename T>
2961 LogicVRegister fmls(VectorFormat vform,
2962 LogicVRegister dst,
2963 const LogicVRegister& src1,
2964 const LogicVRegister& src2);
2965 LogicVRegister fmls(VectorFormat vform,
2966 LogicVRegister dst,
2967 const LogicVRegister& src1,
2968 const LogicVRegister& src2);
2969 LogicVRegister fnmul(VectorFormat vform,
2970 LogicVRegister dst,
2971 const LogicVRegister& src1,
2972 const LogicVRegister& src2);
2973
2974 LogicVRegister fmlal(VectorFormat vform,
2975 LogicVRegister dst,
2976 const LogicVRegister& src1,
2977 const LogicVRegister& src2);
2978 LogicVRegister fmlal2(VectorFormat vform,
2979 LogicVRegister dst,
2980 const LogicVRegister& src1,
2981 const LogicVRegister& src2);
2982 LogicVRegister fmlsl(VectorFormat vform,
2983 LogicVRegister dst,
2984 const LogicVRegister& src1,
2985 const LogicVRegister& src2);
2986 LogicVRegister fmlsl2(VectorFormat vform,
2987 LogicVRegister dst,
2988 const LogicVRegister& src1,
2989 const LogicVRegister& src2);
2990
2991 template <typename T>
2992 LogicVRegister fcmp(VectorFormat vform,
2993 LogicVRegister dst,
2994 const LogicVRegister& src1,
2995 const LogicVRegister& src2,
2996 Condition cond);
2997 LogicVRegister fcmp(VectorFormat vform,
2998 LogicVRegister dst,
2999 const LogicVRegister& src1,
3000 const LogicVRegister& src2,
3001 Condition cond);
3002 LogicVRegister fabscmp(VectorFormat vform,
3003 LogicVRegister dst,
3004 const LogicVRegister& src1,
3005 const LogicVRegister& src2,
3006 Condition cond);
3007 LogicVRegister fcmp_zero(VectorFormat vform,
3008 LogicVRegister dst,
3009 const LogicVRegister& src,
3010 Condition cond);
3011
3012 template <typename T>
3013 LogicVRegister fneg(VectorFormat vform,
3014 LogicVRegister dst,
3015 const LogicVRegister& src);
3016 LogicVRegister fneg(VectorFormat vform,
3017 LogicVRegister dst,
3018 const LogicVRegister& src);
3019 template <typename T>
3020 LogicVRegister frecpx(VectorFormat vform,
3021 LogicVRegister dst,
3022 const LogicVRegister& src);
3023 LogicVRegister frecpx(VectorFormat vform,
3024 LogicVRegister dst,
3025 const LogicVRegister& src);
3026 template <typename T>
3027 LogicVRegister fabs_(VectorFormat vform,
3028 LogicVRegister dst,
3029 const LogicVRegister& src);
3030 LogicVRegister fabs_(VectorFormat vform,
3031 LogicVRegister dst,
3032 const LogicVRegister& src);
3033 LogicVRegister fabd(VectorFormat vform,
3034 LogicVRegister dst,
3035 const LogicVRegister& src1,
3036 const LogicVRegister& src2);
3037
3038 LogicVRegister frint(VectorFormat vform,
3039 LogicVRegister dst,
3040 const LogicVRegister& src,
3041 FPRounding rounding_mode,
3042 bool inexact_exception = false,
3043 FrintMode frint_mode = kFrintToInteger);
3044 LogicVRegister fcvts(VectorFormat vform,
3045 LogicVRegister dst,
3046 const LogicVRegister& src,
3047 FPRounding rounding_mode,
3048 int fbits = 0);
3049 LogicVRegister fcvtu(VectorFormat vform,
3050 LogicVRegister dst,
3051 const LogicVRegister& src,
3052 FPRounding rounding_mode,
3053 int fbits = 0);
3054 LogicVRegister fcvtl(VectorFormat vform,
3055 LogicVRegister dst,
3056 const LogicVRegister& src);
3057 LogicVRegister fcvtl2(VectorFormat vform,
3058 LogicVRegister dst,
3059 const LogicVRegister& src);
3060 LogicVRegister fcvtn(VectorFormat vform,
3061 LogicVRegister dst,
3062 const LogicVRegister& src);
3063 LogicVRegister fcvtn2(VectorFormat vform,
3064 LogicVRegister dst,
3065 const LogicVRegister& src);
3066 LogicVRegister fcvtxn(VectorFormat vform,
3067 LogicVRegister dst,
3068 const LogicVRegister& src);
3069 LogicVRegister fcvtxn2(VectorFormat vform,
3070 LogicVRegister dst,
3071 const LogicVRegister& src);
3072 LogicVRegister fsqrt(VectorFormat vform,
3073 LogicVRegister dst,
3074 const LogicVRegister& src);
3075 LogicVRegister frsqrte(VectorFormat vform,
3076 LogicVRegister dst,
3077 const LogicVRegister& src);
3078 LogicVRegister frecpe(VectorFormat vform,
3079 LogicVRegister dst,
3080 const LogicVRegister& src,
3081 FPRounding rounding);
3082 LogicVRegister ursqrte(VectorFormat vform,
3083 LogicVRegister dst,
3084 const LogicVRegister& src);
3085 LogicVRegister urecpe(VectorFormat vform,
3086 LogicVRegister dst,
3087 const LogicVRegister& src);
3088
3089 template <typename T>
3090 struct TFPMinMaxOp {
3091 typedef T (Simulator::*type)(T a, T b);
3092 };
3093
3094 template <typename T>
3095 LogicVRegister fminmaxv(VectorFormat vform,
3096 LogicVRegister dst,
3097 const LogicVRegister& src,
3098 typename TFPMinMaxOp<T>::type Op);
3099
3100 LogicVRegister fminv(VectorFormat vform,
3101 LogicVRegister dst,
3102 const LogicVRegister& src);
3103 LogicVRegister fmaxv(VectorFormat vform,
3104 LogicVRegister dst,
3105 const LogicVRegister& src);
3106 LogicVRegister fminnmv(VectorFormat vform,
3107 LogicVRegister dst,
3108 const LogicVRegister& src);
3109 LogicVRegister fmaxnmv(VectorFormat vform,
3110 LogicVRegister dst,
3111 const LogicVRegister& src);
3112
3113 static const uint32_t CRC32_POLY = 0x04C11DB7;
3114 static const uint32_t CRC32C_POLY = 0x1EDC6F41;
3115 uint32_t Poly32Mod2(unsigned n, uint64_t data, uint32_t poly);
3116 template <typename T>
3117 uint32_t Crc32Checksum(uint32_t acc, T val, uint32_t poly);
3118 uint32_t Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly);
3119
3120 void SysOp_W(int op, int64_t val);
3121
3122 template <typename T>
3123 T FPRecipSqrtEstimate(T op);
3124 template <typename T>
3125 T FPRecipEstimate(T op, FPRounding rounding);
3126 template <typename T, typename R>
3127 R FPToFixed(T op, int fbits, bool is_signed, FPRounding rounding);
3128
3129 void FPCompare(double val0, double val1, FPTrapFlags trap);
3130 double FPRoundInt(double value, FPRounding round_mode);
3131 double FPRoundInt(double value, FPRounding round_mode, FrintMode frint_mode);
3132 double FPRoundIntCommon(double value, FPRounding round_mode);
3133 double recip_sqrt_estimate(double a);
3134 double recip_estimate(double a);
3135 double FPRecipSqrtEstimate(double a);
3136 double FPRecipEstimate(double a);
3137 double FixedToDouble(int64_t src, int fbits, FPRounding round_mode);
3138 double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode);
3139 float FixedToFloat(int64_t src, int fbits, FPRounding round_mode);
3140 float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode);
3141 ::vixl::internal::SimFloat16 FixedToFloat16(int64_t src,
3142 int fbits,
3143 FPRounding round_mode);
3144 ::vixl::internal::SimFloat16 UFixedToFloat16(uint64_t src,
3145 int fbits,
3146 FPRounding round_mode);
3147 int16_t FPToInt16(double value, FPRounding rmode);
3148 int32_t FPToInt32(double value, FPRounding rmode);
3149 int64_t FPToInt64(double value, FPRounding rmode);
3150 uint16_t FPToUInt16(double value, FPRounding rmode);
3151 uint32_t FPToUInt32(double value, FPRounding rmode);
3152 uint64_t FPToUInt64(double value, FPRounding rmode);
3153 int32_t FPToFixedJS(double value);
3154
3155 template <typename T>
3156 T FPAdd(T op1, T op2);
3157
3158 template <typename T>
3159 T FPNeg(T op);
3160
3161 template <typename T>
3162 T FPDiv(T op1, T op2);
3163
3164 template <typename T>
3165 T FPMax(T a, T b);
3166
3167 template <typename T>
3168 T FPMaxNM(T a, T b);
3169
3170 template <typename T>
3171 T FPMin(T a, T b);
3172
3173 template <typename T>
3174 T FPMinNM(T a, T b);
3175
3176 template <typename T>
3177 T FPMul(T op1, T op2);
3178
3179 template <typename T>
3180 T FPMulx(T op1, T op2);
3181
3182 template <typename T>
3183 T FPMulAdd(T a, T op1, T op2);
3184
3185 template <typename T>
3186 T FPSqrt(T op);
3187
3188 template <typename T>
3189 T FPSub(T op1, T op2);
3190
3191 template <typename T>
3192 T FPRecipStepFused(T op1, T op2);
3193
3194 template <typename T>
3195 T FPRSqrtStepFused(T op1, T op2);
3196
3197 // This doesn't do anything at the moment. We'll need it if we want support
3198 // for cumulative exception bits or floating-point exceptions.
3199 void FPProcessException() {}
3200
3201 bool FPProcessNaNs(const Instruction* instr);
3202
3203 // Pseudo Printf instruction
3204 void DoPrintf(const Instruction* instr);
3205
3206 // Pseudo-instructions to configure CPU features dynamically.
3207 void DoConfigureCPUFeatures(const Instruction* instr);
3208
3209 void DoSaveCPUFeatures(const Instruction* instr);
3210 void DoRestoreCPUFeatures(const Instruction* instr);
3211
3212 // Simulate a runtime call.
3213 void DoRuntimeCall(const Instruction* instr);
3214
3215 // Processor state ---------------------------------------
3216
3217 // Simulated monitors for exclusive access instructions.
3218 SimExclusiveLocalMonitor local_monitor_;
3219 SimExclusiveGlobalMonitor global_monitor_;
3220
3221 // Output stream.
3222 FILE* stream_;
3223 PrintDisassembler* print_disasm_;
3224
3225 // Instruction statistics instrumentation.
3226 Instrument* instrumentation_;
3227
3228 // General purpose registers. Register 31 is the stack pointer.
3229 SimRegister registers_[kNumberOfRegisters];
3230
3231 // Vector registers
3232 SimVRegister vregisters_[kNumberOfVRegisters];
3233
3234 // Program Status Register.
3235 // bits[31, 27]: Condition flags N, Z, C, and V.
3236 // (Negative, Zero, Carry, Overflow)
3237 SimSystemRegister nzcv_;
3238
3239 // Floating-Point Control Register
3240 SimSystemRegister fpcr_;
3241
3242 // Only a subset of FPCR features are supported by the simulator. This helper
3243 // checks that the FPCR settings are supported.
3244 //
3245 // This is checked when floating-point instructions are executed, not when
3246 // FPCR is set. This allows generated code to modify FPCR for external
3247 // functions, or to save and restore it when entering and leaving generated
3248 // code.
3249 void AssertSupportedFPCR() {
3250 // No flush-to-zero support.
3251 VIXL_ASSERT(ReadFpcr().GetFZ() == 0);
3252 // Ties-to-even rounding only.
3253 VIXL_ASSERT(ReadFpcr().GetRMode() == FPTieEven);
3254 // No alternative half-precision support.
3255 VIXL_ASSERT(ReadFpcr().GetAHP() == 0);
3256 }
3257
3258 static int CalcNFlag(uint64_t result, unsigned reg_size) {
3259 return (result >> (reg_size - 1)) & 1;
3260 }
3261
3262 static int CalcZFlag(uint64_t result) { return (result == 0) ? 1 : 0; }
3263
3264 static const uint32_t kConditionFlagsMask = 0xf0000000;
3265
3266 // Stack
3267 byte* stack_;
3268 static const int stack_protection_size_ = 256;
3269 // 2 KB stack.
3270 static const int stack_size_ = 2 * 1024 + 2 * stack_protection_size_;
3271 byte* stack_limit_;
3272
3273 Decoder* decoder_;
3274 // Indicates if the pc has been modified by the instruction and should not be
3275 // automatically incremented.
3276 bool pc_modified_;
3277 const Instruction* pc_;
3278
3279 // Branch type register, used for branch target identification.
3280 BType btype_;
3281
3282 // Next value of branch type register after the current instruction has been
3283 // decoded.
3284 BType next_btype_;
3285
3286 // Global flag for enabling guarded pages.
3287 // TODO: implement guarding at page granularity, rather than globally.
3288 bool guard_pages_;
3289
3290 static const char* xreg_names[];
3291 static const char* wreg_names[];
3292 static const char* hreg_names[];
3293 static const char* sreg_names[];
3294 static const char* dreg_names[];
3295 static const char* vreg_names[];
3296
3297 private:
3298 static const PACKey kPACKeyIA;
3299 static const PACKey kPACKeyIB;
3300 static const PACKey kPACKeyDA;
3301 static const PACKey kPACKeyDB;
3302 static const PACKey kPACKeyGA;
3303
3304 template <typename T>
3305 static T FPDefaultNaN();
3306
3307 // Standard NaN processing.
3308 template <typename T>
3309 T FPProcessNaN(T op) {
3310 VIXL_ASSERT(IsNaN(op));
3311 if (IsSignallingNaN(op)) {
3312 FPProcessException();
3313 }
3314 return (ReadDN() == kUseDefaultNaN) ? FPDefaultNaN<T>() : ToQuietNaN(op);
3315 }
3316
3317 template <typename T>
3318 T FPProcessNaNs(T op1, T op2) {
3319 if (IsSignallingNaN(op1)) {
3320 return FPProcessNaN(op1);
3321 } else if (IsSignallingNaN(op2)) {
3322 return FPProcessNaN(op2);
3323 } else if (IsNaN(op1)) {
3324 VIXL_ASSERT(IsQuietNaN(op1));
3325 return FPProcessNaN(op1);
3326 } else if (IsNaN(op2)) {
3327 VIXL_ASSERT(IsQuietNaN(op2));
3328 return FPProcessNaN(op2);
3329 } else {
3330 return 0.0;
3331 }
3332 }
3333
3334 template <typename T>
3335 T FPProcessNaNs3(T op1, T op2, T op3) {
3336 if (IsSignallingNaN(op1)) {
3337 return FPProcessNaN(op1);
3338 } else if (IsSignallingNaN(op2)) {
3339 return FPProcessNaN(op2);
3340 } else if (IsSignallingNaN(op3)) {
3341 return FPProcessNaN(op3);
3342 } else if (IsNaN(op1)) {
3343 VIXL_ASSERT(IsQuietNaN(op1));
3344 return FPProcessNaN(op1);
3345 } else if (IsNaN(op2)) {
3346 VIXL_ASSERT(IsQuietNaN(op2));
3347 return FPProcessNaN(op2);
3348 } else if (IsNaN(op3)) {
3349 VIXL_ASSERT(IsQuietNaN(op3));
3350 return FPProcessNaN(op3);
3351 } else {
3352 return 0.0;
3353 }
3354 }
3355
3356 bool coloured_trace_;
3357
3358 // A set of TraceParameters flags.
3359 int trace_parameters_;
3360
3361 // Indicates whether the instruction instrumentation is active.
3362 bool instruction_stats_;
3363
3364 // Indicates whether the exclusive-access warning has been printed.
3365 bool print_exclusive_access_warning_;
3366 void PrintExclusiveAccessWarning();
3367
3368 CPUFeaturesAuditor cpu_features_auditor_;
3369 std::vector<CPUFeatures> saved_cpu_features_;
3370
3371 // The simulated state of RNDR and RNDRRS for generating a random number.
3372 uint16_t rndr_state_[3];
3373 };
3374
3375 #if defined(VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT) && __cplusplus < 201402L
3376 // Base case of the recursive template used to emulate C++14
3377 // `std::index_sequence`.
3378 template <size_t... I>
3379 struct Simulator::emulated_make_index_sequence_helper<0, I...>
3380 : Simulator::emulated_index_sequence<I...> {};
3381 #endif
3382
3383 } // namespace aarch64
3384 } // namespace vixl
3385
3386 #endif // VIXL_INCLUDE_SIMULATOR_AARCH64
3387
3388 #endif // VIXL_AARCH64_SIMULATOR_AARCH64_H_
3389