xref: /freebsd/contrib/llvm-project/lldb/include/lldb/Target/RegisterFlags.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 <stdint.h>
13 #include <string>
14 #include <vector>
15 
16 #include "llvm/ADT/StringSet.h"
17 
18 namespace lldb_private {
19 
20 class Stream;
21 class Log;
22 
23 class FieldEnum {
24 public:
25   struct Enumerator {
26     uint64_t m_value;
27     // Short name for the value. Shown in tables and when printing the field's
28     // value. For example "RZ".
29     std::string m_name;
30 
EnumeratorEnumerator31     Enumerator(uint64_t value, std::string name)
32         : m_value(value), m_name(std::move(name)) {}
33 
34     void ToXML(Stream &strm) const;
35 
36     void DumpToLog(Log *log) const;
37   };
38 
39   typedef std::vector<Enumerator> Enumerators;
40 
41   // GDB also includes a "size" that is the size of the underlying register.
42   // We will not store that here but instead use the size of the register
43   // this gets attached to when emitting XML.
44   FieldEnum(std::string id, const Enumerators &enumerators);
45 
GetEnumerators()46   const Enumerators &GetEnumerators() const { return m_enumerators; }
47 
GetID()48   const std::string &GetID() const { return m_id; }
49 
50   void ToXML(Stream &strm, unsigned size) const;
51 
52   void DumpToLog(Log *log) const;
53 
54 private:
55   std::string m_id;
56   Enumerators m_enumerators;
57 };
58 
59 class RegisterFlags {
60 public:
61   class Field {
62   public:
63     /// Where start is the least significant bit and end is the most
64     /// significant bit. The start bit must be <= the end bit.
65     Field(std::string name, unsigned start, unsigned end);
66 
67     /// Construct a field that also has some known enum values.
68     Field(std::string name, unsigned start, unsigned end,
69           const FieldEnum *enum_type);
70 
71     /// Construct a field that occupies a single bit.
72     Field(std::string name, unsigned bit_position);
73 
74     /// Get size of the field in bits. Will always be at least 1.
75     unsigned GetSizeInBits() const;
76 
77     /// Identical to GetSizeInBits, but for the GDB client to use.
78     static unsigned GetSizeInBits(unsigned start, unsigned end);
79 
80     /// A mask that covers all bits of the field.
81     uint64_t GetMask() const;
82 
83     /// The maximum unsigned value that could be contained in this field.
84     uint64_t GetMaxValue() const;
85 
86     /// Identical to GetMaxValue but for the GDB client to use.
87     static uint64_t GetMaxValue(unsigned start, unsigned end);
88 
89     /// Extract value of the field from a whole register value.
GetValue(uint64_t register_value)90     uint64_t GetValue(uint64_t register_value) const {
91       return (register_value & GetMask()) >> m_start;
92     }
93 
GetName()94     const std::string &GetName() const { return m_name; }
GetStart()95     unsigned GetStart() const { return m_start; }
GetEnd()96     unsigned GetEnd() const { return m_end; }
GetEnum()97     const FieldEnum *GetEnum() const { return m_enum_type; }
98     bool Overlaps(const Field &other) const;
99     void DumpToLog(Log *log) const;
100 
101     /// Return the number of bits between this field and the other, that are not
102     /// covered by either field.
103     unsigned PaddingDistance(const Field &other) const;
104 
105     /// Output XML that describes this field, to be inserted into a target XML
106     /// file. Reserved characters in field names like "<" are replaced with
107     /// their XML safe equivalents like "&gt;".
108     void ToXML(Stream &strm) const;
109 
110     bool operator<(const Field &rhs) const {
111       return GetStart() < rhs.GetStart();
112     }
113 
114     bool operator==(const Field &rhs) const {
115       return (m_name == rhs.m_name) && (m_start == rhs.m_start) &&
116              (m_end == rhs.m_end);
117     }
118 
119   private:
120     std::string m_name;
121 
122     /// Start/end bit positions. Where start N, end N means a single bit
123     /// field at position N. We expect that start <= end. Bit positions begin
124     /// at 0.
125     /// Start is the LSB, end is the MSB.
126     unsigned m_start;
127     unsigned m_end;
128 
129     const FieldEnum *m_enum_type;
130   };
131 
132   /// This assumes that:
133   /// * There is at least one field.
134   /// * The fields are sorted in descending order.
135   /// Gaps are allowed, they will be filled with anonymous padding fields.
136   RegisterFlags(std::string id, unsigned size,
137                 const std::vector<Field> &fields);
138 
139   /// Replace all the fields with the new set of fields. All the assumptions
140   /// and checks apply as when you use the constructor. Intended to only be used
141   /// when runtime field detection is needed.
142   void SetFields(const std::vector<Field> &fields);
143 
144   /// Make a string where each line contains the name of a field that has
145   /// enum values, and lists what those values are.
146   std::string DumpEnums(uint32_t max_width) const;
147 
148   // Reverse the order of the fields, keeping their values the same.
149   // For example a field from bit 31 to 30 with value 0b10 will become bits
150   // 1 to 0, with the same 0b10 value.
151   // Use this when you are going to show the register using a bitfield struct
152   // type. If that struct expects MSB first and you are on little endian where
153   // LSB would be first, this corrects that (and vice versa for big endian).
ReverseFieldOrder(T value)154   template <typename T> T ReverseFieldOrder(T value) const {
155     T ret = 0;
156     unsigned shift = 0;
157     for (auto field : GetFields()) {
158       ret |= field.GetValue(value) << shift;
159       shift += field.GetSizeInBits();
160     }
161 
162     return ret;
163   }
164 
GetFields()165   const std::vector<Field> &GetFields() const { return m_fields; }
GetID()166   const std::string &GetID() const { return m_id; }
GetSize()167   unsigned GetSize() const { return m_size; }
168   void DumpToLog(Log *log) const;
169 
170   /// Produce a text table showing the layout of all the fields. Unnamed/padding
171   /// fields will be included, with only their positions shown.
172   /// max_width will be the width in characters of the terminal you are
173   /// going to print the table to. If the table would exceed this width, it will
174   /// be split into many tables as needed.
175   std::string AsTable(uint32_t max_width) const;
176 
177   /// Output XML that describes this set of flags.
178   /// EnumsToXML should have been called before this.
179   void ToXML(Stream &strm) const;
180 
181   /// Enum types must be defined before use, and
182   /// GDBRemoteCommunicationServerLLGS view of the register types is based only
183   /// on the registers. So this method emits any enum types that the upcoming
184   /// set of fields may need. "seen" is a set of Enum IDs that we have already
185   /// printed, that is updated with any printed by this call. This prevents us
186   /// printing the same enum multiple times.
187   void EnumsToXML(Stream &strm, llvm::StringSet<> &seen) const;
188 
189 private:
190   const std::string m_id;
191   /// Size in bytes
192   const unsigned m_size;
193   std::vector<Field> m_fields;
194 };
195 
196 } // namespace lldb_private
197 
198 #endif // LLDB_TARGET_REGISTERFLAGS_H
199