| //===-- RegisterFlags.h -----------------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLDB_TARGET_REGISTERFLAGS_H |
| #define LLDB_TARGET_REGISTERFLAGS_H |
| |
| #include <stdint.h> |
| #include <string> |
| #include <vector> |
| |
| namespace lldb_private { |
| |
| class StreamString; |
| class Log; |
| |
| class RegisterFlags { |
| public: |
| class Field { |
| public: |
| /// Where start is the least significant bit and end is the most |
| /// significant bit. The start bit must be <= the end bit. |
| Field(std::string name, unsigned start, unsigned end); |
| |
| /// Construct a field that occupies a single bit. |
| Field(std::string name, unsigned bit_position) |
| : m_name(std::move(name)), m_start(bit_position), m_end(bit_position) {} |
| |
| /// Get size of the field in bits. Will always be at least 1. |
| unsigned GetSizeInBits() const { return m_end - m_start + 1; } |
| |
| /// A mask that covers all bits of the field. |
| uint64_t GetMask() const { |
| return (((uint64_t)1 << (GetSizeInBits())) - 1) << m_start; |
| } |
| |
| /// Extract value of the field from a whole register value. |
| uint64_t GetValue(uint64_t register_value) const { |
| return (register_value & GetMask()) >> m_start; |
| } |
| |
| const std::string &GetName() const { return m_name; } |
| unsigned GetStart() const { return m_start; } |
| unsigned GetEnd() const { return m_end; } |
| bool Overlaps(const Field &other) const; |
| void log(Log *log) const; |
| |
| /// Return the number of bits between this field and the other, that are not |
| /// covered by either field. |
| unsigned PaddingDistance(const Field &other) const; |
| |
| /// Output XML that describes this field, to be inserted into a target XML |
| /// file. Reserved characters in field names like "<" are replaced with |
| /// their XML safe equivalents like ">". |
| void ToXML(StreamString &strm) const; |
| |
| bool operator<(const Field &rhs) const { |
| return GetStart() < rhs.GetStart(); |
| } |
| |
| bool operator==(const Field &rhs) const { |
| return (m_name == rhs.m_name) && (m_start == rhs.m_start) && |
| (m_end == rhs.m_end); |
| } |
| |
| private: |
| std::string m_name; |
| /// Start/end bit positions. Where start N, end N means a single bit |
| /// field at position N. We expect that start <= end. Bit positions begin |
| /// at 0. |
| /// Start is the LSB, end is the MSB. |
| unsigned m_start; |
| unsigned m_end; |
| }; |
| |
| /// This assumes that: |
| /// * There is at least one field. |
| /// * The fields are sorted in descending order. |
| /// Gaps are allowed, they will be filled with anonymous padding fields. |
| RegisterFlags(std::string id, unsigned size, |
| const std::vector<Field> &fields); |
| |
| /// Replace all the fields with the new set of fields. All the assumptions |
| /// and checks apply as when you use the constructor. Intended to only be used |
| /// when runtime field detection is needed. |
| void SetFields(const std::vector<Field> &fields); |
| |
| // Reverse the order of the fields, keeping their values the same. |
| // For example a field from bit 31 to 30 with value 0b10 will become bits |
| // 1 to 0, with the same 0b10 value. |
| // Use this when you are going to show the register using a bitfield struct |
| // type. If that struct expects MSB first and you are on little endian where |
| // LSB would be first, this corrects that (and vice versa for big endian). |
| template <typename T> T ReverseFieldOrder(T value) const { |
| T ret = 0; |
| unsigned shift = 0; |
| for (auto field : GetFields()) { |
| ret |= field.GetValue(value) << shift; |
| shift += field.GetSizeInBits(); |
| } |
| |
| return ret; |
| } |
| |
| const std::vector<Field> &GetFields() const { return m_fields; } |
| const std::string &GetID() const { return m_id; } |
| unsigned GetSize() const { return m_size; } |
| void log(Log *log) const; |
| |
| /// Produce a text table showing the layout of all the fields. Unnamed/padding |
| /// fields will be included, with only their positions shown. |
| /// max_width will be the width in characters of the terminal you are |
| /// going to print the table to. If the table would exceed this width, it will |
| /// be split into many tables as needed. |
| std::string AsTable(uint32_t max_width) const; |
| |
| // Output XML that describes this set of flags. |
| void ToXML(StreamString &strm) const; |
| |
| private: |
| const std::string m_id; |
| /// Size in bytes |
| const unsigned m_size; |
| std::vector<Field> m_fields; |
| }; |
| |
| } // namespace lldb_private |
| |
| #endif // LLDB_TARGET_REGISTERFLAGS_H |