1/*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include "utils/regmask.h"
16
17#include <gtest/gtest.h>
18#include <bitset>
19
20namespace panda::test {
21
22using BitsetType = std::bitset<RegMask::Size()>;
23
24void CompareWithBitset(RegMask mask, BitsetType base)
25{
26    ASSERT_EQ(mask.Count(), base.count());
27    if (base.any()) {
28        ASSERT_EQ(mask.GetMinRegister(), static_cast<uint32_t>(Ctz(base.to_ulong())));
29        ASSERT_EQ(mask.GetMaxRegister(), base.size() - Clz(static_cast<RegMask::ValueType>(base.to_ulong())) - 1);
30    }
31    ASSERT_EQ(mask.Size(), base.size());
32    ASSERT_EQ(mask.Any(), base.any());
33    ASSERT_EQ(mask.None(), base.none());
34    for (size_t i = 0; i < base.size(); i++) {
35        ASSERT_EQ(mask.Test(i), base.test(i));
36        ASSERT_EQ(mask[i], base[i]);
37    }
38}
39
40void TestRegMask(RegMask::ValueType value)
41{
42    RegMask mask(value);
43    BitsetType base(value);
44    CompareWithBitset(mask, base);
45    for (size_t i = 0; i < base.size(); i++) {
46        mask.set(i);
47        base.set(i);
48        CompareWithBitset(mask, base);
49        mask.reset(i);
50        base.reset(i);
51        CompareWithBitset(mask, base);
52    }
53    mask.Set();
54    base.set();
55    CompareWithBitset(mask, base);
56    mask.Reset();
57    base.reset();
58    CompareWithBitset(mask, base);
59}
60
61void TestDistance(RegMask mask, size_t bit, size_t bits_before, size_t bits_after)
62{
63    ASSERT_EQ(mask.GetDistanceFromTail(bit), bits_before);
64    ASSERT_EQ(mask.GetDistanceFromHead(bit), bits_after);
65}
66
67HWTEST(RegMask, Base, testing::ext::TestSize.Level0)
68{
69    TestRegMask(MakeMask(0, 3, 2, 17, 25, 31));
70    TestRegMask(MakeMask(1, 4, 8, 3, 24, 28, 30));
71    TestRegMask(MakeMaskByExcluding(32, 0));
72    TestRegMask(MakeMaskByExcluding(32, 31));
73    TestRegMask(MakeMaskByExcluding(32, 0, 31));
74    TestRegMask(MakeMaskByExcluding(32, 0, 15, 31));
75    TestRegMask(0U);
76    TestRegMask(~0U);
77
78    RegMask mask(MakeMask(0, 2, 3, 17, 25, 31));
79    TestDistance(mask, 0, 0, 5);
80    TestDistance(mask, 1, 1, 5);
81    TestDistance(mask, 2, 1, 4);
82    TestDistance(mask, 3, 2, 3);
83    TestDistance(mask, 4, 3, 3);
84    TestDistance(mask, 17, 3, 2);
85    TestDistance(mask, 18, 4, 2);
86    TestDistance(mask, 31, 5, 0);
87}
88
89HWTEST(RegMask, SetAndDumpTest, testing::ext::TestSize.Level0)
90{
91    RegMask mask(MakeMask(1, 2, 3));
92    ASSERT_EQ(mask.GetValue(), 14U);
93
94    mask.Set(1U, false);
95    ASSERT_EQ(mask.GetValue(), 12U);
96
97    mask.Set(5U, true);
98    ASSERT_EQ(mask.GetValue(), 44U);
99}
100
101}  // namespace panda::test