1/*
2 * Copyright 2014, General Dynamics C4 Systems
3 *
4 * This software may be distributed and modified according to the terms of
5 * the GNU General Public License version 2. Note that NO WARRANTY is provided.
6 * See "LICENSE_GPLv2.txt" for details.
7 *
8 * @TAG(GD_GPL)
9 */
10
11#ifndef __UTIL_H
12#define __UTIL_H
13
14#define MASK(n) (BIT(n)-1ul)
15#define IS_ALIGNED(n, b) (!((n) & MASK(b)))
16#define ROUND_DOWN(n, b) (((n) >> (b)) << (b))
17#define ROUND_UP(n, b) (((((n) - 1ul) >> (b)) + 1ul) << (b))
18#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
19#define MIN(a, b) ((a) < (b) ? (a) : (b))
20#define MAX(a,b) (((a)>(b))?(a):(b))
21#define PASTE(a, b) a ## b
22#define _STRINGIFY(a) #a
23#define STRINGIFY(a) _STRINGIFY(a)
24
25/* time constants */
26#define MS_IN_S     1000llu
27#define US_IN_MS    1000llu
28#define HZ_IN_KHZ   1000llu
29#define KHZ_IN_MHZ  1000llu
30#define HZ_IN_MHZ   1000000llu
31
32#ifndef __ASSEMBLER__
33
34#define NULL ((void *)0)
35#define BIT(n) (1ul << (n))
36#define UL_CONST(x) PASTE(x, ul)
37
38#define PACKED       __attribute__((packed))
39#define NORETURN     __attribute__((__noreturn__))
40#define CONST        __attribute__((__const__))
41#define PURE         __attribute__((__pure__))
42#define ALIGN(n)     __attribute__((__aligned__(n)))
43#define FASTCALL     __attribute__((fastcall))
44#ifdef __clang__
45#define VISIBLE      /* nothing */
46#else
47#define VISIBLE      __attribute__((externally_visible))
48#endif
49#define NO_INLINE    __attribute__((noinline))
50#define FORCE_INLINE __attribute__((always_inline))
51#define SECTION(sec) __attribute__((__section__(sec)))
52#define UNUSED       __attribute__((unused))
53#define USED         __attribute__((used))
54#define FASTCALL     __attribute__((fastcall))
55#define FORCE_O2     __attribute__((optimize("O2")))
56/** MODIFIES: */
57void __builtin_unreachable(void);
58#define UNREACHABLE()  __builtin_unreachable()
59#define MAY_ALIAS    __attribute__((may_alias))
60
61#define OFFSETOF(type, member) \
62    __builtin_offsetof(type, member)
63
64#ifdef __GNUC__
65/* Borrowed from linux/include/linux/compiler.h */
66#define likely(x)   __builtin_expect(!!(x), 1)
67#define unlikely(x) __builtin_expect(!!(x), 0)
68#else
69#define likely(x)   (!!(x))
70#define unlikely(x) (!!(x))
71#endif
72
73/* need that for compiling with c99 instead of gnu99 */
74#define asm __asm__
75
76/* Evaluate a Kconfig-provided configuration setting at compile-time. */
77#define config_set(macro) _is_set_(macro)
78#define _macrotest_1 ,
79#define _is_set_(value) _is_set__(_macrotest_##value)
80#define _is_set__(comma) _is_set___(comma 1, 0)
81#define _is_set___(_, v, ...) v
82
83/* Check the existence of a configuration setting, returning one value if it
84 * exists and a different one if it does not */
85#define config_ternary(macro, true, false) _config_ternary(macro, true, false)
86#define _config_ternary(value, true, false) _config_ternary_(_macrotest_##value, true, false)
87#define _config_ternary_(comma, true, false) _config_ternary__(comma true, false)
88#define _config_ternary__(_, v, ...) v
89
90/** MODIFIES:
91    FNSPEC
92        halt_spec: "\<Gamma> \<turnstile> {} Call halt_'proc {}"
93*/
94void halt(void) NORETURN;
95void memzero(void *s, unsigned long n);
96void *memset(void *s, unsigned long c, unsigned long n) VISIBLE;
97void *memcpy(void* ptr_dst, const void* ptr_src, unsigned long n) VISIBLE;
98int PURE strncmp(const char *s1, const char *s2, int n);
99long CONST char_to_long(char c);
100long PURE str_to_long(const char* str);
101
102
103int __builtin_clzl (unsigned long x);
104int __builtin_ctzl (unsigned long x);
105
106#ifdef CONFIG_ARCH_RISCV
107uint32_t __clzsi2(uint32_t x);
108uint32_t __ctzsi2(uint32_t x);
109uint32_t __clzdi2(uint64_t x);
110uint32_t __ctzdi2(uint64_t x);
111#endif
112/** MODIFIES: */
113/** DONT_TRANSLATE */
114/** FNSPEC clzl_spec:
115  "\<forall>s. \<Gamma> \<turnstile>
116    {\<sigma>. s = \<sigma> \<and> x_' s \<noteq> 0 }
117      \<acute>ret__long :== PROC clzl(\<acute>x)
118    \<lbrace> \<acute>ret__long = of_nat (word_clz (x_' s)) \<rbrace>"
119*/
120static inline long
121CONST clzl(unsigned long x)
122{
123    return __builtin_clzl(x);
124}
125
126/** MODIFIES: */
127/** DONT_TRANSLATE */
128/** FNSPEC ctzl_spec:
129  "\<forall>s. \<Gamma> \<turnstile>
130    {\<sigma>. s = \<sigma> \<and> x_' s \<noteq> 0 }
131      \<acute>ret__long :== PROC ctzl(\<acute>x)
132    \<lbrace> \<acute>ret__long = of_nat (word_ctz (x_' s)) \<rbrace>"
133*/
134static inline long
135CONST ctzl(unsigned long x)
136{
137    return __builtin_ctzl(x);
138}
139
140#define CTZL(x) __builtin_ctzl(x)
141
142/** DONT_TRANSLATE */
143/** FNSPEC clzl_spec:
144  "\<forall>s. \<Gamma> \<turnstile>
145    {\<sigma>. s = \<sigma> \<and> x_' s \<noteq> 0 }
146      \<acute>ret__long :== PROC clzl(\<acute>x)
147    \<lbrace> \<acute>ret__long = of_nat (word_clz (x_' s)) \<rbrace>"
148*/
149static inline long long
150CONST clzll(unsigned long long x)
151{
152    return __builtin_clzll(x);
153}
154
155int __builtin_popcountl (unsigned long x);
156
157/** DONT_TRANSLATE */
158static inline long
159CONST popcountl(unsigned long mask)
160{
161#ifndef __POPCNT__
162    unsigned int count; // c accumulates the total bits set in v
163    for (count = 0; mask; count++) {
164        mask &= mask - 1; // clear the least significant bit set
165    }
166
167    return count;
168#else
169    return __builtin_popcountl(mask);
170#endif
171}
172
173#define POPCOUNTL(x) popcountl(x)
174
175/* Can be used to insert padding to the next L1 cache line boundary */
176#define PAD_TO_NEXT_CACHE_LN(used) char padding[L1_CACHE_LINE_SIZE - ((used) % L1_CACHE_LINE_SIZE)]
177
178#else /* __ASSEMBLER__ */
179
180/* Some assemblers don't recognise ul (unsigned long) suffix */
181#define BIT(n) (1 << (n))
182#define UL_CONST(x) x
183
184#endif /* !__ASSEMBLER__ */
185#endif /* __UTIL_H */
186