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 = Status::FromErrorStringWithFormatv(
47 format: "invalid register value type for register {0}", args: 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 = Status::FromErrorString(str: "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 = Status::FromErrorStringWithFormat(
69 format: "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 = Status::FromErrorStringWithFormat(
98 format: "%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 = Status::FromErrorString(str: "empty data.");
163 return error;
164 }
165
166 if (reg_info.byte_size == 0) {
167 error = Status::FromErrorString(str: "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(str: "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.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(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 = Status::FromErrorStringWithFormat(
233 format: "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 format: "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 = Status::FromErrorString(str: "Invalid register info argument.");
318 return error;
319 }
320
321 m_type = eTypeInvalid;
322 if (value_str.empty()) {
323 error = Status::FromErrorString(str: "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(str: "Invalid encoding.");
336 break;
337
338 case eEncodingUint:
339 if (byte_size > sizeof(uint64_t)) {
340 error = Status::FromErrorStringWithFormat(
341 format: "unsupported unsigned integer byte size: %u", byte_size);
342 break;
343 }
344 if (value_str.getAsInteger(Radix: 0, Result&: uval64)) {
345 error = Status::FromErrorStringWithFormatv(
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 = Status::FromErrorStringWithFormat(
352 format: "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 = Status::FromErrorStringWithFormat(
360 format: "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 format: "unsupported signed integer byte size: %u", byte_size);
369 break;
370 }
371
372 if (value_str.getAsInteger(Radix: 0, Result&: ival64)) {
373 error = Status::FromErrorStringWithFormatv(
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 = Status::FromErrorStringWithFormat(
380 format: "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 = Status::FromErrorStringWithFormat(
388 format: "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(s: value_string.c_str(), format: "%f", &flt_val) != 1) {
397 error = Status::FromErrorStringWithFormat(
398 format: "'%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(s: value_string.c_str(), format: "%lf", &dbl_val) != 1) {
405 error = Status::FromErrorStringWithFormat(
406 format: "'%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(s: value_string.c_str(), format: "%Lf", &ldbl_val) != 1) {
413 error = Status::FromErrorStringWithFormat(
414 format: "'%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 format: "unsupported float byte size: %u", 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 =
429 Status::FromErrorString(str: "unrecognized vector encoding string value.");
430 break;
431 }
432
433 return error;
434}
435
436bool 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(bit_pos: sign_bitpos);
447 case eTypeFloat:
448 case eTypeDouble:
449 case eTypeLongDouble:
450 case eTypeBytes:
451 break;
452 }
453 return false;
454}
455
456bool 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
482uint16_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
508uint32_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
538uint64_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
573llvm::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
609float 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
628double 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
648long 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
669const 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(storage: buffer.bytes);
682 return buffer.bytes.data();
683 case eTypeBytes:
684 return buffer.bytes.data();
685 }
686 return nullptr;
687}
688
689uint32_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
710bool 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
728void 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(N: length);
733 memcpy(dest: buffer.bytes.data(), src: bytes, n: length);
734 buffer.byte_order = byte_order;
735 } else {
736 m_type = eTypeInvalid;
737 buffer.bytes.resize(N: 0);
738 }
739}
740
741bool 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
762bool RegisterValue::operator!=(const RegisterValue &rhs) const {
763 return !(*this == rhs);
764}
765
766bool 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
806bool 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

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