1
/* -----------------------------------------------------------------------
2
ffi.c - Copyright (c) 1996, 2003, 2004, 2007, 2008 Red Hat, Inc.
4
SPARC Foreign Function Interface
6
Permission is hereby granted, free of charge, to any person obtaining
7
a copy of this software and associated documentation files (the
8
``Software''), to deal in the Software without restriction, including
9
without limitation the rights to use, copy, modify, merge, publish,
10
distribute, sublicense, and/or sell copies of the Software, and to
11
permit persons to whom the Software is furnished to do so, subject to
12
the following conditions:
14
The above copyright notice and this permission notice shall be included
15
in all copies or substantial portions of the Software.
17
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
18
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24
DEALINGS IN THE SOFTWARE.
25
----------------------------------------------------------------------- */
28
#include <ffi_common.h>
33
/* ffi_prep_args is called by the assembly routine once stack space
34
has been allocated for the function's arguments */
36
void ffi_prep_args_v8(char *stack, extended_cif *ecif)
43
/* Skip 16 words for the window save area */
44
argp = stack + 16*sizeof(int);
46
/* This should only really be done when we are returning a structure,
47
however, it's faster just to do it all the time...
49
if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */
50
*(int *) argp = (long)ecif->rvalue;
52
/* And 1 word for the structure return value. */
56
/* Purify will probably complain in our assembly routine, unless we
57
zero out this memory. */
67
p_argv = ecif->avalue;
69
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
73
if ((*p_arg)->type == FFI_TYPE_STRUCT
74
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
75
|| (*p_arg)->type == FFI_TYPE_LONGDOUBLE
79
*(unsigned int *) argp = (unsigned long)(* p_argv);
88
switch ((*p_arg)->type)
91
*(signed int *) argp = *(SINT8 *)(* p_argv);
95
*(unsigned int *) argp = *(UINT8 *)(* p_argv);
99
*(signed int *) argp = *(SINT16 *)(* p_argv);
102
case FFI_TYPE_UINT16:
103
*(unsigned int *) argp = *(UINT16 *)(* p_argv);
112
memcpy(argp, *p_argv, z);
122
int ffi_prep_args_v9(char *stack, extended_cif *ecif)
132
/* Skip 16 words for the window save area */
133
argp = stack + 16*sizeof(long long);
136
/* Purify will probably complain in our assembly routine, unless we
137
zero out this memory. */
139
((long long*)argp)[0] = 0;
140
((long long*)argp)[1] = 0;
141
((long long*)argp)[2] = 0;
142
((long long*)argp)[3] = 0;
143
((long long*)argp)[4] = 0;
144
((long long*)argp)[5] = 0;
147
p_argv = ecif->avalue;
149
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT &&
150
ecif->cif->rtype->size > 32)
152
*(unsigned long long *) argp = (unsigned long)ecif->rvalue;
153
argp += sizeof(long long);
157
for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
163
switch ((*p_arg)->type)
165
case FFI_TYPE_STRUCT:
168
/* For structures larger than 16 bytes we pass reference. */
169
*(unsigned long long *) argp = (unsigned long)* p_argv;
170
argp += sizeof(long long);
177
case FFI_TYPE_DOUBLE:
178
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
179
case FFI_TYPE_LONGDOUBLE:
181
ret = 1; /* We should promote into FP regs as well as integer. */
184
if (z < sizeof(long long))
186
switch ((*p_arg)->type)
189
*(signed long long *) argp = *(SINT8 *)(* p_argv);
193
*(unsigned long long *) argp = *(UINT8 *)(* p_argv);
196
case FFI_TYPE_SINT16:
197
*(signed long long *) argp = *(SINT16 *)(* p_argv);
200
case FFI_TYPE_UINT16:
201
*(unsigned long long *) argp = *(UINT16 *)(* p_argv);
204
case FFI_TYPE_SINT32:
205
*(signed long long *) argp = *(SINT32 *)(* p_argv);
208
case FFI_TYPE_UINT32:
209
*(unsigned long long *) argp = *(UINT32 *)(* p_argv);
213
*(float *) (argp + 4) = *(FLOAT32 *)(* p_argv); /* Right justify */
216
case FFI_TYPE_STRUCT:
217
memcpy(argp, *p_argv, z);
223
z = sizeof(long long);
226
else if (z == sizeof(long long))
228
memcpy(argp, *p_argv, z);
229
z = sizeof(long long);
234
if ((tmp & 1) && (*p_arg)->alignment > 8)
237
argp += sizeof(long long);
239
memcpy(argp, *p_argv, z);
240
z = 2 * sizeof(long long);
250
/* Perform machine dependent cif processing */
251
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
255
if (cif->abi != FFI_V9)
259
/* If we are returning a struct, this will already have been added.
260
Otherwise we need to add it because it's always got to be there! */
262
if (cif->rtype->type != FFI_TYPE_STRUCT)
263
cif->bytes += wordsize;
265
/* sparc call frames require that space is allocated for 6 args,
266
even if they aren't used. Make that space if necessary. */
268
if (cif->bytes < 4*6+4)
275
/* sparc call frames require that space is allocated for 6 args,
276
even if they aren't used. Make that space if necessary. */
278
if (cif->bytes < 8*6)
282
/* Adjust cif->bytes. to include 16 words for the window save area,
283
and maybe the struct/union return pointer area, */
285
cif->bytes += 16 * wordsize;
287
/* The stack must be 2 word aligned, so round bytes up
290
cif->bytes = ALIGN(cif->bytes, 2 * wordsize);
292
/* Set the return type flag */
293
switch (cif->rtype->type)
297
case FFI_TYPE_DOUBLE:
298
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
299
case FFI_TYPE_LONGDOUBLE:
301
cif->flags = cif->rtype->type;
304
case FFI_TYPE_STRUCT:
305
if (cif->abi == FFI_V9 && cif->rtype->size > 32)
306
cif->flags = FFI_TYPE_VOID;
308
cif->flags = FFI_TYPE_STRUCT;
311
case FFI_TYPE_SINT64:
312
case FFI_TYPE_UINT64:
313
if (cif->abi != FFI_V9)
315
cif->flags = FFI_TYPE_SINT64;
320
cif->flags = FFI_TYPE_INT;
326
int ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
328
ffi_type **ptr = &arg->elements[0];
332
if (off & ((*ptr)->alignment - 1))
333
off = ALIGN(off, (*ptr)->alignment);
335
switch ((*ptr)->type)
337
case FFI_TYPE_STRUCT:
338
off = ffi_v9_layout_struct(*ptr, off, ret, intg, flt);
339
off = ALIGN(off, FFI_SIZEOF_ARG);
342
case FFI_TYPE_DOUBLE:
343
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
344
case FFI_TYPE_LONGDOUBLE:
346
memmove(ret + off, flt + off, (*ptr)->size);
350
memmove(ret + off, intg + off, (*ptr)->size);
361
extern int ffi_call_v9(void *, extended_cif *, unsigned,
362
unsigned, unsigned *, void (*fn)(void));
364
extern int ffi_call_v8(void *, extended_cif *, unsigned,
365
unsigned, unsigned *, void (*fn)(void));
368
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
374
ecif.avalue = avalue;
376
/* If the return value is a struct and we don't have a return */
377
/* value address then we need to make one */
379
ecif.rvalue = rvalue;
380
if (cif->rtype->type == FFI_TYPE_STRUCT)
382
if (cif->rtype->size <= 32)
388
ecif.rvalue = alloca(cif->rtype->size);
396
/* We don't yet support calling 32bit code from 64bit */
399
ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
400
cif->flags, rvalue, fn);
405
ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes,
406
cif->flags, rval, fn);
407
if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
408
ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32);
423
extern void ffi_closure_v9(void);
425
extern void ffi_closure_v8(void);
429
ffi_prep_closure_loc (ffi_closure* closure,
431
void (*fun)(ffi_cif*, void*, void**, void*),
435
unsigned int *tramp = (unsigned int *) &closure->tramp[0];
438
/* Trampoline address is equal to the closure address. We take advantage
439
of that to reduce the trampoline size by 8 bytes. */
440
FFI_ASSERT (cif->abi == FFI_V9);
441
fn = (unsigned long) ffi_closure_v9;
442
tramp[0] = 0x83414000; /* rd %pc, %g1 */
443
tramp[1] = 0xca586010; /* ldx [%g1+16], %g5 */
444
tramp[2] = 0x81c14000; /* jmp %g5 */
445
tramp[3] = 0x01000000; /* nop */
446
*((unsigned long *) &tramp[4]) = fn;
448
unsigned long ctx = (unsigned long) codeloc;
449
FFI_ASSERT (cif->abi == FFI_V8);
450
fn = (unsigned long) ffi_closure_v8;
451
tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */
452
tramp[1] = 0x05000000 | ctx >> 10; /* sethi %hi(ctx), %g2 */
453
tramp[2] = 0x81c06000 | (fn & 0x3ff); /* jmp %g1+%lo(fn) */
454
tramp[3] = 0x8410a000 | (ctx & 0x3ff);/* or %g2, %lo(ctx) */
459
closure->user_data = user_data;
461
/* Flush the Icache. FIXME: alignment isn't certain, assume 8 bytes */
463
asm volatile ("flush %0" : : "r" (closure) : "memory");
464
asm volatile ("flush %0" : : "r" (((char *) closure) + 8) : "memory");
466
asm volatile ("iflush %0" : : "r" (closure) : "memory");
467
asm volatile ("iflush %0" : : "r" (((char *) closure) + 8) : "memory");
474
ffi_closure_sparc_inner_v8(ffi_closure *closure,
475
void *rvalue, unsigned long *gpr, unsigned long *scratch)
478
ffi_type **arg_types;
483
arg_types = cif->arg_types;
484
avalue = alloca(cif->nargs * sizeof(void *));
486
/* Copy the caller's structure return address so that the closure
487
returns the data directly to the caller. */
488
if (cif->flags == FFI_TYPE_STRUCT
489
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
490
|| cif->flags == FFI_TYPE_LONGDOUBLE
493
rvalue = (void *) gpr[0];
495
/* Always skip the structure return address. */
498
/* Grab the addresses of the arguments from the stack frame. */
499
for (i = 0; i < cif->nargs; i++)
501
if (arg_types[i]->type == FFI_TYPE_STRUCT
502
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
503
|| arg_types[i]->type == FFI_TYPE_LONGDOUBLE
507
/* Straight copy of invisible reference. */
508
avalue[i] = (void *)gpr[argn++];
510
else if ((arg_types[i]->type == FFI_TYPE_DOUBLE
511
|| arg_types[i]->type == FFI_TYPE_SINT64
512
|| arg_types[i]->type == FFI_TYPE_UINT64)
513
/* gpr is 8-byte aligned. */
516
/* Align on a 8-byte boundary. */
517
scratch[0] = gpr[argn];
518
scratch[1] = gpr[argn+1];
525
/* Always right-justify. */
526
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
527
avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
531
/* Invoke the closure. */
532
(closure->fun) (cif, rvalue, avalue, closure->user_data);
534
/* Tell ffi_closure_sparc how to perform return type promotions. */
535
return cif->rtype->type;
539
ffi_closure_sparc_inner_v9(ffi_closure *closure,
540
void *rvalue, unsigned long *gpr, double *fpr)
543
ffi_type **arg_types;
545
int i, argn, fp_slot_max;
548
arg_types = cif->arg_types;
549
avalue = alloca(cif->nargs * sizeof(void *));
551
/* Copy the caller's structure return address so that the closure
552
returns the data directly to the caller. */
553
if (cif->flags == FFI_TYPE_VOID
554
&& cif->rtype->type == FFI_TYPE_STRUCT)
556
rvalue = (void *) gpr[0];
557
/* Skip the structure return address. */
563
fp_slot_max = 16 - argn;
565
/* Grab the addresses of the arguments from the stack frame. */
566
for (i = 0; i < cif->nargs; i++)
568
if (arg_types[i]->type == FFI_TYPE_STRUCT)
570
if (arg_types[i]->size > 16)
572
/* Straight copy of invisible reference. */
573
avalue[i] = (void *)gpr[argn++];
578
ffi_v9_layout_struct(arg_types[i],
582
(char *) &fpr[argn]);
583
avalue[i] = &gpr[argn];
584
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
590
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
593
&& (arg_types[i]->type == FFI_TYPE_FLOAT
594
|| arg_types[i]->type == FFI_TYPE_DOUBLE
595
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
596
|| arg_types[i]->type == FFI_TYPE_LONGDOUBLE
599
avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size;
601
avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
605
/* Invoke the closure. */
606
(closure->fun) (cif, rvalue, avalue, closure->user_data);
608
/* Tell ffi_closure_sparc how to perform return type promotions. */
609
return cif->rtype->type;