Mercurial > pub > dyncall > dyncall
comparison dyncall/dyncall_callvm_sparc64.c @ 0:3e629dc19168
initial from svn dyncall-1745
author | Daniel Adler |
---|---|
date | Thu, 19 Mar 2015 22:24:28 +0100 |
parents | |
children | 67961454902b |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3e629dc19168 |
---|---|
1 /* | |
2 | |
3 Package: dyncall | |
4 Library: dyncall | |
5 File: dyncall/dyncall_callvm_sparc64.c | |
6 Description: Call VM for sparc64 64-bit processor architecture. | |
7 License: | |
8 | |
9 Copyright (c) 2011-2015 Daniel Adler <dadler@uni-goettingen.de> | |
10 | |
11 Permission to use, copy, modify, and distribute this software for any | |
12 purpose with or without fee is hereby granted, provided that the above | |
13 copyright notice and this permission notice appear in all copies. | |
14 | |
15 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
16 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
17 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
18 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
22 | |
23 */ | |
24 | |
25 | |
26 | |
27 #include "dyncall_callvm_sparc64.h" | |
28 #include "dyncall_call_sparc64.h" | |
29 #include "dyncall_alloc.h" | |
30 | |
31 #define IREGS 6 | |
32 #define FREGS 16 | |
33 #define SREGS 16 | |
34 #define DHEAD (IREGS+FREGS)*8+SREGS*4 | |
35 | |
36 /* Reset argument buffer. */ | |
37 static void dc_callvm_reset_sparc64(DCCallVM* in_self) | |
38 { | |
39 DCCallVM_sparc64* self = (DCCallVM_sparc64*)in_self; | |
40 dcVecResize(&self->mVecHead,DHEAD); | |
41 self->mIntRegs = 0; | |
42 self->mFloatRegs = 0; | |
43 self->mUseSingleFlags = 0; | |
44 } | |
45 | |
46 /* Construtor. */ | |
47 /* the six output registers %o0-%o5 are always loaded, thus we need to ensure the argument buffer has space for at least 24 bytes. */ | |
48 static DCCallVM* dc_callvm_new_sparc64(DCCallVM_vt* vt, DCsize size) | |
49 { | |
50 DCCallVM_sparc64* self = (DCCallVM_sparc64*) dcAllocMem(sizeof(DCCallVM_sparc64)+DHEAD+size); | |
51 dc_callvm_base_init(&self->mInterface, vt); | |
52 dcVecInit(&self->mVecHead,DHEAD+size); | |
53 dc_callvm_reset_sparc64(&self->mInterface); | |
54 return (DCCallVM*)self; | |
55 } | |
56 | |
57 /* Destructor. */ | |
58 static void dc_callvm_free_sparc64(DCCallVM* in_self) | |
59 { | |
60 dcFreeMem(in_self); | |
61 } | |
62 | |
63 /* all integers are promoted to 64-bit. */ | |
64 | |
65 static void dc_callvm_argLongLong_sparc64(DCCallVM* in_self, DClonglong x) | |
66 { | |
67 DCCallVM_sparc64* self = (DCCallVM_sparc64*)in_self; | |
68 if (self->mIntRegs < IREGS) { | |
69 * ( (DClonglong*) ( dcVecAt(&self->mVecHead, (self->mIntRegs++)*8) ) ) = x; | |
70 } else { | |
71 dcVecAppend(&self->mVecHead, &x, sizeof(DClonglong)); | |
72 } | |
73 if (self->mFloatRegs < FREGS) self->mFloatRegs++; | |
74 } | |
75 | |
76 static void dc_callvm_argLong_sparc64 (DCCallVM* in_self, DClong x) { dc_callvm_argLongLong_sparc64(in_self, (DClonglong) x ); } | |
77 static void dc_callvm_argInt_sparc64 (DCCallVM* in_self, DCint x) { dc_callvm_argLongLong_sparc64(in_self, (DClonglong) x ); } | |
78 static void dc_callvm_argBool_sparc64 (DCCallVM* in_self, DCbool x) { dc_callvm_argLongLong_sparc64(in_self, (DClonglong) x ); } | |
79 static void dc_callvm_argChar_sparc64 (DCCallVM* in_self, DCchar x) { dc_callvm_argLongLong_sparc64(in_self, (DClonglong) x ); } | |
80 static void dc_callvm_argShort_sparc64 (DCCallVM* in_self, DCshort x) { dc_callvm_argLongLong_sparc64(in_self, (DClonglong) x ); } | |
81 static void dc_callvm_argPointer_sparc64(DCCallVM* in_self, DCpointer x) { dc_callvm_argLongLong_sparc64(in_self, (DClonglong) x ); } | |
82 | |
83 static void dc_callvm_argDouble_sparc64(DCCallVM* in_self, DCdouble x) | |
84 { | |
85 DCCallVM_sparc64* self = (DCCallVM_sparc64*)in_self; | |
86 if (self->mFloatRegs < FREGS) { | |
87 * ((double*)dcVecAt(&self->mVecHead,(IREGS+(self->mFloatRegs++))*8)) = x; | |
88 } | |
89 if (self->mIntRegs < IREGS) { | |
90 self->mIntRegs++; | |
91 } else { | |
92 dcVecAppend(&self->mVecHead, &x, sizeof(DCdouble)); | |
93 } | |
94 } | |
95 | |
96 static void dc_callvm_argDouble_sparc64_ellipsis(DCCallVM* in_self, DCdouble x) | |
97 { | |
98 union { | |
99 long long l; | |
100 double d; | |
101 } u; | |
102 u.d = x; | |
103 dc_callvm_argLongLong_sparc64(in_self, u.l); | |
104 } | |
105 | |
106 static void dc_callvm_argFloat_sparc64_ellipsis(DCCallVM* in_self, DCfloat x) | |
107 { | |
108 dc_callvm_argDouble_sparc64_ellipsis(in_self, (DCdouble) x); | |
109 } | |
110 | |
111 static void dc_callvm_argFloat_sparc64(DCCallVM* in_self, DCfloat x) | |
112 { | |
113 DCCallVM_sparc64* self = (DCCallVM_sparc64*)in_self; | |
114 if (self->mFloatRegs < FREGS) { | |
115 self->mUseSingleFlags |= 1<<self->mFloatRegs; | |
116 * ((float*)dcVecAt(&self->mVecHead,(IREGS+FREGS)*8 + (self->mFloatRegs++)*4)) = x; | |
117 } | |
118 | |
119 if (self->mIntRegs < IREGS) { | |
120 self->mIntRegs++; | |
121 } else { | |
122 union { | |
123 DCdouble d; | |
124 DClonglong l; | |
125 DCfloat f[2]; | |
126 } u; | |
127 u.f[1] = x; | |
128 dcVecAppend(&self->mVecHead, &u.l, sizeof(DClonglong)); | |
129 } | |
130 } | |
131 | |
132 #if 0 | |
133 /* call: delegate to default call kernel */ | |
134 static void dc_callvm_call_sparc64(DCCallVM* in_self, DCpointer target) | |
135 { | |
136 DCCallVM_sparc64* self = (DCCallVM_sparc64*)in_self; | |
137 dcCall_sparc64(target, dcVecSize(&self->mVecHead), dcVecData(&self->mVecHead)); | |
138 } | |
139 #endif | |
140 | |
141 static void dc_callvm_mode_sparc64(DCCallVM* in_self, DCint mode); | |
142 | |
143 DCCallVM_vt gVT_sparc64_ellipsis = | |
144 { | |
145 &dc_callvm_free_sparc64, | |
146 &dc_callvm_reset_sparc64, | |
147 &dc_callvm_mode_sparc64, | |
148 &dc_callvm_argBool_sparc64, | |
149 &dc_callvm_argChar_sparc64, | |
150 &dc_callvm_argShort_sparc64, | |
151 &dc_callvm_argInt_sparc64, | |
152 &dc_callvm_argLong_sparc64, | |
153 &dc_callvm_argLongLong_sparc64, | |
154 &dc_callvm_argFloat_sparc64_ellipsis, | |
155 &dc_callvm_argDouble_sparc64_ellipsis, | |
156 &dc_callvm_argPointer_sparc64, | |
157 NULL /* argStruct */, | |
158 (DCvoidvmfunc*) &dcCall_sparc64, | |
159 (DCboolvmfunc*) &dcCall_sparc64, | |
160 (DCcharvmfunc*) &dcCall_sparc64, | |
161 (DCshortvmfunc*) &dcCall_sparc64, | |
162 (DCintvmfunc*) &dcCall_sparc64, | |
163 (DClongvmfunc*) &dcCall_sparc64, | |
164 (DClonglongvmfunc*) &dcCall_sparc64, | |
165 (DCfloatvmfunc*) &dcCall_sparc64, | |
166 (DCdoublevmfunc*) &dcCall_sparc64, | |
167 (DCpointervmfunc*) &dcCall_sparc64, | |
168 NULL /* callStruct */ | |
169 }; | |
170 | |
171 /* CallVM virtual table. */ | |
172 DCCallVM_vt gVT_sparc64 = | |
173 { | |
174 &dc_callvm_free_sparc64, | |
175 &dc_callvm_reset_sparc64, | |
176 &dc_callvm_mode_sparc64, | |
177 &dc_callvm_argBool_sparc64, | |
178 &dc_callvm_argChar_sparc64, | |
179 &dc_callvm_argShort_sparc64, | |
180 &dc_callvm_argInt_sparc64, | |
181 &dc_callvm_argLong_sparc64, | |
182 &dc_callvm_argLongLong_sparc64, | |
183 &dc_callvm_argFloat_sparc64, | |
184 &dc_callvm_argDouble_sparc64, | |
185 &dc_callvm_argPointer_sparc64, | |
186 NULL /* argStruct */, | |
187 (DCvoidvmfunc*) &dcCall_sparc64, | |
188 (DCboolvmfunc*) &dcCall_sparc64, | |
189 (DCcharvmfunc*) &dcCall_sparc64, | |
190 (DCshortvmfunc*) &dcCall_sparc64, | |
191 (DCintvmfunc*) &dcCall_sparc64, | |
192 (DClongvmfunc*) &dcCall_sparc64, | |
193 (DClonglongvmfunc*) &dcCall_sparc64, | |
194 (DCfloatvmfunc*) &dcCall_sparc64, | |
195 (DCdoublevmfunc*) &dcCall_sparc64, | |
196 (DCpointervmfunc*) &dcCall_sparc64, | |
197 NULL /* callStruct */ | |
198 }; | |
199 | |
200 /* mode: only a single mode available currently. */ | |
201 static void dc_callvm_mode_sparc64(DCCallVM* in_self, DCint mode) | |
202 { | |
203 switch(mode) { | |
204 case DC_CALL_C_DEFAULT: | |
205 case DC_CALL_C_ELLIPSIS: | |
206 case DC_CALL_C_SPARC64: | |
207 in_self->mVTpointer = &gVT_sparc64; | |
208 break; | |
209 case DC_CALL_C_ELLIPSIS_VARARGS: | |
210 in_self->mVTpointer = &gVT_sparc64_ellipsis; | |
211 break; | |
212 default: | |
213 in_self->mError = DC_ERROR_UNSUPPORTED_MODE; | |
214 break; | |
215 } | |
216 } | |
217 | |
218 | |
219 /* Public API. */ | |
220 DCCallVM* dcNewCallVM(DCsize size) | |
221 { | |
222 return dc_callvm_new_sparc64(&gVT_sparc64,size); | |
223 } | |
224 | |
225 #if 0 | |
226 /* Load integer 32-bit. */ | |
227 static void dc_callvm_argInt_sparc64(DCCallVM* in_self, DCint x) | |
228 { | |
229 DCCallVM_sparc64* self = (DCCallVM_sparc64*)in_self; | |
230 dcVecAppend(&self->mVecHead, &x, sizeof(DCint)); | |
231 } | |
232 | |
233 /* we propagate Bool,Char,Short,Int to LongLong. */ | |
234 | |
235 static void dc_callvm_argBool_sparc64(DCCallVM* in_self, DCbool x) { dc_callvm_argInt_sparc64(in_self, (DCint)x); } | |
236 static void dc_callvm_argChar_sparc64(DCCallVM* in_self, DCchar x) { dc_callvm_argInt_sparc64(in_self, (DCint)x); } | |
237 static void dc_callvm_argShort_sparc64(DCCallVM* in_self, DCshort x) { dc_callvm_argInt_sparc64(in_self, (DCint)x); } | |
238 #endif | |
239 |