1 | /* |
---|
2 | Copyright (c) 2015-2016, Synopsys, Inc. All rights reserved. |
---|
3 | |
---|
4 | Redistribution and use in source and binary forms, with or without |
---|
5 | modification, are permitted provided that the following conditions are met: |
---|
6 | |
---|
7 | 1) Redistributions of source code must retain the above copyright notice, |
---|
8 | this list of conditions and the following disclaimer. |
---|
9 | |
---|
10 | 2) Redistributions in binary form must reproduce the above copyright notice, |
---|
11 | this list of conditions and the following disclaimer in the documentation |
---|
12 | and/or other materials provided with the distribution. |
---|
13 | |
---|
14 | 3) Neither the name of the Synopsys, Inc., nor the names of its contributors |
---|
15 | may be used to endorse or promote products derived from this software |
---|
16 | without specific prior written permission. |
---|
17 | |
---|
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
---|
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
---|
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
---|
21 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
---|
22 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
---|
23 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
---|
24 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
---|
25 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
---|
26 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
---|
27 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
---|
28 | POSSIBILITY OF SUCH DAMAGE. |
---|
29 | */ |
---|
30 | |
---|
31 | /* |
---|
32 | The startup code for the ARC family of processors does the following before |
---|
33 | transferring control to user defined main label: |
---|
34 | 1. Set sp to __stack_top (link time variable) |
---|
35 | 2. Set fp to zero |
---|
36 | 3. Zero out the bss section (for uninitialized globals) |
---|
37 | After returning from main, the processor is halted and the pipeline is |
---|
38 | flushed out. |
---|
39 | |
---|
40 | We expect argc in r0 and argv in r1. These are saved in r13 / r14 during |
---|
41 | the initialization code. |
---|
42 | */ |
---|
43 | |
---|
44 | /* Compatibility with older ARC GCC, that doesn't provide some of the |
---|
45 | preprocessor defines used by newlib and libgloss for ARC. */ |
---|
46 | #if defined (__Xbarrel_shifter) && !defined (__ARC_BARREL_SHIFTER__) |
---|
47 | #define __ARC_BARREL_SHIFTER__ 1 |
---|
48 | #endif |
---|
49 | |
---|
50 | #if defined (__EM__) && !defined (__ARCEM__) |
---|
51 | #define __ARCEM__ 1 |
---|
52 | #endif |
---|
53 | |
---|
54 | #if defined (__HS__) && !defined (__ARCHS__) |
---|
55 | #define __ARCHS__ 1 |
---|
56 | #endif |
---|
57 | |
---|
58 | .file "crt0.S" |
---|
59 | .extern main |
---|
60 | |
---|
61 | #if defined (__ARCEM__) || defined (__ARCHS__) |
---|
62 | .section .ivt, "a", @progbits |
---|
63 | |
---|
64 | ; Helper macro to define weak symbols to include into interrupt vector table. |
---|
65 | ; User code may define those functions in them, so user function will be |
---|
66 | ; referenced in the IVT. By default all handlers point to _exit_halt - so they |
---|
67 | ; always cause application halt, because if application causes an exception or |
---|
68 | ; interrupt, but doesn't set a handler for it - something is wrong in |
---|
69 | ; application. Exception is "start" entry of IVT, which points to __start |
---|
70 | ; function. |
---|
71 | #define IVT_ENTRY(name) \ |
---|
72 | .word name `\ |
---|
73 | .weak name `\ |
---|
74 | .set name, _exit_halt |
---|
75 | |
---|
76 | ; handler's name, number, name, offset in IVT (hex/dec) |
---|
77 | .word __start ; 0 program entry point 0x0 0 |
---|
78 | IVT_ENTRY(memory_error) ; 1 memory_error 0x4 4 |
---|
79 | IVT_ENTRY(instruction_error) ; 2 instruction_error 0x8 8 |
---|
80 | IVT_ENTRY(EV_MachineCheck) ; 3 EV_MachineCheck 0xC 12 |
---|
81 | IVT_ENTRY(EV_TLBMissI) ; 4 EV_TLBMissI 0x10 16 |
---|
82 | IVT_ENTRY(EV_TLBMissD) ; 5 EV_TLBMissD 0x14 20 |
---|
83 | IVT_ENTRY(EV_ProtV) ; 6 EV_ProtV 0x18 24 |
---|
84 | IVT_ENTRY(EV_PrivilegeV) ; 7 EV_PrivilegeV 0x1C 28 |
---|
85 | IVT_ENTRY(EV_SWI) ; 8 EV_SWI 0x20 32 |
---|
86 | IVT_ENTRY(EV_Trap) ; 9 EV_Trap 0x24 36 |
---|
87 | IVT_ENTRY(EV_Extension) ; 10 EV_Extension 0x28 40 |
---|
88 | IVT_ENTRY(EV_DivZero) ; 11 EV_DivZero 0x2C 44 |
---|
89 | IVT_ENTRY(EV_DCError) ; 12 EV_DCError 0x30 48 |
---|
90 | IVT_ENTRY(EV_Maligned) ; 13 EV_Maligned 0x34 52 |
---|
91 | IVT_ENTRY(EV_Ex14) ; 14 unused 0x38 56 |
---|
92 | IVT_ENTRY(EV_Ex15) ; 15 unused 0x3C 60 |
---|
93 | IVT_ENTRY(IRQ_Timer0) ; 16 Timer 0 0x40 64 |
---|
94 | IVT_ENTRY(IRQ_Timer1) ; 17 Timer 1 0x44 68 |
---|
95 | IVT_ENTRY(IRQ_18) ; 18 0x48 72 |
---|
96 | IVT_ENTRY(IRQ_19) ; 19 0x4C 76 |
---|
97 | IVT_ENTRY(IRQ_20) ; 20 0x50 80 |
---|
98 | |
---|
99 | .section .text.__startup, "ax", @progbits |
---|
100 | #else |
---|
101 | .text |
---|
102 | #endif /* __ARCEM__ || __ARCHS__ */ |
---|
103 | |
---|
104 | .global __start |
---|
105 | .type __start, @function |
---|
106 | .align 4 |
---|
107 | #ifdef __ARC601__ |
---|
108 | ; Startup code for the ARC601 processor |
---|
109 | __start: |
---|
110 | mov gp, @__SDATA_BEGIN__ |
---|
111 | mov sp, @__stack_top ; Point to top of stack |
---|
112 | mov r5, 0 ; Zero value |
---|
113 | mov_s r2, @__sbss_start ; r2 = start of the bss section |
---|
114 | sub r3, @_end, r2 ; r3 = size of the bss section in bytes |
---|
115 | |
---|
116 | asr_s r3, r3 |
---|
117 | asr_s r3, r3 ; r3 = size of bss in words |
---|
118 | |
---|
119 | .Lbss_loop: |
---|
120 | cmp r3, 0xff ; Check for max lp_count |
---|
121 | mov.le lp_count, r3 |
---|
122 | mov.gt lp_count, 0xff |
---|
123 | lpnz 2f ; Loop to zero bss |
---|
124 | st.ab r5,[r2, 4] ; Write word of zeros |
---|
125 | nop |
---|
126 | 2: |
---|
127 | sub.f r3, r3, 0xff ; Decrement word count |
---|
128 | jp .Lbss_loop |
---|
129 | |
---|
130 | #else /* __ARC601__ */ |
---|
131 | |
---|
132 | ; Startup code for the ARC600, ARC700 and ARCv2 processors |
---|
133 | ; NOTE: The following restrictions apply on zero overhead loops (other |
---|
134 | ; restrictions are not pertinent to this code) |
---|
135 | ; - loop end should be 4 instruction words away from the lp_count setting |
---|
136 | ; instruction |
---|
137 | ; - loop body should have at least two instruction words |
---|
138 | __start: |
---|
139 | #if defined (__ARCHS__) |
---|
140 | ; Allow unaligned accesses. |
---|
141 | lr r2, [0xA] |
---|
142 | bset r2, r2, 19 |
---|
143 | flag r2 |
---|
144 | #endif |
---|
145 | |
---|
146 | #if defined (__ARC_CODE_DENSITY__) |
---|
147 | ;; Initialize jli_base |
---|
148 | sr @__JLI_TABLE__,[jli_base] |
---|
149 | #endif |
---|
150 | mov gp, @__SDATA_BEGIN__ |
---|
151 | mov_s r2, @__sbss_start ; r2 = start of the bss section |
---|
152 | sub r3, @_end, r2 ; r3 = size of the bss section in bytes |
---|
153 | ; set up the loop counter register to the size (in words) of the bss section |
---|
154 | #if defined (__ARC_BARREL_SHIFTER__) |
---|
155 | asr.f lp_count, r3, 2 |
---|
156 | #else |
---|
157 | asr_s r13, r3 |
---|
158 | asr.f lp_count, r13 |
---|
159 | #endif |
---|
160 | #if defined (__ARC600__) |
---|
161 | ; loop to zero out the bss. Enter loop only if lp_count != 0 |
---|
162 | lpnz @.Lend_zbss |
---|
163 | add r3, pcl, 20 |
---|
164 | sr r3, [2] ; LP_END |
---|
165 | ; initialize stack pointer, and this instruction has 2 words |
---|
166 | mov sp, @__stack_top |
---|
167 | mov_s r3, 0 |
---|
168 | st.ab r3, [r2, 4] ; zero out the word |
---|
169 | .Lend_zbss: |
---|
170 | #else |
---|
171 | mov sp, @__stack_top ; initialize stack pointer |
---|
172 | mov_s r3,0 |
---|
173 | ; loop to zero out the bss. Enter loop only if lp_count != 0 |
---|
174 | lpnz @.Lend_zbss |
---|
175 | st.ab r3,[r2, 4] ; zero out the word |
---|
176 | nop |
---|
177 | .Lend_zbss: |
---|
178 | #endif |
---|
179 | |
---|
180 | #endif /* !__ARC601__ */ |
---|
181 | |
---|
182 | ; Some targets use the .init and .fini sections to create constructors and |
---|
183 | ; destructors, and for these targets we need to call the _init function and |
---|
184 | ; arrange for _fini to be called at program exit. |
---|
185 | mov_s r13, r0 |
---|
186 | mov_s r14, r1 |
---|
187 | ; calling atexit drags in malloc, so instead poke the function |
---|
188 | ; address directly into the reent structure |
---|
189 | ld r1, [gp, @_impure_ptr@sda] |
---|
190 | mov_s r0, @_fini |
---|
191 | add r1, r1, 0x14c ; &_GLOBAL_REENT->atexit0 |
---|
192 | st r1, [r1, -4] ; _GLOBAL_REENT->atexit |
---|
193 | st_s r0, [r1, 8] ; _GLOBAL_REENT->atexit0._fns[0] |
---|
194 | mov_s r0, 1 |
---|
195 | st_s r0, [r1, 4] ; _GLOBAL_REENT->atexit0._ind |
---|
196 | ; branch to _init |
---|
197 | #if defined (__ARCEM__) || defined (__ARCHS__) |
---|
198 | jl @_init |
---|
199 | #else |
---|
200 | bl @_init |
---|
201 | #endif /* __ARCEM__ || __ARCHS__ */ |
---|
202 | |
---|
203 | #ifdef PROFILE_SUPPORT /* Defined in gcrt0.S. */ |
---|
204 | mov r0,@__start |
---|
205 | mov r1,@_etext |
---|
206 | jl @_monstartup |
---|
207 | #endif /* PROFILE_SUPPORT */ |
---|
208 | |
---|
209 | mov_s r0, r13 |
---|
210 | mov_s r1, r14 |
---|
211 | ; branch to main |
---|
212 | #if defined (__ARCEM__) || defined (__ARCHS__) |
---|
213 | mov fp,0 ; initialize frame pointer |
---|
214 | jl @main |
---|
215 | #else |
---|
216 | bl.d @main |
---|
217 | mov fp, 0 ; initialize frame pointer |
---|
218 | #endif /* __ARCEM__ || __ARCHS__ */ |
---|
219 | |
---|
220 | #ifdef PROFILE_SUPPORT |
---|
221 | mov r13, r0 ; Save return code |
---|
222 | jl @_mcleanup |
---|
223 | mov r0, r13 |
---|
224 | #endif /* PROFILE_SUPPORT */ |
---|
225 | |
---|
226 | ; r0 contains exit code |
---|
227 | j @exit |
---|
228 | |
---|
229 | .section .text._exit_halt,"ax",@progbits |
---|
230 | .global _exit_halt |
---|
231 | .type _exit_halt, @function |
---|
232 | .align 4 |
---|
233 | _exit_halt: |
---|
234 | ; r0 contains exit code |
---|
235 | flag 1 |
---|
236 | #if defined (__ARC600__) || defined (__ARC700__) |
---|
237 | ; ARCompact requires 3 nops after flag 1 |
---|
238 | nop |
---|
239 | nop |
---|
240 | nop |
---|
241 | #endif |
---|
242 | b @_exit_halt |
---|
243 | .balign 4 |
---|