1
/* Trampoline construction */
4
* Copyright 1995-1999, 2001-2006 Bruno Haible, <bruno@clisp.org>
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,
14
#include "trampoline.h"
18
#define __hppaold__ /* Old trampoline, real machine code. */
20
#define __hppanew__ /* New trampoline, just a closure. */
23
#if defined(__powerpc__) && !defined(__powerpc64__)
25
#define __powerpcsysv4__ /* SysV.4 ABI, real machine code. */
27
#define __powerpcaix__ /* AIX ABI, just a closure. */
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. */
34
#if defined(__hppanew__)
36
* A function pointer is a biased pointer to a data area whose first word
37
* contains the actual address of the function.
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.
43
#ifndef CODE_EXECUTABLE
44
#define CODE_EXECUTABLE
47
#if defined(__powerpcaix__) || defined(__powerpc64aix__) || defined(__ia64__)
49
* A function pointer is a pointer to a data area whose first word contains
50
* the actual address of the function.
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.
56
#ifndef CODE_EXECUTABLE
57
#define CODE_EXECUTABLE
61
#if defined(AMIGA) /* Amiga running AmigaOS, not Linux */
62
#ifndef CODE_EXECUTABLE /* configure guesses wrong?? */
63
#define CODE_EXECUTABLE
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
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
81
/* Use mmap on /dev/zero. */
82
#define EXECUTABLE_VIA_MMAP_DEVZERO
86
/* Use an shmat'ed page. */
87
#define EXECUTABLE_VIA_SHM
95
#include <stdio.h> /* declares fprintf() */
97
#include <sys/types.h>
98
#include <stdlib.h> /* declares abort(), malloc(), free() */
103
/* Declare getpagesize(). */
104
#ifdef HAVE_GETPAGESIZE
106
extern "C" RETGETPAGESIZETYPE getpagesize (void);
108
extern RETGETPAGESIZETYPE getpagesize (void);
111
#ifdef HAVE_SYS_PARAM_H
112
#include <sys/param.h>
114
/* Not Unix, e.g. mingw32 */
115
#define PAGESIZE 4096
117
#define getpagesize() PAGESIZE
120
/* Declare mprotect() or equivalent. */
121
#ifdef EXECUTABLE_VIA_MPROTECT
123
#include <sys/resource.h>
124
#include <mach/mach_interface.h>
126
#include <mach/mach_init.h>
129
#include <mach_init.h>
131
#include <mach/machine/vm_param.h>
133
#ifdef HAVE_SYS_M88KBCS_H
134
#include <sys/m88kbcs.h>
135
#define getpagesize() 4096 /* ?? */
137
#include <sys/types.h>
138
#include <sys/mman.h>
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
152
/* Declare open(). */
153
#ifdef EXECUTABLE_VIA_MMAP_DEVZERO
154
#include <sys/types.h>
159
/* Declare shmget(), shmat(), shmctl(). */
160
#ifdef EXECUTABLE_VIA_SHM
161
#include <sys/types.h>
164
#ifdef HAVE_SYS_SYSMACROS_H
165
#include <sys/sysmacros.h>
169
/* Support for instruction cache flush. */
171
#if defined(_WIN32) /* WindowsNT or Windows95 */
172
#define WIN32_LEAN_AND_MEAN
173
#define WIN32_EXTRA_LEAN
178
#if defined(AMIGA) /* Amiga running AmigaOS, not Linux */
179
#include <exec/types.h>
180
#include <exec/execbase.h>
181
#include <proto/exec.h>
184
#include <sys/cache.h>
187
#if defined(__mips__) || defined(__mipsn32__) || defined(__mips64__)
189
#include <mips/cachectl.h>
192
#include <asm/cachectl.h>
194
#ifdef HAVE_SYS_CACHECTL_H
195
#include <sys/cachectl.h>
201
#include <sys/syslocal.h>
203
/* Inline assembly function for instruction cache flush. */
204
#if defined(__sparc__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppaold__) || defined(__powerpcsysv4__) || defined(__convex__)
207
#if defined(__sparc__) || defined(__sparc64__)
208
#include "cache-sparc.c"
211
#include "cache-alpha.c"
214
#include "cache-hppa.c"
216
#if defined(__powerpc__) && !defined(__powerpc64__)
217
#include "cache-powerpc.c"
220
#include "cache-convex.c"
223
#if defined(__sparc__) || defined(__sparc64__)
224
extern void __TR_clear_cache_4();
226
extern void __TR_clear_cache();
231
/* Length and alignment of trampoline */
233
#define TRAMP_LENGTH 15
234
#define TRAMP_ALIGN 16 /* 4 for a i386, 16 for a i486 */
237
#define TRAMP_LENGTH 18
238
#define TRAMP_ALIGN 16
240
#if defined(__mips__) && !defined(__mipsn32__)
241
#define TRAMP_LENGTH 32
242
#define TRAMP_ALIGN 4
245
#define TRAMP_LENGTH 36
246
#define TRAMP_ALIGN 4
249
#define TRAMP_LENGTH 84
250
#define TRAMP_ALIGN 4
253
#define TRAMP_LENGTH 48
254
#define TRAMP_ALIGN 8
256
#if defined(__sparc__) && !defined(__sparc64__)
257
#define TRAMP_LENGTH 28
258
#define TRAMP_ALIGN 16
261
#define TRAMP_LENGTH 48
262
#define TRAMP_ALIGN 16
265
#define TRAMP_LENGTH 48
266
#define TRAMP_ALIGN 8
269
#define TRAMP_LENGTH 56
270
#define TRAMP_ALIGN 16
273
#define TRAMP_LENGTH 20
274
#define TRAMP_ALIGN 16
278
#define TRAMP_LENGTH 36
279
#define TRAMP_ALIGN 4
281
#ifdef __powerpcsysv4__
282
#define TRAMP_LENGTH 36
283
#define TRAMP_ALIGN 4
285
#ifdef __powerpcaix__
286
#define TRAMP_LENGTH 24
287
#define TRAMP_ALIGN 4
289
#ifdef __powerpc64aix__
290
#define TRAMP_LENGTH 48
291
#define TRAMP_ALIGN 8
294
#define TRAMP_LENGTH 32
295
#define TRAMP_ALIGN 8
298
#define TRAMP_LENGTH 20
299
#define TRAMP_ALIGN 4
302
#define TRAMP_LENGTH 40
303
#define TRAMP_ALIGN 16
306
#define TRAMP_LENGTH 32
307
#define TRAMP_ALIGN 16
310
#define TRAMP_LENGTH 36
311
#define TRAMP_ALIGN 2
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
323
static char* freelist = NULL;
326
__TR_function alloc_trampoline (__TR_function address, void* variable, void* data)
330
#if !defined(CODE_EXECUTABLE)
331
static long pagesize = 0;
332
#if defined(EXECUTABLE_VIA_MMAP_DEVZERO)
335
/* First, get the page size once and for all. */
338
#if defined(HAVE_MACH_VM)
339
pagesize = vm_page_size;
341
pagesize = getpagesize();
343
#if defined(EXECUTABLE_VIA_MMAP_DEVZERO)
344
zero_fd = open("/dev/zero",O_RDONLY,0644);
346
{ fprintf(stderr,"trampoline: Cannot open /dev/zero!\n"); abort(); }
351
/* 1. Allocate room */
353
#if !defined(CODE_EXECUTABLE) && !defined(EXECUTABLE_VIA_MPROTECT)
354
if (freelist == NULL)
355
{ /* Get a new page. */
357
#ifdef EXECUTABLE_VIA_MMAP_ANONYMOUS
358
page = mmap(0, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_VARIABLE, -1, 0);
360
#ifdef EXECUTABLE_VIA_MMAP_DEVZERO
361
page = mmap(0, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, zero_fd, 0);
363
#ifdef EXECUTABLE_VIA_SHM
364
int shmid = shmget(IPC_PRIVATE, pagesize, 0700|IPC_CREAT);
366
{ page = (char*)(-1); }
368
{ page = shmat(shmid, 0, 0); shmctl(shmid, IPC_RMID, 0); }
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; }
379
function = freelist; freelist = *(char**)freelist;
381
{ char* room = (char*) malloc(sizeof(void*) + TRAMP_LENGTH + TRAMP_ALIGN-1);
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() */
389
/* 2. Fill out the trampoline */
392
* movl $<data>,<variable> C7 05 <variable> <data>
393
* jmp <address> E9 <address>-<here>
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)
413
* movel #<data>,<variable> 23 FC <data> <variable>
414
* jmp <address> 4E F9 <address>
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)
434
#if defined(__mips__) && !defined(__mipsn32__)
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>)
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))
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
486
* .word <variable> <variable>
487
* .word <data> <data>
488
* .word <address> <address>
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)
516
* dli $2,<variable> 3C 02 hi16(hi32(<variable>))
517
* 34 42 lo16(hi32(<variable>))
519
* 34 42 hi16(lo32(<variable>))
521
* 34 42 lo16(lo32(<variable>))
522
* dli $3,<data> 3C 03 hi16(hi32(<data>))
523
* 34 63 lo16(hi32(<data>))
525
* 34 63 hi16(lo32(<data>))
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>))
532
* 37 39 hi16(lo32(<address>))
534
* 37 39 lo16(lo32(<address>))
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))
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
621
* .dword <variable> <variable>
622
* .dword <data> <data>
623
* .dword <address> <address>
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)
643
#if defined(__sparc__) && !defined(__sparc64__)
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)
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))
680
* rd %pc,%g1 83414000
681
* ldx [%g1+24],%g2 C4586018
682
* ldx [%g1+32],%g3 C6586020
683
* ldx [%g1+40],%g1 C2586028
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
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)
718
* br $1,function..ng 00 00 20 C0
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>
729
{ static int code [6] =
730
{ 0xC0200000, 0xA4410014, 0xA461001C, 0xA7610024, 0xB4430000, 0x6BFB0000 };
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;
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]
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
764
* ldsid (0,%r21),%r1 02A010A1
765
* mtsp %r1,%sr0 00011820
766
* be,n 0(%sr0,%r21) E2A00002
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]
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) \
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))
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;
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]
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
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;
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]
893
#ifdef __powerpcsysv4__
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
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))
939
#ifdef __powerpcaix__
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]
964
#ifdef __powerpc64aix__
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]
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
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))
1034
* ld.w #<data>,s1 11C9 <data>
1035
* st.w s1,<variable> 3641 <variable>
1036
* jmp <address> 0140 <address>
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)
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]
1083
* movabsq $<data>,%rax 48 B8 <data>
1084
* movabsq %rax, <variable> 48 A3 <variable>
1085
* movabsq $<address>,%rax 48 B8 <address>
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))
1134
l %r1,.LC0-.LT0_0(%r13)
1135
mvc 0(4,%r1),.LC1-.LT0_0(%r13)
1136
l %r1,.LC2-.LT1_0(%r13)
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)
1169
/* 3. Set memory protection to "executable" */
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)
1181
#if defined(__convex__)
1182
/* Convex OS calls it `mremap()'. */
1183
mremap(start_addr, &len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE);
1186
#if defined(HAVE_SYS_M88KBCS_H)
1187
if (memctl(start_addr, len, MCT_TEXT) == -1)
1189
if (mprotect((void*)start_addr, len, PROT_READ|PROT_WRITE|PROT_EXEC) < 0)
1193
{ fprintf(stderr,"trampoline: cannot make memory executable\n"); abort(); }
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.
1202
#if !(defined(__hppanew__) || defined(__powerpcaix__) || defined(__powerpc64aix__) || defined(__ia64__))
1203
/* Only needed if we really set up machine instructions. */
1206
while (!FlushInstructionCache(GetCurrentProcess(),function,TRAMP_LENGTH))
1211
#if defined(NeXT) && defined(__GNUC__)
1212
__asm__ __volatile__ ("trap #2");
1215
CacheClearE(function,TRAMP_LENGTH,CACRF_ClearI|CACRF_ClearD);
1221
cachectl(CC_IPURGE,function,TRAMP_LENGTH);
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' */
1230
: "a" (_beg), "d" (_len)
1231
: "%a0", "%a1", "%d0", "%d1" /* call-used registers */
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"
1244
: "d" (_beg), "d" (_len)
1245
: "%d0", "%d2", "%d3"
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"
1262
: "r" (function), "g" ((int)TRAMP_LENGTH)
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?? */
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);
1279
/* This assumes that the trampoline fits in at most two cache lines. */
1280
__TR_clear_cache(function,function+TRAMP_LENGTH-1);
1283
__TR_clear_cache(function,function+TRAMP_LENGTH);
1285
#if defined(__powerpc__) && !defined(__powerpc64__)
1286
__TR_clear_cache(function);
1289
sysmot(S88CACHEFLUSHPAGE, (unsigned long)function & -pagesize);
1297
return (__TR_function) (function + TRAMP_BIAS);
1300
void free_trampoline (__TR_function function)
1303
function = (__TR_function)((char*)function - TRAMP_BIAS);
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. */
1309
free(((char**)function)[-1]);
1313
int is_trampoline (void* function)
1317
void* tramp_address = &tramp;
1318
if (!(((long)function & 3) == (TRAMP_BIAS & 3))) return 0;
1320
return ((is_tramp(((char*)function - TRAMP_BIAS))) ? 1 : 0);
1326
__TR_function trampoline_address (void* function)
1328
#ifdef tramp_address
1329
return (__TR_function)(tramp_address(((char*)function - TRAMP_BIAS)));
1335
void* trampoline_variable (void* function)
1337
#ifdef tramp_variable
1338
return (void*)(tramp_variable(((char*)function - TRAMP_BIAS)));
1344
void* trampoline_data (void* function)
1347
return (void*)(tramp_data(((char*)function - TRAMP_BIAS)));