github.com/goccy/go-jit@v0.0.0-20200514131505-ff78d45cf6af/internal/ccall/jit-apply-x86.h (about)

     1  /*
     2   * jit-apply-x86.h - Special definitions for x86 function application.
     3   *
     4   * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
     5   *
     6   * This file is part of the libjit library.
     7   *
     8   * The libjit library is free software: you can redistribute it and/or
     9   * modify it under the terms of the GNU Lesser General Public License
    10   * as published by the Free Software Foundation, either version 2.1 of
    11   * the License, or (at your option) any later version.
    12   *
    13   * The libjit library is distributed in the hope that it will be useful,
    14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    16   * Lesser General Public License for more details.
    17   *
    18   * You should have received a copy of the GNU Lesser General Public
    19   * License along with the libjit library.  If not, see
    20   * <http://www.gnu.org/licenses/>.
    21   */
    22  
    23  #ifndef	_JIT_APPLY_X86_H
    24  #define	_JIT_APPLY_X86_H
    25  
    26  /*
    27   * The "__builtin_apply" functionality in gcc has some problems
    28   * dealing with floating-point values, and it also doesn't handle
    29   * STDCALL and FASTCALL functions well.  Therefore, we use assembly
    30   * code instead.
    31   *
    32   * There are three versions here: gcc/non-Win32, gcc/Win32, and msvc/Win32.
    33   * Cygwin is included in the gcc/Win32 case.
    34   */
    35  
    36  #if defined(__GNUC__)
    37  
    38  #if !defined(__CYGWIN__) && !defined(_WIN32) && !defined(WIN32)
    39  
    40  /* Mac OS X prefixes static symbols with an underscore, and external symbol
    41     references are late-bound through a PIC stub by the dynamic linker */
    42  #ifndef JIT_MEMCPY
    43  # if defined(__APPLE__) && defined(__MACH__)
    44  #  define JIT_MEMCPY "L_memcpy$stub"
    45  # else
    46  #  define JIT_MEMCPY "memcpy@PLT"
    47  # endif
    48  #endif
    49  
    50  #define	jit_builtin_apply(func,args,size,return_float,return_buf)	\
    51  		do { \
    52  			void *__func = (void *)(func); \
    53  			void *__args = (void *)(args); \
    54  			void *__size = (void *)(size); \
    55  			void *__return_buf = alloca(20); \
    56  			(return_buf) = __return_buf; \
    57  			__asm__ ( \
    58  				"pushl %%esi\n\t" \
    59  				"movl %%esp, %%esi\n\t" \
    60  				"subl %2, %%esp\n\t" \
    61  				"movl %%esp, %%eax\n\t" \
    62  				"movl %1, %%ecx\n\t" \
    63  				"movl (%%ecx), %%ecx\n\t" \
    64  				"pushl %2\n\t" \
    65  				"pushl %%ecx\n\t" \
    66  				"pushl %%eax\n\t" \
    67  				"call " JIT_MEMCPY "\n\t" \
    68  				"addl $12, %%esp\n\t" \
    69  				"movl %1, %%ecx\n\t" \
    70  				"movl %0, %%eax\n\t" \
    71  				"call *%%eax\n\t" \
    72  				"movl %3, %%ecx\n\t" \
    73  				"movl %%eax, (%%ecx)\n\t" \
    74  				"movl %%edx, 4(%%ecx)\n\t" \
    75  				"movl %%esi, %%esp\n\t" \
    76  				"popl %%esi\n\t" \
    77  				: : "m"(__func), "m"(__args), "m"(__size), "m"(__return_buf) \
    78  				: "eax", "ecx", "edx" \
    79  			); \
    80  			if((return_float)) \
    81  			{ \
    82  				if(sizeof(jit_nfloat) == sizeof(double)) \
    83  				{ \
    84  					__asm__ ( \
    85  						"movl %0, %%ecx\n\t" \
    86  						"fstpl 8(%%ecx)\n\t" \
    87  						: : "m"(__return_buf) \
    88  						: "ecx", "st" \
    89  					); \
    90  				} \
    91  				else \
    92  				{ \
    93  					__asm__ ( \
    94  						"movl %0, %%ecx\n\t" \
    95  						"fstpt 8(%%ecx)\n\t" \
    96  						: : "m"(__return_buf) \
    97  						: "ecx", "st" \
    98  					); \
    99  				} \
   100  	    		} \
   101  		} while (0)
   102  
   103  #define	jit_builtin_apply_args(type,args)	\
   104  		do { \
   105  			void *__args = alloca(4); \
   106  			__asm__ ( \
   107  				"leal 8(%%ebp), %%eax\n\t" \
   108  				"movl %0, %%ecx\n\t" \
   109  				"movl %%eax, (%%ecx)\n\t" \
   110  				: : "m"(__args) \
   111  				: "eax", "ecx" \
   112  			); \
   113  			(args) = (type)__args; \
   114  		} while (0)
   115  
   116  #define	jit_builtin_return_int(return_buf)	\
   117  		do { \
   118  			__asm__ ( \
   119  				"leal %0, %%ecx\n\t" \
   120  				"movl (%%ecx), %%eax\n\t" \
   121  				"movl 4(%%ecx), %%edx\n\t" \
   122  				: : "m"(*(return_buf)) \
   123  				: "eax", "ecx", "edx" \
   124  			); \
   125  			return; \
   126  		} while (0)
   127  
   128  #define	jit_builtin_return_float(return_buf)	\
   129  		do { \
   130  			jit_nfloat __value = \
   131  				((jit_apply_return *)(return_buf))-> \
   132  					nfloat_value.f_value; \
   133  			if(sizeof(jit_nfloat) == sizeof(double)) \
   134  			{ \
   135  				__asm__ ( \
   136  					"leal %0, %%ecx\n\t" \
   137  					"fldl (%%ecx)\n\t" \
   138  					: : "m"(__value) \
   139  					: "ecx", "st" \
   140  				); \
   141  			} \
   142  			else \
   143  			{ \
   144  				__asm__ ( \
   145  					"leal %0, %%ecx\n\t" \
   146  					"fldt (%%ecx)\n\t" \
   147  					: : "m"(__value) \
   148  					: "ecx", "st" \
   149  				); \
   150  			} \
   151  			return; \
   152  		} while (0)
   153  
   154  #else /* Win32 */
   155  
   156  #define	jit_builtin_apply(func,args,size,return_float,return_buf)	\
   157  		do { \
   158  			void *__func = (void *)(func); \
   159  			void *__args = (void *)(args); \
   160  			void *__size = (void *)(size); \
   161  			void *__return_buf = alloca(20); \
   162  			(return_buf) = __return_buf; \
   163  			__asm__ ( \
   164  				"pushl %%esi\n\t" \
   165  				"movl %%esp, %%esi\n\t" \
   166  				"subl %2, %%esp\n\t" \
   167  				"movl %%esp, %%eax\n\t" \
   168  				"movl %1, %%ecx\n\t" \
   169  				"movl (%%ecx), %%ecx\n\t" \
   170  				"pushl %2\n\t" \
   171  				"pushl %%ecx\n\t" \
   172  				"pushl %%eax\n\t" \
   173  				"call _memcpy\n\t" \
   174  				"addl $12, %%esp\n\t" \
   175  				"movl %1, %%ecx\n\t" \
   176  				"movl 8(%%ecx), %%edx\n\t" \
   177  				"movl 4(%%ecx), %%ecx\n\t" \
   178  				"movl %0, %%eax\n\t" \
   179  				"call *%%eax\n\t" \
   180  				"movl %3, %%ecx\n\t" \
   181  				"movl %%eax, (%%ecx)\n\t" \
   182  				"movl %%edx, 4(%%ecx)\n\t" \
   183  				"movl %%esi, %%esp\n\t" \
   184  				"popl %%esi\n\t" \
   185  				: : "m"(__func), "m"(__args), "m"(__size), "m"(__return_buf) \
   186  				: "eax", "ecx", "edx" \
   187  			); \
   188  			if((return_float)) \
   189  			{ \
   190  				if(sizeof(jit_nfloat) == sizeof(double)) \
   191  				{ \
   192  					__asm__ ( \
   193  						"movl %0, %%ecx\n\t" \
   194  						"fstpl 8(%%ecx)\n\t" \
   195  						: : "m"(__return_buf) \
   196  						: "ecx", "st" \
   197  					); \
   198  				} \
   199  				else \
   200  				{ \
   201  					__asm__ ( \
   202  						"movl %0, %%ecx\n\t" \
   203  						"fstpt 8(%%ecx)\n\t" \
   204  						: : "m"(__return_buf) \
   205  						: "ecx", "st" \
   206  					); \
   207  				} \
   208  			} \
   209  		} while (0)
   210  
   211  #define	jit_builtin_apply_args(type,args)	\
   212  		do { \
   213  			void *__args = alloca(12); \
   214  			__asm__ ( \
   215  				"movl %0, %%eax\n\t" \
   216  				"movl %%ecx, 4(%%eax)\n\t" \
   217  				"movl %%edx, 8(%%eax)\n\t" \
   218  				"leal 8(%%ebp), %%ecx\n\t" \
   219  				"movl %%ecx, (%%eax)\n\t" \
   220  				: : "m"(__args) \
   221  				: "eax", "ecx", "edx" \
   222  			); \
   223  			(args) = (type)__args; \
   224  		} while (0)
   225  
   226  #define	jit_builtin_return_int(return_buf)	\
   227  		do { \
   228  			__asm__ ( \
   229  				"leal %0, %%ecx\n\t" \
   230  				"movl (%%ecx), %%eax\n\t" \
   231  				"movl 4(%%ecx), %%edx\n\t" \
   232  				: : "m"(*(return_buf)) \
   233  				: "eax", "ecx", "edx" \
   234  			); \
   235  			return; \
   236  		} while (0)
   237  
   238  #define	jit_builtin_return_float(return_buf)	\
   239  		do { \
   240  			jit_nfloat __value = \
   241  				((jit_apply_return *)(return_buf))-> \
   242  					nfloat_value.f_value; \
   243  			if(sizeof(jit_nfloat) == sizeof(double)) \
   244  			{ \
   245  				__asm__ ( \
   246  					"leal %0, %%ecx\n\t" \
   247  					"fldl (%%ecx)\n\t" \
   248  					: : "m"(__value) \
   249  					: "ecx", "st" \
   250  				); \
   251  			} \
   252  			else \
   253  			{ \
   254  				__asm__ ( \
   255  					"leal %0, %%ecx\n\t" \
   256  					"fldt (%%ecx)\n\t" \
   257  					: : "m"(__value) \
   258  					: "ecx", "st" \
   259  				); \
   260  			} \
   261  			return; \
   262  		} while (0)
   263  
   264  #endif /* Win32 */
   265  
   266  #elif defined(_MSC_VER)
   267  
   268  #define	jit_builtin_apply(func,args,size,return_float,return_buf)	\
   269  		do { \
   270  			void *__func = (void *)(func); \
   271  			void *__args = (void *)(args); \
   272  			void *__size = (void *)(size); \
   273  			void *__return_buf = alloca(20); \
   274  			(return_buf) = __return_buf; \
   275  			__asm { \
   276  				__asm push esi \
   277  				__asm mov esi, esp \
   278  				__asm sub esp, dword ptr __size \
   279  				__asm mov eax, esp \
   280  				__asm mov ecx, dword ptr __args \
   281  				__asm mov ecx, [ecx] \
   282  				__asm push dword ptr __size \
   283  				__asm push ecx \
   284  				__asm push eax \
   285  				__asm call jit_memcpy \
   286  				__asm add esp, 12 \
   287  				__asm mov ecx, dword ptr __args \
   288  				__asm mov edx, [ecx + 8] \
   289  				__asm mov ecx, [ecx + 4] \
   290  				__asm mov eax, dword ptr __func \
   291  				__asm call eax \
   292  				__asm mov ecx, dword ptr __return_buf \
   293  				__asm mov [ecx], eax \
   294  				__asm mov [ecx + 4], edx \
   295  				__asm mov esp, esi \
   296  				__asm pop esi \
   297  			} \
   298  			if((return_float)) \
   299  			{ \
   300  				__asm { \
   301  					__asm mov ecx, dword ptr __return_buf \
   302  					/*__asm fstpl [ecx + 8]*/ \
   303  					__asm _emit 0xDD \
   304  					__asm _emit 0x59 \
   305  					__asm _emit 0x08 \
   306  				} \
   307  			} \
   308  		} while (0)
   309  
   310  #define	jit_builtin_apply_args(type,args)	\
   311  		do { \
   312  			void *__args = alloca(12); \
   313  			__asm { \
   314  				__asm mov eax, dword ptr __args \
   315  				__asm mov [eax + 4], ecx \
   316  				__asm mov [eax + 8], edx \
   317  				__asm lea ecx, [ebp + 8] \
   318  				__asm mov [eax], ecx \
   319  			} \
   320  			(args) = (type)(__args); \
   321  		} while (0)
   322  
   323  #define	jit_builtin_return_int(return_buf)	\
   324  		do { \
   325  			void *__return_buf = (void *)(return_buf); \
   326  			__asm { \
   327  				__asm mov ecx, dword ptr __return_buf \
   328  				__asm mov eax, [ecx] \
   329  				__asm mov edx, [ecx + 4] \
   330  			} \
   331  			return; \
   332  		} while (0)
   333  
   334  #define	jit_builtin_return_float(return_buf)	\
   335  		do { \
   336  			double __dvalue = \
   337  				((jit_apply_return *)(return_buf))-> \
   338  					nfloat_value.f_value; \
   339  			__asm { \
   340  				__asm lea ecx, dword ptr __dvalue \
   341  				/* __asm fldl [ecx] */ \
   342  				__asm _emit 0xDD \
   343  				__asm _emit 0x01 \
   344  			} \
   345  			return; \
   346  		} while (0)
   347  
   348  #endif /* MSC_VER */
   349  
   350  #define	jit_builtin_return_double(return_buf)	\
   351  	jit_builtin_return_float((return_buf))
   352  
   353  #define	jit_builtin_return_nfloat(return_buf)	\
   354  	jit_builtin_return_float((return_buf))
   355  
   356  /*
   357   * The maximum number of bytes that are needed to represent a closure,
   358   * and the alignment to use for the closure.
   359   */
   360  #define	jit_closure_size		64
   361  #define	jit_closure_align		32
   362  
   363  /*
   364   * The number of bytes that are needed for a redirector stub.
   365   * This includes any extra bytes that are needed for alignment.
   366   */
   367  #define	jit_redirector_size		24
   368  
   369  /*
   370   * The number of bytes that are needed for a indirector stub.
   371   * This includes any extra bytes that are needed for alignment.
   372   */
   373  #define	jit_indirector_size		8
   374  
   375  /*
   376   * We should pad unused code space with NOP's.
   377   */
   378  #define	jit_should_pad			1
   379  
   380  #endif	/* _JIT_APPLY_X86_H */