| /* |
| * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) |
| * |
| * SPDX-License-Identifier: BSD-2-Clause |
| */ |
| |
| #pragma once |
| |
| /* macros for doing basic math */ |
| |
| #include <assert.h> |
| #include <limits.h> |
| #include <stdint.h> |
| #include <utils/attribute.h> |
| #include <utils/builtin.h> |
| #include <stdint.h> |
| #include <utils/verification.h> |
| #include <utils/stringify.h> |
| |
| #define BIT(n) (1ul<<(n)) |
| #define LLBIT(n) (1ull<<(n)) |
| |
| #define MASK_UNSAFE(x) ((BIT(x) - 1ul)) |
| |
| /* The MASK_UNSAFE operation involves using BIT that performs a left shift, this |
| * shift is only defined by the C standard if shifting by 1 less than the |
| * number of bits in a word. MASK allows both the safe creation of masks, and for |
| * creating masks that are larger than what is possible with MASK_UNSAFE, as |
| * MASK_UNSAFE cannot create a MASK that is all 1's */ |
| #define MASK(n) \ |
| __extension__ ({ typeof (n) _n = (n); \ |
| (void)assert((unsigned long)_n <= (sizeof(unsigned long) * 8)); \ |
| (void)assert(_n > 0); \ |
| MASK_UNSAFE(_n - 1) | BIT(_n - 1); \ |
| }) |
| |
| #define IS_ALIGNED(n, b) (!((n) & MASK(b))) |
| |
| /* Calculate the log2 by finding the most significant bit that is set. |
| * We have CLZL, which tells us how many places from the 'left' it is, |
| * and by subtracting that from the number of bits in the word (minus 1) |
| * we learn how many bits from the 'right' it is. */ |
| #define LOG_BASE_2(n) (sizeof(unsigned long) * CHAR_BIT - CLZL(n) - 1) |
| |
| /* Taken from Hacker's Delight, this works on 32 bit integers, |
| * also note that it *will* calculate the *next* power of two, |
| * i.e. NEXT_POWER_OF_2(64) == 128 not 64 */ |
| #define NEXT_POWER_OF_2(x) \ |
| ({ uint32_t temp = (uint32_t) x; \ |
| temp |= (temp >> 1); \ |
| temp |= (temp >> 2); \ |
| temp |= (temp >> 4); \ |
| temp |= (temp >> 8); \ |
| temp |= (temp >> 16); \ |
| temp += 1; \ |
| }) |
| |
| #define IS_POWER_OF_2_OR_ZERO(x) (0 == ((x) & ((x) - 1))) |
| #define IS_POWER_OF_2(x) (((x) != 0) && IS_POWER_OF_2_OR_ZERO(x)) |
| #define ALIGN_UP(x, n) (((x) + (n) - 1) & ~((n) - 1)) |
| #define ALIGN_DOWN(x, n) ((x) & ~((n) - 1)) |
| |
| #define ROUND_DOWN_UNSAFE(n, b) ((n) - ((n) % (b))) |
| |
| #define ROUND_DOWN(n, b) \ |
| ({ typeof (n) _n = (n); \ |
| typeof (b) _b = (b); \ |
| _n - (_n % _b); \ |
| }) |
| |
| #define ROUND_UP_UNSAFE(n, b) ((n) + ((n) % (b) == 0 ? 0 : ((b) - ((n) % (b))))) |
| |
| #define ROUND_UP(n, b) \ |
| ({ typeof (n) _n = (n); \ |
| typeof (b) _b = (b); \ |
| (_n + (_n % _b == 0 ? 0 : (_b - (_n % _b)))); \ |
| }) |
| |
| #define DIV_ROUND_UP(n,d) \ |
| ({ typeof (n) _n = (n); \ |
| typeof (d) _d = (d); \ |
| (_n/_d + (_n % _d == 0 ? 0 : 1)); \ |
| }) |
| |
| /* Divides and rounds to the nearest whole number |
| DIV_ROUND(5,2) returns 3 |
| DIV_ROUND(7,3) returns 2 */ |
| #define DIV_ROUND_UNSAFE(n,d) \ |
| ({ typeof (n) _n = (n); \ |
| typeof (d) _d = (d); \ |
| ((_n + (_d/2)) / _d); \ |
| }) |
| |
| #define DIV_ROUND(n,d) \ |
| ({ typeof (n) _n = (n); \ |
| typeof (d) _d = (d); \ |
| ((_n / _d) + ((_n % _d) >= _d/2 ? 1 : 0)); \ |
| }) |
| |
| #define MIN(a,b) \ |
| ({ typeof (a) _a = (a); \ |
| typeof (b) _b = (b); \ |
| _a < _b ? _a : _b; }) |
| |
| /* used for compile time eval */ |
| #define MIN_UNSAFE(x, y) ((x) < (y) ? (x) : (y)) |
| |
| #define MAX(a,b) \ |
| ({ typeof (a) _a = (a); \ |
| typeof (b) _b = (b); \ |
| _a > _b ? _a : _b; }) |
| |
| /* used for complile time eval */ |
| #define MAX_UNSAFE(x, y) ((x) > (y) ? (x) : (y)) |
| |
| #define INRANGE(a, x, b) MIN(MAX(x, a), b) |
| #define ISINRANGE(a, x, b) \ |
| ({ typeof (x) _x = (x); \ |
| _x == INRANGE(a, _x, b); }) |
| |
| #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) |
| |
| /* Clamp a value between two limits. Sample usage: CLAMP(-3, 7, 4) == 4. */ |
| #define CLAMP(min, value, max) \ |
| ({ typeof (max) _max = (max); \ |
| typeof (min) _min = (min); \ |
| typeof (value) _value = (value); \ |
| if (_value > _max) { \ |
| _value = _max; \ |
| } else if (_value < _min) { \ |
| _value = _min; \ |
| } \ |
| _value; }) |
| |
| /* Clamp an addition. Sample usage: CLAMP_ADD(1<<30, 1<<30, INT_MAX) == INT_MAX. */ |
| #define CLAMP_ADD(operand1, operand2, limit) \ |
| ({ typeof (operand1) _op1 = (operand1); \ |
| typeof (operand2) _op2 = (operand2); \ |
| typeof (limit) _limit = (limit); \ |
| _limit - _op2 < _op1 ? _limit : _op1 + _op2; }) |
| |
| /* Clamp a subtraction. Sample usage: |
| * CLAMP_SUB(-1 * (1<<30), -1 * (1<<30), INT_MIN) == INT_MIN. |
| */ |
| #define CLAMP_SUB(operand1, operand2, limit) \ |
| ({ typeof (operand1) _op1 = (operand1); \ |
| typeof (operand2) _op2 = (operand2); \ |
| typeof (limit) _limit = (limit); \ |
| _limit + _op2 > _op1 ? _limit : _op1 - _op2; }) |
| |
| /* Expands to a struct field declaration suitable for padding structs where each |
| * field must have a specific offset (such as in device drivers). E.g.: |
| * struct device_registers { |
| * uint32_t reg1; // 0x00 |
| * uint32_t reg2; // 0x04 |
| * PAD_BETWEEN(0x04, 0x10, uint32_t); // expands to: uint8_t __padding4[8]; |
| * uint32_t reg3; // 0x10 |
| * } PACKED; |
| * |
| * Using this macro in a struct requires that struct to be defined with |
| * the "packed" attribute. |
| * |
| * @param before offset of struct field before padding |
| * @param after offset of struct field after padding |
| * @param type type of field before padding |
| */ |
| #define PAD_STRUCT_BETWEEN(before, after, type) \ |
| uint8_t JOIN(__padding, __COUNTER__)[(after) - (before) - sizeof(type)] |