[444] | 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 |
---|