home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / Misc / CLISP-2.LHA / CLISP960530-ki.lha / ffcall / trampoline / trampoline.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-25  |  28.2 KB  |  897 lines

  1. /* Trampoline construction */
  2.  
  3. /*
  4.  * Copyright 1995 Bruno Haible, <haible@ma2s2.mathematik.uni-karlsruhe.de>
  5.  *
  6.  * This is free software distributed under the GNU General Public Licence
  7.  * described in the file COPYING. Contact the author if you don't have this
  8.  * or can't live with it. There is ABSOLUTELY NO WARRANTY, explicit or implied,
  9.  * on this software.
  10.  */
  11.  
  12.  
  13. #include "config.h"
  14. #include "trampoline.h"
  15.  
  16. #if defined(__rs6000__)
  17. /*
  18.  * A function pointer is a pointer to a data area whose first word contains
  19.  * the actual address of the function.
  20.  */
  21. extern void (*tramp) (); /* trampoline prototype */
  22. /* We don't need to take any special measures to make the code executable
  23.  * since the actual instructions are in the text segment.
  24.  */
  25. #ifndef CODE_EXECUTABLE
  26. #define CODE_EXECUTABLE
  27. #endif
  28. #endif
  29.  
  30. #if defined(AMIGA)
  31. #include <exec/types.h>
  32. #include <exec/execbase.h>
  33. #include <proto/exec.h>
  34. /* We just need to clear the caches to make the code executable.
  35.  * No need for EXECUTABLE_VIA_ kludges, CODE_EXECUTABLE comes closest.
  36.  */
  37. #ifndef CODE_EXECUTABLE
  38. #define CODE_EXECUTABLE
  39. #endif
  40. #endif
  41.  
  42. #ifndef CODE_EXECUTABLE
  43. /* How do we make the trampoline's code executable? */
  44. #if defined(HAVE_MACH_VM) || defined(__convex__) || defined(HAVE_WORKING_MPROTECT) || defined(HAVE_SYS_M88KBCS_H)
  45. /* mprotect() [or equivalent] the malloc'ed area. */
  46. #define EXECUTABLE_VIA_MPROTECT
  47. #else
  48. #ifdef HAVE_MMAP
  49. /* Use an mmap'ed page. */
  50. #define EXECUTABLE_VIA_MMAP
  51. #ifdef HAVE_MMAP_ANONYMOUS
  52. /* Use mmap with the MAP_ANONYMOUS or MAP_ANON flag. */
  53. #define EXECUTABLE_VIA_MMAP_ANONYMOUS
  54. #else
  55. /* Use mmap on /dev/zero. */
  56. #define EXECUTABLE_VIA_MMAP_DEVZERO
  57. #endif
  58. #else
  59. #ifdef HAVE_SHM
  60. /* Use an shmat'ed page. */
  61. #define EXECUTABLE_VIA_SHM
  62. #else
  63. ??
  64. #endif
  65. #endif
  66. #endif
  67. #endif
  68.  
  69. #ifndef FOR_AMIGA_CLISP
  70. #include <stdio.h> /* declares fprintf() */
  71. #else
  72. extern BPTR Input_handle;
  73. extern struct ExecBase * const SysBase;
  74. #define stderr Input_handle
  75. #define fprintf BPTRfprintf
  76. #endif
  77.  
  78. #include <sys/types.h>
  79. #ifdef HAVE_STDLIB_H
  80. #include <stdlib.h>
  81. #endif
  82. #ifdef HAVE_UNISTD_H
  83. #include <unistd.h>
  84. #endif
  85.  
  86. /* Declare malloc(), free(). */
  87. #ifndef malloc
  88. #ifdef __STDC__
  89. extern RETMALLOCTYPE malloc (MALLOC_SIZE_T size);
  90. #else
  91. extern RETMALLOCTYPE malloc();
  92. #endif
  93. #endif
  94. #ifndef free
  95. #ifdef __STDC__
  96. extern RETFREETYPE free (RETMALLOCTYPE ptr);
  97. #else
  98. extern RETFREETYPE free();
  99. #endif
  100. #endif
  101.  
  102. /* Declare abort(). */
  103. #ifdef __STDC__
  104. extern ABORT_VOLATILE RETABORTTYPE abort (void);
  105. #else
  106. extern ABORT_VOLATILE RETABORTTYPE abort();
  107. #endif
  108.  
  109. /* Declare getpagesize(). */
  110. #ifdef HAVE_GETPAGESIZE
  111. #ifdef __STDC__
  112. extern RETGETPAGESIZETYPE getpagesize (void);
  113. #else
  114. extern RETGETPAGESIZETYPE getpagesize ();
  115. #endif
  116. #else
  117. #include <sys/param.h>
  118. #define getpagesize() PAGESIZE
  119. #endif
  120.  
  121. /* Declare mprotect() or equivalent. */
  122. #ifdef EXECUTABLE_VIA_MPROTECT
  123. #ifdef HAVE_MACH_VM
  124. #include <sys/resource.h>
  125. #include <mach/mach_interface.h>
  126. #ifdef NeXT
  127. #include <mach/mach_init.h>
  128. #endif
  129. #ifdef __osf__
  130. #include <mach_init.h>
  131. #endif
  132. #include <mach/machine/vm_param.h>
  133. #else
  134. #ifdef HAVE_SYS_M88KBCS_H
  135. #include <sys/m88kbcs.h>
  136. #define getpagesize()  4096  /* ?? */
  137. #else
  138. #include <sys/types.h>
  139. #include <sys/mman.h>
  140. #if !defined(__convex__)
  141. #ifdef __STDC__
  142. extern int mprotect (MPROTECT_CONST MMAP_ADDR_T addr, MMAP_SIZE_T len, int prot);
  143. #else
  144. extern int mprotect ();
  145. #endif
  146. #endif
  147. #endif
  148. #endif
  149. #endif
  150.  
  151. /* Declare mmap(). */
  152. #ifdef EXECUTABLE_VIA_MMAP
  153. #include <sys/types.h>
  154. #include <sys/mman.h>
  155. #if !defined(PROT_EXEC) && defined(PROT_EXECUTE) /* Irix 4.0.5 needs this */
  156. #define PROT_EXEC PROT_EXECUTE
  157. #endif
  158. #ifdef __STDC__
  159. extern RETMMAPTYPE mmap (MMAP_ADDR_T addr, MMAP_SIZE_T len, int prot, int flags, int fd, off_t off);
  160. #else
  161. extern RETMMAPTYPE mmap ();
  162. #endif
  163. #endif
  164.  
  165. /* Declare open(). */
  166. #ifdef EXECUTABLE_VIA_MMAP_DEVZERO
  167. #include <sys/types.h>
  168. #include <unistd.h>
  169. #include <fcntl.h>
  170. #ifdef NEED_SYS_FILE_H
  171. #include <sys/file.h>
  172. #endif
  173. #ifdef __STDC__
  174. #ifdef OPEN_DOTS
  175. extern int open (OPEN_CONST char* path, int flags, ...);
  176. #else
  177. extern int open (OPEN_CONST char* path, int flags, MODE_T mode);
  178. #endif
  179. #else
  180. extern int open ();
  181. #endif
  182. #endif
  183.  
  184. /* Declare shmget(), shmat(), shmctl(). */
  185. #ifdef EXECUTABLE_VIA_SHM
  186. #include <sys/types.h>
  187. #include <sys/ipc.h>
  188. #include <sys/shm.h>
  189. #ifdef HAVE_SYS_SYSMACROS_H
  190. #include <sys/sysmacros.h>
  191. #endif
  192. #ifdef __STDC__
  193. extern int shmget (key_t key, SHMGET_SIZE_T size, int shmflg);
  194. extern RETSHMATTYPE shmat (int shmid, SHMAT_CONST RETSHMATTYPE shmaddr, int shmflg);
  195. #ifdef SHMCTL_DOTS
  196. extern int shmctl (int shmid, int cmd, ...);
  197. #else
  198. extern int shmctl (int shmid, int cmd, struct shmid_ds * buf);
  199. #endif
  200. #else
  201. extern int shmget ();
  202. extern RETSHMATTYPE shmat ();
  203. extern int shmctl ();
  204. #endif
  205. #endif
  206.  
  207. /* Support for instruction cache flush. */
  208. #ifdef __mips__
  209. #ifdef ultrix
  210. #include <mips/cachectl.h>
  211. #else
  212. #ifdef linux
  213. #include <linux/cachectl.h>
  214. #else
  215. #ifdef HAVE_SYS_CACHECTL_H
  216. #include <sys/cachectl.h>
  217. #endif
  218. #endif
  219. #endif
  220. #endif
  221. #ifdef __m88k__
  222. #include <sys/syslocal.h>
  223. #endif
  224. /* Inline assembly function for instruction cache flush. */
  225. #if defined(__hppa__) || defined(__convex__)
  226. #ifdef __GNUC__
  227. extern inline
  228. #ifdef __hppa__
  229. #include "cache-hppa.c"
  230. #endif
  231. #ifdef __convex__
  232. #include "cache-convex.c"
  233. #endif
  234. #else
  235. extern void __TR_clear_cache();
  236. #endif
  237. #endif
  238.  
  239. /* Length and alignment of trampoline */
  240. #ifdef __i386__
  241. #define TRAMP_LENGTH 15
  242. #define TRAMP_ALIGN 16  /* 4 for a i386, 16 for a i486 */
  243. #endif
  244. #ifdef __m68k__
  245. #define TRAMP_LENGTH 18
  246. #define TRAMP_ALIGN 16
  247. #endif
  248. #ifdef __mips__
  249. #define TRAMP_LENGTH 32
  250. #define TRAMP_ALIGN 4
  251. #endif
  252. #ifdef __sparc__
  253. #define TRAMP_LENGTH 28
  254. #define TRAMP_ALIGN 16
  255. #endif
  256. #ifdef __alpha__
  257. #define TRAMP_LENGTH 48
  258. #define TRAMP_ALIGN 8
  259. #endif
  260. #ifdef __hppa__
  261. #define TRAMP_LENGTH 56
  262. #define TRAMP_ALIGN 16
  263. #endif
  264. #ifdef __arm__
  265. #define TRAMP_LENGTH 44
  266. #define TRAMP_ALIGN 4
  267. #endif
  268. #ifdef __rs6000__
  269. #define TRAMP_LENGTH 24
  270. #define TRAMP_ALIGN 4
  271. #endif
  272. #ifdef __m88k__
  273. #define TRAMP_LENGTH 32
  274. #define TRAMP_ALIGN 8
  275. #endif
  276. #ifdef __convex__
  277. #define TRAMP_LENGTH 20
  278. #define TRAMP_ALIGN 4
  279. #endif
  280.  
  281. #ifdef FOR_AMIGA_CLISP
  282. #define malloc(c) 0
  283. #define free(a)
  284. #define abort() fehler_sint64(0)    /* do anything */
  285. #endif
  286.  
  287. #if !defined(CODE_EXECUTABLE) && !defined(EXECUTABLE_VIA_MPROTECT)
  288. /* AIX doesn't support mprotect() in malloc'ed memory. Must get pages of
  289.  * memory with execute permission via mmap(). Then keep a free list of
  290.  * free trampolines.
  291.  */
  292. static char* freelist = NULL;
  293. #endif
  294.  
  295. __TR_function alloc_trampoline (address, variable, data)
  296.   __TR_function address;
  297.   void* variable;
  298.   void* data;
  299. {
  300.   char* function;
  301.  
  302. #if !defined(CODE_EXECUTABLE)
  303.   static long pagesize = 0;
  304. #if defined(EXECUTABLE_VIA_MMAP_DEVZERO)
  305.   static int zero_fd;
  306. #endif
  307.   /* First, get the page size once and for all. */
  308.   if (!pagesize)
  309.     {
  310. #if defined(HAVE_MACH_VM)
  311.       pagesize = vm_page_size;
  312. #else
  313.       pagesize = getpagesize();
  314. #endif
  315. #if defined(EXECUTABLE_VIA_MMAP_DEVZERO)
  316.       zero_fd = open("/dev/zero",O_RDONLY,0644);
  317.       if (zero_fd < 0)
  318.         { fprintf(stderr,"trampoline: Cannot open /dev/zero!\n"); abort(); }
  319. #endif
  320.     }
  321. #endif
  322.  
  323.   /* 1. Allocate room */
  324.  
  325. #if !defined(CODE_EXECUTABLE) && !defined(EXECUTABLE_VIA_MPROTECT)
  326.   if (freelist == NULL)
  327.     { /* Get a new page. */
  328.       char* page;
  329. #ifdef EXECUTABLE_VIA_MMAP_ANONYMOUS
  330.       page = mmap(0, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_VARIABLE, -1, 0);
  331. #endif
  332. #ifdef EXECUTABLE_VIA_MMAP_DEVZERO
  333.       page = mmap(0, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, zero_fd, 0);
  334. #endif
  335. #ifdef EXECUTABLE_VIA_SHM
  336.       int shmid = shmget(IPC_PRIVATE, pagesize, 0700|IPC_CREAT);
  337.       if (shmid<0)
  338.         { page = (char*)(-1); }
  339.       else
  340.         { page = shmat(shmid, 0, 0); shmctl(shmid, IPC_RMID, 0); }
  341. #endif
  342.       if (page == (char*)(-1))
  343.         { fprintf(stderr,"trampoline: Out of virtual memory!\n"); abort(); }
  344.       /* Fill it with free trampolines. */
  345.       { char** last = &freelist;
  346.         char* page_end = page + pagesize;
  347.         while (page+TRAMP_LENGTH <= page_end)
  348.           { *last = page; last = (char**)page; page += TRAMP_LENGTH; }
  349.         *last = NULL;
  350.     } }
  351.   function = freelist; freelist = *(char**)freelist;
  352. #else
  353.   { char* room = malloc(sizeof(void*) + TRAMP_LENGTH + TRAMP_ALIGN-1);
  354.     if (!room)
  355.       { fprintf(stderr,"trampoline: Out of virtual memory!\n"); abort(); }
  356.     function = (char*)(((long)room + sizeof(void*) + TRAMP_ALIGN-1) & -TRAMP_ALIGN);
  357.     ((char**)function)[-1] = room; /* backpointer for free_trampoline() */
  358.   }
  359. #endif
  360.  
  361.   /* 2. Fill out the trampoline */
  362. #ifdef __i386__
  363.   /* function:
  364.    *    movl $<data>,<variable>        C7 05 <variable> <data>
  365.    *    jmp <address>            E9 <address>-<here>
  366.    * here:
  367.    */
  368.   *(short *) (function + 0) = 0x05C7;
  369.   *(long *)  (function + 2) = (long) variable;
  370.   *(long *)  (function + 6) = (long) data;
  371.   *(char *)  (function +10) = 0xE9;
  372.   *(long *)  (function +11) = (long) address - (long) (function + 15);
  373. #define is_tramp(function)  \
  374.   *(unsigned short *) (function + 0) == 0x05C7 && \
  375.   *(unsigned char *)  (function +10) == 0xE9
  376. #define tramp_address(function)  \
  377.   *(long *)  (function +11) + (long) (function + 15)
  378. #define tramp_variable(function)  \
  379.   *(long *)  (function + 2)
  380. #define tramp_data(function)  \
  381.   *(long *)  (function + 6)
  382. #endif
  383. #ifdef __m68k__
  384.   /* function:
  385.    *    movel #<data>,<variable>    23 FC <data> <variable>
  386.    *    jmp <address>            4E F9 <address>
  387.    *    nop                4E 71
  388.    */
  389.   *(short *) (function + 0) = 0x23FC;
  390.   *(long *)  (function + 2) = (long) data;
  391.   *(long *)  (function + 6) = (long) variable;
  392.   *(short *) (function +10) = 0x4EF9;
  393.   *(long *)  (function +12) = (long) address;
  394.   *(short *) (function +16) = 0x4E71;
  395. #define is_tramp(function)  \
  396.   *(unsigned short *) (function + 0) == 0x23FC && \
  397.   *(unsigned short *) (function +10) == 0x4EF9 && \
  398.   *(unsigned short *) (function +16) == 0x4E71
  399. #define tramp_address(function)  \
  400.   *(long *)  (function +12)
  401. #define tramp_variable(function)  \
  402.   *(long *)  (function + 6)
  403. #define tramp_data(function)  \
  404.   *(long *)  (function + 2)
  405. #endif
  406. #ifdef __mips__
  407.   /* function:
  408.    *    li $2,<data>&0xffff0000        3C 02 hi16(<data>)
  409.    *    ori $2,$2,<data>&0xffff        34 42 lo16(<data>)
  410.    *    sw $2,<variable>        3C 01 hi16(<variable>)
  411.    *                    AC 22 lo16(<variable>)
  412.    *    li $25,<address>&0xffff0000    3C 19 hi16(<address>)
  413.    *    ori $25,$25,<address>&0xffff    37 39 lo16(<address>)
  414.    *    j $25                03 20 00 08
  415.    *    nop                00 00 00 00
  416.    */
  417.   /* What about big endian / little endian ?? */
  418.   *(short *) (function + 0) = 0x3C02;
  419.   *(short *) (function + 2) = (unsigned long) data >> 16;
  420.   *(short *) (function + 4) = 0x3442;
  421.   *(short *) (function + 6) = (unsigned long) data & 0xffff;
  422.   *(short *) (function + 8) = 0x3C01;
  423.   *(short *) (function +10) = (unsigned long) variable >> 16;
  424.   *(short *) (function +12) = 0xAC22;
  425.   *(short *) (function +14) = (unsigned long) variable & 0xffff;
  426.   *(short *) (function +16) = 0x3C19;
  427.   *(short *) (function +18) = (unsigned long) address >> 16;
  428.   *(short *) (function +20) = 0x3739;
  429.   *(short *) (function +22) = (unsigned long) address & 0xffff;
  430.   *(long *)  (function +24) = 0x03200008;
  431.   *(long *)  (function +28) = 0x00000000;
  432. #define is_tramp(function)  \
  433.   *(unsigned short *) (function + 0) == 0x3C02 && \
  434.   *(unsigned short *) (function + 4) == 0x3442 && \
  435.   *(unsigned short *) (function + 8) == 0x3C01 && \
  436.   *(unsigned short *) (function +12) == 0xAC22 && \
  437.   *(unsigned short *) (function +16) == 0x3C19 && \
  438.   *(unsigned short *) (function +20) == 0x3739 && \
  439.   *(unsigned long *)  (function +24) == 0x03200008 && \
  440.   *(unsigned long *)  (function +28) == 0x00000000
  441. #define hilo(hiword,loword)  \
  442.   (((unsigned long) (hiword) << 16) | (unsigned long) (loword))
  443. #define tramp_address(function)  \
  444.   hilo(*(unsigned short *) (function +18), *(unsigned short *) (function +22))
  445. #define tramp_variable(function)  \
  446.   hilo(*(unsigned short *) (function +10), *(unsigned short *) (function +14))
  447. #define tramp_data(function)  \
  448.   hilo(*(unsigned short *) (function + 2), *(unsigned short *) (function + 6))
  449. #endif
  450. #ifdef __sparc__
  451.   /* function:
  452.    *    sethi %hi(<variable>),%g1    03000000 | (<variable> >> 10)
  453.    *    sethi %hi(<data>),%g2        05000000 | (<data> >> 10)
  454.    *    or %g2,%lo(<data>),%g2        8410A000 | (<data> & 0x3ff)
  455.    *    st %g2,[%g1+%lo(<variable>)]    C4206000 | (<variable> & 0x3ff)
  456.    *    sethi %hi(<address>),%g1    03000000 | (<address> >> 10)
  457.    *    jmp %g1+%lo(<address>)        81C06000 | (<address> & 0x3ff)
  458.    *    nop                01000000
  459.    */
  460. #define hi(word)  ((unsigned long) (word) >> 10)
  461. #define lo(word)  ((unsigned long) (word) & 0x3ff)
  462.   *(long *) (function + 0) = 0x03000000 | hi(variable);
  463.   *(long *) (function + 4) = 0x05000000 | hi(data);
  464.   *(long *) (function + 8) = 0x8410A000 | lo(data);
  465.   *(long *) (function +12) = 0xC4206000 | lo(variable);
  466.   *(long *) (function +16) = 0x03000000 | hi(address);
  467.   *(long *) (function +20) = 0x81C06000 | lo(address);
  468.   *(long *) (function +24) = 0x01000000;
  469. #define is_tramp(function)  \
  470.   (*(long *) (function + 0) & 0xffc00000) == 0x03000000 && \
  471.   (*(long *) (function + 4) & 0xffc00000) == 0x05000000 && \
  472.   (*(long *) (function + 8) & 0xfffffc00) == 0x8410A000 && \
  473.   (*(long *) (function +12) & 0xfffffc00) == 0xC4206000 && \
  474.   (*(long *) (function +16) & 0xffc00000) == 0x03000000 && \
  475.   (*(long *) (function +20) & 0xfffffc00) == 0x81C06000 && \
  476.    *(long *) (function +24)               == 0x01000000
  477. #define hilo(hiword,loword)  (((hiword) << 10) | ((loword) & 0x3ff))
  478. #define tramp_address(function)  \
  479.   hilo(*(long *) (function +16), *(long *) (function +20))
  480. #define tramp_variable(function)  \
  481.   hilo(*(long *) (function + 0), *(long *) (function +12))
  482. #define tramp_data(function)  \
  483.   hilo(*(long *) (function + 4), *(long *) (function + 8))
  484. #endif
  485. #ifdef __alpha__
  486.   /* function:
  487.    *    br $1,function..ng    00 00 20 C0
  488.    * function..ng:
  489.    *    ldq $2,20($1)        14 00 41 A4
  490.    *    ldq $3,28($1)        1C 00 61 A4
  491.    *    ldq $27,36($1)        24 00 61 A7
  492.    *    stq $2,0($3)        00 00 43 B4
  493.    *    jmp $31,($27),0        00 00 FB 6B
  494.    *    .quad <data>        <data>
  495.    *    .quad <variable>    <variable>
  496.    *    .quad <address>        <address>
  497.    */
  498.   { static int code [6] =
  499.       { 0xC0200000, 0xA4410014, 0xA461001C, 0xA7610024, 0xB4430000, 0x6BFB0000 };
  500.     int i;
  501.     for (i=0; i<6; i++) { ((int *) function)[i] = code[i]; }
  502.     ((long *) function)[3] = (long) data;
  503.     ((long *) function)[4] = (long) variable;
  504.     ((long *) function)[5] = (long) address;
  505.   }
  506. #define is_tramp(function)  \
  507.   ((int *) function)[0] == 0xC0200000 && \
  508.   ((int *) function)[1] == 0xA4410014 && \
  509.   ((int *) function)[2] == 0xA461001C && \
  510.   ((int *) function)[3] == 0xA7610024 && \
  511.   ((int *) function)[4] == 0xB4430000 && \
  512.   ((int *) function)[5] == 0x6BFB0000
  513. #define tramp_address(function)  \
  514.   ((long *) function)[5]
  515. #define tramp_variable(function)  \
  516.   ((long *) function)[4]
  517. #define tramp_data(function)  \
  518.   ((long *) function)[3]
  519. #endif
  520. #ifdef __hppa__
  521.   /* function:
  522.    *    ldil L'<data>,%r20        22800000 | hi(<data>)
  523.    *    ldil L'<variable>,%r19        22600000 | hi(<variable>)
  524.    *    ldo R'<data>(%r20),%r20        36940000 | lo(<data>)
  525.    *    stw %r20,R'<variable>(%r19)    6A740000 | lo(<variable>)
  526.    *    ldil L'<address>,%r21        22A00000 | hi(<address>)
  527.    *    ldo R'<address>(%r21),%r21    36B50000 | lo(<address>)
  528.    *    bb,>=,n %r21,30,function2    C7D5C012
  529.    *    depi 0,31,2,%r21        D6A01C1E
  530.    *    ldw 4(0,%r21),%r19        4AB30008
  531.    *    ldw 0(0,%r21),%r21        4AB50000
  532.    * function2:
  533.    *    ldsid (0,%r21),%r1        02A010A1
  534.    *    mtsp %r1,%sr0            00011820
  535.    *    be,n 0(%sr0,%r21)        E2A00002
  536.    *    nop                08000240
  537.    */
  538.   /* When decoding a 21-bit argument in an instruction, the hppa performs
  539.    * the following bit manipulation:
  540.    * assemble21: x[20]...x[0]
  541.    *       --> x[0] x[11]...x[1] x[15]..x[14] x[20]...x[16] x[13]..x[12]
  542.    * When encoding a 21-bit argument into an instruction, we need the
  543.    * to perform the reverse permutation:
  544.    * permute21:  y[20]...y[0]
  545.    *       --> y[6]...y[2] y[8]..y[7] y[1]..y[0] y[19]...y[9] y[20]
  546.    */
  547. #define assemble21(x)  \
  548.   ((((x) & 0x1) << 20) | (((x) & 0xFFE) << 8) | \
  549.    (((x) & 0xC000) >> 7) | (((x) & 0x1F0000) >> 14) | (((x) & 0x3000) >> 12))
  550. #define permute21(y)  \
  551.   ((((y) & 0x7C) << 14) | (((y) & 0x180) << 7) | (((y) & 0x3) << 12) | \
  552.    (((y) & 0xFFE00) >> 8) | (((y) & 0x100000) >> 20))
  553. #define hi(word)  permute21((unsigned long) (word) >> 11)
  554. #define lo(word)  (((unsigned long) (word) & 0x7FF) << 1)
  555.   *(long *) (function + 0) = 0x22800000 | hi(data);
  556.   *(long *) (function + 4) = 0x22600000 | hi(variable);
  557.   *(long *) (function + 8) = 0x36940000 | lo(data);
  558.   *(long *) (function +12) = 0x6A740000 | lo(variable);
  559.   *(long *) (function +16) = 0x22A00000 | hi(address);
  560.   *(long *) (function +20) = 0x36B50000 | lo(address);
  561.   *(long *) (function +24) = 0xC7D5C012;
  562.   *(long *) (function +28) = 0xD6A01C1E;
  563.   *(long *) (function +32) = 0x4AB30008;
  564.   *(long *) (function +36) = 0x4AB50000;
  565.   *(long *) (function +40) = 0x02A010A1;
  566.   *(long *) (function +44) = 0x00011820;
  567.   *(long *) (function +48) = 0xE2A00002;
  568.   *(long *) (function +52) = 0x08000240;
  569. #define is_tramp(function)  \
  570.   ((long) function & 3) == 0 && \
  571.   (*(long *) (function + 0) & 0xffe00000) == 0x22800000 && \
  572.   (*(long *) (function + 4) & 0xffe00000) == 0x22600000 && \
  573.   (*(long *) (function + 8) & 0xfffff000) == 0x36940000 && \
  574.   (*(long *) (function +12) & 0xfffff000) == 0x6A740000 && \
  575.   (*(long *) (function +16) & 0xffe00000) == 0x22A00000 && \
  576.   (*(long *) (function +20) & 0xfffff000) == 0x36B50000 && \
  577.   *(long *) (function +24) == 0xC7D5C012 && \
  578.   *(long *) (function +28) == 0xD6A01C1E && \
  579.   *(long *) (function +32) == 0x4AB30008 && \
  580.   *(long *) (function +36) == 0x4AB50000 && \
  581.   *(long *) (function +40) == 0x02A010A1 && \
  582.   *(long *) (function +44) == 0x00011820 && \
  583.   *(long *) (function +48) == 0xE2A00002 && \
  584.   *(long *) (function +52) == 0x08000240
  585. #define hilo(hiword,loword)  \
  586.   ((assemble21((unsigned long) (hiword)) << 11) | \
  587.    (((unsigned long) (loword) & 0xFFE) >> 1) \
  588.   )
  589. #define tramp_address(function)  \
  590.   hilo(*(long *) (function +16), *(long *) (function +20))
  591. #define tramp_variable(function)  \
  592.   hilo(*(long *) (function + 4), *(long *) (function +12))
  593. #define tramp_data(function)  \
  594.   hilo(*(long *) (function + 0), *(long *) (function + 8))
  595. #endif
  596. #ifdef __arm__
  597.   /* function:
  598.    *    stmfd   sp!,{r0}            E92D0001
  599.    *    ldr     r0,[pc,#_data-.-8]        E59F0014
  600.    *    ldr     ip,[r0,#0]            E590C000
  601.    *    ldr     r0,[pc,#_variable-.-8]        E59F0010
  602.    *    str     ip,[r0,#0]            E580C000
  603.    *    ldmfd   sp!,{r0}^            E8FD0001
  604.    *    ldr     ip,[pc,#_function-.-8]        E59FC008
  605.    *    ldr     pc,[ip,#0]            E59CF000
  606.    * _data:
  607.    *    .word   <data>                <data>
  608.    * _variable:
  609.    *    .word   <variable>            <variable>
  610.    * _function:
  611.    *    .word   <address>            <address>
  612.    */
  613.   { static long code [8] =
  614.       { 0xE92D0001, 0xE59F0014, 0xE590C000, 0xE59F0010,
  615.         0xE580C000, 0xE8FD0001, 0xE59FC008, 0xE59CF000
  616.       };
  617.     int i;
  618.     for (i=0; i<8; i++) { ((long *) function)[i] = code[i]; }
  619.     ((long *) function)[8] = (long) data;
  620.     ((long *) function)[9] = (long) variable;
  621.     ((long *) function)[10] = (long) address;
  622.   }
  623. #endif
  624. #ifdef __rs6000__
  625. #if 1
  626.   /* function:
  627.    *    .long .tramp
  628.    *    .long .mytoc
  629.    *    .long 0
  630.    * .mytoc:
  631.    *    .long <variable>
  632.    *    .long <data>
  633.    *    .long <address>
  634.    */
  635.   *(long *)  (function + 0) = ((long *) &tramp)[0];
  636.   *(long *)  (function + 4) = (long) (function + 12);
  637.   *(long *)  (function + 8) = 0;
  638.   *(long *)  (function +12) = (long) variable;
  639.   *(long *)  (function +16) = (long) data;
  640.   *(long *)  (function +20) = (long) address;
  641. #define is_tramp(function)  \
  642.   ((long *) function)[0] == ((long *) &tramp)[0]
  643. #define tramp_address(function)  \
  644.   ((long *) function)[5]
  645. #define tramp_variable(function)  \
  646.   ((long *) function)[3]
  647. #define tramp_data(function)  \
  648.   ((long *) function)[4]
  649. #else /* old try */
  650.   /* function:
  651.    *    .long .function            <.function>
  652.    *    .long 0                00 00 00 00
  653.    *    .long 0                00 00 00 00
  654.    * .function:
  655.    *    liu 11,hi16(<variable>)        3D 60 hi16(<variable>)
  656.    *    oril 11,11,lo16(<variable>)    61 6B lo16(<variable>)
  657.    *    liu 10,hi16(<data>)        3D 40 hi16(<data>)
  658.    *    oril 10,10,lo16(<data>)        61 4A lo16(<data>)
  659.    *    st 10,0(11)            91 4B 00 00
  660.    *    liu 10,hi16(<address>)        3D 40 hi16(<address>)
  661.    *    oril 10,10,lo16(<address>)    61 4A lo16(<address>)
  662.    *    l 11,8(10)            81 6A 00 08
  663.    *    l 2,4(10)            80 4A 00 04
  664.    *    l 0,0(10)            80 0A 00 00
  665.    *    mtctr 0                7C 09 03 A6
  666.    *    bctr                4E 80 04 20
  667.    */
  668.   *(long *)  (function + 0) = (long) (function + 12);
  669.   *(long *)  (function + 4) = 0;
  670.   *(long *)  (function + 8) = 0;
  671.   *(short *) (function +12) = 0x3D60;
  672.   *(short *) (function +14) = (unsigned long) variable >> 16;
  673.   *(short *) (function +16) = 0x616B;
  674.   *(short *) (function +18) = (unsigned long) variable & 0xffff;
  675.   *(short *) (function +20) = 0x3D40;
  676.   *(short *) (function +22) = (unsigned long) data >> 16;
  677.   *(short *) (function +24) = 0x614A;
  678.   *(short *) (function +26) = (unsigned long) data & 0xffff;
  679.   *(long *)  (function +28) = 0x914B0000;
  680.   *(short *) (function +32) = 0x3D40;
  681.   *(short *) (function +34) = (unsigned long) address >> 16;
  682.   *(short *) (function +36) = 0x614A;
  683.   *(short *) (function +38) = (unsigned long) address & 0xffff;
  684.   *(long *)  (function +40) = 0x816A0008;
  685.   *(long *)  (function +44) = 0x804A0004;
  686.   *(long *)  (function +48) = 0x800A0000;
  687.   *(long *)  (function +52) = 0x7C0903A6;
  688.   *(long *)  (function +56) = 0x4E800420;
  689. #define is_tramp(function)  \
  690.   *(unsigned long *)  (function + 0) == (long) (function + 12) && \
  691.   *(unsigned long *)  (function + 4) == 0 && \
  692.   *(unsigned long *)  (function + 8) == 0 && \
  693.   *(unsigned short *) (function +12) == 0x3D60 && \
  694.   *(unsigned short *) (function +16) == 0x616B && \
  695.   *(unsigned short *) (function +20) == 0x3D40 && \
  696.   *(unsigned short *) (function +24) == 0x614A && \
  697.   *(unsigned long *)  (function +28) == 0x914B0000 && \
  698.   *(unsigned short *) (function +32) == 0x3D40 && \
  699.   *(unsigned short *) (function +36) == 0x614A && \
  700.   *(unsigned long *)  (function +40) == 0x816A0008 && \
  701.   *(unsigned long *)  (function +44) == 0x804A0004 && \
  702.   *(unsigned long *)  (function +48) == 0x800A0000 && \
  703.   *(unsigned long *)  (function +52) == 0x7C0903A6 && \
  704.   *(unsigned long *)  (function +56) == 0x4E800420
  705. #define hilo(hiword,loword)  \
  706.   (((unsigned long) (hiword) << 16) | (unsigned long) (loword))
  707. #define tramp_address(function)  \
  708.   hilo(*(unsigned short *) (function +34), *(unsigned short *) (function +38))
  709. #define tramp_variable(function)  \
  710.   hilo(*(unsigned short *) (function +14), *(unsigned short *) (function +18))
  711. #define tramp_data(function)  \
  712.   hilo(*(unsigned short *) (function +22), *(unsigned short *) (function +26))
  713. #endif
  714. #endif
  715. #ifdef __m88k__
  716.   /* function:
  717.    *    or.u    #r13,#r0,hi16(<variable>)    5D A0 hi16(<variable>)
  718.    *    or      #r13,#r13,lo16(<variable>)    59 AD lo16(<variable>)
  719.    *    or.u    #r10,#r0,hi16(<data>)        5D 40 hi16(<data>)
  720.    *    or      #r10,#r10,lo16(<data>)        59 4A lo16(<data>)
  721.    *    st      #r10,#r0,#r13            F5 40 24 0D
  722.    *    or.u    #r13,#r0,hi16(<address>)    5D A0 hi16(<address>)
  723.    *    or      #r13,#r13,lo16(<address>)    59 AD lo16(<address>)
  724.    *    jmp     #r13                F4 00 C0 0D
  725.    */
  726.   *(short *) (function + 0) = 0x5DA0;
  727.   *(short *) (function + 2) = (unsigned long) variable >> 16;
  728.   *(short *) (function + 4) = 0x59AD;
  729.   *(short *) (function + 6) = (unsigned long) variable & 0xffff;
  730.   *(short *) (function + 8) = 0x5D40;
  731.   *(short *) (function +10) = (unsigned long) data >> 16;
  732.   *(short *) (function +12) = 0x594A;
  733.   *(short *) (function +14) = (unsigned long) data & 0xffff;
  734.   *(long *)  (function +16) = 0xF540240D;
  735.   *(short *) (function +20) = 0x5DA0;
  736.   *(short *) (function +22) = (unsigned long) address >> 16;
  737.   *(short *) (function +24) = 0x59AD;
  738.   *(short *) (function +26) = (unsigned long) address & 0xffff;
  739.   *(long *)  (function +28) = 0xF400C00D;
  740. #define is_tramp(function)  \
  741.   *(unsigned short *) (function + 0) == 0x5DA0 && \
  742.   *(unsigned short *) (function + 4) == 0x59AD && \
  743.   *(unsigned short *) (function + 8) == 0x5D40 && \
  744.   *(unsigned short *) (function +12) == 0x594A && \
  745.   *(unsigned long *)  (function +16) == 0xF540240D && \
  746.   *(unsigned short *) (function +20) == 0x5DA0 && \
  747.   *(unsigned short *) (function +24) == 0x59AD && \
  748.   *(unsigned long *)  (function +28) == 0xF400C00D
  749. #define hilo(hiword,loword)  \
  750.   (((unsigned long) (hiword) << 16) | (unsigned long) (loword))
  751. #define tramp_address(function)  \
  752.   hilo(*(unsigned short *) (function +22), *(unsigned short *) (function +26))
  753. #define tramp_variable(function)  \
  754.   hilo(*(unsigned short *) (function + 2), *(unsigned short *) (function + 6))
  755. #define tramp_data(function)  \
  756.   hilo(*(unsigned short *) (function +10), *(unsigned short *) (function +14))
  757. #endif
  758. #ifdef __convex__
  759.   /* function:
  760.    *    ld.w #<data>,s1                11C9 <data>
  761.    *    st.w s1,<variable>            3641 <variable>
  762.    *    jmp <address>                0140 <address>
  763.    *    ds.h 0                    0000
  764.    */
  765.   *(short *) (function + 0) = 0x11C9;
  766.   *(long *)  (function + 2) = (unsigned long) data;
  767.   *(short *) (function + 6) = 0x3641;
  768.   *(long *)  (function + 8) = (unsigned long) variable;
  769.   *(short *) (function +12) = 0x0140;
  770.   *(long *)  (function +14) = (unsigned long) address;
  771.   *(short *) (function +18) = 0x0000;
  772. #define is_tramp(function)  \
  773.   *(unsigned short *) (function + 0) == 0x11C9 && \
  774.   *(unsigned short *) (function + 6) == 0x3641 && \
  775.   *(unsigned short *) (function +12) == 0x0140 && \
  776.   *(unsigned short *) (function +18) == 0x0000
  777. #define tramp_address(function)  \
  778.   *(long *)  (function +14)
  779. #define tramp_variable(function)  \
  780.   *(long *)  (function + 8)
  781. #define tramp_data(function)  \
  782.   *(long *)  (function + 2)
  783. #endif
  784.  
  785.   /* 3. Set memory protection to "executable" */
  786.  
  787. #if !defined(CODE_EXECUTABLE) && defined(EXECUTABLE_VIA_MPROTECT)
  788.   /* Call mprotect on the pages that contain the range. */
  789.   { unsigned long start_addr = (unsigned long) function;
  790.     unsigned long end_addr = (unsigned long) (function + TRAMP_LENGTH);
  791.     start_addr = start_addr & -pagesize;
  792.     end_addr = (end_addr + pagesize-1) & -pagesize;
  793.    {unsigned long len = end_addr - start_addr;
  794. #if defined(HAVE_MACH_VM)
  795.     if (vm_protect(task_self(),start_addr,len,0,VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE) != KERN_SUCCESS)
  796. #else
  797. #if defined(__convex__)
  798.     /* Convex OS calls it `mremap()'. */
  799.     mremap(start_addr, &len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE);
  800.     if (0)
  801. #else
  802. #if defined(HAVE_SYS_M88KBCS_H)
  803.     if (memctl(start_addr, len, MCT_TEXT) == -1)
  804. #else
  805.     if (mprotect((MMAP_ADDR_T)start_addr, len, PROT_READ|PROT_WRITE|PROT_EXEC) < 0)
  806. #endif
  807. #endif
  808. #endif
  809.       { fprintf(stderr,"trampoline: cannot make memory executable\n"); abort(); }
  810.   }}
  811. #endif
  812.  
  813.   /* 4. Flush instruction cache */
  814.   /* We need this because some CPUs have separate data cache and instruction
  815.    * cache. The freshly built trampoline is visible to the data cache, but not
  816.    * maybe not to the instruction cache. This is hairy.
  817.    */
  818. #if defined(__i386__) || defined(__sparc__) || defined(__alpha__) || defined(__arm__) || defined(__rs6000__)
  819.   /* These CPUs have no separate instruction cache. (I think.) */
  820. #endif
  821. #ifdef __m68k__
  822. #ifdef NeXT
  823.   asm volatile ("trap #2");
  824. #else
  825. #ifdef AMIGA
  826.   CacheClearE(function,TRAMP_LENGTH,CACRF_ClearI|CACRF_ClearD);
  827. #endif
  828. #endif
  829. #endif
  830. #ifdef __mips__
  831.   cacheflush(function,TRAMP_LENGTH,ICACHE);
  832. #endif
  833. #ifdef __hppa__
  834.   /* This assumes that the trampoline fits in at most two cache lines. */
  835.   __TR_clear_cache(function,function+TRAMP_LENGTH-1);
  836. #endif
  837. #ifdef __m88k__
  838.   sysmot(S88CACHEFLUSHPAGE, (unsigned long)function & -pagesize);
  839. #endif
  840. #ifdef __convex__
  841.   __TR_clear_cache();
  842. #endif
  843.  
  844.   return (__TR_function)function;
  845. }
  846.  
  847. void free_trampoline (function)
  848.   __TR_function function;
  849. {
  850. #if !defined(CODE_EXECUTABLE) && !defined(EXECUTABLE_VIA_MPROTECT)
  851.   *(char**)function = freelist; freelist = (char*)function;
  852.   /* It is probably not worth calling munmap() for entirely freed pages. */
  853. #else
  854.   free(((char**)function)[-1]);
  855. #endif
  856. }
  857.  
  858. int is_trampoline (function)
  859.   void* function;
  860. {
  861. #ifdef is_tramp
  862.   return ((is_tramp(((char*)function))) ? 1 : 0);
  863. #else
  864.   abort();
  865. #endif
  866. }
  867.  
  868. __TR_function trampoline_address (function)
  869.   void* function;
  870. {
  871. #ifdef tramp_address
  872.   return (__TR_function)(tramp_address(((char*)function)));
  873. #else
  874.   abort();
  875. #endif
  876. }
  877.  
  878. void* trampoline_variable (function)
  879.   void* function;
  880. {
  881. #ifdef tramp_variable
  882.   return (void*)(tramp_variable(((char*)function)));
  883. #else
  884.   abort();
  885. #endif
  886. }
  887.  
  888. void* trampoline_data (function)
  889.   void* function;
  890. {
  891. #ifdef tramp_data
  892.   return (void*)(tramp_data(((char*)function)));
  893. #else
  894.   abort();
  895. #endif
  896. }
  897.