1160814Ssimon/* 2160814Ssimon * Special support for eabi and SVR4 3160814Ssimon * 4160814Ssimon * Copyright (C) 1995-2020 Free Software Foundation, Inc. 5160814Ssimon * Written By Michael Meissner 6160814Ssimon * 7160814Ssimon * This file is free software; you can redistribute it and/or modify it 8160814Ssimon * under the terms of the GNU General Public License as published by the 9160814Ssimon * Free Software Foundation; either version 3, or (at your option) any 10296341Sdelphij * later version. 11160814Ssimon * 12160814Ssimon * This file is distributed in the hope that it will be useful, but 13160814Ssimon * WITHOUT ANY WARRANTY; without even the implied warranty of 14160814Ssimon * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15160814Ssimon * General Public License for more details. 16160814Ssimon * 17160814Ssimon * Under Section 7 of GPL version 3, you are granted additional 18160814Ssimon * permissions described in the GCC Runtime Library Exception, version 19160814Ssimon * 3.1, as published by the Free Software Foundation. 20160814Ssimon * 21160814Ssimon * You should have received a copy of the GNU General Public License and 22160814Ssimon * a copy of the GCC Runtime Library Exception along with this program; 23160814Ssimon * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24160814Ssimon * <http://www.gnu.org/licenses/>. 25160814Ssimon */ 26160814Ssimon 27160814Ssimon/* Do any initializations needed for the eabi environment */ 28160814Ssimon 29160814Ssimon .section ".text" 30160814Ssimon #include "ppc-asm.h" 31160814Ssimon 32160814Ssimon#ifndef __powerpc64__ 33160814Ssimon 34160814Ssimon .section ".got2","aw" 35160814Ssimon .align 2 36160814Ssimon.LCTOC1 = . /* +32768 */ 37160814Ssimon 38160814Ssimon/* Table of addresses */ 39160814Ssimon.Ltable = .-.LCTOC1 40160814Ssimon .long .LCTOC1 /* address we are really at */ 41160814Ssimon 42160814Ssimon.Lsda = .-.LCTOC1 43160814Ssimon .long _SDA_BASE_ /* address of the first small data area */ 44160814Ssimon 45160814Ssimon.Lsdas = .-.LCTOC1 46160814Ssimon .long __SDATA_START__ /* start of .sdata/.sbss section */ 47160814Ssimon 48160814Ssimon.Lsdae = .-.LCTOC1 49160814Ssimon .long __SBSS_END__ /* end of .sdata/.sbss section */ 50160814Ssimon 51160814Ssimon.Lsda2 = .-.LCTOC1 52160814Ssimon .long _SDA2_BASE_ /* address of the second small data area */ 53160814Ssimon 54160814Ssimon.Lsda2s = .-.LCTOC1 55160814Ssimon .long __SDATA2_START__ /* start of .sdata2/.sbss2 section */ 56160814Ssimon 57160814Ssimon.Lsda2e = .-.LCTOC1 58160814Ssimon .long __SBSS2_END__ /* end of .sdata2/.sbss2 section */ 59160814Ssimon 60160814Ssimon#ifdef _RELOCATABLE 61160814Ssimon.Lgots = .-.LCTOC1 62160814Ssimon .long __GOT_START__ /* Global offset table start */ 63160814Ssimon 64160814Ssimon.Lgotm1 = .-.LCTOC1 65296341Sdelphij .long _GLOBAL_OFFSET_TABLE_-4 /* end of GOT ptrs before BLCL + 3 reserved words */ 66160814Ssimon 67160814Ssimon.Lgotm2 = .-.LCTOC1 68160814Ssimon .long _GLOBAL_OFFSET_TABLE_+12 /* start of GOT ptrs after BLCL + 3 reserved words */ 69160814Ssimon 70296341Sdelphij.Lgote = .-.LCTOC1 71160814Ssimon .long __GOT_END__ /* Global offset table end */ 72296341Sdelphij 73296341Sdelphij.Lgot2s = .-.LCTOC1 74296341Sdelphij .long __GOT2_START__ /* -mrelocatable GOT pointers start */ 75296341Sdelphij 76296341Sdelphij.Lgot2e = .-.LCTOC1 77160814Ssimon .long __GOT2_END__ /* -mrelocatable GOT pointers end */ 78296341Sdelphij 79160814Ssimon.Lfixups = .-.LCTOC1 80160814Ssimon .long __FIXUP_START__ /* start of .fixup section */ 81160814Ssimon 82160814Ssimon.Lfixupe = .-.LCTOC1 83296341Sdelphij .long __FIXUP_END__ /* end of .fixup section */ 84296341Sdelphij 85160814Ssimon.Lctors = .-.LCTOC1 86160814Ssimon .long __CTOR_LIST__ /* start of .ctor section */ 87296341Sdelphij 88296341Sdelphij.Lctore = .-.LCTOC1 89160814Ssimon .long __CTOR_END__ /* end of .ctor section */ 90296341Sdelphij 91160814Ssimon.Ldtors = .-.LCTOC1 92296341Sdelphij .long __DTOR_LIST__ /* start of .dtor section */ 93160814Ssimon 94296341Sdelphij.Ldtore = .-.LCTOC1 95296341Sdelphij .long __DTOR_END__ /* end of .dtor section */ 96296341Sdelphij 97296341Sdelphij.Lexcepts = .-.LCTOC1 98296341Sdelphij .long __EXCEPT_START__ /* start of .gcc_except_table section */ 99160814Ssimon 100160814Ssimon.Lexcepte = .-.LCTOC1 101296341Sdelphij .long __EXCEPT_END__ /* end of .gcc_except_table section */ 102296341Sdelphij 103296341Sdelphij.Linit = .-.LCTOC1 104296341Sdelphij .long .Linit_p /* address of variable to say we've been called */ 105296341Sdelphij 106296341Sdelphij .text 107296341Sdelphij .align 2 108160814Ssimon.Lptr: 109296341Sdelphij .long .LCTOC1-.Laddr /* PC relative pointer to .got2 */ 110296341Sdelphij#endif 111296341Sdelphij 112296341Sdelphij .data 113296341Sdelphij .align 2 114296341Sdelphij.Linit_p: 115160814Ssimon .long 0 116160814Ssimon 117296341Sdelphij .text 118296341Sdelphij 119160814SsimonFUNC_START(__eabi) 120160814Ssimon 121296341Sdelphij/* Eliminate -mrelocatable code if not -mrelocatable, so that this file can 122160814Ssimon be assembled with other assemblers than GAS. */ 123296341Sdelphij 124296341Sdelphij#ifndef _RELOCATABLE 125160814Ssimon addis 10,0,.Linit_p@ha /* init flag */ 126160814Ssimon addis 11,0,.LCTOC1@ha /* load address of .LCTOC1 */ 127296341Sdelphij lwz 9,.Linit_p@l(10) /* init flag */ 128296341Sdelphij addi 11,11,.LCTOC1@l 129160814Ssimon cmplwi 2,9,0 /* init flag != 0? */ 130160814Ssimon bnelr 2 /* return now, if we've been called already */ 131160814Ssimon stw 1,.Linit_p@l(10) /* store a nonzero value in the done flag */ 132160814Ssimon 133160814Ssimon#else /* -mrelocatable */ 134160814Ssimon mflr 0 135296341Sdelphij bl .Laddr /* get current address */ 136160814Ssimon.Laddr: 137160814Ssimon mflr 12 /* real address of .Laddr */ 138160814Ssimon lwz 11,(.Lptr-.Laddr)(12) /* linker generated address of .LCTOC1 */ 139296341Sdelphij add 11,11,12 /* correct to real pointer */ 140160814Ssimon lwz 12,.Ltable(11) /* get linker's idea of where .Laddr is */ 141160814Ssimon lwz 10,.Linit(11) /* address of init flag */ 142296341Sdelphij subf. 12,12,11 /* calculate difference */ 143296341Sdelphij lwzx 9,10,12 /* done flag */ 144296341Sdelphij cmplwi 2,9,0 /* init flag != 0? */ 145296341Sdelphij mtlr 0 /* restore in case branch was taken */ 146296341Sdelphij bnelr 2 /* return now, if we've been called already */ 147296341Sdelphij stwx 1,10,12 /* store a nonzero value in the done flag */ 148160814Ssimon beq+ 0,.Lsdata /* skip if we don't need to relocate */ 149296341Sdelphij 150296341Sdelphij/* We need to relocate the .got2 pointers. */ 151296341Sdelphij 152296341Sdelphij lwz 3,.Lgot2s(11) /* GOT2 pointers start */ 153296341Sdelphij lwz 4,.Lgot2e(11) /* GOT2 pointers end */ 154296341Sdelphij add 3,12,3 /* adjust pointers */ 155160814Ssimon add 4,12,4 156296341Sdelphij bl FUNC_NAME(__eabi_convert) /* convert pointers in .got2 section */ 157296341Sdelphij 158296341Sdelphij/* Fixup the .ctor section for static constructors */ 159296341Sdelphij 160160814Ssimon lwz 3,.Lctors(11) /* constructors pointers start */ 161296341Sdelphij lwz 4,.Lctore(11) /* constructors pointers end */ 162296341Sdelphij bl FUNC_NAME(__eabi_convert) /* convert constructors */ 163296341Sdelphij 164296341Sdelphij/* Fixup the .dtor section for static destructors */ 165296341Sdelphij 166296341Sdelphij lwz 3,.Ldtors(11) /* destructors pointers start */ 167296341Sdelphij lwz 4,.Ldtore(11) /* destructors pointers end */ 168296341Sdelphij bl FUNC_NAME(__eabi_convert) /* convert destructors */ 169296341Sdelphij 170296341Sdelphij/* Fixup the .gcc_except_table section for G++ exceptions */ 171296341Sdelphij 172160814Ssimon lwz 3,.Lexcepts(11) /* exception table pointers start */ 173296341Sdelphij lwz 4,.Lexcepte(11) /* exception table pointers end */ 174160814Ssimon bl FUNC_NAME(__eabi_convert) /* convert exceptions */ 175160814Ssimon 176160814Ssimon/* Fixup the addresses in the GOT below _GLOBAL_OFFSET_TABLE_-4 */ 177296341Sdelphij 178160814Ssimon lwz 3,.Lgots(11) /* GOT table pointers start */ 179296341Sdelphij lwz 4,.Lgotm1(11) /* GOT table pointers below _GLOBAL_OFFSET_TABLE-4 */ 180296341Sdelphij bl FUNC_NAME(__eabi_convert) /* convert lower GOT */ 181296341Sdelphij 182296341Sdelphij/* Fixup the addresses in the GOT above _GLOBAL_OFFSET_TABLE_+12 */ 183296341Sdelphij 184296341Sdelphij lwz 3,.Lgotm2(11) /* GOT table pointers above _GLOBAL_OFFSET_TABLE+12 */ 185296341Sdelphij lwz 4,.Lgote(11) /* GOT table pointers end */ 186296341Sdelphij bl FUNC_NAME(__eabi_convert) /* convert lower GOT */ 187160814Ssimon 188296341Sdelphij/* Fixup any user initialized pointers now (the compiler drops pointers to */ 189296341Sdelphij/* each of the relocs that it does in the .fixup section). */ 190296341Sdelphij 191296341Sdelphij.Lfix: 192296341Sdelphij lwz 3,.Lfixups(11) /* fixup pointers start */ 193296341Sdelphij lwz 4,.Lfixupe(11) /* fixup pointers end */ 194296341Sdelphij bl FUNC_NAME(__eabi_uconvert) /* convert user initialized pointers */ 195296341Sdelphij 196296341Sdelphij.Lsdata: 197296341Sdelphij mtlr 0 /* restore link register */ 198296341Sdelphij#endif /* _RELOCATABLE */ 199296341Sdelphij 200296341Sdelphij/* Only load up register 13 if there is a .sdata and/or .sbss section */ 201296341Sdelphij lwz 3,.Lsdas(11) /* start of .sdata/.sbss section */ 202296341Sdelphij lwz 4,.Lsdae(11) /* end of .sdata/.sbss section */ 203296341Sdelphij cmpw 1,3,4 /* .sdata/.sbss section non-empty? */ 204296341Sdelphij beq- 1,.Lsda2l /* skip loading r13 */ 205296341Sdelphij 206160814Ssimon lwz 13,.Lsda(11) /* load r13 with _SDA_BASE_ address */ 207296341Sdelphij 208296341Sdelphij/* Only load up register 2 if there is a .sdata2 and/or .sbss2 section */ 209296341Sdelphij 210296341Sdelphij.Lsda2l: 211296341Sdelphij lwz 3,.Lsda2s(11) /* start of .sdata/.sbss section */ 212296341Sdelphij lwz 4,.Lsda2e(11) /* end of .sdata/.sbss section */ 213296341Sdelphij cmpw 1,3,4 /* .sdata/.sbss section non-empty? */ 214296341Sdelphij beq+ 1,.Ldone /* skip loading r2 */ 215296341Sdelphij 216160814Ssimon lwz 2,.Lsda2(11) /* load r2 with _SDA2_BASE_ address */ 217160814Ssimon 218296341Sdelphij/* Done adjusting pointers, return by way of doing the C++ global constructors. */ 219296341Sdelphij 220296341Sdelphij.Ldone: 221160814Ssimon b FUNC_NAME(__init) /* do any C++ global constructors (which returns to caller) */ 222160814SsimonFUNC_END(__eabi) 223296341Sdelphij 224160814Ssimon/* Special subroutine to convert a bunch of pointers directly. 225160814Ssimon r0 has original link register 226296341Sdelphij r3 has low pointer to convert 227160814Ssimon r4 has high pointer to convert 228296341Sdelphij r5 .. r10 are scratch registers 229296341Sdelphij r11 has the address of .LCTOC1 in it. 230296341Sdelphij r12 has the value to add to each pointer 231296341Sdelphij r13 .. r31 are unchanged */ 232296341Sdelphij#ifdef _RELOCATABLE 233296341SdelphijFUNC_START(__eabi_convert) 234296341Sdelphij cmplw 1,3,4 /* any pointers to convert? */ 235296341Sdelphij subf 5,3,4 /* calculate number of words to convert */ 236296341Sdelphij bclr 4,4 /* return if no pointers */ 237296341Sdelphij 238296341Sdelphij srawi 5,5,2 239296341Sdelphij addi 3,3,-4 /* start-4 for use with lwzu */ 240296341Sdelphij mtctr 5 241296341Sdelphij 242296341Sdelphij.Lcvt: 243296341Sdelphij lwzu 6,4(3) /* pointer to convert */ 244296341Sdelphij cmpwi 0,6,0 245296341Sdelphij beq- .Lcvt2 /* if pointer is null, don't convert */ 246296341Sdelphij 247296341Sdelphij add 6,6,12 /* convert pointer */ 248296341Sdelphij stw 6,0(3) 249160814Ssimon.Lcvt2: 250296341Sdelphij bdnz+ .Lcvt 251160814Ssimon blr 252296341Sdelphij 253296341SdelphijFUNC_END(__eabi_convert) 254296341Sdelphij 255296341Sdelphij/* Special subroutine to convert the pointers the user has initialized. The 256296341Sdelphij compiler has placed the address of the initialized pointer into the .fixup 257296341Sdelphij section. 258296341Sdelphij 259296341Sdelphij r0 has original link register 260296341Sdelphij r3 has low pointer to convert 261296341Sdelphij r4 has high pointer to convert 262160814Ssimon r5 .. r10 are scratch registers 263160814Ssimon r11 has the address of .LCTOC1 in it. 264296341Sdelphij r12 has the value to add to each pointer 265296341Sdelphij r13 .. r31 are unchanged */ 266296341Sdelphij 267296341SdelphijFUNC_START(__eabi_uconvert) 268296341Sdelphij cmplw 1,3,4 /* any pointers to convert? */ 269296341Sdelphij subf 5,3,4 /* calculate number of words to convert */ 270296341Sdelphij bclr 4,4 /* return if no pointers */ 271296341Sdelphij 272296341Sdelphij srawi 5,5,2 273160814Ssimon addi 3,3,-4 /* start-4 for use with lwzu */ 274160814Ssimon mtctr 5 275296341Sdelphij 276296341Sdelphij.Lucvt: 277296341Sdelphij lwzu 6,4(3) /* next pointer to pointer to convert */ 278296341Sdelphij add 6,6,12 /* adjust pointer */ 279296341Sdelphij lwz 7,0(6) /* get the pointer it points to */ 280160814Ssimon stw 6,0(3) /* store adjusted pointer */ 281160814Ssimon add 7,7,12 /* adjust */ 282296341Sdelphij stw 7,0(6) 283296341Sdelphij bdnz+ .Lucvt 284296341Sdelphij blr 285296341Sdelphij 286296341SdelphijFUNC_END(__eabi_uconvert) 287160814Ssimon#endif 288296341Sdelphij#endif 289296341Sdelphij