#***************************************************************************/
#* FILE NAME:                               COPYRIGHT (c) Freescale 2008   */
#* IVOR4_SW_Handler_Old_VLE.s                     All Rights Reserved      */
#* DESCRIPTION:                                                            */
#*        This file creates prolog, epilog for C ISR and enables nested    */
#*        interrupts. This file starts in memory at the beginning of the   */
#*        ".xcptn" section designated by the label "IVOR4Handler".         */
#* WARNING:  This stack frame does not save the SPEs Accumulator, which    */
#*           is required if SPE instructions are used in ISRs.   If SPE    */
#*           instructions are used, the stack frame must include the       */
#*           accumulator, and prologue and epilogue must be modified.      */
#========================================================================= */
#*                                                                         */
#* REV      AUTHOR       DATE       DESCRIPTION OF CHANGE                  */
#* ---   -----------   ----------   ---------------------                  */
#* 1.0:  S. Mihalik    23/Apr/04     Initial version                       */
#* 1.1:  B. Terry      29/Jul/04    Modified read of IACKR using           */
#*                                  pointer to determine vector  address.  */
#* 1.2   G. Jackson    30/Jul/04    Added ".xcptn" section designation     */
#*                                   for placement into mpc5500cfg.        */
#* 1.3   G. Jackson    12/Oct/04    Green Hills now does not require       */
#*                                    quotation marks around the section   */
#*                                  Added syntax to generate symbols for   */
#*                                    debug.                               */
#* 1.4   G. Jackson    18/Oct/04    Epilogue move of restoration for r3,   */
#*                                    and r4 until after INTC_EOIR.        */
#* 1.5   C. Baker      19/Jul/06    Added comments                         */
#* 1.6   R. Moran      23/Feb/07    Modified instructions to VLE           */
#* 1.7   R. Moran      10/Dec/08    Update formatting                      */
#***************************************************************************/

 # Indent one space to prevent GCC warning
 # STACK FRAME DESIGN: Depth: 20 words (0x50, or 80 bytes)
 #            ************* 
 #   0x2C-50  *  GPR4-12  *
 #   0x28     *  GPR3     * 
 #   0x24     *  GPR0     * 
 #   0x20     *  XER      * 
 #   0x1C     *  CTR      * 
 #   0x18     *  LR       *  
 #   0x14     *  CR       * 
 #   0x10     *  SRR1     *  
 #   0x0C     *  SRR0     * 
 #   0x08     *  padding  * 
 #   0x04     *  padding  * 
 #   0x00     *  SP       * 
 #            ************* 
 
    .globl   IVOR4_Handler

    .section  .xptn_vectors, vax
    .vle

    # On Dual Core these registers are treated as Processor 0
    .equ  INTC_IACKR, 0xfff48010   # Interrupt Acknowledge Register address
    .equ  INTC_EOIR,  0xfff48018   # End Of Interrupt Register address
                                   
    .align  4                       
                                   
IVOR4_Handler:                     
prolog:                            # PROLOGUE 
    e_stwu   r1, -0x50 (r1)        # Create stack frame and store back chain
                                   
    e_stw    r3, 0x28 (r1)         # Save working registers R3
    
    mfSRR1   r3                    # Store SRR1 (must be done before enabling EE)
    e_stw    r3, 0x10 (r1)         
    mfSRR0   r3                    # Store SRR0 (must be done before enabling EE)
    e_stw    r3, 0x0C (r1)         
                                   
    e_lis    r3, INTC_IACKR@ha     # Store address of IACKR in r3
    e_lwz    r3, INTC_IACKR@l(r3)  # Store contents of IACKR in r3 (this is vector table address)    
                                   
    wrteei 1                       # Set MSR[EE]=1 (must wait a couple clocks after reading IACKR)    

    e_lwz    r3, 0x0(r3)           # Read ISR address from ISR Vector Table using pointer
                                       
    e_stw    r4,  0x2c (r1)        # Store another working register
                                   
    mfLR     r4                    # Store LR (Store now since LR will be used for ISR Vector)
    e_stw    r4, 0x14 (r1)         
                                   
    mtLR     r3                    # Store ISR address (from IACKR) to LR to use for branching later
                                   
    e_stw    r12, 0x4C (r1)        # Store rest of gprs
    e_stw    r11, 0x48 (r1)
    e_stw    r10, 0x44 (r1)
    e_stw    r9,  0x40 (r1)
    e_stw    r8,  0x3C (r1)
    e_stw    r7,  0x38 (r1)
    e_stw    r6,  0x34 (r1)
    e_stw    r5,  0x30 (r1)
    e_stw    r0,  0x24 (r1)
    
    mfCR     r3                    # Store CR
    e_stw    r3,  0x20 (r1)
    mfXER    r3                    # Store XER
    e_stw    r3,  0x1C (r1)
    mfCTR    r3                    # Store CTR
    e_stw    r3,  0x18 (r1)
                                
    se_blrl                        # Branch to ISR, but return here

epilog:                            # EPILOGUE

#                                  # STEP 6 :  RESTORE CONTEXT


    
    e_lwz    r3, 0x14 (r1)         # Restore LR
    mtLR     r3
    e_lwz    r3, 0x18 (r1)         # Restore CTR
    mtCTR    r3
    e_lwz    r3, 0x1C (r1)         # Restore XER
    mtXER    r3
    e_lwz    r3, 0x20 (r1)         # Restore CR
    mtcrf    0xff, r3
    
    e_lwz    r0,  0x24 (r1)        # Restore GPRs
    e_lwz    r4,  0x2C (r1)
    e_lwz    r5,  0x30 (r1)
    e_lwz    r6,  0x34 (r1)
    e_lwz    r7,  0x38 (r1)
    e_lwz    r8,  0x3C (r1)
    e_lwz    r9,  0x40 (r1)
    e_lwz    r10, 0x44 (r1)
    e_lwz    r11, 0x48 (r1)
    e_lwz    r12, 0x4C (r1)

    e_lis    r3, INTC_EOIR@ha      # Load upper half of EIOR address to r3
                                                                                                                                                 
    wrteei 0                       # Disable interrupts
    
    mbar 0                         # Ensure interrupt flag has finished clearing
                                   # before writing to INTC_EIOR
    e_stw    r3, INTC_EOIR@l(r3)   # Load lower half of EIOR address to r3 and
                                   # write contents of r3 to INTC_EOIR, address 0xFFF4 8018
    
    e_lwz    r3,  0x0C (r1)        # Restore SRR0
    mtSRR0   r3                      
    e_lwz    r3,  0x10 (r1)        # Restore SRR1
    mtSRR1   r3                      
    e_lwz    r3,  0x28 (r1)        # Restore working register
    e_add16i r1, r1, 0x50          # Restore space on stack

    se_rfi                         # End of Interrupt - re-enables interrupts.
