2015-10-23 20:24:06 +02:00
|
|
|
/*
|
2016-05-02 17:58:47 +02:00
|
|
|
Copyright (c) 2015-2016, Synopsys, Inc. All rights reserved.
|
2015-10-23 20:24:06 +02:00
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
|
|
|
|
1) Redistributions of source code must retain the above copyright notice,
|
|
|
|
this list of conditions and the following disclaimer.
|
|
|
|
|
|
|
|
2) Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
this list of conditions and the following disclaimer in the documentation
|
|
|
|
and/or other materials provided with the distribution.
|
|
|
|
|
|
|
|
3) Neither the name of the Synopsys, Inc., nor the names of its contributors
|
|
|
|
may be used to endorse or promote products derived from this software
|
|
|
|
without specific prior written permission.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
The startup code for the ARC family of processors does the following before
|
|
|
|
transferring control to user defined main label:
|
|
|
|
1. Set sp to __stack_top (link time variable)
|
|
|
|
2. Set fp to zero
|
|
|
|
3. Zero out the bss section (for uninitialized globals)
|
|
|
|
After returning from main, the processor is halted and the pipeline is
|
|
|
|
flushed out.
|
|
|
|
|
|
|
|
We expect argc in r0 and argv in r1. These are saved in r13 / r14 during
|
|
|
|
the initialization code.
|
|
|
|
*/
|
|
|
|
|
2016-05-02 17:58:47 +02:00
|
|
|
/* Compatibility with older ARC GCC, that doesn't provide some of the
|
|
|
|
preprocessor defines used by newlib and libgloss for ARC. */
|
|
|
|
#if defined (__Xbarrel_shifter) && !defined (__ARC_BARREL_SHIFTER__)
|
|
|
|
#define __ARC_BARREL_SHIFTER__ 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined (__EM__) && !defined (__ARCEM__)
|
|
|
|
#define __ARCEM__ 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined (__HS__) && !defined (__ARCHS__)
|
|
|
|
#define __ARCHS__ 1
|
|
|
|
#endif
|
|
|
|
|
2015-10-23 20:24:06 +02:00
|
|
|
.file "crt0.S"
|
|
|
|
.extern main
|
|
|
|
|
2016-05-02 17:58:47 +02:00
|
|
|
#if defined (__ARCEM__) || defined (__ARCHS__)
|
2015-10-23 20:24:06 +02:00
|
|
|
.section .ivt, "a", @progbits
|
|
|
|
|
arc: Rework default exception handlers for ARC EM and HS
Initially crt0.S used a special function, declared as weak as a default
exception handler in interrupt vector table. To let user override individual
handlers, this function had multiple names - one for each IVT entry, which,
however, was terribly confusing for the debugger and user - because it
wasn't clear which symbol will be used as a function name in debugger.
Defining multiple separate functions - one for each handler, would resolve
the mess, but would increase code size of crt0.o.
To clean this up, this patch defines exception handlers as weak symbols as
well, but those are defined as just symbols, not functions, hence there
would be less confusion over what is what. At the same time, users still can
redefine exception handlers symbol by creating functions with respective
names.
libgloss/
2016-05-24 Anton Kolesov <Anton.Kolesov@synopsys.com>
* arc/crt0.S: Convert memory_error and friends to non-function
symbols.
2016-05-13 17:09:43 +02:00
|
|
|
; Helper macro to define weak symbols to include into interrupt vector table.
|
|
|
|
; User code may define those functions in them, so user function will be
|
|
|
|
; referenced in the IVT. By default all handlers point to _exit_halt - so they
|
|
|
|
; always cause application halt, because if application causes an exception or
|
|
|
|
; interrupt, but doesn't set a handler for it - something is wrong in
|
|
|
|
; application. Exception is "start" entry of IVT, which points to __start
|
|
|
|
; function.
|
|
|
|
#define IVT_ENTRY(name) \
|
|
|
|
.word name `\
|
|
|
|
.weak name `\
|
|
|
|
.set name, _exit_halt
|
|
|
|
|
|
|
|
; handler's name, number, name, offset in IVT (hex/dec)
|
|
|
|
.word __start ; 0 program entry point 0x0 0
|
|
|
|
IVT_ENTRY(memory_error) ; 1 memory_error 0x4 4
|
|
|
|
IVT_ENTRY(instruction_error) ; 2 instruction_error 0x8 8
|
|
|
|
IVT_ENTRY(EV_MachineCheck) ; 3 EV_MachineCheck 0xC 12
|
|
|
|
IVT_ENTRY(EV_TLBMissI) ; 4 EV_TLBMissI 0x10 16
|
|
|
|
IVT_ENTRY(EV_TLBMissD) ; 5 EV_TLBMissD 0x14 20
|
|
|
|
IVT_ENTRY(EV_ProtV) ; 6 EV_ProtV 0x18 24
|
|
|
|
IVT_ENTRY(EV_PrivilegeV) ; 7 EV_PrivilegeV 0x1C 28
|
|
|
|
IVT_ENTRY(EV_SWI) ; 8 EV_SWI 0x20 32
|
|
|
|
IVT_ENTRY(EV_Trap) ; 9 EV_Trap 0x24 36
|
|
|
|
IVT_ENTRY(EV_Extension) ; 10 EV_Extension 0x28 40
|
|
|
|
IVT_ENTRY(EV_DivZero) ; 11 EV_DivZero 0x2C 44
|
|
|
|
IVT_ENTRY(EV_DCError) ; 12 EV_DCError 0x30 48
|
|
|
|
IVT_ENTRY(EV_Maligned) ; 13 EV_Maligned 0x34 52
|
|
|
|
IVT_ENTRY(EV_Ex14) ; 14 unused 0x38 56
|
|
|
|
IVT_ENTRY(EV_Ex15) ; 15 unused 0x3C 60
|
|
|
|
IVT_ENTRY(IRQ_Timer0) ; 16 Timer 0 0x40 64
|
|
|
|
IVT_ENTRY(IRQ_Timer1) ; 17 Timer 1 0x44 68
|
|
|
|
IVT_ENTRY(IRQ_18) ; 18 0x48 72
|
|
|
|
IVT_ENTRY(IRQ_19) ; 19 0x4C 76
|
|
|
|
IVT_ENTRY(IRQ_20) ; 20 0x50 80
|
2015-10-23 20:24:06 +02:00
|
|
|
|
|
|
|
.section .text.__startup, "ax", @progbits
|
|
|
|
#else
|
|
|
|
.text
|
2016-05-02 17:58:47 +02:00
|
|
|
#endif /* __ARCEM__ || __ARCHS__ */
|
2015-10-23 20:24:06 +02:00
|
|
|
|
|
|
|
.global __start
|
|
|
|
.type __start, @function
|
2016-06-28 15:12:16 +02:00
|
|
|
.align 4
|
2015-10-23 20:24:06 +02:00
|
|
|
#ifdef __ARC601__
|
|
|
|
; Startup code for the ARC601 processor
|
|
|
|
__start:
|
|
|
|
mov gp, @__SDATA_BEGIN__
|
|
|
|
mov sp, @__stack_top ; Point to top of stack
|
|
|
|
mov r5, 0 ; Zero value
|
|
|
|
mov_s r2, @__sbss_start ; r2 = start of the bss section
|
|
|
|
sub r3, @_end, r2 ; r3 = size of the bss section in bytes
|
|
|
|
|
|
|
|
asr_s r3, r3
|
|
|
|
asr_s r3, r3 ; r3 = size of bss in words
|
|
|
|
|
|
|
|
.Lbss_loop:
|
|
|
|
cmp r3, 0xff ; Check for max lp_count
|
|
|
|
mov.le lp_count, r3
|
|
|
|
mov.gt lp_count, 0xff
|
|
|
|
lpnz 2f ; Loop to zero bss
|
|
|
|
st.ab r5,[r2, 4] ; Write word of zeros
|
|
|
|
nop
|
|
|
|
2:
|
|
|
|
sub.f r3, r3, 0xff ; Decrement word count
|
|
|
|
jp .Lbss_loop
|
|
|
|
|
|
|
|
#else /* __ARC601__ */
|
|
|
|
|
|
|
|
; Startup code for the ARC600, ARC700 and ARCv2 processors
|
|
|
|
; NOTE: The following restrictions apply on zero overhead loops (other
|
|
|
|
; restrictions are not pertinent to this code)
|
|
|
|
; - loop end should be 4 instruction words away from the lp_count setting
|
|
|
|
; instruction
|
|
|
|
; - loop body should have at least two instruction words
|
|
|
|
__start:
|
2016-05-02 17:58:47 +02:00
|
|
|
#if defined (__ARCHS__)
|
2015-10-23 20:24:06 +02:00
|
|
|
; Allow unaligned accesses.
|
|
|
|
lr r2, [0xA]
|
|
|
|
bset r2, r2, 19
|
|
|
|
flag r2
|
|
|
|
#endif
|
2017-05-23 15:05:49 +02:00
|
|
|
|
|
|
|
#if defined (__ARC_CODE_DENSITY__)
|
|
|
|
;; Initialize jli_base
|
|
|
|
sr @__JLI_TABLE__,[jli_base]
|
|
|
|
#endif
|
2015-10-23 20:24:06 +02:00
|
|
|
mov gp, @__SDATA_BEGIN__
|
|
|
|
mov_s r2, @__sbss_start ; r2 = start of the bss section
|
|
|
|
sub r3, @_end, r2 ; r3 = size of the bss section in bytes
|
|
|
|
; set up the loop counter register to the size (in words) of the bss section
|
2016-05-02 18:04:40 +02:00
|
|
|
#if defined (__ARC_BARREL_SHIFTER__)
|
|
|
|
asr.f lp_count, r3, 2
|
|
|
|
#else
|
|
|
|
asr_s r13, r3
|
|
|
|
asr.f lp_count, r13
|
|
|
|
#endif
|
2015-10-23 20:24:06 +02:00
|
|
|
#if defined (__ARC600__)
|
|
|
|
; loop to zero out the bss. Enter loop only if lp_count != 0
|
|
|
|
lpnz @.Lend_zbss
|
|
|
|
add r3, pcl, 20
|
|
|
|
sr r3, [2] ; LP_END
|
|
|
|
; initialize stack pointer, and this instruction has 2 words
|
|
|
|
mov sp, @__stack_top
|
|
|
|
mov_s r3, 0
|
|
|
|
st.ab r3, [r2, 4] ; zero out the word
|
|
|
|
.Lend_zbss:
|
|
|
|
#else
|
|
|
|
mov sp, @__stack_top ; initialize stack pointer
|
|
|
|
mov_s r3,0
|
|
|
|
; loop to zero out the bss. Enter loop only if lp_count != 0
|
|
|
|
lpnz @.Lend_zbss
|
|
|
|
st.ab r3,[r2, 4] ; zero out the word
|
|
|
|
nop
|
|
|
|
.Lend_zbss:
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* !__ARC601__ */
|
|
|
|
|
|
|
|
; Some targets use the .init and .fini sections to create constructors and
|
|
|
|
; destructors, and for these targets we need to call the _init function and
|
|
|
|
; arrange for _fini to be called at program exit.
|
|
|
|
mov_s r13, r0
|
|
|
|
mov_s r14, r1
|
|
|
|
; calling atexit drags in malloc, so instead poke the function
|
|
|
|
; address directly into the reent structure
|
|
|
|
ld r1, [gp, @_impure_ptr@sda]
|
|
|
|
mov_s r0, @_fini
|
|
|
|
add r1, r1, 0x14c ; &_GLOBAL_REENT->atexit0
|
|
|
|
st r1, [r1, -4] ; _GLOBAL_REENT->atexit
|
|
|
|
st_s r0, [r1, 8] ; _GLOBAL_REENT->atexit0._fns[0]
|
|
|
|
mov_s r0, 1
|
|
|
|
st_s r0, [r1, 4] ; _GLOBAL_REENT->atexit0._ind
|
|
|
|
; branch to _init
|
2017-05-23 15:05:49 +02:00
|
|
|
#if defined (__ARCEM__) || defined (__ARCHS__)
|
2015-10-23 20:24:06 +02:00
|
|
|
jl @_init
|
|
|
|
#else
|
|
|
|
bl @_init
|
2016-05-02 17:58:47 +02:00
|
|
|
#endif /* __ARCEM__ || __ARCHS__ */
|
2017-05-23 15:05:48 +02:00
|
|
|
|
|
|
|
#ifdef PROFILE_SUPPORT /* Defined in gcrt0.S. */
|
|
|
|
mov r0,@__start
|
|
|
|
mov r1,@_etext
|
|
|
|
jl @_monstartup
|
|
|
|
#endif /* PROFILE_SUPPORT */
|
|
|
|
|
2015-10-23 20:24:06 +02:00
|
|
|
mov_s r0, r13
|
|
|
|
mov_s r1, r14
|
|
|
|
; branch to main
|
2016-05-02 17:58:47 +02:00
|
|
|
#if defined (__ARCEM__) || defined (__ARCHS__)
|
2015-10-23 20:24:06 +02:00
|
|
|
mov fp,0 ; initialize frame pointer
|
|
|
|
jl @main
|
|
|
|
#else
|
|
|
|
bl.d @main
|
|
|
|
mov fp, 0 ; initialize frame pointer
|
2016-05-02 17:58:47 +02:00
|
|
|
#endif /* __ARCEM__ || __ARCHS__ */
|
2017-05-23 15:05:48 +02:00
|
|
|
|
|
|
|
#ifdef PROFILE_SUPPORT
|
|
|
|
mov r13, r0 ; Save return code
|
|
|
|
jl @_mcleanup
|
|
|
|
mov r0, r13
|
|
|
|
#endif /* PROFILE_SUPPORT */
|
|
|
|
|
2015-10-23 20:24:06 +02:00
|
|
|
; r0 contains exit code
|
|
|
|
j @exit
|
|
|
|
|
2016-05-13 17:21:08 +02:00
|
|
|
.section .text._exit_halt,"ax",@progbits
|
|
|
|
.global _exit_halt
|
|
|
|
.type _exit_halt, @function
|
2016-06-28 15:12:16 +02:00
|
|
|
.align 4
|
2015-10-23 20:24:06 +02:00
|
|
|
_exit_halt:
|
|
|
|
; r0 contains exit code
|
2016-05-13 17:21:08 +02:00
|
|
|
flag 1
|
|
|
|
#if defined (__ARC600__) || defined (__ARC700__)
|
|
|
|
; ARCompact requires 3 nops after flag 1
|
2015-10-23 20:24:06 +02:00
|
|
|
nop
|
|
|
|
nop
|
|
|
|
nop
|
2016-05-13 17:21:08 +02:00
|
|
|
#endif
|
|
|
|
b @_exit_halt
|
|
|
|
.balign 4
|