xref: /nrf52832-nimble/rt-thread/libcpu/arm/cortex-a/start_gcc.S (revision 042d53a763ad75cb1465103098bb88c245d95138)
1/*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date           Author       Notes
8 * 2013-07-05     Bernard      the first version
9 */
10
11.equ Mode_USR,        0x10
12.equ Mode_FIQ,        0x11
13.equ Mode_IRQ,        0x12
14.equ Mode_SVC,        0x13
15.equ Mode_ABT,        0x17
16.equ Mode_UND,        0x1B
17.equ Mode_SYS,        0x1F
18
19.equ I_Bit,           0x80            @ when I bit is set, IRQ is disabled
20.equ F_Bit,           0x40            @ when F bit is set, FIQ is disabled
21
22.equ UND_Stack_Size,     0x00000000
23.equ SVC_Stack_Size,     0x00000100
24.equ ABT_Stack_Size,     0x00000000
25.equ RT_FIQ_STACK_PGSZ,  0x00000000
26.equ RT_IRQ_STACK_PGSZ,  0x00000100
27.equ USR_Stack_Size,     0x00000100
28
29#define ISR_Stack_Size  (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
30                 RT_FIQ_STACK_PGSZ + RT_IRQ_STACK_PGSZ)
31
32.section .data.share.isr
33/* stack */
34.globl stack_start
35.globl stack_top
36
37stack_start:
38.rept ISR_Stack_Size
39.byte 0
40.endr
41stack_top:
42
43.text
44/* reset entry */
45.globl _reset
46_reset:
47    bl      rt_cpu_mmu_disable
48    /* set the cpu to SVC32 mode and disable interrupt */
49    mrs     r0, cpsr
50    bic     r0, r0, #0x1f
51    orr     r0, r0, #0x13
52    msr     cpsr_c, r0
53
54    /* setup stack */
55    bl      stack_setup
56
57    /* clear .bss */
58    mov     r0,#0                   /* get a zero                       */
59    ldr     r1,=__bss_start         /* bss start                        */
60    ldr     r2,=__bss_end           /* bss end                          */
61
62bss_loop:
63    cmp     r1,r2                   /* check if data to clear           */
64    strlo   r0,[r1],#4              /* clear 4 bytes                    */
65    blo     bss_loop                /* loop until done                  */
66
67    /* call C++ constructors of global objects                          */
68    ldr     r0, =__ctors_start__
69    ldr     r1, =__ctors_end__
70
71ctor_loop:
72    cmp     r0, r1
73    beq     ctor_end
74    ldr     r2, [r0], #4
75    stmfd   sp!, {r0-r1}
76    mov     lr, pc
77    bx      r2
78    ldmfd   sp!, {r0-r1}
79    b       ctor_loop
80ctor_end:
81
82    /* start RT-Thread Kernel */
83    ldr     pc, _rtthread_startup
84_rtthread_startup:
85    .word rtthread_startup
86
87stack_setup:
88    ldr     r0, =stack_top
89
90    @  Set the startup stack for svc
91    mov     sp, r0
92
93    @  Enter Undefined Instruction Mode and set its Stack Pointer
94    msr     cpsr_c, #Mode_UND|I_Bit|F_Bit
95    mov     sp, r0
96    sub     r0, r0, #UND_Stack_Size
97
98    @  Enter Abort Mode and set its Stack Pointer
99    msr     cpsr_c, #Mode_ABT|I_Bit|F_Bit
100    mov     sp, r0
101    sub     r0, r0, #ABT_Stack_Size
102
103    @  Enter FIQ Mode and set its Stack Pointer
104    msr     cpsr_c, #Mode_FIQ|I_Bit|F_Bit
105    mov     sp, r0
106    sub     r0, r0, #RT_FIQ_STACK_PGSZ
107
108    @  Enter IRQ Mode and set its Stack Pointer
109    msr     cpsr_c, #Mode_IRQ|I_Bit|F_Bit
110    mov     sp, r0
111    sub     r0, r0, #RT_IRQ_STACK_PGSZ
112
113    /* come back to SVC mode */
114    msr     cpsr_c, #Mode_SVC|I_Bit|F_Bit
115    bx      lr
116
117/* exception handlers: undef, swi, padt, dabt, resv, irq, fiq          */
118.section .text.isr, "ax"
119    .align  5
120.globl vector_fiq
121vector_fiq:
122    stmfd   sp!,{r0-r7,lr}
123    bl      rt_hw_trap_fiq
124    ldmfd   sp!,{r0-r7,lr}
125    subs    pc, lr, #4
126
127.globl      rt_interrupt_enter
128.globl      rt_interrupt_leave
129.globl      rt_thread_switch_interrupt_flag
130.globl      rt_interrupt_from_thread
131.globl      rt_interrupt_to_thread
132
133.globl      rt_current_thread
134.globl      vmm_thread
135.globl      vmm_virq_check
136
137    .align  5
138.globl vector_irq
139vector_irq:
140    stmfd   sp!, {r0-r12,lr}
141
142    bl      rt_interrupt_enter
143    bl      rt_hw_trap_irq
144    bl      rt_interrupt_leave
145
146    @ if rt_thread_switch_interrupt_flag set, jump to
147    @ rt_hw_context_switch_interrupt_do and don't return
148    ldr     r0, =rt_thread_switch_interrupt_flag
149    ldr     r1, [r0]
150    cmp     r1, #1
151    beq     rt_hw_context_switch_interrupt_do
152
153    ldmfd   sp!, {r0-r12,lr}
154    subs    pc,  lr, #4
155
156rt_hw_context_switch_interrupt_do:
157    mov     r1,  #0         @ clear flag
158    str     r1,  [r0]
159
160    mov     r1, sp          @ r1 point to {r0-r3} in stack
161    add     sp, sp, #4*4
162    ldmfd   sp!, {r4-r12,lr}@ reload saved registers
163    mrs     r0,  spsr       @ get cpsr of interrupt thread
164    sub     r2,  lr, #4     @ save old task's pc to r2
165
166    @ Switch to SVC mode with no interrupt. If the usr mode guest is
167    @ interrupted, this will just switch to the stack of kernel space.
168    @ save the registers in kernel space won't trigger data abort.
169    msr     cpsr_c, #I_Bit|F_Bit|Mode_SVC
170
171    stmfd   sp!, {r2}       @ push old task's pc
172    stmfd   sp!, {r4-r12,lr}@ push old task's lr,r12-r4
173    ldmfd   r1,  {r1-r4}    @ restore r0-r3 of the interrupt thread
174    stmfd   sp!, {r1-r4}    @ push old task's r0-r3
175    stmfd   sp!, {r0}       @ push old task's cpsr
176
177    ldr     r4,  =rt_interrupt_from_thread
178    ldr     r5,  [r4]
179    str     sp,  [r5]       @ store sp in preempted tasks's TCB
180
181    ldr     r6,  =rt_interrupt_to_thread
182    ldr     r6,  [r6]
183    ldr     sp,  [r6]       @ get new task's stack pointer
184
185    ldmfd   sp!, {r4}       @ pop new task's cpsr to spsr
186    msr     spsr_cxsf, r4
187
188    ldmfd   sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr
189
190.macro push_svc_reg
191    sub     sp, sp, #17 * 4         @/* Sizeof(struct rt_hw_exp_stack)  */
192    stmia   sp, {r0 - r12}          @/* Calling r0-r12                  */
193    mov     r0, sp
194    mrs     r6, spsr                @/* Save CPSR                       */
195    str     lr, [r0, #15*4]         @/* Push PC                         */
196    str     r6, [r0, #16*4]         @/* Push CPSR                       */
197    cps     #Mode_SVC
198    str     sp, [r0, #13*4]         @/* Save calling SP                 */
199    str     lr, [r0, #14*4]         @/* Save calling PC                 */
200.endm
201
202    .align  5
203    .globl	vector_swi
204vector_swi:
205    push_svc_reg
206    bl      rt_hw_trap_swi
207    b       .
208
209    .align  5
210    .globl	vector_undef
211vector_undef:
212    push_svc_reg
213    bl      rt_hw_trap_undef
214    b       .
215
216    .align  5
217    .globl	vector_pabt
218vector_pabt:
219    push_svc_reg
220    bl      rt_hw_trap_pabt
221    b       .
222
223    .align  5
224    .globl	vector_dabt
225vector_dabt:
226    push_svc_reg
227    bl      rt_hw_trap_dabt
228    b       .
229
230    .align  5
231    .globl	vector_resv
232vector_resv:
233    push_svc_reg
234    bl      rt_hw_trap_resv
235    b       .
236