130 lines
5.6 KiB
C
130 lines
5.6 KiB
C
/***************************************************************************************
|
|
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
|
*
|
|
* NEMU is licensed under Mulan PSL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
* You may obtain a copy of Mulan PSL v2 at:
|
|
* http://license.coscl.org.cn/MulanPSL2
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
*
|
|
* See the Mulan PSL v2 for more details.
|
|
***************************************************************************************/
|
|
|
|
#ifndef __MACRO_H__
|
|
#define __MACRO_H__
|
|
|
|
#include <string.h>
|
|
|
|
// macro stringizing
|
|
#define str_temp(x) #x
|
|
#define str(x) str_temp(x)
|
|
|
|
// strlen() for string constant
|
|
#define STRLEN(CONST_STR) (sizeof(CONST_STR) - 1)
|
|
|
|
// calculate the length of an array
|
|
#define ARRLEN(arr) (int)(sizeof(arr) / sizeof(arr[0]))
|
|
|
|
// macro concatenation
|
|
#define concat_temp(x, y) x##y
|
|
#define concat(x, y) concat_temp(x, y)
|
|
#define concat3(x, y, z) concat(concat(x, y), z)
|
|
#define concat4(x, y, z, w) concat3(concat(x, y), z, w)
|
|
#define concat5(x, y, z, v, w) concat4(concat(x, y), z, v, w)
|
|
|
|
// macro testing
|
|
// See https://stackoverflow.com/questions/26099745/test-if-preprocessor-symbol-is-defined-inside-macro
|
|
#define CHOOSE2nd(a, b, ...) b
|
|
#define MUX_WITH_COMMA(contain_comma, a, b) CHOOSE2nd(contain_comma a, b)
|
|
#define MUX_MACRO_PROPERTY(p, macro, a, b) \
|
|
MUX_WITH_COMMA(concat(p, macro), a, b)
|
|
// define placeholders for some property
|
|
#define __P_DEF_0 X,
|
|
#define __P_DEF_1 X,
|
|
#define __P_ONE_1 X,
|
|
#define __P_ZERO_0 X,
|
|
// define some selection functions based on the properties of BOOLEAN macro
|
|
#define MUXDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, X, Y)
|
|
#define MUXNDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, Y, X)
|
|
#define MUXONE(macro, X, Y) MUX_MACRO_PROPERTY(__P_ONE_, macro, X, Y)
|
|
#define MUXZERO(macro, X, Y) MUX_MACRO_PROPERTY(__P_ZERO_, macro, X, Y)
|
|
|
|
// test if a boolean macro is defined
|
|
#define ISDEF(macro) MUXDEF(macro, 1, 0)
|
|
// test if a boolean macro is undefined
|
|
#define ISNDEF(macro) MUXNDEF(macro, 1, 0)
|
|
// test if a boolean macro is defined to 1
|
|
#define ISONE(macro) MUXONE(macro, 1, 0)
|
|
// test if a boolean macro is defined to 0
|
|
#define ISZERO(macro) MUXZERO(macro, 1, 0)
|
|
// test if a macro of ANY type is defined
|
|
// NOTE1: it ONLY works inside a function, since it calls `strcmp()`
|
|
// NOTE2: macros defined to themselves (#define A A) will get wrong results
|
|
#define isdef(macro) (strcmp("" #macro, "" str(macro)) != 0)
|
|
|
|
// simplification for conditional compilation
|
|
#define __IGNORE(...)
|
|
#define __KEEP(...) __VA_ARGS__
|
|
// keep the code if a boolean macro is defined
|
|
#define IFDEF(macro, ...) MUXDEF(macro, __KEEP, __IGNORE)(__VA_ARGS__)
|
|
// keep the code if a boolean macro is undefined
|
|
#define IFNDEF(macro, ...) MUXNDEF(macro, __KEEP, __IGNORE)(__VA_ARGS__)
|
|
// keep the code if a boolean macro is defined to 1
|
|
#define IFONE(macro, ...) MUXONE(macro, __KEEP, __IGNORE)(__VA_ARGS__)
|
|
// keep the code if a boolean macro is defined to 0
|
|
#define IFZERO(macro, ...) MUXZERO(macro, __KEEP, __IGNORE)(__VA_ARGS__)
|
|
|
|
// functional-programming-like macro (X-macro)
|
|
// apply the function `f` to each element in the container `c`
|
|
// NOTE1: `c` should be defined as a list like:
|
|
// f(a0) f(a1) f(a2) ...
|
|
// NOTE2: each element in the container can be a tuple
|
|
#define MAP(c, f) c(f)
|
|
|
|
#define BITMASK(bits) ((1ull << (bits)) - 1)
|
|
#define BITS(x, hi, lo) \
|
|
(((x) >> (lo)) & BITMASK((hi) - (lo) + 1)) // similar to x[hi:lo] in verilog
|
|
#define SEXT(x, len) \
|
|
({ \
|
|
struct { \
|
|
int64_t n : len; \
|
|
} __x = {.n = x}; \
|
|
(uint64_t) __x.n; \
|
|
})
|
|
|
|
#define ROUNDUP(a, sz) ((((uintptr_t)a) + (sz)-1) & ~((sz)-1))
|
|
#define ROUNDDOWN(a, sz) ((((uintptr_t)a)) & ~((sz)-1))
|
|
|
|
#define PG_ALIGN __attribute((aligned(4096)))
|
|
|
|
#define FAILED_GOTO(tag, exp) \
|
|
do { \
|
|
if ((exp)) \
|
|
goto tag; \
|
|
} while (0)
|
|
|
|
#if !defined(likely)
|
|
#define likely(cond) __builtin_expect(cond, 1)
|
|
#define unlikely(cond) __builtin_expect(cond, 0)
|
|
#endif
|
|
|
|
#define __EXPORT __attribute__((visibility("default")))
|
|
|
|
// for AM IOE
|
|
#define io_read(reg) \
|
|
({ \
|
|
reg##_T __io_param; \
|
|
ioe_read(reg, &__io_param); \
|
|
__io_param; \
|
|
})
|
|
|
|
#define io_write(reg, ...) \
|
|
({ \
|
|
reg##_T __io_param = (reg##_T){__VA_ARGS__}; \
|
|
ioe_write(reg, &__io_param); \
|
|
})
|
|
|
|
#endif
|