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 = Status::FromErrorStringWithFormatv( 47 "invalid register value type for register {0}", 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 = Status::FromErrorString("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 = Status::FromErrorStringWithFormat( 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 = Status::FromErrorStringWithFormat( 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 = Status::FromErrorString("empty data."); 163 return error; 164 } 165 166 if (reg_info.byte_size == 0) { 167 error = Status::FromErrorString("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 = Status::FromErrorString("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.GetByteOrder() == 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 = Status::FromErrorStringWithFormat( 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 = Status::FromErrorStringWithFormat( 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 = Status::FromErrorString("Invalid register info argument."); 318 return error; 319 } 320 321 m_type = eTypeInvalid; 322 if (value_str.empty()) { 323 error = Status::FromErrorString("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 = Status::FromErrorString("Invalid encoding."); 336 break; 337 338 case eEncodingUint: 339 if (byte_size > sizeof(uint64_t)) { 340 error = Status::FromErrorStringWithFormat( 341 "unsupported unsigned integer byte size: %u", byte_size); 342 break; 343 } 344 if (value_str.getAsInteger(0, uval64)) { 345 error = Status::FromErrorStringWithFormatv( 346 "'{0}' is not a valid unsigned integer string value", value_str); 347 break; 348 } 349 350 if (!UInt64ValueIsValidForByteSize(uval64, byte_size)) { 351 error = Status::FromErrorStringWithFormat( 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 = Status::FromErrorStringWithFormat( 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 = Status::FromErrorStringWithFormat( 368 "unsupported signed integer byte size: %u", byte_size); 369 break; 370 } 371 372 if (value_str.getAsInteger(0, ival64)) { 373 error = Status::FromErrorStringWithFormatv( 374 "'{0}' is not a valid signed integer string value", value_str); 375 break; 376 } 377 378 if (!SInt64ValueIsValidForByteSize(ival64, byte_size)) { 379 error = Status::FromErrorStringWithFormat( 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 = Status::FromErrorStringWithFormat( 388 "unsupported signed integer byte size: %u", 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 = Status::FromErrorStringWithFormat( 398 "'%s' is not a valid float string value", 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 = Status::FromErrorStringWithFormat( 406 "'%s' is not a valid float string value", 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 = Status::FromErrorStringWithFormat( 414 "'%s' is not a valid float string value", value_string.c_str()); 415 break; 416 } 417 m_scalar = ldbl_val; 418 m_type = eTypeLongDouble; 419 } else { 420 error = Status::FromErrorStringWithFormat( 421 "unsupported float byte size: %u", byte_size); 422 return error; 423 } 424 break; 425 } 426 case eEncodingVector: 427 if (!ParseVectorEncoding(reg_info, value_str, byte_size, this)) 428 error = 429 Status::FromErrorString("unrecognized vector encoding string value."); 430 break; 431 } 432 433 return error; 434 } 435 436 bool RegisterValue::SignExtend(uint32_t sign_bitpos) { 437 switch (m_type) { 438 case eTypeInvalid: 439 break; 440 441 case eTypeUInt8: 442 case eTypeUInt16: 443 case eTypeUInt32: 444 case eTypeUInt64: 445 case eTypeUInt128: 446 return m_scalar.SignExtend(sign_bitpos); 447 case eTypeFloat: 448 case eTypeDouble: 449 case eTypeLongDouble: 450 case eTypeBytes: 451 break; 452 } 453 return false; 454 } 455 456 bool RegisterValue::CopyValue(const RegisterValue &rhs) { 457 if (this == &rhs) 458 return rhs.m_type != eTypeInvalid; 459 460 m_type = rhs.m_type; 461 switch (m_type) { 462 case eTypeInvalid: 463 return false; 464 case eTypeUInt8: 465 case eTypeUInt16: 466 case eTypeUInt32: 467 case eTypeUInt64: 468 case eTypeUInt128: 469 case eTypeFloat: 470 case eTypeDouble: 471 case eTypeLongDouble: 472 m_scalar = rhs.m_scalar; 473 break; 474 case eTypeBytes: 475 buffer.bytes = rhs.buffer.bytes; 476 buffer.byte_order = rhs.buffer.byte_order; 477 break; 478 } 479 return true; 480 } 481 482 uint16_t RegisterValue::GetAsUInt16(uint16_t fail_value, 483 bool *success_ptr) const { 484 if (success_ptr) 485 *success_ptr = true; 486 487 switch (m_type) { 488 default: 489 break; 490 case eTypeUInt8: 491 case eTypeUInt16: 492 return m_scalar.UShort(fail_value); 493 case eTypeBytes: { 494 switch (buffer.bytes.size()) { 495 default: 496 break; 497 case 1: 498 case 2: 499 return *reinterpret_cast<const uint16_t *>(buffer.bytes.data()); 500 } 501 } break; 502 } 503 if (success_ptr) 504 *success_ptr = false; 505 return fail_value; 506 } 507 508 uint32_t RegisterValue::GetAsUInt32(uint32_t fail_value, 509 bool *success_ptr) const { 510 if (success_ptr) 511 *success_ptr = true; 512 switch (m_type) { 513 default: 514 break; 515 case eTypeUInt8: 516 case eTypeUInt16: 517 case eTypeUInt32: 518 case eTypeFloat: 519 case eTypeDouble: 520 case eTypeLongDouble: 521 return m_scalar.UInt(fail_value); 522 case eTypeBytes: { 523 switch (buffer.bytes.size()) { 524 default: 525 break; 526 case 1: 527 case 2: 528 case 4: 529 return *reinterpret_cast<const uint32_t *>(buffer.bytes.data()); 530 } 531 } break; 532 } 533 if (success_ptr) 534 *success_ptr = false; 535 return fail_value; 536 } 537 538 uint64_t RegisterValue::GetAsUInt64(uint64_t fail_value, 539 bool *success_ptr) const { 540 if (success_ptr) 541 *success_ptr = true; 542 switch (m_type) { 543 default: 544 break; 545 case eTypeUInt8: 546 case eTypeUInt16: 547 case eTypeUInt32: 548 case eTypeUInt64: 549 case eTypeFloat: 550 case eTypeDouble: 551 case eTypeLongDouble: 552 return m_scalar.ULongLong(fail_value); 553 case eTypeBytes: { 554 switch (buffer.bytes.size()) { 555 default: 556 break; 557 case 1: 558 return *(const uint8_t *)buffer.bytes.data(); 559 case 2: 560 return *reinterpret_cast<const uint16_t *>(buffer.bytes.data()); 561 case 4: 562 return *reinterpret_cast<const uint32_t *>(buffer.bytes.data()); 563 case 8: 564 return *reinterpret_cast<const uint64_t *>(buffer.bytes.data()); 565 } 566 } break; 567 } 568 if (success_ptr) 569 *success_ptr = false; 570 return fail_value; 571 } 572 573 llvm::APInt RegisterValue::GetAsUInt128(const llvm::APInt &fail_value, 574 bool *success_ptr) const { 575 if (success_ptr) 576 *success_ptr = true; 577 switch (m_type) { 578 default: 579 break; 580 case eTypeUInt8: 581 case eTypeUInt16: 582 case eTypeUInt32: 583 case eTypeUInt64: 584 case eTypeUInt128: 585 case eTypeFloat: 586 case eTypeDouble: 587 case eTypeLongDouble: 588 return m_scalar.UInt128(fail_value); 589 case eTypeBytes: { 590 switch (buffer.bytes.size()) { 591 default: 592 break; 593 case 1: 594 case 2: 595 case 4: 596 case 8: 597 case 16: 598 return llvm::APInt( 599 BITWIDTH_INT128, NUM_OF_WORDS_INT128, 600 (reinterpret_cast<const type128 *>(buffer.bytes.data()))->x); 601 } 602 } break; 603 } 604 if (success_ptr) 605 *success_ptr = false; 606 return fail_value; 607 } 608 609 float RegisterValue::GetAsFloat(float fail_value, bool *success_ptr) const { 610 if (success_ptr) 611 *success_ptr = true; 612 switch (m_type) { 613 default: 614 break; 615 case eTypeUInt32: 616 case eTypeUInt64: 617 case eTypeUInt128: 618 case eTypeFloat: 619 case eTypeDouble: 620 case eTypeLongDouble: 621 return m_scalar.Float(fail_value); 622 } 623 if (success_ptr) 624 *success_ptr = false; 625 return fail_value; 626 } 627 628 double RegisterValue::GetAsDouble(double fail_value, bool *success_ptr) const { 629 if (success_ptr) 630 *success_ptr = true; 631 switch (m_type) { 632 default: 633 break; 634 635 case eTypeUInt32: 636 case eTypeUInt64: 637 case eTypeUInt128: 638 case eTypeFloat: 639 case eTypeDouble: 640 case eTypeLongDouble: 641 return m_scalar.Double(fail_value); 642 } 643 if (success_ptr) 644 *success_ptr = false; 645 return fail_value; 646 } 647 648 long double RegisterValue::GetAsLongDouble(long double fail_value, 649 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.LongDouble(); 663 } 664 if (success_ptr) 665 *success_ptr = false; 666 return fail_value; 667 } 668 669 const void *RegisterValue::GetBytes() const { 670 switch (m_type) { 671 case eTypeInvalid: 672 break; 673 case eTypeUInt8: 674 case eTypeUInt16: 675 case eTypeUInt32: 676 case eTypeUInt64: 677 case eTypeUInt128: 678 case eTypeFloat: 679 case eTypeDouble: 680 case eTypeLongDouble: 681 m_scalar.GetBytes(buffer.bytes); 682 return buffer.bytes.data(); 683 case eTypeBytes: 684 return buffer.bytes.data(); 685 } 686 return nullptr; 687 } 688 689 uint32_t RegisterValue::GetByteSize() const { 690 switch (m_type) { 691 case eTypeInvalid: 692 break; 693 case eTypeUInt8: 694 return 1; 695 case eTypeUInt16: 696 return 2; 697 case eTypeUInt32: 698 case eTypeUInt64: 699 case eTypeUInt128: 700 case eTypeFloat: 701 case eTypeDouble: 702 case eTypeLongDouble: 703 return m_scalar.GetByteSize(); 704 case eTypeBytes: 705 return buffer.bytes.size(); 706 } 707 return 0; 708 } 709 710 bool RegisterValue::SetUInt(uint64_t uint, uint32_t byte_size) { 711 if (byte_size == 0) { 712 SetUInt64(uint); 713 } else if (byte_size == 1) { 714 SetUInt8(uint); 715 } else if (byte_size <= 2) { 716 SetUInt16(uint); 717 } else if (byte_size <= 4) { 718 SetUInt32(uint); 719 } else if (byte_size <= 8) { 720 SetUInt64(uint); 721 } else if (byte_size <= 16) { 722 SetUInt128(llvm::APInt(128, uint)); 723 } else 724 return false; 725 return true; 726 } 727 728 void RegisterValue::SetBytes(const void *bytes, size_t length, 729 lldb::ByteOrder byte_order) { 730 if (bytes && length > 0) { 731 m_type = eTypeBytes; 732 buffer.bytes.resize(length); 733 memcpy(buffer.bytes.data(), bytes, length); 734 buffer.byte_order = byte_order; 735 } else { 736 m_type = eTypeInvalid; 737 buffer.bytes.resize(0); 738 } 739 } 740 741 bool RegisterValue::operator==(const RegisterValue &rhs) const { 742 if (m_type == rhs.m_type) { 743 switch (m_type) { 744 case eTypeInvalid: 745 return true; 746 case eTypeUInt8: 747 case eTypeUInt16: 748 case eTypeUInt32: 749 case eTypeUInt64: 750 case eTypeUInt128: 751 case eTypeFloat: 752 case eTypeDouble: 753 case eTypeLongDouble: 754 return m_scalar == rhs.m_scalar; 755 case eTypeBytes: 756 return buffer.bytes == rhs.buffer.bytes; 757 } 758 } 759 return false; 760 } 761 762 bool RegisterValue::operator!=(const RegisterValue &rhs) const { 763 return !(*this == rhs); 764 } 765 766 bool RegisterValue::ClearBit(uint32_t bit) { 767 switch (m_type) { 768 case eTypeInvalid: 769 break; 770 771 case eTypeUInt8: 772 case eTypeUInt16: 773 case eTypeUInt32: 774 case eTypeUInt64: 775 case eTypeUInt128: 776 if (bit < (GetByteSize() * 8)) { 777 return m_scalar.ClearBit(bit); 778 } 779 break; 780 781 case eTypeFloat: 782 case eTypeDouble: 783 case eTypeLongDouble: 784 break; 785 786 case eTypeBytes: 787 if (buffer.byte_order == eByteOrderBig || 788 buffer.byte_order == eByteOrderLittle) { 789 uint32_t byte_idx; 790 if (buffer.byte_order == eByteOrderBig) 791 byte_idx = buffer.bytes.size() - (bit / 8) - 1; 792 else 793 byte_idx = bit / 8; 794 795 const uint32_t byte_bit = bit % 8; 796 if (byte_idx < buffer.bytes.size()) { 797 buffer.bytes[byte_idx] &= ~(1u << byte_bit); 798 return true; 799 } 800 } 801 break; 802 } 803 return false; 804 } 805 806 bool RegisterValue::SetBit(uint32_t bit) { 807 switch (m_type) { 808 case eTypeInvalid: 809 break; 810 811 case eTypeUInt8: 812 case eTypeUInt16: 813 case eTypeUInt32: 814 case eTypeUInt64: 815 case eTypeUInt128: 816 if (bit < (GetByteSize() * 8)) { 817 return m_scalar.SetBit(bit); 818 } 819 break; 820 821 case eTypeFloat: 822 case eTypeDouble: 823 case eTypeLongDouble: 824 break; 825 826 case eTypeBytes: 827 if (buffer.byte_order == eByteOrderBig || 828 buffer.byte_order == eByteOrderLittle) { 829 uint32_t byte_idx; 830 if (buffer.byte_order == eByteOrderBig) 831 byte_idx = buffer.bytes.size() - (bit / 8) - 1; 832 else 833 byte_idx = bit / 8; 834 835 const uint32_t byte_bit = bit % 8; 836 if (byte_idx < buffer.bytes.size()) { 837 buffer.bytes[byte_idx] |= (1u << byte_bit); 838 return true; 839 } 840 } 841 break; 842 } 843 return false; 844 } 845