xref: /freebsd-src/contrib/llvm-project/lldb/source/Utility/RegisterValue.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ffd83dbSDimitry Andric //===-- RegisterValue.cpp -------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Utility/RegisterValue.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h"
120b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h"
130b57cec5SDimitry Andric #include "lldb/Utility/Status.h"
140b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
150b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
160b57cec5SDimitry Andric #include "lldb/lldb-defines.h"
170b57cec5SDimitry Andric #include "lldb/lldb-private-types.h"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
200b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric #include <cstdint>
230b57cec5SDimitry Andric #include <string>
240b57cec5SDimitry Andric #include <tuple>
250b57cec5SDimitry Andric #include <vector>
260b57cec5SDimitry Andric 
27fe6060f1SDimitry Andric #include <cassert>
28fe6060f1SDimitry Andric #include <cinttypes>
29fe6060f1SDimitry Andric #include <cstdio>
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric using namespace lldb;
320b57cec5SDimitry Andric using namespace lldb_private;
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric bool RegisterValue::GetData(DataExtractor &data) const {
350b57cec5SDimitry Andric   return data.SetData(GetBytes(), GetByteSize(), GetByteOrder()) > 0;
360b57cec5SDimitry Andric }
370b57cec5SDimitry Andric 
38bdd1243dSDimitry Andric uint32_t RegisterValue::GetAsMemoryData(const RegisterInfo &reg_info, void *dst,
390b57cec5SDimitry Andric                                         uint32_t dst_len,
400b57cec5SDimitry Andric                                         lldb::ByteOrder dst_byte_order,
410b57cec5SDimitry Andric                                         Status &error) const {
420b57cec5SDimitry Andric   // ReadRegister should have already been called on this object prior to
430b57cec5SDimitry Andric   // calling this.
440b57cec5SDimitry Andric   if (GetType() == eTypeInvalid) {
450b57cec5SDimitry Andric     // No value has been read into this object...
460b57cec5SDimitry Andric     error.SetErrorStringWithFormat(
47bdd1243dSDimitry Andric         "invalid register value type for register %s", reg_info.name);
480b57cec5SDimitry Andric     return 0;
490b57cec5SDimitry Andric   }
500b57cec5SDimitry Andric 
51bdd1243dSDimitry Andric   const uint32_t src_len = reg_info.byte_size;
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   // Extract the register data into a data extractor
540b57cec5SDimitry Andric   DataExtractor reg_data;
550b57cec5SDimitry Andric   if (!GetData(reg_data)) {
560b57cec5SDimitry Andric     error.SetErrorString("invalid register value to copy into");
570b57cec5SDimitry Andric     return 0;
580b57cec5SDimitry Andric   }
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   // Prepare a memory buffer that contains some or all of the register value
610b57cec5SDimitry Andric   const uint32_t bytes_copied =
620b57cec5SDimitry Andric       reg_data.CopyByteOrderedData(0,               // src offset
630b57cec5SDimitry Andric                                    src_len,         // src length
640b57cec5SDimitry Andric                                    dst,             // dst buffer
650b57cec5SDimitry Andric                                    dst_len,         // dst length
660b57cec5SDimitry Andric                                    dst_byte_order); // dst byte order
670b57cec5SDimitry Andric   if (bytes_copied == 0)
680b57cec5SDimitry Andric     error.SetErrorStringWithFormat(
69bdd1243dSDimitry Andric         "failed to copy data for register write of %s", reg_info.name);
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   return bytes_copied;
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric 
74bdd1243dSDimitry Andric uint32_t RegisterValue::SetFromMemoryData(const RegisterInfo &reg_info,
750b57cec5SDimitry Andric                                           const void *src, uint32_t src_len,
760b57cec5SDimitry Andric                                           lldb::ByteOrder src_byte_order,
770b57cec5SDimitry Andric                                           Status &error) {
780b57cec5SDimitry Andric   // Moving from addr into a register
790b57cec5SDimitry Andric   //
800b57cec5SDimitry Andric   // Case 1: src_len == dst_len
810b57cec5SDimitry Andric   //
820b57cec5SDimitry Andric   //   |AABBCCDD| Address contents
830b57cec5SDimitry Andric   //   |AABBCCDD| Register contents
840b57cec5SDimitry Andric   //
850b57cec5SDimitry Andric   // Case 2: src_len > dst_len
860b57cec5SDimitry Andric   //
870b57cec5SDimitry Andric   //   Status!  (The register should always be big enough to hold the data)
880b57cec5SDimitry Andric   //
890b57cec5SDimitry Andric   // Case 3: src_len < dst_len
900b57cec5SDimitry Andric   //
910b57cec5SDimitry Andric   //   |AABB| Address contents
920b57cec5SDimitry Andric   //   |AABB0000| Register contents [on little-endian hardware]
930b57cec5SDimitry Andric   //   |0000AABB| Register contents [on big-endian hardware]
94bdd1243dSDimitry Andric   const uint32_t dst_len = reg_info.byte_size;
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   if (src_len > dst_len) {
970b57cec5SDimitry Andric     error.SetErrorStringWithFormat(
980b57cec5SDimitry Andric         "%u bytes is too big to store in register %s (%u bytes)", src_len,
99bdd1243dSDimitry Andric         reg_info.name, dst_len);
1000b57cec5SDimitry Andric     return 0;
1010b57cec5SDimitry Andric   }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   // Use a data extractor to correctly copy and pad the bytes read into the
1040b57cec5SDimitry Andric   // register value
1050b57cec5SDimitry Andric   DataExtractor src_data(src, src_len, src_byte_order, 4);
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric   error = SetValueFromData(reg_info, src_data, 0, true);
1080b57cec5SDimitry Andric   if (error.Fail())
1090b57cec5SDimitry Andric     return 0;
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   // If SetValueFromData succeeded, we must have copied all of src_len
1120b57cec5SDimitry Andric   return src_len;
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric bool RegisterValue::GetScalarValue(Scalar &scalar) const {
1160b57cec5SDimitry Andric   switch (m_type) {
1170b57cec5SDimitry Andric   case eTypeInvalid:
1180b57cec5SDimitry Andric     break;
1190b57cec5SDimitry Andric   case eTypeBytes: {
12006c3fb27SDimitry Andric     DataExtractor data(buffer.bytes.data(), buffer.bytes.size(),
12106c3fb27SDimitry Andric                        buffer.byte_order, 1);
12206c3fb27SDimitry Andric     if (scalar.SetValueFromData(data, lldb::eEncodingUint, buffer.bytes.size())
12306c3fb27SDimitry Andric             .Success())
1240b57cec5SDimitry Andric       return true;
1250b57cec5SDimitry Andric   } break;
1260b57cec5SDimitry Andric   case eTypeUInt8:
1270b57cec5SDimitry Andric   case eTypeUInt16:
1280b57cec5SDimitry Andric   case eTypeUInt32:
1290b57cec5SDimitry Andric   case eTypeUInt64:
1300b57cec5SDimitry Andric   case eTypeUInt128:
1310b57cec5SDimitry Andric   case eTypeFloat:
1320b57cec5SDimitry Andric   case eTypeDouble:
1330b57cec5SDimitry Andric   case eTypeLongDouble:
1340b57cec5SDimitry Andric     scalar = m_scalar;
1350b57cec5SDimitry Andric     return true;
1360b57cec5SDimitry Andric   }
1370b57cec5SDimitry Andric   return false;
1380b57cec5SDimitry Andric }
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric void RegisterValue::Clear() { m_type = eTypeInvalid; }
1410b57cec5SDimitry Andric 
142bdd1243dSDimitry Andric RegisterValue::Type RegisterValue::SetType(const RegisterInfo &reg_info) {
1430b57cec5SDimitry Andric   // To change the type, we simply copy the data in again, using the new format
1440b57cec5SDimitry Andric   RegisterValue copy;
1450b57cec5SDimitry Andric   DataExtractor copy_data;
146bdd1243dSDimitry Andric   if (copy.CopyValue(*this) && copy.GetData(copy_data)) {
147bdd1243dSDimitry Andric     Status error = SetValueFromData(reg_info, copy_data, 0, true);
148bdd1243dSDimitry Andric     assert(error.Success() && "Expected SetValueFromData to succeed.");
149bdd1243dSDimitry Andric     UNUSED_IF_ASSERT_DISABLED(error);
150bdd1243dSDimitry Andric   }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   return m_type;
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
155bdd1243dSDimitry Andric Status RegisterValue::SetValueFromData(const RegisterInfo &reg_info,
1560b57cec5SDimitry Andric                                        DataExtractor &src,
1570b57cec5SDimitry Andric                                        lldb::offset_t src_offset,
1580b57cec5SDimitry Andric                                        bool partial_data_ok) {
1590b57cec5SDimitry Andric   Status error;
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   if (src.GetByteSize() == 0) {
1620b57cec5SDimitry Andric     error.SetErrorString("empty data.");
1630b57cec5SDimitry Andric     return error;
1640b57cec5SDimitry Andric   }
1650b57cec5SDimitry Andric 
166bdd1243dSDimitry Andric   if (reg_info.byte_size == 0) {
1670b57cec5SDimitry Andric     error.SetErrorString("invalid register info.");
1680b57cec5SDimitry Andric     return error;
1690b57cec5SDimitry Andric   }
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   uint32_t src_len = src.GetByteSize() - src_offset;
1720b57cec5SDimitry Andric 
173bdd1243dSDimitry Andric   if (!partial_data_ok && (src_len < reg_info.byte_size)) {
1740b57cec5SDimitry Andric     error.SetErrorString("not enough data.");
1750b57cec5SDimitry Andric     return error;
1760b57cec5SDimitry Andric   }
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   // Cap the data length if there is more than enough bytes for this register
1790b57cec5SDimitry Andric   // value
180bdd1243dSDimitry Andric   if (src_len > reg_info.byte_size)
181bdd1243dSDimitry Andric     src_len = reg_info.byte_size;
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   type128 int128;
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric   m_type = eTypeInvalid;
186bdd1243dSDimitry Andric   switch (reg_info.encoding) {
1870b57cec5SDimitry Andric   case eEncodingInvalid:
1880b57cec5SDimitry Andric     break;
1890b57cec5SDimitry Andric   case eEncodingUint:
1900b57cec5SDimitry Andric   case eEncodingSint:
191bdd1243dSDimitry Andric     if (reg_info.byte_size == 1)
1920b57cec5SDimitry Andric       SetUInt8(src.GetMaxU32(&src_offset, src_len));
193bdd1243dSDimitry Andric     else if (reg_info.byte_size <= 2)
1940b57cec5SDimitry Andric       SetUInt16(src.GetMaxU32(&src_offset, src_len));
195bdd1243dSDimitry Andric     else if (reg_info.byte_size <= 4)
1960b57cec5SDimitry Andric       SetUInt32(src.GetMaxU32(&src_offset, src_len));
197bdd1243dSDimitry Andric     else if (reg_info.byte_size <= 8)
1980b57cec5SDimitry Andric       SetUInt64(src.GetMaxU64(&src_offset, src_len));
199bdd1243dSDimitry Andric     else if (reg_info.byte_size <= 16) {
2000b57cec5SDimitry Andric       uint64_t data1 = src.GetU64(&src_offset);
2010b57cec5SDimitry Andric       uint64_t data2 = src.GetU64(&src_offset);
202*0fca6ea1SDimitry Andric       if (src.GetByteOrder() == eByteOrderBig) {
2030b57cec5SDimitry Andric         int128.x[0] = data1;
2040b57cec5SDimitry Andric         int128.x[1] = data2;
2050b57cec5SDimitry Andric       } else {
2060b57cec5SDimitry Andric         int128.x[0] = data2;
2070b57cec5SDimitry Andric         int128.x[1] = data1;
2080b57cec5SDimitry Andric       }
2090b57cec5SDimitry Andric       SetUInt128(llvm::APInt(128, 2, int128.x));
2100b57cec5SDimitry Andric     }
2110b57cec5SDimitry Andric     break;
2120b57cec5SDimitry Andric   case eEncodingIEEE754:
213bdd1243dSDimitry Andric     if (reg_info.byte_size == sizeof(float))
2140b57cec5SDimitry Andric       SetFloat(src.GetFloat(&src_offset));
215bdd1243dSDimitry Andric     else if (reg_info.byte_size == sizeof(double))
2160b57cec5SDimitry Andric       SetDouble(src.GetDouble(&src_offset));
217bdd1243dSDimitry Andric     else if (reg_info.byte_size == sizeof(long double))
2180b57cec5SDimitry Andric       SetLongDouble(src.GetLongDouble(&src_offset));
2190b57cec5SDimitry Andric     break;
2200b57cec5SDimitry Andric   case eEncodingVector: {
2210b57cec5SDimitry Andric     m_type = eTypeBytes;
22206c3fb27SDimitry Andric     assert(reg_info.byte_size <= kMaxRegisterByteSize);
22306c3fb27SDimitry Andric     buffer.bytes.resize(reg_info.byte_size);
2240b57cec5SDimitry Andric     buffer.byte_order = src.GetByteOrder();
2250b57cec5SDimitry Andric     if (src.CopyByteOrderedData(
2260b57cec5SDimitry Andric             src_offset,          // offset within "src" to start extracting data
2270b57cec5SDimitry Andric             src_len,             // src length
22806c3fb27SDimitry Andric             buffer.bytes.data(), // dst buffer
22906c3fb27SDimitry Andric             buffer.bytes.size(), // dst length
2300b57cec5SDimitry Andric             buffer.byte_order) == 0) // dst byte order
2310b57cec5SDimitry Andric     {
2320b57cec5SDimitry Andric       error.SetErrorStringWithFormat(
233bdd1243dSDimitry Andric           "failed to copy data for register write of %s", reg_info.name);
2340b57cec5SDimitry Andric       return error;
2350b57cec5SDimitry Andric     }
2360b57cec5SDimitry Andric   }
2370b57cec5SDimitry Andric   }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   if (m_type == eTypeInvalid)
2400b57cec5SDimitry Andric     error.SetErrorStringWithFormat(
241bdd1243dSDimitry Andric         "invalid register value type for register %s", reg_info.name);
2420b57cec5SDimitry Andric   return error;
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric // Helper function for RegisterValue::SetValueFromString()
2460b57cec5SDimitry Andric static bool ParseVectorEncoding(const RegisterInfo *reg_info,
2470b57cec5SDimitry Andric                                 llvm::StringRef vector_str,
2480b57cec5SDimitry Andric                                 const uint32_t byte_size,
2490b57cec5SDimitry Andric                                 RegisterValue *reg_value) {
2500b57cec5SDimitry Andric   // Example: vector_str = "{0x2c 0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a
2510b57cec5SDimitry Andric   // 0x2a 0x3e 0x84 0x4f 0x2a 0x3e}".
2520b57cec5SDimitry Andric   vector_str = vector_str.trim();
2530b57cec5SDimitry Andric   vector_str.consume_front("{");
2540b57cec5SDimitry Andric   vector_str.consume_back("}");
2550b57cec5SDimitry Andric   vector_str = vector_str.trim();
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric   char Sep = ' ';
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   // The first split should give us:
2600b57cec5SDimitry Andric   // ('0x2c', '0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a 0x2a 0x3e 0x84 0x4f
2610b57cec5SDimitry Andric   // 0x2a 0x3e').
2620b57cec5SDimitry Andric   llvm::StringRef car;
2630b57cec5SDimitry Andric   llvm::StringRef cdr = vector_str;
2640b57cec5SDimitry Andric   std::tie(car, cdr) = vector_str.split(Sep);
2650b57cec5SDimitry Andric   std::vector<uint8_t> bytes;
2660b57cec5SDimitry Andric   unsigned byte = 0;
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   // Using radix auto-sensing by passing 0 as the radix. Keep on processing the
2690b57cec5SDimitry Andric   // vector elements as long as the parsing succeeds and the vector size is <
2700b57cec5SDimitry Andric   // byte_size.
2710b57cec5SDimitry Andric   while (!car.getAsInteger(0, byte) && bytes.size() < byte_size) {
2720b57cec5SDimitry Andric     bytes.push_back(byte);
2730b57cec5SDimitry Andric     std::tie(car, cdr) = cdr.split(Sep);
2740b57cec5SDimitry Andric   }
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric   // Check for vector of exact byte_size elements.
2770b57cec5SDimitry Andric   if (bytes.size() != byte_size)
2780b57cec5SDimitry Andric     return false;
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric   reg_value->SetBytes(&(bytes.front()), byte_size, eByteOrderLittle);
2810b57cec5SDimitry Andric   return true;
2820b57cec5SDimitry Andric }
2830b57cec5SDimitry Andric 
284480093f4SDimitry Andric static bool UInt64ValueIsValidForByteSize(uint64_t uval64,
285480093f4SDimitry Andric                                           size_t total_byte_size) {
286480093f4SDimitry Andric   if (total_byte_size > 8)
287480093f4SDimitry Andric     return false;
288480093f4SDimitry Andric 
289480093f4SDimitry Andric   if (total_byte_size == 8)
290480093f4SDimitry Andric     return true;
291480093f4SDimitry Andric 
292480093f4SDimitry Andric   const uint64_t max =
293480093f4SDimitry Andric       (static_cast<uint64_t>(1) << static_cast<uint64_t>(total_byte_size * 8)) -
294480093f4SDimitry Andric       1;
295480093f4SDimitry Andric   return uval64 <= max;
296480093f4SDimitry Andric }
297480093f4SDimitry Andric 
298480093f4SDimitry Andric static bool SInt64ValueIsValidForByteSize(int64_t sval64,
299480093f4SDimitry Andric                                           size_t total_byte_size) {
300480093f4SDimitry Andric   if (total_byte_size > 8)
301480093f4SDimitry Andric     return false;
302480093f4SDimitry Andric 
303480093f4SDimitry Andric   if (total_byte_size == 8)
304480093f4SDimitry Andric     return true;
305480093f4SDimitry Andric 
306480093f4SDimitry Andric   const int64_t max = (static_cast<int64_t>(1)
307480093f4SDimitry Andric                        << static_cast<uint64_t>(total_byte_size * 8 - 1)) -
308480093f4SDimitry Andric                       1;
309480093f4SDimitry Andric   const int64_t min = ~(max);
310480093f4SDimitry Andric   return min <= sval64 && sval64 <= max;
311480093f4SDimitry Andric }
312480093f4SDimitry Andric 
3130b57cec5SDimitry Andric Status RegisterValue::SetValueFromString(const RegisterInfo *reg_info,
3140b57cec5SDimitry Andric                                          llvm::StringRef value_str) {
3150b57cec5SDimitry Andric   Status error;
3160b57cec5SDimitry Andric   if (reg_info == nullptr) {
3170b57cec5SDimitry Andric     error.SetErrorString("Invalid register info argument.");
3180b57cec5SDimitry Andric     return error;
3190b57cec5SDimitry Andric   }
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric   m_type = eTypeInvalid;
3220b57cec5SDimitry Andric   if (value_str.empty()) {
3230b57cec5SDimitry Andric     error.SetErrorString("Invalid c-string value string.");
3240b57cec5SDimitry Andric     return error;
3250b57cec5SDimitry Andric   }
3260b57cec5SDimitry Andric   const uint32_t byte_size = reg_info->byte_size;
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric   uint64_t uval64;
3290b57cec5SDimitry Andric   int64_t ival64;
3300b57cec5SDimitry Andric   float flt_val;
3310b57cec5SDimitry Andric   double dbl_val;
3320b57cec5SDimitry Andric   long double ldbl_val;
3330b57cec5SDimitry Andric   switch (reg_info->encoding) {
3340b57cec5SDimitry Andric   case eEncodingInvalid:
3350b57cec5SDimitry Andric     error.SetErrorString("Invalid encoding.");
3360b57cec5SDimitry Andric     break;
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric   case eEncodingUint:
3390b57cec5SDimitry Andric     if (byte_size > sizeof(uint64_t)) {
3400b57cec5SDimitry Andric       error.SetErrorStringWithFormat(
3410b57cec5SDimitry Andric           "unsupported unsigned integer byte size: %u", byte_size);
3420b57cec5SDimitry Andric       break;
3430b57cec5SDimitry Andric     }
3440b57cec5SDimitry Andric     if (value_str.getAsInteger(0, uval64)) {
34506c3fb27SDimitry Andric       error.SetErrorStringWithFormatv(
34606c3fb27SDimitry Andric           "'{0}' is not a valid unsigned integer string value", value_str);
3470b57cec5SDimitry Andric       break;
3480b57cec5SDimitry Andric     }
3490b57cec5SDimitry Andric 
350480093f4SDimitry Andric     if (!UInt64ValueIsValidForByteSize(uval64, byte_size)) {
3510b57cec5SDimitry Andric       error.SetErrorStringWithFormat(
3520b57cec5SDimitry Andric           "value 0x%" PRIx64
3530b57cec5SDimitry Andric           " is too large to fit in a %u byte unsigned integer value",
3540b57cec5SDimitry Andric           uval64, byte_size);
3550b57cec5SDimitry Andric       break;
3560b57cec5SDimitry Andric     }
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric     if (!SetUInt(uval64, reg_info->byte_size)) {
3590b57cec5SDimitry Andric       error.SetErrorStringWithFormat(
3600b57cec5SDimitry Andric           "unsupported unsigned integer byte size: %u", byte_size);
3610b57cec5SDimitry Andric       break;
3620b57cec5SDimitry Andric     }
3630b57cec5SDimitry Andric     break;
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric   case eEncodingSint:
3660b57cec5SDimitry Andric     if (byte_size > sizeof(long long)) {
3670b57cec5SDimitry Andric       error.SetErrorStringWithFormat("unsupported signed integer byte size: %u",
3680b57cec5SDimitry Andric                                      byte_size);
3690b57cec5SDimitry Andric       break;
3700b57cec5SDimitry Andric     }
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric     if (value_str.getAsInteger(0, ival64)) {
37306c3fb27SDimitry Andric       error.SetErrorStringWithFormatv(
37406c3fb27SDimitry Andric           "'{0}' is not a valid signed integer string value", value_str);
3750b57cec5SDimitry Andric       break;
3760b57cec5SDimitry Andric     }
3770b57cec5SDimitry Andric 
378480093f4SDimitry Andric     if (!SInt64ValueIsValidForByteSize(ival64, byte_size)) {
3790b57cec5SDimitry Andric       error.SetErrorStringWithFormat(
3800b57cec5SDimitry Andric           "value 0x%" PRIx64
3810b57cec5SDimitry Andric           " is too large to fit in a %u byte signed integer value",
3820b57cec5SDimitry Andric           ival64, byte_size);
3830b57cec5SDimitry Andric       break;
3840b57cec5SDimitry Andric     }
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric     if (!SetUInt(ival64, reg_info->byte_size)) {
3870b57cec5SDimitry Andric       error.SetErrorStringWithFormat("unsupported signed integer byte size: %u",
3880b57cec5SDimitry Andric                                      byte_size);
3890b57cec5SDimitry Andric       break;
3900b57cec5SDimitry Andric     }
3910b57cec5SDimitry Andric     break;
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric   case eEncodingIEEE754: {
3945ffd83dbSDimitry Andric     std::string value_string = std::string(value_str);
3950b57cec5SDimitry Andric     if (byte_size == sizeof(float)) {
3960b57cec5SDimitry Andric       if (::sscanf(value_string.c_str(), "%f", &flt_val) != 1) {
3970b57cec5SDimitry Andric         error.SetErrorStringWithFormat("'%s' is not a valid float string value",
3980b57cec5SDimitry Andric                                        value_string.c_str());
3990b57cec5SDimitry Andric         break;
4000b57cec5SDimitry Andric       }
4010b57cec5SDimitry Andric       m_scalar = flt_val;
4020b57cec5SDimitry Andric       m_type = eTypeFloat;
4030b57cec5SDimitry Andric     } else if (byte_size == sizeof(double)) {
4040b57cec5SDimitry Andric       if (::sscanf(value_string.c_str(), "%lf", &dbl_val) != 1) {
4050b57cec5SDimitry Andric         error.SetErrorStringWithFormat("'%s' is not a valid float string value",
4060b57cec5SDimitry Andric                                        value_string.c_str());
4070b57cec5SDimitry Andric         break;
4080b57cec5SDimitry Andric       }
4090b57cec5SDimitry Andric       m_scalar = dbl_val;
4100b57cec5SDimitry Andric       m_type = eTypeDouble;
4110b57cec5SDimitry Andric     } else if (byte_size == sizeof(long double)) {
4120b57cec5SDimitry Andric       if (::sscanf(value_string.c_str(), "%Lf", &ldbl_val) != 1) {
4130b57cec5SDimitry Andric         error.SetErrorStringWithFormat("'%s' is not a valid float string value",
4140b57cec5SDimitry Andric                                        value_string.c_str());
4150b57cec5SDimitry Andric         break;
4160b57cec5SDimitry Andric       }
4170b57cec5SDimitry Andric       m_scalar = ldbl_val;
4180b57cec5SDimitry Andric       m_type = eTypeLongDouble;
4190b57cec5SDimitry Andric     } else {
4200b57cec5SDimitry Andric       error.SetErrorStringWithFormat("unsupported float byte size: %u",
4210b57cec5SDimitry Andric                                      byte_size);
4220b57cec5SDimitry Andric       return error;
4230b57cec5SDimitry Andric     }
4240b57cec5SDimitry Andric     break;
4250b57cec5SDimitry Andric   }
4260b57cec5SDimitry Andric   case eEncodingVector:
4270b57cec5SDimitry Andric     if (!ParseVectorEncoding(reg_info, value_str, byte_size, this))
4280b57cec5SDimitry Andric       error.SetErrorString("unrecognized vector encoding string value.");
4290b57cec5SDimitry Andric     break;
4300b57cec5SDimitry Andric   }
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric   return error;
4330b57cec5SDimitry Andric }
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric bool RegisterValue::SignExtend(uint32_t sign_bitpos) {
4360b57cec5SDimitry Andric   switch (m_type) {
4370b57cec5SDimitry Andric   case eTypeInvalid:
4380b57cec5SDimitry Andric     break;
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric   case eTypeUInt8:
4410b57cec5SDimitry Andric   case eTypeUInt16:
4420b57cec5SDimitry Andric   case eTypeUInt32:
4430b57cec5SDimitry Andric   case eTypeUInt64:
4440b57cec5SDimitry Andric   case eTypeUInt128:
4450b57cec5SDimitry Andric     return m_scalar.SignExtend(sign_bitpos);
4460b57cec5SDimitry Andric   case eTypeFloat:
4470b57cec5SDimitry Andric   case eTypeDouble:
4480b57cec5SDimitry Andric   case eTypeLongDouble:
4490b57cec5SDimitry Andric   case eTypeBytes:
4500b57cec5SDimitry Andric     break;
4510b57cec5SDimitry Andric   }
4520b57cec5SDimitry Andric   return false;
4530b57cec5SDimitry Andric }
4540b57cec5SDimitry Andric 
4550b57cec5SDimitry Andric bool RegisterValue::CopyValue(const RegisterValue &rhs) {
4560b57cec5SDimitry Andric   if (this == &rhs)
4570b57cec5SDimitry Andric     return rhs.m_type != eTypeInvalid;
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric   m_type = rhs.m_type;
4600b57cec5SDimitry Andric   switch (m_type) {
4610b57cec5SDimitry Andric   case eTypeInvalid:
4620b57cec5SDimitry Andric     return false;
4630b57cec5SDimitry Andric   case eTypeUInt8:
4640b57cec5SDimitry Andric   case eTypeUInt16:
4650b57cec5SDimitry Andric   case eTypeUInt32:
4660b57cec5SDimitry Andric   case eTypeUInt64:
4670b57cec5SDimitry Andric   case eTypeUInt128:
4680b57cec5SDimitry Andric   case eTypeFloat:
4690b57cec5SDimitry Andric   case eTypeDouble:
4700b57cec5SDimitry Andric   case eTypeLongDouble:
4710b57cec5SDimitry Andric     m_scalar = rhs.m_scalar;
4720b57cec5SDimitry Andric     break;
4730b57cec5SDimitry Andric   case eTypeBytes:
47406c3fb27SDimitry Andric     buffer.bytes = rhs.buffer.bytes;
4750b57cec5SDimitry Andric     buffer.byte_order = rhs.buffer.byte_order;
4760b57cec5SDimitry Andric     break;
4770b57cec5SDimitry Andric   }
4780b57cec5SDimitry Andric   return true;
4790b57cec5SDimitry Andric }
4800b57cec5SDimitry Andric 
4810b57cec5SDimitry Andric uint16_t RegisterValue::GetAsUInt16(uint16_t fail_value,
4820b57cec5SDimitry Andric                                     bool *success_ptr) const {
4830b57cec5SDimitry Andric   if (success_ptr)
4840b57cec5SDimitry Andric     *success_ptr = true;
4850b57cec5SDimitry Andric 
4860b57cec5SDimitry Andric   switch (m_type) {
4870b57cec5SDimitry Andric   default:
4880b57cec5SDimitry Andric     break;
4890b57cec5SDimitry Andric   case eTypeUInt8:
4900b57cec5SDimitry Andric   case eTypeUInt16:
4910b57cec5SDimitry Andric     return m_scalar.UShort(fail_value);
4920b57cec5SDimitry Andric   case eTypeBytes: {
49306c3fb27SDimitry Andric     switch (buffer.bytes.size()) {
4940b57cec5SDimitry Andric     default:
4950b57cec5SDimitry Andric       break;
4960b57cec5SDimitry Andric     case 1:
4970b57cec5SDimitry Andric     case 2:
49806c3fb27SDimitry Andric       return *reinterpret_cast<const uint16_t *>(buffer.bytes.data());
4990b57cec5SDimitry Andric     }
5000b57cec5SDimitry Andric   } break;
5010b57cec5SDimitry Andric   }
5020b57cec5SDimitry Andric   if (success_ptr)
5030b57cec5SDimitry Andric     *success_ptr = false;
5040b57cec5SDimitry Andric   return fail_value;
5050b57cec5SDimitry Andric }
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric uint32_t RegisterValue::GetAsUInt32(uint32_t fail_value,
5080b57cec5SDimitry Andric                                     bool *success_ptr) const {
5090b57cec5SDimitry Andric   if (success_ptr)
5100b57cec5SDimitry Andric     *success_ptr = true;
5110b57cec5SDimitry Andric   switch (m_type) {
5120b57cec5SDimitry Andric   default:
5130b57cec5SDimitry Andric     break;
5140b57cec5SDimitry Andric   case eTypeUInt8:
5150b57cec5SDimitry Andric   case eTypeUInt16:
5160b57cec5SDimitry Andric   case eTypeUInt32:
5170b57cec5SDimitry Andric   case eTypeFloat:
5180b57cec5SDimitry Andric   case eTypeDouble:
5190b57cec5SDimitry Andric   case eTypeLongDouble:
5200b57cec5SDimitry Andric     return m_scalar.UInt(fail_value);
5210b57cec5SDimitry Andric   case eTypeBytes: {
52206c3fb27SDimitry Andric     switch (buffer.bytes.size()) {
5230b57cec5SDimitry Andric     default:
5240b57cec5SDimitry Andric       break;
5250b57cec5SDimitry Andric     case 1:
5260b57cec5SDimitry Andric     case 2:
5270b57cec5SDimitry Andric     case 4:
52806c3fb27SDimitry Andric       return *reinterpret_cast<const uint32_t *>(buffer.bytes.data());
5290b57cec5SDimitry Andric     }
5300b57cec5SDimitry Andric   } break;
5310b57cec5SDimitry Andric   }
5320b57cec5SDimitry Andric   if (success_ptr)
5330b57cec5SDimitry Andric     *success_ptr = false;
5340b57cec5SDimitry Andric   return fail_value;
5350b57cec5SDimitry Andric }
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric uint64_t RegisterValue::GetAsUInt64(uint64_t fail_value,
5380b57cec5SDimitry Andric                                     bool *success_ptr) const {
5390b57cec5SDimitry Andric   if (success_ptr)
5400b57cec5SDimitry Andric     *success_ptr = true;
5410b57cec5SDimitry Andric   switch (m_type) {
5420b57cec5SDimitry Andric   default:
5430b57cec5SDimitry Andric     break;
5440b57cec5SDimitry Andric   case eTypeUInt8:
5450b57cec5SDimitry Andric   case eTypeUInt16:
5460b57cec5SDimitry Andric   case eTypeUInt32:
5470b57cec5SDimitry Andric   case eTypeUInt64:
5480b57cec5SDimitry Andric   case eTypeFloat:
5490b57cec5SDimitry Andric   case eTypeDouble:
5500b57cec5SDimitry Andric   case eTypeLongDouble:
5510b57cec5SDimitry Andric     return m_scalar.ULongLong(fail_value);
5520b57cec5SDimitry Andric   case eTypeBytes: {
55306c3fb27SDimitry Andric     switch (buffer.bytes.size()) {
5540b57cec5SDimitry Andric     default:
5550b57cec5SDimitry Andric       break;
5560b57cec5SDimitry Andric     case 1:
55706c3fb27SDimitry Andric       return *(const uint8_t *)buffer.bytes.data();
5580b57cec5SDimitry Andric     case 2:
55906c3fb27SDimitry Andric       return *reinterpret_cast<const uint16_t *>(buffer.bytes.data());
5600b57cec5SDimitry Andric     case 4:
56106c3fb27SDimitry Andric       return *reinterpret_cast<const uint32_t *>(buffer.bytes.data());
5620b57cec5SDimitry Andric     case 8:
56306c3fb27SDimitry Andric       return *reinterpret_cast<const uint64_t *>(buffer.bytes.data());
5640b57cec5SDimitry Andric     }
5650b57cec5SDimitry Andric   } break;
5660b57cec5SDimitry Andric   }
5670b57cec5SDimitry Andric   if (success_ptr)
5680b57cec5SDimitry Andric     *success_ptr = false;
5690b57cec5SDimitry Andric   return fail_value;
5700b57cec5SDimitry Andric }
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric llvm::APInt RegisterValue::GetAsUInt128(const llvm::APInt &fail_value,
5730b57cec5SDimitry Andric                                         bool *success_ptr) const {
5740b57cec5SDimitry Andric   if (success_ptr)
5750b57cec5SDimitry Andric     *success_ptr = true;
5760b57cec5SDimitry Andric   switch (m_type) {
5770b57cec5SDimitry Andric   default:
5780b57cec5SDimitry Andric     break;
5790b57cec5SDimitry Andric   case eTypeUInt8:
5800b57cec5SDimitry Andric   case eTypeUInt16:
5810b57cec5SDimitry Andric   case eTypeUInt32:
5820b57cec5SDimitry Andric   case eTypeUInt64:
5830b57cec5SDimitry Andric   case eTypeUInt128:
5840b57cec5SDimitry Andric   case eTypeFloat:
5850b57cec5SDimitry Andric   case eTypeDouble:
5860b57cec5SDimitry Andric   case eTypeLongDouble:
5870b57cec5SDimitry Andric     return m_scalar.UInt128(fail_value);
5880b57cec5SDimitry Andric   case eTypeBytes: {
58906c3fb27SDimitry Andric     switch (buffer.bytes.size()) {
5900b57cec5SDimitry Andric     default:
5910b57cec5SDimitry Andric       break;
5920b57cec5SDimitry Andric     case 1:
5930b57cec5SDimitry Andric     case 2:
5940b57cec5SDimitry Andric     case 4:
5950b57cec5SDimitry Andric     case 8:
5960b57cec5SDimitry Andric     case 16:
59706c3fb27SDimitry Andric       return llvm::APInt(
59806c3fb27SDimitry Andric           BITWIDTH_INT128, NUM_OF_WORDS_INT128,
59906c3fb27SDimitry Andric           (reinterpret_cast<const type128 *>(buffer.bytes.data()))->x);
6000b57cec5SDimitry Andric     }
6010b57cec5SDimitry Andric   } break;
6020b57cec5SDimitry Andric   }
6030b57cec5SDimitry Andric   if (success_ptr)
6040b57cec5SDimitry Andric     *success_ptr = false;
6050b57cec5SDimitry Andric   return fail_value;
6060b57cec5SDimitry Andric }
6070b57cec5SDimitry Andric 
6080b57cec5SDimitry Andric float RegisterValue::GetAsFloat(float fail_value, bool *success_ptr) const {
6090b57cec5SDimitry Andric   if (success_ptr)
6100b57cec5SDimitry Andric     *success_ptr = true;
6110b57cec5SDimitry Andric   switch (m_type) {
6120b57cec5SDimitry Andric   default:
6130b57cec5SDimitry Andric     break;
6140b57cec5SDimitry Andric   case eTypeUInt32:
6150b57cec5SDimitry Andric   case eTypeUInt64:
6160b57cec5SDimitry Andric   case eTypeUInt128:
6170b57cec5SDimitry Andric   case eTypeFloat:
6180b57cec5SDimitry Andric   case eTypeDouble:
6190b57cec5SDimitry Andric   case eTypeLongDouble:
6200b57cec5SDimitry Andric     return m_scalar.Float(fail_value);
6210b57cec5SDimitry Andric   }
6220b57cec5SDimitry Andric   if (success_ptr)
6230b57cec5SDimitry Andric     *success_ptr = false;
6240b57cec5SDimitry Andric   return fail_value;
6250b57cec5SDimitry Andric }
6260b57cec5SDimitry Andric 
6270b57cec5SDimitry Andric double RegisterValue::GetAsDouble(double fail_value, bool *success_ptr) const {
6280b57cec5SDimitry Andric   if (success_ptr)
6290b57cec5SDimitry Andric     *success_ptr = true;
6300b57cec5SDimitry Andric   switch (m_type) {
6310b57cec5SDimitry Andric   default:
6320b57cec5SDimitry Andric     break;
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric   case eTypeUInt32:
6350b57cec5SDimitry Andric   case eTypeUInt64:
6360b57cec5SDimitry Andric   case eTypeUInt128:
6370b57cec5SDimitry Andric   case eTypeFloat:
6380b57cec5SDimitry Andric   case eTypeDouble:
6390b57cec5SDimitry Andric   case eTypeLongDouble:
6400b57cec5SDimitry Andric     return m_scalar.Double(fail_value);
6410b57cec5SDimitry Andric   }
6420b57cec5SDimitry Andric   if (success_ptr)
6430b57cec5SDimitry Andric     *success_ptr = false;
6440b57cec5SDimitry Andric   return fail_value;
6450b57cec5SDimitry Andric }
6460b57cec5SDimitry Andric 
6470b57cec5SDimitry Andric long double RegisterValue::GetAsLongDouble(long double fail_value,
6480b57cec5SDimitry Andric                                            bool *success_ptr) const {
6490b57cec5SDimitry Andric   if (success_ptr)
6500b57cec5SDimitry Andric     *success_ptr = true;
6510b57cec5SDimitry Andric   switch (m_type) {
6520b57cec5SDimitry Andric   default:
6530b57cec5SDimitry Andric     break;
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric   case eTypeUInt32:
6560b57cec5SDimitry Andric   case eTypeUInt64:
6570b57cec5SDimitry Andric   case eTypeUInt128:
6580b57cec5SDimitry Andric   case eTypeFloat:
6590b57cec5SDimitry Andric   case eTypeDouble:
6600b57cec5SDimitry Andric   case eTypeLongDouble:
6610b57cec5SDimitry Andric     return m_scalar.LongDouble();
6620b57cec5SDimitry Andric   }
6630b57cec5SDimitry Andric   if (success_ptr)
6640b57cec5SDimitry Andric     *success_ptr = false;
6650b57cec5SDimitry Andric   return fail_value;
6660b57cec5SDimitry Andric }
6670b57cec5SDimitry Andric 
6680b57cec5SDimitry Andric const void *RegisterValue::GetBytes() const {
6690b57cec5SDimitry Andric   switch (m_type) {
6700b57cec5SDimitry Andric   case eTypeInvalid:
6710b57cec5SDimitry Andric     break;
6720b57cec5SDimitry Andric   case eTypeUInt8:
6730b57cec5SDimitry Andric   case eTypeUInt16:
6740b57cec5SDimitry Andric   case eTypeUInt32:
6750b57cec5SDimitry Andric   case eTypeUInt64:
6760b57cec5SDimitry Andric   case eTypeUInt128:
6770b57cec5SDimitry Andric   case eTypeFloat:
6780b57cec5SDimitry Andric   case eTypeDouble:
6790b57cec5SDimitry Andric   case eTypeLongDouble:
6805ffd83dbSDimitry Andric     m_scalar.GetBytes(buffer.bytes);
68106c3fb27SDimitry Andric     return buffer.bytes.data();
6820b57cec5SDimitry Andric   case eTypeBytes:
68306c3fb27SDimitry Andric     return buffer.bytes.data();
6840b57cec5SDimitry Andric   }
6850b57cec5SDimitry Andric   return nullptr;
6860b57cec5SDimitry Andric }
6870b57cec5SDimitry Andric 
6880b57cec5SDimitry Andric uint32_t RegisterValue::GetByteSize() const {
6890b57cec5SDimitry Andric   switch (m_type) {
6900b57cec5SDimitry Andric   case eTypeInvalid:
6910b57cec5SDimitry Andric     break;
6920b57cec5SDimitry Andric   case eTypeUInt8:
6930b57cec5SDimitry Andric     return 1;
6940b57cec5SDimitry Andric   case eTypeUInt16:
6950b57cec5SDimitry Andric     return 2;
6960b57cec5SDimitry Andric   case eTypeUInt32:
6970b57cec5SDimitry Andric   case eTypeUInt64:
6980b57cec5SDimitry Andric   case eTypeUInt128:
6990b57cec5SDimitry Andric   case eTypeFloat:
7000b57cec5SDimitry Andric   case eTypeDouble:
7010b57cec5SDimitry Andric   case eTypeLongDouble:
7020b57cec5SDimitry Andric     return m_scalar.GetByteSize();
7030b57cec5SDimitry Andric   case eTypeBytes:
70406c3fb27SDimitry Andric     return buffer.bytes.size();
7050b57cec5SDimitry Andric   }
7060b57cec5SDimitry Andric   return 0;
7070b57cec5SDimitry Andric }
7080b57cec5SDimitry Andric 
7090b57cec5SDimitry Andric bool RegisterValue::SetUInt(uint64_t uint, uint32_t byte_size) {
7100b57cec5SDimitry Andric   if (byte_size == 0) {
7110b57cec5SDimitry Andric     SetUInt64(uint);
7120b57cec5SDimitry Andric   } else if (byte_size == 1) {
7130b57cec5SDimitry Andric     SetUInt8(uint);
7140b57cec5SDimitry Andric   } else if (byte_size <= 2) {
7150b57cec5SDimitry Andric     SetUInt16(uint);
7160b57cec5SDimitry Andric   } else if (byte_size <= 4) {
7170b57cec5SDimitry Andric     SetUInt32(uint);
7180b57cec5SDimitry Andric   } else if (byte_size <= 8) {
7190b57cec5SDimitry Andric     SetUInt64(uint);
7200b57cec5SDimitry Andric   } else if (byte_size <= 16) {
7210b57cec5SDimitry Andric     SetUInt128(llvm::APInt(128, uint));
7220b57cec5SDimitry Andric   } else
7230b57cec5SDimitry Andric     return false;
7240b57cec5SDimitry Andric   return true;
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric void RegisterValue::SetBytes(const void *bytes, size_t length,
7280b57cec5SDimitry Andric                              lldb::ByteOrder byte_order) {
7290b57cec5SDimitry Andric   if (bytes && length > 0) {
7300b57cec5SDimitry Andric     m_type = eTypeBytes;
73106c3fb27SDimitry Andric     buffer.bytes.resize(length);
73206c3fb27SDimitry Andric     memcpy(buffer.bytes.data(), bytes, length);
7330b57cec5SDimitry Andric     buffer.byte_order = byte_order;
7340b57cec5SDimitry Andric   } else {
7350b57cec5SDimitry Andric     m_type = eTypeInvalid;
73606c3fb27SDimitry Andric     buffer.bytes.resize(0);
7370b57cec5SDimitry Andric   }
7380b57cec5SDimitry Andric }
7390b57cec5SDimitry Andric 
7400b57cec5SDimitry Andric bool RegisterValue::operator==(const RegisterValue &rhs) const {
7410b57cec5SDimitry Andric   if (m_type == rhs.m_type) {
7420b57cec5SDimitry Andric     switch (m_type) {
7430b57cec5SDimitry Andric     case eTypeInvalid:
7440b57cec5SDimitry Andric       return true;
7450b57cec5SDimitry Andric     case eTypeUInt8:
7460b57cec5SDimitry Andric     case eTypeUInt16:
7470b57cec5SDimitry Andric     case eTypeUInt32:
7480b57cec5SDimitry Andric     case eTypeUInt64:
7490b57cec5SDimitry Andric     case eTypeUInt128:
7500b57cec5SDimitry Andric     case eTypeFloat:
7510b57cec5SDimitry Andric     case eTypeDouble:
7520b57cec5SDimitry Andric     case eTypeLongDouble:
7530b57cec5SDimitry Andric       return m_scalar == rhs.m_scalar;
7540b57cec5SDimitry Andric     case eTypeBytes:
75506c3fb27SDimitry Andric       return buffer.bytes == rhs.buffer.bytes;
7560b57cec5SDimitry Andric     }
7570b57cec5SDimitry Andric   }
7580b57cec5SDimitry Andric   return false;
7590b57cec5SDimitry Andric }
7600b57cec5SDimitry Andric 
7610b57cec5SDimitry Andric bool RegisterValue::operator!=(const RegisterValue &rhs) const {
7620b57cec5SDimitry Andric   return !(*this == rhs);
7630b57cec5SDimitry Andric }
7640b57cec5SDimitry Andric 
7650b57cec5SDimitry Andric bool RegisterValue::ClearBit(uint32_t bit) {
7660b57cec5SDimitry Andric   switch (m_type) {
7670b57cec5SDimitry Andric   case eTypeInvalid:
7680b57cec5SDimitry Andric     break;
7690b57cec5SDimitry Andric 
7700b57cec5SDimitry Andric   case eTypeUInt8:
7710b57cec5SDimitry Andric   case eTypeUInt16:
7720b57cec5SDimitry Andric   case eTypeUInt32:
7730b57cec5SDimitry Andric   case eTypeUInt64:
7740b57cec5SDimitry Andric   case eTypeUInt128:
7750b57cec5SDimitry Andric     if (bit < (GetByteSize() * 8)) {
7760b57cec5SDimitry Andric       return m_scalar.ClearBit(bit);
7770b57cec5SDimitry Andric     }
7780b57cec5SDimitry Andric     break;
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric   case eTypeFloat:
7810b57cec5SDimitry Andric   case eTypeDouble:
7820b57cec5SDimitry Andric   case eTypeLongDouble:
7830b57cec5SDimitry Andric     break;
7840b57cec5SDimitry Andric 
7850b57cec5SDimitry Andric   case eTypeBytes:
7860b57cec5SDimitry Andric     if (buffer.byte_order == eByteOrderBig ||
7870b57cec5SDimitry Andric         buffer.byte_order == eByteOrderLittle) {
7880b57cec5SDimitry Andric       uint32_t byte_idx;
7890b57cec5SDimitry Andric       if (buffer.byte_order == eByteOrderBig)
79006c3fb27SDimitry Andric         byte_idx = buffer.bytes.size() - (bit / 8) - 1;
7910b57cec5SDimitry Andric       else
7920b57cec5SDimitry Andric         byte_idx = bit / 8;
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric       const uint32_t byte_bit = bit % 8;
79506c3fb27SDimitry Andric       if (byte_idx < buffer.bytes.size()) {
7960b57cec5SDimitry Andric         buffer.bytes[byte_idx] &= ~(1u << byte_bit);
7970b57cec5SDimitry Andric         return true;
7980b57cec5SDimitry Andric       }
7990b57cec5SDimitry Andric     }
8000b57cec5SDimitry Andric     break;
8010b57cec5SDimitry Andric   }
8020b57cec5SDimitry Andric   return false;
8030b57cec5SDimitry Andric }
8040b57cec5SDimitry Andric 
8050b57cec5SDimitry Andric bool RegisterValue::SetBit(uint32_t bit) {
8060b57cec5SDimitry Andric   switch (m_type) {
8070b57cec5SDimitry Andric   case eTypeInvalid:
8080b57cec5SDimitry Andric     break;
8090b57cec5SDimitry Andric 
8100b57cec5SDimitry Andric   case eTypeUInt8:
8110b57cec5SDimitry Andric   case eTypeUInt16:
8120b57cec5SDimitry Andric   case eTypeUInt32:
8130b57cec5SDimitry Andric   case eTypeUInt64:
8140b57cec5SDimitry Andric   case eTypeUInt128:
8150b57cec5SDimitry Andric     if (bit < (GetByteSize() * 8)) {
8160b57cec5SDimitry Andric       return m_scalar.SetBit(bit);
8170b57cec5SDimitry Andric     }
8180b57cec5SDimitry Andric     break;
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric   case eTypeFloat:
8210b57cec5SDimitry Andric   case eTypeDouble:
8220b57cec5SDimitry Andric   case eTypeLongDouble:
8230b57cec5SDimitry Andric     break;
8240b57cec5SDimitry Andric 
8250b57cec5SDimitry Andric   case eTypeBytes:
8260b57cec5SDimitry Andric     if (buffer.byte_order == eByteOrderBig ||
8270b57cec5SDimitry Andric         buffer.byte_order == eByteOrderLittle) {
8280b57cec5SDimitry Andric       uint32_t byte_idx;
8290b57cec5SDimitry Andric       if (buffer.byte_order == eByteOrderBig)
83006c3fb27SDimitry Andric         byte_idx = buffer.bytes.size() - (bit / 8) - 1;
8310b57cec5SDimitry Andric       else
8320b57cec5SDimitry Andric         byte_idx = bit / 8;
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric       const uint32_t byte_bit = bit % 8;
83506c3fb27SDimitry Andric       if (byte_idx < buffer.bytes.size()) {
8360b57cec5SDimitry Andric         buffer.bytes[byte_idx] |= (1u << byte_bit);
8370b57cec5SDimitry Andric         return true;
8380b57cec5SDimitry Andric       }
8390b57cec5SDimitry Andric     }
8400b57cec5SDimitry Andric     break;
8410b57cec5SDimitry Andric   }
8420b57cec5SDimitry Andric   return false;
8430b57cec5SDimitry Andric }
844