1#include "common.S" 2 3# 4# This file defines some trampolines for calling blocks. A block function 5# looks like this: 6# 7# retType blockFn(block*, ...) 8# 9# An IMP looks like this: 10# 11# retType imp(id, SEL,...) 12# 13# The trampoline must find the block pointer and then call the block function 14# with the correct first argument, the self pointer moved to the second real 15# argument (the first block argument) and the _cmd parameter excised 16 17.file "block_trampolines.S" 18 19 20#if __x86_64 21//////////////////////////////////////////////////////////////////////////////// 22// x86-64 trampoline 23//////////////////////////////////////////////////////////////////////////////// 24.macro trampoline arg0, arg1 25 mov -0x1007(%rip), \arg1 # Load the block pointer into the second argument 26 xchg \arg1, \arg0 # Swap the first and second arguments 27 jmp *-0x1008(%rip) # Call the block function 28.endm 29// The Win64 and SysV x86-64 ABIs use different registers 30# ifdef _WIN64 31# define ARG0 %rcx 32# define ARG1 %rdx 33# define SARG1 %r8 34# else 35# define ARG0 %rdi 36# define ARG1 %rsi 37# define SARG1 %rdx 38# endif 39# define SARG0 ARG1 40 41#elif __i386 42//////////////////////////////////////////////////////////////////////////////// 43// x86-32 trampoline 44//////////////////////////////////////////////////////////////////////////////// 45 46#ifdef _WIN32 47// Mark this compilation unit as SEH-safe 48.text 49.def @feat.00; 50.scl 3; 51.type 0; 52.endef 53.globl @feat.00 54.set @feat.00, 1 55.data 56#endif 57 58.macro trampoline arg0, arg1 59 call 1f # Store the instruction pointer on the stack 601: 61 pop %eax # Load the old instruction pointer 62 mov \arg0(%esp), %ebx # Load the self parameter 63 mov %ebx, \arg1(%esp) # Store self as the second argument 64 mov -0x1005(%eax), %ebx # Load the block pointer to %ebx 65 mov %ebx, \arg0(%esp) # Store the block pointer in the first argument 66 jmp *-0x1001(%eax) # Call the block function 67.endm 68// All arguments on i386 are passed on the stack. These values are stack 69// offsets - on other platforms they're register values. 70# define ARG0 4 71# define ARG1 8 72# define SARG0 8 73# define SARG1 12 74 75#elif __mips__ 76//////////////////////////////////////////////////////////////////////////////// 77// MIPS trampoline 78//////////////////////////////////////////////////////////////////////////////// 79# ifdef _ABI64 80.macro trampoline arg0, arg1 81 move \arg1, \arg0 82 ld \arg0, -4096($25) 83 ld $25, -4088($25) 84 jr $25 85.endm 86# else 87// 32-bit variant. This ought to work with both n32 and o32, because they both 88// use 32-bit pointers and both use the same registers for the first four 89// arguments (and we only care about the first three). 90.macro trampoline arg0, arg1 91 move \arg1, \arg0 92 lw \arg0, -4096($25) 93 lw $25, -4092($25) 94 jr $25 95.endm 96# endif 97#define ARG0 $a0 98#define ARG1 $a1 99#define ARG2 $a2 100 101#elif defined(__ARM_ARCH_ISA_A64) 102//////////////////////////////////////////////////////////////////////////////// 103// AArch64 (ARM64) trampoline 104//////////////////////////////////////////////////////////////////////////////// 105.macro trampoline arg0, arg1 106 adr x17, #-4096 107 mov \arg1, \arg0 108 ldp \arg0, x17, [x17] 109 br x17 110.endm 111#define ARG0 x0 112#define ARG1 x1 113#define SARG0 x0 114#define SARG1 x1 115 116#elif __arm__ 117//////////////////////////////////////////////////////////////////////////////// 118// AArch32 (ARM) trampoline 119//////////////////////////////////////////////////////////////////////////////// 120 121# if (__ARM_ARCH_ISA_THUMB == 2) 122// If we're on a target that supports Thumb 2, then we need slightly more 123// instructions to support Thumb/ARM code for the IMP and so we need to make 124// the trampolines thumb to be able to fit them in 16 bytes (they fit exactly 125// when assembled as Thumb-2). 126.thumb 127.macro trampoline arg0, arg1 128 sub r12, pc, #4095 129 mov \arg1, \arg0 // Move self over _cmd 130 ldr \arg0, [r12, #-5] // Load the block pointer over self 131 ldr r12, [r12, #-1] // Jump to the block function 132 bx r12 133.endm 134# else 135.macro trampoline arg0, arg1 136 sub r12, pc, #4096 137 mov \arg1, \arg0 // Move self over _cmd 138 ldr \arg0, [r12, #-8] // Load the block pointer over self 139 ldr pc, [r12, #-4] // Jump to the block function 140.endm 141# endif // (__ARM_ARCH_ISA_THUMB == 2) 142#define ARG0 r0 143#define ARG1 r1 144#define SARG0 r1 145#define SARG1 r2 146 147#else 148 149#warning imp_implementationWithBlock() not implemented for your architecture 150.macro trampoline arg0, arg1 151.endm 152#define ARG0 0 153#define ARG1 0 154#define SARG0 0 155#define SARG1 0 156 157#endif 158 159 160.globl CDECL(__objc_block_trampoline) 161CDECL(__objc_block_trampoline): 162 trampoline ARG0, ARG1 163.globl CDECL(__objc_block_trampoline_end) 164CDECL(__objc_block_trampoline_end): 165.globl CDECL(__objc_block_trampoline_sret) 166CDECL(__objc_block_trampoline_sret): 167 trampoline SARG0, SARG1 168.globl CDECL(__objc_block_trampoline_end_sret) 169CDECL(__objc_block_trampoline_end_sret): 170 171 172#ifdef __ELF__ 173.section .note.GNU-stack,"",%progbits 174#endif 175