/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Target/RegisterFlags.h
Line | Count | Source |
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 | 284 | : m_name(std::move(name)), m_start(start), m_end(end) { |
22 | 284 | assert(m_start <= m_end && "Start bit must be <= end bit."); |
23 | 284 | } |
24 | | |
25 | | /// Get size of the field in bits. Will always be at least 1. |
26 | 306 | unsigned GetSizeInBits() const { return m_end - m_start + 1; } |
27 | | |
28 | | /// A mask that covers all bits of the field. |
29 | 72 | uint64_t GetMask() const { |
30 | 72 | return (((uint64_t)1 << (GetSizeInBits())) - 1) << m_start; |
31 | 72 | } |
32 | | |
33 | | /// Extract value of the field from a whole register value. |
34 | 69 | uint64_t GetValue(uint64_t register_value) const { |
35 | 69 | return (register_value & GetMask()) >> m_start; |
36 | 69 | } |
37 | | |
38 | 93 | const std::string &GetName() const { return m_name; } |
39 | 2.01k | unsigned GetStart() const { return m_start; } |
40 | 608 | 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 | 601 | bool operator<(const Field &rhs) const { |
49 | 601 | return GetStart() < rhs.GetStart(); |
50 | 601 | } |
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 | 24 | template <typename T> T ReverseFieldOrder(T value) const { |
81 | 24 | T ret = 0; |
82 | 24 | unsigned shift = 0; |
83 | 60 | for (auto field : GetFields()) { |
84 | 60 | ret |= field.GetValue(value) << shift; |
85 | 60 | shift += field.GetSizeInBits(); |
86 | 60 | } |
87 | | |
88 | 24 | return ret; |
89 | 24 | } unsigned int lldb_private::RegisterFlags::ReverseFieldOrder<unsigned int>(unsigned int) const Line | Count | Source | 80 | 19 | template <typename T> T ReverseFieldOrder(T value) const { | 81 | 19 | T ret = 0; | 82 | 19 | unsigned shift = 0; | 83 | 49 | for (auto field : GetFields()) { | 84 | 49 | ret |= field.GetValue(value) << shift; | 85 | 49 | shift += field.GetSizeInBits(); | 86 | 49 | } | 87 | | | 88 | 19 | return ret; | 89 | 19 | } |
unsigned long long lldb_private::RegisterFlags::ReverseFieldOrder<unsigned long long>(unsigned long long) const Line | Count | Source | 80 | 5 | template <typename T> T ReverseFieldOrder(T value) const { | 81 | 5 | T ret = 0; | 82 | 5 | unsigned shift = 0; | 83 | 11 | for (auto field : GetFields()) { | 84 | 11 | ret |= field.GetValue(value) << shift; | 85 | 11 | shift += field.GetSizeInBits(); | 86 | 11 | } | 87 | | | 88 | 5 | return ret; | 89 | 5 | } |
|
90 | | |
91 | 57 | const std::vector<Field> &GetFields() const { return m_fields; } |
92 | 1 | const std::string &GetID() const { return m_id; } |
93 | 55 | 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 |