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