Home | History | Annotate | Download | only in qemu
      1 /* Helper file for declaring TCG helper functions.
      2    Should be included at the start and end of target-foo/helper.h.
      3 
      4    Targets should use DEF_HELPER_N and DEF_HELPER_FLAGS_N to declare helper
      5    functions.  Names should be specified without the helper_ prefix, and
      6    the return and argument types specified.  3 basic types are understood
      7    (i32, i64 and ptr).  Additional aliases are provided for convenience and
      8    to match the types used by the C helper implementation.
      9 
     10    The target helper.h should be included in all files that use/define
     11    helper functions.  THis will ensure that function prototypes are
     12    consistent.  In addition it should be included an extra two times for
     13    helper.c, defining:
     14     GEN_HELPER 1 to produce op generation functions (gen_helper_*)
     15     GEN_HELPER 2 to do runtime registration helper functions.
     16  */
     17 
     18 #ifndef DEF_HELPER_H
     19 #define DEF_HELPER_H 1
     20 
     21 #define HELPER(name) glue(helper_, name)
     22 
     23 #define GET_TCGV_i32 GET_TCGV_I32
     24 #define GET_TCGV_i64 GET_TCGV_I64
     25 #define GET_TCGV_ptr GET_TCGV_PTR
     26 
     27 /* Some types that make sense in C, but not for TCG.  */
     28 #define dh_alias_i32 i32
     29 #define dh_alias_s32 i32
     30 #define dh_alias_int i32
     31 #define dh_alias_i64 i64
     32 #define dh_alias_s64 i64
     33 #define dh_alias_f32 i32
     34 #define dh_alias_f64 i64
     35 #if TARGET_LONG_BITS == 32
     36 #define dh_alias_tl i32
     37 #else
     38 #define dh_alias_tl i64
     39 #endif
     40 #define dh_alias_ptr ptr
     41 #define dh_alias_void void
     42 #define dh_alias_env ptr
     43 #define dh_alias(t) glue(dh_alias_, t)
     44 
     45 #define dh_ctype_i32 uint32_t
     46 #define dh_ctype_s32 int32_t
     47 #define dh_ctype_int int
     48 #define dh_ctype_i64 uint64_t
     49 #define dh_ctype_s64 int64_t
     50 #define dh_ctype_f32 float32
     51 #define dh_ctype_f64 float64
     52 #define dh_ctype_tl target_ulong
     53 #define dh_ctype_ptr void *
     54 #define dh_ctype_void void
     55 #define dh_ctype_env CPUState *
     56 #define dh_ctype(t) dh_ctype_##t
     57 
     58 /* We can't use glue() here because it falls foul of C preprocessor
     59    recursive expansion rules.  */
     60 #define dh_retvar_decl0_void void
     61 #define dh_retvar_decl0_i32 TCGv_i32 retval
     62 #define dh_retvar_decl0_i64 TCGv_i64 retval
     63 #define dh_retvar_decl0_ptr TCGv_ptr retval
     64 #define dh_retvar_decl0(t) glue(dh_retvar_decl0_, dh_alias(t))
     65 
     66 #define dh_retvar_decl_void
     67 #define dh_retvar_decl_i32 TCGv_i32 retval,
     68 #define dh_retvar_decl_i64 TCGv_i64 retval,
     69 #define dh_retvar_decl_ptr TCGv_ptr retval,
     70 #define dh_retvar_decl(t) glue(dh_retvar_decl_, dh_alias(t))
     71 
     72 #define dh_retvar_void TCG_CALL_DUMMY_ARG
     73 #define dh_retvar_i32 GET_TCGV_i32(retval)
     74 #define dh_retvar_i64 GET_TCGV_i64(retval)
     75 #define dh_retvar_ptr GET_TCGV_ptr(retval)
     76 #define dh_retvar(t) glue(dh_retvar_, dh_alias(t))
     77 
     78 #define dh_is_64bit_void 0
     79 #define dh_is_64bit_i32 0
     80 #define dh_is_64bit_i64 1
     81 #define dh_is_64bit_ptr (TCG_TARGET_REG_BITS == 64)
     82 #define dh_is_64bit(t) glue(dh_is_64bit_, dh_alias(t))
     83 
     84 #define dh_is_signed_void 0
     85 #define dh_is_signed_i32 0
     86 #define dh_is_signed_s32 1
     87 #define dh_is_signed_i64 0
     88 #define dh_is_signed_s64 1
     89 #define dh_is_signed_f32 0
     90 #define dh_is_signed_f64 0
     91 #define dh_is_signed_tl  0
     92 #define dh_is_signed_int 1
     93 /* ??? This is highly specific to the host cpu.  There are even special
     94    extension instructions that may be required, e.g. ia64's addp4.  But
     95    for now we don't support any 64-bit targets with 32-bit pointers.  */
     96 #define dh_is_signed_ptr 0
     97 #define dh_is_signed_env dh_is_signed_ptr
     98 #define dh_is_signed(t) dh_is_signed_##t
     99 
    100 #define dh_sizemask(t, n) \
    101   sizemask |= dh_is_64bit(t) << (n*2); \
    102   sizemask |= dh_is_signed(t) << (n*2+1)
    103 
    104 #define dh_arg(t, n) \
    105   args[n - 1] = glue(GET_TCGV_, dh_alias(t))(glue(arg, n)); \
    106   dh_sizemask(t, n)
    107 
    108 #define dh_arg_decl(t, n) glue(TCGv_, dh_alias(t)) glue(arg, n)
    109 
    110 
    111 #define DEF_HELPER_0(name, ret) \
    112     DEF_HELPER_FLAGS_0(name, 0, ret)
    113 #define DEF_HELPER_1(name, ret, t1) \
    114     DEF_HELPER_FLAGS_1(name, 0, ret, t1)
    115 #define DEF_HELPER_2(name, ret, t1, t2) \
    116     DEF_HELPER_FLAGS_2(name, 0, ret, t1, t2)
    117 #define DEF_HELPER_3(name, ret, t1, t2, t3) \
    118     DEF_HELPER_FLAGS_3(name, 0, ret, t1, t2, t3)
    119 #define DEF_HELPER_4(name, ret, t1, t2, t3, t4) \
    120     DEF_HELPER_FLAGS_4(name, 0, ret, t1, t2, t3, t4)
    121 
    122 #endif /* DEF_HELPER_H */
    123 
    124 #ifndef GEN_HELPER
    125 /* Function prototypes.  */
    126 
    127 #define DEF_HELPER_FLAGS_0(name, flags, ret) \
    128 dh_ctype(ret) HELPER(name) (void);
    129 
    130 #define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
    131 dh_ctype(ret) HELPER(name) (dh_ctype(t1));
    132 
    133 #define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
    134 dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2));
    135 
    136 #define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
    137 dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3));
    138 
    139 #define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
    140 dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
    141                                    dh_ctype(t4));
    142 
    143 #undef GEN_HELPER
    144 #define GEN_HELPER -1
    145 
    146 #elif GEN_HELPER == 1
    147 /* Gen functions.  */
    148 
    149 #define DEF_HELPER_FLAGS_0(name, flags, ret) \
    150 static inline void glue(gen_helper_, name)(dh_retvar_decl0(ret)) \
    151 { \
    152   int sizemask; \
    153   sizemask = dh_is_64bit(ret); \
    154   tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 0, NULL); \
    155 }
    156 
    157 #define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
    158 static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1)) \
    159 { \
    160   TCGArg args[1]; \
    161   int sizemask = 0; \
    162   dh_sizemask(ret, 0); \
    163   dh_arg(t1, 1); \
    164   tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 1, args); \
    165 }
    166 
    167 #define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
    168 static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1), \
    169     dh_arg_decl(t2, 2)) \
    170 { \
    171   TCGArg args[2]; \
    172   int sizemask = 0; \
    173   dh_sizemask(ret, 0); \
    174   dh_arg(t1, 1); \
    175   dh_arg(t2, 2); \
    176   tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 2, args); \
    177 }
    178 
    179 #define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
    180 static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1), \
    181     dh_arg_decl(t2, 2), dh_arg_decl(t3, 3)) \
    182 { \
    183   TCGArg args[3]; \
    184   int sizemask = 0; \
    185   dh_sizemask(ret, 0); \
    186   dh_arg(t1, 1); \
    187   dh_arg(t2, 2); \
    188   dh_arg(t3, 3); \
    189   tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 3, args); \
    190 }
    191 
    192 #define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
    193 static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1), \
    194     dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), dh_arg_decl(t4, 4)) \
    195 { \
    196   TCGArg args[4]; \
    197   int sizemask = 0; \
    198   dh_sizemask(ret, 0); \
    199   dh_arg(t1, 1); \
    200   dh_arg(t2, 2); \
    201   dh_arg(t3, 3); \
    202   dh_arg(t4, 4); \
    203   tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 4, args); \
    204 }
    205 
    206 #undef GEN_HELPER
    207 #define GEN_HELPER -1
    208 
    209 #elif GEN_HELPER == 2
    210 /* Register helpers.  */
    211 
    212 #define DEF_HELPER_FLAGS_0(name, flags, ret) \
    213 tcg_register_helper(HELPER(name), #name);
    214 
    215 #define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
    216 DEF_HELPER_FLAGS_0(name, flags, ret)
    217 
    218 #define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
    219 DEF_HELPER_FLAGS_0(name, flags, ret)
    220 
    221 #define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
    222 DEF_HELPER_FLAGS_0(name, flags, ret)
    223 
    224 #define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
    225 DEF_HELPER_FLAGS_0(name, flags, ret)
    226 
    227 #undef GEN_HELPER
    228 #define GEN_HELPER -1
    229 
    230 #elif GEN_HELPER == -1
    231 /* Undefine macros.  */
    232 
    233 #undef DEF_HELPER_FLAGS_0
    234 #undef DEF_HELPER_FLAGS_1
    235 #undef DEF_HELPER_FLAGS_2
    236 #undef DEF_HELPER_FLAGS_3
    237 #undef DEF_HELPER_FLAGS_4
    238 #undef GEN_HELPER
    239 
    240 #endif
    241