1 /* ----------------------------------------------------------------------- 2 ffi.c 3 4 m68k Foreign Function Interface 5 ----------------------------------------------------------------------- */ 6 7 #include <ffi.h> 8 #include <ffi_common.h> 9 10 #include <stdlib.h> 11 #include <unistd.h> 12 #include <sys/syscall.h> 13 #include <asm/cachectl.h> 14 15 void ffi_call_SYSV (extended_cif *, 16 unsigned, unsigned, 17 void *, void (*fn) ()); 18 void *ffi_prep_args (void *stack, extended_cif *ecif); 19 void ffi_closure_SYSV (ffi_closure *); 20 void ffi_closure_struct_SYSV (ffi_closure *); 21 unsigned int ffi_closure_SYSV_inner (ffi_closure *closure, 22 void *resp, void *args); 23 24 /* ffi_prep_args is called by the assembly routine once stack space has 25 been allocated for the function's arguments. */ 26 27 void * 28 ffi_prep_args (void *stack, extended_cif *ecif) 29 { 30 unsigned int i; 31 void **p_argv; 32 char *argp; 33 ffi_type **p_arg; 34 void *struct_value_ptr; 35 36 argp = stack; 37 38 if (ecif->cif->rtype->type == FFI_TYPE_STRUCT 39 && !ecif->cif->flags) 40 struct_value_ptr = ecif->rvalue; 41 else 42 struct_value_ptr = NULL; 43 44 p_argv = ecif->avalue; 45 46 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; 47 i != 0; 48 i--, p_arg++) 49 { 50 size_t z; 51 52 z = (*p_arg)->size; 53 if (z < sizeof (int)) 54 { 55 switch ((*p_arg)->type) 56 { 57 case FFI_TYPE_SINT8: 58 *(signed int *) argp = (signed int) *(SINT8 *) *p_argv; 59 break; 60 61 case FFI_TYPE_UINT8: 62 *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv; 63 break; 64 65 case FFI_TYPE_SINT16: 66 *(signed int *) argp = (signed int) *(SINT16 *) *p_argv; 67 break; 68 69 case FFI_TYPE_UINT16: 70 *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv; 71 break; 72 73 case FFI_TYPE_STRUCT: 74 memcpy (argp + sizeof (int) - z, *p_argv, z); 75 break; 76 77 default: 78 FFI_ASSERT (0); 79 } 80 z = sizeof (int); 81 } 82 else 83 { 84 memcpy (argp, *p_argv, z); 85 86 /* Align if necessary. */ 87 if ((sizeof(int) - 1) & z) 88 z = ALIGN(z, sizeof(int)); 89 } 90 91 p_argv++; 92 argp += z; 93 } 94 95 return struct_value_ptr; 96 } 97 98 #define CIF_FLAGS_INT 1 99 #define CIF_FLAGS_DINT 2 100 #define CIF_FLAGS_FLOAT 4 101 #define CIF_FLAGS_DOUBLE 8 102 #define CIF_FLAGS_LDOUBLE 16 103 #define CIF_FLAGS_POINTER 32 104 #define CIF_FLAGS_STRUCT1 64 105 #define CIF_FLAGS_STRUCT2 128 106 107 /* Perform machine dependent cif processing */ 108 ffi_status 109 ffi_prep_cif_machdep (ffi_cif *cif) 110 { 111 /* Set the return type flag */ 112 switch (cif->rtype->type) 113 { 114 case FFI_TYPE_VOID: 115 cif->flags = 0; 116 break; 117 118 case FFI_TYPE_STRUCT: 119 switch (cif->rtype->size) 120 { 121 case 1: 122 cif->flags = CIF_FLAGS_STRUCT1; 123 break; 124 case 2: 125 cif->flags = CIF_FLAGS_STRUCT2; 126 break; 127 case 4: 128 cif->flags = CIF_FLAGS_INT; 129 break; 130 case 8: 131 cif->flags = CIF_FLAGS_DINT; 132 break; 133 default: 134 cif->flags = 0; 135 break; 136 } 137 break; 138 139 case FFI_TYPE_FLOAT: 140 cif->flags = CIF_FLAGS_FLOAT; 141 break; 142 143 case FFI_TYPE_DOUBLE: 144 cif->flags = CIF_FLAGS_DOUBLE; 145 break; 146 147 case FFI_TYPE_LONGDOUBLE: 148 cif->flags = CIF_FLAGS_LDOUBLE; 149 break; 150 151 case FFI_TYPE_POINTER: 152 cif->flags = CIF_FLAGS_POINTER; 153 break; 154 155 case FFI_TYPE_SINT64: 156 case FFI_TYPE_UINT64: 157 cif->flags = CIF_FLAGS_DINT; 158 break; 159 160 default: 161 cif->flags = CIF_FLAGS_INT; 162 break; 163 } 164 165 return FFI_OK; 166 } 167 168 void 169 ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue) 170 { 171 extended_cif ecif; 172 173 ecif.cif = cif; 174 ecif.avalue = avalue; 175 176 /* If the return value is a struct and we don't have a return value 177 address then we need to make one. */ 178 179 if (rvalue == NULL 180 && cif->rtype->type == FFI_TYPE_STRUCT 181 && cif->rtype->size > 8) 182 ecif.rvalue = alloca (cif->rtype->size); 183 else 184 ecif.rvalue = rvalue; 185 186 switch (cif->abi) 187 { 188 case FFI_SYSV: 189 ffi_call_SYSV (&ecif, cif->bytes, cif->flags, 190 ecif.rvalue, fn); 191 break; 192 193 default: 194 FFI_ASSERT (0); 195 break; 196 } 197 } 198 199 static void 200 ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif) 201 { 202 unsigned int i; 203 void **p_argv; 204 char *argp; 205 ffi_type **p_arg; 206 207 argp = stack; 208 p_argv = avalue; 209 210 for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) 211 { 212 size_t z; 213 214 z = (*p_arg)->size; 215 if (z <= 4) 216 { 217 *p_argv = (void *) (argp + 4 - z); 218 219 z = 4; 220 } 221 else 222 { 223 *p_argv = (void *) argp; 224 225 /* Align if necessary */ 226 if ((sizeof(int) - 1) & z) 227 z = ALIGN(z, sizeof(int)); 228 } 229 230 p_argv++; 231 argp += z; 232 } 233 } 234 235 unsigned int 236 ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args) 237 { 238 ffi_cif *cif; 239 void **arg_area; 240 241 cif = closure->cif; 242 arg_area = (void**) alloca (cif->nargs * sizeof (void *)); 243 244 ffi_prep_incoming_args_SYSV(args, arg_area, cif); 245 246 (closure->fun) (cif, resp, arg_area, closure->user_data); 247 248 return cif->flags; 249 } 250 251 ffi_status 252 ffi_prep_closure_loc (ffi_closure* closure, 253 ffi_cif* cif, 254 void (*fun)(ffi_cif*,void*,void**,void*), 255 void *user_data, 256 void *codeloc) 257 { 258 FFI_ASSERT (cif->abi == FFI_SYSV); 259 260 *(unsigned short *)closure->tramp = 0x207c; 261 *(void **)(closure->tramp + 2) = codeloc; 262 *(unsigned short *)(closure->tramp + 6) = 0x4ef9; 263 if (cif->rtype->type == FFI_TYPE_STRUCT 264 && !cif->flags) 265 *(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV; 266 else 267 *(void **)(closure->tramp + 8) = ffi_closure_SYSV; 268 269 syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE, 270 FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE); 271 272 closure->cif = cif; 273 closure->user_data = user_data; 274 closure->fun = fun; 275 276 return FFI_OK; 277 } 278 279