xref: /llvm-project/lldb/source/Utility/RegisterValue.cpp (revision 0642cd768b80665585c8500bed2933a3b99123dc)
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   // 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 &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         "%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 &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(*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 &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("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