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 *reg_info, void *dst, 39 uint32_t dst_len, 40 lldb::ByteOrder dst_byte_order, 41 Status &error) const { 42 if (reg_info == nullptr) { 43 error.SetErrorString("invalid register info argument."); 44 return 0; 45 } 46 47 // ReadRegister should have already been called on this object prior to 48 // calling this. 49 if (GetType() == eTypeInvalid) { 50 // No value has been read into this object... 51 error.SetErrorStringWithFormat( 52 "invalid register value type for register %s", reg_info->name); 53 return 0; 54 } 55 56 if (dst_len > kMaxRegisterByteSize) { 57 error.SetErrorString("destination is too big"); 58 return 0; 59 } 60 61 const uint32_t src_len = reg_info->byte_size; 62 63 // Extract the register data into a data extractor 64 DataExtractor reg_data; 65 if (!GetData(reg_data)) { 66 error.SetErrorString("invalid register value to copy into"); 67 return 0; 68 } 69 70 // Prepare a memory buffer that contains some or all of the register value 71 const uint32_t bytes_copied = 72 reg_data.CopyByteOrderedData(0, // src offset 73 src_len, // src length 74 dst, // dst buffer 75 dst_len, // dst length 76 dst_byte_order); // dst byte order 77 if (bytes_copied == 0) 78 error.SetErrorStringWithFormat( 79 "failed to copy data for register write of %s", reg_info->name); 80 81 return bytes_copied; 82 } 83 84 uint32_t RegisterValue::SetFromMemoryData(const RegisterInfo *reg_info, 85 const void *src, uint32_t src_len, 86 lldb::ByteOrder src_byte_order, 87 Status &error) { 88 if (reg_info == nullptr) { 89 error.SetErrorString("invalid register info argument."); 90 return 0; 91 } 92 93 // Moving from addr into a register 94 // 95 // Case 1: src_len == dst_len 96 // 97 // |AABBCCDD| Address contents 98 // |AABBCCDD| Register contents 99 // 100 // Case 2: src_len > dst_len 101 // 102 // Status! (The register should always be big enough to hold the data) 103 // 104 // Case 3: src_len < dst_len 105 // 106 // |AABB| Address contents 107 // |AABB0000| Register contents [on little-endian hardware] 108 // |0000AABB| Register contents [on big-endian hardware] 109 if (src_len > kMaxRegisterByteSize) { 110 error.SetErrorStringWithFormat( 111 "register buffer is too small to receive %u bytes of data.", src_len); 112 return 0; 113 } 114 115 const uint32_t dst_len = reg_info->byte_size; 116 117 if (src_len > dst_len) { 118 error.SetErrorStringWithFormat( 119 "%u bytes is too big to store in register %s (%u bytes)", src_len, 120 reg_info->name, dst_len); 121 return 0; 122 } 123 124 // Use a data extractor to correctly copy and pad the bytes read into the 125 // register value 126 DataExtractor src_data(src, src_len, src_byte_order, 4); 127 128 error = SetValueFromData(reg_info, src_data, 0, true); 129 if (error.Fail()) 130 return 0; 131 132 // If SetValueFromData succeeded, we must have copied all of src_len 133 return src_len; 134 } 135 136 bool RegisterValue::GetScalarValue(Scalar &scalar) const { 137 switch (m_type) { 138 case eTypeInvalid: 139 break; 140 case eTypeBytes: { 141 DataExtractor data(buffer.bytes, buffer.length, buffer.byte_order, 1); 142 if (scalar.SetValueFromData(data, lldb::eEncodingUint, 143 buffer.length).Success()) 144 return true; 145 } break; 146 case eTypeUInt8: 147 case eTypeUInt16: 148 case eTypeUInt32: 149 case eTypeUInt64: 150 case eTypeUInt128: 151 case eTypeFloat: 152 case eTypeDouble: 153 case eTypeLongDouble: 154 scalar = m_scalar; 155 return true; 156 } 157 return false; 158 } 159 160 void RegisterValue::Clear() { m_type = eTypeInvalid; } 161 162 RegisterValue::Type RegisterValue::SetType(const RegisterInfo *reg_info) { 163 // To change the type, we simply copy the data in again, using the new format 164 RegisterValue copy; 165 DataExtractor copy_data; 166 if (copy.CopyValue(*this) && copy.GetData(copy_data)) 167 SetValueFromData(reg_info, copy_data, 0, true); 168 169 return m_type; 170 } 171 172 Status RegisterValue::SetValueFromData(const RegisterInfo *reg_info, 173 DataExtractor &src, 174 lldb::offset_t src_offset, 175 bool partial_data_ok) { 176 Status error; 177 178 if (src.GetByteSize() == 0) { 179 error.SetErrorString("empty data."); 180 return error; 181 } 182 183 if (reg_info->byte_size == 0) { 184 error.SetErrorString("invalid register info."); 185 return error; 186 } 187 188 uint32_t src_len = src.GetByteSize() - src_offset; 189 190 if (!partial_data_ok && (src_len < reg_info->byte_size)) { 191 error.SetErrorString("not enough data."); 192 return error; 193 } 194 195 // Cap the data length if there is more than enough bytes for this register 196 // value 197 if (src_len > reg_info->byte_size) 198 src_len = reg_info->byte_size; 199 200 // Zero out the value in case we get partial data... 201 memset(buffer.bytes, 0, sizeof(buffer.bytes)); 202 203 type128 int128; 204 205 m_type = eTypeInvalid; 206 switch (reg_info->encoding) { 207 case eEncodingInvalid: 208 break; 209 case eEncodingUint: 210 case eEncodingSint: 211 if (reg_info->byte_size == 1) 212 SetUInt8(src.GetMaxU32(&src_offset, src_len)); 213 else if (reg_info->byte_size <= 2) 214 SetUInt16(src.GetMaxU32(&src_offset, src_len)); 215 else if (reg_info->byte_size <= 4) 216 SetUInt32(src.GetMaxU32(&src_offset, src_len)); 217 else if (reg_info->byte_size <= 8) 218 SetUInt64(src.GetMaxU64(&src_offset, src_len)); 219 else if (reg_info->byte_size <= 16) { 220 uint64_t data1 = src.GetU64(&src_offset); 221 uint64_t data2 = src.GetU64(&src_offset); 222 if (src.GetByteSize() == eByteOrderBig) { 223 int128.x[0] = data1; 224 int128.x[1] = data2; 225 } else { 226 int128.x[0] = data2; 227 int128.x[1] = data1; 228 } 229 SetUInt128(llvm::APInt(128, 2, int128.x)); 230 } 231 break; 232 case eEncodingIEEE754: 233 if (reg_info->byte_size == sizeof(float)) 234 SetFloat(src.GetFloat(&src_offset)); 235 else if (reg_info->byte_size == sizeof(double)) 236 SetDouble(src.GetDouble(&src_offset)); 237 else if (reg_info->byte_size == sizeof(long double)) 238 SetLongDouble(src.GetLongDouble(&src_offset)); 239 break; 240 case eEncodingVector: { 241 m_type = eTypeBytes; 242 buffer.length = reg_info->byte_size; 243 buffer.byte_order = src.GetByteOrder(); 244 assert(buffer.length <= kMaxRegisterByteSize); 245 if (buffer.length > kMaxRegisterByteSize) 246 buffer.length = kMaxRegisterByteSize; 247 if (src.CopyByteOrderedData( 248 src_offset, // offset within "src" to start extracting data 249 src_len, // src length 250 buffer.bytes, // dst buffer 251 buffer.length, // dst length 252 buffer.byte_order) == 0) // dst byte order 253 { 254 error.SetErrorStringWithFormat( 255 "failed to copy data for register write of %s", reg_info->name); 256 return error; 257 } 258 } 259 } 260 261 if (m_type == eTypeInvalid) 262 error.SetErrorStringWithFormat( 263 "invalid register value type for register %s", reg_info->name); 264 return error; 265 } 266 267 // Helper function for RegisterValue::SetValueFromString() 268 static bool ParseVectorEncoding(const RegisterInfo *reg_info, 269 llvm::StringRef vector_str, 270 const uint32_t byte_size, 271 RegisterValue *reg_value) { 272 // Example: vector_str = "{0x2c 0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a 273 // 0x2a 0x3e 0x84 0x4f 0x2a 0x3e}". 274 vector_str = vector_str.trim(); 275 vector_str.consume_front("{"); 276 vector_str.consume_back("}"); 277 vector_str = vector_str.trim(); 278 279 char Sep = ' '; 280 281 // The first split should give us: 282 // ('0x2c', '0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a 0x2a 0x3e 0x84 0x4f 283 // 0x2a 0x3e'). 284 llvm::StringRef car; 285 llvm::StringRef cdr = vector_str; 286 std::tie(car, cdr) = vector_str.split(Sep); 287 std::vector<uint8_t> bytes; 288 unsigned byte = 0; 289 290 // Using radix auto-sensing by passing 0 as the radix. Keep on processing the 291 // vector elements as long as the parsing succeeds and the vector size is < 292 // byte_size. 293 while (!car.getAsInteger(0, byte) && bytes.size() < byte_size) { 294 bytes.push_back(byte); 295 std::tie(car, cdr) = cdr.split(Sep); 296 } 297 298 // Check for vector of exact byte_size elements. 299 if (bytes.size() != byte_size) 300 return false; 301 302 reg_value->SetBytes(&(bytes.front()), byte_size, eByteOrderLittle); 303 return true; 304 } 305 306 static bool UInt64ValueIsValidForByteSize(uint64_t uval64, 307 size_t total_byte_size) { 308 if (total_byte_size > 8) 309 return false; 310 311 if (total_byte_size == 8) 312 return true; 313 314 const uint64_t max = 315 (static_cast<uint64_t>(1) << static_cast<uint64_t>(total_byte_size * 8)) - 316 1; 317 return uval64 <= max; 318 } 319 320 static bool SInt64ValueIsValidForByteSize(int64_t sval64, 321 size_t total_byte_size) { 322 if (total_byte_size > 8) 323 return false; 324 325 if (total_byte_size == 8) 326 return true; 327 328 const int64_t max = (static_cast<int64_t>(1) 329 << static_cast<uint64_t>(total_byte_size * 8 - 1)) - 330 1; 331 const int64_t min = ~(max); 332 return min <= sval64 && sval64 <= max; 333 } 334 335 Status RegisterValue::SetValueFromString(const RegisterInfo *reg_info, 336 llvm::StringRef value_str) { 337 Status error; 338 if (reg_info == nullptr) { 339 error.SetErrorString("Invalid register info argument."); 340 return error; 341 } 342 343 m_type = eTypeInvalid; 344 if (value_str.empty()) { 345 error.SetErrorString("Invalid c-string value string."); 346 return error; 347 } 348 const uint32_t byte_size = reg_info->byte_size; 349 350 uint64_t uval64; 351 int64_t ival64; 352 float flt_val; 353 double dbl_val; 354 long double ldbl_val; 355 switch (reg_info->encoding) { 356 case eEncodingInvalid: 357 error.SetErrorString("Invalid encoding."); 358 break; 359 360 case eEncodingUint: 361 if (byte_size > sizeof(uint64_t)) { 362 error.SetErrorStringWithFormat( 363 "unsupported unsigned integer byte size: %u", byte_size); 364 break; 365 } 366 if (value_str.getAsInteger(0, uval64)) { 367 error.SetErrorStringWithFormat( 368 "'%s' is not a valid unsigned integer string value", 369 value_str.str().c_str()); 370 break; 371 } 372 373 if (!UInt64ValueIsValidForByteSize(uval64, byte_size)) { 374 error.SetErrorStringWithFormat( 375 "value 0x%" PRIx64 376 " is too large to fit in a %u byte unsigned integer value", 377 uval64, byte_size); 378 break; 379 } 380 381 if (!SetUInt(uval64, reg_info->byte_size)) { 382 error.SetErrorStringWithFormat( 383 "unsupported unsigned integer byte size: %u", byte_size); 384 break; 385 } 386 break; 387 388 case eEncodingSint: 389 if (byte_size > sizeof(long long)) { 390 error.SetErrorStringWithFormat("unsupported signed integer byte size: %u", 391 byte_size); 392 break; 393 } 394 395 if (value_str.getAsInteger(0, ival64)) { 396 error.SetErrorStringWithFormat( 397 "'%s' is not a valid signed integer string value", 398 value_str.str().c_str()); 399 break; 400 } 401 402 if (!SInt64ValueIsValidForByteSize(ival64, byte_size)) { 403 error.SetErrorStringWithFormat( 404 "value 0x%" PRIx64 405 " is too large to fit in a %u byte signed integer value", 406 ival64, byte_size); 407 break; 408 } 409 410 if (!SetUInt(ival64, reg_info->byte_size)) { 411 error.SetErrorStringWithFormat("unsupported signed integer byte size: %u", 412 byte_size); 413 break; 414 } 415 break; 416 417 case eEncodingIEEE754: { 418 std::string value_string = std::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; 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 *reinterpret_cast<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 *reinterpret_cast<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 *reinterpret_cast<const uint16_t *>(buffer.bytes); 586 case 4: 587 return *reinterpret_cast<const uint32_t *>(buffer.bytes); 588 case 8: 589 return *reinterpret_cast<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 (reinterpret_cast<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 m_scalar.GetBytes(buffer.bytes); 706 return buffer.bytes; 707 case eTypeBytes: 708 return buffer.bytes; 709 } 710 return nullptr; 711 } 712 713 uint32_t RegisterValue::GetByteSize() const { 714 switch (m_type) { 715 case eTypeInvalid: 716 break; 717 case eTypeUInt8: 718 return 1; 719 case eTypeUInt16: 720 return 2; 721 case eTypeUInt32: 722 case eTypeUInt64: 723 case eTypeUInt128: 724 case eTypeFloat: 725 case eTypeDouble: 726 case eTypeLongDouble: 727 return m_scalar.GetByteSize(); 728 case eTypeBytes: 729 return buffer.length; 730 } 731 return 0; 732 } 733 734 bool RegisterValue::SetUInt(uint64_t uint, uint32_t byte_size) { 735 if (byte_size == 0) { 736 SetUInt64(uint); 737 } else if (byte_size == 1) { 738 SetUInt8(uint); 739 } else if (byte_size <= 2) { 740 SetUInt16(uint); 741 } else if (byte_size <= 4) { 742 SetUInt32(uint); 743 } else if (byte_size <= 8) { 744 SetUInt64(uint); 745 } else if (byte_size <= 16) { 746 SetUInt128(llvm::APInt(128, uint)); 747 } else 748 return false; 749 return true; 750 } 751 752 void RegisterValue::SetBytes(const void *bytes, size_t length, 753 lldb::ByteOrder byte_order) { 754 // If this assertion fires off we need to increase the size of buffer.bytes, 755 // or make it something that is allocated on the heap. Since the data buffer 756 // is in a union, we can't make it a collection class like SmallVector... 757 if (bytes && length > 0) { 758 assert(length <= sizeof(buffer.bytes) && 759 "Storing too many bytes in a RegisterValue."); 760 m_type = eTypeBytes; 761 buffer.length = length; 762 memcpy(buffer.bytes, bytes, length); 763 buffer.byte_order = byte_order; 764 } else { 765 m_type = eTypeInvalid; 766 buffer.length = 0; 767 } 768 } 769 770 bool RegisterValue::operator==(const RegisterValue &rhs) const { 771 if (m_type == rhs.m_type) { 772 switch (m_type) { 773 case eTypeInvalid: 774 return true; 775 case eTypeUInt8: 776 case eTypeUInt16: 777 case eTypeUInt32: 778 case eTypeUInt64: 779 case eTypeUInt128: 780 case eTypeFloat: 781 case eTypeDouble: 782 case eTypeLongDouble: 783 return m_scalar == rhs.m_scalar; 784 case eTypeBytes: 785 if (buffer.length != rhs.buffer.length) 786 return false; 787 else { 788 uint16_t length = buffer.length; 789 if (length > kMaxRegisterByteSize) 790 length = kMaxRegisterByteSize; 791 return memcmp(buffer.bytes, rhs.buffer.bytes, length) == 0; 792 } 793 break; 794 } 795 } 796 return false; 797 } 798 799 bool RegisterValue::operator!=(const RegisterValue &rhs) const { 800 return !(*this == rhs); 801 } 802 803 bool RegisterValue::ClearBit(uint32_t bit) { 804 switch (m_type) { 805 case eTypeInvalid: 806 break; 807 808 case eTypeUInt8: 809 case eTypeUInt16: 810 case eTypeUInt32: 811 case eTypeUInt64: 812 case eTypeUInt128: 813 if (bit < (GetByteSize() * 8)) { 814 return m_scalar.ClearBit(bit); 815 } 816 break; 817 818 case eTypeFloat: 819 case eTypeDouble: 820 case eTypeLongDouble: 821 break; 822 823 case eTypeBytes: 824 if (buffer.byte_order == eByteOrderBig || 825 buffer.byte_order == eByteOrderLittle) { 826 uint32_t byte_idx; 827 if (buffer.byte_order == eByteOrderBig) 828 byte_idx = buffer.length - (bit / 8) - 1; 829 else 830 byte_idx = bit / 8; 831 832 const uint32_t byte_bit = bit % 8; 833 if (byte_idx < buffer.length) { 834 buffer.bytes[byte_idx] &= ~(1u << byte_bit); 835 return true; 836 } 837 } 838 break; 839 } 840 return false; 841 } 842 843 bool RegisterValue::SetBit(uint32_t bit) { 844 switch (m_type) { 845 case eTypeInvalid: 846 break; 847 848 case eTypeUInt8: 849 case eTypeUInt16: 850 case eTypeUInt32: 851 case eTypeUInt64: 852 case eTypeUInt128: 853 if (bit < (GetByteSize() * 8)) { 854 return m_scalar.SetBit(bit); 855 } 856 break; 857 858 case eTypeFloat: 859 case eTypeDouble: 860 case eTypeLongDouble: 861 break; 862 863 case eTypeBytes: 864 if (buffer.byte_order == eByteOrderBig || 865 buffer.byte_order == eByteOrderLittle) { 866 uint32_t byte_idx; 867 if (buffer.byte_order == eByteOrderBig) 868 byte_idx = buffer.length - (bit / 8) - 1; 869 else 870 byte_idx = bit / 8; 871 872 const uint32_t byte_bit = bit % 8; 873 if (byte_idx < buffer.length) { 874 buffer.bytes[byte_idx] |= (1u << byte_bit); 875 return true; 876 } 877 } 878 break; 879 } 880 return false; 881 } 882