[AMDGPU] Add True16 register classes.
[llvm-project.git] / lldb / unittests / Target / RegisterFlagsTest.cpp
blob194e05959c1659941487ed7a74e0fe16dd6e48e3
1 //===-- RegisterFlagsTest.cpp ---------------------------------------------===//
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 //===----------------------------------------------------------------------===//
9 #include "lldb/Target/RegisterFlags.h"
10 #include "gmock/gmock.h"
11 #include "gtest/gtest.h"
13 using namespace lldb_private;
14 using namespace lldb;
16 TEST(RegisterFlagsTest, Field) {
17 // We assume that start <= end is always true, so that is not tested here.
19 RegisterFlags::Field f1("abc", 0, 0);
20 ASSERT_EQ(f1.GetName(), "abc");
21 // start == end means a 1 bit field.
22 ASSERT_EQ(f1.GetSizeInBits(), (unsigned)1);
23 ASSERT_EQ(f1.GetMask(), (uint64_t)1);
24 ASSERT_EQ(f1.GetValue(0), (uint64_t)0);
25 ASSERT_EQ(f1.GetValue(3), (uint64_t)1);
27 // End is inclusive meaning that start 0 to end 1 includes bit 1
28 // to make a 2 bit field.
29 RegisterFlags::Field f2("", 0, 1);
30 ASSERT_EQ(f2.GetSizeInBits(), (unsigned)2);
31 ASSERT_EQ(f2.GetMask(), (uint64_t)3);
32 ASSERT_EQ(f2.GetValue(UINT64_MAX), (uint64_t)3);
33 ASSERT_EQ(f2.GetValue(UINT64_MAX & ~(uint64_t)3), (uint64_t)0);
35 // If the field doesn't start at 0 we need to shift up/down
36 // to account for it.
37 RegisterFlags::Field f3("", 2, 5);
38 ASSERT_EQ(f3.GetSizeInBits(), (unsigned)4);
39 ASSERT_EQ(f3.GetMask(), (uint64_t)0x3c);
40 ASSERT_EQ(f3.GetValue(UINT64_MAX), (uint64_t)0xf);
41 ASSERT_EQ(f3.GetValue(UINT64_MAX & ~(uint64_t)0x3c), (uint64_t)0);
43 // Fields are sorted lowest starting bit first.
44 ASSERT_TRUE(f2 < f3);
45 ASSERT_FALSE(f3 < f1);
46 ASSERT_FALSE(f1 < f2);
47 ASSERT_FALSE(f1 < f1);
50 static RegisterFlags::Field make_field(unsigned start, unsigned end) {
51 return RegisterFlags::Field("", start, end);
54 TEST(RegisterFlagsTest, FieldOverlaps) {
55 // Single bit fields
56 ASSERT_FALSE(make_field(0, 0).Overlaps(make_field(1, 1)));
57 ASSERT_TRUE(make_field(1, 1).Overlaps(make_field(1, 1)));
58 ASSERT_FALSE(make_field(1, 1).Overlaps(make_field(3, 3)));
60 ASSERT_TRUE(make_field(0, 1).Overlaps(make_field(1, 2)));
61 ASSERT_TRUE(make_field(1, 2).Overlaps(make_field(0, 1)));
62 ASSERT_FALSE(make_field(0, 1).Overlaps(make_field(2, 3)));
63 ASSERT_FALSE(make_field(2, 3).Overlaps(make_field(0, 1)));
65 ASSERT_FALSE(make_field(1, 5).Overlaps(make_field(10, 20)));
66 ASSERT_FALSE(make_field(15, 30).Overlaps(make_field(7, 12)));
69 TEST(RegisterFlagsTest, PaddingDistance) {
70 // We assume that this method is always called with a more significant
71 // (start bit is higher) field first and that they do not overlap.
73 // [field 1][field 2]
74 ASSERT_EQ(make_field(1, 1).PaddingDistance(make_field(0, 0)), 0ULL);
75 // [field 1][..][field 2]
76 ASSERT_EQ(make_field(2, 2).PaddingDistance(make_field(0, 0)), 1ULL);
77 // [field 1][field 1][field 2]
78 ASSERT_EQ(make_field(1, 2).PaddingDistance(make_field(0, 0)), 0ULL);
79 // [field 1][30 bits free][field 2]
80 ASSERT_EQ(make_field(31, 31).PaddingDistance(make_field(0, 0)), 30ULL);
83 static void test_padding(const std::vector<RegisterFlags::Field> &fields,
84 const std::vector<RegisterFlags::Field> &expected) {
85 RegisterFlags rf("", 4, fields);
86 EXPECT_THAT(expected, ::testing::ContainerEq(rf.GetFields()));
89 TEST(RegisterFlagsTest, RegisterFlagsPadding) {
90 // When creating a set of flags we assume that:
91 // * There are >= 1 fields.
92 // * They are sorted in descending order.
93 // * There may be gaps between each field.
95 // Needs no padding
96 auto fields =
97 std::vector<RegisterFlags::Field>{make_field(16, 31), make_field(0, 15)};
98 test_padding(fields, fields);
100 // Needs padding in between the fields, single bit.
101 test_padding({make_field(17, 31), make_field(0, 15)},
102 {make_field(17, 31), make_field(16, 16), make_field(0, 15)});
103 // Multiple bits of padding.
104 test_padding({make_field(17, 31), make_field(0, 14)},
105 {make_field(17, 31), make_field(15, 16), make_field(0, 14)});
107 // Padding before first field, single bit.
108 test_padding({make_field(0, 30)}, {make_field(31, 31), make_field(0, 30)});
109 // Multiple bits.
110 test_padding({make_field(0, 15)}, {make_field(16, 31), make_field(0, 15)});
112 // Padding after last field, single bit.
113 test_padding({make_field(1, 31)}, {make_field(1, 31), make_field(0, 0)});
114 // Multiple bits.
115 test_padding({make_field(2, 31)}, {make_field(2, 31), make_field(0, 1)});
117 // Fields need padding before, in between and after.
118 // [31-28][field 27-24][23-22][field 21-20][19-12][field 11-8][7-0]
119 test_padding({make_field(24, 27), make_field(20, 21), make_field(8, 11)},
120 {make_field(28, 31), make_field(24, 27), make_field(22, 23),
121 make_field(20, 21), make_field(12, 19), make_field(8, 11),
122 make_field(0, 7)});
125 TEST(RegisterFieldsTest, ReverseFieldOrder) {
126 // Unchanged
127 RegisterFlags rf("", 4, {make_field(0, 31)});
128 ASSERT_EQ(0x12345678ULL, (unsigned long long)rf.ReverseFieldOrder(0x12345678));
130 // Swap the two halves around.
131 RegisterFlags rf2("", 4, {make_field(16, 31), make_field(0, 15)});
132 ASSERT_EQ(0x56781234ULL, (unsigned long long)rf2.ReverseFieldOrder(0x12345678));
134 // Many small fields.
135 RegisterFlags rf3("", 4,
136 {make_field(31, 31), make_field(30, 30), make_field(29, 29),
137 make_field(28, 28)});
138 ASSERT_EQ(0x00000005ULL, rf3.ReverseFieldOrder(0xA0000000));
141 TEST(RegisterFlagsTest, AsTable) {
142 // Anonymous fields are shown with an empty name cell,
143 // whether they are known up front or added during construction.
144 RegisterFlags anon_field("", 4, {make_field(0, 31)});
145 ASSERT_EQ("| 31-0 |\n"
146 "|------|\n"
147 "| |",
148 anon_field.AsTable(100));
150 RegisterFlags anon_with_pad("", 4, {make_field(16, 31)});
151 ASSERT_EQ("| 31-16 | 15-0 |\n"
152 "|-------|------|\n"
153 "| | |",
154 anon_with_pad.AsTable(100));
156 // Use the wider of position and name to set the column width.
157 RegisterFlags name_wider("", 4, {RegisterFlags::Field("aardvark", 0, 31)});
158 ASSERT_EQ("| 31-0 |\n"
159 "|----------|\n"
160 "| aardvark |",
161 name_wider.AsTable(100));
162 // When the padding is an odd number, put the remaining 1 on the right.
163 RegisterFlags pos_wider("", 4, {RegisterFlags::Field("?", 0, 31)});
164 ASSERT_EQ("| 31-0 |\n"
165 "|------|\n"
166 "| ? |",
167 pos_wider.AsTable(100));
169 // Single bit fields don't need to show start and end, just one of them.
170 RegisterFlags single_bit("", 4, {make_field(31, 31)});
171 ASSERT_EQ("| 31 | 30-0 |\n"
172 "|----|------|\n"
173 "| | |",
174 single_bit.AsTable(100));
176 // Columns are printed horizontally if max width allows.
177 RegisterFlags many_fields("", 4,
178 {RegisterFlags::Field("cat", 28, 31),
179 RegisterFlags::Field("pigeon", 20, 23),
180 RegisterFlags::Field("wolf", 12, 12),
181 RegisterFlags::Field("x", 0, 4)});
182 ASSERT_EQ("| 31-28 | 27-24 | 23-20 | 19-13 | 12 | 11-5 | 4-0 |\n"
183 "|-------|-------|--------|-------|------|------|-----|\n"
184 "| cat | | pigeon | | wolf | | x |",
185 many_fields.AsTable(100));
187 // max_width tells us when we need to split into further tables.
188 // Here no split is needed.
189 RegisterFlags exact_max_single_col("", 4, {RegisterFlags::Field("?", 0, 31)});
190 ASSERT_EQ("| 31-0 |\n"
191 "|------|\n"
192 "| ? |",
193 exact_max_single_col.AsTable(9));
194 RegisterFlags exact_max_two_col(
195 "", 4,
196 {RegisterFlags::Field("?", 16, 31), RegisterFlags::Field("#", 0, 15)});
197 ASSERT_EQ("| 31-16 | 15-0 |\n"
198 "|-------|------|\n"
199 "| ? | # |",
200 exact_max_two_col.AsTable(16));
202 // If max is less than a single column, just print the single column. The user
203 // will have to put up with some wrapping in this niche case.
204 RegisterFlags zero_max_single_col("", 4, {RegisterFlags::Field("?", 0, 31)});
205 ASSERT_EQ("| 31-0 |\n"
206 "|------|\n"
207 "| ? |",
208 zero_max_single_col.AsTable(0));
209 // Same logic for any following columns. Effectively making a "vertical"
210 // table, just with more grid lines.
211 RegisterFlags zero_max_two_col(
212 "", 4,
213 {RegisterFlags::Field("?", 16, 31), RegisterFlags::Field("#", 0, 15)});
214 ASSERT_EQ("| 31-16 |\n"
215 "|-------|\n"
216 "| ? |\n"
217 "\n"
218 "| 15-0 |\n"
219 "|------|\n"
220 "| # |",
221 zero_max_two_col.AsTable(0));
223 RegisterFlags max_less_than_single_col("", 4,
224 {RegisterFlags::Field("?", 0, 31)});
225 ASSERT_EQ("| 31-0 |\n"
226 "|------|\n"
227 "| ? |",
228 max_less_than_single_col.AsTable(3));
229 RegisterFlags max_less_than_two_col(
230 "", 4,
231 {RegisterFlags::Field("?", 16, 31), RegisterFlags::Field("#", 0, 15)});
232 ASSERT_EQ("| 31-16 |\n"
233 "|-------|\n"
234 "| ? |\n"
235 "\n"
236 "| 15-0 |\n"
237 "|------|\n"
238 "| # |",
239 max_less_than_two_col.AsTable(9));
240 RegisterFlags max_many_columns(
241 "", 4,
242 {RegisterFlags::Field("A", 24, 31), RegisterFlags::Field("B", 16, 23),
243 RegisterFlags::Field("C", 8, 15),
244 RegisterFlags::Field("really long name", 0, 7)});
245 ASSERT_EQ("| 31-24 | 23-16 |\n"
246 "|-------|-------|\n"
247 "| A | B |\n"
248 "\n"
249 "| 15-8 |\n"
250 "|------|\n"
251 "| C |\n"
252 "\n"
253 "| 7-0 |\n"
254 "|------------------|\n"
255 "| really long name |",
256 max_many_columns.AsTable(23));