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

Subversion Repositories openrisc

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

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

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

powered by: WebSVN 2.1.0

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