1 #ifndef RENODE_IMPORTS_H_ 2 #define RENODE_IMPORTS_H_ 3 4 #ifdef __cplusplus 5 #define EXTERN_C extern "C" 6 #else 7 #define EXTERN_C 8 #endif 9 10 /* If this header is used as a part of tlib, we will call this hook after every callback */ 11 #ifdef TARGET_LONG_BITS 12 EXTERN_C void tlib_try_interrupt_translation_block(void); 13 #else 14 #define tlib_try_interrupt_translation_block() 15 #endif 16 17 #include "map.h" 18 19 #define VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N 20 #define VA_NARGS(ARGS...) VA_NARGS_IMPL(_, ##ARGS, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) 21 22 #define CONCAT_0() 23 #define CONCAT_1(A) A 24 #define CONCAT_2(A, B) A##B 25 #define CONCAT_3(A, B, C) A##B##C 26 #define CONCAT_4(A, B, C, D) A##B##C##D 27 #define CONCAT_5(A, B, C, D, E) A##B##C##D##E 28 #define CONCAT_6(A, B, C, D, E, F) A##B##C##D##E##F 29 #define CONCAT_EXP_2(A, B) CONCAT_2(A, B) 30 #define CONCAT_EXP_5(A, B, C, D, E) CONCAT_5(A, B, C, D, E) 31 32 #define CONCAT_IMPL2(N, XS...) CONCAT_##N(XS) 33 #define CONCAT_IMPL(N, XS...) CONCAT_IMPL2(N, XS) 34 #define CONCAT(XS...) CONCAT_IMPL(VA_NARGS(XS), XS) 35 36 #define IF_THEN_ELSE(COND, THEN, ELSE) CONCAT_2(IF_THEN_ELSE_, COND)(THEN, ELSE) 37 #define IF_THEN_ELSE_0(THEN, ELSE) ELSE 38 #define IF_THEN_ELSE_1(THEN, ELSE) THEN 39 40 // We need these typedefs in order for the type name mapping based on token pasting to work 41 typedef void *voidptr; 42 typedef char *charptr; 43 44 #define CSHARP_TYPE_uint8_t Byte 45 #define CSHARP_TYPE_uint16_t UInt16 46 #define CSHARP_TYPE_uint32_t UInt32 47 #define CSHARP_TYPE_uint64_t UInt64 48 #define CSHARP_TYPE_int8_t SByte 49 #define CSHARP_TYPE_int16_t Int16 50 #define CSHARP_TYPE_int32_t Int32 51 #define CSHARP_TYPE_int64_t Int64 52 #define CSHARP_TYPE_charptr String 53 #define CSHARP_TYPE_voidptr IntPtr /* a pointer is a pointer */ 54 #define CSHARP_TYPE_void /* for return types */ 55 #define CSHARP_TYPE_ /* for zero-arg functions */ 56 #define CSHARP_TYPE(TYPE) CSHARP_TYPE_##TYPE 57 58 #define CSHARP_PREFIX_uint8_t Func 59 #define CSHARP_PREFIX_uint16_t Func 60 #define CSHARP_PREFIX_uint32_t Func 61 #define CSHARP_PREFIX_uint64_t Func 62 #define CSHARP_PREFIX_int8_t Func 63 #define CSHARP_PREFIX_int16_t Func 64 #define CSHARP_PREFIX_int32_t Func 65 #define CSHARP_PREFIX_int64_t Func 66 #define CSHARP_PREFIX_charptr Func 67 #define CSHARP_PREFIX_voidptr Func 68 #define CSHARP_PREFIX_void Action 69 #define CSHARP_PREFIX(TYPE) CSHARP_PREFIX_##TYPE 70 71 #define PARAMS_0() void 72 #define PARAMS_1(T0) T0 a0 73 #define PARAMS_2(T0, T1) PARAMS_1(T0), T1 a1 74 #define PARAMS_3(T0, T1, T2) PARAMS_2(T0, T1), T2 a2 75 #define PARAMS_4(T0, T1, T2, T3) PARAMS_3(T0, T1, T2), T3 a3 76 #define PARAMS_5(T0, T1, T2, T3, T4) PARAMS_4(T0, T1, T2, T3), T4 a4 77 #define PARAMS_6(T0, T1, T2, T3, T4, T5) PARAMS_5(T0, T1, T2, T3, T4), T5 a5 78 #define PARAMS_IMPL(N, TYPES...) CONCAT_EXP_2(PARAMS_, N)(TYPES) 79 #define PARAMS(TYPES...) PARAMS_IMPL(VA_NARGS(TYPES), TYPES) 80 81 #define PARAM_NAMES_0() 82 #define PARAM_NAMES_1(T0) a0 83 #define PARAM_NAMES_2(T0, T1) PARAM_NAMES_1(T0), a1 84 #define PARAM_NAMES_3(T0, T1, T2) PARAM_NAMES_2(T0, T1), a2 85 #define PARAM_NAMES_4(T0, T1, T2, T3) PARAM_NAMES_3(T0, T1, T2), a3 86 #define PARAM_NAMES_5(T0, T1, T2, T3, T4) PARAM_NAMES_4(T0, T1, T2, T3), a4 87 #define PARAM_NAMES_6(T0, T1, T2, T3, T4, T5) PARAM_NAMES_5(T0, T1, T2, T3, T4), a5 88 #define PARAM_NAMES_IMPL(N, TYPES...) CONCAT_EXP_2(PARAM_NAMES_, N)(TYPES) 89 #define PARAM_NAMES(TYPES...) PARAM_NAMES_IMPL(VA_NARGS(TYPES), TYPES) 90 91 #define RETURN_KEYWORD_Action 92 #define RETURN_KEYWORD_Func return 93 #define HAS_RETURN_Action 0 94 #define HAS_RETURN_Func 1 95 #define RETURN_KEYWORD(TYPE) CONCAT_EXP_2(RETURN_KEYWORD_, CSHARP_PREFIX(TYPE)) 96 #define HAS_RETURN(TYPE) CONCAT_EXP_2(HAS_RETURN_, CSHARP_PREFIX(TYPE)) 97 98 // Usage example: EXTERNAL_AS(int32_t, CSharpName, c_name, uint32_t, voidptr) 99 // 100 // Warning: for historical reasons, the return type goes FIRST in the generated 101 // renode_external_attach function name, which is reversed from the C# approach 102 // seen in delegate type parameters (as in Func<Arg1, Arg2, Ret>) 103 #define EXTERNAL_AS(RETURN_TYPE, IMPORTED_NAME, LOCAL_NAME, PARAMETER_TYPES...) \ 104 static RETURN_TYPE (*LOCAL_NAME##_callback$)(PARAMS(PARAMETER_TYPES)); \ 105 \ 106 RETURN_TYPE LOCAL_NAME(PARAMS(PARAMETER_TYPES)) \ 107 { \ 108 /* If this function returns a value, generate code of the form \ 109 * uint32_t retval = (*callback)(); return retval;, possibly with something in between. \ 110 * Otherwise, just call it. */ \ 111 IF_THEN_ELSE(HAS_RETURN(RETURN_TYPE), RETURN_TYPE retval =,) \ 112 LOCAL_NAME##_callback$(PARAM_NAMES(PARAMETER_TYPES)); \ 113 tlib_try_interrupt_translation_block(); \ 114 IF_THEN_ELSE(HAS_RETURN(RETURN_TYPE), return retval;,) \ 115 } \ 116 \ 117 EXTERN_C void CONCAT_EXP_5(renode_external_attach__, CSHARP_PREFIX(RETURN_TYPE), \ 118 CSHARP_TYPE(RETURN_TYPE), \ 119 CONCAT(MAP_LIST(CSHARP_TYPE, PARAMETER_TYPES)), \ 120 __##IMPORTED_NAME(RETURN_TYPE (*param)(PARAMS(PARAMETER_TYPES)))) \ 121 { \ 122 LOCAL_NAME##_callback$ = param; \ 123 } 124 125 #define EXTERNAL(RETURN_TYPE, NAME, PARAMETER_TYPES...) \ 126 EXTERNAL_AS(RETURN_TYPE, $##NAME, NAME, PARAMETER_TYPES) 127 128 #endif 129