1/*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date         Author     Notes
8 * 2012-02-13   mojingxian First version
9 */
10
11.global _rt_hw_interrupt_disable;
12.global _rt_hw_interrupt_enable;
13.global _interrupt_thread_switch;
14
15.extern _rt_interrupt_from_thread;
16.extern _rt_interrupt_to_thread;
17.extern _rt_thread_switch_interrupt_flag;
18
19.section/DOUBLE64 program;
20
21/*
22 * rt_base_t rt_hw_interrupt_disable();
23 * return value in R0.
24 */
25_rt_hw_interrupt_disable:
26    CLI  R0;
27
28_rt_hw_interrupt_disable.end:
29    NOP;
30    NOP;
31    NOP;
32    RTS;
33
34/*
35 * void rt_hw_interrupt_enable(rt_base_t level);
36 * R0->level
37 */
38_rt_hw_interrupt_enable:
39    STI  R0;
40
41_rt_hw_interrupt_enable.end:
42    NOP;
43    NOP;
44    NOP;
45    RTS;
46
47_interrupt_thread_switch:
48    /* Save context, interrupts disabled by IPEND[4] bit */
49    [ -- SP ]    = R0;
50    [ -- SP ]    = P1;
51    [ -- SP ]    = RETS;
52    [ -- SP ]    = R1;
53    [ -- SP ]    = R2;
54    [ -- SP ]    = P0;
55    [ -- SP ]    = P2;
56    [ -- SP ]    = ASTAT;
57    R1           = RETI;                  /* IPEND[4] is currently set, globally disabling interrupts  */
58                                          /* IPEND[4] will stay set when RETI is saved through R1      */
59
60    [ -- SP ]    = R1;
61    [ -- SP ]    = (R7:3, P5:3);
62    [ -- SP ]    = FP;
63    [ -- SP ]    = I0;
64    [ -- SP ]    = I1;
65    [ -- SP ]    = I2;
66    [ -- SP ]    = I3;
67    [ -- SP ]    = B0;
68    [ -- SP ]    = B1;
69    [ -- SP ]    = B2;
70    [ -- SP ]    = B3;
71    [ -- SP ]    = L0;
72    [ -- SP ]    = L1;
73    [ -- SP ]    = L2;
74    [ -- SP ]    = L3;
75    [ -- SP ]    = M0;
76    [ -- SP ]    = M1;
77    [ -- SP ]    = M2;
78    [ -- SP ]    = M3;
79    R1.L         = A0.x;
80    [ -- SP ]    = R1;
81    R1           = A0.w;
82    [ -- SP ]    = R1;
83    R1.L         = A1.x;
84    [ -- SP ]    = R1;
85    R1           = A1.w;
86    [ -- SP ]    = R1;
87    [ -- SP ]    = LC0;
88    R3           = 0;
89    LC0          = R3;
90    [ -- SP ]    = LC1;
91    R3           = 0;
92    LC1          = R3;
93    [ -- SP ]    = LT0;
94    [ -- SP ]    = LT1;
95    [ -- SP ]    = LB0;
96    [ -- SP ]    = LB1;
97
98    /* Context save done so save SP in the TCB */
99    P1.h         = _rt_interrupt_from_thread;
100    P1.l         = _rt_interrupt_from_thread;
101    P2           = [ P1 ];
102    [ P2 ]       = SP;
103
104    /* clear rt_thread_switch_interrupt_flag to 0 */
105    P1.h         = _rt_thread_switch_interrupt_flag;
106    P1.l         = _rt_thread_switch_interrupt_flag;
107    R0           = 0;
108    [ P1 ]       = R0;
109
110    /* Get a pointer to the high ready task's TCB */
111    P1.h         = _rt_interrupt_to_thread;
112    P1.l         = _rt_interrupt_to_thread;
113    P2           = [ P1 ];
114    SP           = [ P2 ];
115
116    /* Restoring CPU context and return to task */
117    LB1          = [ SP ++ ];
118    LB0          = [ SP ++ ];
119    LT1          = [ SP ++ ];
120    LT0          = [ SP ++ ];
121    LC1          = [ SP ++ ];
122    LC0          = [ SP ++ ];
123    R0           = [ SP ++ ];
124    A1           = R0;
125    R0           = [ SP ++ ];
126    A1.x         = R0.L;
127    R0           = [ SP ++ ];
128    A0           = R0;
129    R0           = [ SP ++ ];
130    A0.x         = R0.L;
131    M3           = [ SP ++ ];
132    M2           = [ SP ++ ];
133    M1           = [ SP ++ ];
134    M0           = [ SP ++ ];
135    L3           = [ SP ++ ];
136    L2           = [ SP ++ ];
137    L1           = [ SP ++ ];
138    L0           = [ SP ++ ];
139    B3           = [ SP ++ ];
140    B2           = [ SP ++ ];
141    B1           = [ SP ++ ];
142    B0           = [ SP ++ ];
143    I3           = [ SP ++ ];
144    I2           = [ SP ++ ];
145    I1           = [ SP ++ ];
146    I0           = [ SP ++ ];
147    FP           = [ SP ++ ];
148    (R7:3, P5:3) = [ SP ++ ];
149    RETI         = [ SP ++ ];             /* IPEND[4] will stay set when RETI popped from stack        */
150    ASTAT        = [ SP ++ ];
151    P2           = [ SP ++ ];
152    P0           = [ SP ++ ];
153    R2           = [ SP ++ ];
154    R1           = [ SP ++ ];
155    RETS         = [ SP ++ ];
156    P1           = [ SP ++ ];
157    R0           = [ SP ++ ];
158
159_interrupt_thread_switch.end:
160    RTI;
161
162