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