1 /* ----------------------------------------------------------------------- 2 ffi.c - Copyright (c) 1998 Cygnus Solutions 3 Copyright (c) 2004 Simon Posnjak 4 Copyright (c) 2005 Axis Communications AB 5 Copyright (C) 2007 Free Software Foundation, Inc. 6 7 CRIS Foreign Function Interface 8 9 Permission is hereby granted, free of charge, to any person obtaining 10 a copy of this software and associated documentation files (the 11 ``Software''), to deal in the Software without restriction, including 12 without limitation the rights to use, copy, modify, merge, publish, 13 distribute, sublicense, and/or sell copies of the Software, and to 14 permit persons to whom the Software is furnished to do so, subject to 15 the following conditions: 16 17 The above copyright notice and this permission notice shall be included 18 in all copies or substantial portions of the Software. 19 20 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 IN NO EVENT SHALL SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR 24 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 OTHER DEALINGS IN THE SOFTWARE. 27 ----------------------------------------------------------------------- */ 28 29 #include <ffi.h> 30 #include <ffi_common.h> 31 32 #define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) 33 34 static ffi_status 35 initialize_aggregate_packed_struct (ffi_type * arg) 36 { 37 ffi_type **ptr; 38 39 FFI_ASSERT (arg != NULL); 40 41 FFI_ASSERT (arg->elements != NULL); 42 FFI_ASSERT (arg->size == 0); 43 FFI_ASSERT (arg->alignment == 0); 44 45 ptr = &(arg->elements[0]); 46 47 while ((*ptr) != NULL) 48 { 49 if (((*ptr)->size == 0) 50 && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK)) 51 return FFI_BAD_TYPEDEF; 52 53 FFI_ASSERT (ffi_type_test ((*ptr))); 54 55 arg->size += (*ptr)->size; 56 57 arg->alignment = (arg->alignment > (*ptr)->alignment) ? 58 arg->alignment : (*ptr)->alignment; 59 60 ptr++; 61 } 62 63 if (arg->size == 0) 64 return FFI_BAD_TYPEDEF; 65 else 66 return FFI_OK; 67 } 68 69 int 70 ffi_prep_args (char *stack, extended_cif * ecif) 71 { 72 unsigned int i; 73 unsigned int struct_count = 0; 74 void **p_argv; 75 char *argp; 76 ffi_type **p_arg; 77 78 argp = stack; 79 80 p_argv = ecif->avalue; 81 82 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; 83 (i != 0); i--, p_arg++) 84 { 85 size_t z; 86 87 switch ((*p_arg)->type) 88 { 89 case FFI_TYPE_STRUCT: 90 { 91 z = (*p_arg)->size; 92 if (z <= 4) 93 { 94 memcpy (argp, *p_argv, z); 95 z = 4; 96 } 97 else if (z <= 8) 98 { 99 memcpy (argp, *p_argv, z); 100 z = 8; 101 } 102 else 103 { 104 unsigned int uiLocOnStack; 105 z = sizeof (void *); 106 uiLocOnStack = 4 * ecif->cif->nargs + struct_count; 107 struct_count = struct_count + (*p_arg)->size; 108 *(unsigned int *) argp = 109 (unsigned int) (UINT32 *) (stack + uiLocOnStack); 110 memcpy ((stack + uiLocOnStack), *p_argv, (*p_arg)->size); 111 } 112 break; 113 } 114 default: 115 z = (*p_arg)->size; 116 if (z < sizeof (int)) 117 { 118 switch ((*p_arg)->type) 119 { 120 case FFI_TYPE_SINT8: 121 *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv); 122 break; 123 124 case FFI_TYPE_UINT8: 125 *(unsigned int *) argp = 126 (unsigned int) *(UINT8 *) (*p_argv); 127 break; 128 129 case FFI_TYPE_SINT16: 130 *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv); 131 break; 132 133 case FFI_TYPE_UINT16: 134 *(unsigned int *) argp = 135 (unsigned int) *(UINT16 *) (*p_argv); 136 break; 137 138 default: 139 FFI_ASSERT (0); 140 } 141 z = sizeof (int); 142 } 143 else if (z == sizeof (int)) 144 *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv); 145 else 146 memcpy (argp, *p_argv, z); 147 break; 148 } 149 p_argv++; 150 argp += z; 151 } 152 153 return (struct_count); 154 } 155 156 ffi_status FFI_HIDDEN 157 ffi_prep_cif_core (ffi_cif * cif, 158 ffi_abi abi, unsigned int isvariadic, 159 unsigned int nfixedargs, unsigned int ntotalargs, 160 ffi_type * rtype, ffi_type ** atypes) 161 { 162 unsigned bytes = 0; 163 unsigned int i; 164 ffi_type **ptr; 165 166 FFI_ASSERT (cif != NULL); 167 FFI_ASSERT((!isvariadic) || (nfixedargs >= 1)); 168 FFI_ASSERT(nfixedargs <= ntotalargs); 169 FFI_ASSERT (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI); 170 171 cif->abi = abi; 172 cif->arg_types = atypes; 173 cif->nargs = ntotalargs; 174 cif->rtype = rtype; 175 176 cif->flags = 0; 177 178 if ((cif->rtype->size == 0) 179 && (initialize_aggregate_packed_struct (cif->rtype) != FFI_OK)) 180 return FFI_BAD_TYPEDEF; 181 182 FFI_ASSERT_VALID_TYPE (cif->rtype); 183 184 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) 185 { 186 if (((*ptr)->size == 0) 187 && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK)) 188 return FFI_BAD_TYPEDEF; 189 190 FFI_ASSERT_VALID_TYPE (*ptr); 191 192 if (((*ptr)->alignment - 1) & bytes) 193 bytes = ALIGN (bytes, (*ptr)->alignment); 194 if ((*ptr)->type == FFI_TYPE_STRUCT) 195 { 196 if ((*ptr)->size > 8) 197 { 198 bytes += (*ptr)->size; 199 bytes += sizeof (void *); 200 } 201 else 202 { 203 if ((*ptr)->size > 4) 204 bytes += 8; 205 else 206 bytes += 4; 207 } 208 } 209 else 210 bytes += STACK_ARG_SIZE ((*ptr)->size); 211 } 212 213 cif->bytes = bytes; 214 215 return ffi_prep_cif_machdep (cif); 216 } 217 218 ffi_status 219 ffi_prep_cif_machdep (ffi_cif * cif) 220 { 221 switch (cif->rtype->type) 222 { 223 case FFI_TYPE_VOID: 224 case FFI_TYPE_STRUCT: 225 case FFI_TYPE_FLOAT: 226 case FFI_TYPE_DOUBLE: 227 case FFI_TYPE_SINT64: 228 case FFI_TYPE_UINT64: 229 cif->flags = (unsigned) cif->rtype->type; 230 break; 231 232 default: 233 cif->flags = FFI_TYPE_INT; 234 break; 235 } 236 237 return FFI_OK; 238 } 239 240 extern void ffi_call_SYSV (int (*)(char *, extended_cif *), 241 extended_cif *, 242 unsigned, unsigned, unsigned *, void (*fn) ()) 243 __attribute__ ((__visibility__ ("hidden"))); 244 245 void 246 ffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue) 247 { 248 extended_cif ecif; 249 250 ecif.cif = cif; 251 ecif.avalue = avalue; 252 253 if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) 254 { 255 ecif.rvalue = alloca (cif->rtype->size); 256 } 257 else 258 ecif.rvalue = rvalue; 259 260 switch (cif->abi) 261 { 262 case FFI_SYSV: 263 ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes, 264 cif->flags, ecif.rvalue, fn); 265 break; 266 default: 267 FFI_ASSERT (0); 268 break; 269 } 270 } 271 272 /* Because the following variables are not exported outside libffi, we 273 mark them hidden. */ 274 275 /* Assembly code for the jump stub. */ 276 extern const char ffi_cris_trampoline_template[] 277 __attribute__ ((__visibility__ ("hidden"))); 278 279 /* Offset into ffi_cris_trampoline_template of where to put the 280 ffi_prep_closure_inner function. */ 281 extern const int ffi_cris_trampoline_fn_offset 282 __attribute__ ((__visibility__ ("hidden"))); 283 284 /* Offset into ffi_cris_trampoline_template of where to put the 285 closure data. */ 286 extern const int ffi_cris_trampoline_closure_offset 287 __attribute__ ((__visibility__ ("hidden"))); 288 289 /* This function is sibling-called (jumped to) by the closure 290 trampoline. We get R10..R13 at PARAMS[0..3] and a copy of [SP] at 291 PARAMS[4] to simplify handling of a straddling parameter. A copy 292 of R9 is at PARAMS[5] and SP at PARAMS[6]. These parameters are 293 put at the appropriate place in CLOSURE which is then executed and 294 the return value is passed back to the caller. */ 295 296 static unsigned long long 297 ffi_prep_closure_inner (void **params, ffi_closure* closure) 298 { 299 char *register_args = (char *) params; 300 void *struct_ret = params[5]; 301 char *stack_args = params[6]; 302 char *ptr = register_args; 303 ffi_cif *cif = closure->cif; 304 ffi_type **arg_types = cif->arg_types; 305 306 /* Max room needed is number of arguments as 64-bit values. */ 307 void **avalue = alloca (closure->cif->nargs * sizeof(void *)); 308 int i; 309 int doing_regs; 310 long long llret = 0; 311 312 /* Find the address of each argument. */ 313 for (i = 0, doing_regs = 1; i < cif->nargs; i++) 314 { 315 /* Types up to and including 8 bytes go by-value. */ 316 if (arg_types[i]->size <= 4) 317 { 318 avalue[i] = ptr; 319 ptr += 4; 320 } 321 else if (arg_types[i]->size <= 8) 322 { 323 avalue[i] = ptr; 324 ptr += 8; 325 } 326 else 327 { 328 FFI_ASSERT (arg_types[i]->type == FFI_TYPE_STRUCT); 329 330 /* Passed by-reference, so copy the pointer. */ 331 avalue[i] = *(void **) ptr; 332 ptr += 4; 333 } 334 335 /* If we've handled more arguments than fit in registers, start 336 looking at the those passed on the stack. Step over the 337 first one if we had a straddling parameter. */ 338 if (doing_regs && ptr >= register_args + 4*4) 339 { 340 ptr = stack_args + ((ptr > register_args + 4*4) ? 4 : 0); 341 doing_regs = 0; 342 } 343 } 344 345 /* Invoke the closure. */ 346 (closure->fun) (cif, 347 348 cif->rtype->type == FFI_TYPE_STRUCT 349 /* The caller allocated space for the return 350 structure, and passed a pointer to this space in 351 R9. */ 352 ? struct_ret 353 354 /* We take advantage of being able to ignore that 355 the high part isn't set if the return value is 356 not in R10:R11, but in R10 only. */ 357 : (void *) &llret, 358 359 avalue, closure->user_data); 360 361 return llret; 362 } 363 364 /* API function: Prepare the trampoline. */ 365 366 ffi_status 367 ffi_prep_closure_loc (ffi_closure* closure, 368 ffi_cif* cif, 369 void (*fun)(ffi_cif *, void *, void **, void*), 370 void *user_data, 371 void *codeloc) 372 { 373 void *innerfn = ffi_prep_closure_inner; 374 FFI_ASSERT (cif->abi == FFI_SYSV); 375 closure->cif = cif; 376 closure->user_data = user_data; 377 closure->fun = fun; 378 memcpy (closure->tramp, ffi_cris_trampoline_template, 379 FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE); 380 memcpy (closure->tramp + ffi_cris_trampoline_fn_offset, 381 &innerfn, sizeof (void *)); 382 memcpy (closure->tramp + ffi_cris_trampoline_closure_offset, 383 &codeloc, sizeof (void *)); 384 385 return FFI_OK; 386 } 387