Mercurial > pub > dyncall > dyncall
annotate dyncall/dyncall_callvm_mips_o32.c @ 546:ba70fb631bea
x64:
* support for non-standard aggr-by-value packing (#pragma pack, etc.)
* callbacks: handling callconv prefixes in signature
author | Tassilo Philipp |
---|---|
date | Tue, 31 May 2022 19:29:34 +0200 |
parents | 71c884e610f0 |
children |
rev | line source |
---|---|
0 | 1 /* |
2 | |
3 Package: dyncall | |
4 Library: dyncall | |
5 File: dyncall/dyncall_callvm_mips_o32.c | |
6 Description: mips "o32" ABI callvm implementation | |
7 License: | |
8 | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
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 mips o32 abi | |
31 | |
32 REVISION | |
33 2010/06/03 initial | |
34 | |
35 NOTES: | |
36 we need an argument counter for supporting floating point arguments | |
37 correctly. | |
38 | |
39 first two (if any) double/float arguments are mapped via a common structure -- | |
40 code must take care to write the right float argument indices which | |
41 differs on C and Assembly-side depending on endianness. (therefore | |
42 both sources have two variants 'mipseb' and 'mipsel'.) | |
43 (only for the first two float/double arguments) see float/double handling | |
44 | |
45 although, the abi does not expect usage of floats if first argument is | |
46 not floating point, the call kernel can be used universal for all cases. | |
47 | |
48 */ | |
49 | |
50 | |
51 #include "dyncall_callvm_mips_o32.h" | |
52 #include "dyncall_alloc.h" | |
53 #include "dyncall_utils.h" | |
54 | |
55 | |
366
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
323
diff
changeset
|
56 void dcCall_mips_o32(DCpointer target, DCRegData_mips_o32* regdata, DCsize stksize, DCpointer stkdata); |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
323
diff
changeset
|
57 |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
323
diff
changeset
|
58 |
0 | 59 static void dc_callvm_reset_mips_o32(DCCallVM* in_self) |
60 { | |
61 DCCallVM_mips_o32* self = (DCCallVM_mips_o32*)in_self; | |
62 dcVecReset(&self->mVecHead); | |
63 self->mArgCount = 0; | |
64 } | |
65 | |
66 | |
67 static void dc_callvm_free_mips_o32(DCCallVM* in_self) | |
68 { | |
69 dcFreeMem(in_self); | |
70 } | |
71 | |
72 /* arg int -- fillup integer register file OR push on stack */ | |
73 | |
74 static void dc_callvm_argInt_mips_o32(DCCallVM* in_self, DCint i) | |
75 { | |
76 DCCallVM_mips_o32* self = (DCCallVM_mips_o32*)in_self; | |
77 dcVecAppend(&self->mVecHead, &i, sizeof(DCint)); | |
78 self->mArgCount++; | |
79 } | |
80 | |
81 static void dc_callvm_argPointer_mips_o32(DCCallVM* in_self, DCpointer x) | |
82 { | |
302
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
83 dc_callvm_argInt_mips_o32(in_self, *(DCint*)&x); |
0 | 84 } |
85 | |
86 static void dc_callvm_argBool_mips_o32(DCCallVM* in_self, DCbool x) | |
87 { | |
88 dc_callvm_argInt_mips_o32(in_self, (DCint)x); | |
89 } | |
90 | |
91 static void dc_callvm_argChar_mips_o32(DCCallVM* in_self, DCchar x) | |
92 { | |
93 dc_callvm_argInt_mips_o32(in_self, (DCint)x); | |
94 } | |
95 | |
96 static void dc_callvm_argShort_mips_o32(DCCallVM* in_self, DCshort x) | |
97 { | |
98 dc_callvm_argInt_mips_o32(in_self, (DCint)x); | |
99 } | |
100 | |
101 static void dc_callvm_argLong_mips_o32(DCCallVM* in_self, DClong x) | |
102 { | |
103 dc_callvm_argInt_mips_o32(in_self, (DCint)x); | |
104 } | |
105 | |
302
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
106 static void dc_callvm_argLongLong_mips_o32(DCCallVM* in_self, DClonglong x) |
0 | 107 { |
108 DCCallVM_mips_o32* self = (DCCallVM_mips_o32*)in_self; | |
302
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
109 |
0 | 110 /* 64-bit values need to be aligned on 8 byte boundaries */ |
111 dcVecSkip(&self->mVecHead, dcVecSize(&self->mVecHead) & 4); | |
302
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
112 dcVecAppend(&self->mVecHead, &x, sizeof(DClonglong)); |
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
113 self->mArgCount++; |
0 | 114 } |
115 | |
116 static void dc_callvm_argFloat_mips_o32(DCCallVM* in_self, DCfloat x) | |
117 { | |
118 DCCallVM_mips_o32* self = (DCCallVM_mips_o32*)in_self; | |
119 | |
302
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
120 dcVecAppend(&self->mVecHead, &x, sizeof(DCfloat)); |
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
121 |
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
122 #if defined(DC__ABI_HARDFLOAT) |
0 | 123 if (self->mArgCount < 2) { |
305 | 124 /* @@@ unsure if we should zero init, here; seems to work as-is */ |
302
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
125 # if defined(DC__Endian_LITTLE) |
0 | 126 self->mRegData.u[self->mArgCount].f[0] = x; |
302
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
127 # else |
465
e2899b4ff713
- // -> /* */, mainly for consistency (but also for a few obscure compilers)
Tassilo Philipp
parents:
366
diff
changeset
|
128 self->mRegData.u[self->mArgCount].f[1] = x; /* floats in regs always right justified */ |
302
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
129 # endif |
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
130 # if 0 |
0 | 131 self->mRegData.u[self->mArgCount].f[1] = x; |
132 call kernel | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
133 |
302
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
134 mips: |
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
135 lwc1 $f12, 4($5) <--- byte offset 4 |
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
136 lwc1 $f13, 0($5) |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
137 lwc1 $f14, 12($5) <--- byte offset 12 |
302
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
138 lwc1 $f15, 8($5) |
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
139 mipsel: |
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
140 lwc1 $f12, 0($5) <--- byte offset 4 |
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
141 lwc1 $f13, 4($5) |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
142 lwc1 $f14, 8($5) <--- byte offset 12 |
302
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
143 lwc1 $f15, 12($5) |
0 | 144 |
302
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
145 # if defined(DC__Endian_LITTLE) |
0 | 146 /* index 0 and 2 */ |
147 self->mRegData.floats[self->mArgCount*2] = x; | |
302
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
148 # else |
0 | 149 /* index 1 and 3 */ |
150 self->mRegData.floats[self->mArgCount*2+1] = x; | |
302
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
151 # endif |
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
152 # endif |
0 | 153 } |
302
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
154 #endif /* DC__ABI_HARDFLOAT */ |
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
155 |
0 | 156 self->mArgCount++; |
157 } | |
158 | |
159 static void dc_callvm_argDouble_mips_o32(DCCallVM* in_self, DCdouble x) | |
160 { | |
161 DCCallVM_mips_o32* self = (DCCallVM_mips_o32*)in_self; | |
162 /* 64-bit values need to be aligned on 8 byte boundaries */ | |
163 dcVecSkip(&self->mVecHead, dcVecSize(&self->mVecHead) & 4); | |
302
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
164 dcVecAppend(&self->mVecHead, &x, sizeof(DCdouble)); |
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
165 |
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
166 #if defined(DC__ABI_HARDFLOAT) |
0 | 167 if (self->mArgCount < 2) |
168 self->mRegData.u[self->mArgCount].d = x; | |
302
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
169 #endif /* DC__ABI_HARDFLOAT */ |
d55f9d508074
- mips softfloat support for o32 callconv (calls and callbacks, little and big endian)
Tassilo Philipp
parents:
281
diff
changeset
|
170 |
0 | 171 self->mArgCount++; |
172 } | |
173 | |
174 /* Call. */ | |
175 void dc_callvm_call_mips_o32(DCCallVM* in_self, DCpointer target) | |
176 { | |
177 DCCallVM_mips_o32* self = (DCCallVM_mips_o32*)in_self; | |
178 | |
323
6ffb6a00cf55
- cosmetics and comments cleanup for readability
Tassilo Philipp
parents:
305
diff
changeset
|
179 /* provide multiple of 8 (reflecting stack area alignment requirement), and |
6ffb6a00cf55
- cosmetics and comments cleanup for readability
Tassilo Philipp
parents:
305
diff
changeset
|
180 minimum of 16-bytes (to hold first 4 int regis as spill area ($4-$7)) */ |
0 | 181 size_t size = DC_MAX(16, ( ( (unsigned) dcVecSize(&self->mVecHead) ) +7UL ) & (-8UL) ); |
182 | |
183 dcCall_mips_o32(target, &self->mRegData, size, dcVecData(&self->mVecHead)); | |
184 } | |
185 | |
84 | 186 static void dc_callvm_mode_mips_o32(DCCallVM* in_self, DCint mode); |
187 | |
0 | 188 DCCallVM_vt gVT_mips_o32 = |
189 { | |
190 &dc_callvm_free_mips_o32 | |
191 , &dc_callvm_reset_mips_o32 | |
192 , &dc_callvm_mode_mips_o32 | |
193 , &dc_callvm_argBool_mips_o32 | |
194 , &dc_callvm_argChar_mips_o32 | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
195 , &dc_callvm_argShort_mips_o32 |
0 | 196 , &dc_callvm_argInt_mips_o32 |
197 , &dc_callvm_argLong_mips_o32 | |
198 , &dc_callvm_argLongLong_mips_o32 | |
199 , &dc_callvm_argFloat_mips_o32 | |
200 , &dc_callvm_argDouble_mips_o32 | |
201 , &dc_callvm_argPointer_mips_o32 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
202 , NULL /* argAggr */ |
0 | 203 , (DCvoidvmfunc*) &dc_callvm_call_mips_o32 |
204 , (DCboolvmfunc*) &dc_callvm_call_mips_o32 | |
205 , (DCcharvmfunc*) &dc_callvm_call_mips_o32 | |
206 , (DCshortvmfunc*) &dc_callvm_call_mips_o32 | |
207 , (DCintvmfunc*) &dc_callvm_call_mips_o32 | |
208 , (DClongvmfunc*) &dc_callvm_call_mips_o32 | |
209 , (DClonglongvmfunc*) &dc_callvm_call_mips_o32 | |
210 , (DCfloatvmfunc*) &dc_callvm_call_mips_o32 | |
211 , (DCdoublevmfunc*) &dc_callvm_call_mips_o32 | |
212 , (DCpointervmfunc*) &dc_callvm_call_mips_o32 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
213 , NULL /* callAggr */ |
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
214 , NULL /* beginAggr */ |
0 | 215 }; |
216 | |
84 | 217 /* mode: only a single mode available currently. */ |
218 static void dc_callvm_mode_mips_o32(DCCallVM* in_self, DCint mode) | |
0 | 219 { |
84 | 220 DCCallVM_mips_o32* self = (DCCallVM_mips_o32*)in_self; |
221 DCCallVM_vt* vt; | |
222 | |
223 switch(mode) { | |
224 case DC_CALL_C_DEFAULT: | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
225 case DC_CALL_C_DEFAULT_THIS: |
84 | 226 case DC_CALL_C_MIPS32_O32: |
227 case DC_CALL_C_ELLIPSIS: | |
228 case DC_CALL_C_ELLIPSIS_VARARGS: | |
229 vt = &gVT_mips_o32; | |
230 break; | |
231 default: | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
232 self->mInterface.mError = DC_ERROR_UNSUPPORTED_MODE; |
84 | 233 return; |
234 } | |
235 dc_callvm_base_init(&self->mInterface, vt); | |
0 | 236 } |
237 | |
84 | 238 /* Public API. */ |
0 | 239 DCCallVM* dcNewCallVM(DCsize size) |
240 { | |
84 | 241 DCCallVM_mips_o32* p = (DCCallVM_mips_o32*)dcAllocMem(sizeof(DCCallVM_mips_o32)+size); |
242 | |
243 dc_callvm_mode_mips_o32((DCCallVM*)p, DC_CALL_C_DEFAULT); | |
244 | |
245 dcVecInit(&p->mVecHead, size); | |
246 dc_callvm_reset_mips_o32((DCCallVM*)p); | |
247 | |
248 return (DCCallVM*)p; | |
0 | 249 } |
250 |