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/] [vec_ivsr.S] - Blame information for rev 587

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

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