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
31using namespace lldb;
32using namespace lldb_private;
33
34bool RegisterValue::GetData(DataExtractor &data) const {
35 return data.SetData(bytes: GetBytes(), length: GetByteSize(), byte_order: GetByteOrder()) > 0;
36}
37
38uint32_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 // 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(data&: 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(src_offset: 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
74uint32_t RegisterValue::SetFromMemoryData(const RegisterInfo &reg_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, data&: src_data, offset: 0, partial_data_ok: 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
115bool 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, encoding: lldb::eEncodingUint, byte_size: 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
140void RegisterValue::Clear() { m_type = eTypeInvalid; }
141
142RegisterValue::Type RegisterValue::SetType(const RegisterInfo &reg_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(rhs: *this) && copy.GetData(data&: copy_data)) {
147 Status error = SetValueFromData(reg_info, data&: copy_data, offset: 0, partial_data_ok: true);
148 assert(error.Success() && "Expected SetValueFromData to succeed.");
149 UNUSED_IF_ASSERT_DISABLED(error);
150 }
151
152 return m_type;
153}
154
155Status RegisterValue::SetValueFromData(const RegisterInfo &reg_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(offset_ptr: &src_offset, byte_size: src_len));
193 else if (reg_info.byte_size <= 2)
194 SetUInt16(src.GetMaxU32(offset_ptr: &src_offset, byte_size: src_len));
195 else if (reg_info.byte_size <= 4)
196 SetUInt32(uint: src.GetMaxU32(offset_ptr: &src_offset, byte_size: src_len));
197 else if (reg_info.byte_size <= 8)
198 SetUInt64(uint: src.GetMaxU64(offset_ptr: &src_offset, byte_size: src_len));
199 else if (reg_info.byte_size <= 16) {
200 uint64_t data1 = src.GetU64(offset_ptr: &src_offset);
201 uint64_t data2 = src.GetU64(offset_ptr: &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(offset_ptr: &src_offset));
215 else if (reg_info.byte_size == sizeof(double))
216 SetDouble(src.GetDouble(offset_ptr: &src_offset));
217 else if (reg_info.byte_size == sizeof(long double))
218 SetLongDouble(src.GetLongDouble(offset_ptr: &src_offset));
219 break;
220 case eEncodingVector: {
221 m_type = eTypeBytes;
222 assert(reg_info.byte_size <= kMaxRegisterByteSize);
223 buffer.bytes.resize(N: 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 dst: buffer.bytes.data(), // dst buffer
229 dst_len: buffer.bytes.size(), // dst length
230 dst_byte_order: 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()
246static 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(Prefix: "{");
254 vector_str.consume_back(Suffix: "}");
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(args&: car, args&: cdr) = vector_str.split(Separator: 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(Radix: 0, Result&: byte) && bytes.size() < byte_size) {
272 bytes.push_back(x: byte);
273 std::tie(args&: car, args&: cdr) = cdr.split(Separator: 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: &(bytes.front()), length: byte_size, byte_order: eByteOrderLittle);
281 return true;
282}
283
284static 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
298static 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
313Status 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(Radix: 0, Result&: uval64)) {
345 error.SetErrorStringWithFormatv(
346 format: "'{0}' is not a valid unsigned integer string value", args&: value_str);
347 break;
348 }
349
350 if (!UInt64ValueIsValidForByteSize(uval64, total_byte_size: 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(uint: uval64, byte_size: 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(Radix: 0, Result&: ival64)) {
373 error.SetErrorStringWithFormatv(
374 format: "'{0}' is not a valid signed integer string value", args&: value_str);
375 break;
376 }
377
378 if (!SInt64ValueIsValidForByteSize(sval64: ival64, total_byte_size: 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(uint: ival64, byte_size: 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(s: value_string.c_str(), format: "%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(s: value_string.c_str(), format: "%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(s: value_string.c_str(), format: "%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, vector_str: value_str, byte_size, reg_value: this))
428 error.SetErrorString("unrecognized vector encoding string value.");
429 break;
430 }
431
432 return error;
433}
434
435bool 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(bit_pos: sign_bitpos);
446 case eTypeFloat:
447 case eTypeDouble:
448 case eTypeLongDouble:
449 case eTypeBytes:
450 break;
451 }
452 return false;
453}
454
455bool 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
481uint16_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
507uint32_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
537uint64_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
572llvm::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
608float 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
627double 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
647long 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
668const 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(storage: buffer.bytes);
681 return buffer.bytes.data();
682 case eTypeBytes:
683 return buffer.bytes.data();
684 }
685 return nullptr;
686}
687
688uint32_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
709bool 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
727void 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(N: length);
732 memcpy(dest: buffer.bytes.data(), src: bytes, n: length);
733 buffer.byte_order = byte_order;
734 } else {
735 m_type = eTypeInvalid;
736 buffer.bytes.resize(N: 0);
737 }
738}
739
740bool 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
761bool RegisterValue::operator!=(const RegisterValue &rhs) const {
762 return !(*this == rhs);
763}
764
765bool 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
805bool 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

source code of lldb/source/Utility/RegisterValue.cpp