@@ -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,20 +18,20 @@ #define __hppaold__ /* Old trampoline, real machine code. */ #else #define __hppanew__ /* New trampoline, just a closure. */ #endif #endif -#if defined(__rs6000__) -#if defined(__NetBSD__) -#define __rs6000netbsd__ -#else +#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. @@ -42,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_r) (); /* trampoline prototype */ @@ -111,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 @@ -163,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 @@ -213,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(__rs6000netbsd__) || 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 @@ -225,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 @@ -249,15 +244,11 @@ #endif #ifdef __m68k__ #define TRAMP_LENGTH 14 #define TRAMP_ALIGN 16 #endif -#if defined(__mips__) && !defined(__mipsn32__) -#define TRAMP_LENGTH 24 -#define TRAMP_ALIGN 4 -#endif -#ifdef __mipsn32__ +#if defined(__mips__) || defined(__mipsn32__) && !defined(__mips64__) #define TRAMP_LENGTH 24 #define TRAMP_ALIGN 4 #endif #ifdef __mips64old__ #define TRAMP_LENGTH 56 @@ -287,24 +278,24 @@ #define TRAMP_LENGTH 16 #define TRAMP_ALIGN 16 #define TRAMP_BIAS 2 #endif #ifdef __arm__ -#define TRAMP_LENGTH 32 +#define TRAMP_LENGTH 16 #define TRAMP_ALIGN 4 #endif -#ifdef __rs6000sysv4__ +#ifdef __powerpcsysv4__ #define TRAMP_LENGTH 24 #define TRAMP_ALIGN 4 #endif -#ifdef __rs6000netbsd__ -#define TRAMP_LENGTH 24 +#ifdef __powerpcaix__ +#define TRAMP_LENGTH 20 #define TRAMP_ALIGN 4 #endif -#ifdef __rs6000aix__ -#define TRAMP_LENGTH 20 -#define TRAMP_ALIGN 4 +#ifdef __powerpc64aix__ +#define TRAMP_LENGTH 40 +#define TRAMP_ALIGN 8 #endif #ifdef __m88k__ #define TRAMP_LENGTH 20 #define TRAMP_ALIGN 8 #endif @@ -337,18 +328,11 @@ * free trampolines. */ static char* freelist = NULL; #endif -#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) __TR_function alloc_trampoline_r (__TR_function address, void* data0, void* data1) -#else -__TR_function alloc_trampoline_r (address, data0, data1) - __TR_function address; - void* data0; - void* data1; -#endif { char* function; char* data; #if !defined(CODE_EXECUTABLE) @@ -376,11 +360,11 @@ #if !defined(CODE_EXECUTABLE) && !defined(EXECUTABLE_VIA_MPROTECT) /* Note: This memory allocation is not multithread-safe. We might need * to add special (platform dependent) code for locking. * Fortunately, most modern systems where multithread-safety matters - * have EXECUTABLE_VIA_MPROTECT, and those which don't (AIX on rs6000 and + * have EXECUTABLE_VIA_MPROTECT, and those which don't (AIX on powerpc and * HP-UX on hppa) have CODE_EXECUTABLE. Thus no locking code is needed * for the moment. */ if (freelist == NULL) { /* Get a new page. */ @@ -452,10 +436,26 @@ *(long *) (function + 8) + (long) (function + 12) #define tramp_data(function) \ *(long *) (function + 2) #endif #ifdef __m68k__ +#ifdef __NetBSD__ + /* function: + * movel #,a1 22 7C + * jmp
4E F9
+ * nop 4E 71 + */ + *(short *) (function + 0) = 0x227C; + *(long *) (function + 2) = (long) data; + *(short *) (function + 6) = 0x4EF9; + *(long *) (function + 8) = (long) address; + *(short *) (function +12) = 0x4E71; +#define is_tramp(function) \ + *(unsigned short *) (function + 0) == 0x227C && \ + *(unsigned short *) (function + 6) == 0x4EF9 && \ + *(unsigned short *) (function +12) == 0x4E71 +#else /* function: * movel #,a0 20 7C * jmp
4E F9
* nop 4E 71 */ @@ -466,70 +466,36 @@ *(short *) (function +12) = 0x4E71; #define is_tramp(function) \ *(unsigned short *) (function + 0) == 0x207C && \ *(unsigned short *) (function + 6) == 0x4EF9 && \ *(unsigned short *) (function +12) == 0x4E71 +#endif #define tramp_address(function) \ *(long *) (function + 8) #define tramp_data(function) \ *(long *) (function + 2) #endif -#if defined(__mips__) && !defined(__mipsn32__) - /* function: - * li $2,&0xffff0000 3C 02 hi16() - * ori $2,$2,&0xffff 34 42 lo16() - * li $25,
&0xffff0000 3C 19 hi16(
) - * ori $25,$25,
&0xffff 37 39 lo16(
) - * j $25 03 20 00 08 - * nop 00 00 00 00 - */ - /* What about big endian / little endian ?? */ - *(short *) (function + 0) = 0x3C02; - *(short *) (function + 2) = (unsigned long) data >> 16; - *(short *) (function + 4) = 0x3442; - *(short *) (function + 6) = (unsigned long) data & 0xffff; - *(short *) (function + 8) = 0x3C19; - *(short *) (function +10) = (unsigned long) address >> 16; - *(short *) (function +12) = 0x3739; - *(short *) (function +14) = (unsigned long) address & 0xffff; - *(long *) (function +16) = 0x03200008; - *(long *) (function +20) = 0x00000000; -#define is_tramp(function) \ - *(unsigned short *) (function + 0) == 0x3C02 && \ - *(unsigned short *) (function + 4) == 0x3442 && \ - *(unsigned short *) (function + 8) == 0x3C19 && \ - *(unsigned short *) (function +12) == 0x3739 && \ - *(unsigned long *) (function +16) == 0x03200008 && \ - *(unsigned long *) (function +20) == 0x00000000 -#define hilo(hiword,loword) \ - (((unsigned long) (hiword) << 16) | (unsigned long) (loword)) -#define tramp_address(function) \ - hilo(*(unsigned short *) (function +10), *(unsigned short *) (function +14)) -#define tramp_data(function) \ - hilo(*(unsigned short *) (function + 2), *(unsigned short *) (function + 6)) -#endif -#ifdef __mipsn32__ +#if defined(__mips__) || defined(__mipsn32__) && !defined(__mips64__) /* function: * lw $2,16($25) 8F 22 00 10 * lw $25,20($25) 8F 39 00 14 * j $25 03 20 00 08 * nop 00 00 00 00 * .word * .word
*/ - /* What about big endian / little endian ?? */ *(unsigned int *) (function + 0) = 0x8F220010; *(unsigned int *) (function + 4) = 0x8F390014; *(unsigned int *) (function + 8) = 0x03200008; *(unsigned int *) (function +12) = 0x00000000; *(unsigned int *) (function +16) = (unsigned int) data; *(unsigned int *) (function +20) = (unsigned int) address; #define is_tramp(function) \ - *(int *) (function + 0) == 0x8F220010 && \ - *(int *) (function + 4) == 0x8F390014 && \ - *(int *) (function + 8) == 0x03200008 && \ - *(int *) (function +12) == 0x00000000 + *(unsigned int *) (function + 0) == 0x8F220010 && \ + *(unsigned int *) (function + 4) == 0x8F390014 && \ + *(unsigned int *) (function + 8) == 0x03200008 && \ + *(unsigned int *) (function +12) == 0x00000000 #define tramp_address(function) \ *(unsigned int *) (function +20) #define tramp_data(function) \ *(unsigned int *) (function +16) #endif @@ -609,18 +575,21 @@ * j $25 03 20 00 08 * nop 00 00 00 00 * .dword * .dword
*/ - /* What about big endian / little endian ?? */ - *(long *) (function + 0) = 0xDF220010DF390018L; - *(long *) (function + 8) = 0x0320000800000000L; + *(unsigned int *) (function + 0) = 0xDF220010; + *(unsigned int *) (function + 4) = 0xDF390018; + *(unsigned int *) (function + 8) = 0x03200008; + *(unsigned int *) (function +12) = 0x00000000; *(unsigned long *) (function +16) = (unsigned long) data; *(unsigned long *) (function +24) = (unsigned long) address; #define is_tramp(function) \ - *(long *) (function + 0) == 0xDF220010DF390018L && \ - *(long *) (function + 8) == 0x0320000800000000L + *(unsigned int *) (function + 0) == 0xDF220010 && \ + *(unsigned int *) (function + 4) == 0xDF390018 && \ + *(unsigned int *) (function + 8) == 0x03200008 && \ + *(unsigned int *) (function +12) == 0x00000000 #define tramp_address(function) \ *(unsigned long *) (function +24) #define tramp_data(function) \ *(unsigned long *) (function +16) #endif @@ -792,43 +761,59 @@ #define tramp_data(function) \ ((long *) function)[2] #endif #ifdef __arm__ /* function: - * ldr ip,[pc,#_function-.-8] E59FC014 - * ldr ip,[ip,#0] E59CC000 ??Is this correct?? - * stmfd sp!,{ip} E92D1000 - * ldr ip,[pc,#_data-.-8] E59FC004 - * ldr ip,[ip,#0] E59CC000 ??Is this correct?? - * ldmfd sp!,{pc}^ E8FD8000 + * add r12,pc,#8 E28FC008 + * ldr pc,[pc] E59FF000 * _data: - * .word + * .word * _function: - * .word
+ * .word
*/ - { static long code [6] = - { 0xE59FC014, 0xE59CC000, 0xE92D1000, 0xE59FC004, - 0xE59CC000, 0xE8FD8000 - }; - int i; - for (i=0; i<6; i++) { ((long *) function)[i] = code[i]; } - ((long *) function)[6] = (long) data; - ((long *) function)[7] = (long) address; + { + ((long *) function)[0] = 0xE28FC008; + ((long *) function)[1] = 0xE59FF000; + ((long *) function)[2] = (long) data; + ((long *) function)[3] = (long) address; } #define is_tramp(function) \ - ((long *) function)[0] == 0xE59FC014 && \ - ((long *) function)[1] == 0xE59CC000 && \ - ((long *) function)[2] == 0xE92D1000 && \ - ((long *) function)[3] == 0xE59FC004 && \ - ((long *) function)[4] == 0xE59CC000 && \ - ((long *) function)[5] == 0xE8FD8000 + ((long *) function)[0] == 0xE28FC008 && \ + ((long *) function)[1] == 0xE59FF000 #define tramp_address(function) \ - ((long *) function)[7] + ((long *) function)[3] #define tramp_data(function) \ - ((long *) function)[6] + ((long *) function)[2] #endif -#ifdef __rs6000sysv4__ +#ifdef __powerpcsysv4__ +#ifdef __NetBSD__ + /* function: + * {liu|lis} 13,hi16() 3D A0 hi16() + * {oril|ori} 13,13,lo16() 61 AD lo16() + * {liu|lis} 0,hi16(
) 3C 00 hi16(
) + * {oril|ori} 0,0,lo16(
) 60 00 lo16(
) + * mtctr 0 7C 09 03 A6 + * bctr 4E 80 04 20 + */ + *(short *) (function + 0) = 0x3DA0; + *(short *) (function + 2) = (unsigned long) data >> 16; + *(short *) (function + 4) = 0x61AD; + *(short *) (function + 6) = (unsigned long) data & 0xffff; + *(short *) (function + 8) = 0x3C00; + *(short *) (function +10) = (unsigned long) address >> 16; + *(short *) (function +12) = 0x6000; + *(short *) (function +14) = (unsigned long) address & 0xffff; + *(long *) (function +16) = 0x7C0903A6; + *(long *) (function +20) = 0x4E800420; +#define is_tramp(function) \ + *(unsigned short *) (function + 0) == 0x3DA0 && \ + *(unsigned short *) (function + 4) == 0x61AD && \ + *(unsigned short *) (function + 8) == 0x3C00 && \ + *(unsigned short *) (function +12) == 0x6000 && \ + *(unsigned long *) (function +16) == 0x7C0903A6 && \ + *(unsigned long *) (function +20) == 0x4E800420 +#else /* function: * {liu|lis} 11,hi16() 3D 60 hi16() * {oril|ori} 11,11,lo16() 61 6B lo16() * {liu|lis} 0,hi16(
) 3C 00 hi16(
) * {oril|ori} 0,0,lo16(
) 60 00 lo16(
) @@ -850,51 +835,19 @@ *(unsigned short *) (function + 4) == 0x616B && \ *(unsigned short *) (function + 8) == 0x3C00 && \ *(unsigned short *) (function +12) == 0x6000 && \ *(unsigned long *) (function +16) == 0x7C0903A6 && \ *(unsigned long *) (function +20) == 0x4E800420 +#endif #define hilo(hiword,loword) \ (((unsigned long) (hiword) << 16) | (unsigned long) (loword)) #define tramp_address(function) \ hilo(*(unsigned short *) (function +10), *(unsigned short *) (function +14)) #define tramp_data(function) \ hilo(*(unsigned short *) (function + 2), *(unsigned short *) (function + 6)) #endif -#ifdef __rs6000netbsd__ - /* function: - * {liu|lis} 13,hi16() 3D A0 hi16() - * {oril|ori} 13,13,lo16() 61 AD lo16() - * {liu|lis} 0,hi16(
) 3C 00 hi16(
) - * {oril|ori} 0,0,lo16(
) 60 00 lo16(
) - * mtctr 0 7C 09 03 A6 - * bctr 4E 80 04 20 - */ - *(short *) (function + 0) = 0x3DA0; - *(short *) (function + 2) = (unsigned long) data >> 16; - *(short *) (function + 4) = 0x61AD; - *(short *) (function + 6) = (unsigned long) data & 0xffff; - *(short *) (function + 8) = 0x3C00; - *(short *) (function +10) = (unsigned long) address >> 16; - *(short *) (function +12) = 0x6000; - *(short *) (function +14) = (unsigned long) address & 0xffff; - *(long *) (function +16) = 0x7C0903A6; - *(long *) (function +20) = 0x4E800420; -#define is_tramp(function) \ - *(unsigned short *) (function + 0) == 0x3DA0 && \ - *(unsigned short *) (function + 4) == 0x61AD && \ - *(unsigned short *) (function + 8) == 0x3C00 && \ - *(unsigned short *) (function +12) == 0x6000 && \ - *(unsigned long *) (function +16) == 0x7C0903A6 && \ - *(unsigned long *) (function +20) == 0x4E800420 -#define hilo(hiword,loword) \ - (((unsigned long) (hiword) << 16) | (unsigned long) (loword)) -#define tramp_address(function) \ - hilo(*(unsigned short *) (function +10), *(unsigned short *) (function +14)) -#define tramp_data(function) \ - hilo(*(unsigned short *) (function + 2), *(unsigned short *) (function + 6)) -#endif -#ifdef __rs6000aix__ +#ifdef __powerpcaix__ /* function: * .long .tramp_r * .long .mytoc * .long 0 * .mytoc: @@ -904,10 +857,31 @@ *(long *) (function + 0) = ((long *) &tramp_r)[0]; *(long *) (function + 4) = (long) (function + 12); *(long *) (function + 8) = 0; *(long *) (function +12) = (long) data; *(long *) (function +16) = (long) address; +#define is_tramp(function) \ + ((long *) function)[0] == ((long *) &tramp_r)[0] +#define tramp_address(function) \ + ((long *) function)[4] +#define tramp_data(function) \ + ((long *) function)[3] +#endif +#ifdef __powerpc64aix__ + /* function: + * .quad .tramp_r + * .quad .mytoc + * .quad 0 + * .mytoc: + * .quad + * .quad
+ */ + *(long *) (function + 0) = ((long *) &tramp_r)[0]; + *(long *) (function + 8) = (long) (function + 24); + *(long *) (function +16) = 0; + *(long *) (function +24) = (long) data; + *(long *) (function +32) = (long) address; #define is_tramp(function) \ ((long *) function)[0] == ((long *) &tramp_r)[0] #define tramp_address(function) \ ((long *) function)[4] #define tramp_data(function) \ @@ -1082,11 +1056,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; @@ -1163,13 +1137,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 @@ -1180,16 +1154,11 @@ /* 5. Return. */ return (__TR_function) (function + TRAMP_BIAS); } -#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) void free_trampoline_r (__TR_function function) -#else -void free_trampoline_r (function) - __TR_function function; -#endif { #if TRAMP_BIAS function = (__TR_function)((char*)function - TRAMP_BIAS); #endif #if !defined(CODE_EXECUTABLE) && !defined(EXECUTABLE_VIA_MPROTECT) @@ -1198,16 +1167,11 @@ #else free(((char**)function)[-1]); #endif } -#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) int is_trampoline_r (void* function) -#else -int is_trampoline_r (function) - void* function; -#endif { #if defined(is_tramp) && defined(tramp_data) #ifdef __hppanew__ void* tramp_r_address = &tramp_r; if (!(((long)function & 3) == (TRAMP_BIAS & 3))) return 0; @@ -1220,46 +1184,31 @@ #else abort(); #endif } -#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) __TR_function trampoline_r_address (void* function) -#else -__TR_function trampoline_r_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_r_data0 (void* function) -#else -void* trampoline_r_data0 (function) - void* function; -#endif { #ifdef tramp_data return ((void**)((char*)function-TRAMP_BIAS+TRAMP_LENGTH))[0]; #else abort(); #endif } -#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) void* trampoline_r_data1 (void* function) -#else -void* trampoline_r_data1 (function) - void* function; -#endif { #ifdef tramp_data return ((void**)((char*)function-TRAMP_BIAS+TRAMP_LENGTH))[1]; #else abort(); #endif }