• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "aarch64_imm_valid.h"
16 #include <array>
17 #include <iomanip>
18 #include <set>
19 
20 namespace maplebe {
21 const std::set<uint64> ValidBitmaskImmSet = {
22 #include "valid_bitmask_imm.txt"
23 };
24 constexpr uint32 kMaxBitTableSize = 5;
25 constexpr std::array<uint64, kMaxBitTableSize> kBitmaskImmMultTable = {
26     0x0000000100000001UL, 0x0001000100010001UL, 0x0101010101010101UL, 0x1111111111111111UL, 0x5555555555555555UL,
27 };
28 namespace aarch64 {
IsBitmaskImmediate(uint64 val,uint32 bitLen)29 bool IsBitmaskImmediate(uint64 val, uint32 bitLen)
30 {
31     DEBUG_ASSERT(val != 0, "IsBitmaskImmediate() don's accept 0 or -1");
32     DEBUG_ASSERT(static_cast<int64>(val) != -1, "IsBitmaskImmediate() don's accept 0 or -1");
33     if ((bitLen == k32BitSize) && (static_cast<int32>(val) == -1)) {
34         return false;
35     }
36     uint64 val2 = val;
37     if (bitLen == k32BitSize) {
38         val2 = (val2 << k32BitSize) | (val2 & ((1ULL << k32BitSize) - 1));
39     }
40     bool expectedOutcome = (ValidBitmaskImmSet.find(val2) != ValidBitmaskImmSet.end());
41 
42     if ((val & 0x1) != 0) {
43         /*
44          * we want to work with
45          * 0000000000000000000000000000000000000000000001100000000000000000
46          * instead of
47          * 1111111111111111111111111111111111111111111110011111111111111111
48          */
49         val = ~val;
50     }
51 
52     if (bitLen == k32BitSize) {
53         val = (val << k32BitSize) | (val & ((1ULL << k32BitSize) - 1));
54     }
55 
56     /* get the least significant bit set and add it to 'val' */
57     uint64 tmpVal = val + (val & static_cast<uint64>(UINT64_MAX - val + 1));
58 
59     /* now check if tmp is a power of 2 or tmpVal==0. */
60     DEBUG_ASSERT(tmpVal >= 0, "tmpVal -1 should be unsigned");
61     tmpVal = tmpVal & (tmpVal - 1);
62     if (tmpVal == 0) {
63         if (!expectedOutcome) {
64 #if defined(DEBUG) && DEBUG
65             LogInfo::MapleLogger() << "0x" << std::hex << std::setw(static_cast<int>(k16ByteSize)) << std::setfill('0')
66                                    << static_cast<uint64>(val) << "\n";
67 #endif
68             return false;
69         }
70         DEBUG_ASSERT(expectedOutcome, "incorrect implementation: not valid value but returning true");
71         /* power of two or zero ; return true */
72         return true;
73     }
74 
75     int32 p0 = __builtin_ctzll(val);
76     int32 p1 = __builtin_ctzll(tmpVal);
77     int64 diff = p1 - p0;
78 
79     /* check if diff is a power of two; return false if not. */
80     CHECK_FATAL(static_cast<uint64>(diff) >= 1, "value overflow");
81     if ((static_cast<uint64>(diff) & (static_cast<uint64>(diff) - 1)) != 0) {
82         DEBUG_ASSERT(!expectedOutcome, "incorrect implementation: valid value but returning false");
83         return false;
84     }
85 
86     uint32 logDiff = static_cast<uint32>(__builtin_ctzll(static_cast<uint64>(diff)));
87     uint64 pattern = val & ((1ULL << static_cast<uint64>(diff)) - 1);
88 #if defined(DEBUG) && DEBUG
89     bool ret = (val == pattern * kBitmaskImmMultTable[kMaxBitTableSize - logDiff]);
90     DEBUG_ASSERT(expectedOutcome == ret, "incorrect implementation: return value does not match expected outcome");
91     return ret;
92 #else
93     return val == pattern * kBitmaskImmMultTable[kMaxBitTableSize - logDiff];
94 #endif
95 }
96 }  // namespace aarch64
97 }  // namespace maplebe
98