annotate dyncallback/dyncall_callback_x86.c @ 0:3e629dc19168

initial from svn dyncall-1745
author Daniel Adler
date Thu, 19 Mar 2015 22:24:28 +0100
parents
children d48a8b8d2ef9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
1 /*
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
2
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
3 Package: dyncall
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
4 Library: dyncallback
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
5 File: dyncallback/dyncall_callback_x86.c
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
6 Description: Callback - Implementation for x86
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
7 License:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
8
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
9 Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
10 Tassilo Philipp <tphilipp@potion-studios.com>
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
11
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
12 Permission to use, copy, modify, and distribute this software for any
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
13 purpose with or without fee is hereby granted, provided that the above
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
14 copyright notice and this permission notice appear in all copies.
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
15
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
16 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
17 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
18 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
19 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
21 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
22 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
23
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
24 */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
25
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
26
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
27
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
28 #include "dyncall_callback_x86.h"
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
29 #include "dyncall_args_x86.h"
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
30
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
31 #include "dyncall_alloc_wx.h"
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
32 #include "dyncall_signature.h"
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
33
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
34 /*
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
35 * assembly thunk entry for callbacks
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
36 */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
37
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
38 extern void dcCallbackThunkEntry();
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
39
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
40 /* compute stacksize for callee cleanup calling conventions:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
41 *
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
42 * stdcall,fastcall_ms,fastcall_gnu
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
43 */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
44
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
45 static int dcbCleanupSize_x86_cdecl(const char* signature)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
46 {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
47 return 0;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
48 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
49
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
50 static int dcbCleanupSize_x86_std(const char* signature)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
51 {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
52 const char* ptr = signature;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
53 int size = 0;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
54 char ch;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
55 while( (ch = *ptr++) != DC_SIGCHAR_ENDARG ) {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
56 switch(ch) {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
57 case DC_SIGCHAR_BOOL:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
58 case DC_SIGCHAR_CHAR:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
59 case DC_SIGCHAR_SHORT:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
60 case DC_SIGCHAR_INT:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
61 case DC_SIGCHAR_LONG:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
62 case DC_SIGCHAR_POINTER:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
63 case DC_SIGCHAR_UCHAR:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
64 case DC_SIGCHAR_USHORT:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
65 case DC_SIGCHAR_UINT:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
66 case DC_SIGCHAR_ULONG:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
67 case DC_SIGCHAR_STRING:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
68 case DC_SIGCHAR_FLOAT:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
69 size += 4;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
70 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
71 case DC_SIGCHAR_DOUBLE:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
72 case DC_SIGCHAR_LONGLONG:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
73 case DC_SIGCHAR_ULONGLONG:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
74 size += 8;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
75 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
76 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
77 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
78 return size;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
79 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
80
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
81 static int dcbCleanupSize_x86_this_ms(const char* signature)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
82 {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
83 const char* ptr = signature;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
84 int size = 0;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
85 char ch;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
86 while( (ch = *ptr++) != DC_SIGCHAR_ENDARG )
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
87 {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
88 switch(ch)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
89 {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
90 case DC_SIGCHAR_BOOL:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
91 case DC_SIGCHAR_CHAR:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
92 case DC_SIGCHAR_SHORT:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
93 case DC_SIGCHAR_INT:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
94 case DC_SIGCHAR_LONG:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
95 case DC_SIGCHAR_POINTER:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
96 case DC_SIGCHAR_UCHAR:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
97 case DC_SIGCHAR_USHORT:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
98 case DC_SIGCHAR_UINT:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
99 case DC_SIGCHAR_ULONG:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
100 case DC_SIGCHAR_STRING:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
101 case DC_SIGCHAR_FLOAT:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
102 size += 4;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
103 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
104 case DC_SIGCHAR_DOUBLE:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
105 case DC_SIGCHAR_LONGLONG:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
106 case DC_SIGCHAR_ULONGLONG:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
107 size += 8;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
108 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
109 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
110 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
111 return size;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
112 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
113
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
114 static int dcbCleanupSize_x86_fast_ms(const char* signature)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
115 {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
116 const char* ptr = signature;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
117 int size = 0;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
118 int regs = 0;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
119 char ch;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
120 while( (ch = *ptr++) != DC_SIGCHAR_ENDARG )
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
121 {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
122 switch(ch)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
123 {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
124 case DC_SIGCHAR_BOOL:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
125 case DC_SIGCHAR_CHAR:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
126 case DC_SIGCHAR_SHORT:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
127 case DC_SIGCHAR_INT:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
128 case DC_SIGCHAR_LONG:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
129 case DC_SIGCHAR_POINTER:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
130 case DC_SIGCHAR_UCHAR:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
131 case DC_SIGCHAR_USHORT:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
132 case DC_SIGCHAR_UINT:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
133 case DC_SIGCHAR_ULONG:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
134 case DC_SIGCHAR_STRING:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
135 if (regs < 2) regs++;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
136 else size += 4;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
137 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
138 case DC_SIGCHAR_FLOAT:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
139 size += 4;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
140 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
141 case DC_SIGCHAR_DOUBLE:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
142 size += 8;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
143 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
144 case DC_SIGCHAR_LONGLONG:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
145 case DC_SIGCHAR_ULONGLONG:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
146 size += 8;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
147 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
148 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
149 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
150 return size;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
151 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
152
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
153 static int dcbCleanupSize_x86_fast_gnu(const char* signature)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
154 {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
155 const char* ptr = signature;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
156 char ch;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
157 int size = 0;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
158 int regs = 0;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
159 while( (ch = *ptr++) != DC_SIGCHAR_ENDARG ) {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
160 switch(ch) {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
161 case DC_SIGCHAR_FLOAT:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
162 size += 4;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
163 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
164 case DC_SIGCHAR_DOUBLE:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
165 size += 8;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
166 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
167 case DC_SIGCHAR_LONGLONG:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
168 case DC_SIGCHAR_ULONGLONG:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
169 regs = 2;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
170 size += 8;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
171 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
172 default:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
173 if (regs < 2) regs++;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
174 else size += 4;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
175 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
176 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
177 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
178 return size;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
179 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
180
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
181 void dcbInitCallback(DCCallback* pcb, const char* signature, DCCallbackHandler* handler, void* userdata)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
182 {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
183 const char* ptr;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
184 char ch;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
185 int mode;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
186 pcb->handler = handler;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
187 pcb->userdata = userdata;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
188
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
189 ptr = signature;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
190 ch = *ptr;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
191
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
192 /* x86 hints: */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
193
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
194 mode = DC_CALL_C_X86_CDECL;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
195
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
196 if(ch == DC_SIGCHAR_CC_PREFIX)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
197 {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
198 ptr++;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
199 ch = *ptr++;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
200 switch(ch) {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
201 case DC_SIGCHAR_CC_STDCALL: mode = DC_CALL_C_X86_WIN32_STD; break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
202 case DC_SIGCHAR_CC_THISCALL_MS: mode = DC_CALL_C_X86_WIN32_THIS_MS; break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
203 case DC_SIGCHAR_CC_FASTCALL_GNU: mode = DC_CALL_C_X86_WIN32_FAST_GNU; break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
204 case DC_SIGCHAR_CC_FASTCALL_MS: mode = DC_CALL_C_X86_WIN32_FAST_MS; break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
205 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
206 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
207
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
208 /* x86 configuration: */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
209
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
210 switch(mode) {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
211 case DC_CALL_C_X86_CDECL:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
212 pcb->args_vt = &dcArgsVT_default;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
213 pcb->stack_cleanup = dcbCleanupSize_x86_cdecl(ptr);
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
214 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
215 case DC_CALL_C_X86_WIN32_STD:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
216 pcb->args_vt = &dcArgsVT_default;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
217 pcb->stack_cleanup = dcbCleanupSize_x86_std(ptr);
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
218 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
219 case DC_CALL_C_X86_WIN32_THIS_MS:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
220 pcb->args_vt = &dcArgsVT_this_ms;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
221 pcb->stack_cleanup = dcbCleanupSize_x86_this_ms(ptr);
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
222 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
223 case DC_CALL_C_X86_WIN32_FAST_MS:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
224 pcb->args_vt = &dcArgsVT_fast_ms;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
225 pcb->stack_cleanup = dcbCleanupSize_x86_fast_ms(ptr);
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
226 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
227 case DC_CALL_C_X86_WIN32_FAST_GNU:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
228 pcb->args_vt = &dcArgsVT_fast_gnu;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
229 pcb->stack_cleanup = dcbCleanupSize_x86_fast_gnu(ptr);
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
230 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
231 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
232
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
233 #if defined(DC_PLAN9)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
234 /* HACK for Plan9 - 'reuse' pcb->stack_cleanup as a flag
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
235 to indicate if return value is 64bit. The field is not
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
236 used anyways as the caller is responsible to clean up
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
237 the stack in Plan9. If set to '1' the callback kernel
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
238 takes into account an extra stack-parameter (pointer
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
239 to 64bit return value).
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
240 I thought of introducing a new field, but for one single
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
241 x86 calling convention out of many, it seemed overkill
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
242 to change the struct for everybody else. Maybe renaming
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
243 would be a good idea, though. ~ Tassilo
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
244 */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
245 while(*ptr) {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
246 if(*ptr++ == DC_SIGCHAR_ENDARG) {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
247 pcb->stack_cleanup = (*ptr == DC_SIGCHAR_LONGLONG) || (*ptr == DC_SIGCHAR_ULONGLONG);
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
248 break;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
249 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
250 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
251 #endif
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
252 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
253
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
254 /*
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
255 * callback constructor
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
256 */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
257
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
258 DCCallback* dcbNewCallback(const char* signature, DCCallbackHandler* handler, void* userdata)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
259 {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
260 int err;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
261 DCCallback* pcb;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
262 err = dcAllocWX(sizeof(DCCallback), (void**) &pcb);
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
263 if (err != 0) return 0;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
264
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
265 dcbInitThunk(&pcb->thunk, dcCallbackThunkEntry);
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
266 dcbInitCallback(pcb, signature, handler, userdata);
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
267 return pcb;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
268 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
269
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
270 /*
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
271 * free
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
272 */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
273
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
274 void dcbFreeCallback(DCCallback* pcb)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
275 {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
276 dcFreeWX(pcb, sizeof(DCCallback));
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
277 }
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
278
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
279 void* dcbGetUserData(DCCallback* pcb)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
280 {
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
281 return pcb->userdata;
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
282 }