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