1//===-- RegisterValue.cpp -------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/Utility/RegisterValue.h"
10
11#include "lldb/Utility/DataExtractor.h"
12#include "lldb/Utility/Scalar.h"
13#include "lldb/Utility/Status.h"
14#include "lldb/Utility/Stream.h"
15#include "lldb/Utility/StreamString.h"
16#include "lldb/lldb-defines.h"
17#include "lldb/lldb-private-types.h"
18
19#include "llvm/ADT/ArrayRef.h"
20#include "llvm/ADT/StringRef.h"
21
22#include <cstdint>
23#include <string>
24#include <tuple>
25#include <vector>
26
27#include <cassert>
28#include <cinttypes>
29#include <cstdio>
30
31using namespace lldb;
32using namespace lldb_private;
33
34bool RegisterValue::GetData(DataExtractor &data) const {
35  return data.SetData(GetBytes(), GetByteSize(), GetByteOrder()) > 0;
36}
37
38uint32_t RegisterValue::GetAsMemoryData(const RegisterInfo &reg_info, void *dst,
39                                        uint32_t dst_len,
40                                        lldb::ByteOrder dst_byte_order,
41                                        Status &error) const {
42  // ReadRegister should have already been called on this object prior to
43  // calling this.
44  if (GetType() == eTypeInvalid) {
45    // No value has been read into this object...
46    error.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
79uint32_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
126bool 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
150void RegisterValue::Clear() { m_type = eTypeInvalid; }
151
152RegisterValue::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
165Status 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()
261static 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
299static 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
313static 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
328Status 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
452bool 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
472bool 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
500uint16_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
526uint32_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
556uint64_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
591llvm::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
626float 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
645double 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
665long 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
686const 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
706uint32_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
727bool 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
745void 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
763bool 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
792bool RegisterValue::operator!=(const RegisterValue &rhs) const {
793  return !(*this == rhs);
794}
795
796bool 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
836bool 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