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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
/*===========================================================================
2
//
3
//      vec_ivsr.S
4
//
5
//      SPARC vectors: interrupt vector service routine
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):    hmt
43
// Contributors: hmt
44
// Date:         1999-02-20
45
// Purpose:      SPARC vector code
46
// Description:  see vectors.S; this is the default vector service routine
47
//               for interrupts.
48
//
49
//####DESCRIPTIONEND####
50
//
51
//=========================================================================*/
52
 
53
!----------------------------------------------------------------------------
54
 
55
//      .file   "vec_ivsr.S"
56
 
57
!----------------------------------------------------------------------------
58
 
59
#include 
60
#include 
61
 
62
#ifdef CYGPKG_KERNEL
63
# include 
64
#else
65
# undef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
66
# undef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
67
#endif
68
 
69
!------------------------------------------------------------------------
70
 
71
#include 
72
 
73
#define DELAYS_AFTER_WRPSR_SAME_WINDOW
74
#define DELAYS_AFTER_WRWIM
75
 
76
! Macro to mark the stack as we descend, for debugging, because it is likely
77
! that actually running the ISR won~t touch the stack, but the memory needs
78
! to be there.  Normally blank.
79
//#define       MARKSTACKUSED st %sp, [ %sp ]
80
#define MARKSTACKUSED
81
 
82
!------------------------------------------------------------------------
83
 
84
        .text
85
 
86
!---------------------------------------------------------------------------
87
! default interrupt VSR, which calls the appropriate ISR after scheduler
88
! lock and interrupt masking, then interrupt_end().  interrupt_end() must be
89
! called with interrupts enabled, on the original thread stack (no separate
90
! interrupt stack) or with interrupts masked, on the original stack (when
91
! separate interrupt stack is supported).
92
 
93
        .global hal_default_interrupt_vsr
94
hal_default_interrupt_vsr:
95
        ! here,locals have been set up as follows:
96
        ! %l0 = psr (with this CWP/window-level in it)
97
        ! %l1 = pc
98
        ! %l2 = npc
99
        ! %l3 = vector number (1-15 for interrupts)
100
        ! and we are in our own register window, though it is likely that
101
        ! the next one will need to be saved before we can use it:
102
        ! ie. this one is the invalid register window.
103
 
104
        ! must establish a safe stack before re-enabling interrupts + traps
105
        and     %l0, __WINBITS, %l7     ! CWP extracted
106
        ! no inc/dec here, so no need for special measures for not-8-windows
107
        mov     1, %l6
108
        sll     %l6, %l7, %l6           ! 1 << CWP
109
        rd      %wim, %l5
110
        cmp     %l5, %l6                ! are they the same?
111
        bne     1f                      ! No, so the stack is OK as is.
112
 
113
        ! now do by hand an overflow trap, effectively
114
        mov     %g1, %l7                ! (DELAY SLOT)
115
        srl     %l5, 1, %l5
116
        sll     %l6, __WINSIZE-1, %l6
117
        or      %l6, %l5, %g1           ! new WIM in %g1 so we can get it
118
                                        ! within the save:
119
        save                            ! Slip into next window
120
        mov     %g1, %wim               ! Install the new wim
121
                                        ! (invalidates current window!)
122
#ifdef DELAYS_AFTER_WRWIM
123
        nop
124
        nop
125
        nop
126
#endif
127
 
128
        std     %l0, [%sp + 0 * 4]      ! save L & I registers
129
        std     %l2, [%sp + 2 * 4]
130
        std     %l4, [%sp + 4 * 4]
131
        std     %l6, [%sp + 6 * 4]
132
 
133
        std     %i0, [%sp + 8 * 4]
134
        std     %i2, [%sp + 10 * 4]
135
        std     %i4, [%sp + 12 * 4]
136
        std     %i6, [%sp + 14 * 4]
137
 
138
        restore                         ! Go back to trap window.
139
        mov     %l7, %g1                ! Restore %g1
140
 
141
1:      ! now save away the regs we must preserve
142
        sub     %fp, 32 * 4, %sp
143
#ifdef CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT
144
        std     %g0, [%sp + 16 * 4]     ! save G registers
145
        std     %g2, [%sp + 18 * 4]     ! (set %g0 place to 0 to flag special context)
146
        std     %g4, [%sp + 20 * 4]
147
        std     %g6, [%sp + 22 * 4]
148
#else // not CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT
149
        std     %l0, [%sp + 0 * 4]      ! save L & I registers
150
        std     %l2, [%sp + 2 * 4]
151
        std     %l4, [%sp + 4 * 4]
152
        std     %l6, [%sp + 6 * 4]
153
 
154
        std     %i0, [%sp + 8 * 4]
155
        std     %i2, [%sp + 10 * 4]
156
        std     %i4, [%sp + 12 * 4]
157
        std     %i6, [%sp + 14 * 4]
158
 
159
        st      %g1, [%sp + 17 * 4]     ! save G registers
160
        std     %g2, [%sp + 18 * 4]
161
        std     %g4, [%sp + 20 * 4]
162
        std     %g6, [%sp + 22 * 4]
163
 
164
        ! no point whatsoever in saving O registers
165
 
166
        ! and save the CWP in %g0 save place
167
        st      %l0, [%sp + 16 * 4]
168
#endif // ! CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT
169
 
170
        sub     %sp, 24 * 4, %sp        ! fresh frame including
171
                                        ! arg spill area for callees
172
        MARKSTACKUSED                   ! kilroy was here
173
 
174
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
175
        ! we will switch to the interrupt stack unless already running on it
176
 
177
        .extern cyg_interrupt_stack
178
        .extern cyg_interrupt_stack_base
179
        set     cyg_interrupt_stack, %g1
180
        set     cyg_interrupt_stack_base, %g2
181
 
182
        cmp     %sp, %g2                ! below base?
183
        blu     1f                      ! if so, switch.
184
        cmp     %sp, %g1                ! below top? (DELAY SLOT)
185
        blu     2f                      ! if so, DON~T switch.
186
        nop                             ! (DELAY SLOT)
187
1:      ! switch to the interrupt stack
188
        st      %sp, [ %g1 ]            ! there is spare above stack
189
        sub     %g1, 24 * 4, %sp        ! fresh frame including
190
                                        ! arg spill area for callees
191
        MARKSTACKUSED                   ! kilroy was here
192
2:
193
        ! continue as before, already in the interrupt stack.
194
#endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
195
 
196
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
197
        ! Lock the scheduler
198
        .extern SCHED_LOCK_MANGLED_NAME
199
        sethi   %hi(SCHED_LOCK_MANGLED_NAME), %l7
200
        ld      [ %l7 + %lo(SCHED_LOCK_MANGLED_NAME) ], %l6
201
        add     %l6, 1, %l6
202
        st      %l6, [ %l7 + %lo(SCHED_LOCK_MANGLED_NAME) ]
203
#endif
204
 
205
        ! HELP_GDB_WITH_BACKTRACE
206
        mov     %i7, %l5                ! preserve it in l5
207
        mov     %l1, %i7                ! bogus return link here
208
 
209
        ! and we must preserve the Y register (multiply/divide auxiliary)
210
        ! over these calls; we will keep it in %l4 which is otherwise unused.
211
        rd      %y, %l4
212
 
213
        ! Now we can reenable traps and mask off only lower prio interrupts:
214
        andn    %l0, 0xf00, %l7         ! clear PIL field
215
        or      %l7, 0x0e0, %l7         ! and ET (+S,PS)
216
        sll     %l3, 8, %l6             ! trap number (1-15) into PIL bitfield
217
        wr      %l7, %l6, %psr          ! and enable!
218
#ifdef DELAYS_AFTER_WRPSR_SAME_WINDOW
219
        nop
220
        nop
221
        nop
222
#endif
223
        ! now call the ISR and so on with the appropriate args:
224
        ! ie.
225
        ! isr_retcode = (*(hal_interrupt_handlers[ vector ]))
226
        !                          ( vector, hal_interrupt_data[ vector ] );
227
 
228
        ! from hal_arch.h
229
        !// ISR tables
230
        !CYG_ADDRESS    hal_interrupt_handlers[CYGNUM_HAL_ISR_COUNT];
231
        !CYG_ADDRWORD   hal_interrupt_data[CYGNUM_HAL_ISR_COUNT];
232
        !CYG_ADDRESS    hal_interrupt_objects[CYGNUM_HAL_ISR_COUNT];
233
 
234
        mov     %l3, %o0
235
        sll     %l3, 2, %l3             ! %l3 to a word offset
236
        sethi   %hi(hal_interrupt_data), %l7
237
        or      %l7, %lo(hal_interrupt_data), %l7
238
        ld      [ %l7 + %l3 ], %o1
239
 
240
        sethi   %hi(hal_interrupt_handlers), %l7
241
        or      %l7, %lo(hal_interrupt_handlers), %l7
242
        ld      [ %l7 + %l3 ], %l6
243
        call    %l6
244
        nop
245
 
246
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
247
        ! We only need to call _interrupt_end() when there is a kernel
248
        ! present to do any tidying up.
249
 
250
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
251
        ! now we switch back to the user stack (if we~re at the top
252
        ! of the interrupt stack).
253
 
254
        or      %l0, 0xfe0, %l7
255
        wr      %l7, %psr               ! Interrupts all masked, ET
256
#ifdef DELAYS_AFTER_WRPSR_SAME_WINDOW
257
        nop
258
        nop
259
        nop
260
#endif
261
 
262
        .extern cyg_interrupt_stack
263
        set     cyg_interrupt_stack - (24 * 4), %g1
264
 
265
        cmp     %sp, %g1                ! is SP less?
266
        blu     1f                      ! if so, do not change back
267
        nop
268
        ! switch to the thread stack
269
        ld      [ %g1 + (24 * 4) ], %sp         ! there is spare above stack
270
1:
271
 
272
#else // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
273
        ! First restore the processor interrupt level to that interrupted
274
        ! (otherwise a task-switch runs at the current PIL) on the assumption
275
        ! that the ISR dealt with the interrupt source per se, so it is safe
276
        ! to unmask it, effectively:
277
        or      %l0, 0x0e0, %l7         ! original PSR and ET (+S,PS)
278
        wr      %l7, %psr               ! and enable!
279
#ifdef DELAYS_AFTER_WRPSR_SAME_WINDOW
280
        nop
281
        nop
282
        nop
283
#endif
284
#endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
285
 
286
        ! then call interrupt_end( isr_retcode, &intr_object, ®save )
287
        ! to unlock the scheduler and do any rescheduling that~s needed.
288
        ! argument 0 (isr_retcode) is already in place in %o0
289
        sethi   %hi(hal_interrupt_objects), %l7
290
        or      %l7, %lo(hal_interrupt_objects), %l7
291
        ld      [ %l7 + %l3 ], %o1
292
        add     %sp, 24 * 4, %o2        ! saved regset (maybe tiny)
293
 
294
        .extern interrupt_end
295
        call    interrupt_end
296
        nop
297
#endif
298
 
299
        ! restore the Y register having done our callouts to C
300
        wr      %l4, %y
301
 
302
        ! We can reinstall the original CWP here; even if interrupt_end()
303
        ! performed a reschedule (ie. yield/resume pair) we will be in the
304
        ! same window.  The window is preserved by reschedule precisely
305
        ! because it is impossible atomically to disable traps here without
306
        ! involving a CWP living in a register for a time when other
307
        ! interrupts may occur.
308
 
309
        ! disable traps (using the saved psr is fastest way)
310
        wr      %l0, %psr       ! restores flags, disables traps, and old PIL
311
#ifdef DELAYS_AFTER_WRPSR_SAME_WINDOW
312
        nop
313
        nop
314
        nop
315
#endif
316
 
317
        ! HELP_GDB_WITH_BACKTRACE
318
        mov     %l5, %i7        ! restore (unused) return link
319
 
320
        ! and restore other saved regs
321
        ! (see CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT)
322
        add     %sp, 24 * 4, %sp        ! undo fresh frame
323
 
324
        ld      [%sp + 17 * 4], %g1     ! restore G registers
325
        ldd     [%sp + 18 * 4], %g2
326
        ldd     [%sp + 20 * 4], %g4
327
        ldd     [%sp + 22 * 4], %g6
328
 
329
        ! and do NOT restore any other registers L, I or O
330
 
331
        ! Now test for window underflow here and fix up if needs be.
332
        !
333
        ! Why?  interrupt_end() might have yielded us, when only
334
        ! its own frame was restored; its own return to us caused a
335
        ! window underflow trap, as would our return to interruptee
336
        ! unless we deal with it now.
337
 
338
        add     %l0, 1, %l7             ! interruptee~s CWP plus noise
339
        and     %l7, __WINBITS, %l7     ! CWP only
340
#if 8 == __WINSIZE
341
        ! it is in range already
342
#else   // expect 5 or 6 or 7 windows
343
        cmp     %l7, __WINSIZE
344
        bge,a   567f                    ! taken: do delay slot, handle overflow
345
         mov    0, %l7                  ! only if .ge. above
346
567:
347
#endif
348
        mov     1, %l6
349
        sll     %l6, %l7, %l6           ! 1 << CWP
350
        rd      %wim, %l5
351
        cmp     %l5, %l6                ! are they the same?
352
        bne     2f                      ! No, so the stack is OK as is.
353
 
354
        ! now do by hand an underflow trap, effectively
355
        sll     %l5, 1, %l5             ! Rotate wim left
356
        srl     %l6, __WINSIZE-1, %l6
357
        wr      %l5, %l6, %wim
358
#ifdef DELAYS_AFTER_WRWIM
359
        nop                             ! are these delays needed?
360
        nop                             ! (following restore uses wim)
361
        nop
362
#endif
363
        restore                         ! Interruptee~s window
364
        ldd     [%sp + 0 * 4], %l0      ! restore L & I registers
365
        ldd     [%sp + 2 * 4], %l2
366
        ldd     [%sp + 4 * 4], %l4
367
        ldd     [%sp + 6 * 4], %l6
368
 
369
        ldd     [%sp + 8 * 4], %i0
370
        ldd     [%sp + 10 * 4], %i2
371
        ldd     [%sp + 12 * 4], %i4
372
        ldd     [%sp + 14 * 4], %i6
373
        save                            ! Back to trap window
374
 
375
2:      ! restore the condition codes, PSR and PIL and return from trap.
376
        wr      %l0, %psr       ! restores flags, disables traps, and old PIL
377
#ifdef DELAYS_AFTER_WRPSR_SAME_WINDOW
378
        nop
379
        nop
380
        nop
381
#endif
382
        jmpl    %l1,  %g0
383
        rett    %l2
384
 
385
!----------------------------------------------------------------------------
386
 
387
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
388
 
389
! This routine can only be called from a thread stack, maybe
390
! with interrupts (but not traps) disabled.
391
! It switches to the interrupt stack then calls back to the
392
! kernel to execute DSRs.
393
 
394
        .global hal_interrupt_stack_call_pending_DSRs
395
hal_interrupt_stack_call_pending_DSRs:
396
        save    %sp, -24 * 4, %sp
397
 
398
        MARKSTACKUSED                   ! kilroy was here
399
 
400
        ! be atomic
401
        rd      %psr, %l0
402
        andn    %l0, 0x20, %l1          ! clear ET to disable traps
403
        wr      %l1, %psr               ! into the PSR
404
        nop
405
        nop
406
        nop
407
 
408
        mov     %sp, %l7                ! save calling stack location
409
 
410
        ! now switch stack to the interrupt stack, plus some headroom
411
        ! for saving a register set if we are interrupted
412
        .extern cyg_interrupt_stack
413
        set     cyg_interrupt_stack - 4 * 24, %sp
414
 
415
        MARKSTACKUSED                   ! kilroy was here
416
 
417
        ! and enable interrupts unconditionally to call the DSRs
418
        or      %l0, 0x0e0, %l2         ! set ET, S, PS
419
        andn    %l2, 0xf00, %l2         ! PIL to zero
420
        wr      %l2, %psr               ! into the PSR
421
        nop
422
        nop
423
        nop
424
 
425
        .extern cyg_interrupt_call_pending_DSRs
426
        call    cyg_interrupt_call_pending_DSRs
427
        nop
428
 
429
        mov     %l7, %sp                ! restore calling stack
430
 
431
        wr      %l0, %psr               ! restore interrupt status
432
        nop
433
        nop
434
        nop
435
 
436
        ret
437
        restore
438
#endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
439
 
440
!----------------------------------------------------------------------------
441
 
442
! end of vec_ivsr.S

powered by: WebSVN 2.1.0

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