summaryrefslogtreecommitdiff
path: root/src/commonlib/include/commonlib/helpers.h
blob: f3b71d7016adc3a759f3b78df6d4e0f5d0f6c0d8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
 * This file is part of the coreboot project.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifndef COMMONLIB_HELPERS_H
#define COMMONLIB_HELPERS_H
/* This file is for helpers for both coreboot firmware and its utilities. */

#ifndef __ASSEMBLER__
#include <commonlib/compiler.h>
#include <stddef.h>
#endif

#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#endif

#define ALIGN(x, a)             __ALIGN_MASK(x, (__typeof__(x))(a)-1UL)
#define __ALIGN_MASK(x, mask)   (((x)+(mask))&~(mask))
#define ALIGN_UP(x, a)          ALIGN((x), (a))
#define ALIGN_DOWN(x, a)        ((x) & ~((__typeof__(x))(a)-1UL))
#define IS_ALIGNED(x, a)        (((x) & ((__typeof__(x))(a)-1UL)) == 0)

/* Double-evaluation unsafe min/max, for bitfields and outside of functions */
#define __CMP_UNSAFE(a, b, op) ((a) op (b) ? (a) : (b))
#define MIN_UNSAFE(a, b) __CMP_UNSAFE(a, b, <)
#define MAX_UNSAFE(a, b) __CMP_UNSAFE(a, b, >)

#define __CMP_SAFE(a, b, op, var_a, var_b) ({ \
	__TYPEOF_UNLESS_CONST(a, b) var_a = (a); \
	__TYPEOF_UNLESS_CONST(b, a) var_b = (b); \
	var_a op var_b ? var_a : var_b; \
})

#ifdef __ROMCC__	/* romcc doesn't support __builtin_choose_expr() */
#define __CMP(a, b, op) __CMP_UNSAFE(a, b, op)
#else
#define __CMP(a, b, op) __builtin_choose_expr( \
	__builtin_constant_p(a) && __builtin_constant_p(b), \
	__CMP_UNSAFE(a, b, op), __CMP_SAFE(a, b, op, __TMPNAME, __TMPNAME))
#endif

#ifndef MIN
#define MIN(a, b) __CMP(a, b, <)
#endif
#ifndef MAX
#define MAX(a, b) __CMP(a, b, >)
#endif

#ifndef ABS
#define ABS(a) ({ \
	__typeof__(a) _abs_local_a = (a); \
	(_abs_local_a < 0) ? (-_abs_local_a) : _abs_local_a; \
})
#endif

#define IS_POWER_OF_2(x) ({ \
	__typeof__(x) _power_local_x = (x); \
	(_power_local_x & (_power_local_x - 1)) == 0; \
})

#define DIV_ROUND_UP(x, y) ({ \
	__typeof__(x) _div_local_x = (x); \
	__typeof__(y) _div_local_y = (y); \
	(_div_local_x + _div_local_y - 1) / _div_local_y; \
})

#define SWAP(a, b) do { \
	__typeof__(&(a)) _swap_local_a = &(a); \
	__typeof__(&(b)) _swap_local_b = &(b); \
	__typeof__(a) _swap_local_tmp = *_swap_local_a; \
	*_swap_local_a = *_swap_local_b; \
	*_swap_local_b = _swap_local_tmp; \
} while (0)

/*
 * Divide positive or negative dividend by positive divisor and round
 * to closest integer. Result is undefined for negative divisors and
 * for negative dividends if the divisor variable type is unsigned.
 */
#define DIV_ROUND_CLOSEST(x, divisor)({					\
	__typeof__(x) _div_local_x = (x);				\
	__typeof__(divisor) _div_local_d = (divisor);			\
	(((__typeof__(x))-1) > 0 ||					\
	 ((__typeof__(divisor))-1) > 0 || (_div_local_x) > 0) ?		\
		((_div_local_x + (_div_local_d / 2)) / _div_local_d) :	\
		((_div_local_x - (_div_local_d / 2)) / _div_local_d);	\
})

/* Standard units. */
#define KiB (1<<10)
#define MiB (1<<20)
#define GiB (1<<30)
/* Could we ever run into this one? I hope we get this much memory! */
#define TiB (1<<40)

#define KHz (1000)
#define MHz (1000 * KHz)
#define GHz (1000 * MHz)

#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif

#if !defined(__clang__)
#define check_member(structure, member, offset) _Static_assert( \
	offsetof(struct structure, member) == offset, \
	"`struct " #structure "` offset for `" #member "` is not " #offset)
#else
#define check_member(structure, member, offset)
#endif

/**
 * container_of - cast a member of a structure out to the containing structure
 * @param ptr:    the pointer to the member.
 * @param type:   the type of the container struct this is embedded in.
 * @param member: the name of the member within the struct.
 *
 */
#define container_of(ptr, type, member) ({			\
	const __typeof__(((type *)0)->member) *__mptr = (ptr);	\
	(type *)((char *)__mptr - offsetof(type, member)); })

/* Calculate size of structure member. */
#define member_size(type, member)	(sizeof(((type *)0)->member))

#ifndef __unused
#define __unused __attribute__((unused))
#endif

#ifndef alloca
#define alloca(x) __builtin_alloca(x)
#endif

#endif /* COMMONLIB_HELPERS_H */