Mercurial > pub > dyncall > dyncall
annotate dyncall/dyncall_callvm_arm32_arm.c @ 521:a2de1d0a73f3
- more test code generator code sharing/abstraction/simplifications
author | Tassilo Philipp |
---|---|
date | Wed, 13 Apr 2022 10:06:40 +0200 |
parents | ddfb9577a00e |
children | 71c884e610f0 |
rev | line source |
---|---|
0 | 1 /* |
2 | |
3 Package: dyncall | |
4 Library: dyncall | |
5 File: dyncall/dyncall_callvm_arm32_arm.c | |
6 Description: ARM 32-bit "arm" ABI callvm implementation | |
7 License: | |
8 | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
366
diff
changeset
|
9 Copyright (c) 2007-2020 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 | |
28 /* | |
29 | |
30 dyncall callvm for 32bit ARM32 family of processors | |
31 | |
32 SUPPORTED CALLING CONVENTIONS | |
33 armcall | |
34 | |
35 REVISION | |
36 2007/12/11 initial | |
37 | |
38 */ | |
39 | |
40 | |
41 #include "dyncall_callvm_arm32_arm.h" | |
42 #include "dyncall_alloc.h" | |
43 | |
366
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
44 |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
366
diff
changeset
|
45 /* |
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
366
diff
changeset
|
46 ** arm32 arm mode calling convention calls |
366
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
47 ** |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
48 ** - hybrid return-type call (bool ... pointer) |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
49 ** |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
50 ** Note the return type of this declaration is intentially of double-word size (despite |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
51 ** the return value not being used in the code below). |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
52 ** On some platforms (FreeBSD/arm, Nintendo DS, ...) the compiler generates cleanup code |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
53 ** in the caller (dc_callvm_call_arm32_arm) that reuses - thus overwrites - r0 and r1. |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
54 ** With this "hint", we preserve those registers by letting the compiler assume both |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
55 ** registers are used for the return type. |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
56 */ |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
57 DClonglong dcCall_arm32_arm(DCpointer target, DCpointer stackdata, DCsize size); |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
58 |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
59 |
0 | 60 static void dc_callvm_free_arm32_arm(DCCallVM* in_self) |
61 { | |
62 dcFreeMem(in_self); | |
63 } | |
64 | |
65 | |
66 static void dc_callvm_reset_arm32_arm(DCCallVM* in_self) | |
67 { | |
68 DCCallVM_arm32_arm* self = (DCCallVM_arm32_arm*)in_self; | |
69 dcVecReset(&self->mVecHead); | |
70 } | |
71 | |
72 | |
73 static void dc_callvm_argInt_arm32_arm(DCCallVM* in_self, DCint x) | |
74 { | |
75 DCCallVM_arm32_arm* self = (DCCallVM_arm32_arm*)in_self; | |
76 dcVecAppend(&self->mVecHead, &x, sizeof(DCint)); | |
77 } | |
78 | |
79 | |
80 static void dc_callvm_argBool_arm32_arm(DCCallVM* in_self, DCbool x) | |
81 { | |
82 dc_callvm_argInt_arm32_arm(in_self, (DCint)x); | |
83 } | |
84 | |
85 | |
86 static void dc_callvm_argChar_arm32_arm(DCCallVM* in_self, DCchar x) | |
87 { | |
88 dc_callvm_argInt_arm32_arm(in_self, x); | |
89 } | |
90 | |
91 | |
92 static void dc_callvm_argShort_arm32_arm(DCCallVM* in_self, DCshort x) | |
93 { | |
94 dc_callvm_argInt_arm32_arm(in_self, x); | |
95 } | |
96 | |
97 | |
98 static void dc_callvm_argLong_arm32_arm(DCCallVM* in_self, DClong x) | |
99 { | |
100 dc_callvm_argInt_arm32_arm(in_self, x); | |
101 } | |
102 | |
103 | |
104 static void dc_callvm_argLongLong_arm32_arm(DCCallVM* in_self, DClonglong x) | |
105 { | |
106 DCCallVM_arm32_arm* self = (DCCallVM_arm32_arm*)in_self; | |
107 dcVecAppend(&self->mVecHead, &x, sizeof(DClonglong)); | |
108 } | |
109 | |
110 | |
111 static void dc_callvm_argLongLong_arm32_arm_eabi(DCCallVM* in_self, DClonglong x) | |
112 { | |
113 DCCallVM_arm32_arm* self = (DCCallVM_arm32_arm*)in_self; | |
114 | |
115 /* 64 bit values need to be aligned on 8 byte boundaries */ | |
116 dcVecSkip(&self->mVecHead, dcVecSize(&self->mVecHead) & 4); | |
117 dcVecAppend(&self->mVecHead, &x, sizeof(DClonglong)); | |
118 } | |
119 | |
120 | |
121 static void dc_callvm_argFloat_arm32_arm(DCCallVM* in_self, DCfloat x) | |
122 { | |
123 DCCallVM_arm32_arm* self = (DCCallVM_arm32_arm*)in_self; | |
124 dcVecAppend(&self->mVecHead, &x, sizeof(DCfloat)); | |
125 } | |
126 | |
127 | |
128 static void dc_callvm_argDouble_arm32_arm(DCCallVM* in_self, DCdouble x) | |
129 { | |
130 DCCallVM_arm32_arm* self = (DCCallVM_arm32_arm*)in_self; | |
131 dcVecAppend(&self->mVecHead, &x, sizeof(DCdouble)); | |
132 } | |
133 | |
134 | |
135 static void dc_callvm_argDouble_arm32_arm_eabi(DCCallVM* in_self, DCdouble x) | |
136 { | |
137 DCCallVM_arm32_arm* self = (DCCallVM_arm32_arm*)in_self; | |
138 | |
139 /* 64 bit values need to be aligned on 8 byte boundaries */ | |
140 dcVecSkip(&self->mVecHead, dcVecSize(&self->mVecHead) & 4); | |
141 dcVecAppend(&self->mVecHead, &x, sizeof(DCdouble)); | |
142 } | |
143 | |
144 | |
145 static void dc_callvm_argPointer_arm32_arm(DCCallVM* in_self, DCpointer x) | |
146 { | |
147 DCCallVM_arm32_arm* self = (DCCallVM_arm32_arm*)in_self; | |
148 dcVecAppend(&self->mVecHead, &x, sizeof(DCpointer)); | |
149 } | |
150 | |
151 | |
152 /* Call. */ | |
153 void dc_callvm_call_arm32_arm(DCCallVM* in_self, DCpointer target) | |
154 { | |
155 DCCallVM_arm32_arm* self = (DCCallVM_arm32_arm*)in_self; | |
27
523c45dfa8fb
- refactored arm calling conventions' callvm code, so that the code that keeps
cslag
parents:
17
diff
changeset
|
156 dcCall_arm32_arm(target, dcVecData(&self->mVecHead), dcVecSize(&self->mVecHead)); |
0 | 157 } |
158 | |
84 | 159 static void dc_callvm_mode_arm32_arm(DCCallVM* in_self, DCint mode); |
0 | 160 |
161 DCCallVM_vt gVT_arm32_arm = | |
162 { | |
163 &dc_callvm_free_arm32_arm | |
164 , &dc_callvm_reset_arm32_arm | |
165 , &dc_callvm_mode_arm32_arm | |
166 , &dc_callvm_argBool_arm32_arm | |
167 , &dc_callvm_argChar_arm32_arm | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
366
diff
changeset
|
168 , &dc_callvm_argShort_arm32_arm |
0 | 169 , &dc_callvm_argInt_arm32_arm |
170 , &dc_callvm_argLong_arm32_arm | |
171 , &dc_callvm_argLongLong_arm32_arm | |
172 , &dc_callvm_argFloat_arm32_arm | |
173 , &dc_callvm_argDouble_arm32_arm | |
174 , &dc_callvm_argPointer_arm32_arm | |
175 , NULL /* argStruct */ | |
176 , (DCvoidvmfunc*) &dc_callvm_call_arm32_arm | |
177 , (DCboolvmfunc*) &dc_callvm_call_arm32_arm | |
178 , (DCcharvmfunc*) &dc_callvm_call_arm32_arm | |
179 , (DCshortvmfunc*) &dc_callvm_call_arm32_arm | |
180 , (DCintvmfunc*) &dc_callvm_call_arm32_arm | |
181 , (DClongvmfunc*) &dc_callvm_call_arm32_arm | |
182 , (DClonglongvmfunc*) &dc_callvm_call_arm32_arm | |
183 , (DCfloatvmfunc*) &dc_callvm_call_arm32_arm | |
184 , (DCdoublevmfunc*) &dc_callvm_call_arm32_arm | |
185 , (DCpointervmfunc*) &dc_callvm_call_arm32_arm | |
186 , NULL /* callStruct */ | |
187 }; | |
188 | |
189 DCCallVM_vt gVT_arm32_arm_eabi = | |
190 { | |
191 &dc_callvm_free_arm32_arm | |
192 , &dc_callvm_reset_arm32_arm | |
193 , &dc_callvm_mode_arm32_arm | |
194 , &dc_callvm_argBool_arm32_arm | |
195 , &dc_callvm_argChar_arm32_arm | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
366
diff
changeset
|
196 , &dc_callvm_argShort_arm32_arm |
0 | 197 , &dc_callvm_argInt_arm32_arm |
198 , &dc_callvm_argLong_arm32_arm | |
199 , &dc_callvm_argLongLong_arm32_arm_eabi | |
200 , &dc_callvm_argFloat_arm32_arm | |
201 , &dc_callvm_argDouble_arm32_arm_eabi | |
202 , &dc_callvm_argPointer_arm32_arm | |
203 , NULL /* argStruct */ | |
204 , (DCvoidvmfunc*) &dc_callvm_call_arm32_arm | |
205 , (DCboolvmfunc*) &dc_callvm_call_arm32_arm | |
206 , (DCcharvmfunc*) &dc_callvm_call_arm32_arm | |
207 , (DCshortvmfunc*) &dc_callvm_call_arm32_arm | |
208 , (DCintvmfunc*) &dc_callvm_call_arm32_arm | |
209 , (DClongvmfunc*) &dc_callvm_call_arm32_arm | |
210 , (DClonglongvmfunc*) &dc_callvm_call_arm32_arm | |
211 , (DCfloatvmfunc*) &dc_callvm_call_arm32_arm | |
212 , (DCdoublevmfunc*) &dc_callvm_call_arm32_arm | |
213 , (DCpointervmfunc*) &dc_callvm_call_arm32_arm | |
214 , NULL /* callStruct */ | |
215 }; | |
216 | |
84 | 217 static void dc_callvm_mode_arm32_arm(DCCallVM* in_self, DCint mode) |
218 { | |
219 DCCallVM_arm32_arm* self = (DCCallVM_arm32_arm*)in_self; | |
220 DCCallVM_vt* vt; | |
0 | 221 |
84 | 222 switch(mode) { |
223 case DC_CALL_C_ELLIPSIS: | |
224 case DC_CALL_C_ELLIPSIS_VARARGS: | |
0 | 225 /* Check OS if we need EABI as default. */ |
226 #if defined(DC__ABI_ARM_EABI) | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
366
diff
changeset
|
227 case DC_CALL_C_DEFAULT: |
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
366
diff
changeset
|
228 case DC_CALL_C_DEFAULT_THIS: vt = &gVT_arm32_arm_eabi; break; |
0 | 229 #else |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
366
diff
changeset
|
230 case DC_CALL_C_DEFAULT: |
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
366
diff
changeset
|
231 case DC_CALL_C_DEFAULT_THIS: vt = &gVT_arm32_arm; break; |
0 | 232 #endif |
84 | 233 case DC_CALL_C_ARM_ARM: vt = &gVT_arm32_arm; break; |
234 case DC_CALL_C_ARM_ARM_EABI: vt = &gVT_arm32_arm_eabi; break; | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
366
diff
changeset
|
235 default: |
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
366
diff
changeset
|
236 self->mInterface.mError = DC_ERROR_UNSUPPORTED_MODE; |
84 | 237 return; |
238 } | |
239 dc_callvm_base_init(&self->mInterface, vt); | |
0 | 240 } |
241 | |
84 | 242 /* Public API. */ |
243 DCCallVM* dcNewCallVM(DCsize size) | |
0 | 244 { |
84 | 245 /* Store at least 16 bytes (4 words) for internal spill area. Assembly code depends on it. */ |
246 DCCallVM_arm32_arm* p = (DCCallVM_arm32_arm*)dcAllocMem(sizeof(DCCallVM_arm32_arm)+size+16); | |
247 | |
248 dc_callvm_mode_arm32_arm((DCCallVM*)p, DC_CALL_C_DEFAULT); | |
249 | |
250 dcVecInit(&p->mVecHead, size); | |
251 | |
252 return (DCCallVM*)p; | |
0 | 253 } |
254 |