blob: a137b31598317acfdfa9a2a8b9edf29c62a9ff6f [file] [log] [blame]
Karl Meakin88851f92024-05-10 13:59:08 +01001/*
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 */
Karl Meakina5ea9092024-05-28 15:40:33 +010064#define GET_BITS(value, hi, lo) ((value) & GET_BITS_MASK(hi, lo))
Karl Meakin88851f92024-05-10 13:59:08 +010065
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))