Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:42:54

0001 //===-- RegisterFlags.h -----------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLDB_TARGET_REGISTERFLAGS_H
0010 #define LLDB_TARGET_REGISTERFLAGS_H
0011 
0012 #include <stdint.h>
0013 #include <string>
0014 #include <vector>
0015 
0016 #include "llvm/ADT/StringSet.h"
0017 
0018 namespace lldb_private {
0019 
0020 class Stream;
0021 class Log;
0022 
0023 class FieldEnum {
0024 public:
0025   struct Enumerator {
0026     uint64_t m_value;
0027     // Short name for the value. Shown in tables and when printing the field's
0028     // value. For example "RZ".
0029     std::string m_name;
0030 
0031     Enumerator(uint64_t value, std::string name)
0032         : m_value(value), m_name(std::move(name)) {}
0033 
0034     void ToXML(Stream &strm) const;
0035 
0036     void DumpToLog(Log *log) const;
0037   };
0038 
0039   typedef std::vector<Enumerator> Enumerators;
0040 
0041   // GDB also includes a "size" that is the size of the underlying register.
0042   // We will not store that here but instead use the size of the register
0043   // this gets attached to when emitting XML.
0044   FieldEnum(std::string id, const Enumerators &enumerators);
0045 
0046   const Enumerators &GetEnumerators() const { return m_enumerators; }
0047 
0048   const std::string &GetID() const { return m_id; }
0049 
0050   void ToXML(Stream &strm, unsigned size) const;
0051 
0052   void DumpToLog(Log *log) const;
0053 
0054 private:
0055   std::string m_id;
0056   Enumerators m_enumerators;
0057 };
0058 
0059 class RegisterFlags {
0060 public:
0061   class Field {
0062   public:
0063     /// Where start is the least significant bit and end is the most
0064     /// significant bit. The start bit must be <= the end bit.
0065     Field(std::string name, unsigned start, unsigned end);
0066 
0067     /// Construct a field that also has some known enum values.
0068     Field(std::string name, unsigned start, unsigned end,
0069           const FieldEnum *enum_type);
0070 
0071     /// Construct a field that occupies a single bit.
0072     Field(std::string name, unsigned bit_position);
0073 
0074     /// Get size of the field in bits. Will always be at least 1.
0075     unsigned GetSizeInBits() const;
0076 
0077     /// Identical to GetSizeInBits, but for the GDB client to use.
0078     static unsigned GetSizeInBits(unsigned start, unsigned end);
0079 
0080     /// A mask that covers all bits of the field.
0081     uint64_t GetMask() const;
0082 
0083     /// The maximum unsigned value that could be contained in this field.
0084     uint64_t GetMaxValue() const;
0085 
0086     /// Identical to GetMaxValue but for the GDB client to use.
0087     static uint64_t GetMaxValue(unsigned start, unsigned end);
0088 
0089     /// Extract value of the field from a whole register value.
0090     uint64_t GetValue(uint64_t register_value) const {
0091       return (register_value & GetMask()) >> m_start;
0092     }
0093 
0094     const std::string &GetName() const { return m_name; }
0095     unsigned GetStart() const { return m_start; }
0096     unsigned GetEnd() const { return m_end; }
0097     const FieldEnum *GetEnum() const { return m_enum_type; }
0098     bool Overlaps(const Field &other) const;
0099     void DumpToLog(Log *log) const;
0100 
0101     /// Return the number of bits between this field and the other, that are not
0102     /// covered by either field.
0103     unsigned PaddingDistance(const Field &other) const;
0104 
0105     /// Output XML that describes this field, to be inserted into a target XML
0106     /// file. Reserved characters in field names like "<" are replaced with
0107     /// their XML safe equivalents like "&gt;".
0108     void ToXML(Stream &strm) const;
0109 
0110     bool operator<(const Field &rhs) const {
0111       return GetStart() < rhs.GetStart();
0112     }
0113 
0114     bool operator==(const Field &rhs) const {
0115       return (m_name == rhs.m_name) && (m_start == rhs.m_start) &&
0116              (m_end == rhs.m_end);
0117     }
0118 
0119   private:
0120     std::string m_name;
0121 
0122     /// Start/end bit positions. Where start N, end N means a single bit
0123     /// field at position N. We expect that start <= end. Bit positions begin
0124     /// at 0.
0125     /// Start is the LSB, end is the MSB.
0126     unsigned m_start;
0127     unsigned m_end;
0128 
0129     const FieldEnum *m_enum_type;
0130   };
0131 
0132   /// This assumes that:
0133   /// * There is at least one field.
0134   /// * The fields are sorted in descending order.
0135   /// Gaps are allowed, they will be filled with anonymous padding fields.
0136   RegisterFlags(std::string id, unsigned size,
0137                 const std::vector<Field> &fields);
0138 
0139   /// Replace all the fields with the new set of fields. All the assumptions
0140   /// and checks apply as when you use the constructor. Intended to only be used
0141   /// when runtime field detection is needed.
0142   void SetFields(const std::vector<Field> &fields);
0143 
0144   /// Make a string where each line contains the name of a field that has
0145   /// enum values, and lists what those values are.
0146   std::string DumpEnums(uint32_t max_width) const;
0147 
0148   // Reverse the order of the fields, keeping their values the same.
0149   // For example a field from bit 31 to 30 with value 0b10 will become bits
0150   // 1 to 0, with the same 0b10 value.
0151   // Use this when you are going to show the register using a bitfield struct
0152   // type. If that struct expects MSB first and you are on little endian where
0153   // LSB would be first, this corrects that (and vice versa for big endian).
0154   template <typename T> T ReverseFieldOrder(T value) const {
0155     T ret = 0;
0156     unsigned shift = 0;
0157     for (auto field : GetFields()) {
0158       ret |= field.GetValue(value) << shift;
0159       shift += field.GetSizeInBits();
0160     }
0161 
0162     return ret;
0163   }
0164 
0165   const std::vector<Field> &GetFields() const { return m_fields; }
0166   const std::string &GetID() const { return m_id; }
0167   unsigned GetSize() const { return m_size; }
0168   void DumpToLog(Log *log) const;
0169 
0170   /// Produce a text table showing the layout of all the fields. Unnamed/padding
0171   /// fields will be included, with only their positions shown.
0172   /// max_width will be the width in characters of the terminal you are
0173   /// going to print the table to. If the table would exceed this width, it will
0174   /// be split into many tables as needed.
0175   std::string AsTable(uint32_t max_width) const;
0176 
0177   /// Output XML that describes this set of flags.
0178   /// EnumsToXML should have been called before this.
0179   void ToXML(Stream &strm) const;
0180 
0181   /// Enum types must be defined before use, and
0182   /// GDBRemoteCommunicationServerLLGS view of the register types is based only
0183   /// on the registers. So this method emits any enum types that the upcoming
0184   /// set of fields may need. "seen" is a set of Enum IDs that we have already
0185   /// printed, that is updated with any printed by this call. This prevents us
0186   /// printing the same enum multiple times.
0187   void EnumsToXML(Stream &strm, llvm::StringSet<> &seen) const;
0188 
0189 private:
0190   const std::string m_id;
0191   /// Size in bytes
0192   const unsigned m_size;
0193   std::vector<Field> m_fields;
0194 };
0195 
0196 } // namespace lldb_private
0197 
0198 #endif // LLDB_TARGET_REGISTERFLAGS_H