ROSE  0.9.9.109
RegisterDescriptor.h
1 #ifndef Rose_BinaryAnalysis_RegisterDescriptor_H
2 #define Rose_BinaryAnalysis_RegisterDescriptor_H
3 
4 #include <boost/serialization/access.hpp>
5 
6 // FIXME[Robb Matzke 2017-08-04]: Not in Rose::BinaryAnalysis yet (for backward compatibility), but should be.
7 
8 
26  // The major, minor, offset, and size are packed together into this single data member.
27  //
28  // + The major number is the high order four bits at position 28-31 (inclusive) with bit #0 being the LSB.
29  // + The minor number is the 10 bits at position 18-27.
30  // + The offset is the 9 bits at position 9-17, but see note below and offset in [0,511].
31  // + The width-1 is the 9 bits at position 0-8, but see note below and width in [1,512].
32  //
33  // We need to be able to store a width of zero in order to distinguish between valid descriptors and invalid (default
34  // constructed) descriptors, but there aren't enough bits in the width field by itself to do that. We also need to be able
35  // to store and retrive the full range of major, minor, and offset values for zero-width descriptors. To accomplish that,
36  // we use the invarant that the offset+width of a valid descriptor cannot exceed 512 bits. Therefore, if the width field
37  // plus offset field equals 512 then the actual offset is as specified in the range [1,511] and the actual offset is zero;
38  // and if the offset field is 2 and the width field is 511 (the EMPTY_PATTERN constant) then the actual offset and actual
39  // width are both zero.
40  //
41  // There are still unused bit combinations that we could use to extend the ranges of any of the four fields. For instance,
42  // we don't necessarily need to align the fields on bit boundaries. We could use the fact that registers of size R bits need
43  // (R+1)*R/2 values to represent all combinations of offset and size, although this requires integer division to retrieve
44  // the values.
45  uint32_t data_;
46 
47  // This pattern represents major=0, minor=0, offset=0, width=0 (offset field = 2, width field = 511)
48  static const uint32_t EMPTY_PATTERN = 0x000005ff; // EMPTY_PATTERN & ~OFFSET_WIDTH_MASK == 0
49  static const uint32_t OFFSET_WIDTH_MASK = 0x0003ffff; // 9-bit offset and 9-bit width
50 
51 #ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
52 private:
53  friend class boost::serialization::access;
54 
55  template<class S>
56  void serialize(S &s, const unsigned version) {
57  s & BOOST_SERIALIZATION_NVP(data_);
58  }
59 #endif
60 
61 public:
66  : data_(EMPTY_PATTERN) {}
67 
72  RegisterDescriptor(unsigned majr, unsigned minr, size_t offset, size_t width)
73  : data_(0) {
74  majorNumber(majr);
75  minorNumber(minr);
76  setOffsetWidth(offset, width);
77  }
78 
84  unsigned majorNumber() const {
85  return data_ >> 28; // bits 28-31 (4 bits)
86  }
87  void majorNumber(unsigned);
96  unsigned minorNumber() const {
97  return (data_ >> 18) & 0x3ff; // bits 18-27 (10 bits)
98  }
99  void minorNumber(unsigned);
112  inline size_t offset() const {
113  if ((data_ & OFFSET_WIDTH_MASK) == EMPTY_PATTERN)
114  return 0;
115  unsigned offsetField = (data_ >> 9) & 0x1ff; // bits 9-17 (9 bits)
116  unsigned widthField = data_ & 0x1ff; // bits 0-8 (9 bits)
117  if (offsetField + widthField == 512)
118  return offsetField;
119  return offsetField;
120  }
121  void offset(size_t);
131  inline size_t nBits() const {
132  if ((data_ & OFFSET_WIDTH_MASK) == EMPTY_PATTERN)
133  return 0;
134  unsigned offsetField = (data_ >> 9) & 0x1ff; // bits 9-17 (9 bits)
135  unsigned widthField = data_ & 0x1ff; // bits 0-8 (9 bits)
136  if (offsetField + widthField == 512)
137  return 0;
138  return widthField + 1;
139  }
140  void nBits(size_t);
151  void setOffsetWidth(size_t offset, size_t nBits);
152 
156  bool isEmpty() const {
157  return 0 == nBits();
158  }
159 
165  bool operator<(RegisterDescriptor other) const {
166  return data_ < other.data_;
167  }
168 
173  bool operator==(RegisterDescriptor other) const {
174  return data_ == other.data_;
175  }
176 
181  bool operator!=(RegisterDescriptor other) const {
182  return data_ != other.data_;
183  }
184 
188  unsigned hash() const {
189  return data_;
190  }
191 
193  void print(std::ostream &o) const {
194  o <<"{" <<majorNumber() <<"," <<minorNumber() <<"," <<offset() <<"," <<nBits() <<"}";
195  }
196 
197  friend std::ostream& operator<<(std::ostream&, RegisterDescriptor);
198 
200  // Old interface (not deprecated yet, just implemented in terms of the new interface)
202 
203  unsigned get_major() const {
204  return majorNumber();
205  }
206  bool is_valid() const {
207  return !isEmpty();
208  }
209  RegisterDescriptor &set_major(unsigned majr) {
210  majorNumber(majr);
211  return *this;
212  }
213  unsigned get_minor() const {
214  return minorNumber();
215  }
216  RegisterDescriptor &set_minor(unsigned minr) {
217  this->minorNumber(minr);
218  return *this;
219  }
220  unsigned get_offset() const {
221  return offset();
222  }
223  RegisterDescriptor &set_offset(unsigned offset) {
224  this->offset(offset);
225  return *this;
226  }
227  unsigned get_nbits() const {
228  return nBits();
229  }
230  RegisterDescriptor &set_nbits(unsigned nbits) {
231  this->nBits(nbits);
232  return *this;
233  }
234 };
235 
236 #endif
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.
bool operator==(RegisterDescriptor other) const
Check descriptors for equality.
Describes (part of) a physical CPU register.
size_t offset() const
Property: Offset to least-significant bit.
unsigned minorNumber() const
Property: Minor number.
bool operator<(RegisterDescriptor other) const
Compare two descriptors.
size_t nBits() const
Property: Size in bits.
unsigned hash() const
Hash value.
void setOffsetWidth(size_t offset, size_t nBits)
Set offset and size at the same time.
void print(std::ostream &o) const
Print all properties.
unsigned majorNumber() const
Property: Major number.
bool isEmpty() const
Predicate returns true if the width is zero.
RegisterDescriptor()
Create an empty register descriptor.