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