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 ®_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 ®_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 ®_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 ®_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