@@ -1,9 +1,9 @@ /* Trampoline construction */ /* - * Copyright 1995-1999, 2001-2004 Bruno Haible, + * Copyright 1995-1999, 2001-2006 Bruno Haible, * * This is free software distributed under the GNU General Public Licence * described in the file COPYING. Contact the author if you don't have this * or can't live with it. There is ABSOLUTELY NO WARRANTY, explicit or implied, * on this software. @@ -18,17 +18,21 @@ #define __hppaold__ /* Old trampoline, real machine code. */ #else #define __hppanew__ /* New trampoline, just a closure. */ #endif #endif -#if defined(__rs6000__) +#if defined(__powerpc__) && !defined(__powerpc64__) #if !defined(_AIX) -#define __rs6000sysv4__ /* SysV.4 ABI, real machine code. */ +#define __powerpcsysv4__ /* SysV.4 ABI, real machine code. */ #else -#define __rs6000aix__ /* AIX ABI, just a closure. */ +#define __powerpcaix__ /* AIX ABI, just a closure. */ #endif #endif +#if defined(__powerpc64__) +/* The only ABI on powerpc64 known so far is the AIX ABI. */ +#define __powerpc64aix__ /* AIX ABI, just a closure. */ +#endif #if defined(__hppanew__) /* * A function pointer is a biased pointer to a data area whose first word * contains the actual address of the function. */ @@ -38,11 +42,11 @@ */ #ifndef CODE_EXECUTABLE #define CODE_EXECUTABLE #endif #endif -#if defined(__rs6000aix__) || defined(__ia64__) +#if defined(__powerpcaix__) || defined(__powerpc64aix__) || defined(__ia64__) /* * A function pointer is a pointer to a data area whose first word contains * the actual address of the function. */ extern void (*tramp) (); /* trampoline prototype */ @@ -107,14 +111,12 @@ /* Declare getpagesize(). */ #ifdef HAVE_GETPAGESIZE #ifdef __cplusplus extern "C" RETGETPAGESIZETYPE getpagesize (void); -#elif defined(__STDC__) -extern RETGETPAGESIZETYPE getpagesize (void); #else -extern RETGETPAGESIZETYPE getpagesize (); +extern RETGETPAGESIZETYPE getpagesize (void); #endif #else #ifdef HAVE_SYS_PARAM_H #include #else @@ -159,13 +161,10 @@ /* Declare open(). */ #ifdef EXECUTABLE_VIA_MMAP_DEVZERO #include #include #include -#ifdef OPEN_NEEDS_SYS_FILE_H -#include -#endif #endif /* Declare shmget(), shmat(), shmctl(). */ #ifdef EXECUTABLE_VIA_SHM #include @@ -209,11 +208,11 @@ #endif #ifdef __m88k__ #include #endif /* Inline assembly function for instruction cache flush. */ -#if defined(__sparc__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppaold__) || defined(__rs6000sysv4__) || defined(__convex__) +#if defined(__sparc__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppaold__) || defined(__powerpcsysv4__) || defined(__convex__) #ifdef __GNUC__ extern inline #if defined(__sparc__) || defined(__sparc64__) #include "cache-sparc.c" #endif @@ -221,12 +220,12 @@ #include "cache-alpha.c" #endif #ifdef __hppa__ #include "cache-hppa.c" #endif -#ifdef __rs6000__ -#include "cache-rs6000.c" +#if defined(__powerpc__) && !defined(__powerpc64__) +#include "cache-powerpc.c" #endif #ifdef __convex__ #include "cache-convex.c" #endif #else @@ -283,20 +282,24 @@ #define TRAMP_LENGTH 20 #define TRAMP_ALIGN 16 #define TRAMP_BIAS 2 #endif #ifdef __arm__ -#define TRAMP_LENGTH 44 +#define TRAMP_LENGTH 36 #define TRAMP_ALIGN 4 #endif -#ifdef __rs6000sysv4__ +#ifdef __powerpcsysv4__ #define TRAMP_LENGTH 36 #define TRAMP_ALIGN 4 #endif -#ifdef __rs6000aix__ +#ifdef __powerpcaix__ #define TRAMP_LENGTH 24 #define TRAMP_ALIGN 4 +#endif +#ifdef __powerpc64aix__ +#define TRAMP_LENGTH 48 +#define TRAMP_ALIGN 8 #endif #ifdef __m88k__ #define TRAMP_LENGTH 32 #define TRAMP_ALIGN 8 #endif @@ -327,18 +330,11 @@ * free trampolines. */ static char* freelist = NULL; #endif -#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) __TR_function alloc_trampoline (__TR_function address, void* variable, void* data) -#else -__TR_function alloc_trampoline (address, variable, data) - __TR_function address; - void* variable; - void* data; -#endif { char* function; #if !defined(CODE_EXECUTABLE) static long pagesize = 0; @@ -868,52 +864,49 @@ #define tramp_data(function) \ ((long *) function)[3] #endif #ifdef __arm__ /* function: - * stmfd sp!,{r0} E92D0001 - * ldr r0,[pc,#_data-.-8] E59F0014 - * ldr ip,[r0,#0] E590C000 - * ldr r0,[pc,#_variable-.-8] E59F0010 - * str ip,[r0,#0] E580C000 - * ldmfd sp!,{r0}^ E8FD0001 - * ldr ip,[pc,#_function-.-8] E59FC008 - * ldr pc,[ip,#0] E59CF000 + * stmfd sp!,{r0} E92D0001 + * ldr r0,[pc,#16] E59F000C + * ldr ip,[pc,#16] E59FC00C + * str r0,[ip] E58C0000 + * ldmfd sp!,{r0} E8BD0001 + * ldr pc,[pc,#4] E59FF004 * _data: - * .word + * .word * _variable: - * .word + * .word * _function: - * .word
+ * .word
*/ - { static long code [8] = - { 0xE92D0001, 0xE59F0014, 0xE590C000, 0xE59F0010, - 0xE580C000, 0xE8FD0001, 0xE59FC008, 0xE59CF000 - }; - int i; - for (i=0; i<8; i++) { ((long *) function)[i] = code[i]; } - ((long *) function)[8] = (long) data; - ((long *) function)[9] = (long) variable; - ((long *) function)[10] = (long) address; + { + ((long *) function)[0] = 0xE92D0001; + ((long *) function)[1] = 0xE59F000C; + ((long *) function)[2] = 0xE59FC00C; + ((long *) function)[3] = 0xE58C0000; + ((long *) function)[4] = 0xE8BD0001; + ((long *) function)[5] = 0xE59FF004; + ((long *) function)[6] = (long)data; + ((long *) function)[7] = (long)variable; + ((long *) function)[8] = (long)address; } #define is_tramp(function) \ - ((long *) function)[0] == 0xE92D0001 && \ - ((long *) function)[1] == 0xE59F0014 && \ - ((long *) function)[2] == 0xE590C000 && \ - ((long *) function)[3] == 0xE59F0010 && \ - ((long *) function)[4] == 0xE580C000 && \ - ((long *) function)[5] == 0xE8FD0001 && \ - ((long *) function)[6] == 0xE59FC008 && \ - ((long *) function)[7] == 0xE59CF000 + ((long *) function)[0] == 0xE92D0001 && \ + ((long *) function)[1] == 0xE59F000C && \ + ((long *) function)[2] == 0xE59FC00C && \ + ((long *) function)[3] == 0xE58C0000 && \ + ((long *) function)[4] == 0xE8BD0001 && \ + ((long *) function)[5] == 0xE59FF004 #define tramp_address(function) \ - ((long *) function)[10] -#define tramp_variable(function) \ - ((long *) function)[9] -#define tramp_data(function) \ ((long *) function)[8] +#define tramp_variable(function) \ + ((long *) function)[7] +#define tramp_data(function) \ + ((long *) function)[6] #endif -#ifdef __rs6000sysv4__ +#ifdef __powerpcsysv4__ /* function: * {liu|lis} 11,hi16() 3D 60 hi16() * {oril|ori} 11,11,lo16() 61 6B lo16() * {liu|lis} 12,hi16() 3D 80 hi16() * {oril|ori} 12,12,lo16() 61 8C lo16() @@ -955,11 +948,11 @@ #define tramp_variable(function) \ hilo(*(unsigned short *) (function + 2), *(unsigned short *) (function + 6)) #define tramp_data(function) \ hilo(*(unsigned short *) (function +10), *(unsigned short *) (function +14)) #endif -#ifdef __rs6000aix__ +#ifdef __powerpcaix__ /* function: * .long .tramp * .long .mytoc * .long 0 * .mytoc: @@ -971,10 +964,35 @@ *(long *) (function + 4) = (long) (function + 12); *(long *) (function + 8) = 0; *(long *) (function +12) = (long) variable; *(long *) (function +16) = (long) data; *(long *) (function +20) = (long) address; +#define is_tramp(function) \ + ((long *) function)[0] == ((long *) &tramp)[0] +#define tramp_address(function) \ + ((long *) function)[5] +#define tramp_variable(function) \ + ((long *) function)[3] +#define tramp_data(function) \ + ((long *) function)[4] +#endif +#ifdef __powerpc64aix__ + /* function: + * .quad .tramp + * .quad .mytoc + * .quad 0 + * .mytoc: + * .quad + * .quad + * .quad
+ */ + *(long *) (function + 0) = ((long *) &tramp)[0]; + *(long *) (function + 8) = (long) (function + 24); + *(long *) (function +16) = 0; + *(long *) (function +24) = (long) variable; + *(long *) (function +32) = (long) data; + *(long *) (function +40) = (long) address; #define is_tramp(function) \ ((long *) function)[0] == ((long *) &tramp)[0] #define tramp_address(function) \ ((long *) function)[5] #define tramp_variable(function) \ @@ -1193,11 +1211,11 @@ /* 4. Flush instruction cache */ /* We need this because some CPUs have separate data cache and instruction * cache. The freshly built trampoline is visible to the data cache, but not * maybe not to the instruction cache. This is hairy. */ -#if !(defined(__hppanew__) || defined(__rs6000aix__) || defined(__ia64__)) +#if !(defined(__hppanew__) || defined(__powerpcaix__) || defined(__powerpc64aix__) || defined(__ia64__)) /* Only needed if we really set up machine instructions. */ #ifdef __i386__ #if defined(_WIN32) while (!FlushInstructionCache(GetCurrentProcess(),function,TRAMP_LENGTH)) continue; @@ -1274,13 +1292,13 @@ #ifdef __hppa__ /* This assumes that the trampoline fits in at most two cache lines. */ __TR_clear_cache(function,function+TRAMP_LENGTH-1); #endif #ifdef __arm__ - /* This CPU does not have a separate instruction cache. (I think.) */ + __TR_clear_cache(function,function+TRAMP_LENGTH); #endif -#ifdef __rs6000__ +#if defined(__powerpc__) && !defined(__powerpc64__) __TR_clear_cache(function); #endif #ifdef __m88k__ sysmot(S88CACHEFLUSHPAGE, (unsigned long)function & -pagesize); #endif @@ -1291,16 +1309,11 @@ /* 5. Return. */ return (__TR_function) (function + TRAMP_BIAS); } -#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) void free_trampoline (__TR_function function) -#else -void free_trampoline (function) - __TR_function function; -#endif { #if TRAMP_BIAS function = (__TR_function)((char*)function - TRAMP_BIAS); #endif #if !defined(CODE_EXECUTABLE) && !defined(EXECUTABLE_VIA_MPROTECT) @@ -1309,16 +1322,11 @@ #else free(((char**)function)[-1]); #endif } -#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) int is_trampoline (void* function) -#else -int is_trampoline (function) - void* function; -#endif { #ifdef is_tramp #ifdef __hppanew__ void* tramp_address = &tramp; if (!(((long)function & 3) == (TRAMP_BIAS & 3))) return 0; @@ -1327,46 +1335,31 @@ #else abort(); #endif } -#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) __TR_function trampoline_address (void* function) -#else -__TR_function trampoline_address (function) - void* function; -#endif { #ifdef tramp_address return (__TR_function)(tramp_address(((char*)function - TRAMP_BIAS))); #else abort(); #endif } -#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) void* trampoline_variable (void* function) -#else -void* trampoline_variable (function) - void* function; -#endif { #ifdef tramp_variable return (void*)(tramp_variable(((char*)function - TRAMP_BIAS))); #else abort(); #endif } -#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) void* trampoline_data (void* function) -#else -void* trampoline_data (function) - void* function; -#endif { #ifdef tramp_data return (void*)(tramp_data(((char*)function - TRAMP_BIAS))); #else abort(); #endif }