1 //===-- RegisterFlags.h -----------------------------------------*- C++ -*-===//
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 #ifndef LLDB_TARGET_REGISTERFLAGS_H
10 #define LLDB_TARGET_REGISTERFLAGS_H
11 
12 #include "lldb/Utility/Log.h"
13 
14 namespace lldb_private {
15 
16 class RegisterFlags {
17 public:
18   class Field {
19   public:
20     Field(std::string name, unsigned start, unsigned end)
21         : m_name(std::move(name)), m_start(start), m_end(end) {
22       assert(m_start <= m_end && "Start bit must be <= end bit.");
23     }
24 
25     /// Get size of the field in bits. Will always be at least 1.
26     unsigned GetSizeInBits() const { return m_end - m_start + 1; }
27 
28     /// A mask that covers all bits of the field.
29     uint64_t GetMask() const {
30       return (((uint64_t)1 << (GetSizeInBits())) - 1) << m_start;
31     }
32 
33     /// Extract value of the field from a whole register value.
34     uint64_t GetValue(uint64_t register_value) const {
35       return (register_value & GetMask()) >> m_start;
36     }
37 
38     const std::string &GetName() const { return m_name; }
39     unsigned GetStart() const { return m_start; }
40     unsigned GetEnd() const { return m_end; }
41     bool Overlaps(const Field &other) const;
42     void log(Log *log) const;
43 
44     /// Return the number of bits between this field and the other, that are not
45     /// covered by either field.
46     unsigned PaddingDistance(const Field &other) const;
47 
48     bool operator<(const Field &rhs) const {
49       return GetStart() < rhs.GetStart();
50     }
51 
52     bool operator==(const Field &rhs) const {
53       return (m_name == rhs.m_name) && (m_start == rhs.m_start) &&
54              (m_end == rhs.m_end);
55     }
56 
57   private:
58     std::string m_name;
59     /// Start/end bit positions. Where start N, end N means a single bit
60     /// field at position N. We expect that start <= end. Bit positions begin
61     /// at 0.
62     /// Start is the LSB, end is the MSB.
63     unsigned m_start;
64     unsigned m_end;
65   };
66 
67   /// This assumes that:
68   /// * There is at least one field.
69   /// * The fields are sorted in descending order.
70   /// Gaps are allowed, they will be filled with anonymous padding fields.
71   RegisterFlags(std::string id, unsigned size,
72                 const std::vector<Field> &fields);
73 
74   // Reverse the order of the fields, keeping their values the same.
75   // For example a field from bit 31 to 30 with value 0b10 will become bits
76   // 1 to 0, with the same 0b10 value.
77   // Use this when you are going to show the register using a bitfield struct
78   // type. If that struct expects MSB first and you are on little endian where
79   // LSB would be first, this corrects that (and vice versa for big endian).
80   template <typename T> T ReverseFieldOrder(T value) const {
81     T ret = 0;
82     unsigned shift = 0;
83     for (auto field : GetFields()) {
84       ret |= field.GetValue(value) << shift;
85       shift += field.GetSizeInBits();
86     }
87 
88     return ret;
89   }
90 
91   const std::vector<Field> &GetFields() const { return m_fields; }
92   const std::string &GetID() const { return m_id; }
93   unsigned GetSize() const { return m_size; }
94   void log(Log *log) const;
95 
96   /// Produce a text table showing the layout of all the fields. Unnamed/padding
97   /// fields will be included, with only their positions shown.
98   /// max_width will be the width in characters of the terminal you are
99   /// going to print the table to. If the table would exceed this width, it will
100   /// be split into many tables as needed.
101   std::string AsTable(uint32_t max_width) const;
102 
103 private:
104   const std::string m_id;
105   /// Size in bytes
106   const unsigned m_size;
107   std::vector<Field> m_fields;
108 };
109 
110 } // namespace lldb_private
111 
112 #endif // LLDB_TARGET_REGISTERFLAGS_H
113