| Index: src/arm64/simulator-arm64.h
|
| diff --git a/src/arm64/simulator-arm64.h b/src/arm64/simulator-arm64.h
|
| index 918f0e96de31d5dc31d4503be1902874957adbae..3016e616e4df8b8d1c41bba8df303f8a0c851125 100644
|
| --- a/src/arm64/simulator-arm64.h
|
| +++ b/src/arm64/simulator-arm64.h
|
| @@ -70,239 +70,6 @@ class SimulatorStack : public v8::internal::AllStatic {
|
|
|
| #else // !defined(USE_SIMULATOR)
|
|
|
| -// Assemble the specified IEEE-754 components into the target type and apply
|
| -// appropriate rounding.
|
| -// sign: 0 = positive, 1 = negative
|
| -// exponent: Unbiased IEEE-754 exponent.
|
| -// mantissa: The mantissa of the input. The top bit (which is not encoded for
|
| -// normal IEEE-754 values) must not be omitted. This bit has the
|
| -// value 'pow(2, exponent)'.
|
| -//
|
| -// The input value is assumed to be a normalized value. That is, the input may
|
| -// not be infinity or NaN. If the source value is subnormal, it must be
|
| -// normalized before calling this function such that the highest set bit in the
|
| -// mantissa has the value 'pow(2, exponent)'.
|
| -//
|
| -// Callers should use FPRoundToFloat or FPRoundToDouble directly, rather than
|
| -// calling a templated FPRound.
|
| -template <class T, int ebits, int mbits>
|
| -T FPRound(int64_t sign, int64_t exponent, uint64_t mantissa,
|
| - FPRounding round_mode) {
|
| - static_assert((sizeof(T) * 8) >= (1 + ebits + mbits),
|
| - "destination type T not large enough");
|
| - static_assert(sizeof(T) <= sizeof(uint64_t),
|
| - "maximum size of destination type T is 64 bits");
|
| - static_assert(std::is_unsigned<T>::value,
|
| - "destination type T must be unsigned");
|
| -
|
| - DCHECK((sign == 0) || (sign == 1));
|
| -
|
| - // Only FPTieEven and FPRoundOdd rounding modes are implemented.
|
| - DCHECK((round_mode == FPTieEven) || (round_mode == FPRoundOdd));
|
| -
|
| - // Rounding can promote subnormals to normals, and normals to infinities. For
|
| - // example, a double with exponent 127 (FLT_MAX_EXP) would appear to be
|
| - // encodable as a float, but rounding based on the low-order mantissa bits
|
| - // could make it overflow. With ties-to-even rounding, this value would become
|
| - // an infinity.
|
| -
|
| - // ---- Rounding Method ----
|
| - //
|
| - // The exponent is irrelevant in the rounding operation, so we treat the
|
| - // lowest-order bit that will fit into the result ('onebit') as having
|
| - // the value '1'. Similarly, the highest-order bit that won't fit into
|
| - // the result ('halfbit') has the value '0.5'. The 'point' sits between
|
| - // 'onebit' and 'halfbit':
|
| - //
|
| - // These bits fit into the result.
|
| - // |---------------------|
|
| - // mantissa = 0bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
| - // ||
|
| - // / |
|
| - // / halfbit
|
| - // onebit
|
| - //
|
| - // For subnormal outputs, the range of representable bits is smaller and
|
| - // the position of onebit and halfbit depends on the exponent of the
|
| - // input, but the method is otherwise similar.
|
| - //
|
| - // onebit(frac)
|
| - // |
|
| - // | halfbit(frac) halfbit(adjusted)
|
| - // | / /
|
| - // | | |
|
| - // 0b00.0 (exact) -> 0b00.0 (exact) -> 0b00
|
| - // 0b00.0... -> 0b00.0... -> 0b00
|
| - // 0b00.1 (exact) -> 0b00.0111..111 -> 0b00
|
| - // 0b00.1... -> 0b00.1... -> 0b01
|
| - // 0b01.0 (exact) -> 0b01.0 (exact) -> 0b01
|
| - // 0b01.0... -> 0b01.0... -> 0b01
|
| - // 0b01.1 (exact) -> 0b01.1 (exact) -> 0b10
|
| - // 0b01.1... -> 0b01.1... -> 0b10
|
| - // 0b10.0 (exact) -> 0b10.0 (exact) -> 0b10
|
| - // 0b10.0... -> 0b10.0... -> 0b10
|
| - // 0b10.1 (exact) -> 0b10.0111..111 -> 0b10
|
| - // 0b10.1... -> 0b10.1... -> 0b11
|
| - // 0b11.0 (exact) -> 0b11.0 (exact) -> 0b11
|
| - // ... / | / |
|
| - // / | / |
|
| - // / |
|
| - // adjusted = frac - (halfbit(mantissa) & ~onebit(frac)); / |
|
| - //
|
| - // mantissa = (mantissa >> shift) + halfbit(adjusted);
|
| -
|
| - const int mantissa_offset = 0;
|
| - const int exponent_offset = mantissa_offset + mbits;
|
| - const int sign_offset = exponent_offset + ebits;
|
| - DCHECK_EQ(sign_offset, static_cast<int>(sizeof(T) * 8 - 1));
|
| -
|
| - // Bail out early for zero inputs.
|
| - if (mantissa == 0) {
|
| - return static_cast<T>(sign << sign_offset);
|
| - }
|
| -
|
| - // If all bits in the exponent are set, the value is infinite or NaN.
|
| - // This is true for all binary IEEE-754 formats.
|
| - const int infinite_exponent = (1 << ebits) - 1;
|
| - const int max_normal_exponent = infinite_exponent - 1;
|
| -
|
| - // Apply the exponent bias to encode it for the result. Doing this early makes
|
| - // it easy to detect values that will be infinite or subnormal.
|
| - exponent += max_normal_exponent >> 1;
|
| -
|
| - if (exponent > max_normal_exponent) {
|
| - // Overflow: the input is too large for the result type to represent.
|
| - if (round_mode == FPTieEven) {
|
| - // FPTieEven rounding mode handles overflows using infinities.
|
| - exponent = infinite_exponent;
|
| - mantissa = 0;
|
| - } else {
|
| - DCHECK_EQ(round_mode, FPRoundOdd);
|
| - // FPRoundOdd rounding mode handles overflows using the largest magnitude
|
| - // normal number.
|
| - exponent = max_normal_exponent;
|
| - mantissa = (UINT64_C(1) << exponent_offset) - 1;
|
| - }
|
| - return static_cast<T>((sign << sign_offset) |
|
| - (exponent << exponent_offset) |
|
| - (mantissa << mantissa_offset));
|
| - }
|
| -
|
| - // Calculate the shift required to move the top mantissa bit to the proper
|
| - // place in the destination type.
|
| - const int highest_significant_bit = 63 - CountLeadingZeros(mantissa, 64);
|
| - int shift = highest_significant_bit - mbits;
|
| -
|
| - if (exponent <= 0) {
|
| - // The output will be subnormal (before rounding).
|
| - // For subnormal outputs, the shift must be adjusted by the exponent. The +1
|
| - // is necessary because the exponent of a subnormal value (encoded as 0) is
|
| - // the same as the exponent of the smallest normal value (encoded as 1).
|
| - shift += -exponent + 1;
|
| -
|
| - // Handle inputs that would produce a zero output.
|
| - //
|
| - // Shifts higher than highest_significant_bit+1 will always produce a zero
|
| - // result. A shift of exactly highest_significant_bit+1 might produce a
|
| - // non-zero result after rounding.
|
| - if (shift > (highest_significant_bit + 1)) {
|
| - if (round_mode == FPTieEven) {
|
| - // The result will always be +/-0.0.
|
| - return static_cast<T>(sign << sign_offset);
|
| - } else {
|
| - DCHECK_EQ(round_mode, FPRoundOdd);
|
| - DCHECK_NE(mantissa, 0U);
|
| - // For FPRoundOdd, if the mantissa is too small to represent and
|
| - // non-zero return the next "odd" value.
|
| - return static_cast<T>((sign << sign_offset) | 1);
|
| - }
|
| - }
|
| -
|
| - // Properly encode the exponent for a subnormal output.
|
| - exponent = 0;
|
| - } else {
|
| - // Clear the topmost mantissa bit, since this is not encoded in IEEE-754
|
| - // normal values.
|
| - mantissa &= ~(UINT64_C(1) << highest_significant_bit);
|
| - }
|
| -
|
| - if (shift > 0) {
|
| - if (round_mode == FPTieEven) {
|
| - // We have to shift the mantissa to the right. Some precision is lost, so
|
| - // we need to apply rounding.
|
| - uint64_t onebit_mantissa = (mantissa >> (shift)) & 1;
|
| - uint64_t halfbit_mantissa = (mantissa >> (shift - 1)) & 1;
|
| - uint64_t adjustment = (halfbit_mantissa & ~onebit_mantissa);
|
| - uint64_t adjusted = mantissa - adjustment;
|
| - T halfbit_adjusted = (adjusted >> (shift - 1)) & 1;
|
| -
|
| - T result =
|
| - static_cast<T>((sign << sign_offset) | (exponent << exponent_offset) |
|
| - ((mantissa >> shift) << mantissa_offset));
|
| -
|
| - // A very large mantissa can overflow during rounding. If this happens,
|
| - // the exponent should be incremented and the mantissa set to 1.0
|
| - // (encoded as 0). Applying halfbit_adjusted after assembling the float
|
| - // has the nice side-effect that this case is handled for free.
|
| - //
|
| - // This also handles cases where a very large finite value overflows to
|
| - // infinity, or where a very large subnormal value overflows to become
|
| - // normal.
|
| - return result + halfbit_adjusted;
|
| - } else {
|
| - DCHECK_EQ(round_mode, FPRoundOdd);
|
| - // If any bits at position halfbit or below are set, onebit (ie. the
|
| - // bottom bit of the resulting mantissa) must be set.
|
| - uint64_t fractional_bits = mantissa & ((UINT64_C(1) << shift) - 1);
|
| - if (fractional_bits != 0) {
|
| - mantissa |= UINT64_C(1) << shift;
|
| - }
|
| -
|
| - return static_cast<T>((sign << sign_offset) |
|
| - (exponent << exponent_offset) |
|
| - ((mantissa >> shift) << mantissa_offset));
|
| - }
|
| - } else {
|
| - // We have to shift the mantissa to the left (or not at all). The input
|
| - // mantissa is exactly representable in the output mantissa, so apply no
|
| - // rounding correction.
|
| - return static_cast<T>((sign << sign_offset) |
|
| - (exponent << exponent_offset) |
|
| - ((mantissa << -shift) << mantissa_offset));
|
| - }
|
| -}
|
| -
|
| -// Representation of memory, with typed getters and setters for access.
|
| -class SimMemory {
|
| - public:
|
| - template <typename T>
|
| - static T AddressUntag(T address) {
|
| - // Cast the address using a C-style cast. A reinterpret_cast would be
|
| - // appropriate, but it can't cast one integral type to another.
|
| - uint64_t bits = (uint64_t)address;
|
| - return (T)(bits & ~kAddressTagMask);
|
| - }
|
| -
|
| - template <typename T, typename A>
|
| - static T Read(A address) {
|
| - T value;
|
| - address = AddressUntag(address);
|
| - DCHECK((sizeof(value) == 1) || (sizeof(value) == 2) ||
|
| - (sizeof(value) == 4) || (sizeof(value) == 8) ||
|
| - (sizeof(value) == 16));
|
| - memcpy(&value, reinterpret_cast<const char*>(address), sizeof(value));
|
| - return value;
|
| - }
|
| -
|
| - template <typename T, typename A>
|
| - static void Write(A address, T value) {
|
| - address = AddressUntag(address);
|
| - DCHECK((sizeof(value) == 1) || (sizeof(value) == 2) ||
|
| - (sizeof(value) == 4) || (sizeof(value) == 8) ||
|
| - (sizeof(value) == 16));
|
| - memcpy(reinterpret_cast<char*>(address), &value, sizeof(value));
|
| - }
|
| -};
|
|
|
| // The proper way to initialize a simulated system register (such as NZCV) is as
|
| // follows:
|
| @@ -358,330 +125,29 @@ class SimSystemRegister {
|
|
|
|
|
| // Represent a register (r0-r31, v0-v31).
|
| -template <int kSizeInBytes>
|
| class SimRegisterBase {
|
| public:
|
| template<typename T>
|
| void Set(T new_value) {
|
| - static_assert(sizeof(new_value) <= kSizeInBytes,
|
| - "Size of new_value must be <= size of template type.");
|
| - if (sizeof(new_value) < kSizeInBytes) {
|
| - // All AArch64 registers are zero-extending.
|
| - memset(value_ + sizeof(new_value), 0, kSizeInBytes - sizeof(new_value));
|
| - }
|
| + value_ = 0;
|
| memcpy(&value_, &new_value, sizeof(T));
|
| - NotifyRegisterWrite();
|
| }
|
|
|
| - // Insert a typed value into a register, leaving the rest of the register
|
| - // unchanged. The lane parameter indicates where in the register the value
|
| - // should be inserted, in the range [ 0, sizeof(value_) / sizeof(T) ), where
|
| - // 0 represents the least significant bits.
|
| - template <typename T>
|
| - void Insert(int lane, T new_value) {
|
| - DCHECK_GE(lane, 0);
|
| - DCHECK_LE(sizeof(new_value) + (lane * sizeof(new_value)),
|
| - static_cast<unsigned>(kSizeInBytes));
|
| - memcpy(&value_[lane * sizeof(new_value)], &new_value, sizeof(new_value));
|
| - NotifyRegisterWrite();
|
| - }
|
| -
|
| - template <typename T>
|
| - T Get(int lane = 0) const {
|
| + template<typename T>
|
| + T Get() const {
|
| T result;
|
| - DCHECK_GE(lane, 0);
|
| - DCHECK_LE(sizeof(result) + (lane * sizeof(result)),
|
| - static_cast<unsigned>(kSizeInBytes));
|
| - memcpy(&result, &value_[lane * sizeof(result)], sizeof(result));
|
| + memcpy(&result, &value_, sizeof(T));
|
| return result;
|
| }
|
|
|
| - // TODO(all): Make this return a map of updated bytes, so that we can
|
| - // highlight updated lanes for load-and-insert. (That never happens for scalar
|
| - // code, but NEON has some instructions that can update individual lanes.)
|
| - bool WrittenSinceLastLog() const { return written_since_last_log_; }
|
| -
|
| - void NotifyRegisterLogged() { written_since_last_log_ = false; }
|
| -
|
| protected:
|
| - uint8_t value_[kSizeInBytes];
|
| -
|
| - // Helpers to aid with register tracing.
|
| - bool written_since_last_log_;
|
| -
|
| - void NotifyRegisterWrite() { written_since_last_log_ = true; }
|
| + int64_t value_;
|
| };
|
|
|
| -typedef SimRegisterBase<kXRegSize> SimRegister; // r0-r31
|
| -typedef SimRegisterBase<kQRegSize> SimVRegister; // v0-v31
|
| -
|
| -// Representation of a vector register, with typed getters and setters for lanes
|
| -// and additional information to represent lane state.
|
| -class LogicVRegister {
|
| - public:
|
| - inline LogicVRegister(SimVRegister& other) // NOLINT
|
| - : register_(other) {
|
| - for (unsigned i = 0; i < arraysize(saturated_); i++) {
|
| - saturated_[i] = kNotSaturated;
|
| - }
|
| - for (unsigned i = 0; i < arraysize(round_); i++) {
|
| - round_[i] = false;
|
| - }
|
| - }
|
| -
|
| - int64_t Int(VectorFormat vform, int index) const {
|
| - int64_t element;
|
| - switch (LaneSizeInBitsFromFormat(vform)) {
|
| - case 8:
|
| - element = register_.Get<int8_t>(index);
|
| - break;
|
| - case 16:
|
| - element = register_.Get<int16_t>(index);
|
| - break;
|
| - case 32:
|
| - element = register_.Get<int32_t>(index);
|
| - break;
|
| - case 64:
|
| - element = register_.Get<int64_t>(index);
|
| - break;
|
| - default:
|
| - UNREACHABLE();
|
| - return 0;
|
| - }
|
| - return element;
|
| - }
|
| -
|
| - uint64_t Uint(VectorFormat vform, int index) const {
|
| - uint64_t element;
|
| - switch (LaneSizeInBitsFromFormat(vform)) {
|
| - case 8:
|
| - element = register_.Get<uint8_t>(index);
|
| - break;
|
| - case 16:
|
| - element = register_.Get<uint16_t>(index);
|
| - break;
|
| - case 32:
|
| - element = register_.Get<uint32_t>(index);
|
| - break;
|
| - case 64:
|
| - element = register_.Get<uint64_t>(index);
|
| - break;
|
| - default:
|
| - UNREACHABLE();
|
| - return 0;
|
| - }
|
| - return element;
|
| - }
|
| -
|
| - uint64_t UintLeftJustified(VectorFormat vform, int index) const {
|
| - return Uint(vform, index) << (64 - LaneSizeInBitsFromFormat(vform));
|
| - }
|
| -
|
| - int64_t IntLeftJustified(VectorFormat vform, int index) const {
|
| - uint64_t value = UintLeftJustified(vform, index);
|
| - int64_t result;
|
| - memcpy(&result, &value, sizeof(result));
|
| - return result;
|
| - }
|
| -
|
| - void SetInt(VectorFormat vform, int index, int64_t value) const {
|
| - switch (LaneSizeInBitsFromFormat(vform)) {
|
| - case 8:
|
| - register_.Insert(index, static_cast<int8_t>(value));
|
| - break;
|
| - case 16:
|
| - register_.Insert(index, static_cast<int16_t>(value));
|
| - break;
|
| - case 32:
|
| - register_.Insert(index, static_cast<int32_t>(value));
|
| - break;
|
| - case 64:
|
| - register_.Insert(index, static_cast<int64_t>(value));
|
| - break;
|
| - default:
|
| - UNREACHABLE();
|
| - return;
|
| - }
|
| - }
|
| -
|
| - void SetIntArray(VectorFormat vform, const int64_t* src) const {
|
| - ClearForWrite(vform);
|
| - for (int i = 0; i < LaneCountFromFormat(vform); i++) {
|
| - SetInt(vform, i, src[i]);
|
| - }
|
| - }
|
| -
|
| - void SetUint(VectorFormat vform, int index, uint64_t value) const {
|
| - switch (LaneSizeInBitsFromFormat(vform)) {
|
| - case 8:
|
| - register_.Insert(index, static_cast<uint8_t>(value));
|
| - break;
|
| - case 16:
|
| - register_.Insert(index, static_cast<uint16_t>(value));
|
| - break;
|
| - case 32:
|
| - register_.Insert(index, static_cast<uint32_t>(value));
|
| - break;
|
| - case 64:
|
| - register_.Insert(index, static_cast<uint64_t>(value));
|
| - break;
|
| - default:
|
| - UNREACHABLE();
|
| - return;
|
| - }
|
| - }
|
| -
|
| - void SetUintArray(VectorFormat vform, const uint64_t* src) const {
|
| - ClearForWrite(vform);
|
| - for (int i = 0; i < LaneCountFromFormat(vform); i++) {
|
| - SetUint(vform, i, src[i]);
|
| - }
|
| - }
|
| -
|
| - void ReadUintFromMem(VectorFormat vform, int index, uint64_t addr) const;
|
| -
|
| - void WriteUintToMem(VectorFormat vform, int index, uint64_t addr) const;
|
| -
|
| - template <typename T>
|
| - T Float(int index) const {
|
| - return register_.Get<T>(index);
|
| - }
|
| -
|
| - template <typename T>
|
| - void SetFloat(int index, T value) const {
|
| - register_.Insert(index, value);
|
| - }
|
| -
|
| - // When setting a result in a register of size less than Q, the top bits of
|
| - // the Q register must be cleared.
|
| - void ClearForWrite(VectorFormat vform) const {
|
| - unsigned size = RegisterSizeInBytesFromFormat(vform);
|
| - for (unsigned i = size; i < kQRegSize; i++) {
|
| - SetUint(kFormat16B, i, 0);
|
| - }
|
| - }
|
|
|
| - // Saturation state for each lane of a vector.
|
| - enum Saturation {
|
| - kNotSaturated = 0,
|
| - kSignedSatPositive = 1 << 0,
|
| - kSignedSatNegative = 1 << 1,
|
| - kSignedSatMask = kSignedSatPositive | kSignedSatNegative,
|
| - kSignedSatUndefined = kSignedSatMask,
|
| - kUnsignedSatPositive = 1 << 2,
|
| - kUnsignedSatNegative = 1 << 3,
|
| - kUnsignedSatMask = kUnsignedSatPositive | kUnsignedSatNegative,
|
| - kUnsignedSatUndefined = kUnsignedSatMask
|
| - };
|
| -
|
| - // Getters for saturation state.
|
| - Saturation GetSignedSaturation(int index) {
|
| - return static_cast<Saturation>(saturated_[index] & kSignedSatMask);
|
| - }
|
| -
|
| - Saturation GetUnsignedSaturation(int index) {
|
| - return static_cast<Saturation>(saturated_[index] & kUnsignedSatMask);
|
| - }
|
| -
|
| - // Setters for saturation state.
|
| - void ClearSat(int index) { saturated_[index] = kNotSaturated; }
|
| -
|
| - void SetSignedSat(int index, bool positive) {
|
| - SetSatFlag(index, positive ? kSignedSatPositive : kSignedSatNegative);
|
| - }
|
| +typedef SimRegisterBase SimRegister; // r0-r31
|
| +typedef SimRegisterBase SimFPRegister; // v0-v31
|
|
|
| - void SetUnsignedSat(int index, bool positive) {
|
| - SetSatFlag(index, positive ? kUnsignedSatPositive : kUnsignedSatNegative);
|
| - }
|
| -
|
| - void SetSatFlag(int index, Saturation sat) {
|
| - saturated_[index] = static_cast<Saturation>(saturated_[index] | sat);
|
| - DCHECK_NE(sat & kUnsignedSatMask, kUnsignedSatUndefined);
|
| - DCHECK_NE(sat & kSignedSatMask, kSignedSatUndefined);
|
| - }
|
| -
|
| - // Saturate lanes of a vector based on saturation state.
|
| - LogicVRegister& SignedSaturate(VectorFormat vform) {
|
| - for (int i = 0; i < LaneCountFromFormat(vform); i++) {
|
| - Saturation sat = GetSignedSaturation(i);
|
| - if (sat == kSignedSatPositive) {
|
| - SetInt(vform, i, MaxIntFromFormat(vform));
|
| - } else if (sat == kSignedSatNegative) {
|
| - SetInt(vform, i, MinIntFromFormat(vform));
|
| - }
|
| - }
|
| - return *this;
|
| - }
|
| -
|
| - LogicVRegister& UnsignedSaturate(VectorFormat vform) {
|
| - for (int i = 0; i < LaneCountFromFormat(vform); i++) {
|
| - Saturation sat = GetUnsignedSaturation(i);
|
| - if (sat == kUnsignedSatPositive) {
|
| - SetUint(vform, i, MaxUintFromFormat(vform));
|
| - } else if (sat == kUnsignedSatNegative) {
|
| - SetUint(vform, i, 0);
|
| - }
|
| - }
|
| - return *this;
|
| - }
|
| -
|
| - // Getter for rounding state.
|
| - bool GetRounding(int index) { return round_[index]; }
|
| -
|
| - // Setter for rounding state.
|
| - void SetRounding(int index, bool round) { round_[index] = round; }
|
| -
|
| - // Round lanes of a vector based on rounding state.
|
| - LogicVRegister& Round(VectorFormat vform) {
|
| - for (int i = 0; i < LaneCountFromFormat(vform); i++) {
|
| - SetUint(vform, i, Uint(vform, i) + (GetRounding(i) ? 1 : 0));
|
| - }
|
| - return *this;
|
| - }
|
| -
|
| - // Unsigned halve lanes of a vector, and use the saturation state to set the
|
| - // top bit.
|
| - LogicVRegister& Uhalve(VectorFormat vform) {
|
| - for (int i = 0; i < LaneCountFromFormat(vform); i++) {
|
| - uint64_t val = Uint(vform, i);
|
| - SetRounding(i, (val & 1) == 1);
|
| - val >>= 1;
|
| - if (GetUnsignedSaturation(i) != kNotSaturated) {
|
| - // If the operation causes unsigned saturation, the bit shifted into the
|
| - // most significant bit must be set.
|
| - val |= (MaxUintFromFormat(vform) >> 1) + 1;
|
| - }
|
| - SetInt(vform, i, val);
|
| - }
|
| - return *this;
|
| - }
|
| -
|
| - // Signed halve lanes of a vector, and use the carry state to set the top bit.
|
| - LogicVRegister& Halve(VectorFormat vform) {
|
| - for (int i = 0; i < LaneCountFromFormat(vform); i++) {
|
| - int64_t val = Int(vform, i);
|
| - SetRounding(i, (val & 1) == 1);
|
| - val >>= 1;
|
| - if (GetSignedSaturation(i) != kNotSaturated) {
|
| - // If the operation causes signed saturation, the sign bit must be
|
| - // inverted.
|
| - val ^= (MaxUintFromFormat(vform) >> 1) + 1;
|
| - }
|
| - SetInt(vform, i, val);
|
| - }
|
| - return *this;
|
| - }
|
| -
|
| - private:
|
| - SimVRegister& register_;
|
| -
|
| - // Allocate one saturation state entry per lane; largest register is type Q,
|
| - // and lanes can be a minimum of one byte wide.
|
| - Saturation saturated_[kQRegSize];
|
| -
|
| - // Allocate one rounding state entry per lane.
|
| - bool round_[kQRegSize];
|
| -};
|
|
|
| class Simulator : public DecoderVisitor {
|
| public:
|
| @@ -849,7 +315,6 @@ class Simulator : public DecoderVisitor {
|
| CheckBreakNext();
|
| Decode(pc_);
|
| increment_pc();
|
| - LogAllWrittenRegisters();
|
| CheckBreakpoints();
|
| }
|
|
|
| @@ -868,7 +333,7 @@ class Simulator : public DecoderVisitor {
|
| //
|
| template<typename T>
|
| T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
|
| - DCHECK_LT(code, static_cast<unsigned>(kNumberOfRegisters));
|
| + DCHECK(code < kNumberOfRegisters);
|
| if (IsZeroRegister(code, r31mode)) {
|
| return 0;
|
| }
|
| @@ -884,8 +349,6 @@ class Simulator : public DecoderVisitor {
|
| return reg<int64_t>(code, r31mode);
|
| }
|
|
|
| - enum RegLogMode { LogRegWrites, NoRegLog };
|
| -
|
| // Write 'value' into an integer register. The value is zero-extended. This
|
| // behaviour matches AArch64 register writes.
|
| template<typename T>
|
| @@ -910,7 +373,7 @@ class Simulator : public DecoderVisitor {
|
| template <typename T>
|
| void set_reg_no_log(unsigned code, T value,
|
| Reg31Mode r31mode = Reg31IsZeroRegister) {
|
| - DCHECK_LT(code, static_cast<unsigned>(kNumberOfRegisters));
|
| + DCHECK(code < kNumberOfRegisters);
|
| if (!IsZeroRegister(code, r31mode)) {
|
| registers_[code].Set(value);
|
| }
|
| @@ -929,39 +392,16 @@ class Simulator : public DecoderVisitor {
|
| // Commonly-used special cases.
|
| template<typename T>
|
| void set_lr(T value) {
|
| - DCHECK_EQ(sizeof(T), static_cast<unsigned>(kPointerSize));
|
| + DCHECK(sizeof(T) == kPointerSize);
|
| set_reg(kLinkRegCode, value);
|
| }
|
|
|
| template<typename T>
|
| void set_sp(T value) {
|
| - DCHECK_EQ(sizeof(T), static_cast<unsigned>(kPointerSize));
|
| + DCHECK(sizeof(T) == kPointerSize);
|
| set_reg(31, value, Reg31IsStackPointer);
|
| }
|
|
|
| - // Vector register accessors.
|
| - // These are equivalent to the integer register accessors, but for vector
|
| - // registers.
|
| -
|
| - // A structure for representing a 128-bit Q register.
|
| - struct qreg_t {
|
| - uint8_t val[kQRegSize];
|
| - };
|
| -
|
| - // Basic accessor: read the register as the specified type.
|
| - template <typename T>
|
| - T vreg(unsigned code) const {
|
| - static_assert((sizeof(T) == kBRegSize) || (sizeof(T) == kHRegSize) ||
|
| - (sizeof(T) == kSRegSize) || (sizeof(T) == kDRegSize) ||
|
| - (sizeof(T) == kQRegSize),
|
| - "Template type must match size of register.");
|
| - DCHECK_LT(code, static_cast<unsigned>(kNumberOfVRegisters));
|
| -
|
| - return vregisters_[code].Get<T>();
|
| - }
|
| -
|
| - inline SimVRegister& vreg(unsigned code) { return vregisters_[code]; }
|
| -
|
| int64_t sp() { return xreg(31, Reg31IsStackPointer); }
|
| int64_t jssp() { return xreg(kJSSPCode, Reg31IsStackPointer); }
|
| int64_t fp() {
|
| @@ -971,135 +411,87 @@ class Simulator : public DecoderVisitor {
|
|
|
| Address get_sp() const { return reg<Address>(31, Reg31IsStackPointer); }
|
|
|
| - // Common specialized accessors for the vreg() template.
|
| - uint8_t breg(unsigned code) const { return vreg<uint8_t>(code); }
|
| -
|
| - float hreg(unsigned code) const { return vreg<uint16_t>(code); }
|
| -
|
| - float sreg(unsigned code) const { return vreg<float>(code); }
|
| -
|
| - uint32_t sreg_bits(unsigned code) const { return vreg<uint32_t>(code); }
|
| + template<typename T>
|
| + T fpreg(unsigned code) const {
|
| + DCHECK(code < kNumberOfRegisters);
|
| + return fpregisters_[code].Get<T>();
|
| + }
|
|
|
| - double dreg(unsigned code) const { return vreg<double>(code); }
|
| + // Common specialized accessors for the fpreg() template.
|
| + float sreg(unsigned code) const {
|
| + return fpreg<float>(code);
|
| + }
|
|
|
| - uint64_t dreg_bits(unsigned code) const { return vreg<uint64_t>(code); }
|
| + uint32_t sreg_bits(unsigned code) const {
|
| + return fpreg<uint32_t>(code);
|
| + }
|
|
|
| - qreg_t qreg(unsigned code) const { return vreg<qreg_t>(code); }
|
| + double dreg(unsigned code) const {
|
| + return fpreg<double>(code);
|
| + }
|
|
|
| - // As above, with parameterized size and return type. The value is
|
| - // either zero-extended or truncated to fit, as required.
|
| - template <typename T>
|
| - T vreg(unsigned size, unsigned code) const {
|
| - uint64_t raw = 0;
|
| - T result;
|
| + uint64_t dreg_bits(unsigned code) const {
|
| + return fpreg<uint64_t>(code);
|
| + }
|
|
|
| + double fpreg(unsigned size, unsigned code) const {
|
| switch (size) {
|
| - case kSRegSize:
|
| - raw = vreg<uint32_t>(code);
|
| - break;
|
| - case kDRegSize:
|
| - raw = vreg<uint64_t>(code);
|
| - break;
|
| + case kSRegSizeInBits: return sreg(code);
|
| + case kDRegSizeInBits: return dreg(code);
|
| default:
|
| UNREACHABLE();
|
| - break;
|
| + return 0.0;
|
| }
|
| -
|
| - static_assert(sizeof(result) <= sizeof(raw),
|
| - "Template type must be <= 64 bits.");
|
| - // Copy the result and truncate to fit. This assumes a little-endian host.
|
| - memcpy(&result, &raw, sizeof(result));
|
| - return result;
|
| }
|
|
|
| // Write 'value' into a floating-point register. The value is zero-extended.
|
| // This behaviour matches AArch64 register writes.
|
| - template <typename T>
|
| - void set_vreg(unsigned code, T value, RegLogMode log_mode = LogRegWrites) {
|
| - static_assert(
|
| - (sizeof(value) == kBRegSize) || (sizeof(value) == kHRegSize) ||
|
| - (sizeof(value) == kSRegSize) || (sizeof(value) == kDRegSize) ||
|
| - (sizeof(value) == kQRegSize),
|
| - "Template type must match size of register.");
|
| - DCHECK_LT(code, static_cast<unsigned>(kNumberOfVRegisters));
|
| - vregisters_[code].Set(value);
|
| -
|
| - if (log_mode == LogRegWrites) {
|
| - LogVRegister(code, GetPrintRegisterFormat(value));
|
| - }
|
| - }
|
| -
|
| - // Common specialized accessors for the set_vreg() template.
|
| - void set_breg(unsigned code, int8_t value,
|
| - RegLogMode log_mode = LogRegWrites) {
|
| - set_vreg(code, value, log_mode);
|
| - }
|
| -
|
| - void set_hreg(unsigned code, int16_t value,
|
| - RegLogMode log_mode = LogRegWrites) {
|
| - set_vreg(code, value, log_mode);
|
| - }
|
| + template<typename T>
|
| + void set_fpreg(unsigned code, T value) {
|
| + set_fpreg_no_log(code, value);
|
|
|
| - void set_sreg(unsigned code, float value,
|
| - RegLogMode log_mode = LogRegWrites) {
|
| - set_vreg(code, value, log_mode);
|
| + if (sizeof(value) <= kSRegSize) {
|
| + LogFPRegister(code, kPrintSRegValue);
|
| + } else {
|
| + LogFPRegister(code, kPrintDRegValue);
|
| + }
|
| }
|
|
|
| - void set_sreg_bits(unsigned code, uint32_t value,
|
| - RegLogMode log_mode = LogRegWrites) {
|
| - set_vreg(code, value, log_mode);
|
| + // Common specialized accessors for the set_fpreg() template.
|
| + void set_sreg(unsigned code, float value) {
|
| + set_fpreg(code, value);
|
| }
|
|
|
| - void set_dreg(unsigned code, double value,
|
| - RegLogMode log_mode = LogRegWrites) {
|
| - set_vreg(code, value, log_mode);
|
| + void set_sreg_bits(unsigned code, uint32_t value) {
|
| + set_fpreg(code, value);
|
| }
|
|
|
| - void set_dreg_bits(unsigned code, uint64_t value,
|
| - RegLogMode log_mode = LogRegWrites) {
|
| - set_vreg(code, value, log_mode);
|
| + void set_dreg(unsigned code, double value) {
|
| + set_fpreg(code, value);
|
| }
|
|
|
| - void set_qreg(unsigned code, qreg_t value,
|
| - RegLogMode log_mode = LogRegWrites) {
|
| - set_vreg(code, value, log_mode);
|
| + void set_dreg_bits(unsigned code, uint64_t value) {
|
| + set_fpreg(code, value);
|
| }
|
|
|
| // As above, but don't automatically log the register update.
|
| template <typename T>
|
| - void set_vreg_no_log(unsigned code, T value) {
|
| - STATIC_ASSERT((sizeof(value) == kBRegSize) ||
|
| - (sizeof(value) == kHRegSize) ||
|
| - (sizeof(value) == kSRegSize) ||
|
| - (sizeof(value) == kDRegSize) || (sizeof(value) == kQRegSize));
|
| - DCHECK_LT(code, static_cast<unsigned>(kNumberOfVRegisters));
|
| - vregisters_[code].Set(value);
|
| - }
|
| -
|
| - void set_breg_no_log(unsigned code, uint8_t value) {
|
| - set_vreg_no_log(code, value);
|
| - }
|
| -
|
| - void set_hreg_no_log(unsigned code, uint16_t value) {
|
| - set_vreg_no_log(code, value);
|
| + void set_fpreg_no_log(unsigned code, T value) {
|
| + DCHECK((sizeof(value) == kDRegSize) || (sizeof(value) == kSRegSize));
|
| + DCHECK(code < kNumberOfFPRegisters);
|
| + fpregisters_[code].Set(value);
|
| }
|
|
|
| void set_sreg_no_log(unsigned code, float value) {
|
| - set_vreg_no_log(code, value);
|
| + set_fpreg_no_log(code, value);
|
| }
|
|
|
| void set_dreg_no_log(unsigned code, double value) {
|
| - set_vreg_no_log(code, value);
|
| - }
|
| -
|
| - void set_qreg_no_log(unsigned code, qreg_t value) {
|
| - set_vreg_no_log(code, value);
|
| + set_fpreg_no_log(code, value);
|
| }
|
|
|
| SimSystemRegister& nzcv() { return nzcv_; }
|
| SimSystemRegister& fpcr() { return fpcr_; }
|
| - FPRounding RMode() { return static_cast<FPRounding>(fpcr_.RMode()); }
|
| - bool DN() { return fpcr_.DN() != 0; }
|
|
|
| // Debug helpers
|
|
|
| @@ -1126,195 +518,66 @@ class Simulator : public DecoderVisitor {
|
|
|
| // Print all registers of the specified types.
|
| void PrintRegisters();
|
| - void PrintVRegisters();
|
| + void PrintFPRegisters();
|
| void PrintSystemRegisters();
|
|
|
| - // As above, but only print the registers that have been updated.
|
| - void PrintWrittenRegisters();
|
| - void PrintWrittenVRegisters();
|
| -
|
| - // As above, but respect LOG_REG and LOG_VREG.
|
| - void LogWrittenRegisters() {
|
| - if (log_parameters() & LOG_REGS) PrintWrittenRegisters();
|
| - }
|
| - void LogWrittenVRegisters() {
|
| - if (log_parameters() & LOG_VREGS) PrintWrittenVRegisters();
|
| - }
|
| - void LogAllWrittenRegisters() {
|
| - LogWrittenRegisters();
|
| - LogWrittenVRegisters();
|
| - }
|
| -
|
| - // Specify relevant register formats for Print(V)Register and related helpers.
|
| - enum PrintRegisterFormat {
|
| - // The lane size.
|
| - kPrintRegLaneSizeB = 0 << 0,
|
| - kPrintRegLaneSizeH = 1 << 0,
|
| - kPrintRegLaneSizeS = 2 << 0,
|
| - kPrintRegLaneSizeW = kPrintRegLaneSizeS,
|
| - kPrintRegLaneSizeD = 3 << 0,
|
| - kPrintRegLaneSizeX = kPrintRegLaneSizeD,
|
| - kPrintRegLaneSizeQ = 4 << 0,
|
| -
|
| - kPrintRegLaneSizeOffset = 0,
|
| - kPrintRegLaneSizeMask = 7 << 0,
|
| -
|
| - // The lane count.
|
| - kPrintRegAsScalar = 0,
|
| - kPrintRegAsDVector = 1 << 3,
|
| - kPrintRegAsQVector = 2 << 3,
|
| -
|
| - kPrintRegAsVectorMask = 3 << 3,
|
| -
|
| - // Indicate floating-point format lanes. (This flag is only supported for S-
|
| - // and D-sized lanes.)
|
| - kPrintRegAsFP = 1 << 5,
|
| -
|
| - // Supported combinations.
|
| -
|
| - kPrintXReg = kPrintRegLaneSizeX | kPrintRegAsScalar,
|
| - kPrintWReg = kPrintRegLaneSizeW | kPrintRegAsScalar,
|
| - kPrintSReg = kPrintRegLaneSizeS | kPrintRegAsScalar | kPrintRegAsFP,
|
| - kPrintDReg = kPrintRegLaneSizeD | kPrintRegAsScalar | kPrintRegAsFP,
|
| -
|
| - kPrintReg1B = kPrintRegLaneSizeB | kPrintRegAsScalar,
|
| - kPrintReg8B = kPrintRegLaneSizeB | kPrintRegAsDVector,
|
| - kPrintReg16B = kPrintRegLaneSizeB | kPrintRegAsQVector,
|
| - kPrintReg1H = kPrintRegLaneSizeH | kPrintRegAsScalar,
|
| - kPrintReg4H = kPrintRegLaneSizeH | kPrintRegAsDVector,
|
| - kPrintReg8H = kPrintRegLaneSizeH | kPrintRegAsQVector,
|
| - kPrintReg1S = kPrintRegLaneSizeS | kPrintRegAsScalar,
|
| - kPrintReg2S = kPrintRegLaneSizeS | kPrintRegAsDVector,
|
| - kPrintReg4S = kPrintRegLaneSizeS | kPrintRegAsQVector,
|
| - kPrintReg1SFP = kPrintRegLaneSizeS | kPrintRegAsScalar | kPrintRegAsFP,
|
| - kPrintReg2SFP = kPrintRegLaneSizeS | kPrintRegAsDVector | kPrintRegAsFP,
|
| - kPrintReg4SFP = kPrintRegLaneSizeS | kPrintRegAsQVector | kPrintRegAsFP,
|
| - kPrintReg1D = kPrintRegLaneSizeD | kPrintRegAsScalar,
|
| - kPrintReg2D = kPrintRegLaneSizeD | kPrintRegAsQVector,
|
| - kPrintReg1DFP = kPrintRegLaneSizeD | kPrintRegAsScalar | kPrintRegAsFP,
|
| - kPrintReg2DFP = kPrintRegLaneSizeD | kPrintRegAsQVector | kPrintRegAsFP,
|
| - kPrintReg1Q = kPrintRegLaneSizeQ | kPrintRegAsScalar
|
| - };
|
| -
|
| - unsigned GetPrintRegLaneSizeInBytesLog2(PrintRegisterFormat format) {
|
| - return (format & kPrintRegLaneSizeMask) >> kPrintRegLaneSizeOffset;
|
| - }
|
| -
|
| - unsigned GetPrintRegLaneSizeInBytes(PrintRegisterFormat format) {
|
| - return 1 << GetPrintRegLaneSizeInBytesLog2(format);
|
| - }
|
| -
|
| - unsigned GetPrintRegSizeInBytesLog2(PrintRegisterFormat format) {
|
| - if (format & kPrintRegAsDVector) return kDRegSizeLog2;
|
| - if (format & kPrintRegAsQVector) return kQRegSizeLog2;
|
| -
|
| - // Scalar types.
|
| - return GetPrintRegLaneSizeInBytesLog2(format);
|
| - }
|
| -
|
| - unsigned GetPrintRegSizeInBytes(PrintRegisterFormat format) {
|
| - return 1 << GetPrintRegSizeInBytesLog2(format);
|
| - }
|
| -
|
| - unsigned GetPrintRegLaneCount(PrintRegisterFormat format) {
|
| - unsigned reg_size_log2 = GetPrintRegSizeInBytesLog2(format);
|
| - unsigned lane_size_log2 = GetPrintRegLaneSizeInBytesLog2(format);
|
| - DCHECK_GE(reg_size_log2, lane_size_log2);
|
| - return 1 << (reg_size_log2 - lane_size_log2);
|
| - }
|
| -
|
| - template <typename T>
|
| - PrintRegisterFormat GetPrintRegisterFormat(T value) {
|
| - return GetPrintRegisterFormatForSize(sizeof(value));
|
| - }
|
| -
|
| - PrintRegisterFormat GetPrintRegisterFormat(double value) {
|
| - static_assert(sizeof(value) == kDRegSize,
|
| - "D register must be size of double.");
|
| - return GetPrintRegisterFormatForSizeFP(sizeof(value));
|
| + // Like Print* (above), but respect log_parameters().
|
| + void LogSystemRegisters() {
|
| + if (log_parameters() & LOG_SYS_REGS) PrintSystemRegisters();
|
| }
|
| -
|
| - PrintRegisterFormat GetPrintRegisterFormat(float value) {
|
| - static_assert(sizeof(value) == kSRegSize,
|
| - "S register must be size of float.");
|
| - return GetPrintRegisterFormatForSizeFP(sizeof(value));
|
| + void LogRegisters() {
|
| + if (log_parameters() & LOG_REGS) PrintRegisters();
|
| }
|
| -
|
| - PrintRegisterFormat GetPrintRegisterFormat(VectorFormat vform);
|
| - PrintRegisterFormat GetPrintRegisterFormatFP(VectorFormat vform);
|
| -
|
| - PrintRegisterFormat GetPrintRegisterFormatForSize(size_t reg_size,
|
| - size_t lane_size);
|
| -
|
| - PrintRegisterFormat GetPrintRegisterFormatForSize(size_t size) {
|
| - return GetPrintRegisterFormatForSize(size, size);
|
| + void LogFPRegisters() {
|
| + if (log_parameters() & LOG_FP_REGS) PrintFPRegisters();
|
| }
|
|
|
| - PrintRegisterFormat GetPrintRegisterFormatForSizeFP(size_t size) {
|
| - switch (size) {
|
| - default:
|
| - UNREACHABLE();
|
| - case kDRegSize:
|
| - return kPrintDReg;
|
| - case kSRegSize:
|
| - return kPrintSReg;
|
| - }
|
| - }
|
| -
|
| - PrintRegisterFormat GetPrintRegisterFormatTryFP(PrintRegisterFormat format) {
|
| - if ((GetPrintRegLaneSizeInBytes(format) == kSRegSize) ||
|
| - (GetPrintRegLaneSizeInBytes(format) == kDRegSize)) {
|
| - return static_cast<PrintRegisterFormat>(format | kPrintRegAsFP);
|
| - }
|
| - return format;
|
| - }
|
| + // Specify relevant register sizes, for PrintFPRegister.
|
| + //
|
| + // These values are bit masks; they can be combined in case multiple views of
|
| + // a machine register are interesting.
|
| + enum PrintFPRegisterSizes {
|
| + kPrintDRegValue = 1 << kDRegSize,
|
| + kPrintSRegValue = 1 << kSRegSize,
|
| + kPrintAllFPRegValues = kPrintDRegValue | kPrintSRegValue
|
| + };
|
|
|
| // Print individual register values (after update).
|
| void PrintRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer);
|
| - void PrintVRegister(unsigned code, PrintRegisterFormat sizes);
|
| + void PrintFPRegister(unsigned code,
|
| + PrintFPRegisterSizes sizes = kPrintAllFPRegValues);
|
| void PrintSystemRegister(SystemRegister id);
|
|
|
| // Like Print* (above), but respect log_parameters().
|
| void LogRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer) {
|
| if (log_parameters() & LOG_REGS) PrintRegister(code, r31mode);
|
| }
|
| - void LogVRegister(unsigned code, PrintRegisterFormat format) {
|
| - if (log_parameters() & LOG_VREGS) PrintVRegister(code, format);
|
| + void LogFPRegister(unsigned code,
|
| + PrintFPRegisterSizes sizes = kPrintAllFPRegValues) {
|
| + if (log_parameters() & LOG_FP_REGS) PrintFPRegister(code, sizes);
|
| }
|
| void LogSystemRegister(SystemRegister id) {
|
| if (log_parameters() & LOG_SYS_REGS) PrintSystemRegister(id);
|
| }
|
|
|
| // Print memory accesses.
|
| - void PrintRead(uintptr_t address, unsigned reg_code,
|
| - PrintRegisterFormat format);
|
| - void PrintWrite(uintptr_t address, unsigned reg_code,
|
| - PrintRegisterFormat format);
|
| - void PrintVRead(uintptr_t address, unsigned reg_code,
|
| - PrintRegisterFormat format, unsigned lane);
|
| - void PrintVWrite(uintptr_t address, unsigned reg_code,
|
| - PrintRegisterFormat format, unsigned lane);
|
| + void PrintRead(uintptr_t address, size_t size, unsigned reg_code);
|
| + void PrintReadFP(uintptr_t address, size_t size, unsigned reg_code);
|
| + void PrintWrite(uintptr_t address, size_t size, unsigned reg_code);
|
| + void PrintWriteFP(uintptr_t address, size_t size, unsigned reg_code);
|
|
|
| // Like Print* (above), but respect log_parameters().
|
| - void LogRead(uintptr_t address, unsigned reg_code,
|
| - PrintRegisterFormat format) {
|
| - if (log_parameters() & LOG_REGS) PrintRead(address, reg_code, format);
|
| - }
|
| - void LogWrite(uintptr_t address, unsigned reg_code,
|
| - PrintRegisterFormat format) {
|
| - if (log_parameters() & LOG_WRITE) PrintWrite(address, reg_code, format);
|
| - }
|
| - void LogVRead(uintptr_t address, unsigned reg_code,
|
| - PrintRegisterFormat format, unsigned lane = 0) {
|
| - if (log_parameters() & LOG_VREGS) {
|
| - PrintVRead(address, reg_code, format, lane);
|
| - }
|
| + void LogRead(uintptr_t address, size_t size, unsigned reg_code) {
|
| + if (log_parameters() & LOG_REGS) PrintRead(address, size, reg_code);
|
| }
|
| - void LogVWrite(uintptr_t address, unsigned reg_code,
|
| - PrintRegisterFormat format, unsigned lane = 0) {
|
| - if (log_parameters() & LOG_WRITE) {
|
| - PrintVWrite(address, reg_code, format, lane);
|
| - }
|
| + void LogReadFP(uintptr_t address, size_t size, unsigned reg_code) {
|
| + if (log_parameters() & LOG_FP_REGS) PrintReadFP(address, size, reg_code);
|
| + }
|
| + void LogWrite(uintptr_t address, size_t size, unsigned reg_code) {
|
| + if (log_parameters() & LOG_WRITE) PrintWrite(address, size, reg_code);
|
| + }
|
| + void LogWriteFP(uintptr_t address, size_t size, unsigned reg_code) {
|
| + if (log_parameters() & LOG_WRITE) PrintWriteFP(address, size, reg_code);
|
| }
|
|
|
| int log_parameters() { return log_parameters_; }
|
| @@ -1333,14 +596,6 @@ class Simulator : public DecoderVisitor {
|
| }
|
| }
|
|
|
| - // Helper functions for register tracing.
|
| - void PrintRegisterRawHelper(unsigned code, Reg31Mode r31mode,
|
| - int size_in_bytes = kXRegSize);
|
| - void PrintVRegisterRawHelper(unsigned code, int bytes = kQRegSize,
|
| - int lsb = 0);
|
| - void PrintVRegisterFPHelper(unsigned code, unsigned lane_size_in_bytes,
|
| - int lane_count = 1, int rightmost_lane = 0);
|
| -
|
| static inline const char* WRegNameForCode(unsigned code,
|
| Reg31Mode mode = Reg31IsZeroRegister);
|
| static inline const char* XRegNameForCode(unsigned code,
|
| @@ -1415,10 +670,6 @@ class Simulator : public DecoderVisitor {
|
| void LoadStoreWriteBack(unsigned addr_reg,
|
| int64_t offset,
|
| AddrMode addrmode);
|
| - void NEONLoadStoreMultiStructHelper(const Instruction* instr,
|
| - AddrMode addr_mode);
|
| - void NEONLoadStoreSingleStructHelper(const Instruction* instr,
|
| - AddrMode addr_mode);
|
| void CheckMemoryAccess(uintptr_t address, uintptr_t stack);
|
|
|
| // Memory read helpers.
|
| @@ -1426,8 +677,7 @@ class Simulator : public DecoderVisitor {
|
| T MemoryRead(A address) {
|
| T value;
|
| STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
|
| - (sizeof(value) == 4) || (sizeof(value) == 8) ||
|
| - (sizeof(value) == 16));
|
| + (sizeof(value) == 4) || (sizeof(value) == 8));
|
| memcpy(&value, reinterpret_cast<const void*>(address), sizeof(value));
|
| return value;
|
| }
|
| @@ -1436,8 +686,7 @@ class Simulator : public DecoderVisitor {
|
| template <typename T, typename A>
|
| void MemoryWrite(A address, T value) {
|
| STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
|
| - (sizeof(value) == 4) || (sizeof(value) == 8) ||
|
| - (sizeof(value) == 16));
|
| + (sizeof(value) == 4) || (sizeof(value) == 8));
|
| memcpy(reinterpret_cast<void*>(address), &value, sizeof(value));
|
| }
|
|
|
| @@ -1455,652 +704,14 @@ class Simulator : public DecoderVisitor {
|
| void DataProcessing2Source(Instruction* instr);
|
| template <typename T>
|
| void BitfieldHelper(Instruction* instr);
|
| - uint16_t PolynomialMult(uint8_t op1, uint8_t op2);
|
| -
|
| - void ld1(VectorFormat vform, LogicVRegister dst, uint64_t addr);
|
| - void ld1(VectorFormat vform, LogicVRegister dst, int index, uint64_t addr);
|
| - void ld1r(VectorFormat vform, LogicVRegister dst, uint64_t addr);
|
| - void ld2(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
|
| - uint64_t addr);
|
| - void ld2(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
|
| - int index, uint64_t addr);
|
| - void ld2r(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
|
| - uint64_t addr);
|
| - void ld3(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
|
| - LogicVRegister dst3, uint64_t addr);
|
| - void ld3(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
|
| - LogicVRegister dst3, int index, uint64_t addr);
|
| - void ld3r(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
|
| - LogicVRegister dst3, uint64_t addr);
|
| - void ld4(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
|
| - LogicVRegister dst3, LogicVRegister dst4, uint64_t addr);
|
| - void ld4(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
|
| - LogicVRegister dst3, LogicVRegister dst4, int index, uint64_t addr);
|
| - void ld4r(VectorFormat vform, LogicVRegister dst1, LogicVRegister dst2,
|
| - LogicVRegister dst3, LogicVRegister dst4, uint64_t addr);
|
| - void st1(VectorFormat vform, LogicVRegister src, uint64_t addr);
|
| - void st1(VectorFormat vform, LogicVRegister src, int index, uint64_t addr);
|
| - void st2(VectorFormat vform, LogicVRegister src, LogicVRegister src2,
|
| - uint64_t addr);
|
| - void st2(VectorFormat vform, LogicVRegister src, LogicVRegister src2,
|
| - int index, uint64_t addr);
|
| - void st3(VectorFormat vform, LogicVRegister src, LogicVRegister src2,
|
| - LogicVRegister src3, uint64_t addr);
|
| - void st3(VectorFormat vform, LogicVRegister src, LogicVRegister src2,
|
| - LogicVRegister src3, int index, uint64_t addr);
|
| - void st4(VectorFormat vform, LogicVRegister src, LogicVRegister src2,
|
| - LogicVRegister src3, LogicVRegister src4, uint64_t addr);
|
| - void st4(VectorFormat vform, LogicVRegister src, LogicVRegister src2,
|
| - LogicVRegister src3, LogicVRegister src4, int index, uint64_t addr);
|
| - LogicVRegister cmp(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - Condition cond);
|
| - LogicVRegister cmp(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, int imm, Condition cond);
|
| - LogicVRegister cmptst(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister add(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister addp(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister mla(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister mls(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister mul(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister mul(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister mla(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister mls(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister pmul(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| -
|
| - typedef LogicVRegister (Simulator::*ByElementOp)(VectorFormat vform,
|
| - LogicVRegister dst,
|
| - const LogicVRegister& src1,
|
| - const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister fmul(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister fmla(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister fmls(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister fmulx(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister smull(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister smull2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister umull(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister umull2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister smlal(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister smlal2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister umlal(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister umlal2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister smlsl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister smlsl2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister umlsl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister umlsl2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister sqdmull(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister sqdmull2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1,
|
| - const LogicVRegister& src2, int index);
|
| - LogicVRegister sqdmlal(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister sqdmlal2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1,
|
| - const LogicVRegister& src2, int index);
|
| - LogicVRegister sqdmlsl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister sqdmlsl2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1,
|
| - const LogicVRegister& src2, int index);
|
| - LogicVRegister sqdmulh(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister sqrdmulh(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1,
|
| - const LogicVRegister& src2, int index);
|
| - LogicVRegister sub(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister and_(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister orr(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister orn(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister eor(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister bic(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister bic(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, uint64_t imm);
|
| - LogicVRegister bif(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister bit(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister bsl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister cls(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister clz(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister cnt(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister not_(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister rbit(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister rev(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int revSize);
|
| - LogicVRegister rev16(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister rev32(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister rev64(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister addlp(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, bool is_signed,
|
| - bool do_accumulate);
|
| - LogicVRegister saddlp(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister uaddlp(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister sadalp(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister uadalp(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister ext(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - int index);
|
| - LogicVRegister ins_element(VectorFormat vform, LogicVRegister dst,
|
| - int dst_index, const LogicVRegister& src,
|
| - int src_index);
|
| - LogicVRegister ins_immediate(VectorFormat vform, LogicVRegister dst,
|
| - int dst_index, uint64_t imm);
|
| - LogicVRegister dup_element(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int src_index);
|
| - LogicVRegister dup_immediate(VectorFormat vform, LogicVRegister dst,
|
| - uint64_t imm);
|
| - LogicVRegister movi(VectorFormat vform, LogicVRegister dst, uint64_t imm);
|
| - LogicVRegister mvni(VectorFormat vform, LogicVRegister dst, uint64_t imm);
|
| - LogicVRegister orr(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, uint64_t imm);
|
| - LogicVRegister sshl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister ushl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister SMinMax(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - bool max);
|
| - LogicVRegister smax(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister smin(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister SMinMaxP(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1,
|
| - const LogicVRegister& src2, bool max);
|
| - LogicVRegister smaxp(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister sminp(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister addp(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister addv(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister uaddlv(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister saddlv(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister SMinMaxV(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, bool max);
|
| - LogicVRegister smaxv(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister sminv(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister uxtl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister uxtl2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister sxtl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister sxtl2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister Table(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& ind, bool zero_out_of_bounds,
|
| - const LogicVRegister* tab1,
|
| - const LogicVRegister* tab2 = NULL,
|
| - const LogicVRegister* tab3 = NULL,
|
| - const LogicVRegister* tab4 = NULL);
|
| - LogicVRegister tbl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& tab, const LogicVRegister& ind);
|
| - LogicVRegister tbl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& tab, const LogicVRegister& tab2,
|
| - const LogicVRegister& ind);
|
| - LogicVRegister tbl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& tab, const LogicVRegister& tab2,
|
| - const LogicVRegister& tab3, const LogicVRegister& ind);
|
| - LogicVRegister tbl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& tab, const LogicVRegister& tab2,
|
| - const LogicVRegister& tab3, const LogicVRegister& tab4,
|
| - const LogicVRegister& ind);
|
| - LogicVRegister tbx(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& tab, const LogicVRegister& ind);
|
| - LogicVRegister tbx(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& tab, const LogicVRegister& tab2,
|
| - const LogicVRegister& ind);
|
| - LogicVRegister tbx(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& tab, const LogicVRegister& tab2,
|
| - const LogicVRegister& tab3, const LogicVRegister& ind);
|
| - LogicVRegister tbx(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& tab, const LogicVRegister& tab2,
|
| - const LogicVRegister& tab3, const LogicVRegister& tab4,
|
| - const LogicVRegister& ind);
|
| - LogicVRegister uaddl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister uaddl2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister uaddw(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister uaddw2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister saddl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister saddl2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister saddw(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister saddw2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister usubl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister usubl2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister usubw(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister usubw2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister ssubl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister ssubl2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister ssubw(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister ssubw2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister UMinMax(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - bool max);
|
| - LogicVRegister umax(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister umin(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister UMinMaxP(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1,
|
| - const LogicVRegister& src2, bool max);
|
| - LogicVRegister umaxp(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister uminp(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister UMinMaxV(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, bool max);
|
| - LogicVRegister umaxv(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister uminv(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister trn1(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister trn2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister zip1(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister zip2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister uzp1(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister uzp2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister shl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister scvtf(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int fbits,
|
| - FPRounding rounding_mode);
|
| - LogicVRegister ucvtf(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int fbits,
|
| - FPRounding rounding_mode);
|
| - LogicVRegister sshll(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister sshll2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister shll(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister shll2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister ushll(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister ushll2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister sli(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister sri(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister sshr(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister ushr(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister ssra(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister usra(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister srsra(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister ursra(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister suqadd(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister usqadd(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister sqshl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister uqshl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister sqshlu(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister abs(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister neg(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister ExtractNarrow(VectorFormat vform, LogicVRegister dst,
|
| - bool dstIsSigned, const LogicVRegister& src,
|
| - bool srcIsSigned);
|
| - LogicVRegister xtn(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister sqxtn(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister uqxtn(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister sqxtun(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister AbsDiff(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - bool issigned);
|
| - LogicVRegister saba(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister uaba(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister shrn(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister shrn2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister rshrn(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister rshrn2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister uqshrn(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister uqshrn2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister uqrshrn(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister uqrshrn2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister sqshrn(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister sqshrn2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister sqrshrn(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister sqrshrn2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister sqshrun(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister sqshrun2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister sqrshrun(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister sqrshrun2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, int shift);
|
| - LogicVRegister sqrdmulh(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1,
|
| - const LogicVRegister& src2, bool round = true);
|
| - LogicVRegister sqdmulh(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1,
|
| - const LogicVRegister& src2);
|
| -#define NEON_3VREG_LOGIC_LIST(V) \
|
| - V(addhn) \
|
| - V(addhn2) \
|
| - V(raddhn) \
|
| - V(raddhn2) \
|
| - V(subhn) \
|
| - V(subhn2) \
|
| - V(rsubhn) \
|
| - V(rsubhn2) \
|
| - V(pmull) \
|
| - V(pmull2) \
|
| - V(sabal) \
|
| - V(sabal2) \
|
| - V(uabal) \
|
| - V(uabal2) \
|
| - V(sabdl) \
|
| - V(sabdl2) \
|
| - V(uabdl) \
|
| - V(uabdl2) \
|
| - V(smull) \
|
| - V(smull2) \
|
| - V(umull) \
|
| - V(umull2) \
|
| - V(smlal) \
|
| - V(smlal2) \
|
| - V(umlal) \
|
| - V(umlal2) \
|
| - V(smlsl) \
|
| - V(smlsl2) \
|
| - V(umlsl) \
|
| - V(umlsl2) \
|
| - V(sqdmlal) \
|
| - V(sqdmlal2) \
|
| - V(sqdmlsl) \
|
| - V(sqdmlsl2) \
|
| - V(sqdmull) \
|
| - V(sqdmull2)
|
| -
|
| -#define DEFINE_LOGIC_FUNC(FXN) \
|
| - LogicVRegister FXN(VectorFormat vform, LogicVRegister dst, \
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - NEON_3VREG_LOGIC_LIST(DEFINE_LOGIC_FUNC)
|
| -#undef DEFINE_LOGIC_FUNC
|
| -
|
| -#define NEON_FP3SAME_LIST(V) \
|
| - V(fadd, FPAdd, false) \
|
| - V(fsub, FPSub, true) \
|
| - V(fmul, FPMul, true) \
|
| - V(fmulx, FPMulx, true) \
|
| - V(fdiv, FPDiv, true) \
|
| - V(fmax, FPMax, false) \
|
| - V(fmin, FPMin, false) \
|
| - V(fmaxnm, FPMaxNM, false) \
|
| - V(fminnm, FPMinNM, false)
|
| -
|
| -#define DECLARE_NEON_FP_VECTOR_OP(FN, OP, PROCNAN) \
|
| - template <typename T> \
|
| - LogicVRegister FN(VectorFormat vform, LogicVRegister dst, \
|
| - const LogicVRegister& src1, const LogicVRegister& src2); \
|
| - LogicVRegister FN(VectorFormat vform, LogicVRegister dst, \
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - NEON_FP3SAME_LIST(DECLARE_NEON_FP_VECTOR_OP)
|
| -#undef DECLARE_NEON_FP_VECTOR_OP
|
| -
|
| -#define NEON_FPPAIRWISE_LIST(V) \
|
| - V(faddp, fadd, FPAdd) \
|
| - V(fmaxp, fmax, FPMax) \
|
| - V(fmaxnmp, fmaxnm, FPMaxNM) \
|
| - V(fminp, fmin, FPMin) \
|
| - V(fminnmp, fminnm, FPMinNM)
|
| -
|
| -#define DECLARE_NEON_FP_PAIR_OP(FNP, FN, OP) \
|
| - LogicVRegister FNP(VectorFormat vform, LogicVRegister dst, \
|
| - const LogicVRegister& src1, const LogicVRegister& src2); \
|
| - LogicVRegister FNP(VectorFormat vform, LogicVRegister dst, \
|
| - const LogicVRegister& src);
|
| - NEON_FPPAIRWISE_LIST(DECLARE_NEON_FP_PAIR_OP)
|
| -#undef DECLARE_NEON_FP_PAIR_OP
|
| -
|
| - template <typename T>
|
| - LogicVRegister frecps(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister frecps(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - template <typename T>
|
| - LogicVRegister frsqrts(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1,
|
| - const LogicVRegister& src2);
|
| - LogicVRegister frsqrts(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1,
|
| - const LogicVRegister& src2);
|
| - template <typename T>
|
| - LogicVRegister fmla(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister fmla(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - template <typename T>
|
| - LogicVRegister fmls(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister fmls(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister fnmul(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
|
|
| template <typename T>
|
| - LogicVRegister fcmp(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - Condition cond);
|
| - LogicVRegister fcmp(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - Condition cond);
|
| - LogicVRegister fabscmp(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2,
|
| - Condition cond);
|
| - LogicVRegister fcmp_zero(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, Condition cond);
|
| -
|
| - template <typename T>
|
| - LogicVRegister fneg(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister fneg(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - template <typename T>
|
| - LogicVRegister frecpx(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister frecpx(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - template <typename T>
|
| - LogicVRegister fabs_(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister fabs_(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister fabd(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src1, const LogicVRegister& src2);
|
| - LogicVRegister frint(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, FPRounding rounding_mode,
|
| - bool inexact_exception = false);
|
| - LogicVRegister fcvts(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, FPRounding rounding_mode,
|
| - int fbits = 0);
|
| - LogicVRegister fcvtu(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, FPRounding rounding_mode,
|
| - int fbits = 0);
|
| - LogicVRegister fcvtl(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister fcvtl2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister fcvtn(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister fcvtn2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister fcvtxn(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister fcvtxn2(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister fsqrt(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister frsqrte(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister frecpe(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, FPRounding rounding);
|
| - LogicVRegister ursqrte(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister urecpe(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| -
|
| - typedef float (Simulator::*FPMinMaxOp)(float a, float b);
|
| -
|
| - LogicVRegister FMinMaxV(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src, FPMinMaxOp Op);
|
| -
|
| - LogicVRegister fminv(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister fmaxv(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister fminnmv(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| - LogicVRegister fmaxnmv(VectorFormat vform, LogicVRegister dst,
|
| - const LogicVRegister& src);
|
| -
|
| - template <typename T>
|
| - T FPRecipSqrtEstimate(T op);
|
| - template <typename T>
|
| - T FPRecipEstimate(T op, FPRounding rounding);
|
| - template <typename T, typename R>
|
| - R FPToFixed(T op, int fbits, bool is_signed, FPRounding rounding);
|
| + T FPDefaultNaN() const;
|
|
|
| void FPCompare(double val0, double val1);
|
| double FPRoundInt(double value, FPRounding round_mode);
|
| double FPToDouble(float value);
|
| float FPToFloat(double value, FPRounding round_mode);
|
| - float FPToFloat(float16 value);
|
| - float16 FPToFloat16(float value, FPRounding round_mode);
|
| - float16 FPToFloat16(double value, FPRounding round_mode);
|
| - double recip_sqrt_estimate(double a);
|
| - double recip_estimate(double a);
|
| - double FPRecipSqrtEstimate(double a);
|
| - double FPRecipEstimate(double a);
|
| double FixedToDouble(int64_t src, int fbits, FPRounding round_mode);
|
| double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode);
|
| float FixedToFloat(int64_t src, int fbits, FPRounding round_mode);
|
| @@ -2132,9 +743,6 @@ class Simulator : public DecoderVisitor {
|
| T FPMul(T op1, T op2);
|
|
|
| template <typename T>
|
| - T FPMulx(T op1, T op2);
|
| -
|
| - template <typename T>
|
| T FPMulAdd(T a, T op1, T op2);
|
|
|
| template <typename T>
|
| @@ -2143,18 +751,17 @@ class Simulator : public DecoderVisitor {
|
| template <typename T>
|
| T FPSub(T op1, T op2);
|
|
|
| + // Standard NaN processing.
|
| template <typename T>
|
| - T FPRecipStepFused(T op1, T op2);
|
| + T FPProcessNaN(T op);
|
|
|
| - template <typename T>
|
| - T FPRSqrtStepFused(T op1, T op2);
|
| + bool FPProcessNaNs(Instruction* instr);
|
|
|
| - // This doesn't do anything at the moment. We'll need it if we want support
|
| - // for cumulative exception bits or floating-point exceptions.
|
| - void FPProcessException() {}
|
| + template <typename T>
|
| + T FPProcessNaNs(T op1, T op2);
|
|
|
| - // Standard NaN processing.
|
| - bool FPProcessNaNs(Instruction* instr);
|
| + template <typename T>
|
| + T FPProcessNaNs3(T op1, T op2, T op3);
|
|
|
| void CheckStackAlignment();
|
|
|
| @@ -2166,7 +773,7 @@ class Simulator : public DecoderVisitor {
|
| static const uint64_t kCallerSavedRegisterCorruptionValue =
|
| 0xca11edc0de000000UL;
|
| // This value is a NaN in both 32-bit and 64-bit FP.
|
| - static const uint64_t kCallerSavedVRegisterCorruptionValue =
|
| + static const uint64_t kCallerSavedFPRegisterCorruptionValue =
|
| 0x7ff000007f801000UL;
|
| // This value is a mix of 32/64-bits NaN and "verbose" immediate.
|
| static const uint64_t kDefaultCPURegisterCorruptionValue =
|
| @@ -2194,7 +801,7 @@ class Simulator : public DecoderVisitor {
|
| SimRegister registers_[kNumberOfRegisters];
|
|
|
| // Floating point registers
|
| - SimVRegister vregisters_[kNumberOfVRegisters];
|
| + SimFPRegister fpregisters_[kNumberOfFPRegisters];
|
|
|
| // Processor state
|
| // bits[31, 27]: Condition flags N, Z, C, and V.
|
| @@ -2352,67 +959,10 @@ class Simulator : public DecoderVisitor {
|
| private:
|
| void Init(FILE* stream);
|
|
|
| - template <typename T>
|
| - static T FPDefaultNaN();
|
| -
|
| - template <typename T>
|
| - T FPProcessNaN(T op) {
|
| - DCHECK(std::isnan(op));
|
| - return fpcr().DN() ? FPDefaultNaN<T>() : ToQuietNaN(op);
|
| - }
|
| -
|
| - template <typename T>
|
| - T FPProcessNaNs(T op1, T op2) {
|
| - if (IsSignallingNaN(op1)) {
|
| - return FPProcessNaN(op1);
|
| - } else if (IsSignallingNaN(op2)) {
|
| - return FPProcessNaN(op2);
|
| - } else if (std::isnan(op1)) {
|
| - DCHECK(IsQuietNaN(op1));
|
| - return FPProcessNaN(op1);
|
| - } else if (std::isnan(op2)) {
|
| - DCHECK(IsQuietNaN(op2));
|
| - return FPProcessNaN(op2);
|
| - } else {
|
| - return 0.0;
|
| - }
|
| - }
|
| -
|
| - template <typename T>
|
| - T FPProcessNaNs3(T op1, T op2, T op3) {
|
| - if (IsSignallingNaN(op1)) {
|
| - return FPProcessNaN(op1);
|
| - } else if (IsSignallingNaN(op2)) {
|
| - return FPProcessNaN(op2);
|
| - } else if (IsSignallingNaN(op3)) {
|
| - return FPProcessNaN(op3);
|
| - } else if (std::isnan(op1)) {
|
| - DCHECK(IsQuietNaN(op1));
|
| - return FPProcessNaN(op1);
|
| - } else if (std::isnan(op2)) {
|
| - DCHECK(IsQuietNaN(op2));
|
| - return FPProcessNaN(op2);
|
| - } else if (std::isnan(op3)) {
|
| - DCHECK(IsQuietNaN(op3));
|
| - return FPProcessNaN(op3);
|
| - } else {
|
| - return 0.0;
|
| - }
|
| - }
|
| -
|
| int log_parameters_;
|
| Isolate* isolate_;
|
| };
|
|
|
| -template <>
|
| -inline double Simulator::FPDefaultNaN<double>() {
|
| - return kFP64DefaultNaN;
|
| -}
|
| -
|
| -template <>
|
| -inline float Simulator::FPDefaultNaN<float>() {
|
| - return kFP32DefaultNaN;
|
| -}
|
|
|
| // When running with the simulator transition into simulated execution at this
|
| // point.
|
|
|