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