summaryrefslogtreecommitdiff
path: root/ldso
diff options
context:
space:
mode:
Diffstat (limited to 'ldso')
-rw-r--r--ldso/ldso/cris/dl-startup.h35
-rw-r--r--ldso/ldso/cris/dl-sysdep.h24
-rw-r--r--ldso/ldso/cris/resolve.S88
3 files changed, 116 insertions, 31 deletions
diff --git a/ldso/ldso/cris/dl-startup.h b/ldso/ldso/cris/dl-startup.h
index 3274b41a5..417cb5096 100644
--- a/ldso/ldso/cris/dl-startup.h
+++ b/ldso/ldso/cris/dl-startup.h
@@ -4,22 +4,43 @@
/* This code fixes the stack pointer so that the dynamic linker
* can find argc, argv and auxvt (Auxillary Vector Table). */
+#ifdef __arch_v32
+
+asm("" \
+" .text\n" \
+" .globl _start\n" \
+" .type _start,@function\n" \
+"_start:\n" \
+" move.d $sp,$r10\n" \
+" lapc _dl_start,$r9\n" \
+" jsr $r9\n" \
+" nop\n" \
+" moveq 0,$r8\n" \
+" jump $r10\n" \
+" move $r8,$srp\n" \
+" .size _start,.-_start\n" \
+" .previous\n" \
+);
+
+#else
+
asm("" \
" .text\n" \
" .globl _start\n" \
" .type _start,@function\n" \
"_start:\n" \
-" move.d $sp,$r10\n" \
-" move.d $pc,$r9\n" \
-" add.d _dl_start - ., $r9\n" \
-" jsr $r9\n" \
-" moveq 0,$r8\n" \
-" move $r8,$srp\n" \
-" jump $r10\n" \
+" move.d $sp,$r10\n" \
+" move.d $pc,$r9\n" \
+" add.d _dl_start - ., $r9\n" \
+" jsr $r9\n" \
+" moveq 0,$r8\n" \
+" move $r8,$srp\n" \
+" jump $r10\n" \
" .size _start,.-_start\n" \
" .previous\n" \
);
+#endif /* __arch_v32 */
/* 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
diff --git a/ldso/ldso/cris/dl-sysdep.h b/ldso/ldso/cris/dl-sysdep.h
index b58f5e0a3..b5fa89035 100644
--- a/ldso/ldso/cris/dl-sysdep.h
+++ b/ldso/ldso/cris/dl-sysdep.h
@@ -68,8 +68,32 @@ elf_machine_load_address(void)
{
Elf32_Addr gotaddr_diff;
+#ifdef __arch_v32
+ extern char ___CRISv32_dummy[] __asm__ ("_dl_start");
+
+ __asm__ ("addo.w _dl_start:GOT16,$r0,$acr\n\t"
+ "lapc _dl_start,%0\n\t"
+ "sub.d [$acr],%0"
+ /* For v32, we need to force GCC to have R0 loaded with
+ _GLOBAL_OFFSET_TABLE_ at this point, which might not
+ otherwise have happened in the caller. (For v10, it's
+ loaded for non-global variables too, so we don't need
+ anything special there.) We accomplish this by faking the
+ address of a global variable (as seen by GCC) as input to
+ the asm; that address calculation goes through the GOT.
+ Use of this function happens before we've filled in the
+ GOT, so the address itself will not be correctly
+ calculated, therefore we don't use any symbol whose
+ address may be re-used later on. Let's just reuse the
+ _dl_start symbol, faking it as a global by renaming it as
+ another variable through an asm. */
+ : "=r" (gotaddr_diff)
+ : "g" (___CRISv32_dummy)
+ : "acr");
+#else
__asm__ ("sub.d [$r0+_dl_start:GOT16],$r0,%0\n\t"
"add.d _dl_start:GOTOFF,%0" : "=r" (gotaddr_diff));
+#endif
return gotaddr_diff;
}
diff --git a/ldso/ldso/cris/resolve.S b/ldso/ldso/cris/resolve.S
index 9d2f079fe..9ca27b5ef 100644
--- a/ldso/ldso/cris/resolve.S
+++ b/ldso/ldso/cris/resolve.S
@@ -17,33 +17,73 @@
.globl _dl_linux_resolve
.type _dl_linux_resolve,@function
+#ifdef __arch_v32
+
+_dl_linux_resolve:
+ subq 4,$sp
+ move.d $r0,[$sp]
+ subq 4,$sp
+ move.d $r13,[$sp]
+ subq 4,$sp
+ move.d $r12,[$sp]
+ subq 4,$sp
+ move.d $r11,[$sp]
+ subq 4,$sp
+ addoq 5*4,$sp,$acr
+ move.d $r10,[$sp]
+ subq 4,$sp
+ move $mof,$r10
+ move.d $r9,[$sp]
+ subq 4,$sp
+ move.d [$acr],$r11
+ move $srp,[$sp]
+ lapc _GLOBAL_OFFSET_TABLE_,$r0
+ move.d _dl_linux_resolver:PLTG,$r9
+ add.d $r0,$r9
+ jsr $r9
+ nop
+ move.d $r10,$acr
+ move [$sp+],$srp
+ move.d [$sp+],$r9
+ move.d [$sp+],$r10
+ move.d [$sp+],$r11
+ move.d [$sp+],$r12
+ move.d [$sp+],$r13
+ move.d [$sp+],$r0
+ jump $acr
+ addq 4,$sp
+
+#else
+
_dl_linux_resolve:
- push $r13
- push $r12
- push $r11
- push $r10
- push $r9
- push $r0
- push $srp
- move.d [$sp+7*4],$r11
- move $mof,$r10
+ push $r13
+ push $r12
+ push $r11
+ push $r10
+ push $r9
+ push $r0
+ push $srp
+ move.d [$sp+7*4],$r11
+ move $mof,$r10
#ifdef __PIC__
- move.d $pc,$r0
- sub.d .:GOTOFF,$r0
- move.d _dl_linux_resolver:PLTG,$r9
- add.d $r0,$r9
- jsr $r9
+ move.d $pc,$r0
+ sub.d .:GOTOFF,$r0
+ move.d _dl_linux_resolver:PLTG,$r9
+ add.d $r0,$r9
+ jsr $r9
#else
- jsr _dl_linux_resolver
+ jsr _dl_linux_resolver
#endif
- move.d $r10,[$sp+7*4]
- pop $srp
- pop $r0
- pop $r9
- pop $r10
- pop $r11
- pop $r12
- pop $r13
- jump [$sp+]
+ move.d $r10,[$sp+7*4]
+ pop $srp
+ pop $r0
+ pop $r9
+ pop $r10
+ pop $r11
+ pop $r12
+ pop $r13
+ jump [$sp+]
+
+#endif /* __arch_v32 */
.size _dl_linux_resolve, . - _dl_linux_resolve