v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
simulator-arm64.h
Go to the documentation of this file.
1// Copyright 2013 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_EXECUTION_ARM64_SIMULATOR_ARM64_H_
6#define V8_EXECUTION_ARM64_SIMULATOR_ARM64_H_
7
8// globals.h defines USE_SIMULATOR.
10
11#if defined(USE_SIMULATOR)
12
13#include <stdarg.h>
14
15#include <vector>
16
24#include "src/utils/utils.h"
25
26namespace v8 {
27namespace internal {
28
29// Assemble the specified IEEE-754 components into the target type and apply
30// appropriate rounding.
31// sign: 0 = positive, 1 = negative
32// exponent: Unbiased IEEE-754 exponent.
33// mantissa: The mantissa of the input. The top bit (which is not encoded for
34// normal IEEE-754 values) must not be omitted. This bit has the
35// value 'pow(2, exponent)'.
36//
37// The input value is assumed to be a normalized value. That is, the input may
38// not be infinity or NaN. If the source value is subnormal, it must be
39// normalized before calling this function such that the highest set bit in the
40// mantissa has the value 'pow(2, exponent)'.
41//
42// Callers should use FPRoundToFloat or FPRoundToDouble directly, rather than
43// calling a templated FPRound.
44template <class T, int ebits, int mbits>
45T FPRound(int64_t sign, int64_t exponent, uint64_t mantissa,
46 FPRounding round_mode) {
47 static_assert((sizeof(T) * 8) >= (1 + ebits + mbits),
48 "destination type T not large enough");
49 static_assert(sizeof(T) <= sizeof(uint64_t),
50 "maximum size of destination type T is 64 bits");
51 static_assert(std::is_unsigned<T>::value,
52 "destination type T must be unsigned");
53
54 DCHECK((sign == 0) || (sign == 1));
55
56 // Only FPTieEven and FPRoundOdd rounding modes are implemented.
57 DCHECK((round_mode == FPTieEven) || (round_mode == FPRoundOdd));
58
59 // Rounding can promote subnormals to normals, and normals to infinities. For
60 // example, a double with exponent 127 (FLT_MAX_EXP) would appear to be
61 // encodable as a float, but rounding based on the low-order mantissa bits
62 // could make it overflow. With ties-to-even rounding, this value would become
63 // an infinity.
64
65 // ---- Rounding Method ----
66 //
67 // The exponent is irrelevant in the rounding operation, so we treat the
68 // lowest-order bit that will fit into the result ('onebit') as having
69 // the value '1'. Similarly, the highest-order bit that won't fit into
70 // the result ('halfbit') has the value '0.5'. The 'point' sits between
71 // 'onebit' and 'halfbit':
72 //
73 // These bits fit into the result.
74 // |---------------------|
75 // mantissa = 0bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
76 // ||
77 // / |
78 // / halfbit
79 // onebit
80 //
81 // For subnormal outputs, the range of representable bits is smaller and
82 // the position of onebit and halfbit depends on the exponent of the
83 // input, but the method is otherwise similar.
84 //
85 // onebit(frac)
86 // |
87 // | halfbit(frac) halfbit(adjusted)
88 // | / /
89 // | | |
90 // 0b00.0 (exact) -> 0b00.0 (exact) -> 0b00
91 // 0b00.0... -> 0b00.0... -> 0b00
92 // 0b00.1 (exact) -> 0b00.0111..111 -> 0b00
93 // 0b00.1... -> 0b00.1... -> 0b01
94 // 0b01.0 (exact) -> 0b01.0 (exact) -> 0b01
95 // 0b01.0... -> 0b01.0... -> 0b01
96 // 0b01.1 (exact) -> 0b01.1 (exact) -> 0b10
97 // 0b01.1... -> 0b01.1... -> 0b10
98 // 0b10.0 (exact) -> 0b10.0 (exact) -> 0b10
99 // 0b10.0... -> 0b10.0... -> 0b10
100 // 0b10.1 (exact) -> 0b10.0111..111 -> 0b10
101 // 0b10.1... -> 0b10.1... -> 0b11
102 // 0b11.0 (exact) -> 0b11.0 (exact) -> 0b11
103 // ... / | / |
104 // / | / |
105 // / |
106 // adjusted = frac - (halfbit(mantissa) & ~onebit(frac)); / |
107 //
108 // mantissa = (mantissa >> shift) + halfbit(adjusted);
109
110 const int mantissa_offset = 0;
111 const int exponent_offset = mantissa_offset + mbits;
112 const int sign_offset = exponent_offset + ebits;
113 DCHECK_EQ(sign_offset, static_cast<int>(sizeof(T) * 8 - 1));
114
115 // Bail out early for zero inputs.
116 if (mantissa == 0) {
117 return static_cast<T>(sign << sign_offset);
118 }
119
120 // If all bits in the exponent are set, the value is infinite or NaN.
121 // This is true for all binary IEEE-754 formats.
122 const int infinite_exponent = (1 << ebits) - 1;
123 const int max_normal_exponent = infinite_exponent - 1;
124
125 // Apply the exponent bias to encode it for the result. Doing this early makes
126 // it easy to detect values that will be infinite or subnormal.
127 exponent += max_normal_exponent >> 1;
128
129 if (exponent > max_normal_exponent) {
130 // Overflow: the input is too large for the result type to represent.
131 if (round_mode == FPTieEven) {
132 // FPTieEven rounding mode handles overflows using infinities.
133 exponent = infinite_exponent;
134 mantissa = 0;
135 } else {
136 DCHECK_EQ(round_mode, FPRoundOdd);
137 // FPRoundOdd rounding mode handles overflows using the largest magnitude
138 // normal number.
139 exponent = max_normal_exponent;
140 mantissa = (UINT64_C(1) << exponent_offset) - 1;
141 }
142 return static_cast<T>((sign << sign_offset) |
143 (exponent << exponent_offset) |
144 (mantissa << mantissa_offset));
145 }
146
147 // Calculate the shift required to move the top mantissa bit to the proper
148 // place in the destination type.
149 const int highest_significant_bit = 63 - CountLeadingZeros(mantissa, 64);
150 int shift = highest_significant_bit - mbits;
151
152 if (exponent <= 0) {
153 // The output will be subnormal (before rounding).
154 // For subnormal outputs, the shift must be adjusted by the exponent. The +1
155 // is necessary because the exponent of a subnormal value (encoded as 0) is
156 // the same as the exponent of the smallest normal value (encoded as 1).
157 shift += -exponent + 1;
158
159 // Handle inputs that would produce a zero output.
160 //
161 // Shifts higher than highest_significant_bit+1 will always produce a zero
162 // result. A shift of exactly highest_significant_bit+1 might produce a
163 // non-zero result after rounding.
164 if (shift > (highest_significant_bit + 1)) {
165 if (round_mode == FPTieEven) {
166 // The result will always be +/-0.0.
167 return static_cast<T>(sign << sign_offset);
168 } else {
169 DCHECK_EQ(round_mode, FPRoundOdd);
170 DCHECK_NE(mantissa, 0U);
171 // For FPRoundOdd, if the mantissa is too small to represent and
172 // non-zero return the next "odd" value.
173 return static_cast<T>((sign << sign_offset) | 1);
174 }
175 }
176
177 // Properly encode the exponent for a subnormal output.
178 exponent = 0;
179 } else {
180 // Clear the topmost mantissa bit, since this is not encoded in IEEE-754
181 // normal values.
182 mantissa &= ~(UINT64_C(1) << highest_significant_bit);
183 }
184
185 if (shift > 0) {
186 if (round_mode == FPTieEven) {
187 // We have to shift the mantissa to the right. Some precision is lost, so
188 // we need to apply rounding.
189 uint64_t onebit_mantissa = (mantissa >> (shift)) & 1;
190 uint64_t halfbit_mantissa = (mantissa >> (shift - 1)) & 1;
191 uint64_t adjustment = (halfbit_mantissa & ~onebit_mantissa);
192 uint64_t adjusted = mantissa - adjustment;
193 T halfbit_adjusted = (adjusted >> (shift - 1)) & 1;
194
195 T result =
196 static_cast<T>((sign << sign_offset) | (exponent << exponent_offset) |
197 ((mantissa >> shift) << mantissa_offset));
198
199 // A very large mantissa can overflow during rounding. If this happens,
200 // the exponent should be incremented and the mantissa set to 1.0
201 // (encoded as 0). Applying halfbit_adjusted after assembling the float
202 // has the nice side-effect that this case is handled for free.
203 //
204 // This also handles cases where a very large finite value overflows to
205 // infinity, or where a very large subnormal value overflows to become
206 // normal.
207 return result + halfbit_adjusted;
208 } else {
209 DCHECK_EQ(round_mode, FPRoundOdd);
210 // If any bits at position halfbit or below are set, onebit (ie. the
211 // bottom bit of the resulting mantissa) must be set.
212 uint64_t fractional_bits = mantissa & ((UINT64_C(1) << shift) - 1);
213 if (fractional_bits != 0) {
214 mantissa |= UINT64_C(1) << shift;
215 }
216
217 return static_cast<T>((sign << sign_offset) |
218 (exponent << exponent_offset) |
219 ((mantissa >> shift) << mantissa_offset));
220 }
221 } else {
222 // We have to shift the mantissa to the left (or not at all). The input
223 // mantissa is exactly representable in the output mantissa, so apply no
224 // rounding correction.
225 return static_cast<T>((sign << sign_offset) |
226 (exponent << exponent_offset) |
227 ((mantissa << -shift) << mantissa_offset));
228 }
229}
230
231class CachePage {
232 // TODO(all): Simulate instruction cache.
233};
234
235// Representation of memory, with typed getters and setters for access.
236class SimMemory {
237 public:
238 template <typename T>
239 static T AddressUntag(T address) {
240 // Cast the address using a C-style cast. A reinterpret_cast would be
241 // appropriate, but it can't cast one integral type to another.
242 uint64_t bits = (uint64_t)address;
243 return (T)(bits & ~kAddressTagMask);
244 }
245
246 template <typename T, typename A>
247 static T Read(A address) {
248 T value;
249 address = AddressUntag(address);
250 DCHECK((sizeof(value) == 1) || (sizeof(value) == 2) ||
251 (sizeof(value) == 4) || (sizeof(value) == 8) ||
252 (sizeof(value) == 16));
253 memcpy(&value, reinterpret_cast<const char*>(address), sizeof(value));
254 return value;
255 }
256
257 template <typename T, typename A>
258 static void Write(A address, T value) {
259 address = AddressUntag(address);
260 DCHECK((sizeof(value) == 1) || (sizeof(value) == 2) ||
261 (sizeof(value) == 4) || (sizeof(value) == 8) ||
262 (sizeof(value) == 16));
263 memcpy(reinterpret_cast<char*>(address), &value, sizeof(value));
264 }
265};
266
267// The proper way to initialize a simulated system register (such as NZCV) is as
268// follows:
269// SimSystemRegister nzcv = SimSystemRegister::DefaultValueFor(NZCV);
270class SimSystemRegister {
271 public:
272 // The default constructor represents a register which has no writable bits.
273 // It is not possible to set its value to anything other than 0.
274 SimSystemRegister() : value_(0), write_ignore_mask_(0xffffffff) {}
275
276 uint32_t RawValue() const { return value_; }
277
278 void SetRawValue(uint32_t new_value) {
279 value_ = (value_ & write_ignore_mask_) | (new_value & ~write_ignore_mask_);
280 }
281
282 uint32_t Bits(int msb, int lsb) const {
283 return unsigned_bitextract_32(msb, lsb, value_);
284 }
285
286 int32_t SignedBits(int msb, int lsb) const {
287 return signed_bitextract_32(msb, lsb, value_);
288 }
289
290 void SetBits(int msb, int lsb, uint32_t bits);
291
292 // Default system register values.
293 static SimSystemRegister DefaultValueFor(SystemRegister id);
294
295#define DEFINE_GETTER(Name, HighBit, LowBit, Func, Type) \
296 Type Name() const { return static_cast<Type>(Func(HighBit, LowBit)); } \
297 void Set##Name(Type bits) { \
298 SetBits(HighBit, LowBit, static_cast<Type>(bits)); \
299 }
300#define DEFINE_WRITE_IGNORE_MASK(Name, Mask) \
301 static const uint32_t Name##WriteIgnoreMask = ~static_cast<uint32_t>(Mask);
302 SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER, DEFINE_WRITE_IGNORE_MASK)
303#undef DEFINE_ZERO_BITS
304#undef DEFINE_GETTER
305
306 protected:
307 // Most system registers only implement a few of the bits in the word. Other
308 // bits are "read-as-zero, write-ignored". The write_ignore_mask argument
309 // describes the bits which are not modifiable.
310 SimSystemRegister(uint32_t value, uint32_t write_ignore_mask)
311 : value_(value), write_ignore_mask_(write_ignore_mask) {}
312
313 uint32_t value_;
314 uint32_t write_ignore_mask_;
315};
316
317// Represent a register (r0-r31, v0-v31).
318template <int kSizeInBytes>
319class SimRegisterBase {
320 public:
321 template <typename T>
322 void Set(T new_value) {
323 static_assert(sizeof(new_value) <= kSizeInBytes,
324 "Size of new_value must be <= size of template type.");
325 if (sizeof(new_value) < kSizeInBytes) {
326 // All AArch64 registers are zero-extending.
327 memset(value_ + sizeof(new_value), 0, kSizeInBytes - sizeof(new_value));
328 }
329 memcpy(&value_, &new_value, sizeof(T));
330 NotifyRegisterWrite();
331 }
332
333 // Insert a typed value into a register, leaving the rest of the register
334 // unchanged. The lane parameter indicates where in the register the value
335 // should be inserted, in the range [ 0, sizeof(value_) / sizeof(T) ), where
336 // 0 represents the least significant bits.
337 template <typename T>
338 void Insert(int lane, T new_value) {
339 DCHECK_GE(lane, 0);
340 DCHECK_LE(sizeof(new_value) + (lane * sizeof(new_value)),
341 static_cast<unsigned>(kSizeInBytes));
342 memcpy(&value_[lane * sizeof(new_value)], &new_value, sizeof(new_value));
343 NotifyRegisterWrite();
344 }
345
346 template <typename T>
347 T Get(int lane = 0) const {
348 T result;
349 DCHECK_GE(lane, 0);
350 DCHECK_LE(sizeof(result) + (lane * sizeof(result)),
351 static_cast<unsigned>(kSizeInBytes));
352 memcpy(&result, &value_[lane * sizeof(result)], sizeof(result));
353 return result;
354 }
355
356 // TODO(all): Make this return a map of updated bytes, so that we can
357 // highlight updated lanes for load-and-insert. (That never happens for scalar
358 // code, but NEON has some instructions that can update individual lanes.)
359 bool WrittenSinceLastLog() const { return written_since_last_log_; }
360
361 void NotifyRegisterLogged() { written_since_last_log_ = false; }
362
363 protected:
364 uint8_t value_[kSizeInBytes];
365
366 // Helpers to aid with register tracing.
367 bool written_since_last_log_;
368
369 void NotifyRegisterWrite() { written_since_last_log_ = true; }
370};
371
372using SimRegister = SimRegisterBase<kXRegSize>; // r0-r31
373using SimVRegister = SimRegisterBase<kQRegSize>; // v0-v31
374
375using sim_uint128_t = std::pair<uint64_t, uint64_t>;
376
377// Representation of a vector register, with typed getters and setters for lanes
378// and additional information to represent lane state.
379class LogicVRegister {
380 public:
381 inline LogicVRegister(SimVRegister& other) // NOLINT
382 : register_(other) {
383 for (unsigned i = 0; i < arraysize(saturated_); i++) {
384 saturated_[i] = kNotSaturated;
385 }
386 for (unsigned i = 0; i < arraysize(round_); i++) {
387 round_[i] = false;
388 }
389 }
390
391 int64_t Int(VectorFormat vform, int index) const {
392 int64_t element;
393 switch (LaneSizeInBitsFromFormat(vform)) {
394 case 8:
395 element = register_.Get<int8_t>(index);
396 break;
397 case 16:
398 element = register_.Get<int16_t>(index);
399 break;
400 case 32:
401 element = register_.Get<int32_t>(index);
402 break;
403 case 64:
404 element = register_.Get<int64_t>(index);
405 break;
406 default:
407 UNREACHABLE();
408 return 0;
409 }
410 return element;
411 }
412
413 uint64_t Uint(VectorFormat vform, int index) const {
414 uint64_t element;
415 switch (LaneSizeInBitsFromFormat(vform)) {
416 case 8:
417 element = register_.Get<uint8_t>(index);
418 break;
419 case 16:
420 element = register_.Get<uint16_t>(index);
421 break;
422 case 32:
423 element = register_.Get<uint32_t>(index);
424 break;
425 case 64:
426 element = register_.Get<uint64_t>(index);
427 break;
428 default:
429 UNREACHABLE();
430 return 0;
431 }
432 return element;
433 }
434
435 uint64_t UintLeftJustified(VectorFormat vform, int index) const {
436 return Uint(vform, index) << (64 - LaneSizeInBitsFromFormat(vform));
437 }
438
439 int64_t IntLeftJustified(VectorFormat vform, int index) const {
440 uint64_t value = UintLeftJustified(vform, index);
441 int64_t result;
442 memcpy(&result, &value, sizeof(result));
443 return result;
444 }
445
446 void SetInt(VectorFormat vform, int index, int64_t value) const {
447 switch (LaneSizeInBitsFromFormat(vform)) {
448 case 8:
449 register_.Insert(index, static_cast<int8_t>(value));
450 break;
451 case 16:
452 register_.Insert(index, static_cast<int16_t>(value));
453 break;
454 case 32:
455 register_.Insert(index, static_cast<int32_t>(value));
456 break;
457 case 64:
458 register_.Insert(index, static_cast<int64_t>(value));
459 break;
460 default:
461 UNREACHABLE();
462 return;
463 }
464 }
465
466 void SetIntArray(VectorFormat vform, const int64_t* src) const {
467 ClearForWrite(vform);
468 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
469 SetInt(vform, i, src[i]);
470 }
471 }
472
473 void SetUint(VectorFormat vform, int index, uint64_t value) const {
474 switch (LaneSizeInBitsFromFormat(vform)) {
475 case 8:
476 register_.Insert(index, static_cast<uint8_t>(value));
477 break;
478 case 16:
479 register_.Insert(index, static_cast<uint16_t>(value));
480 break;
481 case 32:
482 register_.Insert(index, static_cast<uint32_t>(value));
483 break;
484 case 64:
485 register_.Insert(index, static_cast<uint64_t>(value));
486 break;
487 default:
488 UNREACHABLE();
489 return;
490 }
491 }
492
493 void SetUint(VectorFormat vform, int index, sim_uint128_t value) const {
494 if (LaneSizeInBitsFromFormat(vform) <= 64) {
495 SetUint(vform, index, value.second);
496 return;
497 }
498 DCHECK((vform == kFormat1Q) && (index == 0));
499 SetUint(kFormat2D, 0, value.second);
500 SetUint(kFormat2D, 1, value.first);
501 }
502
503 void SetUintArray(VectorFormat vform, const uint64_t* src) const {
504 ClearForWrite(vform);
505 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
506 SetUint(vform, i, src[i]);
507 }
508 }
509
510 void ReadUintFromMem(VectorFormat vform, int index, uint64_t addr) const;
511
512 void WriteUintToMem(VectorFormat vform, int index, uint64_t addr) const;
513
514 template <typename T>
515 T Float(int index) const {
516 return register_.Get<T>(index);
517 }
518
519 template <typename T>
520 void SetFloat(int index, T value) const {
521 register_.Insert(index, value);
522 }
523
524 // When setting a result in a register of size less than Q, the top bits of
525 // the Q register must be cleared.
526 void ClearForWrite(VectorFormat vform) const {
527 unsigned size = RegisterSizeInBytesFromFormat(vform);
528 for (unsigned i = size; i < kQRegSize; i++) {
529 SetUint(kFormat16B, i, 0);
530 }
531 }
532
533 // Saturation state for each lane of a vector.
534 enum Saturation {
535 kNotSaturated = 0,
536 kSignedSatPositive = 1 << 0,
537 kSignedSatNegative = 1 << 1,
538 kSignedSatMask = kSignedSatPositive | kSignedSatNegative,
539 kSignedSatUndefined = kSignedSatMask,
540 kUnsignedSatPositive = 1 << 2,
541 kUnsignedSatNegative = 1 << 3,
542 kUnsignedSatMask = kUnsignedSatPositive | kUnsignedSatNegative,
543 kUnsignedSatUndefined = kUnsignedSatMask
544 };
545
546 // Getters for saturation state.
547 Saturation GetSignedSaturation(int index) {
548 return static_cast<Saturation>(saturated_[index] & kSignedSatMask);
549 }
550
551 Saturation GetUnsignedSaturation(int index) {
552 return static_cast<Saturation>(saturated_[index] & kUnsignedSatMask);
553 }
554
555 // Setters for saturation state.
556 void ClearSat(int index) { saturated_[index] = kNotSaturated; }
557
558 void SetSignedSat(int index, bool positive) {
559 SetSatFlag(index, positive ? kSignedSatPositive : kSignedSatNegative);
560 }
561
562 void SetUnsignedSat(int index, bool positive) {
563 SetSatFlag(index, positive ? kUnsignedSatPositive : kUnsignedSatNegative);
564 }
565
566 void SetSatFlag(int index, Saturation sat) {
567 saturated_[index] = static_cast<Saturation>(saturated_[index] | sat);
568 DCHECK_NE(sat & kUnsignedSatMask, kUnsignedSatUndefined);
569 DCHECK_NE(sat & kSignedSatMask, kSignedSatUndefined);
570 }
571
572 // Saturate lanes of a vector based on saturation state.
573 LogicVRegister& SignedSaturate(VectorFormat vform) {
574 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
575 Saturation sat = GetSignedSaturation(i);
576 if (sat == kSignedSatPositive) {
577 SetInt(vform, i, MaxIntFromFormat(vform));
578 } else if (sat == kSignedSatNegative) {
579 SetInt(vform, i, MinIntFromFormat(vform));
580 }
581 }
582 return *this;
583 }
584
585 LogicVRegister& UnsignedSaturate(VectorFormat vform) {
586 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
587 Saturation sat = GetUnsignedSaturation(i);
588 if (sat == kUnsignedSatPositive) {
589 SetUint(vform, i, MaxUintFromFormat(vform));
590 } else if (sat == kUnsignedSatNegative) {
591 SetUint(vform, i, 0);
592 }
593 }
594 return *this;
595 }
596
597 // Getter for rounding state.
598 bool GetRounding(int index) { return round_[index]; }
599
600 // Setter for rounding state.
601 void SetRounding(int index, bool round) { round_[index] = round; }
602
603 // Round lanes of a vector based on rounding state.
604 LogicVRegister& Round(VectorFormat vform) {
605 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
606 SetUint(vform, i, Uint(vform, i) + (GetRounding(i) ? 1 : 0));
607 }
608 return *this;
609 }
610
611 // Unsigned halve lanes of a vector, and use the saturation state to set the
612 // top bit.
613 LogicVRegister& Uhalve(VectorFormat vform) {
614 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
615 uint64_t val = Uint(vform, i);
616 SetRounding(i, (val & 1) == 1);
617 val >>= 1;
618 if (GetUnsignedSaturation(i) != kNotSaturated) {
619 // If the operation causes unsigned saturation, the bit shifted into the
620 // most significant bit must be set.
621 val |= (MaxUintFromFormat(vform) >> 1) + 1;
622 }
623 SetInt(vform, i, val);
624 }
625 return *this;
626 }
627
628 // Signed halve lanes of a vector, and use the carry state to set the top bit.
629 LogicVRegister& Halve(VectorFormat vform) {
630 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
631 int64_t val = Int(vform, i);
632 SetRounding(i, (val & 1) == 1);
633 val >>= 1;
634 if (GetSignedSaturation(i) != kNotSaturated) {
635 // If the operation causes signed saturation, the sign bit must be
636 // inverted.
637 val ^= (MaxUintFromFormat(vform) >> 1) + 1;
638 }
639 SetInt(vform, i, val);
640 }
641 return *this;
642 }
643
644 bool Is(const LogicVRegister& r) const { return &register_ == &r.register_; }
645
646 private:
647 SimVRegister& register_;
648
649 // Allocate one saturation state entry per lane; largest register is type Q,
650 // and lanes can be a minimum of one byte wide.
651 Saturation saturated_[kQRegSize];
652
653 // Allocate one rounding state entry per lane.
654 bool round_[kQRegSize];
655};
656
657// Using multiple inheritance here is permitted because {DecoderVisitor} is a
658// pure interface class with only pure virtual methods.
659class Simulator : public DecoderVisitor, public SimulatorBase {
660 public:
661 static void SetRedirectInstruction(Instruction* instruction);
662 static bool ICacheMatch(void* one, void* two) { return false; }
663 static void FlushICache(base::CustomMatcherHashMap* i_cache, void* start,
664 size_t size) {
665 USE(i_cache);
666 USE(start);
667 USE(size);
668 }
669
670 V8_EXPORT_PRIVATE explicit Simulator(
671 Decoder<DispatchingDecoderVisitor>* decoder, Isolate* isolate = nullptr,
672 FILE* stream = stderr);
673 Simulator();
674 V8_EXPORT_PRIVATE ~Simulator();
675
676 // System functions.
677
678 V8_EXPORT_PRIVATE static Simulator* current(v8::internal::Isolate* isolate);
679
680 // A wrapper class that stores an argument for one of the above Call
681 // functions.
682 //
683 // Only arguments up to 64 bits in size are supported.
684 class CallArgument {
685 public:
686 template <typename T>
687 explicit CallArgument(T argument) {
688 bits_ = 0;
689 DCHECK(sizeof(argument) <= sizeof(bits_));
690 memcpy(&bits_, &argument, sizeof(argument));
691 type_ = X_ARG;
692 }
693
694 explicit CallArgument(double argument) {
695 DCHECK(sizeof(argument) == sizeof(bits_));
696 memcpy(&bits_, &argument, sizeof(argument));
697 type_ = D_ARG;
698 }
699
700 explicit CallArgument(float argument) {
701 // Make the D register a NaN to try to trap errors if the callee expects a
702 // double. If it expects a float, the callee should ignore the top word.
703 DCHECK(sizeof(kFP64SignallingNaN) == sizeof(bits_));
704 memcpy(&bits_, &kFP64SignallingNaN, sizeof(kFP64SignallingNaN));
705 // Write the float payload to the S register.
706 DCHECK(sizeof(argument) <= sizeof(bits_));
707 memcpy(&bits_, &argument, sizeof(argument));
708 type_ = D_ARG;
709 }
710
711 // This indicates the end of the arguments list, so that CallArgument
712 // objects can be passed into varargs functions.
713 static CallArgument End() { return CallArgument(); }
714
715 int64_t bits() const { return bits_; }
716 bool IsEnd() const { return type_ == NO_ARG; }
717 bool IsX() const { return type_ == X_ARG; }
718 bool IsD() const { return type_ == D_ARG; }
719
720 private:
721 enum CallArgumentType { X_ARG, D_ARG, NO_ARG };
722
723 // All arguments are aligned to at least 64 bits and we don't support
724 // passing bigger arguments, so the payload size can be fixed at 64 bits.
725 int64_t bits_;
726 CallArgumentType type_;
727
728 CallArgument() { type_ = NO_ARG; }
729 };
730
731 // Call an arbitrary function taking an arbitrary number of arguments.
732 template <typename Return, typename... Args>
733 Return Call(Address entry, Args... args) {
734 // Convert all arguments to CallArgument.
735 CallArgument call_args[] = {CallArgument(args)..., CallArgument::End()};
736 CallImpl(entry, call_args);
737 return ReadReturn<Return>();
738 }
739
740 // Start the debugging command line.
741 void Debug();
742
743 // Executes a single debug command. Takes ownership of the command (so that it
744 // can store it for repeat executions), and returns true if the debugger
745 // should resume execution after this command completes.
746 bool ExecDebugCommand(ArrayUniquePtr<char> command);
747
748 bool GetValue(const char* desc, int64_t* value);
749
750 bool PrintValue(const char* desc);
751
752 // Push an address onto the JS stack.
753 V8_EXPORT_PRIVATE uintptr_t PushAddress(uintptr_t address);
754
755 // Pop an address from the JS stack.
756 V8_EXPORT_PRIVATE uintptr_t PopAddress();
757
758 // Accessor to the internal simulator stack area. Adds a safety
759 // margin to prevent overflows (kAdditionalStackMargin).
760 uintptr_t StackLimit(uintptr_t c_limit) const;
761 uintptr_t StackBase() const;
762 void SetStackLimit(uintptr_t limit);
763 // Return central stack view, without additional safety margins.
764 // Users, for example wasm::StackMemory, can add their own.
765 base::Vector<uint8_t> GetCentralStackView() const;
766 static constexpr int JSStackLimitMargin() { return kAdditionalStackMargin; }
767
768 void IterateRegistersAndStack(::heap::base::StackVisitor* visitor);
769
770 V8_EXPORT_PRIVATE void ResetState();
771
772 void DoRuntimeCall(Instruction* instr);
773
774 // Run the simulator.
775 static const Instruction* kEndOfSimAddress;
776 void DecodeInstruction();
777 void Run();
778 V8_EXPORT_PRIVATE void RunFrom(Instruction* start);
779
780 // Simulation helpers.
781 template <typename T>
782 void set_pc(T new_pc) {
783 static_assert(sizeof(T) == sizeof(pc_));
784 memcpy(&pc_, &new_pc, sizeof(T));
785 pc_modified_ = true;
786 }
787 Instruction* pc() { return pc_; }
788
789 void increment_pc() {
790 if (!pc_modified_) {
791 pc_ = pc_->following();
792 }
793
794 pc_modified_ = false;
795 }
796
797 virtual void Decode(Instruction* instr) { decoder_->Decode(instr); }
798
799 // Branch Target Identification (BTI)
800 //
801 // Executing an instruction updates PSTATE.BTYPE, as described in the table
802 // below. Execution of an instruction on a guarded page is allowed if either:
803 // * PSTATE.BTYPE is 00, or
804 // * it is a BTI or PACI[AB]SP instruction that accepts the current value of
805 // PSTATE.BTYPE (as described in the table below), or
806 // * it is BRK or HLT instruction that causes some higher-priority exception.
807 //
808 // --------------------------------------------------------------------------
809 // | Last-executed instruction | Sets | Accepted by |
810 // | | BTYPE to | BTI | BTI j | BTI c | BTI jc |
811 // --------------------------------------------------------------------------
812 // | - BR from an unguarded page. | | | | | |
813 // | - BR from guarded page, | | | | | |
814 // | to x16 or x17. | 01 | | X | X | X |
815 // --------------------------------------------------------------------------
816 // | BR from guarded page, | | | | | |
817 // | not to x16 or x17. | 11 | | X | | X |
818 // --------------------------------------------------------------------------
819 // | BLR | 10 | | | X | X |
820 // --------------------------------------------------------------------------
821 // | Any other instruction | | | | | |
822 // |(including RET). | 00 | X | X | X | X |
823 // --------------------------------------------------------------------------
824 //
825 // PACI[AB]SP is treated either like "BTI c" or "BTI jc", according to the
826 // value of SCTLR_EL1.BT0. Details available in ARM DDI 0487E.a, D5-2580.
827
828 enum BType {
829 // Set when executing any instruction, except those cases listed below.
830 DefaultBType = 0,
831
832 // Set when an indirect branch is taken from an unguarded page, or from a
833 // guarded page to ip0 or ip1 (x16 or x17), eg "br ip0".
834 BranchFromUnguardedOrToIP = 1,
835
836 // Set when an indirect branch and link (call) is taken, eg. "blr x0".
837 BranchAndLink = 2,
838
839 // Set when an indirect branch is taken from a guarded page to a register
840 // that is not ip0 or ip1 (x16 or x17), eg, "br x0".
841 BranchFromGuardedNotToIP = 3
842 };
843
844 BType btype() const { return btype_; }
845 void ResetBType() { btype_ = DefaultBType; }
846 void set_btype(BType btype) { btype_ = btype; }
847
848 // Helper function to determine BType for branches.
849 BType GetBTypeFromInstruction(const Instruction* instr) const;
850
851 bool PcIsInGuardedPage() const { return guard_pages_; }
852 void SetGuardedPages(bool guard_pages) { guard_pages_ = guard_pages; }
853
854 void CheckBTypeForPAuth() {
855 DCHECK(pc_->IsPAuth());
856 Instr instr = pc_->Mask(SystemPAuthMask);
857 // Only PACI[AB]SP allowed here, and we only support PACIBSP.
858 CHECK(instr == PACIBSP);
859 // Check BType allows PACI[AB]SP instructions.
860 switch (btype()) {
861 case BranchFromGuardedNotToIP:
862 // This case depends on the value of SCTLR_EL1.BT0, which we assume
863 // here to be set. This makes PACI[AB]SP behave like "BTI c",
864 // disallowing its execution when BTYPE is BranchFromGuardedNotToIP
865 // (0b11).
866 FATAL("Executing PACIBSP with wrong BType.");
867 case BranchFromUnguardedOrToIP:
868 case BranchAndLink:
869 break;
870 case DefaultBType:
871 UNREACHABLE();
872 }
873 }
874
875 void CheckBTypeForBti() {
876 DCHECK(pc_->IsBti());
877 switch (pc_->ImmHint()) {
878 case BTI_jc:
879 break;
880 case BTI: {
881 DCHECK(btype() != DefaultBType);
882 FATAL("Executing BTI with wrong BType (expected 0, got %d).", btype());
883 break;
884 }
885 case BTI_c:
886 if (btype() == BranchFromGuardedNotToIP) {
887 FATAL("Executing BTI c with wrong BType (3).");
888 }
889 break;
890 case BTI_j:
891 if (btype() == BranchAndLink) {
892 FATAL("Executing BTI j with wrong BType (2).");
893 }
894 break;
895 default:
897 }
898 }
899
900 void CheckBType() {
901 // On guarded pages, if BType is not zero, take an exception on any
902 // instruction other than BTI, PACI[AB]SP, HLT or BRK.
903 if (PcIsInGuardedPage() && (btype() != DefaultBType)) {
904 if (pc_->IsPAuth()) {
905 CheckBTypeForPAuth();
906 } else if (pc_->IsBti()) {
907 CheckBTypeForBti();
908 } else if (!pc_->IsException()) {
909 FATAL("Executing non-BTI instruction with wrong BType.");
910 }
911 }
912 }
913
914 void ExecuteInstruction() {
915 DCHECK(IsAligned(reinterpret_cast<uintptr_t>(pc_), kInstrSize));
916 CheckBType();
917 ResetBType();
918 CheckBreakNext();
919 Decode(pc_);
920 increment_pc();
921 LogAllWrittenRegisters();
922 CheckBreakpoints();
923 }
924
925// Declare all Visitor functions.
926#define DECLARE(A) void Visit##A(Instruction* instr);
928#undef DECLARE
929 void VisitNEON3SameFP(NEON3SameOp op, VectorFormat vf, SimVRegister& rd,
930 SimVRegister& rn, SimVRegister& rm);
931
932 bool IsZeroRegister(unsigned code, Reg31Mode r31mode) const {
933 return ((code == 31) && (r31mode == Reg31IsZeroRegister));
934 }
935
936 // Register accessors.
937 // Return 'size' bits of the value of an integer register, as the specified
938 // type. The value is zero-extended to fill the result.
939 //
940 template <typename T>
941 T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
942 DCHECK_LT(code, static_cast<unsigned>(kNumberOfRegisters));
943 if (IsZeroRegister(code, r31mode)) {
944 return 0;
945 }
946 return registers_[code].Get<T>();
947 }
948
949 // Common specialized accessors for the reg() template.
950 int32_t wreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
951 return reg<int32_t>(code, r31mode);
952 }
953
954 int64_t xreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
955 return reg<int64_t>(code, r31mode);
956 }
957
958 enum RegLogMode { LogRegWrites, NoRegLog };
959
960 // Write 'value' into an integer register. The value is zero-extended. This
961 // behaviour matches AArch64 register writes.
962 template <typename T>
963 void set_reg(unsigned code, T value,
964 Reg31Mode r31mode = Reg31IsZeroRegister) {
965 set_reg_no_log(code, value, r31mode);
966 LogRegister(code, r31mode);
967 }
968
969 // Common specialized accessors for the set_reg() template.
970 void set_wreg(unsigned code, int32_t value,
971 Reg31Mode r31mode = Reg31IsZeroRegister) {
972 set_reg(code, value, r31mode);
973 }
974
975 void set_xreg(unsigned code, int64_t value,
976 Reg31Mode r31mode = Reg31IsZeroRegister) {
977 set_reg(code, value, r31mode);
978 }
979
980 // As above, but don't automatically log the register update.
981 template <typename T>
982 void set_reg_no_log(unsigned code, T value,
983 Reg31Mode r31mode = Reg31IsZeroRegister) {
984 DCHECK_LT(code, static_cast<unsigned>(kNumberOfRegisters));
985 if (!IsZeroRegister(code, r31mode)) {
986 registers_[code].Set(value);
987 }
988 }
989
990 void set_wreg_no_log(unsigned code, int32_t value,
991 Reg31Mode r31mode = Reg31IsZeroRegister) {
992 set_reg_no_log(code, value, r31mode);
993 }
994
995 void set_xreg_no_log(unsigned code, int64_t value,
996 Reg31Mode r31mode = Reg31IsZeroRegister) {
997 set_reg_no_log(code, value, r31mode);
998 }
999
1000 // Commonly-used special cases.
1001 template <typename T>
1002 void set_lr(T value) {
1003 DCHECK_EQ(sizeof(T), static_cast<unsigned>(kSystemPointerSize));
1004 set_reg(kLinkRegCode, value);
1005 }
1006
1007 template <typename T>
1008 void set_sp(T value) {
1009 DCHECK_EQ(sizeof(T), static_cast<unsigned>(kSystemPointerSize));
1010 set_reg(31, value, Reg31IsStackPointer);
1011 }
1012
1013 // Vector register accessors.
1014 // These are equivalent to the integer register accessors, but for vector
1015 // registers.
1016
1017 // A structure for representing a 128-bit Q register.
1018 struct qreg_t {
1019 uint8_t val[kQRegSize];
1020 };
1021
1022 // Basic accessor: read the register as the specified type.
1023 template <typename T>
1024 T vreg(unsigned code) const {
1025 static_assert((sizeof(T) == kBRegSize) || (sizeof(T) == kHRegSize) ||
1026 (sizeof(T) == kSRegSize) || (sizeof(T) == kDRegSize) ||
1027 (sizeof(T) == kQRegSize),
1028 "Template type must match size of register.");
1029 DCHECK_LT(code, static_cast<unsigned>(kNumberOfVRegisters));
1030
1031 return vregisters_[code].Get<T>();
1032 }
1033
1034 inline SimVRegister& vreg(unsigned code) { return vregisters_[code]; }
1035
1036 int64_t sp() { return xreg(31, Reg31IsStackPointer); }
1037 int64_t fp() { return xreg(kFramePointerRegCode, Reg31IsStackPointer); }
1038 Instruction* lr() { return reg<Instruction*>(kLinkRegCode); }
1039
1040 Address get_sp() const { return reg<Address>(31, Reg31IsStackPointer); }
1041
1042 // Common specialized accessors for the vreg() template.
1043 uint8_t breg(unsigned code) const { return vreg<uint8_t>(code); }
1044
1045 float hreg(unsigned code) const { return vreg<uint16_t>(code); }
1046
1047 float sreg(unsigned code) const { return vreg<float>(code); }
1048
1049 uint32_t sreg_bits(unsigned code) const { return vreg<uint32_t>(code); }
1050
1051 double dreg(unsigned code) const { return vreg<double>(code); }
1052
1053 uint64_t dreg_bits(unsigned code) const { return vreg<uint64_t>(code); }
1054
1055 qreg_t qreg(unsigned code) const { return vreg<qreg_t>(code); }
1056
1057 // As above, with parameterized size and return type. The value is
1058 // either zero-extended or truncated to fit, as required.
1059 template <typename T>
1060 T vreg(unsigned size, unsigned code) const {
1061 uint64_t raw = 0;
1062 T result;
1063
1064 switch (size) {
1065 case kSRegSize:
1066 raw = vreg<uint32_t>(code);
1067 break;
1068 case kDRegSize:
1069 raw = vreg<uint64_t>(code);
1070 break;
1071 default:
1072 UNREACHABLE();
1073 }
1074
1075 static_assert(sizeof(result) <= sizeof(raw),
1076 "Template type must be <= 64 bits.");
1077 // Copy the result and truncate to fit. This assumes a little-endian host.
1078 memcpy(&result, &raw, sizeof(result));
1079 return result;
1080 }
1081
1082 // Write 'value' into a floating-point register. The value is zero-extended.
1083 // This behaviour matches AArch64 register writes.
1084 template <typename T>
1085 void set_vreg(unsigned code, T value, RegLogMode log_mode = LogRegWrites) {
1086 static_assert(
1087 (sizeof(value) == kBRegSize) || (sizeof(value) == kHRegSize) ||
1088 (sizeof(value) == kSRegSize) || (sizeof(value) == kDRegSize) ||
1089 (sizeof(value) == kQRegSize),
1090 "Template type must match size of register.");
1091 DCHECK_LT(code, static_cast<unsigned>(kNumberOfVRegisters));
1092 vregisters_[code].Set(value);
1093
1094 if (log_mode == LogRegWrites) {
1095 LogVRegister(code, GetPrintRegisterFormat(value));
1096 }
1097 }
1098
1099 // Common specialized accessors for the set_vreg() template.
1100 void set_breg(unsigned code, int8_t value,
1101 RegLogMode log_mode = LogRegWrites) {
1102 set_vreg(code, value, log_mode);
1103 }
1104
1105 void set_hreg(unsigned code, int16_t value,
1106 RegLogMode log_mode = LogRegWrites) {
1107 set_vreg(code, value, log_mode);
1108 }
1109
1110 void set_sreg(unsigned code, float value,
1111 RegLogMode log_mode = LogRegWrites) {
1112 set_vreg(code, value, log_mode);
1113 }
1114
1115 void set_sreg_bits(unsigned code, uint32_t value,
1116 RegLogMode log_mode = LogRegWrites) {
1117 set_vreg(code, value, log_mode);
1118 }
1119
1120 void set_dreg(unsigned code, double value,
1121 RegLogMode log_mode = LogRegWrites) {
1122 set_vreg(code, value, log_mode);
1123 }
1124
1125 void set_dreg_bits(unsigned code, uint64_t value,
1126 RegLogMode log_mode = LogRegWrites) {
1127 set_vreg(code, value, log_mode);
1128 }
1129
1130 void set_qreg(unsigned code, qreg_t value,
1131 RegLogMode log_mode = LogRegWrites) {
1132 set_vreg(code, value, log_mode);
1133 }
1134
1135 // As above, but don't automatically log the register update.
1136 template <typename T>
1137 void set_vreg_no_log(unsigned code, T value) {
1138 static_assert((sizeof(value) == kBRegSize) ||
1139 (sizeof(value) == kHRegSize) ||
1140 (sizeof(value) == kSRegSize) ||
1141 (sizeof(value) == kDRegSize) || (sizeof(value) == kQRegSize));
1142 DCHECK_LT(code, static_cast<unsigned>(kNumberOfVRegisters));
1143 vregisters_[code].Set(value);
1144 }
1145
1146 void set_breg_no_log(unsigned code, uint8_t value) {
1147 set_vreg_no_log(code, value);
1148 }
1149
1150 void set_hreg_no_log(unsigned code, uint16_t value) {
1151 set_vreg_no_log(code, value);
1152 }
1153
1154 void set_sreg_no_log(unsigned code, float value) {
1155 set_vreg_no_log(code, value);
1156 }
1157
1158 void set_dreg_no_log(unsigned code, double value) {
1159 set_vreg_no_log(code, value);
1160 }
1161
1162 void set_qreg_no_log(unsigned code, qreg_t value) {
1163 set_vreg_no_log(code, value);
1164 }
1165
1166 SimSystemRegister& nzcv() { return nzcv_; }
1167 SimSystemRegister& fpcr() { return fpcr_; }
1168 FPRounding RMode() { return static_cast<FPRounding>(fpcr_.RMode()); }
1169 bool DN() { return fpcr_.DN() != 0; }
1170
1171 // Debug helpers
1172
1173 // Simulator breakpoints.
1174 struct Breakpoint {
1175 Instruction* location;
1176 bool enabled;
1177 };
1178 std::vector<Breakpoint> breakpoints_;
1179 void SetBreakpoint(Instruction* breakpoint);
1180 void ListBreakpoints();
1181 void CheckBreakpoints();
1182
1183 // Helpers for the 'next' command.
1184 // When this is set, the Simulator will insert a breakpoint after the next BL
1185 // instruction it meets.
1186 bool break_on_next_;
1187 // Check if the Simulator should insert a break after the current instruction
1188 // for the 'next' command.
1189 void CheckBreakNext();
1190
1191 // Disassemble instruction at the given address.
1192 void PrintInstructionsAt(Instruction* pc, uint64_t count);
1193
1194 // Print all registers of the specified types.
1195 void PrintRegisters();
1196 void PrintVRegisters();
1197 void PrintSystemRegisters();
1198
1199 // As above, but only print the registers that have been updated.
1200 void PrintWrittenRegisters();
1201 void PrintWrittenVRegisters();
1202
1203 // As above, but respect LOG_REG and LOG_VREG.
1204 void LogWrittenRegisters() {
1205 if (log_parameters() & LOG_REGS) PrintWrittenRegisters();
1206 }
1207 void LogWrittenVRegisters() {
1208 if (log_parameters() & LOG_VREGS) PrintWrittenVRegisters();
1209 }
1210 void LogAllWrittenRegisters() {
1211 LogWrittenRegisters();
1212 LogWrittenVRegisters();
1213 }
1214
1215 // Specify relevant register formats for Print(V)Register and related helpers.
1216 enum PrintRegisterFormat {
1217 // The lane size.
1218 kPrintRegLaneSizeB = 0 << 0,
1219 kPrintRegLaneSizeH = 1 << 0,
1220 kPrintRegLaneSizeS = 2 << 0,
1221 kPrintRegLaneSizeW = kPrintRegLaneSizeS,
1222 kPrintRegLaneSizeD = 3 << 0,
1223 kPrintRegLaneSizeX = kPrintRegLaneSizeD,
1224 kPrintRegLaneSizeQ = 4 << 0,
1225
1226 kPrintRegLaneSizeOffset = 0,
1227 kPrintRegLaneSizeMask = 7 << 0,
1228
1229 // The lane count.
1230 kPrintRegAsScalar = 0,
1231 kPrintRegAsDVector = 1 << 3,
1232 kPrintRegAsQVector = 2 << 3,
1233
1234 kPrintRegAsVectorMask = 3 << 3,
1235
1236 // Indicate floating-point format lanes. (This flag is only supported for S-
1237 // and D-sized lanes.)
1238 kPrintRegAsFP = 1 << 5,
1239
1240 // Supported combinations.
1241
1242 kPrintXReg = kPrintRegLaneSizeX | kPrintRegAsScalar,
1243 kPrintWReg = kPrintRegLaneSizeW | kPrintRegAsScalar,
1244 kPrintSReg = kPrintRegLaneSizeS | kPrintRegAsScalar | kPrintRegAsFP,
1245 kPrintDReg = kPrintRegLaneSizeD | kPrintRegAsScalar | kPrintRegAsFP,
1246
1247 kPrintReg1B = kPrintRegLaneSizeB | kPrintRegAsScalar,
1248 kPrintReg8B = kPrintRegLaneSizeB | kPrintRegAsDVector,
1249 kPrintReg16B = kPrintRegLaneSizeB | kPrintRegAsQVector,
1250 kPrintReg1H = kPrintRegLaneSizeH | kPrintRegAsScalar,
1251 kPrintReg4H = kPrintRegLaneSizeH | kPrintRegAsDVector,
1252 kPrintReg8H = kPrintRegLaneSizeH | kPrintRegAsQVector,
1253 kPrintReg1S = kPrintRegLaneSizeS | kPrintRegAsScalar,
1254 kPrintReg2S = kPrintRegLaneSizeS | kPrintRegAsDVector,
1255 kPrintReg4S = kPrintRegLaneSizeS | kPrintRegAsQVector,
1256 kPrintReg1SFP = kPrintRegLaneSizeS | kPrintRegAsScalar | kPrintRegAsFP,
1257 kPrintReg2SFP = kPrintRegLaneSizeS | kPrintRegAsDVector | kPrintRegAsFP,
1258 kPrintReg4SFP = kPrintRegLaneSizeS | kPrintRegAsQVector | kPrintRegAsFP,
1259 kPrintReg1D = kPrintRegLaneSizeD | kPrintRegAsScalar,
1260 kPrintReg2D = kPrintRegLaneSizeD | kPrintRegAsQVector,
1261 kPrintReg1DFP = kPrintRegLaneSizeD | kPrintRegAsScalar | kPrintRegAsFP,
1262 kPrintReg2DFP = kPrintRegLaneSizeD | kPrintRegAsQVector | kPrintRegAsFP,
1263 kPrintReg1Q = kPrintRegLaneSizeQ | kPrintRegAsScalar
1264 };
1265
1266 unsigned GetPrintRegLaneSizeInBytesLog2(PrintRegisterFormat format) {
1267 return (format & kPrintRegLaneSizeMask) >> kPrintRegLaneSizeOffset;
1268 }
1269
1270 unsigned GetPrintRegLaneSizeInBytes(PrintRegisterFormat format) {
1271 return 1 << GetPrintRegLaneSizeInBytesLog2(format);
1272 }
1273
1274 unsigned GetPrintRegSizeInBytesLog2(PrintRegisterFormat format) {
1275 if (format & kPrintRegAsDVector) return kDRegSizeLog2;
1276 if (format & kPrintRegAsQVector) return kQRegSizeLog2;
1277
1278 // Scalar types.
1279 return GetPrintRegLaneSizeInBytesLog2(format);
1280 }
1281
1282 unsigned GetPrintRegSizeInBytes(PrintRegisterFormat format) {
1283 return 1 << GetPrintRegSizeInBytesLog2(format);
1284 }
1285
1286 unsigned GetPrintRegLaneCount(PrintRegisterFormat format) {
1287 unsigned reg_size_log2 = GetPrintRegSizeInBytesLog2(format);
1288 unsigned lane_size_log2 = GetPrintRegLaneSizeInBytesLog2(format);
1289 DCHECK_GE(reg_size_log2, lane_size_log2);
1290 return 1 << (reg_size_log2 - lane_size_log2);
1291 }
1292
1293 template <typename T>
1294 PrintRegisterFormat GetPrintRegisterFormat(T value) {
1295 return GetPrintRegisterFormatForSize(sizeof(value));
1296 }
1297
1298 PrintRegisterFormat GetPrintRegisterFormat(double value) {
1299 static_assert(sizeof(value) == kDRegSize,
1300 "D register must be size of double.");
1301 return GetPrintRegisterFormatForSizeFP(sizeof(value));
1302 }
1303
1304 PrintRegisterFormat GetPrintRegisterFormat(float value) {
1305 static_assert(sizeof(value) == kSRegSize,
1306 "S register must be size of float.");
1307 return GetPrintRegisterFormatForSizeFP(sizeof(value));
1308 }
1309
1310 PrintRegisterFormat GetPrintRegisterFormat(VectorFormat vform);
1311 PrintRegisterFormat GetPrintRegisterFormatFP(VectorFormat vform);
1312
1313 PrintRegisterFormat GetPrintRegisterFormatForSize(size_t reg_size,
1314 size_t lane_size);
1315
1316 PrintRegisterFormat GetPrintRegisterFormatForSize(size_t size) {
1317 return GetPrintRegisterFormatForSize(size, size);
1318 }
1319
1320 PrintRegisterFormat GetPrintRegisterFormatForSizeFP(size_t size) {
1321 switch (size) {
1322 default:
1323 UNREACHABLE();
1324 case kDRegSize:
1325 return kPrintDReg;
1326 case kSRegSize:
1327 return kPrintSReg;
1328 }
1329 }
1330
1331 PrintRegisterFormat GetPrintRegisterFormatTryFP(PrintRegisterFormat format) {
1332 if ((GetPrintRegLaneSizeInBytes(format) == kSRegSize) ||
1333 (GetPrintRegLaneSizeInBytes(format) == kDRegSize)) {
1334 return static_cast<PrintRegisterFormat>(format | kPrintRegAsFP);
1335 }
1336 return format;
1337 }
1338
1339 // Print individual register values (after update).
1340 void PrintRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer);
1341 void PrintVRegister(unsigned code, PrintRegisterFormat sizes);
1342 void PrintSystemRegister(SystemRegister id);
1343
1344 // Like Print* (above), but respect log_parameters().
1345 void LogRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer) {
1346 if (log_parameters() & LOG_REGS) PrintRegister(code, r31mode);
1347 }
1348 void LogVRegister(unsigned code, PrintRegisterFormat format) {
1349 if (log_parameters() & LOG_VREGS) PrintVRegister(code, format);
1350 }
1351 void LogSystemRegister(SystemRegister id) {
1352 if (log_parameters() & LOG_SYS_REGS) PrintSystemRegister(id);
1353 }
1354
1355 // Print memory accesses.
1356 void PrintRead(uintptr_t address, unsigned reg_code,
1357 PrintRegisterFormat format);
1358 void PrintWrite(uintptr_t address, unsigned reg_code,
1359 PrintRegisterFormat format);
1360 void PrintVRead(uintptr_t address, unsigned reg_code,
1361 PrintRegisterFormat format, unsigned lane);
1362 void PrintVWrite(uintptr_t address, unsigned reg_code,
1363 PrintRegisterFormat format, unsigned lane);
1364
1365 // Like Print* (above), but respect log_parameters().
1366 void LogRead(uintptr_t address, unsigned reg_code,
1367 PrintRegisterFormat format) {
1368 if (log_parameters() & LOG_REGS) PrintRead(address, reg_code, format);
1369 }
1370 void LogWrite(uintptr_t address, unsigned reg_code,
1371 PrintRegisterFormat format) {
1372 if (log_parameters() & LOG_WRITE) PrintWrite(address, reg_code, format);
1373 }
1374 void LogVRead(uintptr_t address, unsigned reg_code,
1375 PrintRegisterFormat format, unsigned lane = 0) {
1376 if (log_parameters() & LOG_VREGS) {
1377 PrintVRead(address, reg_code, format, lane);
1378 }
1379 }
1380 void LogVWrite(uintptr_t address, unsigned reg_code,
1381 PrintRegisterFormat format, unsigned lane = 0) {
1382 if (log_parameters() & LOG_WRITE) {
1383 PrintVWrite(address, reg_code, format, lane);
1384 }
1385 }
1386
1387 int log_parameters() { return log_parameters_; }
1388 void set_log_parameters(int new_parameters) {
1389 log_parameters_ = new_parameters;
1390 if (!decoder_) {
1391 if (new_parameters & LOG_DISASM) {
1392 PrintF("Run --debug-sim to dynamically turn on disassembler\n");
1393 }
1394 return;
1395 }
1396 if (new_parameters & LOG_DISASM) {
1397 decoder_->InsertVisitorBefore(print_disasm_, this);
1398 } else {
1399 decoder_->RemoveVisitor(print_disasm_);
1400 }
1401 }
1402
1403 // Helper functions for register tracing.
1404 void PrintRegisterRawHelper(unsigned code, Reg31Mode r31mode,
1405 int size_in_bytes = kXRegSize);
1406 void PrintVRegisterRawHelper(unsigned code, int bytes = kQRegSize,
1407 int lsb = 0);
1408 void PrintVRegisterFPHelper(unsigned code, unsigned lane_size_in_bytes,
1409 int lane_count = 1, int rightmost_lane = 0);
1410
1411 static inline const char* WRegNameForCode(
1412 unsigned code, Reg31Mode mode = Reg31IsZeroRegister);
1413 static inline const char* XRegNameForCode(
1414 unsigned code, Reg31Mode mode = Reg31IsZeroRegister);
1415 static inline const char* SRegNameForCode(unsigned code);
1416 static inline const char* DRegNameForCode(unsigned code);
1417 static inline const char* VRegNameForCode(unsigned code);
1418 static inline int CodeFromName(const char* name);
1419
1420 enum PointerType { kDataPointer, kInstructionPointer };
1421
1422 struct PACKey {
1423 uint64_t high;
1424 uint64_t low;
1425 int number;
1426 };
1427
1428 static V8_EXPORT_PRIVATE const PACKey kPACKeyIB;
1429
1430 // Current implementation is that all pointers are tagged.
1431 static bool HasTBI(uint64_t ptr, PointerType type) {
1432 USE(ptr, type);
1433 return true;
1434 }
1435
1436 // Current implementation uses 48-bit virtual addresses.
1437 static int GetBottomPACBit(uint64_t ptr, int ttbr) {
1438 USE(ptr, ttbr);
1439 DCHECK((ttbr == 0) || (ttbr == 1));
1440 return 48;
1441 }
1442
1443 // The top PAC bit is 55 for the purposes of relative bit fields with TBI,
1444 // however bit 55 is the TTBR bit regardless of TBI so isn't part of the PAC
1445 // codes in pointers.
1446 static int GetTopPACBit(uint64_t ptr, PointerType type) {
1447 return HasTBI(ptr, type) ? 55 : 63;
1448 }
1449
1450 // Armv8.3 Pointer authentication helpers.
1451 V8_EXPORT_PRIVATE static uint64_t CalculatePACMask(uint64_t ptr,
1452 PointerType type,
1453 int ext_bit);
1454 V8_EXPORT_PRIVATE static uint64_t ComputePAC(uint64_t data, uint64_t context,
1455 PACKey key);
1456 V8_EXPORT_PRIVATE static uint64_t AuthPAC(uint64_t ptr, uint64_t context,
1457 PACKey key, PointerType type);
1458 V8_EXPORT_PRIVATE static uint64_t AddPAC(uint64_t ptr, uint64_t context,
1459 PACKey key, PointerType type);
1460 V8_EXPORT_PRIVATE static uint64_t StripPAC(uint64_t ptr, PointerType type);
1461
1462 protected:
1463 // Simulation helpers ------------------------------------
1464 bool ConditionPassed(Condition cond) {
1465 SimSystemRegister& flags = nzcv();
1466 switch (cond) {
1467 case eq:
1468 return flags.Z();
1469 case ne:
1470 return !flags.Z();
1471 case hs:
1472 return flags.C();
1473 case lo:
1474 return !flags.C();
1475 case mi:
1476 return flags.N();
1477 case pl:
1478 return !flags.N();
1479 case vs:
1480 return flags.V();
1481 case vc:
1482 return !flags.V();
1483 case hi:
1484 return flags.C() && !flags.Z();
1485 case ls:
1486 return !(flags.C() && !flags.Z());
1487 case ge:
1488 return flags.N() == flags.V();
1489 case lt:
1490 return flags.N() != flags.V();
1491 case gt:
1492 return !flags.Z() && (flags.N() == flags.V());
1493 case le:
1494 return !(!flags.Z() && (flags.N() == flags.V()));
1495 case nv: // Fall through.
1496 case al:
1497 return true;
1498 default:
1499 UNREACHABLE();
1500 }
1501 }
1502
1503 bool ConditionFailed(Condition cond) { return !ConditionPassed(cond); }
1504
1505 template <typename T>
1506 void AddSubHelper(Instruction* instr, T op2);
1507 template <typename T>
1508 T AddWithCarry(bool set_flags, T left, T right, int carry_in = 0);
1509 template <typename T>
1510 void AddSubWithCarry(Instruction* instr);
1511 template <typename T>
1512 void LogicalHelper(Instruction* instr, T op2);
1513 template <typename T>
1514 void ConditionalCompareHelper(Instruction* instr, T op2);
1515 void LoadStoreHelper(Instruction* instr, int64_t offset, AddrMode addrmode);
1516 void LoadStorePairHelper(Instruction* instr, AddrMode addrmode);
1517 template <typename T>
1518 void CompareAndSwapHelper(const Instruction* instr);
1519 template <typename T>
1520 void CompareAndSwapPairHelper(const Instruction* instr);
1521 template <typename T>
1522 void AtomicMemorySimpleHelper(const Instruction* instr);
1523 template <typename T>
1524 void AtomicMemorySwapHelper(const Instruction* instr);
1525 uintptr_t LoadStoreAddress(unsigned addr_reg, int64_t offset,
1526 AddrMode addrmode);
1527 void LoadStoreWriteBack(unsigned addr_reg, int64_t offset, AddrMode addrmode);
1528 void NEONLoadStoreMultiStructHelper(const Instruction* instr,
1529 AddrMode addr_mode);
1530 void NEONLoadStoreSingleStructHelper(const Instruction* instr,
1531 AddrMode addr_mode);
1532 void CheckMemoryAccess(uintptr_t address, uintptr_t stack);
1533
1534 // "Probe" if an address range can be read. This is currently implemented
1535 // by doing a 1-byte read of the last accessed byte, since the assumption is
1536 // that if the last byte is accessible, also all lower bytes are accessible
1537 // (which holds true for Wasm).
1538 // Returns true if the access was successful, false if the access raised a
1539 // signal which was then handled by the trap handler (also see
1540 // {trap_handler::ProbeMemory}). If the access raises a signal which is not
1541 // handled by the trap handler (e.g. because the current PC is not registered
1542 // as a protected instruction), the signal will propagate and make the process
1543 // crash. If no trap handler is available, this always returns true.
1544 bool ProbeMemory(uintptr_t address, uintptr_t access_size);
1545
1546 // Memory read helpers.
1547 template <typename T, typename A>
1548 T MemoryRead(A address) {
1549 T value;
1550 static_assert((sizeof(value) == 1) || (sizeof(value) == 2) ||
1551 (sizeof(value) == 4) || (sizeof(value) == 8) ||
1552 (sizeof(value) == 16));
1553 memcpy(&value, reinterpret_cast<const void*>(address), sizeof(value));
1554 return value;
1555 }
1556
1557 // Memory write helpers.
1558 template <typename T, typename A>
1559 void MemoryWrite(A address, T value) {
1560 static_assert((sizeof(value) == 1) || (sizeof(value) == 2) ||
1561 (sizeof(value) == 4) || (sizeof(value) == 8) ||
1562 (sizeof(value) == 16));
1563 memcpy(reinterpret_cast<void*>(address), &value, sizeof(value));
1564 }
1565
1566 template <typename T>
1567 T ShiftOperand(T value, Shift shift_type, unsigned amount);
1568 template <typename T>
1569 T ExtendValue(T value, Extend extend_type, unsigned left_shift = 0);
1570 template <typename T>
1571 void Extract(Instruction* instr);
1572 template <typename T>
1573 void DataProcessing2Source(Instruction* instr);
1574 template <typename T>
1575 void BitfieldHelper(Instruction* instr);
1576 uint16_t PolynomialMult(uint8_t op1, uint8_t op2);
1577 sim_uint128_t PolynomialMult128(uint64_t op1, uint64_t op2,
1578 int lane_size_in_bits) const;
1579 sim_uint128_t Lsl128(sim_uint128_t x, unsigned shift) const;
1580 sim_uint128_t Eor128(sim_uint128_t x, sim_uint128_t y) const;
1581
1582 void ld1(VectorFormat vform, LogicVRegister dst, uint64_t addr);
1583 void ld1(VectorFormat vform, LogicVRegister dst, int index, uint64_t addr);
1584 void ld1r(VectorFormat vform, LogicVRegister dst, uint64_t addr);
1585 void ld2(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
1586 uint64_t addr);
1587 void ld2(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
1588 int index, uint64_t addr);
1589 void ld2r(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
1590 uint64_t addr);
1591 void ld3(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
1592 LogicVRegister dst3, uint64_t addr);
1593 void ld3(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
1594 LogicVRegister dst3, int index, uint64_t addr);
1595 void ld3r(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
1596 LogicVRegister dst3, uint64_t addr);
1597 void ld4(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
1598 LogicVRegister dst3, LogicVRegister dst4, uint64_t addr);
1599 void ld4(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
1600 LogicVRegister dst3, LogicVRegister dst4, int index, uint64_t addr);
1601 void ld4r(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
1602 LogicVRegister dst3, LogicVRegister dst4, uint64_t addr);
1603 void st1(VectorFormat vform, LogicVRegister src, uint64_t addr);
1604 void st1(VectorFormat vform, LogicVRegister src, int index, uint64_t addr);
1605 void st2(VectorFormat vform, LogicVRegister src, LogicVRegister src2,
1606 uint64_t addr);
1607 void st2(VectorFormat vform, LogicVRegister src, LogicVRegister src2,
1608 int index, uint64_t addr);
1609 void st3(VectorFormat vform, LogicVRegister src, LogicVRegister src2,
1610 LogicVRegister src3, uint64_t addr);
1611 void st3(VectorFormat vform, LogicVRegister src, LogicVRegister src2,
1612 LogicVRegister src3, int index, uint64_t addr);
1613 void st4(VectorFormat vform, LogicVRegister src, LogicVRegister src2,
1614 LogicVRegister src3, LogicVRegister src4, uint64_t addr);
1615 void st4(VectorFormat vform, LogicVRegister src, LogicVRegister src2,
1616 LogicVRegister src3, LogicVRegister src4, int index, uint64_t addr);
1617 LogicVRegister cmp(VectorFormat vform, LogicVRegister dst,
1618 const LogicVRegister& src1, const LogicVRegister& src2,
1619 Condition cond);
1620 LogicVRegister cmp(VectorFormat vform, LogicVRegister dst,
1621 const LogicVRegister& src1, int imm, Condition cond);
1622 LogicVRegister cmptst(VectorFormat vform, LogicVRegister dst,
1623 const LogicVRegister& src1, const LogicVRegister& src2);
1624 LogicVRegister add(VectorFormat vform, LogicVRegister dst,
1625 const LogicVRegister& src1, const LogicVRegister& src2);
1626 LogicVRegister addp(VectorFormat vform, LogicVRegister dst,
1627 const LogicVRegister& src1, const LogicVRegister& src2);
1628 LogicVRegister mla(VectorFormat vform, LogicVRegister dst,
1629 const LogicVRegister& src1, const LogicVRegister& src2);
1630 LogicVRegister mls(VectorFormat vform, LogicVRegister dst,
1631 const LogicVRegister& src1, const LogicVRegister& src2);
1632 LogicVRegister mul(VectorFormat vform, LogicVRegister dst,
1633 const LogicVRegister& src1, const LogicVRegister& src2);
1634 LogicVRegister mul(VectorFormat vform, LogicVRegister dst,
1635 const LogicVRegister& src1, const LogicVRegister& src2,
1636 int index);
1637 LogicVRegister mla(VectorFormat vform, LogicVRegister dst,
1638 const LogicVRegister& src1, const LogicVRegister& src2,
1639 int index);
1640 LogicVRegister mls(VectorFormat vform, LogicVRegister dst,
1641 const LogicVRegister& src1, const LogicVRegister& src2,
1642 int index);
1643 LogicVRegister pmul(VectorFormat vform, LogicVRegister dst,
1644 const LogicVRegister& src1, const LogicVRegister& src2);
1645
1646 using ByElementOp = LogicVRegister (Simulator::*)(VectorFormat vform,
1647 LogicVRegister dst,
1648 const LogicVRegister& src1,
1649 const LogicVRegister& src2,
1650 int index);
1651 LogicVRegister fmul(VectorFormat vform, LogicVRegister dst,
1652 const LogicVRegister& src1, const LogicVRegister& src2,
1653 int index);
1654 LogicVRegister fmla(VectorFormat vform, LogicVRegister dst,
1655 const LogicVRegister& src1, const LogicVRegister& src2,
1656 int index);
1657 LogicVRegister fmls(VectorFormat vform, LogicVRegister dst,
1658 const LogicVRegister& src1, const LogicVRegister& src2,
1659 int index);
1660 LogicVRegister fmulx(VectorFormat vform, LogicVRegister dst,
1661 const LogicVRegister& src1, const LogicVRegister& src2,
1662 int index);
1663 LogicVRegister smull(VectorFormat vform, LogicVRegister dst,
1664 const LogicVRegister& src1, const LogicVRegister& src2,
1665 int index);
1666 LogicVRegister smull2(VectorFormat vform, LogicVRegister dst,
1667 const LogicVRegister& src1, const LogicVRegister& src2,
1668 int index);
1669 LogicVRegister umull(VectorFormat vform, LogicVRegister dst,
1670 const LogicVRegister& src1, const LogicVRegister& src2,
1671 int index);
1672 LogicVRegister umull2(VectorFormat vform, LogicVRegister dst,
1673 const LogicVRegister& src1, const LogicVRegister& src2,
1674 int index);
1675 LogicVRegister smlal(VectorFormat vform, LogicVRegister dst,
1676 const LogicVRegister& src1, const LogicVRegister& src2,
1677 int index);
1678 LogicVRegister smlal2(VectorFormat vform, LogicVRegister dst,
1679 const LogicVRegister& src1, const LogicVRegister& src2,
1680 int index);
1681 LogicVRegister umlal(VectorFormat vform, LogicVRegister dst,
1682 const LogicVRegister& src1, const LogicVRegister& src2,
1683 int index);
1684 LogicVRegister umlal2(VectorFormat vform, LogicVRegister dst,
1685 const LogicVRegister& src1, const LogicVRegister& src2,
1686 int index);
1687 LogicVRegister smlsl(VectorFormat vform, LogicVRegister dst,
1688 const LogicVRegister& src1, const LogicVRegister& src2,
1689 int index);
1690 LogicVRegister smlsl2(VectorFormat vform, LogicVRegister dst,
1691 const LogicVRegister& src1, const LogicVRegister& src2,
1692 int index);
1693 LogicVRegister umlsl(VectorFormat vform, LogicVRegister dst,
1694 const LogicVRegister& src1, const LogicVRegister& src2,
1695 int index);
1696 LogicVRegister umlsl2(VectorFormat vform, LogicVRegister dst,
1697 const LogicVRegister& src1, const LogicVRegister& src2,
1698 int index);
1699 LogicVRegister sqdmull(VectorFormat vform, LogicVRegister dst,
1700 const LogicVRegister& src1, const LogicVRegister& src2,
1701 int index);
1702 LogicVRegister sqdmull2(VectorFormat vform, LogicVRegister dst,
1703 const LogicVRegister& src1,
1704 const LogicVRegister& src2, int index);
1705 LogicVRegister sqdmlal(VectorFormat vform, LogicVRegister dst,
1706 const LogicVRegister& src1, const LogicVRegister& src2,
1707 int index);
1708 LogicVRegister sqdmlal2(VectorFormat vform, LogicVRegister dst,
1709 const LogicVRegister& src1,
1710 const LogicVRegister& src2, int index);
1711 LogicVRegister sqdmlsl(VectorFormat vform, LogicVRegister dst,
1712 const LogicVRegister& src1, const LogicVRegister& src2,
1713 int index);
1714 LogicVRegister sqdmlsl2(VectorFormat vform, LogicVRegister dst,
1715 const LogicVRegister& src1,
1716 const LogicVRegister& src2, int index);
1717 LogicVRegister sqdmulh(VectorFormat vform, LogicVRegister dst,
1718 const LogicVRegister& src1, const LogicVRegister& src2,
1719 int index);
1720 LogicVRegister sqrdmulh(VectorFormat vform, LogicVRegister dst,
1721 const LogicVRegister& src1,
1722 const LogicVRegister& src2, int index);
1723 LogicVRegister sub(VectorFormat vform, LogicVRegister dst,
1724 const LogicVRegister& src1, const LogicVRegister& src2);
1725 LogicVRegister and_(VectorFormat vform, LogicVRegister dst,
1726 const LogicVRegister& src1, const LogicVRegister& src2);
1727 LogicVRegister orr(VectorFormat vform, LogicVRegister dst,
1728 const LogicVRegister& src1, const LogicVRegister& src2);
1729 LogicVRegister orn(VectorFormat vform, LogicVRegister dst,
1730 const LogicVRegister& src1, const LogicVRegister& src2);
1731 LogicVRegister eor(VectorFormat vform, LogicVRegister dst,
1732 const LogicVRegister& src1, const LogicVRegister& src2);
1733 LogicVRegister bic(VectorFormat vform, LogicVRegister dst,
1734 const LogicVRegister& src1, const LogicVRegister& src2);
1735 LogicVRegister bic(VectorFormat vform, LogicVRegister dst,
1736 const LogicVRegister& src, uint64_t imm);
1737 LogicVRegister bif(VectorFormat vform, LogicVRegister dst,
1738 const LogicVRegister& src1, const LogicVRegister& src2);
1739 LogicVRegister bit(VectorFormat vform, LogicVRegister dst,
1740 const LogicVRegister& src1, const LogicVRegister& src2);
1741 LogicVRegister bsl(VectorFormat vform, LogicVRegister dst,
1742 const LogicVRegister& src1, const LogicVRegister& src2);
1743 LogicVRegister cls(VectorFormat vform, LogicVRegister dst,
1744 const LogicVRegister& src);
1745 LogicVRegister clz(VectorFormat vform, LogicVRegister dst,
1746 const LogicVRegister& src);
1747 LogicVRegister cnt(VectorFormat vform, LogicVRegister dst,
1748 const LogicVRegister& src);
1749 LogicVRegister not_(VectorFormat vform, LogicVRegister dst,
1750 const LogicVRegister& src);
1751 LogicVRegister rbit(VectorFormat vform, LogicVRegister dst,
1752 const LogicVRegister& src);
1753 LogicVRegister rev(VectorFormat vform, LogicVRegister dst,
1754 const LogicVRegister& src, int revSize);
1755 LogicVRegister rev16(VectorFormat vform, LogicVRegister dst,
1756 const LogicVRegister& src);
1757 LogicVRegister rev32(VectorFormat vform, LogicVRegister dst,
1758 const LogicVRegister& src);
1759 LogicVRegister rev64(VectorFormat vform, LogicVRegister dst,
1760 const LogicVRegister& src);
1761 LogicVRegister addlp(VectorFormat vform, LogicVRegister dst,
1762 const LogicVRegister& src, bool is_signed,
1763 bool do_accumulate);
1764 LogicVRegister saddlp(VectorFormat vform, LogicVRegister dst,
1765 const LogicVRegister& src);
1766 LogicVRegister uaddlp(VectorFormat vform, LogicVRegister dst,
1767 const LogicVRegister& src);
1768 LogicVRegister sadalp(VectorFormat vform, LogicVRegister dst,
1769 const LogicVRegister& src);
1770 LogicVRegister uadalp(VectorFormat vform, LogicVRegister dst,
1771 const LogicVRegister& src);
1772 LogicVRegister ext(VectorFormat vform, LogicVRegister dst,
1773 const LogicVRegister& src1, const LogicVRegister& src2,
1774 int index);
1775 LogicVRegister ins_element(VectorFormat vform, LogicVRegister dst,
1776 int dst_index, const LogicVRegister& src,
1777 int src_index);
1778 LogicVRegister ins_immediate(VectorFormat vform, LogicVRegister dst,
1779 int dst_index, uint64_t imm);
1780 LogicVRegister dup_element(VectorFormat vform, LogicVRegister dst,
1781 const LogicVRegister& src, int src_index);
1782 LogicVRegister dup_immediate(VectorFormat vform, LogicVRegister dst,
1783 uint64_t imm);
1784 LogicVRegister movi(VectorFormat vform, LogicVRegister dst, uint64_t imm);
1785 LogicVRegister mvni(VectorFormat vform, LogicVRegister dst, uint64_t imm);
1786 LogicVRegister orr(VectorFormat vform, LogicVRegister dst,
1787 const LogicVRegister& src, uint64_t imm);
1788 LogicVRegister sshl(VectorFormat vform, LogicVRegister dst,
1789 const LogicVRegister& src1, const LogicVRegister& src2);
1790 LogicVRegister ushl(VectorFormat vform, LogicVRegister dst,
1791 const LogicVRegister& src1, const LogicVRegister& src2);
1792 LogicVRegister SMinMax(VectorFormat vform, LogicVRegister dst,
1793 const LogicVRegister& src1, const LogicVRegister& src2,
1794 bool max);
1795 LogicVRegister smax(VectorFormat vform, LogicVRegister dst,
1796 const LogicVRegister& src1, const LogicVRegister& src2);
1797 LogicVRegister smin(VectorFormat vform, LogicVRegister dst,
1798 const LogicVRegister& src1, const LogicVRegister& src2);
1799 LogicVRegister SMinMaxP(VectorFormat vform, LogicVRegister dst,
1800 const LogicVRegister& src1,
1801 const LogicVRegister& src2, bool max);
1802 LogicVRegister smaxp(VectorFormat vform, LogicVRegister dst,
1803 const LogicVRegister& src1, const LogicVRegister& src2);
1804 LogicVRegister sminp(VectorFormat vform, LogicVRegister dst,
1805 const LogicVRegister& src1, const LogicVRegister& src2);
1806 LogicVRegister addp(VectorFormat vform, LogicVRegister dst,
1807 const LogicVRegister& src);
1808 LogicVRegister addv(VectorFormat vform, LogicVRegister dst,
1809 const LogicVRegister& src);
1810 LogicVRegister uaddlv(VectorFormat vform, LogicVRegister dst,
1811 const LogicVRegister& src);
1812 LogicVRegister saddlv(VectorFormat vform, LogicVRegister dst,
1813 const LogicVRegister& src);
1814 LogicVRegister SMinMaxV(VectorFormat vform, LogicVRegister dst,
1815 const LogicVRegister& src, bool max);
1816 LogicVRegister smaxv(VectorFormat vform, LogicVRegister dst,
1817 const LogicVRegister& src);
1818 LogicVRegister sminv(VectorFormat vform, LogicVRegister dst,
1819 const LogicVRegister& src);
1820 LogicVRegister uxtl(VectorFormat vform, LogicVRegister dst,
1821 const LogicVRegister& src);
1822 LogicVRegister uxtl2(VectorFormat vform, LogicVRegister dst,
1823 const LogicVRegister& src);
1824 LogicVRegister sxtl(VectorFormat vform, LogicVRegister dst,
1825 const LogicVRegister& src);
1826 LogicVRegister sxtl2(VectorFormat vform, LogicVRegister dst,
1827 const LogicVRegister& src);
1828 LogicVRegister Table(VectorFormat vform, LogicVRegister dst,
1829 const LogicVRegister& ind, bool zero_out_of_bounds,
1830 const LogicVRegister* tab1,
1831 const LogicVRegister* tab2 = nullptr,
1832 const LogicVRegister* tab3 = nullptr,
1833 const LogicVRegister* tab4 = nullptr);
1834 LogicVRegister tbl(VectorFormat vform, LogicVRegister dst,
1835 const LogicVRegister& tab, const LogicVRegister& ind);
1836 LogicVRegister tbl(VectorFormat vform, LogicVRegister dst,
1837 const LogicVRegister& tab, const LogicVRegister& tab2,
1838 const LogicVRegister& ind);
1839 LogicVRegister tbl(VectorFormat vform, LogicVRegister dst,
1840 const LogicVRegister& tab, const LogicVRegister& tab2,
1841 const LogicVRegister& tab3, const LogicVRegister& ind);
1842 LogicVRegister tbl(VectorFormat vform, LogicVRegister dst,
1843 const LogicVRegister& tab, const LogicVRegister& tab2,
1844 const LogicVRegister& tab3, const LogicVRegister& tab4,
1845 const LogicVRegister& ind);
1846 LogicVRegister tbx(VectorFormat vform, LogicVRegister dst,
1847 const LogicVRegister& tab, const LogicVRegister& ind);
1848 LogicVRegister tbx(VectorFormat vform, LogicVRegister dst,
1849 const LogicVRegister& tab, const LogicVRegister& tab2,
1850 const LogicVRegister& ind);
1851 LogicVRegister tbx(VectorFormat vform, LogicVRegister dst,
1852 const LogicVRegister& tab, const LogicVRegister& tab2,
1853 const LogicVRegister& tab3, const LogicVRegister& ind);
1854 LogicVRegister tbx(VectorFormat vform, LogicVRegister dst,
1855 const LogicVRegister& tab, const LogicVRegister& tab2,
1856 const LogicVRegister& tab3, const LogicVRegister& tab4,
1857 const LogicVRegister& ind);
1858 LogicVRegister uaddl(VectorFormat vform, LogicVRegister dst,
1859 const LogicVRegister& src1, const LogicVRegister& src2);
1860 LogicVRegister uaddl2(VectorFormat vform, LogicVRegister dst,
1861 const LogicVRegister& src1, const LogicVRegister& src2);
1862 LogicVRegister uaddw(VectorFormat vform, LogicVRegister dst,
1863 const LogicVRegister& src1, const LogicVRegister& src2);
1864 LogicVRegister uaddw2(VectorFormat vform, LogicVRegister dst,
1865 const LogicVRegister& src1, const LogicVRegister& src2);
1866 LogicVRegister saddl(VectorFormat vform, LogicVRegister dst,
1867 const LogicVRegister& src1, const LogicVRegister& src2);
1868 LogicVRegister saddl2(VectorFormat vform, LogicVRegister dst,
1869 const LogicVRegister& src1, const LogicVRegister& src2);
1870 LogicVRegister saddw(VectorFormat vform, LogicVRegister dst,
1871 const LogicVRegister& src1, const LogicVRegister& src2);
1872 LogicVRegister saddw2(VectorFormat vform, LogicVRegister dst,
1873 const LogicVRegister& src1, const LogicVRegister& src2);
1874 LogicVRegister usubl(VectorFormat vform, LogicVRegister dst,
1875 const LogicVRegister& src1, const LogicVRegister& src2);
1876 LogicVRegister usubl2(VectorFormat vform, LogicVRegister dst,
1877 const LogicVRegister& src1, const LogicVRegister& src2);
1878 LogicVRegister usubw(VectorFormat vform, LogicVRegister dst,
1879 const LogicVRegister& src1, const LogicVRegister& src2);
1880 LogicVRegister usubw2(VectorFormat vform, LogicVRegister dst,
1881 const LogicVRegister& src1, const LogicVRegister& src2);
1882 LogicVRegister ssubl(VectorFormat vform, LogicVRegister dst,
1883 const LogicVRegister& src1, const LogicVRegister& src2);
1884 LogicVRegister ssubl2(VectorFormat vform, LogicVRegister dst,
1885 const LogicVRegister& src1, const LogicVRegister& src2);
1886 LogicVRegister ssubw(VectorFormat vform, LogicVRegister dst,
1887 const LogicVRegister& src1, const LogicVRegister& src2);
1888 LogicVRegister ssubw2(VectorFormat vform, LogicVRegister dst,
1889 const LogicVRegister& src1, const LogicVRegister& src2);
1890 LogicVRegister UMinMax(VectorFormat vform, LogicVRegister dst,
1891 const LogicVRegister& src1, const LogicVRegister& src2,
1892 bool max);
1893 LogicVRegister umax(VectorFormat vform, LogicVRegister dst,
1894 const LogicVRegister& src1, const LogicVRegister& src2);
1895 LogicVRegister umin(VectorFormat vform, LogicVRegister dst,
1896 const LogicVRegister& src1, const LogicVRegister& src2);
1897 LogicVRegister UMinMaxP(VectorFormat vform, LogicVRegister dst,
1898 const LogicVRegister& src1,
1899 const LogicVRegister& src2, bool max);
1900 LogicVRegister umaxp(VectorFormat vform, LogicVRegister dst,
1901 const LogicVRegister& src1, const LogicVRegister& src2);
1902 LogicVRegister uminp(VectorFormat vform, LogicVRegister dst,
1903 const LogicVRegister& src1, const LogicVRegister& src2);
1904 LogicVRegister UMinMaxV(VectorFormat vform, LogicVRegister dst,
1905 const LogicVRegister& src, bool max);
1906 LogicVRegister umaxv(VectorFormat vform, LogicVRegister dst,
1907 const LogicVRegister& src);
1908 LogicVRegister uminv(VectorFormat vform, LogicVRegister dst,
1909 const LogicVRegister& src);
1910 LogicVRegister trn1(VectorFormat vform, LogicVRegister dst,
1911 const LogicVRegister& src1, const LogicVRegister& src2);
1912 LogicVRegister trn2(VectorFormat vform, LogicVRegister dst,
1913 const LogicVRegister& src1, const LogicVRegister& src2);
1914 LogicVRegister zip1(VectorFormat vform, LogicVRegister dst,
1915 const LogicVRegister& src1, const LogicVRegister& src2);
1916 LogicVRegister zip2(VectorFormat vform, LogicVRegister dst,
1917 const LogicVRegister& src1, const LogicVRegister& src2);
1918 LogicVRegister uzp1(VectorFormat vform, LogicVRegister dst,
1919 const LogicVRegister& src1, const LogicVRegister& src2);
1920 LogicVRegister uzp2(VectorFormat vform, LogicVRegister dst,
1921 const LogicVRegister& src1, const LogicVRegister& src2);
1922 LogicVRegister shl(VectorFormat vform, LogicVRegister dst,
1923 const LogicVRegister& src, int shift);
1924 LogicVRegister scvtf(VectorFormat vform, LogicVRegister dst,
1925 const LogicVRegister& src, int fbits,
1926 FPRounding rounding_mode);
1927 LogicVRegister ucvtf(VectorFormat vform, LogicVRegister dst,
1928 const LogicVRegister& src, int fbits,
1929 FPRounding rounding_mode);
1930 LogicVRegister sshll(VectorFormat vform, LogicVRegister dst,
1931 const LogicVRegister& src, int shift);
1932 LogicVRegister sshll2(VectorFormat vform, LogicVRegister dst,
1933 const LogicVRegister& src, int shift);
1934 LogicVRegister shll(VectorFormat vform, LogicVRegister dst,
1935 const LogicVRegister& src);
1936 LogicVRegister shll2(VectorFormat vform, LogicVRegister dst,
1937 const LogicVRegister& src);
1938 LogicVRegister ushll(VectorFormat vform, LogicVRegister dst,
1939 const LogicVRegister& src, int shift);
1940 LogicVRegister ushll2(VectorFormat vform, LogicVRegister dst,
1941 const LogicVRegister& src, int shift);
1942 LogicVRegister sli(VectorFormat vform, LogicVRegister dst,
1943 const LogicVRegister& src, int shift);
1944 LogicVRegister sri(VectorFormat vform, LogicVRegister dst,
1945 const LogicVRegister& src, int shift);
1946 LogicVRegister sshr(VectorFormat vform, LogicVRegister dst,
1947 const LogicVRegister& src, int shift);
1948 LogicVRegister ushr(VectorFormat vform, LogicVRegister dst,
1949 const LogicVRegister& src, int shift);
1950 LogicVRegister ssra(VectorFormat vform, LogicVRegister dst,
1951 const LogicVRegister& src, int shift);
1952 LogicVRegister usra(VectorFormat vform, LogicVRegister dst,
1953 const LogicVRegister& src, int shift);
1954 LogicVRegister srsra(VectorFormat vform, LogicVRegister dst,
1955 const LogicVRegister& src, int shift);
1956 LogicVRegister ursra(VectorFormat vform, LogicVRegister dst,
1957 const LogicVRegister& src, int shift);
1958 LogicVRegister suqadd(VectorFormat vform, LogicVRegister dst,
1959 const LogicVRegister& src);
1960 LogicVRegister usqadd(VectorFormat vform, LogicVRegister dst,
1961 const LogicVRegister& src);
1962 LogicVRegister sqshl(VectorFormat vform, LogicVRegister dst,
1963 const LogicVRegister& src, int shift);
1964 LogicVRegister uqshl(VectorFormat vform, LogicVRegister dst,
1965 const LogicVRegister& src, int shift);
1966 LogicVRegister sqshlu(VectorFormat vform, LogicVRegister dst,
1967 const LogicVRegister& src, int shift);
1968 LogicVRegister abs(VectorFormat vform, LogicVRegister dst,
1969 const LogicVRegister& src);
1970 LogicVRegister neg(VectorFormat vform, LogicVRegister dst,
1971 const LogicVRegister& src);
1972 LogicVRegister ExtractNarrow(VectorFormat vform, LogicVRegister dst,
1973 bool dstIsSigned, const LogicVRegister& src,
1974 bool srcIsSigned);
1975 LogicVRegister xtn(VectorFormat vform, LogicVRegister dst,
1976 const LogicVRegister& src);
1977 LogicVRegister sqxtn(VectorFormat vform, LogicVRegister dst,
1978 const LogicVRegister& src);
1979 LogicVRegister uqxtn(VectorFormat vform, LogicVRegister dst,
1980 const LogicVRegister& src);
1981 LogicVRegister sqxtun(VectorFormat vform, LogicVRegister dst,
1982 const LogicVRegister& src);
1983 LogicVRegister AbsDiff(VectorFormat vform, LogicVRegister dst,
1984 const LogicVRegister& src1, const LogicVRegister& src2,
1985 bool issigned);
1986 LogicVRegister saba(VectorFormat vform, LogicVRegister dst,
1987 const LogicVRegister& src1, const LogicVRegister& src2);
1988 LogicVRegister uaba(VectorFormat vform, LogicVRegister dst,
1989 const LogicVRegister& src1, const LogicVRegister& src2);
1990 LogicVRegister shrn(VectorFormat vform, LogicVRegister dst,
1991 const LogicVRegister& src, int shift);
1992 LogicVRegister shrn2(VectorFormat vform, LogicVRegister dst,
1993 const LogicVRegister& src, int shift);
1994 LogicVRegister rshrn(VectorFormat vform, LogicVRegister dst,
1995 const LogicVRegister& src, int shift);
1996 LogicVRegister rshrn2(VectorFormat vform, LogicVRegister dst,
1997 const LogicVRegister& src, int shift);
1998 LogicVRegister uqshrn(VectorFormat vform, LogicVRegister dst,
1999 const LogicVRegister& src, int shift);
2000 LogicVRegister uqshrn2(VectorFormat vform, LogicVRegister dst,
2001 const LogicVRegister& src, int shift);
2002 LogicVRegister uqrshrn(VectorFormat vform, LogicVRegister dst,
2003 const LogicVRegister& src, int shift);
2004 LogicVRegister uqrshrn2(VectorFormat vform, LogicVRegister dst,
2005 const LogicVRegister& src, int shift);
2006 LogicVRegister sqshrn(VectorFormat vform, LogicVRegister dst,
2007 const LogicVRegister& src, int shift);
2008 LogicVRegister sqshrn2(VectorFormat vform, LogicVRegister dst,
2009 const LogicVRegister& src, int shift);
2010 LogicVRegister sqrshrn(VectorFormat vform, LogicVRegister dst,
2011 const LogicVRegister& src, int shift);
2012 LogicVRegister sqrshrn2(VectorFormat vform, LogicVRegister dst,
2013 const LogicVRegister& src, int shift);
2014 LogicVRegister sqshrun(VectorFormat vform, LogicVRegister dst,
2015 const LogicVRegister& src, int shift);
2016 LogicVRegister sqshrun2(VectorFormat vform, LogicVRegister dst,
2017 const LogicVRegister& src, int shift);
2018 LogicVRegister sqrshrun(VectorFormat vform, LogicVRegister dst,
2019 const LogicVRegister& src, int shift);
2020 LogicVRegister sqrshrun2(VectorFormat vform, LogicVRegister dst,
2021 const LogicVRegister& src, int shift);
2022 LogicVRegister sqrdmulh(VectorFormat vform, LogicVRegister dst,
2023 const LogicVRegister& src1,
2024 const LogicVRegister& src2, bool round = true);
2025 LogicVRegister dot(VectorFormat vform, LogicVRegister dst,
2026 const LogicVRegister& src1, const LogicVRegister& src2,
2027 bool is_src1_signed, bool is_src2_signed);
2028 LogicVRegister sdot(VectorFormat vform, LogicVRegister dst,
2029 const LogicVRegister& src1, const LogicVRegister& src2);
2030 LogicVRegister sqdmulh(VectorFormat vform, LogicVRegister dst,
2031 const LogicVRegister& src1,
2032 const LogicVRegister& src2);
2033#define NEON_3VREG_LOGIC_LIST(V) \
2034 V(addhn) \
2035 V(addhn2) \
2036 V(raddhn) \
2037 V(raddhn2) \
2038 V(subhn) \
2039 V(subhn2) \
2040 V(rsubhn) \
2041 V(rsubhn2) \
2042 V(pmull) \
2043 V(pmull2) \
2044 V(sabal) \
2045 V(sabal2) \
2046 V(uabal) \
2047 V(uabal2) \
2048 V(sabdl) \
2049 V(sabdl2) \
2050 V(uabdl) \
2051 V(uabdl2) \
2052 V(smull) \
2053 V(smull2) \
2054 V(umull) \
2055 V(umull2) \
2056 V(smlal) \
2057 V(smlal2) \
2058 V(umlal) \
2059 V(umlal2) \
2060 V(smlsl) \
2061 V(smlsl2) \
2062 V(umlsl) \
2063 V(umlsl2) \
2064 V(sqdmlal) \
2065 V(sqdmlal2) \
2066 V(sqdmlsl) \
2067 V(sqdmlsl2) \
2068 V(sqdmull) \
2069 V(sqdmull2)
2070
2071#define DEFINE_LOGIC_FUNC(FXN) \
2072 LogicVRegister FXN(VectorFormat vform, LogicVRegister dst, \
2073 const LogicVRegister& src1, const LogicVRegister& src2);
2074 NEON_3VREG_LOGIC_LIST(DEFINE_LOGIC_FUNC)
2075#undef DEFINE_LOGIC_FUNC
2076
2077#define NEON_FP3SAME_LIST(V) \
2078 V(fadd, FPAdd, false) \
2079 V(fsub, FPSub, true) \
2080 V(fmul, FPMul, true) \
2081 V(fmulx, FPMulx, true) \
2082 V(fdiv, FPDiv, true) \
2083 V(fmax, FPMax, false) \
2084 V(fmin, FPMin, false) \
2085 V(fmaxnm, FPMaxNM, false) \
2086 V(fminnm, FPMinNM, false)
2087
2088#define DECLARE_NEON_FP_VECTOR_OP(FN, OP, PROCNAN) \
2089 template <typename T> \
2090 LogicVRegister FN(VectorFormat vform, LogicVRegister dst, \
2091 const LogicVRegister& src1, const LogicVRegister& src2); \
2092 LogicVRegister FN(VectorFormat vform, LogicVRegister dst, \
2093 const LogicVRegister& src1, const LogicVRegister& src2);
2094 NEON_FP3SAME_LIST(DECLARE_NEON_FP_VECTOR_OP)
2095#undef DECLARE_NEON_FP_VECTOR_OP
2096
2097#define NEON_FPPAIRWISE_LIST(V) \
2098 V(faddp, fadd, FPAdd) \
2099 V(fmaxp, fmax, FPMax) \
2100 V(fmaxnmp, fmaxnm, FPMaxNM) \
2101 V(fminp, fmin, FPMin) \
2102 V(fminnmp, fminnm, FPMinNM)
2103
2104#define DECLARE_NEON_FP_PAIR_OP(FNP, FN, OP) \
2105 LogicVRegister FNP(VectorFormat vform, LogicVRegister dst, \
2106 const LogicVRegister& src1, const LogicVRegister& src2); \
2107 LogicVRegister FNP(VectorFormat vform, LogicVRegister dst, \
2108 const LogicVRegister& src);
2109 NEON_FPPAIRWISE_LIST(DECLARE_NEON_FP_PAIR_OP)
2110#undef DECLARE_NEON_FP_PAIR_OP
2111
2112 template <typename T>
2113 LogicVRegister frecps(VectorFormat vform, LogicVRegister dst,
2114 const LogicVRegister& src1, const LogicVRegister& src2);
2115 LogicVRegister frecps(VectorFormat vform, LogicVRegister dst,
2116 const LogicVRegister& src1, const LogicVRegister& src2);
2117 template <typename T>
2118 LogicVRegister frsqrts(VectorFormat vform, LogicVRegister dst,
2119 const LogicVRegister& src1,
2120 const LogicVRegister& src2);
2121 LogicVRegister frsqrts(VectorFormat vform, LogicVRegister dst,
2122 const LogicVRegister& src1,
2123 const LogicVRegister& src2);
2124 template <typename T>
2125 LogicVRegister fmla(VectorFormat vform, LogicVRegister dst,
2126 const LogicVRegister& src1, const LogicVRegister& src2);
2127 LogicVRegister fmla(VectorFormat vform, LogicVRegister dst,
2128 const LogicVRegister& src1, const LogicVRegister& src2);
2129 template <typename T>
2130 LogicVRegister fmls(VectorFormat vform, LogicVRegister dst,
2131 const LogicVRegister& src1, const LogicVRegister& src2);
2132 LogicVRegister fmls(VectorFormat vform, LogicVRegister dst,
2133 const LogicVRegister& src1, const LogicVRegister& src2);
2134 LogicVRegister fnmul(VectorFormat vform, LogicVRegister dst,
2135 const LogicVRegister& src1, const LogicVRegister& src2);
2136
2137 template <typename T>
2138 LogicVRegister fcmp(VectorFormat vform, LogicVRegister dst,
2139 const LogicVRegister& src1, const LogicVRegister& src2,
2140 Condition cond);
2141 LogicVRegister fcmp(VectorFormat vform, LogicVRegister dst,
2142 const LogicVRegister& src1, const LogicVRegister& src2,
2143 Condition cond);
2144 LogicVRegister fabscmp(VectorFormat vform, LogicVRegister dst,
2145 const LogicVRegister& src1, const LogicVRegister& src2,
2146 Condition cond);
2147 LogicVRegister fcmp_zero(VectorFormat vform, LogicVRegister dst,
2148 const LogicVRegister& src, Condition cond);
2149
2150 template <typename T>
2151 LogicVRegister fneg(VectorFormat vform, LogicVRegister dst,
2152 const LogicVRegister& src);
2153 LogicVRegister fneg(VectorFormat vform, LogicVRegister dst,
2154 const LogicVRegister& src);
2155 template <typename T>
2156 LogicVRegister frecpx(VectorFormat vform, LogicVRegister dst,
2157 const LogicVRegister& src);
2158 LogicVRegister frecpx(VectorFormat vform, LogicVRegister dst,
2159 const LogicVRegister& src);
2160 template <typename T>
2161 LogicVRegister fabs_(VectorFormat vform, LogicVRegister dst,
2162 const LogicVRegister& src);
2163 LogicVRegister fabs_(VectorFormat vform, LogicVRegister dst,
2164 const LogicVRegister& src);
2165 LogicVRegister fabd(VectorFormat vform, LogicVRegister dst,
2166 const LogicVRegister& src1, const LogicVRegister& src2);
2167 LogicVRegister frint(VectorFormat vform, LogicVRegister dst,
2168 const LogicVRegister& src, FPRounding rounding_mode,
2169 bool inexact_exception = false);
2170 LogicVRegister fcvts(VectorFormat vform, LogicVRegister dst,
2171 const LogicVRegister& src, FPRounding rounding_mode,
2172 int fbits = 0);
2173 LogicVRegister fcvtu(VectorFormat vform, LogicVRegister dst,
2174 const LogicVRegister& src, FPRounding rounding_mode,
2175 int fbits = 0);
2176 LogicVRegister fcvtl(VectorFormat vform, LogicVRegister dst,
2177 const LogicVRegister& src);
2178 LogicVRegister fcvtl2(VectorFormat vform, LogicVRegister dst,
2179 const LogicVRegister& src);
2180 LogicVRegister fcvtn(VectorFormat vform, LogicVRegister dst,
2181 const LogicVRegister& src);
2182 LogicVRegister fcvtn2(VectorFormat vform, LogicVRegister dst,
2183 const LogicVRegister& src);
2184 LogicVRegister fcvtxn(VectorFormat vform, LogicVRegister dst,
2185 const LogicVRegister& src);
2186 LogicVRegister fcvtxn2(VectorFormat vform, LogicVRegister dst,
2187 const LogicVRegister& src);
2188 LogicVRegister fsqrt(VectorFormat vform, LogicVRegister dst,
2189 const LogicVRegister& src);
2190 LogicVRegister frsqrte(VectorFormat vform, LogicVRegister dst,
2191 const LogicVRegister& src);
2192 LogicVRegister frecpe(VectorFormat vform, LogicVRegister dst,
2193 const LogicVRegister& src, FPRounding rounding);
2194 LogicVRegister ursqrte(VectorFormat vform, LogicVRegister dst,
2195 const LogicVRegister& src);
2196 LogicVRegister urecpe(VectorFormat vform, LogicVRegister dst,
2197 const LogicVRegister& src);
2198
2199 using FPMinMaxOp = float (Simulator::*)(float a, float b);
2200
2201 LogicVRegister FMinMaxV(VectorFormat vform, LogicVRegister dst,
2202 const LogicVRegister& src, FPMinMaxOp Op);
2203
2204 LogicVRegister fminv(VectorFormat vform, LogicVRegister dst,
2205 const LogicVRegister& src);
2206 LogicVRegister fmaxv(VectorFormat vform, LogicVRegister dst,
2207 const LogicVRegister& src);
2208 LogicVRegister fminnmv(VectorFormat vform, LogicVRegister dst,
2209 const LogicVRegister& src);
2210 LogicVRegister fmaxnmv(VectorFormat vform, LogicVRegister dst,
2211 const LogicVRegister& src);
2212
2213 template <typename T>
2214 T FPRecipSqrtEstimate(T op);
2215 template <typename T>
2216 T FPRecipEstimate(T op, FPRounding rounding);
2217 template <typename T, typename R>
2218 R FPToFixed(T op, int fbits, bool is_signed, FPRounding rounding);
2219
2220 void FPCompare(double val0, double val1);
2221 double FPRoundInt(double value, FPRounding round_mode);
2222 double FPToDouble(float value);
2223 float FPToFloat(double value, FPRounding round_mode);
2224 float FPToFloat(float16 value);
2225 float16 FPToFloat16(float value, FPRounding round_mode);
2226 float16 FPToFloat16(double value, FPRounding round_mode);
2227 double recip_sqrt_estimate(double a);
2228 double recip_estimate(double a);
2229 double FPRecipSqrtEstimate(double a);
2230 double FPRecipEstimate(double a);
2231 double FixedToDouble(int64_t src, int fbits, FPRounding round_mode);
2232 double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode);
2233 float FixedToFloat(int64_t src, int fbits, FPRounding round_mode);
2234 float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode);
2235 float16 FixedToFloat16(int64_t src, int fbits, FPRounding round_mode);
2236 float16 UFixedToFloat16(uint64_t src, int fbits, FPRounding round_mode);
2237 int16_t FPToInt16(double value, FPRounding rmode);
2238 int32_t FPToInt32(double value, FPRounding rmode);
2239 int64_t FPToInt64(double value, FPRounding rmode);
2240 uint16_t FPToUInt16(double value, FPRounding rmode);
2241 uint32_t FPToUInt32(double value, FPRounding rmode);
2242 uint64_t FPToUInt64(double value, FPRounding rmode);
2243 int32_t FPToFixedJS(double value);
2244
2245 template <typename T>
2246 T FPAdd(T op1, T op2);
2247
2248 template <typename T>
2249 T FPDiv(T op1, T op2);
2250
2251 template <typename T>
2252 T FPMax(T a, T b);
2253
2254 template <typename T>
2255 T FPMaxNM(T a, T b);
2256
2257 template <typename T>
2258 T FPMin(T a, T b);
2259
2260 template <typename T>
2261 T FPMinNM(T a, T b);
2262
2263 template <typename T>
2264 T FPMul(T op1, T op2);
2265
2266 template <typename T>
2267 T FPMulx(T op1, T op2);
2268
2269 template <typename T>
2270 T FPMulAdd(T a, T op1, T op2);
2271
2272 template <typename T>
2273 T FPSqrt(T op);
2274
2275 template <typename T>
2276 T FPSub(T op1, T op2);
2277
2278 template <typename T>
2279 T FPRecipStepFused(T op1, T op2);
2280
2281 template <typename T>
2282 T FPRSqrtStepFused(T op1, T op2);
2283
2284 // This doesn't do anything at the moment. We'll need it if we want support
2285 // for cumulative exception bits or floating-point exceptions.
2286 void FPProcessException() {}
2287
2288 // Standard NaN processing.
2289 bool FPProcessNaNs(Instruction* instr);
2290
2291 void CheckStackAlignment();
2292
2293 inline void CheckPCSComplianceAndRun();
2294
2295#ifdef DEBUG
2296 // Corruption values should have their least significant byte cleared to
2297 // allow the code of the register being corrupted to be inserted.
2298 static const uint64_t kCallerSavedRegisterCorruptionValue =
2299 0xca11edc0de000000UL;
2300 // This value is a NaN in both 32-bit and 64-bit FP.
2301 static const uint64_t kCallerSavedVRegisterCorruptionValue =
2302 0x7ff000007f801000UL;
2303 // This value is a mix of 32/64-bits NaN and "verbose" immediate.
2304 static const uint64_t kDefaultCPURegisterCorruptionValue =
2305 0x7ffbad007f8bad00UL;
2306
2307 void CorruptRegisters(CPURegList* list,
2308 uint64_t value = kDefaultCPURegisterCorruptionValue);
2309 void CorruptAllCallerSavedCPURegisters();
2310#endif
2311
2312 // Pseudo Printf instruction
2313 void DoPrintf(Instruction* instr);
2314
2315 // Pseudo instruction for switching stack limit
2316 void DoSwitchStackLimit(Instruction* instr);
2317
2318 // Processor state ---------------------------------------
2319
2320 // Output stream.
2321 FILE* stream_;
2322 PrintDisassembler* print_disasm_;
2323 void PRINTF_FORMAT(2, 3) TraceSim(const char* format, ...);
2324
2325 // General purpose registers. Register 31 is the stack pointer.
2326 SimRegister registers_[kNumberOfRegisters];
2327
2328 // Floating point registers
2329 SimVRegister vregisters_[kNumberOfVRegisters];
2330
2331 // Processor state
2332 // bits[31, 27]: Condition flags N, Z, C, and V.
2333 // (Negative, Zero, Carry, Overflow)
2334 SimSystemRegister nzcv_;
2335
2336 // Floating-Point Control Register
2337 SimSystemRegister fpcr_;
2338
2339 // Only a subset of FPCR features are supported by the simulator. This helper
2340 // checks that the FPCR settings are supported.
2341 //
2342 // This is checked when floating-point instructions are executed, not when
2343 // FPCR is set. This allows generated code to modify FPCR for external
2344 // functions, or to save and restore it when entering and leaving generated
2345 // code.
2346 void AssertSupportedFPCR() {
2347 DCHECK_EQ(fpcr().FZ(), 0); // No flush-to-zero support.
2348 DCHECK(fpcr().RMode() == FPTieEven); // Ties-to-even rounding only.
2349
2350 // The simulator does not support half-precision operations so fpcr().AHP()
2351 // is irrelevant, and is not checked here.
2352 }
2353
2354 template <typename T>
2355 static int CalcNFlag(T result) {
2356 return (result >> (sizeof(T) * 8 - 1)) & 1;
2357 }
2358
2359 static int CalcZFlag(uint64_t result) { return result == 0; }
2360
2361 static const uint32_t kConditionFlagsMask = 0xf0000000;
2362
2363 // Stack
2364 uintptr_t stack_;
2365 static const size_t kStackProtectionSize = KB;
2366 // This includes a protection margin at each end of the stack area.
2367 static size_t AllocatedStackSize() {
2368 return (v8_flags.sim_stack_size * KB) + (2 * kStackProtectionSize);
2369 }
2370 static size_t UsableStackSize() { return v8_flags.sim_stack_size * KB; }
2371 uintptr_t stack_limit_;
2372 // Added in Simulator::StackLimit()
2373 static const int kAdditionalStackMargin = 4 * KB;
2374
2375 Decoder<DispatchingDecoderVisitor>* decoder_;
2376 Decoder<DispatchingDecoderVisitor>* disassembler_decoder_;
2377
2378 // Indicates if the pc has been modified by the instruction and should not be
2379 // automatically incremented.
2380 bool pc_modified_;
2381 Instruction* pc_;
2382
2383 // Branch type register, used for branch target identification.
2384 BType btype_;
2385
2386 // Global flag for enabling guarded pages.
2387 // TODO(arm64): implement guarding at page granularity, rather than globally.
2388 bool guard_pages_;
2389
2390 static const char* xreg_names[];
2391 static const char* wreg_names[];
2392 static const char* sreg_names[];
2393 static const char* dreg_names[];
2394 static const char* vreg_names[];
2395
2396 // Debugger input.
2397 void set_last_debugger_input(ArrayUniquePtr<char> input) {
2398 last_debugger_input_ = std::move(input);
2399 }
2400 const char* last_debugger_input() { return last_debugger_input_.get(); }
2401 ArrayUniquePtr<char> last_debugger_input_;
2402
2403 // Synchronization primitives. See ARM DDI 0487A.a, B2.10. Pair types not
2404 // implemented.
2405 enum class MonitorAccess {
2406 Open,
2407 Exclusive,
2408 };
2409
2410 enum class TransactionSize {
2411 None = 0,
2412 Byte = 1,
2413 HalfWord = 2,
2414 Word = 4,
2415 DoubleWord = 8,
2416 };
2417
2418 TransactionSize get_transaction_size(unsigned size);
2419
2420 // The least-significant bits of the address are ignored. The number of bits
2421 // is implementation-defined, between 3 and 11. See ARM DDI 0487A.a, B2.10.3.
2422 static const uintptr_t kExclusiveTaggedAddrMask = ~((1 << 11) - 1);
2423
2424 class LocalMonitor {
2425 public:
2426 LocalMonitor();
2427
2428 // These functions manage the state machine for the local monitor, but do
2429 // not actually perform loads and stores. NotifyStoreExcl only returns
2430 // true if the exclusive store is allowed; the global monitor will still
2431 // have to be checked to see whether the memory should be updated.
2432 void NotifyLoad();
2433 void NotifyLoadExcl(uintptr_t addr, TransactionSize size);
2434 void NotifyStore();
2435 bool NotifyStoreExcl(uintptr_t addr, TransactionSize size);
2436
2437 private:
2438 void Clear();
2439
2440 MonitorAccess access_state_;
2441 uintptr_t tagged_addr_;
2442 TransactionSize size_;
2443 };
2444
2445 class GlobalMonitor {
2446 public:
2447 class SimulatorMutex final {
2448 public:
2449 explicit SimulatorMutex(GlobalMonitor* global_monitor) {
2450 if (!global_monitor->IsSingleThreaded()) {
2451 guard.emplace(global_monitor->mutex_);
2452 }
2453 }
2454
2455 private:
2456 std::optional<base::MutexGuard> guard;
2457 };
2458
2459 class Processor {
2460 public:
2461 Processor();
2462
2463 private:
2464 friend class GlobalMonitor;
2465 // These functions manage the state machine for the global monitor, but do
2466 // not actually perform loads and stores.
2467 void Clear_Locked();
2468 void NotifyLoadExcl_Locked(uintptr_t addr);
2469 void NotifyStore_Locked(bool is_requesting_processor);
2470 bool NotifyStoreExcl_Locked(uintptr_t addr, bool is_requesting_processor);
2471
2472 MonitorAccess access_state_;
2473 uintptr_t tagged_addr_;
2474 Processor* next_;
2475 Processor* prev_;
2476 // A stxr can fail due to background cache evictions. Rather than
2477 // simulating this, we'll just occasionally introduce cases where an
2478 // exclusive store fails. This will happen once after every
2479 // kMaxFailureCounter exclusive stores.
2480 static const int kMaxFailureCounter = 5;
2481 int failure_counter_;
2482 };
2483
2484 void NotifyLoadExcl_Locked(uintptr_t addr, Processor* processor);
2485 void NotifyStore_Locked(Processor* processor);
2486 bool NotifyStoreExcl_Locked(uintptr_t addr, Processor* processor);
2487
2488 // Called when the simulator is constructed.
2489 void PrependProcessor(Processor* processor);
2490 // Called when the simulator is destroyed.
2491 void RemoveProcessor(Processor* processor);
2492
2493 static GlobalMonitor* Get();
2494
2495 private:
2496 bool IsSingleThreaded() const { return num_processors_ == 1; }
2497
2498 // Private constructor. Call {GlobalMonitor::Get()} to get the singleton.
2499 GlobalMonitor() = default;
2500 friend class base::LeakyObject<GlobalMonitor>;
2501
2502 Processor* head_ = nullptr;
2503 std::atomic<uint32_t> num_processors_ = 0;
2504 base::Mutex mutex_;
2505 };
2506
2507 LocalMonitor local_monitor_;
2508 GlobalMonitor::Processor global_monitor_processor_;
2509 GlobalMonitor* global_monitor_;
2510
2511 private:
2512 void Init(FILE* stream);
2513
2514 V8_EXPORT_PRIVATE void CallImpl(Address entry, CallArgument* args);
2515
2516 void CallAnyCTypeFunction(Address target_address,
2517 const EncodedCSignature& signature);
2518
2519 // Read floating point return values.
2520 template <typename T>
2521 T ReadReturn()
2522 requires std::is_floating_point<T>::value
2523 {
2524 return static_cast<T>(dreg(0));
2525 }
2526 // Read non-float return values.
2527 template <typename T>
2528 T ReadReturn()
2529 requires(!std::is_floating_point<T>::value)
2530 {
2531 return ConvertReturn<T>(xreg(0));
2532 }
2533
2534 template <typename T>
2535 static T FPDefaultNaN();
2536
2537 template <typename T>
2538 T FPProcessNaN(T op) {
2539 DCHECK(std::isnan(op));
2540 return fpcr().DN() ? FPDefaultNaN<T>() : ToQuietNaN(op);
2541 }
2542
2543 template <typename T>
2544 T FPProcessNaNs(T op1, T op2) {
2545 if (IsSignallingNaN(op1)) {
2546 return FPProcessNaN(op1);
2547 } else if (IsSignallingNaN(op2)) {
2548 return FPProcessNaN(op2);
2549 } else if (std::isnan(op1)) {
2550 DCHECK(IsQuietNaN(op1));
2551 return FPProcessNaN(op1);
2552 } else if (std::isnan(op2)) {
2553 DCHECK(IsQuietNaN(op2));
2554 return FPProcessNaN(op2);
2555 } else {
2556 return 0.0;
2557 }
2558 }
2559
2560 template <typename T>
2561 T FPProcessNaNs3(T op1, T op2, T op3) {
2562 if (IsSignallingNaN(op1)) {
2563 return FPProcessNaN(op1);
2564 } else if (IsSignallingNaN(op2)) {
2565 return FPProcessNaN(op2);
2566 } else if (IsSignallingNaN(op3)) {
2567 return FPProcessNaN(op3);
2568 } else if (std::isnan(op1)) {
2569 DCHECK(IsQuietNaN(op1));
2570 return FPProcessNaN(op1);
2571 } else if (std::isnan(op2)) {
2572 DCHECK(IsQuietNaN(op2));
2573 return FPProcessNaN(op2);
2574 } else if (std::isnan(op3)) {
2575 DCHECK(IsQuietNaN(op3));
2576 return FPProcessNaN(op3);
2577 } else {
2578 return 0.0;
2579 }
2580 }
2581
2582 int log_parameters_;
2583 // Instruction counter only valid if v8_flags.stop_sim_at isn't 0.
2584 int icount_for_stop_sim_at_;
2585 Isolate* isolate_;
2586};
2587
2588template <>
2589inline double Simulator::FPDefaultNaN<double>() {
2590 return kFP64DefaultNaN;
2591}
2592
2593template <>
2594inline float Simulator::FPDefaultNaN<float>() {
2595 return kFP32DefaultNaN;
2596}
2597
2598template <>
2599inline float16 Simulator::FPDefaultNaN<float16>() {
2600 return kFP16DefaultNaN;
2601}
2602
2603} // namespace internal
2604} // namespace v8
2605
2606#endif // defined(USE_SIMULATOR)
2607#endif // V8_EXECUTION_ARM64_SIMULATOR_ARM64_H_
Isolate * isolate_
#define T
#define one
Register const value_
base::Mutex & mutex_
Handle< Code > code
const int size_
Definition assembler.cc:132
const ObjectRef type_
#define SYSTEM_REGISTER_FIELDS_LIST(V_, M_)
int start
#define VISITOR_LIST(V)
#define DECLARE(A)
LineAndColumn current
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
refactor address components for immediate indexing make OptimizeMaglevOnNextCall optimize to turbofan instead of maglev filter for tracing turbofan compilation trace turbo cfg trace TurboFan s graph trimmer trace TurboFan s control equivalence trace TurboFan s register allocator trace stack load store counters for optimized code in run fuzzing &&concurrent_recompilation trace_turbo trace_turbo_scheduled trace_turbo_stack_accesses verify TurboFan machine graph of code stubs enable FixedArray bounds checks print TurboFan statistics of wasm compilations maximum cumulative size of bytecode considered for inlining scale factor of bytecode size used to calculate the inlining budget * KB
OptionalOpIndex index
int32_t offset
#define DEFINE_GETTER(Name, HighBit, LowBit, Func)
std::optional< TNode< JSArray > > a
RoundingMode rounding_mode
Instruction * instr
ZoneVector< RpoNumber > & result
LiftoffRegister reg
int y
int x
int r
Definition mul-fft.cc:298
STL namespace.
int int32_t
Definition unicode.cc:40
unsigned short uint16_t
Definition unicode.cc:39
signed short int16_t
Definition unicode.cc:38
uintptr_t Address
Definition memory.h:13
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
Definition graph.h:1231
UntaggedUnion< Float32, Float64 > Float
Definition index.h:536
UntaggedUnion< Word32, Word64 > Word
Definition index.h:535
V8_INLINE Address AuthPAC(Address pc, Address sp)
bool IsSignallingNaN(double num)
Definition utils-arm64.h:82
V8_EXPORT_PRIVATE int LaneCountFromFormat(VectorFormat vform)
bool Is(IndirectHandle< U > value)
Definition handles-inl.h:51
void PrintF(const char *format,...)
Definition utils.cc:39
int32_t signed_bitextract_32(int msb, int lsb, uint32_t x)
Definition utils.h:563
constexpr int kSRegSize
constexpr int kHRegSize
int64_t MinIntFromFormat(VectorFormat vform)
V8_EXPORT_PRIVATE const double kFP64DefaultNaN
V8_EXPORT_PRIVATE const float kFP32DefaultNaN
uint64_t MaxUintFromFormat(VectorFormat vform)
double ToQuietNaN(double num)
const float16 kFP16DefaultNaN
bool IsQuietNaN(T num)
constexpr int U
constexpr int kQRegSizeLog2
int64_t MaxIntFromFormat(VectorFormat vform)
constexpr int kDRegSizeLog2
constexpr int kBRegSize
constexpr int kQRegSize
unsigned LaneSizeInBitsFromFormat(VectorFormat vform)
V8_EXPORT_PRIVATE FlagValues v8_flags
constexpr int kDRegSize
static int CountLeadingZeros(uint64_t value, int width)
Definition utils-arm64.h:34
unsigned RegisterSizeInBytesFromFormat(VectorFormat vform)
uint32_t unsigned_bitextract_32(int msb, int lsb, uint32_t x)
Definition utils.h:555
@ None
Definition v8-object.h:141
base::SmallVector< RegisterT, kStaticCapacity > registers_
const uintptr_t stack_limit_
Node * prev_
#define PRINTF_FORMAT(format_param, dots_param)
#define UNREACHABLE()
Definition logging.h:67
#define FATAL(...)
Definition logging.h:47
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define UNIMPLEMENTED()
Definition logging.h:66
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define USE(...)
Definition macros.h:293
#define V8_EXPORT_PRIVATE
Definition macros.h:460
constexpr bool IsAligned(T value, U alignment)
Definition macros.h:403
#define arraysize(array)
Definition macros.h:67
std::unique_ptr< ValueMirror > value
std::unique_ptr< ValueMirror > key