xref: /nrf52832-nimble/rt-thread/libcpu/arm/s3c24x0/start_gcc.S (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero/*
2*10465441SEvalZero * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero *
4*10465441SEvalZero * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero *
6*10465441SEvalZero * Change Logs:
7*10465441SEvalZero * Date           Author       Notes
8*10465441SEvalZero * 2006-03-13     Bernard      first version
9*10465441SEvalZero * 2006-10-05     Alsor.Z      for s3c2440 initialize
10*10465441SEvalZero * 2008-01-29     Yi.Qiu       for QEMU emulator
11*10465441SEvalZero */
12*10465441SEvalZero
13*10465441SEvalZero#define CONFIG_STACKSIZE 	512
14*10465441SEvalZero#define S_FRAME_SIZE 		72
15*10465441SEvalZero
16*10465441SEvalZero#define S_OLD_R0 			68
17*10465441SEvalZero#define S_PSR  				64
18*10465441SEvalZero#define S_PC  				60
19*10465441SEvalZero#define S_LR  				56
20*10465441SEvalZero#define S_SP  				52
21*10465441SEvalZero
22*10465441SEvalZero#define S_IP  				48
23*10465441SEvalZero#define S_FP  				44
24*10465441SEvalZero#define S_R10  				40
25*10465441SEvalZero#define S_R9  				36
26*10465441SEvalZero#define S_R8  				32
27*10465441SEvalZero#define S_R7  				28
28*10465441SEvalZero#define S_R6  				24
29*10465441SEvalZero#define S_R5  				20
30*10465441SEvalZero#define S_R4  				16
31*10465441SEvalZero#define S_R3  				12
32*10465441SEvalZero#define S_R2  				8
33*10465441SEvalZero#define S_R1  				4
34*10465441SEvalZero#define S_R0 				0
35*10465441SEvalZero
36*10465441SEvalZero.equ 	USERMODE, 			0x10
37*10465441SEvalZero.equ 	FIQMODE,			0x11
38*10465441SEvalZero.equ 	IRQMODE,			0x12
39*10465441SEvalZero.equ 	SVCMODE,			0x13
40*10465441SEvalZero.equ 	ABORTMODE,			0x17
41*10465441SEvalZero.equ 	UNDEFMODE,			0x1b
42*10465441SEvalZero.equ 	MODEMASK,			0x1f
43*10465441SEvalZero.equ 	NOINT,				0xc0
44*10465441SEvalZero
45*10465441SEvalZero.equ 	RAM_BASE,			0x00000000	/*Start address of RAM		*/
46*10465441SEvalZero.equ 	ROM_BASE,			0x30000000	/*Start address of Flash	*/
47*10465441SEvalZero
48*10465441SEvalZero.equ 	MPLLCON,			0x4c000004	/*Mpll control register		*/
49*10465441SEvalZero.equ 	M_MDIV,				0x20
50*10465441SEvalZero.equ 	M_PDIV,				0x4
51*10465441SEvalZero.equ 	M_SDIV,				0x2
52*10465441SEvalZero
53*10465441SEvalZero.equ 	INTMSK,				0x4a000008
54*10465441SEvalZero.equ 	INTSUBMSK, 			0x4a00001c
55*10465441SEvalZero.equ 	WTCON, 				0x53000000
56*10465441SEvalZero.equ 	LOCKTIME,			0x4c000000
57*10465441SEvalZero.equ 	CLKDIVN,			0x4c000014	/*Clock divider control		*/
58*10465441SEvalZero.equ 	GPHCON,				0x56000070	/*Port H control			*/
59*10465441SEvalZero.equ 	GPHUP,				0x56000078	/*Pull-up control H			*/
60*10465441SEvalZero.equ 	BWSCON,				0x48000000	/*Bus width & wait status	*/
61*10465441SEvalZero.equ 	BANKCON0,			0x48000004	/*Boot ROM control			*/
62*10465441SEvalZero.equ 	BANKCON1,			0x48000008	/*BANK1 control				*/
63*10465441SEvalZero.equ 	BANKCON2,			0x4800000c	/*BANK2 cControl			*/
64*10465441SEvalZero.equ 	BANKCON3,			0x48000010	/*BANK3 control				*/
65*10465441SEvalZero.equ 	BANKCON4,			0x48000014	/*BANK4 control				*/
66*10465441SEvalZero.equ 	BANKCON5,			0x48000018	/*BANK5 control				*/
67*10465441SEvalZero.equ 	BANKCON6,			0x4800001c	/*BANK6 control				*/
68*10465441SEvalZero.equ 	BANKCON7,			0x48000020	/*BANK7 control				*/
69*10465441SEvalZero.equ 	REFRESH,			0x48000024	/*DRAM/SDRAM efresh			*/
70*10465441SEvalZero.equ 	BANKSIZE,			0x48000028	/*Flexible Bank Size		*/
71*10465441SEvalZero.equ 	MRSRB6,				0x4800002c	/*Mode egister set for SDRAM*/
72*10465441SEvalZero.equ 	MRSRB7,				0x48000030	/*Mode egister set for SDRAM*/
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
85*10465441SEvalZero.globl _start
86*10465441SEvalZero_start:
87*10465441SEvalZero	b		reset
88*10465441SEvalZero	ldr		pc, _vector_undef
89*10465441SEvalZero	ldr		pc, _vector_swi
90*10465441SEvalZero	ldr		pc, _vector_pabt
91*10465441SEvalZero	ldr		pc, _vector_dabt
92*10465441SEvalZero	ldr		pc, _vector_resv
93*10465441SEvalZero	ldr		pc, _vector_irq
94*10465441SEvalZero	ldr		pc, _vector_fiq
95*10465441SEvalZero
96*10465441SEvalZero_vector_undef:	.word vector_undef
97*10465441SEvalZero_vector_swi:	.word vector_swi
98*10465441SEvalZero_vector_pabt:	.word vector_pabt
99*10465441SEvalZero_vector_dabt:	.word vector_dabt
100*10465441SEvalZero_vector_resv:	.word vector_resv
101*10465441SEvalZero_vector_irq:	.word vector_irq
102*10465441SEvalZero_vector_fiq:	.word vector_fiq
103*10465441SEvalZero
104*10465441SEvalZero.balignl 	16,0xdeadbeef
105*10465441SEvalZero
106*10465441SEvalZero/*
107*10465441SEvalZero *************************************************************************
108*10465441SEvalZero *
109*10465441SEvalZero * Startup Code (reset vector)
110*10465441SEvalZero * relocate armboot to ram
111*10465441SEvalZero * setup stack
112*10465441SEvalZero * jump to second stage
113*10465441SEvalZero *
114*10465441SEvalZero *************************************************************************
115*10465441SEvalZero */
116*10465441SEvalZero
117*10465441SEvalZero_TEXT_BASE:
118*10465441SEvalZero	.word	TEXT_BASE
119*10465441SEvalZero
120*10465441SEvalZero/*
121*10465441SEvalZero * rtthread kernel start and end
122*10465441SEvalZero * which are defined in linker script
123*10465441SEvalZero */
124*10465441SEvalZero.globl _rtthread_start
125*10465441SEvalZero_rtthread_start:
126*10465441SEvalZero	.word _start
127*10465441SEvalZero
128*10465441SEvalZero.globl _rtthread_end
129*10465441SEvalZero_rtthread_end:
130*10465441SEvalZero	.word  _end
131*10465441SEvalZero
132*10465441SEvalZero/*
133*10465441SEvalZero * rtthread bss start and end which are defined in linker script
134*10465441SEvalZero */
135*10465441SEvalZero.globl _bss_start
136*10465441SEvalZero_bss_start:
137*10465441SEvalZero	.word __bss_start
138*10465441SEvalZero
139*10465441SEvalZero.globl _bss_end
140*10465441SEvalZero_bss_end:
141*10465441SEvalZero	.word __bss_end
142*10465441SEvalZero
143*10465441SEvalZero/* IRQ stack memory (calculated at run-time) 						*/
144*10465441SEvalZero.globl IRQ_STACK_START
145*10465441SEvalZeroIRQ_STACK_START:
146*10465441SEvalZero	.word _irq_stack_start + 1024
147*10465441SEvalZero
148*10465441SEvalZero.globl FIQ_STACK_START
149*10465441SEvalZeroFIQ_STACK_START:
150*10465441SEvalZero	.word _fiq_stack_start + 1024
151*10465441SEvalZero
152*10465441SEvalZero.globl UNDEFINED_STACK_START
153*10465441SEvalZeroUNDEFINED_STACK_START:
154*10465441SEvalZero	.word _undefined_stack_start + CONFIG_STACKSIZE
155*10465441SEvalZero
156*10465441SEvalZero.globl ABORT_STACK_START
157*10465441SEvalZeroABORT_STACK_START:
158*10465441SEvalZero	.word _abort_stack_start + CONFIG_STACKSIZE
159*10465441SEvalZero
160*10465441SEvalZero.globl _STACK_START
161*10465441SEvalZero_STACK_START:
162*10465441SEvalZero	.word _svc_stack_start + 4096
163*10465441SEvalZero
164*10465441SEvalZero/* ----------------------------------entry------------------------------*/
165*10465441SEvalZeroreset:
166*10465441SEvalZero
167*10465441SEvalZero	/* set the cpu to SVC32 mode 	*/
168*10465441SEvalZero	mrs		r0,cpsr
169*10465441SEvalZero	bic		r0,r0,#MODEMASK
170*10465441SEvalZero	orr		r0,r0,#SVCMODE
171*10465441SEvalZero	msr		cpsr,r0
172*10465441SEvalZero
173*10465441SEvalZero	/* watch dog disable 			*/
174*10465441SEvalZero	ldr 	r0,=WTCON
175*10465441SEvalZero	ldr 	r1,=0x0
176*10465441SEvalZero	str 	r1,[r0]
177*10465441SEvalZero
178*10465441SEvalZero	/* mask all IRQs by clearing all bits in the INTMRs 				*/
179*10465441SEvalZero	ldr		r1, =INTMSK
180*10465441SEvalZero	ldr		r0, =0xffffffff
181*10465441SEvalZero	str		r0, [r1]
182*10465441SEvalZero	ldr		r1, =INTSUBMSK
183*10465441SEvalZero	ldr		r0, =0x7fff				/*all sub interrupt disable			*/
184*10465441SEvalZero	str		r0, [r1]
185*10465441SEvalZero
186*10465441SEvalZero	/* set interrupt vector 		*/
187*10465441SEvalZero	ldr 	r0, _load_address
188*10465441SEvalZero	mov		r1, #0x0				/* target address    				*/
189*10465441SEvalZero	add		r2, r0, #0x20			/* size, 32bytes         			*/
190*10465441SEvalZero
191*10465441SEvalZerocopy_loop:
192*10465441SEvalZero	ldmia	r0!, {r3-r10}			/* copy from source address [r0]    */
193*10465441SEvalZero	stmia	r1!, {r3-r10}			/* copy to   target address [r1]    */
194*10465441SEvalZero	cmp		r0, r2					/* until source end addreee [r2]    */
195*10465441SEvalZero	ble		copy_loop
196*10465441SEvalZero
197*10465441SEvalZero	/* setup stack */
198*10465441SEvalZero	bl		stack_setup
199*10465441SEvalZero
200*10465441SEvalZero	/* clear .bss */
201*10465441SEvalZero	mov   	r0,#0                   /* get a zero 						*/
202*10465441SEvalZero	ldr   	r1,=__bss_start         /* bss start 						*/
203*10465441SEvalZero	ldr   	r2,=__bss_end           /* bss end 							*/
204*10465441SEvalZero
205*10465441SEvalZerobss_loop:
206*10465441SEvalZero	cmp   	r1,r2                   /* check if data to clear 			*/
207*10465441SEvalZero	strlo 	r0,[r1],#4              /* clear 4 bytes 					*/
208*10465441SEvalZero	blo   	bss_loop                /* loop until done 					*/
209*10465441SEvalZero
210*10465441SEvalZero	/* call C++ constructors of global objects 							*/
211*10465441SEvalZero	ldr 	r0, =__ctors_start__
212*10465441SEvalZero	ldr 	r1, =__ctors_end__
213*10465441SEvalZero
214*10465441SEvalZeroctor_loop:
215*10465441SEvalZero	cmp 	r0, r1
216*10465441SEvalZero	beq 	ctor_end
217*10465441SEvalZero	ldr 	r2, [r0], #4
218*10465441SEvalZero	stmfd 	sp!, {r0-r1}
219*10465441SEvalZero	mov 	lr, pc
220*10465441SEvalZero	bx 		r2
221*10465441SEvalZero	ldmfd 	sp!, {r0-r1}
222*10465441SEvalZero	b		ctor_loop
223*10465441SEvalZero
224*10465441SEvalZeroctor_end:
225*10465441SEvalZero
226*10465441SEvalZero	/* start RT-Thread Kernel 		*/
227*10465441SEvalZero	ldr		pc, _rtthread_startup
228*10465441SEvalZero
229*10465441SEvalZero_rtthread_startup:
230*10465441SEvalZero	.word rtthread_startup
231*10465441SEvalZero#if defined (__FLASH_BUILD__)
232*10465441SEvalZero_load_address:
233*10465441SEvalZero	.word ROM_BASE + _TEXT_BASE
234*10465441SEvalZero#else
235*10465441SEvalZero_load_address:
236*10465441SEvalZero	.word RAM_BASE + _TEXT_BASE
237*10465441SEvalZero#endif
238*10465441SEvalZero
239*10465441SEvalZero/*
240*10465441SEvalZero *************************************************************************
241*10465441SEvalZero *
242*10465441SEvalZero * Interrupt handling
243*10465441SEvalZero *
244*10465441SEvalZero *************************************************************************
245*10465441SEvalZero */
246*10465441SEvalZero
247*10465441SEvalZero/* exception handlers 				*/
248*10465441SEvalZero	.align  5
249*10465441SEvalZerovector_undef:
250*10465441SEvalZero	sub 	sp, sp, #S_FRAME_SIZE
251*10465441SEvalZero	stmia 	sp, {r0 - r12}   		/* Calling r0-r12					*/
252*10465441SEvalZero	add		r8, sp, #S_PC
253*10465441SEvalZero	stmdb   r8, {sp, lr}^           /* Calling SP, LR					*/
254*10465441SEvalZero	str		lr, [r8, #0]            /* Save calling PC					*/
255*10465441SEvalZero	mrs		r6, spsr
256*10465441SEvalZero	str		r6, [r8, #4]            /* Save CPSR						*/
257*10465441SEvalZero	str		r0, [r8, #8]            /* Save OLD_R0						*/
258*10465441SEvalZero	mov		r0, sp
259*10465441SEvalZero
260*10465441SEvalZero	bl		rt_hw_trap_udef
261*10465441SEvalZero
262*10465441SEvalZero	.align	5
263*10465441SEvalZerovector_swi:
264*10465441SEvalZero	bl 		rt_hw_trap_swi
265*10465441SEvalZero
266*10465441SEvalZero	.align	5
267*10465441SEvalZerovector_pabt:
268*10465441SEvalZero	bl 		rt_hw_trap_pabt
269*10465441SEvalZero
270*10465441SEvalZero	.align	5
271*10465441SEvalZerovector_dabt:
272*10465441SEvalZero	sub 	sp, sp, #S_FRAME_SIZE
273*10465441SEvalZero	stmia 	sp, {r0 - r12}   		/* Calling r0-r12					*/
274*10465441SEvalZero	add		r8, sp, #S_PC
275*10465441SEvalZero	stmdb   r8, {sp, lr}^           /* Calling SP, LR					*/
276*10465441SEvalZero	str		lr, [r8, #0]            /* Save calling PC					*/
277*10465441SEvalZero	mrs		r6, spsr
278*10465441SEvalZero	str		r6, [r8, #4]            /* Save CPSR						*/
279*10465441SEvalZero	str		r0, [r8, #8]            /* Save OLD_R0						*/
280*10465441SEvalZero	mov		r0, sp
281*10465441SEvalZero
282*10465441SEvalZero	bl 		rt_hw_trap_dabt
283*10465441SEvalZero
284*10465441SEvalZero	.align	5
285*10465441SEvalZerovector_resv:
286*10465441SEvalZero	bl 		rt_hw_trap_resv
287*10465441SEvalZero
288*10465441SEvalZero.globl 		rt_interrupt_enter
289*10465441SEvalZero.globl 		rt_interrupt_leave
290*10465441SEvalZero.globl 		rt_thread_switch_interrupt_flag
291*10465441SEvalZero.globl 		rt_interrupt_from_thread
292*10465441SEvalZero.globl 		rt_interrupt_to_thread
293*10465441SEvalZerovector_irq:
294*10465441SEvalZero	stmfd	sp!, {r0-r12,lr}
295*10465441SEvalZero	bl		rt_interrupt_enter
296*10465441SEvalZero	bl		rt_hw_trap_irq
297*10465441SEvalZero	bl		rt_interrupt_leave
298*10465441SEvalZero
299*10465441SEvalZero	/* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */
300*10465441SEvalZero	ldr		r0, =rt_thread_switch_interrupt_flag
301*10465441SEvalZero	ldr		r1, [r0]
302*10465441SEvalZero	cmp		r1, #1
303*10465441SEvalZero	beq		_interrupt_thread_switch
304*10465441SEvalZero
305*10465441SEvalZero	ldmfd	sp!, {r0-r12,lr}
306*10465441SEvalZero	subs	pc, lr, #4
307*10465441SEvalZero
308*10465441SEvalZero	.align	5
309*10465441SEvalZerovector_fiq:
310*10465441SEvalZero	stmfd	sp!,{r0-r7,lr}
311*10465441SEvalZero	bl 		rt_hw_trap_fiq
312*10465441SEvalZero	ldmfd	sp!,{r0-r7,lr}
313*10465441SEvalZero	subs	pc,lr,#4
314*10465441SEvalZero
315*10465441SEvalZero_interrupt_thread_switch:
316*10465441SEvalZero	mov		r1,  #0					/* clear rt_thread_switch_interrupt_flag*/
317*10465441SEvalZero	str		r1,  [r0]
318*10465441SEvalZero
319*10465441SEvalZero	ldmfd	sp!, {r0-r12,lr}		/* reload saved registers			*/
320*10465441SEvalZero	stmfd	sp!, {r0-r3}			/* save r0-r3						*/
321*10465441SEvalZero	mov		r1,  sp
322*10465441SEvalZero	add		sp,  sp, #16			/* restore sp						*/
323*10465441SEvalZero	sub		r2,  lr, #4				/* save old task's pc to r2			*/
324*10465441SEvalZero
325*10465441SEvalZero	mrs		r3,  spsr				/* disable interrupt				*/
326*10465441SEvalZero	orr		r0,  r3, #NOINT
327*10465441SEvalZero	msr		spsr_c, r0
328*10465441SEvalZero
329*10465441SEvalZero	ldr		r0,  =.+8				/* switch to interrupted task's stack*/
330*10465441SEvalZero	movs	pc,  r0
331*10465441SEvalZero
332*10465441SEvalZero	stmfd	sp!, {r2}				/* push old task's pc				*/
333*10465441SEvalZero	stmfd	sp!, {r4-r12,lr}		/* push old task's lr,r12-r4		*/
334*10465441SEvalZero	mov		r4,  r1					/* Special optimised code below		*/
335*10465441SEvalZero	mov		r5,  r3
336*10465441SEvalZero	ldmfd	r4!, {r0-r3}
337*10465441SEvalZero	stmfd	sp!, {r0-r3}			/* push old task's r3-r0			*/
338*10465441SEvalZero	stmfd	sp!, {r5}				/* push old task's psr				*/
339*10465441SEvalZero	mrs		r4,  spsr
340*10465441SEvalZero	stmfd	sp!, {r4}				/* push old task's spsr				*/
341*10465441SEvalZero
342*10465441SEvalZero	ldr		r4,  =rt_interrupt_from_thread
343*10465441SEvalZero	ldr		r5,  [r4]
344*10465441SEvalZero	str		sp,  [r5]				/* store sp in preempted tasks's TCB*/
345*10465441SEvalZero
346*10465441SEvalZero	ldr	r6,  =rt_interrupt_to_thread
347*10465441SEvalZero	ldr	r6,  [r6]
348*10465441SEvalZero	ldr	sp,  [r6]					/* get new task's stack pointer		*/
349*10465441SEvalZero
350*10465441SEvalZero	ldmfd	sp!, {r4}				/* pop new task's spsr				*/
351*10465441SEvalZero	msr		SPSR_cxsf, r4
352*10465441SEvalZero	ldmfd	sp!, {r4}				/* pop new task's psr				*/
353*10465441SEvalZero	msr		CPSR_cxsf, r4
354*10465441SEvalZero
355*10465441SEvalZero	ldmfd	sp!, {r0-r12,lr,pc}		/* pop new task's r0-r12,lr & pc	*/
356*10465441SEvalZero
357*10465441SEvalZerostack_setup:
358*10465441SEvalZero	mrs		r0, cpsr
359*10465441SEvalZero	bic		r0, r0, #MODEMASK
360*10465441SEvalZero	orr		r1, r0, #UNDEFMODE|NOINT
361*10465441SEvalZero	msr		cpsr_cxsf, r1			/* undef mode						*/
362*10465441SEvalZero	ldr		sp, UNDEFINED_STACK_START
363*10465441SEvalZero
364*10465441SEvalZero	orr		r1,r0,#ABORTMODE|NOINT
365*10465441SEvalZero	msr		cpsr_cxsf,r1			/* abort mode						*/
366*10465441SEvalZero	ldr		sp, ABORT_STACK_START
367*10465441SEvalZero
368*10465441SEvalZero	orr		r1,r0,#IRQMODE|NOINT
369*10465441SEvalZero	msr		cpsr_cxsf,r1			/* IRQ mode							*/
370*10465441SEvalZero	ldr		sp, IRQ_STACK_START
371*10465441SEvalZero
372*10465441SEvalZero	orr		r1,r0,#FIQMODE|NOINT
373*10465441SEvalZero	msr		cpsr_cxsf,r1			/* FIQ mode							*/
374*10465441SEvalZero	ldr		sp, FIQ_STACK_START
375*10465441SEvalZero
376*10465441SEvalZero	bic		r0,r0,#MODEMASK
377*10465441SEvalZero	orr		r1,r0,#SVCMODE|NOINT
378*10465441SEvalZero	msr		cpsr_cxsf,r1			/* SVC mode							*/
379*10465441SEvalZero
380*10465441SEvalZero	ldr		sp, _STACK_START
381*10465441SEvalZero
382*10465441SEvalZero	/* USER mode is not initialized. */
383*10465441SEvalZero	mov		pc,lr					/* The LR register may be not valid for the mode changes.*/
384*10465441SEvalZero
385*10465441SEvalZero/*/*}*/
386*10465441SEvalZero
387