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