1/*
2Copyright (c) 2013-2014 Andes Technology Corporation.
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7
8    Redistributions of source code must retain the above copyright
9    notice, this list of conditions and the following disclaimer.
10
11    Redistributions in binary form must reproduce the above copyright
12    notice, this list of conditions and the following disclaimer in the
13    documentation and/or other materials provided with the distribution.
14
15    The name of the company may not be used to endorse or promote
16    products derived from this software without specific prior written
17    permission.
18
19THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22DISCLAIMED.  IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY
23DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*/
30
31##==============================================================================
32##
33##	crt0.S
34##
35##	nds32 startup code
36##
37##==============================================================================
38
39#include "syscall_extra.h"
40
41##------------------------------------------------------------------------------
42## Vector table setup
43##------------------------------------------------------------------------------
44	.section	.nds32_init, "ax"
45	j	_start
46
47##------------------------------------------------------------------------------
48## Startup code implementation
49##------------------------------------------------------------------------------
50	.section	.text
51	.weak	_SDA_BASE_
52	.weak	_ITB_BASE_
53	.weak	_arg_init
54	.weak	__pre_c_init
55	.weak	__post_c_init
56	.weak	_call_exit
57	.global	_start
58	.type	_start, @function
59	.align	2
60_start:
61	/* The initialization sequence really does matter !!!
62	   The global pointer must be
63	   initialized precedence over all others.  */
64
65.L_init_gp:
66	/* Initialization for global pointer.  The symbol _SDA_BASE_ is
67	   determined by Linker.  SDA stands for Small Data Access.  */
68	la	$gp, _SDA_BASE_
69
70#if __NDS32_EXT_EX9__
71.L_init_itb:
72	/* Initialization for Instruction Table Base (ITB).
73	   The symbol _ITB_BASE_ is determined by Linker.
74	   Set $ITB only if MSC_CFG.EIT (cr4.b'24) is set.  */
75	mfsr	$r0, $MSC_CFG
76	srli	$r0, $r0, 24
77	andi	$r0, $r0, 0x1
78	beqz	$r0, 1f		/* Fall through ?  */
79	la	$r0, _ITB_BASE_
80	mtusr	$r0, $ITB
811:
82#endif
83
84.L_init_sp:
85	/* Initialization for stack pointer.  The symbol _stack is defined
86	   in linker script.  Make sure $sp is 8-byte aligned.  */
87	la	$sp, _stack
88#if __NDS32_ISA_V3__
89	bitci	$sp, $sp, #7
90#else
91	movi	$r0, #-8		/* Set $r0 as 0xFFFFFFF8.  */
92	and	$sp, $sp, $r0
93#endif
94
95#if __NDS32_EXT_FPU_SP__ || __NDS32_EXT_FPU_DP__
96.L_init_fpu:
97	/* Initialize FPU
98	   Set FUCOP_CTL.CP0EN (fucpr.b'0).  */
99	mfsr	$r0, $FUCOP_CTL
100	ori	$r0, $r0, 0x1
101	mtsr	$r0, $FUCOP_CTL
102	dsb
103	/* According to [bugzilla #9425], set flush-to-zero mode.
104	   That is, set $FPCSR.DNZ(b'12) = 1.  */
105	FMFCSR	$r0
106	ori	$r0, $r0, 0x1000
107	FMTCSR	$r0
108	dsb
109#endif
110
111.L_pre_c_init:
112	! call __pre_c_init if provided
113	! sample __pre_c_init is in BSP
114	la	$r15, __pre_c_init	! load address of __pre_c_init
115	beqz	$r15, .L_zero_out_bss	! check existence of __pre_c_init
116	jral	$r15			! pre-c-runtime initialization
117
118.L_zero_out_bss:
119	/* Zero out the bss section.
120	   Equivalence C code for follow part:
121	   if (_end == _edata) goto .L_post_c_init
122	   unsinged int *ptr = _edata;
123	   while (ptr != _end)
124	     *ptr++ = 0
125	   $r0 = ptr/_edata
126	   $r1 = _end
127	   $r2 = 0
128	 */
129	la	$r0, _edata
130	la	$r1, _end
131	movi	$r2, #0
132	beq	$r0, $r1, .L_post_c_init	/* Branch if no bss.  */
133.Lword_clear:
134	swi.bi	$r2, [$r0], #4
135	bne	$r0, $r1, .Lword_clear
136
137.L_post_c_init:
138	! call __post_c_init if provided
139	! no sample __post_c_init is provided
140	la	$r15, __post_c_init	! load address of __post_c_init
141	beqz	$r15, .L_arg_init	! check existence of __post_c_init
142	jral	$r15			! post-c-runtime initialization
143
144.L_arg_init:
145	! argc/argv initialization if necessary
146	la	$r7, _arg_init		! get address of _arg_init
147	beqz	$r7, .L_clean_reg	! if there isn't _arg_init, go main
148	addi	$sp, $sp, -512		! allocate space for command line
149					! and arguments
150	move	$r6, $sp		! r6 = buffer addr of cmd line
151	move	$r0, $r6		! r0 = buffer addr of cmd line
152	syscall	SYS_getcmdline		! get cmd line
153	move	$r0, $r6		! r0 = buffer addr of cmd line
154	addi	$r1, $r6, 256		! r1 = argv
155	jral	$r7			! init argc/argv
156	addi	$r1, $r6, 256		! r1 = argv
157	b	.L_call_main
158
159.L_clean_reg:
160	/* Prepare argc/argv/env for main function.
161	   Since there is no operating system so far,
162	   we set $r0, $r1, and $r2 to be zero.
163	   Note: $r2 already set to zero in .L_zero_out_bss: code fragment.  */
164	movi	$r0, 0
165	movi	$r1, 0
166	movi	$r2, 0
167
168.L_call_main:
169	/* Call 'main'.  */
170	bal	main
171
172	/* Call _call_exit.  */
173	! call _call_exit if necessary; default implementation is in crtexit.c
174	la	$r15, _call_exit		! load address of _call_exit
175	beqz	$r15, .L_terminate_program	! no _call_exit? go exit
176	jral	$r15				! _call_exit will never return
177
178.L_terminate_program:
179	/* There are two ways to terminate program:
180	    1. User "syscall 0x1" directly.
181	    2. Call exit. The  return value $r0 from main() is
182	      implicitly passed as argument.
183
184	    Currently, we use option 2 as a solution to follow C99 5.1.2.2.3,
185	    but aware that general exit() will do some cleanup procedures
186	    which may result in large-memory-footprints.  */
187	bal	exit
188
189.L_forever_loop:
190	/* Should never return here.  */
191	b	.L_forever_loop
192
193	.size	_start, .-_start
194