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