• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1static std::set<uint64> ValidBitmaskImmSet = {
2#include "valid_bitmask_imm.txt"
3};
4constexpr uint32 kMaxBitTableSize = 5;
5constexpr std::array<uint64, kMaxBitTableSize> bitmaskImmMultTable = {
6    0x0000000100000001UL, 0x0001000100010001UL, 0x0101010101010101UL, 0x1111111111111111UL, 0x5555555555555555UL,
7};
8
9bool IsBitSizeImmediate(uint64 val, uint32 bitLen, uint32 nLowerZeroBits) {
10    /* mask1 is a 64bits number that is all 1 shifts left size bits */
11    const uint64 mask1 = 0xffffffffffffffffUL << bitLen;
12    /* mask2 is a 64 bits number that nlowerZeroBits are all 1, higher bits aro all 0 */
13    uint64 mask2 = (1UL << static_cast<uint64>(nLowerZeroBits)) - 1UL;
14    return (mask2 & val) == 0UL && (mask1 & ((static_cast<uint64>(val)) >> nLowerZeroBits)) == 0UL;
15};
16
17bool IsBitmaskImmediate(uint64 val, uint32 bitLen) {
18  DEBUG_ASSERT(val != 0, "IsBitmaskImmediate() don's accept 0 or -1");
19  DEBUG_ASSERT(static_cast<int64>(val) != -1, "IsBitmaskImmediate() don's accept 0 or -1");
20  if ((bitLen == k32BitSize) && (static_cast<int32>(val) == -1)) {
21    return false;
22  }
23  uint64 val2 = val;
24  if (bitLen == k32BitSize) {
25    val2 = (val2 << k32BitSize) | (val2 & ((1ULL << k32BitSize) - 1));
26  }
27  bool expectedOutcome = (ValidBitmaskImmSet.find(val2) != ValidBitmaskImmSet.end());
28
29  if ((val & 0x1) != 0) {
30    /*
31     * we want to work with
32     * 0000000000000000000000000000000000000000000001100000000000000000
33     * instead of
34     * 1111111111111111111111111111111111111111111110011111111111111111
35     */
36    val = ~val;
37  }
38
39  if (bitLen == k32BitSize) {
40    val = (val << k32BitSize) | (val & ((1ULL << k32BitSize) - 1));
41  }
42
43  /* get the least significant bit set and add it to 'val' */
44  uint64 tmpVal = val + (val & static_cast<uint64>(UINT64_MAX - val + 1));
45
46  /* now check if tmp is a power of 2 or tmpVal==0. */
47  tmpVal = tmpVal & (tmpVal - 1);
48  if (tmpVal == 0) {
49    if (!expectedOutcome) {
50      LogInfo::MapleLogger() << "0x" << std::hex << std::setw(static_cast<int>(k16ByteSize)) <<
51          std::setfill('0') << static_cast<uint64>(val) << "\n";
52      return false;
53    }
54    DEBUG_ASSERT(expectedOutcome, "incorrect implementation: not valid value but returning true");
55    /* power of two or zero ; return true */
56    return true;
57  }
58
59  int32 p0 = __builtin_ctzll(val);
60  int32 p1 = __builtin_ctzll(tmpVal);
61  int64 diff = p1 - p0;
62
63  /* check if diff is a power of two; return false if not. */
64  if ((static_cast<uint64>(diff) & (static_cast<uint64>(diff) - 1)) != 0) {
65    DEBUG_ASSERT(!expectedOutcome, "incorrect implementation: valid value but returning false");
66    return false;
67  }
68
69  int32 logDiff = __builtin_ctzll(static_cast<uint64>(diff));
70  int64 pattern = static_cast<int64>(val & ((1ULL << static_cast<uint64>(diff)) - 1));
71#if DEBUG
72  bool ret = (val == pattern * bitmaskImmMultTable[kMaxBitTableSize - logDiff]);
73  DEBUG_ASSERT(expectedOutcome == ret, "incorrect implementation: return value does not match expected outcome");
74  return ret;
75#else
76  return val == pattern * bitmaskImmMultTable[kMaxBitTableSize - logDiff];
77#endif
78}
79
80bool Imm12BitValid(int64 value) {
81  bool result = IsBitSizeImmediate(static_cast<uint64>(value), kMaxImmVal12Bits, 0);
82  // for target linux-aarch64-gnu
83  result = result || IsBitSizeImmediate(static_cast<uint64>(value), kMaxImmVal12Bits, kMaxImmVal12Bits);
84  return result;
85}
86
87bool Imm12BitMaskValid(int64 value) {
88  if (value == 0 || static_cast<int64>(value) == -1) {
89    return true;
90  }
91  return IsBitmaskImmediate(static_cast<uint64>(value), k32BitSize);
92}
93
94bool Imm13BitValid(int64 value) {
95  bool result = IsBitSizeImmediate(static_cast<uint64>(value), kMaxImmVal13Bits, 0);
96  // for target linux-aarch64-gnu
97  result = result || IsBitSizeImmediate(static_cast<uint64>(value), kMaxImmVal13Bits, kMaxImmVal13Bits);
98  return result;
99}
100
101bool Imm13BitMaskValid(int64 value) {
102  if (value == 0 || static_cast<int64>(value) == -1) {
103    return true;
104  }
105  return IsBitmaskImmediate(static_cast<uint64>(value), k64BitSize);
106}
107
108bool Imm16BitValid(int64 value) {
109  bool result = IsBitSizeImmediate(static_cast<uint64>(value), kMaxImmVal16Bits, 0);
110   /*
111    * for target linux-aarch64-gnu
112    * aarch64 assembly takes up to 24-bits immediate, generating
113    * either cmp or cmp with shift 12 encoding
114    */
115  result = result || IsBitSizeImmediate(static_cast<uint64>(value), kMaxImmVal12Bits, kMaxImmVal12Bits);
116  return result;
117}
118
119/*
120 * 8bit         : 0
121 * halfword     : 1
122 * 32bit - word : 2
123 * 64bit - word : 3
124 * 128bit- word : 4
125 */
126bool StrLdrSignedOfstValid(int64 value, uint32 wordSize) {
127  if (value <= k256BitSize && value >= kNegative256BitSize) {
128    return true;
129  } else if ((value > k256BitSize) && (value <= kMaxPimm[wordSize])) {
130    uint64 mask = (1U << wordSize) - 1U;
131    return (static_cast<uint64>(value) & mask) ? false : true;
132  }
133  return false;
134}
135
136
137bool StrLdr8ImmValid(int64 value) {
138  return StrLdrSignedOfstValid(value, 0);
139}
140
141bool StrLdr16ImmValid(int64 value) {
142  return StrLdrSignedOfstValid(value, k1ByteSize);
143}
144
145bool StrLdr32ImmValid(int64 value) {
146  return StrLdrSignedOfstValid(value, k2ByteSize);
147}
148
149bool StrLdr32PairImmValid(int64 value) {
150  if ((value <= kMaxSimm32Pair)  && (value >= kMinSimm32)) {
151    return (static_cast<uint64>(value) & 3) ? false : true;
152  }
153  return false;
154}
155
156bool StrLdr64ImmValid(int64 value) {
157 return StrLdrSignedOfstValid(value, k3ByteSize);
158}
159
160bool StrLdr64PairImmValid(int64 value) {
161  if (value <= kMaxSimm64Pair && (value >= kMinSimm64)) {
162    return (static_cast<uint64>(value) & 7) ? false : true;
163  }
164  return false;
165}
166
167bool StrLdr128ImmValid(int64 value) {
168  return StrLdrSignedOfstValid(value, k4ByteSize);
169}
170
171bool StrLdr128PairImmValid(int64 value) {
172  if (value < k1024BitSize && (value >= kNegative1024BitSize)) {
173    return (static_cast<uint64>(value) & 0xf) ? false : true;
174  }
175  return false;
176}
177