1/*
2   Copyright (c) 2015, 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	.file	"crt0.S"
45	.extern main
46
47#if defined (__EM__) || defined (__HS__)
48	.section .ivt, "a", @progbits
49
50; handler's name,          type,    number,name,   offset in IVT (hex/dec)
51.word   __start           ; exception   0   program entry point  0x0     0
52.word   memory_error      ; exception   1   memory_error         0x4     4
53.word   instruction_error ; exception   2   instruction_error    0x8     8
54.word   EV_MachineCheck   ; exception   3   EV_MachineCheck      0xC     12
55.word   EV_TLBMissI       ; exception   4   EV_TLBMissI          0x10    16
56.word   EV_TLBMissD       ; exception   5   EV_TLBMissD          0x14    20
57.word   EV_ProtV          ; exception   6   EV_ProtV             0x18    24
58.word   EV_PrivilegeV     ; exception   7   EV_PrivilegeV        0x1C    28
59.word   EV_SWI            ; exception   8   EV_SWI               0x20    32
60.word   EV_Trap           ; exception   9   EV_Trap              0x24    36
61.word   EV_Extension      ; exception   10  EV_Extension         0x28    40
62.word   EV_DivZero        ; exception   11  EV_DivZero           0x2C    44
63.word   EV_DCError        ; exception   12  EV_DCError           0x30    48
64.word   EV_Malignedr      ; exception   13  EV_Maligned          0x34    52
65.word   _exit_halt        ; exception   14  unused               0x38    56
66.word   _exit_halt        ; exception   15  unused               0x3C    60
67.word   IRQ_Timer0        ; IRQ         16  Timer 0              0x40    64
68.word   IRQ_Timer1        ; IRQ         17  Timer 1              0x44    68
69.word   IRQ_18            ; IRQ         18                       0x48    72
70.word   IRQ_19            ; IRQ         19                       0x4C    76
71.word   IRQ_20            ; IRQ         20                       0x50    80
72
73
74	.section .text.__startup, "ax", @progbits
75#else
76	.text
77#endif
78
79	.global	__start
80	.type	__start, @function
81
82#ifdef __ARC601__
83; Startup code for the ARC601 processor
84__start:
85	mov	gp, @__SDATA_BEGIN__
86	mov	sp, @__stack_top	; Point to top of stack
87	mov	r5, 0			; Zero value
88	mov_s	r2, @__sbss_start	; r2 = start of the bss section
89	sub	r3, @_end, r2		; r3 = size of the bss section in bytes
90
91	asr_s	r3, r3
92	asr_s	r3, r3			; r3 = size of bss in words
93
94.Lbss_loop:
95	cmp	r3, 0xff		; Check for max lp_count
96	mov.le	lp_count, r3
97	mov.gt	lp_count, 0xff
98	lpnz	2f			; Loop to zero bss
99	st.ab	r5,[r2, 4]		; Write word of zeros
100	nop
1012:
102	sub.f	r3, r3, 0xff		; Decrement word count
103	jp	.Lbss_loop
104
105#else	/* __ARC601__ */
106
107; Startup code for the ARC600, ARC700 and ARCv2 processors
108; NOTE:  The following restrictions apply on zero overhead loops (other
109; restrictions are not pertinent to this code)
110; - loop end should be 4 instruction words away from the lp_count setting
111;   instruction
112; - loop body should have at least two instruction words
113__start:
114#if defined (__HS__)
115	; Allow unaligned accesses.
116	lr	r2, [0xA]
117	bset	r2, r2, 19
118	flag	r2
119#endif
120	mov	gp, @__SDATA_BEGIN__
121	mov_s	r2, @__sbss_start	; r2 = start of the bss section
122	sub	r3, @_end, r2		; r3 = size of the bss section in bytes
123	; set up the loop counter register to the size (in words) of the bss section
124	asr.f	lp_count, r3, 2
125#if defined (__ARC600__)
126	; loop to zero out the bss.  Enter loop only if lp_count != 0
127	lpnz	@.Lend_zbss
128	add	r3, pcl, 20
129	sr	r3, [2]			; LP_END
130	; initialize stack pointer, and this instruction has 2 words
131	mov	sp, @__stack_top
132	mov_s	r3, 0
133	st.ab	r3, [r2, 4]		; zero out the word
134.Lend_zbss:
135#else
136	mov	sp, @__stack_top	; initialize stack pointer
137	mov_s	r3,0
138	; loop to zero out the bss.  Enter loop only if lp_count != 0
139	lpnz	@.Lend_zbss
140	st.ab	r3,[r2, 4]		; zero out the word
141	nop
142.Lend_zbss:
143#endif
144
145#endif /* !__ARC601__ */
146
147; Some  targets use the .init and .fini sections to create constructors and
148; destructors, and for these targets we need to call the _init function and
149; arrange for _fini to be called at program exit.
150	mov_s	r13, r0
151	mov_s	r14, r1
152	; calling atexit drags in malloc, so instead poke the function
153	; address directly into the reent structure
154	ld	r1, [gp, @_impure_ptr@sda]
155	mov_s	r0, @_fini
156	add	r1, r1, 0x14c		; &_GLOBAL_REENT->atexit0
157	st	r1, [r1, -4]		; _GLOBAL_REENT->atexit
158	st_s	r0, [r1, 8]		; _GLOBAL_REENT->atexit0._fns[0]
159	mov_s	r0, 1
160	st_s	r0, [r1, 4]		; _GLOBAL_REENT->atexit0._ind
161; branch to _init
162#if defined (__EM__) || defined (__HS__)
163	jl	@_init
164#else
165	bl	@_init
166#endif
167	mov_s	r0, r13
168	mov_s	r1, r14
169; branch to main
170#if defined (__EM__) || defined (__HS__)
171	mov	fp,0			; initialize frame pointer
172	jl	@main
173#else
174	bl.d	@main
175	mov	fp, 0			; initialize frame pointer
176#endif
177	; r0 contains exit code
178	j	@exit
179
180#if defined (__EM__) || defined (__HS__)
181; ARCv2 default interrupt routines, defined as weak symbols.
182; Default implementation halts the core.  To conserve code size those symbols
183; share a single implementation, however as a downside debugger and
184; disassembler will not be able to distinguish one from another.
185.weak   memory_error
186.weak   instruction_error
187.weak   EV_MachineCheck
188.weak   EV_TLBMissI
189.weak   EV_TLBMissD
190.weak   EV_ProtV
191.weak   EV_PrivilegeV
192.weak   EV_SWI
193.weak   EV_Trap
194.weak   EV_Extension
195.weak   EV_DivZero
196.weak   EV_DCError
197.weak   EV_Malignedr
198.weak   IRQ_Timer0
199.weak   IRQ_Timer1
200.weak   IRQ_18
201.weak   IRQ_19
202.weak   IRQ_20
203
204.balign 4
205memory_error        :
206instruction_error   :
207EV_MachineCheck     :
208EV_TLBMissI         :
209EV_TLBMissD         :
210EV_ProtV            :
211EV_PrivilegeV       :
212EV_SWI              :
213EV_Trap             :
214EV_Extension        :
215EV_DivZero          :
216EV_DCError          :
217EV_Malignedr        :
218IRQ_Timer0          :
219IRQ_Timer1          :
220IRQ_18              :
221IRQ_19              :
222IRQ_20              :
223.Lloop_halt:
224	flag	0x01
225	nop
226	b	.Lloop_halt
227	nop
228#endif
229
230	.section .text._exit_halt,"ax",@progbits
231	.global	 _exit_halt
232	.type	 _exit_halt, @function
233
234_exit_halt:
235	; r0 contains exit code
236	flag	0x01
237	nop
238	nop			; ARCompact requires 3 nops after flag 1
239	nop
240	b	@_exit_halt
241	nop
242