Mercurial > pub > dyncall > dyncall
annotate dyncall/dyncall_callvm_arm32_arm_armhf.c @ 321:72b450cc3be8
- cosmetics/cleanup
author | Tassilo Philipp |
---|---|
date | Sat, 16 Nov 2019 00:14:47 +0100 |
parents | f5577f6bf97a |
children | ad5f9803f52f |
rev | line source |
---|---|
0 | 1 /* |
2 | |
3 Package: dyncall | |
4 Library: dyncall | |
5 File: dyncall/dyncall_callvm_arm32_arm_armhf.c | |
6 Description: ARM 'armhf' ABI implementation | |
7 License: | |
8 | |
281 | 9 Copyright (c) 2007-2018 Daniel Adler <dadler@uni-goettingen.de>, |
0 | 10 Tassilo Philipp <tphilipp@potion-studios.com> |
11 | |
12 Permission to use, copy, modify, and distribute this software for any | |
13 purpose with or without fee is hereby granted, provided that the above | |
14 copyright notice and this permission notice appear in all copies. | |
15 | |
16 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
17 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
18 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
19 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
21 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
22 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
23 | |
24 */ | |
25 | |
26 | |
27 #include "dyncall_callvm_arm32_arm_armhf.h" | |
28 #include "dyncall_alloc.h" | |
29 | |
30 | |
31 static void deinit(DCCallVM* in_self) | |
32 { | |
33 dcFreeMem(in_self); | |
34 } | |
35 | |
36 | |
37 static void reset(DCCallVM* in_p) | |
38 { | |
39 DCCallVM_arm32_armhf* p = (DCCallVM_arm32_armhf*)in_p; | |
40 p->i = 0; | |
41 p->s = 0; | |
42 p->d = 0; | |
43 dcVecResize(&p->mVecHead, 16); | |
44 } | |
45 | |
46 static void a_int(DCCallVM* in_self, DCint x) | |
47 { | |
48 DCCallVM_arm32_armhf* p = (DCCallVM_arm32_armhf*)in_self; | |
49 if (p->i < 16) { | |
50 * (DCint*) dcVecAt(&p->mVecHead, p->i) = x; | |
51 p->i += 4; | |
52 } else { | |
53 dcVecAppend(&p->mVecHead, &x, sizeof(DCint)); | |
54 } | |
55 } | |
56 | |
57 static void a_bool (DCCallVM* in_self, DCbool x) { a_int(in_self, (DCint)x); } | |
58 static void a_char (DCCallVM* in_self, DCchar x) { a_int(in_self, x); } | |
59 static void a_short (DCCallVM* in_self, DCshort x) { a_int(in_self, x); } | |
60 static void a_long (DCCallVM* in_self, DClong x) { a_int(in_self, x); } | |
51 | 61 |
0 | 62 static void a_longlong(DCCallVM* in_self, DClonglong x) |
63 { | |
64 DCCallVM_arm32_armhf* p = (DCCallVM_arm32_armhf*)in_self; | |
65 | |
66 p->i = (p->i+4) & -8; | |
67 if (p->i < 16) { | |
68 * (DClonglong*) dcVecAt(&p->mVecHead, p->i) = x; | |
69 p->i += 8; | |
70 } else { | |
71 /* 64 bit values need to be aligned on 8 byte boundaries */ | |
72 dcVecSkip(&p->mVecHead, dcVecSize(&p->mVecHead) & 4); | |
73 dcVecAppend(&p->mVecHead, &x, sizeof(DClonglong)); | |
74 } | |
75 } | |
51 | 76 |
0 | 77 static void a_pointer(DCCallVM* in_p, DCpointer x) { a_int(in_p, (DCint) x ); } |
78 | |
79 static void a_float(DCCallVM* in_p, DCfloat x) | |
80 { | |
81 DCCallVM_arm32_armhf* p = (DCCallVM_arm32_armhf*)in_p; | |
82 if (p->s < 16) { | |
83 p->S[p->s++] = x; | |
84 if (p->d < p->s) { | |
85 p->d = (p->s+1) & ~(1U); | |
86 } else { | |
87 p->s = p->d; | |
88 } | |
89 } else { | |
90 dcVecAppend(&p->mVecHead, &x, sizeof(DCfloat)); | |
51 | 91 } |
0 | 92 } |
93 | |
94 static void a_double(DCCallVM* in_p, DCdouble x) | |
95 { | |
47 | 96 union { |
97 DCdouble d; | |
98 DCchar b[8]; | |
99 } v; | |
100 | |
0 | 101 DCCallVM_arm32_armhf* p = (DCCallVM_arm32_armhf*)in_p; |
102 if (p->d < 16) { | |
146
0ab08c1541f0
- fixed armhf ellipsis calls, were ignoring spill area
cslag
parents:
84
diff
changeset
|
103 * (DCdouble*) &p->S[p->d] = x; |
0 | 104 p->d += 2; |
105 if (!(p->s & 1)) { | |
51 | 106 /* if s is even it always equals d. otherwise, s points to an odd float register. */ |
0 | 107 p->s = p->d; |
108 } | |
109 } else { | |
47 | 110 p->s = 16; /* fp registers all full - need to use stack now: stop filling gaps for single precision, also */ |
0 | 111 v.d = x; |
112 /* 64 bit values need to be aligned on 8 byte boundaries */ | |
113 dcVecSkip(&p->mVecHead, dcVecSize(&p->mVecHead) & 4); | |
114 dcVecAppend(&p->mVecHead, &v.b[0], sizeof(DCdouble)); | |
115 } | |
116 } | |
117 | |
51 | 118 static void a_float_ellipsis(DCCallVM* in_p, DCfloat x) |
119 { | |
120 a_int(in_p, *(DCint*)&x); | |
121 } | |
122 | |
123 static void a_double_ellipsis(DCCallVM* in_p, DCdouble x) | |
124 { | |
125 a_longlong(in_p, *(DClonglong*)&x); | |
126 } | |
127 | |
0 | 128 void call(DCCallVM* in_p, DCpointer target) |
129 { | |
130 DCCallVM_arm32_armhf* p = (DCCallVM_arm32_armhf*)in_p; | |
131 dcCall_arm32_armhf(target, dcVecData(&p->mVecHead), dcVecSize(&p->mVecHead), &p->S[0]); | |
132 } | |
133 | |
84 | 134 static void mode(DCCallVM* in_self,DCint mode); |
135 | |
0 | 136 DCCallVM_vt vt_armhf = |
137 { | |
138 &deinit | |
139 , &reset | |
140 , &mode | |
141 , &a_bool | |
142 , &a_char | |
51 | 143 , &a_short |
0 | 144 , &a_int |
145 , &a_long | |
146 , &a_longlong | |
147 , &a_float | |
148 , &a_double | |
149 , &a_pointer | |
150 , NULL /* argStruct */ | |
151 , (DCvoidvmfunc*) &call | |
152 , (DCboolvmfunc*) &call | |
153 , (DCcharvmfunc*) &call | |
154 , (DCshortvmfunc*) &call | |
155 , (DCintvmfunc*) &call | |
156 , (DClongvmfunc*) &call | |
157 , (DClonglongvmfunc*) &call | |
158 , (DCfloatvmfunc*) &call | |
159 , (DCdoublevmfunc*) &call | |
160 , (DCpointervmfunc*) &call | |
161 , NULL /* callStruct */ | |
162 }; | |
163 | |
51 | 164 DCCallVM_vt vt_armhf_ellipsis = |
165 { | |
166 &deinit | |
167 , &reset | |
168 , &mode | |
169 , &a_bool | |
170 , &a_char | |
171 , &a_short | |
172 , &a_int | |
173 , &a_long | |
174 , &a_longlong | |
175 , &a_float_ellipsis | |
176 , &a_double_ellipsis | |
177 , &a_pointer | |
178 , NULL /* argStruct */ | |
179 , (DCvoidvmfunc*) &call | |
180 , (DCboolvmfunc*) &call | |
181 , (DCcharvmfunc*) &call | |
182 , (DCshortvmfunc*) &call | |
183 , (DCintvmfunc*) &call | |
184 , (DClongvmfunc*) &call | |
185 , (DClonglongvmfunc*) &call | |
186 , (DCfloatvmfunc*) &call | |
187 , (DCdoublevmfunc*) &call | |
188 , (DCpointervmfunc*) &call | |
189 , NULL /* callStruct */ | |
190 }; | |
191 | |
84 | 192 static void mode(DCCallVM* in_self, DCint mode) |
0 | 193 { |
84 | 194 DCCallVM_arm32_armhf* self = (DCCallVM_arm32_armhf*)in_self; |
195 DCCallVM_vt* vt; | |
0 | 196 |
197 switch(mode) { | |
51 | 198 case DC_CALL_C_DEFAULT: |
199 case DC_CALL_C_ARM_ARMHF: | |
84 | 200 vt = &vt_armhf; |
51 | 201 break; |
0 | 202 case DC_CALL_C_ELLIPSIS: |
203 case DC_CALL_C_ELLIPSIS_VARARGS: | |
84 | 204 vt = &vt_armhf_ellipsis; |
0 | 205 break; |
51 | 206 default: |
84 | 207 self->mInterface.mError = DC_ERROR_UNSUPPORTED_MODE; |
0 | 208 return; |
209 } | |
84 | 210 dc_callvm_base_init(&self->mInterface, vt); |
0 | 211 } |
212 | |
84 | 213 /* Public API. */ |
214 DCCallVM* dcNewCallVM(DCsize size) | |
215 { | |
216 /* Store at least 16 bytes (4 words for first 4 int args) for internal spill area. Assembly code depends on it. */ | |
217 DCCallVM_arm32_armhf* p = (DCCallVM_arm32_armhf*)dcAllocMem(sizeof(DCCallVM_arm32_armhf)+size+16); | |
218 | |
219 mode((DCCallVM*)p, DC_CALL_C_DEFAULT); | |
220 | |
221 dcVecInit(&p->mVecHead, size); | |
222 reset((DCCallVM*)p); | |
223 | |
224 return (DCCallVM*)p; | |
225 } | |
226 |