190075Sobrien/* 290075Sobrien * Special support for eabi and SVR4 390075Sobrien * 490075Sobrien * Copyright (C) 1995, 1996, 1998, 2000, 2001 Free Software Foundation, Inc. 590075Sobrien * Written By Michael Meissner 690075Sobrien * 790075Sobrien * This file is free software; you can redistribute it and/or modify it 890075Sobrien * under the terms of the GNU General Public License as published by the 990075Sobrien * Free Software Foundation; either version 2, or (at your option) any 1090075Sobrien * later version. 1190075Sobrien * 1290075Sobrien * In addition to the permissions in the GNU General Public License, the 1390075Sobrien * Free Software Foundation gives you unlimited permission to link the 1490075Sobrien * compiled version of this file with other programs, and to distribute 1590075Sobrien * those programs without any restriction coming from the use of this 1690075Sobrien * file. (The General Public License restrictions do apply in other 1790075Sobrien * respects; for example, they cover modification of the file, and 1890075Sobrien * distribution when not linked into another program.) 1990075Sobrien * 2090075Sobrien * This file is distributed in the hope that it will be useful, but 2190075Sobrien * WITHOUT ANY WARRANTY; without even the implied warranty of 2290075Sobrien * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 2390075Sobrien * General Public License for more details. 2490075Sobrien * 2590075Sobrien * You should have received a copy of the GNU General Public License 2690075Sobrien * along with this program; see the file COPYING. If not, write to 27169689Skan * the Free Software Foundation, 51 Franklin Street, Fifth Floor, 28169689Skan * Boston, MA 02110-1301, USA. 2990075Sobrien * 3090075Sobrien * As a special exception, if you link this library with files 3190075Sobrien * compiled with GCC to produce an executable, this does not cause 3290075Sobrien * the resulting executable to be covered by the GNU General Public License. 3390075Sobrien * This exception does not however invalidate any other reasons why 3490075Sobrien * the executable file might be covered by the GNU General Public License. 3590075Sobrien */ 3690075Sobrien 3790075Sobrien/* Do any initializations needed for the eabi environment */ 3890075Sobrien 3990075Sobrien .file "eabi.asm" 4090075Sobrien .section ".text" 4190075Sobrien #include "ppc-asm.h" 4290075Sobrien 4390075Sobrien#ifndef __powerpc64__ 4490075Sobrien 4590075Sobrien .section ".got2","aw" 4690075Sobrien .align 2 4790075Sobrien.LCTOC1 = . /* +32768 */ 4890075Sobrien 4990075Sobrien/* Table of addresses */ 5090075Sobrien.Ltable = .-.LCTOC1 5190075Sobrien .long .LCTOC1 /* address we are really at */ 5290075Sobrien 5390075Sobrien.Lsda = .-.LCTOC1 5490075Sobrien .long _SDA_BASE_ /* address of the first small data area */ 5590075Sobrien 5690075Sobrien.Lsdas = .-.LCTOC1 5790075Sobrien .long __SDATA_START__ /* start of .sdata/.sbss section */ 5890075Sobrien 5990075Sobrien.Lsdae = .-.LCTOC1 6090075Sobrien .long __SBSS_END__ /* end of .sdata/.sbss section */ 6190075Sobrien 6290075Sobrien.Lsda2 = .-.LCTOC1 6390075Sobrien .long _SDA2_BASE_ /* address of the second small data area */ 6490075Sobrien 6590075Sobrien.Lsda2s = .-.LCTOC1 6690075Sobrien .long __SDATA2_START__ /* start of .sdata2/.sbss2 section */ 6790075Sobrien 6890075Sobrien.Lsda2e = .-.LCTOC1 6990075Sobrien .long __SBSS2_END__ /* end of .sdata2/.sbss2 section */ 7090075Sobrien 7190075Sobrien#ifdef _RELOCATABLE 7290075Sobrien.Lgots = .-.LCTOC1 7390075Sobrien .long __GOT_START__ /* Global offset table start */ 7490075Sobrien 7590075Sobrien.Lgotm1 = .-.LCTOC1 7690075Sobrien .long _GLOBAL_OFFSET_TABLE_-4 /* end of GOT ptrs before BLCL + 3 reserved words */ 7790075Sobrien 7890075Sobrien.Lgotm2 = .-.LCTOC1 7990075Sobrien .long _GLOBAL_OFFSET_TABLE_+12 /* start of GOT ptrs after BLCL + 3 reserved words */ 8090075Sobrien 8190075Sobrien.Lgote = .-.LCTOC1 8290075Sobrien .long __GOT_END__ /* Global offset table end */ 8390075Sobrien 8490075Sobrien.Lgot2s = .-.LCTOC1 8590075Sobrien .long __GOT2_START__ /* -mrelocatable GOT pointers start */ 8690075Sobrien 8790075Sobrien.Lgot2e = .-.LCTOC1 8890075Sobrien .long __GOT2_END__ /* -mrelocatable GOT pointers end */ 8990075Sobrien 9090075Sobrien.Lfixups = .-.LCTOC1 9190075Sobrien .long __FIXUP_START__ /* start of .fixup section */ 9290075Sobrien 9390075Sobrien.Lfixupe = .-.LCTOC1 9490075Sobrien .long __FIXUP_END__ /* end of .fixup section */ 9590075Sobrien 9690075Sobrien.Lctors = .-.LCTOC1 9790075Sobrien .long __CTOR_LIST__ /* start of .ctor section */ 9890075Sobrien 9990075Sobrien.Lctore = .-.LCTOC1 10090075Sobrien .long __CTOR_END__ /* end of .ctor section */ 10190075Sobrien 10290075Sobrien.Ldtors = .-.LCTOC1 10390075Sobrien .long __DTOR_LIST__ /* start of .dtor section */ 10490075Sobrien 10590075Sobrien.Ldtore = .-.LCTOC1 10690075Sobrien .long __DTOR_END__ /* end of .dtor section */ 10790075Sobrien 10890075Sobrien.Lexcepts = .-.LCTOC1 10990075Sobrien .long __EXCEPT_START__ /* start of .gcc_except_table section */ 11090075Sobrien 11190075Sobrien.Lexcepte = .-.LCTOC1 11290075Sobrien .long __EXCEPT_END__ /* end of .gcc_except_table section */ 11390075Sobrien 11490075Sobrien.Linit = .-.LCTOC1 11590075Sobrien .long .Linit_p /* address of variable to say we've been called */ 11690075Sobrien 11790075Sobrien .text 11890075Sobrien .align 2 11990075Sobrien.Lptr: 12090075Sobrien .long .LCTOC1-.Laddr /* PC relative pointer to .got2 */ 12190075Sobrien#endif 12290075Sobrien 12390075Sobrien .data 12490075Sobrien .align 2 12590075Sobrien.Linit_p: 12690075Sobrien .long 0 12790075Sobrien 12890075Sobrien .text 12990075Sobrien 13090075SobrienFUNC_START(__eabi) 13190075Sobrien 13290075Sobrien/* Eliminate -mrelocatable code if not -mrelocatable, so that this file can 13390075Sobrien be assembled with other assemblers than GAS. */ 13490075Sobrien 13590075Sobrien#ifndef _RELOCATABLE 13690075Sobrien addis 10,0,.Linit_p@ha /* init flag */ 13790075Sobrien addis 11,0,.LCTOC1@ha /* load address of .LCTOC1 */ 13890075Sobrien lwz 9,.Linit_p@l(10) /* init flag */ 13990075Sobrien addi 11,11,.LCTOC1@l 14090075Sobrien cmplwi 2,9,0 /* init flag != 0? */ 14190075Sobrien bnelr 2 /* return now, if we've been called already */ 142117395Skan stw 1,.Linit_p@l(10) /* store a nonzero value in the done flag */ 14390075Sobrien 14490075Sobrien#else /* -mrelocatable */ 14590075Sobrien mflr 0 14690075Sobrien bl .Laddr /* get current address */ 14790075Sobrien.Laddr: 14890075Sobrien mflr 12 /* real address of .Laddr */ 14990075Sobrien lwz 11,(.Lptr-.Laddr)(12) /* linker generated address of .LCTOC1 */ 15090075Sobrien add 11,11,12 /* correct to real pointer */ 15190075Sobrien lwz 12,.Ltable(11) /* get linker's idea of where .Laddr is */ 15290075Sobrien lwz 10,.Linit(11) /* address of init flag */ 15390075Sobrien subf. 12,12,11 /* calculate difference */ 15490075Sobrien lwzx 9,10,12 /* done flag */ 15590075Sobrien cmplwi 2,9,0 /* init flag != 0? */ 15690075Sobrien mtlr 0 /* restore in case branch was taken */ 15790075Sobrien bnelr 2 /* return now, if we've been called already */ 158117395Skan stwx 1,10,12 /* store a nonzero value in the done flag */ 15990075Sobrien beq+ 0,.Lsdata /* skip if we don't need to relocate */ 16090075Sobrien 16190075Sobrien/* We need to relocate the .got2 pointers. */ 16290075Sobrien 16390075Sobrien lwz 3,.Lgot2s(11) /* GOT2 pointers start */ 16490075Sobrien lwz 4,.Lgot2e(11) /* GOT2 pointers end */ 16590075Sobrien add 3,12,3 /* adjust pointers */ 16690075Sobrien add 4,12,4 16790075Sobrien bl FUNC_NAME(__eabi_convert) /* convert pointers in .got2 section */ 16890075Sobrien 16990075Sobrien/* Fixup the .ctor section for static constructors */ 17090075Sobrien 17190075Sobrien lwz 3,.Lctors(11) /* constructors pointers start */ 17290075Sobrien lwz 4,.Lctore(11) /* constructors pointers end */ 17390075Sobrien bl FUNC_NAME(__eabi_convert) /* convert constructors */ 17490075Sobrien 17590075Sobrien/* Fixup the .dtor section for static destructors */ 17690075Sobrien 17790075Sobrien lwz 3,.Ldtors(11) /* destructors pointers start */ 17890075Sobrien lwz 4,.Ldtore(11) /* destructors pointers end */ 17990075Sobrien bl FUNC_NAME(__eabi_convert) /* convert destructors */ 18090075Sobrien 18190075Sobrien/* Fixup the .gcc_except_table section for G++ exceptions */ 18290075Sobrien 18390075Sobrien lwz 3,.Lexcepts(11) /* exception table pointers start */ 18490075Sobrien lwz 4,.Lexcepte(11) /* exception table pointers end */ 18590075Sobrien bl FUNC_NAME(__eabi_convert) /* convert exceptions */ 18690075Sobrien 18790075Sobrien/* Fixup the addresses in the GOT below _GLOBAL_OFFSET_TABLE_-4 */ 18890075Sobrien 18990075Sobrien lwz 3,.Lgots(11) /* GOT table pointers start */ 19090075Sobrien lwz 4,.Lgotm1(11) /* GOT table pointers below _GLOBAL_OFFSET_TABLE-4 */ 19190075Sobrien bl FUNC_NAME(__eabi_convert) /* convert lower GOT */ 19290075Sobrien 19390075Sobrien/* Fixup the addresses in the GOT above _GLOBAL_OFFSET_TABLE_+12 */ 19490075Sobrien 19590075Sobrien lwz 3,.Lgotm2(11) /* GOT table pointers above _GLOBAL_OFFSET_TABLE+12 */ 19690075Sobrien lwz 4,.Lgote(11) /* GOT table pointers end */ 19790075Sobrien bl FUNC_NAME(__eabi_convert) /* convert lower GOT */ 19890075Sobrien 19990075Sobrien/* Fixup any user initialized pointers now (the compiler drops pointers to */ 20090075Sobrien/* each of the relocs that it does in the .fixup section). */ 20190075Sobrien 20290075Sobrien.Lfix: 20390075Sobrien lwz 3,.Lfixups(11) /* fixup pointers start */ 20490075Sobrien lwz 4,.Lfixupe(11) /* fixup pointers end */ 20590075Sobrien bl FUNC_NAME(__eabi_uconvert) /* convert user initialized pointers */ 20690075Sobrien 20790075Sobrien.Lsdata: 20890075Sobrien mtlr 0 /* restore link register */ 20990075Sobrien#endif /* _RELOCATABLE */ 21090075Sobrien 21190075Sobrien/* Only load up register 13 if there is a .sdata and/or .sbss section */ 21290075Sobrien lwz 3,.Lsdas(11) /* start of .sdata/.sbss section */ 21390075Sobrien lwz 4,.Lsdae(11) /* end of .sdata/.sbss section */ 21490075Sobrien cmpw 1,3,4 /* .sdata/.sbss section non-empty? */ 21590075Sobrien beq- 1,.Lsda2l /* skip loading r13 */ 21690075Sobrien 21790075Sobrien lwz 13,.Lsda(11) /* load r13 with _SDA_BASE_ address */ 21890075Sobrien 21990075Sobrien/* Only load up register 2 if there is a .sdata2 and/or .sbss2 section */ 22090075Sobrien 22190075Sobrien.Lsda2l: 22290075Sobrien lwz 3,.Lsda2s(11) /* start of .sdata/.sbss section */ 22390075Sobrien lwz 4,.Lsda2e(11) /* end of .sdata/.sbss section */ 22490075Sobrien cmpw 1,3,4 /* .sdata/.sbss section non-empty? */ 22590075Sobrien beq+ 1,.Ldone /* skip loading r2 */ 22690075Sobrien 22790075Sobrien lwz 2,.Lsda2(11) /* load r2 with _SDA2_BASE_ address */ 22890075Sobrien 22990075Sobrien/* Done adjusting pointers, return by way of doing the C++ global constructors. */ 23090075Sobrien 23190075Sobrien.Ldone: 23290075Sobrien b FUNC_NAME(__init) /* do any C++ global constructors (which returns to caller) */ 23390075SobrienFUNC_END(__eabi) 23490075Sobrien 23590075Sobrien/* Special subroutine to convert a bunch of pointers directly. 23690075Sobrien r0 has original link register 23790075Sobrien r3 has low pointer to convert 23890075Sobrien r4 has high pointer to convert 23990075Sobrien r5 .. r10 are scratch registers 24090075Sobrien r11 has the address of .LCTOC1 in it. 24190075Sobrien r12 has the value to add to each pointer 24290075Sobrien r13 .. r31 are unchanged */ 24390075Sobrien 24490075SobrienFUNC_START(__eabi_convert) 24590075Sobrien cmplw 1,3,4 /* any pointers to convert? */ 24690075Sobrien subf 5,3,4 /* calculate number of words to convert */ 24790075Sobrien bclr 4,4 /* return if no pointers */ 24890075Sobrien 24990075Sobrien srawi 5,5,2 25090075Sobrien addi 3,3,-4 /* start-4 for use with lwzu */ 25190075Sobrien mtctr 5 25290075Sobrien 25390075Sobrien.Lcvt: 25490075Sobrien lwzu 6,4(3) /* pointer to convert */ 255146895Skan cmpwi 0,6,0 25690075Sobrien beq- .Lcvt2 /* if pointer is null, don't convert */ 25790075Sobrien 25890075Sobrien add 6,6,12 /* convert pointer */ 25990075Sobrien stw 6,0(3) 26090075Sobrien.Lcvt2: 26190075Sobrien bdnz+ .Lcvt 26290075Sobrien blr 26390075Sobrien 26490075SobrienFUNC_END(__eabi_convert) 26590075Sobrien 26690075Sobrien/* Special subroutine to convert the pointers the user has initialized. The 26790075Sobrien compiler has placed the address of the initialized pointer into the .fixup 26890075Sobrien section. 26990075Sobrien 27090075Sobrien r0 has original link register 27190075Sobrien r3 has low pointer to convert 27290075Sobrien r4 has high pointer to convert 27390075Sobrien r5 .. r10 are scratch registers 27490075Sobrien r11 has the address of .LCTOC1 in it. 27590075Sobrien r12 has the value to add to each pointer 27690075Sobrien r13 .. r31 are unchanged */ 27790075Sobrien 27890075SobrienFUNC_START(__eabi_uconvert) 27990075Sobrien cmplw 1,3,4 /* any pointers to convert? */ 28090075Sobrien subf 5,3,4 /* calculate number of words to convert */ 28190075Sobrien bclr 4,4 /* return if no pointers */ 28290075Sobrien 28390075Sobrien srawi 5,5,2 28490075Sobrien addi 3,3,-4 /* start-4 for use with lwzu */ 28590075Sobrien mtctr 5 28690075Sobrien 28790075Sobrien.Lucvt: 28890075Sobrien lwzu 6,4(3) /* next pointer to pointer to convert */ 28990075Sobrien add 6,6,12 /* adjust pointer */ 29090075Sobrien lwz 7,0(6) /* get the pointer it points to */ 29190075Sobrien stw 6,0(3) /* store adjusted pointer */ 29290075Sobrien add 7,7,12 /* adjust */ 29390075Sobrien stw 7,0(6) 29490075Sobrien bdnz+ .Lucvt 29590075Sobrien blr 29690075Sobrien 29790075SobrienFUNC_END(__eabi_uconvert) 29890075Sobrien 29990075Sobrien#endif 300