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 * 2011-12-17     nl1031       first implementation for MicroBlaze.
9 */
10
11#include "microblaze.inc"
12
13	.text
14    	.globl	rt_interrupt_enter
15    	.globl	rt_interrupt_leave
16
17/*
18 * rt_base_t rt_hw_interrupt_disable()
19 * copy from ucos-ii
20 */
21
22	.globl	rt_hw_interrupt_disable
23	.ent	rt_hw_interrupt_disable
24	.align	2
25rt_hw_interrupt_disable:
26    	ADDIK   r1, r1, -4
27    	SW      r4, r1, r0
28
29    	MFS     r3, RMSR
30    	ANDNI   r4, r3, IE_BIT
31    	MTS     RMSR, r4
32
33    	LW      r4, r1, r0
34    	ADDIK   r1, r1, 4
35
36    	AND     r0, r0, r0             /* NO-OP - pipeline flush                             */
37    	AND     r0, r0, r0             /* NO-OP - pipeline flush                             */
38    	AND     r0, r0, r0             /* NO-OP - pipeline flush                             */
39
40    	RTSD    r15, 8
41    	AND     r0, r0, r0
42	.end	rt_hw_interrupt_disable
43
44/*
45 * void rt_hw_interrupt_enable(rt_base_t level)
46 * copy from ucos-ii
47 */
48	.globl	rt_hw_interrupt_enable
49	.ent	rt_hw_interrupt_enable
50	.align	2
51rt_hw_interrupt_enable:
52    	RTSD    r15, 8
53    	MTS     rMSR, r5               		/* Move the saved status from r5 into rMSR            */
54	.end	rt_hw_interrupt_enable
55
56/*
57 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to)
58 * r5 --> from
59 * r6 --> to
60 */
61
62	.globl rt_interrupt_from_thread
63	.globl rt_interrupt_to_thread
64	.globl rt_hw_context_switch
65	.ent rt_hw_context_switch
66	.align	2
67rt_hw_context_switch:
68	PUSH_ALL
69    	MFS     r3,  RMSR                   /* save the MSR */
70    	SWI     r3,  r1, STACK_RMSR
71	SWI		r1,  r5, 0					/* store sp in preempted tasks TCB */
72	LWI		r1,  r6, 0					/* get new task stack pointer */
73
74    	LWI     r3,  r1, STACK_RMSR
75    	ANDI    r3,  r3, IE_BIT
76    	BNEI    r3,  rt_hw_context_switch_ie /*if IE bit set,should be use RTID (return from interrupt). */
77
78    	LWI     r3,  r1, STACK_RMSR
79    	MTS     RMSR,r3
80	POP_ALL
81    	ADDIK   r1,  r1, STACK_SIZE
82    	RTSD    r15, 8
83    	AND     r0,  r0, r0
84
85rt_hw_context_switch_ie:
86
87    	LWI     r3,  r1, STACK_RMSR
88    	ANDNI   r3,  r3, IE_BIT         	/* clear IE bit, prevent interrupt occur immediately*/
89    	MTS     RMSR,r3
90    	LWI     r3,  r1, STACK_R03
91	POP_ALL
92    	ADDIK   r1,  r1, STACK_SIZE
93    	RTID    r14, 0                    	/* IE bit will be set automatically */
94    	AND     r0,  r0, r0
95	.end	rt_hw_context_switch
96
97/*
98 * void rt_hw_context_switch_to(rt_uint32 to)
99 * r5 --> to
100 */
101	.globl 	rt_hw_context_switch_to
102	.ent   	rt_hw_context_switch_to
103	.align	2
104rt_hw_context_switch_to:
105	LWI		r1,	 r5, 0 					/* get new task stack pointer */
106    	LWI     r3,  r1, STACK_RMSR
107    	ANDNI   r3,  r3, IE_BIT         	/* clear IE bit, prevent interrupt occur immediately*/
108    	MTS     RMSR,r3
109	POP_ALL
110    	ADDIK   r1,  r1, STACK_SIZE
111    	RTID    r14, 0                    	/* IE bit will be set automatically */
112    	AND     r0,  r0, r0
113
114	.end 	rt_hw_context_switch_to
115
116/*
117 * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to)
118 */
119	.globl 	rt_thread_switch_interrupt_flag
120	.globl 	rt_hw_context_switch_interrupt
121	.ent rt_hw_context_switch_interrupt
122	.align	2
123rt_hw_context_switch_interrupt:
124	LA	r3,	r0, rt_thread_switch_interrupt_flag
125	LWI	r4, r3, 0					/* load rt_thread_switch_interrupt_flag into r4 */
126
127	ANDI	r4, r4, 1
128	BNEI	r4, _reswitch				/* if rt_thread_switch_interrupt_flag = 1 */
129
130	ADDIK	r4, r0, 1					/* set rt_thread_switch_interrupt_flag to 1 */
131	SWI	r4, r3, 0
132
133	LA	r3, r0, rt_interrupt_from_thread /* set rt_interrupt_from_thread */
134	SWI	r5, r3, 0 					/* rt_interrupt_from_thread = from */
135_reswitch:
136	LA	r3, r0, rt_interrupt_to_thread	/* set rt_interrupt_to_thread */
137	SWI	r6, r3, 0 					/* rt_interrupt_to_thread = to */
138    	RTSD    r15, 8
139    	AND     r0, r0, r0
140	.end rt_hw_context_switch_interrupt
141
142
143    .globl     	_interrupt_handler
144	.section .text
145	.align 	2
146	.ent _interrupt_handler
147	.type _interrupt_handler, @function
148
149_interrupt_handler:
150	PUSH_ALL
151    	MFS     r3,  RMSR
152    	ORI     r3,  r3, IE_BIT
153    	SWI     r3,  r1, STACK_RMSR         	/* push MSR    */
154
155    	BRLID   r15, rt_interrupt_enter
156    	AND     r0,  r0, r0
157
158    	BRLID   r15, rt_hw_trap_irq
159    	AND     r0,  r0, r0
160
161    	BRLID   r15, rt_interrupt_leave
162    	AND     r0,  r0, r0
163
164	/*
165	 * if rt_thread_switch_interrupt_flag set, jump to
166	 * rt_hw_context_switch_interrupt_do and don't return
167	 */
168	LA	r3,  r0, rt_thread_switch_interrupt_flag
169	LWI	r4,  r3, 0
170
171	ANDI	r4,  r4, 1
172	BNEI 	r4,  rt_hw_context_switch_interrupt_do
173
174    	LWI     r3,  r1, STACK_RMSR
175    	ANDNI   r3,  r3, IE_BIT
176    	MTS     RMSR,r3
177	POP_ALL
178    	ADDIK   r1,  r1, STACK_SIZE
179
180    	RTID    r14, 0
181    	AND     r0,  r0, r0
182
183/*
184 * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
185 */
186rt_hw_context_switch_interrupt_do:
187	SWI	r0,  r3, 0 						/* clear rt_thread_switch_interrupt_flag */
188
189	LA	r3,  r0, rt_interrupt_from_thread
190	LW	r4,  r0, r3
191	SWI	r1,  r4, 0						/* store sp in preempted tasks's TCB */
192
193	LA	r3,  r0, rt_interrupt_to_thread
194	LW	r4,  r0, r3
195	LWI	r1,  r4, 0						/* get new task's stack pointer */
196
197    	LWI     r3,  r1, STACK_RMSR
198    	ANDI    r3,  r3, IE_BIT
199    	BNEI    r3,  return_with_ie     	/*if IE bit set,should be use RTID (return from interrupt). */
200
201    	LWI     r3,  r1, STACK_RMSR
202    	MTS     RMSR,r3
203	POP_ALL
204    	ADDIK   r1,  r1, STACK_SIZE
205    	RTSD    r15, 8
206    	AND     r0,  r0, r0
207
208return_with_ie:
209
210    	LWI     r3,  r1, STACK_RMSR
211    	ANDNI   r3,  r3, IE_BIT         	/* clear IE bit, prevent interrupt occur immediately*/
212    	MTS     RMSR,r3
213    	LWI     r3,  r1, STACK_R03
214	POP_ALL
215    	ADDIK   r1,  r1, STACK_SIZE
216    	RTID    r14, 0                    	/* IE bit will be set automatically */
217    	AND     r0,  r0, r0
218
219.end _interrupt_handler
220
221