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