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