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