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