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 |
|
---|
12 | /* ffi_prep_args is called by the assembly routine once stack space has
|
---|
13 | been allocated for the function's arguments. */
|
---|
14 |
|
---|
15 | static void *
|
---|
16 | ffi_prep_args (void *stack, extended_cif *ecif)
|
---|
17 | {
|
---|
18 | unsigned int i;
|
---|
19 | void **p_argv;
|
---|
20 | char *argp;
|
---|
21 | ffi_type **p_arg;
|
---|
22 | void *struct_value_ptr;
|
---|
23 |
|
---|
24 | argp = stack;
|
---|
25 |
|
---|
26 | if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
|
---|
27 | && ecif->cif->rtype->size > 8)
|
---|
28 | struct_value_ptr = ecif->rvalue;
|
---|
29 | else
|
---|
30 | struct_value_ptr = NULL;
|
---|
31 |
|
---|
32 | p_argv = ecif->avalue;
|
---|
33 |
|
---|
34 | for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
---|
35 | i != 0;
|
---|
36 | i--, p_arg++)
|
---|
37 | {
|
---|
38 | size_t z;
|
---|
39 |
|
---|
40 | /* Align if necessary. */
|
---|
41 | if (((*p_arg)->alignment - 1) & (unsigned) argp)
|
---|
42 | argp = (char *) ALIGN (argp, (*p_arg)->alignment);
|
---|
43 |
|
---|
44 | z = (*p_arg)->size;
|
---|
45 | if (z < sizeof (int))
|
---|
46 | {
|
---|
47 | switch ((*p_arg)->type)
|
---|
48 | {
|
---|
49 | case FFI_TYPE_SINT8:
|
---|
50 | *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
|
---|
51 | break;
|
---|
52 |
|
---|
53 | case FFI_TYPE_UINT8:
|
---|
54 | *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
|
---|
55 | break;
|
---|
56 |
|
---|
57 | case FFI_TYPE_SINT16:
|
---|
58 | *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
|
---|
59 | break;
|
---|
60 |
|
---|
61 | case FFI_TYPE_UINT16:
|
---|
62 | *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
|
---|
63 | break;
|
---|
64 |
|
---|
65 | case FFI_TYPE_STRUCT:
|
---|
66 | memcpy (argp + sizeof (int) - z, *p_argv, z);
|
---|
67 | break;
|
---|
68 |
|
---|
69 | default:
|
---|
70 | FFI_ASSERT (0);
|
---|
71 | }
|
---|
72 | z = sizeof (int);
|
---|
73 | }
|
---|
74 | else
|
---|
75 | memcpy (argp, *p_argv, z);
|
---|
76 | p_argv++;
|
---|
77 | argp += z;
|
---|
78 | }
|
---|
79 |
|
---|
80 | return struct_value_ptr;
|
---|
81 | }
|
---|
82 |
|
---|
83 | #define CIF_FLAGS_INT 1
|
---|
84 | #define CIF_FLAGS_DINT 2
|
---|
85 | #define CIF_FLAGS_FLOAT 4
|
---|
86 | #define CIF_FLAGS_DOUBLE 8
|
---|
87 | #define CIF_FLAGS_LDOUBLE 16
|
---|
88 | #define CIF_FLAGS_POINTER 32
|
---|
89 | #define CIF_FLAGS_STRUCT 64
|
---|
90 |
|
---|
91 | /* Perform machine dependent cif processing */
|
---|
92 | ffi_status
|
---|
93 | ffi_prep_cif_machdep (ffi_cif *cif)
|
---|
94 | {
|
---|
95 | /* Set the return type flag */
|
---|
96 | switch (cif->rtype->type)
|
---|
97 | {
|
---|
98 | case FFI_TYPE_VOID:
|
---|
99 | cif->flags = 0;
|
---|
100 | break;
|
---|
101 |
|
---|
102 | case FFI_TYPE_STRUCT:
|
---|
103 | if (cif->rtype->size > 4 && cif->rtype->size <= 8)
|
---|
104 | cif->flags = CIF_FLAGS_DINT;
|
---|
105 | else if (cif->rtype->size <= 4)
|
---|
106 | cif->flags = CIF_FLAGS_STRUCT;
|
---|
107 | else
|
---|
108 | cif->flags = 0;
|
---|
109 | break;
|
---|
110 |
|
---|
111 | case FFI_TYPE_FLOAT:
|
---|
112 | cif->flags = CIF_FLAGS_FLOAT;
|
---|
113 | break;
|
---|
114 |
|
---|
115 | case FFI_TYPE_DOUBLE:
|
---|
116 | cif->flags = CIF_FLAGS_DOUBLE;
|
---|
117 | break;
|
---|
118 |
|
---|
119 | case FFI_TYPE_LONGDOUBLE:
|
---|
120 | cif->flags = CIF_FLAGS_LDOUBLE;
|
---|
121 | break;
|
---|
122 |
|
---|
123 | case FFI_TYPE_POINTER:
|
---|
124 | cif->flags = CIF_FLAGS_POINTER;
|
---|
125 | break;
|
---|
126 |
|
---|
127 | case FFI_TYPE_SINT64:
|
---|
128 | case FFI_TYPE_UINT64:
|
---|
129 | cif->flags = CIF_FLAGS_DINT;
|
---|
130 | break;
|
---|
131 |
|
---|
132 | default:
|
---|
133 | cif->flags = CIF_FLAGS_INT;
|
---|
134 | break;
|
---|
135 | }
|
---|
136 |
|
---|
137 | return FFI_OK;
|
---|
138 | }
|
---|
139 |
|
---|
140 | extern void ffi_call_SYSV (void *(*) (void *, extended_cif *),
|
---|
141 | extended_cif *,
|
---|
142 | unsigned, unsigned, unsigned,
|
---|
143 | void *, void (*fn) ());
|
---|
144 |
|
---|
145 | void
|
---|
146 | ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
|
---|
147 | {
|
---|
148 | extended_cif ecif;
|
---|
149 |
|
---|
150 | ecif.cif = cif;
|
---|
151 | ecif.avalue = avalue;
|
---|
152 |
|
---|
153 | /* If the return value is a struct and we don't have a return value
|
---|
154 | address then we need to make one. */
|
---|
155 |
|
---|
156 | if (rvalue == NULL
|
---|
157 | && cif->rtype->type == FFI_TYPE_STRUCT
|
---|
158 | && cif->rtype->size > 8)
|
---|
159 | ecif.rvalue = alloca (cif->rtype->size);
|
---|
160 | else
|
---|
161 | ecif.rvalue = rvalue;
|
---|
162 |
|
---|
163 |
|
---|
164 | switch (cif->abi)
|
---|
165 | {
|
---|
166 | case FFI_SYSV:
|
---|
167 | ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes,
|
---|
168 | cif->flags, cif->rtype->size * 8,
|
---|
169 | ecif.rvalue, fn);
|
---|
170 | break;
|
---|
171 |
|
---|
172 | default:
|
---|
173 | FFI_ASSERT (0);
|
---|
174 | break;
|
---|
175 | }
|
---|
176 | }
|
---|