mirror of https://github.com/ademakov/libjit
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
320 lines
7.9 KiB
320 lines
7.9 KiB
/*
|
|
* jit-apply-x86.h - Special definitions for x86 function application.
|
|
*
|
|
* Copyright (C) 2004 Southern Storm Software, Pty Ltd.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#ifndef _JIT_APPLY_X86_H
|
|
#define _JIT_APPLY_X86_H
|
|
|
|
/*
|
|
* The "__builtin_apply" functionality in gcc has some problems
|
|
* dealing with floating-point values, and it also doesn't handle
|
|
* STDCALL and FASTCALL functions well. Therefore, we use assembly
|
|
* code instead.
|
|
*
|
|
* There are three versions here: gcc/non-Win32, gcc/Win32, and msvc/Win32.
|
|
*/
|
|
|
|
#if defined(__GNUC__)
|
|
|
|
#if !defined(__CYGWIN__) && !defined(__CYGWIN32__) && \
|
|
!defined(_WIN32) && !defined(WIN32)
|
|
|
|
#define jit_builtin_apply(func,args,size,return_float,return_buf) \
|
|
do { \
|
|
void *__func = (void *)(func); \
|
|
void *__args = (void *)(args); \
|
|
void *__size = (void *)(size); \
|
|
void *__return_buf = alloca(20); \
|
|
(return_buf) = __return_buf; \
|
|
__asm__ ( \
|
|
"pushl %%esi\n\t" \
|
|
"movl %%esp, %%esi\n\t" \
|
|
"subl %2, %%esp\n\t" \
|
|
"movl %%esp, %%eax\n\t" \
|
|
"movl %1, %%ecx\n\t" \
|
|
"movl (%%ecx), %%ecx\n\t" \
|
|
"pushl %2\n\t" \
|
|
"pushl %%ecx\n\t" \
|
|
"pushl %%eax\n\t" \
|
|
"call memcpy\n\t" \
|
|
"addl $12, %%esp\n\t" \
|
|
"movl %1, %%ecx\n\t" \
|
|
"movl %0, %%eax\n\t" \
|
|
"call *%%eax\n\t" \
|
|
"movl %3, %%ecx\n\t" \
|
|
"movl %%eax, (%%ecx)\n\t" \
|
|
"movl %%edx, 4(%%ecx)\n\t" \
|
|
"movl %%esi, %%esp\n\t" \
|
|
"popl %%esi\n\t" \
|
|
: : "m"(__func), "m"(__args), "m"(__size), "m"(__return_buf) \
|
|
: "eax", "ecx", "edx" \
|
|
); \
|
|
if((return_float)) \
|
|
{ \
|
|
__asm__ ( \
|
|
"movl %0, %%ecx\n\t" \
|
|
"fstpt 8(%%ecx)\n\t" \
|
|
: : "m"(__return_buf) \
|
|
: "ecx", "st" \
|
|
); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define jit_builtin_apply_args(type,args) \
|
|
do { \
|
|
void *__args = alloca(4); \
|
|
__asm__ ( \
|
|
"leal 8(%%ebp), %%eax\n\t" \
|
|
"movl %0, %%ecx\n\t" \
|
|
"movl %%eax, (%%ecx)\n\t" \
|
|
: : "m"(__args) \
|
|
: "eax", "ecx" \
|
|
); \
|
|
(args) = (type)__args; \
|
|
} while (0)
|
|
|
|
#define jit_builtin_return_int(return_buf) \
|
|
do { \
|
|
__asm__ ( \
|
|
"movl %0, %%ecx\n\t" \
|
|
"movl (%%ecx), %%eax\n\t" \
|
|
"movl 4(%%ecx), %%edx\n\t" \
|
|
: : "m"((return_buf)) \
|
|
: "eax", "ecx", "edx" \
|
|
); \
|
|
return; \
|
|
} while (0)
|
|
|
|
#define jit_builtin_return_float(return_buf) \
|
|
do { \
|
|
jit_nfloat __value = \
|
|
((jit_apply_return *)(return_buf))-> \
|
|
f_value.inner_value.nfloat_value; \
|
|
if(sizeof(jit_nfloat) == sizeof(double)) \
|
|
{ \
|
|
__asm__ ( \
|
|
"leal %0, %%ecx\n\t" \
|
|
"fldl (%%ecx)\n\t" \
|
|
: : "m"(__value) \
|
|
: "ecx", "st" \
|
|
); \
|
|
} \
|
|
else \
|
|
{ \
|
|
__asm__ ( \
|
|
"leal %0, %%ecx\n\t" \
|
|
"fldt (%%ecx)\n\t" \
|
|
: : "m"(__value) \
|
|
: "ecx", "st" \
|
|
); \
|
|
} \
|
|
return; \
|
|
} while (0)
|
|
|
|
#else /* Win32 */
|
|
|
|
#define jit_builtin_apply(func,args,size,return_float,return_buf) \
|
|
do { \
|
|
void *__func = (void *)(func); \
|
|
void *__args = (void *)(args); \
|
|
void *__size = (void *)(size); \
|
|
void *__return_buf = alloca(20); \
|
|
(return_buf) = __return_buf; \
|
|
__asm__ ( \
|
|
"pushl %%esi\n\t" \
|
|
"movl %%esp, %%esi\n\t" \
|
|
"subl %2, %%esp\n\t" \
|
|
"movl %%esp, %%eax\n\t" \
|
|
"movl %1, %%ecx\n\t" \
|
|
"movl (%%ecx), %%ecx\n\t" \
|
|
"pushl %2\n\t" \
|
|
"pushl %%ecx\n\t" \
|
|
"pushl %%eax\n\t" \
|
|
"call _memcpy\n\t" \
|
|
"addl $12, %%esp\n\t" \
|
|
"movl %1, %%ecx\n\t" \
|
|
"movl 8(%%ecx), %%edx\n\t" \
|
|
"movl 4(%%ecx), %%ecx\n\t" \
|
|
"movl %0, %%eax\n\t" \
|
|
"call *%%eax\n\t" \
|
|
"movl %3, %%ecx\n\t" \
|
|
"movl %%eax, (%%ecx)\n\t" \
|
|
"movl %%edx, 4(%%ecx)\n\t" \
|
|
"movl %%esi, %%esp\n\t" \
|
|
"popl %%esi\n\t" \
|
|
: : "m"(__func), "m"(__args), "m"(__size), "m"(__return_buf) \
|
|
: "eax", "ecx", "edx" \
|
|
); \
|
|
if((return_float)) \
|
|
{ \
|
|
__asm__ ( \
|
|
"movl %0, %%ecx\n\t" \
|
|
"fstpt 8(%%ecx)\n\t" \
|
|
: : "m"(__return_buf) \
|
|
: "ecx", "st" \
|
|
); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define jit_builtin_apply_args(type,args) \
|
|
do { \
|
|
void *__args = alloca(12); \
|
|
__asm__ ( \
|
|
"movl %0, %%eax\n\t" \
|
|
"movl %%ecx, 4(%%eax)\n\t" \
|
|
"movl %%edx, 8(%%eax)\n\t" \
|
|
"leal 8(%%ebp), %%ecx\n\t" \
|
|
"movl %%ecx, (%%eax)\n\t" \
|
|
: : "m"(__args) \
|
|
: "eax", "ecx", "edx" \
|
|
); \
|
|
(args) = (type)__args; \
|
|
} while (0)
|
|
|
|
#define jit_builtin_return_int(return_buf) \
|
|
do { \
|
|
__asm__ ( \
|
|
"movl %0, %%ecx\n\t" \
|
|
"movl (%%ecx), %%eax\n\t" \
|
|
"movl 4(%%ecx), %%edx\n\t" \
|
|
: : "m"((return_buf)) \
|
|
: "eax", "ecx", "edx" \
|
|
); \
|
|
return; \
|
|
} while (0)
|
|
|
|
#define jit_builtin_return_float(return_buf) \
|
|
do { \
|
|
double __value = \
|
|
((jit_apply_return *)(return_buf))-> \
|
|
f_value.inner_value.nfloat_value; \
|
|
__asm__ ( \
|
|
"leal %0, %%ecx\n\t" \
|
|
"fldl (%%ecx)\n\t" \
|
|
: : "m"(__value) \
|
|
: "ecx", "st" \
|
|
); \
|
|
return; \
|
|
} while (0)
|
|
|
|
#endif /* Win32 */
|
|
|
|
#elif defined(_MSC_VER)
|
|
|
|
#define jit_builtin_apply(func,args,size,return_float,return_buf) \
|
|
do { \
|
|
void *__func = (void *)(func); \
|
|
void *__args = (void *)(args); \
|
|
void *__size = (void *)(size); \
|
|
void *__return_buf = alloca(20); \
|
|
(return_buf) = __return_buf; \
|
|
__asm { \
|
|
__asm push esi \
|
|
__asm mov esi, esp \
|
|
__asm sub esp, dword ptr __size \
|
|
__asm mov eax, esp \
|
|
__asm mov ecx, dword ptr __args \
|
|
__asm mov ecx, [ecx] \
|
|
__asm push dword ptr __size \
|
|
__asm push ecx \
|
|
__asm push eax \
|
|
__asm call jit_memcpy \
|
|
__asm add esp, 12 \
|
|
__asm mov ecx, dword ptr __args \
|
|
__asm mov edx, [ecx + 8] \
|
|
__asm mov ecx, [ecx + 4] \
|
|
__asm mov eax, dword ptr __func \
|
|
__asm call eax \
|
|
__asm mov ecx, dword ptr __return_buf \
|
|
__asm mov [ecx], eax \
|
|
__asm mov [ecx + 4], edx \
|
|
__asm mov esp, esi \
|
|
__asm pop esi \
|
|
} \
|
|
if((return_float)) \
|
|
{ \
|
|
__asm { \
|
|
__asm mov ecx, dword ptr __return_buf \
|
|
/*__asm fstpt [ecx + 8]*/ \
|
|
__asm _emit 0xDB \
|
|
__asm _emit 0x79 \
|
|
__asm _emit 0x08 \
|
|
} \
|
|
} \
|
|
} while (0)
|
|
|
|
#define jit_builtin_apply_args(type,args) \
|
|
do { \
|
|
void *__args = alloca(12); \
|
|
__asm { \
|
|
__asm mov eax, dword ptr __args \
|
|
__asm mov [eax + 4], ecx \
|
|
__asm mov [eax + 8], edx \
|
|
__asm lea ecx, [ebp + 8] \
|
|
__asm mov [eax], ecx \
|
|
} \
|
|
(args) = (type)(__args); \
|
|
} while (0)
|
|
|
|
#define jit_builtin_return_int(return_buf) \
|
|
do { \
|
|
void *__return_buf = (void *)(return_buf); \
|
|
__asm { \
|
|
__asm mov ecx, dword ptr __return_buf \
|
|
__asm mov eax, [ecx] \
|
|
__asm mov edx, [ecx + 4] \
|
|
} \
|
|
return; \
|
|
} while (0)
|
|
|
|
#define jit_builtin_return_float(return_buf) \
|
|
do { \
|
|
double __value = \
|
|
((jit_apply_return *)(return_buf))-> \
|
|
f_value.inner_value.nfloat_value; \
|
|
__asm { \
|
|
__asm lea ecx, dword ptr __value \
|
|
/* __asm fldl [ecx] */ \
|
|
__asm _emit 0xDD \
|
|
__asm _emit 0x01 \
|
|
} \
|
|
return; \
|
|
} while (0)
|
|
|
|
#endif /* MSC_VER */
|
|
|
|
/*
|
|
* The maximum number of bytes that are needed to represent a closure,
|
|
* and the alignment to use for the closure.
|
|
*/
|
|
#define jit_closure_size 64
|
|
#define jit_closure_align 32
|
|
|
|
/*
|
|
* The number of bytes that are needed for a redirector stub.
|
|
* This includes any extra bytes that are needed for alignment.
|
|
*/
|
|
#define jit_redirector_size 32
|
|
|
|
/*
|
|
* We should pad unused code space with NOP's.
|
|
*/
|
|
#define jit_should_pad 1
|
|
|
|
#endif /* _JIT_APPLY_X86_H */
|
|
|