|  | /*  Special support for trampolines | 
|  | * | 
|  | *   Copyright (C) 1996-2021 Free Software Foundation, Inc. | 
|  | *   Written By Michael Meissner | 
|  | * | 
|  | * This file is free software; you can redistribute it and/or modify it | 
|  | * under the terms of the GNU General Public License as published by the | 
|  | * Free Software Foundation; either version 3, or (at your option) any | 
|  | * later version. | 
|  | * | 
|  | * This file is distributed in the hope that it will be useful, but | 
|  | * WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * General Public License for more details. | 
|  | * | 
|  | * Under Section 7 of GPL version 3, you are granted additional | 
|  | * permissions described in the GCC Runtime Library Exception, version | 
|  | * 3.1, as published by the Free Software Foundation. | 
|  | * | 
|  | * You should have received a copy of the GNU General Public License and | 
|  | * a copy of the GCC Runtime Library Exception along with this program; | 
|  | * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see | 
|  | * <http://www.gnu.org/licenses/>. | 
|  | */ | 
|  |  | 
|  | #include "darwin-asm.h" | 
|  |  | 
|  | /* Set up trampolines.  */ | 
|  |  | 
|  | .text | 
|  | .align	LOG2_GPR_BYTES | 
|  | Ltrampoline_initial: | 
|  | mflr	r0 | 
|  | bl	1f | 
|  | Lfunc = .-Ltrampoline_initial | 
|  | .g_long	0		/* will be replaced with function address */ | 
|  | Lchain = .-Ltrampoline_initial | 
|  | .g_long	0		/* will be replaced with static chain */ | 
|  | 1:	mflr	r11 | 
|  | lg	r12,0(r11)	/* function address */ | 
|  | mtlr	r0 | 
|  | mtctr	r12 | 
|  | lg	r11,GPR_BYTES(r11)	/* static chain */ | 
|  | bctr | 
|  |  | 
|  | trampoline_size = .-Ltrampoline_initial | 
|  |  | 
|  | /* R3 = stack address to store trampoline */ | 
|  | /* R4 = length of trampoline area */ | 
|  | /* R5 = function address */ | 
|  | /* R6 = static chain */ | 
|  |  | 
|  | .globl ___trampoline_setup | 
|  | ___trampoline_setup: | 
|  | mflr	r0		/* save return address */ | 
|  | bcl 20,31,LCF0		/* load up __trampoline_initial into r7 */ | 
|  | LCF0: | 
|  | mflr	r11 | 
|  | addis	r7,r11,ha16(LTRAMP-LCF0) | 
|  | lg	r7,lo16(LTRAMP-LCF0)(r7) | 
|  | subi	r7,r7,4 | 
|  | li	r8,trampoline_size	/* verify trampoline big enough */ | 
|  | cmpg	cr1,r8,r4 | 
|  | srwi	r4,r4,2			/* # words to move (insns always 4-byte) */ | 
|  | addi	r9,r3,-4	/* adjust pointer for lgu */ | 
|  | mtctr	r4 | 
|  | blt	cr1,Labort | 
|  |  | 
|  | mtlr	r0 | 
|  |  | 
|  | /* Copy the instructions to the stack */ | 
|  | Lmove: | 
|  | lwzu	r10,4(r7) | 
|  | stwu	r10,4(r9) | 
|  | bdnz	Lmove | 
|  |  | 
|  | /* Store correct function and static chain */ | 
|  | stg	r5,Lfunc(r3) | 
|  | stg	r6,Lchain(r3) | 
|  |  | 
|  | /* Now flush both caches */ | 
|  | mtctr	r4 | 
|  | Lcache: | 
|  | icbi	0,r3 | 
|  | dcbf	0,r3 | 
|  | addi	r3,r3,4 | 
|  | bdnz	Lcache | 
|  |  | 
|  | /* Ensure cache-flushing has finished.  */ | 
|  | sync | 
|  | isync | 
|  |  | 
|  | /* Make stack writeable.  */ | 
|  | b	___enable_execute_stack | 
|  |  | 
|  | Labort: | 
|  | #ifdef __DYNAMIC__ | 
|  | bl	L_abort$stub | 
|  | .data | 
|  | .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 | 
|  | .align 2 | 
|  | L_abort$stub: | 
|  | .indirect_symbol _abort | 
|  | mflr r0 | 
|  | bcl 20,31,L0$_abort | 
|  | L0$_abort: | 
|  | mflr r11 | 
|  | addis r11,r11,ha16(L_abort$lazy_ptr-L0$_abort) | 
|  | mtlr r0 | 
|  | lgu r12,lo16(L_abort$lazy_ptr-L0$_abort)(r11) | 
|  | mtctr r12 | 
|  | bctr | 
|  | .data | 
|  | .lazy_symbol_pointer | 
|  | L_abort$lazy_ptr: | 
|  | .indirect_symbol _abort | 
|  | .g_long	dyld_stub_binding_helper | 
|  | #else | 
|  | bl	_abort | 
|  | #endif | 
|  | .data | 
|  | .align LOG2_GPR_BYTES | 
|  | LTRAMP: | 
|  | .g_long Ltrampoline_initial | 
|  |  |