~ubuntu-branches/debian/squeeze/ffcall/squeeze

« back to all changes in this revision

Viewing changes to trampoline/trampoline.c

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Egger
  • Date: 2010-06-26 15:29:30 UTC
  • mfrom: (5.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20100626152930-c09y01gk3szcnykn
Tags: 1.10+cvs20100619-2
Ship to unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Trampoline construction */
 
2
 
 
3
/*
 
4
 * Copyright 1995-1999, 2001-2006 Bruno Haible, <bruno@clisp.org>
 
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(__hppa__)
 
17
#if 0
 
18
#define __hppaold__  /* Old trampoline, real machine code. */
 
19
#else
 
20
#define __hppanew__  /* New trampoline, just a closure. */
 
21
#endif
 
22
#endif
 
23
#if defined(__powerpc__) && !defined(__powerpc64__)
 
24
#if !defined(_AIX)
 
25
#define __powerpcsysv4__  /* SysV.4 ABI, real machine code. */
 
26
#else
 
27
#define __powerpcaix__  /* AIX ABI, just a closure. */
 
28
#endif
 
29
#endif
 
30
#if defined(__powerpc64__)
 
31
/* The only ABI on powerpc64 known so far is the AIX ABI. */
 
32
#define __powerpc64aix__  /* AIX ABI, just a closure. */
 
33
#endif
 
34
#if defined(__hppanew__)
 
35
/*
 
36
 * A function pointer is a biased pointer to a data area whose first word
 
37
 * contains the actual address of the function.
 
38
 */
 
39
extern void tramp (); /* trampoline prototype */
 
40
/* We don't need to take any special measures to make the code executable
 
41
 * since the actual instructions are in the text segment.
 
42
 */
 
43
#ifndef CODE_EXECUTABLE
 
44
#define CODE_EXECUTABLE
 
45
#endif
 
46
#endif
 
47
#if defined(__powerpcaix__) || defined(__powerpc64aix__) || defined(__ia64__)
 
48
/*
 
49
 * A function pointer is a pointer to a data area whose first word contains
 
50
 * the actual address of the function.
 
51
 */
 
52
extern void (*tramp) (); /* trampoline prototype */
 
53
/* We don't need to take any special measures to make the code executable
 
54
 * since the actual instructions are in the text segment.
 
55
 */
 
56
#ifndef CODE_EXECUTABLE
 
57
#define CODE_EXECUTABLE
 
58
#endif
 
59
#endif
 
60
#if defined(__m68k__)
 
61
#if defined(AMIGA) /* Amiga running AmigaOS, not Linux */
 
62
#ifndef CODE_EXECUTABLE /* configure guesses wrong?? */
 
63
#define CODE_EXECUTABLE
 
64
#endif
 
65
#endif
 
66
#endif
 
67
 
 
68
#ifndef CODE_EXECUTABLE
 
69
/* How do we make the trampoline's code executable? */
 
70
#if defined(HAVE_MACH_VM) || defined(__convex__) || defined(HAVE_WORKING_MPROTECT) || defined(HAVE_SYS_M88KBCS_H)
 
71
/* mprotect() [or equivalent] the malloc'ed area. */
 
72
#define EXECUTABLE_VIA_MPROTECT
 
73
#else
 
74
#ifdef HAVE_MMAP
 
75
/* Use an mmap'ed page. */
 
76
#define EXECUTABLE_VIA_MMAP
 
77
#ifdef HAVE_MMAP_ANONYMOUS
 
78
/* Use mmap with the MAP_ANONYMOUS or MAP_ANON flag. */
 
79
#define EXECUTABLE_VIA_MMAP_ANONYMOUS
 
80
#else
 
81
/* Use mmap on /dev/zero. */
 
82
#define EXECUTABLE_VIA_MMAP_DEVZERO
 
83
#endif
 
84
#else
 
85
#ifdef HAVE_SHM
 
86
/* Use an shmat'ed page. */
 
87
#define EXECUTABLE_VIA_SHM
 
88
#else
 
89
??
 
90
#endif
 
91
#endif
 
92
#endif
 
93
#endif
 
94
 
 
95
#include <stdio.h> /* declares fprintf() */
 
96
 
 
97
#include <sys/types.h>
 
98
#include <stdlib.h> /* declares abort(), malloc(), free() */
 
99
#ifdef HAVE_UNISTD_H
 
100
#include <unistd.h>
 
101
#endif
 
102
 
 
103
/* Declare getpagesize(). */
 
104
#ifdef HAVE_GETPAGESIZE
 
105
#ifdef __cplusplus
 
106
extern "C" RETGETPAGESIZETYPE getpagesize (void);
 
107
#else
 
108
extern RETGETPAGESIZETYPE getpagesize (void);
 
109
#endif
 
110
#else
 
111
#ifdef HAVE_SYS_PARAM_H
 
112
#include <sys/param.h>
 
113
#else
 
114
/* Not Unix, e.g. mingw32 */
 
115
#define PAGESIZE 4096
 
116
#endif
 
117
#define getpagesize() PAGESIZE
 
118
#endif
 
119
 
 
120
/* Declare mprotect() or equivalent. */
 
121
#ifdef EXECUTABLE_VIA_MPROTECT
 
122
#ifdef HAVE_MACH_VM
 
123
#include <sys/resource.h>
 
124
#include <mach/mach_interface.h>
 
125
#ifdef NeXT
 
126
#include <mach/mach_init.h>
 
127
#endif
 
128
#ifdef __osf__
 
129
#include <mach_init.h>
 
130
#endif
 
131
#include <mach/machine/vm_param.h>
 
132
#else
 
133
#ifdef HAVE_SYS_M88KBCS_H
 
134
#include <sys/m88kbcs.h>
 
135
#define getpagesize()  4096  /* ?? */
 
136
#else
 
137
#include <sys/types.h>
 
138
#include <sys/mman.h>
 
139
#endif
 
140
#endif
 
141
#endif
 
142
 
 
143
/* Declare mmap(). */
 
144
#ifdef EXECUTABLE_VIA_MMAP
 
145
#include <sys/types.h>
 
146
#include <sys/mman.h>
 
147
#if !defined(PROT_EXEC) && defined(PROT_EXECUTE) /* Irix 4.0.5 needs this */
 
148
#define PROT_EXEC PROT_EXECUTE
 
149
#endif
 
150
#endif
 
151
 
 
152
/* Declare open(). */
 
153
#ifdef EXECUTABLE_VIA_MMAP_DEVZERO
 
154
#include <sys/types.h>
 
155
#include <unistd.h>
 
156
#include <fcntl.h>
 
157
#endif
 
158
 
 
159
/* Declare shmget(), shmat(), shmctl(). */
 
160
#ifdef EXECUTABLE_VIA_SHM
 
161
#include <sys/types.h>
 
162
#include <sys/ipc.h>
 
163
#include <sys/shm.h>
 
164
#ifdef HAVE_SYS_SYSMACROS_H
 
165
#include <sys/sysmacros.h>
 
166
#endif
 
167
#endif
 
168
 
 
169
/* Support for instruction cache flush. */
 
170
#ifdef __i386__
 
171
#if defined(_WIN32) /* WindowsNT or Windows95 */
 
172
#define WIN32_LEAN_AND_MEAN
 
173
#define WIN32_EXTRA_LEAN
 
174
#include <windows.h>
 
175
#endif
 
176
#endif
 
177
#ifdef __m68k__
 
178
#if defined(AMIGA) /* Amiga running AmigaOS, not Linux */
 
179
#include <exec/types.h>
 
180
#include <exec/execbase.h>
 
181
#include <proto/exec.h>
 
182
#endif
 
183
#ifdef hpux
 
184
#include <sys/cache.h>
 
185
#endif
 
186
#endif
 
187
#if defined(__mips__) || defined(__mipsn32__) || defined(__mips64__)
 
188
#ifdef ultrix
 
189
#include <mips/cachectl.h>
 
190
#else
 
191
#ifdef linux
 
192
#include <asm/cachectl.h>
 
193
#else
 
194
#ifdef HAVE_SYS_CACHECTL_H
 
195
#include <sys/cachectl.h>
 
196
#endif
 
197
#endif
 
198
#endif
 
199
#endif
 
200
#ifdef __m88k__
 
201
#include <sys/syslocal.h>
 
202
#endif
 
203
/* Inline assembly function for instruction cache flush. */
 
204
#if defined(__sparc__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppaold__) || defined(__powerpcsysv4__) || defined(__convex__)
 
205
#ifdef __GNUC__
 
206
extern inline
 
207
#if defined(__sparc__) || defined(__sparc64__)
 
208
#include "cache-sparc.c"
 
209
#endif
 
210
#ifdef __alpha__
 
211
#include "cache-alpha.c"
 
212
#endif
 
213
#ifdef __hppa__
 
214
#include "cache-hppa.c"
 
215
#endif
 
216
#if defined(__powerpc__) && !defined(__powerpc64__)
 
217
#include "cache-powerpc.c"
 
218
#endif
 
219
#ifdef __convex__
 
220
#include "cache-convex.c"
 
221
#endif
 
222
#else
 
223
#if defined(__sparc__) || defined(__sparc64__)
 
224
extern void __TR_clear_cache_4();
 
225
#else
 
226
extern void __TR_clear_cache();
 
227
#endif
 
228
#endif
 
229
#endif
 
230
 
 
231
/* Length and alignment of trampoline */
 
232
#ifdef __i386__
 
233
#define TRAMP_LENGTH 15
 
234
#define TRAMP_ALIGN 16  /* 4 for a i386, 16 for a i486 */
 
235
#endif
 
236
#ifdef __m68k__
 
237
#define TRAMP_LENGTH 18
 
238
#define TRAMP_ALIGN 16
 
239
#endif
 
240
#if defined(__mips__) && !defined(__mipsn32__)
 
241
#define TRAMP_LENGTH 32
 
242
#define TRAMP_ALIGN 4
 
243
#endif
 
244
#ifdef __mipsn32__
 
245
#define TRAMP_LENGTH 36
 
246
#define TRAMP_ALIGN 4
 
247
#endif
 
248
#ifdef __mips64old__
 
249
#define TRAMP_LENGTH 84
 
250
#define TRAMP_ALIGN 4
 
251
#endif
 
252
#ifdef __mips64__
 
253
#define TRAMP_LENGTH 48
 
254
#define TRAMP_ALIGN 8
 
255
#endif
 
256
#if defined(__sparc__) && !defined(__sparc64__)
 
257
#define TRAMP_LENGTH 28
 
258
#define TRAMP_ALIGN 16
 
259
#endif
 
260
#ifdef __sparc64__
 
261
#define TRAMP_LENGTH 48
 
262
#define TRAMP_ALIGN 16
 
263
#endif
 
264
#ifdef __alpha__
 
265
#define TRAMP_LENGTH 48
 
266
#define TRAMP_ALIGN 8
 
267
#endif
 
268
#ifdef __hppaold__
 
269
#define TRAMP_LENGTH 56
 
270
#define TRAMP_ALIGN 16
 
271
#endif
 
272
#ifdef __hppanew__
 
273
#define TRAMP_LENGTH 20
 
274
#define TRAMP_ALIGN 16
 
275
#define TRAMP_BIAS 2
 
276
#endif
 
277
#ifdef __arm__
 
278
#define TRAMP_LENGTH 36
 
279
#define TRAMP_ALIGN 4
 
280
#endif
 
281
#ifdef __powerpcsysv4__
 
282
#define TRAMP_LENGTH 36
 
283
#define TRAMP_ALIGN 4
 
284
#endif
 
285
#ifdef __powerpcaix__
 
286
#define TRAMP_LENGTH 24
 
287
#define TRAMP_ALIGN 4
 
288
#endif
 
289
#ifdef __powerpc64aix__
 
290
#define TRAMP_LENGTH 48
 
291
#define TRAMP_ALIGN 8
 
292
#endif
 
293
#ifdef __m88k__
 
294
#define TRAMP_LENGTH 32
 
295
#define TRAMP_ALIGN 8
 
296
#endif
 
297
#ifdef __convex__
 
298
#define TRAMP_LENGTH 20
 
299
#define TRAMP_ALIGN 4
 
300
#endif
 
301
#ifdef __ia64__
 
302
#define TRAMP_LENGTH 40
 
303
#define TRAMP_ALIGN 16
 
304
#endif
 
305
#ifdef __x86_64__
 
306
#define TRAMP_LENGTH 32
 
307
#define TRAMP_ALIGN 16
 
308
#endif
 
309
#ifdef __s390__
 
310
#define TRAMP_LENGTH 36
 
311
#define TRAMP_ALIGN 2
 
312
#endif
 
313
 
 
314
#ifndef TRAMP_BIAS
 
315
#define TRAMP_BIAS 0
 
316
#endif
 
317
 
 
318
#if !defined(CODE_EXECUTABLE) && !defined(EXECUTABLE_VIA_MPROTECT)
 
319
/* AIX doesn't support mprotect() in malloc'ed memory. Must get pages of
 
320
 * memory with execute permission via mmap(). Then keep a free list of
 
321
 * free trampolines.
 
322
 */
 
323
static char* freelist = NULL;
 
324
#endif
 
325
 
 
326
__TR_function alloc_trampoline (__TR_function address, void* variable, void* data)
 
327
{
 
328
  char* function;
 
329
 
 
330
#if !defined(CODE_EXECUTABLE)
 
331
  static long pagesize = 0;
 
332
#if defined(EXECUTABLE_VIA_MMAP_DEVZERO)
 
333
  static int zero_fd;
 
334
#endif
 
335
  /* First, get the page size once and for all. */
 
336
  if (!pagesize)
 
337
    {
 
338
#if defined(HAVE_MACH_VM)
 
339
      pagesize = vm_page_size;
 
340
#else
 
341
      pagesize = getpagesize();
 
342
#endif
 
343
#if defined(EXECUTABLE_VIA_MMAP_DEVZERO)
 
344
      zero_fd = open("/dev/zero",O_RDONLY,0644);
 
345
      if (zero_fd < 0)
 
346
        { fprintf(stderr,"trampoline: Cannot open /dev/zero!\n"); abort(); }
 
347
#endif
 
348
    }
 
349
#endif
 
350
 
 
351
  /* 1. Allocate room */
 
352
 
 
353
#if !defined(CODE_EXECUTABLE) && !defined(EXECUTABLE_VIA_MPROTECT)
 
354
  if (freelist == NULL)
 
355
    { /* Get a new page. */
 
356
      char* page;
 
357
#ifdef EXECUTABLE_VIA_MMAP_ANONYMOUS
 
358
      page = mmap(0, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_VARIABLE, -1, 0);
 
359
#endif
 
360
#ifdef EXECUTABLE_VIA_MMAP_DEVZERO
 
361
      page = mmap(0, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, zero_fd, 0);
 
362
#endif
 
363
#ifdef EXECUTABLE_VIA_SHM
 
364
      int shmid = shmget(IPC_PRIVATE, pagesize, 0700|IPC_CREAT);
 
365
      if (shmid<0)
 
366
        { page = (char*)(-1); }
 
367
      else
 
368
        { page = shmat(shmid, 0, 0); shmctl(shmid, IPC_RMID, 0); }
 
369
#endif
 
370
      if (page == (char*)(-1))
 
371
        { fprintf(stderr,"trampoline: Out of virtual memory!\n"); abort(); }
 
372
      /* Fill it with free trampolines. */
 
373
      { char** last = &freelist;
 
374
        char* page_end = page + pagesize;
 
375
        while (page+TRAMP_LENGTH <= page_end)
 
376
          { *last = page; last = (char**)page; page += TRAMP_LENGTH; }
 
377
        *last = NULL;
 
378
    } }
 
379
  function = freelist; freelist = *(char**)freelist;
 
380
#else
 
381
  { char* room = (char*) malloc(sizeof(void*) + TRAMP_LENGTH + TRAMP_ALIGN-1);
 
382
    if (!room)
 
383
      { fprintf(stderr,"trampoline: Out of virtual memory!\n"); abort(); }
 
384
    function = (char*)(((long)room + sizeof(void*) + TRAMP_ALIGN-1) & -TRAMP_ALIGN);
 
385
    ((char**)function)[-1] = room; /* backpointer for free_trampoline() */
 
386
  }
 
387
#endif
 
388
 
 
389
  /* 2. Fill out the trampoline */
 
390
#ifdef __i386__
 
391
  /* function:
 
392
   *    movl $<data>,<variable>         C7 05 <variable> <data>
 
393
   *    jmp <address>                   E9 <address>-<here>
 
394
   * here:
 
395
   */
 
396
  *(short *) (function + 0) = 0x05C7;
 
397
  *(long *)  (function + 2) = (long) variable;
 
398
  *(long *)  (function + 6) = (long) data;
 
399
  *(char *)  (function +10) = 0xE9;
 
400
  *(long *)  (function +11) = (long) address - (long) (function + 15);
 
401
#define is_tramp(function)  \
 
402
  *(unsigned short *) (function + 0) == 0x05C7 && \
 
403
  *(unsigned char *)  (function +10) == 0xE9
 
404
#define tramp_address(function)  \
 
405
  *(long *)  (function +11) + (long) (function + 15)
 
406
#define tramp_variable(function)  \
 
407
  *(long *)  (function + 2)
 
408
#define tramp_data(function)  \
 
409
  *(long *)  (function + 6)
 
410
#endif
 
411
#ifdef __m68k__
 
412
  /* function:
 
413
   *    movel #<data>,<variable>        23 FC <data> <variable>
 
414
   *    jmp <address>                   4E F9 <address>
 
415
   *    nop                             4E 71
 
416
   */
 
417
  *(short *) (function + 0) = 0x23FC;
 
418
  *(long *)  (function + 2) = (long) data;
 
419
  *(long *)  (function + 6) = (long) variable;
 
420
  *(short *) (function +10) = 0x4EF9;
 
421
  *(long *)  (function +12) = (long) address;
 
422
  *(short *) (function +16) = 0x4E71;
 
423
#define is_tramp(function)  \
 
424
  *(unsigned short *) (function + 0) == 0x23FC && \
 
425
  *(unsigned short *) (function +10) == 0x4EF9 && \
 
426
  *(unsigned short *) (function +16) == 0x4E71
 
427
#define tramp_address(function)  \
 
428
  *(long *)  (function +12)
 
429
#define tramp_variable(function)  \
 
430
  *(long *)  (function + 6)
 
431
#define tramp_data(function)  \
 
432
  *(long *)  (function + 2)
 
433
#endif
 
434
#if defined(__mips__) && !defined(__mipsn32__)
 
435
  /* function:
 
436
   *    li $2,<data>&0xffff0000         3C 02 hi16(<data>)
 
437
   *    ori $2,$2,<data>&0xffff         34 42 lo16(<data>)
 
438
   *    sw $2,<variable>                3C 01 hi16(<variable>)
 
439
   *                                    AC 22 lo16(<variable>)
 
440
   *    li $25,<address>&0xffff0000     3C 19 hi16(<address>)
 
441
   *    ori $25,$25,<address>&0xffff    37 39 lo16(<address>)
 
442
   *    j $25                           03 20 00 08
 
443
   *    nop                             00 00 00 00
 
444
   */
 
445
  /* What about big endian / little endian ?? */
 
446
  *(short *) (function + 0) = 0x3C02;
 
447
  *(short *) (function + 2) = (unsigned long) data >> 16;
 
448
  *(short *) (function + 4) = 0x3442;
 
449
  *(short *) (function + 6) = (unsigned long) data & 0xffff;
 
450
  *(short *) (function + 8) = 0x3C01;
 
451
  *(short *) (function +10) = (unsigned long) variable >> 16;
 
452
  *(short *) (function +12) = 0xAC22;
 
453
  *(short *) (function +14) = (unsigned long) variable & 0xffff;
 
454
  *(short *) (function +16) = 0x3C19;
 
455
  *(short *) (function +18) = (unsigned long) address >> 16;
 
456
  *(short *) (function +20) = 0x3739;
 
457
  *(short *) (function +22) = (unsigned long) address & 0xffff;
 
458
  *(long *)  (function +24) = 0x03200008;
 
459
  *(long *)  (function +28) = 0x00000000;
 
460
#define is_tramp(function)  \
 
461
  *(unsigned short *) (function + 0) == 0x3C02 && \
 
462
  *(unsigned short *) (function + 4) == 0x3442 && \
 
463
  *(unsigned short *) (function + 8) == 0x3C01 && \
 
464
  *(unsigned short *) (function +12) == 0xAC22 && \
 
465
  *(unsigned short *) (function +16) == 0x3C19 && \
 
466
  *(unsigned short *) (function +20) == 0x3739 && \
 
467
  *(unsigned long *)  (function +24) == 0x03200008 && \
 
468
  *(unsigned long *)  (function +28) == 0x00000000
 
469
#define hilo(hiword,loword)  \
 
470
  (((unsigned long) (hiword) << 16) | (unsigned long) (loword))
 
471
#define tramp_address(function)  \
 
472
  hilo(*(unsigned short *) (function +18), *(unsigned short *) (function +22))
 
473
#define tramp_variable(function)  \
 
474
  hilo(*(unsigned short *) (function +10), *(unsigned short *) (function +14))
 
475
#define tramp_data(function)  \
 
476
  hilo(*(unsigned short *) (function + 2), *(unsigned short *) (function + 6))
 
477
#endif
 
478
#ifdef __mipsn32__
 
479
  /* function:
 
480
   *    lw $2,24($25)                   8F 22 00 18
 
481
   *    lw $3,28($25)                   8F 23 00 1C
 
482
   *    sw $3,0($2)                     AC 43 00 00
 
483
   *    lw $25,32($25)                  8F 39 00 20
 
484
   *    j $25                           03 20 00 08
 
485
   *    nop                             00 00 00 00
 
486
   *    .word <variable>                <variable>
 
487
   *    .word <data>                    <data>
 
488
   *    .word <address>                 <address>
 
489
   */
 
490
  /* What about big endian / little endian ?? */
 
491
  *(unsigned int *) (function + 0) = 0x8F220018;
 
492
  *(unsigned int *) (function + 4) = 0x8F23001C;
 
493
  *(unsigned int *) (function + 8) = 0xAC430000;
 
494
  *(unsigned int *) (function +12) = 0x8F390020;
 
495
  *(unsigned int *) (function +16) = 0x03200008;
 
496
  *(unsigned int *) (function +20) = 0x00000000;
 
497
  *(unsigned int *) (function +24) = (unsigned int) variable;
 
498
  *(unsigned int *) (function +28) = (unsigned int) data;
 
499
  *(unsigned int *) (function +32) = (unsigned int) address;
 
500
#define is_tramp(function)  \
 
501
  *(int *)          (function + 0) == 0x8F220018 && \
 
502
  *(int *)          (function + 4) == 0x8F23001C && \
 
503
  *(int *)          (function + 8) == 0xAC430000 && \
 
504
  *(int *)          (function +12) == 0x8F390020 && \
 
505
  *(int *)          (function +16) == 0x03200008 && \
 
506
  *(int *)          (function +20) == 0x00000000
 
507
#define tramp_address(function)  \
 
508
  *(unsigned int *) (function +32)
 
509
#define tramp_variable(function)  \
 
510
  *(unsigned int *) (function +24)
 
511
#define tramp_data(function)  \
 
512
  *(unsigned int *) (function +28)
 
513
#endif
 
514
#ifdef __mips64old__
 
515
  /* function:
 
516
   *    dli $2,<variable>               3C 02 hi16(hi32(<variable>))
 
517
   *                                    34 42 lo16(hi32(<variable>))
 
518
   *                                    00 02 14 38
 
519
   *                                    34 42 hi16(lo32(<variable>))
 
520
   *                                    00 02 14 38
 
521
   *                                    34 42 lo16(lo32(<variable>))
 
522
   *    dli $3,<data>                   3C 03 hi16(hi32(<data>))
 
523
   *                                    34 63 lo16(hi32(<data>))
 
524
   *                                    00 03 1C 38
 
525
   *                                    34 63 hi16(lo32(<data>))
 
526
   *                                    00 03 1C 38
 
527
   *                                    34 63 lo16(lo32(<data>))
 
528
   *    sd $3,0($2)                     FC 43 00 00
 
529
   *    dli $25,<address>               3C 19 hi16(hi32(<address>))
 
530
   *                                    37 39 lo16(hi32(<address>))
 
531
   *                                    00 19 CC 38
 
532
   *                                    37 39 hi16(lo32(<address>))
 
533
   *                                    00 19 CC 38
 
534
   *                                    37 39 lo16(lo32(<address>))
 
535
   *    j $25                           03 20 00 08
 
536
   *    nop                             00 00 00 00
 
537
   */
 
538
  /* What about big endian / little endian ?? */
 
539
  *(short *) (function + 0) = 0x3C02;
 
540
  *(short *) (function + 2) = (unsigned long) variable >> 48;
 
541
  *(short *) (function + 4) = 0x3442;
 
542
  *(short *) (function + 6) = ((unsigned long) variable >> 32) & 0xffff;
 
543
  *(int *)   (function + 8) = 0x00021438;
 
544
  *(short *) (function +12) = 0x3442;
 
545
  *(short *) (function +14) = ((unsigned long) variable >> 16) & 0xffff;
 
546
  *(int *)   (function +16) = 0x00021438;
 
547
  *(short *) (function +20) = 0x3442;
 
548
  *(short *) (function +22) = (unsigned long) variable & 0xffff;
 
549
  *(short *) (function +24) = 0x3C03;
 
550
  *(short *) (function +26) = (unsigned long) data >> 48;
 
551
  *(short *) (function +28) = 0x3463;
 
552
  *(short *) (function +30) = ((unsigned long) data >> 32) & 0xffff;
 
553
  *(int *)   (function +32) = 0x00031C38;
 
554
  *(short *) (function +36) = 0x3463;
 
555
  *(short *) (function +38) = ((unsigned long) data >> 16) & 0xffff;
 
556
  *(int *)   (function +40) = 0x00031C38;
 
557
  *(short *) (function +44) = 0x3463;
 
558
  *(short *) (function +46) = (unsigned long) data & 0xffff;
 
559
  *(int *)   (function +48) = 0xFC430000;
 
560
  *(short *) (function +52) = 0x3C19;
 
561
  *(short *) (function +54) = (unsigned long) address >> 48;
 
562
  *(short *) (function +56) = 0x3739;
 
563
  *(short *) (function +58) = ((unsigned long) address >> 32) & 0xffff;
 
564
  *(int *)   (function +60) = 0x0019CC38;
 
565
  *(short *) (function +64) = 0x3739;
 
566
  *(short *) (function +66) = ((unsigned long) address >> 16) & 0xffff;
 
567
  *(int *)   (function +68) = 0x0019CC38;
 
568
  *(short *) (function +72) = 0x3739;
 
569
  *(short *) (function +74) = (unsigned long) address & 0xffff;
 
570
  *(int *)   (function +76) = 0x03200008;
 
571
  *(int *)   (function +80) = 0x00000000;
 
572
#define is_tramp(function)  \
 
573
  *(unsigned short *) (function + 0) == 0x3C02 && \
 
574
  *(unsigned short *) (function + 4) == 0x3442 && \
 
575
  *(unsigned int *)   (function + 8) == 0x00021438 && \
 
576
  *(unsigned short *) (function +12) == 0x3442 && \
 
577
  *(unsigned int *)   (function +16) == 0x00021438 && \
 
578
  *(unsigned short *) (function +20) == 0x3442 && \
 
579
  *(unsigned short *) (function +24) == 0x3C03 && \
 
580
  *(unsigned short *) (function +28) == 0x3463 && \
 
581
  *(unsigned int *)   (function +32) == 0x00031C38 && \
 
582
  *(unsigned short *) (function +36) == 0x3463 && \
 
583
  *(unsigned int *)   (function +40) == 0x00031C38 && \
 
584
  *(unsigned short *) (function +44) == 0x3463 && \
 
585
  *(unsigned int *)   (function +48) == 0xFC430000 && \
 
586
  *(unsigned short *) (function +52) == 0x3C19 && \
 
587
  *(unsigned short *) (function +56) == 0x3739 && \
 
588
  *(unsigned int *)   (function +60) == 0x0019CC38 && \
 
589
  *(unsigned short *) (function +64) == 0x3739 && \
 
590
  *(unsigned int *)   (function +68) == 0x0019CC38 && \
 
591
  *(unsigned short *) (function +72) == 0x3739 && \
 
592
  *(unsigned int *)   (function +76) == 0x03200008 && \
 
593
  *(unsigned int *)   (function +80) == 0x00000000
 
594
#define hilo(word3,word2,word1,word0)  \
 
595
  (((unsigned long) (word3) << 48) | ((unsigned long) (word2) << 32) | \
 
596
   ((unsigned long) (word1) << 16) | (unsigned long) (word0))
 
597
#define tramp_address(function)  \
 
598
  hilo(*(unsigned short *) (function +54), \
 
599
       *(unsigned short *) (function +58), \
 
600
       *(unsigned short *) (function +66), \
 
601
       *(unsigned short *) (function +74))
 
602
#define tramp_variable(function)  \
 
603
  hilo(*(unsigned short *) (function + 2), \
 
604
       *(unsigned short *) (function + 6), \
 
605
       *(unsigned short *) (function +14), \
 
606
       *(unsigned short *) (function +22))
 
607
#define tramp_data(function)  \
 
608
  hilo(*(unsigned short *) (function +26), \
 
609
       *(unsigned short *) (function +30), \
 
610
       *(unsigned short *) (function +38), \
 
611
       *(unsigned short *) (function +46))
 
612
#endif
 
613
#ifdef __mips64__
 
614
  /* function:
 
615
   *    ld $2,24($25)                   DF 22 00 18
 
616
   *    ld $3,32($25)                   DF 23 00 20
 
617
   *    sd $3,0($2)                     FC 43 00 00
 
618
   *    ld $25,40($25)                  DF 39 00 28
 
619
   *    j $25                           03 20 00 08
 
620
   *    nop                             00 00 00 00
 
621
   *    .dword <variable>               <variable>
 
622
   *    .dword <data>                   <data>
 
623
   *    .dword <address>                <address>
 
624
   */
 
625
  /* What about big endian / little endian ?? */
 
626
  *(long *)          (function + 0) = 0xDF220018DF230020L;
 
627
  *(long *)          (function + 8) = 0xFC430000DF390028L;
 
628
  *(long *)          (function +16) = 0x0320000800000000L;
 
629
  *(unsigned long *) (function +24) = (unsigned long) variable;
 
630
  *(unsigned long *) (function +32) = (unsigned long) data;
 
631
  *(unsigned long *) (function +40) = (unsigned long) address;
 
632
#define is_tramp(function)  \
 
633
  *(long *)          (function + 0) == 0xDF220018DF230020L && \
 
634
  *(long *)          (function + 8) == 0xFC430000DF390028L && \
 
635
  *(long *)          (function +16) == 0x0320000800000000L
 
636
#define tramp_address(function)  \
 
637
  *(unsigned long *) (function +40)
 
638
#define tramp_variable(function)  \
 
639
  *(unsigned long *) (function +24)
 
640
#define tramp_data(function)  \
 
641
  *(unsigned long *) (function +32)
 
642
#endif
 
643
#if defined(__sparc__) && !defined(__sparc64__)
 
644
  /* function:
 
645
   *    sethi %hi(<variable>),%g1       03000000 | (<variable> >> 10)
 
646
   *    sethi %hi(<data>),%g2           05000000 | (<data> >> 10)
 
647
   *    or %g2,%lo(<data>),%g2          8410A000 | (<data> & 0x3ff)
 
648
   *    st %g2,[%g1+%lo(<variable>)]    C4206000 | (<variable> & 0x3ff)
 
649
   *    sethi %hi(<address>),%g1        03000000 | (<address> >> 10)
 
650
   *    jmp %g1+%lo(<address>)          81C06000 | (<address> & 0x3ff)
 
651
   *    nop                             01000000
 
652
   */
 
653
#define hi(word)  ((unsigned long) (word) >> 10)
 
654
#define lo(word)  ((unsigned long) (word) & 0x3ff)
 
655
  *(long *) (function + 0) = 0x03000000 | hi(variable);
 
656
  *(long *) (function + 4) = 0x05000000 | hi(data);
 
657
  *(long *) (function + 8) = 0x8410A000 | lo(data);
 
658
  *(long *) (function +12) = 0xC4206000 | lo(variable);
 
659
  *(long *) (function +16) = 0x03000000 | hi(address);
 
660
  *(long *) (function +20) = 0x81C06000 | lo(address);
 
661
  *(long *) (function +24) = 0x01000000;
 
662
#define is_tramp(function)  \
 
663
  (*(long *) (function + 0) & 0xffc00000) == 0x03000000 && \
 
664
  (*(long *) (function + 4) & 0xffc00000) == 0x05000000 && \
 
665
  (*(long *) (function + 8) & 0xfffffc00) == 0x8410A000 && \
 
666
  (*(long *) (function +12) & 0xfffffc00) == 0xC4206000 && \
 
667
  (*(long *) (function +16) & 0xffc00000) == 0x03000000 && \
 
668
  (*(long *) (function +20) & 0xfffffc00) == 0x81C06000 && \
 
669
   *(long *) (function +24)               == 0x01000000
 
670
#define hilo(hiword,loword)  (((hiword) << 10) | ((loword) & 0x3ff))
 
671
#define tramp_address(function)  \
 
672
  hilo(*(long *) (function +16), *(long *) (function +20))
 
673
#define tramp_variable(function)  \
 
674
  hilo(*(long *) (function + 0), *(long *) (function +12))
 
675
#define tramp_data(function)  \
 
676
  hilo(*(long *) (function + 4), *(long *) (function + 8))
 
677
#endif
 
678
#ifdef __sparc64__
 
679
  /* function:
 
680
   *    rd %pc,%g1                      83414000
 
681
   *    ldx [%g1+24],%g2                C4586018
 
682
   *    ldx [%g1+32],%g3                C6586020
 
683
   *    ldx [%g1+40],%g1                C2586028
 
684
   *    jmp %g1                         81C04000
 
685
   *    stx %g3,[%g2]                   C6708000
 
686
   *    .long high32(<variable>)        <variable> >> 32
 
687
   *    .long low32(<variable>)         <variable> & 0xffffffff
 
688
   *    .long high32(<data>)            <data> >> 32
 
689
   *    .long low32(<data>)             <data> & 0xffffffff
 
690
   *    .long high32(<address>)         <address> >> 32
 
691
   *    .long low32(<address>)          <address> & 0xffffffff
 
692
   */
 
693
  *(int *)  (function + 0) = 0x83414000;
 
694
  *(int *)  (function + 4) = 0xC4586018;
 
695
  *(int *)  (function + 8) = 0xC6586020;
 
696
  *(int *)  (function +12) = 0xC2586028;
 
697
  *(int *)  (function +16) = 0x81C04000;
 
698
  *(int *)  (function +20) = 0xC6708000;
 
699
  *(long *) (function +24) = (long) variable;
 
700
  *(long *) (function +32) = (long) data;
 
701
  *(long *) (function +40) = (long) address;
 
702
#define is_tramp(function)  \
 
703
  *(int *)  (function + 0) == 0x83414000 && \
 
704
  *(int *)  (function + 4) == 0xC4586018 && \
 
705
  *(int *)  (function + 8) == 0xC6586020 && \
 
706
  *(int *)  (function +12) == 0xC2586028 && \
 
707
  *(int *)  (function +16) == 0x81C04000 && \
 
708
  *(int *)  (function +20) == 0xC6708000
 
709
#define tramp_address(function)  \
 
710
  *(long *) (function +40)
 
711
#define tramp_variable(function)  \
 
712
  *(long *) (function +24)
 
713
#define tramp_data(function)  \
 
714
  *(long *) (function +32)
 
715
#endif
 
716
#ifdef __alpha__
 
717
  /* function:
 
718
   *    br $1,function..ng      00 00 20 C0
 
719
   * function..ng:
 
720
   *    ldq $2,20($1)           14 00 41 A4
 
721
   *    ldq $3,28($1)           1C 00 61 A4
 
722
   *    ldq $27,36($1)          24 00 61 A7
 
723
   *    stq $2,0($3)            00 00 43 B4
 
724
   *    jmp $31,($27),0         00 00 FB 6B
 
725
   *    .quad <data>            <data>
 
726
   *    .quad <variable>        <variable>
 
727
   *    .quad <address>         <address>
 
728
   */
 
729
  { static int code [6] =
 
730
      { 0xC0200000, 0xA4410014, 0xA461001C, 0xA7610024, 0xB4430000, 0x6BFB0000 };
 
731
    int i;
 
732
    for (i=0; i<6; i++) { ((int *) function)[i] = code[i]; }
 
733
    ((long *) function)[3] = (long) data;
 
734
    ((long *) function)[4] = (long) variable;
 
735
    ((long *) function)[5] = (long) address;
 
736
  }
 
737
#define is_tramp(function)  \
 
738
  ((int *) function)[0] == 0xC0200000 && \
 
739
  ((int *) function)[1] == 0xA4410014 && \
 
740
  ((int *) function)[2] == 0xA461001C && \
 
741
  ((int *) function)[3] == 0xA7610024 && \
 
742
  ((int *) function)[4] == 0xB4430000 && \
 
743
  ((int *) function)[5] == 0x6BFB0000
 
744
#define tramp_address(function)  \
 
745
  ((long *) function)[5]
 
746
#define tramp_variable(function)  \
 
747
  ((long *) function)[4]
 
748
#define tramp_data(function)  \
 
749
  ((long *) function)[3]
 
750
#endif
 
751
#ifdef __hppaold__
 
752
  /* function:
 
753
   *    ldil L'<data>,%r20              22800000 | hi(<data>)
 
754
   *    ldil L'<variable>,%r19          22600000 | hi(<variable>)
 
755
   *    ldo R'<data>(%r20),%r20         36940000 | lo(<data>)
 
756
   *    stw %r20,R'<variable>(%r19)     6A740000 | lo(<variable>)
 
757
   *    ldil L'<address>,%r21           22A00000 | hi(<address>)
 
758
   *    ldo R'<address>(%r21),%r21      36B50000 | lo(<address>)
 
759
   *    bb,>=,n %r21,30,function2       C7D5C012
 
760
   *    depi 0,31,2,%r21                D6A01C1E
 
761
   *    ldw 4(0,%r21),%r19              4AB30008
 
762
   *    ldw 0(0,%r21),%r21              4AB50000
 
763
   * function2:
 
764
   *    ldsid (0,%r21),%r1              02A010A1
 
765
   *    mtsp %r1,%sr0                   00011820
 
766
   *    be,n 0(%sr0,%r21)               E2A00002
 
767
   *    nop                             08000240
 
768
   */
 
769
  /* When decoding a 21-bit argument in an instruction, the hppa performs
 
770
   * the following bit manipulation:
 
771
   * assemble21: x[20]...x[0]
 
772
   *       --> x[0] x[11]...x[1] x[15]..x[14] x[20]...x[16] x[13]..x[12]
 
773
   * When encoding a 21-bit argument into an instruction, we need the
 
774
   * to perform the reverse permutation:
 
775
   * permute21:  y[20]...y[0]
 
776
   *       --> y[6]...y[2] y[8]..y[7] y[1]..y[0] y[19]...y[9] y[20]
 
777
   */
 
778
#define assemble21(x)  \
 
779
  ((((x) & 0x1) << 20) | (((x) & 0xFFE) << 8) | \
 
780
   (((x) & 0xC000) >> 7) | (((x) & 0x1F0000) >> 14) | (((x) & 0x3000) >> 12))
 
781
#define permute21(y)  \
 
782
  ((((y) & 0x7C) << 14) | (((y) & 0x180) << 7) | (((y) & 0x3) << 12) | \
 
783
   (((y) & 0xFFE00) >> 8) | (((y) & 0x100000) >> 20))
 
784
#define hi(word)  permute21((unsigned long) (word) >> 11)
 
785
#define lo(word)  (((unsigned long) (word) & 0x7FF) << 1)
 
786
  *(long *) (function + 0) = 0x22800000 | hi(data);
 
787
  *(long *) (function + 4) = 0x22600000 | hi(variable);
 
788
  *(long *) (function + 8) = 0x36940000 | lo(data);
 
789
  *(long *) (function +12) = 0x6A740000 | lo(variable);
 
790
  *(long *) (function +16) = 0x22A00000 | hi(address);
 
791
  *(long *) (function +20) = 0x36B50000 | lo(address);
 
792
  *(long *) (function +24) = 0xC7D5C012;
 
793
  *(long *) (function +28) = 0xD6A01C1E;
 
794
  *(long *) (function +32) = 0x4AB30008;
 
795
  *(long *) (function +36) = 0x4AB50000;
 
796
  *(long *) (function +40) = 0x02A010A1;
 
797
  *(long *) (function +44) = 0x00011820;
 
798
  *(long *) (function +48) = 0xE2A00002;
 
799
  *(long *) (function +52) = 0x08000240;
 
800
#define is_tramp(function)  \
 
801
  ((long) function & 3) == 0 && \
 
802
  (*(long *) (function + 0) & 0xffe00000) == 0x22800000 && \
 
803
  (*(long *) (function + 4) & 0xffe00000) == 0x22600000 && \
 
804
  (*(long *) (function + 8) & 0xfffff000) == 0x36940000 && \
 
805
  (*(long *) (function +12) & 0xfffff000) == 0x6A740000 && \
 
806
  (*(long *) (function +16) & 0xffe00000) == 0x22A00000 && \
 
807
  (*(long *) (function +20) & 0xfffff000) == 0x36B50000 && \
 
808
  *(long *) (function +24) == 0xC7D5C012 && \
 
809
  *(long *) (function +28) == 0xD6A01C1E && \
 
810
  *(long *) (function +32) == 0x4AB30008 && \
 
811
  *(long *) (function +36) == 0x4AB50000 && \
 
812
  *(long *) (function +40) == 0x02A010A1 && \
 
813
  *(long *) (function +44) == 0x00011820 && \
 
814
  *(long *) (function +48) == 0xE2A00002 && \
 
815
  *(long *) (function +52) == 0x08000240
 
816
#define hilo(hiword,loword)  \
 
817
  ((assemble21((unsigned long) (hiword)) << 11) | \
 
818
   (((unsigned long) (loword) & 0xFFE) >> 1) \
 
819
  )
 
820
#define tramp_address(function)  \
 
821
  hilo(*(long *) (function +16), *(long *) (function +20))
 
822
#define tramp_variable(function)  \
 
823
  hilo(*(long *) (function + 4), *(long *) (function +12))
 
824
#define tramp_data(function)  \
 
825
  hilo(*(long *) (function + 0), *(long *) (function + 8))
 
826
#endif
 
827
#ifdef __hppanew__
 
828
  /* function:
 
829
   *    .long   tramp
 
830
   *    .long   closure
 
831
   * closure:
 
832
   *    .long   <variable>
 
833
   *    .long   <data>
 
834
   *    .long   <address>
 
835
   */
 
836
  { /* work around a bug in gcc 3.* */
 
837
    void* tramp_address = &tramp;
 
838
    *(long *) (function + 0) = ((long *) ((char*)tramp_address-2))[0];
 
839
    *(long *) (function + 4) = (long) (function + 8);
 
840
    *(long *) (function + 8) = (long) variable;
 
841
    *(long *) (function +12) = (long) data;
 
842
    *(long *) (function +16) = (long) address;
 
843
  }
 
844
#define is_tramp(function)  \
 
845
  ((long *) function)[0] == ((long *) ((char*)tramp_address-2))[0]
 
846
#define tramp_address(function)  \
 
847
  ((long *) function)[4]
 
848
#define tramp_variable(function)  \
 
849
  ((long *) function)[2]
 
850
#define tramp_data(function)  \
 
851
  ((long *) function)[3]
 
852
#endif
 
853
#ifdef __arm__
 
854
  /* function:
 
855
   *    stmfd   sp!,{r0}                E92D0001
 
856
   *    ldr     r0,[pc,#16]             E59F000C
 
857
   *    ldr     ip,[pc,#16]             E59FC00C
 
858
   *    str     r0,[ip]                 E58C0000
 
859
   *    ldmfd   sp!,{r0}                E8BD0001
 
860
   *    ldr     pc,[pc,#4]              E59FF004
 
861
   * _data:
 
862
   *    .word   <data>
 
863
   * _variable:
 
864
   *    .word   <variable>
 
865
   * _function:
 
866
   *    .word   <address>
 
867
   */
 
868
  {
 
869
    ((long *) function)[0] = 0xE92D0001;
 
870
    ((long *) function)[1] = 0xE59F000C;
 
871
    ((long *) function)[2] = 0xE59FC00C;
 
872
    ((long *) function)[3] = 0xE58C0000;
 
873
    ((long *) function)[4] = 0xE8BD0001;
 
874
    ((long *) function)[5] = 0xE59FF004;
 
875
    ((long *) function)[6] = (long)data;
 
876
    ((long *) function)[7] = (long)variable;
 
877
    ((long *) function)[8] = (long)address;
 
878
  }
 
879
#define is_tramp(function)  \
 
880
    ((long *) function)[0] == 0xE92D0001 && \
 
881
    ((long *) function)[1] == 0xE59F000C && \
 
882
    ((long *) function)[2] == 0xE59FC00C && \
 
883
    ((long *) function)[3] == 0xE58C0000 && \
 
884
    ((long *) function)[4] == 0xE8BD0001 && \
 
885
    ((long *) function)[5] == 0xE59FF004
 
886
#define tramp_address(function)  \
 
887
  ((long *) function)[8]
 
888
#define tramp_variable(function)  \
 
889
  ((long *) function)[7]
 
890
#define tramp_data(function)  \
 
891
  ((long *) function)[6]
 
892
#endif
 
893
#ifdef __powerpcsysv4__
 
894
  /* function:
 
895
   *    {liu|lis} 11,hi16(<variable>)           3D 60 hi16(<variable>)
 
896
   *    {oril|ori} 11,11,lo16(<variable>)       61 6B lo16(<variable>)
 
897
   *    {liu|lis} 12,hi16(<data>)               3D 80 hi16(<data>)
 
898
   *    {oril|ori} 12,12,lo16(<data>)           61 8C lo16(<data>)
 
899
   *    {st|stw} 12,0(11)                       91 8B 00 00
 
900
   *    {liu|lis} 0,hi16(<address>)             3C 00 hi16(<address>)
 
901
   *    {oril|ori} 0,0,lo16(<address>)          60 00 lo16(<address>)
 
902
   *    mtctr 0                                 7C 09 03 A6
 
903
   *    bctr                                    4E 80 04 20
 
904
   */
 
905
  *(short *) (function + 0) = 0x3D60;
 
906
  *(short *) (function + 2) = (unsigned long) variable >> 16;
 
907
  *(short *) (function + 4) = 0x616B;
 
908
  *(short *) (function + 6) = (unsigned long) variable & 0xffff;
 
909
  *(short *) (function + 8) = 0x3D80;
 
910
  *(short *) (function +10) = (unsigned long) data >> 16;
 
911
  *(short *) (function +12) = 0x618C;
 
912
  *(short *) (function +14) = (unsigned long) data & 0xffff;
 
913
  *(long *)  (function +16) = 0x918B0000;
 
914
  *(short *) (function +20) = 0x3C00;
 
915
  *(short *) (function +22) = (unsigned long) address >> 16;
 
916
  *(short *) (function +24) = 0x6000;
 
917
  *(short *) (function +26) = (unsigned long) address & 0xffff;
 
918
  *(long *)  (function +28) = 0x7C0903A6;
 
919
  *(long *)  (function +32) = 0x4E800420;
 
920
#define is_tramp(function)  \
 
921
  *(unsigned short *) (function + 0) == 0x3D60 && \
 
922
  *(unsigned short *) (function + 4) == 0x616B && \
 
923
  *(unsigned short *) (function + 8) == 0x3D80 && \
 
924
  *(unsigned short *) (function +12) == 0x618C && \
 
925
  *(unsigned long *)  (function +16) == 0x918B0000 && \
 
926
  *(unsigned short *) (function +20) == 0x3C00 && \
 
927
  *(unsigned short *) (function +24) == 0x6000 && \
 
928
  *(unsigned long *)  (function +28) == 0x7C0903A6 && \
 
929
  *(unsigned long *)  (function +32) == 0x4E800420
 
930
#define hilo(hiword,loword)  \
 
931
  (((unsigned long) (hiword) << 16) | (unsigned long) (loword))
 
932
#define tramp_address(function)  \
 
933
  hilo(*(unsigned short *) (function +22), *(unsigned short *) (function +26))
 
934
#define tramp_variable(function)  \
 
935
  hilo(*(unsigned short *) (function + 2), *(unsigned short *) (function + 6))
 
936
#define tramp_data(function)  \
 
937
  hilo(*(unsigned short *) (function +10), *(unsigned short *) (function +14))
 
938
#endif
 
939
#ifdef __powerpcaix__
 
940
  /* function:
 
941
   *    .long .tramp
 
942
   *    .long .mytoc
 
943
   *    .long 0
 
944
   * .mytoc:
 
945
   *    .long <variable>
 
946
   *    .long <data>
 
947
   *    .long <address>
 
948
   */
 
949
  *(long *)  (function + 0) = ((long *) &tramp)[0];
 
950
  *(long *)  (function + 4) = (long) (function + 12);
 
951
  *(long *)  (function + 8) = 0;
 
952
  *(long *)  (function +12) = (long) variable;
 
953
  *(long *)  (function +16) = (long) data;
 
954
  *(long *)  (function +20) = (long) address;
 
955
#define is_tramp(function)  \
 
956
  ((long *) function)[0] == ((long *) &tramp)[0]
 
957
#define tramp_address(function)  \
 
958
  ((long *) function)[5]
 
959
#define tramp_variable(function)  \
 
960
  ((long *) function)[3]
 
961
#define tramp_data(function)  \
 
962
  ((long *) function)[4]
 
963
#endif
 
964
#ifdef __powerpc64aix__
 
965
  /* function:
 
966
   *    .quad .tramp
 
967
   *    .quad .mytoc
 
968
   *    .quad 0
 
969
   * .mytoc:
 
970
   *    .quad <variable>
 
971
   *    .quad <data>
 
972
   *    .quad <address>
 
973
   */
 
974
  *(long *)  (function + 0) = ((long *) &tramp)[0];
 
975
  *(long *)  (function + 8) = (long) (function + 24);
 
976
  *(long *)  (function +16) = 0;
 
977
  *(long *)  (function +24) = (long) variable;
 
978
  *(long *)  (function +32) = (long) data;
 
979
  *(long *)  (function +40) = (long) address;
 
980
#define is_tramp(function)  \
 
981
  ((long *) function)[0] == ((long *) &tramp)[0]
 
982
#define tramp_address(function)  \
 
983
  ((long *) function)[5]
 
984
#define tramp_variable(function)  \
 
985
  ((long *) function)[3]
 
986
#define tramp_data(function)  \
 
987
  ((long *) function)[4]
 
988
#endif
 
989
#ifdef __m88k__
 
990
  /* function:
 
991
   *    or.u    #r13,#r0,hi16(<variable>)       5D A0 hi16(<variable>)
 
992
   *    or      #r13,#r13,lo16(<variable>)      59 AD lo16(<variable>)
 
993
   *    or.u    #r10,#r0,hi16(<data>)           5D 40 hi16(<data>)
 
994
   *    or      #r10,#r10,lo16(<data>)          59 4A lo16(<data>)
 
995
   *    st      #r10,#r0,#r13                   F5 40 24 0D
 
996
   *    or.u    #r13,#r0,hi16(<address>)        5D A0 hi16(<address>)
 
997
   *    or      #r13,#r13,lo16(<address>)       59 AD lo16(<address>)
 
998
   *    jmp     #r13                            F4 00 C0 0D
 
999
   */
 
1000
  *(short *) (function + 0) = 0x5DA0;
 
1001
  *(short *) (function + 2) = (unsigned long) variable >> 16;
 
1002
  *(short *) (function + 4) = 0x59AD;
 
1003
  *(short *) (function + 6) = (unsigned long) variable & 0xffff;
 
1004
  *(short *) (function + 8) = 0x5D40;
 
1005
  *(short *) (function +10) = (unsigned long) data >> 16;
 
1006
  *(short *) (function +12) = 0x594A;
 
1007
  *(short *) (function +14) = (unsigned long) data & 0xffff;
 
1008
  *(long *)  (function +16) = 0xF540240D;
 
1009
  *(short *) (function +20) = 0x5DA0;
 
1010
  *(short *) (function +22) = (unsigned long) address >> 16;
 
1011
  *(short *) (function +24) = 0x59AD;
 
1012
  *(short *) (function +26) = (unsigned long) address & 0xffff;
 
1013
  *(long *)  (function +28) = 0xF400C00D;
 
1014
#define is_tramp(function)  \
 
1015
  *(unsigned short *) (function + 0) == 0x5DA0 && \
 
1016
  *(unsigned short *) (function + 4) == 0x59AD && \
 
1017
  *(unsigned short *) (function + 8) == 0x5D40 && \
 
1018
  *(unsigned short *) (function +12) == 0x594A && \
 
1019
  *(unsigned long *)  (function +16) == 0xF540240D && \
 
1020
  *(unsigned short *) (function +20) == 0x5DA0 && \
 
1021
  *(unsigned short *) (function +24) == 0x59AD && \
 
1022
  *(unsigned long *)  (function +28) == 0xF400C00D
 
1023
#define hilo(hiword,loword)  \
 
1024
  (((unsigned long) (hiword) << 16) | (unsigned long) (loword))
 
1025
#define tramp_address(function)  \
 
1026
  hilo(*(unsigned short *) (function +22), *(unsigned short *) (function +26))
 
1027
#define tramp_variable(function)  \
 
1028
  hilo(*(unsigned short *) (function + 2), *(unsigned short *) (function + 6))
 
1029
#define tramp_data(function)  \
 
1030
  hilo(*(unsigned short *) (function +10), *(unsigned short *) (function +14))
 
1031
#endif
 
1032
#ifdef __convex__
 
1033
  /* function:
 
1034
   *    ld.w #<data>,s1                         11C9 <data>
 
1035
   *    st.w s1,<variable>                      3641 <variable>
 
1036
   *    jmp <address>                           0140 <address>
 
1037
   *    ds.h 0                                  0000
 
1038
   */
 
1039
  *(short *) (function + 0) = 0x11C9;
 
1040
  *(long *)  (function + 2) = (unsigned long) data;
 
1041
  *(short *) (function + 6) = 0x3641;
 
1042
  *(long *)  (function + 8) = (unsigned long) variable;
 
1043
  *(short *) (function +12) = 0x0140;
 
1044
  *(long *)  (function +14) = (unsigned long) address;
 
1045
  *(short *) (function +18) = 0x0000;
 
1046
#define is_tramp(function)  \
 
1047
  *(unsigned short *) (function + 0) == 0x11C9 && \
 
1048
  *(unsigned short *) (function + 6) == 0x3641 && \
 
1049
  *(unsigned short *) (function +12) == 0x0140 && \
 
1050
  *(unsigned short *) (function +18) == 0x0000
 
1051
#define tramp_address(function)  \
 
1052
  *(long *)  (function +14)
 
1053
#define tramp_variable(function)  \
 
1054
  *(long *)  (function + 8)
 
1055
#define tramp_data(function)  \
 
1056
  *(long *)  (function + 2)
 
1057
#endif
 
1058
#ifdef __ia64__
 
1059
  /* function:
 
1060
   *    data8   tramp
 
1061
   *    data8   closure
 
1062
   * closure:
 
1063
   *    data8   <address>
 
1064
   *    data8   <variable>
 
1065
   *    data8   <data>
 
1066
   */
 
1067
  *(long *) (function + 0) = (long) &tramp;
 
1068
  *(long *) (function + 8) = (long) (function + 16);
 
1069
  *(long *) (function +16) = (long) address;
 
1070
  *(long *) (function +24) = (long) variable;
 
1071
  *(long *) (function +32) = (long) data;
 
1072
#define is_tramp(function)  \
 
1073
  ((long *) function)[0] == (long) &tramp
 
1074
#define tramp_address(function)  \
 
1075
  ((long *) function)[2]
 
1076
#define tramp_variable(function)  \
 
1077
  ((long *) function)[3]
 
1078
#define tramp_data(function)  \
 
1079
  ((long *) function)[4]
 
1080
#endif
 
1081
#ifdef __x86_64__
 
1082
  /* function:
 
1083
   *    movabsq $<data>,%rax            48 B8 <data>
 
1084
   *    movabsq %rax, <variable>        48 A3 <variable>
 
1085
   *    movabsq $<address>,%rax         48 B8 <address>
 
1086
   *    jmp *%rax                       FF E0
 
1087
   */
 
1088
  *(short *) (function + 0) = 0xB848;
 
1089
  *(short *) (function + 2) = (unsigned long) data & 0xffff;
 
1090
  *(int *)   (function + 4) = ((unsigned long) data >> 16) & 0xffffffff;
 
1091
  *(short *) (function + 8) = ((unsigned long) data >> 48) & 0xffff;
 
1092
  *(short *) (function +10) = 0xA348;
 
1093
  *(int *)   (function +12) = (unsigned long) variable & 0xffffffff;
 
1094
  *(int *)   (function +16) = ((unsigned long) variable >> 32) & 0xffffffff;
 
1095
  *(short *) (function +20) = 0xB848;
 
1096
  *(short *) (function +22) = (unsigned long) address & 0xffff;
 
1097
  *(int *)   (function +24) = ((unsigned long) address >> 16) & 0xffffffff;
 
1098
  *(short *) (function +28) = ((unsigned long) address >> 48) & 0xffff;
 
1099
  *(short *) (function +30) = 0xE0FF;
 
1100
#define is_tramp(function)  \
 
1101
  *(unsigned short *) (function + 0) == 0xB848 && \
 
1102
  *(unsigned short *) (function +10) == 0xA348 && \
 
1103
  *(unsigned short *) (function +20) == 0xB848 && \
 
1104
  *(unsigned short *) (function +30) == 0xE0FF
 
1105
#define hilo(hiword,loword)  \
 
1106
  (((unsigned long) (hiword) << 32) | (unsigned long) (loword))
 
1107
#define himidlo(hishort,midword,loshort)  \
 
1108
  (((unsigned long) (hishort) << 48) | (unsigned long) (midword) << 16 \
 
1109
   | (unsigned long) (loshort))
 
1110
#define tramp_address(function)  \
 
1111
  himidlo(*(unsigned short *) (function +28), \
 
1112
          *(unsigned int *)   (function +24), \
 
1113
          *(unsigned short *) (function +22))
 
1114
#define tramp_variable(function)  \
 
1115
  hilo(*(unsigned int *) (function +16), *(unsigned int *) (function +12))
 
1116
#define tramp_data(function)  \
 
1117
  himidlo(*(unsigned short *) (function + 8), \
 
1118
          *(unsigned int *)   (function + 4), \
 
1119
          *(unsigned short *) (function + 2))
 
1120
#endif
 
1121
#ifdef __s390__
 
1122
  /* function:
 
1123
 
 
1124
        lr      %r0,%r13
 
1125
        bras    %r13,.LTN0_0
 
1126
.LT0_0:
 
1127
.LC0:
 
1128
        .long   0x73554711
 
1129
.LC1:
 
1130
        .long   0x12345678
 
1131
.LC2:
 
1132
        .long   0xbabebec0
 
1133
.LTN0_0:
 
1134
        l       %r1,.LC0-.LT0_0(%r13)
 
1135
        mvc     0(4,%r1),.LC1-.LT0_0(%r13)
 
1136
        l       %r1,.LC2-.LT1_0(%r13)
 
1137
        lr      %r13,%r0
 
1138
        br      %r1
 
1139
  */
 
1140
  /* What about big endian / little endian ?? */
 
1141
  *(unsigned short *) (function + 0) = 0x180D;
 
1142
  *(unsigned int *)   (function + 2) = 0xA7D50008;
 
1143
  *(unsigned int *)   (function + 6) = (unsigned int) variable;
 
1144
  *(unsigned int *)   (function +10) = (unsigned int) data;
 
1145
  *(unsigned int *)   (function +14) = (unsigned int) address;
 
1146
  *(unsigned int *)   (function +18) = 0x5810D000;
 
1147
  *(unsigned int *)   (function +22) = 0xD2031000;
 
1148
  *(unsigned short *) (function +26) = 0xD004;
 
1149
  *(unsigned int *)   (function +28) = 0x5810D008;
 
1150
  *(unsigned short *) (function +32) = 0x18D0;
 
1151
  *(unsigned short *) (function +34) = 0x07f1;
 
1152
#define is_tramp(function)  \
 
1153
  *(short *)          (function + 0) == 0x180D && \
 
1154
  *(int *)            (function + 2) == 0xA7D50008 && \
 
1155
  *(int *)            (function +18) == 0x5810D000 && \
 
1156
  *(int *)            (function +22) == 0xD2031000 && \
 
1157
  *(short *)          (function +26) == 0xD004 && \
 
1158
  *(int *)            (function +28) == 0x5810D008 && \
 
1159
  *(short *)          (function +32) == 0x18D0 && \
 
1160
  *(short *)          (function +34) == 0x07f1
 
1161
#define tramp_address(function)  \
 
1162
  *(unsigned int *) (function +14)
 
1163
#define tramp_variable(function)  \
 
1164
  *(unsigned int *) (function +6)
 
1165
#define tramp_data(function)  \
 
1166
  *(unsigned int *) (function +10)
 
1167
#endif
 
1168
 
 
1169
  /* 3. Set memory protection to "executable" */
 
1170
 
 
1171
#if !defined(CODE_EXECUTABLE) && defined(EXECUTABLE_VIA_MPROTECT)
 
1172
  /* Call mprotect on the pages that contain the range. */
 
1173
  { unsigned long start_addr = (unsigned long) function;
 
1174
    unsigned long end_addr = (unsigned long) (function + TRAMP_LENGTH);
 
1175
    start_addr = start_addr & -pagesize;
 
1176
    end_addr = (end_addr + pagesize-1) & -pagesize;
 
1177
   {unsigned long len = end_addr - start_addr;
 
1178
#if defined(HAVE_MACH_VM)
 
1179
    if (vm_protect(task_self(),start_addr,len,0,VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE) != KERN_SUCCESS)
 
1180
#else
 
1181
#if defined(__convex__)
 
1182
    /* Convex OS calls it `mremap()'. */
 
1183
    mremap(start_addr, &len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE);
 
1184
    if (0)
 
1185
#else
 
1186
#if defined(HAVE_SYS_M88KBCS_H)
 
1187
    if (memctl(start_addr, len, MCT_TEXT) == -1)
 
1188
#else
 
1189
    if (mprotect((void*)start_addr, len, PROT_READ|PROT_WRITE|PROT_EXEC) < 0)
 
1190
#endif
 
1191
#endif
 
1192
#endif
 
1193
      { fprintf(stderr,"trampoline: cannot make memory executable\n"); abort(); }
 
1194
  }}
 
1195
#endif
 
1196
 
 
1197
  /* 4. Flush instruction cache */
 
1198
  /* We need this because some CPUs have separate data cache and instruction
 
1199
   * cache. The freshly built trampoline is visible to the data cache, but not
 
1200
   * maybe not to the instruction cache. This is hairy.
 
1201
   */
 
1202
#if !(defined(__hppanew__) || defined(__powerpcaix__) || defined(__powerpc64aix__) || defined(__ia64__))
 
1203
  /* Only needed if we really set up machine instructions. */
 
1204
#ifdef __i386__
 
1205
#if defined(_WIN32)
 
1206
  while (!FlushInstructionCache(GetCurrentProcess(),function,TRAMP_LENGTH))
 
1207
    continue;
 
1208
#endif
 
1209
#endif
 
1210
#ifdef __m68k__
 
1211
#if defined(NeXT) && defined(__GNUC__)
 
1212
  __asm__ __volatile__ ("trap #2");
 
1213
#endif
 
1214
#if defined(AMIGA)
 
1215
  CacheClearE(function,TRAMP_LENGTH,CACRF_ClearI|CACRF_ClearD);
 
1216
#endif
 
1217
#if defined(apollo)
 
1218
  cache_$clear();
 
1219
#endif
 
1220
#if defined(hpux)
 
1221
  cachectl(CC_IPURGE,function,TRAMP_LENGTH);
 
1222
#endif
 
1223
#if defined(__NetBSD__) && defined(__GNUC__)
 
1224
  { register unsigned long _beg __asm__ ("%a1") = (unsigned long) function;
 
1225
    register unsigned long _len __asm__ ("%d1") = TRAMP_LENGTH;
 
1226
    __asm__ __volatile__ (
 
1227
      "move%.l %#0x80000004,%/d0\n\t" /* CC_EXTPURGE | C_IPURGE */
 
1228
      "trap #12"                      /* kernel call `cachectl' */
 
1229
      :
 
1230
      : "a" (_beg), "d" (_len)
 
1231
      : "%a0", "%a1", "%d0", "%d1"    /* call-used registers */
 
1232
      );
 
1233
  }
 
1234
#endif
 
1235
#if defined(__linux__) && defined(__GNUC__)
 
1236
  { register unsigned long _beg __asm__ ("%d1") = (unsigned long) function;
 
1237
    register unsigned long _len __asm__ ("%d4") = TRAMP_LENGTH + 32;
 
1238
    __asm__ __volatile__ (
 
1239
      "move%.l %#123,%/d0\n\t"
 
1240
      "move%.l %#1,%/d2\n\t"
 
1241
      "move%.l %#3,%/d3\n\t"
 
1242
      "trap %#0"
 
1243
      :
 
1244
      : "d" (_beg), "d" (_len)
 
1245
      : "%d0", "%d2", "%d3"
 
1246
      );
 
1247
  }
 
1248
#endif
 
1249
#if defined(AUX) && defined(__GNUC__)
 
1250
  /* sysm68k(105, addr, scope, cache, len) */
 
1251
  __asm__ __volatile__ (
 
1252
    "move%.l %1,%/sp@-\n\t"
 
1253
    "move%.l %#3,%/sp@-\n\t"
 
1254
    "move%.l %#1,%/sp@-\n\t"
 
1255
    "move%.l %0,%/sp@-\n\t"
 
1256
    "move%.l %#105,%/sp@-\n\t"
 
1257
    "move%.l %#0,%/sp@-\n\t"
 
1258
    "move%.l %#38,%/sp@-\n\t"
 
1259
    "trap %#0\n\t"
 
1260
    "add%.l %#24,%/sp"
 
1261
    :
 
1262
    : "r" (function), "g" ((int)TRAMP_LENGTH)
 
1263
    : "%d0"
 
1264
    );
 
1265
#endif
 
1266
#endif
 
1267
#if defined(__mips__) || defined(__mipsn32__) || defined(__mips64__)
 
1268
  cacheflush(function,TRAMP_LENGTH,ICACHE);
 
1269
  /* gforth-0.3.0 uses BCACHE instead of ICACHE. Why?? */
 
1270
#endif
 
1271
#if defined(__sparc__) || defined(__sparc64__)
 
1272
  /* This assumes that the trampoline fits in at most four cache lines. */
 
1273
  __TR_clear_cache_4(function,function+TRAMP_LENGTH-1);
 
1274
#endif
 
1275
#ifdef __alpha__
 
1276
  __TR_clear_cache();
 
1277
#endif
 
1278
#ifdef __hppa__
 
1279
  /* This assumes that the trampoline fits in at most two cache lines. */
 
1280
  __TR_clear_cache(function,function+TRAMP_LENGTH-1);
 
1281
#endif
 
1282
#ifdef __arm__
 
1283
  __TR_clear_cache(function,function+TRAMP_LENGTH);
 
1284
#endif
 
1285
#if defined(__powerpc__) && !defined(__powerpc64__)
 
1286
  __TR_clear_cache(function);
 
1287
#endif
 
1288
#ifdef __m88k__
 
1289
  sysmot(S88CACHEFLUSHPAGE, (unsigned long)function & -pagesize);
 
1290
#endif
 
1291
#ifdef __convex__
 
1292
  __TR_clear_cache();
 
1293
#endif
 
1294
#endif
 
1295
 
 
1296
  /* 5. Return. */
 
1297
  return (__TR_function) (function + TRAMP_BIAS);
 
1298
}
 
1299
 
 
1300
void free_trampoline (__TR_function function)
 
1301
{
 
1302
#if TRAMP_BIAS
 
1303
  function = (__TR_function)((char*)function - TRAMP_BIAS);
 
1304
#endif
 
1305
#if !defined(CODE_EXECUTABLE) && !defined(EXECUTABLE_VIA_MPROTECT)
 
1306
  *(char**)function = freelist; freelist = (char*)function;
 
1307
  /* It is probably not worth calling munmap() for entirely freed pages. */
 
1308
#else
 
1309
  free(((char**)function)[-1]);
 
1310
#endif
 
1311
}
 
1312
 
 
1313
int is_trampoline (void* function)
 
1314
{
 
1315
#ifdef is_tramp
 
1316
#ifdef __hppanew__
 
1317
  void* tramp_address = &tramp;
 
1318
  if (!(((long)function & 3) == (TRAMP_BIAS & 3))) return 0;
 
1319
#endif
 
1320
  return ((is_tramp(((char*)function - TRAMP_BIAS))) ? 1 : 0);
 
1321
#else
 
1322
  abort();
 
1323
#endif
 
1324
}
 
1325
 
 
1326
__TR_function trampoline_address (void* function)
 
1327
{
 
1328
#ifdef tramp_address
 
1329
  return (__TR_function)(tramp_address(((char*)function - TRAMP_BIAS)));
 
1330
#else
 
1331
  abort();
 
1332
#endif
 
1333
}
 
1334
 
 
1335
void* trampoline_variable (void* function)
 
1336
{
 
1337
#ifdef tramp_variable
 
1338
  return (void*)(tramp_variable(((char*)function - TRAMP_BIAS)));
 
1339
#else
 
1340
  abort();
 
1341
#endif
 
1342
}
 
1343
 
 
1344
void* trampoline_data (void* function)
 
1345
{
 
1346
#ifdef tramp_data
 
1347
  return (void*)(tramp_data(((char*)function - TRAMP_BIAS)));
 
1348
#else
 
1349
  abort();
 
1350
#endif
 
1351
}