1/*  Special support for trampolines
2 *
3 *   Copyright (C) 1996-2020 Free Software Foundation, Inc.
4 *   Written By Michael Meissner
5 *
6 * This file is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 3, or (at your option) any
9 * later version.
10 *
11 * This file is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * General Public License for more details.
15 *
16 * Under Section 7 of GPL version 3, you are granted additional
17 * permissions described in the GCC Runtime Library Exception, version
18 * 3.1, as published by the Free Software Foundation.
19 *
20 * You should have received a copy of the GNU General Public License and
21 * a copy of the GCC Runtime Library Exception along with this program;
22 * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 * <http://www.gnu.org/licenses/>.
24 */
25
26#include "darwin-asm.h"
27
28/* Set up trampolines.  */
29
30.text
31	.align	LOG2_GPR_BYTES
32Ltrampoline_initial:
33	mflr	r0
34	bl	1f
35Lfunc = .-Ltrampoline_initial
36	.g_long	0		/* will be replaced with function address */
37Lchain = .-Ltrampoline_initial
38	.g_long	0		/* will be replaced with static chain */
391:	mflr	r11
40	lg	r12,0(r11)	/* function address */
41	mtlr	r0
42	mtctr	r12
43	lg	r11,GPR_BYTES(r11)	/* static chain */
44	bctr
45
46trampoline_size = .-Ltrampoline_initial
47
48/* R3 = stack address to store trampoline */
49/* R4 = length of trampoline area */
50/* R5 = function address */
51/* R6 = static chain */
52
53	.globl ___trampoline_setup
54___trampoline_setup:
55	mflr	r0		/* save return address */
56        bcl 20,31,LCF0		/* load up __trampoline_initial into r7 */
57LCF0:
58        mflr	r11
59        addis	r7,r11,ha16(LTRAMP-LCF0)
60	lg	r7,lo16(LTRAMP-LCF0)(r7)
61	subi	r7,r7,4
62	li	r8,trampoline_size	/* verify trampoline big enough */
63	cmpg	cr1,r8,r4
64	srwi	r4,r4,2			/* # words to move (insns always 4-byte) */
65	addi	r9,r3,-4	/* adjust pointer for lgu */
66	mtctr	r4
67	blt	cr1,Labort
68
69	mtlr	r0
70
71	/* Copy the instructions to the stack */
72Lmove:
73	lwzu	r10,4(r7)
74	stwu	r10,4(r9)
75	bdnz	Lmove
76
77	/* Store correct function and static chain */
78	stg	r5,Lfunc(r3)
79	stg	r6,Lchain(r3)
80
81	/* Now flush both caches */
82	mtctr	r4
83Lcache:
84	icbi	0,r3
85	dcbf	0,r3
86	addi	r3,r3,4
87	bdnz	Lcache
88
89	/* Ensure cache-flushing has finished.  */
90	sync
91	isync
92
93	/* Make stack writeable.  */
94	b	___enable_execute_stack
95
96Labort:
97#ifdef __DYNAMIC__
98	bl	L_abort$stub
99.data
100.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
101	.align 2
102L_abort$stub:
103        .indirect_symbol _abort
104        mflr r0
105        bcl 20,31,L0$_abort
106L0$_abort:
107        mflr r11
108        addis r11,r11,ha16(L_abort$lazy_ptr-L0$_abort)
109        mtlr r0
110	lgu r12,lo16(L_abort$lazy_ptr-L0$_abort)(r11)
111        mtctr r12
112        bctr
113.data
114.lazy_symbol_pointer
115L_abort$lazy_ptr:
116        .indirect_symbol _abort
117	.g_long	dyld_stub_binding_helper
118#else
119	bl	_abort
120#endif
121.data
122	.align LOG2_GPR_BYTES
123LTRAMP:
124	.g_long Ltrampoline_initial
125
126