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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [hal/] [powerpc/] [arch/] [v2_0/] [src/] [vectors.S] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
##==========================================================================
2
##
3
##      vectors.S
4
##
5
##      PowerPC exception vectors
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
## Copyright (C) 2002 Gary Thomas
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):    nickg, jskov
45
## Contributors: nickg, jskov
46
## Date:         1999-02-20
47
## Purpose:      PowerPC exception vectors
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
#===========================================================================
58
#
59
#       The PowerPC exception handling has changed as of version 1.3.1.
60
#       The primary motivation for rewriting the code was to bring it more
61
#       in line with the other HALs, in particular to allow a RAM application
62
#       to cleanly take over only a subset of vectors from a running ROM
63
#       monitor.
64
#
65
#       GDB stubs (and CygMon, should it be ported to PPC) copies
66
#       exception vector entry handler code to address 0. These vector entry
67
#       handlers (defined by the exception_vector macro below) compute
68
#       a vector index into the hal_vsr_table, fetch the pointer, and
69
#       jump to the HAL vector service routine (VSR).
70
#
71
#       The hal_vsr_table is located immediately after the vector
72
#       handlers (at address 0x3000), allowing RAM applications to
73
#       change VSRs as necessary, while still keeping desired ROM
74
#       monitor functionality available for debugging.
75
#
76
#       ROM applications can still be configured to leave the vector entry
77
#       handlers at 0xff000000, but there is at the moment no
78
#       provision for reclaiming the reserved vector space in RAM to
79
#       application usage.
80
#
81
#       RAM applications can also be configured to provide exception
82
#       handlers which are copied to address 0 on startup, thus taking
83
#       full control of the target.
84
#
85
#
86
#       Default configuration is for RAM applications to rely on an
87
#       existing ROM monitor to provide debugging functionality, and
88
#       for ROM applications to copy vectors to address 0.
89
#
90
#
91
#       Unfortunately the new exception scheme is not compatible with the
92
#       old scheme. Stubs and applications must be compiled using the same
93
#       scheme (i.e., old binaries will not run with new stubs, and new
94
#       binaries will not run with old stubs).
95
#
96
#===========================================================================
97
 
98
#include 
99
 
100
#ifdef CYGPKG_KERNEL
101
#include      // CYGPKG_KERNEL_INSTRUMENT
102
#endif
103
 
104
#define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS
105
#include 
106
 
107
#===========================================================================
108
 
109
//        .file   "vectors.S"
110
 
111
        .extern hal_interrupt_data
112
        .extern hal_interrupt_handlers
113
        .extern hal_interrupt_objects
114
        .extern hal_vsr_table
115
 
116
        .extern cyg_hal_invoke_constructors
117
        .extern cyg_instrument
118
        .extern cyg_start
119
        .extern hal_IRQ_init
120
        .extern hal_MMU_init
121
        .extern hal_enable_caches
122
        .extern hal_hardware_init
123
        .extern initialize_stub
124
 
125
        .extern __bss_start
126
        .extern __bss_end
127
        .extern __sbss_start
128
        .extern __sbss_end
129
 
130
#===========================================================================
131
# MSR initialization value
132
# zero all bits except:
133
# FP = floating point available
134
# ME = machine check enabled
135
# IP = vectors at 0xFFFxxxxx (ROM startup only)
136
# IR = instruction address translation
137
# DR = data address translation
138
# RI = recoverable interrupt
139
 
140
#define CYG_MSR_COMMON (MSR_FP | MSR_ME | MSR_RI)
141
 
142
#if (CYGHWR_HAL_POWERPC_VECTOR_BASE == 0xfff00000)
143
# define IP_BIT MSR_IP
144
#else
145
# define IP_BIT 0
146
#endif
147
 
148
#ifdef CYGHWR_HAL_POWERPC_ENABLE_MMU
149
# define IR_DR_BITS (MSR_IR | MSR_DR)
150
#else
151
# define IR_DR_BITS 0
152
#endif
153
 
154
#define CYG_MSR (CYG_MSR_COMMON | IP_BIT | IR_DR_BITS)
155
 
156
# Include variant macros after MSR definition.
157
#include 
158
#include 
159
 
160
 
161
#===========================================================================
162
# If the following option is enabled, we only save registers up to R12.
163
# The PowerPC ABI defines registers 13..31 as callee saved and thus we do
164
# not need to save them when calling C functions.
165
 
166
#ifdef CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT
167
# define MAX_SAVE_REG    12
168
#else
169
# define MAX_SAVE_REG    31
170
#endif
171
 
172
 
173
#if defined(CYGHWR_HAL_POWERPC_NEED_VECTORS)
174
 
175
#===========================================================================
176
# Start by defining the exceptions vectors that must be placed at
177
# locations 0xFFF00000 or 0x00000000. The following code will normally
178
# be located at 0xFFF00000 in the ROM. It may optionally be copied out
179
# to 0x00000000 if we want to use the RAM vectors. For this reason this code
180
# MUST BE POSITION INDEPENDENT.
181
 
182
        .section ".vectors","ax"
183
 
184
#---------------------------------------------------------------------------
185
# Macros for generating an exception vector service routine
186
 
187
# Reset vector macro
188
 
189
        .macro  reset_vector name
190
        .p2align 8
191
        .globl  __exception_\name
192
__exception_\name:
193
#ifdef CYGSEM_HAL_POWERPC_RESET_USES_JUMP
194
        bl      _start
195
#else
196
        lwi     r3,_start
197
        mtlr    r3
198
        blr
199
#endif
200
 
201
        .endm
202
 
203
# Generic vector macro
204
 
205
        .macro  exception_vector name
206
        .p2align 8
207
        .globl  __exception_\name
208
__exception_\name:
209
        mtspr   SPRG1,r3                     # stash some work registers away
210
        mtspr   SPRG2,r4
211
        mtspr   SPRG3,r5
212
        mfcr    r4                           # stash CR
213
        li      r5,__exception_\name-rom_vectors       # load low half of vector addr
214
        srwi    r5,r5,6                      # shift right by 6
215
        lwi     r3,hal_vsr_table             # table base
216
        lwzx    r3,r3,r5                     # address of vsr
217
        mflr    r5                           # save link register
218
        mtlr    r3                           # put vsr address into it
219
        li      r3,__exception_\name-rom_vectors       # reload low half of vector addr
220
        blr                                  # go to common code
221
        .endm
222
 
223
#---------------------------------------------------------------------------
224
# Define the exception vectors.
225
 
226
// Some platforms won't let us put the vector code just where we want
227
// This macro introduces some lattitude in vector placement
228
 
229
#ifdef CYG_HAL_FUDGE_VECTOR_ALIGNMENT
230
        hal_fudge_vector_alignment
231
#endif
232
 
233
rom_vectors:
234
        # These are the architecture defined vectors that
235
        # are always present.
236
#ifdef CYG_HAL_RESERVED_VECTOR_00000
237
        hal_reserved_vector_00000
238
#else
239
        exception_vector        reserved_00000
240
#endif
241
        reset_vector            reset
242
        exception_vector        machine_check
243
        exception_vector        data_storage
244
        exception_vector        instruction_storage
245
        exception_vector        external
246
        exception_vector        alignment
247
        exception_vector        program
248
        exception_vector        floatingpoint_unavailable
249
        exception_vector        decrementer
250
        exception_vector        reserved_00a00
251
        exception_vector        reserved_00b00
252
        exception_vector        system_call
253
        exception_vector        trace
254
        exception_vector        floatingpoint_assist
255
        exception_vector        reserved_00f00
256
 
257
        # Variants may define extra vectors.
258
        hal_extra_vectors
259
 
260
rom_vectors_end:
261
 
262
#else //  CYGHWR_HAL_POWERPC_NEED_VECTORS
263
 
264
        # When vectors are not included this is the primary entry point.
265
        .globl  __exception_reset
266
__exception_reset:
267
        lwi     r3,_start
268
        mtlr    r3
269
        blr
270
 
271
#endif //  CYGHWR_HAL_POWERPC_NEED_VECTORS
272
 
273
 
274
 
275
#===========================================================================
276
# Real startup code. We jump here from the various reset vectors to set up
277
# the world.
278
 
279
        .text
280
        .globl  _start
281
_start:
282
        # Initialize CPU to a post-reset state, ensuring the ground doesn''t
283
        # shift under us while we try to set things up.
284
        hal_cpu_init
285
 
286
        # Set up global offset table
287
        lwi     r2,_GLOBAL_OFFSET_TABLE_
288
 
289
        # set up time base register to zero
290
        xor     r3,r3,r3
291
        mtspr   TBL_W,r3
292
        xor     r4,r4,r4
293
        mtspr   TBU_W,r4
294
 
295
        # Call platform specific hardware initialization
296
        # This may include memory controller initialization. It is not
297
        # safe to access RAM until after this point.
298
        bl      hal_hardware_init       # this is platform dependent
299
        .globl  _hal_hardware_init_done
300
_hal_hardware_init_done:
301
 
302
#if !defined(CYG_HAL_STARTUP_ROM) && defined(CYGSEM_HAL_POWERPC_COPY_VECTORS)
303
        lwi     r3,rom_vectors-4
304
        lwi     r4,(CYGHWR_HAL_POWERPC_VECTOR_BASE - 4)
305
        lwi     r5,rom_vectors_end-4
306
0:      lwzu    r0,4(r3)
307
        stwu    r0,4(r4)
308
        cmplw   r3,r5
309
        bne     0b
310
#endif
311
 
312
        # set up stack
313
        lwi     sp,__interrupt_stack
314
        mtspr   SPRG0,sp        # save in sprg0 for later use
315
 
316
        # Set up exception handlers and VSR table, taking care not to
317
        # step on any ROM monitor''s toes.
318
        hal_mon_init
319
 
320
#if defined(CYG_HAL_STARTUP_ROM)
321
 
322
        # Copy data from ROM to ram
323
        lwi     r3,__rom_data_start     # r3 = rom start
324
        lwi     r4,__ram_data_start     # r4 = ram start
325
        lwi     r5,__ram_data_end       # r5 = ram end
326
 
327
        cmplw   r4,r5                   # skip if no data
328
        beq     2f
329
 
330
1:
331
        lwz     r0,0(r3)                # get word from ROM
332
        stw     r0,0(r4)                # store in RAM
333
        addi    r3,r3,4                 # increment by 1 word
334
        addi    r4,r4,4                 # increment by 1 word
335
        cmplw   r4,r5                   # compare
336
        blt     1b                      # loop if not yet done
337
2:
338
#endif
339
 
340
        # clear BSS
341
        lwi     r3,__bss_start  # r3 = start
342
        lwi     r4,__bss_end    # r4 = end
343
        li      r0,0            # r0 = 0
344
        cmplw   r3,r4           # skip if no bss
345
        beq     2f
346
 
347
1:      stw     r0,0(r3)        # store zero
348
        addi    r3,r3,4         # increment by 1 word
349
        cmplw   r3,r4           # compare
350
        blt     1b              # loop if not yet done
351
2:
352
 
353
        # clear SBSS
354
        lwi     r3,__sbss_start # r3 = start
355
        lwi     r4,__sbss_end   # r4 = end
356
        cmplw   r3,r4           # skip if no sbss
357
        beq     2f
358
 
359
1:      stw     r0,0(r3)        # store zero
360
        addi    r3,r3,4         # increment by 1 word
361
        cmplw   r3,r4           # compare
362
        blt     1b              # loop if not yet done
363
2:
364
 
365
        # It is now safe to call C functions which may rely on initialized
366
        # data.
367
 
368
        # Set up stack for calls to C code.
369
        subi    sp,sp,12                        # make space on stack
370
        li      r0,0
371
        stw     r0,0(sp)                        # clear back chain
372
        stw     r0,8(sp)                        # zero return pc
373
        stwu    sp,-CYGARC_PPC_STACK_FRAME_SIZE(sp) # create new stack frame
374
 
375
        # Variant HALs may need to do something special before we continue
376
        bl      hal_variant_init
377
 
378
        # Platform initialization
379
        bl      hal_platform_init
380
 
381
        # MMU and cache are controlled by the same option since caching
382
        # on the PPC does not make sense without the MMU to mark regions
383
        # which should not be cached.
384
#ifdef CYGHWR_HAL_POWERPC_ENABLE_MMU
385
        # Initialize MMU.
386
        bl      hal_MMU_init
387
 
388
        # Enable MMU so we can safely enable caches.
389
        lwi     r3,CYG_MSR              # interrupts enabled later
390
        sync
391
        mtmsr   r3
392
        sync
393
 
394
        # Enable caches
395
        bl      hal_enable_caches
396
#endif // CYGHWR_HAL_POWERPC_ENABLE_MMU
397
 
398
        # set up platform specific interrupt environment
399
        bl      hal_IRQ_init
400
 
401
        # call c++ constructors
402
        bl      cyg_hal_invoke_constructors
403
 
404
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
405
        bl      initialize_stub
406
#endif
407
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
408
    || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
409
        .extern hal_ctrlc_isr_init
410
        bl     hal_ctrlc_isr_init
411
#endif
412
 
413
        bl      cyg_start                       # call cyg_start
414
9:
415
        b       9b              # if we return, loop
416
 
417
#---------------------------------------------------------------------------
418
# This code handles the common part of all exception handlers.
419
# It saves the machine state onto the stack  and then calls
420
# a "C" routine to do the rest of the work. This work may result
421
# in thread switches, and changes to the saved state. When we return
422
# here the saved state is restored and execution is continued.
423
 
424
        .text
425
 
426
        .globl cyg_hal_default_exception_vsr
427
cyg_hal_default_exception_vsr:
428
 
429
        # We come here with all register containing their
430
        # pre-exception values except:
431
        # R3    = ls 16 bits of vector address
432
        # R4    = saved CR
433
        # R5    = saved LR
434
        # LR    = VSR address
435
        # SPRG1 = old R3
436
        # SPRG2 = old R4
437
        # SPRG3 = old R5
438
        # SRR0  = old PC
439
        # SRR1  = old MSR and the exception cause (the POW state is lost!)
440
 
441
        subi    sp,sp,CYGARC_PPC_EXCEPTION_DECREMENT
442
                                        # leave space for registers and
443
                                        # a safety margin
444
#ifdef CYGPKG_HAL_POWERPC_PPC40x
445
// The caches on this processor are always enabled when the MMU is on
446
// (and disabled when off).  Thus we need to be careful about cache
447
// polution and staleness when changing the MMU state.
448
// At this point, the MMU is off due to the exception.  We need to
449
// flush the part of the cache which may be touched before the MMU
450
// is reenabled so that memory will be consistent when that happens.
451
// Of course, this is complicated by the fact that there are no "free"
452
// registers at this point in the code.
453
        dcbf    0,sp                    // Flushes first line
454
        stw     r3,0(sp)                // This is now safe
455
        li      r3,CYGARC_PPCREG_VECTOR // Flush lines which will be changed
456
        dcbf    r3,sp
457
        li      r3,CYGARC_PPCREG_CR
458
        dcbf    r3,sp
459
        li      r3,CYGARC_PPCREG_LR
460
        dcbf    r3,sp
461
        lwz     r3,0(sp)                // Restore register
462
#endif
463
 
464
        # First, save away some registers
465
        stw     r3,CYGARC_PPCREG_VECTOR(sp)    # stash vector
466
        stw     r4,CYGARC_PPCREG_CR(sp)        # stash CR
467
        stw     r5,CYGARC_PPCREG_LR(sp)        # stash LR
468
 
469
#ifdef CYGDBG_HAL_POWERPC_FRAME_WALLS
470
        # Mark this fram as an Exception frame
471
        lwi     r3,0xDDDDDDE0
472
        stw     r3,CYGARC_PPCREG_WALL_HEAD(sp)
473
        lwi     r3,0xDDDDDDE1
474
        stw     r3,CYGARC_PPCREG_WALL_TAIL(sp)
475
#endif
476
 
477
        # Enable MMU.
478
        lwi     r3,CYG_MSR
479
        sync
480
        mtmsr   r3
481
        sync
482
 
483
        mfspr   r3,SPRG1                # save original R3
484
        stw     r3,CYGARC_PPCREG_REGS+3*4(sp)
485
        mfspr   r4,SPRG2                # save original R4
486
        stw     r4,CYGARC_PPCREG_REGS+4*4(sp)
487
        mfspr   r5,SPRG3                # save original R5
488
        stw     r5,CYGARC_PPCREG_REGS+5*4(sp)
489
 
490
        stw     r0,CYGARC_PPCREG_REGS+0*4(sp)  # save R0
491
        stw     r2,CYGARC_PPCREG_REGS+2*4(sp)  # save R2
492
 
493
        mr      r3,sp                   # recreate original SP
494
        addi    r3,r3,CYGARC_PPC_EXCEPTION_DECREMENT
495
        stw     r3,CYGARC_PPCREG_REGS+1*4(sp)  # and save it in state
496
 
497
        # Save registers r6..r12/r31
498
        .set    _reg,6
499
        .rept   MAX_SAVE_REG+1-6
500
        stw     _reg,(CYGARC_PPCREG_REGS+_reg*4)(sp)
501
        .set    _reg,_reg+1
502
        .endr
503
 
504
        # Save registers used in vsr (r14+r15)
505
        stw     r14,(CYGARC_PPCREG_REGS+14*4)(sp)
506
        stw     r15,(CYGARC_PPCREG_REGS+15*4)(sp)
507
 
508
        # get remaining family CPU registers
509
        mfxer   r3
510
        mfctr   r4
511
        mfsrr0  r5
512
        mfsrr1  r6
513
        # and store them
514
        stw     r3,CYGARC_PPCREG_XER(sp)
515
        stw     r4,CYGARC_PPCREG_CTR(sp)
516
        stw     r5,CYGARC_PPCREG_PC(sp)
517
        stw     r6,CYGARC_PPCREG_MSR(sp)
518
 
519
        # Save variant registers
520
        hal_variant_save sp
521
 
522
        # Save FPU registers
523
        hal_fpu_save sp
524
 
525
        # The entire CPU state is now stashed on the stack,
526
        # call into C to do something with it.
527
 
528
        mr      r3,sp                           # R3 = register dump
529
 
530
        subi    sp,sp,CYGARC_PPC_STACK_FRAME_SIZE # make a null frame
531
 
532
        li      r0,0                            # R0 = 0
533
        stw     r0,0(sp)                        # backchain = 0
534
        stw     r0,8(sp)                        # return pc = 0
535
 
536
        stwu    sp,-CYGARC_PPC_STACK_FRAME_SIZE(sp) # create new stack frame
537
                                                # where C code can save LR
538
 
539
        lwi     r5,restore_state                # get return link
540
        mtlr    r5                              # to link register
541
 
542
        .extern cyg_hal_exception_handler
543
        b       cyg_hal_exception_handler       # call C code, r3 = registers
544
 
545
        # When the call returns it will go to restore_state below.
546
 
547
 
548
##--------------------------------------------------------------------------
549
## The following macros are defined depending on whether the Interrupt
550
## system is using isr tables or chaining, and depending on the interrupt
551
## controller in the system.
552
 
553
#ifndef CYGPKG_HAL_POWERPC_INTC_DEFINED
554
 
555
## This is the simple version. No interrupt controller, CYGARC_PPCREG_VECTOR
556
## is updated with the decoded interrupt vector. Isr tables/chaining
557
## use same interrupt decoder.
558
## Bit 21 biffers between decrementer (0) and external (1).
559
 
560
        # decode the interrupt
561
        .macro  hal_intc_decode dreg,state
562
        lwz     \dreg,CYGARC_PPCREG_VECTOR(\state) # retrieve vector number,
563
        rlwinm  \dreg,\dreg,22,31,31               # isolate bit 21 and update
564
        stw     \dreg,CYGARC_PPCREG_VECTOR(\state) # vector in state frame.
565
        slwi    \dreg,\dreg,2                      # convert to word offset.
566
        .endm
567
 
568
#endif // CYGPKG_HAL_POWERPC_INTC_DEFINED
569
 
570
#---------------------------------------------------------------------------
571
# Common interrupt handling code.
572
 
573
        .globl cyg_hal_default_interrupt_vsr
574
cyg_hal_default_interrupt_vsr:
575
 
576
        # We come here with all register containing their
577
        # pre-exception values except:
578
        # R3    = ls 16 bits of vector address
579
        # R4    = saved CR
580
        # R5    = saved LR
581
        # LR    = VSR address
582
        # SPRG1 = old R3
583
        # SPRG2 = old R4
584
        # SPRG3 = old R5
585
        # SRR0  = old PC
586
        # SRR1  = old MSR
587
 
588
 
589
        subi    sp,sp,CYGARC_PPC_EXCEPTION_DECREMENT
590
                                        # leave space for registers and
591
                                        # a safety margin
592
#ifdef CYGPKG_HAL_POWERPC_PPC40x
593
// The caches on this processor are always enabled when the MMU is on
594
// (and disabled when off).  Thus we need to be careful about cache
595
// polution and staleness when changing the MMU state.
596
// At this point, the MMU is off due to the exception.  We need to
597
// flush the part of the cache which may be touched before the MMU
598
// is reenabled so that memory will be consistent when that happens.
599
// Of course, this is complicated by the fact that there are no "free"
600
// registers at this point in the code.
601
        dcbf    0,sp                    // Flushes first line
602
        stw     r3,0(sp)                // This is now safe
603
        li      r3,CYGARC_PPCREG_VECTOR // Flush lines which will be changed
604
        dcbf    r3,sp
605
        li      r3,CYGARC_PPCREG_CR
606
        dcbf    r3,sp
607
        li      r3,CYGARC_PPCREG_LR
608
        dcbf    r3,sp
609
        lwz     r3,0(sp)                // Restore register
610
#endif
611
 
612
        stw     r3,CYGARC_PPCREG_VECTOR(sp)    # stash vector
613
        stw     r4,CYGARC_PPCREG_CR(sp)        # stash CR
614
        stw     r5,CYGARC_PPCREG_LR(sp)        # stash LR
615
 
616
#ifdef CYGDBG_HAL_POWERPC_FRAME_WALLS
617
        # Mark this fram as an 1nterrupt frame
618
        lwi     r3,0xDDDDDD10
619
        stw     r3,CYGARC_PPCREG_WALL_HEAD(sp)
620
        lwi     r3,0xDDDDDD11
621
        stw     r3,CYGARC_PPCREG_WALL_TAIL(sp)
622
#endif
623
 
624
        # Enable MMU.
625
        lwi     r3,CYG_MSR
626
        sync
627
        mtmsr   r3
628
        sync
629
 
630
        mfspr   r3,SPRG1                # save original R3
631
        stw     r3,CYGARC_PPCREG_REGS+3*4(sp)
632
        mfspr   r4,SPRG2                # save original R4
633
        stw     r4,CYGARC_PPCREG_REGS+4*4(sp)
634
        mfspr   r5,SPRG3                # save original R5
635
        stw     r5,CYGARC_PPCREG_REGS+5*4(sp)
636
 
637
        stw     r0,CYGARC_PPCREG_REGS+0*4(sp)  # save R0
638
        stw     r2,CYGARC_PPCREG_REGS+2*4(sp)  # save R2
639
 
640
        mr      r3,sp                   # recreate original SP
641
        addi    r3,r3,CYGARC_PPC_EXCEPTION_DECREMENT
642
        stw     r3,CYGARC_PPCREG_REGS+1*4(sp)  # and save it in state
643
 
644
        # Save registers r6..r12/r31
645
        .set    _reg,6
646
        .rept   MAX_SAVE_REG+1-6
647
        stw     _reg,(CYGARC_PPCREG_REGS+_reg*4)(sp)
648
        .set    _reg,_reg+1
649
        .endr
650
 
651
        # Save registers used in vsr (r14+r15)
652
        stw     r14,CYGARC_PPCREG_REGS+14*4(sp)
653
        stw     r15,CYGARC_PPCREG_REGS+15*4(sp)
654
 
655
        # get remaining family CPU registers
656
        mfxer   r3
657
        mfctr   r4
658
        mfsrr0  r5
659
        mfsrr1  r6
660
 
661
        # and store them
662
        stw     r3,CYGARC_PPCREG_XER(sp)
663
        stw     r4,CYGARC_PPCREG_CTR(sp)
664
        stw     r5,CYGARC_PPCREG_PC(sp)
665
        stw     r6,CYGARC_PPCREG_MSR(sp)
666
 
667
        # Save variant registers
668
        hal_variant_save sp
669
 
670
        # Save FPU registers
671
        hal_fpu_save sp
672
 
673
        # The entire CPU state is now stashed on the stack,
674
        # increment the scheduler lock and call the ISR
675
        # for this vector.
676
 
677
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
678
        .extern cyg_scheduler_sched_lock
679
        lwi     r3,cyg_scheduler_sched_lock
680
        lwz     r4,0(r3)
681
        addi    r4,r4,1
682
        stw     r4,0(r3)
683
#endif
684
 
685
        mr      r14,sp                          # r14 = register dump
686
 
687
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
688
        lwi     r3,__interrupt_stack            # stack top
689
        lwi     r4,__interrupt_stack_base       # stack base
690
        sub.    r5,sp,r4                        # sp - base
691
        blt     1f                              # if < 0 - not on istack
692
        sub.    r5,r3,sp                        # top - sp
693
        bgt     2f                              # if > 0 - already on istack
694
 
695
1:      mr      sp,r3                           # switch to istack
696
 
697
2:      stwu    r14,-4(sp)                      # save old SP on stack
698
 
699
#endif
700
 
701
        subi    sp,sp,CYGARC_PPC_STACK_FRAME_SIZE # make a null frame
702
 
703
        li      r0,0                            # R0 = 0
704
        stw     r0,0(sp)                        # backchain = 0
705
        stw     r0,8(sp)                        # return pc = 0
706
 
707
        stwu    sp,-CYGARC_PPC_STACK_FRAME_SIZE(sp) # create new stack frame
708
                                                # where C code can save LR
709
 
710
#if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
711
 
712
        lwi     r3,0x0301                       # r3 = type = INTR,RAISE
713
        lwz     r4,CYGARC_PPCREG_VECTOR(r14)    # arg1 = vector address
714
        srwi    r4,r4,8                         # arg1 = vector number
715
        xor     r5,r5,r5                        # arg2 = 0
716
        bl      cyg_instrument                  # call instrument function
717
 
718
#endif
719
 
720
        hal_intc_decode r15,r14                # get table index
721
 
722
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
723
    || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
724
        # If we are supporting Ctrl-C interrupts from GDB, we must squirrel
725
        # away a pointer to the save interrupt state here so that we can
726
        # plant a breakpoint at some later time.
727
 
728
        .extern hal_saved_interrupt_state
729
        lwi     r3,hal_saved_interrupt_state
730
        stw     r14,0(r3)
731
 
732
#endif
733
 
734
#ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING
735
 
736
#ifdef CYGPKG_HAL_POWERPC_MPC8xx
737
        # The CPM controller allows nested interrupts. However,
738
        # it sits on the back of the SIU controller which has no
739
        # HW support for this. In effect, SW masking of lower
740
        # priority IRQs in the SIU would be required for this to work.
741
#endif
742
 
743
#endif
744
 
745
        lwz     r3,CYGARC_PPCREG_VECTOR(r14)    # retrieve decoded vector #
746
 
747
        lwi     r6,hal_interrupt_handlers       # get interrupt handler table
748
        lwzx    r6,r6,r15                       # load routine pointer
749
 
750
        lwi     r4,hal_interrupt_data           # get interrupt data table
751
        lwzx    r4,r4,r15                       # load data pointer
752
                                                # R4 = data argument
753
        mr      r5,r14                          # R5 = saved registers
754
 
755
        mtctr   r6                              # put isr address in ctr
756
 
757
        bctrl                                   # branch to ctr reg and link
758
 
759
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
760
 
761
        # If we are returning from the last nested interrupt, move back
762
        # to the thread stack. interrupt_end() must be called on the
763
        # thread stack since it potentially causes a context switch.
764
        # Since we have arranged for the top of stack location to
765
        # contain the sp we need to go back to here, just pop it off
766
        # and put it in SP.
767
 
768
 
769
        lwz     sp,CYGARC_PPC_STACK_FRAME_SIZE*2(sp) # sp = *sp
770
 
771
        subi    sp,sp,CYGARC_PPC_STACK_FRAME_SIZE # make a null frame
772
 
773
        li      r0,0                            # R0 = 0
774
        stw     r0,0(sp)                        # backchain = 0
775
        stw     r0,8(sp)                        # return pc = 0
776
 
777
        stwu    sp,-CYGARC_PPC_STACK_FRAME_SIZE(sp) # create new stack frame
778
                                                # where C code can save LR
779
#endif
780
 
781
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
782
 
783
        # We only need to call _interrupt_end() when there is a kernel
784
        # present to do any tidying up.
785
 
786
        # on return r3 bit 1 will indicate whether a DSR is
787
        # to be posted. Pass this together with a pointer to
788
        # the interrupt object we have just used to the
789
        # interrupt tidy up routine.
790
 
791
        # Note that r14 and r15 are defined to be preserved across
792
        # calls by the calling convention, so they still contain
793
        # the register dump and the vector number respectively.
794
 
795
        lwi     r4,hal_interrupt_objects        # get interrupt object table
796
        lwzx    r4,r4,r15                       # load object pointer
797
        mr      r5,r14                          # arg3 = saved register dump
798
 
799
        .extern interrupt_end
800
        bl      interrupt_end                   # call into C to finish off
801
#endif
802
 
803
restore_state:
804
        # All done, restore CPU state and continue
805
 
806
        # retrieve CPU state pointer
807
        addi    sp,sp,CYGARC_PPC_STACK_FRAME_SIZE*2
808
 
809
        # Restore FPU registers
810
        hal_fpu_load sp
811
 
812
        # Restore variant registers
813
        hal_variant_load sp
814
 
815
        # get sprs we want to restore
816
        # stuff some of them into the CPU
817
        lwz     r3,CYGARC_PPCREG_XER(sp)
818
        lwz     r4,CYGARC_PPCREG_LR(sp)
819
        lwz     r5,CYGARC_PPCREG_CTR(sp)
820
        mtxer   r3
821
        mtlr    r4
822
        mtctr   r5
823
 
824
        # Restore registers used in vsr (r14+r15)
825
        lwz     r14,CYGARC_PPCREG_REGS+14*4(r1)
826
        lwz     r15,CYGARC_PPCREG_REGS+15*4(r1)
827
 
828
        # restore registers r6..r12/r31
829
        .set    _reg,6
830
        .rept   MAX_SAVE_REG+1-6
831
        lwz     _reg,(CYGARC_PPCREG_REGS+_reg*4)(sp)
832
        .set    _reg,_reg+1
833
        .endr
834
 
835
        hal_cpu_int_disable
836
 
837
        # restore R0 and R2
838
        lwz     r0,CYGARC_PPCREG_REGS+0*4(sp)
839
        lwz     r2,CYGARC_PPCREG_REGS+2*4(sp)
840
 
841
        # Here all the registers are loaded except
842
        # sp = HAL_SavedRegisters
843
        # r3 = ccr
844
        # r4 = srr0 = pc
845
        # r5 = srr1 = msr
846
        #
847
        # We have to disable interrupts while srr0 and
848
        # srr1 are loaded, since another interrupt will
849
        # destroy them.
850
 
851
        lwz     r3,CYGARC_PPCREG_CR(sp)
852
        lwz     r4,CYGARC_PPCREG_PC(sp)
853
        lwz     r5,CYGARC_PPCREG_MSR(sp)
854
        mtcr    r3                      # set ccr
855
        mtsrr0  r4                      # load old pc
856
        mtsrr1  r5                      # load old msr
857
 
858
#ifdef CYGDBG_HAL_POWERPC_FRAME_WALLS
859
        # Mark this frame as (almost) dead.
860
        lwi     r3,0xDDDDDDD0
861
        stw     r3,CYGARC_PPCREG_WALL_HEAD(sp)
862
        lwi     r3,0xDDDDDDD1
863
        stw     r3,CYGARC_PPCREG_WALL_TAIL(sp)
864
#endif
865
 
866
        lwz     r3,CYGARC_PPCREG_REGS+3*4(sp)  # load r3 value
867
        lwz     r4,CYGARC_PPCREG_REGS+4*4(sp)  # load r4 value
868
        lwz     r5,CYGARC_PPCREG_REGS+5*4(sp)  # load r5 value
869
        lwz     sp,CYGARC_PPCREG_REGS+1*4(sp)  # restore sp
870
 
871
        sync                            # settle things down
872
        isync
873
        rfi                             # and return
874
 
875
 
876
 
877
##-----------------------------------------------------------------------------
878
## Execute pending DSRs on the interrupt stack with interrupts enabled.
879
## Note: this can only be called from code running on a thread stack
880
 
881
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
882
        .extern cyg_interrupt_call_pending_DSRs
883
 
884
FUNC_START(hal_interrupt_stack_call_pending_DSRs)
885
        # Change to interrupt stack, save state and set up stack for
886
        # calls to C code.
887
        mr      r3,sp
888
        lwi     r4,__interrupt_stack
889
        subi    r4,r4,24                        # make space on stack
890
        mr      sp,r4
891
        stw     r3,12(sp)                       # save old sp
892
        mfmsr   r3
893
        stw     r3,16(sp)                       # save old MSR
894
        mflr    r3
895
        stw     r3,20(sp)                       # save old LR
896
 
897
        li      r0,0
898
        stw     r0,0(sp)                        # clear back chain
899
        stw     r0,8(sp)                        # zero return pc
900
 
901
        hal_cpu_int_enable
902
 
903
        # Call into kernel which will execute DSRs
904
        stwu    sp,-CYGARC_PPC_STACK_FRAME_SIZE(sp)
905
        bl      cyg_interrupt_call_pending_DSRs
906
        addi    sp,sp,CYGARC_PPC_STACK_FRAME_SIZE
907
 
908
        lwz     r3,20(sp)                       # restore LR
909
        mtlr    r3
910
        lwz     r5,12(sp)                       # get SP from saved state
911
        lwz     r3,16(sp)                       # restore interrupt setting
912
        hal_cpu_int_merge r3
913
 
914
        mr      sp,r5                           # restore stack pointer
915
        blr                                     # and return to caller
916
#endif
917
 
918
#---------------------------------------------------------------------------
919
## Temporary interrupt stack
920
 
921
        .section ".bss"
922
 
923
        .balign 16
924
        .global cyg_interrupt_stack_base
925
cyg_interrupt_stack_base:
926
__interrupt_stack_base:
927
        .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
928
        .byte 0
929
        .endr
930
        .balign 16
931
        .global cyg_interrupt_stack
932
cyg_interrupt_stack:
933
__interrupt_stack:
934
 
935
        .long   0,0,0,0,0,0,0,0
936
 
937
#---------------------------------------------------------------------------
938
# end of vectors.S

powered by: WebSVN 2.1.0

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