1 //===-- RegisterValue.cpp -------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Utility/RegisterValue.h" 10 11 #include "lldb/Utility/DataExtractor.h" 12 #include "lldb/Utility/Scalar.h" 13 #include "lldb/Utility/Status.h" 14 #include "lldb/Utility/Stream.h" 15 #include "lldb/Utility/StreamString.h" 16 #include "lldb/lldb-defines.h" 17 #include "lldb/lldb-private-types.h" 18 19 #include "llvm/ADT/ArrayRef.h" 20 #include "llvm/ADT/StringRef.h" 21 22 #include <cstdint> 23 #include <string> 24 #include <tuple> 25 #include <vector> 26 27 #include <cassert> 28 #include <cinttypes> 29 #include <cstdio> 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 bool RegisterValue::GetData(DataExtractor &data) const { 35 return data.SetData(GetBytes(), GetByteSize(), GetByteOrder()) > 0; 36 } 37 38 uint32_t RegisterValue::GetAsMemoryData(const RegisterInfo ®_info, void *dst, 39 uint32_t dst_len, 40 lldb::ByteOrder dst_byte_order, 41 Status &error) const { 42 // ReadRegister should have already been called on this object prior to 43 // calling this. 44 if (GetType() == eTypeInvalid) { 45 // No value has been read into this object... 46 error.SetErrorStringWithFormat( 47 "invalid register value type for register %s", reg_info.name); 48 return 0; 49 } 50 51 if (dst_len > kMaxRegisterByteSize) { 52 error.SetErrorString("destination is too big"); 53 return 0; 54 } 55 56 const uint32_t src_len = reg_info.byte_size; 57 58 // Extract the register data into a data extractor 59 DataExtractor reg_data; 60 if (!GetData(reg_data)) { 61 error.SetErrorString("invalid register value to copy into"); 62 return 0; 63 } 64 65 // Prepare a memory buffer that contains some or all of the register value 66 const uint32_t bytes_copied = 67 reg_data.CopyByteOrderedData(0, // src offset 68 src_len, // src length 69 dst, // dst buffer 70 dst_len, // dst length 71 dst_byte_order); // dst byte order 72 if (bytes_copied == 0) 73 error.SetErrorStringWithFormat( 74 "failed to copy data for register write of %s", reg_info.name); 75 76 return bytes_copied; 77 } 78 79 uint32_t RegisterValue::SetFromMemoryData(const RegisterInfo ®_info, 80 const void *src, uint32_t src_len, 81 lldb::ByteOrder src_byte_order, 82 Status &error) { 83 // Moving from addr into a register 84 // 85 // Case 1: src_len == dst_len 86 // 87 // |AABBCCDD| Address contents 88 // |AABBCCDD| Register contents 89 // 90 // Case 2: src_len > dst_len 91 // 92 // Status! (The register should always be big enough to hold the data) 93 // 94 // Case 3: src_len < dst_len 95 // 96 // |AABB| Address contents 97 // |AABB0000| Register contents [on little-endian hardware] 98 // |0000AABB| Register contents [on big-endian hardware] 99 if (src_len > kMaxRegisterByteSize) { 100 error.SetErrorStringWithFormat( 101 "register buffer is too small to receive %u bytes of data.", src_len); 102 return 0; 103 } 104 105 const uint32_t dst_len = reg_info.byte_size; 106 107 if (src_len > dst_len) { 108 error.SetErrorStringWithFormat( 109 "%u bytes is too big to store in register %s (%u bytes)", src_len, 110 reg_info.name, dst_len); 111 return 0; 112 } 113 114 // Use a data extractor to correctly copy and pad the bytes read into the 115 // register value 116 DataExtractor src_data(src, src_len, src_byte_order, 4); 117 118 error = SetValueFromData(reg_info, src_data, 0, true); 119 if (error.Fail()) 120 return 0; 121 122 // If SetValueFromData succeeded, we must have copied all of src_len 123 return src_len; 124 } 125 126 bool RegisterValue::GetScalarValue(Scalar &scalar) const { 127 switch (m_type) { 128 case eTypeInvalid: 129 break; 130 case eTypeBytes: { 131 DataExtractor data(buffer.bytes, buffer.length, buffer.byte_order, 1); 132 if (scalar.SetValueFromData(data, lldb::eEncodingUint, 133 buffer.length).Success()) 134 return true; 135 } break; 136 case eTypeUInt8: 137 case eTypeUInt16: 138 case eTypeUInt32: 139 case eTypeUInt64: 140 case eTypeUInt128: 141 case eTypeFloat: 142 case eTypeDouble: 143 case eTypeLongDouble: 144 scalar = m_scalar; 145 return true; 146 } 147 return false; 148 } 149 150 void RegisterValue::Clear() { m_type = eTypeInvalid; } 151 152 RegisterValue::Type RegisterValue::SetType(const RegisterInfo ®_info) { 153 // To change the type, we simply copy the data in again, using the new format 154 RegisterValue copy; 155 DataExtractor copy_data; 156 if (copy.CopyValue(*this) && copy.GetData(copy_data)) { 157 Status error = SetValueFromData(reg_info, copy_data, 0, true); 158 assert(error.Success() && "Expected SetValueFromData to succeed."); 159 UNUSED_IF_ASSERT_DISABLED(error); 160 } 161 162 return m_type; 163 } 164 165 Status RegisterValue::SetValueFromData(const RegisterInfo ®_info, 166 DataExtractor &src, 167 lldb::offset_t src_offset, 168 bool partial_data_ok) { 169 Status error; 170 171 if (src.GetByteSize() == 0) { 172 error.SetErrorString("empty data."); 173 return error; 174 } 175 176 if (reg_info.byte_size == 0) { 177 error.SetErrorString("invalid register info."); 178 return error; 179 } 180 181 uint32_t src_len = src.GetByteSize() - src_offset; 182 183 if (!partial_data_ok && (src_len < reg_info.byte_size)) { 184 error.SetErrorString("not enough data."); 185 return error; 186 } 187 188 // Cap the data length if there is more than enough bytes for this register 189 // value 190 if (src_len > reg_info.byte_size) 191 src_len = reg_info.byte_size; 192 193 // Zero out the value in case we get partial data... 194 memset(buffer.bytes, 0, sizeof(buffer.bytes)); 195 196 type128 int128; 197 198 m_type = eTypeInvalid; 199 switch (reg_info.encoding) { 200 case eEncodingInvalid: 201 break; 202 case eEncodingUint: 203 case eEncodingSint: 204 if (reg_info.byte_size == 1) 205 SetUInt8(src.GetMaxU32(&src_offset, src_len)); 206 else if (reg_info.byte_size <= 2) 207 SetUInt16(src.GetMaxU32(&src_offset, src_len)); 208 else if (reg_info.byte_size <= 4) 209 SetUInt32(src.GetMaxU32(&src_offset, src_len)); 210 else if (reg_info.byte_size <= 8) 211 SetUInt64(src.GetMaxU64(&src_offset, src_len)); 212 else if (reg_info.byte_size <= 16) { 213 uint64_t data1 = src.GetU64(&src_offset); 214 uint64_t data2 = src.GetU64(&src_offset); 215 if (src.GetByteSize() == eByteOrderBig) { 216 int128.x[0] = data1; 217 int128.x[1] = data2; 218 } else { 219 int128.x[0] = data2; 220 int128.x[1] = data1; 221 } 222 SetUInt128(llvm::APInt(128, 2, int128.x)); 223 } 224 break; 225 case eEncodingIEEE754: 226 if (reg_info.byte_size == sizeof(float)) 227 SetFloat(src.GetFloat(&src_offset)); 228 else if (reg_info.byte_size == sizeof(double)) 229 SetDouble(src.GetDouble(&src_offset)); 230 else if (reg_info.byte_size == sizeof(long double)) 231 SetLongDouble(src.GetLongDouble(&src_offset)); 232 break; 233 case eEncodingVector: { 234 m_type = eTypeBytes; 235 buffer.length = reg_info.byte_size; 236 buffer.byte_order = src.GetByteOrder(); 237 assert(buffer.length <= kMaxRegisterByteSize); 238 if (buffer.length > kMaxRegisterByteSize) 239 buffer.length = kMaxRegisterByteSize; 240 if (src.CopyByteOrderedData( 241 src_offset, // offset within "src" to start extracting data 242 src_len, // src length 243 buffer.bytes, // dst buffer 244 buffer.length, // dst length 245 buffer.byte_order) == 0) // dst byte order 246 { 247 error.SetErrorStringWithFormat( 248 "failed to copy data for register write of %s", reg_info.name); 249 return error; 250 } 251 } 252 } 253 254 if (m_type == eTypeInvalid) 255 error.SetErrorStringWithFormat( 256 "invalid register value type for register %s", reg_info.name); 257 return error; 258 } 259 260 // Helper function for RegisterValue::SetValueFromString() 261 static bool ParseVectorEncoding(const RegisterInfo *reg_info, 262 llvm::StringRef vector_str, 263 const uint32_t byte_size, 264 RegisterValue *reg_value) { 265 // Example: vector_str = "{0x2c 0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a 266 // 0x2a 0x3e 0x84 0x4f 0x2a 0x3e}". 267 vector_str = vector_str.trim(); 268 vector_str.consume_front("{"); 269 vector_str.consume_back("}"); 270 vector_str = vector_str.trim(); 271 272 char Sep = ' '; 273 274 // The first split should give us: 275 // ('0x2c', '0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a 0x2a 0x3e 0x84 0x4f 276 // 0x2a 0x3e'). 277 llvm::StringRef car; 278 llvm::StringRef cdr = vector_str; 279 std::tie(car, cdr) = vector_str.split(Sep); 280 std::vector<uint8_t> bytes; 281 unsigned byte = 0; 282 283 // Using radix auto-sensing by passing 0 as the radix. Keep on processing the 284 // vector elements as long as the parsing succeeds and the vector size is < 285 // byte_size. 286 while (!car.getAsInteger(0, byte) && bytes.size() < byte_size) { 287 bytes.push_back(byte); 288 std::tie(car, cdr) = cdr.split(Sep); 289 } 290 291 // Check for vector of exact byte_size elements. 292 if (bytes.size() != byte_size) 293 return false; 294 295 reg_value->SetBytes(&(bytes.front()), byte_size, eByteOrderLittle); 296 return true; 297 } 298 299 static bool UInt64ValueIsValidForByteSize(uint64_t uval64, 300 size_t total_byte_size) { 301 if (total_byte_size > 8) 302 return false; 303 304 if (total_byte_size == 8) 305 return true; 306 307 const uint64_t max = 308 (static_cast<uint64_t>(1) << static_cast<uint64_t>(total_byte_size * 8)) - 309 1; 310 return uval64 <= max; 311 } 312 313 static bool SInt64ValueIsValidForByteSize(int64_t sval64, 314 size_t total_byte_size) { 315 if (total_byte_size > 8) 316 return false; 317 318 if (total_byte_size == 8) 319 return true; 320 321 const int64_t max = (static_cast<int64_t>(1) 322 << static_cast<uint64_t>(total_byte_size * 8 - 1)) - 323 1; 324 const int64_t min = ~(max); 325 return min <= sval64 && sval64 <= max; 326 } 327 328 Status RegisterValue::SetValueFromString(const RegisterInfo *reg_info, 329 llvm::StringRef value_str) { 330 Status error; 331 if (reg_info == nullptr) { 332 error.SetErrorString("Invalid register info argument."); 333 return error; 334 } 335 336 m_type = eTypeInvalid; 337 if (value_str.empty()) { 338 error.SetErrorString("Invalid c-string value string."); 339 return error; 340 } 341 const uint32_t byte_size = reg_info->byte_size; 342 343 uint64_t uval64; 344 int64_t ival64; 345 float flt_val; 346 double dbl_val; 347 long double ldbl_val; 348 switch (reg_info->encoding) { 349 case eEncodingInvalid: 350 error.SetErrorString("Invalid encoding."); 351 break; 352 353 case eEncodingUint: 354 if (byte_size > sizeof(uint64_t)) { 355 error.SetErrorStringWithFormat( 356 "unsupported unsigned integer byte size: %u", byte_size); 357 break; 358 } 359 if (value_str.getAsInteger(0, uval64)) { 360 error.SetErrorStringWithFormat( 361 "'%s' is not a valid unsigned integer string value", 362 value_str.str().c_str()); 363 break; 364 } 365 366 if (!UInt64ValueIsValidForByteSize(uval64, byte_size)) { 367 error.SetErrorStringWithFormat( 368 "value 0x%" PRIx64 369 " is too large to fit in a %u byte unsigned integer value", 370 uval64, byte_size); 371 break; 372 } 373 374 if (!SetUInt(uval64, reg_info->byte_size)) { 375 error.SetErrorStringWithFormat( 376 "unsupported unsigned integer byte size: %u", byte_size); 377 break; 378 } 379 break; 380 381 case eEncodingSint: 382 if (byte_size > sizeof(long long)) { 383 error.SetErrorStringWithFormat("unsupported signed integer byte size: %u", 384 byte_size); 385 break; 386 } 387 388 if (value_str.getAsInteger(0, ival64)) { 389 error.SetErrorStringWithFormat( 390 "'%s' is not a valid signed integer string value", 391 value_str.str().c_str()); 392 break; 393 } 394 395 if (!SInt64ValueIsValidForByteSize(ival64, byte_size)) { 396 error.SetErrorStringWithFormat( 397 "value 0x%" PRIx64 398 " is too large to fit in a %u byte signed integer value", 399 ival64, byte_size); 400 break; 401 } 402 403 if (!SetUInt(ival64, reg_info->byte_size)) { 404 error.SetErrorStringWithFormat("unsupported signed integer byte size: %u", 405 byte_size); 406 break; 407 } 408 break; 409 410 case eEncodingIEEE754: { 411 std::string value_string = std::string(value_str); 412 if (byte_size == sizeof(float)) { 413 if (::sscanf(value_string.c_str(), "%f", &flt_val) != 1) { 414 error.SetErrorStringWithFormat("'%s' is not a valid float string value", 415 value_string.c_str()); 416 break; 417 } 418 m_scalar = flt_val; 419 m_type = eTypeFloat; 420 } else if (byte_size == sizeof(double)) { 421 if (::sscanf(value_string.c_str(), "%lf", &dbl_val) != 1) { 422 error.SetErrorStringWithFormat("'%s' is not a valid float string value", 423 value_string.c_str()); 424 break; 425 } 426 m_scalar = dbl_val; 427 m_type = eTypeDouble; 428 } else if (byte_size == sizeof(long double)) { 429 if (::sscanf(value_string.c_str(), "%Lf", &ldbl_val) != 1) { 430 error.SetErrorStringWithFormat("'%s' is not a valid float string value", 431 value_string.c_str()); 432 break; 433 } 434 m_scalar = ldbl_val; 435 m_type = eTypeLongDouble; 436 } else { 437 error.SetErrorStringWithFormat("unsupported float byte size: %u", 438 byte_size); 439 return error; 440 } 441 break; 442 } 443 case eEncodingVector: 444 if (!ParseVectorEncoding(reg_info, value_str, byte_size, this)) 445 error.SetErrorString("unrecognized vector encoding string value."); 446 break; 447 } 448 449 return error; 450 } 451 452 bool RegisterValue::SignExtend(uint32_t sign_bitpos) { 453 switch (m_type) { 454 case eTypeInvalid: 455 break; 456 457 case eTypeUInt8: 458 case eTypeUInt16: 459 case eTypeUInt32: 460 case eTypeUInt64: 461 case eTypeUInt128: 462 return m_scalar.SignExtend(sign_bitpos); 463 case eTypeFloat: 464 case eTypeDouble: 465 case eTypeLongDouble: 466 case eTypeBytes: 467 break; 468 } 469 return false; 470 } 471 472 bool RegisterValue::CopyValue(const RegisterValue &rhs) { 473 if (this == &rhs) 474 return rhs.m_type != eTypeInvalid; 475 476 m_type = rhs.m_type; 477 switch (m_type) { 478 case eTypeInvalid: 479 return false; 480 case eTypeUInt8: 481 case eTypeUInt16: 482 case eTypeUInt32: 483 case eTypeUInt64: 484 case eTypeUInt128: 485 case eTypeFloat: 486 case eTypeDouble: 487 case eTypeLongDouble: 488 m_scalar = rhs.m_scalar; 489 break; 490 case eTypeBytes: 491 assert(rhs.buffer.length <= kMaxRegisterByteSize); 492 ::memcpy(buffer.bytes, rhs.buffer.bytes, kMaxRegisterByteSize); 493 buffer.length = rhs.buffer.length; 494 buffer.byte_order = rhs.buffer.byte_order; 495 break; 496 } 497 return true; 498 } 499 500 uint16_t RegisterValue::GetAsUInt16(uint16_t fail_value, 501 bool *success_ptr) const { 502 if (success_ptr) 503 *success_ptr = true; 504 505 switch (m_type) { 506 default: 507 break; 508 case eTypeUInt8: 509 case eTypeUInt16: 510 return m_scalar.UShort(fail_value); 511 case eTypeBytes: { 512 switch (buffer.length) { 513 default: 514 break; 515 case 1: 516 case 2: 517 return *reinterpret_cast<const uint16_t *>(buffer.bytes); 518 } 519 } break; 520 } 521 if (success_ptr) 522 *success_ptr = false; 523 return fail_value; 524 } 525 526 uint32_t RegisterValue::GetAsUInt32(uint32_t fail_value, 527 bool *success_ptr) const { 528 if (success_ptr) 529 *success_ptr = true; 530 switch (m_type) { 531 default: 532 break; 533 case eTypeUInt8: 534 case eTypeUInt16: 535 case eTypeUInt32: 536 case eTypeFloat: 537 case eTypeDouble: 538 case eTypeLongDouble: 539 return m_scalar.UInt(fail_value); 540 case eTypeBytes: { 541 switch (buffer.length) { 542 default: 543 break; 544 case 1: 545 case 2: 546 case 4: 547 return *reinterpret_cast<const uint32_t *>(buffer.bytes); 548 } 549 } break; 550 } 551 if (success_ptr) 552 *success_ptr = false; 553 return fail_value; 554 } 555 556 uint64_t RegisterValue::GetAsUInt64(uint64_t fail_value, 557 bool *success_ptr) const { 558 if (success_ptr) 559 *success_ptr = true; 560 switch (m_type) { 561 default: 562 break; 563 case eTypeUInt8: 564 case eTypeUInt16: 565 case eTypeUInt32: 566 case eTypeUInt64: 567 case eTypeFloat: 568 case eTypeDouble: 569 case eTypeLongDouble: 570 return m_scalar.ULongLong(fail_value); 571 case eTypeBytes: { 572 switch (buffer.length) { 573 default: 574 break; 575 case 1: 576 return *(const uint8_t *)buffer.bytes; 577 case 2: 578 return *reinterpret_cast<const uint16_t *>(buffer.bytes); 579 case 4: 580 return *reinterpret_cast<const uint32_t *>(buffer.bytes); 581 case 8: 582 return *reinterpret_cast<const uint64_t *>(buffer.bytes); 583 } 584 } break; 585 } 586 if (success_ptr) 587 *success_ptr = false; 588 return fail_value; 589 } 590 591 llvm::APInt RegisterValue::GetAsUInt128(const llvm::APInt &fail_value, 592 bool *success_ptr) const { 593 if (success_ptr) 594 *success_ptr = true; 595 switch (m_type) { 596 default: 597 break; 598 case eTypeUInt8: 599 case eTypeUInt16: 600 case eTypeUInt32: 601 case eTypeUInt64: 602 case eTypeUInt128: 603 case eTypeFloat: 604 case eTypeDouble: 605 case eTypeLongDouble: 606 return m_scalar.UInt128(fail_value); 607 case eTypeBytes: { 608 switch (buffer.length) { 609 default: 610 break; 611 case 1: 612 case 2: 613 case 4: 614 case 8: 615 case 16: 616 return llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, 617 (reinterpret_cast<const type128 *>(buffer.bytes))->x); 618 } 619 } break; 620 } 621 if (success_ptr) 622 *success_ptr = false; 623 return fail_value; 624 } 625 626 float RegisterValue::GetAsFloat(float fail_value, bool *success_ptr) const { 627 if (success_ptr) 628 *success_ptr = true; 629 switch (m_type) { 630 default: 631 break; 632 case eTypeUInt32: 633 case eTypeUInt64: 634 case eTypeUInt128: 635 case eTypeFloat: 636 case eTypeDouble: 637 case eTypeLongDouble: 638 return m_scalar.Float(fail_value); 639 } 640 if (success_ptr) 641 *success_ptr = false; 642 return fail_value; 643 } 644 645 double RegisterValue::GetAsDouble(double fail_value, bool *success_ptr) const { 646 if (success_ptr) 647 *success_ptr = true; 648 switch (m_type) { 649 default: 650 break; 651 652 case eTypeUInt32: 653 case eTypeUInt64: 654 case eTypeUInt128: 655 case eTypeFloat: 656 case eTypeDouble: 657 case eTypeLongDouble: 658 return m_scalar.Double(fail_value); 659 } 660 if (success_ptr) 661 *success_ptr = false; 662 return fail_value; 663 } 664 665 long double RegisterValue::GetAsLongDouble(long double fail_value, 666 bool *success_ptr) const { 667 if (success_ptr) 668 *success_ptr = true; 669 switch (m_type) { 670 default: 671 break; 672 673 case eTypeUInt32: 674 case eTypeUInt64: 675 case eTypeUInt128: 676 case eTypeFloat: 677 case eTypeDouble: 678 case eTypeLongDouble: 679 return m_scalar.LongDouble(); 680 } 681 if (success_ptr) 682 *success_ptr = false; 683 return fail_value; 684 } 685 686 const void *RegisterValue::GetBytes() const { 687 switch (m_type) { 688 case eTypeInvalid: 689 break; 690 case eTypeUInt8: 691 case eTypeUInt16: 692 case eTypeUInt32: 693 case eTypeUInt64: 694 case eTypeUInt128: 695 case eTypeFloat: 696 case eTypeDouble: 697 case eTypeLongDouble: 698 m_scalar.GetBytes(buffer.bytes); 699 return buffer.bytes; 700 case eTypeBytes: 701 return buffer.bytes; 702 } 703 return nullptr; 704 } 705 706 uint32_t RegisterValue::GetByteSize() const { 707 switch (m_type) { 708 case eTypeInvalid: 709 break; 710 case eTypeUInt8: 711 return 1; 712 case eTypeUInt16: 713 return 2; 714 case eTypeUInt32: 715 case eTypeUInt64: 716 case eTypeUInt128: 717 case eTypeFloat: 718 case eTypeDouble: 719 case eTypeLongDouble: 720 return m_scalar.GetByteSize(); 721 case eTypeBytes: 722 return buffer.length; 723 } 724 return 0; 725 } 726 727 bool RegisterValue::SetUInt(uint64_t uint, uint32_t byte_size) { 728 if (byte_size == 0) { 729 SetUInt64(uint); 730 } else if (byte_size == 1) { 731 SetUInt8(uint); 732 } else if (byte_size <= 2) { 733 SetUInt16(uint); 734 } else if (byte_size <= 4) { 735 SetUInt32(uint); 736 } else if (byte_size <= 8) { 737 SetUInt64(uint); 738 } else if (byte_size <= 16) { 739 SetUInt128(llvm::APInt(128, uint)); 740 } else 741 return false; 742 return true; 743 } 744 745 void RegisterValue::SetBytes(const void *bytes, size_t length, 746 lldb::ByteOrder byte_order) { 747 // If this assertion fires off we need to increase the size of buffer.bytes, 748 // or make it something that is allocated on the heap. Since the data buffer 749 // is in a union, we can't make it a collection class like SmallVector... 750 if (bytes && length > 0) { 751 assert(length <= sizeof(buffer.bytes) && 752 "Storing too many bytes in a RegisterValue."); 753 m_type = eTypeBytes; 754 buffer.length = length; 755 memcpy(buffer.bytes, bytes, length); 756 buffer.byte_order = byte_order; 757 } else { 758 m_type = eTypeInvalid; 759 buffer.length = 0; 760 } 761 } 762 763 bool RegisterValue::operator==(const RegisterValue &rhs) const { 764 if (m_type == rhs.m_type) { 765 switch (m_type) { 766 case eTypeInvalid: 767 return true; 768 case eTypeUInt8: 769 case eTypeUInt16: 770 case eTypeUInt32: 771 case eTypeUInt64: 772 case eTypeUInt128: 773 case eTypeFloat: 774 case eTypeDouble: 775 case eTypeLongDouble: 776 return m_scalar == rhs.m_scalar; 777 case eTypeBytes: 778 if (buffer.length != rhs.buffer.length) 779 return false; 780 else { 781 uint16_t length = buffer.length; 782 if (length > kMaxRegisterByteSize) 783 length = kMaxRegisterByteSize; 784 return memcmp(buffer.bytes, rhs.buffer.bytes, length) == 0; 785 } 786 break; 787 } 788 } 789 return false; 790 } 791 792 bool RegisterValue::operator!=(const RegisterValue &rhs) const { 793 return !(*this == rhs); 794 } 795 796 bool RegisterValue::ClearBit(uint32_t bit) { 797 switch (m_type) { 798 case eTypeInvalid: 799 break; 800 801 case eTypeUInt8: 802 case eTypeUInt16: 803 case eTypeUInt32: 804 case eTypeUInt64: 805 case eTypeUInt128: 806 if (bit < (GetByteSize() * 8)) { 807 return m_scalar.ClearBit(bit); 808 } 809 break; 810 811 case eTypeFloat: 812 case eTypeDouble: 813 case eTypeLongDouble: 814 break; 815 816 case eTypeBytes: 817 if (buffer.byte_order == eByteOrderBig || 818 buffer.byte_order == eByteOrderLittle) { 819 uint32_t byte_idx; 820 if (buffer.byte_order == eByteOrderBig) 821 byte_idx = buffer.length - (bit / 8) - 1; 822 else 823 byte_idx = bit / 8; 824 825 const uint32_t byte_bit = bit % 8; 826 if (byte_idx < buffer.length) { 827 buffer.bytes[byte_idx] &= ~(1u << byte_bit); 828 return true; 829 } 830 } 831 break; 832 } 833 return false; 834 } 835 836 bool RegisterValue::SetBit(uint32_t bit) { 837 switch (m_type) { 838 case eTypeInvalid: 839 break; 840 841 case eTypeUInt8: 842 case eTypeUInt16: 843 case eTypeUInt32: 844 case eTypeUInt64: 845 case eTypeUInt128: 846 if (bit < (GetByteSize() * 8)) { 847 return m_scalar.SetBit(bit); 848 } 849 break; 850 851 case eTypeFloat: 852 case eTypeDouble: 853 case eTypeLongDouble: 854 break; 855 856 case eTypeBytes: 857 if (buffer.byte_order == eByteOrderBig || 858 buffer.byte_order == eByteOrderLittle) { 859 uint32_t byte_idx; 860 if (buffer.byte_order == eByteOrderBig) 861 byte_idx = buffer.length - (bit / 8) - 1; 862 else 863 byte_idx = bit / 8; 864 865 const uint32_t byte_bit = bit % 8; 866 if (byte_idx < buffer.length) { 867 buffer.bytes[byte_idx] |= (1u << byte_bit); 868 return true; 869 } 870 } 871 break; 872 } 873 return false; 874 } 875