1c87b03e5Sespie/* 2c87b03e5Sespie * Special support for eabi and SVR4 3c87b03e5Sespie * 4c87b03e5Sespie * Copyright (C) 1995, 1996, 1998, 2000, 2001 Free Software Foundation, Inc. 5c87b03e5Sespie * Written By Michael Meissner 6c87b03e5Sespie * 7c87b03e5Sespie * This file is free software; you can redistribute it and/or modify it 8c87b03e5Sespie * under the terms of the GNU General Public License as published by the 9c87b03e5Sespie * Free Software Foundation; either version 2, or (at your option) any 10c87b03e5Sespie * later version. 11c87b03e5Sespie * 12c87b03e5Sespie * In addition to the permissions in the GNU General Public License, the 13c87b03e5Sespie * Free Software Foundation gives you unlimited permission to link the 14c87b03e5Sespie * compiled version of this file with other programs, and to distribute 15c87b03e5Sespie * those programs without any restriction coming from the use of this 16c87b03e5Sespie * file. (The General Public License restrictions do apply in other 17c87b03e5Sespie * respects; for example, they cover modification of the file, and 18c87b03e5Sespie * distribution when not linked into another program.) 19c87b03e5Sespie * 20c87b03e5Sespie * This file is distributed in the hope that it will be useful, but 21c87b03e5Sespie * WITHOUT ANY WARRANTY; without even the implied warranty of 22c87b03e5Sespie * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23c87b03e5Sespie * General Public License for more details. 24c87b03e5Sespie * 25c87b03e5Sespie * You should have received a copy of the GNU General Public License 26c87b03e5Sespie * along with this program; see the file COPYING. If not, write to 27c87b03e5Sespie * the Free Software Foundation, 59 Temple Place - Suite 330, 28c87b03e5Sespie * Boston, MA 02111-1307, USA. 29c87b03e5Sespie * 30c87b03e5Sespie * As a special exception, if you link this library with files 31c87b03e5Sespie * compiled with GCC to produce an executable, this does not cause 32c87b03e5Sespie * the resulting executable to be covered by the GNU General Public License. 33c87b03e5Sespie * This exception does not however invalidate any other reasons why 34c87b03e5Sespie * the executable file might be covered by the GNU General Public License. 35c87b03e5Sespie */ 36c87b03e5Sespie 37c87b03e5Sespie/* Do any initializations needed for the eabi environment */ 38c87b03e5Sespie 39c87b03e5Sespie .file "eabi.asm" 40c87b03e5Sespie .section ".text" 41*ddbba0f0Sespie #include "rs6000/ppc-asm.h" 42c87b03e5Sespie 43c87b03e5Sespie#ifndef __powerpc64__ 44c87b03e5Sespie 45c87b03e5Sespie .section ".got2","aw" 46c87b03e5Sespie .align 2 47c87b03e5Sespie.LCTOC1 = . /* +32768 */ 48c87b03e5Sespie 49c87b03e5Sespie/* Table of addresses */ 50c87b03e5Sespie.Ltable = .-.LCTOC1 51c87b03e5Sespie .long .LCTOC1 /* address we are really at */ 52c87b03e5Sespie 53c87b03e5Sespie.Lsda = .-.LCTOC1 54c87b03e5Sespie .long _SDA_BASE_ /* address of the first small data area */ 55c87b03e5Sespie 56c87b03e5Sespie.Lsdas = .-.LCTOC1 57c87b03e5Sespie .long __SDATA_START__ /* start of .sdata/.sbss section */ 58c87b03e5Sespie 59c87b03e5Sespie.Lsdae = .-.LCTOC1 60c87b03e5Sespie .long __SBSS_END__ /* end of .sdata/.sbss section */ 61c87b03e5Sespie 62c87b03e5Sespie.Lsda2 = .-.LCTOC1 63c87b03e5Sespie .long _SDA2_BASE_ /* address of the second small data area */ 64c87b03e5Sespie 65c87b03e5Sespie.Lsda2s = .-.LCTOC1 66c87b03e5Sespie .long __SDATA2_START__ /* start of .sdata2/.sbss2 section */ 67c87b03e5Sespie 68c87b03e5Sespie.Lsda2e = .-.LCTOC1 69c87b03e5Sespie .long __SBSS2_END__ /* end of .sdata2/.sbss2 section */ 70c87b03e5Sespie 71c87b03e5Sespie#ifdef _RELOCATABLE 72c87b03e5Sespie.Lgots = .-.LCTOC1 73c87b03e5Sespie .long __GOT_START__ /* Global offset table start */ 74c87b03e5Sespie 75c87b03e5Sespie.Lgotm1 = .-.LCTOC1 76c87b03e5Sespie .long _GLOBAL_OFFSET_TABLE_-4 /* end of GOT ptrs before BLCL + 3 reserved words */ 77c87b03e5Sespie 78c87b03e5Sespie.Lgotm2 = .-.LCTOC1 79c87b03e5Sespie .long _GLOBAL_OFFSET_TABLE_+12 /* start of GOT ptrs after BLCL + 3 reserved words */ 80c87b03e5Sespie 81c87b03e5Sespie.Lgote = .-.LCTOC1 82c87b03e5Sespie .long __GOT_END__ /* Global offset table end */ 83c87b03e5Sespie 84c87b03e5Sespie.Lgot2s = .-.LCTOC1 85c87b03e5Sespie .long __GOT2_START__ /* -mrelocatable GOT pointers start */ 86c87b03e5Sespie 87c87b03e5Sespie.Lgot2e = .-.LCTOC1 88c87b03e5Sespie .long __GOT2_END__ /* -mrelocatable GOT pointers end */ 89c87b03e5Sespie 90c87b03e5Sespie.Lfixups = .-.LCTOC1 91c87b03e5Sespie .long __FIXUP_START__ /* start of .fixup section */ 92c87b03e5Sespie 93c87b03e5Sespie.Lfixupe = .-.LCTOC1 94c87b03e5Sespie .long __FIXUP_END__ /* end of .fixup section */ 95c87b03e5Sespie 96c87b03e5Sespie.Lctors = .-.LCTOC1 97c87b03e5Sespie .long __CTOR_LIST__ /* start of .ctor section */ 98c87b03e5Sespie 99c87b03e5Sespie.Lctore = .-.LCTOC1 100c87b03e5Sespie .long __CTOR_END__ /* end of .ctor section */ 101c87b03e5Sespie 102c87b03e5Sespie.Ldtors = .-.LCTOC1 103c87b03e5Sespie .long __DTOR_LIST__ /* start of .dtor section */ 104c87b03e5Sespie 105c87b03e5Sespie.Ldtore = .-.LCTOC1 106c87b03e5Sespie .long __DTOR_END__ /* end of .dtor section */ 107c87b03e5Sespie 108c87b03e5Sespie.Lexcepts = .-.LCTOC1 109c87b03e5Sespie .long __EXCEPT_START__ /* start of .gcc_except_table section */ 110c87b03e5Sespie 111c87b03e5Sespie.Lexcepte = .-.LCTOC1 112c87b03e5Sespie .long __EXCEPT_END__ /* end of .gcc_except_table section */ 113c87b03e5Sespie 114c87b03e5Sespie.Linit = .-.LCTOC1 115c87b03e5Sespie .long .Linit_p /* address of variable to say we've been called */ 116c87b03e5Sespie 117c87b03e5Sespie .text 118c87b03e5Sespie .align 2 119c87b03e5Sespie.Lptr: 120c87b03e5Sespie .long .LCTOC1-.Laddr /* PC relative pointer to .got2 */ 121c87b03e5Sespie#endif 122c87b03e5Sespie 123c87b03e5Sespie .data 124c87b03e5Sespie .align 2 125c87b03e5Sespie.Linit_p: 126c87b03e5Sespie .long 0 127c87b03e5Sespie 128c87b03e5Sespie .text 129c87b03e5Sespie 130c87b03e5SespieFUNC_START(__eabi) 131c87b03e5Sespie 132c87b03e5Sespie/* Eliminate -mrelocatable code if not -mrelocatable, so that this file can 133c87b03e5Sespie be assembled with other assemblers than GAS. */ 134c87b03e5Sespie 135c87b03e5Sespie#ifndef _RELOCATABLE 136c87b03e5Sespie addis 10,0,.Linit_p@ha /* init flag */ 137c87b03e5Sespie addis 11,0,.LCTOC1@ha /* load address of .LCTOC1 */ 138c87b03e5Sespie lwz 9,.Linit_p@l(10) /* init flag */ 139c87b03e5Sespie addi 11,11,.LCTOC1@l 140c87b03e5Sespie cmplwi 2,9,0 /* init flag != 0? */ 141c87b03e5Sespie bnelr 2 /* return now, if we've been called already */ 142c87b03e5Sespie stw 1,.Linit_p@l(10) /* store a nonzero value in the done flag */ 143c87b03e5Sespie 144c87b03e5Sespie#else /* -mrelocatable */ 145c87b03e5Sespie mflr 0 146c87b03e5Sespie bl .Laddr /* get current address */ 147c87b03e5Sespie.Laddr: 148c87b03e5Sespie mflr 12 /* real address of .Laddr */ 149c87b03e5Sespie lwz 11,(.Lptr-.Laddr)(12) /* linker generated address of .LCTOC1 */ 150c87b03e5Sespie add 11,11,12 /* correct to real pointer */ 151c87b03e5Sespie lwz 12,.Ltable(11) /* get linker's idea of where .Laddr is */ 152c87b03e5Sespie lwz 10,.Linit(11) /* address of init flag */ 153c87b03e5Sespie subf. 12,12,11 /* calculate difference */ 154c87b03e5Sespie lwzx 9,10,12 /* done flag */ 155c87b03e5Sespie cmplwi 2,9,0 /* init flag != 0? */ 156c87b03e5Sespie mtlr 0 /* restore in case branch was taken */ 157c87b03e5Sespie bnelr 2 /* return now, if we've been called already */ 158c87b03e5Sespie stwx 1,10,12 /* store a nonzero value in the done flag */ 159c87b03e5Sespie beq+ 0,.Lsdata /* skip if we don't need to relocate */ 160c87b03e5Sespie 161c87b03e5Sespie/* We need to relocate the .got2 pointers. */ 162c87b03e5Sespie 163c87b03e5Sespie lwz 3,.Lgot2s(11) /* GOT2 pointers start */ 164c87b03e5Sespie lwz 4,.Lgot2e(11) /* GOT2 pointers end */ 165c87b03e5Sespie add 3,12,3 /* adjust pointers */ 166c87b03e5Sespie add 4,12,4 167c87b03e5Sespie bl FUNC_NAME(__eabi_convert) /* convert pointers in .got2 section */ 168c87b03e5Sespie 169c87b03e5Sespie/* Fixup the .ctor section for static constructors */ 170c87b03e5Sespie 171c87b03e5Sespie lwz 3,.Lctors(11) /* constructors pointers start */ 172c87b03e5Sespie lwz 4,.Lctore(11) /* constructors pointers end */ 173c87b03e5Sespie bl FUNC_NAME(__eabi_convert) /* convert constructors */ 174c87b03e5Sespie 175c87b03e5Sespie/* Fixup the .dtor section for static destructors */ 176c87b03e5Sespie 177c87b03e5Sespie lwz 3,.Ldtors(11) /* destructors pointers start */ 178c87b03e5Sespie lwz 4,.Ldtore(11) /* destructors pointers end */ 179c87b03e5Sespie bl FUNC_NAME(__eabi_convert) /* convert destructors */ 180c87b03e5Sespie 181c87b03e5Sespie/* Fixup the .gcc_except_table section for G++ exceptions */ 182c87b03e5Sespie 183c87b03e5Sespie lwz 3,.Lexcepts(11) /* exception table pointers start */ 184c87b03e5Sespie lwz 4,.Lexcepte(11) /* exception table pointers end */ 185c87b03e5Sespie bl FUNC_NAME(__eabi_convert) /* convert exceptions */ 186c87b03e5Sespie 187c87b03e5Sespie/* Fixup the addresses in the GOT below _GLOBAL_OFFSET_TABLE_-4 */ 188c87b03e5Sespie 189c87b03e5Sespie lwz 3,.Lgots(11) /* GOT table pointers start */ 190c87b03e5Sespie lwz 4,.Lgotm1(11) /* GOT table pointers below _GLOBAL_OFFSET_TABLE-4 */ 191c87b03e5Sespie bl FUNC_NAME(__eabi_convert) /* convert lower GOT */ 192c87b03e5Sespie 193c87b03e5Sespie/* Fixup the addresses in the GOT above _GLOBAL_OFFSET_TABLE_+12 */ 194c87b03e5Sespie 195c87b03e5Sespie lwz 3,.Lgotm2(11) /* GOT table pointers above _GLOBAL_OFFSET_TABLE+12 */ 196c87b03e5Sespie lwz 4,.Lgote(11) /* GOT table pointers end */ 197c87b03e5Sespie bl FUNC_NAME(__eabi_convert) /* convert lower GOT */ 198c87b03e5Sespie 199c87b03e5Sespie/* Fixup any user initialized pointers now (the compiler drops pointers to */ 200c87b03e5Sespie/* each of the relocs that it does in the .fixup section). */ 201c87b03e5Sespie 202c87b03e5Sespie.Lfix: 203c87b03e5Sespie lwz 3,.Lfixups(11) /* fixup pointers start */ 204c87b03e5Sespie lwz 4,.Lfixupe(11) /* fixup pointers end */ 205c87b03e5Sespie bl FUNC_NAME(__eabi_uconvert) /* convert user initialized pointers */ 206c87b03e5Sespie 207c87b03e5Sespie.Lsdata: 208c87b03e5Sespie mtlr 0 /* restore link register */ 209c87b03e5Sespie#endif /* _RELOCATABLE */ 210c87b03e5Sespie 211c87b03e5Sespie/* Only load up register 13 if there is a .sdata and/or .sbss section */ 212c87b03e5Sespie lwz 3,.Lsdas(11) /* start of .sdata/.sbss section */ 213c87b03e5Sespie lwz 4,.Lsdae(11) /* end of .sdata/.sbss section */ 214c87b03e5Sespie cmpw 1,3,4 /* .sdata/.sbss section non-empty? */ 215c87b03e5Sespie beq- 1,.Lsda2l /* skip loading r13 */ 216c87b03e5Sespie 217c87b03e5Sespie lwz 13,.Lsda(11) /* load r13 with _SDA_BASE_ address */ 218c87b03e5Sespie 219c87b03e5Sespie/* Only load up register 2 if there is a .sdata2 and/or .sbss2 section */ 220c87b03e5Sespie 221c87b03e5Sespie.Lsda2l: 222c87b03e5Sespie lwz 3,.Lsda2s(11) /* start of .sdata/.sbss section */ 223c87b03e5Sespie lwz 4,.Lsda2e(11) /* end of .sdata/.sbss section */ 224c87b03e5Sespie cmpw 1,3,4 /* .sdata/.sbss section non-empty? */ 225c87b03e5Sespie beq+ 1,.Ldone /* skip loading r2 */ 226c87b03e5Sespie 227c87b03e5Sespie lwz 2,.Lsda2(11) /* load r2 with _SDA2_BASE_ address */ 228c87b03e5Sespie 229c87b03e5Sespie/* Done adjusting pointers, return by way of doing the C++ global constructors. */ 230c87b03e5Sespie 231c87b03e5Sespie.Ldone: 232c87b03e5Sespie b FUNC_NAME(__init) /* do any C++ global constructors (which returns to caller) */ 233c87b03e5SespieFUNC_END(__eabi) 234c87b03e5Sespie 235c87b03e5Sespie/* Special subroutine to convert a bunch of pointers directly. 236c87b03e5Sespie r0 has original link register 237c87b03e5Sespie r3 has low pointer to convert 238c87b03e5Sespie r4 has high pointer to convert 239c87b03e5Sespie r5 .. r10 are scratch registers 240c87b03e5Sespie r11 has the address of .LCTOC1 in it. 241c87b03e5Sespie r12 has the value to add to each pointer 242c87b03e5Sespie r13 .. r31 are unchanged */ 243c87b03e5Sespie 244c87b03e5SespieFUNC_START(__eabi_convert) 245c87b03e5Sespie cmplw 1,3,4 /* any pointers to convert? */ 246c87b03e5Sespie subf 5,3,4 /* calculate number of words to convert */ 247c87b03e5Sespie bclr 4,4 /* return if no pointers */ 248c87b03e5Sespie 249c87b03e5Sespie srawi 5,5,2 250c87b03e5Sespie addi 3,3,-4 /* start-4 for use with lwzu */ 251c87b03e5Sespie mtctr 5 252c87b03e5Sespie 253c87b03e5Sespie.Lcvt: 254c87b03e5Sespie lwzu 6,4(3) /* pointer to convert */ 255c87b03e5Sespie cmpi 0,6,0 256c87b03e5Sespie beq- .Lcvt2 /* if pointer is null, don't convert */ 257c87b03e5Sespie 258c87b03e5Sespie add 6,6,12 /* convert pointer */ 259c87b03e5Sespie stw 6,0(3) 260c87b03e5Sespie.Lcvt2: 261c87b03e5Sespie bdnz+ .Lcvt 262c87b03e5Sespie blr 263c87b03e5Sespie 264c87b03e5SespieFUNC_END(__eabi_convert) 265c87b03e5Sespie 266c87b03e5Sespie/* Special subroutine to convert the pointers the user has initialized. The 267c87b03e5Sespie compiler has placed the address of the initialized pointer into the .fixup 268c87b03e5Sespie section. 269c87b03e5Sespie 270c87b03e5Sespie r0 has original link register 271c87b03e5Sespie r3 has low pointer to convert 272c87b03e5Sespie r4 has high pointer to convert 273c87b03e5Sespie r5 .. r10 are scratch registers 274c87b03e5Sespie r11 has the address of .LCTOC1 in it. 275c87b03e5Sespie r12 has the value to add to each pointer 276c87b03e5Sespie r13 .. r31 are unchanged */ 277c87b03e5Sespie 278c87b03e5SespieFUNC_START(__eabi_uconvert) 279c87b03e5Sespie cmplw 1,3,4 /* any pointers to convert? */ 280c87b03e5Sespie subf 5,3,4 /* calculate number of words to convert */ 281c87b03e5Sespie bclr 4,4 /* return if no pointers */ 282c87b03e5Sespie 283c87b03e5Sespie srawi 5,5,2 284c87b03e5Sespie addi 3,3,-4 /* start-4 for use with lwzu */ 285c87b03e5Sespie mtctr 5 286c87b03e5Sespie 287c87b03e5Sespie.Lucvt: 288c87b03e5Sespie lwzu 6,4(3) /* next pointer to pointer to convert */ 289c87b03e5Sespie add 6,6,12 /* adjust pointer */ 290c87b03e5Sespie lwz 7,0(6) /* get the pointer it points to */ 291c87b03e5Sespie stw 6,0(3) /* store adjusted pointer */ 292c87b03e5Sespie add 7,7,12 /* adjust */ 293c87b03e5Sespie stw 7,0(6) 294c87b03e5Sespie bdnz+ .Lucvt 295c87b03e5Sespie blr 296c87b03e5Sespie 297c87b03e5SespieFUNC_END(__eabi_uconvert) 298c87b03e5Sespie 299c87b03e5Sespie#endif 300