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