Home | History | Annotate | Download | only in exec
      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_noreturn noreturn
     43 #define dh_alias_env ptr
     44 #define dh_alias(t) glue(dh_alias_, t)
     45 
     46 #define dh_ctype_i32 uint32_t
     47 #define dh_ctype_s32 int32_t
     48 #define dh_ctype_int int
     49 #define dh_ctype_i64 uint64_t
     50 #define dh_ctype_s64 int64_t
     51 #define dh_ctype_f32 float32
     52 #define dh_ctype_f64 float64
     53 #define dh_ctype_tl target_ulong
     54 #define dh_ctype_ptr void *
     55 #define dh_ctype_void void
     56 #define dh_ctype_noreturn void QEMU_NORETURN
     57 #define dh_ctype_env CPUArchState *
     58 #define dh_ctype(t) dh_ctype_##t
     59 
     60 /* We can't use glue() here because it falls foul of C preprocessor
     61    recursive expansion rules.  */
     62 #define dh_retvar_decl0_void void
     63 #define dh_retvar_decl0_noreturn void
     64 #define dh_retvar_decl0_i32 TCGv_i32 retval
     65 #define dh_retvar_decl0_i64 TCGv_i64 retval
     66 #define dh_retvar_decl0_ptr TCGv_ptr retval
     67 #define dh_retvar_decl0(t) glue(dh_retvar_decl0_, dh_alias(t))
     68 
     69 #define dh_retvar_decl_void
     70 #define dh_retvar_decl_noreturn
     71 #define dh_retvar_decl_i32 TCGv_i32 retval,
     72 #define dh_retvar_decl_i64 TCGv_i64 retval,
     73 #define dh_retvar_decl_ptr TCGv_ptr retval,
     74 #define dh_retvar_decl(t) glue(dh_retvar_decl_, dh_alias(t))
     75 
     76 #define dh_retvar_void TCG_CALL_DUMMY_ARG
     77 #define dh_retvar_noreturn TCG_CALL_DUMMY_ARG
     78 #define dh_retvar_i32 GET_TCGV_i32(retval)
     79 #define dh_retvar_i64 GET_TCGV_i64(retval)
     80 #define dh_retvar_ptr GET_TCGV_ptr(retval)
     81 #define dh_retvar(t) glue(dh_retvar_, dh_alias(t))
     82 
     83 #define dh_is_64bit_void 0
     84 #define dh_is_64bit_noreturn 0
     85 #define dh_is_64bit_i32 0
     86 #define dh_is_64bit_i64 1
     87 #define dh_is_64bit_ptr (TCG_TARGET_REG_BITS == 64)
     88 #define dh_is_64bit(t) glue(dh_is_64bit_, dh_alias(t))
     89 
     90 #define dh_is_signed_void 0
     91 #define dh_is_signed_noreturn 0
     92 #define dh_is_signed_i32 0
     93 #define dh_is_signed_s32 1
     94 #define dh_is_signed_i64 0
     95 #define dh_is_signed_s64 1
     96 #define dh_is_signed_f32 0
     97 #define dh_is_signed_f64 0
     98 #define dh_is_signed_tl  0
     99 #define dh_is_signed_int 1
    100 /* ??? This is highly specific to the host cpu.  There are even special
    101    extension instructions that may be required, e.g. ia64's addp4.  But
    102    for now we don't support any 64-bit targets with 32-bit pointers.  */
    103 #define dh_is_signed_ptr 0
    104 #define dh_is_signed_env dh_is_signed_ptr
    105 #define dh_is_signed(t) dh_is_signed_##t
    106 
    107 #define dh_sizemask(t, n) \
    108   sizemask |= dh_is_64bit(t) << (n*2); \
    109   sizemask |= dh_is_signed(t) << (n*2+1)
    110 
    111 #define dh_arg(t, n) \
    112   args[n - 1] = glue(GET_TCGV_, dh_alias(t))(glue(arg, n)); \
    113   dh_sizemask(t, n)
    114 
    115 #define dh_arg_decl(t, n) glue(TCGv_, dh_alias(t)) glue(arg, n)
    116 
    117 
    118 #define DEF_HELPER_0(name, ret) \
    119     DEF_HELPER_FLAGS_0(name, 0, ret)
    120 #define DEF_HELPER_1(name, ret, t1) \
    121     DEF_HELPER_FLAGS_1(name, 0, ret, t1)
    122 #define DEF_HELPER_2(name, ret, t1, t2) \
    123     DEF_HELPER_FLAGS_2(name, 0, ret, t1, t2)
    124 #define DEF_HELPER_3(name, ret, t1, t2, t3) \
    125     DEF_HELPER_FLAGS_3(name, 0, ret, t1, t2, t3)
    126 #define DEF_HELPER_4(name, ret, t1, t2, t3, t4) \
    127     DEF_HELPER_FLAGS_4(name, 0, ret, t1, t2, t3, t4)
    128 #define DEF_HELPER_5(name, ret, t1, t2, t3, t4, t5) \
    129     DEF_HELPER_FLAGS_5(name, 0, ret, t1, t2, t3, t4, t5)
    130 
    131 /* MAX_OPC_PARAM_IARGS must be set to n if last entry is DEF_HELPER_FLAGS_n. */
    132 
    133 #endif /* DEF_HELPER_H */
    134 
    135 #ifndef GEN_HELPER
    136 /* Function prototypes.  */
    137 
    138 #define DEF_HELPER_FLAGS_0(name, flags, ret) \
    139 dh_ctype(ret) HELPER(name) (void);
    140 
    141 #define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
    142 dh_ctype(ret) HELPER(name) (dh_ctype(t1));
    143 
    144 #define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
    145 dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2));
    146 
    147 #define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
    148 dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3));
    149 
    150 #define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
    151 dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
    152                                    dh_ctype(t4));
    153 
    154 #define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
    155 dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
    156                             dh_ctype(t4), dh_ctype(t5));
    157 
    158 #undef GEN_HELPER
    159 #define GEN_HELPER -1
    160 
    161 #elif GEN_HELPER == 1
    162 /* Gen functions.  */
    163 
    164 #define DEF_HELPER_FLAGS_0(name, flags, ret) \
    165 static inline void glue(gen_helper_, name)(dh_retvar_decl0(ret)) \
    166 { \
    167   int sizemask; \
    168   sizemask = dh_is_64bit(ret); \
    169   tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 0, NULL); \
    170 }
    171 
    172 #define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
    173 static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1)) \
    174 { \
    175   TCGArg args[1]; \
    176   int sizemask = 0; \
    177   dh_sizemask(ret, 0); \
    178   dh_arg(t1, 1); \
    179   tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 1, args); \
    180 }
    181 
    182 #define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
    183 static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1), \
    184     dh_arg_decl(t2, 2)) \
    185 { \
    186   TCGArg args[2]; \
    187   int sizemask = 0; \
    188   dh_sizemask(ret, 0); \
    189   dh_arg(t1, 1); \
    190   dh_arg(t2, 2); \
    191   tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 2, args); \
    192 }
    193 
    194 #define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
    195 static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1), \
    196     dh_arg_decl(t2, 2), dh_arg_decl(t3, 3)) \
    197 { \
    198   TCGArg args[3]; \
    199   int sizemask = 0; \
    200   dh_sizemask(ret, 0); \
    201   dh_arg(t1, 1); \
    202   dh_arg(t2, 2); \
    203   dh_arg(t3, 3); \
    204   tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 3, args); \
    205 }
    206 
    207 #define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
    208 static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1), \
    209     dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), dh_arg_decl(t4, 4)) \
    210 { \
    211   TCGArg args[4]; \
    212   int sizemask = 0; \
    213   dh_sizemask(ret, 0); \
    214   dh_arg(t1, 1); \
    215   dh_arg(t2, 2); \
    216   dh_arg(t3, 3); \
    217   dh_arg(t4, 4); \
    218   tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 4, args); \
    219 }
    220 
    221 #define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
    222 static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
    223     dh_arg_decl(t1, 1),  dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
    224     dh_arg_decl(t4, 4), dh_arg_decl(t5, 5)) \
    225 { \
    226   TCGArg args[5]; \
    227   int sizemask = 0; \
    228   dh_sizemask(ret, 0); \
    229   dh_arg(t1, 1); \
    230   dh_arg(t2, 2); \
    231   dh_arg(t3, 3); \
    232   dh_arg(t4, 4); \
    233   dh_arg(t5, 5); \
    234   tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 5, args); \
    235 }
    236 
    237 #undef GEN_HELPER
    238 #define GEN_HELPER -1
    239 
    240 #elif GEN_HELPER == 2
    241 /* Register helpers.  */
    242 
    243 #define DEF_HELPER_FLAGS_0(name, flags, ret)  { HELPER(name), #name },
    244 
    245 #define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
    246 DEF_HELPER_FLAGS_0(name, flags, ret)
    247 
    248 #define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
    249 DEF_HELPER_FLAGS_0(name, flags, ret)
    250 
    251 #define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
    252 DEF_HELPER_FLAGS_0(name, flags, ret)
    253 
    254 #define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
    255 DEF_HELPER_FLAGS_0(name, flags, ret)
    256 
    257 #define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
    258 DEF_HELPER_FLAGS_0(name, flags, ret)
    259 
    260 #undef GEN_HELPER
    261 #define GEN_HELPER -1
    262 
    263 #elif GEN_HELPER == -1
    264 /* Undefine macros.  */
    265 
    266 #undef DEF_HELPER_FLAGS_0
    267 #undef DEF_HELPER_FLAGS_1
    268 #undef DEF_HELPER_FLAGS_2
    269 #undef DEF_HELPER_FLAGS_3
    270 #undef DEF_HELPER_FLAGS_4
    271 #undef DEF_HELPER_FLAGS_5
    272 #undef GEN_HELPER
    273 
    274 #endif
    275