1/* Special support for trampolines 2 * 3 * Copyright (C) 1996-2018 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/* Set up trampolines. */ 27 28 .section ".text" 29#include "ppc-asm.h" 30#include "config.h" 31 32#ifndef __powerpc64__ 33 .type trampoline_initial,@object 34 .align 2 35trampoline_initial: 36 mflr r0 37 bcl 20,31,1f 38.Lfunc = .-trampoline_initial 39 .long 0 /* will be replaced with function address */ 40.Lchain = .-trampoline_initial 41 .long 0 /* will be replaced with static chain */ 421: mflr r11 43 mtlr r0 44 lwz r0,0(r11) /* function address */ 45 lwz r11,4(r11) /* static chain */ 46 mtctr r0 47 bctr 48 49trampoline_size = .-trampoline_initial 50 .size trampoline_initial,trampoline_size 51 52 53/* R3 = stack address to store trampoline */ 54/* R4 = length of trampoline area */ 55/* R5 = function address */ 56/* R6 = static chain */ 57 58FUNC_START(__trampoline_setup) 59 mflr r0 /* save return address */ 60 bcl 20,31,.LCF0 /* load up __trampoline_initial into r7 */ 61.LCF0: 62 mflr r11 63 addi r7,r11,trampoline_initial-4-.LCF0 /* trampoline address -4 */ 64 65 li r8,trampoline_size /* verify that the trampoline is big enough */ 66 cmpw cr1,r8,r4 67 srwi r4,r4,2 /* # words to move */ 68 addi r9,r3,-4 /* adjust pointer for lwzu */ 69 mtctr r4 70 blt cr1,.Labort 71 72 mtlr r0 73 74 /* Copy the instructions to the stack */ 75.Lmove: 76 lwzu r10,4(r7) 77 stwu r10,4(r9) 78 bdnz .Lmove 79 80 /* Store correct function and static chain */ 81 stw r5,.Lfunc(r3) 82 stw r6,.Lchain(r3) 83 84 /* Now flush both caches */ 85 mtctr r4 86.Lcache: 87 icbi 0,r3 88 dcbf 0,r3 89 addi r3,r3,4 90 bdnz .Lcache 91 92 /* Finally synchronize things & return */ 93 sync 94 isync 95 blr 96 97.Labort: 98/* Use a longcall sequence in the non PIC case on VxWorks, to prevent 99 possible relocation errors if this is module-loaded very far away from 100 the 'abort' entry point. */ 101#if defined (__VXWORKS__) && ! (defined __PIC__ || defined __pic__) 102 lis r11,JUMP_TARGET(abort)@ha 103 addic r11,r11,JUMP_TARGET(abort)@l 104 mtlr r11 105 blrl 106#else 107 108#if (defined __PIC__ || defined __pic__) && defined HAVE_AS_REL16 109 bcl 20,31,1f 1101: mflr r30 111 addis r30,r30,_GLOBAL_OFFSET_TABLE_-1b@ha 112 addi r30,r30,_GLOBAL_OFFSET_TABLE_-1b@l 113#endif 114 bl JUMP_TARGET(abort) 115FUNC_END(__trampoline_setup) 116 117#endif 118 119#elif _CALL_ELF == 2 120 .type trampoline_initial,@object 121 .align 3 122trampoline_initial: 123 ld r11,.Lchain(r12) 124 ld r12,.Lfunc(r12) 125 mtctr r12 126 bctr 127.Lfunc = .-trampoline_initial 128 .quad 0 /* will be replaced with function address */ 129.Lchain = .-trampoline_initial 130 .quad 0 /* will be replaced with static chain */ 131 132trampoline_size = .-trampoline_initial 133 .size trampoline_initial,trampoline_size 134 135 136/* R3 = stack address to store trampoline */ 137/* R4 = length of trampoline area */ 138/* R5 = function address */ 139/* R6 = static chain */ 140 141 .pushsection ".toc","aw" 142.LC0: 143 .quad trampoline_initial-8 144 .popsection 145 146FUNC_START(__trampoline_setup) 147 addis 7,2,.LC0@toc@ha 148 ld 7,.LC0@toc@l(7) /* trampoline address -8 */ 149 150 li r8,trampoline_size /* verify that the trampoline is big enough */ 151 cmpw cr1,r8,r4 152 srwi r4,r4,3 /* # doublewords to move */ 153 addi r9,r3,-8 /* adjust pointer for stdu */ 154 mtctr r4 155 blt cr1,.Labort 156 157 /* Copy the instructions to the stack */ 158.Lmove: 159 ldu r10,8(r7) 160 stdu r10,8(r9) 161 bdnz .Lmove 162 163 /* Store correct function and static chain */ 164 std r5,.Lfunc(r3) 165 std r6,.Lchain(r3) 166 167 /* Now flush both caches */ 168 mtctr r4 169.Lcache: 170 icbi 0,r3 171 dcbf 0,r3 172 addi r3,r3,8 173 bdnz .Lcache 174 175 /* Finally synchronize things & return */ 176 sync 177 isync 178 blr 179 180.Labort: 181 bl JUMP_TARGET(abort) 182 nop 183FUNC_END(__trampoline_setup) 184 185#endif 186