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 namespace lldb_private { 17 18 class StreamString; 19 class Log; 20 21 class RegisterFlags { 22 public: 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. Field(std::string name,unsigned bit_position)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. GetSizeInBits()34 unsigned GetSizeInBits() const { return m_end - m_start + 1; } 35 36 /// A mask that covers all bits of the field. GetMask()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. GetValue(uint64_t register_value)42 uint64_t GetValue(uint64_t register_value) const { 43 return (register_value & GetMask()) >> m_start; 44 } 45 GetName()46 const std::string &GetName() const { return m_name; } GetStart()47 unsigned GetStart() const { return m_start; } GetEnd()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 ">". 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). ReverseFieldOrder(T value)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 GetFields()109 const std::vector<Field> &GetFields() const { return m_fields; } GetID()110 const std::string &GetID() const { return m_id; } GetSize()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 124 private: 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