| 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 | 
|---|