]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-startup.h
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / ldso / ldso / c6x / dl-startup.h
1 /* Copyright (C) 2010 Texas Instruments Incorporated
2  * Contributed by Mark Salter <msalter@redhat.com>
3  *
4  * Borrowed heavily from frv arch:
5  * Copyright (C) 2003 Red Hat, Inc.
6  * 
7  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
8  */
9
10 #undef DL_START
11 #define DL_START(X)   \
12 int  \
13 _dl_start (unsigned placeholder, \
14            struct elf32_dsbt_loadmap *dl_boot_progmap, \
15            struct elf32_dsbt_loadmap *dl_boot_ldsomap, \
16            Elf32_Dyn *dl_boot_ldso_dyn_pointer,        \
17            X)
18
19 /*
20  * On entry, the kernel has set up the stack thusly:
21  *
22  *      0(sp)                   pad0
23  *      4(sp)                   pad1
24  *      8(sp)                   argc
25  *      12(sp)                  argv[0]
26  *      ...
27  *      (4*(argc+3))(sp)        NULL
28  *      (4*(argc+4))(sp)        envp[0]
29  *      ...
30  *                              NULL
31  *
32  * Register values are unspecified, except:
33  *
34  *      B4  --> executable loadmap address
35  *      A6  --> interpreter loadmap address
36  *      B6  --> dynamic section address
37  *      B14 --> our DP setup by kernel
38  *
39  * NB: DSBT index is always 0 for the executable
40  *     and 1 for the interpreter
41  */
42
43 __asm__("       .text\n"
44         ".globl _start\n"
45         "_start:\n"
46         "          B .S2                _dl_start\n"
47         "          STW .D2T2            B14, *+B14[1]\n"
48         "          ADD .D1X             B15,8,A8\n"
49         "          ADDKPC .S2           ret_from_dl,B3,2\n"
50         "ret_from_dl:\n"
51         "          B .S2X               A4\n"
52         " ||       LDW .D2T2            *+B14[0],B14\n"
53         "          ADDKPC .S2           __dl_fini,B0,0\n"
54         "          MV .S1X              B0,A4\n"
55         "          NOP\n"
56         "          NOP\n"
57         "          NOP\n"
58         "__dl_fini:\n"
59         "          LDW .D2T2            *+B14[1],B14\n"
60         "          NOP          4\n"
61         "          LDW .D2T1            *+B14($GOT(_dl_fini)), A0\n"
62         "          NOP          4\n"
63         "          BNOP .S2X            A0, 5\n");
64
65 __asm__("       .text\n"
66         "__c6x_cache_sync:\n"
67         "          MVK .S2              330,B0\n"
68         "          SWE\n"
69         "          NOP\n"
70         "          BNOP .S2             B3,5\n"
71         "          NOP\n"
72         "          NOP\n"
73         "          NOP\n"
74         "          NOP\n"
75         "\n"
76 );
77
78 /*
79  * Get a pointer to the argv array.  On many platforms this can be just
80  * the address of the first argument, on other platforms we need to
81  * do something a little more subtle here.
82  */
83 #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS) + 1)
84
85 struct elf32_dsbt_loadmap;
86
87 /*
88  * Here is a macro to perform a relocation.  This is only used when
89  * bootstrapping the dynamic loader.  RELP is the relocation that we
90  * are performing, REL is the pointer to the address we are relocating.
91  * SYMBOL is the symbol involved in the relocation, and LOAD is the
92  * load address.
93  */
94 #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
95         switch(ELF32_R_TYPE((RELP)->r_info)){                           \
96         case R_C6000_ABS_L16:                                           \
97             {                                                           \
98                     unsigned int opcode = *(REL);                       \
99                     unsigned int v = (SYMBOL) + (RELP)->r_addend;       \
100                     opcode &= ~0x7fff80;                                \
101                     opcode |= ((v & 0xffff) << 7);                      \
102                     *(REL) = opcode;                                    \
103             }                                                           \
104             break;                                                      \
105         case R_C6000_ABS_H16:                                           \
106             {                                                           \
107                     unsigned int opcode = *(REL);                       \
108                     unsigned int v = (SYMBOL) + (RELP)->r_addend;       \
109                     opcode &= ~0x7fff80;                                \
110                     opcode |= ((v >> 9) & 0x7fff80);                    \
111                     *(REL) = opcode;                                    \
112             }                                                           \
113             break;                                                      \
114         case R_C6000_ABS32:                                             \
115             *(REL) = (SYMBOL) + (RELP)->r_addend;                       \
116             break;                                                      \
117         default:                                                        \
118           _dl_exit(1);                                                  \
119         }
120
121 extern void __c6x_cache_sync(unsigned long start, unsigned long end)
122   attribute_hidden;