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