summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/microblaze/cpu_asm.S
blob: d095e62f6906b2e2991d81460b3ce6b80f3bdfea (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/* SPDX-License-Identifier: BSD-2-Clause */

/**
 * @file
 *
 * @ingroup RTEMSScoreCPUMicroBlaze
 *
 * @brief MicroBlaze interrupt handler implementation
 */

/*
 * Copyright (C) 2021 On-Line Applications Research Corporation (OAR)
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <rtems/asm.h>
#include <rtems/score/percpu.h>

	.text
	.globl _ISR_Handler
	.align 2

_ISR_Handler:
	/* Save stack frame */
	swi  r3, r1, MICROBLAZE_INTERRUPT_FRAME_R3
	swi  r4, r1, MICROBLAZE_INTERRUPT_FRAME_R4
	swi  r6, r1, MICROBLAZE_INTERRUPT_FRAME_R6
	swi  r7, r1, MICROBLAZE_INTERRUPT_FRAME_R7
	swi  r8, r1, MICROBLAZE_INTERRUPT_FRAME_R8
	swi  r9, r1, MICROBLAZE_INTERRUPT_FRAME_R9
	swi r10, r1, MICROBLAZE_INTERRUPT_FRAME_R10
	swi r11, r1, MICROBLAZE_INTERRUPT_FRAME_R11
	swi r12, r1, MICROBLAZE_INTERRUPT_FRAME_R12
	swi r15, r1, MICROBLAZE_INTERRUPT_FRAME_R15
	swi r18, r1, MICROBLAZE_INTERRUPT_FRAME_R18

	xori r3, r5, 0xFFFF
	beqi r3, do_exception

	/* Disable dispatching */
	lwi r3, r0, _Per_CPU_Information + 16
	addik r3, r3, 1
	swi r3, r0, _Per_CPU_Information + 16

	swi r14, r1, MICROBLAZE_INTERRUPT_FRAME_R14

	/* Is SP < INTERRUPT_STACK_LOW? */
	lwi r4, r0, _Per_CPU_Information
	rsubk r3, r4, r1
	blei r3, switch_to_interrupt_stack

	/* Is SP > INTERRUPT_STACK_HIGH? */
	lwi r4, r0, _Per_CPU_Information + 4
	rsubk r3, r4, r1
	bgei r3, switch_to_interrupt_stack

	bri on_interrupt_stack

switch_to_interrupt_stack:
	add r4, r0, r1
	lwi r1, r0, _Per_CPU_Information + 4
	addik r1, r1, -52
	swi r4, r1, 0

on_interrupt_stack:
	/* Add 1 to ISR_NEST_LEVEL */
	lwi r3, r0, _Per_CPU_Information + 8
	addik r3, r3, 1
	swi r3, r0, _Per_CPU_Information + 8

	bralid r15, bsp_interrupt_dispatch
	nop

	/* Subtract 1 from ISR_NEST_LEVEL */
	lwi r3, r0, _Per_CPU_Information + 8
	addik r3, r3, -1
	swi r3, r0, _Per_CPU_Information + 8

	/* Is ISR_NEST_LEVEL > 0? */
	bgti r3, after_stack_switch

	/* Switch back to interrupted thread stack */
	lwi r1, r1, 0

after_stack_switch:
	/* Subtract 1 from THREAD_DISPATCH_DISABLE_LEVEL */
	lwi r3, r0, _Per_CPU_Information + 16
	addik r3, r3, -1
	swi r3, r0, _Per_CPU_Information + 16

	/* Is THREAD_DISPATCH_DISABLE_LEVEL != 0? */
	bnei r3, quick_exit

	/* Is DISPATCH_NEEDED == 0? */
	lwi r3, r0, _Per_CPU_Information + 20
	beqi r3, quick_exit

	/* Return to interrupted thread and make it do a dispatch */
	addik r14, r0, thread_dispatch
	rtid r14, 0
	nop

quick_exit:
	/* Simple return from nested interrupt */
	/* Restore registers */
	lwi  r3, r1, MICROBLAZE_INTERRUPT_FRAME_R3
	lwi  r4, r1, MICROBLAZE_INTERRUPT_FRAME_R4
	lwi  r5, r1, MICROBLAZE_INTERRUPT_FRAME_R5
	lwi  r6, r1, MICROBLAZE_INTERRUPT_FRAME_R6
	lwi  r7, r1, MICROBLAZE_INTERRUPT_FRAME_R7
	lwi  r8, r1, MICROBLAZE_INTERRUPT_FRAME_R8
	lwi  r9, r1, MICROBLAZE_INTERRUPT_FRAME_R9
	lwi r10, r1, MICROBLAZE_INTERRUPT_FRAME_R10
	lwi r11, r1, MICROBLAZE_INTERRUPT_FRAME_R11
	lwi r12, r1, MICROBLAZE_INTERRUPT_FRAME_R12
	lwi r14, r1, MICROBLAZE_INTERRUPT_FRAME_R14
	lwi r15, r1, MICROBLAZE_INTERRUPT_FRAME_R15
	lwi r18, r1, MICROBLAZE_INTERRUPT_FRAME_R18

	/* Remove stack frame */
	addik r1, r1, 52

	rtid r14, 0
	nop

thread_dispatch:
	/* Reserve stack */
	addik r1, r1, -52
	/* Save scratch registers */
	swi  r3, r1, MICROBLAZE_INTERRUPT_FRAME_R3
	swi  r4, r1, MICROBLAZE_INTERRUPT_FRAME_R4
	swi  r5, r1, MICROBLAZE_INTERRUPT_FRAME_R5
	swi  r6, r1, MICROBLAZE_INTERRUPT_FRAME_R6
	swi  r7, r1, MICROBLAZE_INTERRUPT_FRAME_R7
	swi  r8, r1, MICROBLAZE_INTERRUPT_FRAME_R8
	swi  r9, r1, MICROBLAZE_INTERRUPT_FRAME_R9
	swi r10, r1, MICROBLAZE_INTERRUPT_FRAME_R10
	swi r11, r1, MICROBLAZE_INTERRUPT_FRAME_R11
	swi r12, r1, MICROBLAZE_INTERRUPT_FRAME_R12
	swi r14, r1, MICROBLAZE_INTERRUPT_FRAME_R14
	swi r15, r1, MICROBLAZE_INTERRUPT_FRAME_R15
	swi r18, r1, MICROBLAZE_INTERRUPT_FRAME_R18

	bralid r15, _Thread_Dispatch
	nop

	/* Restore scratch registers */
	lwi  r3, r1, MICROBLAZE_INTERRUPT_FRAME_R3
	lwi  r4, r1, MICROBLAZE_INTERRUPT_FRAME_R4
	lwi  r5, r1, MICROBLAZE_INTERRUPT_FRAME_R5
	lwi  r6, r1, MICROBLAZE_INTERRUPT_FRAME_R6
	lwi  r7, r1, MICROBLAZE_INTERRUPT_FRAME_R7
	lwi  r8, r1, MICROBLAZE_INTERRUPT_FRAME_R8
	lwi  r9, r1, MICROBLAZE_INTERRUPT_FRAME_R9
	lwi r10, r1, MICROBLAZE_INTERRUPT_FRAME_R10
	lwi r11, r1, MICROBLAZE_INTERRUPT_FRAME_R11
	lwi r12, r1, MICROBLAZE_INTERRUPT_FRAME_R12
	lwi r14, r1, MICROBLAZE_INTERRUPT_FRAME_R14
	lwi r15, r1, MICROBLAZE_INTERRUPT_FRAME_R15
	lwi r18, r1, MICROBLAZE_INTERRUPT_FRAME_R18
	/* Free stack space */
	addik r1, r1, 52

	bri quick_exit

do_exception:
	/* exception no longer in progress */
	mfs r3, rmsr
	andni r3, r3, 0x200
	mts rmsr, r3
	addi r5, r0, 9
	add r6, r0, r1

	brai _Terminate