diff options
Diffstat (limited to 'ldso/ldso/or1k/dl-startup.h')
-rw-r--r-- | ldso/ldso/or1k/dl-startup.h | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/ldso/ldso/or1k/dl-startup.h b/ldso/ldso/or1k/dl-startup.h new file mode 100644 index 000000000..3c99bcd5c --- /dev/null +++ b/ldso/ldso/or1k/dl-startup.h @@ -0,0 +1,106 @@ +/* Startup code for the OpenRISC 1000 platform, + based on microblaze implementation */ +/* + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +__asm__ ("\ + .text\n\ + .globl _start\n\ + .type _start,@function\n\ + .hidden _start\n\ +_start:\n\ + l.ori r3, r9, 0\n\ + l.ori r3, r1, 0\n\ + l.movhi r11, 0\n\ +1:\n\ + l.addi r3, r3, 4\n\ + l.lwz r12, 0(r3)\n\ + l.sfnei r12, 0\n\ + l.addi r11, r11, 1\n\ + l.bf 1b\n\ + l.nop\n\ + l.ori r3, r11, 0\n\ + l.ori r3, r1, 0\n\ + l.addi r11, r11, -1\n\ + /* store argument counter to stack */\n\ + l.sw 0(r3), r11\n\ + l.addi r1, r1, -24\n\ + l.sw 0(r1), r9\n\ +\n\ + l.jal .LPC0\n\ +#ifndef __OR1K_NODELAY__\n\ + l.nop\n\ +#endif\n\ + /* Load the PIC register */\n\ +.LPC0:\n\ + l.movhi r16, gotpchi(_GLOBAL_OFFSET_TABLE_+(.-.LPC0))\n\ + l.ori r16, r16, gotpclo(_GLOBAL_OFFSET_TABLE_+(.-.LPC0))\n\ + l.add r16, r16, r9\n\ +\n\ + l.jal _dl_start\n\ + l.nop\n\ + /* FALLTHRU */\n\ +\n\ + .globl _dl_start_user\n\ + .type _dl_start_user,@function\n\ +_dl_start_user:\n\ + l.movhi r12, gotoffhi(_dl_skip_args)\n\ + l.ori r12, r12, gotofflo(_dl_skip_args)\n\ + l.add r12, r12, r16\n\ + l.lwz r12, 0(r12)\n\ + l.lwz r3, 24(r1)\n\ +\n\ + l.movhi r9, gotoffhi(_dl_fini)\n\ + l.ori r9, r9, gotofflo(_dl_fini)\n\ + l.add r9, r9, r16\n\ +\n\ + l.addi r9, r9, -8\n\ + l.addi r1, r1, 24\n\ + l.jr r11\n\ + l.nop\n\ + .size _dl_start_user, . - _dl_start_user\n\ + .previous\n\ +"); +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address of the first argument, on other platforms we need to + * do something a little more subtle here. + */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS)+1) + +/* The ld.so library requires relocations */ +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, + unsigned long symbol_addr, unsigned long load_addr, + attribute_unused Elf32_Sym *symtab) +{ + + switch (ELF_R_TYPE(rpnt->r_info)) + { + case R_OR1K_RELATIVE: + + *reloc_addr = load_addr + rpnt->r_addend; + break; + + default: + _dl_exit(1); + break; + + } + +} |