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