Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:59

0001 /*
0002  * vectors.S
0003  *
0004  *  This file contains the assembly code for the PowerPC exception veneers
0005  *  for RTEMS.
0006  *
0007  *
0008  *  MPC5xx port sponsored by Defence Research and Development Canada - Suffield
0009  *  Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
0010  *
0011  *  Derived from libbsp/powerpc/mbx8xx/vectors/vectors.S,
0012  *
0013  *  (c) 1999, Eric Valette valette@crf.canon.fr
0014  */
0015 
0016 #include <rtems/asm.h>
0017 #include <rtems/score/cpu.h>
0018 #include <libcpu/vectors.h>
0019 #include <bsp.h>
0020 
0021 #define SYNC \
0022     sync; \
0023     isync
0024 
0025 
0026 /*
0027  * Hardware exception vector table.
0028  *
0029  * The MPC555 can be configured to use a compressed vector table with 8
0030  * bytes per entry, rather than the usual 0x100 bytes of other PowerPC
0031  * devices.  The following macro uses this feature to save the better part
0032  * of 8 kbytes of flash ROM.
0033  *
0034  * Each vector table entry has room for only a simple branch instruction
0035  * which branches to a prologue specific to that exception.  This
0036  * exception-specific prologue begins the context save, loads the exception
0037  * number into a register, and jumps to a common exception prologue, below.
0038  */
0039 
0040     .macro  vectors num=0, total=NUM_EXCEPTIONS  /* create vector table */
0041 
0042 /* vector table entry */
0043     .section .vectors, "ax"
0044 
0045     ba  specific_prologue\@     /* run specific prologue */
0046     .long   0               /* each entry is 8 bytes */
0047 
0048 /* exception-specific prologue */
0049     .text
0050 
0051 specific_prologue\@:
0052     stwu    r1, -EXCEPTION_FRAME_END(r1)    /* open stack frame */
0053     stw r4, GPR4_OFFSET(r1)     /* preserve register */
0054     li  r4, \num            /* get exception number */
0055     b   common_prologue         /* run common prologue */
0056 
0057 /* invoke macro recursively to create remainder of table */
0058     .if \total - (\num + 1)
0059     vectors "(\num + 1)", \total
0060     .endif
0061 
0062     .endm
0063 
0064 
0065 /* invoke macro to create entire vector table */
0066     vectors
0067 
0068 
0069 /*
0070  * Common exception prologue.
0071  *
0072  * Because the MPC555 vector table is in flash ROM, it's not possible to
0073  * change the exception handlers by overwriting them at run-time, so this
0074  * common exception prologue uses a table of exception handler pointers to
0075  * provide equivalent flexibility.
0076  *
0077  * When the actual exception handler is run, R1 points to the base of a new
0078  * exception stack frame, in which R3, R4 and LR have been saved.  R4 holds
0079  * the exception number.
0080  */
0081     .text
0082 
0083 common_prologue:
0084     stw r3, GPR3_OFFSET(r1)     /* preserve registers */
0085     mflr    r3
0086     stw r3, EXC_LR_OFFSET(r1)
0087 
0088     slwi    r3, r4, 2               /* make table offset */
0089     addis   r3, r3, exception_handler_table@ha  /* point to entry */
0090     addi    r3, r3, exception_handler_table@l
0091     lwz r3, 0(r3)               /* get entry */
0092     mtlr    r3                  /* run it */
0093     blr
0094 
0095 
0096 /*
0097  * Default exception handler.
0098  *
0099  * The function initialize_exceptions() initializes all of the entries in
0100  * the exception handler table with pointers to this routine, which saves
0101  * the remainder of the interrupted code's state, then calls
0102  * C_default_exception_handler() to dump registers.
0103  *
0104  * On entry, R1 points to a new exception stack frame in which R3, R4, and
0105  * LR have been saved.  R4 holds the exception number.
0106  */
0107     .text
0108 
0109 PUBLIC_VAR(default_exception_handler)
0110 SYM (default_exception_handler):
0111     /*
0112      * Save the interrupted code's program counter and MSR.  Beyond this
0113      * point, all exceptions are recoverable.  Use an RCPU-specific SPR
0114      * to set the RI bit in the MSR to indicate the recoverable state.
0115      */
0116     mfsrr0  r3
0117     stw r3, SRR0_FRAME_OFFSET(r1)
0118     mfsrr1  r3
0119     stw r3, SRR1_FRAME_OFFSET(r1)
0120 
0121     mtspr   eid, r3         /* set MSR[RI], clear MSR[EE] */
0122     SYNC
0123 
0124     /*
0125      * Save the remainder of the general-purpose registers.
0126      *
0127      * Compute the value of R1 at exception entry before storing it in
0128      * the frame.
0129      *
0130      * Note that R2 should never change (it's the EABI pointer to
0131      * .sdata2), but we save it just in case.
0132      *
0133      * Recall that R3 and R4 were saved by the specific- and
0134      * common-exception handlers before entry to this routine.
0135      */
0136     stw r0, GPR0_OFFSET(r1)
0137         addi    r0, r1, EXCEPTION_FRAME_END
0138         stw     r0, GPR1_OFFSET(r1)
0139     stw r2, GPR2_OFFSET(r1)
0140     stmw    r5, GPR5_OFFSET(r1)     /* save R5 to R31 */
0141 
0142     /*
0143      * Save the remainder of the UISA special-purpose registers.  Recall
0144      * that LR was saved before entry.
0145      */
0146     mfcr    r0
0147     stw r0,  EXC_CR_OFFSET(r1)
0148     mfctr   r0
0149     stw r0,  EXC_CTR_OFFSET(r1)
0150     mfxer   r0
0151     stw r0,  EXC_XER_OFFSET(r1)
0152 
0153     /*
0154      * Call C-language portion of the default exception handler, passing
0155      * in the address of the frame.
0156      *
0157      * To simplify things a bit, we assume that the target routine is
0158      * within +/- 32 Mbyte from here, which is a reasonable assumption
0159      * on the MPC555.
0160      */
0161     stw r4, EXCEPTION_NUMBER_OFFSET(r1) /* save exception number */
0162     addi    r3, r1, 0x8         /* get frame address */
0163     bl  C_default_exception_handler /* call handler */
0164 
0165     /*
0166      * Restore UISA special-purpose registers.
0167      */
0168     lwz r0,  EXC_XER_OFFSET(r1)
0169     mtxer   r0
0170     lwz r0,  EXC_CTR_OFFSET(r1)
0171     mtctr   r0
0172     lwz r0,  EXC_CR_OFFSET(r1)
0173     mtcr    r0
0174     lwz r0,  EXC_LR_OFFSET(r1)
0175     mtlr    r0
0176 
0177     /*
0178      * Restore most general-purpose registers.
0179      */
0180     lmw r2, GPR2_OFFSET(r1)
0181 
0182     /*
0183      * Restore the interrupted code's program counter and MSR, but first
0184      * use an RCPU-specific special-purpose register to clear the RI
0185      * bit, indicating that exceptions are temporarily non-recoverable.
0186      */
0187     mtspr   nri, r0         /* clear MSR[RI] */
0188     SYNC
0189 
0190     lwz r0, SRR1_FRAME_OFFSET(r1)
0191     mtsrr1  r0
0192     lwz r0, SRR0_FRAME_OFFSET(r1)
0193     mtsrr0  r0
0194 
0195     /*
0196      * Restore the final GPR, close the stack frame, and return to the
0197      * interrupted code.
0198      */
0199     lwz r0, GPR0_OFFSET(r1)
0200     addi    r1, r1, EXCEPTION_FRAME_END
0201     SYNC
0202     rfi