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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [openrisc/] [arch/] [current/] [src/] [vectors.S] - Blame information for rev 249

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

Line No. Rev Author Line
1 27 unneback
##==========================================================================
2
##
3
##      Vectors.S
4
##
5
##      OpenRISC exception vectors, interrupt-handling, reset and
6
##        platform-indepent initialization
7
##
8
##==========================================================================
9
#####ECOSGPLCOPYRIGHTBEGIN####
10
## -------------------------------------------
11
## This file is part of eCos, the Embedded Configurable Operating System.
12
## Copyright (C) 2002 Red Hat, Inc.
13
##
14
## eCos is free software; you can redistribute it and/or modify it under
15
## the terms of the GNU General Public License as published by the Free
16
## Software Foundation; either version 2 or (at your option) any later version.
17
##
18
## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19
## 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 along
24
## with eCos; if not, write to the Free Software Foundation, Inc.,
25
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26
##
27
## As a special exception, if other files instantiate templates or use macros
28
## or inline functions from this file, or you compile this file and link it
29
## with other works to produce a work based on this file, this file does not
30
## by itself cause the resulting work to be covered by the GNU General Public
31
## License. However the source code for this file must still be made available
32
## in accordance with section (3) of the GNU General Public License.
33
##
34
## This exception does not invalidate any other reasons why a work based on
35
## this file might be covered by the GNU General Public License.
36
##
37
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38
## at http://sources.redhat.com/ecos/ecos-license/
39
## -------------------------------------------
40
#####ECOSGPLCOPYRIGHTEND####
41
##==========================================================================
42
#######DESCRIPTIONBEGIN####
43
##
44
## Author(s):    sfurman
45
## Contributors:
46
## Date:         2003-01-20
47
## Purpose:      OpenRISC interrupts, exception vectors and reset
48
## Description:  This file defines the code placed into the exception
49
##               vectors. It also contains the first level default VSRs
50
##               that save and restore state for both exceptions and
51
##               interrupts.
52
##
53
######DESCRIPTIONEND####
54
##
55
##==========================================================================
56
 
57
#include 
58
 
59
#ifdef CYGPKG_KERNEL
60
#include      // CYGPKG_KERNEL_INSTRUMENT
61
#endif
62
 
63
#include 
64
#include 
65
 
66
#===========================================================================
67
 
68
 
69
        .extern _hal_vsr_table
70
 
71
        .extern _cyg_hal_invoke_constructors
72
        .extern _cyg_instrument
73
        .extern _cyg_start
74
        .extern _hal_IRQ_init
75
        .extern _hal_platform_init
76
        .extern _initialize_stub
77
 
78
        .extern __bss_start
79
        .extern __bss_end
80
        .extern __sbss_start
81
        .extern __sbss_end
82
 
83
# Include variant macros after MSR definition.
84
#include 
85
#include 
86
 
87
 
88
#===========================================================================
89
# Start by defining the exceptions vectors that must be placed in low
90
# memory, starting at location 0x100.
91
 
92
        .section ".vectors","ax"
93
 
94
#---------------------------------------------------------------------------
95
# Macros for generating an exception vector service routine
96
 
97
# Reset vector macro
98
 
99
        .macro  reset_vector name org
100
        .p2align 8
101
        .globl  __exception_\name
102
__exception_\name:
103
        load32i r3,_start
104
        l.jr    r3
105
        l.nop           # delay slot
106
        .endm
107
 
108
# Generic vector macro
109
 
110
        .macro  exception_vector name org
111
        .p2align 8
112
        .globl  __exception_\name
113
__exception_\name:
114
        l.addi  sp,sp,-SIZEOF_OR1KREGS  # space for registers
115
 
116
        # Store General Purpose Registers (GPRs).
117
 
118
        l.sw     3 * OR1K_GPRSIZE(sp), r3
119
        l.sw     4 * OR1K_GPRSIZE(sp), r4
120
        l.sw     5 * OR1K_GPRSIZE(sp), r5
121
        l.sw     6 * OR1K_GPRSIZE(sp), r6
122
        l.sw     7 * OR1K_GPRSIZE(sp), r7
123
        l.sw     8 * OR1K_GPRSIZE(sp), r8
124
        l.sw     9 * OR1K_GPRSIZE(sp), r9
125
        l.sw    11 * OR1K_GPRSIZE(sp), r11
126
        l.sw    13 * OR1K_GPRSIZE(sp), r13
127
        l.sw    15 * OR1K_GPRSIZE(sp), r15
128
        l.sw    17 * OR1K_GPRSIZE(sp), r17
129
        l.sw    19 * OR1K_GPRSIZE(sp), r19
130
        l.sw    21 * OR1K_GPRSIZE(sp), r21
131
        l.sw    23 * OR1K_GPRSIZE(sp), r23
132
        l.sw    25 * OR1K_GPRSIZE(sp), r25
133
        l.sw    27 * OR1K_GPRSIZE(sp), r27
134
        l.sw    29 * OR1K_GPRSIZE(sp), r29
135
        l.sw    31 * OR1K_GPRSIZE(sp), r31
136
 
137
 
138
#ifndef CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT
139
 
140
        # R0 is not typically stored because it is always zero-valued,
141
        # but we store it here for consistency when examining registers
142
        # in the debugger.
143
        l.sw     0 * OR1K_GPRSIZE(sp), r0
144
 
145
        # Callee-saved regs don't need to be preserved across a call into
146
        # an ISR, but we can do so to make debugging easier.
147
        l.sw     2 * OR1K_GPRSIZE(sp), r2
148
        l.sw    10 * OR1K_GPRSIZE(sp), r10
149
        l.sw    12 * OR1K_GPRSIZE(sp), r12
150
        l.sw    14 * OR1K_GPRSIZE(sp), r14
151
        l.sw    16 * OR1K_GPRSIZE(sp), r16
152
        l.sw    18 * OR1K_GPRSIZE(sp), r18
153
        l.sw    20 * OR1K_GPRSIZE(sp), r20
154
        l.sw    22 * OR1K_GPRSIZE(sp), r22
155
        l.sw    24 * OR1K_GPRSIZE(sp), r24
156
        l.sw    26 * OR1K_GPRSIZE(sp), r26
157
        l.sw    28 * OR1K_GPRSIZE(sp), r28
158
        l.sw    30 * OR1K_GPRSIZE(sp), r30
159
 
160
        # save MAC LO and HI regs
161
        l.mfspr r5,r0,SPR_MACLO
162
        l.sw    OR1KREG_MACLO(sp),r5
163
        l.mfspr r5,r0,SPR_MACHI
164
        l.sw    OR1KREG_MACHI(sp),r5
165
#endif
166
 
167
        # Save SP of interruptee in reg dump
168
        l.addi  r5,sp,SIZEOF_OR1KREGS
169
        l.sw     1 * OR1K_GPRSIZE(sp),r5
170
 
171
        # ...and the PC
172
        l.mfspr r5,r0,SPR_EPCR_BASE
173
        l.sw    OR1KREG_PC(sp),r5
174
 
175
        # ... and the Supervisor Register
176
        l.mfspr r5,r0,SPR_ESR_BASE
177
        l.sw    OR1KREG_SR(sp),r5
178
 
179
        # ... and the exception's effective address, if there is one.
180
        # FIXME - don't need to do this for some exceptions
181
        l.mfspr r5,r0,SPR_EEAR_BASE
182
        l.sw    OR1KREG_EEAR(sp),r5
183
 
184
        # Second arg to VSR is exception number
185
        # First vector is located at 0x100, second at 0x200, etc.
186
        # Shift right to get vector number for address lookup.
187
        l.ori   r4,r0,(\org>>8)
188
        l.sw    OR1KREG_VECTOR(sp),r4
189
 
190
        # Lookup address of VSR in table and jump to it
191
        #   Arg 0: Pointer to HAL_SavedRegisters struct
192
        #   Arg 1: Vector #
193
        load32i r5,_hal_vsr_table+(\org>>6)
194
        l.lwz   r5,0(r5)
195
        l.jr    r5                           # To the VSR, Batman
196
 
197
        # First arg to VSR is SP
198
        l.or    r3,r0,sp                     # Delay slot
199
 
200
        .endm
201
 
202
#---------------------------------------------------------------------------
203
# Define the exception vectors.
204
 
205
rom_vectors:
206
        # These are the architecture-defined vectors that
207
        # are always present.
208
 
209
        reset_vector            reset                   0x100
210
        exception_vector        bus_error               0x200
211
        exception_vector        data_page_fault         0x300
212
        exception_vector        instruction_page_fault  0x400
213
        exception_vector        tick_timer              0x500
214
        exception_vector        unaligned_access        0x600
215
        exception_vector        illegal_instruction     0x700
216
        exception_vector        external_interrupt      0x800
217
        exception_vector        dtlb_miss               0x900
218
        exception_vector        itlb_miss               0xa00
219
        exception_vector        range                   0xb00
220
        exception_vector        syscall                 0xc00
221
        exception_vector        reserved                0xd00
222
        exception_vector        trap                    0xe00
223
 
224
rom_vectors_end:
225
 
226
 
227
#if     defined(CYG_HAL_STARTUP_ROM) ||                 \
228
        (       defined(CYG_HAL_STARTUP_RAM) &&         \
229
                !defined(CYGSEM_HAL_USE_ROM_MONITOR))
230
 
231
        .macro  hal_vsr_table_init
232
 
233
        # Next initialize the VSR table. This happens whether the
234
        # vectors were copied to RAM or not.
235
 
236
        # First fill with exception handlers
237
        load32i r3,_cyg_hal_default_exception_vsr
238
        load32i r4,_hal_vsr_table+4  # First entry in table is unused
239
        l.ori   r5,r0,CYGNUM_HAL_VSR_COUNT
240
1:      l.sw    0(r4),r3
241
        l.addi  r5,r5,-1
242
        l.sfgtsi r5,0
243
        l.bf    1b
244
        l.addi  r4,r4,4         # delay slot
245
 
246
        # Then fill in the interrupt handlers
247
        load32i r4,_hal_vsr_table
248
        load32i r3,_cyg_hal_default_interrupt_vsr
249
        l.sw    CYGNUM_HAL_VECTOR_INTERRUPT*4(r4),r3
250
        l.sw    CYGNUM_HAL_VECTOR_TICK_TIMER*4(r4),r3
251
        .endm
252
 
253
#elif defined(CYG_HAL_STARTUP_RAM) && defined(CYGSEM_HAL_USE_ROM_MONITOR)
254
 
255
        # Initialize the VSR table entries
256
        # We only take control of the interrupt vectors,
257
        # the rest are left to the ROM for now...
258
 
259
        .macro  hal_vsr_table_init
260
        load32i r4,_hal_vsr_table
261
        load32i r3,_cyg_hal_default_interrupt_vsr
262
        l.sw    CYGNUM_HAL_VECTOR_INTERRUPT*4(r4),r3
263
        l.sw    CYGNUM_HAL_VECTOR_TICK_TIMER*4(r4),r3
264
        .endm
265
 
266
 
267
#else
268
 
269
#error "Need to define hal_vsr_table_init"
270
 
271
#endif
272
 
273
# I-Cache initialization macro
274
        .macro  hal_icache_init
275
        /* Disable I-Cache */
276
        l.mfspr r13,r0,SPR_SR
277
        l.addi  r11,r0,-1
278
        l.xori  r11,r11,SPR_SR_ICE
279
        l.and   r11,r13,r11
280
        l.mtspr r0,r11,SPR_SR
281
 
282
        /* Invalidate I-Cache */
283
        l.addi  r13,r0,0
284
        l.addi  r11,r0,HAL_ICACHE_SIZE
285
1:
286
        l.mtspr r0,r13,SPR_ICBIR
287
        l.sfne  r13,r11
288
        l.bf    1b
289
        l.addi  r13,r13,HAL_ICACHE_LINE_SIZE
290
 
291
        /* Enable I-Cache */
292
        l.mfspr r13,r0,SPR_SR
293
        l.ori   r13,r13,SPR_SR_ICE
294
        l.mtspr r0,r13,SPR_SR
295
 
296
        /* Flush instructions out of instruction buffer */
297
        l.nop
298
        l.nop
299
        l.nop
300
        l.nop
301
        l.nop
302
        .endm
303
 
304
# D-Cache initialization macro
305
        .macro  hal_dcache_init
306
 
307
        /* Flush DC */
308
        l.addi  r10,r0,0
309
        l.addi  r11,r0,HAL_DCACHE_SIZE
310
1:
311
        l.mtspr r0,r10,SPR_DCBIR
312
        l.sfne  r10,r11
313
        l.bf    1b
314
        l.addi  r10,r10,HAL_DCACHE_LINE_SIZE
315
 
316
        /* Enable DC */
317
        l.mfspr r10,r0,SPR_SR
318
        l.ori   r10,r10,SPR_SR_DCE
319
        l.mtspr r0,r10,SPR_SR
320
        .endm
321
 
322
#===========================================================================
323
# Startup code:  We jump here from the reset vector to set up the world.
324
 
325
        .text
326
 
327
FUNC_START(start)
328
 
329
        # Initialize Supervision Register:
330
        #   Supervisor mode on, all interrupts off, caches off
331
        #
332
        # (If we've entered here from a hardware reset, then the SR is already
333
        # set to this value, but we may have jumped here as part of a soft
334
        # system reset.)
335
        l.ori   r3,r0,SPR_SR_SM
336
        l.mtspr r0,r3,SPR_SR
337
 
338
        # Run platform-specific hardware initialization code.
339
        # This may include memory controller initialization.
340
        # Hence, it is not safe to access RAM until after this point.
341
        hal_hardware_init
342
 
343
#ifdef CYGSEM_HAL_ENABLE_ICACHE_ON_STARTUP
344
        # Enable I-Cache
345
        hal_icache_init
346
#endif
347
 
348
#ifdef CYGSEM_HAL_ENABLE_DCACHE_ON_STARTUP
349
        # Enable D-Cache
350
        hal_dcache_init
351
#endif
352
 
353
        # Start the tick timer, in case timer polling routine hal_delay_us() is called.
354
        # Initially, no interrupts are generated by the tick timer.  Later on, that
355
        # may change when the kernel is initialized.
356
        l.movhi r3, hi(0x40000000|CYGNUM_HAL_RTC_PERIOD)
357
        l.mtspr r0,r3, SPR_TTMR
358
 
359
        .globl  _hal_hardware_init_done
360
_hal_hardware_init_done:
361
 
362
        # set up stack
363
        load32i sp,__interrupt_stack
364
 
365
        # Make a dummy frame on the stack, so that stack backtraces are sane
366
        # for debugging.  On return from that function, the restore_state()
367
        # function is called to resume the interrupted thread.
368
        l.addi  sp,sp,-8
369
        l.sw    4(sp),r0        # Dummy saved FP
370
        l.sw    0(sp),r0        # Dummy saved LR
371
 
372
        # Set up exception handlers and VSR table, taking care not to
373
        # step on any ROM monitor VSRs.
374
        hal_vsr_table_init
375
 
376
#if defined(CYG_HAL_STARTUP_ROM)
377
        # Copy exception/interrupt vectors from ROM to address 0x100
378
        load32i r4,0x100
379
        load32i r3,rom_vectors
380
        load32i r5,rom_vectors_end
381
1:      l.sfeq  r3,r5
382
        l.bf    2f
383
        l.lwz   r6,0(r3)
384
        l.sw    0(r4),r6
385
        l.addi  r3,r3,4
386
        l.j     1b
387
        l.addi  r4,r4,4         # delay slot
388
2:
389
 
390
        # Copy .data section into RAM
391
        load32i r3,__rom_data_start
392
        load32i r4,__ram_data_start
393
        load32i r5,__ram_data_end
394
1:      l.sfeq  r4,r5
395
        l.bf    2f
396
        l.lwz   r6,0(r3)
397
        l.sw    0(r4),r6
398
        l.addi  r3,r3,4
399
        l.j     1b
400
        l.addi  r4,r4,4         # delay slot
401
2:
402
 
403
#endif
404
 
405
        # clear BSS
406
        load32i r4,__bss_start
407
        load32i r5,__bss_end
408
1:      l.sfeq  r4,r5
409
        l.bf    2f
410
        l.nop
411
        l.sw    0(r4),r0
412
        l.j     1b
413
        l.addi  r4,r4,4
414
2:
415
 
416
        # Note:  no SBSS section to clear with OpenRISC target
417
 
418
        # Platform-specific initialization
419
        l.jal   _hal_platform_init
420
        l.nop   # delay slot
421
 
422
        # call c++ constructors
423
        l.jal   _cyg_hal_invoke_constructors
424
        l.nop   # delay slot
425
 
426
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
427
        l.jal   _initialize_stub
428
        l.nop   # delay slot
429
#endif
430
 
431
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
432
    || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
433
        .extern _hal_ctrlc_isr_init
434
        l.jal   _hal_ctrlc_isr_init
435
        l.nop   # delay slot
436
#endif
437
 
438
        l.jal   _cyg_start       # call cyg_start()
439
        l.nop   # delay slot
440
9:
441
        l.j     9b              # if we return, loop
442
 
443
FUNC_END(start)
444
 
445
#---------------------------------------------------------------------------
446
# This code handles the common part of all exception handlers.
447
# On entry, the machine state is already saved on the stack.
448
#
449
# R3 = pointer to HAL_SavedRegisters struct containing saved machine state
450
# R4 = Vector number
451
#
452
# It calls a C routine to do any work, which may result in
453
# thread switches and changes to the saved state. When we return
454
# here, the saved state is restored and execution is continued.
455
 
456
        .text
457
 
458
FUNC_START(cyg_hal_default_exception_vsr)
459
 
460
        .extern _cyg_hal_exception_handler
461
 
462
        # Call C code
463
 
464
        # When cyg_hal_exception_handler() returns, it will jump
465
        # directly to restore_state(), which will resume execution
466
        # at the location of the exception.
467
        l.movhi r9, hi(restore_state)
468
        l.j     _cyg_hal_exception_handler
469
        l.ori   r9,r9,lo(restore_state) #Delay slot
470
 
471
        # Control never reaches this point,
472
 
473
FUNC_END(cyg_hal_default_exception_vsr)
474
 
475
#---------------------------------------------------------------------------
476
# This code handles all interrupts and dispatches to a C ISR function
477
# On entry, the machine state is already saved on the stack.
478
#
479
# R3 = pointer to HAL_SavedRegisters struct containing saved machine state
480
# R4 = Vector number
481
#
482
# After we return here, the saved state is restored and execution is continued.
483
 
484
#ifdef CYGIMP_FORCE_INTERRUPT_HANDLING_CODE_IN_RAM
485
        .section .text.ram,"ax"
486
#else
487
        .section .text,"ax"
488
#endif
489
 
490
FUNC_START(cyg_hal_default_interrupt_vsr)
491
 
492
        # Stash away pointer to saved regs for later
493
        l.or    r31,r3,r3
494
 
495
        # Set scheduler lock to prevent thread rescheduling while the ISR runs
496
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
497
        .extern _cyg_scheduler_sched_lock
498
        load32i r5, _cyg_scheduler_sched_lock
499
        l.lwz   r6,0(r5)
500
        l.addi  r6,r6,1
501
        l.sw    0(r5),r6
502
#endif
503
 
504
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
505
        # Interrupts execute on their own dedicated stack.
506
        # If we're on a thread stack, switch to the interrupt stack.
507
        # If we're called inside a nested interrupt, do nothing.
508
        l.or    r6,sp,sp                        # Stash SP for later
509
        load32i r7,__interrupt_stack            # stack top (highest addr + 1)
510
        load32i r8,__interrupt_stack_base       # stack base (lowest addr)
511
        l.sfltu sp,r8                           # if (sp < __interrupt_stack_base)
512
        l.bf    1f                              #    switch to interrupt stack
513
        l.sfltu sp,r7                           # if (sp < __interrupt_stack_top)
514
        l.bf   2f                               #    already on interrupt stack
515
        l.nop                                   # delay slot
516
1:      l.or    sp,r7,r7                        # Switch to interrupt stack
517
2:      l.addi  sp,sp,-8                        # Make space to save old SP...
518
        l.sw    0(sp),r6                        # ...and save it on the stack
519
#endif
520
 
521
        # Call C code
522
 
523
#if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
524
        # Log the interrupt if kernel tracing is enabled
525
        l.ori   r3,r0,0x0301                    # arg1 = type = INTR,RAISE
526
                                                # arg2 = vector number
527
        l.ori   r5,r0,r0                        # arg3 = 0
528
        l.jal   _cyg_instrument                  # call instrument function
529
 
530
#endif
531
 
532
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
533
    || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
534
        # If we are supporting Ctrl-C interrupts from GDB, we must squirrel
535
        # away a pointer to the save interrupt state here so that we can
536
        # plant a breakpoint at some later time.
537
 
538
        .extern _hal_saved_interrupt_state
539
        load32i r8,_hal_saved_interrupt_state
540
        l.sw    0(r8),r31
541
 
542
#endif
543
 
544
        # In the event of multiple pending interrupts, determine which
545
        # one will be serviced first.  By software convention, the lowest
546
        # numbered external interrupt gets priority.
547
        #
548
        # The (internal) tick timer interrupt is serviced only if no
549
        # external interrupts are pending.
550
 
551
        # Read the PIC interrupt controller's status register
552
        l.mfspr r9,r0,SPR_PICSR
553
 
554
        # Any pending external interrupts ?
555
        l.sfnei r9,0
556
        l.bf    check_for_external_interrupts
557
 
558
        # Theoretically, the only way we could get here is if the tick timer
559
        # interrupt fired, but we check to be sure that's what happened.
560
        l.sfeqi r4,CYGNUM_HAL_VECTOR_TICK_TIMER
561
        l.bf    3f
562
        l.ori   r3,r0,CYGNUM_HAL_INTERRUPT_RTC  # delay slot
563
 
564
#ifndef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS
565
        l.jal   _hal_spurious_IRQ
566
        l.nop
567
#endif // CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS
568
        l.j     ignore_spurious_interrupt
569
 
570
        # Identify the lowest numbered interrupt bit in the PIC's PSR,
571
        # numbering the MSB as 31 and the LSB as 0
572
check_for_external_interrupts:
573
        l.ori   r3,r0,0
574
2:      l.andi  r11,r9,1                        # Test low bit
575
        l.sfnei r11,0
576
        l.bf    3f
577
        l.srli  r9,r9,1                         # Shift right 1 bit
578
        l.j     2b
579
        l.addi  r3,r3,1                         # Delay slot
580
3:
581
 
582
        # At this point, r3 contains the ISR number, from 0-32
583
        # which will be used to index the table of ISRs
584
        l.slli  r15,r3,2
585
        load32i r9, _hal_interrupt_handlers     # get interrupt handler table
586
        l.add   r9,r9,r15
587
        l.lwz   r11,0(r9)                       # load ISR pointer
588
        load32i r9, _hal_interrupt_data         # get interrupt data table
589
        l.add   r9,r9,r15
590
        l.lwz   r4,0(r9)                        # load data arg to ISR
591
 
592
        # Call ISR
593
        #   arg0 = ISR #
594
        #   arg1 = data arg associated with interrupt
595
        l.jalr  r11
596
        l.nop
597
 
598
ignore_spurious_interrupt:
599
 
600
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
601
 
602
        # If we are returning from the last nested interrupt, move back
603
        # to the thread stack. interrupt_end() must be called on the
604
        # thread stack since it potentially causes a context switch.
605
        # Since we have arranged for the top of stack location to
606
        # contain the sp we need to go back to here, just pop it off
607
        # and put it in SP.
608
 
609
        l.lwz   sp,0(sp)
610
#endif
611
 
612
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
613
 
614
        # We only need to call _interrupt_end() when there is a kernel
615
        # present to do any tidying up.
616
 
617
        # on return r11 bit 1 will indicate whether a DSR is
618
        # to be posted. Pass this together with a pointer to
619
        # the interrupt object we have just used to the
620
        # interrupt tidy up routine.
621
        l.or    r3,r11,r11
622
 
623
        # Get pointer to HAL_SavedRegisters struct, stashed earlier
624
        l.or    r5,r31,r31
625
 
626
        # Get opaque object associated w/ interrupt vector
627
        load32i r9, _hal_interrupt_objects          # get interrupt data table
628
        l.add   r9,r9,r15
629
        l.lwz   r4,0(r9)
630
 
631
        # Call interrupt_end() to execute any pending DSRs
632
        #   Arg 0 = return value from ISR
633
        #   Arg 1 = object associated with interrupt
634
        #   Arg 2 = HAL_SavedRegisters struct
635
 
636
        .extern _interrupt_end
637
        l.jal   _interrupt_end                   # call into C to finish off
638
        l.nop
639
#endif
640
 
641
        # Fall through to restore_state...
642
 
643
# Return from either an interrupt or an exception
644
#
645
# On entry:
646
#    SP = pointer to (HAL_SavedRegisters struct)
647
#
648
restore_state:
649
 
650
        # Restore General Purpose Registers (GPRs).
651
        # R0 is not restored because it is always zero-valued.
652
        # R1, R3, and R4 are used as temps, so they are restored a little later
653
        l.lwz   r5,   5 * OR1K_GPRSIZE(sp)
654
        l.lwz   r6,   6 * OR1K_GPRSIZE(sp)
655
        l.lwz   r7,   7 * OR1K_GPRSIZE(sp)
656
        l.lwz   r8,   8 * OR1K_GPRSIZE(sp)
657
        l.lwz   r9,   9 * OR1K_GPRSIZE(sp)
658
        l.lwz   r11, 11 * OR1K_GPRSIZE(sp)
659
        l.lwz   r13, 13 * OR1K_GPRSIZE(sp)
660
        l.lwz   r15, 15 * OR1K_GPRSIZE(sp)
661
        l.lwz   r17, 17 * OR1K_GPRSIZE(sp)
662
        l.lwz   r19, 19 * OR1K_GPRSIZE(sp)
663
        l.lwz   r21, 21 * OR1K_GPRSIZE(sp)
664
        l.lwz   r23, 23 * OR1K_GPRSIZE(sp)
665
        l.lwz   r25, 25 * OR1K_GPRSIZE(sp)
666
        l.lwz   r27, 27 * OR1K_GPRSIZE(sp)
667
        l.lwz   r29, 29 * OR1K_GPRSIZE(sp)
668
        l.lwz   r31, 31 * OR1K_GPRSIZE(sp)
669
 
670
#ifndef CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT
671
        # Callee-saved regs don't need to be preserved across a call into
672
        # an ISR, but we can do so to make debugging easier.
673
 
674
        l.lwz   r2,   2 * OR1K_GPRSIZE(sp)
675
        l.lwz   r10, 10 * OR1K_GPRSIZE(sp)
676
        l.lwz   r12, 12 * OR1K_GPRSIZE(sp)
677
        l.lwz   r14, 14 * OR1K_GPRSIZE(sp)
678
        l.lwz   r16, 16 * OR1K_GPRSIZE(sp)
679
        l.lwz   r18, 18 * OR1K_GPRSIZE(sp)
680
        l.lwz   r20, 20 * OR1K_GPRSIZE(sp)
681
        l.lwz   r22, 22 * OR1K_GPRSIZE(sp)
682
        l.lwz   r24, 24 * OR1K_GPRSIZE(sp)
683
        l.lwz   r26, 26 * OR1K_GPRSIZE(sp)
684
        l.lwz   r28, 28 * OR1K_GPRSIZE(sp)
685
        l.lwz   r30, 30 * OR1K_GPRSIZE(sp)
686
 
687
        # Restore MAC LO and HI regs
688
        l.lwz   r4, OR1KREG_MACLO(sp)
689
        l.mtspr r0,r4,SPR_MACLO
690
        l.lwz   r4, OR1KREG_MACHI(sp)
691
        l.mtspr r0,r4,SPR_MACHI
692
#endif
693
 
694
        # Must disable interrupts, since they could clobber ESR and EPC regs
695
        l.mfspr r3, r0, SPR_SR
696
        load32i r4,~(SPR_SR_TEE|SPR_SR_IEE)
697
        l.and   r3, r4, r3
698
        l.mtspr r0, r3, SPR_SR
699
 
700
        # At this point we've restored all the pre-interrupt GPRs except for the SP.
701
        # Restore pre-interrupt SR, SP, and PC
702
        l.lwz    r4,  OR1KREG_SR(sp)
703
        l.mtspr  r0, r4, SPR_ESR_BASE
704
 
705
        l.lwz    r4,  OR1KREG_PC(sp)
706
        l.mtspr  r0, r4, SPR_EPCR_BASE
707
 
708
        l.lwz   r4,   4 * OR1K_GPRSIZE(sp)
709
        l.lwz   r3,   3 * OR1K_GPRSIZE(sp)
710
        l.lwz    sp,  1 * OR1K_GPRSIZE(sp)
711
 
712
        # All done, restore CPU state and continue
713
        l.rfe
714
        l.nop           # Delay slot
715
 
716
 
717
##-----------------------------------------------------------------------------
718
## Execute pending DSRs on the interrupt stack with interrupts enabled.
719
## Note: this can only be called from code running on a thread stack
720
 
721
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
722
        .extern _cyg_interrupt_call_pending_DSRs
723
 
724
        .text
725
FUNC_START(hal_interrupt_stack_call_pending_DSRs)
726
        # Switch to interrupt stack
727
        l.or    r3, sp, sp      # Stash entry SP
728
        load32i sp, __interrupt_stack
729
        l.addi  sp, sp, -16
730
        l.sw    0(sp), r3       # Save entry SP
731
        l.mfspr r4,r0,SPR_SR
732
        l.sw    4(sp), r4       # Save interrupt state
733
        l.ori   r4, r4, SPR_SR_IEE|SPR_SR_TEE
734
        l.sw    8(sp),lr
735
 
736
        l.jal   _cyg_interrupt_call_pending_DSRs
737
        # Enable interrupts before calling DSRs
738
        l.mtspr r0, r4, SPR_SR  # Delay slot
739
 
740
        l.lwz   r4, 4(sp)
741
        l.lwz   lr, 8(sp)
742
        l.lwz   sp, 0(sp)
743
 
744
        # Merge original interrupt state with (possibly altered) SR reg
745
        l.andi  r4, r4, SPR_SR_IEE|SPR_SR_TEE
746
        l.mfspr r5, r0, SPR_SR
747
        load32i r6, ~(SPR_SR_IEE|SPR_SR_TEE)
748
        l.and   r5, r5, r6
749
        l.or    r4, r4, r5
750
 
751
        l.jr    r9
752
        l.mtspr r0, r4, SPR_SR  # Delay slot
753
 
754
FUNC_END(hal_interrupt_stack_call_pending_DSRs)
755
#endif
756
 
757
##-----------------------------------------------------------------------------
758
## Switch to a new stack.
759
## This is used in RedBoot to allow code to execute in a different
760
## stack context.
761
 
762
FUNC_START(hal_program_new_stack)
763
        # Arguments are:
764
        # r3 = function to call
765
        # r4 = stack pointer to use
766
 
767
        # Dummy prologue, so that debugger is fooled into thinking there
768
        # is a stack frame.  The debugger will use the offsets in the prologue
769
        # below to read the saved register values out of the *new* stack.
770
        l.addi  sp,sp,-8
771
        l.sw    0(sp),fp
772
        l.addi  fp,sp,8
773
        l.sw    4(sp),lr
774
 
775
        l.or    r5,sp,sp        # Remember original SP
776
        l.addi  r6,fp,-8        # Remember original FP
777
        l.or    sp,r4,r4        # Switch to new stack
778
 
779
        # "Real prologue" - Offsets here must match dummy prologue above
780
        l.addi  sp,sp,-16
781
        l.sw    0(sp),r6        # So debugger can know caller's FP
782
        l.sw    4(sp),lr        # So debugger can know caller's PC
783
        l.sw    8(sp),r5        # Save old SP on stack
784
 
785
        # Call function
786
        l.jalr  r3
787
        l.nop
788
 
789
        l.lwz   sp, 8(sp)       # Restore original SP
790
        l.lwz   lr, 4(sp)
791
        l.jr    lr              # Return to caller
792
        l.addi  sp,sp, 8        # Delay slot
793
 
794
FUNC_END(hal_program_new_stack)
795
 
796
#---------------------------------------------------------------------------
797
## Temporary interrupt stack
798
 
799
        .section ".bss"
800
 
801
        .balign 16
802
        .global _cyg_interrupt_stack_base
803
_cyg_interrupt_stack_base:
804
__interrupt_stack_base:
805
        .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
806
        .byte 0
807
        .endr
808
        .balign 16
809
        .global _cyg_interrupt_stack
810
_cyg_interrupt_stack:
811
__interrupt_stack:
812
 
813
        .long   0,0,0,0,0,0,0,0
814
 
815
#--------------------------------------
816
        .data
817
        .extern _hal_default_isr
818
 
819
        .globl  _hal_interrupt_handlers
820
_hal_interrupt_handlers:
821
        .rept   CYGNUM_HAL_ISR_COUNT
822
        .long   _hal_default_isr
823
        .endr
824
 
825
        .globl  _hal_interrupt_data
826
_hal_interrupt_data:
827
        .rept   CYGNUM_HAL_ISR_COUNT
828
        .long   0
829
        .endr
830
 
831
        .globl  _hal_interrupt_objects
832
_hal_interrupt_objects:
833
        .rept   CYGNUM_HAL_ISR_COUNT
834
        .long   0
835
        .endr
836
 
837
#---------------------------------------------------------------------------
838
# end of vectors.S

powered by: WebSVN 2.1.0

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