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 34static ffi_status 35initialize_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 69int 70ffi_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 156ffi_status 157ffi_prep_cif (ffi_cif * cif, 158 ffi_abi abi, unsigned int nargs, 159 ffi_type * rtype, ffi_type ** atypes) 160{ 161 unsigned bytes = 0; 162 unsigned int i; 163 ffi_type **ptr; 164 165 FFI_ASSERT (cif != NULL); 166 FFI_ASSERT ((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI)); 167 168 cif->abi = abi; 169 cif->arg_types = atypes; 170 cif->nargs = nargs; 171 cif->rtype = rtype; 172 173 cif->flags = 0; 174 175 if ((cif->rtype->size == 0) 176 && (initialize_aggregate_packed_struct (cif->rtype) != FFI_OK)) 177 return FFI_BAD_TYPEDEF; 178 179 FFI_ASSERT_VALID_TYPE (cif->rtype); 180 181 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) 182 { 183 if (((*ptr)->size == 0) 184 && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK)) 185 return FFI_BAD_TYPEDEF; 186 187 FFI_ASSERT_VALID_TYPE (*ptr); 188 189 if (((*ptr)->alignment - 1) & bytes) 190 bytes = ALIGN (bytes, (*ptr)->alignment); 191 if ((*ptr)->type == FFI_TYPE_STRUCT) 192 { 193 if ((*ptr)->size > 8) 194 { 195 bytes += (*ptr)->size; 196 bytes += sizeof (void *); 197 } 198 else 199 { 200 if ((*ptr)->size > 4) 201 bytes += 8; 202 else 203 bytes += 4; 204 } 205 } 206 else 207 bytes += STACK_ARG_SIZE ((*ptr)->size); 208 } 209 210 cif->bytes = bytes; 211 212 return ffi_prep_cif_machdep (cif); 213} 214 215ffi_status 216ffi_prep_cif_machdep (ffi_cif * cif) 217{ 218 switch (cif->rtype->type) 219 { 220 case FFI_TYPE_VOID: 221 case FFI_TYPE_STRUCT: 222 case FFI_TYPE_FLOAT: 223 case FFI_TYPE_DOUBLE: 224 case FFI_TYPE_SINT64: 225 case FFI_TYPE_UINT64: 226 cif->flags = (unsigned) cif->rtype->type; 227 break; 228 229 default: 230 cif->flags = FFI_TYPE_INT; 231 break; 232 } 233 234 return FFI_OK; 235} 236 237extern void ffi_call_SYSV (int (*)(char *, extended_cif *), 238 extended_cif *, 239 unsigned, unsigned, unsigned *, void (*fn) ()) 240 __attribute__ ((__visibility__ ("hidden"))); 241 242void 243ffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue) 244{ 245 extended_cif ecif; 246 247 ecif.cif = cif; 248 ecif.avalue = avalue; 249 250 if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) 251 { 252 ecif.rvalue = alloca (cif->rtype->size); 253 } 254 else 255 ecif.rvalue = rvalue; 256 257 switch (cif->abi) 258 { 259 case FFI_SYSV: 260 ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes, 261 cif->flags, ecif.rvalue, fn); 262 break; 263 default: 264 FFI_ASSERT (0); 265 break; 266 } 267} 268 269/* Because the following variables are not exported outside libffi, we 270 mark them hidden. */ 271 272/* Assembly code for the jump stub. */ 273extern const char ffi_cris_trampoline_template[] 274 __attribute__ ((__visibility__ ("hidden"))); 275 276/* Offset into ffi_cris_trampoline_template of where to put the 277 ffi_prep_closure_inner function. */ 278extern const int ffi_cris_trampoline_fn_offset 279 __attribute__ ((__visibility__ ("hidden"))); 280 281/* Offset into ffi_cris_trampoline_template of where to put the 282 closure data. */ 283extern const int ffi_cris_trampoline_closure_offset 284 __attribute__ ((__visibility__ ("hidden"))); 285 286/* This function is sibling-called (jumped to) by the closure 287 trampoline. We get R10..R13 at PARAMS[0..3] and a copy of [SP] at 288 PARAMS[4] to simplify handling of a straddling parameter. A copy 289 of R9 is at PARAMS[5] and SP at PARAMS[6]. These parameters are 290 put at the appropriate place in CLOSURE which is then executed and 291 the return value is passed back to the caller. */ 292 293static unsigned long long 294ffi_prep_closure_inner (void **params, ffi_closure* closure) 295{ 296 char *register_args = (char *) params; 297 void *struct_ret = params[5]; 298 char *stack_args = params[6]; 299 char *ptr = register_args; 300 ffi_cif *cif = closure->cif; 301 ffi_type **arg_types = cif->arg_types; 302 303 /* Max room needed is number of arguments as 64-bit values. */ 304 void **avalue = alloca (closure->cif->nargs * sizeof(void *)); 305 int i; 306 int doing_regs; 307 long long llret = 0; 308 309 /* Find the address of each argument. */ 310 for (i = 0, doing_regs = 1; i < cif->nargs; i++) 311 { 312 /* Types up to and including 8 bytes go by-value. */ 313 if (arg_types[i]->size <= 4) 314 { 315 avalue[i] = ptr; 316 ptr += 4; 317 } 318 else if (arg_types[i]->size <= 8) 319 { 320 avalue[i] = ptr; 321 ptr += 8; 322 } 323 else 324 { 325 FFI_ASSERT (arg_types[i]->type == FFI_TYPE_STRUCT); 326 327 /* Passed by-reference, so copy the pointer. */ 328 avalue[i] = *(void **) ptr; 329 ptr += 4; 330 } 331 332 /* If we've handled more arguments than fit in registers, start 333 looking at the those passed on the stack. Step over the 334 first one if we had a straddling parameter. */ 335 if (doing_regs && ptr >= register_args + 4*4) 336 { 337 ptr = stack_args + ((ptr > register_args + 4*4) ? 4 : 0); 338 doing_regs = 0; 339 } 340 } 341 342 /* Invoke the closure. */ 343 (closure->fun) (cif, 344 345 cif->rtype->type == FFI_TYPE_STRUCT 346 /* The caller allocated space for the return 347 structure, and passed a pointer to this space in 348 R9. */ 349 ? struct_ret 350 351 /* We take advantage of being able to ignore that 352 the high part isn't set if the return value is 353 not in R10:R11, but in R10 only. */ 354 : (void *) &llret, 355 356 avalue, closure->user_data); 357 358 return llret; 359} 360 361/* API function: Prepare the trampoline. */ 362 363ffi_status 364ffi_prep_closure_loc (ffi_closure* closure, 365 ffi_cif* cif, 366 void (*fun)(ffi_cif *, void *, void **, void*), 367 void *user_data, 368 void *codeloc) 369{ 370 void *innerfn = ffi_prep_closure_inner; 371 FFI_ASSERT (cif->abi == FFI_SYSV); 372 closure->cif = cif; 373 closure->user_data = user_data; 374 closure->fun = fun; 375 memcpy (closure->tramp, ffi_cris_trampoline_template, 376 FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE); 377 memcpy (closure->tramp + ffi_cris_trampoline_fn_offset, 378 &innerfn, sizeof (void *)); 379 memcpy (closure->tramp + ffi_cris_trampoline_closure_offset, 380 &codeloc, sizeof (void *)); 381 382 return FFI_OK; 383} 384