1343181Sdim//===-- RegisterValue.cpp ---------------------------------------*- C++ -*-===// 2343181Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6343181Sdim// 7343181Sdim//===----------------------------------------------------------------------===// 8343181Sdim 9343181Sdim#include "lldb/Utility/RegisterValue.h" 10343181Sdim 11343181Sdim#include "lldb/Utility/DataExtractor.h" 12343181Sdim#include "lldb/Utility/Scalar.h" 13343181Sdim#include "lldb/Utility/Status.h" 14343181Sdim#include "lldb/Utility/Stream.h" 15343181Sdim#include "lldb/Utility/StreamString.h" 16343181Sdim#include "lldb/lldb-defines.h" 17343181Sdim#include "lldb/lldb-private-types.h" 18343181Sdim 19343181Sdim#include "llvm/ADT/ArrayRef.h" 20343181Sdim#include "llvm/ADT/StringRef.h" 21343181Sdim 22343181Sdim#include <cstdint> 23343181Sdim#include <string> 24343181Sdim#include <tuple> 25343181Sdim#include <vector> 26343181Sdim 27343181Sdim#include <assert.h> 28343181Sdim#include <inttypes.h> 29343181Sdim#include <stdio.h> 30343181Sdim 31343181Sdimusing namespace lldb; 32343181Sdimusing namespace lldb_private; 33343181Sdim 34343181Sdimbool RegisterValue::GetData(DataExtractor &data) const { 35343181Sdim return data.SetData(GetBytes(), GetByteSize(), GetByteOrder()) > 0; 36343181Sdim} 37343181Sdim 38343181Sdimuint32_t RegisterValue::GetAsMemoryData(const RegisterInfo *reg_info, void *dst, 39343181Sdim uint32_t dst_len, 40343181Sdim lldb::ByteOrder dst_byte_order, 41343181Sdim Status &error) const { 42343181Sdim if (reg_info == nullptr) { 43343181Sdim error.SetErrorString("invalid register info argument."); 44343181Sdim return 0; 45343181Sdim } 46343181Sdim 47343181Sdim // ReadRegister should have already been called on this object prior to 48343181Sdim // calling this. 49343181Sdim if (GetType() == eTypeInvalid) { 50343181Sdim // No value has been read into this object... 51343181Sdim error.SetErrorStringWithFormat( 52343181Sdim "invalid register value type for register %s", reg_info->name); 53343181Sdim return 0; 54343181Sdim } 55343181Sdim 56343181Sdim if (dst_len > kMaxRegisterByteSize) { 57343181Sdim error.SetErrorString("destination is too big"); 58343181Sdim return 0; 59343181Sdim } 60343181Sdim 61343181Sdim const uint32_t src_len = reg_info->byte_size; 62343181Sdim 63343181Sdim // Extract the register data into a data extractor 64343181Sdim DataExtractor reg_data; 65343181Sdim if (!GetData(reg_data)) { 66343181Sdim error.SetErrorString("invalid register value to copy into"); 67343181Sdim return 0; 68343181Sdim } 69343181Sdim 70343181Sdim // Prepare a memory buffer that contains some or all of the register value 71343181Sdim const uint32_t bytes_copied = 72343181Sdim reg_data.CopyByteOrderedData(0, // src offset 73343181Sdim src_len, // src length 74343181Sdim dst, // dst buffer 75343181Sdim dst_len, // dst length 76343181Sdim dst_byte_order); // dst byte order 77343181Sdim if (bytes_copied == 0) 78343181Sdim error.SetErrorStringWithFormat( 79343181Sdim "failed to copy data for register write of %s", reg_info->name); 80343181Sdim 81343181Sdim return bytes_copied; 82343181Sdim} 83343181Sdim 84343181Sdimuint32_t RegisterValue::SetFromMemoryData(const RegisterInfo *reg_info, 85343181Sdim const void *src, uint32_t src_len, 86343181Sdim lldb::ByteOrder src_byte_order, 87343181Sdim Status &error) { 88343181Sdim if (reg_info == nullptr) { 89343181Sdim error.SetErrorString("invalid register info argument."); 90343181Sdim return 0; 91343181Sdim } 92343181Sdim 93343181Sdim // Moving from addr into a register 94343181Sdim // 95343181Sdim // Case 1: src_len == dst_len 96343181Sdim // 97343181Sdim // |AABBCCDD| Address contents 98343181Sdim // |AABBCCDD| Register contents 99343181Sdim // 100343181Sdim // Case 2: src_len > dst_len 101343181Sdim // 102343181Sdim // Status! (The register should always be big enough to hold the data) 103343181Sdim // 104343181Sdim // Case 3: src_len < dst_len 105343181Sdim // 106343181Sdim // |AABB| Address contents 107343181Sdim // |AABB0000| Register contents [on little-endian hardware] 108343181Sdim // |0000AABB| Register contents [on big-endian hardware] 109343181Sdim if (src_len > kMaxRegisterByteSize) { 110343181Sdim error.SetErrorStringWithFormat( 111343181Sdim "register buffer is too small to receive %u bytes of data.", src_len); 112343181Sdim return 0; 113343181Sdim } 114343181Sdim 115343181Sdim const uint32_t dst_len = reg_info->byte_size; 116343181Sdim 117343181Sdim if (src_len > dst_len) { 118343181Sdim error.SetErrorStringWithFormat( 119343181Sdim "%u bytes is too big to store in register %s (%u bytes)", src_len, 120343181Sdim reg_info->name, dst_len); 121343181Sdim return 0; 122343181Sdim } 123343181Sdim 124343181Sdim // Use a data extractor to correctly copy and pad the bytes read into the 125343181Sdim // register value 126343181Sdim DataExtractor src_data(src, src_len, src_byte_order, 4); 127343181Sdim 128343181Sdim error = SetValueFromData(reg_info, src_data, 0, true); 129343181Sdim if (error.Fail()) 130343181Sdim return 0; 131343181Sdim 132343181Sdim // If SetValueFromData succeeded, we must have copied all of src_len 133343181Sdim return src_len; 134343181Sdim} 135343181Sdim 136343181Sdimbool RegisterValue::GetScalarValue(Scalar &scalar) const { 137343181Sdim switch (m_type) { 138343181Sdim case eTypeInvalid: 139343181Sdim break; 140343181Sdim case eTypeBytes: { 141343181Sdim switch (buffer.length) { 142343181Sdim default: 143343181Sdim break; 144343181Sdim case 1: 145343181Sdim scalar = *(const uint8_t *)buffer.bytes; 146343181Sdim return true; 147343181Sdim case 2: 148353358Sdim scalar = *reinterpret_cast<const uint16_t *>(buffer.bytes); 149343181Sdim return true; 150343181Sdim case 4: 151353358Sdim scalar = *reinterpret_cast<const uint32_t *>(buffer.bytes); 152343181Sdim return true; 153343181Sdim case 8: 154353358Sdim scalar = *reinterpret_cast<const uint64_t *>(buffer.bytes); 155343181Sdim return true; 156343181Sdim case 16: 157343181Sdim case 32: 158353358Sdim case 64: 159343181Sdim if (buffer.length % sizeof(uint64_t) == 0) { 160343181Sdim const auto length_in_bits = buffer.length * 8; 161343181Sdim const auto length_in_uint64 = buffer.length / sizeof(uint64_t); 162343181Sdim scalar = 163343181Sdim llvm::APInt(length_in_bits, 164353358Sdim llvm::ArrayRef<uint64_t>( 165353358Sdim reinterpret_cast<const uint64_t *>(buffer.bytes), 166353358Sdim length_in_uint64)); 167343181Sdim return true; 168343181Sdim } 169343181Sdim break; 170343181Sdim } 171343181Sdim } break; 172343181Sdim case eTypeUInt8: 173343181Sdim case eTypeUInt16: 174343181Sdim case eTypeUInt32: 175343181Sdim case eTypeUInt64: 176343181Sdim case eTypeUInt128: 177343181Sdim case eTypeFloat: 178343181Sdim case eTypeDouble: 179343181Sdim case eTypeLongDouble: 180343181Sdim scalar = m_scalar; 181343181Sdim return true; 182343181Sdim } 183343181Sdim return false; 184343181Sdim} 185343181Sdim 186343181Sdimvoid RegisterValue::Clear() { m_type = eTypeInvalid; } 187343181Sdim 188343181SdimRegisterValue::Type RegisterValue::SetType(const RegisterInfo *reg_info) { 189343181Sdim // To change the type, we simply copy the data in again, using the new format 190343181Sdim RegisterValue copy; 191343181Sdim DataExtractor copy_data; 192343181Sdim if (copy.CopyValue(*this) && copy.GetData(copy_data)) 193343181Sdim SetValueFromData(reg_info, copy_data, 0, true); 194343181Sdim 195343181Sdim return m_type; 196343181Sdim} 197343181Sdim 198343181SdimStatus RegisterValue::SetValueFromData(const RegisterInfo *reg_info, 199343181Sdim DataExtractor &src, 200343181Sdim lldb::offset_t src_offset, 201343181Sdim bool partial_data_ok) { 202343181Sdim Status error; 203343181Sdim 204343181Sdim if (src.GetByteSize() == 0) { 205343181Sdim error.SetErrorString("empty data."); 206343181Sdim return error; 207343181Sdim } 208343181Sdim 209343181Sdim if (reg_info->byte_size == 0) { 210343181Sdim error.SetErrorString("invalid register info."); 211343181Sdim return error; 212343181Sdim } 213343181Sdim 214343181Sdim uint32_t src_len = src.GetByteSize() - src_offset; 215343181Sdim 216343181Sdim if (!partial_data_ok && (src_len < reg_info->byte_size)) { 217343181Sdim error.SetErrorString("not enough data."); 218343181Sdim return error; 219343181Sdim } 220343181Sdim 221343181Sdim // Cap the data length if there is more than enough bytes for this register 222343181Sdim // value 223343181Sdim if (src_len > reg_info->byte_size) 224343181Sdim src_len = reg_info->byte_size; 225343181Sdim 226343181Sdim // Zero out the value in case we get partial data... 227343181Sdim memset(buffer.bytes, 0, sizeof(buffer.bytes)); 228343181Sdim 229343181Sdim type128 int128; 230343181Sdim 231343181Sdim m_type = eTypeInvalid; 232343181Sdim switch (reg_info->encoding) { 233343181Sdim case eEncodingInvalid: 234343181Sdim break; 235343181Sdim case eEncodingUint: 236343181Sdim case eEncodingSint: 237343181Sdim if (reg_info->byte_size == 1) 238343181Sdim SetUInt8(src.GetMaxU32(&src_offset, src_len)); 239343181Sdim else if (reg_info->byte_size <= 2) 240343181Sdim SetUInt16(src.GetMaxU32(&src_offset, src_len)); 241343181Sdim else if (reg_info->byte_size <= 4) 242343181Sdim SetUInt32(src.GetMaxU32(&src_offset, src_len)); 243343181Sdim else if (reg_info->byte_size <= 8) 244343181Sdim SetUInt64(src.GetMaxU64(&src_offset, src_len)); 245343181Sdim else if (reg_info->byte_size <= 16) { 246343181Sdim uint64_t data1 = src.GetU64(&src_offset); 247343181Sdim uint64_t data2 = src.GetU64(&src_offset); 248343181Sdim if (src.GetByteSize() == eByteOrderBig) { 249343181Sdim int128.x[0] = data1; 250343181Sdim int128.x[1] = data2; 251343181Sdim } else { 252343181Sdim int128.x[0] = data2; 253343181Sdim int128.x[1] = data1; 254343181Sdim } 255343181Sdim SetUInt128(llvm::APInt(128, 2, int128.x)); 256343181Sdim } 257343181Sdim break; 258343181Sdim case eEncodingIEEE754: 259343181Sdim if (reg_info->byte_size == sizeof(float)) 260343181Sdim SetFloat(src.GetFloat(&src_offset)); 261343181Sdim else if (reg_info->byte_size == sizeof(double)) 262343181Sdim SetDouble(src.GetDouble(&src_offset)); 263343181Sdim else if (reg_info->byte_size == sizeof(long double)) 264343181Sdim SetLongDouble(src.GetLongDouble(&src_offset)); 265343181Sdim break; 266343181Sdim case eEncodingVector: { 267343181Sdim m_type = eTypeBytes; 268343181Sdim buffer.length = reg_info->byte_size; 269343181Sdim buffer.byte_order = src.GetByteOrder(); 270343181Sdim assert(buffer.length <= kMaxRegisterByteSize); 271343181Sdim if (buffer.length > kMaxRegisterByteSize) 272343181Sdim buffer.length = kMaxRegisterByteSize; 273343181Sdim if (src.CopyByteOrderedData( 274343181Sdim src_offset, // offset within "src" to start extracting data 275343181Sdim src_len, // src length 276343181Sdim buffer.bytes, // dst buffer 277343181Sdim buffer.length, // dst length 278343181Sdim buffer.byte_order) == 0) // dst byte order 279343181Sdim { 280343181Sdim error.SetErrorStringWithFormat( 281343181Sdim "failed to copy data for register write of %s", reg_info->name); 282343181Sdim return error; 283343181Sdim } 284343181Sdim } 285343181Sdim } 286343181Sdim 287343181Sdim if (m_type == eTypeInvalid) 288343181Sdim error.SetErrorStringWithFormat( 289343181Sdim "invalid register value type for register %s", reg_info->name); 290343181Sdim return error; 291343181Sdim} 292343181Sdim 293343181Sdim// Helper function for RegisterValue::SetValueFromString() 294343181Sdimstatic bool ParseVectorEncoding(const RegisterInfo *reg_info, 295343181Sdim llvm::StringRef vector_str, 296343181Sdim const uint32_t byte_size, 297343181Sdim RegisterValue *reg_value) { 298343181Sdim // Example: vector_str = "{0x2c 0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a 299343181Sdim // 0x2a 0x3e 0x84 0x4f 0x2a 0x3e}". 300343181Sdim vector_str = vector_str.trim(); 301343181Sdim vector_str.consume_front("{"); 302343181Sdim vector_str.consume_back("}"); 303343181Sdim vector_str = vector_str.trim(); 304343181Sdim 305343181Sdim char Sep = ' '; 306343181Sdim 307343181Sdim // The first split should give us: 308343181Sdim // ('0x2c', '0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a 0x2a 0x3e 0x84 0x4f 309343181Sdim // 0x2a 0x3e'). 310343181Sdim llvm::StringRef car; 311343181Sdim llvm::StringRef cdr = vector_str; 312343181Sdim std::tie(car, cdr) = vector_str.split(Sep); 313343181Sdim std::vector<uint8_t> bytes; 314343181Sdim unsigned byte = 0; 315343181Sdim 316343181Sdim // Using radix auto-sensing by passing 0 as the radix. Keep on processing the 317343181Sdim // vector elements as long as the parsing succeeds and the vector size is < 318343181Sdim // byte_size. 319343181Sdim while (!car.getAsInteger(0, byte) && bytes.size() < byte_size) { 320343181Sdim bytes.push_back(byte); 321343181Sdim std::tie(car, cdr) = cdr.split(Sep); 322343181Sdim } 323343181Sdim 324343181Sdim // Check for vector of exact byte_size elements. 325343181Sdim if (bytes.size() != byte_size) 326343181Sdim return false; 327343181Sdim 328343181Sdim reg_value->SetBytes(&(bytes.front()), byte_size, eByteOrderLittle); 329343181Sdim return true; 330343181Sdim} 331343181Sdim 332360784Sdimstatic bool UInt64ValueIsValidForByteSize(uint64_t uval64, 333360784Sdim size_t total_byte_size) { 334360784Sdim if (total_byte_size > 8) 335360784Sdim return false; 336360784Sdim 337360784Sdim if (total_byte_size == 8) 338360784Sdim return true; 339360784Sdim 340360784Sdim const uint64_t max = 341360784Sdim (static_cast<uint64_t>(1) << static_cast<uint64_t>(total_byte_size * 8)) - 342360784Sdim 1; 343360784Sdim return uval64 <= max; 344360784Sdim} 345360784Sdim 346360784Sdimstatic bool SInt64ValueIsValidForByteSize(int64_t sval64, 347360784Sdim size_t total_byte_size) { 348360784Sdim if (total_byte_size > 8) 349360784Sdim return false; 350360784Sdim 351360784Sdim if (total_byte_size == 8) 352360784Sdim return true; 353360784Sdim 354360784Sdim const int64_t max = (static_cast<int64_t>(1) 355360784Sdim << static_cast<uint64_t>(total_byte_size * 8 - 1)) - 356360784Sdim 1; 357360784Sdim const int64_t min = ~(max); 358360784Sdim return min <= sval64 && sval64 <= max; 359360784Sdim} 360360784Sdim 361343181SdimStatus RegisterValue::SetValueFromString(const RegisterInfo *reg_info, 362343181Sdim llvm::StringRef value_str) { 363343181Sdim Status error; 364343181Sdim if (reg_info == nullptr) { 365343181Sdim error.SetErrorString("Invalid register info argument."); 366343181Sdim return error; 367343181Sdim } 368343181Sdim 369343181Sdim m_type = eTypeInvalid; 370343181Sdim if (value_str.empty()) { 371343181Sdim error.SetErrorString("Invalid c-string value string."); 372343181Sdim return error; 373343181Sdim } 374343181Sdim const uint32_t byte_size = reg_info->byte_size; 375343181Sdim 376343181Sdim uint64_t uval64; 377343181Sdim int64_t ival64; 378343181Sdim float flt_val; 379343181Sdim double dbl_val; 380343181Sdim long double ldbl_val; 381343181Sdim switch (reg_info->encoding) { 382343181Sdim case eEncodingInvalid: 383343181Sdim error.SetErrorString("Invalid encoding."); 384343181Sdim break; 385343181Sdim 386343181Sdim case eEncodingUint: 387343181Sdim if (byte_size > sizeof(uint64_t)) { 388343181Sdim error.SetErrorStringWithFormat( 389343181Sdim "unsupported unsigned integer byte size: %u", byte_size); 390343181Sdim break; 391343181Sdim } 392343181Sdim if (value_str.getAsInteger(0, uval64)) { 393343181Sdim error.SetErrorStringWithFormat( 394343181Sdim "'%s' is not a valid unsigned integer string value", 395343181Sdim value_str.str().c_str()); 396343181Sdim break; 397343181Sdim } 398343181Sdim 399360784Sdim if (!UInt64ValueIsValidForByteSize(uval64, byte_size)) { 400343181Sdim error.SetErrorStringWithFormat( 401343181Sdim "value 0x%" PRIx64 402343181Sdim " is too large to fit in a %u byte unsigned integer value", 403343181Sdim uval64, byte_size); 404343181Sdim break; 405343181Sdim } 406343181Sdim 407343181Sdim if (!SetUInt(uval64, reg_info->byte_size)) { 408343181Sdim error.SetErrorStringWithFormat( 409343181Sdim "unsupported unsigned integer byte size: %u", byte_size); 410343181Sdim break; 411343181Sdim } 412343181Sdim break; 413343181Sdim 414343181Sdim case eEncodingSint: 415343181Sdim if (byte_size > sizeof(long long)) { 416343181Sdim error.SetErrorStringWithFormat("unsupported signed integer byte size: %u", 417343181Sdim byte_size); 418343181Sdim break; 419343181Sdim } 420343181Sdim 421343181Sdim if (value_str.getAsInteger(0, ival64)) { 422343181Sdim error.SetErrorStringWithFormat( 423343181Sdim "'%s' is not a valid signed integer string value", 424343181Sdim value_str.str().c_str()); 425343181Sdim break; 426343181Sdim } 427343181Sdim 428360784Sdim if (!SInt64ValueIsValidForByteSize(ival64, byte_size)) { 429343181Sdim error.SetErrorStringWithFormat( 430343181Sdim "value 0x%" PRIx64 431343181Sdim " is too large to fit in a %u byte signed integer value", 432343181Sdim ival64, byte_size); 433343181Sdim break; 434343181Sdim } 435343181Sdim 436343181Sdim if (!SetUInt(ival64, reg_info->byte_size)) { 437343181Sdim error.SetErrorStringWithFormat("unsupported signed integer byte size: %u", 438343181Sdim byte_size); 439343181Sdim break; 440343181Sdim } 441343181Sdim break; 442343181Sdim 443343181Sdim case eEncodingIEEE754: { 444343181Sdim std::string value_string = value_str; 445343181Sdim if (byte_size == sizeof(float)) { 446343181Sdim if (::sscanf(value_string.c_str(), "%f", &flt_val) != 1) { 447343181Sdim error.SetErrorStringWithFormat("'%s' is not a valid float string value", 448343181Sdim value_string.c_str()); 449343181Sdim break; 450343181Sdim } 451343181Sdim m_scalar = flt_val; 452343181Sdim m_type = eTypeFloat; 453343181Sdim } else if (byte_size == sizeof(double)) { 454343181Sdim if (::sscanf(value_string.c_str(), "%lf", &dbl_val) != 1) { 455343181Sdim error.SetErrorStringWithFormat("'%s' is not a valid float string value", 456343181Sdim value_string.c_str()); 457343181Sdim break; 458343181Sdim } 459343181Sdim m_scalar = dbl_val; 460343181Sdim m_type = eTypeDouble; 461343181Sdim } else if (byte_size == sizeof(long double)) { 462343181Sdim if (::sscanf(value_string.c_str(), "%Lf", &ldbl_val) != 1) { 463343181Sdim error.SetErrorStringWithFormat("'%s' is not a valid float string value", 464343181Sdim value_string.c_str()); 465343181Sdim break; 466343181Sdim } 467343181Sdim m_scalar = ldbl_val; 468343181Sdim m_type = eTypeLongDouble; 469343181Sdim } else { 470343181Sdim error.SetErrorStringWithFormat("unsupported float byte size: %u", 471343181Sdim byte_size); 472343181Sdim return error; 473343181Sdim } 474343181Sdim break; 475343181Sdim } 476343181Sdim case eEncodingVector: 477343181Sdim if (!ParseVectorEncoding(reg_info, value_str, byte_size, this)) 478343181Sdim error.SetErrorString("unrecognized vector encoding string value."); 479343181Sdim break; 480343181Sdim } 481343181Sdim 482343181Sdim return error; 483343181Sdim} 484343181Sdim 485343181Sdimbool RegisterValue::SignExtend(uint32_t sign_bitpos) { 486343181Sdim switch (m_type) { 487343181Sdim case eTypeInvalid: 488343181Sdim break; 489343181Sdim 490343181Sdim case eTypeUInt8: 491343181Sdim case eTypeUInt16: 492343181Sdim case eTypeUInt32: 493343181Sdim case eTypeUInt64: 494343181Sdim case eTypeUInt128: 495343181Sdim return m_scalar.SignExtend(sign_bitpos); 496343181Sdim case eTypeFloat: 497343181Sdim case eTypeDouble: 498343181Sdim case eTypeLongDouble: 499343181Sdim case eTypeBytes: 500343181Sdim break; 501343181Sdim } 502343181Sdim return false; 503343181Sdim} 504343181Sdim 505343181Sdimbool RegisterValue::CopyValue(const RegisterValue &rhs) { 506343181Sdim if (this == &rhs) 507343181Sdim return rhs.m_type != eTypeInvalid; 508343181Sdim 509343181Sdim m_type = rhs.m_type; 510343181Sdim switch (m_type) { 511343181Sdim case eTypeInvalid: 512343181Sdim return false; 513343181Sdim case eTypeUInt8: 514343181Sdim case eTypeUInt16: 515343181Sdim case eTypeUInt32: 516343181Sdim case eTypeUInt64: 517343181Sdim case eTypeUInt128: 518343181Sdim case eTypeFloat: 519343181Sdim case eTypeDouble: 520343181Sdim case eTypeLongDouble: 521343181Sdim m_scalar = rhs.m_scalar; 522343181Sdim break; 523343181Sdim case eTypeBytes: 524343181Sdim assert(rhs.buffer.length <= kMaxRegisterByteSize); 525343181Sdim ::memcpy(buffer.bytes, rhs.buffer.bytes, kMaxRegisterByteSize); 526343181Sdim buffer.length = rhs.buffer.length; 527343181Sdim buffer.byte_order = rhs.buffer.byte_order; 528343181Sdim break; 529343181Sdim } 530343181Sdim return true; 531343181Sdim} 532343181Sdim 533343181Sdimuint16_t RegisterValue::GetAsUInt16(uint16_t fail_value, 534343181Sdim bool *success_ptr) const { 535343181Sdim if (success_ptr) 536343181Sdim *success_ptr = true; 537343181Sdim 538343181Sdim switch (m_type) { 539343181Sdim default: 540343181Sdim break; 541343181Sdim case eTypeUInt8: 542343181Sdim case eTypeUInt16: 543343181Sdim return m_scalar.UShort(fail_value); 544343181Sdim case eTypeBytes: { 545343181Sdim switch (buffer.length) { 546343181Sdim default: 547343181Sdim break; 548343181Sdim case 1: 549343181Sdim case 2: 550353358Sdim return *reinterpret_cast<const uint16_t *>(buffer.bytes); 551343181Sdim } 552343181Sdim } break; 553343181Sdim } 554343181Sdim if (success_ptr) 555343181Sdim *success_ptr = false; 556343181Sdim return fail_value; 557343181Sdim} 558343181Sdim 559343181Sdimuint32_t RegisterValue::GetAsUInt32(uint32_t fail_value, 560343181Sdim bool *success_ptr) const { 561343181Sdim if (success_ptr) 562343181Sdim *success_ptr = true; 563343181Sdim switch (m_type) { 564343181Sdim default: 565343181Sdim break; 566343181Sdim case eTypeUInt8: 567343181Sdim case eTypeUInt16: 568343181Sdim case eTypeUInt32: 569343181Sdim case eTypeFloat: 570343181Sdim case eTypeDouble: 571343181Sdim case eTypeLongDouble: 572343181Sdim return m_scalar.UInt(fail_value); 573343181Sdim case eTypeBytes: { 574343181Sdim switch (buffer.length) { 575343181Sdim default: 576343181Sdim break; 577343181Sdim case 1: 578343181Sdim case 2: 579343181Sdim case 4: 580353358Sdim return *reinterpret_cast<const uint32_t *>(buffer.bytes); 581343181Sdim } 582343181Sdim } break; 583343181Sdim } 584343181Sdim if (success_ptr) 585343181Sdim *success_ptr = false; 586343181Sdim return fail_value; 587343181Sdim} 588343181Sdim 589343181Sdimuint64_t RegisterValue::GetAsUInt64(uint64_t fail_value, 590343181Sdim bool *success_ptr) const { 591343181Sdim if (success_ptr) 592343181Sdim *success_ptr = true; 593343181Sdim switch (m_type) { 594343181Sdim default: 595343181Sdim break; 596343181Sdim case eTypeUInt8: 597343181Sdim case eTypeUInt16: 598343181Sdim case eTypeUInt32: 599343181Sdim case eTypeUInt64: 600343181Sdim case eTypeFloat: 601343181Sdim case eTypeDouble: 602343181Sdim case eTypeLongDouble: 603343181Sdim return m_scalar.ULongLong(fail_value); 604343181Sdim case eTypeBytes: { 605343181Sdim switch (buffer.length) { 606343181Sdim default: 607343181Sdim break; 608343181Sdim case 1: 609343181Sdim return *(const uint8_t *)buffer.bytes; 610343181Sdim case 2: 611353358Sdim return *reinterpret_cast<const uint16_t *>(buffer.bytes); 612343181Sdim case 4: 613353358Sdim return *reinterpret_cast<const uint32_t *>(buffer.bytes); 614343181Sdim case 8: 615353358Sdim return *reinterpret_cast<const uint64_t *>(buffer.bytes); 616343181Sdim } 617343181Sdim } break; 618343181Sdim } 619343181Sdim if (success_ptr) 620343181Sdim *success_ptr = false; 621343181Sdim return fail_value; 622343181Sdim} 623343181Sdim 624343181Sdimllvm::APInt RegisterValue::GetAsUInt128(const llvm::APInt &fail_value, 625343181Sdim bool *success_ptr) const { 626343181Sdim if (success_ptr) 627343181Sdim *success_ptr = true; 628343181Sdim switch (m_type) { 629343181Sdim default: 630343181Sdim break; 631343181Sdim case eTypeUInt8: 632343181Sdim case eTypeUInt16: 633343181Sdim case eTypeUInt32: 634343181Sdim case eTypeUInt64: 635343181Sdim case eTypeUInt128: 636343181Sdim case eTypeFloat: 637343181Sdim case eTypeDouble: 638343181Sdim case eTypeLongDouble: 639343181Sdim return m_scalar.UInt128(fail_value); 640343181Sdim case eTypeBytes: { 641343181Sdim switch (buffer.length) { 642343181Sdim default: 643343181Sdim break; 644343181Sdim case 1: 645343181Sdim case 2: 646343181Sdim case 4: 647343181Sdim case 8: 648343181Sdim case 16: 649343181Sdim return llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, 650353358Sdim (reinterpret_cast<const type128 *>(buffer.bytes))->x); 651343181Sdim } 652343181Sdim } break; 653343181Sdim } 654343181Sdim if (success_ptr) 655343181Sdim *success_ptr = false; 656343181Sdim return fail_value; 657343181Sdim} 658343181Sdim 659343181Sdimfloat RegisterValue::GetAsFloat(float fail_value, bool *success_ptr) const { 660343181Sdim if (success_ptr) 661343181Sdim *success_ptr = true; 662343181Sdim switch (m_type) { 663343181Sdim default: 664343181Sdim break; 665343181Sdim case eTypeUInt32: 666343181Sdim case eTypeUInt64: 667343181Sdim case eTypeUInt128: 668343181Sdim case eTypeFloat: 669343181Sdim case eTypeDouble: 670343181Sdim case eTypeLongDouble: 671343181Sdim return m_scalar.Float(fail_value); 672343181Sdim } 673343181Sdim if (success_ptr) 674343181Sdim *success_ptr = false; 675343181Sdim return fail_value; 676343181Sdim} 677343181Sdim 678343181Sdimdouble RegisterValue::GetAsDouble(double fail_value, bool *success_ptr) const { 679343181Sdim if (success_ptr) 680343181Sdim *success_ptr = true; 681343181Sdim switch (m_type) { 682343181Sdim default: 683343181Sdim break; 684343181Sdim 685343181Sdim case eTypeUInt32: 686343181Sdim case eTypeUInt64: 687343181Sdim case eTypeUInt128: 688343181Sdim case eTypeFloat: 689343181Sdim case eTypeDouble: 690343181Sdim case eTypeLongDouble: 691343181Sdim return m_scalar.Double(fail_value); 692343181Sdim } 693343181Sdim if (success_ptr) 694343181Sdim *success_ptr = false; 695343181Sdim return fail_value; 696343181Sdim} 697343181Sdim 698343181Sdimlong double RegisterValue::GetAsLongDouble(long double fail_value, 699343181Sdim bool *success_ptr) const { 700343181Sdim if (success_ptr) 701343181Sdim *success_ptr = true; 702343181Sdim switch (m_type) { 703343181Sdim default: 704343181Sdim break; 705343181Sdim 706343181Sdim case eTypeUInt32: 707343181Sdim case eTypeUInt64: 708343181Sdim case eTypeUInt128: 709343181Sdim case eTypeFloat: 710343181Sdim case eTypeDouble: 711343181Sdim case eTypeLongDouble: 712343181Sdim return m_scalar.LongDouble(); 713343181Sdim } 714343181Sdim if (success_ptr) 715343181Sdim *success_ptr = false; 716343181Sdim return fail_value; 717343181Sdim} 718343181Sdim 719343181Sdimconst void *RegisterValue::GetBytes() const { 720343181Sdim switch (m_type) { 721343181Sdim case eTypeInvalid: 722343181Sdim break; 723343181Sdim case eTypeUInt8: 724343181Sdim case eTypeUInt16: 725343181Sdim case eTypeUInt32: 726343181Sdim case eTypeUInt64: 727343181Sdim case eTypeUInt128: 728343181Sdim case eTypeFloat: 729343181Sdim case eTypeDouble: 730343181Sdim case eTypeLongDouble: 731343181Sdim return m_scalar.GetBytes(); 732343181Sdim case eTypeBytes: 733343181Sdim return buffer.bytes; 734343181Sdim } 735343181Sdim return nullptr; 736343181Sdim} 737343181Sdim 738343181Sdimuint32_t RegisterValue::GetByteSize() const { 739343181Sdim switch (m_type) { 740343181Sdim case eTypeInvalid: 741343181Sdim break; 742343181Sdim case eTypeUInt8: 743343181Sdim return 1; 744343181Sdim case eTypeUInt16: 745343181Sdim return 2; 746343181Sdim case eTypeUInt32: 747343181Sdim case eTypeUInt64: 748343181Sdim case eTypeUInt128: 749343181Sdim case eTypeFloat: 750343181Sdim case eTypeDouble: 751343181Sdim case eTypeLongDouble: 752343181Sdim return m_scalar.GetByteSize(); 753343181Sdim case eTypeBytes: 754343181Sdim return buffer.length; 755343181Sdim } 756343181Sdim return 0; 757343181Sdim} 758343181Sdim 759343181Sdimbool RegisterValue::SetUInt(uint64_t uint, uint32_t byte_size) { 760343181Sdim if (byte_size == 0) { 761343181Sdim SetUInt64(uint); 762343181Sdim } else if (byte_size == 1) { 763343181Sdim SetUInt8(uint); 764343181Sdim } else if (byte_size <= 2) { 765343181Sdim SetUInt16(uint); 766343181Sdim } else if (byte_size <= 4) { 767343181Sdim SetUInt32(uint); 768343181Sdim } else if (byte_size <= 8) { 769343181Sdim SetUInt64(uint); 770343181Sdim } else if (byte_size <= 16) { 771343181Sdim SetUInt128(llvm::APInt(128, uint)); 772343181Sdim } else 773343181Sdim return false; 774343181Sdim return true; 775343181Sdim} 776343181Sdim 777343181Sdimvoid RegisterValue::SetBytes(const void *bytes, size_t length, 778343181Sdim lldb::ByteOrder byte_order) { 779343181Sdim // If this assertion fires off we need to increase the size of buffer.bytes, 780343181Sdim // or make it something that is allocated on the heap. Since the data buffer 781343181Sdim // is in a union, we can't make it a collection class like SmallVector... 782343181Sdim if (bytes && length > 0) { 783343181Sdim assert(length <= sizeof(buffer.bytes) && 784343181Sdim "Storing too many bytes in a RegisterValue."); 785343181Sdim m_type = eTypeBytes; 786343181Sdim buffer.length = length; 787343181Sdim memcpy(buffer.bytes, bytes, length); 788343181Sdim buffer.byte_order = byte_order; 789343181Sdim } else { 790343181Sdim m_type = eTypeInvalid; 791343181Sdim buffer.length = 0; 792343181Sdim } 793343181Sdim} 794343181Sdim 795343181Sdimbool RegisterValue::operator==(const RegisterValue &rhs) const { 796343181Sdim if (m_type == rhs.m_type) { 797343181Sdim switch (m_type) { 798343181Sdim case eTypeInvalid: 799343181Sdim return true; 800343181Sdim case eTypeUInt8: 801343181Sdim case eTypeUInt16: 802343181Sdim case eTypeUInt32: 803343181Sdim case eTypeUInt64: 804343181Sdim case eTypeUInt128: 805343181Sdim case eTypeFloat: 806343181Sdim case eTypeDouble: 807343181Sdim case eTypeLongDouble: 808343181Sdim return m_scalar == rhs.m_scalar; 809343181Sdim case eTypeBytes: 810343181Sdim if (buffer.length != rhs.buffer.length) 811343181Sdim return false; 812343181Sdim else { 813343181Sdim uint8_t length = buffer.length; 814343181Sdim if (length > kMaxRegisterByteSize) 815343181Sdim length = kMaxRegisterByteSize; 816343181Sdim return memcmp(buffer.bytes, rhs.buffer.bytes, length) == 0; 817343181Sdim } 818343181Sdim break; 819343181Sdim } 820343181Sdim } 821343181Sdim return false; 822343181Sdim} 823343181Sdim 824343181Sdimbool RegisterValue::operator!=(const RegisterValue &rhs) const { 825343181Sdim return !(*this == rhs); 826343181Sdim} 827343181Sdim 828343181Sdimbool RegisterValue::ClearBit(uint32_t bit) { 829343181Sdim switch (m_type) { 830343181Sdim case eTypeInvalid: 831343181Sdim break; 832343181Sdim 833343181Sdim case eTypeUInt8: 834343181Sdim case eTypeUInt16: 835343181Sdim case eTypeUInt32: 836343181Sdim case eTypeUInt64: 837343181Sdim case eTypeUInt128: 838343181Sdim if (bit < (GetByteSize() * 8)) { 839343181Sdim return m_scalar.ClearBit(bit); 840343181Sdim } 841343181Sdim break; 842343181Sdim 843343181Sdim case eTypeFloat: 844343181Sdim case eTypeDouble: 845343181Sdim case eTypeLongDouble: 846343181Sdim break; 847343181Sdim 848343181Sdim case eTypeBytes: 849343181Sdim if (buffer.byte_order == eByteOrderBig || 850343181Sdim buffer.byte_order == eByteOrderLittle) { 851343181Sdim uint32_t byte_idx; 852343181Sdim if (buffer.byte_order == eByteOrderBig) 853343181Sdim byte_idx = buffer.length - (bit / 8) - 1; 854343181Sdim else 855343181Sdim byte_idx = bit / 8; 856343181Sdim 857343181Sdim const uint32_t byte_bit = bit % 8; 858343181Sdim if (byte_idx < buffer.length) { 859343181Sdim buffer.bytes[byte_idx] &= ~(1u << byte_bit); 860343181Sdim return true; 861343181Sdim } 862343181Sdim } 863343181Sdim break; 864343181Sdim } 865343181Sdim return false; 866343181Sdim} 867343181Sdim 868343181Sdimbool RegisterValue::SetBit(uint32_t bit) { 869343181Sdim switch (m_type) { 870343181Sdim case eTypeInvalid: 871343181Sdim break; 872343181Sdim 873343181Sdim case eTypeUInt8: 874343181Sdim case eTypeUInt16: 875343181Sdim case eTypeUInt32: 876343181Sdim case eTypeUInt64: 877343181Sdim case eTypeUInt128: 878343181Sdim if (bit < (GetByteSize() * 8)) { 879343181Sdim return m_scalar.SetBit(bit); 880343181Sdim } 881343181Sdim break; 882343181Sdim 883343181Sdim case eTypeFloat: 884343181Sdim case eTypeDouble: 885343181Sdim case eTypeLongDouble: 886343181Sdim break; 887343181Sdim 888343181Sdim case eTypeBytes: 889343181Sdim if (buffer.byte_order == eByteOrderBig || 890343181Sdim buffer.byte_order == eByteOrderLittle) { 891343181Sdim uint32_t byte_idx; 892343181Sdim if (buffer.byte_order == eByteOrderBig) 893343181Sdim byte_idx = buffer.length - (bit / 8) - 1; 894343181Sdim else 895343181Sdim byte_idx = bit / 8; 896343181Sdim 897343181Sdim const uint32_t byte_bit = bit % 8; 898343181Sdim if (byte_idx < buffer.length) { 899343181Sdim buffer.bytes[byte_idx] |= (1u << byte_bit); 900343181Sdim return true; 901343181Sdim } 902343181Sdim } 903343181Sdim break; 904343181Sdim } 905343181Sdim return false; 906343181Sdim} 907