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