ROSE 0.11.145.247
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
8#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
9#include <boost/serialization/access.hpp>
10#endif
11
12namespace Rose {
13namespace BinaryAnalysis {
14
32 // The major, minor, offset, and size are packed together into this single data member.
33 //
34 // + The major number is the high order four bits at position 28-31 (inclusive) with bit #0 being the LSB.
35 // + The minor number is the 10 bits at position 18-27.
36 // + The offset is the 9 bits at position 9-17, but see note below and offset in [0,511].
37 // + The width-1 is the 9 bits at position 0-8, but see note below and width in [1,512].
38 //
39 // We need to be able to store a width of zero in order to distinguish between valid descriptors and invalid (default
40 // constructed) descriptors, but there aren't enough bits in the width field by itself to do that. We also need to be able
41 // to store and retrive the full range of major, minor, and offset values for zero-width descriptors. To accomplish that,
42 // we use the invarant that the offset+width of a valid descriptor cannot exceed 512 bits. Therefore, if the width field
43 // plus offset field equals 512 then the actual offset is as specified in the range [1,511] and the actual offset is zero;
44 // and if the offset field is 2 and the width field is 511 (the EMPTY_PATTERN constant) then the actual offset and actual
45 // width are both zero.
46 //
47 // There are still unused bit combinations that we could use to extend the ranges of any of the four fields. For instance,
48 // we don't necessarily need to align the fields on bit boundaries. We could use the fact that registers of size R bits need
49 // (R+1)*R/2 values to represent all combinations of offset and size, although this requires integer division to retrieve
50 // the values.
51 uint32_t data_;
52
53 // This pattern represents major=0, minor=0, offset=0, width=0 (offset field = 2, width field = 511)
54 static const uint32_t EMPTY_PATTERN = 0x000005ff; // EMPTY_PATTERN & ~OFFSET_WIDTH_MASK == 0
55 static const uint32_t OFFSET_WIDTH_MASK = 0x0003ffff; // 9-bit offset and 9-bit width
56
57#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
58private:
59 friend class boost::serialization::access;
60
61 template<class S>
62 void serialize(S &s, const unsigned /*version*/) {
63 s & BOOST_SERIALIZATION_NVP(data_);
64 }
65#endif
66
67public:
72 : data_(EMPTY_PATTERN) {}
73
78 RegisterDescriptor(unsigned majr, unsigned minr, size_t offset, size_t width)
79 : data_(0) {
80 majorNumber(majr);
81 minorNumber(minr);
82 setOffsetWidth(offset, width);
83 }
84
86 static RegisterDescriptor fromRaw(uint32_t raw) {
87 RegisterDescriptor retval;
88 retval.data_ = raw;
89 return retval;
90 }
91
93 static unsigned maxMajor();
94
96 static unsigned maxMinor();
97
99 static unsigned maxOffset();
100
104 static unsigned maxNBits();
105
111 unsigned majorNumber() const {
112 return data_ >> 28; // bits 28-31 (4 bits)
113 }
114 void majorNumber(unsigned);
123 unsigned minorNumber() const {
124 return (data_ >> 18) & 0x3ff; // bits 18-27 (10 bits)
125 }
126 void minorNumber(unsigned);
139 inline size_t offset() const {
140 if ((data_ & OFFSET_WIDTH_MASK) == EMPTY_PATTERN)
141 return 0;
142 unsigned offsetField = (data_ >> 9) & 0x1ff; // bits 9-17 (9 bits)
143 unsigned widthField = data_ & 0x1ff; // bits 0-8 (9 bits)
144 if (offsetField + widthField == 512)
145 return offsetField;
146 return offsetField;
147 }
148 void offset(size_t);
158 inline size_t nBits() const {
159 if ((data_ & OFFSET_WIDTH_MASK) == EMPTY_PATTERN)
160 return 0;
161 unsigned offsetField = (data_ >> 9) & 0x1ff; // bits 9-17 (9 bits)
162 unsigned widthField = data_ & 0x1ff; // bits 0-8 (9 bits)
163 if (offsetField + widthField == 512)
164 return 0;
165 return widthField + 1;
166 }
167 void nBits(size_t);
175 if (const size_t n = nBits()) {
177 } else {
178 return {};
179 }
180 }
181
190 void setOffsetWidth(size_t offset, size_t nBits);
191
195 bool isEmpty() const {
196 return 0 == nBits();
197 }
198
202 bool isValid() const {
203 return nBits() != 0;
204 }
205
209 uint32_t raw() const {
210 return data_;
211 }
212 void raw(uint32_t r) {
213 data_ = r;
214 }
217 // The following trickery is to have something like "explicit operator bool" before C++11
218private:
219 typedef void(RegisterDescriptor::*unspecified_bool)() const;
220 void this_type_does_not_support_comparisons() const {}
221public:
222 operator unspecified_bool() const {
223 return isEmpty() ? 0 : &RegisterDescriptor::this_type_does_not_support_comparisons;
224 }
225
231 bool operator<(RegisterDescriptor other) const {
232 return data_ < other.data_;
233 }
234
239 bool operator==(RegisterDescriptor other) const {
240 return data_ == other.data_;
241 }
242
247 bool operator!=(RegisterDescriptor other) const {
248 return data_ != other.data_;
249 }
250
257
260
264 unsigned hash() const {
265 return data_;
266 }
267
269 void print(std::ostream &o) const {
270 o <<"{" <<majorNumber() <<"," <<minorNumber() <<"," <<offset() <<"," <<nBits() <<"}";
271 }
272
274 std::string toString() const;
275
276 friend std::ostream& operator<<(std::ostream&, RegisterDescriptor);
277
279 // Old interface (not deprecated yet, just implemented in terms of the new interface)
281
282 unsigned get_major() const {
283 return majorNumber();
284 }
285 bool is_valid() const {
286 return !isEmpty();
287 }
288 RegisterDescriptor &set_major(unsigned majr) {
289 majorNumber(majr);
290 return *this;
291 }
292 unsigned get_minor() const {
293 return minorNumber();
294 }
295 RegisterDescriptor &set_minor(unsigned minr) {
296 this->minorNumber(minr);
297 return *this;
298 }
299 unsigned get_offset() const {
300 return offset();
301 }
302 RegisterDescriptor &set_offset(unsigned offset) {
303 this->offset(offset);
304 return *this;
305 }
306 unsigned get_nbits() const {
307 return nBits();
308 }
309 RegisterDescriptor &set_nbits(unsigned nbits) {
310 this->nBits(nbits);
311 return *this;
312 }
313};
314
315} // namespace
316} // namespace
317
318#endif
319#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.