4 #if !(defined( _WIN32) || (defined(__FreeBSD__) && defined(__i386__)))
5 #define __fastcall __attribute((fastcall))
8 #ifndef __leading_underscore
14 /////////////////////////////////////////////////////////////////////////
15 ////////// TRAP FRAMEWORK
16 /////////////////////////////////////////////////////////////////////////
17 // if you cast 'TRAP' to a function pointer and call it,
18 // it will save all 8 registers,
19 // and jump into C-code (previously set using 'SET_TRAP_HANDLER(x)'),
20 // in C-code you can pop DWORDs from stack and modify registers
23 void *SYMBOL(trap_handler
);
25 extern unsigned char SYMBOL(trap
)[];
31 "addl $0x4, 0xc(%esp);"
33 "call *_trap_handler;"
35 "movl 0xc(%esp), %eax;"
36 "movl %eax, 0x20(%esp);"
43 unsigned edi
, esi
, ebp
, esp
, ebx
, edx
, ecx
, eax
;
47 #define M_FLOAT(addr) (*(float *)(addr))
48 #define M_DWORD(addr) (*(unsigned *)(addr))
49 #define M_WORD(addr) (*(unsigned short *)(addr))
50 #define M_BYTE(addr) (*(unsigned char *)(addr))
51 #define R_EAX ((tf)->eax)
52 #define R_ECX ((tf)->ecx)
53 #define R_EDX ((tf)->edx)
54 #define R_EBX ((tf)->ebx)
55 #define R_ESP ((tf)->esp)
56 #define R_EBP ((tf)->ebp)
57 #define R_ESI ((tf)->esi)
58 #define R_EDI ((tf)->edi)
60 #define ARG(x) (M_DWORD(R_ESP + (x) * 4))
62 #define RETN(x) do { \
63 M_DWORD(R_ESP + (x)) = M_DWORD(R_ESP); \
69 printf("EAX: %08X\n", R_EAX); \
70 printf("ECX: %08X\n", R_ECX); \
71 printf("EDX: %08X\n", R_EDX); \
72 printf("EBX: %08X\n", R_EBX); \
73 printf("ESP: %08X\n", R_ESP); \
74 printf("EBP: %08X\n", R_EBP); \
75 printf("ESI: %08X\n", R_ESI); \
76 printf("EDI: %08X\n", R_EDI); \
78 printf("[RETADDR]: %08X\n", M_DWORD(R_ESP)); \
79 for (i = 1; i <= 8; i++) { \
80 printf("[ARG%4d]: %08X\n", i, ARG(i)); \
84 #define SET_TRAP_HANDLER(x) ((SYMBOL(trap_handler)) = (x))
85 #define TRAP ((void *) &SYMBOL(trap))
89 /////////////////////////////////////////////////////////////////////////
90 ////////// SAFECALL FRAMEWORK
91 /////////////////////////////////////////////////////////////////////////
92 // this framework will convert any calling convention to cdecl
93 // usage: first set call target with 'SET_SAFECALL_TARGET(x)'
94 // then cast 'SAFECALL' to target function pointer type and invoke it
95 // after calling, 'ESPDIFF' is the difference of old and new esp
97 void *SYMBOL(sc_call_target
);
98 unsigned SYMBOL(sc_retn_addr
);
99 unsigned SYMBOL(sc_old_esp
);
100 unsigned SYMBOL(sc_new_esp
);
102 extern unsigned char SYMBOL(safecall
)[];
106 "popl _sc_retn_addr;"
107 "movl %esp, _sc_old_esp;"
108 "call *_sc_call_target;"
109 "movl %esp, _sc_new_esp;"
110 "movl _sc_old_esp, %esp;"
111 "jmp *_sc_retn_addr;"
114 #define SET_SAFECALL_TARGET(x) ((SYMBOL(sc_call_target)) = (x))
115 #define SAFECALL ((void *) &SYMBOL(safecall))
116 #define ESPDIFF (SYMBOL(sc_new_esp) - SYMBOL(sc_old_esp))
119 /////////////////////////////////////////////////////////////////////////
120 ////////// TEST FASTCALL INVOKE
121 /////////////////////////////////////////////////////////////////////////
123 void check_fastcall_invoke_0(struct trapframe
*tf
)
129 void check_fastcall_invoke_1(struct trapframe
*tf
)
132 assert(R_ECX
== 0x11111111);
135 void check_fastcall_invoke_2(struct trapframe
*tf
)
138 assert(R_ECX
== 0x11111111);
139 assert(R_EDX
== 0x22222222);
142 void check_fastcall_invoke_3(struct trapframe
*tf
)
145 assert(R_ECX
== 0x11111111);
146 assert(R_EDX
== 0x22222222);
147 assert(ARG(1) == 0x33333333);
150 void check_fastcall_invoke_4(struct trapframe
*tf
)
153 assert(R_ECX
== 0x11111111);
154 assert(R_EDX
== 0x22222222);
155 assert(ARG(1) == 0x33333333);
156 assert(ARG(2) == 0x44444444);
160 void check_fastcall_invoke_5(struct trapframe
*tf
)
163 assert(R_ECX
== 0x11111111);
164 assert(R_EDX
== 0x22222222);
165 assert(ARG(1) == 0x33333333);
166 assert(ARG(2) == 0x44444444);
167 assert(ARG(3) == 0x55555555);
171 void test_fastcall_invoke()
173 SET_TRAP_HANDLER(check_fastcall_invoke_0
);
174 ((void __fastcall (*)(void)) TRAP
)();
176 SET_TRAP_HANDLER(check_fastcall_invoke_1
);
177 ((void __fastcall (*)(unsigned)) TRAP
)(0x11111111);
179 SET_TRAP_HANDLER(check_fastcall_invoke_2
);
180 ((void __fastcall (*)(unsigned, unsigned)) TRAP
)(0x11111111, 0x22222222);
182 SET_TRAP_HANDLER(check_fastcall_invoke_3
);
183 ((void __fastcall (*)(unsigned, unsigned, unsigned)) TRAP
)(0x11111111, 0x22222222, 0x33333333);
185 SET_TRAP_HANDLER(check_fastcall_invoke_4
);
186 ((void __fastcall (*)(unsigned, unsigned, unsigned, unsigned)) TRAP
)(0x11111111, 0x22222222, 0x33333333, 0x44444444);
188 SET_TRAP_HANDLER(check_fastcall_invoke_5
);
189 ((void __fastcall (*)(unsigned, unsigned, unsigned, unsigned, unsigned)) TRAP
)(0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555);
193 /////////////////////////////////////////////////////////////////////////
194 ////////// TEST FUNCTION CODE GENERATION
195 /////////////////////////////////////////////////////////////////////////
197 int __fastcall
check_fastcall_espdiff_0(void)
202 int __fastcall
check_fastcall_espdiff_1(int a
)
207 int __fastcall
check_fastcall_espdiff_2(int a
, int b
)
212 int __fastcall
check_fastcall_espdiff_3(int a
, int b
, int c
)
217 int __fastcall
check_fastcall_espdiff_4(int a
, int b
, int c
, int d
)
219 return a
+ b
+ c
+ d
;
222 int __fastcall
check_fastcall_espdiff_5(int a
, int b
, int c
, int d
, int e
)
224 return a
+ b
+ c
+ d
+ e
;
227 void test_fastcall_espdiff()
230 SET_SAFECALL_TARGET(check_fastcall_espdiff_0
);
231 x
= ((typeof(&check_fastcall_espdiff_0
))SAFECALL
)();
233 assert(ESPDIFF
== 0);
235 SET_SAFECALL_TARGET(check_fastcall_espdiff_1
);
236 x
= ((typeof(&check_fastcall_espdiff_1
))SAFECALL
)(1);
238 assert(ESPDIFF
== 0);
240 SET_SAFECALL_TARGET(check_fastcall_espdiff_2
);
241 x
= ((typeof(&check_fastcall_espdiff_2
))SAFECALL
)(1, 2);
243 assert(ESPDIFF
== 0);
245 SET_SAFECALL_TARGET(check_fastcall_espdiff_3
);
246 x
= ((typeof(&check_fastcall_espdiff_3
))SAFECALL
)(1, 2, 3);
247 assert(x
== 1 + 2 + 3);
248 assert(ESPDIFF
== 1*4);
250 SET_SAFECALL_TARGET(check_fastcall_espdiff_4
);
251 x
= ((typeof(&check_fastcall_espdiff_4
))SAFECALL
)(1, 2, 3, 4);
252 assert(x
== 1 + 2 + 3 + 4);
253 assert(ESPDIFF
== 2*4);
255 SET_SAFECALL_TARGET(check_fastcall_espdiff_5
);
256 x
= ((typeof(&check_fastcall_espdiff_5
))SAFECALL
)(1, 2, 3, 4, 5);
257 assert(x
== 1 + 2 + 3 + 4 + 5);
258 assert(ESPDIFF
== 3*4);
266 for (i
= 1; i
<= N
; i
++) {
267 test_fastcall_espdiff();
270 for (i
= 1; i
<= N
; i
++) {
271 test_fastcall_invoke();