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 break; 384 385 case eEncodingSint: 386 if (byte_size > sizeof(long long)) { 387 error.SetErrorStringWithFormat("unsupported signed integer byte size: %u", 388 byte_size); 389 break; 390 } 391 392 if (value_str.getAsInteger(0, ival64)) { 393 error.SetErrorStringWithFormat( 394 "'%s' is not a valid signed integer string value", 395 value_str.str().c_str()); 396 break; 397 } 398 399 if (!Args::SInt64ValueIsValidForByteSize(ival64, byte_size)) { 400 error.SetErrorStringWithFormat( 401 "value 0x%" PRIx64 402 " is too large to fit in a %u byte signed integer value", 403 ival64, byte_size); 404 break; 405 } 406 407 if (!SetUInt(ival64, reg_info->byte_size)) { 408 error.SetErrorStringWithFormat("unsupported signed integer byte size: %u", 409 byte_size); 410 break; 411 } 412 break; 413 414 case eEncodingIEEE754: { 415 std::string value_string = value_str; 416 if (byte_size == sizeof(float)) { 417 if (::sscanf(value_string.c_str(), "%f", &flt_val) != 1) { 418 error.SetErrorStringWithFormat("'%s' is not a valid float string value", 419 value_string.c_str()); 420 break; 421 } 422 m_scalar = flt_val; 423 m_type = eTypeFloat; 424 } else if (byte_size == sizeof(double)) { 425 if (::sscanf(value_string.c_str(), "%lf", &dbl_val) != 1) { 426 error.SetErrorStringWithFormat("'%s' is not a valid float string value", 427 value_string.c_str()); 428 break; 429 } 430 m_scalar = dbl_val; 431 m_type = eTypeDouble; 432 } else if (byte_size == sizeof(long double)) { 433 if (::sscanf(value_string.c_str(), "%Lf", &ldbl_val) != 1) { 434 error.SetErrorStringWithFormat("'%s' is not a valid float string value", 435 value_string.c_str()); 436 break; 437 } 438 m_scalar = ldbl_val; 439 m_type = eTypeLongDouble; 440 } else { 441 error.SetErrorStringWithFormat("unsupported float byte size: %u", 442 byte_size); 443 return error; 444 } 445 break; 446 } 447 case eEncodingVector: 448 if (!ParseVectorEncoding(reg_info, value_str, byte_size, this)) 449 error.SetErrorString("unrecognized vector encoding string value."); 450 break; 451 } 452 453 return error; 454 } 455 456 bool RegisterValue::SignExtend(uint32_t sign_bitpos) { 457 switch (m_type) { 458 case eTypeInvalid: 459 break; 460 461 case eTypeUInt8: 462 case eTypeUInt16: 463 case eTypeUInt32: 464 case eTypeUInt64: 465 case eTypeUInt128: 466 return m_scalar.SignExtend(sign_bitpos); 467 case eTypeFloat: 468 case eTypeDouble: 469 case eTypeLongDouble: 470 case eTypeBytes: 471 break; 472 } 473 return false; 474 } 475 476 bool RegisterValue::CopyValue(const RegisterValue &rhs) { 477 if (this == &rhs) 478 return rhs.m_type == eTypeInvalid ? false : true; 479 480 m_type = rhs.m_type; 481 switch (m_type) { 482 case eTypeInvalid: 483 return false; 484 case eTypeUInt8: 485 case eTypeUInt16: 486 case eTypeUInt32: 487 case eTypeUInt64: 488 case eTypeUInt128: 489 case eTypeFloat: 490 case eTypeDouble: 491 case eTypeLongDouble: 492 m_scalar = rhs.m_scalar; 493 break; 494 case eTypeBytes: 495 assert(rhs.buffer.length <= kMaxRegisterByteSize); 496 ::memcpy(buffer.bytes, rhs.buffer.bytes, kMaxRegisterByteSize); 497 buffer.length = rhs.buffer.length; 498 buffer.byte_order = rhs.buffer.byte_order; 499 break; 500 } 501 return true; 502 } 503 504 uint16_t RegisterValue::GetAsUInt16(uint16_t fail_value, 505 bool *success_ptr) const { 506 if (success_ptr) 507 *success_ptr = true; 508 509 switch (m_type) { 510 default: 511 break; 512 case eTypeUInt8: 513 case eTypeUInt16: 514 return m_scalar.UShort(fail_value); 515 case eTypeBytes: { 516 switch (buffer.length) { 517 default: 518 break; 519 case 1: 520 case 2: 521 return *(const uint16_t *)buffer.bytes; 522 } 523 } break; 524 } 525 if (success_ptr) 526 *success_ptr = false; 527 return fail_value; 528 } 529 530 uint32_t RegisterValue::GetAsUInt32(uint32_t fail_value, 531 bool *success_ptr) const { 532 if (success_ptr) 533 *success_ptr = true; 534 switch (m_type) { 535 default: 536 break; 537 case eTypeUInt8: 538 case eTypeUInt16: 539 case eTypeUInt32: 540 case eTypeFloat: 541 case eTypeDouble: 542 case eTypeLongDouble: 543 return m_scalar.UInt(fail_value); 544 case eTypeBytes: { 545 switch (buffer.length) { 546 default: 547 break; 548 case 1: 549 case 2: 550 case 4: 551 return *(const uint32_t *)buffer.bytes; 552 } 553 } break; 554 } 555 if (success_ptr) 556 *success_ptr = false; 557 return fail_value; 558 } 559 560 uint64_t RegisterValue::GetAsUInt64(uint64_t fail_value, 561 bool *success_ptr) const { 562 if (success_ptr) 563 *success_ptr = true; 564 switch (m_type) { 565 default: 566 break; 567 case eTypeUInt8: 568 case eTypeUInt16: 569 case eTypeUInt32: 570 case eTypeUInt64: 571 case eTypeFloat: 572 case eTypeDouble: 573 case eTypeLongDouble: 574 return m_scalar.ULongLong(fail_value); 575 case eTypeBytes: { 576 switch (buffer.length) { 577 default: 578 break; 579 case 1: 580 return *(const uint8_t *)buffer.bytes; 581 case 2: 582 return *(const uint16_t *)buffer.bytes; 583 case 4: 584 return *(const uint32_t *)buffer.bytes; 585 case 8: 586 return *(const uint64_t *)buffer.bytes; 587 } 588 } break; 589 } 590 if (success_ptr) 591 *success_ptr = false; 592 return fail_value; 593 } 594 595 llvm::APInt RegisterValue::GetAsUInt128(const llvm::APInt &fail_value, 596 bool *success_ptr) const { 597 if (success_ptr) 598 *success_ptr = true; 599 switch (m_type) { 600 default: 601 break; 602 case eTypeUInt8: 603 case eTypeUInt16: 604 case eTypeUInt32: 605 case eTypeUInt64: 606 case eTypeUInt128: 607 case eTypeFloat: 608 case eTypeDouble: 609 case eTypeLongDouble: 610 return m_scalar.UInt128(fail_value); 611 case eTypeBytes: { 612 switch (buffer.length) { 613 default: 614 break; 615 case 1: 616 case 2: 617 case 4: 618 case 8: 619 case 16: 620 return llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, 621 ((const type128 *)buffer.bytes)->x); 622 } 623 } break; 624 } 625 if (success_ptr) 626 *success_ptr = false; 627 return fail_value; 628 } 629 630 float RegisterValue::GetAsFloat(float fail_value, bool *success_ptr) const { 631 if (success_ptr) 632 *success_ptr = true; 633 switch (m_type) { 634 default: 635 break; 636 case eTypeUInt32: 637 case eTypeUInt64: 638 case eTypeUInt128: 639 case eTypeFloat: 640 case eTypeDouble: 641 case eTypeLongDouble: 642 return m_scalar.Float(fail_value); 643 } 644 if (success_ptr) 645 *success_ptr = false; 646 return fail_value; 647 } 648 649 double RegisterValue::GetAsDouble(double fail_value, bool *success_ptr) const { 650 if (success_ptr) 651 *success_ptr = true; 652 switch (m_type) { 653 default: 654 break; 655 656 case eTypeUInt32: 657 case eTypeUInt64: 658 case eTypeUInt128: 659 case eTypeFloat: 660 case eTypeDouble: 661 case eTypeLongDouble: 662 return m_scalar.Double(fail_value); 663 } 664 if (success_ptr) 665 *success_ptr = false; 666 return fail_value; 667 } 668 669 long double RegisterValue::GetAsLongDouble(long double fail_value, 670 bool *success_ptr) const { 671 if (success_ptr) 672 *success_ptr = true; 673 switch (m_type) { 674 default: 675 break; 676 677 case eTypeUInt32: 678 case eTypeUInt64: 679 case eTypeUInt128: 680 case eTypeFloat: 681 case eTypeDouble: 682 case eTypeLongDouble: 683 return m_scalar.LongDouble(); 684 } 685 if (success_ptr) 686 *success_ptr = false; 687 return fail_value; 688 } 689 690 const void *RegisterValue::GetBytes() const { 691 switch (m_type) { 692 case eTypeInvalid: 693 break; 694 case eTypeUInt8: 695 case eTypeUInt16: 696 case eTypeUInt32: 697 case eTypeUInt64: 698 case eTypeUInt128: 699 case eTypeFloat: 700 case eTypeDouble: 701 case eTypeLongDouble: 702 return m_scalar.GetBytes(); 703 case eTypeBytes: 704 return buffer.bytes; 705 } 706 return nullptr; 707 } 708 709 uint32_t RegisterValue::GetByteSize() const { 710 switch (m_type) { 711 case eTypeInvalid: 712 break; 713 case eTypeUInt8: 714 return 1; 715 case eTypeUInt16: 716 return 2; 717 case eTypeUInt32: 718 case eTypeUInt64: 719 case eTypeUInt128: 720 case eTypeFloat: 721 case eTypeDouble: 722 case eTypeLongDouble: 723 return m_scalar.GetByteSize(); 724 case eTypeBytes: 725 return buffer.length; 726 } 727 return 0; 728 } 729 730 bool RegisterValue::SetUInt(uint64_t uint, uint32_t byte_size) { 731 if (byte_size == 0) { 732 SetUInt64(uint); 733 } else if (byte_size == 1) { 734 SetUInt8(uint); 735 } else if (byte_size <= 2) { 736 SetUInt16(uint); 737 } else if (byte_size <= 4) { 738 SetUInt32(uint); 739 } else if (byte_size <= 8) { 740 SetUInt64(uint); 741 } else if (byte_size <= 16) { 742 SetUInt128(llvm::APInt(128, uint)); 743 } else 744 return false; 745 return true; 746 } 747 748 void RegisterValue::SetBytes(const void *bytes, size_t length, 749 lldb::ByteOrder byte_order) { 750 // If this assertion fires off we need to increase the size of buffer.bytes, 751 // or make it something that is allocated on the heap. Since the data buffer 752 // is in a union, we can't make it a collection class like SmallVector... 753 if (bytes && length > 0) { 754 assert(length <= sizeof(buffer.bytes) && 755 "Storing too many bytes in a RegisterValue."); 756 m_type = eTypeBytes; 757 buffer.length = length; 758 memcpy(buffer.bytes, bytes, length); 759 buffer.byte_order = byte_order; 760 } else { 761 m_type = eTypeInvalid; 762 buffer.length = 0; 763 } 764 } 765 766 bool RegisterValue::operator==(const RegisterValue &rhs) const { 767 if (m_type == rhs.m_type) { 768 switch (m_type) { 769 case eTypeInvalid: 770 return true; 771 case eTypeUInt8: 772 case eTypeUInt16: 773 case eTypeUInt32: 774 case eTypeUInt64: 775 case eTypeUInt128: 776 case eTypeFloat: 777 case eTypeDouble: 778 case eTypeLongDouble: 779 return m_scalar == rhs.m_scalar; 780 case eTypeBytes: 781 if (buffer.length != rhs.buffer.length) 782 return false; 783 else { 784 uint8_t length = buffer.length; 785 if (length > kMaxRegisterByteSize) 786 length = kMaxRegisterByteSize; 787 return memcmp(buffer.bytes, rhs.buffer.bytes, length) == 0; 788 } 789 break; 790 } 791 } 792 return false; 793 } 794 795 bool RegisterValue::operator!=(const RegisterValue &rhs) const { 796 if (m_type != rhs.m_type) 797 return true; 798 switch (m_type) { 799 case eTypeInvalid: 800 return false; 801 case eTypeUInt8: 802 case eTypeUInt16: 803 case eTypeUInt32: 804 case eTypeUInt64: 805 case eTypeUInt128: 806 case eTypeFloat: 807 case eTypeDouble: 808 case eTypeLongDouble: 809 return m_scalar != rhs.m_scalar; 810 case eTypeBytes: 811 if (buffer.length != rhs.buffer.length) { 812 return true; 813 } else { 814 uint8_t length = buffer.length; 815 if (length > kMaxRegisterByteSize) 816 length = kMaxRegisterByteSize; 817 return memcmp(buffer.bytes, rhs.buffer.bytes, length) != 0; 818 } 819 break; 820 } 821 return true; 822 } 823 824 bool RegisterValue::ClearBit(uint32_t bit) { 825 switch (m_type) { 826 case eTypeInvalid: 827 break; 828 829 case eTypeUInt8: 830 case eTypeUInt16: 831 case eTypeUInt32: 832 case eTypeUInt64: 833 case eTypeUInt128: 834 if (bit < (GetByteSize() * 8)) { 835 return m_scalar.ClearBit(bit); 836 } 837 break; 838 839 case eTypeFloat: 840 case eTypeDouble: 841 case eTypeLongDouble: 842 break; 843 844 case eTypeBytes: 845 if (buffer.byte_order == eByteOrderBig || 846 buffer.byte_order == eByteOrderLittle) { 847 uint32_t byte_idx; 848 if (buffer.byte_order == eByteOrderBig) 849 byte_idx = buffer.length - (bit / 8) - 1; 850 else 851 byte_idx = bit / 8; 852 853 const uint32_t byte_bit = bit % 8; 854 if (byte_idx < buffer.length) { 855 buffer.bytes[byte_idx] &= ~(1u << byte_bit); 856 return true; 857 } 858 } 859 break; 860 } 861 return false; 862 } 863 864 bool RegisterValue::SetBit(uint32_t bit) { 865 switch (m_type) { 866 case eTypeInvalid: 867 break; 868 869 case eTypeUInt8: 870 case eTypeUInt16: 871 case eTypeUInt32: 872 case eTypeUInt64: 873 case eTypeUInt128: 874 if (bit < (GetByteSize() * 8)) { 875 return m_scalar.SetBit(bit); 876 } 877 break; 878 879 case eTypeFloat: 880 case eTypeDouble: 881 case eTypeLongDouble: 882 break; 883 884 case eTypeBytes: 885 if (buffer.byte_order == eByteOrderBig || 886 buffer.byte_order == eByteOrderLittle) { 887 uint32_t byte_idx; 888 if (buffer.byte_order == eByteOrderBig) 889 byte_idx = buffer.length - (bit / 8) - 1; 890 else 891 byte_idx = bit / 8; 892 893 const uint32_t byte_bit = bit % 8; 894 if (byte_idx < buffer.length) { 895 buffer.bytes[byte_idx] |= (1u << byte_bit); 896 return true; 897 } 898 } 899 break; 900 } 901 return false; 902 } 903