1 ##=============================================================================##
4 ## OpenRISC context switch code
6 ##=============================================================================
7 #####ECOSGPLCOPYRIGHTBEGIN####
8 ## -------------------------------------------
9 ## This file is part of eCos, the Embedded Configurable Operating System.
10 ## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 ## eCos is free software; you can redistribute it and/or modify it under
13 ## the terms of the GNU General Public License as published by the Free
14 ## Software Foundation; either version 2 or (at your option) any later version.
16 ## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
17 ## WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 ## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 ## You should have received a copy of the GNU General Public License along
22 ## with eCos; if not, write to the Free Software Foundation, Inc.,
23 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 ## As a special exception, if other files instantiate templates or use macros
26 ## or inline functions from this file, or you compile this file and link it
27 ## with other works to produce a work based on this file, this file does not
28 ## by itself cause the resulting work to be covered by the GNU General Public
29 ## License. However the source code for this file must still be made available
30 ## in accordance with section (3) of the GNU General Public License.
32 ## This exception does not invalidate any other reasons why a work based on
33 ## this file might be covered by the GNU General Public License.
35 ## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
36 ## at http://sources.redhat.com/ecos/ecos-license/
37 ## -------------------------------------------
38 #####ECOSGPLCOPYRIGHTEND####
39 ##=============================================================================
40 #######DESCRIPTIONBEGIN####
42 ## Author(s): Scott Furman
45 ## Purpose: OpenRISC context switch code
46 ## Description: This file contains implementations of the thread context
47 ## switch routines. It also contains the longjmp() and setjmp()
50 ######DESCRIPTIONEND####
52 ##=============================================================================
54 #include <pkgconf/hal.h>
56 #include <cyg/hal/arch.inc>
57 #include <cyg/hal/openrisc.inc>
61 #------------------------------------------------------------------------------
62 # hal_thread_switch_context()
63 # Switch thread contexts
64 # R3 = address of sp of next thread to execute
65 # R4 = address of sp save location of current thread
67 FUNC_START(hal_thread_switch_context)
68 l.addi sp,sp,-SIZEOF_OR1KREGS # space for registers
70 # Store General Purpose Registers (GPRs).
71 l.sw 2 * OR1K_GPRSIZE(sp), r2
72 l.sw 9 * OR1K_GPRSIZE(sp), r9
73 l.sw 10 * OR1K_GPRSIZE(sp), r10
74 l.sw 12 * OR1K_GPRSIZE(sp), r12
75 l.sw 14 * OR1K_GPRSIZE(sp), r14
76 l.sw 16 * OR1K_GPRSIZE(sp), r16
77 l.sw 18 * OR1K_GPRSIZE(sp), r18
78 l.sw 20 * OR1K_GPRSIZE(sp), r20
79 l.sw 22 * OR1K_GPRSIZE(sp), r22
80 l.sw 24 * OR1K_GPRSIZE(sp), r24
81 l.sw 26 * OR1K_GPRSIZE(sp), r26
82 l.sw 28 * OR1K_GPRSIZE(sp), r28
83 l.sw 30 * OR1K_GPRSIZE(sp), r30
85 #ifndef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
87 # R0 is not typically stored because it is always zero-valued,
88 # but we store it here for consistency when examining registers
90 l.sw 0 * OR1K_GPRSIZE(sp), r0
92 # Caller-saved regs don't need to be preserved across
93 # context switches, but we do so to make debugging easier.
95 l.sw 3 * OR1K_GPRSIZE(sp), r3
96 l.sw 4 * OR1K_GPRSIZE(sp), r4
97 l.sw 5 * OR1K_GPRSIZE(sp), r5
98 l.sw 6 * OR1K_GPRSIZE(sp), r6
99 l.sw 7 * OR1K_GPRSIZE(sp), r7
100 l.sw 8 * OR1K_GPRSIZE(sp), r8
101 l.sw 11 * OR1K_GPRSIZE(sp), r11
102 l.sw 13 * OR1K_GPRSIZE(sp), r13
103 l.sw 15 * OR1K_GPRSIZE(sp), r15
104 l.sw 17 * OR1K_GPRSIZE(sp), r17
105 l.sw 19 * OR1K_GPRSIZE(sp), r19
106 l.sw 21 * OR1K_GPRSIZE(sp), r21
107 l.sw 23 * OR1K_GPRSIZE(sp), r23
108 l.sw 25 * OR1K_GPRSIZE(sp), r25
109 l.sw 27 * OR1K_GPRSIZE(sp), r27
110 l.sw 29 * OR1K_GPRSIZE(sp), r29
111 l.sw 31 * OR1K_GPRSIZE(sp), r31
113 # save MAC LO and HI regs
114 l.mfspr r5,r0,SPR_MACLO
115 l.sw OR1KREG_MACLO(sp),r5
116 l.mfspr r5,r0,SPR_MACHI
117 l.sw OR1KREG_MACHI(sp),r5
121 #ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT
122 # Make the thread context look like an exception context if thread-
123 # aware debugging is required. This state does not need restoring.
124 l.sw OR1KREG_PC(sp),r9
127 l.addi r5,sp,SIZEOF_OR1KREGS # save SP in reg dump
128 l.sw 1 * OR1K_GPRSIZE(sp), r5
130 l.mfspr r5,r0,SPR_SR # save SR in reg dump
131 l.sw OR1KREG_SR(sp), r5
133 # Return resulting new SP to caller via second argument
136 # Now load the destination thread by dropping through
137 # to hal_thread_load_context...
138 FUNC_END(hal_thread_switch_context)
141 #------------------------------------------------------------------------------
142 # hal_thread_load_context()
143 # Load thread context
144 # R3 = address of sp of next thread to execute
145 # Note that this function is also the second half of hal_thread_switch_context()
146 # and is simply dropped into from it.
148 FUNC_START(hal_thread_load_context)
153 # Restore General Purpose Registers (GPRs).
154 # R0 is not restored because it is always zero-valued.
155 l.lwz r2, 2 * OR1K_GPRSIZE(sp)
156 l.lwz r9, 9 * OR1K_GPRSIZE(sp)
157 l.lwz r10, 10 * OR1K_GPRSIZE(sp)
158 l.lwz r12, 12 * OR1K_GPRSIZE(sp)
159 l.lwz r14, 14 * OR1K_GPRSIZE(sp)
160 l.lwz r16, 16 * OR1K_GPRSIZE(sp)
161 l.lwz r18, 18 * OR1K_GPRSIZE(sp)
162 l.lwz r20, 20 * OR1K_GPRSIZE(sp)
163 l.lwz r22, 22 * OR1K_GPRSIZE(sp)
164 l.lwz r24, 24 * OR1K_GPRSIZE(sp)
165 l.lwz r26, 26 * OR1K_GPRSIZE(sp)
166 l.lwz r28, 28 * OR1K_GPRSIZE(sp)
167 l.lwz r30, 30 * OR1K_GPRSIZE(sp)
169 # Merge interrupt-enable state of new thread into
171 load32i r5,~(SPR_SR_TEE|SPR_SR_IEE)
172 l.mfspr r6, r0, SPR_SR
174 l.lwz r5, OR1KREG_SR(sp)
175 l.andi r5, r5, (SPR_SR_TEE|SPR_SR_IEE)
177 l.mtspr r0, r5, SPR_SR
179 #ifndef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
181 # Caller-saved regs don't need to be preserved across
182 # context switches, but we do so here to make debugging
185 # Restore MAC LO and HI regs
186 l.lwz r5, OR1KREG_MACLO(sp)
187 l.mtspr r0,r5,SPR_MACLO
188 l.lwz r5, OR1KREG_MACHI(sp)
189 l.mtspr r0,r5,SPR_MACHI
191 l.lwz r4, 4 * OR1K_GPRSIZE(sp)
192 l.lwz r5, 5 * OR1K_GPRSIZE(sp)
193 l.lwz r6, 6 * OR1K_GPRSIZE(sp)
194 l.lwz r7, 7 * OR1K_GPRSIZE(sp)
195 l.lwz r8, 8 * OR1K_GPRSIZE(sp)
196 l.lwz r11, 11 * OR1K_GPRSIZE(sp)
197 l.lwz r13, 13 * OR1K_GPRSIZE(sp)
198 l.lwz r15, 15 * OR1K_GPRSIZE(sp)
199 l.lwz r17, 17 * OR1K_GPRSIZE(sp)
200 l.lwz r19, 19 * OR1K_GPRSIZE(sp)
201 l.lwz r21, 21 * OR1K_GPRSIZE(sp)
202 l.lwz r23, 23 * OR1K_GPRSIZE(sp)
203 l.lwz r25, 25 * OR1K_GPRSIZE(sp)
204 l.lwz r27, 27 * OR1K_GPRSIZE(sp)
205 l.lwz r29, 29 * OR1K_GPRSIZE(sp)
206 l.lwz r31, 31 * OR1K_GPRSIZE(sp)
210 # If this is the first time we're running a thread, R3
211 # contains the argument to the thread entry point function,
212 # So we always have to restore it even though it's a callee-saved
214 l.lwz r3, 3 * OR1K_GPRSIZE(sp)
216 # Finally, restore target thread's true SP
217 l.lwz sp, 1 * OR1K_GPRSIZE(sp)
220 l.nop # delay slot - must be nop
222 FUNC_END(hal_thread_load_context)
224 #------------------------------------------------------------------------------
225 # HAL longjmp, setjmp implementations
226 # hal_setjmp saves only callee-saved registers into buffer supplied in r3:
227 # 1,2,9,10,13,15,17,19,21,23,25,27,29,31
228 # Note: These definitions are repeated in hal_arch.h. If changes are required
229 # remember to update both sets.
231 #define CYGARC_JMP_BUF_R1 0
232 #define CYGARC_JMP_BUF_R2 1
233 #define CYGARC_JMP_BUF_R9 2
234 #define CYGARC_JMP_BUF_R10 3
235 #define CYGARC_JMP_BUF_R12 4
236 #define CYGARC_JMP_BUF_R14 5
237 #define CYGARC_JMP_BUF_R16 6
238 #define CYGARC_JMP_BUF_R18 7
239 #define CYGARC_JMP_BUF_R20 8
240 #define CYGARC_JMP_BUF_R22 9
241 #define CYGARC_JMP_BUF_R24 10
242 #define CYGARC_JMP_BUF_R26 11
243 #define CYGARC_JMP_BUF_R28 12
244 #define CYGARC_JMP_BUF_R30 13
246 #define CYGARC_JMP_BUF_SIZE 14
248 #define jmpbuf_regsize 4
250 FUNC_START(hal_setjmp)
251 # Store General Purpose Registers (GPRs).
252 # R0 is not stored because it is always zero-valued.
253 # Caller-saved registers are not stored
254 l.sw CYGARC_JMP_BUF_R1 * OR1K_GPRSIZE(r3), r1
255 l.sw CYGARC_JMP_BUF_R2 * OR1K_GPRSIZE(r3), r2
256 l.sw CYGARC_JMP_BUF_R9 * OR1K_GPRSIZE(r3), r9
257 l.sw CYGARC_JMP_BUF_R10 * OR1K_GPRSIZE(r3), r10
258 l.sw CYGARC_JMP_BUF_R12 * OR1K_GPRSIZE(r3), r12
259 l.sw CYGARC_JMP_BUF_R14 * OR1K_GPRSIZE(r3), r14
260 l.sw CYGARC_JMP_BUF_R16 * OR1K_GPRSIZE(r3), r16
261 l.sw CYGARC_JMP_BUF_R18 * OR1K_GPRSIZE(r3), r18
262 l.sw CYGARC_JMP_BUF_R20 * OR1K_GPRSIZE(r3), r20
263 l.sw CYGARC_JMP_BUF_R22 * OR1K_GPRSIZE(r3), r22
264 l.sw CYGARC_JMP_BUF_R24 * OR1K_GPRSIZE(r3), r24
265 l.sw CYGARC_JMP_BUF_R26 * OR1K_GPRSIZE(r3), r26
266 l.sw CYGARC_JMP_BUF_R28 * OR1K_GPRSIZE(r3), r28
267 l.sw CYGARC_JMP_BUF_R30 * OR1K_GPRSIZE(r3), r30
273 FUNC_START(hal_longjmp)
274 l.lwz r1, CYGARC_JMP_BUF_R1 * OR1K_GPRSIZE(r3)
275 l.lwz r2, CYGARC_JMP_BUF_R2 * OR1K_GPRSIZE(r3)
276 l.lwz r9, CYGARC_JMP_BUF_R9 * OR1K_GPRSIZE(r3)
277 l.lwz r10, CYGARC_JMP_BUF_R10 * OR1K_GPRSIZE(r3)
278 l.lwz r12, CYGARC_JMP_BUF_R12 * OR1K_GPRSIZE(r3)
279 l.lwz r14, CYGARC_JMP_BUF_R14 * OR1K_GPRSIZE(r3)
280 l.lwz r16, CYGARC_JMP_BUF_R16 * OR1K_GPRSIZE(r3)
281 l.lwz r18, CYGARC_JMP_BUF_R18 * OR1K_GPRSIZE(r3)
282 l.lwz r20, CYGARC_JMP_BUF_R20 * OR1K_GPRSIZE(r3)
283 l.lwz r22, CYGARC_JMP_BUF_R22 * OR1K_GPRSIZE(r3)
284 l.lwz r24, CYGARC_JMP_BUF_R24 * OR1K_GPRSIZE(r3)
285 l.lwz r26, CYGARC_JMP_BUF_R26 * OR1K_GPRSIZE(r3)
286 l.lwz r28, CYGARC_JMP_BUF_R28 * OR1K_GPRSIZE(r3)
287 l.lwz r30, CYGARC_JMP_BUF_R30 * OR1K_GPRSIZE(r3)
291 FUNC_END(hal_longjmp)
294 #------------------------------------------------------------------------------