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 ">". 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