ROSE 0.11.145.192
RegisterDescriptor.h
1#ifndef ROSE_BinaryAnalysis_RegisterDescriptor_H
2#define ROSE_BinaryAnalysis_RegisterDescriptor_H
3#include <featureTests.h>
4#ifdef ROSE_ENABLE_BINARY_ANALYSIS
5
6#include <Sawyer/Interval.h>
7#include <boost/serialization/access.hpp>
8
9namespace Rose {
10namespace BinaryAnalysis {
11
29 // The major, minor, offset, and size are packed together into this single data member.
30 //
31 // + The major number is the high order four bits at position 28-31 (inclusive) with bit #0 being the LSB.
32 // + The minor number is the 10 bits at position 18-27.
33 // + The offset is the 9 bits at position 9-17, but see note below and offset in [0,511].
34 // + The width-1 is the 9 bits at position 0-8, but see note below and width in [1,512].
35 //
36 // We need to be able to store a width of zero in order to distinguish between valid descriptors and invalid (default
37 // constructed) descriptors, but there aren't enough bits in the width field by itself to do that. We also need to be able
38 // to store and retrive the full range of major, minor, and offset values for zero-width descriptors. To accomplish that,
39 // we use the invarant that the offset+width of a valid descriptor cannot exceed 512 bits. Therefore, if the width field
40 // plus offset field equals 512 then the actual offset is as specified in the range [1,511] and the actual offset is zero;
41 // and if the offset field is 2 and the width field is 511 (the EMPTY_PATTERN constant) then the actual offset and actual
42 // width are both zero.
43 //
44 // There are still unused bit combinations that we could use to extend the ranges of any of the four fields. For instance,
45 // we don't necessarily need to align the fields on bit boundaries. We could use the fact that registers of size R bits need
46 // (R+1)*R/2 values to represent all combinations of offset and size, although this requires integer division to retrieve
47 // the values.
48 uint32_t data_;
49
50 // This pattern represents major=0, minor=0, offset=0, width=0 (offset field = 2, width field = 511)
51 static const uint32_t EMPTY_PATTERN = 0x000005ff; // EMPTY_PATTERN & ~OFFSET_WIDTH_MASK == 0
52 static const uint32_t OFFSET_WIDTH_MASK = 0x0003ffff; // 9-bit offset and 9-bit width
53
54#ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
55private:
56 friend class boost::serialization::access;
57
58 template<class S>
59 void serialize(S &s, const unsigned /*version*/) {
60 s & BOOST_SERIALIZATION_NVP(data_);
61 }
62#endif
63
64public:
69 : data_(EMPTY_PATTERN) {}
70
75 RegisterDescriptor(unsigned majr, unsigned minr, size_t offset, size_t width)
76 : data_(0) {
77 majorNumber(majr);
78 minorNumber(minr);
79 setOffsetWidth(offset, width);
80 }
81
83 static RegisterDescriptor fromRaw(uint32_t raw) {
84 RegisterDescriptor retval;
85 retval.data_ = raw;
86 return retval;
87 }
88
90 static unsigned maxMajor();
91
93 static unsigned maxMinor();
94
96 static unsigned maxOffset();
97
101 static unsigned maxNBits();
102
108 unsigned majorNumber() const {
109 return data_ >> 28; // bits 28-31 (4 bits)
110 }
111 void majorNumber(unsigned);
120 unsigned minorNumber() const {
121 return (data_ >> 18) & 0x3ff; // bits 18-27 (10 bits)
122 }
123 void minorNumber(unsigned);
136 inline size_t offset() const {
137 if ((data_ & OFFSET_WIDTH_MASK) == EMPTY_PATTERN)
138 return 0;
139 unsigned offsetField = (data_ >> 9) & 0x1ff; // bits 9-17 (9 bits)
140 unsigned widthField = data_ & 0x1ff; // bits 0-8 (9 bits)
141 if (offsetField + widthField == 512)
142 return offsetField;
143 return offsetField;
144 }
145 void offset(size_t);
155 inline size_t nBits() const {
156 if ((data_ & OFFSET_WIDTH_MASK) == EMPTY_PATTERN)
157 return 0;
158 unsigned offsetField = (data_ >> 9) & 0x1ff; // bits 9-17 (9 bits)
159 unsigned widthField = data_ & 0x1ff; // bits 0-8 (9 bits)
160 if (offsetField + widthField == 512)
161 return 0;
162 return widthField + 1;
163 }
164 void nBits(size_t);
172 if (const size_t n = nBits()) {
174 } else {
175 return {};
176 }
177 }
178
187 void setOffsetWidth(size_t offset, size_t nBits);
188
192 bool isEmpty() const {
193 return 0 == nBits();
194 }
195
199 bool isValid() const {
200 return nBits() != 0;
201 }
202
206 uint32_t raw() const {
207 return data_;
208 }
209 void raw(uint32_t r) {
210 data_ = r;
211 }
214 // The following trickery is to have something like "explicit operator bool" before C++11
215private:
216 typedef void(RegisterDescriptor::*unspecified_bool)() const;
217 void this_type_does_not_support_comparisons() const {}
218public:
219 operator unspecified_bool() const {
220 return isEmpty() ? 0 : &RegisterDescriptor::this_type_does_not_support_comparisons;
221 }
222
228 bool operator<(RegisterDescriptor other) const {
229 return data_ < other.data_;
230 }
231
236 bool operator==(RegisterDescriptor other) const {
237 return data_ == other.data_;
238 }
239
244 bool operator!=(RegisterDescriptor other) const {
245 return data_ != other.data_;
246 }
247
254
257
261 unsigned hash() const {
262 return data_;
263 }
264
266 void print(std::ostream &o) const {
267 o <<"{" <<majorNumber() <<"," <<minorNumber() <<"," <<offset() <<"," <<nBits() <<"}";
268 }
269
271 std::string toString() const;
272
273 friend std::ostream& operator<<(std::ostream&, RegisterDescriptor);
274
276 // Old interface (not deprecated yet, just implemented in terms of the new interface)
278
279 unsigned get_major() const {
280 return majorNumber();
281 }
282 bool is_valid() const {
283 return !isEmpty();
284 }
285 RegisterDescriptor &set_major(unsigned majr) {
286 majorNumber(majr);
287 return *this;
288 }
289 unsigned get_minor() const {
290 return minorNumber();
291 }
292 RegisterDescriptor &set_minor(unsigned minr) {
293 this->minorNumber(minr);
294 return *this;
295 }
296 unsigned get_offset() const {
297 return offset();
298 }
299 RegisterDescriptor &set_offset(unsigned offset) {
300 this->offset(offset);
301 return *this;
302 }
303 unsigned get_nbits() const {
304 return nBits();
305 }
306 RegisterDescriptor &set_nbits(unsigned nbits) {
307 this->nBits(nbits);
308 return *this;
309 }
310};
311
312} // namespace
313} // namespace
314
315#endif
316#endif
Describes (part of) a physical CPU register.
bool operator<(RegisterDescriptor other) const
Compare two descriptors.
void raw(uint32_t r)
The raw value of the descriptor.
static RegisterDescriptor fromRaw(uint32_t raw)
Construct a descriptor from a raw value.
void offset(size_t)
Property: Offset to least-significant bit.
static unsigned maxMajor()
Maximum possible major number.
bool operator==(RegisterDescriptor other) const
Check descriptors for equality.
static unsigned maxMinor()
Maximum possible minor number.
static unsigned maxOffset()
Maximum possible bit offset.
void nBits(size_t)
Property: Size in bits.
void majorNumber(unsigned)
Property: Major number.
bool operator!=(RegisterDescriptor other) const
Check descriptors for inequality.
RegisterDescriptor(unsigned majr, unsigned minr, size_t offset, size_t width)
Construct a descriptor from its constituent parts.
RegisterDescriptor()
Create an empty register descriptor.
RegisterDescriptor operator&(RegisterDescriptor other) const
Compute the intersection of two regiter descriptors.
std::string toString() const
Show the properties as a string.
size_t offset() const
Property: Offset to least-significant bit.
void print(std::ostream &o) const
Print all properties.
bool isSubsetOf(RegisterDescriptor other) const
True if this descriptor is a subset of the specified descriptor.
void setOffsetWidth(size_t offset, size_t nBits)
Set offset and size at the same time.
unsigned minorNumber() const
Property: Minor number.
uint32_t raw() const
The raw value of the descriptor.
Sawyer::Container::Interval< size_t > bits() const
Bit range.
bool isEmpty() const
Predicate returns true if the width is zero.
static unsigned maxNBits()
Maximum possible size in bits.
bool isValid() const
Predicate returns true if width is non-zero.
void minorNumber(unsigned)
Property: Minor number.
unsigned majorNumber() const
Property: Major number.
size_t nBits() const
Property: Size in bits.
Range of values delimited by endpoints.
Definition Interval.h:31
static Interval baseSize(T lo, T size)
Construct an interval from one endpoint and a size.
Definition Interval.h:173
The ROSE library.