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