| //===- CHERICapabilityFormat.cpp ------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/Support/CHERICapabilityFormat.h" | |
| #include "llvm/ADT/bit.h" | |
| namespace llvm { | |
| template <typename AddressType, unsigned MW, unsigned MAX_E> | |
| AddressType RVYCapabilityFormat<AddressType, MW, MAX_E>::getAlignmentMaskImpl( | |
| uint64_t Length) { | |
| static constexpr unsigned int IE_TAKE_BITS = 3; | |
| if (Length == 0) | |
| return RVYCapabilityFormat::AddressMask; | |
| // Extract bits that overflow the uncompressed mantissa window. | |
| uint64_t Slice = static_cast<uint64_t>(Length) >> (MW - 1); | |
| unsigned int E = 64 - llvm::countl_zero(Slice); | |
| // We use internal exponent if length overflows OR the denormal boundary | |
| // bit is set. | |
| bool IE = (E != 0) || ((static_cast<uint64_t>(Length) >> (MW - 2)) & 1); | |
| // Include bits used by the internal exponent for the shift value. | |
| unsigned int Eprime = IE ? (E + IE_TAKE_BITS) : 0; | |
| assert(E <= MAX_E && "Raw exponent exceeds architecture maximum"); | |
| assert(Eprime <= sizeof(AddressType) * 8 && | |
| "Shift amount exceeds integer width"); | |
| // Left-shift ~0 to mask out the lost precision bits | |
| return RVYCapabilityFormat::AddressMask << Eprime; | |
| } | |
| template struct CHERICapabilityFormatBase<RVYCapabilityFormat<uint32_t, 10, 24>, | |
| uint32_t>; | |
| template struct CHERICapabilityFormatBase<RVYCapabilityFormat<uint64_t, 14, 52>, | |
| uint64_t>; | |
| template struct RVYCapabilityFormat<uint32_t, 10, 24>; | |
| template struct RVYCapabilityFormat<uint64_t, 14, 52>; | |
| uint32_t CHERIoTCapabilityFormat::getAlignmentMaskImpl(uint32_t Length) { | |
| // Per section 7.13.4 and table 7.4 in the v1.0 CHERIoT specification. | |
| constexpr uint32_t NINE_SET_BITS = 511; | |
| uint32_t E; | |
| if (Length > NINE_SET_BITS << 14) | |
| E = 24; | |
| else { | |
| E = Length > NINE_SET_BITS ? 32 - llvm::countl_zero(Length) - 9 : 0; | |
| if (Length > NINE_SET_BITS << E) | |
| ++E; | |
| assert(E <= 14 && "CHERIoT capabilities cannot encode E between 14 and 24"); | |
| } | |
| return CHERIoTCapabilityFormat::AddressMask << E; | |
| } | |
| template struct CHERICapabilityFormatBase<CHERIoTCapabilityFormat, uint32_t>; | |
| } // namespace llvm |