xref: /nrf52832-nimble/rt-thread/libcpu/unicore32/sep6200/start_gcc.S (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero/*
2*10465441SEvalZero * File      : start.S
3*10465441SEvalZero * This file is part of RT-Thread RTOS
4*10465441SEvalZero * COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team
5*10465441SEvalZero *
6*10465441SEvalZero *  This program is free software; you can redistribute it and/or modify
7*10465441SEvalZero *  it under the terms of the GNU General Public License as published by
8*10465441SEvalZero *  the Free Software Foundation; either version 2 of the License, or
9*10465441SEvalZero *  (at your option) any later version.
10*10465441SEvalZero *
11*10465441SEvalZero *  This program is distributed in the hope that it will be useful,
12*10465441SEvalZero *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13*10465441SEvalZero *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*10465441SEvalZero *  GNU General Public License for more details.
15*10465441SEvalZero *
16*10465441SEvalZero *  You should have received a copy of the GNU General Public License along
17*10465441SEvalZero *  with this program; if not, write to the Free Software Foundation, Inc.,
18*10465441SEvalZero *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*10465441SEvalZero *
20*10465441SEvalZero * Change Logs:
21*10465441SEvalZero * Date           Author       Notes
22*10465441SEvalZero * 2013-07-13     Peng Fan     First implementation
23*10465441SEvalZero */
24*10465441SEvalZero
25*10465441SEvalZero
26*10465441SEvalZero#define CONFIG_STACKSIZE 	1024
27*10465441SEvalZero#define S_FRAME_SIZE 		132
28*10465441SEvalZero
29*10465441SEvalZero#define S_OLD_R0 			132
30*10465441SEvalZero#define S_PSR  				128
31*10465441SEvalZero#define S_PC  				124
32*10465441SEvalZero#define S_LR  				120
33*10465441SEvalZero#define S_SP  				116
34*10465441SEvalZero
35*10465441SEvalZero#define S_IP  				112
36*10465441SEvalZero#define S_FP  				108
37*10465441SEvalZero#define S_R26  				104
38*10465441SEvalZero#define S_R25  				100
39*10465441SEvalZero#define S_R24  				96
40*10465441SEvalZero#define S_R23  				92
41*10465441SEvalZero#define S_R22  				88
42*10465441SEvalZero#define S_R21  				84
43*10465441SEvalZero#define S_R20 				80
44*10465441SEvalZero#define S_R19  				76
45*10465441SEvalZero#define S_R18  				72
46*10465441SEvalZero#define S_R17  				68
47*10465441SEvalZero#define S_R16  				64
48*10465441SEvalZero#define S_R15  				60
49*10465441SEvalZero#define S_R14  				56
50*10465441SEvalZero#define S_R13  				52
51*10465441SEvalZero#define S_R12  				48
52*10465441SEvalZero#define S_R11  				44
53*10465441SEvalZero#define S_R10  				40
54*10465441SEvalZero#define S_R9  				36
55*10465441SEvalZero#define S_R8  				32
56*10465441SEvalZero#define S_R7  				28
57*10465441SEvalZero#define S_R6  				24
58*10465441SEvalZero#define S_R5  				20
59*10465441SEvalZero#define S_R4  				16
60*10465441SEvalZero#define S_R3  				12
61*10465441SEvalZero#define S_R2  				8
62*10465441SEvalZero#define S_R1  				4
63*10465441SEvalZero#define S_R0 				0
64*10465441SEvalZero
65*10465441SEvalZero.equ 	USERMODE,			0x10
66*10465441SEvalZero.equ 	REALMODE,			0x11
67*10465441SEvalZero.equ 	IRQMODE,			0x12
68*10465441SEvalZero.equ 	PRIVMODE,			0x13
69*10465441SEvalZero.equ 	TRAPMODE,			0x17
70*10465441SEvalZero.equ 	EXTNMODE,			0x1b
71*10465441SEvalZero.equ 	MODEMASK,			0x1f
72*10465441SEvalZero.equ 	NOINT,				0xc0
73*10465441SEvalZero
74*10465441SEvalZero/*
75*10465441SEvalZero *************************************************************************
76*10465441SEvalZero *
77*10465441SEvalZero * Jump vector table
78*10465441SEvalZero *
79*10465441SEvalZero *************************************************************************
80*10465441SEvalZero */
81*10465441SEvalZero
82*10465441SEvalZero.section .init, "ax"
83*10465441SEvalZero.code 32
84*10465441SEvalZero.globl _start
85*10465441SEvalZero_start:
86*10465441SEvalZero     b   reset
87*10465441SEvalZero     ldw pc, _extend_handle
88*10465441SEvalZero     ldw pc, _swi_handle
89*10465441SEvalZero     ldw pc, _iabort_handle
90*10465441SEvalZero     ldw pc, _dabort_handle
91*10465441SEvalZero     ldw pc, _reserve_handle
92*10465441SEvalZero     ldw pc, _IRQ_handle
93*10465441SEvalZero     ldw pc, _FIQ_handle
94*10465441SEvalZero
95*10465441SEvalZero_extend_handle:     .word extend_handle
96*10465441SEvalZero_swi_handle:        .word swi_handle
97*10465441SEvalZero_iabort_handle:     .word iabort_handle
98*10465441SEvalZero_dabort_handle:     .word dabort_handle
99*10465441SEvalZero_reserve_handle:    .word reserve_handle
100*10465441SEvalZero_IRQ_handle:        .word IRQ_handle
101*10465441SEvalZero_FIQ_handle:        .word FIQ_handle
102*10465441SEvalZero    .balignl 16,0xdeadbeef
103*10465441SEvalZero
104*10465441SEvalZero/*
105*10465441SEvalZero *************************************************************************
106*10465441SEvalZero *
107*10465441SEvalZero * Startup Code (reset vector)
108*10465441SEvalZero * relocate armboot to ram
109*10465441SEvalZero * setup stack
110*10465441SEvalZero * jump to second stage
111*10465441SEvalZero *
112*10465441SEvalZero *************************************************************************
113*10465441SEvalZero */
114*10465441SEvalZero.global _TEXT_BASE
115*10465441SEvalZero_TEXT_BASE:
116*10465441SEvalZero     .word   TEXT_BASE
117*10465441SEvalZero
118*10465441SEvalZero.globl _rtthread_start
119*10465441SEvalZero_rtthread_start:
120*10465441SEvalZero     .word   _start
121*10465441SEvalZero
122*10465441SEvalZero.globl _rtthread_end
123*10465441SEvalZero_rtthread_end:
124*10465441SEvalZero     .word   _end
125*10465441SEvalZero
126*10465441SEvalZero.globl _bss_start
127*10465441SEvalZero_bss_start:
128*10465441SEvalZero     .word   __bss_start     @ load end address
129*10465441SEvalZero
130*10465441SEvalZero.globl _bss_end
131*10465441SEvalZero_bss_end:
132*10465441SEvalZero    .word   __bss_end
133*10465441SEvalZero
134*10465441SEvalZero.globl IRQ_STACK_START
135*10465441SEvalZeroIRQ_STACK_START:
136*10465441SEvalZero    .word   _irq_stack_start + 1024
137*10465441SEvalZero
138*10465441SEvalZero.globl FIQ_STACK_START
139*10465441SEvalZeroFIQ_STACK_START:
140*10465441SEvalZero     .word   _fiq_stack_start +1024
141*10465441SEvalZero
142*10465441SEvalZero.globl UNDEFINED_STACK_START
143*10465441SEvalZeroUNDEFINED_STACK_START:
144*10465441SEvalZero	.word _undefined_stack_start + CONFIG_STACKSIZE
145*10465441SEvalZero
146*10465441SEvalZero.globl ABORT_STACK_START
147*10465441SEvalZeroABORT_STACK_START:
148*10465441SEvalZero	.word _abort_stack_start + CONFIG_STACKSIZE
149*10465441SEvalZero
150*10465441SEvalZero.globl _STACK_START
151*10465441SEvalZero_STACK_START:
152*10465441SEvalZero	.word _priv_stack_start + 4096
153*10465441SEvalZero
154*10465441SEvalZero.equ  SEP6200_VIC_BASE,		 0xb0000000
155*10465441SEvalZero.equ  SEP6200_SYSCTL_BASE,	 0xb0008000
156*10465441SEvalZero/* ----------------------------------entry------------------------------*/
157*10465441SEvalZeroreset:
158*10465441SEvalZero	/* set the cpu to PRIV mode and disable cpu interrupt */
159*10465441SEvalZero	mov		r0, asr
160*10465441SEvalZero	andn		r0, r0, #0xff
161*10465441SEvalZero	or		r0, r0, #PRIVMODE|NOINT
162*10465441SEvalZero	mov.a		asr, r0
163*10465441SEvalZero
164*10465441SEvalZero	/* mask all IRQs by clearing all bits in the INTMRs */
165*10465441SEvalZero	ldw	r1, =SEP6200_VIC_BASE
166*10465441SEvalZero	ldw 	r0, =0xffffffff
167*10465441SEvalZero	stw	r0, [r1+], #0x20 /*interrupt enable clear*/
168*10465441SEvalZero	stw	r0, [r1+], #0x24
169*10465441SEvalZero
170*10465441SEvalZero
171*10465441SEvalZero	/*remap ddr to 0x00000000 address*/
172*10465441SEvalZero	ldw	r1, =SEP6200_SYSCTL_BASE
173*10465441SEvalZero	ldw	r0, [r1+]
174*10465441SEvalZero	ldw	r2, =0x80000000
175*10465441SEvalZero	or	r0, r0, r2
176*10465441SEvalZero	stw	r2, [r1+]
177*10465441SEvalZero
178*10465441SEvalZero	/* set interrupt vector */
179*10465441SEvalZero	/*do nothing here for vector*/
180*10465441SEvalZero
181*10465441SEvalZero	/* setup stack */
182*10465441SEvalZero	b.l		stack_setup
183*10465441SEvalZero
184*10465441SEvalZero  /* copy the vector code to address 0 */
185*10465441SEvalZero	ldw	r12, =0x100
186*10465441SEvalZero	ldw	r0, = 0x40000000
187*10465441SEvalZero	ldw	r1, = 0x00000000
188*10465441SEvalZerocopy_vetor:
189*10465441SEvalZero	ldw	r2, [r0]
190*10465441SEvalZero	stw	r2, [r1]
191*10465441SEvalZero	add	r0, r0, #4
192*10465441SEvalZero	add	r1, r1, #4
193*10465441SEvalZero	sub	r12, r12, #4
194*10465441SEvalZero	cmpsub.a	r12, #0
195*10465441SEvalZero	bne	copy_vetor
196*10465441SEvalZero
197*10465441SEvalZero	/* clear .bss */
198*10465441SEvalZero	ldw   	r0, _bss_start         /* bss start   */
199*10465441SEvalZero	ldw   	r1, _bss_end           /* bss end     */
200*10465441SEvalZero	mov   	r2,#0                  /* get a zero  */
201*10465441SEvalZero
202*10465441SEvalZero
203*10465441SEvalZerobss_loop:
204*10465441SEvalZero	stw r2, [r0]            @ clear loop...
205*10465441SEvalZero	add r0, r0, #4
206*10465441SEvalZero	cmpsub.a    r0, r1
207*10465441SEvalZero	bel bss_loop
208*10465441SEvalZero
209*10465441SEvalZero	/* call C++ constructors of global objects 							*/
210*10465441SEvalZero	ldw	r0, =__ctors_start__
211*10465441SEvalZero	ldw	r1, =__ctors_end__
212*10465441SEvalZero
213*10465441SEvalZeroctor_loop:
214*10465441SEvalZero	cmpsub.a	r0, r1
215*10465441SEvalZero	beq	ctor_end
216*10465441SEvalZero	ldw.w	r2, [r0]+, #4
217*10465441SEvalZero	stm.w	(r0, r1), [sp-]
218*10465441SEvalZero	add	lr, pc, #4
219*10465441SEvalZero	mov	pc, r2
220*10465441SEvalZero	ldm.w	(r0, r1), [sp]+
221*10465441SEvalZero	b ctor_loop
222*10465441SEvalZeroctor_end:
223*10465441SEvalZero
224*10465441SEvalZero  /*enable interrupt*/
225*10465441SEvalZero	mov 	r0, asr
226*10465441SEvalZero	andn 	r1, r0, #NOINT
227*10465441SEvalZero	mov.a 	asr, r1
228*10465441SEvalZero
229*10465441SEvalZero	/* start RT-Thread Kernel */
230*10465441SEvalZero	ldw		pc, _rtthread_startup
231*10465441SEvalZero
232*10465441SEvalZero_rtthread_startup:
233*10465441SEvalZero	.word rtthread_startup
234*10465441SEvalZero
235*10465441SEvalZero/*
236*10465441SEvalZero *************************************************************************
237*10465441SEvalZero *
238*10465441SEvalZero * Interrupt handling
239*10465441SEvalZero *
240*10465441SEvalZero *************************************************************************
241*10465441SEvalZero */
242*10465441SEvalZero
243*10465441SEvalZero/* exception handlers */
244*10465441SEvalZero/*Just simple implementation here */
245*10465441SEvalZero	.align  5
246*10465441SEvalZeroextend_handle:
247*10465441SEvalZero    b rt_hw_trap_extn
248*10465441SEvalZeroswi_handle:
249*10465441SEvalZero    b rt_hw_trap_swi
250*10465441SEvalZeroiabort_handle:
251*10465441SEvalZero    b rt_hw_trap_pabt
252*10465441SEvalZerodabort_handle:
253*10465441SEvalZero    b rt_hw_trap_dabt
254*10465441SEvalZeroreserve_handle:
255*10465441SEvalZero    b rt_hw_trap_resv
256*10465441SEvalZero
257*10465441SEvalZero.globl 		rt_interrupt_enter
258*10465441SEvalZero.globl 		rt_interrupt_leave
259*10465441SEvalZero.globl 		rt_thread_switch_interrupt_flag
260*10465441SEvalZero.globl 		rt_interrupt_from_thread
261*10465441SEvalZero.globl 		rt_interrupt_to_thread
262*10465441SEvalZeroIRQ_handle:
263*10465441SEvalZero
264*10465441SEvalZero  stm.w (lr), [sp-]
265*10465441SEvalZero  stm.w (r16 - r28), [sp-]
266*10465441SEvalZero  stm.w (r0 - r15), [sp-]
267*10465441SEvalZero
268*10465441SEvalZero	b.l		rt_interrupt_enter
269*10465441SEvalZero	b.l		rt_hw_trap_irq
270*10465441SEvalZero	b.l		rt_interrupt_leave
271*10465441SEvalZero
272*10465441SEvalZero	/* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */
273*10465441SEvalZero	ldw		r0, =rt_thread_switch_interrupt_flag
274*10465441SEvalZero	ldw		r1, [r0+]
275*10465441SEvalZero	cmpsub.a	r1, #1
276*10465441SEvalZero	beq		_interrupt_thread_switch
277*10465441SEvalZero
278*10465441SEvalZero  ldm.w (r0 - r15), [sp]+
279*10465441SEvalZero  ldm.w (r16 - r28), [sp]+
280*10465441SEvalZero  ldm.w (lr), [sp]+
281*10465441SEvalZero  mov.a pc, lr
282*10465441SEvalZero
283*10465441SEvalZero	.align	5
284*10465441SEvalZeroFIQ_handle:
285*10465441SEvalZero  b rt_hw_trap_fiq
286*10465441SEvalZero
287*10465441SEvalZero_interrupt_thread_switch:
288*10465441SEvalZero
289*10465441SEvalZero	mov		r1,  #0	/* clear rt_thread_switch_interrupt_flag*/
290*10465441SEvalZero	stw		r1,  [r0+]
291*10465441SEvalZero
292*10465441SEvalZero	/*reload register*/
293*10465441SEvalZero  ldm.w (r0 - r15), [sp]+
294*10465441SEvalZero  ldm.w (r16 - r28), [sp]+
295*10465441SEvalZero  ldm.w (lr), [sp]+
296*10465441SEvalZero
297*10465441SEvalZero	stm.w	(r0 - r3), [sp-] /*save r0-r3*/
298*10465441SEvalZero
299*10465441SEvalZero	mov		r1,  sp
300*10465441SEvalZero	add		sp,  sp, #16 /* restore sp */
301*10465441SEvalZero	mov		r2,  lr	/* save old task's pc to r2 */
302*10465441SEvalZero
303*10465441SEvalZero  mov r3, bsr
304*10465441SEvalZero  mov r0, #0xd3 /*I:F:0:PRIV*/
305*10465441SEvalZero  mov.a asr, r0
306*10465441SEvalZero
307*10465441SEvalZero	stm.w	(r2), [sp-] /* push old task's pc */
308*10465441SEvalZero
309*10465441SEvalZero	/* push old task's registers */
310*10465441SEvalZero  stm.w (lr), [sp-]
311*10465441SEvalZero  stm.w (r16 - r28), [sp-]
312*10465441SEvalZero  stm.w (r4 - r15), [sp-]
313*10465441SEvalZero	mov		r4,  r1	/* Special optimised code below		*/
314*10465441SEvalZero  mov		r5,  r3
315*10465441SEvalZero  ldm.w (r0 - r3), [r4]+
316*10465441SEvalZero  stm.w (r0 - r3), [sp-] /*push old task's r3-r0*/
317*10465441SEvalZero	stm.w	(r5),	 [sp-] /* push old task's asr */
318*10465441SEvalZero	mov	r4, bsr
319*10465441SEvalZero	stm.w (r4), [sp-]	/* push old task's bsr*/
320*10465441SEvalZero
321*10465441SEvalZero	ldw		r4,  =rt_interrupt_from_thread
322*10465441SEvalZero	ldw		r5,  [r4+]
323*10465441SEvalZero	stw		sp,  [r5+] /* store sp in preempted tasks's TCB*/
324*10465441SEvalZero
325*10465441SEvalZero	ldw	r6,  =rt_interrupt_to_thread
326*10465441SEvalZero	ldw	r6,  [r6+]
327*10465441SEvalZero	ldw	sp,  [r6+] /* get new task's stack pointer	*/
328*10465441SEvalZero
329*10465441SEvalZero	ldm.w	(r4), [sp]+	/* pop new task's spsr				*/
330*10465441SEvalZero	mov.a	bsr, r4
331*10465441SEvalZero	ldm.w	(r4), [sp]+	/* pop new task's psr				*/
332*10465441SEvalZero	mov.a	asr, r4
333*10465441SEvalZero
334*10465441SEvalZero	/* pop new task's r0-r28,lr & pc */
335*10465441SEvalZero
336*10465441SEvalZero  ldm.w (r0 - r15), [sp]+
337*10465441SEvalZero  ldm.w (r16 - r28), [sp]+
338*10465441SEvalZero  ldm.w (lr), [sp]+
339*10465441SEvalZero  ldm.w (pc), [sp]+
340*10465441SEvalZero
341*10465441SEvalZerostack_setup:
342*10465441SEvalZero	/*irq*/
343*10465441SEvalZero  mov ip, lr
344*10465441SEvalZero	mov		r0, asr
345*10465441SEvalZero	andn  r0, r0, #0x1f
346*10465441SEvalZero	or		r0, r0, #IRQMODE|NOINT
347*10465441SEvalZero	mov.a		asr, r0 /*IRQMODE*/
348*10465441SEvalZero  ldw   r0, =IRQ_STACK_START
349*10465441SEvalZero  ldw   sp, [r0+]
350*10465441SEvalZero	/*ldw		sp, IRQ_STACK_START*/
351*10465441SEvalZero
352*10465441SEvalZero	/*priv*/
353*10465441SEvalZero	mov		r0, asr
354*10465441SEvalZero	andn    	r0, r0, #0x1f
355*10465441SEvalZero	or		r0, r0, #PRIVMODE|NOINT
356*10465441SEvalZero	mov.a		asr, r0 /*PRIVMODE*/
357*10465441SEvalZero  ldw   r0, =_STACK_START
358*10465441SEvalZero  ldw   sp, [r0+]
359*10465441SEvalZero	/*ldw		sp, _STACK_START*/
360*10465441SEvalZero  mov lr, ip
361*10465441SEvalZero	/*fiq and other mode is not implemented in code here*/
362*10465441SEvalZero	mov 		pc, lr /*lr may not be valid for the mode changes*/
363*10465441SEvalZero/*/*}*/
364