summaryrefslogtreecommitdiff
path: root/ldso/ldso/c6x/dl-startup.h
diff options
context:
space:
mode:
Diffstat (limited to 'ldso/ldso/c6x/dl-startup.h')
-rw-r--r--ldso/ldso/c6x/dl-startup.h72
1 files changed, 69 insertions, 3 deletions
diff --git a/ldso/ldso/c6x/dl-startup.h b/ldso/ldso/c6x/dl-startup.h
index 70a8b89a7..c83e33cb3 100644
--- a/ldso/ldso/c6x/dl-startup.h
+++ b/ldso/ldso/c6x/dl-startup.h
@@ -6,10 +6,9 @@
*
* Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
*/
-
#undef DL_START
#define DL_START(X) \
-int \
+static void * __attribute_used__ \
_dl_start (unsigned placeholder, \
struct elf32_dsbt_loadmap *dl_boot_progmap, \
struct elf32_dsbt_loadmap *dl_boot_ldsomap, \
@@ -34,7 +33,6 @@ _dl_start (unsigned placeholder, \
* B4 --> executable loadmap address
* A6 --> interpreter loadmap address
* B6 --> dynamic section address
- * B14 --> our DP setup by kernel
*
* NB: DSBT index is always 0 for the executable
* and 1 for the interpreter
@@ -44,6 +42,74 @@ __asm__(" .text\n"
".globl _start\n"
".hidden _start\n"
"_start:\n"
+ /* Find interpreter DSBT base in dynamic section */
+ " MV .S2 B6,B2\n"
+ " || ADD .D1X B6,4,A2\n"
+ " LDW .D2T2 *B2++[2],B0\n"
+ " || LDW .D1T1 *A2++[2],A0\n"
+ " MVKL .S2 " __stringify(DT_C6000_DSBT_BASE) ",B7\n"
+ " MVKH .S2 " __stringify(DT_C6000_DSBT_BASE) ",B7\n"
+ " NOP\n"
+ " NOP\n"
+ /*
+ * B0 now holds dynamic tag and A0 holds tag value.
+ * Loop through looking for DSBT base tag
+ */
+ "0:\n"
+ " [B0] CMPEQ .L2 B0,B7,B1\n"
+ " || [!B0] MVK .S2 1,B1\n"
+ " [!B1] BNOP .S1 0b,5\n"
+ " ||[!B1] LDW .D2T2 *B2++[2],B0\n"
+ " ||[!B1] LDW .D1T1 *A2++[2],A0\n"
+ /*
+ * DSBT base in A0 needs to be relocated.
+ * Search through our loadmap to find where it got loaded.
+ *
+ * struct elf32_dsbt_loadmap {
+ * Elf32_Half version;
+ * Elf32_Half nsegs;
+ * struct {
+ * Elf32_Addr addr;
+ * Elf32_Addr p_vaddr;
+ * Elf32_Word p_memsz;
+ * } segments[];
+ * }
+ *
+ */
+ " MV .S1 A6,A1\n"
+ " [!A1] MV .S1X B4,A1\n"
+ " ADD .D1 A1,2,A3\n"
+ " LDHU .D1T2 *A3++[1],B0\n" /* nsegs */
+ " LDW .D1T1 *A3++[1],A10\n" /* addr */
+ " LDW .D1T1 *A3++[1],A11\n" /* p_vaddr */
+ " LDW .D1T1 *A3++[1],A12\n" /* p_memsz */
+ " NOP\n"
+ " NOP\n"
+ /*
+ * Here we have:
+ * B0 -> number of segments to search.
+ * A3 -> pointer to next segment to check
+ * A10 -> segment load address
+ * A11 -> ELF segment virt address
+ * A12 -> ELF segment size
+ */
+ "0:\n"
+ " [!B0] B .S2 0f\n"
+ " SUB .D2 B0,1,B0\n"
+ " CMPLTU .L1 A0,A11,A13\n"
+ " || SUB .S1 A12,1,A12\n"
+ " ADD .D1 A11,A12,A12\n"
+ " CMPGTU .L1 A0,A12,A14\n"
+ " OR .L1 A13,A14,A2\n"
+ " [A2] B .S2 0b\n"
+ " || [!A2] SUB .L1 A0,A11,A0\n"
+ " [B0] LDW .D1T1 *A3++[1],A10\n" /* addr */
+ " || [!A2] ADD .L1 A0,A10,A0\n"
+ " [B0] LDW .D1T1 *A3++[1],A11\n" /* p_vaddr */
+ " [B0] LDW .D1T1 *A3++[1],A12\n" /* p_memsz */
+ " MV .S2X A0,B14\n"
+ " NOP\n"
+ "0:\n"
" B .S2 _dl_start\n"
" STW .D2T2 B14, *+B14[1]\n"
" ADD .D1X B15,8,A8\n"