OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [sparclite/] [arch/] [current/] [src/] [context.S] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
/*=============================================================================
2
//
3
//      context.S
4
//
5
//      SPARClite context switch code
6
//
7
//=============================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later
16
// version.
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21
// for more details.
22
//
23
// You should have received a copy of the GNU General Public License
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
26
//
27
// As a special exception, if other files instantiate templates or use
28
// macros or inline functions from this file, or you compile this file
29
// and link it with other works to produce a work based on this file,
30
// this file does not by itself cause the resulting work to be covered by
31
// the GNU General Public License. However the source code for this file
32
// must still be made available in accordance with section (3) of the GNU
33
// General Public License v2.
34
//
35
// This exception does not invalidate any other reasons why a work based
36
// on this file might be covered by the GNU General Public License.
37
// -------------------------------------------
38
// ####ECOSGPLCOPYRIGHTEND####
39
//=============================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):   nickg, gthomas, hmt
43
// Contributors:        nickg, gthomas, hmt
44
// Date:        1998-12-15
45
// Purpose:     SPARClite context switch code
46
// Description: This file contains implementations of the thread context
47
//              switch routines. It also contains the longjmp() and setjmp()
48
//              routines.
49
//
50
//####DESCRIPTIONEND####
51
//
52
//===========================================================================*/
53
 
54
#include 
55
 
56
#include 
57
 
58
#define DELAYS_AFTER_WRPSR_SAME_WINDOW
59
#define DELAYS_AFTER_WRWIM
60
 
61
        .text
62
 
63
! ------------------------------------------------------------------------------
64
!  hal_thread_switch_context
65
!  Switch thread contexts
66
!  %o0 = address of sp of next thread to execute
67
!  %o1 = address of sp save location of current thread
68
 
69
        .global hal_thread_switch_context
70
hal_thread_switch_context:
71
 
72
        ! First take the stack down to make room for the saved register
73
        ! state, including a window save area at the base.  Leave the
74
        ! current window save area undisturbed.  It is unused within the
75
        ! save but will become current again when we continue in this
76
        ! context.  This lets us do this whole piece of work without
77
        ! diabling interrupts for too long, since, for example, we can
78
        ! lower the stack atomically with one instruction:
79
        sub     %sp, SAVE_REGS_SIZE, %sp
80
        st      %sp, [ %o1 ]            ! return SP for this thread
81
 
82
        std     %l0, [%sp + 0 * 4]      ! save L & I registers
83
        std     %l2, [%sp + 2 * 4]
84
        std     %l4, [%sp + 4 * 4]
85
        std     %l6, [%sp + 6 * 4]
86
 
87
        std     %i0, [%sp + 8 * 4]
88
        std     %i2, [%sp + 10 * 4]
89
        std     %i4, [%sp + 12 * 4]
90
        std     %i6, [%sp + 14 * 4]
91
 
92
#ifdef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
93
        st      %o7, [%sp + 31 * 4]     ! save only the return address
94
        ! and no need to preserve %o0 even though it is restored
95
#else // save a maximal context
96
        st      %g1, [%sp + 17 * 4]     ! save G & O registers
97
        std     %g2, [%sp + 18 * 4]
98
        std     %g4, [%sp + 20 * 4]
99
        std     %g6, [%sp + 22 * 4]
100
 
101
        std     %o0, [%sp + 24 * 4]
102
        std     %o2, [%sp + 26 * 4]
103
        std     %o4, [%sp + 28 * 4]
104
        std     %o6, [%sp + 30 * 4]
105
#endif // !CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
106
        ! and save the CWP in %g0 save place
107
        rd      %psr, %g7
108
        st      %g7, [%sp + 16 * 4]
109
 
110
        ! Now load the destination thread by dropping through
111
        ! to hal_thread_load_context
112
 
113
! ------------------------------------------------------------------------------
114
!  hal_thread_load_context
115
!  Load thread context
116
!  %o0 = address of sp of next thread to execute
117
!  Note that this function is also the second half of hal_thread_switch_context
118
!  and is simply dropped into from it.
119
 
120
        .global hal_thread_load_context
121
hal_thread_load_context:
122
 
123
        ! Here, we are a leaf routine but with slightly odd properties.
124
        ! The stack is still the callers at this point but the register
125
        ! set is up for grabs.  So we can use globals:
126
 
127
        ld      [ %o0 ], %g7            ! Get the next saved SP
128
 
129
        ! DISABLE INTERRUPTS *ONLY* NOT TRAPS
130
        rd      %psr, %g6
131
        or      %g6, 0xfe0, %g5         ! PIL up to 15 leave traps enabled
132
        wr      %g5, %psr
133
 
134
        ! force out all our callers register sets onto the stack
135
        ! if necessary: the system will handily take care of this for
136
        ! us as follows:
137
        save    %sp, -16 * 4, %sp       ! need all these to preserve
138
        save    %sp, -16 * 4, %sp       ! the linked list property...
139
        save    %sp, -16 * 4, %sp
140
        save    %sp, -16 * 4, %sp
141
#if 6 < __WINSIZE
142
        save    %sp, -16 * 4, %sp
143
#if 7 < __WINSIZE
144
        save    %sp, -16 * 4, %sp
145
#endif
146
#endif
147
        ! Fewer saves if fewer register windows.  For 8 register windows,
148
        ! six of these is correct; a seventh would force out the current
149
        ! set that was already saved manually above.  Note that minimal
150
        ! space is allowed on stack for locals and ins in case this
151
        ! sequence itself gets interrupted and recurses too deep.
152
 
153
        ! now select the new window with traps disabled...
154
 
155
        ! get the new PSR and CWP that we will ultimately restore
156
        ! from the %g0 save place...
157
        ld      [%g7 + 16 * 4], %g6     ! %g7 holds the new stack pointer
158
        andn    %g6, 0x20, %g5          ! clear ET into %g5
159
        and     %g6, __WINBITS, %g4     ! CWP bits only in %g4
160
 
161
        ! calculate a new WIM...
162
        add     %g4, 1, %g3             ! required invalid window number
163
#if 8 == __WINSIZE
164
        and     %g3, __WINBITS, %g3     ! modulo 8
165
#else   // expect 5 or 6 or 7 windows
166
        cmp     %g3, __WINSIZE
167
        bge,a   567f                    ! taken: do delay slot, handle overflow
168
         mov    0, %g3                  ! only if .ge. above
169
567:
170
#endif
171
        mov     1, %g2
172
        sll     %g2, %g3, %g2           ! converted to a mask for the WIM
173
 
174
        ! DISABLE INTERRUPTS (TRAPS)
175
        wr      %g5, %psr               ! set CWP to new window, disable traps
176
        wr      %g2, %wim               ! and WIM to new value
177
        nop
178
        nop
179
        nop
180
 
181
        ! Must do this atomically so that the registers match the stack.
182
        ! After locals and ins are loaded, we are conformant to the PCS
183
        ! so can re-enable interrupts.
184
        mov     %g7, %sp                ! target sp in situ (%sp = %o6)
185
 
186
        ldd     [%sp + 0 * 4], %l0      ! restore L & I registers
187
        ldd     [%sp + 2 * 4], %l2
188
        ldd     [%sp + 4 * 4], %l4
189
        ldd     [%sp + 6 * 4], %l6
190
 
191
        ldd     [%sp + 8 * 4], %i0
192
        ldd     [%sp + 10 * 4], %i2
193
        ldd     [%sp + 12 * 4], %i4
194
        ldd     [%sp + 14 * 4], %i6
195
 
196
        ! RESTORE INTERRUPTS to saved state
197
        wr      %g6, %psr               ! set new CWP and old ET and PIL
198
        nop
199
        nop
200
        nop
201
 
202
        ! now load the rest of the context; we can be interrupted here
203
        ! (if the saved context was a voluntary yield or threadstart)
204
        ! but that is OK, other state will be preserved in that case...
205
 
206
#ifdef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
207
        ld      [%sp + 24 * 4], %o0     ! must load the initial argument
208
#else // restore a maximal context
209
        ld      [%sp + 17 * 4], %g1
210
        ldd     [%sp + 18 * 4], %g2
211
        ldd     [%sp + 20 * 4], %g4
212
        ldd     [%sp + 22 * 4], %g6
213
 
214
        ldd     [%sp + 24 * 4], %o0
215
        ldd     [%sp + 26 * 4], %o2
216
        ldd     [%sp + 28 * 4], %o4
217
#endif // !CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
218
                                        ! %o6 = %sp, already set up
219
        ld      [%sp + 31 * 4], %o7     ! "return" address
220
 
221
        retl
222
        add     %sp, SAVE_REGS_SIZE, %sp ! and set the stack back
223
                                        ! to its entrant value
224
 
225
! ------------------------------------------------------------------------------
226
!  HAL longjmp, setjmp implementations
227
 
228
!FUNC_START(hal_setjmp)
229
        .global hal_setjmp
230
hal_setjmp:
231
        ! Treat this as a leaf routine, may as well.
232
        ! %o0 is the address of the buffer.
233
 
234
        std     %l0, [%o0 + 0 * 4]      ! save L & I registers
235
        std     %l2, [%o0 + 2 * 4]
236
        std     %l4, [%o0 + 4 * 4]
237
        std     %l6, [%o0 + 6 * 4]
238
 
239
        std     %i0, [%o0 + 8 * 4]
240
        std     %i2, [%o0 + 10 * 4]
241
        std     %i4, [%o0 + 12 * 4]
242
        std     %i6, [%o0 + 14 * 4]
243
 
244
#ifdef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
245
        std     %o6, [%o0 + 30 * 4]     ! just save %sp and return address
246
#else // save a maximal context
247
        st      %g1, [%o0 + 17 * 4]     ! save G & O registers
248
        std     %g2, [%o0 + 18 * 4]
249
        std     %g4, [%o0 + 20 * 4]
250
        std     %g6, [%o0 + 22 * 4]
251
 
252
        std     %o0, [%o0 + 24 * 4]
253
        std     %o2, [%o0 + 26 * 4]
254
        std     %o4, [%o0 + 28 * 4]
255
        std     %o6, [%o0 + 30 * 4]
256
#endif // !CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
257
 
258
        ! and save the CWP in %g0 save place
259
        rd      %psr, %g7
260
        st      %g7, [%o0 + 16 * 4]
261
 
262
        ! DISABLE INTERRUPTS *ONLY* NOT TRAPS
263
        or      %g7, 0xfe0, %g6         ! PIL up to 15 leave traps enabled
264
        wr      %g6, %psr
265
 
266
        ! force out all our callers register sets onto the stack
267
        ! if necessary: the system will handily take care of this for
268
        ! us as follows:
269
        save    %sp, -16 * 4, %sp       ! need all these to preserve
270
        save    %sp, -16 * 4, %sp       ! the linked list property...
271
        save    %sp, -16 * 4, %sp
272
        save    %sp, -16 * 4, %sp
273
#if 6 < __WINSIZE
274
        save    %sp, -16 * 4, %sp
275
#if 7 < __WINSIZE
276
        save    %sp, -16 * 4, %sp
277
#endif
278
#endif
279
        ! Fewer saves if fewer register windows.  For 8 register windows,
280
        ! six of these is correct; a seventh would force out the current
281
        ! set that was already saved manually above.  Note that minimal
282
        ! space is allowed on stack for locals and ins in case this
283
        ! sequence itself gets interrupted and recurses too deep.
284
 
285
        ! (after all, we are about to call deeper not shallower, otherwise
286
        !  using setjmp is inappropriate)
287
 
288
        ! ENABLE INTERRUPTS
289
        wr      %g7, %psr               ! set CWP back to as-was
290
        nop
291
        nop
292
        nop
293
 
294
#ifndef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
295
        ldd     [%o0 + 22 * 4], %g6     ! preserve %g7 and %g6
296
#endif
297
 
298
        retl                            ! ret and return zero to indicate
299
        mov     0, %o0                  ! not longjumped-to
300
 
301
!  hal_longjmp loads state from arg0 and returns arg1
302
!FUNC_START(hal_longjmp)
303
        .global hal_longjmp
304
hal_longjmp:
305
        ! This is kind of a leaf routine, it returns elsewhere
306
        ! %o0 is the address of the buffer.
307
        ! %o1 is the value to return in %o0 (since we are a leaf)
308
 
309
        mov     %o0, %g7                ! keep the pointer handy
310
        mov     %o1, %g1                ! and the return value
311
        ! now select the new window with traps disabled...
312
        rd      %psr, %g6
313
                                        ! preserve ET, clear CWP
314
        andn    %g6, __WINBITS_MAXIMAL, %g6
315
        andn    %g6, 0x20, %g5          ! clear ET also into %g5
316
 
317
        ! get new CWP from %g0 save place...
318
        ld      [%g7 + 16 * 4], %g4     ! %g7 holds the new stack pointer
319
        and     %g4, __WINBITS, %g4     ! preserve CWP bits
320
 
321
        ! calculate a new WIM...
322
        add     %g4, 1, %g3             ! required invalid window number
323
#if 8 == __WINSIZE
324
        and     %g3, __WINBITS, %g3     ! modulo 8
325
#else   // expect 5 or 6 or 7 windows
326
        cmp     %g3, __WINSIZE
327
        bge,a   567f                    ! taken: do delay slot, handle overflow
328
         mov    0, %g3                  ! only if .ge. above
329
567:
330
#endif
331
        mov     1, %g2
332
        sll     %g2, %g3, %g2           ! converted to a mask for the WIM
333
 
334
        ! DISABLE INTERRUPTS
335
        wr      %g5, %g4, %psr          ! set CWP to new window, disable traps
336
        wr      %g2, %wim               ! and WIM to new value
337
        nop
338
        nop
339
        nop
340
 
341
        ! Must do this atomically so that the registers match the stack.
342
        ! After locals and ins are loaded, we are conformant to the PCS
343
        ! so can re-enable interrupts.
344
 
345
        ldd     [%g7 + 0 * 4], %l0      ! restore L & I registers
346
        ldd     [%g7 + 2 * 4], %l2
347
        ldd     [%g7 + 4 * 4], %l4
348
        ldd     [%g7 + 6 * 4], %l6
349
 
350
        ldd     [%g7 + 8 * 4], %i0
351
        ldd     [%g7 + 10 * 4], %i2
352
        ldd     [%g7 + 12 * 4], %i4
353
        ldd     [%g7 + 14 * 4], %i6
354
 
355
        ld      [%g7 + 30 * 4], %sp     ! %o6 = %sp, set up now so as to conform
356
                                        ! to PCS and so be interruptible
357
        ! ENABLE INTERRUPTS
358
        wr      %g6, %g4, %psr          ! set new CWP and old ET
359
        nop
360
        nop
361
        nop
362
 
363
        ! now load the rest of the context; we can be interrupted here, but
364
        ! that is OK, other state will be preserved in that case...
365
#ifdef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
366
        ! we are not preserving globals...
367
                                        ! %o6 = %sp, already set up
368
        ld      [%g7 + 31 * 4], %o7     ! "return" address
369
        retl                            ! %g1 still holds the return value
370
        mov     %g1, %o0
371
 
372
#else // load a maximal context
373
        mov     %g7, %o0                ! original pointer was in %o0 anyway
374
 
375
        ldd     [%o0 + 18 * 4], %g2
376
        ldd     [%o0 + 20 * 4], %g4
377
        ldd     [%o0 + 22 * 4], %g6
378
 
379
        ld      [%o0 + 25 * 4], %o1     ! %o0 = original pointer
380
        ldd     [%o0 + 26 * 4], %o2
381
        ldd     [%o0 + 28 * 4], %o4
382
                                        ! %o6 = %sp, already set up
383
        ld      [%o0 + 31 * 4], %o7     ! "return" address
384
 
385
        ! %g1 still holds the return value; want to get this into %o0
386
        ! and restore %g1 from the saved state;  %o0 is the state pointer:
387
                                        ! g1 = R,   o0 = P
388
        xor     %o0, %g1, %g1           ! g1 = R^P, o0 = P
389
        xor     %o0, %g1, %o0           ! g1 = R^P, o0 = R
390
        xor     %o0, %g1, %g1           ! g1 = P,   o0 = R all done
391
 
392
        retl
393
        ld      [%g1 + 17 * 4], %g1     ! and finally restore %g1
394
#endif // !CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
395
 
396
! ------------------------------------------------------------------------------
397
! end of context.S
398
 
399
 
400
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.