190075Sobrien/*  Special support for trampolines
290075Sobrien *
3169689Skan *   Copyright (C) 1996, 1997, 2000, 2004, 2005 Free Software Foundation, Inc.
490075Sobrien *   Written By Michael Meissner
590075Sobrien * 
690075Sobrien * This file is free software; you can redistribute it and/or modify it
790075Sobrien * under the terms of the GNU General Public License as published by the
890075Sobrien * Free Software Foundation; either version 2, or (at your option) any
990075Sobrien * later version.
1090075Sobrien * 
1190075Sobrien * In addition to the permissions in the GNU General Public License, the
1290075Sobrien * Free Software Foundation gives you unlimited permission to link the
1390075Sobrien * compiled version of this file with other programs, and to distribute
1490075Sobrien * those programs without any restriction coming from the use of this
1590075Sobrien * file.  (The General Public License restrictions do apply in other
1690075Sobrien * respects; for example, they cover modification of the file, and
1790075Sobrien * distribution when not linked into another program.)
1890075Sobrien * 
1990075Sobrien * This file is distributed in the hope that it will be useful, but
2090075Sobrien * WITHOUT ANY WARRANTY; without even the implied warranty of
2190075Sobrien * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2290075Sobrien * General Public License for more details.
2390075Sobrien * 
2490075Sobrien * You should have received a copy of the GNU General Public License
2590075Sobrien * along with this program; see the file COPYING.  If not, write to
26169689Skan * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
27169689Skan * Boston, MA 02110-1301, USA.
2890075Sobrien * 
2990075Sobrien *  As a special exception, if you link this library with files
3090075Sobrien *  compiled with GCC to produce an executable, this does not cause the
3190075Sobrien *  resulting executable to be covered by the GNU General Public License.
3290075Sobrien *  This exception does not however invalidate any other reasons why the
3390075Sobrien *  executable file might be covered by the GNU General Public License.
3490075Sobrien */ 
3590075Sobrien
36169689Skan#include "darwin-asm.h"
37169689Skan
3890075Sobrien/* Set up trampolines.  */
3990075Sobrien
4090075Sobrien.text
41169689Skan	.align	LOG2_GPR_BYTES
4290075SobrienLtrampoline_initial:
4390075Sobrien	mflr	r0
4490075Sobrien	bl	1f
4590075SobrienLfunc = .-Ltrampoline_initial
46169689Skan	.g_long	0		/* will be replaced with function address */
4790075SobrienLchain = .-Ltrampoline_initial
48169689Skan	.g_long	0		/* will be replaced with static chain */
4990075Sobrien1:	mflr	r11
50169689Skan	lg	r12,0(r11)	/* function address */
5190075Sobrien	mtlr	r0
5290075Sobrien	mtctr	r12
53169689Skan	lg	r11,GPR_BYTES(r11)	/* static chain */
5490075Sobrien	bctr
5590075Sobrien
5690075Sobrientrampoline_size = .-Ltrampoline_initial
5790075Sobrien
5890075Sobrien/* R3 = stack address to store trampoline */
5990075Sobrien/* R4 = length of trampoline area */
6090075Sobrien/* R5 = function address */
6190075Sobrien/* R6 = static chain */
6290075Sobrien
6390075Sobrien	.globl ___trampoline_setup
6490075Sobrien___trampoline_setup:
6590075Sobrien	mflr	r0		/* save return address */
6690075Sobrien        bcl 20,31,LCF0		/* load up __trampoline_initial into r7 */
6790075SobrienLCF0:
6890075Sobrien        mflr	r11
69117395Skan        addis	r7,r11,ha16(LTRAMP-LCF0)
70169689Skan	lg	r7,lo16(LTRAMP-LCF0)(r7)
7190075Sobrien	subi	r7,r7,4
7290075Sobrien	li	r8,trampoline_size	/* verify trampoline big enough */
73169689Skan	cmpg	cr1,r8,r4
74169689Skan	srwi	r4,r4,2			/* # words to move (insns always 4-byte) */
75169689Skan	addi	r9,r3,-4	/* adjust pointer for lgu */
7690075Sobrien	mtctr	r4
7790075Sobrien	blt	cr1,Labort
7890075Sobrien
7990075Sobrien	mtlr	r0
8090075Sobrien
8190075Sobrien	/* Copy the instructions to the stack */
8290075SobrienLmove:
8390075Sobrien	lwzu	r10,4(r7)
8490075Sobrien	stwu	r10,4(r9)
8590075Sobrien	bdnz	Lmove
8690075Sobrien
8790075Sobrien	/* Store correct function and static chain */
88169689Skan	stg	r5,Lfunc(r3)
89169689Skan	stg	r6,Lchain(r3)
9090075Sobrien
9190075Sobrien	/* Now flush both caches */
9290075Sobrien	mtctr	r4
9390075SobrienLcache:
9490075Sobrien	icbi	0,r3
9590075Sobrien	dcbf	0,r3
9690075Sobrien	addi	r3,r3,4
9790075Sobrien	bdnz	Lcache
9890075Sobrien
99169689Skan	/* Ensure cache-flushing has finished.  */
10090075Sobrien	sync
10190075Sobrien	isync
10290075Sobrien
103169689Skan	/* Make stack writeable.  */
104169689Skan	b	___enable_execute_stack
105169689Skan
10690075SobrienLabort:
10790075Sobrien#ifdef __DYNAMIC__
10890075Sobrien	bl	L_abort$stub
10990075Sobrien.data
110169689Skan.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
111169689Skan	.align 2
11290075SobrienL_abort$stub:
11390075Sobrien        .indirect_symbol _abort
11490075Sobrien        mflr r0
11590075Sobrien        bcl 20,31,L0$_abort
11690075SobrienL0$_abort:
11790075Sobrien        mflr r11
11890075Sobrien        addis r11,r11,ha16(L_abort$lazy_ptr-L0$_abort)
11990075Sobrien        mtlr r0
120169689Skan	lgu r12,lo16(L_abort$lazy_ptr-L0$_abort)(r11)
12190075Sobrien        mtctr r12
12290075Sobrien        bctr
12390075Sobrien.data
12490075Sobrien.lazy_symbol_pointer
12590075SobrienL_abort$lazy_ptr:
12690075Sobrien        .indirect_symbol _abort
127169689Skan	.g_long	dyld_stub_binding_helper
12890075Sobrien#else
12990075Sobrien	bl	_abort
13090075Sobrien#endif
13190075Sobrien.data
132169689Skan	.align LOG2_GPR_BYTES
13390075SobrienLTRAMP:
134169689Skan	.g_long Ltrampoline_initial
13590075Sobrien
136