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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [sparc/] [arch/] [v2_0/] [src/] [context.S] - Blame information for rev 454

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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