/* * 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 */