1/*
2 * Copyright (c) 2006-2019, 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 * 2019-07-28     zdzn         add smp support
10 */
11
12#include "../rtconfig.h"
13.section .text, "ax"
14
15#ifdef RT_USING_SMP
16#define rt_hw_interrupt_disable rt_hw_local_irq_disable
17#define rt_hw_interrupt_enable  rt_hw_local_irq_enable
18#endif
19
20/*
21 * rt_base_t rt_hw_interrupt_disable();
22 */
23.globl rt_hw_interrupt_disable
24rt_hw_interrupt_disable:
25    mrs r0, cpsr
26    cpsid i
27    bx  lr
28
29/*
30 * void rt_hw_interrupt_enable(rt_base_t level);
31 */
32.globl rt_hw_interrupt_enable
33rt_hw_interrupt_enable:
34    msr cpsr, r0
35    bx  lr
36
37/*
38 * void rt_hw_context_switch_to(rt_uint32 to, struct rt_thread *to_thread);
39 * r0 --> to (thread stack)
40 * r1 --> to_thread
41 */
42.globl rt_hw_context_switch_to
43rt_hw_context_switch_to:
44    ldr sp, [r0]            @ get new task stack pointer
45
46#ifdef RT_USING_SMP
47    mov     r0, r1
48    bl      rt_cpus_lock_status_restore
49#endif /*RT_USING_SMP*/
50    b       rt_hw_context_switch_exit
51
52.section .bss.share.isr
53_guest_switch_lvl:
54    .word 0
55
56.globl vmm_virq_update
57
58.section .text.isr, "ax"
59/*
60 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to, struct rt_thread *to_thread);
61 * r0 --> from (from_thread stack)
62 * r1 --> to (to_thread stack)
63 * r2 --> to_thread
64 */
65.globl rt_hw_context_switch
66rt_hw_context_switch:
67    stmfd   sp!, {lr}       @ push pc (lr should be pushed in place of PC)
68    stmfd   sp!, {r0-r12, lr}   @ push lr & register file
69
70    mrs r4, cpsr
71    tst lr, #0x01
72    orrne r4, r4, #0x20     @ it's thumb code
73
74    stmfd sp!, {r4}         @ push cpsr
75
76#ifdef RT_USING_SMART
77    stmfd sp, {r13, r14}^   @ push usr_sp usr_lr
78    sub sp, #8
79#endif
80#ifdef RT_USING_FPU
81    /* fpu context */
82    vmrs r6, fpexc
83    tst  r6, #(1<<30)
84    beq 1f
85    vstmdb sp!, {d0-d15}
86    vstmdb sp!, {d16-d31}
87    vmrs r5, fpscr
88    stmfd sp!, {r5}
891:
90    stmfd sp!, {r6}
91#endif
92
93    str sp, [r0]            @ store sp in preempted tasks TCB
94    ldr sp, [r1]            @ get new task stack pointer
95
96#ifdef RT_USING_SMP
97    mov     r0, r2
98    bl      rt_cpus_lock_status_restore
99#endif /*RT_USING_SMP*/
100    b       rt_hw_context_switch_exit
101
102/*
103 * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
104 */
105.equ Mode_USR,        0x10
106.equ Mode_FIQ,        0x11
107.equ Mode_IRQ,        0x12
108.equ Mode_SVC,        0x13
109.equ Mode_ABT,        0x17
110.equ Mode_UND,        0x1B
111.equ Mode_SYS,        0x1F
112
113.equ I_Bit,           0x80            @ when I bit is set, IRQ is disabled
114.equ F_Bit,           0x40            @ when F bit is set, FIQ is disabled
115
116.globl rt_thread_switch_interrupt_flag
117.globl rt_interrupt_from_thread
118.globl rt_interrupt_to_thread
119.globl rt_hw_context_switch_interrupt
120rt_hw_context_switch_interrupt:
121#ifdef RT_USING_SMP
122    /* r0 :svc_mod context
123     * r1 :addr of from_thread's sp
124     * r2 :addr of to_thread's sp
125     * r3 :to_thread's tcb
126     */
127
128    str     r0, [r1]
129
130    ldr     sp, [r2]
131    mov     r0, r3
132    bl      rt_cpus_lock_status_restore
133
134    b       rt_hw_context_switch_exit
135
136#else /*RT_USING_SMP*/
137    ldr r2, =rt_thread_switch_interrupt_flag
138    ldr r3, [r2]
139    cmp r3, #1
140    beq _reswitch
141    ldr ip, =rt_interrupt_from_thread   @ set rt_interrupt_from_thread
142    mov r3, #1              @ set rt_thread_switch_interrupt_flag to 1
143    str r0, [ip]
144    str r3, [r2]
145_reswitch:
146    ldr r2, =rt_interrupt_to_thread     @ set rt_interrupt_to_thread
147    str r1, [r2]
148    bx  lr
149#endif /*RT_USING_SMP*/
150
151.global rt_hw_context_switch_exit
152rt_hw_context_switch_exit:
153
154#ifdef RT_USING_SMP
155#ifdef RT_USING_SIGNALS
156    mov     r0, sp
157    cps #Mode_IRQ
158    bl      rt_signal_check
159    cps #Mode_SVC
160    mov     sp, r0
161#endif
162#endif
163#ifdef RT_USING_FPU
164/* fpu context */
165    ldmfd sp!, {r6}
166    vmsr fpexc, r6
167    tst  r6, #(1<<30)
168    beq 1f
169    ldmfd sp!, {r5}
170    vmsr fpscr, r5
171    vldmia sp!, {d16-d31}
172    vldmia sp!, {d0-d15}
173
174#endif
175
176#ifdef RT_USING_SMART
177    ldmfd   sp, {r13, r14}^ /* usr_sp, usr_lr */
178    add     sp, #8
179#endif
180    ldmfd   sp!, {r4}
181    msr     spsr_cxsf, r4        /* original mode */
182    ldmfd   sp!, {r0-r12,lr,pc}^ /* irq return */
183
184