1 /* 2 * Copyright 2024 The Hafnium Authors. 3 * 4 * Use of this source code is governed by a BSD-style 5 * license that can be found in the LICENSE file or at 6 * https://opensource.org/licenses/BSD-3-Clause. 7 */ 8 9 #include <stdbool.h> 10 #include <stdint.h> 11 12 #if defined(__ASSEMBLY__) 13 #define STATIC_ASSERT(expr, msg) 0 14 #else 15 #define STATIC_ASSERT(expr, msg) \ 16 __extension__({ \ 17 static_assert(expr, msg); \ 18 0; \ 19 }) 20 #endif 21 22 /** 23 * NOTE: The below macroos use the notation `[hi:lo]` to mean the bits 24 * from `lo` up-to and including `hi`. This matches the notation used in the 25 * FF-A specification. 26 * Examples: 27 * - bits `[4:0]` of `0xAF` are `1111`, 28 * - bits `[7:4]` of `0xAF` are `1010`, 29 * - bits `[31:0]` means the lower half of a 64-bit integer 30 * - bits `[63:32]` means the upper half of a 64-bit integer 31 * - bits `[63:0]` means the whole 64-bit integer 32 */ 33 34 /** 35 * Isolate the `n`th bit of `value`. 36 */ 37 #define GET_BIT(value, n) \ 38 (STATIC_ASSERT((n) < 64, "n out of bounds") + \ 39 ((value) & (UINT64_C(1) << (n)))) 40 41 /** 42 * Return true if the `n`th bit of `value` is 1. 43 */ 44 #define IS_BIT_SET(value, n) (GET_BIT(value, n) != 0) 45 46 /** 47 * Return true if the `n`th bit of `value` is 0. 48 */ 49 #define IS_BIT_UNSET(value, n) (GET_BIT(value, n) == 0) 50 51 /** 52 * Return a mask suitable for isolating bits `[hi:lo]` of a 64-bit 53 * integer. 54 */ 55 #define GET_BITS_MASK(hi, lo) \ 56 (STATIC_ASSERT((hi) < 64, "hi out of bounds") + \ 57 STATIC_ASSERT((hi) >= (lo), "hi must be >= lo") + \ 58 (((~UINT64_C(0)) - (UINT64_C(1) << (lo)) + 1) & \ 59 (~UINT64_C(0) >> (64 - 1 - (hi))))) 60 61 /** 62 * Isolate bits `[hi:lo]` of `value`. 63 */ 64 #define GET_BITS(value, hi, lo) ((value) & GET_BITS_MASK(hi, lo)) 65 66 /** 67 * Return true if any bits `[lo:hi]` of `value` are 1. 68 */ 69 #define ANY_BITS_SET(value, hi, lo) (GET_BITS(value, hi, lo) != 0) 70 71 /** 72 * Return true if all bits `[lo:hi]` of `value` are 1. 73 */ 74 #define ALL_BITS_SET(value, hi, lo) \ 75 (GET_BITS(value, hi, lo) == GET_BITS_MASK(hi, lo)) 76 77 /** 78 * Return true if any bits `[lo:hi]` of `value` are 0. 79 */ 80 #define ANY_BITS_UNSET(value, hi, lo) (!ALL_BITS_SET(value, hi, lo)) 81 82 /** 83 * Return true if all bits `[lo:hi]` of `value` are 0. 84 */ 85 #define ALL_BITS_UNSET(value, hi, lo) (!ANY_BITS_SET(value, hi, lo)) 86