diff options
author | Waldemar Brodkorb <wbx@openadk.org> | 2016-04-21 01:25:29 +0200 |
---|---|---|
committer | Waldemar Brodkorb <wbx@uclibc-ng.org> | 2016-06-30 03:24:42 +0200 |
commit | ee92c0fe5c1b9d59508273916e2c9a75b68dbc13 (patch) | |
tree | 65a22258b12f84325910fc2ad47e2b02696ef593 /ldso/ldso/nds32/dl-startup.h | |
parent | dd46699e46decb7273f44dc2cbf307f096dc39e8 (diff) |
nds32: add support for new architecture
Add support for Andes Technology NDS32 architecture.
See here http://www.andestech.com/en/index/index.htm for more
informaton. Verification of the port from an older uClibc
port was done on a sponsored AG101p board.
The testsuite only has 5 errors, three are related to
an existing bug in dlclose() with LT.old, also happening
on cris32 and m68k.
Failures to fallocate/posix_fallocate are unresolved.
Thanks to Andes Technology sponsoring the hardware and
being very helpful while doing the uClibc-ng porting.
Signed-off-by: Waldemar Brodkorb <wbx@uclibc-ng.org>
Diffstat (limited to 'ldso/ldso/nds32/dl-startup.h')
-rw-r--r-- | ldso/ldso/nds32/dl-startup.h | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/ldso/ldso/nds32/dl-startup.h b/ldso/ldso/nds32/dl-startup.h new file mode 100644 index 000000000..f700531ca --- /dev/null +++ b/ldso/ldso/nds32/dl-startup.h @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2016 Andes Technology, Inc. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Need bootstrap relocations */ +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP) +# define STACK_PUSH +# define STACK_POP +#else +# define STACK_PUSH "addi $sp, $sp, -24" +# define STACK_POP "addi $sp, $sp, 24" +#endif + + +#ifdef __NDS32_N1213_43U1H__ +__asm__("\ + .text\n\ + .globl _start\n\ + .globl _dl_start\n\ + .globl _dl_start_user\n\ + .type _start,#function\n\ + .type _dl_start,#function\n\ + .type _dl_start_user,#function\n\ + .align 4\n\ + .pic\n\ +1:\n\ + ret\n\ +_start:\n\ + ! we are PIC code, so get global offset table\n\ + jal 1b\n\ + sethi $gp, HI20(_GLOBAL_OFFSET_TABLE_)\n\ + ori $gp, $gp, LO12(_GLOBAL_OFFSET_TABLE_+4)\n\ + add $gp, $lp, $gp\n\ +\n\ + ! at start time, all the args are on the stack\n\ + addi $r0, $sp, 0\n\ + ! adjust stack\n\ + !addi $sp, $sp, -24\n\ + "STACK_PUSH"\n\ + bal _dl_start@PLT\n\ + ! save user entry point in r6\n\ + addi $r6, $r0, 0\n\ + ! adjust sp and reload registers\n\ + !addi $sp, $sp, 24\n\ + "STACK_POP"\n\ +\n\ +_dl_start_user:\n\ +\n\ + ! See if we were run as a command with the executable file\n\ + ! name as an extra leading argument.\n\ + ! skip these arguments\n\ + l.w $r2, _dl_skip_args@GOTOFF ! args to skip\n\ + lwi $r0, [$sp+0] ! original argc\n\ + slli $r1, $r2, 2 ! offset for new sp\n\ + add $sp, $sp, $r1 ! adjust sp to skip args\n\ + sub $r0, $r0, $r2 ! set new argc\n\ + swi $r0, [$sp+0] ! save new argc\n\ +\n\ + ! load address of _dl_fini finalizer function\n\ + la $r5, _dl_fini@GOTOFF\n\ + ! jump to the user_s entry point\n\ + addi $r15, $r6, 0\n\ + jr $r15\n\ + .size _dl_start_user, . - _dl_start_user\n\ + .previous\n\ +"); +#else +__asm__("\ + .text\n\ + .globl _start\n\ + .globl _dl_start\n\ + .globl _dl_start_user\n\ + .type _start,#function\n\ + .type _dl_start,#function\n\ + .type _dl_start_user,#function\n\ + .align 4\n\ + .pic\n\ +_start:\n\ + ! we are PIC code, so get global offset table\n\ + mfusr $r15, $PC \n\ + sethi $gp, HI20(_GLOBAL_OFFSET_TABLE_ + 4)\n\ + ori $gp, $gp, LO12(_GLOBAL_OFFSET_TABLE_ + 8)\n\ + add $gp, $r15, $gp\n\ +\n\ + ! at start time, all the args are on the stack\n\ + addi $r0, $sp, 0\n\ + ! adjust stack\n\ + !addi $sp, $sp, -24\n\ + "STACK_PUSH"\n\ + bal _dl_start@PLT\n\ + ! save user entry point in r6\n\ + addi $r6, $r0, 0\n\ + ! adjust sp and reload registers\n\ + !addi $sp, $sp, 24\n\ + "STACK_POP"\n\ +\n\ +_dl_start_user:\n\ + ! See if we were run as a command with the executable file\n\ + ! name as an extra leading argument.\n\ + ! skip these arguments\n\ + l.w $r2, _dl_skip_args@GOTOFF ! args to skip\n\ + lwi $r0, [$sp+0] ! original argc\n\ + slli $r1, $r2, 2 ! offset for new sp\n\ + add $sp, $sp, $r1 ! adjust sp to skip args\n\ + sub $r0, $r0, $r2 ! set new argc\n\ + swi $r0, [$sp+0] ! save new argc\n\ +\n\ + ! load address of _dl_fini finalizer function\n\ + la $r5, _dl_fini@GOTOFF\n\ + ! jump to the user_s entry point\n\ + jr $r6\n\ + .size _dl_start_user, . - _dl_start_user\n\ + .previous\n\ +"); +#endif + +#define COPY_UNALIGNED_WORD(swp, twp, align) \ + { \ + void *__s = (swp), *__t = (twp); \ + unsigned char *__s1 = __s, *__t1 = __t; \ + unsigned short *__s2 = __s, *__t2 = __t; \ + unsigned long *__s4 = __s, *__t4 = __t; \ + switch ((align)) \ + { \ + case 0: \ + *__t4 = *__s4; \ + break; \ + case 2: \ + *__t2++ = *__s2++; \ + *__t2 = *__s2; \ + break; \ + default: \ + *__t1++ = *__s1++; \ + *__t1++ = *__s1++; \ + *__t1++ = *__s1++; \ + *__t1 = *__s1; \ + break; \ + } \ + } + +/* Get a pointer to the argv array. On many platforms this can be just + * the address if 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) + +/* Handle relocation of the symbols in the dynamic loader. */ +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, + unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab) +{ + Elf32_Addr value; + switch (ELF32_R_TYPE(rpnt->r_info)) { + case R_NDS32_NONE: + break; + case R_NDS32_32: + case R_NDS32_GLOB_DAT: + case R_NDS32_JMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_NDS32_32_RELA: + value = symbol_addr + rpnt->r_addend; + COPY_UNALIGNED_WORD (&value, reloc_addr, (int) reloc_addr & 3); + break; +#undef COPY_UNALIGNED_WORD + case R_NDS32_RELATIVE: + *reloc_addr = load_addr + rpnt->r_addend; + break; + default: + SEND_STDERR("Unsupported relocation type\n"); + _dl_exit(1); + } +} |