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