comparison dyncall/dyncall_callvm_x64.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_x64.c
6 Description:
7 License:
8
9 Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
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 /* MS Windows x64 calling convention, AMD64 SystemV ABI. */
30
31
32 #include "dyncall_callvm_x64.h"
33 #include "dyncall_alloc.h"
34 #include "dyncall_struct.h"
35
36 static DCCallVM* dc_callvm_new_x64(DCCallVM_vt* vt, DCsize size)
37 {
38 DCCallVM_x64* self = (DCCallVM_x64*)dcAllocMem(sizeof(DCCallVM_x64)+size);
39
40 dc_callvm_base_init(&self->mInterface, vt);
41
42 /* Since we store register parameters in DCCallVM_x64 directly, adjust the stack size. */
43 size -= sizeof(DCRegData_x64);
44 size = (((signed long)size) < 0) ? 0 : size;
45
46
47 self->mRegCount.i = self->mRegCount.f = 0;
48
49 dcVecInit(&self->mVecHead, size);
50 return (DCCallVM*)self;
51 }
52
53
54 static void dc_callvm_free_x64(DCCallVM* in_self)
55 {
56 dcFreeMem(in_self);
57 }
58
59
60 static void dc_callvm_reset_x64(DCCallVM* in_self)
61 {
62 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
63 dcVecReset(&self->mVecHead);
64 self->mRegCount.i = self->mRegCount.f = 0;
65 }
66
67
68 static void dc_callvm_mode_x64(DCCallVM* self, DCint mode)
69 {
70 switch(mode) {
71 case DC_CALL_C_DEFAULT:
72 case DC_CALL_C_ELLIPSIS:
73 break;
74 default:
75 self->mError = DC_ERROR_UNSUPPORTED_MODE;
76 break;
77 }
78 }
79
80
81 static void dc_callvm_argLongLong_x64(DCCallVM* in_self, DClonglong x)
82 {
83 /* A long long always has 64 bits on the supported x64 platforms (lp64 on unix and llp64 on windows). */
84 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
85 if(self->mRegCount.i < numIntRegs)
86 self->mRegData.i[self->mRegCount.i++] = x;
87 else
88 dcVecAppend(&self->mVecHead, &x, sizeof(DClonglong));
89 }
90
91
92 static void dc_callvm_argBool_x64(DCCallVM* in_self, DCbool x)
93 {
94 dc_callvm_argLongLong_x64(in_self, (DClonglong)x);
95 }
96
97
98 static void dc_callvm_argChar_x64(DCCallVM* in_self, DCchar x)
99 {
100 dc_callvm_argLongLong_x64(in_self, x);
101 }
102
103
104 static void dc_callvm_argShort_x64(DCCallVM* in_self, DCshort x)
105 {
106 dc_callvm_argLongLong_x64(in_self, x);
107 }
108
109
110 static void dc_callvm_argInt_x64(DCCallVM* in_self, DCint x)
111 {
112 dc_callvm_argLongLong_x64(in_self, x);
113 }
114
115
116 static void dc_callvm_argLong_x64(DCCallVM* in_self, DClong x)
117 {
118 dc_callvm_argLongLong_x64(in_self, x);
119 }
120
121
122 static void dc_callvm_argFloat_x64(DCCallVM* in_self, DCfloat x)
123 {
124 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
125
126 /* Although not promoted to doubles, floats are stored with 64bits in this API.*/
127 union {
128 DCdouble d;
129 DCfloat f;
130 } f;
131 f.f = x;
132
133 if(self->mRegCount.f < numFloatRegs)
134 *(DCfloat*)&self->mRegData.f[self->mRegCount.f++] = x;
135 else
136 dcVecAppend(&self->mVecHead, &f.f, sizeof(DCdouble));
137 }
138
139
140 static void dc_callvm_argDouble_x64(DCCallVM* in_self, DCdouble x)
141 {
142 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
143 if(self->mRegCount.f < numFloatRegs)
144 self->mRegData.f[self->mRegCount.f++] = x;
145 else
146 dcVecAppend(&self->mVecHead, &x, sizeof(DCdouble));
147 }
148
149
150 static void dc_callvm_argPointer_x64(DCCallVM* in_self, DCpointer x)
151 {
152 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
153 if(self->mRegCount.i < numIntRegs)
154 *(DCpointer*)&self->mRegData.i[self->mRegCount.i++] = x;
155 else
156 dcVecAppend(&self->mVecHead, &x, sizeof(DCpointer));
157 }
158
159 static void dc_callvm_argStruct_x64(DCCallVM* in_self, DCstruct* s, DCpointer x)
160 {
161 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
162 dcVecAppend(&self->mVecHead, x, s->size);
163 /*printf("dc_callvm_argStruct_x64 size = %d\n", (int)s->size);@@@*/
164 if (s->size <= 64)
165 dcArgStructUnroll(in_self, s, x);
166 /*else@@@*/
167 /* dcVecAppend(&self->mVecHead, &x, sizeof(DCpointer));@@@*/
168 }
169
170
171 /* Call. */
172 void dc_callvm_call_x64(DCCallVM* in_self, DCpointer target)
173 {
174 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
175 #if defined(DC_UNIX)
176 dcCall_x64_sysv(
177 #else
178 dcCall_x64_win64(
179 #endif
180 dcVecSize(&self->mVecHead), /* Size of stack data. */
181 dcVecData(&self->mVecHead), /* Pointer to stack arguments. */
182 self->mRegData.i, /* Pointer to register arguments (ints on SysV). */
183 #if defined(DC_UNIX)
184 self->mRegData.f, /* Pointer to floating point register arguments. */
185 #endif
186 target
187 );
188 }
189
190
191 DCCallVM_vt gVT_x64 =
192 {
193 &dc_callvm_free_x64
194 , &dc_callvm_reset_x64
195 , &dc_callvm_mode_x64
196 , &dc_callvm_argBool_x64
197 , &dc_callvm_argChar_x64
198 , &dc_callvm_argShort_x64
199 , &dc_callvm_argInt_x64
200 , &dc_callvm_argLong_x64
201 , &dc_callvm_argLongLong_x64
202 , &dc_callvm_argFloat_x64
203 , &dc_callvm_argDouble_x64
204 , &dc_callvm_argPointer_x64
205 , &dc_callvm_argStruct_x64
206 , (DCvoidvmfunc*) &dc_callvm_call_x64
207 , (DCboolvmfunc*) &dc_callvm_call_x64
208 , (DCcharvmfunc*) &dc_callvm_call_x64
209 , (DCshortvmfunc*) &dc_callvm_call_x64
210 , (DCintvmfunc*) &dc_callvm_call_x64
211 , (DClongvmfunc*) &dc_callvm_call_x64
212 , (DClonglongvmfunc*) &dc_callvm_call_x64
213 , (DCfloatvmfunc*) &dc_callvm_call_x64
214 , (DCdoublevmfunc*) &dc_callvm_call_x64
215 , (DCpointervmfunc*) &dc_callvm_call_x64
216 , NULL /* callStruct */
217 };
218
219
220 DCCallVM* dcNewCallVM_x64(DCsize size)
221 {
222 return dc_callvm_new_x64(&gVT_x64, size);
223 }
224
225 DCCallVM* dcNewCallVM(DCsize size)
226 {
227 return dcNewCallVM_x64(size);
228 }
229